| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #ifndef CHROME_FRAME_TEST_IE_EVENT_SINK_H_ | |
| 6 #define CHROME_FRAME_TEST_IE_EVENT_SINK_H_ | |
| 7 | |
| 8 #include <atlbase.h> | |
| 9 #include <atlwin.h> | |
| 10 #include <exdispid.h> | |
| 11 #include <string> | |
| 12 | |
| 13 #include "base/win/scoped_comptr.h" | |
| 14 #include "chrome_frame/chrome_tab.h" | |
| 15 #include "chrome_frame/test/simulate_input.h" | |
| 16 #include "chrome_frame/test_utils.h" | |
| 17 | |
| 18 namespace chrome_frame_test { | |
| 19 | |
| 20 // Listener for all events from the IEEventSink, defined below. This includes | |
| 21 // IE and CF events. Unfortunately some of these events are unreliable or have | |
| 22 // strange behavior across different platforms/browsers. See notes besides | |
| 23 // each method. | |
| 24 class IEEventListener { | |
| 25 public: | |
| 26 virtual ~IEEventListener() {} | |
| 27 | |
| 28 // IE callbacks | |
| 29 virtual void OnNavigateError(IDispatch* dispatch, VARIANT* url, | |
| 30 VARIANT* frame_name, VARIANT* status_code, | |
| 31 VARIANT* cancel) {} | |
| 32 // This does not occur in IE 6 in CF when navigating between fragments | |
| 33 // on the same page, although it does occur with back/forward across such. | |
| 34 virtual void OnBeforeNavigate2(IDispatch* dispatch, VARIANT* url, | |
| 35 VARIANT* flags, VARIANT* target_frame_name, | |
| 36 VARIANT* post_data, VARIANT* headers, | |
| 37 VARIANT_BOOL* cancel) {} | |
| 38 virtual void OnDownloadBegin() {} | |
| 39 virtual void OnNavigateComplete2(IDispatch* dispatch, VARIANT* url) {} | |
| 40 virtual void OnNewWindow2(IDispatch** dispatch, VARIANT_BOOL* cancel) {} | |
| 41 virtual void OnNewWindow3(IDispatch** dispatch, VARIANT_BOOL* cancel, | |
| 42 DWORD flags, BSTR url_context, BSTR url) {} | |
| 43 // This occurs twice on IE >= 7 after window.open calls. | |
| 44 virtual void OnDocumentComplete(IDispatch* dispatch, VARIANT* url_variant) {} | |
| 45 virtual void OnFileDownload(VARIANT_BOOL active_doc, VARIANT_BOOL* cancel) {} | |
| 46 virtual void OnQuit() {} | |
| 47 | |
| 48 // CF callbacks | |
| 49 virtual void OnLoad(const wchar_t* url) {} | |
| 50 virtual void OnLoadError(const wchar_t* url) {} | |
| 51 virtual void OnMessage(const wchar_t* message, const wchar_t* origin, | |
| 52 const wchar_t* source) {} | |
| 53 virtual void OnNewBrowserWindow(IDispatch* new_window, const wchar_t* url) {} | |
| 54 }; | |
| 55 | |
| 56 // Listener for IPropertyNotifySink. | |
| 57 class PropertyNotifySinkListener { | |
| 58 public: | |
| 59 virtual ~PropertyNotifySinkListener() {} | |
| 60 virtual void OnChanged(DISPID dispid) {} | |
| 61 virtual void OnRequestEdit(DISPID dispid) {} | |
| 62 }; | |
| 63 | |
| 64 // This class sets up event sinks to the IWebBrowser interface. It forwards | |
| 65 // all events to its listener. | |
| 66 class IEEventSink | |
| 67 : public CComObjectRootEx<CComSingleThreadModel>, | |
| 68 public IDispEventSimpleImpl<0, IEEventSink, | |
| 69 &DIID_DWebBrowserEvents2>, | |
| 70 public IUnknown { | |
| 71 public: | |
| 72 typedef IDispEventSimpleImpl<0, IEEventSink, | |
| 73 &DIID_DWebBrowserEvents2> DispEventsImpl; | |
| 74 IEEventSink(); | |
| 75 ~IEEventSink(); | |
| 76 | |
| 77 // Launches IE, sets up the sink to forward events to the listener, and | |
| 78 // navigates to the given page. | |
| 79 HRESULT LaunchIEAndNavigate(const std::wstring& navigate_url, | |
| 80 IEEventListener* listener); | |
| 81 | |
| 82 // Navigate to the given url. | |
| 83 HRESULT Navigate(const std::wstring& navigate_url); | |
| 84 | |
| 85 // Listen to events from this |browser_disp|, which should be queryable for | |
| 86 // IWebBrowser2. | |
| 87 void Attach(IDispatch* browser_disp); | |
| 88 | |
| 89 // Listen to events from the given browser. | |
| 90 HRESULT Attach(IWebBrowser2* browser); | |
| 91 | |
| 92 // Stop listening to the associated web browser and possibly wait for it to | |
| 93 // close, if this browser has its own process. | |
| 94 void Uninitialize(); | |
| 95 | |
| 96 // Closes the web browser in such a way that the OnQuit notification will | |
| 97 // be fired when the window closes (async). | |
| 98 HRESULT CloseWebBrowser(); | |
| 99 | |
| 100 // Posts a message to the given target in ChromeFrame. |target| may be "*". | |
| 101 void PostMessageToCF(const std::wstring& message, const std::wstring& target); | |
| 102 | |
| 103 // Set input focus to chrome frame window. | |
| 104 void SetFocusToRenderer(); | |
| 105 | |
| 106 // Send keyboard input to the renderer window hosted in chrome using direct | |
| 107 // key down/up messages. | |
| 108 void SendKeys(const char* input_string); | |
| 109 | |
| 110 // Send mouse click to the renderer window hosted in chrome using | |
| 111 // SendInput API. | |
| 112 void SendMouseClick(int x, int y, simulate_input::MouseButton button); | |
| 113 | |
| 114 // Get the HWND for the browser's main window. Will fail test if window | |
| 115 // not found. | |
| 116 HWND GetBrowserWindow(); | |
| 117 | |
| 118 // Get the HWND for the browser's renderer window. Will fail test if | |
| 119 // renderer window not found. | |
| 120 HWND GetRendererWindow(); | |
| 121 | |
| 122 // Same as above, but does not fail the test if the window cannot be found. | |
| 123 // In that case, the returned handle will be NULL. | |
| 124 HWND GetRendererWindowSafe(); | |
| 125 | |
| 126 // Returns whether CF is rendering the current page. | |
| 127 bool IsCFRendering(); | |
| 128 | |
| 129 // Expect the renderer window to have focus. | |
| 130 void ExpectRendererWindowHasFocus(); | |
| 131 | |
| 132 // Expect the address bar to have |url|. | |
| 133 void ExpectAddressBarUrl(const std::wstring& url); | |
| 134 | |
| 135 // These methods are just simple wrappers of the IWebBrowser2 methods. | |
| 136 // They are needed because you cannot post tasks to IWebBrowser2. | |
| 137 void GoBack() { | |
| 138 web_browser2_->GoBack(); | |
| 139 } | |
| 140 | |
| 141 void GoForward() { | |
| 142 web_browser2_->GoForward(); | |
| 143 } | |
| 144 | |
| 145 void Refresh(); | |
| 146 | |
| 147 void Exec(const GUID* cmd_group_guid, DWORD command_id, | |
| 148 DWORD cmd_exec_opt, VARIANT* in_args, VARIANT* out_args); | |
| 149 | |
| 150 // Set the listener for this sink, which can be NULL. | |
| 151 void set_listener(IEEventListener* listener) { listener_ = listener; } | |
| 152 | |
| 153 IWebBrowser2* web_browser2() { return web_browser2_.get(); } | |
| 154 | |
| 155 // Used only for debugging/logging purposes. | |
| 156 bool reference_count() { return m_dwRef; } | |
| 157 | |
| 158 static void SetAbnormalShutdown(bool abnormal_shutdown); | |
| 159 | |
| 160 private: | |
| 161 void ConnectToChromeFrame(); | |
| 162 void DisconnectFromChromeFrame(); | |
| 163 void FindIEProcessId(); | |
| 164 | |
| 165 // IE callbacks. | |
| 166 BEGIN_COM_MAP(IEEventSink) | |
| 167 COM_INTERFACE_ENTRY(IUnknown) | |
| 168 END_COM_MAP() | |
| 169 | |
| 170 BEGIN_SINK_MAP(IEEventSink) | |
| 171 SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_BEFORENAVIGATE2, | |
| 172 OnBeforeNavigate2, &kBeforeNavigate2Info) | |
| 173 SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_DOWNLOADBEGIN, | |
| 174 OnDownloadBegin, &kVoidMethodInfo) | |
| 175 SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_NAVIGATECOMPLETE2, | |
| 176 OnNavigateComplete2, &kNavigateComplete2Info) | |
| 177 SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_NAVIGATEERROR, | |
| 178 OnNavigateError, &kNavigateErrorInfo) | |
| 179 SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_NEWWINDOW2, | |
| 180 OnNewWindow2, &kNewWindow2Info) | |
| 181 SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_NEWWINDOW3, | |
| 182 OnNewWindow3, &kNewWindow3Info) | |
| 183 SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, | |
| 184 OnDocumentComplete, &kDocumentCompleteInfo) | |
| 185 SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_FILEDOWNLOAD, | |
| 186 OnFileDownload, &kFileDownloadInfo) | |
| 187 SINK_ENTRY_INFO(0, DIID_DWebBrowserEvents2, DISPID_ONQUIT, | |
| 188 OnQuit, &kVoidMethodInfo) | |
| 189 END_SINK_MAP() | |
| 190 | |
| 191 STDMETHOD_(void, OnNavigateError)(IDispatch* dispatch, VARIANT* url, | |
| 192 VARIANT* frame_name, VARIANT* status_code, | |
| 193 VARIANT* cancel); | |
| 194 STDMETHOD(OnBeforeNavigate2)(IDispatch* dispatch, VARIANT* url, | |
| 195 VARIANT* flags, VARIANT* target_frame_name, | |
| 196 VARIANT* post_data, VARIANT* headers, | |
| 197 VARIANT_BOOL* cancel); | |
| 198 STDMETHOD_(void, OnDownloadBegin)(); | |
| 199 STDMETHOD_(void, OnNavigateComplete2)(IDispatch* dispatch, VARIANT* url); | |
| 200 STDMETHOD_(void, OnNewWindow2)(IDispatch** dispatch, VARIANT_BOOL* cancel); | |
| 201 STDMETHOD_(void, OnNewWindow3)(IDispatch** dispatch, VARIANT_BOOL* cancel, | |
| 202 DWORD flags, BSTR url_context, BSTR url); | |
| 203 STDMETHOD_(void, OnDocumentComplete)(IDispatch* dispatch, | |
| 204 VARIANT* url_variant); | |
| 205 STDMETHOD_(void, OnFileDownload)(VARIANT_BOOL active_doc, | |
| 206 VARIANT_BOOL* cancel); | |
| 207 STDMETHOD_(void, OnQuit)(); | |
| 208 | |
| 209 STDMETHOD(Invoke)(DISPID dispid, | |
| 210 REFIID riid, LCID lcid, | |
| 211 WORD flags, | |
| 212 DISPPARAMS* params, | |
| 213 VARIANT* result, | |
| 214 EXCEPINFO* except_info, | |
| 215 UINT* arg_error); | |
| 216 | |
| 217 // IChromeFrame callbacks | |
| 218 HRESULT OnLoad(const VARIANT* param); | |
| 219 HRESULT OnLoadError(const VARIANT* param); | |
| 220 HRESULT OnMessage(const VARIANT* param); | |
| 221 | |
| 222 base::win::ScopedComPtr<IWebBrowser2> web_browser2_; | |
| 223 base::win::ScopedComPtr<IChromeFrame> chrome_frame_; | |
| 224 DispCallback<IEEventSink> onmessage_; | |
| 225 DispCallback<IEEventSink> onloaderror_; | |
| 226 DispCallback<IEEventSink> onload_; | |
| 227 IEEventListener* listener_; | |
| 228 base::ProcessId ie_process_id_; | |
| 229 bool did_receive_on_quit_; | |
| 230 static bool abnormal_shutdown_; | |
| 231 | |
| 232 static _ATL_FUNC_INFO kBeforeNavigate2Info; | |
| 233 static _ATL_FUNC_INFO kNavigateComplete2Info; | |
| 234 static _ATL_FUNC_INFO kNavigateErrorInfo; | |
| 235 static _ATL_FUNC_INFO kNewWindow2Info; | |
| 236 static _ATL_FUNC_INFO kNewWindow3Info; | |
| 237 static _ATL_FUNC_INFO kVoidMethodInfo; | |
| 238 static _ATL_FUNC_INFO kDocumentCompleteInfo; | |
| 239 static _ATL_FUNC_INFO kFileDownloadInfo; | |
| 240 }; | |
| 241 | |
| 242 class PropertyNotifySinkImpl | |
| 243 : public CComObjectRootEx<CComSingleThreadModel>, | |
| 244 public IPropertyNotifySink { | |
| 245 public: | |
| 246 PropertyNotifySinkImpl() : listener_(NULL) { | |
| 247 } | |
| 248 | |
| 249 BEGIN_COM_MAP(PropertyNotifySinkImpl) | |
| 250 COM_INTERFACE_ENTRY(IPropertyNotifySink) | |
| 251 END_COM_MAP() | |
| 252 | |
| 253 STDMETHOD(OnChanged)(DISPID dispid) { | |
| 254 if (listener_) | |
| 255 listener_->OnChanged(dispid); | |
| 256 return S_OK; | |
| 257 } | |
| 258 | |
| 259 STDMETHOD(OnRequestEdit)(DISPID dispid) { | |
| 260 if (listener_) | |
| 261 listener_->OnRequestEdit(dispid); | |
| 262 return S_OK; | |
| 263 } | |
| 264 | |
| 265 void set_listener(PropertyNotifySinkListener* listener) { | |
| 266 DCHECK(listener_ == NULL || listener == NULL); | |
| 267 listener_ = listener; | |
| 268 } | |
| 269 | |
| 270 protected: | |
| 271 PropertyNotifySinkListener* listener_; | |
| 272 }; | |
| 273 | |
| 274 } // namespace chrome_frame_test | |
| 275 | |
| 276 #endif // CHROME_FRAME_TEST_IE_EVENT_SINK_H_ | |
| OLD | NEW |