OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights |
3 * reserved. | 3 * reserved. |
4 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 4 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
5 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. | 5 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. |
6 * (http://www.torchmobile.com/) | 6 * (http://www.torchmobile.com/) |
7 * Copyright (C) 2008 Alp Toker <alp@atoker.com> | 7 * Copyright (C) 2008 Alp Toker <alp@atoker.com> |
8 * Copyright (C) Research In Motion Limited 2009. All rights reserved. | 8 * Copyright (C) Research In Motion Limited 2009. All rights reserved. |
9 * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com> | 9 * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com> |
10 * Copyright (C) 2011 Google Inc. All rights reserved. | 10 * Copyright (C) 2011 Google Inc. All rights reserved. |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 if (Client()) { | 447 if (Client()) { |
448 ScriptForbiddenScope forbid_scripts; | 448 ScriptForbiddenScope forbid_scripts; |
449 Client()->DispatchDidFinishDocumentLoad(); | 449 Client()->DispatchDidFinishDocumentLoad(); |
450 } | 450 } |
451 | 451 |
452 if (Client()) { | 452 if (Client()) { |
453 Client()->RunScriptsAtDocumentReady( | 453 Client()->RunScriptsAtDocumentReady( |
454 document_loader_ ? document_loader_->IsCommittedButEmpty() : true); | 454 document_loader_ ? document_loader_->IsCommittedButEmpty() : true); |
455 } | 455 } |
456 | 456 |
457 CheckCompleted(); | 457 frame_->GetDocument()->CheckCompleted(); |
458 | 458 |
459 if (!frame_->View()) | 459 if (!frame_->View()) |
460 return; | 460 return; |
461 | 461 |
462 // Check if the scrollbars are really needed for the content. If not, remove | 462 // Check if the scrollbars are really needed for the content. If not, remove |
463 // them, relayout, and repaint. | 463 // them, relayout, and repaint. |
464 frame_->View()->RestoreScrollbar(); | 464 frame_->View()->RestoreScrollbar(); |
465 ProcessFragment(frame_->GetDocument()->Url(), document_loader_->LoadType(), | 465 ProcessFragment(frame_->GetDocument()->Url(), document_loader_->LoadType(), |
466 kNavigationToDifferentDocument); | 466 kNavigationToDifferentDocument); |
467 } | 467 } |
468 | 468 |
469 static bool AllDescendantsAreComplete(Frame* frame) { | |
470 for (Frame* child = frame->Tree().FirstChild(); child; | |
471 child = child->Tree().TraverseNext(frame)) { | |
472 if (child->IsLoading()) | |
473 return false; | |
474 } | |
475 return true; | |
476 } | |
477 | |
478 bool FrameLoader::AllAncestorsAreComplete() const { | 469 bool FrameLoader::AllAncestorsAreComplete() const { |
479 for (Frame* ancestor = frame_; ancestor; | 470 for (Frame* ancestor = frame_; ancestor; |
480 ancestor = ancestor->Tree().Parent()) { | 471 ancestor = ancestor->Tree().Parent()) { |
481 if (ancestor->IsLoading()) | 472 if (ancestor->IsLoading()) |
482 return false; | 473 return false; |
483 } | 474 } |
484 return true; | 475 return true; |
485 } | 476 } |
486 | 477 |
487 static bool ShouldComplete(Document* document) { | 478 void FrameLoader::DidFinishNavigation() { |
488 if (!document->GetFrame()) | 479 // We should have either finished the provisional or committed navigation if |
489 return false; | 480 // this is called. Only delcare the whole frame finished if neither is in |
490 if (document->Parsing() || document->IsInDOMContentLoaded()) | 481 // progress. |
491 return false; | 482 DCHECK(document_loader_->SentDidFinishLoad() || !HasProvisionalNavigation()); |
492 if (!document->HaveImportsLoaded()) | 483 if (!document_loader_->SentDidFinishLoad() || HasProvisionalNavigation()) |
493 return false; | |
494 if (document->Fetcher()->BlockingRequestCount()) | |
495 return false; | |
496 if (document->IsDelayingLoadEvent()) | |
497 return false; | |
498 return AllDescendantsAreComplete(document->GetFrame()); | |
499 } | |
500 | |
501 static bool ShouldSendFinishNotification(LocalFrame* frame) { | |
502 // Don't send didFinishLoad more than once per DocumentLoader. | |
503 if (frame->Loader().GetDocumentLoader()->SentDidFinishLoad()) | |
504 return false; | |
505 | |
506 // We might have declined to run the load event due to an imminent | |
507 // content-initiated navigation. | |
508 if (!frame->GetDocument()->LoadEventFinished()) | |
509 return false; | |
510 | |
511 // An event might have restarted a child frame. | |
512 if (!AllDescendantsAreComplete(frame)) | |
513 return false; | |
514 | |
515 // Don't notify if the frame is being detached. | |
516 if (!frame->IsAttached()) | |
517 return false; | |
518 | |
519 return true; | |
520 } | |
521 | |
522 static bool ShouldSendCompleteNotification(LocalFrame* frame) { | |
523 // FIXME: We might have already sent stop notifications and be re-completing. | |
524 if (!frame->IsLoading()) | |
525 return false; | |
526 // Only send didStopLoading() if there are no navigations in progress at all, | |
527 // whether committed, provisional, or pending. | |
528 return frame->Loader().GetDocumentLoader()->SentDidFinishLoad() && | |
529 !frame->Loader().HasProvisionalNavigation(); | |
530 } | |
531 | |
532 void FrameLoader::CheckCompleted() { | |
533 if (!ShouldComplete(frame_->GetDocument())) | |
534 return; | 484 return; |
535 | 485 |
536 if (Client()) { | 486 if (frame_->IsLoading()) { |
537 Client()->RunScriptsAtDocumentIdle(); | |
538 | |
539 // Injected scripts may have disconnected this frame. | |
540 if (!Client()) | |
541 return; | |
542 | |
543 // Check again, because runScriptsAtDocumentIdle() may have delayed the load | |
544 // event. | |
545 if (!ShouldComplete(frame_->GetDocument())) | |
546 return; | |
547 } | |
548 | |
549 // OK, completed. | |
550 frame_->GetDocument()->SetReadyState(Document::kComplete); | |
551 if (frame_->GetDocument()->LoadEventStillNeeded()) | |
552 frame_->GetDocument()->ImplicitClose(); | |
553 | |
554 frame_->GetNavigationScheduler().StartTimer(); | |
555 | |
556 if (frame_->View()) | |
557 frame_->View()->HandleLoadCompleted(); | |
558 | |
559 // The readystatechanged or load event may have disconnected this frame. | |
560 if (!frame_->Client()) | |
561 return; | |
562 | |
563 if (ShouldSendFinishNotification(frame_)) { | |
564 // Report mobile vs. desktop page statistics. This will only report on | |
565 // Android. | |
566 if (frame_->IsMainFrame()) | |
567 frame_->GetDocument()->GetViewportDescription().ReportMobilePageStats( | |
568 frame_); | |
569 document_loader_->SetSentDidFinishLoad(); | |
570 Client()->DispatchDidFinishLoad(); | |
571 // Finishing the load can detach the frame when running layout tests. | |
572 if (!frame_->Client()) | |
573 return; | |
574 } | |
575 | |
576 if (ShouldSendCompleteNotification(frame_)) { | |
577 progress_tracker_->ProgressCompleted(); | 487 progress_tracker_->ProgressCompleted(); |
578 // Retry restoring scroll offset since finishing loading disables content | 488 // Retry restoring scroll offset since finishing loading disables content |
579 // size clamping. | 489 // size clamping. |
580 RestoreScrollPositionAndViewState(); | 490 RestoreScrollPositionAndViewState(); |
581 if (document_loader_) | 491 if (document_loader_) |
582 document_loader_->SetLoadType(kFrameLoadTypeStandard); | 492 document_loader_->SetLoadType(kFrameLoadTypeStandard); |
583 frame_->DomWindow()->FinishedLoading(); | 493 frame_->DomWindow()->FinishedLoading(); |
584 } | 494 } |
585 | 495 |
586 Frame* parent = frame_->Tree().Parent(); | 496 Frame* parent = frame_->Tree().Parent(); |
587 if (parent && parent->IsLocalFrame()) | 497 if (parent && parent->IsLocalFrame()) |
588 ToLocalFrame(parent)->Loader().CheckCompleted(); | 498 ToLocalFrame(parent)->GetDocument()->CheckCompleted(); |
589 } | 499 } |
590 | 500 |
591 void FrameLoader::CheckTimerFired(TimerBase*) { | 501 void FrameLoader::CheckTimerFired(TimerBase*) { |
592 if (Page* page = frame_->GetPage()) { | 502 if (Page* page = frame_->GetPage()) { |
593 if (page->Suspended()) | 503 if (page->Suspended()) |
594 return; | 504 return; |
595 } | 505 } |
596 CheckCompleted(); | 506 frame_->GetDocument()->CheckCompleted(); |
597 } | 507 } |
598 | 508 |
599 void FrameLoader::ScheduleCheckCompleted() { | 509 void FrameLoader::ScheduleCheckCompleted() { |
600 if (!check_timer_.IsActive()) | 510 if (!check_timer_.IsActive()) |
601 check_timer_.StartOneShot(0, BLINK_FROM_HERE); | 511 check_timer_.StartOneShot(0, BLINK_FROM_HERE); |
602 } | 512 } |
603 | 513 |
604 Frame* FrameLoader::Opener() { | 514 Frame* FrameLoader::Opener() { |
605 return Client() ? Client()->Opener() : 0; | 515 return Client() ? Client()->Opener() : 0; |
606 } | 516 } |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 document_loader_->SetIsClientRedirect(client_redirect == | 604 document_loader_->SetIsClientRedirect(client_redirect == |
695 ClientRedirectPolicy::kClientRedirect); | 605 ClientRedirectPolicy::kClientRedirect); |
696 if (history_item) | 606 if (history_item) |
697 document_loader_->SetItemForHistoryNavigation(history_item); | 607 document_loader_->SetItemForHistoryNavigation(history_item); |
698 UpdateForSameDocumentNavigation(url, kSameDocumentNavigationDefault, nullptr, | 608 UpdateForSameDocumentNavigation(url, kSameDocumentNavigationDefault, nullptr, |
699 kScrollRestorationAuto, frame_load_type, | 609 kScrollRestorationAuto, frame_load_type, |
700 initiating_document); | 610 initiating_document); |
701 | 611 |
702 document_loader_->GetInitialScrollState().was_scrolled_by_user = false; | 612 document_loader_->GetInitialScrollState().was_scrolled_by_user = false; |
703 | 613 |
704 CheckCompleted(); | 614 frame_->GetDocument()->CheckCompleted(); |
705 | 615 |
706 frame_->DomWindow()->StatePopped(state_object | 616 frame_->DomWindow()->StatePopped(state_object |
707 ? std::move(state_object) | 617 ? std::move(state_object) |
708 : SerializedScriptValue::NullValue()); | 618 : SerializedScriptValue::NullValue()); |
709 | 619 |
710 if (history_item) | 620 if (history_item) |
711 RestoreScrollPositionAndViewStateForLoadType(frame_load_type); | 621 RestoreScrollPositionAndViewStateForLoadType(frame_load_type); |
712 | 622 |
713 // We need to scroll to the fragment whether or not a hash change occurred, | 623 // We need to scroll to the fragment whether or not a hash change occurred, |
714 // since the user might have scrolled since the previous navigation. | 624 // since the user might have scrolled since the previous navigation. |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1074 return; | 984 return; |
1075 | 985 |
1076 in_stop_all_loaders_ = true; | 986 in_stop_all_loaders_ = true; |
1077 | 987 |
1078 for (Frame* child = frame_->Tree().FirstChild(); child; | 988 for (Frame* child = frame_->Tree().FirstChild(); child; |
1079 child = child->Tree().NextSibling()) { | 989 child = child->Tree().NextSibling()) { |
1080 if (child->IsLocalFrame()) | 990 if (child->IsLocalFrame()) |
1081 ToLocalFrame(child)->Loader().StopAllLoaders(); | 991 ToLocalFrame(child)->Loader().StopAllLoaders(); |
1082 } | 992 } |
1083 | 993 |
1084 frame_->GetDocument()->SuppressLoadEvent(); | 994 frame_->GetDocument()->CancelParsing(); |
1085 if (document_loader_) | 995 if (document_loader_) |
1086 document_loader_->Fetcher()->StopFetching(); | 996 document_loader_->Fetcher()->StopFetching(); |
1087 frame_->GetDocument()->CancelParsing(); | |
1088 if (!protect_provisional_loader_) | 997 if (!protect_provisional_loader_) |
1089 DetachDocumentLoader(provisional_document_loader_); | 998 DetachDocumentLoader(provisional_document_loader_); |
1090 | 999 |
1091 check_timer_.Stop(); | 1000 check_timer_.Stop(); |
1092 frame_->GetNavigationScheduler().Cancel(); | 1001 frame_->GetNavigationScheduler().Cancel(); |
1093 | 1002 |
1094 // It's possible that the above actions won't have stopped loading if load | 1003 // It's possible that the above actions won't have stopped loading if load |
1095 // completion had been blocked on parsing or if we were in the middle of | 1004 // completion had been blocked on parsing or if we were in the middle of |
1096 // committing an empty document. In that case, emulate a failed navigation. | 1005 // committing an empty document. In that case, emulate a failed navigation. |
1097 if (!provisional_document_loader_ && document_loader_ && | 1006 if (!provisional_document_loader_ && document_loader_ && |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1324 progress_tracker_.Clear(); | 1233 progress_tracker_.Clear(); |
1325 } | 1234 } |
1326 | 1235 |
1327 TRACE_EVENT_OBJECT_DELETED_WITH_ID("loading", "FrameLoader", this); | 1236 TRACE_EVENT_OBJECT_DELETED_WITH_ID("loading", "FrameLoader", this); |
1328 detached_ = true; | 1237 detached_ = true; |
1329 } | 1238 } |
1330 | 1239 |
1331 void FrameLoader::DetachProvisionalDocumentLoader(DocumentLoader* loader) { | 1240 void FrameLoader::DetachProvisionalDocumentLoader(DocumentLoader* loader) { |
1332 DCHECK_EQ(loader, provisional_document_loader_); | 1241 DCHECK_EQ(loader, provisional_document_loader_); |
1333 DetachDocumentLoader(provisional_document_loader_); | 1242 DetachDocumentLoader(provisional_document_loader_); |
| 1243 DidFinishNavigation(); |
1334 } | 1244 } |
1335 | 1245 |
1336 bool FrameLoader::ShouldPerformFragmentNavigation(bool is_form_submission, | 1246 bool FrameLoader::ShouldPerformFragmentNavigation(bool is_form_submission, |
1337 const String& http_method, | 1247 const String& http_method, |
1338 FrameLoadType load_type, | 1248 FrameLoadType load_type, |
1339 const KURL& url) { | 1249 const KURL& url) { |
1340 // We don't do this if we are submitting a form with method other than "GET", | 1250 // We don't do this if we are submitting a form with method other than "GET", |
1341 // explicitly reloading, currently displaying a frameset, or if the URL does | 1251 // explicitly reloading, currently displaying a frameset, or if the URL does |
1342 // not have a fragment. | 1252 // not have a fragment. |
1343 return DeprecatedEqualIgnoringCase(http_method, HTTPNames::GET) && | 1253 return DeprecatedEqualIgnoringCase(http_method, HTTPNames::GET) && |
(...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1850 // TODO(japhet): This is needed because the browser process DCHECKs if the | 1760 // TODO(japhet): This is needed because the browser process DCHECKs if the |
1851 // first entry we commit in a new frame has replacement set. It's unclear | 1761 // first entry we commit in a new frame has replacement set. It's unclear |
1852 // whether the DCHECK is right, investigate removing this special case. | 1762 // whether the DCHECK is right, investigate removing this special case. |
1853 bool replace_current_item = load_type == kFrameLoadTypeReplaceCurrentItem && | 1763 bool replace_current_item = load_type == kFrameLoadTypeReplaceCurrentItem && |
1854 (!Opener() || !request.Url().IsEmpty()); | 1764 (!Opener() || !request.Url().IsEmpty()); |
1855 loader->SetReplacesCurrentHistoryItem(replace_current_item); | 1765 loader->SetReplacesCurrentHistoryItem(replace_current_item); |
1856 return loader; | 1766 return loader; |
1857 } | 1767 } |
1858 | 1768 |
1859 } // namespace blink | 1769 } // namespace blink |
OLD | NEW |