Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3619)

Unified Diff: chrome/installer/util/shell_util.cc

Issue 10453041: Support for interactive set-chrome-as-default in Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/installer/util/shell_util.cc
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index 7753fc646e646d9b718a05314eb5e0f3a4d5ea6a..73e70a36377581fd311930ef55ebfb67b6deb0be 100644
--- a/chrome/installer/util/shell_util.cc
+++ b/chrome/installer/util/shell_util.cc
@@ -77,7 +77,6 @@ class RegistryEntry {
// are needed to register Chromium ProgIds.
// These entries should be registered in HKCU for user-level installs and in
// HKLM for system-level installs.
- // TODO (gab): Extract the Windows 8 only registrations out of this function.
static bool GetProgIdEntries(BrowserDistribution* dist,
const string16& chrome_exe,
const string16& suffix,
@@ -149,7 +148,7 @@ class RegistryEntry {
}
// The following entries are required as of Windows 8, but do not
- // depend on the DelegateExecute.
+ // depend on the DelegateExecute verb handler being set.
if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
entries->push_front(new RegistryEntry(
chrome_html_prog_id, ShellUtil::kRegAppUserModelId, app_id));
@@ -490,6 +489,10 @@ bool ElevateAndRegisterChrome(BrowserDistribution* dist,
const string16& chrome_exe,
const string16& suffix,
const string16& protocol) {
+ // Only user-level installs prior to Windows 8 should need to elevate to
+ // register.
+ DCHECK(InstallUtil::IsPerUserInstall(chrome_exe.c_str()));
+ DCHECK_LT(base::win::GetVersion(), base::win::VERSION_WIN8);
FilePath exe_path =
FilePath::FromWStringHack(chrome_exe).DirName()
.Append(installer::kSetupExe);
@@ -589,12 +592,13 @@ bool AnotherUserHasDefaultBrowser(BrowserDistribution* dist,
// Launches the Windows 7 and Windows 8 application association dialog, which
// is the only documented way to make a browser the default browser on
// Windows 8.
-bool LaunchApplicationAssociationDialog(const string16& app_id) {
- base::win::ScopedComPtr<IApplicationAssociationRegistrationUI> aarui;
- HRESULT hr = aarui.CreateInstance(CLSID_ApplicationAssociationRegistrationUI);
- if (FAILED(hr))
- return false;
- hr = aarui->LaunchAdvancedAssociationUI(app_id.c_str());
+bool LaunchApplicationAssociationDialog() {
+ const wchar_t* protocol = L"http";
+ OPENASINFO open_as_info = {};
+ open_as_info.pcszFile = protocol;
+ open_as_info.oaifInFlags =
+ OAIF_URL_PROTOCOL | OAIF_FORCE_REGISTRATION | OAIF_REGISTER_EXT;
+ HRESULT hr = SHOpenWithDialog(NULL, &open_as_info);
return SUCCEEDED(hr);
}
@@ -647,6 +651,14 @@ void RemoveBadWindows8RegistrationIfNeeded(
}
}
+// Returns the root registry key (HKLM or HKCU) into which system registration
+// for default protocols must be placed. As of Windows 8 everything can go in
+// HKCU for per-user installs.
+HKEY DetermineRegistrationRoot(bool is_per_user) {
+ return is_per_user && base::win::GetVersion() >= base::win::VERSION_WIN8 ?
+ HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
+}
+
} // namespace
const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon";
@@ -912,9 +924,17 @@ bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist,
int shell_change,
const string16& chrome_exe,
bool elevate_if_not_admin) {
+ DCHECK(!(shell_change & ShellUtil::SYSTEM_LEVEL) || IsUserAnAdmin());
+
if (!dist->CanSetAsDefault())
return false;
+ // Windows 8 does not permit making a browser default just like that.
+ // This process needs to be routed through the system's UI. Use
+ // ShowMakeChromeDefaultSystemUI instead (below).
+ if (base::win::GetVersion() >= base::win::VERSION_WIN8)
+ return false;
+
ShellUtil::RegisterChromeBrowser(dist, chrome_exe, L"", elevate_if_not_admin);
bool ret = true;
@@ -933,9 +953,12 @@ bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist,
// control panel. This action does not require elevation and we
// don't get to control window activation. More info at:
// http://msdn.microsoft.com/en-us/library/cc144154(VS.85).aspx
- return LaunchApplicationAssociationDialog(app_name.c_str());
+ // Since this will show a modal UI elementm this has been split into
+ // a separate flow (see ShowMakeChromeDefaultSystemUI).
+ return false;
+ }
- } else if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
+ if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
// On Windows Vista and Win7 we still can set ourselves via the
// the IApplicationAssociationRegistration interface.
VLOG(1) << "Registering Chrome as default browser on Vista.";
@@ -997,6 +1020,24 @@ bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist,
return ret;
}
+bool ShellUtil::ShowMakeChromeDefaultSystemUI(
+ BrowserDistribution* dist, int shell_change, const string16& chrome_exe,
+ bool elevate_if_not_admin) {
+ if (!dist->CanSetAsDefault())
+ return false;
+
+ ShellUtil::RegisterChromeBrowser(dist, chrome_exe, L"", elevate_if_not_admin);
+
+ // On Windows 8, you can't set yourself as the default handler
+ // programatically. In other words IApplicationAssociationRegistration
+ // has been rendered useless. What you can do is to launch
+ // "Set Program Associations" section of the "Default Programs"
+ // control panel. This action does not require elevation and we
+ // don't get to control window activation. More info at:
+ // http://msdn.microsoft.com/en-us/library/cc144154(VS.85).aspx
+ return LaunchApplicationAssociationDialog();
+}
+
bool ShellUtil::MakeChromeDefaultProtocolClient(BrowserDistribution* dist,
const string16& chrome_exe,
const string16& protocol) {
@@ -1077,29 +1118,34 @@ bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist,
if (IsChromeRegistered(dist, chrome_exe, suffix))
return true;
- // If user is an admin try to register and return the status.
- if (IsUserAnAdmin()) {
+ bool user_level = InstallUtil::IsPerUserInstall(chrome_exe.c_str());
+ HKEY root = DetermineRegistrationRoot(user_level);
+
+ // Do the full registration if we can do it at user-level or if the user is an
+ // admin.
+ if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) {
std::list<RegistryEntry*> progids;
STLElementDeleter<std::list<RegistryEntry*> > progids_deleter(&progids);
std::list<RegistryEntry*> sys_entries;
STLElementDeleter<std::list<RegistryEntry*> > sys_deleter(&sys_entries);
RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &progids);
RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &sys_entries);
- return AddRegistryEntries(
- InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ?
- HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
- progids) &&
- AddRegistryEntries(HKEY_LOCAL_MACHINE, sys_entries);
+ return AddRegistryEntries(user_level ? HKEY_CURRENT_USER :
+ HKEY_LOCAL_MACHINE,
+ progids) &&
+ AddRegistryEntries(root, sys_entries);
}
- // If user is not an admin and OS is Vista, try to elevate and register.
+ // If the user is not an admin and OS is between Vista and Windows 7
+ // inclusively, try to elevate and register. This is only intended for
+ // user-level installs as system-level installs should always be run with
+ // admin rights.
if (elevate_if_not_admin &&
base::win::GetVersion() >= base::win::VERSION_VISTA &&
ElevateAndRegisterChrome(dist, chrome_exe, suffix, L""))
return true;
- // If we got to this point then all we can do is create ProgIds under HKCU
- // on XP as well as Vista.
+ // If we got to this point then all we can do is create ProgIds under HKCU.
std::list<RegistryEntry*> entries;
STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries);
RegistryEntry::GetProgIdEntries(dist, chrome_exe, L"", &entries);
@@ -1129,7 +1175,10 @@ bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist,
if (IsChromeRegisteredForProtocol(dist, suffix, protocol))
return true;
- if (IsUserAnAdmin()) {
+ HKEY root = DetermineRegistrationRoot(
+ InstallUtil::IsPerUserInstall(chrome_exe.c_str()));
+
+ if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) {
// We can do this operation directly.
// If we're not registered at all, try to register. If that fails
// we should give up.
@@ -1143,14 +1192,13 @@ bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist,
STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries);
RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol,
&entries);
- return AddRegistryEntries(HKEY_LOCAL_MACHINE, entries);
+ return AddRegistryEntries(root, entries);
} else if (elevate_if_not_admin &&
base::win::GetVersion() >= base::win::VERSION_VISTA) {
// Elevate to do the whole job
return ElevateAndRegisterChrome(dist, chrome_exe, suffix, protocol);
} else {
- // we need admin rights to register our capability. If we don't
- // have them and can't elevate, give up.
+ // Admin rights are required to register capabilities before Windows 8.
return false;
}
}

Powered by Google App Engine
This is Rietveld 408576698