| Index: chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer_unittest.cc
|
| diff --git a/chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3a4a02afc678fcfbe4da68c535ace4cc3c66eee2
|
| --- /dev/null
|
| +++ b/chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer_unittest.cc
|
| @@ -0,0 +1,270 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer.h"
|
| +
|
| +#include "chrome/browser/browser_process.h"
|
| +#include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h"
|
| +#include "chrome/browser/sessions/session_restore.h"
|
| +#include "chrome/browser/sessions/tab_loader.h"
|
| +#include "chrome/browser/ui/tabs/tab_strip_model.h"
|
| +#include "chrome/browser/ui/tabs/test_tab_strip_model_delegate.h"
|
| +#include "chrome/test/base/testing_profile.h"
|
| +#include "content/public/browser/browser_url_handler.h"
|
| +#include "content/public/common/browser_side_navigation_policy.h"
|
| +#include "content/public/common/referrer.h"
|
| +#include "content/public/test/web_contents_tester.h"
|
| +
|
| +using RestoredTab = SessionRestoreDelegate::RestoredTab;
|
| +
|
| +namespace {
|
| +
|
| +const char kDefaultTestUrl[] = "https://google.com";
|
| +const char kDefaultTestUrl2[] = "https://example.com";
|
| +
|
| +} // namespace
|
| +
|
| +class SessionRestorePageLoadMetricsObserverTest
|
| + : public page_load_metrics::PageLoadMetricsObserverTestHarness {
|
| + protected:
|
| + void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) override {
|
| + std::unique_ptr<SessionRestorePageLoadMetricsObserver> observer =
|
| + SessionRestorePageLoadMetricsObserver::CreateIfNeeded();
|
| + if (observer)
|
| + tracker->AddObserver(std::move(observer));
|
| + }
|
| +
|
| + void SetUp() override {
|
| + page_load_metrics::PageLoadMetricsObserverTestHarness::SetUp();
|
| +
|
| + // Stop the initial loading.
|
| + StopLoading(web_contents());
|
| +
|
| + // Create the tab manager to register its SessionRestoreObserver before
|
| + // session restore starts.
|
| + g_browser_process->GetTabManager();
|
| +
|
| + restored_tabs_.emplace_back(web_contents(), false, false, false);
|
| + PopulateAllFirstPaintTimings(&timing_);
|
| + }
|
| +
|
| + void StartSessionRestore() const {
|
| + // Emulate the start of session restore.
|
| + for (auto& observer : SessionRestore::observers())
|
| + observer.OnSessionRestoreStartedLoadingTabs();
|
| + }
|
| +
|
| + void TearDown() override {
|
| + page_load_metrics::PageLoadMetricsObserverTestHarness::TearDown();
|
| + restored_tabs_.clear();
|
| + }
|
| +
|
| + // Populate first paint and first [contentful,meaningful] paint timings.
|
| + void PopulateAllFirstPaintTimings(
|
| + page_load_metrics::mojom::PageLoadTiming* timing_) {
|
| + page_load_metrics::InitPageLoadTimingForTest(timing_);
|
| + timing_->navigation_start = base::Time::FromDoubleT(1);
|
| + timing_->paint_timing->first_meaningful_paint =
|
| + base::TimeDelta::FromMilliseconds(10);
|
| + PopulateRequiredTimingFields(timing_);
|
| + }
|
| +
|
| + void ExpectFirstPaintMetricsTotalCount(int expected_total_count) {
|
| + // SessionRestorePageLoadMetricsObserver is disabled when browser-side
|
| + // navigation is enabled
|
| + if (content::IsBrowserSideNavigationEnabled())
|
| + expected_total_count = 0;
|
| +
|
| + histogram_tester().ExpectTotalCount(
|
| + internal::kHistogramSessionRestoreForegroundTabFirstPaint,
|
| + expected_total_count);
|
| + histogram_tester().ExpectTotalCount(
|
| + internal::kHistogramSessionRestoreForegroundTabFirstContentfulPaint,
|
| + expected_total_count);
|
| + histogram_tester().ExpectTotalCount(
|
| + internal::kHistogramSessionRestoreForegroundTabFirstMeaningfulPaint,
|
| + expected_total_count);
|
| + }
|
| +
|
| + void RestoreTabs() {
|
| + TabLoader::RestoreTabs(restored_tabs_, base::TimeTicks());
|
| + }
|
| +
|
| + void SimulateTimingUpdate() {
|
| + PageLoadMetricsObserverTestHarness::SimulateTimingUpdate(timing_);
|
| + }
|
| +
|
| + void StopLoading(content::WebContents* contents) {
|
| + content::WebContentsTester::For(contents)->TestSetIsLoading(false);
|
| + }
|
| +
|
| + // Navigate with a RELOAD page transition to emulate session restore.
|
| + void NavigateAndCommitWithReloadTransition(content::WebContents* contents,
|
| + const GURL& url) {
|
| + contents->GetController().LoadURL(
|
| + url, content::Referrer(), ui::PAGE_TRANSITION_RELOAD, std::string());
|
| + GURL loaded_url(url);
|
| + bool reverse_on_redirect = false;
|
| + content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
|
| + &loaded_url, contents->GetBrowserContext(), &reverse_on_redirect);
|
| + // LoadURL created a navigation entry, now simulate the RenderView sending
|
| + // a notification that it actually navigated.
|
| + content::WebContentsTester::For(contents)->CommitPendingNavigation();
|
| + }
|
| +
|
| + private:
|
| + page_load_metrics::mojom::PageLoadTiming timing_;
|
| + std::vector<RestoredTab> restored_tabs_;
|
| +};
|
| +
|
| +TEST_F(SessionRestorePageLoadMetricsObserverTest, NoMetrics) {
|
| + ExpectFirstPaintMetricsTotalCount(0);
|
| +}
|
| +
|
| +TEST_F(SessionRestorePageLoadMetricsObserverTest,
|
| + FirstPaintsOutOfSessionRestore) {
|
| + NavigateAndCommitWithReloadTransition(web_contents(), GURL(kDefaultTestUrl));
|
| + SimulateTimingUpdate();
|
| + ExpectFirstPaintMetricsTotalCount(0);
|
| +}
|
| +
|
| +TEST_F(SessionRestorePageLoadMetricsObserverTest, InitialForegroundTabChanged) {
|
| + TestTabStripModelDelegate tab_strip_delegate;
|
| + TabStripModel tab_strip(&tab_strip_delegate, profile());
|
| + tab_strip.AddObserver(g_browser_process->GetTabManager());
|
| +
|
| + std::unique_ptr<content::WebContents> test_contents(CreateTestWebContents());
|
| + std::vector<RestoredTab> restored_tabs{
|
| + RestoredTab(test_contents.get(), false, false, false),
|
| + RestoredTab(web_contents(), false, false, false)};
|
| +
|
| + // Tab strip with 2 tabs: tab 0 is foreground, tab 1 is background.
|
| + tab_strip.AppendWebContents(restored_tabs[0].contents(), true);
|
| + tab_strip.AppendWebContents(restored_tabs[1].contents(), false);
|
| +
|
| + // Start loading tab 0 but do not finish loading it.
|
| + StartSessionRestore();
|
| + TabLoader::RestoreTabs(restored_tabs, base::TimeTicks());
|
| + NavigateAndCommitWithReloadTransition(restored_tabs[0].contents(),
|
| + GURL(kDefaultTestUrl));
|
| +
|
| + // Switch to tab 1 and load it completely.
|
| + tab_strip.ActivateTabAt(1, true);
|
| + NavigateAndCommitWithReloadTransition(web_contents(), GURL(kDefaultTestUrl));
|
| + SimulateTimingUpdate();
|
| +
|
| + // No paint timings recorded because the initial foreground tab was changed.
|
| + ExpectFirstPaintMetricsTotalCount(0);
|
| +}
|
| +
|
| +TEST_F(SessionRestorePageLoadMetricsObserverTest,
|
| + ForegroundTabLoadedInSessionRestore) {
|
| + // Restore one tab which finishes loading in foreground.
|
| + StartSessionRestore();
|
| + RestoreTabs();
|
| + NavigateAndCommitWithReloadTransition(web_contents(), GURL(kDefaultTestUrl));
|
| + SimulateTimingUpdate();
|
| + ExpectFirstPaintMetricsTotalCount(1);
|
| +}
|
| +
|
| +TEST_F(SessionRestorePageLoadMetricsObserverTest,
|
| + BackgroundTabLoadedInSessionRestore) {
|
| + // Set the tab to background before the PageLoadMetricsObserver was created.
|
| + web_contents()->WasHidden();
|
| +
|
| + // Load the restored tab in background.
|
| + StartSessionRestore();
|
| + RestoreTabs();
|
| + NavigateAndCommitWithReloadTransition(web_contents(), GURL(kDefaultTestUrl));
|
| + SimulateTimingUpdate();
|
| +
|
| + // No paint timings recorded because the loaded tab was in background.
|
| + ExpectFirstPaintMetricsTotalCount(0);
|
| +}
|
| +
|
| +TEST_F(SessionRestorePageLoadMetricsObserverTest,
|
| + TabIsHiddenBeforeFirstPaints) {
|
| + // Hide the tab after it starts loading but before it finishes loading.
|
| + StartSessionRestore();
|
| + RestoreTabs();
|
| + NavigateAndCommitWithReloadTransition(web_contents(), GURL(kDefaultTestUrl));
|
| + web_contents()->WasHidden();
|
| + SimulateTimingUpdate();
|
| +
|
| + // No paint timings recorded because tab was hidden before the first paints.
|
| + ExpectFirstPaintMetricsTotalCount(0);
|
| +}
|
| +
|
| +TEST_F(SessionRestorePageLoadMetricsObserverTest,
|
| + MultipleSessionRestoresWithoutInitialForegroundTabChange) {
|
| + // First session restore.
|
| + StartSessionRestore();
|
| + RestoreTabs();
|
| + NavigateAndCommitWithReloadTransition(web_contents(), GURL(kDefaultTestUrl));
|
| + SimulateTimingUpdate();
|
| + StopLoading(web_contents());
|
| + ExpectFirstPaintMetricsTotalCount(1);
|
| +
|
| + // Clear committed URL so the next session restore starts from an emtpy URL.
|
| + NavigateAndCommitWithReloadTransition(web_contents(), GURL());
|
| + StopLoading(web_contents());
|
| +
|
| + // Second session restore.
|
| + StartSessionRestore();
|
| + RestoreTabs();
|
| +
|
| + // Load the only foreground tab with first paints.
|
| + NavigateAndCommitWithReloadTransition(web_contents(), GURL(kDefaultTestUrl2));
|
| + SimulateTimingUpdate();
|
| + ExpectFirstPaintMetricsTotalCount(2);
|
| +}
|
| +
|
| +TEST_F(SessionRestorePageLoadMetricsObserverTest,
|
| + MultipleSessionRestoresWithInitialForegroundTabChange) {
|
| + TestTabStripModelDelegate tab_strip_delegate;
|
| + TabStripModel tab_strip(&tab_strip_delegate, profile());
|
| + tab_strip.AddObserver(g_browser_process->GetTabManager());
|
| +
|
| + std::unique_ptr<content::WebContents> test_contents(CreateTestWebContents());
|
| + std::vector<RestoredTab> restored_tabs{
|
| + RestoredTab(test_contents.get(), false, false, false),
|
| + RestoredTab(web_contents(), false, false, false)};
|
| +
|
| + // Tab strip with 2 tabs: tab 0 is foreground, tab 1 is background.
|
| + tab_strip.AppendWebContents(restored_tabs[0].contents(), true);
|
| + tab_strip.AppendWebContents(restored_tabs[1].contents(), false);
|
| +
|
| + // First session restore.
|
| + StartSessionRestore();
|
| + TabLoader::RestoreTabs(restored_tabs, base::TimeTicks());
|
| +
|
| + // Start and stop loading foreground tab 0 without first paints.
|
| + NavigateAndCommitWithReloadTransition(restored_tabs[0].contents(),
|
| + GURL(kDefaultTestUrl));
|
| + StopLoading(restored_tabs[0].contents());
|
| +
|
| + // Switch to tab 1 to change the initial foreground tab.
|
| + tab_strip.ActivateTabAt(1, true);
|
| +
|
| + // Load the foreground tab with first paints.
|
| + NavigateAndCommitWithReloadTransition(web_contents(), GURL(kDefaultTestUrl));
|
| + SimulateTimingUpdate();
|
| + StopLoading(web_contents());
|
| +
|
| + // No paint timings recorded because the initial foreground tab was changed.
|
| + ExpectFirstPaintMetricsTotalCount(0);
|
| +
|
| + // Clear committed URL so the next session restore starts from an emtpy URL.
|
| + NavigateAndCommitWithReloadTransition(web_contents(), GURL());
|
| + StopLoading(web_contents());
|
| +
|
| + // Second session restore.
|
| + StartSessionRestore();
|
| + TabLoader::RestoreTabs(restored_tabs, base::TimeTicks());
|
| +
|
| + // Load the foreground tab with first paints.
|
| + NavigateAndCommitWithReloadTransition(web_contents(), GURL(kDefaultTestUrl2));
|
| + SimulateTimingUpdate();
|
| + ExpectFirstPaintMetricsTotalCount(1);
|
| +}
|
|
|