Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // This file defines functions that integrate Chrome in Windows shell. These | 5 // This file defines functions that integrate Chrome in Windows shell. These |
| 6 // functions can be used by Chrome as well as Chrome installer. All of the | 6 // functions can be used by Chrome as well as Chrome installer. All of the |
| 7 // work is done by the local functions defined in anonymous namespace in | 7 // work is done by the local functions defined in anonymous namespace in |
| 8 // this class. | 8 // this class. |
| 9 | 9 |
| 10 #include "chrome/installer/util/shell_util.h" | 10 #include "chrome/installer/util/shell_util.h" |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 184 // class. | 184 // class. |
| 185 class RegistryEntry { | 185 class RegistryEntry { |
| 186 public: | 186 public: |
| 187 // A bit-field enum of places to look for this key in the Windows registry. | 187 // A bit-field enum of places to look for this key in the Windows registry. |
| 188 enum LookForIn { | 188 enum LookForIn { |
| 189 LOOK_IN_HKCU = 1 << 0, | 189 LOOK_IN_HKCU = 1 << 0, |
| 190 LOOK_IN_HKLM = 1 << 1, | 190 LOOK_IN_HKLM = 1 << 1, |
| 191 LOOK_IN_HKCU_THEN_HKLM = LOOK_IN_HKCU | LOOK_IN_HKLM, | 191 LOOK_IN_HKCU_THEN_HKLM = LOOK_IN_HKCU | LOOK_IN_HKLM, |
| 192 }; | 192 }; |
| 193 | 193 |
| 194 // Details about a Windows application, to be entered into the registry for | |
| 195 // the purpose of file associations. | |
| 196 struct ApplicationInfo { | |
| 197 ApplicationInfo() | |
| 198 : set_delegate_execute(false), | |
| 199 file_type_icon_index(0), | |
| 200 application_icon_index(0) {} | |
| 201 | |
| 202 // 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.
| |
| 203 // application. | |
| 204 base::string16 prog_id; | |
| 205 // The friendly name, and the path of the icon that will be used for files | |
| 206 // of these types when associated with this application by default. (They | |
| 207 // are NOT the name/icon that will represent the application under the Open | |
| 208 // With menu.) | |
| 209 base::string16 file_type_name; | |
| 210 // TODO(mgiuca): |file_type_icon_path| should be a base::FilePath. | |
| 211 base::string16 file_type_icon_path; | |
| 212 int file_type_icon_index; | |
| 213 // The command to execute when opening a file via this association. It | |
| 214 // 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.
| |
| 215 // TODO(mgiuca): |command_line| should be a base::CommandLine. | |
| 216 base::string16 command_line; | |
| 217 // 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.
| |
| 218 // from |prog_id|. May be empty. | |
| 219 base::string16 app_id; | |
| 220 | |
| 221 // User-visible details about this application. Any of these may be empty. | |
| 222 base::string16 application_name; | |
| 223 // TODO(mgiuca): |application_icon_path| should be a base::FilePath. | |
| 224 base::string16 application_icon_path; | |
| 225 int application_icon_index; | |
| 226 base::string16 application_description; | |
| 227 base::string16 publisher_name; | |
| 228 | |
| 229 // Whether the application will have a DelegateExecute key. This should only | |
| 230 // be used by Windows 8 Metro web browsers (i.e. Chrome itself). All other | |
| 231 // fields in this section are ignored if this is false. | |
| 232 bool set_delegate_execute; | |
| 233 // 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.
| |
| 234 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.
| |
| 235 // The command to execute when opening this application via the Metro UI. | |
| 236 base::string16 delegate_command; | |
| 237 }; | |
| 238 | |
| 194 // Returns the Windows browser client registration key for Chrome. For | 239 // Returns the Windows browser client registration key for Chrome. For |
| 195 // example: "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly | 240 // example: "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly |
| 196 // speaking, we should use the name of the executable (e.g., "chrome.exe"), | 241 // speaking, we should use the name of the executable (e.g., "chrome.exe"), |
| 197 // but that ship has sailed. The cost of switching now is re-prompting users | 242 // but that ship has sailed. The cost of switching now is re-prompting users |
| 198 // to make Chrome their default browser, which isn't polite. |suffix| is the | 243 // to make Chrome their default browser, which isn't polite. |suffix| is the |
| 199 // user-specific registration suffix; see GetUserSpecificDefaultBrowserSuffix | 244 // user-specific registration suffix; see GetUserSpecificDefaultBrowserSuffix |
| 200 // in shell_util.h for details. | 245 // in shell_util.h for details. |
| 201 static base::string16 GetBrowserClientKey(BrowserDistribution* dist, | 246 static base::string16 GetBrowserClientKey(BrowserDistribution* dist, |
| 202 const base::string16& suffix) { | 247 const base::string16& suffix) { |
| 203 DCHECK(suffix.empty() || suffix[0] == L'.'); | 248 DCHECK(suffix.empty() || suffix[0] == L'.'); |
| 204 return base::string16(ShellUtil::kRegStartMenuInternet) | 249 return base::string16(ShellUtil::kRegStartMenuInternet) |
| 205 .append(1, L'\\') | 250 .append(1, L'\\') |
| 206 .append(dist->GetBaseAppName()) | 251 .append(dist->GetBaseAppName()) |
| 207 .append(suffix); | 252 .append(suffix); |
| 208 } | 253 } |
| 209 | 254 |
| 210 // Returns the Windows Default Programs capabilities key for Chrome. For | 255 // Returns the Windows Default Programs capabilities key for Chrome. For |
| 211 // example: | 256 // example: |
| 212 // "Software\Clients\StartMenuInternet\Chromium[.user]\Capabilities". | 257 // "Software\Clients\StartMenuInternet\Chromium[.user]\Capabilities". |
| 213 static base::string16 GetCapabilitiesKey(BrowserDistribution* dist, | 258 static base::string16 GetCapabilitiesKey(BrowserDistribution* dist, |
| 214 const base::string16& suffix) { | 259 const base::string16& suffix) { |
| 215 return GetBrowserClientKey(dist, suffix).append(L"\\Capabilities"); | 260 return GetBrowserClientKey(dist, suffix).append(L"\\Capabilities"); |
| 216 } | 261 } |
| 217 | 262 |
| 218 // This method returns a list of all the registry entries that | 263 // This method returns a list of all the registry entries that |
| 219 // are needed to register this installation's ProgId and AppId. | 264 // are needed to register this installation's ProgId and AppId. |
| 220 // These entries need to be registered in HKLM prior to Win8. | 265 // These entries need to be registered in HKLM prior to Win8. |
| 221 static void GetProgIdEntries(BrowserDistribution* dist, | 266 static void GetChromeProgIdEntries(BrowserDistribution* dist, |
| 222 const base::string16& chrome_exe, | 267 const base::string16& chrome_exe, |
| 223 const base::string16& suffix, | 268 const base::string16& suffix, |
| 224 ScopedVector<RegistryEntry>* entries) { | 269 ScopedVector<RegistryEntry>* entries) { |
| 225 base::string16 icon_path( | 270 int chrome_icon_index = |
| 226 ShellUtil::FormatIconLocation( | 271 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME); |
| 227 chrome_exe, | 272 |
| 228 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME))); | 273 ApplicationInfo app_info; |
| 229 base::string16 open_cmd(ShellUtil::GetChromeShellOpenCmd(chrome_exe)); | 274 app_info.prog_id = GetBrowserProgId(suffix); |
| 230 base::string16 delegate_command( | 275 app_info.file_type_name = dist->GetBrowserProgIdDesc(); |
| 231 ShellUtil::GetChromeDelegateCommand(chrome_exe)); | 276 // File types associated with Chrome are just given the Chrome icon. |
| 232 // For user-level installs: entries for the app id and DelegateExecute verb | 277 app_info.file_type_icon_path = chrome_exe; |
| 233 // handler will be in HKCU; thus we do not need a suffix on those entries. | 278 app_info.file_type_icon_index = chrome_icon_index; |
| 234 base::string16 app_id( | 279 app_info.command_line = ShellUtil::GetChromeShellOpenCmd(chrome_exe); |
| 235 ShellUtil::GetBrowserModelId( | 280 // For user-level installs: entries for the app id will be in HKCU; thus we |
| 236 dist, InstallUtil::IsPerUserInstall(chrome_exe.c_str()))); | 281 // do not need a suffix on those entries. |
| 237 base::string16 delegate_guid; | 282 app_info.app_id = ShellUtil::GetBrowserModelId( |
| 238 bool set_delegate_execute = | 283 dist, InstallUtil::IsPerUserInstall(chrome_exe.c_str())); |
| 239 IsChromeMetroSupported() && | |
| 240 dist->GetCommandExecuteImplClsid(&delegate_guid); | |
| 241 | 284 |
| 242 // DelegateExecute ProgId. Needed for Chrome Metro in Windows 8. | 285 // DelegateExecute ProgId. Needed for Chrome Metro in Windows 8. |
| 243 if (set_delegate_execute) { | 286 app_info.delegate_command = ShellUtil::GetChromeDelegateCommand(chrome_exe); |
| 287 app_info.set_delegate_execute = | |
| 288 IsChromeMetroSupported() && | |
| 289 dist->GetCommandExecuteImplClsid(&app_info.delegate_guid); | |
| 290 | |
| 291 // TODO(grt): http://crbug.com/75152 Write a reference to a localized | |
| 292 // resource for name, description, and company. | |
| 293 app_info.application_name = dist->GetDisplayName(); | |
| 294 app_info.application_icon_path = chrome_exe; | |
| 295 app_info.application_icon_index = chrome_icon_index; | |
| 296 app_info.application_description = dist->GetAppDescription(); | |
| 297 app_info.publisher_name = dist->GetPublisherName(); | |
| 298 | |
| 299 GetProgIdEntries(app_info, entries); | |
| 300 } | |
| 301 | |
| 302 // Gets the registry entries to register an application in the Windows | |
| 303 // registry. |app_info| provides all of the information needed. | |
| 304 static void GetProgIdEntries(const ApplicationInfo& app_info, | |
| 305 ScopedVector<RegistryEntry>* entries) { | |
| 306 if (app_info.set_delegate_execute) { | |
| 244 base::string16 model_id_shell(ShellUtil::kRegClasses); | 307 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).
| |
| 245 model_id_shell.push_back(base::FilePath::kSeparators[0]); | 308 model_id_shell.push_back(base::FilePath::kSeparators[0]); |
| 246 model_id_shell.append(app_id); | 309 model_id_shell.append(app_info.app_id); |
| 247 model_id_shell.append(ShellUtil::kRegExePath); | 310 model_id_shell.append(ShellUtil::kRegExePath); |
| 248 model_id_shell.append(ShellUtil::kRegShellPath); | 311 model_id_shell.append(ShellUtil::kRegShellPath); |
| 249 | 312 |
| 250 // <root hkey>\Software\Classes\<app_id>\.exe\shell @=open | 313 // <root hkey>\Software\Classes\<app_id>\.exe\shell @=open |
| 251 entries->push_back(new RegistryEntry(model_id_shell, | 314 entries->push_back(new RegistryEntry(model_id_shell, |
| 252 ShellUtil::kRegVerbOpen)); | 315 ShellUtil::kRegVerbOpen)); |
| 253 | 316 |
| 254 // Each of Chrome's shortcuts has an appid; which, as of Windows 8, is | 317 // Each shortcut has an appid; which, as of Windows 8, is registered to |
| 255 // registered to handle some verbs. This registration has the side-effect | 318 // handle some verbs. This registration has the side-effect that these |
| 256 // that these verbs now show up in the shortcut's context menu. We | 319 // verbs now show up in the shortcut's context menu. We mitigate this |
| 257 // mitigate this side-effect by making the context menu entries | 320 // side-effect by making the context menu entries user readable/localized |
| 258 // user readable/localized strings. See relevant MSDN article: | 321 // strings. See relevant MSDN article: |
| 259 // http://msdn.microsoft.com/en-US/library/windows/desktop/cc144171.aspx | 322 // http://msdn.microsoft.com/en-US/library/windows/desktop/cc144171.aspx |
| 260 const struct { | 323 const struct { |
| 261 const wchar_t* verb; | 324 const wchar_t* verb; |
| 262 int name_id; | 325 int name_id; |
| 263 } verbs[] = { | 326 } verbs[] = { |
| 264 { ShellUtil::kRegVerbOpen, -1 }, | 327 { ShellUtil::kRegVerbOpen, -1 }, |
| 265 { ShellUtil::kRegVerbOpenNewWindow, IDS_SHORTCUT_NEW_WINDOW_BASE }, | 328 { ShellUtil::kRegVerbOpenNewWindow, IDS_SHORTCUT_NEW_WINDOW_BASE }, |
| 266 }; | 329 }; |
| 267 for (size_t i = 0; i < arraysize(verbs); ++i) { | 330 for (size_t i = 0; i < arraysize(verbs); ++i) { |
| 268 base::string16 sub_path(model_id_shell); | 331 base::string16 sub_path(model_id_shell); |
| 269 sub_path.push_back(base::FilePath::kSeparators[0]); | 332 sub_path.push_back(base::FilePath::kSeparators[0]); |
| 270 sub_path.append(verbs[i].verb); | 333 sub_path.append(verbs[i].verb); |
| 271 | 334 |
| 272 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb> | 335 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb> |
| 273 if (verbs[i].name_id != -1) { | 336 if (verbs[i].name_id != -1) { |
| 274 // TODO(grt): http://crbug.com/75152 Write a reference to a localized | 337 // TODO(grt): http://crbug.com/75152 Write a reference to a localized |
| 275 // resource. | 338 // resource. |
| 276 base::string16 verb_name( | 339 base::string16 verb_name( |
| 277 installer::GetLocalizedString(verbs[i].name_id)); | 340 installer::GetLocalizedString(verbs[i].name_id)); |
| 278 entries->push_back(new RegistryEntry(sub_path, verb_name.c_str())); | 341 entries->push_back(new RegistryEntry(sub_path, verb_name.c_str())); |
| 279 } | 342 } |
| 343 // TODO(mgiuca): Generalize this or move it into the Chrome-specific | |
| 344 // 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
| |
| 280 entries->push_back(new RegistryEntry( | 345 entries->push_back(new RegistryEntry( |
| 281 sub_path, L"CommandId", L"Browser.Launch")); | 346 sub_path, L"CommandId", L"Browser.Launch")); |
| 282 | 347 |
| 283 sub_path.push_back(base::FilePath::kSeparators[0]); | 348 sub_path.push_back(base::FilePath::kSeparators[0]); |
| 284 sub_path.append(ShellUtil::kRegCommand); | 349 sub_path.append(ShellUtil::kRegCommand); |
| 285 | 350 |
| 286 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>\command | 351 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>\command |
| 287 entries->push_back(new RegistryEntry(sub_path, delegate_command)); | 352 entries->push_back( |
| 353 new RegistryEntry(sub_path, app_info.delegate_command)); | |
| 288 entries->push_back(new RegistryEntry( | 354 entries->push_back(new RegistryEntry( |
| 289 sub_path, ShellUtil::kRegDelegateExecute, delegate_guid)); | 355 sub_path, ShellUtil::kRegDelegateExecute, app_info.delegate_guid)); |
| 290 } | 356 } |
| 291 } | 357 } |
| 292 | 358 |
| 293 // File association ProgId | 359 // File association ProgId |
| 294 base::string16 chrome_html_prog_id(ShellUtil::kRegClasses); | 360 base::string16 prog_id_path(ShellUtil::kRegClasses); |
| 295 chrome_html_prog_id.push_back(base::FilePath::kSeparators[0]); | 361 prog_id_path.push_back(base::FilePath::kSeparators[0]); |
| 296 chrome_html_prog_id.append(GetBrowserProgId(suffix)); | 362 prog_id_path.append(app_info.prog_id); |
| 363 entries->push_back( | |
| 364 new RegistryEntry(prog_id_path, app_info.file_type_name)); | |
| 297 entries->push_back(new RegistryEntry( | 365 entries->push_back(new RegistryEntry( |
| 298 chrome_html_prog_id, dist->GetBrowserProgIdDesc())); | 366 prog_id_path + ShellUtil::kRegDefaultIcon, |
| 367 ShellUtil::FormatIconLocation(app_info.file_type_icon_path, | |
| 368 app_info.file_type_icon_index))); | |
| 299 entries->push_back(new RegistryEntry( | 369 entries->push_back(new RegistryEntry( |
| 300 chrome_html_prog_id + ShellUtil::kRegDefaultIcon, icon_path)); | 370 prog_id_path + ShellUtil::kRegShellOpen, app_info.command_line)); |
| 301 entries->push_back(new RegistryEntry( | 371 if (app_info.set_delegate_execute) { |
| 302 chrome_html_prog_id + ShellUtil::kRegShellOpen, open_cmd)); | 372 entries->push_back( |
| 303 if (set_delegate_execute) { | 373 new RegistryEntry(prog_id_path + ShellUtil::kRegShellOpen, |
| 304 entries->push_back(new RegistryEntry( | 374 ShellUtil::kRegDelegateExecute, |
| 305 chrome_html_prog_id + ShellUtil::kRegShellOpen, | 375 app_info.delegate_guid)); |
| 306 ShellUtil::kRegDelegateExecute, delegate_guid)); | |
| 307 } | 376 } |
| 308 | 377 |
| 309 // The following entries are required as of Windows 8, but do not | 378 // The following entries are required as of Windows 8, but do not |
| 310 // depend on the DelegateExecute verb handler being set. | 379 // depend on the DelegateExecute verb handler being set. |
| 311 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { | 380 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { |
| 312 entries->push_back(new RegistryEntry( | 381 if (!app_info.app_id.empty()) { |
| 313 chrome_html_prog_id, ShellUtil::kRegAppUserModelId, app_id)); | 382 entries->push_back(new RegistryEntry( |
| 383 prog_id_path, ShellUtil::kRegAppUserModelId, app_info.app_id)); | |
| 384 } | |
| 314 | 385 |
| 315 // Add \Software\Classes\ChromeHTML\Application entries | 386 // Add \Software\Classes\<prog_id>\Application entries |
| 316 base::string16 chrome_application(chrome_html_prog_id + | 387 base::string16 application_path(prog_id_path + |
| 317 ShellUtil::kRegApplication); | 388 ShellUtil::kRegApplication); |
| 318 entries->push_back(new RegistryEntry( | 389 if (!app_info.app_id.empty()) { |
| 319 chrome_application, ShellUtil::kRegAppUserModelId, app_id)); | 390 entries->push_back(new RegistryEntry( |
| 320 entries->push_back(new RegistryEntry( | 391 application_path, ShellUtil::kRegAppUserModelId, app_info.app_id)); |
| 321 chrome_application, ShellUtil::kRegApplicationIcon, icon_path)); | 392 } |
| 322 // TODO(grt): http://crbug.com/75152 Write a reference to a localized | 393 if (!app_info.application_icon_path.empty()) { |
| 323 // resource for name, description, and company. | 394 entries->push_back(new RegistryEntry( |
| 324 entries->push_back(new RegistryEntry( | 395 application_path, |
| 325 chrome_application, ShellUtil::kRegApplicationName, | 396 ShellUtil::kRegApplicationIcon, |
| 326 dist->GetDisplayName())); | 397 ShellUtil::FormatIconLocation(app_info.application_icon_path, |
| 327 entries->push_back(new RegistryEntry( | 398 app_info.application_icon_index))); |
| 328 chrome_application, ShellUtil::kRegApplicationDescription, | 399 } |
| 329 dist->GetAppDescription())); | 400 if (!app_info.application_name.empty()) { |
| 330 entries->push_back(new RegistryEntry( | 401 entries->push_back(new RegistryEntry(application_path, |
| 331 chrome_application, ShellUtil::kRegApplicationCompany, | 402 ShellUtil::kRegApplicationName, |
| 332 dist->GetPublisherName())); | 403 app_info.application_name)); |
| 404 } | |
| 405 if (!app_info.application_description.empty()) { | |
| 406 entries->push_back( | |
| 407 new RegistryEntry(application_path, | |
| 408 ShellUtil::kRegApplicationDescription, | |
| 409 app_info.application_description)); | |
| 410 } | |
| 411 if (!app_info.publisher_name.empty()) { | |
| 412 entries->push_back(new RegistryEntry(application_path, | |
| 413 ShellUtil::kRegApplicationCompany, | |
| 414 app_info.publisher_name)); | |
| 415 } | |
| 333 } | 416 } |
| 334 } | 417 } |
| 335 | 418 |
| 336 // This method returns a list of the registry entries needed to declare a | 419 // This method returns a list of the registry entries needed to declare a |
| 337 // capability of handling a protocol on Windows. | 420 // capability of handling a protocol on Windows. |
| 338 static void GetProtocolCapabilityEntries( | 421 static void GetProtocolCapabilityEntries( |
| 339 BrowserDistribution* dist, | 422 BrowserDistribution* dist, |
| 340 const base::string16& suffix, | 423 const base::string16& suffix, |
| 341 const base::string16& protocol, | 424 const base::string16& protocol, |
| 342 ScopedVector<RegistryEntry>* entries) { | 425 ScopedVector<RegistryEntry>* entries) { |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 426 } | 509 } |
| 427 | 510 |
| 428 // This method returns a list of the registry entries required for this | 511 // This method returns a list of the registry entries required for this |
| 429 // installation to be registered in the Windows shell. | 512 // installation to be registered in the Windows shell. |
| 430 // In particular: | 513 // In particular: |
| 431 // - App Paths | 514 // - App Paths |
| 432 // http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121 | 515 // http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121 |
| 433 // - File Associations | 516 // - File Associations |
| 434 // http://msdn.microsoft.com/en-us/library/bb166549 | 517 // http://msdn.microsoft.com/en-us/library/bb166549 |
| 435 // These entries need to be registered in HKLM prior to Win8. | 518 // These entries need to be registered in HKLM prior to Win8. |
| 436 static void GetAppRegistrationEntries(const base::string16& chrome_exe, | 519 static void GetChromeAppRegistrationEntries( |
| 437 const base::string16& suffix, | 520 const base::string16& chrome_exe, |
| 438 ScopedVector<RegistryEntry>* entries) { | 521 const base::string16& suffix, |
| 522 ScopedVector<RegistryEntry>* entries) { | |
| 439 const base::FilePath chrome_path(chrome_exe); | 523 const base::FilePath chrome_path(chrome_exe); |
| 440 base::string16 app_path_key(ShellUtil::kAppPathsRegistryKey); | 524 base::string16 app_path_key(ShellUtil::kAppPathsRegistryKey); |
| 441 app_path_key.push_back(base::FilePath::kSeparators[0]); | 525 app_path_key.push_back(base::FilePath::kSeparators[0]); |
| 442 app_path_key.append(chrome_path.BaseName().value()); | 526 app_path_key.append(chrome_path.BaseName().value()); |
| 443 entries->push_back(new RegistryEntry(app_path_key, chrome_exe)); | 527 entries->push_back(new RegistryEntry(app_path_key, chrome_exe)); |
| 444 entries->push_back(new RegistryEntry(app_path_key, | 528 entries->push_back(new RegistryEntry(app_path_key, |
| 445 ShellUtil::kAppPathsRegistryPathName, chrome_path.DirName().value())); | 529 ShellUtil::kAppPathsRegistryPathName, chrome_path.DirName().value())); |
| 446 | 530 |
| 447 const base::string16 html_prog_id(GetBrowserProgId(suffix)); | 531 const base::string16 html_prog_id(GetBrowserProgId(suffix)); |
| 448 for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) { | 532 for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) { |
| 449 base::string16 key(ShellUtil::kRegClasses); | 533 GetAppExtRegistrationEntries( |
| 450 key.push_back(base::FilePath::kSeparators[0]); | 534 html_prog_id, ShellUtil::kPotentialFileAssociations[i], entries); |
| 451 key.append(ShellUtil::kPotentialFileAssociations[i]); | |
| 452 key.push_back(base::FilePath::kSeparators[0]); | |
| 453 key.append(ShellUtil::kRegOpenWithProgids); | |
| 454 entries->push_back( | |
| 455 new RegistryEntry(key, html_prog_id, base::string16())); | |
| 456 } | 535 } |
| 457 } | 536 } |
| 458 | 537 |
| 538 // Gets the registry entries to register an application as a handler for a | |
| 539 // particular file extension. |prog_id| is the unique internal name Windows | |
| 540 // uses for the application. |ext| is the file extension, which must begin | |
| 541 // with a '.'. | |
| 542 static void GetAppExtRegistrationEntries( | |
| 543 const base::string16& prog_id, | |
| 544 const base::string16& ext, | |
| 545 ScopedVector<RegistryEntry>* entries) { | |
| 546 // In HKEY_CLASSES_ROOT\EXT\OpenWithProgids, create an empty value with this | |
| 547 // class's prog_id. | |
| 548 base::string16 key_name(ShellUtil::kRegClasses); | |
| 549 key_name.push_back(base::FilePath::kSeparators[0]); | |
| 550 key_name.append(ext); | |
| 551 key_name.push_back(base::FilePath::kSeparators[0]); | |
| 552 key_name.append(ShellUtil::kRegOpenWithProgids); | |
| 553 entries->push_back(new RegistryEntry(key_name, prog_id, base::string16())); | |
| 554 } | |
| 555 | |
| 556 // Gets the registry entries to register an application as the default handler | |
| 557 // for a particular file extension. |prog_id| is the unique internal name | |
| 558 // Windows uses for the application. |ext| is the file extension, which must | |
| 559 // begin with a '.'. If |overwrite_existing|, always sets the default handler; | |
| 560 // otherwise only sets if there is no existing default. | |
| 561 static void GetAppDefaultRegistrationEntries( | |
| 562 const base::string16& prog_id, | |
| 563 const base::string16& ext, | |
| 564 bool overwrite_existing, | |
| 565 ScopedVector<RegistryEntry>* entries) { | |
| 566 // Set the default value of HKEY_CLASSES_ROOT\EXT to this class's name. | |
| 567 base::string16 key_name(ShellUtil::kRegClasses); | |
| 568 key_name.push_back(base::FilePath::kSeparators[0]); | |
| 569 key_name.append(ext); | |
| 570 scoped_ptr<RegistryEntry> default_association( | |
| 571 new RegistryEntry(key_name, prog_id)); | |
| 572 if (overwrite_existing || | |
| 573 !default_association->KeyExistsInRegistry( | |
| 574 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.
| |
| 575 entries->push_back(default_association.release()); | |
| 576 } | |
| 577 } | |
| 578 | |
| 459 // This method returns a list of all the user level registry entries that | 579 // This method returns a list of all the user level registry entries that |
| 460 // are needed to make Chromium the default handler for a protocol on XP. | 580 // are needed to make Chromium the default handler for a protocol on XP. |
| 461 static void GetXPStyleUserProtocolEntries( | 581 static void GetXPStyleUserProtocolEntries( |
| 462 const base::string16& protocol, | 582 const base::string16& protocol, |
| 463 const base::string16& chrome_icon, | 583 const base::string16& chrome_icon, |
| 464 const base::string16& chrome_open, | 584 const base::string16& chrome_open, |
| 465 ScopedVector<RegistryEntry>* entries) { | 585 ScopedVector<RegistryEntry>* entries) { |
| 466 // Protocols associations. | 586 // Protocols associations. |
| 467 base::string16 url_key(ShellUtil::kRegClasses); | 587 base::string16 url_key(ShellUtil::kRegClasses); |
| 468 url_key.push_back(base::FilePath::kSeparators[0]); | 588 url_key.push_back(base::FilePath::kSeparators[0]); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 497 // we register them anyways as some legacy apps are hardcoded to lookup those | 617 // we register them anyways as some legacy apps are hardcoded to lookup those |
| 498 // values. | 618 // values. |
| 499 static void GetXPStyleDefaultBrowserUserEntries( | 619 static void GetXPStyleDefaultBrowserUserEntries( |
| 500 BrowserDistribution* dist, | 620 BrowserDistribution* dist, |
| 501 const base::string16& chrome_exe, | 621 const base::string16& chrome_exe, |
| 502 const base::string16& suffix, | 622 const base::string16& suffix, |
| 503 ScopedVector<RegistryEntry>* entries) { | 623 ScopedVector<RegistryEntry>* entries) { |
| 504 // File extension associations. | 624 // File extension associations. |
| 505 base::string16 html_prog_id(GetBrowserProgId(suffix)); | 625 base::string16 html_prog_id(GetBrowserProgId(suffix)); |
| 506 for (int i = 0; ShellUtil::kDefaultFileAssociations[i] != NULL; i++) { | 626 for (int i = 0; ShellUtil::kDefaultFileAssociations[i] != NULL; i++) { |
| 507 base::string16 ext_key(ShellUtil::kRegClasses); | 627 GetAppDefaultRegistrationEntries( |
| 508 ext_key.push_back(base::FilePath::kSeparators[0]); | 628 html_prog_id, ShellUtil::kDefaultFileAssociations[i], true, entries); |
| 509 ext_key.append(ShellUtil::kDefaultFileAssociations[i]); | |
| 510 entries->push_back(new RegistryEntry(ext_key, html_prog_id)); | |
| 511 } | 629 } |
| 512 | 630 |
| 513 // Protocols associations. | 631 // Protocols associations. |
| 514 base::string16 chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe); | 632 base::string16 chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe); |
| 515 base::string16 chrome_icon = | 633 base::string16 chrome_icon = |
| 516 ShellUtil::FormatIconLocation( | 634 ShellUtil::FormatIconLocation( |
| 517 chrome_exe, | 635 chrome_exe, |
| 518 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME)); | 636 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME)); |
| 519 for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) { | 637 for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) { |
| 520 GetXPStyleUserProtocolEntries(ShellUtil::kBrowserProtocolAssociations[i], | 638 GetXPStyleUserProtocolEntries(ShellUtil::kBrowserProtocolAssociations[i], |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 556 DCHECK(look_for_in); | 674 DCHECK(look_for_in); |
| 557 | 675 |
| 558 RegistryStatus status = DOES_NOT_EXIST; | 676 RegistryStatus status = DOES_NOT_EXIST; |
| 559 if (look_for_in & LOOK_IN_HKCU) | 677 if (look_for_in & LOOK_IN_HKCU) |
| 560 status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER); | 678 status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER); |
| 561 if (status == DOES_NOT_EXIST && (look_for_in & LOOK_IN_HKLM)) | 679 if (status == DOES_NOT_EXIST && (look_for_in & LOOK_IN_HKLM)) |
| 562 status = StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE); | 680 status = StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE); |
| 563 return status == SAME_VALUE; | 681 return status == SAME_VALUE; |
| 564 } | 682 } |
| 565 | 683 |
| 684 // Checks if the current registry entry exists in \|key_path_|\|name_|, | |
| 685 // regardless of value. Same lookup rules as ExistsInRegistry. | |
| 686 // Unlike ExistsInRegistry, this returns true if some other value is present | |
| 687 // with the same key. | |
| 688 bool KeyExistsInRegistry(uint32 look_for_in) const { | |
| 689 DCHECK(look_for_in); | |
| 690 | |
| 691 RegistryStatus status = DOES_NOT_EXIST; | |
| 692 if (look_for_in & LOOK_IN_HKCU) | |
| 693 status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER); | |
| 694 if (status == DOES_NOT_EXIST && (look_for_in & LOOK_IN_HKLM)) | |
| 695 status = StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE); | |
| 696 return status != DOES_NOT_EXIST; | |
| 697 } | |
| 698 | |
| 566 private: | 699 private: |
| 567 // States this RegistryKey can be in compared to the registry. | 700 // States this RegistryKey can be in compared to the registry. |
| 568 enum RegistryStatus { | 701 enum RegistryStatus { |
| 569 // |name_| does not exist in the registry | 702 // |name_| does not exist in the registry |
| 570 DOES_NOT_EXIST, | 703 DOES_NOT_EXIST, |
| 571 // |name_| exists, but its value != |value_| | 704 // |name_| exists, but its value != |value_| |
| 572 DIFFERENT_VALUE, | 705 DIFFERENT_VALUE, |
| 573 // |name_| exists and its value is |value_| | 706 // |name_| exists and its value is |value_| |
| 574 SAME_VALUE, | 707 SAME_VALUE, |
| 575 }; | 708 }; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 669 // under a single registry root. Not doing so caused http://crbug.com/144910 for | 802 // under a single registry root. Not doing so caused http://crbug.com/144910 for |
| 670 // users who first-installed Chrome in that revision range (those users are | 803 // users who first-installed Chrome in that revision range (those users are |
| 671 // still impacted by http://crbug.com/144910). This method will keep returning | 804 // still impacted by http://crbug.com/144910). This method will keep returning |
| 672 // true for affected users (i.e. who have all the registrations, but over both | 805 // true for affected users (i.e. who have all the registrations, but over both |
| 673 // registry roots). | 806 // registry roots). |
| 674 bool IsChromeRegistered(BrowserDistribution* dist, | 807 bool IsChromeRegistered(BrowserDistribution* dist, |
| 675 const base::string16& chrome_exe, | 808 const base::string16& chrome_exe, |
| 676 const base::string16& suffix, | 809 const base::string16& suffix, |
| 677 uint32 look_for_in) { | 810 uint32 look_for_in) { |
| 678 ScopedVector<RegistryEntry> entries; | 811 ScopedVector<RegistryEntry> entries; |
| 679 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries); | 812 RegistryEntry::GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries); |
| 680 RegistryEntry::GetShellIntegrationEntries(dist, chrome_exe, suffix, &entries); | 813 RegistryEntry::GetShellIntegrationEntries(dist, chrome_exe, suffix, &entries); |
| 681 RegistryEntry::GetAppRegistrationEntries(chrome_exe, suffix, &entries); | 814 RegistryEntry::GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries); |
| 682 return AreEntriesRegistered(entries, look_for_in); | 815 return AreEntriesRegistered(entries, look_for_in); |
| 683 } | 816 } |
| 684 | 817 |
| 685 // This method checks if Chrome is already registered on the local machine | 818 // This method checks if Chrome is already registered on the local machine |
| 686 // for the requested protocol. It just checks the one value required for this. | 819 // for the requested protocol. It just checks the one value required for this. |
| 687 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. | 820 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. |
| 688 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, | 821 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, |
| 689 const base::string16& suffix, | 822 const base::string16& suffix, |
| 690 const base::string16& protocol, | 823 const base::string16& protocol, |
| 691 uint32 look_for_in) { | 824 uint32 look_for_in) { |
| (...skipping 1364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2056 // Check if chrome is already registered with this suffix. | 2189 // Check if chrome is already registered with this suffix. |
| 2057 if (IsChromeRegistered(dist, chrome_exe, suffix, look_for_in)) | 2190 if (IsChromeRegistered(dist, chrome_exe, suffix, look_for_in)) |
| 2058 return true; | 2191 return true; |
| 2059 | 2192 |
| 2060 bool result = true; | 2193 bool result = true; |
| 2061 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { | 2194 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { |
| 2062 // Do the full registration if we can do it at user-level or if the user is | 2195 // Do the full registration if we can do it at user-level or if the user is |
| 2063 // an admin. | 2196 // an admin. |
| 2064 ScopedVector<RegistryEntry> progid_and_appreg_entries; | 2197 ScopedVector<RegistryEntry> progid_and_appreg_entries; |
| 2065 ScopedVector<RegistryEntry> shell_entries; | 2198 ScopedVector<RegistryEntry> shell_entries; |
| 2066 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, | 2199 RegistryEntry::GetChromeProgIdEntries( |
| 2067 &progid_and_appreg_entries); | 2200 dist, chrome_exe, suffix, &progid_and_appreg_entries); |
| 2068 RegistryEntry::GetAppRegistrationEntries(chrome_exe, suffix, | 2201 RegistryEntry::GetChromeAppRegistrationEntries( |
| 2069 &progid_and_appreg_entries); | 2202 chrome_exe, suffix, &progid_and_appreg_entries); |
| 2070 RegistryEntry::GetShellIntegrationEntries( | 2203 RegistryEntry::GetShellIntegrationEntries( |
| 2071 dist, chrome_exe, suffix, &shell_entries); | 2204 dist, chrome_exe, suffix, &shell_entries); |
| 2072 result = (AddRegistryEntries(root, progid_and_appreg_entries) && | 2205 result = (AddRegistryEntries(root, progid_and_appreg_entries) && |
| 2073 AddRegistryEntries(root, shell_entries)); | 2206 AddRegistryEntries(root, shell_entries)); |
| 2074 } else if (elevate_if_not_admin && | 2207 } else if (elevate_if_not_admin && |
| 2075 base::win::GetVersion() >= base::win::VERSION_VISTA && | 2208 base::win::GetVersion() >= base::win::VERSION_VISTA && |
| 2076 ElevateAndRegisterChrome(dist, chrome_exe, suffix, base::string16())) { | 2209 ElevateAndRegisterChrome(dist, chrome_exe, suffix, base::string16())) { |
| 2077 // If the user is not an admin and OS is between Vista and Windows 7 | 2210 // If the user is not an admin and OS is between Vista and Windows 7 |
| 2078 // inclusively, try to elevate and register. This is only intended for | 2211 // inclusively, try to elevate and register. This is only intended for |
| 2079 // user-level installs as system-level installs should always be run with | 2212 // user-level installs as system-level installs should always be run with |
| 2080 // admin rights. | 2213 // admin rights. |
| 2081 result = true; | 2214 result = true; |
| 2082 } else { | 2215 } else { |
| 2083 // If we got to this point then all we can do is create ProgId and basic app | 2216 // If we got to this point then all we can do is create ProgId and basic app |
| 2084 // registrations under HKCU. | 2217 // registrations under HKCU. |
| 2085 ScopedVector<RegistryEntry> entries; | 2218 ScopedVector<RegistryEntry> entries; |
| 2086 RegistryEntry::GetProgIdEntries( | 2219 RegistryEntry::GetChromeProgIdEntries( |
| 2087 dist, chrome_exe, base::string16(), &entries); | 2220 dist, chrome_exe, base::string16(), &entries); |
| 2088 // Prefer to use |suffix|; unless Chrome's ProgIds are already registered | 2221 // Prefer to use |suffix|; unless Chrome's ProgIds are already registered |
| 2089 // with no suffix (as per the old registration style): in which case some | 2222 // with no suffix (as per the old registration style): in which case some |
| 2090 // other registry entries could refer to them and since we were not able to | 2223 // other registry entries could refer to them and since we were not able to |
| 2091 // set our HKLM entries above, we are better off not altering these here. | 2224 // set our HKLM entries above, we are better off not altering these here. |
| 2092 if (!AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU)) { | 2225 if (!AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU)) { |
| 2093 if (!suffix.empty()) { | 2226 if (!suffix.empty()) { |
| 2094 entries.clear(); | 2227 entries.clear(); |
| 2095 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries); | 2228 RegistryEntry::GetChromeProgIdEntries( |
| 2096 RegistryEntry::GetAppRegistrationEntries(chrome_exe, suffix, &entries); | 2229 dist, chrome_exe, suffix, &entries); |
| 2230 RegistryEntry::GetChromeAppRegistrationEntries( | |
| 2231 chrome_exe, suffix, &entries); | |
| 2097 } | 2232 } |
| 2098 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); | 2233 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); |
| 2099 } else { | 2234 } else { |
| 2100 // The ProgId is registered unsuffixed in HKCU, also register the app with | 2235 // The ProgId is registered unsuffixed in HKCU, also register the app with |
| 2101 // Windows in HKCU (this was not done in the old registration style and | 2236 // Windows in HKCU (this was not done in the old registration style and |
| 2102 // thus needs to be done after the above check for the unsuffixed | 2237 // thus needs to be done after the above check for the unsuffixed |
| 2103 // registration). | 2238 // registration). |
| 2104 entries.clear(); | 2239 entries.clear(); |
| 2105 RegistryEntry::GetAppRegistrationEntries(chrome_exe, base::string16(), | 2240 RegistryEntry::GetChromeAppRegistrationEntries( |
| 2106 &entries); | 2241 chrome_exe, base::string16(), &entries); |
| 2107 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); | 2242 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); |
| 2108 } | 2243 } |
| 2109 } | 2244 } |
| 2110 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); | 2245 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); |
| 2111 return result; | 2246 return result; |
| 2112 } | 2247 } |
| 2113 | 2248 |
| 2114 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, | 2249 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, |
| 2115 const base::string16& chrome_exe, | 2250 const base::string16& chrome_exe, |
| 2116 const base::string16& unique_suffix, | 2251 const base::string16& unique_suffix, |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2285 // are any left...). | 2420 // are any left...). |
| 2286 if (free_bits >= 8 && next_byte_index < size) { | 2421 if (free_bits >= 8 && next_byte_index < size) { |
| 2287 free_bits -= 8; | 2422 free_bits -= 8; |
| 2288 bit_stream += bytes[next_byte_index++] << free_bits; | 2423 bit_stream += bytes[next_byte_index++] << free_bits; |
| 2289 } | 2424 } |
| 2290 } | 2425 } |
| 2291 | 2426 |
| 2292 DCHECK_EQ(ret.length(), encoded_length); | 2427 DCHECK_EQ(ret.length(), encoded_length); |
| 2293 return ret; | 2428 return ret; |
| 2294 } | 2429 } |
| 2430 | |
| 2431 // static | |
| 2432 bool ShellUtil::AddFileAssociations( | |
| 2433 const base::string16& progid, | |
| 2434 const base::CommandLine& command_line, | |
| 2435 const base::string16& file_type_name, | |
| 2436 const base::FilePath& icon_path, | |
| 2437 const std::set<base::string16>& file_extensions) { | |
| 2438 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
| |
| 2439 | |
| 2440 // Create a class for this app. | |
| 2441 RegistryEntry::ApplicationInfo app_info; | |
| 2442 app_info.prog_id = progid; | |
| 2443 app_info.file_type_name = file_type_name; | |
| 2444 app_info.file_type_icon_path = icon_path.value(); | |
| 2445 app_info.file_type_icon_index = 0; | |
| 2446 app_info.command_line = command_line.GetCommandLineString(); | |
| 2447 RegistryEntry::GetProgIdEntries(app_info, &entries); | |
| 2448 | |
| 2449 // Associate each extension that the app can handle with the class. Set this | |
| 2450 // app as the default handler if and only if there is no existing default. | |
| 2451 for (std::set<base::string16>::const_iterator it = file_extensions.begin(); | |
| 2452 it != file_extensions.end(); | |
| 2453 ++it) { | |
| 2454 // TODO(mgiuca): Do we allow empty file extensions? | |
| 2455 // TODO(mgiuca): Do we allow file extensions with a '.' in them? | |
| 2456 DCHECK(!it->empty()); | |
| 2457 DCHECK((*it)[0] != L'.'); | |
| 2458 base::string16 ext(1, L'.'); | |
| 2459 ext.append(*it); | |
| 2460 RegistryEntry::GetAppExtRegistrationEntries(progid, ext, &entries); | |
| 2461 RegistryEntry::GetAppDefaultRegistrationEntries( | |
| 2462 progid, ext, false, &entries); | |
| 2463 } | |
| 2464 | |
| 2465 return AddRegistryEntries(HKEY_CURRENT_USER, entries); | |
| 2466 } | |
| 2467 | |
| 2468 // static | |
| 2469 bool ShellUtil::DeleteFileAssociations(const base::string16& progid) { | |
| 2470 // Delete the key HKEY_CLASSES_ROOT\PROGID. | |
| 2471 base::string16 key_path(ShellUtil::kRegClasses); | |
| 2472 key_path.push_back(base::FilePath::kSeparators[0]); | |
| 2473 key_path.append(progid); | |
| 2474 return InstallUtil::DeleteRegistryKey( | |
| 2475 HKEY_CURRENT_USER, key_path, WorkItem::kWow64Default); | |
| 2476 | |
| 2477 // TODO(mgiuca): Remove the extension association entries. This requires that | |
| 2478 // the extensions associated with a particular prog_id are stored in that | |
| 2479 // prog_id's key. | |
| 2480 } | |
| OLD | NEW |