blob: 0d4723d88c274807aab73325330fe0b086f5f8a8 [file] [log] [blame]
// Copyright (c) 2010 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.
#ifndef CHROME_BROWSER_FIRST_RUN_H_
#define CHROME_BROWSER_FIRST_RUN_H_
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "chrome/browser/browser_process_impl.h"
#include "chrome/browser/importer/importer.h"
#include "chrome/common/result_codes.h"
#include "gfx/native_widget_types.h"
#include "googleurl/src/gurl.h"
class CommandLine;
class FilePath;
class Profile;
class ProcessSingleton;
// This class contains the chrome first-run installation actions needed to
// fully test the custom installer. It also contains the opposite actions to
// execute during uninstall. When the first run UI is ready we won't
// do the actions unconditionally. Currently the only action is to create a
// desktop shortcut.
//
// The way we detect first-run is by looking at a 'sentinel' file.
// If it does not exist we understand that we need to do the first time
// install work for this user. After that the sentinel file is created.
class FirstRun {
public:
// There are three types of possible first run bubbles:
typedef enum {
LARGEBUBBLE = 0, // The normal bubble, with search engine choice
OEMBUBBLE, // Smaller bubble for OEM builds
MINIMALBUBBLE // Minimal bubble shown after search engine dialog
} BubbleType;
// See ProcessMasterPreferences for more info about this structure.
struct MasterPrefs {
int ping_delay;
bool homepage_defined;
int do_import_items;
int dont_import_items;
bool run_search_engine_experiment;
bool randomize_search_engine_experiment;
std::vector<GURL> new_tabs;
std::vector<GURL> bookmarks;
};
#if defined(OS_WIN)
// Creates the desktop shortcut to chrome for the current user. Returns
// false if it fails. It will overwrite the shortcut if it exists.
static bool CreateChromeDesktopShortcut();
// Creates the quick launch shortcut to chrome for the current user. Returns
// false if it fails. It will overwrite the shortcut if it exists.
static bool CreateChromeQuickLaunchShortcut();
// Returns true if we are being run in a locale in which search experiments
// are allowed.
static bool InSearchExperimentLocale();
#endif // OS_WIN
// Import bookmarks and/or browser items (depending on platform support)
// in this process. This function is paired with FirstRun::ImportSettings().
// This function might or might not show a visible UI depending on the
// cmdline parameters.
static int ImportNow(Profile* profile, const CommandLine& cmdline);
// Automatically import history and home page (and search engine, if
// nonorganic).
static void AutoImport(Profile* profile,
bool homepage_defined,
int import_items,
int dont_import_items,
bool search_engine_experiment,
bool randomize_search_engine_experiment,
ProcessSingleton* process_singleton);
// The master preferences is a JSON file with the same entries as the
// 'Default\Preferences' file. This function locates this file from a standard
// location and processes it so it becomes the default preferences in the
// profile pointed to by |user_data_dir|. After processing the file, the
// function returns true if and only if showing the first run dialog is
// needed. The detailed settings in the preference file are reported via
// |preference_details|.
//
// This function destroys any existing prefs file and it is meant to be
// invoked only on first run.
//
// See chrome/installer/util/master_preferences.h for a description of
// 'master_preferences' file.
static bool ProcessMasterPreferences(const FilePath& user_data_dir,
MasterPrefs* out_prefs);
// Returns true if this is the first time chrome is run for this user.
static bool IsChromeFirstRun();
// Creates the sentinel file that signals that chrome has been configured.
static bool CreateSentinel();
// Removes the sentinel file created in ConfigDone(). Returns false if the
// sentinel file could not be removed.
static bool RemoveSentinel();
// Imports settings in a separate process. It spawns a second dedicated
// browser process that just does the import with the import progress UI.
static bool ImportSettings(Profile* profile, int browser_type,
int items_to_import,
gfx::NativeView parent_window);
// Sets the kShouldShowFirstRunBubble local state pref so that the browser
// shows the bubble once the main message loop gets going (or refrains from
// showing the bubble, if |show_bubble| is false). Returns false if the pref
// could not be set. This function can be called multiple times, but only the
// initial call will actually set the preference.
static bool SetShowFirstRunBubblePref(bool show_bubble);
// Sets the kShouldUseOEMFirstRunBubble local state pref so that the
// browser shows the OEM first run bubble once the main message loop
// gets going. Returns false if the pref could not be set.
static bool SetOEMFirstRunBubblePref();
// Sets the kShouldUseMinimalFirstRunBubble local state pref so that the
// browser shows the minimal first run bubble once the main message loop
// gets going. Returns false if the pref could not be set.
static bool SetMinimalFirstRunBubblePref();
// Sets the kShouldShowWelcomePage local state pref so that the browser
// loads the welcome tab once the message loop gets going. Returns false
// if the pref could not be set.
static bool SetShowWelcomePagePref();
private:
friend class FirstRunTest;
#if defined(OS_WIN)
// Imports settings in a separate process. It is the implementation of the
// public version. |skip_first_run_ui| is true if no first run UI should
// appear (search engine dialog, Firefox import warning dialog).
static bool ImportSettings(Profile* profile, int browser_type,
int items_to_import,
const std::wstring& import_path,
bool skip_first_run_ui,
gfx::NativeView parent_window);
// Import browser items in this process. The browser and the items to
// import are encoded int the command line.
static int ImportFromBrowser(Profile* profile, const CommandLine& cmdline);
#elif defined(OS_LINUX)
static bool ImportBookmarks(const std::wstring& import_bookmarks_path);
#endif
// Import bookmarks from an html file. The path to the file is provided in
// the command line.
static int ImportFromFile(Profile* profile, const CommandLine& cmdline);
// Gives the full path to the sentinel file. The file might not exist.
static bool GetFirstRunSentinelFilePath(FilePath* path);
// This class is for scoping purposes.
DISALLOW_IMPLICIT_CONSTRUCTORS(FirstRun);
};
#if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
// This class contains the actions that need to be performed when an upgrade
// is required. This involves mainly swapping the chrome exe and relaunching
// the new browser.
class Upgrade {
public:
#if defined(OS_WIN)
// Possible results of ShowTryChromeDialog().
enum TryResult {
TD_TRY_CHROME, // Launch chrome right now.
TD_NOT_NOW, // Don't launch chrome. Exit now.
TD_UNINSTALL_CHROME, // Initiate chrome uninstall and exit.
TD_DIALOG_ERROR, // An error occurred creating the dialog.
TD_LAST_ENUM
};
// Check if current chrome.exe is already running as a browser process by
// trying to create a Global event with name same as full path of chrome.exe.
// This method caches the handle to this event so on subsequent calls also
// it can first close the handle and check for any other process holding the
// handle to the event.
static bool IsBrowserAlreadyRunning();
// If the new_chrome.exe exists (placed by the installer then is swapped
// to chrome.exe and the old chrome is renamed to old_chrome.exe. If there
// is no new_chrome.exe or the swap fails the return is false;
static bool SwapNewChromeExeIfPresent();
// Combines the two methods, RelaunchChromeBrowser and
// SwapNewChromeExeIfPresent, to perform the rename and relaunch of
// the browser. Note that relaunch does NOT exit the existing browser process.
// If this is called before message loop is executed, simply exit the main
// function. If browser is already running, you will need to exit it.
static bool DoUpgradeTasks(const CommandLine& command_line);
// Shows a modal dialog asking the user to give chrome another try. See
// above for the possible outcomes of the function. This is an experimental,
// non-localized dialog.
// |version| can be 0, 1 or 2 and selects what strings to present.
static TryResult ShowTryChromeDialog(size_t version);
#endif // OS_WIN
// Launches chrome again simulating a 'user' launch. If chrome could not
// be launched the return is false.
static bool RelaunchChromeBrowser(const CommandLine& command_line);
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
static void SaveLastModifiedTimeOfExe();
#endif
static void SetNewCommandLine(CommandLine* new_command_line) {
// Takes ownership of the pointer.
new_command_line_ = new_command_line;
}
// Launches a new instance of the browser if the current instance in
// persistent mode an upgrade is detected.
static void RelaunchChromeBrowserWithNewCommandLineIfNeeded();
// Windows:
// Checks if chrome_new.exe is present in the current instance's install.
// Linux:
// Checks if the last modified time of chrome is newer than that of the
// current running instance.
static bool IsUpdatePendingRestart();
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
private:
static double GetLastModifiedTimeOfExe();
static double saved_last_modified_time_of_exe_;
#endif
static CommandLine* new_command_line_;
};
#endif // (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
// A subclass of BrowserProcessImpl that does not have a GoogleURLTracker or
// IntranetRedirectDetector so we don't do any URL fetches (as we have no IO
// thread to fetch on).
class FirstRunBrowserProcess : public BrowserProcessImpl {
public:
explicit FirstRunBrowserProcess(const CommandLine& command_line)
: BrowserProcessImpl(command_line) {
}
virtual ~FirstRunBrowserProcess() { }
virtual GoogleURLTracker* google_url_tracker() { return NULL; }
virtual IntranetRedirectDetector* intranet_redirect_detector() {
return NULL;
}
private:
DISALLOW_COPY_AND_ASSIGN(FirstRunBrowserProcess);
};
// This class is used by FirstRun::ImportNow to get notified of the outcome of
// the import operation. It differs from ImportProcessRunner in that this
// class executes in the context of importing child process.
// The values that it handles are meant to be used as the process exit code.
class FirstRunImportObserver : public ImportObserver {
public:
FirstRunImportObserver()
: loop_running_(false), import_result_(ResultCodes::NORMAL_EXIT) {
}
int import_result() const;
virtual void ImportCanceled();
virtual void ImportComplete();
void RunLoop();
private:
void Finish();
bool loop_running_;
int import_result_;
DISALLOW_COPY_AND_ASSIGN(FirstRunImportObserver);
};
// Show the First Run UI to the user, allowing them to create shortcuts for
// the app, import their bookmarks and other data from another browser into
// |profile| and perhaps some other tasks.
// |process_singleton| is used to lock the handling of CopyData messages
// while the First Run UI is visible.
// |homepage_defined| true indicates that homepage is defined in master
// preferences and should not be imported from another browser.
// |import_items| specifies the items to import, specified in master
// preferences and will override default behavior of importer.
// |dont_import_items| specifies the items *not* to import, specified in master
// preferences and will override default behavior of importer.
// |search_engine_experiment| indicates whether the experimental search engine
// window should be shown.
// |randomize_search_engine_experiment| is true if the logos in the search
// engine window should be shown in randomized order.
// Returns true if the user clicked "Start", false if the user pressed "Cancel"
// or closed the dialog.
bool OpenFirstRunDialog(Profile* profile,
bool homepage_defined,
int import_items,
int dont_import_items,
bool search_engine_experiment,
bool randomize_search_engine_experiment,
ProcessSingleton* process_singleton);
#endif // CHROME_BROWSER_FIRST_RUN_H_