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

Side by Side Diff: chrome_frame/test/chrome_frame_test_utils.cc

Issue 218019: Initial import of the Chrome Frame codebase. Integration in chrome.gyp coming... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 3 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
« no previous file with comments | « chrome_frame/test/chrome_frame_test_utils.h ('k') | chrome_frame/test/chrome_frame_unittests.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 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.
4
5 #include "chrome_frame/test/chrome_frame_test_utils.h"
6
7 #include <atlbase.h>
8 #include <atlwin.h>
9 #include <iepmapi.h>
10
11 #include "base/registry.h" // to find IE and firefox
12 #include "base/scoped_handle.h"
13 #include "base/scoped_comptr_win.h"
14 #include "base/string_util.h"
15 #include "base/win_util.h"
16 #include "chrome/common/chrome_switches.h"
17
18 namespace chrome_frame_test {
19
20 const wchar_t kIEImageName[] = L"iexplore.exe";
21 const wchar_t kIEBrokerImageName[] = L"ieuser.exe";
22 const wchar_t kFirefoxImageName[] = L"firefox.exe";
23 const wchar_t kOperaImageName[] = L"opera.exe";
24 const wchar_t kSafariImageName[] = L"safari.exe";
25 const wchar_t kChromeImageName[] = L"chrome.exe";
26
27 bool IsTopLevelWindow(HWND window) {
28 long style = GetWindowLong(window, GWL_STYLE); // NOLINT
29 if (!(style & WS_CHILD))
30 return true;
31
32 HWND parent = GetParent(window);
33 if (!parent)
34 return true;
35
36 if (parent == GetDesktopWindow())
37 return true;
38
39 return false;
40 }
41
42 // Callback function for EnumThreadWindows.
43 BOOL CALLBACK CloseWindowsThreadCallback(HWND hwnd, LPARAM param) {
44 int& count = *reinterpret_cast<int*>(param);
45 if (IsWindowVisible(hwnd)) {
46 if (IsWindowEnabled(hwnd)) {
47 DWORD results = 0;
48 if (!::SendMessageTimeout(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0, SMTO_BLOCK,
49 10000, &results)) {
50 DLOG(WARNING) << "Window hung: " << StringPrintf(L"%08X", hwnd);
51 }
52 count++;
53 } else {
54 DLOG(WARNING) << "Skipping disabled window: "
55 << StringPrintf(L"%08X", hwnd);
56 }
57 }
58 return TRUE; // continue enumeration
59 }
60
61 // Attempts to close all non-child, visible windows on the given thread.
62 // The return value is the number of visible windows a close request was
63 // sent to.
64 int CloseVisibleTopLevelWindowsOnThread(DWORD thread_id) {
65 int window_close_attempts = 0;
66 EnumThreadWindows(thread_id, CloseWindowsThreadCallback,
67 reinterpret_cast<LPARAM>(&window_close_attempts));
68 return window_close_attempts;
69 }
70
71 // Enumerates the threads of a process and attempts to close visible non-child
72 // windows on all threads of the process.
73 // The return value is the number of visible windows a close request was
74 // sent to.
75 int CloseVisibleWindowsOnAllThreads(HANDLE process) {
76 DWORD process_id = ::GetProcessId(process);
77 if (process_id == 0) {
78 NOTREACHED();
79 return 0;
80 }
81
82 ScopedHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0));
83 if (!snapshot.IsValid()) {
84 NOTREACHED();
85 return 0;
86 }
87
88 int window_close_attempts = 0;
89 THREADENTRY32 te = { sizeof(THREADENTRY32) };
90 if (Thread32First(snapshot, &te)) {
91 do {
92 if (RTL_CONTAINS_FIELD(&te, te.dwSize, th32OwnerProcessID) &&
93 te.th32OwnerProcessID == process_id) {
94 window_close_attempts +=
95 CloseVisibleTopLevelWindowsOnThread(te.th32ThreadID);
96 }
97 te.dwSize = sizeof(te);
98 } while (Thread32Next(snapshot, &te));
99 }
100
101 return window_close_attempts;
102 }
103
104 class ForegroundHelperWindow : public CWindowImpl<ForegroundHelperWindow> {
105 public:
106 BEGIN_MSG_MAP(ForegroundHelperWindow)
107 MESSAGE_HANDLER(WM_HOTKEY, OnHotKey)
108 END_MSG_MAP()
109
110 HRESULT SetForeground(HWND window) {
111 DCHECK(::IsWindow(window));
112 if (NULL == Create(NULL, NULL, NULL, WS_POPUP))
113 return AtlHresultFromLastError();
114
115 static const int hotkey_id = 0x0000baba;
116
117 SetWindowLongPtr(GWLP_USERDATA, reinterpret_cast<ULONG_PTR>(window));
118 RegisterHotKey(m_hWnd, hotkey_id, 0, VK_F22);
119
120 MSG msg = {0};
121 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
122
123 INPUT hotkey = {0};
124 hotkey.type = INPUT_KEYBOARD;
125 hotkey.ki.wVk = VK_F22;
126 SendInput(1, &hotkey, sizeof(hotkey));
127
128 while (GetMessage(&msg, NULL, 0, 0)) {
129 TranslateMessage(&msg);
130 DispatchMessage(&msg);
131 if (WM_HOTKEY == msg.message)
132 break;
133 }
134
135 UnregisterHotKey(m_hWnd, hotkey_id);
136 DestroyWindow();
137
138 return S_OK;
139 }
140
141 LRESULT OnHotKey(UINT msg, WPARAM wp, LPARAM lp, BOOL& handled) { // NOLINT
142 HWND window = reinterpret_cast<HWND>(GetWindowLongPtr(GWLP_USERDATA));
143 SetForegroundWindow(window);
144 return 1;
145 }
146 };
147
148 bool ForceSetForegroundWindow(HWND window) {
149 if (GetForegroundWindow() == window)
150 return true;
151 ForegroundHelperWindow foreground_helper_window;
152 HRESULT hr = foreground_helper_window.SetForeground(window);
153 return SUCCEEDED(hr);
154 }
155
156 struct PidAndWindow {
157 base::ProcessId pid;
158 HWND hwnd;
159 };
160
161 BOOL CALLBACK FindWindowInProcessCallback(HWND hwnd, LPARAM param) {
162 PidAndWindow* paw = reinterpret_cast<PidAndWindow*>(param);
163 base::ProcessId pid;
164 GetWindowThreadProcessId(hwnd, &pid);
165 if (pid == paw->pid && IsWindowVisible(hwnd)) {
166 paw->hwnd = hwnd;
167 return FALSE;
168 }
169
170 return TRUE;
171 }
172
173 bool EnsureProcessInForeground(base::ProcessId process_id) {
174 HWND hwnd = GetForegroundWindow();
175 base::ProcessId current_foreground_pid = 0;
176 DWORD active_thread_id = GetWindowThreadProcessId(hwnd,
177 &current_foreground_pid);
178 if (current_foreground_pid == process_id)
179 return true;
180
181 PidAndWindow paw = { process_id };
182 EnumWindows(FindWindowInProcessCallback, reinterpret_cast<LPARAM>(&paw));
183 if (!IsWindow(paw.hwnd)) {
184 DLOG(ERROR) << "failed to find process window";
185 return false;
186 }
187
188 bool ret = ForceSetForegroundWindow(paw.hwnd);
189 DLOG_IF(ERROR, !ret) << "ForceSetForegroundWindow: " << ret;
190
191 return ret;
192 }
193
194 // Iterates through all the characters in the string and simulates
195 // keyboard input. The input goes to the currently active application.
196 bool SendString(const wchar_t* string) {
197 DCHECK(string != NULL);
198
199 INPUT input[2] = {0};
200 input[0].type = INPUT_KEYBOARD;
201 input[0].ki.dwFlags = KEYEVENTF_UNICODE; // to avoid shift, etc.
202 input[1] = input[0];
203 input[1].ki.dwFlags |= KEYEVENTF_KEYUP;
204
205 for (const wchar_t* p = string; *p; p++) {
206 input[0].ki.wScan = input[1].ki.wScan = *p;
207 SendInput(2, input, sizeof(INPUT));
208 }
209
210 return true;
211 }
212
213 void SendVirtualKey(int16 key) {
214 INPUT input = { INPUT_KEYBOARD };
215 input.ki.wVk = key;
216 SendInput(1, &input, sizeof(input));
217 input.ki.dwFlags = KEYEVENTF_KEYUP;
218 SendInput(1, &input, sizeof(input));
219 }
220
221 void SendChar(char c) {
222 SendVirtualKey(VkKeyScanA(c));
223 }
224
225 void SendString(const char* s) {
226 while (*s) {
227 SendChar(*s);
228 s++;
229 }
230 }
231
232 // Sends a keystroke to the currently active application with optional
233 // modifiers set.
234 bool SendMnemonic(WORD mnemonic_char, bool shift_pressed, bool control_pressed,
235 bool alt_pressed) {
236 INPUT special_keys[3] = {0};
237 for (int index = 0; index < arraysize(special_keys); ++index) {
238 special_keys[index].type = INPUT_KEYBOARD;
239 special_keys[index].ki.dwFlags = 0;
240 }
241
242 int num_special_keys = 0;
243 if (shift_pressed) {
244 special_keys[num_special_keys].ki.wVk = VK_SHIFT;
245 num_special_keys++;
246 }
247
248 if (control_pressed) {
249 special_keys[num_special_keys].ki.wVk = VK_CONTROL;
250 num_special_keys++;
251 }
252
253 if (alt_pressed) {
254 special_keys[num_special_keys].ki.wVk = VK_MENU;
255 num_special_keys++;
256 }
257
258 // Depress the modifiers.
259 SendInput(num_special_keys, special_keys, sizeof(INPUT));
260
261 Sleep(100);
262
263 INPUT mnemonic = {0};
264 mnemonic.type = INPUT_KEYBOARD;
265 mnemonic.ki.wVk = mnemonic_char;
266
267 // Depress and release the mnemonic.
268 SendInput(1, &mnemonic, sizeof(INPUT));
269 Sleep(100);
270
271 mnemonic.ki.dwFlags |= KEYEVENTF_KEYUP;
272 SendInput(1, &mnemonic, sizeof(INPUT));
273 Sleep(100);
274
275 // Now release the modifiers.
276 for (int index = 0; index < num_special_keys; index++) {
277 special_keys[index].ki.dwFlags |= KEYEVENTF_KEYUP;
278 }
279
280 SendInput(num_special_keys, special_keys, sizeof(INPUT));
281 Sleep(100);
282
283 return true;
284 }
285
286 std::wstring GetExecutableAppPath(const std::wstring& file) {
287 std::wstring kAppPathsKey =
288 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\";
289
290 std::wstring app_path;
291 RegKey key(HKEY_LOCAL_MACHINE, (kAppPathsKey + file).c_str());
292 if (key.Handle()) {
293 key.ReadValue(NULL, &app_path);
294 }
295
296 return app_path;
297 }
298
299 std::wstring FormatCommandForApp(const std::wstring& exe_name,
300 const std::wstring& argument) {
301 std::wstring reg_path(StringPrintf(L"Applications\\%ls\\shell\\open\\command",
302 exe_name.c_str()));
303 RegKey key(HKEY_CLASSES_ROOT, reg_path.c_str());
304
305 std::wstring command;
306 if (key.Handle()) {
307 key.ReadValue(NULL, &command);
308 int found = command.find(L"%1");
309 if (found >= 0) {
310 command.replace(found, 2, argument);
311 }
312 }
313 return command;
314 }
315
316 base::ProcessHandle LaunchExecutable(const std::wstring& executable,
317 const std::wstring& argument) {
318 base::ProcessHandle process = NULL;
319 std::wstring path = GetExecutableAppPath(executable);
320 if (path.empty()) {
321 path = FormatCommandForApp(executable, argument);
322 if (path.empty()) {
323 DLOG(ERROR) << "Failed to find executable: " << executable;
324 } else {
325 CommandLine cmdline(L"");
326 cmdline.ParseFromString(path);
327 base::LaunchApp(cmdline, false, false, &process);
328 }
329 } else {
330 CommandLine cmdline(path);
331 cmdline.AppendLooseValue(argument);
332 base::LaunchApp(cmdline, false, false, &process);
333 }
334 return process;
335 }
336
337 base::ProcessHandle LaunchFirefox(const std::wstring& url) {
338 return LaunchExecutable(kFirefoxImageName, url);
339 }
340
341 base::ProcessHandle LaunchSafari(const std::wstring& url) {
342 return LaunchExecutable(kSafariImageName, url);
343 }
344
345 base::ProcessHandle LaunchChrome(const std::wstring& url) {
346 return LaunchExecutable(kChromeImageName,
347 StringPrintf(L"--%ls ", switches::kNoFirstRun) + url);
348 }
349
350 base::ProcessHandle LaunchOpera(const std::wstring& url) {
351 // NOTE: For Opera tests to work it must be configured to start up with
352 // a blank page. There is an command line switch, -nosession, that's supposed
353 // to avoid opening up the previous session, but that switch is not working.
354 // TODO(tommi): Include a special ini file (opera6.ini) for opera and launch
355 // with our required settings. This file is by default stored here:
356 // "%USERPROFILE%\Application Data\Opera\Opera\profile\opera6.ini"
357 return LaunchExecutable(kOperaImageName, url);
358 }
359
360 base::ProcessHandle LaunchIEOnVista(const std::wstring& url) {
361 typedef HRESULT (WINAPI* IELaunchURLPtr)(
362 const wchar_t* url,
363 PROCESS_INFORMATION *pi,
364 VOID *info);
365
366 IELaunchURLPtr launch;
367 PROCESS_INFORMATION pi = {0};
368 IELAUNCHURLINFO info = {sizeof info, 0};
369 HMODULE h = LoadLibrary(L"ieframe.dll");
370 if (!h)
371 return NULL;
372 launch = reinterpret_cast<IELaunchURLPtr>(GetProcAddress(h, "IELaunchURL"));
373 HRESULT hr = launch(url.c_str(), &pi, &info);
374 FreeLibrary(h);
375 if (SUCCEEDED(hr))
376 CloseHandle(pi.hThread);
377 return pi.hProcess;
378 }
379
380 base::ProcessHandle LaunchIE(const std::wstring& url) {
381 if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) {
382 return LaunchIEOnVista(url);
383 } else {
384 return LaunchExecutable(kIEImageName, url);
385 }
386 }
387
388 int CloseAllIEWindows() {
389 int ret = 0;
390
391 ScopedComPtr<IShellWindows> windows;
392 HRESULT hr = ::CoCreateInstance(__uuidof(ShellWindows), NULL, CLSCTX_ALL,
393 IID_IShellWindows, reinterpret_cast<void**>(windows.Receive()));
394 DCHECK(SUCCEEDED(hr));
395
396 if (SUCCEEDED(hr)) {
397 long count = 0; // NOLINT
398 windows->get_Count(&count);
399 VARIANT i = { VT_I4 };
400 for (i.lVal = 0; i.lVal < count; ++i.lVal) {
401 ScopedComPtr<IDispatch> folder;
402 windows->Item(i, folder.Receive());
403 if (folder != NULL) {
404 ScopedComPtr<IWebBrowser2> browser;
405 if (SUCCEEDED(browser.QueryFrom(folder))) {
406 browser->Quit();
407 ++ret;
408 }
409 }
410 }
411 }
412
413 return ret;
414 }
415
416 } // namespace chrome_frame_test
OLDNEW
« no previous file with comments | « chrome_frame/test/chrome_frame_test_utils.h ('k') | chrome_frame/test/chrome_frame_unittests.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698