diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:20:51 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:20:51 +0000 |
commit | f5b16fed647e941aa66933178da85db2860d639b (patch) | |
tree | f00e9856c04aad3b558a140955e7674add33f051 /webkit/activex_shim | |
parent | 920c091ac3ee15079194c82ae8a7a18215f3f23c (diff) | |
download | chromium_src-f5b16fed647e941aa66933178da85db2860d639b.zip chromium_src-f5b16fed647e941aa66933178da85db2860d639b.tar.gz chromium_src-f5b16fed647e941aa66933178da85db2860d639b.tar.bz2 |
Add webkit to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/activex_shim')
22 files changed, 5409 insertions, 0 deletions
diff --git a/webkit/activex_shim/README b/webkit/activex_shim/README new file mode 100644 index 0000000..4f8ae51 --- /dev/null +++ b/webkit/activex_shim/README @@ -0,0 +1,7 @@ +This project is to support ActiveX controls with a plugin shim. + +Test: + +C:\Program Files\Mozilla Firefox\firefox.exe +C:\Program Files\Opera\Opera.exe +C:\chrome\chrome\Debug\chrome.exe diff --git a/webkit/activex_shim/SConscript b/webkit/activex_shim/SConscript new file mode 100644 index 0000000..5774b4e --- /dev/null +++ b/webkit/activex_shim/SConscript @@ -0,0 +1,73 @@ +# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Import('env')
+
+env = env.Clone()
+
+env.Prepend(
+ CPPPATH = [
+ '$NPAPI_DIR',
+ '#/..',
+ ],
+)
+
+env.Append(
+ CPPDEFINES = [
+ 'TRACK_INTERFACE',
+ ],
+ CCFLAGS = [
+ '/TP',
+
+ '/WX',
+ '/Wp64',
+
+ '/wd4503',
+ '/wd4819',
+ ],
+# TODO(bradnelson): Scons should really have a way to handle this.
+ ARFLAGS = [
+ '/LIBPATH:$PLATFORMSDK_VISTA_REL', 'Urlmon.Lib',
+ ],
+)
+
+input_files = [
+ 'activex_plugin.cc',
+ 'activex_shared.cc',
+ 'activex_util.cc',
+ 'dispatch_object.cc',
+ 'npn_scripting.cc',
+ 'npp_impl.cc',
+ 'web_activex_container.cc',
+ 'web_activex_site.cc',
+]
+
+env.StaticLibrary('activex_shim', input_files)
+
+
diff --git a/webkit/activex_shim/activex_plugin.cc b/webkit/activex_shim/activex_plugin.cc new file mode 100644 index 0000000..e4e0fb8 --- /dev/null +++ b/webkit/activex_shim/activex_plugin.cc @@ -0,0 +1,489 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "webkit/activex_shim/activex_plugin.h" + +#include <algorithm> + +#include "base/fix_wp64.h" +#include "base/string_util.h" +#include "googleurl/src/gurl.h" +#include "webkit/activex_shim/activex_shared.h" +#include "webkit/activex_shim/activex_util.h" +#include "webkit/activex_shim/npp_impl.h" +#include "webkit/activex_shim/npn_scripting.h" +#include "webkit/activex_shim/web_activex_site.h" + +using std::string; +using std::wstring; + +namespace activex_shim { + +// Constant strings used in SetProp. +const wchar_t WNDPROP_ORIGINAL_WNDPROC[] = L"activexshim_orgwndproc"; + +ActiveXPlugin::ActiveXPlugin(NPP instance) + : DispatchObject(NULL), + npp_(instance), + container_(NULL), + windowless_(false), + tried_activation_(false), + control_activated_(false), + activex_type_(ACTIVEX_GENERIC) { + rect_.left = 0; + rect_.top = 0; + rect_.right = 0; + rect_.bottom = 0; +} + +ActiveXPlugin::~ActiveXPlugin() { + // Releases all spawned Dispatch objects so that we won't have dangling + // references. + ReleaseSpawned(); +} + +// Firefox makes it pretty easy to distiguish between attrs and real params. +// it always places attrs first, then a pair with name "PARAM" and empty value. +// However, Chrome always put params first, then attrs. Need to figure out +// a way to handle them nicely. +void ActiveXPlugin::ProcessParams(int16 argc, char* argn[], char* argv[]) { + // TODO(ruijiang): This list is not exhaustive yet. Add all possible + // commmon attributes. + static const char* const excluded_param_names[] = { + "id", "name", "type", "class", "classid", + "codebase", "width", "height" }; + + // Handle parameters. + for (int i = 0; i < argc; i++) { + if (argn[i] == NULL) + continue; + + ControlParam param; + param.name = UTF8ToWide(argn[i]); + // Sometimes browser will pass NULL when no value is present. + if (argv[i] != NULL) { + param.value = UTF8ToWide(argv[i]); + } + if (LowerCaseEqualsASCII(param.name, "classid")) { + std::string clsid_ascii; + if (GetClsidFromClassidAttribute(argv[i], &clsid_ascii)) { + std::wstring raw_clsid = UTF8ToWide(clsid_ascii); + clsid_ = wstring(L"{") + raw_clsid + L"}"; + activex_type_ = MapClassIdToType(clsid_ascii); + } + } + if (LowerCaseEqualsASCII(param.name, "codebase")) { + codebase_ = param.value; + } + bool ignore = false; + for (int i = 0; i < arraysize(excluded_param_names); i++) { + if (LowerCaseEqualsASCII(param.name, excluded_param_names[i])) { + ignore = true; + break; + } + } + if (!ignore) + params_.push_back(param); + } +} + +void ActiveXPlugin::ConvertForEmbeddedWmp() { + clsid_ = L"{6bf52a52-394a-11d3-b153-00c04f79faa6}"; + ControlParam* existing_url_param = NULL; + std::wstring src; + // Find the src parameter and use it to add a new url parameter. + for (unsigned int i = 0; i < params_.size(); i++) { + if (LowerCaseEqualsASCII(params_[i].name, "src")) + src = params_[i].value; + else if (LowerCaseEqualsASCII(params_[i].name, "url")) + existing_url_param = ¶ms_[i]; + } + if (!src.empty()) { + if (existing_url_param == NULL) + params_.push_back(ControlParam(L"url", src)); + else + existing_url_param->value = src; + } +} + +NPError ActiveXPlugin::NPP_New(NPMIMEType plugin_type, int16 argc, char* argn[], + char* argv[], NPSavedData* saved) { + ProcessParams(argc, argn, argv); + + // If mimetype is not activex, it must be windows media type. Do necessary + // param conversion. + if (!IsMimeTypeActiveX(plugin_type)) + ConvertForEmbeddedWmp(); + + DCHECK(container_ == NULL); + container_.reset(new NoRefIUnknownImpl<WebActiveXContainer>); + // At this time we don't know the browser window yet. + container_->Init(this); + HRESULT hr = container_->CreateControlWithSite(clsid_.c_str()); + // TODO(ruijiang): We may still return OK, then show error inside the control + // so that user may get a chance to install it. + if (FAILED(hr)) + return NPERR_GENERIC_ERROR; + + // Does the control support windowless activation? + // TODO(ruijiang): temporary disable windowless plugin cause it's not fully + // working yet. + if (false && container_->GetFirstSite()->inplace_object_windowless_ != NULL) { + // TODO(ruijiang): Fix this. Right now Chrome will never return browser + // window when plugin hasn't set NPPVpluginWindowBool to false yet. + // Fix Chrome then we could remove this line. + g_browser->setvalue(npp_, NPPVpluginWindowBool, false); + // If we could get the container window successfully, we could go + // windowless. + HWND hwnd = NULL; + g_browser->getvalue(npp_, NPNVnetscapeWindow, &hwnd); + if (hwnd) { + container_->set_container_wnd(hwnd); + g_browser->setvalue(npp_, NPPVpluginWindowBool, false); + windowless_ = true; + } else { + g_browser->setvalue(npp_, NPPVpluginWindowBool, + reinterpret_cast<void*>(true)); + } + } + + // TODO(ruijiang): It is very common that controls query for the current url + // during activation. In the current Chrome multi-process structure this + // often causes deadlock (e.g. realplayer). Let's cache the url first while + // looking for ways to solve deadlock. + GetCurrentURL(); + return 0; +} + +void SubclassWindow(HWND hwnd, WNDPROC wndproc) { + LONG_PTR org_wndproc = SetWindowLongPtr( + hwnd, GWL_WNDPROC, reinterpret_cast<LONG_PTR>(wndproc)); + SetProp(hwnd, WNDPROP_ORIGINAL_WNDPROC, + reinterpret_cast<HANDLE>(org_wndproc)); +} + +// Unsubclass a window that has been subclassed by us (has the property +// WNDPROP_ORIGINAL_WNDPROC) +void UnsubclassWindow(HWND hwnd) { + WNDPROC org_wndproc = static_cast<WNDPROC>( + GetProp(hwnd, WNDPROP_ORIGINAL_WNDPROC)); + // Either this window has already been unsubclassed or it is not subclassed + // by us. + if (org_wndproc == NULL) + return; + SetWindowLongPtr(hwnd, + GWL_WNDPROC, + reinterpret_cast<LONG_PTR>(org_wndproc)); + RemoveProp(hwnd, WNDPROP_ORIGINAL_WNDPROC); +} + +// Window procedure to subclass Window created by control. +LRESULT CALLBACK ControlWindowProc(HWND hwnd, UINT msg, + WPARAM wparam, LPARAM lparam) { + WNDPROC org_wndproc = static_cast<WNDPROC>( + GetProp(hwnd, WNDPROP_ORIGINAL_WNDPROC)); + switch(msg) { + case WM_KEYDOWN: + if (wparam == VK_TAB) { + // TODO(ruijiang): Handle the tab key to transfer focus back to browser. + // HWND hparent = GetParent(hwnd); + // HWND hparent2 = GetParent(hparent); + // PostMessage(hparent2, WM_KEYDOWN, wparam, lparam); + // return 0; + } + break; + case WM_DESTROY: + // Unsubclass myself. + UnsubclassWindow(hwnd); + break; + } + if (org_wndproc != NULL) + return CallWindowProc(org_wndproc, hwnd, msg, wparam, lparam); + else + return 0; +} + +// NPP API Processing. +NPError ActiveXPlugin::NPP_SetWindow(NPWindow* window) { + if (window->type != NPWindowTypeWindow && + window->type != NPWindowTypeDrawable) + return NPERR_GENERIC_ERROR; + + // Remember the window position. This position is relative to the browser. + rect_.left = window->x; + rect_.top = window->y; + rect_.right = rect_.left + window->width; + rect_.bottom = rect_.top + window->height; + + RECT client; + client.left = 0; + client.top = 0; + client.right = window->width; + client.bottom = window->height; + + // This happens when we did not create the container because we do not + // allow initialization of certain ActiveX objects. + if (container_ == NULL) + return NPERR_GENERIC_ERROR; + + if (!tried_activation_) { + // Do not try activation again. + tried_activation_ = true; + + // For windowed controls we need to get the plugin window. + if (window->type == NPWindowTypeWindow) + container_->set_container_wnd(static_cast<HWND>(window->window)); + WebActiveXSite* site = container_->GetFirstSite(); + if (site == NULL) + return NPERR_GENERIC_ERROR; + POINT pos; + if (windowless()) { + pos.x = window->x; + pos.y = window->y; + } else { + pos.x = 0; + pos.y = 0; + } + HRESULT hr = site->ActivateControl(pos.x, pos.y, window->width, + window->height, params_); + if (FAILED(hr)) + return NPERR_GENERIC_ERROR; + + // We are done with activation. + control_activated_ = true; + + if (window->type == NPWindowTypeWindow) { + HWND hwnd = static_cast<HWND>(window->window); + // The window some browser (FF) created does not clip children. It will + // cause blinking of the control area during resizing, clicking etc. + SetWindowLong(hwnd, GWL_STYLE, + GetWindowLong(hwnd, GWL_STYLE) | WS_CLIPCHILDREN | + WS_CLIPSIBLINGS); + // If the control has a window, we need to subclass it. + CComQIPtr<IOleWindow> ole_window = container_->GetFirstControl(); + if (ole_window != NULL) { + HWND control_wnd = NULL; + hr = ole_window->GetWindow(&control_wnd); + if (SUCCEEDED(hr)) { + SubclassWindow(control_wnd, ControlWindowProc); + } + } + } + return 0; + } else if (control_activated_) { + WebActiveXSite* site = container_->GetFirstSite(); + DCHECK(site != NULL); + if (window->type == NPWindowTypeWindow) { + site->SetRect(&client); + } else { + site->SetRect(&rect_); + } + return 0; + } else { + return NPERR_GENERIC_ERROR; + } +} + +NPError ActiveXPlugin::NPP_NewStream(NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype) { + return 0; +} + +NPError ActiveXPlugin::NPP_DestroyStream(NPStream* stream, NPReason reason) { + return 0; +} + +int32 ActiveXPlugin::NPP_WriteReady(NPStream* stream) { + // TODO(ruijiang): Now returns an arbitary value. Will handle it later. + return 65536; +} + +int32 ActiveXPlugin::NPP_Write(NPStream* stream, int32 offset, int32 len, + void* buffer) { + // TODO(ruijiang): Pretend we have processed it. Otherwise FireFox will + // pretty much deadlock. + return len; +} + +void ActiveXPlugin::NPP_StreamAsFile(NPStream* stream, const char* fname) { +} + +void ActiveXPlugin::NPP_Print(NPPrint* platformPrint) { +} + +int16 ActiveXPlugin::NPP_HandleEvent(void* event) { + if (!control_activated_) + return NPERR_GENERIC_ERROR; + + NPEvent* evt = static_cast<NPEvent*>(event); + // TODO(ruijiang): Handle various events here for windowless control. + switch (evt->event) { + case WM_PAINT: + return HandlePaintEvent( + reinterpret_cast<HDC>(static_cast<LONG_PTR>(evt->wParam)), + reinterpret_cast<NPRect*>(static_cast<LONG_PTR>(evt->lParam))); + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + case WM_LBUTTONDBLCLK: + case WM_MBUTTONDBLCLK: + case WM_RBUTTONDBLCLK: + case WM_MOUSEMOVE: + case WM_KEYUP: + case WM_KEYDOWN: + case WM_SETFOCUS: + return HandleInputEvent(evt->event, evt->wParam, evt->lParam); + case WM_SETCURSOR: + // TODO(ruijiang): seems we are not getting this message + break; + case WM_KILLFOCUS: + // TODO(ruijiang): We are not getting this message yet. + break; + default: + break; + } + + return 0; +} + +int16 ActiveXPlugin::HandlePaintEvent(HDC dc, NPRect* invalid_area) { + // Chrome sets world transform by a certain offset in some cases, e.g., + // clicking on the control. This will cause unfortunate effect on ActiveX + // control, because some will try to adjust the drawing rect and reset the + // window/view point origin to 0. However, they are not aware of the new + // SetWolrTransform feature. Thus causing drawing off the real control area + // (see atlctl.h: CComControlBase::OnDrawAdvanced) + // On the other hand, FireFox never changes the origins. I've spent hours + // figuring out what went wrong... + int saved = SaveDC(dc); + + POINT offset; + offset.x = offset.y = 0; + // Easy way to figure out the difference between world and device. + LPtoDP(dc, &offset, 1); + RECT rc = rect_; + OffsetRect(&rc, offset.x, offset.y); + + // Reset everything so that device page has the same origin as the world. + SetWindowOrgEx(dc, 0, 0, NULL); + SetViewportOrgEx(dc, 0, 0, NULL); + if (GetGraphicsMode(dc) == GM_ADVANCED) { + XFORM f; + if (GetWorldTransform(dc, &f)) { + f.eDx = 0; + f.eDy = 0; + SetWorldTransform(dc, &f); + } + } + + WebActiveXSite* site = container_->GetFirstSite(); + if (site->view_object_ != NULL) + site->view_object_->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, dc, + reinterpret_cast<RECTL*>(&rc), NULL, NULL, 0); + + RestoreDC(dc, saved); + return 0; +} + +int16 ActiveXPlugin::HandleInputEvent(uint32 msg, uint32 wparam, + uint32 lparam) { + WebActiveXSite* site = container_->GetFirstSite(); + if (site->inplace_object_windowless_ == NULL) + return 0; + LRESULT result; + HRESULT hr = site->inplace_object_windowless_->OnWindowMessage( + msg, wparam, lparam, &result); + return 0; +} + +void ActiveXPlugin::NPP_URLNotify(const char* url, NPReason reason, + void* notifyData) { +} + +NPError ActiveXPlugin::NPP_GetValue(NPPVariable variable, void* value) { + if (variable == NPPVpluginScriptableNPObject) { + *(static_cast<void**>(value)) = GetScriptableNPObject(); + return 0; + } + return NPERR_GENERIC_ERROR; +} + +NPError ActiveXPlugin::NPP_SetValue(NPNVariable variable, void* value) { + // No setable value yet. + return NPERR_GENERIC_ERROR; +} + +void ActiveXPlugin::Draw(HDC dc, RECT* lprc, RECT* lpclip) { + // TODO(ruijiang): Temporary. Fix this later. + int ret = FillRect(dc, lprc, + static_cast<HBRUSH>(GetStockObject(DKGRAY_BRUSH))); + TextOut(dc, lprc->left, lprc->top, _T("HelloWorld"), 5); +} + +IDispatch* ActiveXPlugin::GetDispatch() { + if (container_ == NULL) + return NULL; + IUnknown* unk = container_->GetFirstControl(); + CComQIPtr<IDispatch> disp = unk; + if (disp == NULL) + return NULL; + IDispatch* res = disp.Detach(); + res->Release(); + return res; +} + +NPNScriptableObject ActiveXPlugin::GetWindow() { + if (!window_.IsValid()) { + NPObject* object = NULL; + g_browser->getvalue(npp_, NPNVWindowNPObject, &object); + window_ = NPNScriptableObject(npp_, object); + } + return window_; +} + +std::wstring ActiveXPlugin::GetCurrentURL() { + if (url_.size()) + return url_; + url_ = GetWindow().GetObjectProperty("document").GetStringProperty("URL"); + return url_; +} + +std::wstring ActiveXPlugin::ResolveURL(const std::wstring& url) { + // TODO(ruijiang): consider the base element of document. + std::wstring doc_url = GetCurrentURL(); + GURL base(doc_url); + GURL ret = base.Resolve(url); + return UTF8ToWide(ret.spec()); +} + + +} // namespace activex_shim diff --git a/webkit/activex_shim/activex_plugin.h b/webkit/activex_shim/activex_plugin.h new file mode 100644 index 0000000..add1589 --- /dev/null +++ b/webkit/activex_shim/activex_plugin.h @@ -0,0 +1,128 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef WEBKIT_ACTIVEX_SHIM_ACTIVEX_PLUGIN_H__ +#define WEBKIT_ACTIVEX_SHIM_ACTIVEX_PLUGIN_H__ + +#include <string> +#include <vector> +#include "base/scoped_ptr.h" +#include "webkit/glue/plugins/nphostapi.h" +#include "webkit/activex_shim/activex_shared.h" +#include "webkit/activex_shim/dispatch_object.h" +#include "webkit/activex_shim/npn_scripting.h" +#include "webkit/activex_shim/web_activex_container.h" +#include "webkit/activex_shim/web_activex_site.h" + +namespace activex_shim { + +// ActiveXPlugin, a host for ActiveX control. There is one ActiveXPlugin object +// for each ActiveX control. It handles NPAPI calls from the browser side +// and is responsible for most activities of the plugin. +class ActiveXPlugin : public DispatchObject { + public: + explicit ActiveXPlugin(NPP instance); + ~ActiveXPlugin(); + + // NPP API Processing. + NPError NPP_New(NPMIMEType plugin_type, int16 argc, char* argn[], + char* argv[], NPSavedData* saved); + NPError NPP_SetWindow(NPWindow* window); + NPError NPP_NewStream(NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype); + NPError NPP_DestroyStream(NPStream* stream, NPReason reason); + int32 NPP_WriteReady(NPStream* stream); + int32 NPP_Write(NPStream* stream, int32 offset, int32 len, void* buffer); + void NPP_StreamAsFile(NPStream* stream, const char* fname); + void NPP_Print(NPPrint* platformPrint); + int16 NPP_HandleEvent(void* event); + void NPP_URLNotify(const char* url, NPReason reason, void* notifyData); + NPError NPP_GetValue(NPPVariable variable, void* value); + NPError NPP_SetValue(NPNVariable variable, void* value); + + void Draw(HDC dc, RECT* lprc, RECT* lpclip); + + // Get scriptable window object from the browser. + NPNScriptableObject GetWindow(); + // Retrieves the URL of current webpage from the browser. + std::wstring GetCurrentURL(); + // Resolves the relative URL (could be already an absolute URL too) to return + // full URL based on current document's URL and base. + std::wstring ResolveURL(const std::wstring& url); + bool windowless() { return windowless_; } + NPP npp() { return npp_; } + ActiveXTypes activex_type() { return activex_type_; } + + private: + // Process parameters passed in from browser. + void ProcessParams(int16 argc, char* argn[], char* argv[]); + // For handling wmp mime type, we need to initialize params differently + // (change src to corresponding param for wmp control), and set clsid to wmp. + void ConvertForEmbeddedWmp(); + + // Overrided functions of base class: DispatchObject. + virtual IDispatch* GetDispatch(); + virtual NPP GetNPP() { return npp_; } + virtual bool NPObjectOwnsMe() { return false; } + + // Event handlers for windowless plugin. + int16 HandlePaintEvent(HDC dc, NPRect* invalid_area); + int16 HandleInputEvent(uint32 msg, uint32 wparam, uint32 lparam); + + // Related NPP instance. + NPP npp_; + // Position of the control relative to the browser. + RECT rect_; + // Initialization parameters from param tags and object tag. + std::vector<ControlParam> params_; + // Clsid of the activex object. + std::wstring clsid_; + std::wstring codebase_; + // At this point every plugin has one container. It simplifies things. + scoped_ptr<WebActiveXContainer> container_; + // True if the control supports windowless and we are creating a windowless + // plugin. + bool windowless_; + // Have we ever tried to activate the control. + bool tried_activation_; + // Whether we have successfully created the control and activated it. + bool control_activated_; + // Initially this is not initialized. We assign it on the first call to + // GetWindow, then we will keep this copy. + NPNScriptableObject window_; + ActiveXTypes activex_type_; + // Cache of the current url. It is used very frequently. + std::wstring url_; + + DISALLOW_EVIL_CONSTRUCTORS(ActiveXPlugin); +}; + +} // namespace activex_shim + +#endif // #ifndef WEBKIT_ACTIVEX_SHIM_ACTIVEX_PLUGIN_H__ diff --git a/webkit/activex_shim/activex_shared.cc b/webkit/activex_shim/activex_shared.cc new file mode 100644 index 0000000..46ba5f6 --- /dev/null +++ b/webkit/activex_shim/activex_shared.cc @@ -0,0 +1,253 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "webkit/activex_shim/activex_shared.h" + +#include <windows.h> +#include "base/command_line.h" +#include "base/file_version_info.h" +#include "base/string_util.h" +#include "base/registry.h" +#include "googleurl/src/gurl.h" + +namespace activex_shim { + +namespace { +struct ActiveXAttribute { + const char* clsid; + ActiveXTypes type; + // allowed_sites is a (list) of simple patterns of sites. Rules are: + // - if pattern is empty or NULL pointer, no sites are allowed. + // - sites are separated by ";" + // - "*" will match any sites. + // - "file" matches file url starts with "file://" + // - anything else matches the last part of the host. + // e.g. "95559.com;ecitic.com" allows controls running from 95559.com and + // ecitic.com. + // See MatchUrlForSinglePattern for details. + const char* allowed_sites; + const char* allowed_codebase_sites; +}; +} // unnamed namespace. + +static const ActiveXAttribute activex_attributes[] = { + {"d27cdb6e-ae6d-11cf-96b8-444553540000", ACTIVEX_FLASH}, + // WMP 7 and later + {"6bf52a52-394a-11d3-b153-00c04f79faa6", ACTIVEX_WMP, "*", "microsoft.com"}, + // WMP 6.4 + {"22d6f312-b0f6-11d0-94ab-0080c74c7e95", ACTIVEX_WMP, "*", "microsoft.com"}, + {"cfcdaa03-8be4-11cf-b84b-0020afbbccfa", ACTIVEX_REALPLAYER}, + {"02bf25d5-8c17-4b23-bc80-d3488abddc6b", ACTIVEX_QUICKTIME}, + {"166b1bca-3f9c-11cf-8075-444553540000", ACTIVEX_SHOCKWAVE}, + {"4e174456-5ee6-494d-b6f2-2b52898a620e", ACTIVEX_TESTCONTROL, "file"}, +}; + +// See chrome_switches.cc, switches::kAllowAllActiveX. We duplicate the value +// here to avoid dependency on Chrome. +static const wchar_t kAllowAllActiveX[] = L"allow-all-activex"; + +static const ActiveXAttribute* FindActiveX(const std::string& clsid) { + for (unsigned int i = 0; i < arraysize(activex_attributes); ++i) { + if (LowerCaseEqualsASCII(clsid, activex_attributes[i].clsid)) + return &activex_attributes[i]; + } + return NULL; +} + +ActiveXTypes MapClassIdToType(const std::string& clsid) { + const ActiveXAttribute* attr = FindActiveX(clsid); + if (attr != NULL) + return attr->type; + else + return ACTIVEX_GENERIC; +} + +bool MatchUrlForSinglePattern(const GURL& url, const std::string& pattern) { + if (pattern.empty()) + return false; + if (pattern == "*") + return true; + if (pattern == "file") + return url.SchemeIsFile(); + return url.DomainIs(pattern.c_str()); +} + +bool MatchUrlForPatterns(const GURL& url, const std::string& patterns) { + std::vector<std::string> v; + SplitString(patterns, ';', &v); + for (unsigned int i = 0; i < v.size(); ++i) { + if (MatchUrlForSinglePattern(url, v[i])) + return true; + } + return false; +} + +// Whether allow-all-activex is specified in the command line. +static bool IsAllowAllActiveX() { + static bool parsed_flag = false; + static bool allow_all_activex = false; + if (!parsed_flag) { + CommandLine command_line; + allow_all_activex = command_line.HasSwitch(kAllowAllActiveX); + parsed_flag = true; + } + return allow_all_activex; +} + +// If an ActiveX control is allowed to run from a specific URL. +bool IsActiveXAllowed(const std::string& clsid, const GURL& url) { + if (IsAllowAllActiveX()) + return true; + const ActiveXAttribute* attr = FindActiveX(clsid); + if (attr == NULL) + return false; + if (attr->allowed_sites == NULL) + return false; + return MatchUrlForPatterns(url, attr->allowed_sites); +} + +// If an ActiveX control's codebase comes from allowed websites. +bool IsCodebaseAllowed(const std::string& clsid, const std::string& codebase) { + if (IsAllowAllActiveX()) + return true; + GURL url(codebase); + const ActiveXAttribute* attr = FindActiveX(clsid); + if (attr == NULL) + return false; + if (attr->allowed_codebase_sites == NULL) + return false; + return MatchUrlForPatterns(url, attr->allowed_codebase_sites); +} + +bool GetClsidFromClassidAttribute(const std::string& classid, + std::string* clsid) { + const unsigned int kClsidPrefixSize = 6; + if (classid.size() > kClsidPrefixSize) { + std::string prefix = classid.substr(0, kClsidPrefixSize); + if (LowerCaseEqualsASCII(prefix, "clsid:")) { + TrimWhitespace(classid.substr(kClsidPrefixSize), TRIM_ALL, clsid); + return true; + } + } + return false; +} + +std::string GetVersionFromCodebaseAttribute(const std::string& codebase) { + std::string version; + size_t pos = codebase.find('#'); + if (pos == std::string::npos) + return version; + std::string rest = codebase.substr(pos + 1); + std::string version_prefix = "version="; + if (!StartsWithASCII(rest, "version=", false)) + return version; + size_t i; + for (i = version_prefix.size(); i < rest.size(); i++) { + char c = rest[i]; + if (c != ',' && (c > '9' || c < '0')) + break; + } + return rest.substr(version_prefix.size(), i - version_prefix.size()); +} + +// The version string should always be in the form of "1,2,0,4". +static bool ParseVersionFromCodebase(const std::string& version, + DWORD* version_ms, + DWORD* version_ls) { + *version_ms = 0; + *version_ls = 0; + std::vector<int> v; + std::vector<std::string> sv; + SplitString(version, ',', &sv); + for (size_t i = 0; i < sv.size(); ++i) + v.push_back(atoi(sv[i].c_str())); + if (v.size() != 4) + return false; + *version_ms = MAKELONG(v[1], v[0]); + *version_ls = MAKELONG(v[3], v[2]); + return true; +} + +bool IsActiveXInstalled(const std::string& combined_clsid) { + std::string clsid, version; + size_t pos = combined_clsid.find('#'); + if (pos == std::string::npos) { + clsid = combined_clsid; + } else { + clsid = combined_clsid.substr(0, pos); + version = combined_clsid.substr(pos + 1); + } + RegKey key; + std::wstring key_path = std::wstring(L"CLSID\\{") + ASCIIToWide(clsid) + L"}"; + if (!key.Open(HKEY_CLASSES_ROOT, key_path.c_str(), KEY_READ)) + return false; + // If no specific version is required, any installed version would be fine. + if (version.empty()) + return true; + DWORD requested_version_ms = 0; + DWORD requested_version_ls = 0; + if (!ParseVersionFromCodebase(version, + &requested_version_ms, + &requested_version_ls)) + return true; + // Get the path to the dll. + std::wstring path; + RegKey(HKEY_CLASSES_ROOT, (key_path + L"\\InprocServer32").c_str()). + ReadValue(NULL, &path); + if (path.empty()) + return false; + + // Get the file version from the dll. + DWORD file_version_ms, file_version_ls; + FileVersionInfo* vi = FileVersionInfo::CreateFileVersionInfo(path); + if (vi == NULL) + return false; + if (vi->fixed_file_info() == NULL) { + delete vi; + return false; + } + file_version_ms = vi->fixed_file_info()->dwFileVersionMS; + file_version_ls = vi->fixed_file_info()->dwFileVersionLS; + delete vi; + + // Compare the request version and actual file version. + if (file_version_ms > requested_version_ms) + return true; + else if (file_version_ms < requested_version_ms) + return false; + else + return file_version_ls >= requested_version_ls; +} + +bool IsMimeTypeActiveX(const std::string& mimetype) { + return LowerCaseEqualsASCII(mimetype, "application/x-oleobject") || + LowerCaseEqualsASCII(mimetype, "application/oleobject"); +} + +} // namespace activex_shim diff --git a/webkit/activex_shim/activex_shared.h b/webkit/activex_shim/activex_shared.h new file mode 100644 index 0000000..65679aa --- /dev/null +++ b/webkit/activex_shim/activex_shared.h @@ -0,0 +1,91 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Thes file contains stuff that should be shared among projects that do some +// special handling with ActiveX. + +#ifndef WEBKIT_ACTIVEX_SHIM_ACTIVEX_SHARED_H__ +#define WEBKIT_ACTIVEX_SHIM_ACTIVEX_SHARED_H__ + +#include <string> + +class GURL; + +namespace activex_shim { + +// Well known ActiveX control types that we may need to do special processing +// to support them better. +enum ActiveXTypes { + ACTIVEX_GENERIC, + ACTIVEX_FLASH, + ACTIVEX_WMP, + ACTIVEX_REALPLAYER, + ACTIVEX_QUICKTIME, + ACTIVEX_SHOCKWAVE, + ACTIVEX_TESTCONTROL, // Internal test control. +}; + +// Given a clsid, map it to ActiveXTypes. The given clsid must be in format +// as: d27cdb6e-ae6d-11cf-96b8-444553540000. i.e. no {} at both ends, +// no spaces, case insensitive. +ActiveXTypes MapClassIdToType(const std::string& clsid); + +// Parse out the real clsid given from a classid attribute of an object tag. +// the classid string should be in format as: +// clsid:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX +bool GetClsidFromClassidAttribute(const std::string& classid, + std::string* clsid); + +// Get version string from codebase attribute of an object tag. e.g.: +// codebase="https://site.cmbchina.com/download/CMBEdit.cab#version=1,2,0,1", +// then we will return "1,2,0,1". if the version part doesn't exist, +// returns empty string. +std::string GetVersionFromCodebaseAttribute(const std::string& codebase); + +// Look up the registry to see if ActiveX is installed. Here clsid could be just +// clsid, e.g. "0CA54D3F-CEAE-48AF-9A2B-31909CB9515D". Or it could be combined +// with a version string comes from the codebase: +// "0CA54D3F-CEAE-48AF-9A2B-31909CB9515D#1,2,0,1". In the latter case, we need +// to look up the version info of the dll to see if it meets the version +// requirement. +bool IsActiveXInstalled(const std::string& combined_clsid); + +// If an ActiveX control is allowed to run from a specific URL. +bool IsActiveXAllowed(const std::string& clsid, const GURL& url); + +// If an ActiveX control's codebase comes from allowed websites. +bool IsCodebaseAllowed(const std::string& clsid, const std::string& codebase); + +// Check If a given mimetype is of "application/x-oleobject" or +// "application/oleobject" +bool IsMimeTypeActiveX(const std::string& mimetype); + +} // namespace activex_shim + +#endif // #ifndef WEBKIT_ACTIVEX_SHIM_ACTIVEX_SHARED_H__ diff --git a/webkit/activex_shim/activex_shim.vcproj b/webkit/activex_shim/activex_shim.vcproj new file mode 100644 index 0000000..26d4adc --- /dev/null +++ b/webkit/activex_shim/activex_shim.vcproj @@ -0,0 +1,204 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="activex_shim" + ProjectGUID="{F4F4BCAA-EA59-445C-A119-3E6C29647A51}" + RootNamespace="activex_shim" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="4" + InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;.\activex_shim.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + PreprocessorDefinitions="TRACK_INTERFACE" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="4" + InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;.\activex_shim.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <File + RelativePath=".\activex_plugin.cc" + > + </File> + <File + RelativePath=".\activex_plugin.h" + > + </File> + <File + RelativePath=".\activex_shared.cc" + > + </File> + <File + RelativePath=".\activex_shared.h" + > + </File> + <File + RelativePath=".\activex_util.cc" + > + </File> + <File + RelativePath=".\activex_util.h" + > + </File> + <File + RelativePath=".\dispatch_object.cc" + > + </File> + <File + RelativePath=".\dispatch_object.h" + > + </File> + <File + RelativePath=".\ihtmldocument_impl.h" + > + </File> + <File + RelativePath=".\iwebbrowser_impl.h" + > + </File> + <File + RelativePath=".\npn_scripting.cc" + > + </File> + <File + RelativePath=".\npn_scripting.h" + > + </File> + <File + RelativePath=".\npp_impl.cc" + > + </File> + <File + RelativePath=".\npp_impl.h" + > + </File> + <File + RelativePath=".\README" + > + </File> + <File + RelativePath=".\web_activex_container.cc" + > + </File> + <File + RelativePath=".\web_activex_container.h" + > + </File> + <File + RelativePath=".\web_activex_site.cc" + > + </File> + <File + RelativePath=".\web_activex_site.h" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/webkit/activex_shim/activex_shim.vsprops b/webkit/activex_shim/activex_shim.vsprops new file mode 100644 index 0000000..77b6090 --- /dev/null +++ b/webkit/activex_shim/activex_shim.vsprops @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="activex_shim" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\third_party\npapi\using_npapi.vsprops" + > + <Tool + Name="VCLibrarianTool" + AdditionalDependencies="urlmon.lib" + /> +</VisualStudioPropertySheet> diff --git a/webkit/activex_shim/activex_util.cc b/webkit/activex_shim/activex_util.cc new file mode 100644 index 0000000..f7f218b --- /dev/null +++ b/webkit/activex_shim/activex_util.cc @@ -0,0 +1,495 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "webkit/activex_shim/activex_util.h" + +#include <exdisp.h> +#include <math.h> +#include <ocmm.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; + CComPtr<ITypeInfo> tpi; + TYPEATTR* typeattr = NULL; + do { + HRESULT hr = disp->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &tpi); + 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) { + unsigned long ret = 0; + + // If we have the interface then check that first. + CComQIPtr<IObjectSafety> object_safety = control; + if (object_safety != NULL) { + // 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; + CComPtr<ICatInformation> cat_info; + hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, + NULL, CLSCTX_INPROC_SERVER, IID_ICatInformation, + reinterpret_cast<void**>(&cat_info)); + 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 diff --git a/webkit/activex_shim/activex_util.h b/webkit/activex_shim/activex_util.h new file mode 100644 index 0000000..122fe1f --- /dev/null +++ b/webkit/activex_shim/activex_util.h @@ -0,0 +1,192 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef WEBKIT_ACTIVEX_SHIM_ACTIVEX_UTIL_H__ +#define WEBKIT_ACTIVEX_SHIM_ACTIVEX_UTIL_H__ + +#include <windows.h> +#include <comdef.h> +#include <string> +#include "base/logging.h" +#include "webkit/glue/plugins/nphostapi.h" + +namespace activex_shim { + +class DispatchObject; + +// Logging +#ifdef TRACK_INTERFACE +#define TRACK_METHOD() LOG(INFO) << "Called: " << __FUNCTION__ +#define TRACK_QUERY_INTERFACE(iid, succeeded) \ + TrackQueryInterface(iid, succeeded, __FUNCTION__) +#else +#define TRACK_METHOD() +#define TRACK_QUERY_INTERFACE(iid, succeeded) +#endif + +// Unfortunately this value is not defined in any Windows header. +const int kHimetricPerInch = 2540; + +// Used in macro to log which interface is queried and if it is successful. +void TrackQueryInterface(REFIID iid, bool succeeded, const char* from_function); + +// NP types conversions +bool NPIdentifierToWString(NPIdentifier name, std::wstring* ret); +bool VariantToNPVariant(DispatchObject* obj, const VARIANT* vt, NPVariant* npv); +bool NPVariantToVariant(const NPVariant* npv, VARIANT* vt); + +// Dispatch interface helpers +bool DispGetID(IDispatch* disp, const wchar_t* name, DISPID* dispid); +bool DispIsMethodOrProperty(IDispatch* disp, const wchar_t* name, + bool checkmethod); +// This is a general invoke function. Use this function to call methods or +// get properties. +// DO NOT use this function to set properties. Use DispSetProperty instead. +bool DispInvoke(IDispatch* disp, const wchar_t* name, VARIANT* args, + int arg_count, VARIANT* result); +// A special version for PROPERTYSET. +bool DispSetProperty(IDispatch* disp, const wchar_t* name, + const VARIANT& rvalue); + +// ActiveX object security +enum ActiveXSafety { + SAFE_FOR_SCRIPTING = 0x1, + SAFE_FOR_INITIALIZING = 0x2, +}; + +// Gets the IObjectSafety interface of the control and set its safe options. +unsigned long GetAndSetObjectSafetyOptions(IUnknown* control); +// Uses the StdComponentCategoriesMgr to determine the safety options the object +// registered. +unsigned long GetRegisteredObjectSafetyOptions(const CLSID& clsid); + +// Coord transformation +// Screen coord to Himetric coord. +long ScreenToHimetricX(long x); +long ScreenToHimetricY(long y); +void ScreenToHimetric(long cx, long cy, SIZE* size); + +// Create a copy of the string with memory allocated by CoTaskMemAlloc +wchar_t* CoTaskMemAllocString(const std::wstring& s); + +// Reference counted IUnknown implementation. +template <class Base> class IUnknownImpl : public Base { + public: + IUnknownImpl() : ref_(1) { + } + // IUnknown + virtual ULONG STDMETHODCALLTYPE AddRef() { return ++ref_; } + virtual ULONG STDMETHODCALLTYPE Release() { + --ref_; + if (ref_ == 0) { + delete this; + } + } + // We don't add QueryInterface here cause normally the subclass should + // have its own implementation. + + private: + ULONG ref_; +}; + +// The original CComObject does reference counting and delete object when +// reference count reaches 0. This is not desirable for us. If an ActiveX +// control incorrectly decrease our reference, then we will crash. Thus +// let's manage our own life! +template <class Base> class NoRefIUnknownImpl : public Base { + public: + ~NoRefIUnknownImpl() { + // Let the base class clean up before destruction. It's dangerous for base + // class to do cleanup in destructor, because we usually create the + // object as: NoRefIUnknownImpl<WebActiveXSite>. So when it + // destructs, the outer NoRefIUnknownImpl destructs first, then virtual + // table pointer of IUnknown interface is modified. At this time if we call + // control's code like IOleInPlaceObject::InPlaceDeactivate, and it calls + // back to IUnknown of myself, it will cause "pure function call" exception. + // + // Using a FinalRelease is what ATL does. I found the reason after getting + // the crashes in base class' destructor. + FinalRelease(); + } + // IUnknown + virtual ULONG STDMETHODCALLTYPE AddRef() { return 1; } + virtual ULONG STDMETHODCALLTYPE Release() { return 0; } + // We don't add QueryInterface here cause normally the subclass should + // have its own implementation. +}; + +// A Minimum IDispatch implementation. Used for other classes who need +// the interface but lazy to implement all the typeinfo etc. +class MinimumIDispatchImpl : public IDispatch { + public: + virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* ctinfo) { + *ctinfo = 0; + return S_OK; + } + virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT itinfo, LCID lcid, + ITypeInfo** tinfo) { + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames( + REFIID riid, + LPOLESTR* names, + UINT cnames, + LCID lcid, + DISPID* dispids) { + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE Invoke( + DISPID dispid, + REFIID riid, + LCID lcid, + WORD flags, + DISPPARAMS* params, + VARIANT* result, + EXCEPINFO* except_info, + UINT* arg_error) { + return E_NOTIMPL; + } +}; + +// This struct is a simple wrap of VARIANT type, so that it could automatically +// initialize when constructed and clear when destructed. +// DO NOT add any virtual function or variable members to this struct, because +// it could be used in arrays. +struct ScopedVariant : public VARIANT { + ScopedVariant() { + VariantInit(this); + } + ~ScopedVariant() { + VariantClear(this); + } +}; + +} // namespace activex_shim + +#endif // #ifndef WEBKIT_ACTIVEX_SHIM_ACTIVEX_UTIL_H__ diff --git a/webkit/activex_shim/dispatch_object.cc b/webkit/activex_shim/dispatch_object.cc new file mode 100644 index 0000000..e15a6de --- /dev/null +++ b/webkit/activex_shim/dispatch_object.cc @@ -0,0 +1,315 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "webkit/activex_shim/dispatch_object.h" + +#include <algorithm> +#include <string> +#include <vector> + +#include "base/logging.h" +#include "webkit/activex_shim/activex_util.h" +#include "webkit/activex_shim/npp_impl.h" + +using std::string; +using std::wstring; + +namespace activex_shim { + +// Used when the browser asks for scriptable object. +static NPClass npclass = { + 1, // NP_CLASS_STRUCT_VERSION, + NPAllocate, + NPDeallocate, + NPInvalidate, + NPHasMethod, + NPInvoke, + NPInvokeDefault, + NPHasProperty, + NPGetProperty, + NPSetProperty, + NPRemoveProperty +}; + +DispatchObject::DispatchObject(DispatchObject* root) + : npobject_(NULL), + root_(root), + deleting_spawned_children_(false) { +} + +DispatchObject::~DispatchObject() { + if (npobject_) { + // We are gone, but the NPObject may still be there. So remove + // the reference to myself to avoid future trouble. + npobject_->dispatch_object = NULL; + } +} + +NPObject* DispatchObject::GetScriptableNPObject() { + if (npobject_ == NULL) { + npobject_ = static_cast<DispatchNPObject*>(NPAllocate(&npclass)); + } else { + // If it is requesting the object again, we should just return the + // object with increased reference count. + g_browser->retainobject(npobject_); + } + return npobject_; +} + +NPObject* DispatchObject::NPAllocate(NPClass* cls) { + DispatchNPObject* obj = new DispatchNPObject(); + obj->_class = cls; + obj->referenceCount = 1; + obj->dispatch_object = this; + return obj; +} + +void DispatchObject::NPInvalidate() { +} + +void DispatchObject::OnDeallocateObject(DispatchNPObject* obj) { + DCHECK_EQ(obj, npobject_); + if (obj == npobject_) { + // Just null our reference so that we won't accidentally access it + // during destruction. + npobject_ = NULL; + if (NPObjectOwnsMe()) { + delete this; + } + } +} + +bool DispatchObject::NPHasMethod(NPIdentifier name) { + wstring wname; + if (!NPIdentifierToWString(name, &wname)) + return false; + return DispIsMethodOrProperty(GetDispatch(), wname.c_str(), true); +} + +bool DispatchObject::NPHasProperty(NPIdentifier name) { + wstring wname; + if (!NPIdentifierToWString(name, &wname)) + return false; + return DispIsMethodOrProperty(GetDispatch(), wname.c_str(), false); + // Here is another way. But the problem is it can not distiguish between + // method and property. + // DISPID dispid; + // if (GetDispID(npobj->dispatch_object->GetDispatch(), wname.c_str(), &dispid)) + // return true; +} + +bool DispatchObject::NPInvoke(NPIdentifier name, const NPVariant* args, + uint32_t argCount, NPVariant* result) { + wstring wname; + if (!NPIdentifierToWString(name, &wname)) + return false; + std::vector<ScopedVariant> vars; + ScopedVariant vtres; + bool res = false; + do { + if (argCount > 0) { + vars.resize(argCount); + unsigned int i; + for (i = 0; i < argCount; i++) { + // Note that we need to reverse the order of arguments for + // IDispatch::Invoke. + if (!NPVariantToVariant(&args[argCount - i - 1], &vars[i])) + break; + } + if (i < argCount) + break; + } + if (!DispInvoke(GetDispatch(), wname.c_str(), + argCount > 0 ? &vars[0] : NULL, + argCount, &vtres)) + break; + if (!VariantToNPVariant(this, &vtres, result)) + break; + res = true; + } while (false); + return res; +} + +bool DispatchObject::NPInvokeDefault(const NPVariant* args, uint32_t argCount, + NPVariant* result) { + return false; +} + +bool DispatchObject::NPGetProperty(NPIdentifier name, NPVariant* variant) { + wstring wname; + if (!NPIdentifierToWString(name, &wname)) + return false; + ScopedVariant result; + if (!DispInvoke(GetDispatch(), wname.c_str(), NULL, 0, &result)) + return false; + if (!VariantToNPVariant(this, &result, variant)) + return false; + return true; +} + +bool DispatchObject::NPSetProperty(NPIdentifier name, const NPVariant* variant) { + wstring wname; + if (!NPIdentifierToWString(name, &wname)) + return false; + ScopedVariant rvalue; + if (!NPVariantToVariant(variant, &rvalue)) + return false; + if (!DispSetProperty(GetDispatch(), wname.c_str(), rvalue)) + return false; + return true; +} + +bool DispatchObject::NPRemoveProperty(NPIdentifier propertyName) { + return false; +} + +void DispatchObject::AddSpawned(DispatchObject* obj) { + // I myself must be the root. + DCHECK(root_ == NULL); + spawned_children_.push_back(obj); +} + +void DispatchObject::RemoveSpawned(DispatchObject* obj) { + // This is to avoid problem when the root object is calling ReleaseSpawned to + // delete all spawned children. + if (deleting_spawned_children_) + return; + DCHECK(root_ == NULL); + SpawnedChildrenList::iterator it = std::find(spawned_children_.begin(), + spawned_children_.end(), obj); + if (it == spawned_children_.end()) { + DCHECK(false); + return; + } + spawned_children_.erase(it); +} + +void DispatchObject::ReleaseSpawned() { + DCHECK(root_ == NULL); + deleting_spawned_children_ = true; + for (SpawnedChildrenList::iterator it = spawned_children_.begin(); + it != spawned_children_.end(); ++it) + delete *it; + deleting_spawned_children_ = false; + spawned_children_.clear(); +} + +SpawnedDispatchObject::SpawnedDispatchObject(IDispatch* dispatch, + DispatchObject* root) + : DispatchObject(root), + dispatch_(dispatch) { + if (dispatch) + dispatch->AddRef(); + DCHECK(root != NULL); + root->AddSpawned(this); +} + +SpawnedDispatchObject::~SpawnedDispatchObject() { + if (dispatch_) + dispatch_->Release(); + DCHECK(root_ != NULL); + root_->RemoveSpawned(this); +} + +/////////////////////////////////////////////////////////////////////////////// +// Scripting object functions implementation. + +NPObject* NPAllocate(NPP npp, NPClass* theClass) { + DispatchObject* dispatch_object = static_cast<DispatchObject*>(npp->pdata); + return dispatch_object->NPAllocate(theClass); +} + +void NPDeallocate(NPObject* obj) { + DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); + // The dispatch_object could be well gone before the NPObject is released. + if (npobj->dispatch_object != NULL) { + npobj->dispatch_object->OnDeallocateObject(npobj); + } + delete npobj; +} + +void NPInvalidate(NPObject* obj) { + DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); + if (npobj->dispatch_object == NULL) + return; + npobj->dispatch_object->NPInvalidate(); +} + +bool NPHasMethod(NPObject* obj, NPIdentifier name) { + DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); + if (npobj->dispatch_object == NULL) + return false; + return npobj->dispatch_object->NPHasMethod(name); +} + +bool NPInvoke(NPObject* obj, NPIdentifier name, const NPVariant* args, + uint32_t argCount, NPVariant* result) { + DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); + if (npobj->dispatch_object == NULL) + return false; + return npobj->dispatch_object->NPInvoke(name, args, argCount, result); +} + +bool NPInvokeDefault(NPObject* obj, const NPVariant* args, uint32_t argCount, + NPVariant* result) { + DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); + if (npobj->dispatch_object == NULL) + return false; + return npobj->dispatch_object->NPInvokeDefault(args, argCount, result); +} + +bool NPHasProperty(NPObject* obj, NPIdentifier name) { + DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); + if (npobj->dispatch_object == NULL) + return false; + return npobj->dispatch_object->NPHasProperty(name); +} + +bool NPGetProperty(NPObject* obj, NPIdentifier name, NPVariant* variant) { + DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); + if (npobj->dispatch_object == NULL) + return false; + return npobj->dispatch_object->NPGetProperty(name, variant); +} + +bool NPSetProperty(NPObject* obj, NPIdentifier name, const NPVariant* variant) { + DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); + if (npobj->dispatch_object == NULL) + return false; + return npobj->dispatch_object->NPSetProperty(name, variant); +} + +bool NPRemoveProperty(NPObject* obj, NPIdentifier name) { + DispatchNPObject* npobj = static_cast<DispatchNPObject*>(obj); + if (npobj->dispatch_object == NULL) + return false; + return npobj->dispatch_object->NPRemoveProperty(name); +} + +} // namespace activex_shim diff --git a/webkit/activex_shim/dispatch_object.h b/webkit/activex_shim/dispatch_object.h new file mode 100644 index 0000000..f342448 --- /dev/null +++ b/webkit/activex_shim/dispatch_object.h @@ -0,0 +1,149 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef WEBKIT_ACTIVEX_SHIM_DISPATCH_OBJECT_H__ +#define WEBKIT_ACTIVEX_SHIM_DISPATCH_OBJECT_H__ + +#include <oaidl.h> + +#include <list> + +#include "base/scoped_ptr.h" +#include "webkit/glue/plugins/nphostapi.h" + +namespace activex_shim { + +struct DispatchNPObject; + +// DispatchObject provides service to translate calls on NPObject to the +// underlying IDispatch interface. It is isolated from the ActiveXPlugin, so +// that when we have scripts like: +// wmp.controls.stop(); +// We can create a spawned dispatch object for "controls" -- an IDispatch +// interface returned from property "controls" of the wmp activex control. +class DispatchObject { + public: + DispatchObject(DispatchObject* root); + virtual ~DispatchObject(); + + // This is used when NPP_GetValue is called by browser and asked for + // NPPVpluginScriptableNPObject. + NPObject* GetScriptableNPObject(); + + // Object scripting + NPObject* NPAllocate(NPClass* theClass); + void NPInvalidate(); + bool NPHasMethod(NPIdentifier name); + bool NPHasProperty(NPIdentifier name); + bool NPInvoke(NPIdentifier name, const NPVariant* args, + uint32_t argCount, NPVariant* result); + bool NPInvokeDefault(const NPVariant* args, uint32_t argCount, + NPVariant* result); + bool NPGetProperty(NPIdentifier name, NPVariant* variant); + bool NPSetProperty(NPIdentifier name, const NPVariant* variant); + bool NPRemoveProperty(NPIdentifier propertyName); + + // Called by NPDeallocate so that we can remove our reference. + void OnDeallocateObject(DispatchNPObject* obj); + DispatchObject* root() { return root_== NULL ? this : root_; } + // Only the root object needs to take care of this. + void AddSpawned(DispatchObject* obj); + // If a spawned child is released earlier than the root object, it needs to + // call this function to remove itself from the children list, to avoid + // another destruction when the root object is being destructed. + void RemoveSpawned(DispatchObject* obj); + + protected: + // Only the root object can release spawned dispatch object. The root object + // is coupled with the actual ActiveX control. Thus if the control is dead + // we must also release all Dispatch interfaces from that control. + void ReleaseSpawned(); + // root_ is the owner of this object. If root_ == NULL, then this object + // itself is the root. + DispatchObject* const root_; + + private: + typedef std::list<DispatchObject*> SpawnedChildrenList; + + // Must be overrided by subclass to be functional. + virtual IDispatch* GetDispatch() = 0; + // If this is true, when the related npobject is released, it should delete + // this object as well. + virtual bool NPObjectOwnsMe() = 0; + + // We create only one NPObject per ActiveXPlugin. It may have different life + // span than ActiveXPlugin thus we need a separate object created + // specifically for this purpose. + DispatchNPObject* npobject_; + // A list of spawned children from this root object (if it is). + SpawnedChildrenList spawned_children_; + bool deleting_spawned_children_; +}; + +// The spawned dipatch object contains a reference to an IDispatch interface +// that it owns. Its lifetime is controlled by the lifetime of related +// NPObject, and the root DispatchObject it is spawned from. +class SpawnedDispatchObject : public DispatchObject { + public: + // Constructor will addref to the dispatch interface, and add itself to + // spawned children of root. + SpawnedDispatchObject(IDispatch* dispatch, DispatchObject* root); + ~SpawnedDispatchObject(); + + private: + virtual IDispatch* GetDispatch() { return dispatch_; } + virtual bool NPObjectOwnsMe() { return true; } + + IDispatch* dispatch_; +}; + +// A simple extension of the NPObject. So that we can put additional information +// like who is the underlying DispatchObject with the NPObject. When methods of +// NPObject are requested we can resort to the DispatchObject to handle them. +struct DispatchNPObject : public NPObject { + DispatchObject* dispatch_object; +}; + +// These functions are to support scriptable plugin object. +NPObject* NPAllocate(NPP npp, NPClass* theClass); +void NPDeallocate(NPObject* obj); +void NPInvalidate(NPObject* obj); +bool NPHasMethod(NPObject* obj, NPIdentifier name); +bool NPInvoke(NPObject* obj, NPIdentifier name, const NPVariant* args, + uint32_t argCount, NPVariant* result); +bool NPInvokeDefault(NPObject* obj, const NPVariant* args, uint32_t argCount, + NPVariant* result); +bool NPHasProperty(NPObject* obj, NPIdentifier name); +bool NPGetProperty(NPObject* obj, NPIdentifier name, NPVariant* variant); +bool NPSetProperty(NPObject* obj, NPIdentifier name, const NPVariant* variant); +bool NPRemoveProperty(NPObject* npobj, NPIdentifier propertyName); + +} // namespace activex_shim + +#endif // #ifndef WEBKIT_ACTIVEX_SHIM_DISPATCH_OBJECT_H__ diff --git a/webkit/activex_shim/ihtmldocument_impl.h b/webkit/activex_shim/ihtmldocument_impl.h new file mode 100644 index 0000000..205e4f6 --- /dev/null +++ b/webkit/activex_shim/ihtmldocument_impl.h @@ -0,0 +1,508 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef WEBKIT_ACTIVEX_SHIM_IHTMLDOCUMENT_IMPL_H__ +#define WEBKIT_ACTIVEX_SHIM_IHTMLDOCUMENT_IMPL_H__ + +#include <mshtml.h> +#include "webkit/activex_shim/activex_util.h" + +namespace activex_shim { + +// TODO(ruijiang): Right now this is a dummy implementation of IHTMLDocument2. +// We should connect it with NPObject directly and implement necessary +// functions needed by controls. +class IHTMLDocument2Impl : public IHTMLDocument2 { + public: + // IHTMLDocument + virtual HRESULT STDMETHODCALLTYPE get_Script(IDispatch **p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + + // IHTMLDocument2 + virtual HRESULT STDMETHODCALLTYPE get_all(IHTMLElementCollection** p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_body(IHTMLElement** p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_activeElement(IHTMLElement** p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_images(IHTMLElementCollection** p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_applets(IHTMLElementCollection** p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_links(IHTMLElementCollection** p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_forms(IHTMLElementCollection** p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_anchors(IHTMLElementCollection** p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_title(BSTR v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_title(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_scripts(IHTMLElementCollection** p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_designMode(BSTR v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_designMode(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_selection(IHTMLSelectionObject** p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_readyState(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_frames(IHTMLFramesCollection2** p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_embeds(IHTMLElementCollection** p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_plugins(IHTMLElementCollection** p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_alinkColor(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_alinkColor(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_bgColor(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_bgColor(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_fgColor(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_fgColor(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_linkColor(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_linkColor(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_vlinkColor(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_vlinkColor(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_referrer(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_location(IHTMLLocation** p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_lastModified(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_URL(BSTR v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_URL(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_domain(BSTR v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_domain(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_cookie(BSTR v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_cookie(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_expando(VARIANT_BOOL v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_expando(VARIANT_BOOL* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_charset(BSTR v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_charset(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_defaultCharset(BSTR v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_defaultCharset(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_mimeType(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_fileSize(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_fileCreatedDate(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_fileModifiedDate(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_fileUpdatedDate(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_security(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_protocol(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_nameProp(BSTR* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE write(SAFEARRAY* psarray) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE writeln(SAFEARRAY* psarray) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE open(BSTR url, + VARIANT name, + VARIANT features, + VARIANT replace, + IDispatch** pom_window_result) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE close() { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE clear() { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE queryCommandSupported(BSTR cmd_id, + VARIANT_BOOL* ret) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE queryCommandEnabled(BSTR cmd_id, + VARIANT_BOOL* ret) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE queryCommandState(BSTR cmd_id, + VARIANT_BOOL* ret) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE queryCommandIndeterm(BSTR cmd_id, + VARIANT_BOOL* ret) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE queryCommandText(BSTR cmd_id, + BSTR* pcmd_text) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE queryCommandValue(BSTR cmd_id, + VARIANT* pcmd_value) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE execCommand(BSTR cmd_id, + VARIANT_BOOL show_ui, + VARIANT value, + VARIANT_BOOL* ret) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE execCommandShowHelp(BSTR cmd_id, + VARIANT_BOOL* ret) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE createElement(BSTR e_tag, + IHTMLElement** new_elem) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onhelp(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onhelp(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onclick(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onclick(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_ondblclick(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_ondblclick(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onkeyup(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onkeyup(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onkeydown(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onkeydown(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onkeypress(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onkeypress(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onmouseup(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onmouseup(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onmousedown(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onmousedown(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onmousemove(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onmousemove(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onmouseout(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onmouseout(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onmouseover(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onmouseover(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onreadystatechange(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onreadystatechange(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onafterupdate(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onafterupdate(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onrowexit(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onrowexit(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onrowenter(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onrowenter(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_ondragstart(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_ondragstart(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onselectstart(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onselectstart(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE elementFromPoint( + long x, + long y, + IHTMLElement** element_hit) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_parentWindow(IHTMLWindow2** p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_styleSheets( + IHTMLStyleSheetsCollection** p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onbeforeupdate(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onbeforeupdate(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_onerrorupdate(VARIANT v) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_onerrorupdate(VARIANT* p) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE toString(BSTR* str) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE createStyleSheet( + BSTR href, + long index, + IHTMLStyleSheet** new_style_sheet) { + TRACK_METHOD(); + return E_NOTIMPL; + } +}; + +} // namespace activex_shim + +#endif // #ifndef WEBKIT_ACTIVEX_SHIM_IHTMLDOCUMENT_IMPL_H__ diff --git a/webkit/activex_shim/iwebbrowser_impl.h b/webkit/activex_shim/iwebbrowser_impl.h new file mode 100644 index 0000000..b5f6ba4 --- /dev/null +++ b/webkit/activex_shim/iwebbrowser_impl.h @@ -0,0 +1,328 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef WEBKIT_ACTIVEX_SHIM_IWEBBROWSER_IMPL_H__ +#define WEBKIT_ACTIVEX_SHIM_IWEBBROWSER_IMPL_H__ + +#include <exdisp.h> +#include <mshtml.h> +#include "webkit/activex_shim/activex_util.h" + +namespace activex_shim { + +// Dummy implementation of IWebBrowser2 interface. +class IWebBrowser2Impl : public IWebBrowser2 { + public: + // IWebBrowser + virtual HRESULT STDMETHODCALLTYPE GoBack() { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE GoForward() { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE GoHome() { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE GoSearch() { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE Navigate(BSTR url, + VARIANT* flags, + VARIANT* target_frame_name, + VARIANT* post_data, + VARIANT* headers) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE Refresh() { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE Refresh2(VARIANT* level) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE Stop() { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_Application(IDispatch** disp) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_Parent(IDispatch** disp) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_Container(IDispatch** disp) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_Document(IDispatch** disp) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_TopLevelContainer(VARIANT_BOOL* b) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_Type(BSTR* type) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_Left(long* pl) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_Left(long left) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_Top(long* pl) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_Top(long top) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_Width(long* pl) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_Width(long width) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_Height(long* pl) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_Height(long height) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_LocationName(BSTR* location_name) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_LocationURL(BSTR* location_url) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_Busy(VARIANT_BOOL* b) { + TRACK_METHOD(); + return E_NOTIMPL; + } + + // IWebBrowserApp + virtual HRESULT STDMETHODCALLTYPE Quit() { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE ClientToWindow(int* pcx, int* pcy) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE PutProperty(BSTR property, + VARIANT vt_value) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE GetProperty(BSTR property, + VARIANT* pvt_value) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_Name(BSTR* name) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_HWND(SHANDLE_PTR* hwnd) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_FullName(BSTR* full_name) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_Path(BSTR* path) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_Visible(VARIANT_BOOL* b) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_Visible(VARIANT_BOOL value) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_StatusBar(VARIANT_BOOL* b) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_StatusBar(VARIANT_BOOL value) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_StatusText(BSTR* status_text) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_StatusText(BSTR status_text) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_ToolBar(int* value) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_ToolBar(int value) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_MenuBar(VARIANT_BOOL* value) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_MenuBar(VARIANT_BOOL value) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_FullScreen( + VARIANT_BOOL* pb_full_screen) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_FullScreen(VARIANT_BOOL b_full_screen) { + TRACK_METHOD(); + return E_NOTIMPL; + } + + // IWebBrowser2 + virtual HRESULT STDMETHODCALLTYPE Navigate2(VARIANT* url, + VARIANT* flags, + VARIANT* target_frame_name, + VARIANT* post_data, + VARIANT* headers) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE QueryStatusWB(OLECMDID cmd_id, + OLECMDF* pcmdf) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE ExecWB(OLECMDID cmd_id, + OLECMDEXECOPT cmdexecopt, + VARIANT* pva_in, + VARIANT* pva_out) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE ShowBrowserBar(VARIANT* pva_clsid, + VARIANT* pvar_show, + VARIANT* pvar_size) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_ReadyState(READYSTATE* pl_ready_state) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_Offline(VARIANT_BOOL* pb_offline) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_Offline(VARIANT_BOOL b_offline) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_Silent(VARIANT_BOOL* pb_silent) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_Silent(VARIANT_BOOL b_silent) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_RegisterAsBrowser( + VARIANT_BOOL* pb_register) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_RegisterAsBrowser( + VARIANT_BOOL b_register) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_RegisterAsDropTarget( + VARIANT_BOOL* pb_register) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_RegisterAsDropTarget( + VARIANT_BOOL b_register) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_TheaterMode(VARIANT_BOOL* pb_register) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_TheaterMode(VARIANT_BOOL b_register) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_AddressBar(VARIANT_BOOL* value) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_AddressBar(VARIANT_BOOL value) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE get_Resizable(VARIANT_BOOL* value) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE put_Resizable(VARIANT_BOOL value) { + TRACK_METHOD(); + return E_NOTIMPL; + } +}; + +} // namespace activex_shim + +#endif // #ifndef WEBKIT_ACTIVEX_SHIM_IWEBBROWSER_IMPL_H__ diff --git a/webkit/activex_shim/npn_scripting.cc b/webkit/activex_shim/npn_scripting.cc new file mode 100644 index 0000000..aaf3960 --- /dev/null +++ b/webkit/activex_shim/npn_scripting.cc @@ -0,0 +1,295 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "webkit/activex_shim/npn_scripting.h" + +#include "base/logging.h" +#include "base/string_util.h" +#include "webkit/activex_shim/npp_impl.h" + +namespace activex_shim { + +NPNScriptableObject::NPNScriptableObject() : npp_(NULL), object_(NULL) { +} + +NPNScriptableObject::NPNScriptableObject(NPP npp, NPObject* object) + : npp_(npp), + object_(object) { +} + +NPNScriptableObject::NPNScriptableObject(NPNScriptableObject& object) + : npp_(object.npp_), + object_(object.object_) { + if (object_) + g_browser->retainobject(object_); +} + +NPNScriptableObject::~NPNScriptableObject() { + Release(); +} + +NPNScriptableObject& NPNScriptableObject::operator=( + NPNScriptableObject& object) { + if (this == &object) + return *this; + if (object_) + g_browser->releaseobject(object_); + npp_ = object.npp_; + object_ = object.object_; + if (object_) + g_browser->retainobject(object_); + return *this; +} + +void NPNScriptableObject::Init(NPP npp, NPObject* object) { + Release(); + npp_ = npp; + object_ = object; +} + +void NPNScriptableObject::Release() { + if (object_) { + g_browser->releaseobject(object_); + object_ = NULL; + } + npp_ = NULL; +} + +bool NPNScriptableObject::HasProperty(const std::string& name) { + if (!IsValid()) + return false; + NPIdentifier id = g_browser->getstringidentifier(name.c_str()); + bool res = g_browser->hasproperty(npp_, object_, id); + // How do we release id since it's coming from the browser? the answer is + // we never release them. See implementation of NPN_GetStringIdentifier + // in npruntime.cpp. + return res; +} + +bool NPNScriptableObject::GetProperty(const std::string& name, NPVariant* ret) { + if (!IsValid()) + return false; + NPIdentifier id = g_browser->getstringidentifier(name.c_str()); + return g_browser->getproperty(npp_, object_, id, ret); +} + +bool NPNScriptableObject::SetProperty(const std::string& name, + const NPVariant& val) { + if (!IsValid()) + return false; + NPIdentifier id = g_browser->getstringidentifier(name.c_str()); + return g_browser->setproperty(npp_, object_, id, &val); +} + +NPNScriptableObject NPNScriptableObject::GetObjectProperty( + const std::string& name, + bool* succeeded) { + NPNScriptableObject res; + if (succeeded) + *succeeded = false; + NPVariant var; + if (!GetProperty(name, &var)) + return res; + if (var.type == NPVariantType_Object) { + res.Init(npp_, var.value.objectValue); + // From now, the object should have reference count as 1. We shall not + // release the variant cause it will release the object. + if (succeeded) + *succeeded = true; + } else { + g_browser->releasevariantvalue(&var); + } + return res; +} + +std::wstring NPNScriptableObject::GetStringProperty(const std::string& name, + bool* succeeded) { + std::wstring res; + if (succeeded) + *succeeded = false; + NPVariant var; + if (!GetProperty(name, &var)) + return res; + if (var.type == NPVariantType_String) { + std::string tmp(var.value.stringValue.UTF8Characters, + var.value.stringValue.UTF8Length); + res = UTF8ToWide(tmp.c_str()); + if (succeeded) + *succeeded = true; + } + // We've made a copy of the string. Thus we should release the variant in + // any case. + g_browser->releasevariantvalue(&var); + return res; +} + +bool NPNScriptableObject::SetStringProperty(const std::string& name, + const std::wstring& val) { + NPVariantWrap var; + var.SetString(val); + return SetProperty(name, var); +} + +bool NPNScriptableObject::Invoke(const std::string& name, + const char* format, ...) { + if (!IsValid()) + return false; + NPIdentifier id = g_browser->getstringidentifier(name.c_str()); + std::vector<NPVariantWrap> args; + va_list argptr; + va_start(argptr, format); + for (const char* p = format; *p; ++p) { + char c = *p; + DCHECK(c == '%' && *(p + 1) != 0); + if (c != '%' || *(p + 1) == 0) + continue; + ++p; + c = *p; + NPVariantWrap var; + switch(c) { + case 's': { + // String + wchar_t *s = va_arg(argptr, wchar_t*); + var.SetString(s); + break; + } + case 'd': { + // String + int n = va_arg(argptr, int); + var.SetInt(n); + break; + } + default: { + DCHECK(false); + break; + } + } + args.push_back(var); + } + NPVariant ret; + ret.type = NPVariantType_Void; + bool res = false; + if (args.size()) + res = g_browser->invoke(npp_, object_, id, &args[0], + static_cast<unsigned int>(args.size()), &ret); + else + res = g_browser->invoke(npp_, object_, id, NULL, 0, &ret); + + g_browser->releasevariantvalue(&ret); + return res; +} + +NPVariantWrap::NPVariantWrap() { + type = NPVariantType_Void; +} + +NPVariantWrap::NPVariantWrap(const NPVariantWrap& v) { + type = NPVariantType_Void; + Copy(v); +} + +NPVariantWrap::~NPVariantWrap() { + Release(); +} + +NPVariantWrap& NPVariantWrap::operator=(const NPVariantWrap& v) { + if (this != &v) + Copy(v); + return *this; +} + +void NPVariantWrap::Copy(const NPVariant& v) { + if (this == &v) + return; + Release(); + switch(v.type) { + case NPVariantType_Void: + break; + case NPVariantType_Null: + break; + case NPVariantType_Bool: + value.boolValue = v.value.boolValue; + break; + case NPVariantType_Int32: + value.intValue = v.value.intValue; + break; + case NPVariantType_Double: + value.doubleValue = v.value.doubleValue; + break; + case NPVariantType_String: + SetUTF8String(v.value.stringValue.UTF8Characters, + v.value.stringValue.UTF8Length); + break; + case NPVariantType_Object: + g_browser->retainobject(v.value.objectValue); + value.objectValue = v.value.objectValue; + break; + default: + DCHECK(false); + break; + } + type = v.type; +} + +void NPVariantWrap::Release() { + if (type == NPVariantType_String) { + delete[] value.stringValue.UTF8Characters; + } else if (type == NPVariantType_Object) { + g_browser->releaseobject(value.objectValue); + } + type = NPVariantType_Void; +} + +void NPVariantWrap::SetBool(bool val) { + Release(); + value.boolValue = val; + type = NPVariantType_Bool; +} + +void NPVariantWrap::SetInt(int val) { + Release(); + value.intValue = val; + type = NPVariantType_Int32; +} + +void NPVariantWrap::SetUTF8String(const NPUTF8* p, unsigned int size) { + Release(); + value.stringValue.UTF8Characters = new char[size + 1]; + memcpy(const_cast<NPUTF8*>(value.stringValue.UTF8Characters), + p, size + 1); + value.stringValue.UTF8Length = size; + type = NPVariantType_String; +} + +void NPVariantWrap::SetString(const std::wstring& val) { + std::string s = WideToUTF8(val); + SetUTF8String(s.c_str(), static_cast<unsigned int>(s.size())); +} + +} // namespace activex_shim diff --git a/webkit/activex_shim/npn_scripting.h b/webkit/activex_shim/npn_scripting.h new file mode 100644 index 0000000..c7d2c6e --- /dev/null +++ b/webkit/activex_shim/npn_scripting.h @@ -0,0 +1,120 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef WEBKIT_ACTIVEX_SHIM_NPN_SCRIPTING_H__ +#define WEBKIT_ACTIVEX_SHIM_NPN_SCRIPTING_H__ + +#include <string> +#include "webkit/glue/plugins/nphostapi.h" + +namespace activex_shim { + +class NPNWindow; +class NPNDocument; + +// Simplifies querying and calling methods of a scriptable NPObject +class NPNScriptableObject { + public: + NPNScriptableObject(); + // The caller should leave the NPObject to me and don't worry about releasing + // the NPObject. + NPNScriptableObject(NPP npp, NPObject* object); + // Implement copy constructor so that we could easily do things like: + // NPNScriptableObject location = window.GetObjectProperty("location"); + // In this copy constructor we will ask the browser to add ref to the + // underlying NPObject (retainobject). + NPNScriptableObject(NPNScriptableObject& object); + // We will call the browser to release the object. + ~NPNScriptableObject(); + + // We will take over the object. Thus we don't add ref here. + void Init(NPP npp, NPObject* object); + // Release container object and set it to NULL. + void Release(); + // Reference counting for assignment + NPNScriptableObject& operator=(NPNScriptableObject& object); + + bool IsValid() { return object_ != NULL; } + bool HasProperty(const std::string& name); + // Caller is responsible to release the ret value if succeeded. + bool GetProperty(const std::string& name, NPVariant* ret); + bool SetProperty(const std::string& name, const NPVariant& val); + + // More specific Get/Set properties for convenience. + // If you don't care if the call was successful, you can pass succeeded as + // NULL. It is used to differentiate the case when we get an empty string, + // and don't know if it is because the call failed or not. + std::wstring GetStringProperty(const std::string& name, bool* succeeded); + std::wstring GetStringProperty(const std::string& name) { + return GetStringProperty(name, NULL); + } + bool SetStringProperty(const std::string& name, const std::wstring& val); + // See comments for GetStringProperty. + NPNScriptableObject GetObjectProperty(const std::string& name, + bool* succeeded); + NPNScriptableObject GetObjectProperty(const std::string& name) { + return GetObjectProperty(name, NULL); + } + + // Invoke a method of the NPObject. format should be exactly like (only the + // ones listed here are supported): + // %s: the following param is a null terminated wchar_t* string. + // %d: the following param is an integer. + // Example: window.Invoke("open", "%s%s", L"http://b", L"_blank") + // This is only used internally so we have control over format string. + bool Invoke(const std::string& name, const char* format, ...); + + private: + // Which NP instance created me. Used to pass as parameters in NPN_Invoke + // like calls. + NPP npp_; + // The NPObject that I am operating on. + NPObject* object_; +}; + +// Helper class to simplify use of NPVariant. Never add any virtual function +// or member variables to this class because we will use it like +// vector<NPVariantWrap> and pass the internal array as NPVariant* to NPAPI +// calls. +struct NPVariantWrap : public NPVariant { + NPVariantWrap(); + NPVariantWrap(const NPVariantWrap& v); + ~NPVariantWrap(); + NPVariantWrap& operator=(const NPVariantWrap& v); + void Release(); + void Copy(const NPVariant& v); + void SetBool(bool val); + void SetInt(int val); + void SetString(const std::wstring& val); + void SetUTF8String(const NPUTF8* p, unsigned int size); +}; + +} // namespace activex_shim + +#endif // #ifndef WEBKIT_ACTIVEX_SHIM_NPN_SCRIPTING_H__ diff --git a/webkit/activex_shim/npp_impl.cc b/webkit/activex_shim/npp_impl.cc new file mode 100644 index 0000000..49ed808 --- /dev/null +++ b/webkit/activex_shim/npp_impl.cc @@ -0,0 +1,173 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "webkit/activex_shim/npp_impl.h" + +#include <algorithm> + +#include "webkit/activex_shim/activex_plugin.h" +#include "webkit/activex_shim/activex_util.h" + +#pragma warning(disable: 4267 4312) + +using std::string; +using std::wstring; + +namespace activex_shim { + +NPNetscapeFuncs* g_browser; + +// Standard NPAPI functions. +NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, + char* argn[], char* argv[], NPSavedData* saved); +NPError NPP_Destroy(NPP instance, NPSavedData** save); +NPError NPP_SetWindow(NPP instance, NPWindow* window); +NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype); +NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason); +int32 NPP_WriteReady(NPP instance, NPStream* stream); +int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, + void* buffer); +void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname); +void NPP_Print(NPP instance, NPPrint* platformPrint); +int16 NPP_HandleEvent(NPP instance, void* event); +void NPP_URLNotify(NPP instance, const char* url, NPReason reason, + void* notifyData); +NPError NPP_GetValue(NPP instance, NPPVariable variable, void* value); +NPError NPP_SetValue(NPP instance, NPNVariable variable, void* value); + +NPError WINAPI ActiveX_Shim_NP_GetEntryPoints(NPPluginFuncs* funcs) { + funcs->version = 11; + funcs->size = sizeof(*funcs); + funcs->newp = NPP_New; + funcs->destroy = NPP_Destroy; + funcs->setwindow = NPP_SetWindow; + funcs->newstream = NPP_NewStream; + funcs->destroystream = NPP_DestroyStream; + funcs->asfile = NPP_StreamAsFile; + funcs->writeready = NPP_WriteReady; + funcs->write = NPP_Write; + funcs->print = NPP_Print; + funcs->event = NPP_HandleEvent; + funcs->urlnotify = NPP_URLNotify; + funcs->getvalue = NPP_GetValue; + funcs->setvalue = NPP_SetValue; + + return NPERR_NO_ERROR; +} + +NPError WINAPI ActiveX_Shim_NP_Initialize(NPNetscapeFuncs* funcs) { + g_browser = funcs; + + // Not all browsers call CoInitialize during startup. Do this to make sure we + // won't have problem later on creating ActiveX controls. + // Right now the object creation request comes from the same thread as the + // one calling NP_Initialize. We should watch it if it comes from a different + // thread. + CoInitialize(NULL); + return 0; +} + +NPError WINAPI ActiveX_Shim_NP_Shutdown(void) { + CoUninitialize(); + return 0; +} + +NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, + char* argn[], char* argv[], NPSavedData* saved) { + ActiveXPlugin* plugin = new ActiveXPlugin(instance); + instance->pdata = plugin; + return plugin->NPP_New(pluginType, argc, argn, argv, saved); +} + +NPError NPP_Destroy(NPP instance, NPSavedData** save) { + ActiveXPlugin* plugin = static_cast<ActiveXPlugin*>(instance->pdata); + delete plugin; + return 0; +} + +NPError NPP_SetWindow(NPP instance, NPWindow* window) { + ActiveXPlugin* plugin = static_cast<ActiveXPlugin*>(instance->pdata); + return plugin->NPP_SetWindow(window); +} + +NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype) { + ActiveXPlugin* plugin = static_cast<ActiveXPlugin*>(instance->pdata); + return plugin->NPP_NewStream(type, stream, seekable, stype); +} + +NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) { + ActiveXPlugin* plugin = static_cast<ActiveXPlugin*>(instance->pdata); + return plugin->NPP_DestroyStream(stream, reason); +} + +int32 NPP_WriteReady(NPP instance, NPStream* stream) { + ActiveXPlugin* plugin = static_cast<ActiveXPlugin*>(instance->pdata); + return plugin->NPP_WriteReady(stream); +} + +int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, + void* buffer) { + ActiveXPlugin* plugin = static_cast<ActiveXPlugin*>(instance->pdata); + return plugin->NPP_Write(stream, offset, len, buffer); +} + +void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) { + ActiveXPlugin* plugin = static_cast<ActiveXPlugin*>(instance->pdata); + plugin->NPP_StreamAsFile(stream, fname); +} + +void NPP_Print(NPP instance, NPPrint* platformPrint) { + ActiveXPlugin* plugin = static_cast<ActiveXPlugin*>(instance->pdata); + plugin->NPP_Print(platformPrint); +} + +int16 NPP_HandleEvent(NPP instance, void* event) { + ActiveXPlugin* plugin = static_cast<ActiveXPlugin*>(instance->pdata); + return plugin->NPP_HandleEvent(event); +} + +void NPP_URLNotify(NPP instance, const char* url, NPReason reason, + void* notifyData) { + ActiveXPlugin* plugin = static_cast<ActiveXPlugin*>(instance->pdata); + plugin->NPP_URLNotify(url, reason, notifyData); +} + +NPError NPP_GetValue(NPP instance, NPPVariable variable, void* value) { + ActiveXPlugin* plugin = static_cast<ActiveXPlugin*>(instance->pdata); + return plugin->NPP_GetValue(variable, value); +} + +NPError NPP_SetValue(NPP instance, NPNVariable variable, void* value) { + ActiveXPlugin* plugin = static_cast<ActiveXPlugin*>(instance->pdata); + return plugin->NPP_SetValue(variable, value); +} + +} // namespace activex_shim diff --git a/webkit/activex_shim/npp_impl.h b/webkit/activex_shim/npp_impl.h new file mode 100644 index 0000000..04cc67d --- /dev/null +++ b/webkit/activex_shim/npp_impl.h @@ -0,0 +1,48 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef WEBKIT_ACTIVEX_SHIM_NPP_IMPL_H__ +#define WEBKIT_ACTIVEX_SHIM_NPP_IMPL_H__ + +#include "webkit/glue/plugins/nphostapi.h" + +namespace activex_shim { + +// Entry functions. To avoid name conflict when used in activex_shim_dll, they +// are additionally prefixed. +NPError WINAPI ActiveX_Shim_NP_GetEntryPoints(NPPluginFuncs* funcs); +NPError WINAPI ActiveX_Shim_NP_Initialize(NPNetscapeFuncs* funcs); +NPError WINAPI ActiveX_Shim_NP_Shutdown(void); + +// Initialized in NP_Initialize. +extern NPNetscapeFuncs* g_browser; + +} // namespace activex_shim + +#endif // #ifndef WEBKIT_ACTIVEX_SHIM_NPP_IMPL_H__ diff --git a/webkit/activex_shim/web_activex_container.cc b/webkit/activex_shim/web_activex_container.cc new file mode 100644 index 0000000..872db61 --- /dev/null +++ b/webkit/activex_shim/web_activex_container.cc @@ -0,0 +1,371 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "webkit/activex_shim/web_activex_container.h" + +#include "webkit/activex_shim/activex_plugin.h" +#include "webkit/activex_shim/activex_util.h" +#include "webkit/activex_shim/npn_scripting.h" +#include "webkit/activex_shim/npp_impl.h" +#include "webkit/activex_shim/web_activex_site.h" + +namespace activex_shim { + +// WebActiveXContainer +WebActiveXContainer::WebActiveXContainer() + : plugin_(NULL), + container_wnd_(NULL) { +} + +WebActiveXContainer::~WebActiveXContainer() { + // Don't do anything here. Do everything in FinalRelease. +} + +void WebActiveXContainer::Init(ActiveXPlugin* plugin) { + plugin_ = plugin; +} + +void WebActiveXContainer::FinalRelease() { + container_wnd_ = NULL; + for (unsigned int i = 0; i < sites_.size(); i++) { + delete sites_[i]; + } + sites_.clear(); +} + +// IUnknown +HRESULT STDMETHODCALLTYPE WebActiveXContainer::QueryInterface( + REFIID iid, + void** object) { + *object = NULL; + if (iid == IID_IUnknown) { + *object = static_cast<IUnknown*>(static_cast<IOleContainer*>(this)); + } else if (iid == IID_IDispatch) { + *object = static_cast<IDispatch*>(static_cast<IHTMLDocument2Impl*>(this)); + } else if (iid == IID_IParseDisplayName) { + *object = static_cast<IParseDisplayName*>(this); + } else if (iid == IID_IOleContainer) { + *object = static_cast<IOleContainer*>(this); + } else if (iid == IID_IOleWindow) { + *object = static_cast<IOleWindow*>(this); + } else if (iid == IID_IOleInPlaceUIWindow) { + *object = static_cast<IOleInPlaceUIWindow*>(this); + } else if (iid == IID_IOleInPlaceFrame) { + *object = static_cast<IOleInPlaceFrame*>(this); + } else if (iid == IID_IHTMLDocument) { + *object = static_cast<IHTMLDocument*>(this); + } else if (iid == IID_IHTMLDocument2) { + *object = static_cast<IHTMLDocument2*>(this); + } else if (iid == IID_IWebBrowser) { + *object = static_cast<IWebBrowser*>(this); + } else if (iid == IID_IWebBrowserApp) { + *object = static_cast<IWebBrowserApp*>(this); + } else if (iid == IID_IWebBrowser2) { + *object = static_cast<IWebBrowser2*>(this); + } else if (iid == IID_IBindHost) { + *object = static_cast<IBindHost*>(this); + } + TRACK_QUERY_INTERFACE(iid, *object != NULL); + return (*object != NULL) ? S_OK : E_NOINTERFACE; +} + +// IParseDisplayName +HRESULT STDMETHODCALLTYPE WebActiveXContainer::ParseDisplayName( + IBindCtx* bc, + LPOLESTR display_name, + ULONG* cheaten, + IMoniker** moniker) { + TRACK_METHOD(); + // Do not support this. + return E_NOTIMPL; +} + +// IOleContainer +HRESULT STDMETHODCALLTYPE WebActiveXContainer::EnumObjects(DWORD flags, + IEnumUnknown** ppenum) { + TRACK_METHOD(); + // Do not support enumeration. + return E_NOTIMPL; +}; + +HRESULT STDMETHODCALLTYPE WebActiveXContainer::LockContainer(BOOL lock) { + TRACK_METHOD(); + // Do not allow locking container. + return E_NOTIMPL; +}; + +// IOleWindow + +HRESULT STDMETHODCALLTYPE WebActiveXContainer::GetWindow(HWND* wnd) { + TRACK_METHOD(); + *wnd = container_wnd(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXContainer::ContextSensitiveHelp( + BOOL enter_mode) { + TRACK_METHOD(); + return E_NOTIMPL; +} + +// IOleInPlaceUIWindow +HRESULT STDMETHODCALLTYPE WebActiveXContainer::GetBorder(LPRECT border) { + TRACK_METHOD(); + // Does not allow tool bar etc. + return INPLACE_E_NOTOOLSPACE; +} + +HRESULT STDMETHODCALLTYPE WebActiveXContainer::RequestBorderSpace( + LPCBORDERWIDTHS border_widths) { + TRACK_METHOD(); + return INPLACE_E_NOTOOLSPACE; +} + +HRESULT STDMETHODCALLTYPE WebActiveXContainer::SetBorderSpace( + LPCBORDERWIDTHS border_widths) { + TRACK_METHOD(); + return E_UNEXPECTED; +} + +HRESULT STDMETHODCALLTYPE WebActiveXContainer::SetActiveObject( + IOleInPlaceActiveObject* active_object, + LPCOLESTR obj_name) { + TRACK_METHOD(); + // Ignore whatever. + return S_OK; +} + +// IOleInPlaceFrame + +HRESULT STDMETHODCALLTYPE WebActiveXContainer::InsertMenus( + HMENU hmenu_shared, + LPOLEMENUGROUPWIDTHS menu_widths) { + TRACK_METHOD(); + // No menu is allowed. + return E_UNEXPECTED; +} + +HRESULT STDMETHODCALLTYPE WebActiveXContainer::SetMenu( + HMENU hmenu_shared, + HOLEMENU hole_menu, + HWND active_object) { + TRACK_METHOD(); + return E_UNEXPECTED; +} + +HRESULT STDMETHODCALLTYPE WebActiveXContainer::RemoveMenus( + HMENU hmenu_shared) { + TRACK_METHOD(); + return E_UNEXPECTED; +} + +HRESULT STDMETHODCALLTYPE WebActiveXContainer::SetStatusText( + LPCOLESTR status_text) { + TRACK_METHOD(); + return E_UNEXPECTED; +} + +HRESULT STDMETHODCALLTYPE WebActiveXContainer::EnableModeless(BOOL enable) { + TRACK_METHOD(); + return E_UNEXPECTED; +} + +HRESULT STDMETHODCALLTYPE WebActiveXContainer::TranslateAccelerator( + LPMSG msg, + WORD id) { + TRACK_METHOD(); + // TODO(ruijiang): Link it with browser message processing. + // Returning S_FALSE means: The keystroke was not used. + return S_FALSE; +} + +// IHTMLDocument2 +HRESULT STDMETHODCALLTYPE WebActiveXContainer::get_URL(BSTR* p) { + TRACK_METHOD(); + std::wstring url = plugin_->GetCurrentURL(); + *p = SysAllocString(url.c_str()); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXContainer::get_cookie(BSTR* p) { + TRACK_METHOD(); + *p = SysAllocString(plugin_->GetWindow(). + GetObjectProperty("document").GetStringProperty("cookie").c_str()); + return S_OK; +} + +// IWebBrowser +HRESULT STDMETHODCALLTYPE WebActiveXContainer::Navigate( + BSTR url, + VARIANT* flags, + VARIANT* target_frame_name, + VARIANT* post_data, + VARIANT* headers) { + TRACK_METHOD(); + // TODO(ruijiang): See if we need to handle the optional params. + plugin_->GetWindow().Invoke("open", "%s%s", url, L"_blank"); + return S_OK; +} + +// IWebBrowserApp +HRESULT STDMETHODCALLTYPE WebActiveXContainer::get_LocationURL( + BSTR* location_url) { + return get_URL(location_url); +} + +// IBindHost + +// Flash uses CreateMoniker to get the url of the movie its "movie" parameter +// points to. We must implement this otherwise Flash will not work. +HRESULT STDMETHODCALLTYPE WebActiveXContainer::CreateMoniker( + LPOLESTR szName, + IBindCtx* bc, + IMoniker** mk, + DWORD reserved) { + TRACK_METHOD(); + std::wstring url = plugin_->ResolveURL(szName); + HRESULT hr = CreateURLMoniker(NULL, url.c_str(), mk); + return hr; +} + +HRESULT STDMETHODCALLTYPE WebActiveXContainer::MonikerBindToStorage( + IMoniker* mk, + IBindCtx* bc, + IBindStatusCallback* bsc, + REFIID riid, + void** obj) { + // QuickTime uses this function to get the movie data from the container. + TRACK_METHOD(); + IBindCtx* new_bc = NULL; + // Logic is a little tricky here. When bc is passed in, we should use that; + // otherwise we need to create a new one and release it after done. + IBindCtx* bc_to_use = bc; + if (bc == NULL) { + CreateBindCtx(0, &new_bc); + if (!new_bc) + return E_FAIL; + bc_to_use = new_bc; + } + // We must register the callback otherwise control will not know when new + // data arrive. + if (bsc) + RegisterBindStatusCallback(bc_to_use, bsc, NULL, 0); + HRESULT hr = mk->BindToStorage(bc_to_use, NULL, riid, obj); + if (new_bc) + new_bc->Release(); + return hr; +} + +HRESULT STDMETHODCALLTYPE WebActiveXContainer::MonikerBindToObject( + IMoniker* mk, + IBindCtx* bc, + IBindStatusCallback* bsc, + REFIID riid, + void** obj) { + TRACK_METHOD(); + return E_NOTIMPL; +} + +HRESULT WebActiveXContainer::CreateControlWithSite(const wchar_t* clsid) { + HRESULT hr; + CLSID id; + hr = CLSIDFromString(const_cast<LPOLESTR>(clsid), &id); + if (FAILED(hr)) + return hr; + + IUnknown* control; + hr = CoCreateInstance(id, NULL, CLSCTX_INPROC_SERVER, __uuidof(IUnknown), + (LPVOID*)&control); + if (FAILED(hr)) + return hr; + + // First try to get the IObjectSafety interface and get/set options. + // If failed then see if the object has registered itself as safe. + unsigned long safety_flag = GetAndSetObjectSafetyOptions(control); + if (!(safety_flag & SAFE_FOR_INITIALIZING) || + !(safety_flag & SAFE_FOR_SCRIPTING)) { + safety_flag = GetRegisteredObjectSafetyOptions(id); + if (!(safety_flag & SAFE_FOR_INITIALIZING) || + !(safety_flag & SAFE_FOR_SCRIPTING)) + return E_FAIL; + } + + // Create client site and pass it to the control. + WebActiveXSite* site = new NoRefIUnknownImpl<WebActiveXSite>; + // From now on, we should assume site will take care of the lifecycle + // of control. + site->Init(this, control); + control = NULL; + + sites_.push_back(site); + return S_OK; +} + +bool WebActiveXContainer::OnWindowMessage(UINT msg, WPARAM wparam, + LPARAM lparam, LRESULT* result) { + HRESULT hr; + for (unsigned int i = 0; i < sites_.size(); i++) { + WebActiveXSite* site = sites_[i]; + CComQIPtr<IOleInPlaceObjectWindowless> windowless = site->control_; + if (windowless == NULL) + continue; + + if (msg == WM_MOUSEMOVE || msg == WM_LBUTTONDOWN || msg == WM_LBUTTONUP) { + POINT pt; + pt.x = LOWORD(lparam); + pt.y = HIWORD(lparam); + if (PtInRect(&site->rect_, pt)) { + hr = windowless->OnWindowMessage(msg, wparam, lparam, result); + if (hr == S_OK) + return true; + } + } + } + + // We did not consume the message. The caller can now process it. + return false; +} + +IUnknown* WebActiveXContainer::GetFirstControl() { + if (sites_.size()) { + return sites_[0]->control_; + } else { + return NULL; + } +} + +WebActiveXSite* WebActiveXContainer::GetFirstSite() { + if (sites_.size()) { + return sites_[0]; + } else { + return NULL; + } +} + +} // namespace activex_shim diff --git a/webkit/activex_shim/web_activex_container.h b/webkit/activex_shim/web_activex_container.h new file mode 100644 index 0000000..6b0e2b0 --- /dev/null +++ b/webkit/activex_shim/web_activex_container.h @@ -0,0 +1,216 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef WEBKIT_ACTIVEX_SHIM_WEB_ACTIVEX_CONTAINER_H__ +#define WEBKIT_ACTIVEX_SHIM_WEB_ACTIVEX_CONTAINER_H__ + +#include <atlbase.h> +#include <atlcom.h> +#include <string> +#include <vector> +#include "webkit/activex_shim/activex_util.h" +#include "webkit/activex_shim/ihtmldocument_impl.h" +#include "webkit/activex_shim/iwebbrowser_impl.h" + +namespace activex_shim { + +class ActiveXPlugin; +class WebActiveXSite; + +// WebActiveXContainer, as the container of the ActiveX control, +// implements the basic interfaces need to manage and interact with ActiveX +// controls. +// Theoretically this container can hold multiple sites/controls. However, +// in our case we only use 1 container per control for now. +// +// IOleContainer: +// Required interface. +// IOleInPlaceFrame +// Required interface. +// IHTMLDocument2: +// WMP will query this interface to get URL. +// IWebBrowser2: +// Flash will use IWebBrowser::Navigate to open a URL. +// IBindHost: +// Flash will use this interface to resolve URL. +class WebActiveXContainer : public IOleContainer, + public IOleInPlaceFrame, + public IHTMLDocument2Impl, + public IWebBrowser2Impl, + public IBindHost { + public: + WebActiveXContainer(); + virtual ~WebActiveXContainer(); + + // Initialize container with related ActiveXPlugin. + void Init(ActiveXPlugin* plugin); + // Deactivate and release contained controls. called by outer + // NoRefIUnknownImpl's destructor. + void FinalRelease(); + + // Create ActiveX control together with its site. Do not do any initialization + // now but we will query the interface that the control can support, + // to decide whether it is viewable, supports windowless etc. + HRESULT CreateControlWithSite(const wchar_t* clsid); + // Called by ActiveXPlugin when it gets browser window first time. + void set_container_wnd(HWND hwnd) { container_wnd_ = hwnd; } + HWND container_wnd() { return container_wnd_; } + // Returns the IUnknown of the first control. NULL if it doesn't have any. + IUnknown* GetFirstControl(); + // Returns the first site. NULL if it doesn't have any. + WebActiveXSite* GetFirstSite(); + ActiveXPlugin* plugin() { return plugin_; } + + // The containing Window should call this upon messages. Return true if we + // consumed the message + bool OnWindowMessage(UINT msg, WPARAM wparam, LPARAM lparam, + LRESULT* result); + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, + void** object); + + // IDispatch + virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* ctinfo) { + TRACK_METHOD(); + *ctinfo = 0; + return S_OK; + } + virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT itinfo, LCID lcid, + ITypeInfo** tinfo) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames( + REFIID riid, + LPOLESTR* names, + UINT cnames, + LCID lcid, + DISPID* dispids) { + TRACK_METHOD(); + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE Invoke( + DISPID dispid, + REFIID riid, + LCID lcid, + WORD flags, + DISPPARAMS* params, + VARIANT* result, + EXCEPINFO* except_info, + UINT* arg_error) { + TRACK_METHOD(); + return E_NOTIMPL; + } + + // IParseDisplayName + virtual HRESULT STDMETHODCALLTYPE ParseDisplayName( + IBindCtx* bc, + LPOLESTR display_name, + ULONG* cheaten, + IMoniker** moniker); + + // IOleContainer + virtual HRESULT STDMETHODCALLTYPE EnumObjects(DWORD flags, + IEnumUnknown** ppenum); + virtual HRESULT STDMETHODCALLTYPE LockContainer(BOOL lock); + + // IOleWindow + virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND* wnd); + virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL enter_mode); + + // IOleInPlaceUIWindow + virtual HRESULT STDMETHODCALLTYPE GetBorder(LPRECT border); + virtual HRESULT STDMETHODCALLTYPE RequestBorderSpace( + LPCBORDERWIDTHS border_widths); + virtual HRESULT STDMETHODCALLTYPE SetBorderSpace( + LPCBORDERWIDTHS border_widths); + virtual HRESULT STDMETHODCALLTYPE SetActiveObject( + IOleInPlaceActiveObject* active_object, + LPCOLESTR obj_name); + + // IOleInPlaceFrame + virtual HRESULT STDMETHODCALLTYPE InsertMenus( + HMENU hmenu_shared, + LPOLEMENUGROUPWIDTHS menu_widths); + virtual HRESULT STDMETHODCALLTYPE SetMenu( + HMENU hmenu_shared, + HOLEMENU hole_menu, + HWND active_object); + virtual HRESULT STDMETHODCALLTYPE RemoveMenus(HMENU hmenu_shared); + virtual HRESULT STDMETHODCALLTYPE SetStatusText(LPCOLESTR status_text); + virtual HRESULT STDMETHODCALLTYPE EnableModeless(BOOL enable); + virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator( + LPMSG msg, + WORD id); + + // IHTMLDocument2 + virtual HRESULT STDMETHODCALLTYPE get_URL(BSTR* p); + virtual HRESULT STDMETHODCALLTYPE get_cookie(BSTR* p); + + // IWebBrowser + virtual HRESULT STDMETHODCALLTYPE Navigate(BSTR url, + VARIANT* flags, + VARIANT* target_frame_name, + VARIANT* post_data, + VARIANT* headers); + + // IWebBrowserApp + virtual HRESULT STDMETHODCALLTYPE get_LocationURL(BSTR* location_url); + + // IBindHost + virtual HRESULT STDMETHODCALLTYPE CreateMoniker( + LPOLESTR szName, + IBindCtx* bc, + IMoniker** mk, + DWORD reserved); + virtual HRESULT STDMETHODCALLTYPE MonikerBindToStorage( + IMoniker* mk, + IBindCtx* bc, + IBindStatusCallback* bsc, + REFIID riid, + void** obj); + virtual HRESULT STDMETHODCALLTYPE MonikerBindToObject( + IMoniker* mk, + IBindCtx* bc, + IBindStatusCallback* bsc, + REFIID riid, + void** obj); + + private: + ActiveXPlugin* plugin_; + HWND container_wnd_; + std::vector<WebActiveXSite*> sites_; + + DISALLOW_EVIL_CONSTRUCTORS(WebActiveXContainer); +}; + +} // namespace activex_shim + +#endif // #ifndef WEBKIT_ACTIVEX_SHIM_WEB_ACTIVEX_CONTAINER_H__ diff --git a/webkit/activex_shim/web_activex_site.cc b/webkit/activex_shim/web_activex_site.cc new file mode 100644 index 0000000..85bf675 --- /dev/null +++ b/webkit/activex_shim/web_activex_site.cc @@ -0,0 +1,692 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "webkit/activex_shim/web_activex_site.h" + +#include <exdisp.h> +#include <oaidl.h> +#include <shlguid.h> + +#include "base/string_util.h" +#include "webkit/activex_shim/activex_plugin.h" +#include "webkit/activex_shim/npp_impl.h" +#include "webkit/activex_shim/web_activex_container.h" + +namespace activex_shim { + +// WebActiveXSite +WebActiveXSite::WebActiveXSite() + : container_(NULL), + control_(NULL), + inplace_activated_(false), + has_capture_(false) { + rect_.left = 0; + rect_.top = 0; + rect_.right = 0; + rect_.bottom = 0; +} + +WebActiveXSite::~WebActiveXSite() { + // Don't do anything here. Do everything in FinalRelease. +} + +void WebActiveXSite::Init(WebActiveXContainer* container, IUnknown* control) { + container_ = container; + control_.Attach(control); + dispatch_ = control; + ole_object_ = control; + inplace_object_ = control; + view_object_ = control; + inplace_object_windowless_ = control; +} + +void WebActiveXSite::FinalRelease() { + // We must release everything here instead of leaving it to the destructor. + // Otherwise crash is possible. + if (control_ != NULL) { + dispatch_.Release(); + view_object_.Release(); + inplace_object_windowless_.Release(); + if (inplace_object_ != NULL) { + if (inplace_activated_) { + // If we just deactivate without checking whether the control has been + // inplace activated, the control may behave irratically. Flash will + // decrease its reference count during deactivation. Thus causing + // crash when we try to release it later. + inplace_object_->InPlaceDeactivate(); + inplace_activated_ = false; + } + inplace_object_.Release(); + } + if (ole_object_ != NULL) { + ole_object_->SetClientSite(NULL); + ole_object_->Close(OLECLOSE_NOSAVE); + ole_object_.Release(); + } + long ref = control_.Detach()->Release(); + // It should be 0 otherwise we have incorrect ref counting. + // Shockwave is known to have ref counting problems. All other controls + // behave well. + DCHECK(ref == 0 || container_->plugin()->activex_type() + == ACTIVEX_SHOCKWAVE); + } +} + +HRESULT WebActiveXSite::ActivateControl( + int x, int y, int width, int height, + const std::vector<ControlParam>& params) { + // Set the rect size of site first before SetClientSite. Otherwise the + // control may query the site for such information during SetClientSite. + rect_.left = x; + rect_.top = y; + rect_.right = rect_.left + width; + rect_.bottom = rect_.top + height; + + HRESULT hr; + if (ole_object_ != NULL) { + hr = ole_object_->SetClientSite(static_cast<IOleClientSite*>(this)); + if (FAILED(hr)) + return hr; + } + SetExtent(width, height); + + // Set initial properties. + CComQIPtr<IPersistPropertyBag> persist_property_bag = control_; + CComQIPtr<IPersistPropertyBag2> persist_property_bag2 = control_; + if (persist_property_bag2 != NULL || persist_property_bag != NULL) { + // Use property bag for initialization. This is the preferred way. + initial_params_ = params; + // Use bag2 first. + if (persist_property_bag2 != NULL) { + persist_property_bag2->InitNew(); + hr = persist_property_bag2->Load(this, NULL); + DCHECK(SUCCEEDED(hr)); + } else { + persist_property_bag->InitNew(); + hr = persist_property_bag->Load(this, NULL); + DCHECK(SUCCEEDED(hr)); + } + // We don't need this anymore. + initial_params_.clear(); + } else if (dispatch_ != NULL) { + // Use the dispatch interface to set the initial properties. This is + // less efficient for most controls. + for (unsigned int i = 0; i < params.size(); ++i) { + const ControlParam& param = params[i]; + VARIANT vtvalue; + // TODO(ruijiang): Think about type conversion. + vtvalue.vt = VT_BSTR; + vtvalue.bstrVal = SysAllocString(param.value.c_str()); + DispSetProperty(dispatch_, param.name.c_str(), vtvalue); + VariantClear(&vtvalue); + } + } + + // In place activate it if it is able to. + if (inplace_object_ != NULL) { + hr = DoVerb(OLEIVERB_INPLACEACTIVATE); + if (FAILED(hr)) + return hr; + } + + return S_OK; +} + +HRESULT WebActiveXSite::DoVerb(long verb) { + if (ole_object_ != NULL) { + HRESULT hr = ole_object_->DoVerb(verb, NULL, + static_cast<IOleClientSite*>(this), 0, + container_->container_wnd(), &rect_); + if (verb == OLEIVERB_INPLACEACTIVATE && SUCCEEDED(hr)) + inplace_activated_ = true; + return hr; + } else { + return E_UNEXPECTED; + } +} + +HRESULT WebActiveXSite::SetExtent(int width, int height) { + if (ole_object_ != NULL) { + SIZEL size; + if (width < 0) + width = 0; + if (height < 0) + height = 0; + ScreenToHimetric(width, height, &size); + return ole_object_->SetExtent(DVASPECT_CONTENT, &size); + } else { + return E_UNEXPECTED; + } +} + +void WebActiveXSite::SetRect(const RECT* rect) { + if (EqualRect(&rect_, rect)) + return; + SetExtent(rect->right - rect->left, rect->bottom - rect->top); + if (inplace_object_ != NULL) { + inplace_object_->SetObjectRects(rect, rect); + rect_ = *rect; + } +} + +// IUnknown +HRESULT STDMETHODCALLTYPE WebActiveXSite::QueryInterface(REFIID iid, + void** object) { + *object = NULL; + if (iid == IID_IUnknown) { + // Avoid ambiguous resolution of IUnknown. + *object = static_cast<IUnknown*>(static_cast<MinimumIDispatchImpl*>(this)); + } else if (iid == IID_IDispatch) { + *object = static_cast<MinimumIDispatchImpl*>(this); + } else if (iid == IID_IOleClientSite) { + *object = static_cast<IOleClientSite*>(this); + } else if (iid == IID_IOleControlSite) { + *object = static_cast<IOleControlSite*>(this); + } else if (iid == IID_IOleInPlaceSite) { + *object = static_cast<IOleInPlaceSite*>(this); + } else if (iid == IID_IOleInPlaceSiteEx) { + *object = static_cast<IOleInPlaceSiteEx*>(this); + } else if (iid == IID_IOleInPlaceSiteWindowless) { + if (container_->plugin()->windowless()) + *object = static_cast<IOleInPlaceSiteWindowless*>(this); + } else if (iid == IID_IServiceProvider) { + *object = static_cast<IServiceProvider*>(this); + } else if (iid == IID_IPropertyBag) { + *object = static_cast<IPropertyBag*>(this); + } else if (iid == IID_IPropertyBag2) { + *object = static_cast<IPropertyBag2*>(this); + } + TRACK_QUERY_INTERFACE(iid, *object != NULL); + return (*object != NULL) ? S_OK : E_NOINTERFACE; +} + +// IOleClientSite +HRESULT STDMETHODCALLTYPE WebActiveXSite::SaveObject() { + // Do not support saving object to persistant storage. + return E_NOTIMPL; +} + +// Even though Flash will call this method to get the url, it will not use +// the url to resolve its movie path. +// However, according to http://support.microsoft.com/kb/181678, this is +// a valid way of getting url from ActiveX control. +HRESULT STDMETHODCALLTYPE WebActiveXSite::GetMoniker( + DWORD assign, + DWORD which_moniker, + IMoniker** moniker) { + TRACK_METHOD(); + if (which_moniker == OLEWHICHMK_CONTAINER) { + std::wstring url = container_->plugin()->GetCurrentURL(); + HRESULT hr = CreateURLMoniker(NULL, url.c_str(), moniker); + return hr; + } else { + return E_FAIL; + } +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::GetContainer( + IOleContainer** container) { + *container = container_; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::ShowObject() { + TRACK_METHOD(); + // The control asks us to show the object which we already did. + return S_OK; +}; + +HRESULT STDMETHODCALLTYPE WebActiveXSite::OnShowWindow(BOOL show) { + TRACK_METHOD(); + // Doesn't apply to us. + return S_OK; +}; + +HRESULT STDMETHODCALLTYPE WebActiveXSite::RequestNewObjectLayout() { + TRACK_METHOD(); + // As MSDN says: "Currently, there is no standard mechanism by which + // a container can negotiate how much room an object would like. When + // such a negotiation is defined, responding to this method will be + // optional for containers." + return E_NOTIMPL; +} + +// IOleControlSite +HRESULT STDMETHODCALLTYPE WebActiveXSite::OnControlInfoChanged() { + TRACK_METHOD(); + // As we do not support mnemonics, we do not need to retrieve control info. + // This may change in the future though. + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::LockInPlaceActive(BOOL lock) { + TRACK_METHOD(); + // We don't support this. + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::GetExtendedControl(IDispatch** disp) { + TRACK_METHOD(); + // We do not support extended control. + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::TransformCoords(POINTL* ptl_himetric, + POINTF* ptf_container, + DWORD flags) { + TRACK_METHOD(); + // TODO(ruijiang): so far haven't found anyone use this yet. Be aware and + // add support if needed. + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::TranslateAccelerator( + MSG* msg, + DWORD modifiers) { + TRACK_METHOD(); + // It would be nice if controls call this and let me process accelerator + // first. But unfortunately all of them I tested don't. So let's ignore + // and just keep an eye on it. + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::OnFocus(BOOL got_focus) { + TRACK_METHOD(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::ShowPropertyFrame() { + TRACK_METHOD(); + // No we don't want to show property sheet. + return E_NOTIMPL; +} + +// IOleWindow + +HRESULT STDMETHODCALLTYPE WebActiveXSite::GetWindow(HWND* wnd) { + *wnd = container_->container_wnd(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::ContextSensitiveHelp( + BOOL enter_mode) { + // Do not support this. + return E_NOTIMPL; +} + +// IOleInPlaceSite + +HRESULT STDMETHODCALLTYPE WebActiveXSite::CanInPlaceActivate() { + TRACK_METHOD(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::OnInPlaceActivate() { + TRACK_METHOD(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::OnInPlaceDeactivate() { + TRACK_METHOD(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::OnUIActivate() { + TRACK_METHOD(); + // If we have multiple sites in a container we may deactivate the previous + // active control. This is not a requirement though. + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::OnUIDeactivate(BOOL undoable) { + TRACK_METHOD(); + // Some controls will call this when they lose focus. Right now we don't need + // to do anything about it. + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::GetWindowContext( + IOleInPlaceFrame** frame, + IOleInPlaceUIWindow** doc, + LPRECT pos, + LPRECT clip, + LPOLEINPLACEFRAMEINFO frame_info) { + TRACK_METHOD(); + if (frame) { + *frame = container_; + } + if (doc) + *doc = NULL; + if (pos) + *pos = rect_; + if (clip) + *clip = rect_; + if (frame_info) { + frame_info->fMDIApp = FALSE; + frame_info->hwndFrame = container_->container_wnd(); + frame_info->haccel = NULL; + frame_info->cAccelEntries = 0; + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::Scroll(SIZE scroll_extant) { + TRACK_METHOD(); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::DiscardUndoState() { + TRACK_METHOD(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::DeactivateAndUndo() { + TRACK_METHOD(); + // Just let the object know that it's deactivated. + if (inplace_object_ != NULL) + inplace_object_->UIDeactivate(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::OnPosRectChange(LPCRECT pos) { + TRACK_METHOD(); + // We do not let the control move/resize itself. It should be controled + // by the container/browser. + return E_UNEXPECTED; +} + +// IOleInPlaceSiteEx + +HRESULT STDMETHODCALLTYPE WebActiveXSite::OnInPlaceActivateEx( + BOOL* no_redraw, + DWORD flags) { + TRACK_METHOD(); + // Redraw doesn't hurt. + if (no_redraw) + *no_redraw = FALSE; + if (flags & ACTIVATE_WINDOWLESS) { + // TODO(ruijiang): At this point we know for sure the object is activated + // as windowless. Revisit when we implement windowless controls. + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::OnInPlaceDeactivateEx( + BOOL no_redraw) { + TRACK_METHOD(); + // See also: OnInPlaceDeactivate + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::RequestUIActivate() { + TRACK_METHOD(); + return S_OK; +} + +// IOleInPlaceSiteWindowless + +HRESULT STDMETHODCALLTYPE WebActiveXSite::CanWindowlessActivate() { + TRACK_METHOD(); + // Yes, we prefer windowless activation. + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::GetCapture() { + TRACK_METHOD(); + return has_capture_ ? S_OK : S_FALSE; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::SetCapture(BOOL capture) { + TRACK_METHOD(); + // TODO(ruijiang): for now, let's cheat the control that it can always get + // what it wants (capture). + if (capture) { + has_capture_ = true; + return S_OK; + } else { + has_capture_ = false; + return S_OK; + } +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::GetFocus() { + TRACK_METHOD(); + // TODO(ruijiang): handle it. + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::SetFocus(BOOL focus) { + TRACK_METHOD(); + // TODO(ruijiang): handle it. + if (focus) { + return S_FALSE; + } else { + return S_OK; + } +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::GetDC( + LPCRECT rect, + DWORD flags, + HDC* dc) { + // It's probably not wise to get the dc of Chrome window and return it, + // because we always draw onto a memory dc. Thus we may have to disappoint + // the caller. + // TODO(ruijiang): We may enable this for other browsers like FireFox. + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::ReleaseDC(HDC dc) { + // TODO(ruijiang): We may enable this for other browsers like FireFox. + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::InvalidateRect( + LPCRECT rect, + BOOL erase) { + // This would be the rect (in client coord of the control) that we will + // invalidate. + RECT rc; + // Control's client area, start from top-left corner as 0. + RECT client = rect_; + OffsetRect(&client, -rect_.left, -rect_.top); + if (rect) { + RECT rc_in_client = *rect; + OffsetRect(&rc_in_client, -rect_.left, -rect_.top); + if (!IntersectRect(&rc, &rc_in_client, &client)) + return S_OK; + } else { + rc = client; + } + // Convert it to NPRect. Now rc is relative to the upper-left corner of + // control. This is the requirement of NPN_InvalidateRect. + NPRect npr; + npr.left = static_cast<uint16>(rc.left); + npr.top = static_cast<uint16>(rc.top); + npr.right = static_cast<uint16>(rc.right); + npr.bottom = static_cast<uint16>(rc.bottom); + g_browser->invalidaterect(container_->plugin()->npp(), &npr); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::InvalidateRgn( + HRGN rgn, + BOOL erase) { + TRACK_METHOD(); + if (rgn == NULL) { + return InvalidateRect(NULL, erase); + } else { + // TODO(ruijiang): So far no one is using this function yet. So let's just + // invalidate the whole area. Optimize this when we need to. + return InvalidateRect(NULL, erase); + } +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::ScrollRect( + INT dx, + INT dy, + LPCRECT scroll, + LPCRECT clip) { + TRACK_METHOD(); + // TODO(ruijiang): revisit. + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::AdjustRect(LPRECT rc) { + TRACK_METHOD(); + // TODO(ruijiang): revisit. + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::OnDefWindowMessage( + UINT msg, + WPARAM wparam, + LPARAM lparam, + LRESULT* result) { + TRACK_METHOD(); + // TODO(ruijiang): handle it later. + return E_NOTIMPL; +} + +// IServiceProvider +HRESULT STDMETHODCALLTYPE WebActiveXSite::QueryService( + REFGUID guid, + REFIID riid, + void** object) { + HRESULT hr = E_FAIL; + // TODO(ruijiang): We may need to support SID_SWebBrowserApp and + // IID_IHTMLWindow2 in the future. + if (guid == IID_IBindHost || guid == IID_IWebBrowserApp) + hr = container_->QueryInterface(riid, object); + TRACK_QUERY_INTERFACE(riid, *object != NULL); + return hr; +} + +// IPropertyBag +HRESULT STDMETHODCALLTYPE WebActiveXSite::Read(LPCOLESTR prop_name, + VARIANT* var, + IErrorLog* err_log) { + unsigned int i; + for (i = 0; i < initial_params_.size(); ++i) { + if (_wcsicmp(prop_name, initial_params_[i].name.c_str()) == 0) + break; + } + if (i >= initial_params_.size()) + return E_INVALIDARG; + if (var->vt == VT_EMPTY || var->vt == VT_BSTR) { + // We don't need to do any conversion in this case. + var->vt = VT_BSTR; + var->bstrVal = ::SysAllocString(initial_params_[i].value.c_str()); + return S_OK; + } else { + // We need to try type conversion. + ScopedVariant org; + org.vt = VT_BSTR; + org.bstrVal = ::SysAllocString(initial_params_[i].value.c_str()); + HRESULT hr = VariantChangeType(var, &org, 0, var->vt); + return FAILED(hr) ? E_FAIL : S_OK; + } +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::Write(LPCOLESTR prop_name, + VARIANT* var) { + TRACK_METHOD(); + return E_NOTIMPL; +} + +// IPropertyBag2 +HRESULT STDMETHODCALLTYPE WebActiveXSite::Read(ULONG c_properties, + PROPBAG2* prop_bag, + IErrorLog* err_log, + VARIANT* value, + HRESULT* error) { + if (!prop_bag) + return E_INVALIDARG; + for (unsigned int i = 0; i < c_properties; ++i) { + PROPBAG2* p = prop_bag + i; + value->vt = p->vt; + HRESULT hr = Read(p->pstrName, value + i, err_log); + if (error) + error[i] = hr; + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::Write(ULONG c_properties, + PROPBAG2* prop_bag, + VARIANT* value) { + TRACK_METHOD(); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::CountProperties( + ULONG* pc_properties) { + if (!pc_properties) + return E_INVALIDARG; + *pc_properties = static_cast<ULONG>(initial_params_.size()); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::GetPropertyInfo( + ULONG iproperty, + ULONG c_properties, + PROPBAG2* prop_bag, + ULONG* properties_returned) { + if (!prop_bag) + return E_INVALIDARG; + if (iproperty >= initial_params_.size()) + return E_INVALIDARG; + unsigned int i; + for (i = iproperty; + i < iproperty + c_properties && i < initial_params_.size(); + ++i) { + PROPBAG2* p = prop_bag + (i - iproperty); + memset(p, 0, sizeof(PROPBAG2)); + p->dwType = PROPBAG2_TYPE_DATA; + p->vt = VT_BSTR; + p->cfType = CF_TEXT; + p->dwHint = iproperty; + // According to the document of IPropertyBag2::GetPropertyInfo, here + // requires a string allocated by CoTaskMemAlloc. + p->pstrName = CoTaskMemAllocString(initial_params_[i].name); + } + if (properties_returned) + *properties_returned = i - iproperty; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebActiveXSite::LoadObject(LPCOLESTR name, + DWORD hint, + IUnknown* unk_object, + IErrorLog* err_log) { + TRACK_METHOD(); + return E_NOTIMPL; +} + +} // namespace activex_shim diff --git a/webkit/activex_shim/web_activex_site.h b/webkit/activex_shim/web_activex_site.h new file mode 100644 index 0000000..1a94020 --- /dev/null +++ b/webkit/activex_shim/web_activex_site.h @@ -0,0 +1,250 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef WEBKIT_ACTIVEX_SHIM_WEB_ACTIVEX_SITE_H__ +#define WEBKIT_ACTIVEX_SHIM_WEB_ACTIVEX_SITE_H__ + +#include <atlbase.h> +#include <atlcom.h> +#include <objsafe.h> +#include <map> +#include <vector> +#include "webkit/activex_shim/activex_util.h" + +namespace activex_shim { + +class WebActiveXContainer; +class ActiveXPlugin; + +// Control creation parameters +struct ControlParam { + ControlParam(const std::wstring& new_name, const std::wstring& new_value) { + name = new_name; + value = new_value; + } + ControlParam() { } + std::wstring name; + std::wstring value; +}; + +// ActiveX control site to receive requests etc from the ActiveX control, +// and interact the container to host a control. +// Implemented interfaces: +// IDispatch: +// Required for ambient properties. +// IOleClientSite: +// Required interface. +// IOleControlSite: +// Required interface. +// IOleInPlaceSiteWindowless: +// Required for windowless activation. +// IServiceProvider: +// Some controls use this interface to get interface to the IBindHost, +// IWebBrowserApp interfaces. e.g., Flash needs the IBindHost to create +// a moniker to the movie. Thus this is a required interface. +// IPropertyBag: +// If the control supports IPersistPropertyBag, we could use this interface +// to initialize the control with param values. +class WebActiveXSite : public MinimumIDispatchImpl, + public IOleClientSite, + public IOleControlSite, + public IOleInPlaceSiteWindowless, + public IServiceProvider, + public IPropertyBag, + public IPropertyBag2 { + public: + WebActiveXSite(); + // It's necessary to make it virtual because we do not directly create + // this object. Instead we usually create NoRefIUnknownImpl<WebActiveXSite> + virtual ~WebActiveXSite(); + + // Container calls this to init a site. The container should assume passing + // the ownership of IUnknown to site, and not try to release control there + // after. Site will release control in FinalRelease. + void Init(WebActiveXContainer* container, IUnknown* control); + // Deactive and release ActiveX control. Cleanup everything. + void FinalRelease(); + // Sets the extent of the control, params and inplace activates it. + HRESULT ActivateControl(int x, int y, int width, int height, + const std::vector<ControlParam>& params); + // A simplified version of calling control's DoVerb. + HRESULT DoVerb(long verb); + // Changes the position/size of the control. The container/plugin is + // responsible to call this everytime the control's position/size changed. + void SetRect(const RECT* rect); + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, + void** object); + + // IOleClientSite + virtual HRESULT STDMETHODCALLTYPE SaveObject(); + virtual HRESULT STDMETHODCALLTYPE GetMoniker( + DWORD assign, + DWORD which_moniker, + IMoniker** moniker); + virtual HRESULT STDMETHODCALLTYPE GetContainer(IOleContainer** container); + virtual HRESULT STDMETHODCALLTYPE ShowObject(); + virtual HRESULT STDMETHODCALLTYPE OnShowWindow(BOOL show); + virtual HRESULT STDMETHODCALLTYPE RequestNewObjectLayout(); + + // IOleControlSite + virtual HRESULT STDMETHODCALLTYPE OnControlInfoChanged(); + virtual HRESULT STDMETHODCALLTYPE LockInPlaceActive(BOOL lock); + virtual HRESULT STDMETHODCALLTYPE GetExtendedControl(IDispatch** disp); + virtual HRESULT STDMETHODCALLTYPE TransformCoords(POINTL* ptl_himetric, + POINTF* ptf_container, + DWORD flags); + virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(MSG* msg, + DWORD modifiers); + virtual HRESULT STDMETHODCALLTYPE OnFocus(BOOL got_focus); + virtual HRESULT STDMETHODCALLTYPE ShowPropertyFrame(); + + // IOleWindow + virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND* wnd); + virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL enter_mode); + + // IOleInPlaceSite + virtual HRESULT STDMETHODCALLTYPE CanInPlaceActivate(); + virtual HRESULT STDMETHODCALLTYPE OnInPlaceActivate(); + virtual HRESULT STDMETHODCALLTYPE OnUIActivate(); + virtual HRESULT STDMETHODCALLTYPE GetWindowContext( + IOleInPlaceFrame** frame, + IOleInPlaceUIWindow** doc, + LPRECT pos, + LPRECT clip, + LPOLEINPLACEFRAMEINFO frame_info); + virtual HRESULT STDMETHODCALLTYPE Scroll(SIZE scroll_extant); + virtual HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL undoable); + virtual HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate(); + virtual HRESULT STDMETHODCALLTYPE DiscardUndoState(); + virtual HRESULT STDMETHODCALLTYPE DeactivateAndUndo(); + virtual HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT pos); + + // IOleInPlaceSiteEx + virtual HRESULT STDMETHODCALLTYPE OnInPlaceActivateEx( + BOOL* no_redraw, + DWORD flags); + virtual HRESULT STDMETHODCALLTYPE OnInPlaceDeactivateEx(BOOL no_redraw); + virtual HRESULT STDMETHODCALLTYPE RequestUIActivate(); + + // IOleInPlaceSiteWindowless + virtual HRESULT STDMETHODCALLTYPE CanWindowlessActivate(); + virtual HRESULT STDMETHODCALLTYPE GetCapture(); + virtual HRESULT STDMETHODCALLTYPE SetCapture(BOOL capture); + virtual HRESULT STDMETHODCALLTYPE GetFocus(); + virtual HRESULT STDMETHODCALLTYPE SetFocus(BOOL focus); + virtual HRESULT STDMETHODCALLTYPE GetDC( + LPCRECT rect, + DWORD flags, + HDC* dc); + virtual HRESULT STDMETHODCALLTYPE ReleaseDC(HDC dc); + virtual HRESULT STDMETHODCALLTYPE InvalidateRect( + LPCRECT rect, + BOOL erase); + virtual HRESULT STDMETHODCALLTYPE InvalidateRgn( + HRGN rgn, + BOOL erase); + virtual HRESULT STDMETHODCALLTYPE ScrollRect( + INT dx, + INT dy, + LPCRECT scroll, + LPCRECT clip); + virtual HRESULT STDMETHODCALLTYPE AdjustRect(LPRECT rc); + virtual HRESULT STDMETHODCALLTYPE OnDefWindowMessage( + UINT msg, + WPARAM wparam, + LPARAM lparam, + LRESULT* result); + + // IServiceProvider + virtual HRESULT STDMETHODCALLTYPE QueryService( + REFGUID guid, + REFIID riid, + void** object); + + // IPropertyBag + virtual HRESULT STDMETHODCALLTYPE Read(LPCOLESTR prop_name, VARIANT* var, + IErrorLog* err_log); + virtual HRESULT STDMETHODCALLTYPE Write(LPCOLESTR prop_name, VARIANT* var); + + // IPropertyBag2 + virtual HRESULT STDMETHODCALLTYPE Read(ULONG c_properties, + PROPBAG2* prop_bag, + IErrorLog* err_log, + VARIANT* value, + HRESULT* error); + virtual HRESULT STDMETHODCALLTYPE Write(ULONG c_properties, + PROPBAG2* prop_bag, + VARIANT* value); + virtual HRESULT STDMETHODCALLTYPE CountProperties(ULONG* c_properties); + virtual HRESULT STDMETHODCALLTYPE GetPropertyInfo(ULONG iproperty, + ULONG c_properties, + PROPBAG2* prop_bag, + ULONG* properties_returned); + virtual HRESULT STDMETHODCALLTYPE LoadObject(LPCOLESTR pstr_name, + DWORD hint, + IUnknown* unk_object, + IErrorLog* err_log); + + friend WebActiveXContainer; + friend ActiveXPlugin; + + private: + // Call IOleObject::SetExtent to change the size of the control. width and + // height should be in pixels. + HRESULT SetExtent(int width, int height); + + WebActiveXContainer* container_; + // Theorectically the control could support only IUnknown interface. This is + // is the minimum requirement. + CComPtr<IUnknown> control_; + // These are all optional interfaces and they could be NULL even if we have + // created the control successfully. + CComQIPtr<IDispatch> dispatch_; + CComQIPtr<IOleObject> ole_object_; + CComQIPtr<IOleInPlaceObject> inplace_object_; + CComQIPtr<IViewObject> view_object_; + CComQIPtr<IOleInPlaceObjectWindowless> inplace_object_windowless_; + RECT rect_; + // We need to remember whether we are activated so we can decide whether to + // deactivate during destruction. + bool inplace_activated_; + bool has_capture_; + // We need to save the initial properties so that during control + // initialization, the control can query us (IPropertyBag) for those + // properties. + std::vector<ControlParam> initial_params_; + + DISALLOW_EVIL_CONSTRUCTORS(WebActiveXSite); +}; + +} // namespace activex_shim + +#endif // #ifndef WEBKIT_ACTIVEX_SHIM_WEB_ACTIVEX_SITE_H__ |