| // Copyright 2016 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. |
| |
| #include "chrome/browser/ui/startup/startup_browser_creator_impl.h" |
| |
| #include "base/command_line.h" |
| #include "chrome/browser/ui/startup/startup_tab_provider.h" |
| #include "chrome/common/url_constants.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using Creator = StartupBrowserCreatorImpl; |
| |
| namespace { |
| |
| // Bits for FakeStartupTabProvider options. |
| constexpr uint32_t kOnboardingTabs = 1 << 0; |
| constexpr uint32_t kDistributionFirstRunTabs = 1 << 1; |
| constexpr uint32_t kResetTriggerTabs = 1 << 2; |
| constexpr uint32_t kPinnedTabs = 1 << 3; |
| constexpr uint32_t kPreferencesTabs = 1 << 4; |
| constexpr uint32_t kNewTabPageTabs = 1 << 5; |
| constexpr uint32_t kWelcomeBackTab = 1 << 6; |
| constexpr uint32_t kPostCrashTab = 1 << 7; |
| |
| class FakeStartupTabProvider : public StartupTabProvider { |
| public: |
| // For each option passed, the corresponding adder below will add a sentinel |
| // tab and return true. For options not passed, the adder will return false. |
| explicit FakeStartupTabProvider(uint32_t options) : options_(options) {} |
| |
| StartupTabs GetOnboardingTabs(Profile* profile) const override { |
| StartupTabs tabs; |
| if (options_ & kOnboardingTabs) |
| tabs.emplace_back(GURL("https://onboarding"), false); |
| return tabs; |
| } |
| |
| StartupTabs GetDistributionFirstRunTabs( |
| StartupBrowserCreator* browser_creator) const override { |
| StartupTabs tabs; |
| if (options_ & kDistributionFirstRunTabs) |
| tabs.emplace_back(GURL("https://distribution"), false); |
| return tabs; |
| } |
| |
| StartupTabs GetResetTriggerTabs(Profile* profile) const override { |
| StartupTabs tabs; |
| if (options_ & kResetTriggerTabs) |
| tabs.emplace_back(GURL("https://reset-trigger"), false); |
| return tabs; |
| } |
| |
| StartupTabs GetPinnedTabs(const base::CommandLine& command_line_, |
| Profile* profile) const override { |
| StartupTabs tabs; |
| if (options_ & kPinnedTabs) |
| tabs.emplace_back(GURL("https://pinned"), true); |
| return tabs; |
| } |
| |
| StartupTabs GetPreferencesTabs(const base::CommandLine& command_line_, |
| Profile* profile) const override { |
| StartupTabs tabs; |
| if (options_ & kPreferencesTabs) |
| tabs.emplace_back(GURL("https://prefs"), false); |
| return tabs; |
| } |
| |
| StartupTabs GetNewTabPageTabs(const base::CommandLine& command_line_, |
| Profile* profile) const override { |
| StartupTabs tabs; |
| if (options_ & kNewTabPageTabs) |
| tabs.emplace_back(GURL("https://new-tab"), false); |
| return tabs; |
| } |
| |
| StartupTabs GetWelcomeBackTabs(Profile* profile, |
| StartupBrowserCreator* browser_creator, |
| bool process_startup) const override { |
| StartupTabs tabs; |
| if (process_startup && (options_ & kWelcomeBackTab)) |
| tabs.emplace_back(GURL("https://welcome-back"), false); |
| return tabs; |
| } |
| |
| StartupTabs GetPostCrashTabs( |
| bool has_incompatible_applications) const override { |
| StartupTabs tabs; |
| if (has_incompatible_applications && (options_ & kPostCrashTab)) |
| tabs.emplace_back(GURL("https://incompatible-applications"), false); |
| return tabs; |
| } |
| |
| private: |
| const uint32_t options_; |
| }; |
| |
| } // namespace |
| |
| // "Standard" case: Tabs specified in onboarding, reset trigger, pinned tabs, or |
| // preferences shouldn't interfere with each other. Nothing specified on the |
| // command line. Reset trigger always appears first. |
| TEST(StartupBrowserCreatorImplTest, DetermineStartupTabs) { |
| FakeStartupTabProvider provider(kOnboardingTabs | kResetTriggerTabs | |
| kPinnedTabs | kPreferencesTabs | |
| kNewTabPageTabs); |
| Creator impl(base::FilePath(), |
| base::CommandLine(base::CommandLine::NO_PROGRAM), |
| chrome::startup::IS_FIRST_RUN); |
| |
| StartupTabs output = impl.DetermineStartupTabs(provider, StartupTabs(), true, |
| false, false, false, true); |
| ASSERT_EQ(4U, output.size()); |
| EXPECT_EQ("reset-trigger", output[0].url.host()); |
| EXPECT_EQ("onboarding", output[1].url.host()); |
| EXPECT_EQ("prefs", output[2].url.host()); |
| EXPECT_EQ("pinned", output[3].url.host()); |
| |
| // No extra onboarding content for managed starts. |
| output = impl.DetermineStartupTabs(provider, StartupTabs(), true, false, |
| false, false, false); |
| ASSERT_EQ(3U, output.size()); |
| EXPECT_EQ("reset-trigger", output[0].url.host()); |
| EXPECT_EQ("prefs", output[1].url.host()); |
| EXPECT_EQ("pinned", output[2].url.host()); |
| } |
| |
| // Only the New Tab Page should appear in Incognito mode, skipping all the usual |
| // tabs. |
| TEST(StartupBrowserCreatorImplTest, DetermineStartupTabs_Incognito) { |
| FakeStartupTabProvider provider(kOnboardingTabs | kDistributionFirstRunTabs | |
| kResetTriggerTabs | kPinnedTabs | |
| kPreferencesTabs | kNewTabPageTabs); |
| Creator impl(base::FilePath(), |
| base::CommandLine(base::CommandLine::NO_PROGRAM), |
| chrome::startup::IS_FIRST_RUN); |
| |
| StartupTabs output = impl.DetermineStartupTabs(provider, StartupTabs(), true, |
| true, false, false, true); |
| ASSERT_EQ(1U, output.size()); |
| // Check for the actual NTP URL, rather than the sentinel returned by the |
| // fake, because the Provider is ignored entirely when short-circuited by |
| // incognito logic. |
| EXPECT_EQ(GURL(chrome::kChromeUINewTabURL), output[0].url); |
| } |
| |
| // Also only show the New Tab Page after a crash, except if there is a |
| // problem application. |
| TEST(StartupBrowserCreatorImplTest, DetermineStartupTabs_Crash) { |
| FakeStartupTabProvider provider( |
| kOnboardingTabs | kDistributionFirstRunTabs | kResetTriggerTabs | |
| kPinnedTabs | kPreferencesTabs | kNewTabPageTabs | kPostCrashTab); |
| Creator impl(base::FilePath(), |
| base::CommandLine(base::CommandLine::NO_PROGRAM), |
| chrome::startup::IS_FIRST_RUN); |
| |
| // Regular Crash Recovery case: |
| StartupTabs output = impl.DetermineStartupTabs(provider, StartupTabs(), true, |
| false, true, false, true); |
| ASSERT_EQ(1U, output.size()); |
| // Check for the actual NTP URL, rather than the sentinel returned by the |
| // fake, because the Provider is ignored entirely when short-circuited by |
| // the post-crash logic. |
| EXPECT_EQ(GURL(chrome::kChromeUINewTabURL), output[0].url); |
| |
| // Crash Recovery case with problem applications: |
| output = impl.DetermineStartupTabs(provider, StartupTabs(), true, false, true, |
| true, true); |
| ASSERT_EQ(1U, output.size()); |
| EXPECT_EQ(GURL("https://incompatible-applications"), output[0].url); |
| } |
| |
| // If Master Preferences specifies content, this should block all other |
| // policies. The only exception is command line URLs, tested below. |
| TEST(StartupBrowserCreatorImplTest, DetermineStartupTabs_MasterPrefs) { |
| FakeStartupTabProvider provider(kOnboardingTabs | kDistributionFirstRunTabs | |
| kResetTriggerTabs | kPinnedTabs | |
| kPreferencesTabs | kNewTabPageTabs); |
| Creator impl(base::FilePath(), |
| base::CommandLine(base::CommandLine::NO_PROGRAM), |
| chrome::startup::IS_FIRST_RUN); |
| |
| StartupTabs output = impl.DetermineStartupTabs(provider, StartupTabs(), true, |
| false, false, false, true); |
| ASSERT_EQ(1U, output.size()); |
| EXPECT_EQ("distribution", output[0].url.host()); |
| } |
| |
| // URLs specified on the command line should always appear, and should block |
| // all other tabs except the Reset Trigger tab. |
| TEST(StartupBrowserCreatorImplTest, DetermineStartupTabs_CommandLine) { |
| FakeStartupTabProvider provider(kOnboardingTabs | kDistributionFirstRunTabs | |
| kResetTriggerTabs | kPinnedTabs | |
| kPreferencesTabs | kNewTabPageTabs); |
| Creator impl(base::FilePath(), |
| base::CommandLine(base::CommandLine::NO_PROGRAM), |
| chrome::startup::IS_FIRST_RUN); |
| |
| StartupTabs cmd_line_tabs = {StartupTab(GURL("https://cmd-line"), false)}; |
| |
| StartupTabs output = impl.DetermineStartupTabs(provider, cmd_line_tabs, true, |
| false, false, false, true); |
| ASSERT_EQ(2U, output.size()); |
| EXPECT_EQ("reset-trigger", output[0].url.host()); |
| EXPECT_EQ("cmd-line", output[1].url.host()); |
| |
| // Also test that both incognito and crash recovery don't interfere with |
| // command line tabs. |
| |
| // Incognito |
| output = impl.DetermineStartupTabs(provider, cmd_line_tabs, true, true, false, |
| false, true); |
| ASSERT_EQ(1U, output.size()); |
| EXPECT_EQ("cmd-line", output[0].url.host()); |
| |
| // Crash Recovery |
| output = impl.DetermineStartupTabs(provider, cmd_line_tabs, true, false, true, |
| false, true); |
| ASSERT_EQ(1U, output.size()); |
| EXPECT_EQ("cmd-line", output[0].url.host()); |
| |
| // Crash Recovery with incompatible applications. |
| output = impl.DetermineStartupTabs(provider, cmd_line_tabs, true, false, true, |
| true, true); |
| ASSERT_EQ(1U, output.size()); |
| EXPECT_EQ("cmd-line", output[0].url.host()); |
| } |
| |
| // New Tab Page should appear alongside pinned tabs and the reset trigger, but |
| // should be superseded by onboarding tabs and by tabs specified in preferences. |
| TEST(StartupBrowserCreatorImplTest, DetermineStartupTabs_NewTabPage) { |
| FakeStartupTabProvider provider_allows_ntp(kPinnedTabs | kResetTriggerTabs | |
| kNewTabPageTabs); |
| Creator impl(base::FilePath(), |
| base::CommandLine(base::CommandLine::NO_PROGRAM), |
| chrome::startup::IS_FIRST_RUN); |
| |
| StartupTabs output = impl.DetermineStartupTabs( |
| provider_allows_ntp, StartupTabs(), true, false, false, false, true); |
| ASSERT_EQ(3U, output.size()); |
| EXPECT_EQ("reset-trigger", output[0].url.host()); |
| EXPECT_EQ("new-tab", output[1].url.host()); |
| EXPECT_EQ("pinned", output[2].url.host()); |
| } |
| |
| // The welcome back page should appear before any other session restore tabs. |
| TEST(StartupBrowserCreatorImplTest, DetermineStartupTabs_WelcomeBackPage) { |
| FakeStartupTabProvider provider_allows_ntp(kPinnedTabs | kPreferencesTabs | |
| kWelcomeBackTab); |
| Creator impl(base::FilePath(), |
| base::CommandLine(base::CommandLine::NO_PROGRAM), |
| chrome::startup::IS_FIRST_RUN); |
| |
| StartupTabs output = impl.DetermineStartupTabs( |
| provider_allows_ntp, StartupTabs(), true, false, false, false, true); |
| ASSERT_EQ(3U, output.size()); |
| EXPECT_EQ("welcome-back", output[0].url.host()); |
| EXPECT_EQ("prefs", output[1].url.host()); |
| EXPECT_EQ("pinned", output[2].url.host()); |
| |
| // No welcome back for non-startup opens. |
| output = impl.DetermineStartupTabs(provider_allows_ntp, StartupTabs(), false, |
| false, false, false, true); |
| ASSERT_EQ(2U, output.size()); |
| EXPECT_EQ("prefs", output[0].url.host()); |
| EXPECT_EQ("pinned", output[1].url.host()); |
| |
| // No welcome back for managed starts even if first run. |
| output = impl.DetermineStartupTabs(provider_allows_ntp, StartupTabs(), true, |
| false, false, false, false); |
| ASSERT_EQ(2U, output.size()); |
| EXPECT_EQ("prefs", output[0].url.host()); |
| EXPECT_EQ("pinned", output[1].url.host()); |
| } |
| |
| TEST(StartupBrowserCreatorImplTest, DetermineBrowserOpenBehavior_Startup) { |
| SessionStartupPref pref_default(SessionStartupPref::Type::DEFAULT); |
| SessionStartupPref pref_last(SessionStartupPref::Type::LAST); |
| SessionStartupPref pref_urls(SessionStartupPref::Type::URLS); |
| |
| // The most typical case: startup, not recovering from a crash, no switches. |
| // Test each pref with and without command-line tabs. |
| Creator::BrowserOpenBehavior output = Creator::DetermineBrowserOpenBehavior( |
| pref_default, Creator::PROCESS_STARTUP); |
| EXPECT_EQ(Creator::BrowserOpenBehavior::NEW, output); |
| |
| output = Creator::DetermineBrowserOpenBehavior( |
| pref_default, Creator::PROCESS_STARTUP | Creator::HAS_CMD_LINE_TABS); |
| EXPECT_EQ(Creator::BrowserOpenBehavior::NEW, output); |
| |
| output = Creator::DetermineBrowserOpenBehavior(pref_urls, |
| Creator::PROCESS_STARTUP); |
| EXPECT_EQ(Creator::BrowserOpenBehavior::NEW, output); |
| |
| output = Creator::DetermineBrowserOpenBehavior( |
| pref_urls, Creator::PROCESS_STARTUP | Creator::HAS_CMD_LINE_TABS); |
| EXPECT_EQ(Creator::BrowserOpenBehavior::NEW, output); |
| |
| output = Creator::DetermineBrowserOpenBehavior(pref_last, |
| Creator::PROCESS_STARTUP); |
| EXPECT_EQ(Creator::BrowserOpenBehavior::SYNCHRONOUS_RESTORE, output); |
| |
| output = Creator::DetermineBrowserOpenBehavior( |
| pref_last, Creator::PROCESS_STARTUP | Creator::HAS_CMD_LINE_TABS); |
| EXPECT_EQ(Creator::BrowserOpenBehavior::SYNCHRONOUS_RESTORE, output); |
| } |
| |
| TEST(StartupBrowserCreatorImplTest, DetermineBrowserOpenBehavior_CmdLineTabs) { |
| SessionStartupPref pref_default(SessionStartupPref::Type::DEFAULT); |
| SessionStartupPref pref_last(SessionStartupPref::Type::LAST); |
| SessionStartupPref pref_urls(SessionStartupPref::Type::URLS); |
| |
| // Command line tabs after startup should prompt use of existing window, |
| // regardless of pref. |
| Creator::BrowserOpenBehavior output = Creator::DetermineBrowserOpenBehavior( |
| pref_default, Creator::HAS_CMD_LINE_TABS); |
| EXPECT_EQ(Creator::BrowserOpenBehavior::USE_EXISTING, output); |
| |
| output = Creator::DetermineBrowserOpenBehavior(pref_urls, |
| Creator::HAS_CMD_LINE_TABS); |
| EXPECT_EQ(Creator::BrowserOpenBehavior::USE_EXISTING, output); |
| |
| output = Creator::DetermineBrowserOpenBehavior(pref_last, |
| Creator::HAS_CMD_LINE_TABS); |
| EXPECT_EQ(Creator::BrowserOpenBehavior::USE_EXISTING, output); |
| |
| // Exception: this can be overridden by passing a switch. |
| output = Creator::DetermineBrowserOpenBehavior( |
| pref_urls, Creator::HAS_NEW_WINDOW_SWITCH | Creator::HAS_CMD_LINE_TABS); |
| EXPECT_EQ(Creator::BrowserOpenBehavior::NEW, output); |
| } |
| |
| TEST(StartupBrowserCreatorImplTest, DetermineBrowserOpenBehavior_PostCrash) { |
| SessionStartupPref pref_last(SessionStartupPref::Type::LAST); |
| |
| // Launching after crash should block session restore. |
| Creator::BrowserOpenBehavior output = Creator::DetermineBrowserOpenBehavior( |
| pref_last, Creator::PROCESS_STARTUP | Creator::IS_POST_CRASH_LAUNCH); |
| EXPECT_EQ(Creator::BrowserOpenBehavior::NEW, output); |
| } |
| |
| TEST(StartupBrowserCreatorImplTest, DetermineBrowserOpenBehavior_NotStartup) { |
| SessionStartupPref pref_default(SessionStartupPref::Type::DEFAULT); |
| SessionStartupPref pref_last(SessionStartupPref::Type::LAST); |
| SessionStartupPref pref_urls(SessionStartupPref::Type::URLS); |
| |
| // Launch after startup without command-line tabs should always create a new |
| // window. |
| Creator::BrowserOpenBehavior output = |
| Creator::DetermineBrowserOpenBehavior(pref_default, 0); |
| EXPECT_EQ(Creator::BrowserOpenBehavior::NEW, output); |
| |
| output = Creator::DetermineBrowserOpenBehavior(pref_last, 0); |
| EXPECT_EQ(Creator::BrowserOpenBehavior::NEW, output); |
| |
| output = Creator::DetermineBrowserOpenBehavior(pref_urls, 0); |
| EXPECT_EQ(Creator::BrowserOpenBehavior::NEW, output); |
| } |