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

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

Issue 1578833003: Moved shell_util functions into new shell_registry_util module. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 11 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_registry_util.h ('k') | chrome/installer/util/shell_util.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/installer/util/shell_registry_util.cc
diff --git a/chrome/installer/util/shell_registry_util.cc b/chrome/installer/util/shell_registry_util.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b06afb4259c98195a5e36a5adae8b44af31d2d3c
--- /dev/null
+++ b/chrome/installer/util/shell_registry_util.cc
@@ -0,0 +1,421 @@
+// Copyright 2016 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.
+
+#include "chrome/installer/util/shell_registry_util.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/win/windows_version.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/installer_util_strings.h"
+#include "chrome/installer/util/l10n_string_util.h"
+#include "chrome/installer/util/registry_entry.h"
+#include "chrome/installer/util/shell_util.h"
+
+namespace installer_util {
+
+namespace {
+
+// Returns the current (or installed) browser's ProgId (e.g.
+// "ChromeHTML|suffix|").
+// |suffix| can be the empty string.
+base::string16 GetBrowserProgId(const base::string16& suffix) {
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ base::string16 chrome_html(dist->GetBrowserProgIdPrefix());
+ chrome_html.append(suffix);
+
+ // ProgIds cannot be longer than 39 characters.
+ // Ref: http://msdn.microsoft.com/en-us/library/aa911706.aspx.
+ // Make all new registrations comply with this requirement (existing
+ // registrations must be preserved).
+ base::string16 new_style_suffix;
+ if (ShellUtil::GetUserSpecificRegistrySuffix(&new_style_suffix) &&
+ suffix == new_style_suffix && chrome_html.length() > 39) {
+ NOTREACHED();
+ chrome_html.erase(39);
+ }
+ return chrome_html;
+}
+
+// Returns the Windows Default Programs capabilities key for Chrome. For
+// example:
+// "Software\Clients\StartMenuInternet\Chromium[.user]\Capabilities".
+base::string16 GetCapabilitiesKey(BrowserDistribution* dist,
+ const base::string16& suffix) {
+ return GetBrowserClientKey(dist, suffix).append(L"\\Capabilities");
+}
+
+// DelegateExecute ProgId. Needed for Chrome Metro in Windows 8. This is only
+// needed for registring a web browser, not for general associations.
+ScopedVector<RegistryEntry> GetChromeDelegateExecuteEntries(
+ const base::FilePath& chrome_exe,
+ const ApplicationInfo& app_info) {
+ ScopedVector<RegistryEntry> entries;
+
+ base::string16 app_id_shell_key(ShellUtil::kRegClasses);
+ app_id_shell_key.push_back(base::FilePath::kSeparators[0]);
+ app_id_shell_key.append(app_info.app_id);
+ app_id_shell_key.append(ShellUtil::kRegExePath);
+ app_id_shell_key.append(ShellUtil::kRegShellPath);
+
+ // <root hkey>\Software\Classes\<app_id>\.exe\shell @=open
+ entries.push_back(
+ new RegistryEntry(app_id_shell_key, ShellUtil::kRegVerbOpen));
+
+ // The command to execute when opening this application via the Metro UI.
+ const base::string16 delegate_command(
+ ShellUtil::GetChromeDelegateCommand(chrome_exe));
+
+ // Each of Chrome's shortcuts has an appid; which, as of Windows 8, is
+ // registered to handle some verbs. This registration has the side-effect
+ // that these verbs now show up in the shortcut's context menu. We
+ // mitigate this side-effect by making the context menu entries
+ // user readable/localized strings. See relevant MSDN article:
+ // http://msdn.microsoft.com/en-US/library/windows/desktop/cc144171.aspx
+ static const struct {
+ const wchar_t* verb;
+ int name_id;
+ } verbs[] = {
+ {ShellUtil::kRegVerbOpen, -1},
+ {ShellUtil::kRegVerbOpenNewWindow, IDS_SHORTCUT_NEW_WINDOW_BASE},
+ };
+ for (const auto& verb_and_id : verbs) {
+ base::string16 sub_path(app_id_shell_key);
+ sub_path.push_back(base::FilePath::kSeparators[0]);
+ sub_path.append(verb_and_id.verb);
+
+ // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>
+ if (verb_and_id.name_id != -1) {
+ // TODO(grt): http://crbug.com/75152 Write a reference to a localized
+ // resource.
+ const base::string16 verb_name(
+ installer::GetLocalizedString(verb_and_id.name_id));
+ entries.push_back(new RegistryEntry(sub_path, verb_name.c_str()));
+ }
+ entries.push_back(
+ new RegistryEntry(sub_path, L"CommandId", L"Browser.Launch"));
+
+ sub_path.push_back(base::FilePath::kSeparators[0]);
+ sub_path.append(ShellUtil::kRegCommand);
+
+ // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>\command
+ entries.push_back(new RegistryEntry(sub_path, delegate_command));
+ entries.push_back(new RegistryEntry(
+ sub_path, ShellUtil::kRegDelegateExecute, app_info.delegate_clsid));
+ }
+
+ return entries;
+}
+
+} // namespace
+
+const wchar_t kReinstallCommand[] = L"ReinstallCommand";
+
+base::string16 GetBrowserClientKey(BrowserDistribution* dist,
+ const base::string16& suffix) {
+ DCHECK(suffix.empty() || suffix[0] == L'.');
+ return base::string16(ShellUtil::kRegStartMenuInternet)
+ .append(1, L'\\')
+ .append(dist->GetBaseAppName())
+ .append(suffix);
+}
+
+void GetProgIdEntries(const ApplicationInfo& app_info,
+ ScopedVector<RegistryEntry>* entries) {
+ // Basic sanity checks.
+ DCHECK(!app_info.prog_id.empty());
+ DCHECK_NE(L'.', app_info.prog_id[0]);
+
+ // File association ProgId
+ base::string16 prog_id_path(ShellUtil::kRegClasses);
+ prog_id_path.push_back(base::FilePath::kSeparators[0]);
+ prog_id_path.append(app_info.prog_id);
+ entries->push_back(new RegistryEntry(prog_id_path, app_info.file_type_name));
+ entries->push_back(new RegistryEntry(
+ prog_id_path + ShellUtil::kRegDefaultIcon,
+ ShellUtil::FormatIconLocation(app_info.file_type_icon_path,
+ app_info.file_type_icon_index)));
+ entries->push_back(new RegistryEntry(prog_id_path + ShellUtil::kRegShellOpen,
+ app_info.command_line));
+ if (!app_info.delegate_clsid.empty()) {
+ entries->push_back(new RegistryEntry(
+ prog_id_path + ShellUtil::kRegShellOpen, ShellUtil::kRegDelegateExecute,
+ app_info.delegate_clsid));
+ // TODO(scottmg): Simplify after Metro removal. https://crbug.com/558054.
+ entries->back()->set_removal_flag(RegistryEntry::RemovalFlag::VALUE);
+ }
+
+ // 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) {
+ if (!app_info.app_id.empty()) {
+ entries->push_back(new RegistryEntry(
+ prog_id_path, ShellUtil::kRegAppUserModelId, app_info.app_id));
+ }
+
+ // Add \Software\Classes\<prog_id>\Application entries
+ base::string16 application_path(prog_id_path + ShellUtil::kRegApplication);
+ if (!app_info.app_id.empty()) {
+ entries->push_back(new RegistryEntry(
+ application_path, ShellUtil::kRegAppUserModelId, app_info.app_id));
+ }
+ if (!app_info.application_icon_path.empty()) {
+ entries->push_back(new RegistryEntry(
+ application_path, ShellUtil::kRegApplicationIcon,
+ ShellUtil::FormatIconLocation(app_info.application_icon_path,
+ app_info.application_icon_index)));
+ }
+ if (!app_info.application_name.empty()) {
+ entries->push_back(new RegistryEntry(application_path,
+ ShellUtil::kRegApplicationName,
+ app_info.application_name));
+ }
+ if (!app_info.application_description.empty()) {
+ entries->push_back(new RegistryEntry(
+ application_path, ShellUtil::kRegApplicationDescription,
+ app_info.application_description));
+ }
+ if (!app_info.publisher_name.empty()) {
+ entries->push_back(new RegistryEntry(application_path,
+ ShellUtil::kRegApplicationCompany,
+ app_info.publisher_name));
+ }
+ }
+}
+
+void GetChromeProgIdEntries(BrowserDistribution* dist,
+ const base::FilePath& chrome_exe,
+ const base::string16& suffix,
+ ScopedVector<RegistryEntry>* entries) {
+ int chrome_icon_index =
+ dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME);
+
+ ApplicationInfo app_info;
+ app_info.prog_id = GetBrowserProgId(suffix);
+ app_info.file_type_name = dist->GetBrowserProgIdDesc();
+ // File types associated with Chrome are just given the Chrome icon.
+ app_info.file_type_icon_path = chrome_exe;
+ app_info.file_type_icon_index = chrome_icon_index;
+ app_info.command_line = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
+ // For user-level installs: entries for the app id will be in HKCU; thus we
+ // do not need a suffix on those entries.
+ app_info.app_id = ShellUtil::GetBrowserModelId(
+ dist, InstallUtil::IsPerUserInstall(chrome_exe));
+
+ // TODO(grt): http://crbug.com/75152 Write a reference to a localized
+ // resource for name, description, and company.
+ app_info.application_name = dist->GetDisplayName();
+ app_info.application_icon_path = chrome_exe;
+ app_info.application_icon_index = chrome_icon_index;
+ app_info.application_description = dist->GetAppDescription();
+ app_info.publisher_name = dist->GetPublisherName();
+
+ app_info.delegate_clsid = dist->GetCommandExecuteImplClsid();
+
+ GetProgIdEntries(app_info, entries);
+
+ if (!app_info.delegate_clsid.empty()) {
+ ScopedVector<RegistryEntry> delegate_execute_entries =
+ GetChromeDelegateExecuteEntries(chrome_exe, app_info);
+ // Remove the keys (not only their values) so that Windows will continue
+ // to launch Chrome without a pesky association error.
+ // TODO(scottmg): Simplify after Metro removal. https://crbug.com/558054.
+ for (RegistryEntry* entry : delegate_execute_entries)
+ entry->set_removal_flag(RegistryEntry::RemovalFlag::KEY);
+ // Move |delegate_execute_entries| to |entries|.
+ entries->insert(entries->end(), delegate_execute_entries.begin(),
+ delegate_execute_entries.end());
+ delegate_execute_entries.weak_clear();
+ }
+}
+
+void GetProtocolCapabilityEntries(BrowserDistribution* dist,
+ const base::string16& suffix,
+ const base::string16& protocol,
+ ScopedVector<RegistryEntry>* entries) {
+ entries->push_back(new RegistryEntry(
+ GetCapabilitiesKey(dist, suffix).append(L"\\URLAssociations"), protocol,
+ GetBrowserProgId(suffix)));
+}
+
+void GetShellIntegrationEntries(BrowserDistribution* dist,
+ const base::FilePath& chrome_exe,
+ const base::string16& suffix,
+ ScopedVector<RegistryEntry>* entries) {
+ const base::string16 icon_path(ShellUtil::FormatIconLocation(
+ chrome_exe, dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME)));
+ const base::string16 quoted_exe_path(L"\"" + chrome_exe.value() + L"\"");
+
+ // Register for the Start Menu "Internet" link (pre-Win7).
+ const base::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_back(
+ new RegistryEntry(start_menu_entry, dist->GetDisplayName()));
+ // Register the "open" verb for launching Chrome via the "Internet" link.
+ 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_back(new RegistryEntry(
+ start_menu_entry + ShellUtil::kRegDefaultIcon, icon_path));
+
+ // Register installation information.
+ base::string16 install_info(start_menu_entry + L"\\InstallInfo");
+ // Note: not using CommandLine since it has ambiguous rules for quoting
+ // strings.
+ entries->push_back(
+ new RegistryEntry(install_info, kReinstallCommand,
+ quoted_exe_path + L" --" +
+ base::ASCIIToUTF16(switches::kMakeDefaultBrowser)));
+ entries->push_back(new RegistryEntry(
+ install_info, L"HideIconsCommand",
+ quoted_exe_path + L" --" + base::ASCIIToUTF16(switches::kHideIcons)));
+ entries->push_back(new RegistryEntry(
+ install_info, L"ShowIconsCommand",
+ quoted_exe_path + L" --" + base::ASCIIToUTF16(switches::kShowIcons)));
+ entries->push_back(new RegistryEntry(install_info, L"IconsVisible", 1));
+
+ // Register with Default Programs.
+ const base::string16 reg_app_name(dist->GetBaseAppName().append(suffix));
+ // Tell Windows where to find Chrome's Default Programs info.
+ const base::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_back(new RegistryEntry(capabilities,
+ ShellUtil::kRegApplicationDescription,
+ dist->GetLongAppDescription()));
+ entries->push_back(new RegistryEntry(
+ capabilities, ShellUtil::kRegApplicationIcon, icon_path));
+ entries->push_back(new RegistryEntry(
+ capabilities, ShellUtil::kRegApplicationName, dist->GetDisplayName()));
+
+ entries->push_back(new RegistryEntry(capabilities + L"\\Startmenu",
+ L"StartMenuInternet", reg_app_name));
+
+ const base::string16 html_prog_id(GetBrowserProgId(suffix));
+ for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) {
+ entries->push_back(new RegistryEntry(
+ capabilities + L"\\FileAssociations",
+ ShellUtil::kPotentialFileAssociations[i], html_prog_id));
+ }
+ for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL; i++) {
+ entries->push_back(new RegistryEntry(
+ capabilities + L"\\URLAssociations",
+ ShellUtil::kPotentialProtocolAssociations[i], html_prog_id));
+ }
+}
+
+void GetAppExtRegistrationEntries(const base::string16& prog_id,
+ const base::string16& ext,
+ ScopedVector<RegistryEntry>* entries) {
+ // In HKEY_CURRENT_USER\Software\Classes\EXT\OpenWithProgids, create an
+ // empty value with this class's ProgId.
+ base::string16 key_name(ShellUtil::kRegClasses);
+ key_name.push_back(base::FilePath::kSeparators[0]);
+ key_name.append(ext);
+ key_name.push_back(base::FilePath::kSeparators[0]);
+ key_name.append(ShellUtil::kRegOpenWithProgids);
+ entries->push_back(new RegistryEntry(key_name, prog_id, base::string16()));
+}
+
+void GetChromeAppRegistrationEntries(const base::FilePath& chrome_exe,
+ const base::string16& suffix,
+ ScopedVector<RegistryEntry>* entries) {
+ base::string16 app_path_key(ShellUtil::kAppPathsRegistryKey);
+ app_path_key.push_back(base::FilePath::kSeparators[0]);
+ app_path_key.append(chrome_exe.BaseName().value());
+ entries->push_back(new RegistryEntry(app_path_key, chrome_exe.value()));
+ entries->push_back(new RegistryEntry(app_path_key,
+ ShellUtil::kAppPathsRegistryPathName,
+ chrome_exe.DirName().value()));
+
+ const base::string16 html_prog_id(GetBrowserProgId(suffix));
+ for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) {
+ GetAppExtRegistrationEntries(
+ html_prog_id, ShellUtil::kPotentialFileAssociations[i], entries);
+ }
+}
+
+void GetAppDefaultRegistrationEntries(const base::string16& prog_id,
+ const base::string16& ext,
+ bool overwrite_existing,
+ ScopedVector<RegistryEntry>* entries) {
+ // Set the default value of HKEY_CURRENT_USER\Software\Classes\EXT to this
+ // class's name.
+ base::string16 key_name(ShellUtil::kRegClasses);
+ key_name.push_back(base::FilePath::kSeparators[0]);
+ key_name.append(ext);
+ scoped_ptr<RegistryEntry> default_association(
+ new RegistryEntry(key_name, prog_id));
+ if (overwrite_existing ||
+ !default_association->KeyExistsInRegistry(RegistryEntry::LOOK_IN_HKCU)) {
+ entries->push_back(default_association.release());
+ }
+}
+
+void GetXPStyleUserProtocolEntries(const base::string16& protocol,
+ const base::string16& chrome_icon,
+ const base::string16& chrome_open,
+ ScopedVector<RegistryEntry>* entries) {
+ // Protocols associations.
+ base::string16 url_key(ShellUtil::kRegClasses);
+ url_key.push_back(base::FilePath::kSeparators[0]);
+ url_key.append(protocol);
+
+ // 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_back(
+ new RegistryEntry(url_key, ShellUtil::kRegUrlProtocol, base::string16()));
+
+ // <root hkey>\Software\Classes\<protocol>\DefaultIcon
+ base::string16 icon_key = url_key + ShellUtil::kRegDefaultIcon;
+ entries->push_back(new RegistryEntry(icon_key, chrome_icon));
+
+ // <root hkey>\Software\Classes\<protocol>\shell\open\command
+ base::string16 shell_key = url_key + ShellUtil::kRegShellOpen;
+ entries->push_back(new RegistryEntry(shell_key, chrome_open));
+
+ // <root hkey>\Software\Classes\<protocol>\shell\open\ddeexec
+ base::string16 dde_key = url_key + L"\\shell\\open\\ddeexec";
+ entries->push_back(new RegistryEntry(dde_key, base::string16()));
+
+ // <root hkey>\Software\Classes\<protocol>\shell\@
+ base::string16 protocol_shell_key = url_key + ShellUtil::kRegShellPath;
+ entries->push_back(new RegistryEntry(protocol_shell_key, L"open"));
+}
+
+void GetXPStyleDefaultBrowserUserEntries(BrowserDistribution* dist,
+ const base::FilePath& chrome_exe,
+ const base::string16& suffix,
+ ScopedVector<RegistryEntry>* entries) {
+ // File extension associations.
+ base::string16 html_prog_id(GetBrowserProgId(suffix));
+ for (int i = 0; ShellUtil::kDefaultFileAssociations[i] != NULL; i++) {
+ GetAppDefaultRegistrationEntries(
+ html_prog_id, ShellUtil::kDefaultFileAssociations[i], true, entries);
+ }
+
+ // Protocols associations.
+ base::string16 chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
+ base::string16 chrome_icon = ShellUtil::FormatIconLocation(
+ chrome_exe, dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME));
+ for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) {
+ GetXPStyleUserProtocolEntries(ShellUtil::kBrowserProtocolAssociations[i],
+ chrome_icon, chrome_open, entries);
+ }
+
+ // start->Internet shortcut.
+ base::string16 start_menu(ShellUtil::kRegStartMenuInternet);
+ base::string16 app_name = dist->GetBaseAppName() + suffix;
+ entries->push_back(new RegistryEntry(start_menu, app_name));
+}
+
+} // namespace installer_util
« no previous file with comments | « chrome/installer/util/shell_registry_util.h ('k') | chrome/installer/util/shell_util.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698