WebKit Bugzilla
Attachment 356196 Details for
Bug 192193
: Add initial support for 'Cross-Origin-Opener-Policy' HTTP header
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-192193-20181130104122.patch (text/plain), 71.02 KB, created by
Chris Dumez
on 2018-11-30 10:41:22 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Chris Dumez
Created:
2018-11-30 10:41:22 PST
Size:
71.02 KB
patch
obsolete
>Subversion Revision: 238614 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 1f37acd62c1fde9ae11b177c7ec60412bd3c4de9..fecb58e9880e346053ffa82f7819d531623ccbf8 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,116 @@ >+2018-11-29 Chris Dumez <cdumez@apple.com> >+ >+ Add initial support for 'Cross-Origin-Opener-Policy' HTTP header >+ https://bugs.webkit.org/show_bug.cgi?id=192193 >+ <rdar://problem/42013525> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add initial support for 'Cross-Origin-Opener-Policy' HTTP header as discussed in: >+ - https://github.com/whatwg/html/issues/3740 >+ >+ Supported syntax is currently: >+ Cross-Origin-Opener-Policy: [same-origin | same-site] >+ >+ When navigating cross-origin (or cross-site) to a document that serves the >+ 'Cross-Origin-Opener-Policy: same-origin' (or 'same-site') header, we create >+ a new browsing context group to isolate the frame. We do so by: >+ - Disowning our opener >+ - Have our openees disown us >+ - Use a fresh ScriptController / WindowProxy so that existing wrappers keep pointing >+ to the old window. (note that the old window will become frameless once we've created >+ the window for the new document and the old window will look closed/frameless from >+ JS). >+ >+ Note that isolation can also happen for same-site navigations if the source and >+ destination have a different Cross-Origin-Opener-Policy header. >+ >+ In the future, this will allow us to process-swap on such navigation. However, this part >+ is not implemented yet. For now, this does Web isolation but no process isolation. >+ >+ Note that support for an additional 'unsafe-allow-outgoing' flag is being discussed upstream >+ but is not implemented in this patch. >+ >+ The feature is currently behind an experimental feature flag, off by default. >+ >+ Test: http/tests/security/Cross-Origin-Opener-Policy/cross-origin-opener-policy-basic.html >+ >+ * dom/Document.cpp: >+ (WebCore::Document::initSecurityContext): >+ Make sure document inherits crossOriginOpenerPolicy from its opener. >+ >+ (WebCore::Document::crossOriginOpenerPolicy const): >+ (WebCore::Document::setCrossOriginOpenerPolicy): >+ * dom/Document.h: >+ Save crossOriginOpenerPolicy on the document. This is needed to check for policy mismatch >+ between source and destination when navigating. >+ >+ * loader/CrossOriginAccessControl.cpp: >+ (WebCore::isSameSiteURL): >+ (WebCore::shouldCrossOriginResourcePolicyCancelLoad): >+ * loader/CrossOriginAccessControl.h: >+ Move same site check logic out of shouldCrossOriginResourcePolicyCancelLoad() and into >+ isSameSiteURL() so that it can be reused. >+ >+ * loader/DocumentLoader.cpp: >+ (WebCore::DocumentLoader::responseReceived): >+ When we receive the NetworkResponse, check if the Cross-Origin-Opener-Policy header >+ is present and ask the FrameLoader to isolate us if necessary. >+ >+ * loader/PolicyChecker.cpp: >+ (WebCore::PolicyChecker::checkNavigationPolicy): >+ * loader/FrameLoader.cpp: >+ (WebCore::FrameLoader::loadURL): >+ Move the updating of NavigationAction's openedViaWindowOpenWithOpener / HasOpenedFrames >+ flags from FrameLoader::loadURL() to PolicyChecker::checkNavigationPolicy() since >+ NavigationAction objects are created in multiple places and we were failing to set >+ the flags in other places than loadURL(). This bug was found by one of my new API >+ tests. >+ >+ (WebCore::FrameLoader::isolateIfNecessaryDueToCrossOriginOpenerPolicy): >+ (WebCore::FrameLoader::isolateFromOtherBrowsingContexts): >+ Isolate the browsing context if directed by the Cross-Origin-Opener-Policy header by: >+ - Disowning our opener >+ - Have our openees disown us >+ - Use a fresh ScriptController / WindowProxy so that existing wrappers keep pointing >+ to the old window. >+ >+ * loader/FrameLoader.h: >+ (WebCore::FrameLoader::hasOpenedFrames const): >+ Add getter to check if the frame has opened any other frames. >+ >+ * page/DOMWindow.cpp: >+ (WebCore::DOMWindow::createWindow): >+ Pass new boolean to setOpenedViaWindowOpenWithOpener(). >+ >+ * page/AbstractFrame.cpp: >+ (WebCore::AbstractFrame::resetWindowProxy): >+ * page/Frame.cpp: >+ (WebCore::Frame::resetScript): >+ * page/Frame.h: >+ Add resetScript() method to reconstruct the ScriptController / WindowProxy. This makes sure that >+ we get a fresh ScriptController / WindowProxy for the frame when it is navigated and the >+ 'Cross-Origin-Opener-Policy' HTTP header causes isolation. Existing wrappers will keep pointing >+ to the current window, which will become frameless once with create a window for the new >+ document. >+ >+ * page/Page.h: >+ (WebCore::Page::setOpenedViaWindowOpenWithOpener): >+ Have setter take a boolean so that the value can be reset. >+ >+ * page/RuntimeEnabledFeatures.h: >+ (WebCore::RuntimeEnabledFeatures::setCrossOriginOpenerPolicyEnabled): >+ (WebCore::RuntimeEnabledFeatures::crossOriginOpenerPolicyEnabled const): >+ Add RuntimeEnabledFeature for this header, off by default. >+ >+ * platform/network/HTTPHeaderNames.in: >+ Add Cross-Origin-Opener-Policy header. >+ >+ * platform/network/HTTPParsers.cpp: >+ (WebCore::parseCrossOriginOpenerPolicyHeader): >+ * platform/network/HTTPParsers.h: >+ Add utility function for parsing the 'Cross-Origin-Opener-Policy' HTTP header. >+ > 2018-11-28 Zalan Bujtas <zalan@apple.com> > > [LFC][Quirk] Use non-collapsed vertical margin values when the container is stretched to the size of the ICB. >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 80a8fd4e246d464e3eb9ecf3769011d06b67e750..6b6f5746918fc9808567ffadd3f009b0efe95dc1 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,23 @@ >+2018-11-29 Chris Dumez <cdumez@apple.com> >+ >+ Add initial support for 'Cross-Origin-Opener-Policy' HTTP header >+ https://bugs.webkit.org/show_bug.cgi?id=192193 >+ <rdar://problem/42013525> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add private API to turn on the feature. >+ >+ * Shared/WebPreferences.yaml: >+ * UIProcess/API/C/WKPreferences.cpp: >+ (WKPreferencesGetCrossOriginOpenerPolicyEnabled): >+ (WKPreferencesSetCrossOriginOpenerPolicyEnabled): >+ * UIProcess/API/C/WKPreferencesRef.h: >+ * UIProcess/API/Cocoa/WKPreferences.mm: >+ (-[WKPreferences _setCrossOriginOpenerPolicyEnabled:]): >+ (-[WKPreferences _crossOriginOpenerPolicyEnabled]): >+ * UIProcess/API/Cocoa/WKPreferencesPrivate.h: >+ > 2018-11-28 Alexey Proskuryakov <ap@apple.com> > > Modernize version checks for same site cookie support >diff --git a/Source/WebKitLegacy/mac/ChangeLog b/Source/WebKitLegacy/mac/ChangeLog >index bf46902e7cf0e03fb3313360cabc0fa689bf0789..c249f67463478b1864e7cbfbbf80555dd0beb30c 100644 >--- a/Source/WebKitLegacy/mac/ChangeLog >+++ b/Source/WebKitLegacy/mac/ChangeLog >@@ -1,3 +1,22 @@ >+2018-11-29 Chris Dumez <cdumez@apple.com> >+ >+ Add initial support for 'Cross-Origin-Opener-Policy' HTTP header >+ https://bugs.webkit.org/show_bug.cgi?id=192193 >+ <rdar://problem/42013525> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add private SPI to turn on the feature. >+ >+ * WebView/WebPreferenceKeysPrivate.h: >+ * WebView/WebPreferences.mm: >+ (+[WebPreferences initialize]): >+ (-[WebPreferences crossOriginOpenerPolicyEnabled]): >+ (-[WebPreferences setCrossOriginOpenerPolicyEnabled:]): >+ * WebView/WebPreferencesPrivate.h: >+ * WebView/WebView.mm: >+ (-[WebView _preferencesChanged:]): >+ > 2018-11-27 Mark Lam <mark.lam@apple.com> > > ENABLE_FAST_JIT_PERMISSIONS should be false for iosmac. >diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp >index 5c2ff134910960b53920870c68a85d32860183ad..4720249de9d53f2e7761a353c17d92ab261ba4cf 100644 >--- a/Source/WebCore/dom/Document.cpp >+++ b/Source/WebCore/dom/Document.cpp >@@ -532,6 +532,7 @@ Document::Document(Frame* frame, const URL& url, unsigned documentClasses, unsig > , m_didAssociateFormControlsTimer(*this, &Document::didAssociateFormControlsTimerFired) > , m_cookieCacheExpiryTimer(*this, &Document::invalidateDOMCookieCache) > , m_socketProvider(page() ? &page()->socketProvider() : nullptr) >+ , m_crossOriginOpenerPolicy(CrossOriginOpenerPolicy::None) > , m_isSynthesized(constructionFlags & Synthesized) > , m_isNonRenderedPlaceholder(constructionFlags & NonRenderedPlaceholder) > , m_orientationNotifier(currentOrientation(frame)) >@@ -5815,6 +5816,7 @@ void Document::initSecurityContext() > // We alias the SecurityOrigins to match Firefox, see Bug 15313 > // https://bugs.webkit.org/show_bug.cgi?id=15313 > setSecurityOriginPolicy(ownerFrame->document()->securityOriginPolicy()); >+ setCrossOriginOpenerPolicy(ownerFrame->document()->crossOriginOpenerPolicy()); > } > > bool Document::shouldInheritContentSecurityPolicyFromOwner() const >@@ -8478,4 +8480,14 @@ void Document::setPaintWorkletGlobalScope(Ref<PaintWorkletGlobalScope>&& scope) > } > #endif > >+CrossOriginOpenerPolicy Document::crossOriginOpenerPolicy() const >+{ >+ return m_crossOriginOpenerPolicy; >+} >+ >+void Document::setCrossOriginOpenerPolicy(CrossOriginOpenerPolicy policy) >+{ >+ m_crossOriginOpenerPolicy = policy; >+} >+ > } // namespace WebCore >diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h >index 559a5be63af393b25e90fb503549f2819e8a773e..1b5dcb707c620d12498ca0a06178c56c50fa021f 100644 >--- a/Source/WebCore/dom/Document.h >+++ b/Source/WebCore/dom/Document.h >@@ -206,6 +206,7 @@ enum CollectionType; > enum class ShouldOpenExternalURLsPolicy : uint8_t; > > enum class RouteSharingPolicy : uint8_t; >+enum class CrossOriginOpenerPolicy; > > using PlatformDisplayID = uint32_t; > >@@ -1353,6 +1354,9 @@ public: > SecurityOrigin& securityOrigin() const { return *SecurityContext::securityOrigin(); } > SecurityOrigin& topOrigin() const final { return topDocument().securityOrigin(); } > >+ CrossOriginOpenerPolicy crossOriginOpenerPolicy() const; >+ void setCrossOriginOpenerPolicy(CrossOriginOpenerPolicy); >+ > Ref<FontFaceSet> fonts(); > > void ensurePlugInsInjectedScript(DOMWrapperWorld&); >@@ -1958,6 +1962,7 @@ private: > PageCacheState m_pageCacheState { NotInPageCache }; > std::optional<ReferrerPolicy> m_referrerPolicy; > ReadyState m_readyState { Complete }; >+ CrossOriginOpenerPolicy m_crossOriginOpenerPolicy; > > MutationObserverOptions m_mutationObserverTypes { 0 }; > >diff --git a/Source/WebCore/loader/CrossOriginAccessControl.cpp b/Source/WebCore/loader/CrossOriginAccessControl.cpp >index 0d26a1faac183574043faa7b4a9ec6d11180b817..87c26eb52501364aff6f7f3492d8c8f2117e45a0 100644 >--- a/Source/WebCore/loader/CrossOriginAccessControl.cpp >+++ b/Source/WebCore/loader/CrossOriginAccessControl.cpp >@@ -216,6 +216,17 @@ bool validatePreflightResponse(const ResourceRequest& request, const ResourceRes > return true; > } > >+bool isSameSiteURL(const SecurityOrigin& sourceOrigin, const URL& destinationURL) >+{ >+ if (sourceOrigin.isUnique()) >+ return false; >+ if (!registrableDomainsAreEqual(destinationURL, ResourceRequest::partitionName(sourceOrigin.host()))) >+ return false; >+ if (sourceOrigin.protocol() == "http" && destinationURL.protocolIs("https")) >+ return false; >+ return true; >+} >+ > static inline bool shouldCrossOriginResourcePolicyCancelLoad(const SecurityOrigin& origin, const ResourceResponse& response) > { > if (origin.canRequest(response.url())) >@@ -227,13 +238,7 @@ static inline bool shouldCrossOriginResourcePolicyCancelLoad(const SecurityOrigi > return true; > > if (policy == CrossOriginResourcePolicy::SameSite) { >- if (origin.isUnique()) >- return true; >-#if ENABLE(PUBLIC_SUFFIX_LIST) >- if (!registrableDomainsAreEqual(response.url(), ResourceRequest::partitionName(origin.host()))) >- return true; >-#endif >- if (origin.protocol() == "http" && response.url().protocol() == "https") >+ if (!isSameSiteURL(origin, response.url())) > return true; > } > >diff --git a/Source/WebCore/loader/CrossOriginAccessControl.h b/Source/WebCore/loader/CrossOriginAccessControl.h >index d2b09bd5db5676c01abf823d3f0722a770ea540b..949461709d469d832db55deeea0b99d06da366a1 100644 >--- a/Source/WebCore/loader/CrossOriginAccessControl.h >+++ b/Source/WebCore/loader/CrossOriginAccessControl.h >@@ -64,5 +64,6 @@ WEBCORE_EXPORT bool passesAccessControlCheck(const ResourceResponse&, StoredCred > WEBCORE_EXPORT bool validatePreflightResponse(const ResourceRequest&, const ResourceResponse&, StoredCredentialsPolicy, SecurityOrigin&, String& errorDescription); > > WEBCORE_EXPORT std::optional<ResourceError> validateCrossOriginResourcePolicy(const SecurityOrigin&, const URL&, const ResourceResponse&); >+WEBCORE_EXPORT bool isSameSiteURL(const SecurityOrigin& sourceOrigin, const URL& destinationURL); > > } // namespace WebCore >diff --git a/Source/WebCore/loader/DocumentLoader.cpp b/Source/WebCore/loader/DocumentLoader.cpp >index d851af0ee6ce8e2cbb124630efbd6056a02885b8..5b7fc765e80aea0aea7baa0ae0fb1c09925da1d9 100644 >--- a/Source/WebCore/loader/DocumentLoader.cpp >+++ b/Source/WebCore/loader/DocumentLoader.cpp >@@ -788,6 +788,9 @@ void DocumentLoader::responseReceived(const ResourceResponse& response, Completi > } > } > >+ String crossOriginOpenerPolicy = response.httpHeaderFields().get(HTTPHeaderName::CrossOriginOpenerPolicy); >+ frameLoader()->isolateIfNecessaryDueToCrossOriginOpenerPolicy(crossOriginOpenerPolicy, response.url()); >+ > // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred. > // See <rdar://problem/6304600> for more details. > #if !USE(CF) >diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp >index c93cebd1f2c709146825e67899c61fa6703e8547..4039fcbb37b58586e6e0cdb4d64f570b6c11f4cd 100644 >--- a/Source/WebCore/loader/FrameLoader.cpp >+++ b/Source/WebCore/loader/FrameLoader.cpp >@@ -46,6 +46,7 @@ > #include "CommonVM.h" > #include "ContentFilter.h" > #include "ContentSecurityPolicy.h" >+#include "CrossOriginAccessControl.h" > #include "DOMWindow.h" > #include "DatabaseManager.h" > #include "DiagnosticLoggingClient.h" >@@ -102,6 +103,7 @@ > #include "ResourceLoadInfo.h" > #include "ResourceLoadObserver.h" > #include "ResourceRequest.h" >+#include "RuntimeEnabledFeatures.h" > #include "SVGDocument.h" > #include "SVGLocatable.h" > #include "SVGNames.h" >@@ -755,6 +757,10 @@ void FrameLoader::didBeginDocument(bool dispatch) > if (!headerContentLanguage.isEmpty()) > m_frame.document()->setContentLanguage(headerContentLanguage); > } >+ >+ String crossOriginOpenerPolicyString = m_documentLoader->response().httpHeaderField(HTTPHeaderName::CrossOriginOpenerPolicy); >+ if (!crossOriginOpenerPolicyString.isEmpty()) >+ m_frame.document()->setCrossOriginOpenerPolicy(parseCrossOriginOpenerPolicyHeader(crossOriginOpenerPolicyString)); > } > > history().restoreDocumentState(); >@@ -1358,9 +1364,6 @@ void FrameLoader::loadURL(FrameLoadRequest&& frameLoadRequest, const String& ref > return; > > NavigationAction action { frameLoadRequest.requester(), request, frameLoadRequest.initiatedByMainFrame(), newLoadType, isFormSubmission, event, frameLoadRequest.shouldOpenExternalURLsPolicy(), frameLoadRequest.downloadAttribute() }; >- if (m_frame.page() && m_frame.page()->openedViaWindowOpenWithOpener()) >- action.setOpenedViaWindowOpenWithOpener(); >- action.setHasOpenedFrames(!m_openedFrames.isEmpty()); > action.setLockHistory(lockHistory); > action.setLockBackForwardList(frameLoadRequest.lockBackForwardList()); > >@@ -3519,6 +3522,60 @@ bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, con > return false; > } > >+void FrameLoader::isolateIfNecessaryDueToCrossOriginOpenerPolicy(const String& content, const URL& destinationURL) >+{ >+ if (!RuntimeEnabledFeatures::sharedFeatures().crossOriginOpenerPolicyEnabled()) >+ return; >+ >+ if (!m_frame.isMainFrame() || !m_frame.document()) >+ return; >+ >+ auto policy = parseCrossOriginOpenerPolicyHeader(content); >+ >+ // No matter their origins, if the source and the destionation disagree on the cross-origin opener policy, then we isolate the destination. >+ if (policy != m_frame.document()->crossOriginOpenerPolicy()) { >+ RELEASE_LOG_IF_ALLOWED("isolateIfNecessaryDueToCrossOriginOpenerPolicy: isolating browsing context from any opener / openees due to Cross-Origin-Opener-policy mismatch between source and destination"); >+ isolateFromOtherBrowsingContexts(); >+ return; >+ } >+ >+ switch (policy) { >+ case CrossOriginOpenerPolicy::SameOrigin: { >+ auto destinationOrigin = SecurityOrigin::create(destinationURL); >+ if (!destinationOrigin->isSameSchemeHostPort(m_frame.document()->securityOrigin())) { >+ RELEASE_LOG_IF_ALLOWED("isolateIfNecessaryDueToCrossOriginOpenerPolicy: isolating browsing context from any opener / openees due to Cross-Origin-Opener-policy: same-origin"); >+ isolateFromOtherBrowsingContexts(); >+ } >+ break; >+ } >+ case CrossOriginOpenerPolicy::SameSite: >+ if (!isSameSiteURL(m_frame.document()->securityOrigin(), destinationURL)) { >+ RELEASE_LOG_IF_ALLOWED("isolateIfNecessaryDueToCrossOriginOpenerPolicy: isolating browsing context from any opener / openees due to Cross-Origin-Opener-policy: same-site"); >+ isolateFromOtherBrowsingContexts(); >+ } >+ break; >+ case CrossOriginOpenerPolicy::None: >+ break; >+ } >+} >+ >+void FrameLoader::isolateFromOtherBrowsingContexts() >+{ >+ // Disown opener. >+ setOpener(nullptr); >+ if (auto* page = m_frame.page()) >+ page->setOpenedViaWindowOpenWithOpener(false); >+ >+ // Disconnect from openees. >+ for (auto& frame : m_openedFrames) >+ frame->loader().m_opener = nullptr; >+ m_openedFrames.clear(); >+ >+ // Make sure we use fresh Window proxies. The old window proxies will keep pointing to the old window which will be frameless when >+ // a new window is created for this frame. >+ m_frame.resetScript(); >+} >+ > void FrameLoader::loadProvisionalItemFromCachedPage() > { > DocumentLoader* provisionalLoader = provisionalDocumentLoader(); >diff --git a/Source/WebCore/loader/FrameLoader.h b/Source/WebCore/loader/FrameLoader.h >index a0bca8edc48a4236dfb168bf209aef08d41eafa5..2eacfd1d34ad352f996cb39457b82ecc49f51de0 100644 >--- a/Source/WebCore/loader/FrameLoader.h >+++ b/Source/WebCore/loader/FrameLoader.h >@@ -248,6 +248,7 @@ public: > > WEBCORE_EXPORT Frame* opener(); > WEBCORE_EXPORT void setOpener(Frame*); >+ bool hasOpenedFrames() const { return !m_openedFrames.isEmpty(); } > > void resetMultipleFormSubmissionProtection(); > >@@ -276,6 +277,7 @@ public: > void applyUserAgentIfNeeded(ResourceRequest&); > > bool shouldInterruptLoadForXFrameOptions(const String&, const URL&, unsigned long requestIdentifier); >+ void isolateIfNecessaryDueToCrossOriginOpenerPolicy(const String&, const URL& destinationURL); > > void completed(); > bool allAncestorsAreComplete() const; // including this >@@ -321,6 +323,8 @@ private: > MayNotAttemptCacheOnlyLoadForFormSubmissionItem > }; > >+ void isolateFromOtherBrowsingContexts(); >+ > bool allChildrenAreComplete() const; // immediate children, not all descendants > > void checkTimerFired(); >diff --git a/Source/WebCore/loader/PolicyChecker.cpp b/Source/WebCore/loader/PolicyChecker.cpp >index 4f90f94b7f1b957d76c6ed3d2762f477227907fa..e61356696af8529a9a6a7135c6bd3706abfba6a5 100644 >--- a/Source/WebCore/loader/PolicyChecker.cpp >+++ b/Source/WebCore/loader/PolicyChecker.cpp >@@ -106,6 +106,10 @@ void PolicyChecker::checkNavigationPolicy(ResourceRequest&& request, const Resou > loader->setTriggeringAction(NavigationAction { action }); > } > >+ if (m_frame.page() && m_frame.page()->openedViaWindowOpenWithOpener()) >+ action.setOpenedViaWindowOpenWithOpener(); >+ action.setHasOpenedFrames(m_frame.loader().hasOpenedFrames()); >+ > // Don't ask more than once for the same request or if we are loading an empty URL. > // This avoids confusion on the part of the client. > if (equalIgnoringHeaderFields(request, loader->lastCheckedRequest()) || (!request.isNull() && request.url().isEmpty())) { >diff --git a/Source/WebCore/page/AbstractFrame.cpp b/Source/WebCore/page/AbstractFrame.cpp >index 594a55e10451bab9e871ee981fb3b62e429552a2..68e63706d78ae184fa34c12d7adcff8613cf8e7f 100644 >--- a/Source/WebCore/page/AbstractFrame.cpp >+++ b/Source/WebCore/page/AbstractFrame.cpp >@@ -40,4 +40,10 @@ AbstractFrame::~AbstractFrame() > m_windowProxy->detachFromFrame(); > } > >+void AbstractFrame::resetWindowProxy() >+{ >+ m_windowProxy->detachFromFrame(); >+ m_windowProxy = WindowProxy::create(*this); >+} >+ > } // namespace WebCore >diff --git a/Source/WebCore/page/AbstractFrame.h b/Source/WebCore/page/AbstractFrame.h >index 995a3612820a6ff414ac0d104edc48924872ff4f..18ba9287cc349c5e8a58888755cbb86586f5c7b8 100644 >--- a/Source/WebCore/page/AbstractFrame.h >+++ b/Source/WebCore/page/AbstractFrame.h >@@ -49,6 +49,8 @@ public: > protected: > AbstractFrame(); > >+ void resetWindowProxy(); >+ > private: > virtual AbstractDOMWindow* virtualWindow() const = 0; > >diff --git a/Source/WebCore/page/DOMWindow.cpp b/Source/WebCore/page/DOMWindow.cpp >index 368e8bc3363edcc3907fdd0b9723f0cca37b8c8d..114a5700769a0ec261dadd244a799860c9b7f7b1 100644 >--- a/Source/WebCore/page/DOMWindow.cpp >+++ b/Source/WebCore/page/DOMWindow.cpp >@@ -2239,7 +2239,7 @@ ExceptionOr<RefPtr<Frame>> DOMWindow::createWindow(const String& urlString, cons > > if (!windowFeatures.noopener) { > newFrame->loader().setOpener(&openerFrame); >- newFrame->page()->setOpenedViaWindowOpenWithOpener(); >+ newFrame->page()->setOpenedViaWindowOpenWithOpener(true); > } > if (created) > newFrame->page()->setOpenedByDOM(); >diff --git a/Source/WebCore/page/Frame.cpp b/Source/WebCore/page/Frame.cpp >index 10d2c4ffd8a2207eaaa2f6ab6b0a51368518e15b..5ff8fbda6789f4a42c214a04eaa471cf4e5ea1e0 100644 >--- a/Source/WebCore/page/Frame.cpp >+++ b/Source/WebCore/page/Frame.cpp >@@ -1130,4 +1130,10 @@ void Frame::selfOnlyDeref() > deref(); > } > >+void Frame::resetScript() >+{ >+ resetWindowProxy(); >+ m_script = makeUniqueRef<ScriptController>(*this); >+} >+ > } // namespace WebCore >diff --git a/Source/WebCore/page/Frame.h b/Source/WebCore/page/Frame.h >index b747fd6c6e4032368c06b7ec87c564008a279d53..1139bffa491f10090e6f32ee4e3e2e4dc18d7fc3 100644 >--- a/Source/WebCore/page/Frame.h >+++ b/Source/WebCore/page/Frame.h >@@ -167,6 +167,7 @@ public: > const CSSAnimationController& animation() const { return m_animationController; } > ScriptController& script() { return m_script; } > const ScriptController& script() const { return m_script; } >+ void resetScript(); > > WEBCORE_EXPORT RenderView* contentRenderer() const; // Root of the render tree for the document contained in this frame. > WEBCORE_EXPORT RenderWidget* ownerRenderer() const; // Renderer for the element that contains this frame. >diff --git a/Source/WebCore/page/Page.h b/Source/WebCore/page/Page.h >index 3dbe572cd32903d5fcbd6c37e051bceb10723e7e..4344f17dabbfdf8c1a83dc2dce42e6e0fcad97a1 100644 >--- a/Source/WebCore/page/Page.h >+++ b/Source/WebCore/page/Page.h >@@ -204,7 +204,7 @@ public: > void setOpenedByDOM(); > > bool openedViaWindowOpenWithOpener() const { return m_openedViaWindowOpenWithOpener; } >- void setOpenedViaWindowOpenWithOpener() { m_openedViaWindowOpenWithOpener = true; } >+ void setOpenedViaWindowOpenWithOpener(bool value) { m_openedViaWindowOpenWithOpener = value; } > > WEBCORE_EXPORT void goToItem(HistoryItem&, FrameLoadType, ShouldTreatAsContinuingLoad); > >diff --git a/Source/WebCore/page/RuntimeEnabledFeatures.h b/Source/WebCore/page/RuntimeEnabledFeatures.h >index ac795057f545d96e0158d56993ff2051b774afa6..43ff7b0617d20c6d2f9aca580a8e38cc5a5ce906 100644 >--- a/Source/WebCore/page/RuntimeEnabledFeatures.h >+++ b/Source/WebCore/page/RuntimeEnabledFeatures.h >@@ -46,6 +46,9 @@ public: > void setBlankAnchorTargetImpliesNoOpenerEnabled(bool isEnabled) { m_blankAnchorTargetImpliesNoOpenerEnabled = isEnabled; } > bool blankAnchorTargetImpliesNoOpenerEnabled() const { return m_blankAnchorTargetImpliesNoOpenerEnabled; } > >+ void setCrossOriginOpenerPolicyEnabled(bool isEnabled) { m_crossOriginOpenerPolicyEnabled = isEnabled; } >+ bool crossOriginOpenerPolicyEnabled() const { return m_crossOriginOpenerPolicyEnabled; } >+ > void setDisplayContentsEnabled(bool isEnabled) { m_isDisplayContentsEnabled = isEnabled; } > bool displayContentsEnabled() const { return m_isDisplayContentsEnabled; } > >@@ -329,6 +332,7 @@ private: > RuntimeEnabledFeatures(); > > bool m_blankAnchorTargetImpliesNoOpenerEnabled { true }; >+ bool m_crossOriginOpenerPolicyEnabled { false }; > bool m_areModernMediaControlsEnabled { false }; > bool m_isLinkPreloadEnabled { true }; > bool m_isLinkPrefetchEnabled { false }; >diff --git a/Source/WebCore/platform/network/HTTPHeaderNames.in b/Source/WebCore/platform/network/HTTPHeaderNames.in >index 47f69040e81b92a2f03f2772436eaa4c62e82bf1..8379aa14c4c02cb8079a5c0f323ec0932c3e843e 100644 >--- a/Source/WebCore/platform/network/HTTPHeaderNames.in >+++ b/Source/WebCore/platform/network/HTTPHeaderNames.in >@@ -50,8 +50,8 @@ Content-Type > Content-Range > Cookie > Cookie2 >+Cross-Origin-Opener-Policy > Cross-Origin-Resource-Policy >-Cross-Origin-Window-Policy > Date > DNT > Default-Style >diff --git a/Source/WebCore/platform/network/HTTPParsers.cpp b/Source/WebCore/platform/network/HTTPParsers.cpp >index 942c7017f4d100d2ac74e04a7336de59a1cabe89..3efce620a12d514e32afcf90676cd4b5b413c322 100644 >--- a/Source/WebCore/platform/network/HTTPParsers.cpp >+++ b/Source/WebCore/platform/network/HTTPParsers.cpp >@@ -524,6 +524,19 @@ XFrameOptionsDisposition parseXFrameOptionsHeader(const String& header) > return result; > } > >+CrossOriginOpenerPolicy parseCrossOriginOpenerPolicyHeader(StringView header) >+{ >+ CrossOriginOpenerPolicy policy = CrossOriginOpenerPolicy::None; >+ if (header.isEmpty()) >+ return policy; >+ >+ if (equalLettersIgnoringASCIICase(header, "same-origin")) >+ policy = CrossOriginOpenerPolicy::SameOrigin; >+ else if (equalLettersIgnoringASCIICase(header, "same-site")) >+ policy = CrossOriginOpenerPolicy::SameSite; >+ return policy; >+} >+ > bool parseRange(const String& range, long long& rangeOffset, long long& rangeEnd, long long& rangeSuffixLength) > { > // The format of "Range" header is defined in RFC 2616 Section 14.35.1. >diff --git a/Source/WebCore/platform/network/HTTPParsers.h b/Source/WebCore/platform/network/HTTPParsers.h >index abe739d8e722733c038aefbcefe4e702d422d66b..dab89f07b4b25431f2b087663d9d43581d6fa70f 100644 >--- a/Source/WebCore/platform/network/HTTPParsers.h >+++ b/Source/WebCore/platform/network/HTTPParsers.h >@@ -71,6 +71,12 @@ enum class CrossOriginResourcePolicy { > Invalid > }; > >+enum class CrossOriginOpenerPolicy { >+ None, >+ SameOrigin, >+ SameSite >+}; >+ > bool isValidReasonPhrase(const String&); > bool isValidHTTPHeaderValue(const String&); > bool isValidAcceptHeaderValue(const String&); >@@ -85,6 +91,7 @@ void findCharsetInMediaType(const String& mediaType, unsigned int& charsetPos, u > XSSProtectionDisposition parseXSSProtectionHeader(const String& header, String& failureReason, unsigned& failurePosition, String& reportURL); > AtomicString extractReasonPhraseFromHTTPStatusLine(const String&); > WEBCORE_EXPORT XFrameOptionsDisposition parseXFrameOptionsHeader(const String&); >+CrossOriginOpenerPolicy parseCrossOriginOpenerPolicyHeader(StringView); > > // -1 could be set to one of the return parameters to indicate the value is not specified. > WEBCORE_EXPORT bool parseRange(const String&, long long& rangeOffset, long long& rangeEnd, long long& rangeSuffixLength); >diff --git a/Source/WebKit/Shared/WebPreferences.yaml b/Source/WebKit/Shared/WebPreferences.yaml >index 936452def559294b565faef92acca8118aecc937..660aa247fd4b9473ee7c138e3a2d09c05e3c8b0e 100644 >--- a/Source/WebKit/Shared/WebPreferences.yaml >+++ b/Source/WebKit/Shared/WebPreferences.yaml >@@ -6,6 +6,14 @@ BlankAnchorTargetImpliesNoOpenerEnabled: > humanReadableDescription: "target=_blank on anchor elements implies rel=noopener" > category: experimental > >+CrossOriginOpenerPolicyEnabled: >+ type: bool >+ defaultValue: false >+ webcoreBinding: RuntimeEnabledFeatures >+ humanReadableName: "Support for Cross-Origin-Opener-Policy HTTP header" >+ humanReadableDescription: "Support for Cross-Origin-Opener-Policy HTTP header" >+ category: experimental >+ > JavaScriptEnabled: > type: bool > defaultValue: true >diff --git a/Source/WebKit/UIProcess/API/C/WKPreferences.cpp b/Source/WebKit/UIProcess/API/C/WKPreferences.cpp >index 823174a29d94997854a07a1a39386179c0a2d8c0..b878d9e75f305f2e4baca909b8690dadf3ba36d5 100644 >--- a/Source/WebKit/UIProcess/API/C/WKPreferences.cpp >+++ b/Source/WebKit/UIProcess/API/C/WKPreferences.cpp >@@ -2030,6 +2030,16 @@ bool WKPreferencesGetRestrictedHTTPResponseAccess(WKPreferencesRef preferencesRe > return toImpl(preferencesRef)->restrictedHTTPResponseAccess(); > } > >+bool WKPreferencesGetCrossOriginOpenerPolicyEnabled(WKPreferencesRef preferencesRef) >+{ >+ return toImpl(preferencesRef)->crossOriginOpenerPolicyEnabled(); >+} >+ >+void WKPreferencesSetCrossOriginOpenerPolicyEnabled(WKPreferencesRef preferencesRef, bool enabled) >+{ >+ toImpl(preferencesRef)->setCrossOriginOpenerPolicyEnabled(enabled); >+} >+ > void WKPreferencesSetServerTimingEnabled(WKPreferencesRef preferencesRef, bool flag) > { > toImpl(preferencesRef)->setServerTimingEnabled(flag); >diff --git a/Source/WebKit/UIProcess/API/C/WKPreferencesRef.h b/Source/WebKit/UIProcess/API/C/WKPreferencesRef.h >index 9716693f6d8603481951adea40e65df96857001c..6f20f408ed91390c14f1654e659c928a8af583c6 100644 >--- a/Source/WebKit/UIProcess/API/C/WKPreferencesRef.h >+++ b/Source/WebKit/UIProcess/API/C/WKPreferencesRef.h >@@ -320,9 +320,13 @@ WK_EXPORT void WKPreferencesSetMediaCapabilitiesEnabled(WKPreferencesRef prefere > WK_EXPORT bool WKPreferencesGetRestrictedHTTPResponseAccess(WKPreferencesRef preferencesRef); > WK_EXPORT void WKPreferencesSetRestrictedHTTPResponseAccess(WKPreferencesRef preferencesRef, bool allow); > >+// Defaults to false. >+WK_EXPORT bool WKPreferencesGetCrossOriginOpenerPolicyEnabled(WKPreferencesRef preferencesRef); >+WK_EXPORT void WKPreferencesSetCrossOriginOpenerPolicyEnabled(WKPreferencesRef preferencesRef, bool allow); >+ > // Defaults to false. > WK_EXPORT bool WKPreferencesGetCrossOriginResourcePolicyEnabled(WKPreferencesRef preferencesRef); >-WK_EXPORT void WKPreferencesSetCrossOriginResourcePolicyEnabled(WKPreferencesRef preferencesRef, bool allow); >+WK_EXPORT void WKPreferencesSetCrossOriginResourcePolicyEnabled(WKPreferencesRef preferencesRef, bool enabled); > > // Defaults to false. > WK_EXPORT bool WKPreferencesGetProcessSwapOnNavigationEnabled(WKPreferencesRef preferencesRef); >diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm b/Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm >index eda9c818e66123bc148875afb737eddcb06167bb..9f9053cfcab86a0873fb3fbff98ce944ce63b3e1 100644 >--- a/Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm >+++ b/Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm >@@ -1346,6 +1346,16 @@ - (BOOL)_webAnimationsCSSIntegrationEnabled > return _preferences->webAnimationsCSSIntegrationEnabled(); > } > >+- (void)_setCrossOriginOpenerPolicyEnabled:(BOOL)enabled >+{ >+ _preferences->setCrossOriginOpenerPolicyEnabled(enabled); >+} >+ >+- (BOOL)_crossOriginOpenerPolicyEnabled >+{ >+ return _preferences->crossOriginOpenerPolicyEnabled(); >+} >+ > @end > > #endif // WK_API_ENABLED >diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h b/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h >index 28698bfbe6e9a37c791ebc30d5df05005af28049..078a373547308567a02d6edaf91ae52bd90c93d7 100644 >--- a/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h >+++ b/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h >@@ -150,6 +150,7 @@ typedef NS_ENUM(NSInteger, _WKEditableLinkBehavior) { > @property (nonatomic, setter=_setShouldIgnoreMetaViewport:) BOOL _shouldIgnoreMetaViewport WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)); > @property (nonatomic, setter=_setVideoQualityIncludesDisplayCompositingEnabled:) BOOL _videoQualityIncludesDisplayCompositingEnabled WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)); > @property (nonatomic, setter=_setWebAnimationsCSSIntegrationEnabled:) BOOL _webAnimationsCSSIntegrationEnabled WK_API_AVAILABLE(macosx(10.14), ios(WK_IOS_TBA)); >+@property (nonatomic, setter=_setCrossOriginOpenerPolicyEnabled:) BOOL _crossOriginOpenerPolicyEnabled WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)); > > #if !TARGET_OS_IPHONE > @property (nonatomic, setter=_setWebGLEnabled:) BOOL _webGLEnabled WK_API_AVAILABLE(macosx(10.13.4)); >diff --git a/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h b/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h >index b73f6cb6830430fa18124b678520a06c14a4cc80..7d106a4fd912f5d5a761cbbde6137e38f4167a67 100644 >--- a/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h >+++ b/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h >@@ -175,6 +175,7 @@ > #define WebKitDataTransferItemsEnabledPreferenceKey @"WebKitDataTransferItemsEnabled" > #define WebKitCustomPasteboardDataEnabledPreferenceKey @"WebKitCustomPasteboardDataEnabled" > #define WebKitCacheAPIEnabledPreferenceKey @"WebKitCacheAPIEnabled" >+#define WebKitCrossOriginOpenerPolicyEnabledPreferenceKey @"WebKitCrossOriginOpenerPolicyEnabled" > #define WebKitFetchAPIEnabledPreferenceKey @"WebKitFetchAPIEnabled" > #define WebKitWritableStreamAPIEnabledPreferenceKey @"WebKitWritableStreamAPIEnabled" > #define WebKitReadableByteStreamAPIEnabledPreferenceKey @"WebKitReadableByteStreamAPIEnabled" >diff --git a/Source/WebKitLegacy/mac/WebView/WebPreferences.mm b/Source/WebKitLegacy/mac/WebView/WebPreferences.mm >index 7e1cfc1b1e29b46d6dbd1f33cb44c0b11591517a..3af47a42f84edf6ca9f450bf39b523e2458d882d 100644 >--- a/Source/WebKitLegacy/mac/WebView/WebPreferences.mm >+++ b/Source/WebKitLegacy/mac/WebView/WebPreferences.mm >@@ -637,6 +637,7 @@ + (void)initialize > [NSNumber numberWithBool:NO], WebKitWebMetalEnabledPreferenceKey, > #endif > [NSNumber numberWithBool:NO], WebKitCacheAPIEnabledPreferenceKey, >+ [NSNumber numberWithBool:NO], WebKitCrossOriginOpenerPolicyEnabledPreferenceKey, > [NSNumber numberWithBool:YES], WebKitFetchAPIEnabledPreferenceKey, > > #if ENABLE(STREAMS_API) >@@ -3027,6 +3028,16 @@ - (void)setCacheAPIEnabled:(BOOL)flag > [self _setBoolValue:flag forKey:WebKitCacheAPIEnabledPreferenceKey]; > } > >+- (BOOL)crossOriginOpenerPolicyEnabled >+{ >+ return [self _boolValueForKey:WebKitCrossOriginOpenerPolicyEnabledPreferenceKey]; >+} >+ >+- (void)setCrossOriginOpenerPolicyEnabled:(BOOL)flag >+{ >+ [self _setBoolValue:flag forKey:WebKitCrossOriginOpenerPolicyEnabledPreferenceKey]; >+} >+ > - (BOOL)fetchAPIEnabled > { > return [self _boolValueForKey:WebKitFetchAPIEnabledPreferenceKey]; >diff --git a/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h b/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h >index 20b33429510785e706c1563331209661017a5e56..81605ad09b8f7ed3a6bbc0f6b6a7bb60eb76650e 100644 >--- a/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h >+++ b/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h >@@ -543,6 +543,9 @@ extern NSString *WebPreferencesCacheModelChangedInternalNotification WEBKIT_DEPR > - (BOOL)cacheAPIEnabled; > - (void)setCacheAPIEnabled:(BOOL)enabled; > >+- (BOOL)crossOriginOpenerPolicyEnabled; >+- (void)setCrossOriginOpenerPolicyEnabled:(BOOL)enabled; >+ > - (void)setFetchAPIEnabled:(BOOL)flag; > - (BOOL)fetchAPIEnabled; > >diff --git a/Source/WebKitLegacy/mac/WebView/WebView.mm b/Source/WebKitLegacy/mac/WebView/WebView.mm >index 893fa08ccf90658b447bb65bc39bfa359b7be003..b37d85adceb480b4ebe92c01050cc3fb3456e0f0 100644 >--- a/Source/WebKitLegacy/mac/WebView/WebView.mm >+++ b/Source/WebKitLegacy/mac/WebView/WebView.mm >@@ -3105,6 +3105,7 @@ - (void)_preferencesChanged:(WebPreferences *)preferences > > RuntimeEnabledFeatures::sharedFeatures().setCacheAPIEnabled([preferences cacheAPIEnabled]); > RuntimeEnabledFeatures::sharedFeatures().setFetchAPIEnabled([preferences fetchAPIEnabled]); >+ RuntimeEnabledFeatures::sharedFeatures().setCrossOriginOpenerPolicyEnabled([preferences crossOriginOpenerPolicyEnabled]); > > #if ENABLE(STREAMS_API) > RuntimeEnabledFeatures::sharedFeatures().setWritableStreamAPIEnabled([preferences writableStreamAPIEnabled]); >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index ecbcd97f30b0fe7ea95b6e4444f24fdff0369756..757cfcab56b8948a92d7999dfde0a77495a256e7 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,21 @@ >+2018-11-30 Chris Dumez <cdumez@apple.com> >+ >+ Add initial support for 'Cross-Origin-Opener-Policy' HTTP header >+ https://bugs.webkit.org/show_bug.cgi?id=192193 >+ <rdar://problem/42013525> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add API test coverage. >+ >+ * DumpRenderTree/mac/DumpRenderTree.mm: >+ (enableExperimentalFeatures): >+ * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm: >+ (-[PSONScheme addMappingFromURLString:toHeaders:]): >+ (-[PSONScheme webView:startURLSchemeTask:]): >+ * WebKitTestRunner/TestController.cpp: >+ (WTR::TestController::resetPreferencesToConsistentValues): >+ > 2018-11-28 Zalan Bujtas <zalan@apple.com> > > [LFC][Quirk] Use non-collapsed vertical margin values when the container is stretched to the size of the ICB. >diff --git a/Tools/DumpRenderTree/mac/DumpRenderTree.mm b/Tools/DumpRenderTree/mac/DumpRenderTree.mm >index 5de612c59f367c4d094c8fb3178286ed3bdcbff0..15878c66d13cb3f154f701aa4fd18b923eb12f6b 100644 >--- a/Tools/DumpRenderTree/mac/DumpRenderTree.mm >+++ b/Tools/DumpRenderTree/mac/DumpRenderTree.mm >@@ -864,6 +864,7 @@ static void enableExperimentalFeatures(WebPreferences* preferences) > [preferences setAriaReflectionEnabled:YES]; > [preferences setVisualViewportAPIEnabled:YES]; > [preferences setColorFilterEnabled:YES]; >+ [preferences setCrossOriginOpenerPolicyEnabled:YES]; > [preferences setServerTimingEnabled:YES]; > [preferences setIntersectionObserverEnabled:YES]; > preferences.sourceBufferChangeTypeEnabled = YES; >diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm >index f32fae510964deb6b6417e2bc9fdbca0b13cf942..bb6b18603a018188dfbdf7eef7d85fa84cc11472 100644 >--- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm >+++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm >@@ -189,6 +189,7 @@ @interface PSONScheme : NSObject <WKURLSchemeHandler> { > const char* _bytes; > HashMap<String, String> _redirects; > HashMap<String, RetainPtr<NSData *>> _dataMappings; >+ HashMap<String, NSDictionary<NSString *, NSString *> *> _headers; > } > - (instancetype)initWithBytes:(const char*)bytes; > - (void)addRedirectFromURLString:(NSString *)sourceURLString toURLString:(NSString *)destinationURLString; >@@ -214,6 +215,11 @@ - (void)addMappingFromURLString:(NSString *)urlString toData:(const char*)data > _dataMappings.set(urlString, [NSData dataWithBytesNoCopy:(void*)data length:strlen(data) freeWhenDone:NO]); > } > >+- (void)addMappingFromURLString:(NSString *)urlString toHeaders:(NSDictionary<NSString *, NSString *> *)headers >+{ >+ _headers.set(urlString, headers); >+} >+ > - (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task > { > NSURL *finalURL = task.request.URL; >@@ -227,7 +233,11 @@ - (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)ta > [(id<WKURLSchemeTaskPrivate>)task _didPerformRedirection:redirectResponse.get() newRequest:request.get()]; > } > >- RetainPtr<NSURLResponse> response = adoptNS([[NSURLResponse alloc] initWithURL:finalURL MIMEType:@"text/html" expectedContentLength:1 textEncodingName:nil]); >+ NSDictionary<NSString *, NSString *> *headers = _headers.get(task.request.URL.absoluteString); >+ if (!headers) >+ headers = @{ @"Content-Type" : @"text/html", }; >+ >+ RetainPtr<NSURLResponse> response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:finalURL statusCode:200 HTTPVersion:@"2.0" headerFields:headers]); > [task didReceiveResponse:response.get()]; > > if (auto data = _dataMappings.get([finalURL absoluteString])) >@@ -335,10 +345,35 @@ window.onload = function() { > </script> > )PSONRESOURCE"; > >+static const char* windowOpenCrossOriginButSameSiteWithOpenerTestBytes = R"PSONRESOURCE( >+<script> >+window.onload = function() { >+ w = window.open("pson://bugs.webkit.org/main.html"); >+} >+</script> >+)PSONRESOURCE"; >+ > static const char* windowOpenCrossSiteWithOpenerTestBytes = R"PSONRESOURCE( > <script> > window.onload = function() { >- window.open("pson://www.apple.com/main.html"); >+ w = window.open("pson://www.apple.com/main.html"); >+} >+</script> >+)PSONRESOURCE"; >+ >+static const char* windowOpenCrossSiteWithOpenerLinkTargetingTestBytes = R"PSONRESOURCE( >+<a id="testLink" target="foo" href="pson://www.webkit.org/main2.html">Link</a> >+<script> >+window.onload = function() { >+ w = window.open("pson://www.apple.com/main.html", "foo"); >+} >+</script> >+)PSONRESOURCE"; >+ >+static const char* windowOpenSameSiteWithOpenerTestBytes = R"PSONRESOURCE( >+<script> >+window.onload = function() { >+ w = window.open("pson://www.webkit.org/main2.html"); > } > </script> > )PSONRESOURCE"; >@@ -2973,6 +3008,481 @@ TEST(ProcessSwap, GoBackToSuspendedPageWithMainFrameIDThatIsNotOne) > EXPECT_EQ(pid1, pid5); > } > >+enum class NewWindowShouldBeIsolated { No, Yes }; >+enum class NewWindowOrigin { SameOrigin, CrossOriginButSameSite, CrossSite }; >+void runCrossOriginOpenerPolicyTest(const String& crossOriginOpenerPolicy, NewWindowOrigin newWindowOrigin, NewWindowShouldBeIsolated newWindowShouldBeIsolated) >+{ >+ auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]); >+ [processPoolConfiguration setProcessSwapsOnNavigation:YES]; >+ auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]); >+ >+ auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]); >+ [webViewConfiguration setProcessPool:processPool.get()]; >+ auto handler = adoptNS([[PSONScheme alloc] init]); >+ NSString *destinationURL; >+ switch (newWindowOrigin) { >+ case NewWindowOrigin::SameOrigin: >+ [handler addMappingFromURLString:@"pson://www.webkit.org/main1.html" toData:windowOpenSameSiteWithOpenerTestBytes]; // Opens "pson://www.webkit.org/main2.html". >+ destinationURL = @"pson://www.webkit.org/main2.html"; >+ break; >+ case NewWindowOrigin::CrossOriginButSameSite: >+ [handler addMappingFromURLString:@"pson://www.webkit.org/main1.html" toData:windowOpenCrossOriginButSameSiteWithOpenerTestBytes]; // Opens "pson://bugs.webkit.org/main.html". >+ destinationURL = @"pson://bugs.webkit.org/main.html"; >+ break; >+ case NewWindowOrigin::CrossSite: >+ [handler addMappingFromURLString:@"pson://www.webkit.org/main1.html" toData:windowOpenCrossSiteWithOpenerTestBytes]; // Opens "pson://www.apple.com/main.html". >+ destinationURL = @"pson://www.apple.com/main.html"; >+ break; >+ } >+ [handler addMappingFromURLString:@"pson://www.webkit.org/main1.html" toHeaders:@{ @"Content-Type": @"text/html", @"Cross-Origin-Opener-Policy": (NSString *)crossOriginOpenerPolicy }]; >+ [handler addMappingFromURLString:destinationURL toHeaders:@{ @"Content-Type": @"text/html", @"Cross-Origin-Opener-Policy": (NSString *)crossOriginOpenerPolicy }]; >+ >+ [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"]; >+ >+ auto messageHandler = adoptNS([[PSONMessageHandler alloc] init]); >+ [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"pson"]; >+ >+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]); >+ auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]); >+ [webView setNavigationDelegate:navigationDelegate.get()]; >+ auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]); >+ [webView setUIDelegate:uiDelegate.get()]; >+ >+ [webView configuration].preferences._crossOriginOpenerPolicyEnabled = YES; >+ >+ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html"]]; >+ >+ [webView loadRequest:request]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ TestWebKitAPI::Util::run(&didCreateWebView); >+ didCreateWebView = false; >+ >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ // FIXME: We should be able to process-swap when newWindowShouldBeIsolated == NewWindowShouldBeIsolated::Yes. >+ EXPECT_EQ([webView _webProcessIdentifier], [createdWebView _webProcessIdentifier]); >+ >+ EXPECT_WK_STREQ(@"pson://www.webkit.org/main1.html", [[webView URL] absoluteString]); >+ EXPECT_WK_STREQ(destinationURL, [[createdWebView URL] absoluteString]); >+ >+ [webView evaluateJavaScript:@"w.closed ? 'true' : 'false'" completionHandler: [&] (id closed, NSError *error) { >+ if (newWindowShouldBeIsolated == NewWindowShouldBeIsolated::Yes) >+ EXPECT_WK_STREQ(@"true", closed); >+ else >+ EXPECT_WK_STREQ(@"false", closed); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ // New window should not have an opener. >+ [webView evaluateJavaScript:@"w.opener ? 'true' : 'false'" completionHandler: [&] (id hasOpener, NSError *error) { >+ if (newWindowShouldBeIsolated == NewWindowShouldBeIsolated::Yes) >+ EXPECT_WK_STREQ(@"false", hasOpener); >+ else >+ EXPECT_WK_STREQ(@"true", hasOpener); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ [createdWebView evaluateJavaScript:@"window.opener ? 'true' : 'false'" completionHandler: [&] (id hasOpener, NSError *error) { >+ if (newWindowShouldBeIsolated == NewWindowShouldBeIsolated::Yes) >+ EXPECT_WK_STREQ(@"false", hasOpener); >+ else >+ EXPECT_WK_STREQ(@"true", hasOpener); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+} >+ >+TEST(ProcessSwap, WindowOpenSameOriginCrossOriginOpenerPolicySameOrigin) >+{ >+ runCrossOriginOpenerPolicyTest("same-origin", NewWindowOrigin::SameOrigin, NewWindowShouldBeIsolated::No); >+} >+ >+TEST(ProcessSwap, WindowOpenCrossOriginOriginCrossOriginOpenerPolicySameOrigin) >+{ >+ runCrossOriginOpenerPolicyTest("same-origin", NewWindowOrigin::CrossOriginButSameSite, NewWindowShouldBeIsolated::Yes); >+} >+ >+TEST(ProcessSwap, WindowOpenCrossSiteOriginCrossOriginOpenerPolicySameOrigin) >+{ >+ runCrossOriginOpenerPolicyTest("same-origin", NewWindowOrigin::CrossSite, NewWindowShouldBeIsolated::Yes); >+} >+ >+TEST(ProcessSwap, WindowOpenSameOriginCrossOriginOpenerPolicySameSite) >+{ >+ runCrossOriginOpenerPolicyTest("same-site", NewWindowOrigin::SameOrigin, NewWindowShouldBeIsolated::No); >+} >+ >+TEST(ProcessSwap, WindowOpenCrossOriginOriginCrossOriginOpenerPolicySameSite) >+{ >+ runCrossOriginOpenerPolicyTest("same-site", NewWindowOrigin::CrossOriginButSameSite, NewWindowShouldBeIsolated::No); >+} >+ >+TEST(ProcessSwap, WindowOpenCrossSiteOriginCrossOriginOpenerPolicySameSite) >+{ >+ runCrossOriginOpenerPolicyTest("same-site", NewWindowOrigin::CrossSite, NewWindowShouldBeIsolated::Yes); >+} >+ >+static const char* saveOpenerTestBytes = R"PSONRESOURCE( >+<script> >+window.onload = function() { >+ savedOpener = opener; >+} >+</script> >+)PSONRESOURCE"; >+ >+TEST(ProcessSwap, NavigateToWindowWithCrossOriginOpenerPolicy) >+{ >+ auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]); >+ [processPoolConfiguration setProcessSwapsOnNavigation:YES]; >+ auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]); >+ >+ auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]); >+ [webViewConfiguration setProcessPool:processPool.get()]; >+ auto handler = adoptNS([[PSONScheme alloc] init]); >+ [handler addMappingFromURLString:@"pson://www.webkit.org/main1.html" toData:windowOpenSameSiteWithOpenerTestBytes]; // Opens "pson://www.webkit.org/main2.html". >+ [handler addMappingFromURLString:@"pson://www.webkit.org/main2.html" toData:saveOpenerTestBytes]; >+ [handler addMappingFromURLString:@"pson://www.apple.com/main.html" toHeaders:@{ @"Content-Type": @"text/html", @"Cross-Origin-Opener-Policy": @"same-origin" }]; >+ >+ [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"]; >+ >+ auto messageHandler = adoptNS([[PSONMessageHandler alloc] init]); >+ [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"pson"]; >+ >+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]); >+ auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]); >+ [webView setNavigationDelegate:navigationDelegate.get()]; >+ auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]); >+ [webView setUIDelegate:uiDelegate.get()]; >+ >+ [webView configuration].preferences._crossOriginOpenerPolicyEnabled = YES; >+ >+ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html"]]; >+ >+ [webView loadRequest:request]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ TestWebKitAPI::Util::run(&didCreateWebView); >+ didCreateWebView = false; >+ >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ EXPECT_EQ([webView _webProcessIdentifier], [createdWebView _webProcessIdentifier]); >+ auto webkitPID = [webView _webProcessIdentifier]; >+ >+ EXPECT_WK_STREQ(@"pson://www.webkit.org/main1.html", [[webView URL] absoluteString]); >+ EXPECT_WK_STREQ(@"pson://www.webkit.org/main2.html", [[createdWebView URL] absoluteString]); >+ >+ // New window should have an opener. >+ [createdWebView evaluateJavaScript:@"window.opener ? 'true' : 'false'" completionHandler: [&] (id hasOpener, NSError *error) { >+ EXPECT_WK_STREQ(@"true", hasOpener); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ [createdWebView evaluateJavaScript:@"window.opener.closed ? 'true' : 'false'" completionHandler: [&] (id openerIsClosed, NSError *error) { >+ EXPECT_WK_STREQ(@"false", openerIsClosed); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ // Navigate cross-origin to a page with 'Cross-Origin-Opener-Policy: same-origin'. >+ request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main.html"]]; >+ >+ [webView loadRequest:request]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [[webView URL] absoluteString]); >+ >+ // FIXME: we should be able to process-swap in this case. >+ EXPECT_EQ(webkitPID, [webView _webProcessIdentifier]); >+ >+ // Auxiliary window should no longer have an opener. >+ [createdWebView evaluateJavaScript:@"window.opener ? 'true' : 'false'" completionHandler: [&] (id hasOpener, NSError *error) { >+ EXPECT_WK_STREQ(@"false", hasOpener); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ // Saved opener should appear closed. >+ [createdWebView evaluateJavaScript:@"savedOpener.closed ? 'true' : 'false'" completionHandler: [&] (id savedOpenerIsClosed, NSError *error) { >+ EXPECT_WK_STREQ(@"true", savedOpenerIsClosed); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ [createdWebView evaluateJavaScript:@"savedOpener.location.href" completionHandler: [&] (id savedOpenerURL, NSError *error) { >+ EXPECT_WK_STREQ(@"about:blank", savedOpenerURL); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+} >+ >+// Source has the header, destination does hot. >+TEST(ProcessSwap, CrossOriginOpenerPolicyMismatchDuringSameOriginNavigation1) >+{ >+ auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]); >+ [processPoolConfiguration setProcessSwapsOnNavigation:YES]; >+ auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]); >+ >+ auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]); >+ [webViewConfiguration setProcessPool:processPool.get()]; >+ auto handler = adoptNS([[PSONScheme alloc] init]); >+ [handler addMappingFromURLString:@"pson://www.webkit.org/main1.html" toData:windowOpenSameSiteWithOpenerTestBytes]; // Opens "pson://www.webkit.org/main2.html". >+ [handler addMappingFromURLString:@"pson://www.webkit.org/main1.html" toHeaders:@{ @"Content-Type": @"text/html", @"Cross-Origin-Opener-Policy": @"same-origin" }]; >+ [handler addMappingFromURLString:@"pson://www.webkit.org/main2.html" toData:saveOpenerTestBytes]; >+ [handler addMappingFromURLString:@"pson://www.webkit.org/main2.html" toHeaders:@{ @"Content-Type": @"text/html", @"Cross-Origin-Opener-Policy": @"same-origin" }]; >+ >+ [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"]; >+ >+ auto messageHandler = adoptNS([[PSONMessageHandler alloc] init]); >+ [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"pson"]; >+ >+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]); >+ auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]); >+ [webView setNavigationDelegate:navigationDelegate.get()]; >+ auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]); >+ [webView setUIDelegate:uiDelegate.get()]; >+ >+ [webView configuration].preferences._crossOriginOpenerPolicyEnabled = YES; >+ >+ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html"]]; >+ >+ [webView loadRequest:request]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ TestWebKitAPI::Util::run(&didCreateWebView); >+ didCreateWebView = false; >+ >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ EXPECT_EQ([webView _webProcessIdentifier], [createdWebView _webProcessIdentifier]); >+ auto webkitPID = [webView _webProcessIdentifier]; >+ >+ EXPECT_WK_STREQ(@"pson://www.webkit.org/main1.html", [[webView URL] absoluteString]); >+ EXPECT_WK_STREQ(@"pson://www.webkit.org/main2.html", [[createdWebView URL] absoluteString]); >+ >+ // New window should have an opener. >+ [createdWebView evaluateJavaScript:@"window.opener ? 'true' : 'false'" completionHandler: [&] (id hasOpener, NSError *error) { >+ EXPECT_WK_STREQ(@"true", hasOpener); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ [createdWebView evaluateJavaScript:@"window.opener.closed ? 'true' : 'false'" completionHandler: [&] (id openerIsClosed, NSError *error) { >+ EXPECT_WK_STREQ(@"false", openerIsClosed); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ // Navigate away from page with 'Cross-Origin-Opener-Policy: same-origin'. >+ request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main3.html"]]; >+ >+ [webView loadRequest:request]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ EXPECT_WK_STREQ(@"pson://www.webkit.org/main3.html", [[webView URL] absoluteString]); >+ >+ // FIXME: we should be able to process-swap in this case. >+ EXPECT_EQ(webkitPID, [webView _webProcessIdentifier]); >+ >+ // Auxiliary window should no longer have an opener. >+ [createdWebView evaluateJavaScript:@"window.opener ? 'true' : 'false'" completionHandler: [&] (id hasOpener, NSError *error) { >+ EXPECT_WK_STREQ(@"false", hasOpener); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ // Saved opener should appear closed. >+ [createdWebView evaluateJavaScript:@"savedOpener.closed ? 'true' : 'false'" completionHandler: [&] (id savedOpenerIsClosed, NSError *error) { >+ EXPECT_WK_STREQ(@"true", savedOpenerIsClosed); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ [createdWebView evaluateJavaScript:@"savedOpener.location.href" completionHandler: [&] (id savedOpenerURL, NSError *error) { >+ EXPECT_WK_STREQ(@"about:blank", savedOpenerURL); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+} >+ >+// Source does not have the header, destination does. >+TEST(ProcessSwap, CrossOriginOpenerPolicyMismatchDuringSameOriginNavigation2) >+{ >+ auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]); >+ [processPoolConfiguration setProcessSwapsOnNavigation:YES]; >+ auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]); >+ >+ auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]); >+ [webViewConfiguration setProcessPool:processPool.get()]; >+ auto handler = adoptNS([[PSONScheme alloc] init]); >+ [handler addMappingFromURLString:@"pson://www.webkit.org/main1.html" toData:windowOpenSameSiteWithOpenerTestBytes]; // Opens "pson://www.webkit.org/main2.html". >+ [handler addMappingFromURLString:@"pson://www.webkit.org/main2.html" toData:saveOpenerTestBytes]; >+ [handler addMappingFromURLString:@"pson://www.webkit.org/main3.html" toHeaders:@{ @"Content-Type": @"text/html", @"Cross-Origin-Opener-Policy": @"same-origin" }]; >+ >+ [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"]; >+ >+ auto messageHandler = adoptNS([[PSONMessageHandler alloc] init]); >+ [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"pson"]; >+ >+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]); >+ auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]); >+ [webView setNavigationDelegate:navigationDelegate.get()]; >+ auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]); >+ [webView setUIDelegate:uiDelegate.get()]; >+ >+ [webView configuration].preferences._crossOriginOpenerPolicyEnabled = YES; >+ >+ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html"]]; >+ >+ [webView loadRequest:request]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ TestWebKitAPI::Util::run(&didCreateWebView); >+ didCreateWebView = false; >+ >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ EXPECT_EQ([webView _webProcessIdentifier], [createdWebView _webProcessIdentifier]); >+ auto webkitPID = [webView _webProcessIdentifier]; >+ >+ EXPECT_WK_STREQ(@"pson://www.webkit.org/main1.html", [[webView URL] absoluteString]); >+ EXPECT_WK_STREQ(@"pson://www.webkit.org/main2.html", [[createdWebView URL] absoluteString]); >+ >+ // New window should have an opener. >+ [createdWebView evaluateJavaScript:@"window.opener ? 'true' : 'false'" completionHandler: [&] (id hasOpener, NSError *error) { >+ EXPECT_WK_STREQ(@"true", hasOpener); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ [createdWebView evaluateJavaScript:@"window.opener.closed ? 'true' : 'false'" completionHandler: [&] (id openerIsClosed, NSError *error) { >+ EXPECT_WK_STREQ(@"false", openerIsClosed); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ // Navigate away from page with 'Cross-Origin-Opener-Policy: same-origin'. >+ request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main3.html"]]; >+ >+ [webView loadRequest:request]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ EXPECT_WK_STREQ(@"pson://www.webkit.org/main3.html", [[webView URL] absoluteString]); >+ >+ // FIXME: we should be able to process-swap in this case. >+ EXPECT_EQ(webkitPID, [webView _webProcessIdentifier]); >+ >+ // Auxiliary window should no longer have an opener. >+ [createdWebView evaluateJavaScript:@"window.opener ? 'true' : 'false'" completionHandler: [&] (id hasOpener, NSError *error) { >+ EXPECT_WK_STREQ(@"false", hasOpener); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ // Saved opener should appear closed. >+ [createdWebView evaluateJavaScript:@"savedOpener.closed ? 'true' : 'false'" completionHandler: [&] (id savedOpenerIsClosed, NSError *error) { >+ EXPECT_WK_STREQ(@"true", savedOpenerIsClosed); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ [createdWebView evaluateJavaScript:@"savedOpener.location.href" completionHandler: [&] (id savedOpenerURL, NSError *error) { >+ EXPECT_WK_STREQ(@"about:blank", savedOpenerURL); >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+} >+ >+TEST(ProcessSwap, CrossOriginOpenerPolicyPreventsLinkTargeting) >+{ >+ auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]); >+ [processPoolConfiguration setProcessSwapsOnNavigation:YES]; >+ auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]); >+ >+ auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]); >+ [webViewConfiguration setProcessPool:processPool.get()]; >+ auto handler = adoptNS([[PSONScheme alloc] init]); >+ [handler addMappingFromURLString:@"pson://www.webkit.org/main1.html" toData:windowOpenCrossSiteWithOpenerLinkTargetingTestBytes]; // Opens "pson://www.apple.com/main.html". >+ [handler addMappingFromURLString:@"pson://www.apple.com/main.html" toHeaders:@{ @"Content-Type": @"text/html", @"Cross-Origin-Opener-Policy": @"same-origin" }]; >+ >+ [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"]; >+ >+ auto messageHandler = adoptNS([[PSONMessageHandler alloc] init]); >+ [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"pson"]; >+ >+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]); >+ auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]); >+ [webView setNavigationDelegate:navigationDelegate.get()]; >+ auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]); >+ [webView setUIDelegate:uiDelegate.get()]; >+ >+ [webView configuration].preferences._crossOriginOpenerPolicyEnabled = YES; >+ >+ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html"]]; >+ >+ [webView loadRequest:request]; >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ TestWebKitAPI::Util::run(&didCreateWebView); >+ didCreateWebView = false; >+ >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ EXPECT_WK_STREQ(@"pson://www.webkit.org/main1.html", [[webView URL] absoluteString]); >+ EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [[createdWebView URL] absoluteString]); >+ >+ RetainPtr<WKWebView> firstCreatedWebView = createdWebView; >+ >+ // Click the link with target "foo", which matches the name of the new isolated window. >+ // This should create a new WebView instead of navigating the existing one since they do not belong to the same browsing context group. >+ [webView evaluateJavaScript:@"testLink.click()" completionHandler:nil]; >+ >+ TestWebKitAPI::Util::run(&didCreateWebView); >+ didCreateWebView = false; >+ >+ TestWebKitAPI::Util::run(&done); >+ done = false; >+ >+ EXPECT_WK_STREQ(@"pson://www.webkit.org/main1.html", [[webView URL] absoluteString]); >+ EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [[firstCreatedWebView URL] absoluteString]); >+ EXPECT_WK_STREQ(@"pson://www.webkit.org/main2.html", [[createdWebView URL] absoluteString]); >+} >+ > #endif // PLATFORM(MAC) > > #endif // WK_API_ENABLED >diff --git a/Tools/WebKitTestRunner/TestController.cpp b/Tools/WebKitTestRunner/TestController.cpp >index 56374f70cc0f8e3033f2129ddea0f825f7756ed5..1476ff80f70559d077378d6dfee81f648a7840a3 100644 >--- a/Tools/WebKitTestRunner/TestController.cpp >+++ b/Tools/WebKitTestRunner/TestController.cpp >@@ -817,6 +817,7 @@ void TestController::resetPreferencesToConsistentValues(const TestOptions& optio > WKPreferencesSetCSSOMViewScrollingAPIEnabled(preferences, true); > WKPreferencesSetMediaCapabilitiesEnabled(preferences, true); > >+ WKPreferencesSetCrossOriginOpenerPolicyEnabled(preferences, true); > WKPreferencesSetRestrictedHTTPResponseAccess(preferences, true); > > WKPreferencesSetServerTimingEnabled(preferences, true); >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index e1622f59e1eae2f18c96472fca54305015c3bef2..2fd5ec547956e248eafccaa6522210eb4cc7e617 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,18 @@ >+2018-11-29 Chris Dumez <cdumez@apple.com> >+ >+ Add initial support for 'Cross-Origin-Opener-Policy' HTTP header >+ https://bugs.webkit.org/show_bug.cgi?id=192193 >+ <rdar://problem/42013525> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add layout test coverage. >+ >+ * http/tests/security/Cross-Origin-Opener-Policy/cross-origin-opener-policy-basic-expected.txt: Added. >+ * http/tests/security/Cross-Origin-Opener-Policy/cross-origin-opener-policy-basic.html: Added. >+ * http/tests/security/Cross-Origin-Opener-Policy/resources/serve-cross-origin-opener-policy.cgi: Added. >+ * platform/win/TestExpectations: >+ > 2018-11-27 Jiewen Tan <jiewen_tan@apple.com> > > Unreviewed, test gardening >diff --git a/LayoutTests/http/tests/security/Cross-Origin-Opener-Policy/cross-origin-opener-policy-basic-expected.txt b/LayoutTests/http/tests/security/Cross-Origin-Opener-Policy/cross-origin-opener-policy-basic-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..2a65d699fa4ceeb7649301443df2d28ccbd122eb >--- /dev/null >+++ b/LayoutTests/http/tests/security/Cross-Origin-Opener-Policy/cross-origin-opener-policy-basic-expected.txt >@@ -0,0 +1,31 @@ >+Tests that 'Cross-Origin-Opener-Policy: same-origin / same-site' isolates openee from opener. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+w = window.open('http://localhost:8000/security/Cross-Origin-Opener-Policy/resources/serve-cross-origin-opener-policy.cgi?policy=same-origin', 'same-origin') >+PASS w.closed is false >+PASS w.opener is this >+PASS w.location.href is "about:blank" >+PASS w.closed became true >+PASS w.closed is true >+PASS w.opener is null >+PASS w.location.href is "about:blank" >+ w2 = window.open('', 'same-origin') >+PASS w === w2 is false >+PASS w2.location.href is "about:blank" >+w = window.open('http://localhost:8000/security/Cross-Origin-Opener-Policy/resources/serve-cross-origin-opener-policy.cgi?policy=same-site', 'same-site') >+PASS w.closed is false >+PASS w.opener is this >+PASS w.location.href is "about:blank" >+PASS w.closed became true >+PASS w.closed is true >+PASS w.opener is null >+PASS w.location.href is "about:blank" >+ w2 = window.open('', 'same-site') >+PASS w === w2 is false >+PASS w2.location.href is "about:blank" >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/http/tests/security/Cross-Origin-Opener-Policy/cross-origin-opener-policy-basic.html b/LayoutTests/http/tests/security/Cross-Origin-Opener-Policy/cross-origin-opener-policy-basic.html >new file mode 100644 >index 0000000000000000000000000000000000000000..c6c37258e15b1c78e3266ed1946cb28ab10cc15a >--- /dev/null >+++ b/LayoutTests/http/tests/security/Cross-Origin-Opener-Policy/cross-origin-opener-policy-basic.html >@@ -0,0 +1,48 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<script src="/js-test-resources/js-test.js"></script> >+</head> >+<body> >+<script> >+description("Tests that 'Cross-Origin-Opener-Policy: same-origin / same-site' isolates openee from opener."); >+jsTestIsAsync = true; >+ >+if (window.testRunner) >+ testRunner.setCanOpenWindows(); >+ >+function runCrossOriginOpenerPolicyTest(_headerValue) >+{ >+ headerValue = _headerValue; >+ return new Promise(function (resolve) { >+ evalAndLog("w = window.open('http://localhost:8000/security/Cross-Origin-Opener-Policy/resources/serve-cross-origin-opener-policy.cgi?policy=" + headerValue + "', '" + headerValue + "')"); >+ shouldBeFalse("w.closed"); >+ shouldBe("w.opener", "this"); >+ shouldBeEqualToString("w.location.href", "about:blank"); >+ >+ // w will eventually get closed as the new window is navigated to a page protected by 'Cross-Origin-Opener-Policy: same-site | same-origin'. >+ shouldBecomeEqual("w.closed", "true", () => { >+ shouldBeTrue("w.closed"); >+ shouldBeNull("w.opener"); >+ shouldBeEqualToString("w.location.href", "about:blank"); >+ >+ // It should not be possible to look-up the isolated window by name. >+ evalAndLog(" w2 = window.open('', '" + headerValue + "')"); >+ shouldBeFalse("w === w2"); >+ shouldBeEqualToString("w2.location.href", "about:blank"); >+ >+ resolve(); >+ }); >+ }); >+} >+ >+onload = () => { >+ runCrossOriginOpenerPolicyTest("same-origin").then(() => { >+ runCrossOriginOpenerPolicyTest("same-site").then(() => { >+ finishJSTest(); >+ }); >+ }); >+}; >+</script> >+</body> >+</html> >diff --git a/LayoutTests/http/tests/security/Cross-Origin-Opener-Policy/resources/serve-cross-origin-opener-policy.cgi b/LayoutTests/http/tests/security/Cross-Origin-Opener-Policy/resources/serve-cross-origin-opener-policy.cgi >new file mode 100755 >index 0000000000000000000000000000000000000000..76833857b00c200324db689bf125cc0344c8bbe1 >--- /dev/null >+++ b/LayoutTests/http/tests/security/Cross-Origin-Opener-Policy/resources/serve-cross-origin-opener-policy.cgi >@@ -0,0 +1,12 @@ >+#!/usr/bin/perl -wT >+use strict; >+ >+use CGI qw(:standard); >+my $query = new CGI; >+my $policy = $query->param('policy'); >+ >+print "Content-Type: text/html\n"; >+print "Cache-Control: no-cache, no-store\n"; >+print "Cross-Origin-Opener-Policy: $policy\n\n"; >+ >+print "<p>TEST</p>\n"; >diff --git a/LayoutTests/platform/win/TestExpectations b/LayoutTests/platform/win/TestExpectations >index 85b51380434c977b100285d8b2d41f6fe68c068a..422a5b19811c05b6ec5d6a46be234821383fcc59 100644 >--- a/LayoutTests/platform/win/TestExpectations >+++ b/LayoutTests/platform/win/TestExpectations >@@ -4235,6 +4235,9 @@ webkit.org/b/190520 editing/pasteboard/copy-paste-across-shadow-boundaries-with- > # WebGPU is not supported on Windows > webgpu [ Skip ] > >+# There is currently no API to enable this feature on Windows. >+http/tests/security/Cross-Origin-Opener-Policy [ Skip ] >+ > webkit.org/b/191194 fast/block/basic/inline-content-with-floating-image.html [ Failure ] > webkit.org/b/191194 fast/block/basic/inline-content-with-floating-images2.html [ Failure ] > webkit.org/b/191194 fast/dom/inline-event-attributes-release.html [ Failure ]
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 192193
:
356095
|
356103
|
356115
|
356182
|
356185
|
356196
|
356213
|
433910
|
433976
|
434029
|
434047
|
434127
|
434134
|
434136
|
434288
|
434317
|
434433
|
434436
|
434468
|
434660