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

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

Issue 159172: Allow two user level installs of Chrome to have default browser settings. (Closed)
Patch Set: update comment. Created 11 years, 5 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
« no previous file with comments | « chrome/installer/util/shell_util.h ('k') | chrome/installer/util/util_constants.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/installer/util/shell_util.cc
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index 2a7619a5e95c4406484d7b4ac3cb4e98b4377267..12613168e34d4e0a544df36fb90c560052692a90 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))
« no previous file with comments | « chrome/installer/util/shell_util.h ('k') | chrome/installer/util/util_constants.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698