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 424 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 allDescendantsAreComplete(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)) { |
448 if (!child->isLocalFrame()) { | 448 if (child->isLoadingAsChild()) |
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 allDescendantsAreComplete(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 (!allDescendantsAreComplete(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 |