first_run.h revision bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293
1// Copyright (c) 2010 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#ifndef CHROME_BROWSER_FIRST_RUN_FIRST_RUN_H_
6#define CHROME_BROWSER_FIRST_RUN_FIRST_RUN_H_
7#pragma once
8
9#include <vector>
10
11#include "base/basictypes.h"
12#include "chrome/browser/browser_process_impl.h"
13#include "chrome/browser/importer/importer.h"
14#include "chrome/common/result_codes.h"
15#include "gfx/native_widget_types.h"
16#include "googleurl/src/gurl.h"
17
18class CommandLine;
19class FilePath;
20class Profile;
21class ProcessSingleton;
22
23// This class contains the chrome first-run installation actions needed to
24// fully test the custom installer. It also contains the opposite actions to
25// execute during uninstall. When the first run UI is ready we won't
26// do the actions unconditionally. Currently the only action is to create a
27// desktop shortcut.
28//
29// The way we detect first-run is by looking at a 'sentinel' file.
30// If it does not exist we understand that we need to do the first time
31// install work for this user. After that the sentinel file is created.
32class FirstRun {
33 public:
34  // There are three types of possible first run bubbles:
35  typedef enum {
36    LARGE_BUBBLE,      // The normal bubble, with search engine choice
37    OEM_BUBBLE,        // Smaller bubble for OEM builds
38    MINIMAL_BUBBLE     // Minimal bubble shown after search engine dialog
39  } BubbleType;
40  // See ProcessMasterPreferences for more info about this structure.
41  struct MasterPrefs {
42    int ping_delay;
43    bool homepage_defined;
44    int do_import_items;
45    int dont_import_items;
46    bool run_search_engine_experiment;
47    bool randomize_search_engine_experiment;
48    bool make_chrome_default;
49    std::vector<GURL> new_tabs;
50    std::vector<GURL> bookmarks;
51  };
52#if defined(OS_WIN)
53  // Creates the desktop shortcut to chrome for the current user. Returns
54  // false if it fails. It will overwrite the shortcut if it exists.
55  static bool CreateChromeDesktopShortcut();
56  // Creates the quick launch shortcut to chrome for the current user. Returns
57  // false if it fails. It will overwrite the shortcut if it exists.
58  static bool CreateChromeQuickLaunchShortcut();
59  // Returns true if we are being run in a locale in which search experiments
60  // are allowed.
61  static bool InSearchExperimentLocale();
62#endif  // OS_WIN
63  // Import bookmarks and/or browser items (depending on platform support)
64  // in this process. This function is paired with FirstRun::ImportSettings().
65  // This function might or might not show a visible UI depending on the
66  // cmdline parameters.
67  static int ImportNow(Profile* profile, const CommandLine& cmdline);
68
69  // Automatically import history and home page (and search engine, if
70  // nonorganic).
71  static void AutoImport(
72      Profile* profile,
73      bool homepage_defined,
74      int import_items,
75      int dont_import_items,
76      bool search_engine_experiment,
77      bool randomize_search_engine_experiment,
78      bool make_chrome_default,
79      ProcessSingleton* process_singleton);
80
81  // Does platform specific setup. Called at the start of AutoImport.
82  static void PlatformSetup();
83
84  // Returns whether the current install is "organic".
85  static bool IsOrganic();
86
87  // Shows the search engine choice dialog, and any other platform dialogs.
88  // Only called in "organic" installs.
89  static void ShowFirstRunDialog(Profile* profile,
90                                 bool randomize_search_engine_experiment);
91
92  // The master preferences is a JSON file with the same entries as the
93  // 'Default\Preferences' file. This function locates this file from a standard
94  // location and processes it so it becomes the default preferences in the
95  // profile pointed to by |user_data_dir|. After processing the file, the
96  // function returns true if and only if showing the first run dialog is
97  // needed. The detailed settings in the preference file are reported via
98  // |preference_details|.
99  //
100  // This function destroys any existing prefs file and it is meant to be
101  // invoked only on first run.
102  //
103  // See chrome/installer/util/master_preferences.h for a description of
104  // 'master_preferences' file.
105  static bool ProcessMasterPreferences(const FilePath& user_data_dir,
106                                       MasterPrefs* out_prefs);
107
108  // Returns true if this is the first time chrome is run for this user.
109  static bool IsChromeFirstRun();
110  // Creates the sentinel file that signals that chrome has been configured.
111  static bool CreateSentinel();
112  // Removes the sentinel file created in ConfigDone(). Returns false if the
113  // sentinel file could not be removed.
114  static bool RemoveSentinel();
115  // Imports settings. This may be done in a separate process depending on the
116  // platform, but it will always block until done. The return value indicates
117  // success.
118  static bool ImportSettings(Profile* profile,
119                             scoped_refptr<ImporterHost> importer_host,
120                             int items_to_import);
121
122  // Sets the kShouldShowFirstRunBubble local state pref so that the browser
123  // shows the bubble once the main message loop gets going (or refrains from
124  // showing the bubble, if |show_bubble| is false). Returns false if the pref
125  // could not be set. This function can be called multiple times, but only the
126  // initial call will actually set the preference.
127  static bool SetShowFirstRunBubblePref(bool show_bubble);
128
129  // Sets the kShouldUseOEMFirstRunBubble local state pref so that the
130  // browser shows the OEM first run bubble once the main message loop
131  // gets going. Returns false if the pref could not be set.
132  static bool SetOEMFirstRunBubblePref();
133
134  // Sets the kShouldUseMinimalFirstRunBubble local state pref so that the
135  // browser shows the minimal first run bubble once the main message loop
136  // gets going. Returns false if the pref could not be set.
137  static bool SetMinimalFirstRunBubblePref();
138
139  // Sets the kShouldShowWelcomePage local state pref so that the browser
140  // loads the welcome tab once the message loop gets going. Returns false
141  // if the pref could not be set.
142  static bool SetShowWelcomePagePref();
143
144 private:
145  friend class FirstRunTest;
146  FRIEND_TEST_ALL_PREFIXES(Toolbar5ImporterTest, BookmarkParse);
147
148#if defined(OS_WIN)
149  // Writes the EULA to a temporary file, returned in |*eula_path|, and returns
150  // true if successful.
151  static bool WriteEULAtoTempFile(FilePath* eula_path);
152  // Launches the setup exe with the given parameter/value on the command-line,
153  // waits for its termination, returns its exit code in |*ret_code|, and
154  // returns true if the exit code is valid.
155  static bool LaunchSetupWithParam(const std::string& param,
156                                   const std::wstring& value,
157                                   int* ret_code);
158  // Installs a task to do an extensions update check once the extensions system
159  // is running.
160  static void DoDelayedInstallExtensions();
161  // Imports settings in a separate process. It is the implementation of the
162  // public version.  |skip_first_run_ui| is true if no first run UI should
163  // appear (search engine dialog, Firefox import warning dialog).
164  static bool ImportSettings(Profile* profile, int browser_type,
165                             int items_to_import,
166                             const FilePath& import_path,
167                             bool skip_first_run_ui,
168                             gfx::NativeView parent_window);
169  // Import browser items in this process. The browser and the items to
170  // import are encoded int the command line.
171  static int ImportFromBrowser(Profile* profile, const CommandLine& cmdline);
172#else
173  static bool ImportBookmarks(const FilePath& import_bookmarks_path);
174#endif
175
176  // Import bookmarks from an html file. The path to the file is provided in
177  // the command line.
178  static int ImportFromFile(Profile* profile, const CommandLine& cmdline);
179
180  // Gives the full path to the sentinel file. The file might not exist.
181  static bool GetFirstRunSentinelFilePath(FilePath* path);
182
183  enum FirstRunState {
184    FIRST_RUN_UNKNOWN,  // The state is not tested or set yet.
185    FIRST_RUN_TRUE,
186    FIRST_RUN_FALSE
187  };
188  // This variable should only be accessed through IsChromeFirstRun().
189  static FirstRunState first_run_;
190
191  // This class is for scoping purposes.
192  DISALLOW_IMPLICIT_CONSTRUCTORS(FirstRun);
193};
194
195#if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
196// This class contains the actions that need to be performed when an upgrade
197// is required. This involves mainly swapping the chrome exe and relaunching
198// the new browser.
199class Upgrade {
200 public:
201#if defined(OS_WIN)
202  // Possible results of ShowTryChromeDialog().
203  enum TryResult {
204    TD_TRY_CHROME,          // Launch chrome right now.
205    TD_NOT_NOW,             // Don't launch chrome. Exit now.
206    TD_UNINSTALL_CHROME,    // Initiate chrome uninstall and exit.
207    TD_DIALOG_ERROR,        // An error occurred creating the dialog.
208    TD_LAST_ENUM
209  };
210
211  // Check if current chrome.exe is already running as a browser process by
212  // trying to create a Global event with name same as full path of chrome.exe.
213  // This method caches the handle to this event so on subsequent calls also
214  // it can first close the handle and check for any other process holding the
215  // handle to the event.
216  static bool IsBrowserAlreadyRunning();
217
218  // If the new_chrome.exe exists (placed by the installer then is swapped
219  // to chrome.exe and the old chrome is renamed to old_chrome.exe. If there
220  // is no new_chrome.exe or the swap fails the return is false;
221  static bool SwapNewChromeExeIfPresent();
222
223  // Combines the two methods, RelaunchChromeBrowser and
224  // SwapNewChromeExeIfPresent, to perform the rename and relaunch of
225  // the browser. Note that relaunch does NOT exit the existing browser process.
226  // If this is called before message loop is executed, simply exit the main
227  // function. If browser is already running, you will need to exit it.
228  static bool DoUpgradeTasks(const CommandLine& command_line);
229
230  // Shows a modal dialog asking the user to give chrome another try. See
231  // above for the possible outcomes of the function. This is an experimental,
232  // non-localized dialog.
233  // |version| can be 0, 1 or 2 and selects what strings to present.
234  static TryResult ShowTryChromeDialog(size_t version);
235#endif  // OS_WIN
236
237  // Launches chrome again simulating a 'user' launch. If chrome could not
238  // be launched the return is false.
239  static bool RelaunchChromeBrowser(const CommandLine& command_line);
240
241#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
242  static void SaveLastModifiedTimeOfExe();
243#endif
244
245  static void SetNewCommandLine(CommandLine* new_command_line) {
246    // Takes ownership of the pointer.
247    new_command_line_ = new_command_line;
248  }
249
250  // Launches a new instance of the browser if the current instance in
251  // persistent mode an upgrade is detected.
252  static void RelaunchChromeBrowserWithNewCommandLineIfNeeded();
253
254  // Windows:
255  //  Checks if chrome_new.exe is present in the current instance's install.
256  // Linux:
257  //  Checks if the last modified time of chrome is newer than that of the
258  //  current running instance.
259  static bool IsUpdatePendingRestart();
260
261#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
262 private:
263  static double GetLastModifiedTimeOfExe();
264  static double saved_last_modified_time_of_exe_;
265#endif
266  static CommandLine* new_command_line_;
267};
268#endif  // (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
269
270// A subclass of BrowserProcessImpl that does not have a GoogleURLTracker or
271// IntranetRedirectDetector so we don't do any URL fetches (as we have no IO
272// thread to fetch on).
273class FirstRunBrowserProcess : public BrowserProcessImpl {
274 public:
275  explicit FirstRunBrowserProcess(const CommandLine& command_line)
276      : BrowserProcessImpl(command_line) {
277  }
278  virtual ~FirstRunBrowserProcess() { }
279
280  virtual GoogleURLTracker* google_url_tracker() { return NULL; }
281  virtual IntranetRedirectDetector* intranet_redirect_detector() {
282    return NULL;
283  }
284
285 private:
286  DISALLOW_COPY_AND_ASSIGN(FirstRunBrowserProcess);
287};
288
289// This class is used by FirstRun::ImportNow to get notified of the outcome of
290// the import operation. It differs from ImportProcessRunner in that this
291// class executes in the context of importing child process.
292// The values that it handles are meant to be used as the process exit code.
293class FirstRunImportObserver : public ImportObserver {
294 public:
295  FirstRunImportObserver()
296      : loop_running_(false), import_result_(ResultCodes::NORMAL_EXIT) {
297  }
298  int import_result() const;
299  virtual void ImportCanceled();
300  virtual void ImportComplete();
301  void RunLoop();
302 private:
303  void Finish();
304  bool loop_running_;
305  int import_result_;
306  DISALLOW_COPY_AND_ASSIGN(FirstRunImportObserver);
307};
308
309#endif  // CHROME_BROWSER_FIRST_RUN_FIRST_RUN_H_
310