Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv ed. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv ed. |
| 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
| 4 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/) | 4 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/) |
| 5 * Copyright (C) 2008 Alp Toker <alp@atoker.com> | 5 * Copyright (C) 2008 Alp Toker <alp@atoker.com> |
| 6 * Copyright (C) Research In Motion Limited 2009. All rights reserved. | 6 * Copyright (C) Research In Motion Limited 2009. All rights reserved. |
| 7 * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com> | 7 * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com> |
| 8 * Copyright (C) 2011 Google Inc. All rights reserved. | 8 * Copyright (C) 2011 Google Inc. All rights reserved. |
| 9 * | 9 * |
| 10 * Redistribution and use in source and binary forms, with or without | 10 * Redistribution and use in source and binary forms, with or without |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 240 stopLoading(); | 240 stopLoading(); |
| 241 | 241 |
| 242 if (Page* page = m_frame->page()) | 242 if (Page* page = m_frame->page()) |
| 243 page->undoStack().didUnloadFrame(*m_frame); | 243 page->undoStack().didUnloadFrame(*m_frame); |
| 244 return true; | 244 return true; |
| 245 } | 245 } |
| 246 | 246 |
| 247 void FrameLoader::didExplicitOpen() | 247 void FrameLoader::didExplicitOpen() |
| 248 { | 248 { |
| 249 // Calling document.open counts as committing the first real document load. | 249 // Calling document.open counts as committing the first real document load. |
| 250 if (!m_stateMachine.committedFirstRealDocumentLoad()) { | 250 if (!m_stateMachine.committedFirstRealDocumentLoad()) |
| 251 m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad ); | 251 m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad ); |
| 252 m_progressTracker->progressStarted(); | 252 |
| 253 } | 253 m_progressTracker->progressStarted(); |
|
Nate Chapin
2015/01/12 18:39:30
I should probably explicitly mention what this is
dcheng
2015/01/13 00:20:52
Does this mean a document.write() with no document
Nate Chapin
2015/01/13 21:13:00
I just tested it, and yes :(
Updated this patch t
| |
| 254 | 254 |
| 255 // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results | 255 // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results |
| 256 // from a subsequent window.document.open / window.document.write call. | 256 // from a subsequent window.document.open / window.document.write call. |
| 257 // Canceling redirection here works for all cases because document.open | 257 // Canceling redirection here works for all cases because document.open |
| 258 // implicitly precedes document.write. | 258 // implicitly precedes document.write. |
| 259 m_frame->navigationScheduler().cancel(); | 259 m_frame->navigationScheduler().cancel(); |
| 260 } | 260 } |
| 261 | 261 |
| 262 void FrameLoader::clear() | 262 void FrameLoader::clear() |
| 263 { | 263 { |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 435 // If not, remove them, relayout, and repaint. | 435 // If not, remove them, relayout, and repaint. |
| 436 m_frame->view()->restoreScrollbar(); | 436 m_frame->view()->restoreScrollbar(); |
| 437 scrollToFragmentWithParentBoundary(m_frame->document()->url()); | 437 scrollToFragmentWithParentBoundary(m_frame->document()->url()); |
| 438 } | 438 } |
| 439 | 439 |
| 440 void FrameLoader::loadDone() | 440 void FrameLoader::loadDone() |
| 441 { | 441 { |
| 442 checkCompleted(); | 442 checkCompleted(); |
| 443 } | 443 } |
| 444 | 444 |
| 445 bool FrameLoader::allChildrenAreComplete() const | 445 static bool allChildrenAreComplete(Frame* frame) |
| 446 { | 446 { |
| 447 for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree ().nextSibling()) { | 447 for (Frame* child = frame->tree().firstChild(); child; child = child->tree() .traverseNext(frame)) { |
|
dcheng
2015/01/09 22:52:25
I assume you intentionally changed this from nextS
Nate Chapin
2015/01/12 18:39:30
Done.
| |
| 448 if (!child->isLocalFrame()) { | 448 if (child->isLoading()) |
| 449 if (!child->checkLoadComplete()) { | |
| 450 return false; | |
| 451 } | |
| 452 continue; | |
| 453 } | |
| 454 LocalFrame* frame = toLocalFrame(child); | |
| 455 if (!frame->document()->isLoadCompleted() || frame->loader().m_provision alDocumentLoader) | |
| 456 return false; | 449 return false; |
| 457 } | 450 } |
| 458 return true; | 451 return true; |
| 459 } | 452 } |
| 460 | 453 |
| 461 bool FrameLoader::allAncestorsAreComplete() const | 454 bool FrameLoader::allAncestorsAreComplete() const |
| 462 { | 455 { |
| 463 for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree().parent ()) { | 456 for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree().parent ()) { |
| 464 if (ancestor->isLocalFrame()) { | 457 if (ancestor->isLoading()) |
| 465 if (!toLocalFrame(ancestor)->document()->loadEventFinished()) | 458 return false; |
| 466 return false; | 459 } |
| 467 } else { | 460 return true; |
| 468 if (!ancestor->checkLoadComplete()) { | 461 } |
| 469 return false; | |
| 470 } | |
| 471 } | |
| 472 | 462 |
| 473 } | 463 static bool shouldComplete(Document* document) |
| 464 { | |
| 465 if (document->parsing() || document->isInDOMContentLoaded()) | |
| 466 return false; | |
| 467 if (!document->haveImportsLoaded()) | |
| 468 return false; | |
| 469 if (document->fetcher()->requestCount()) | |
| 470 return false; | |
| 471 if (document->isDelayingLoadEvent()) | |
| 472 return false; | |
| 473 return allChildrenAreComplete(document->frame()); | |
| 474 } | |
| 475 | |
| 476 static bool shouldSendCompleteNotifications(LocalFrame* frame) | |
| 477 { | |
| 478 // Don't send stop notifications for inital empty documents, since they don' t generate start notifications. | |
| 479 if (!frame->loader().stateMachine()->committedFirstRealDocumentLoad()) | |
| 480 return false; | |
| 481 | |
| 482 // FIXME: We might have already sent stop notifications and be re-completing . | |
| 483 if (!frame->isLoading()) | |
| 484 return false; | |
| 485 | |
| 486 // The readystatechanged or load event may have disconnected this frame. | |
| 487 if (!frame->client()) | |
| 488 return false; | |
| 489 | |
| 490 // An event might have restarted a child frame. | |
| 491 if (!allChildrenAreComplete(frame)) | |
| 492 return false; | |
| 493 | |
| 494 // An event might have restarted this frame by scheduling a new navigation. | |
| 495 if (frame->loader().provisionalDocumentLoader()) | |
| 496 return false; | |
| 497 | |
| 498 // We might have declined to run the load event due to an imminent content-i nitiated navigation. | |
| 499 if (!frame->document()->loadEventFinished()) | |
| 500 return false; | |
| 474 return true; | 501 return true; |
| 475 } | 502 } |
| 476 | 503 |
| 477 void FrameLoader::checkCompleted() | 504 void FrameLoader::checkCompleted() |
| 478 { | 505 { |
| 479 RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get()); | 506 RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get()); |
| 480 | 507 if (!shouldComplete(m_frame->document())) |
| 481 if (m_frame->document()->isLoadCompleted() && m_stateMachine.committedFirstR ealDocumentLoad()) | |
| 482 return; | |
| 483 | |
| 484 // Are we still parsing? | |
| 485 if (m_frame->document()->parsing() || m_frame->document()->isInDOMContentLoa ded()) | |
| 486 return; | |
| 487 | |
| 488 // Still waiting imports? | |
| 489 if (!m_frame->document()->haveImportsLoaded()) | |
| 490 return; | |
| 491 | |
| 492 // Still waiting for images/scripts? | |
| 493 if (m_frame->document()->fetcher()->requestCount()) | |
| 494 return; | |
| 495 | |
| 496 // Still waiting for elements that don't go through a FrameLoader? | |
| 497 if (m_frame->document()->isDelayingLoadEvent()) | |
| 498 return; | |
| 499 | |
| 500 // Any frame that hasn't completed yet? | |
| 501 if (!allChildrenAreComplete()) | |
| 502 return; | 508 return; |
| 503 | 509 |
| 504 // OK, completed. | 510 // OK, completed. |
| 505 m_frame->document()->setReadyState(Document::Complete); | 511 m_frame->document()->setReadyState(Document::Complete); |
| 506 if (m_frame->document()->loadEventStillNeeded()) | 512 if (m_frame->document()->loadEventStillNeeded()) |
| 507 m_frame->document()->implicitClose(); | 513 m_frame->document()->implicitClose(); |
| 508 | 514 |
| 509 m_frame->navigationScheduler().startTimer(); | 515 m_frame->navigationScheduler().startTimer(); |
| 510 | 516 |
| 511 // Retry restoring scroll offset since finishing the load event disables con tent | 517 // Retry restoring scroll offset since finishing the load event disables con tent |
| 512 // size clamping. | 518 // size clamping. |
| 513 restoreScrollPositionAndViewState(); | 519 restoreScrollPositionAndViewState(); |
| 514 if (m_frame->view()) | 520 if (m_frame->view()) |
| 515 m_frame->view()->handleLoadCompleted(); | 521 m_frame->view()->handleLoadCompleted(); |
| 516 | 522 |
| 523 if (shouldSendCompleteNotifications(m_frame)) { | |
| 524 m_loadType = FrameLoadTypeStandard; | |
| 525 m_progressTracker->progressCompleted(); | |
| 526 m_frame->localDOMWindow()->finishedLoading(); | |
| 527 | |
| 528 // Report mobile vs. desktop page statistics. This will only report on A ndroid. | |
| 529 if (m_frame->isMainFrame()) | |
| 530 m_frame->document()->viewportDescription().reportMobilePageStats(m_f rame); | |
| 531 client()->dispatchDidFinishLoad(); | |
| 532 } | |
| 533 | |
| 517 Frame* parent = m_frame->tree().parent(); | 534 Frame* parent = m_frame->tree().parent(); |
| 518 if (parent && parent->isLocalFrame()) | 535 if (parent && parent->isLocalFrame()) |
| 519 toLocalFrame(parent)->loader().checkCompleted(); | 536 toLocalFrame(parent)->loader().checkCompleted(); |
| 520 if (m_frame->page()) | |
| 521 checkLoadComplete(); | |
| 522 } | 537 } |
| 523 | 538 |
| 524 void FrameLoader::checkTimerFired(Timer<FrameLoader>*) | 539 void FrameLoader::checkTimerFired(Timer<FrameLoader>*) |
| 525 { | 540 { |
| 526 if (Page* page = m_frame->page()) { | 541 if (Page* page = m_frame->page()) { |
| 527 if (page->defersLoading()) | 542 if (page->defersLoading()) |
| 528 return; | 543 return; |
| 529 } | 544 } |
| 530 checkCompleted(); | 545 checkCompleted(); |
| 531 } | 546 } |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 982 bool FrameLoader::isLoadingMainFrame() const | 997 bool FrameLoader::isLoadingMainFrame() const |
| 983 { | 998 { |
| 984 return m_frame->isMainFrame(); | 999 return m_frame->isMainFrame(); |
| 985 } | 1000 } |
| 986 | 1001 |
| 987 FrameLoadType FrameLoader::loadType() const | 1002 FrameLoadType FrameLoader::loadType() const |
| 988 { | 1003 { |
| 989 return m_loadType; | 1004 return m_loadType; |
| 990 } | 1005 } |
| 991 | 1006 |
| 992 bool FrameLoader::checkLoadCompleteForThisFrame() | |
| 993 { | |
| 994 ASSERT(client()->hasWebView()); | |
| 995 RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get()); | |
| 996 | |
| 997 bool allChildrenAreDoneLoading = true; | |
| 998 for (RefPtrWillBeRawPtr<Frame> child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) { | |
| 999 allChildrenAreDoneLoading &= child->checkLoadComplete(); | |
| 1000 } | |
| 1001 if (!allChildrenAreDoneLoading) | |
| 1002 return false; | |
| 1003 | |
| 1004 if (!m_frame->isLoading()) | |
| 1005 return true; | |
| 1006 if (m_provisionalDocumentLoader || !m_documentLoader) | |
| 1007 return false; | |
| 1008 if (!m_frame->document()->loadEventFinished()) | |
| 1009 return false; | |
| 1010 if (!m_stateMachine.committedFirstRealDocumentLoad()) | |
| 1011 return true; | |
| 1012 | |
| 1013 m_progressTracker->progressCompleted(); | |
| 1014 m_frame->localDOMWindow()->finishedLoading(); | |
| 1015 | |
| 1016 // Report mobile vs. desktop page statistics. This will only report on Andro id. | |
| 1017 if (m_frame->isMainFrame()) | |
| 1018 m_frame->document()->viewportDescription().reportMobilePageStats(m_frame ); | |
| 1019 | |
| 1020 client()->dispatchDidFinishLoad(); | |
| 1021 m_loadType = FrameLoadTypeStandard; | |
| 1022 return true; | |
| 1023 } | |
| 1024 | |
| 1025 void FrameLoader::restoreScrollPositionAndViewState() | 1007 void FrameLoader::restoreScrollPositionAndViewState() |
| 1026 { | 1008 { |
| 1027 FrameView* view = m_frame->view(); | 1009 FrameView* view = m_frame->view(); |
| 1028 if (!m_frame->page() || !view || !m_currentItem || !m_stateMachine.committed FirstRealDocumentLoad()) | 1010 if (!m_frame->page() || !view || !m_currentItem || !m_stateMachine.committed FirstRealDocumentLoad()) |
| 1029 return; | 1011 return; |
| 1030 | 1012 |
| 1031 if (!needsHistoryItemRestore(m_loadType)) | 1013 if (!needsHistoryItemRestore(m_loadType)) |
| 1032 return; | 1014 return; |
| 1033 | 1015 |
| 1034 // This tries to balance 1. restoring as soon as possible, 2. detecting | 1016 // This tries to balance 1. restoring as soon as possible, 2. detecting |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1062 } else { | 1044 } else { |
| 1063 view->setScrollPositionNonProgrammatically(m_currentItem->scrollPoint()) ; | 1045 view->setScrollPositionNonProgrammatically(m_currentItem->scrollPoint()) ; |
| 1064 } | 1046 } |
| 1065 | 1047 |
| 1066 if (m_frame->isMainFrame()) { | 1048 if (m_frame->isMainFrame()) { |
| 1067 if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scroll ingCoordinator()) | 1049 if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scroll ingCoordinator()) |
| 1068 scrollingCoordinator->frameViewRootLayerDidChange(view); | 1050 scrollingCoordinator->frameViewRootLayerDidChange(view); |
| 1069 } | 1051 } |
| 1070 } | 1052 } |
| 1071 | 1053 |
| 1072 // Called every time a resource is completely loaded or an error is received. | |
| 1073 void FrameLoader::checkLoadComplete() | |
| 1074 { | |
| 1075 ASSERT(client()->hasWebView()); | |
| 1076 m_frame->page()->mainFrame()->checkLoadComplete(); | |
| 1077 } | |
| 1078 | |
| 1079 String FrameLoader::userAgent(const KURL& url) const | 1054 String FrameLoader::userAgent(const KURL& url) const |
| 1080 { | 1055 { |
| 1081 String userAgent = client()->userAgent(url); | 1056 String userAgent = client()->userAgent(url); |
| 1082 InspectorInstrumentation::applyUserAgentOverride(m_frame, &userAgent); | 1057 InspectorInstrumentation::applyUserAgentOverride(m_frame, &userAgent); |
| 1083 return userAgent; | 1058 return userAgent; |
| 1084 } | 1059 } |
| 1085 | 1060 |
| 1086 void FrameLoader::detach() | 1061 void FrameLoader::detach() |
| 1087 { | 1062 { |
| 1088 #if !ENABLE(OILPAN) | 1063 #if !ENABLE(OILPAN) |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1125 m_progressTracker->progressCompleted(); | 1100 m_progressTracker->progressCompleted(); |
| 1126 } else { | 1101 } else { |
| 1127 ASSERT(loader == m_documentLoader); | 1102 ASSERT(loader == m_documentLoader); |
| 1128 if (m_frame->document()->parser()) | 1103 if (m_frame->document()->parser()) |
| 1129 m_frame->document()->parser()->stopParsing(); | 1104 m_frame->document()->parser()->stopParsing(); |
| 1130 if (!m_provisionalDocumentLoader && m_frame->isLoading()) { | 1105 if (!m_provisionalDocumentLoader && m_frame->isLoading()) { |
| 1131 client()->dispatchDidFailLoad(error); | 1106 client()->dispatchDidFailLoad(error); |
| 1132 m_progressTracker->progressCompleted(); | 1107 m_progressTracker->progressCompleted(); |
| 1133 } | 1108 } |
| 1134 } | 1109 } |
| 1135 | |
| 1136 checkCompleted(); | 1110 checkCompleted(); |
| 1137 if (m_frame->page()) | |
| 1138 checkLoadComplete(); | |
| 1139 } | 1111 } |
| 1140 | 1112 |
| 1141 bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission, const S tring& httpMethod, FrameLoadType loadType, const KURL& url) | 1113 bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission, const S tring& httpMethod, FrameLoadType loadType, const KURL& url) |
| 1142 { | 1114 { |
| 1143 ASSERT(loadType != FrameLoadTypeReloadFromOrigin); | 1115 ASSERT(loadType != FrameLoadTypeReloadFromOrigin); |
| 1144 // We don't do this if we are submitting a form with method other than "GET" , explicitly reloading, | 1116 // We don't do this if we are submitting a form with method other than "GET" , explicitly reloading, |
| 1145 // currently displaying a frameset, or if the URL does not have a fragment. | 1117 // currently displaying a frameset, or if the URL does not have a fragment. |
| 1146 return (!isFormSubmission || equalIgnoringCase(httpMethod, "GET")) | 1118 return (!isFormSubmission || equalIgnoringCase(httpMethod, "GET")) |
| 1147 && loadType != FrameLoadTypeReload | 1119 && loadType != FrameLoadTypeReload |
| 1148 && loadType != FrameLoadTypeSame | 1120 && loadType != FrameLoadTypeSame |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1432 | 1404 |
| 1433 // FIXME: We need a way to propagate strict mixed content checking flags to | 1405 // FIXME: We need a way to propagate strict mixed content checking flags to |
| 1434 // out-of-process frames. For now, we'll always enforce. | 1406 // out-of-process frames. For now, we'll always enforce. |
| 1435 if (!parentFrame->isLocalFrame()) | 1407 if (!parentFrame->isLocalFrame()) |
| 1436 return true; | 1408 return true; |
| 1437 | 1409 |
| 1438 return toLocalFrame(parentFrame)->document()->shouldEnforceStrictMixedConten tChecking(); | 1410 return toLocalFrame(parentFrame)->document()->shouldEnforceStrictMixedConten tChecking(); |
| 1439 } | 1411 } |
| 1440 | 1412 |
| 1441 } // namespace blink | 1413 } // namespace blink |
| OLD | NEW |