kiosk: Management UI polish.
[chromium-blink-merge.git] / chrome_frame / test_utils.cc
blobef780468f44d4e7d156c08f7a310442e1ef0e3a1
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome_frame/test_utils.h"
7 #include <atlbase.h>
8 #include <atlwin.h>
9 #include <shellapi.h>
11 #include <algorithm>
13 #include "base/command_line.h"
14 #include "base/file_util.h"
15 #include "base/files/file_path.h"
16 #include "base/logging.h"
17 #include "base/path_service.h"
18 #include "base/process/kill.h"
19 #include "base/process/launch.h"
20 #include "base/strings/stringprintf.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/win/scoped_handle.h"
23 #include "chrome/common/chrome_paths.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chrome_frame/test/chrome_frame_test_utils.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 const wchar_t kChromeFrameDllName[] = L"npchrome_frame.dll";
29 const wchar_t kChromeLauncherExeName[] = L"chrome_launcher.exe";
30 // How long to wait for DLLs to register or unregister themselves before killing
31 // the registrar.
32 const int64 kDllRegistrationTimeoutMs = 30 * 1000;
34 base::FilePath GetChromeFrameBuildPath() {
35 base::FilePath build_path;
36 PathService::Get(chrome::DIR_APP, &build_path);
38 base::FilePath dll_path = build_path.Append(kChromeFrameDllName);
40 if (!base::PathExists(dll_path)) {
41 // Well, dang.. try looking in the current directory.
42 dll_path = build_path.Append(kChromeFrameDllName);
45 if (!base::PathExists(dll_path)) {
46 // No luck, return something empty.
47 dll_path = base::FilePath();
50 return dll_path;
53 const wchar_t ScopedChromeFrameRegistrar::kCallRegistrationEntrypointSwitch[] =
54 L"--call-registration-entrypoint";
56 bool ScopedChromeFrameRegistrar::register_chrome_path_provider_ = false;
58 // static
59 void ScopedChromeFrameRegistrar::RegisterDefaults() {
60 if (!register_chrome_path_provider_) {
61 chrome::RegisterPathProvider();
62 register_chrome_path_provider_ = true;
66 // Registers or unregisters the DLL at |path| by calling out to the current
67 // executable with --call-registration-entrypoint. Loading the DLL into the
68 // test process is problematic for component=shared_library builds since
69 // singletons in base.dll aren't designed to handle multiple initialization.
70 // Use of rundll32.exe is problematic since it does not return useful error
71 // information.
72 // static
73 void ScopedChromeFrameRegistrar::DoRegistration(
74 const string16& path,
75 RegistrationType registration_type,
76 RegistrationOperation registration_operation) {
77 static const char* const kEntrypoints[] = {
78 "DllRegisterServer",
79 "DllUnregisterServer",
80 "DllRegisterUserServer",
81 "DllUnregisterUserServer",
84 DCHECK(!path.empty());
85 DCHECK(registration_type == PER_USER || registration_type == SYSTEM_LEVEL);
86 DCHECK(registration_operation == REGISTER ||
87 registration_operation == UNREGISTER);
89 int entrypoint_index = 0;
90 base::LaunchOptions launch_options;
91 base::ProcessHandle process_handle = INVALID_HANDLE_VALUE;
92 int exit_code = -1;
94 if (registration_type == PER_USER)
95 entrypoint_index += 2;
96 if (registration_operation == UNREGISTER)
97 entrypoint_index += 1;
98 string16 registration_command(ASCIIToUTF16("\""));
99 registration_command +=
100 CommandLine::ForCurrentProcess()->GetProgram().value();
101 registration_command += ASCIIToUTF16("\" ");
102 registration_command += kCallRegistrationEntrypointSwitch;
103 registration_command += ASCIIToUTF16(" \"");
104 registration_command += path;
105 registration_command += ASCIIToUTF16("\" ");
106 registration_command += ASCIIToUTF16(kEntrypoints[entrypoint_index]);
107 launch_options.wait = true;
108 if (!base::LaunchProcess(registration_command, launch_options,
109 &process_handle)) {
110 PLOG(FATAL)
111 << "Failed to register or unregister DLL with command: "
112 << registration_command;
113 } else {
114 base::win::ScopedHandle rundll32(process_handle);
115 if (!base::WaitForExitCodeWithTimeout(
116 process_handle, &exit_code,
117 base::TimeDelta::FromMilliseconds(kDllRegistrationTimeoutMs))) {
118 LOG(ERROR) << "Timeout waiting to register or unregister DLL with "
119 "command: " << registration_command;
120 base::KillProcess(process_handle, 0, false);
121 NOTREACHED() << "Aborting test due to registration failure.";
124 if (exit_code != 0) {
125 if (registration_operation == REGISTER) {
126 LOG(ERROR)
127 << "DLL registration failed (exit code: 0x" << std::hex << exit_code
128 << ", command: " << registration_command
129 << "). Make sure you are running as Admin.";
130 ::ExitProcess(1);
131 } else {
132 LOG(WARNING)
133 << "DLL unregistration failed (exit code: 0x" << std::hex << exit_code
134 << ", command: " << registration_command << ").";
139 // static
140 void ScopedChromeFrameRegistrar::RegisterAtPath(
141 const std::wstring& path, RegistrationType registration_type) {
142 DoRegistration(path, registration_type, REGISTER);
145 // static
146 void ScopedChromeFrameRegistrar::UnregisterAtPath(
147 const std::wstring& path, RegistrationType registration_type) {
148 DoRegistration(path, registration_type, UNREGISTER);
151 base::FilePath ScopedChromeFrameRegistrar::GetReferenceChromeFrameDllPath() {
152 base::FilePath reference_build_dir;
153 PathService::Get(chrome::DIR_APP, &reference_build_dir);
155 reference_build_dir = reference_build_dir.DirName();
156 reference_build_dir = reference_build_dir.DirName();
158 reference_build_dir = reference_build_dir.AppendASCII("chrome_frame");
159 reference_build_dir = reference_build_dir.AppendASCII("tools");
160 reference_build_dir = reference_build_dir.AppendASCII("test");
161 reference_build_dir = reference_build_dir.AppendASCII("reference_build");
162 reference_build_dir = reference_build_dir.AppendASCII("chrome");
163 reference_build_dir = reference_build_dir.AppendASCII("servers");
164 reference_build_dir = reference_build_dir.Append(kChromeFrameDllName);
165 return reference_build_dir;
168 // static
169 void ScopedChromeFrameRegistrar::RegisterAndExitProcessIfDirected() {
170 // This method is invoked before any Chromium helpers have been initialized.
171 // Take pains to use only Win32 and CRT functions.
172 int argc = 0;
173 const wchar_t* const* argv = ::CommandLineToArgvW(::GetCommandLine(), &argc);
174 if (argc < 2 || ::lstrcmp(argv[1], kCallRegistrationEntrypointSwitch) != 0)
175 return;
176 if (argc != 4) {
177 printf("Usage: %S %S <path to dll> <entrypoint>\n", argv[0],
178 kCallRegistrationEntrypointSwitch);
179 return;
182 // The only way to leave from here on down is ExitProcess.
183 const wchar_t* dll_path = argv[2];
184 const wchar_t* wide_entrypoint = argv[3];
185 char entrypoint[256];
186 HRESULT exit_code = 0;
187 int entrypoint_len = lstrlen(wide_entrypoint);
188 if (entrypoint_len <= 0 || entrypoint_len >= arraysize(entrypoint)) {
189 exit_code = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND);
190 } else {
191 // Convert wide to narrow. Since the entrypoint must be a narrow string
192 // anyway, it is safe to truncate each character like this.
193 std::copy(wide_entrypoint, wide_entrypoint + entrypoint_len + 1,
194 &entrypoint[0]);
195 HMODULE dll_module = ::LoadLibrary(dll_path);
196 if (dll_module == NULL) {
197 exit_code = HRESULT_FROM_WIN32(::GetLastError());
198 } else {
199 typedef HRESULT (STDAPICALLTYPE *RegisterFp)();
200 RegisterFp register_func =
201 reinterpret_cast<RegisterFp>(::GetProcAddress(dll_module,
202 entrypoint));
203 if (register_func == NULL) {
204 exit_code = HRESULT_FROM_WIN32(::GetLastError());
205 } else {
206 exit_code = register_func();
208 ::FreeLibrary(dll_module);
212 ::ExitProcess(exit_code);
215 // Non-statics
217 ScopedChromeFrameRegistrar::ScopedChromeFrameRegistrar(
218 const std::wstring& path, RegistrationType registration_type)
219 : registration_type_(registration_type) {
220 if (!register_chrome_path_provider_) {
221 // Register paths needed by the ScopedChromeFrameRegistrar.
222 chrome::RegisterPathProvider();
223 register_chrome_path_provider_ = true;
225 original_dll_path_ = path;
226 RegisterChromeFrameAtPath(original_dll_path_);
229 ScopedChromeFrameRegistrar::ScopedChromeFrameRegistrar(
230 RegistrationType registration_type)
231 : registration_type_(registration_type) {
232 if (!register_chrome_path_provider_) {
233 // Register paths needed by the ScopedChromeFrameRegistrar.
234 chrome::RegisterPathProvider();
235 register_chrome_path_provider_ = true;
237 original_dll_path_ = GetChromeFrameBuildPath().value();
238 RegisterChromeFrameAtPath(original_dll_path_);
241 ScopedChromeFrameRegistrar::~ScopedChromeFrameRegistrar() {
242 if (base::FilePath(original_dll_path_) !=
243 base::FilePath(new_chrome_frame_dll_path_)) {
244 RegisterChromeFrameAtPath(original_dll_path_);
245 } else if (registration_type_ == PER_USER) {
246 UnregisterAtPath(new_chrome_frame_dll_path_, registration_type_);
247 HWND chrome_frame_helper_window =
248 FindWindow(L"ChromeFrameHelperWindowClass", NULL);
249 if (IsWindow(chrome_frame_helper_window)) {
250 PostMessage(chrome_frame_helper_window, WM_CLOSE, 0, 0);
251 } else {
252 base::KillProcesses(L"chrome_frame_helper.exe", 0, NULL);
257 void ScopedChromeFrameRegistrar::RegisterChromeFrameAtPath(
258 const std::wstring& path) {
259 RegisterAtPath(path, registration_type_);
260 new_chrome_frame_dll_path_ = path;
263 void ScopedChromeFrameRegistrar::RegisterReferenceChromeFrameBuild() {
264 RegisterChromeFrameAtPath(GetReferenceChromeFrameDllPath().value());
267 std::wstring ScopedChromeFrameRegistrar::GetChromeFrameDllPath() const {
268 return new_chrome_frame_dll_path_;
271 bool IsWorkstationLocked() {
272 bool is_locked = true;
273 HDESK input_desk = ::OpenInputDesktop(0, 0, GENERIC_READ);
274 if (input_desk) {
275 wchar_t name[256] = {0};
276 DWORD needed = 0;
277 if (::GetUserObjectInformation(input_desk,
278 UOI_NAME,
279 name,
280 sizeof(name),
281 &needed)) {
282 is_locked = lstrcmpi(name, L"default") != 0;
284 ::CloseDesktop(input_desk);
286 return is_locked;