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

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

Issue 487693002: ShellUtil: Add generic methods to add/delete Windows file associations. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added TODO. Created 6 years, 3 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
Index: chrome/installer/util/shell_util.cc
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index 1e67163d9173198f8f002a714d59d160dfbf932c..c30feaa7135198ee69ea9c76403213c5d206db9b 100644
--- a/chrome/installer/util/shell_util.cc
+++ b/chrome/installer/util/shell_util.cc
@@ -191,6 +191,51 @@ class RegistryEntry {
LOOK_IN_HKCU_THEN_HKLM = LOOK_IN_HKCU | LOOK_IN_HKLM,
};
+ // Details about a Windows application, to be entered into the registry for
+ // the purpose of file associations.
+ struct ApplicationInfo {
+ ApplicationInfo()
+ : set_delegate_execute(false),
+ file_type_icon_index(0),
+ application_icon_index(0) {}
+
+ // The unique internal name Windows will use for file associations with this
grt (UTC plus 2) 2014/10/01 16:28:38 instead of "unique internal name," which doesn't s
Matt Giuca 2014/10/02 09:36:34 Done.
+ // application.
+ base::string16 prog_id;
+ // The friendly name, and the path of the icon that will be used for files
+ // of these types when associated with this application by default. (They
+ // are NOT the name/icon that will represent the application under the Open
+ // With menu.)
+ base::string16 file_type_name;
+ // TODO(mgiuca): |file_type_icon_path| should be a base::FilePath.
+ base::string16 file_type_icon_path;
+ int file_type_icon_index;
+ // The command to execute when opening a file via this association. It
+ // should contain "%1" to pass the filename as an argument.
grt (UTC plus 2) 2014/10/01 16:28:38 should or must? what happens if it doesn't?
Matt Giuca 2014/10/02 09:36:33 Then the filename won't get passed as an argument.
+ // TODO(mgiuca): |command_line| should be a base::CommandLine.
+ base::string16 command_line;
+ // The unique internal name used by Windows 8 for this application. Distinct
grt (UTC plus 2) 2014/10/01 16:28:38 where possible, please use the same terminology as
Matt Giuca 2014/10/02 09:36:34 Done.
+ // from |prog_id|. May be empty.
+ base::string16 app_id;
+
+ // User-visible details about this application. Any of these may be empty.
+ base::string16 application_name;
+ // TODO(mgiuca): |application_icon_path| should be a base::FilePath.
+ base::string16 application_icon_path;
+ int application_icon_index;
+ base::string16 application_description;
+ base::string16 publisher_name;
+
+ // Whether the application will have a DelegateExecute key. This should only
+ // be used by Windows 8 Metro web browsers (i.e. Chrome itself). All other
+ // fields in this section are ignored if this is false.
+ bool set_delegate_execute;
+ // A GUID for this application.
grt (UTC plus 2) 2014/10/01 16:28:38 // The CLSID for the application's DelegateExecute
Matt Giuca 2014/10/02 09:36:34 Done.
+ base::string16 delegate_guid;
grt (UTC plus 2) 2014/10/01 16:28:38 delegate_clsid
Matt Giuca 2014/10/02 09:36:34 Done.
+ // The command to execute when opening this application via the Metro UI.
+ base::string16 delegate_command;
+ };
+
// Returns the Windows browser client registration key for Chrome. For
// example: "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly
// speaking, we should use the name of the executable (e.g., "chrome.exe"),
@@ -218,32 +263,50 @@ class RegistryEntry {
// This method returns a list of all the registry entries that
// are needed to register this installation's ProgId and AppId.
// These entries need to be registered in HKLM prior to Win8.
- static void GetProgIdEntries(BrowserDistribution* dist,
- const base::string16& chrome_exe,
- const base::string16& suffix,
- ScopedVector<RegistryEntry>* entries) {
- base::string16 icon_path(
- ShellUtil::FormatIconLocation(
- chrome_exe,
- dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME)));
- base::string16 open_cmd(ShellUtil::GetChromeShellOpenCmd(chrome_exe));
- base::string16 delegate_command(
- ShellUtil::GetChromeDelegateCommand(chrome_exe));
- // For user-level installs: entries for the app id and DelegateExecute verb
- // handler will be in HKCU; thus we do not need a suffix on those entries.
- base::string16 app_id(
- ShellUtil::GetBrowserModelId(
- dist, InstallUtil::IsPerUserInstall(chrome_exe.c_str())));
- base::string16 delegate_guid;
- bool set_delegate_execute =
- IsChromeMetroSupported() &&
- dist->GetCommandExecuteImplClsid(&delegate_guid);
+ static void GetChromeProgIdEntries(BrowserDistribution* dist,
+ const base::string16& 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.c_str()));
// DelegateExecute ProgId. Needed for Chrome Metro in Windows 8.
- if (set_delegate_execute) {
+ app_info.delegate_command = ShellUtil::GetChromeDelegateCommand(chrome_exe);
+ app_info.set_delegate_execute =
+ IsChromeMetroSupported() &&
+ dist->GetCommandExecuteImplClsid(&app_info.delegate_guid);
+
+ // 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();
+
+ GetProgIdEntries(app_info, entries);
+ }
+
+ // Gets the registry entries to register an application in the Windows
+ // registry. |app_info| provides all of the information needed.
+ static void GetProgIdEntries(const ApplicationInfo& app_info,
+ ScopedVector<RegistryEntry>* entries) {
+ if (app_info.set_delegate_execute) {
base::string16 model_id_shell(ShellUtil::kRegClasses);
grt (UTC plus 2) 2014/10/01 16:28:38 DCHECK_NE(std::string16(), app_info.app_id); and o
Matt Giuca 2014/10/02 09:36:34 No longer applies (reverted all this code).
model_id_shell.push_back(base::FilePath::kSeparators[0]);
- model_id_shell.append(app_id);
+ model_id_shell.append(app_info.app_id);
model_id_shell.append(ShellUtil::kRegExePath);
model_id_shell.append(ShellUtil::kRegShellPath);
@@ -251,11 +314,11 @@ class RegistryEntry {
entries->push_back(new RegistryEntry(model_id_shell,
ShellUtil::kRegVerbOpen));
- // 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:
+ // Each shortcut 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
const struct {
const wchar_t* verb;
@@ -277,6 +340,8 @@ class RegistryEntry {
installer::GetLocalizedString(verbs[i].name_id));
entries->push_back(new RegistryEntry(sub_path, verb_name.c_str()));
}
+ // TODO(mgiuca): Generalize this or move it into the Chrome-specific
+ // code. DO NOT SUBMIT.
grt (UTC plus 2) 2014/10/01 16:28:38 DO NOT SUBMIT?
Matt Giuca 2014/10/02 09:36:34 It just means I'm planning to do this before submi
gab 2014/10/02 13:03:59 Nice, didn't know about this trick, I was using a
entries->push_back(new RegistryEntry(
sub_path, L"CommandId", L"Browser.Launch"));
@@ -284,52 +349,70 @@ class RegistryEntry {
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, app_info.delegate_command));
entries->push_back(new RegistryEntry(
- sub_path, ShellUtil::kRegDelegateExecute, delegate_guid));
+ sub_path, ShellUtil::kRegDelegateExecute, app_info.delegate_guid));
}
}
// File association ProgId
- base::string16 chrome_html_prog_id(ShellUtil::kRegClasses);
- chrome_html_prog_id.push_back(base::FilePath::kSeparators[0]);
- chrome_html_prog_id.append(GetBrowserProgId(suffix));
- entries->push_back(new RegistryEntry(
- chrome_html_prog_id, dist->GetBrowserProgIdDesc()));
+ 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(
- chrome_html_prog_id + ShellUtil::kRegDefaultIcon, icon_path));
+ prog_id_path + ShellUtil::kRegDefaultIcon,
+ ShellUtil::FormatIconLocation(app_info.file_type_icon_path,
+ app_info.file_type_icon_index)));
entries->push_back(new RegistryEntry(
- chrome_html_prog_id + ShellUtil::kRegShellOpen, open_cmd));
- if (set_delegate_execute) {
- entries->push_back(new RegistryEntry(
- chrome_html_prog_id + ShellUtil::kRegShellOpen,
- ShellUtil::kRegDelegateExecute, delegate_guid));
+ prog_id_path + ShellUtil::kRegShellOpen, app_info.command_line));
+ if (app_info.set_delegate_execute) {
+ entries->push_back(
+ new RegistryEntry(prog_id_path + ShellUtil::kRegShellOpen,
+ ShellUtil::kRegDelegateExecute,
+ app_info.delegate_guid));
}
// 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_back(new RegistryEntry(
- chrome_html_prog_id, ShellUtil::kRegAppUserModelId, app_id));
+ if (!app_info.app_id.empty()) {
+ entries->push_back(new RegistryEntry(
+ prog_id_path, ShellUtil::kRegAppUserModelId, app_info.app_id));
+ }
- // Add \Software\Classes\ChromeHTML\Application entries
- base::string16 chrome_application(chrome_html_prog_id +
- ShellUtil::kRegApplication);
- entries->push_back(new RegistryEntry(
- chrome_application, ShellUtil::kRegAppUserModelId, app_id));
- 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_back(new RegistryEntry(
- chrome_application, ShellUtil::kRegApplicationName,
- dist->GetDisplayName()));
- entries->push_back(new RegistryEntry(
- chrome_application, ShellUtil::kRegApplicationDescription,
- dist->GetAppDescription()));
- entries->push_back(new RegistryEntry(
- chrome_application, ShellUtil::kRegApplicationCompany,
- dist->GetPublisherName()));
+ // 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));
+ }
}
}
@@ -433,9 +516,10 @@ class RegistryEntry {
// - File Associations
// http://msdn.microsoft.com/en-us/library/bb166549
// These entries need to be registered in HKLM prior to Win8.
- static void GetAppRegistrationEntries(const base::string16& chrome_exe,
- const base::string16& suffix,
- ScopedVector<RegistryEntry>* entries) {
+ static void GetChromeAppRegistrationEntries(
+ const base::string16& chrome_exe,
+ const base::string16& suffix,
+ ScopedVector<RegistryEntry>* entries) {
const base::FilePath chrome_path(chrome_exe);
base::string16 app_path_key(ShellUtil::kAppPathsRegistryKey);
app_path_key.push_back(base::FilePath::kSeparators[0]);
@@ -446,13 +530,49 @@ class RegistryEntry {
const base::string16 html_prog_id(GetBrowserProgId(suffix));
for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) {
- base::string16 key(ShellUtil::kRegClasses);
- key.push_back(base::FilePath::kSeparators[0]);
- key.append(ShellUtil::kPotentialFileAssociations[i]);
- key.push_back(base::FilePath::kSeparators[0]);
- key.append(ShellUtil::kRegOpenWithProgids);
- entries->push_back(
- new RegistryEntry(key, html_prog_id, base::string16()));
+ GetAppExtRegistrationEntries(
+ html_prog_id, ShellUtil::kPotentialFileAssociations[i], entries);
+ }
+ }
+
+ // Gets the registry entries to register an application as a handler for a
+ // particular file extension. |prog_id| is the unique internal name Windows
+ // uses for the application. |ext| is the file extension, which must begin
+ // with a '.'.
+ static void GetAppExtRegistrationEntries(
+ const base::string16& prog_id,
+ const base::string16& ext,
+ ScopedVector<RegistryEntry>* entries) {
+ // In HKEY_CLASSES_ROOT\EXT\OpenWithProgids, create an empty value with this
+ // class's prog_id.
+ 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()));
+ }
+
+ // Gets the registry entries to register an application as the default handler
+ // for a particular file extension. |prog_id| is the unique internal name
+ // Windows uses for the application. |ext| is the file extension, which must
+ // begin with a '.'. If |overwrite_existing|, always sets the default handler;
+ // otherwise only sets if there is no existing default.
+ static void GetAppDefaultRegistrationEntries(
+ const base::string16& prog_id,
+ const base::string16& ext,
+ bool overwrite_existing,
+ ScopedVector<RegistryEntry>* entries) {
+ // Set the default value of HKEY_CLASSES_ROOT\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)) {
grt (UTC plus 2) 2014/10/01 16:28:38 is HKCU correct here? the comment above says HKCR.
Matt Giuca 2014/10/02 09:36:33 Done.
+ entries->push_back(default_association.release());
}
}
@@ -504,10 +624,8 @@ class RegistryEntry {
// File extension associations.
base::string16 html_prog_id(GetBrowserProgId(suffix));
for (int i = 0; ShellUtil::kDefaultFileAssociations[i] != NULL; i++) {
- base::string16 ext_key(ShellUtil::kRegClasses);
- ext_key.push_back(base::FilePath::kSeparators[0]);
- ext_key.append(ShellUtil::kDefaultFileAssociations[i]);
- entries->push_back(new RegistryEntry(ext_key, html_prog_id));
+ GetAppDefaultRegistrationEntries(
+ html_prog_id, ShellUtil::kDefaultFileAssociations[i], true, entries);
}
// Protocols associations.
@@ -563,6 +681,21 @@ class RegistryEntry {
return status == SAME_VALUE;
}
+ // Checks if the current registry entry exists in \|key_path_|\|name_|,
+ // regardless of value. Same lookup rules as ExistsInRegistry.
+ // Unlike ExistsInRegistry, this returns true if some other value is present
+ // with the same key.
+ bool KeyExistsInRegistry(uint32 look_for_in) const {
+ DCHECK(look_for_in);
+
+ RegistryStatus status = DOES_NOT_EXIST;
+ if (look_for_in & LOOK_IN_HKCU)
+ status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER);
+ if (status == DOES_NOT_EXIST && (look_for_in & LOOK_IN_HKLM))
+ status = StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE);
+ return status != DOES_NOT_EXIST;
+ }
+
private:
// States this RegistryKey can be in compared to the registry.
enum RegistryStatus {
@@ -676,9 +809,9 @@ bool IsChromeRegistered(BrowserDistribution* dist,
const base::string16& suffix,
uint32 look_for_in) {
ScopedVector<RegistryEntry> entries;
- RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries);
+ RegistryEntry::GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries);
RegistryEntry::GetShellIntegrationEntries(dist, chrome_exe, suffix, &entries);
- RegistryEntry::GetAppRegistrationEntries(chrome_exe, suffix, &entries);
+ RegistryEntry::GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries);
return AreEntriesRegistered(entries, look_for_in);
}
@@ -2063,10 +2196,10 @@ bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist,
// an admin.
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::GetChromeProgIdEntries(
+ dist, chrome_exe, suffix, &progid_and_appreg_entries);
+ RegistryEntry::GetChromeAppRegistrationEntries(
+ chrome_exe, suffix, &progid_and_appreg_entries);
RegistryEntry::GetShellIntegrationEntries(
dist, chrome_exe, suffix, &shell_entries);
result = (AddRegistryEntries(root, progid_and_appreg_entries) &&
@@ -2083,7 +2216,7 @@ bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist,
// 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(
+ RegistryEntry::GetChromeProgIdEntries(
dist, chrome_exe, base::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
@@ -2092,8 +2225,10 @@ bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist,
if (!AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU)) {
if (!suffix.empty()) {
entries.clear();
- RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries);
- RegistryEntry::GetAppRegistrationEntries(chrome_exe, suffix, &entries);
+ RegistryEntry::GetChromeProgIdEntries(
+ dist, chrome_exe, suffix, &entries);
+ RegistryEntry::GetChromeAppRegistrationEntries(
+ chrome_exe, suffix, &entries);
}
result = AddRegistryEntries(HKEY_CURRENT_USER, entries);
} else {
@@ -2102,8 +2237,8 @@ bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist,
// thus needs to be done after the above check for the unsuffixed
// registration).
entries.clear();
- RegistryEntry::GetAppRegistrationEntries(chrome_exe, base::string16(),
- &entries);
+ RegistryEntry::GetChromeAppRegistrationEntries(
+ chrome_exe, base::string16(), &entries);
result = AddRegistryEntries(HKEY_CURRENT_USER, entries);
}
}
@@ -2292,3 +2427,54 @@ base::string16 ShellUtil::ByteArrayToBase32(const uint8* bytes, size_t size) {
DCHECK_EQ(ret.length(), encoded_length);
return ret;
}
+
+// static
+bool ShellUtil::AddFileAssociations(
+ const base::string16& progid,
+ const base::CommandLine& command_line,
+ const base::string16& file_type_name,
+ const base::FilePath& icon_path,
+ const std::set<base::string16>& file_extensions) {
+ ScopedVector<RegistryEntry> entries;
grt (UTC plus 2) 2014/10/01 16:28:38 DCHECK that command_line contains %1?
Matt Giuca 2014/10/02 09:36:34 I don't know if we want that. It's still a valid f
+
+ // Create a class for this app.
+ RegistryEntry::ApplicationInfo app_info;
+ app_info.prog_id = progid;
+ app_info.file_type_name = file_type_name;
+ app_info.file_type_icon_path = icon_path.value();
+ app_info.file_type_icon_index = 0;
+ app_info.command_line = command_line.GetCommandLineString();
+ RegistryEntry::GetProgIdEntries(app_info, &entries);
+
+ // Associate each extension that the app can handle with the class. Set this
+ // app as the default handler if and only if there is no existing default.
+ for (std::set<base::string16>::const_iterator it = file_extensions.begin();
+ it != file_extensions.end();
+ ++it) {
+ // TODO(mgiuca): Do we allow empty file extensions?
+ // TODO(mgiuca): Do we allow file extensions with a '.' in them?
+ DCHECK(!it->empty());
+ DCHECK((*it)[0] != L'.');
+ base::string16 ext(1, L'.');
+ ext.append(*it);
+ RegistryEntry::GetAppExtRegistrationEntries(progid, ext, &entries);
+ RegistryEntry::GetAppDefaultRegistrationEntries(
+ progid, ext, false, &entries);
+ }
+
+ return AddRegistryEntries(HKEY_CURRENT_USER, entries);
+}
+
+// static
+bool ShellUtil::DeleteFileAssociations(const base::string16& progid) {
+ // Delete the key HKEY_CLASSES_ROOT\PROGID.
+ base::string16 key_path(ShellUtil::kRegClasses);
+ key_path.push_back(base::FilePath::kSeparators[0]);
+ key_path.append(progid);
+ return InstallUtil::DeleteRegistryKey(
+ HKEY_CURRENT_USER, key_path, WorkItem::kWow64Default);
+
+ // TODO(mgiuca): Remove the extension association entries. This requires that
+ // the extensions associated with a particular prog_id are stored in that
+ // prog_id's key.
+}

Powered by Google App Engine
This is Rietveld 408576698