Home | History | Annotate | Download | only in test
      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.
      4 
      5 #include "chrome_frame/com_message_event.h"
      6 
      7 #include <atlbase.h>
      8 #include <atlcom.h>
      9 
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 
     12 // To allow the unit test read-only access to check protected member variables.
     13 class FriendlyComMessageEvent : public ComMessageEvent {
     14  public:
     15   inline IHTMLEventObj* basic_event() { return basic_event_; }
     16 };
     17 
     18 class ATL_NO_VTABLE MockDumbContainer :
     19     public CComObjectRoot,
     20     public IOleContainer {
     21  public:
     22   DECLARE_NOT_AGGREGATABLE(MockDumbContainer)
     23   BEGIN_COM_MAP(MockDumbContainer)
     24     COM_INTERFACE_ENTRY(IParseDisplayName)
     25     COM_INTERFACE_ENTRY(IOleContainer)
     26   END_COM_MAP()
     27 
     28   STDMETHOD(ParseDisplayName)(IBindCtx*, LPOLESTR, ULONG*, IMoniker**) {
     29     NOTREACHED();
     30     return E_NOTIMPL;
     31   }
     32   STDMETHOD(EnumObjects)(DWORD, IEnumUnknown**) {
     33     NOTREACHED();
     34     return E_NOTIMPL;
     35   }
     36   STDMETHOD(LockContainer)(BOOL) {
     37     NOTREACHED();
     38     return E_NOTIMPL;
     39   }
     40 };
     41 
     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);
     47 
     48   CComObject<FriendlyComMessageEvent>* event_obj = NULL;
     49   CComObject<FriendlyComMessageEvent>::CreateInstance(&event_obj);
     50   base::win::ScopedComPtr<IUnknown> event_ref(event_obj);
     51 
     52   bool result = event_obj->Initialize(container, "hi", "http://www.foo.com/",
     53                                       "message");
     54   EXPECT_TRUE(result);
     55   EXPECT_TRUE(!event_obj->basic_event());
     56 }
     57 
     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,
     64     public IOleContainer,
     65     public IHTMLDocument2,
     66     public IHTMLDocument4,
     67     public IHTMLEventObj {
     68  public:
     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)
     78   END_COM_MAP()
     79 
     80   static const DISPID kDispId = 424242;
     81   static const long kResultValue = 42;
     82 
     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);
     87   }
     88 
     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;
     95     return S_OK;
     96   }
     97 
     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;
    103     return S_OK;
    104   }
    105 
    106 
    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 { \
    112       NOTREACHED(); \
    113       return E_NOTIMPL; \
    114     }
    115 
    116   // IDispatch
    117   STDMETHODNOTIMP(GetTypeInfoCount, (UINT*));
    118   STDMETHODNOTIMP(GetTypeInfo, (UINT, LCID, ITypeInfo**));
    119 
    120   // IParseDisplayName
    121   STDMETHODNOTIMP(ParseDisplayName, (IBindCtx*, LPOLESTR, ULONG*, IMoniker**));
    122   // IOleContainer
    123   STDMETHODNOTIMP(EnumObjects, (DWORD, IEnumUnknown**));
    124   STDMETHODNOTIMP(LockContainer, (BOOL));
    125   // IHTMLDocument
    126   STDMETHODNOTIMP(get_Script, (IDispatch**));
    127   // IHTMLDocument2
    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**));
    236   // IHTMLDocument4
    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*));
    250   // IHTMLEventObj
    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
    277 };
    278 
    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);
    284 
    285   CComObject<FriendlyComMessageEvent>* event_obj = NULL;
    286   CComObject<FriendlyComMessageEvent>::CreateInstance(&event_obj);
    287   base::win::ScopedComPtr<IUnknown> event_ref(event_obj);
    288 
    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());
    293 
    294   // Name handled natively by CF's ComMessageEvent.
    295   DISPID dispid = -1;
    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);
    301 
    302   // Name not handled by CF's ComMessageEvent.
    303   dispid = -1;
    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);
    309 
    310   // Invoke function handled by ComMessageEvent.
    311   CComDispatchDriver dispatcher(event_obj);
    312   CComVariant result;
    313   hr = dispatcher.GetProperty(ComMessageEvent::DISPID_MESSAGE_EVENT_DATA,
    314                               &result);
    315   EXPECT_HRESULT_SUCCEEDED(hr);
    316   EXPECT_EQ(result.vt, VT_BSTR);
    317   EXPECT_EQ(wcscmp(result.bstrVal, L"hi"), 0);
    318 
    319   // And now check passthrough.
    320   result.Clear();
    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);
    325 }
    326