| Index: chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
|
| diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
|
| index d69596d91d1237754423b7a0bef40dc08c2d9ca2..e165403c3b58a6654ed90c92b410089de4d51000 100644
|
| --- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
|
| +++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
|
| @@ -2,10 +2,17 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| +#include <memory>
|
| +#include <string>
|
| +#include <unordered_set>
|
| +#include <utility>
|
| +#include <vector>
|
| +
|
| #include "base/command_line.h"
|
| #include "base/files/scoped_temp_dir.h"
|
| #include "base/logging.h"
|
| #include "base/macros.h"
|
| +#include "base/memory/ptr_util.h"
|
| #include "base/memory/weak_ptr.h"
|
| #include "base/run_loop.h"
|
| #include "base/test/histogram_tester.h"
|
| @@ -19,12 +26,16 @@
|
| #include "chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h"
|
| #include "chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.h"
|
| #include "chrome/browser/page_load_metrics/observers/no_state_prefetch_page_load_metrics_observer.h"
|
| +#include "chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer.h"
|
| #include "chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.h"
|
| +#include "chrome/browser/page_load_metrics/page_load_metrics_initialize.h"
|
| #include "chrome/browser/page_load_metrics/page_load_tracker.h"
|
| #include "chrome/browser/prefs/session_startup_pref.h"
|
| #include "chrome/browser/prerender/prerender_histograms.h"
|
| #include "chrome/browser/prerender/prerender_origin.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/sessions/session_restore.h"
|
| +#include "chrome/browser/sessions/session_restore_test_helper.h"
|
| #include "chrome/browser/sessions/session_service_factory.h"
|
| #include "chrome/browser/sessions/session_service_test_helper.h"
|
| #include "chrome/browser/ui/browser.h"
|
| @@ -37,11 +48,14 @@
|
| #include "chrome/test/base/in_process_browser_test.h"
|
| #include "chrome/test/base/ui_test_utils.h"
|
| #include "components/prefs/pref_service.h"
|
| +#include "components/sessions/core/serialized_navigation_entry.h"
|
| +#include "components/sessions/core/serialized_navigation_entry_test_helper.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/render_process_host.h"
|
| #include "content/public/browser/render_view_host.h"
|
| #include "content/public/common/content_features.h"
|
| #include "content/public/common/content_switches.h"
|
| +#include "content/public/common/referrer.h"
|
| #include "content/public/test/browser_test_utils.h"
|
| #include "content/public/test/download_test_observer.h"
|
| #include "net/base/net_errors.h"
|
| @@ -53,6 +67,7 @@
|
| #include "net/url_request/url_request_context.h"
|
| #include "net/url_request/url_request_context_getter.h"
|
| #include "third_party/WebKit/public/platform/web_feature.mojom.h"
|
| +#include "url/gurl.h"
|
|
|
| namespace {
|
|
|
| @@ -1118,19 +1133,20 @@ class SessionRestorePageLoadMetricsBrowserTest
|
| // PageLoadMetricsBrowserTest:
|
| void SetUpOnMainThread() override {
|
| PageLoadMetricsBrowserTest::SetUpOnMainThread();
|
| - SessionStartupPref::SetStartupPref(
|
| - browser()->profile(), SessionStartupPref(SessionStartupPref::LAST));
|
| ASSERT_TRUE(embedded_test_server()->Start());
|
| + }
|
| +
|
| + Browser* QuitBrowserAndRestore(Browser* browser) {
|
| + Profile* profile = browser->profile();
|
| +
|
| + SessionStartupPref::SetStartupPref(
|
| + profile, SessionStartupPref(SessionStartupPref::LAST));
|
| #if defined(OS_CHROMEOS)
|
| SessionServiceTestHelper helper(
|
| - SessionServiceFactory::GetForProfile(browser()->profile()));
|
| + SessionServiceFactory::GetForProfile(profile));
|
| helper.SetForceBrowserNotAliveWithNoWindows(true);
|
| helper.ReleaseService();
|
| #endif
|
| - }
|
| -
|
| - Browser* QuitBrowserAndRestore(Browser* browser) {
|
| - Profile* profile = browser->profile();
|
|
|
| std::unique_ptr<ScopedKeepAlive> keep_alive(new ScopedKeepAlive(
|
| KeepAliveOrigin::SESSION_RESTORE, KeepAliveRestartOption::DISABLED));
|
| @@ -1139,7 +1155,11 @@ class SessionRestorePageLoadMetricsBrowserTest
|
| // Create a new window, which should trigger session restore.
|
| chrome::NewEmptyWindow(profile);
|
| ui_test_utils::BrowserAddedObserver window_observer;
|
| - return window_observer.WaitForSingleNewBrowser();
|
| + SessionRestoreTestHelper restore_observer;
|
| +
|
| + Browser* new_browser = window_observer.WaitForSingleNewBrowser();
|
| + restore_observer.Wait();
|
| + return new_browser;
|
| }
|
|
|
| void WaitForTabsToLoad(Browser* browser) {
|
| @@ -1147,18 +1167,72 @@ class SessionRestorePageLoadMetricsBrowserTest
|
| content::WebContents* contents =
|
| browser->tab_strip_model()->GetWebContentsAt(i);
|
| contents->GetController().LoadIfNecessary();
|
| - content::WaitForLoadStop(contents);
|
| + ASSERT_TRUE(content::WaitForLoadStop(contents));
|
| }
|
| }
|
|
|
| + // The PageLoadMetricsWaiter can observe first meaningful paints on these test
|
| + // pages while not on other simple pages such as /title1.html.
|
| GURL GetTestURL() const {
|
| - return embedded_test_server()->GetURL("/title1.html");
|
| + return embedded_test_server()->GetURL(
|
| + "/page_load_metrics/main_frame_with_iframe.html");
|
| + }
|
| +
|
| + GURL GetTestURL2() const {
|
| + return embedded_test_server()->GetURL("/title2.html");
|
| + }
|
| +
|
| + void ExpectFirstPaintMetricsTotalCount(int expected_total_count) const {
|
| + histogram_tester_.ExpectTotalCount(
|
| + internal::kHistogramSessionRestoreForegroundTabFirstPaint,
|
| + expected_total_count);
|
| + histogram_tester_.ExpectTotalCount(
|
| + internal::kHistogramSessionRestoreForegroundTabFirstContentfulPaint,
|
| + expected_total_count);
|
| + histogram_tester_.ExpectTotalCount(
|
| + internal::kHistogramSessionRestoreForegroundTabFirstMeaningfulPaint,
|
| + expected_total_count);
|
| }
|
|
|
| private:
|
| DISALLOW_COPY_AND_ASSIGN(SessionRestorePageLoadMetricsBrowserTest);
|
| };
|
|
|
| +class SessionRestorePaintWaiter : public SessionRestoreObserver {
|
| + public:
|
| + SessionRestorePaintWaiter() { SessionRestore::AddObserver(this); }
|
| + ~SessionRestorePaintWaiter() { SessionRestore::RemoveObserver(this); }
|
| +
|
| + // SessionRestoreObserver implementation:
|
| + void OnWillRestoreTab(content::WebContents* contents) override {
|
| + chrome::InitializePageLoadMetricsForWebContents(contents);
|
| + auto waiter = base::MakeUnique<PageLoadMetricsWaiter>(contents);
|
| + waiter->AddPageExpectation(TimingField::FIRST_PAINT);
|
| + waiter->AddPageExpectation(TimingField::FIRST_CONTENTFUL_PAINT);
|
| + waiter->AddPageExpectation(TimingField::FIRST_MEANINGFUL_PAINT);
|
| + waiters_[contents] = std::move(waiter);
|
| + }
|
| +
|
| + // First meaningful paints occur only on foreground tabs.
|
| + void WaitForForegroundTabs(size_t num_expected_foreground_tabs) {
|
| + size_t num_actual_foreground_tabs = 0;
|
| + for (auto iter = waiters_.begin(); iter != waiters_.end(); ++iter) {
|
| + if (!iter->first->IsVisible())
|
| + continue;
|
| + iter->second->Wait();
|
| + ++num_actual_foreground_tabs;
|
| + }
|
| + EXPECT_EQ(num_expected_foreground_tabs, num_actual_foreground_tabs);
|
| + }
|
| +
|
| + private:
|
| + std::unordered_map<content::WebContents*,
|
| + std::unique_ptr<PageLoadMetricsWaiter>>
|
| + waiters_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SessionRestorePaintWaiter);
|
| +};
|
| +
|
| IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
|
| InitialVisibilityOfSingleRestoredTab) {
|
| ui_test_utils::NavigateToURL(browser(), GetTestURL());
|
| @@ -1168,7 +1242,7 @@ IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
|
| page_load_metrics::internal::kPageLoadStartedInForeground, true, 1);
|
|
|
| Browser* new_browser = QuitBrowserAndRestore(browser());
|
| - WaitForTabsToLoad(new_browser);
|
| + ASSERT_NO_FATAL_FAILURE(WaitForTabsToLoad(new_browser));
|
|
|
| histogram_tester_.ExpectTotalCount(
|
| page_load_metrics::internal::kPageLoadStartedInForeground, 2);
|
| @@ -1188,7 +1262,7 @@ IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
|
| page_load_metrics::internal::kPageLoadStartedInForeground, false, 1);
|
|
|
| Browser* new_browser = QuitBrowserAndRestore(browser());
|
| - WaitForTabsToLoad(new_browser);
|
| + ASSERT_NO_FATAL_FAILURE(WaitForTabsToLoad(new_browser));
|
|
|
| TabStripModel* tab_strip = new_browser->tab_strip_model();
|
| ASSERT_TRUE(tab_strip);
|
| @@ -1201,3 +1275,229 @@ IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
|
| histogram_tester_.ExpectBucketCount(
|
| page_load_metrics::internal::kPageLoadStartedInForeground, false, 2);
|
| }
|
| +
|
| +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
|
| + NoSessionRestore) {
|
| + ui_test_utils::NavigateToURL(browser(), GetTestURL());
|
| + ExpectFirstPaintMetricsTotalCount(0);
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
|
| + SingleTabSessionRestore) {
|
| + ui_test_utils::NavigateToURL(browser(), GetTestURL());
|
| +
|
| + SessionRestorePaintWaiter session_restore_paint_waiter;
|
| + QuitBrowserAndRestore(browser());
|
| +
|
| + session_restore_paint_waiter.WaitForForegroundTabs(1);
|
| + ExpectFirstPaintMetricsTotalCount(1);
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
|
| + MultipleTabsSessionRestore) {
|
| + ui_test_utils::NavigateToURL(browser(), GetTestURL());
|
| + ui_test_utils::NavigateToURLWithDisposition(
|
| + browser(), GetTestURL(), WindowOpenDisposition::NEW_BACKGROUND_TAB,
|
| + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
|
| +
|
| + SessionRestorePaintWaiter session_restore_paint_waiter;
|
| + Browser* new_browser = QuitBrowserAndRestore(browser());
|
| +
|
| + TabStripModel* tab_strip = new_browser->tab_strip_model();
|
| + ASSERT_TRUE(tab_strip);
|
| + ASSERT_EQ(2, tab_strip->count());
|
| +
|
| + // Only metrics of the initial foreground tab are recorded.
|
| + session_restore_paint_waiter.WaitForForegroundTabs(1);
|
| + ExpectFirstPaintMetricsTotalCount(1);
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
|
| + NavigationDuringSessionRestore) {
|
| + NavigateToUntrackedUrl();
|
| + Browser* new_browser = QuitBrowserAndRestore(browser());
|
| +
|
| + auto waiter = base::MakeUnique<PageLoadMetricsWaiter>(
|
| + new_browser->tab_strip_model()->GetActiveWebContents());
|
| + waiter->AddPageExpectation(TimingField::FIRST_MEANINGFUL_PAINT);
|
| + ui_test_utils::NavigateToURL(new_browser, GetTestURL());
|
| + waiter->Wait();
|
| +
|
| + // No metrics recorded for the second navigation because the tab navigated
|
| + // away during session restore.
|
| + ExpectFirstPaintMetricsTotalCount(0);
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
|
| + LoadingAfterSessionRestore) {
|
| + ui_test_utils::NavigateToURL(browser(), GetTestURL());
|
| +
|
| + Browser* new_browser = nullptr;
|
| + {
|
| + SessionRestorePaintWaiter session_restore_paint_waiter;
|
| + new_browser = QuitBrowserAndRestore(browser());
|
| +
|
| + session_restore_paint_waiter.WaitForForegroundTabs(1);
|
| + ExpectFirstPaintMetricsTotalCount(1);
|
| + }
|
| +
|
| + // Load a new page after session restore.
|
| + auto waiter = base::MakeUnique<PageLoadMetricsWaiter>(
|
| + new_browser->tab_strip_model()->GetActiveWebContents());
|
| + waiter->AddPageExpectation(TimingField::FIRST_MEANINGFUL_PAINT);
|
| + ui_test_utils::NavigateToURL(new_browser, GetTestURL());
|
| + waiter->Wait();
|
| +
|
| + // No more metrics because the navigation is after session restore.
|
| + ExpectFirstPaintMetricsTotalCount(1);
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
|
| + InitialForegroundTabChanged) {
|
| + ui_test_utils::NavigateToURL(browser(), GetTestURL());
|
| + ui_test_utils::NavigateToURLWithDisposition(
|
| + browser(), GetTestURL(), WindowOpenDisposition::NEW_BACKGROUND_TAB,
|
| + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
|
| +
|
| + SessionRestorePaintWaiter session_restore_paint_waiter;
|
| + Browser* new_browser = QuitBrowserAndRestore(browser());
|
| +
|
| + // Change the foreground tab before the first meaningful paint.
|
| + TabStripModel* tab_strip = new_browser->tab_strip_model();
|
| + ASSERT_TRUE(tab_strip);
|
| + ASSERT_EQ(2, tab_strip->count());
|
| + ASSERT_EQ(0, tab_strip->active_index());
|
| + tab_strip->ActivateTabAt(1, true);
|
| +
|
| + session_restore_paint_waiter.WaitForForegroundTabs(1);
|
| +
|
| + // No metrics were recorded because initial foreground tab was switched away.
|
| + ExpectFirstPaintMetricsTotalCount(0);
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
|
| + MultipleSessionRestores) {
|
| + ui_test_utils::NavigateToURL(browser(), GetTestURL());
|
| +
|
| + Browser* current_browser = browser();
|
| + const int num_session_restores = 3;
|
| + for (int i = 1; i <= num_session_restores; ++i) {
|
| + SessionRestorePaintWaiter session_restore_paint_waiter;
|
| + current_browser = QuitBrowserAndRestore(current_browser);
|
| + session_restore_paint_waiter.WaitForForegroundTabs(1);
|
| + ExpectFirstPaintMetricsTotalCount(i);
|
| + }
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
|
| + RestoreForeignTab) {
|
| + sessions::SerializedNavigationEntry nav =
|
| + sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
|
| + GetTestURL().spec(), "one");
|
| +
|
| + // Set up the restore data.
|
| + sync_pb::SessionTab sync_data;
|
| + sync_data.set_tab_visual_index(0);
|
| + sync_data.set_current_navigation_index(1);
|
| + sync_data.set_pinned(false);
|
| + sync_data.add_navigation()->CopyFrom(nav.ToSyncData());
|
| +
|
| + sessions::SessionTab tab;
|
| + tab.SetFromSyncData(sync_data, base::Time::Now());
|
| + ASSERT_EQ(1, browser()->tab_strip_model()->count());
|
| +
|
| + // Restore in the current tab.
|
| + content::WebContents* tab_contents = nullptr;
|
| + {
|
| + SessionRestorePaintWaiter session_restore_paint_waiter;
|
| + tab_contents = SessionRestore::RestoreForeignSessionTab(
|
| + browser()->tab_strip_model()->GetActiveWebContents(), tab,
|
| + WindowOpenDisposition::CURRENT_TAB);
|
| + ASSERT_EQ(1, browser()->tab_strip_model()->count());
|
| + ASSERT_TRUE(tab_contents);
|
| + ASSERT_EQ(GetTestURL(), tab_contents->GetURL());
|
| +
|
| + session_restore_paint_waiter.WaitForForegroundTabs(1);
|
| + ExpectFirstPaintMetricsTotalCount(1);
|
| + }
|
| +
|
| + // Restore in a new foreground tab.
|
| + {
|
| + SessionRestorePaintWaiter session_restore_paint_waiter;
|
| + tab_contents = SessionRestore::RestoreForeignSessionTab(
|
| + browser()->tab_strip_model()->GetActiveWebContents(), tab,
|
| + WindowOpenDisposition::NEW_FOREGROUND_TAB);
|
| + ASSERT_EQ(2, browser()->tab_strip_model()->count());
|
| + ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
|
| + ASSERT_TRUE(tab_contents);
|
| + ASSERT_EQ(GetTestURL(), tab_contents->GetURL());
|
| +
|
| + session_restore_paint_waiter.WaitForForegroundTabs(1);
|
| + ExpectFirstPaintMetricsTotalCount(2);
|
| + }
|
| +
|
| + // Restore in a new background tab.
|
| + {
|
| + tab_contents = SessionRestore::RestoreForeignSessionTab(
|
| + browser()->tab_strip_model()->GetActiveWebContents(), tab,
|
| + WindowOpenDisposition::NEW_BACKGROUND_TAB);
|
| + ASSERT_EQ(3, browser()->tab_strip_model()->count());
|
| + ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
|
| + ASSERT_TRUE(tab_contents);
|
| + ASSERT_EQ(GetTestURL(), tab_contents->GetURL());
|
| + ASSERT_NO_FATAL_FAILURE(WaitForTabsToLoad(browser()));
|
| +
|
| + // Do not record timings of initially background tabs.
|
| + ExpectFirstPaintMetricsTotalCount(2);
|
| + }
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
|
| + RestoreForeignSession) {
|
| + Profile* profile = browser()->profile();
|
| +
|
| + sessions::SerializedNavigationEntry nav1 =
|
| + sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
|
| + GetTestURL().spec(), "one");
|
| + sessions::SerializedNavigationEntry nav2 =
|
| + sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
|
| + GetTestURL2().spec(), "two");
|
| +
|
| + // Set up the restore data: one window with two tabs.
|
| + std::vector<const sessions::SessionWindow*> session;
|
| + sessions::SessionWindow window;
|
| + auto tab1 = base::MakeUnique<sessions::SessionTab>();
|
| + {
|
| + sync_pb::SessionTab sync_data;
|
| + sync_data.set_tab_visual_index(0);
|
| + sync_data.set_current_navigation_index(0);
|
| + sync_data.set_pinned(true);
|
| + sync_data.add_navigation()->CopyFrom(nav1.ToSyncData());
|
| + tab1->SetFromSyncData(sync_data, base::Time::Now());
|
| + }
|
| + window.tabs.push_back(std::move(tab1));
|
| +
|
| + auto tab2 = base::MakeUnique<sessions::SessionTab>();
|
| + {
|
| + sync_pb::SessionTab sync_data;
|
| + sync_data.set_tab_visual_index(1);
|
| + sync_data.set_current_navigation_index(0);
|
| + sync_data.set_pinned(false);
|
| + sync_data.add_navigation()->CopyFrom(nav2.ToSyncData());
|
| + tab2->SetFromSyncData(sync_data, base::Time::Now());
|
| + }
|
| + window.tabs.push_back(std::move(tab2));
|
| +
|
| + // Restore the session window with 2 tabs.
|
| + session.push_back(static_cast<const sessions::SessionWindow*>(&window));
|
| + ui_test_utils::BrowserAddedObserver window_observer;
|
| + SessionRestorePaintWaiter session_restore_paint_waiter;
|
| + SessionRestore::RestoreForeignSessionWindows(profile, session.begin(),
|
| + session.end());
|
| + Browser* new_browser = window_observer.WaitForSingleNewBrowser();
|
| + ASSERT_TRUE(new_browser);
|
| + ASSERT_EQ(2, new_browser->tab_strip_model()->count());
|
| +
|
| + session_restore_paint_waiter.WaitForForegroundTabs(1);
|
| + ExpectFirstPaintMetricsTotalCount(1);
|
| +}
|
|
|