Diff
Modified: trunk/Source/WTF/ChangeLog (284142 => 284143)
--- trunk/Source/WTF/ChangeLog 2021-10-14 01:46:22 UTC (rev 284142)
+++ trunk/Source/WTF/ChangeLog 2021-10-14 02:12:31 UTC (rev 284143)
@@ -1,3 +1,15 @@
+2021-10-13 Megan Gardner <[email protected]>
+
+ Scroll To Text Fragment directive parsing
+ https://bugs.webkit.org/show_bug.cgi?id=231410
+
+ Reviewed by Chris Dumez.
+
+ Text directive parsing for
+ https://wicg.github.io/scroll-to-text-fragment/
+
+ * Scripts/Preferences/WebPreferencesExperimental.yaml:
+
2021-10-13 Chris Dumez <[email protected]>
Drop makeWeakPtr() and use WeakPtr { } directly
Modified: trunk/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml (284142 => 284143)
--- trunk/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml 2021-10-14 01:46:22 UTC (rev 284142)
+++ trunk/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml 2021-10-14 02:12:31 UTC (rev 284143)
@@ -1153,6 +1153,18 @@
default: false
WebCore:
default: false
+
+ScrollToTextFragmentEnabled:
+ type: bool
+ humanReadableName: "Scroll To Text Fragment"
+ humanReadableDescription: "Enable Scroll To Text Fragment"
+ defaultValue:
+ WebKitLegacy:
+ default: false
+ WebKit:
+ default: false
+ WebCore:
+ default: false
ServerTimingEnabled:
type: bool
Modified: trunk/Source/WebCore/ChangeLog (284142 => 284143)
--- trunk/Source/WebCore/ChangeLog 2021-10-14 01:46:22 UTC (rev 284142)
+++ trunk/Source/WebCore/ChangeLog 2021-10-14 02:12:31 UTC (rev 284143)
@@ -1,3 +1,37 @@
+2021-10-13 Megan Gardner <[email protected]>
+
+ Scroll To Text Fragment directive parsing
+ https://bugs.webkit.org/show_bug.cgi?id=231410
+
+ Reviewed by Chris Dumez.
+
+ Text directive parsing for
+ https://wicg.github.io/scroll-to-text-fragment/
+
+ Make a new class to handle the parsing of the text directive.
+ The parsing is defined in the linked spec.
+ The directive should be stored on Document and in a future
+ patch the matching algorithm will find the text and scroll
+ and highlight it.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * dom/Document.h:
+ (WebCore::Document::setFragmentDirective):
+ (WebCore::Document::fragmentDirective const):
+ * dom/FragmentDirectiveParser.cpp: Added.
+ (WebCore::FragmentDirectiveParser::create):
+ (WebCore::FragmentDirectiveParser::FragmentDirectiveParser):
+ (WebCore::FragmentDirectiveParser::parseFragmentDirective):
+ * dom/FragmentDirectiveParser.h: Added.
+ (WebCore::FragmentDirectiveParser::parsedTextDirectives):
+ (WebCore::FragmentDirectiveParser::fragmentDirective):
+ (WebCore::FragmentDirectiveParser::urlFragment):
+ (WebCore::FragmentDirectiveParser::isValid):
+ * page/FrameView.cpp:
+ (WebCore::FrameView::scrollToFragment):
+ * platform/Logging.h:
+
2021-10-13 Chris Dumez <[email protected]>
Drop makeWeakPtr() and use WeakPtr { } directly
Modified: trunk/Source/WebCore/Sources.txt (284142 => 284143)
--- trunk/Source/WebCore/Sources.txt 2021-10-14 01:46:22 UTC (rev 284142)
+++ trunk/Source/WebCore/Sources.txt 2021-10-14 02:12:31 UTC (rev 284143)
@@ -921,6 +921,7 @@
dom/ExtensionStyleSheets.cpp
dom/FocusEvent.cpp
dom/FormDataEvent.cpp
+dom/FragmentDirectiveParser.cpp
dom/FullscreenManager.cpp
dom/GCReachableRef.cpp
dom/HashChangeEvent.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (284142 => 284143)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-10-14 01:46:22 UTC (rev 284142)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-10-14 02:12:31 UTC (rev 284143)
@@ -8442,6 +8442,8 @@
443F04260E75C8FB007E5407 /* NetworkStateNotifierIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkStateNotifierIOS.mm; sourceTree = "<group>"; };
444D4E210F708B2E003158E0 /* WebCoreURLResponseIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCoreURLResponseIOS.mm; sourceTree = "<group>"; };
445210DD25D61EFF003A2ED8 /* AppHighlight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppHighlight.h; sourceTree = "<group>"; };
+ 445612AA270F6F3700758C97 /* FragmentDirectiveParser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FragmentDirectiveParser.cpp; sourceTree = "<group>"; };
+ 445612AB270F6F3800758C97 /* FragmentDirectiveParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FragmentDirectiveParser.h; sourceTree = "<group>"; };
445775E420472F73008DCE5D /* LocalDefaultSystemAppearance.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LocalDefaultSystemAppearance.h; sourceTree = "<group>"; };
445775E92047303B008DCE5D /* LocalDefaultSystemAppearance.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LocalDefaultSystemAppearance.mm; sourceTree = "<group>"; };
446DC64624A29D9B0061F390 /* PlaybackTargetClientContextIdentifier.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlaybackTargetClientContextIdentifier.h; sourceTree = "<group>"; };
@@ -30690,6 +30692,8 @@
2A66439126A006AF00C147A1 /* FormDataEvent.cpp */,
2A66439026A006AF00C147A1 /* FormDataEvent.h */,
2A66438E26A006AE00C147A1 /* FormDataEvent.idl */,
+ 445612AA270F6F3700758C97 /* FragmentDirectiveParser.cpp */,
+ 445612AB270F6F3800758C97 /* FragmentDirectiveParser.h */,
A853123C11D0471B00D4D077 /* FragmentScriptingPermission.h */,
CD92F5172261038200F87BB3 /* FullscreenManager.cpp */,
CD92F5162261038200F87BB3 /* FullscreenManager.h */,
Modified: trunk/Source/WebCore/dom/Document.h (284142 => 284143)
--- trunk/Source/WebCore/dom/Document.h 2021-10-14 01:46:22 UTC (rev 284142)
+++ trunk/Source/WebCore/dom/Document.h 2021-10-14 02:12:31 UTC (rev 284143)
@@ -1639,6 +1639,9 @@
const Editor& editor() const { return m_editor; }
FrameSelection& selection() { return m_selection; }
const FrameSelection& selection() const { return m_selection; }
+
+ void setFragmentDirective(const String& fragmentDirective) { m_fragmentDirective = fragmentDirective; }
+ const String& fragmentDirective() const { return m_fragmentDirective; }
void prepareCanvasesForDisplayIfNeeded();
void clearCanvasPreparation(HTMLCanvasElement&);
@@ -2234,6 +2237,8 @@
UniqueRef<Editor> m_editor;
UniqueRef<FrameSelection> m_selection;
+
+ String m_fragmentDirective;
ListHashSet<Ref<Element>> m_topLayerElements;
UniqueRef<WhitespaceCache> m_whitespaceCache;
Added: trunk/Source/WebCore/dom/FragmentDirectiveParser.cpp (0 => 284143)
--- trunk/Source/WebCore/dom/FragmentDirectiveParser.cpp (rev 0)
+++ trunk/Source/WebCore/dom/FragmentDirectiveParser.cpp 2021-10-14 02:12:31 UTC (rev 284143)
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FragmentDirectiveParser.h"
+
+#include "Logging.h"
+#include <wtf/URL.h>
+#include <wtf/text/TextStream.h>
+
+
+namespace WebCore {
+
+FragmentDirectiveParser::FragmentDirectiveParser(const URL& url)
+{
+ ASCIILiteral fragmentDirectiveDelimiter = ":~:"_s;
+ auto fragmentIdentifier = url.fragmentIdentifier();
+
+ if (fragmentIdentifier.isEmpty()) {
+ m_remainingURLFragment = fragmentIdentifier;
+ return;
+ }
+
+ auto fragmentDirectiveStart = fragmentIdentifier.find(StringView(fragmentDirectiveDelimiter));
+
+ if (fragmentDirectiveStart == notFound) {
+ m_remainingURLFragment = fragmentIdentifier;
+ return;
+ }
+
+ auto fragmentDirective = fragmentIdentifier.substring(fragmentDirectiveStart + fragmentDirectiveDelimiter.length());
+
+ // FIXME: this needs to be set on the original URL
+ m_remainingURLFragment = fragmentIdentifier.left(fragmentDirectiveStart);
+
+ parseFragmentDirective(fragmentDirective);
+
+ m_fragmentDirective = fragmentDirective.toString();
+ m_isValid = true;
+}
+
+void FragmentDirectiveParser::parseFragmentDirective(StringView fragmentDirective)
+{
+ LOG_WITH_STREAM(TextFragment, stream << " parseFragmentDirective: ");
+
+ Vector<ParsedTextDirective> parsedTextDirectives;
+ String textDirectivePrefix = "text="_s;
+
+ auto directives = fragmentDirective.split('&');
+
+ LOG_WITH_STREAM(TextFragment, stream << " parseFragmentDirective: ");
+
+ for (auto directive : directives) {
+ if (!directive.startsWith(textDirectivePrefix))
+ continue;
+
+ auto textDirective = directive.substring(textDirectivePrefix.length());
+
+ Deque<String> tokens;
+ bool containsEmptyToken = false;
+ for (auto token : textDirective.split(',')) {
+ if (token.isEmpty()) {
+ LOG_WITH_STREAM(TextFragment, stream << " empty token ");
+ containsEmptyToken = true;
+ break;
+ }
+ tokens.append(token.toString());
+ }
+ if (containsEmptyToken)
+ continue;
+ // FIXME: add decoding for % encoded strings.
+ if (tokens.size() > 4 || tokens.size() < 1) {
+ LOG_WITH_STREAM(TextFragment, stream << " wrong number of tokens ");
+ continue;
+ }
+
+ ParsedTextDirective parsedTextDirective;
+
+ if (tokens.first().endsWith('-') && tokens.first().length() > 1) {
+ tokens.first().truncate(tokens.first().length() - 2);
+ parsedTextDirective.prefix = tokens.first();
+ tokens.removeFirst();
+ }
+
+ if (tokens.last().startsWith('-') && tokens.last().length() > 1) {
+ tokens.last().remove(0);
+ parsedTextDirective.suffix = tokens.takeLast();
+ }
+
+ if (tokens.size() != 1 && tokens.size() != 2) {
+ LOG_WITH_STREAM(TextFragment, stream << " not enough tokens ");
+ continue;
+ }
+
+ parsedTextDirective.textStart = tokens.first();
+
+ if (tokens.size() == 2)
+ parsedTextDirective.textEnd = tokens.last();
+
+ parsedTextDirectives.append(parsedTextDirective);
+ }
+
+ m_parsedTextDirectives = parsedTextDirectives;
+}
+
+} // namespace WebCore
Added: trunk/Source/WebCore/dom/FragmentDirectiveParser.h (0 => 284143)
--- trunk/Source/WebCore/dom/FragmentDirectiveParser.h (rev 0)
+++ trunk/Source/WebCore/dom/FragmentDirectiveParser.h 2021-10-14 02:12:31 UTC (rev 284143)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+struct ParsedTextDirective {
+ String textStart;
+ String textEnd;
+ String prefix;
+ String suffix;
+};
+
+class FragmentDirectiveParser {
+public:
+ explicit FragmentDirectiveParser(const URL&);
+
+ const Vector<ParsedTextDirective>& parsedTextDirectives() const { return m_parsedTextDirectives; };
+ StringView fragmentDirective() const { return m_fragmentDirective; };
+ StringView remainingURLFragment() const { return m_remainingURLFragment; };
+ bool isValid() const { return m_isValid; };
+
+private:
+ FragmentDirectiveParser() = delete;
+ void parseFragmentDirective(StringView);
+
+ Vector<ParsedTextDirective> m_parsedTextDirectives;
+ StringView m_remainingURLFragment;
+ StringView m_fragmentDirective;
+ bool m_isValid { false };
+};
+
+} // namespace WebCore
Modified: trunk/Source/WebCore/page/FrameView.cpp (284142 => 284143)
--- trunk/Source/WebCore/page/FrameView.cpp 2021-10-14 01:46:22 UTC (rev 284142)
+++ trunk/Source/WebCore/page/FrameView.cpp 2021-10-14 02:12:31 UTC (rev 284143)
@@ -47,6 +47,7 @@
#include "EventNames.h"
#include "FloatRect.h"
#include "FocusController.h"
+#include "FragmentDirectiveParser.h"
#include "Frame.h"
#include "FrameFlattening.h"
#include "FrameLoader.h"
@@ -2216,7 +2217,25 @@
bool FrameView::scrollToFragment(const URL& url)
{
+ ASSERT(frame().document());
+ Ref document = *frame().document();
+
auto fragmentIdentifier = url.fragmentIdentifier();
+
+ if (document->settings().scrollToTextFragmentEnabled()) {
+ FragmentDirectiveParser fragmentDirectiveParser(url);
+
+ if (fragmentDirectiveParser.isValid()) {
+ auto fragmentDirective = fragmentDirectiveParser.fragmentDirective().toString();
+ document->setFragmentDirective(fragmentDirective);
+
+ auto parsedTextDirectives = fragmentDirectiveParser.parsedTextDirectives();
+ // FIXME: Scroll to the range specified by the directive.
+
+ } else
+ fragmentIdentifier = fragmentDirectiveParser.remainingURLFragment();
+ }
+
if (scrollToFragmentInternal(fragmentIdentifier))
return true;
Modified: trunk/Source/WebCore/platform/Logging.h (284142 => 284143)
--- trunk/Source/WebCore/platform/Logging.h 2021-10-14 01:46:22 UTC (rev 284142)
+++ trunk/Source/WebCore/platform/Logging.h 2021-10-14 02:12:31 UTC (rev 284143)
@@ -115,6 +115,7 @@
M(StyleSheets) \
M(SVG) \
M(TextAutosizing) \
+ M(TextFragment) \
M(TextShaping) \
M(Tiling) \
M(Threading) \