Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(825)

Unified Diff: Source/core/frame/Frame.cpp

Issue 799923006: Make canNavigate() OOPI-friendly (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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())

Powered by Google App Engine
This is Rietveld 408576698