OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 #include "win8/test/metro_registration_helper.h" | 5 #include "win8/test/metro_registration_helper.h" |
6 | 6 |
| 7 #include <shlobj.h> |
| 8 |
| 9 #include <vector> |
| 10 |
7 #include "base/command_line.h" | 11 #include "base/command_line.h" |
8 #include "base/file_util.h" | 12 #include "base/file_util.h" |
9 #include "base/files/file_path.h" | 13 #include "base/files/file_path.h" |
10 #include "base/logging.h" | 14 #include "base/logging.h" |
11 #include "base/path_service.h" | 15 #include "base/path_service.h" |
12 #include "base/process.h" | 16 #include "base/process.h" |
13 #include "base/process_util.h" | 17 #include "base/process_util.h" |
| 18 #include "base/string16.h" |
| 19 #include "base/win/scoped_co_mem.h" |
| 20 #include "base/win/scoped_comptr.h" |
14 #include "base/win/scoped_handle.h" | 21 #include "base/win/scoped_handle.h" |
| 22 #include "win8/test/open_with_dialog_controller.h" |
15 #include "win8/test/test_registrar_constants.h" | 23 #include "win8/test/test_registrar_constants.h" |
16 | 24 |
17 namespace { | 25 namespace { |
18 | 26 |
19 const int kRegistrationTimeoutSeconds = 30; | 27 const int kRegistrationTimeoutSeconds = 30; |
20 | 28 |
21 // Copied from util_constants.cc to avoid taking a dependency on installer_util. | 29 // Copied from util_constants.cc to avoid taking a dependency on installer_util. |
22 const wchar_t kChromeExe[] = L"chrome.exe"; | 30 const wchar_t kChromeExe[] = L"chrome.exe"; |
23 const wchar_t kRegistrar[] = L"test_registrar.exe"; | 31 const wchar_t kRegistrar[] = L"test_registrar.exe"; |
24 | 32 |
25 } | 33 // Registers chrome.exe as a potential Win8 default browser. It will then show |
26 | 34 // up in the default browser selection dialog as kDefaultTestExeName. Intended |
27 namespace win8 { | 35 // to be used by a test binary in the build output directory and assumes the |
28 | 36 // presence of test_registrar.exe, a viewer process, and all needed DLLs in the |
29 bool RegisterTestDefaultBrowser(const string16& app_user_model_id, | 37 // same directory as the calling module. |
30 const string16& viewer_process_name) { | 38 bool RegisterTestDefaultBrowser() { |
31 base::FilePath dir; | 39 base::FilePath dir; |
32 if (!PathService::Get(base::DIR_EXE, &dir)) | 40 if (!PathService::Get(base::DIR_EXE, &dir)) |
33 return false; | 41 return false; |
34 | 42 |
35 base::FilePath chrome_exe(dir.Append(kChromeExe)); | 43 base::FilePath chrome_exe(dir.Append(kChromeExe)); |
36 base::FilePath registrar(dir.Append(kRegistrar)); | 44 base::FilePath registrar(dir.Append(kRegistrar)); |
37 | 45 |
38 if (!file_util::PathExists(chrome_exe) || !file_util::PathExists(registrar)) { | 46 if (!file_util::PathExists(chrome_exe) || !file_util::PathExists(registrar)) { |
39 LOG(ERROR) << "Could not locate " << kChromeExe << " or " << kRegistrar; | 47 LOG(ERROR) << "Could not locate " << kChromeExe << " or " << kRegistrar; |
40 return false; | 48 return false; |
41 } | 49 } |
42 | 50 |
43 // Perform the registration by invoking test_registrar.exe with the | 51 // Perform the registration by invoking test_registrar.exe. |
44 // necessary flags: | |
45 // test_registrar.exe /RegServer --appid=<appid> --exe-name=<name> | |
46 CommandLine register_command(registrar); | 52 CommandLine register_command(registrar); |
47 register_command.AppendArg("/RegServer"); | 53 register_command.AppendArg("/RegServer"); |
48 register_command.AppendSwitchNative(win8::test::kTestAppUserModelId, | |
49 app_user_model_id); | |
50 register_command.AppendSwitchNative(win8::test::kTestExeName, | |
51 viewer_process_name); | |
52 | 54 |
53 base::win::ScopedHandle register_handle; | 55 base::win::ScopedHandle register_handle; |
54 if (base::LaunchProcess(register_command, base::LaunchOptions(), | 56 if (base::LaunchProcess(register_command, base::LaunchOptions(), |
55 register_handle.Receive())) { | 57 register_handle.Receive())) { |
56 int ret = 0; | 58 int ret = 0; |
57 if (base::WaitForExitCodeWithTimeout( | 59 if (base::WaitForExitCodeWithTimeout( |
58 register_handle, &ret, | 60 register_handle, &ret, |
59 base::TimeDelta::FromSeconds(kRegistrationTimeoutSeconds))) { | 61 base::TimeDelta::FromSeconds(kRegistrationTimeoutSeconds))) { |
60 if (ret == 0) { | 62 if (ret == 0) { |
61 return true; | 63 return true; |
62 } else { | 64 } else { |
63 LOG(ERROR) << "Win8 registration using " | 65 LOG(ERROR) << "Win8 registration using " |
64 << register_command.GetCommandLineString() | 66 << register_command.GetCommandLineString() |
65 << " failed with error code " << ret; | 67 << " failed with error code " << ret; |
66 } | 68 } |
67 } else { | 69 } else { |
68 LOG(ERROR) << "Win8 registration using " | 70 LOG(ERROR) << "Win8 registration using " |
69 << register_command.GetCommandLineString() << " timed out."; | 71 << register_command.GetCommandLineString() << " timed out."; |
70 } | 72 } |
71 } | 73 } |
72 | 74 |
73 PLOG(ERROR) << "Failed to launch Win8 registration utility using " | 75 PLOG(ERROR) << "Failed to launch Win8 registration utility using " |
74 << register_command.GetCommandLineString(); | 76 << register_command.GetCommandLineString(); |
75 return false; | 77 return false; |
76 } | 78 } |
77 | 79 |
| 80 // Returns true if the test viewer's progid is the default handler for |
| 81 // |protocol|. |
| 82 bool IsTestDefaultForProtocol(const wchar_t* protocol) { |
| 83 base::win::ScopedComPtr<IApplicationAssociationRegistration> registration; |
| 84 HRESULT hr = registration.CreateInstance( |
| 85 CLSID_ApplicationAssociationRegistration, NULL, CLSCTX_INPROC); |
| 86 if (FAILED(hr)) { |
| 87 LOG(ERROR) << std::hex << hr; |
| 88 return false; |
| 89 } |
| 90 |
| 91 base::win::ScopedCoMem<wchar_t> current_app; |
| 92 hr = registration->QueryCurrentDefault(protocol, AT_URLPROTOCOL, |
| 93 AL_EFFECTIVE, ¤t_app); |
| 94 if (FAILED(hr)) { |
| 95 LOG(ERROR) << std::hex << hr; |
| 96 return false; |
| 97 } |
| 98 |
| 99 return string16(win8::test::kDefaultTestProgId).compare(current_app) == 0; |
| 100 } |
| 101 |
| 102 } // namespace |
| 103 |
| 104 namespace win8 { |
| 105 |
| 106 bool MakeTestDefaultBrowserSynchronously() { |
| 107 static const wchar_t kDefaultBrowserProtocol[] = L"http"; |
| 108 |
| 109 if (!RegisterTestDefaultBrowser()) |
| 110 return false; |
| 111 |
| 112 // Make sure the registration changes have been acknowledged by the shell |
| 113 // before querying for the current default. |
| 114 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSH, NULL, NULL); |
| 115 |
| 116 // OpenWithDialogController will fail if the Test Runner is already default |
| 117 // since it will not show up verbatim in the dialog (e.g., in EN-US, it will |
| 118 // be prefixed by "Keep using "). |
| 119 if (IsTestDefaultForProtocol(kDefaultBrowserProtocol)) |
| 120 return true; |
| 121 |
| 122 std::vector<base::string16> choices; |
| 123 OpenWithDialogController controller; |
| 124 HRESULT hr = controller.RunSynchronously( |
| 125 NULL, kDefaultBrowserProtocol, win8::test::kDefaultTestExeName, &choices); |
| 126 LOG_IF(ERROR, FAILED(hr)) << std::hex << hr; |
| 127 DCHECK(IsTestDefaultForProtocol(kDefaultBrowserProtocol)); |
| 128 return SUCCEEDED(hr); |
| 129 } |
| 130 |
78 } // namespace win8 | 131 } // namespace win8 |
OLD | NEW |