1 /* 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 4 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 5 * Copyright (C) 2008 Alp Toker <alp (at) atoker.com> 6 * Copyright (C) Research In Motion Limited 2009. All rights reserved. 7 * Copyright (C) 2011 Kris Jordan <krisjordan (at) gmail.com> 8 * Copyright (C) 2011 Google Inc. All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 20 * its contributors may be used to endorse or promote products derived 21 * from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include "config.h" 36 #include "core/loader/FrameLoader.h" 37 38 #include "HTMLNames.h" 39 #include "bindings/v8/DOMWrapperWorld.h" 40 #include "bindings/v8/ScriptController.h" 41 #include "bindings/v8/SerializedScriptValue.h" 42 #include "core/dom/BeforeUnloadEvent.h" 43 #include "core/dom/Document.h" 44 #include "core/dom/Element.h" 45 #include "core/dom/Event.h" 46 #include "core/dom/EventNames.h" 47 #include "core/dom/PageTransitionEvent.h" 48 #include "core/editing/Editor.h" 49 #include "core/history/BackForwardController.h" 50 #include "core/history/HistoryItem.h" 51 #include "core/html/HTMLFormElement.h" 52 #include "core/html/HTMLInputElement.h" 53 #include "core/html/HTMLObjectElement.h" 54 #include "core/html/parser/HTMLParserIdioms.h" 55 #include "core/inspector/InspectorController.h" 56 #include "core/inspector/InspectorInstrumentation.h" 57 #include "core/loader/DocumentLoadTiming.h" 58 #include "core/loader/DocumentLoader.h" 59 #include "core/loader/FormState.h" 60 #include "core/loader/FormSubmission.h" 61 #include "core/loader/FrameLoadRequest.h" 62 #include "core/loader/FrameLoaderClient.h" 63 #include "core/loader/IconController.h" 64 #include "core/loader/ProgressTracker.h" 65 #include "core/loader/ResourceLoader.h" 66 #include "core/loader/UniqueIdentifier.h" 67 #include "core/loader/appcache/ApplicationCacheHost.h" 68 #include "core/loader/cache/ResourceFetcher.h" 69 #include "core/page/Chrome.h" 70 #include "core/page/ChromeClient.h" 71 #include "core/page/ContentSecurityPolicy.h" 72 #include "core/page/ContentSecurityPolicyResponseHeaders.h" 73 #include "core/page/DOMWindow.h" 74 #include "core/page/EventHandler.h" 75 #include "core/page/Frame.h" 76 #include "core/page/FrameTree.h" 77 #include "core/page/FrameView.h" 78 #include "core/page/Page.h" 79 #include "core/page/Settings.h" 80 #include "core/page/WindowFeatures.h" 81 #include "core/platform/Logging.h" 82 #include "core/platform/ScrollAnimator.h" 83 #include "core/platform/graphics/FloatRect.h" 84 #include "core/platform/network/HTTPParsers.h" 85 #include "core/platform/network/ResourceRequest.h" 86 #include "core/xml/parser/XMLDocumentParser.h" 87 #include "modules/webdatabase/DatabaseManager.h" 88 #include "weborigin/SecurityOrigin.h" 89 #include "weborigin/SecurityPolicy.h" 90 #include "wtf/TemporaryChange.h" 91 #include "wtf/text/CString.h" 92 #include "wtf/text/WTFString.h" 93 94 namespace WebCore { 95 96 using namespace HTMLNames; 97 98 static const char defaultAcceptHeader[] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; 99 100 bool isBackForwardLoadType(FrameLoadType type) 101 { 102 return type == FrameLoadTypeBackForward; 103 } 104 105 // This is not in the FrameLoader class to emphasize that it does not depend on 106 // private FrameLoader data, and to avoid increasing the number of public functions 107 // with access to private data. Since only this .cpp file needs it, making it 108 // non-member lets us exclude it from the header file, thus keeping core/loader/FrameLoader.h's 109 // API simpler. 110 // 111 static bool isDocumentSandboxed(Frame* frame, SandboxFlags mask) 112 { 113 return frame->document() && frame->document()->isSandboxed(mask); 114 } 115 116 class FrameLoader::FrameProgressTracker { 117 public: 118 static PassOwnPtr<FrameProgressTracker> create(Frame* frame) { return adoptPtr(new FrameProgressTracker(frame)); } 119 ~FrameProgressTracker() 120 { 121 ASSERT(!m_inProgress || m_frame->page()); 122 if (m_inProgress) 123 m_frame->page()->progress()->progressCompleted(m_frame); 124 } 125 126 void progressStarted() 127 { 128 ASSERT(m_frame->page()); 129 if (!m_inProgress) 130 m_frame->page()->progress()->progressStarted(m_frame); 131 m_inProgress = true; 132 } 133 134 void progressCompleted() 135 { 136 ASSERT(m_inProgress); 137 ASSERT(m_frame->page()); 138 m_inProgress = false; 139 m_frame->page()->progress()->progressCompleted(m_frame); 140 } 141 142 private: 143 FrameProgressTracker(Frame* frame) 144 : m_frame(frame) 145 , m_inProgress(false) 146 { 147 } 148 149 Frame* m_frame; 150 bool m_inProgress; 151 }; 152 153 FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client) 154 : m_frame(frame) 155 , m_client(client) 156 , m_history(frame) 157 , m_notifer(frame) 158 , m_icon(adoptPtr(new IconController(frame))) 159 , m_mixedContentChecker(frame) 160 , m_state(FrameStateProvisional) 161 , m_loadType(FrameLoadTypeStandard) 162 , m_inStopAllLoaders(false) 163 , m_pageDismissalEventBeingDispatched(NoDismissal) 164 , m_isComplete(false) 165 , m_containsPlugins(false) 166 , m_needsClear(false) 167 , m_checkTimer(this, &FrameLoader::checkTimerFired) 168 , m_shouldCallCheckCompleted(false) 169 , m_shouldCallCheckLoadComplete(false) 170 , m_opener(0) 171 , m_didAccessInitialDocument(false) 172 , m_didAccessInitialDocumentTimer(this, &FrameLoader::didAccessInitialDocumentTimerFired) 173 , m_suppressOpenerInNewFrame(false) 174 , m_startingClientRedirect(false) 175 , m_forcedSandboxFlags(SandboxNone) 176 , m_hasAllowedNavigationViaBeforeUnloadConfirmationPanel(false) 177 { 178 } 179 180 FrameLoader::~FrameLoader() 181 { 182 setOpener(0); 183 184 HashSet<Frame*>::iterator end = m_openedFrames.end(); 185 for (HashSet<Frame*>::iterator it = m_openedFrames.begin(); it != end; ++it) 186 (*it)->loader()->m_opener = 0; 187 188 m_client->frameLoaderDestroyed(); 189 } 190 191 void FrameLoader::init() 192 { 193 // This somewhat odd set of steps gives the frame an initial empty document. 194 m_provisionalDocumentLoader = m_client->createDocumentLoader(ResourceRequest(KURL(ParsedURLString, emptyString())), SubstituteData()); 195 m_provisionalDocumentLoader->setFrame(m_frame); 196 m_provisionalDocumentLoader->startLoadingMainResource(); 197 m_frame->document()->cancelParsing(); 198 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument); 199 m_progressTracker = FrameProgressTracker::create(m_frame); 200 } 201 202 void FrameLoader::setDefersLoading(bool defers) 203 { 204 if (m_documentLoader) 205 m_documentLoader->setDefersLoading(defers); 206 if (m_provisionalDocumentLoader) 207 m_provisionalDocumentLoader->setDefersLoading(defers); 208 if (m_policyDocumentLoader) 209 m_policyDocumentLoader->setDefersLoading(defers); 210 history()->setDefersLoading(defers); 211 212 if (!defers) { 213 m_frame->navigationScheduler()->startTimer(); 214 startCheckCompleteTimer(); 215 } 216 } 217 218 void FrameLoader::submitForm(PassRefPtr<FormSubmission> submission) 219 { 220 ASSERT(submission->method() == FormSubmission::PostMethod || submission->method() == FormSubmission::GetMethod); 221 222 // FIXME: Find a good spot for these. 223 ASSERT(submission->data()); 224 ASSERT(submission->state()); 225 ASSERT(!submission->state()->sourceDocument()->frame() || submission->state()->sourceDocument()->frame() == m_frame); 226 227 if (!m_frame->page()) 228 return; 229 230 if (submission->action().isEmpty()) 231 return; 232 233 if (isDocumentSandboxed(m_frame, SandboxForms)) { 234 // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists. 235 m_frame->document()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Blocked form submission to '" + submission->action().elidedString() + "' because the form's frame is sandboxed and the 'allow-forms' permission is not set."); 236 return; 237 } 238 239 if (protocolIsJavaScript(submission->action())) { 240 if (!m_frame->document()->contentSecurityPolicy()->allowFormAction(KURL(submission->action()))) 241 return; 242 m_frame->script()->executeScriptIfJavaScriptURL(submission->action()); 243 return; 244 } 245 246 Frame* targetFrame = findFrameForNavigation(submission->target(), submission->state()->sourceDocument()); 247 if (!targetFrame) { 248 if (!DOMWindow::allowPopUp(m_frame) && !ScriptController::processingUserGesture()) 249 return; 250 251 targetFrame = m_frame; 252 } else 253 submission->clearTarget(); 254 255 if (!targetFrame->page()) 256 return; 257 258 // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way. 259 260 // We do not want to submit more than one form from the same page, nor do we want to submit a single 261 // form more than once. This flag prevents these from happening; not sure how other browsers prevent this. 262 // The flag is reset in each time we start handle a new mouse or key down event, and 263 // also in setView since this part may get reused for a page from the back/forward cache. 264 // The form multi-submit logic here is only needed when we are submitting a form that affects this frame. 265 266 // FIXME: Frame targeting is only one of the ways the submission could end up doing something other 267 // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly 268 // needed any more now that we reset m_submittedFormURL on each mouse or key down event. 269 270 if (m_frame->tree()->isDescendantOf(targetFrame)) { 271 if (m_submittedFormURL == submission->requestURL()) 272 return; 273 m_submittedFormURL = submission->requestURL(); 274 } 275 276 submission->setReferrer(outgoingReferrer()); 277 submission->setOrigin(outgoingOrigin()); 278 279 targetFrame->navigationScheduler()->scheduleFormSubmission(submission); 280 } 281 282 void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy) 283 { 284 if (m_frame->document() && m_frame->document()->parser()) 285 m_frame->document()->parser()->stopParsing(); 286 287 if (unloadEventPolicy != UnloadEventPolicyNone) { 288 if (m_frame->document()) { 289 if (m_frame->document()->unloadEventStillNeeded()) { 290 m_frame->document()->unloadEventStarted(); 291 Element* currentFocusedElement = m_frame->document()->focusedElement(); 292 if (currentFocusedElement && currentFocusedElement->hasTagName(inputTag)) 293 toHTMLInputElement(currentFocusedElement)->endEditing(); 294 if (m_pageDismissalEventBeingDispatched == NoDismissal) { 295 if (unloadEventPolicy == UnloadEventPolicyUnloadAndPageHide) { 296 m_pageDismissalEventBeingDispatched = PageHideDismissal; 297 m_frame->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, false), m_frame->document()); 298 } 299 RefPtr<Event> unloadEvent(Event::create(eventNames().unloadEvent, false, false)); 300 // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed 301 // while dispatching the event, so protect it to prevent writing the end 302 // time into freed memory. 303 RefPtr<DocumentLoader> documentLoader = m_provisionalDocumentLoader; 304 m_pageDismissalEventBeingDispatched = UnloadDismissal; 305 if (documentLoader && !documentLoader->timing()->unloadEventStart() && !documentLoader->timing()->unloadEventEnd()) { 306 DocumentLoadTiming* timing = documentLoader->timing(); 307 ASSERT(timing->navigationStart()); 308 timing->markUnloadEventStart(); 309 m_frame->domWindow()->dispatchEvent(unloadEvent, m_frame->document()); 310 timing->markUnloadEventEnd(); 311 } else { 312 m_frame->domWindow()->dispatchEvent(unloadEvent, m_frame->document()); 313 } 314 } 315 m_pageDismissalEventBeingDispatched = NoDismissal; 316 if (m_frame->document()) { 317 m_frame->document()->updateStyleIfNeeded(); 318 m_frame->document()->unloadEventWasHandled(); 319 } 320 } 321 } 322 323 // Dispatching the unload event could have made m_frame->document() null. 324 if (m_frame->document()) { 325 // Don't remove event listeners from a transitional empty document (see bug 28716 for more information). 326 bool keepEventListeners = m_stateMachine.isDisplayingInitialEmptyDocument() && m_provisionalDocumentLoader 327 && m_frame->document()->isSecureTransitionTo(m_provisionalDocumentLoader->url()); 328 329 if (!keepEventListeners) 330 m_frame->document()->removeAllEventListeners(); 331 } 332 } 333 334 m_isComplete = true; // to avoid calling completed() in finishedParsing() 335 336 if (m_frame->document() && m_frame->document()->parsing()) { 337 finishedParsing(); 338 m_frame->document()->setParsing(false); 339 } 340 341 if (Document* doc = m_frame->document()) { 342 // FIXME: HTML5 doesn't tell us to set the state to complete when aborting, but we do anyway to match legacy behavior. 343 // http://www.w3.org/Bugs/Public/show_bug.cgi?id=10537 344 doc->setReadyState(Document::Complete); 345 346 // FIXME: Should the DatabaseManager watch for something like ActiveDOMObject::stop() rather than being special-cased here? 347 DatabaseManager::manager().stopDatabases(doc, 0); 348 } 349 350 // FIXME: This will cancel redirection timer, which really needs to be restarted when restoring the frame from b/f cache. 351 m_frame->navigationScheduler()->cancel(); 352 } 353 354 void FrameLoader::stop() 355 { 356 // http://bugs.webkit.org/show_bug.cgi?id=10854 357 // The frame's last ref may be removed and it will be deleted by checkCompleted(). 358 RefPtr<Frame> protector(m_frame); 359 360 if (DocumentParser* parser = m_frame->document()->parser()) { 361 parser->stopParsing(); 362 parser->finish(); 363 } 364 } 365 366 bool FrameLoader::closeURL() 367 { 368 history()->saveDocumentState(); 369 370 // Should only send the pagehide event here if the current document exists. 371 Document* currentDocument = m_frame->document(); 372 stopLoading(currentDocument ? UnloadEventPolicyUnloadAndPageHide : UnloadEventPolicyUnloadOnly); 373 374 m_frame->editor()->clearUndoRedoOperations(); 375 return true; 376 } 377 378 void FrameLoader::didExplicitOpen() 379 { 380 m_isComplete = false; 381 382 // Calling document.open counts as committing the first real document load. 383 if (!m_stateMachine.committedFirstRealDocumentLoad()) 384 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit); 385 386 // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results 387 // from a subsequent window.document.open / window.document.write call. 388 // Canceling redirection here works for all cases because document.open 389 // implicitly precedes document.write. 390 m_frame->navigationScheduler()->cancel(); 391 } 392 393 void FrameLoader::cancelAndClear() 394 { 395 m_frame->navigationScheduler()->cancel(); 396 397 if (!m_isComplete) 398 closeURL(); 399 400 clear(ClearScriptObjects | ClearWindowObject); 401 } 402 403 void FrameLoader::clear(ClearOptions options) 404 { 405 m_frame->editor()->clear(); 406 407 if (!m_needsClear) 408 return; 409 m_needsClear = false; 410 411 m_frame->document()->cancelParsing(); 412 m_frame->document()->stopActiveDOMObjects(); 413 if (m_frame->document()->attached()) { 414 m_frame->document()->prepareForDestruction(); 415 m_frame->document()->removeFocusedElementOfSubtree(m_frame->document()); 416 } 417 418 // Do this after detaching the document so that the unload event works. 419 if (options & ClearWindowProperties) { 420 InspectorInstrumentation::frameWindowDiscarded(m_frame, m_frame->domWindow()); 421 m_frame->domWindow()->reset(); 422 m_frame->script()->clearWindowShell(); 423 } 424 425 m_frame->selection()->prepareForDestruction(); 426 m_frame->eventHandler()->clear(); 427 if (m_frame->view()) 428 m_frame->view()->clear(); 429 430 if (options & ClearWindowObject) { 431 // Do not drop the DOMWindow (and Document) before the ScriptController and view are cleared 432 // as some destructors might still try to access the document. 433 m_frame->setDOMWindow(0); 434 } 435 436 m_containsPlugins = false; 437 438 if (options & ClearScriptObjects) 439 m_frame->script()->clearScriptObjects(); 440 441 m_frame->script()->enableEval(); 442 443 m_frame->navigationScheduler()->clear(); 444 445 m_checkTimer.stop(); 446 m_shouldCallCheckCompleted = false; 447 m_shouldCallCheckLoadComplete = false; 448 449 if (m_stateMachine.isDisplayingInitialEmptyDocument() && m_stateMachine.committedFirstRealDocumentLoad()) 450 m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad); 451 } 452 453 void FrameLoader::receivedFirstData() 454 { 455 if (m_stateMachine.creatingInitialEmptyDocument()) 456 return; 457 458 dispatchDidCommitLoad(); 459 dispatchDidClearWindowObjectsInAllWorlds(); 460 461 if (m_documentLoader) { 462 StringWithDirection ptitle = m_documentLoader->title(); 463 // If we have a title let the WebView know about it. 464 if (!ptitle.isNull()) 465 m_client->dispatchDidReceiveTitle(ptitle); 466 } 467 } 468 469 void FrameLoader::setOutgoingReferrer(const KURL& url) 470 { 471 m_outgoingReferrer = url.strippedForUseAsReferrer(); 472 } 473 474 void FrameLoader::didBeginDocument(bool dispatch) 475 { 476 m_needsClear = true; 477 m_isComplete = false; 478 m_frame->document()->setReadyState(Document::Loading); 479 480 if (history()->currentItem() && m_loadType == FrameLoadTypeBackForward) 481 m_frame->document()->statePopped(history()->currentItem()->stateObject()); 482 483 if (dispatch) 484 dispatchDidClearWindowObjectsInAllWorlds(); 485 486 m_frame->document()->initContentSecurityPolicy(m_documentLoader ? ContentSecurityPolicyResponseHeaders(m_documentLoader->response()) : ContentSecurityPolicyResponseHeaders()); 487 488 Settings* settings = m_frame->document()->settings(); 489 if (settings) { 490 m_frame->document()->fetcher()->setImagesEnabled(settings->areImagesEnabled()); 491 m_frame->document()->fetcher()->setAutoLoadImages(settings->loadsImagesAutomatically()); 492 } 493 494 if (m_documentLoader) { 495 String dnsPrefetchControl = m_documentLoader->response().httpHeaderField("X-DNS-Prefetch-Control"); 496 if (!dnsPrefetchControl.isEmpty()) 497 m_frame->document()->parseDNSPrefetchControlHeader(dnsPrefetchControl); 498 499 String headerContentLanguage = m_documentLoader->response().httpHeaderField("Content-Language"); 500 if (!headerContentLanguage.isEmpty()) { 501 size_t commaIndex = headerContentLanguage.find(','); 502 headerContentLanguage.truncate(commaIndex); // notFound == -1 == don't truncate 503 headerContentLanguage = headerContentLanguage.stripWhiteSpace(isHTMLSpace); 504 if (!headerContentLanguage.isEmpty()) 505 m_frame->document()->setContentLanguage(headerContentLanguage); 506 } 507 } 508 509 history()->restoreDocumentState(); 510 } 511 512 void FrameLoader::finishedParsing() 513 { 514 if (m_stateMachine.creatingInitialEmptyDocument()) 515 return; 516 517 // This can be called from the Frame's destructor, in which case we shouldn't protect ourselves 518 // because doing so will cause us to re-enter the destructor when protector goes out of scope. 519 // Null-checking the FrameView indicates whether or not we're in the destructor. 520 RefPtr<Frame> protector = m_frame->view() ? m_frame : 0; 521 522 m_client->dispatchDidFinishDocumentLoad(); 523 524 checkCompleted(); 525 526 if (!m_frame->view()) 527 return; // We are being destroyed by something checkCompleted called. 528 529 // Check if the scrollbars are really needed for the content. 530 // If not, remove them, relayout, and repaint. 531 m_frame->view()->restoreScrollbar(); 532 scrollToFragmentWithParentBoundary(m_frame->document()->url()); 533 } 534 535 void FrameLoader::loadDone() 536 { 537 checkCompleted(); 538 } 539 540 bool FrameLoader::allChildrenAreComplete() const 541 { 542 for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) { 543 if (!child->loader()->m_isComplete) 544 return false; 545 } 546 return true; 547 } 548 549 bool FrameLoader::allAncestorsAreComplete() const 550 { 551 for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree()->parent()) { 552 if (!ancestor->loader()->m_isComplete) 553 return false; 554 } 555 return true; 556 } 557 558 void FrameLoader::checkCompleted() 559 { 560 RefPtr<Frame> protect(m_frame); 561 m_shouldCallCheckCompleted = false; 562 563 if (m_frame->view()) 564 m_frame->view()->handleLoadCompleted(); 565 566 // Have we completed before? 567 if (m_isComplete) 568 return; 569 570 // Are we still parsing? 571 if (m_frame->document()->parsing()) 572 return; 573 574 // Still waiting for images/scripts? 575 if (m_frame->document()->fetcher()->requestCount()) 576 return; 577 578 // Still waiting for elements that don't go through a FrameLoader? 579 if (m_frame->document()->isDelayingLoadEvent()) 580 return; 581 582 // Any frame that hasn't completed yet? 583 if (!allChildrenAreComplete()) 584 return; 585 586 // OK, completed. 587 m_isComplete = true; 588 m_requestedHistoryItem = 0; 589 m_frame->document()->setReadyState(Document::Complete); 590 if (m_frame->document()->loadEventStillNeeded()) 591 m_frame->document()->implicitClose(); 592 593 m_frame->navigationScheduler()->startTimer(); 594 595 completed(); 596 if (m_frame->page()) 597 checkLoadComplete(); 598 599 if (m_frame->view()) 600 m_frame->view()->handleLoadCompleted(); 601 } 602 603 void FrameLoader::checkTimerFired(Timer<FrameLoader>*) 604 { 605 RefPtr<Frame> protect(m_frame); 606 607 if (Page* page = m_frame->page()) { 608 if (page->defersLoading()) 609 return; 610 } 611 if (m_shouldCallCheckCompleted) 612 checkCompleted(); 613 if (m_shouldCallCheckLoadComplete) 614 checkLoadComplete(); 615 } 616 617 void FrameLoader::startCheckCompleteTimer() 618 { 619 if (!(m_shouldCallCheckCompleted || m_shouldCallCheckLoadComplete)) 620 return; 621 if (m_checkTimer.isActive()) 622 return; 623 m_checkTimer.startOneShot(0); 624 } 625 626 void FrameLoader::scheduleCheckCompleted() 627 { 628 m_shouldCallCheckCompleted = true; 629 startCheckCompleteTimer(); 630 } 631 632 void FrameLoader::scheduleCheckLoadComplete() 633 { 634 m_shouldCallCheckLoadComplete = true; 635 startCheckCompleteTimer(); 636 } 637 638 String FrameLoader::outgoingReferrer() const 639 { 640 // See http://www.whatwg.org/specs/web-apps/current-work/#fetching-resources 641 // for why we walk the parent chain for srcdoc documents. 642 Frame* frame = m_frame; 643 while (frame->document()->isSrcdocDocument()) { 644 frame = frame->tree()->parent(); 645 // Srcdoc documents cannot be top-level documents, by definition, 646 // because they need to be contained in iframes with the srcdoc. 647 ASSERT(frame); 648 } 649 return frame->loader()->m_outgoingReferrer; 650 } 651 652 String FrameLoader::outgoingOrigin() const 653 { 654 return m_frame->document()->securityOrigin()->toString(); 655 } 656 657 bool FrameLoader::checkIfFormActionAllowedByCSP(const KURL& url) const 658 { 659 if (m_submittedFormURL.isEmpty()) 660 return true; 661 662 return m_frame->document()->contentSecurityPolicy()->allowFormAction(url); 663 } 664 665 Frame* FrameLoader::opener() 666 { 667 return m_opener; 668 } 669 670 void FrameLoader::setOpener(Frame* opener) 671 { 672 if (m_opener && !opener) 673 m_client->didDisownOpener(); 674 675 if (m_opener) 676 m_opener->loader()->m_openedFrames.remove(m_frame); 677 if (opener) 678 opener->loader()->m_openedFrames.add(m_frame); 679 m_opener = opener; 680 681 if (m_frame->document()) 682 m_frame->document()->initSecurityContext(); 683 } 684 685 // FIXME: This does not belong in FrameLoader! 686 void FrameLoader::handleFallbackContent() 687 { 688 HTMLFrameOwnerElement* owner = m_frame->ownerElement(); 689 if (!owner || !owner->hasTagName(objectTag)) 690 return; 691 static_cast<HTMLObjectElement*>(owner)->renderFallbackContent(); 692 } 693 694 bool FrameLoader::allowPlugins(ReasonForCallingAllowPlugins reason) 695 { 696 Settings* settings = m_frame->settings(); 697 bool allowed = m_client->allowPlugins(settings && settings->arePluginsEnabled()); 698 if (!allowed && reason == AboutToInstantiatePlugin) 699 m_client->didNotAllowPlugins(); 700 return allowed; 701 } 702 703 void FrameLoader::resetMultipleFormSubmissionProtection() 704 { 705 m_submittedFormURL = KURL(); 706 } 707 708 void FrameLoader::updateForSameDocumentNavigation(const KURL& newURL, SameDocumentNavigationSource sameDocumentNavigationSource, PassRefPtr<SerializedScriptValue> data, const String& title, UpdateBackForwardListPolicy updateBackForwardList) 709 { 710 // Update the data source's request with the new URL to fake the URL change 711 KURL oldURL = m_frame->document()->url(); 712 m_frame->document()->setURL(newURL); 713 setOutgoingReferrer(newURL); 714 documentLoader()->replaceRequestURLForSameDocumentNavigation(newURL); 715 716 // updateBackForwardListForFragmentScroll() must happen after 717 // replaceRequestURLForSameDocumentNavigation(), since we add based on 718 // the current request. 719 if (updateBackForwardList == UpdateBackForwardList) 720 history()->updateBackForwardListForFragmentScroll(); 721 722 if (sameDocumentNavigationSource == SameDocumentNavigationDefault) 723 history()->updateForSameDocumentNavigation(); 724 else if (sameDocumentNavigationSource == SameDocumentNavigationPushState) 725 history()->pushState(data, title, newURL.string()); 726 else if (sameDocumentNavigationSource == SameDocumentNavigationReplaceState) 727 history()->replaceState(data, title, newURL.string()); 728 else 729 ASSERT_NOT_REACHED(); 730 731 // Generate start and stop notifications only when loader is completed so that we 732 // don't fire them for fragment redirection that happens in window.onload handler. 733 // See https://bugs.webkit.org/show_bug.cgi?id=31838 734 if (m_frame->document()->loadEventFinished()) 735 m_client->postProgressStartedNotification(); 736 737 m_documentLoader->clearRedirectChain(); 738 if (m_documentLoader->isClientRedirect()) 739 m_documentLoader->appendRedirect(oldURL); 740 m_documentLoader->appendRedirect(newURL); 741 742 m_client->dispatchDidNavigateWithinPage(); 743 744 if (m_frame->document()->loadEventFinished()) 745 m_client->postProgressFinishedNotification(); 746 } 747 748 void FrameLoader::loadInSameDocument(const KURL& url, PassRefPtr<SerializedScriptValue> stateObject, bool isNewNavigation) 749 { 750 // If we have a state object, we cannot also be a new navigation. 751 ASSERT(!stateObject || (stateObject && !isNewNavigation)); 752 753 KURL oldURL = m_frame->document()->url(); 754 // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor 755 bool hashChange = equalIgnoringFragmentIdentifier(url, oldURL) && url.fragmentIdentifier() != oldURL.fragmentIdentifier(); 756 if (hashChange) { 757 m_frame->eventHandler()->stopAutoscrollTimer(); 758 m_frame->document()->enqueueHashchangeEvent(oldURL, url); 759 } 760 m_documentLoader->setIsClientRedirect((m_startingClientRedirect && !isNewNavigation) || !UserGestureIndicator::processingUserGesture()); 761 m_documentLoader->setReplacesCurrentHistoryItem(!isNewNavigation); 762 UpdateBackForwardListPolicy updateBackForwardList = isNewNavigation && !shouldTreatURLAsSameAsCurrent(url) && !stateObject ? UpdateBackForwardList : DoNotUpdateBackForwardList; 763 updateForSameDocumentNavigation(url, SameDocumentNavigationDefault, 0, String(), updateBackForwardList); 764 765 // It's important to model this as a load that starts and immediately finishes. 766 // Otherwise, the parent frame may think we never finished loading. 767 started(); 768 769 // We need to scroll to the fragment whether or not a hash change occurred, since 770 // the user might have scrolled since the previous navigation. 771 scrollToFragmentWithParentBoundary(url); 772 773 m_isComplete = false; 774 checkCompleted(); 775 776 m_frame->document()->statePopped(stateObject ? stateObject : SerializedScriptValue::nullValue()); 777 } 778 779 bool FrameLoader::isComplete() const 780 { 781 return m_isComplete; 782 } 783 784 void FrameLoader::completed() 785 { 786 RefPtr<Frame> protect(m_frame); 787 788 for (Frame* descendant = m_frame->tree()->traverseNext(m_frame); descendant; descendant = descendant->tree()->traverseNext(m_frame)) 789 descendant->navigationScheduler()->startTimer(); 790 791 if (Frame* parent = m_frame->tree()->parent()) 792 parent->loader()->checkCompleted(); 793 794 if (m_frame->view()) 795 m_frame->view()->maintainScrollPositionAtAnchor(0); 796 } 797 798 void FrameLoader::started() 799 { 800 for (Frame* frame = m_frame; frame; frame = frame->tree()->parent()) 801 frame->loader()->m_isComplete = false; 802 } 803 804 void FrameLoader::prepareForHistoryNavigation() 805 { 806 // If there is no currentItem, but we still want to engage in 807 // history navigation we need to manufacture one, and update 808 // the state machine of this frame to impersonate having 809 // loaded it. 810 RefPtr<HistoryItem> currentItem = history()->currentItem(); 811 if (!currentItem) { 812 insertDummyHistoryItem(); 813 814 ASSERT(stateMachine()->isDisplayingInitialEmptyDocument()); 815 stateMachine()->advanceTo(FrameLoaderStateMachine::StartedFirstRealLoad); 816 stateMachine()->advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit); 817 stateMachine()->advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad); 818 } 819 } 820 821 void FrameLoader::setReferrerForFrameRequest(ResourceRequest& request, ShouldSendReferrer shouldSendReferrer) 822 { 823 if (shouldSendReferrer == NeverSendReferrer) { 824 request.clearHTTPReferrer(); 825 return; 826 } 827 828 String argsReferrer(request.httpReferrer()); 829 if (argsReferrer.isEmpty()) 830 argsReferrer = outgoingReferrer(); 831 String referrer = SecurityPolicy::generateReferrerHeader(m_frame->document()->referrerPolicy(), request.url(), argsReferrer); 832 833 request.setHTTPReferrer(referrer); 834 RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer); 835 addHTTPOriginIfNeeded(request, referrerOrigin->toString()); 836 } 837 838 FrameLoadType FrameLoader::determineFrameLoadType(const FrameLoadRequest& request) 839 { 840 if (m_frame->tree()->parent() && !m_stateMachine.startedFirstRealLoad()) 841 return FrameLoadTypeInitialInChildFrame; 842 if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData) 843 return FrameLoadTypeReload; 844 if (request.lockBackForwardList()) 845 return FrameLoadTypeRedirectWithLockedBackForwardList; 846 if (!request.requester() && shouldTreatURLAsSameAsCurrent(request.resourceRequest().url())) 847 return FrameLoadTypeSame; 848 if (shouldTreatURLAsSameAsCurrent(request.substituteData().failingURL()) && m_loadType == FrameLoadTypeReload) 849 return FrameLoadTypeReload; 850 return FrameLoadTypeStandard; 851 } 852 853 bool FrameLoader::prepareRequestForThisFrame(FrameLoadRequest& request) 854 { 855 // If no SecurityOrigin was specified, skip security checks and assume the caller has fully initialized the FrameLoadRequest. 856 if (!request.requester()) 857 return true; 858 859 KURL url = request.resourceRequest().url(); 860 if (m_frame->script()->executeScriptIfJavaScriptURL(url)) 861 return false; 862 863 if (!request.requester()->canDisplay(url)) { 864 reportLocalLoadFailed(m_frame, url.elidedString()); 865 return false; 866 } 867 868 if (request.requester() && !request.formState() && request.frameName().isEmpty()) 869 request.setFrameName(m_frame->document()->baseTarget()); 870 871 // If the requesting SecurityOrigin is not this Frame's SecurityOrigin, the request was initiated by a different frame that should 872 // have already set the referrer. 873 if (request.requester() == m_frame->document()->securityOrigin()) 874 setReferrerForFrameRequest(request.resourceRequest(), request.shouldSendReferrer()); 875 return true; 876 } 877 878 static bool shouldOpenInNewWindow(Frame* targetFrame, const FrameLoadRequest& request, const NavigationAction& action) 879 { 880 if (!targetFrame && !request.frameName().isEmpty()) 881 return true; 882 if (!request.formState()) 883 return false; 884 NavigationPolicy navigationPolicy = NavigationPolicyCurrentTab; 885 if (!action.specifiesNavigationPolicy(&navigationPolicy)) 886 return false; 887 return navigationPolicy != NavigationPolicyCurrentTab; 888 } 889 890 void FrameLoader::load(const FrameLoadRequest& passedRequest) 891 { 892 ASSERT(!m_suppressOpenerInNewFrame); 893 ASSERT(m_frame->document()); 894 895 // Protect frame from getting blown away inside dispatchBeforeLoadEvent in loadWithDocumentLoader. 896 RefPtr<Frame> protect(m_frame); 897 898 if (m_inStopAllLoaders) 899 return; 900 901 FrameLoadRequest request(passedRequest); 902 if (!prepareRequestForThisFrame(request)) 903 return; 904 905 // The search for a target frame is done earlier in the case of form submission. 906 Frame* targetFrame = request.formState() ? 0 : findFrameForNavigation(request.frameName()); 907 if (targetFrame && targetFrame != m_frame) { 908 request.setFrameName("_self"); 909 targetFrame->loader()->load(request); 910 return; 911 } 912 913 FrameLoadType newLoadType = determineFrameLoadType(request); 914 NavigationAction action(request.resourceRequest(), newLoadType, request.formState(), request.triggeringEvent()); 915 if (shouldOpenInNewWindow(targetFrame, request, action)) { 916 TemporaryChange<bool> changeOpener(m_suppressOpenerInNewFrame, request.shouldSendReferrer() == NeverSendReferrer); 917 checkNewWindowPolicyAndContinue(request.formState(), request.frameName(), action); 918 return; 919 } 920 921 TemporaryChange<bool> changeClientRedirect(m_startingClientRedirect, request.clientRedirect()); 922 if (shouldPerformFragmentNavigation(request.formState(), request.resourceRequest().httpMethod(), newLoadType, request.resourceRequest().url())) { 923 checkNavigationPolicyAndContinueFragmentScroll(action, newLoadType != FrameLoadTypeRedirectWithLockedBackForwardList); 924 return; 925 } 926 bool sameURL = shouldTreatURLAsSameAsCurrent(request.resourceRequest().url()); 927 loadWithNavigationAction(request.resourceRequest(), action, newLoadType, request.formState(), request.substituteData()); 928 // Example of this case are sites that reload the same URL with a different cookie 929 // driving the generated content, or a master frame with links that drive a target 930 // frame, where the user has clicked on the same link repeatedly. 931 if (sameURL && newLoadType != FrameLoadTypeReload && newLoadType != FrameLoadTypeReloadFromOrigin && request.resourceRequest().httpMethod() != "POST") 932 m_loadType = FrameLoadTypeSame; 933 } 934 935 SubstituteData FrameLoader::defaultSubstituteDataForURL(const KURL& url) 936 { 937 if (!shouldTreatURLAsSrcdocDocument(url)) 938 return SubstituteData(); 939 String srcdoc = m_frame->ownerElement()->fastGetAttribute(srcdocAttr); 940 ASSERT(!srcdoc.isNull()); 941 CString encodedSrcdoc = srcdoc.utf8(); 942 return SubstituteData(SharedBuffer::create(encodedSrcdoc.data(), encodedSrcdoc.length()), "text/html", "UTF-8", KURL()); 943 } 944 945 void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url) 946 { 947 ASSERT(!url.isEmpty()); 948 if (!frame) 949 return; 950 951 frame->document()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Not allowed to load local resource: " + url); 952 } 953 954 bool FrameLoader::willLoadMediaElementURL(KURL& url) 955 { 956 ResourceRequest request(url); 957 958 unsigned long identifier; 959 ResourceError error; 960 requestFromDelegate(request, identifier, error); 961 notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, ResourceResponse(url, String(), -1, String(), String()), 0, -1, -1, error); 962 963 url = request.url(); 964 965 return error.isNull(); 966 } 967 968 void FrameLoader::reload(ReloadPolicy reloadPolicy, const KURL& overrideURL, const String& overrideEncoding) 969 { 970 DocumentLoader* documentLoader = activeDocumentLoader(); 971 if (!documentLoader) 972 return; 973 974 if (m_state == FrameStateProvisional) 975 insertDummyHistoryItem(); 976 frame()->loader()->history()->saveDocumentAndScrollState(); 977 978 ResourceRequest request = documentLoader->request(); 979 // FIXME: We need to reset cache policy to prevent it from being incorrectly propagted to the reload. 980 // Do we need to propagate anything other than the url? 981 request.setCachePolicy(UseProtocolCachePolicy); 982 if (!overrideURL.isEmpty()) 983 request.setURL(overrideURL); 984 else if (!documentLoader->unreachableURL().isEmpty()) 985 request.setURL(documentLoader->unreachableURL()); 986 987 FrameLoadType type = reloadPolicy == EndToEndReload ? FrameLoadTypeReloadFromOrigin : FrameLoadTypeReload; 988 NavigationAction action(request, type, request.httpMethod() == "POST"); 989 loadWithNavigationAction(request, action, type, 0, SubstituteData(), overrideEncoding); 990 } 991 992 void FrameLoader::stopAllLoaders(ClearProvisionalItemPolicy clearProvisionalItemPolicy) 993 { 994 if (m_pageDismissalEventBeingDispatched != NoDismissal) 995 return; 996 997 // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this. 998 if (m_inStopAllLoaders) 999 return; 1000 1001 // Calling stopLoading() on the provisional document loader can blow away 1002 // the frame from underneath. 1003 RefPtr<Frame> protect(m_frame); 1004 1005 m_inStopAllLoaders = true; 1006 1007 // If no new load is in progress, we should clear the provisional item from history 1008 // before we call stopLoading. 1009 if (clearProvisionalItemPolicy == ShouldClearProvisionalItem) 1010 history()->setProvisionalItem(0); 1011 1012 for (RefPtr<Frame> child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) 1013 child->loader()->stopAllLoaders(clearProvisionalItemPolicy); 1014 if (m_provisionalDocumentLoader) 1015 m_provisionalDocumentLoader->stopLoading(); 1016 if (m_documentLoader) 1017 m_documentLoader->stopLoading(); 1018 1019 if (m_provisionalDocumentLoader) 1020 m_provisionalDocumentLoader->detachFromFrame(); 1021 m_provisionalDocumentLoader = 0; 1022 1023 m_checkTimer.stop(); 1024 1025 m_inStopAllLoaders = false; 1026 } 1027 1028 void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete) 1029 { 1030 // stopAllLoaders can detach the Frame, so protect it. 1031 RefPtr<Frame> protect(m_frame); 1032 stopAllLoaders(); 1033 1034 if (deferCheckLoadComplete) 1035 scheduleCheckLoadComplete(); 1036 else if (m_frame->page()) 1037 checkLoadComplete(); 1038 } 1039 1040 DocumentLoader* FrameLoader::activeDocumentLoader() const 1041 { 1042 if (m_state == FrameStateProvisional) 1043 return m_provisionalDocumentLoader.get(); 1044 return m_documentLoader.get(); 1045 } 1046 1047 void FrameLoader::didAccessInitialDocument() 1048 { 1049 // We only need to notify the client once, and only for the main frame. 1050 if (isLoadingMainFrame() && !m_didAccessInitialDocument) { 1051 m_didAccessInitialDocument = true; 1052 // Notify asynchronously, since this is called within a JavaScript security check. 1053 m_didAccessInitialDocumentTimer.startOneShot(0); 1054 } 1055 } 1056 1057 void FrameLoader::didAccessInitialDocumentTimerFired(Timer<FrameLoader>*) 1058 { 1059 m_client->didAccessInitialDocument(); 1060 } 1061 1062 void FrameLoader::notifyIfInitialDocumentAccessed() 1063 { 1064 if (m_didAccessInitialDocumentTimer.isActive() 1065 && m_stateMachine.isDisplayingInitialEmptyDocument()) { 1066 m_didAccessInitialDocumentTimer.stop(); 1067 didAccessInitialDocumentTimerFired(0); 1068 } 1069 } 1070 1071 bool FrameLoader::isLoading() const 1072 { 1073 DocumentLoader* docLoader = activeDocumentLoader(); 1074 if (!docLoader) 1075 return false; 1076 return docLoader->isLoading(); 1077 } 1078 1079 void FrameLoader::commitProvisionalLoad() 1080 { 1081 ASSERT(m_client->hasWebView()); 1082 ASSERT(m_state == FrameStateProvisional); 1083 RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader; 1084 RefPtr<Frame> protect(m_frame); 1085 1086 closeOldDataSources(); 1087 1088 // Check if the destination page is allowed to access the previous page's timing information. 1089 if (m_frame->document()) { 1090 RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::create(pdl->request().url()); 1091 pdl->timing()->setHasSameOriginAsPreviousDocument(securityOrigin->canRequest(m_frame->document()->url())); 1092 } 1093 1094 clearAllowNavigationViaBeforeUnloadConfirmationPanel(); 1095 1096 // The call to closeURL() invokes the unload event handler, which can execute arbitrary 1097 // JavaScript. If the script initiates a new load, we need to abandon the current load, 1098 // or the two will stomp each other. 1099 if (m_documentLoader) 1100 closeURL(); 1101 if (pdl != m_provisionalDocumentLoader) 1102 return; 1103 1104 // detachChildren() can trigger this frame's unload event, and therefore 1105 // script can run and do just about anything. For example, an unload event that calls 1106 // document.write("") on its parent frame can lead to a recursive detachChildren() 1107 // invocation for this frame. Leave the loader that is being committed in a temporarily 1108 // detached state, such that it can't be found and cancelled. 1109 RefPtr<DocumentLoader> loaderBeingCommitted = m_provisionalDocumentLoader.release(); 1110 detachChildren(); 1111 if (m_documentLoader) 1112 m_documentLoader->detachFromFrame(); 1113 m_documentLoader = loaderBeingCommitted; 1114 m_state = FrameStateCommittedPage; 1115 1116 if (isLoadingMainFrame()) 1117 m_frame->page()->chrome().client()->needTouchEvents(false); 1118 1119 history()->updateForCommit(); 1120 m_client->transitionToCommittedForNewPage(); 1121 1122 if (!m_stateMachine.creatingInitialEmptyDocument() && !m_stateMachine.committedFirstRealDocumentLoad()) 1123 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit); 1124 1125 // A redirect was scheduled before the first real document was committed. 1126 // This can happen when one frame changes another frame's location. 1127 if (m_frame->navigationScheduler()->redirectScheduledDuringLoad()) 1128 return; 1129 m_frame->navigationScheduler()->cancel(); 1130 m_frame->editor()->clearLastEditCommand(); 1131 1132 // If we are still in the process of initializing an empty document then 1133 // its frame is not in a consistent state for rendering, so avoid setJSStatusBarText 1134 // since it may cause clients to attempt to render the frame. 1135 if (!m_stateMachine.creatingInitialEmptyDocument()) { 1136 DOMWindow* window = m_frame->domWindow(); 1137 window->setStatus(String()); 1138 window->setDefaultStatus(String()); 1139 } 1140 started(); 1141 } 1142 1143 void FrameLoader::closeOldDataSources() 1144 { 1145 // FIXME: Is it important for this traversal to be postorder instead of preorder? 1146 // If so, add helpers for postorder traversal, and use them. If not, then lets not 1147 // use a recursive algorithm here. 1148 for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) 1149 child->loader()->closeOldDataSources(); 1150 1151 if (m_documentLoader) 1152 m_client->dispatchWillClose(); 1153 } 1154 1155 bool FrameLoader::isHostedByObjectElement() const 1156 { 1157 HTMLFrameOwnerElement* owner = m_frame->ownerElement(); 1158 return owner && owner->hasTagName(objectTag); 1159 } 1160 1161 bool FrameLoader::isLoadingMainFrame() const 1162 { 1163 Page* page = m_frame->page(); 1164 return page && m_frame == page->mainFrame(); 1165 } 1166 1167 bool FrameLoader::subframeIsLoading() const 1168 { 1169 // It's most likely that the last added frame is the last to load so we walk backwards. 1170 for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling()) { 1171 FrameLoader* childLoader = child->loader(); 1172 DocumentLoader* documentLoader = childLoader->documentLoader(); 1173 if (documentLoader && documentLoader->isLoadingInAPISense()) 1174 return true; 1175 documentLoader = childLoader->provisionalDocumentLoader(); 1176 if (documentLoader && documentLoader->isLoadingInAPISense()) 1177 return true; 1178 documentLoader = childLoader->policyDocumentLoader(); 1179 if (documentLoader) 1180 return true; 1181 } 1182 return false; 1183 } 1184 1185 FrameLoadType FrameLoader::loadType() const 1186 { 1187 return m_loadType; 1188 } 1189 1190 CachePolicy FrameLoader::subresourceCachePolicy() const 1191 { 1192 if (m_isComplete) 1193 return CachePolicyVerify; 1194 1195 if (m_loadType == FrameLoadTypeReloadFromOrigin) 1196 return CachePolicyReload; 1197 1198 if (Frame* parentFrame = m_frame->tree()->parent()) { 1199 CachePolicy parentCachePolicy = parentFrame->loader()->subresourceCachePolicy(); 1200 if (parentCachePolicy != CachePolicyVerify) 1201 return parentCachePolicy; 1202 } 1203 1204 if (m_loadType == FrameLoadTypeReload) 1205 return CachePolicyRevalidate; 1206 1207 const ResourceRequest& request(documentLoader()->request()); 1208 1209 if (request.cachePolicy() == ReturnCacheDataElseLoad) 1210 return CachePolicyHistoryBuffer; 1211 1212 return CachePolicyVerify; 1213 } 1214 1215 void FrameLoader::checkLoadCompleteForThisFrame() 1216 { 1217 ASSERT(m_client->hasWebView()); 1218 if (m_state != FrameStateCommittedPage) 1219 return; 1220 1221 if (!m_documentLoader || (m_documentLoader->isLoadingInAPISense() && !m_documentLoader->isStopping())) 1222 return; 1223 1224 m_state = FrameStateComplete; 1225 1226 // FIXME: Is this subsequent work important if we already navigated away? 1227 // Maybe there are bugs because of that, or extra work we can skip because 1228 // the new page is ready. 1229 1230 // If the user had a scroll point, scroll to it, overriding the anchor point if any. 1231 if (m_frame->page()) { 1232 if (isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload || m_loadType == FrameLoadTypeReloadFromOrigin) 1233 history()->restoreScrollPositionAndViewState(); 1234 } 1235 1236 if (!m_stateMachine.committedFirstRealDocumentLoad()) 1237 return; 1238 1239 m_progressTracker->progressCompleted(); 1240 if (Page* page = m_frame->page()) { 1241 if (m_frame == page->mainFrame()) 1242 page->resetRelevantPaintedObjectCounter(); 1243 } 1244 1245 const ResourceError& error = m_documentLoader->mainDocumentError(); 1246 if (!error.isNull()) 1247 m_client->dispatchDidFailLoad(error); 1248 else 1249 m_client->dispatchDidFinishLoad(); 1250 m_loadType = FrameLoadTypeStandard; 1251 } 1252 1253 void FrameLoader::didLayout(LayoutMilestones milestones) 1254 { 1255 m_client->dispatchDidLayout(milestones); 1256 } 1257 1258 void FrameLoader::didFirstLayout() 1259 { 1260 if (m_frame->page() && isBackForwardLoadType(m_loadType)) 1261 history()->restoreScrollPositionAndViewState(); 1262 } 1263 1264 void FrameLoader::detachChildren() 1265 { 1266 typedef Vector<RefPtr<Frame> > FrameVector; 1267 FrameVector childrenToDetach; 1268 childrenToDetach.reserveCapacity(m_frame->tree()->childCount()); 1269 for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling()) 1270 childrenToDetach.append(child); 1271 FrameVector::iterator end = childrenToDetach.end(); 1272 for (FrameVector::iterator it = childrenToDetach.begin(); it != end; it++) 1273 (*it)->loader()->detachFromParent(); 1274 } 1275 1276 void FrameLoader::closeAndRemoveChild(Frame* child) 1277 { 1278 child->tree()->detachFromParent(); 1279 1280 child->setView(0); 1281 if (child->ownerElement() && child->page()) 1282 child->page()->decrementSubframeCount(); 1283 child->willDetachPage(); 1284 child->detachFromPage(); 1285 1286 m_frame->tree()->removeChild(child); 1287 } 1288 1289 // Called every time a resource is completely loaded or an error is received. 1290 void FrameLoader::checkLoadComplete() 1291 { 1292 ASSERT(m_client->hasWebView()); 1293 1294 m_shouldCallCheckLoadComplete = false; 1295 1296 // FIXME: Always traversing the entire frame tree is a bit inefficient, but 1297 // is currently needed in order to null out the previous history item for all frames. 1298 if (Page* page = m_frame->page()) { 1299 Vector<RefPtr<Frame>, 10> frames; 1300 for (RefPtr<Frame> frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) 1301 frames.append(frame); 1302 // To process children before their parents, iterate the vector backwards. 1303 for (size_t i = frames.size(); i; --i) 1304 frames[i - 1]->loader()->checkLoadCompleteForThisFrame(); 1305 } 1306 } 1307 1308 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const 1309 { 1310 if (!recurse) 1311 return m_frame->document()->fetcher()->requestCount(); 1312 1313 int count = 0; 1314 for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame)) 1315 count += frame->document()->fetcher()->requestCount(); 1316 return count; 1317 } 1318 1319 String FrameLoader::userAgent(const KURL& url) const 1320 { 1321 String userAgent = m_client->userAgent(url); 1322 InspectorInstrumentation::applyUserAgentOverride(m_frame, &userAgent); 1323 return userAgent; 1324 } 1325 1326 void FrameLoader::frameDetached() 1327 { 1328 // stopAllLoaders can detach the Frame, so protect it. 1329 RefPtr<Frame> protect(m_frame); 1330 stopAllLoaders(); 1331 m_frame->document()->stopActiveDOMObjects(); 1332 detachFromParent(); 1333 } 1334 1335 void FrameLoader::detachFromParent() 1336 { 1337 // stopAllLoaders can detach the Frame, so protect it. 1338 RefPtr<Frame> protect(m_frame); 1339 1340 closeURL(); 1341 history()->saveScrollPositionAndViewStateToItem(history()->currentItem()); 1342 detachChildren(); 1343 // stopAllLoaders() needs to be called after detachChildren(), because detachedChildren() 1344 // will trigger the unload event handlers of any child frames, and those event 1345 // handlers might start a new subresource load in this frame. 1346 stopAllLoaders(); 1347 1348 InspectorInstrumentation::frameDetachedFromParent(m_frame); 1349 1350 if (m_documentLoader) 1351 m_documentLoader->detachFromFrame(); 1352 m_documentLoader = 0; 1353 m_client->detachedFromParent(); 1354 1355 m_progressTracker.clear(); 1356 1357 if (Frame* parent = m_frame->tree()->parent()) { 1358 parent->loader()->closeAndRemoveChild(m_frame); 1359 parent->loader()->scheduleCheckCompleted(); 1360 } else { 1361 m_frame->setView(0); 1362 m_frame->willDetachPage(); 1363 m_frame->detachFromPage(); 1364 } 1365 } 1366 1367 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request) 1368 { 1369 bool isMainResource = (request.targetType() == ResourceRequest::TargetIsMainFrame) || (request.targetType() == ResourceRequest::TargetIsSubframe); 1370 1371 if (isMainResource && isLoadingMainFrame()) 1372 request.setFirstPartyForCookies(request.url()); 1373 else 1374 request.setFirstPartyForCookies(m_frame->document()->firstPartyForCookies()); 1375 1376 // The remaining modifications are only necessary for HTTP and HTTPS. 1377 if (!request.url().isEmpty() && !request.url().protocolIsInHTTPFamily()) 1378 return; 1379 1380 applyUserAgent(request); 1381 1382 if (request.cachePolicy() == ReloadIgnoringCacheData) { 1383 if (m_loadType == FrameLoadTypeReload) 1384 request.setHTTPHeaderField("Cache-Control", "max-age=0"); 1385 else if (m_loadType == FrameLoadTypeReloadFromOrigin) { 1386 request.setHTTPHeaderField("Cache-Control", "no-cache"); 1387 request.setHTTPHeaderField("Pragma", "no-cache"); 1388 } 1389 } 1390 1391 if (isMainResource) 1392 request.setHTTPAccept(defaultAcceptHeader); 1393 1394 // Make sure we send the Origin header. 1395 addHTTPOriginIfNeeded(request, String()); 1396 } 1397 1398 void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, const String& origin) 1399 { 1400 if (!request.httpOrigin().isEmpty()) 1401 return; // Request already has an Origin header. 1402 1403 // Don't send an Origin header for GET or HEAD to avoid privacy issues. 1404 // For example, if an intranet page has a hyperlink to an external web 1405 // site, we don't want to include the Origin of the request because it 1406 // will leak the internal host name. Similar privacy concerns have lead 1407 // to the widespread suppression of the Referer header at the network 1408 // layer. 1409 if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD") 1410 return; 1411 1412 // For non-GET and non-HEAD methods, always send an Origin header so the 1413 // server knows we support this feature. 1414 1415 if (origin.isEmpty()) { 1416 // If we don't know what origin header to attach, we attach the value 1417 // for an empty origin. 1418 request.setHTTPOrigin(SecurityOrigin::createUnique()->toString()); 1419 return; 1420 } 1421 1422 request.setHTTPOrigin(origin); 1423 } 1424 1425 unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& data) 1426 { 1427 ASSERT(m_frame->document()); 1428 String referrer = SecurityPolicy::generateReferrerHeader(m_frame->document()->referrerPolicy(), request.url(), outgoingReferrer()); 1429 1430 ResourceRequest initialRequest = request; 1431 initialRequest.setTimeoutInterval(10); 1432 1433 if (!referrer.isEmpty()) 1434 initialRequest.setHTTPReferrer(referrer); 1435 addHTTPOriginIfNeeded(initialRequest, outgoingOrigin()); 1436 1437 addExtraFieldsToRequest(initialRequest); 1438 1439 unsigned long identifier = 0; 1440 ResourceRequest newRequest(initialRequest); 1441 requestFromDelegate(newRequest, identifier, error); 1442 1443 if (error.isNull()) { 1444 ASSERT(!newRequest.isNull()); 1445 documentLoader()->applicationCacheHost()->willStartLoadingSynchronously(newRequest); 1446 ResourceLoader::loadResourceSynchronously(newRequest, storedCredentials, error, response, data); 1447 } 1448 int encodedDataLength = response.resourceLoadInfo() ? static_cast<int>(response.resourceLoadInfo()->encodedDataLength) : -1; 1449 notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, response, data.data(), data.size(), encodedDataLength, error); 1450 return identifier; 1451 } 1452 1453 const ResourceRequest& FrameLoader::originalRequest() const 1454 { 1455 return activeDocumentLoader()->originalRequestCopy(); 1456 } 1457 1458 void FrameLoader::receivedMainResourceError(const ResourceError& error) 1459 { 1460 // Retain because the stop may release the last reference to it. 1461 RefPtr<Frame> protect(m_frame); 1462 1463 RefPtr<DocumentLoader> loader = activeDocumentLoader(); 1464 // FIXME: Don't want to do this if an entirely new load is going, so should check 1465 // that both data sources on the frame are either this or nil. 1466 stop(); 1467 1468 // FIXME: We really ought to be able to just check for isCancellation() here, but there are some 1469 // ResourceErrors that setIsCancellation() but aren't created by ResourceError::cancelledError(). 1470 ResourceError c(ResourceError::cancelledError(KURL())); 1471 if (error.errorCode() != c.errorCode() || error.domain() != c.domain()) 1472 handleFallbackContent(); 1473 1474 if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) { 1475 if (m_submittedFormURL == m_provisionalDocumentLoader->originalRequestCopy().url()) 1476 m_submittedFormURL = KURL(); 1477 1478 m_client->dispatchDidFailProvisionalLoad(error); 1479 if (loader != m_provisionalDocumentLoader) 1480 return; 1481 m_provisionalDocumentLoader->detachFromFrame(); 1482 m_provisionalDocumentLoader = 0; 1483 m_progressTracker->progressCompleted(); 1484 m_state = FrameStateComplete; 1485 1486 // Reset the back forward list to the last committed history item at the top level. 1487 RefPtr<HistoryItem> item = m_frame->page()->mainFrame()->loader()->history()->currentItem(); 1488 if (isBackForwardLoadType(loadType()) && !history()->provisionalItem() && item) 1489 m_frame->page()->backForward()->setCurrentItem(item.get()); 1490 } 1491 1492 checkCompleted(); 1493 if (m_frame->page()) 1494 checkLoadComplete(); 1495 } 1496 1497 void FrameLoader::checkNavigationPolicyAndContinueFragmentScroll(const NavigationAction& action, bool isNewNavigation) 1498 { 1499 m_documentLoader->setTriggeringAction(action); 1500 1501 const ResourceRequest& request = action.resourceRequest(); 1502 if (!m_documentLoader->shouldContinueForNavigationPolicy(request, DocumentLoader::PolicyCheckFragment)) 1503 return; 1504 1505 // If we have a provisional request for a different document, a fragment scroll should cancel it. 1506 if (m_provisionalDocumentLoader && !equalIgnoringFragmentIdentifier(m_provisionalDocumentLoader->request().url(), request.url())) { 1507 m_provisionalDocumentLoader->stopLoading(); 1508 if (m_provisionalDocumentLoader) 1509 m_provisionalDocumentLoader->detachFromFrame(); 1510 m_provisionalDocumentLoader = 0; 1511 } 1512 loadInSameDocument(request.url(), 0, isNewNavigation); 1513 } 1514 1515 bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission, const String& httpMethod, FrameLoadType loadType, const KURL& url) 1516 { 1517 ASSERT(loadType != FrameLoadTypeBackForward); 1518 ASSERT(loadType != FrameLoadTypeReloadFromOrigin); 1519 // We don't do this if we are submitting a form with method other than "GET", explicitly reloading, 1520 // currently displaying a frameset, or if the URL does not have a fragment. 1521 return (!isFormSubmission || equalIgnoringCase(httpMethod, "GET")) 1522 && loadType != FrameLoadTypeReload 1523 && loadType != FrameLoadTypeSame 1524 && url.hasFragmentIdentifier() 1525 && equalIgnoringFragmentIdentifier(m_frame->document()->url(), url) 1526 // We don't want to just scroll if a link from within a 1527 // frameset is trying to reload the frameset into _top. 1528 && !m_frame->document()->isFrameSet(); 1529 } 1530 1531 void FrameLoader::scrollToFragmentWithParentBoundary(const KURL& url) 1532 { 1533 FrameView* view = m_frame->view(); 1534 if (!view) 1535 return; 1536 1537 // Leaking scroll position to a cross-origin ancestor would permit the so-called "framesniffing" attack. 1538 RefPtr<Frame> boundaryFrame(url.hasFragmentIdentifier() ? m_frame->document()->findUnsafeParentScrollPropagationBoundary() : 0); 1539 1540 if (boundaryFrame) 1541 boundaryFrame->view()->setSafeToPropagateScrollToParent(false); 1542 1543 view->scrollToFragment(url); 1544 1545 if (boundaryFrame) 1546 boundaryFrame->view()->setSafeToPropagateScrollToParent(true); 1547 } 1548 1549 bool FrameLoader::shouldClose() 1550 { 1551 Page* page = m_frame->page(); 1552 if (!page || !page->chrome().canRunBeforeUnloadConfirmPanel()) 1553 return true; 1554 1555 // Store all references to each subframe in advance since beforeunload's event handler may modify frame 1556 Vector<RefPtr<Frame> > targetFrames; 1557 targetFrames.append(m_frame); 1558 for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame)) 1559 targetFrames.append(child); 1560 1561 bool shouldClose = false; 1562 { 1563 NavigationDisablerForBeforeUnload navigationDisabler; 1564 size_t i; 1565 1566 for (i = 0; i < targetFrames.size(); i++) { 1567 if (!targetFrames[i]->tree()->isDescendantOf(m_frame)) 1568 continue; 1569 if (!targetFrames[i]->loader()->fireBeforeUnloadEvent(page->chrome(), this)) 1570 break; 1571 } 1572 1573 if (i == targetFrames.size()) 1574 shouldClose = true; 1575 } 1576 1577 if (!shouldClose) 1578 m_submittedFormURL = KURL(); 1579 1580 return shouldClose; 1581 } 1582 1583 bool FrameLoader::fireBeforeUnloadEvent(Chrome& chrome, FrameLoader* navigatingFrameLoader) 1584 { 1585 DOMWindow* domWindow = m_frame->domWindow(); 1586 if (!domWindow) 1587 return true; 1588 1589 RefPtr<Document> document = m_frame->document(); 1590 if (!document->body()) 1591 return true; 1592 1593 RefPtr<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create(); 1594 m_pageDismissalEventBeingDispatched = BeforeUnloadDismissal; 1595 domWindow->dispatchEvent(beforeUnloadEvent.get(), domWindow->document()); 1596 m_pageDismissalEventBeingDispatched = NoDismissal; 1597 1598 if (!beforeUnloadEvent->defaultPrevented()) 1599 document->defaultEventHandler(beforeUnloadEvent.get()); 1600 if (beforeUnloadEvent->result().isNull()) 1601 return true; 1602 1603 if (navigatingFrameLoader->hasAllowedNavigationViaBeforeUnloadConfirmationPanel()) { 1604 m_frame->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Blocked attempt to show multiple 'beforeunload' confirmation panels for a single navigation."); 1605 return true; 1606 } 1607 1608 String text = document->displayStringModifiedByEncoding(beforeUnloadEvent->result()); 1609 if (chrome.runBeforeUnloadConfirmPanel(text, m_frame)) { 1610 navigatingFrameLoader->didAllowNavigationViaBeforeUnloadConfirmationPanel(); 1611 return true; 1612 } 1613 return false; 1614 } 1615 1616 void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const NavigationAction& action, FrameLoadType type, PassRefPtr<FormState> formState, const SubstituteData& substituteData, const String& overrideEncoding) 1617 { 1618 ASSERT(m_client->hasWebView()); 1619 if (m_pageDismissalEventBeingDispatched != NoDismissal) 1620 return; 1621 1622 // We skip dispatching the beforeload event on the frame owner if we've already committed a real 1623 // document load because the event would leak subsequent activity by the frame which the parent 1624 // frame isn't supposed to learn. For example, if the child frame navigated to a new URL, the 1625 // parent frame shouldn't learn the URL. 1626 if (!m_stateMachine.committedFirstRealDocumentLoad() && m_frame->ownerElement() && !m_frame->ownerElement()->dispatchBeforeLoadEvent(request.url().string())) 1627 return; 1628 1629 if (!m_stateMachine.startedFirstRealLoad()) 1630 m_stateMachine.advanceTo(FrameLoaderStateMachine::StartedFirstRealLoad); 1631 1632 m_policyDocumentLoader = m_client->createDocumentLoader(request, substituteData.isValid() ? substituteData : defaultSubstituteDataForURL(request.url())); 1633 m_policyDocumentLoader->setFrame(m_frame); 1634 m_policyDocumentLoader->setTriggeringAction(action); 1635 m_policyDocumentLoader->setReplacesCurrentHistoryItem(type == FrameLoadTypeRedirectWithLockedBackForwardList); 1636 m_policyDocumentLoader->setIsClientRedirect(m_startingClientRedirect); 1637 1638 if (Frame* parent = m_frame->tree()->parent()) 1639 m_policyDocumentLoader->setOverrideEncoding(parent->loader()->documentLoader()->overrideEncoding()); 1640 else if (!overrideEncoding.isEmpty()) 1641 m_policyDocumentLoader->setOverrideEncoding(overrideEncoding); 1642 else if (m_documentLoader) 1643 m_policyDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding()); 1644 1645 // stopAllLoaders can detach the Frame, so protect it. 1646 RefPtr<Frame> protect(m_frame); 1647 if (!m_policyDocumentLoader->shouldContinueForNavigationPolicy(request, DocumentLoader::PolicyCheckStandard) || !shouldClose()) { 1648 m_policyDocumentLoader->detachFromFrame(); 1649 m_policyDocumentLoader = 0; 1650 return; 1651 } 1652 1653 // A new navigation is in progress, so don't clear the history's provisional item. 1654 stopAllLoaders(ShouldNotClearProvisionalItem); 1655 1656 // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders() 1657 // might detach the current FrameLoader, in which case we should bail on this newly defunct load. 1658 if (!m_frame->page()) 1659 return; 1660 1661 if (isLoadingMainFrame()) 1662 m_frame->page()->inspectorController()->resume(); 1663 m_frame->navigationScheduler()->cancel(); 1664 1665 m_provisionalDocumentLoader = m_policyDocumentLoader.release(); 1666 m_loadType = type; 1667 m_state = FrameStateProvisional; 1668 1669 if (formState) 1670 m_client->dispatchWillSubmitForm(formState); 1671 1672 m_progressTracker->progressStarted(); 1673 if (m_provisionalDocumentLoader->isClientRedirect()) 1674 m_provisionalDocumentLoader->appendRedirect(m_frame->document()->url()); 1675 m_provisionalDocumentLoader->appendRedirect(m_provisionalDocumentLoader->request().url()); 1676 m_client->dispatchDidStartProvisionalLoad(); 1677 ASSERT(m_provisionalDocumentLoader); 1678 m_provisionalDocumentLoader->startLoadingMainResource(); 1679 } 1680 1681 void FrameLoader::checkNewWindowPolicyAndContinue(PassRefPtr<FormState> formState, const String& frameName, const NavigationAction& action) 1682 { 1683 if (m_pageDismissalEventBeingDispatched != NoDismissal) 1684 return; 1685 1686 if (m_frame->document() && m_frame->document()->isSandboxed(SandboxPopups)) 1687 return; 1688 1689 if (!DOMWindow::allowPopUp(m_frame)) 1690 return; 1691 1692 NavigationPolicy navigationPolicy = NavigationPolicyNewForegroundTab; 1693 action.specifiesNavigationPolicy(&navigationPolicy); 1694 1695 if (navigationPolicy == NavigationPolicyDownload) { 1696 m_client->loadURLExternally(action.resourceRequest(), navigationPolicy); 1697 return; 1698 } 1699 1700 RefPtr<Frame> frame = m_frame; 1701 RefPtr<Frame> mainFrame = m_frame; 1702 1703 if (!m_frame->settings() || m_frame->settings()->supportsMultipleWindows()) { 1704 struct WindowFeatures features; 1705 Page* newPage = m_frame->page()->chrome().client()->createWindow(m_frame, FrameLoadRequest(m_frame->document()->securityOrigin()), 1706 features, action, navigationPolicy); 1707 1708 // createWindow can return null (e.g., popup blocker denies the window). 1709 if (!newPage) 1710 return; 1711 mainFrame = newPage->mainFrame(); 1712 } 1713 1714 if (frameName != "_blank") 1715 mainFrame->tree()->setName(frameName); 1716 1717 mainFrame->page()->setOpenedByDOM(); 1718 mainFrame->page()->chrome().show(navigationPolicy); 1719 if (!m_suppressOpenerInNewFrame) { 1720 mainFrame->loader()->setOpener(frame.get()); 1721 mainFrame->document()->setReferrerPolicy(frame->document()->referrerPolicy()); 1722 } 1723 1724 // FIXME: We can't just send our NavigationAction to the new FrameLoader's loadWithNavigationAction(), we need to 1725 // create a new one with a default NavigationType and no triggering event. We should figure out why. 1726 mainFrame->loader()->loadWithNavigationAction(action.resourceRequest(), NavigationAction(action.resourceRequest()), FrameLoadTypeStandard, formState, SubstituteData()); 1727 } 1728 1729 void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error) 1730 { 1731 ASSERT(!request.isNull()); 1732 1733 identifier = 0; 1734 if (Page* page = m_frame->page()) 1735 identifier = createUniqueIdentifier(); 1736 1737 ResourceRequest newRequest(request); 1738 notifier()->dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse()); 1739 1740 if (newRequest.isNull()) 1741 error = ResourceError::cancelledError(request.url()); 1742 else 1743 error = ResourceError(); 1744 1745 request = newRequest; 1746 } 1747 1748 void FrameLoader::loadedResourceFromMemoryCache(Resource* resource) 1749 { 1750 Page* page = m_frame->page(); 1751 if (!page) 1752 return; 1753 1754 if (!resource->shouldSendResourceLoadCallbacks()) 1755 return; 1756 1757 // Main resource delegate messages are synthesized in MainResourceLoader, so we must not send them here. 1758 if (resource->type() == Resource::MainResource) 1759 return; 1760 1761 ResourceRequest request(resource->url()); 1762 m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize()); 1763 1764 unsigned long identifier; 1765 ResourceError error; 1766 requestFromDelegate(request, identifier, error); 1767 InspectorInstrumentation::markResourceAsCached(page, identifier); 1768 notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, resource->response(), 0, resource->encodedSize(), 0, error); 1769 } 1770 1771 void FrameLoader::applyUserAgent(ResourceRequest& request) 1772 { 1773 String userAgent = this->userAgent(request.url()); 1774 ASSERT(!userAgent.isNull()); 1775 request.setHTTPUserAgent(userAgent); 1776 } 1777 1778 bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, const KURL& url, unsigned long requestIdentifier) 1779 { 1780 UseCounter::count(m_frame->document(), UseCounter::XFrameOptions); 1781 1782 Frame* topFrame = m_frame->tree()->top(); 1783 if (m_frame == topFrame) 1784 return false; 1785 1786 XFrameOptionsDisposition disposition = parseXFrameOptionsHeader(content); 1787 1788 switch (disposition) { 1789 case XFrameOptionsSameOrigin: { 1790 UseCounter::count(m_frame->document(), UseCounter::XFrameOptionsSameOrigin); 1791 RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url); 1792 if (!origin->isSameSchemeHostPort(topFrame->document()->securityOrigin())) 1793 return true; 1794 for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) { 1795 if (!origin->isSameSchemeHostPort(frame->document()->securityOrigin())) { 1796 UseCounter::count(m_frame->document(), UseCounter::XFrameOptionsSameOriginWithBadAncestorChain); 1797 break; 1798 } 1799 } 1800 return false; 1801 } 1802 case XFrameOptionsDeny: 1803 return true; 1804 case XFrameOptionsAllowAll: 1805 return false; 1806 case XFrameOptionsConflict: 1807 m_frame->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Multiple 'X-Frame-Options' headers with conflicting values ('" + content + "') encountered when loading '" + url.elidedString() + "'. Falling back to 'DENY'.", requestIdentifier); 1808 return true; 1809 case XFrameOptionsInvalid: 1810 m_frame->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Invalid 'X-Frame-Options' header encountered when loading '" + url.elidedString() + "': '" + content + "' is not a recognized directive. The header will be ignored.", requestIdentifier); 1811 return false; 1812 default: 1813 ASSERT_NOT_REACHED(); 1814 return false; 1815 } 1816 } 1817 1818 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const 1819 { 1820 if (!history()->currentItem()) 1821 return false; 1822 return url == history()->currentItem()->url() || url == history()->currentItem()->originalURL(); 1823 } 1824 1825 bool FrameLoader::shouldTreatURLAsSrcdocDocument(const KURL& url) const 1826 { 1827 if (!equalIgnoringCase(url.string(), "about:srcdoc")) 1828 return false; 1829 HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement(); 1830 if (!ownerElement) 1831 return false; 1832 if (!ownerElement->hasTagName(iframeTag)) 1833 return false; 1834 return ownerElement->fastHasAttribute(srcdocAttr); 1835 } 1836 1837 Frame* FrameLoader::findFrameForNavigation(const AtomicString& name, Document* activeDocument) 1838 { 1839 Frame* frame = m_frame->tree()->find(name); 1840 1841 // From http://www.whatwg.org/specs/web-apps/current-work/#seamlessLinks: 1842 // 1843 // If the source browsing context is the same as the browsing context 1844 // being navigated, and this browsing context has its seamless browsing 1845 // context flag set, and the browsing context being navigated was not 1846 // chosen using an explicit self-navigation override, then find the 1847 // nearest ancestor browsing context that does not have its seamless 1848 // browsing context flag set, and continue these steps as if that 1849 // browsing context was the one that was going to be navigated instead. 1850 if (frame == m_frame && name != "_self" && m_frame->document()->shouldDisplaySeamlesslyWithParent()) { 1851 for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree()->parent()) { 1852 if (!ancestor->document()->shouldDisplaySeamlesslyWithParent()) { 1853 frame = ancestor; 1854 break; 1855 } 1856 } 1857 ASSERT(frame != m_frame); 1858 } 1859 1860 if (activeDocument) { 1861 if (!activeDocument->canNavigate(frame)) 1862 return 0; 1863 } else { 1864 // FIXME: Eventually all callers should supply the actual activeDocument 1865 // so we can call canNavigate with the right document. 1866 if (!m_frame->document()->canNavigate(frame)) 1867 return 0; 1868 } 1869 1870 return frame; 1871 } 1872 1873 void FrameLoader::loadSameDocumentItem(HistoryItem* item) 1874 { 1875 ASSERT(item->documentSequenceNumber() == history()->currentItem()->documentSequenceNumber()); 1876 1877 // Save user view state to the current history item here since we don't do a normal load. 1878 // FIXME: Does form state need to be saved here too? 1879 history()->saveScrollPositionAndViewStateToItem(history()->currentItem()); 1880 if (FrameView* view = m_frame->view()) 1881 view->setWasScrolledByUser(false); 1882 1883 history()->setCurrentItem(item); 1884 1885 // loadInSameDocument() actually changes the URL and notifies load delegates of a "fake" load 1886 loadInSameDocument(item->url(), item->stateObject(), false); 1887 1888 // Restore user view state from the current history item here since we don't do a normal load. 1889 history()->restoreScrollPositionAndViewState(); 1890 } 1891 1892 // FIXME: This function should really be split into a couple pieces, some of 1893 // which should be methods of HistoryController and some of which should be 1894 // methods of FrameLoader. 1895 void FrameLoader::loadDifferentDocumentItem(HistoryItem* item) 1896 { 1897 // Remember this item so we can traverse any child items as child frames load 1898 history()->setProvisionalItem(item); 1899 1900 RefPtr<FormData> formData = item->formData(); 1901 ResourceRequest request(item->url()); 1902 request.setHTTPReferrer(item->referrer()); 1903 if (formData) { 1904 request.setHTTPMethod("POST"); 1905 request.setHTTPBody(formData); 1906 request.setHTTPContentType(item->formContentType()); 1907 RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item->referrer()); 1908 addHTTPOriginIfNeeded(request, securityOrigin->toString()); 1909 } 1910 1911 loadWithNavigationAction(request, NavigationAction(request, FrameLoadTypeBackForward, formData), FrameLoadTypeBackForward, 0, SubstituteData()); 1912 } 1913 1914 void FrameLoader::loadHistoryItem(HistoryItem* item) 1915 { 1916 m_requestedHistoryItem = item; 1917 HistoryItem* currentItem = history()->currentItem(); 1918 bool sameDocumentNavigation = currentItem && item->shouldDoSameDocumentNavigationTo(currentItem); 1919 1920 if (sameDocumentNavigation) 1921 loadSameDocumentItem(item); 1922 else 1923 loadDifferentDocumentItem(item); 1924 } 1925 1926 void FrameLoader::insertDummyHistoryItem() 1927 { 1928 RefPtr<HistoryItem> currentItem = HistoryItem::create(); 1929 history()->setCurrentItem(currentItem.get()); 1930 frame()->page()->backForward()->setCurrentItem(currentItem.get()); 1931 } 1932 1933 void FrameLoader::setTitle(const StringWithDirection& title) 1934 { 1935 documentLoader()->setTitle(title); 1936 } 1937 1938 String FrameLoader::referrer() const 1939 { 1940 return m_documentLoader ? m_documentLoader->request().httpReferrer() : ""; 1941 } 1942 1943 void FrameLoader::dispatchDocumentElementAvailable() 1944 { 1945 m_client->documentElementAvailable(); 1946 } 1947 1948 void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() 1949 { 1950 if (!m_frame->script()->canExecuteScripts(NotAboutToExecuteScript)) 1951 return; 1952 1953 Vector<RefPtr<DOMWrapperWorld> > worlds; 1954 DOMWrapperWorld::getAllWorlds(worlds); 1955 for (size_t i = 0; i < worlds.size(); ++i) 1956 dispatchDidClearWindowObjectInWorld(worlds[i].get()); 1957 } 1958 1959 void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world) 1960 { 1961 if (!m_frame->script()->canExecuteScripts(NotAboutToExecuteScript) || !m_frame->script()->existingWindowShell(world)) 1962 return; 1963 1964 m_client->dispatchDidClearWindowObjectInWorld(world); 1965 1966 if (Page* page = m_frame->page()) 1967 page->inspectorController()->didClearWindowObjectInWorld(m_frame, world); 1968 1969 InspectorInstrumentation::didClearWindowObjectInWorld(m_frame, world); 1970 } 1971 1972 SandboxFlags FrameLoader::effectiveSandboxFlags() const 1973 { 1974 SandboxFlags flags = m_forcedSandboxFlags; 1975 if (Frame* parentFrame = m_frame->tree()->parent()) 1976 flags |= parentFrame->document()->sandboxFlags(); 1977 if (HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement()) 1978 flags |= ownerElement->sandboxFlags(); 1979 return flags; 1980 } 1981 1982 void FrameLoader::didChangeTitle(DocumentLoader* loader) 1983 { 1984 if (loader == m_documentLoader) { 1985 // Must update the entries in the back-forward list too. 1986 history()->setCurrentItemTitle(loader->title()); 1987 m_client->dispatchDidReceiveTitle(loader->title()); 1988 } 1989 } 1990 1991 void FrameLoader::dispatchDidCommitLoad() 1992 { 1993 m_client->dispatchDidCommitLoad(); 1994 1995 InspectorInstrumentation::didCommitLoad(m_frame, m_documentLoader.get()); 1996 1997 m_frame->page()->didCommitLoad(m_frame); 1998 1999 if (m_frame->page()->mainFrame() == m_frame) 2000 m_frame->page()->useCounter()->didCommitLoad(); 2001 2002 } 2003 2004 } // namespace WebCore 2005