blob: 09ac1dd30b5c850f5ec3fd0c1ede3d5e9876eccb [file] [log] [blame]
// Copyright (c) 2015 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 <stddef.h>
#include <memory>
#include "base/callback_list.h"
#include "base/command_line.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/threading/thread_restrictions.h"
#include "base/win/windows_version.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profile_resetter/triggered_profile_resetter.h"
#include "chrome/browser/profile_resetter/triggered_profile_resetter_factory.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/signin/signin_promo.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/startup/startup_browser_creator.h"
#include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.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 "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/prefs/pref_service.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
// Check that there are two browsers. Find the one that is not |browser|.
Browser* FindOneOtherBrowser(Browser* browser) {
// There should only be one other browser.
EXPECT_EQ(2u, chrome::GetBrowserCount(browser->profile()));
// Find the new browser.
for (auto* b : *BrowserList::GetInstance()) {
if (b != browser)
return b;
}
return nullptr;
}
class MockTriggeredProfileResetter : public TriggeredProfileResetter {
public:
MockTriggeredProfileResetter() : TriggeredProfileResetter(nullptr) {}
void Activate() override {}
bool HasResetTrigger() override { return has_reset_trigger_; }
static void SetHasResetTrigger(bool has_reset_trigger) {
has_reset_trigger_ = has_reset_trigger;
}
private:
static bool has_reset_trigger_;
DISALLOW_COPY_AND_ASSIGN(MockTriggeredProfileResetter);
};
bool MockTriggeredProfileResetter::has_reset_trigger_ = false;
std::unique_ptr<KeyedService> BuildMockTriggeredProfileResetter(
content::BrowserContext* context) {
return base::WrapUnique(new MockTriggeredProfileResetter);
}
GURL GetTriggeredResetSettingsURL() {
return GURL(
chrome::GetSettingsUrl(chrome::kTriggeredResetProfileSettingsSubPage));
}
} // namespace
class StartupBrowserCreatorTriggeredResetTest : public InProcessBrowserTest {
public:
StartupBrowserCreatorTriggeredResetTest() {}
protected:
void SetUpInProcessBrowserTestFixture() override {
will_create_browser_context_services_subscription_ =
BrowserContextDependencyManager::GetInstance()
->RegisterWillCreateBrowserContextServicesCallbackForTesting(
base::Bind(&StartupBrowserCreatorTriggeredResetTest::
OnWillCreateBrowserContextServices,
base::Unretained(this)));
}
private:
void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
TriggeredProfileResetterFactory::GetInstance()->SetTestingFactory(
context, &BuildMockTriggeredProfileResetter);
}
std::unique_ptr<
base::CallbackList<void(content::BrowserContext*)>::Subscription>
will_create_browser_context_services_subscription_;
DISALLOW_COPY_AND_ASSIGN(StartupBrowserCreatorTriggeredResetTest);
};
IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTriggeredResetTest,
TestTriggeredReset) {
// Use a couple same-site HTTP URLs.
ASSERT_TRUE(embedded_test_server()->Start());
std::vector<GURL> urls;
urls.push_back(embedded_test_server()->GetURL("/title1.html"));
urls.push_back(embedded_test_server()->GetURL("/title2.html"));
Profile* profile = browser()->profile();
// Avoid showing the Welcome page.
profile->GetPrefs()->SetBoolean(prefs::kHasSeenWelcomePage, true);
#if defined(OS_WIN)
// Do not show the Windows 10 promo page.
g_browser_process->local_state()->SetBoolean(prefs::kHasSeenWin10PromoPage,
true);
#endif
// Set the startup preference to open these URLs.
SessionStartupPref pref(SessionStartupPref::URLS);
pref.urls = urls;
SessionStartupPref::SetStartupPref(profile, pref);
// Keep the browser process running while browsers are closed.
ScopedKeepAlive keep_alive(KeepAliveOrigin::BROWSER,
KeepAliveRestartOption::DISABLED);
// Close the browser.
CloseBrowserAsynchronously(browser());
// Prep the next launch to offer a reset prompt.
MockTriggeredProfileResetter::SetHasResetTrigger(true);
// Do a simple non-process-startup browser launch.
base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
StartupBrowserCreatorImpl launch(base::FilePath(), dummy,
chrome::startup::IS_NOT_FIRST_RUN);
ASSERT_TRUE(launch.Launch(profile, std::vector<GURL>(), false));
// This should have created a new browser window. |browser()| is still
// around at this point, even though we've closed its window.
Browser* new_browser = FindOneOtherBrowser(browser());
ASSERT_TRUE(new_browser);
std::vector<GURL> expected_urls(urls);
expected_urls.insert(expected_urls.begin(), GetTriggeredResetSettingsURL());
TabStripModel* tab_strip = new_browser->tab_strip_model();
ASSERT_EQ(static_cast<int>(expected_urls.size()), tab_strip->count());
for (size_t i = 0; i < expected_urls.size(); i++)
EXPECT_EQ(expected_urls[i], tab_strip->GetWebContentsAt(i)->GetURL());
}
class StartupBrowserCreatorTriggeredResetFirstRunTest
: public StartupBrowserCreatorTriggeredResetTest {
public:
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(switches::kForceFirstRun);
}
};
IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTriggeredResetFirstRunTest,
TestTriggeredResetDoesNotShowWithFirstRunURLs) {
// The presence of First Run tabs (in production code, these commonly come
// from master_preferences) should suppress the reset UI. Check that this is
// the case.
ASSERT_TRUE(embedded_test_server()->Start());
StartupBrowserCreator browser_creator;
browser_creator.AddFirstRunTab(
embedded_test_server()->GetURL("/title1.html"));
browser_creator.AddFirstRunTab(
embedded_test_server()->GetURL("/title2.html"));
// Prep the next launch to be offered a reset prompt.
MockTriggeredProfileResetter::SetHasResetTrigger(true);
// Avoid showing the Welcome page.
browser()->profile()->GetPrefs()->SetBoolean(prefs::kHasSeenWelcomePage,
true);
// Do a process-startup browser launch.
base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
chrome::startup::IS_FIRST_RUN);
ASSERT_TRUE(launch.Launch(browser()->profile(), std::vector<GURL>(), true));
// This should have created a new browser window.
Browser* new_browser = FindOneOtherBrowser(browser());
ASSERT_TRUE(new_browser);
// Verify that only the first-run tabs are shown.
TabStripModel* tab_strip = new_browser->tab_strip_model();
ASSERT_EQ(2, tab_strip->count());
EXPECT_EQ("title1.html",
tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName());
EXPECT_EQ("title2.html",
tab_strip->GetWebContentsAt(1)->GetURL().ExtractFileName());
}
IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTriggeredResetTest,
TestMultiProfile) {
SessionStartupPref pref(SessionStartupPref::DEFAULT);
SessionStartupPref::SetStartupPref(browser()->profile(), pref);
// Keep the browser process running while browsers are closed.
ScopedKeepAlive keep_alive(KeepAliveOrigin::BROWSER,
KeepAliveRestartOption::DISABLED);
// Close the browser.
CloseBrowserAsynchronously(browser());
// Prep the next launch to offer a reset prompt.
MockTriggeredProfileResetter::SetHasResetTrigger(true);
// Do a simple non-process-startup browser launch.
base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
{
StartupBrowserCreatorImpl launch(base::FilePath(), dummy,
chrome::startup::IS_NOT_FIRST_RUN);
ASSERT_TRUE(
launch.Launch(browser()->profile(), std::vector<GURL>(), false));
}
// This should have created a new browser window. |browser()| is still
// around at this point, even though we've closed its window.
Browser* new_browser = FindOneOtherBrowser(browser());
ASSERT_TRUE(new_browser);
// Now create a second browser instance pointing to a different profile.
ProfileManager* profile_manager = g_browser_process->profile_manager();
base::FilePath path =
profile_manager->user_data_dir().AppendASCII("test_profile");
Profile* other_profile = nullptr;
{
base::ScopedAllowBlockingForTesting allow_blocking;
other_profile =
Profile::CreateProfile(path, nullptr, Profile::CREATE_MODE_SYNCHRONOUS);
}
profile_manager->RegisterTestingProfile(other_profile, true, false);
// Use a couple same-site HTTP URLs.
ASSERT_TRUE(embedded_test_server()->Start());
std::vector<GURL> urls;
urls.push_back(embedded_test_server()->GetURL("/title1.html"));
urls.push_back(embedded_test_server()->GetURL("/title2.html"));
// Set the startup preference to open these URLs.
SessionStartupPref other_prefs(SessionStartupPref::URLS);
other_prefs.urls = urls;
SessionStartupPref::SetStartupPref(other_profile, other_prefs);
// Again prep the next launch to get a reset prompt.
MockTriggeredProfileResetter::SetHasResetTrigger(true);
// Same kind of simple non-process-startup browser launch.
{
StartupBrowserCreatorImpl launch(base::FilePath(), dummy,
chrome::startup::IS_NOT_FIRST_RUN);
ASSERT_TRUE(launch.Launch(other_profile, std::vector<GURL>(), false));
}
Browser* other_profile_browser =
chrome::FindBrowserWithProfile(other_profile);
ASSERT_NE(nullptr, other_profile_browser);
// Check for the expected reset dialog in the second browser too.
TabStripModel* other_tab_strip = other_profile_browser->tab_strip_model();
ASSERT_LT(0, other_tab_strip->count());
EXPECT_EQ(GetTriggeredResetSettingsURL(),
other_tab_strip->GetActiveWebContents()->GetURL());
}