1 // Copyright (c) 2011 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 #include "chrome_frame/com_message_event.h"
10 #include "testing/gtest/include/gtest/gtest.h"
12 // To allow the unit test read-only access to check protected member variables.
13 class FriendlyComMessageEvent
: public ComMessageEvent
{
15 inline IHTMLEventObj
* basic_event() { return basic_event_
; }
18 class ATL_NO_VTABLE MockDumbContainer
:
19 public CComObjectRoot
,
20 public IOleContainer
{
22 DECLARE_NOT_AGGREGATABLE(MockDumbContainer
)
23 BEGIN_COM_MAP(MockDumbContainer
)
24 COM_INTERFACE_ENTRY(IParseDisplayName
)
25 COM_INTERFACE_ENTRY(IOleContainer
)
28 STDMETHOD(ParseDisplayName
)(IBindCtx
*, LPOLESTR
, ULONG
*, IMoniker
**) {
32 STDMETHOD(EnumObjects
)(DWORD
, IEnumUnknown
**) {
36 STDMETHOD(LockContainer
)(BOOL
) {
42 TEST(ComMessageEvent
, WithDumbContainer
) {
43 CComObject
<MockDumbContainer
>* container_obj
= NULL
;
44 CComObject
<MockDumbContainer
>::CreateInstance(&container_obj
);
45 base::win::ScopedComPtr
<IOleContainer
> container(container_obj
);
46 EXPECT_FALSE(!container
);
48 CComObject
<FriendlyComMessageEvent
>* event_obj
= NULL
;
49 CComObject
<FriendlyComMessageEvent
>::CreateInstance(&event_obj
);
50 base::win::ScopedComPtr
<IUnknown
> event_ref(event_obj
);
52 bool result
= event_obj
->Initialize(container
, "hi", "http://www.foo.com/",
55 EXPECT_TRUE(!event_obj
->basic_event());
58 // Mock object to mimic a "smart" container, e.g. IE, that will
59 // be able to return an IHTMLDocument2 and 4, and from which you
60 // can get an IHTMLEventObj implementation. Doubles as a mock
61 // IHTMLEventObj implementation.
62 class ATL_NO_VTABLE MockSmartContainer
:
63 public CComObjectRoot
,
65 public IHTMLDocument2
,
66 public IHTMLDocument4
,
67 public IHTMLEventObj
{
69 DECLARE_NOT_AGGREGATABLE(MockSmartContainer
)
70 BEGIN_COM_MAP(MockSmartContainer
)
71 COM_INTERFACE_ENTRY_IID(IID_IDispatch
, IHTMLEventObj
)
72 COM_INTERFACE_ENTRY(IParseDisplayName
)
73 COM_INTERFACE_ENTRY(IOleContainer
)
74 COM_INTERFACE_ENTRY(IHTMLDocument
)
75 COM_INTERFACE_ENTRY(IHTMLDocument2
)
76 COM_INTERFACE_ENTRY(IHTMLDocument4
)
77 COM_INTERFACE_ENTRY(IHTMLEventObj
)
80 static const DISPID kDispId
= 424242;
81 static const long kResultValue
= 42;
83 // Only method we actually implement from IHTMLDocument4, to give
84 // out the mock IHTMLEventObj.
85 STDMETHOD(createEventObject
)(VARIANT
*, IHTMLEventObj
** event_obj
) {
86 return GetUnknown()->QueryInterface(event_obj
);
89 // Dummy IDispatch implementation for unit testing, to validate
90 // passthrough semantics.
91 STDMETHOD(GetIDsOfNames
)(REFIID iid
, LPOLESTR
* names
, UINT num_names
,
92 LCID lcid
, DISPID
* disp_ids
) {
93 DCHECK(num_names
== 1);
94 disp_ids
[0] = kDispId
;
98 STDMETHOD(Invoke
)(DISPID id
, REFIID iid
, LCID lcid
, WORD flags
,
99 DISPPARAMS
* disp_params
, VARIANT
* var_result
,
100 EXCEPINFO
* excep_info
, UINT
* arg_error
) {
101 var_result
->vt
= VT_I4
;
102 var_result
->lVal
= kResultValue
;
107 // Do-nothing implementation of the rest of the interface methods.
108 // To make this less verbose, define a macro here and undefine it
109 // at the end of the list.
110 #define STDMETHODNOTIMP(method, parameters) \
111 STDMETHOD(method) parameters { \
117 STDMETHODNOTIMP(GetTypeInfoCount
, (UINT
*));
118 STDMETHODNOTIMP(GetTypeInfo
, (UINT
, LCID
, ITypeInfo
**));
121 STDMETHODNOTIMP(ParseDisplayName
, (IBindCtx
*, LPOLESTR
, ULONG
*, IMoniker
**));
123 STDMETHODNOTIMP(EnumObjects
, (DWORD
, IEnumUnknown
**));
124 STDMETHODNOTIMP(LockContainer
, (BOOL
));
126 STDMETHODNOTIMP(get_Script
, (IDispatch
**));
128 STDMETHODNOTIMP(get_all
, (IHTMLElementCollection
**));
129 STDMETHODNOTIMP(get_body
, (IHTMLElement
**));
130 STDMETHODNOTIMP(get_activeElement
, (IHTMLElement
**));
131 STDMETHODNOTIMP(get_images
, (IHTMLElementCollection
**));
132 STDMETHODNOTIMP(get_applets
, (IHTMLElementCollection
**));
133 STDMETHODNOTIMP(get_links
, (IHTMLElementCollection
**));
134 STDMETHODNOTIMP(get_forms
, (IHTMLElementCollection
**));
135 STDMETHODNOTIMP(get_anchors
, (IHTMLElementCollection
**));
136 STDMETHODNOTIMP(put_title
, (BSTR
));
137 STDMETHODNOTIMP(get_title
, (BSTR
*));
138 STDMETHODNOTIMP(get_scripts
, (IHTMLElementCollection
**));
139 STDMETHODNOTIMP(put_designMode
, (BSTR
));
140 STDMETHODNOTIMP(get_designMode
, (BSTR
*));
141 STDMETHODNOTIMP(get_selection
, (IHTMLSelectionObject
**));
142 STDMETHODNOTIMP(get_readyState
, (BSTR
*));
143 STDMETHODNOTIMP(get_frames
, (IHTMLFramesCollection2
**));
144 STDMETHODNOTIMP(get_embeds
, (IHTMLElementCollection
**));
145 STDMETHODNOTIMP(get_plugins
, (IHTMLElementCollection
**));
146 STDMETHODNOTIMP(put_alinkColor
, (VARIANT
));
147 STDMETHODNOTIMP(get_alinkColor
, (VARIANT
*));
148 STDMETHODNOTIMP(put_bgColor
, (VARIANT
));
149 STDMETHODNOTIMP(get_bgColor
, (VARIANT
*));
150 STDMETHODNOTIMP(put_fgColor
, (VARIANT
));
151 STDMETHODNOTIMP(get_fgColor
, (VARIANT
*));
152 STDMETHODNOTIMP(put_linkColor
, (VARIANT
));
153 STDMETHODNOTIMP(get_linkColor
, (VARIANT
*));
154 STDMETHODNOTIMP(put_vlinkColor
, (VARIANT
));
155 STDMETHODNOTIMP(get_vlinkColor
, (VARIANT
*));
156 STDMETHODNOTIMP(get_referrer
, (BSTR
*));
157 STDMETHODNOTIMP(get_location
, (IHTMLLocation
**));
158 STDMETHODNOTIMP(get_lastModified
, (BSTR
*));
159 STDMETHODNOTIMP(put_URL
, (BSTR
));
160 STDMETHODNOTIMP(get_URL
, (BSTR
*));
161 STDMETHODNOTIMP(put_domain
, (BSTR
));
162 STDMETHODNOTIMP(get_domain
, (BSTR
*));
163 STDMETHODNOTIMP(put_cookie
, (BSTR
));
164 STDMETHODNOTIMP(get_cookie
, (BSTR
*));
165 STDMETHODNOTIMP(put_expando
, (VARIANT_BOOL
));
166 STDMETHODNOTIMP(get_expando
, (VARIANT_BOOL
*));
167 STDMETHODNOTIMP(put_charset
, (BSTR
));
168 STDMETHODNOTIMP(get_charset
, (BSTR
*));
169 STDMETHODNOTIMP(put_defaultCharset
, (BSTR
));
170 STDMETHODNOTIMP(get_defaultCharset
, (BSTR
*));
171 STDMETHODNOTIMP(get_mimeType
, (BSTR
*));
172 STDMETHODNOTIMP(get_fileSize
, (BSTR
*));
173 STDMETHODNOTIMP(get_fileCreatedDate
, (BSTR
*));
174 STDMETHODNOTIMP(get_fileModifiedDate
, (BSTR
*));
175 STDMETHODNOTIMP(get_fileUpdatedDate
, (BSTR
*));
176 STDMETHODNOTIMP(get_security
, (BSTR
*));
177 STDMETHODNOTIMP(get_protocol
, (BSTR
*));
178 STDMETHODNOTIMP(get_nameProp
, (BSTR
*));
179 STDMETHODNOTIMP(write
, (SAFEARRAY
*));
180 STDMETHODNOTIMP(writeln
, (SAFEARRAY
*));
181 STDMETHODNOTIMP(open
, (BSTR
, VARIANT
, VARIANT
, VARIANT
, IDispatch
**));
182 STDMETHODNOTIMP(close
, ());
183 STDMETHODNOTIMP(clear
, ());
184 STDMETHODNOTIMP(queryCommandSupported
, (BSTR
, VARIANT_BOOL
*));
185 STDMETHODNOTIMP(queryCommandEnabled
, (BSTR
, VARIANT_BOOL
*));
186 STDMETHODNOTIMP(queryCommandState
, (BSTR
, VARIANT_BOOL
*));
187 STDMETHODNOTIMP(queryCommandIndeterm
, (BSTR
, VARIANT_BOOL
*));
188 STDMETHODNOTIMP(queryCommandText
, (BSTR
, BSTR
*));
189 STDMETHODNOTIMP(queryCommandValue
, (BSTR
, VARIANT
*));
190 STDMETHODNOTIMP(execCommand
, (BSTR
, VARIANT_BOOL
, VARIANT
, VARIANT_BOOL
*));
191 STDMETHODNOTIMP(execCommandShowHelp
, (BSTR
, VARIANT_BOOL
*));
192 STDMETHODNOTIMP(createElement
, (BSTR
, IHTMLElement
**));
193 STDMETHODNOTIMP(put_onhelp
, (VARIANT
));
194 STDMETHODNOTIMP(get_onhelp
, (VARIANT
*));
195 STDMETHODNOTIMP(put_onclick
, (VARIANT
));
196 STDMETHODNOTIMP(get_onclick
, (VARIANT
*));
197 STDMETHODNOTIMP(put_ondblclick
, (VARIANT
));
198 STDMETHODNOTIMP(get_ondblclick
, (VARIANT
*));
199 STDMETHODNOTIMP(put_onkeyup
, (VARIANT
));
200 STDMETHODNOTIMP(get_onkeyup
, (VARIANT
*));
201 STDMETHODNOTIMP(put_onkeydown
, (VARIANT
));
202 STDMETHODNOTIMP(get_onkeydown
, (VARIANT
*));
203 STDMETHODNOTIMP(put_onkeypress
, (VARIANT
));
204 STDMETHODNOTIMP(get_onkeypress
, (VARIANT
*));
205 STDMETHODNOTIMP(put_onmouseup
, (VARIANT
));
206 STDMETHODNOTIMP(get_onmouseup
, (VARIANT
*));
207 STDMETHODNOTIMP(put_onmousedown
, (VARIANT
));
208 STDMETHODNOTIMP(get_onmousedown
, (VARIANT
*));
209 STDMETHODNOTIMP(put_onmousemove
, (VARIANT
));
210 STDMETHODNOTIMP(get_onmousemove
, (VARIANT
*));
211 STDMETHODNOTIMP(put_onmouseout
, (VARIANT
));
212 STDMETHODNOTIMP(get_onmouseout
, (VARIANT
*));
213 STDMETHODNOTIMP(put_onmouseover
, (VARIANT
));
214 STDMETHODNOTIMP(get_onmouseover
, (VARIANT
*));
215 STDMETHODNOTIMP(put_onreadystatechange
, (VARIANT
));
216 STDMETHODNOTIMP(get_onreadystatechange
, (VARIANT
*));
217 STDMETHODNOTIMP(put_onafterupdate
, (VARIANT
));
218 STDMETHODNOTIMP(get_onafterupdate
, (VARIANT
*));
219 STDMETHODNOTIMP(put_onrowexit
, (VARIANT
));
220 STDMETHODNOTIMP(get_onrowexit
, (VARIANT
*));
221 STDMETHODNOTIMP(put_onrowenter
, (VARIANT
));
222 STDMETHODNOTIMP(get_onrowenter
, (VARIANT
*));
223 STDMETHODNOTIMP(put_ondragstart
, (VARIANT
));
224 STDMETHODNOTIMP(get_ondragstart
, (VARIANT
*));
225 STDMETHODNOTIMP(put_onselectstart
, (VARIANT
));
226 STDMETHODNOTIMP(get_onselectstart
, (VARIANT
*));
227 STDMETHODNOTIMP(elementFromPoint
, (long, long, IHTMLElement
**));
228 STDMETHODNOTIMP(get_parentWindow
, (IHTMLWindow2
**));
229 STDMETHODNOTIMP(get_styleSheets
, (IHTMLStyleSheetsCollection
**));
230 STDMETHODNOTIMP(put_onbeforeupdate
, (VARIANT
));
231 STDMETHODNOTIMP(get_onbeforeupdate
, (VARIANT
*));
232 STDMETHODNOTIMP(put_onerrorupdate
, (VARIANT
));
233 STDMETHODNOTIMP(get_onerrorupdate
, (VARIANT
*));
234 STDMETHODNOTIMP(toString
, (BSTR
*));
235 STDMETHODNOTIMP(createStyleSheet
, (BSTR
, long, IHTMLStyleSheet
**));
237 STDMETHODNOTIMP(focus
, ());
238 STDMETHODNOTIMP(hasFocus
, (VARIANT_BOOL
*));
239 STDMETHODNOTIMP(put_onselectionchange
, (VARIANT
));
240 STDMETHODNOTIMP(get_onselectionchange
, (VARIANT
*));
241 STDMETHODNOTIMP(get_namespaces
, (IDispatch
**));
242 STDMETHODNOTIMP(createDocumentFromUrl
, (BSTR
, BSTR
, IHTMLDocument2
**));
243 STDMETHODNOTIMP(put_media
, (BSTR
));
244 STDMETHODNOTIMP(get_media
, (BSTR
*));
245 STDMETHODNOTIMP(fireEvent
, (BSTR
, VARIANT
*, VARIANT_BOOL
*));
246 STDMETHODNOTIMP(createRenderStyle
, (BSTR
, IHTMLRenderStyle
**));
247 STDMETHODNOTIMP(put_oncontrolselect
, (VARIANT
));
248 STDMETHODNOTIMP(get_oncontrolselect
, (VARIANT
*));
249 STDMETHODNOTIMP(get_URLUnencoded
, (BSTR
*));
251 STDMETHODNOTIMP(get_srcElement
, (IHTMLElement
**))
252 STDMETHODNOTIMP(get_altKey
, (VARIANT_BOOL
*));
253 STDMETHODNOTIMP(get_ctrlKey
, (VARIANT_BOOL
*));
254 STDMETHODNOTIMP(get_shiftKey
, (VARIANT_BOOL
*));
255 STDMETHODNOTIMP(put_returnValue
, (VARIANT
));
256 STDMETHODNOTIMP(get_returnValue
, (VARIANT
*));
257 STDMETHODNOTIMP(put_cancelBubble
, (VARIANT_BOOL
));
258 STDMETHODNOTIMP(get_cancelBubble
, (VARIANT_BOOL
*));
259 STDMETHODNOTIMP(get_fromElement
, (IHTMLElement
**));
260 STDMETHODNOTIMP(get_toElement
, (IHTMLElement
**));
261 STDMETHODNOTIMP(put_keyCode
, (long));
262 STDMETHODNOTIMP(get_keyCode
, (long*));
263 STDMETHODNOTIMP(get_button
, (long*));
264 STDMETHODNOTIMP(get_type
, (BSTR
*));
265 STDMETHODNOTIMP(get_qualifier
, (BSTR
*));
266 STDMETHODNOTIMP(get_reason
, (long*));
267 STDMETHODNOTIMP(get_x
, (long*));
268 STDMETHODNOTIMP(get_y
, (long*));
269 STDMETHODNOTIMP(get_clientX
, (long*));
270 STDMETHODNOTIMP(get_clientY
, (long*));
271 STDMETHODNOTIMP(get_offsetX
, (long*));
272 STDMETHODNOTIMP(get_offsetY
, (long*));
273 STDMETHODNOTIMP(get_screenX
, (long*));
274 STDMETHODNOTIMP(get_screenY
, (long*));
275 STDMETHODNOTIMP(get_srcFilter
, (IDispatch
**));
276 #undef STDMETHODNOTIMP
279 TEST(ComMessageEvent
, WithSmartContainer
) {
280 CComObject
<MockSmartContainer
>* container_obj
= NULL
;
281 CComObject
<MockSmartContainer
>::CreateInstance(&container_obj
);
282 base::win::ScopedComPtr
<IOleContainer
> container(container_obj
);
283 EXPECT_FALSE(!container
);
285 CComObject
<FriendlyComMessageEvent
>* event_obj
= NULL
;
286 CComObject
<FriendlyComMessageEvent
>::CreateInstance(&event_obj
);
287 base::win::ScopedComPtr
<IUnknown
> event_ref(event_obj
);
289 bool succeeded
= event_obj
->Initialize(container
, "hi",
290 "http://www.foo.com/", "message");
291 EXPECT_TRUE(succeeded
);
292 EXPECT_FALSE(!event_obj
->basic_event());
294 // Name handled natively by CF's ComMessageEvent.
296 LPOLESTR name
= L
"data";
297 HRESULT hr
= event_obj
->GetIDsOfNames(IID_IDispatch
, &name
, 1,
298 LOCALE_USER_DEFAULT
, &dispid
);
299 EXPECT_HRESULT_SUCCEEDED(hr
);
300 EXPECT_EQ(dispid
, ComMessageEvent::DISPID_MESSAGE_EVENT_DATA
);
302 // Name not handled by CF's ComMessageEvent.
304 name
= L
"nothandledatallbyanyone";
305 hr
= event_obj
->GetIDsOfNames(IID_IDispatch
, &name
, 1,
306 LOCALE_USER_DEFAULT
, &dispid
);
307 EXPECT_HRESULT_SUCCEEDED(hr
);
308 EXPECT_EQ(dispid
, MockSmartContainer::kDispId
);
310 // Invoke function handled by ComMessageEvent.
311 CComDispatchDriver
dispatcher(event_obj
);
313 hr
= dispatcher
.GetProperty(ComMessageEvent::DISPID_MESSAGE_EVENT_DATA
,
315 EXPECT_HRESULT_SUCCEEDED(hr
);
316 EXPECT_EQ(result
.vt
, VT_BSTR
);
317 EXPECT_EQ(wcscmp(result
.bstrVal
, L
"hi"), 0);
319 // And now check passthrough.
321 hr
= dispatcher
.GetProperty(MockSmartContainer::kDispId
, &result
);
322 EXPECT_HRESULT_SUCCEEDED(hr
);
323 EXPECT_EQ(result
.vt
, VT_I4
);
324 EXPECT_EQ(result
.lVal
, MockSmartContainer::kResultValue
);