Index: chrome_frame/com_message_event.cc |
=================================================================== |
--- chrome_frame/com_message_event.cc (revision 0) |
+++ chrome_frame/com_message_event.cc (revision 0) |
@@ -0,0 +1,157 @@ |
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome_frame/com_message_event.h" |
+ |
+#include "base/logging.h" |
+#include "base/string_util.h" |
+ |
+ComMessageEvent::ComMessageEvent() { |
+} |
+ |
+ComMessageEvent::~ComMessageEvent() { |
+} |
+ |
+bool ComMessageEvent::Initialize(IOleContainer* container, |
+ const std::string& message, |
+ const std::string& origin, |
+ const std::string& event_type) { |
+ DCHECK(container); |
+ message_ = message; |
+ origin_ = origin; |
+ type_ = event_type; |
+ |
+ // May remain NULL if container not IE |
+ ScopedComPtr<IHTMLEventObj> basic_event; |
+ ScopedComPtr<IHTMLDocument2> doc; |
+ |
+ // Fetching doc may fail in non-IE containers. |
+ container->QueryInterface(doc.Receive()); |
+ if (doc) { |
+ ScopedComPtr<IHTMLDocument4> doc4; |
+ doc4.QueryFrom(doc); |
+ DCHECK(doc4); // supported by IE5.5 and higher |
+ if (doc4) { |
+ // IHTMLEventObj5 is only supported in IE8 and later, so we provide our |
+ // own (minimalistic) implementation of it. |
+ doc4->createEventObject(NULL, basic_event.Receive()); |
+ DCHECK(basic_event); |
+ } |
+ } |
+ |
+ basic_event_ = basic_event; |
+ return true; |
+} |
+ |
+STDMETHODIMP ComMessageEvent::GetTypeInfoCount(UINT* info) { |
+ // Don't DCHECK as python scripts might still call this function |
+ // inadvertently. |
+ DLOG(WARNING) << "Not implemented: " << __FUNCTION__; |
+ return E_NOTIMPL; |
+} |
+ |
+STDMETHODIMP ComMessageEvent::GetTypeInfo(UINT which_info, LCID lcid, |
+ ITypeInfo** type_info) { |
+ NOTREACHED(); |
+ return E_NOTIMPL; |
+} |
+ |
+STDMETHODIMP ComMessageEvent::GetIDsOfNames(REFIID iid, LPOLESTR* names, |
+ UINT count_names, LCID lcid, |
+ DISPID* dispids) { |
+ HRESULT hr = S_OK; |
+ |
+ // Note that since we're using LowerCaseEqualsASCII for string comparison, |
+ // the second argument _must_ be all lower case. I.e. we cannot compare |
+ // against L"messagePort" since it has a capital 'P'. |
+ for (UINT i = 0; SUCCEEDED(hr) && i < count_names; ++i) { |
+ const wchar_t* name_begin = names[i]; |
+ const wchar_t* name_end = name_begin + wcslen(name_begin); |
+ if (LowerCaseEqualsASCII(name_begin, name_end, "data")) { |
+ dispids[i] = DISPID_MESSAGE_EVENT_DATA; |
+ } else if (LowerCaseEqualsASCII(name_begin, name_end, "origin")) { |
+ dispids[i] = DISPID_MESSAGE_EVENT_ORIGIN; |
+ } else if (LowerCaseEqualsASCII(name_begin, name_end, "lasteventid")) { |
+ dispids[i] = DISPID_MESSAGE_EVENT_LAST_EVENT_ID; |
+ } else if (LowerCaseEqualsASCII(name_begin, name_end, "source")) { |
+ dispids[i] = DISPID_MESSAGE_EVENT_SOURCE; |
+ } else if (LowerCaseEqualsASCII(name_begin, name_end, "messageport")) { |
+ dispids[i] = DISPID_MESSAGE_EVENT_MESSAGE_PORT; |
+ } else if (LowerCaseEqualsASCII(name_begin, name_end, "type")) { |
+ dispids[i] = DISPID_MESSAGE_EVENT_TYPE; |
+ } else { |
+ if (basic_event_) { |
+ hr = basic_event_->GetIDsOfNames(IID_IDispatch, &names[i], 1, lcid, |
+ &dispids[i]); |
+ } else { |
+ hr = DISP_E_MEMBERNOTFOUND; |
+ } |
+ |
+ if (FAILED(hr)) { |
+ DLOG(WARNING) << "member not found: " << names[i] |
+ << StringPrintf(L"0x%08X", hr); |
+ } |
+ } |
+ } |
+ return hr; |
+} |
+ |
+STDMETHODIMP ComMessageEvent::Invoke(DISPID dispid, REFIID iid, LCID lcid, |
+ WORD flags, DISPPARAMS* params, |
+ VARIANT* result, EXCEPINFO* excepinfo, |
+ UINT* arg_err) { |
+ HRESULT hr = DISP_E_MEMBERNOTFOUND; |
+ switch (dispid) { |
+ case DISPID_MESSAGE_EVENT_DATA: |
+ hr = GetStringProperty(flags, UTF8ToWide(message_).c_str(), result); |
+ break; |
+ |
+ case DISPID_MESSAGE_EVENT_ORIGIN: |
+ hr = GetStringProperty(flags, UTF8ToWide(origin_).c_str(), result); |
+ break; |
+ |
+ case DISPID_MESSAGE_EVENT_TYPE: |
+ hr = GetStringProperty(flags, UTF8ToWide(type_).c_str(), result); |
+ break; |
+ |
+ case DISPID_MESSAGE_EVENT_LAST_EVENT_ID: |
+ hr = GetStringProperty(flags, L"", result); |
+ break; |
+ |
+ case DISPID_MESSAGE_EVENT_SOURCE: |
+ case DISPID_MESSAGE_EVENT_MESSAGE_PORT: |
+ if (flags & DISPATCH_PROPERTYGET) { |
+ result->vt = VT_NULL; |
+ hr = S_OK; |
+ } else { |
+ hr = DISP_E_TYPEMISMATCH; |
+ } |
+ break; |
+ |
+ default: |
+ if (basic_event_) { |
+ hr = basic_event_->Invoke(dispid, iid, lcid, flags, params, result, |
+ excepinfo, arg_err); |
+ } |
+ break; |
+ } |
+ |
+ return hr; |
+} |
+ |
+HRESULT ComMessageEvent::GetStringProperty(WORD flags, const wchar_t* value, |
+ VARIANT* result) { |
+ if (!result) |
+ return E_INVALIDARG; |
+ |
+ HRESULT hr; |
+ if (flags & DISPATCH_PROPERTYGET) { |
+ result->vt = VT_BSTR; |
+ result->bstrVal = ::SysAllocString(value); |
+ hr = S_OK; |
+ } else { |
+ hr = DISP_E_TYPEMISMATCH; |
+ } |
+ return hr; |
+} |