summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/plugins/android
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-09 16:25:46 +0100
committerSteve Block <steveblock@google.com>2011-05-12 14:28:33 +0100
commit31dbc523d9ee6fd7d7e46c540b5f675eeb559ed7 (patch)
tree3e73099a4bf4c6849c6f448aa3aba9fe408998f8 /Source/WebCore/plugins/android
parentcad810f21b803229eb11403f9209855525a25d57 (diff)
downloadexternal_webkit-31dbc523d9ee6fd7d7e46c540b5f675eeb559ed7.zip
external_webkit-31dbc523d9ee6fd7d7e46c540b5f675eeb559ed7.tar.gz
external_webkit-31dbc523d9ee6fd7d7e46c540b5f675eeb559ed7.tar.bz2
Merge WebKit at r75315: Move Android-specific WebCore files to Source
This moves files in the following WebCore subdirectories ... - bindings/js - bindings/v8/custom - plugins/android - platform/android - platform/graphics/android - page/ - css/ - dom/ - loader/archive/android
Diffstat (limited to 'Source/WebCore/plugins/android')
-rw-r--r--Source/WebCore/plugins/android/PluginClient.h45
-rw-r--r--Source/WebCore/plugins/android/PluginDataAndroid.cpp69
-rw-r--r--Source/WebCore/plugins/android/PluginPackageAndroid.cpp417
-rw-r--r--Source/WebCore/plugins/android/PluginViewAndroid.cpp735
4 files changed, 1266 insertions, 0 deletions
diff --git a/Source/WebCore/plugins/android/PluginClient.h b/Source/WebCore/plugins/android/PluginClient.h
new file mode 100644
index 0000000..e3f7ddf
--- /dev/null
+++ b/Source/WebCore/plugins/android/PluginClient.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 PLUGINCLIENT_H_
+#define PLUGINCLIENT_H_
+
+#include "PlatformString.h"
+#include <wtf/Vector.h>
+
+using namespace WebCore;
+
+namespace android {
+
+ class PluginClient
+ {
+ public:
+ virtual ~PluginClient() {}
+ virtual Vector<String> getPluginDirectories() = 0;
+ virtual String getPluginSharedDataDirectory() = 0;
+ };
+}
+
+#endif /* PLUGINCLIENT_H_ */
diff --git a/Source/WebCore/plugins/android/PluginDataAndroid.cpp b/Source/WebCore/plugins/android/PluginDataAndroid.cpp
new file mode 100644
index 0000000..f46f0f6
--- /dev/null
+++ b/Source/WebCore/plugins/android/PluginDataAndroid.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ * Copyright (C) 2008 Trolltech ASA
+ * Copyright (C) 2006, 2007 Apple 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 "config.h"
+#include "PluginData.h"
+
+#include "PluginDatabase.h"
+#include "PluginPackage.h"
+
+namespace WebCore {
+
+void PluginData::initPlugins()
+{
+ PluginDatabase *db = PluginDatabase::installedPlugins();
+ const Vector<PluginPackage*> &plugins = db->plugins();
+
+ for (unsigned int i = 0; i < plugins.size(); ++i) {
+ PluginInfo info;
+ PluginPackage* package = plugins[i];
+
+ info.name = package->name();
+ info.file = package->fileName();
+ info.desc = package->description();
+
+ const MIMEToDescriptionsMap& mimeToDescriptions = package->mimeToDescriptions();
+ MIMEToDescriptionsMap::const_iterator end = mimeToDescriptions.end();
+ for (MIMEToDescriptionsMap::const_iterator it = mimeToDescriptions.begin(); it != end; ++it) {
+ MimeClassInfo mime;
+ mime.type = it->first;
+ mime.desc = it->second;
+ mime.extensions = package->mimeToExtensions().get(mime.type);
+ info.mimes.append(mime);
+ }
+
+ m_plugins.append(info);
+ }
+}
+
+void PluginData::refresh()
+{
+ PluginDatabase *db = PluginDatabase::installedPlugins();
+ db->refresh();
+}
+
+};
diff --git a/Source/WebCore/plugins/android/PluginPackageAndroid.cpp b/Source/WebCore/plugins/android/PluginPackageAndroid.cpp
new file mode 100644
index 0000000..24de122
--- /dev/null
+++ b/Source/WebCore/plugins/android/PluginPackageAndroid.cpp
@@ -0,0 +1,417 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ * Copyright (C) 2006, 2007 Apple 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 "config.h"
+#include "PluginPackage.h"
+
+#ifdef ANDROID_PLUGINS
+
+#include "JNIUtility.h"
+#include "PlatformString.h"
+#include "PluginDatabase.h"
+#include "PluginMainThreadScheduler.h"
+#include "Timer.h"
+#include "npfunctions.h"
+#include "npruntime_impl.h"
+#include <dlfcn.h>
+#include <errno.h>
+#include <wtf/text/CString.h>
+
+// un-comment this to enable logging
+//#define PLUGIN_DEBUG_LOCAL
+#define LOG_TAG "WebKit"
+#include "NotImplemented.h"
+#include "PluginDebug.h"
+#include "PluginDebugAndroid.h"
+
+namespace WebCore {
+
+// Simple class which calls dlclose() on a dynamic library when going
+// out of scope. Call ok() if the handle should stay open.
+class DynamicLibraryCloser
+{
+ public:
+ DynamicLibraryCloser(PlatformModule *module) : m_module(module) { }
+ ~DynamicLibraryCloser()
+ {
+ // Close the library if non-NULL reference and open.
+ if (m_module && *m_module)
+ {
+ dlclose(*m_module);
+ *m_module = 0;
+ }
+ }
+ void ok() { m_module = NULL; }
+
+ private:
+ PlatformModule *m_module;
+};
+
+// A container for a dummy npp instance. This is used to allow
+// NPN_PluginThreadAsyncCall() to be used with NULL passed as the npp
+// instance. This is substituted instead, and is shared between all
+// plugins which behave in this way. This will be lazily created in
+// the first call to NPN_PluginThreadAsyncCall().
+class DummyNpp {
+ public:
+ DummyNpp() {
+ m_npp = new NPP_t();
+ m_npp->pdata = NULL;
+ m_npp->ndata = NULL;
+ PluginMainThreadScheduler::scheduler().registerPlugin(m_npp);
+ }
+ ~DummyNpp() {
+ PluginMainThreadScheduler::scheduler().unregisterPlugin(m_npp);
+ delete m_npp;
+ }
+ NPP_t *getInstance() { return m_npp; }
+
+ private:
+ NPP_t *m_npp;
+};
+
+static bool getEntryPoint(PlatformModule module,
+ const char *name,
+ void **entry_point)
+{
+ dlerror();
+ *entry_point = dlsym(module, name);
+ const char *error = dlerror();
+ if(error == NULL && *entry_point != NULL) {
+ return true;
+ } else {
+ PLUGIN_LOG("Couldn't get entry point \"%s\": %s\n",
+ name, error);
+ return false;
+ }
+}
+
+bool PluginPackage::isPluginBlacklisted()
+{
+ // No blacklisted Android plugins... yet!
+ return false;
+}
+
+void PluginPackage::determineQuirks(const String& mimeType)
+{
+ // The Gears implementation relies on it being loaded *all the time*,
+ // so check to see if this package represents the Gears plugin and
+ // load it.
+ if (mimeType == "application/x-googlegears") {
+ m_quirks.add(PluginQuirkDontUnloadPlugin);
+ }
+}
+
+static void Android_NPN_PluginThreadAsyncCall(NPP instance,
+ void (*func) (void *),
+ void *userData)
+{
+ // Translate all instance == NULL to a dummy actual npp.
+ static DummyNpp dummyNpp;
+ if (instance == NULL) {
+ instance = dummyNpp.getInstance();
+ }
+ // Call through to the wrapped function.
+ NPN_PluginThreadAsyncCall(instance, func, userData);
+}
+
+static void initializeExtraBrowserFuncs(NPNetscapeFuncs *funcs)
+{
+ funcs->version = NP_VERSION_MINOR;
+ funcs->geturl = NPN_GetURL;
+ funcs->posturl = NPN_PostURL;
+ funcs->requestread = NPN_RequestRead;
+ funcs->newstream = NPN_NewStream;
+ funcs->write = NPN_Write;
+ funcs->destroystream = NPN_DestroyStream;
+ funcs->status = NPN_Status;
+ funcs->uagent = NPN_UserAgent;
+ funcs->memalloc = NPN_MemAlloc;
+ funcs->memfree = NPN_MemFree;
+ funcs->memflush = NPN_MemFlush;
+ funcs->reloadplugins = NPN_ReloadPlugins;
+ funcs->geturlnotify = NPN_GetURLNotify;
+ funcs->posturlnotify = NPN_PostURLNotify;
+ funcs->getvalue = NPN_GetValue;
+ funcs->setvalue = NPN_SetValue;
+ funcs->invalidaterect = NPN_InvalidateRect;
+ funcs->invalidateregion = NPN_InvalidateRegion;
+ funcs->forceredraw = NPN_ForceRedraw;
+ funcs->getJavaEnv = NPN_GetJavaEnv;
+ funcs->getJavaPeer = NPN_GetJavaPeer;
+ funcs->pushpopupsenabledstate = NPN_PushPopupsEnabledState;
+ funcs->poppopupsenabledstate = NPN_PopPopupsEnabledState;
+ funcs->pluginthreadasynccall = Android_NPN_PluginThreadAsyncCall;
+ funcs->scheduletimer = NPN_ScheduleTimer;
+ funcs->unscheduletimer = NPN_UnscheduleTimer;
+
+ funcs->releasevariantvalue = _NPN_ReleaseVariantValue;
+ funcs->getstringidentifier = _NPN_GetStringIdentifier;
+ funcs->getstringidentifiers = _NPN_GetStringIdentifiers;
+ funcs->getintidentifier = _NPN_GetIntIdentifier;
+ funcs->identifierisstring = _NPN_IdentifierIsString;
+ funcs->utf8fromidentifier = _NPN_UTF8FromIdentifier;
+ funcs->intfromidentifier = _NPN_IntFromIdentifier;
+ funcs->createobject = _NPN_CreateObject;
+ funcs->retainobject = _NPN_RetainObject;
+ funcs->releaseobject = _NPN_ReleaseObject;
+ funcs->invoke = _NPN_Invoke;
+ funcs->invokeDefault = _NPN_InvokeDefault;
+ funcs->evaluate = _NPN_Evaluate;
+ funcs->getproperty = _NPN_GetProperty;
+ funcs->setproperty = _NPN_SetProperty;
+ funcs->removeproperty = _NPN_RemoveProperty;
+ funcs->hasproperty = _NPN_HasProperty;
+ funcs->hasmethod = _NPN_HasMethod;
+ funcs->setexception = _NPN_SetException;
+ funcs->enumerate = _NPN_Enumerate;
+}
+
+bool PluginPackage::load()
+{
+ PLUGIN_LOG("tid:%d isActive:%d isLoaded:%d loadCount:%d\n",
+ gettid(),
+ m_freeLibraryTimer.isActive(),
+ m_isLoaded,
+ m_loadCount);
+ if (m_freeLibraryTimer.isActive()) {
+ ASSERT(m_module);
+ m_freeLibraryTimer.stop();
+ } else if (m_isLoaded) {
+ if (m_quirks.contains(PluginQuirkDontAllowMultipleInstances))
+ return false;
+ m_loadCount++;
+ PLUGIN_LOG("Already loaded, count now %d\n", m_loadCount);
+ return true;
+ } else {
+ ASSERT(m_loadCount == 0);
+ ASSERT(m_module == NULL);
+
+ PLUGIN_LOG("Loading \"%s\"\n", m_path.utf8().data());
+
+ // Open the library
+ void *handle = dlopen(m_path.utf8().data(), RTLD_NOW);
+ if(!handle) {
+ PLUGIN_LOG("Couldn't load plugin library \"%s\": %s\n",
+ m_path.utf8().data(), dlerror());
+ return false;
+ }
+ m_module = handle;
+ PLUGIN_LOG("Fetch Info Loaded %p\n", m_module);
+ }
+
+ // This object will call dlclose() and set m_module to NULL
+ // when going out of scope.
+ DynamicLibraryCloser dlCloser(&m_module);
+
+
+ NP_InitializeFuncPtr NP_Initialize;
+ if(!getEntryPoint(m_module, "NP_Initialize", (void **) &NP_Initialize) ||
+ !getEntryPoint(m_module, "NP_Shutdown", (void **) &m_NPP_Shutdown)) {
+ PLUGIN_LOG("Couldn't find Initialize function\n");
+ return false;
+ }
+
+ // Provide the plugin with our browser function table and grab its
+ // plugin table. Provide the Java environment and the Plugin which
+ // can be used to override the defaults if the plugin wants.
+ initializeBrowserFuncs();
+ // call this afterwards, which may re-initialize some methods, but ensures
+ // that any additional (or changed) procs are set. There is no real attempt
+ // to have this step be minimal (i.e. only what we add/override), since the
+ // core version (initializeBrowserFuncs) can change in the future.
+ initializeExtraBrowserFuncs(&m_browserFuncs);
+
+ memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs));
+ m_pluginFuncs.size = sizeof(m_pluginFuncs);
+ if(NP_Initialize(&m_browserFuncs,
+ &m_pluginFuncs,
+ JSC::Bindings::getJNIEnv()) != NPERR_NO_ERROR) {
+ PLUGIN_LOG("Couldn't initialize plugin\n");
+ return false;
+ }
+
+ // Don't close the library - loaded OK.
+ dlCloser.ok();
+ m_isLoaded = true;
+ ++m_loadCount;
+ PLUGIN_LOG("Initial load ok, count now %d\n", m_loadCount);
+ return true;
+}
+
+bool PluginPackage::fetchInfo()
+{
+ PLUGIN_LOG("Fetch Info Loading \"%s\"\n", m_path.utf8().data());
+
+ // Open the library
+ void *handle = dlopen(m_path.utf8().data(), RTLD_NOW);
+ if(!handle) {
+ PLUGIN_LOG("Couldn't load plugin library \"%s\": %s\n",
+ m_path.utf8().data(), dlerror());
+ return false;
+ }
+ PLUGIN_LOG("Fetch Info Loaded %p\n", handle);
+
+ // This object will call dlclose() and set m_module to NULL
+ // when going out of scope.
+ DynamicLibraryCloser dlCloser(&handle);
+
+ // Get the three entry points we need for Linux Netscape Plug-ins
+ NP_GetMIMEDescriptionFuncPtr NP_GetMIMEDescription;
+ NPP_GetValueProcPtr NP_GetValue;
+ if(!getEntryPoint(handle, "NP_GetMIMEDescription",
+ (void **) &NP_GetMIMEDescription) ||
+ !getEntryPoint(handle, "NP_GetValue", (void **) &NP_GetValue)) {
+ // If any of those failed to resolve, fail the entire load
+ return false;
+ }
+
+ // Get the plugin name and description using NP_GetValue
+ const char *name;
+ const char *description;
+ if(NP_GetValue(NULL, NPPVpluginNameString, &name) != NPERR_NO_ERROR ||
+ NP_GetValue(NULL, NPPVpluginDescriptionString, &description) !=
+ NPERR_NO_ERROR) {
+ PLUGIN_LOG("Couldn't get name/description using NP_GetValue\n");
+ return false;
+ }
+
+ PLUGIN_LOG("Plugin name: \"%s\"\n", name);
+ PLUGIN_LOG("Plugin description: \"%s\"\n", description);
+ m_name = name;
+ m_description = description;
+
+ // fileName is just the trailing part of the path
+ int last_slash = m_path.reverseFind('/');
+ if(last_slash < 0)
+ m_fileName = m_path;
+ else
+ m_fileName = m_path.substring(last_slash + 1);
+
+ // Grab the MIME description. This is in the format, e.g:
+ // application/x-somescriptformat:ssf:Some Script Format
+ String mimeDescription(NP_GetMIMEDescription());
+ PLUGIN_LOG("MIME description: \"%s\"\n", mimeDescription.utf8().data());
+ // Clear out the current mappings.
+ m_mimeToDescriptions.clear();
+ m_mimeToExtensions.clear();
+ // Split the description into its component entries, separated by
+ // semicolons.
+ Vector<String> mimeEntries;
+ mimeDescription.split(';', true, mimeEntries);
+ // Iterate through the entries, adding them to the MIME mappings.
+ for(Vector<String>::const_iterator it = mimeEntries.begin();
+ it != mimeEntries.end(); ++it) {
+ // Each part is split into 3 fields separated by colons
+ // Field 1 is the MIME type (e.g "application/x-shockwave-flash").
+ // Field 2 is a comma separated list of file extensions.
+ // Field 3 is a human readable short description.
+ const String &mimeEntry = *it;
+ Vector<String> fields;
+ mimeEntry.split(':', true, fields);
+ if(fields.size() != 3) {
+ PLUGIN_LOG("Bad MIME entry \"%s\"\n", mimeEntry.utf8().data());
+ return false;
+ }
+
+ const String& mimeType = fields[0];
+ Vector<String> extensions;
+ fields[1].split(',', true, extensions);
+ const String& description = fields[2];
+
+ determineQuirks(mimeType);
+
+ PLUGIN_LOG("mime_type: \"%s\"\n", mimeType.utf8().data());
+ PLUGIN_LOG("extensions: \"%s\"\n", fields[1].utf8().data());
+ PLUGIN_LOG("description: \"%s\"\n", description.utf8().data());
+
+ // Map the mime type to the vector of extensions and the description
+ if(!extensions.isEmpty())
+ m_mimeToExtensions.set(mimeType, extensions);
+ if(!description.isEmpty())
+ m_mimeToDescriptions.set(mimeType, description);
+ }
+
+ PLUGIN_LOG("Fetch Info Loaded plugin details ok \"%s\"\n",
+ m_path.utf8().data());
+
+ // If this plugin needs to be kept in memory, unload the module now
+ // and load it permanently.
+ if (m_quirks.contains(PluginQuirkDontUnloadPlugin)) {
+ dlCloser.ok();
+ dlclose(handle);
+ load();
+ }
+
+ // dlCloser will unload the plugin if required.
+ return true;
+}
+
+unsigned PluginPackage::hash() const
+{
+ const unsigned hashCodes[] = {
+ m_name.impl()->hash(),
+ m_description.impl()->hash(),
+ m_mimeToExtensions.size(),
+ };
+
+ return StringImpl::computeHash(reinterpret_cast<const UChar*>(hashCodes),
+ sizeof(hashCodes) / sizeof(UChar));
+}
+
+bool PluginPackage::equal(const PluginPackage& a, const PluginPackage& b)
+{
+ if (a.m_name != b.m_name)
+ return false;
+
+ if (a.m_description != b.m_description)
+ return false;
+
+ if (a.m_mimeToExtensions.size() != b.m_mimeToExtensions.size())
+ return false;
+
+ MIMEToExtensionsMap::const_iterator::Keys end =
+ a.m_mimeToExtensions.end().keys();
+ for (MIMEToExtensionsMap::const_iterator::Keys it =
+ a.m_mimeToExtensions.begin().keys();
+ it != end;
+ ++it) {
+ if (!b.m_mimeToExtensions.contains(*it)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+uint16_t PluginPackage::NPVersion() const
+{
+ return NP_VERSION_MINOR;
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/plugins/android/PluginViewAndroid.cpp b/Source/WebCore/plugins/android/PluginViewAndroid.cpp
new file mode 100644
index 0000000..6c712d0
--- /dev/null
+++ b/Source/WebCore/plugins/android/PluginViewAndroid.cpp
@@ -0,0 +1,735 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ * Copyright (C) 2006, 2007 Apple 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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.
+ */
+
+#define LOG_TAG "WebCore"
+
+#include "config.h"
+#include "PluginView.h"
+
+#include "Document.h"
+#include "Element.h"
+#include "EventNames.h"
+#include "FocusController.h"
+#include "FrameLoader.h"
+#include "FrameLoadRequest.h"
+#include "FrameTree.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HTMLNames.h"
+#include "HTMLPlugInElement.h"
+#include "Image.h"
+#include "KeyboardEvent.h"
+#include "MIMETypeRegistry.h"
+#include "MouseEvent.h"
+#include "NetworkStateNotifier.h"
+#include "NotImplemented.h"
+#include "Page.h"
+#include "PlatformGraphicsContext.h"
+#include "PlatformKeyboardEvent.h"
+#include "PluginMainThreadScheduler.h"
+#include "PluginPackage.h"
+#include "Touch.h"
+#include "TouchEvent.h"
+#include "TouchList.h"
+#include "android_graphics.h"
+#include "SkCanvas.h"
+#include "npruntime_impl.h"
+// #include "runtime_root.h"
+#include "utils/SystemClock.h"
+#include "ScriptController.h"
+#include "Settings.h"
+
+#if USE(JSC)
+#include <runtime/JSLock.h>
+#endif
+
+#include <wtf/ASCIICType.h>
+// #include "runtime.h"
+#include "WebViewCore.h"
+
+/* Controls the printing of log messages in this file. This must be defined
+ before PluginDebugAndroid.h is included.
+ */
+// #define PLUGIN_DEBUG_LOCAL
+#define TRACE_KEY_EVENTS 0
+
+#include "PluginDebug.h"
+#include "PluginDebugAndroid.h"
+#include "PluginViewBridgeAndroid.h"
+#include "PluginWidgetAndroid.h"
+
+#include "android_npapi.h"
+#include "ANPOpenGL_npapi.h"
+#include "ANPSurface_npapi.h"
+#include "ANPSystem_npapi.h"
+#include "ANPVideo_npapi.h"
+#include "SkANP.h"
+#include "SkFlipPixelRef.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern void ANPAudioTrackInterfaceV0_Init(ANPInterface* value);
+extern void ANPAudioTrackInterfaceV1_Init(ANPInterface* value);
+extern void ANPBitmapInterfaceV0_Init(ANPInterface* value);
+extern void ANPCanvasInterfaceV0_Init(ANPInterface* value);
+extern void ANPEventInterfaceV0_Init(ANPInterface* value);
+extern void ANPLogInterfaceV0_Init(ANPInterface* value);
+extern void ANPMatrixInterfaceV0_Init(ANPInterface* value);
+extern void ANPOffscreenInterfaceV0_Init(ANPInterface* value);
+extern void ANPPaintInterfaceV0_Init(ANPInterface* value);
+extern void ANPPathInterfaceV0_Init(ANPInterface* value);
+extern void ANPSurfaceInterfaceV0_Init(ANPInterface* value);
+extern void ANPTypefaceInterfaceV0_Init(ANPInterface* value);
+extern void ANPWindowInterfaceV0_Init(ANPInterface* value);
+extern void ANPWindowInterfaceV1_Init(ANPInterface* value);
+extern void ANPSystemInterfaceV0_Init(ANPInterface* value);
+extern void ANPSystemInterfaceV1_Init(ANPInterface* value);
+extern void ANPSystemInterfaceV2_Init(ANPInterface* value);
+extern void ANPOpenGLInterfaceV0_Init(ANPInterface* value);
+extern void ANPVideoInterfaceV0_Init(ANPInterface* value);
+
+struct VarProcPair {
+ int enumValue;
+ size_t size;
+ void (*proc)(ANPInterface*);
+};
+
+#define VARPROCLINE(name) \
+ k##name##_ANPGetValue, sizeof(ANP##name), ANP##name##_Init
+
+static const VarProcPair gVarProcs[] = {
+ { VARPROCLINE(AudioTrackInterfaceV0) },
+ { VARPROCLINE(AudioTrackInterfaceV1) },
+ { VARPROCLINE(BitmapInterfaceV0) },
+ { VARPROCLINE(CanvasInterfaceV0) },
+ { VARPROCLINE(EventInterfaceV0) },
+ { VARPROCLINE(LogInterfaceV0) },
+ { VARPROCLINE(MatrixInterfaceV0) },
+ { VARPROCLINE(PaintInterfaceV0) },
+ { VARPROCLINE(PathInterfaceV0) },
+ { VARPROCLINE(SurfaceInterfaceV0) },
+ { VARPROCLINE(TypefaceInterfaceV0) },
+ { VARPROCLINE(WindowInterfaceV0) },
+ { VARPROCLINE(WindowInterfaceV1) },
+ { VARPROCLINE(SystemInterfaceV0) },
+ { VARPROCLINE(SystemInterfaceV1) },
+ { VARPROCLINE(SystemInterfaceV2) },
+ { VARPROCLINE(OpenGLInterfaceV0) },
+ { VARPROCLINE(VideoInterfaceV0) },
+};
+
+/* return true if var was an interface request (error will be set accordingly)
+ return false if var is not a recognized interface (and ignore error param)
+ */
+static bool anp_getInterface(NPNVariable var, void* value, NPError* error) {
+ const VarProcPair* iter = gVarProcs;
+ const VarProcPair* stop = gVarProcs + SK_ARRAY_COUNT(gVarProcs);
+ while (iter < stop) {
+ if (iter->enumValue == var) {
+ ANPInterface* i = reinterpret_cast<ANPInterface*>(value);
+ if (i->inSize < iter->size) {
+ SkDebugf("------- interface %d, expected size %d, allocated %d\n",
+ var, iter->size, i->inSize);
+ *error = NPERR_INCOMPATIBLE_VERSION_ERROR;
+ } else {
+ iter->proc(i);
+ *error = NPERR_NO_ERROR;
+ }
+ return true;
+ }
+ iter += 1;
+ }
+ SkDebugf("------ unknown NPNVariable %d\n", var);
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+using std::min;
+
+using namespace WTF;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+void PluginView::platformInit()
+{
+ setPlatformWidget(new PluginViewBridgeAndroid());
+
+ m_isWindowed = false; // we don't support windowed yet
+
+ m_window = new PluginWidgetAndroid(this);
+
+ m_npWindow.type = NPWindowTypeDrawable;
+ m_npWindow.window = 0;
+}
+
+bool PluginView::platformStart()
+{
+ return true;
+}
+
+void PluginView::platformDestroy()
+{
+ delete m_window;
+}
+
+PlatformLayer* PluginView::platformLayer() const
+{
+ return (PlatformLayer*) m_window->getLayer();
+}
+
+#if ENABLE(TOUCH_EVENTS)
+void PluginView::handleTouchEvent(TouchEvent* event)
+{
+ if (!m_window->isAcceptingEvent(kTouch_ANPEventFlag))
+ return;
+
+ if (!m_window->inFullScreen() && m_parentFrame->document()->focusedNode() != m_element)
+ return;
+
+ ANPEvent evt;
+ SkANP::InitEvent(&evt, kMultiTouch_ANPEventType);
+
+ const AtomicString& type = event->type();
+ if (eventNames().touchstartEvent == type)
+ evt.data.multiTouch.action = kDown_ANPTouchAction;
+ else if (eventNames().touchendEvent == type)
+ evt.data.multiTouch.action = kUp_ANPTouchAction;
+ else if (eventNames().touchmoveEvent == type)
+ evt.data.multiTouch.action = kMove_ANPTouchAction;
+ else if (eventNames().touchcancelEvent == type)
+ evt.data.multiTouch.action = kCancel_ANPTouchAction;
+ else if (eventNames().touchlongpressEvent == type)
+ evt.data.multiTouch.action = kLongPress_ANPTouchAction;
+ else if (eventNames().touchdoubletapEvent == type)
+ evt.data.multiTouch.action = kDoubleTap_ANPTouchAction;
+ else
+ return;
+
+ // set the id and timestamp
+ evt.data.multiTouch.id = 0; // TODO
+ evt.data.multiTouch.timestamp = 0; // TODO
+
+ // In the event of a touchend (up) or touchcancel event, we must ask the changedTouch for the
+ // co-ordinates as there is no touch in touches anymore.
+ TouchList* touches = (evt.data.multiTouch.action == kUp_ANPTouchAction
+ || evt.data.multiTouch.action == kCancel_ANPTouchAction) ? event->changedTouches() : event->touches();
+
+ // set each touchPoint
+ int pointerCount = touches->length();
+ evt.data.multiTouch.pointerCount = pointerCount;
+ evt.data.multiTouch.touchPoint = new TouchPoint[pointerCount];
+
+ for (int x = 0; x < evt.data.multiTouch.pointerCount; x++) {
+ Touch* touch = touches->item(x);
+ // Convert to coordinates that are relative to the plugin.
+ IntPoint localPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(IntPoint(touch->pageX(), touch->pageY())));
+
+ evt.data.multiTouch.touchPoint[x].id = touch->identifier();
+ evt.data.multiTouch.touchPoint[x].x = localPos.x();
+ evt.data.multiTouch.touchPoint[x].y = localPos.y();
+ evt.data.multiTouch.touchPoint[x].pressure = 1; // TODO
+ evt.data.multiTouch.touchPoint[x].size = 1; // TODO
+ }
+
+ if (m_window->sendEvent(evt))
+ event->preventDefault();
+
+ // cleanup the touch points we allocated
+ delete[] evt.data.multiTouch.touchPoint;
+}
+#endif
+
+void PluginView::handleMouseEvent(MouseEvent* event)
+{
+ const AtomicString& type = event->type();
+ bool isUp = (eventNames().mouseupEvent == type);
+ bool isDown = (eventNames().mousedownEvent == type);
+
+ ANPEvent evt;
+
+ if (isUp || isDown) {
+ SkANP::InitEvent(&evt, kMouse_ANPEventType);
+ evt.data.mouse.action = isUp ? kUp_ANPMouseAction : kDown_ANPMouseAction;
+
+ // Convert to coordinates that are relative to the plugin.
+ IntPoint localPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(event->absoluteLocation()));
+ evt.data.mouse.x = localPos.x();
+ evt.data.mouse.y = localPos.y();
+
+ if (isDown) {
+ // The plugin needs focus to receive keyboard and touch events
+ m_element->focus();
+ event->setDefaultHandled();
+ }
+ }
+ else {
+ return;
+ }
+
+ if (m_window->sendEvent(evt)) {
+ event->setDefaultHandled();
+ }
+}
+
+static ANPKeyModifier make_modifiers(bool shift, bool alt) {
+ ANPKeyModifier mod = 0;
+ if (shift) {
+ mod |= kShift_ANPKeyModifier;
+ }
+ if (alt) {
+ mod |= kAlt_ANPKeyModifier;
+ }
+ return mod;
+}
+
+void PluginView::handleFocusEvent(bool hasFocus)
+{
+ ANPEvent evt;
+ SkANP::InitEvent(&evt, kLifecycle_ANPEventType);
+ evt.data.lifecycle.action = hasFocus ? kGainFocus_ANPLifecycleAction :
+ kLoseFocus_ANPLifecycleAction;
+ m_window->sendEvent(evt);
+
+ // redraw the plugin which subsequently invalidates the nav cache
+ IntRect rect = IntRect(m_npWindow.x, m_npWindow.y,
+ m_npWindow.width, m_npWindow.height);
+ m_window->webViewCore()->contentInvalidate(rect);
+}
+
+void PluginView::handleKeyboardEvent(KeyboardEvent* event)
+{
+ if (!m_window->isAcceptingEvent(kKey_ANPEventFlag))
+ return;
+
+ const PlatformKeyboardEvent* pke = event->keyEvent();
+ if (NULL == pke) {
+ return;
+ }
+
+ bool ignoreEvent = false;
+
+ ANPEvent evt;
+ SkANP::InitEvent(&evt, kKey_ANPEventType);
+
+ switch (pke->type()) {
+ case PlatformKeyboardEvent::KeyDown:
+#if TRACE_KEY_EVENTS
+ PLUGIN_LOG("--------- KeyDown, ignore\n");
+#endif
+ ignoreEvent = true;
+ break;
+ case PlatformKeyboardEvent::RawKeyDown:
+ evt.data.key.action = kDown_ANPKeyAction;
+ break;
+ case PlatformKeyboardEvent::Char:
+#if TRACE_KEY_EVENTS
+ PLUGIN_LOG("--------- Char, ignore\n");
+#endif
+ ignoreEvent = true;
+ break;
+ case PlatformKeyboardEvent::KeyUp:
+ evt.data.key.action = kUp_ANPKeyAction;
+ break;
+ default:
+#if TRACE_KEY_EVENTS
+ PLUGIN_LOG("------ unexpected keyevent type %d\n", pke->type());
+#endif
+ ignoreEvent = true;
+ break;
+ }
+
+ /* the plugin should be the only party able to return nav control to the
+ * browser UI. Therefore, if we discard an event on behalf of the plugin
+ * we should mark the event as being handled.
+ */
+ if (ignoreEvent) {
+ int keyCode = pke->nativeVirtualKeyCode();
+ if (keyCode >= kDpadUp_ANPKeyCode && keyCode <= kDpadCenter_ANPKeyCode)
+ event->setDefaultHandled();
+ return;
+ }
+
+ evt.data.key.nativeCode = pke->nativeVirtualKeyCode();
+ evt.data.key.virtualCode = pke->windowsVirtualKeyCode();
+ evt.data.key.repeatCount = pke->repeatCount();
+ evt.data.key.modifiers = make_modifiers(pke->shiftKey(), pke->altKey());
+ evt.data.key.unichar = pke->unichar();
+
+ if (m_window->sendEvent(evt)) {
+ event->setDefaultHandled();
+ } else if (m_window->inFullScreen()){
+ // while in the full screen mode, always consumes the key events and
+ // keeps the document focus
+ event->setDefaultHandled();
+ } else {
+ // remove the plugin from the document's focus
+ m_parentFrame->document()->focusedNodeRemoved();
+ }
+}
+
+NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf)
+{
+ notImplemented();
+ return NPERR_GENERIC_ERROR;
+}
+
+bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPError* result)
+{
+ // our interface query is valid with no NPP instance
+ *result = NPERR_GENERIC_ERROR;
+
+ switch (variable) {
+ case NPNVisOfflineBool: {
+ if (value != NULL) {
+ bool* retValue = static_cast<bool*>(value);
+ *retValue = !networkStateNotifier().onLine();
+ *result = NPERR_NO_ERROR;
+ return true;
+ }
+ break;
+ }
+ case kJavaContext_ANPGetValue: {
+ jobject* retObject = static_cast<jobject*>(value);
+ *retObject = android::WebViewCore::getApplicationContext();
+ *result = NPERR_NO_ERROR;
+ return true;
+ }
+ default:
+ ; // do nothing
+ }
+
+ (void)anp_getInterface(variable, value, result);
+ return true;
+}
+
+void PluginView::setParent(ScrollView* parent)
+{
+ PLUGIN_LOG("--%p SetParent old=[%p], new=[%p] \n", instance(), this->parent(), parent);
+
+ Widget::setParent(parent);
+
+ if (parent) {
+ // the widget needs initialized now so that the plugin has access to
+ // WebViewCore when NPP_New is called
+ if (m_window && !m_window->webViewCore()) {
+ android::WebViewCore* c = android::WebViewCore::getWebViewCore(this->parent());
+ m_window->init(c);
+ }
+ init();
+
+ /* Our widget needs to recompute its m_windowRect which then sets
+ the NPWindowRect if necessary. This ensures that if NPWindowRect
+ is set prior to parent() being set that we still (1) notify the
+ plugin of its current rect and (2) that we execute our logic in
+ PluginWidgetAndroid in response to changes to NPWindowRect.
+ */
+ updatePluginWidget();
+ }
+}
+
+void PluginView::setNPWindowRect(const IntRect&)
+{
+ setNPWindowIfNeeded();
+}
+
+void PluginView::setNPWindowIfNeeded()
+{
+ PLUGIN_LOG("--%p SetWindow isStarted=[%d] \n", instance(), m_isStarted);
+
+ if (!m_isStarted || !parent())
+ return;
+
+ // in Android, plugin always get the setwindow() in the page coordinate.
+
+ // the m_npWindow is relative to the page
+ m_npWindow.x = m_pageRect.x();
+ m_npWindow.y = m_pageRect.y();
+ m_npWindow.width = m_pageRect.width();
+ m_npWindow.height = m_pageRect.height();
+
+ m_npWindow.clipRect.left = m_pageRect.x();
+ m_npWindow.clipRect.top = m_pageRect.y();
+ m_npWindow.clipRect.right = m_pageRect.x() + m_pageRect.width();
+ m_npWindow.clipRect.bottom = m_pageRect.y() + m_pageRect.height();
+
+ if (m_plugin->pluginFuncs()->setwindow) {
+#if USE(JSC)
+ JSC::JSLock::DropAllLocks dropAllLocks(false);
+#endif
+ setCallingPlugin(true);
+ m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow);
+ setCallingPlugin(false);
+ }
+
+ m_window->setWindow(&m_npWindow, m_isTransparent);
+}
+
+bool PluginView::platformGetValue(NPNVariable variable, void* value, NPError* result)
+{
+ switch (variable) {
+ case NPNVWindowNPObject: {
+ NPObject* windowScriptObject =
+ m_parentFrame->script()->windowScriptNPObject();
+
+ // Return value is expected to be retained, as described
+ // here:
+ // <http://www.mozilla.org/projects/plugin/npruntime.html>
+ if (windowScriptObject)
+ _NPN_RetainObject(windowScriptObject);
+
+ void** v = (void**)value;
+ *v = windowScriptObject;
+
+ *result = NPERR_NO_ERROR;
+ return true;
+ }
+
+ case NPNVPluginElementNPObject: {
+ NPObject* pluginScriptObject = 0;
+
+ if (m_element->hasTagName(appletTag) ||
+ m_element->hasTagName(embedTag) ||
+ m_element->hasTagName(objectTag)) {
+ HTMLPlugInElement* pluginElement =
+ static_cast<HTMLPlugInElement*>(m_element);
+ pluginScriptObject = pluginElement->getNPObject();
+ }
+
+ // Return value is expected to be retained, as described
+ // here:
+ // <http://www.mozilla.org/projects/plugin/npruntime.html>
+ if (pluginScriptObject)
+ _NPN_RetainObject(pluginScriptObject);
+
+ void** v = (void**)value;
+ *v = pluginScriptObject;
+
+ *result = NPERR_NO_ERROR;
+ return true;
+ }
+
+ case NPNVnetscapeWindow: {
+ // Return the top level WebView Java object associated
+ // with this instance.
+ jobject *retObject = static_cast<jobject*>(value);
+ *retObject = android::WebViewCore::getWebViewCore(parent())->getWebViewJavaObject();
+ *result = NPERR_NO_ERROR;
+ return true;
+ }
+
+ case NPNVisOfflineBool: {
+ if (value == NULL) {
+ *result = NPERR_GENERIC_ERROR;
+ return true;
+ }
+ bool* retValue = static_cast<bool*>(value);
+ *retValue = !networkStateNotifier().onLine();
+ *result = NPERR_NO_ERROR;
+ return true;
+ }
+
+ case kSupportedDrawingModel_ANPGetValue: {
+ uint32_t* bits = reinterpret_cast<uint32_t*>(value);
+ *bits = kBitmap_ANPDrawingModel & kSurface_ANPDrawingModel;
+ *result = NPERR_NO_ERROR;
+ return true;
+ }
+
+ case kJavaContext_ANPGetValue: {
+ jobject* retObject = static_cast<jobject*>(value);
+ *retObject = android::WebViewCore::getWebViewCore(parent())->getContext();
+ *result = NPERR_NO_ERROR;
+ return true;
+ }
+
+ default: {
+ NPError error = NPERR_GENERIC_ERROR;
+ (void)anp_getInterface(variable, value, &error);
+ *result = error;
+ return true;
+ }
+ }
+}
+
+NPError PluginView::platformSetValue(NPPVariable variable, void* value)
+{
+ NPError error = NPERR_GENERIC_ERROR;
+
+ switch (variable) {
+ case kRequestDrawingModel_ANPSetValue: {
+ ANPDrawingModel model = reinterpret_cast<ANPDrawingModel>(value);
+ if (m_window->setDrawingModel(model))
+ error = NPERR_NO_ERROR;
+ break;
+ }
+ case kAcceptEvents_ANPSetValue : {
+ if(value) {
+ ANPEventFlags flags = *reinterpret_cast<ANPEventFlags*>(value);
+ m_window->updateEventFlags(flags);
+ error = NPERR_NO_ERROR;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return error;
+}
+
+void PluginView::invalidateRect(const IntRect& r)
+{
+ m_window->inval(r, true);
+}
+
+void PluginView::invalidateRect(NPRect* rect)
+{
+ IntRect r;
+
+ if (rect) {
+ r = IntRect(rect->left, rect->top,
+ rect->right - rect->left, rect->bottom - rect->top);
+ } else {
+ r = IntRect(0, 0, m_npWindow.width, m_npWindow.height);
+ }
+
+ m_window->inval(r, true);
+}
+
+void PluginView::invalidateRegion(NPRegion region)
+{
+ // we don't support/define regions (yet), so do nothing
+}
+
+void PluginView::forceRedraw()
+{
+ this->invalidateRect(0);
+}
+
+void PluginView::setFocus(bool focused)
+{
+ Widget::setFocus(focused);
+// SkDebugf("------------- setFocus %p\n", this);
+}
+
+void PluginView::show()
+{
+ setSelfVisible(true);
+ Widget::show();
+
+ if (platformPluginWidget())
+ platformPluginWidget()->layoutSurface();
+
+}
+
+void PluginView::hide()
+{
+ setSelfVisible(false);
+ Widget::hide();
+
+ if (platformPluginWidget())
+ platformPluginWidget()->layoutSurface();
+}
+
+void PluginView::setParentVisible(bool visible) {
+
+ if (isParentVisible() == visible)
+ return;
+
+ Widget::setParentVisible(visible);
+
+ if (platformPluginWidget())
+ platformPluginWidget()->layoutSurface();
+
+}
+
+void PluginView::paint(GraphicsContext* context, const IntRect& rect)
+{
+ if (!m_isStarted) {
+ // Draw the "missing plugin" image
+ paintMissingPluginIcon(context, rect);
+ return;
+ }
+
+ IntRect frame = frameRect();
+ if (!frame.width() || !frame.height()) {
+ PLUGIN_LOG("--%p FrameRect Dimensions are (0,0).\n", instance());
+ return;
+ }
+
+ if (m_window->isSurfaceDrawingModel()) {
+ /* the document position of the frame (e.g. iFrame) containing the
+ surface may have changed, which requires us to to update the global
+ coordinates of the surface. This is necessary because the plugin has
+ not moved within its parent frame and therefore will not get any
+ notification of its global position change.
+ */
+ updatePluginWidget();
+ m_window->setSurfaceClip(context->platformContext()->mCanvas->getTotalClip().getBounds());
+ } else {
+ m_window->inval(rect, false);
+ context->save();
+ context->translate(frame.x(), frame.y());
+ m_window->draw(android_gc2canvas(context));
+ context->restore();
+ }
+
+
+}
+
+void PluginView::updatePluginWidget()
+{
+ FrameView* frameView = static_cast<FrameView*>(parent());
+ PLUGIN_LOG("--%p UpdatePluginWidget frame=[%p] \n", instance(), frameView);
+ if (frameView) {
+ m_windowRect = frameView->contentsToWindow(frameRect());
+
+ IntRect oldPageRect = m_pageRect;
+
+ // only the top ScrollView can have the offset
+ m_pageRect = m_windowRect;
+ ScrollView* top = parent();
+ while (top->parent())
+ top = top->parent();
+ m_pageRect.move(top->scrollOffset());
+
+ if (m_pageRect != oldPageRect)
+ setNPWindowIfNeeded();
+ }
+}
+
+void PluginView::halt() {
+ notImplemented();
+}
+
+void PluginView::restart() {
+ notImplemented();
+}
+
+} // namespace WebCore