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

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

Issue 2822016: [chrome_frame] Refactor/merge IE no interference tests with other mock event ... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 5 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/ie_event_sink.h ('k') | chrome_frame/test/mock_ie_event_sink_actions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2010 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/ie_event_sink.h"
6
7 #include "base/scoped_bstr_win.h"
8 #include "base/scoped_handle.h"
9 #include "base/utf_string_conversions.h"
10 #include "base/win_util.h"
11 #include "chrome_frame/test/chrome_frame_test_utils.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace chrome_frame_test {
15
16 const int kDefaultWaitForIEToTerminateMs = 10 * 1000;
17
18 _ATL_FUNC_INFO IEEventSink::kNavigateErrorInfo = {
19 CC_STDCALL, VT_EMPTY, 5, {
20 VT_DISPATCH,
21 VT_VARIANT | VT_BYREF,
22 VT_VARIANT | VT_BYREF,
23 VT_VARIANT | VT_BYREF,
24 VT_BOOL | VT_BYREF,
25 }
26 };
27
28 _ATL_FUNC_INFO IEEventSink::kNavigateComplete2Info = {
29 CC_STDCALL, VT_EMPTY, 2, {
30 VT_DISPATCH,
31 VT_VARIANT | VT_BYREF
32 }
33 };
34
35 _ATL_FUNC_INFO IEEventSink::kBeforeNavigate2Info = {
36 CC_STDCALL, VT_EMPTY, 7, {
37 VT_DISPATCH,
38 VT_VARIANT | VT_BYREF,
39 VT_VARIANT | VT_BYREF,
40 VT_VARIANT | VT_BYREF,
41 VT_VARIANT | VT_BYREF,
42 VT_VARIANT | VT_BYREF,
43 VT_BOOL | VT_BYREF
44 }
45 };
46
47 _ATL_FUNC_INFO IEEventSink::kNewWindow2Info = {
48 CC_STDCALL, VT_EMPTY, 2, {
49 VT_DISPATCH | VT_BYREF,
50 VT_BOOL | VT_BYREF,
51 }
52 };
53
54 _ATL_FUNC_INFO IEEventSink::kNewWindow3Info = {
55 CC_STDCALL, VT_EMPTY, 5, {
56 VT_DISPATCH | VT_BYREF,
57 VT_BOOL | VT_BYREF,
58 VT_UINT,
59 VT_BSTR,
60 VT_BSTR
61 }
62 };
63
64 _ATL_FUNC_INFO IEEventSink::kVoidMethodInfo = {
65 CC_STDCALL, VT_EMPTY, 0, {NULL}};
66
67 _ATL_FUNC_INFO IEEventSink::kDocumentCompleteInfo = {
68 CC_STDCALL, VT_EMPTY, 2, {
69 VT_DISPATCH,
70 VT_VARIANT | VT_BYREF
71 }
72 };
73
74 _ATL_FUNC_INFO IEEventSink::kFileDownloadInfo = {
75 CC_STDCALL, VT_EMPTY, 2, {
76 VT_BOOL,
77 VT_BOOL | VT_BYREF
78 }
79 };
80
81 IEEventSink::IEEventSink()
82 : ALLOW_THIS_IN_INITIALIZER_LIST(
83 onmessage_(this, &IEEventSink::OnMessage)),
84 ALLOW_THIS_IN_INITIALIZER_LIST(
85 onloaderror_(this, &IEEventSink::OnLoadError)),
86 ALLOW_THIS_IN_INITIALIZER_LIST(
87 onload_(this, &IEEventSink::OnLoad)),
88 listener_(NULL),
89 ie_process_id_(0),
90 did_receive_on_quit_(false) {
91 }
92
93 IEEventSink::~IEEventSink() {
94 Uninitialize();
95 }
96
97 // IEEventSink member defines
98 void IEEventSink::Attach(IDispatch* browser_disp) {
99 EXPECT_TRUE(NULL != browser_disp);
100 if (browser_disp) {
101 EXPECT_HRESULT_SUCCEEDED(web_browser2_.QueryFrom(browser_disp));
102 EXPECT_TRUE(S_OK == DispEventAdvise(web_browser2_,
103 &DIID_DWebBrowserEvents2));
104 FindIEProcessId();
105 }
106 }
107
108 void IEEventSink::Uninitialize() {
109 DisconnectFromChromeFrame();
110 if (web_browser2_.get()) {
111 if (m_dwEventCookie != 0xFEFEFEFE) {
112 DispEventUnadvise(web_browser2_);
113 CoDisconnectObject(this, 0);
114 }
115
116 if (!did_receive_on_quit_) {
117 // Log the browser window url for debugging purposes.
118 ScopedBstr browser_url;
119 web_browser2_->get_LocationURL(browser_url.Receive());
120 std::wstring browser_url_wstring;
121 browser_url_wstring.assign(browser_url, browser_url.Length());
122 std::string browser_url_string = WideToUTF8(browser_url_wstring);
123 EXPECT_TRUE(did_receive_on_quit_) << "OnQuit was not received for "
124 << "browser with url "
125 << browser_url_string;
126
127 web_browser2_->Quit();
128 }
129
130 web_browser2_.Release();
131 }
132 }
133
134 bool IEEventSink::IsCFRendering() {
135 DCHECK(web_browser2_);
136
137 HWND renderer_window;
138 if (web_browser2_) {
139 ScopedComPtr<IDispatch> doc;
140 web_browser2_->get_Document(doc.Receive());
141 if (doc) {
142 ScopedComPtr<IOleWindow> ole_window;
143 ole_window.QueryFrom(doc);
144 if (ole_window) {
145 ole_window->GetWindow(&renderer_window);
146 if (IsWindow(renderer_window)) {
147 wchar_t class_name[MAX_PATH] = {0};
148 GetClassName(renderer_window, class_name, arraysize(class_name));
149 return _wcsicmp(class_name, L"Internet Explorer_Server") != 0;
150 }
151 }
152 }
153 }
154 return false;
155 }
156
157 void IEEventSink::SetFocusToRenderer() {
158 simulate_input::SetKeyboardFocusToWindow(GetRendererWindow());
159 }
160
161 void IEEventSink::SendKeys(const wchar_t* input_string) {
162 SetFocusToRenderer();
163 simulate_input::SendStringW(input_string);
164 }
165
166 void IEEventSink::SendMouseClick(int x, int y,
167 simulate_input::MouseButton button) {
168 simulate_input::SendMouseClick(GetRendererWindow(), x, y, button);
169 }
170
171 void IEEventSink::ExpectRendererWindowHasFocus() {
172 HWND renderer_window = GetRendererWindow();
173 EXPECT_TRUE(IsWindow(renderer_window));
174
175 if (IsCFRendering()) {
176 for (HWND first_child = renderer_window;
177 IsWindow(first_child); first_child = GetWindow(first_child, GW_CHILD)) {
178 renderer_window = first_child;
179 }
180
181 wchar_t class_name[MAX_PATH] = {0};
182 GetClassName(renderer_window, class_name, arraysize(class_name));
183 EXPECT_EQ(0, _wcsicmp(class_name, L"Chrome_RenderWidgetHostHWND"));
184 }
185
186 DWORD renderer_thread = 0;
187 DWORD renderer_process = 0;
188 renderer_thread = GetWindowThreadProcessId(renderer_window,
189 &renderer_process);
190
191 ASSERT_TRUE(AttachThreadInput(GetCurrentThreadId(), renderer_thread, TRUE));
192 HWND focus_window = GetFocus();
193 EXPECT_TRUE(focus_window == renderer_window);
194 EXPECT_TRUE(AttachThreadInput(GetCurrentThreadId(), renderer_thread, FALSE));
195 }
196
197 void IEEventSink::ExpectAddressBarUrl(
198 const std::wstring& expected_url) {
199 DCHECK(web_browser2_);
200 if (web_browser2_) {
201 ScopedBstr address_bar_url;
202 EXPECT_EQ(S_OK, web_browser2_->get_LocationURL(address_bar_url.Receive()));
203 EXPECT_EQ(expected_url, std::wstring(address_bar_url));
204 }
205 }
206
207 void IEEventSink::Exec(const GUID* cmd_group_guid, DWORD command_id,
208 DWORD cmd_exec_opt, VARIANT* in_args,
209 VARIANT* out_args) {
210 ScopedComPtr<IOleCommandTarget> shell_browser_cmd_target;
211 DoQueryService(SID_STopLevelBrowser, web_browser2_,
212 shell_browser_cmd_target.Receive());
213 ASSERT_TRUE(NULL != shell_browser_cmd_target);
214 EXPECT_HRESULT_SUCCEEDED(shell_browser_cmd_target->Exec(cmd_group_guid,
215 command_id, cmd_exec_opt, in_args, out_args));
216 }
217
218 HWND IEEventSink::GetRendererWindow() {
219 HWND renderer_window = NULL;
220 if (IsCFRendering()) {
221 DCHECK(chrome_frame_);
222 ScopedComPtr<IOleWindow> ole_window;
223 ole_window.QueryFrom(chrome_frame_);
224 EXPECT_TRUE(ole_window.get());
225
226 if (ole_window) {
227 HWND activex_window = NULL;
228 ole_window->GetWindow(&activex_window);
229 EXPECT_TRUE(IsWindow(activex_window));
230
231 // chrome tab window is the first (and the only) child of activex
232 HWND chrome_tab_window = GetWindow(activex_window, GW_CHILD);
233 EXPECT_TRUE(IsWindow(chrome_tab_window));
234 renderer_window = GetWindow(chrome_tab_window, GW_CHILD);
235 }
236 } else {
237 DCHECK(web_browser2_);
238 ScopedComPtr<IDispatch> doc;
239 HRESULT hr = web_browser2_->get_Document(doc.Receive());
240 EXPECT_HRESULT_SUCCEEDED(hr);
241 EXPECT_TRUE(doc);
242 if (doc) {
243 ScopedComPtr<IOleWindow> ole_window;
244 ole_window.QueryFrom(doc);
245 EXPECT_TRUE(ole_window);
246 if (ole_window) {
247 ole_window->GetWindow(&renderer_window);
248 }
249 }
250 }
251
252 EXPECT_TRUE(IsWindow(renderer_window));
253 return renderer_window;
254 }
255
256 HRESULT IEEventSink::LaunchIEAndNavigate(
257 const std::wstring& navigate_url, IEEventListener* listener) {
258 listener_ = listener;
259 HRESULT hr = LaunchIEAsComServer(web_browser2_.Receive());
260 EXPECT_EQ(S_OK, hr);
261 if (hr == S_OK) {
262 FindIEProcessId();
263 web_browser2_->put_Visible(VARIANT_TRUE);
264 hr = DispEventAdvise(web_browser2_, &DIID_DWebBrowserEvents2);
265 EXPECT_TRUE(hr == S_OK);
266 hr = Navigate(navigate_url);
267 }
268
269 DLOG_IF(WARNING, FAILED(hr)) << "Failed to launch IE. Error:" << hr;
270 return hr;
271 }
272
273 HRESULT IEEventSink::Navigate(const std::wstring& navigate_url) {
274 VARIANT empty = ScopedVariant::kEmptyVariant;
275 ScopedVariant url;
276 url.Set(navigate_url.c_str());
277
278 HRESULT hr = S_OK;
279 hr = web_browser2_->Navigate2(url.AsInput(), &empty, &empty, &empty, &empty);
280 EXPECT_TRUE(hr == S_OK);
281 return hr;
282 }
283
284 HRESULT IEEventSink::CloseWebBrowser() {
285 if (!web_browser2_)
286 return E_FAIL;
287
288 DisconnectFromChromeFrame();
289 web_browser2_->Quit();
290 return S_OK;
291 }
292
293 void IEEventSink::Refresh() {
294 ScopedVariant refresh_level(REFRESH_NORMAL);
295 web_browser2_->Refresh2(refresh_level.AsInput());
296 }
297
298 void IEEventSink::ConnectToChromeFrame() {
299 DCHECK(web_browser2_);
300 if (chrome_frame_.get())
301 return;
302 ScopedComPtr<IShellBrowser> shell_browser;
303 DoQueryService(SID_STopLevelBrowser, web_browser2_,
304 shell_browser.Receive());
305
306 if (shell_browser) {
307 ScopedComPtr<IShellView> shell_view;
308 shell_browser->QueryActiveShellView(shell_view.Receive());
309 if (shell_view) {
310 shell_view->GetItemObject(SVGIO_BACKGROUND, __uuidof(IChromeFrame),
311 reinterpret_cast<void**>(chrome_frame_.Receive()));
312 }
313
314 if (chrome_frame_) {
315 ScopedVariant onmessage(onmessage_.ToDispatch());
316 ScopedVariant onloaderror(onloaderror_.ToDispatch());
317 ScopedVariant onload(onload_.ToDispatch());
318 EXPECT_HRESULT_SUCCEEDED(chrome_frame_->put_onmessage(onmessage));
319 EXPECT_HRESULT_SUCCEEDED(chrome_frame_->put_onloaderror(onloaderror));
320 EXPECT_HRESULT_SUCCEEDED(chrome_frame_->put_onload(onload));
321 }
322 }
323 }
324
325 void IEEventSink::DisconnectFromChromeFrame() {
326 if (chrome_frame_) {
327 // Use a local ref counted copy of the IChromeFrame interface as the
328 // outgoing calls could cause the interface to be deleted due to a message
329 // pump running in the context of the outgoing call.
330 ScopedComPtr<IChromeFrame> chrome_frame(chrome_frame_);
331 chrome_frame_.Release();
332 ScopedVariant dummy(static_cast<IDispatch*>(NULL));
333 chrome_frame->put_onmessage(dummy);
334 chrome_frame->put_onload(dummy);
335 chrome_frame->put_onloaderror(dummy);
336 }
337 }
338
339 void IEEventSink::FindIEProcessId() {
340 // Grab the process id here in case it will be too late to do it
341 // in Uninitialize.
342 HWND hwnd = NULL;
343 web_browser2_->get_HWND(reinterpret_cast<SHANDLE_PTR*>(&hwnd));
344 EXPECT_TRUE(::IsWindow(hwnd));
345 if (::IsWindow(hwnd))
346 ::GetWindowThreadProcessId(hwnd, &ie_process_id_);
347 }
348
349 // Event callbacks
350 STDMETHODIMP_(void) IEEventSink::OnDownloadBegin() {
351 if (listener_)
352 listener_->OnDownloadBegin();
353 }
354
355 STDMETHODIMP_(void) IEEventSink::OnNewWindow2(IDispatch** disp,
356 VARIANT_BOOL* s) {
357 if (listener_)
358 listener_->OnNewWindow2(disp, s);
359 }
360
361 STDMETHODIMP_(void) IEEventSink::OnNavigateError(IDispatch* dispatch,
362 VARIANT* url, VARIANT* frame_name, VARIANT* status_code, VARIANT* cancel) {
363 DLOG(INFO) << __FUNCTION__;
364 if (listener_)
365 listener_->OnNavigateError(dispatch, url, frame_name, status_code, cancel);
366 }
367
368 STDMETHODIMP IEEventSink::OnBeforeNavigate2(
369 IDispatch* dispatch, VARIANT* url, VARIANT* flags,
370 VARIANT* target_frame_name, VARIANT* post_data, VARIANT* headers,
371 VARIANT_BOOL* cancel) {
372 DLOG(INFO) << __FUNCTION__
373 << StringPrintf("%ls - 0x%08X", url->bstrVal, this);
374 // Reset any existing reference to chrome frame since this is a new
375 // navigation.
376 DisconnectFromChromeFrame();
377 if (listener_)
378 listener_->OnBeforeNavigate2(dispatch, url, flags, target_frame_name,
379 post_data, headers, cancel);
380 return S_OK;
381 }
382
383 STDMETHODIMP_(void) IEEventSink::OnNavigateComplete2(
384 IDispatch* dispatch, VARIANT* url) {
385 DLOG(INFO) << __FUNCTION__;
386 ConnectToChromeFrame();
387 if (listener_)
388 listener_->OnNavigateComplete2(dispatch, url);
389 }
390
391 STDMETHODIMP_(void) IEEventSink::OnDocumentComplete(
392 IDispatch* dispatch, VARIANT* url) {
393 DLOG(INFO) << __FUNCTION__;
394 EXPECT_TRUE(url);
395 if (!url)
396 return;
397 if (listener_)
398 listener_->OnDocumentComplete(dispatch, url);
399 }
400
401 STDMETHODIMP_(void) IEEventSink::OnFileDownload(
402 VARIANT_BOOL active_doc, VARIANT_BOOL* cancel) {
403 DLOG(INFO) << __FUNCTION__ << StringPrintf(" 0x%08X ad=%i", this,
404 active_doc);
405 if (listener_)
406 listener_->OnFileDownload(active_doc, cancel);
407 // Always cancel file downloads in tests.
408 *cancel = VARIANT_TRUE;
409 }
410
411 STDMETHODIMP_(void) IEEventSink::OnNewWindow3(
412 IDispatch** dispatch, VARIANT_BOOL* cancel, DWORD flags, BSTR url_context,
413 BSTR url) {
414 DLOG(INFO) << __FUNCTION__;
415 EXPECT_TRUE(dispatch);
416 if (!dispatch)
417 return;
418
419 if (listener_)
420 listener_->OnNewWindow3(dispatch, cancel, flags, url_context, url);
421
422 // Note that |dispatch| is an [in/out] argument. IE is asking listeners if
423 // they want to use a IWebBrowser2 of their choice for the new window.
424 // Since we need to listen on events on the new browser, we create one
425 // if needed.
426 if (!*dispatch) {
427 ScopedComPtr<IDispatch> new_browser;
428 HRESULT hr = new_browser.CreateInstance(CLSID_InternetExplorer, NULL,
429 CLSCTX_LOCAL_SERVER);
430 DCHECK(SUCCEEDED(hr) && new_browser);
431 *dispatch = new_browser.Detach();
432 }
433
434 if (*dispatch)
435 listener_->OnNewBrowserWindow(*dispatch, url);
436 }
437
438 STDMETHODIMP_(void) IEEventSink::OnQuit() {
439 DLOG(INFO) << __FUNCTION__;
440
441 did_receive_on_quit_ = true;
442
443 DispEventUnadvise(web_browser2_);
444 CoDisconnectObject(this, 0);
445
446 if (listener_)
447 listener_->OnQuit();
448 }
449
450 HRESULT IEEventSink::OnLoad(const VARIANT* param) {
451 DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal;
452 ScopedVariant stack_object(*param);
453 if (chrome_frame_) {
454 if (listener_)
455 listener_->OnLoad(param->bstrVal);
456 } else {
457 DLOG(WARNING) << "Invalid chrome frame pointer";
458 }
459 return S_OK;
460 }
461
462 HRESULT IEEventSink::OnLoadError(const VARIANT* param) {
463 DLOG(INFO) << __FUNCTION__ << " " << param->bstrVal;
464 if (chrome_frame_) {
465 if (listener_)
466 listener_->OnLoadError(param->bstrVal);
467 } else {
468 DLOG(WARNING) << "Invalid chrome frame pointer";
469 }
470 return S_OK;
471 }
472
473 HRESULT IEEventSink::OnMessage(const VARIANT* param) {
474 DLOG(INFO) << __FUNCTION__ << " " << param;
475 if (!chrome_frame_.get()) {
476 DLOG(WARNING) << "Invalid chrome frame pointer";
477 return S_OK;
478 }
479
480 ScopedVariant data, origin, source;
481 if (param && (V_VT(param) == VT_DISPATCH)) {
482 wchar_t* properties[] = { L"data", L"origin", L"source" };
483 const int prop_count = arraysize(properties);
484 DISPID ids[prop_count] = {0};
485
486 HRESULT hr = param->pdispVal->GetIDsOfNames(IID_NULL, properties,
487 prop_count, LOCALE_SYSTEM_DEFAULT, ids);
488 if (SUCCEEDED(hr)) {
489 DISPPARAMS params = { 0 };
490 EXPECT_HRESULT_SUCCEEDED(param->pdispVal->Invoke(ids[0], IID_NULL,
491 LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &params,
492 data.Receive(), NULL, NULL));
493 EXPECT_HRESULT_SUCCEEDED(param->pdispVal->Invoke(ids[1], IID_NULL,
494 LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &params,
495 origin.Receive(), NULL, NULL));
496 EXPECT_HRESULT_SUCCEEDED(param->pdispVal->Invoke(ids[2], IID_NULL,
497 LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &params,
498 source.Receive(), NULL, NULL));
499 }
500 }
501
502 if (listener_)
503 listener_->OnMessage(V_BSTR(&data), V_BSTR(&origin), V_BSTR(&source));
504 return S_OK;
505 }
506
507 } // namespace chrome_frame_test
OLDNEW
« no previous file with comments | « chrome_frame/test/ie_event_sink.h ('k') | chrome_frame/test/mock_ie_event_sink_actions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698