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..6f7eece666d832fbb1c526749ab09c75724f5198 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 |
+ // 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. |
gab
2014/09/12 13:32:37
Agreed as that makes types more explicit, what pre
Matt Giuca
2014/09/15 03:49:46
Yes, I want to avoid touching heaps of other code
|
+ 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. |
+ // 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 |
+ // 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; |
gab
2014/09/12 13:32:37
This is the core info, I'd say put this block firs
Matt Giuca
2014/09/15 03:49:46
What do you mean by "core info"? All of this is op
|
+ |
+ // 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. |
+ base::string16 delegate_guid; |
+ // 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,46 @@ 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) { |
+ ApplicationInfo app_info; |
+ app_info.prog_id = GetBrowserProgId(suffix); |
+ app_info.file_type_name = dist->GetBrowserProgIdDesc(); |
+ app_info.file_type_icon_path = chrome_exe; |
+ app_info.file_type_icon_index = |
+ dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME); |
+ 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); |
+ |
+ // The Chrome app icon path is the same as its file type path. |
+ app_info.application_name = dist->GetDisplayName(); |
+ app_info.application_icon_path = app_info.file_type_icon_path; |
+ app_info.application_icon_index = app_info.file_type_icon_index; |
+ app_info.application_description = dist->GetAppDescription(); |
+ app_info.publisher_name = dist->GetPublisherName(); |
gab
2014/09/12 13:32:36
As mentioned above, put this information first (an
Matt Giuca
2014/09/15 03:49:46
See comment above.
OK I've done the latter sugges
|
+ |
+ 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); |
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 +310,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; |
@@ -284,52 +343,72 @@ 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)); |
+ 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, dist->GetBrowserProgIdDesc())); |
+ 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::kRegDefaultIcon, icon_path)); |
- 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)); |
+ // 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))); |
+ } |
// TODO(grt): http://crbug.com/75152 Write a reference to a localized |
gab
2014/09/12 13:32:36
This TODO now belongs in the Chrome specific metho
Matt Giuca
2014/09/15 03:49:46
Done.
|
// 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())); |
+ 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)); |
+ } |
gab
2014/09/12 13:32:36
Does it really hurt to set those if they're empty?
Matt Giuca
2014/09/15 03:49:46
I don't know, but I could imagine Windows treating
|
} |
} |
@@ -433,9 +512,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,16 +526,50 @@ 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 name. |
gab
2014/09/12 13:32:37
s/name/prog_id
Matt Giuca
2014/09/15 03:49:46
Done.
|
+ 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( |
gab
2014/09/12 13:32:36
Note in the method name that these are XP style de
Matt Giuca
2014/09/15 03:49:45
They certainly work in Windows 7 (haven't tested i
gab
2014/09/18 01:16:15
You're right that IApplicationAssociationRegistrat
Matt Giuca
2014/09/30 10:21:12
Where on that page ([1]) does it say it doesn't wo
gab
2014/10/01 14:31:11
Browsers are special indeed in that being default
Matt Giuca
2014/10/02 09:36:33
I have completed my investigation on Windows 8, an
|
+ 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)) |
+ entries->push_back(default_association.release()); |
gab
2014/09/12 13:32:36
nit: {} since conditional is multiline
Matt Giuca
2014/09/15 03:49:45
Done.
|
+ } |
+ |
// This method returns a list of all the user level registry entries that |
// are needed to make Chromium the default handler for a protocol on XP. |
static void GetXPStyleUserProtocolEntries( |
@@ -504,10 +618,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 +675,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 { |
gab
2014/09/12 13:32:37
Seems your only caller of this cares only about HK
Matt Giuca
2014/09/15 03:49:46
I think for the latter reason that it's best to ke
|
+ 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 +803,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 +2190,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 +2210,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 +2219,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 +2231,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 +2421,50 @@ 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; |
+ |
+ // 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) { |
+ base::string16 ext(1, L'.'); |
gab
2014/09/12 13:32:36
Add this check above.
DCHECK(!it->empty() && (*it
Matt Giuca
2014/09/15 03:49:46
Done.
|
+ 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); |
+ |
+ // Note: there is no need to remove the association from the extension to the |
+ // class, as Windows will ignore it. See: |
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/cc144148.aspx |
gab
2014/09/12 13:32:37
Right but you should still delete the OpenWith reg
Matt Giuca
2014/09/15 03:49:46
While that document doesn't say *not* to remove th
gab
2014/09/18 01:16:15
The documentation *does* explicitly say that these
Matt Giuca
2014/09/30 10:21:12
But remember I will be calling this code far more
gab
2014/10/01 14:31:11
Ok fair enough, but I still think we should remove
Matt Giuca
2014/10/02 09:36:33
Acknowledged.
|
+} |