Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1760)

Unified Diff: chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc

Issue 2930013005: [Tab Metrics] Measure FP, FCP and FMP for Foreground Tab during Session Restore (Closed)
Patch Set: Address Bryan comments Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
+}

Powered by Google App Engine
This is Rietveld 408576698