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 |