| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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" |
| 11 | 11 |
| 12 #include <windows.h> | 12 #include <windows.h> |
| 13 #include <shlobj.h> | 13 #include <shlobj.h> |
| 14 | 14 |
| 15 #include "base/command_line.h" | 15 #include "base/command_line.h" |
| 16 #include "base/file_path.h" | 16 #include "base/file_path.h" |
| 17 #include "base/file_util.h" | 17 #include "base/file_util.h" |
| 18 #include "base/logging.h" | 18 #include "base/logging.h" |
| 19 #include "base/memory/scoped_ptr.h" | 19 #include "base/memory/scoped_ptr.h" |
| 20 #include "base/stl_util-inl.h" | 20 #include "base/stl_util-inl.h" |
| 21 #include "base/string_number_conversions.h" | 21 #include "base/string_number_conversions.h" |
| 22 #include "base/string_split.h" | 22 #include "base/string_split.h" |
| 23 #include "base/string_util.h" | 23 #include "base/string_util.h" |
| 24 #include "base/utf_string_conversions.h" | 24 #include "base/utf_string_conversions.h" |
| 25 #include "base/values.h" | 25 #include "base/values.h" |
| 26 #include "base/win/registry.h" | 26 #include "base/win/registry.h" |
| 27 #include "base/win/scoped_comptr.h" |
| 27 #include "base/win/windows_version.h" | 28 #include "base/win/windows_version.h" |
| 28 #include "chrome/common/chrome_constants.h" | 29 #include "chrome/common/chrome_constants.h" |
| 29 #include "chrome/common/chrome_switches.h" | 30 #include "chrome/common/chrome_switches.h" |
| 30 #include "chrome/installer/util/browser_distribution.h" | 31 #include "chrome/installer/util/browser_distribution.h" |
| 31 #include "chrome/installer/util/install_util.h" | 32 #include "chrome/installer/util/install_util.h" |
| 32 #include "chrome/installer/util/master_preferences.h" | 33 #include "chrome/installer/util/master_preferences.h" |
| 33 #include "chrome/installer/util/master_preferences_constants.h" | 34 #include "chrome/installer/util/master_preferences_constants.h" |
| 34 | 35 |
| 35 #include "installer_util_strings.h" | 36 #include "installer_util_strings.h" |
| 36 | 37 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 63 entries->push_front(new RegistryEntry( | 64 entries->push_front(new RegistryEntry( |
| 64 chrome_html_prog_id, ShellUtil::kRegUrlProtocol, L"")); | 65 chrome_html_prog_id, ShellUtil::kRegUrlProtocol, L"")); |
| 65 entries->push_front(new RegistryEntry( | 66 entries->push_front(new RegistryEntry( |
| 66 chrome_html_prog_id + ShellUtil::kRegDefaultIcon, icon_path)); | 67 chrome_html_prog_id + ShellUtil::kRegDefaultIcon, icon_path)); |
| 67 entries->push_front(new RegistryEntry( | 68 entries->push_front(new RegistryEntry( |
| 68 chrome_html_prog_id + ShellUtil::kRegShellOpen, open_cmd)); | 69 chrome_html_prog_id + ShellUtil::kRegShellOpen, open_cmd)); |
| 69 | 70 |
| 70 return true; | 71 return true; |
| 71 } | 72 } |
| 72 | 73 |
| 74 // This method returns a list of the system level registry entries |
| 75 // needed to declare a capability of handling a protocol. |
| 76 static bool GetProtocolCapabilityEntries(BrowserDistribution* dist, |
| 77 const std::wstring& chrome_exe, |
| 78 const std::wstring& suffix, |
| 79 const std::wstring& protocol, |
| 80 std::list<RegistryEntry*>* entries) { |
| 81 std::wstring app_name = dist->GetApplicationName() + suffix; |
| 82 std::wstring start_menu_entry(ShellUtil::kRegStartMenuInternet); |
| 83 start_menu_entry.append(L"\\" + app_name); |
| 84 |
| 85 std::wstring capabilities(start_menu_entry + L"\\Capabilities"); |
| 86 |
| 87 std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId); |
| 88 html_prog_id.append(suffix); |
| 89 entries->push_front(new RegistryEntry(capabilities + L"\\URLAssociations", |
| 90 protocol, html_prog_id)); |
| 91 return true; |
| 92 } |
| 93 |
| 94 |
| 73 // This method returns a list of all the system level registry entries that | 95 // This method returns a list of all the system level registry entries that |
| 74 // are needed to register Chromium on the machine. | 96 // are needed to register Chromium on the machine. |
| 75 static bool GetSystemEntries(BrowserDistribution* dist, | 97 static bool GetSystemEntries(BrowserDistribution* dist, |
| 76 const std::wstring& chrome_exe, | 98 const std::wstring& chrome_exe, |
| 77 const std::wstring& suffix, | 99 const std::wstring& suffix, |
| 78 std::list<RegistryEntry*>* entries) { | 100 std::list<RegistryEntry*>* entries) { |
| 79 std::wstring icon_path = ShellUtil::GetChromeIcon(dist, chrome_exe); | 101 std::wstring icon_path = ShellUtil::GetChromeIcon(dist, chrome_exe); |
| 80 std::wstring quoted_exe_path = L"\"" + chrome_exe + L"\""; | 102 std::wstring quoted_exe_path = L"\"" + chrome_exe + L"\""; |
| 81 | 103 |
| 82 std::wstring app_name = dist->GetApplicationName() + suffix; | 104 std::wstring app_name = dist->GetApplicationName() + suffix; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 112 entries->push_front(new RegistryEntry(capabilities + L"\\StartMenu", | 134 entries->push_front(new RegistryEntry(capabilities + L"\\StartMenu", |
| 113 L"StartMenuInternet", app_name)); | 135 L"StartMenuInternet", app_name)); |
| 114 | 136 |
| 115 std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId); | 137 std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId); |
| 116 html_prog_id.append(suffix); | 138 html_prog_id.append(suffix); |
| 117 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { | 139 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { |
| 118 entries->push_front(new RegistryEntry( | 140 entries->push_front(new RegistryEntry( |
| 119 capabilities + L"\\FileAssociations", | 141 capabilities + L"\\FileAssociations", |
| 120 ShellUtil::kFileAssociations[i], html_prog_id)); | 142 ShellUtil::kFileAssociations[i], html_prog_id)); |
| 121 } | 143 } |
| 122 for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) { | 144 for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL; |
| 145 i++) { |
| 123 entries->push_front(new RegistryEntry( | 146 entries->push_front(new RegistryEntry( |
| 124 capabilities + L"\\URLAssociations", | 147 capabilities + L"\\URLAssociations", |
| 125 ShellUtil::kProtocolAssociations[i], html_prog_id)); | 148 ShellUtil::kPotentialProtocolAssociations[i], html_prog_id)); |
| 126 } | 149 } |
| 127 | 150 |
| 128 FilePath chrome_path(chrome_exe); | 151 FilePath chrome_path(chrome_exe); |
| 129 std::wstring app_path_key(ShellUtil::kAppPathsRegistryKey); | 152 std::wstring app_path_key(ShellUtil::kAppPathsRegistryKey); |
| 130 file_util::AppendToPath(&app_path_key, chrome_path.BaseName().value()); | 153 file_util::AppendToPath(&app_path_key, chrome_path.BaseName().value()); |
| 131 entries->push_front(new RegistryEntry(app_path_key, chrome_exe)); | 154 entries->push_front(new RegistryEntry(app_path_key, chrome_exe)); |
| 132 entries->push_front(new RegistryEntry(app_path_key, | 155 entries->push_front(new RegistryEntry(app_path_key, |
| 133 ShellUtil::kAppPathsRegistryPathName, chrome_path.DirName().value())); | 156 ShellUtil::kAppPathsRegistryPathName, chrome_path.DirName().value())); |
| 134 | 157 |
| 135 // TODO: add chrome to open with list (Bug 16726). | 158 // TODO: add chrome to open with list (Bug 16726). |
| 136 return true; | 159 return true; |
| 137 } | 160 } |
| 138 | 161 |
| 139 // This method returns a list of all the user level registry entries that | 162 // This method returns a list of all the user level registry entries that |
| 163 // are needed to make Chromium the default handler for a protocol. |
| 164 static bool GetUserProtocolEntries(BrowserDistribution* dist, |
| 165 const std::wstring& chrome_exe, |
| 166 const std::wstring& suffix, |
| 167 const std::wstring& protocol, |
| 168 const std::wstring& chrome_icon, |
| 169 const std::wstring& chrome_open, |
| 170 std::list<RegistryEntry*>* entries) { |
| 171 // Protocols associations. |
| 172 std::wstring url_key(ShellUtil::kRegClasses); |
| 173 file_util::AppendToPath(&url_key, protocol); |
| 174 |
| 175 // This registry value tells Windows that this 'class' is a URL scheme |
| 176 // so IE, explorer and other apps will route it to our handler. |
| 177 // <root hkey>\Software\Classes\<protocol>\URL Protocol |
| 178 entries->push_front(new RegistryEntry(url_key, |
| 179 ShellUtil::kRegUrlProtocol, L"")); |
| 180 |
| 181 // <root hkey>\Software\Classes\<protocol>\DefaultIcon |
| 182 std::wstring icon_key = url_key + ShellUtil::kRegDefaultIcon; |
| 183 entries->push_front(new RegistryEntry(icon_key, chrome_icon)); |
| 184 |
| 185 // <root hkey>\Software\Classes\<protocol>\shell\open\command |
| 186 std::wstring shell_key = url_key + ShellUtil::kRegShellOpen; |
| 187 entries->push_front(new RegistryEntry(shell_key, chrome_open)); |
| 188 |
| 189 // <root hkey>\Software\Classes\<protocol>\shell\open\ddeexec |
| 190 std::wstring dde_key = url_key + L"\\shell\\open\\ddeexec"; |
| 191 entries->push_front(new RegistryEntry(dde_key, L"")); |
| 192 |
| 193 // <root hkey>\Software\Classes\<protocol>\shell\@ |
| 194 std::wstring protocol_shell_key = url_key + ShellUtil::kRegShellPath; |
| 195 entries->push_front(new RegistryEntry(protocol_shell_key, L"open")); |
| 196 |
| 197 return true; |
| 198 } |
| 199 |
| 200 // This method returns a list of all the user level registry entries that |
| 140 // are needed to make Chromium default browser. | 201 // are needed to make Chromium default browser. |
| 141 static bool GetUserEntries(BrowserDistribution* dist, | 202 static bool GetUserEntries(BrowserDistribution* dist, |
| 142 const std::wstring& chrome_exe, | 203 const std::wstring& chrome_exe, |
| 143 const std::wstring& suffix, | 204 const std::wstring& suffix, |
| 144 std::list<RegistryEntry*>* entries) { | 205 std::list<RegistryEntry*>* entries) { |
| 145 // File extension associations. | 206 // File extension associations. |
| 146 std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId); | 207 std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId); |
| 147 html_prog_id.append(suffix); | 208 html_prog_id.append(suffix); |
| 148 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { | 209 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { |
| 149 std::wstring ext_key(ShellUtil::kRegClasses); | 210 std::wstring ext_key(ShellUtil::kRegClasses); |
| 150 file_util::AppendToPath(&ext_key, ShellUtil::kFileAssociations[i]); | 211 file_util::AppendToPath(&ext_key, ShellUtil::kFileAssociations[i]); |
| 151 entries->push_front(new RegistryEntry(ext_key, html_prog_id)); | 212 entries->push_front(new RegistryEntry(ext_key, html_prog_id)); |
| 152 } | 213 } |
| 153 | 214 |
| 154 // Protocols associations. | 215 // Protocols associations. |
| 155 std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe); | 216 std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe); |
| 156 std::wstring chrome_icon = ShellUtil::GetChromeIcon(dist, chrome_exe); | 217 std::wstring chrome_icon = ShellUtil::GetChromeIcon(dist, chrome_exe); |
| 157 for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) { | 218 for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) { |
| 158 std::wstring url_key(ShellUtil::kRegClasses); | 219 GetUserProtocolEntries(dist, chrome_exe, suffix, |
| 159 file_util::AppendToPath(&url_key, ShellUtil::kProtocolAssociations[i]); | 220 ShellUtil::kBrowserProtocolAssociations[i], |
| 160 | 221 chrome_icon, chrome_open, entries); |
| 161 // <root hkey>\Software\Classes\<protocol>\DefaultIcon | |
| 162 std::wstring icon_key = url_key + ShellUtil::kRegDefaultIcon; | |
| 163 entries->push_front(new RegistryEntry(icon_key, chrome_icon)); | |
| 164 | |
| 165 // <root hkey>\Software\Classes\<protocol>\shell\open\command | |
| 166 std::wstring shell_key = url_key + ShellUtil::kRegShellOpen; | |
| 167 entries->push_front(new RegistryEntry(shell_key, chrome_open)); | |
| 168 | |
| 169 // <root hkey>\Software\Classes\<protocol>\shell\open\ddeexec | |
| 170 std::wstring dde_key = url_key + L"\\shell\\open\\ddeexec"; | |
| 171 entries->push_front(new RegistryEntry(dde_key, L"")); | |
| 172 | |
| 173 // <root hkey>\Software\Classes\<protocol>\shell\@ | |
| 174 std::wstring protocol_shell_key = url_key + ShellUtil::kRegShellPath; | |
| 175 entries->push_front(new RegistryEntry(protocol_shell_key, L"open")); | |
| 176 } | 222 } |
| 177 | 223 |
| 178 // start->Internet shortcut. | 224 // start->Internet shortcut. |
| 179 std::wstring start_menu(ShellUtil::kRegStartMenuInternet); | 225 std::wstring start_menu(ShellUtil::kRegStartMenuInternet); |
| 180 std::wstring app_name = dist->GetApplicationName() + suffix; | 226 std::wstring app_name = dist->GetApplicationName() + suffix; |
| 181 entries->push_front(new RegistryEntry(start_menu, app_name)); | 227 entries->push_front(new RegistryEntry(start_menu, app_name)); |
| 182 return true; | 228 return true; |
| 183 } | 229 } |
| 184 | 230 |
| 185 // Generate work_item tasks required to create current registry entry and | 231 // Generate work_item tasks required to create current registry entry and |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries); | 336 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries); |
| 291 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin(); | 337 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin(); |
| 292 itr != entries.end() && registered; ++itr) { | 338 itr != entries.end() && registered; ++itr) { |
| 293 // We do not need registered = registered && ... since the loop condition | 339 // We do not need registered = registered && ... since the loop condition |
| 294 // is set to exit early. | 340 // is set to exit early. |
| 295 registered = (*itr)->ExistsInHKLM(); | 341 registered = (*itr)->ExistsInHKLM(); |
| 296 } | 342 } |
| 297 return registered; | 343 return registered; |
| 298 } | 344 } |
| 299 | 345 |
| 346 // This method checks if Chrome is already registered on the local machine |
| 347 // for the requested protocol. It just checks the one value required for this. |
| 348 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, |
| 349 const std::wstring& chrome_exe, |
| 350 const std::wstring& suffix, |
| 351 const std::wstring& protocol) { |
| 352 bool registered = true; |
| 353 std::list<RegistryEntry*> entries; |
| 354 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries); |
| 355 RegistryEntry::GetProtocolCapabilityEntries(dist, chrome_exe, suffix, |
| 356 protocol, &entries); |
| 357 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin(); |
| 358 itr != entries.end() && registered; ++itr) { |
| 359 // We do not need registered = registered && ... since the loop condition |
| 360 // is set to exit early. |
| 361 registered = (*itr)->ExistsInHKLM(); |
| 362 } |
| 363 return registered; |
| 364 } |
| 365 |
| 300 // This method registers Chrome on Vista by launching an elevated setup.exe. | 366 // This method registers Chrome on Vista by launching an elevated setup.exe. |
| 301 // That will show the user the standard Vista elevation prompt. If the user | 367 // That will show the user the standard Vista elevation prompt. If the user |
| 302 // accepts it the new process will make the necessary changes and return SUCCESS | 368 // accepts it the new process will make the necessary changes and return SUCCESS |
| 303 // that we capture and return. | 369 // that we capture and return. |
| 370 // If protocol is non-empty we will also register Chrome as being capable of |
| 371 // handling the protocol. |
| 304 bool ElevateAndRegisterChrome(BrowserDistribution* dist, | 372 bool ElevateAndRegisterChrome(BrowserDistribution* dist, |
| 305 const std::wstring& chrome_exe, | 373 const std::wstring& chrome_exe, |
| 306 const std::wstring& suffix) { | 374 const std::wstring& suffix, |
| 375 const std::wstring& protocol) { |
| 307 FilePath exe_path = | 376 FilePath exe_path = |
| 308 FilePath::FromWStringHack(chrome_exe).DirName() | 377 FilePath::FromWStringHack(chrome_exe).DirName() |
| 309 .Append(installer::kSetupExe); | 378 .Append(installer::kSetupExe); |
| 310 if (!file_util::PathExists(exe_path)) { | 379 if (!file_util::PathExists(exe_path)) { |
| 311 HKEY reg_root = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? | 380 HKEY reg_root = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? |
| 312 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; | 381 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; |
| 313 RegKey key(reg_root, dist->GetUninstallRegPath().c_str(), KEY_READ); | 382 RegKey key(reg_root, dist->GetUninstallRegPath().c_str(), KEY_READ); |
| 314 std::wstring uninstall_string; | 383 std::wstring uninstall_string; |
| 315 key.ReadValue(installer::kUninstallStringField, &uninstall_string); | 384 key.ReadValue(installer::kUninstallStringField, &uninstall_string); |
| 316 CommandLine command_line = CommandLine::FromString(uninstall_string); | 385 CommandLine command_line = CommandLine::FromString(uninstall_string); |
| 317 exe_path = command_line.GetProgram(); | 386 exe_path = command_line.GetProgram(); |
| 318 } | 387 } |
| 319 | 388 |
| 320 if (file_util::PathExists(exe_path)) { | 389 if (file_util::PathExists(exe_path)) { |
| 321 CommandLine cmd(exe_path); | 390 CommandLine cmd(exe_path); |
| 322 cmd.AppendSwitchNative(installer::switches::kRegisterChromeBrowser, | 391 cmd.AppendSwitchNative(installer::switches::kRegisterChromeBrowser, |
| 323 chrome_exe); | 392 chrome_exe); |
| 324 if (!suffix.empty()) { | 393 if (!suffix.empty()) { |
| 325 cmd.AppendSwitchNative( | 394 cmd.AppendSwitchNative( |
| 326 installer::switches::kRegisterChromeBrowserSuffix, suffix); | 395 installer::switches::kRegisterChromeBrowserSuffix, suffix); |
| 327 } | 396 } |
| 328 | 397 |
| 329 CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); | 398 CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); |
| 330 if (browser_command_line.HasSwitch(switches::kChromeFrame)) { | 399 if (browser_command_line.HasSwitch(switches::kChromeFrame)) { |
| 331 cmd.AppendSwitch(installer::switches::kChromeFrame); | 400 cmd.AppendSwitch(installer::switches::kChromeFrame); |
| 332 } | 401 } |
| 333 | 402 |
| 403 if (!protocol.empty()) { |
| 404 cmd.AppendSwitchNative( |
| 405 installer::switches::kRegisterURLProtocol, protocol); |
| 406 } |
| 407 |
| 334 DWORD ret_val = 0; | 408 DWORD ret_val = 0; |
| 335 InstallUtil::ExecuteExeAsAdmin(cmd, &ret_val); | 409 InstallUtil::ExecuteExeAsAdmin(cmd, &ret_val); |
| 336 if (ret_val == 0) | 410 if (ret_val == 0) |
| 337 return true; | 411 return true; |
| 338 } | 412 } |
| 339 return false; | 413 return false; |
| 340 } | 414 } |
| 341 | 415 |
| 342 // This method tries to figure out if another user has already registered her | 416 // This method tries to figure out if another user has already registered her |
| 343 // own copy of Chrome so that we can avoid overwriting it and append current | 417 // own copy of Chrome so that we can avoid overwriting it and append current |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 return false; | 463 return false; |
| 390 else | 464 else |
| 391 one_mismatch = true; | 465 one_mismatch = true; |
| 392 } | 466 } |
| 393 } | 467 } |
| 394 return true; | 468 return true; |
| 395 } | 469 } |
| 396 | 470 |
| 397 } // namespace | 471 } // namespace |
| 398 | 472 |
| 399 | |
| 400 const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon"; | 473 const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon"; |
| 401 const wchar_t* ShellUtil::kRegShellPath = L"\\shell"; | 474 const wchar_t* ShellUtil::kRegShellPath = L"\\shell"; |
| 402 const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command"; | 475 const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command"; |
| 403 const wchar_t* ShellUtil::kRegStartMenuInternet = | 476 const wchar_t* ShellUtil::kRegStartMenuInternet = |
| 404 L"Software\\Clients\\StartMenuInternet"; | 477 L"Software\\Clients\\StartMenuInternet"; |
| 405 const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes"; | 478 const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes"; |
| 406 const wchar_t* ShellUtil::kRegRegisteredApplications = | 479 const wchar_t* ShellUtil::kRegRegisteredApplications = |
| 407 L"Software\\RegisteredApplications"; | 480 L"Software\\RegisteredApplications"; |
| 408 const wchar_t* ShellUtil::kRegVistaUrlPrefs = | 481 const wchar_t* ShellUtil::kRegVistaUrlPrefs = |
| 409 L"Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\" | 482 L"Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\" |
| 410 L"http\\UserChoice"; | 483 L"http\\UserChoice"; |
| 411 const wchar_t* ShellUtil::kAppPathsRegistryKey = | 484 const wchar_t* ShellUtil::kAppPathsRegistryKey = |
| 412 L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths"; | 485 L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths"; |
| 413 const wchar_t* ShellUtil::kAppPathsRegistryPathName = L"Path"; | 486 const wchar_t* ShellUtil::kAppPathsRegistryPathName = L"Path"; |
| 414 | 487 |
| 415 #if defined(GOOGLE_CHROME_BUILD) | 488 #if defined(GOOGLE_CHROME_BUILD) |
| 416 const wchar_t* ShellUtil::kChromeHTMLProgId = L"ChromeHTML"; | 489 const wchar_t* ShellUtil::kChromeHTMLProgId = L"ChromeHTML"; |
| 417 const wchar_t* ShellUtil::kChromeHTMLProgIdDesc = L"Chrome HTML Document"; | 490 const wchar_t* ShellUtil::kChromeHTMLProgIdDesc = L"Chrome HTML Document"; |
| 418 #else | 491 #else |
| 419 const wchar_t* ShellUtil::kChromeHTMLProgId = L"ChromiumHTML"; | 492 const wchar_t* ShellUtil::kChromeHTMLProgId = L"ChromiumHTML"; |
| 420 const wchar_t* ShellUtil::kChromeHTMLProgIdDesc = L"Chromium HTML Document"; | 493 const wchar_t* ShellUtil::kChromeHTMLProgIdDesc = L"Chromium HTML Document"; |
| 421 #endif | 494 #endif |
| 422 | 495 |
| 423 const wchar_t* ShellUtil::kFileAssociations[] = {L".htm", L".html", L".shtml", | 496 const wchar_t* ShellUtil::kFileAssociations[] = {L".htm", L".html", L".shtml", |
| 424 L".xht", L".xhtml", NULL}; | 497 L".xht", L".xhtml", NULL}; |
| 425 const wchar_t* ShellUtil::kProtocolAssociations[] = {L"ftp", L"http", L"https", | 498 const wchar_t* ShellUtil::kBrowserProtocolAssociations[] = {L"ftp", L"http", |
| 426 NULL}; | 499 L"https", NULL}; |
| 500 const wchar_t* ShellUtil::kPotentialProtocolAssociations[] = {L"ftp", L"http", |
| 501 L"https", L"mailto", L"webcal", NULL}; |
| 427 const wchar_t* ShellUtil::kRegUrlProtocol = L"URL Protocol"; | 502 const wchar_t* ShellUtil::kRegUrlProtocol = L"URL Protocol"; |
| 428 | 503 |
| 429 bool ShellUtil::AdminNeededForRegistryCleanup(BrowserDistribution* dist, | 504 bool ShellUtil::AdminNeededForRegistryCleanup(BrowserDistribution* dist, |
| 430 const std::wstring& suffix) { | 505 const std::wstring& suffix) { |
| 431 bool cleanup_needed = false; | 506 bool cleanup_needed = false; |
| 432 std::list<RegistryEntry*> entries; | 507 std::list<RegistryEntry*> entries; |
| 433 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries); | 508 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries); |
| 434 RegistryEntry::GetProgIdEntries(dist, L"chrome.exe", suffix, &entries); | 509 RegistryEntry::GetProgIdEntries(dist, L"chrome.exe", suffix, &entries); |
| 435 RegistryEntry::GetSystemEntries(dist, L"chrome.exe", suffix, &entries); | 510 RegistryEntry::GetSystemEntries(dist, L"chrome.exe", suffix, &entries); |
| 436 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin(); | 511 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin(); |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 if (!dist->CanSetAsDefault()) | 704 if (!dist->CanSetAsDefault()) |
| 630 return false; | 705 return false; |
| 631 | 706 |
| 632 ShellUtil::RegisterChromeBrowser(dist, chrome_exe, L"", elevate_if_not_admin); | 707 ShellUtil::RegisterChromeBrowser(dist, chrome_exe, L"", elevate_if_not_admin); |
| 633 | 708 |
| 634 bool ret = true; | 709 bool ret = true; |
| 635 // First use the new "recommended" way on Vista to make Chrome default | 710 // First use the new "recommended" way on Vista to make Chrome default |
| 636 // browser. | 711 // browser. |
| 637 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { | 712 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { |
| 638 VLOG(1) << "Registering Chrome as default browser on Vista."; | 713 VLOG(1) << "Registering Chrome as default browser on Vista."; |
| 639 IApplicationAssociationRegistration* pAAR; | 714 base::win::ScopedComPtr<IApplicationAssociationRegistration> pAAR; |
| 640 HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration, | 715 HRESULT hr = pAAR.CreateInstance(CLSID_ApplicationAssociationRegistration, |
| 641 NULL, CLSCTX_INPROC, __uuidof(IApplicationAssociationRegistration), | 716 NULL, CLSCTX_INPROC); |
| 642 (void**)&pAAR); | |
| 643 if (SUCCEEDED(hr)) { | 717 if (SUCCEEDED(hr)) { |
| 644 std::wstring app_name = dist->GetApplicationName(); | 718 std::wstring app_name = dist->GetApplicationName(); |
| 645 std::wstring suffix; | 719 std::wstring suffix; |
| 646 if (ShellUtil::GetUserSpecificDefaultBrowserSuffix(dist, &suffix)) | 720 if (ShellUtil::GetUserSpecificDefaultBrowserSuffix(dist, &suffix)) |
| 647 app_name += suffix; | 721 app_name += suffix; |
| 648 | 722 |
| 649 hr = pAAR->SetAppAsDefaultAll(app_name.c_str()); | 723 for (int i = 0; |
| 650 pAAR->Release(); | 724 SUCCEEDED(hr) && ShellUtil::kBrowserProtocolAssociations[i] != NULL; |
| 725 i++) { |
| 726 hr = pAAR->SetAppAsDefault(app_name.c_str(), |
| 727 ShellUtil::kBrowserProtocolAssociations[i], AT_URLPROTOCOL); |
| 728 } |
| 729 |
| 730 for (int i = 0; |
| 731 SUCCEEDED(hr) && ShellUtil::kFileAssociations[i] != NULL; i++) { |
| 732 hr = pAAR->SetAppAsDefault(app_name.c_str(), |
| 733 ShellUtil::kFileAssociations[i], AT_FILEEXTENSION); |
| 734 } |
| 651 } | 735 } |
| 652 if (!SUCCEEDED(hr)) { | 736 if (!SUCCEEDED(hr)) { |
| 653 ret = false; | 737 ret = false; |
| 654 LOG(ERROR) << "Could not make Chrome default browser."; | 738 LOG(ERROR) << "Could not make Chrome default browser (Vista): HRESULT=" |
| 739 << hr << "."; |
| 655 } | 740 } |
| 656 } | 741 } |
| 657 | 742 |
| 658 // Now use the old way to associate Chrome with supported protocols and file | 743 // Now use the old way to associate Chrome with supported protocols and file |
| 659 // associations. This should not be required on Vista but since some | 744 // associations. This should not be required on Vista but since some |
| 660 // applications still read Software\Classes\http key directly, we have to do | 745 // applications still read Software\Classes\http key directly, we have to do |
| 661 // this on Vista also. | 746 // this on Vista also. |
| 662 | 747 |
| 663 std::list<RegistryEntry*> entries; | 748 std::list<RegistryEntry*> entries; |
| 664 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries); | 749 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries); |
| 665 std::wstring suffix; | 750 std::wstring suffix; |
| 666 if (!GetUserSpecificDefaultBrowserSuffix(dist, &suffix)) | 751 if (!GetUserSpecificDefaultBrowserSuffix(dist, &suffix)) |
| 667 suffix = L""; | 752 suffix = L""; |
| 668 RegistryEntry::GetUserEntries(dist, chrome_exe, suffix, &entries); | 753 RegistryEntry::GetUserEntries(dist, chrome_exe, suffix, &entries); |
| 669 // Change the default browser for current user. | 754 // Change the default browser for current user. |
| 670 if ((shell_change & ShellUtil::CURRENT_USER) && | 755 if ((shell_change & ShellUtil::CURRENT_USER) && |
| 671 !AddRegistryEntries(HKEY_CURRENT_USER, entries)) | 756 !AddRegistryEntries(HKEY_CURRENT_USER, entries)) { |
| 672 ret = false; | 757 ret = false; |
| 758 LOG(ERROR) << "Could not make Chrome default browser (XP/current user)."; |
| 759 } |
| 673 | 760 |
| 674 // Chrome as default browser at system level. | 761 // Chrome as default browser at system level. |
| 675 if ((shell_change & ShellUtil::SYSTEM_LEVEL) && | 762 if ((shell_change & ShellUtil::SYSTEM_LEVEL) && |
| 676 !AddRegistryEntries(HKEY_LOCAL_MACHINE, entries)) | 763 !AddRegistryEntries(HKEY_LOCAL_MACHINE, entries)) { |
| 677 ret = false; | 764 ret = false; |
| 765 LOG(ERROR) << "Could not make Chrome default browser (XP/system level)."; |
| 766 } |
| 678 | 767 |
| 679 // Send Windows notification event so that it can update icons for | 768 // Send Windows notification event so that it can update icons for |
| 680 // file associations. | 769 // file associations. |
| 681 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); | 770 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); |
| 682 return ret; | 771 return ret; |
| 683 } | 772 } |
| 684 | 773 |
| 774 bool ShellUtil::MakeChromeDefaultProtocolClient(BrowserDistribution* dist, |
| 775 const std::wstring& chrome_exe, |
| 776 const std::wstring& protocol) { |
| 777 if (!dist->CanSetAsDefault()) |
| 778 return false; |
| 779 |
| 780 ShellUtil::RegisterChromeForProtocol(dist, chrome_exe, L"", protocol, true); |
| 781 |
| 782 bool ret = true; |
| 783 // First use the new "recommended" way on Vista to make Chrome default |
| 784 // protocol handler. |
| 785 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { |
| 786 VLOG(1) << "Registering Chrome as default handler for " << protocol |
| 787 << " on Vista."; |
| 788 base::win::ScopedComPtr<IApplicationAssociationRegistration> pAAR; |
| 789 HRESULT hr = pAAR.CreateInstance(CLSID_ApplicationAssociationRegistration, |
| 790 NULL, CLSCTX_INPROC); |
| 791 if (SUCCEEDED(hr)) { |
| 792 std::wstring app_name = dist->GetApplicationName(); |
| 793 std::wstring suffix; |
| 794 if (ShellUtil::GetUserSpecificDefaultBrowserSuffix(dist, &suffix)) |
| 795 app_name += suffix; |
| 796 |
| 797 hr = pAAR->SetAppAsDefault(app_name.c_str(), protocol.c_str(), |
| 798 AT_URLPROTOCOL); |
| 799 } |
| 800 if (!SUCCEEDED(hr)) { |
| 801 ret = false; |
| 802 LOG(ERROR) << "Could not make Chrome default protocol client (Vista):" |
| 803 << " HRESULT=" << hr << "."; |
| 804 } |
| 805 } |
| 806 |
| 807 // Now use the old way to associate Chrome with the desired protocol. This |
| 808 // should not be required on Vista but since some applications still read |
| 809 // Software\Classes\http key directly, we have to do this on Vista also. |
| 810 |
| 811 std::list<RegistryEntry*> entries; |
| 812 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries); |
| 813 std::wstring suffix; |
| 814 if (!GetUserSpecificDefaultBrowserSuffix(dist, &suffix)) |
| 815 suffix = L""; |
| 816 std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe); |
| 817 std::wstring chrome_icon = ShellUtil::GetChromeIcon(dist, chrome_exe); |
| 818 RegistryEntry::GetUserProtocolEntries(dist, chrome_exe, suffix, protocol, |
| 819 chrome_icon, chrome_open, &entries); |
| 820 // Change the default protocol handler for current user. |
| 821 if (!AddRegistryEntries(HKEY_CURRENT_USER, entries)) { |
| 822 ret = false; |
| 823 LOG(ERROR) << "Could not make Chrome default protocol client (XP)."; |
| 824 } |
| 825 |
| 826 return ret; |
| 827 } |
| 828 |
| 685 bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist, | 829 bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist, |
| 686 const std::wstring& chrome_exe, | 830 const std::wstring& chrome_exe, |
| 687 const std::wstring& unique_suffix, | 831 const std::wstring& unique_suffix, |
| 688 bool elevate_if_not_admin) { | 832 bool elevate_if_not_admin) { |
| 689 if (!dist->CanSetAsDefault()) | 833 if (!dist->CanSetAsDefault()) |
| 690 return false; | 834 return false; |
| 691 | 835 |
| 692 // First figure out we need to append a suffix to the registry entries to | 836 // First figure out we need to append a suffix to the registry entries to |
| 693 // make them unique. | 837 // make them unique. |
| 694 std::wstring suffix; | 838 std::wstring suffix; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 709 std::list<RegistryEntry*> entries; | 853 std::list<RegistryEntry*> entries; |
| 710 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries); | 854 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries); |
| 711 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries); | 855 RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries); |
| 712 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries); | 856 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries); |
| 713 return AddRegistryEntries(HKEY_LOCAL_MACHINE, entries); | 857 return AddRegistryEntries(HKEY_LOCAL_MACHINE, entries); |
| 714 } | 858 } |
| 715 | 859 |
| 716 // If user is not an admin and OS is Vista, try to elevate and register. | 860 // If user is not an admin and OS is Vista, try to elevate and register. |
| 717 if (elevate_if_not_admin && | 861 if (elevate_if_not_admin && |
| 718 base::win::GetVersion() >= base::win::VERSION_VISTA && | 862 base::win::GetVersion() >= base::win::VERSION_VISTA && |
| 719 ElevateAndRegisterChrome(dist, chrome_exe, suffix)) | 863 ElevateAndRegisterChrome(dist, chrome_exe, suffix, L"")) |
| 720 return true; | 864 return true; |
| 721 | 865 |
| 722 // If we got to this point then all we can do is create ProgIds under HKCU | 866 // If we got to this point then all we can do is create ProgIds under HKCU |
| 723 // on XP as well as Vista. | 867 // on XP as well as Vista. |
| 724 std::list<RegistryEntry*> entries; | 868 std::list<RegistryEntry*> entries; |
| 725 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries); | 869 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries); |
| 726 RegistryEntry::GetProgIdEntries(dist, chrome_exe, L"", &entries); | 870 RegistryEntry::GetProgIdEntries(dist, chrome_exe, L"", &entries); |
| 727 return AddRegistryEntries(HKEY_CURRENT_USER, entries); | 871 return AddRegistryEntries(HKEY_CURRENT_USER, entries); |
| 728 } | 872 } |
| 729 | 873 |
| 874 bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, |
| 875 const std::wstring& chrome_exe, |
| 876 const std::wstring& unique_suffix, |
| 877 const std::wstring& protocol, |
| 878 bool elevate_if_not_admin) { |
| 879 if (!dist->CanSetAsDefault()) |
| 880 return false; |
| 881 |
| 882 // Figure out we need to append a suffix to the registry entries to |
| 883 // make them unique. |
| 884 std::wstring suffix; |
| 885 if (!unique_suffix.empty()) { |
| 886 suffix = unique_suffix; |
| 887 } else if (InstallUtil::IsPerUserInstall(chrome_exe.c_str()) && |
| 888 !GetUserSpecificDefaultBrowserSuffix(dist, &suffix) && |
| 889 !AnotherUserHasDefaultBrowser(dist, chrome_exe)) { |
| 890 suffix = L""; |
| 891 } |
| 892 |
| 893 // Check if Chromium is already registered with this suffix. |
| 894 if (IsChromeRegisteredForProtocol(dist, chrome_exe, suffix, protocol)) |
| 895 return true; |
| 896 |
| 897 if (IsUserAnAdmin()) { |
| 898 // We can do this operation directly. |
| 899 // If we're not registered at all, try to register. If that fails |
| 900 // we should give up. |
| 901 if (!IsChromeRegistered(dist, chrome_exe, suffix) && |
| 902 !RegisterChromeBrowser(dist, chrome_exe, suffix, false)) { |
| 903 return false; |
| 904 } |
| 905 |
| 906 // Write in the capabillity for the protocol. |
| 907 std::list<RegistryEntry*> entries; |
| 908 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries); |
| 909 RegistryEntry::GetProtocolCapabilityEntries(dist, chrome_exe, suffix, |
| 910 protocol, &entries); |
| 911 return AddRegistryEntries(HKEY_LOCAL_MACHINE, entries); |
| 912 } else if (elevate_if_not_admin && |
| 913 base::win::GetVersion() >= base::win::VERSION_VISTA) { |
| 914 // Elevate to do the whole job |
| 915 return ElevateAndRegisterChrome(dist, chrome_exe, suffix, protocol); |
| 916 } else { |
| 917 // we need admin rights to register our capability. If we don't |
| 918 // have them and can't elevate, give up. |
| 919 return false; |
| 920 } |
| 921 } |
| 922 |
| 730 bool ShellUtil::RemoveChromeDesktopShortcut(BrowserDistribution* dist, | 923 bool ShellUtil::RemoveChromeDesktopShortcut(BrowserDistribution* dist, |
| 731 int shell_change, bool alternate) { | 924 int shell_change, bool alternate) { |
| 732 std::wstring shortcut_name; | 925 std::wstring shortcut_name; |
| 733 if (!ShellUtil::GetChromeShortcutName(dist, &shortcut_name, alternate)) | 926 if (!ShellUtil::GetChromeShortcutName(dist, &shortcut_name, alternate)) |
| 734 return false; | 927 return false; |
| 735 | 928 |
| 736 bool ret = true; | 929 bool ret = true; |
| 737 if (shell_change & ShellUtil::CURRENT_USER) { | 930 if (shell_change & ShellUtil::CURRENT_USER) { |
| 738 FilePath shortcut_path; | 931 FilePath shortcut_path; |
| 739 if (ShellUtil::GetDesktopPath(false, &shortcut_path)) { | 932 if (ShellUtil::GetDesktopPath(false, &shortcut_path)) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 816 chrome_exe.c_str(), // target | 1009 chrome_exe.c_str(), // target |
| 817 shortcut.c_str(), // shortcut | 1010 shortcut.c_str(), // shortcut |
| 818 chrome_path.c_str(), // working dir | 1011 chrome_path.c_str(), // working dir |
| 819 NULL, // arguments | 1012 NULL, // arguments |
| 820 description.c_str(), // description | 1013 description.c_str(), // description |
| 821 chrome_exe.c_str(), // icon file | 1014 chrome_exe.c_str(), // icon file |
| 822 icon_index, // icon index | 1015 icon_index, // icon index |
| 823 dist->GetBrowserAppId().c_str()); // app id | 1016 dist->GetBrowserAppId().c_str()); // app id |
| 824 } | 1017 } |
| 825 } | 1018 } |
| OLD | NEW |