Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: chrome/installer/util/shell_util.cc

Issue 6961013: Allow chrome to become the os default handler for arbitrary protocols on mac/win. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More changes for comments; fix for a bug introduced with DefaultWebClientWorker refactoring Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698