| // Copyright 2013 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. |
| |
| #import "ios/chrome/browser/metrics/tab_usage_recorder_browser_agent.h" |
| |
| #import <UIKit/UIKit.h> |
| |
| #include <memory> |
| |
| #include "base/metrics/histogram_samples.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/task_environment.h" |
| #import "components/previous_session_info/previous_session_info.h" |
| #import "ios/chrome/browser/main/test_browser.h" |
| #import "ios/chrome/browser/web_state_list/web_state_list.h" |
| #import "ios/chrome/browser/web_state_list/web_state_opener.h" |
| #import "ios/web/public/test/fakes/fake_navigation_manager.h" |
| #import "ios/web/public/test/fakes/fake_web_state.h" |
| #include "ios/web/public/test/web_task_environment.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "testing/platform_test.h" |
| #import "third_party/ocmock/OCMock/OCMock.h" |
| |
| #if !defined(__has_feature) || !__has_feature(objc_arc) |
| #error "This file requires ARC support." |
| #endif |
| |
| namespace { |
| |
| // The number of alive tabs at a renderer termination used by unit test. |
| const int kAliveTabsCountAtRendererTermination = 2; |
| |
| // The number of timestamps added to the renderer termination timestamp list |
| // that are not counted in the RecentlyAliveTabs metric. |
| const int kExpiredTimesAddedCount = 2; |
| |
| // URL constants used by TabUsageRecorderBrowserAgentTest. |
| const char kURL[] = "http://www.chromium.org"; |
| const char kNativeURL[] = "chrome://version"; |
| |
| // Option to InsertFakeWebState() to create the WebState for a tab that is in |
| // memory or not. |
| enum WebStateInMemoryOption { NOT_IN_MEMORY = 0, IN_MEMORY }; |
| |
| } // namespace |
| |
| class TabUsageRecorderBrowserAgentTest : public PlatformTest { |
| protected: |
| TabUsageRecorderBrowserAgentTest() |
| : application_(OCMClassMock([UIApplication class])) { |
| TabUsageRecorderBrowserAgent::CreateForBrowser(&browser_); |
| tab_usage_recorder_ = TabUsageRecorderBrowserAgent::FromBrowser(&browser_); |
| OCMStub([application_ sharedApplication]).andReturn(application_); |
| } |
| |
| ~TabUsageRecorderBrowserAgentTest() override { [application_ stopMocking]; } |
| |
| web::FakeWebState* InsertFakeWebState(const char* url, |
| WebStateInMemoryOption in_memory) { |
| auto fake_navigation_manager = |
| std::make_unique<web::FakeNavigationManager>(); |
| web::NavigationItem* item = |
| InsertItemToFakeNavigationManager(fake_navigation_manager.get(), url); |
| fake_navigation_manager->SetLastCommittedItem(item); |
| |
| auto fake_web_state = std::make_unique<web::FakeWebState>(); |
| fake_web_state->SetNavigationManager(std::move(fake_navigation_manager)); |
| fake_web_state->SetIsEvicted(in_memory == NOT_IN_MEMORY); |
| |
| const int insertion_index = browser_.GetWebStateList()->InsertWebState( |
| WebStateList::kInvalidIndex, std::move(fake_web_state), |
| WebStateList::INSERT_NO_FLAGS, WebStateOpener()); |
| |
| return static_cast<web::FakeWebState*>( |
| browser_.GetWebStateList()->GetWebStateAt(insertion_index)); |
| } |
| |
| web::NavigationItem* InsertItemToFakeNavigationManager( |
| web::FakeNavigationManager* fake_navigation_manager, |
| const char* url) { |
| fake_navigation_manager->AddItem(GURL(), ui::PAGE_TRANSITION_LINK); |
| web::NavigationItem* item = fake_navigation_manager->GetItemAtIndex( |
| fake_navigation_manager->GetLastCommittedItemIndex()); |
| item->SetVirtualURL(GURL(url)); |
| return item; |
| } |
| |
| void AddTimeToDequeInTabUsageRecorder(base::TimeTicks time) { |
| tab_usage_recorder_->termination_timestamps_.push_back(time); |
| } |
| |
| web::WebTaskEnvironment task_environment_; |
| TestBrowser browser_; |
| base::HistogramTester histogram_tester_; |
| TabUsageRecorderBrowserAgent* tab_usage_recorder_; |
| id application_; |
| }; |
| |
| TEST_F(TabUsageRecorderBrowserAgentTest, SwitchBetweenInMemoryTabs) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, IN_MEMORY); |
| |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| histogram_tester_.ExpectUniqueSample( |
| tab_usage_recorder::kSelectedTabHistogramName, |
| tab_usage_recorder::IN_MEMORY, 1); |
| } |
| |
| TEST_F(TabUsageRecorderBrowserAgentTest, SwitchToEvictedTab) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| histogram_tester_.ExpectUniqueSample( |
| tab_usage_recorder::kSelectedTabHistogramName, |
| tab_usage_recorder::EVICTED, 1); |
| } |
| |
| TEST_F(TabUsageRecorderBrowserAgentTest, SwitchFromEvictedTab) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, IN_MEMORY); |
| |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| histogram_tester_.ExpectUniqueSample( |
| tab_usage_recorder::kSelectedTabHistogramName, |
| tab_usage_recorder::IN_MEMORY, 1); |
| } |
| |
| TEST_F(TabUsageRecorderBrowserAgentTest, SwitchBetweenEvictedTabs) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| histogram_tester_.ExpectUniqueSample( |
| tab_usage_recorder::kSelectedTabHistogramName, |
| tab_usage_recorder::EVICTED, 1); |
| } |
| |
| TEST_F(TabUsageRecorderBrowserAgentTest, CountPageLoadsBeforeEvictedTab) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| |
| // Call reload an arbitrary number of times. |
| const int kNumReloads = 4; |
| for (int i = 0; i < kNumReloads; i++) { |
| tab_usage_recorder_->RecordPageLoadStart(mock_tab_a); |
| } |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| histogram_tester_.ExpectUniqueSample( |
| tab_usage_recorder::kPageLoadsBeforeEvictedTabSelected, kNumReloads, 1); |
| } |
| |
| // Tests that chrome:// URLs are not counted in page load stats. |
| TEST_F(TabUsageRecorderBrowserAgentTest, CountNativePageLoadsBeforeEvictedTab) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kNativeURL, IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kNativeURL, NOT_IN_MEMORY); |
| |
| // Call reload an arbitrary number of times. |
| const int kNumReloads = 4; |
| for (int i = 0; i < kNumReloads; i++) { |
| tab_usage_recorder_->RecordPageLoadStart(mock_tab_a); |
| } |
| |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| histogram_tester_.ExpectTotalCount( |
| tab_usage_recorder::kPageLoadsBeforeEvictedTabSelected, 0); |
| } |
| |
| // Tests that page load stats is not updated for an evicted tab that has a |
| // pending chrome:// URL. |
| TEST_F(TabUsageRecorderBrowserAgentTest, |
| CountPendingNativePageLoadBeforeEvictedTab) { |
| web::FakeWebState* old_tab = InsertFakeWebState(kURL, IN_MEMORY); |
| web::FakeWebState* new_evicted_tab = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| |
| tab_usage_recorder_->RecordPageLoadStart(old_tab); |
| |
| auto* fake_navigation_manager = static_cast<web::FakeNavigationManager*>( |
| new_evicted_tab->GetNavigationManager()); |
| web::NavigationItem* item = |
| InsertItemToFakeNavigationManager(fake_navigation_manager, kNativeURL); |
| fake_navigation_manager->SetPendingItem(item); |
| |
| tab_usage_recorder_->RecordTabSwitched(old_tab, new_evicted_tab); |
| histogram_tester_.ExpectTotalCount( |
| tab_usage_recorder::kPageLoadsBeforeEvictedTabSelected, 0); |
| } |
| |
| TEST_F(TabUsageRecorderBrowserAgentTest, TestColdStartTabs) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| web::FakeWebState* mock_tab_c = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| // Set A and B as cold-start evicted tabs. Leave C just evicted. |
| std::vector<web::WebState*> cold_start_web_states = { |
| mock_tab_a, |
| mock_tab_b, |
| }; |
| tab_usage_recorder_->InitialRestoredTabs(mock_tab_a, cold_start_web_states); |
| |
| // Switch from A (cold start evicted) to B (cold start evicted). |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| // Switch from B (cold start evicted) to C (evicted). |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_b, mock_tab_c); |
| histogram_tester_.ExpectTotalCount( |
| tab_usage_recorder::kSelectedTabHistogramName, 2); |
| histogram_tester_.ExpectBucketCount( |
| tab_usage_recorder::kSelectedTabHistogramName, |
| tab_usage_recorder::EVICTED_DUE_TO_COLD_START, 1); |
| histogram_tester_.ExpectBucketCount( |
| tab_usage_recorder::kSelectedTabHistogramName, |
| tab_usage_recorder::EVICTED, 1); |
| } |
| |
| TEST_F(TabUsageRecorderBrowserAgentTest, TestSwitchedModeTabs) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| web::FakeWebState* mock_tab_c = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| tab_usage_recorder_->RecordPrimaryTabModelChange(false, nullptr); |
| |
| // Switch from A (incognito evicted) to B (incognito evicted). |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| // Switch from B (incognito evicted) to C (evicted). |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_b, mock_tab_c); |
| histogram_tester_.ExpectTotalCount( |
| tab_usage_recorder::kSelectedTabHistogramName, 2); |
| histogram_tester_.ExpectBucketCount( |
| tab_usage_recorder::kSelectedTabHistogramName, |
| tab_usage_recorder::EVICTED_DUE_TO_INCOGNITO, 0); |
| histogram_tester_.ExpectBucketCount( |
| tab_usage_recorder::kSelectedTabHistogramName, |
| tab_usage_recorder::EVICTED, 2); |
| } |
| |
| TEST_F(TabUsageRecorderBrowserAgentTest, TestEvictedTabReloadTime) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| tab_usage_recorder_->RecordPageLoadStart(mock_tab_b); |
| tab_usage_recorder_->RecordPageLoadDone(mock_tab_b, true); |
| histogram_tester_.ExpectTotalCount(tab_usage_recorder::kEvictedTabReloadTime, |
| 1); |
| } |
| |
| TEST_F(TabUsageRecorderBrowserAgentTest, TestEvictedTabReloadSuccess) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| tab_usage_recorder_->RecordPageLoadStart(mock_tab_b); |
| tab_usage_recorder_->RecordPageLoadDone(mock_tab_b, true); |
| histogram_tester_.ExpectUniqueSample( |
| tab_usage_recorder::kEvictedTabReloadSuccessRate, |
| tab_usage_recorder::LOAD_SUCCESS, 1); |
| } |
| |
| TEST_F(TabUsageRecorderBrowserAgentTest, TestEvictedTabReloadFailure) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| tab_usage_recorder_->RecordPageLoadStart(mock_tab_b); |
| tab_usage_recorder_->RecordPageLoadDone(mock_tab_b, false); |
| histogram_tester_.ExpectUniqueSample( |
| tab_usage_recorder::kEvictedTabReloadSuccessRate, |
| tab_usage_recorder::LOAD_FAILURE, 1); |
| } |
| |
| TEST_F(TabUsageRecorderBrowserAgentTest, TestUserWaitedForEvictedTabLoad) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| tab_usage_recorder_->RecordPageLoadStart(mock_tab_b); |
| tab_usage_recorder_->RecordPageLoadDone(mock_tab_b, true); |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_b, mock_tab_a); |
| histogram_tester_.ExpectUniqueSample( |
| tab_usage_recorder::kDidUserWaitForEvictedTabReload, |
| tab_usage_recorder::USER_WAITED, 1); |
| } |
| |
| TEST_F(TabUsageRecorderBrowserAgentTest, TestUserDidNotWaitForEvictedTabLoad) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| tab_usage_recorder_->RecordPageLoadStart(mock_tab_b); |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_b, mock_tab_a); |
| histogram_tester_.ExpectUniqueSample( |
| tab_usage_recorder::kDidUserWaitForEvictedTabReload, |
| tab_usage_recorder::USER_DID_NOT_WAIT, 1); |
| } |
| |
| TEST_F(TabUsageRecorderBrowserAgentTest, |
| TestUserBackgroundedDuringEvictedTabLoad) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| tab_usage_recorder_->RecordPageLoadStart(mock_tab_b); |
| tab_usage_recorder_->AppDidEnterBackground(); |
| histogram_tester_.ExpectUniqueSample( |
| tab_usage_recorder::kDidUserWaitForEvictedTabReload, |
| tab_usage_recorder::USER_LEFT_CHROME, 1); |
| } |
| |
| TEST_F(TabUsageRecorderBrowserAgentTest, TestTimeBetweenRestores) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| // Should record the time since launch until this page load begins. |
| tab_usage_recorder_->RecordPageLoadStart(mock_tab_b); |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_b, mock_tab_a); |
| // Should record the time since previous restore until this restore. |
| tab_usage_recorder_->RecordPageLoadStart(mock_tab_a); |
| histogram_tester_.ExpectTotalCount(tab_usage_recorder::kTimeBetweenRestores, |
| 2); |
| } |
| |
| TEST_F(TabUsageRecorderBrowserAgentTest, TestTimeAfterLastRestore) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| // Should record time since launch until background. |
| tab_usage_recorder_->AppDidEnterBackground(); |
| tab_usage_recorder_->AppWillEnterForeground(); |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| // Should record nothing. |
| tab_usage_recorder_->RecordPageLoadStart(mock_tab_b); |
| histogram_tester_.ExpectTotalCount(tab_usage_recorder::kTimeAfterLastRestore, |
| 1); |
| } |
| |
| // Verifies that metrics are recorded correctly when a renderer terminates. |
| TEST_F(TabUsageRecorderBrowserAgentTest, RendererTerminated) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| OCMStub([static_cast<UIApplication*>(application_) applicationState]) |
| .andReturn(UIApplicationStateActive); |
| |
| // Add some extra WebStates that are not considered evicted so that |
| // TabUsageRecorder count kAliveTabsCountAtRendererTermination tabs |
| // as alive when mock_tab_a is evicted. |
| for (int ii = 0; ii < kAliveTabsCountAtRendererTermination; ++ii) { |
| ignore_result(InsertFakeWebState(kURL, IN_MEMORY)); |
| } |
| |
| base::TimeTicks now = base::TimeTicks::Now(); |
| |
| // Add |kExpiredTimesAddedCount| expired timestamps and one recent timestamp |
| // to the termination timestamp list. |
| for (int seconds = kExpiredTimesAddedCount; seconds > 0; seconds--) { |
| int expired_time_delta = |
| tab_usage_recorder::kSecondsBeforeRendererTermination + seconds; |
| AddTimeToDequeInTabUsageRecorder( |
| now - base::TimeDelta::FromSeconds(expired_time_delta)); |
| } |
| base::TimeTicks recent_time = |
| now - base::TimeDelta::FromSeconds( |
| tab_usage_recorder::kSecondsBeforeRendererTermination / 2); |
| AddTimeToDequeInTabUsageRecorder(recent_time); |
| |
| mock_tab_a->OnRenderProcessGone(); |
| |
| NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; |
| BOOL saw_memory_warning = |
| [defaults boolForKey:previous_session_info_constants:: |
| kDidSeeMemoryWarningShortlyBeforeTerminating]; |
| histogram_tester_.ExpectUniqueSample( |
| tab_usage_recorder::kRendererTerminationSawMemoryWarning, |
| saw_memory_warning, 1); |
| histogram_tester_.ExpectUniqueSample( |
| tab_usage_recorder::kRendererTerminationAliveRenderers, |
| kAliveTabsCountAtRendererTermination, 1); |
| // Tests that the logged count of recently alive renderers is equal to the |
| // live count at termination plus the recent termination and the |
| // renderer terminated just now. |
| histogram_tester_.ExpectUniqueSample( |
| tab_usage_recorder::kRendererTerminationRecentlyAliveRenderers, |
| kAliveTabsCountAtRendererTermination + 2, 1); |
| |
| // Regression test for crbug.com/935205 |
| // Terminate the same tab again. Verify that it isn't double-counted. |
| mock_tab_a->OnRenderProcessGone(); |
| histogram_tester_.ExpectUniqueSample( |
| tab_usage_recorder::kRendererTerminationAliveRenderers, |
| kAliveTabsCountAtRendererTermination, 1); |
| histogram_tester_.ExpectUniqueSample( |
| tab_usage_recorder::kRendererTerminationRecentlyAliveRenderers, |
| kAliveTabsCountAtRendererTermination + 2, 1); |
| } |
| |
| // Verifies that metrics are recorded correctly when a renderer terminated tab |
| // is switched to and reloaded. |
| TEST_F(TabUsageRecorderBrowserAgentTest, SwitchToRendererTerminatedTab) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, NOT_IN_MEMORY); |
| OCMStub([static_cast<UIApplication*>(application_) applicationState]) |
| .andReturn(UIApplicationStateActive); |
| |
| mock_tab_b->OnRenderProcessGone(); |
| tab_usage_recorder_->RecordTabSwitched(mock_tab_a, mock_tab_b); |
| |
| histogram_tester_.ExpectUniqueSample( |
| tab_usage_recorder::kSelectedTabHistogramName, |
| tab_usage_recorder::EVICTED_DUE_TO_RENDERER_TERMINATION, 1); |
| } |
| |
| // Verifies that Tab.StateAtRendererTermination metric is correctly reported |
| // when the application is in the foreground. |
| TEST_F(TabUsageRecorderBrowserAgentTest, StateAtRendererTerminationForeground) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, IN_MEMORY); |
| OCMStub([static_cast<UIApplication*>(application_) applicationState]) |
| .andReturn(UIApplicationStateActive); |
| |
| mock_tab_a->WasShown(); |
| mock_tab_a->OnRenderProcessGone(); |
| histogram_tester_.ExpectBucketCount( |
| tab_usage_recorder::kRendererTerminationStateHistogram, |
| tab_usage_recorder::FOREGROUND_TAB_FOREGROUND_APP, 1); |
| |
| mock_tab_b->OnRenderProcessGone(); |
| histogram_tester_.ExpectBucketCount( |
| tab_usage_recorder::kRendererTerminationStateHistogram, |
| tab_usage_recorder::BACKGROUND_TAB_FOREGROUND_APP, 1); |
| } |
| |
| // Verifies that Tab.StateAtRendererTermination metric is correctly reported |
| // when the application is in the background. |
| TEST_F(TabUsageRecorderBrowserAgentTest, StateAtRendererTerminationBackground) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, IN_MEMORY); |
| OCMStub([static_cast<UIApplication*>(application_) applicationState]) |
| .andReturn(UIApplicationStateBackground); |
| |
| mock_tab_a->WasShown(); |
| mock_tab_a->OnRenderProcessGone(); |
| histogram_tester_.ExpectBucketCount( |
| tab_usage_recorder::kRendererTerminationStateHistogram, |
| tab_usage_recorder::FOREGROUND_TAB_BACKGROUND_APP, 1); |
| |
| mock_tab_b->OnRenderProcessGone(); |
| histogram_tester_.ExpectBucketCount( |
| tab_usage_recorder::kRendererTerminationStateHistogram, |
| tab_usage_recorder::BACKGROUND_TAB_BACKGROUND_APP, 1); |
| } |
| |
| // Verifies that Tab.StateAtRendererTermination metric is correctly reported |
| // when the application is in the inactive state. |
| TEST_F(TabUsageRecorderBrowserAgentTest, StateAtRendererTerminationInactive) { |
| web::FakeWebState* mock_tab_a = InsertFakeWebState(kURL, IN_MEMORY); |
| web::FakeWebState* mock_tab_b = InsertFakeWebState(kURL, IN_MEMORY); |
| OCMStub([static_cast<UIApplication*>(application_) applicationState]) |
| .andReturn(UIApplicationStateInactive); |
| |
| mock_tab_a->WasShown(); |
| mock_tab_a->OnRenderProcessGone(); |
| histogram_tester_.ExpectBucketCount( |
| tab_usage_recorder::kRendererTerminationStateHistogram, |
| tab_usage_recorder::FOREGROUND_TAB_BACKGROUND_APP, 1); |
| |
| mock_tab_b->OnRenderProcessGone(); |
| histogram_tester_.ExpectBucketCount( |
| tab_usage_recorder::kRendererTerminationStateHistogram, |
| tab_usage_recorder::BACKGROUND_TAB_BACKGROUND_APP, 1); |
| } |