Allow navigations in subframes to get a ShouldOpenExternalURLsPolicy of "ShouldAllow".
<rdar://problem/22485589> and https://bugs.webkit.org/show_bug.cgi?id=174178
Reviewed by Alex Christensen.
Source/WebCore:
Test: loader/navigation-policy/should-open-external-urls/subframe-navigated-programatically-by-main-frame.html
This patch introduces a new flag to FrameLoadRequest to track when it is known with certainty that a
FrameLoadRequest originates from the main frame.
Later, when calculating the final ShouldOpenExternalURLsPolicy, main frames navigating iframes get to propagate
their permissions to the iframe.
* bindings/js/CommonVM.cpp:
(WebCore::lexicalFrameFromCommonVM): Helper to grab the current frame associated with the current JS callstack.
* bindings/js/CommonVM.h:
* inspector/InspectorFrontendClientLocal.cpp:
(WebCore::InspectorFrontendClientLocal::openInNewTab):
* inspector/InspectorPageAgent.cpp:
(WebCore::InspectorPageAgent::navigate):
Add the new flag to FrameLoadRequest (and force almost everybody to explicitly include the flag):
* loader/FrameLoadRequest.cpp:
(WebCore::FrameLoadRequest::FrameLoadRequest):
* loader/FrameLoadRequest.h:
(WebCore::FrameLoadRequest::FrameLoadRequest):
(WebCore::FrameLoadRequest::navigationInitiatedByMainFrame):
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::urlSelected):
(WebCore::FrameLoader::loadURLIntoChildFrame):
(WebCore::shouldOpenExternalURLsPolicyToApply): Helper that takes the new flag into account when deciding
what the final ShouldOpenExternalURLsPolicy will be.
(WebCore::applyShouldOpenExternalURLsPolicyToNewDocumentLoader):
(WebCore::FrameLoader::loadURL):
(WebCore::FrameLoader::load):
(WebCore::FrameLoader::loadWithNavigationAction):
(WebCore::FrameLoader::reloadWithOverrideEncoding):
(WebCore::FrameLoader::reload):
(WebCore::FrameLoader::loadPostRequest):
(WebCore::FrameLoader::continueLoadAfterNewWindowPolicy):
(WebCore::FrameLoader::loadDifferentDocumentItem):
(WebCore::createWindow):
(WebCore::FrameLoader::applyShouldOpenExternalURLsPolicyToNewDocumentLoader): Deleted.
* loader/FrameLoader.h:
* loader/FrameLoaderTypes.h:
* loader/NavigationAction.h:
(WebCore::NavigationAction::navigationInitiatedByMainFrame):
* loader/NavigationScheduler.cpp:
(WebCore::ScheduledNavigation::ScheduledNavigation): Grab the "initiating frame" at the time the
ScheduledNavigation is created, as it dictates the policy we decide later.
(WebCore::ScheduledNavigation::navigationInitiatedByMainFrame):
(WebCore::NavigationScheduler::scheduleLocationChange):
* page/ContextMenuController.cpp:
(WebCore::openNewWindow):
(WebCore::ContextMenuController::contextMenuItemSelected):
* page/DOMWindow.cpp:
(WebCore::DOMWindow::createWindow):
Source/WebKit/ios:
Adopt to the new constructor for FrameLoadRequest.
* WebView/WebPDFViewPlaceholder.mm:
(-[WebPDFViewPlaceholder simulateClickOnLinkToURL:]):
Source/WebKit/mac:
Adopt to the new constructor for FrameLoadRequest.
* WebView/WebPDFView.mm:
(-[WebPDFView PDFViewWillClickOnLink:withURL:]):
Source/WebKit/win:
Adopt to the new constructor for FrameLoadRequest.
* Plugins/PluginView.cpp:
(WebCore::PluginView::start):
(WebCore::PluginView::getURLNotify):
(WebCore::PluginView::getURL):
(WebCore::PluginView::handlePost):
Source/WebKit2:
Adopt to the new constructor for FrameLoadRequest.
* WebProcess/Plugins/PluginView.cpp:
(WebKit::PluginView::loadURL):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchCreatePage):
* WebProcess/WebPage/WebInspector.cpp:
(WebKit::WebInspector::openInNewTab):
LayoutTests:
Added a new explicit test and updated expectations for an old one.
* loader/navigation-policy/should-open-external-urls/resources/main-frame-with-subframe-main-programatically-navigates-subframe.html: Added.
* loader/navigation-policy/should-open-external-urls/subframe-click-target-self-expected.txt:
* loader/navigation-policy/should-open-external-urls/subframe-navigated-programatically-by-main-frame-expected.txt: Added.
* loader/navigation-policy/should-open-external-urls/subframe-navigated-programatically-by-main-frame.html: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@219170 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/loader/NavigationScheduler.cpp b/Source/WebCore/loader/NavigationScheduler.cpp
index b41a54f..3bcb1a5 100644
--- a/Source/WebCore/loader/NavigationScheduler.cpp
+++ b/Source/WebCore/loader/NavigationScheduler.cpp
@@ -33,6 +33,7 @@
#include "NavigationScheduler.h"
#include "BackForwardController.h"
+#include "CommonVM.h"
#include "DOMWindow.h"
#include "DocumentLoader.h"
#include "Event.h"
@@ -79,6 +80,10 @@
, m_userGestureToForward(UserGestureIndicator::currentUserGesture())
, m_shouldOpenExternalURLsPolicy(externalURLPolicy)
{
+ if (auto* frame = lexicalFrameFromCommonVM()) {
+ if (frame->isMainFrame())
+ m_navigationInitiatedByMainFrame = NavigationInitiatedByMainFrame::Yes;
+ }
}
virtual ~ScheduledNavigation() { }
@@ -98,6 +103,7 @@
protected:
void clearUserGesture() { m_userGestureToForward = nullptr; }
ShouldOpenExternalURLsPolicy shouldOpenExternalURLs() const { return m_shouldOpenExternalURLsPolicy; }
+ NavigationInitiatedByMainFrame navigationInitiatedByMainFrame() const { return m_navigationInitiatedByMainFrame; };
private:
double m_delay;
@@ -107,6 +113,7 @@
bool m_isLocationChange;
RefPtr<UserGestureToken> m_userGestureToForward;
ShouldOpenExternalURLsPolicy m_shouldOpenExternalURLsPolicy { ShouldOpenExternalURLsPolicy::ShouldNotAllow };
+ NavigationInitiatedByMainFrame m_navigationInitiatedByMainFrame { NavigationInitiatedByMainFrame::Unknown };
};
class ScheduledURLNavigation : public ScheduledNavigation {
@@ -125,7 +132,7 @@
UserGestureIndicator gestureIndicator { userGestureToForward() };
ResourceRequest resourceRequest { m_url, m_referrer, UseProtocolCachePolicy };
- FrameLoadRequest frameLoadRequest { m_initiatingDocument.get(), *m_securityOrigin, resourceRequest, "_self", lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, shouldOpenExternalURLs() };
+ FrameLoadRequest frameLoadRequest { m_initiatingDocument.get(), *m_securityOrigin, resourceRequest, "_self", lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, shouldOpenExternalURLs(), navigationInitiatedByMainFrame() };
frame.loader().changeLocation(WTFMove(frameLoadRequest));
}
@@ -186,7 +193,7 @@
bool refresh = equalIgnoringFragmentIdentifier(frame.document()->url(), url());
ResourceRequest resourceRequest { url(), referrer(), refresh ? ReloadIgnoringCacheData : UseProtocolCachePolicy };
- FrameLoadRequest frameLoadRequest { initiatingDocument(), *securityOrigin(), resourceRequest, "_self", lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Allow, shouldOpenExternalURLs() };
+ FrameLoadRequest frameLoadRequest { initiatingDocument(), *securityOrigin(), resourceRequest, "_self", lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Allow, shouldOpenExternalURLs(), navigationInitiatedByMainFrame() };
frame.loader().changeLocation(WTFMove(frameLoadRequest));
}
@@ -202,7 +209,8 @@
UserGestureIndicator gestureIndicator { userGestureToForward() };
ResourceRequest resourceRequest { url(), referrer(), UseProtocolCachePolicy };
- FrameLoadRequest frameLoadRequest { initiatingDocument(), *securityOrigin(), resourceRequest, "_self", lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Allow, shouldOpenExternalURLs() };
+ FrameLoadRequest frameLoadRequest { initiatingDocument(), *securityOrigin(), resourceRequest, "_self", lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Allow, shouldOpenExternalURLs(), navigationInitiatedByMainFrame() };
+
frame.loader().changeLocation(WTFMove(frameLoadRequest));
}
};
@@ -219,7 +227,8 @@
UserGestureIndicator gestureIndicator { userGestureToForward() };
ResourceRequest resourceRequest { url(), referrer(), ReloadIgnoringCacheData };
- FrameLoadRequest frameLoadRequest { initiatingDocument(), *securityOrigin(), resourceRequest, "_self", lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, shouldOpenExternalURLs() };
+ FrameLoadRequest frameLoadRequest { initiatingDocument(), *securityOrigin(), resourceRequest, "_self", lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, shouldOpenExternalURLs(), navigationInitiatedByMainFrame() };
+
frame.loader().changeLocation(WTFMove(frameLoadRequest));
}
};
@@ -271,7 +280,7 @@
auto& requestingDocument = m_submission->state().sourceDocument();
if (!requestingDocument.canNavigate(&frame))
return;
- FrameLoadRequest frameLoadRequest { requestingDocument, requestingDocument.securityOrigin(), { }, { }, lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, shouldOpenExternalURLs() };
+ FrameLoadRequest frameLoadRequest { requestingDocument, requestingDocument.securityOrigin(), { }, { }, lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, shouldOpenExternalURLs(), navigationInitiatedByMainFrame() };
m_submission->populateFrameLoadRequest(frameLoadRequest);
frame.loader().loadFrameRequest(WTFMove(frameLoadRequest), m_submission->event(), &m_submission->state());
}
@@ -321,7 +330,7 @@
SubstituteData replacementData { SharedBuffer::create(), m_originDocument.url(), replacementResponse, SubstituteData::SessionHistoryVisibility::Hidden };
ResourceRequest resourceRequest { m_originDocument.url(), emptyString(), ReloadIgnoringCacheData };
- FrameLoadRequest frameLoadRequest { m_originDocument, m_originDocument.securityOrigin(), resourceRequest, { }, lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, shouldOpenExternalURLs() };
+ FrameLoadRequest frameLoadRequest { m_originDocument, m_originDocument.securityOrigin(), resourceRequest, { }, lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, shouldOpenExternalURLs(), navigationInitiatedByMainFrame() };
frameLoadRequest.setSubstituteData(replacementData);
frame.loader().load(WTFMove(frameLoadRequest));
}
@@ -420,7 +429,10 @@
// fragment part, we don't need to schedule the location change.
if (url.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(m_frame.document()->url(), url)) {
ResourceRequest resourceRequest { m_frame.document()->completeURL(url), referrer, UseProtocolCachePolicy };
- FrameLoadRequest frameLoadRequest { initiatingDocument, securityOrigin, resourceRequest, ASCIILiteral("_self"), lockHistory, lockBackForwardList, MaybeSendReferrer, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Allow, initiatingDocument.shouldOpenExternalURLsPolicyToPropagate() };
+ auto* frame = lexicalFrameFromCommonVM();
+ auto navigationInitiatedByMainFrame = frame && frame->isMainFrame() ? NavigationInitiatedByMainFrame::Yes : NavigationInitiatedByMainFrame::Unknown;
+
+ FrameLoadRequest frameLoadRequest { initiatingDocument, securityOrigin, resourceRequest, ASCIILiteral("_self"), lockHistory, lockBackForwardList, MaybeSendReferrer, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Allow, initiatingDocument.shouldOpenExternalURLsPolicyToPropagate(), navigationInitiatedByMainFrame };
loader.changeLocation(WTFMove(frameLoadRequest));
return;
}