Title: [259523] trunk
Revision
259523
Author
[email protected]
Date
2020-04-03 17:44:31 -0700 (Fri, 03 Apr 2020)

Log Message

Add SPI to make WKUserScripts wait for a notification
https://bugs.webkit.org/show_bug.cgi?id=209845
<rdar://problem/60342299>

Patch by Alex Christensen <[email protected]> on 2020-04-03
Reviewed by Chris Dumez.

Source/WebCore:

There's also SPI on WKWebView to provide this notification, and on WKWebViewConfiguration to start out with this notification.

* dom/ExtensionStyleSheets.cpp:
(WebCore::ExtensionStyleSheets::updateInjectedStyleSheetCache const):
* html/ImageDocument.cpp:
(WebCore::ImageDocument::createDocumentStructure):
* html/MediaDocument.cpp:
(WebCore::MediaDocumentParser::createDocumentStructure):
* html/PluginDocument.cpp:
(WebCore::PluginDocumentParser::createDocumentStructure):
* html/parser/HTMLConstructionSite.cpp:
(WebCore::HTMLConstructionSite::dispatchDocumentElementAvailableIfNeeded):
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::finishedParsing):
* page/Frame.cpp:
(WebCore::Frame::injectUserScripts):
(WebCore::Frame::injectUserScriptImmediately):
* page/Page.cpp:
(WebCore::m_deviceOrientationUpdateProvider):
(WebCore::Page::notifyToInjectUserScripts):
(WebCore::Page::addUserScriptAwaitingNotification):
(WebCore::Page::injectUserStyleSheet):
(WebCore::Page::removeInjectedUserStyleSheet):
* page/Page.h:
(WebCore::Page::hasBeenNotifiedToInjectUserScripts const):
* page/PageConfiguration.h:
* page/UserContentTypes.h:
(): Deleted.
* page/UserScript.h:
(WebCore::UserScript::UserScript):
(WebCore::UserScript::waitForNotificationBeforeInjecting const):
(WebCore::UserScript::encode const):
(WebCore::UserScript::decode):
* page/UserScriptTypes.h:
(): Deleted.
* page/UserStyleSheet.h:
(WebCore::UserStyleSheet::UserStyleSheet):
* xml/parser/XMLDocumentParserLibxml2.cpp:
(WebCore::XMLDocumentParser::startElementNs):

Source/WebKit:

* Shared/API/c/WKSharedAPICast.h:
(WebKit::toUserScriptInjectionTime):
(WebKit::toWKUserScriptInjectionTime):
(WebKit::toUserContentInjectedFrames):
* Shared/WebPageCreationParameters.cpp:
(WebKit::WebPageCreationParameters::encode const):
(WebKit::WebPageCreationParameters::decode):
* Shared/WebPageCreationParameters.h:
* Shared/WebUserContentControllerDataTypes.cpp:
(WebKit::WebUserScriptData::decode):
* UIProcess/API/APIPageConfiguration.h:
(API::PageConfiguration::userScriptsShouldWaitUntilNotification const):
(API::PageConfiguration::setUserScriptsShouldWaitUntilNotification):
* UIProcess/API/APIUserScript.h:
* UIProcess/API/C/WKPageGroup.cpp:
(WKPageGroupAddUserScript):
* UIProcess/API/C/WKUserScriptRef.cpp:
(WKUserScriptCreateWithSource):
(WKUserScriptGetMainFrameOnly):
* UIProcess/API/Cocoa/WKUserScript.mm:
(-[WKUserScript initWithSource:injectionTime:forMainFrameOnly:]):
(-[WKUserScript isForMainFrameOnly]):
(-[WKUserScript _initWithSource:injectionTime:forMainFrameOnly:legacyWhitelist:legacyBlacklist:userContentWorld:]):
(-[WKUserScript _initWithSource:injectionTime:forMainFrameOnly:legacyWhitelist:legacyBlacklist:associatedURL:userContentWorld:]):
(-[WKUserScript _initWithSource:injectionTime:forMainFrameOnly:legacyWhitelist:legacyBlacklist:contentWorld:]):
(-[WKUserScript _initWithSource:injectionTime:forMainFrameOnly:legacyWhitelist:legacyBlacklist:associatedURL:contentWorld:]):
(-[WKUserScript _initWithSource:injectionTime:forMainFrameOnly:legacyWhitelist:legacyBlacklist:associatedURL:contentWorld:waitForNotification:]):
* UIProcess/API/Cocoa/WKUserScriptInternal.h:
(API::toWebCoreUserScriptInjectionTime):
(API::toWKUserScriptInjectionTime):
* UIProcess/API/Cocoa/WKUserScriptPrivate.h:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _notifyUserScripts]):
* UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
(-[WKWebViewConfiguration _userScriptsShouldWaitUntilNotification]):
(-[WKWebViewConfiguration _setUserScriptsShouldWaitUntilNotification:]):
* UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/API/Cocoa/_WKUserStyleSheet.mm:
(-[_WKUserStyleSheet initWithSource:forMainFrameOnly:]):
(-[_WKUserStyleSheet initWithSource:forWKWebView:forMainFrameOnly:userContentWorld:]):
(-[_WKUserStyleSheet initWithSource:forMainFrameOnly:legacyWhitelist:legacyBlacklist:userContentWorld:]):
(-[_WKUserStyleSheet initWithSource:forMainFrameOnly:legacyWhitelist:legacyBlacklist:baseURL:userContentWorld:]):
(-[_WKUserStyleSheet isForMainFrameOnly]):
* UIProcess/WebPageProxy.cpp:
* UIProcess/WebPageProxy.h:
* WebProcess/UserContent/WebUserContentController.cpp:
(WebKit::WebUserContentController::addUserScriptInternal):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::m_processDisplayName):
(WebKit::WebPage::notifyUserScripts):
(WebKit::WebPage::addUserScript):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

Source/WebKitLegacy/mac:

* WebView/WebView.mm:
(-[WebView _injectOutlookQuirksScript]):

Source/WebKitLegacy/win:

* WebView.cpp:
(WebView::addUserScriptToGroup):
(WebView::addUserStyleSheetToGroup):

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/UserContentController.mm:
(TEST):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (259522 => 259523)


--- trunk/Source/WebCore/ChangeLog	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebCore/ChangeLog	2020-04-04 00:44:31 UTC (rev 259523)
@@ -1,5 +1,53 @@
 2020-04-03  Alex Christensen  <[email protected]>
 
+        Add SPI to make WKUserScripts wait for a notification
+        https://bugs.webkit.org/show_bug.cgi?id=209845
+        <rdar://problem/60342299>
+
+        Reviewed by Chris Dumez.
+
+        There's also SPI on WKWebView to provide this notification, and on WKWebViewConfiguration to start out with this notification.
+
+        * dom/ExtensionStyleSheets.cpp:
+        (WebCore::ExtensionStyleSheets::updateInjectedStyleSheetCache const):
+        * html/ImageDocument.cpp:
+        (WebCore::ImageDocument::createDocumentStructure):
+        * html/MediaDocument.cpp:
+        (WebCore::MediaDocumentParser::createDocumentStructure):
+        * html/PluginDocument.cpp:
+        (WebCore::PluginDocumentParser::createDocumentStructure):
+        * html/parser/HTMLConstructionSite.cpp:
+        (WebCore::HTMLConstructionSite::dispatchDocumentElementAvailableIfNeeded):
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::finishedParsing):
+        * page/Frame.cpp:
+        (WebCore::Frame::injectUserScripts):
+        (WebCore::Frame::injectUserScriptImmediately):
+        * page/Page.cpp:
+        (WebCore::m_deviceOrientationUpdateProvider):
+        (WebCore::Page::notifyToInjectUserScripts):
+        (WebCore::Page::addUserScriptAwaitingNotification):
+        (WebCore::Page::injectUserStyleSheet):
+        (WebCore::Page::removeInjectedUserStyleSheet):
+        * page/Page.h:
+        (WebCore::Page::hasBeenNotifiedToInjectUserScripts const):
+        * page/PageConfiguration.h:
+        * page/UserContentTypes.h:
+        (): Deleted.
+        * page/UserScript.h:
+        (WebCore::UserScript::UserScript):
+        (WebCore::UserScript::waitForNotificationBeforeInjecting const):
+        (WebCore::UserScript::encode const):
+        (WebCore::UserScript::decode):
+        * page/UserScriptTypes.h:
+        (): Deleted.
+        * page/UserStyleSheet.h:
+        (WebCore::UserStyleSheet::UserStyleSheet):
+        * xml/parser/XMLDocumentParserLibxml2.cpp:
+        (WebCore::XMLDocumentParser::startElementNs):
+
+2020-04-03  Alex Christensen  <[email protected]>
+
         Use-after-move of `formState` in WebCore::PolicyChecker::checkNavigationPolicy()
         https://bugs.webkit.org/show_bug.cgi?id=209987
 

Modified: trunk/Source/WebCore/dom/ExtensionStyleSheets.cpp (259522 => 259523)


--- trunk/Source/WebCore/dom/ExtensionStyleSheets.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebCore/dom/ExtensionStyleSheets.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -138,7 +138,7 @@
         if (userStyleSheet.pageID())
             return;
 
-        if (userStyleSheet.injectedFrames() == InjectInTopFrameOnly && m_document.ownerElement())
+        if (userStyleSheet.injectedFrames() == UserContentInjectedFrames::InjectInTopFrameOnly && m_document.ownerElement())
             return;
 
         if (!UserContentURLPattern::matchesPatterns(m_document.url(), userStyleSheet.whitelist(), userStyleSheet.blacklist()))

Modified: trunk/Source/WebCore/html/ImageDocument.cpp (259522 => 259523)


--- trunk/Source/WebCore/html/ImageDocument.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebCore/html/ImageDocument.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -221,7 +221,7 @@
     appendChild(rootElement);
     rootElement->insertedByParser();
 
-    frame()->injectUserScripts(InjectAtDocumentStart);
+    frame()->injectUserScripts(UserScriptInjectionTime::DocumentStart);
 
     // We need a <head> so that the call to setTitle() later on actually has an <head> to append to <title> to.
     auto head = HTMLHeadElement::create(*this);

Modified: trunk/Source/WebCore/html/MediaDocument.cpp (259522 => 259523)


--- trunk/Source/WebCore/html/MediaDocument.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebCore/html/MediaDocument.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -93,7 +93,7 @@
     rootElement->insertedByParser();
 
     if (document.frame())
-        document.frame()->injectUserScripts(InjectAtDocumentStart);
+        document.frame()->injectUserScripts(UserScriptInjectionTime::DocumentStart);
 
 #if PLATFORM(IOS_FAMILY)
     auto headElement = HTMLHeadElement::create(document);

Modified: trunk/Source/WebCore/html/PluginDocument.cpp (259522 => 259523)


--- trunk/Source/WebCore/html/PluginDocument.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebCore/html/PluginDocument.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -74,7 +74,7 @@
     rootElement->insertedByParser();
 
     if (document.frame())
-        document.frame()->injectUserScripts(InjectAtDocumentStart);
+        document.frame()->injectUserScripts(UserScriptInjectionTime::DocumentStart);
 
 #if PLATFORM(IOS_FAMILY)
     // Should not be able to zoom into standalone plug-in documents.

Modified: trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp (259522 => 259523)


--- trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -270,7 +270,7 @@
         return;
 
     if (auto frame = makeRefPtr(m_document.frame()))
-        frame->injectUserScripts(InjectAtDocumentStart);
+        frame->injectUserScripts(UserScriptInjectionTime::DocumentStart);
 }
 
 void HTMLConstructionSite::insertHTMLHtmlStartTagBeforeHTML(AtomicHTMLToken&& token)

Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (259522 => 259523)


--- trunk/Source/WebCore/loader/FrameLoader.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -793,7 +793,7 @@
 {
     LOG(Loading, "WebCoreLoading %s: Finished parsing", m_frame.tree().uniqueName().string().utf8().data());
 
-    m_frame.injectUserScripts(InjectAtDocumentEnd);
+    m_frame.injectUserScripts(UserScriptInjectionTime::DocumentEnd);
 
     if (m_stateMachine.creatingInitialEmptyDocument())
         return;

Modified: trunk/Source/WebCore/page/Frame.cpp (259522 => 259523)


--- trunk/Source/WebCore/page/Frame.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebCore/page/Frame.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -619,9 +619,14 @@
     if (loader().stateMachine().creatingInitialEmptyDocument() && !settings().shouldInjectUserScriptsInInitialEmptyDocument())
         return;
 
-    m_page->userContentProvider().forEachUserScript([this, protectedThis = makeRef(*this), injectionTime](DOMWrapperWorld& world, const UserScript& script) {
-        if (script.injectionTime() == injectionTime)
-            injectUserScriptImmediately(world, script);
+    bool pageWasNotified = m_page->hasBeenNotifiedToInjectUserScripts();
+    m_page->userContentProvider().forEachUserScript([this, protectedThis = makeRef(*this), injectionTime, pageWasNotified] (DOMWrapperWorld& world, const UserScript& script) {
+        if (script.injectionTime() == injectionTime) {
+            if (script.waitForNotificationBeforeInjecting() == WaitForNotificationBeforeInjecting::Yes && !pageWasNotified)
+                m_page->addUserScriptAwaitingNotification(world, script);
+            else
+                injectUserScriptImmediately(world, script);
+        }
     });
 }
 
@@ -637,7 +642,7 @@
     auto* document = this->document();
     if (!document)
         return;
-    if (script.injectedFrames() == InjectInTopFrameOnly && !isMainFrame())
+    if (script.injectedFrames() == UserContentInjectedFrames::InjectInTopFrameOnly && !isMainFrame())
         return;
     if (!UserContentURLPattern::matchesPatterns(document->url(), script.whitelist(), script.blacklist()))
         return;

Modified: trunk/Source/WebCore/page/Page.cpp (259522 => 259523)


--- trunk/Source/WebCore/page/Page.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebCore/page/Page.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -124,6 +124,7 @@
 #include "UserContentProvider.h"
 #include "UserContentURLPattern.h"
 #include "UserInputBridge.h"
+#include "UserScript.h"
 #include "UserStyleSheet.h"
 #include "ValidationMessageClient.h"
 #include "VisitedLinkState.h"
@@ -337,6 +338,9 @@
             m_corsDisablingPatterns.uncheckedAppend(WTFMove(parsedPattern));
     }
     m_corsDisablingPatterns.shrinkToFit();
+    
+    if (!pageConfiguration.userScriptsShouldWaitUntilNotification)
+        m_hasBeenNotifiedToInjectUserScripts = true;
 }
 
 Page::~Page()
@@ -2473,6 +2477,20 @@
     return m_userContentProvider;
 }
 
+void Page::notifyToInjectUserScripts()
+{
+    for (auto* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+        for (const auto& pair : m_userScriptsAwaitingNotification)
+            frame->injectUserScriptImmediately(pair.first, pair.second.get());
+    }
+    m_userScriptsAwaitingNotification.clear();
+}
+
+void Page::addUserScriptAwaitingNotification(DOMWrapperWorld& world, const UserScript& script)
+{
+    m_userScriptsAwaitingNotification.append({ makeRef(world), makeUniqueRef<UserScript>(script) });
+}
+
 void Page::setUserContentProvider(Ref<UserContentProvider>&& userContentProvider)
 {
     m_userContentProvider->removePage(*this);
@@ -3073,7 +3091,7 @@
         return;
     }
 
-    if (userStyleSheet.injectedFrames() == InjectInTopFrameOnly) {
+    if (userStyleSheet.injectedFrames() == UserContentInjectedFrames::InjectInTopFrameOnly) {
         if (auto* document = m_mainFrame->document())
             document->extensionStyleSheets().injectPageSpecificUserStyleSheet(userStyleSheet);
     } else {
@@ -3092,7 +3110,7 @@
         return;
     }
 
-    if (userStyleSheet.injectedFrames() == InjectInTopFrameOnly) {
+    if (userStyleSheet.injectedFrames() == UserContentInjectedFrames::InjectInTopFrameOnly) {
         if (auto* document = m_mainFrame->document())
             document->extensionStyleSheets().removePageSpecificUserStyleSheet(userStyleSheet);
     } else {

Modified: trunk/Source/WebCore/page/Page.h (259522 => 259523)


--- trunk/Source/WebCore/page/Page.h	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebCore/page/Page.h	2020-04-04 00:44:31 UTC (rev 259523)
@@ -140,6 +140,7 @@
 class UserContentProvider;
 class UserContentURLPattern;
 class UserInputBridge;
+class UserScript;
 class UserStyleSheet;
 class ValidationMessageClient;
 class VisibleSelection;
@@ -734,6 +735,10 @@
     bool shouldFireResizeEvents() const { return m_shouldFireResizeEvents; }
     void setShouldFireResizeEvents(bool shouldFireResizeEvents) { m_shouldFireResizeEvents = shouldFireResizeEvents; }
 
+    bool hasBeenNotifiedToInjectUserScripts() const { return m_hasBeenNotifiedToInjectUserScripts; }
+    WEBCORE_EXPORT void notifyToInjectUserScripts();
+    void addUserScriptAwaitingNotification(DOMWrapperWorld&, const UserScript&);
+
 private:
     struct Navigation {
         RegistrableDomain domain;
@@ -1015,6 +1020,8 @@
     bool m_shouldFireResizeEvents { true };
     bool m_loadsSubresources { true };
     bool m_loadsFromNetwork { true };
+    bool m_hasBeenNotifiedToInjectUserScripts { false };
+    Vector<std::pair<Ref<DOMWrapperWorld>, UniqueRef<UserScript>>> m_userScriptsAwaitingNotification;
 };
 
 inline PageGroup& Page::group()

Modified: trunk/Source/WebCore/page/PageConfiguration.h (259522 => 259523)


--- trunk/Source/WebCore/page/PageConfiguration.h	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebCore/page/PageConfiguration.h	2020-04-04 00:44:31 UTC (rev 259523)
@@ -129,6 +129,7 @@
     UniqueRef<MediaRecorderProvider> mediaRecorderProvider;
     bool loadsSubresources { true };
     bool loadsFromNetwork { true };
+    bool userScriptsShouldWaitUntilNotification { true };
 };
 
 }

Modified: trunk/Source/WebCore/page/UserContentTypes.h (259522 => 259523)


--- trunk/Source/WebCore/page/UserContentTypes.h	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebCore/page/UserContentTypes.h	2020-04-04 00:44:31 UTC (rev 259523)
@@ -27,6 +27,6 @@
 
 namespace WebCore {
 
-enum UserContentInjectedFrames { InjectInAllFrames, InjectInTopFrameOnly };
+enum class UserContentInjectedFrames : bool { InjectInAllFrames, InjectInTopFrameOnly };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/page/UserScript.h (259522 => 259523)


--- trunk/Source/WebCore/page/UserScript.h	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebCore/page/UserScript.h	2020-04-04 00:44:31 UTC (rev 259523)
@@ -35,10 +35,13 @@
 class UserScript {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    UserScript() = default;
     ~UserScript() = default;
+    UserScript(const UserScript&) = default;
+    UserScript(UserScript&&) = default;
+    UserScript& operator=(const UserScript&) = default;
+    UserScript& operator=(UserScript&&) = default;
 
-    UserScript(String&& source, URL&& url, Vector<String>&& whitelist, Vector<String>&& blacklist, UserScriptInjectionTime injectionTime, UserContentInjectedFrames injectedFrames)
+    UserScript(String&& source, URL&& url, Vector<String>&& whitelist, Vector<String>&& blacklist, UserScriptInjectionTime injectionTime, UserContentInjectedFrames injectedFrames, WaitForNotificationBeforeInjecting waitForNotification)
         : m_source(WTFMove(source))
         , m_url(WTFMove(url))
         , m_whitelist(WTFMove(whitelist))
@@ -45,6 +48,7 @@
         , m_blacklist(WTFMove(blacklist))
         , m_injectionTime(injectionTime)
         , m_injectedFrames(injectedFrames)
+        , m_waitForNotificationBeforeInjecting(waitForNotification)
     {
     }
 
@@ -54,9 +58,10 @@
     const Vector<String>& blacklist() const { return m_blacklist; }
     UserScriptInjectionTime injectionTime() const { return m_injectionTime; }
     UserContentInjectedFrames injectedFrames() const { return m_injectedFrames; }
+    WaitForNotificationBeforeInjecting waitForNotificationBeforeInjecting() const { return m_waitForNotificationBeforeInjecting; }
 
     template<class Encoder> void encode(Encoder&) const;
-    template<class Decoder> static bool decode(Decoder&, UserScript&);
+    template<class Decoder> static Optional<UserScript> decode(Decoder&);
 
 private:
     String m_source;
@@ -63,8 +68,9 @@
     URL m_url;
     Vector<String> m_whitelist;
     Vector<String> m_blacklist;
-    UserScriptInjectionTime m_injectionTime { InjectAtDocumentStart };
-    UserContentInjectedFrames m_injectedFrames { InjectInAllFrames };
+    UserScriptInjectionTime m_injectionTime { UserScriptInjectionTime::DocumentStart };
+    UserContentInjectedFrames m_injectedFrames { UserContentInjectedFrames::InjectInAllFrames };
+    WaitForNotificationBeforeInjecting m_waitForNotificationBeforeInjecting { WaitForNotificationBeforeInjecting::No };
 };
 
 template<class Encoder>
@@ -74,39 +80,58 @@
     encoder << m_url;
     encoder << m_whitelist;
     encoder << m_blacklist;
-    encoder.encodeEnum(m_injectionTime);
-    encoder.encodeEnum(m_injectedFrames);
+    encoder << m_injectionTime;
+    encoder << m_injectedFrames;
+    encoder << m_waitForNotificationBeforeInjecting;
 }
 
 template<class Decoder>
-bool UserScript::decode(Decoder& decoder, UserScript& userScript)
+Optional<UserScript> UserScript::decode(Decoder& decoder)
 {
-    String source;
-    if (!decoder.decode(source))
-        return false;
+    Optional<String> source;
+    decoder >> source;
+    if (!source)
+        return WTF::nullopt;
     
-    URL url;
-    if (!decoder.decode(url))
-        return false;
+    Optional<URL> url;
+    decoder >> url;
+    if (!url)
+        return WTF::nullopt;
     
-    Vector<String> whitelist;
-    if (!decoder.decode(whitelist))
-        return false;
+    Optional<Vector<String>> whitelist;
+    decoder >> whitelist;
+    if (!whitelist)
+        return WTF::nullopt;
     
-    Vector<String> blacklist;
-    if (!decoder.decode(blacklist))
-        return false;
+    Optional<Vector<String>> blacklist;
+    decoder >> blacklist;
+    if (!blacklist)
+        return WTF::nullopt;
     
-    UserScriptInjectionTime injectionTime;
-    if (!decoder.decodeEnum(injectionTime))
-        return false;
+    Optional<UserScriptInjectionTime> injectionTime;
+    decoder >> injectionTime;
+    if (!injectionTime)
+        return WTF::nullopt;
     
-    UserContentInjectedFrames injectedFrames;
-    if (!decoder.decodeEnum(injectedFrames))
-        return false;
+    Optional<UserContentInjectedFrames> injectedFrames;
+    decoder >> injectedFrames;
+    if (!injectedFrames)
+        return WTF::nullopt;
     
-    userScript = { WTFMove(source), WTFMove(url), WTFMove(whitelist), WTFMove(blacklist), injectionTime, injectedFrames };
-    return true;
+    Optional<WaitForNotificationBeforeInjecting> waitForNotification;
+    decoder >> waitForNotification;
+    if (!waitForNotification)
+        return WTF::nullopt;
+    
+    return {{
+        WTFMove(*source),
+        WTFMove(*url),
+        WTFMove(*whitelist),
+        WTFMove(*blacklist),
+        WTFMove(*injectionTime),
+        WTFMove(*injectedFrames),
+        WTFMove(*waitForNotification)
+    }};
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/page/UserScriptTypes.h (259522 => 259523)


--- trunk/Source/WebCore/page/UserScriptTypes.h	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebCore/page/UserScriptTypes.h	2020-04-04 00:44:31 UTC (rev 259523)
@@ -30,7 +30,8 @@
 
 namespace WebCore {
 
-enum UserScriptInjectionTime { InjectAtDocumentStart, InjectAtDocumentEnd };
+enum class UserScriptInjectionTime : bool { DocumentStart, DocumentEnd };
+enum class WaitForNotificationBeforeInjecting : bool { No, Yes };
 
 class DOMWrapperWorld;
 class UserScript;

Modified: trunk/Source/WebCore/page/UserStyleSheet.h (259522 => 259523)


--- trunk/Source/WebCore/page/UserStyleSheet.h	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebCore/page/UserStyleSheet.h	2020-04-04 00:44:31 UTC (rev 259523)
@@ -38,7 +38,7 @@
     WTF_MAKE_FAST_ALLOCATED;
 public:
     UserStyleSheet()
-        : m_injectedFrames(InjectInAllFrames)
+        : m_injectedFrames(UserContentInjectedFrames::InjectInAllFrames)
         , m_level(UserStyleUserLevel)
     {
     }

Modified: trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp (259522 => 259523)


--- trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -813,7 +813,7 @@
         downcast<HTMLHtmlElement>(newElement.get()).insertedByParser();
 
     if (!m_parsingFragment && isFirstElement && document()->frame())
-        document()->frame()->injectUserScripts(InjectAtDocumentStart);
+        document()->frame()->injectUserScripts(UserScriptInjectionTime::DocumentStart);
 }
 
 void XMLDocumentParser::endElementNs()

Modified: trunk/Source/WebKit/ChangeLog (259522 => 259523)


--- trunk/Source/WebKit/ChangeLog	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/ChangeLog	2020-04-04 00:44:31 UTC (rev 259523)
@@ -1,5 +1,68 @@
 2020-04-03  Alex Christensen  <[email protected]>
 
+        Add SPI to make WKUserScripts wait for a notification
+        https://bugs.webkit.org/show_bug.cgi?id=209845
+        <rdar://problem/60342299>
+
+        Reviewed by Chris Dumez.
+
+        * Shared/API/c/WKSharedAPICast.h:
+        (WebKit::toUserScriptInjectionTime):
+        (WebKit::toWKUserScriptInjectionTime):
+        (WebKit::toUserContentInjectedFrames):
+        * Shared/WebPageCreationParameters.cpp:
+        (WebKit::WebPageCreationParameters::encode const):
+        (WebKit::WebPageCreationParameters::decode):
+        * Shared/WebPageCreationParameters.h:
+        * Shared/WebUserContentControllerDataTypes.cpp:
+        (WebKit::WebUserScriptData::decode):
+        * UIProcess/API/APIPageConfiguration.h:
+        (API::PageConfiguration::userScriptsShouldWaitUntilNotification const):
+        (API::PageConfiguration::setUserScriptsShouldWaitUntilNotification):
+        * UIProcess/API/APIUserScript.h:
+        * UIProcess/API/C/WKPageGroup.cpp:
+        (WKPageGroupAddUserScript):
+        * UIProcess/API/C/WKUserScriptRef.cpp:
+        (WKUserScriptCreateWithSource):
+        (WKUserScriptGetMainFrameOnly):
+        * UIProcess/API/Cocoa/WKUserScript.mm:
+        (-[WKUserScript initWithSource:injectionTime:forMainFrameOnly:]):
+        (-[WKUserScript isForMainFrameOnly]):
+        (-[WKUserScript _initWithSource:injectionTime:forMainFrameOnly:legacyWhitelist:legacyBlacklist:userContentWorld:]):
+        (-[WKUserScript _initWithSource:injectionTime:forMainFrameOnly:legacyWhitelist:legacyBlacklist:associatedURL:userContentWorld:]):
+        (-[WKUserScript _initWithSource:injectionTime:forMainFrameOnly:legacyWhitelist:legacyBlacklist:contentWorld:]):
+        (-[WKUserScript _initWithSource:injectionTime:forMainFrameOnly:legacyWhitelist:legacyBlacklist:associatedURL:contentWorld:]):
+        (-[WKUserScript _initWithSource:injectionTime:forMainFrameOnly:legacyWhitelist:legacyBlacklist:associatedURL:contentWorld:waitForNotification:]):
+        * UIProcess/API/Cocoa/WKUserScriptInternal.h:
+        (API::toWebCoreUserScriptInjectionTime):
+        (API::toWKUserScriptInjectionTime):
+        * UIProcess/API/Cocoa/WKUserScriptPrivate.h:
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _notifyUserScripts]):
+        * UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
+        (-[WKWebViewConfiguration _userScriptsShouldWaitUntilNotification]):
+        (-[WKWebViewConfiguration _setUserScriptsShouldWaitUntilNotification:]):
+        * UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+        * UIProcess/API/Cocoa/_WKUserStyleSheet.mm:
+        (-[_WKUserStyleSheet initWithSource:forMainFrameOnly:]):
+        (-[_WKUserStyleSheet initWithSource:forWKWebView:forMainFrameOnly:userContentWorld:]):
+        (-[_WKUserStyleSheet initWithSource:forMainFrameOnly:legacyWhitelist:legacyBlacklist:userContentWorld:]):
+        (-[_WKUserStyleSheet initWithSource:forMainFrameOnly:legacyWhitelist:legacyBlacklist:baseURL:userContentWorld:]):
+        (-[_WKUserStyleSheet isForMainFrameOnly]):
+        * UIProcess/WebPageProxy.cpp:
+        * UIProcess/WebPageProxy.h:
+        * WebProcess/UserContent/WebUserContentController.cpp:
+        (WebKit::WebUserContentController::addUserScriptInternal):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::m_processDisplayName):
+        (WebKit::WebPage::notifyUserScripts):
+        (WebKit::WebPage::addUserScript):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
+2020-04-03  Alex Christensen  <[email protected]>
+
         Use AuthenticationChallenge instead of AuthenticationChallengeProxy for ResourceLoadDelegate
         https://bugs.webkit.org/show_bug.cgi?id=207639
 

Modified: trunk/Source/WebKit/Shared/API/c/WKSharedAPICast.h (259522 => 259523)


--- trunk/Source/WebKit/Shared/API/c/WKSharedAPICast.h	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/Shared/API/c/WKSharedAPICast.h	2020-04-04 00:44:31 UTC (rev 259523)
@@ -993,21 +993,21 @@
 {
     switch (wkInjectedTime) {
     case kWKInjectAtDocumentStart:
-        return WebCore::InjectAtDocumentStart;
+        return WebCore::UserScriptInjectionTime::DocumentStart;
     case kWKInjectAtDocumentEnd:
-        return WebCore::InjectAtDocumentEnd;
+        return WebCore::UserScriptInjectionTime::DocumentEnd;
     }
 
     ASSERT_NOT_REACHED();
-    return WebCore::InjectAtDocumentStart;
+    return WebCore::UserScriptInjectionTime::DocumentStart;
 }
 
 inline _WKUserScriptInjectionTime toWKUserScriptInjectionTime(WebCore::UserScriptInjectionTime injectedTime)
 {
     switch (injectedTime) {
-    case WebCore::InjectAtDocumentStart:
+    case WebCore::UserScriptInjectionTime::DocumentStart:
         return kWKInjectAtDocumentStart;
-    case WebCore::InjectAtDocumentEnd:
+    case WebCore::UserScriptInjectionTime::DocumentEnd:
         return kWKInjectAtDocumentEnd;
     }
 
@@ -1019,13 +1019,13 @@
 {
     switch (wkInjectedFrames) {
     case kWKInjectInAllFrames:
-        return WebCore::InjectInAllFrames;
+        return WebCore::UserContentInjectedFrames::InjectInAllFrames;
     case kWKInjectInTopFrameOnly:
-        return WebCore::InjectInTopFrameOnly;
+        return WebCore::UserContentInjectedFrames::InjectInTopFrameOnly;
     }
 
     ASSERT_NOT_REACHED();
-    return WebCore::InjectInAllFrames;
+    return WebCore::UserContentInjectedFrames::InjectInAllFrames;
 }
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/Shared/WebPageCreationParameters.cpp (259522 => 259523)


--- trunk/Source/WebKit/Shared/WebPageCreationParameters.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/Shared/WebPageCreationParameters.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -135,6 +135,7 @@
     encoder << corsDisablingPatterns;
     encoder << loadsSubresources;
     encoder << loadsFromNetwork;
+    encoder << userScriptsShouldWaitUntilNotification;
     encoder << crossOriginAccessControlCheckEnabled;
     encoder << processDisplayName;
 
@@ -430,6 +431,12 @@
         return WTF::nullopt;
     parameters.loadsFromNetwork = *loadsFromNetwork;
 
+    Optional<bool> userScriptsShouldWaitUntilNotification;
+    decoder >> userScriptsShouldWaitUntilNotification;
+    if (!userScriptsShouldWaitUntilNotification)
+        return WTF::nullopt;
+    parameters.userScriptsShouldWaitUntilNotification = *userScriptsShouldWaitUntilNotification;
+    
     Optional<bool> crossOriginAccessControlCheckEnabled;
     decoder >> crossOriginAccessControlCheckEnabled;
     if (!crossOriginAccessControlCheckEnabled)

Modified: trunk/Source/WebKit/Shared/WebPageCreationParameters.h (259522 => 259523)


--- trunk/Source/WebKit/Shared/WebPageCreationParameters.h	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/Shared/WebPageCreationParameters.h	2020-04-04 00:44:31 UTC (rev 259523)
@@ -202,6 +202,7 @@
 
     String overriddenMediaType;
     Vector<String> corsDisablingPatterns;
+    bool userScriptsShouldWaitUntilNotification { true };
     bool loadsSubresources { true };
     bool loadsFromNetwork { true };
 

Modified: trunk/Source/WebKit/Shared/WebUserContentControllerDataTypes.cpp (259522 => 259523)


--- trunk/Source/WebKit/Shared/WebUserContentControllerDataTypes.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/Shared/WebUserContentControllerDataTypes.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -49,11 +49,12 @@
     if (!worldIdentifier)
         return WTF::nullopt;
     
-    WebCore::UserScript userScript;
-    if (!decoder.decode(userScript))
+    Optional<WebCore::UserScript> userScript;
+    decoder >> userScript;
+    if (!userScript)
         return WTF::nullopt;
     
-    return {{ WTFMove(*identifier), WTFMove(*worldIdentifier), WTFMove(userScript) }};
+    return {{ WTFMove(*identifier), WTFMove(*worldIdentifier), WTFMove(*userScript) }};
 }
 
 void WebUserStyleSheetData::encode(IPC::Encoder& encoder) const

Modified: trunk/Source/WebKit/UIProcess/API/APIPageConfiguration.cpp (259522 => 259523)


--- trunk/Source/WebKit/UIProcess/API/APIPageConfiguration.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/UIProcess/API/APIPageConfiguration.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -90,6 +90,7 @@
         copy->m_urlSchemeHandlers.set(pair.key, pair.value.copyRef());
     copy->m_corsDisablingPatterns = this->m_corsDisablingPatterns;
     copy->m_crossOriginAccessControlCheckEnabled = this->m_crossOriginAccessControlCheckEnabled;
+    copy->m_userScriptsShouldWaitUntilNotification = this->m_userScriptsShouldWaitUntilNotification;
     copy->m_webViewCategory = this->m_webViewCategory;
 
     copy->m_processDisplayName = this->m_processDisplayName;

Modified: trunk/Source/WebKit/UIProcess/API/APIPageConfiguration.h (259522 => 259523)


--- trunk/Source/WebKit/UIProcess/API/APIPageConfiguration.h	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/UIProcess/API/APIPageConfiguration.h	2020-04-04 00:44:31 UTC (rev 259523)
@@ -136,6 +136,9 @@
 
     const Vector<WTF::String>& corsDisablingPatterns() const { return m_corsDisablingPatterns; }
     void setCORSDisablingPatterns(Vector<WTF::String>&& patterns) { m_corsDisablingPatterns = WTFMove(patterns); }
+    
+    bool userScriptsShouldWaitUntilNotification() const { return m_userScriptsShouldWaitUntilNotification; }
+    void setUserScriptsShouldWaitUntilNotification(bool value) { m_userScriptsShouldWaitUntilNotification = value; }
 
     bool crossOriginAccessControlCheckEnabled() const { return m_crossOriginAccessControlCheckEnabled; }
     void setCrossOriginAccessControlCheckEnabled(bool enabled) { m_crossOriginAccessControlCheckEnabled = enabled; }
@@ -191,6 +194,7 @@
 
     HashMap<WTF::String, Ref<WebKit::WebURLSchemeHandler>> m_urlSchemeHandlers;
     Vector<WTF::String> m_corsDisablingPatterns;
+    bool m_userScriptsShouldWaitUntilNotification { true };
     bool m_crossOriginAccessControlCheckEnabled { true };
     WTF::String m_processDisplayName;
     WebKit::WebViewCategory m_webViewCategory { WebKit::WebViewCategory::AppBoundDomain };

Modified: trunk/Source/WebKit/UIProcess/API/APIUserScript.h (259522 => 259523)


--- trunk/Source/WebKit/UIProcess/API/APIUserScript.h	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/UIProcess/API/APIUserScript.h	2020-04-04 00:44:31 UTC (rev 259523)
@@ -36,7 +36,7 @@
 public:
     static WTF::URL generateUniqueURL();
 
-    static Ref<UserScript> create(WebCore::UserScript userScript, API::ContentWorld& world)
+    static Ref<UserScript> create(WebCore::UserScript&& userScript, API::ContentWorld& world)
     {
         return adoptRef(*new UserScript(WTFMove(userScript), world));
     }
@@ -43,8 +43,9 @@
 
     UserScript(WebCore::UserScript, API::ContentWorld&);
 
+    WebCore::UserScript& userScript() { return m_userScript; }
     const WebCore::UserScript& userScript() const { return m_userScript; }
-    
+
     ContentWorld& contentWorld() { return m_world; }
     const ContentWorld& contentWorld() const { return m_world; }
     

Modified: trunk/Source/WebKit/UIProcess/API/C/WKPageGroup.cpp (259522 => 259523)


--- trunk/Source/WebKit/UIProcess/API/C/WKPageGroup.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/UIProcess/API/C/WKPageGroup.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -99,7 +99,7 @@
     auto blacklist = toImpl(blacklistedURLPatterns);
     
     auto url = "" ? aboutBlankURL() :  URL(URL(), baseURLString);
-    Ref<API::UserScript> userScript = API::UserScript::create(WebCore::UserScript { WTFMove(source), WTFMove(url), whitelist ? whitelist->toStringVector() : Vector<String>(), blacklist ? blacklist->toStringVector() : Vector<String>(), toUserScriptInjectionTime(injectionTime), toUserContentInjectedFrames(injectedFrames) }, API::ContentWorld::pageContentWorld());
+    Ref<API::UserScript> userScript = API::UserScript::create(WebCore::UserScript { WTFMove(source), WTFMove(url), whitelist ? whitelist->toStringVector() : Vector<String>(), blacklist ? blacklist->toStringVector() : Vector<String>(), toUserScriptInjectionTime(injectionTime), toUserContentInjectedFrames(injectedFrames), WebCore::WaitForNotificationBeforeInjecting::No }, API::ContentWorld::pageContentWorld());
     toImpl(pageGroupRef)->userContentController().addUserScript(userScript.get(), InjectUserScriptImmediately::No);
 }
 

Modified: trunk/Source/WebKit/UIProcess/API/C/WKUserScriptRef.cpp (259522 => 259523)


--- trunk/Source/WebKit/UIProcess/API/C/WKUserScriptRef.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/UIProcess/API/C/WKUserScriptRef.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -38,7 +38,7 @@
 
 WKUserScriptRef WKUserScriptCreateWithSource(WKStringRef sourceRef, _WKUserScriptInjectionTime injectionTime, bool forMainFrameOnly)
 {
-    return toAPI(&API::UserScript::create(WebCore::UserScript { toWTFString(sourceRef), API::UserScript::generateUniqueURL(), { }, { }, toUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames }, API::ContentWorld::pageContentWorld()).leakRef());
+    return toAPI(&API::UserScript::create(WebCore::UserScript { toWTFString(sourceRef), API::UserScript::generateUniqueURL(), { }, { }, toUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::UserContentInjectedFrames::InjectInTopFrameOnly : WebCore::UserContentInjectedFrames::InjectInAllFrames, WebCore::WaitForNotificationBeforeInjecting::No }, API::ContentWorld::pageContentWorld()).leakRef());
 }
 
 WKStringRef WKUserScriptCopySource(WKUserScriptRef userScriptRef)
@@ -53,5 +53,5 @@
 
 bool WKUserScriptGetMainFrameOnly(WKUserScriptRef userScriptRef)
 {
-    return toImpl(userScriptRef)->userScript().injectedFrames() == WebCore::InjectInTopFrameOnly;
+    return toImpl(userScriptRef)->userScript().injectedFrames() == WebCore::UserContentInjectedFrames::InjectInTopFrameOnly;
 }

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKUserScript.mm (259522 => 259523)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKUserScript.mm	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKUserScript.mm	2020-04-04 00:44:31 UTC (rev 259523)
@@ -35,7 +35,7 @@
     if (!(self = [super init]))
         return nil;
 
-    API::Object::constructInWrapper<API::UserScript>(self, WebCore::UserScript { WTF::String(source), API::UserScript::generateUniqueURL(), { }, { }, API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames }, API::ContentWorld::pageContentWorld());
+    API::Object::constructInWrapper<API::UserScript>(self, WebCore::UserScript { WTF::String(source), API::UserScript::generateUniqueURL(), { }, { }, API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::UserContentInjectedFrames::InjectInTopFrameOnly : WebCore::UserContentInjectedFrames::InjectInAllFrames, WebCore::WaitForNotificationBeforeInjecting::No }, API::ContentWorld::pageContentWorld());
 
     return self;
 }
@@ -59,7 +59,7 @@
 
 - (BOOL)isForMainFrameOnly
 {
-    return _userScript->userScript().injectedFrames() == WebCore::InjectInTopFrameOnly;
+    return _userScript->userScript().injectedFrames() == WebCore::UserContentInjectedFrames::InjectInTopFrameOnly;
 }
 
 - (id)copyWithZone:(NSZone *)zone
@@ -84,7 +84,7 @@
     if (!(self = [super init]))
         return nil;
 
-    API::Object::constructInWrapper<API::UserScript>(self, WebCore::UserScript { WTF::String(source), API::UserScript::generateUniqueURL(), API::toStringVector(legacyWhitelist), API::toStringVector(legacyBlacklist), API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames }, *userContentWorld->_contentWorld->_contentWorld);
+    API::Object::constructInWrapper<API::UserScript>(self, WebCore::UserScript { WTF::String(source), API::UserScript::generateUniqueURL(), API::toStringVector(legacyWhitelist), API::toStringVector(legacyBlacklist), API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::UserContentInjectedFrames::InjectInTopFrameOnly : WebCore::UserContentInjectedFrames::InjectInAllFrames, WebCore::WaitForNotificationBeforeInjecting::No }, *userContentWorld->_contentWorld->_contentWorld);
 
     return self;
 }
@@ -94,7 +94,7 @@
     if (!(self = [super init]))
         return nil;
 
-    API::Object::constructInWrapper<API::UserScript>(self, WebCore::UserScript { WTF::String(source), URL(associatedURL), API::toStringVector(legacyWhitelist), API::toStringVector(legacyBlacklist), API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames }, *userContentWorld->_contentWorld->_contentWorld);
+    API::Object::constructInWrapper<API::UserScript>(self, WebCore::UserScript { WTF::String(source), URL(associatedURL), API::toStringVector(legacyWhitelist), API::toStringVector(legacyBlacklist), API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::UserContentInjectedFrames::InjectInTopFrameOnly : WebCore::UserContentInjectedFrames::InjectInAllFrames, WebCore::WaitForNotificationBeforeInjecting::No }, *userContentWorld->_contentWorld->_contentWorld);
 
     return self;
 }
@@ -110,7 +110,7 @@
     if (!(self = [super init]))
         return nil;
 
-    API::Object::constructInWrapper<API::UserScript>(self, WebCore::UserScript { WTF::String(source), API::UserScript::generateUniqueURL(), API::toStringVector(legacyWhitelist), API::toStringVector(legacyBlacklist), API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames }, *contentWorld->_contentWorld);
+    API::Object::constructInWrapper<API::UserScript>(self, WebCore::UserScript { WTF::String(source), API::UserScript::generateUniqueURL(), API::toStringVector(legacyWhitelist), API::toStringVector(legacyBlacklist), API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::UserContentInjectedFrames::InjectInTopFrameOnly : WebCore::UserContentInjectedFrames::InjectInAllFrames, WebCore::WaitForNotificationBeforeInjecting::No }, *contentWorld->_contentWorld);
 
     return self;
 }
@@ -120,11 +120,21 @@
     if (!(self = [super init]))
         return nil;
 
-    API::Object::constructInWrapper<API::UserScript>(self, WebCore::UserScript { WTF::String(source), URL(associatedURL), API::toStringVector(legacyWhitelist), API::toStringVector(legacyBlacklist), API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames }, *contentWorld->_contentWorld);
+    API::Object::constructInWrapper<API::UserScript>(self, WebCore::UserScript { WTF::String(source), URL(associatedURL), API::toStringVector(legacyWhitelist), API::toStringVector(legacyBlacklist), API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::UserContentInjectedFrames::InjectInTopFrameOnly : WebCore::UserContentInjectedFrames::InjectInAllFrames, WebCore::WaitForNotificationBeforeInjecting::No }, *contentWorld->_contentWorld);
 
     return self;
 }
 
+- (instancetype)_initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly legacyWhitelist:(NSArray<NSString *> *)legacyWhitelist legacyBlacklist:(NSArray<NSString *> *)legacyBlacklist associatedURL:(NSURL *)associatedURL contentWorld:(WKContentWorld *)contentWorld deferRunningUntilNotification:(BOOL)deferRunningUntilNotification
+{
+    if (!(self = [super init]))
+        return nil;
+
+    API::Object::constructInWrapper<API::UserScript>(self, WebCore::UserScript { WTF::String(source), URL(associatedURL), API::toStringVector(legacyWhitelist), API::toStringVector(legacyBlacklist), API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::UserContentInjectedFrames::InjectInTopFrameOnly : WebCore::UserContentInjectedFrames::InjectInAllFrames, deferRunningUntilNotification ? WebCore::WaitForNotificationBeforeInjecting::Yes : WebCore::WaitForNotificationBeforeInjecting::No }, *contentWorld->_contentWorld);
+
+    return self;
+}
+
 - (WKContentWorld *)_contentWorld
 {
     return wrapper(_userScript->contentWorld());

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKUserScriptInternal.h (259522 => 259523)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKUserScriptInternal.h	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKUserScriptInternal.h	2020-04-04 00:44:31 UTC (rev 259523)
@@ -41,23 +41,21 @@
 {
     switch (injectionTime) {
     case WKUserScriptInjectionTimeAtDocumentStart:
-        return WebCore::InjectAtDocumentStart;
-
+        return WebCore::UserScriptInjectionTime::DocumentStart;
     case WKUserScriptInjectionTimeAtDocumentEnd:
-        return WebCore::InjectAtDocumentEnd;
+        return WebCore::UserScriptInjectionTime::DocumentEnd;
     }
 
     ASSERT_NOT_REACHED();
-    return WebCore::InjectAtDocumentEnd;
+    return WebCore::UserScriptInjectionTime::DocumentEnd;
 }
 
 inline WKUserScriptInjectionTime toWKUserScriptInjectionTime(WebCore::UserScriptInjectionTime injectionTime)
 {
     switch (injectionTime) {
-    case WebCore::InjectAtDocumentStart:
+    case WebCore::UserScriptInjectionTime::DocumentStart:
         return WKUserScriptInjectionTimeAtDocumentStart;
-
-    case WebCore::InjectAtDocumentEnd:
+    case WebCore::UserScriptInjectionTime::DocumentEnd:
         return WKUserScriptInjectionTimeAtDocumentEnd;
     }
 

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKUserScriptPrivate.h (259522 => 259523)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKUserScriptPrivate.h	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKUserScriptPrivate.h	2020-04-04 00:44:31 UTC (rev 259523)
@@ -38,6 +38,8 @@
 - (instancetype)_initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly legacyWhitelist:(NSArray<NSString *> *)legacyWhitelist legacyBlacklist:(NSArray<NSString *> *)legacyBlacklist contentWorld:(WKContentWorld *)contentWorld WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 - (instancetype)_initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly legacyWhitelist:(NSArray<NSString *> *)legacyWhitelist legacyBlacklist:(NSArray<NSString *> *)legacyBlacklist associatedURL:(NSURL *)associatedURL contentWorld:(WKContentWorld *)contentWorld WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 
+- (instancetype)_initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly legacyWhitelist:(NSArray<NSString *> *)legacyWhitelist legacyBlacklist:(NSArray<NSString *> *)legacyBlacklist associatedURL:(NSURL *)associatedURL contentWorld:(WKContentWorld *)contentWorld deferRunningUntilNotification:(BOOL)deferRunningUntilNotification WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 @property (nonatomic, readonly) _WKUserContentWorld *_userContentWorld WK_API_AVAILABLE(macos(10.12), ios(10.0));
 @property (nonatomic, readonly) WKContentWorld *_contentWorld WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm (259522 => 259523)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2020-04-04 00:44:31 UTC (rev 259523)
@@ -2326,6 +2326,16 @@
     _page->updateWebsitePolicies(WTFMove(data));
 }
 
+- (void)_notifyUserScripts
+{
+    _page->notifyUserScripts();
+}
+
+- (BOOL)_deferrableUserScriptsNeedNotification
+{
+    return _page->userScriptsNeedNotification();
+}
+
 - (BOOL)_allowsRemoteInspection
 {
 #if ENABLE(REMOTE_INSPECTOR)

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm (259522 => 259523)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm	2020-04-04 00:44:31 UTC (rev 259523)
@@ -933,6 +933,16 @@
     return _pageConfiguration->loadsSubresources();
 }
 
+- (BOOL)_deferrableUserScriptsShouldWaitUntilNotification
+{
+    return _pageConfiguration->userScriptsShouldWaitUntilNotification();
+}
+
+- (void)_setDeferrableUserScriptsShouldWaitUntilNotification:(BOOL)value
+{
+    _pageConfiguration->setUserScriptsShouldWaitUntilNotification(value);
+}
+
 - (void)_setCrossOriginAccessControlCheckEnabled:(BOOL)enabled
 {
     _pageConfiguration->setCrossOriginAccessControlCheckEnabled(enabled);

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h (259522 => 259523)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h	2020-04-04 00:44:31 UTC (rev 259523)
@@ -84,6 +84,7 @@
 
 @property (nonatomic, readonly) WKWebsiteDataStore *_websiteDataStoreIfExists WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 @property (nonatomic, copy, setter=_setCORSDisablingPatterns:) NSArray<NSString *> *_corsDisablingPatterns WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+@property (nonatomic, setter=_setDeferrableUserScriptsShouldWaitUntilNotification:) BOOL _deferrableUserScriptsShouldWaitUntilNotification WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 @property (nonatomic, setter=_setCrossOriginAccessControlCheckEnabled:) BOOL _crossOriginAccessControlCheckEnabled WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 
 @property (nonatomic, setter=_setLoadsFromNetwork:) BOOL _loadsFromNetwork WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h (259522 => 259523)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h	2020-04-04 00:44:31 UTC (rev 259523)
@@ -207,6 +207,8 @@
 
 - (void)_updateWebsitePolicies:(_WKWebsitePolicies *)websitePolicies WK_API_DEPRECATED_WITH_REPLACEMENT("-_updateWebpagePreferences:", macos(10.13, WK_MAC_TBA), ios(11.3, WK_IOS_TBA));
 - (void)_updateWebpagePreferences:(WKWebpagePreferences *)webpagePreferences WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (void)_notifyUserScripts WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+@property (nonatomic, readonly) BOOL _deferrableUserScriptsNeedNotification WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 
 - (void)_evaluateJavaScriptWithoutUserGesture:(NSString *)_javascript_String completionHandler:(void (^)(id, NSError *))completionHandler WK_API_AVAILABLE(macos(10.13), ios(11.0));
 - (void)_evaluateJavaScript:(NSString *)_javascript_String inFrame:(WKFrameInfo *)frame inContentWorld:(WKContentWorld *)contentWorld completionHandler:(void (^)(id, NSError * error))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm (259522 => 259523)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm	2020-04-04 00:44:31 UTC (rev 259523)
@@ -44,7 +44,7 @@
     // FIXME: In the API test, we can use generateUniqueURL below before the API::Object constructor has done this... where should this really be?
     WebKit::InitializeWebKit2();
 
-    API::Object::constructInWrapper<API::UserStyleSheet>(self, WebCore::UserStyleSheet { WTF::String(source), API::UserStyleSheet::generateUniqueURL(), { }, { }, forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames, WebCore::UserStyleUserLevel }, API::ContentWorld::pageContentWorld());
+    API::Object::constructInWrapper<API::UserStyleSheet>(self, WebCore::UserStyleSheet { WTF::String(source), API::UserStyleSheet::generateUniqueURL(), { }, { }, forMainFrameOnly ? WebCore::UserContentInjectedFrames::InjectInTopFrameOnly : WebCore::UserContentInjectedFrames::InjectInAllFrames, WebCore::UserStyleUserLevel }, API::ContentWorld::pageContentWorld());
 
     return self;
 }
@@ -58,7 +58,7 @@
     // FIXME: In the API test, we can use generateUniqueURL below before the API::Object constructor has done this... where should this really be?
     WebKit::InitializeWebKit2();
 
-    API::Object::constructInWrapper<API::UserStyleSheet>(self, WebCore::UserStyleSheet { WTF::String(source), API::UserStyleSheet::generateUniqueURL(), { },  { }, forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames, WebCore::UserStyleUserLevel, [webView _page]->webPageID() }, *userContentWorld->_contentWorld->_contentWorld);
+    API::Object::constructInWrapper<API::UserStyleSheet>(self, WebCore::UserStyleSheet { WTF::String(source), API::UserStyleSheet::generateUniqueURL(), { },  { }, forMainFrameOnly ? WebCore::UserContentInjectedFrames::InjectInTopFrameOnly : WebCore::UserContentInjectedFrames::InjectInAllFrames, WebCore::UserStyleUserLevel, [webView _page]->webPageID() }, *userContentWorld->_contentWorld->_contentWorld);
 
     return self;
 }
@@ -71,7 +71,7 @@
     // FIXME: In the API test, we can use generateUniqueURL below before the API::Object constructor has done this... where should this really be?
     WebKit::InitializeWebKit2();
 
-    API::Object::constructInWrapper<API::UserStyleSheet>(self, WebCore::UserStyleSheet { WTF::String(source), API::UserStyleSheet::generateUniqueURL(), API::toStringVector(legacyWhitelist), API::toStringVector(legacyBlacklist), forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames, WebCore::UserStyleUserLevel }, *userContentWorld->_contentWorld->_contentWorld);
+    API::Object::constructInWrapper<API::UserStyleSheet>(self, WebCore::UserStyleSheet { WTF::String(source), API::UserStyleSheet::generateUniqueURL(), API::toStringVector(legacyWhitelist), API::toStringVector(legacyBlacklist), forMainFrameOnly ? WebCore::UserContentInjectedFrames::InjectInTopFrameOnly : WebCore::UserContentInjectedFrames::InjectInAllFrames, WebCore::UserStyleUserLevel }, *userContentWorld->_contentWorld->_contentWorld);
 
     return self;
 }
@@ -84,7 +84,7 @@
     // FIXME: In the API test, we can use generateUniqueURL below before the API::Object constructor has done this... where should this really be?
     WebKit::InitializeWebKit2();
 
-    API::Object::constructInWrapper<API::UserStyleSheet>(self, WebCore::UserStyleSheet { WTF::String(source), {  URL(), WTF::String([baseURL _web_originalDataAsWTFString]) }, API::toStringVector(legacyWhitelist), API::toStringVector(legacyBlacklist), forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames, WebCore::UserStyleUserLevel }, *userContentWorld->_contentWorld->_contentWorld);
+    API::Object::constructInWrapper<API::UserStyleSheet>(self, WebCore::UserStyleSheet { WTF::String(source), {  URL(), WTF::String([baseURL _web_originalDataAsWTFString]) }, API::toStringVector(legacyWhitelist), API::toStringVector(legacyBlacklist), forMainFrameOnly ? WebCore::UserContentInjectedFrames::InjectInTopFrameOnly : WebCore::UserContentInjectedFrames::InjectInAllFrames, WebCore::UserStyleUserLevel }, *userContentWorld->_contentWorld->_contentWorld);
 
     return self;
 }
@@ -109,7 +109,7 @@
 
 - (BOOL)isForMainFrameOnly
 {
-    return _userStyleSheet->userStyleSheet().injectedFrames() == WebCore::InjectInTopFrameOnly;
+    return _userStyleSheet->userStyleSheet().injectedFrames() == WebCore::UserContentInjectedFrames::InjectInTopFrameOnly;
 }
 
 - (id)copyWithZone:(NSZone *)zone

Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitUserContent.cpp (259522 => 259523)


--- trunk/Source/WebKit/UIProcess/API/glib/WebKitUserContent.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitUserContent.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -50,12 +50,12 @@
 {
     switch (injectedFrames) {
     case WEBKIT_USER_CONTENT_INJECT_TOP_FRAME:
-        return InjectInTopFrameOnly;
+        return UserContentInjectedFrames::InjectInTopFrameOnly;
     case WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES:
-        return InjectInAllFrames;
+        return UserContentInjectedFrames::InjectInAllFrames;
     default:
         ASSERT_NOT_REACHED();
-        return InjectInAllFrames;
+        return UserContentInjectedFrames::InjectInAllFrames;
     }
 }
 
@@ -76,12 +76,12 @@
 {
     switch (injectionTime) {
     case WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START:
-        return InjectAtDocumentStart;
+        return UserScriptInjectionTime::DocumentStart;
     case WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END:
-        return InjectAtDocumentEnd;
+        return UserScriptInjectionTime::DocumentEnd;
     default:
         ASSERT_NOT_REACHED();
-        return InjectAtDocumentStart;
+        return UserScriptInjectionTime::DocumentStart;
     }
 }
 
@@ -214,7 +214,7 @@
             String::fromUTF8(source), URL { },
             toStringVector(whitelist), toStringVector(blacklist),
             toUserScriptInjectionTime(injectionTime),
-            toUserContentInjectedFrames(injectedFrames) }, world)))
+            toUserContentInjectedFrames(injectedFrames), WebCore::WaitForNotificationBeforeInjecting::No }, world)))
         , referenceCount(1)
     {
     }

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (259522 => 259523)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -7768,6 +7768,7 @@
 
     parameters.overriddenMediaType = m_overriddenMediaType;
     parameters.corsDisablingPatterns = m_configuration->corsDisablingPatterns();
+    parameters.userScriptsShouldWaitUntilNotification = m_configuration->userScriptsShouldWaitUntilNotification();
     parameters.loadsFromNetwork = m_configuration->loadsFromNetwork();
     parameters.loadsSubresources = m_configuration->loadsSubresources();
     parameters.crossOriginAccessControlCheckEnabled = m_configuration->crossOriginAccessControlCheckEnabled();
@@ -8191,6 +8192,19 @@
     send(Messages::WebPage::UpdateWebsitePolicies(websitePolicies));
 }
 
+void WebPageProxy::notifyUserScripts()
+{
+    m_userScriptsNotified = true;
+    send(Messages::WebPage::NotifyUserScripts());
+}
+
+bool WebPageProxy::userScriptsNeedNotification() const
+{
+    if (!m_configuration->userScriptsShouldWaitUntilNotification())
+        return false;
+    return !m_userScriptsNotified;
+}
+
 void WebPageProxy::didFinishLoadingDataForCustomContentProvider(const String& suggestedFilename, const IPC::DataReference& dataReference)
 {
     pageClient().didFinishLoadingDataForCustomContentProvider(ResourceResponseBase::sanitizeSuggestedFilename(suggestedFilename), dataReference);

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (259522 => 259523)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2020-04-04 00:44:31 UTC (rev 259523)
@@ -611,6 +611,8 @@
     bool willHandleHorizontalScrollEvents() const;
 
     void updateWebsitePolicies(WebsitePoliciesData&&);
+    void notifyUserScripts();
+    bool userScriptsNeedNotification() const;
 
     bool canShowMIMEType(const String& mimeType);
 
@@ -2772,6 +2774,7 @@
     NavigatingToAppBoundDomain m_isNavigatingToAppBoundDomain { NavigatingToAppBoundDomain::No };
     NavigatedAwayFromAppBoundDomain m_hasNavigatedAwayFromAppBoundDomain { NavigatedAwayFromAppBoundDomain::No };
     bool m_ignoresAppBoundDomains { false };
+    bool m_userScriptsNotified { false };
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/WebProcess/UserContent/WebUserContentController.cpp (259522 => 259523)


--- trunk/Source/WebKit/WebProcess/UserContent/WebUserContentController.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/WebProcess/UserContent/WebUserContentController.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -392,7 +392,7 @@
                 return;
 
             auto& mainFrame = page.mainFrame();
-            if (userScript.injectedFrames() == InjectInTopFrameOnly) {
+            if (userScript.injectedFrames() == UserContentInjectedFrames::InjectInTopFrameOnly) {
                 mainFrame.injectUserScriptImmediately(world.coreWorld(), userScript);
                 return;
             }

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (259522 => 259523)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -529,6 +529,7 @@
 #endif
 
     pageConfiguration.corsDisablingPatterns = WTFMove(parameters.corsDisablingPatterns);
+    pageConfiguration.userScriptsShouldWaitUntilNotification = parameters.userScriptsShouldWaitUntilNotification;
     pageConfiguration.loadsSubresources = parameters.loadsSubresources;
     pageConfiguration.loadsFromNetwork = parameters.loadsFromNetwork;
 
@@ -6284,6 +6285,14 @@
 #endif
 }
 
+void WebPage::notifyUserScripts()
+{
+    if (!m_page)
+        return;
+
+    m_page->notifyToInjectUserScripts();
+}
+
 unsigned WebPage::extendIncrementalRenderingSuppression()
 {
     unsigned token = m_maximumRenderingSuppressionToken + 1;
@@ -6436,7 +6445,7 @@
 
 void WebPage::addUserScript(String&& source, InjectedBundleScriptWorld& world, WebCore::UserContentInjectedFrames injectedFrames, WebCore::UserScriptInjectionTime injectionTime)
 {
-    WebCore::UserScript userScript { WTFMove(source), URL(aboutBlankURL()), Vector<String>(), Vector<String>(), injectionTime, injectedFrames };
+    WebCore::UserScript userScript { WTFMove(source), URL(aboutBlankURL()), Vector<String>(), Vector<String>(), injectionTime, injectedFrames, WebCore::WaitForNotificationBeforeInjecting::No };
 
     m_userContentController->addUserScript(world, WTFMove(userScript));
 }

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (259522 => 259523)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2020-04-04 00:44:31 UTC (rev 259523)
@@ -1615,6 +1615,7 @@
     void reportUsedFeatures();
 
     void updateWebsitePolicies(WebsitePoliciesData&&);
+    void notifyUserScripts();
 
     void changeFont(WebCore::FontChanges&&);
     void changeFontAttributes(WebCore::FontAttributeChanges&&);

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (259522 => 259523)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2020-04-04 00:44:31 UTC (rev 259523)
@@ -186,6 +186,7 @@
     DidRemoveBackForwardItem(struct WebCore::BackForwardItemIdentifier backForwardItemID)
 
     UpdateWebsitePolicies(struct WebKit::WebsitePoliciesData websitePolicies)
+    NotifyUserScripts()
     DidReceivePolicyDecision(WebCore::FrameIdentifier frameID, uint64_t listenerID, struct WebKit::PolicyDecision policyDecision)
 
     ContinueWillSubmitForm(WebCore::FrameIdentifier frameID, uint64_t listenerID)

Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (259522 => 259523)


--- trunk/Source/WebKitLegacy/mac/ChangeLog	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog	2020-04-04 00:44:31 UTC (rev 259523)
@@ -1,3 +1,14 @@
+2020-04-03  Alex Christensen  <[email protected]>
+
+        Add SPI to make WKUserScripts wait for a notification
+        https://bugs.webkit.org/show_bug.cgi?id=209845
+        <rdar://problem/60342299>
+
+        Reviewed by Chris Dumez.
+
+        * WebView/WebView.mm:
+        (-[WebView _injectOutlookQuirksScript]):
+
 2020-04-03  Tim Horton  <[email protected]>
 
         Add a visual debug indicator for locating and identifying all kinds of WebViews

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebView.mm (259522 => 259523)


--- trunk/Source/WebKitLegacy/mac/WebView/WebView.mm	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebView.mm	2020-04-04 00:44:31 UTC (rev 259523)
@@ -1228,7 +1228,7 @@
 -(void)_injectOutlookQuirksScript
 {
     static NSString *outlookQuirksScriptContents = leakOutlookQuirksUserScriptContents();
-    _private->group->userContentController().addUserScript(*core([WebScriptWorld world]), makeUnique<WebCore::UserScript>(outlookQuirksScriptContents, URL(), Vector<String>(), Vector<String>(), WebCore::InjectAtDocumentEnd, WebCore::InjectInAllFrames));
+    _private->group->userContentController().addUserScript(*core([WebScriptWorld world]), makeUnique<WebCore::UserScript>(outlookQuirksScriptContents, URL(), Vector<String>(), Vector<String>(), WebCore::UserScriptInjectionTime::DocumentEnd, WebCore::UserContentInjectedFrames::InjectInAllFrames, WebCore::WaitForNotificationBeforeInjecting::No));
 
 }
 #endif
@@ -4681,7 +4681,7 @@
     if (!world)
         return;
 
-    auto userScript = makeUnique<WebCore::UserScript>(source, url, toStringVector(whitelist), toStringVector(blacklist), injectionTime == WebInjectAtDocumentStart ? WebCore::InjectAtDocumentStart : WebCore::InjectAtDocumentEnd, injectedFrames == WebInjectInAllFrames ? WebCore::InjectInAllFrames : WebCore::InjectInTopFrameOnly);
+    auto userScript = makeUnique<WebCore::UserScript>(source, url, toStringVector(whitelist), toStringVector(blacklist), injectionTime == WebInjectAtDocumentStart ? WebCore::UserScriptInjectionTime::DocumentStart : WebCore::UserScriptInjectionTime::DocumentEnd, injectedFrames == WebInjectInAllFrames ? WebCore::UserContentInjectedFrames::InjectInAllFrames : WebCore::UserContentInjectedFrames::InjectInTopFrameOnly, WebCore::WaitForNotificationBeforeInjecting::No);
     viewGroup->userContentController().addUserScript(*core(world), WTFMove(userScript));
 }
 
@@ -4704,7 +4704,7 @@
     if (!world)
         return;
 
-    auto styleSheet = makeUnique<WebCore::UserStyleSheet>(source, url, toStringVector(whitelist), toStringVector(blacklist), injectedFrames == WebInjectInAllFrames ? WebCore::InjectInAllFrames : WebCore::InjectInTopFrameOnly, WebCore::UserStyleUserLevel);
+    auto styleSheet = makeUnique<WebCore::UserStyleSheet>(source, url, toStringVector(whitelist), toStringVector(blacklist), injectedFrames == WebInjectInAllFrames ? WebCore::UserContentInjectedFrames::InjectInAllFrames : WebCore::UserContentInjectedFrames::InjectInTopFrameOnly, WebCore::UserStyleUserLevel);
     viewGroup->userContentController().addUserStyleSheet(*core(world), WTFMove(styleSheet), WebCore::InjectInExistingDocuments);
 }
 

Modified: trunk/Source/WebKitLegacy/win/ChangeLog (259522 => 259523)


--- trunk/Source/WebKitLegacy/win/ChangeLog	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKitLegacy/win/ChangeLog	2020-04-04 00:44:31 UTC (rev 259523)
@@ -1,3 +1,15 @@
+2020-04-03  Alex Christensen  <[email protected]>
+
+        Add SPI to make WKUserScripts wait for a notification
+        https://bugs.webkit.org/show_bug.cgi?id=209845
+        <rdar://problem/60342299>
+
+        Reviewed by Chris Dumez.
+
+        * WebView.cpp:
+        (WebView::addUserScriptToGroup):
+        (WebView::addUserStyleSheetToGroup):
+
 2020-04-01  Darin Adler  <[email protected]>
 
         Remove all uses of live ranges from TextIterator

Modified: trunk/Source/WebKitLegacy/win/WebView.cpp (259522 => 259523)


--- trunk/Source/WebKitLegacy/win/WebView.cpp	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Source/WebKitLegacy/win/WebView.cpp	2020-04-04 00:44:31 UTC (rev 259523)
@@ -7006,8 +7006,8 @@
 
     WebScriptWorld* world = reinterpret_cast<WebScriptWorld*>(iWorld);
     auto userScript = makeUnique<UserScript>(source, toURL(url), toStringVector(whitelist, whitelistCount),
-        toStringVector(blacklist, blacklistCount), injectionTime == WebInjectAtDocumentStart ? InjectAtDocumentStart : InjectAtDocumentEnd,
-        injectedFrames == WebInjectInAllFrames ? InjectInAllFrames : InjectInTopFrameOnly);
+        toStringVector(blacklist, blacklistCount), injectionTime == WebInjectAtDocumentStart ? UserScriptInjectionTime::DocumentStart : UserScriptInjectionTime::DocumentEnd,
+        injectedFrames == WebInjectInAllFrames ? UserContentInjectedFrames::InjectInAllFrames : UserContentInjectedFrames::InjectInTopFrameOnly, WaitForNotificationBeforeInjecting::No);
     viewGroup->userContentController().addUserScript(world->world(), WTFMove(userScript));
     return S_OK;
 }
@@ -7033,7 +7033,7 @@
 
     WebScriptWorld* world = reinterpret_cast<WebScriptWorld*>(iWorld);
     auto styleSheet = makeUnique<UserStyleSheet>(source, toURL(url), toStringVector(whitelist, whitelistCount), toStringVector(blacklist, blacklistCount),
-        injectedFrames == WebInjectInAllFrames ? InjectInAllFrames : InjectInTopFrameOnly, UserStyleUserLevel);
+        injectedFrames == WebInjectInAllFrames ? UserContentInjectedFrames::InjectInAllFrames : UserContentInjectedFrames::InjectInTopFrameOnly, UserStyleUserLevel);
     viewGroup->userContentController().addUserStyleSheet(world->world(), WTFMove(styleSheet), InjectInExistingDocuments);
     return S_OK;
 }

Modified: trunk/Tools/ChangeLog (259522 => 259523)


--- trunk/Tools/ChangeLog	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Tools/ChangeLog	2020-04-04 00:44:31 UTC (rev 259523)
@@ -1,3 +1,14 @@
+2020-04-03  Alex Christensen  <[email protected]>
+
+        Add SPI to make WKUserScripts wait for a notification
+        https://bugs.webkit.org/show_bug.cgi?id=209845
+        <rdar://problem/60342299>
+
+        Reviewed by Chris Dumez.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/UserContentController.mm:
+        (TEST):
+
 2020-04-03  Kate Cheney  <[email protected]>
 
         Prevent non app-bound domain cookies from being read or set using API calls

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/UserContentController.mm (259522 => 259523)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/UserContentController.mm	2020-04-04 00:16:04 UTC (rev 259522)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/UserContentController.mm	2020-04-04 00:44:31 UTC (rev 259523)
@@ -28,10 +28,13 @@
 #import "PlatformUtilities.h"
 #import "Test.h"
 #import "TestNavigationDelegate.h"
+#import "TestUIDelegate.h"
+#import "TestWKWebView.h"
 #import <WebKit/WKProcessPoolPrivate.h>
 #import <WebKit/WKUserContentControllerPrivate.h>
 #import <WebKit/WKUserScript.h>
 #import <WebKit/WKUserScriptPrivate.h>
+#import <WebKit/WKWebViewConfigurationPrivate.h>
 #import <WebKit/WebKit.h>
 #import <WebKit/_WKProcessPoolConfiguration.h>
 #import <WebKit/_WKUserContentWorld.h>
@@ -811,3 +814,33 @@
     waitForMessages(6);
     compareMessages({"start all", "start all", "end main", "start all", "end main", "start all"});
 }
+
+TEST(WKUserContentController, UserScriptNotification)
+{
+    WKUserScript *waitsForNotification = [[[WKUserScript alloc] _initWithSource:@"alert('waited for notification')" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES legacyWhitelist:[NSArray array] legacyBlacklist:[NSArray array] associatedURL:[NSURL URLWithString:@"test:///script"] contentWorld:[WKContentWorld defaultClientWorld] deferRunningUntilNotification:YES] autorelease];
+    WKUserScript *documentEnd = [[[WKUserScript alloc] initWithSource:@"alert('document parsing ended')" injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES] autorelease];
+
+    TestWKWebView *webView1 = [[TestWKWebView new] autorelease];
+    EXPECT_TRUE(webView1._deferrableUserScriptsNeedNotification);
+    [webView1.configuration.userContentController addUserScript:waitsForNotification];
+    [webView1.configuration.userContentController addUserScript:documentEnd];
+    TestUIDelegate *delegate = [[TestUIDelegate new] autorelease];
+    webView1.UIDelegate = delegate;
+    [webView1 loadTestPageNamed:@"simple"];
+    EXPECT_WK_STREQ([delegate waitForAlert], "document parsing ended");
+    [webView1 _notifyUserScripts];
+    EXPECT_FALSE(webView1._deferrableUserScriptsNeedNotification);
+    EXPECT_WK_STREQ([delegate waitForAlert], "waited for notification");
+
+    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration new] autorelease];
+    EXPECT_TRUE(configuration._deferrableUserScriptsShouldWaitUntilNotification);
+    configuration._deferrableUserScriptsShouldWaitUntilNotification = NO;
+    TestWKWebView *webView2 = [[[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration] autorelease];
+    EXPECT_FALSE(webView2._deferrableUserScriptsNeedNotification);
+    [webView2.configuration.userContentController addUserScript:waitsForNotification];
+    [webView2.configuration.userContentController addUserScript:documentEnd];
+    webView2.UIDelegate = delegate;
+    [webView2 loadTestPageNamed:@"simple"];
+    EXPECT_WK_STREQ([delegate waitForAlert], "waited for notification");
+    EXPECT_WK_STREQ([delegate waitForAlert], "document parsing ended");
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to