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/Document.h" 43 #include "core/dom/Element.h" 44 #include "core/editing/Editor.h" 45 #include "core/editing/UndoStack.h" 46 #include "core/events/Event.h" 47 #include "core/events/PageTransitionEvent.h" 48 #include "core/events/ThreadLocalEventNames.h" 49 #include "core/fetch/FetchContext.h" 50 #include "core/fetch/ResourceFetcher.h" 51 #include "core/fetch/ResourceLoader.h" 52 #include "core/frame/ContentSecurityPolicy.h" 53 #include "core/frame/ContentSecurityPolicyResponseHeaders.h" 54 #include "core/frame/DOMWindow.h" 55 #include "core/frame/Frame.h" 56 #include "core/frame/FrameView.h" 57 #include "core/html/HTMLFormElement.h" 58 #include "core/html/HTMLFrameOwnerElement.h" 59 #include "core/html/parser/HTMLParserIdioms.h" 60 #include "core/inspector/InspectorController.h" 61 #include "core/inspector/InspectorInstrumentation.h" 62 #include "core/loader/DocumentLoadTiming.h" 63 #include "core/loader/DocumentLoader.h" 64 #include "core/loader/FormState.h" 65 #include "core/loader/FormSubmission.h" 66 #include "core/loader/FrameFetchContext.h" 67 #include "core/loader/FrameLoadRequest.h" 68 #include "core/loader/FrameLoaderClient.h" 69 #include "core/loader/ProgressTracker.h" 70 #include "core/loader/UniqueIdentifier.h" 71 #include "core/loader/appcache/ApplicationCacheHost.h" 72 #include "core/page/BackForwardClient.h" 73 #include "core/page/Chrome.h" 74 #include "core/page/ChromeClient.h" 75 #include "core/page/CreateWindow.h" 76 #include "core/page/EventHandler.h" 77 #include "core/page/FrameTree.h" 78 #include "core/page/Page.h" 79 #include "core/frame/Settings.h" 80 #include "core/page/WindowFeatures.h" 81 #include "core/page/scrolling/ScrollingCoordinator.h" 82 #include "core/xml/parser/XMLDocumentParser.h" 83 #include "modules/webdatabase/DatabaseManager.h" 84 #include "platform/Logging.h" 85 #include "platform/UserGestureIndicator.h" 86 #include "platform/geometry/FloatRect.h" 87 #include "platform/network/HTTPParsers.h" 88 #include "platform/network/ResourceRequest.h" 89 #include "platform/scroll/ScrollAnimator.h" 90 #include "platform/weborigin/SecurityOrigin.h" 91 #include "platform/weborigin/SecurityPolicy.h" 92 #include "wtf/TemporaryChange.h" 93 #include "wtf/text/CString.h" 94 #include "wtf/text/WTFString.h" 95 96 namespace WebCore { 97 98 using namespace HTMLNames; 99 100 static const char defaultAcceptHeader[] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; 101 102 bool isBackForwardLoadType(FrameLoadType type) 103 { 104 return type == FrameLoadTypeBackForward; 105 } 106 107 class FrameLoader::FrameProgressTracker { 108 public: 109 static PassOwnPtr<FrameProgressTracker> create(Frame* frame) { return adoptPtr(new FrameProgressTracker(frame)); } 110 ~FrameProgressTracker() 111 { 112 ASSERT(!m_inProgress || m_frame->page()); 113 if (m_inProgress) 114 m_frame->page()->progress().progressCompleted(m_frame); 115 } 116 117 void progressStarted() 118 { 119 ASSERT(m_frame->page()); 120 if (!m_inProgress) 121 m_frame->page()->progress().progressStarted(m_frame); 122 m_inProgress = true; 123 } 124 125 void progressCompleted() 126 { 127 ASSERT(m_inProgress); 128 ASSERT(m_frame->page()); 129 m_inProgress = false; 130 m_frame->page()->progress().progressCompleted(m_frame); 131 } 132 133 private: 134 FrameProgressTracker(Frame* frame) 135 : m_frame(frame) 136 , m_inProgress(false) 137 { 138 } 139 140 Frame* m_frame; 141 bool m_inProgress; 142 }; 143 144 FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client) 145 : m_frame(frame) 146 , m_client(client) 147 , m_mixedContentChecker(frame) 148 , m_state(FrameStateProvisional) 149 , m_loadType(FrameLoadTypeStandard) 150 , m_fetchContext(FrameFetchContext::create(frame)) 151 , m_inStopAllLoaders(false) 152 , m_isComplete(false) 153 , m_checkTimer(this, &FrameLoader::checkTimerFired) 154 , m_shouldCallCheckCompleted(false) 155 , m_opener(0) 156 , m_didAccessInitialDocument(false) 157 , m_didAccessInitialDocumentTimer(this, &FrameLoader::didAccessInitialDocumentTimerFired) 158 , m_forcedSandboxFlags(SandboxNone) 159 { 160 } 161 162 FrameLoader::~FrameLoader() 163 { 164 setOpener(0); 165 166 HashSet<Frame*>::iterator end = m_openedFrames.end(); 167 for (HashSet<Frame*>::iterator it = m_openedFrames.begin(); it != end; ++it) 168 (*it)->loader().m_opener = 0; 169 170 m_client->frameLoaderDestroyed(); 171 } 172 173 void FrameLoader::init() 174 { 175 // This somewhat odd set of steps gives the frame an initial empty document. 176 m_provisionalDocumentLoader = m_client->createDocumentLoader(ResourceRequest(KURL(ParsedURLString, emptyString())), SubstituteData()); 177 m_provisionalDocumentLoader->setFrame(m_frame); 178 m_provisionalDocumentLoader->startLoadingMainResource(); 179 m_frame->document()->cancelParsing(); 180 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument); 181 m_progressTracker = FrameProgressTracker::create(m_frame); 182 } 183 184 void FrameLoader::setDefersLoading(bool defers) 185 { 186 if (m_documentLoader) 187 m_documentLoader->setDefersLoading(defers); 188 if (m_provisionalDocumentLoader) 189 m_provisionalDocumentLoader->setDefersLoading(defers); 190 if (m_policyDocumentLoader) 191 m_policyDocumentLoader->setDefersLoading(defers); 192 193 if (!defers) { 194 m_frame->navigationScheduler().startTimer(); 195 startCheckCompleteTimer(); 196 } 197 } 198 199 void FrameLoader::stopLoading() 200 { 201 m_isComplete = true; // to avoid calling completed() in finishedParsing() 202 203 if (m_frame->document() && m_frame->document()->parsing()) { 204 finishedParsing(); 205 m_frame->document()->setParsing(false); 206 } 207 208 if (Document* doc = m_frame->document()) { 209 // FIXME: HTML5 doesn't tell us to set the state to complete when aborting, but we do anyway to match legacy behavior. 210 // http://www.w3.org/Bugs/Public/show_bug.cgi?id=10537 211 doc->setReadyState(Document::Complete); 212 213 // FIXME: Should the DatabaseManager watch for something like ActiveDOMObject::stop() rather than being special-cased here? 214 DatabaseManager::manager().stopDatabases(doc, 0); 215 } 216 217 // FIXME: This will cancel redirection timer, which really needs to be restarted when restoring the frame from b/f cache. 218 m_frame->navigationScheduler().cancel(); 219 } 220 221 void FrameLoader::saveDocumentAndScrollState() 222 { 223 if (!m_currentItem) 224 return; 225 226 Document* document = m_frame->document(); 227 if (m_currentItem->isCurrentDocument(document) && document->isActive()) 228 m_currentItem->setDocumentState(document->formElementsState()); 229 230 if (!m_frame->view()) 231 return; 232 233 m_currentItem->setScrollPoint(m_frame->view()->scrollPosition()); 234 if (m_frame->isMainFrame() && !m_frame->page()->inspectorController().deviceEmulationEnabled()) 235 m_currentItem->setPageScaleFactor(m_frame->page()->pageScaleFactor()); 236 } 237 238 void FrameLoader::clearScrollPositionAndViewState() 239 { 240 ASSERT(m_frame->isMainFrame()); 241 if (!m_currentItem) 242 return; 243 m_currentItem->clearScrollPoint(); 244 m_currentItem->setPageScaleFactor(0); 245 } 246 247 bool FrameLoader::closeURL() 248 { 249 // This is done when a back/forward navigation begins (and the current item 250 // changes) in loadHistoryItem(). Saving now will save the state will save 251 // to the wrong item if the navigation is back/forward. 252 if (m_loadType != FrameLoadTypeBackForward) 253 saveDocumentAndScrollState(); 254 255 // Should only send the pagehide event here if the current document exists. 256 if (m_frame->document()) 257 m_frame->document()->dispatchUnloadEvents(); 258 stopLoading(); 259 260 if (Page* page = m_frame->page()) 261 page->undoStack().didUnloadFrame(*m_frame); 262 return true; 263 } 264 265 void FrameLoader::didExplicitOpen() 266 { 267 m_isComplete = false; 268 269 // Calling document.open counts as committing the first real document load. 270 if (!m_stateMachine.committedFirstRealDocumentLoad()) 271 m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad); 272 273 // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results 274 // from a subsequent window.document.open / window.document.write call. 275 // Canceling redirection here works for all cases because document.open 276 // implicitly precedes document.write. 277 m_frame->navigationScheduler().cancel(); 278 } 279 280 void FrameLoader::clear(ClearOptions options) 281 { 282 if (m_stateMachine.creatingInitialEmptyDocument()) 283 return; 284 285 m_frame->editor().clear(); 286 m_frame->document()->cancelParsing(); 287 m_frame->document()->prepareForDestruction(); 288 m_frame->document()->removeFocusedElementOfSubtree(m_frame->document()); 289 290 // Do this after detaching the document so that the unload event works. 291 if (options & ClearWindowProperties) { 292 InspectorInstrumentation::frameWindowDiscarded(m_frame, m_frame->domWindow()); 293 m_frame->domWindow()->reset(); 294 m_frame->script().clearWindowShell(); 295 } 296 297 m_frame->selection().prepareForDestruction(); 298 m_frame->eventHandler().clear(); 299 if (m_frame->view()) 300 m_frame->view()->clear(); 301 302 if (options & ClearWindowObject) { 303 // Do not drop the DOMWindow (and Document) before the ScriptController and view are cleared 304 // as some destructors might still try to access the document. 305 m_frame->setDOMWindow(0); 306 } 307 308 if (options & ClearScriptObjects) 309 m_frame->script().clearScriptObjects(); 310 311 m_frame->script().enableEval(); 312 313 m_frame->navigationScheduler().clear(); 314 315 m_checkTimer.stop(); 316 m_shouldCallCheckCompleted = false; 317 318 if (m_stateMachine.isDisplayingInitialEmptyDocument()) 319 m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad); 320 } 321 322 void FrameLoader::setHistoryItemStateForCommit(HistoryItemPolicy historyItemPolicy) 323 { 324 if (!m_currentItem || historyItemPolicy == CreateNewHistoryItem || m_currentItem->url() != m_documentLoader->url()) { 325 if (!m_currentItem || historyItemPolicy == CreateNewHistoryItem) 326 m_currentItem = HistoryItem::create(); 327 else 328 m_currentItem->reset(); 329 const KURL& unreachableURL = m_documentLoader->unreachableURL(); 330 const KURL& url = unreachableURL.isEmpty() ? m_documentLoader->requestURL() : unreachableURL; 331 const KURL& originalURL = unreachableURL.isEmpty() ? m_documentLoader->originalURL() : unreachableURL; 332 m_currentItem->setURL(url); 333 m_currentItem->setTarget(m_frame->tree().uniqueName()); 334 m_currentItem->setTargetFrameID(m_frame->frameID()); 335 m_currentItem->setOriginalURLString(originalURL.string()); 336 } 337 m_currentItem->setFormInfoFromRequest(m_documentLoader->request()); 338 } 339 340 void FrameLoader::receivedFirstData() 341 { 342 if (m_stateMachine.creatingInitialEmptyDocument()) 343 return; 344 NavigationHistoryPolicy navigationHistoryPolicy = NavigationReusedHistoryEntry; 345 if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isURLValidForNewHistoryEntry()) 346 navigationHistoryPolicy = NavigationCreatedHistoryEntry; 347 HistoryItemPolicy historyItemPolicy = DoNotCreateNewHistoryItem; 348 if (m_loadType == FrameLoadTypeInitialInChildFrame || navigationHistoryPolicy == NavigationCreatedHistoryEntry) 349 historyItemPolicy = CreateNewHistoryItem; 350 setHistoryItemStateForCommit(historyItemPolicy); 351 352 if (!m_stateMachine.committedMultipleRealLoads() && navigationHistoryPolicy == NavigationCreatedHistoryEntry) 353 m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedMultipleRealLoads); 354 355 m_client->dispatchDidCommitLoad(m_frame, m_currentItem.get(), navigationHistoryPolicy); 356 357 InspectorInstrumentation::didCommitLoad(m_frame, m_documentLoader.get()); 358 m_frame->page()->didCommitLoad(m_frame); 359 dispatchDidClearWindowObjectsInAllWorlds(); 360 } 361 362 void FrameLoader::didBeginDocument(bool dispatch) 363 { 364 m_isComplete = false; 365 m_frame->document()->setReadyState(Document::Loading); 366 367 if (m_currentItem && m_loadType == FrameLoadTypeBackForward) 368 m_frame->domWindow()->statePopped(m_currentItem->stateObject()); 369 370 if (dispatch) 371 dispatchDidClearWindowObjectsInAllWorlds(); 372 373 m_frame->document()->initContentSecurityPolicy(m_documentLoader ? ContentSecurityPolicyResponseHeaders(m_documentLoader->response()) : ContentSecurityPolicyResponseHeaders()); 374 375 Settings* settings = m_frame->document()->settings(); 376 if (settings) { 377 m_frame->document()->fetcher()->setImagesEnabled(settings->imagesEnabled()); 378 m_frame->document()->fetcher()->setAutoLoadImages(settings->loadsImagesAutomatically()); 379 } 380 381 if (m_documentLoader) { 382 const AtomicString& dnsPrefetchControl = m_documentLoader->response().httpHeaderField("X-DNS-Prefetch-Control"); 383 if (!dnsPrefetchControl.isEmpty()) 384 m_frame->document()->parseDNSPrefetchControlHeader(dnsPrefetchControl); 385 386 String headerContentLanguage = m_documentLoader->response().httpHeaderField("Content-Language"); 387 if (!headerContentLanguage.isEmpty()) { 388 size_t commaIndex = headerContentLanguage.find(','); 389 headerContentLanguage.truncate(commaIndex); // kNotFound == -1 == don't truncate 390 headerContentLanguage = headerContentLanguage.stripWhiteSpace(isHTMLSpace<UChar>); 391 if (!headerContentLanguage.isEmpty()) 392 m_frame->document()->setContentLanguage(AtomicString(headerContentLanguage)); 393 } 394 } 395 396 if (m_currentItem && m_loadType == FrameLoadTypeBackForward) 397 m_frame->document()->setStateForNewFormElements(m_currentItem->documentState()); 398 } 399 400 void FrameLoader::finishedParsing() 401 { 402 if (m_stateMachine.creatingInitialEmptyDocument()) 403 return; 404 405 // This can be called from the Frame's destructor, in which case we shouldn't protect ourselves 406 // because doing so will cause us to re-enter the destructor when protector goes out of scope. 407 // Null-checking the FrameView indicates whether or not we're in the destructor. 408 RefPtr<Frame> protector = m_frame->view() ? m_frame : 0; 409 410 m_client->dispatchDidFinishDocumentLoad(); 411 412 checkCompleted(); 413 414 if (!m_frame->view()) 415 return; // We are being destroyed by something checkCompleted called. 416 417 // Check if the scrollbars are really needed for the content. 418 // If not, remove them, relayout, and repaint. 419 m_frame->view()->restoreScrollbar(); 420 scrollToFragmentWithParentBoundary(m_frame->document()->url()); 421 } 422 423 void FrameLoader::loadDone() 424 { 425 checkCompleted(); 426 } 427 428 bool FrameLoader::allChildrenAreComplete() const 429 { 430 for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) { 431 if (!child->loader().m_isComplete) 432 return false; 433 } 434 return true; 435 } 436 437 bool FrameLoader::allAncestorsAreComplete() const 438 { 439 for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree().parent()) { 440 if (!ancestor->document()->loadEventFinished()) 441 return false; 442 } 443 return true; 444 } 445 446 void FrameLoader::checkCompleted() 447 { 448 RefPtr<Frame> protect(m_frame); 449 m_shouldCallCheckCompleted = false; 450 451 if (m_frame->view()) 452 m_frame->view()->handleLoadCompleted(); 453 454 // Have we completed before? 455 if (m_isComplete) 456 return; 457 458 // Are we still parsing? 459 if (m_frame->document()->parsing()) 460 return; 461 462 // Still waiting for images/scripts? 463 if (m_frame->document()->fetcher()->requestCount()) 464 return; 465 466 // Still waiting for elements that don't go through a FrameLoader? 467 if (m_frame->document()->isDelayingLoadEvent()) 468 return; 469 470 // Any frame that hasn't completed yet? 471 if (!allChildrenAreComplete()) 472 return; 473 474 // OK, completed. 475 m_isComplete = true; 476 m_frame->document()->setReadyState(Document::Complete); 477 if (m_frame->document()->loadEventStillNeeded()) 478 m_frame->document()->implicitClose(); 479 480 m_frame->navigationScheduler().startTimer(); 481 482 completed(); 483 if (m_frame->page()) 484 checkLoadComplete(); 485 486 if (m_frame->view()) 487 m_frame->view()->handleLoadCompleted(); 488 } 489 490 void FrameLoader::checkTimerFired(Timer<FrameLoader>*) 491 { 492 RefPtr<Frame> protect(m_frame); 493 494 if (Page* page = m_frame->page()) { 495 if (page->defersLoading()) 496 return; 497 } 498 if (m_shouldCallCheckCompleted) 499 checkCompleted(); 500 } 501 502 void FrameLoader::startCheckCompleteTimer() 503 { 504 if (!m_shouldCallCheckCompleted) 505 return; 506 if (m_checkTimer.isActive()) 507 return; 508 m_checkTimer.startOneShot(0); 509 } 510 511 void FrameLoader::scheduleCheckCompleted() 512 { 513 m_shouldCallCheckCompleted = true; 514 startCheckCompleteTimer(); 515 } 516 517 Frame* FrameLoader::opener() 518 { 519 return m_opener; 520 } 521 522 void FrameLoader::setOpener(Frame* opener) 523 { 524 if (m_opener && !opener) 525 m_client->didDisownOpener(); 526 527 if (m_opener) 528 m_opener->loader().m_openedFrames.remove(m_frame); 529 if (opener) 530 opener->loader().m_openedFrames.add(m_frame); 531 m_opener = opener; 532 533 if (m_frame->document()) 534 m_frame->document()->initSecurityContext(); 535 } 536 537 bool FrameLoader::allowPlugins(ReasonForCallingAllowPlugins reason) 538 { 539 Settings* settings = m_frame->settings(); 540 bool allowed = m_client->allowPlugins(settings && settings->pluginsEnabled()); 541 if (!allowed && reason == AboutToInstantiatePlugin) 542 m_client->didNotAllowPlugins(); 543 return allowed; 544 } 545 546 void FrameLoader::updateForSameDocumentNavigation(const KURL& newURL, SameDocumentNavigationSource sameDocumentNavigationSource, PassRefPtr<SerializedScriptValue> data, UpdateBackForwardListPolicy updateBackForwardList) 547 { 548 // Update the data source's request with the new URL to fake the URL change 549 m_frame->document()->setURL(newURL); 550 documentLoader()->updateForSameDocumentNavigation(newURL); 551 552 // Generate start and stop notifications only when loader is completed so that we 553 // don't fire them for fragment redirection that happens in window.onload handler. 554 // See https://bugs.webkit.org/show_bug.cgi?id=31838 555 if (m_frame->document()->loadEventFinished()) 556 m_client->postProgressStartedNotification(); 557 558 NavigationHistoryPolicy navigationHistoryPolicy = NavigationReusedHistoryEntry; 559 if (updateBackForwardList == UpdateBackForwardList || (sameDocumentNavigationSource == SameDocumentNavigationPushState && m_currentItem)) { 560 navigationHistoryPolicy = NavigationCreatedHistoryEntry; 561 setHistoryItemStateForCommit(CreateNewHistoryItem); 562 } 563 m_client->dispatchDidNavigateWithinPage(navigationHistoryPolicy, m_currentItem.get()); 564 m_client->dispatchDidReceiveTitle(m_frame->document()->title()); 565 566 if (m_currentItem) { 567 m_currentItem->setURL(newURL); 568 if (sameDocumentNavigationSource != SameDocumentNavigationDefault) { 569 m_currentItem->setStateObject(data); 570 m_currentItem->setFormData(0); 571 m_currentItem->setFormContentType(nullAtom); 572 } 573 } 574 575 if (m_frame->document()->loadEventFinished()) 576 m_client->postProgressFinishedNotification(); 577 } 578 579 void FrameLoader::loadInSameDocument(const KURL& url, PassRefPtr<SerializedScriptValue> stateObject, bool isNewNavigation, ClientRedirectPolicy clientRedirect) 580 { 581 // If we have a state object, we cannot also be a new navigation. 582 ASSERT(!stateObject || (stateObject && !isNewNavigation)); 583 584 KURL oldURL = m_frame->document()->url(); 585 // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor 586 bool hashChange = equalIgnoringFragmentIdentifier(url, oldURL) && url.fragmentIdentifier() != oldURL.fragmentIdentifier(); 587 if (hashChange) { 588 m_frame->eventHandler().stopAutoscroll(); 589 m_frame->domWindow()->enqueueHashchangeEvent(oldURL, url); 590 } 591 m_documentLoader->setIsClientRedirect((clientRedirect == ClientRedirect && !isNewNavigation) || !UserGestureIndicator::processingUserGesture()); 592 m_documentLoader->setReplacesCurrentHistoryItem(!isNewNavigation); 593 UpdateBackForwardListPolicy updateBackForwardList = isNewNavigation && !shouldTreatURLAsSameAsCurrent(url) && !stateObject ? UpdateBackForwardList : DoNotUpdateBackForwardList; 594 updateForSameDocumentNavigation(url, SameDocumentNavigationDefault, 0, updateBackForwardList); 595 596 // It's important to model this as a load that starts and immediately finishes. 597 // Otherwise, the parent frame may think we never finished loading. 598 started(); 599 600 // We need to scroll to the fragment whether or not a hash change occurred, since 601 // the user might have scrolled since the previous navigation. 602 scrollToFragmentWithParentBoundary(url); 603 604 m_isComplete = false; 605 checkCompleted(); 606 607 m_frame->domWindow()->statePopped(stateObject ? stateObject : SerializedScriptValue::nullValue()); 608 } 609 610 void FrameLoader::completed() 611 { 612 RefPtr<Frame> protect(m_frame); 613 614 for (Frame* descendant = m_frame->tree().traverseNext(m_frame); descendant; descendant = descendant->tree().traverseNext(m_frame)) 615 descendant->navigationScheduler().startTimer(); 616 617 if (Frame* parent = m_frame->tree().parent()) 618 parent->loader().checkCompleted(); 619 620 if (m_frame->view()) 621 m_frame->view()->maintainScrollPositionAtAnchor(0); 622 } 623 624 void FrameLoader::started() 625 { 626 for (Frame* frame = m_frame; frame; frame = frame->tree().parent()) 627 frame->loader().m_isComplete = false; 628 } 629 630 void FrameLoader::setReferrerForFrameRequest(ResourceRequest& request, ShouldSendReferrer shouldSendReferrer, Document* originDocument) 631 { 632 if (shouldSendReferrer == NeverSendReferrer) { 633 request.clearHTTPReferrer(); 634 return; 635 } 636 637 // Always use the initiating document to generate the referrer. 638 // We need to generateReferrerHeader(), because we might not have enforced ReferrerPolicy or https->http 639 // referrer suppression yet. 640 String argsReferrer(request.httpReferrer()); 641 if (argsReferrer.isEmpty()) 642 argsReferrer = originDocument->outgoingReferrer(); 643 String referrer = SecurityPolicy::generateReferrerHeader(originDocument->referrerPolicy(), request.url(), argsReferrer); 644 645 request.setHTTPReferrer(referrer); 646 RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer); 647 addHTTPOriginIfNeeded(request, referrerOrigin->toString()); 648 } 649 650 bool FrameLoader::isScriptTriggeredFormSubmissionInChildFrame(const FrameLoadRequest& request) const 651 { 652 // If this is a child frame and the form submission was triggered by a script, lock the back/forward list 653 // to match IE and Opera. 654 // See https://bugs.webkit.org/show_bug.cgi?id=32383 for the original motivation for this. 655 if (!m_frame->tree().parent() || UserGestureIndicator::processingUserGesture()) 656 return false; 657 return request.formState() && request.formState()->formSubmissionTrigger() == SubmittedByJavaScript; 658 } 659 660 FrameLoadType FrameLoader::determineFrameLoadType(const FrameLoadRequest& request) 661 { 662 if (m_frame->tree().parent() && !m_stateMachine.startedFirstRealLoad()) 663 return FrameLoadTypeInitialInChildFrame; 664 if (!m_frame->tree().parent() && !m_frame->page()->backForward().backForwardListCount()) 665 return FrameLoadTypeStandard; 666 if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData) 667 return FrameLoadTypeReload; 668 if (request.lockBackForwardList() || isScriptTriggeredFormSubmissionInChildFrame(request)) 669 return FrameLoadTypeRedirectWithLockedBackForwardList; 670 if (!request.originDocument() && shouldTreatURLAsSameAsCurrent(request.resourceRequest().url())) 671 return FrameLoadTypeSame; 672 if (shouldTreatURLAsSameAsCurrent(request.substituteData().failingURL()) && m_loadType == FrameLoadTypeReload) 673 return FrameLoadTypeReload; 674 return FrameLoadTypeStandard; 675 } 676 677 bool FrameLoader::prepareRequestForThisFrame(FrameLoadRequest& request) 678 { 679 // If no origin Document* was specified, skip security checks and assume the caller has fully initialized the FrameLoadRequest. 680 if (!request.originDocument()) 681 return true; 682 683 KURL url = request.resourceRequest().url(); 684 if (m_frame->script().executeScriptIfJavaScriptURL(url)) 685 return false; 686 687 if (!request.originDocument()->securityOrigin()->canDisplay(url)) { 688 reportLocalLoadFailed(m_frame, url.elidedString()); 689 return false; 690 } 691 692 if (!request.formState() && request.frameName().isEmpty()) 693 request.setFrameName(m_frame->document()->baseTarget()); 694 695 setReferrerForFrameRequest(request.resourceRequest(), request.shouldSendReferrer(), request.originDocument()); 696 return true; 697 } 698 699 void FrameLoader::load(const FrameLoadRequest& passedRequest) 700 { 701 ASSERT(m_frame->document()); 702 703 // Protect frame from getting blown away inside dispatchBeforeLoadEvent in loadWithDocumentLoader. 704 RefPtr<Frame> protect(m_frame); 705 706 if (m_inStopAllLoaders) 707 return; 708 709 FrameLoadRequest request(passedRequest); 710 if (!prepareRequestForThisFrame(request)) 711 return; 712 713 RefPtr<Frame> targetFrame = request.formState() ? 0 : findFrameForNavigation(request.frameName(), request.formState() ? request.formState()->sourceDocument() : m_frame->document()); 714 if (targetFrame && targetFrame != m_frame) { 715 request.setFrameName("_self"); 716 targetFrame->loader().load(request); 717 if (Page* page = targetFrame->page()) 718 page->chrome().focus(); 719 return; 720 } 721 722 FrameLoadType newLoadType = determineFrameLoadType(request); 723 NavigationAction action(request.resourceRequest(), newLoadType, request.formState(), request.triggeringEvent()); 724 if ((!targetFrame && !request.frameName().isEmpty()) || action.shouldOpenInNewWindow()) { 725 if (action.policy() == NavigationPolicyDownload) 726 m_client->loadURLExternally(action.resourceRequest(), NavigationPolicyDownload); 727 else 728 createWindowForRequest(request, m_frame, action.policy(), request.shouldSendReferrer()); 729 return; 730 } 731 732 if (shouldPerformFragmentNavigation(request.formState(), request.resourceRequest().httpMethod(), newLoadType, request.resourceRequest().url())) { 733 checkNavigationPolicyAndContinueFragmentScroll(action, newLoadType != FrameLoadTypeRedirectWithLockedBackForwardList, request.clientRedirect()); 734 return; 735 } 736 bool sameURL = shouldTreatURLAsSameAsCurrent(request.resourceRequest().url()); 737 loadWithNavigationAction(action, newLoadType, request.formState(), request.substituteData(), request.clientRedirect()); 738 // Example of this case are sites that reload the same URL with a different cookie 739 // driving the generated content, or a master frame with links that drive a target 740 // frame, where the user has clicked on the same link repeatedly. 741 if (sameURL && newLoadType != FrameLoadTypeReload && newLoadType != FrameLoadTypeReloadFromOrigin && request.resourceRequest().httpMethod() != "POST") 742 m_loadType = FrameLoadTypeSame; 743 } 744 745 SubstituteData FrameLoader::defaultSubstituteDataForURL(const KURL& url) 746 { 747 if (!shouldTreatURLAsSrcdocDocument(url)) 748 return SubstituteData(); 749 String srcdoc = m_frame->ownerElement()->fastGetAttribute(srcdocAttr); 750 ASSERT(!srcdoc.isNull()); 751 CString encodedSrcdoc = srcdoc.utf8(); 752 return SubstituteData(SharedBuffer::create(encodedSrcdoc.data(), encodedSrcdoc.length()), "text/html", "UTF-8", KURL()); 753 } 754 755 void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url) 756 { 757 ASSERT(!url.isEmpty()); 758 if (!frame) 759 return; 760 761 frame->document()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Not allowed to load local resource: " + url); 762 } 763 764 void FrameLoader::reload(ReloadPolicy reloadPolicy, const KURL& overrideURL, const AtomicString& overrideEncoding) 765 { 766 DocumentLoader* documentLoader = activeDocumentLoader(); 767 if (!documentLoader) 768 return; 769 770 ResourceRequest request = documentLoader->request(); 771 // FIXME: We need to reset cache policy to prevent it from being incorrectly propagted to the reload. 772 // Do we need to propagate anything other than the url? 773 request.setCachePolicy(UseProtocolCachePolicy); 774 if (!overrideURL.isEmpty()) 775 request.setURL(overrideURL); 776 else if (!documentLoader->unreachableURL().isEmpty()) 777 request.setURL(documentLoader->unreachableURL()); 778 779 FrameLoadType type = reloadPolicy == EndToEndReload ? FrameLoadTypeReloadFromOrigin : FrameLoadTypeReload; 780 NavigationAction action(request, type, request.httpMethod() == "POST"); 781 loadWithNavigationAction(action, type, 0, SubstituteData(), NotClientRedirect, overrideEncoding); 782 } 783 784 void FrameLoader::stopAllLoaders() 785 { 786 if (m_frame->document()->pageDismissalEventBeingDispatched() != Document::NoDismissal) 787 return; 788 789 // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this. 790 if (m_inStopAllLoaders) 791 return; 792 793 // Calling stopLoading() on the provisional document loader can blow away 794 // the frame from underneath. 795 RefPtr<Frame> protect(m_frame); 796 797 m_inStopAllLoaders = true; 798 799 for (RefPtr<Frame> child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) 800 child->loader().stopAllLoaders(); 801 if (m_provisionalDocumentLoader) 802 m_provisionalDocumentLoader->stopLoading(); 803 if (m_documentLoader) 804 m_documentLoader->stopLoading(); 805 806 if (m_provisionalDocumentLoader) 807 m_provisionalDocumentLoader->detachFromFrame(); 808 m_provisionalDocumentLoader = 0; 809 810 m_checkTimer.stop(); 811 812 m_inStopAllLoaders = false; 813 814 m_client->didStopAllLoaders(); 815 } 816 817 DocumentLoader* FrameLoader::activeDocumentLoader() const 818 { 819 if (m_state == FrameStateProvisional) 820 return m_provisionalDocumentLoader.get(); 821 return m_documentLoader.get(); 822 } 823 824 void FrameLoader::didAccessInitialDocument() 825 { 826 // We only need to notify the client once, and only for the main frame. 827 if (isLoadingMainFrame() && !m_didAccessInitialDocument) { 828 m_didAccessInitialDocument = true; 829 // Notify asynchronously, since this is called within a JavaScript security check. 830 m_didAccessInitialDocumentTimer.startOneShot(0); 831 } 832 } 833 834 void FrameLoader::didAccessInitialDocumentTimerFired(Timer<FrameLoader>*) 835 { 836 m_client->didAccessInitialDocument(); 837 } 838 839 void FrameLoader::notifyIfInitialDocumentAccessed() 840 { 841 if (m_didAccessInitialDocumentTimer.isActive()) { 842 m_didAccessInitialDocumentTimer.stop(); 843 didAccessInitialDocumentTimerFired(0); 844 } 845 } 846 847 bool FrameLoader::isLoading() const 848 { 849 DocumentLoader* docLoader = activeDocumentLoader(); 850 if (!docLoader) 851 return false; 852 return docLoader->isLoading(); 853 } 854 855 void FrameLoader::commitProvisionalLoad() 856 { 857 ASSERT(m_client->hasWebView()); 858 ASSERT(m_state == FrameStateProvisional); 859 RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader; 860 RefPtr<Frame> protect(m_frame); 861 862 closeOldDataSources(); 863 864 // Check if the destination page is allowed to access the previous page's timing information. 865 if (m_frame->document()) { 866 RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::create(pdl->request().url()); 867 pdl->timing()->setHasSameOriginAsPreviousDocument(securityOrigin->canRequest(m_frame->document()->url())); 868 } 869 870 // The call to closeURL() invokes the unload event handler, which can execute arbitrary 871 // JavaScript. If the script initiates a new load, we need to abandon the current load, 872 // or the two will stomp each other. 873 // detachChildren will similarly trigger child frame unload event handlers. 874 if (m_documentLoader) 875 closeURL(); 876 detachChildren(); 877 if (pdl != m_provisionalDocumentLoader) 878 return; 879 if (m_documentLoader) 880 m_documentLoader->detachFromFrame(); 881 m_documentLoader = m_provisionalDocumentLoader.release(); 882 m_state = FrameStateCommittedPage; 883 884 if (isLoadingMainFrame()) 885 m_frame->page()->chrome().client().needTouchEvents(false); 886 887 m_client->transitionToCommittedForNewPage(); 888 m_frame->navigationScheduler().cancel(); 889 m_frame->editor().clearLastEditCommand(); 890 891 // If we are still in the process of initializing an empty document then 892 // its frame is not in a consistent state for rendering, so avoid setJSStatusBarText 893 // since it may cause clients to attempt to render the frame. 894 if (!m_stateMachine.creatingInitialEmptyDocument()) { 895 DOMWindow* window = m_frame->domWindow(); 896 window->setStatus(String()); 897 window->setDefaultStatus(String()); 898 } 899 started(); 900 } 901 902 void FrameLoader::closeOldDataSources() 903 { 904 // FIXME: Is it important for this traversal to be postorder instead of preorder? 905 // If so, add helpers for postorder traversal, and use them. If not, then lets not 906 // use a recursive algorithm here. 907 for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) 908 child->loader().closeOldDataSources(); 909 910 if (m_documentLoader) 911 m_client->dispatchWillClose(); 912 } 913 914 bool FrameLoader::isLoadingMainFrame() const 915 { 916 return m_frame->isMainFrame(); 917 } 918 919 bool FrameLoader::subframeIsLoading() const 920 { 921 // It's most likely that the last added frame is the last to load so we walk backwards. 922 for (Frame* child = m_frame->tree().lastChild(); child; child = child->tree().previousSibling()) { 923 const FrameLoader& childLoader = child->loader(); 924 DocumentLoader* documentLoader = childLoader.documentLoader(); 925 if (documentLoader && documentLoader->isLoadingInAPISense()) 926 return true; 927 documentLoader = childLoader.provisionalDocumentLoader(); 928 if (documentLoader && documentLoader->isLoadingInAPISense()) 929 return true; 930 documentLoader = childLoader.policyDocumentLoader(); 931 if (documentLoader) 932 return true; 933 } 934 return false; 935 } 936 937 FrameLoadType FrameLoader::loadType() const 938 { 939 return m_loadType; 940 } 941 942 void FrameLoader::checkLoadCompleteForThisFrame() 943 { 944 ASSERT(m_client->hasWebView()); 945 946 if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) { 947 const ResourceError& error = m_provisionalDocumentLoader->mainDocumentError(); 948 if (error.isNull()) 949 return; 950 RefPtr<DocumentLoader> loader = m_provisionalDocumentLoader; 951 m_client->dispatchDidFailProvisionalLoad(error); 952 if (loader != m_provisionalDocumentLoader) 953 return; 954 m_provisionalDocumentLoader->detachFromFrame(); 955 m_provisionalDocumentLoader = 0; 956 m_progressTracker->progressCompleted(); 957 m_state = FrameStateComplete; 958 } 959 960 if (m_state != FrameStateCommittedPage) 961 return; 962 963 if (!m_documentLoader || (m_documentLoader->isLoadingInAPISense() && !m_inStopAllLoaders)) 964 return; 965 966 m_state = FrameStateComplete; 967 968 // FIXME: Is this subsequent work important if we already navigated away? 969 // Maybe there are bugs because of that, or extra work we can skip because 970 // the new page is ready. 971 972 // If the user had a scroll point, scroll to it, overriding the anchor point if any. 973 restoreScrollPositionAndViewState(); 974 975 if (!m_stateMachine.committedFirstRealDocumentLoad()) 976 return; 977 978 m_progressTracker->progressCompleted(); 979 980 const ResourceError& error = m_documentLoader->mainDocumentError(); 981 if (!error.isNull()) 982 m_client->dispatchDidFailLoad(error); 983 else 984 m_client->dispatchDidFinishLoad(); 985 m_loadType = FrameLoadTypeStandard; 986 } 987 988 // There is a race condition between the layout and load completion that affects restoring the scroll position. 989 // We try to restore the scroll position at both the first layout and upon load completion. 990 // 1) If first layout happens before the load completes, we want to restore the scroll position then so that the 991 // first time we draw the page is already scrolled to the right place, instead of starting at the top and later 992 // jumping down. It is possible that the old scroll position is past the part of the doc laid out so far, in 993 // which case the restore silent fails and we will fix it in when we try to restore on doc completion. 994 // 2) If the layout happens after the load completes, the attempt to restore at load completion time silently 995 // fails. We then successfully restore it when the layout happens. 996 void FrameLoader::restoreScrollPositionAndViewState(RestorePolicy restorePolicy) 997 { 998 if (!isBackForwardLoadType(m_loadType) && m_loadType != FrameLoadTypeReload && m_loadType != FrameLoadTypeReloadFromOrigin && restorePolicy != ForcedRestoreForSameDocumentHistoryNavigation) 999 return; 1000 if (!m_frame->page() || !m_currentItem || !m_stateMachine.committedFirstRealDocumentLoad()) 1001 return; 1002 1003 if (FrameView* view = m_frame->view()) { 1004 if (m_frame->isMainFrame()) { 1005 if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scrollingCoordinator()) 1006 scrollingCoordinator->frameViewRootLayerDidChange(view); 1007 } 1008 1009 if (!view->wasScrolledByUser() || restorePolicy == ForcedRestoreForSameDocumentHistoryNavigation) { 1010 if (m_frame->isMainFrame() && m_currentItem->pageScaleFactor()) 1011 m_frame->page()->setPageScaleFactor(m_currentItem->pageScaleFactor(), m_currentItem->scrollPoint()); 1012 else 1013 view->setScrollPositionNonProgrammatically(m_currentItem->scrollPoint()); 1014 } 1015 } 1016 } 1017 1018 void FrameLoader::didFirstLayout() 1019 { 1020 restoreScrollPositionAndViewState(); 1021 } 1022 1023 void FrameLoader::detachChildren() 1024 { 1025 typedef Vector<RefPtr<Frame> > FrameVector; 1026 FrameVector childrenToDetach; 1027 childrenToDetach.reserveCapacity(m_frame->tree().childCount()); 1028 for (Frame* child = m_frame->tree().lastChild(); child; child = child->tree().previousSibling()) 1029 childrenToDetach.append(child); 1030 FrameVector::iterator end = childrenToDetach.end(); 1031 for (FrameVector::iterator it = childrenToDetach.begin(); it != end; it++) 1032 (*it)->loader().detachFromParent(); 1033 } 1034 1035 void FrameLoader::closeAndRemoveChild(Frame* child) 1036 { 1037 child->tree().detachFromParent(); 1038 1039 child->setView(0); 1040 if (child->ownerElement() && child->page()) 1041 child->page()->decrementSubframeCount(); 1042 child->willDetachPage(); 1043 child->detachFromPage(); 1044 1045 m_frame->tree().removeChild(child); 1046 } 1047 1048 // Called every time a resource is completely loaded or an error is received. 1049 void FrameLoader::checkLoadComplete() 1050 { 1051 ASSERT(m_client->hasWebView()); 1052 1053 // FIXME: Always traversing the entire frame tree is a bit inefficient, but 1054 // is currently needed in order to null out the previous history item for all frames. 1055 if (Page* page = m_frame->page()) { 1056 Vector<RefPtr<Frame>, 10> frames; 1057 for (RefPtr<Frame> frame = page->mainFrame(); frame; frame = frame->tree().traverseNext()) 1058 frames.append(frame); 1059 // To process children before their parents, iterate the vector backwards. 1060 for (size_t i = frames.size(); i; --i) 1061 frames[i - 1]->loader().checkLoadCompleteForThisFrame(); 1062 } 1063 } 1064 1065 void FrameLoader::checkLoadComplete(DocumentLoader* documentLoader) 1066 { 1067 if (documentLoader) 1068 documentLoader->checkLoadComplete(); 1069 checkLoadComplete(); 1070 } 1071 1072 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const 1073 { 1074 if (!recurse) 1075 return m_frame->document()->fetcher()->requestCount(); 1076 1077 int count = 0; 1078 for (Frame* frame = m_frame; frame; frame = frame->tree().traverseNext(m_frame)) 1079 count += frame->document()->fetcher()->requestCount(); 1080 return count; 1081 } 1082 1083 String FrameLoader::userAgent(const KURL& url) const 1084 { 1085 String userAgent = m_client->userAgent(url); 1086 InspectorInstrumentation::applyUserAgentOverride(m_frame, &userAgent); 1087 return userAgent; 1088 } 1089 1090 void FrameLoader::frameDetached() 1091 { 1092 // stopAllLoaders can detach the Frame, so protect it. 1093 RefPtr<Frame> protect(m_frame); 1094 stopAllLoaders(); 1095 detachFromParent(); 1096 } 1097 1098 void FrameLoader::detachFromParent() 1099 { 1100 // stopAllLoaders can detach the Frame, so protect it. 1101 RefPtr<Frame> protect(m_frame); 1102 1103 closeURL(); 1104 detachChildren(); 1105 // stopAllLoaders() needs to be called after detachChildren(), because detachedChildren() 1106 // will trigger the unload event handlers of any child frames, and those event 1107 // handlers might start a new subresource load in this frame. 1108 stopAllLoaders(); 1109 1110 InspectorInstrumentation::frameDetachedFromParent(m_frame); 1111 1112 if (m_documentLoader) 1113 m_documentLoader->detachFromFrame(); 1114 m_documentLoader = 0; 1115 m_client->detachedFromParent(); 1116 1117 m_progressTracker.clear(); 1118 1119 if (Frame* parent = m_frame->tree().parent()) { 1120 parent->loader().closeAndRemoveChild(m_frame); 1121 parent->loader().scheduleCheckCompleted(); 1122 } else { 1123 m_frame->setView(0); 1124 m_frame->willDetachPage(); 1125 m_frame->detachFromPage(); 1126 } 1127 } 1128 1129 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request) 1130 { 1131 bool isMainResource = (request.targetType() == ResourceRequest::TargetIsMainFrame) || (request.targetType() == ResourceRequest::TargetIsSubframe); 1132 1133 if (isMainResource && isLoadingMainFrame()) 1134 request.setFirstPartyForCookies(request.url()); 1135 else 1136 request.setFirstPartyForCookies(m_frame->document()->firstPartyForCookies()); 1137 1138 // The remaining modifications are only necessary for HTTP and HTTPS. 1139 if (!request.url().isEmpty() && !request.url().protocolIsInHTTPFamily()) 1140 return; 1141 1142 applyUserAgent(request); 1143 1144 if (request.cachePolicy() == ReloadIgnoringCacheData) { 1145 if (m_loadType == FrameLoadTypeReload) 1146 request.setHTTPHeaderField("Cache-Control", "max-age=0"); 1147 else if (m_loadType == FrameLoadTypeReloadFromOrigin) { 1148 request.setHTTPHeaderField("Cache-Control", "no-cache"); 1149 request.setHTTPHeaderField("Pragma", "no-cache"); 1150 } 1151 } 1152 1153 if (isMainResource) 1154 request.setHTTPAccept(defaultAcceptHeader); 1155 1156 // Make sure we send the Origin header. 1157 addHTTPOriginIfNeeded(request, nullAtom); 1158 } 1159 1160 void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, const AtomicString& origin) 1161 { 1162 if (!request.httpOrigin().isEmpty()) 1163 return; // Request already has an Origin header. 1164 1165 // Don't send an Origin header for GET or HEAD to avoid privacy issues. 1166 // For example, if an intranet page has a hyperlink to an external web 1167 // site, we don't want to include the Origin of the request because it 1168 // will leak the internal host name. Similar privacy concerns have lead 1169 // to the widespread suppression of the Referer header at the network 1170 // layer. 1171 if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD") 1172 return; 1173 1174 // For non-GET and non-HEAD methods, always send an Origin header so the 1175 // server knows we support this feature. 1176 1177 if (origin.isEmpty()) { 1178 // If we don't know what origin header to attach, we attach the value 1179 // for an empty origin. 1180 request.setHTTPOrigin(SecurityOrigin::createUnique()->toString()); 1181 return; 1182 } 1183 1184 request.setHTTPOrigin(origin); 1185 } 1186 1187 const ResourceRequest& FrameLoader::originalRequest() const 1188 { 1189 return activeDocumentLoader()->originalRequestCopy(); 1190 } 1191 1192 void FrameLoader::receivedMainResourceError(const ResourceError& error) 1193 { 1194 // Retain because the stop may release the last reference to it. 1195 RefPtr<Frame> protect(m_frame); 1196 1197 RefPtr<DocumentLoader> loader = activeDocumentLoader(); 1198 if (m_frame->document()->parser()) 1199 m_frame->document()->parser()->stopParsing(); 1200 1201 // FIXME: We really ought to be able to just check for isCancellation() here, but there are some 1202 // ResourceErrors that setIsCancellation() but aren't created by ResourceError::cancelledError(). 1203 ResourceError c(ResourceError::cancelledError(KURL())); 1204 if ((error.errorCode() != c.errorCode() || error.domain() != c.domain()) && m_frame->ownerElement()) 1205 m_frame->ownerElement()->renderFallbackContent(); 1206 1207 checkCompleted(); 1208 if (m_frame->page()) 1209 checkLoadComplete(); 1210 } 1211 1212 void FrameLoader::checkNavigationPolicyAndContinueFragmentScroll(const NavigationAction& action, bool isNewNavigation, ClientRedirectPolicy clientRedirect) 1213 { 1214 m_documentLoader->setTriggeringAction(action); 1215 1216 const ResourceRequest& request = action.resourceRequest(); 1217 if (!m_documentLoader->shouldContinueForNavigationPolicy(request, DocumentLoader::PolicyCheckFragment)) 1218 return; 1219 1220 // If we have a provisional request for a different document, a fragment scroll should cancel it. 1221 if (m_provisionalDocumentLoader && !equalIgnoringFragmentIdentifier(m_provisionalDocumentLoader->request().url(), request.url())) { 1222 m_provisionalDocumentLoader->stopLoading(); 1223 if (m_provisionalDocumentLoader) 1224 m_provisionalDocumentLoader->detachFromFrame(); 1225 m_provisionalDocumentLoader = 0; 1226 } 1227 saveDocumentAndScrollState(); 1228 loadInSameDocument(request.url(), 0, isNewNavigation, clientRedirect); 1229 } 1230 1231 bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission, const String& httpMethod, FrameLoadType loadType, const KURL& url) 1232 { 1233 ASSERT(loadType != FrameLoadTypeBackForward); 1234 ASSERT(loadType != FrameLoadTypeReloadFromOrigin); 1235 // We don't do this if we are submitting a form with method other than "GET", explicitly reloading, 1236 // currently displaying a frameset, or if the URL does not have a fragment. 1237 return (!isFormSubmission || equalIgnoringCase(httpMethod, "GET")) 1238 && loadType != FrameLoadTypeReload 1239 && loadType != FrameLoadTypeSame 1240 && url.hasFragmentIdentifier() 1241 && equalIgnoringFragmentIdentifier(m_frame->document()->url(), url) 1242 // We don't want to just scroll if a link from within a 1243 // frameset is trying to reload the frameset into _top. 1244 && !m_frame->document()->isFrameSet(); 1245 } 1246 1247 void FrameLoader::scrollToFragmentWithParentBoundary(const KURL& url) 1248 { 1249 FrameView* view = m_frame->view(); 1250 if (!view) 1251 return; 1252 1253 // Leaking scroll position to a cross-origin ancestor would permit the so-called "framesniffing" attack. 1254 RefPtr<Frame> boundaryFrame(url.hasFragmentIdentifier() ? m_frame->document()->findUnsafeParentScrollPropagationBoundary() : 0); 1255 1256 if (boundaryFrame) 1257 boundaryFrame->view()->setSafeToPropagateScrollToParent(false); 1258 1259 view->scrollToFragment(url); 1260 1261 if (boundaryFrame) 1262 boundaryFrame->view()->setSafeToPropagateScrollToParent(true); 1263 } 1264 1265 bool FrameLoader::shouldClose() 1266 { 1267 Page* page = m_frame->page(); 1268 if (!page || !page->chrome().canRunBeforeUnloadConfirmPanel()) 1269 return true; 1270 1271 // Store all references to each subframe in advance since beforeunload's event handler may modify frame 1272 Vector<RefPtr<Frame> > targetFrames; 1273 targetFrames.append(m_frame); 1274 for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().traverseNext(m_frame)) 1275 targetFrames.append(child); 1276 1277 bool shouldClose = false; 1278 { 1279 NavigationDisablerForBeforeUnload navigationDisabler; 1280 size_t i; 1281 1282 bool didAllowNavigation = false; 1283 for (i = 0; i < targetFrames.size(); i++) { 1284 if (!targetFrames[i]->tree().isDescendantOf(m_frame)) 1285 continue; 1286 if (!targetFrames[i]->document()->dispatchBeforeUnloadEvent(page->chrome(), didAllowNavigation)) 1287 break; 1288 } 1289 1290 if (i == targetFrames.size()) 1291 shouldClose = true; 1292 } 1293 return shouldClose; 1294 } 1295 1296 void FrameLoader::loadWithNavigationAction(const NavigationAction& action, FrameLoadType type, PassRefPtr<FormState> formState, const SubstituteData& substituteData, ClientRedirectPolicy clientRedirect, const AtomicString& overrideEncoding) 1297 { 1298 ASSERT(m_client->hasWebView()); 1299 if (m_frame->document()->pageDismissalEventBeingDispatched() != Document::NoDismissal) 1300 return; 1301 1302 // We skip dispatching the beforeload event on the frame owner if we've already committed a real 1303 // document load because the event would leak subsequent activity by the frame which the parent 1304 // frame isn't supposed to learn. For example, if the child frame navigated to a new URL, the 1305 // parent frame shouldn't learn the URL. 1306 const ResourceRequest& request = action.resourceRequest(); 1307 if (!m_stateMachine.committedFirstRealDocumentLoad() && m_frame->ownerElement() && !m_frame->ownerElement()->dispatchBeforeLoadEvent(request.url().string())) 1308 return; 1309 1310 if (!m_stateMachine.startedFirstRealLoad()) 1311 m_stateMachine.advanceTo(FrameLoaderStateMachine::StartedFirstRealLoad); 1312 1313 // The current load should replace the history item if it is the first real 1314 // load of the frame. 1315 bool replacesCurrentHistoryItem = false; 1316 if (type == FrameLoadTypeRedirectWithLockedBackForwardList 1317 || !m_stateMachine.committedFirstRealDocumentLoad()) { 1318 replacesCurrentHistoryItem = true; 1319 } 1320 1321 m_policyDocumentLoader = m_client->createDocumentLoader(request, substituteData.isValid() ? substituteData : defaultSubstituteDataForURL(request.url())); 1322 m_policyDocumentLoader->setFrame(m_frame); 1323 m_policyDocumentLoader->setTriggeringAction(action); 1324 m_policyDocumentLoader->setReplacesCurrentHistoryItem(replacesCurrentHistoryItem); 1325 m_policyDocumentLoader->setIsClientRedirect(clientRedirect == ClientRedirect); 1326 1327 if (Frame* parent = m_frame->tree().parent()) 1328 m_policyDocumentLoader->setOverrideEncoding(parent->loader().documentLoader()->overrideEncoding()); 1329 else if (!overrideEncoding.isEmpty()) 1330 m_policyDocumentLoader->setOverrideEncoding(overrideEncoding); 1331 else if (m_documentLoader) 1332 m_policyDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding()); 1333 1334 // stopAllLoaders can detach the Frame, so protect it. 1335 RefPtr<Frame> protect(m_frame); 1336 if ((!m_policyDocumentLoader->shouldContinueForNavigationPolicy(request, DocumentLoader::PolicyCheckStandard) || !shouldClose()) && m_policyDocumentLoader) { 1337 m_policyDocumentLoader->detachFromFrame(); 1338 m_policyDocumentLoader = 0; 1339 return; 1340 } 1341 1342 // A new navigation is in progress, so don't clear the history's provisional item. 1343 stopAllLoaders(); 1344 1345 // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders() 1346 // might detach the current FrameLoader, in which case we should bail on this newly defunct load. 1347 if (!m_frame->page() || !m_policyDocumentLoader) 1348 return; 1349 1350 if (isLoadingMainFrame()) 1351 m_frame->page()->inspectorController().resume(); 1352 m_frame->navigationScheduler().cancel(); 1353 1354 m_provisionalDocumentLoader = m_policyDocumentLoader.release(); 1355 m_loadType = type; 1356 m_state = FrameStateProvisional; 1357 1358 if (formState) 1359 m_client->dispatchWillSubmitForm(formState); 1360 1361 m_progressTracker->progressStarted(); 1362 if (m_provisionalDocumentLoader->isClientRedirect()) 1363 m_provisionalDocumentLoader->appendRedirect(m_frame->document()->url()); 1364 m_provisionalDocumentLoader->appendRedirect(m_provisionalDocumentLoader->request().url()); 1365 m_client->dispatchDidStartProvisionalLoad(); 1366 ASSERT(m_provisionalDocumentLoader); 1367 m_provisionalDocumentLoader->startLoadingMainResource(); 1368 } 1369 1370 void FrameLoader::applyUserAgent(ResourceRequest& request) 1371 { 1372 String userAgent = this->userAgent(request.url()); 1373 ASSERT(!userAgent.isNull()); 1374 request.setHTTPUserAgent(userAgent); 1375 } 1376 1377 bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, const KURL& url, unsigned long requestIdentifier) 1378 { 1379 UseCounter::count(m_frame->domWindow(), UseCounter::XFrameOptions); 1380 1381 Frame* topFrame = m_frame->tree().top(); 1382 if (m_frame == topFrame) 1383 return false; 1384 1385 XFrameOptionsDisposition disposition = parseXFrameOptionsHeader(content); 1386 1387 switch (disposition) { 1388 case XFrameOptionsSameOrigin: { 1389 UseCounter::count(m_frame->domWindow(), UseCounter::XFrameOptionsSameOrigin); 1390 RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url); 1391 if (!origin->isSameSchemeHostPort(topFrame->document()->securityOrigin())) 1392 return true; 1393 for (Frame* frame = m_frame->tree().parent(); frame; frame = frame->tree().parent()) { 1394 if (!origin->isSameSchemeHostPort(frame->document()->securityOrigin())) { 1395 UseCounter::count(m_frame->domWindow(), UseCounter::XFrameOptionsSameOriginWithBadAncestorChain); 1396 break; 1397 } 1398 } 1399 return false; 1400 } 1401 case XFrameOptionsDeny: 1402 return true; 1403 case XFrameOptionsAllowAll: 1404 return false; 1405 case XFrameOptionsConflict: 1406 m_frame->document()->addConsoleMessageWithRequestIdentifier(JSMessageSource, ErrorMessageLevel, "Multiple 'X-Frame-Options' headers with conflicting values ('" + content + "') encountered when loading '" + url.elidedString() + "'. Falling back to 'DENY'.", requestIdentifier); 1407 return true; 1408 case XFrameOptionsInvalid: 1409 m_frame->document()->addConsoleMessageWithRequestIdentifier(JSMessageSource, ErrorMessageLevel, "Invalid 'X-Frame-Options' header encountered when loading '" + url.elidedString() + "': '" + content + "' is not a recognized directive. The header will be ignored.", requestIdentifier); 1410 return false; 1411 default: 1412 ASSERT_NOT_REACHED(); 1413 return false; 1414 } 1415 } 1416 1417 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const 1418 { 1419 if (!m_currentItem) 1420 return false; 1421 return url == m_currentItem->url() || url == m_currentItem->originalURL(); 1422 } 1423 1424 bool FrameLoader::shouldTreatURLAsSrcdocDocument(const KURL& url) const 1425 { 1426 if (!equalIgnoringCase(url.string(), "about:srcdoc")) 1427 return false; 1428 HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement(); 1429 if (!ownerElement) 1430 return false; 1431 if (!ownerElement->hasTagName(iframeTag)) 1432 return false; 1433 return ownerElement->fastHasAttribute(srcdocAttr); 1434 } 1435 1436 Frame* FrameLoader::findFrameForNavigation(const AtomicString& name, Document* activeDocument) 1437 { 1438 ASSERT(activeDocument); 1439 Frame* frame = m_frame->tree().find(name); 1440 1441 // From http://www.whatwg.org/specs/web-apps/current-work/#seamlessLinks: 1442 // 1443 // If the source browsing context is the same as the browsing context 1444 // being navigated, and this browsing context has its seamless browsing 1445 // context flag set, and the browsing context being navigated was not 1446 // chosen using an explicit self-navigation override, then find the 1447 // nearest ancestor browsing context that does not have its seamless 1448 // browsing context flag set, and continue these steps as if that 1449 // browsing context was the one that was going to be navigated instead. 1450 if (frame == m_frame && name != "_self" && m_frame->document()->shouldDisplaySeamlesslyWithParent()) { 1451 for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree().parent()) { 1452 if (!ancestor->document()->shouldDisplaySeamlesslyWithParent()) { 1453 frame = ancestor; 1454 break; 1455 } 1456 } 1457 ASSERT(frame != m_frame); 1458 } 1459 1460 if (!activeDocument->canNavigate(frame)) 1461 return 0; 1462 return frame; 1463 } 1464 1465 void FrameLoader::loadHistoryItem(HistoryItem* item, HistoryLoadType historyLoadType) 1466 { 1467 saveDocumentAndScrollState(); 1468 m_currentItem = item; 1469 if (historyLoadType == HistorySameDocumentLoad) { 1470 loadInSameDocument(item->url(), item->stateObject(), false, NotClientRedirect); 1471 restoreScrollPositionAndViewState(ForcedRestoreForSameDocumentHistoryNavigation); 1472 return; 1473 } 1474 1475 RefPtr<FormData> formData = item->formData(); 1476 ResourceRequest request(item->url()); 1477 request.setHTTPReferrer(item->referrer()); 1478 if (formData) { 1479 request.setHTTPMethod("POST"); 1480 request.setHTTPBody(formData); 1481 request.setHTTPContentType(item->formContentType()); 1482 RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item->referrer()); 1483 addHTTPOriginIfNeeded(request, securityOrigin->toString()); 1484 } 1485 1486 loadWithNavigationAction(NavigationAction(request, FrameLoadTypeBackForward, formData), FrameLoadTypeBackForward, 0, SubstituteData()); 1487 } 1488 1489 void FrameLoader::dispatchDocumentElementAvailable() 1490 { 1491 m_client->documentElementAvailable(); 1492 } 1493 1494 void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() 1495 { 1496 if (!m_frame->script().canExecuteScripts(NotAboutToExecuteScript)) 1497 return; 1498 1499 Vector<RefPtr<DOMWrapperWorld> > worlds; 1500 DOMWrapperWorld::getAllWorlds(worlds); 1501 for (size_t i = 0; i < worlds.size(); ++i) 1502 dispatchDidClearWindowObjectInWorld(worlds[i].get()); 1503 } 1504 1505 void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world) 1506 { 1507 if (!m_frame->script().canExecuteScripts(NotAboutToExecuteScript) || !m_frame->script().existingWindowShell(world)) 1508 return; 1509 1510 m_client->dispatchDidClearWindowObjectInWorld(world); 1511 1512 if (Page* page = m_frame->page()) 1513 page->inspectorController().didClearWindowObjectInWorld(m_frame, world); 1514 1515 InspectorInstrumentation::didClearWindowObjectInWorld(m_frame, world); 1516 } 1517 1518 SandboxFlags FrameLoader::effectiveSandboxFlags() const 1519 { 1520 SandboxFlags flags = m_forcedSandboxFlags; 1521 if (Frame* parentFrame = m_frame->tree().parent()) 1522 flags |= parentFrame->document()->sandboxFlags(); 1523 if (HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement()) 1524 flags |= ownerElement->sandboxFlags(); 1525 return flags; 1526 } 1527 1528 } // namespace WebCore 1529