diff options
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/chrome_browser_main.cc | 10 | ||||
-rw-r--r-- | chrome/browser/first_run/first_run.h | 17 | ||||
-rw-r--r-- | chrome/browser/first_run/first_run_posix.cc | 15 | ||||
-rw-r--r-- | chrome/browser/first_run/first_run_win.cc | 119 | ||||
-rw-r--r-- | chrome/browser/process_singleton_win.cc | 4 | ||||
-rw-r--r-- | chrome/browser/shell_integration_win.cc | 7 |
6 files changed, 105 insertions, 67 deletions
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index d40fb0d..b0e2f70 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc @@ -821,8 +821,14 @@ int ChromeBrowserMainParts::PreCreateThreadsImpl() { // is initialized. first_run_ui_bypass_ = false; // True to skip first run UI. if (is_first_run_) { - first_run_ui_bypass_ = !first_run::ProcessMasterPreferences( - user_data_dir_, master_prefs_.get()); + first_run::ProcessMasterPreferencesResult pmp_result = + first_run::ProcessMasterPreferences(user_data_dir_, + master_prefs_.get()); + if (pmp_result == first_run::EULA_EXIT_NOW) + return chrome::RESULT_CODE_EULA_REFUSED; + + first_run_ui_bypass_ = (pmp_result == first_run::SKIP_FIRST_RUN); + AddFirstRunNewTabs(browser_creator_.get(), master_prefs_->new_tabs); // If we are running in App mode, we do not want to show the importer diff --git a/chrome/browser/first_run/first_run.h b/chrome/browser/first_run/first_run.h index 34c3deb..1e57550 100644 --- a/chrome/browser/first_run/first_run.h +++ b/chrome/browser/first_run/first_run.h @@ -38,6 +38,12 @@ enum FirstRunBubbleMetric { NUM_FIRST_RUN_BUBBLE_METRICS }; +enum ProcessMasterPreferencesResult { + SHOW_FIRST_RUN = 0, // Should show the first run flow. + SKIP_FIRST_RUN, // Should skip the first run flow. + EULA_EXIT_NOW, // Should immediately exit due to EULA flow. +}; + // See ProcessMasterPreferences for more info about this structure. struct MasterPrefs { MasterPrefs(); @@ -107,17 +113,18 @@ FilePath MasterPrefsPath(); // '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|. +// function returns a value from the ProcessMasterPreferencesResult enum, +// indicating whether the first run flow should be shown, skipped, or whether +// the browser should exit. // // 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. -bool ProcessMasterPreferences(const FilePath& user_data_dir, - MasterPrefs* out_prefs); +ProcessMasterPreferencesResult ProcessMasterPreferences( + const FilePath& user_data_dir, + MasterPrefs* out_prefs); // Show the first run search engine bubble at the first appropriate opportunity. // This bubble may be delayed by other UI, like global errors and sync promos. diff --git a/chrome/browser/first_run/first_run_posix.cc b/chrome/browser/first_run/first_run_posix.cc index e5e0132..6724ec2 100644 --- a/chrome/browser/first_run/first_run_posix.cc +++ b/chrome/browser/first_run/first_run_posix.cc @@ -127,22 +127,23 @@ int ImportNow(Profile* profile, const CommandLine& cmdline) { return internal::ImportBookmarkFromFileIfNeeded(profile, cmdline); } -bool ProcessMasterPreferences(const FilePath& user_data_dir, - MasterPrefs* out_prefs) { +ProcessMasterPreferencesResult ProcessMasterPreferences( + const FilePath& user_data_dir, + MasterPrefs* out_prefs) { DCHECK(!user_data_dir.empty()); FilePath master_prefs_path; scoped_ptr<installer::MasterPreferences> install_prefs(internal::LoadMasterPrefs(&master_prefs_path)); if (!install_prefs.get()) - return true; + return SHOW_FIRST_RUN; out_prefs->new_tabs = install_prefs->GetFirstRunTabs(); internal::SetRLZPref(out_prefs, install_prefs.get()); if (!internal::CopyPrefFile(user_data_dir, master_prefs_path)) - return true; + return SHOW_FIRST_RUN; internal::SetupMasterPrefsFromInstallPrefs(out_prefs, install_prefs.get()); @@ -152,7 +153,7 @@ bool ProcessMasterPreferences(const FilePath& user_data_dir, // Note we are skipping all other master preferences if skip-first-run-ui // is *not* specified. (That is, we continue only if skipping first run ui.) if (!internal::SkipFirstRunUI(install_prefs.get())) - return true; + return SHOW_FIRST_RUN; // From here on we won't show first run so we need to do the work to show the // bubble anyway, unless it's already been explicitly suppressed. @@ -162,13 +163,13 @@ bool ProcessMasterPreferences(const FilePath& user_data_dir, // proceed because ImportSettings will launch the importer process which // would end up here if the sentinel is not present. if (!CreateSentinel()) - return false; + return SKIP_FIRST_RUN; internal::SetShowWelcomePagePrefIfNeeded(install_prefs.get()); internal::SetImportPreferencesAndLaunchImport(out_prefs, install_prefs.get()); internal::SetDefaultBrowser(install_prefs.get()); - return false; + return SKIP_FIRST_RUN; } diff --git a/chrome/browser/first_run/first_run_win.cc b/chrome/browser/first_run/first_run_win.cc index 077a1cf..fbd92bc 100644 --- a/chrome/browser/first_run/first_run_win.cc +++ b/chrome/browser/first_run/first_run_win.cc @@ -4,6 +4,7 @@ #include "chrome/browser/first_run/first_run.h" +#include <shellapi.h> #include <shlobj.h> #include <windows.h> @@ -15,6 +16,7 @@ #include "base/string_split.h" #include "base/stringprintf.h" #include "base/utf_string_conversions.h" +#include "base/win/metro.h" #include "base/win/object_watcher.h" #include "base/win/windows_version.h" #include "chrome/browser/browser_process.h" @@ -52,11 +54,10 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/layout.h" #include "ui/base/ui_base_switches.h" +#include "ui/base/win/shell.h" namespace { -const char kEULASentinelFile[] = "EULA Accepted"; - // Helper class that performs delayed first-run tasks that need more of the // chrome infrastructure to be up and running before they can be attempted. class FirstRunDelayedTasks : public content::NotificationObserver { @@ -144,53 +145,61 @@ void PlatformSetup(Profile* profile) { CreateChromeQuickLaunchShortcut(); } -// Launches the setup exe with the given parameter/value on the command-line, -// waits for its termination, returns its exit code in |*ret_code|, and -// returns true if the exit code is valid. -bool LaunchSetupWithParam(const std::string& param, - const FilePath::StringType& value, - int* ret_code) { - FilePath exe_path; - if (!PathService::Get(base::DIR_MODULE, &exe_path)) +// Launches the setup exe with the given parameter/value on the command-line. +// For non-metro Windows, it waits for its termination, returns its exit code +// in |*ret_code|, and returns true if the exit code is valid. +// For metro Windows, it launches setup via ShellExecuteEx and returns in order +// to bounce the user back to the desktop, then returns immediately. +bool LaunchSetupForEula(const FilePath::StringType& value, int* ret_code) { + FilePath exe_dir; + if (!PathService::Get(base::DIR_MODULE, &exe_dir)) return false; - exe_path = exe_path.Append(installer::kInstallerDir); - exe_path = exe_path.Append(installer::kSetupExe); + exe_dir = exe_dir.Append(installer::kInstallerDir); + FilePath exe_path = exe_dir.Append(installer::kSetupExe); base::ProcessHandle ph; - CommandLine cl(exe_path); - cl.AppendSwitchNative(param, value); + + CommandLine cl(CommandLine::NO_PROGRAM); + cl.AppendSwitchNative(installer::switches::kShowEula, value); CommandLine* browser_command_line = CommandLine::ForCurrentProcess(); if (browser_command_line->HasSwitch(switches::kChromeFrame)) { cl.AppendSwitch(switches::kChromeFrame); } - // TODO(evan): should this use options.wait = true? - if (!base::LaunchProcess(cl, base::LaunchOptions(), &ph)) - return false; - DWORD wr = ::WaitForSingleObject(ph, INFINITE); - if (wr != WAIT_OBJECT_0) - return false; - return (TRUE == ::GetExitCodeProcess(ph, reinterpret_cast<DWORD*>(ret_code))); -} - -// Populates |path| with the path to |file| in the sentinel directory. This is -// the application directory for user-level installs, and the default user data -// dir for system-level installs. Returns false on error. -bool GetSentinelFilePath(const char* file, FilePath* path) { - FilePath exe_path; - if (!PathService::Get(base::DIR_EXE, &exe_path)) - return false; - if (InstallUtil::IsPerUserInstall(exe_path.value().c_str())) - *path = exe_path; - else if (!PathService::Get(chrome::DIR_USER_DATA, path)) + if (base::win::IsMetroProcess()) { + cl.AppendSwitch(installer::switches::kShowEulaForMetro); + + // This obscure use of the 'log usage' mask for windows 8 is documented here + // http://go.microsoft.com/fwlink/?LinkID=243079. It causes the desktop + // process to receive focus. Pass SEE_MASK_FLAG_NO_UI to avoid hangs if an + // error occurs since the UI can't be shown from a metro process. + ui::win::OpenAnyViaShell(exe_path.value(), + exe_dir.value(), + cl.GetCommandLineString(), + SEE_MASK_FLAG_LOG_USAGE | SEE_MASK_FLAG_NO_UI); return false; + } else { + base::LaunchOptions launch_options; + launch_options.wait = true; + CommandLine setup_path(exe_path); + setup_path.AppendArguments(cl, false); + + DWORD exit_code = 0; + if (!base::LaunchProcess(setup_path, launch_options, &ph) || + !::GetExitCodeProcess(ph, &exit_code)) { + return false; + } - *path = path->AppendASCII(file); - return true; + *ret_code = exit_code; + return true; + } } bool GetEULASentinelFilePath(FilePath* path) { - return GetSentinelFilePath(kEULASentinelFile, path); + return InstallUtil::GetSentinelFilePath( + installer::kEULASentinelFile, + BrowserDistribution::GetDistribution(), + path); } // Returns true if the EULA is required but has not been accepted by this user. @@ -234,7 +243,10 @@ bool CreateEULASentinel() { return file_util::WriteFile(eula_sentinel, "", 0) != -1; } -void ShowPostInstallEULAIfNeeded(installer::MasterPreferences* install_prefs) { +// Shows the EULA dialog if required. Returns true if the EULA is accepted, +// returns false if the EULA has not been accepted, in which case the browser +// should exit. +bool ShowPostInstallEULAIfNeeded(installer::MasterPreferences* install_prefs) { if (IsEULANotAccepted(install_prefs)) { // Show the post-installation EULA. This is done by setup.exe and the // result determines if we continue or not. We wait here until the user @@ -245,14 +257,14 @@ void ShowPostInstallEULAIfNeeded(installer::MasterPreferences* install_prefs) { FilePath inner_html; if (WriteEULAtoTempFile(&inner_html)) { int retcode = 0; - if (!LaunchSetupWithParam(installer::switches::kShowEula, - inner_html.value(), &retcode) || + if (!LaunchSetupForEula(inner_html.value(), &retcode) || (retcode != installer::EULA_ACCEPTED && retcode != installer::EULA_ACCEPTED_OPT_IN)) { - LOG(WARNING) << "EULA rejected. Fast exit."; - ::ExitProcess(1); + LOG(WARNING) << "EULA flow requires fast exit."; + return false; } CreateEULASentinel(); + if (retcode == installer::EULA_ACCEPTED) { VLOG(1) << "EULA : no collection"; GoogleUpdateSettings::SetCollectStatsConsent(false); @@ -262,6 +274,7 @@ void ShowPostInstallEULAIfNeeded(installer::MasterPreferences* install_prefs) { } } } + return true; } // Installs a task to do an extensions update check once the extensions system @@ -498,7 +511,10 @@ bool ImportSettings(Profile* profile, } bool GetFirstRunSentinelFilePath(FilePath* path) { - return GetSentinelFilePath(kSentinelFile, path); + return InstallUtil::GetSentinelFilePath( + kSentinelFile, + BrowserDistribution::GetDistribution(), + path); } void SetImportPreferencesAndLaunchImport( @@ -590,23 +606,26 @@ FilePath MasterPrefsPath() { return master_prefs.AppendASCII(installer::kDefaultMasterPrefs); } -bool ProcessMasterPreferences(const FilePath& user_data_dir, - MasterPrefs* out_prefs) { +ProcessMasterPreferencesResult ProcessMasterPreferences( + const FilePath& user_data_dir, + MasterPrefs* out_prefs) { DCHECK(!user_data_dir.empty()); FilePath master_prefs_path; scoped_ptr<installer::MasterPreferences> install_prefs(internal::LoadMasterPrefs(&master_prefs_path)); if (!install_prefs.get()) - return true; + return SHOW_FIRST_RUN; out_prefs->new_tabs = install_prefs->GetFirstRunTabs(); internal::SetRLZPref(out_prefs, install_prefs.get()); - ShowPostInstallEULAIfNeeded(install_prefs.get()); + + if (!ShowPostInstallEULAIfNeeded(install_prefs.get())) + return EULA_EXIT_NOW; if (!internal::CopyPrefFile(user_data_dir, master_prefs_path)) - return true; + return SHOW_FIRST_RUN; DoDelayedInstallExtensionsIfNeeded(install_prefs.get()); @@ -618,19 +637,19 @@ bool ProcessMasterPreferences(const FilePath& user_data_dir, // Note we are skipping all other master preferences if skip-first-run-ui // is *not* specified. (That is, we continue only if skipping first run ui.) if (!internal::SkipFirstRunUI(install_prefs.get())) - return true; + return SHOW_FIRST_RUN; // We need to be able to create the first run sentinel or else we cannot // proceed because ImportSettings will launch the importer process which // would end up here if the sentinel is not present. if (!CreateSentinel()) - return false; + return SKIP_FIRST_RUN; internal::SetShowWelcomePagePrefIfNeeded(install_prefs.get()); internal::SetImportPreferencesAndLaunchImport(out_prefs, install_prefs.get()); internal::SetDefaultBrowser(install_prefs.get()); - return false; + return SKIP_FIRST_RUN; } } // namespace first_run diff --git a/chrome/browser/process_singleton_win.cc b/chrome/browser/process_singleton_win.cc index 54731ca..a8c3b26 100644 --- a/chrome/browser/process_singleton_win.cc +++ b/chrome/browser/process_singleton_win.cc @@ -23,6 +23,7 @@ #include "chrome/browser/ui/simple_message_box.h" #include "chrome/common/chrome_constants.h" #include "chrome/installer/util/browser_distribution.h" +#include "chrome/installer/util/install_util.h" #include "chrome/installer/util/shell_util.h" #include "chrome/installer/util/wmi.h" #include "content/public/common/result_codes.h" @@ -133,7 +134,8 @@ bool ActivateMetroChrome() { return false; } string16 app_id = ShellUtil::GetBrowserModelId( - BrowserDistribution::GetDistribution(), chrome_exe.value()); + BrowserDistribution::GetDistribution(), + InstallUtil::IsPerUserInstall(chrome_exe.value().c_str())); if (app_id.empty()) { NOTREACHED() << "Failed to get chrome app user model id."; return false; diff --git a/chrome/browser/shell_integration_win.cc b/chrome/browser/shell_integration_win.cc index 27b9212..34e8d3e 100644 --- a/chrome/browser/shell_integration_win.cc +++ b/chrome/browser/shell_integration_win.cc @@ -293,7 +293,8 @@ bool GetExpectedAppId(const FilePath& chrome_exe, command_line.GetSwitchValueASCII(switches::kAppId))); } else { BrowserDistribution* dist = BrowserDistribution::GetDistribution(); - app_name = ShellUtil::GetBrowserModelId(dist, chrome_exe.value()); + app_name = ShellUtil::GetBrowserModelId( + dist, InstallUtil::IsPerUserInstall(chrome_exe.value().c_str())); } expected_app_id->assign( @@ -558,7 +559,9 @@ string16 ShellIntegration::GetChromiumModelIdForProfile( return dist->GetBaseAppId(); } return GetAppModelIdForProfile( - ShellUtil::GetBrowserModelId(dist, chrome_exe.value()), profile_path); + ShellUtil::GetBrowserModelId( + dist, InstallUtil::IsPerUserInstall(chrome_exe.value().c_str())), + profile_path); } string16 ShellIntegration::GetChromiumIconPath() { |