OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> | 2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> |
3 * 1999 Lars Knoll <knoll@kde.org> | 3 * 1999 Lars Knoll <knoll@kde.org> |
4 * 1999 Antti Koivisto <koivisto@kde.org> | 4 * 1999 Antti Koivisto <koivisto@kde.org> |
5 * 2000 Simon Hausmann <hausmann@kde.org> | 5 * 2000 Simon Hausmann <hausmann@kde.org> |
6 * 2000 Stefan Schimanski <1Stein@gmx.de> | 6 * 2000 Stefan Schimanski <1Stein@gmx.de> |
7 * 2001 George Staikos <staikos@kde.org> | 7 * 2001 George Staikos <staikos@kde.org> |
8 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ights reserved. | 8 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ights reserved. |
9 * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com> | 9 * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com> |
10 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 10 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 return client; | 143 return client; |
144 } | 144 } |
145 | 145 |
146 ChromeClient& Frame::chromeClient() const | 146 ChromeClient& Frame::chromeClient() const |
147 { | 147 { |
148 if (Page* page = this->page()) | 148 if (Page* page = this->page()) |
149 return page->chrome().client(); | 149 return page->chrome().client(); |
150 return emptyChromeClient(); | 150 return emptyChromeClient(); |
151 } | 151 } |
152 | 152 |
| 153 Frame* Frame::findFrameForNavigation(const AtomicString& name, Frame& activeFram
e) |
| 154 { |
| 155 Frame* frame = tree().find(name); |
| 156 if (!frame || !activeFrame.canNavigate(*frame)) |
| 157 return nullptr; |
| 158 return frame; |
| 159 } |
| 160 |
| 161 static bool canAccessAncestor(const SecurityOrigin& activeSecurityOrigin, const
Frame* targetFrame) |
| 162 { |
| 163 // targetFrame can be 0 when we're trying to navigate a top-level frame |
| 164 // that has a 0 opener. |
| 165 if (!targetFrame) |
| 166 return false; |
| 167 |
| 168 const bool isLocalActiveOrigin = activeSecurityOrigin.isLocal(); |
| 169 for (const Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame
= ancestorFrame->tree().parent()) { |
| 170 const SecurityOrigin* ancestorSecurityOrigin = ancestorFrame->securityCo
ntext()->securityOrigin(); |
| 171 if (activeSecurityOrigin.canAccess(ancestorSecurityOrigin)) |
| 172 return true; |
| 173 |
| 174 // Allow file URL descendant navigation even when allowFileAccessFromFil
eURLs is false. |
| 175 // FIXME: It's a bit strange to special-case local origins here. Should
we be doing |
| 176 // something more general instead? |
| 177 if (isLocalActiveOrigin && ancestorSecurityOrigin->isLocal()) |
| 178 return true; |
| 179 } |
| 180 |
| 181 return false; |
| 182 } |
| 183 |
| 184 bool Frame::canNavigate(const Frame& targetFrame) |
| 185 { |
| 186 // Frame-busting is generally allowed, but blocked for sandboxed frames lack
ing the 'allow-top-navigation' flag. |
| 187 if (!securityContext()->isSandboxed(SandboxTopNavigation) && targetFrame ==
tree().top()) |
| 188 return true; |
| 189 |
| 190 if (securityContext()->isSandboxed(SandboxNavigation)) { |
| 191 if (targetFrame.tree().isDescendantOf(this)) |
| 192 return true; |
| 193 |
| 194 const char* reason = "The frame attempting navigation is sandboxed, and
is therefore disallowed from navigating its ancestors."; |
| 195 if (securityContext()->isSandboxed(SandboxTopNavigation) && targetFrame
== tree().top()) |
| 196 reason = "The frame attempting navigation of the top-level window is
sandboxed, but the 'allow-top-navigation' flag is not set."; |
| 197 |
| 198 printNavigationErrorMessage(targetFrame, reason); |
| 199 return false; |
| 200 } |
| 201 |
| 202 ASSERT(securityContext()->securityOrigin()); |
| 203 SecurityOrigin& origin = *securityContext()->securityOrigin(); |
| 204 |
| 205 // This is the normal case. A document can navigate its decendant frames, |
| 206 // or, more generally, a document can navigate a frame if the document is |
| 207 // in the same origin as any of that frame's ancestors (in the frame |
| 208 // hierarchy). |
| 209 // |
| 210 // See http://www.adambarth.com/papers/2008/barth-jackson-mitchell.pdf for |
| 211 // historical information about this security check. |
| 212 if (canAccessAncestor(origin, &targetFrame)) |
| 213 return true; |
| 214 |
| 215 // Top-level frames are easier to navigate than other frames because they |
| 216 // display their URLs in the address bar (in most browsers). However, there |
| 217 // are still some restrictions on navigation to avoid nuisance attacks. |
| 218 // Specifically, a document can navigate a top-level frame if that frame |
| 219 // opened the document or if the document is the same-origin with any of |
| 220 // the top-level frame's opener's ancestors (in the frame hierarchy). |
| 221 // |
| 222 // In both of these cases, the document performing the navigation is in |
| 223 // some way related to the frame being navigate (e.g., by the "opener" |
| 224 // and/or "parent" relation). Requiring some sort of relation prevents a |
| 225 // document from navigating arbitrary, unrelated top-level frames. |
| 226 if (!targetFrame.tree().parent()) { |
| 227 if (targetFrame == client()->opener()) |
| 228 return true; |
| 229 if (canAccessAncestor(origin, targetFrame.client()->opener())) |
| 230 return true; |
| 231 } |
| 232 |
| 233 printNavigationErrorMessage(targetFrame, "The frame attempting navigation is
neither same-origin with the target, nor is it the target's parent or opener.")
; |
| 234 return false; |
| 235 } |
| 236 |
| 237 Frame* Frame::findUnsafeParentScrollPropagationBoundary() |
| 238 { |
| 239 Frame* currentFrame = this; |
| 240 Frame* ancestorFrame = tree().parent(); |
| 241 |
| 242 while (ancestorFrame) { |
| 243 if (!ancestorFrame->securityContext()->securityOrigin()->canAccess(secur
ityContext()->securityOrigin())) |
| 244 return currentFrame; |
| 245 currentFrame = ancestorFrame; |
| 246 ancestorFrame = ancestorFrame->tree().parent(); |
| 247 } |
| 248 return nullptr; |
| 249 } |
| 250 |
153 RenderPart* Frame::ownerRenderer() const | 251 RenderPart* Frame::ownerRenderer() const |
154 { | 252 { |
155 if (!deprecatedLocalOwner()) | 253 if (!deprecatedLocalOwner()) |
156 return nullptr; | 254 return nullptr; |
157 RenderObject* object = deprecatedLocalOwner()->renderer(); | 255 RenderObject* object = deprecatedLocalOwner()->renderer(); |
158 if (!object) | 256 if (!object) |
159 return nullptr; | 257 return nullptr; |
160 // FIXME: If <object> is ever fixed to disassociate itself from frames | 258 // FIXME: If <object> is ever fixed to disassociate itself from frames |
161 // that it has started but canceled, then this can turn into an ASSERT | 259 // that it has started but canceled, then this can turn into an ASSERT |
162 // since ownerElement() would be 0 when the load is canceled. | 260 // since ownerElement() would be 0 when the load is canceled. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 | 301 |
204 if (m_owner) { | 302 if (m_owner) { |
205 if (m_owner->isLocal()) | 303 if (m_owner->isLocal()) |
206 toHTMLFrameOwnerElement(m_owner)->setContentFrame(*this); | 304 toHTMLFrameOwnerElement(m_owner)->setContentFrame(*this); |
207 } else { | 305 } else { |
208 page()->setMainFrame(this); | 306 page()->setMainFrame(this); |
209 } | 307 } |
210 } | 308 } |
211 | 309 |
212 } // namespace blink | 310 } // namespace blink |
OLD | NEW |