summaryrefslogtreecommitdiffstats
path: root/chrome/common/chrome_plugin_lib.cc
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
commit09911bf300f1a419907a9412154760efd0b7abc3 (patch)
treef131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/common/chrome_plugin_lib.cc
parent586acc5fe142f498261f52c66862fa417c3d52d2 (diff)
downloadchromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common/chrome_plugin_lib.cc')
-rw-r--r--chrome/common/chrome_plugin_lib.cc278
1 files changed, 278 insertions, 0 deletions
diff --git a/chrome/common/chrome_plugin_lib.cc b/chrome/common/chrome_plugin_lib.cc
new file mode 100644
index 0000000..f1d85eb
--- /dev/null
+++ b/chrome/common/chrome_plugin_lib.cc
@@ -0,0 +1,278 @@
+// 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 "chrome/common/chrome_plugin_lib.h"
+
+#include "base/command_line.h"
+#include "base/histogram.h"
+#include "base/path_service.h"
+#include "base/perftimer.h"
+#include "base/registry.h"
+#include "base/string_util.h"
+#include "chrome/common/chrome_counters.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/chrome_paths.h"
+#include "webkit/glue/plugins/plugin_list.h"
+
+const TCHAR ChromePluginLib::kRegistryChromePlugins[] =
+ _T("Software\\Google\\Chrome\\Plugins");
+static const TCHAR kRegistryLoadOnStartup[] = _T("LoadOnStartup");
+static const TCHAR kRegistryPath[] = _T("Path");
+
+typedef stdext::hash_map<std::wstring, scoped_refptr<ChromePluginLib> >
+ PluginMap;
+
+// A map of all the instantiated plugins.
+static PluginMap* g_loaded_libs;
+
+// The thread plugins are loaded and used in, lazily initialized upon
+// the first creation call.
+static DWORD g_plugin_thread_id = 0;
+
+static bool IsSingleProcessMode() {
+ // We don't support ChromePlugins in single-process mode.
+ CommandLine command_line;
+ return command_line.HasSwitch(switches::kSingleProcess);
+}
+
+// static
+ChromePluginLib* ChromePluginLib::Create(const std::wstring& filename,
+ const CPBrowserFuncs* bfuncs) {
+ // Keep a map of loaded plugins to ensure we only load each library once.
+ if (!g_loaded_libs) {
+ g_loaded_libs = new PluginMap();
+ g_plugin_thread_id = ::GetCurrentThreadId();
+ }
+ DCHECK(IsPluginThread());
+
+ // Lower case to match how PluginList::LoadPlugin stores the path.
+ std::wstring filename_lc = StringToLowerASCII(filename);
+
+ PluginMap::const_iterator iter = g_loaded_libs->find(filename_lc);
+ if (iter != g_loaded_libs->end())
+ return iter->second;
+
+ scoped_refptr<ChromePluginLib> plugin(new ChromePluginLib(filename_lc));
+ if (!plugin->CP_Initialize(bfuncs))
+ return NULL;
+
+ (*g_loaded_libs)[filename_lc] = plugin;
+ return plugin;
+}
+
+// static
+ChromePluginLib* ChromePluginLib::Find(const std::wstring& filename) {
+ if (g_loaded_libs) {
+ PluginMap::const_iterator iter = g_loaded_libs->find(filename);
+ if (iter != g_loaded_libs->end())
+ return iter->second;
+ }
+ return NULL;
+}
+
+// static
+void ChromePluginLib::Destroy(const std::wstring& filename) {
+ DCHECK(g_loaded_libs);
+ PluginMap::iterator iter = g_loaded_libs->find(filename);
+ if (iter != g_loaded_libs->end()) {
+ iter->second->Unload();
+ g_loaded_libs->erase(iter);
+ }
+}
+
+// static
+bool ChromePluginLib::IsPluginThread() {
+ return ::GetCurrentThreadId() == g_plugin_thread_id;
+}
+
+// static
+void ChromePluginLib::RegisterPluginsWithNPAPI() {
+ // We don't support ChromePlugins in single-process mode.
+ if (IsSingleProcessMode())
+ return;
+
+ std::wstring path;
+ if (!PathService::Get(chrome::FILE_GEARS_PLUGIN, &path))
+ return;
+ // Note: we can only access the NPAPI list because the PluginService has done
+ // the locking for us. We should not touch it anywhere else.
+ NPAPI::PluginList::AddExtraPluginPath(path);
+}
+
+static void LogPluginLoadTime(const TimeDelta &time) {
+ UMA_HISTOGRAM_TIMES(L"Gears.LoadTime", time);
+}
+
+// static
+void ChromePluginLib::LoadChromePlugins(const CPBrowserFuncs* bfuncs) {
+ static bool loaded = false;
+ if (loaded)
+ return;
+ loaded = true;
+
+ // We don't support ChromePlugins in single-process mode.
+ if (IsSingleProcessMode())
+ return;
+
+ std::wstring path;
+ if (!PathService::Get(chrome::FILE_GEARS_PLUGIN, &path))
+ return;
+
+ PerfTimer timer;
+ ChromePluginLib::Create(path, bfuncs);
+ LogPluginLoadTime(timer.Elapsed());
+
+ // TODO(mpcomplete): disabled loading of plugins from the registry until we
+ // phase out registry keys from the gears installer.
+#if 0
+ for (RegistryKeyIterator iter(HKEY_CURRENT_USER, kRegistryChromePlugins);
+ iter.Valid(); ++iter) {
+ // Use the registry to gather plugin across the file system.
+ std::wstring reg_path = kRegistryChromePlugins;
+ reg_path.append(L"\\");
+ reg_path.append(iter.Name());
+ RegKey key(HKEY_CURRENT_USER, reg_path.c_str());
+
+ DWORD is_persistent;
+ if (key.ReadValueDW(kRegistryLoadOnStartup, &is_persistent) &&
+ is_persistent) {
+ std::wstring path;
+ if (key.ReadValue(kRegistryPath, &path)) {
+ ChromePluginLib::Create(path, bfuncs);
+ }
+ }
+ }
+#endif
+}
+
+// static
+void ChromePluginLib::UnloadAllPlugins() {
+ if (g_loaded_libs) {
+ PluginMap::iterator it;
+ for (PluginMap::iterator it = g_loaded_libs->begin();
+ it != g_loaded_libs->end(); ++it) {
+ it->second->Unload();
+ }
+ delete g_loaded_libs;
+ g_loaded_libs = NULL;
+ }
+}
+
+ChromePluginLib::ChromePluginLib(const std::wstring& filename)
+ : filename_(filename),
+ module_(0),
+ initialized_(false),
+ CP_VersionNegotiate_(NULL),
+ CP_Initialize_(NULL) {
+ memset((void*)&plugin_funcs_, 0, sizeof(plugin_funcs_));
+}
+
+ChromePluginLib::~ChromePluginLib() {
+}
+
+bool ChromePluginLib::CP_Initialize(const CPBrowserFuncs* bfuncs) {
+ if (initialized_)
+ return true;
+
+ if (!Load())
+ return false;
+
+ if (CP_VersionNegotiate_) {
+ uint16 selected_version = 0;
+ CPError rv = CP_VersionNegotiate_(CP_VERSION, CP_VERSION,
+ &selected_version);
+ if ( (rv != CPERR_SUCCESS) || (selected_version != CP_VERSION))
+ return false;
+ }
+
+ plugin_funcs_.size = sizeof(plugin_funcs_);
+ CPError rv = CP_Initialize_(cpid(), bfuncs, &plugin_funcs_);
+ initialized_ = (rv == CPERR_SUCCESS) &&
+ (CP_GET_MAJOR_VERSION(plugin_funcs_.version) == CP_MAJOR_VERSION) &&
+ (CP_GET_MINOR_VERSION(plugin_funcs_.version) <= CP_MINOR_VERSION);
+
+ return initialized_;
+}
+
+void ChromePluginLib::CP_Shutdown() {
+ DCHECK(initialized_);
+ functions().shutdown();
+ initialized_ = false;
+ memset((void*)&plugin_funcs_, 0, sizeof(plugin_funcs_));
+}
+
+int ChromePluginLib::CP_Test(void* param) {
+ DCHECK(initialized_);
+ if (!CP_Test_)
+ return -1;
+ return CP_Test_(param);
+}
+
+bool ChromePluginLib::Load() {
+ DCHECK(module_ == 0);
+ module_ = LoadLibrary(filename_.c_str());
+ if (module_ == 0)
+ return false;
+
+ // required initialization function
+ CP_Initialize_ = reinterpret_cast<CP_InitializeFunc>
+ (GetProcAddress(module_, "CP_Initialize"));
+
+ if (!CP_Initialize_) {
+ FreeLibrary(module_);
+ module_ = 0;
+ return false;
+ }
+
+ // optional version negotiation function
+ CP_VersionNegotiate_ = reinterpret_cast<CP_VersionNegotiateFunc>
+ (GetProcAddress(module_, "CP_VersionNegotiate"));
+
+ // optional test function
+ CP_Test_ = reinterpret_cast<CP_TestFunc>
+ (GetProcAddress(module_, "CP_Test"));
+
+ return true;
+}
+
+void ChromePluginLib::Unload() {
+ NotificationService::current()->Notify(
+ NOTIFY_CHROME_PLUGIN_UNLOADED,
+ Source<ChromePluginLib>(this),
+ NotificationService::NoDetails());
+
+ if (initialized_)
+ CP_Shutdown();
+
+ if (module_) {
+ FreeLibrary(module_);
+ module_ = 0;
+ }
+}