summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkuchhal@chromium.org <kuchhal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-23 19:51:18 +0000
committerkuchhal@chromium.org <kuchhal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-23 19:51:18 +0000
commit3bf6ade0846bb7a03e586a96feda2d9bbd466139 (patch)
tree32c95ee82f497f8aa7a84b986efe65e4a513bb77
parentf32aa33411516549857f4f18ec9b53f599952e38 (diff)
downloadchromium_src-3bf6ade0846bb7a03e586a96feda2d9bbd466139.zip
chromium_src-3bf6ade0846bb7a03e586a96feda2d9bbd466139.tar.gz
chromium_src-3bf6ade0846bb7a03e586a96feda2d9bbd466139.tar.bz2
Allow two user level installs of Chrome to have default browser settings.
This change will allow two Windows users to install thier own copy of Chrome and set it as default browser. There is a bunch of refactoring in this change. - Divided the registry entries into three categories: * Entries that are only read from HKLM * Entries that actually tie file/protocol associations to Chrome. This will almost always be in HKCU (except when it is a OEM install). * Entries that we can create in HKCU if we fail to create them in HKLM. - For single user machine nothing should change. - For two users on the same machine (each with a different user level Chrome installed), the second user's default browser will get renamed to Chromium.<user> and the required registry entries will also be renamed so that they do not overwrite first users's registry entries. BUG=3641 TEST=Install and set Chromium as default browser from two different logins on the same machine for various combinations of XP/Vista, admin users/non admin user, user-level install/system-level install. Review URL: http://codereview.chromium.org/159172 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21428 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/shell_integration.cc28
-rw-r--r--chrome/installer/setup/install.cc21
-rw-r--r--chrome/installer/setup/setup_main.cc21
-rw-r--r--chrome/installer/setup/uninstall.cc32
-rw-r--r--chrome/installer/setup/uninstall.h10
-rw-r--r--chrome/installer/util/shell_util.cc713
-rw-r--r--chrome/installer/util/shell_util.h89
-rw-r--r--chrome/installer/util/util_constants.cc3
-rw-r--r--chrome/installer/util/util_constants.h7
9 files changed, 522 insertions, 402 deletions
diff --git a/chrome/browser/shell_integration.cc b/chrome/browser/shell_integration.cc
index ebcadbd..6f1957a 100644
--- a/chrome/browser/shell_integration.cc
+++ b/chrome/browser/shell_integration.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2009 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.
@@ -33,15 +33,9 @@ bool ShellIntegration::SetAsDefaultBrowser() {
return false;
}
- ShellUtil::RegisterStatus register_status =
- ShellUtil::AddChromeToSetAccessDefaults(chrome_exe, false);
- if (register_status == ShellUtil::FAILURE) {
- LOG(ERROR) << "Chrome could not be registered on the machine.";
- return false;
- }
-
// From UI currently we only allow setting default browser for current user.
- if (!ShellUtil::MakeChromeDefault(ShellUtil::CURRENT_USER, chrome_exe)) {
+ if (!ShellUtil::MakeChromeDefault(ShellUtil::CURRENT_USER,
+ chrome_exe, true)) {
LOG(ERROR) << "Chrome could not be set as default browser.";
return false;
}
@@ -77,14 +71,22 @@ bool ShellIntegration::IsDefaultBrowser() {
if (!SUCCEEDED(hr))
return false;
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ std::wstring app_name = dist->GetApplicationName();
+ std::wstring app_name_with_suffix;
+ ShellUtil::GetUserSpecificDefaultBrowserSuffix(&app_name_with_suffix);
+ app_name_with_suffix = app_name + app_name_with_suffix;
for (int i = 0; i < _countof(kChromeProtocols); i++) {
BOOL result = TRUE;
- BrowserDistribution* dist = BrowserDistribution::GetDistribution();
hr = pAAR->QueryAppIsDefault(kChromeProtocols[i].c_str(), AT_URLPROTOCOL,
- AL_EFFECTIVE, dist->GetApplicationName().c_str(), &result);
+ AL_EFFECTIVE, app_name_with_suffix.c_str(), &result);
if (!SUCCEEDED(hr) || (result == FALSE)) {
- pAAR->Release();
- return false;
+ hr = pAAR->QueryAppIsDefault(kChromeProtocols[i].c_str(),
+ AT_URLPROTOCOL, AL_EFFECTIVE, app_name.c_str(), &result);
+ if (!SUCCEEDED(hr) || (result == FALSE)) {
+ pAAR->Release();
+ return false;
+ }
}
}
pAAR->Release();
diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc
index c409317..2a3bc3a 100644
--- a/chrome/installer/setup/install.cc
+++ b/chrome/installer/setup/install.cc
@@ -286,26 +286,19 @@ void RegisterChromeOnMachine(const std::wstring& install_path, int options) {
// have admin rights and we want to ignore the error.
AddChromeToMediaPlayerList();
- // We try to register Chrome as a valid browser on local machine. This
- // will work only if current user has admin rights.
+ // Is --make-chrome-default option is given we make Chrome default browser
+ // otherwise we only register it on the machine as a valid browser.
std::wstring chrome_exe(install_path);
file_util::AppendToPath(&chrome_exe, installer_util::kChromeExe);
LOG(INFO) << "Registering Chrome as browser";
- ShellUtil::RegisterStatus ret = ShellUtil::FAILURE;
if (options & installer_util::MAKE_CHROME_DEFAULT) {
- ret = ShellUtil::AddChromeToSetAccessDefaults(chrome_exe, false);
- if (ret == ShellUtil::SUCCESS) {
- if (system_level) {
- ShellUtil::MakeChromeDefault(
- ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, chrome_exe);
- } else {
- ShellUtil::MakeChromeDefault(ShellUtil::CURRENT_USER, chrome_exe);
- }
- }
+ int level = ShellUtil::CURRENT_USER;
+ if (system_level)
+ level = level | ShellUtil::SYSTEM_LEVEL;
+ ShellUtil::MakeChromeDefault(level, chrome_exe, true);
} else {
- ret = ShellUtil::AddChromeToSetAccessDefaults(chrome_exe, true);
+ ShellUtil::RegisterChromeBrowser(chrome_exe, L"", false);
}
- LOG(INFO) << "Return status of Chrome browser registration " << ret;
}
} // namespace
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 159f065..d73e4db 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -573,7 +573,13 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
// make any user specific changes in this option.
std::wstring chrome_exe(cmd_line.GetSwitchValue(
installer_util::switches::kRegisterChromeBrowser));
- exit_code = ShellUtil::AddChromeToSetAccessDefaults(chrome_exe, true);
+ std::wstring suffix;
+ if (cmd_line.HasSwitch(
+ installer_util::switches::kRegisterChromeBrowserSuffix)) {
+ suffix = cmd_line.GetSwitchValue(
+ installer_util::switches::kRegisterChromeBrowserSuffix);
+ }
+ exit_code = ShellUtil::RegisterChromeBrowser(chrome_exe, suffix, false);
return true;
} else if (cmd_line.HasSwitch(installer_util::switches::kRenameChromeExe)) {
// If --rename-chrome-exe is specified, we want to rename the executables
@@ -582,8 +588,19 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
return true;
} else if (cmd_line.HasSwitch(
installer_util::switches::kRemoveChromeRegistration)) {
+ // This is almost reverse of --register-chrome-browser option above.
+ // Here we delete Chrome browser registration. This option should only
+ // be used when setup.exe is launched with admin rights. We do not
+ // make any user specific changes in this option.
+ std::wstring suffix;
+ if (cmd_line.HasSwitch(
+ installer_util::switches::kRegisterChromeBrowserSuffix)) {
+ suffix = cmd_line.GetSwitchValue(
+ installer_util::switches::kRegisterChromeBrowserSuffix);
+ }
installer_util::InstallStatus tmp = installer_util::UNKNOWN_STATUS;
- installer_setup::DeleteChromeRegistrationKeys(HKEY_LOCAL_MACHINE, tmp);
+ installer_setup::DeleteChromeRegistrationKeys(HKEY_LOCAL_MACHINE,
+ suffix, tmp);
exit_code = tmp;
return true;
} else if (cmd_line.HasSwitch(installer_util::switches::kInactiveUserToast)) {
diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc
index a67e01b..7152f04 100644
--- a/chrome/installer/setup/uninstall.cc
+++ b/chrome/installer/setup/uninstall.cc
@@ -243,6 +243,7 @@ installer_util::InstallStatus IsChromeActiveOrUserCancelled(
bool installer_setup::DeleteChromeRegistrationKeys(HKEY root,
+ const std::wstring& browser_entry_suffix,
installer_util::InstallStatus& exit_code) {
RegKey key(root, L"", KEY_ALL_ACCESS);
@@ -262,11 +263,12 @@ bool installer_setup::DeleteChromeRegistrationKeys(HKEY root,
ext_association.append(chrome::kExtensionFileExtension);
DeleteRegistryKey(key, ext_association);
- // Delete Software\Clients\StartMenuInternet\chrome.exe
+ // Delete Software\Clients\StartMenuInternet\Chromium
BrowserDistribution* dist = BrowserDistribution::GetDistribution();
std::wstring set_access_key(ShellUtil::kRegStartMenuInternet);
file_util::AppendToPath(&set_access_key, dist->GetApplicationName());
DeleteRegistryKey(key, set_access_key);
+
// We have renamed the StartMenuInternet\chrome.exe to
// StartMenuInternet\Chromium so for old users we still need to delete
// the old key.
@@ -274,10 +276,25 @@ bool installer_setup::DeleteChromeRegistrationKeys(HKEY root,
file_util::AppendToPath(&old_set_access_key, installer_util::kChromeExe);
DeleteRegistryKey(key, old_set_access_key);
- // Delete Software\RegisteredApplications\Chrome
+ // Delete Software\RegisteredApplications\Chromium
DeleteRegistryValue(root, ShellUtil::kRegRegisteredApplications,
dist->GetApplicationName());
+ // Delete Software\Classes\ChromeHTML.<user>
+ // Delete Software\Classes\ChromeExt.<user>
+ // Delete Software\Clients\StartMenuInternet\Chromium.<user>
+ // Delete Software\RegisteredApplications\Chromium.<user>
+ if (!browser_entry_suffix.empty()) {
+ html_prog_id.append(browser_entry_suffix);
+ DeleteRegistryKey(key, html_prog_id);
+ ext_prog_id.append(browser_entry_suffix);
+ DeleteRegistryKey(key, ext_prog_id);
+ set_access_key.append(browser_entry_suffix);
+ DeleteRegistryKey(key, set_access_key);
+ DeleteRegistryValue(root, ShellUtil::kRegRegisteredApplications,
+ dist->GetApplicationName() + browser_entry_suffix);
+ }
+
// Delete Software\Classes\Applications\chrome.exe
std::wstring app_key(ShellUtil::kRegClasses);
file_util::AppendToPath(&app_key, L"Applications");
@@ -307,6 +324,8 @@ installer_util::InstallStatus installer_setup::UninstallChrome(
const std::wstring& exe_path, bool system_uninstall,
bool remove_all, bool force_uninstall,
const CommandLine& cmd_line, const wchar_t* cmd_params) {
+ std::wstring suffix;
+ ShellUtil::GetUserSpecificDefaultBrowserSuffix(&suffix);
installer_util::InstallStatus status = installer_util::UNINSTALL_CONFIRMED;
if (force_uninstall) {
// Since --force-uninstall command line option is used, we are going to
@@ -335,6 +354,11 @@ installer_util::InstallStatus installer_setup::UninstallChrome(
// Append --remove-chrome-registration to remove registry keys only.
params.append(L" --");
params.append(installer_util::switches::kRemoveChromeRegistration);
+ if (!suffix.empty()) {
+ params.append(L" --");
+ params.append(installer_util::switches::kRegisterChromeBrowserSuffix);
+ params.append(L"=\"" + suffix + L"\"");
+ }
DWORD exit_code = installer_util::UNKNOWN_STATUS;
InstallUtil::ExecuteExeAsAdmin(exe, params, &exit_code);
}
@@ -366,12 +390,12 @@ installer_util::InstallStatus installer_setup::UninstallChrome(
// Remove all Chrome registration keys.
installer_util::InstallStatus ret = installer_util::UNKNOWN_STATUS;
- DeleteChromeRegistrationKeys(reg_root, ret);
+ DeleteChromeRegistrationKeys(reg_root, suffix, ret);
// For user level install also we end up creating some keys in HKLM if user
// sets Chrome as default browser. So delete those as well (needs admin).
if (remove_all && !system_uninstall)
- DeleteChromeRegistrationKeys(HKEY_LOCAL_MACHINE, ret);
+ DeleteChromeRegistrationKeys(HKEY_LOCAL_MACHINE, suffix, ret);
// Delete shared registry keys as well (these require admin rights) if
// remove_all option is specified.
diff --git a/chrome/installer/setup/uninstall.h b/chrome/installer/setup/uninstall.h
index 2f44f80..1047f90 100644
--- a/chrome/installer/setup/uninstall.h
+++ b/chrome/installer/setup/uninstall.h
@@ -4,8 +4,8 @@
//
// This file declares Chrome uninstall related functions.
-#ifndef CHROME_INSTALLER_SETUP_UNINSTALL_H__
-#define CHROME_INSTALLER_SETUP_UNINSTALL_H__
+#ifndef CHROME_INSTALLER_SETUP_UNINSTALL_H_
+#define CHROME_INSTALLER_SETUP_UNINSTALL_H_
#include <string>
@@ -18,8 +18,10 @@
namespace installer_setup {
// This function removes all Chrome registration related keys. It returns true
// if successful, otherwise false. The error code is set in |exit_code|.
-// |root| is the registry root (HKLM|HKCU)
+// |root| is the registry root (HKLM|HKCU) and |browser_entry_suffix| is the
+// suffix for default browser entry name in the registry (optional).
bool DeleteChromeRegistrationKeys(HKEY root,
+ const std::wstring& browser_entry_suffix,
installer_util::InstallStatus& exit_code);
// This function uninstalls Chrome.
@@ -42,4 +44,4 @@ installer_util::InstallStatus UninstallChrome(
} // namespace installer_setup
-#endif // CHROME_INSTALLER_SETUP_UNINSTALL_H__
+#endif // CHROME_INSTALLER_SETUP_UNINSTALL_H_
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index 2a7619a..1261316 100644
--- a/chrome/installer/util/shell_util.cc
+++ b/chrome/installer/util/shell_util.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2009 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.
//
@@ -7,30 +7,24 @@
// work is done by the local functions defined in anonymous namespace in
// this class.
+#include "chrome/installer/util/shell_util.h"
+
#include <windows.h>
-#include <shellapi.h>
#include <shlobj.h>
-#include "chrome/installer/util/shell_util.h"
-
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
-#include "base/path_service.h"
#include "base/registry.h"
#include "base/scoped_ptr.h"
+#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "base/win_util.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/installer/util/browser_distribution.h"
-#include "chrome/installer/util/create_reg_key_work_item.h"
#include "chrome/installer/util/install_util.h"
-#include "chrome/installer/util/l10n_string_util.h"
-#include "chrome/installer/util/set_reg_value_work_item.h"
-#include "chrome/installer/util/util_constants.h"
-#include "chrome/installer/util/work_item.h"
#include "installer_util_strings.h"
@@ -43,101 +37,169 @@ namespace {
// class.
class RegistryEntry {
public:
- // This method returns a list of all the registry entries that are needed
- // to register Chrome.
- static std::list<RegistryEntry*> GetAllEntries(
- const std::wstring& chrome_exe) {
- std::list<RegistryEntry*> entries;
- std::wstring icon_path(chrome_exe);
- ShellUtil::GetChromeIcon(icon_path);
- std::wstring quoted_exe_path = L"\"" + chrome_exe + L"\"";
+ // This method returns a list of all the registry entries that
+ // are needed to register Chromium ProgIds.
+ static bool GetProgIdEntries(const std::wstring& chrome_exe,
+ const std::wstring& suffix,
+ std::list<RegistryEntry*>* entries) {
+ std::wstring icon_path = ShellUtil::GetChromeIcon(chrome_exe);
std::wstring open_cmd = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
+ // File association ProgId
std::wstring chrome_html_prog_id(ShellUtil::kRegClasses);
file_util::AppendToPath(&chrome_html_prog_id, ShellUtil::kChromeHTMLProgId);
- entries.push_front(new RegistryEntry(chrome_html_prog_id,
- ShellUtil::kChromeHTMLProgIdDesc));
- entries.push_front(new RegistryEntry(chrome_html_prog_id,
- ShellUtil::kRegUrlProtocol, L""));
- entries.push_front(new RegistryEntry(
+ chrome_html_prog_id.append(suffix);
+ entries->push_front(new RegistryEntry(
+ chrome_html_prog_id, ShellUtil::kChromeHTMLProgIdDesc));
+ entries->push_front(new RegistryEntry(
+ chrome_html_prog_id, ShellUtil::kRegUrlProtocol, L""));
+ entries->push_front(new RegistryEntry(
chrome_html_prog_id + ShellUtil::kRegDefaultIcon, icon_path));
- entries.push_front(new RegistryEntry(
+ entries->push_front(new RegistryEntry(
chrome_html_prog_id + ShellUtil::kRegShellOpen, open_cmd));
- std::wstring exe_name = file_util::GetFilenameFromPath(chrome_exe);
- std::wstring app_key = L"Software\\Classes\\Applications\\" + exe_name +
- L"\\shell\\open\\command";
- entries.push_front(new RegistryEntry(app_key, open_cmd));
- for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
- std::wstring open_with_key(L"Software\\Classes\\");
- open_with_key.append(ShellUtil::kFileAssociations[i]);
- open_with_key.append(L"\\OpenWithList\\" + exe_name);
- entries.push_front(new RegistryEntry(open_with_key, std::wstring()));
- }
-
- // Chrome Extension file handler
+ // Chrome Extension ProgId
+ std::wstring ext_prog_id(ShellUtil::kRegClasses);
+ file_util::AppendToPath(&ext_prog_id, ShellUtil::kChromeExtProgId);
+ ext_prog_id.append(suffix);
+ entries->push_front(new RegistryEntry(
+ ext_prog_id, ShellUtil::kChromeExtProgIdDesc));
+ entries->push_front(new RegistryEntry(
+ ext_prog_id + ShellUtil::kRegDefaultIcon, icon_path));
std::wstring install_cmd =
ShellUtil::GetChromeInstallExtensionCmd(chrome_exe);
- std::wstring prog_id = std::wstring(L"Software\\Classes\\") +
- ShellUtil::kChromeExtProgId;
- entries.push_front(new RegistryEntry(prog_id,
- ShellUtil::kChromeExtProgIdDesc));
- entries.push_front(new RegistryEntry(
- prog_id + ShellUtil::kRegDefaultIcon, icon_path));
- entries.push_front(new RegistryEntry(
- prog_id + ShellUtil::kRegShellOpen, install_cmd));
+ entries->push_front(new RegistryEntry(
+ ext_prog_id + ShellUtil::kRegShellOpen, install_cmd));
+
+ return true;
+ }
+
+ // This method returns a list of all the system level registry entries that
+ // are needed to register Chromium on the machine.
+ static bool GetSystemEntries(const std::wstring& chrome_exe,
+ const std::wstring& suffix,
+ std::list<RegistryEntry*>* entries) {
+ std::wstring icon_path = ShellUtil::GetChromeIcon(chrome_exe);
+ std::wstring quoted_exe_path = L"\"" + chrome_exe + L"\"";
BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ std::wstring app_name = dist->GetApplicationName() + suffix;
std::wstring start_menu_entry(ShellUtil::kRegStartMenuInternet);
- start_menu_entry.append(L"\\" + dist->GetApplicationName());
- entries.push_front(new RegistryEntry(start_menu_entry,
- dist->GetApplicationName()));
- entries.push_front(new RegistryEntry(
+ start_menu_entry.append(L"\\" + app_name);
+ entries->push_front(new RegistryEntry(start_menu_entry, app_name));
+ entries->push_front(new RegistryEntry(
start_menu_entry + ShellUtil::kRegShellOpen, quoted_exe_path));
- entries.push_front(new RegistryEntry(
+ entries->push_front(new RegistryEntry(
start_menu_entry + ShellUtil::kRegDefaultIcon, icon_path));
std::wstring install_info(start_menu_entry + L"\\InstallInfo");
- entries.push_front(new RegistryEntry(install_info, L"ReinstallCommand",
+ entries->push_front(new RegistryEntry(install_info, L"ReinstallCommand",
quoted_exe_path + L" --" + switches::kMakeDefaultBrowser));
- entries.push_front(new RegistryEntry(install_info, L"HideIconsCommand",
+ entries->push_front(new RegistryEntry(install_info, L"HideIconsCommand",
quoted_exe_path + L" --" + switches::kHideIcons));
- entries.push_front(new RegistryEntry(install_info, L"ShowIconsCommand",
+ entries->push_front(new RegistryEntry(install_info, L"ShowIconsCommand",
quoted_exe_path + L" --" + switches::kShowIcons));
- entries.push_front(new RegistryEntry(install_info, L"IconsVisible", 1));
+ entries->push_front(new RegistryEntry(install_info, L"IconsVisible", 1));
std::wstring capabilities(start_menu_entry + L"\\Capabilities");
- entries.push_front(new RegistryEntry(ShellUtil::kRegRegisteredApplications,
- dist->GetApplicationName(),
- capabilities));
- entries.push_front(new RegistryEntry(
+ entries->push_front(new RegistryEntry(ShellUtil::kRegRegisteredApplications,
+ app_name, capabilities));
+ entries->push_front(new RegistryEntry(
capabilities, L"ApplicationDescription", dist->GetApplicationName()));
- entries.push_front(new RegistryEntry(
+ entries->push_front(new RegistryEntry(
capabilities, L"ApplicationIcon", icon_path));
- entries.push_front(new RegistryEntry(
- capabilities, L"ApplicationName", dist->GetApplicationName()));
+ entries->push_front(new RegistryEntry(
+ capabilities, L"ApplicationName", app_name));
+
+ entries->push_front(new RegistryEntry(capabilities + L"\\StartMenu",
+ L"StartMenuInternet", app_name));
- entries.push_front(new RegistryEntry(capabilities + L"\\StartMenu",
- L"StartMenuInternet", dist->GetApplicationName()));
+ std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId);
+ html_prog_id.append(suffix);
for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
- entries.push_front(new RegistryEntry(
+ entries->push_front(new RegistryEntry(
capabilities + L"\\FileAssociations",
- ShellUtil::kFileAssociations[i], ShellUtil::kChromeHTMLProgId));
+ ShellUtil::kFileAssociations[i], html_prog_id));
}
- entries.push_front(new RegistryEntry(
- capabilities + L"\\FileAssociations",
- chrome::kExtensionFileExtension, ShellUtil::kChromeExtProgId));
for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) {
- entries.push_front(new RegistryEntry(
+ entries->push_front(new RegistryEntry(
capabilities + L"\\URLAssociations",
- ShellUtil::kProtocolAssociations[i], ShellUtil::kChromeHTMLProgId));
+ ShellUtil::kProtocolAssociations[i], html_prog_id));
}
- return entries;
+ std::wstring ext_prog_id(ShellUtil::kChromeExtProgId);
+ ext_prog_id.append(suffix);
+ entries->push_front(new RegistryEntry(
+ capabilities + L"\\FileAssociations",
+ chrome::kExtensionFileExtension, ext_prog_id));
+
+ FilePath chrome_path(chrome_exe);
+ std::wstring app_path_key(ShellUtil::kAppPathsRegistryKey);
+ file_util::AppendToPath(&app_path_key, chrome_path.BaseName().value());
+ entries->push_front(new RegistryEntry(app_path_key, chrome_exe));
+ entries->push_front(new RegistryEntry(app_path_key,
+ ShellUtil::kAppPathsRegistryPathName, chrome_path.DirName().value()));
+
+ // TODO: add chrome to open with list (Bug 16726).
+ return true;
+ }
+
+ // This method returns a list of all the user level registry entries that
+ // are needed to make Chromium default browser.
+ static bool GetUserEntries(const std::wstring& chrome_exe,
+ const std::wstring& suffix,
+ std::list<RegistryEntry*>* entries) {
+ // File extension associations.
+ std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId);
+ html_prog_id.append(suffix);
+ for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
+ std::wstring ext_key(ShellUtil::kRegClasses);
+ file_util::AppendToPath(&ext_key, ShellUtil::kFileAssociations[i]);
+ entries->push_front(new RegistryEntry(ext_key, html_prog_id));
+ }
+
+ // .crx file type extension.
+ std::wstring ext_key(ShellUtil::kRegClasses);
+ ext_key.append(L".");
+ ext_key.append(chrome::kExtensionFileExtension);
+ std::wstring ext_prog_id(ShellUtil::kChromeExtProgId);
+ ext_prog_id.append(suffix);
+ entries->push_front(new RegistryEntry(ext_key, ext_prog_id));
+
+ // Protocols associations.
+ std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
+ std::wstring chrome_icon = ShellUtil::GetChromeIcon(chrome_exe);
+ for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) {
+ std::wstring url_key(ShellUtil::kRegClasses);
+ file_util::AppendToPath(&url_key, ShellUtil::kProtocolAssociations[i]);
+
+ // <root hkey>\Software\Classes\<protocol>\DefaultIcon
+ std::wstring icon_key = url_key + ShellUtil::kRegDefaultIcon;
+ entries->push_front(new RegistryEntry(icon_key, chrome_icon));
+
+ // <root hkey>\Software\Classes\<protocol>\shell\open\command
+ std::wstring shell_key = url_key + ShellUtil::kRegShellOpen;
+ entries->push_front(new RegistryEntry(shell_key, chrome_open));
+
+ // <root hkey>\Software\Classes\<protocol>\shell\open\ddeexec
+ std::wstring dde_key = url_key + L"\\shell\\open\\ddeexec";
+ entries->push_front(new RegistryEntry(dde_key, L""));
+
+ // <root hkey>\Software\Classes\<protocol>\shell\@
+ std::wstring protocol_shell_key = url_key + ShellUtil::kRegShellPath;
+ entries->push_front(new RegistryEntry(protocol_shell_key, L"open"));
+ }
+
+ // start->Internet shortcut.
+ std::wstring start_menu(ShellUtil::kRegStartMenuInternet);
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ entries->push_front(new RegistryEntry(start_menu,
+ dist->GetApplicationName()));
+ return true;
}
// Generate work_item tasks required to create current registry entry and
// add them to the given work item list.
- void AddToWorkItemList(HKEY root, WorkItemList *items) {
+ void AddToWorkItemList(HKEY root, WorkItemList *items) const {
items->AddCreateRegKeyWorkItem(root, _key_path);
if (_is_string) {
items->AddSetRegValueWorkItem(root, _key_path, _name, _value, true);
@@ -148,7 +210,7 @@ class RegistryEntry {
// Checks if the current registry entry exists in HKLM registry and the value
// is same.
- bool ExistsInHKLM() {
+ bool ExistsInHKLM() const {
RegKey key(HKEY_LOCAL_MACHINE, _key_path.c_str());
bool found = false;
if (_is_string) {
@@ -168,7 +230,7 @@ class RegistryEntry {
// Checks if the current registry entry exists in HKLM registry
// (only the name).
- bool NameExistsInHKLM() {
+ bool NameExistsInHKLM() const {
RegKey key(HKEY_LOCAL_MACHINE, _key_path.c_str());
bool found = false;
if (_is_string) {
@@ -183,6 +245,8 @@ class RegistryEntry {
}
private:
+ DISALLOW_COPY_AND_ASSIGN(RegistryEntry);
+
// Create a object that represent default value of a key
RegistryEntry(const std::wstring& key_path, const std::wstring& value)
: _key_path(key_path), _name(),
@@ -211,176 +275,143 @@ class RegistryEntry {
}; // class RegistryEntry
-// This method checks if Chrome is already registered on the local machine.
-// It gets all the required registry entries for Chrome and then checks if
-// they exist in HKLM. Returns true if all the entries exist, otherwise false.
-bool IsChromeRegistered(const std::wstring& chrome_exe) {
- bool registered = true;
- std::list<RegistryEntry*> entries = RegistryEntry::GetAllEntries(chrome_exe);
- for (std::list<RegistryEntry*>::iterator itr = entries.begin();
- itr != entries.end(); ++itr) {
- if (registered && !(*itr)->ExistsInHKLM())
- registered = false;
- delete (*itr);
- }
- LOG(INFO) << "Check for Chrome registration returned " << registered;
- return registered;
-}
-
-bool BindChromeAssociations(HKEY root_key, const std::wstring& chrome_exe) {
- // Create a list of registry entries to create so that we can rollback
- // in case of problem.
+// This method converts all the RegistryEntries from the given list to
+// Set/CreateRegWorkItems and runs them using WorkItemList.
+bool AddRegistryEntries(HKEY root, const std::list<RegistryEntry*>& entries) {
scoped_ptr<WorkItemList> items(WorkItem::CreateWorkItemList());
- // file extension associations
- std::wstring classes_path(ShellUtil::kRegClasses);
- for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
- std::wstring key_path = classes_path + L"\\" +
- ShellUtil::kFileAssociations[i];
- items->AddCreateRegKeyWorkItem(root_key, key_path);
- items->AddSetRegValueWorkItem(root_key, key_path, L"",
- ShellUtil::kChromeHTMLProgId, true);
- }
-
- // .crx file type extension
- std::wstring file_extension_key = classes_path + L"\\." +
- chrome::kExtensionFileExtension;
- items->AddCreateRegKeyWorkItem(root_key, file_extension_key);
- items->AddSetRegValueWorkItem(root_key, file_extension_key, L"",
- ShellUtil::kChromeExtProgId, true);
-
-
- // protocols associations
- std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
- std::wstring chrome_icon(chrome_exe);
- ShellUtil::GetChromeIcon(chrome_icon);
- for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) {
- std::wstring key_path = classes_path + L"\\" +
- ShellUtil::kProtocolAssociations[i];
- // <root hkey>\Software\Classes\<protocol>\DefaultIcon
- std::wstring icon_path = key_path + ShellUtil::kRegDefaultIcon;
- items->AddCreateRegKeyWorkItem(root_key, icon_path);
- items->AddSetRegValueWorkItem(root_key, icon_path, L"",
- chrome_icon, true);
- // <root hkey>\Software\Classes\<protocol>\shell\open\command
- std::wstring shell_path = key_path + ShellUtil::kRegShellOpen;
- items->AddCreateRegKeyWorkItem(root_key, shell_path);
- items->AddSetRegValueWorkItem(root_key, shell_path, L"",
- chrome_open, true);
- // <root hkey>\Software\Classes\<protocol>\shell\open\ddeexec
- std::wstring dde_path = key_path + L"\\shell\\open\\ddeexec";
- items->AddCreateRegKeyWorkItem(root_key, dde_path);
- items->AddSetRegValueWorkItem(root_key, dde_path, L"", L"", true);
- // <root hkey>\Software\Classes\<protocol>\shell\@
- std::wstring protocol_shell_path = key_path + ShellUtil::kRegShellPath;
- items->AddSetRegValueWorkItem(root_key, protocol_shell_path, L"",
- L"open", true);
- }
-
- // start->Internet shortcut.
- std::wstring start_internet(ShellUtil::kRegStartMenuInternet);
- items->AddCreateRegKeyWorkItem(root_key, start_internet);
- BrowserDistribution* dist = BrowserDistribution::GetDistribution();
- items->AddSetRegValueWorkItem(root_key, start_internet, L"",
- dist->GetApplicationName(), true);
+ for (std::list<RegistryEntry*>::const_iterator itr = entries.begin();
+ itr != entries.end(); ++itr)
+ (*itr)->AddToWorkItemList(root, items.get());
// Apply all the registry changes and if there is a problem, rollback
if (!items->Do()) {
- LOG(ERROR) << "Error while registering Chrome as default browser";
items->Rollback();
return false;
}
return true;
}
-// Populate work_item_list with WorkItem entries that will add chrome.exe to
-// the set of App Paths registry keys so that ShellExecute can find it. Note
-// that this is done in HKLM, regardless of whether this is a single-user
-// install or not. For non-admin users, this will fail.
-// chrome_exe: full path to chrome.exe
-// work_item_list: pointer to the WorkItemList that will be populated
-void AddChromeAppPathWorkItems(const std::wstring& chrome_exe,
- WorkItemList* item_list) {
- FilePath chrome_path(chrome_exe);
- std::wstring app_path_key(ShellUtil::kAppPathsRegistryKey);
- file_util::AppendToPath(&app_path_key, chrome_path.BaseName().value());
- item_list->AddCreateRegKeyWorkItem(HKEY_LOCAL_MACHINE, app_path_key);
- item_list->AddSetRegValueWorkItem(HKEY_LOCAL_MACHINE, app_path_key, L"",
- chrome_exe, true);
- item_list->AddSetRegValueWorkItem(HKEY_LOCAL_MACHINE, app_path_key,
- ShellUtil::kAppPathsRegistryPathName,
- chrome_path.DirName().value(), true);
+// This method checks if Chrome is already registered on the local machine.
+// It gets all the required registry entries for Chrome and then checks if
+// they exist in HKLM. Returns true if all the entries exist, otherwise false.
+bool IsChromeRegistered(const std::wstring& chrome_exe,
+ const std::wstring& suffix) {
+ bool registered = true;
+ std::list<RegistryEntry*> entries;
+ STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
+ RegistryEntry::GetProgIdEntries(chrome_exe, suffix, &entries);
+ RegistryEntry::GetSystemEntries(chrome_exe, suffix, &entries);
+ for (std::list<RegistryEntry*>::const_iterator itr = entries.begin();
+ itr != entries.end() && registered; ++itr) {
+ // We do not need registered = registered && ... since the loop condition
+ // is set to exit early.
+ registered = (*itr)->ExistsInHKLM();
+ }
+ return registered;
}
-// This method creates the registry entries required for Add/Remove Programs->
-// Set Program Access and Defaults, Start->Default Programs on Windows Vista
-// and Chrome ProgIds for file extension and protocol handler. root_key is
-// the root registry (HKLM or HKCU).
-bool SetAccessDefaultRegEntries(HKEY root_key,
- const std::wstring& chrome_exe) {
- LOG(INFO) << "Registering Chrome browser " << chrome_exe;
- // Create a list of registry entries work items so that we can rollback
- // in case of problem.
- scoped_ptr<WorkItemList> items(WorkItem::CreateWorkItemList());
-
- std::list<RegistryEntry*> entries = RegistryEntry::GetAllEntries(chrome_exe);
- for (std::list<RegistryEntry*>::iterator itr = entries.begin();
- itr != entries.end(); ++itr) {
- (*itr)->AddToWorkItemList(root_key, items.get());
- delete (*itr);
+// This method registers Chrome on Vista by launching eleavated setup.exe.
+// That will show user standard Vista elevation prompt. If user accepts it
+// the new process will make the necessary changes and return SUCCESS that
+// we capture and return.
+bool ElevateAndRegisterChrome(const std::wstring& chrome_exe,
+ const std::wstring& suffix) {
+ std::wstring exe_path(file_util::GetDirectoryFromPath(chrome_exe));
+ file_util::AppendToPath(&exe_path, installer_util::kSetupExe);
+ if (!file_util::PathExists(exe_path)) {
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ HKEY reg_root = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ?
+ HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
+ RegKey key(reg_root, dist->GetUninstallRegPath().c_str());
+ key.ReadValue(installer_util::kUninstallStringField, &exe_path);
+ CommandLine command_line(L"");
+ command_line.ParseFromString(exe_path);
+ exe_path = command_line.program();
}
+ if (file_util::PathExists(exe_path)) {
+ std::wstring params(L"--");
+ params.append(installer_util::switches::kRegisterChromeBrowser);
+ params.append(L"=\"" + chrome_exe + L"\"");
+ if (!suffix.empty()) {
+ params.append(L"--");
+ params.append(installer_util::switches::kRegisterChromeBrowserSuffix);
+ params.append(L"=\"" + suffix + L"\"");
+ }
+ DWORD ret_val = 0;
+ InstallUtil::ExecuteExeAsAdmin(exe_path, params, &ret_val);
+ if (ret_val == 0)
+ return true;
+ }
+ return false;
+}
- // Append the App Paths registry entries. Do this only if we are an admin,
- // since they are always written to HKLM.
- if (IsUserAnAdmin())
- AddChromeAppPathWorkItems(chrome_exe, items.get());
-
- // Apply all the registry changes and if there is a problem, rollback.
- if (!items->Do()) {
- LOG(ERROR) << "Failed to add Chrome to Set Program Access and Defaults";
- items->Rollback();
+// This method checks if user specific default browser registry entry exists.
+// (i.e. Software\Clients\StartMenuInternet\Chromium.<user>)
+bool UserSpecificDefaultBrowserEntryExists() {
+ std::wstring suffix;
+ if (!ShellUtil::GetUserSpecificDefaultBrowserSuffix(&suffix))
return false;
- }
- return true;
+ std::wstring start_menu_entry(ShellUtil::kRegStartMenuInternet);
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ start_menu_entry.append(L"\\" + dist->GetApplicationName() + suffix);
+ RegKey key(HKEY_LOCAL_MACHINE, start_menu_entry.c_str());
+ return key.Valid();
}
+// This method tries to figure out if another user has already registered her
+// own copy of Chrome so that we can avoid overwriting it and append current
+// user's login name to default browser registry entries. This function is
+// not meant to detect all cases. It just tries to handle the most common case.
+// All the conditions below have to be true for it to return true:
+// - Software\Clients\StartMenuInternet\Chromium\"" key should have a valid
+// value.
+// - The value should not be same as given value in |chrome_exe|
+// - Finally to handle the default install path (C:\Document and Settings\
+// <user>\Local Settings\Application Data\Chromium\Application) the value
+// of the above key should differ from |chrome_exe| only in user name.
+bool AnotherUserHasDefaultBrowser(const std::wstring& chrome_exe) {
+ std::wstring reg_key(ShellUtil::kRegStartMenuInternet);
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ reg_key.append(L"\\" + dist->GetApplicationName() + ShellUtil::kRegShellOpen);
+ RegKey key(HKEY_LOCAL_MACHINE, reg_key.c_str());
+ std::wstring registry_chrome_exe;
+ if (!key.ReadValue(L"", &registry_chrome_exe) ||
+ registry_chrome_exe.length() < 2)
+ return false;
-// This method registers Chrome on Vista. It checks if we are currently
-// running as admin and if not, it launches setup.exe as administrator which
-// will show user standard Vista elevation prompt. If user accepts it
-// the new process will make the necessary changes and return SUCCESS that
-// we capture and return.
-ShellUtil::RegisterStatus RegisterOnVista(const std::wstring& chrome_exe,
- bool skip_if_not_admin) {
- if (IsUserAnAdmin() &&
- SetAccessDefaultRegEntries(HKEY_LOCAL_MACHINE, chrome_exe))
- return ShellUtil::SUCCESS;
-
- if (!skip_if_not_admin) {
- std::wstring exe_path(file_util::GetDirectoryFromPath(chrome_exe));
- file_util::AppendToPath(&exe_path, installer_util::kSetupExe);
- if (!file_util::PathExists(exe_path)) {
- BrowserDistribution* dist = BrowserDistribution::GetDistribution();
- HKEY reg_root = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ?
- HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
- RegKey key(reg_root, dist->GetUninstallRegPath().c_str());
- key.ReadValue(installer_util::kUninstallStringField, &exe_path);
- CommandLine command_line(L"");
- command_line.ParseFromString(exe_path);
- exe_path = command_line.program();
- }
- if (file_util::PathExists(exe_path)) {
- std::wstring params(L"--");
- params.append(installer_util::switches::kRegisterChromeBrowser);
- params.append(L"=\"" + chrome_exe + L"\"");
- DWORD ret_val = ShellUtil::SUCCESS;
- InstallUtil::ExecuteExeAsAdmin(exe_path, params, &ret_val);
- if (ret_val == ShellUtil::SUCCESS)
- return ShellUtil::SUCCESS;
+ registry_chrome_exe = registry_chrome_exe.substr(1,
+ registry_chrome_exe.length() - 2);
+ if ((registry_chrome_exe.size() == chrome_exe.size()) &&
+ (std::equal(chrome_exe.begin(), chrome_exe.end(),
+ registry_chrome_exe.begin(),
+ CaseInsensitiveCompare<wchar_t>())))
+ return false;
+
+ std::vector<std::wstring> v1, v2;
+ SplitString(registry_chrome_exe, L'\\', &v1);
+ SplitString(chrome_exe, L'\\', &v2);
+ if (v1.size() == 0 || v2.size() == 0 || v1.size() != v2.size())
+ return false;
+
+ // Now check that only one of the values within two '\' chars differ.
+ std::vector<std::wstring>::iterator itr1 = v1.begin();
+ std::vector<std::wstring>::iterator itr2 = v2.begin();
+ bool one_mismatch = false;
+ for ( ; itr1 < v1.end() && itr2 < v2.end(); ++itr1, ++itr2) {
+ std::wstring s1 = *itr1;
+ std::wstring s2 = *itr2;
+ if ((s1.size() != s2.size()) ||
+ (!std::equal(s1.begin(), s1.end(),
+ s2.begin(), CaseInsensitiveCompare<wchar_t>()))) {
+ if (one_mismatch)
+ return false;
+ else
+ one_mismatch = true;
}
}
- return ShellUtil::FAILURE;
+ return true;
}
} // namespace
@@ -404,11 +435,11 @@ const wchar_t* ShellUtil::kAppPathsRegistryPathName = L"Path";
#if defined(GOOGLE_CHROME_BUILD)
const wchar_t* ShellUtil::kChromeExtProgId = L"ChromeExt";
const wchar_t* ShellUtil::kChromeHTMLProgId = L"ChromeHTML";
-const wchar_t* ShellUtil::kChromeHTMLProgIdDesc = L"Chrome HTML";
+const wchar_t* ShellUtil::kChromeHTMLProgIdDesc = L"Chrome HTML Document";
#else
const wchar_t* ShellUtil::kChromeExtProgId = L"ChromiumExt";
const wchar_t* ShellUtil::kChromeHTMLProgId = L"ChromiumHTML";
-const wchar_t* ShellUtil::kChromeHTMLProgIdDesc = L"Chromium HTML";
+const wchar_t* ShellUtil::kChromeHTMLProgIdDesc = L"Chromium HTML Document";
#endif
const wchar_t* ShellUtil::kFileAssociations[] = {L".htm", L".html", L".shtml",
@@ -419,104 +450,24 @@ const wchar_t* ShellUtil::kRegUrlProtocol = L"URL Protocol";
const wchar_t* ShellUtil::kChromeExtProgIdDesc = L"Chrome Extension Installer";
-ShellUtil::RegisterStatus ShellUtil::AddChromeToSetAccessDefaults(
- const std::wstring& chrome_exe, bool skip_if_not_admin) {
- if (IsChromeRegistered(chrome_exe))
- return ShellUtil::SUCCESS;
-
- if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA)
- return RegisterOnVista(chrome_exe, skip_if_not_admin);
-
- // Try adding these entries to HKLM first and if that fails try adding
- // to HKCU.
- if (SetAccessDefaultRegEntries(HKEY_LOCAL_MACHINE, chrome_exe))
- return ShellUtil::SUCCESS;
-
- if (!skip_if_not_admin &&
- SetAccessDefaultRegEntries(HKEY_CURRENT_USER, chrome_exe))
- return ShellUtil::REGISTERED_PER_USER;
-
- return ShellUtil::FAILURE;
-}
-
bool ShellUtil::AdminNeededForRegistryCleanup() {
bool cleanup_needed = false;
- std::list<RegistryEntry*> entries = RegistryEntry::GetAllEntries(
- installer_util::kChromeExe);
- for (std::list<RegistryEntry*>::iterator itr = entries.begin();
- itr != entries.end(); ++itr) {
- if (!cleanup_needed && (*itr)->NameExistsInHKLM())
- cleanup_needed = true;
- delete (*itr);
+ std::list<RegistryEntry*> entries;
+ STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
+ RegistryEntry::GetProgIdEntries(L"chrome.exe", L"", &entries);
+ RegistryEntry::GetSystemEntries(L"chrome.exe", L"", &entries);
+
+ std::wstring suffix;
+ GetUserSpecificDefaultBrowserSuffix(&suffix);
+ RegistryEntry::GetProgIdEntries(L"chrome.exe", suffix, &entries);
+ RegistryEntry::GetSystemEntries(L"chrome.exe", suffix, &entries);
+ for (std::list<RegistryEntry*>::const_iterator itr = entries.begin();
+ itr != entries.end() && !cleanup_needed; ++itr) {
+ cleanup_needed = (*itr)->NameExistsInHKLM();
}
return cleanup_needed;
}
-bool ShellUtil::GetChromeIcon(std::wstring& chrome_icon) {
- if (chrome_icon.empty())
- return false;
-
- chrome_icon.append(L",0");
- return true;
-}
-
-std::wstring ShellUtil::GetChromeShellOpenCmd(const std::wstring& chrome_exe) {
- return L"\"" + chrome_exe + L"\" -- \"%1\"";
-}
-
-std::wstring ShellUtil::GetChromeInstallExtensionCmd(
- const std::wstring& chrome_exe) {
- return L"\"" + chrome_exe + L"\" --install-extension=\"%1\"";
-}
-
-bool ShellUtil::GetChromeShortcutName(std::wstring* shortcut, bool alternate) {
- BrowserDistribution* dist = BrowserDistribution::GetDistribution();
- shortcut->assign(alternate ? dist->GetAlternateApplicationName() :
- dist->GetApplicationName());
- shortcut->append(L".lnk");
- return true;
-}
-
-bool ShellUtil::GetDesktopPath(bool system_level, std::wstring* path) {
- wchar_t desktop[MAX_PATH];
- int dir = system_level ? CSIDL_COMMON_DESKTOPDIRECTORY :
- CSIDL_DESKTOPDIRECTORY;
- if (FAILED(SHGetFolderPath(NULL, dir, NULL, SHGFP_TYPE_CURRENT, desktop)))
- return false;
- *path = desktop;
- return true;
-}
-
-bool ShellUtil::GetQuickLaunchPath(bool system_level, std::wstring* path) {
- const static wchar_t* kQuickLaunchPath =
- L"Microsoft\\Internet Explorer\\Quick Launch";
- wchar_t qlaunch[MAX_PATH];
- if (system_level) {
- // We are accessing GetDefaultUserProfileDirectory this way so that we do
- // not have to declare dependency to Userenv.lib for chrome.exe
- typedef BOOL (WINAPI *PROFILE_FUNC)(LPWSTR, LPDWORD);
- HMODULE module = LoadLibrary(L"Userenv.dll");
- PROFILE_FUNC p = reinterpret_cast<PROFILE_FUNC>(GetProcAddress(module,
- "GetDefaultUserProfileDirectoryW"));
- DWORD size = _countof(qlaunch);
- if ((p == NULL) || ((p)(qlaunch, &size) != TRUE))
- return false;
- *path = qlaunch;
- if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) {
- file_util::AppendToPath(path, L"AppData\\Roaming");
- } else {
- file_util::AppendToPath(path, L"Application Data");
- }
- } else {
- if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL,
- SHGFP_TYPE_CURRENT, qlaunch)))
- return false;
- *path = qlaunch;
- }
- file_util::AppendToPath(path, kQuickLaunchPath);
- return true;
-}
-
bool ShellUtil::CreateChromeDesktopShortcut(const std::wstring& chrome_exe,
const std::wstring& description,
int shell_change, bool alternate,
@@ -587,8 +538,84 @@ bool ShellUtil::CreateChromeQuickLaunchShortcut(const std::wstring& chrome_exe,
return ret;
}
+std::wstring ShellUtil::GetChromeIcon(const std::wstring& chrome_exe) {
+ std::wstring chrome_icon(chrome_exe);
+ chrome_icon.append(L",0");
+ return chrome_icon;
+}
+
+std::wstring ShellUtil::GetChromeInstallExtensionCmd(
+ const std::wstring& chrome_exe) {
+ return L"\"" + chrome_exe + L"\" --install-extension=\"%1\"";
+}
+
+std::wstring ShellUtil::GetChromeShellOpenCmd(const std::wstring& chrome_exe) {
+ return L"\"" + chrome_exe + L"\" -- \"%1\"";
+}
+
+bool ShellUtil::GetChromeShortcutName(std::wstring* shortcut, bool alternate) {
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ shortcut->assign(alternate ? dist->GetAlternateApplicationName() :
+ dist->GetApplicationName());
+ shortcut->append(L".lnk");
+ return true;
+}
+
+bool ShellUtil::GetDesktopPath(bool system_level, std::wstring* path) {
+ wchar_t desktop[MAX_PATH];
+ int dir = system_level ? CSIDL_COMMON_DESKTOPDIRECTORY :
+ CSIDL_DESKTOPDIRECTORY;
+ if (FAILED(SHGetFolderPath(NULL, dir, NULL, SHGFP_TYPE_CURRENT, desktop)))
+ return false;
+ *path = desktop;
+ return true;
+}
+
+bool ShellUtil::GetQuickLaunchPath(bool system_level, std::wstring* path) {
+ const static wchar_t* kQuickLaunchPath =
+ L"Microsoft\\Internet Explorer\\Quick Launch";
+ wchar_t qlaunch[MAX_PATH];
+ if (system_level) {
+ // We are accessing GetDefaultUserProfileDirectory this way so that we do
+ // not have to declare dependency to Userenv.lib for chrome.exe
+ typedef BOOL (WINAPI *PROFILE_FUNC)(LPWSTR, LPDWORD);
+ HMODULE module = LoadLibrary(L"Userenv.dll");
+ PROFILE_FUNC p = reinterpret_cast<PROFILE_FUNC>(GetProcAddress(module,
+ "GetDefaultUserProfileDirectoryW"));
+ DWORD size = _countof(qlaunch);
+ if ((p == NULL) || ((p)(qlaunch, &size) != TRUE))
+ return false;
+ *path = qlaunch;
+ if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) {
+ file_util::AppendToPath(path, L"AppData\\Roaming");
+ } else {
+ file_util::AppendToPath(path, L"Application Data");
+ }
+ } else {
+ if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL,
+ SHGFP_TYPE_CURRENT, qlaunch)))
+ return false;
+ *path = qlaunch;
+ }
+ file_util::AppendToPath(path, kQuickLaunchPath);
+ return true;
+}
+
+bool ShellUtil::GetUserSpecificDefaultBrowserSuffix(std::wstring* entry) {
+ wchar_t user_name[256];
+ DWORD size = _countof(user_name);
+ if (::GetUserName(user_name, &size) == 0)
+ return false;
+ entry->assign(L".");
+ entry->append(user_name);
+ return true;
+}
+
bool ShellUtil::MakeChromeDefault(int shell_change,
- const std::wstring& chrome_exe) {
+ const std::wstring& chrome_exe,
+ bool elevate_if_not_admin) {
+ ShellUtil::RegisterChromeBrowser(chrome_exe, L"", elevate_if_not_admin);
+
bool ret = true;
// First use the new "recommended" way on Vista to make Chrome default
// browser.
@@ -613,14 +640,21 @@ bool ShellUtil::MakeChromeDefault(int shell_change,
// associations. This should not be required on Vista but since some
// applications still read Software\Classes\http key directly, we have to do
// this on Vista also.
+
+ std::list<RegistryEntry*> entries;
+ STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
+ std::wstring suffix;
+ if (UserSpecificDefaultBrowserEntryExists())
+ GetUserSpecificDefaultBrowserSuffix(&suffix);
+ RegistryEntry::GetUserEntries(chrome_exe, suffix, &entries);
// Change the default browser for current user.
if ((shell_change & ShellUtil::CURRENT_USER) &&
- !BindChromeAssociations(HKEY_CURRENT_USER, chrome_exe))
- ret = false;
+ !AddRegistryEntries(HKEY_CURRENT_USER, entries))
+ ret = false;
// Chrome as default browser at system level.
if ((shell_change & ShellUtil::SYSTEM_LEVEL) &&
- !BindChromeAssociations(HKEY_LOCAL_MACHINE, chrome_exe))
+ !AddRegistryEntries(HKEY_LOCAL_MACHINE, entries))
ret = false;
// Send Windows notification event so that it can update icons for
@@ -629,6 +663,47 @@ bool ShellUtil::MakeChromeDefault(int shell_change,
return ret;
}
+bool ShellUtil::RegisterChromeBrowser(const std::wstring& chrome_exe,
+ const std::wstring& unique_suffix,
+ bool elevate_if_not_admin) {
+ // First figure out we need to append a suffix to the registry entries to
+ // make them unique.
+ std::wstring suffix;
+ if (!unique_suffix.empty()) {
+ suffix = unique_suffix;
+ } else if (InstallUtil::IsPerUserInstall(chrome_exe.c_str()) &&
+ (UserSpecificDefaultBrowserEntryExists() ||
+ AnotherUserHasDefaultBrowser(chrome_exe))) {
+ GetUserSpecificDefaultBrowserSuffix(&suffix);
+ }
+
+ // Check if Chromium is already registered with this suffix.
+ if (IsChromeRegistered(chrome_exe, suffix))
+ return true;
+
+ // If user is an admin try to register and return the status.
+ if (IsUserAnAdmin()) {
+ std::list<RegistryEntry*> entries;
+ STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
+ RegistryEntry::GetProgIdEntries(chrome_exe, suffix, &entries);
+ RegistryEntry::GetSystemEntries(chrome_exe, suffix, &entries);
+ return AddRegistryEntries(HKEY_LOCAL_MACHINE, entries);
+ }
+
+ // If user is not an admin and OS is Vista, try to elevate and register.
+ if (elevate_if_not_admin &&
+ win_util::GetWinVersion() >= win_util::WINVERSION_VISTA &&
+ ElevateAndRegisterChrome(chrome_exe, suffix))
+ return true;
+
+ // If we got to this point then all we can do is create ProgIds under HKCU
+ // on XP as well as Vista.
+ std::list<RegistryEntry*> entries;
+ STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
+ RegistryEntry::GetProgIdEntries(chrome_exe, L"", &entries);
+ return AddRegistryEntries(HKEY_CURRENT_USER, entries);
+}
+
bool ShellUtil::RemoveChromeDesktopShortcut(int shell_change, bool alternate) {
std::wstring shortcut_name;
if (!ShellUtil::GetChromeShortcutName(&shortcut_name, alternate))
diff --git a/chrome/installer/util/shell_util.h b/chrome/installer/util/shell_util.h
index a834496c..6eb7390 100644
--- a/chrome/installer/util/shell_util.h
+++ b/chrome/installer/util/shell_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2009 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.
//
@@ -6,8 +6,8 @@
// Windows shell. These methods are all static and currently part of
// ShellUtil class.
-#ifndef CHROME_INSTALLER_UTIL_SHELL_UTIL_H__
-#define CHROME_INSTALLER_UTIL_SHELL_UTIL_H__
+#ifndef CHROME_INSTALLER_UTIL_SHELL_UTIL_H_
+#define CHROME_INSTALLER_UTIL_SHELL_UTIL_H_
#include <windows.h>
#include <string>
@@ -25,13 +25,6 @@ class ShellUtil {
SYSTEM_LEVEL = 0x2 // Make any shell changes only at the system level
};
- // Return value of AddChromeToSetAccessDefaults.
- enum RegisterStatus {
- SUCCESS, // Registration of Chrome successful (in HKLM)
- FAILURE, // Registration failed (no changes made)
- REGISTERED_PER_USER // Registered Chrome as per user (in HKCU)
- };
-
// Relative path of DefaultIcon registry entry (prefixed with '\').
static const wchar_t* kRegDefaultIcon;
@@ -62,7 +55,7 @@ class ShellUtil {
// Name that we give to Chrome file association handler ProgId.
static const wchar_t* kChromeHTMLProgId;
- // Description of Chrome file/URL association handler ProgId.
+ // Description of Chrome file association handler ProgId.
static const wchar_t* kChromeHTMLProgIdDesc;
// Registry path that stores url associations on Vista.
@@ -83,27 +76,6 @@ class ShellUtil {
// Description of Chrome file/URL association handler ProgId.
static const wchar_t* kChromeExtProgIdDesc;
- // This method adds Chrome to the list that shows up in Add/Remove Programs->
- // Set Program Access and Defaults and also creates Chrome ProgIds under
- // Software\Classes. This method requires write access to HKLM so is just
- // best effort deal. If write to HKLM fails and skip_if_not_admin is false,
- // this method will:
- // - add the ProgId entries to HKCU on XP. HKCU entries will not make
- // Chrome show in Set Program Access and Defaults but they are still useful
- // because we can make Chrome run when user clicks on http link or html
- // file.
- // - will try to launch setup.exe with admin priviledges on Vista to do
- // these tasks. Users will see standard Vista elevation prompt and if they
- // enter the right credentials, the write operation will work.
- // Currently skip_if_not_admin is false only when user tries to make Chrome
- // default browser and Chrome is not registered on the machine.
- //
- // chrome_exe: full path to chrome.exe.
- // skip_if_not_admin: if false will make this method try alternate methods
- // as described above.
- static RegisterStatus AddChromeToSetAccessDefaults(
- const std::wstring& chrome_exe, bool skip_if_not_admin);
-
// Checks if we need Admin rights for registry cleanup by checking if any
// entry exists in HKLM.
static bool AdminNeededForRegistryCleanup();
@@ -137,8 +109,8 @@ class ShellUtil {
// This method appends the Chrome icon index inside chrome.exe to the
// chrome.exe path passed in as input, to generate the full path for
// Chrome icon that can be used as value for Windows registry keys.
- // chrome_icon: full path to chrome.exe.
- static bool GetChromeIcon(std::wstring& chrome_icon);
+ // |chrome_exe| full path to chrome.exe.
+ static std::wstring GetChromeIcon(const std::wstring& chrome_exe);
// This method returns the command to open URLs/files using chrome. Typically
// this command is written to the registry under shell\open\command key.
@@ -167,17 +139,48 @@ class ShellUtil {
// User's profile only affects any new user profiles (not existing ones).
static bool GetQuickLaunchPath(bool system_level, std::wstring* path);
- // Make Chrome default browser. Before calling this function Chrome should
- // already have been registered by calling AddChromeToSetAccessDefaults()
- // method, otherwise this function will fail.
+ // This function gets a suffix (user's login name) that can be added
+ // to Chromium default browser entry in the registry to create a unique name
+ // if there are multiple users on the machine, each with their own copy of
+ // Chromium that they want to set as default browser.
+ // This suffix value is assigned to |entry|.
+ static bool GetUserSpecificDefaultBrowserSuffix(std::wstring* entry);
+
+ // Make Chrome default browser.
// shell_change: Defined whether to register as default browser at system
// level or user level. If value has ShellChange::SYSTEM_LEVEL
- // we should be running as admin user. Currently this setting
- // does not have any effect on Vista where we always set
- // as default only for the current user.
+ // we should be running as admin user.
// chrome_exe: The chrome.exe path to register as default browser.
+ // elevate_if_not_admin: On Vista if user is not admin, try to elevate for
+ // Chrome registration.
static bool MakeChromeDefault(int shell_change,
- const std::wstring& chrome_exe);
+ const std::wstring& chrome_exe,
+ bool elevate_if_not_admin);
+
+ // This method adds Chrome to the list that shows up in Add/Remove Programs->
+ // Set Program Access and Defaults and also creates Chrome ProgIds under
+ // Software\Classes. This method requires write access to HKLM so is just
+ // best effort deal. If write to HKLM fails and elevate_if_not_admin is true,
+ // this method will:
+ // - add the ProgId entries to HKCU on XP. HKCU entries will not make
+ // Chrome show in Set Program Access and Defaults but they are still useful
+ // because we can make Chrome run when user clicks on http link or html
+ // file.
+ // - will try to launch setup.exe with admin priviledges on Vista to do
+ // these tasks. Users will see standard Vista elevation prompt and if they
+ // enter the right credentials, the write operation will work.
+ // Currently elevate_if_not_admin is true only when user tries to make Chrome
+ // default browser (through the UI or through installer options) and Chrome
+ // is not registered on the machine.
+ //
+ // |chrome_exe| full path to chrome.exe.
+ // |unique_suffix| Optional input. If given, this function appends the value
+ // to default browser entries names that it creates in the registry.
+ // |elevate_if_not_admin| if true will make this method try alternate methods
+ // as described above.
+ static bool RegisterChromeBrowser(const std::wstring& chrome_exe,
+ const std::wstring& unique_suffix,
+ bool elevate_if_not_admin);
// Remove Chrome shortcut from Desktop.
// If shell_change is CURRENT_USER, the shortcut is removed from the
@@ -206,8 +209,8 @@ class ShellUtil {
bool create_new);
private:
- DISALLOW_EVIL_CONSTRUCTORS(ShellUtil);
+ DISALLOW_COPY_AND_ASSIGN(ShellUtil);
};
-#endif // CHROME_INSTALLER_UTIL_SHELL_UTIL_H__
+#endif // CHROME_INSTALLER_UTIL_SHELL_UTIL_H_
diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc
index 99df51e..07afdeb 100644
--- a/chrome/installer/util/util_constants.cc
+++ b/chrome/installer/util/util_constants.cc
@@ -57,6 +57,9 @@ const wchar_t kNewSetupExe[] = L"new-setup-exe";
// options kInstallArchive and kUninstall are ignored.
const wchar_t kRegisterChromeBrowser[] = L"register-chrome-browser";
+const wchar_t kRegisterChromeBrowserSuffix[] =
+ L"register-chrome-browser-suffix";
+
// Renames chrome.exe to old_chrome.exe and renames new_chrome.exe to chrome.exe
// to support in-use updates. Also deletes opv key.
const wchar_t kRenameChromeExe[] = L"rename-chrome-exe";
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h
index 7bc753f..5256d6a 100644
--- a/chrome/installer/util/util_constants.h
+++ b/chrome/installer/util/util_constants.h
@@ -5,8 +5,8 @@
// Defines all install related constants that need to be used by Chrome as
// well as Chrome Installer.
-#ifndef CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H__
-#define CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H__
+#ifndef CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H_
+#define CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H_
namespace installer_util {
@@ -81,6 +81,7 @@ extern const wchar_t kLogFile[];
extern const wchar_t kMakeChromeDefault[];
extern const wchar_t kNewSetupExe[];
extern const wchar_t kRegisterChromeBrowser[];
+extern const wchar_t kRegisterChromeBrowserSuffix[];
extern const wchar_t kRenameChromeExe[];
extern const wchar_t kRemoveChromeRegistration[];
extern const wchar_t kRunAsAdmin[];
@@ -109,4 +110,4 @@ extern const wchar_t kUninstallInstallationDate[];
} // namespace installer_util
-#endif // CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H__
+#endif // CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H_