summaryrefslogtreecommitdiffstats
path: root/chrome/installer/util
diff options
context:
space:
mode:
authorkoz@chromium.org <koz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-26 07:48:02 +0000
committerkoz@chromium.org <koz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-26 07:48:02 +0000
commit4468a5b324c9e1af0f756ccb4ba5f97a37892eb9 (patch)
tree467daa8d43f65986353d4f1bb5cf82e71cebd3a8 /chrome/installer/util
parente31d4c246deaefc59fe4f4fa66a74cd827694a41 (diff)
downloadchromium_src-4468a5b324c9e1af0f756ccb4ba5f97a37892eb9.zip
chromium_src-4468a5b324c9e1af0f756ccb4ba5f97a37892eb9.tar.gz
chromium_src-4468a5b324c9e1af0f756ccb4ba5f97a37892eb9.tar.bz2
Allow chrome to become the os default handler for arbitrary protocols on mac/win.
Note this is unused currently, but will be hooked up to navigator.registerProtocolHandler in a subsequent change. BUG=83556 TEST=Manual Review URL: http://codereview.chromium.org/6961013 Patch from Ben Wells <benwells@chromium.org>. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86793 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/installer/util')
-rw-r--r--chrome/installer/util/shell_util.cc265
-rw-r--r--chrome/installer/util/shell_util.h56
-rw-r--r--chrome/installer/util/util_constants.cc5
-rw-r--r--chrome/installer/util/util_constants.h1
4 files changed, 287 insertions, 40 deletions
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index 1d30439..6dad7c7 100644
--- a/chrome/installer/util/shell_util.cc
+++ b/chrome/installer/util/shell_util.cc
@@ -24,6 +24,7 @@
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "base/win/registry.h"
+#include "base/win/scoped_comptr.h"
#include "base/win/windows_version.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
@@ -70,6 +71,27 @@ class RegistryEntry {
return true;
}
+ // This method returns a list of the system level registry entries
+ // needed to declare a capability of handling a protocol.
+ static bool GetProtocolCapabilityEntries(BrowserDistribution* dist,
+ const std::wstring& chrome_exe,
+ const std::wstring& suffix,
+ const std::wstring& protocol,
+ std::list<RegistryEntry*>* entries) {
+ std::wstring app_name = dist->GetApplicationName() + suffix;
+ std::wstring start_menu_entry(ShellUtil::kRegStartMenuInternet);
+ start_menu_entry.append(L"\\" + app_name);
+
+ std::wstring capabilities(start_menu_entry + L"\\Capabilities");
+
+ std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId);
+ html_prog_id.append(suffix);
+ entries->push_front(new RegistryEntry(capabilities + L"\\URLAssociations",
+ protocol, html_prog_id));
+ 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(BrowserDistribution* dist,
@@ -119,10 +141,11 @@ class RegistryEntry {
capabilities + L"\\FileAssociations",
ShellUtil::kFileAssociations[i], html_prog_id));
}
- for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) {
+ for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL;
+ i++) {
entries->push_front(new RegistryEntry(
capabilities + L"\\URLAssociations",
- ShellUtil::kProtocolAssociations[i], html_prog_id));
+ ShellUtil::kPotentialProtocolAssociations[i], html_prog_id));
}
FilePath chrome_path(chrome_exe);
@@ -137,6 +160,44 @@ class RegistryEntry {
}
// 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(BrowserDistribution* dist,
+ const std::wstring& chrome_exe,
+ const std::wstring& suffix,
+ const std::wstring& protocol,
+ const std::wstring& chrome_icon,
+ const std::wstring& chrome_open,
+ std::list<RegistryEntry*>* entries) {
+ // Protocols associations.
+ std::wstring url_key(ShellUtil::kRegClasses);
+ file_util::AppendToPath(&url_key, 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_front(new RegistryEntry(url_key,
+ ShellUtil::kRegUrlProtocol, L""));
+
+ // <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"));
+
+ 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(BrowserDistribution* dist,
const std::wstring& chrome_exe,
@@ -154,25 +215,10 @@ class RegistryEntry {
// Protocols associations.
std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
std::wstring chrome_icon = ShellUtil::GetChromeIcon(dist, 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"));
+ for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) {
+ GetUserProtocolEntries(dist, chrome_exe, suffix,
+ ShellUtil::kBrowserProtocolAssociations[i],
+ chrome_icon, chrome_open, entries);
}
// start->Internet shortcut.
@@ -297,13 +343,36 @@ bool IsChromeRegistered(BrowserDistribution* dist,
return registered;
}
+// This method checks if Chrome is already registered on the local machine
+// for the requested protocol. It just checks the one value required for this.
+bool IsChromeRegisteredForProtocol(BrowserDistribution* dist,
+ const std::wstring& chrome_exe,
+ const std::wstring& suffix,
+ const std::wstring& protocol) {
+ bool registered = true;
+ std::list<RegistryEntry*> entries;
+ STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
+ RegistryEntry::GetProtocolCapabilityEntries(dist, chrome_exe, suffix,
+ protocol, &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 registers Chrome on Vista by launching an elevated setup.exe.
// That will show the user the standard Vista elevation prompt. If the user
// accepts it the new process will make the necessary changes and return SUCCESS
// that we capture and return.
+// If protocol is non-empty we will also register Chrome as being capable of
+// handling the protocol.
bool ElevateAndRegisterChrome(BrowserDistribution* dist,
const std::wstring& chrome_exe,
- const std::wstring& suffix) {
+ const std::wstring& suffix,
+ const std::wstring& protocol) {
FilePath exe_path =
FilePath::FromWStringHack(chrome_exe).DirName()
.Append(installer::kSetupExe);
@@ -331,6 +400,11 @@ bool ElevateAndRegisterChrome(BrowserDistribution* dist,
cmd.AppendSwitch(installer::switches::kChromeFrame);
}
+ if (!protocol.empty()) {
+ cmd.AppendSwitchNative(
+ installer::switches::kRegisterURLProtocol, protocol);
+ }
+
DWORD ret_val = 0;
InstallUtil::ExecuteExeAsAdmin(cmd, &ret_val);
if (ret_val == 0)
@@ -396,7 +470,6 @@ bool AnotherUserHasDefaultBrowser(BrowserDistribution* dist,
} // namespace
-
const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon";
const wchar_t* ShellUtil::kRegShellPath = L"\\shell";
const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command";
@@ -422,8 +495,10 @@ const wchar_t* ShellUtil::kChromeHTMLProgIdDesc = L"Chromium HTML Document";
const wchar_t* ShellUtil::kFileAssociations[] = {L".htm", L".html", L".shtml",
L".xht", L".xhtml", NULL};
-const wchar_t* ShellUtil::kProtocolAssociations[] = {L"ftp", L"http", L"https",
- NULL};
+const wchar_t* ShellUtil::kBrowserProtocolAssociations[] = {L"ftp", L"http",
+ L"https", NULL};
+const wchar_t* ShellUtil::kPotentialProtocolAssociations[] = {L"ftp", L"http",
+ L"https", L"mailto", L"webcal", NULL};
const wchar_t* ShellUtil::kRegUrlProtocol = L"URL Protocol";
bool ShellUtil::AdminNeededForRegistryCleanup(BrowserDistribution* dist,
@@ -636,22 +711,32 @@ bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist,
// browser.
if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
VLOG(1) << "Registering Chrome as default browser on Vista.";
- IApplicationAssociationRegistration* pAAR;
- HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
- NULL, CLSCTX_INPROC, __uuidof(IApplicationAssociationRegistration),
- (void**)&pAAR);
+ base::win::ScopedComPtr<IApplicationAssociationRegistration> pAAR;
+ HRESULT hr = pAAR.CreateInstance(CLSID_ApplicationAssociationRegistration,
+ NULL, CLSCTX_INPROC);
if (SUCCEEDED(hr)) {
std::wstring app_name = dist->GetApplicationName();
std::wstring suffix;
if (ShellUtil::GetUserSpecificDefaultBrowserSuffix(dist, &suffix))
app_name += suffix;
- hr = pAAR->SetAppAsDefaultAll(app_name.c_str());
- pAAR->Release();
+ for (int i = 0;
+ SUCCEEDED(hr) && ShellUtil::kBrowserProtocolAssociations[i] != NULL;
+ i++) {
+ hr = pAAR->SetAppAsDefault(app_name.c_str(),
+ ShellUtil::kBrowserProtocolAssociations[i], AT_URLPROTOCOL);
+ }
+
+ for (int i = 0;
+ SUCCEEDED(hr) && ShellUtil::kFileAssociations[i] != NULL; i++) {
+ hr = pAAR->SetAppAsDefault(app_name.c_str(),
+ ShellUtil::kFileAssociations[i], AT_FILEEXTENSION);
+ }
}
if (!SUCCEEDED(hr)) {
ret = false;
- LOG(ERROR) << "Could not make Chrome default browser.";
+ LOG(ERROR) << "Could not make Chrome default browser (Vista): HRESULT="
+ << hr << ".";
}
}
@@ -668,13 +753,17 @@ bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist,
RegistryEntry::GetUserEntries(dist, chrome_exe, suffix, &entries);
// Change the default browser for current user.
if ((shell_change & ShellUtil::CURRENT_USER) &&
- !AddRegistryEntries(HKEY_CURRENT_USER, entries))
- ret = false;
+ !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))
+ !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.
@@ -682,6 +771,61 @@ bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist,
return ret;
}
+bool ShellUtil::MakeChromeDefaultProtocolClient(BrowserDistribution* dist,
+ const std::wstring& chrome_exe,
+ const std::wstring& protocol) {
+ if (!dist->CanSetAsDefault())
+ return false;
+
+ ShellUtil::RegisterChromeForProtocol(dist, chrome_exe, L"", protocol, true);
+
+ bool ret = true;
+ // First use the new "recommended" way on Vista to make Chrome default
+ // protocol handler.
+ if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
+ VLOG(1) << "Registering Chrome as default handler for " << protocol
+ << " on Vista.";
+ base::win::ScopedComPtr<IApplicationAssociationRegistration> pAAR;
+ HRESULT hr = pAAR.CreateInstance(CLSID_ApplicationAssociationRegistration,
+ NULL, CLSCTX_INPROC);
+ if (SUCCEEDED(hr)) {
+ std::wstring app_name = dist->GetApplicationName();
+ std::wstring suffix;
+ if (ShellUtil::GetUserSpecificDefaultBrowserSuffix(dist, &suffix))
+ app_name += suffix;
+
+ hr = pAAR->SetAppAsDefault(app_name.c_str(), protocol.c_str(),
+ AT_URLPROTOCOL);
+ }
+ if (!SUCCEEDED(hr)) {
+ ret = false;
+ LOG(ERROR) << "Could not make Chrome default protocol client (Vista):"
+ << " HRESULT=" << hr << ".";
+ }
+ }
+
+ // Now use the old way to associate Chrome with the desired protocol. 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 (!GetUserSpecificDefaultBrowserSuffix(dist, &suffix))
+ suffix = L"";
+ std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
+ std::wstring chrome_icon = ShellUtil::GetChromeIcon(dist, chrome_exe);
+ RegistryEntry::GetUserProtocolEntries(dist, chrome_exe, suffix, protocol,
+ chrome_icon, chrome_open, &entries);
+ // Change the default protocol handler for current user.
+ if (!AddRegistryEntries(HKEY_CURRENT_USER, entries)) {
+ ret = false;
+ LOG(ERROR) << "Could not make Chrome default protocol client (XP).";
+ }
+
+ return ret;
+}
+
bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist,
const std::wstring& chrome_exe,
const std::wstring& unique_suffix,
@@ -716,7 +860,7 @@ bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist,
// If user is not an admin and OS is Vista, try to elevate and register.
if (elevate_if_not_admin &&
base::win::GetVersion() >= base::win::VERSION_VISTA &&
- ElevateAndRegisterChrome(dist, chrome_exe, suffix))
+ ElevateAndRegisterChrome(dist, chrome_exe, suffix, L""))
return true;
// If we got to this point then all we can do is create ProgIds under HKCU
@@ -727,6 +871,55 @@ bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist,
return AddRegistryEntries(HKEY_CURRENT_USER, entries);
}
+bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist,
+ const std::wstring& chrome_exe,
+ const std::wstring& unique_suffix,
+ const std::wstring& protocol,
+ bool elevate_if_not_admin) {
+ if (!dist->CanSetAsDefault())
+ return false;
+
+ // 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()) &&
+ !GetUserSpecificDefaultBrowserSuffix(dist, &suffix) &&
+ !AnotherUserHasDefaultBrowser(dist, chrome_exe)) {
+ suffix = L"";
+ }
+
+ // Check if Chromium is already registered with this suffix.
+ if (IsChromeRegisteredForProtocol(dist, chrome_exe, suffix, protocol))
+ return true;
+
+ if (IsUserAnAdmin()) {
+ // We can do this operation directly.
+ // If we're not registered at all, try to register. If that fails
+ // we should give up.
+ if (!IsChromeRegistered(dist, chrome_exe, suffix) &&
+ !RegisterChromeBrowser(dist, chrome_exe, suffix, false)) {
+ return false;
+ }
+
+ // Write in the capabillity for the protocol.
+ std::list<RegistryEntry*> entries;
+ STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
+ RegistryEntry::GetProtocolCapabilityEntries(dist, chrome_exe, suffix,
+ protocol, &entries);
+ return AddRegistryEntries(HKEY_LOCAL_MACHINE, entries);
+ } else if (elevate_if_not_admin &&
+ base::win::GetVersion() >= base::win::VERSION_VISTA) {
+ // Elevate to do the whole job
+ return ElevateAndRegisterChrome(dist, chrome_exe, suffix, protocol);
+ } else {
+ // we need admin rights to register our capability. If we don't
+ // have them and can't elevate, give up.
+ return false;
+ }
+}
+
bool ShellUtil::RemoveChromeDesktopShortcut(BrowserDistribution* dist,
int shell_change, bool alternate) {
std::wstring shortcut_name;
diff --git a/chrome/installer/util/shell_util.h b/chrome/installer/util/shell_util.h
index b34f4f6..fcb0fb8 100644
--- a/chrome/installer/util/shell_util.h
+++ b/chrome/installer/util/shell_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
//
@@ -30,6 +30,9 @@ class ShellUtil {
SYSTEM_LEVEL = 0x2 // Make any shell changes only at the system level
};
+ // Relative path of the URL Protocol registry entry (prefixed with '\').
+ static const wchar_t* kRegURLProtocol;
+
// Relative path of DefaultIcon registry entry (prefixed with '\').
static const wchar_t* kRegDefaultIcon;
@@ -69,8 +72,12 @@ class ShellUtil {
// File extensions that Chrome registers itself for.
static const wchar_t* kFileAssociations[];
- // Protocols that Chrome registers itself for.
- static const wchar_t* kProtocolAssociations[];
+ // Protocols that Chrome registers itself as the default handler for
+ // when the user makes Chrome the default browser.
+ static const wchar_t* kBrowserProtocolAssociations[];
+
+ // Protocols that Chrome registers itself as being capable of handling.
+ static const wchar_t* kPotentialProtocolAssociations[];
// Registry value name that is needed for ChromeHTML ProgId
static const wchar_t* kRegUrlProtocol;
@@ -156,7 +163,18 @@ class ShellUtil {
static bool GetUserSpecificDefaultBrowserSuffix(BrowserDistribution* dist,
std::wstring* entry);
- // Make Chrome default browser.
+ // Make Chrome the default browser. This function works by going through
+ // the url protocols and file associations that are related to general
+ // browsing, e.g. http, https, .html etc., and requesting to become the
+ // default handler for each. If any of these fails the operation will return
+ // false to indicate failure, which is consistent with the return value of
+ // ShellIntegration::IsDefaultBrowser.
+ //
+ // In the case of failure any successful changes will be left, however no
+ // more changes will be attempted.
+ // TODO(benwells): Attempt to undo any changes that were successfully made.
+ // http://crbug.com/83970
+ //
// shell_change: Defined whether to register as default browser at system
// level or user level. If value has ShellChange::SYSTEM_LEVEL
// we should be running as admin user.
@@ -168,6 +186,13 @@ class ShellUtil {
const std::wstring& chrome_exe,
bool elevate_if_not_admin);
+ // Make Chrome the default application for a protocol.
+ // chrome_exe: The chrome.exe path to register as default browser.
+ // protocol: The protocol to register as the default handler for.
+ static bool MakeChromeDefaultProtocolClient(BrowserDistribution* dist,
+ const std::wstring& chrome_exe,
+ const std::wstring& protocol);
+
// This method adds Chrome to the list that shows up in Add/Remove Programs->
// Set Program Access and Defaults and also creates Chrome ProgIds under
// Software\Classes. This method requires write access to HKLM so is just
@@ -194,6 +219,29 @@ class ShellUtil {
const std::wstring& unique_suffix,
bool elevate_if_not_admin);
+ // This method declares to Windows that Chrome is capable of handling the
+ // given protocol. This function will call the RegisterChromeBrowser function
+ // to register with Windows as capable of handling the protocol, if it isn't
+ // currently registered as capable.
+ // Declaring the capability of handling a protocol is necessary to register
+ // as the default handler for the protocol in Vista and later versions of
+ // Windows.
+ //
+ // If called by the browser and elevation is required, it will elevate by
+ // calling setup.exe which will again call this function with elevate false.
+ //
+ // |chrome_exe| full path to chrome.exe.
+ // |unique_suffix| Optional input. If given, this function appends the value
+ // to default browser entries names that it creates in the registry.
+ // |protocol| The protocol to register as being capable of handling.s
+ // |elevate_if_not_admin| if true will make this method try alternate methods
+ // as described above.
+ static bool RegisterChromeForProtocol(BrowserDistribution* dist,
+ const std::wstring& chrome_exe,
+ const std::wstring& unique_suffix,
+ const std::wstring& protocol,
+ bool elevate_if_not_admin);
+
// Remove Chrome shortcut from Desktop.
// If shell_change is CURRENT_USER, the shortcut is removed from the
// Desktop folder of current user's profile.
diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc
index bd92223..bfc1007 100644
--- a/chrome/installer/util/util_constants.cc
+++ b/chrome/installer/util/util_constants.cc
@@ -106,6 +106,11 @@ const char kRegisterChromeBrowser[] = "register-chrome-browser";
const char kRegisterChromeBrowserSuffix[] =
"register-chrome-browser-suffix";
+// Switch to allow an extra URL protocol to be registered. This option is used
+// in conjunction with kRegisterChromeBrowser to specify an extra protocol
+// in addition to the standard set of protocols.
+const char kRegisterURLProtocol[] = "register-url-protocol";
+
// Renames chrome.exe to old_chrome.exe and renames new_chrome.exe to chrome.exe
// to support in-use updates. Also deletes opv key.
const char kRenameChromeExe[] = "rename-chrome-exe";
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h
index 9153b7b..16cb791 100644
--- a/chrome/installer/util/util_constants.h
+++ b/chrome/installer/util/util_constants.h
@@ -136,6 +136,7 @@ extern const char kMultiInstall[];
extern const char kNewSetupExe[];
extern const char kRegisterChromeBrowser[];
extern const char kRegisterChromeBrowserSuffix[];
+extern const char kRegisterURLProtocol[];
extern const char kRenameChromeExe[];
extern const char kRemoveChromeRegistration[];
extern const char kRunAsAdmin[];