Bluetooth: clean up Bluetooth classes
[chromium-blink-merge.git] / chrome_frame / test / mock_ie_event_sink_test.h
blob2d99cb28001130dfd03c0f194838c7666ff4debf
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 #ifndef CHROME_FRAME_TEST_MOCK_IE_EVENT_SINK_TEST_H_
6 #define CHROME_FRAME_TEST_MOCK_IE_EVENT_SINK_TEST_H_
8 #include <atlbase.h>
9 #include <atlcom.h>
10 #include <string>
11 #include <vector>
13 #include "base/files/file_path.h"
14 #include "base/string_number_conversions.h"
15 #include "base/stringprintf.h"
16 #include "base/utf_string_conversions.h"
17 #include "base/win/object_watcher.h"
18 #include "chrome_frame/test/chrome_frame_test_utils.h"
19 #include "chrome_frame/test/chrome_frame_ui_test_utils.h"
20 #include "chrome_frame/test/ie_event_sink.h"
21 #include "chrome_frame/test/test_server.h"
22 #include "chrome_frame/test/test_with_web_server.h"
23 #include "chrome_frame/test/win_event_receiver.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "third_party/xulrunner-sdk/win/include/accessibility/AccessibleEventId.h"
28 namespace chrome_frame_test {
30 // Convenience enum for specifying whether a load occurred in IE or CF.
31 enum LoadedInRenderer {
32 IN_IE = 0,
33 IN_CF
36 // This mocks an IEEventListener, providing methods for expecting certain
37 // sequences of events.
38 class MockIEEventSink : public IEEventListener {
39 public:
40 MockIEEventSink() {
41 CComObject<IEEventSink>::CreateInstance(&event_sink_);
42 event_sink_->AddRef();
45 ~MockIEEventSink() {
46 Detach();
47 int reference_count = event_sink_->reference_count();
48 LOG_IF(ERROR, reference_count != 1)
49 << "Event sink is still referenced externally: ref count = "
50 << reference_count;
51 event_sink_->Release();
54 // Override IEEventListener methods.
55 MOCK_METHOD7(OnBeforeNavigate2, void (IDispatch* dispatch, // NOLINT
56 VARIANT* url,
57 VARIANT* flags,
58 VARIANT* target_frame_name,
59 VARIANT* post_data,
60 VARIANT* headers,
61 VARIANT_BOOL* cancel));
62 MOCK_METHOD2(OnNavigateComplete2, void (IDispatch* dispatch, // NOLINT
63 VARIANT* url));
64 MOCK_METHOD5(OnNewWindow3, void (IDispatch** dispatch, // NOLINT
65 VARIANT_BOOL* cancel,
66 DWORD flags,
67 BSTR url_context,
68 BSTR url));
69 MOCK_METHOD2(OnNewWindow2, void (IDispatch** dispatch, // NOLINT
70 VARIANT_BOOL* cancel));
71 MOCK_METHOD5(OnNavigateError, void (IDispatch* dispatch, // NOLINT
72 VARIANT* url,
73 VARIANT* frame_name,
74 VARIANT* status_code,
75 VARIANT* cancel));
76 MOCK_METHOD2(OnFileDownload, void (VARIANT_BOOL active_doc, // NOLINT
77 VARIANT_BOOL* cancel));
78 MOCK_METHOD0(OnQuit, void ()); // NOLINT
79 MOCK_METHOD1(OnLoadError, void (const wchar_t* url)); // NOLINT
80 MOCK_METHOD3(OnMessage, void (const wchar_t* message, // NOLINT
81 const wchar_t* origin,
82 const wchar_t* source));
83 MOCK_METHOD2(OnNewBrowserWindow, void (IDispatch* dispatch, // NOLINT
84 const wchar_t* url));
86 // Convenience OnLoad method which is called once when a page is loaded with
87 // |is_cf| set to whether the renderer is CF or not.
88 MOCK_METHOD2(OnLoad, void (bool is_cf, const wchar_t* url)); // NOLINT
90 // Attach |dispatch| to the event sink and begin listening to the source's
91 // events.
92 void Attach(IDispatch* dispatch) {
93 event_sink_->set_listener(this);
94 event_sink_->Attach(dispatch);
97 void Detach() {
98 event_sink_->set_listener(NULL);
99 event_sink_->Uninitialize();
102 // Expect a normal navigation to |url| to occur in CF or IE.
103 void ExpectNavigation(bool is_cf, const std::wstring& url);
105 // Similar as above, but should be used in cases where IE6 with CF may not
106 // generate an OnBeforeNavigate event during the navigation. This occurs
107 // during in-page navigation (via anchors), form submission, window.open
108 // to target "self", and possibly others.
109 void ExpectNavigationOptionalBefore(bool is_cf, const std::wstring& url);
111 // Expect a navigation in a new window created by a window.open call to |url|.
112 // |parent_cf| signifies whether the parent frame was loaded in CF, while
113 // |new_window_cf| signifies whether to expect the new page to be loaded in
114 // CF.
115 void ExpectJavascriptWindowOpenNavigation(bool parent_cf, bool new_window_cf,
116 const std::wstring& url);
118 // Expect a new window to open. The new event sink will be attached to
119 // |new_window_mock|.
120 void ExpectNewWindow(MockIEEventSink* new_window_mock);
122 // Expects any and all navigations.
123 void ExpectAnyNavigations();
125 void ExpectDocumentReadystate(int ready_state);
127 IEEventSink* event_sink() { return event_sink_; }
129 private:
130 // Override IE's OnDocumentComplete to call our OnLoad, iff it is IE actually
131 // rendering the page.
132 virtual void OnDocumentComplete(IDispatch* dispatch, VARIANT* url);
134 // Override CF's OnLoad to call our OnLoad.
135 virtual void OnLoad(const wchar_t* url) {
136 OnLoad(IN_CF, url);
139 // Helper method for expecting navigations. |before_cardinality| specifies
140 // the cardinality for the BeforeNavigate expectation and
141 // |complete_cardinality| specifies the cardinality for the NavigateComplete
142 // expectation. Returns the set of expectations added.
143 // Note: Prefer making a new Expect... method before making this public.
144 testing::ExpectationSet ExpectNavigationCardinality(const std::wstring& url,
145 testing::Cardinality before_cardinality,
146 testing::Cardinality complete_cardinality);
148 // It may be necessary to create this on the heap. Otherwise, if the
149 // reference count is greater than zero, a debug assert will be triggered
150 // in the destructor. This happens at least when IE crashes. In that case,
151 // DispEventUnadvise and CoDisconnectObject are not sufficient to decrement
152 // the reference count.
153 // TODO(kkania): Investigate if the above is true.
154 CComObject<IEEventSink>* event_sink_;
157 // This mocks a PropertyNotifySinkListener, providing methods for
158 // expecting certain sequences of events.
159 class MockPropertyNotifySinkListener : public PropertyNotifySinkListener {
160 public:
161 MockPropertyNotifySinkListener() : cookie_(0), sink_(NULL) {
162 CComObject<PropertyNotifySinkImpl>::CreateInstance(&sink_);
163 sink_->AddRef();
164 sink_->set_listener(this);
167 ~MockPropertyNotifySinkListener() {
168 Detach();
169 sink_->set_listener(NULL);
170 LOG_IF(ERROR, sink_->m_dwRef != 1)
171 << "Event sink is still referenced externally: ref count = "
172 << sink_->m_dwRef;
173 sink_->Release();
176 // Override PropertyNotifySinkListener methods.
177 MOCK_METHOD1(OnChanged, void (DISPID dispid)); // NOLINT
179 bool Attach(IUnknown* obj) {
180 DCHECK_EQ(cookie_, 0UL);
181 DCHECK(obj);
182 HRESULT hr = AtlAdvise(obj, sink_->GetUnknown(), IID_IPropertyNotifySink,
183 &cookie_);
184 if (SUCCEEDED(hr)) {
185 event_source_ = obj;
186 } else {
187 LOG(ERROR) << base::StringPrintf("AtlAdvise: 0x%08X", hr);
188 cookie_ = 0;
191 return SUCCEEDED(hr);
194 void Detach() {
195 if (event_source_) {
196 DCHECK_NE(cookie_, 0UL);
197 AtlUnadvise(event_source_, IID_IPropertyNotifySink, cookie_);
198 event_source_.Release();
199 cookie_ = 0;
203 private:
204 CComObject<PropertyNotifySinkImpl>* sink_;
205 DWORD cookie_;
206 base::win::ScopedComPtr<IUnknown> event_source_;
209 // Allows tests to observe when processes exit.
210 class MockObjectWatcherDelegate : public base::win::ObjectWatcher::Delegate {
211 public:
212 // base::win::ObjectWatcher::Delegate implementation
213 MOCK_METHOD1(OnObjectSignaled, void (HANDLE process_handle)); // NOLINT
215 virtual ~MockObjectWatcherDelegate() {
216 // Would be nice to free them when OnObjectSignaled is called, too, but
217 // it doesn't seem worth it.
218 for (std::vector<HANDLE>::iterator it = process_handles_.begin();
219 it != process_handles_.end(); ++it) {
220 ::CloseHandle(*it);
224 // Registers this instance to watch |process_handle| for termination.
225 void WatchProcess(HANDLE process_handle) {
226 process_handles_.push_back(process_handle);
227 object_watcher_.StartWatching(process_handle, this);
230 // Registers this instance to watch |hwnd|'s owning process for termination.
231 void WatchProcessForHwnd(HWND hwnd) {
232 DWORD pid = 0;
233 ::GetWindowThreadProcessId(hwnd, &pid);
234 EXPECT_TRUE(pid);
235 if (pid != 0) {
236 HANDLE process_handle = ::OpenProcess(SYNCHRONIZE, FALSE, pid);
237 EXPECT_TRUE(process_handle);
238 if (process_handle != NULL) {
239 WatchProcess(process_handle);
244 private:
245 std::vector<HANDLE> process_handles_;
246 base::win::ObjectWatcher object_watcher_;
249 // Mocks a window observer so that tests can detect new windows.
250 class MockWindowObserver : public WindowObserver {
251 public:
252 // WindowObserver implementation
253 MOCK_METHOD1(OnWindowOpen, void (HWND hwnd)); // NOLINT
254 MOCK_METHOD1(OnWindowClose, void (HWND hwnd)); // NOLINT
256 void WatchWindow(std::string caption_pattern, std::string class_pattern) {
257 window_watcher_.AddObserver(this, caption_pattern, class_pattern);
260 private:
261 WindowWatchdog window_watcher_;
264 class MockAccEventObserver : public AccEventObserver {
265 public:
266 MOCK_METHOD1(OnAccDocLoad, void (HWND)); // NOLINT
267 MOCK_METHOD3(OnAccValueChange, void (HWND, AccObject*, // NOLINT
268 const std::wstring&));
269 MOCK_METHOD1(OnMenuPopup, void (HWND)); // NOLINT
270 MOCK_METHOD2(OnTextCaretMoved, void (HWND, AccObject*)); // NOLINT
273 // This test fixture provides common methods needed for testing CF
274 // integration with IE. gMock is used to verify that IE is reporting correct
275 // navigational events and MockWebServer is used to verify that the correct
276 // requests are going out.
277 class MockIEEventSinkTest {
278 public:
279 MockIEEventSinkTest();
280 MockIEEventSinkTest(int port, const std::wstring& address,
281 const base::FilePath& root_dir);
283 ~MockIEEventSinkTest() {
284 // Detach manually here so that it occurs before |last_resort_close_ie_|
285 // is destroyed.
286 ie_mock_.Detach();
289 // Launches IE as a COM server and sets |ie_mock_| as the event sink, then
290 // navigates to the given url. Then the timed message loop is run until
291 // |ie_mock_| receives OnQuit or the timeout is exceeded.
292 void LaunchIEAndNavigate(const std::wstring& url);
294 // Same as above but allows the timeout to be specified.
295 void LaunchIENavigateAndLoop(const std::wstring& url,
296 base::TimeDelta timeout);
298 // Returns the url for the test file given. |relative_path| should be
299 // relative to the test data directory.
300 std::wstring GetTestUrl(const std::wstring& relative_path);
302 // Returns the absolute FilePath for the test file given. |relative_path|
303 // should be relative to the test data directory.
304 base::FilePath GetTestFilePath(const std::wstring& relative_path);
306 // Returns the url for an html page just containing some text. Iff |use_cf|
307 // is true, the chrome_frame meta tag will be included too.
308 std::wstring GetSimplePageUrl() {
309 return GetTestUrl(L"simple.html");
312 // Returns the title of the html page at |GetSimplePageUrl()|.
313 std::wstring GetSimplePageTitle() {
314 return L"simple web page";
317 // Returns the url for an html page just containing one link to the simple
318 // page mentioned above.
319 std::wstring GetLinkPageUrl() {
320 return GetTestUrl(L"link.html");
323 // Returns the title of the html page at |GetLinkPageUrl()|.
324 std::wstring GetLinkPageTitle() {
325 return L"link";
328 // Returns the url for an html page containing several anchors pointing
329 // to different parts of the page. |index| specifies what fragment to
330 // append to the url. If zero, no fragment is appended. The highest fragment
331 // is #a4.
332 std::wstring GetAnchorPageUrl(int index) {
333 DCHECK_LT(index, 5);
334 std::wstring base_name = L"anchor.html";
335 if (index > 0)
336 base_name += std::wstring(L"#a") + base::IntToString16(index);
337 return GetTestUrl(base_name);
340 // Returns the title of the html page at |GetAnchorPageUrl()|.
341 std::wstring GetAnchorPageTitle() {
342 return L"Chrome Frame Test";
345 // Returns the url for an html page that will, when clicked, open a new window
346 // to |target|.
347 std::wstring GetWindowOpenUrl(const wchar_t* target) {
348 return GetTestUrl(std::wstring(L"window_open.html?").append(target));
351 // Returns the title of the html page at |GetWindowOpenUrl()|.
352 std::wstring GetWindowOpenTitle() {
353 return L"window open";
356 protected:
357 CloseIeAtEndOfScope last_resort_close_ie_;
358 chrome_frame_test::TimedMsgLoop loop_;
359 testing::StrictMock<MockIEEventSink> ie_mock_;
360 testing::StrictMock<MockWebServer> server_mock_;
361 scoped_refptr<HungCOMCallDetector> hung_call_detector_;
362 private:
363 DISALLOW_COPY_AND_ASSIGN(MockIEEventSinkTest);
366 } // namespace chrome_frame_test
368 #endif // CHROME_FRAME_TEST_MOCK_IE_EVENT_SINK_TEST_H_