Commit f5a05dc4 authored by gab@chromium.org's avatar gab@chromium.org

Register Chrome in Open With... for File Associations at install on Windows.

Refactor shell_util.cc to use ScopedVector<RegistryEntry> instead of std::list<RegistryEntry*>

BUG=139597
TEST=Chrome shows up in the Open With context menu immediately post-install (not after first-run/make default).
Make sure App Paths still work (i.e. launch "chrome.exe" from Run dialog).

For the OpenWith test (say you're testing OpenWith for .htm files), make sure that you delete Chrome ProgIds from:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.htm\OpenWithProgids
(they are automatically copied there by Windows so if you have previously installed Chrome on this machine and made it default at least once Windows will have picked this up already).

Review URL: https://chromiumcodereview.appspot.com/10823178

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150234 0039d316-1c4b-4281-b951-d872f2087c98
parent c3fdbdf7
......@@ -392,7 +392,7 @@ void RegisterChromeOnMachine(const InstallerState& installer_state,
AddChromeToMediaPlayerList();
// Make Chrome the default browser if desired when possible. Otherwise, only
// register it for shell integration.
// register it with Windows.
BrowserDistribution* dist = product.distribution();
const string16 chrome_exe(
installer_state.target_path().Append(installer::kChromeExe).value());
......
......@@ -592,19 +592,19 @@ bool DeleteChromeRegistrationKeys(BrowserDistribution* dist, HKEY root,
// For user-level installs we now only write these entries in HKCU, but since
// old installs did install them to HKLM we will try to remove them in HKLM as
// well anyways.
string16 html_prog_id(ShellUtil::kRegClasses);
html_prog_id.push_back(FilePath::kSeparators[0]);
html_prog_id.append(ShellUtil::kChromeHTMLProgId);
html_prog_id.append(browser_entry_suffix);
InstallUtil::DeleteRegistryKey(root, html_prog_id);
const string16 prog_id(ShellUtil::kChromeHTMLProgId + browser_entry_suffix);
string16 reg_prog_id(ShellUtil::kRegClasses);
reg_prog_id.push_back(FilePath::kSeparators[0]);
reg_prog_id.append(prog_id);
InstallUtil::DeleteRegistryKey(root, reg_prog_id);
// Delete Software\Classes\Chrome (Same comment as above applies for this too)
string16 chrome_app_id(ShellUtil::kRegClasses);
chrome_app_id.push_back(FilePath::kSeparators[0]);
string16 reg_app_id(ShellUtil::kRegClasses);
reg_app_id.push_back(FilePath::kSeparators[0]);
// Append the requested suffix manually here (as ShellUtil::GetBrowserModelId
// would otherwise try to figure out the currently installed suffix).
chrome_app_id.append(dist->GetBaseAppId() + browser_entry_suffix);
InstallUtil::DeleteRegistryKey(root, chrome_app_id);
reg_app_id.append(dist->GetBaseAppId() + browser_entry_suffix);
InstallUtil::DeleteRegistryKey(root, reg_app_id);
// Delete all Start Menu Internet registrations that refer to this Chrome.
{
......@@ -644,7 +644,8 @@ bool DeleteChromeRegistrationKeys(BrowserDistribution* dist, HKEY root,
InstallUtil::DeleteRegistryValue(root, ShellUtil::kRegRegisteredApplications,
dist->GetBaseAppName() + browser_entry_suffix);
// Delete Software\Classes\Applications\chrome.exe
// Delete the App Paths and Applications keys that let Explorer find Chrome:
// http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121
string16 app_key(ShellUtil::kRegClasses);
app_key.push_back(FilePath::kSeparators[0]);
app_key.append(L"Applications");
......@@ -652,23 +653,31 @@ bool DeleteChromeRegistrationKeys(BrowserDistribution* dist, HKEY root,
app_key.append(installer::kChromeExe);
InstallUtil::DeleteRegistryKey(root, app_key);
// Delete the App Paths key that lets explorer find Chrome.
string16 app_path_key(ShellUtil::kAppPathsRegistryKey);
app_path_key.push_back(FilePath::kSeparators[0]);
app_path_key.append(installer::kChromeExe);
InstallUtil::DeleteRegistryKey(root, app_path_key);
// Cleanup OpenWithList
string16 open_with_key;
for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
open_with_key.assign(ShellUtil::kRegClasses);
open_with_key.push_back(FilePath::kSeparators[0]);
open_with_key.append(ShellUtil::kFileAssociations[i]);
open_with_key.push_back(FilePath::kSeparators[0]);
open_with_key.append(L"OpenWithList");
open_with_key.push_back(FilePath::kSeparators[0]);
open_with_key.append(installer::kChromeExe);
InstallUtil::DeleteRegistryKey(root, open_with_key);
// Cleanup OpenWithList and OpenWithProgids:
// http://msdn.microsoft.com/en-us/library/bb166549
string16 file_assoc_key;
string16 open_with_list_key;
string16 open_with_progids_key;
for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; ++i) {
file_assoc_key.assign(ShellUtil::kRegClasses);
file_assoc_key.push_back(FilePath::kSeparators[0]);
file_assoc_key.append(ShellUtil::kFileAssociations[i]);
file_assoc_key.push_back(FilePath::kSeparators[0]);
open_with_list_key.assign(file_assoc_key);
open_with_list_key.append(L"OpenWithList");
open_with_list_key.push_back(FilePath::kSeparators[0]);
open_with_list_key.append(installer::kChromeExe);
InstallUtil::DeleteRegistryKey(root, open_with_list_key);
open_with_progids_key.assign(file_assoc_key);
open_with_progids_key.append(ShellUtil::kRegOpenWithProgids);
InstallUtil::DeleteRegistryValue(root, open_with_progids_key, prog_id);
}
// Cleanup in case Chrome had been made the default browser.
......@@ -1025,7 +1034,7 @@ InstallStatus UninstallProduct(const InstallationState& original_state,
// GetCurrentInstallationSuffix() above)).
// TODO(gab): This can still leave parts of a suffixed install behind. To be
// able to remove them we would need to be able to remove only suffixed
// entries (as it is now some of the shell integration entries are
// entries (as it is now some of the registry entries (e.g. App Paths) are
// unsuffixed; thus removing suffixed installs is prohibited in HKLM if
// !|remove_all| for now).
if (installer_state.system_install() ||
......
......@@ -13,7 +13,6 @@
#include <windows.h>
#include <limits>
#include <list>
#include <string>
#include "base/command_line.h"
......@@ -23,8 +22,9 @@
#include "base/logging.h"
#include "base/md5.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/path_service.h"
#include "base/stl_util.h"
#include "base/string16.h"
#include "base/string_number_conversions.h"
#include "base/string_split.h"
#include "base/string_util.h"
......@@ -204,13 +204,13 @@ class RegistryEntry {
}
// This method returns a list of all the registry entries that
// are needed to register Chromium ProgIds.
// are needed to register this installation's ProgId and AppId.
// These entries should be registered in HKCU for user-level installs and in
// HKLM for system-level installs.
static bool GetProgIdEntries(BrowserDistribution* dist,
static void GetProgIdEntries(BrowserDistribution* dist,
const string16& chrome_exe,
const string16& suffix,
std::list<RegistryEntry*>* entries) {
ScopedVector<RegistryEntry>* entries) {
string16 icon_path(ShellUtil::GetChromeIcon(dist, chrome_exe));
string16 open_cmd(ShellUtil::GetChromeShellOpenCmd(chrome_exe));
string16 delegate_command(ShellUtil::GetChromeDelegateCommand(chrome_exe));
......@@ -234,8 +234,8 @@ class RegistryEntry {
model_id_shell.append(ShellUtil::kRegShellPath);
// <root hkey>\Software\Classes\<app_id>\.exe\shell @=open
entries->push_front(new RegistryEntry(model_id_shell,
ShellUtil::kRegVerbOpen));
entries->push_back(new RegistryEntry(model_id_shell,
ShellUtil::kRegVerbOpen));
const wchar_t* const verbs[] = { ShellUtil::kRegVerbOpen,
ShellUtil::kRegVerbOpenNewWindow,
......@@ -246,15 +246,15 @@ class RegistryEntry {
sub_path.append(verbs[i]);
// <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
sub_path, L"CommandId", L"Browser.Launch"));
sub_path.push_back(FilePath::kSeparators[0]);
sub_path.append(ShellUtil::kRegCommand);
// <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>\command
entries->push_front(new RegistryEntry(sub_path, delegate_command));
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(sub_path, delegate_command));
entries->push_back(new RegistryEntry(
sub_path, ShellUtil::kRegDelegateExecute, delegate_guid));
}
}
......@@ -263,16 +263,16 @@ class RegistryEntry {
string16 chrome_html_prog_id(ShellUtil::kRegClasses);
chrome_html_prog_id.push_back(FilePath::kSeparators[0]);
chrome_html_prog_id.append(GetBrowserProgId(suffix));
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
chrome_html_prog_id, ShellUtil::kChromeHTMLProgIdDesc));
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
chrome_html_prog_id, ShellUtil::kRegUrlProtocol, L""));
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
chrome_html_prog_id + ShellUtil::kRegDefaultIcon, icon_path));
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
chrome_html_prog_id + ShellUtil::kRegShellOpen, open_cmd));
if (set_delegate_execute) {
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
chrome_html_prog_id + ShellUtil::kRegShellOpen,
ShellUtil::kRegDelegateExecute, delegate_guid));
}
......@@ -280,133 +280,153 @@ class RegistryEntry {
// The following entries are required as of Windows 8, but do not
// depend on the DelegateExecute verb handler being set.
if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
chrome_html_prog_id, ShellUtil::kRegAppUserModelId, app_id));
// Add \Software\Classes\ChromeHTML\Application entries
string16 chrome_application(chrome_html_prog_id +
ShellUtil::kRegApplication);
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
chrome_application, ShellUtil::kRegAppUserModelId, app_id));
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
chrome_application, ShellUtil::kRegApplicationIcon, icon_path));
// TODO(grt): http://crbug.com/75152 Write a reference to a localized
// resource for name, description, and company.
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
chrome_application, ShellUtil::kRegApplicationName,
dist->GetAppShortCutName()));
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
chrome_application, ShellUtil::kRegApplicationDescription,
dist->GetAppDescription()));
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
chrome_application, ShellUtil::kRegApplicationCompany,
dist->GetPublisherName()));
}
return true;
}
// This method returns a list of the registry entries needed to declare a
// capability of handling a protocol on Windows.
static bool GetProtocolCapabilityEntries(BrowserDistribution* dist,
const string16& suffix,
const string16& protocol,
std::list<RegistryEntry*>* entries) {
entries->push_front(new RegistryEntry(
static void GetProtocolCapabilityEntries(
BrowserDistribution* dist,
const string16& suffix,
const string16& protocol,
ScopedVector<RegistryEntry>* entries) {
entries->push_back(new RegistryEntry(
GetCapabilitiesKey(dist, suffix).append(L"\\URLAssociations"),
protocol, GetBrowserProgId(suffix)));
return true;
}
// This method returns a list of all the registry entries required to fully
// integrate Chrome with Windows (i.e. StartMenuInternet, Default Programs,
// AppPaths, etc.). This entries need to be registered in HKLM prior to Win8.
static bool GetShellIntegrationEntries(BrowserDistribution* dist,
// This method returns a list of the registry entries required to register
// this installation in "RegisteredApplications" on Windows (to appear in
// Default Programs, StartMenuInternet, etc.).
// These entries need to be registered in HKLM prior to Win8.
// If |suffix| is not empty, these entries are guaranteed to be unique on this
// machine.
static void GetShellIntegrationEntries(BrowserDistribution* dist,
const string16& chrome_exe,
const string16& suffix,
std::list<RegistryEntry*>* entries) {
string16 icon_path = ShellUtil::GetChromeIcon(dist, chrome_exe);
string16 quoted_exe_path = L"\"" + chrome_exe + L"\"";
ScopedVector<RegistryEntry>* entries) {
const string16 icon_path(ShellUtil::GetChromeIcon(dist, chrome_exe));
const string16 quoted_exe_path(L"\"" + chrome_exe + L"\"");
// Register for the Start Menu "Internet" link (pre-Win7).
const string16 start_menu_entry(GetBrowserClientKey(dist, suffix));
// Register Chrome's display name.
// TODO(grt): http://crbug.com/75152 Also set LocalizedString; see
// http://msdn.microsoft.com/en-us/library/windows/desktop/cc144109(v=VS.85).aspx#registering_the_display_name
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
start_menu_entry, dist->GetAppShortCutName()));
// Register the "open" verb for launching Chrome via the "Internet" link.
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
start_menu_entry + ShellUtil::kRegShellOpen, quoted_exe_path));
// Register Chrome's icon for the Start Menu "Internet" link.
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
start_menu_entry + ShellUtil::kRegDefaultIcon, icon_path));
// Register installation information.
string16 install_info(start_menu_entry + L"\\InstallInfo");
// Note: not using CommandLine since it has ambiguous rules for quoting
// strings.
entries->push_front(new RegistryEntry(install_info, kReinstallCommand,
entries->push_back(new RegistryEntry(install_info, kReinstallCommand,
quoted_exe_path + L" --" + ASCIIToWide(switches::kMakeDefaultBrowser)));
entries->push_front(new RegistryEntry(install_info, L"HideIconsCommand",
entries->push_back(new RegistryEntry(install_info, L"HideIconsCommand",
quoted_exe_path + L" --" + ASCIIToWide(switches::kHideIcons)));
entries->push_front(new RegistryEntry(install_info, L"ShowIconsCommand",
entries->push_back(new RegistryEntry(install_info, L"ShowIconsCommand",
quoted_exe_path + L" --" + ASCIIToWide(switches::kShowIcons)));
entries->push_front(new RegistryEntry(install_info, L"IconsVisible", 1));
entries->push_back(new RegistryEntry(install_info, L"IconsVisible", 1));
// Register with Default Programs.
string16 reg_app_name(dist->GetBaseAppName().append(suffix));
const string16 reg_app_name(dist->GetBaseAppName().append(suffix));
// Tell Windows where to find Chrome's Default Programs info.
string16 capabilities(GetCapabilitiesKey(dist, suffix));
entries->push_front(new RegistryEntry(ShellUtil::kRegRegisteredApplications,
const string16 capabilities(GetCapabilitiesKey(dist, suffix));
entries->push_back(new RegistryEntry(ShellUtil::kRegRegisteredApplications,
reg_app_name, capabilities));
// Write out Chrome's Default Programs info.
// TODO(grt): http://crbug.com/75152 Write a reference to a localized
// resource rather than this.
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
capabilities, ShellUtil::kRegApplicationDescription,
dist->GetLongAppDescription()));
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
capabilities, ShellUtil::kRegApplicationIcon, icon_path));
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
capabilities, ShellUtil::kRegApplicationName,
dist->GetAppShortCutName()));
entries->push_front(new RegistryEntry(capabilities + L"\\Startmenu",
entries->push_back(new RegistryEntry(capabilities + L"\\Startmenu",
L"StartMenuInternet", reg_app_name));
string16 html_prog_id(GetBrowserProgId(suffix));
const string16 html_prog_id(GetBrowserProgId(suffix));
for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
capabilities + L"\\FileAssociations",
ShellUtil::kFileAssociations[i], html_prog_id));
}
for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL;
i++) {
entries->push_front(new RegistryEntry(
entries->push_back(new RegistryEntry(
capabilities + L"\\URLAssociations",
ShellUtil::kPotentialProtocolAssociations[i], html_prog_id));
}
}
// Application Registration.
FilePath chrome_path(chrome_exe);
// This method returns a list of the registry entries required for this
// installation to be registered in the Windows shell.
// In particular:
// - App Paths
// http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121
// - File Associations
// http://msdn.microsoft.com/en-us/library/bb166549
// These entries should be registered in HKCU for user-level installs and in
// HKLM for system-level installs.
static void GetAppRegistrationEntries(const string16& chrome_exe,
const string16& suffix,
ScopedVector<RegistryEntry>* entries) {
const FilePath chrome_path(chrome_exe);
string16 app_path_key(ShellUtil::kAppPathsRegistryKey);
app_path_key.push_back(FilePath::kSeparators[0]);
app_path_key.append(chrome_path.BaseName().value());
entries->push_front(new RegistryEntry(app_path_key, chrome_exe));
entries->push_front(new RegistryEntry(app_path_key,
entries->push_back(new RegistryEntry(app_path_key, chrome_exe));
entries->push_back(new RegistryEntry(app_path_key,
ShellUtil::kAppPathsRegistryPathName, chrome_path.DirName().value()));
// TODO: add chrome to open with list (Bug 16726).
return true;
const string16 html_prog_id(GetBrowserProgId(suffix));
for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
string16 key(ShellUtil::kRegClasses);
key.push_back(FilePath::kSeparators[0]);
key.append(ShellUtil::kFileAssociations[i]);
key.push_back(FilePath::kSeparators[0]);
key.append(ShellUtil::kRegOpenWithProgids);
entries->push_back(new RegistryEntry(key, html_prog_id, string16()));
}
}
// This method returns a list of all the user level registry entries that
// are needed to make Chromium the default handler for a protocol.
static bool GetUserProtocolEntries(const string16& protocol,
static void GetUserProtocolEntries(const string16& protocol,
const string16& chrome_icon,
const string16& chrome_open,
std::list<RegistryEntry*>* entries) {
ScopedVector<RegistryEntry>* entries) {
// Protocols associations.
string16 url_key(ShellUtil::kRegClasses);
url_key.push_back(FilePath::kSeparators[0]);
......@@ -415,41 +435,43 @@ class RegistryEntry {
// This registry value tells Windows that this 'class' is a URL scheme
// so IE, explorer and other apps will route it to our handler.
// <root hkey>\Software\Classes\<protocol>\URL Protocol
entries->push_front(new RegistryEntry(url_key,
entries->push_back(new RegistryEntry(url_key,
ShellUtil::kRegUrlProtocol, L""));
// <root hkey>\Software\Classes\<protocol>\DefaultIcon
string16 icon_key = url_key + ShellUtil::kRegDefaultIcon;
entries->push_front(new RegistryEntry(icon_key, chrome_icon));
entries->push_back(new RegistryEntry(icon_key, chrome_icon));
// <root hkey>\Software\Classes\<protocol>\shell\open\command
string16 shell_key = url_key + ShellUtil::kRegShellOpen;
entries->push_front(new RegistryEntry(shell_key, chrome_open));
entries->push_back(new RegistryEntry(shell_key, chrome_open));
// <root hkey>\Software\Classes\<protocol>\shell\open\ddeexec
string16 dde_key = url_key + L"\\shell\\open\\ddeexec";
entries->push_front(new RegistryEntry(dde_key, L""));
entries->push_back(new RegistryEntry(dde_key, L""));
// <root hkey>\Software\Classes\<protocol>\shell\@
string16 protocol_shell_key = url_key + ShellUtil::kRegShellPath;
entries->push_front(new RegistryEntry(protocol_shell_key, L"open"));
return true;
entries->push_back(new RegistryEntry(protocol_shell_key, L"open"));
}
// This method returns a list of all the user level registry entries that
// are needed to make Chromium default browser.
static bool GetUserEntries(BrowserDistribution* dist,
const string16& chrome_exe,
const string16& suffix,
std::list<RegistryEntry*>* entries) {
// Some of these entries are irrelevant in recent versions of Windows, but
// we register them anyways as some legacy apps are hardcoded to lookup those
// values.
static void GetDefaultBrowserUserEntries(
BrowserDistribution* dist,
const string16& chrome_exe,
const string16& suffix,
ScopedVector<RegistryEntry>* entries) {
// File extension associations.
string16 html_prog_id(GetBrowserProgId(suffix));
for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
string16 ext_key(ShellUtil::kRegClasses);
ext_key.push_back(FilePath::kSeparators[0]);
ext_key.append(ShellUtil::kFileAssociations[i]);
entries->push_front(new RegistryEntry(ext_key, html_prog_id));
entries->push_back(new RegistryEntry(ext_key, html_prog_id));
}
// Protocols associations.
......@@ -463,8 +485,7 @@ class RegistryEntry {
// start->Internet shortcut.
string16 start_menu(ShellUtil::kRegStartMenuInternet);
string16 app_name = dist->GetBaseAppName() + suffix;
entries->push_front(new RegistryEntry(start_menu, app_name));
return true;
entries->push_back(new RegistryEntry(start_menu, app_name));
}
// Generate work_item tasks required to create current registry entry and
......@@ -566,10 +587,10 @@ class RegistryEntry {
// 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) {
bool AddRegistryEntries(HKEY root, const ScopedVector<RegistryEntry>& entries) {
scoped_ptr<WorkItemList> items(WorkItem::CreateWorkItemList());
for (std::list<RegistryEntry*>::const_iterator itr = entries.begin();
for (ScopedVector<RegistryEntry>::const_iterator itr = entries.begin();
itr != entries.end(); ++itr)
(*itr)->AddToWorkItemList(root, items.get());
......@@ -584,10 +605,10 @@ bool AddRegistryEntries(HKEY root, const std::list<RegistryEntry*>& entries) {
// Checks that all |entries| are present on this computer.
// |look_for_in| is passed to RegistryEntry::ExistsInRegistry(). Documentation
// for it can be found there.
bool AreEntriesRegistered(const std::list<RegistryEntry*>& entries,
bool AreEntriesRegistered(const ScopedVector<RegistryEntry>& entries,
uint32 look_for_in) {
bool registered = true;
for (std::list<RegistryEntry*>::const_iterator itr = entries.begin();
for (ScopedVector<RegistryEntry>::const_iterator itr = entries.begin();
registered && itr != entries.end(); ++itr) {
// We do not need registered = registered && ... since the loop condition
// is set to exit early.
......@@ -601,11 +622,10 @@ bool AreEntriesRegistered(const std::list<RegistryEntry*>& entries,
bool IsChromeRegistered(BrowserDistribution* dist,
const string16& chrome_exe,
const string16& suffix) {
std::list<RegistryEntry*> entries;
STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries);
ScopedVector<RegistryEntry> entries;
RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries);
RegistryEntry::GetShellIntegrationEntries(
dist, chrome_exe, suffix, &entries);
RegistryEntry::GetShellIntegrationEntries(dist, chrome_exe, suffix, &entries);
RegistryEntry::GetAppRegistrationEntries(chrome_exe, suffix, &entries);
return AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU_THEN_HKLM);
}
......@@ -614,8 +634,7 @@ bool IsChromeRegistered(BrowserDistribution* dist,
bool IsChromeRegisteredForProtocol(BrowserDistribution* dist,
const string16& suffix,
const string16& protocol) {
std::list<RegistryEntry*> entries;
STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries);
ScopedVector<RegistryEntry> entries;
RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, &entries);
return AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU_THEN_HKLM);
}
......@@ -868,6 +887,35 @@ HKEY DetermineShellIntegrationRoot(bool is_per_user) {
HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
}
// Associates Chrome with supported protocols and file 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+ as well.
bool RegisterChromeAsDefaultForXP(BrowserDistribution* dist,
int shell_change,
const string16& chrome_exe) {
bool ret = true;
ScopedVector<RegistryEntry> entries;
RegistryEntry::GetDefaultBrowserUserEntries(
dist, chrome_exe,
ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe), &entries);
// Change the default browser for current user.
if ((shell_change & ShellUtil::CURRENT_USER) &&
!AddRegistryEntries(HKEY_CURRENT_USER, entries)) {
ret = false;
LOG(ERROR) << "Could not make Chrome default browser (XP/current user).";
}
// Chrome as default browser at system level.
if ((shell_change & ShellUtil::SYSTEM_LEVEL) &&
!AddRegistryEntries(HKEY_LOCAL_MACHINE, entries)) {
ret = false;
LOG(ERROR) << "Could not make Chrome default browser (XP/system level).";
}
return ret;
}
} // namespace
const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon";
......@@ -914,6 +962,7 @@ const wchar_t* ShellUtil::kRegVerbOpenNewWindow = L"opennewwindow";
const wchar_t* ShellUtil::kRegVerbRun = L"run";
const wchar_t* ShellUtil::kRegCommand = L"command";
const wchar_t* ShellUtil::kRegDelegateExecute = L"DelegateExecute";
const wchar_t* ShellUtil::kRegOpenWithProgids = L"OpenWithProgids";
bool ShellUtil::QuickIsChromeRegisteredInHKLM(BrowserDistribution* dist,
const string16& chrome_exe,
......@@ -1288,29 +1337,8 @@ bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist,
}
}
// Now use the old way to associate Chrome with supported protocols and file
// 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);
RegistryEntry::GetUserEntries(
dist, chrome_exe, GetCurrentInstallationSuffix(dist, chrome_exe),
&entries);
// Change the default browser for current user.
if ((shell_change & ShellUtil::CURRENT_USER) &&
!AddRegistryEntries(HKEY_CURRENT_USER, entries)) {
if (!RegisterChromeAsDefaultForXP(dist, shell_change, chrome_exe))
ret = false;
LOG(ERROR) << "Could not make Chrome default browser (XP/current user).";
}
// Chrome as default browser at system level.
if ((shell_change & ShellUtil::SYSTEM_LEVEL) &&
!AddRegistryEntries(HKEY_LOCAL_MACHINE, entries)) {
ret = false;
LOG(ERROR) << "Could not make Chrome default browser (XP/system level).";
}
// Send Windows notification event so that it can update icons for
// file associations.
......@@ -1334,7 +1362,16 @@ bool ShellUtil::ShowMakeChromeDefaultSystemUI(BrowserDistribution* dist,
// control panel, which is a mess, or pop the concise "How you want to open
// webpages?" dialog. We choose the latter.
// Return true only when the user took an action and there was no error.
return LaunchSelectDefaultProtocolHandlerDialog(L"http");
const bool ret = LaunchSelectDefaultProtocolHandlerDialog(L"http");
if (ret) {
const int shell_change =
InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? CURRENT_USER :
SYSTEM_LEVEL;
RegisterChromeAsDefaultForXP(dist, shell_change, chrome_exe);
}
return ret;
}
bool ShellUtil::MakeChromeDefaultProtocolClient(BrowserDistribution* dist,
......@@ -1370,8 +1407,7 @@ bool ShellUtil::MakeChromeDefaultProtocolClient(BrowserDistribution* dist,
// 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);
ScopedVector<RegistryEntry> entries;
const string16 suffix(GetCurrentInstallationSuffix(dist, chrome_exe));
const string16 chrome_open(ShellUtil::GetChromeShellOpenCmd(chrome_exe));
const string16 chrome_icon(ShellUtil::GetChromeIcon(dist, chrome_exe));
......@@ -1413,16 +1449,17 @@ bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist,
// Do the full registration if we can do it at user-level or if the user is an
// admin.
if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) {
std::list<RegistryEntry*> progids;
STLElementDeleter<std::list<RegistryEntry*> > progids_deleter(&progids);
std::list<RegistryEntry*> shell_entries;
STLElementDeleter<std::list<RegistryEntry*> > shell_deleter(&shell_entries);
RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &progids);
ScopedVector<RegistryEntry> progid_and_appreg_entries;
ScopedVector<RegistryEntry> shell_entries;
RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix,
&progid_and_appreg_entries);
RegistryEntry::GetAppRegistrationEntries(chrome_exe, suffix,
&progid_and_appreg_entries);
RegistryEntry::GetShellIntegrationEntries(
dist, chrome_exe, suffix, &shell_entries);
return AddRegistryEntries(user_level ? HKEY_CURRENT_USER :
HKEY_LOCAL_MACHINE,
progids) &&
progid_and_appreg_entries) &&
AddRegistryEntries(root, shell_entries);
}
......@@ -1435,20 +1472,29 @@ bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist,
ElevateAndRegisterChrome(dist, chrome_exe, suffix, L""))
return true;
// If we got to this point then all we can do is create ProgIds under HKCU.
std::list<RegistryEntry*> entries;
STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries);
RegistryEntry::GetProgIdEntries(dist, chrome_exe, L"", &entries);
// If we got to this point then all we can do is create ProgId and basic app
// registrations under HKCU.
ScopedVector<RegistryEntry> entries;
RegistryEntry::GetProgIdEntries(dist, chrome_exe, string16(), &entries);
// Prefer to use |suffix|; unless Chrome's ProgIds are already registered with
// no suffix (as per the old registration style): in which case some other
// registry entries could refer to them and since we were not able to set our
// HKLM entries above, we are better off not altering these here.
if (!AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU)) {
if (!suffix.empty()) {
STLDeleteElements(&entries);
entries.clear();
RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries);
RegistryEntry::GetAppRegistrationEntries(chrome_exe, suffix, &entries);
}
return AddRegistryEntries(HKEY_CURRENT_USER, entries);
} else {
// The ProgId is registered unsuffixed in HKCU, also register the app with
// Windows in HKCU (this was not done in the old registration style and
// thus needs to be done after the above check for the unsuffixed
// registration).
entries.clear();
RegistryEntry::GetAppRegistrationEntries(chrome_exe, string16(), &entries);
return AddRegistryEntries(HKEY_CURRENT_USER, entries);
}
return true;
}
......@@ -1482,10 +1528,9 @@ bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist,
return false;
// Write in the capabillity for the protocol.
std::list<RegistryEntry*> entries;
STLElementDeleter<std::list<RegistryEntry*> > entries_deleter(&entries);
ScopedVector<RegistryEntry> entries;
RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol,
&entries);
&entries);
return AddRegistryEntries(root, entries);
} else if (elevate_if_not_admin &&
base::win::GetVersion() >= base::win::VERSION_VISTA) {
......
......@@ -124,6 +124,9 @@ class ShellUtil {
// Registry value name for the DelegateExecute verb handler.
static const wchar_t* kRegDelegateExecute;
// Registry value name for the OpenWithProgids entry for file associations.
static const wchar_t* kRegOpenWithProgids;
// Returns true if |chrome_exe| is registered in HKLM with |suffix|.
// Note: This only checks one deterministic key in HKLM for |chrome_exe| and
// doesn't otherwise validate a full Chrome install in HKLM.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment