| 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 29 matching lines...) Expand all Loading... |
| 40 #include "base/win/shortcut.h" | 40 #include "base/win/shortcut.h" |
| 41 #include "base/win/win_util.h" | 41 #include "base/win/win_util.h" |
| 42 #include "base/win/windows_version.h" | 42 #include "base/win/windows_version.h" |
| 43 #include "chrome/common/chrome_constants.h" | 43 #include "chrome/common/chrome_constants.h" |
| 44 #include "chrome/common/chrome_switches.h" | 44 #include "chrome/common/chrome_switches.h" |
| 45 #include "chrome/installer/util/browser_distribution.h" | 45 #include "chrome/installer/util/browser_distribution.h" |
| 46 #include "chrome/installer/util/install_util.h" | 46 #include "chrome/installer/util/install_util.h" |
| 47 #include "chrome/installer/util/l10n_string_util.h" | 47 #include "chrome/installer/util/l10n_string_util.h" |
| 48 #include "chrome/installer/util/master_preferences.h" | 48 #include "chrome/installer/util/master_preferences.h" |
| 49 #include "chrome/installer/util/master_preferences_constants.h" | 49 #include "chrome/installer/util/master_preferences_constants.h" |
| 50 #include "chrome/installer/util/registry_entry.h" |
| 50 #include "chrome/installer/util/util_constants.h" | 51 #include "chrome/installer/util/util_constants.h" |
| 51 #include "chrome/installer/util/work_item.h" | 52 #include "chrome/installer/util/work_item.h" |
| 52 | 53 |
| 53 #include "installer_util_strings.h" // NOLINT | 54 #include "installer_util_strings.h" // NOLINT |
| 54 | 55 |
| 55 using base::win::RegKey; | 56 using base::win::RegKey; |
| 56 | 57 |
| 57 namespace { | 58 namespace { |
| 58 | 59 |
| 59 // An enum used to tell QuickIsChromeRegistered() which level of registration | 60 // An enum used to tell QuickIsChromeRegistered() which level of registration |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 | 171 |
| 171 bool UserSpecificRegistrySuffix::GetSuffix(base::string16* suffix) { | 172 bool UserSpecificRegistrySuffix::GetSuffix(base::string16* suffix) { |
| 172 if (suffix_.empty()) { | 173 if (suffix_.empty()) { |
| 173 NOTREACHED(); | 174 NOTREACHED(); |
| 174 return false; | 175 return false; |
| 175 } | 176 } |
| 176 suffix->assign(suffix_); | 177 suffix->assign(suffix_); |
| 177 return true; | 178 return true; |
| 178 } | 179 } |
| 179 | 180 |
| 180 // This class represents a single registry entry. The objective is to | 181 // Returns the Windows browser client registration key for Chrome. For example: |
| 181 // encapsulate all the registry entries required for registering Chrome at one | 182 // "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly speaking, we |
| 182 // place. This class can not be instantiated outside the class and the objects | 183 // should use the name of the executable (e.g., "chrome.exe"), but that ship has |
| 183 // of this class type can be obtained only by calling a static method of this | 184 // sailed. The cost of switching now is re-prompting users to make Chrome their |
| 184 // class. | 185 // default browser, which isn't polite. |suffix| is the user-specific |
| 185 class RegistryEntry { | 186 // registration suffix; see GetUserSpecificDefaultBrowserSuffix in shell_util.h |
| 186 public: | 187 // for details. |
| 187 // A bit-field enum of places to look for this key in the Windows registry. | 188 base::string16 GetBrowserClientKey(BrowserDistribution* dist, |
| 188 enum LookForIn { | 189 const base::string16& suffix) { |
| 189 LOOK_IN_HKCU = 1 << 0, | 190 DCHECK(suffix.empty() || suffix[0] == L'.'); |
| 190 LOOK_IN_HKLM = 1 << 1, | 191 return base::string16(ShellUtil::kRegStartMenuInternet) |
| 191 LOOK_IN_HKCU_THEN_HKLM = LOOK_IN_HKCU | LOOK_IN_HKLM, | 192 .append(1, L'\\') |
| 192 }; | 193 .append(dist->GetBaseAppName()) |
| 193 | 194 .append(suffix); |
| 194 // Details about a Windows application, to be entered into the registry for | 195 } |
| 195 // the purpose of file associations. | 196 |
| 196 struct ApplicationInfo { | 197 // Returns the Windows Default Programs capabilities key for Chrome. For |
| 197 ApplicationInfo() : file_type_icon_index(0), application_icon_index(0) {} | 198 // example: |
| 198 | 199 // "Software\Clients\StartMenuInternet\Chromium[.user]\Capabilities". |
| 199 // The ProgId used by Windows for file associations with this application. | 200 base::string16 GetCapabilitiesKey(BrowserDistribution* dist, |
| 200 // Must not be empty or start with a '.'. | 201 const base::string16& suffix) { |
| 201 base::string16 prog_id; | 202 return GetBrowserClientKey(dist, suffix).append(L"\\Capabilities"); |
| 202 // The friendly name, and the path of the icon that will be used for files | 203 } |
| 203 // of these types when associated with this application by default. (They | 204 |
| 204 // are NOT the name/icon that will represent the application under the Open | 205 // Details about a Windows application, to be entered into the registry for the |
| 205 // With menu.) | 206 // purpose of file associations. |
| 206 base::string16 file_type_name; | 207 struct ApplicationInfo { |
| 207 // TODO(mgiuca): |file_type_icon_path| should be a base::FilePath. | 208 ApplicationInfo() : file_type_icon_index(0), application_icon_index(0) {} |
| 208 base::string16 file_type_icon_path; | 209 |
| 209 int file_type_icon_index; | 210 // The ProgId used by Windows for file associations with this application. |
| 210 // The command to execute when opening a file via this association. It | 211 // Must not be empty or start with a '.'. |
| 211 // should contain "%1" (to tell Windows to pass the filename as an | 212 base::string16 prog_id; |
| 212 // argument). | 213 // The friendly name, and the path of the icon that will be used for files of |
| 213 // TODO(mgiuca): |command_line| should be a base::CommandLine. | 214 // these types when associated with this application by default. (They are NOT |
| 214 base::string16 command_line; | 215 // the name/icon that will represent the application under the Open With |
| 215 // The AppUserModelId used by Windows 8 for this application. Distinct from | 216 // menu.) |
| 216 // |prog_id|. | 217 base::string16 file_type_name; |
| 217 base::string16 app_id; | 218 // TODO(mgiuca): |file_type_icon_path| should be a base::FilePath. |
| 218 | 219 base::string16 file_type_icon_path; |
| 219 // User-visible details about this application. Any of these may be empty. | 220 int file_type_icon_index; |
| 220 base::string16 application_name; | 221 // The command to execute when opening a file via this association. It should |
| 221 // TODO(mgiuca): |application_icon_path| should be a base::FilePath. | 222 // contain "%1" (to tell Windows to pass the filename as an argument). |
| 222 base::string16 application_icon_path; | 223 // TODO(mgiuca): |command_line| should be a base::CommandLine. |
| 223 int application_icon_index; | 224 base::string16 command_line; |
| 224 base::string16 application_description; | 225 // The AppUserModelId used by Windows 8 for this application. Distinct from |
| 225 base::string16 publisher_name; | 226 // |prog_id|. |
| 226 | 227 base::string16 app_id; |
| 227 // The CLSID for the application's DelegateExecute handler. May be empty. | 228 |
| 228 base::string16 delegate_clsid; | 229 // User-visible details about this application. Any of these may be empty. |
| 229 }; | 230 base::string16 application_name; |
| 230 | 231 // TODO(mgiuca): |application_icon_path| should be a base::FilePath. |
| 231 // Returns the Windows browser client registration key for Chrome. For | 232 base::string16 application_icon_path; |
| 232 // example: "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly | 233 int application_icon_index; |
| 233 // speaking, we should use the name of the executable (e.g., "chrome.exe"), | 234 base::string16 application_description; |
| 234 // but that ship has sailed. The cost of switching now is re-prompting users | 235 base::string16 publisher_name; |
| 235 // to make Chrome their default browser, which isn't polite. |suffix| is the | 236 |
| 236 // user-specific registration suffix; see GetUserSpecificDefaultBrowserSuffix | 237 // The CLSID for the application's DelegateExecute handler. May be empty. |
| 237 // in shell_util.h for details. | 238 base::string16 delegate_clsid; |
| 238 static base::string16 GetBrowserClientKey(BrowserDistribution* dist, | 239 }; |
| 239 const base::string16& suffix) { | 240 |
| 240 DCHECK(suffix.empty() || suffix[0] == L'.'); | 241 // Gets the registry entries to register an application in the Windows registry. |
| 241 return base::string16(ShellUtil::kRegStartMenuInternet) | 242 // |app_info| provides all of the information needed. |
| 242 .append(1, L'\\') | 243 void GetProgIdEntries(const ApplicationInfo& app_info, |
| 243 .append(dist->GetBaseAppName()) | 244 ScopedVector<RegistryEntry>* entries) { |
| 244 .append(suffix); | 245 // Basic sanity checks. |
| 245 } | 246 DCHECK(!app_info.prog_id.empty()); |
| 246 | 247 DCHECK_NE(L'.', app_info.prog_id[0]); |
| 247 // Returns the Windows Default Programs capabilities key for Chrome. For | 248 |
| 248 // example: | 249 // File association ProgId |
| 249 // "Software\Clients\StartMenuInternet\Chromium[.user]\Capabilities". | 250 base::string16 prog_id_path(ShellUtil::kRegClasses); |
| 250 static base::string16 GetCapabilitiesKey(BrowserDistribution* dist, | 251 prog_id_path.push_back(base::FilePath::kSeparators[0]); |
| 251 const base::string16& suffix) { | 252 prog_id_path.append(app_info.prog_id); |
| 252 return GetBrowserClientKey(dist, suffix).append(L"\\Capabilities"); | 253 entries->push_back(new RegistryEntry(prog_id_path, app_info.file_type_name)); |
| 253 } | 254 entries->push_back(new RegistryEntry( |
| 254 | 255 prog_id_path + ShellUtil::kRegDefaultIcon, |
| 255 // This method returns a list of all the registry entries that | 256 ShellUtil::FormatIconLocation(app_info.file_type_icon_path, |
| 256 // are needed to register this installation's ProgId and AppId. | 257 app_info.file_type_icon_index))); |
| 257 // These entries need to be registered in HKLM prior to Win8. | 258 entries->push_back(new RegistryEntry(prog_id_path + ShellUtil::kRegShellOpen, |
| 258 static void GetChromeProgIdEntries(BrowserDistribution* dist, | 259 app_info.command_line)); |
| 259 const base::string16& chrome_exe, | 260 if (!app_info.delegate_clsid.empty()) { |
| 261 entries->push_back( |
| 262 new RegistryEntry(prog_id_path + ShellUtil::kRegShellOpen, |
| 263 ShellUtil::kRegDelegateExecute, |
| 264 app_info.delegate_clsid)); |
| 265 } |
| 266 |
| 267 // The following entries are required as of Windows 8, but do not |
| 268 // depend on the DelegateExecute verb handler being set. |
| 269 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { |
| 270 if (!app_info.app_id.empty()) { |
| 271 entries->push_back(new RegistryEntry( |
| 272 prog_id_path, ShellUtil::kRegAppUserModelId, app_info.app_id)); |
| 273 } |
| 274 |
| 275 // Add \Software\Classes\<prog_id>\Application entries |
| 276 base::string16 application_path(prog_id_path + ShellUtil::kRegApplication); |
| 277 if (!app_info.app_id.empty()) { |
| 278 entries->push_back(new RegistryEntry( |
| 279 application_path, ShellUtil::kRegAppUserModelId, app_info.app_id)); |
| 280 } |
| 281 if (!app_info.application_icon_path.empty()) { |
| 282 entries->push_back(new RegistryEntry( |
| 283 application_path, |
| 284 ShellUtil::kRegApplicationIcon, |
| 285 ShellUtil::FormatIconLocation(app_info.application_icon_path, |
| 286 app_info.application_icon_index))); |
| 287 } |
| 288 if (!app_info.application_name.empty()) { |
| 289 entries->push_back(new RegistryEntry(application_path, |
| 290 ShellUtil::kRegApplicationName, |
| 291 app_info.application_name)); |
| 292 } |
| 293 if (!app_info.application_description.empty()) { |
| 294 entries->push_back( |
| 295 new RegistryEntry(application_path, |
| 296 ShellUtil::kRegApplicationDescription, |
| 297 app_info.application_description)); |
| 298 } |
| 299 if (!app_info.publisher_name.empty()) { |
| 300 entries->push_back(new RegistryEntry(application_path, |
| 301 ShellUtil::kRegApplicationCompany, |
| 302 app_info.publisher_name)); |
| 303 } |
| 304 } |
| 305 } |
| 306 |
| 307 // This method returns a list of all the registry entries that are needed to |
| 308 // register this installation's ProgId and AppId. These entries need to be |
| 309 // registered in HKLM prior to Win8. |
| 310 void GetChromeProgIdEntries(BrowserDistribution* dist, |
| 311 const base::string16& chrome_exe, |
| 312 const base::string16& suffix, |
| 313 ScopedVector<RegistryEntry>* entries) { |
| 314 int chrome_icon_index = |
| 315 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME); |
| 316 |
| 317 ApplicationInfo app_info; |
| 318 app_info.prog_id = GetBrowserProgId(suffix); |
| 319 app_info.file_type_name = dist->GetBrowserProgIdDesc(); |
| 320 // File types associated with Chrome are just given the Chrome icon. |
| 321 app_info.file_type_icon_path = chrome_exe; |
| 322 app_info.file_type_icon_index = chrome_icon_index; |
| 323 app_info.command_line = ShellUtil::GetChromeShellOpenCmd(chrome_exe); |
| 324 // For user-level installs: entries for the app id will be in HKCU; thus we |
| 325 // do not need a suffix on those entries. |
| 326 app_info.app_id = ShellUtil::GetBrowserModelId( |
| 327 dist, InstallUtil::IsPerUserInstall(chrome_exe.c_str())); |
| 328 |
| 329 // The command to execute when opening this application via the Metro UI. |
| 330 base::string16 delegate_command( |
| 331 ShellUtil::GetChromeDelegateCommand(chrome_exe)); |
| 332 bool set_delegate_execute = |
| 333 IsChromeMetroSupported() && |
| 334 dist->GetCommandExecuteImplClsid(&app_info.delegate_clsid); |
| 335 |
| 336 // TODO(grt): http://crbug.com/75152 Write a reference to a localized |
| 337 // resource for name, description, and company. |
| 338 app_info.application_name = dist->GetDisplayName(); |
| 339 app_info.application_icon_path = chrome_exe; |
| 340 app_info.application_icon_index = chrome_icon_index; |
| 341 app_info.application_description = dist->GetAppDescription(); |
| 342 app_info.publisher_name = dist->GetPublisherName(); |
| 343 |
| 344 GetProgIdEntries(app_info, entries); |
| 345 |
| 346 // DelegateExecute ProgId. Needed for Chrome Metro in Windows 8. This is |
| 347 // only needed for registring a web browser, not for general associations. |
| 348 if (set_delegate_execute) { |
| 349 base::string16 model_id_shell(ShellUtil::kRegClasses); |
| 350 model_id_shell.push_back(base::FilePath::kSeparators[0]); |
| 351 model_id_shell.append(app_info.app_id); |
| 352 model_id_shell.append(ShellUtil::kRegExePath); |
| 353 model_id_shell.append(ShellUtil::kRegShellPath); |
| 354 |
| 355 // <root hkey>\Software\Classes\<app_id>\.exe\shell @=open |
| 356 entries->push_back( |
| 357 new RegistryEntry(model_id_shell, ShellUtil::kRegVerbOpen)); |
| 358 |
| 359 // Each of Chrome's shortcuts has an appid; which, as of Windows 8, is |
| 360 // registered to handle some verbs. This registration has the side-effect |
| 361 // that these verbs now show up in the shortcut's context menu. We |
| 362 // mitigate this side-effect by making the context menu entries |
| 363 // user readable/localized strings. See relevant MSDN article: |
| 364 // http://msdn.microsoft.com/en-US/library/windows/desktop/cc144171.aspx |
| 365 const struct { |
| 366 const wchar_t* verb; |
| 367 int name_id; |
| 368 } verbs[] = { |
| 369 {ShellUtil::kRegVerbOpen, -1}, |
| 370 {ShellUtil::kRegVerbOpenNewWindow, IDS_SHORTCUT_NEW_WINDOW_BASE}, |
| 371 }; |
| 372 for (size_t i = 0; i < arraysize(verbs); ++i) { |
| 373 base::string16 sub_path(model_id_shell); |
| 374 sub_path.push_back(base::FilePath::kSeparators[0]); |
| 375 sub_path.append(verbs[i].verb); |
| 376 |
| 377 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb> |
| 378 if (verbs[i].name_id != -1) { |
| 379 // TODO(grt): http://crbug.com/75152 Write a reference to a localized |
| 380 // resource. |
| 381 base::string16 verb_name( |
| 382 installer::GetLocalizedString(verbs[i].name_id)); |
| 383 entries->push_back(new RegistryEntry(sub_path, verb_name.c_str())); |
| 384 } |
| 385 entries->push_back( |
| 386 new RegistryEntry(sub_path, L"CommandId", L"Browser.Launch")); |
| 387 |
| 388 sub_path.push_back(base::FilePath::kSeparators[0]); |
| 389 sub_path.append(ShellUtil::kRegCommand); |
| 390 |
| 391 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>\command |
| 392 entries->push_back(new RegistryEntry(sub_path, delegate_command)); |
| 393 entries->push_back(new RegistryEntry( |
| 394 sub_path, ShellUtil::kRegDelegateExecute, app_info.delegate_clsid)); |
| 395 } |
| 396 } |
| 397 } |
| 398 |
| 399 // This method returns a list of the registry entries needed to declare a |
| 400 // capability of handling a protocol on Windows. |
| 401 void GetProtocolCapabilityEntries(BrowserDistribution* dist, |
| 402 const base::string16& suffix, |
| 403 const base::string16& protocol, |
| 404 ScopedVector<RegistryEntry>* entries) { |
| 405 entries->push_back(new RegistryEntry( |
| 406 GetCapabilitiesKey(dist, suffix).append(L"\\URLAssociations"), |
| 407 protocol, |
| 408 GetBrowserProgId(suffix))); |
| 409 } |
| 410 |
| 411 // This method returns a list of the registry entries required to register this |
| 412 // installation in "RegisteredApplications" on Windows (to appear in Default |
| 413 // Programs, StartMenuInternet, etc.). These entries need to be registered in |
| 414 // HKLM prior to Win8. If |suffix| is not empty, these entries are guaranteed to |
| 415 // be unique on this machine. |
| 416 void GetShellIntegrationEntries(BrowserDistribution* dist, |
| 417 const base::string16& chrome_exe, |
| 418 const base::string16& suffix, |
| 419 ScopedVector<RegistryEntry>* entries) { |
| 420 const base::string16 icon_path(ShellUtil::FormatIconLocation( |
| 421 chrome_exe, dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME))); |
| 422 const base::string16 quoted_exe_path(L"\"" + chrome_exe + L"\""); |
| 423 |
| 424 // Register for the Start Menu "Internet" link (pre-Win7). |
| 425 const base::string16 start_menu_entry(GetBrowserClientKey(dist, suffix)); |
| 426 // Register Chrome's display name. |
| 427 // TODO(grt): http://crbug.com/75152 Also set LocalizedString; see |
| 428 // http://msdn.microsoft.com/en-us/library/windows/desktop/cc144109(v=VS.85).a
spx#registering_the_display_name |
| 429 entries->push_back( |
| 430 new RegistryEntry(start_menu_entry, dist->GetDisplayName())); |
| 431 // Register the "open" verb for launching Chrome via the "Internet" link. |
| 432 entries->push_back(new RegistryEntry( |
| 433 start_menu_entry + ShellUtil::kRegShellOpen, quoted_exe_path)); |
| 434 // Register Chrome's icon for the Start Menu "Internet" link. |
| 435 entries->push_back(new RegistryEntry( |
| 436 start_menu_entry + ShellUtil::kRegDefaultIcon, icon_path)); |
| 437 |
| 438 // Register installation information. |
| 439 base::string16 install_info(start_menu_entry + L"\\InstallInfo"); |
| 440 // Note: not using CommandLine since it has ambiguous rules for quoting |
| 441 // strings. |
| 442 entries->push_back( |
| 443 new RegistryEntry(install_info, |
| 444 kReinstallCommand, |
| 445 quoted_exe_path + L" --" + |
| 446 base::ASCIIToWide(switches::kMakeDefaultBrowser))); |
| 447 entries->push_back(new RegistryEntry( |
| 448 install_info, |
| 449 L"HideIconsCommand", |
| 450 quoted_exe_path + L" --" + base::ASCIIToWide(switches::kHideIcons))); |
| 451 entries->push_back(new RegistryEntry( |
| 452 install_info, |
| 453 L"ShowIconsCommand", |
| 454 quoted_exe_path + L" --" + base::ASCIIToWide(switches::kShowIcons))); |
| 455 entries->push_back(new RegistryEntry(install_info, L"IconsVisible", 1)); |
| 456 |
| 457 // Register with Default Programs. |
| 458 const base::string16 reg_app_name(dist->GetBaseAppName().append(suffix)); |
| 459 // Tell Windows where to find Chrome's Default Programs info. |
| 460 const base::string16 capabilities(GetCapabilitiesKey(dist, suffix)); |
| 461 entries->push_back(new RegistryEntry( |
| 462 ShellUtil::kRegRegisteredApplications, reg_app_name, capabilities)); |
| 463 // Write out Chrome's Default Programs info. |
| 464 // TODO(grt): http://crbug.com/75152 Write a reference to a localized |
| 465 // resource rather than this. |
| 466 entries->push_back(new RegistryEntry(capabilities, |
| 467 ShellUtil::kRegApplicationDescription, |
| 468 dist->GetLongAppDescription())); |
| 469 entries->push_back(new RegistryEntry( |
| 470 capabilities, ShellUtil::kRegApplicationIcon, icon_path)); |
| 471 entries->push_back(new RegistryEntry( |
| 472 capabilities, ShellUtil::kRegApplicationName, dist->GetDisplayName())); |
| 473 |
| 474 entries->push_back(new RegistryEntry( |
| 475 capabilities + L"\\Startmenu", L"StartMenuInternet", reg_app_name)); |
| 476 |
| 477 const base::string16 html_prog_id(GetBrowserProgId(suffix)); |
| 478 for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) { |
| 479 entries->push_back( |
| 480 new RegistryEntry(capabilities + L"\\FileAssociations", |
| 481 ShellUtil::kPotentialFileAssociations[i], |
| 482 html_prog_id)); |
| 483 } |
| 484 for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL; i++) { |
| 485 entries->push_back( |
| 486 new RegistryEntry(capabilities + L"\\URLAssociations", |
| 487 ShellUtil::kPotentialProtocolAssociations[i], |
| 488 html_prog_id)); |
| 489 } |
| 490 } |
| 491 |
| 492 // Gets the registry entries to register an application as a handler for a |
| 493 // particular file extension. |prog_id| is the ProgId used by Windows for the |
| 494 // application. |ext| is the file extension, which must begin with a '.'. |
| 495 void GetAppExtRegistrationEntries(const base::string16& prog_id, |
| 496 const base::string16& ext, |
| 497 ScopedVector<RegistryEntry>* entries) { |
| 498 // In HKEY_CURRENT_USER\Software\Classes\EXT\OpenWithProgids, create an |
| 499 // empty value with this class's ProgId. |
| 500 base::string16 key_name(ShellUtil::kRegClasses); |
| 501 key_name.push_back(base::FilePath::kSeparators[0]); |
| 502 key_name.append(ext); |
| 503 key_name.push_back(base::FilePath::kSeparators[0]); |
| 504 key_name.append(ShellUtil::kRegOpenWithProgids); |
| 505 entries->push_back(new RegistryEntry(key_name, prog_id, base::string16())); |
| 506 } |
| 507 |
| 508 // This method returns a list of the registry entries required for this |
| 509 // installation to be registered in the Windows shell. In particular: |
| 510 // - App Paths |
| 511 // http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121 |
| 512 // - File Associations |
| 513 // http://msdn.microsoft.com/en-us/library/bb166549 |
| 514 // These entries need to be registered in HKLM prior to Win8. |
| 515 void GetChromeAppRegistrationEntries(const base::string16& chrome_exe, |
| 260 const base::string16& suffix, | 516 const base::string16& suffix, |
| 261 ScopedVector<RegistryEntry>* entries) { | 517 ScopedVector<RegistryEntry>* entries) { |
| 262 int chrome_icon_index = | 518 const base::FilePath chrome_path(chrome_exe); |
| 263 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME); | 519 base::string16 app_path_key(ShellUtil::kAppPathsRegistryKey); |
| 264 | 520 app_path_key.push_back(base::FilePath::kSeparators[0]); |
| 265 ApplicationInfo app_info; | 521 app_path_key.append(chrome_path.BaseName().value()); |
| 266 app_info.prog_id = GetBrowserProgId(suffix); | 522 entries->push_back(new RegistryEntry(app_path_key, chrome_exe)); |
| 267 app_info.file_type_name = dist->GetBrowserProgIdDesc(); | 523 entries->push_back(new RegistryEntry(app_path_key, |
| 268 // File types associated with Chrome are just given the Chrome icon. | 524 ShellUtil::kAppPathsRegistryPathName, |
| 269 app_info.file_type_icon_path = chrome_exe; | 525 chrome_path.DirName().value())); |
| 270 app_info.file_type_icon_index = chrome_icon_index; | 526 |
| 271 app_info.command_line = ShellUtil::GetChromeShellOpenCmd(chrome_exe); | 527 const base::string16 html_prog_id(GetBrowserProgId(suffix)); |
| 272 // For user-level installs: entries for the app id will be in HKCU; thus we | 528 for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) { |
| 273 // do not need a suffix on those entries. | 529 GetAppExtRegistrationEntries( |
| 274 app_info.app_id = ShellUtil::GetBrowserModelId( | 530 html_prog_id, ShellUtil::kPotentialFileAssociations[i], entries); |
| 275 dist, InstallUtil::IsPerUserInstall(chrome_exe.c_str())); | 531 } |
| 276 | 532 } |
| 277 // The command to execute when opening this application via the Metro UI. | 533 |
| 278 base::string16 delegate_command( | 534 // Gets the registry entries to register an application as the default handler |
| 279 ShellUtil::GetChromeDelegateCommand(chrome_exe)); | 535 // for a particular file extension. |prog_id| is the ProgId used by Windows for |
| 280 bool set_delegate_execute = | 536 // the application. |ext| is the file extension, which must begin with a '.'. If |
| 281 IsChromeMetroSupported() && | 537 // |overwrite_existing|, always sets the default handler; otherwise only sets if |
| 282 dist->GetCommandExecuteImplClsid(&app_info.delegate_clsid); | 538 // there is no existing default. |
| 283 | 539 // |
| 284 // TODO(grt): http://crbug.com/75152 Write a reference to a localized | 540 // This has no effect on Windows 8. Windows 8 ignores the default and lets the |
| 285 // resource for name, description, and company. | 541 // user choose. If there is only one handler for a file, it will automatically |
| 286 app_info.application_name = dist->GetDisplayName(); | 542 // become the default. Otherwise, the first time the user opens a file, they are |
| 287 app_info.application_icon_path = chrome_exe; | 543 // presented with the dialog to set the default handler. (This is roughly |
| 288 app_info.application_icon_index = chrome_icon_index; | 544 // equivalent to being called with |overwrite_existing| false.) |
| 289 app_info.application_description = dist->GetAppDescription(); | 545 void GetAppDefaultRegistrationEntries(const base::string16& prog_id, |
| 290 app_info.publisher_name = dist->GetPublisherName(); | 546 const base::string16& ext, |
| 291 | 547 bool overwrite_existing, |
| 292 GetProgIdEntries(app_info, entries); | 548 ScopedVector<RegistryEntry>* entries) { |
| 293 | 549 // Set the default value of HKEY_CURRENT_USER\Software\Classes\EXT to this |
| 294 // DelegateExecute ProgId. Needed for Chrome Metro in Windows 8. This is | 550 // class's name. |
| 295 // only needed for registring a web browser, not for general associations. | 551 base::string16 key_name(ShellUtil::kRegClasses); |
| 296 if (set_delegate_execute) { | 552 key_name.push_back(base::FilePath::kSeparators[0]); |
| 297 base::string16 model_id_shell(ShellUtil::kRegClasses); | 553 key_name.append(ext); |
| 298 model_id_shell.push_back(base::FilePath::kSeparators[0]); | 554 scoped_ptr<RegistryEntry> default_association( |
| 299 model_id_shell.append(app_info.app_id); | 555 new RegistryEntry(key_name, prog_id)); |
| 300 model_id_shell.append(ShellUtil::kRegExePath); | 556 if (overwrite_existing || |
| 301 model_id_shell.append(ShellUtil::kRegShellPath); | 557 !default_association->KeyExistsInRegistry(RegistryEntry::LOOK_IN_HKCU)) { |
| 302 | 558 entries->push_back(default_association.release()); |
| 303 // <root hkey>\Software\Classes\<app_id>\.exe\shell @=open | 559 } |
| 304 entries->push_back(new RegistryEntry(model_id_shell, | 560 } |
| 305 ShellUtil::kRegVerbOpen)); | 561 |
| 306 | 562 // This method returns a list of all the user level registry entries that are |
| 307 // Each of Chrome's shortcuts has an appid; which, as of Windows 8, is | 563 // needed to make Chromium the default handler for a protocol on XP. |
| 308 // registered to handle some verbs. This registration has the side-effect | 564 void GetXPStyleUserProtocolEntries(const base::string16& protocol, |
| 309 // that these verbs now show up in the shortcut's context menu. We | 565 const base::string16& chrome_icon, |
| 310 // mitigate this side-effect by making the context menu entries | 566 const base::string16& chrome_open, |
| 311 // user readable/localized strings. See relevant MSDN article: | 567 ScopedVector<RegistryEntry>* entries) { |
| 312 // http://msdn.microsoft.com/en-US/library/windows/desktop/cc144171.aspx | 568 // Protocols associations. |
| 313 const struct { | 569 base::string16 url_key(ShellUtil::kRegClasses); |
| 314 const wchar_t* verb; | 570 url_key.push_back(base::FilePath::kSeparators[0]); |
| 315 int name_id; | 571 url_key.append(protocol); |
| 316 } verbs[] = { | 572 |
| 317 { ShellUtil::kRegVerbOpen, -1 }, | 573 // This registry value tells Windows that this 'class' is a URL scheme |
| 318 { ShellUtil::kRegVerbOpenNewWindow, IDS_SHORTCUT_NEW_WINDOW_BASE }, | 574 // so IE, explorer and other apps will route it to our handler. |
| 319 }; | 575 // <root hkey>\Software\Classes\<protocol>\URL Protocol |
| 320 for (size_t i = 0; i < arraysize(verbs); ++i) { | 576 entries->push_back( |
| 321 base::string16 sub_path(model_id_shell); | 577 new RegistryEntry(url_key, ShellUtil::kRegUrlProtocol, base::string16())); |
| 322 sub_path.push_back(base::FilePath::kSeparators[0]); | 578 |
| 323 sub_path.append(verbs[i].verb); | 579 // <root hkey>\Software\Classes\<protocol>\DefaultIcon |
| 324 | 580 base::string16 icon_key = url_key + ShellUtil::kRegDefaultIcon; |
| 325 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb> | 581 entries->push_back(new RegistryEntry(icon_key, chrome_icon)); |
| 326 if (verbs[i].name_id != -1) { | 582 |
| 327 // TODO(grt): http://crbug.com/75152 Write a reference to a localized | 583 // <root hkey>\Software\Classes\<protocol>\shell\open\command |
| 328 // resource. | 584 base::string16 shell_key = url_key + ShellUtil::kRegShellOpen; |
| 329 base::string16 verb_name( | 585 entries->push_back(new RegistryEntry(shell_key, chrome_open)); |
| 330 installer::GetLocalizedString(verbs[i].name_id)); | 586 |
| 331 entries->push_back(new RegistryEntry(sub_path, verb_name.c_str())); | 587 // <root hkey>\Software\Classes\<protocol>\shell\open\ddeexec |
| 332 } | 588 base::string16 dde_key = url_key + L"\\shell\\open\\ddeexec"; |
| 333 entries->push_back(new RegistryEntry( | 589 entries->push_back(new RegistryEntry(dde_key, base::string16())); |
| 334 sub_path, L"CommandId", L"Browser.Launch")); | 590 |
| 335 | 591 // <root hkey>\Software\Classes\<protocol>\shell\@ |
| 336 sub_path.push_back(base::FilePath::kSeparators[0]); | 592 base::string16 protocol_shell_key = url_key + ShellUtil::kRegShellPath; |
| 337 sub_path.append(ShellUtil::kRegCommand); | 593 entries->push_back(new RegistryEntry(protocol_shell_key, L"open")); |
| 338 | 594 } |
| 339 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>\command | 595 |
| 340 entries->push_back(new RegistryEntry(sub_path, delegate_command)); | 596 // This method returns a list of all the user level registry entries that are |
| 341 entries->push_back(new RegistryEntry( | 597 // needed to make Chromium default browser on XP. Some of these entries are |
| 342 sub_path, ShellUtil::kRegDelegateExecute, app_info.delegate_clsid)); | 598 // irrelevant in recent versions of Windows, but we register them anyways as |
| 343 } | 599 // some legacy apps are hardcoded to lookup those values. |
| 344 } | 600 void GetXPStyleDefaultBrowserUserEntries(BrowserDistribution* dist, |
| 345 } | |
| 346 | |
| 347 // Gets the registry entries to register an application in the Windows | |
| 348 // registry. |app_info| provides all of the information needed. | |
| 349 static void GetProgIdEntries(const ApplicationInfo& app_info, | |
| 350 ScopedVector<RegistryEntry>* entries) { | |
| 351 // Basic sanity checks. | |
| 352 DCHECK(!app_info.prog_id.empty()); | |
| 353 DCHECK_NE(L'.', app_info.prog_id[0]); | |
| 354 | |
| 355 // File association ProgId | |
| 356 base::string16 prog_id_path(ShellUtil::kRegClasses); | |
| 357 prog_id_path.push_back(base::FilePath::kSeparators[0]); | |
| 358 prog_id_path.append(app_info.prog_id); | |
| 359 entries->push_back( | |
| 360 new RegistryEntry(prog_id_path, app_info.file_type_name)); | |
| 361 entries->push_back(new RegistryEntry( | |
| 362 prog_id_path + ShellUtil::kRegDefaultIcon, | |
| 363 ShellUtil::FormatIconLocation(app_info.file_type_icon_path, | |
| 364 app_info.file_type_icon_index))); | |
| 365 entries->push_back(new RegistryEntry( | |
| 366 prog_id_path + ShellUtil::kRegShellOpen, app_info.command_line)); | |
| 367 if (!app_info.delegate_clsid.empty()) { | |
| 368 entries->push_back( | |
| 369 new RegistryEntry(prog_id_path + ShellUtil::kRegShellOpen, | |
| 370 ShellUtil::kRegDelegateExecute, | |
| 371 app_info.delegate_clsid)); | |
| 372 } | |
| 373 | |
| 374 // The following entries are required as of Windows 8, but do not | |
| 375 // depend on the DelegateExecute verb handler being set. | |
| 376 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { | |
| 377 if (!app_info.app_id.empty()) { | |
| 378 entries->push_back(new RegistryEntry( | |
| 379 prog_id_path, ShellUtil::kRegAppUserModelId, app_info.app_id)); | |
| 380 } | |
| 381 | |
| 382 // Add \Software\Classes\<prog_id>\Application entries | |
| 383 base::string16 application_path(prog_id_path + | |
| 384 ShellUtil::kRegApplication); | |
| 385 if (!app_info.app_id.empty()) { | |
| 386 entries->push_back(new RegistryEntry( | |
| 387 application_path, ShellUtil::kRegAppUserModelId, app_info.app_id)); | |
| 388 } | |
| 389 if (!app_info.application_icon_path.empty()) { | |
| 390 entries->push_back(new RegistryEntry( | |
| 391 application_path, | |
| 392 ShellUtil::kRegApplicationIcon, | |
| 393 ShellUtil::FormatIconLocation(app_info.application_icon_path, | |
| 394 app_info.application_icon_index))); | |
| 395 } | |
| 396 if (!app_info.application_name.empty()) { | |
| 397 entries->push_back(new RegistryEntry(application_path, | |
| 398 ShellUtil::kRegApplicationName, | |
| 399 app_info.application_name)); | |
| 400 } | |
| 401 if (!app_info.application_description.empty()) { | |
| 402 entries->push_back( | |
| 403 new RegistryEntry(application_path, | |
| 404 ShellUtil::kRegApplicationDescription, | |
| 405 app_info.application_description)); | |
| 406 } | |
| 407 if (!app_info.publisher_name.empty()) { | |
| 408 entries->push_back(new RegistryEntry(application_path, | |
| 409 ShellUtil::kRegApplicationCompany, | |
| 410 app_info.publisher_name)); | |
| 411 } | |
| 412 } | |
| 413 } | |
| 414 | |
| 415 // This method returns a list of the registry entries needed to declare a | |
| 416 // capability of handling a protocol on Windows. | |
| 417 static void GetProtocolCapabilityEntries( | |
| 418 BrowserDistribution* dist, | |
| 419 const base::string16& suffix, | |
| 420 const base::string16& protocol, | |
| 421 ScopedVector<RegistryEntry>* entries) { | |
| 422 entries->push_back(new RegistryEntry( | |
| 423 GetCapabilitiesKey(dist, suffix).append(L"\\URLAssociations"), | |
| 424 protocol, GetBrowserProgId(suffix))); | |
| 425 } | |
| 426 | |
| 427 // This method returns a list of the registry entries required to register | |
| 428 // this installation in "RegisteredApplications" on Windows (to appear in | |
| 429 // Default Programs, StartMenuInternet, etc.). | |
| 430 // These entries need to be registered in HKLM prior to Win8. | |
| 431 // If |suffix| is not empty, these entries are guaranteed to be unique on this | |
| 432 // machine. | |
| 433 static void GetShellIntegrationEntries(BrowserDistribution* dist, | |
| 434 const base::string16& chrome_exe, | 601 const base::string16& chrome_exe, |
| 435 const base::string16& suffix, | 602 const base::string16& suffix, |
| 436 ScopedVector<RegistryEntry>* entries) { | 603 ScopedVector<RegistryEntry>* entries) { |
| 437 const base::string16 icon_path( | 604 // File extension associations. |
| 438 ShellUtil::FormatIconLocation( | 605 base::string16 html_prog_id(GetBrowserProgId(suffix)); |
| 439 chrome_exe, | 606 for (int i = 0; ShellUtil::kDefaultFileAssociations[i] != NULL; i++) { |
| 440 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME))); | 607 GetAppDefaultRegistrationEntries( |
| 441 const base::string16 quoted_exe_path(L"\"" + chrome_exe + L"\""); | 608 html_prog_id, ShellUtil::kDefaultFileAssociations[i], true, entries); |
| 442 | 609 } |
| 443 // Register for the Start Menu "Internet" link (pre-Win7). | 610 |
| 444 const base::string16 start_menu_entry(GetBrowserClientKey(dist, suffix)); | 611 // Protocols associations. |
| 445 // Register Chrome's display name. | 612 base::string16 chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe); |
| 446 // TODO(grt): http://crbug.com/75152 Also set LocalizedString; see | 613 base::string16 chrome_icon = ShellUtil::FormatIconLocation( |
| 447 // http://msdn.microsoft.com/en-us/library/windows/desktop/cc144109(v=VS.85)
.aspx#registering_the_display_name | 614 chrome_exe, dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME)); |
| 448 entries->push_back(new RegistryEntry( | 615 for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) { |
| 449 start_menu_entry, dist->GetDisplayName())); | 616 GetXPStyleUserProtocolEntries(ShellUtil::kBrowserProtocolAssociations[i], |
| 450 // Register the "open" verb for launching Chrome via the "Internet" link. | 617 chrome_icon, |
| 451 entries->push_back(new RegistryEntry( | 618 chrome_open, |
| 452 start_menu_entry + ShellUtil::kRegShellOpen, quoted_exe_path)); | 619 entries); |
| 453 // Register Chrome's icon for the Start Menu "Internet" link. | 620 } |
| 454 entries->push_back(new RegistryEntry( | 621 |
| 455 start_menu_entry + ShellUtil::kRegDefaultIcon, icon_path)); | 622 // start->Internet shortcut. |
| 456 | 623 base::string16 start_menu(ShellUtil::kRegStartMenuInternet); |
| 457 // Register installation information. | 624 base::string16 app_name = dist->GetBaseAppName() + suffix; |
| 458 base::string16 install_info(start_menu_entry + L"\\InstallInfo"); | 625 entries->push_back(new RegistryEntry(start_menu, app_name)); |
| 459 // Note: not using CommandLine since it has ambiguous rules for quoting | 626 } |
| 460 // strings. | |
| 461 entries->push_back(new RegistryEntry(install_info, kReinstallCommand, | |
| 462 quoted_exe_path + L" --" + | |
| 463 base::ASCIIToWide(switches::kMakeDefaultBrowser))); | |
| 464 entries->push_back(new RegistryEntry(install_info, L"HideIconsCommand", | |
| 465 quoted_exe_path + L" --" + | |
| 466 base::ASCIIToWide(switches::kHideIcons))); | |
| 467 entries->push_back(new RegistryEntry(install_info, L"ShowIconsCommand", | |
| 468 quoted_exe_path + L" --" + | |
| 469 base::ASCIIToWide(switches::kShowIcons))); | |
| 470 entries->push_back(new RegistryEntry(install_info, L"IconsVisible", 1)); | |
| 471 | |
| 472 // Register with Default Programs. | |
| 473 const base::string16 reg_app_name(dist->GetBaseAppName().append(suffix)); | |
| 474 // Tell Windows where to find Chrome's Default Programs info. | |
| 475 const base::string16 capabilities(GetCapabilitiesKey(dist, suffix)); | |
| 476 entries->push_back(new RegistryEntry(ShellUtil::kRegRegisteredApplications, | |
| 477 reg_app_name, capabilities)); | |
| 478 // Write out Chrome's Default Programs info. | |
| 479 // TODO(grt): http://crbug.com/75152 Write a reference to a localized | |
| 480 // resource rather than this. | |
| 481 entries->push_back(new RegistryEntry( | |
| 482 capabilities, ShellUtil::kRegApplicationDescription, | |
| 483 dist->GetLongAppDescription())); | |
| 484 entries->push_back(new RegistryEntry( | |
| 485 capabilities, ShellUtil::kRegApplicationIcon, icon_path)); | |
| 486 entries->push_back(new RegistryEntry( | |
| 487 capabilities, ShellUtil::kRegApplicationName, | |
| 488 dist->GetDisplayName())); | |
| 489 | |
| 490 entries->push_back(new RegistryEntry(capabilities + L"\\Startmenu", | |
| 491 L"StartMenuInternet", reg_app_name)); | |
| 492 | |
| 493 const base::string16 html_prog_id(GetBrowserProgId(suffix)); | |
| 494 for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) { | |
| 495 entries->push_back(new RegistryEntry( | |
| 496 capabilities + L"\\FileAssociations", | |
| 497 ShellUtil::kPotentialFileAssociations[i], html_prog_id)); | |
| 498 } | |
| 499 for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL; | |
| 500 i++) { | |
| 501 entries->push_back(new RegistryEntry( | |
| 502 capabilities + L"\\URLAssociations", | |
| 503 ShellUtil::kPotentialProtocolAssociations[i], html_prog_id)); | |
| 504 } | |
| 505 } | |
| 506 | |
| 507 // This method returns a list of the registry entries required for this | |
| 508 // installation to be registered in the Windows shell. | |
| 509 // In particular: | |
| 510 // - App Paths | |
| 511 // http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121 | |
| 512 // - File Associations | |
| 513 // http://msdn.microsoft.com/en-us/library/bb166549 | |
| 514 // These entries need to be registered in HKLM prior to Win8. | |
| 515 static void GetChromeAppRegistrationEntries( | |
| 516 const base::string16& chrome_exe, | |
| 517 const base::string16& suffix, | |
| 518 ScopedVector<RegistryEntry>* entries) { | |
| 519 const base::FilePath chrome_path(chrome_exe); | |
| 520 base::string16 app_path_key(ShellUtil::kAppPathsRegistryKey); | |
| 521 app_path_key.push_back(base::FilePath::kSeparators[0]); | |
| 522 app_path_key.append(chrome_path.BaseName().value()); | |
| 523 entries->push_back(new RegistryEntry(app_path_key, chrome_exe)); | |
| 524 entries->push_back(new RegistryEntry(app_path_key, | |
| 525 ShellUtil::kAppPathsRegistryPathName, chrome_path.DirName().value())); | |
| 526 | |
| 527 const base::string16 html_prog_id(GetBrowserProgId(suffix)); | |
| 528 for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) { | |
| 529 GetAppExtRegistrationEntries( | |
| 530 html_prog_id, ShellUtil::kPotentialFileAssociations[i], entries); | |
| 531 } | |
| 532 } | |
| 533 | |
| 534 // Gets the registry entries to register an application as a handler for a | |
| 535 // particular file extension. |prog_id| is the ProgId used by Windows for the | |
| 536 // application. |ext| is the file extension, which must begin with a '.'. | |
| 537 static void GetAppExtRegistrationEntries( | |
| 538 const base::string16& prog_id, | |
| 539 const base::string16& ext, | |
| 540 ScopedVector<RegistryEntry>* entries) { | |
| 541 // In HKEY_CURRENT_USER\Software\Classes\EXT\OpenWithProgids, create an | |
| 542 // empty value with this class's ProgId. | |
| 543 base::string16 key_name(ShellUtil::kRegClasses); | |
| 544 key_name.push_back(base::FilePath::kSeparators[0]); | |
| 545 key_name.append(ext); | |
| 546 key_name.push_back(base::FilePath::kSeparators[0]); | |
| 547 key_name.append(ShellUtil::kRegOpenWithProgids); | |
| 548 entries->push_back(new RegistryEntry(key_name, prog_id, base::string16())); | |
| 549 } | |
| 550 | |
| 551 // Gets the registry entries to register an application as the default handler | |
| 552 // for a particular file extension. |prog_id| is the ProgId used by Windows | |
| 553 // for the application. |ext| is the file extension, which must begin with a | |
| 554 // '.'. If |overwrite_existing|, always sets the default handler; otherwise | |
| 555 // only sets if there is no existing default. | |
| 556 // | |
| 557 // This has no effect on Windows 8. Windows 8 ignores the default and lets the | |
| 558 // user choose. If there is only one handler for a file, it will automatically | |
| 559 // become the default. Otherwise, the first time the user opens a file, they | |
| 560 // are presented with the dialog to set the default handler. (This is roughly | |
| 561 // equivalent to being called with |overwrite_existing| false.) | |
| 562 static void GetAppDefaultRegistrationEntries( | |
| 563 const base::string16& prog_id, | |
| 564 const base::string16& ext, | |
| 565 bool overwrite_existing, | |
| 566 ScopedVector<RegistryEntry>* entries) { | |
| 567 // Set the default value of HKEY_CURRENT_USER\Software\Classes\EXT to this | |
| 568 // class's name. | |
| 569 base::string16 key_name(ShellUtil::kRegClasses); | |
| 570 key_name.push_back(base::FilePath::kSeparators[0]); | |
| 571 key_name.append(ext); | |
| 572 scoped_ptr<RegistryEntry> default_association( | |
| 573 new RegistryEntry(key_name, prog_id)); | |
| 574 if (overwrite_existing || | |
| 575 !default_association->KeyExistsInRegistry( | |
| 576 RegistryEntry::LOOK_IN_HKCU)) { | |
| 577 entries->push_back(default_association.release()); | |
| 578 } | |
| 579 } | |
| 580 | |
| 581 // This method returns a list of all the user level registry entries that | |
| 582 // are needed to make Chromium the default handler for a protocol on XP. | |
| 583 static void GetXPStyleUserProtocolEntries( | |
| 584 const base::string16& protocol, | |
| 585 const base::string16& chrome_icon, | |
| 586 const base::string16& chrome_open, | |
| 587 ScopedVector<RegistryEntry>* entries) { | |
| 588 // Protocols associations. | |
| 589 base::string16 url_key(ShellUtil::kRegClasses); | |
| 590 url_key.push_back(base::FilePath::kSeparators[0]); | |
| 591 url_key.append(protocol); | |
| 592 | |
| 593 // This registry value tells Windows that this 'class' is a URL scheme | |
| 594 // so IE, explorer and other apps will route it to our handler. | |
| 595 // <root hkey>\Software\Classes\<protocol>\URL Protocol | |
| 596 entries->push_back(new RegistryEntry(url_key, | |
| 597 ShellUtil::kRegUrlProtocol, base::string16())); | |
| 598 | |
| 599 // <root hkey>\Software\Classes\<protocol>\DefaultIcon | |
| 600 base::string16 icon_key = url_key + ShellUtil::kRegDefaultIcon; | |
| 601 entries->push_back(new RegistryEntry(icon_key, chrome_icon)); | |
| 602 | |
| 603 // <root hkey>\Software\Classes\<protocol>\shell\open\command | |
| 604 base::string16 shell_key = url_key + ShellUtil::kRegShellOpen; | |
| 605 entries->push_back(new RegistryEntry(shell_key, chrome_open)); | |
| 606 | |
| 607 // <root hkey>\Software\Classes\<protocol>\shell\open\ddeexec | |
| 608 base::string16 dde_key = url_key + L"\\shell\\open\\ddeexec"; | |
| 609 entries->push_back(new RegistryEntry(dde_key, base::string16())); | |
| 610 | |
| 611 // <root hkey>\Software\Classes\<protocol>\shell\@ | |
| 612 base::string16 protocol_shell_key = url_key + ShellUtil::kRegShellPath; | |
| 613 entries->push_back(new RegistryEntry(protocol_shell_key, L"open")); | |
| 614 } | |
| 615 | |
| 616 // This method returns a list of all the user level registry entries that | |
| 617 // are needed to make Chromium default browser on XP. | |
| 618 // Some of these entries are irrelevant in recent versions of Windows, but | |
| 619 // we register them anyways as some legacy apps are hardcoded to lookup those | |
| 620 // values. | |
| 621 static void GetXPStyleDefaultBrowserUserEntries( | |
| 622 BrowserDistribution* dist, | |
| 623 const base::string16& chrome_exe, | |
| 624 const base::string16& suffix, | |
| 625 ScopedVector<RegistryEntry>* entries) { | |
| 626 // File extension associations. | |
| 627 base::string16 html_prog_id(GetBrowserProgId(suffix)); | |
| 628 for (int i = 0; ShellUtil::kDefaultFileAssociations[i] != NULL; i++) { | |
| 629 GetAppDefaultRegistrationEntries( | |
| 630 html_prog_id, ShellUtil::kDefaultFileAssociations[i], true, entries); | |
| 631 } | |
| 632 | |
| 633 // Protocols associations. | |
| 634 base::string16 chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe); | |
| 635 base::string16 chrome_icon = | |
| 636 ShellUtil::FormatIconLocation( | |
| 637 chrome_exe, | |
| 638 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME)); | |
| 639 for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) { | |
| 640 GetXPStyleUserProtocolEntries(ShellUtil::kBrowserProtocolAssociations[i], | |
| 641 chrome_icon, chrome_open, entries); | |
| 642 } | |
| 643 | |
| 644 // start->Internet shortcut. | |
| 645 base::string16 start_menu(ShellUtil::kRegStartMenuInternet); | |
| 646 base::string16 app_name = dist->GetBaseAppName() + suffix; | |
| 647 entries->push_back(new RegistryEntry(start_menu, app_name)); | |
| 648 } | |
| 649 | |
| 650 // Generate work_item tasks required to create current registry entry and | |
| 651 // add them to the given work item list. | |
| 652 void AddToWorkItemList(HKEY root, WorkItemList *items) const { | |
| 653 items->AddCreateRegKeyWorkItem(root, key_path_, WorkItem::kWow64Default); | |
| 654 if (is_string_) { | |
| 655 items->AddSetRegValueWorkItem( | |
| 656 root, key_path_, WorkItem::kWow64Default, name_, value_, true); | |
| 657 } else { | |
| 658 items->AddSetRegValueWorkItem( | |
| 659 root, key_path_, WorkItem::kWow64Default, name_, int_value_, true); | |
| 660 } | |
| 661 } | |
| 662 | |
| 663 // Checks if the current registry entry exists in HKCU\|key_path_|\|name_| | |
| 664 // and value is |value_|. If the key does NOT exist in HKCU, checks for | |
| 665 // the correct name and value in HKLM. | |
| 666 // |look_for_in| specifies roots (HKCU and/or HKLM) in which to look for the | |
| 667 // key, unspecified roots are not looked into (i.e. the the key is assumed not | |
| 668 // to exist in them). | |
| 669 // |look_for_in| must at least specify one root to look into. | |
| 670 // If |look_for_in| is LOOK_IN_HKCU_THEN_HKLM, this method mimics Windows' | |
| 671 // behavior when searching in HKCR (HKCU takes precedence over HKLM). For | |
| 672 // registrations outside of HKCR on versions of Windows prior to Win8, | |
| 673 // Chrome's values go in HKLM. This function will make unnecessary (but | |
| 674 // harmless) queries into HKCU in that case. | |
| 675 bool ExistsInRegistry(uint32 look_for_in) const { | |
| 676 DCHECK(look_for_in); | |
| 677 | |
| 678 RegistryStatus status = DOES_NOT_EXIST; | |
| 679 if (look_for_in & LOOK_IN_HKCU) | |
| 680 status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER); | |
| 681 if (status == DOES_NOT_EXIST && (look_for_in & LOOK_IN_HKLM)) | |
| 682 status = StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE); | |
| 683 return status == SAME_VALUE; | |
| 684 } | |
| 685 | |
| 686 // Checks if the current registry entry exists in \|key_path_|\|name_|, | |
| 687 // regardless of value. Same lookup rules as ExistsInRegistry. | |
| 688 // Unlike ExistsInRegistry, this returns true if some other value is present | |
| 689 // with the same key. | |
| 690 bool KeyExistsInRegistry(uint32 look_for_in) const { | |
| 691 DCHECK(look_for_in); | |
| 692 | |
| 693 RegistryStatus status = DOES_NOT_EXIST; | |
| 694 if (look_for_in & LOOK_IN_HKCU) | |
| 695 status = StatusInRegistryUnderRoot(HKEY_CURRENT_USER); | |
| 696 if (status == DOES_NOT_EXIST && (look_for_in & LOOK_IN_HKLM)) | |
| 697 status = StatusInRegistryUnderRoot(HKEY_LOCAL_MACHINE); | |
| 698 return status != DOES_NOT_EXIST; | |
| 699 } | |
| 700 | |
| 701 private: | |
| 702 // States this RegistryKey can be in compared to the registry. | |
| 703 enum RegistryStatus { | |
| 704 // |name_| does not exist in the registry | |
| 705 DOES_NOT_EXIST, | |
| 706 // |name_| exists, but its value != |value_| | |
| 707 DIFFERENT_VALUE, | |
| 708 // |name_| exists and its value is |value_| | |
| 709 SAME_VALUE, | |
| 710 }; | |
| 711 | |
| 712 // Create a object that represent default value of a key | |
| 713 RegistryEntry(const base::string16& key_path, const base::string16& value) | |
| 714 : key_path_(key_path), name_(), | |
| 715 is_string_(true), value_(value), int_value_(0) { | |
| 716 } | |
| 717 | |
| 718 // Create a object that represent a key of type REG_SZ | |
| 719 RegistryEntry(const base::string16& key_path, const base::string16& name, | |
| 720 const base::string16& value) | |
| 721 : key_path_(key_path), name_(name), | |
| 722 is_string_(true), value_(value), int_value_(0) { | |
| 723 } | |
| 724 | |
| 725 // Create a object that represent a key of integer type | |
| 726 RegistryEntry(const base::string16& key_path, const base::string16& name, | |
| 727 DWORD value) | |
| 728 : key_path_(key_path), name_(name), | |
| 729 is_string_(false), value_(), int_value_(value) { | |
| 730 } | |
| 731 | |
| 732 base::string16 key_path_; // key path for the registry entry | |
| 733 base::string16 name_; // name of the registry entry | |
| 734 bool is_string_; // true if current registry entry is of type REG_SZ | |
| 735 base::string16 value_; // string value (useful if is_string_ = true) | |
| 736 DWORD int_value_; // integer value (useful if is_string_ = false) | |
| 737 | |
| 738 // Helper function for ExistsInRegistry(). | |
| 739 // Returns the RegistryStatus of the current registry entry in | |
| 740 // |root|\|key_path_|\|name_|. | |
| 741 RegistryStatus StatusInRegistryUnderRoot(HKEY root) const { | |
| 742 RegKey key(root, key_path_.c_str(), KEY_QUERY_VALUE); | |
| 743 bool found = false; | |
| 744 bool correct_value = false; | |
| 745 if (is_string_) { | |
| 746 base::string16 read_value; | |
| 747 found = key.ReadValue(name_.c_str(), &read_value) == ERROR_SUCCESS; | |
| 748 if (found) { | |
| 749 correct_value = read_value.size() == value_.size() && | |
| 750 std::equal(value_.begin(), value_.end(), read_value.begin(), | |
| 751 base::CaseInsensitiveCompare<wchar_t>()); | |
| 752 } | |
| 753 } else { | |
| 754 DWORD read_value; | |
| 755 found = key.ReadValueDW(name_.c_str(), &read_value) == ERROR_SUCCESS; | |
| 756 if (found) | |
| 757 correct_value = read_value == int_value_; | |
| 758 } | |
| 759 return found ? | |
| 760 (correct_value ? SAME_VALUE : DIFFERENT_VALUE) : DOES_NOT_EXIST; | |
| 761 } | |
| 762 | |
| 763 DISALLOW_COPY_AND_ASSIGN(RegistryEntry); | |
| 764 }; // class RegistryEntry | |
| 765 | |
| 766 | 627 |
| 767 // This method converts all the RegistryEntries from the given list to | 628 // This method converts all the RegistryEntries from the given list to |
| 768 // Set/CreateRegWorkItems and runs them using WorkItemList. | 629 // Set/CreateRegWorkItems and runs them using WorkItemList. |
| 769 bool AddRegistryEntries(HKEY root, const ScopedVector<RegistryEntry>& entries) { | 630 bool AddRegistryEntries(HKEY root, const ScopedVector<RegistryEntry>& entries) { |
| 770 scoped_ptr<WorkItemList> items(WorkItem::CreateWorkItemList()); | 631 scoped_ptr<WorkItemList> items(WorkItem::CreateWorkItemList()); |
| 771 | 632 |
| 772 for (ScopedVector<RegistryEntry>::const_iterator itr = entries.begin(); | 633 for (ScopedVector<RegistryEntry>::const_iterator itr = entries.begin(); |
| 773 itr != entries.end(); ++itr) | 634 itr != entries.end(); ++itr) |
| 774 (*itr)->AddToWorkItemList(root, items.get()); | 635 (*itr)->AddToWorkItemList(root, items.get()); |
| 775 | 636 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 804 // under a single registry root. Not doing so caused http://crbug.com/144910 for | 665 // under a single registry root. Not doing so caused http://crbug.com/144910 for |
| 805 // users who first-installed Chrome in that revision range (those users are | 666 // users who first-installed Chrome in that revision range (those users are |
| 806 // still impacted by http://crbug.com/144910). This method will keep returning | 667 // still impacted by http://crbug.com/144910). This method will keep returning |
| 807 // true for affected users (i.e. who have all the registrations, but over both | 668 // true for affected users (i.e. who have all the registrations, but over both |
| 808 // registry roots). | 669 // registry roots). |
| 809 bool IsChromeRegistered(BrowserDistribution* dist, | 670 bool IsChromeRegistered(BrowserDistribution* dist, |
| 810 const base::string16& chrome_exe, | 671 const base::string16& chrome_exe, |
| 811 const base::string16& suffix, | 672 const base::string16& suffix, |
| 812 uint32 look_for_in) { | 673 uint32 look_for_in) { |
| 813 ScopedVector<RegistryEntry> entries; | 674 ScopedVector<RegistryEntry> entries; |
| 814 RegistryEntry::GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries); | 675 GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries); |
| 815 RegistryEntry::GetShellIntegrationEntries(dist, chrome_exe, suffix, &entries); | 676 GetShellIntegrationEntries(dist, chrome_exe, suffix, &entries); |
| 816 RegistryEntry::GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries); | 677 GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries); |
| 817 return AreEntriesRegistered(entries, look_for_in); | 678 return AreEntriesRegistered(entries, look_for_in); |
| 818 } | 679 } |
| 819 | 680 |
| 820 // This method checks if Chrome is already registered on the local machine | 681 // This method checks if Chrome is already registered on the local machine |
| 821 // for the requested protocol. It just checks the one value required for this. | 682 // for the requested protocol. It just checks the one value required for this. |
| 822 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. | 683 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. |
| 823 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, | 684 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, |
| 824 const base::string16& suffix, | 685 const base::string16& suffix, |
| 825 const base::string16& protocol, | 686 const base::string16& protocol, |
| 826 uint32 look_for_in) { | 687 uint32 look_for_in) { |
| 827 ScopedVector<RegistryEntry> entries; | 688 ScopedVector<RegistryEntry> entries; |
| 828 RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); | 689 GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); |
| 829 return AreEntriesRegistered(entries, look_for_in); | 690 return AreEntriesRegistered(entries, look_for_in); |
| 830 } | 691 } |
| 831 | 692 |
| 832 // This method registers Chrome on Vista by launching an elevated setup.exe. | 693 // This method registers Chrome on Vista by launching an elevated setup.exe. |
| 833 // That will show the user the standard Vista elevation prompt. If the user | 694 // That will show the user the standard Vista elevation prompt. If the user |
| 834 // accepts it the new process will make the necessary changes and return SUCCESS | 695 // accepts it the new process will make the necessary changes and return SUCCESS |
| 835 // that we capture and return. | 696 // that we capture and return. |
| 836 // If protocol is non-empty we will also register Chrome as being capable of | 697 // If protocol is non-empty we will also register Chrome as being capable of |
| 837 // handling the protocol. | 698 // handling the protocol. |
| 838 bool ElevateAndRegisterChrome(BrowserDistribution* dist, | 699 bool ElevateAndRegisterChrome(BrowserDistribution* dist, |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 932 case CONFIRM_PROGID_REGISTRATION: | 793 case CONFIRM_PROGID_REGISTRATION: |
| 933 // Software\Classes\ChromeHTML|suffix| | 794 // Software\Classes\ChromeHTML|suffix| |
| 934 reg_key = ShellUtil::kRegClasses; | 795 reg_key = ShellUtil::kRegClasses; |
| 935 reg_key.push_back(base::FilePath::kSeparators[0]); | 796 reg_key.push_back(base::FilePath::kSeparators[0]); |
| 936 reg_key.append(dist->GetBrowserProgIdPrefix()); | 797 reg_key.append(dist->GetBrowserProgIdPrefix()); |
| 937 reg_key.append(suffix); | 798 reg_key.append(suffix); |
| 938 break; | 799 break; |
| 939 case CONFIRM_SHELL_REGISTRATION: | 800 case CONFIRM_SHELL_REGISTRATION: |
| 940 case CONFIRM_SHELL_REGISTRATION_IN_HKLM: | 801 case CONFIRM_SHELL_REGISTRATION_IN_HKLM: |
| 941 // Software\Clients\StartMenuInternet\Google Chrome|suffix| | 802 // Software\Clients\StartMenuInternet\Google Chrome|suffix| |
| 942 reg_key = RegistryEntry::GetBrowserClientKey(dist, suffix); | 803 reg_key = GetBrowserClientKey(dist, suffix); |
| 943 break; | 804 break; |
| 944 default: | 805 default: |
| 945 NOTREACHED(); | 806 NOTREACHED(); |
| 946 break; | 807 break; |
| 947 } | 808 } |
| 948 reg_key.append(ShellUtil::kRegShellOpen); | 809 reg_key.append(ShellUtil::kRegShellOpen); |
| 949 | 810 |
| 950 // ProgId registrations are allowed to reside in HKCU for user-level installs | 811 // ProgId registrations are allowed to reside in HKCU for user-level installs |
| 951 // (and values there have priority over values in HKLM). The same is true for | 812 // (and values there have priority over values in HKLM). The same is true for |
| 952 // shell integration entries as of Windows 8. | 813 // shell integration entries as of Windows 8. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 } | 879 } |
| 1019 | 880 |
| 1020 // Associates Chrome with supported protocols and file associations. This should | 881 // Associates Chrome with supported protocols and file associations. This should |
| 1021 // not be required on Vista+ but since some applications still read | 882 // not be required on Vista+ but since some applications still read |
| 1022 // Software\Classes\http key directly, we have to do this on Vista+ as well. | 883 // Software\Classes\http key directly, we have to do this on Vista+ as well. |
| 1023 bool RegisterChromeAsDefaultXPStyle(BrowserDistribution* dist, | 884 bool RegisterChromeAsDefaultXPStyle(BrowserDistribution* dist, |
| 1024 int shell_change, | 885 int shell_change, |
| 1025 const base::string16& chrome_exe) { | 886 const base::string16& chrome_exe) { |
| 1026 bool ret = true; | 887 bool ret = true; |
| 1027 ScopedVector<RegistryEntry> entries; | 888 ScopedVector<RegistryEntry> entries; |
| 1028 RegistryEntry::GetXPStyleDefaultBrowserUserEntries( | 889 GetXPStyleDefaultBrowserUserEntries( |
| 1029 dist, chrome_exe, | 890 dist, |
| 1030 ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe), &entries); | 891 chrome_exe, |
| 892 ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe), |
| 893 &entries); |
| 1031 | 894 |
| 1032 // Change the default browser for current user. | 895 // Change the default browser for current user. |
| 1033 if ((shell_change & ShellUtil::CURRENT_USER) && | 896 if ((shell_change & ShellUtil::CURRENT_USER) && |
| 1034 !AddRegistryEntries(HKEY_CURRENT_USER, entries)) { | 897 !AddRegistryEntries(HKEY_CURRENT_USER, entries)) { |
| 1035 ret = false; | 898 ret = false; |
| 1036 LOG(ERROR) << "Could not make Chrome default browser (XP/current user)."; | 899 LOG(ERROR) << "Could not make Chrome default browser (XP/current user)."; |
| 1037 } | 900 } |
| 1038 | 901 |
| 1039 // Chrome as default browser at system level. | 902 // Chrome as default browser at system level. |
| 1040 if ((shell_change & ShellUtil::SYSTEM_LEVEL) && | 903 if ((shell_change & ShellUtil::SYSTEM_LEVEL) && |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1054 BrowserDistribution* dist, | 917 BrowserDistribution* dist, |
| 1055 const base::string16& chrome_exe, | 918 const base::string16& chrome_exe, |
| 1056 const base::string16& protocol) { | 919 const base::string16& protocol) { |
| 1057 ScopedVector<RegistryEntry> entries; | 920 ScopedVector<RegistryEntry> entries; |
| 1058 const base::string16 chrome_open( | 921 const base::string16 chrome_open( |
| 1059 ShellUtil::GetChromeShellOpenCmd(chrome_exe)); | 922 ShellUtil::GetChromeShellOpenCmd(chrome_exe)); |
| 1060 const base::string16 chrome_icon( | 923 const base::string16 chrome_icon( |
| 1061 ShellUtil::FormatIconLocation( | 924 ShellUtil::FormatIconLocation( |
| 1062 chrome_exe, | 925 chrome_exe, |
| 1063 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME))); | 926 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME))); |
| 1064 RegistryEntry::GetXPStyleUserProtocolEntries(protocol, chrome_icon, | 927 GetXPStyleUserProtocolEntries(protocol, chrome_icon, chrome_open, &entries); |
| 1065 chrome_open, &entries); | |
| 1066 // Change the default protocol handler for current user. | 928 // Change the default protocol handler for current user. |
| 1067 if (!AddRegistryEntries(HKEY_CURRENT_USER, entries)) { | 929 if (!AddRegistryEntries(HKEY_CURRENT_USER, entries)) { |
| 1068 LOG(ERROR) << "Could not make Chrome default protocol client (XP)."; | 930 LOG(ERROR) << "Could not make Chrome default protocol client (XP)."; |
| 1069 return false; | 931 return false; |
| 1070 } | 932 } |
| 1071 | 933 |
| 1072 return true; | 934 return true; |
| 1073 } | 935 } |
| 1074 | 936 |
| 1075 // Returns |properties.shortcut_name| if the property is set, otherwise it | 937 // Returns |properties.shortcut_name| if the property is set, otherwise it |
| (...skipping 1115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2191 // Check if chrome is already registered with this suffix. | 2053 // Check if chrome is already registered with this suffix. |
| 2192 if (IsChromeRegistered(dist, chrome_exe, suffix, look_for_in)) | 2054 if (IsChromeRegistered(dist, chrome_exe, suffix, look_for_in)) |
| 2193 return true; | 2055 return true; |
| 2194 | 2056 |
| 2195 bool result = true; | 2057 bool result = true; |
| 2196 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { | 2058 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { |
| 2197 // Do the full registration if we can do it at user-level or if the user is | 2059 // Do the full registration if we can do it at user-level or if the user is |
| 2198 // an admin. | 2060 // an admin. |
| 2199 ScopedVector<RegistryEntry> progid_and_appreg_entries; | 2061 ScopedVector<RegistryEntry> progid_and_appreg_entries; |
| 2200 ScopedVector<RegistryEntry> shell_entries; | 2062 ScopedVector<RegistryEntry> shell_entries; |
| 2201 RegistryEntry::GetChromeProgIdEntries( | 2063 GetChromeProgIdEntries( |
| 2202 dist, chrome_exe, suffix, &progid_and_appreg_entries); | 2064 dist, chrome_exe, suffix, &progid_and_appreg_entries); |
| 2203 RegistryEntry::GetChromeAppRegistrationEntries( | 2065 GetChromeAppRegistrationEntries( |
| 2204 chrome_exe, suffix, &progid_and_appreg_entries); | 2066 chrome_exe, suffix, &progid_and_appreg_entries); |
| 2205 RegistryEntry::GetShellIntegrationEntries( | 2067 GetShellIntegrationEntries(dist, chrome_exe, suffix, &shell_entries); |
| 2206 dist, chrome_exe, suffix, &shell_entries); | |
| 2207 result = (AddRegistryEntries(root, progid_and_appreg_entries) && | 2068 result = (AddRegistryEntries(root, progid_and_appreg_entries) && |
| 2208 AddRegistryEntries(root, shell_entries)); | 2069 AddRegistryEntries(root, shell_entries)); |
| 2209 } else if (elevate_if_not_admin && | 2070 } else if (elevate_if_not_admin && |
| 2210 base::win::GetVersion() >= base::win::VERSION_VISTA && | 2071 base::win::GetVersion() >= base::win::VERSION_VISTA && |
| 2211 ElevateAndRegisterChrome(dist, chrome_exe, suffix, base::string16())) { | 2072 ElevateAndRegisterChrome(dist, chrome_exe, suffix, base::string16())) { |
| 2212 // If the user is not an admin and OS is between Vista and Windows 7 | 2073 // If the user is not an admin and OS is between Vista and Windows 7 |
| 2213 // inclusively, try to elevate and register. This is only intended for | 2074 // inclusively, try to elevate and register. This is only intended for |
| 2214 // user-level installs as system-level installs should always be run with | 2075 // user-level installs as system-level installs should always be run with |
| 2215 // admin rights. | 2076 // admin rights. |
| 2216 result = true; | 2077 result = true; |
| 2217 } else { | 2078 } else { |
| 2218 // If we got to this point then all we can do is create ProgId and basic app | 2079 // If we got to this point then all we can do is create ProgId and basic app |
| 2219 // registrations under HKCU. | 2080 // registrations under HKCU. |
| 2220 ScopedVector<RegistryEntry> entries; | 2081 ScopedVector<RegistryEntry> entries; |
| 2221 RegistryEntry::GetChromeProgIdEntries( | 2082 GetChromeProgIdEntries(dist, chrome_exe, base::string16(), &entries); |
| 2222 dist, chrome_exe, base::string16(), &entries); | |
| 2223 // Prefer to use |suffix|; unless Chrome's ProgIds are already registered | 2083 // Prefer to use |suffix|; unless Chrome's ProgIds are already registered |
| 2224 // with no suffix (as per the old registration style): in which case some | 2084 // with no suffix (as per the old registration style): in which case some |
| 2225 // other registry entries could refer to them and since we were not able to | 2085 // other registry entries could refer to them and since we were not able to |
| 2226 // set our HKLM entries above, we are better off not altering these here. | 2086 // set our HKLM entries above, we are better off not altering these here. |
| 2227 if (!AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU)) { | 2087 if (!AreEntriesRegistered(entries, RegistryEntry::LOOK_IN_HKCU)) { |
| 2228 if (!suffix.empty()) { | 2088 if (!suffix.empty()) { |
| 2229 entries.clear(); | 2089 entries.clear(); |
| 2230 RegistryEntry::GetChromeProgIdEntries( | 2090 GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries); |
| 2231 dist, chrome_exe, suffix, &entries); | 2091 GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries); |
| 2232 RegistryEntry::GetChromeAppRegistrationEntries( | |
| 2233 chrome_exe, suffix, &entries); | |
| 2234 } | 2092 } |
| 2235 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); | 2093 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); |
| 2236 } else { | 2094 } else { |
| 2237 // The ProgId is registered unsuffixed in HKCU, also register the app with | 2095 // The ProgId is registered unsuffixed in HKCU, also register the app with |
| 2238 // Windows in HKCU (this was not done in the old registration style and | 2096 // Windows in HKCU (this was not done in the old registration style and |
| 2239 // thus needs to be done after the above check for the unsuffixed | 2097 // thus needs to be done after the above check for the unsuffixed |
| 2240 // registration). | 2098 // registration). |
| 2241 entries.clear(); | 2099 entries.clear(); |
| 2242 RegistryEntry::GetChromeAppRegistrationEntries( | 2100 GetChromeAppRegistrationEntries(chrome_exe, base::string16(), &entries); |
| 2243 chrome_exe, base::string16(), &entries); | |
| 2244 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); | 2101 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); |
| 2245 } | 2102 } |
| 2246 } | 2103 } |
| 2247 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); | 2104 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); |
| 2248 return result; | 2105 return result; |
| 2249 } | 2106 } |
| 2250 | 2107 |
| 2251 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, | 2108 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, |
| 2252 const base::string16& chrome_exe, | 2109 const base::string16& chrome_exe, |
| 2253 const base::string16& unique_suffix, | 2110 const base::string16& unique_suffix, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2280 return true; | 2137 return true; |
| 2281 | 2138 |
| 2282 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { | 2139 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { |
| 2283 // We can do this operation directly. | 2140 // We can do this operation directly. |
| 2284 // First, make sure Chrome is fully registered on this machine. | 2141 // First, make sure Chrome is fully registered on this machine. |
| 2285 if (!RegisterChromeBrowser(dist, chrome_exe, suffix, false)) | 2142 if (!RegisterChromeBrowser(dist, chrome_exe, suffix, false)) |
| 2286 return false; | 2143 return false; |
| 2287 | 2144 |
| 2288 // Write in the capabillity for the protocol. | 2145 // Write in the capabillity for the protocol. |
| 2289 ScopedVector<RegistryEntry> entries; | 2146 ScopedVector<RegistryEntry> entries; |
| 2290 RegistryEntry::GetProtocolCapabilityEntries(dist, suffix, protocol, | 2147 GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); |
| 2291 &entries); | |
| 2292 return AddRegistryEntries(root, entries); | 2148 return AddRegistryEntries(root, entries); |
| 2293 } else if (elevate_if_not_admin && | 2149 } else if (elevate_if_not_admin && |
| 2294 base::win::GetVersion() >= base::win::VERSION_VISTA) { | 2150 base::win::GetVersion() >= base::win::VERSION_VISTA) { |
| 2295 // Elevate to do the whole job | 2151 // Elevate to do the whole job |
| 2296 return ElevateAndRegisterChrome(dist, chrome_exe, suffix, protocol); | 2152 return ElevateAndRegisterChrome(dist, chrome_exe, suffix, protocol); |
| 2297 } else { | 2153 } else { |
| 2298 // Admin rights are required to register capabilities before Windows 8. | 2154 // Admin rights are required to register capabilities before Windows 8. |
| 2299 return false; | 2155 return false; |
| 2300 } | 2156 } |
| 2301 } | 2157 } |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2433 // static | 2289 // static |
| 2434 bool ShellUtil::AddFileAssociations( | 2290 bool ShellUtil::AddFileAssociations( |
| 2435 const base::string16& prog_id, | 2291 const base::string16& prog_id, |
| 2436 const base::CommandLine& command_line, | 2292 const base::CommandLine& command_line, |
| 2437 const base::string16& file_type_name, | 2293 const base::string16& file_type_name, |
| 2438 const base::FilePath& icon_path, | 2294 const base::FilePath& icon_path, |
| 2439 const std::set<base::string16>& file_extensions) { | 2295 const std::set<base::string16>& file_extensions) { |
| 2440 ScopedVector<RegistryEntry> entries; | 2296 ScopedVector<RegistryEntry> entries; |
| 2441 | 2297 |
| 2442 // Create a class for this app. | 2298 // Create a class for this app. |
| 2443 RegistryEntry::ApplicationInfo app_info; | 2299 ApplicationInfo app_info; |
| 2444 app_info.prog_id = prog_id; | 2300 app_info.prog_id = prog_id; |
| 2445 app_info.file_type_name = file_type_name; | 2301 app_info.file_type_name = file_type_name; |
| 2446 app_info.file_type_icon_path = icon_path.value(); | 2302 app_info.file_type_icon_path = icon_path.value(); |
| 2447 app_info.file_type_icon_index = 0; | 2303 app_info.file_type_icon_index = 0; |
| 2448 app_info.command_line = command_line.GetCommandLineString(); | 2304 app_info.command_line = command_line.GetCommandLineString(); |
| 2449 RegistryEntry::GetProgIdEntries(app_info, &entries); | 2305 GetProgIdEntries(app_info, &entries); |
| 2450 | 2306 |
| 2451 // Associate each extension that the app can handle with the class. Set this | 2307 // Associate each extension that the app can handle with the class. Set this |
| 2452 // app as the default handler if and only if there is no existing default. | 2308 // app as the default handler if and only if there is no existing default. |
| 2453 for (std::set<base::string16>::const_iterator it = file_extensions.begin(); | 2309 for (std::set<base::string16>::const_iterator it = file_extensions.begin(); |
| 2454 it != file_extensions.end(); | 2310 it != file_extensions.end(); |
| 2455 ++it) { | 2311 ++it) { |
| 2456 // Do not allow empty file extensions, or extensions beginning with a '.'. | 2312 // Do not allow empty file extensions, or extensions beginning with a '.'. |
| 2457 DCHECK(!it->empty()); | 2313 DCHECK(!it->empty()); |
| 2458 DCHECK_NE(L'.', (*it)[0]); | 2314 DCHECK_NE(L'.', (*it)[0]); |
| 2459 base::string16 ext(1, L'.'); | 2315 base::string16 ext(1, L'.'); |
| 2460 ext.append(*it); | 2316 ext.append(*it); |
| 2461 RegistryEntry::GetAppExtRegistrationEntries(prog_id, ext, &entries); | 2317 GetAppExtRegistrationEntries(prog_id, ext, &entries); |
| 2462 | 2318 |
| 2463 // Regstering as the default will have no effect on Windows 8 (see | 2319 // Regstering as the default will have no effect on Windows 8 (see |
| 2464 // documentation for GetAppDefaultRegistrationEntries). However, if our app | 2320 // documentation for GetAppDefaultRegistrationEntries). However, if our app |
| 2465 // is the only handler, it will automatically become the default, so the | 2321 // is the only handler, it will automatically become the default, so the |
| 2466 // same effect is achieved. | 2322 // same effect is achieved. |
| 2467 RegistryEntry::GetAppDefaultRegistrationEntries( | 2323 GetAppDefaultRegistrationEntries(prog_id, ext, false, &entries); |
| 2468 prog_id, ext, false, &entries); | |
| 2469 } | 2324 } |
| 2470 | 2325 |
| 2471 return AddRegistryEntries(HKEY_CURRENT_USER, entries); | 2326 return AddRegistryEntries(HKEY_CURRENT_USER, entries); |
| 2472 } | 2327 } |
| 2473 | 2328 |
| 2474 // static | 2329 // static |
| 2475 bool ShellUtil::DeleteFileAssociations(const base::string16& prog_id) { | 2330 bool ShellUtil::DeleteFileAssociations(const base::string16& prog_id) { |
| 2476 // Delete the key HKEY_CURRENT_USER\Software\Classes\PROGID. | 2331 // Delete the key HKEY_CURRENT_USER\Software\Classes\PROGID. |
| 2477 base::string16 key_path(ShellUtil::kRegClasses); | 2332 base::string16 key_path(ShellUtil::kRegClasses); |
| 2478 key_path.push_back(base::FilePath::kSeparators[0]); | 2333 key_path.push_back(base::FilePath::kSeparators[0]); |
| 2479 key_path.append(prog_id); | 2334 key_path.append(prog_id); |
| 2480 return InstallUtil::DeleteRegistryKey( | 2335 return InstallUtil::DeleteRegistryKey( |
| 2481 HKEY_CURRENT_USER, key_path, WorkItem::kWow64Default); | 2336 HKEY_CURRENT_USER, key_path, WorkItem::kWow64Default); |
| 2482 | 2337 |
| 2483 // TODO(mgiuca): Remove the extension association entries. This requires that | 2338 // TODO(mgiuca): Remove the extension association entries. This requires that |
| 2484 // the extensions associated with a particular prog_id are stored in that | 2339 // the extensions associated with a particular prog_id are stored in that |
| 2485 // prog_id's key. | 2340 // prog_id's key. |
| 2486 } | 2341 } |
| OLD | NEW |