summaryrefslogtreecommitdiffstats
path: root/WebCore/plugins/PluginPackage.cpp
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
commit1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353 (patch)
tree4457a7306ea5acb43fe05bfe0973b1f7faf97ba2 /WebCore/plugins/PluginPackage.cpp
parent9364f22aed35e1a1e9d07c121510f80be3ab0502 (diff)
downloadexternal_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.zip
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.gz
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.bz2
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'WebCore/plugins/PluginPackage.cpp')
-rw-r--r--WebCore/plugins/PluginPackage.cpp166
1 files changed, 166 insertions, 0 deletions
diff --git a/WebCore/plugins/PluginPackage.cpp b/WebCore/plugins/PluginPackage.cpp
new file mode 100644
index 0000000..f3c9075
--- /dev/null
+++ b/WebCore/plugins/PluginPackage.cpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Collabora Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "config.h"
+#include "PluginPackage.h"
+
+#include "CString.h"
+#include "MIMETypeRegistry.h"
+#include "PluginDatabase.h"
+#include "PluginDebug.h"
+#include "Timer.h"
+#include "npruntime_impl.h"
+#include <string.h>
+#include <wtf/OwnArrayPtr.h>
+
+namespace WebCore {
+
+PluginPackage::~PluginPackage()
+{
+ // This destructor gets called during refresh() if PluginDatabase's
+ // PluginSet hash is already populated, as it removes items from
+ // the hash table. Calling the destructor on a loaded plug-in of
+ // course would cause a crash, so we check to call unload before we
+ // ASSERT.
+ // FIXME: There is probably a better way to fix this.
+ if (m_loadCount == 0)
+ unloadWithoutShutdown();
+ else
+ unload();
+
+ ASSERT(!m_isLoaded);
+}
+
+void PluginPackage::freeLibrarySoon()
+{
+ ASSERT(!m_freeLibraryTimer.isActive());
+ ASSERT(m_module);
+ ASSERT(m_loadCount == 0);
+
+#ifdef ANDROID_PLUGINS
+ // TODO(jripley): Timer<T> is broken. Unload immediately for now.
+ unloadModule(m_module);
+ m_module = 0;
+#else
+ m_freeLibraryTimer.startOneShot(0);
+#endif
+}
+
+void PluginPackage::freeLibraryTimerFired(Timer<PluginPackage>*)
+{
+ ASSERT(m_module);
+ ASSERT(m_loadCount == 0);
+
+ unloadModule(m_module);
+ m_module = 0;
+}
+
+
+int PluginPackage::compare(const PluginPackage& compareTo) const
+{
+ // Sort plug-ins that allow multiple instances first.
+ bool AallowsMultipleInstances = !quirks().contains(PluginQuirkDontAllowMultipleInstances);
+ bool BallowsMultipleInstances = !compareTo.quirks().contains(PluginQuirkDontAllowMultipleInstances);
+ if (AallowsMultipleInstances != BallowsMultipleInstances)
+ return AallowsMultipleInstances ? -1 : 1;
+
+ // Sort plug-ins in a preferred path first.
+ bool AisInPreferredDirectory = PluginDatabase::isPreferredPluginDirectory(parentDirectory());
+ bool BisInPreferredDirectory = PluginDatabase::isPreferredPluginDirectory(compareTo.parentDirectory());
+ if (AisInPreferredDirectory != BisInPreferredDirectory)
+ return AisInPreferredDirectory ? -1 : 1;
+
+ int diff = strcmp(name().utf8().data(), compareTo.name().utf8().data());
+ if (diff)
+ return diff;
+
+ if (diff = compareFileVersion(compareTo.version()))
+ return diff;
+
+ return strcmp(parentDirectory().utf8().data(), compareTo.parentDirectory().utf8().data());
+}
+
+PluginPackage::PluginPackage(const String& path, const time_t& lastModified)
+ : m_isLoaded(false)
+ , m_loadCount(0)
+ , m_path(path)
+ , m_moduleVersion(0)
+ , m_module(0)
+ , m_lastModified(lastModified)
+ , m_freeLibraryTimer(this, &PluginPackage::freeLibraryTimerFired)
+{
+ m_fileName = pathGetFileName(m_path);
+ m_parentDirectory = m_path.left(m_path.length() - m_fileName.length() - 1);
+}
+
+void PluginPackage::unload()
+{
+ if (!m_isLoaded)
+ return;
+
+ if (--m_loadCount > 0)
+ return;
+
+ m_NPP_Shutdown();
+
+ unloadWithoutShutdown();
+}
+
+void PluginPackage::unloadWithoutShutdown()
+{
+ if (!m_isLoaded)
+ return;
+
+ ASSERT(m_loadCount == 0);
+ ASSERT(m_module);
+
+#if defined(ANDROID_PLUGINS)
+ // Remove the Java object from PluginList.
+ unregisterPluginObject();
+#endif
+
+ // <rdar://5530519>: Crash when closing tab with pdf file (Reader 7 only)
+ // If the plugin has subclassed its parent window, as with Reader 7, we may have
+ // gotten here by way of the plugin's internal window proc forwarding a message to our
+ // original window proc. If we free the plugin library from here, we will jump back
+ // to code we just freed when we return, so delay calling FreeLibrary at least until
+ // the next message loop
+ freeLibrarySoon();
+
+ m_isLoaded = false;
+}
+
+PassRefPtr<PluginPackage> PluginPackage::createPackage(const String& path, const time_t& lastModified)
+{
+ RefPtr<PluginPackage> package = adoptRef(new PluginPackage(path, lastModified));
+
+ if (!package->fetchInfo())
+ return 0;
+
+ return package.release();
+}
+
+}