blob: e5c4a2e1a9f79cc1dd1c6904d97eb0bcf43d7ac4 [file] [log] [blame]
// 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, false);
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, true);
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, false);
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, false);
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, false);
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, false);
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, false);
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, false);
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, false);
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, false);
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, false);
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, false);
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, false);
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, true);
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);
}