chromium/ios/chrome/browser/start_surface/ui_bundled/start_surface_scene_agent_unittest.mm

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "ios/chrome/browser/start_surface/ui_bundled/start_surface_scene_agent.h"

#import "base/test/metrics/histogram_tester.h"
#import "base/test/scoped_feature_list.h"
#import "components/favicon/ios/web_favicon_driver.h"
#import "components/sync_preferences/testing_pref_service_syncable.h"
#import "components/tab_groups/tab_group_id.h"
#import "ios/chrome/app/application_delegate/app_state.h"
#import "ios/chrome/app/application_delegate/fake_startup_information.h"
#import "ios/chrome/browser/ntp/model/new_tab_page_tab_helper.h"
#import "ios/chrome/browser/shared/coordinator/scene/test/fake_scene_state.h"
#import "ios/chrome/browser/shared/model/browser/browser.h"
#import "ios/chrome/browser/shared/model/browser/browser_provider.h"
#import "ios/chrome/browser/shared/model/browser/browser_provider_interface.h"
#import "ios/chrome/browser/shared/model/prefs/pref_names.h"
#import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
#import "ios/chrome/browser/shared/model/url/chrome_url_constants.h"
#import "ios/chrome/browser/shared/model/url/url_util.h"
#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/browser/signin/model/fake_system_identity.h"
#import "ios/chrome/browser/signin/model/fake_system_identity_manager.h"
#import "ios/chrome/browser/start_surface/ui_bundled/start_surface_features.h"
#import "ios/chrome/browser/start_surface/ui_bundled/start_surface_recent_tab_browser_agent.h"
#import "ios/chrome/browser/start_surface/ui_bundled/start_surface_util.h"
#import "ios/chrome/browser/tab_insertion/model/tab_insertion_browser_agent.h"
#import "ios/chrome/test/scoped_key_window.h"
#import "ios/chrome/test/testing_application_context.h"
#import "ios/web/public/test/fakes/fake_web_state.h"
#import "ios/web/public/test/web_task_environment.h"
#import "testing/gtest/include/gtest/gtest.h"
#import "testing/platform_test.h"
#import "third_party/ocmock/OCMock/OCMock.h"

using tab_groups::TabGroupId;

namespace {
const char kURL[] = "https://chromium.org/";
}

// A fake that allows setting initStage.
@interface FakeAppStateInitStage : AppState
// Init stage that will be returned by the initStage getter when testing.
@property(nonatomic, assign) InitStage initStageForTesting;
@end

@implementation FakeAppStateInitStage

- (InitStage)initStage {
  return self.initStageForTesting;
}

@end

class StartSurfaceSceneAgentTest : public PlatformTest {
 public:
  StartSurfaceSceneAgentTest()
      : browser_state_(TestChromeBrowserState::Builder().Build()),
        startup_information_([[FakeStartupInformation alloc] init]),
        app_state_([[FakeAppStateInitStage alloc]
            initWithStartupInformation:startup_information_]),
        scene_state_([[FakeSceneState alloc]
            initWithAppState:app_state_
                browserState:browser_state_.get()]),
        agent_([[StartSurfaceSceneAgent alloc] init]) {
    pref_service_.registry()->RegisterIntegerPref(
        prefs::kIosMagicStackSegmentationTabResumptionImpressionsSinceFreshness,
        -1);
    scene_state_.scene = static_cast<UIWindowScene*>(
        [[[UIApplication sharedApplication] connectedScenes] anyObject]);
    agent_.sceneState = scene_state_;
    Browser* browser =
        scene_state_.browserProviderInterface.mainBrowserProvider.browser;
    StartSurfaceRecentTabBrowserAgent::CreateForBrowser(browser);
    TabInsertionBrowserAgent::CreateForBrowser(browser);
    histogram_tester_ = std::make_unique<base::HistogramTester>();
    TestingApplicationContext::GetGlobal()->SetLocalState(&pref_service_);
  }

  void TearDown() override {
    agent_ = nil;
    scene_state_ = nil;
    TestingApplicationContext::GetGlobal()->SetLocalState(nullptr);
    PlatformTest::TearDown();
  }

  FakeSystemIdentityManager* fake_system_identity_manager() {
    return FakeSystemIdentityManager::FromSystemIdentityManager(
        GetApplicationContext()->GetSystemIdentityManager());
  }

 protected:
  web::WebTaskEnvironment task_environment_;
  sync_preferences::TestingPrefServiceSyncable pref_service_;
  std::unique_ptr<TestChromeBrowserState> browser_state_;
  FakeStartupInformation* startup_information_;
  FakeAppStateInitStage* app_state_;
  // The scene state that the agent works with.
  FakeSceneState* scene_state_;
  ScopedKeyWindow scoped_window_;
  // The tested agent
  StartSurfaceSceneAgent* agent_;
  std::unique_ptr<base::HistogramTester> histogram_tester_;

  // Create WebState at `index` with `url` as the current url.
  void InsertNewWebState(int index, GURL url) {
    auto test_web_state = std::make_unique<web::FakeWebState>();
    test_web_state->SetCurrentURL(url);
    test_web_state->SetNavigationItemCount(1);
    test_web_state->SetBrowserState(browser_state_.get());
    Browser* browser =
        scene_state_.browserProviderInterface.mainBrowserProvider.browser;
    WebStateList* web_state_list = browser->GetWebStateList();
    NewTabPageTabHelper::CreateForWebState(test_web_state.get());
    web_state_list->InsertWebState(
        std::move(test_web_state),
        WebStateList::InsertionParams::AtIndex(index));
  }

  // Create a WebState that has a navigation history of more than one at `index`
  // with `url` as the current url.
  void InsertNewWebStateWithNavigationHistory(int index, GURL url) {
    auto test_web_state = std::make_unique<web::FakeWebState>();
    test_web_state->SetCurrentURL(url);
    test_web_state->SetNavigationItemCount(2);
    Browser* browser =
        scene_state_.browserProviderInterface.mainBrowserProvider.browser;
    WebStateList* web_state_list = browser->GetWebStateList();
    web_state_list->InsertWebState(
        std::move(test_web_state),
        WebStateList::InsertionParams::AtIndex(index));
  }
};

// Tests that all but one of the NTP tabs are removed after the app goes from a
// foreground to a background state.
TEST_F(StartSurfaceSceneAgentTest, RemoveExcessNTPs) {
  base::test::ScopedFeatureList scoped_feature_list;
  std::vector<base::test::FeatureRef> enabled_features;
  enabled_features.push_back(kRemoveExcessNTPs);

  scoped_feature_list.InitWithFeatures(enabled_features, {});

  InsertNewWebState(0, GURL(kChromeUINewTabURL));
  InsertNewWebState(1, GURL(kChromeUINewTabURL));
  InsertNewWebState(2, GURL(kURL));
  InsertNewWebState(3, GURL(kChromeUINewTabURL));

  [agent_ sceneState:scene_state_
      transitionedToActivationLevel:SceneActivationLevelForegroundActive];
  histogram_tester_->ExpectTotalCount("IOS.NTP.ExcessRemovedTabCount", 0);

  // Transition to the background, triggering the NTP clean up.
  [agent_ sceneState:scene_state_
      transitionedToActivationLevel:SceneActivationLevelBackground];

  // Expect 2 calls to IOS.NTP.ExcessRemovedTabCount. One for the regular
  // browser, one for the incognito browser.
  histogram_tester_->ExpectTotalCount("IOS.NTP.ExcessRemovedTabCount", 2);
  // Regular browser got 2 NTP removed.
  histogram_tester_->ExpectBucketCount("IOS.NTP.ExcessRemovedTabCount", 2, 1);
  // Incognito browser got no NTP removed.
  histogram_tester_->ExpectBucketCount("IOS.NTP.ExcessRemovedTabCount", 0, 1);
  WebStateList* web_state_list =
      scene_state_.browserProviderInterface.mainBrowserProvider.browser
          ->GetWebStateList();
  ASSERT_EQ(2, web_state_list->count());
  // NTP at index 3 should be the one saved, so the remaining WebState with an
  // NTP should now be at index 1.
  EXPECT_EQ(web_state_list->GetWebStateAt(0)->GetVisibleURL(), kURL);
  EXPECT_TRUE(IsUrlNtp(web_state_list->GetWebStateAt(1)->GetVisibleURL()));
}

// Tests that the NTP tab with navigation history is the only NTP tab that is
// kept after moving to the background state.
TEST_F(StartSurfaceSceneAgentTest, OnlyRemoveEmptyNTPs) {
  base::test::ScopedFeatureList scoped_feature_list;
  std::vector<base::test::FeatureRef> enabled_features;
  enabled_features.push_back(kRemoveExcessNTPs);

  scoped_feature_list.InitWithFeatures(enabled_features, {});

  InsertNewWebState(0, GURL(kChromeUINewTabURL));
  InsertNewWebState(1, GURL(kURL));
  InsertNewWebStateWithNavigationHistory(2, GURL(kChromeUINewTabURL));
  InsertNewWebState(3, GURL(kChromeUINewTabURL));

  [agent_ sceneState:scene_state_
      transitionedToActivationLevel:SceneActivationLevelForegroundActive];
  histogram_tester_->ExpectTotalCount("IOS.NTP.ExcessRemovedTabCount", 0);

  // Transition to the background, triggering the NTP clean up.
  [agent_ sceneState:scene_state_
      transitionedToActivationLevel:SceneActivationLevelBackground];

  // Expect 2 calls to IOS.NTP.ExcessRemovedTabCount. One for the regular
  // browser, one for the incognito browser.
  histogram_tester_->ExpectTotalCount("IOS.NTP.ExcessRemovedTabCount", 2);
  // Regular browser got 2 NTP removed.
  histogram_tester_->ExpectBucketCount("IOS.NTP.ExcessRemovedTabCount", 2, 1);
  // Incognito browser got no NTP removed.
  histogram_tester_->ExpectBucketCount("IOS.NTP.ExcessRemovedTabCount", 0, 1);
  WebStateList* web_state_list =
      scene_state_.browserProviderInterface.mainBrowserProvider.browser
          ->GetWebStateList();
  ASSERT_EQ(2, web_state_list->count());
  EXPECT_EQ(web_state_list->GetWebStateAt(0)->GetVisibleURL(), kURL);
  EXPECT_TRUE(IsUrlNtp(web_state_list->GetWebStateAt(1)->GetVisibleURL()));
  EXPECT_GT(web_state_list->GetWebStateAt(1)->GetNavigationItemCount(), 1);
}

// Tests that, starting with a WebState with navigation history showing the NTP
// and an active WebState with no navigation history, the former WebState is
// kept and becomes the active WebState after backgrounding.
TEST_F(StartSurfaceSceneAgentTest, KeepAndActivateNonEmptyNTP) {
  base::test::ScopedFeatureList scoped_feature_list;
  std::vector<base::test::FeatureRef> enabled_features;
  enabled_features.push_back(kRemoveExcessNTPs);

  scoped_feature_list.InitWithFeatures(enabled_features, {});
  InsertNewWebStateWithNavigationHistory(0, GURL(kChromeUINewTabURL));
  InsertNewWebState(1, GURL(kURL));
  InsertNewWebState(2, GURL(kChromeUINewTabURL));
  WebStateList* web_state_list =
      scene_state_.browserProviderInterface.mainBrowserProvider.browser
          ->GetWebStateList();
  web_state_list->ActivateWebStateAt(2);
  [agent_ sceneState:scene_state_
      transitionedToActivationLevel:SceneActivationLevelForegroundActive];
  histogram_tester_->ExpectTotalCount("IOS.NTP.ExcessRemovedTabCount", 0);

  // Transition to the background, triggering the NTP clean up.
  [agent_ sceneState:scene_state_
      transitionedToActivationLevel:SceneActivationLevelBackground];

  // Expect 2 calls to IOS.NTP.ExcessRemovedTabCount. One for the regular
  // browser, one for the incognito browser.
  histogram_tester_->ExpectTotalCount("IOS.NTP.ExcessRemovedTabCount", 2);
  // Regular browser got 1 NTP removed.
  histogram_tester_->ExpectBucketCount("IOS.NTP.ExcessRemovedTabCount", 1, 1);
  // Incognito browser got no NTP removed.
  histogram_tester_->ExpectBucketCount("IOS.NTP.ExcessRemovedTabCount", 0, 1);
  ASSERT_EQ(2, web_state_list->count());
  EXPECT_TRUE(IsUrlNtp(web_state_list->GetWebStateAt(0)->GetVisibleURL()));
  EXPECT_GT(web_state_list->GetWebStateAt(0)->GetNavigationItemCount(), 1);
  EXPECT_EQ(web_state_list->GetActiveWebState(),
            web_state_list->GetWebStateAt(0));
  EXPECT_EQ(web_state_list->GetWebStateAt(1)->GetVisibleURL(), kURL);
}

// Tests that empty NTPs in tab groups are removed, keeping at most one per
// group, and one for the ungrouped tabs.
TEST_F(StartSurfaceSceneAgentTest, KeepAtMostOneEmptyNTPPerGroup) {
  base::test::ScopedFeatureList scoped_feature_list;
  std::vector<base::test::FeatureRef> enabled_features;
  enabled_features.push_back(kRemoveExcessNTPs);

  scoped_feature_list.InitWithFeatures(enabled_features, {});
  InsertNewWebStateWithNavigationHistory(0, GURL(kChromeUINewTabURL));
  InsertNewWebState(1, GURL(kURL));
  InsertNewWebState(2, GURL(kChromeUINewTabURL));
  InsertNewWebState(3, GURL(kChromeUINewTabURL));
  InsertNewWebState(4, GURL(kChromeUINewTabURL));
  InsertNewWebStateWithNavigationHistory(5, GURL(kChromeUINewTabURL));
  InsertNewWebState(6, GURL(kChromeUINewTabURL));
  WebStateList* web_state_list =
      scene_state_.browserProviderInterface.mainBrowserProvider.browser
          ->GetWebStateList();
  const TabGroup* group_0 =
      web_state_list->CreateGroup({0, 1, 2, 3}, {}, TabGroupId::GenerateNew());
  const TabGroup* group_1 =
      web_state_list->CreateGroup({6}, {}, TabGroupId::GenerateNew());
  [agent_ sceneState:scene_state_
      transitionedToActivationLevel:SceneActivationLevelForegroundActive];
  histogram_tester_->ExpectTotalCount("IOS.NTP.ExcessRemovedTabCount", 0);

  // Transition to the background, triggering the NTP clean up.
  [agent_ sceneState:scene_state_
      transitionedToActivationLevel:SceneActivationLevelBackground];

  // Expect 2 calls to IOS.NTP.ExcessRemovedTabCount. One for the regular
  // browser, one for the incognito browser.
  histogram_tester_->ExpectTotalCount("IOS.NTP.ExcessRemovedTabCount", 2);
  // Regular browser got 3 NTP removed.
  histogram_tester_->ExpectBucketCount("IOS.NTP.ExcessRemovedTabCount", 3, 1);
  // Incognito browser got no NTP removed.
  histogram_tester_->ExpectBucketCount("IOS.NTP.ExcessRemovedTabCount", 0, 1);
  ASSERT_EQ(4, web_state_list->count());
  // First is NTP with navigation, in `group_0`.
  EXPECT_TRUE(IsUrlNtp(web_state_list->GetWebStateAt(0)->GetVisibleURL()));
  EXPECT_GT(web_state_list->GetWebStateAt(0)->GetNavigationItemCount(), 1);
  EXPECT_EQ(group_0, web_state_list->GetGroupOfWebStateAt(0));
  // Second is non-NTP, in group_0.
  EXPECT_EQ(web_state_list->GetWebStateAt(1)->GetVisibleURL(), kURL);
  EXPECT_EQ(group_0, web_state_list->GetGroupOfWebStateAt(1));
  // Third is NTP with navigation, in no group.
  EXPECT_TRUE(IsUrlNtp(web_state_list->GetWebStateAt(2)->GetVisibleURL()));
  EXPECT_GT(web_state_list->GetWebStateAt(2)->GetNavigationItemCount(), 1);
  EXPECT_EQ(nullptr, web_state_list->GetGroupOfWebStateAt(2));
  // Fourth is empty NTP (no navigation), in group_1.
  EXPECT_TRUE(IsUrlNtp(web_state_list->GetWebStateAt(3)->GetVisibleURL()));
  EXPECT_LE(web_state_list->GetWebStateAt(3)->GetNavigationItemCount(), 1);
  EXPECT_EQ(group_1, web_state_list->GetGroupOfWebStateAt(3));
}

// Tests that when the active tab is a grouped NTP that gets closed, a new
// ungrouped NTP is opened and activated.
TEST_F(StartSurfaceSceneAgentTest,
       ClosingGroupedActiveNTPSpawnsNewUngroupedNTP) {
  base::test::ScopedFeatureList scoped_feature_list;
  std::vector<base::test::FeatureRef> enabled_features;
  enabled_features.push_back(kRemoveExcessNTPs);

  scoped_feature_list.InitWithFeatures(enabled_features, {});
  InsertNewWebState(0, GURL(kChromeUINewTabURL));
  InsertNewWebState(1, GURL(kChromeUINewTabURL));
  WebStateList* web_state_list =
      scene_state_.browserProviderInterface.mainBrowserProvider.browser
          ->GetWebStateList();
  web_state_list->ActivateWebStateAt(0);
  const TabGroup* group_0 =
      web_state_list->CreateGroup({0, 1}, {}, TabGroupId::GenerateNew());
  [agent_ sceneState:scene_state_
      transitionedToActivationLevel:SceneActivationLevelForegroundActive];
  histogram_tester_->ExpectTotalCount("IOS.NTP.ExcessRemovedTabCount", 0);

  // Transition to the background, triggering the NTP clean up.
  [agent_ sceneState:scene_state_
      transitionedToActivationLevel:SceneActivationLevelBackground];

  // Expect 2 calls to IOS.NTP.ExcessRemovedTabCount. One for the regular
  // browser, one for the incognito browser.
  histogram_tester_->ExpectTotalCount("IOS.NTP.ExcessRemovedTabCount", 2);
  // Regular browser got 1 NTP removed.
  histogram_tester_->ExpectBucketCount("IOS.NTP.ExcessRemovedTabCount", 1, 1);
  // Incognito browser got no NTP removed.
  histogram_tester_->ExpectBucketCount("IOS.NTP.ExcessRemovedTabCount", 0, 1);
  ASSERT_EQ(2, web_state_list->count());
  // First is NTP initially at index 1, in `group_0`.
  EXPECT_TRUE(IsUrlNtp(web_state_list->GetWebStateAt(0)->GetVisibleURL()));
  EXPECT_LE(web_state_list->GetWebStateAt(0)->GetNavigationItemCount(), 1);
  EXPECT_EQ(group_0, web_state_list->GetGroupOfWebStateAt(0));
  // Second is a newly-opened empty NTP, in no group. It needs to load first, as
  // it's a real WebState.
  web_state_list->GetWebStateAt(1)->GetNavigationManager()->LoadIfNecessary();
  EXPECT_TRUE(IsUrlNtp(web_state_list->GetWebStateAt(1)->GetVisibleURL()));
  EXPECT_LE(web_state_list->GetWebStateAt(1)->GetNavigationItemCount(), 1);
  EXPECT_EQ(nullptr, web_state_list->GetGroupOfWebStateAt(1));
}

// Tests that IOS.StartSurfaceShown is correctly logged for a valid warm start
// open.
TEST_F(StartSurfaceSceneAgentTest, LogCorrectWarmStartHistogram) {
  std::map<std::string, std::string> parameters;
  parameters[kReturnToStartSurfaceInactiveDurationInSeconds] = "0";
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitAndEnableFeatureWithParameters(kStartSurface,
                                                         parameters);

  app_state_.initStageForTesting = InitStageFinal;

  InsertNewWebState(0, GURL(kURL));
  InsertNewWebState(1, GURL(kChromeUINewTabURL));
  WebStateList* web_state_list =
      scene_state_.browserProviderInterface.mainBrowserProvider.browser
          ->GetWebStateList();
  web_state_list->ActivateWebStateAt(0);
  favicon::WebFaviconDriver::CreateForWebState(
      web_state_list->GetActiveWebState(),
      /*favicon_service=*/nullptr);
  SetStartSurfaceSessionObjectForSceneState(scene_state_);

  histogram_tester_->ExpectTotalCount("IOS.BackgroundTimeBeforeWarmStart", 0);
  [agent_ sceneState:scene_state_
      transitionedToActivationLevel:SceneActivationLevelForegroundActive];
  histogram_tester_->ExpectTotalCount("IOS.BackgroundTimeBeforeWarmStart", 1);
}

// Tests that IOS.StartSurfaceShown is correctly logged for a valid cold start
// open.
TEST_F(StartSurfaceSceneAgentTest, LogCorrectColdStartHistogram) {
  std::map<std::string, std::string> parameters;
  parameters[kReturnToStartSurfaceInactiveDurationInSeconds] = "0";
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitAndEnableFeatureWithParameters(kStartSurface,
                                                         parameters);

  app_state_.initStageForTesting = InitStageFinal;
  [startup_information_ setIsColdStart:YES];

  InsertNewWebState(0, GURL(kURL));
  InsertNewWebState(1, GURL(kChromeUINewTabURL));
  WebStateList* web_state_list =
      scene_state_.browserProviderInterface.mainBrowserProvider.browser
          ->GetWebStateList();
  web_state_list->ActivateWebStateAt(0);
  favicon::WebFaviconDriver::CreateForWebState(
      web_state_list->GetActiveWebState(),
      /*favicon_service=*/nullptr);

  histogram_tester_->ExpectTotalCount("IOS.BackgroundTimeBeforeColdStart", 0);
  [agent_ sceneState:scene_state_
      transitionedToActivationLevel:SceneActivationLevelForegroundActive];
  histogram_tester_->ExpectTotalCount("IOS.BackgroundTimeBeforeColdStart", 1);
}

TEST_F(StartSurfaceSceneAgentTest, PrefetchCapabilitiesOnAppStart) {
  base::test::ScopedFeatureList scoped_feature_list(
      kPrefetchSystemCapabilitiesOnAppStartup);

  // Set up fake identity with account capabilities.
  FakeSystemIdentity* identity = [FakeSystemIdentity fakeIdentity1];
  fake_system_identity_manager()->AddIdentity(identity);

  AccountCapabilitiesTestMutator* mutator =
      fake_system_identity_manager()->GetPendingCapabilitiesMutator(identity);
  mutator->SetAllSupportedCapabilities(true);

  // Set up expected app state that prefetches capabilities.
  app_state_.initStageForTesting = InitStageFinal;
  [startup_information_ setIsColdStart:YES];

  InsertNewWebState(0, GURL(kURL));
  InsertNewWebState(1, GURL(kChromeUINewTabURL));
  WebStateList* web_state_list =
      scene_state_.browserProviderInterface.mainBrowserProvider.browser
          ->GetWebStateList();
  web_state_list->ActivateWebStateAt(0);
  favicon::WebFaviconDriver::CreateForWebState(
      web_state_list->GetActiveWebState(),
      /*favicon_service=*/nullptr);

  ASSERT_FALSE(fake_system_identity_manager()
                   ->GetVisibleCapabilities(identity)
                   .AreAllCapabilitiesKnown());

  [agent_ sceneState:scene_state_
      transitionedToActivationLevel:SceneActivationLevelForegroundActive];
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(fake_system_identity_manager()
                  ->GetVisibleCapabilities(identity)
                  .AreAllCapabilitiesKnown());
}

TEST_F(StartSurfaceSceneAgentTest, DisablePrefetchCapabilitiesOnAppStart) {
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitAndDisableFeature(
      kPrefetchSystemCapabilitiesOnAppStartup);

  // Set up fake identity with account capabilities.
  FakeSystemIdentity* identity = [FakeSystemIdentity fakeIdentity1];
  fake_system_identity_manager()->AddIdentity(identity);

  AccountCapabilitiesTestMutator* mutator =
      fake_system_identity_manager()->GetPendingCapabilitiesMutator(identity);
  mutator->SetAllSupportedCapabilities(true);

  // Set up expected app state that prefetches capabilities.
  app_state_.initStageForTesting = InitStageFinal;
  [startup_information_ setIsColdStart:YES];

  InsertNewWebState(0, GURL(kURL));
  InsertNewWebState(1, GURL(kChromeUINewTabURL));
  WebStateList* web_state_list =
      scene_state_.browserProviderInterface.mainBrowserProvider.browser
          ->GetWebStateList();
  web_state_list->ActivateWebStateAt(0);
  favicon::WebFaviconDriver::CreateForWebState(
      web_state_list->GetActiveWebState(),
      /*favicon_service=*/nullptr);

  ASSERT_FALSE(fake_system_identity_manager()
                   ->GetVisibleCapabilities(identity)
                   .AreAllCapabilitiesKnown());

  [agent_ sceneState:scene_state_
      transitionedToActivationLevel:SceneActivationLevelForegroundActive];
  base::RunLoop().RunUntilIdle();

  EXPECT_FALSE(fake_system_identity_manager()
                   ->GetVisibleCapabilities(identity)
                   .AreAllCapabilitiesKnown());
}