Index: chrome/browser/first_run/first_run_win.cc |
diff --git a/chrome/browser/first_run/first_run_win.cc b/chrome/browser/first_run/first_run_win.cc |
index 077a1cfaacd0cc76cb4d4208bcfd41fc8c744d10..7e86c32c85252e9b728325310ca9cd789ab7e299 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,33 +145,50 @@ 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) |
+ if (base::win::IsMetroProcess()) { |
+ cl.AppendSwitch(installer::switches::kShowEulaForMetro); |
+ |
+ // This obscure use of the 'log usage' mask for windows 8 is documented |
+ // here http://goo.gl/HBOe9. It causes the desktop process to receive |
grt (UTC plus 2)
2012/09/20 15:58:31
please link to the current version of the MS doc r
robertshield
2012/09/21 01:24:43
Done.
|
+ // 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; |
- return (TRUE == ::GetExitCodeProcess(ph, reinterpret_cast<DWORD*>(ret_code))); |
+ } else { |
+ base::LaunchOptions launch_options; |
+ launch_options.wait = true; |
+ CommandLine setup_path(exe_path); |
+ setup_path.AppendArguments(cl, false); |
+ |
+ if (!base::LaunchProcess(setup_path, launch_options, &ph)) |
+ return false; |
+ return ( |
+ TRUE == ::GetExitCodeProcess(ph, reinterpret_cast<DWORD*>(ret_code))); |
grt (UTC plus 2)
2012/09/20 15:58:31
1. please COMPILE_ASSERT(sizeof(*ret_code) == size
robertshield
2012/09/21 01:24:43
Done.
|
+ } |
} |
// Populates |path| with the path to |file| in the sentinel directory. This is |
@@ -190,7 +208,7 @@ bool GetSentinelFilePath(const char* file, FilePath* path) { |
} |
bool GetEULASentinelFilePath(FilePath* path) { |
- return GetSentinelFilePath(kEULASentinelFile, path); |
+ return GetSentinelFilePath(installer::kEULASentinelFile, path); |
} |
// Returns true if the EULA is required but has not been accepted by this user. |
@@ -234,7 +252,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 +266,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 +283,7 @@ void ShowPostInstallEULAIfNeeded(installer::MasterPreferences* install_prefs) { |
} |
} |
} |
+ return true; |
} |
// Installs a task to do an extensions update check once the extensions system |
@@ -590,23 +612,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 +643,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 |