- add sources.
[platform/framework/web/crosswalk.git] / src / chrome_frame / com_message_event.cc
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 "base/logging.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/strings/utf_string_conversions.h"
11
12 ComMessageEvent::ComMessageEvent() {
13 }
14
15 ComMessageEvent::~ComMessageEvent() {
16 }
17
18 bool ComMessageEvent::Initialize(IOleContainer* container,
19                                  const std::string& message,
20                                  const std::string& origin,
21                                  const std::string& event_type) {
22   DLOG_IF(WARNING, !container) << __FUNCTION__ << " no container";
23   message_ = message;
24   origin_ = origin;
25   type_ = event_type;
26
27   // May remain NULL if container not IE
28   base::win::ScopedComPtr<IHTMLEventObj> basic_event;
29   base::win::ScopedComPtr<IHTMLDocument2> doc;
30
31   // Fetching doc may fail in non-IE containers
32   // and container might be NULL in some applications.
33   if (container)
34     container->QueryInterface(doc.Receive());
35   if (doc) {
36     base::win::ScopedComPtr<IHTMLDocument4> doc4;
37     doc4.QueryFrom(doc);
38     DCHECK(doc4);  // supported by IE5.5 and higher
39     if (doc4) {
40       // IHTMLEventObj5 is only supported in IE8 and later, so we provide our
41       // own (minimalistic) implementation of it.
42       doc4->createEventObject(NULL, basic_event.Receive());
43       DCHECK(basic_event);
44     }
45   }
46
47   basic_event_ = basic_event;
48   return true;
49 }
50
51 STDMETHODIMP ComMessageEvent::GetTypeInfoCount(UINT* info) {
52   // Don't DCHECK as python scripts might still call this function
53   // inadvertently.
54   DLOG(WARNING) << "Not implemented: " << __FUNCTION__;
55   return E_NOTIMPL;
56 }
57
58 STDMETHODIMP ComMessageEvent::GetTypeInfo(UINT which_info, LCID lcid,
59                                           ITypeInfo** type_info) {
60   DLOG(WARNING) << "Not implemented: " << __FUNCTION__;
61   return E_NOTIMPL;
62 }
63
64 STDMETHODIMP ComMessageEvent::GetIDsOfNames(REFIID iid, LPOLESTR* names,
65                                             UINT count_names, LCID lcid,
66                                             DISPID* dispids) {
67   HRESULT hr = S_OK;
68
69   // Note that since we're using LowerCaseEqualsASCII for string comparison,
70   // the second argument _must_ be all lower case.  I.e. we cannot compare
71   // against L"messagePort" since it has a capital 'P'.
72   for (UINT i = 0; SUCCEEDED(hr) && i < count_names; ++i) {
73     const wchar_t* name_begin = names[i];
74     const wchar_t* name_end = name_begin + wcslen(name_begin);
75     if (LowerCaseEqualsASCII(name_begin, name_end, "data")) {
76       dispids[i] = DISPID_MESSAGE_EVENT_DATA;
77     } else if (LowerCaseEqualsASCII(name_begin, name_end, "origin")) {
78       dispids[i] = DISPID_MESSAGE_EVENT_ORIGIN;
79     } else if (LowerCaseEqualsASCII(name_begin, name_end, "lasteventid")) {
80       dispids[i] = DISPID_MESSAGE_EVENT_LAST_EVENT_ID;
81     } else if (LowerCaseEqualsASCII(name_begin, name_end, "source")) {
82       dispids[i] = DISPID_MESSAGE_EVENT_SOURCE;
83     } else if (LowerCaseEqualsASCII(name_begin, name_end, "messageport")) {
84       dispids[i] = DISPID_MESSAGE_EVENT_MESSAGE_PORT;
85     } else if (LowerCaseEqualsASCII(name_begin, name_end, "type")) {
86       dispids[i] = DISPID_MESSAGE_EVENT_TYPE;
87     } else {
88       if (basic_event_) {
89         hr = basic_event_->GetIDsOfNames(IID_IDispatch, &names[i], 1, lcid,
90                                          &dispids[i]);
91       } else {
92         hr = DISP_E_MEMBERNOTFOUND;
93       }
94
95       if (FAILED(hr)) {
96         DLOG(WARNING) << "member not found: " << names[i]
97                       << base::StringPrintf(L"0x%08X", hr);
98       }
99     }
100   }
101   return hr;
102 }
103
104 STDMETHODIMP ComMessageEvent::Invoke(DISPID dispid, REFIID iid, LCID lcid,
105                                      WORD flags, DISPPARAMS* params,
106                                      VARIANT* result, EXCEPINFO* excepinfo,
107                                      UINT* arg_err) {
108   HRESULT hr = DISP_E_MEMBERNOTFOUND;
109   switch (dispid) {
110     case DISPID_MESSAGE_EVENT_DATA:
111       hr = GetStringProperty(flags, UTF8ToWide(message_).c_str(), result);
112       break;
113
114     case DISPID_MESSAGE_EVENT_ORIGIN:
115       hr = GetStringProperty(flags, UTF8ToWide(origin_).c_str(), result);
116       break;
117
118     case DISPID_MESSAGE_EVENT_TYPE:
119       hr = GetStringProperty(flags, UTF8ToWide(type_).c_str(), result);
120       break;
121
122     case DISPID_MESSAGE_EVENT_LAST_EVENT_ID:
123       hr = GetStringProperty(flags, L"", result);
124       break;
125
126     case DISPID_MESSAGE_EVENT_SOURCE:
127     case DISPID_MESSAGE_EVENT_MESSAGE_PORT:
128       if (flags & DISPATCH_PROPERTYGET) {
129         result->vt = VT_NULL;
130         hr = S_OK;
131       } else {
132         hr = DISP_E_TYPEMISMATCH;
133       }
134       break;
135
136     default:
137       if (basic_event_) {
138         hr = basic_event_->Invoke(dispid, iid, lcid, flags, params, result,
139                                   excepinfo, arg_err);
140       }
141       break;
142   }
143
144   return hr;
145 }
146
147 HRESULT ComMessageEvent::GetStringProperty(WORD flags, const wchar_t* value,
148                                            VARIANT* result) {
149   if (!result)
150     return E_INVALIDARG;
151
152   HRESULT hr;
153   if (flags & DISPATCH_PROPERTYGET) {
154     result->vt = VT_BSTR;
155     result->bstrVal = ::SysAllocString(value);
156     hr = S_OK;
157   } else {
158     hr = DISP_E_TYPEMISMATCH;
159   }
160   return hr;
161 }