| 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 #include "chrome/common/chrome_switches.h" | 46 #include "chrome/common/chrome_switches.h" |
| 47 #include "chrome/installer/util/beacons.h" | 47 #include "chrome/installer/util/beacons.h" |
| 48 #include "chrome/installer/util/browser_distribution.h" | 48 #include "chrome/installer/util/browser_distribution.h" |
| 49 #include "chrome/installer/util/install_util.h" | 49 #include "chrome/installer/util/install_util.h" |
| 50 #include "chrome/installer/util/installer_util_strings.h" | 50 #include "chrome/installer/util/installer_util_strings.h" |
| 51 #include "chrome/installer/util/l10n_string_util.h" | 51 #include "chrome/installer/util/l10n_string_util.h" |
| 52 #include "chrome/installer/util/master_preferences.h" | 52 #include "chrome/installer/util/master_preferences.h" |
| 53 #include "chrome/installer/util/master_preferences_constants.h" | 53 #include "chrome/installer/util/master_preferences_constants.h" |
| 54 #include "chrome/installer/util/registry_entry.h" | 54 #include "chrome/installer/util/registry_entry.h" |
| 55 #include "chrome/installer/util/scoped_user_protocol_entry.h" | 55 #include "chrome/installer/util/scoped_user_protocol_entry.h" |
| 56 #include "chrome/installer/util/shell_registry_util.h" |
| 56 #include "chrome/installer/util/util_constants.h" | 57 #include "chrome/installer/util/util_constants.h" |
| 57 #include "chrome/installer/util/work_item.h" | 58 #include "chrome/installer/util/work_item.h" |
| 58 | 59 |
| 59 using base::win::RegKey; | 60 using base::win::RegKey; |
| 60 | 61 |
| 61 namespace { | 62 namespace { |
| 62 | 63 |
| 63 // An enum used to tell QuickIsChromeRegistered() which level of registration | 64 // An enum used to tell QuickIsChromeRegistered() which level of registration |
| 64 // the caller wants to confirm. | 65 // the caller wants to confirm. |
| 65 enum RegistrationConfirmationLevel { | 66 enum RegistrationConfirmationLevel { |
| 66 // Only look for Chrome's ProgIds. | 67 // Only look for Chrome's ProgIds. |
| 67 // This is sufficient when we are trying to determine the suffix of the | 68 // This is sufficient when we are trying to determine the suffix of the |
| 68 // currently running Chrome as shell integration registrations might not be | 69 // currently running Chrome as shell integration registrations might not be |
| 69 // present. | 70 // present. |
| 70 CONFIRM_PROGID_REGISTRATION = 0, | 71 CONFIRM_PROGID_REGISTRATION = 0, |
| 71 // Confirm that Chrome is fully integrated with Windows (i.e. registered with | 72 // Confirm that Chrome is fully integrated with Windows (i.e. registered with |
| 72 // Defaut Programs). These registrations can be in HKCU as of Windows 8. | 73 // Defaut Programs). These registrations can be in HKCU as of Windows 8. |
| 73 // Note: Shell registration implies ProgId registration. | 74 // Note: Shell registration implies ProgId registration. |
| 74 CONFIRM_SHELL_REGISTRATION, | 75 CONFIRM_SHELL_REGISTRATION, |
| 75 // Same as CONFIRM_SHELL_REGISTRATION, but only look in HKLM (used when | 76 // Same as CONFIRM_SHELL_REGISTRATION, but only look in HKLM (used when |
| 76 // uninstalling to know whether elevation is required to clean up the | 77 // uninstalling to know whether elevation is required to clean up the |
| 77 // registry). | 78 // registry). |
| 78 CONFIRM_SHELL_REGISTRATION_IN_HKLM, | 79 CONFIRM_SHELL_REGISTRATION_IN_HKLM, |
| 79 }; | 80 }; |
| 80 | 81 |
| 81 const wchar_t kReinstallCommand[] = L"ReinstallCommand"; | |
| 82 | |
| 83 // Returns the current (or installed) browser's ProgId (e.g. | |
| 84 // "ChromeHTML|suffix|"). | |
| 85 // |suffix| can be the empty string. | |
| 86 base::string16 GetBrowserProgId(const base::string16& suffix) { | |
| 87 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | |
| 88 base::string16 chrome_html(dist->GetBrowserProgIdPrefix()); | |
| 89 chrome_html.append(suffix); | |
| 90 | |
| 91 // ProgIds cannot be longer than 39 characters. | |
| 92 // Ref: http://msdn.microsoft.com/en-us/library/aa911706.aspx. | |
| 93 // Make all new registrations comply with this requirement (existing | |
| 94 // registrations must be preserved). | |
| 95 base::string16 new_style_suffix; | |
| 96 if (ShellUtil::GetUserSpecificRegistrySuffix(&new_style_suffix) && | |
| 97 suffix == new_style_suffix && chrome_html.length() > 39) { | |
| 98 NOTREACHED(); | |
| 99 chrome_html.erase(39); | |
| 100 } | |
| 101 return chrome_html; | |
| 102 } | |
| 103 | |
| 104 // This class is used to initialize and cache a base 32 encoding of the md5 hash | 82 // This class is used to initialize and cache a base 32 encoding of the md5 hash |
| 105 // of this user's sid preceded by a dot. | 83 // of this user's sid preceded by a dot. |
| 106 // This is guaranteed to be unique on the machine and 27 characters long | 84 // This is guaranteed to be unique on the machine and 27 characters long |
| 107 // (including the '.'). | 85 // (including the '.'). |
| 108 // This is then meant to be used as a suffix on all registrations that may | 86 // This is then meant to be used as a suffix on all registrations that may |
| 109 // conflict with another user-level Chrome install. | 87 // conflict with another user-level Chrome install. |
| 110 class UserSpecificRegistrySuffix { | 88 class UserSpecificRegistrySuffix { |
| 111 public: | 89 public: |
| 112 // All the initialization is done in the constructor to be able to build the | 90 // All the initialization is done in the constructor to be able to build the |
| 113 // suffix in a thread-safe manner when used in conjunction with a | 91 // suffix in a thread-safe manner when used in conjunction with a |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 | 127 |
| 150 bool UserSpecificRegistrySuffix::GetSuffix(base::string16* suffix) { | 128 bool UserSpecificRegistrySuffix::GetSuffix(base::string16* suffix) { |
| 151 if (suffix_.empty()) { | 129 if (suffix_.empty()) { |
| 152 NOTREACHED(); | 130 NOTREACHED(); |
| 153 return false; | 131 return false; |
| 154 } | 132 } |
| 155 suffix->assign(suffix_); | 133 suffix->assign(suffix_); |
| 156 return true; | 134 return true; |
| 157 } | 135 } |
| 158 | 136 |
| 159 // Details about a Windows application, to be entered into the registry for the | |
| 160 // purpose of file associations. | |
| 161 struct ApplicationInfo { | |
| 162 ApplicationInfo() : file_type_icon_index(0), application_icon_index(0) {} | |
| 163 | |
| 164 // The ProgId used by Windows for file associations with this application. | |
| 165 // Must not be empty or start with a '.'. | |
| 166 base::string16 prog_id; | |
| 167 // The friendly name, and the path of the icon that will be used for files of | |
| 168 // these types when associated with this application by default. (They are NOT | |
| 169 // the name/icon that will represent the application under the Open With | |
| 170 // menu.) | |
| 171 base::string16 file_type_name; | |
| 172 base::FilePath file_type_icon_path; | |
| 173 int file_type_icon_index; | |
| 174 // The command to execute when opening a file via this association. It should | |
| 175 // contain "%1" (to tell Windows to pass the filename as an argument). | |
| 176 // TODO(mgiuca): |command_line| should be a base::CommandLine. | |
| 177 base::string16 command_line; | |
| 178 // The AppUserModelId used by Windows 8 for this application. Distinct from | |
| 179 // |prog_id|. | |
| 180 base::string16 app_id; | |
| 181 | |
| 182 // User-visible details about this application. Any of these may be empty. | |
| 183 base::string16 application_name; | |
| 184 base::FilePath application_icon_path; | |
| 185 int application_icon_index; | |
| 186 base::string16 application_description; | |
| 187 base::string16 publisher_name; | |
| 188 | |
| 189 // The CLSID for the application's DelegateExecute handler. May be empty. | |
| 190 base::string16 delegate_clsid; | |
| 191 }; | |
| 192 | |
| 193 // Returns the Windows browser client registration key for Chrome. For example: | |
| 194 // "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly speaking, we | |
| 195 // should use the name of the executable (e.g., "chrome.exe"), but that ship has | |
| 196 // sailed. The cost of switching now is re-prompting users to make Chrome their | |
| 197 // default browser, which isn't polite. |suffix| is the user-specific | |
| 198 // registration suffix; see GetUserSpecificDefaultBrowserSuffix in shell_util.h | |
| 199 // for details. | |
| 200 base::string16 GetBrowserClientKey(BrowserDistribution* dist, | |
| 201 const base::string16& suffix) { | |
| 202 DCHECK(suffix.empty() || suffix[0] == L'.'); | |
| 203 return base::string16(ShellUtil::kRegStartMenuInternet) | |
| 204 .append(1, L'\\') | |
| 205 .append(dist->GetBaseAppName()) | |
| 206 .append(suffix); | |
| 207 } | |
| 208 | |
| 209 // Returns the Windows Default Programs capabilities key for Chrome. For | |
| 210 // example: | |
| 211 // "Software\Clients\StartMenuInternet\Chromium[.user]\Capabilities". | |
| 212 base::string16 GetCapabilitiesKey(BrowserDistribution* dist, | |
| 213 const base::string16& suffix) { | |
| 214 return GetBrowserClientKey(dist, suffix).append(L"\\Capabilities"); | |
| 215 } | |
| 216 | |
| 217 // DelegateExecute ProgId. Needed for Chrome Metro in Windows 8. This is only | |
| 218 // needed for registring a web browser, not for general associations. | |
| 219 ScopedVector<RegistryEntry> GetChromeDelegateExecuteEntries( | |
| 220 const base::FilePath& chrome_exe, | |
| 221 const ApplicationInfo& app_info) { | |
| 222 ScopedVector<RegistryEntry> entries; | |
| 223 | |
| 224 base::string16 app_id_shell_key(ShellUtil::kRegClasses); | |
| 225 app_id_shell_key.push_back(base::FilePath::kSeparators[0]); | |
| 226 app_id_shell_key.append(app_info.app_id); | |
| 227 app_id_shell_key.append(ShellUtil::kRegExePath); | |
| 228 app_id_shell_key.append(ShellUtil::kRegShellPath); | |
| 229 | |
| 230 // <root hkey>\Software\Classes\<app_id>\.exe\shell @=open | |
| 231 entries.push_back( | |
| 232 new RegistryEntry(app_id_shell_key, ShellUtil::kRegVerbOpen)); | |
| 233 | |
| 234 // The command to execute when opening this application via the Metro UI. | |
| 235 const base::string16 delegate_command( | |
| 236 ShellUtil::GetChromeDelegateCommand(chrome_exe)); | |
| 237 | |
| 238 // Each of Chrome's shortcuts has an appid; which, as of Windows 8, is | |
| 239 // registered to handle some verbs. This registration has the side-effect | |
| 240 // that these verbs now show up in the shortcut's context menu. We | |
| 241 // mitigate this side-effect by making the context menu entries | |
| 242 // user readable/localized strings. See relevant MSDN article: | |
| 243 // http://msdn.microsoft.com/en-US/library/windows/desktop/cc144171.aspx | |
| 244 static const struct { | |
| 245 const wchar_t* verb; | |
| 246 int name_id; | |
| 247 } verbs[] = { | |
| 248 {ShellUtil::kRegVerbOpen, -1}, | |
| 249 {ShellUtil::kRegVerbOpenNewWindow, IDS_SHORTCUT_NEW_WINDOW_BASE}, | |
| 250 }; | |
| 251 for (const auto& verb_and_id : verbs) { | |
| 252 base::string16 sub_path(app_id_shell_key); | |
| 253 sub_path.push_back(base::FilePath::kSeparators[0]); | |
| 254 sub_path.append(verb_and_id.verb); | |
| 255 | |
| 256 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb> | |
| 257 if (verb_and_id.name_id != -1) { | |
| 258 // TODO(grt): http://crbug.com/75152 Write a reference to a localized | |
| 259 // resource. | |
| 260 const base::string16 verb_name( | |
| 261 installer::GetLocalizedString(verb_and_id.name_id)); | |
| 262 entries.push_back(new RegistryEntry(sub_path, verb_name.c_str())); | |
| 263 } | |
| 264 entries.push_back( | |
| 265 new RegistryEntry(sub_path, L"CommandId", L"Browser.Launch")); | |
| 266 | |
| 267 sub_path.push_back(base::FilePath::kSeparators[0]); | |
| 268 sub_path.append(ShellUtil::kRegCommand); | |
| 269 | |
| 270 // <root hkey>\Software\Classes\<app_id>\.exe\shell\<verb>\command | |
| 271 entries.push_back(new RegistryEntry(sub_path, delegate_command)); | |
| 272 entries.push_back(new RegistryEntry( | |
| 273 sub_path, ShellUtil::kRegDelegateExecute, app_info.delegate_clsid)); | |
| 274 } | |
| 275 | |
| 276 return entries; | |
| 277 } | |
| 278 | |
| 279 // Gets the registry entries to register an application in the Windows registry. | |
| 280 // |app_info| provides all of the information needed. | |
| 281 void GetProgIdEntries(const ApplicationInfo& app_info, | |
| 282 ScopedVector<RegistryEntry>* entries) { | |
| 283 // Basic sanity checks. | |
| 284 DCHECK(!app_info.prog_id.empty()); | |
| 285 DCHECK_NE(L'.', app_info.prog_id[0]); | |
| 286 | |
| 287 // File association ProgId | |
| 288 base::string16 prog_id_path(ShellUtil::kRegClasses); | |
| 289 prog_id_path.push_back(base::FilePath::kSeparators[0]); | |
| 290 prog_id_path.append(app_info.prog_id); | |
| 291 entries->push_back(new RegistryEntry(prog_id_path, app_info.file_type_name)); | |
| 292 entries->push_back(new RegistryEntry( | |
| 293 prog_id_path + ShellUtil::kRegDefaultIcon, | |
| 294 ShellUtil::FormatIconLocation(app_info.file_type_icon_path, | |
| 295 app_info.file_type_icon_index))); | |
| 296 entries->push_back(new RegistryEntry(prog_id_path + ShellUtil::kRegShellOpen, | |
| 297 app_info.command_line)); | |
| 298 if (!app_info.delegate_clsid.empty()) { | |
| 299 entries->push_back(new RegistryEntry( | |
| 300 prog_id_path + ShellUtil::kRegShellOpen, ShellUtil::kRegDelegateExecute, | |
| 301 app_info.delegate_clsid)); | |
| 302 // TODO(scottmg): Simplify after Metro removal. https://crbug.com/558054. | |
| 303 entries->back()->set_removal_flag(RegistryEntry::RemovalFlag::VALUE); | |
| 304 } | |
| 305 | |
| 306 // The following entries are required as of Windows 8, but do not | |
| 307 // depend on the DelegateExecute verb handler being set. | |
| 308 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { | |
| 309 if (!app_info.app_id.empty()) { | |
| 310 entries->push_back(new RegistryEntry( | |
| 311 prog_id_path, ShellUtil::kRegAppUserModelId, app_info.app_id)); | |
| 312 } | |
| 313 | |
| 314 // Add \Software\Classes\<prog_id>\Application entries | |
| 315 base::string16 application_path(prog_id_path + ShellUtil::kRegApplication); | |
| 316 if (!app_info.app_id.empty()) { | |
| 317 entries->push_back(new RegistryEntry( | |
| 318 application_path, ShellUtil::kRegAppUserModelId, app_info.app_id)); | |
| 319 } | |
| 320 if (!app_info.application_icon_path.empty()) { | |
| 321 entries->push_back(new RegistryEntry( | |
| 322 application_path, ShellUtil::kRegApplicationIcon, | |
| 323 ShellUtil::FormatIconLocation(app_info.application_icon_path, | |
| 324 app_info.application_icon_index))); | |
| 325 } | |
| 326 if (!app_info.application_name.empty()) { | |
| 327 entries->push_back(new RegistryEntry(application_path, | |
| 328 ShellUtil::kRegApplicationName, | |
| 329 app_info.application_name)); | |
| 330 } | |
| 331 if (!app_info.application_description.empty()) { | |
| 332 entries->push_back(new RegistryEntry( | |
| 333 application_path, ShellUtil::kRegApplicationDescription, | |
| 334 app_info.application_description)); | |
| 335 } | |
| 336 if (!app_info.publisher_name.empty()) { | |
| 337 entries->push_back(new RegistryEntry(application_path, | |
| 338 ShellUtil::kRegApplicationCompany, | |
| 339 app_info.publisher_name)); | |
| 340 } | |
| 341 } | |
| 342 } | |
| 343 | |
| 344 // This method returns a list of all the registry entries that are needed to | |
| 345 // register this installation's ProgId and AppId. These entries need to be | |
| 346 // registered in HKLM prior to Win8. | |
| 347 void GetChromeProgIdEntries(BrowserDistribution* dist, | |
| 348 const base::FilePath& chrome_exe, | |
| 349 const base::string16& suffix, | |
| 350 ScopedVector<RegistryEntry>* entries) { | |
| 351 int chrome_icon_index = | |
| 352 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME); | |
| 353 | |
| 354 ApplicationInfo app_info; | |
| 355 app_info.prog_id = GetBrowserProgId(suffix); | |
| 356 app_info.file_type_name = dist->GetBrowserProgIdDesc(); | |
| 357 // File types associated with Chrome are just given the Chrome icon. | |
| 358 app_info.file_type_icon_path = chrome_exe; | |
| 359 app_info.file_type_icon_index = chrome_icon_index; | |
| 360 app_info.command_line = ShellUtil::GetChromeShellOpenCmd(chrome_exe); | |
| 361 // For user-level installs: entries for the app id will be in HKCU; thus we | |
| 362 // do not need a suffix on those entries. | |
| 363 app_info.app_id = ShellUtil::GetBrowserModelId( | |
| 364 dist, InstallUtil::IsPerUserInstall(chrome_exe)); | |
| 365 | |
| 366 // TODO(grt): http://crbug.com/75152 Write a reference to a localized | |
| 367 // resource for name, description, and company. | |
| 368 app_info.application_name = dist->GetDisplayName(); | |
| 369 app_info.application_icon_path = chrome_exe; | |
| 370 app_info.application_icon_index = chrome_icon_index; | |
| 371 app_info.application_description = dist->GetAppDescription(); | |
| 372 app_info.publisher_name = dist->GetPublisherName(); | |
| 373 | |
| 374 app_info.delegate_clsid = dist->GetCommandExecuteImplClsid(); | |
| 375 | |
| 376 GetProgIdEntries(app_info, entries); | |
| 377 | |
| 378 if (!app_info.delegate_clsid.empty()) { | |
| 379 ScopedVector<RegistryEntry> delegate_execute_entries = | |
| 380 GetChromeDelegateExecuteEntries(chrome_exe, app_info); | |
| 381 // Remove the keys (not only their values) so that Windows will continue | |
| 382 // to launch Chrome without a pesky association error. | |
| 383 // TODO(scottmg): Simplify after Metro removal. https://crbug.com/558054. | |
| 384 for (RegistryEntry* entry : delegate_execute_entries) | |
| 385 entry->set_removal_flag(RegistryEntry::RemovalFlag::KEY); | |
| 386 // Move |delegate_execute_entries| to |entries|. | |
| 387 entries->insert(entries->end(), delegate_execute_entries.begin(), | |
| 388 delegate_execute_entries.end()); | |
| 389 delegate_execute_entries.weak_clear(); | |
| 390 } | |
| 391 } | |
| 392 | |
| 393 // This method returns a list of the registry entries needed to declare a | |
| 394 // capability of handling a protocol on Windows. | |
| 395 void GetProtocolCapabilityEntries(BrowserDistribution* dist, | |
| 396 const base::string16& suffix, | |
| 397 const base::string16& protocol, | |
| 398 ScopedVector<RegistryEntry>* entries) { | |
| 399 entries->push_back(new RegistryEntry( | |
| 400 GetCapabilitiesKey(dist, suffix).append(L"\\URLAssociations"), protocol, | |
| 401 GetBrowserProgId(suffix))); | |
| 402 } | |
| 403 | |
| 404 // This method returns a list of the registry entries required to register this | |
| 405 // installation in "RegisteredApplications" on Windows (to appear in Default | |
| 406 // Programs, StartMenuInternet, etc.). These entries need to be registered in | |
| 407 // HKLM prior to Win8. If |suffix| is not empty, these entries are guaranteed to | |
| 408 // be unique on this machine. | |
| 409 void GetShellIntegrationEntries(BrowserDistribution* dist, | |
| 410 const base::FilePath& chrome_exe, | |
| 411 const base::string16& suffix, | |
| 412 ScopedVector<RegistryEntry>* entries) { | |
| 413 const base::string16 icon_path(ShellUtil::FormatIconLocation( | |
| 414 chrome_exe, dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME))); | |
| 415 const base::string16 quoted_exe_path(L"\"" + chrome_exe.value() + L"\""); | |
| 416 | |
| 417 // Register for the Start Menu "Internet" link (pre-Win7). | |
| 418 const base::string16 start_menu_entry(GetBrowserClientKey(dist, suffix)); | |
| 419 // Register Chrome's display name. | |
| 420 // TODO(grt): http://crbug.com/75152 Also set LocalizedString; see | |
| 421 // http://msdn.microsoft.com/en-us/library/windows/desktop/cc144109(v=VS.85).a
spx#registering_the_display_name | |
| 422 entries->push_back( | |
| 423 new RegistryEntry(start_menu_entry, dist->GetDisplayName())); | |
| 424 // Register the "open" verb for launching Chrome via the "Internet" link. | |
| 425 entries->push_back(new RegistryEntry( | |
| 426 start_menu_entry + ShellUtil::kRegShellOpen, quoted_exe_path)); | |
| 427 // Register Chrome's icon for the Start Menu "Internet" link. | |
| 428 entries->push_back(new RegistryEntry( | |
| 429 start_menu_entry + ShellUtil::kRegDefaultIcon, icon_path)); | |
| 430 | |
| 431 // Register installation information. | |
| 432 base::string16 install_info(start_menu_entry + L"\\InstallInfo"); | |
| 433 // Note: not using CommandLine since it has ambiguous rules for quoting | |
| 434 // strings. | |
| 435 entries->push_back( | |
| 436 new RegistryEntry(install_info, kReinstallCommand, | |
| 437 quoted_exe_path + L" --" + | |
| 438 base::ASCIIToUTF16(switches::kMakeDefaultBrowser))); | |
| 439 entries->push_back(new RegistryEntry( | |
| 440 install_info, L"HideIconsCommand", | |
| 441 quoted_exe_path + L" --" + base::ASCIIToUTF16(switches::kHideIcons))); | |
| 442 entries->push_back(new RegistryEntry( | |
| 443 install_info, L"ShowIconsCommand", | |
| 444 quoted_exe_path + L" --" + base::ASCIIToUTF16(switches::kShowIcons))); | |
| 445 entries->push_back(new RegistryEntry(install_info, L"IconsVisible", 1)); | |
| 446 | |
| 447 // Register with Default Programs. | |
| 448 const base::string16 reg_app_name(dist->GetBaseAppName().append(suffix)); | |
| 449 // Tell Windows where to find Chrome's Default Programs info. | |
| 450 const base::string16 capabilities(GetCapabilitiesKey(dist, suffix)); | |
| 451 entries->push_back(new RegistryEntry(ShellUtil::kRegRegisteredApplications, | |
| 452 reg_app_name, capabilities)); | |
| 453 // Write out Chrome's Default Programs info. | |
| 454 // TODO(grt): http://crbug.com/75152 Write a reference to a localized | |
| 455 // resource rather than this. | |
| 456 entries->push_back(new RegistryEntry(capabilities, | |
| 457 ShellUtil::kRegApplicationDescription, | |
| 458 dist->GetLongAppDescription())); | |
| 459 entries->push_back(new RegistryEntry( | |
| 460 capabilities, ShellUtil::kRegApplicationIcon, icon_path)); | |
| 461 entries->push_back(new RegistryEntry( | |
| 462 capabilities, ShellUtil::kRegApplicationName, dist->GetDisplayName())); | |
| 463 | |
| 464 entries->push_back(new RegistryEntry(capabilities + L"\\Startmenu", | |
| 465 L"StartMenuInternet", reg_app_name)); | |
| 466 | |
| 467 const base::string16 html_prog_id(GetBrowserProgId(suffix)); | |
| 468 for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) { | |
| 469 entries->push_back(new RegistryEntry( | |
| 470 capabilities + L"\\FileAssociations", | |
| 471 ShellUtil::kPotentialFileAssociations[i], html_prog_id)); | |
| 472 } | |
| 473 for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL; i++) { | |
| 474 entries->push_back(new RegistryEntry( | |
| 475 capabilities + L"\\URLAssociations", | |
| 476 ShellUtil::kPotentialProtocolAssociations[i], html_prog_id)); | |
| 477 } | |
| 478 } | |
| 479 | |
| 480 // Gets the registry entries to register an application as a handler for a | |
| 481 // particular file extension. |prog_id| is the ProgId used by Windows for the | |
| 482 // application. |ext| is the file extension, which must begin with a '.'. | |
| 483 void GetAppExtRegistrationEntries(const base::string16& prog_id, | |
| 484 const base::string16& ext, | |
| 485 ScopedVector<RegistryEntry>* entries) { | |
| 486 // In HKEY_CURRENT_USER\Software\Classes\EXT\OpenWithProgids, create an | |
| 487 // empty value with this class's ProgId. | |
| 488 base::string16 key_name(ShellUtil::kRegClasses); | |
| 489 key_name.push_back(base::FilePath::kSeparators[0]); | |
| 490 key_name.append(ext); | |
| 491 key_name.push_back(base::FilePath::kSeparators[0]); | |
| 492 key_name.append(ShellUtil::kRegOpenWithProgids); | |
| 493 entries->push_back(new RegistryEntry(key_name, prog_id, base::string16())); | |
| 494 } | |
| 495 | |
| 496 // This method returns a list of the registry entries required for this | |
| 497 // installation to be registered in the Windows shell. | |
| 498 // In particular: | |
| 499 // - App Paths | |
| 500 // http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121 | |
| 501 // - File Associations | |
| 502 // http://msdn.microsoft.com/en-us/library/bb166549 | |
| 503 // These entries need to be registered in HKLM prior to Win8. | |
| 504 void GetChromeAppRegistrationEntries(const base::FilePath& chrome_exe, | |
| 505 const base::string16& suffix, | |
| 506 ScopedVector<RegistryEntry>* entries) { | |
| 507 base::string16 app_path_key(ShellUtil::kAppPathsRegistryKey); | |
| 508 app_path_key.push_back(base::FilePath::kSeparators[0]); | |
| 509 app_path_key.append(chrome_exe.BaseName().value()); | |
| 510 entries->push_back(new RegistryEntry(app_path_key, chrome_exe.value())); | |
| 511 entries->push_back(new RegistryEntry(app_path_key, | |
| 512 ShellUtil::kAppPathsRegistryPathName, | |
| 513 chrome_exe.DirName().value())); | |
| 514 | |
| 515 const base::string16 html_prog_id(GetBrowserProgId(suffix)); | |
| 516 for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; i++) { | |
| 517 GetAppExtRegistrationEntries( | |
| 518 html_prog_id, ShellUtil::kPotentialFileAssociations[i], entries); | |
| 519 } | |
| 520 } | |
| 521 | |
| 522 // Gets the registry entries to register an application as the default handler | |
| 523 // for a particular file extension. |prog_id| is the ProgId used by Windows for | |
| 524 // the application. |ext| is the file extension, which must begin with a '.'. If | |
| 525 // |overwrite_existing|, always sets the default handler; otherwise only sets if | |
| 526 // there is no existing default. | |
| 527 // | |
| 528 // This has no effect on Windows 8. Windows 8 ignores the default and lets the | |
| 529 // user choose. If there is only one handler for a file, it will automatically | |
| 530 // become the default. Otherwise, the first time the user opens a file, they are | |
| 531 // presented with the dialog to set the default handler. (This is roughly | |
| 532 // equivalent to being called with |overwrite_existing| false.) | |
| 533 void GetAppDefaultRegistrationEntries(const base::string16& prog_id, | |
| 534 const base::string16& ext, | |
| 535 bool overwrite_existing, | |
| 536 ScopedVector<RegistryEntry>* entries) { | |
| 537 // Set the default value of HKEY_CURRENT_USER\Software\Classes\EXT to this | |
| 538 // class's name. | |
| 539 base::string16 key_name(ShellUtil::kRegClasses); | |
| 540 key_name.push_back(base::FilePath::kSeparators[0]); | |
| 541 key_name.append(ext); | |
| 542 scoped_ptr<RegistryEntry> default_association( | |
| 543 new RegistryEntry(key_name, prog_id)); | |
| 544 if (overwrite_existing || | |
| 545 !default_association->KeyExistsInRegistry(RegistryEntry::LOOK_IN_HKCU)) { | |
| 546 entries->push_back(default_association.release()); | |
| 547 } | |
| 548 } | |
| 549 | |
| 550 // This method returns a list of all the user level registry entries that are | |
| 551 // needed to make Chromium the default handler for a protocol on XP. | |
| 552 void GetXPStyleUserProtocolEntries(const base::string16& protocol, | |
| 553 const base::string16& chrome_icon, | |
| 554 const base::string16& chrome_open, | |
| 555 ScopedVector<RegistryEntry>* entries) { | |
| 556 // Protocols associations. | |
| 557 base::string16 url_key(ShellUtil::kRegClasses); | |
| 558 url_key.push_back(base::FilePath::kSeparators[0]); | |
| 559 url_key.append(protocol); | |
| 560 | |
| 561 // This registry value tells Windows that this 'class' is a URL scheme | |
| 562 // so IE, explorer and other apps will route it to our handler. | |
| 563 // <root hkey>\Software\Classes\<protocol>\URL Protocol | |
| 564 entries->push_back( | |
| 565 new RegistryEntry(url_key, ShellUtil::kRegUrlProtocol, base::string16())); | |
| 566 | |
| 567 // <root hkey>\Software\Classes\<protocol>\DefaultIcon | |
| 568 base::string16 icon_key = url_key + ShellUtil::kRegDefaultIcon; | |
| 569 entries->push_back(new RegistryEntry(icon_key, chrome_icon)); | |
| 570 | |
| 571 // <root hkey>\Software\Classes\<protocol>\shell\open\command | |
| 572 base::string16 shell_key = url_key + ShellUtil::kRegShellOpen; | |
| 573 entries->push_back(new RegistryEntry(shell_key, chrome_open)); | |
| 574 | |
| 575 // <root hkey>\Software\Classes\<protocol>\shell\open\ddeexec | |
| 576 base::string16 dde_key = url_key + L"\\shell\\open\\ddeexec"; | |
| 577 entries->push_back(new RegistryEntry(dde_key, base::string16())); | |
| 578 | |
| 579 // <root hkey>\Software\Classes\<protocol>\shell\@ | |
| 580 base::string16 protocol_shell_key = url_key + ShellUtil::kRegShellPath; | |
| 581 entries->push_back(new RegistryEntry(protocol_shell_key, L"open")); | |
| 582 } | |
| 583 | |
| 584 // This method returns a list of all the user level registry entries that are | |
| 585 // needed to make Chromium default browser on XP. Some of these entries are | |
| 586 // irrelevant in recent versions of Windows, but we register them anyways as | |
| 587 // some legacy apps are hardcoded to lookup those values. | |
| 588 void GetXPStyleDefaultBrowserUserEntries(BrowserDistribution* dist, | |
| 589 const base::FilePath& chrome_exe, | |
| 590 const base::string16& suffix, | |
| 591 ScopedVector<RegistryEntry>* entries) { | |
| 592 // File extension associations. | |
| 593 base::string16 html_prog_id(GetBrowserProgId(suffix)); | |
| 594 for (int i = 0; ShellUtil::kDefaultFileAssociations[i] != NULL; i++) { | |
| 595 GetAppDefaultRegistrationEntries( | |
| 596 html_prog_id, ShellUtil::kDefaultFileAssociations[i], true, entries); | |
| 597 } | |
| 598 | |
| 599 // Protocols associations. | |
| 600 base::string16 chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe); | |
| 601 base::string16 chrome_icon = ShellUtil::FormatIconLocation( | |
| 602 chrome_exe, dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME)); | |
| 603 for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) { | |
| 604 GetXPStyleUserProtocolEntries(ShellUtil::kBrowserProtocolAssociations[i], | |
| 605 chrome_icon, chrome_open, entries); | |
| 606 } | |
| 607 | |
| 608 // start->Internet shortcut. | |
| 609 base::string16 start_menu(ShellUtil::kRegStartMenuInternet); | |
| 610 base::string16 app_name = dist->GetBaseAppName() + suffix; | |
| 611 entries->push_back(new RegistryEntry(start_menu, app_name)); | |
| 612 } | |
| 613 | |
| 614 // Checks that all |entries| are present on this computer (or absent if their | 137 // Checks that all |entries| are present on this computer (or absent if their |
| 615 // |removal_flag_| is set). |look_for_in| is passed to | 138 // |removal_flag_| is set). |look_for_in| is passed to |
| 616 // RegistryEntry::ExistsInRegistry(). Documentation for it can be found there. | 139 // RegistryEntry::ExistsInRegistry(). Documentation for it can be found there. |
| 617 bool AreEntriesAsDesired(const ScopedVector<RegistryEntry>& entries, | 140 bool AreEntriesAsDesired(const ScopedVector<RegistryEntry>& entries, |
| 618 uint32_t look_for_in) { | 141 uint32_t look_for_in) { |
| 619 for (const auto* entry : entries) { | 142 for (const auto* entry : entries) { |
| 620 if (entry->ExistsInRegistry(look_for_in) != !entry->IsFlaggedForRemoval()) | 143 if (entry->ExistsInRegistry(look_for_in) != !entry->IsFlaggedForRemoval()) |
| 621 return false; | 144 return false; |
| 622 } | 145 } |
| 623 return true; | 146 return true; |
| 624 } | 147 } |
| 625 | 148 |
| 626 // Checks that all required registry entries for Chrome are already present on | 149 // Checks that all required registry entries for Chrome are already present on |
| 627 // this computer (or absent if their |removal_flag_| is set). | 150 // this computer (or absent if their |removal_flag_| is set). |
| 628 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. | 151 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. |
| 629 // Note: between r133333 and r154145 we were registering parts of Chrome in HKCU | 152 // Note: between r133333 and r154145 we were registering parts of Chrome in HKCU |
| 630 // and parts in HKLM for user-level installs; we now always register everything | 153 // and parts in HKLM for user-level installs; we now always register everything |
| 631 // under a single registry root. Not doing so caused http://crbug.com/144910 for | 154 // under a single registry root. Not doing so caused http://crbug.com/144910 for |
| 632 // users who first-installed Chrome in that revision range (those users are | 155 // users who first-installed Chrome in that revision range (those users are |
| 633 // still impacted by http://crbug.com/144910). This method will keep returning | 156 // still impacted by http://crbug.com/144910). This method will keep returning |
| 634 // true for affected users (i.e. who have all the registrations, but over both | 157 // true for affected users (i.e. who have all the registrations, but over both |
| 635 // registry roots). | 158 // registry roots). |
| 636 bool IsChromeRegistered(BrowserDistribution* dist, | 159 bool IsChromeRegistered(BrowserDistribution* dist, |
| 637 const base::FilePath& chrome_exe, | 160 const base::FilePath& chrome_exe, |
| 638 const base::string16& suffix, | 161 const base::string16& suffix, |
| 639 uint32_t look_for_in) { | 162 uint32_t look_for_in) { |
| 640 ScopedVector<RegistryEntry> entries; | 163 ScopedVector<RegistryEntry> entries; |
| 641 GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries); | 164 installer_util::GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries); |
| 642 GetShellIntegrationEntries(dist, chrome_exe, suffix, &entries); | 165 installer_util::GetShellIntegrationEntries(dist, chrome_exe, suffix, |
| 643 GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries); | 166 &entries); |
| 167 installer_util::GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries); |
| 644 return AreEntriesAsDesired(entries, look_for_in); | 168 return AreEntriesAsDesired(entries, look_for_in); |
| 645 } | 169 } |
| 646 | 170 |
| 647 // This method checks if Chrome is already registered on the local machine | 171 // This method checks if Chrome is already registered on the local machine |
| 648 // for the requested protocol. It just checks the one value required for this. | 172 // for the requested protocol. It just checks the one value required for this. |
| 649 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. | 173 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. |
| 650 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, | 174 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, |
| 651 const base::string16& suffix, | 175 const base::string16& suffix, |
| 652 const base::string16& protocol, | 176 const base::string16& protocol, |
| 653 uint32_t look_for_in) { | 177 uint32_t look_for_in) { |
| 654 ScopedVector<RegistryEntry> entries; | 178 ScopedVector<RegistryEntry> entries; |
| 655 GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); | 179 installer_util::GetProtocolCapabilityEntries(dist, suffix, protocol, |
| 180 &entries); |
| 656 return AreEntriesAsDesired(entries, look_for_in); | 181 return AreEntriesAsDesired(entries, look_for_in); |
| 657 } | 182 } |
| 658 | 183 |
| 659 // This method registers Chrome on Vista by launching an elevated setup.exe. | 184 // This method registers Chrome on Vista by launching an elevated setup.exe. |
| 660 // That will show the user the standard Vista elevation prompt. If the user | 185 // That will show the user the standard Vista elevation prompt. If the user |
| 661 // accepts it the new process will make the necessary changes and return SUCCESS | 186 // accepts it the new process will make the necessary changes and return SUCCESS |
| 662 // that we capture and return. | 187 // that we capture and return. |
| 663 // If protocol is non-empty we will also register Chrome as being capable of | 188 // If protocol is non-empty we will also register Chrome as being capable of |
| 664 // handling the protocol. | 189 // handling the protocol. |
| 665 bool ElevateAndRegisterChrome(BrowserDistribution* dist, | 190 bool ElevateAndRegisterChrome(BrowserDistribution* dist, |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 766 case CONFIRM_PROGID_REGISTRATION: | 291 case CONFIRM_PROGID_REGISTRATION: |
| 767 // Software\Classes\ChromeHTML|suffix| | 292 // Software\Classes\ChromeHTML|suffix| |
| 768 reg_key = ShellUtil::kRegClasses; | 293 reg_key = ShellUtil::kRegClasses; |
| 769 reg_key.push_back(base::FilePath::kSeparators[0]); | 294 reg_key.push_back(base::FilePath::kSeparators[0]); |
| 770 reg_key.append(dist->GetBrowserProgIdPrefix()); | 295 reg_key.append(dist->GetBrowserProgIdPrefix()); |
| 771 reg_key.append(suffix); | 296 reg_key.append(suffix); |
| 772 break; | 297 break; |
| 773 case CONFIRM_SHELL_REGISTRATION: | 298 case CONFIRM_SHELL_REGISTRATION: |
| 774 case CONFIRM_SHELL_REGISTRATION_IN_HKLM: | 299 case CONFIRM_SHELL_REGISTRATION_IN_HKLM: |
| 775 // Software\Clients\StartMenuInternet\Google Chrome|suffix| | 300 // Software\Clients\StartMenuInternet\Google Chrome|suffix| |
| 776 reg_key = GetBrowserClientKey(dist, suffix); | 301 reg_key = installer_util::GetBrowserClientKey(dist, suffix); |
| 777 break; | 302 break; |
| 778 default: | 303 default: |
| 779 NOTREACHED(); | 304 NOTREACHED(); |
| 780 break; | 305 break; |
| 781 } | 306 } |
| 782 reg_key.append(ShellUtil::kRegShellOpen); | 307 reg_key.append(ShellUtil::kRegShellOpen); |
| 783 | 308 |
| 784 // ProgId registrations are allowed to reside in HKCU for user-level installs | 309 // ProgId registrations are allowed to reside in HKCU for user-level installs |
| 785 // (and values there have priority over values in HKLM). The same is true for | 310 // (and values there have priority over values in HKLM). The same is true for |
| 786 // shell integration entries as of Windows 8. | 311 // shell integration entries as of Windows 8. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 } | 373 } |
| 849 | 374 |
| 850 // Associates Chrome with supported protocols and file associations. This should | 375 // Associates Chrome with supported protocols and file associations. This should |
| 851 // not be required on Vista+ but since some applications still read | 376 // not be required on Vista+ but since some applications still read |
| 852 // Software\Classes\http key directly, we have to do this on Vista+ as well. | 377 // Software\Classes\http key directly, we have to do this on Vista+ as well. |
| 853 bool RegisterChromeAsDefaultXPStyle(BrowserDistribution* dist, | 378 bool RegisterChromeAsDefaultXPStyle(BrowserDistribution* dist, |
| 854 int shell_change, | 379 int shell_change, |
| 855 const base::FilePath& chrome_exe) { | 380 const base::FilePath& chrome_exe) { |
| 856 bool ret = true; | 381 bool ret = true; |
| 857 ScopedVector<RegistryEntry> entries; | 382 ScopedVector<RegistryEntry> entries; |
| 858 GetXPStyleDefaultBrowserUserEntries( | 383 installer_util::GetXPStyleDefaultBrowserUserEntries( |
| 859 dist, chrome_exe, | 384 dist, chrome_exe, |
| 860 ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe), &entries); | 385 ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe), &entries); |
| 861 | 386 |
| 862 // Change the default browser for current user. | 387 // Change the default browser for current user. |
| 863 if ((shell_change & ShellUtil::CURRENT_USER) && | 388 if ((shell_change & ShellUtil::CURRENT_USER) && |
| 864 !ShellUtil::AddRegistryEntries(HKEY_CURRENT_USER, entries)) { | 389 !ShellUtil::AddRegistryEntries(HKEY_CURRENT_USER, entries)) { |
| 865 ret = false; | 390 ret = false; |
| 866 LOG(ERROR) << "Could not make Chrome default browser (XP/current user)."; | 391 LOG(ERROR) << "Could not make Chrome default browser (XP/current user)."; |
| 867 } | 392 } |
| 868 | 393 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 884 BrowserDistribution* dist, | 409 BrowserDistribution* dist, |
| 885 const base::FilePath& chrome_exe, | 410 const base::FilePath& chrome_exe, |
| 886 const base::string16& protocol) { | 411 const base::string16& protocol) { |
| 887 ScopedVector<RegistryEntry> entries; | 412 ScopedVector<RegistryEntry> entries; |
| 888 const base::string16 chrome_open( | 413 const base::string16 chrome_open( |
| 889 ShellUtil::GetChromeShellOpenCmd(chrome_exe)); | 414 ShellUtil::GetChromeShellOpenCmd(chrome_exe)); |
| 890 const base::string16 chrome_icon( | 415 const base::string16 chrome_icon( |
| 891 ShellUtil::FormatIconLocation( | 416 ShellUtil::FormatIconLocation( |
| 892 chrome_exe, | 417 chrome_exe, |
| 893 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME))); | 418 dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME))); |
| 894 GetXPStyleUserProtocolEntries(protocol, chrome_icon, chrome_open, &entries); | 419 installer_util::GetXPStyleUserProtocolEntries(protocol, chrome_icon, |
| 420 chrome_open, &entries); |
| 895 // Change the default protocol handler for current user. | 421 // Change the default protocol handler for current user. |
| 896 if (!ShellUtil::AddRegistryEntries(HKEY_CURRENT_USER, entries)) { | 422 if (!ShellUtil::AddRegistryEntries(HKEY_CURRENT_USER, entries)) { |
| 897 LOG(ERROR) << "Could not make Chrome default protocol client (XP)."; | 423 LOG(ERROR) << "Could not make Chrome default protocol client (XP)."; |
| 898 return false; | 424 return false; |
| 899 } | 425 } |
| 900 | 426 |
| 901 return true; | 427 return true; |
| 902 } | 428 } |
| 903 | 429 |
| 904 // Returns |properties.shortcut_name| if the property is set, otherwise it | 430 // Returns |properties.shortcut_name| if the property is set, otherwise it |
| (...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1625 if (key.Open(root, client_path.c_str(), | 1151 if (key.Open(root, client_path.c_str(), |
| 1626 KEY_QUERY_VALUE) != ERROR_SUCCESS || | 1152 KEY_QUERY_VALUE) != ERROR_SUCCESS || |
| 1627 key.ReadValue(NULL, &name) != ERROR_SUCCESS || | 1153 key.ReadValue(NULL, &name) != ERROR_SUCCESS || |
| 1628 name.empty() || | 1154 name.empty() || |
| 1629 name.find(dist->GetBaseAppName()) != base::string16::npos) { | 1155 name.find(dist->GetBaseAppName()) != base::string16::npos) { |
| 1630 continue; | 1156 continue; |
| 1631 } | 1157 } |
| 1632 // Read the browser's reinstall command. | 1158 // Read the browser's reinstall command. |
| 1633 if (key.Open(root, (client_path + L"\\InstallInfo").c_str(), | 1159 if (key.Open(root, (client_path + L"\\InstallInfo").c_str(), |
| 1634 KEY_QUERY_VALUE) == ERROR_SUCCESS && | 1160 KEY_QUERY_VALUE) == ERROR_SUCCESS && |
| 1635 key.ReadValue(kReinstallCommand, &command) == ERROR_SUCCESS && | 1161 key.ReadValue(installer_util::kReinstallCommand, &command) == |
| 1162 ERROR_SUCCESS && |
| 1636 !command.empty()) { | 1163 !command.empty()) { |
| 1637 (*browsers)[name] = command; | 1164 (*browsers)[name] = command; |
| 1638 } | 1165 } |
| 1639 } | 1166 } |
| 1640 } | 1167 } |
| 1641 } | 1168 } |
| 1642 | 1169 |
| 1643 base::string16 ShellUtil::GetCurrentInstallationSuffix( | 1170 base::string16 ShellUtil::GetCurrentInstallationSuffix( |
| 1644 BrowserDistribution* dist, | 1171 BrowserDistribution* dist, |
| 1645 const base::FilePath& chrome_exe) { | 1172 const base::FilePath& chrome_exe) { |
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2032 // Check if chrome is already registered with this suffix. | 1559 // Check if chrome is already registered with this suffix. |
| 2033 if (IsChromeRegistered(dist, chrome_exe, suffix, look_for_in)) | 1560 if (IsChromeRegistered(dist, chrome_exe, suffix, look_for_in)) |
| 2034 return true; | 1561 return true; |
| 2035 | 1562 |
| 2036 bool result = true; | 1563 bool result = true; |
| 2037 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { | 1564 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { |
| 2038 // Do the full registration if we can do it at user-level or if the user is | 1565 // Do the full registration if we can do it at user-level or if the user is |
| 2039 // an admin. | 1566 // an admin. |
| 2040 ScopedVector<RegistryEntry> progid_and_appreg_entries; | 1567 ScopedVector<RegistryEntry> progid_and_appreg_entries; |
| 2041 ScopedVector<RegistryEntry> shell_entries; | 1568 ScopedVector<RegistryEntry> shell_entries; |
| 2042 GetChromeProgIdEntries(dist, chrome_exe, suffix, | 1569 installer_util::GetChromeProgIdEntries(dist, chrome_exe, suffix, |
| 2043 &progid_and_appreg_entries); | 1570 &progid_and_appreg_entries); |
| 2044 GetChromeAppRegistrationEntries(chrome_exe, suffix, | 1571 installer_util::GetChromeAppRegistrationEntries(chrome_exe, suffix, |
| 2045 &progid_and_appreg_entries); | 1572 &progid_and_appreg_entries); |
| 2046 GetShellIntegrationEntries(dist, chrome_exe, suffix, &shell_entries); | 1573 installer_util::GetShellIntegrationEntries(dist, chrome_exe, suffix, |
| 1574 &shell_entries); |
| 2047 result = (AddRegistryEntries(root, progid_and_appreg_entries) && | 1575 result = (AddRegistryEntries(root, progid_and_appreg_entries) && |
| 2048 AddRegistryEntries(root, shell_entries)); | 1576 AddRegistryEntries(root, shell_entries)); |
| 2049 } else if (elevate_if_not_admin && | 1577 } else if (elevate_if_not_admin && |
| 2050 base::win::GetVersion() >= base::win::VERSION_VISTA && | 1578 base::win::GetVersion() >= base::win::VERSION_VISTA && |
| 2051 ElevateAndRegisterChrome(dist, chrome_exe, suffix, base::string16())) { | 1579 ElevateAndRegisterChrome(dist, chrome_exe, suffix, base::string16())) { |
| 2052 // If the user is not an admin and OS is between Vista and Windows 7 | 1580 // If the user is not an admin and OS is between Vista and Windows 7 |
| 2053 // inclusively, try to elevate and register. This is only intended for | 1581 // inclusively, try to elevate and register. This is only intended for |
| 2054 // user-level installs as system-level installs should always be run with | 1582 // user-level installs as system-level installs should always be run with |
| 2055 // admin rights. | 1583 // admin rights. |
| 2056 result = true; | 1584 result = true; |
| 2057 } else { | 1585 } else { |
| 2058 // If we got to this point then all we can do is create ProgId and basic app | 1586 // If we got to this point then all we can do is create ProgId and basic app |
| 2059 // registrations under HKCU. | 1587 // registrations under HKCU. |
| 2060 ScopedVector<RegistryEntry> entries; | 1588 ScopedVector<RegistryEntry> entries; |
| 2061 GetChromeProgIdEntries(dist, chrome_exe, base::string16(), &entries); | 1589 installer_util::GetChromeProgIdEntries(dist, chrome_exe, base::string16(), |
| 1590 &entries); |
| 2062 // Prefer to use |suffix|; unless Chrome's ProgIds are already registered | 1591 // Prefer to use |suffix|; unless Chrome's ProgIds are already registered |
| 2063 // with no suffix (as per the old registration style): in which case some | 1592 // with no suffix (as per the old registration style): in which case some |
| 2064 // other registry entries could refer to them and since we were not able to | 1593 // other registry entries could refer to them and since we were not able to |
| 2065 // set our HKLM entries above, we are better off not altering these here. | 1594 // set our HKLM entries above, we are better off not altering these here. |
| 2066 if (!AreEntriesAsDesired(entries, RegistryEntry::LOOK_IN_HKCU)) { | 1595 if (!AreEntriesAsDesired(entries, RegistryEntry::LOOK_IN_HKCU)) { |
| 2067 if (!suffix.empty()) { | 1596 if (!suffix.empty()) { |
| 2068 entries.clear(); | 1597 entries.clear(); |
| 2069 GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries); | 1598 installer_util::GetChromeProgIdEntries(dist, chrome_exe, suffix, |
| 2070 GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries); | 1599 &entries); |
| 1600 installer_util::GetChromeAppRegistrationEntries(chrome_exe, suffix, |
| 1601 &entries); |
| 2071 } | 1602 } |
| 2072 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); | 1603 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); |
| 2073 } else { | 1604 } else { |
| 2074 // The ProgId is registered unsuffixed in HKCU, also register the app with | 1605 // The ProgId is registered unsuffixed in HKCU, also register the app with |
| 2075 // Windows in HKCU (this was not done in the old registration style and | 1606 // Windows in HKCU (this was not done in the old registration style and |
| 2076 // thus needs to be done after the above check for the unsuffixed | 1607 // thus needs to be done after the above check for the unsuffixed |
| 2077 // registration). | 1608 // registration). |
| 2078 entries.clear(); | 1609 entries.clear(); |
| 2079 GetChromeAppRegistrationEntries(chrome_exe, base::string16(), &entries); | 1610 installer_util::GetChromeAppRegistrationEntries( |
| 1611 chrome_exe, base::string16(), &entries); |
| 2080 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); | 1612 result = AddRegistryEntries(HKEY_CURRENT_USER, entries); |
| 2081 } | 1613 } |
| 2082 } | 1614 } |
| 2083 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); | 1615 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); |
| 2084 return result; | 1616 return result; |
| 2085 } | 1617 } |
| 2086 | 1618 |
| 2087 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, | 1619 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, |
| 2088 const base::FilePath& chrome_exe, | 1620 const base::FilePath& chrome_exe, |
| 2089 const base::string16& unique_suffix, | 1621 const base::string16& unique_suffix, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2116 return true; | 1648 return true; |
| 2117 | 1649 |
| 2118 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { | 1650 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { |
| 2119 // We can do this operation directly. | 1651 // We can do this operation directly. |
| 2120 // First, make sure Chrome is fully registered on this machine. | 1652 // First, make sure Chrome is fully registered on this machine. |
| 2121 if (!RegisterChromeBrowser(dist, chrome_exe, suffix, false)) | 1653 if (!RegisterChromeBrowser(dist, chrome_exe, suffix, false)) |
| 2122 return false; | 1654 return false; |
| 2123 | 1655 |
| 2124 // Write in the capabillity for the protocol. | 1656 // Write in the capabillity for the protocol. |
| 2125 ScopedVector<RegistryEntry> entries; | 1657 ScopedVector<RegistryEntry> entries; |
| 2126 GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); | 1658 installer_util::GetProtocolCapabilityEntries(dist, suffix, protocol, |
| 1659 &entries); |
| 2127 return AddRegistryEntries(root, entries); | 1660 return AddRegistryEntries(root, entries); |
| 2128 } else if (elevate_if_not_admin && | 1661 } else if (elevate_if_not_admin && |
| 2129 base::win::GetVersion() >= base::win::VERSION_VISTA) { | 1662 base::win::GetVersion() >= base::win::VERSION_VISTA) { |
| 2130 // Elevate to do the whole job | 1663 // Elevate to do the whole job |
| 2131 return ElevateAndRegisterChrome(dist, chrome_exe, suffix, protocol); | 1664 return ElevateAndRegisterChrome(dist, chrome_exe, suffix, protocol); |
| 2132 } else { | 1665 } else { |
| 2133 // Admin rights are required to register capabilities before Windows 8. | 1666 // Admin rights are required to register capabilities before Windows 8. |
| 2134 return false; | 1667 return false; |
| 2135 } | 1668 } |
| 2136 } | 1669 } |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2269 // static | 1802 // static |
| 2270 bool ShellUtil::AddFileAssociations( | 1803 bool ShellUtil::AddFileAssociations( |
| 2271 const base::string16& prog_id, | 1804 const base::string16& prog_id, |
| 2272 const base::CommandLine& command_line, | 1805 const base::CommandLine& command_line, |
| 2273 const base::string16& file_type_name, | 1806 const base::string16& file_type_name, |
| 2274 const base::FilePath& icon_path, | 1807 const base::FilePath& icon_path, |
| 2275 const std::set<base::string16>& file_extensions) { | 1808 const std::set<base::string16>& file_extensions) { |
| 2276 ScopedVector<RegistryEntry> entries; | 1809 ScopedVector<RegistryEntry> entries; |
| 2277 | 1810 |
| 2278 // Create a class for this app. | 1811 // Create a class for this app. |
| 2279 ApplicationInfo app_info; | 1812 installer_util::ApplicationInfo app_info; |
| 2280 app_info.prog_id = prog_id; | 1813 app_info.prog_id = prog_id; |
| 2281 app_info.file_type_name = file_type_name; | 1814 app_info.file_type_name = file_type_name; |
| 2282 app_info.file_type_icon_path = icon_path; | 1815 app_info.file_type_icon_path = icon_path; |
| 2283 app_info.file_type_icon_index = 0; | 1816 app_info.file_type_icon_index = 0; |
| 2284 app_info.command_line = command_line.GetCommandLineStringWithPlaceholders(); | 1817 app_info.command_line = command_line.GetCommandLineStringWithPlaceholders(); |
| 2285 GetProgIdEntries(app_info, &entries); | 1818 installer_util::GetProgIdEntries(app_info, &entries); |
| 2286 | 1819 |
| 2287 // Associate each extension that the app can handle with the class. Set this | 1820 // Associate each extension that the app can handle with the class. Set this |
| 2288 // app as the default handler if and only if there is no existing default. | 1821 // app as the default handler if and only if there is no existing default. |
| 2289 for (std::set<base::string16>::const_iterator it = file_extensions.begin(); | 1822 for (std::set<base::string16>::const_iterator it = file_extensions.begin(); |
| 2290 it != file_extensions.end(); | 1823 it != file_extensions.end(); |
| 2291 ++it) { | 1824 ++it) { |
| 2292 // Do not allow empty file extensions, or extensions beginning with a '.'. | 1825 // Do not allow empty file extensions, or extensions beginning with a '.'. |
| 2293 DCHECK(!it->empty()); | 1826 DCHECK(!it->empty()); |
| 2294 DCHECK_NE(L'.', (*it)[0]); | 1827 DCHECK_NE(L'.', (*it)[0]); |
| 2295 base::string16 ext(1, L'.'); | 1828 base::string16 ext(1, L'.'); |
| 2296 ext.append(*it); | 1829 ext.append(*it); |
| 2297 GetAppExtRegistrationEntries(prog_id, ext, &entries); | 1830 installer_util::GetAppExtRegistrationEntries(prog_id, ext, &entries); |
| 2298 | 1831 |
| 2299 // Regstering as the default will have no effect on Windows 8 (see | 1832 // Regstering as the default will have no effect on Windows 8 (see |
| 2300 // documentation for GetAppDefaultRegistrationEntries). However, if our app | 1833 // documentation for GetAppDefaultRegistrationEntries). However, if our app |
| 2301 // is the only handler, it will automatically become the default, so the | 1834 // is the only handler, it will automatically become the default, so the |
| 2302 // same effect is achieved. | 1835 // same effect is achieved. |
| 2303 GetAppDefaultRegistrationEntries(prog_id, ext, false, &entries); | 1836 installer_util::GetAppDefaultRegistrationEntries(prog_id, ext, false, |
| 1837 &entries); |
| 2304 } | 1838 } |
| 2305 | 1839 |
| 2306 return AddRegistryEntries(HKEY_CURRENT_USER, entries); | 1840 return AddRegistryEntries(HKEY_CURRENT_USER, entries); |
| 2307 } | 1841 } |
| 2308 | 1842 |
| 2309 // static | 1843 // static |
| 2310 bool ShellUtil::DeleteFileAssociations(const base::string16& prog_id) { | 1844 bool ShellUtil::DeleteFileAssociations(const base::string16& prog_id) { |
| 2311 // Delete the key HKEY_CURRENT_USER\Software\Classes\PROGID. | 1845 // Delete the key HKEY_CURRENT_USER\Software\Classes\PROGID. |
| 2312 base::string16 key_path(kRegClasses); | 1846 base::string16 key_path(kRegClasses); |
| 2313 key_path.push_back(base::FilePath::kSeparators[0]); | 1847 key_path.push_back(base::FilePath::kSeparators[0]); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2329 itr != entries.end(); ++itr) | 1863 itr != entries.end(); ++itr) |
| 2330 (*itr)->AddToWorkItemList(root, items.get()); | 1864 (*itr)->AddToWorkItemList(root, items.get()); |
| 2331 | 1865 |
| 2332 // Apply all the registry changes and if there is a problem, rollback | 1866 // Apply all the registry changes and if there is a problem, rollback |
| 2333 if (!items->Do()) { | 1867 if (!items->Do()) { |
| 2334 items->Rollback(); | 1868 items->Rollback(); |
| 2335 return false; | 1869 return false; |
| 2336 } | 1870 } |
| 2337 return true; | 1871 return true; |
| 2338 } | 1872 } |
| OLD | NEW |