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