15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome_frame/com_message_event.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ComMessageEvent::ComMessageEvent() {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ComMessageEvent::~ComMessageEvent() {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ComMessageEvent::Initialize(IOleContainer* container,
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const std::string& message,
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const std::string& origin,
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const std::string& event_type) {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DLOG_IF(WARNING, !container) << __FUNCTION__ << " no container";
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_ = message;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  origin_ = origin;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  type_ = event_type;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // May remain NULL if container not IE
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IHTMLEventObj> basic_event;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IHTMLDocument2> doc;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fetching doc may fail in non-IE containers
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and container might be NULL in some applications.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (container)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    container->QueryInterface(doc.Receive());
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (doc) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::win::ScopedComPtr<IHTMLDocument4> doc4;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    doc4.QueryFrom(doc);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(doc4);  // supported by IE5.5 and higher
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (doc4) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // IHTMLEventObj5 is only supported in IE8 and later, so we provide our
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // own (minimalistic) implementation of it.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      doc4->createEventObject(NULL, basic_event.Receive());
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(basic_event);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  basic_event_ = basic_event;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STDMETHODIMP ComMessageEvent::GetTypeInfoCount(UINT* info) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't DCHECK as python scripts might still call this function
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // inadvertently.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DLOG(WARNING) << "Not implemented: " << __FUNCTION__;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return E_NOTIMPL;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STDMETHODIMP ComMessageEvent::GetTypeInfo(UINT which_info, LCID lcid,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          ITypeInfo** type_info) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DLOG(WARNING) << "Not implemented: " << __FUNCTION__;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return E_NOTIMPL;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STDMETHODIMP ComMessageEvent::GetIDsOfNames(REFIID iid, LPOLESTR* names,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            UINT count_names, LCID lcid,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            DISPID* dispids) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = S_OK;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that since we're using LowerCaseEqualsASCII for string comparison,
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the second argument _must_ be all lower case.  I.e. we cannot compare
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // against L"messagePort" since it has a capital 'P'.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (UINT i = 0; SUCCEEDED(hr) && i < count_names; ++i) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const wchar_t* name_begin = names[i];
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const wchar_t* name_end = name_begin + wcslen(name_begin);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (LowerCaseEqualsASCII(name_begin, name_end, "data")) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dispids[i] = DISPID_MESSAGE_EVENT_DATA;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (LowerCaseEqualsASCII(name_begin, name_end, "origin")) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dispids[i] = DISPID_MESSAGE_EVENT_ORIGIN;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (LowerCaseEqualsASCII(name_begin, name_end, "lasteventid")) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dispids[i] = DISPID_MESSAGE_EVENT_LAST_EVENT_ID;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (LowerCaseEqualsASCII(name_begin, name_end, "source")) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dispids[i] = DISPID_MESSAGE_EVENT_SOURCE;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (LowerCaseEqualsASCII(name_begin, name_end, "messageport")) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dispids[i] = DISPID_MESSAGE_EVENT_MESSAGE_PORT;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (LowerCaseEqualsASCII(name_begin, name_end, "type")) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dispids[i] = DISPID_MESSAGE_EVENT_TYPE;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (basic_event_) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hr = basic_event_->GetIDsOfNames(IID_IDispatch, &names[i], 1, lcid,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         &dispids[i]);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hr = DISP_E_MEMBERNOTFOUND;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (FAILED(hr)) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DLOG(WARNING) << "member not found: " << names[i]
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      << base::StringPrintf(L"0x%08X", hr);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hr;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STDMETHODIMP ComMessageEvent::Invoke(DISPID dispid, REFIID iid, LCID lcid,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     WORD flags, DISPPARAMS* params,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     VARIANT* result, EXCEPINFO* excepinfo,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     UINT* arg_err) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = DISP_E_MEMBERNOTFOUND;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (dispid) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DISPID_MESSAGE_EVENT_DATA:
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hr = GetStringProperty(flags, UTF8ToWide(message_).c_str(), result);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DISPID_MESSAGE_EVENT_ORIGIN:
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hr = GetStringProperty(flags, UTF8ToWide(origin_).c_str(), result);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DISPID_MESSAGE_EVENT_TYPE:
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hr = GetStringProperty(flags, UTF8ToWide(type_).c_str(), result);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DISPID_MESSAGE_EVENT_LAST_EVENT_ID:
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hr = GetStringProperty(flags, L"", result);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DISPID_MESSAGE_EVENT_SOURCE:
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DISPID_MESSAGE_EVENT_MESSAGE_PORT:
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (flags & DISPATCH_PROPERTYGET) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result->vt = VT_NULL;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hr = S_OK;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hr = DISP_E_TYPEMISMATCH;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (basic_event_) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hr = basic_event_->Invoke(dispid, iid, lcid, flags, params, result,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  excepinfo, arg_err);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hr;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT ComMessageEvent::GetStringProperty(WORD flags, const wchar_t* value,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           VARIANT* result) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return E_INVALIDARG;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (flags & DISPATCH_PROPERTYGET) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->vt = VT_BSTR;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->bstrVal = ::SysAllocString(value);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hr = S_OK;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hr = DISP_E_TYPEMISMATCH;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hr;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
162