blob: 8e0ceb34fb2dbbde35581be05a6c1fc976b485c4 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/containers/contains.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_future.h"
#include "chrome/browser/lacros/browser_service_lacros.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h"
#include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_test_util.h"
#include "chrome/browser/sessions/exit_type_service.h"
#include "chrome/browser/sessions/session_restore.h"
#include "chrome/browser/sessions/session_restore_test_utils.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/profile_picker.h"
#include "chrome/browser/ui/profile_ui_test_utils.h"
#include "chrome/browser/ui/views/session_crashed_bubble_view.h"
#include "chrome/browser/ui/web_applications/app_browser_controller.h"
#include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
#include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
#include "chrome/browser/web_applications/web_app_install_info.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#include "components/keep_alive_registry/scoped_keep_alive.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/display/screen.h"
namespace {
web_app::AppId InstallPWA(Profile* profile, const GURL& start_url) {
auto web_app_info = std::make_unique<WebAppInstallInfo>();
web_app_info->start_url = start_url;
web_app_info->scope = start_url.GetWithoutFilename();
web_app_info->user_display_mode =
web_app::mojom::UserDisplayMode::kStandalone;
web_app_info->title = u"A Web App";
return web_app::test::InstallWebApp(profile, std::move(web_app_info));
}
} // namespace
class BrowserLauncherTest : public InProcessBrowserTest {
public:
BrowserLauncherTest() {
// Suppress the test-created about blank tab to be more representative of
// the startup and launch environment for testing.
set_open_about_blank_on_browser_launch(false);
}
BrowserLauncherTest(const BrowserLauncherTest&) = delete;
BrowserLauncherTest& operator=(const BrowserLauncherTest&) = delete;
~BrowserLauncherTest() override = default;
// InProcessBrowserTest:
void SetUpCommandLine(base::CommandLine* command_line) override {
InProcessBrowserTest::SetUpCommandLine(command_line);
// The kNoStartupWindow is applied when launching lacros-chrome with the
// kDoNotOpenWindow initial browser action.
command_line->AppendSwitch(switches::kNoStartupWindow);
}
void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
browser_service_ = std::make_unique<BrowserServiceLacros>();
}
void TearDownOnMainThread() override {
if (!skip_uninstall_) {
UninstallWebApps();
}
InProcessBrowserTest::TearDownOnMainThread();
}
void NewWindowSync(bool incognito, bool should_trigger_session_restore) {
base::test::TestFuture<void> new_window_future;
browser_service()->NewWindow(
incognito, should_trigger_session_restore,
display::Screen::GetScreen()->GetDisplayForNewWindows().id(),
new_window_future.GetCallback());
ASSERT_TRUE(new_window_future.Wait())
<< "NewWindow did not trigger the callback.";
}
void DisableWelcomePages(const std::vector<Profile*>& profiles) {
for (Profile* profile : profiles)
profile->GetPrefs()->SetBoolean(prefs::kHasSeenWelcomePage, true);
// Also disable What's New.
PrefService* pref_service = g_browser_process->local_state();
pref_service->SetInteger(prefs::kLastWhatsNewVersion, CHROME_VERSION_MAJOR);
}
// Creates a new profile with a URLS startup preference and an open tab.
void SetupSingleProfileWithURLSPreference() {
ProfileManager* profile_manager = g_browser_process->profile_manager();
ASSERT_TRUE(embedded_test_server()->Start());
// Create two profiles.
base::FilePath dest_path = profile_manager->user_data_dir();
Profile* profile = nullptr;
{
base::ScopedAllowBlockingForTesting allow_blocking;
profile = profile_manager->GetProfile(
dest_path.Append(FILE_PATH_LITERAL("New Profile")));
ASSERT_TRUE(profile);
}
DisableWelcomePages({profile});
// Don't delete Profile too early.
ScopedProfileKeepAlive profile_keep_alive(
profile, ProfileKeepAliveOrigin::kBrowserWindow);
// Open some urls in the browser.
Browser* browser = Browser::Create(
Browser::CreateParams(Browser::TYPE_NORMAL, profile, true));
chrome::NewTab(browser);
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser, embedded_test_server()->GetURL("/empty.html")));
// Establish the startup preference.
std::vector<GURL> urls;
urls.push_back(ui_test_utils::GetTestUrl(
base::FilePath(base::FilePath::kCurrentDirectory),
base::FilePath(FILE_PATH_LITERAL("title1.html"))));
urls.push_back(ui_test_utils::GetTestUrl(
base::FilePath(base::FilePath::kCurrentDirectory),
base::FilePath(FILE_PATH_LITERAL("title2.html"))));
// Set different startup preferences for the profile.
SessionStartupPref pref(SessionStartupPref::URLS);
pref.urls = urls;
SessionStartupPref::SetStartupPref(profile, pref);
profile->GetPrefs()->CommitPendingWrite();
// Ensure the session ends with the profile created above.
auto last_opened_profiles =
g_browser_process->profile_manager()->GetLastOpenedProfiles();
EXPECT_EQ(1u, last_opened_profiles.size());
EXPECT_TRUE(base::Contains(last_opened_profiles, profile));
}
BrowserServiceLacros* browser_service() const {
return browser_service_.get();
}
GURL GetWebAppStartUrl() const {
return GURL("https://lacros.example.com/example/index");
}
void SetSkipUninstall(bool value) { skip_uninstall_ = value; }
private:
void UninstallWebApps() {
ProfileManager* profile_manager = g_browser_process->profile_manager();
auto* profile = profile_manager->GetProfile(
profile_manager->GetPrimaryUserProfilePath());
web_app::WebAppRegistrar& registrar =
web_app::WebAppProvider::GetForTest(profile)->registrar_unsafe();
for (auto& app_id : registrar.GetAppIds()) {
web_app::test::UninstallWebApp(profile, app_id);
}
}
std::unique_ptr<BrowserServiceLacros> browser_service_;
bool skip_uninstall_ = false;
};
IN_PROC_BROWSER_TEST_F(BrowserLauncherTest, PRE_FullRestoreWithTwoProfiles) {
// Simulate a full restore by creating the profiles in a PRE_ test.
ProfileManager* profile_manager = g_browser_process->profile_manager();
ASSERT_TRUE(embedded_test_server()->Start());
// Create two profiles.
base::FilePath dest_path = profile_manager->user_data_dir();
Profile* profile1 = nullptr;
Profile* profile2 = nullptr;
{
base::ScopedAllowBlockingForTesting allow_blocking;
profile1 = profile_manager->GetProfile(
dest_path.Append(FILE_PATH_LITERAL("New Profile 1")));
ASSERT_TRUE(profile1);
profile2 = profile_manager->GetProfile(
dest_path.Append(FILE_PATH_LITERAL("New Profile 2")));
ASSERT_TRUE(profile2);
}
DisableWelcomePages({profile1, profile2});
// Don't delete Profiles too early.
ScopedProfileKeepAlive profile1_keep_alive(
profile1, ProfileKeepAliveOrigin::kBrowserWindow);
ScopedProfileKeepAlive profile2_keep_alive(
profile2, ProfileKeepAliveOrigin::kBrowserWindow);
// Open some urls with the browsers, and close them.
Browser* browser1 = Browser::Create(
Browser::CreateParams(Browser::TYPE_NORMAL, profile1, true));
chrome::NewTab(browser1);
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser1, embedded_test_server()->GetURL("/empty.html")));
Browser* browser2 = Browser::Create(
Browser::CreateParams(Browser::TYPE_NORMAL, profile2, true));
chrome::NewTab(browser2);
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser2, embedded_test_server()->GetURL("/form.html")));
// Set different startup preferences for the 2 profiles.
std::vector<GURL> urls1;
urls1.push_back(ui_test_utils::GetTestUrl(
base::FilePath(base::FilePath::kCurrentDirectory),
base::FilePath(FILE_PATH_LITERAL("title1.html"))));
std::vector<GURL> urls2;
urls2.push_back(ui_test_utils::GetTestUrl(
base::FilePath(base::FilePath::kCurrentDirectory),
base::FilePath(FILE_PATH_LITERAL("title2.html"))));
// Set different startup preferences for the 2 profiles.
SessionStartupPref pref1(SessionStartupPref::URLS);
pref1.urls = urls1;
SessionStartupPref::SetStartupPref(profile1, pref1);
SessionStartupPref pref2(SessionStartupPref::URLS);
pref2.urls = urls2;
SessionStartupPref::SetStartupPref(profile2, pref2);
profile1->GetPrefs()->CommitPendingWrite();
profile2->GetPrefs()->CommitPendingWrite();
// Ensure the session ends with the above two profiles.
auto last_opened_profiles =
g_browser_process->profile_manager()->GetLastOpenedProfiles();
EXPECT_EQ(2u, last_opened_profiles.size());
EXPECT_TRUE(base::Contains(last_opened_profiles, profile1));
EXPECT_TRUE(base::Contains(last_opened_profiles, profile2));
}
IN_PROC_BROWSER_TEST_F(BrowserLauncherTest, FullRestoreWithTwoProfiles) {
// Browser launch should be suppressed with the kNoStartupWindow switch.
ASSERT_FALSE(browser());
ProfileManager* profile_manager = g_browser_process->profile_manager();
// Open the two profiles.
base::FilePath dest_path = profile_manager->user_data_dir();
Profile* profile1 = nullptr;
Profile* profile2 = nullptr;
{
base::ScopedAllowBlockingForTesting allow_blocking;
profile1 = profile_manager->GetProfile(
dest_path.Append(FILE_PATH_LITERAL("New Profile 1")));
ASSERT_TRUE(profile1);
profile2 = profile_manager->GetProfile(
dest_path.Append(FILE_PATH_LITERAL("New Profile 2")));
ASSERT_TRUE(profile2);
}
// The profiles to be restored should match those setup in the PRE_ test.
auto last_opened_profiles =
g_browser_process->profile_manager()->GetLastOpenedProfiles();
EXPECT_EQ(2u, last_opened_profiles.size());
EXPECT_TRUE(base::Contains(last_opened_profiles, profile1));
EXPECT_TRUE(base::Contains(last_opened_profiles, profile2));
// Trigger Lacros full restore.
base::test::TestFuture<void> restore_waiter_future;
testing::SessionsRestoredWaiter restore_waiter(
restore_waiter_future.GetCallback(), 2);
browser_service()->OpenForFullRestore(/*skip_crash_restore=*/true);
ASSERT_TRUE(restore_waiter_future.Wait())
<< "restore_waiter did not trigger the callback.";
// The startup URLs are ignored, and instead the last open sessions are
// restored.
EXPECT_TRUE(profile1->restored_last_session());
EXPECT_TRUE(profile2->restored_last_session());
Browser* new_browser = nullptr;
ASSERT_EQ(1u, chrome::GetBrowserCount(profile1));
new_browser = chrome::FindBrowserWithProfile(profile1);
ASSERT_TRUE(new_browser);
TabStripModel* tab_strip = new_browser->tab_strip_model();
ASSERT_EQ(1, tab_strip->count());
EXPECT_EQ("/empty.html",
tab_strip->GetWebContentsAt(0)->GetLastCommittedURL().path());
ASSERT_EQ(1u, chrome::GetBrowserCount(profile2));
new_browser = chrome::FindBrowserWithProfile(profile2);
ASSERT_TRUE(new_browser);
tab_strip = new_browser->tab_strip_model();
ASSERT_EQ(1, tab_strip->count());
EXPECT_EQ("/form.html",
tab_strip->GetWebContentsAt(0)->GetLastCommittedURL().path());
}
IN_PROC_BROWSER_TEST_F(BrowserLauncherTest,
PRE_FullRestoreWillRestoreWebAppsIfPreviouslyOpen) {
// Browser launch should be suppressed with the kNoStartupWindow switch.
ASSERT_FALSE(browser());
ProfileManager* profile_manager = g_browser_process->profile_manager();
ASSERT_TRUE(embedded_test_server()->Start());
auto* profile =
profile_manager->GetProfile(profile_manager->GetPrimaryUserProfilePath());
// Don't delete the profile too early.
ScopedProfileKeepAlive profile_keep_alive(
profile, ProfileKeepAliveOrigin::kBrowserWindow);
// Set the startup pref to restore the last session.
SessionStartupPref pref(SessionStartupPref::LAST);
SessionStartupPref::SetStartupPref(profile, pref);
profile->GetPrefs()->CommitPendingWrite();
// Install and launch a PWA.
web_app::AppId app_id = InstallPWA(profile, GetWebAppStartUrl());
Browser* app_browser = web_app::LaunchWebAppBrowserAndWait(profile, app_id);
ASSERT_NE(app_browser, nullptr);
ASSERT_EQ(app_browser->type(), Browser::Type::TYPE_APP);
ASSERT_TRUE(web_app::AppBrowserController::IsForWebApp(app_browser, app_id));
// Launch a browser.
Browser* browser = Browser::Create(
Browser::CreateParams(Browser::TYPE_NORMAL, profile, true));
chrome::NewTab(browser);
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser, embedded_test_server()->GetURL("/empty.html")));
// Verify the state of the browser's tab strip.
TabStripModel* tab_strip = browser->tab_strip_model();
EXPECT_EQ(1, tab_strip->count());
EXPECT_EQ("/empty.html",
tab_strip->GetWebContentsAt(0)->GetLastCommittedURL().path());
// Ensure the session ends with the profile in last profiles.
auto last_opened_profiles =
g_browser_process->profile_manager()->GetLastOpenedProfiles();
EXPECT_EQ(1u, last_opened_profiles.size());
EXPECT_TRUE(base::Contains(last_opened_profiles, profile));
SetSkipUninstall(true);
}
IN_PROC_BROWSER_TEST_F(BrowserLauncherTest,
FullRestoreWillRestoreWebAppsIfPreviouslyOpen) {
// Browser launch should be suppressed with the kNoStartupWindow switch.
ASSERT_FALSE(browser());
ProfileManager* profile_manager = g_browser_process->profile_manager();
ASSERT_TRUE(embedded_test_server()->Start());
auto* profile =
profile_manager->GetProfile(profile_manager->GetPrimaryUserProfilePath());
// The profile should match the one set up in the PRE_ test.
auto last_opened_profiles =
g_browser_process->profile_manager()->GetLastOpenedProfiles();
EXPECT_EQ(1u, last_opened_profiles.size());
EXPECT_TRUE(base::Contains(last_opened_profiles, profile));
// Trigger Lacros full restore.
EXPECT_FALSE(profile->restored_last_session());
base::test::TestFuture<void> restore_waiter_future;
testing::SessionsRestoredWaiter restore_waiter(
restore_waiter_future.GetCallback(), 1);
browser_service()->OpenForFullRestore(/*skip_crash_restore=*/true);
ASSERT_TRUE(restore_waiter_future.Wait())
<< "restore_waiter did not trigger the callback.";
// The last session should be logged as restored.
EXPECT_TRUE(profile->restored_last_session());
// A tabbed browser and app browser should have been restored.
ASSERT_EQ(2u, chrome::GetBrowserCount(profile));
Browser* tabbed_browser =
chrome::FindAllTabbedBrowsersWithProfile(profile)[0];
TabStripModel* tab_strip = tabbed_browser->tab_strip_model();
ASSERT_EQ(1, tab_strip->count());
EXPECT_EQ("/empty.html",
tab_strip->GetWebContentsAt(0)->GetLastCommittedURL().path());
Browser* app_browser = nullptr;
for (auto* browser : *BrowserList::GetInstance()) {
if (browser->type() != Browser::Type::TYPE_APP)
continue;
EXPECT_FALSE(app_browser);
app_browser = browser;
}
ASSERT_TRUE(app_browser);
}
// Lacros Apps should only be restored when launching for full restore. Ensure
// Apps are not restored when performing a non-full-restore session restore for
// the browser (i.e. if all lacros windows are closed and a browser window is
// later re-opened we should trigger a session restore, but not restore any
// previously open app windows).
IN_PROC_BROWSER_TEST_F(
BrowserLauncherTest,
SessionRestoreDoesNotTriggerAppRestoreWhenOpeningNewWindows) {
// Browser launch should be suppressed with the kNoStartupWindow switch.
ASSERT_FALSE(browser());
ProfileManager* profile_manager = g_browser_process->profile_manager();
ASSERT_TRUE(embedded_test_server()->Start());
auto* profile =
profile_manager->GetProfile(profile_manager->GetPrimaryUserProfilePath());
// Keep the browser process running while the browsers are closed.
ScopedKeepAlive keep_alive(KeepAliveOrigin::BROWSER,
KeepAliveRestartOption::DISABLED);
ScopedProfileKeepAlive profile_keep_alive(
profile, ProfileKeepAliveOrigin::kBrowserWindow);
// Install and launch a PWA.
web_app::AppId app_id = InstallPWA(profile, GetWebAppStartUrl());
Browser* app_browser = web_app::LaunchWebAppBrowserAndWait(profile, app_id);
ASSERT_NE(app_browser, nullptr);
ASSERT_EQ(app_browser->type(), Browser::Type::TYPE_APP);
ASSERT_TRUE(web_app::AppBrowserController::IsForWebApp(app_browser, app_id));
// Launch a browser.
Browser* browser = Browser::Create(
Browser::CreateParams(Browser::TYPE_NORMAL, profile, true));
chrome::NewTab(browser);
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser, embedded_test_server()->GetURL("/empty.html")));
// Verify the state of the browser's tab strip.
TabStripModel* tab_strip = browser->tab_strip_model();
EXPECT_EQ(1, tab_strip->count());
EXPECT_EQ("/empty.html",
tab_strip->GetWebContentsAt(0)->GetLastCommittedURL().path());
// Close all browser windows and wait for the operation to complete.
size_t browser_count = chrome::GetTotalBrowserCount();
CloseAllBrowsers();
for (size_t i = 0; i < browser_count; ++i)
ui_test_utils::WaitForBrowserToClose();
ASSERT_EQ(0u, BrowserList::GetInstance()->size());
// Trigger a new window with session restore.
base::test::TestFuture<void> restore_waiter_future;
testing::SessionsRestoredWaiter restore_waiter(
restore_waiter_future.GetCallback(), 1);
NewWindowSync(/*incognito=*/false, /*should_trigger_session_restore=*/true);
ASSERT_TRUE(restore_waiter_future.Wait())
<< "restore_waiter did not trigger the callback.";
// The browser window should be restored but app browser should not.
ASSERT_EQ(1u, chrome::GetBrowserCount(profile));
browser = chrome::FindAllTabbedBrowsersWithProfile(profile)[0];
tab_strip = browser->tab_strip_model();
ASSERT_EQ(1, tab_strip->count());
EXPECT_EQ("/empty.html",
tab_strip->GetWebContentsAt(0)->GetLastCommittedURL().path());
}
IN_PROC_BROWSER_TEST_F(BrowserLauncherTest,
PRE_FullRestoreDoNotSkipCrashRestore) {
// Simulate a full restore by setting up a profile in a PRE_ test.
SetupSingleProfileWithURLSPreference();
}
IN_PROC_BROWSER_TEST_F(BrowserLauncherTest, FullRestoreDoNotSkipCrashRestore) {
// Browser launch should be suppressed with the kNoStartupWindow switch.
ASSERT_FALSE(browser());
ProfileManager* profile_manager = g_browser_process->profile_manager();
// Open the profile.
base::FilePath dest_path = profile_manager->user_data_dir();
Profile* profile = nullptr;
{
base::ScopedAllowBlockingForTesting allow_blocking;
profile = profile_manager->GetProfile(
dest_path.Append(FILE_PATH_LITERAL("New Profile")));
ASSERT_TRUE(profile);
}
// The profile to be restored should match the one in the PRE_ test.
auto last_opened_profiles =
g_browser_process->profile_manager()->GetLastOpenedProfiles();
EXPECT_EQ(1u, last_opened_profiles.size());
EXPECT_TRUE(base::Contains(last_opened_profiles, profile));
// Disable the profile picker and set the exit type to crashed.
g_browser_process->local_state()->SetInteger(
prefs::kBrowserProfilePickerAvailabilityOnStartup,
static_cast<int>(ProfilePicker::AvailabilityOnStartup::kDisabled));
ExitTypeService::GetInstanceForProfile(profile)
->SetLastSessionExitTypeForTest(ExitType::kCrashed);
// Trigger Lacros full restore but do not skip crash restore prompts.
browser_service()->OpenForFullRestore(/*skip_crash_restore=*/false);
// The browser should not be restored but instead we should have the browser's
// crash restore bubble prompt.
Browser* new_browser = nullptr;
ASSERT_EQ(1u, chrome::GetBrowserCount(profile));
new_browser = chrome::FindBrowserWithProfile(profile);
ASSERT_TRUE(new_browser);
TabStripModel* tab_strip = new_browser->tab_strip_model();
ASSERT_EQ(1, tab_strip->count());
EXPECT_TRUE(content::WaitForLoadStop(tab_strip->GetWebContentsAt(0)));
views::BubbleDialogDelegate* crash_bubble_delegate =
SessionCrashedBubbleView::GetInstanceForTest();
EXPECT_TRUE(crash_bubble_delegate);
}
IN_PROC_BROWSER_TEST_F(BrowserLauncherTest, PRE_FullRestoreSkipCrashRestore) {
// Simulate a full restore by setting up a profile in a PRE_ test.
SetupSingleProfileWithURLSPreference();
}
IN_PROC_BROWSER_TEST_F(BrowserLauncherTest, FullRestoreSkipCrashRestore) {
// Browser launch should be suppressed with the kNoStartupWindow switch.
ASSERT_FALSE(browser());
ProfileManager* profile_manager = g_browser_process->profile_manager();
// Open the profile.
base::FilePath dest_path = profile_manager->user_data_dir();
Profile* profile = nullptr;
{
base::ScopedAllowBlockingForTesting allow_blocking;
profile = profile_manager->GetProfile(
dest_path.Append(FILE_PATH_LITERAL("New Profile")));
ASSERT_TRUE(profile);
}
// The profile to be restored should match the one in the PRE_ test.
auto last_opened_profiles =
g_browser_process->profile_manager()->GetLastOpenedProfiles();
EXPECT_EQ(1u, last_opened_profiles.size());
EXPECT_TRUE(base::Contains(last_opened_profiles, profile));
// Disable the profile picker and set the exit type to crashed.
g_browser_process->local_state()->SetInteger(
prefs::kBrowserProfilePickerAvailabilityOnStartup,
static_cast<int>(ProfilePicker::AvailabilityOnStartup::kDisabled));
ExitTypeService::GetInstanceForProfile(profile)
->SetLastSessionExitTypeForTest(ExitType::kCrashed);
// Trigger Lacros full restore and skip crash restore prompts.
base::test::TestFuture<void> restore_waiter_future;
testing::SessionsRestoredWaiter restore_waiter(
restore_waiter_future.GetCallback(), 1);
browser_service()->OpenForFullRestore(/*skip_crash_restore=*/true);
ASSERT_TRUE(restore_waiter_future.Wait())
<< "restore_waiter did not trigger the callback.";
// The browser should be restored (ignoring startup preference).
Browser* new_browser = nullptr;
ASSERT_EQ(1u, chrome::GetBrowserCount(profile));
new_browser = chrome::FindBrowserWithProfile(profile);
ASSERT_TRUE(new_browser);
TabStripModel* tab_strip = new_browser->tab_strip_model();
ASSERT_EQ(1, tab_strip->count());
EXPECT_EQ("/empty.html",
tab_strip->GetWebContentsAt(0)->GetLastCommittedURL().path());
}