| 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"", ®istry_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))
|
|
|