summaryrefslogtreecommitdiffstats
path: root/webkit/activex_shim
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-27 00:20:51 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-27 00:20:51 +0000
commitf5b16fed647e941aa66933178da85db2860d639b (patch)
treef00e9856c04aad3b558a140955e7674add33f051 /webkit/activex_shim
parent920c091ac3ee15079194c82ae8a7a18215f3f23c (diff)
downloadchromium_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')
-rw-r--r--webkit/activex_shim/README7
-rw-r--r--webkit/activex_shim/SConscript73
-rw-r--r--webkit/activex_shim/activex_plugin.cc489
-rw-r--r--webkit/activex_shim/activex_plugin.h128
-rw-r--r--webkit/activex_shim/activex_shared.cc253
-rw-r--r--webkit/activex_shim/activex_shared.h91
-rw-r--r--webkit/activex_shim/activex_shim.vcproj204
-rw-r--r--webkit/activex_shim/activex_shim.vsprops12
-rw-r--r--webkit/activex_shim/activex_util.cc495
-rw-r--r--webkit/activex_shim/activex_util.h192
-rw-r--r--webkit/activex_shim/dispatch_object.cc315
-rw-r--r--webkit/activex_shim/dispatch_object.h149
-rw-r--r--webkit/activex_shim/ihtmldocument_impl.h508
-rw-r--r--webkit/activex_shim/iwebbrowser_impl.h328
-rw-r--r--webkit/activex_shim/npn_scripting.cc295
-rw-r--r--webkit/activex_shim/npn_scripting.h120
-rw-r--r--webkit/activex_shim/npp_impl.cc173
-rw-r--r--webkit/activex_shim/npp_impl.h48
-rw-r--r--webkit/activex_shim/web_activex_container.cc371
-rw-r--r--webkit/activex_shim/web_activex_container.h216
-rw-r--r--webkit/activex_shim/web_activex_site.cc692
-rw-r--r--webkit/activex_shim/web_activex_site.h250
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 = &params_[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, &params, &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, &params, 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__