OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv
ed. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv
ed. |
3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
4 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) | 4 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) |
5 * Copyright (C) 2008 Alp Toker <alp@atoker.com> | 5 * Copyright (C) 2008 Alp Toker <alp@atoker.com> |
6 * Copyright (C) Research In Motion Limited 2009. All rights reserved. | 6 * Copyright (C) Research In Motion Limited 2009. All rights reserved. |
7 * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com> | 7 * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com> |
8 * Copyright (C) 2011 Google Inc. All rights reserved. | 8 * Copyright (C) 2011 Google Inc. All rights reserved. |
9 * | 9 * |
10 * Redistribution and use in source and binary forms, with or without | 10 * Redistribution and use in source and binary forms, with or without |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 m_suppressOpenerInNewFrame = false; | 286 m_suppressOpenerInNewFrame = false; |
287 } | 287 } |
288 | 288 |
289 void FrameLoader::submitForm(PassRefPtr<FormSubmission> submission) | 289 void FrameLoader::submitForm(PassRefPtr<FormSubmission> submission) |
290 { | 290 { |
291 ASSERT(submission->method() == FormSubmission::PostMethod || submission->met
hod() == FormSubmission::GetMethod); | 291 ASSERT(submission->method() == FormSubmission::PostMethod || submission->met
hod() == FormSubmission::GetMethod); |
292 | 292 |
293 // FIXME: Find a good spot for these. | 293 // FIXME: Find a good spot for these. |
294 ASSERT(submission->data()); | 294 ASSERT(submission->data()); |
295 ASSERT(submission->state()); | 295 ASSERT(submission->state()); |
296 ASSERT(submission->state()->sourceFrame() == m_frame); | 296 ASSERT(!submission->state()->sourceDocument()->frame() || submission->state(
)->sourceDocument()->frame() == m_frame); |
297 | 297 |
298 if (!m_frame->page()) | 298 if (!m_frame->page()) |
299 return; | 299 return; |
300 | 300 |
301 if (submission->action().isEmpty()) | 301 if (submission->action().isEmpty()) |
302 return; | 302 return; |
303 | 303 |
304 if (isDocumentSandboxed(m_frame, SandboxForms)) | 304 if (isDocumentSandboxed(m_frame, SandboxForms)) |
305 return; | 305 return; |
306 | 306 |
307 if (protocolIsJavaScript(submission->action())) { | 307 if (protocolIsJavaScript(submission->action())) { |
308 m_isExecutingJavaScriptFormAction = true; | 308 m_isExecutingJavaScriptFormAction = true; |
309 m_frame->script()->executeIfJavaScriptURL(submission->action(), DoNotRep
laceDocumentIfJavaScriptURL); | 309 m_frame->script()->executeIfJavaScriptURL(submission->action(), DoNotRep
laceDocumentIfJavaScriptURL); |
310 m_isExecutingJavaScriptFormAction = false; | 310 m_isExecutingJavaScriptFormAction = false; |
311 return; | 311 return; |
312 } | 312 } |
313 | 313 |
314 Frame* targetFrame = m_frame->tree()->find(submission->target()); | 314 Frame* targetFrame = m_frame->tree()->find(submission->target()); |
315 if (!shouldAllowNavigation(targetFrame)) | 315 if (!submission->state()->sourceDocument()->canNavigate(targetFrame)) |
316 return; | 316 return; |
317 if (!targetFrame) { | 317 if (!targetFrame) { |
318 if (!DOMWindow::allowPopUp(m_frame) && !ScriptController::processingUser
Gesture()) | 318 if (!DOMWindow::allowPopUp(m_frame) && !ScriptController::processingUser
Gesture()) |
319 return; | 319 return; |
320 | 320 |
321 targetFrame = m_frame; | 321 targetFrame = m_frame; |
322 } else | 322 } else |
323 submission->clearTarget(); | 323 submission->clearTarget(); |
324 | 324 |
325 if (!targetFrame->page()) | 325 if (!targetFrame->page()) |
(...skipping 837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1163 else | 1163 else |
1164 loadType = FrameLoadTypeStandard; | 1164 loadType = FrameLoadTypeStandard; |
1165 | 1165 |
1166 if (request.resourceRequest().httpMethod() == "POST") | 1166 if (request.resourceRequest().httpMethod() == "POST") |
1167 loadPostRequest(request.resourceRequest(), referrer, request.frameName()
, lockHistory, loadType, event, formState.get()); | 1167 loadPostRequest(request.resourceRequest(), referrer, request.frameName()
, lockHistory, loadType, event, formState.get()); |
1168 else | 1168 else |
1169 loadURL(request.resourceRequest().url(), referrer, request.frameName(),
lockHistory, loadType, event, formState.get()); | 1169 loadURL(request.resourceRequest().url(), referrer, request.frameName(),
lockHistory, loadType, event, formState.get()); |
1170 | 1170 |
1171 // FIXME: It's possible this targetFrame will not be the same frame that was
targeted by the actual | 1171 // FIXME: It's possible this targetFrame will not be the same frame that was
targeted by the actual |
1172 // load if frame names have changed. | 1172 // load if frame names have changed. |
1173 Frame* sourceFrame = formState ? formState->sourceFrame() : m_frame; | 1173 Frame* sourceFrame = formState ? formState->sourceDocument()->frame() : m_fr
ame; |
| 1174 if (!sourceFrame) |
| 1175 sourceFrame = m_frame; |
1174 Frame* targetFrame = sourceFrame->loader()->findFrameForNavigation(request.f
rameName()); | 1176 Frame* targetFrame = sourceFrame->loader()->findFrameForNavigation(request.f
rameName()); |
1175 if (targetFrame && targetFrame != sourceFrame) { | 1177 if (targetFrame && targetFrame != sourceFrame) { |
1176 if (Page* page = targetFrame->page()) | 1178 if (Page* page = targetFrame->page()) |
1177 page->chrome()->focus(); | 1179 page->chrome()->focus(); |
1178 } | 1180 } |
1179 } | 1181 } |
1180 | 1182 |
1181 void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const Stri
ng& frameName, bool lockHistory, FrameLoadType newLoadType, | 1183 void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const Stri
ng& frameName, bool lockHistory, FrameLoadType newLoadType, |
1182 PassRefPtr<Event> event, PassRefPtr<FormState> prpFormState) | 1184 PassRefPtr<Event> event, PassRefPtr<FormState> prpFormState) |
1183 { | 1185 { |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1489 | 1491 |
1490 // If we're about to re-post, set up action so the application can warn the
user. | 1492 // If we're about to re-post, set up action so the application can warn the
user. |
1491 if (request.httpMethod() == "POST") | 1493 if (request.httpMethod() == "POST") |
1492 loader->setTriggeringAction(NavigationAction(request, NavigationTypeForm
Resubmitted)); | 1494 loader->setTriggeringAction(NavigationAction(request, NavigationTypeForm
Resubmitted)); |
1493 | 1495 |
1494 loader->setOverrideEncoding(m_documentLoader->overrideEncoding()); | 1496 loader->setOverrideEncoding(m_documentLoader->overrideEncoding()); |
1495 | 1497 |
1496 loadWithDocumentLoader(loader.get(), endToEndReload ? FrameLoadTypeReloadFro
mOrigin : FrameLoadTypeReload, 0); | 1498 loadWithDocumentLoader(loader.get(), endToEndReload ? FrameLoadTypeReloadFro
mOrigin : FrameLoadTypeReload, 0); |
1497 } | 1499 } |
1498 | 1500 |
1499 static bool canAccessAncestor(const SecurityOrigin* activeSecurityOrigin, Frame*
targetFrame) | |
1500 { | |
1501 // targetFrame can be NULL when we're trying to navigate a top-level frame | |
1502 // that has a NULL opener. | |
1503 if (!targetFrame) | |
1504 return false; | |
1505 | |
1506 const bool isLocalActiveOrigin = activeSecurityOrigin->isLocal(); | |
1507 for (Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ance
storFrame->tree()->parent()) { | |
1508 Document* ancestorDocument = ancestorFrame->document(); | |
1509 if (!ancestorDocument) | |
1510 return true; | |
1511 | |
1512 const SecurityOrigin* ancestorSecurityOrigin = ancestorDocument->securit
yOrigin(); | |
1513 if (activeSecurityOrigin->canAccess(ancestorSecurityOrigin)) | |
1514 return true; | |
1515 | |
1516 // Allow file URL descendant navigation even when allowFileAccessFromFil
eURLs is false. | |
1517 if (isLocalActiveOrigin && ancestorSecurityOrigin->isLocal()) | |
1518 return true; | |
1519 } | |
1520 | |
1521 return false; | |
1522 } | |
1523 | |
1524 bool FrameLoader::shouldAllowNavigation(Frame* targetFrame) const | |
1525 { | |
1526 // The navigation change is safe if the active frame is: | |
1527 // - in the same security origin as the target or one of the target's | |
1528 // ancestors. | |
1529 // | |
1530 // Or the target frame is: | |
1531 // - a top-level frame in the frame hierarchy and the active frame can | |
1532 // navigate the target frame's opener per above or it is the opener of | |
1533 // the target frame. | |
1534 | |
1535 if (!targetFrame) | |
1536 return true; | |
1537 | |
1538 // Performance optimization. | |
1539 if (m_frame == targetFrame) | |
1540 return true; | |
1541 | |
1542 // Let a frame navigate the top-level window that contains it. This is | |
1543 // important to allow because it lets a site "frame-bust" (escape from a | |
1544 // frame created by another web site). | |
1545 if (!isDocumentSandboxed(m_frame, SandboxTopNavigation) && targetFrame == m_
frame->tree()->top()) | |
1546 return true; | |
1547 | |
1548 // A sandboxed frame can only navigate itself and its descendants. | |
1549 if (isDocumentSandboxed(m_frame, SandboxNavigation) && !targetFrame->tree()-
>isDescendantOf(m_frame)) | |
1550 return false; | |
1551 | |
1552 // Let a frame navigate its opener if the opener is a top-level window. | |
1553 if (!targetFrame->tree()->parent() && m_frame->loader()->opener() == targetF
rame) | |
1554 return true; | |
1555 | |
1556 Document* activeDocument = m_frame->document(); | |
1557 ASSERT(activeDocument); | |
1558 const SecurityOrigin* activeSecurityOrigin = activeDocument->securityOrigin(
); | |
1559 | |
1560 // For top-level windows, check the opener. | |
1561 if (!targetFrame->tree()->parent() && canAccessAncestor(activeSecurityOrigin
, targetFrame->loader()->opener())) | |
1562 return true; | |
1563 | |
1564 // In general, check the frame's ancestors. | |
1565 if (canAccessAncestor(activeSecurityOrigin, targetFrame)) | |
1566 return true; | |
1567 | |
1568 Document* targetDocument = targetFrame->document(); | |
1569 // FIXME: this error message should contain more specifics of why the naviga
tion change is not allowed. | |
1570 String message = "Unsafe JavaScript attempt to initiate a navigation change
for frame with URL " + | |
1571 targetDocument->url().string() + " from frame with URL " +
activeDocument->url().string() + ".\n"; | |
1572 | |
1573 // FIXME: should we print to the console of the activeFrame as well? | |
1574 targetFrame->domWindow()->printErrorMessage(message); | |
1575 | |
1576 return false; | |
1577 } | |
1578 | |
1579 void FrameLoader::stopAllLoaders(ClearProvisionalItemPolicy clearProvisionalItem
Policy) | 1501 void FrameLoader::stopAllLoaders(ClearProvisionalItemPolicy clearProvisionalItem
Policy) |
1580 { | 1502 { |
1581 ASSERT(!m_frame->document() || !m_frame->document()->inPageCache()); | 1503 ASSERT(!m_frame->document() || !m_frame->document()->inPageCache()); |
1582 if (m_pageDismissalEventBeingDispatched != NoDismissal) | 1504 if (m_pageDismissalEventBeingDispatched != NoDismissal) |
1583 return; | 1505 return; |
1584 | 1506 |
1585 // If this method is called from within this method, infinite recursion can
occur (3442218). Avoid this. | 1507 // If this method is called from within this method, infinite recursion can
occur (3442218). Avoid this. |
1586 if (m_inStopAllLoaders) | 1508 if (m_inStopAllLoaders) |
1587 return; | 1509 return; |
1588 | 1510 |
(...skipping 1458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3047 | 2969 |
3048 if (!m_didPerformFirstNavigation && page->backForward()->currentItem() && !p
age->backForward()->backItem() && !page->backForward()->forwardItem()) { | 2970 if (!m_didPerformFirstNavigation && page->backForward()->currentItem() && !p
age->backForward()->backItem() && !page->backForward()->forwardItem()) { |
3049 m_didPerformFirstNavigation = true; | 2971 m_didPerformFirstNavigation = true; |
3050 m_client->didPerformFirstNavigation(); | 2972 m_client->didPerformFirstNavigation(); |
3051 } | 2973 } |
3052 } | 2974 } |
3053 | 2975 |
3054 Frame* FrameLoader::findFrameForNavigation(const AtomicString& name) | 2976 Frame* FrameLoader::findFrameForNavigation(const AtomicString& name) |
3055 { | 2977 { |
3056 Frame* frame = m_frame->tree()->find(name); | 2978 Frame* frame = m_frame->tree()->find(name); |
3057 if (!shouldAllowNavigation(frame)) | 2979 // FIXME: We calling canNavigate on the Document that's requesting the |
| 2980 // navigation, not based on the document that happens to be displayed in |
| 2981 // this Frame. |
| 2982 if (!m_frame->document()->canNavigate(frame)) |
3058 return 0; | 2983 return 0; |
3059 return frame; | 2984 return frame; |
3060 } | 2985 } |
3061 | 2986 |
3062 void FrameLoader::loadSameDocumentItem(HistoryItem* item) | 2987 void FrameLoader::loadSameDocumentItem(HistoryItem* item) |
3063 { | 2988 { |
3064 ASSERT(item->documentSequenceNumber() == history()->currentItem()->documentS
equenceNumber()); | 2989 ASSERT(item->documentSequenceNumber() == history()->currentItem()->documentS
equenceNumber()); |
3065 | 2990 |
3066 // Save user view state to the current history item here since we don't do a
normal load. | 2991 // Save user view state to the current history item here since we don't do a
normal load. |
3067 // FIXME: Does form state need to be saved here too? | 2992 // FIXME: Does form state need to be saved here too? |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3310 { | 3235 { |
3311 return true; | 3236 return true; |
3312 } | 3237 } |
3313 | 3238 |
3314 Frame* createWindow(Frame* openerFrame, Frame* lookupFrame, const FrameLoadReque
st& request, const WindowFeatures& features, bool& created) | 3239 Frame* createWindow(Frame* openerFrame, Frame* lookupFrame, const FrameLoadReque
st& request, const WindowFeatures& features, bool& created) |
3315 { | 3240 { |
3316 ASSERT(!features.dialog || request.frameName().isEmpty()); | 3241 ASSERT(!features.dialog || request.frameName().isEmpty()); |
3317 | 3242 |
3318 if (!request.frameName().isEmpty() && request.frameName() != "_blank") { | 3243 if (!request.frameName().isEmpty() && request.frameName() != "_blank") { |
3319 Frame* frame = lookupFrame->tree()->find(request.frameName()); | 3244 Frame* frame = lookupFrame->tree()->find(request.frameName()); |
3320 if (frame && openerFrame->loader()->shouldAllowNavigation(frame)) { | 3245 if (frame && openerFrame->document()->canNavigate(frame)) { |
3321 if (Page* page = frame->page()) | 3246 if (Page* page = frame->page()) |
3322 page->chrome()->focus(); | 3247 page->chrome()->focus(); |
3323 created = false; | 3248 created = false; |
3324 return frame; | 3249 return frame; |
3325 } | 3250 } |
3326 } | 3251 } |
3327 | 3252 |
3328 // Sandboxed frames cannot open new auxiliary browsing contexts. | 3253 // Sandboxed frames cannot open new auxiliary browsing contexts. |
3329 if (isDocumentSandboxed(openerFrame, SandboxPopups)) | 3254 if (isDocumentSandboxed(openerFrame, SandboxPopups)) |
3330 return 0; | 3255 return 0; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3372 windowRect.setHeight(features.height + (windowRect.height() - pageSize.h
eight())); | 3297 windowRect.setHeight(features.height + (windowRect.height() - pageSize.h
eight())); |
3373 page->chrome()->setWindowRect(windowRect); | 3298 page->chrome()->setWindowRect(windowRect); |
3374 | 3299 |
3375 page->chrome()->show(); | 3300 page->chrome()->show(); |
3376 | 3301 |
3377 created = true; | 3302 created = true; |
3378 return frame; | 3303 return frame; |
3379 } | 3304 } |
3380 | 3305 |
3381 } // namespace WebCore | 3306 } // namespace WebCore |
OLD | NEW |