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 |