1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <string>
6
7#include "base/command_line.h"
8#include "base/files/file_path.h"
9#include "base/memory/ref_counted.h"
10#include "base/prefs/pref_service.h"
11#include "base/strings/string_util.h"
12#include "base/strings/utf_string_conversions.h"
13#include "chrome/browser/browser_process.h"
14#include "chrome/browser/extensions/component_loader.h"
15#include "chrome/browser/first_run/first_run.h"
16#include "chrome/browser/importer/importer_list.h"
17#include "chrome/browser/prefs/chrome_pref_service_factory.h"
18#include "chrome/browser/profiles/profile_manager.h"
19#include "chrome/browser/ui/browser.h"
20#include "chrome/browser/ui/tabs/tab_strip_model.h"
21#include "chrome/common/chrome_switches.h"
22#include "chrome/common/pref_names.h"
23#include "chrome/common/url_constants.h"
24#include "chrome/test/base/in_process_browser_test.h"
25#include "chrome/test/base/ui_test_utils.h"
26#include "components/user_prefs/user_prefs.h"
27#include "content/public/browser/web_contents.h"
28#include "content/public/common/content_switches.h"
29#include "content/public/test/test_launcher.h"
30#include "testing/gtest/include/gtest/gtest.h"
31
32typedef InProcessBrowserTest FirstRunBrowserTest;
33
34IN_PROC_BROWSER_TEST_F(FirstRunBrowserTest, SetShowFirstRunBubblePref) {
35  EXPECT_TRUE(g_browser_process->local_state()->FindPreference(
36      prefs::kShowFirstRunBubbleOption));
37  EXPECT_EQ(first_run::FIRST_RUN_BUBBLE_DONT_SHOW,
38            g_browser_process->local_state()->GetInteger(
39                prefs::kShowFirstRunBubbleOption));
40  EXPECT_TRUE(first_run::SetShowFirstRunBubblePref(
41      first_run::FIRST_RUN_BUBBLE_SHOW));
42  ASSERT_TRUE(g_browser_process->local_state()->FindPreference(
43      prefs::kShowFirstRunBubbleOption));
44  EXPECT_EQ(first_run::FIRST_RUN_BUBBLE_SHOW,
45            g_browser_process->local_state()->GetInteger(
46                prefs::kShowFirstRunBubbleOption));
47  // Test that toggling the value works in either direction after it's been set.
48  EXPECT_TRUE(first_run::SetShowFirstRunBubblePref(
49      first_run::FIRST_RUN_BUBBLE_DONT_SHOW));
50  EXPECT_EQ(first_run::FIRST_RUN_BUBBLE_DONT_SHOW,
51            g_browser_process->local_state()->GetInteger(
52                prefs::kShowFirstRunBubbleOption));
53  // Test that the value can't be set to FIRST_RUN_BUBBLE_SHOW after it has been
54  // set to FIRST_RUN_BUBBLE_SUPPRESS.
55  EXPECT_TRUE(first_run::SetShowFirstRunBubblePref(
56      first_run::FIRST_RUN_BUBBLE_SUPPRESS));
57  EXPECT_EQ(first_run::FIRST_RUN_BUBBLE_SUPPRESS,
58            g_browser_process->local_state()->GetInteger(
59                prefs::kShowFirstRunBubbleOption));
60  EXPECT_TRUE(first_run::SetShowFirstRunBubblePref(
61      first_run::FIRST_RUN_BUBBLE_SHOW));
62  EXPECT_EQ(first_run::FIRST_RUN_BUBBLE_SUPPRESS,
63            g_browser_process->local_state()->GetInteger(
64                prefs::kShowFirstRunBubbleOption));
65}
66
67IN_PROC_BROWSER_TEST_F(FirstRunBrowserTest, SetShouldShowWelcomePage) {
68  EXPECT_FALSE(first_run::ShouldShowWelcomePage());
69  first_run::SetShouldShowWelcomePage();
70  EXPECT_TRUE(first_run::ShouldShowWelcomePage());
71  EXPECT_FALSE(first_run::ShouldShowWelcomePage());
72}
73
74#if !defined(OS_CHROMEOS)
75namespace {
76
77// A generic test class to be subclassed by test classes testing specific
78// master_preferences. All subclasses must call SetMasterPreferencesForTest()
79// from their SetUp() method before deferring the remainder of Setup() to this
80// class.
81class FirstRunMasterPrefsBrowserTestBase : public InProcessBrowserTest {
82 public:
83  FirstRunMasterPrefsBrowserTestBase() {}
84
85 protected:
86  virtual void SetUp() OVERRIDE {
87    // All users of this test class need to call SetMasterPreferencesForTest()
88    // before this class' SetUp() is invoked.
89    ASSERT_TRUE(text_.get());
90
91    ASSERT_TRUE(base::CreateTemporaryFile(&prefs_file_));
92    EXPECT_TRUE(base::WriteFile(prefs_file_, text_->c_str(), text_->size()));
93    first_run::SetMasterPrefsPathForTesting(prefs_file_);
94
95    // This invokes BrowserMain, and does the import, so must be done last.
96    InProcessBrowserTest::SetUp();
97  }
98
99  virtual void TearDown() OVERRIDE {
100    EXPECT_TRUE(base::DeleteFile(prefs_file_, false));
101    InProcessBrowserTest::TearDown();
102  }
103
104  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
105    InProcessBrowserTest::SetUpCommandLine(command_line);
106    command_line->AppendSwitch(switches::kForceFirstRun);
107    EXPECT_EQ(first_run::AUTO_IMPORT_NONE, first_run::auto_import_state());
108
109    extensions::ComponentLoader::EnableBackgroundExtensionsForTesting();
110  }
111
112  void SetMasterPreferencesForTest(const char text[]) {
113    text_.reset(new std::string(text));
114  }
115
116 private:
117  base::FilePath prefs_file_;
118  scoped_ptr<std::string> text_;
119
120  DISALLOW_COPY_AND_ASSIGN(FirstRunMasterPrefsBrowserTestBase);
121};
122
123template<const char Text[]>
124class FirstRunMasterPrefsBrowserTestT
125    : public FirstRunMasterPrefsBrowserTestBase {
126 public:
127  FirstRunMasterPrefsBrowserTestT() {}
128
129 protected:
130  virtual void SetUp() OVERRIDE {
131    SetMasterPreferencesForTest(Text);
132    FirstRunMasterPrefsBrowserTestBase::SetUp();
133  }
134
135 private:
136  DISALLOW_COPY_AND_ASSIGN(FirstRunMasterPrefsBrowserTestT);
137};
138
139// Returns the true expected import state, derived from the original
140// |expected_import_state|, for the current test machine's configuration. Some
141// bot configurations do not have another profile (browser) to import from and
142// thus the import must not be expected to have occurred.
143int MaskExpectedImportState(int expected_import_state) {
144  scoped_ptr<ImporterList> importer_list(new ImporterList());
145  base::RunLoop run_loop;
146  importer_list->DetectSourceProfiles(
147      g_browser_process->GetApplicationLocale(),
148      false,  // include_interactive_profiles?
149      run_loop.QuitClosure());
150  run_loop.Run();
151  int source_profile_count = importer_list->count();
152#if defined(OS_WIN)
153  // On Windows, the importer's DetectIEProfiles() will always add to the count.
154  // Internet Explorer always exists and always has something to import.
155  EXPECT_GT(source_profile_count, 0);
156#endif
157  if (source_profile_count == 0)
158    return expected_import_state & ~first_run::AUTO_IMPORT_PROFILE_IMPORTED;
159  return expected_import_state;
160}
161
162}  // namespace
163
164extern const char kImportDefault[] =
165    "{\n"
166    "}\n";
167typedef FirstRunMasterPrefsBrowserTestT<kImportDefault>
168    FirstRunMasterPrefsImportDefault;
169// http://crbug.com/314221
170#if defined(GOOGLE_CHROME_BUILD) && (defined(OS_MACOSX) || defined(OS_LINUX))
171#define MAYBE_ImportDefault DISABLED_ImportDefault
172#else
173#define MAYBE_ImportDefault ImportDefault
174#endif
175IN_PROC_BROWSER_TEST_F(FirstRunMasterPrefsImportDefault, MAYBE_ImportDefault) {
176  int auto_import_state = first_run::auto_import_state();
177  EXPECT_EQ(MaskExpectedImportState(first_run::AUTO_IMPORT_CALLED |
178                                    first_run::AUTO_IMPORT_PROFILE_IMPORTED),
179            auto_import_state);
180}
181
182// The bookmarks file doesn't actually need to exist for this integration test
183// to trigger the interaction being tested.
184extern const char kImportBookmarksFile[] =
185    "{\n"
186    "  \"distribution\": {\n"
187    "     \"import_bookmarks_from_file\": \"/foo/doesntexists.wtv\"\n"
188    "  }\n"
189    "}\n";
190typedef FirstRunMasterPrefsBrowserTestT<kImportBookmarksFile>
191    FirstRunMasterPrefsImportBookmarksFile;
192// http://crbug.com/314221
193#if defined(GOOGLE_CHROME_BUILD) && (defined(OS_MACOSX) || defined(OS_LINUX))
194#define MAYBE_ImportBookmarksFile DISABLED_ImportBookmarksFile
195#else
196#define MAYBE_ImportBookmarksFile ImportBookmarksFile
197#endif
198IN_PROC_BROWSER_TEST_F(FirstRunMasterPrefsImportBookmarksFile,
199                       MAYBE_ImportBookmarksFile) {
200  int auto_import_state = first_run::auto_import_state();
201  EXPECT_EQ(
202      MaskExpectedImportState(first_run::AUTO_IMPORT_CALLED |
203                              first_run::AUTO_IMPORT_PROFILE_IMPORTED |
204                              first_run::AUTO_IMPORT_BOOKMARKS_FILE_IMPORTED),
205      auto_import_state);
206}
207
208// Test an import with all import options disabled. This is a regression test
209// for http://crbug.com/169984 where this would cause the import process to
210// stay running, and the NTP to be loaded with no apps.
211extern const char kImportNothing[] =
212    "{\n"
213    "  \"distribution\": {\n"
214    "    \"import_bookmarks\": false,\n"
215    "    \"import_history\": false,\n"
216    "    \"import_home_page\": false,\n"
217    "    \"import_search_engine\": false\n"
218    "  }\n"
219    "}\n";
220typedef FirstRunMasterPrefsBrowserTestT<kImportNothing>
221    FirstRunMasterPrefsImportNothing;
222// http://crbug.com/314221
223#if defined(GOOGLE_CHROME_BUILD) && (defined(OS_MACOSX) || defined(OS_LINUX))
224#define MAYBE_ImportNothingAndShowNewTabPage \
225    DISABLED_ImportNothingAndShowNewTabPage
226#else
227#define MAYBE_ImportNothingAndShowNewTabPage ImportNothingAndShowNewTabPage
228#endif
229IN_PROC_BROWSER_TEST_F(FirstRunMasterPrefsImportNothing,
230                       MAYBE_ImportNothingAndShowNewTabPage) {
231  EXPECT_EQ(first_run::AUTO_IMPORT_CALLED, first_run::auto_import_state());
232  ui_test_utils::NavigateToURLWithDisposition(
233      browser(), GURL(chrome::kChromeUINewTabURL), CURRENT_TAB,
234      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
235  content::WebContents* tab = browser()->tab_strip_model()->GetWebContentsAt(0);
236  EXPECT_EQ(1, tab->GetMaxPageID());
237}
238
239// Test first run with some tracked preferences.
240extern const char kWithTrackedPrefs[] =
241    "{\n"
242    "  \"homepage\": \"example.com\",\n"
243    "  \"homepage_is_newtabpage\": false\n"
244    "}\n";
245// A test fixture that will run in a first run scenario with master_preferences
246// set to kWithTrackedPrefs. Parameterizable on the SettingsEnforcement
247// experiment to be forced.
248class FirstRunMasterPrefsWithTrackedPreferences
249    : public FirstRunMasterPrefsBrowserTestT<kWithTrackedPrefs>,
250      public testing::WithParamInterface<std::string> {
251 public:
252  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
253    FirstRunMasterPrefsBrowserTestT::SetUpCommandLine(command_line);
254    command_line->AppendSwitchASCII(
255        switches::kForceFieldTrials,
256        std::string(chrome_prefs::internals::kSettingsEnforcementTrialName) +
257            "/" + GetParam() + "/");
258  }
259};
260
261// http://crbug.com/314221
262#if defined(GOOGLE_CHROME_BUILD) && (defined(OS_MACOSX) || defined(OS_LINUX))
263#define MAYBE_TrackedPreferencesSurviveFirstRun \
264    DISABLED_TrackedPreferencesSurviveFirstRun
265#else
266#define MAYBE_TrackedPreferencesSurviveFirstRun \
267    TrackedPreferencesSurviveFirstRun
268#endif
269IN_PROC_BROWSER_TEST_P(FirstRunMasterPrefsWithTrackedPreferences,
270                       MAYBE_TrackedPreferencesSurviveFirstRun) {
271  const PrefService* user_prefs = browser()->profile()->GetPrefs();
272  EXPECT_EQ("example.com", user_prefs->GetString(prefs::kHomePage));
273  EXPECT_FALSE(user_prefs->GetBoolean(prefs::kHomePageIsNewTabPage));
274
275  // The test for kHomePageIsNewTabPage above relies on the fact that true is
276  // the default (hence false must be the user's pref); ensure this fact remains
277  // true.
278  const base::Value* default_homepage_is_ntp_value =
279      user_prefs->GetDefaultPrefValue(prefs::kHomePageIsNewTabPage);
280  ASSERT_TRUE(default_homepage_is_ntp_value != NULL);
281  bool default_homepage_is_ntp = false;
282  EXPECT_TRUE(
283      default_homepage_is_ntp_value->GetAsBoolean(&default_homepage_is_ntp));
284  EXPECT_TRUE(default_homepage_is_ntp);
285}
286
287INSTANTIATE_TEST_CASE_P(
288    FirstRunMasterPrefsWithTrackedPreferencesInstance,
289    FirstRunMasterPrefsWithTrackedPreferences,
290    testing::Values(
291        chrome_prefs::internals::kSettingsEnforcementGroupNoEnforcement,
292        chrome_prefs::internals::kSettingsEnforcementGroupEnforceAlways,
293        chrome_prefs::internals::
294            kSettingsEnforcementGroupEnforceAlwaysWithDSE,
295        chrome_prefs::internals::
296            kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE));
297
298#endif  // !defined(OS_CHROMEOS)
299