Index: Source/core/frame/Frame.cpp |
diff --git a/Source/core/frame/Frame.cpp b/Source/core/frame/Frame.cpp |
index cc04f692752cab7a1c1c01af6fb82ed9b16099d9..4cd7ea533647736ac97d5fd05b8c68c72ba1cb9e 100644 |
--- a/Source/core/frame/Frame.cpp |
+++ b/Source/core/frame/Frame.cpp |
@@ -150,6 +150,108 @@ ChromeClient& Frame::chromeClient() const |
return emptyChromeClient(); |
} |
+Frame* Frame::findFrameForNavigation(const AtomicString& name, Frame* activeFrame) |
+{ |
+ ASSERT(activeFrame); |
+ Frame* frame = tree().find(name); |
dcheng
2014/12/13 01:55:48
Not really related to this patch, but I wonder if
Nate Chapin
2014/12/20 00:09:14
That's an interesting question for the future.
|
+ if (!frame || !activeFrame->canNavigate(*frame)) |
+ return 0; |
dcheng
2014/12/13 01:55:48
nullptr
Nate Chapin
2014/12/20 00:09:14
Done.
|
+ return frame; |
+} |
+ |
+static bool canAccessAncestor(const SecurityOrigin& activeSecurityOrigin, const Frame* targetFrame) |
+{ |
+ // targetFrame can be 0 when we're trying to navigate a top-level frame |
+ // that has a 0 opener. |
+ if (!targetFrame) |
+ return false; |
+ |
+ const bool isLocalActiveOrigin = activeSecurityOrigin.isLocal(); |
+ for (const Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree().parent()) { |
+ const SecurityOrigin* ancestorSecurityOrigin = ancestorFrame->securityContext()->securityOrigin(); |
+ if (activeSecurityOrigin.canAccess(ancestorSecurityOrigin)) |
+ return true; |
+ |
+ // Allow file URL descendant navigation even when allowFileAccessFromFileURLs is false. |
+ // FIXME: It's a bit strange to special-case local origins here. Should we be doing |
+ // something more general instead? |
+ if (isLocalActiveOrigin && ancestorSecurityOrigin->isLocal()) |
+ return true; |
+ } |
+ |
+ return false; |
+} |
+ |
+bool Frame::canNavigate(const Frame& targetFrame) |
+{ |
+ // Frame-busting is generally allowed, but blocked for sandboxed frames lacking the 'allow-top-navigation' flag. |
+ if (!securityContext()->isSandboxed(SandboxTopNavigation) && targetFrame == tree().top()) |
+ return true; |
+ |
+ if (securityContext()->isSandboxed(SandboxNavigation)) { |
+ if (targetFrame.tree().isDescendantOf(this)) |
+ return true; |
+ |
+ const char* reason = "The frame attempting navigation is sandboxed, and is therefore disallowed from navigating its ancestors."; |
+ 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."; |
+ |
+ printNavigationErrorMessage(targetFrame, reason); |
+ return false; |
+ } |
+ |
+ ASSERT(securityContext()->securityOrigin()); |
+ SecurityOrigin& origin = *securityContext()->securityOrigin(); |
+ |
+ // This is the normal case. A document can navigate its decendant frames, |
+ // or, more generally, a document can navigate a frame if the document is |
+ // in the same origin as any of that frame's ancestors (in the frame |
+ // hierarchy). |
+ // |
+ // See http://www.adambarth.com/papers/2008/barth-jackson-mitchell.pdf for |
+ // historical information about this security check. |
+ if (canAccessAncestor(origin, &targetFrame)) |
+ return true; |
+ |
+ // Top-level frames are easier to navigate than other frames because they |
+ // display their URLs in the address bar (in most browsers). However, there |
+ // are still some restrictions on navigation to avoid nuisance attacks. |
+ // Specifically, a document can navigate a top-level frame if that frame |
+ // opened the document or if the document is the same-origin with any of |
+ // the top-level frame's opener's ancestors (in the frame hierarchy). |
+ // |
+ // In both of these cases, the document performing the navigation is in |
+ // some way related to the frame being navigate (e.g., by the "opener" |
+ // and/or "parent" relation). Requiring some sort of relation prevents a |
+ // document from navigating arbitrary, unrelated top-level frames. |
+ if (!targetFrame.tree().parent()) { |
+ if (targetFrame == client()->opener()) |
+ return true; |
+ if (canAccessAncestor(origin, targetFrame.client()->opener())) |
+ return true; |
+ } |
+ |
+ printNavigationErrorMessage(targetFrame, "The frame attempting navigation is neither same-origin with the target, nor is it the target's parent or opener."); |
+ return false; |
+} |
+ |
+LocalFrame* Document::findUnsafeParentScrollPropagationBoundary() |
+{ |
+ LocalFrame* currentFrame = m_frame; |
+ Frame* ancestorFrame = currentFrame->tree().parent(); |
+ |
+ while (ancestorFrame) { |
+ // FIXME: We don't yet have access to a RemoteFrame's security origin. |
dcheng
2014/12/13 01:55:48
Should we fix this while we're here?
Nate Chapin
2014/12/20 00:09:14
Done. Also, moved this function to frame, changed
|
+ if (!ancestorFrame->isLocalFrame()) |
+ return currentFrame; |
+ if (!toLocalFrame(ancestorFrame)->document()->securityOrigin()->canAccess(securityOrigin())) |
+ return currentFrame; |
+ currentFrame = toLocalFrame(ancestorFrame); |
+ ancestorFrame = ancestorFrame->tree().parent(); |
+ } |
+ return 0; |
dcheng
2014/12/13 01:55:48
nullptr
Nate Chapin
2014/12/20 00:09:14
Done.
|
+} |
+ |
RenderPart* Frame::ownerRenderer() const |
{ |
if (!deprecatedLocalOwner()) |