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 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
389 if (Client()) { | 389 if (Client()) { |
390 ScriptForbiddenScope forbid_scripts; | 390 ScriptForbiddenScope forbid_scripts; |
391 Client()->DispatchDidFinishDocumentLoad(); | 391 Client()->DispatchDidFinishDocumentLoad(); |
392 } | 392 } |
393 | 393 |
394 if (Client()) { | 394 if (Client()) { |
395 Client()->RunScriptsAtDocumentReady( | 395 Client()->RunScriptsAtDocumentReady( |
396 document_loader_ ? document_loader_->IsCommittedButEmpty() : true); | 396 document_loader_ ? document_loader_->IsCommittedButEmpty() : true); |
397 } | 397 } |
398 | 398 |
399 CheckCompleted(); | 399 frame_->GetDocument()->CheckCompleted(); |
Nate Chapin
2017/04/11 23:25:50
FrameLoader::FinishedParsing is only called from D
| |
400 | 400 |
401 if (!frame_->View()) | 401 if (!frame_->View()) |
402 return; | 402 return; |
403 | 403 |
404 // Check if the scrollbars are really needed for the content. If not, remove | 404 // Check if the scrollbars are really needed for the content. If not, remove |
405 // them, relayout, and repaint. | 405 // them, relayout, and repaint. |
406 frame_->View()->RestoreScrollbar(); | 406 frame_->View()->RestoreScrollbar(); |
407 ProcessFragment(frame_->GetDocument()->Url(), document_loader_->LoadType(), | 407 ProcessFragment(frame_->GetDocument()->Url(), document_loader_->LoadType(), |
408 kNavigationToDifferentDocument); | 408 kNavigationToDifferentDocument); |
409 } | 409 } |
410 | 410 |
411 static bool AllDescendantsAreComplete(Frame* frame) { | |
412 for (Frame* child = frame->Tree().FirstChild(); child; | |
413 child = child->Tree().TraverseNext(frame)) { | |
414 if (child->IsLoading()) | |
415 return false; | |
416 } | |
417 return true; | |
418 } | |
419 | |
420 bool FrameLoader::AllAncestorsAreComplete() const { | 411 bool FrameLoader::AllAncestorsAreComplete() const { |
421 for (Frame* ancestor = frame_; ancestor; | 412 for (Frame* ancestor = frame_; ancestor; |
422 ancestor = ancestor->Tree().Parent()) { | 413 ancestor = ancestor->Tree().Parent()) { |
423 if (ancestor->IsLoading()) | 414 if (ancestor->IsLoading()) |
424 return false; | 415 return false; |
425 } | 416 } |
426 return true; | 417 return true; |
427 } | 418 } |
428 | 419 |
429 static bool ShouldComplete(Document* document) { | 420 void FrameLoader::DidFinishNavigation() { |
430 if (!document->GetFrame()) | 421 // We should have either finished the provisional or committed navigation if |
431 return false; | 422 // this is called. Only delcare the whole frame finished if neither is in |
432 if (document->Parsing() || document->IsInDOMContentLoaded()) | 423 // progress. |
433 return false; | 424 DCHECK(document_loader_->SentDidFinishLoad() || !HasProvisionalNavigation()); |
434 if (!document->HaveImportsLoaded()) | 425 if (!document_loader_->SentDidFinishLoad() || HasProvisionalNavigation()) |
Nate Chapin
2017/04/11 23:25:50
So now:
* Failing a navigation, whether before or
| |
435 return false; | |
436 if (document->Fetcher()->BlockingRequestCount()) | |
437 return false; | |
438 if (document->IsDelayingLoadEvent()) | |
439 return false; | |
440 return AllDescendantsAreComplete(document->GetFrame()); | |
441 } | |
442 | |
443 static bool ShouldSendFinishNotification(LocalFrame* frame) { | |
444 // Don't send didFinishLoad more than once per DocumentLoader. | |
445 if (frame->Loader().GetDocumentLoader()->SentDidFinishLoad()) | |
446 return false; | |
447 | |
448 // We might have declined to run the load event due to an imminent | |
449 // content-initiated navigation. | |
450 if (!frame->GetDocument()->LoadEventFinished()) | |
451 return false; | |
452 | |
453 // An event might have restarted a child frame. | |
454 if (!AllDescendantsAreComplete(frame)) | |
455 return false; | |
456 | |
457 // Don't notify if the frame is being detached. | |
458 if (!frame->IsAttached()) | |
459 return false; | |
460 | |
461 return true; | |
462 } | |
463 | |
464 static bool ShouldSendCompleteNotification(LocalFrame* frame) { | |
465 // FIXME: We might have already sent stop notifications and be re-completing. | |
466 if (!frame->IsLoading()) | |
467 return false; | |
468 // Only send didStopLoading() if there are no navigations in progress at all, | |
469 // whether committed, provisional, or pending. | |
470 return frame->Loader().GetDocumentLoader()->SentDidFinishLoad() && | |
471 !frame->Loader().HasProvisionalNavigation(); | |
472 } | |
473 | |
474 void FrameLoader::CheckCompleted() { | |
475 if (!ShouldComplete(frame_->GetDocument())) | |
476 return; | 426 return; |
477 | 427 |
478 if (Client()) { | 428 if (frame_->IsLoading()) { |
Nate Chapin
2017/04/11 23:25:50
It's a shame we need to handle the case where DidF
| |
479 Client()->RunScriptsAtDocumentIdle(); | |
480 | |
481 // Injected scripts may have disconnected this frame. | |
482 if (!Client()) | |
483 return; | |
484 | |
485 // Check again, because runScriptsAtDocumentIdle() may have delayed the load | |
486 // event. | |
487 if (!ShouldComplete(frame_->GetDocument())) | |
488 return; | |
489 } | |
490 | |
491 // OK, completed. | |
492 frame_->GetDocument()->SetReadyState(Document::kComplete); | |
493 if (frame_->GetDocument()->LoadEventStillNeeded()) | |
494 frame_->GetDocument()->ImplicitClose(); | |
495 | |
496 frame_->GetNavigationScheduler().StartTimer(); | |
497 | |
498 if (frame_->View()) | |
499 frame_->View()->HandleLoadCompleted(); | |
500 | |
501 // The readystatechanged or load event may have disconnected this frame. | |
502 if (!frame_->Client()) | |
503 return; | |
504 | |
505 if (ShouldSendFinishNotification(frame_)) { | |
506 // Report mobile vs. desktop page statistics. This will only report on | |
507 // Android. | |
508 if (frame_->IsMainFrame()) | |
509 frame_->GetDocument()->GetViewportDescription().ReportMobilePageStats( | |
510 frame_); | |
511 document_loader_->SetSentDidFinishLoad(); | |
512 Client()->DispatchDidFinishLoad(); | |
513 // Finishing the load can detach the frame when running layout tests. | |
514 if (!frame_->Client()) | |
515 return; | |
516 } | |
517 | |
518 if (ShouldSendCompleteNotification(frame_)) { | |
519 progress_tracker_->ProgressCompleted(); | 429 progress_tracker_->ProgressCompleted(); |
520 // Retry restoring scroll offset since finishing loading disables content | 430 // Retry restoring scroll offset since finishing loading disables content |
521 // size clamping. | 431 // size clamping. |
522 RestoreScrollPositionAndViewState(); | 432 RestoreScrollPositionAndViewState(); |
523 if (document_loader_) | 433 if (document_loader_) |
524 document_loader_->SetLoadType(kFrameLoadTypeStandard); | 434 document_loader_->SetLoadType(kFrameLoadTypeStandard); |
525 frame_->DomWindow()->FinishedLoading(); | 435 frame_->DomWindow()->FinishedLoading(); |
526 } | 436 } |
527 | 437 |
528 Frame* parent = frame_->Tree().Parent(); | 438 Frame* parent = frame_->Tree().Parent(); |
529 if (parent && parent->IsLocalFrame()) | 439 if (parent && parent->IsLocalFrame()) |
530 ToLocalFrame(parent)->Loader().CheckCompleted(); | 440 ToLocalFrame(parent)->GetDocument()->CheckCompleted(); |
531 } | 441 } |
532 | 442 |
533 void FrameLoader::CheckTimerFired(TimerBase*) { | 443 void FrameLoader::CheckTimerFired(TimerBase*) { |
534 if (Page* page = frame_->GetPage()) { | 444 if (Page* page = frame_->GetPage()) { |
535 if (page->Suspended()) | 445 if (page->Suspended()) |
536 return; | 446 return; |
537 } | 447 } |
538 CheckCompleted(); | 448 frame_->GetDocument()->CheckCompleted(); |
539 } | 449 } |
540 | 450 |
541 void FrameLoader::ScheduleCheckCompleted() { | 451 void FrameLoader::ScheduleCheckCompleted() { |
542 if (!check_timer_.IsActive()) | 452 if (!check_timer_.IsActive()) |
543 check_timer_.StartOneShot(0, BLINK_FROM_HERE); | 453 check_timer_.StartOneShot(0, BLINK_FROM_HERE); |
544 } | 454 } |
545 | 455 |
546 Frame* FrameLoader::Opener() { | 456 Frame* FrameLoader::Opener() { |
547 return Client() ? Client()->Opener() : 0; | 457 return Client() ? Client()->Opener() : 0; |
548 } | 458 } |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
636 document_loader_->SetIsClientRedirect(client_redirect == | 546 document_loader_->SetIsClientRedirect(client_redirect == |
637 ClientRedirectPolicy::kClientRedirect); | 547 ClientRedirectPolicy::kClientRedirect); |
638 if (history_item) | 548 if (history_item) |
639 document_loader_->SetItemForHistoryNavigation(history_item); | 549 document_loader_->SetItemForHistoryNavigation(history_item); |
640 UpdateForSameDocumentNavigation(url, kSameDocumentNavigationDefault, nullptr, | 550 UpdateForSameDocumentNavigation(url, kSameDocumentNavigationDefault, nullptr, |
641 kScrollRestorationAuto, frame_load_type, | 551 kScrollRestorationAuto, frame_load_type, |
642 initiating_document); | 552 initiating_document); |
643 | 553 |
644 document_loader_->GetInitialScrollState().was_scrolled_by_user = false; | 554 document_loader_->GetInitialScrollState().was_scrolled_by_user = false; |
645 | 555 |
646 CheckCompleted(); | 556 frame_->GetDocument()->CheckCompleted(); |
647 | 557 |
648 frame_->DomWindow()->StatePopped(state_object | 558 frame_->DomWindow()->StatePopped(state_object |
649 ? std::move(state_object) | 559 ? std::move(state_object) |
650 : SerializedScriptValue::NullValue()); | 560 : SerializedScriptValue::NullValue()); |
651 | 561 |
652 if (history_item) | 562 if (history_item) |
653 RestoreScrollPositionAndViewStateForLoadType(frame_load_type); | 563 RestoreScrollPositionAndViewStateForLoadType(frame_load_type); |
654 | 564 |
655 // We need to scroll to the fragment whether or not a hash change occurred, | 565 // We need to scroll to the fragment whether or not a hash change occurred, |
656 // since the user might have scrolled since the previous navigation. | 566 // since the user might have scrolled since the previous navigation. |
(...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1774 // TODO(japhet): This is needed because the browser process DCHECKs if the | 1684 // TODO(japhet): This is needed because the browser process DCHECKs if the |
1775 // first entry we commit in a new frame has replacement set. It's unclear | 1685 // first entry we commit in a new frame has replacement set. It's unclear |
1776 // whether the DCHECK is right, investigate removing this special case. | 1686 // whether the DCHECK is right, investigate removing this special case. |
1777 bool replace_current_item = load_type == kFrameLoadTypeReplaceCurrentItem && | 1687 bool replace_current_item = load_type == kFrameLoadTypeReplaceCurrentItem && |
1778 (!Opener() || !request.Url().IsEmpty()); | 1688 (!Opener() || !request.Url().IsEmpty()); |
1779 loader->SetReplacesCurrentHistoryItem(replace_current_item); | 1689 loader->SetReplacesCurrentHistoryItem(replace_current_item); |
1780 return loader; | 1690 return loader; |
1781 } | 1691 } |
1782 | 1692 |
1783 } // namespace blink | 1693 } // namespace blink |
OLD | NEW |