| OLD | NEW |
| (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 #ifndef CHROME_FRAME_TEST_MOCK_IE_EVENT_SINK_TEST_H_ |
| 6 #define CHROME_FRAME_TEST_MOCK_IE_EVENT_SINK_TEST_H_ |
| 7 |
| 8 #include <atlbase.h> |
| 9 #include <atlcom.h> |
| 10 #include <string> |
| 11 |
| 12 #include "chrome_frame/test/chrome_frame_test_utils.h" |
| 13 #include "chrome_frame/test/ie_event_sink.h" |
| 14 #include "chrome_frame/test/test_server.h" |
| 15 #include "chrome_frame/test/test_with_web_server.h" |
| 16 #include "testing/gmock/include/gmock/gmock.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 |
| 19 namespace chrome_frame_test { |
| 20 |
| 21 // Convenience enum for specifying whether a load occurred in IE or CF. |
| 22 enum LoadedInRenderer { |
| 23 IN_IE = 0, |
| 24 IN_CF |
| 25 }; |
| 26 |
| 27 // This mocks an IEEventListener, providing methods for expecting certain |
| 28 // sequences of events. |
| 29 class MockIEEventSink : public IEEventListener { |
| 30 public: |
| 31 MockIEEventSink() { |
| 32 CComObject<IEEventSink>::CreateInstance(&event_sink_); |
| 33 event_sink_->AddRef(); |
| 34 } |
| 35 |
| 36 ~MockIEEventSink() { |
| 37 Detach(); |
| 38 DLOG_IF(ERROR, !event_sink_->IsReferenceCountOne()) |
| 39 << "Event sink is still referenced externally"; |
| 40 event_sink_->Release(); |
| 41 } |
| 42 |
| 43 // Override IEEventListener methods. |
| 44 MOCK_METHOD7(OnBeforeNavigate2, void (IDispatch* dispatch, // NOLINT |
| 45 VARIANT* url, |
| 46 VARIANT* flags, |
| 47 VARIANT* target_frame_name, |
| 48 VARIANT* post_data, |
| 49 VARIANT* headers, |
| 50 VARIANT_BOOL* cancel)); |
| 51 MOCK_METHOD2(OnNavigateComplete2, void (IDispatch* dispatch, // NOLINT |
| 52 VARIANT* url)); |
| 53 MOCK_METHOD5(OnNewWindow3, void (IDispatch** dispatch, // NOLINT |
| 54 VARIANT_BOOL* cancel, |
| 55 DWORD flags, |
| 56 BSTR url_context, |
| 57 BSTR url)); |
| 58 MOCK_METHOD2(OnNewWindow2, void (IDispatch** dispatch, // NOLINT |
| 59 VARIANT_BOOL* cancel)); |
| 60 MOCK_METHOD5(OnNavigateError, void (IDispatch* dispatch, // NOLINT |
| 61 VARIANT* url, |
| 62 VARIANT* frame_name, |
| 63 VARIANT* status_code, |
| 64 VARIANT* cancel)); |
| 65 MOCK_METHOD2(OnFileDownload, void (VARIANT_BOOL active_doc, // NOLINT |
| 66 VARIANT_BOOL* cancel)); |
| 67 MOCK_METHOD0(OnQuit, void ()); // NOLINT |
| 68 MOCK_METHOD1(OnLoadError, void (const wchar_t* url)); // NOLINT |
| 69 MOCK_METHOD3(OnMessage, void (const wchar_t* message, // NOLINT |
| 70 const wchar_t* origin, |
| 71 const wchar_t* source)); |
| 72 MOCK_METHOD2(OnNewBrowserWindow, void (IDispatch* dispatch, // NOLINT |
| 73 const wchar_t* url)); |
| 74 |
| 75 // Convenience OnLoad method which is called once when a page is loaded with |
| 76 // |is_cf| set to whether the renderer is CF or not. |
| 77 MOCK_METHOD2(OnLoad, void (bool is_cf, const wchar_t* url)); // NOLINT |
| 78 |
| 79 // Attach |dispatch| to the event sink and begin listening to the source's |
| 80 // events. |
| 81 void Attach(IDispatch* dispatch) { |
| 82 event_sink_->set_listener(this); |
| 83 event_sink_->Attach(dispatch); |
| 84 } |
| 85 |
| 86 void Detach() { |
| 87 event_sink_->set_listener(NULL); |
| 88 event_sink_->Uninitialize(); |
| 89 } |
| 90 |
| 91 // Expect a normal navigation to |url| to occur in CF or IE. |
| 92 void ExpectNavigation(bool is_cf, const std::wstring& url); |
| 93 |
| 94 // Same as above, but used when the new navigation is to a diffrent fragment |
| 95 // in the same page. |
| 96 void ExpectInPageNavigation(bool is_cf, const std::wstring& url); |
| 97 |
| 98 // Expect a navigation in a new window created by a window.open call to |url|. |
| 99 // |parent_cf| signifies whether the parent frame was loaded in CF, while |
| 100 // |new_window_cf| signifies whether to expect the new page to be loaded in |
| 101 // CF. |
| 102 void ExpectJavascriptWindowOpenNavigation(bool parent_cf, bool new_window_cf, |
| 103 const std::wstring& url); |
| 104 |
| 105 // Expect a new window to open. The new event sink will be attached to |
| 106 // |new_window_mock|. |
| 107 void ExpectNewWindow(MockIEEventSink* new_window_mock); |
| 108 |
| 109 // Expects any and all navigations. |
| 110 void ExpectAnyNavigations(); |
| 111 |
| 112 IEEventSink* event_sink() { return event_sink_; } |
| 113 |
| 114 private: |
| 115 // Override IE's OnDocumentComplete to call our OnLoad, iff it is IE actually |
| 116 // rendering the page. |
| 117 virtual void OnDocumentComplete(IDispatch* dispatch, VARIANT* url) { |
| 118 if (!event_sink_->IsCFRendering()) |
| 119 OnLoad(IN_IE, V_BSTR(url)); |
| 120 } |
| 121 |
| 122 // Override CF's OnLoad to call our OnLoad. |
| 123 virtual void OnLoad(const wchar_t* url) { |
| 124 OnLoad(IN_CF, url); |
| 125 } |
| 126 |
| 127 // Helper method for expecting navigations. |before_cardinality| specifies |
| 128 // the cardinality for the BeforeNavigate expectation and |
| 129 // |complete_cardinality| specifies the cardinality for the NavigateComplete |
| 130 // expectation. Returns the set of expectations added. |
| 131 // Note: Prefer making a new Expect... method before making this public. |
| 132 testing::ExpectationSet ExpectNavigationCardinality(const std::wstring& url, |
| 133 testing::Cardinality before_cardinality, |
| 134 testing::Cardinality complete_cardinality); |
| 135 |
| 136 // It may be necessary to create this on the heap. Otherwise, if the |
| 137 // reference count is greater than zero, a debug assert will be triggered |
| 138 // in the destructor. This happens at least when IE crashes. In that case, |
| 139 // DispEventUnadvise and CoDisconnectObject are not sufficient to decrement |
| 140 // the reference count. |
| 141 // TODO(kkania): Investigate if the above is true. |
| 142 CComObject<IEEventSink>* event_sink_; |
| 143 }; |
| 144 |
| 145 // Mocks a window observer so that tests can detect new windows. |
| 146 class MockWindowObserver : public WindowObserver { |
| 147 public: |
| 148 // Override WindowObserver methods. |
| 149 MOCK_METHOD2(OnWindowDetected, void (HWND hwnd, // NOLINT |
| 150 const std::string& caption)); |
| 151 |
| 152 // Watch for all windows of the given class type. |
| 153 void WatchWindow(const wchar_t* window_class) { |
| 154 DCHECK(window_class); |
| 155 window_watcher_.AddObserver(this, WideToUTF8(window_class)); |
| 156 } |
| 157 |
| 158 private: |
| 159 WindowWatchdog window_watcher_; |
| 160 }; |
| 161 |
| 162 // This test fixture provides common methods needed for testing CF |
| 163 // integration with IE. gMock is used to verify that IE is reporting correct |
| 164 // navigational events and MockWebServer is used to verify that the correct |
| 165 // requests are going out. |
| 166 class MockIEEventSinkTest { |
| 167 public: |
| 168 MockIEEventSinkTest(); |
| 169 |
| 170 ~MockIEEventSinkTest() { |
| 171 // Detach manually here so that it occurs before |last_resort_close_ie_| |
| 172 // is destroyed. |
| 173 ie_mock_.Detach(); |
| 174 } |
| 175 |
| 176 // Launches IE as a COM server and sets |ie_mock_| as the event sink, then |
| 177 // navigates to the given url. Then the timed message loop is run until |
| 178 // |ie_mock_| receives OnQuit or the timeout is exceeded. |
| 179 void LaunchIEAndNavigate(const std::wstring& url); |
| 180 |
| 181 // Same as above but allows the timeout to be specified. |
| 182 void LaunchIENavigateAndLoop(const std::wstring& url, int timeout); |
| 183 |
| 184 // Returns the url for the test file given. |relative_path| should be |
| 185 // relative to the test data directory. |
| 186 std::wstring GetTestUrl(const std::wstring& relative_path); |
| 187 |
| 188 // Returns the absolute FilePath for the test file given. |relative_path| |
| 189 // should be relative to the test data directory. |
| 190 FilePath GetTestFilePath(const std::wstring& relative_path); |
| 191 |
| 192 // Returns the url for an html page just containing some text. Iff |use_cf| |
| 193 // is true, the chrome_frame meta tag will be included too. |
| 194 std::wstring GetSimplePageUrl() { |
| 195 return GetTestUrl(L"simple.html"); |
| 196 } |
| 197 |
| 198 // Returns the url for an html page just containing one link to the simple |
| 199 // page mentioned above. |
| 200 std::wstring GetLinkPageUrl() { |
| 201 return GetTestUrl(L"link.html"); |
| 202 } |
| 203 |
| 204 // Returns the url for an html page containing several anchors pointing |
| 205 // to different parts of the page. |index| specifies what fragment to |
| 206 // append to the url. If zero, no fragment is appended. The highest fragment |
| 207 // is #a4. |
| 208 std::wstring GetAnchorPageUrl(int index) { |
| 209 DCHECK_LT(index, 5); |
| 210 std::wstring base_name = L"anchor.html"; |
| 211 if (index > 0) |
| 212 base_name += std::wstring(L"#a") + IntToWString(index); |
| 213 return GetTestUrl(base_name); |
| 214 } |
| 215 |
| 216 protected: |
| 217 CloseIeAtEndOfScope last_resort_close_ie_; |
| 218 chrome_frame_test::TimedMsgLoop loop_; |
| 219 testing::StrictMock<MockIEEventSink> ie_mock_; |
| 220 testing::StrictMock<MockWebServer> server_mock_; |
| 221 |
| 222 private: |
| 223 DISALLOW_COPY_AND_ASSIGN(MockIEEventSinkTest); |
| 224 }; |
| 225 |
| 226 } // namespace chrome_frame_test |
| 227 |
| 228 #endif // CHROME_FRAME_TEST_MOCK_IE_EVENT_SINK_TEST_H_ |
| OLD | NEW |