| // Copyright 2020 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/incognito_usage_app_state_agent.h" |
| |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/scoped_mock_clock_override.h" |
| #import "ios/chrome/app/application_delegate/app_state.h" |
| #import "ios/chrome/browser/ui/main/scene_state.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "testing/gtest_mac.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 |
| |
| @interface IncognitoUsageAppStateAgent (Testing) <AppStateObserver, |
| SceneStateObserver> |
| - (void)applicationWillTerminate; |
| @property(nonatomic, assign) BOOL incognitoContentVisible; |
| @end |
| |
| class IncognitoUsageAppStateAgentTest : public PlatformTest { |
| public: |
| void AdvanceClock(const base::TimeDelta& delay) { |
| scoped_clock_.Advance(delay); |
| } |
| |
| void SetScene1ActivationLevel(SceneActivationLevel activation_level) { |
| scene1_activation_level_ = activation_level; |
| [incognito_agent_ sceneState:mock_scene_state1_ |
| transitionedToActivationLevel:activation_level]; |
| } |
| |
| void SetScene2ActivationLevel(SceneActivationLevel activation_level) { |
| scene2_activation_level_ = activation_level; |
| [incognito_agent_ sceneState:mock_scene_state2_ |
| transitionedToActivationLevel:activation_level]; |
| } |
| |
| void SetScene1DisplaysIncognito(BOOL displays_incognito) { |
| scene1_displays_incognito_ = displays_incognito; |
| [incognito_agent_ sceneState:mock_scene_state1_ |
| isDisplayingIncognitoContent:displays_incognito]; |
| } |
| void SetScene2DisplaysIncognito(BOOL displays_incognito) { |
| scene2_displays_incognito_ = displays_incognito; |
| [incognito_agent_ sceneState:mock_scene_state2_ |
| isDisplayingIncognitoContent:displays_incognito]; |
| } |
| |
| protected: |
| void SetUp() override { |
| PlatformTest::SetUp(); |
| incognito_agent_ = [[IncognitoUsageAppStateAgent alloc] init]; |
| mock_app_state_ = OCMClassMock([AppState class]); |
| mock_scene_state1_ = OCMClassMock([SceneState class]); |
| mock_scene_state2_ = OCMClassMock([SceneState class]); |
| |
| NSArray* connected_scenes = @[ mock_scene_state1_, mock_scene_state2_ ]; |
| OCMStub([mock_app_state_ connectedScenes]).andReturn(connected_scenes); |
| [incognito_agent_ setAppState:mock_app_state_]; |
| |
| OCMStub([mock_scene_state1_ incognitoContentVisible]) |
| .andDo(^(NSInvocation* invocation) { |
| [invocation setReturnValue:&scene1_displays_incognito_]; |
| }); |
| OCMStub([mock_scene_state2_ incognitoContentVisible]) |
| .andDo(^(NSInvocation* invocation) { |
| [invocation setReturnValue:&scene2_displays_incognito_]; |
| }); |
| OCMStub([mock_scene_state1_ activationLevel]) |
| .andDo(^(NSInvocation* invocation) { |
| [invocation setReturnValue:&scene1_activation_level_]; |
| }); |
| OCMStub([mock_scene_state2_ activationLevel]) |
| .andDo(^(NSInvocation* invocation) { |
| [invocation setReturnValue:&scene2_activation_level_]; |
| }); |
| [incognito_agent_ appState:mock_app_state_ |
| sceneConnected:mock_scene_state1_]; |
| [incognito_agent_ appState:mock_app_state_ |
| sceneConnected:mock_scene_state2_]; |
| } |
| |
| void TearDown() override { |
| SetScene1DisplaysIncognito(NO); |
| SetScene2DisplaysIncognito(NO); |
| PlatformTest::TearDown(); |
| } |
| |
| base::HistogramTester histogram_tester_; |
| base::ScopedMockClockOverride scoped_clock_; |
| IncognitoUsageAppStateAgent* incognito_agent_; |
| id mock_app_state_; |
| id mock_scene_state1_; |
| id mock_scene_state2_; |
| __block BOOL scene1_displays_incognito_ = NO; |
| __block BOOL scene2_displays_incognito_ = NO; |
| __block SceneActivationLevel scene1_activation_level_ = |
| SceneActivationLevelBackground; |
| __block SceneActivationLevel scene2_activation_level_ = |
| SceneActivationLevelBackground; |
| }; |
| |
| // Tests metrics that a session of 1 minute is recorded |
| TEST_F(IncognitoUsageAppStateAgentTest, NormalIncognitoSession) { |
| // One scene Foregrounded, no Incognito |
| SetScene1ActivationLevel(SceneActivationLevelForegroundActive); |
| |
| EXPECT_FALSE(incognito_agent_.incognitoContentVisible); |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| |
| AdvanceClock(base::TimeDelta::FromMinutes(1)); |
| |
| // Display one incognito for 1 minute |
| SetScene1DisplaysIncognito(YES); |
| EXPECT_TRUE(incognito_agent_.incognitoContentVisible); |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| AdvanceClock(base::TimeDelta::FromMinutes(1)); |
| |
| // Back to normal |
| SetScene1DisplaysIncognito(NO); |
| EXPECT_FALSE(incognito_agent_.incognitoContentVisible); |
| // Metrics is still not logged. |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| |
| // Back to incognito |
| AdvanceClock(base::TimeDelta::FromMinutes(1)); |
| SetScene1DisplaysIncognito(YES); |
| EXPECT_TRUE(incognito_agent_.incognitoContentVisible); |
| // Metrics from previous time should be logged. |
| histogram_tester_.ExpectUniqueTimeSample("IOS.Incognito.TimeSpent", |
| base::TimeDelta::FromMinutes(1), 1); |
| } |
| |
| // Tests metrics that a session of 5 seconds is not recorded |
| TEST_F(IncognitoUsageAppStateAgentTest, ShortIncognitoSession) { |
| // One scene Foregrounded, no Incognito |
| SetScene1ActivationLevel(SceneActivationLevelForegroundActive); |
| |
| EXPECT_FALSE(incognito_agent_.incognitoContentVisible); |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| |
| AdvanceClock(base::TimeDelta::FromMinutes(1)); |
| |
| // Display one incognito for 5 seconds |
| SetScene1DisplaysIncognito(YES); |
| EXPECT_TRUE(incognito_agent_.incognitoContentVisible); |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| AdvanceClock(base::TimeDelta::FromSeconds(5)); |
| |
| // Back to normal |
| SetScene1DisplaysIncognito(NO); |
| EXPECT_FALSE(incognito_agent_.incognitoContentVisible); |
| // Metrics is still not logged. |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| |
| // Back to incognito |
| AdvanceClock(base::TimeDelta::FromMinutes(1)); |
| SetScene1DisplaysIncognito(YES); |
| EXPECT_TRUE(incognito_agent_.incognitoContentVisible); |
| // Metrics from previous time should not be logged. |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| } |
| |
| // Tests metrics that a short interruption of 5 seconds is not recorded. |
| TEST_F(IncognitoUsageAppStateAgentTest, ShortNormalSession) { |
| // One scene Foregrounded, no Incognito |
| SetScene1ActivationLevel(SceneActivationLevelForegroundActive); |
| |
| EXPECT_FALSE(incognito_agent_.incognitoContentVisible); |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| |
| AdvanceClock(base::TimeDelta::FromMinutes(1)); |
| |
| // Display one incognito for 1 minute |
| SetScene1DisplaysIncognito(YES); |
| EXPECT_TRUE(incognito_agent_.incognitoContentVisible); |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| AdvanceClock(base::TimeDelta::FromMinutes(1)); |
| |
| // Back to normal |
| SetScene1DisplaysIncognito(NO); |
| EXPECT_FALSE(incognito_agent_.incognitoContentVisible); |
| // Metrics is still not logged. |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| |
| // Back to incognito |
| AdvanceClock(base::TimeDelta::FromSeconds(5)); |
| SetScene1DisplaysIncognito(YES); |
| EXPECT_TRUE(incognito_agent_.incognitoContentVisible); |
| // Nothing logged yet |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| |
| AdvanceClock(base::TimeDelta::FromSeconds(55)); |
| SetScene1DisplaysIncognito(NO); |
| EXPECT_FALSE(incognito_agent_.incognitoContentVisible); |
| // Metrics is still not logged. |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| |
| AdvanceClock(base::TimeDelta::FromMinutes(1)); |
| SetScene1DisplaysIncognito(YES); |
| EXPECT_TRUE(incognito_agent_.incognitoContentVisible); |
| // Metrics from previous time should be logged. |
| histogram_tester_.ExpectUniqueTimeSample("IOS.Incognito.TimeSpent", |
| base::TimeDelta::FromMinutes(2), 1); |
| } |
| |
| // Tests metrics that the current incognito life time is reported. |
| TEST_F(IncognitoUsageAppStateAgentTest, ApplicationTerminatesInIncognito) { |
| // One scene Foregrounded, no Incognito |
| SetScene1ActivationLevel(SceneActivationLevelForegroundActive); |
| |
| EXPECT_FALSE(incognito_agent_.incognitoContentVisible); |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| |
| AdvanceClock(base::TimeDelta::FromMinutes(1)); |
| // Display one incognito for 1 minute |
| SetScene1DisplaysIncognito(YES); |
| EXPECT_TRUE(incognito_agent_.incognitoContentVisible); |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| AdvanceClock(base::TimeDelta::FromMinutes(1)); |
| |
| [incognito_agent_ applicationWillTerminate]; |
| // Metrics from previous time should be logged. |
| histogram_tester_.ExpectUniqueTimeSample("IOS.Incognito.TimeSpent", |
| base::TimeDelta::FromMinutes(1), 1); |
| } |
| |
| // Tests metrics that the last incognito life time is reported. |
| TEST_F(IncognitoUsageAppStateAgentTest, ApplicationTerminatesInNormal) { |
| // One scene Foregrounded, no Incognito |
| SetScene1ActivationLevel(SceneActivationLevelForegroundActive); |
| |
| EXPECT_FALSE(incognito_agent_.incognitoContentVisible); |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| |
| AdvanceClock(base::TimeDelta::FromMinutes(1)); |
| // Display one incognito for 1 minute |
| SetScene1DisplaysIncognito(YES); |
| EXPECT_TRUE(incognito_agent_.incognitoContentVisible); |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| AdvanceClock(base::TimeDelta::FromMinutes(1)); |
| SetScene1DisplaysIncognito(NO); |
| EXPECT_FALSE(incognito_agent_.incognitoContentVisible); |
| histogram_tester_.ExpectTotalCount("IOS.Incognito.TimeSpent", 0); |
| |
| [incognito_agent_ applicationWillTerminate]; |
| // Metrics from previous time should be logged. |
| histogram_tester_.ExpectUniqueTimeSample("IOS.Incognito.TimeSpent", |
| base::TimeDelta::FromMinutes(1), 1); |
| } |
| |
| // Tests incognitoContentVisible in various scenarios. |
| TEST_F(IncognitoUsageAppStateAgentTest, IncognitoContentVisibleValue) { |
| // Two scenes background normal. |
| EXPECT_FALSE(incognito_agent_.incognitoContentVisible); |
| |
| // Incognito in background. |
| SetScene1DisplaysIncognito(YES); |
| EXPECT_FALSE(incognito_agent_.incognitoContentVisible); |
| |
| // Foreground incognito |
| SetScene1ActivationLevel(SceneActivationLevelForegroundActive); |
| EXPECT_TRUE(incognito_agent_.incognitoContentVisible); |
| |
| // Background it |
| SetScene1ActivationLevel(SceneActivationLevelBackground); |
| EXPECT_FALSE(incognito_agent_.incognitoContentVisible); |
| |
| // Foreground incognito |
| SetScene1ActivationLevel(SceneActivationLevelForegroundActive); |
| EXPECT_TRUE(incognito_agent_.incognitoContentVisible); |
| |
| // Switch to normal |
| SetScene1DisplaysIncognito(NO); |
| EXPECT_FALSE(incognito_agent_.incognitoContentVisible); |
| |
| // Foreground second scene |
| SetScene2ActivationLevel(SceneActivationLevelForegroundActive); |
| EXPECT_FALSE(incognito_agent_.incognitoContentVisible); |
| |
| // Incognito in foreground. |
| SetScene1DisplaysIncognito(YES); |
| EXPECT_TRUE(incognito_agent_.incognitoContentVisible); |
| |
| // Second Incognito in foreground. |
| SetScene2DisplaysIncognito(YES); |
| EXPECT_TRUE(incognito_agent_.incognitoContentVisible); |
| |
| // Background 1 |
| SetScene1ActivationLevel(SceneActivationLevelBackground); |
| EXPECT_TRUE(incognito_agent_.incognitoContentVisible); |
| |
| // Switch the other to normal. |
| SetScene2DisplaysIncognito(NO); |
| EXPECT_FALSE(incognito_agent_.incognitoContentVisible); |
| } |