| Index: webkit/activex_shim/activex_util.cc
|
| ===================================================================
|
| --- webkit/activex_shim/activex_util.cc (revision 25626)
|
| +++ webkit/activex_shim/activex_util.cc (working copy)
|
| @@ -1,476 +0,0 @@
|
| -// Copyright (c) 2006-2008 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 "webkit/activex_shim/activex_util.h"
|
| -
|
| -#include <exdisp.h>
|
| -#include <math.h>
|
| -#include <ocmm.h>
|
| -
|
| -#include "base/scoped_comptr_win.h"
|
| -#include "base/string_util.h"
|
| -#include "webkit/activex_shim/npp_impl.h"
|
| -#include "webkit/activex_shim/activex_plugin.h"
|
| -
|
| -using std::string;
|
| -using std::wstring;
|
| -
|
| -namespace activex_shim {
|
| -
|
| -#ifdef TRACK_INTERFACE
|
| -
|
| -namespace {
|
| -struct IIDToName {
|
| - IID iid;
|
| - const char* name;
|
| -};
|
| -} // namespace
|
| -
|
| -#define MAP_IID_TO_NAME(name) {IID_##name, #name},
|
| -
|
| -// Map frequently used iid to names. If unknown, return "Unknown:{xxxx-..}".
|
| -static string MapIIDToName(REFIID iid) {
|
| - IIDToName const well_known_interface_names[] = {
|
| - MAP_IID_TO_NAME(IUnknown)
|
| - MAP_IID_TO_NAME(IDispatch)
|
| - MAP_IID_TO_NAME(IParseDisplayName)
|
| - MAP_IID_TO_NAME(IOleContainer)
|
| - MAP_IID_TO_NAME(IOleWindow)
|
| - MAP_IID_TO_NAME(IOleInPlaceUIWindow)
|
| - MAP_IID_TO_NAME(IOleInPlaceFrame)
|
| - MAP_IID_TO_NAME(IHTMLDocument)
|
| - MAP_IID_TO_NAME(IHTMLDocument2)
|
| - MAP_IID_TO_NAME(IHTMLWindow2)
|
| - MAP_IID_TO_NAME(IOleClientSite)
|
| - MAP_IID_TO_NAME(IOleControlSite)
|
| - MAP_IID_TO_NAME(IOleInPlaceSite)
|
| - MAP_IID_TO_NAME(IOleInPlaceSiteEx)
|
| - MAP_IID_TO_NAME(IOleInPlaceSiteWindowless)
|
| - MAP_IID_TO_NAME(IServiceProvider)
|
| - MAP_IID_TO_NAME(IBindHost)
|
| - MAP_IID_TO_NAME(IWebBrowserApp)
|
| - MAP_IID_TO_NAME(ITimerService)
|
| - };
|
| - for (int i = 0; i < arraysize(well_known_interface_names); ++i) {
|
| - if (well_known_interface_names[i].iid == iid)
|
| - return well_known_interface_names[i].name;
|
| - }
|
| - LPOLESTR sz = NULL;
|
| - StringFromIID(iid, &sz);
|
| - string res = string("Unknown:") + WideToUTF8(sz);
|
| - CoTaskMemFree(sz);
|
| - return res;
|
| -}
|
| -
|
| -void TrackQueryInterface(REFIID iid, bool succeeded,
|
| - const char* from_function) {
|
| - string name = MapIIDToName(iid);
|
| - if (succeeded) {
|
| - LOG(INFO) << "Successfully Queried: " << name << " in " \
|
| - << from_function;
|
| - } else {
|
| - LOG(WARNING) << "Failed to Query: " << name << " in " \
|
| - << from_function;
|
| - }
|
| -}
|
| -
|
| -#endif // #ifdef TRACK_INTERFACE
|
| -
|
| -bool NPIdentifierToWString(NPIdentifier name, wstring* ret) {
|
| - if (!g_browser->identifierisstring(name))
|
| - return false;
|
| -
|
| - NPUTF8* str = g_browser->utf8fromidentifier(name);
|
| - *ret = UTF8ToWide(str);
|
| - g_browser->memfree(str);
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool DispGetID(IDispatch* disp, const wchar_t* name, DISPID* dispid) {
|
| - if (disp == NULL)
|
| - return false;
|
| - HRESULT hr = disp->GetIDsOfNames(IID_NULL, const_cast<LPOLESTR*>(&name), 1,
|
| - LOCALE_SYSTEM_DEFAULT, dispid);
|
| - if (FAILED(hr))
|
| - return false;
|
| - return true;
|
| -}
|
| -
|
| -// Get the ITypeInfo of the dispatch interface and look for the FUNCDESC of
|
| -// the member. If not found or disp is NULL, return false.
|
| -static bool DispGetFuncDesc(IDispatch* disp, const wchar_t* name,
|
| - FUNCDESC* func) {
|
| - if (disp == NULL)
|
| - return false;
|
| - bool res = false;
|
| - ScopedComPtr<ITypeInfo> tpi;
|
| - TYPEATTR* typeattr = NULL;
|
| - do {
|
| - HRESULT hr = disp->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, tpi.Receive());
|
| - if (FAILED(hr))
|
| - break;
|
| - hr = tpi->GetTypeAttr(&typeattr);
|
| - if (FAILED(hr))
|
| - break;
|
| -
|
| - MEMBERID memid;
|
| - hr = tpi->GetIDsOfNames(const_cast<LPOLESTR*>(&name), 1, &memid);
|
| - if (FAILED(hr))
|
| - break;
|
| -
|
| - for (int i = 0; i < typeattr->cFuncs && !res; i++) {
|
| - FUNCDESC* funcdesc = NULL;
|
| - hr = tpi->GetFuncDesc(i, &funcdesc);
|
| - if (FAILED(hr))
|
| - continue;
|
| - if (memid == funcdesc->memid) {
|
| - *func = *funcdesc;
|
| - res = true;
|
| - }
|
| - tpi->ReleaseFuncDesc(funcdesc);
|
| - }
|
| - } while(false);
|
| - if (tpi && typeattr)
|
| - tpi->ReleaseTypeAttr(typeattr);
|
| - return res;
|
| -}
|
| -
|
| -bool DispIsMethodOrProperty(IDispatch* disp, const wchar_t* name,
|
| - bool checkmethod) {
|
| - FUNCDESC funcdesc;
|
| - if (DispGetFuncDesc(disp, name, &funcdesc)) {
|
| - // If it has multiple params, for PROPERTYGET, we have to treat it like a
|
| - // method, because the scripting engine will not handle properties with
|
| - // parameters.
|
| - bool is_method = funcdesc.invkind == INVOKE_FUNC || funcdesc.cParams > 0;
|
| - return checkmethod == is_method;
|
| - } else {
|
| - // If it does not have a FUNCDESC, it should be a variable (property) if it
|
| - // has a dispid.
|
| - DISPID dispid;
|
| - if (DispGetID(disp, name, &dispid))
|
| - return checkmethod == false;
|
| - else
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -bool DispSetProperty(IDispatch* disp, const wchar_t* name,
|
| - const VARIANT& rvalue) {
|
| - if (disp == NULL)
|
| - return false;
|
| -
|
| - DISPID dispid;
|
| - if (!DispGetID(disp, name, &dispid))
|
| - return false;
|
| - DISPPARAMS params = {0};
|
| - params.cArgs = 1;
|
| - params.rgvarg = const_cast<VARIANTARG*>(&rvalue);
|
| - DISPID dispid_named = DISPID_PROPERTYPUT;
|
| - params.cNamedArgs = 1;
|
| - params.rgdispidNamedArgs = &dispid_named;
|
| -
|
| - unsigned int argerr;
|
| - ScopedVariant result;
|
| - HRESULT hr = disp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
|
| - DISPATCH_PROPERTYPUT, ¶ms, &result, NULL,
|
| - &argerr);
|
| - return SUCCEEDED(hr);
|
| -}
|
| -
|
| -bool DispInvoke(IDispatch* disp, const wchar_t* name, VARIANT* args,
|
| - int arg_count, VARIANT* result) {
|
| - if (disp == NULL)
|
| - return false;
|
| -
|
| - unsigned int invoke_option;
|
| - DISPID dispid;
|
| - FUNCDESC funcdesc;
|
| - if (DispGetFuncDesc(disp, name, &funcdesc)) {
|
| - dispid = funcdesc.memid;
|
| - switch (funcdesc.invkind) {
|
| - case INVOKE_FUNC:
|
| - invoke_option = DISPATCH_METHOD;
|
| - break;
|
| - case INVOKE_PROPERTYGET:
|
| - invoke_option = DISPATCH_PROPERTYGET;
|
| - break;
|
| - default:
|
| - return false;
|
| - }
|
| - } else {
|
| - // Could be a variable if it doesn't have a FUNCDESC.
|
| - if (DispGetID(disp, name, &dispid))
|
| - invoke_option = DISPATCH_PROPERTYGET;
|
| - else
|
| - return false;
|
| - }
|
| - VariantInit(result);
|
| - DISPPARAMS params = {0};
|
| - params.cArgs = arg_count;
|
| - params.rgvarg = args;
|
| - unsigned int argerr;
|
| -
|
| - HRESULT hr = disp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
|
| - invoke_option, ¶ms, result, NULL, &argerr);
|
| - return SUCCEEDED(hr);
|
| -}
|
| -
|
| -// If the given interface is safe for the flag, return true. Otherwise
|
| -// try to enable the safety option for the flag, return true if succeeded.
|
| -bool TestAndSetObjectSafetyOption(IObjectSafety* object_safety,
|
| - const IID& iid, DWORD flag) {
|
| - DWORD supported_options = 0, enabled_options = 0;
|
| - HRESULT hr = object_safety->GetInterfaceSafetyOptions(iid,
|
| - &supported_options,
|
| - &enabled_options);
|
| - if (SUCCEEDED(hr)) {
|
| - if (enabled_options & flag) {
|
| - return true;
|
| - } else if (supported_options & flag) {
|
| - hr = object_safety->SetInterfaceSafetyOptions(iid, flag, flag);
|
| - if (SUCCEEDED(hr))
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -unsigned long GetAndSetObjectSafetyOptions(IUnknown* control) {
|
| - if (!control)
|
| - return 0;
|
| -
|
| - // If we have the interface then check that first.
|
| - ScopedComPtr<IObjectSafety> object_safety;
|
| - object_safety.QueryFrom(control);
|
| - if (!object_safety)
|
| - return 0;
|
| -
|
| - unsigned long ret = 0;
|
| -
|
| - // Some controls only claim IPersistPropertyBag is safe. The best way
|
| - // would be checking if an interface is safe only when we use it. In reality
|
| - // this is sufficient enough, considering we have a whitelist.
|
| - static IID persist_iids[] = {IID_IPersist, IID_IPersistPropertyBag,
|
| - IID_IPersistPropertyBag2};
|
| - for (int i = 0; i < arraysize(persist_iids); ++i) {
|
| - if (TestAndSetObjectSafetyOption(object_safety, persist_iids[i],
|
| - INTERFACESAFE_FOR_UNTRUSTED_DATA)) {
|
| - ret |= SAFE_FOR_INITIALIZING;
|
| - break;
|
| - }
|
| - }
|
| - if (TestAndSetObjectSafetyOption(object_safety, IID_IDispatch,
|
| - INTERFACESAFE_FOR_UNTRUSTED_CALLER))
|
| - ret |= SAFE_FOR_SCRIPTING;
|
| -
|
| - return ret;
|
| -}
|
| -
|
| -unsigned long GetRegisteredObjectSafetyOptions(const CLSID& clsid) {
|
| - unsigned long ret = 0;
|
| - HRESULT hr;
|
| - ScopedComPtr<ICatInformation> cat_info;
|
| - hr = cat_info.CreateInstance(CLSID_StdComponentCategoriesMgr,
|
| - NULL, CLSCTX_INPROC_SERVER);
|
| - DCHECK(SUCCEEDED(hr));
|
| - if (FAILED(hr))
|
| - return ret;
|
| -
|
| - hr = cat_info->IsClassOfCategories(clsid, 1, &CATID_SafeForInitializing,
|
| - 0, NULL);
|
| - if (hr == S_OK)
|
| - ret |= SAFE_FOR_INITIALIZING;
|
| - hr = cat_info->IsClassOfCategories(clsid, 1, &CATID_SafeForScripting,
|
| - 0, NULL);
|
| - if (hr == S_OK)
|
| - ret |= SAFE_FOR_SCRIPTING;
|
| -
|
| - return ret;
|
| -}
|
| -
|
| -namespace {
|
| -// To allow only querying once for most frequently used device caps.
|
| -struct DeviceCaps {
|
| - DeviceCaps() {
|
| - inited_ = false;
|
| - }
|
| - long GetLogPixelX() {
|
| - Use();
|
| - return log_pixel_x;
|
| - }
|
| - long GetLogPixelY() {
|
| - Use();
|
| - return log_pixel_y;
|
| - }
|
| - private:
|
| - // Purposely make this inline.
|
| - void Use() {
|
| - if (!inited_)
|
| - Init();
|
| - }
|
| - void Init();
|
| -
|
| - bool inited_;
|
| - long log_pixel_x;
|
| - long log_pixel_y;
|
| -};
|
| -
|
| -void DeviceCaps::Init() {
|
| - HDC dc = ::GetWindowDC(NULL);
|
| - log_pixel_x = ::GetDeviceCaps(dc, LOGPIXELSX);
|
| - log_pixel_y = ::GetDeviceCaps(dc, LOGPIXELSY);
|
| - ::ReleaseDC(NULL, dc);
|
| - inited_ = true;
|
| -}
|
| -} // namespace
|
| -
|
| -static DeviceCaps g_devicecaps;
|
| -
|
| -long ScreenToHimetricX(long x) {
|
| - return MulDiv(x, kHimetricPerInch, g_devicecaps.GetLogPixelX());
|
| -}
|
| -
|
| -long ScreenToHimetricY(long y) {
|
| - return MulDiv(y, kHimetricPerInch, g_devicecaps.GetLogPixelY());
|
| -}
|
| -
|
| -void ScreenToHimetric(long cx, long cy, SIZE* size) {
|
| - size->cx = ScreenToHimetricX(cx);
|
| - size->cy = ScreenToHimetricY(cy);
|
| -}
|
| -
|
| -bool VariantToNPVariant(DispatchObject* obj, const VARIANT* vt,
|
| - NPVariant* npv) {
|
| - // TODO(ruijiang): Support more types when necessary.
|
| - switch(vt->vt) {
|
| - case VT_BSTR: {
|
| - npv->type = NPVariantType_String;
|
| - if (vt->bstrVal == NULL) {
|
| - npv->value.stringValue.UTF8Characters = NULL;
|
| - npv->value.stringValue.UTF8Length = 0;
|
| - return true;
|
| - }
|
| - string s;
|
| - s = WideToUTF8(vt->bstrVal);
|
| - // We need to let browser allocate this memory because this will go
|
| - // out of our control and be used/released by the browser.
|
| - npv->value.stringValue.UTF8Characters =
|
| - static_cast<NPUTF8*>(g_browser->memalloc((uint32)s.size()));
|
| - memcpy(static_cast<void*>(const_cast<NPUTF8*>(
|
| - npv->value.stringValue.UTF8Characters)),
|
| - s.c_str(), s.size());
|
| - npv->value.stringValue.UTF8Length = static_cast<uint32>(s.size());
|
| - return true;
|
| - }
|
| - case VT_DISPATCH: {
|
| - SpawnedDispatchObject* disp_object =
|
| - new SpawnedDispatchObject(vt->pdispVal, obj->root());
|
| - npv->type = NPVariantType_Object;
|
| - npv->value.objectValue = disp_object->GetScriptableNPObject();
|
| - return true;
|
| - }
|
| - // All integer types.
|
| - case VT_I1:
|
| - case VT_I2:
|
| - case VT_I4:
|
| - case VT_INT:
|
| - case VT_UI1:
|
| - case VT_UI2:
|
| - case VT_UI4:
|
| - case VT_UINT: {
|
| - ScopedVariant tmp;
|
| - if (FAILED(VariantChangeType(&tmp, vt, 0, VT_I4)))
|
| - return false;
|
| - npv->type = NPVariantType_Int32;
|
| - npv->value.intValue = tmp.lVal;
|
| - return true;
|
| - }
|
| - // Float number types.
|
| - case VT_I8:
|
| - case VT_UI8:
|
| - case VT_CY:
|
| - case VT_R4:
|
| - case VT_R8: {
|
| - ScopedVariant tmp;
|
| - if (FAILED(VariantChangeType(&tmp, vt, 0, VT_R8)))
|
| - return false;
|
| - npv->type = NPVariantType_Double;
|
| - npv->value.doubleValue = tmp.dblVal;
|
| - return true;
|
| - }
|
| - case VT_BOOL: {
|
| - npv->type = NPVariantType_Bool;
|
| - npv->value.boolValue = vt->boolVal != VARIANT_FALSE;
|
| - return true;
|
| - }
|
| - case VT_NULL: {
|
| - npv->type = NPVariantType_Null;
|
| - return true;
|
| - }
|
| - case VT_EMPTY: {
|
| - npv->type = NPVariantType_Void;
|
| - return true;
|
| - }
|
| - default: {
|
| - return false;
|
| - }
|
| - }
|
| -}
|
| -
|
| -bool NPVariantToVariant(const NPVariant* npv, VARIANT* vt) {
|
| - VariantInit(vt);
|
| - switch(npv->type) {
|
| - case NPVariantType_String:
|
| - vt->vt = VT_BSTR;
|
| - if (npv->value.stringValue.UTF8Length > 0) {
|
| - string str;
|
| - str.assign(npv->value.stringValue.UTF8Characters,
|
| - npv->value.stringValue.UTF8Length);
|
| - vt->bstrVal = SysAllocString(UTF8ToWide(str.c_str()).c_str());
|
| - } else {
|
| - vt->bstrVal = NULL;
|
| - }
|
| - return true;
|
| - case NPVariantType_Int32:
|
| - vt->vt = VT_I4;
|
| - vt->intVal = npv->value.intValue;
|
| - return true;
|
| - case NPVariantType_Double:
|
| - vt->vt = VT_R8;
|
| - vt->dblVal = npv->value.doubleValue;
|
| - return true;
|
| - case NPVariantType_Bool:
|
| - vt->vt = VT_BOOL;
|
| - vt->boolVal = npv->value.boolValue ? VARIANT_TRUE : VARIANT_FALSE;
|
| - return true;
|
| - case NPVariantType_Null:
|
| - vt->vt = VT_NULL;
|
| - return true;
|
| - case NPVariantType_Void:
|
| - // According to: http://developer.mozilla.org/en/docs/NPVariant
|
| - // Void type corresponds to JavaScript type: undefined, which means
|
| - // no value has been assigned. Thus VT_EMPTY is the best variant matches
|
| - // void.
|
| - vt->vt = VT_EMPTY;
|
| - return true;
|
| - case NPVariantType_Object:
|
| - // TODO(ruijiang): We probably need to convert NP object to IDispatch,
|
| - // which would be a pretty hard job. (consider the many interfaces of
|
| - // IHTML*).
|
| - return false;
|
| - default:
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -wchar_t* CoTaskMemAllocString(const std::wstring& s) {
|
| - size_t cb = (s.size() + 1) * sizeof(wchar_t);
|
| - LPOLESTR p = static_cast<LPOLESTR>(CoTaskMemAlloc(cb));
|
| - memcpy(p, s.c_str(), cb);
|
| - return p;
|
| -}
|
| -
|
| -} // namespace activex_shim
|
|
|