2008-11-12 Tor Arne Vestbø <tavestbo@trolltech.com>
authorvestbo@webkit.org <vestbo@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 13 Nov 2008 15:20:43 +0000 (15:20 +0000)
committervestbo@webkit.org <vestbo@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 13 Nov 2008 15:20:43 +0000 (15:20 +0000)
        Reviewed by Simon Hausmann.

        Inital implementation of PluginPackage and PluginView for Mac NPAPI support in WebCore

        Currently only used by QtWebKit. See also:

        https://bugs.webkit.org/show_bug.cgi?id=21427

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@38371 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/WebCore.pro
WebCore/platform/qt/TemporaryLinkStubs.cpp
WebCore/plugins/PluginView.cpp
WebCore/plugins/PluginView.h
WebCore/plugins/mac/PluginPackageMac.cpp [new file with mode: 0644]
WebCore/plugins/mac/PluginViewMac.cpp [new file with mode: 0644]

index 58b7397..63eff55 100644 (file)
@@ -1,3 +1,63 @@
+2008-11-12  Tor Arne Vestbø  <tavestbo@trolltech.com>
+
+        Reviewed by Simon Hausmann.
+
+        Inital implementation of PluginPackage and PluginView for Mac NPAPI support in WebCore
+
+        Currently only used by QtWebKit. See also:
+
+        https://bugs.webkit.org/show_bug.cgi?id=21427
+
+        * WebCore.pro:
+        * platform/qt/TemporaryLinkStubs.cpp:
+        (PluginView::userAgentStatic):
+        (PluginView::getValueStatic):
+        * plugins/PluginView.cpp:
+        (WebCore::PluginView::handleEvent):
+        (WebCore::PluginView::setValue):
+        (WebCore::PluginView::PluginView):
+        * plugins/PluginView.h:
+        (WebCore::PluginView::setPlatformPluginWidget):
+        * plugins/mac/PluginPackageMac.cpp: Added.
+        (WebCore::PluginPackage::determineQuirks):
+        (WebCore::readPListFile):
+        (WebCore::stringListFromResourceId):
+        (WebCore::PluginPackage::fetchInfo):
+        (WebCore::PluginPackage::load):
+        (WebCore::PluginPackage::hash):
+        (WebCore::PluginPackage::equal):
+        (WebCore::PluginPackage::compareFileVersion):
+        * plugins/mac/PluginViewMac.cpp: Added.
+        (WebCore::nativeWindowFor):
+        (WebCore::cgHandleFor):
+        (WebCore::topLevelOffsetFor):
+        (WebCore::PluginView::init):
+        (WebCore::PluginView::~PluginView):
+        (WebCore::PluginView::stop):
+        (WebCore::PluginView::getValueStatic):
+        (WebCore::PluginView::getValue):
+        (WebCore::PluginView::setParent):
+        (WebCore::PluginView::show):
+        (WebCore::PluginView::hide):
+        (WebCore::PluginView::setFocus):
+        (WebCore::PluginView::setParentVisible):
+        (WebCore::PluginView::setNPWindowRect):
+        (WebCore::PluginView::setNPWindowIfNeeded):
+        (WebCore::PluginView::updatePluginWidget):
+        (WebCore::PluginView::paint):
+        (WebCore::PluginView::invalidateRect):
+        (WebCore::PluginView::invalidateRegion):
+        (WebCore::PluginView::forceRedraw):
+        (WebCore::PluginView::handleMouseEvent):
+        (WebCore::PluginView::handleKeyboardEvent):
+        (WebCore::PluginView::nullEventTimerFired):
+        (WebCore::modifiersForEvent):
+        (WebCore::PluginView::globalMousePosForPlugin):
+        (WebCore::PluginView::dispatchNPEvent):
+        (WebCore::PluginView::userAgent):
+        (WebCore::PluginView::userAgentStatic):
+        (WebCore::PluginView::handlePostReadFile):
+
 2008-11-12  Alexey Proskuryakov  <ap@webkit.org>
 
         Reviewed by Darin Adler.
 2008-11-12  Alexey Proskuryakov  <ap@webkit.org>
 
         Reviewed by Darin Adler.
index 0e21505..6c65bd6 100644 (file)
@@ -72,12 +72,14 @@ win32-g++ {
 !contains(DEFINES, ENABLE_SVG_ANIMATION=.): DEFINES += ENABLE_SVG_ANIMATION=1
 !contains(DEFINES, ENABLE_SVG_AS_IMAGE=.): DEFINES += ENABLE_SVG_AS_IMAGE=1
 !contains(DEFINES, ENABLE_SVG_USE=.): DEFINES += ENABLE_SVG_USE=1
 !contains(DEFINES, ENABLE_SVG_ANIMATION=.): DEFINES += ENABLE_SVG_ANIMATION=1
 !contains(DEFINES, ENABLE_SVG_AS_IMAGE=.): DEFINES += ENABLE_SVG_AS_IMAGE=1
 !contains(DEFINES, ENABLE_SVG_USE=.): DEFINES += ENABLE_SVG_USE=1
+
+# HTML5 media support
 contains(QT_CONFIG, phonon):DEFINES += ENABLE_VIDEO=1
 else:DEFINES += ENABLE_VIDEO=0
 
 contains(QT_CONFIG, phonon):DEFINES += ENABLE_VIDEO=1
 else:DEFINES += ENABLE_VIDEO=0
 
-unix|win32-*:!mac:!embedded:!wince*:!symbian {
+# Nescape plugins support (NPAPI)
+unix|win32-*:!embedded:!wince*:!symbian {
     DEFINES += ENABLE_NETSCAPE_PLUGIN_API=1
     DEFINES += ENABLE_NETSCAPE_PLUGIN_API=1
-    unix: DEFINES += XP_UNIX
 } else {
     DEFINES += ENABLE_NETSCAPE_PLUGIN_API=0
 }
 } else {
     DEFINES += ENABLE_NETSCAPE_PLUGIN_API=0
 }
@@ -1104,6 +1106,12 @@ SOURCES += \
     win32-*: SOURCES += platform/win/SystemTimeWin.cpp
     else: SOURCES += platform/qt/SystemTimeQt.cpp
 
     win32-*: SOURCES += platform/win/SystemTimeWin.cpp
     else: SOURCES += platform/qt/SystemTimeQt.cpp
 
+    mac {
+        SOURCES += \
+            platform/text/cf/StringCF.cpp \
+            platform/text/cf/StringImplCF.cpp
+    }
+
     win32-* {
         LIBS += -lgdi32
         LIBS += -luser32
     win32-* {
         LIBS += -lgdi32
         LIBS += -luser32
@@ -1126,31 +1134,43 @@ SOURCES += \
 
 contains(DEFINES, ENABLE_NETSCAPE_PLUGIN_API=1) {
 
 
 contains(DEFINES, ENABLE_NETSCAPE_PLUGIN_API=1) {
 
-        SOURCES += plugins/npapi.cpp
+    SOURCES += plugins/npapi.cpp
 
 
-        unix:!mac {
+    unix {
+        mac {
+            SOURCES += \
+                plugins/mac/PluginPackageMac.cpp \
+                plugins/mac/PluginViewMac.cpp
+            OBJECTIVE_SOURCES += \
+                platform/text/mac/StringImplMac.mm \
+                platform/mac/WebCoreNSStringExtras.mm
+            INCLUDEPATH += platform/mac
+            # Note: XP_MACOSX is defined in npapi.h
+        } else {
             SOURCES += \
                 plugins/qt/PluginPackageQt.cpp \
                 plugins/qt/PluginViewQt.cpp
             SOURCES += \
                 plugins/qt/PluginPackageQt.cpp \
                 plugins/qt/PluginViewQt.cpp
+            DEFINES += XP_UNIX
         }
         }
+    }
 
 
-        win32-* {
-            INCLUDEPATH += $$PWD/plugins/win
-
-            SOURCES += page/win/PageWin.cpp \
-                       plugins/win/PluginDatabaseWin.cpp \
-                       plugins/win/PluginPackageWin.cpp \
-                       plugins/win/PluginMessageThrottlerWin.cpp \
-                       plugins/win/PluginViewWin.cpp
-
-            LIBS += \
-                -ladvapi32 \
-                -lgdi32 \
-                -lshell32 \
-                -lshlwapi \
-                -luser32 \
-                -lversion
-        }
+    win32-* {
+        INCLUDEPATH += $$PWD/plugins/win
+
+        SOURCES += page/win/PageWin.cpp \
+                   plugins/win/PluginDatabaseWin.cpp \
+                   plugins/win/PluginPackageWin.cpp \
+                   plugins/win/PluginMessageThrottlerWin.cpp \
+                   plugins/win/PluginViewWin.cpp
+
+        LIBS += \
+            -ladvapi32 \
+            -lgdi32 \
+            -lshell32 \
+            -lshlwapi \
+            -luser32 \
+            -lversion
+    }
 
 }
 
 
 }
 
index 6950eb7..6963dbb 100644 (file)
@@ -74,7 +74,7 @@
 
 using namespace WebCore;
 
 
 using namespace WebCore;
 
-#if !defined(Q_WS_X11) && !defined(Q_WS_WIN)
+#if (!defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC32)) || defined(Q_OS_WINCE)
 
 bool PluginPackage::fetchInfo() { notImplemented(); return false; }
 unsigned PluginPackage::hash() const { notImplemented(); return 0; }
 
 bool PluginPackage::fetchInfo() { notImplemented(); return false; }
 unsigned PluginPackage::hash() const { notImplemented(); return 0; }
@@ -83,6 +83,9 @@ int PluginPackage::compareFileVersion(const PlatformModuleVersion&) const { notI
 
 void PluginView::setNPWindowRect(const IntRect&) { notImplemented(); }
 const char* PluginView::userAgent() { notImplemented(); return 0; }
 
 void PluginView::setNPWindowRect(const IntRect&) { notImplemented(); }
 const char* PluginView::userAgent() { notImplemented(); return 0; }
+#if ENABLE(NETSCAPE_PLUGIN_API)
+const char* PluginView::userAgentStatic() { notImplemented(); return 0; }
+#endif
 void PluginView::invalidateRect(NPRect*) { notImplemented(); }
 void PluginView::invalidateRect(const IntRect&) { notImplemented(); }
 void PluginView::invalidateRegion(NPRegion) { notImplemented(); }
 void PluginView::invalidateRect(NPRect*) { notImplemented(); }
 void PluginView::invalidateRect(const IntRect&) { notImplemented(); }
 void PluginView::invalidateRegion(NPRegion) { notImplemented(); }
@@ -98,6 +101,9 @@ void PluginView::handleKeyboardEvent(KeyboardEvent*) { notImplemented(); }
 void PluginView::handleMouseEvent(MouseEvent*) { notImplemented(); }
 NPError PluginView::handlePostReadFile(Vector<char>&, uint32, const char*) { notImplemented(); return NPERR_GENERIC_ERROR; }
 NPError PluginView::getValue(NPNVariable, void*) { notImplemented(); return NPERR_GENERIC_ERROR; }
 void PluginView::handleMouseEvent(MouseEvent*) { notImplemented(); }
 NPError PluginView::handlePostReadFile(Vector<char>&, uint32, const char*) { notImplemented(); return NPERR_GENERIC_ERROR; }
 NPError PluginView::getValue(NPNVariable, void*) { notImplemented(); return NPERR_GENERIC_ERROR; }
+#if ENABLE(NETSCAPE_PLUGIN_API)
+NPError PluginView::getValueStatic(NPNVariable, void*) { return NPERR_GENERIC_ERROR; }
+#endif
 PluginView::~PluginView() {}
 #endif
 
 PluginView::~PluginView() {}
 #endif
 
index 55bd3ae..0271d13 100644 (file)
@@ -419,6 +419,12 @@ NPError PluginView::setValue(NPPVariable variable, void* value)
     case NPPVpluginTransparentBool:
         m_isTransparent = value;
         return NPERR_NO_ERROR;
     case NPPVpluginTransparentBool:
         m_isTransparent = value;
         return NPERR_NO_ERROR;
+#if defined(XP_MACOSX)
+    case NPPVpluginDrawingModel:
+        return NPERR_NO_ERROR;
+    case NPPVpluginEventModel:
+        return NPERR_NO_ERROR;
+#endif
     default:
         notImplemented();
         return NPERR_GENERIC_ERROR;
     default:
         notImplemented();
         return NPERR_GENERIC_ERROR;
@@ -540,7 +546,11 @@ PluginView::PluginView(Frame* parentFrame, const IntSize& size, PluginPackage* p
     , m_popPopupsStateTimer(this, &PluginView::popPopupsStateTimerFired)
     , m_paramNames(0)
     , m_paramValues(0)
     , m_popPopupsStateTimer(this, &PluginView::popPopupsStateTimerFired)
     , m_paramNames(0)
     , m_paramValues(0)
+#if defined(XP_MACOSX)
+    , m_isWindowed(false)
+#else
     , m_isWindowed(true)
     , m_isWindowed(true)
+#endif
     , m_isTransparent(false)
     , m_haveInitialized(false)
 #if PLATFORM(GTK) || defined(Q_WS_X11)
     , m_isTransparent(false)
     , m_haveInitialized(false)
 #if PLATFORM(GTK) || defined(Q_WS_X11)
@@ -554,7 +564,7 @@ PluginView::PluginView(Frame* parentFrame, const IntSize& size, PluginPackage* p
     , m_lastMessage(0)
     , m_isCallingPluginWndProc(false)
 #endif
     , m_lastMessage(0)
     , m_isCallingPluginWndProc(false)
 #endif
-#if PLATFORM(WIN_OS) && PLATFORM(QT)
+#if (PLATFORM(QT) && PLATFORM(WIN_OS)) || defined(XP_MACOSX)
     , m_window(0)
 #endif
     , m_loadManually(loadManually)
     , m_window(0)
 #endif
     , m_loadManually(loadManually)
index 3404abb..c22cdd0 100644 (file)
@@ -263,11 +263,13 @@ namespace WebCore {
         bool m_isCallingPluginWndProc;
 #endif
 
         bool m_isCallingPluginWndProc;
 #endif
 
-#if PLATFORM(WIN_OS) && PLATFORM(QT)
-        // Only under Qt on Windows, the plugin widget (HWND) does not match the native widget (QWidget).
-        PlatformPluginWidget m_window; // for windowed plug-ins
+#if (PLATFORM(QT) && PLATFORM(WIN_OS)) || defined(XP_MACOSX)
+        // On Mac OSX and Qt/Windows the plugin does not have its own native widget,
+        // but is using the containing window as its reference for positioning/painting.
+        PlatformPluginWidget m_window;
 public:
         PlatformPluginWidget platformPluginWidget() const { return m_window; }
 public:
         PlatformPluginWidget platformPluginWidget() const { return m_window; }
+        void setPlatformPluginWidget(PlatformPluginWidget widget) { m_window = widget; }
 #else
 public:
         PlatformPluginWidget platformPluginWidget() const { return platformWidget(); }
 #else
 public:
         PlatformPluginWidget platformPluginWidget() const { return platformWidget(); }
@@ -275,6 +277,15 @@ public:
 
 private:
 
 
 private:
 
+#if defined(XP_MACOSX)
+        NP_CGContext m_npCgContext;
+        OwnPtr<Timer<PluginView> > m_nullEventTimer;
+
+        void setNPWindowIfNeeded();
+        void nullEventTimerFired(Timer<PluginView>*);
+        Point globalMousePosForPlugin() const;
+#endif
+
         mutable IntRect m_clipRect; // The clip rect to apply to a windowed plug-in
         mutable IntRect m_windowRect; // Our window rect.
 
         mutable IntRect m_clipRect; // The clip rect to apply to a windowed plug-in
         mutable IntRect m_windowRect; // Our window rect.
 
diff --git a/WebCore/plugins/mac/PluginPackageMac.cpp b/WebCore/plugins/mac/PluginPackageMac.cpp
new file mode 100644 (file)
index 0000000..b316306
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
+ * Copyright (C) 2008 Collabora Ltd. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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.
+ */
+
+#ifndef __LP64__
+
+#include "config.h"
+#include "PluginPackage.h"
+
+#include <wtf/RetainPtr.h>
+#include "CString.h"
+#include "MIMETypeRegistry.h"
+#include "NotImplemented.h"
+#include "npruntime_impl.h"
+#include "PluginDatabase.h"
+#include "PluginDebug.h"
+#include "WebCoreNSStringExtras.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#define PluginNameOrDescriptionStringNumber     126
+#define MIMEDescriptionStringNumber             127
+#define MIMEListStringStringNumber              128
+
+namespace WebCore {
+
+void PluginPackage::determineQuirks(const String& mimeType)
+{
+    if (MIMETypeRegistry::isJavaAppletMIMEType(mimeType)) {
+        // Because a single process cannot create multiple VMs, and we cannot reliably unload a
+        // Java VM, we cannot unload the Java plugin, or we'll lose reference to our only VM
+        m_quirks.add(PluginQuirkDontUnloadPlugin);
+
+        // Setting the window region to an empty region causes bad scrolling repaint problems
+        // with the Java plug-in.
+        m_quirks.add(PluginQuirkDontClipToZeroRectWhenScrolling);
+    }
+
+    if (mimeType == "application/x-shockwave-flash") {
+        // The flash plugin only requests windowless plugins if we return a mozilla user agent
+        m_quirks.add(PluginQuirkWantsMozillaUserAgent);
+        m_quirks.add(PluginQuirkThrottleInvalidate);
+        m_quirks.add(PluginQuirkThrottleWMUserPlusOneMessages);
+        m_quirks.add(PluginQuirkFlashURLNotifyBug);
+    }
+
+}
+
+typedef void (*BP_CreatePluginMIMETypesPreferencesFuncPtr)(void);
+
+static WTF::RetainPtr<CFDictionaryRef> readPListFile(CFStringRef fileName, bool createFile, CFBundleRef bundle)
+{
+    if (createFile) {
+        BP_CreatePluginMIMETypesPreferencesFuncPtr funcPtr =
+            (BP_CreatePluginMIMETypesPreferencesFuncPtr)CFBundleGetFunctionPointerForName(bundle, CFSTR("BP_CreatePluginMIMETypesPreferences"));
+        if (funcPtr)
+            funcPtr();
+    }
+
+    WTF::RetainPtr<CFDictionaryRef> map;
+    WTF::RetainPtr<CFURLRef> url =
+        CFURLCreateWithFileSystemPath(kCFAllocatorDefault, fileName, kCFURLPOSIXPathStyle, false);
+
+    CFDataRef resource = 0;
+    SInt32 code;
+    if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, url.get(), &resource, 0, 0, &code))
+        return map;
+
+    WTF::RetainPtr<CFPropertyListRef> propertyList =
+            CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resource, kCFPropertyListImmutable, 0);
+
+    CFRelease(resource);
+
+    if (!propertyList)
+        return map;
+
+    if (CFGetTypeID(propertyList.get()) != CFDictionaryGetTypeID())
+        return map;
+
+    map = static_cast<CFDictionaryRef>(static_cast<CFPropertyListRef>(propertyList.get()));
+    return map;
+}
+
+static Vector<String> stringListFromResourceId(SInt16 id)
+{
+    Vector<String> list;
+
+    Handle handle = Get1Resource('STR#', id);
+    if (!handle)
+        return list;
+
+    CFStringEncoding encoding = stringEncodingForResource(handle);
+
+    unsigned char* p = (unsigned char*)*handle;
+    if (!p)
+        return list;
+
+    SInt16 count = *(SInt16*)p;
+    p += sizeof(SInt16);
+
+    for (SInt16 i = 0; i < count; ++i) {
+        unsigned char length = *p;
+        WTF::RetainPtr<CFStringRef> str = CFStringCreateWithPascalString(0, p, encoding);
+        list.append(str.get());
+        p += 1 + length;
+    }
+
+    return list;
+}
+
+bool PluginPackage::fetchInfo()
+{
+    if (!load())
+        return false;
+
+    WTF::RetainPtr<CFDictionaryRef> mimeDict;
+
+    WTF::RetainPtr<CFTypeRef> mimeTypesFileName = CFBundleGetValueForInfoDictionaryKey(m_module, CFSTR("WebPluginMIMETypesFilename"));
+    if (mimeTypesFileName && CFGetTypeID(mimeTypesFileName.get()) == CFStringGetTypeID()) {
+
+        WTF::RetainPtr<CFStringRef> fileName = (CFStringRef)mimeTypesFileName.get();
+        WTF::RetainPtr<CFStringRef> homeDir = homeDirectoryPath().createCFString();
+        WTF::RetainPtr<CFStringRef> path = CFStringCreateWithFormat(0, 0, CFSTR("%@/Library/Preferences/%@"), homeDir.get(), fileName.get());
+
+        WTF::RetainPtr<CFDictionaryRef> plist = readPListFile(path.get(), /*createFile*/ false, m_module);
+        if (plist) {
+            // If the plist isn't localized, have the plug-in recreate it in the preferred language.
+            WTF::RetainPtr<CFStringRef> localizationName =
+                (CFStringRef)CFDictionaryGetValue(plist.get(), CFSTR("WebPluginLocalizationName"));
+            CFLocaleRef locale = CFLocaleCopyCurrent();
+            if (localizationName != CFLocaleGetIdentifier(locale))
+                plist = readPListFile(path.get(), /*createFile*/ true, m_module);
+
+            CFRelease(locale);
+        } else {
+            // Plist doesn't exist, ask the plug-in to create it.
+            plist = readPListFile(path.get(), /*createFile*/ true, m_module);
+        }
+
+        mimeDict = (CFDictionaryRef)CFDictionaryGetValue(plist.get(), CFSTR("WebPluginMIMETypes"));
+    }
+
+    if (!mimeDict)
+        mimeDict = (CFDictionaryRef)CFBundleGetValueForInfoDictionaryKey(m_module, CFSTR("WebPluginMIMETypes"));
+
+    if (mimeDict) {
+        CFIndex propCount = CFDictionaryGetCount(mimeDict.get());
+        Vector<const void*, 128> keys(propCount);
+        Vector<const void*, 128> values(propCount);
+        CFDictionaryGetKeysAndValues(mimeDict.get(), keys.data(), values.data());
+        for (int i = 0; i < propCount; ++i) {
+            String mimeType = (CFStringRef)keys[i];
+            mimeType = mimeType.lower();
+
+            WTF::RetainPtr<CFDictionaryRef> extensionsDict = (CFDictionaryRef)values[i];
+
+            WTF:RetainPtr<CFNumberRef> enabled = (CFNumberRef)CFDictionaryGetValue(extensionsDict.get(), CFSTR("WebPluginTypeEnabled"));
+            if (enabled) {
+                int enabledValue = 0;
+                if (CFNumberGetValue(enabled.get(), kCFNumberIntType, &enabledValue) && enabledValue == 0)
+                    continue;
+            }
+
+            Vector<String> mimeExtensions;
+            WTF::RetainPtr<CFArrayRef> extensions = (CFArrayRef)CFDictionaryGetValue(extensionsDict.get(), CFSTR("WebPluginExtensions"));
+            if (extensions) {
+                CFIndex extensionCount = CFArrayGetCount(extensions.get());
+                for (CFIndex i = 0; i < extensionCount; ++i) {
+                    String extension =(CFStringRef)CFArrayGetValueAtIndex(extensions.get(), i);
+                    extension = extension.lower();
+                    mimeExtensions.append(extension);
+                }
+            }
+            m_mimeToExtensions.set(mimeType, mimeExtensions);
+
+            String description = (CFStringRef)CFDictionaryGetValue(extensionsDict.get(), CFSTR("WebPluginTypeDescription"));
+            m_mimeToDescriptions.set(mimeType, description);
+        }
+
+        m_name = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(m_module, CFSTR("WebPluginName"));
+        m_description = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(m_module, CFSTR("WebPluginDescription"));
+
+    } else {
+        int resFile = CFBundleOpenBundleResourceMap(m_module);
+
+        UseResFile(resFile);
+
+        Vector<String> mimes = stringListFromResourceId(MIMEListStringStringNumber);
+
+        if (mimes.size() % 2 != 0)
+            return false;
+
+        Vector<String> descriptions = stringListFromResourceId(MIMEDescriptionStringNumber);
+        if (descriptions.size() != mimes.size() / 2)
+            return false;
+
+        for (size_t i = 0;  i < mimes.size(); i += 2) {
+            String mime = mimes[i].lower();
+            Vector<String> extensions;
+            mimes[i + 1].lower().split(UChar(','), extensions);
+
+            m_mimeToExtensions.set(mime, extensions);
+
+            m_mimeToDescriptions.set(mime, descriptions[i / 2]);
+        }
+
+        Vector<String> names = stringListFromResourceId(PluginNameOrDescriptionStringNumber);
+        if (names.size() == 2) {
+            m_description = names[0];
+            m_name = names[1];
+        }
+
+        CFBundleCloseBundleResourceMap(m_module, resFile);
+    }
+
+    return true;
+}
+
+bool PluginPackage::load()
+{
+    if (m_isLoaded) {
+        m_loadCount++;
+        return true;
+    }
+
+    WTF::RetainPtr<CFStringRef> path(AdoptCF, m_path.createCFString());
+    WTF::RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path.get(),
+                                                                        kCFURLPOSIXPathStyle, false));
+    m_module = CFBundleCreate(NULL, url.get());
+    if (!m_module || !CFBundleLoadExecutable(m_module)) {
+        LOG(Plugin, "%s not loaded", m_path.utf8().data());
+        return false;
+    }
+
+    m_isLoaded = true;
+
+    NP_GetEntryPointsFuncPtr NP_GetEntryPoints = 0;
+    NP_InitializeFuncPtr NP_Initialize;
+    NPError npErr;
+
+    NP_Initialize = (NP_InitializeFuncPtr)CFBundleGetFunctionPointerForName(m_module, CFSTR("NP_Initialize"));
+    NP_GetEntryPoints = (NP_GetEntryPointsFuncPtr)CFBundleGetFunctionPointerForName(m_module, CFSTR("NP_GetEntryPoints"));
+    m_NPP_Shutdown = (NPP_ShutdownProcPtr)CFBundleGetFunctionPointerForName(m_module, CFSTR("NP_Shutdown"));
+
+    if (!NP_Initialize || !NP_GetEntryPoints || !m_NPP_Shutdown)
+        goto abort;
+
+    memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs));
+    m_pluginFuncs.size = sizeof(m_pluginFuncs);
+
+    npErr = NP_GetEntryPoints(&m_pluginFuncs);
+    LOG_NPERROR(npErr);
+    if (npErr != NPERR_NO_ERROR)
+        goto abort;
+
+    m_browserFuncs.size = sizeof (m_browserFuncs);
+    m_browserFuncs.version = NP_VERSION_MINOR;
+    m_browserFuncs.geturl = NPN_GetURL;
+    m_browserFuncs.posturl = NPN_PostURL;
+    m_browserFuncs.requestread = NPN_RequestRead;
+    m_browserFuncs.newstream = NPN_NewStream;
+    m_browserFuncs.write = NPN_Write;
+    m_browserFuncs.destroystream = NPN_DestroyStream;
+    m_browserFuncs.status = NPN_Status;
+    m_browserFuncs.uagent = NPN_UserAgent;
+    m_browserFuncs.memalloc = NPN_MemAlloc;
+    m_browserFuncs.memfree = NPN_MemFree;
+    m_browserFuncs.memflush = NPN_MemFlush;
+    m_browserFuncs.reloadplugins = NPN_ReloadPlugins;
+    m_browserFuncs.geturlnotify = NPN_GetURLNotify;
+    m_browserFuncs.posturlnotify = NPN_PostURLNotify;
+    m_browserFuncs.getvalue = NPN_GetValue;
+    m_browserFuncs.setvalue = NPN_SetValue;
+    m_browserFuncs.invalidaterect = NPN_InvalidateRect;
+    m_browserFuncs.invalidateregion = NPN_InvalidateRegion;
+    m_browserFuncs.forceredraw = NPN_ForceRedraw;
+    m_browserFuncs.getJavaEnv = NPN_GetJavaEnv;
+    m_browserFuncs.getJavaPeer = NPN_GetJavaPeer;
+    m_browserFuncs.pushpopupsenabledstate = NPN_PushPopupsEnabledState;
+    m_browserFuncs.poppopupsenabledstate = NPN_PopPopupsEnabledState;
+
+    m_browserFuncs.releasevariantvalue = _NPN_ReleaseVariantValue;
+    m_browserFuncs.getstringidentifier = _NPN_GetStringIdentifier;
+    m_browserFuncs.getstringidentifiers = _NPN_GetStringIdentifiers;
+    m_browserFuncs.getintidentifier = _NPN_GetIntIdentifier;
+    m_browserFuncs.identifierisstring = _NPN_IdentifierIsString;
+    m_browserFuncs.utf8fromidentifier = _NPN_UTF8FromIdentifier;
+    m_browserFuncs.createobject = _NPN_CreateObject;
+    m_browserFuncs.retainobject = _NPN_RetainObject;
+    m_browserFuncs.releaseobject = _NPN_ReleaseObject;
+    m_browserFuncs.invoke = _NPN_Invoke;
+    m_browserFuncs.invokeDefault = _NPN_InvokeDefault;
+    m_browserFuncs.evaluate = _NPN_Evaluate;
+    m_browserFuncs.getproperty = _NPN_GetProperty;
+    m_browserFuncs.setproperty = _NPN_SetProperty;
+    m_browserFuncs.removeproperty = _NPN_RemoveProperty;
+    m_browserFuncs.hasproperty = _NPN_HasMethod;
+    m_browserFuncs.hasmethod = _NPN_HasProperty;
+    m_browserFuncs.setexception = _NPN_SetException;
+    m_browserFuncs.enumerate = _NPN_Enumerate;
+
+    npErr = NP_Initialize(&m_browserFuncs);
+    if (npErr != NPERR_NO_ERROR)
+        goto abort;
+
+    m_loadCount++;
+    return true;
+
+abort:
+    unloadWithoutShutdown();
+    return false;
+}
+
+unsigned PluginPackage::hash() const
+{
+    unsigned hashCodes[2] = {
+        m_path.impl()->hash(),
+        m_lastModified
+    };
+
+    return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), 2 * sizeof(unsigned) / sizeof(UChar));
+}
+
+bool PluginPackage::equal(const PluginPackage& a, const PluginPackage& b)
+{
+    return a.m_description == b.m_description;
+}
+
+int PluginPackage::compareFileVersion(const PlatformModuleVersion& compareVersion) const
+{
+    // return -1, 0, or 1 if plug-in version is less than, equal to, or greater than
+    // the passed version
+    if (m_moduleVersion != compareVersion)
+        return m_moduleVersion > compareVersion ? 1 : -1;
+    return 0;
+}
+
+} // namespace WebCore
+
+#endif // !__LP64__
diff --git a/WebCore/plugins/mac/PluginViewMac.cpp b/WebCore/plugins/mac/PluginViewMac.cpp
new file mode 100644 (file)
index 0000000..6dd9996
--- /dev/null
@@ -0,0 +1,691 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
+ * Copyright (C) 2008 Collabora Ltd. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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.
+ */
+
+#ifndef __LP64__
+
+#include "config.h"
+#include "PluginView.h"
+
+#include <runtime/JSLock.h>
+#include <runtime/JSValue.h>
+#include "wtf/RetainPtr.h"
+
+#include "Document.h"
+#include "DocumentLoader.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 "JSDOMBinding.h"
+#include "KeyboardEvent.h"
+#include "MouseEvent.h"
+#include "NotImplemented.h"
+#include "npruntime_impl.h"
+#include "Page.h"
+#include "PlatformMouseEvent.h"
+#include "PlatformKeyboardEvent.h"
+#include "PluginDebug.h"
+#include "PluginPackage.h"
+#include "PluginMainThreadScheduler.h"
+#include "RenderLayer.h"
+#include "runtime.h"
+#include "runtime_root.h"
+#include "ScriptController.h"
+#include "Settings.h"
+
+using JSC::ExecState;
+using JSC::Interpreter;
+using JSC::JSLock;
+using JSC::JSObject;
+using JSC::JSValue;
+using JSC::UString;
+
+#if PLATFORM(QT)
+#include <QWidget>
+#include <QKeyEvent>
+QT_BEGIN_NAMESPACE
+extern Q_GUI_EXPORT OSWindowRef qt_mac_window_for(const QWidget *w);
+QT_END_NAMESPACE
+#endif
+
+using std::min;
+
+using namespace WTF;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+static int modifiersForEvent(UIEventWithKeyState *event);
+
+static inline WindowRef nativeWindowFor(PlatformWidget widget)
+{
+#if PLATFORM(QT)
+    if (widget)
+        return static_cast<WindowRef>(qt_mac_window_for(widget));
+#endif
+    return 0;
+}
+
+static inline CGContextRef cgHandleFor(PlatformWidget widget)
+{
+#if PLATFORM(QT)
+    if (widget)
+        return (CGContextRef)widget->macCGHandle();
+#endif
+    return 0;
+}
+
+static inline IntPoint topLevelOffsetFor(PlatformWidget widget)
+{
+#if PLATFORM(QT)
+    if (widget) {
+        PlatformWidget topLevel = widget->window();
+        return widget->mapTo(topLevel, QPoint(0, 0)) + topLevel->geometry().topLeft() - topLevel->pos();
+    }
+#endif
+    return IntPoint();
+}
+
+// --------------- Lifetime management -----------------
+
+void PluginView::init()
+{
+    if (m_haveInitialized)
+        return;
+    m_haveInitialized = true;
+
+    if (!m_plugin) {
+        ASSERT(m_status == PluginStatusCanNotFindPlugin);
+        return;
+    }
+
+    if (!m_plugin->load()) {
+        m_plugin = 0;
+        m_status = PluginStatusCanNotLoadPlugin;
+        return;
+    }
+
+    if (!start()) {
+        m_status = PluginStatusCanNotLoadPlugin;
+        return;
+    }
+
+    setPlatformPluginWidget(m_parentFrame->view()->hostWindow()->platformWindow());
+
+    m_npCgContext.window = 0;
+    m_npCgContext.context = 0;
+    m_npWindow.window = (void*)&m_npCgContext;
+    m_npWindow.type = NPWindowTypeWindow;
+    m_npWindow.x = 0;
+    m_npWindow.y = 0;
+    m_npWindow.width = 0;
+    m_npWindow.height = 0;
+    m_npWindow.clipRect.left = 0;
+    m_npWindow.clipRect.top = 0;
+    m_npWindow.clipRect.right = 0;
+    m_npWindow.clipRect.bottom = 0;
+
+    setIsNPAPIPlugin(true);
+
+    show();
+
+    m_status = PluginStatusLoadedSuccessfully;
+
+    // TODO: Implement null timer throttling depending on plugin activation
+    m_nullEventTimer.set(new Timer<PluginView>(this, &PluginView::nullEventTimerFired));
+    m_nullEventTimer->startRepeating(0.02);
+}
+
+PluginView::~PluginView()
+{
+    stop();
+
+    deleteAllValues(m_requests);
+
+    freeStringArray(m_paramNames, m_paramCount);
+    freeStringArray(m_paramValues, m_paramCount);
+
+    m_parentFrame->script()->cleanupScriptObjectsForPlugin(this);
+
+    if (m_plugin && !(m_plugin->quirks().contains(PluginQuirkDontUnloadPlugin)))
+        m_plugin->unload();
+
+    m_window = 0;
+}
+
+void PluginView::stop()
+{
+    if (!m_isStarted)
+        return;
+
+    HashSet<RefPtr<PluginStream> > streams = m_streams;
+    HashSet<RefPtr<PluginStream> >::iterator end = streams.end();
+    for (HashSet<RefPtr<PluginStream> >::iterator it = streams.begin(); it != end; ++it) {
+        (*it)->stop();
+        disconnectStream((*it).get());
+    }
+
+    ASSERT(m_streams.isEmpty());
+
+    m_isStarted = false;
+
+    JSC::JSLock::DropAllLocks dropAllLocks(false);
+
+    PluginMainThreadScheduler::scheduler().unregisterPlugin(m_instance);
+
+    // Destroy the plugin
+    PluginView::setCurrentPluginView(this);
+    setCallingPlugin(true);
+    m_plugin->pluginFuncs()->destroy(m_instance, 0);
+    setCallingPlugin(false);
+    PluginView::setCurrentPluginView(0);
+
+    m_instance->pdata = 0;
+}
+
+NPError PluginView::getValueStatic(NPNVariable variable, void* value)
+{
+    LOG(Plugin, "PluginView::getValueStatic(%d)", variable);
+
+    switch (variable) {
+    case NPNVToolkit:
+        *((uint32 *)value) = 0;
+        return NPERR_NO_ERROR;
+
+    case NPNVjavascriptEnabledBool:
+        *((uint32 *)value) = true;
+        return NPERR_NO_ERROR;
+
+    default:
+        return NPERR_GENERIC_ERROR;
+    }
+}
+
+NPError PluginView::getValue(NPNVariable variable, void* value)
+{
+    LOG(Plugin, "PluginView::getValue(%d)", variable);
+
+    switch (variable) {
+    case NPNVWindowNPObject: {
+        if (m_isJavaScriptPaused)
+            return NPERR_GENERIC_ERROR;
+
+        NPObject* windowScriptObject = m_parentFrame->script()->windowScriptNPObject();
+
+        // Return value is expected to be retained, as described in
+        // <http://www.mozilla.org/projects/plugin/npruntime.html>
+        if (windowScriptObject)
+            _NPN_RetainObject(windowScriptObject);
+
+        void** v = (void**)value;
+        *v = windowScriptObject;
+
+        return NPERR_NO_ERROR;
+    }
+
+    case NPNVPluginElementNPObject: {
+        if (m_isJavaScriptPaused)
+            return NPERR_GENERIC_ERROR;
+
+        NPObject* pluginScriptObject = 0;
+
+        if (m_element->hasTagName(appletTag) || m_element->hasTagName(embedTag) || m_element->hasTagName(objectTag))
+            pluginScriptObject = static_cast<HTMLPlugInElement*>(m_element)->getNPObject();
+
+        // Return value is expected to be retained, as described in
+        // <http://www.mozilla.org/projects/plugin/npruntime.html>
+        if (pluginScriptObject)
+            _NPN_RetainObject(pluginScriptObject);
+
+        void** v = (void**)value;
+        *v = pluginScriptObject;
+
+        return NPERR_NO_ERROR;
+    }
+
+    case NPNVsupportsCoreGraphicsBool:
+        *((uint32 *)value) = true;
+        return NPERR_NO_ERROR;
+
+    default:
+        return getValueStatic(variable, value);
+    }
+
+}
+void PluginView::setParent(ScrollView* parent)
+{
+    Widget::setParent(parent);
+
+    if (parent)
+        init();
+}
+
+// -------------- Geometry and painting ----------------
+
+void PluginView::show()
+{
+    LOG(Plugin, "PluginView::show()");
+
+    setSelfVisible(true);
+
+    if (isParentVisible() && platformPluginWidget())
+        platformPluginWidget()->setVisible(true);
+
+    Widget::show();
+}
+
+void PluginView::hide()
+{
+    LOG(Plugin, "PluginView::hide()");
+
+    setSelfVisible(false);
+
+    if (isParentVisible() && platformPluginWidget())
+        platformPluginWidget()->setVisible(false);
+
+    Widget::hide();
+}
+
+void PluginView::setFocus()
+{
+    LOG(Plugin, "PluginView::setFocus()");
+
+    if (platformPluginWidget())
+       platformPluginWidget()->setFocus(Qt::OtherFocusReason);
+   else
+       Widget::setFocus();
+
+    // TODO: Also handle and pass on blur events (focus lost)
+
+    EventRecord record;
+    record.what = getFocusEvent;
+    record.message = 0;
+    record.when = TickCount();
+    record.where = globalMousePosForPlugin();
+    record.modifiers = GetCurrentKeyModifiers();
+
+    if (!dispatchNPEvent(record))
+        LOG(Events, "PluginView::setFocus(): Get-focus event not accepted");
+}
+
+void PluginView::setParentVisible(bool visible)
+{
+    if (isParentVisible() == visible)
+        return;
+
+    Widget::setParentVisible(visible);
+
+    if (isSelfVisible() && platformPluginWidget())
+        platformPluginWidget()->setVisible(visible);
+}
+
+void PluginView::setNPWindowRect(const IntRect&)
+{
+    setNPWindowIfNeeded();
+}
+
+void PluginView::setNPWindowIfNeeded()
+{
+    if (!m_isStarted || !parent() || !m_plugin->pluginFuncs()->setwindow)
+        return;
+
+    CGContextRef newContextRef = cgHandleFor(platformPluginWidget());
+    if (!newContextRef)
+        return;
+
+    WindowRef newWindowRef = nativeWindowFor(platformPluginWidget());
+    if (!newWindowRef)
+        return;
+
+    ASSERT(parent()->isFrameView());
+    FrameView* frameView = static_cast<FrameView*>(parent());
+    IntRect newGeometry = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size());
+
+    // TODO: also compare clip rects
+    if (newGeometry == m_windowRect
+        && newWindowRef == m_npCgContext.window
+        && newContextRef == m_npCgContext.context)
+    return;
+
+    m_npWindow.window = (void*)&m_npCgContext;
+    m_npCgContext.window = newWindowRef;
+    m_npCgContext.context = newContextRef;
+
+    m_windowRect = newGeometry;
+    m_npWindow.x = m_windowRect.x();
+    m_npWindow.y = m_windowRect.y();
+    m_npWindow.width = m_windowRect.width();
+    m_npWindow.height = m_windowRect.height();
+
+    // TODO: (also clip against scrollbars, etc.)
+    m_npWindow.clipRect.left = 0;
+    m_npWindow.clipRect.top = 0;
+    m_npWindow.clipRect.right = m_windowRect.width();
+    m_npWindow.clipRect.bottom = m_windowRect.height();
+
+    PluginView::setCurrentPluginView(this);
+    JSC::JSLock::DropAllLocks dropAllLocks(false);
+    setCallingPlugin(true);
+    m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow);
+    setCallingPlugin(false);
+    PluginView::setCurrentPluginView(0);
+}
+
+void PluginView::updatePluginWidget() const
+{
+    // Nothing to do here. We update the plugin widget
+    // in paint(), if the NPWindow struct has changed.
+}
+
+void PluginView::paint(GraphicsContext* context, const IntRect& rect)
+{
+    if (!m_isStarted)
+        return; // TODO: Draw the "missing plugin" image
+
+    if (context->paintingDisabled())
+        return;
+
+    setNPWindowIfNeeded();
+
+    EventRecord event;
+    event.what = updateEvt;
+    event.message = (long unsigned int)m_npCgContext.window;
+    event.when = TickCount();
+    event.where.h = 0;
+    event.where.v = 0;
+    event.modifiers = GetCurrentKeyModifiers();
+
+    CGContextRef cg = m_npCgContext.context;
+    CGContextSaveGState(cg);
+    IntPoint offset = frameRect().location();
+    CGContextTranslateCTM(cg, offset.x(), offset.y());
+
+    if (!dispatchNPEvent(event))
+        LOG(Events, "PluginView::paint(): Paint event not accepted");
+
+    CGContextRestoreGState(cg);
+}
+
+void PluginView::invalidateRect(const IntRect& rect)
+{
+    if (platformPluginWidget()) {
+        // TODO: optimize
+        platformPluginWidget()->update();
+        return;
+    }
+}
+
+void PluginView::invalidateRect(NPRect* rect)
+{
+    // TODO: optimize
+    invalidate();
+}
+
+void PluginView::invalidateRegion(NPRegion region)
+{
+    // TODO: optimize
+    invalidate();
+}
+
+void PluginView::forceRedraw()
+{
+    notImplemented();
+}
+
+
+// ----------------- Event handling --------------------
+
+void PluginView::handleMouseEvent(MouseEvent* event)
+{
+    EventRecord record;
+
+    if (event->type() == eventNames().mousemoveEvent) {
+        // Mouse movement is handled by null timer events
+        return;
+    } else if (event->type() == eventNames().mouseoverEvent) {
+        record.what = adjustCursorEvent;
+    } else if (event->type() == eventNames().mouseoutEvent) {
+        record.what = adjustCursorEvent;
+    } else if (event->type() == eventNames().mousedownEvent) {
+        record.what = mouseDown;
+        // The plugin needs focus to receive keyboard events
+        if (Page* page = m_parentFrame->page())
+            page->focusController()->setFocusedFrame(m_parentFrame);
+        m_parentFrame->document()->setFocusedNode(m_element);
+    } else if (event->type() == eventNames().mouseupEvent) {
+        record.what = mouseUp;
+    } else {
+        return;
+    }
+
+    record.where = globalMousePosForPlugin();
+    record.modifiers = modifiersForEvent(event);
+
+    if (!event->buttonDown())
+        record.modifiers |= btnState;
+
+    if (event->button() == 2)
+        record.modifiers |= controlKey;
+
+    if (!dispatchNPEvent(record)) {
+        if (record.what == adjustCursorEvent)
+            return; // Signals that the plugin wants a normal cursor
+
+        LOG(Events, "PluginView::handleMouseEvent(): Mouse event type %d at %d,%d not accepted",
+                record.what, record.where.h, record.where.v);
+    } else {
+        event->setDefaultHandled();
+    }
+}
+
+void PluginView::handleKeyboardEvent(KeyboardEvent* event)
+{
+    LOG(Plugin, "PluginView::handleKeyboardEvent() ----------------- ");
+
+    LOG(Plugin, "PV::hKE(): KE.keyCode: 0x%02X, KE.charCode: %d",
+            event->keyCode(), event->charCode());
+
+    EventRecord record;
+
+    if (event->type() == eventNames().keydownEvent) {
+        // This event is the result of a PlatformKeyboardEvent::KeyDown which
+        // was disambiguated into a PlatformKeyboardEvent::RawKeyDown. Since
+        // we don't have access to the text here, we return, and wait for the
+        // corresponding event based on PlatformKeyboardEvent::Char.
+        return;
+    } else if (event->type() == eventNames().keypressEvent) {
+        // Which would be this one. This event was disambiguated from the same
+        // PlatformKeyboardEvent::KeyDown, but to a PlatformKeyboardEvent::Char,
+        // which retains the text from the original event. So, we can safely pass
+        // on the event as a key-down event to the plugin.
+        record.what = keyDown;
+    } else if (event->type() == eventNames().keyupEvent) {
+        // PlatformKeyboardEvent::KeyUp events always have the text, so nothing
+        // fancy here.
+        record.what = keyUp;
+    } else {
+        return;
+    }
+
+    const PlatformKeyboardEvent* platformEvent = event->keyEvent();
+    int keyCode = platformEvent->nativeVirtualKeyCode();
+
+    const String text = platformEvent->text();
+    if (text.length() < 1) {
+        event->setDefaultHandled();
+        return;
+    }
+
+    WTF::RetainPtr<CFStringRef> cfText(WTF::AdoptCF, text.createCFString());
+
+    LOG(Plugin, "PV::hKE(): PKE.text: %s, PKE.unmodifiedText: %s, PKE.keyIdentifier: %s",
+            text.ascii().data(), platformEvent->unmodifiedText().ascii().data(),
+            platformEvent->keyIdentifier().ascii().data());
+
+    char charCodes[2] = { 0, 0 };
+    if (!CFStringGetCString(cfText.get(), charCodes, 2, CFStringGetSystemEncoding())) {
+        LOG_ERROR("Could not resolve character code using system encoding.");
+        event->setDefaultHandled();
+        return;
+    }
+
+    record.where = globalMousePosForPlugin();
+    record.modifiers = modifiersForEvent(event);
+    record.message = ((keyCode & 0xFF) << 8) | (charCodes[0] & 0xFF);
+    record.when = TickCount();
+
+    LOG(Plugin, "PV::hKE(): record.modifiers: %d", record.modifiers);
+
+    LOG(Plugin, "PV::hKE(): PKE.qtEvent()->nativeVirtualKey: 0x%02X, charCode: %d",
+               keyCode, int(uchar(charCodes[0])));
+
+    if (!dispatchNPEvent(record))
+        LOG(Events, "PluginView::handleKeyboardEvent(): Keyboard event type %d not accepted", record.what);
+    else
+        event->setDefaultHandled();
+}
+
+void PluginView::nullEventTimerFired(Timer<PluginView>*)
+{
+    EventRecord record;
+
+    record.what = nullEvent;
+    record.message = 0;
+    record.when = TickCount();
+    record.where = globalMousePosForPlugin();
+    record.modifiers = GetCurrentKeyModifiers();
+    if (!Button())
+        record.modifiers |= btnState;
+
+    if (!dispatchNPEvent(record))
+        LOG(Events, "PluginView::nullEventTimerFired(): Null event not accepted");
+}
+
+static int modifiersForEvent(UIEventWithKeyState* event)
+{
+    int modifiers = 0;
+
+    if (event->ctrlKey())
+        modifiers |= controlKey;
+
+    if (event->altKey())
+        modifiers |= optionKey;
+
+    if (event->metaKey())
+        modifiers |= cmdKey;
+
+    if (event->shiftKey())
+        modifiers |= shiftKey;
+
+     return modifiers;
+}
+
+Point PluginView::globalMousePosForPlugin() const
+{
+    Point pos;
+    GetGlobalMouse(&pos);
+
+    IntPoint offset = topLevelOffsetFor(platformPluginWidget());
+    pos.h -= offset.x();
+    pos.v -= offset.y();
+
+    pos.h = static_cast<short>(pos.h * HIGetScaleFactor());
+    pos.v = static_cast<short>(pos.v * HIGetScaleFactor());
+
+    return pos;
+}
+
+bool PluginView::dispatchNPEvent(NPEvent& event)
+{
+    PluginView::setCurrentPluginView(this);
+    JSC::JSLock::DropAllLocks dropAllLocks(false);
+    setCallingPlugin(true);
+
+    bool accepted = m_plugin->pluginFuncs()->event(m_instance, &event);
+
+    setCallingPlugin(false);
+    PluginView::setCurrentPluginView(0);
+    return accepted;
+}
+
+// ------------------- Miscellaneous  ------------------
+
+static const char* MozillaUserAgent = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0";
+
+const char* PluginView::userAgent()
+{
+    if (m_plugin->quirks().contains(PluginQuirkWantsMozillaUserAgent))
+        return MozillaUserAgent;
+
+    if (m_userAgent.isNull())
+        m_userAgent = m_parentFrame->loader()->userAgent(m_url).utf8();
+
+    return m_userAgent.data();
+}
+
+const char* PluginView::userAgentStatic()
+{
+    return MozillaUserAgent;
+}
+
+NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32 len, const char* buf)
+{
+    String filename(buf, len);
+
+    if (filename.startsWith("file:///"))
+        filename = filename.substring(8);
+
+    if (!fileExists(filename))
+        return NPERR_FILE_NOT_FOUND;
+
+    FILE* fileHandle = fopen((filename.utf8()).data(), "r");
+
+    if (fileHandle == 0)
+        return NPERR_FILE_NOT_FOUND;
+
+    int bytesRead = fread(buffer.data(), 1, 0, fileHandle);
+
+    fclose(fileHandle);
+
+    if (bytesRead <= 0)
+        return NPERR_FILE_NOT_FOUND;
+
+    return NPERR_NO_ERROR;
+}
+
+} // namespace WebCore
+
+#endif // !__LP64__