Title: [211758] trunk
Revision
211758
Author
[email protected]
Date
2017-02-06 16:25:00 -0800 (Mon, 06 Feb 2017)

Log Message

Allow some schemes to opt-out of CORS
https://bugs.webkit.org/show_bug.cgi?id=167795

Patch by Youenn Fablet <[email protected]> on 2017-02-06
Reviewed by Alex Christensen.

Source/WebCore:

Test: http/tests/security/bypassing-cors-checks-for-extension-urls.html

Adding the possibility to opt out of CORS for DocumentThreadableLoader clients (fetch and XHR).
This is made specific to the case of user extension URLs for pages running user scripts.
Introducing a boolean flag in Page for that purpose.
Introducing a helper routine in SchemeRegistry to centralize the various user script extension schemes.

* loader/DocumentThreadableLoader.cpp:
(WebCore::DocumentThreadableLoader::DocumentThreadableLoader):
* page/Frame.cpp:
(WebCore::Frame::injectUserScripts):
* page/Page.h:
(WebCore::Page::setAsRunningUserScripts):
(WebCore::Page::isRunningUserScripts):
* platform/SchemeRegistry.cpp:
(WebCore::SchemeRegistry::isUserExtensionScheme):
* platform/SchemeRegistry.h:
* testing/Internals.cpp:
(WebCore::Internals::setAsRunningUserScripts):
* testing/Internals.h:
* testing/Internals.idl:

LayoutTests:

* http/tests/security/bypassing-cors-checks-for-extension-urls-expected.txt: Added.
* http/tests/security/bypassing-cors-checks-for-extension-urls.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (211757 => 211758)


--- trunk/LayoutTests/ChangeLog	2017-02-06 23:56:09 UTC (rev 211757)
+++ trunk/LayoutTests/ChangeLog	2017-02-07 00:25:00 UTC (rev 211758)
@@ -1,3 +1,13 @@
+2017-02-06  Youenn Fablet  <[email protected]>
+
+        Allow some schemes to opt-out of CORS
+        https://bugs.webkit.org/show_bug.cgi?id=167795
+
+        Reviewed by Alex Christensen.
+
+        * http/tests/security/bypassing-cors-checks-for-extension-urls-expected.txt: Added.
+        * http/tests/security/bypassing-cors-checks-for-extension-urls.html: Added.
+
 2017-02-06  Chris Dumez  <[email protected]>
 
         Align [[OwnPropertyKeys]] with the HTML specification for cross-origin Window / Location objects

Added: trunk/LayoutTests/http/tests/security/bypassing-cors-checks-for-extension-urls-expected.txt (0 => 211758)


--- trunk/LayoutTests/http/tests/security/bypassing-cors-checks-for-extension-urls-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/bypassing-cors-checks-for-extension-urls-expected.txt	2017-02-07 00:25:00 UTC (rev 211758)
@@ -0,0 +1,8 @@
+CONSOLE MESSAGE: line 19: XMLHttpRequest cannot load safari-extension://test1. Cross origin requests are only supported for HTTP.
+This test ensures that XHR/Fetch will bypass CORS for user extension URLS in case the page is running user scripts.
+
+
+PASS Bypassing CORS on synchronous XHR - should trigger a CORS error message 
+PASS Bypassing CORS on synchronous XHR - should not trigger a CORS error message 
+PASS Bypassing CORS on asynchronous fetch - should not trigger a CORS error message 
+

Added: trunk/LayoutTests/http/tests/security/bypassing-cors-checks-for-extension-urls.html (0 => 211758)


--- trunk/LayoutTests/http/tests/security/bypassing-cors-checks-for-extension-urls.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/bypassing-cors-checks-for-extension-urls.html	2017-02-07 00:25:00 UTC (rev 211758)
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+</head>
+<body>
+<p>
+    This test ensures that XHR/Fetch will bypass CORS for user extension URLS in case the page is running user scripts.
+</p>
+<script>
+    if (!window.internals)
+        alert("This test requires WebKit internals API to work properly");
+
+    test(() => {
+        xhr = new XMLHttpRequest();
+        xhr.open("GET", "safari-extension://test1", false);
+        assert_throws({name: "NetworkError"}, () => { xhr.send() });
+    }, "Bypassing CORS on synchronous XHR - should trigger a CORS error message");
+
+    test(() => {
+        internals.setAsRunningUserScripts();
+
+        xhr = new XMLHttpRequest();
+        xhr.open("GET", "safari-extension://test3", false);
+        assert_throws({name: "NetworkError"}, () => { xhr.send() });
+    }, "Bypassing CORS on synchronous XHR - should not trigger a CORS error message");
+
+    promise_test((test) => {
+        return promise_rejects(test, new TypeError, fetch("safari-extension://test4"));
+    }, "Bypassing CORS on asynchronous fetch - should not trigger a CORS error message");
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (211757 => 211758)


--- trunk/Source/WebCore/ChangeLog	2017-02-06 23:56:09 UTC (rev 211757)
+++ trunk/Source/WebCore/ChangeLog	2017-02-07 00:25:00 UTC (rev 211758)
@@ -1,3 +1,32 @@
+2017-02-06  Youenn Fablet  <[email protected]>
+
+        Allow some schemes to opt-out of CORS
+        https://bugs.webkit.org/show_bug.cgi?id=167795
+
+        Reviewed by Alex Christensen.
+
+        Test: http/tests/security/bypassing-cors-checks-for-extension-urls.html
+
+        Adding the possibility to opt out of CORS for DocumentThreadableLoader clients (fetch and XHR).
+        This is made specific to the case of user extension URLs for pages running user scripts.
+        Introducing a boolean flag in Page for that purpose.
+        Introducing a helper routine in SchemeRegistry to centralize the various user script extension schemes.
+
+        * loader/DocumentThreadableLoader.cpp:
+        (WebCore::DocumentThreadableLoader::DocumentThreadableLoader):
+        * page/Frame.cpp:
+        (WebCore::Frame::injectUserScripts):
+        * page/Page.h:
+        (WebCore::Page::setAsRunningUserScripts):
+        (WebCore::Page::isRunningUserScripts):
+        * platform/SchemeRegistry.cpp:
+        (WebCore::SchemeRegistry::isUserExtensionScheme):
+        * platform/SchemeRegistry.h:
+        * testing/Internals.cpp:
+        (WebCore::Internals::setAsRunningUserScripts):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 2017-02-06  Chris Dumez  <[email protected]>
 
         Align [[OwnPropertyKeys]] with the HTML specification for cross-origin Window / Location objects

Modified: trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp (211757 => 211758)


--- trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp	2017-02-06 23:56:09 UTC (rev 211757)
+++ trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp	2017-02-07 00:25:00 UTC (rev 211758)
@@ -110,6 +110,11 @@
     if (m_async && m_options.mode == FetchOptions::Mode::Cors)
         m_originalHeaders = request.httpHeaderFields();
 
+    if (document.page() && document.page()->isRunningUserScripts() && SchemeRegistry::isUserExtensionScheme(request.url().protocol().toStringWithoutCopying())) {
+        m_options.mode = FetchOptions::Mode::NoCors;
+        m_options.filteringPolicy = ResponseFilteringPolicy::Disable;
+    }
+
     // As per step 11 of https://fetch.spec.whatwg.org/#main-fetch, data scheme (if same-origin data-URL flag is set) and about scheme are considered same-origin.
     if (request.url().protocolIsData())
         m_sameOriginRequest = options.sameOriginDataURLFlag == SameOriginDataURLFlag::Set;

Modified: trunk/Source/WebCore/page/Frame.cpp (211757 => 211758)


--- trunk/Source/WebCore/page/Frame.cpp	2017-02-06 23:56:09 UTC (rev 211757)
+++ trunk/Source/WebCore/page/Frame.cpp	2017-02-07 00:25:00 UTC (rev 211758)
@@ -710,8 +710,10 @@
         if (script.injectedFrames() == InjectInTopFrameOnly && ownerElement())
             return;
 
-        if (script.injectionTime() == injectionTime && UserContentURLPattern::matchesPatterns(document->url(), script.whitelist(), script.blacklist()))
+        if (script.injectionTime() == injectionTime && UserContentURLPattern::matchesPatterns(document->url(), script.whitelist(), script.blacklist())) {
+            m_page->setAsRunningUserScripts();
             m_script->evaluateInWorld(ScriptSourceCode(script.source(), script.url()), world);
+        }
     });
 }
 

Modified: trunk/Source/WebCore/page/Page.h (211757 => 211758)


--- trunk/Source/WebCore/page/Page.h	2017-02-06 23:56:09 UTC (rev 211757)
+++ trunk/Source/WebCore/page/Page.h	2017-02-07 00:25:00 UTC (rev 211758)
@@ -391,6 +391,9 @@
     void setResourceUsageOverlayVisible(bool);
 #endif
 
+    void setAsRunningUserScripts() { m_isRunningUserScripts = true; }
+    bool isRunningUserScripts() const { return m_isRunningUserScripts; }
+
     void setDebugger(JSC::Debugger*);
     JSC::Debugger* debugger() const { return m_debugger; }
 
@@ -775,6 +778,8 @@
     std::optional<EventThrottlingBehavior> m_eventThrottlingBehaviorOverride;
 
     std::unique_ptr<PerformanceMonitor> m_performanceMonitor;
+
+    bool m_isRunningUserScripts { false };
 };
 
 inline PageGroup& Page::group()

Modified: trunk/Source/WebCore/platform/SchemeRegistry.cpp (211757 => 211758)


--- trunk/Source/WebCore/platform/SchemeRegistry.cpp	2017-02-06 23:56:09 UTC (rev 211757)
+++ trunk/Source/WebCore/platform/SchemeRegistry.cpp	2017-02-07 00:25:00 UTC (rev 211758)
@@ -357,4 +357,14 @@
 }
 #endif
 
+bool SchemeRegistry::isUserExtensionScheme(const String& scheme)
+{
+    UNUSED_PARAM(scheme);
+#if PLATFORM(MAC)
+    if (scheme == "safari-extension")
+        return true;
+#endif
+    return false;
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/SchemeRegistry.h (211757 => 211758)


--- trunk/Source/WebCore/platform/SchemeRegistry.h	2017-02-06 23:56:09 UTC (rev 211757)
+++ trunk/Source/WebCore/platform/SchemeRegistry.h	2017-02-07 00:25:00 UTC (rev 211758)
@@ -99,6 +99,8 @@
     WEBCORE_EXPORT static void registerURLSchemeAsCachePartitioned(const String& scheme);
     static bool shouldPartitionCacheForURLScheme(const String& scheme);
 #endif
+
+    static bool isUserExtensionScheme(const String& scheme);
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/testing/Internals.cpp (211757 => 211758)


--- trunk/Source/WebCore/testing/Internals.cpp	2017-02-06 23:56:09 UTC (rev 211757)
+++ trunk/Source/WebCore/testing/Internals.cpp	2017-02-07 00:25:00 UTC (rev 211758)
@@ -3690,4 +3690,10 @@
 }
 #endif
 
+void Internals::setAsRunningUserScripts(Document& document)
+{
+    if (document.page())
+        document.page()->setAsRunningUserScripts();
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/testing/Internals.h (211757 => 211758)


--- trunk/Source/WebCore/testing/Internals.h	2017-02-06 23:56:09 UTC (rev 211757)
+++ trunk/Source/WebCore/testing/Internals.h	2017-02-07 00:25:00 UTC (rev 211758)
@@ -526,6 +526,8 @@
     void setQuickLookPassword(const String&);
 #endif
 
+    void setAsRunningUserScripts(Document&);
+
 private:
     explicit Internals(Document&);
     Document* contextDocument() const;

Modified: trunk/Source/WebCore/testing/Internals.idl (211757 => 211758)


--- trunk/Source/WebCore/testing/Internals.idl	2017-02-06 23:56:09 UTC (rev 211757)
+++ trunk/Source/WebCore/testing/Internals.idl	2017-02-07 00:25:00 UTC (rev 211758)
@@ -499,4 +499,6 @@
 #if defined(WTF_PLATFORM_IOS) && WTF_PLATFORM_IOS
     void setQuickLookPassword(DOMString password);
 #endif
+
+    [CallWith=Document] void setAsRunningUserScripts();
 };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to