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" |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
63 entries->push_front(new RegistryEntry( | 63 entries->push_front(new RegistryEntry( |
64 chrome_html_prog_id, ShellUtil::kRegUrlProtocol, L"")); | 64 chrome_html_prog_id, ShellUtil::kRegUrlProtocol, L"")); |
65 entries->push_front(new RegistryEntry( | 65 entries->push_front(new RegistryEntry( |
66 chrome_html_prog_id + ShellUtil::kRegDefaultIcon, icon_path)); | 66 chrome_html_prog_id + ShellUtil::kRegDefaultIcon, icon_path)); |
67 entries->push_front(new RegistryEntry( | 67 entries->push_front(new RegistryEntry( |
68 chrome_html_prog_id + ShellUtil::kRegShellOpen, open_cmd)); | 68 chrome_html_prog_id + ShellUtil::kRegShellOpen, open_cmd)); |
69 | 69 |
70 return true; | 70 return true; |
71 } | 71 } |
72 | 72 |
73 // This method returns a list of the system level registry entries | |
74 // needed to declare a capability of handling a protocol. | |
75 static bool GetProtocolCapabilityEntries(BrowserDistribution* dist, | |
76 const std::wstring& chrome_exe, | |
77 const std::wstring& suffix, | |
78 const std::wstring& protocol, | |
79 std::list<RegistryEntry*>* entries) { | |
80 std::wstring app_name = dist->GetApplicationName() + suffix; | |
81 std::wstring start_menu_entry(ShellUtil::kRegStartMenuInternet); | |
82 start_menu_entry.append(L"\\" + app_name); | |
83 | |
84 std::wstring capabilities(start_menu_entry + L"\\Capabilities"); | |
85 | |
86 std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId); | |
87 html_prog_id.append(suffix); | |
88 entries->push_front(new RegistryEntry(capabilities + L"\\URLAssociations", | |
89 protocol, html_prog_id)); | |
90 return true; | |
91 } | |
92 | |
93 | |
73 // This method returns a list of all the system level registry entries that | 94 // This method returns a list of all the system level registry entries that |
74 // are needed to register Chromium on the machine. | 95 // are needed to register Chromium on the machine. |
75 static bool GetSystemEntries(BrowserDistribution* dist, | 96 static bool GetSystemEntries(BrowserDistribution* dist, |
76 const std::wstring& chrome_exe, | 97 const std::wstring& chrome_exe, |
77 const std::wstring& suffix, | 98 const std::wstring& suffix, |
78 std::list<RegistryEntry*>* entries) { | 99 std::list<RegistryEntry*>* entries) { |
79 std::wstring icon_path = ShellUtil::GetChromeIcon(dist, chrome_exe); | 100 std::wstring icon_path = ShellUtil::GetChromeIcon(dist, chrome_exe); |
80 std::wstring quoted_exe_path = L"\"" + chrome_exe + L"\""; | 101 std::wstring quoted_exe_path = L"\"" + chrome_exe + L"\""; |
81 | 102 |
82 std::wstring app_name = dist->GetApplicationName() + suffix; | 103 std::wstring app_name = dist->GetApplicationName() + suffix; |
(...skipping 29 matching lines...) Expand all Loading... | |
112 entries->push_front(new RegistryEntry(capabilities + L"\\StartMenu", | 133 entries->push_front(new RegistryEntry(capabilities + L"\\StartMenu", |
113 L"StartMenuInternet", app_name)); | 134 L"StartMenuInternet", app_name)); |
114 | 135 |
115 std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId); | 136 std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId); |
116 html_prog_id.append(suffix); | 137 html_prog_id.append(suffix); |
117 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { | 138 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { |
118 entries->push_front(new RegistryEntry( | 139 entries->push_front(new RegistryEntry( |
119 capabilities + L"\\FileAssociations", | 140 capabilities + L"\\FileAssociations", |
120 ShellUtil::kFileAssociations[i], html_prog_id)); | 141 ShellUtil::kFileAssociations[i], html_prog_id)); |
121 } | 142 } |
122 for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) { | 143 for (int i = 0; ShellUtil::kPotentialProtocolAssociations[i] != NULL; |
144 i++) { | |
123 entries->push_front(new RegistryEntry( | 145 entries->push_front(new RegistryEntry( |
124 capabilities + L"\\URLAssociations", | 146 capabilities + L"\\URLAssociations", |
125 ShellUtil::kProtocolAssociations[i], html_prog_id)); | 147 ShellUtil::kPotentialProtocolAssociations[i], html_prog_id)); |
126 } | 148 } |
127 | 149 |
128 FilePath chrome_path(chrome_exe); | 150 FilePath chrome_path(chrome_exe); |
129 std::wstring app_path_key(ShellUtil::kAppPathsRegistryKey); | 151 std::wstring app_path_key(ShellUtil::kAppPathsRegistryKey); |
130 file_util::AppendToPath(&app_path_key, chrome_path.BaseName().value()); | 152 file_util::AppendToPath(&app_path_key, chrome_path.BaseName().value()); |
131 entries->push_front(new RegistryEntry(app_path_key, chrome_exe)); | 153 entries->push_front(new RegistryEntry(app_path_key, chrome_exe)); |
132 entries->push_front(new RegistryEntry(app_path_key, | 154 entries->push_front(new RegistryEntry(app_path_key, |
133 ShellUtil::kAppPathsRegistryPathName, chrome_path.DirName().value())); | 155 ShellUtil::kAppPathsRegistryPathName, chrome_path.DirName().value())); |
134 | 156 |
135 // TODO: add chrome to open with list (Bug 16726). | 157 // TODO: add chrome to open with list (Bug 16726). |
136 return true; | 158 return true; |
137 } | 159 } |
138 | 160 |
139 // This method returns a list of all the user level registry entries that | 161 // This method returns a list of all the user level registry entries that |
162 // are needed to make Chromium the default handler for a protocol. | |
163 static bool GetUserProtocolEntries(BrowserDistribution* dist, | |
164 const std::wstring& chrome_exe, | |
165 const std::wstring& suffix, | |
166 const std::wstring& protocol, | |
167 const std::wstring& chrome_icon, | |
168 const std::wstring& chrome_open, | |
169 std::list<RegistryEntry*>* entries) { | |
xiyuan
2011/05/24 17:55:20
nit: please fix args alignment
benwells
2011/05/25 08:07:19
Done.
| |
170 // Protocols associations. | |
171 std::wstring url_key(ShellUtil::kRegClasses); | |
172 file_util::AppendToPath(&url_key, protocol); | |
173 | |
174 // This registry value tells Windows that this 'class' is a URL scheme | |
175 // so IE, explorer and other apps will route it to our handler. | |
176 // <root hkey>\Software\Classes\<protocol>\URL Protocol | |
177 entries->push_front(new RegistryEntry(url_key, | |
178 ShellUtil::kRegURLProtocol, L"")); | |
179 | |
180 // <root hkey>\Software\Classes\<protocol>\DefaultIcon | |
181 std::wstring icon_key = url_key + ShellUtil::kRegDefaultIcon; | |
182 entries->push_front(new RegistryEntry(icon_key, chrome_icon)); | |
183 | |
184 // <root hkey>\Software\Classes\<protocol>\shell\open\command | |
185 std::wstring shell_key = url_key + ShellUtil::kRegShellOpen; | |
186 entries->push_front(new RegistryEntry(shell_key, chrome_open)); | |
187 | |
188 // <root hkey>\Software\Classes\<protocol>\shell\open\ddeexec | |
189 std::wstring dde_key = url_key + L"\\shell\\open\\ddeexec"; | |
190 entries->push_front(new RegistryEntry(dde_key, L"")); | |
191 | |
192 // <root hkey>\Software\Classes\<protocol>\shell\@ | |
193 std::wstring protocol_shell_key = url_key + ShellUtil::kRegShellPath; | |
194 entries->push_front(new RegistryEntry(protocol_shell_key, L"open")); | |
195 | |
196 return true; | |
197 } | |
198 | |
199 // This method returns a list of all the user level registry entries that | |
140 // are needed to make Chromium default browser. | 200 // are needed to make Chromium default browser. |
141 static bool GetUserEntries(BrowserDistribution* dist, | 201 static bool GetUserEntries(BrowserDistribution* dist, |
142 const std::wstring& chrome_exe, | 202 const std::wstring& chrome_exe, |
143 const std::wstring& suffix, | 203 const std::wstring& suffix, |
144 std::list<RegistryEntry*>* entries) { | 204 std::list<RegistryEntry*>* entries) { |
145 // File extension associations. | 205 // File extension associations. |
146 std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId); | 206 std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId); |
147 html_prog_id.append(suffix); | 207 html_prog_id.append(suffix); |
148 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { | 208 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { |
149 std::wstring ext_key(ShellUtil::kRegClasses); | 209 std::wstring ext_key(ShellUtil::kRegClasses); |
150 file_util::AppendToPath(&ext_key, ShellUtil::kFileAssociations[i]); | 210 file_util::AppendToPath(&ext_key, ShellUtil::kFileAssociations[i]); |
151 entries->push_front(new RegistryEntry(ext_key, html_prog_id)); | 211 entries->push_front(new RegistryEntry(ext_key, html_prog_id)); |
152 } | 212 } |
153 | 213 |
154 // Protocols associations. | 214 // Protocols associations. |
155 std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe); | 215 std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe); |
156 std::wstring chrome_icon = ShellUtil::GetChromeIcon(dist, chrome_exe); | 216 std::wstring chrome_icon = ShellUtil::GetChromeIcon(dist, chrome_exe); |
157 for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) { | 217 for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) { |
158 std::wstring url_key(ShellUtil::kRegClasses); | 218 GetUserProtocolEntries(dist, chrome_exe, suffix, |
159 file_util::AppendToPath(&url_key, ShellUtil::kProtocolAssociations[i]); | 219 ShellUtil::kBrowserProtocolAssociations[i], |
160 | 220 chrome_icon, chrome_open, entries); |
xiyuan
2011/05/24 17:55:20
nit: should use either 4 spaces indentation or ali
benwells
2011/05/25 08:07:19
Done.
| |
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 } | 221 } |
177 | 222 |
178 // start->Internet shortcut. | 223 // start->Internet shortcut. |
179 std::wstring start_menu(ShellUtil::kRegStartMenuInternet); | 224 std::wstring start_menu(ShellUtil::kRegStartMenuInternet); |
180 std::wstring app_name = dist->GetApplicationName() + suffix; | 225 std::wstring app_name = dist->GetApplicationName() + suffix; |
181 entries->push_front(new RegistryEntry(start_menu, app_name)); | 226 entries->push_front(new RegistryEntry(start_menu, app_name)); |
182 return true; | 227 return true; |
183 } | 228 } |
184 | 229 |
185 // Generate work_item tasks required to create current registry entry and | 230 // 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); | 335 RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries); |
291 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin(); | 336 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin(); |
292 itr != entries.end() && registered; ++itr) { | 337 itr != entries.end() && registered; ++itr) { |
293 // We do not need registered = registered && ... since the loop condition | 338 // We do not need registered = registered && ... since the loop condition |
294 // is set to exit early. | 339 // is set to exit early. |
295 registered = (*itr)->ExistsInHKLM(); | 340 registered = (*itr)->ExistsInHKLM(); |
296 } | 341 } |
297 return registered; | 342 return registered; |
298 } | 343 } |
299 | 344 |
345 // This method checks if Chrome is already registered on the local machine | |
346 // for the requested protocol. It just checks the one value required for this. | |
347 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, | |
348 const std::wstring& chrome_exe, | |
349 const std::wstring& suffix, | |
350 const std::wstring& protocol) { | |
351 bool registered = true; | |
352 std::list<RegistryEntry*> entries; | |
353 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries); | |
354 RegistryEntry::GetProtocolCapabilityEntries(dist, chrome_exe, suffix, | |
355 protocol, &entries); | |
356 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin(); | |
357 itr != entries.end() && registered; ++itr) { | |
358 // We do not need registered = registered && ... since the loop condition | |
359 // is set to exit early. | |
360 registered = (*itr)->ExistsInHKLM(); | |
361 } | |
362 return registered; | |
363 } | |
364 | |
300 // This method registers Chrome on Vista by launching an elevated setup.exe. | 365 // 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 | 366 // 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 | 367 // accepts it the new process will make the necessary changes and return SUCCESS |
303 // that we capture and return. | 368 // that we capture and return. |
369 // If protocol is non-empty we will also register Chrome as being capable of | |
370 // handling the protocol. | |
304 bool ElevateAndRegisterChrome(BrowserDistribution* dist, | 371 bool ElevateAndRegisterChrome(BrowserDistribution* dist, |
305 const std::wstring& chrome_exe, | 372 const std::wstring& chrome_exe, |
306 const std::wstring& suffix) { | 373 const std::wstring& suffix, |
374 const std::wstring& protocol) { | |
307 FilePath exe_path = | 375 FilePath exe_path = |
308 FilePath::FromWStringHack(chrome_exe).DirName() | 376 FilePath::FromWStringHack(chrome_exe).DirName() |
309 .Append(installer::kSetupExe); | 377 .Append(installer::kSetupExe); |
310 if (!file_util::PathExists(exe_path)) { | 378 if (!file_util::PathExists(exe_path)) { |
311 HKEY reg_root = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? | 379 HKEY reg_root = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ? |
312 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; | 380 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; |
313 RegKey key(reg_root, dist->GetUninstallRegPath().c_str(), KEY_READ); | 381 RegKey key(reg_root, dist->GetUninstallRegPath().c_str(), KEY_READ); |
314 std::wstring uninstall_string; | 382 std::wstring uninstall_string; |
315 key.ReadValue(installer::kUninstallStringField, &uninstall_string); | 383 key.ReadValue(installer::kUninstallStringField, &uninstall_string); |
316 CommandLine command_line = CommandLine::FromString(uninstall_string); | 384 CommandLine command_line = CommandLine::FromString(uninstall_string); |
317 exe_path = command_line.GetProgram(); | 385 exe_path = command_line.GetProgram(); |
318 } | 386 } |
319 | 387 |
320 if (file_util::PathExists(exe_path)) { | 388 if (file_util::PathExists(exe_path)) { |
321 CommandLine cmd(exe_path); | 389 CommandLine cmd(exe_path); |
322 cmd.AppendSwitchNative(installer::switches::kRegisterChromeBrowser, | 390 cmd.AppendSwitchNative(installer::switches::kRegisterChromeBrowser, |
323 chrome_exe); | 391 chrome_exe); |
324 if (!suffix.empty()) { | 392 if (!suffix.empty()) { |
325 cmd.AppendSwitchNative( | 393 cmd.AppendSwitchNative( |
326 installer::switches::kRegisterChromeBrowserSuffix, suffix); | 394 installer::switches::kRegisterChromeBrowserSuffix, suffix); |
327 } | 395 } |
328 | 396 |
329 CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); | 397 CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); |
330 if (browser_command_line.HasSwitch(switches::kChromeFrame)) { | 398 if (browser_command_line.HasSwitch(switches::kChromeFrame)) { |
331 cmd.AppendSwitch(installer::switches::kChromeFrame); | 399 cmd.AppendSwitch(installer::switches::kChromeFrame); |
332 } | 400 } |
333 | 401 |
402 if (!protocol.empty()) { | |
403 cmd.AppendSwitchNative( | |
404 installer::switches::kRegisterURLProtocol, protocol); | |
405 } | |
406 | |
334 DWORD ret_val = 0; | 407 DWORD ret_val = 0; |
335 InstallUtil::ExecuteExeAsAdmin(cmd, &ret_val); | 408 InstallUtil::ExecuteExeAsAdmin(cmd, &ret_val); |
336 if (ret_val == 0) | 409 if (ret_val == 0) |
337 return true; | 410 return true; |
338 } | 411 } |
339 return false; | 412 return false; |
340 } | 413 } |
341 | 414 |
342 // This method tries to figure out if another user has already registered her | 415 // 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 | 416 // 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; | 462 return false; |
390 else | 463 else |
391 one_mismatch = true; | 464 one_mismatch = true; |
392 } | 465 } |
393 } | 466 } |
394 return true; | 467 return true; |
395 } | 468 } |
396 | 469 |
397 } // namespace | 470 } // namespace |
398 | 471 |
399 | 472 const wchar_t* ShellUtil::kRegURLProtocol = L"URL Protocol"; |
grt (UTC plus 2)
2011/05/24 20:27:53
Remove this and use kRegUrlProtocol (defined below
benwells
2011/05/25 08:07:19
Done.
| |
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 IApplicationAssociationRegistration* pAAR; |
xiyuan
2011/05/24 17:55:20
nit: please fix indentation
xiyuan
2011/05/24 17:55:20
suggest to use ScopedComPtr
benwells
2011/05/25 08:07:19
Done.
benwells
2011/05/25 08:07:19
Done.
| |
640 HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration, | 715 HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration, |
641 NULL, CLSCTX_INPROC, __uuidof(IApplicationAssociationRegistration), | 716 NULL, CLSCTX_INPROC, __uuidof(IApplicationAssociationRegistration), |
642 (void**)&pAAR); | 717 (void**)&pAAR); |
643 if (SUCCEEDED(hr)) { | 718 if (SUCCEEDED(hr)) { |
644 std::wstring app_name = dist->GetApplicationName(); | 719 std::wstring app_name = dist->GetApplicationName(); |
645 std::wstring suffix; | 720 std::wstring suffix; |
646 if (ShellUtil::GetUserSpecificDefaultBrowserSuffix(dist, &suffix)) | 721 if (ShellUtil::GetUserSpecificDefaultBrowserSuffix(dist, &suffix)) |
647 app_name += suffix; | 722 app_name += suffix; |
648 | 723 |
649 hr = pAAR->SetAppAsDefaultAll(app_name.c_str()); | 724 for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) { |
725 if (SUCCEEDED(hr)) { | |
xiyuan
2011/05/24 17:55:20
Think you should break out of loop when !SUCCEEDED
benwells
2011/05/25 08:07:19
Done.
grt (UTC plus 2)
2011/05/25 14:35:45
I wonder about this: why not make registration a b
benwells
2011/05/26 00:23:04
I have left the return value as is as it is consis
| |
726 hr = pAAR->SetAppAsDefault(app_name.c_str(), | |
727 ShellUtil::kBrowserProtocolAssociations[i], | |
728 AT_URLPROTOCOL); | |
729 } | |
730 } | |
731 | |
732 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { | |
733 if (SUCCEEDED(hr)) { | |
xiyuan
2011/05/24 17:55:20
similarly here, need to get out of loop when faile
benwells
2011/05/25 08:07:19
Done.
| |
734 hr = pAAR->SetAppAsDefault(app_name.c_str(), | |
735 ShellUtil::kFileAssociations[i], AT_FILEEXTENSION); | |
736 } | |
737 } | |
650 pAAR->Release(); | 738 pAAR->Release(); |
651 } | 739 } |
652 if (!SUCCEEDED(hr)) { | 740 if (!SUCCEEDED(hr)) { |
653 ret = false; | 741 ret = false; |
654 LOG(ERROR) << "Could not make Chrome default browser."; | 742 LOG(ERROR) << "Could not make Chrome default browser."; |
grt (UTC plus 2)
2011/05/24 20:27:53
How about logging hr so that we get some idea of w
benwells
2011/05/25 08:07:19
Done.
| |
655 } | 743 } |
656 } | 744 } |
657 | 745 |
658 // Now use the old way to associate Chrome with supported protocols and file | 746 // 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 | 747 // associations. This should not be required on Vista but since some |
660 // applications still read Software\Classes\http key directly, we have to do | 748 // applications still read Software\Classes\http key directly, we have to do |
661 // this on Vista also. | 749 // this on Vista also. |
662 | 750 |
663 std::list<RegistryEntry*> entries; | 751 std::list<RegistryEntry*> entries; |
664 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries); | 752 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries); |
(...skipping 10 matching lines...) Expand all Loading... | |
675 if ((shell_change & ShellUtil::SYSTEM_LEVEL) && | 763 if ((shell_change & ShellUtil::SYSTEM_LEVEL) && |
676 !AddRegistryEntries(HKEY_LOCAL_MACHINE, entries)) | 764 !AddRegistryEntries(HKEY_LOCAL_MACHINE, entries)) |
677 ret = false; | 765 ret = false; |
678 | 766 |
679 // Send Windows notification event so that it can update icons for | 767 // Send Windows notification event so that it can update icons for |
680 // file associations. | 768 // file associations. |
681 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); | 769 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); |
682 return ret; | 770 return ret; |
683 } | 771 } |
684 | 772 |
773 bool ShellUtil::MakeChromeDefaultProtocolClient(BrowserDistribution* dist, | |
774 const std::wstring& chrome_exe, | |
775 const std::wstring& protocol) { | |
776 if (!dist->CanSetAsDefault()) | |
777 return false; | |
778 | |
779 ShellUtil::RegisterChromeForProtocol(dist, chrome_exe, L"", protocol, true); | |
780 | |
781 bool ret = true; | |
782 // First use the new "recommended" way on Vista to make Chrome default | |
783 // protocol handler. | |
784 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { | |
785 VLOG(1) << "Registering Chrome as default handler for " << protocol | |
786 << " on Vista."; | |
787 IApplicationAssociationRegistration* pAAR; | |
xiyuan
2011/05/24 17:55:20
similar to above, please fix indentation and sugge
benwells
2011/05/25 08:07:19
Done.
| |
788 HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration, | |
789 NULL, CLSCTX_INPROC, __uuidof(IApplicationAssociationRegistration), | |
790 (void**)&pAAR); | |
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 pAAR->Release(); | |
800 } | |
801 if (!SUCCEEDED(hr)) { | |
802 ret = false; | |
803 LOG(ERROR) << "Could not make Chrome default protocol client (Vista)."; | |
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 | |
xiyuan
2011/05/24 17:55:20
nit: nuke the empty line
benwells
2011/05/25 08:07:19
Done.
| |
913 } else if (elevate_if_not_admin && | |
914 base::win::GetVersion() >= base::win::VERSION_VISTA) { | |
grt (UTC plus 2)
2011/05/24 20:27:53
align with the 'e' in "(elevate" above
benwells
2011/05/25 08:07:19
Done.
| |
915 // Elevate to do the whole job | |
916 return ElevateAndRegisterChrome(dist, chrome_exe, suffix, protocol); | |
917 } else { | |
918 // we need admin rights to register our capability. If we don't | |
919 // have them and can't elevate, give up. | |
920 return false; | |
921 } | |
922 } | |
923 | |
730 bool ShellUtil::RemoveChromeDesktopShortcut(BrowserDistribution* dist, | 924 bool ShellUtil::RemoveChromeDesktopShortcut(BrowserDistribution* dist, |
731 int shell_change, bool alternate) { | 925 int shell_change, bool alternate) { |
732 std::wstring shortcut_name; | 926 std::wstring shortcut_name; |
733 if (!ShellUtil::GetChromeShortcutName(dist, &shortcut_name, alternate)) | 927 if (!ShellUtil::GetChromeShortcutName(dist, &shortcut_name, alternate)) |
734 return false; | 928 return false; |
735 | 929 |
736 bool ret = true; | 930 bool ret = true; |
737 if (shell_change & ShellUtil::CURRENT_USER) { | 931 if (shell_change & ShellUtil::CURRENT_USER) { |
738 FilePath shortcut_path; | 932 FilePath shortcut_path; |
739 if (ShellUtil::GetDesktopPath(false, &shortcut_path)) { | 933 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 | 1010 chrome_exe.c_str(), // target |
817 shortcut.c_str(), // shortcut | 1011 shortcut.c_str(), // shortcut |
818 chrome_path.c_str(), // working dir | 1012 chrome_path.c_str(), // working dir |
819 NULL, // arguments | 1013 NULL, // arguments |
820 description.c_str(), // description | 1014 description.c_str(), // description |
821 chrome_exe.c_str(), // icon file | 1015 chrome_exe.c_str(), // icon file |
822 icon_index, // icon index | 1016 icon_index, // icon index |
823 dist->GetBrowserAppId().c_str()); // app id | 1017 dist->GetBrowserAppId().c_str()); // app id |
824 } | 1018 } |
825 } | 1019 } |
OLD | NEW |