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();
};