Index: third_party/WebKit/Source/core/frame/Frame.cpp |
diff --git a/third_party/WebKit/Source/core/frame/Frame.cpp b/third_party/WebKit/Source/core/frame/Frame.cpp |
index 6fc666a026896c7f746b408538fa0e0ff8d525cd..16a6b5cd051f9eff96e9ca5158dba9aef41566a5 100644 |
--- a/third_party/WebKit/Source/core/frame/Frame.cpp |
+++ b/third_party/WebKit/Source/core/frame/Frame.cpp |
@@ -42,6 +42,7 @@ |
#include "core/layout/LayoutPart.h" |
#include "core/loader/EmptyClients.h" |
#include "core/loader/FrameLoaderClient.h" |
+#include "core/loader/NavigationScheduler.h" |
#include "core/page/FocusController.h" |
#include "core/page/Page.h" |
#include "platform/Histogram.h" |
@@ -168,19 +169,28 @@ bool Frame::canNavigate(const Frame& targetFrame) |
String errorReason; |
bool isAllowedNavigation = canNavigateWithoutFramebusting(targetFrame, errorReason); |
- // Frame-busting is generally allowed, but blocked for sandboxed frames lacking the 'allow-top-navigation' flag. |
if (targetFrame != this && !securityContext()->isSandboxed(SandboxTopNavigation) && targetFrame == tree().top()) { |
DEFINE_STATIC_LOCAL(EnumerationHistogram, framebustHistogram, ("WebCore.Framebust", 4)); |
const unsigned userGestureBit = 0x1; |
const unsigned allowedBit = 0x2; |
unsigned framebustParams = 0; |
UseCounter::count(&targetFrame, UseCounter::TopNavigationFromSubFrame); |
- if (UserGestureIndicator::processingUserGesture()) |
+ bool hasUserGesture = UserGestureIndicator::processingUserGesture(); |
+ if (hasUserGesture) |
framebustParams |= userGestureBit; |
if (isAllowedNavigation) |
framebustParams |= allowedBit; |
framebustHistogram.count(framebustParams); |
- return true; |
+ // Frame-busting used to be generally allowed in most situations, but may now blocked if there is no user gesture. |
+ if (!RuntimeEnabledFeatures::framebustingNeedsSameOriginOrUserGestureEnabled()) |
Mike West
2016/08/31 13:14:48
Is the "same origin" bit accurate? I don't see a s
|
+ return true; |
+ if (hasUserGesture || isAllowedNavigation) |
+ return true; |
+ errorReason = "The frame attempting navigation is targeting its top-level window, but is neither same-origin with its target nor is it processing a user gesture. See https://www.chromestatus.com/features/5851021045661696."; |
+ printNavigationErrorMessage(targetFrame, errorReason.latin1().data()); |
+ if (isLocalFrame()) |
+ toLocalFrame(this)->navigationScheduler().schedulePageBlock(toLocalFrame(this)->document()); |
+ return false; |
} |
if (!isAllowedNavigation && !errorReason.isNull()) |
printNavigationErrorMessage(targetFrame, errorReason.latin1().data()); |
@@ -198,6 +208,10 @@ bool Frame::canNavigateWithoutFramebusting(const Frame& targetFrame, String& rea |
if (targetFrame == targetFrame.tree().top() && targetFrame.tree().top() != tree().top() && !securityContext()->isSandboxed(SandboxPropagatesToAuxiliaryBrowsingContexts)) |
return true; |
+ // Top navigation can be opted-in. |
+ if (!securityContext()->isSandboxed(SandboxTopNavigation) && targetFrame == tree().top()) |
+ return true; |
+ |
// Otherwise, block the navigation. |
if (securityContext()->isSandboxed(SandboxTopNavigation) && targetFrame == tree().top()) |
reason = "The frame attempting navigation of the top-level window is sandboxed, but the 'allow-top-navigation' flag is not set."; |