| 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 |