summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-26 14:16:48 +0000
committerrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-26 14:16:48 +0000
commit7867996916cc0ca3d1d89d26c15bb7b39e994419 (patch)
tree89c2fb2fc2f5d41574d70d2fbf1ad93f7a858f1c
parentd83e5704eeb51d6e9fec081c00a618ad852abe35 (diff)
downloadchromium_src-7867996916cc0ca3d1d89d26c15bb7b39e994419.zip
chromium_src-7867996916cc0ca3d1d89d26c15bb7b39e994419.tar.gz
chromium_src-7867996916cc0ca3d1d89d26c15bb7b39e994419.tar.bz2
Enable EULA dialog to be shown from metro Chrome.
BUG=131033 TEST=Run Chrome in Metro mode while the EULA dialog still needs to be accepted. Get kicked back to the desktop to accept the dialog. On accept, get kicked back into metro mode. Review URL: https://chromiumcodereview.appspot.com/10837222 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@158797 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chrome_browser_main.cc10
-rw-r--r--chrome/browser/first_run/first_run.h17
-rw-r--r--chrome/browser/first_run/first_run_posix.cc15
-rw-r--r--chrome/browser/first_run/first_run_win.cc119
-rw-r--r--chrome/browser/process_singleton_win.cc4
-rw-r--r--chrome/browser/shell_integration_win.cc7
-rw-r--r--chrome/common/chrome_result_codes.h3
-rw-r--r--chrome/installer/setup/setup_main.cc45
-rw-r--r--chrome/installer/util/google_update_settings.cc22
-rw-r--r--chrome/installer/util/install_util.cc24
-rw-r--r--chrome/installer/util/install_util.h7
-rw-r--r--chrome/installer/util/shell_util.cc25
-rw-r--r--chrome/installer/util/shell_util.h2
-rw-r--r--chrome/installer/util/util_constants.cc4
-rw-r--r--chrome/installer/util/util_constants.h2
-rw-r--r--ui/base/win/shell.cc10
-rw-r--r--ui/base/win/shell.h1
17 files changed, 213 insertions, 104 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() {
diff --git a/chrome/common/chrome_result_codes.h b/chrome/common/chrome_result_codes.h
index b6f7a839..a29de59 100644
--- a/chrome/common/chrome_result_codes.h
+++ b/chrome/common/chrome_result_codes.h
@@ -82,6 +82,9 @@ enum ResultCode {
// A dummy value we should not use. See crbug.com/152285.
RESULT_CODE_NOTUSED_2,
+ // Returned when the user has not yet accepted the EULA.
+ RESULT_CODE_EULA_REFUSED,
+
// Last return code (keep this last).
RESULT_CODE_CHROME_LAST_CODE,
};
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 3c416d1..3371787 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -21,6 +21,7 @@
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "base/win/registry.h"
+#include "base/win/scoped_comptr.h"
#include "base/win/scoped_handle.h"
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
@@ -1031,6 +1032,40 @@ installer::InstallStatus ShowEULADialog(const string16& inner_frame) {
return installer::EULA_ACCEPTED;
}
+// Creates the sentinel indicating that the EULA was required and has been
+// accepted.
+bool CreateEULASentinel(BrowserDistribution* dist) {
+ FilePath eula_sentinel;
+ if (!InstallUtil::GetSentinelFilePath(installer::kEULASentinelFile,
+ dist, &eula_sentinel)) {
+ return false;
+ }
+ return file_util::WriteFile(eula_sentinel, "", 0) != -1;
+}
+
+void ActivateMetroChrome() {
+ // Check to see if we're per-user or not. Need to do this since we may
+ // not have been invoked with --system-level even for a machine install.
+ wchar_t exe_path[MAX_PATH * 2] = {};
+ GetModuleFileName(NULL, exe_path, arraysize(exe_path));
+ bool is_per_user_install = InstallUtil::IsPerUserInstall(exe_path);
+
+ string16 app_model_id =
+ ShellUtil::GetBrowserModelId(BrowserDistribution::GetDistribution(),
+ is_per_user_install);
+
+ base::win::ScopedComPtr<IApplicationActivationManager> activator;
+ HRESULT hr = activator.CreateInstance(CLSID_ApplicationActivationManager);
+ if (SUCCEEDED(hr)) {
+ DWORD pid = 0;
+ hr = activator->ActivateApplication(
+ app_model_id.c_str(), L"open", AO_NONE, &pid);
+ }
+
+ LOG_IF(ERROR, FAILED(hr)) << "Tried and failed to launch Metro Chrome. "
+ << "hr=" << std::hex << hr;
+}
+
// This method processes any command line options that make setup.exe do
// various tasks other than installation (renaming chrome.exe, showing eula
// among others). This function returns true if any such command line option
@@ -1090,9 +1125,15 @@ bool HandleNonInstallCmdLineOptions(const InstallationState& original_state,
string16 inner_frame =
cmd_line.GetSwitchValueNative(installer::switches::kShowEula);
*exit_code = ShowEULADialog(inner_frame);
+
if (installer::EULA_REJECTED != *exit_code) {
- GoogleUpdateSettings::SetEULAConsent(
- original_state, BrowserDistribution::GetDistribution(), true);
+ if (GoogleUpdateSettings::SetEULAConsent(
+ original_state, BrowserDistribution::GetDistribution(), true)) {
+ CreateEULASentinel(BrowserDistribution::GetDistribution());
+ }
+ // For a metro-originated launch, we now need to launch back into metro.
+ if (cmd_line.HasSwitch(installer::switches::kShowEulaForMetro))
+ ActivateMetroChrome();
}
} else if (cmd_line.HasSwitch(
installer::switches::kConfigureUserSettings)) {
diff --git a/chrome/installer/util/google_update_settings.cc b/chrome/installer/util/google_update_settings.cc
index 27e2cc7..1520577 100644
--- a/chrome/installer/util/google_update_settings.cc
+++ b/chrome/installer/util/google_update_settings.cc
@@ -38,14 +38,6 @@ const GoogleUpdateSettings::UpdatePolicy kGoogleUpdateDefaultUpdatePolicy =
GoogleUpdateSettings::UPDATES_DISABLED;
#endif
-// An list of search results in increasing order of desirability.
-enum EulaSearchResult {
- NO_SETTING,
- FOUND_CLIENT_STATE,
- FOUND_OPPOSITE_SETTING,
- FOUND_SAME_SETTING
-};
-
bool ReadGoogleUpdateStrKey(const wchar_t* const name, std::wstring* value) {
// The registry functions below will end up going to disk. Do this on another
// thread to avoid slowing the IO thread. http://crbug.com/62121
@@ -108,20 +100,6 @@ bool RemoveGoogleUpdateStrKey(const wchar_t* const name) {
return (key.DeleteValue(name) == ERROR_SUCCESS);
}
-EulaSearchResult HasEULASetting(HKEY root, const std::wstring& state_key,
- bool setting) {
- RegKey key;
- DWORD previous_value = setting ? 1 : 0;
- if (key.Open(root, state_key.c_str(), KEY_QUERY_VALUE) != ERROR_SUCCESS)
- return NO_SETTING;
- if (key.ReadValueDW(google_update::kRegEULAAceptedField,
- &previous_value) != ERROR_SUCCESS)
- return FOUND_CLIENT_STATE;
-
- return ((previous_value != 0) == setting) ?
- FOUND_SAME_SETTING : FOUND_OPPOSITE_SETTING;
-}
-
bool GetChromeChannelInternal(bool system_install,
bool add_multi_modifier,
string16* channel) {
diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc
index 6b327f8..0c1dd99 100644
--- a/chrome/installer/util/install_util.cc
+++ b/chrome/installer/util/install_util.cc
@@ -26,6 +26,7 @@
#include "base/win/windows_version.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/google_update_constants.h"
+#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/l10n_string_util.h"
#include "chrome/installer/util/installation_state.h"
#include "chrome/installer/util/util_constants.h"
@@ -358,6 +359,29 @@ bool InstallUtil::HasDelegateExecuteHandler(BrowserDistribution* dist,
return found;
}
+bool InstallUtil::GetSentinelFilePath(const char* file,
+ BrowserDistribution* dist,
+ FilePath* path) {
+ FilePath exe_path;
+ if (!PathService::Get(base::DIR_EXE, &exe_path))
+ return false;
+
+ if (IsPerUserInstall(exe_path.value().c_str())) {
+ *path = exe_path;
+ } else {
+ std::vector<FilePath> user_data_dir_paths;
+ installer::GetChromeUserDataPaths(dist, &user_data_dir_paths);
+
+ if (!user_data_dir_paths.empty())
+ *path = user_data_dir_paths[0];
+ else
+ return false;
+ }
+
+ *path = path->AppendASCII(file);
+ return true;
+}
+
// This method tries to delete a registry key and logs an error message
// in case of failure. It returns true if deletion is successful (or the key did
// not exist), otherwise false.
diff --git a/chrome/installer/util/install_util.h b/chrome/installer/util/install_util.h
index fe2db2b..e10025c 100644
--- a/chrome/installer/util/install_util.h
+++ b/chrome/installer/util/install_util.h
@@ -98,6 +98,13 @@ class InstallUtil {
static bool HasDelegateExecuteHandler(BrowserDistribution* dist,
const string16& chrome_exe);
+ // 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.
+ static bool GetSentinelFilePath(const char* file,
+ BrowserDistribution* dist,
+ FilePath* path);
+
// Deletes the registry key at path key_path under the key given by root_key.
static bool DeleteRegistryKey(HKEY root_key, const string16& key_path);
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index 73aeabe..113b479 100644
--- a/chrome/installer/util/shell_util.cc
+++ b/chrome/installer/util/shell_util.cc
@@ -216,7 +216,9 @@ class RegistryEntry {
string16 delegate_command(ShellUtil::GetChromeDelegateCommand(chrome_exe));
// For user-level installs: entries for the app id and DelegateExecute verb
// handler will be in HKCU; thus we do not need a suffix on those entries.
- string16 app_id(ShellUtil::GetBrowserModelId(dist, chrome_exe));
+ string16 app_id(
+ ShellUtil::GetBrowserModelId(
+ dist, InstallUtil::IsPerUserInstall(chrome_exe.c_str())));
string16 delegate_guid;
// TODO(grt): remove HasDelegateExecuteHandler when the exe is ever-present;
// see also install_worker.cc's AddDelegateExecuteWorkItems.
@@ -752,13 +754,16 @@ void RemoveBadWindows8RegistrationIfNeeded(
!IsChromeMetroSupported())) {
// There's no need to rollback, so forgo the usual work item lists and just
// remove the values from the registry.
- const HKEY root_key = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ?
- HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
+ bool is_per_user_install =
+ InstallUtil::IsPerUserInstall(chrome_exe.c_str());
+ const HKEY root_key = is_per_user_install ? HKEY_CURRENT_USER :
+ HKEY_LOCAL_MACHINE;
// Use the current installation's suffix, not the about-to-be-installed
// suffix.
const string16 installation_suffix(
ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe));
- const string16 app_id(ShellUtil::GetBrowserModelId(dist, chrome_exe));
+ const string16 app_id(ShellUtil::GetBrowserModelId(dist,
+ is_per_user_install));
// <root hkey>\Software\Classes\<app_id>
string16 key(ShellUtil::kRegClasses);
@@ -1206,11 +1211,10 @@ string16 ShellUtil::GetApplicationName(BrowserDistribution* dist,
}
string16 ShellUtil::GetBrowserModelId(BrowserDistribution* dist,
- const string16& chrome_exe) {
+ bool is_per_user_install) {
string16 app_id(dist->GetBaseAppId());
string16 suffix;
- if (InstallUtil::IsPerUserInstall(chrome_exe.c_str()) &&
- !GetUserSpecificRegistrySuffix(&suffix)) {
+ if (is_per_user_install && !GetUserSpecificRegistrySuffix(&suffix)) {
NOTREACHED();
}
// There is only one component (i.e. the suffixed appid) in this case, but it
@@ -1644,7 +1648,8 @@ void ShellUtil::RemoveChromeStartScreenShortcuts(BrowserDistribution* dist,
}
app_shortcuts_path = app_shortcuts_path.Append(
- GetBrowserModelId(dist, chrome_exe));
+ GetBrowserModelId(dist,
+ InstallUtil::IsPerUserInstall(chrome_exe.c_str())));
if (!file_util::DirectoryExists(app_shortcuts_path)) {
VLOG(1) << "No start screen shortcuts to delete.";
return;
@@ -1675,7 +1680,9 @@ bool ShellUtil::UpdateChromeShortcut(BrowserDistribution* dist,
&icon_index);
}
- const string16 app_id(GetBrowserModelId(dist, chrome_exe));
+ const string16 app_id(
+ GetBrowserModelId(dist,
+ InstallUtil::IsPerUserInstall(chrome_exe.c_str())));
const bool is_dual_mode = ((options & ShellUtil::SHORTCUT_DUAL_MODE) != 0);
const base::win::ShortcutOperation operation =
(options & ShellUtil::SHORTCUT_CREATE_ALWAYS) != 0 ?
diff --git a/chrome/installer/util/shell_util.h b/chrome/installer/util/shell_util.h
index b6afc95..538a42e 100644
--- a/chrome/installer/util/shell_util.h
+++ b/chrome/installer/util/shell_util.h
@@ -260,7 +260,7 @@ class ShellUtil {
// to other registration entries which are suffixed as described in
// GetCurrentInstallationSuffix() above).
static string16 GetBrowserModelId(BrowserDistribution* dist,
- const string16& chrome_exe);
+ bool is_per_user_install);
// Returns an AppUserModelId composed of each member of |components| separated
// by dots.
diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc
index d370fc3..b27f61c 100644
--- a/chrome/installer/util/util_constants.cc
+++ b/chrome/installer/util/util_constants.cc
@@ -155,6 +155,9 @@ const char kVerboseLogging[] = "verbose-logging";
// Show the embedded EULA dialog.
const char kShowEula[] = "show-eula";
+// Show the embedded EULA dialog, relaunch metro Chrome on acceptance.
+const char kShowEulaForMetro[] = "show-eula-for-metro";
+
// Use the alternate desktop shortcut name.
const char kAltDesktopShortcut[] = "alt-desktop-shortcut";
@@ -189,6 +192,7 @@ const wchar_t kCmdQuickEnableApplicationHost[] =
L"quick-enable-application-host";
const wchar_t kCmdQuickEnableCf[] = L"quick-enable-cf";
const wchar_t kDelegateExecuteExe[] = L"delegate_execute.exe";
+const char kEULASentinelFile[] = "EULA Accepted";
const wchar_t kGoogleChromeInstallSubDir1[] = L"Google";
const wchar_t kGoogleChromeInstallSubDir2[] = L"Chrome";
const wchar_t kInstallBinaryDir[] = L"Application";
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h
index 2ed6c4f..03dd059 100644
--- a/chrome/installer/util/util_constants.h
+++ b/chrome/installer/util/util_constants.h
@@ -162,6 +162,7 @@ extern const char kUninstall[];
extern const char kUpdateSetupExe[];
extern const char kVerboseLogging[];
extern const char kShowEula[];
+extern const char kShowEulaForMetro[];
extern const char kAltDesktopShortcut[];
extern const char kInactiveUserToast[];
extern const char kSystemLevelToast[];
@@ -184,6 +185,7 @@ extern const wchar_t kCmdOnOsUpgrade[];
extern const wchar_t kCmdQuickEnableApplicationHost[];
extern const wchar_t kCmdQuickEnableCf[];
extern const wchar_t kDelegateExecuteExe[];
+extern const char kEULASentinelFile[];
extern const wchar_t kGoogleChromeInstallSubDir1[];
extern const wchar_t kGoogleChromeInstallSubDir2[];
extern const wchar_t kInstallBinaryDir[];
diff --git a/ui/base/win/shell.cc b/ui/base/win/shell.cc
index f8e9d79..32ca484 100644
--- a/ui/base/win/shell.cc
+++ b/ui/base/win/shell.cc
@@ -58,12 +58,15 @@ bool OpenItemWithExternalApp(const string16& full_path) {
bool OpenAnyViaShell(const string16& full_path,
const string16& directory,
+ const string16& args,
DWORD mask) {
SHELLEXECUTEINFO sei = { sizeof(sei) };
sei.fMask = mask;
sei.nShow = SW_SHOWNORMAL;
sei.lpFile = full_path.c_str();
sei.lpDirectory = directory.c_str();
+ if (!args.empty())
+ sei.lpParameters = args.c_str();
if (::ShellExecuteExW(&sei))
return true;
@@ -73,12 +76,13 @@ bool OpenAnyViaShell(const string16& full_path,
}
bool OpenItemViaShell(const FilePath& full_path) {
- return OpenAnyViaShell(full_path.value(), full_path.DirName().value(), 0);
+ return OpenAnyViaShell(full_path.value(), full_path.DirName().value(),
+ string16(), 0);
}
bool OpenItemViaShellNoZoneCheck(const FilePath& full_path) {
- return OpenAnyViaShell(full_path.value(), string16(),
- SEE_MASK_NOZONECHECKS | SEE_MASK_FLAG_DDEWAIT);
+ return OpenAnyViaShell(full_path.value(), string16(), string16(),
+ SEE_MASK_NOZONECHECKS | SEE_MASK_FLAG_DDEWAIT);
}
void SetAppIdForWindow(const string16& app_id, HWND hwnd) {
diff --git a/ui/base/win/shell.h b/ui/base/win/shell.h
index dd3f75d..bf2e263 100644
--- a/ui/base/win/shell.h
+++ b/ui/base/win/shell.h
@@ -31,6 +31,7 @@ UI_EXPORT bool OpenItemViaShellNoZoneCheck(const FilePath& full_path);
// registered for the item, it behaves the same as OpenItemViaShell.
UI_EXPORT bool OpenAnyViaShell(const string16& full_path,
const string16& directory,
+ const string16& args,
DWORD mask);
// Ask the user, via the Windows "Open With" dialog, for an application to use