diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:20:51 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:20:51 +0000 |
commit | f5b16fed647e941aa66933178da85db2860d639b (patch) | |
tree | f00e9856c04aad3b558a140955e7674add33f051 /webkit/default_plugin | |
parent | 920c091ac3ee15079194c82ae8a7a18215f3f23c (diff) | |
download | chromium_src-f5b16fed647e941aa66933178da85db2860d639b.zip chromium_src-f5b16fed647e941aa66933178da85db2860d639b.tar.gz chromium_src-f5b16fed647e941aa66933178da85db2860d639b.tar.bz2 |
Add webkit to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/default_plugin')
-rw-r--r-- | webkit/default_plugin/SConscript | 73 | ||||
-rw-r--r-- | webkit/default_plugin/activex_installer.cc | 142 | ||||
-rw-r--r-- | webkit/default_plugin/activex_installer.h | 89 | ||||
-rw-r--r-- | webkit/default_plugin/default_plugin.cc | 45 | ||||
-rw-r--r-- | webkit/default_plugin/default_plugin.ico | bin | 0 -> 4286 bytes | |||
-rw-r--r-- | webkit/default_plugin/default_plugin.vcproj | 183 | ||||
-rw-r--r-- | webkit/default_plugin/default_plugin.vsprops | 12 | ||||
-rw-r--r-- | webkit/default_plugin/default_plugin_shared.h | 51 | ||||
-rw-r--r-- | webkit/default_plugin/install_dialog.cc | 202 | ||||
-rw-r--r-- | webkit/default_plugin/install_dialog.h | 82 | ||||
-rw-r--r-- | webkit/default_plugin/plugin_database_handler.cc | 343 | ||||
-rw-r--r-- | webkit/default_plugin/plugin_database_handler.h | 167 | ||||
-rw-r--r-- | webkit/default_plugin/plugin_impl.cc | 764 | ||||
-rw-r--r-- | webkit/default_plugin/plugin_impl.h | 396 | ||||
-rw-r--r-- | webkit/default_plugin/plugin_install_job_monitor.cc | 124 | ||||
-rw-r--r-- | webkit/default_plugin/plugin_install_job_monitor.h | 91 | ||||
-rw-r--r-- | webkit/default_plugin/plugin_main.cc | 237 | ||||
-rw-r--r-- | webkit/default_plugin/plugin_main.h | 59 |
18 files changed, 3060 insertions, 0 deletions
diff --git a/webkit/default_plugin/SConscript b/webkit/default_plugin/SConscript new file mode 100644 index 0000000..fc6eca2 --- /dev/null +++ b/webkit/default_plugin/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 = [
+ '#/../webkit/glue',
+ '$ICU38/public/common',
+ '$ICU38/public/i18n',
+ '#/../third_party/libxml/include',
+ '#/../third_party/npapi',
+ '#/..',
+ ],
+)
+
+env.Append(
+ CPPDEFINES = [
+ 'U_STATIC_IMPLEMENTATION',
+ 'LIBXML_STATIC',
+ ],
+ CCFLAGS = [
+ '/TP',
+
+ '/WX',
+ '/Wp64',
+
+ '/wd4503',
+ '/wd4819',
+ ],
+)
+
+input_files = [
+ 'activex_installer.cc',
+ 'default_plugin.cc',
+ 'plugin_main.cc',
+ 'plugin_impl.cc',
+ 'plugin_database_handler.cc',
+ 'plugin_install_job_monitor.cc',
+ 'install_dialog.cc',
+]
+
+env.StaticLibrary('default_plugin', input_files)
+
+
diff --git a/webkit/default_plugin/activex_installer.cc b/webkit/default_plugin/activex_installer.cc new file mode 100644 index 0000000..07b05a0 --- /dev/null +++ b/webkit/default_plugin/activex_installer.cc @@ -0,0 +1,142 @@ +// 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/default_plugin/activex_installer.h" +#include "base/string_util.h" + +ActiveXInstaller::ActiveXInstaller() + : wnd_(NULL), + notification_msg_(0) { +} + +void ActiveXInstaller::Cleanup() { + if (bind_ctx_ != NULL) { + RevokeBindStatusCallback(bind_ctx_, this); + bind_ctx_.Release(); + } +} + +HRESULT ActiveXInstaller::StartDownload(const std::string& clsid, + const std::string& codebase, + HWND wnd, + UINT notification_msg) { + wnd_ = wnd; + notification_msg_ = notification_msg; + + HRESULT hr = E_FAIL; + do { + CLSID id; + hr = CLSIDFromString(const_cast<LPOLESTR>(ASCIIToWide(clsid).c_str()), &id); + if (FAILED(hr)) + break; + + // Create the bind context, register it with myself (status callback). + hr = CreateBindCtx(0, &bind_ctx_); + if (FAILED(hr)) + break; + BIND_OPTS opts; + opts.cbStruct = sizeof(opts); + bind_ctx_->GetBindOptions(&opts); + opts.grfFlags |= BIND_MAYBOTHERUSER; + bind_ctx_->SetBindOptions(&opts); + + hr = RegisterBindStatusCallback(bind_ctx_, this, 0, 0); + if (FAILED(hr)) + break; + CComPtr<IClassFactory> class_factory; + hr = CoGetClassObjectFromURL(id, ASCIIToWide(codebase).c_str(), 0xffffffff, + 0xffffffff, NULL, bind_ctx_, + CLSCTX_INPROC_HANDLER | CLSCTX_INPROC_SERVER, + 0, IID_IClassFactory, (void**)&class_factory); + } while(false); + + switch (hr) { + case S_OK: + PostMessage(wnd_, notification_msg_, hr, 0); + break; + case MK_S_ASYNCHRONOUS: + // Still need to wait until IBindStatusCallback is updated. + break; + default: + PostMessage(wnd_, notification_msg_, hr, 0); + break; + } + return hr; +} + +HRESULT STDMETHODCALLTYPE ActiveXInstaller::OnStartBinding(DWORD dw_reserved, + IBinding* pib) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE ActiveXInstaller::GetPriority(LONG* pn_priority) { + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE ActiveXInstaller::OnLowResource(DWORD reserved) { + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE ActiveXInstaller::OnProgress(ULONG ul_progress, + ULONG ul_progress_max, + ULONG ul_status_code, + LPCWSTR sz_status_text) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE ActiveXInstaller::OnStopBinding(HRESULT hresult, + LPCWSTR sz_error) { + if (wnd_) + PostMessage(wnd_, notification_msg_, hresult, 0); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE ActiveXInstaller::GetBindInfo(DWORD* grf_bindf, + BINDINFO* pbindinfo) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE ActiveXInstaller::OnDataAvailable( + DWORD grf_bscf, + DWORD dw_size, + FORMATETC* pformatetc, + STGMEDIUM* pstgmed) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE ActiveXInstaller::OnObjectAvailable(REFIID riid, + IUnknown* punk) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE ActiveXInstaller::GetWindow(REFGUID rguid_reason, + HWND* phwnd) { + *phwnd = wnd_; + return S_OK; +} diff --git a/webkit/default_plugin/activex_installer.h b/webkit/default_plugin/activex_installer.h new file mode 100644 index 0000000..08d6404 --- /dev/null +++ b/webkit/default_plugin/activex_installer.h @@ -0,0 +1,89 @@ +// 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_DEFAULT_PLUGIN_ACTIVEX_INSTALLER_H__ +#define WEBKIT_DEFAULT_PLUGIN_ACTIVEX_INSTALLER_H__ + +#include <atlbase.h> +#include <atlcom.h> +#include <windows.h> +#include <string> + +// ActiveXInstaller is to help install an ActiveX control from a URL, usually +// given by codebase. +class ActiveXInstaller : public CComObjectRootEx<CComMultiThreadModel>, + public IBindStatusCallback, + public IWindowForBindingUI { + public: + ActiveXInstaller(); + + // Start download and installation for an ActiveX control. After download + // installation, the installer will send notification_msg to wnd, where + // WPARAM of the message denotes the HRESULT. + HRESULT StartDownload(const std::string& clsid, const std::string& codebase, + HWND wnd, UINT notification_msg); + // Revoke binding and release it if it's created. + void Cleanup(); + + // IBindStatusCallback + virtual HRESULT STDMETHODCALLTYPE OnStartBinding(DWORD dw_reserved, + IBinding* pib); + virtual HRESULT STDMETHODCALLTYPE GetPriority(LONG* pn_priority); + virtual HRESULT STDMETHODCALLTYPE OnLowResource(DWORD reserved); + virtual HRESULT STDMETHODCALLTYPE OnProgress(ULONG ul_progress, + ULONG ul_progress_max, + ULONG ul_status_code, + LPCWSTR sz_status_text); + virtual HRESULT STDMETHODCALLTYPE OnStopBinding(HRESULT hresult, + LPCWSTR sz_error); + virtual HRESULT STDMETHODCALLTYPE GetBindInfo(DWORD* grf_bindf, + BINDINFO* pbindinfo); + virtual HRESULT STDMETHODCALLTYPE OnDataAvailable(DWORD grf_bscf, + DWORD dw_size, + FORMATETC* pformatetc, + STGMEDIUM* pstgmed); + virtual HRESULT STDMETHODCALLTYPE OnObjectAvailable(REFIID riid, + IUnknown* punk); + + // IWindowForBindingUI + virtual HRESULT STDMETHODCALLTYPE GetWindow(REFGUID rguid_reason, + HWND* phwnd); + +BEGIN_COM_MAP(ActiveXInstaller) + COM_INTERFACE_ENTRY(IBindStatusCallback) + COM_INTERFACE_ENTRY(IWindowForBindingUI) +END_COM_MAP() + + private: + HWND wnd_; + UINT notification_msg_; + CComPtr<IBindCtx> bind_ctx_; +}; + +#endif // #ifndef WEBKIT_DEFAULT_PLUGIN_ACTIVEX_INSTALLER_H__ diff --git a/webkit/default_plugin/default_plugin.cc b/webkit/default_plugin/default_plugin.cc new file mode 100644 index 0000000..d995cae --- /dev/null +++ b/webkit/default_plugin/default_plugin.cc @@ -0,0 +1,45 @@ +// 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 "base/logging.h" +#include "webkit/default_plugin/plugin_main.h" + +extern "C" { +NPError WINAPI NP_GetEntryPoints(NPPluginFuncs* funcs) { + return default_plugin::NP_GetEntryPoints(funcs); +} + +NPError WINAPI NP_Initialize(NPNetscapeFuncs* funcs) { + return default_plugin::NP_Initialize(funcs); +} + +NPError WINAPI NP_Shutdown() { + return default_plugin::NP_Shutdown(); +} +} // extern "C" diff --git a/webkit/default_plugin/default_plugin.ico b/webkit/default_plugin/default_plugin.ico Binary files differnew file mode 100644 index 0000000..fa794a5 --- /dev/null +++ b/webkit/default_plugin/default_plugin.ico diff --git a/webkit/default_plugin/default_plugin.vcproj b/webkit/default_plugin/default_plugin.vcproj new file mode 100644 index 0000000..f64f00a --- /dev/null +++ b/webkit/default_plugin/default_plugin.vcproj @@ -0,0 +1,183 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="default_plugin" + ProjectGUID="{5916D37D-8C97-424F-A904-74E52594C2D6}" + RootNamespace="default_plugin" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="4" + InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;.\default_plugin.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> + <Configuration + Name="Release|Win32" + ConfigurationType="4" + InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;.\default_plugin.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_installer.cc" + > + </File> + <File + RelativePath=".\activex_installer.h" + > + </File> + <File + RelativePath=".\default_plugin.cc" + > + </File> + <File + RelativePath=".\default_plugin_shared.h" + > + </File> + <File + RelativePath=".\install_dialog.cc" + > + </File> + <File + RelativePath=".\install_dialog.h" + > + </File> + <File + RelativePath=".\plugin_database_handler.cc" + > + </File> + <File + RelativePath=".\plugin_database_handler.h" + > + </File> + <File + RelativePath=".\plugin_impl.cc" + > + </File> + <File + RelativePath=".\plugin_impl.h" + > + </File> + <File + RelativePath=".\plugin_install_job_monitor.cc" + > + </File> + <File + RelativePath=".\plugin_install_job_monitor.h" + > + </File> + <File + RelativePath=".\plugin_main.cc" + > + </File> + <File + RelativePath=".\plugin_main.h" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/webkit/default_plugin/default_plugin.vsprops b/webkit/default_plugin/default_plugin.vsprops new file mode 100644 index 0000000..db8a4cd --- /dev/null +++ b/webkit/default_plugin/default_plugin.vsprops @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="default plugin" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\third_party\npapi\using_npapi.vsprops;$(SolutionDir)..\third_party\libxml\build\using_libxml.vsprops;$(SolutionDir)..\third_party\icu38\build\using_icu.vsprops" + > + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="$(IntDir)\..\localized_strings" + /> +</VisualStudioPropertySheet> diff --git a/webkit/default_plugin/default_plugin_shared.h b/webkit/default_plugin/default_plugin_shared.h new file mode 100644 index 0000000..f53c3aa --- /dev/null +++ b/webkit/default_plugin/default_plugin_shared.h @@ -0,0 +1,51 @@ +// 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 default plugin + +#ifndef WEBKIT_DEFAULT_PLUGIN_DEFAULT_PLUGIN_SHARED_H +#define WEBKIT_DEFAULT_PLUGIN_DEFAULT_PLUGIN_SHARED_H + +namespace default_plugin { + +// We use the NPNGetValue host function to send notification message to host. +// This corresponds to NPNVariable defined in npapi.h. However, we don't care +// too much about value conflicts because on the host side, it will only respond +// to such request coming from default plugin. +const int kMissingPluginStatusStart = 3000; + +enum MissingPluginStatus { + MISSING_PLUGIN_AVAILABLE, + MISSING_PLUGIN_USER_STARTED_DOWNLOAD +}; + +} // namespace activex_shim + +#endif // #ifndef WEBKIT_DEFAULT_PLUGIN_DEFAULT_PLUGIN_SHARED_H diff --git a/webkit/default_plugin/install_dialog.cc b/webkit/default_plugin/install_dialog.cc new file mode 100644 index 0000000..b0f2125 --- /dev/null +++ b/webkit/default_plugin/install_dialog.cc @@ -0,0 +1,202 @@ +// 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/default_plugin/install_dialog.h" + +#include "base/logging.h" +#include "base/string_util.h" +#include "webkit/default_plugin/plugin_impl.h" +#include "webkit/glue/webkit_glue.h" +// This file is generated when the webkit_strings.grd file is compiled +// It is generated under chrome/webkit/<debug\release>/obj/localized_strings +// folder. This path is added to the include path in the associated vsprops +// file. +#include "webkit_strings.h" + +bool PluginInstallDialog::Initialize(PluginInstallerImpl* plugin_impl, + const std::wstring& plugin_name) { + if (!plugin_impl) { + NOTREACHED(); + return false; + } + + plugin_impl_ = plugin_impl; + plugin_name_ = plugin_name; + return true; +} + +HWND PluginInstallDialog::Create(HWND parent_window, LPARAM init_param) { + // Most of the code here is based on CDialogImpl<T>::Create. + DCHECK(m_hWnd == NULL); + + // Allocate the thunk structure here, where we can fail + // gracefully. + BOOL thunk_inited = m_thunk.Init(NULL, NULL); + if (thunk_inited == FALSE) { + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } + + _AtlWinModule.AddCreateWndData(&m_thunk.cd, this); + +#ifdef _DEBUG + m_bModal = false; +#endif // _DEBUG + + HINSTANCE instance_handle = _AtlBaseModule.GetResourceInstance(); + + HRSRC dialog_resource = FindResource(instance_handle, + MAKEINTRESOURCE(IDD), RT_DIALOG); + if (!dialog_resource) { + NOTREACHED(); + return NULL; + } + + HGLOBAL dialog_template = LoadResource(instance_handle, + dialog_resource); + if (!dialog_template) { + NOTREACHED(); + return NULL; + } + + _DialogSplitHelper::DLGTEMPLATEEX* dialog_template_struct = + reinterpret_cast<_DialogSplitHelper::DLGTEMPLATEEX *>( + ::LockResource(dialog_template)); + DCHECK(dialog_template_struct != NULL); + + unsigned long dialog_template_size = + SizeofResource(instance_handle, dialog_resource); + + HGLOBAL rtl_layout_dialog_template = NULL; + + if (IsRTLLayout()) { + rtl_layout_dialog_template = GlobalAlloc(GPTR, dialog_template_size); + DCHECK(rtl_layout_dialog_template != NULL); + + _DialogSplitHelper::DLGTEMPLATEEX* rtl_layout_dialog_template_struct = + reinterpret_cast<_DialogSplitHelper::DLGTEMPLATEEX*>( + ::GlobalLock(rtl_layout_dialog_template)); + DCHECK(rtl_layout_dialog_template_struct != NULL); + + memcpy(rtl_layout_dialog_template_struct, dialog_template_struct, + dialog_template_size); + + rtl_layout_dialog_template_struct->exStyle |= + (WS_EX_LAYOUTRTL | WS_EX_RTLREADING); + + dialog_template_struct = rtl_layout_dialog_template_struct; + } + + HWND dialog_window = + CreateDialogIndirectParam( + instance_handle, + reinterpret_cast<DLGTEMPLATE*>(dialog_template_struct), + parent_window, StartDialogProc, init_param); + + DCHECK(m_hWnd == dialog_window); + + if (rtl_layout_dialog_template) { + GlobalUnlock(rtl_layout_dialog_template); + GlobalFree(rtl_layout_dialog_template); + } + + return dialog_window; +} + + +LRESULT PluginInstallDialog::OnInitDialog(UINT message, WPARAM wparam, + LPARAM lparam, BOOL& handled) { + std::wstring dialog_title = + PluginInstallerImpl::ReplaceStringForPossibleEmptyReplacement( + IDS_DEFAULT_PLUGIN_CONFIRMATION_DIALOG_TITLE, + IDS_DEFAULT_PLUGIN_CONFIRMATION_DIALOG_TITLE_NO_PLUGIN_NAME, + plugin_name_); + AdjustTextDirectionality(&dialog_title); + SetWindowText(dialog_title.c_str()); + + std::wstring get_the_plugin_btn_msg = + webkit_glue::GetLocalizedString( + IDS_DEFAULT_PLUGIN_GET_THE_PLUGIN_BTN_MSG); + AdjustTextDirectionality(&get_the_plugin_btn_msg); + SetDlgItemText(IDB_GET_THE_PLUGIN, get_the_plugin_btn_msg.c_str()); + + std::wstring cancel_plugin_download_msg = + webkit_glue::GetLocalizedString( + IDS_DEFAULT_PLUGIN_CANCEL_PLUGIN_DOWNLOAD_MSG); + AdjustTextDirectionality(&cancel_plugin_download_msg); + SetDlgItemText(IDCANCEL, cancel_plugin_download_msg.c_str()); + + std::wstring plugin_user_action_msg = + PluginInstallerImpl::ReplaceStringForPossibleEmptyReplacement( + IDS_DEFAULT_PLUGIN_USER_OPTION_MSG, + IDS_DEFAULT_PLUGIN_USER_OPTION_MSG_NO_PLUGIN_NAME, + plugin_name_); + AdjustTextDirectionality(&plugin_user_action_msg); + SetDlgItemText(IDC_PLUGIN_INSTALL_CONFIRMATION_LABEL, + plugin_user_action_msg.c_str()); + return 0; +} + + +LRESULT PluginInstallDialog::OnGetPlugin(WORD notify_code, WORD id, + HWND wnd_ctl, BOOL &handled) { + if (!plugin_impl_) { + NOTREACHED(); + return 0; + } + + DestroyWindow(); + plugin_impl_->DownloadPlugin(); + return 0; +} + +LRESULT PluginInstallDialog::OnCancel(WORD notify_code, WORD id, HWND wnd_ctl, + BOOL &handled) { + DestroyWindow(); + plugin_impl_->DownloadCancelled(); + return 0; +} + + +bool PluginInstallDialog::IsRTLLayout() const { + return plugin_impl_ ? plugin_impl_->IsRTLLayout() : false; +} + +// TODO(idana) bug# 1246452: use the library l10n_util once it is moved from +// the Chrome module into the Base module. For now, we simply copy/paste the +// same code. +void PluginInstallDialog::AdjustTextDirectionality(std::wstring* text) const { + if (IsRTLLayout()) { + // Inserting an RLE (Right-To-Left Embedding) mark as the first character. + text->insert(0, L"\x202B"); + + // Inserting a PDF (Pop Directional Formatting) mark as the last character. + text->append(L"\x202C"); + } +} diff --git a/webkit/default_plugin/install_dialog.h b/webkit/default_plugin/install_dialog.h new file mode 100644 index 0000000..b8e28be --- /dev/null +++ b/webkit/default_plugin/install_dialog.h @@ -0,0 +1,82 @@ +// 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_DEFAULT_PLUGIN_INSTALL_DIALOG_H__ +#define WEBKIT_DEFAULT_PLUGIN_INSTALL_DIALOG_H__ + +#include <atlbase.h> +#include <atlwin.h> +#include <string> + +#include "webkit/glue/webkit_resources.h" + +class PluginInstallerImpl; + +// Displays the plugin installation dialog containing information +// about the mime type of the plugin being downloaded, the URL +// where it would be downloaded from, etc. +class PluginInstallDialog : public CDialogImpl<PluginInstallDialog> { + public: + PluginInstallDialog() + : plugin_impl_(NULL) { + } + ~PluginInstallDialog() {} + + enum {IDD = IDD_DEFAULT_PLUGIN_INSTALL_DIALOG}; + + BEGIN_MSG_MAP(PluginInstallDialog) + MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) + COMMAND_ID_HANDLER(IDB_GET_THE_PLUGIN, OnGetPlugin) + COMMAND_ID_HANDLER(IDCANCEL, OnCancel) + END_MSG_MAP() + + bool Initialize(PluginInstallerImpl* plugin_impl, + const std::wstring& plugin_name); + + // Implemented to ensure that we handle RTL layouts correctly. + HWND Create(HWND parent_window, LPARAM init_param); + + protected: + LRESULT OnInitDialog(UINT message, WPARAM wparam, LPARAM lparam, + BOOL& handled); + LRESULT OnGetPlugin(WORD notify_code, WORD id, HWND wnd_ctl, BOOL &handled); + LRESULT OnCancel(WORD notify_code, WORD id, HWND wnd_ctl, BOOL &handled); + + // Determines whether the UI layout is right-to-left. + bool IsRTLLayout() const; + + // Wraps the string with Unicode directionality characters in order to make + // sure BiDi text is rendered correctly when the UI layout is right-to-left. + void AdjustTextDirectionality(std::wstring* text) const; + + PluginInstallerImpl* plugin_impl_; + std::wstring plugin_name_; +}; + +#endif // WEBKIT_DEFAULT_PLUGIN_INSTALL_DIALOG_H__ diff --git a/webkit/default_plugin/plugin_database_handler.cc b/webkit/default_plugin/plugin_database_handler.cc new file mode 100644 index 0000000..3d534ee --- /dev/null +++ b/webkit/default_plugin/plugin_database_handler.cc @@ -0,0 +1,343 @@ +// 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/default_plugin/plugin_database_handler.h" + +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/string_util.h" +#include "base/time.h" +#include "third_party/libxml/include/libxml/parser.h" +#include "third_party/libxml/include/libxml/xpath.h" +#include "webkit/default_plugin/plugin_impl.h" +#include "webkit/default_plugin/plugin_main.h" + +PluginDatabaseHandler::PluginDatabaseHandler( + PluginInstallerImpl& plugin_installer_instance) + : plugin_downloads_file_(INVALID_HANDLE_VALUE), + plugin_installer_instance_(plugin_installer_instance), + ignore_plugin_db_data_(false) { +} + +PluginDatabaseHandler::~PluginDatabaseHandler() { + if (plugin_downloads_file_ != INVALID_HANDLE_VALUE) { + ::CloseHandle(plugin_downloads_file_); + plugin_downloads_file_ = INVALID_HANDLE_VALUE; + } +} + +bool PluginDatabaseHandler::DownloadPluginsFileIfNeeded( + const std::string& plugin_finder_url) { + DCHECK(!plugin_finder_url.empty()); + // The time in days for which the plugins list is cached. + // TODO(iyengar) Make this configurable. + const int kPluginsListCacheTimeInDays = 3; + + plugin_finder_url_ = plugin_finder_url; + + PathService::Get(base::DIR_MODULE, &plugins_file_); + plugins_file_ += L"\\chrome_plugins_file.xml"; + + bool initiate_download = false; + if (!file_util::PathExists(plugins_file_)) { + initiate_download = true; + } else { + SYSTEMTIME creation_system_time = {0}; + if (!file_util::GetFileCreationLocalTime(plugins_file_, + &creation_system_time)) { + NOTREACHED(); + return false; + } + + FILETIME creation_file_time = {0}; + ::SystemTimeToFileTime(&creation_system_time, &creation_file_time); + + FILETIME current_time = {0}; + ::GetSystemTimeAsFileTime(¤t_time); + + Time file_time = Time::FromFileTime(creation_file_time); + Time current_system_time = Time::FromFileTime(current_time); + + TimeDelta time_diff = file_time - current_system_time; + if (time_diff.InDays() > kPluginsListCacheTimeInDays) { + initiate_download = true; + } + } + + if (initiate_download) { + DLOG(INFO) << "Initiating GetURLNotify on the plugin finder URL " + << plugin_finder_url.c_str(); + + plugin_installer_instance_.set_plugin_installer_state( + PluginListDownloadInitiated); + + DCHECK(default_plugin::g_browser->geturlnotify); + default_plugin::g_browser->geturlnotify( + plugin_installer_instance_.instance(), plugin_finder_url.c_str(), + NULL, NULL); + } else { + DLOG(INFO) << "Plugins file " << plugins_file_.c_str() + << " already exists"; + plugin_downloads_file_ = ::CreateFile(plugins_file_.c_str(), GENERIC_READ, + FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (plugin_downloads_file_ == INVALID_HANDLE_VALUE) { + DLOG(INFO) << "Failed to open plugins file " + << plugins_file_.c_str() << " Error " + << ::GetLastError(); + NOTREACHED(); + return false; + } + // The URLNotify function contains all handling needed to parse the plugins + // file and display the UI accordingly. + plugin_installer_instance_.set_plugin_installer_state( + PluginListDownloadInitiated); + plugin_installer_instance_.URLNotify(plugin_finder_url.c_str(), + NPRES_DONE); + } + return true; +} + +int32 PluginDatabaseHandler::Write(NPStream* stream, int32 offset, + int32 buffer_length, void* buffer) { + if (ignore_plugin_db_data_) { + return buffer_length; + } + + if (plugin_downloads_file_ == INVALID_HANDLE_VALUE) { + DLOG(INFO) << "About to create plugins file " << plugins_file_.c_str(); + plugin_downloads_file_ = CreateFile(plugins_file_.c_str(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + if (plugin_downloads_file_ == INVALID_HANDLE_VALUE) { + unsigned long error = ::GetLastError(); + if (error == ERROR_SHARING_VIOLATION) { + // File may have been downloaded by another plugin instance on this + // page. + plugin_downloads_file_ = ::CreateFile( + plugins_file_.c_str(), GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (plugin_downloads_file_ != INVALID_HANDLE_VALUE) { + ignore_plugin_db_data_ = true; + return buffer_length; + } + } + + DLOG(INFO) << "Failed to create plugins file " + << plugins_file_.c_str() << " Error " + << ::GetLastError(); + NOTREACHED(); + return 0; + } + } + + unsigned long bytes_written = 0; + if (0 == lstrcmpiA(stream->url, plugin_finder_url_.c_str())) { + DCHECK(plugin_downloads_file_ != INVALID_HANDLE_VALUE); + + WriteFile(plugin_downloads_file_, buffer, buffer_length, &bytes_written, + NULL); + DCHECK(buffer_length == bytes_written); + } + return bytes_written; +} + + +bool PluginDatabaseHandler::ParsePluginList() { + if (plugin_downloads_file_ == INVALID_HANDLE_VALUE) { + DLOG(WARNING) << "Invalid plugins file"; + NOTREACHED(); + return false; + } + + bool parse_result = false; + + std::string plugins_file = WideToUTF8(plugins_file_.c_str()); + xmlDocPtr plugin_downloads_doc = xmlParseFile(plugins_file.c_str()); + if (plugin_downloads_doc == NULL) { + DLOG(WARNING) << "Failed to parse plugins file " << plugins_file.c_str(); + return parse_result; + } + + xmlXPathContextPtr context = NULL; + xmlXPathObjectPtr plugins_result = NULL; + + do { + context = xmlXPathNewContext(plugin_downloads_doc); + if (context == NULL) { + DLOG(WARNING) << "Failed to retrieve XPath context"; + NOTREACHED(); + parse_result = false; + break; + } + + plugins_result = + xmlXPathEvalExpression(reinterpret_cast<const xmlChar*>("//plugin"), + context); + if ((plugins_result == NULL) || + xmlXPathNodeSetIsEmpty(plugins_result->nodesetval)) { + DLOG(WARNING) << "Failed to find XPath //plugin"; + NOTREACHED(); + parse_result = false; + break; + } + + xmlNodeSetPtr plugin_list = plugins_result->nodesetval; + for (int plugin_index = 0; plugin_index < plugin_list->nodeNr; + ++plugin_index) { + PluginDetail plugin_detail; + if (!ReadPluginInfo(plugin_list->nodeTab[plugin_index]->children, + &plugin_detail)) { + DLOG(ERROR) << "Failed to read plugin details at index " + << plugin_index; + break; + } + downloaded_plugins_list_.push_back(plugin_detail); + } + if (downloaded_plugins_list_.size()) + parse_result = true; + } while (0); + + xmlXPathFreeContext(context); + xmlXPathFreeObject(plugins_result); + xmlFreeDoc(plugin_downloads_doc); + xmlCleanupParser(); + DLOG(INFO) << "Parse plugins file result " << parse_result; + return parse_result; +} + +bool PluginDatabaseHandler::GetPluginDetailsForMimeType( + const char* mime_type, const char* language, + std::string* download_url, std::wstring* plugin_name) { + if (!mime_type || !language || !download_url || !plugin_name) { + NOTREACHED(); + return false; + } + + PluginList::iterator plugin_index; + for (plugin_index = downloaded_plugins_list_.begin(); + plugin_index != downloaded_plugins_list_.end(); + ++plugin_index) { + const PluginDetail& current_plugin = *plugin_index; + if ((0 == lstrcmpiA(mime_type, current_plugin.mime_type.c_str())) && + (0 == lstrcmpiA(language, current_plugin.language.c_str()))) { + *download_url = current_plugin.download_url; + *plugin_name = current_plugin.display_name; + return true; + } + } + return false; +} + +void PluginDatabaseHandler::Close(bool delete_file) { + if (plugin_downloads_file_ != INVALID_HANDLE_VALUE) { + ::CloseHandle(plugin_downloads_file_); + plugin_downloads_file_ = INVALID_HANDLE_VALUE; + if (delete_file) { + ::DeleteFile(plugins_file_.c_str()); + plugins_file_.clear(); + } + } +} + +bool PluginDatabaseHandler::ReadPluginInfo(_xmlNode* plugin_node, + PluginDetail* plugin_detail) { + if (!plugin_node) { + NOTREACHED(); + return false; + } + + _xmlNode* plugin_mime_type = plugin_node->next; + if ((plugin_mime_type == NULL) || + (plugin_mime_type->next == NULL)) { + DLOG(WARNING) << "Failed to find mime type node in file"; + NOTREACHED(); + return false; + } + + _xmlNode* plugin_mime_type_val = plugin_mime_type->children; + if (plugin_mime_type_val == NULL) { + DLOG(WARNING) << "Invalid mime type"; + NOTREACHED(); + return false; + } + // Skip the first child of each node as it is the text element + // for that node. + _xmlNode* plugin_lang_node = plugin_mime_type->next->next; + if ((plugin_lang_node == NULL) || + (plugin_lang_node->next == NULL)) { + DLOG(WARNING) << "Failed to find plugin language node"; + NOTREACHED(); + return false; + } + _xmlNode* plugin_lang_val = plugin_lang_node->children; + if (plugin_lang_val == NULL) { + DLOG(WARNING) << "Invalid plugin language"; + NOTREACHED(); + return false; + } + _xmlNode* plugin_name_node = plugin_lang_node->next->next; + if ((plugin_name_node == NULL) || + (plugin_name_node->next == NULL)) { + DLOG(WARNING) << "Failed to find plugin name node"; + NOTREACHED(); + return false; + } + _xmlNode* plugin_name_val = plugin_name_node->children; + if (plugin_name_val == NULL) { + DLOG(WARNING) << "Invalid plugin name"; + NOTREACHED(); + return false; + } + _xmlNode* plugin_download_url_node = plugin_name_node->next->next; + if (plugin_download_url_node == NULL) { + DLOG(WARNING) << "Failed to find plugin URL node"; + NOTREACHED(); + return false; + } + _xmlNode* plugin_download_url_val = plugin_download_url_node->children; + if (plugin_download_url_val == NULL) { + DLOG(WARNING) << "Invalid plugin URL"; + NOTREACHED(); + return false; + } + + plugin_detail->display_name = + UTF8ToWide(reinterpret_cast<const char*>(plugin_name_val->content)); + plugin_detail->download_url = + reinterpret_cast<const char*>(plugin_download_url_val->content); + plugin_detail->mime_type = + reinterpret_cast<const char*>(plugin_mime_type_val->content); + plugin_detail->language = + reinterpret_cast<const char*>(plugin_lang_val->content); + + return true; +} diff --git a/webkit/default_plugin/plugin_database_handler.h b/webkit/default_plugin/plugin_database_handler.h new file mode 100644 index 0000000..a4813f5 --- /dev/null +++ b/webkit/default_plugin/plugin_database_handler.h @@ -0,0 +1,167 @@ +// 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_DEFAULT_PLUGIN_PLUGIN_DATABASE_HANDLER_H +#define WEBKIT_DEFAULT_PLUGIN_PLUGIN_DATABASE_HANDLER_H + +#include <windows.h> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "bindings/npapi.h" + +// Individual plugin details +struct PluginDetail { + std::string mime_type; + std::string download_url; + std::wstring display_name; + std::string language; +}; + +typedef std::vector<PluginDetail> PluginList; + +class PluginInstallerImpl; +struct _xmlNode; + +// This class handles download of the plugins database file from the plugin +// finder URL passed in. It also provides functionality to parse the plugins +// file and to locate the desired plugin mime type in the parsed plugin list. +// The format of the plugins databse file is as below:- +// <plugins> +// <plugin> +// <mime> </mime> (Mime type of the plugin) +// <lang> </lang> (Supported language) +// <url> </url> (Link to the plugin installer) +// </plugin> +// <plugin> +// </plugins> +class PluginDatabaseHandler { + public: + // plugin_installer_instance is a reference maintained to the current + // PluginInstallerImpl instance. + explicit PluginDatabaseHandler( + PluginInstallerImpl& plugin_installer_instance); + + virtual ~PluginDatabaseHandler(); + + // Downloads the plugins database file if needed. + // + // Parameters: + // plugin_finder_url + // Specifies the http/https location of the chrome plugin finder. + // Returns true on success. + bool DownloadPluginsFileIfNeeded(const std::string& plugin_finder_url); + + // Writes data to the plugins database file. + // + // Parameters: + // stream + // Pointer to the current stream. + // offset + // Indicates the data offset. + // buffer_length + // Specifies the length of the data buffer. + // buffer + // Pointer to the actual buffer. + // Returns the number of bytes actually written, 0 on error. + int32 Write(NPStream* stream, int32 offset, int32 buffer_length, + void* buffer); + + const std::wstring& plugins_file() const { + return plugins_file_; + } + + // Parses the XML file containing the list of available third-party + // plugins and adds them to a list. + // Returns true on success + bool ParsePluginList(); + + // Returns the plugin details for the third party plugin mime type passed in. + // + // Parameters: + // mime_type + // Specifies the mime type of the desired third party plugin. + // language + // Specifies the desired plugin language. + // download_url + // Output parameter which contans the plugin download URL on success. + // display_name + // Output parameter which contains the display name of the plugin on + // success. + // Returns true if the plugin details were found. + bool GetPluginDetailsForMimeType(const char* mime_type, + const char* language, + std::string* download_url, + std::wstring* display_name); + + // Closes the handle to the plugin database file. + // + // Parameters: + // delete_file + // Indicates if the plugin database file should be deleted. + void Close(bool delete_file); + + protected: + // Reads plugin information off an individual XML node. + // + // Parameters: + // plugin_node + // Pointer to the plugin XML node. + // plugin_detail + // Output parameter which contains the details of the plugin on success. + // Returns true on success. + bool ReadPluginInfo(_xmlNode* plugin_node, PluginDetail* plugin_detail); + + private: + // Contains the full path of the downloaded plugins file containing + // information about available third party plugin downloads. + std::wstring plugins_file_; + // Handle to the downloaded plugins file. + HANDLE plugin_downloads_file_; + // List of downloaded plugins. This is generated the first time the + // plugins file is downloaded and parsed. Each item in the list is + // of the type PluginDetail, and contains information about the third + // party plugin like it's mime type, download link, etc. + PluginList downloaded_plugins_list_; + // We maintain a reference to the PluginInstallerImpl instance to be able + // to achieve plugin installer state changes and to notify the instance + // about download completions. + PluginInstallerImpl& plugin_installer_instance_; + // The plugin finder url + std::string plugin_finder_url_; + // Set if the current instance should ignore plugin data. This is required + // if multiple null plugin instances attempt to download the plugin + // database. In this case the first instance to create the plugins database + // file locally writes to the file. The remaining instances ignore the + // downloaded data. + bool ignore_plugin_db_data_; +}; + +#endif // WEBKIT_DEFAULT_PLUGIN_PLUGIN_DATABASE_DOWNLOAD_HANDLER_H diff --git a/webkit/default_plugin/plugin_impl.cc b/webkit/default_plugin/plugin_impl.cc new file mode 100644 index 0000000..3aca6de --- /dev/null +++ b/webkit/default_plugin/plugin_impl.cc @@ -0,0 +1,764 @@ +// 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/default_plugin/plugin_impl.h" + +#include <shellapi.h> + +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/string_util.h" +#include "base/time.h" +#include "googleurl/src/gurl.h" +#include "unicode/locid.h" +#include "webkit/default_plugin/activex_installer.h" +#include "webkit/activex_shim/activex_shared.h" +#include "webkit/activex_shim/npn_scripting.h" +#include "webkit/default_plugin/default_plugin_shared.h" +#include "webkit/default_plugin/plugin_main.h" +#include "webkit/glue/webkit_glue.h" +#include "webkit/glue/webkit_resources.h" +// This file is generated when the webkit_strings.grd file is compiled. +// The path is the chrome/webkit/<debug\release>/obj/localized_strings +// folder. This path is added to the include path in the associated vsprops +// file. +#include "webkit_strings.h" + +static const int TOOLTIP_MAX_WIDTH = 500; + +PluginInstallerImpl::PluginInstallerImpl(int16 mode) + : instance_(NULL), + is_activex_(false), + mode_(mode), + plugin_install_stream_(NULL), + plugin_installer_state_(PluginInstallerStateUndefined), + enable_click_(false), + icon_(NULL), + bold_font_(NULL), + regular_font_(NULL), + underline_font_(NULL), + tooltip_(NULL), + activex_installer_(NULL), + plugin_database_handler_(*this) { +} + +PluginInstallerImpl::~PluginInstallerImpl() { + installation_job_monitor_thread_.Stop(); + + if (bold_font_) + ::DeleteObject(bold_font_); + + if (underline_font_) + ::DeleteObject(underline_font_); + + if (activex_installer_) { + activex_installer_->Cleanup(); + activex_installer_->Release(); + } + + if (tooltip_) + ::DestroyWindow(tooltip_); +} + +bool PluginInstallerImpl::Initialize(HINSTANCE module_handle, NPP instance, + NPMIMEType mime_type, int16 argc, + char* argn[], char* argv[]) { + DLOG(INFO) << __FUNCTION__ << " Mime Type : " << mime_type; + DCHECK(instance != NULL); + DCHECK(module_handle != NULL); + + // The clsid without the {} parentheses. + std::string raw_activex_clsid; + if (!ParseInstantiationArguments(mime_type, instance, argc, argn, argv, + &raw_activex_clsid)) { + DLOG(ERROR) << "Incorrect arguments passed to plugin"; + NOTREACHED(); + return false; + } + + if (!installation_job_monitor_thread_.Initialize()) { + DLOG(ERROR) << "Failed to initialize plugin install job"; + NOTREACHED(); + return false; + } + + InitializeResources(module_handle); + + if (is_activex_) { + // If the codebase is not from a whitelisted website, we do not allow + // download. + if (!activex_shim::IsCodebaseAllowed(raw_activex_clsid, + activex_codebase_)) { + activex_codebase_.clear(); + plugin_download_url_.clear(); + } + + if (!plugin_download_url_.empty()) { + set_plugin_installer_state(PluginListDownloaded); + DisplayAvailablePluginStatus(); + NotifyPluginStatus(default_plugin::MISSING_PLUGIN_AVAILABLE); + } else { + set_plugin_installer_state(PluginListDownloadFailed); + DisplayStatus(IDS_DEFAULT_PLUGIN_NO_PLUGIN_AVAILABLE_MSG); + } + } else { + DisplayStatus(IDS_DEFAULT_PLUGIN_GET_PLUGIN_MSG_NO_PLUGIN_NAME); + plugin_database_handler_.DownloadPluginsFileIfNeeded(plugin_finder_url_); + } + + return true; +} + +void PluginInstallerImpl::Shutdown() { + if (install_dialog_.IsWindow()) { + install_dialog_.DestroyWindow(); + } + if (IsWindow()) { + DestroyWindow(); + } +} + +void PluginInstallerImpl::NewStream(NPStream* stream) { + plugin_install_stream_ = stream; +} + +void PluginInstallerImpl::DestroyStream(NPStream* stream, NPError reason) { + if (stream == plugin_install_stream_) + plugin_install_stream_ = NULL; +} + +bool PluginInstallerImpl::WriteReady(NPStream* stream) { + bool ready_to_accept_data = false; + + if (plugin_installer_state() != PluginListDownloadInitiated) { + DCHECK(default_plugin::g_browser); + DCHECK(default_plugin::g_browser->destroystream); + // We don't want any data, kill the stream. + default_plugin::g_browser->destroystream(instance_, stream, NPRES_DONE); + } + if (0 == lstrcmpiA(stream->url, plugin_finder_url_.c_str())) { + ready_to_accept_data = true; + } + return ready_to_accept_data; +} + +int32 PluginInstallerImpl::Write(NPStream* stream, int32 offset, + int32 buffer_length, void* buffer) { + if (plugin_installer_state() != PluginListDownloadInitiated) { + DCHECK(default_plugin::g_browser); + DCHECK(default_plugin::g_browser->destroystream); + // We don't want any data, kill the stream. + default_plugin::g_browser->destroystream(instance_, stream, NPRES_DONE); + return 0; + } + + return plugin_database_handler_.Write(stream, offset, buffer_length, buffer); +} + +void PluginInstallerImpl::ClearDisplay() { + enable_click_ = false; + command_.clear(); + optional_additional_message_.clear(); + get_plugin_link_message_.clear(); +} + +void PluginInstallerImpl::RefreshDisplay() { + if (!IsWindow()) + return; + UpdateToolTip(); + + InvalidateRect(NULL, TRUE); + UpdateWindow(); +} + +bool PluginInstallerImpl::CreateToolTip() { + DWORD ex_styles = IsRTLLayout() ? WS_EX_LAYOUTRTL : 0; + tooltip_ = CreateWindowEx(ex_styles, TOOLTIPS_CLASS, NULL, + WS_POPUP | TTS_ALWAYSTIP, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + m_hWnd, NULL, NULL, NULL); + if (!tooltip_) + return false; + + // Associate the ToolTip with the tool. + TOOLINFO tool_info = {0}; + tool_info.cbSize = sizeof(tool_info); + tool_info.hwnd = m_hWnd; + tool_info.uFlags = TTF_IDISHWND | TTF_SUBCLASS; + tool_info.uId = reinterpret_cast<UINT_PTR>(m_hWnd); + tool_info.lpszText = NULL; + SendMessage(tooltip_, TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&tool_info)); + SendMessage(tooltip_, TTM_SETMAXTIPWIDTH, 0, TOOLTIP_MAX_WIDTH); + return true; +} + +void PluginInstallerImpl::UpdateToolTip() { + if (tooltip_ == NULL) + return; + std::wstring tip = command_; + if (!optional_additional_message_.empty()) + tip += std::wstring(L"\n\r") + optional_additional_message_; + + TOOLINFO tool_info = {0}; + tool_info.cbSize = sizeof(tool_info); + tool_info.hwnd = m_hWnd; + tool_info.uFlags = TTF_IDISHWND; + tool_info.uId = reinterpret_cast<UINT_PTR>(m_hWnd); + tool_info.lpszText = const_cast<LPWSTR>(tip.c_str()); + SendMessage(tooltip_, TTM_UPDATETIPTEXT, 0, (LPARAM)&tool_info); +} + +void PluginInstallerImpl::DisplayAvailablePluginStatus() { + ClearDisplay(); + enable_click_ = true; + command_ = ReplaceStringForPossibleEmptyReplacement( + IDS_DEFAULT_PLUGIN_GET_PLUGIN_MSG, + IDS_DEFAULT_PLUGIN_GET_PLUGIN_MSG_NO_PLUGIN_NAME, + plugin_name_); + optional_additional_message_ = + webkit_glue::GetLocalizedString(IDS_DEFAULT_PLUGIN_GET_PLUGIN_MSG_2); + get_plugin_link_message_ = webkit_glue::GetLocalizedString( + IDS_DEFAULT_PLUGIN_GET_THE_PLUGIN_BTN_MSG); + RefreshDisplay(); +} + +void PluginInstallerImpl::DisplayStatus(int message_resource_id) { + ClearDisplay(); + command_ = + webkit_glue::GetLocalizedString(message_resource_id); + RefreshDisplay(); +} + +void PluginInstallerImpl::DisplayPluginDownloadFailedStatus() { + ClearDisplay(); + command_ = webkit_glue::GetLocalizedString( + IDS_DEFAULT_PLUGIN_DOWNLOAD_FAILED_MSG); + command_ = ReplaceStringPlaceholders( + command_, + ASCIIToWide(plugin_download_url_), + NULL); + RefreshDisplay(); +} + +void PluginInstallerImpl::URLNotify(const char* url, NPReason reason) { + DCHECK(plugin_installer_state_ == PluginListDownloadInitiated); + + if (plugin_installer_state_ == PluginListDownloadInitiated) { + bool plugin_available = false; + if (reason == NPRES_DONE) { + DLOG(INFO) << "Received Done notification for plugin list download"; + set_plugin_installer_state(PluginListDownloaded); + plugin_database_handler_.ParsePluginList(); + if (plugin_database_handler_.GetPluginDetailsForMimeType( + mime_type_.c_str(), desired_language_.c_str(), + &plugin_download_url_, &plugin_name_)) { + plugin_available = true; + } else { + set_plugin_installer_state(PluginListDownloadedPluginNotFound); + } + + plugin_database_handler_.Close(false); + } else { + DLOG(WARNING) << "Failed to download plugin list"; + set_plugin_installer_state(PluginListDownloadFailed); + + plugin_database_handler_.Close(true); + } + + if (plugin_available) { + DLOG(INFO) << "Plugin available for mime type " << mime_type_; + DisplayAvailablePluginStatus(); + NotifyPluginStatus(default_plugin::MISSING_PLUGIN_AVAILABLE); + } else { + DLOG(WARNING) << "No plugin available for mime type " << mime_type_; + DisplayStatus(IDS_DEFAULT_PLUGIN_NO_PLUGIN_AVAILABLE_MSG); + } + } + + default_plugin::g_browser->destroystream(instance_, plugin_install_stream_, + NPRES_DONE); +} + +int16 PluginInstallerImpl::NPP_HandleEvent(void* event) { + // This is a hack. The renderer will send a direct custom message to ask for + // installation. + NPEvent* npp_event = static_cast<NPEvent*>(event); + if (npp_event->event == kInstallMissingPluginMessage) { + // We could get this message because InfoBar may not be in sync with our + // internal processing. So we need to check the status. + if (plugin_installer_state() == PluginListDownloaded) { + ShowInstallDialog(); + } + } + return 0; +} + +std::wstring PluginInstallerImpl::ReplaceStringForPossibleEmptyReplacement( + int message_id_with_placeholders, + int messsage_id_without_placeholders, + const std::wstring& replacement_string) { + // If the replacement_string is not empty, load the string identified by + // the resource id message_id_with_placeholders, and replace the + // placeholder with the replacement_string. Otherwise return the string + // identified by resource id messsage_id_without_placeholders. + if (replacement_string.empty()) { + return webkit_glue::GetLocalizedString(messsage_id_without_placeholders); + } else { + std::wstring string_with_placeholders = + webkit_glue::GetLocalizedString(message_id_with_placeholders); + return ReplaceStringPlaceholders(string_with_placeholders, + replacement_string, NULL); + } +} + +bool PluginInstallerImpl::SetWindow(HWND parent_window) { + if (!::IsWindow(parent_window)) { + // No window created yet. Ignore this call. + if (!IsWindow()) + return true; + // Parent window has been destroyed. + Shutdown(); + return true; + } + + RECT parent_rect = {0}; + + if (IsWindow()) { + ::GetClientRect(parent_window, &parent_rect); + SetWindowPos(NULL, &parent_rect, SWP_SHOWWINDOW); + return true; + } + // First time in -- no window created by plugin yet. + ::GetClientRect(parent_window, &parent_rect); + Create(parent_window, parent_rect, NULL, WS_CHILD | WS_BORDER); + DCHECK(IsWindow()); + installation_job_monitor_thread_.set_plugin_window(m_hWnd); + + CreateToolTip(); + UpdateToolTip(); + + UpdateWindow(); + ShowWindow(SW_SHOW); + + return true; +} + +void PluginInstallerImpl::DownloadPlugin() { + set_plugin_installer_state(PluginDownloadInitiated); + + DLOG(INFO) << "Initiating download for plugin URL " + << plugin_download_url_.c_str(); + + DisplayStatus(IDS_DEFAULT_PLUGIN_DOWNLOADING_PLUGIN_MSG); + + if (is_activex_) { + if (activex_installer_ == NULL) { + CComObject<ActiveXInstaller>::CreateInstance(&activex_installer_); + activex_installer_->AddRef(); + } + activex_installer_->StartDownload(activex_clsid_, activex_codebase_, m_hWnd, + kActivexInstallResult); + } else { + webkit_glue::DownloadUrl(plugin_download_url_, m_hWnd); + } +} + +void PluginInstallerImpl::DownloadCancelled() { + DisplayAvailablePluginStatus(); +} + +LRESULT PluginInstallerImpl::OnEraseBackGround(UINT message, WPARAM wparam, + LPARAM lparam, BOOL& handled) { + HDC paint_device_context = reinterpret_cast<HDC>(wparam); + RECT erase_rect = {0}; + ::GetClipBox(paint_device_context, &erase_rect); + HBRUSH brush = ::CreateSolidBrush(RGB(252, 235, 162)); + DCHECK(brush); + ::FillRect(paint_device_context, &erase_rect, brush); + ::DeleteObject(brush); + return 1; +} + +// Use ICU in order to determine whether the locale is right-to-left. +// +// TODO(idana) bug# 1246452: there is already code in +// chrome/common/l10n_util.h/cc that uses ICU to determine the locale +// direction. We don't currently use this code since code in WebKit should not +// depend on code in Chrome. We can fix this by pulling (at least part of) the +// l10n_util functionality up into the Base module. +bool PluginInstallerImpl::IsRTLLayout() const { + const Locale& locale = Locale::getDefault(); + const char* lang = locale.getLanguage(); + + // Check only for Arabic and Hebrew languages for now. + if (strcmp(lang, "ar") == 0 || strcmp(lang, "he") == 0) { + return true; + } + return false; +} + +LRESULT PluginInstallerImpl::OnPaint(UINT message, WPARAM wparam, LPARAM lparam, + BOOL& handled) { + PAINTSTRUCT paint_struct = {0}; + BeginPaint(&paint_struct); + + int save_dc_context = SaveDC(paint_struct.hdc); + // The drawing order is as below:- + // 1. The Get plugin link at the top left corner. + // 2. The plugin icon. + // 3. The text describing user actions to the right of the icon. + SIZE get_plugin_link_extents = {0}; + HFONT old_font = + reinterpret_cast<HFONT>(SelectObject(paint_struct.hdc, regular_font_)); + + GetTextExtentPoint32(paint_struct.hdc, get_plugin_link_message_.c_str(), + static_cast<int>(get_plugin_link_message_.length()), + &get_plugin_link_extents); + + POINT device_point = {0}; + device_point.x = get_plugin_link_extents.cx; + device_point.y = get_plugin_link_extents.cy; + LPtoDP(paint_struct.hdc, &device_point, 1); + + RECT text_rect = {0}; + text_rect.left = 5; + text_rect.right = text_rect.left + device_point.x; + text_rect.top = 5; + text_rect.bottom = text_rect.top + device_point.y; + + RECT client_rect = {0}; + GetClientRect(&client_rect); + + int icon_width = GetSystemMetrics(SM_CXICON); + int icon_height = GetSystemMetrics(SM_CYICON); + + int x = (client_rect.right / 2) - icon_width / 2; + int y = (client_rect.bottom / 2) - icon_height / 2; + + DCHECK(icon_); + DrawIcon(paint_struct.hdc, x, y, icon_); + + int old_mode = SetBkMode(paint_struct.hdc, TRANSPARENT); + COLORREF old_color = SetTextColor(paint_struct.hdc, RGB(0, 0, 255)); + + // If the UI layout is right-to-left, we need to mirror the position of the + // link text and also make sure that the text is aligned to the right. + DWORD draw_text_flags = DT_VCENTER; + if (IsRTLLayout()) { + draw_text_flags |= DT_RTLREADING | DT_RIGHT; + int text_width = text_rect.right - text_rect.left; + int client_width = client_rect.right - client_rect.left; + text_rect.left = client_width - text_rect.left - text_width; + text_rect.right = text_rect.left + text_width; + } else { + draw_text_flags |= DT_LEFT; + } + + DrawText(paint_struct.hdc, get_plugin_link_message_.c_str(), + static_cast<int>(get_plugin_link_message_.length()), + &text_rect, draw_text_flags); + + SIZE command_extents = {0}; + GetTextExtentPoint32(paint_struct.hdc, command_.c_str(), + static_cast<int>(command_.length()), &command_extents); + + int y_origin = y + (icon_height) + 10; + int x_origin = x - command_extents.cx / 2 + icon_width / 2; + + // If the window is too small then no point in attempting to display plugin + // information. In any case this info is displayed when the user hovers + // over the plugin window. + int window_width = client_rect.right - client_rect.left; + int window_height = client_rect.bottom - client_rect.top; + + if ((x_origin + command_extents.cx <= window_width) && + (y_origin + command_extents.cy <= window_height)) { + PaintUserActionInformation(paint_struct.hdc, x_origin, y_origin); + } + + RestoreDC(paint_struct.hdc, save_dc_context); + EndPaint(&paint_struct); + return 0; +} + +void PluginInstallerImpl::PaintUserActionInformation(HDC paint_dc, + int x_origin, + int y_origin) { + SelectObject(paint_dc, regular_font_); + + SIZE command_extents = {0}; + GetTextExtentPoint32(paint_dc, command_.c_str(), + static_cast<int>(command_.length()), &command_extents); + POINT device_point = {0}; + device_point.x = command_extents.cx; + device_point.y = command_extents.cy; + LPtoDP(paint_dc, &device_point, 1); + + RECT text_rect = {0}; + text_rect.left = x_origin; + text_rect.right = text_rect.left + device_point.x; + text_rect.top = y_origin; + text_rect.bottom = text_rect.top + device_point.y; + + SetTextColor(paint_dc, RGB(0, 0, 0)); + + // Make sure we pass the right BiDi flags to DrawText if the UI layout is + // right-to-left. + UINT additional_dt_flags = IsRTLLayout() ? DT_RTLREADING : 0; + DrawText(paint_dc, command_.c_str(), + static_cast<int>(command_.length()), &text_rect, + DT_CENTER | DT_VCENTER | additional_dt_flags); + + if (!optional_additional_message_.empty()) { + SelectObject(paint_dc, regular_font_); + + SIZE optional_text_extents = {0}; + int optional_message_length = + static_cast<int>(optional_additional_message_.length()); + GetTextExtentPoint32(paint_dc, + optional_additional_message_.c_str(), + optional_message_length, + &optional_text_extents); + POINT device_point = {0}; + device_point.x = optional_text_extents.cx; + device_point.y = optional_text_extents.cy; + LPtoDP(paint_dc, &device_point, 1); + + text_rect.right = text_rect.left + device_point.x; + text_rect.top = y_origin + command_extents.cy + 2; + text_rect.bottom = text_rect.top + device_point.y; + + DrawText(paint_dc, optional_additional_message_.c_str(), + static_cast<int>(optional_additional_message_.length()), + &text_rect, DT_CENTER | DT_VCENTER | additional_dt_flags); + } +} + +void PluginInstallerImpl::ShowInstallDialog() { + enable_click_ = false; + install_dialog_.Initialize(this, plugin_name_); + install_dialog_.Create(m_hWnd, NULL); + install_dialog_.ShowWindow(SW_SHOW); +} + +LRESULT PluginInstallerImpl::OnLButtonDown(UINT message, WPARAM wparam, + LPARAM lparam, BOOL& handled) { + if (!enable_click_) + return 0; + if (plugin_installer_state() == PluginListDownloaded) { + ShowInstallDialog(); + NotifyPluginStatus(default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD); + } else if (plugin_installer_state_ == PluginInstallerLaunchSuccess) { + DCHECK(default_plugin::g_browser); + DCHECK(default_plugin::g_browser->geturl); + default_plugin::g_browser->geturl( + instance_, + "javascript:navigator.plugins.refresh(true)", + "_self"); + default_plugin::g_browser->geturl( + instance_, + "javascript:window.location.reload(true)", + "_self"); + } + + return 0; +} + +LRESULT PluginInstallerImpl::OnSetCursor(UINT message, WPARAM wparam, + LPARAM lparam, BOOL& handled) { + if (enable_click_) { + ::SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_HAND))); + return 1; + } + handled = FALSE; + return 0; +} + +LRESULT PluginInstallerImpl::OnRefreshPlugins(UINT message, WPARAM wparam, + LPARAM lparam, BOOL& handled) { + DCHECK(default_plugin::g_browser); + DCHECK(default_plugin::g_browser->geturl); + default_plugin::g_browser->geturl( + instance_, + "javascript:navigator.plugins.refresh(true)", + "_self"); + default_plugin::g_browser->geturl( + instance_, + "javascript:window.location.reload(true)", + "_self"); + return 0; +} + +LRESULT PluginInstallerImpl::OnCopyData(UINT message, WPARAM wparam, + LPARAM lparam, BOOL& handled) { + COPYDATASTRUCT* download_file_info = + reinterpret_cast<COPYDATASTRUCT*>(lparam); + if (!download_file_info || !download_file_info->dwData) { + DLOG(WARNING) << "Failed to download plugin"; + set_plugin_installer_state(PluginDownloadFailed); + DisplayPluginDownloadFailedStatus(); + } else { + DLOG(INFO) << "Successfully downloaded plugin installer"; + set_plugin_installer_state(PluginDownloadCompleted); + + std::wstring file_path = + reinterpret_cast<const wchar_t*>(download_file_info->lpData); + + SHELLEXECUTEINFO shell_execute_info = {0}; + shell_execute_info.cbSize = sizeof(shell_execute_info); + shell_execute_info.fMask = SEE_MASK_NOCLOSEPROCESS; + shell_execute_info.lpFile = file_path.c_str(); + + if (!ShellExecuteEx(&shell_execute_info)) { + DLOG(WARNING) << "Failed to launch plugin installer " + << file_path.c_str() << " Error " + << ::GetLastError(); + set_plugin_installer_state(PluginInstallerLaunchFailure); + DisplayStatus(IDS_DEFAULT_PLUGIN_INSTALLATION_FAILED_MSG); + NOTREACHED(); + } else { + DLOG(INFO) << "Successfully launched plugin installer"; + set_plugin_installer_state(PluginInstallerLaunchSuccess); + installation_job_monitor_thread_.AssignProcessToJob( + shell_execute_info.hProcess); + DisplayStatus(IDS_DEFAULT_PLUGIN_REFRESH_PLUGIN_MSG); + enable_click_ = true; + RefreshDisplay(); + } + } + return 0; +} + +LRESULT PluginInstallerImpl::OnActiveXInstallResult(UINT message, + WPARAM wparam, + LPARAM lparam, + BOOL& handled) { + handled = TRUE; + + if (SUCCEEDED(wparam)) { + set_plugin_installer_state(PluginInstallerLaunchSuccess); + DisplayStatus(IDS_DEFAULT_PLUGIN_REFRESH_PLUGIN_MSG); + PostMessage(kRefreshPluginsMessage, 0, 0); + } else if ((wparam == INET_E_UNKNOWN_PROTOCOL) || + (wparam == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND))) { + set_plugin_installer_state(PluginDownloadFailed); + DisplayPluginDownloadFailedStatus(); + } else { + set_plugin_installer_state(PluginInstallerLaunchFailure); + DisplayStatus(IDS_DEFAULT_PLUGIN_INSTALLATION_FAILED_MSG); + } + return 0; +} + +std::string PluginInstallerImpl::ResolveURL(NPP instance, + const std::string& relative_url) { + NPObject* object = NULL; + default_plugin::g_browser->getvalue(instance, NPNVWindowNPObject, &object); + activex_shim::NPNScriptableObject window(instance, object); + std::wstring url = + window.GetObjectProperty("document").GetStringProperty("URL"); + GURL base(url); + return base.Resolve(relative_url).spec(); +} + +bool PluginInstallerImpl::InitializeResources(HINSTANCE module_handle) { + DCHECK(icon_ == NULL); + DCHECK(regular_font_ == NULL); + DCHECK(bold_font_ == NULL); + DCHECK(underline_font_ == NULL); + + icon_ = LoadIcon(module_handle, MAKEINTRESOURCE(IDI_DEFAULT_PLUGIN_ICON)); + DCHECK(icon_ != NULL); + + desired_language_ = "en-us"; + regular_font_ = reinterpret_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT)); + DCHECK(regular_font_ != NULL); + + LOGFONT font_info = {0}; + GetObject(regular_font_, sizeof(LOGFONT), &font_info); + font_info.lfWeight |= FW_BOLD; + bold_font_ = CreateFontIndirect(&font_info); + DCHECK(bold_font_ != NULL); + + font_info.lfUnderline = TRUE; + underline_font_ = CreateFontIndirect(&font_info); + DCHECK(underline_font_ != NULL); + return true; +} + +bool PluginInstallerImpl::ParseInstantiationArguments( + NPMIMEType mime_type, NPP instance, int16 argc, char* argn[], char* argv[], + std::string* raw_activex_clsid) { + instance_ = instance; + mime_type_ = mime_type; + + for (int i = 0; i < argc; ++i) { + if (LowerCaseEqualsASCII(argn[i], "classid") && + activex_shim::GetClsidFromClassidAttribute(argv[i], + raw_activex_clsid)) { + is_activex_ = true; + activex_clsid_ = std::string("{") + *raw_activex_clsid + "}"; + } + if (LowerCaseEqualsASCII(argn[i], "codebase")) { + activex_codebase_ = ResolveURL(instance, argv[i]); + size_t pos = activex_codebase_.find('#'); + if (pos != std::string::npos) + plugin_download_url_ = activex_codebase_.substr(0, pos); + else + plugin_download_url_ = activex_codebase_; + } + } + + if (!is_activex_) { + if (!mime_type || !instance) { + DLOG(WARNING) << __FUNCTION__ << " Invalid parameters passed in"; + NOTREACHED(); + return false; + } + + if (!webkit_glue::GetPluginFinderURL(&plugin_finder_url_)) { + NOTREACHED(); + DLOG(WARNING) << __FUNCTION__ << " Failed to get the plugin finder URL"; + return false; + } + + DLOG(INFO) << "Plugin finder URL is " << plugin_finder_url_.c_str(); + } + + return true; +} + +void PluginInstallerImpl::NotifyPluginStatus(int status) { + default_plugin::g_browser->getvalue( + instance_, + static_cast<NPNVariable>( + default_plugin::kMissingPluginStatusStart + status), + NULL); +} diff --git a/webkit/default_plugin/plugin_impl.h b/webkit/default_plugin/plugin_impl.h new file mode 100644 index 0000000..a1245c6 --- /dev/null +++ b/webkit/default_plugin/plugin_impl.h @@ -0,0 +1,396 @@ +// 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_DEFAULT_PLUGIN_PLUGIN_IMPL_H__ +#define WEBKIT_DEFAULT_PLUGIN_PLUGIN_IMPL_H__ + +#include <atlbase.h> +#include <atlwin.h> +#include <string> +#include <vector> + +#include "base/logging.h" +#include "bindings/npapi.h" +#include "webkit/default_plugin/install_dialog.h" +#include "webkit/default_plugin/plugin_database_handler.h" +#include "webkit/default_plugin/plugin_install_job_monitor.h" + +// Possible plugin installer states. +enum PluginInstallerState { + PluginInstallerStateUndefined, + PluginListDownloadInitiated, + PluginListDownloaded, + PluginListDownloadedPluginNotFound, + PluginListDownloadFailed, + PluginDownloadInitiated, + PluginDownloadCompleted, + PluginDownloadFailed, + PluginInstallerLaunchSuccess, + PluginInstallerLaunchFailure +}; + +class ActiveXInstaller; +class PluginInstallDialog; +class PluginDatabaseHandler; + +// Provides the plugin installation functionality. This class is +// instantiated with the information like the mime type of the +// target plugin, the display mode, etc. +class PluginInstallerImpl : public CWindowImpl<PluginInstallerImpl> { + public: + static const int kRefreshPluginsMessage = WM_APP + 1; + static const int kInstallMissingPluginMessage = WM_APP + 2; + static const int kActivexInstallResult = WM_USER + 74; + + // mode is the plugin instantiation mode, i.e. whether it is a full + // page plugin (NP_FULL) or an embedded plugin (NP_EMBED) + explicit PluginInstallerImpl(int16 mode); + virtual ~PluginInstallerImpl(); + + BEGIN_MSG_MAP(PluginInstallerImpl) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackGround) + MESSAGE_HANDLER(WM_PAINT, OnPaint) + MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) + MESSAGE_HANDLER(kRefreshPluginsMessage, OnRefreshPlugins) + MESSAGE_HANDLER(WM_COPYDATA, OnCopyData) + MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor) + MESSAGE_HANDLER(kActivexInstallResult, OnActiveXInstallResult) + END_MSG_MAP() + + // Initializes the plugin with the instance information, mime type + // and the list of parameters passed down to the plugin from the webpage. + // + // Parameters: + // module_handle + // The handle to the dll in which this object is instantiated. + // instance + // The plugins opaque instance handle. + // mime_type + // Identifies the third party plugin which would be eventually installed. + // argc + // Indicates the count of arguments passed in from the webpage. + // argv + // Pointer to the arguments. + // Returns true on success. + bool Initialize(HINSTANCE module_handle, NPP instance, NPMIMEType mime_type, + int16 argc, char* argn[], char* argv[]); + + // Displays the default plugin UI. + // + // Parameters: + // parent_window + // Handle to the parent window. + bool SetWindow(HWND parent_window); + + // Destroys the install dialog and the plugin window. + void Shutdown(); + + // Starts plugin download. Spawns the plugin installer after it is + // downloaded. + void DownloadPlugin(); + + // Indicates that the plugin download was cancelled. + void DownloadCancelled(); + + // Initializes the plugin download stream. + // + // Parameters: + // stream + // Pointer to the new stream being created. + void NewStream(NPStream* stream); + + // Uninitializes the plugin download stream. + // + // Parameters: + // stream + // Pointer to the stream being destroyed. + // reason + // Indicates why the stream is being destroyed. + // + void DestroyStream(NPStream* stream, NPError reason); + + // Determines whether the plugin is ready to accept data. + // We only accept data when we have initiated a download for the plugin + // database. + // + // Parameters: + // stream + // Pointer to the stream being destroyed. + // Returns true if the plugin is ready to accept data. + bool WriteReady(NPStream* stream); + + // Delivers data to the plugin instance. + // + // Parameters: + // stream + // Pointer to the stream being destroyed. + // offset + // Indicates the data offset. + // buffer_length + // Indicates the length of the data buffer. + // buffer + // Pointer to the actual buffer. + // Returns the number of bytes actually written, 0 on error. + int32 Write(NPStream* stream, int32 offset, int32 buffer_length, + void* buffer); + + // Handles notifications received in response to GetURLNotify calls issued + // by the plugin. + // + // Parameters: + // url + // Pointer to the URL. + // reason + // Describes why the notification was sent. + void URLNotify(const char* url, NPReason reason); + + // Initiates activex installs if applicable. + // Note: The null plugin being a windowed plugin does not have to implement + // NPP_HandleEvent. However to handle activex installations, we have this + // hack to allow the renderer to send out a request for installing the + // activex. + int16 NPP_HandleEvent(void* event); + + HWND window() const { return m_hWnd; } + const std::string& mime_type() const { return mime_type_; } + + // Replaces a resource string with the placeholder passed in as an argument + // + // Parameters: + // message_id_with_placeholders + // The resource id of the string with placeholders. This is only used if + // the placeholder string (the replacement_string) parameter is valid. + // message_id_without_placeholders + // The resource id of the string to be returned if the placeholder is + // empty. + // replacement_string + // The placeholder which replaces tokens in the string identified by + // resource id message_id_with_placeholders. + // Returns a string which has the placeholders replaced, or the string + // without placeholders. + static std::wstring ReplaceStringForPossibleEmptyReplacement( + int message_id_with_placeholders, int message_id_without_placeholders, + const std::wstring& replacement_string); + + // Setter/getter combination to set and retreieve the current + // state of the plugin installer. + void set_plugin_installer_state(PluginInstallerState new_state) { + plugin_installer_state_ = new_state; + } + + PluginInstallerState plugin_installer_state() const { + return plugin_installer_state_; + } + + // Getter for the NPP instance member. + const NPP instance() const { + return instance_; + } + + // Returns whether or not the UI layout is right-to-left (such as Hebrew or + // Arabic). + bool IsRTLLayout() const; + + protected: + // Window message handlers. + LRESULT OnPaint(UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled); + LRESULT OnEraseBackGround(UINT message, WPARAM wparam, LPARAM lparam, + BOOL& handled); + LRESULT OnLButtonDown(UINT message, WPARAM wparam, LPARAM lparam, + BOOL& handled); + LRESULT OnSetCursor(UINT message, WPARAM wparam, LPARAM lparam, + BOOL& handled); + + // Refreshes the loaded plugin list and reloads the current page. + LRESULT OnRefreshPlugins(UINT message, WPARAM wparam, LPARAM lparam, + BOOL& handled); + + // Launches the third party plugin installer. This message is + // received when the request to download the installer, initiated by + // plugin completes. + LRESULT OnCopyData(UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled); + + // Displays status information for ActiveX installs + LRESULT OnActiveXInstallResult(UINT message, WPARAM wparam, LPARAM lparam, + BOOL& handled); + + // Displays the plugin install confirmation dialog. + void ShowInstallDialog(); + + // Clears the current display state. + void ClearDisplay(); + + // Displays the status message identified by the message resource id + // passed in. + // + // Parameters: + // message_resource_id parameter + // The resource id of the message to be displayed. + void DisplayStatus(int message_resource_id); + + // Displays status information for the third party plugin which is needed + // by the page. + void DisplayAvailablePluginStatus(); + + // Displays information related to third party plugin download failure. + void DisplayPluginDownloadFailedStatus(); + + // Enables the plugin window if required and initiates an update of the + // the plugin window. + void RefreshDisplay(); + + // Create tooltip window. + bool CreateToolTip(); + + // Update ToolTip text with the message shown inside the default plugin. + void UpdateToolTip(); + + // Resolves the relative URL (could be already an absolute URL too) to return + // full URL based on current document's URL and base. + // + // Parameters: + // instance + // The plugins opaque instance handle. + // relative_url + // The URL to be resolved. + // Returns the resolved URL. + std::string ResolveURL(NPP instance, const std::string& relative_url); + + // Initializes resources like the icon, fonts, etc needed by the plugin + // installer + // + // Parameters: + // module_handle + // Handle to the dll in which this object is instantiated. + // Returns true on success. + bool InitializeResources(HINSTANCE module_handle); + + // Parses the plugin instantiation arguments. This includes checking for + // whether this is an activex install and reading the appropriate + // arguments like codebase, etc. For plugin installs we download the + // plugin finder URL and initalize the mime type and the plugin instance + // info. + // + // Parameters: + // module_handle + // The handle to the dll in which this object is instantiated. + // instance + // The plugins opaque instance handle. + // mime_type + // Identifies the third party plugin which would be eventually installed. + // argc + // Indicates the count of arguments passed in from the webpage. + // argv + // Pointer to the arguments. + // raw_activex_clsid + // Output parameter which contains the CLSID of the Activex plugin needed. + // This is only applicable if the webpage specifically requests an ActiveX + // control. + // Returns true on success. + bool ParseInstantiationArguments(NPMIMEType mime_type, NPP instance, + int16 argc, char* argn[], char* argv[], + std::string* raw_activex_clsid); + + // Paints user action messages to the plugin window. These include messages + // like whether the user should click on the plugin window to download the + // plugin, etc. + // + // Parameters: + // paint_dc + // The device context returned in BeginPaint. + // x_origin + // Horizontal reference point indicating where the text is to be displayed. + // y_origin + // Vertical reference point indicating where the text is to be displayed. + // + void PaintUserActionInformation(HDC paint_dc, int x_origin, int y_origin); + + private: + // Notify the renderer that plugin is available to download. + void NotifyPluginStatus(int status); + + // The plugins opaque instance handle + NPP instance_; + // If this is to install activex + bool is_activex_; + // The plugin instantiation mode (NP_FULL or NP_EMBED) + int16 mode_; + // The handle to the icon displayed in the plugin installation window. + HICON icon_; + // The Get plugin link message string displayed at the top left corner of + // the plugin window. + std::wstring get_plugin_link_message_; + // The command string displayed in the plugin installation window. + std::wstring command_; + // An additional message displayed at times by the plugin. + std::wstring optional_additional_message_; + // The current stream. + NPStream* plugin_install_stream_; + // The plugin finder URL. + std::string plugin_finder_url_; + // The desired mime type. + std::string mime_type_; + // The desired language. + std::string desired_language_; + // The plugin name. + std::wstring plugin_name_; + // The actual download URL. + std::string plugin_download_url_; + // The current state of the plugin installer. + PluginInstallerState plugin_installer_state_; + // Used to display the UI for plugin installation. + PluginInstallDialog install_dialog_; + // To enable auto refresh of the plugin window once the installation + // is complete, we spawn the installation process in a job, and monitor + // IO completion events on the job. When the active process count of the + // job falls to zero, we initiate an auto refresh of the plugin list + // which enables the downloaded plugin to be instantiated. + // The completion events from the job are monitored in an independent + // thread. + PluginInstallationJobMonitorThread installation_job_monitor_thread_; + // This object handles download and parsing of the plugins database. + PluginDatabaseHandler plugin_database_handler_; + // Indicates if the left click to download/refresh should be enabled or not. + bool enable_click_; + // Handles to the fonts used to display text in the plugin window. + HFONT bold_font_; + HFONT regular_font_; + HFONT underline_font_; + // Tooltip Window. + HWND tooltip_; + // ActiveX related. + std::string activex_codebase_; + std::string activex_clsid_; + CComObject<ActiveXInstaller>* activex_installer_; + + DISALLOW_EVIL_CONSTRUCTORS(PluginInstallerImpl); +}; + + +#endif // WEBKIT_DEFAULT_PLUGIN_PLUGIN_IMPL_H__ diff --git a/webkit/default_plugin/plugin_install_job_monitor.cc b/webkit/default_plugin/plugin_install_job_monitor.cc new file mode 100644 index 0000000..09b06d6 --- /dev/null +++ b/webkit/default_plugin/plugin_install_job_monitor.cc @@ -0,0 +1,124 @@ +// 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/default_plugin/plugin_install_job_monitor.h" + +#include "webkit/default_plugin/plugin_impl.h" + +PluginInstallationJobMonitorThread::PluginInstallationJobMonitorThread() + : Thread("Chrome plugin install thread"), + install_job_completion_port_(NULL), + stop_job_monitoring_(false), + plugin_window_(NULL), + install_job_(NULL) { +} + +PluginInstallationJobMonitorThread::~PluginInstallationJobMonitorThread() { + if (install_job_) { + ::CloseHandle(install_job_); + install_job_ = NULL; + } +} + +bool PluginInstallationJobMonitorThread::Initialize() { + DCHECK(install_job_ == NULL); + + install_job_ = ::CreateJobObject(NULL, NULL); + if (install_job_ == NULL) { + DLOG(ERROR) << "Failed to create plugin install job. Error = " + << ::GetLastError(); + NOTREACHED(); + return false; + } + + return Start(); +} + +void PluginInstallationJobMonitorThread::Init() { + if (!install_job_) { + DLOG(WARNING) << "Invalid job information"; + NOTREACHED(); + return; + } + + DCHECK(install_job_completion_port_ == NULL); + + install_job_completion_port_ = + ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, + reinterpret_cast<ULONG_PTR>(install_job_), 0); + DCHECK(install_job_completion_port_ != NULL); + + JOBOBJECT_ASSOCIATE_COMPLETION_PORT job_completion_port = {0}; + job_completion_port.CompletionKey = install_job_; + job_completion_port.CompletionPort = install_job_completion_port_; + + if (!SetInformationJobObject(install_job_, + JobObjectAssociateCompletionPortInformation, + &job_completion_port, + sizeof(job_completion_port))) { + DLOG(WARNING) << "Failed to associate completion port with job object.Err " + << ::GetLastError(); + NOTREACHED(); + return; + } + + while (!stop_job_monitoring_) { + unsigned long job_event = 0; + unsigned long completion_key = 0; + LPOVERLAPPED overlapped = NULL; + + if (::GetQueuedCompletionStatus( + install_job_completion_port_, &job_event, + &completion_key, &overlapped, INFINITE)) { + if (job_event == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO) { + DLOG(INFO) << "All processes in the installer job have exited."; + DLOG(INFO) << "Initiating refresh on the plugins list"; + DCHECK(::IsWindow(plugin_window_)); + PostMessageW(plugin_window_, + PluginInstallerImpl::kRefreshPluginsMessage, 0, 0); + } + } + } +} + +void PluginInstallationJobMonitorThread::Stop() { + stop_job_monitoring_ = true; + ::PostQueuedCompletionStatus( + install_job_completion_port_, JOB_OBJECT_MSG_END_OF_JOB_TIME, + reinterpret_cast<ULONG_PTR>(install_job_), NULL); + Thread::Stop(); + ::CloseHandle(install_job_completion_port_); + install_job_completion_port_ = NULL; +} + +bool PluginInstallationJobMonitorThread::AssignProcessToJob( + HANDLE process_handle) { + BOOL result = AssignProcessToJobObject(install_job_, process_handle); + return result ? true : false; +} diff --git a/webkit/default_plugin/plugin_install_job_monitor.h b/webkit/default_plugin/plugin_install_job_monitor.h new file mode 100644 index 0000000..64e104f --- /dev/null +++ b/webkit/default_plugin/plugin_install_job_monitor.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. + +#ifndef WEBKIT_DEFAULT_PLUGIN_PLUGIN_INSTALL_JOB_MONITOR_H__ +#define WEBKIT_DEFAULT_PLUGIN_PLUGIN_INSTALL_JOB_MONITOR_H__ + +#include "base/logging.h" +#include "base/thread.h" + +// Provides the plugin installation job monitoring functionality. +// The PluginInstallationJobMonitorThread class represents a background +// thread which monitors the install job completion port which is associated +// with the job when an instance of this class is initialized. +class PluginInstallationJobMonitorThread : public Thread { + public: + PluginInstallationJobMonitorThread(); + virtual ~PluginInstallationJobMonitorThread(); + + // Initializes the plugin install job. This involves creating the job object + // and starting the thread which monitors the job completion port. + // Returns true on success. + bool Initialize(); + + // Stops job monitoring and invokes the base Stop function. + void Stop(); + + // Simple setter/getters for the plugin window handle. + void set_plugin_window(HWND plugin_window) { + DCHECK(::IsWindow(plugin_window)); + plugin_window_ = plugin_window; + } + + HWND plugin_window() const { + return plugin_window_; + } + + // Adds a process to the job object. + // + // Parameters: + // process_handle + // Handle to the process which is to be added to the plugin install job. + // Returns true on success. + bool AssignProcessToJob(HANDLE process_handle); + + protected: + // Blocks on the plugin installation job completion port by invoking the + // GetQueuedCompletionStatus API. + // We return from this function when the job monitoring thread is stopped. + virtual void Init(); + + private: + // The install job completion port. Created in Init. + HANDLE install_job_completion_port_; + // Indicates that job monitoring is to be stopped + bool stop_job_monitoring_; + // The install job. Should be created before the job monitor thread + // is started. + HANDLE install_job_; + // The plugin window handle. + HWND plugin_window_; + + DISALLOW_EVIL_CONSTRUCTORS(PluginInstallationJobMonitorThread); +}; + +#endif // WEBKIT_DEFAULT_PLUGIN_PLUGIN_INSTALL_JOB_MONITOR_H__ diff --git a/webkit/default_plugin/plugin_main.cc b/webkit/default_plugin/plugin_main.cc new file mode 100644 index 0000000..07c0108 --- /dev/null +++ b/webkit/default_plugin/plugin_main.cc @@ -0,0 +1,237 @@ +// 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/default_plugin/plugin_main.h" + +#include "base/logging.h" +#include "webkit/activex_shim/npp_impl.h" +#include "webkit/default_plugin/plugin_impl.h" +#include "webkit/glue/webkit_glue.h" + +namespace default_plugin { +// +// Forward declare the linker-provided pseudo variable for the +// current module handle. +// +extern "C" IMAGE_DOS_HEADER __ImageBase; + +// get the handle to the currently executing module +inline HMODULE GetCurrentModuleHandle() { + return reinterpret_cast<HINSTANCE>(&__ImageBase); +} + +// Initialized in NP_Initialize. +NPNetscapeFuncs* g_browser = NULL; + +NPError WINAPI 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->writeready = NPP_WriteReady; + funcs->write = NPP_Write; + funcs->asfile = NULL; + funcs->print = NULL; + funcs->event = NPP_HandleEvent; + funcs->urlnotify = NPP_URLNotify; + funcs->getvalue = NULL; + funcs->setvalue = NULL; + return NPERR_NO_ERROR; +} + +NPError WINAPI NP_Initialize(NPNetscapeFuncs* funcs) { + g_browser = funcs; + activex_shim::g_browser = funcs; + return 0; +} + +NPError WINAPI NP_Shutdown(void) { + g_browser = NULL; + return 0; +} + +NPError NPP_New(NPMIMEType plugin_type, NPP instance, uint16 mode, int16 argc, + char* argn[], char* argv[], NPSavedData* saved) { + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + // We don't want the null plugin to work in the following cases:- + // 1. Test-shell + // 2. The plugin is running in the renderer process. + if (webkit_glue::IsPluginRunningInRendererProcess()) { + return NPERR_GENERIC_ERROR; + } + + PluginInstallerImpl* plugin_impl = new PluginInstallerImpl(mode); + plugin_impl->Initialize(GetCurrentModuleHandle(), instance, plugin_type, argc, + argn, argv); + instance->pdata = reinterpret_cast<void*>(plugin_impl); + return NPERR_NO_ERROR; +} + +NPError NPP_Destroy(NPP instance, NPSavedData** save) { + PluginInstallerImpl* plugin_impl = + reinterpret_cast<PluginInstallerImpl*>(instance->pdata); + + if (plugin_impl) { + plugin_impl->Shutdown(); + delete plugin_impl; + } + + return NPERR_NO_ERROR; +} + +NPError NPP_SetWindow(NPP instance, NPWindow* window_info) { + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + if (window_info == NULL) { + NOTREACHED(); + return NPERR_GENERIC_ERROR; + } + + // We may still get a NPP_SetWindow call from webkit in the + // single-process/test_shell case, as this gets invoked in the plugin + // destruction code path. + if (webkit_glue::IsPluginRunningInRendererProcess()) { + return NPERR_GENERIC_ERROR; + } + + PluginInstallerImpl* plugin_impl = + reinterpret_cast<PluginInstallerImpl*>(instance->pdata); + + if (plugin_impl == NULL) { + NOTREACHED(); + return NPERR_GENERIC_ERROR; + } + + HWND window_handle = reinterpret_cast<HWND>(window_info->window); + if (!plugin_impl->SetWindow(window_handle)) { + delete plugin_impl; + return NPERR_GENERIC_ERROR; + } + + return NPERR_NO_ERROR; +} + +NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype) { + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + PluginInstallerImpl* plugin_impl = + reinterpret_cast<PluginInstallerImpl*>(instance->pdata); + + if (!plugin_impl) { + NOTREACHED(); + return NPERR_INVALID_INSTANCE_ERROR; + } + + plugin_impl->NewStream(stream); + return NPERR_NO_ERROR; +} + +NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) { + if (instance == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + PluginInstallerImpl* plugin_impl = + reinterpret_cast<PluginInstallerImpl*>(instance->pdata); + + if (!plugin_impl) { + NOTREACHED(); + return NPERR_INVALID_INSTANCE_ERROR; + } + + plugin_impl->DestroyStream(stream, reason); + return NPERR_NO_ERROR; +} + +int32 NPP_WriteReady(NPP instance, NPStream* stream) { + if (instance == NULL) + return 0; + + PluginInstallerImpl* plugin_impl = + reinterpret_cast<PluginInstallerImpl*>(instance->pdata); + + if (!plugin_impl) { + NOTREACHED(); + return 0; + } + + if (plugin_impl->WriteReady(stream)) + return 0x7FFFFFFF; + return 0; +} + +int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, + void* buffer) { + if (instance == NULL) + return 0; + + PluginInstallerImpl* plugin_impl = + reinterpret_cast<PluginInstallerImpl*>(instance->pdata); + + if (!plugin_impl) { + NOTREACHED(); + return 0; + } + + return plugin_impl->Write(stream, offset, len, buffer); +} + +void NPP_URLNotify(NPP instance, const char* url, NPReason reason, + void* notifyData) { + if (instance != NULL) { + PluginInstallerImpl* plugin_impl = + reinterpret_cast<PluginInstallerImpl*>(instance->pdata); + + if (!plugin_impl) { + NOTREACHED(); + return; + } + + plugin_impl->URLNotify(url, reason); + } +} + +int16 NPP_HandleEvent(NPP instance, void* event) { + if (instance == NULL) + return 0; + + PluginInstallerImpl* plugin_impl = + reinterpret_cast<PluginInstallerImpl*>(instance->pdata); + + return plugin_impl->NPP_HandleEvent(event); +} + +} // default_plugin diff --git a/webkit/default_plugin/plugin_main.h b/webkit/default_plugin/plugin_main.h new file mode 100644 index 0000000..b4e3568 --- /dev/null +++ b/webkit/default_plugin/plugin_main.h @@ -0,0 +1,59 @@ +// 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 <algorithm> +#include <string> + +#include "bindings/npapi.h" +#include "webkit/glue/plugins/nphostapi.h" + +namespace default_plugin { + +extern 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_URLNotify(NPP instance, const char* url, NPReason reason, + void* notifyData); +int16 NPP_HandleEvent(NPP instance, void* event); + +NPError WINAPI NP_GetEntryPoints(NPPluginFuncs* funcs); +NPError WINAPI NP_Initialize(NPNetscapeFuncs* funcs); +NPError WINAPI NP_Shutdown(void); + +} // default_plugin |