Bug 1092630: Get rid of native widgets for OS X NPAPI plugins, make things work much better under e10s. Patch by Josh Aas, Markus Stange, Steven Michaud, David Parks. r=smichaud/jst/josh (more reviews pending)
authorJosh Aas <joshmoz@gmail.com>
Thu, 11 Dec 2014 08:44:07 -0600
changeset 246808 a6db8f54f5aa47f79302fc52f11b30694020f879
parent 246807 d60b577569dd32b99c4a5e547e747b992b5d7b39
child 246809 60b4aefc4c0c0d42f3effb234df2e1e26622b75f
push id698
push userjlund@mozilla.com
push dateMon, 23 Mar 2015 22:08:11 +0000
treeherdermozilla-release@b0c0ae7b02a3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmichaud, jst, josh
bugs1092630
milestone37.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1092630: Get rid of native widgets for OS X NPAPI plugins, make things work much better under e10s. Patch by Josh Aas, Markus Stange, Steven Michaud, David Parks. r=smichaud/jst/josh (more reviews pending)
dom/base/nsFrameLoader.cpp
dom/ipc/PBrowser.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
dom/plugins/base/moz.build
dom/plugins/base/nsNPAPIPlugin.cpp
dom/plugins/base/nsNPAPIPluginInstance.cpp
dom/plugins/base/nsNPAPIPluginInstance.h
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/base/nsPluginInstanceOwner.h
dom/plugins/ipc/PluginInstanceChild.cpp
dom/plugins/ipc/PluginUtilsOSX.mm
dom/plugins/test/mochitest/cocoa_focus.html
dom/plugins/test/mochitest/test_convertpoint.xul
dom/plugins/test/testplugin/nptest.cpp
dom/plugins/test/testplugin/nptest_macosx.mm
layout/base/nsPresContext.cpp
layout/generic/moz.build
layout/generic/nsPluginFrame.cpp
layout/generic/nsPluginFrame.h
layout/generic/nsPluginUtilsOSX.h
layout/generic/nsPluginUtilsOSX.mm
layout/generic/nsSubDocumentFrame.cpp
layout/generic/nsSubDocumentFrame.h
view/nsViewManager.cpp
widget/BasicEvents.h
widget/PuppetWidget.cpp
widget/PuppetWidget.h
widget/TextEvents.h
widget/WidgetEventImpl.cpp
widget/cocoa/ComplexTextInputPanel.h
widget/cocoa/ComplexTextInputPanel.mm
widget/cocoa/TextInputHandler.h
widget/cocoa/TextInputHandler.mm
widget/cocoa/moz.build
widget/cocoa/mozView.h
widget/cocoa/nsAppShell.mm
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
widget/cocoa/nsCocoaFeatures.h
widget/cocoa/nsCocoaFeatures.mm
widget/cocoa/nsCocoaUtils.h
widget/cocoa/nsCocoaUtils.mm
widget/cocoa/nsCocoaWindow.mm
widget/cocoa/nsMenuBarX.mm
widget/nsGUIEventIPC.h
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -905,17 +905,18 @@ nsFrameLoader::ShowRemoteFrame(const nsI
       mRemoteBrowserInitialized = true;
     }
   } else {
     nsIntRect dimensions;
     NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), false);
 
     // Don't show remote iframe if we are waiting for the completion of reflow.
     if (!aFrame || !(aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
-      mRemoteBrowser->UpdateDimensions(dimensions, size);
+      nsIntPoint chromeDisp = aFrame->GetChromeDisplacement();
+      mRemoteBrowser->UpdateDimensions(dimensions, size, chromeDisp);
     }
   }
 
   return true;
 }
 
 void
 nsFrameLoader::Hide()
@@ -1937,17 +1938,18 @@ nsFrameLoader::GetWindowDimensions(nsInt
 NS_IMETHODIMP
 nsFrameLoader::UpdatePositionAndSize(nsSubDocumentFrame *aIFrame)
 {
   if (mRemoteFrame) {
     if (mRemoteBrowser) {
       nsIntSize size = aIFrame->GetSubdocumentSize();
       nsIntRect dimensions;
       NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), NS_ERROR_FAILURE);
-      mRemoteBrowser->UpdateDimensions(dimensions, size);
+      nsIntPoint chromeDisp = aIFrame->GetChromeDisplacement();
+      mRemoteBrowser->UpdateDimensions(dimensions, size, chromeDisp);
     }
     return NS_OK;
   }
   return UpdateBaseWindowPositionAndSize(aIFrame);
 }
 
 nsresult
 nsFrameLoader::UpdateBaseWindowPositionAndSize(nsSubDocumentFrame *aIFrame)
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -435,17 +435,18 @@ child:
          TextureFactoryIdentifier textureFactoryIdentifier,
          uint64_t layersId,
          nullable PRenderFrame renderFrame);
 
     LoadURL(nsCString uri);
 
     CacheFileDescriptor(nsString path, FileDescriptor fd);
 
-    UpdateDimensions(nsIntRect rect, nsIntSize size, ScreenOrientation orientation) compress;
+    UpdateDimensions(nsIntRect rect, nsIntSize size, ScreenOrientation orientation,
+                     nsIntPoint chromeDisp) compress;
 
     UpdateFrame(FrameMetrics frame);
 
     // The following methods correspond to functions on the GeckoContentController
     // interface in gfx/layers/apz/public/GeckoContentController.h. Refer to documentation
     // in that file for these functions.
     AcknowledgeScrollUpdate(ViewID aScrollId, uint32_t aScrollGeneration);
     HandleDoubleTap(CSSPoint point, ScrollableLayerGuid aGuid);
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -2005,23 +2005,25 @@ TabChild::RecvShow(const nsIntSize& aSiz
 #endif
 
     bool res = InitTabChildGlobal();
     ApplyShowInfo(aInfo);
     return res;
 }
 
 bool
-TabChild::RecvUpdateDimensions(const nsIntRect& rect, const nsIntSize& size, const ScreenOrientation& orientation)
+TabChild::RecvUpdateDimensions(const nsIntRect& rect, const nsIntSize& size,
+                               const ScreenOrientation& orientation, const nsIntPoint& chromeDisp)
 {
     if (!mRemoteFrame) {
         return true;
     }
 
     mOuterRect = rect;
+    mChromeDisp = chromeDisp;
 
     bool initialSizing = !HasValidInnerSize()
                       && (size.width != 0 && size.height != 0);
     if (initialSizing) {
       mHasValidInnerSize = true;
     }
 
     mOrientation = orientation;
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -319,17 +319,18 @@ public:
     virtual bool RecvShow(const nsIntSize& aSize,
                           const ShowInfo& aInfo,
                           const ScrollingBehavior& aScrolling,
                           const TextureFactoryIdentifier& aTextureFactoryIdentifier,
                           const uint64_t& aLayersId,
                           PRenderFrameChild* aRenderFrame) MOZ_OVERRIDE;
     virtual bool RecvUpdateDimensions(const nsIntRect& rect,
                                       const nsIntSize& size,
-                                      const ScreenOrientation& orientation) MOZ_OVERRIDE;
+                                      const ScreenOrientation& orientation,
+                                      const nsIntPoint& chromeDisp) MOZ_OVERRIDE;
     virtual bool RecvUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics) MOZ_OVERRIDE;
     virtual bool RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
                                              const uint32_t& aScrollGeneration) MOZ_OVERRIDE;
     virtual bool RecvHandleDoubleTap(const CSSPoint& aPoint,
                                      const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE;
     virtual bool RecvHandleSingleTap(const CSSPoint& aPoint,
                                      const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE;
     virtual bool RecvHandleLongTap(const CSSPoint& aPoint,
@@ -490,16 +491,18 @@ public:
 
     /**
      * Native widget remoting protocol for use with windowed plugins with e10s.
      */
     PPluginWidgetChild* AllocPPluginWidgetChild() MOZ_OVERRIDE;
     bool DeallocPPluginWidgetChild(PPluginWidgetChild* aActor) MOZ_OVERRIDE;
     already_AddRefed<nsIWidget> CreatePluginWidget(nsIWidget* aParent);
 
+    nsIntPoint GetChromeDisplacement() { return mChromeDisp; };
+
 protected:
     virtual ~TabChild();
 
     virtual PRenderFrameChild* AllocPRenderFrameChild() MOZ_OVERRIDE;
     virtual bool DeallocPRenderFrameChild(PRenderFrameChild* aFrame) MOZ_OVERRIDE;
     virtual bool RecvDestroy() MOZ_OVERRIDE;
     virtual bool RecvSetUpdateHitRegion(const bool& aEnabled) MOZ_OVERRIDE;
     virtual bool RecvSetIsDocShellActive(const bool& aIsActive) MOZ_OVERRIDE;
@@ -648,16 +651,18 @@ private:
 
     bool mTouchEndCancelled;
     bool mEndTouchIsClick;
 
     bool mIgnoreKeyPressEvent;
     nsRefPtr<ActiveElementManager> mActiveElementManager;
     bool mHasValidInnerSize;
     bool mDestroyed;
+    // Position of tab, relative to parent widget (typically the window)
+    nsIntPoint mChromeDisp;
     TabId mUniqueId;
 
     DISALLOW_EVIL_CONSTRUCTORS(TabChild);
 };
 
 }
 }
 
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -613,33 +613,34 @@ TabParent::Show(const nsIntSize& size)
       bool isPrivate = mFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::mozprivatebrowsing);
       info = ShowInfo(name, allowFullscreen, isPrivate);
     }
 
     unused << SendShow(size, info, scrolling, textureFactoryIdentifier, layersId, renderFrame);
 }
 
 void
-TabParent::UpdateDimensions(const nsIntRect& rect, const nsIntSize& size)
+TabParent::UpdateDimensions(const nsIntRect& rect, const nsIntSize& size,
+                            const nsIntPoint& aChromeDisp)
 {
   if (mIsDestroyed) {
     return;
   }
   hal::ScreenConfiguration config;
   hal::GetCurrentScreenConfiguration(&config);
   ScreenOrientation orientation = config.orientation();
 
   if (!mUpdatedDimensions || mOrientation != orientation ||
       mDimensions != size || !mRect.IsEqualEdges(rect)) {
     mUpdatedDimensions = true;
     mRect = rect;
     mDimensions = size;
     mOrientation = orientation;
 
-    unused << SendUpdateDimensions(mRect, mDimensions, mOrientation);
+    unused << SendUpdateDimensions(mRect, mDimensions, mOrientation, aChromeDisp);
   }
 }
 
 void
 TabParent::UpdateFrame(const FrameMetrics& aFrameMetrics)
 {
   if (!mIsDestroyed) {
     unused << SendUpdateFrame(aFrameMetrics);
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -220,17 +220,18 @@ public:
     AllocPColorPickerParent(const nsString& aTitle, const nsString& aInitialColor) MOZ_OVERRIDE;
     virtual bool DeallocPColorPickerParent(PColorPickerParent* aColorPicker) MOZ_OVERRIDE;
 
     void LoadURL(nsIURI* aURI);
     // XXX/cjones: it's not clear what we gain by hiding these
     // message-sending functions under a layer of indirection and
     // eating the return values
     void Show(const nsIntSize& size);
-    void UpdateDimensions(const nsIntRect& rect, const nsIntSize& size);
+    void UpdateDimensions(const nsIntRect& rect, const nsIntSize& size,
+                          const nsIntPoint& chromeDisp);
     void UpdateFrame(const layers::FrameMetrics& aFrameMetrics);
     void UIResolutionChanged();
     void AcknowledgeScrollUpdate(const ViewID& aScrollId, const uint32_t& aScrollGeneration);
     void HandleDoubleTap(const CSSPoint& aPoint,
                          int32_t aModifiers,
                          const ScrollableLayerGuid& aGuid);
     void HandleSingleTap(const CSSPoint& aPoint,
                          int32_t aModifiers,
--- a/dom/plugins/base/moz.build
+++ b/dom/plugins/base/moz.build
@@ -93,20 +93,22 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'andr
     # using #defines, which results in Wswitch warnings in gcc-4.6.
     # Therefore, enable FAIL_ON_WARNINGS only on non-Android platforms.
     FAIL_ON_WARNINGS = True
 
 MSVC_ENABLE_PGO = True
 
 LOCAL_INCLUDES += [
     '/dom/base',
+    '/dom/plugins/ipc',
     '/layout/generic',
     '/layout/xul',
     '/widget',
     '/widget/android',
+    '/widget/cocoa',
     '/xpcom/base',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     LOCAL_INCLUDES += [
         '/dom/plugins/base/android',
     ]
 
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -47,16 +47,17 @@
 #include "nsIObserverService.h"
 #include <prinrval.h>
 
 #ifdef MOZ_WIDGET_COCOA
 #include <Carbon/Carbon.h>
 #include <ApplicationServices/ApplicationServices.h>
 #include <OpenGL/OpenGL.h>
 #include "nsCocoaFeatures.h"
+#include "PluginUtilsOSX.h"
 #endif
 
 // needed for nppdf plugin
 #if (MOZ_WIDGET_GTK)
 #include <gdk/gdk.h>
 #include <gdk/gdkx.h>
 #if (MOZ_WIDGET_GTK == 2)
 #include "gtk2xtbin.h"
@@ -2116,23 +2117,23 @@ NPError
 
   case NPNVsupportsCoreGraphicsBool: {
     *(NPBool*)result = true;
 
     return NPERR_NO_ERROR;
   }
 
   case NPNVsupportsCoreAnimationBool: {
-    *(NPBool*)result = nsCocoaFeatures::SupportCoreAnimationPlugins();
+    *(NPBool*)result = true;
 
     return NPERR_NO_ERROR;
   }
 
   case NPNVsupportsInvalidatingCoreAnimationBool: {
-    *(NPBool*)result = nsCocoaFeatures::SupportCoreAnimationPlugins();
+    *(NPBool*)result = true;
 
     return NPERR_NO_ERROR;
   }
 
   case NPNVsupportsCompositingCoreAnimationPluginsBool: {
     *(NPBool*)result = PR_TRUE;
 
     return NPERR_NO_ERROR;
@@ -2779,21 +2780,60 @@ void
     return;
 
   inst->UnscheduleTimer(timerID);
 }
 
 NPError
 _popupcontextmenu(NPP instance, NPMenu* menu)
 {
+#ifdef MOZ_WIDGET_COCOA
   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
-  if (!inst)
+
+  double pluginX, pluginY;
+  double screenX, screenY;
+
+  const NPCocoaEvent* currentEvent = static_cast<NPCocoaEvent*>(inst->GetCurrentEvent());
+  if (!currentEvent) {
     return NPERR_GENERIC_ERROR;
-
-  return inst->PopUpContextMenu(menu);
+  }
+
+  // Ensure that the events has an x/y value.
+  if (currentEvent->type != NPCocoaEventMouseDown    &&
+      currentEvent->type != NPCocoaEventMouseUp      &&
+      currentEvent->type != NPCocoaEventMouseMoved   &&
+      currentEvent->type != NPCocoaEventMouseEntered &&
+      currentEvent->type != NPCocoaEventMouseExited  &&
+      currentEvent->type != NPCocoaEventMouseDragged) {
+      return NPERR_GENERIC_ERROR;
+  }
+
+  pluginX = currentEvent->data.mouse.pluginX;
+  pluginY = currentEvent->data.mouse.pluginY;
+
+  if ((pluginX < 0.0) || (pluginY < 0.0))
+    return NPERR_GENERIC_ERROR;
+
+  NPBool success = _convertpoint(instance,
+                                 pluginX,  pluginY, NPCoordinateSpacePlugin,
+                                 &screenX, &screenY, NPCoordinateSpaceScreen);
+
+  if (success) {
+    return mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(menu,
+                                    screenX, screenY,
+                                    nullptr,
+                                    nullptr);
+  } else {
+    NS_WARNING("Convertpoint failed, could not created contextmenu.");
+    return NPERR_GENERIC_ERROR;
+  }
+#else
+    NS_WARNING("Not supported on this platform!");
+    return NPERR_GENERIC_ERROR;
+#endif
 }
 
 NPBool
 _convertpoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace)
 {
   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
   if (!inst)
     return false;
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -168,35 +168,36 @@ using namespace mozilla;
 using namespace mozilla::plugins::parent;
 using namespace mozilla::layers;
 
 static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
 
 NS_IMPL_ISUPPORTS0(nsNPAPIPluginInstance)
 
 nsNPAPIPluginInstance::nsNPAPIPluginInstance()
-  :
-    mDrawingModel(kDefaultDrawingModel),
+  : mDrawingModel(kDefaultDrawingModel)
 #ifdef MOZ_WIDGET_ANDROID
-    mANPDrawingModel(0),
-    mFullScreenOrientation(dom::eScreenOrientation_LandscapePrimary),
-    mWakeLocked(false),
-    mFullScreen(false),
-    mInverted(false),
+  , mANPDrawingModel(0)
+  , mFullScreenOrientation(dom::eScreenOrientation_LandscapePrimary)
+  , mWakeLocked(false)
+  , mFullScreen(false)
+  , mInverted(false)
 #endif
-    mRunning(NOT_STARTED),
-    mWindowless(false),
-    mTransparent(false),
-    mCached(false),
-    mUsesDOMForCursor(false),
-    mInPluginInitCall(false),
-    mPlugin(nullptr),
-    mMIMEType(nullptr),
-    mOwner(nullptr),
-    mCurrentPluginEvent(nullptr)
+  , mRunning(NOT_STARTED)
+  , mWindowless(false)
+  , mTransparent(false)
+  , mCached(false)
+  , mUsesDOMForCursor(false)
+  , mInPluginInitCall(false)
+  , mPlugin(nullptr)
+  , mMIMEType(nullptr)
+  , mOwner(nullptr)
+#ifdef XP_MACOSX
+  , mCurrentPluginEvent(nullptr)
+#endif
 #ifdef MOZ_WIDGET_ANDROID
   , mOnScreen(true)
 #endif
   , mHaveJavaC2PJSObjectQuirk(false)
   , mCachedParamLength(0)
   , mCachedParamNames(nullptr)
   , mCachedParamValues(nullptr)
 {
@@ -666,31 +667,35 @@ nsresult nsNPAPIPluginInstance::HandleEv
   if (!mPlugin || !mPlugin->GetLibrary())
     return NS_ERROR_FAILURE;
 
   NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
 
   int16_t tmpResult = kNPEventNotHandled;
 
   if (pluginFunctions->event) {
+#ifdef XP_MACOSX
     mCurrentPluginEvent = event;
+#endif
 #if defined(XP_WIN)
     NS_TRY_SAFE_CALL_RETURN(tmpResult, (*pluginFunctions->event)(&mNPP, event), this,
                             aSafeToReenterGecko);
 #else
     MAIN_THREAD_JNI_REF_GUARD;
     tmpResult = (*pluginFunctions->event)(&mNPP, event);
 #endif
     NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,
       ("NPP HandleEvent called: this=%p, npp=%p, event=%p, return=%d\n",
       this, &mNPP, event, tmpResult));
 
     if (result)
       *result = tmpResult;
+#ifdef XP_MACOSX
     mCurrentPluginEvent = nullptr;
+#endif
   }
 
   return NS_OK;
 }
 
 nsresult nsNPAPIPluginInstance::GetValueFromPlugin(NPPVariable variable, void* value)
 {
   if (!mPlugin || !mPlugin->GetLibrary())
@@ -1147,17 +1152,18 @@ bool
 nsNPAPIPluginInstance::ShouldCache()
 {
   return mCached;
 }
 
 nsresult
 nsNPAPIPluginInstance::IsWindowless(bool* isWindowless)
 {
-#ifdef MOZ_WIDGET_ANDROID
+#if defined(MOZ_WIDGET_ANDROID) || defined(XP_MACOSX)
+  // All OS X plugins are windowless.
   // On android, pre-honeycomb, all plugins are treated as windowless.
   *isWindowless = true;
 #else
   *isWindowless = mWindowless;
 #endif
   return NS_OK;
 }
 
@@ -1506,33 +1512,23 @@ nsNPAPIPluginInstance::UnscheduleTimer(u
 
   // remove timer struct from array
   mTimers.RemoveElementAt(index);
 
   // delete timer
   delete t;
 }
 
-// Show the context menu at the location for the current event.
-// This can only be called from within an NPP_SendEvent call.
-NPError
-nsNPAPIPluginInstance::PopUpContextMenu(NPMenu* menu)
-{
-  if (mOwner && mCurrentPluginEvent)
-    return mOwner->ShowNativeContextMenu(menu, mCurrentPluginEvent);
-
-  return NPERR_GENERIC_ERROR;
-}
-
 NPBool
 nsNPAPIPluginInstance::ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
                                     double *destX, double *destY, NPCoordinateSpace destSpace)
 {
-  if (mOwner)
+  if (mOwner) {
     return mOwner->ConvertPoint(sourceX, sourceY, sourceSpace, destX, destY, destSpace);
+  }
 
   return false;
 }
 
 nsresult
 nsNPAPIPluginInstance::GetDOMElement(nsIDOMElement* *result)
 {
   if (!mOwner) {
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -129,16 +129,20 @@ public:
 
   NPError SetUsesDOMForCursor(bool aUsesDOMForCursor);
   bool UsesDOMForCursor();
 
   void SetDrawingModel(NPDrawingModel aModel);
   void RedrawPlugin();
 #ifdef XP_MACOSX
   void SetEventModel(NPEventModel aModel);
+
+  void* GetCurrentEvent() {
+    return mCurrentPluginEvent;
+  }
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
   void NotifyForeground(bool aForeground);
   void NotifyOnScreen(bool aOnScreen);
   void MemoryPressure();
   void NotifyFullScreen(bool aFullScreen);
   void NotifySize(nsIntSize size);
@@ -256,17 +260,16 @@ public:
 
   nsresult IsPrivateBrowsing(bool *aEnabled);
 
   nsresult GetDOMElement(nsIDOMElement* *result);
 
   nsNPAPITimer* TimerWithID(uint32_t id, uint32_t* index);
   uint32_t      ScheduleTimer(uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID));
   void          UnscheduleTimer(uint32_t timerID);
-  NPError       PopUpContextMenu(NPMenu* menu);
   NPBool        ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
 
 
   nsTArray<nsNPAPIPluginStreamListener*> *StreamListeners();
 
   nsTArray<nsPluginStreamListenerPeer*> *FileCachedStreamListeners();
 
   nsresult AsyncSetWindow(NPWindow& window);
@@ -363,18 +366,20 @@ private:
   char* mMIMEType;
 
   // Weak pointer to the owner. The owner nulls this out (by calling
   // InvalidateOwner()) when it's no longer our owner.
   nsPluginInstanceOwner *mOwner;
 
   nsTArray<nsNPAPITimer*> mTimers;
 
+#ifdef XP_MACOSX
   // non-null during a HandleEvent call
   void* mCurrentPluginEvent;
+#endif
 
   // Timestamp for the last time this plugin was stopped.
   // This is only valid when the plugin is actually stopped!
   mozilla::TimeStamp mStopTime;
 
 #ifdef MOZ_WIDGET_ANDROID
   void EnsureSharedTexture();
   mozilla::TemporaryRef<mozilla::gl::AndroidSurfaceTexture> CreateSurfaceTexture();
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -52,30 +52,33 @@ using mozilla::DefaultXDisplay;
 #include "EGLUtils.h"
 #include "nsIContentInlines.h"
 #include "mozilla/MiscEvents.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/dom/HTMLObjectElementBinding.h"
 #include "mozilla/dom/TabChild.h"
 #include "nsFrameSelection.h"
+#include "PuppetWidget.h"
+#include "nsPIWindowRoot.h"
 
 #include "nsContentCID.h"
 #include "nsWidgetsCID.h"
 static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 #ifdef XP_WIN
 #include <wtypes.h>
 #include <winuser.h>
 #endif
 
 #ifdef XP_MACOSX
-#include <Carbon/Carbon.h>
-#include "nsPluginUtilsOSX.h"
+#include "ComplexTextInputPanel.h"
+#include "nsIDOMXULDocument.h"
+#include "nsIDOMXULCommandDispatcher.h"
 #endif
 
 #ifdef MOZ_WIDGET_GTK
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
@@ -90,16 +93,20 @@ using namespace mozilla::dom;
 #include <android/log.h>
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 
+static inline nsPoint AsNsPoint(const nsIntPoint &p) {
+  return nsPoint(p.x, p.y);
+}
+
 // special class for handeling DOM context menu events because for
 // some reason it starves other mouse events if implemented on the
 // same class
 class nsPluginDOMContextMenuListener : public nsIDOMEventListener
 {
   virtual ~nsPluginDOMContextMenuListener();
 
 public:
@@ -325,18 +332,21 @@ nsPluginInstanceOwner::nsPluginInstanceO
 
   mPluginFrame = nullptr;
   mContent = nullptr;
   mWidgetCreationComplete = false;
 #ifdef XP_MACOSX
   memset(&mCGPluginPortCopy, 0, sizeof(NP_CGContext));
   mInCGPaintLevel = 0;
   mSentInitialTopLevelWindowEvent = false;
+  mLastWindowIsActive = false;
+  mLastContentFocused = false;
+  mLastScaleFactor = 1.0;
   mColorProfile = nullptr;
-  mPluginPortChanged = false;
+  mShouldBlurOnActivate = false;
 #endif
   mContentFocused = false;
   mWidgetVisible = true;
   mPluginWindowVisible = false;
   mPluginDocumentActiveState = true;
   mLastMouseDownButtonType = -1;
 
 #ifdef XP_MACOSX
@@ -724,43 +734,262 @@ NS_IMETHODIMP nsPluginInstanceOwner::Set
 #ifdef XP_MACOSX
   mEventModel = static_cast<NPEventModel>(eventModel);
   return NS_OK;
 #else
   return NS_ERROR_NOT_IMPLEMENTED;
 #endif
 }
 
+// This is no longer used, just leaving it here so we don't have to change
+// the nsIPluginInstanceOwner interface.
 NPError nsPluginInstanceOwner::ShowNativeContextMenu(NPMenu* menu, void* event)
 {
-  if (!menu || !event)
-    return NPERR_GENERIC_ERROR;
+  return NPERR_GENERIC_ERROR;
+}
 
 #ifdef XP_MACOSX
-  if (GetEventModel() != NPEventModelCocoa)
-    return NPERR_INCOMPATIBLE_VERSION_ERROR;
-
-  return NS_NPAPI_ShowCocoaContextMenu(static_cast<void*>(menu), mWidget,
-                                       static_cast<NPCocoaEvent*>(event));
-#else
-  return NPERR_INCOMPATIBLE_VERSION_ERROR;
-#endif
+NPBool nsPluginInstanceOwner::ConvertPointPuppet(PuppetWidget *widget,
+                                                 nsPluginFrame* pluginFrame,
+                                                 double sourceX, double sourceY,
+                                                 NPCoordinateSpace sourceSpace,
+                                                 double *destX, double *destY,
+                                                 NPCoordinateSpace destSpace)
+{
+  NS_ENSURE_TRUE(widget && widget->GetOwningTabChild() && pluginFrame, false);
+  // Caller has to want a result.
+  NS_ENSURE_TRUE(destX || destY, false);
+
+  if (sourceSpace == destSpace) {
+    if (destX) {
+      *destX = sourceX;
+    }
+    if (destY) {
+      *destY = sourceY;
+    }
+    return true;
+  }
+
+  nsPresContext* presContext = pluginFrame->PresContext();
+  double scaleFactor = double(nsPresContext::AppUnitsPerCSSPixel())/
+    presContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom();
+
+  PuppetWidget *puppetWidget = static_cast<PuppetWidget*>(widget);
+  PuppetWidget *rootWidget = static_cast<PuppetWidget*>(widget->GetTopLevelWidget());
+  if (!rootWidget) {
+    return false;
+  }
+  nsPoint chromeSize = AsNsPoint(rootWidget->GetChromeDimensions()) / scaleFactor;
+  nsIntSize intScreenDims = rootWidget->GetScreenDimensions();
+  nsSize screenDims = nsSize(intScreenDims.width / scaleFactor,
+                             intScreenDims.height / scaleFactor);
+  int32_t screenH = screenDims.height;
+  nsPoint windowPosition = AsNsPoint(rootWidget->GetWindowPosition()) / scaleFactor;
+
+  // Window size is tab size + chrome size.
+  nsIntRect tabContentBounds;
+  NS_ENSURE_SUCCESS(puppetWidget->GetBounds(tabContentBounds), false);
+  tabContentBounds.ScaleInverseRoundOut(scaleFactor);
+  int32_t windowH = tabContentBounds.height + int(chromeSize.y);
+
+  // This is actually relative to window-chrome.
+  nsPoint pluginPosition = AsNsPoint(pluginFrame->GetScreenRect().TopLeft());
+
+  // Convert (sourceX, sourceY) to 'real' (not PuppetWidget) screen space.
+  // In OSX, the Y-axis increases upward, which is the reverse of ours.
+  // We want OSX coordinates for window and screen so those equations are swapped.
+  nsPoint sourcePoint(sourceX, sourceY);
+  nsPoint screenPoint;
+  switch (sourceSpace) {
+    case NPCoordinateSpacePlugin:
+      screenPoint = sourcePoint + pluginFrame->GetContentRectRelativeToSelf().TopLeft() +
+        chromeSize + pluginPosition + windowPosition;
+      break;
+    case NPCoordinateSpaceWindow:
+      screenPoint = nsPoint(sourcePoint.x, windowH-sourcePoint.y) +
+        windowPosition;
+      break;
+    case NPCoordinateSpaceFlippedWindow:
+      screenPoint = sourcePoint + windowPosition;
+      break;
+    case NPCoordinateSpaceScreen:
+      screenPoint = nsPoint(sourcePoint.x, screenH-sourcePoint.y);
+      break;
+    case NPCoordinateSpaceFlippedScreen:
+      screenPoint = sourcePoint;
+      break;
+    default:
+      return false;
+  }
+
+  // Convert from screen to dest space.
+  nsPoint destPoint;
+  switch (destSpace) {
+    case NPCoordinateSpacePlugin:
+      destPoint = screenPoint - pluginFrame->GetContentRectRelativeToSelf().TopLeft() -
+        chromeSize - pluginPosition - windowPosition;
+      break;
+    case NPCoordinateSpaceWindow:
+      destPoint = screenPoint - windowPosition;
+      destPoint.y = windowH - destPoint.y;
+      break;
+    case NPCoordinateSpaceFlippedWindow:
+      destPoint = screenPoint - windowPosition;
+      break;
+    case NPCoordinateSpaceScreen:
+      destPoint = nsPoint(screenPoint.x, screenH-screenPoint.y);
+      break;
+    case NPCoordinateSpaceFlippedScreen:
+      destPoint = screenPoint;
+      break;
+    default:
+      return false;
+  }
+
+  if (destX) {
+    *destX = destPoint.x;
+  }
+  if (destY) {
+    *destY = destPoint.y;
+  }
+
+  return true;
 }
 
+NPBool nsPluginInstanceOwner::ConvertPointNoPuppet(nsIWidget *widget,
+                                                   nsPluginFrame* pluginFrame,
+                                                   double sourceX, double sourceY,
+                                                   NPCoordinateSpace sourceSpace,
+                                                   double *destX, double *destY,
+                                                   NPCoordinateSpace destSpace)
+{
+  NS_ENSURE_TRUE(widget && pluginFrame, false);
+  // Caller has to want a result.
+  NS_ENSURE_TRUE(destX || destY, false);
+
+  if (sourceSpace == destSpace) {
+    if (destX) {
+      *destX = sourceX;
+    }
+    if (destY) {
+      *destY = sourceY;
+    }
+    return true;
+  }
+
+  nsPresContext* presContext = pluginFrame->PresContext();
+  double scaleFactor = double(nsPresContext::AppUnitsPerCSSPixel())/
+    presContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom();
+
+  nsCOMPtr<nsIScreenManager> screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
+  if (!screenMgr) {
+    return false;
+  }
+  nsCOMPtr<nsIScreen> screen;
+  screenMgr->ScreenForNativeWidget(widget->GetNativeData(NS_NATIVE_WINDOW), getter_AddRefs(screen));
+  if (!screen) {
+    return false;
+  }
+
+  int32_t screenX, screenY, screenWidth, screenHeight;
+  screen->GetRect(&screenX, &screenY, &screenWidth, &screenHeight);
+  screenHeight /= scaleFactor;
+
+  nsIntRect windowScreenBounds;
+  NS_ENSURE_SUCCESS(widget->GetScreenBounds(windowScreenBounds), false);
+  windowScreenBounds.ScaleInverseRoundOut(scaleFactor);
+  int32_t windowX = windowScreenBounds.x;
+  int32_t windowY = windowScreenBounds.y;
+  int32_t windowHeight = windowScreenBounds.height;
+
+  nsIntRect pluginScreenRect = pluginFrame->GetScreenRect();
+
+  double screenXGecko, screenYGecko;
+  switch (sourceSpace) {
+    case NPCoordinateSpacePlugin:
+      screenXGecko = pluginScreenRect.x + sourceX;
+      screenYGecko = pluginScreenRect.y + sourceY;
+      break;
+    case NPCoordinateSpaceWindow:
+      screenXGecko = windowX + sourceX;
+      screenYGecko = windowY + (windowHeight - sourceY);
+      break;
+    case NPCoordinateSpaceFlippedWindow:
+      screenXGecko = windowX + sourceX;
+      screenYGecko = windowY + sourceY;
+      break;
+    case NPCoordinateSpaceScreen:
+      screenXGecko = sourceX;
+      screenYGecko = screenHeight - sourceY;
+      break;
+    case NPCoordinateSpaceFlippedScreen:
+      screenXGecko = sourceX;
+      screenYGecko = sourceY;
+      break;
+    default:
+      return false;
+  }
+
+  double destXCocoa, destYCocoa;
+  switch (destSpace) {
+    case NPCoordinateSpacePlugin:
+      destXCocoa = screenXGecko - pluginScreenRect.x;
+      destYCocoa = screenYGecko - pluginScreenRect.y;
+      break;
+    case NPCoordinateSpaceWindow:
+      destXCocoa = screenXGecko - windowX;
+      destYCocoa = windowHeight - (screenYGecko - windowY);
+      break;
+    case NPCoordinateSpaceFlippedWindow:
+      destXCocoa = screenXGecko - windowX;
+      destYCocoa = screenYGecko - windowY;
+      break;
+    case NPCoordinateSpaceScreen:
+      destXCocoa = screenXGecko;
+      destYCocoa = screenHeight - screenYGecko;
+      break;
+    case NPCoordinateSpaceFlippedScreen:
+      destXCocoa = screenXGecko;
+      destYCocoa = screenYGecko;
+      break;
+    default:
+      return false;
+  }
+
+  if (destX) {
+    *destX = destXCocoa;
+  }
+  if (destY) {
+    *destY = destYCocoa;
+  }
+
+  return true;
+}
+#endif // XP_MACOSX
+
 NPBool nsPluginInstanceOwner::ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
                                            double *destX, double *destY, NPCoordinateSpace destSpace)
 {
 #ifdef XP_MACOSX
-  if (!mWidget)
+  if (!mPluginFrame) {
     return false;
-
-  return NS_NPAPI_ConvertPointCocoa(mWidget->GetNativeData(NS_NATIVE_WIDGET),
-                                    sourceX, sourceY, sourceSpace, destX, destY, destSpace);
+  }
+
+  MOZ_ASSERT(mPluginFrame->GetNearestWidget());
+
+  if (nsIWidget::UsePuppetWidgets()) {
+    return ConvertPointPuppet(static_cast<PuppetWidget*>(mPluginFrame->GetNearestWidget()),
+                               mPluginFrame, sourceX, sourceY, sourceSpace,
+                               destX, destY, destSpace);
+  }
+
+  return ConvertPointNoPuppet(mPluginFrame->GetNearestWidget(),
+                              mPluginFrame, sourceX, sourceY, sourceSpace,
+                              destX, destY, destSpace);
 #else
-  // we should implement this for all platforms
   return false;
 #endif
 }
 
 NS_IMETHODIMP nsPluginInstanceOwner::GetTagType(nsPluginTagType *result)
 {
   NS_ENSURE_ARG_POINTER(result);
 
@@ -999,38 +1228,22 @@ void* nsPluginInstanceOwner::GetPluginPo
 {
   if (GetDrawingModel() == NPDrawingModelCoreGraphics ||
       GetDrawingModel() == NPDrawingModelCoreAnimation ||
       GetDrawingModel() == NPDrawingModelInvalidatingCoreAnimation)
     return &mCGPluginPortCopy;
   return nullptr;
 }
 
-// Currently (on OS X in Cocoa widgets) any changes made as a result of
-// calling GetPluginPortFromWidget() are immediately reflected in the NPWindow
-// structure that has been passed to the plugin via SetWindow().  This is
-// because calls to nsChildView::GetNativeData(NS_NATIVE_PLUGIN_PORT_CG)
-// always return a pointer to the same internal (private) object, but may
-// make changes inside that object.  All calls to GetPluginPortFromWidget() made while
-// the plugin is active (i.e. excluding those made at our initialization)
-// need to take this into account.  The easiest way to do so is to replace
-// them with calls to SetPluginPortAndDetectChange().  This method keeps track
-// of when calls to GetPluginPortFromWidget() result in changes, and sets a flag to make
-// sure SetWindow() gets called the next time through FixUpPluginWindow(), so
-// that the plugin is notified of these changes.
-void* nsPluginInstanceOwner::SetPluginPortAndDetectChange()
+void nsPluginInstanceOwner::SetPluginPort()
 {
-  if (!mPluginWindow)
-    return nullptr;
-  void* pluginPort = GetPluginPortFromWidget();
-  if (!pluginPort)
-    return nullptr;
+  void* pluginPort = GetPluginPort();
+  if (!pluginPort || !mPluginWindow)
+    return;
   mPluginWindow->window = pluginPort;
-
-  return mPluginWindow->window;
 }
 
 void nsPluginInstanceOwner::BeginCGPaint()
 {
   ++mInCGPaintLevel;
 }
 
 void nsPluginInstanceOwner::EndCGPaint()
@@ -1266,17 +1479,16 @@ nsresult nsPluginInstanceOwner::Dispatch
   if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow)) {
     // continue only for cases without child window
     return aFocusEvent->PreventDefault(); // consume event
   }
 #endif
 
   WidgetEvent* theEvent = aFocusEvent->GetInternalNSEvent();
   if (theEvent) {
-    // we only care about the message in ProcessEvent
     WidgetGUIEvent focusEvent(theEvent->mFlags.mIsTrusted, theEvent->message,
                               nullptr);
     nsEventStatus rv = ProcessEvent(focusEvent);
     if (nsEventStatus_eConsumeNoDefault == rv) {
       aFocusEvent->PreventDefault();
       aFocusEvent->StopPropagation();
     }
   }
@@ -1390,40 +1602,45 @@ nsresult nsPluginInstanceOwner::Dispatch
 
 nsresult
 nsPluginInstanceOwner::HandleEvent(nsIDOMEvent* aEvent)
 {
   NS_ASSERTION(mInstance, "Should have a valid plugin instance or not receive events.");
 
   nsAutoString eventType;
   aEvent->GetType(eventType);
+
+#ifdef XP_MACOSX
+  if (eventType.EqualsLiteral("activate") ||
+      eventType.EqualsLiteral("deactivate")) {
+    WindowFocusMayHaveChanged();
+    return NS_OK;
+  }
+  if (eventType.EqualsLiteral("MozPerformDelayedBlur")) {
+    if (mShouldBlurOnActivate) {
+      WidgetGUIEvent blurEvent(true, NS_BLUR_CONTENT, nullptr);
+      ProcessEvent(blurEvent);
+      mShouldBlurOnActivate = false;
+    }
+    return NS_OK;
+  }
+#endif
+
   if (eventType.EqualsLiteral("focus")) {
     mContentFocused = true;
     return DispatchFocusToPlugin(aEvent);
   }
   if (eventType.EqualsLiteral("blur")) {
     mContentFocused = false;
     return DispatchFocusToPlugin(aEvent);
   }
   if (eventType.EqualsLiteral("mousedown")) {
     return ProcessMouseDown(aEvent);
   }
   if (eventType.EqualsLiteral("mouseup")) {
-    // Don't send a mouse-up event to the plugin if its button type doesn't
-    // match that of the preceding mouse-down event (if any).  This kind of
-    // mismatch can happen if the previous mouse-down event was sent to a DOM
-    // element above the plugin, the mouse is still above the plugin, and the
-    // mouse-down event caused the element to disappear.  See bug 627649 and
-    // bug 909678.
-    WidgetMouseEvent* mouseEvent = aEvent->GetInternalNSEvent()->AsMouseEvent();
-    if (mouseEvent &&
-        static_cast<int>(mouseEvent->button) != mLastMouseDownButtonType) {
-      aEvent->PreventDefault();
-      return NS_OK;
-    }
     return DispatchMouseToPlugin(aEvent);
   }
   if (eventType.EqualsLiteral("mousemove")) {
     return DispatchMouseToPlugin(aEvent, true);
   }
   if (eventType.EqualsLiteral("click") ||
       eventType.EqualsLiteral("dblclick") ||
       eventType.EqualsLiteral("mouseover") ||
@@ -1459,123 +1676,296 @@ static unsigned int XInputEventState(con
   if (anEvent.IsShift()) state |= ShiftMask;
   if (anEvent.IsControl()) state |= ControlMask;
   if (anEvent.IsAlt()) state |= Mod1Mask;
   if (anEvent.IsMeta()) state |= Mod4Mask;
   return state;
 }
 #endif
 
+#ifdef XP_MACOSX
+
+// Returns whether or not content is the content that is or would be
+// focused if the top-level chrome window was active.
+static bool
+ContentIsFocusedWithinWindow(nsIContent* aContent)
+{
+  nsPIDOMWindow* outerWindow = aContent->OwnerDoc()->GetWindow();
+  if (!outerWindow) {
+    return false;
+  }
+
+  nsPIDOMWindow* rootWindow = outerWindow->GetPrivateRoot();
+  if (!rootWindow) {
+    return false;
+  }
+
+  nsFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (!fm) {
+    return false;
+  }
+
+  nsCOMPtr<nsPIDOMWindow> focusedFrame;
+  nsCOMPtr<nsIContent> focusedContent = fm->GetFocusedDescendant(rootWindow, true, getter_AddRefs(focusedFrame));
+  return (focusedContent.get() == aContent);
+}
+
+static NPCocoaEventType
+CocoaEventTypeForEvent(const WidgetGUIEvent& anEvent, nsIFrame* aObjectFrame)
+{
+  const NPCocoaEvent* event = static_cast<const NPCocoaEvent*>(anEvent.mPluginEvent);
+  if (event) {
+    return event->type;
+  }
+
+  switch (anEvent.message) {
+    case NS_MOUSE_ENTER_SYNTH:
+      return NPCocoaEventMouseEntered;
+    case NS_MOUSE_EXIT_SYNTH:
+      return NPCocoaEventMouseExited;
+    case NS_MOUSE_MOVE:
+    {
+      // We don't know via information on events from the widget code whether or not
+      // we're dragging. The widget code just generates mouse move events from native
+      // drag events. If anybody is capturing, this is a drag event.
+      if (nsIPresShell::GetCapturingContent()) {
+        return NPCocoaEventMouseDragged;
+      }
+
+      return NPCocoaEventMouseMoved;
+    }
+    case NS_MOUSE_BUTTON_DOWN:
+      return NPCocoaEventMouseDown;
+    case NS_MOUSE_BUTTON_UP:
+      return NPCocoaEventMouseUp;
+    case NS_KEY_DOWN:
+      return NPCocoaEventKeyDown;
+    case NS_KEY_UP:
+      return NPCocoaEventKeyUp;
+    case NS_FOCUS_CONTENT:
+    case NS_BLUR_CONTENT:
+      return NPCocoaEventFocusChanged;
+    case NS_MOUSE_SCROLL:
+      return NPCocoaEventScrollWheel;
+    default:
+      return (NPCocoaEventType)0;
+  }
+}
+
+static NPCocoaEvent
+TranslateToNPCocoaEvent(WidgetGUIEvent* anEvent, nsIFrame* aObjectFrame)
+{
+  NPCocoaEvent cocoaEvent;
+  InitializeNPCocoaEvent(&cocoaEvent);
+  cocoaEvent.type = CocoaEventTypeForEvent(*anEvent, aObjectFrame);
+
+  if (anEvent->message == NS_MOUSE_MOVE ||
+      anEvent->message == NS_MOUSE_BUTTON_DOWN ||
+      anEvent->message == NS_MOUSE_BUTTON_UP ||
+      anEvent->message == NS_MOUSE_SCROLL ||
+      anEvent->message == NS_MOUSE_ENTER_SYNTH ||
+      anEvent->message == NS_MOUSE_EXIT_SYNTH)
+  {
+    nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(anEvent, aObjectFrame) -
+                 aObjectFrame->GetContentRectRelativeToSelf().TopLeft();
+    nsPresContext* presContext = aObjectFrame->PresContext();
+    // Plugin event coordinates need to be translated from device pixels
+    // into "display pixels" in HiDPI modes.
+    double scaleFactor = double(nsPresContext::AppUnitsPerCSSPixel())/
+      aObjectFrame->PresContext()->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom();
+    size_t intScaleFactor = ceil(scaleFactor);
+    nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x) / intScaleFactor,
+                    presContext->AppUnitsToDevPixels(pt.y) / intScaleFactor);
+    cocoaEvent.data.mouse.pluginX = double(ptPx.x);
+    cocoaEvent.data.mouse.pluginY = double(ptPx.y);
+  }
+
+  switch (anEvent->message) {
+    case NS_MOUSE_BUTTON_DOWN:
+    case NS_MOUSE_BUTTON_UP:
+    {
+      WidgetMouseEvent* mouseEvent = anEvent->AsMouseEvent();
+      if (mouseEvent) {
+        switch (mouseEvent->button) {
+          case WidgetMouseEvent::eLeftButton:
+            cocoaEvent.data.mouse.buttonNumber = 0;
+            break;
+          case WidgetMouseEvent::eRightButton:
+            cocoaEvent.data.mouse.buttonNumber = 1;
+            break;
+          case WidgetMouseEvent::eMiddleButton:
+            cocoaEvent.data.mouse.buttonNumber = 2;
+            break;
+          default:
+            NS_WARNING("Mouse button we don't know about?");
+        }
+        cocoaEvent.data.mouse.clickCount = mouseEvent->clickCount;
+      } else {
+        NS_WARNING("NS_MOUSE_BUTTON_UP/DOWN is not a WidgetMouseEvent?");
+      }
+      break;
+    }
+    case NS_MOUSE_SCROLL:
+    {
+      WidgetWheelEvent* wheelEvent = anEvent->AsWheelEvent();
+      if (wheelEvent) {
+        cocoaEvent.data.mouse.deltaX = wheelEvent->lineOrPageDeltaX;
+        cocoaEvent.data.mouse.deltaY = wheelEvent->lineOrPageDeltaY;
+      } else {
+        NS_WARNING("NS_MOUSE_SCROLL is not a WidgetWheelEvent? (could be, haven't checked)");
+      }
+      break;
+    }
+    case NS_KEY_DOWN:
+    case NS_KEY_UP:
+    {
+      WidgetKeyboardEvent* keyEvent = anEvent->AsKeyboardEvent();
+
+      cocoaEvent.data.key.keyCode = keyEvent->mNativeKeyCode;
+      cocoaEvent.data.key.isARepeat = keyEvent->mIsRepeat;
+      cocoaEvent.data.key.modifierFlags = keyEvent->mNativeModifierFlags;
+      const char16_t* nativeChars = keyEvent->mNativeCharacters.get();
+      cocoaEvent.data.key.characters =
+        (NPNSString*)::CFStringCreateWithCharacters(NULL,
+                                                    reinterpret_cast<const UniChar*>(nativeChars),
+                                                    keyEvent->mNativeCharacters.Length());
+      const char16_t* nativeCharsIgnoringModifiers = keyEvent->mNativeCharactersIgnoringModifiers.get();
+      cocoaEvent.data.key.charactersIgnoringModifiers =
+        (NPNSString*)::CFStringCreateWithCharacters(NULL,
+                                                    reinterpret_cast<const UniChar*>(nativeCharsIgnoringModifiers),
+                                                    keyEvent->mNativeCharactersIgnoringModifiers.Length());
+      break;
+    }
+    case NS_FOCUS_CONTENT:
+    case NS_BLUR_CONTENT:
+      cocoaEvent.data.focus.hasFocus = (anEvent->message == NS_FOCUS_CONTENT);
+      break;
+    default:
+      break;
+  }
+  return cocoaEvent;
+}
+
+void nsPluginInstanceOwner::PerformDelayedBlurs()
+{
+  nsCOMPtr<EventTarget> windowRoot = mContent->OwnerDoc()->GetWindow()->GetTopWindowRoot();
+  nsContentUtils::DispatchTrustedEvent(mContent->OwnerDoc(),
+                                       windowRoot,
+                                       NS_LITERAL_STRING("MozPerformDelayedBlur"),
+                                       false, false, nullptr);
+}
+
+#endif
+
 nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
 {
   nsEventStatus rv = nsEventStatus_eIgnore;
 
-  if (!mInstance || !mPluginFrame)   // if mInstance is null, we shouldn't be here
+  if (!mInstance || !mPluginFrame) {
     return nsEventStatus_eIgnore;
+  }
 
 #ifdef XP_MACOSX
-  if (!mWidget)
+  NPEventModel eventModel = GetEventModel();
+  if (eventModel != NPEventModelCocoa) {
     return nsEventStatus_eIgnore;
-
-  // we never care about synthesized mouse enter
-  if (anEvent.message == NS_MOUSE_ENTER_SYNTH)
+  }
+
+  // In the Cocoa event model, focus is per-window. Don't tell a plugin it lost
+  // focus unless it lost focus within the window. For example, ignore a blur
+  // event if it's coming due to the plugin's window deactivating.
+  if (anEvent.message == NS_BLUR_CONTENT &&
+      ContentIsFocusedWithinWindow(mContent)) {
+    mShouldBlurOnActivate = true;
     return nsEventStatus_eIgnore;
-
-  nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
-  if (!pluginWidget || NS_FAILED(pluginWidget->StartDrawPlugin()))
+  }
+
+  // Also, don't tell the plugin it gained focus again after we've already given
+  // it focus. This might happen if it has focus, its window is blurred, then the
+  // window is made active again. The plugin never lost in-window focus, so it
+  // shouldn't get a focus event again.
+  if (anEvent.message == NS_FOCUS_CONTENT &&
+      mLastContentFocused == true) {
+    mShouldBlurOnActivate = false;
     return nsEventStatus_eIgnore;
-
-  NPEventModel eventModel = GetEventModel();
-
-  // If we have to synthesize an event we'll use one of these.
-  NPCocoaEvent synthCocoaEvent;
-  const NPCocoaEvent* event = static_cast<const NPCocoaEvent*>(anEvent.mPluginEvent);
-  nsPoint pt =
-  nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mPluginFrame) -
-  mPluginFrame->GetContentRectRelativeToSelf().TopLeft();
-  nsPresContext* presContext = mPluginFrame->PresContext();
-  // Plugin event coordinates need to be translated from device pixels
-  // into "display pixels" in HiDPI modes.
-  double scaleFactor = 1.0;
-  GetContentsScaleFactor(&scaleFactor);
-  size_t intScaleFactor = ceil(scaleFactor);
-  nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x) / intScaleFactor,
-                  presContext->AppUnitsToDevPixels(pt.y) / intScaleFactor);
-
-  if (!event) {
-    InitializeNPCocoaEvent(&synthCocoaEvent);
-    switch (anEvent.message) {
-      case NS_MOUSE_MOVE:
-      {
-        // Ignore mouse-moved events that happen as part of a dragging
-        // operation that started over another frame.  See bug 525078.
-        nsRefPtr<nsFrameSelection> frameselection = mPluginFrame->GetFrameSelection();
-        if (!frameselection->GetDragState() ||
-          (nsIPresShell::GetCapturingContent() == mPluginFrame->GetContent())) {
-          synthCocoaEvent.type = NPCocoaEventMouseMoved;
-          synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
-          synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
-          event = &synthCocoaEvent;
-        }
+  }
+
+  // Now, if we're going to send a focus event, update mLastContentFocused and
+  // tell any plugins in our window that we have taken focus, so they should
+  // perform any delayed blurs.
+  if (anEvent.message == NS_FOCUS_CONTENT ||
+      anEvent.message == NS_BLUR_CONTENT) {
+    mLastContentFocused = (anEvent.message == NS_FOCUS_CONTENT);
+    mShouldBlurOnActivate = false;
+    PerformDelayedBlurs();
+  }
+
+  NPCocoaEvent cocoaEvent = TranslateToNPCocoaEvent(const_cast<WidgetGUIEvent*>(&anEvent), mPluginFrame);
+  if (cocoaEvent.type == (NPCocoaEventType)0) {
+    return nsEventStatus_eIgnore;
+  }
+
+  if (cocoaEvent.type == NPCocoaEventKeyDown) {
+    ComplexTextInputPanel* ctiPanel = ComplexTextInputPanel::GetSharedComplexTextInputPanel();
+    if (ctiPanel && ctiPanel->IsInComposition()) {
+      nsAutoString outText;
+      ctiPanel->InterpretKeyEvent(&cocoaEvent, outText);
+      if (!outText.IsEmpty()) {
+        CFStringRef cfString = ::CFStringCreateWithCharacters(kCFAllocatorDefault,
+                                                              reinterpret_cast<const UniChar*>(outText.get()),
+                                                              outText.Length());
+
+        NPCocoaEvent textEvent;
+        InitializeNPCocoaEvent(&textEvent);
+        textEvent.type = NPCocoaEventTextInput;
+        textEvent.data.text.text = (NPNSString*)cfString;
+
+        mInstance->HandleEvent(&textEvent, nullptr);
       }
-        break;
-      case NS_MOUSE_BUTTON_DOWN:
-        synthCocoaEvent.type = NPCocoaEventMouseDown;
-        synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
-        synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
-        event = &synthCocoaEvent;
-        break;
-      case NS_MOUSE_BUTTON_UP:
-        // If we're in a dragging operation that started over another frame,
-        // convert it into a mouse-entered event (in the Cocoa Event Model).
-        // See bug 525078.
-        if (anEvent.AsMouseEvent()->button == WidgetMouseEvent::eLeftButton &&
-            (nsIPresShell::GetCapturingContent() != mPluginFrame->GetContent())) {
-          synthCocoaEvent.type = NPCocoaEventMouseEntered;
-          synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
-          synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
-          event = &synthCocoaEvent;
-        } else {
-          synthCocoaEvent.type = NPCocoaEventMouseUp;
-          synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
-          synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
-          event = &synthCocoaEvent;
-        }
-        break;
-      default:
-        break;
-    }
-
-    // If we still don't have an event, bail.
-    if (!event) {
-      pluginWidget->EndDrawPlugin();
-      return nsEventStatus_eIgnore;
+      return nsEventStatus_eConsumeNoDefault;
     }
   }
 
   int16_t response = kNPEventNotHandled;
-  void* window = FixUpPluginWindow(ePluginPaintEnable);
-  if (window || (eventModel == NPEventModelCocoa)) {
-    mInstance->HandleEvent(const_cast<NPCocoaEvent*>(event),
-                           &response,
-                           NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
+  mInstance->HandleEvent(&cocoaEvent,
+                         &response,
+                         NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
+  if (response == kNPEventStartIME) {
+    nsAutoString outText;
+    ComplexTextInputPanel* ctiPanel = ComplexTextInputPanel::GetSharedComplexTextInputPanel();
+
+    // Place ctiPanel by passing the coordinates of the bottom-left of the plugin,
+    // in screen-coordinates.
+    double screenX, screenY;
+    ConvertPoint(0.0, mPluginFrame->GetScreenRect().height, NPCoordinateSpacePlugin,
+                 &screenX, &screenY, NPCoordinateSpaceScreen);
+
+    ctiPanel->PlacePanel(screenX, screenY);
+    ctiPanel->InterpretKeyEvent(&cocoaEvent, outText);
+
+    if (!outText.IsEmpty()) {
+      CFStringRef cfString = ::CFStringCreateWithCharacters(kCFAllocatorDefault,
+                                                            reinterpret_cast<const UniChar*>(outText.get()),
+                                                            outText.Length());
+
+      NPCocoaEvent textEvent;
+      InitializeNPCocoaEvent(&textEvent);
+      textEvent.type = NPCocoaEventTextInput;
+      textEvent.data.text.text = (NPNSString*)cfString;
+
+      mInstance->HandleEvent(&textEvent, nullptr);
+     }
   }
 
-  if (eventModel == NPEventModelCocoa && response == kNPEventStartIME) {
-    pluginWidget->StartComplexTextInputForCurrentEvent();
-  }
-
-  if ((response == kNPEventHandled || response == kNPEventStartIME) &&
-      !(anEvent.message == NS_MOUSE_BUTTON_DOWN &&
-        anEvent.AsMouseEvent()->button == WidgetMouseEvent::eLeftButton &&
-        !mContentFocused)) {
+  bool handled = (response == kNPEventHandled || response == kNPEventStartIME);
+  bool leftMouseButtonDown = (anEvent.message == NS_MOUSE_BUTTON_DOWN) &&
+                             (anEvent.AsMouseEvent()->button == WidgetMouseEvent::eLeftButton);
+  if (handled && !(leftMouseButtonDown && !mContentFocused)) {
     rv = nsEventStatus_eConsumeNoDefault;
   }
-
-  pluginWidget->EndDrawPlugin();
 #endif
 
 #ifdef XP_WIN
   // this code supports windowless plugins
   const NPEvent *pPluginEvent = static_cast<const NPEvent*>(anEvent.mPluginEvent);
   // we can get synthetic events from the EventStateManager... these
   // have no pluginEvent
   NPEvent pluginEvent;
@@ -2039,21 +2429,17 @@ void nsPluginInstanceOwner::Paint(const 
   GetContentsScaleFactor(&scaleFactor);
   if (scaleFactor != 1.0) {
     ::CGContextScaleCTM(cgContext, scaleFactor, scaleFactor);
     // Convert aDirtyRect from device pixels to "display pixels"
     // for HiDPI modes
     dirtyRectCopy.ScaleRoundOut(1.0 / scaleFactor);
   }
 
-  nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
-  if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
-    DoCocoaEventDrawRect(dirtyRectCopy, cgContext);
-    pluginWidget->EndDrawPlugin();
-  }
+  DoCocoaEventDrawRect(dirtyRectCopy, cgContext);
 }
 
 void nsPluginInstanceOwner::DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGContextRef cgContext)
 {
   if (!mInstance || !mPluginFrame)
     return;
 
   // The context given here is only valid during the HandleEvent call.
@@ -2404,36 +2790,30 @@ nsresult nsPluginInstanceOwner::Init(nsI
   mContent->AddEventListener(NS_LITERAL_STRING("dragexit"), this, true);
   mContent->AddEventListener(NS_LITERAL_STRING("dragstart"), this, true);
   mContent->AddEventListener(NS_LITERAL_STRING("draggesture"), this, true);
   mContent->AddEventListener(NS_LITERAL_STRING("dragend"), this, true);
 
   return NS_OK;
 }
 
-void* nsPluginInstanceOwner::GetPluginPortFromWidget()
+void* nsPluginInstanceOwner::GetPluginPort()
 {
 //!!! Port must be released for windowless plugins on Windows, because it is HDC !!!
 
   void* result = nullptr;
   if (mWidget) {
 #ifdef XP_WIN
     if (mPluginWindow && (mPluginWindow->type == NPWindowTypeDrawable))
       result = mWidget->GetNativeData(NS_NATIVE_GRAPHIC); // HDC
     else
 #endif
-#ifdef XP_MACOSX
-    if (GetDrawingModel() == NPDrawingModelCoreGraphics ||
-        GetDrawingModel() == NPDrawingModelCoreAnimation ||
-        GetDrawingModel() == NPDrawingModelInvalidatingCoreAnimation)
-      result = mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT_CG);
-    else
-#endif
       result = mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT); // HWND/gdk window
   }
+
   return result;
 }
 
 void nsPluginInstanceOwner::ReleasePluginPort(void * pluginPort)
 {
 #ifdef XP_WIN
   if (mWidget && mPluginWindow &&
       mPluginWindow->type == NPWindowTypeDrawable) {
@@ -2498,31 +2878,16 @@ NS_IMETHODIMP nsPluginInstanceOwner::Cre
         return rv;
       }
     }
 
 
     mWidget->EnableDragDrop(true);
     mWidget->Show(false);
     mWidget->Enable(false);
-
-#ifdef XP_MACOSX
-    // Now that we have a widget we want to set the event model before
-    // any events are processed.
-    nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
-    if (!pluginWidget) {
-      return NS_ERROR_FAILURE;
-    }
-    pluginWidget->SetPluginEventModel(GetEventModel());
-    pluginWidget->SetPluginDrawingModel(GetDrawingModel());
-
-    if (GetDrawingModel() == NPDrawingModelCoreAnimation) {
-      AddToCARefreshTimer();
-    }
-#endif
   }
 
   if (mPluginFrame) {
     // nullptr widget is fine, will result in windowless setup.
     mPluginFrame->PrepForDrawing(mWidget);
   }
 
   if (windowless) {
@@ -2543,100 +2908,65 @@ NS_IMETHODIMP nsPluginInstanceOwner::Cre
     GetPluginDescription(description);
     NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
     mFlash10Quirks = StringBeginsWith(description, flash10Head);
 #endif
   } else if (mWidget) {
     // mPluginWindow->type is used in |GetPluginPort| so it must
     // be initialized first
     mPluginWindow->type = NPWindowTypeWindow;
-    mPluginWindow->window = GetPluginPortFromWidget();
+    mPluginWindow->window = GetPluginPort();
     // tell the plugin window about the widget
     mPluginWindow->SetPluginWidget(mWidget);
 
     // tell the widget about the current plugin instance owner.
     nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
     if (pluginWidget) {
       pluginWidget->SetPluginInstanceOwner(this);
     }
   }
 
+#ifdef XP_MACOSX
+  if (GetDrawingModel() == NPDrawingModelCoreAnimation) {
+    AddToCARefreshTimer();
+  }
+#endif
+
   mWidgetCreationComplete = true;
 
   return NS_OK;
 }
 
 // Mac specific code to fix up the port location and clipping region
 #ifdef XP_MACOSX
 
-void* nsPluginInstanceOwner::FixUpPluginWindow(int32_t inPaintState)
+void nsPluginInstanceOwner::FixUpPluginWindow(int32_t inPaintState)
 {
-  if (!mWidget || !mPluginWindow || !mInstance || !mPluginFrame)
-    return nullptr;
-
-  nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
-  if (!pluginWidget)
-    return nullptr;
+  if (!mPluginWindow || !mInstance || !mPluginFrame) {
+    return;
+  }
 
   // If we've already set up a CGContext in nsPluginFrame::PaintPlugin(), we
-  // don't want calls to SetPluginPortAndDetectChange() to step on our work.
+  // don't want calls to SetPluginPort() to step on our work.
   if (mInCGPaintLevel < 1) {
-    SetPluginPortAndDetectChange();
-  }
-
-  // We'll need the top-level Cocoa window for the Cocoa event model.
-  nsIWidget* widget = mPluginFrame->GetNearestWidget();
-  if (!widget)
-    return nullptr;
-  void *cocoaTopLevelWindow = widget->GetNativeData(NS_NATIVE_WINDOW);
-  // We don't expect to have a top level window in a content process
-  if (!cocoaTopLevelWindow && XRE_GetProcessType() == GeckoProcessType_Default) {
-    return nullptr;
-  }
-
-  nsIntPoint pluginOrigin;
-  nsIntRect widgetClip;
-  bool widgetVisible;
-  pluginWidget->GetPluginClipRect(widgetClip, pluginOrigin, widgetVisible);
-  // TODO: Detect visibility for e10s mac plugins
-  if (XRE_GetProcessType() != GeckoProcessType_Default) {
-    widgetVisible = true;
+    SetPluginPort();
   }
-  mWidgetVisible = widgetVisible;
-
-  // printf("GetPluginClipRect returning visible %d\n", widgetVisible);
-
-  // This would be a lot easier if we could use obj-c here,
-  // but we can't. Since we have only nsIWidget and we can't
-  // use its native widget (an obj-c object) we have to go
-  // from the widget's screen coordinates to its window coords
-  // instead of straight to window coords.
-  nsIntPoint geckoScreenCoords = mWidget->WidgetToScreenOffset();
-
-  nsRect windowRect;
-  if (cocoaTopLevelWindow) {
-    NS_NPAPI_CocoaWindowFrame(cocoaTopLevelWindow, windowRect);
-  }
-
-  double scaleFactor = 1.0;
-  GetContentsScaleFactor(&scaleFactor);
-  int intScaleFactor = ceil(scaleFactor);
-
-  // Convert geckoScreenCoords from device pixels to "display pixels"
-  // for HiDPI modes.
-  mPluginWindow->x = geckoScreenCoords.x/intScaleFactor - windowRect.x;
-  mPluginWindow->y = geckoScreenCoords.y/intScaleFactor - windowRect.y;
+
+  nsIntSize widgetClip = mPluginFrame->GetWidgetlessClipRect().Size();
+
+  mPluginWindow->x = 0;
+  mPluginWindow->y = 0;
 
   NPRect oldClipRect = mPluginWindow->clipRect;
 
   // fix up the clipping region
-  mPluginWindow->clipRect.top    = widgetClip.y;
-  mPluginWindow->clipRect.left   = widgetClip.x;
-
-  if (!mWidgetVisible || inPaintState == ePluginPaintDisable) {
+  mPluginWindow->clipRect.top  = 0;
+  mPluginWindow->clipRect.left = 0;
+
+  if (inPaintState == ePluginPaintDisable) {
     mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top;
     mPluginWindow->clipRect.right  = mPluginWindow->clipRect.left;
   }
   else if (XRE_GetProcessType() != GeckoProcessType_Default)
   {
     // For e10s we only support async windowless plugin. This means that
     // we're always going to allocate a full window for the plugin to draw
     // for even if the plugin is mostly outside of the scroll port. Thus
@@ -2650,44 +2980,88 @@ void* nsPluginInstanceOwner::FixUpPlugin
     mPluginWindow->clipRect.right  = mPluginWindow->clipRect.left + widgetClip.width;
   }
 
   // if the clip rect changed, call SetWindow()
   // (RealPlayer needs this to draw correctly)
   if (mPluginWindow->clipRect.left    != oldClipRect.left   ||
       mPluginWindow->clipRect.top     != oldClipRect.top    ||
       mPluginWindow->clipRect.right   != oldClipRect.right  ||
-      mPluginWindow->clipRect.bottom  != oldClipRect.bottom ||
-      mPluginPortChanged)
+      mPluginWindow->clipRect.bottom  != oldClipRect.bottom)
   {
     if (UseAsyncRendering()) {
       mInstance->AsyncSetWindow(mPluginWindow);
     }
     else {
       mPluginWindow->CallSetWindow(mInstance);
     }
-    mPluginPortChanged = false;
   }
 
   // After the first NPP_SetWindow call we need to send an initial
   // top-level window focus event.
   if (!mSentInitialTopLevelWindowEvent) {
     // Set this before calling ProcessEvent to avoid endless recursion.
     mSentInitialTopLevelWindowEvent = true;
 
-    WidgetPluginEvent pluginEvent(true, NS_PLUGIN_FOCUS_EVENT, nullptr);
-    NPCocoaEvent cocoaEvent;
-    InitializeNPCocoaEvent(&cocoaEvent);
-    cocoaEvent.type = NPCocoaEventWindowFocusChanged;
-    cocoaEvent.data.focus.hasFocus = cocoaTopLevelWindow ? NS_NPAPI_CocoaWindowIsMain(cocoaTopLevelWindow) : true;
-    pluginEvent.mPluginEvent.Copy(cocoaEvent);
-    ProcessEvent(pluginEvent);
+    bool isActive = WindowIsActive();
+    SendWindowFocusChanged(isActive);
+    mLastWindowIsActive = isActive;
+  }
+}
+
+void
+nsPluginInstanceOwner::WindowFocusMayHaveChanged()
+{
+  if (!mSentInitialTopLevelWindowEvent) {
+    return;
+  }
+
+  bool isActive = WindowIsActive();
+  if (isActive != mLastWindowIsActive) {
+    SendWindowFocusChanged(isActive);
+    mLastWindowIsActive = isActive;
+  }
+}
+
+bool
+nsPluginInstanceOwner::WindowIsActive()
+{
+  if (!mPluginFrame) {
+    return false;
   }
 
-  return nullptr;
+  EventStates docState = mPluginFrame->GetContent()->OwnerDoc()->GetDocumentState();
+  return !docState.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE);
+}
+
+void
+nsPluginInstanceOwner::SendWindowFocusChanged(bool aIsActive)
+{
+  if (!mInstance) {
+    return;
+  }
+
+  NPCocoaEvent cocoaEvent;
+  InitializeNPCocoaEvent(&cocoaEvent);
+  cocoaEvent.type = NPCocoaEventWindowFocusChanged;
+  cocoaEvent.data.focus.hasFocus = aIsActive;
+  mInstance->HandleEvent(&cocoaEvent,
+                         nullptr,
+                         NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
+}
+
+void
+nsPluginInstanceOwner::ResolutionMayHaveChanged()
+{
+  double scaleFactor = 1.0;
+  GetContentsScaleFactor(&scaleFactor);
+  if (scaleFactor != mLastScaleFactor) {
+    ContentsScaleFactorChanged(scaleFactor);
+    mLastScaleFactor = scaleFactor;
+   }
 }
 
 void
 nsPluginInstanceOwner::HidePluginWindow()
 {
   if (!mPluginWindow || !mInstance) {
     return;
   }
@@ -2831,16 +3205,28 @@ void nsPluginInstanceOwner::SetFrame(nsP
 {
   // Don't do anything if the frame situation hasn't changed.
   if (mPluginFrame == aFrame) {
     return;
   }
 
   // If we already have a frame that is changing or going away...
   if (mPluginFrame) {
+    if (mContent && mContent->OwnerDoc() && mContent->OwnerDoc()->GetWindow()) {
+      nsCOMPtr<EventTarget> windowRoot = mContent->OwnerDoc()->GetWindow()->GetTopWindowRoot();
+      if (windowRoot) {
+        windowRoot->RemoveEventListener(NS_LITERAL_STRING("activate"),
+                                              this, false);
+        windowRoot->RemoveEventListener(NS_LITERAL_STRING("deactivate"),
+                                              this, false);
+        windowRoot->RemoveEventListener(NS_LITERAL_STRING("MozPerformDelayedBlur"),
+                                              this, false);
+      }
+    }
+
     // Make sure the old frame isn't holding a reference to us.
     mPluginFrame->SetInstanceOwner(nullptr);
   }
 
   // Swap in the new frame (or no frame)
   mPluginFrame = aFrame;
 
   // Set up a new frame
@@ -2854,16 +3240,29 @@ void nsPluginInstanceOwner::SetFrame(nsP
     mPluginFrame->FixupWindow(mPluginFrame->GetContentRectRelativeToSelf().Size());
     mPluginFrame->InvalidateFrame();
 
     nsFocusManager* fm = nsFocusManager::GetFocusManager();
     const nsIContent* content = aFrame->GetContent();
     if (fm && content) {
       mContentFocused = (content == fm->GetFocusedContent());
     }
+
+    // Register for widget-focus events on the window root.
+    if (mContent && mContent->OwnerDoc() && mContent->OwnerDoc()->GetWindow()) {
+      nsCOMPtr<EventTarget> windowRoot = mContent->OwnerDoc()->GetWindow()->GetTopWindowRoot();
+      if (windowRoot) {
+        windowRoot->AddEventListener(NS_LITERAL_STRING("activate"),
+                                           this, false, false);
+        windowRoot->AddEventListener(NS_LITERAL_STRING("deactivate"),
+                                           this, false, false);
+        windowRoot->AddEventListener(NS_LITERAL_STRING("MozPerformDelayedBlur"),
+                                           this, false, false);
+      }
+    }
   }
 }
 
 nsPluginFrame* nsPluginInstanceOwner::GetFrame()
 {
   return mPluginFrame;
 }
 
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -28,17 +28,22 @@ struct nsIntRect;
 class nsPluginDOMContextMenuListener;
 class nsPluginFrame;
 class nsDisplayListBuilder;
 
 namespace mozilla {
 namespace dom {
 struct MozPluginParameter;
 }
+namespace widget {
+class PuppetWidget;
 }
+}
+
+using mozilla::widget::PuppetWidget;
 
 #ifdef MOZ_X11
 class gfxXlibSurface;
 #ifdef MOZ_WIDGET_QT
 #include "gfxQtNativeRenderer.h"
 #else
 #include "gfxXlibNativeRenderer.h"
 #endif
@@ -57,16 +62,17 @@ public:
   NS_DECL_NSIPRIVACYTRANSITIONOBSERVER
   
   NS_IMETHOD GetURL(const char *aURL, const char *aTarget,
                     nsIInputStream *aPostStream, 
                     void *aHeadersData, uint32_t aHeadersDataLen) MOZ_OVERRIDE;
   
   NS_IMETHOD ShowStatus(const char16_t *aStatusMsg) MOZ_OVERRIDE;
   
+  // This can go away, just leaving it here to avoid changing the interface.
   NPError    ShowNativeContextMenu(NPMenu* menu, void* event) MOZ_OVERRIDE;
   
   NPBool     ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
                           double *destX, double *destY, NPCoordinateSpace destSpace) MOZ_OVERRIDE;
   
   /**
    * Get the type of the HTML tag that was used ot instantiate this
    * plugin.  Currently supported tags are EMBED, OBJECT and APPLET.
@@ -103,45 +109,45 @@ public:
              const gfxRect& aFrameRect,
              const gfxRect& aDirtyRect);
 #endif
 
   //locals
   
   nsresult Init(nsIContent* aContent);
   
-  void* GetPluginPortFromWidget();
+  void* GetPluginPort();
   void ReleasePluginPort(void* pluginPort);
 
   nsEventStatus ProcessEvent(const mozilla::WidgetGUIEvent& anEvent);
   
 #ifdef XP_MACOSX
   enum { ePluginPaintEnable, ePluginPaintDisable };
-  
+
+  void WindowFocusMayHaveChanged();
+  void ResolutionMayHaveChanged();
+
+  bool WindowIsActive();
+  void SendWindowFocusChanged(bool aIsActive);
   NPDrawingModel GetDrawingModel();
   bool IsRemoteDrawingCoreAnimation();
   nsresult ContentsScaleFactorChanged(double aContentsScaleFactor);
   NPEventModel GetEventModel();
   static void CARefresh(nsITimer *aTimer, void *aClosure);
   void AddToCARefreshTimer();
   void RemoveFromCARefreshTimer();
   // This calls into the plugin (NPP_SetWindow) and can run script.
-  void* FixUpPluginWindow(int32_t inPaintState);
+  void FixUpPluginWindow(int32_t inPaintState);
   void HidePluginWindow();
-  // Set a flag that (if true) indicates the plugin port info has changed and
-  // SetWindow() needs to be called.
-  void SetPluginPortChanged(bool aState) { mPluginPortChanged = aState; }
   // Return a pointer to the internal nsPluginPort structure that's used to
   // store a copy of plugin port info and to detect when it's been changed.
   void* GetPluginPortCopy();
   // Set plugin port info in the plugin (in the 'window' member of the
-  // NPWindow structure passed to the plugin by SetWindow()) and set a
-  // flag (mPluginPortChanged) to indicate whether or not this info has
-  // changed, and SetWindow() needs to be called again.
-  void* SetPluginPortAndDetectChange();
+  // NPWindow structure passed to the plugin by SetWindow()).
+  void SetPluginPort();
   // Flag when we've set up a Thebes (and CoreGraphics) context in
   // nsPluginFrame::PaintPlugin().  We need to know this in
   // FixUpPluginWindow() (i.e. we need to know when FixUpPluginWindow() has
   // been called from nsPluginFrame::PaintPlugin() when we're using the
   // CoreGraphics drawing model).
   void BeginCGPaint();
   void EndCGPaint();
 #else // XP_MACOSX
@@ -283,27 +289,29 @@ private:
   NP_CGContext                              mCGPluginPortCopy;
   int32_t                                   mInCGPaintLevel;
   mozilla::RefPtr<MacIOSurface>             mIOSurface;
   mozilla::RefPtr<nsCARenderer>             mCARenderer;
   CGColorSpaceRef                           mColorProfile;
   static nsCOMPtr<nsITimer>                *sCATimer;
   static nsTArray<nsPluginInstanceOwner*>  *sCARefreshListeners;
   bool                                      mSentInitialTopLevelWindowEvent;
+  bool                                      mLastWindowIsActive;
+  bool                                      mLastContentFocused;
+  double                                    mLastScaleFactor;
+  // True if, the next time the window is activated, we should blur ourselves.
+  bool                                      mShouldBlurOnActivate;
 #endif
 
   // Initially, the event loop nesting level we were created on, it's updated
   // if we detect the appshell is on a lower level as long as we're not stopped.
   // We delay DoStopPlugin() until the appshell reaches this level or lower.
   uint32_t                    mLastEventloopNestingLevel;
   bool                        mContentFocused;
   bool                        mWidgetVisible;    // used on Mac to store our widget's visible state
-#ifdef XP_MACOSX
-  bool                        mPluginPortChanged;
-#endif
 #ifdef MOZ_X11
   // Used with windowless plugins only, initialized in CreateWidget().
   bool                        mFlash10Quirks;
 #endif
   bool                        mPluginWindowVisible;
   bool                        mPluginDocumentActiveState;
 
 #ifdef XP_MACOSX
@@ -318,16 +326,26 @@ private:
   // pointer to wrapper for nsIDOMContextMenuListener
   nsRefPtr<nsPluginDOMContextMenuListener> mCXMenuListener;
   
   nsresult DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent);
   nsresult DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent,
                                  bool aAllowPropagate = false);
   nsresult DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent);
 
+#ifdef XP_MACOSX
+  static NPBool ConvertPointPuppet(PuppetWidget *widget, nsPluginFrame* pluginFrame,
+                            double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
+                            double *destX, double *destY, NPCoordinateSpace destSpace);
+  static NPBool ConvertPointNoPuppet(nsIWidget *widget, nsPluginFrame* pluginFrame,
+                            double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
+                            double *destX, double *destY, NPCoordinateSpace destSpace);
+  void PerformDelayedBlurs();
+#endif    // XP_MACOSX
+
   int mLastMouseDownButtonType;
 
 #ifdef MOZ_X11
   class Renderer
 #if defined(MOZ_WIDGET_QT)
   : public gfxQtNativeRenderer
 #else
   : public gfxXlibNativeRenderer
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -383,22 +383,22 @@ PluginInstanceChild::NPN_GetValue(NPNVar
 
 #ifdef XP_MACOSX
    case NPNVsupportsCoreGraphicsBool: {
         *((NPBool*)aValue) = true;
         return NPERR_NO_ERROR;
     }
 
     case NPNVsupportsCoreAnimationBool: {
-        *((NPBool*)aValue) = nsCocoaFeatures::SupportCoreAnimationPlugins();
+        *((NPBool*)aValue) = true;
         return NPERR_NO_ERROR;
     }
 
     case NPNVsupportsInvalidatingCoreAnimationBool: {
-        *((NPBool*)aValue) = nsCocoaFeatures::SupportCoreAnimationPlugins();
+        *((NPBool*)aValue) = true;
         return NPERR_NO_ERROR;
     }
 
     case NPNVsupportsCompositingCoreAnimationPluginsBool: {
         *((NPBool*)aValue) = true;
         return NPERR_NO_ERROR;
     }
 
--- a/dom/plugins/ipc/PluginUtilsOSX.mm
+++ b/dom/plugins/ipc/PluginUtilsOSX.mm
@@ -215,36 +215,42 @@ NPError mozilla::plugins::PluginUtilsOSX
   // Set the native cursor to the OS default (an arrow) before displaying the
   // context menu.  Otherwise (if the plugin has changed the cursor) it may
   // stay as the plugin has set it -- which means it may be invisible.  We
   // need to do this because we display the context menu without making the
   // plugin process the foreground process.  If we did, the cursor would
   // change to an arrow cursor automatically -- as it does in Chrome.
   [[NSCursor arrowCursor] set];
 
-  // Create a timer to process browser events while waiting
-  // on the menu. This prevents the browser from hanging
-  // during the lifetime of the menu.
-  EventProcessor* eventProcessor = [[EventProcessor alloc] init];
-  [eventProcessor setRemoteEvents:remoteEvent pluginModule:pluginModule];
-  NSTimer *eventTimer = [NSTimer timerWithTimeInterval:EVENT_PROCESS_DELAY
-                             target:eventProcessor selector:@selector(onTick) 
-                             userInfo:nil repeats:TRUE];
-  // Use NSEventTrackingRunLoopMode otherwise the timer will
-  // not fire during the right click menu.
-  [[NSRunLoop currentRunLoop] addTimer:eventTimer 
-                              forMode:NSEventTrackingRunLoopMode];
+  EventProcessor* eventProcessor = nullptr;
+  NSTimer *eventTimer = nullptr;
+  if (pluginModule) {
+    // Create a timer to process browser events while waiting
+    // on the menu. This prevents the browser from hanging
+    // during the lifetime of the menu.
+    eventProcessor = [[EventProcessor alloc] init];
+    [eventProcessor setRemoteEvents:remoteEvent pluginModule:pluginModule];
+    eventTimer = [NSTimer timerWithTimeInterval:EVENT_PROCESS_DELAY
+                                   target:eventProcessor selector:@selector(onTick)
+                                   userInfo:nil repeats:TRUE];
+    // Use NSEventTrackingRunLoopMode otherwise the timer will
+    // not fire during the right click menu.
+    [[NSRunLoop currentRunLoop] addTimer:eventTimer
+                                 forMode:NSEventTrackingRunLoopMode];
+  }
 
   NSMenu* nsmenu = reinterpret_cast<NSMenu*>(aMenu);
   NSPoint screen_point = ::NSMakePoint(aX, aY);
 
   [nsmenu popUpMenuPositioningItem:nil atLocation:screen_point inView:nil];
 
-  [eventTimer invalidate];
-  [eventProcessor release];
+  if (pluginModule) {
+    [eventTimer invalidate];
+    [eventProcessor release];
+  }
 
   return NPERR_NO_ERROR;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NPERR_GENERIC_ERROR);
 }
 
 void mozilla::plugins::PluginUtilsOSX::InvokeNativeEventLoop()
 {
--- a/dom/plugins/test/mochitest/cocoa_focus.html
+++ b/dom/plugins/test/mochitest/cocoa_focus.html
@@ -54,64 +54,64 @@
       }
       is(initialStateUnknown, true, "Initial state should be unknown, assumed false.");
 
       // Give the plugin focus (the window is already focused).
       utils.sendNativeMouseEvent(plugin1X, plugin1Y, NSLeftMouseDown, 0, plugin1);
       utils.sendNativeMouseEvent(plugin1X, plugin1Y, NSLeftMouseUp, 0, plugin1);
       expectedEventCount++;
 
-      is(plugin1.getFocusState(), true, "Plugin should have focus.");
+      is(plugin1.getFocusState(), true, "(1) Plugin should have focus.");
       is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
 
       // Make sure window activation state changes don't spontaneously
       // change plugin focus.
 
       // Blur the window.
       window.blur();
 
-      is(plugin1.getFocusState(), true, "Plugin should still have focus.");
+      is(plugin1.getFocusState(), true, "(2) Plugin should still have focus.");
       is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
 
       // Focus the window.
       window.focus();
 
-      is(plugin1.getFocusState(), true, "Plugin should still have focus.");
+      is(plugin1.getFocusState(), true, "(3) Plugin should still have focus.");
       is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
 
       // Take focus from the plugin.
       utils.sendNativeMouseEvent(plugin2X, plugin2Y, NSLeftMouseDown, 0, plugin2);
       utils.sendNativeMouseEvent(plugin2X, plugin2Y, NSLeftMouseUp, 0, plugin2);
       expectedEventCount++;
 
-      is(plugin1.getFocusState(), false, "Plugin should not have focus.");
+      is(plugin1.getFocusState(), false, "(4) Plugin should not have focus.");
       is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
 
       // Make sure window activation causes the plugin to be informed of focus
       // changes that took place while the window was inactive.
 
       // Give the plugin focus (the window is already focused).
       utils.sendNativeMouseEvent(plugin1X, plugin1Y, NSLeftMouseDown, 0, plugin1);
       utils.sendNativeMouseEvent(plugin1X, plugin1Y, NSLeftMouseUp, 0, plugin1);
       expectedEventCount++;
 
       // Blur the window.
       window.blur();
 
       // Take focus from the plugin while the window is blurred.
       plugin2.focus();
 
-      is(plugin1.getFocusState(), true, "Plugin should still have focus.");
+      is(plugin1.getFocusState(), true, "(5) Plugin should still have focus.");
       is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
 
       // Focus the window.
       window.focus();
       expectedEventCount++;
 
-      is(plugin1.getFocusState(), false, "Plugin should not have focus.");
+      is(plugin1.getFocusState(), false, "(6) Plugin should not have focus.");
       is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
 
       window.opener.testsFinished();
     }
 
     // Onload hander doesn't work for these tests -- no events arrive at the plugin.
     window.opener.SimpleTest.waitForFocus(runTests, window);
 
--- a/dom/plugins/test/mochitest/test_convertpoint.xul
+++ b/dom/plugins/test/mochitest/test_convertpoint.xul
@@ -24,21 +24,20 @@ function runTests() {
   // the plugin hasn't been placed yet.
   if (pluginElement.convertPointX(1, 0, 0, 2) == 0) {
     setTimeout(runTests, 0);
     return;
   }
 
   var domWindowUtils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                              .getInterface(Components.interfaces.nsIDOMWindowUtils);
-  var devPxPerCSSPx = domWindowUtils.screenPixelsPerCSSPixel;
 
   var pluginRect = pluginElement.getBoundingClientRect();
-  var pluginX = (pluginRect.left * devPxPerCSSPx) + ((window.mozInnerScreenX * devPxPerCSSPx) - window.screenX);
-  var pluginY = (pluginRect.top * devPxPerCSSPx) + ((window.mozInnerScreenY * devPxPerCSSPx) - window.screenY);
+  var pluginX = pluginRect.left + (window.mozInnerScreenX - window.screenX);
+  var pluginY = pluginRect.top + (window.mozInnerScreenY - window.screenY);
 
   var windowX = window.screenX;
   var windowY = window.screenY;
   var windowHeight = window.outerHeight;
 
   var screenHeight = window.screen.height;
 
   // arbitrary coordinates of test point in plugin top-left origin terms
--- a/dom/plugins/test/testplugin/nptest.cpp
+++ b/dom/plugins/test/testplugin/nptest.cpp
@@ -3389,17 +3389,17 @@ getTopLevelWindowActivationEventCount(NP
   InstanceData* id = static_cast<InstanceData*>(npp->pdata);
 
   INT32_TO_NPVARIANT(id->topLevelWindowActivationEventCount, *result);
 
   return true;
 }
 
 // Returns top-level window activation state as indicated by Cocoa NPAPI's
-// NPCocoaEventWindowFocusChanged events - 'true' if active, 'false' if not.
+// NPCocoaEventFocusChanged events - 'true' if active, 'false' if not.
 // Throws an exception if no events have been received and thus this state
 // is unknown.
 bool
 getFocusState(NPObject* npobj, const NPVariant* args, uint32_t argCount,
               NPVariant* result)
 {
   if (argCount != 0)
     return false;
--- a/dom/plugins/test/testplugin/nptest_macosx.mm
+++ b/dom/plugins/test/testplugin/nptest_macosx.mm
@@ -233,16 +233,17 @@ pluginHandleEvent(InstanceData* instance
 
   switch (cocoaEvent->type) {
     case NPCocoaEventDrawRect:
       pluginDraw(instanceData, cocoaEvent);
       break;
     case NPCocoaEventMouseDown:
     case NPCocoaEventMouseUp:
     case NPCocoaEventMouseMoved:
+    case NPCocoaEventMouseDragged:
       instanceData->lastMouseX = (int32_t)cocoaEvent->data.mouse.pluginX;
       instanceData->lastMouseY = (int32_t)cocoaEvent->data.mouse.pluginY;
       if (cocoaEvent->type == NPCocoaEventMouseUp) {
         instanceData->mouseUpEventCount++;
       }
       break;
     case NPCocoaEventWindowFocusChanged:
       instanceData->topLevelWindowActivationState = cocoaEvent->data.focus.hasFocus ?
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -2926,16 +2926,18 @@ void
 nsRootPresContext::CancelApplyPluginGeometryTimer()
 {
   if (mApplyPluginGeometryTimer) {
     mApplyPluginGeometryTimer->Cancel();
     mApplyPluginGeometryTimer = nullptr;
   }
 }
 
+#ifndef XP_MACOSX
+
 static bool
 HasOverlap(const nsIntPoint& aOffset1, const nsTArray<nsIntRect>& aClipRects1,
            const nsIntPoint& aOffset2, const nsTArray<nsIntRect>& aClipRects2)
 {
   nsIntPoint offsetDelta = aOffset1 - aOffset2;
   for (uint32_t i = 0; i < aClipRects1.Length(); ++i) {
     for (uint32_t j = 0; j < aClipRects2.Length(); ++j) {
       if ((aClipRects1[i] + offsetDelta).Intersects(aClipRects2[j]))
@@ -2994,28 +2996,16 @@ SortConfigurations(nsTArray<nsIWidget::C
     }
     // Note that we always move the last plugin in pluginsToMove, if we
     // can't find any other plugin to move
     aConfigurations->AppendElement(pluginsToMove[i]);
     pluginsToMove.RemoveElementAt(i);
   }
 }
 
-static PLDHashOperator
-PluginDidSetGeometryEnumerator(nsRefPtrHashKey<nsIContent>* aEntry, void* userArg)
-{
-  nsPluginFrame* f = static_cast<nsPluginFrame*>(aEntry->GetKey()->GetPrimaryFrame());
-  if (!f) {
-    NS_WARNING("Null frame in PluginDidSetGeometryEnumerator");
-    return PL_DHASH_NEXT;
-  }
-  f->DidSetWidgetGeometry();
-  return PL_DHASH_NEXT;
-}
-
 struct PluginGetGeometryUpdateClosure {
   nsTArray<nsIWidget::Configuration> mConfigurations;
 };
 static PLDHashOperator
 PluginGetGeometryUpdate(nsRefPtrHashKey<nsIContent>* aEntry, void* userArg)
 {
   PluginGetGeometryUpdateClosure* closure =
     static_cast<PluginGetGeometryUpdateClosure*>(userArg);
@@ -3023,30 +3013,47 @@ PluginGetGeometryUpdate(nsRefPtrHashKey<
   if (!f) {
     NS_WARNING("Null frame in GetPluginGeometryUpdate");
     return PL_DHASH_NEXT;
   }
   f->GetWidgetConfiguration(&closure->mConfigurations);
   return PL_DHASH_NEXT;
 }
 
+#endif  // #ifndef XP_MACOSX
+
+static PLDHashOperator
+PluginDidSetGeometryEnumerator(nsRefPtrHashKey<nsIContent>* aEntry, void* userArg)
+{
+  nsPluginFrame* f = static_cast<nsPluginFrame*>(aEntry->GetKey()->GetPrimaryFrame());
+  if (!f) {
+    NS_WARNING("Null frame in PluginDidSetGeometryEnumerator");
+    return PL_DHASH_NEXT;
+  }
+  f->DidSetWidgetGeometry();
+  return PL_DHASH_NEXT;
+}
+
 void
 nsRootPresContext::ApplyPluginGeometryUpdates()
 {
+#ifndef XP_MACOSX
   CancelApplyPluginGeometryTimer();
 
   PluginGetGeometryUpdateClosure closure;
   mRegisteredPlugins.EnumerateEntries(PluginGetGeometryUpdate, &closure);
   // Walk mRegisteredPlugins and ask each plugin for its configuration
   if (!closure.mConfigurations.IsEmpty()) {
     nsIWidget* widget = closure.mConfigurations[0].mChild->GetParent();
     NS_ASSERTION(widget, "Plugins must have a parent window");
     SortConfigurations(&closure.mConfigurations);
     widget->ConfigureChildren(closure.mConfigurations);
   }
+#endif  // #ifndef XP_MACOSX
+
   mRegisteredPlugins.EnumerateEntries(PluginDidSetGeometryEnumerator, nullptr);
 }
 
 static void
 NotifyDidPaintForSubtreeCallback(nsITimer *aTimer, void *aClosure)
 {
   nsPresContext* presContext = (nsPresContext*)aClosure;
   nsAutoScriptBlocker blockScripts;
--- a/layout/generic/moz.build
+++ b/layout/generic/moz.build
@@ -101,21 +101,16 @@ UNIFIED_SOURCES += [
 
 # nsLineLayout.cpp needs to be built separately because it uses plarena.h.
 # nsPluginFrame.cpp needs to be built separately because of name clashes in the OS X headers.
 SOURCES += [
     'nsLineLayout.cpp',
     'nsPluginFrame.cpp',
 ]
 
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
-    UNIFIED_SOURCES += [
-        'nsPluginUtilsOSX.mm',
-    ]
-
 FAIL_ON_WARNINGS = not CONFIG['_MSC_VER']
 
 MSVC_ENABLE_PGO = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
--- a/layout/generic/nsPluginFrame.cpp
+++ b/layout/generic/nsPluginFrame.cpp
@@ -64,17 +64,16 @@
 
 #ifdef MOZ_LOGGING
 #define FORCE_PR_LOG 1 /* Allow logging in the release build */
 #endif /* MOZ_LOGGING */
 #include "prlog.h"
 
 #ifdef XP_MACOSX
 #include "gfxQuartzNativeDrawing.h"
-#include "nsPluginUtilsOSX.h"
 #include "mozilla/gfx/QuartzSupport.h"
 #endif
 
 #ifdef MOZ_X11
 #include "mozilla/X11Util.h"
 using mozilla::DefaultXDisplay;
 #endif
 
@@ -98,53 +97,16 @@ GetObjectFrameLog()
 {
   static PRLogModuleInfo *sLog;
   if (!sLog)
     sLog = PR_NewLogModule("nsPluginFrame");
   return sLog;
 }
 #endif /* PR_LOGGING */
 
-#if defined(XP_MACOSX) && !defined(__LP64__)
-
-// The header files QuickdrawAPI.h and QDOffscreen.h are missing on OS X 10.7
-// and up (though the QuickDraw APIs defined in them are still present) -- so
-// we need to supply the relevant parts of their contents here.  It's likely
-// that Apple will eventually remove the APIs themselves (probably in OS X
-// 10.8), so we need to make them weak imports, and test for their presence
-// before using them.
-extern "C" {
-  #if !defined(__QUICKDRAWAPI__)
-  extern void SetRect(
-    Rect * r,
-    short  left,
-    short  top,
-    short  right,
-    short  bottom)
-    __attribute__((weak_import));
-  #endif /* __QUICKDRAWAPI__ */
-
-  #if !defined(__QDOFFSCREEN__)
-  extern QDErr NewGWorldFromPtr(
-    GWorldPtr *   offscreenGWorld,
-    UInt32        PixelFormat,
-    const Rect *  boundsRect,
-    CTabHandle    cTable,                /* can be nullptr */
-    GDHandle      aGDevice,              /* can be nullptr */
-    GWorldFlags   flags,
-    Ptr           newBuffer,
-    SInt32        rowBytes)
-    __attribute__((weak_import));
-  extern void DisposeGWorld(GWorldPtr offscreenGWorld)
-    __attribute__((weak_import));
-  #endif /* __QDOFFSCREEN__ */
-}
-
-#endif /* #if defined(XP_MACOSX) && !defined(__LP64__) */
-
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 
 class PluginBackgroundSink : public ReadbackSink {
 public:
   PluginBackgroundSink(nsPluginFrame* aFrame, uint64_t aStartSequenceNumber)
     : mLastSequenceNumber(aStartSequenceNumber), mFrame(aFrame) {}
@@ -215,17 +177,17 @@ a11y::AccType
 nsPluginFrame::AccessibleType()
 {
   return a11y::ePluginType;
 }
 
 #ifdef XP_WIN
 NS_IMETHODIMP nsPluginFrame::GetPluginPort(HWND *aPort)
 {
-  *aPort = (HWND) mInstanceOwner->GetPluginPortFromWidget();
+  *aPort = (HWND) mInstanceOwner->GetPluginPort();
   return NS_OK;
 }
 #endif
 #endif
 
 void
 nsPluginFrame::Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
@@ -383,20 +345,17 @@ nsPluginFrame::PrepForDrawing(nsIWidget 
       if (NS_GET_A(bgcolor) > 0) {  // make sure we got an actual color
         mWidget->SetBackgroundColor(bgcolor);
         break;
       }
     }
   } else {
     // Changing to windowless mode changes the NPWindow geometry.
     FixupWindow(GetContentRectRelativeToSelf().Size());
-
-#ifndef XP_MACOSX
     RegisterPluginForGeometryUpdates();
-#endif
   }
 
   if (!IsHidden()) {
     viewMan->SetViewVisibility(view, nsViewVisibility_kShow);
   }
 
 #ifdef ACCESSIBILITY
   nsAccessibilityService* accService = nsIPresShell::AccService();
@@ -572,48 +531,32 @@ nsPluginFrame::FixupWindow(const nsSize&
   if (!mInstanceOwner)
     return;
 
   NPWindow *window;
   mInstanceOwner->GetWindow(window);
 
   NS_ENSURE_TRUE_VOID(window);
 
-#ifdef XP_MACOSX
-  nsWeakFrame weakFrame(this);
-  mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintDisable);
-  if (!weakFrame.IsAlive()) {
-    return;
-  }
-#endif
-
   bool windowless = (window->type == NPWindowTypeDrawable);
 
   nsIntPoint origin = GetWindowOriginInPixels(windowless);
 
   // window must be in "display pixels"
   double scaleFactor = 1.0;
   if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
     scaleFactor = 1.0;
   }
   int intScaleFactor = ceil(scaleFactor);
   window->x = origin.x / intScaleFactor;
   window->y = origin.y / intScaleFactor;
   window->width = presContext->AppUnitsToDevPixels(aSize.width) / intScaleFactor;
   window->height = presContext->AppUnitsToDevPixels(aSize.height) / intScaleFactor;
 
-  // on the Mac we need to set the clipRect to { 0, 0, 0, 0 } for now. This will keep
-  // us from drawing on screen until the widget is properly positioned, which will not
-  // happen until we have finished the reflow process.
-#ifdef XP_MACOSX
-  window->clipRect.top = 0;
-  window->clipRect.left = 0;
-  window->clipRect.bottom = 0;
-  window->clipRect.right = 0;
-#else
+#ifndef XP_MACOSX
   mInstanceOwner->UpdateWindowPositionAndClipRect(false);
 #endif
 
   NotifyPluginReflowObservers();
 }
 
 nsresult
 nsPluginFrame::CallSetWindow(bool aCheckIsHidden)
@@ -625,29 +568,25 @@ nsPluginFrame::CallSetWindow(bool aCheck
   if (!mInstanceOwner ||
       NS_FAILED(rv = mInstanceOwner->GetInstance(getter_AddRefs(pi))) ||
       !pi ||
       NS_FAILED(rv = mInstanceOwner->GetWindow(win)) || 
       !win)
     return rv;
 
   nsPluginNativeWindow *window = (nsPluginNativeWindow *)win;
-#ifdef XP_MACOSX
-  nsWeakFrame weakFrame(this);
-  mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintDisable);
-  if (!weakFrame.IsAlive()) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-#endif
 
   if (aCheckIsHidden && IsHidden())
     return NS_ERROR_FAILURE;
 
   // refresh the plugin port as well
-  window->window = mInstanceOwner->GetPluginPortFromWidget();
+#ifdef XP_MACOSX
+  mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable);
+#endif
+  window->window = mInstanceOwner->GetPluginPort();
 
   // Adjust plugin dimensions according to pixel snap results
   // and reduce amount of SetWindow calls
   nsPresContext* presContext = PresContext();
   nsRootPresContext* rootPC = presContext->GetRootPresContext();
   if (!rootPC)
     return NS_ERROR_FAILURE;
   int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
@@ -1059,53 +998,49 @@ void
 nsPluginFrame::NotifyPluginReflowObservers()
 {
   nsContentUtils::AddScriptRunner(new PluginEventNotifier(NS_LITERAL_STRING("reflow")));
 }
 
 void
 nsPluginFrame::DidSetWidgetGeometry()
 {
-#if defined(XP_MACOSX)
-  if (mInstanceOwner) {
-    mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable);
-  }
-#else
+#ifndef XP_MACOSX
   if (!mWidget && mInstanceOwner) {
     // UpdateWindowVisibility will notify the plugin of position changes
     // by updating the NPWindow and calling NPP_SetWindow/AsyncSetWindow.
     // We treat windowless plugins inside popups as always visible, since
     // plugins inside popups don't get valid mNextConfigurationBounds
     // set up.
     mInstanceOwner->UpdateWindowVisibility(
       nsLayoutUtils::IsPopup(nsLayoutUtils::GetDisplayRootFrame(this)) ||
       !mNextConfigurationBounds.IsEmpty());
   }
+#else
+  CallSetWindow(false);
 #endif
 }
 
 bool
 nsPluginFrame::IsOpaque() const
 {
 #if defined(XP_MACOSX)
-  // ???
   return false;
 #elif defined(MOZ_WIDGET_ANDROID)
   // We don't know, so just assume transparent
   return false;
 #else
   return !IsTransparentMode();
 #endif
 }
 
 bool
 nsPluginFrame::IsTransparentMode() const
 {
 #if defined(XP_MACOSX)
-  // ???
   return false;
 #else
   if (!mInstanceOwner)
     return false;
 
   NPWindow *window = nullptr;
   mInstanceOwner->GetWindow(window);
   if (!window) {
@@ -1148,27 +1083,33 @@ nsPluginFrame::BuildDisplayList(nsDispla
 
 #ifndef XP_MACOSX
   if (mWidget && aBuilder->IsInTransform()) {
     // Windowed plugins should not be rendered inside a transform.
     return;
   }
 #endif
 
-  if (aBuilder->IsForPainting() && mInstanceOwner && mInstanceOwner->UseAsyncRendering()) {
-    NPWindow* window = nullptr;
-    mInstanceOwner->GetWindow(window);
-    bool isVisible = window && window->width > 0 && window->height > 0;
-    if (isVisible && aBuilder->ShouldSyncDecodeImages()) {
-  #ifndef XP_MACOSX
-      mInstanceOwner->UpdateWindowVisibility(true);
-  #endif
+  if (aBuilder->IsForPainting() && mInstanceOwner) {
+#ifdef XP_MACOSX
+    mInstanceOwner->ResolutionMayHaveChanged();
+    mInstanceOwner->WindowFocusMayHaveChanged();
+#endif
+    if (mInstanceOwner->UseAsyncRendering()) {
+      NPWindow* window = nullptr;
+      mInstanceOwner->GetWindow(window);
+      bool isVisible = window && window->width > 0 && window->height > 0;
+      if (isVisible && aBuilder->ShouldSyncDecodeImages()) {
+#ifndef XP_MACOSX
+        mInstanceOwner->UpdateWindowVisibility(true);
+#endif
+      }
+
+      mInstanceOwner->NotifyPaintWaiter(aBuilder);
     }
-
-    mInstanceOwner->NotifyPaintWaiter(aBuilder);
   }
 
   DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
     clip(aBuilder, this);
 
   // determine if we are printing
   if (type == nsPresContext::eContext_Print) {
     aLists.Content()->AppendNewToTop(new (aBuilder)
@@ -1248,127 +1189,20 @@ nsPluginFrame::PrintPlugin(nsRenderingCo
   bool windowless = false;
   pi->IsWindowless(&windowless);
   window.type = windowless ? NPWindowTypeDrawable : NPWindowTypeWindow;
 
   window.clipRect.bottom = 0; window.clipRect.top = 0;
   window.clipRect.left = 0; window.clipRect.right = 0;
 
 // platform specific printing code
-#if defined(XP_MACOSX) && !defined(__LP64__)
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-  DrawTarget& aDrawTarget = *aRenderingContext.GetDrawTarget();
-
-  // Don't use this code if any of the QuickDraw APIs it currently requires
-  // are missing (as they probably will be on OS X 10.8 and up).
-  if (!&::SetRect || !&::NewGWorldFromPtr || !&::DisposeGWorld) {
-    NS_WARNING("Cannot print plugin -- required QuickDraw APIs are missing!");
-    return;
-  }
-
-  nsSize contentSize = GetContentRectRelativeToSelf().Size();
-  window.x = 0;
-  window.y = 0;
-  window.width = presContext->AppUnitsToDevPixels(contentSize.width);
-  window.height = presContext->AppUnitsToDevPixels(contentSize.height);
-
-  gfxContext *ctx = aRenderingContext.ThebesContext();
-  if (!ctx)
-    return;
-  gfxContextAutoSaveRestore save(ctx);
-
-  ctx->NewPath();
-
-  gfx::Rect rect(window.x, window.y, window.width, window.height);
-
-  ctx->Rectangle(ThebesRect(rect));
-  ctx->Clip();
-
-  gfxQuartzNativeDrawing nativeDraw(aDrawTarget, rect);
-  CGContextRef cgContext = nativeDraw.BeginNativeDrawing();
-  if (!cgContext) {
-    nativeDraw.EndNativeDrawing();
-    return;
-  }
-
-  window.clipRect.right = window.width;
-  window.clipRect.bottom = window.height;
-  window.type = NPWindowTypeDrawable;
-
-  ::Rect gwBounds;
-  ::SetRect(&gwBounds, 0, 0, window.width, window.height);
-
-  nsTArray<char> buffer(window.width * window.height * 4);
-  CGColorSpaceRef cspace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
-  if (!cspace) {
-    nativeDraw.EndNativeDrawing();
-    return;
-  }
-  CGContextRef cgBuffer =
-    ::CGBitmapContextCreate(buffer.Elements(), 
-                            window.width, window.height, 8, window.width * 4,
-                            cspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedFirst);
-  ::CGColorSpaceRelease(cspace);
-  if (!cgBuffer) {
-    nativeDraw.EndNativeDrawing();
-    return;
-  }
-  GWorldPtr gWorld;
-  if (::NewGWorldFromPtr(&gWorld, k32ARGBPixelFormat, &gwBounds,
-                         nullptr, nullptr, 0,
-                         buffer.Elements(), window.width * 4) != noErr) {
-    ::CGContextRelease(cgBuffer);
-    nativeDraw.EndNativeDrawing();
-    return;
-  }
-
-  window.clipRect.right = window.width;
-  window.clipRect.bottom = window.height;
-  window.type = NPWindowTypeDrawable;
-  // Setting nsPluginPrint/NPPrint.print.embedPrint.window.window to
-  // &GWorldPtr and nsPluginPrint/NPPrint.print.embedPrint.platformPrint to
-  // GWorldPtr isn't any kind of standard (it's not documented anywhere).
-  // But that's what WebKit does.  And it's what the Flash plugin (apparently
-  // the only NPAPI plugin on OS X to support printing) seems to expect.  So
-  // we do the same.  The Flash plugin uses the CoreGraphics drawing mode.
-  // But a GWorldPtr should be usable in either CoreGraphics or QuickDraw
-  // drawing mode.  See bug 191046.
-  window.window = &gWorld;
-  npprint.print.embedPrint.platformPrint = gWorld;
-  npprint.print.embedPrint.window = window;
-  pi->Print(&npprint);
-
-  ::CGContextTranslateCTM(cgContext, 0.0f, float(window.height));
-  ::CGContextScaleCTM(cgContext, 1.0f, -1.0f);
-  CGImageRef image = ::CGBitmapContextCreateImage(cgBuffer);
-  if (!image) {
-    ::CGContextRestoreGState(cgContext);
-    ::CGContextRelease(cgBuffer);
-    ::DisposeGWorld(gWorld);
-    nativeDraw.EndNativeDrawing();
-    return;
-  }
-  ::CGContextDrawImage(cgContext,
-                       ::CGRectMake(0, 0, window.width, window.height),
-                       image);
-  ::CGImageRelease(image);
-  ::CGContextRelease(cgBuffer);
-
-  ::DisposeGWorld(gWorld);
-
-  nativeDraw.EndNativeDrawing();
-#pragma clang diagnostic warning "-Wdeprecated-declarations"
-#elif defined(XP_UNIX)
-
-  /* XXX this just flat-out doesn't work in a thebes world --
-   * RenderEPS is a no-op.  So don't bother to do any work here.
-   */
+#if defined(XP_UNIX) || defined(XP_MACOSX)
+  // Doesn't work in a thebes world, or on OS X.
   (void)window;
   (void)npprint;
-
 #elif defined(XP_WIN)
 
   /* On Windows, we use the win32 printing surface to print.  This, in
    * turn, uses the Cairo paginated surface, which in turn uses the
    * meta surface to record all operations and then play them back.
    * This doesn't work too well for plugins, because if plugins render
    * directly into the DC, the meta surface won't have any knowledge
    * of them, and so at the end when it actually does the replay step,
@@ -1856,25 +1690,16 @@ nsPluginFrame::HandleEvent(nsPresContext
       return fm->SetFocus(elem, 0);
   }
   else if (anEvent->message == NS_PLUGIN_FOCUS) {
     nsIFocusManager* fm = nsFocusManager::GetFocusManager();
     if (fm)
       return fm->FocusPlugin(GetContent());
   }
 
-#ifdef XP_MACOSX
-  if (anEvent->message == NS_PLUGIN_RESOLUTION_CHANGED) {
-    double scaleFactor = 1.0;
-    mInstanceOwner->GetContentsScaleFactor(&scaleFactor);
-    mInstanceOwner->ContentsScaleFactorChanged(scaleFactor);
-    return NS_OK;
-  }
-#endif
-
   if (mInstanceOwner->SendNativeEvents() &&
       anEvent->IsNativeEventDelivererForPlugin()) {
     *anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
     // Due to plugin code reentering Gecko, this frame may be dead at this
     // point.
     return rv;
   }
 
@@ -2029,23 +1854,17 @@ nsPluginFrame::EndSwapDocShells(nsISuppo
     widget->SetParent(parent);
     nsWeakFrame weakFrame(objectFrame);
     objectFrame->CallSetWindow();
     if (!weakFrame.IsAlive()) {
       return;
     }
   }
 
-#ifdef XP_MACOSX
-  if (objectFrame->mWidget) {
-    objectFrame->RegisterPluginForGeometryUpdates();
-  }
-#else
   objectFrame->RegisterPluginForGeometryUpdates();
-#endif
 }
 
 nsIFrame*
 NS_NewObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsPluginFrame(aContext);
 }
 
--- a/layout/generic/nsPluginFrame.h
+++ b/layout/generic/nsPluginFrame.h
@@ -133,16 +133,21 @@ public:
         return;
       }
       nsIWidget::Configuration* configuration = aConfigurations->AppendElement();
       configuration->mChild = mWidget;
       configuration->mBounds = mNextConfigurationBounds;
       configuration->mClipRegion = mNextConfigurationClipRegion;
     }
   }
+
+  nsIntRect GetWidgetlessClipRect() {
+    return RegionFromArray(mNextConfigurationClipRegion).GetBounds();
+  }
+
   /**
    * Called after all widget position/size/clip regions have been changed
    * (even if there isn't a widget for this plugin).
    */
   void DidSetWidgetGeometry();
 
   // accessibility support
 #ifdef ACCESSIBILITY
@@ -253,16 +258,25 @@ private:
   // mRootPresContextRegisteredWith, so that we can be sure we unregister
   // from the right root prest context in UnregisterPluginForGeometryUpdates.
   void RegisterPluginForGeometryUpdates();
 
   // Unregisters the plugin for geometry updated with the root pres context
   // stored in mRootPresContextRegisteredWith.
   void UnregisterPluginForGeometryUpdates();
 
+  static const nsIntRegion RegionFromArray(const nsTArray<nsIntRect>& aRects)
+  {
+    nsIntRegion region;
+    for (uint32_t i = 0; i < aRects.Length(); ++i) {
+      region.Or(region, aRects[i]);
+    }
+    return region;
+  }
+
   class PluginEventNotifier : public nsRunnable {
   public:
     explicit PluginEventNotifier(const nsString &aEventType) : 
       mEventType(aEventType) {}
     
     NS_IMETHOD Run() MOZ_OVERRIDE;
   private:
     nsString mEventType;
deleted file mode 100644
--- a/layout/generic/nsPluginUtilsOSX.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-// vim:set ts=2 sts=2 sw=2 et cin:
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// We can use Carbon in this header but not Cocoa. Cocoa pointers must be void.
-
-#ifndef __LP64__
-#import <Carbon/Carbon.h>
-#endif
-
-#include "nsIWidget.h"
-#include "npapi.h"
-
-struct nsRect;
-
-// We use void pointers to avoid exporting native event types to cross-platform code.
-
-#ifndef __LP64__
-// Get the rect for an entire top-level Carbon window in screen coords.
-void NS_NPAPI_CarbonWindowFrame(WindowRef aWindow, nsRect& outRect);
-#endif
-
-// Get the rect for an entire top-level Cocoa window in screen coords.
-void NS_NPAPI_CocoaWindowFrame(void* aWindow, nsRect& outRect);
-
-// Returns whether or not a Cocoa NSWindow has main status.
-bool NS_NPAPI_CocoaWindowIsMain(void* aWindow);
-
-// Puts up a Cocoa context menu (NSMenu) for a particular NPCocoaEvent.
-NPError NS_NPAPI_ShowCocoaContextMenu(void* menu, nsIWidget* widget, NPCocoaEvent* event);
-
-NPBool NS_NPAPI_ConvertPointCocoa(void* inView,
-                                  double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
-                                  double *destX, double *destY, NPCoordinateSpace destSpace);
-
deleted file mode 100644
--- a/layout/generic/nsPluginUtilsOSX.mm
+++ /dev/null
@@ -1,207 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-// vim:set ts=2 sts=2 sw=2 et cin:
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsPluginUtilsOSX.h"
-
-#import <Cocoa/Cocoa.h>
-#import <QuartzCore/QuartzCore.h>
-#include "nsObjCExceptions.h"
-
-#ifndef __LP64__
-void NS_NPAPI_CarbonWindowFrame(WindowRef aWindow, nsRect& outRect)
-{
-  if (!aWindow)
-    return;
-
-  Rect windowRect;
-  ::GetWindowBounds(aWindow, kWindowStructureRgn, &windowRect);
-  outRect.x = windowRect.left;
-  outRect.y = windowRect.top;
-  outRect.width = windowRect.right - windowRect.left;
-  outRect.height = windowRect.bottom - windowRect.top;
-}
-#endif
-
-void NS_NPAPI_CocoaWindowFrame(void* aWindow, nsRect& outRect)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
-  if (!aWindow)
-    return;
-
-  NSWindow* window = (NSWindow*)aWindow;
-
-  float menubarScreenHeight;
-  NSArray* allScreens = [NSScreen screens];
-  if ([allScreens count])
-    menubarScreenHeight = [[allScreens objectAtIndex:0] frame].size.height;
-  else
-    return; // If there are no screens, there's not much we can say.
-
-  NSRect frame = [window frame];
-  outRect.x = (nscoord)frame.origin.x;
-  outRect.y = (nscoord)(menubarScreenHeight - (frame.origin.y + frame.size.height));
-  outRect.width = (nscoord)frame.size.width;
-  outRect.height = (nscoord)frame.size.height;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-bool NS_NPAPI_CocoaWindowIsMain(void* aWindow)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
-  if (!aWindow)
-    return true;
-
-  NSWindow* window = (NSWindow*)aWindow;
-
-  return (bool)[window isMainWindow];
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(true);
-}
-
-NPError NS_NPAPI_ShowCocoaContextMenu(void* menu, nsIWidget* widget, NPCocoaEvent* event)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
-  if (!menu || !widget || !event)
-    return NPERR_GENERIC_ERROR;
-
-  NSMenu* cocoaMenu = (NSMenu*)menu;
-  NSView* cocoaView = (NSView*)widget->GetNativeData(NS_NATIVE_WIDGET);
-
-  NSEventType cocoaEventType = NSRightMouseDown;
-  unsigned int cocoaModifierFlags = 0;
-  double x = 0.0;   // Coordinates for the context menu in plugin terms, top-left origin.
-  double y = 0.0;
-
-  NPCocoaEventType eventType = event->type;
-  if (eventType == NPCocoaEventMouseDown ||
-      eventType == NPCocoaEventMouseUp ||
-      eventType == NPCocoaEventMouseMoved ||
-      eventType == NPCocoaEventMouseEntered ||
-      eventType == NPCocoaEventMouseExited ||
-      eventType == NPCocoaEventMouseDragged) {
-    x = event->data.mouse.pluginX;
-    y = event->data.mouse.pluginY;
-    if ((x < 0.0) || (y < 0.0))
-      return NPERR_GENERIC_ERROR;
-  }
-
-  // Flip the coords to bottom-left origin.
-  NSRect viewFrame = [cocoaView frame];
-  double shiftedX = x;
-  double shiftedY = viewFrame.size.height - y;
-  // Shift to window coords.
-  shiftedX += viewFrame.origin.x;
-  shiftedY += [cocoaView convertPoint:NSMakePoint(0,0) toView:nil].y - viewFrame.size.height;
-
-  // Create an NSEvent we can use to show the context menu. Only the location
-  // is important here so just simulate a right mouse down. The coordinates
-  // must be in top-level window terms.
-  NSEvent* cocoaEvent = [NSEvent mouseEventWithType:cocoaEventType
-                                           location:NSMakePoint(shiftedX, shiftedY)
-                                      modifierFlags:cocoaModifierFlags
-                                          timestamp:0
-                                       windowNumber:[[cocoaView window] windowNumber]
-                                            context:nil
-                                        eventNumber:0
-                                         clickCount:1
-                                           pressure:0.0];
-
-  [NSMenu popUpContextMenu:cocoaMenu withEvent:cocoaEvent forView:cocoaView];
-
-  return NPERR_NO_ERROR;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NPERR_GENERIC_ERROR);
-}
-
-NPBool NS_NPAPI_ConvertPointCocoa(void* inView,
-                                  double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
-                                  double *destX, double *destY, NPCoordinateSpace destSpace)
-{
-  // Plugins don't always have a view/frame. It would be odd to ask for a point conversion
-  // without a view, so we'll warn about it, but it's technically OK.
-  if (!inView) {
-    NS_WARNING("Must have a native view to convert coordinates.");
-    return false;
-  }
-
-  // Caller has to want a result.
-  if (!destX && !destY)
-    return false;
-
-  if (sourceSpace == destSpace) {
-    if (destX)
-      *destX = sourceX;
-    if (destY)
-      *destY = sourceY;
-    return true;
-  }
-
-  NSView* view = (NSView*)inView;
-  NSWindow* window = [view window];
-  NSPoint sourcePoint = NSMakePoint(sourceX, sourceY);
-
-  // Convert to screen space.
-  NSPoint screenPoint;
-  switch (sourceSpace) {
-    case NPCoordinateSpacePlugin:
-      screenPoint = [view convertPoint:sourcePoint toView:nil];
-      screenPoint = [window convertBaseToScreen:screenPoint];
-      break;
-    case NPCoordinateSpaceWindow:
-      screenPoint = [window convertBaseToScreen:sourcePoint];
-      break;
-    case NPCoordinateSpaceFlippedWindow:
-      sourcePoint.y = [window frame].size.height - sourcePoint.y;
-      screenPoint = [window convertBaseToScreen:sourcePoint];
-      break;
-    case NPCoordinateSpaceScreen:
-      screenPoint = sourcePoint;
-      break;
-    case NPCoordinateSpaceFlippedScreen:
-      sourcePoint.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - sourcePoint.y;
-      screenPoint = sourcePoint;
-      break;
-    default:
-      return false;
-  }
-
-  // Convert from screen to dest space.
-  NSPoint destPoint;
-  switch (destSpace) {
-    case NPCoordinateSpacePlugin:
-      destPoint = [window convertScreenToBase:screenPoint];
-      destPoint = [view convertPoint:destPoint fromView:nil];
-      break;
-    case NPCoordinateSpaceWindow:
-      destPoint = [window convertScreenToBase:screenPoint];
-      break;
-    case NPCoordinateSpaceFlippedWindow:
-      destPoint = [window convertScreenToBase:screenPoint];
-      destPoint.y = [window frame].size.height - destPoint.y;
-      break;
-    case NPCoordinateSpaceScreen:
-      destPoint = screenPoint;
-      break;
-    case NPCoordinateSpaceFlippedScreen:
-      destPoint = screenPoint;
-      destPoint.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - destPoint.y;
-      break;
-    default:
-      return false;
-  }
-
-  if (destX)
-    *destX = destPoint.x;
-  if (destY)
-    *destY = destPoint.y;
-
-  return true;
-}
-
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -1254,8 +1254,29 @@ nsSubDocumentFrame::ObtainIntrinsicSizeF
 
     if (subDocRoot && subDocRoot->GetContent() &&
         subDocRoot->GetContent()->NodeInfo()->Equals(nsGkAtoms::svg, kNameSpaceID_SVG)) {
       return subDocRoot; // SVG documents have an intrinsic size
     }
   }
   return nullptr;
 }
+
+nsIntPoint
+nsSubDocumentFrame::GetChromeDisplacement()
+{
+  nsIFrame* nextFrame = nsLayoutUtils::GetCrossDocParentFrame(this);
+  if (!nextFrame) {
+    NS_WARNING("Couldn't find window chrome to calculate displacement to.");
+    return nsIntPoint();
+  }
+
+  nsIFrame* rootFrame = nextFrame;
+  while (nextFrame) {
+    rootFrame = nextFrame;
+    nextFrame = nsLayoutUtils::GetCrossDocParentFrame(rootFrame);
+  }
+
+  nsPoint offset = GetOffsetToCrossDoc(rootFrame);
+  int32_t appUnitsPerDevPixel = rootFrame->PresContext()->AppUnitsPerDevPixel();
+  return nsIntPoint((int)(offset.x/appUnitsPerDevPixel),
+                    (int)(offset.y/appUnitsPerDevPixel));
+}
--- a/layout/generic/nsSubDocumentFrame.h
+++ b/layout/generic/nsSubDocumentFrame.h
@@ -122,16 +122,18 @@ public:
   }
 
   /**
    * Return true if pointer event hit-testing should be allowed to target
    * content in the subdocument.
    */
   bool PassPointerEventsToChildren();
 
+  nsIntPoint GetChromeDisplacement();
+
 protected:
   friend class AsyncFrameInit;
 
   // Helper method to look up the HTML marginwidth & marginheight attributes
   nsIntSize GetMarginAttributes();
 
   nsFrameLoader* FrameLoader();
 
--- a/view/nsViewManager.cpp
+++ b/view/nsViewManager.cpp
@@ -750,18 +750,17 @@ nsViewManager::DispatchEvent(WidgetGUIEv
   }
 
   // If the view has no frame, look for a view that does.
   nsIFrame* frame = view->GetFrame();
   if (!frame &&
       (dispatchUsingCoordinates || aEvent->HasKeyEventMessage() ||
        aEvent->IsIMERelatedEvent() ||
        aEvent->IsNonRetargetedNativeEventDelivererForPlugin() ||
-       aEvent->HasPluginActivationEventMessage() ||
-       aEvent->message == NS_PLUGIN_RESOLUTION_CHANGED)) {
+       aEvent->HasPluginActivationEventMessage())) {
     while (view && !view->GetFrame()) {
       view = view->GetParent();
     }
 
     if (view) {
       frame = view->GetFrame();
     }
   }
--- a/widget/BasicEvents.h
+++ b/widget/BasicEvents.h
@@ -60,21 +60,16 @@
 #define NS_ONLINE                        (NS_WINDOW_START + 65)
 
 // NS_BEFORERESIZE_EVENT used to be here (NS_WINDOW_START + 66)
 
 // Indicates that the user is either idle or active
 #define NS_MOZ_USER_IDLE                 (NS_WINDOW_START + 67)
 #define NS_MOZ_USER_ACTIVE               (NS_WINDOW_START + 68)
 
-// The resolution at which a plugin should draw has changed, for
-// example as the result of changing from a HiDPI mode to a non-
-// HiDPI mode.
-#define NS_PLUGIN_RESOLUTION_CHANGED     (NS_WINDOW_START + 69)
-
 #define NS_LANGUAGECHANGE                (NS_WINDOW_START + 70)
 
 #define NS_MOUSE_MESSAGE_START          300
 #define NS_MOUSE_MOVE                   (NS_MOUSE_MESSAGE_START)
 #define NS_MOUSE_BUTTON_UP              (NS_MOUSE_MESSAGE_START + 1)
 #define NS_MOUSE_BUTTON_DOWN            (NS_MOUSE_MESSAGE_START + 2)
 #define NS_MOUSE_ENTER                  (NS_MOUSE_MESSAGE_START + 22)
 #define NS_MOUSE_EXIT                   (NS_MOUSE_MESSAGE_START + 23)
--- a/widget/PuppetWidget.cpp
+++ b/widget/PuppetWidget.cpp
@@ -825,32 +825,61 @@ PuppetWidget::GetNativeData(uint32_t aDa
     break;
   default:
     NS_WARNING("nsWindow::GetNativeData called with bad value");
     break;
   }
   return nullptr;
 }
 
+nsIntPoint
+PuppetWidget::GetChromeDimensions()
+{
+  if (!GetOwningTabChild()) {
+    NS_WARNING("PuppetWidget without Tab does not have chrome information.");
+    return nsIntPoint();
+  }
+  return GetOwningTabChild()->GetChromeDisplacement();
+}
+
+nsIntPoint
+PuppetWidget::GetWindowPosition()
+{
+  if (!GetOwningTabChild()) {
+    return nsIntPoint();
+  }
+
+  int32_t winX, winY, winW, winH;
+  NS_ENSURE_SUCCESS(GetOwningTabChild()->GetDimensions(0, &winX, &winY, &winW, &winH), nsIntPoint());
+  return nsIntPoint(winX, winY);
+}
+
 PuppetScreen::PuppetScreen(void *nativeScreen)
 {
 }
 
 PuppetScreen::~PuppetScreen()
 {
 }
 
 static ScreenConfiguration
 ScreenConfig()
 {
   ScreenConfiguration config;
   hal::GetCurrentScreenConfiguration(&config);
   return config;
 }
 
+nsIntSize
+PuppetWidget::GetScreenDimensions()
+{
+  nsIntRect r = ScreenConfig().rect();
+  return nsIntSize(r.width, r.height);
+}
+
 NS_IMETHODIMP
 PuppetScreen::GetId(uint32_t *outId)
 {
   *outId = 1;
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/widget/PuppetWidget.h
+++ b/widget/PuppetWidget.h
@@ -188,16 +188,24 @@ public:
 
   virtual TabChild* GetOwningTabChild() MOZ_OVERRIDE { return mTabChild; }
   virtual void ClearBackingScaleCache()
   {
     mDPI = -1;
     mDefaultScale = -1;
   }
 
+  nsIntSize GetScreenDimensions();
+
+  // Get the size of the chrome of the window that this tab belongs to.
+  nsIntPoint GetChromeDimensions();
+
+  // Get the screen position of the application window.
+  nsIntPoint GetWindowPosition();
+
 protected:
   bool mEnabled;
   bool mVisible;
 
 private:
   nsresult Paint();
 
   void SetChild(PuppetWidget* aChild);
--- a/widget/TextEvents.h
+++ b/widget/TextEvents.h
@@ -92,16 +92,20 @@ public:
     , location(nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD)
     , isChar(false)
     , mIsRepeat(false)
     , mIsComposing(false)
     , mKeyNameIndex(mozilla::KEY_NAME_INDEX_Unidentified)
     , mCodeNameIndex(CODE_NAME_INDEX_UNKNOWN)
     , mNativeKeyEvent(nullptr)
     , mUniqueId(0)
+#ifdef XP_MACOSX
+    , mNativeKeyCode(0)
+    , mNativeModifierFlags(0)
+#endif
   {
   }
 
   virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
   {
     MOZ_ASSERT(mClass == eKeyboardEventClass,
                "Duplicate() must be overridden by sub class");
     // Not copying widget, it is a weak reference.
@@ -146,16 +150,24 @@ public:
   // OS-specific native event can optionally be preserved
   void* mNativeKeyEvent;
   // Unique id associated with a keydown / keypress event. Used in identifing
   // keypress events for removal from async event dispatch queue in metrofx
   // after preventDefault is called on keydown events. It's ok if this wraps
   // over long periods.
   uint32_t mUniqueId;
 
+#ifdef XP_MACOSX
+  // Values given by a native NSEvent, for use with Cocoa NPAPI plugins.
+  uint16_t mNativeKeyCode;
+  uint32_t mNativeModifierFlags;
+  nsString mNativeCharacters;
+  nsString mNativeCharactersIgnoringModifiers;
+#endif
+
   void GetDOMKeyName(nsAString& aKeyName)
   {
     if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
       aKeyName = mKeyValue;
       return;
     }
     GetDOMKeyName(mKeyNameIndex, aKeyName);
   }
--- a/widget/WidgetEventImpl.cpp
+++ b/widget/WidgetEventImpl.cpp
@@ -186,18 +186,17 @@ WidgetEvent::IsUsingCoordinates() const
 {
   const WidgetMouseEvent* mouseEvent = AsMouseEvent();
   if (mouseEvent) {
     return !mouseEvent->IsContextMenuKeyEvent();
   }
   return !HasKeyEventMessage() && !IsIMERelatedEvent() &&
          !HasPluginActivationEventMessage() &&
          !IsNativeEventDelivererForPlugin() &&
-         !IsContentCommandEvent() &&
-         message != NS_PLUGIN_RESOLUTION_CHANGED;
+         !IsContentCommandEvent();
 }
 
 bool
 WidgetEvent::IsTargetedAtFocusedWindow() const
 {
   const WidgetMouseEvent* mouseEvent = AsMouseEvent();
   if (mouseEvent) {
     return mouseEvent->IsContextMenuKeyEvent();
--- a/widget/cocoa/ComplexTextInputPanel.h
+++ b/widget/cocoa/ComplexTextInputPanel.h
@@ -23,28 +23,24 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Modified by Josh Aas of Mozilla Corporation.
  */
 
 #ifndef ComplexTextInputPanel_h_
 #define ComplexTextInputPanel_h_
 
-#import <Cocoa/Cocoa.h>
-
-@interface ComplexTextInputPanel : NSPanel {
-  NSTextView *mInputTextView;
-}
-
-+ (ComplexTextInputPanel*)sharedComplexTextInputPanel;
+#include "nsString.h"
+#include "npapi.h"
 
-- (NSTextInputContext*)inputContext;
-- (BOOL)interpretKeyEvent:(NSEvent*)event string:(NSString**)string;
-- (void)cancelComposition;
-- (BOOL)inComposition;
+class ComplexTextInputPanel
+{
+public:
+  static ComplexTextInputPanel* GetSharedComplexTextInputPanel();
+  virtual void PlacePanel(int32_t x, int32_t y) = 0; // Bottom left coordinate of plugin in screen coords
+  virtual void InterpretKeyEvent(NPCocoaEvent* aEvent, nsAString& aOutText) = 0;
+  virtual bool IsInComposition() = 0;
 
-// This places the text input panel fully onscreen and below the lower left
-// corner of the focused plugin.
-- (void)adjustTo:(NSView*)view;
-
-@end
+protected:
+  virtual ~ComplexTextInputPanel() {};
+};
 
 #endif // ComplexTextInputPanel_h_
--- a/widget/cocoa/ComplexTextInputPanel.mm
+++ b/widget/cocoa/ComplexTextInputPanel.mm
@@ -22,33 +22,54 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  *
  * Modified by Josh Aas of Mozilla Corporation.
  */
 
 #import "ComplexTextInputPanel.h"
 
+#import <Cocoa/Cocoa.h>
+
 #include <algorithm>
 #include "mozilla/Preferences.h"
 #include "nsChildView.h"
 #include "nsCocoaFeatures.h"
 
 using namespace mozilla;
 
+extern "C" OSStatus TSMProcessRawKeyEvent(EventRef anEvent);
+
 #define kInputWindowHeight 20
 
-@implementation ComplexTextInputPanel
+@interface ComplexTextInputPanelImpl : NSPanel {
+  NSTextView *mInputTextView;
+}
+
++ (ComplexTextInputPanelImpl*)sharedComplexTextInputPanelImpl;
 
-+ (ComplexTextInputPanel*)sharedComplexTextInputPanel
+- (NSTextInputContext*)inputContext;
+- (void)interpretKeyEvent:(NSEvent*)event string:(NSString**)string;
+- (void)cancelComposition;
+- (BOOL)inComposition;
+
+// This places the text input panel fully onscreen and below the lower left
+// corner of the focused plugin.
+- (void)adjustTo:(NSPoint)point;
+
+@end
+
+@implementation ComplexTextInputPanelImpl
+
++ (ComplexTextInputPanelImpl*)sharedComplexTextInputPanelImpl
 {
-  static ComplexTextInputPanel *sComplexTextInputPanel;
-  if (!sComplexTextInputPanel)
-    sComplexTextInputPanel = [[ComplexTextInputPanel alloc] init];
-  return sComplexTextInputPanel;
+  static ComplexTextInputPanelImpl *sComplexTextInputPanelImpl;
+  if (!sComplexTextInputPanelImpl)
+    sComplexTextInputPanelImpl = [[ComplexTextInputPanelImpl alloc] init];
+  return sComplexTextInputPanelImpl;
 }
 
 - (id)init
 {
   // In the original Apple code the style mask is given by a function which is not open source.
   // What could possibly be worth hiding in that function, I do not know.
   // Courtesy of gdb: stylemask: 011000011111, 0x61f
   self = [super initWithContentRect:NSZeroRect styleMask:0x61f backing:NSBackingStoreBuffered defer:YES];
@@ -102,41 +123,55 @@ using namespace mozilla;
     NS_ENSURE_SUCCESS(rv, );
     sDoCancel = cancelComposition ? 1 : 0;
   }
   if (sDoCancel) {
     [self cancelComposition];
   }
 }
 
-- (BOOL)interpretKeyEvent:(NSEvent*)event string:(NSString**)string
+- (void)interpretKeyEvent:(NSEvent*)event string:(NSString**)string
 {
-  BOOL hadMarkedText = [mInputTextView hasMarkedText];
-
   *string = nil;
 
-  if (![[mInputTextView inputContext] handleEvent:event])
-    return NO;
+  if (!nsCocoaFeatures::OnMountainLionOrLater()) {
+    // This "works" on OS X 10.7 and below, but at the cost of breaking plugin
+    // IME, even in non-e10s mode: In an IME like Kotoeri Hiragana, every key
+    // gets sent to the plugin individually.
+    if (![[mInputTextView inputContext] handleEvent:event]) {
+      return;
+    }
+  } else {
+    // On OS X 10.8 and above we can't use -[NSTextInputContext handleEvent:]
+    // -- it doesn't work with a synthesized event. We need to activate the
+    // input context and call TSMProcessRawKeyEvent instead. This also allows
+    // plugin IME to work properly in non-e10s mode.
+    [[mInputTextView inputContext] activate];
+    OSErr err = TSMProcessRawKeyEvent((EventRef)[event eventRef]);
+    if (err != noErr) {
+      return;
+    }
+  }
 
   if ([mInputTextView hasMarkedText]) {
     // Don't show the input method window for dead keys
-    if ([[event characters] length] > 0)
+    if ([[event characters] length] > 0) {
       [self orderFront:nil];
-
-    return YES;
+    }
+    return;
   } else {
     [self orderOut:nil];
 
     NSString *text = [[mInputTextView textStorage] string];
-    if ([text length] > 0)
+    if ([text length] > 0) {
       *string = [[text copy] autorelease];
+    }
   }
 
   [mInputTextView setString:@""];
-  return hadMarkedText;
 }
 
 - (NSTextInputContext*)inputContext
 {
   return [mInputTextView inputContext];
 }
 
 - (void)cancelComposition
@@ -145,33 +180,23 @@ using namespace mozilla;
   [self orderOut:nil];
 }
 
 - (BOOL)inComposition
 {
   return [mInputTextView hasMarkedText];
 }
 
-- (void)adjustTo:(NSView*)view
+- (void)adjustTo:(NSPoint)point
 {
-  NSRect viewRect = [view frame];
-  viewRect.origin.x = 0;
-  viewRect.origin.y = 0;
-  viewRect = [view convertRect:viewRect toView:nil];
-  if (nsCocoaFeatures::OnLionOrLater()) {
-    viewRect = [[view window] convertRectToScreen:viewRect];
-  } else {
-    viewRect.origin = [[view window] convertBaseToScreen:viewRect.origin];
-  }
   NSRect selfRect = [self frame];
-  CGFloat minWidth = static_cast<CGFloat>(
-                       Preferences::GetUint("ui.plugin.panel.min-width", 500));
-  NSRect rect = NSMakeRect(viewRect.origin.x,
-                           viewRect.origin.y - selfRect.size.height,
-                           std::max(viewRect.size.width, minWidth),
+  CGFloat minWidth = static_cast<CGFloat>(Preferences::GetUint("ui.plugin.panel.min-width", 500));
+  NSRect rect = NSMakeRect(point.x,
+                           point.y - selfRect.size.height,
+                           500,
                            selfRect.size.height);
 
   // Adjust to screen.
   NSRect screenRect = [[NSScreen mainScreen] visibleFrame];
   if (rect.origin.x < screenRect.origin.x) {
     rect.origin.x = screenRect.origin.x;
   }
   if (rect.origin.y < screenRect.origin.y) {
@@ -187,8 +212,75 @@ using namespace mozilla;
   if (yMostOfScreen < yMost) {
     rect.origin.y -= yMost - yMostOfScreen;
   }
 
   [self setFrame:rect display:[self isVisible]];
 }
 
 @end
+
+class ComplexTextInputPanelPrivate : public ComplexTextInputPanel
+{
+public:
+  ComplexTextInputPanelPrivate();
+
+  virtual void InterpretKeyEvent(NPCocoaEvent* aEvent, nsAString& aOutText);
+  virtual bool IsInComposition();
+  virtual void PlacePanel(int32_t x, int32_t y);
+private:
+  ~ComplexTextInputPanelPrivate();
+  ComplexTextInputPanelImpl* mPanel;
+};
+
+ComplexTextInputPanelPrivate::ComplexTextInputPanelPrivate()
+{
+  mPanel = [[ComplexTextInputPanelImpl alloc] init];
+}
+
+ComplexTextInputPanelPrivate::~ComplexTextInputPanelPrivate()
+{
+  [mPanel release];
+}
+
+ComplexTextInputPanel*
+ComplexTextInputPanel::GetSharedComplexTextInputPanel()
+{
+  static ComplexTextInputPanelPrivate *sComplexTextInputPanelPrivate;
+  if (!sComplexTextInputPanelPrivate) {
+    sComplexTextInputPanelPrivate = new ComplexTextInputPanelPrivate();
+  }
+  return sComplexTextInputPanelPrivate;
+}
+
+void
+ComplexTextInputPanelPrivate::InterpretKeyEvent(NPCocoaEvent* aEvent, nsAString& aOutText)
+{
+  NSEvent* nativeEvent = [NSEvent keyEventWithType:NSKeyDown
+                                          location:NSMakePoint(0,0)
+                                     modifierFlags:aEvent->data.key.modifierFlags
+                                         timestamp:0
+                                      windowNumber:[mPanel windowNumber]
+                                           context:[mPanel graphicsContext]
+                                        characters:(NSString*)aEvent->data.key.characters
+                       charactersIgnoringModifiers:(NSString*)aEvent->data.key.charactersIgnoringModifiers
+                                         isARepeat:aEvent->data.key.isARepeat
+                                           keyCode:aEvent->data.key.keyCode];
+
+  NSString* textString = nil;
+  [mPanel interpretKeyEvent:nativeEvent string:&textString];
+
+  if (textString) {
+    nsCocoaUtils::GetStringForNSString(textString, aOutText);
+  }
+}
+
+bool
+ComplexTextInputPanelPrivate::IsInComposition()
+{
+  return !![mPanel inComposition];
+}
+
+void
+ComplexTextInputPanelPrivate::PlacePanel(int32_t x, int32_t y)
+{
+  [mPanel adjustTo:NSMakePoint(x, y)];
+}
--- a/widget/cocoa/TextInputHandler.h
+++ b/widget/cocoa/TextInputHandler.h
@@ -10,17 +10,16 @@
 #include "nsCocoaUtils.h"
 
 #import <Carbon/Carbon.h>
 #import <Cocoa/Cocoa.h>
 #include "mozView.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsITimer.h"
-#include "npapi.h"
 #include "nsTArray.h"
 #include "mozilla/EventForwards.h"
 
 class nsChildView;
 
 namespace mozilla {
 namespace widget {
 
@@ -312,19 +311,18 @@ protected:
   CFArrayRef mInputSourceList;
   const UCKeyboardLayout* mUCKeyboardLayout;
   int8_t mIsRTL;
 
   bool mOverrideKeyboard;
 };
 
 /**
- * TextInputHandlerBase is a base class of PluginTextInputHandler,
- * IMEInputHandler and TextInputHandler.  Utility methods should be implemented
- * this level.
+ * TextInputHandlerBase is a base class of IMEInputHandler and TextInputHandler.
+ * Utility methods should be implemented this level.
  */
 
 class TextInputHandlerBase
 {
 public:
   nsrefcnt AddRef()
   {
     NS_PRECONDITION(int32_t(mRefCnt) >= 0, "mRefCnt is negative");
@@ -674,174 +672,29 @@ private:
   };
 
   KeyboardLayoutOverride mKeyboardOverride;
 
   static int32_t sSecureEventInputCount;
 };
 
 /**
- * PluginTextInputHandler handles text input events for plugins.
- */
-
-class PluginTextInputHandler : public TextInputHandlerBase
-{
-public:
-
-  /**
-   * When starting complex text input for current event on plugin, this is
-   * called.  See also the comment of StartComplexTextInputForCurrentEvent() of
-   * nsIPluginWidget.
-   */
-  nsresult StartComplexTextInputForCurrentEvent()
-  {
-    mPluginComplexTextInputRequested = true;
-    return NS_OK;
-  }
-
-  /**
-   * HandleKeyDownEventForPlugin() handles aNativeKeyEvent.
-   *
-   * @param aNativeKeyEvent       A native NSKeyDown event.
-   */
-  void HandleKeyDownEventForPlugin(NSEvent* aNativeKeyEvent);
-
-  /**
-   * HandleKeyUpEventForPlugin() handles aNativeKeyEvent.
-   *
-   * @param aNativeKeyEvent       A native NSKeyUp event.
-   */
-  void HandleKeyUpEventForPlugin(NSEvent* aNativeKeyEvent);
-
-  /**
-   * ConvertCocoaKeyEventToNPCocoaEvent() converts aCocoaEvent to NPCocoaEvent.
-   *
-   * @param aCocoaEvent           A native key event.
-   * @param aPluginEvent          The result.
-   */
-  static void ConvertCocoaKeyEventToNPCocoaEvent(NSEvent* aCocoaEvent,
-                                                 NPCocoaEvent& aPluginEvent);
-
-#ifndef __LP64__
-
-  /**
-   * InstallPluginKeyEventsHandler() is called when initializing process.
-   * RemovePluginKeyEventsHandler() is called when finalizing process.
-   * These methods initialize/finalize global resource for handling events for
-   * plugins.
-   */
-  static void InstallPluginKeyEventsHandler();
-  static void RemovePluginKeyEventsHandler();
-
-  /**
-   * This must be called before first key/IME event for plugins.
-   * This method initializes IMKInputSession methods swizzling.
-   */
-  static void SwizzleMethods();
-
-  /**
-   * When a composition starts or finishes, this is called.
-   */
-  void SetPluginTSMInComposition(bool aInComposition)
-  {
-    mPluginTSMInComposition = aInComposition;
-  }
-
-#endif // #ifndef __LP64__
-
-protected:
-  bool mIgnoreNextKeyUpEvent;
-
-  PluginTextInputHandler(nsChildView* aWidget, NSView<mozView> *aNativeView);
-  ~PluginTextInputHandler();
-
-private:
-
-#ifndef __LP64__
-  TSMDocumentID mPluginTSMDoc;
-
-  bool mPluginTSMInComposition;
-#endif // #ifndef __LP64__
-
-  bool mPluginComplexTextInputRequested;
-
-  /**
-   * DispatchCocoaNPAPITextEvent() dispatches a text event for Cocoa plugin.
-   *
-   * @param aString               A string inputted by the dispatching event.
-   * @return                      TRUE if the dispatched event was consumed.
-   *                              Otherwise, FALSE.
-   */
-  bool DispatchCocoaNPAPITextEvent(NSString* aString);
-
-  /**
-   * Whether the plugin is in composition or not.
-   * On 32bit build, this returns the state of mPluginTSMInComposition.
-   * On 64bit build, this returns ComplexTextInputPanel's state.
-   *
-   * @return                      TRUE if plugin is in composition.  Otherwise,
-   *                              FALSE.
-   */
-  bool IsInPluginComposition();
-
-#ifndef __LP64__
-
-  /**
-   * Create a TSM document for use with plugins, so that we can support IME in
-   * them.  Once it's created, if need be (re)activate it.  Some plugins (e.g.
-   * the Flash plugin running in Camino) don't create their own TSM document --
-   * without which IME can't work.  Others (e.g. the Flash plugin running in
-   * Firefox) create a TSM document that (somehow) makes the input window behave
-   * badly when it contains more than one kind of input (say Hiragana and
-   * Romaji).  (We can't just use the per-NSView TSM documents that Cocoa
-   * provides (those created and managed by the NSTSMInputContext class) -- for
-   * some reason TSMProcessRawKeyEvent() doesn't work with them.)
-   */
-  void ActivatePluginTSMDocument();
-
-  /**
-   * HandleCarbonPluginKeyEvent() handles the aKeyEvent.  This is called by
-   * PluginKeyEventsHandler().
-   *
-   * @param aKeyEvent             A native Carbon event.
-   */
-  void HandleCarbonPluginKeyEvent(EventRef aKeyEvent);
-
-  /**
-   * Target for text services events sent as the result of calls made to
-   * TSMProcessRawKeyEvent() in HandleKeyDownEventForPlugin() when a plugin has
-   * the focus.  The calls to TSMProcessRawKeyEvent() short-circuit Cocoa-based
-   * IME (which would otherwise interfere with our efforts) and allow Carbon-
-   * based IME to work in plugins (via the NPAPI).  This strategy doesn't cause
-   * trouble for plugins that (like the Java Embedding Plugin) bypass the NPAPI
-   * to get their keyboard events and do their own Cocoa-based IME.
-   */
-  static OSStatus PluginKeyEventsHandler(EventHandlerCallRef aHandlerRef,
-                                         EventRef aEvent,
-                                         void *aUserData);
-
-  static EventHandlerRef sPluginKeyEventsHandler;
-
-#endif // #ifndef __LP64__
-};
-
-/**
  * IMEInputHandler manages:
  *   1. The IME/keyboard layout statement of nsChildView.
  *   2. The IME composition statement of nsChildView.
  * And also provides the methods which controls the current IME transaction of
  * the instance.
  *
  * Note that an nsChildView handles one or more NSView's events.  E.g., even if
  * a text editor on XUL panel element, the input events handled on the parent
  * (or its ancestor) widget handles it (the native focus is set to it).  The
  * actual focused view is notified by OnFocusChangeInGecko.
  */
 
-class IMEInputHandler : public PluginTextInputHandler
+class IMEInputHandler : public TextInputHandlerBase
 {
 public:
   virtual bool OnDestroyWidget(nsChildView* aDestroyingWidget);
 
   virtual void OnFocusChangeInGecko(bool aFocus);
 
   void OnSelectionChange() { mSelectedRange.location = NSNotFound; }
 
--- a/widget/cocoa/TextInputHandler.mm
+++ b/widget/cocoa/TextInputHandler.mm
@@ -17,44 +17,16 @@
 #include "nsChildView.h"
 #include "nsObjCExceptions.h"
 #include "nsBidiUtils.h"
 #include "nsToolkit.h"
 #include "nsCocoaUtils.h"
 #include "WidgetUtils.h"
 #include "nsPrintfCString.h"
 
-#ifdef __LP64__
-#include "ComplexTextInputPanel.h"
-#include <objc/runtime.h>
-#endif // __LP64__
-
-#ifndef __LP64__
-enum {
-  // Currently focused ChildView (while this TSM document is active).
-  // Transient (only set while TSMProcessRawKeyEvent() is processing a key
-  // event), and the ChildView will be retained and released around the call
-  // to TSMProcessRawKeyEvent() -- so it can be weak.
-  kFocusedChildViewTSMDocPropertyTag  = 'GKFV', // type ChildView* [WEAK]
-};
-
-// Undocumented HIToolbox function used by WebKit to allow Carbon-based IME
-// to work in a Cocoa-based browser (like Safari or Cocoa-widgets Firefox).
-// (Recent WebKit versions actually use a thin wrapper around this function
-// called WKSendKeyEventToTSM().)
-//
-// Calling TSMProcessRawKeyEvent() from ChildView's keyDown: and keyUp:
-// methods (when the ChildView is a plugin view) bypasses Cocoa's IME
-// infrastructure and (instead) causes Carbon TSM events to be sent on each
-// NSKeyDown event.  We install a Carbon event handler
-// (PluginKeyEventsHandler()) to catch these events and pass them to Gecko
-// (which in turn passes them to the plugin).
-extern "C" long TSMProcessRawKeyEvent(EventRef carbonEvent);
-#endif // __LP64__
-
 using namespace mozilla;
 using namespace mozilla::widget;
 
 #ifdef PR_LOGGING
 
 PRLogModuleInfo* gLog = nullptr;
 
 static const char*
@@ -799,16 +771,32 @@ TISInputSourceWrapper::InitKeyEvent(NSEv
   NS_ENSURE_TRUE(aNativeKeyEvent, );
 
   nsCocoaUtils::InitInputEvent(aKeyEvent, aNativeKeyEvent);
 
   // This is used only while dispatching the event (which is a synchronous
   // call), so there is no need to retain and release this data.
   aKeyEvent.mNativeKeyEvent = aNativeKeyEvent;
 
+  // Fill in fields used for Cocoa NPAPI plugins
+  if ([aNativeKeyEvent type] == NSKeyDown ||
+      [aNativeKeyEvent type] == NSKeyUp) {
+    aKeyEvent.mNativeKeyCode = [aNativeKeyEvent keyCode];
+    aKeyEvent.mNativeModifierFlags = [aNativeKeyEvent modifierFlags];
+    nsAutoString nativeChars;
+    nsCocoaUtils::GetStringForNSString([aNativeKeyEvent characters], nativeChars);
+    aKeyEvent.mNativeCharacters.Assign(nativeChars);
+    nsAutoString nativeCharsIgnoringModifiers;
+    nsCocoaUtils::GetStringForNSString([aNativeKeyEvent charactersIgnoringModifiers], nativeCharsIgnoringModifiers);
+    aKeyEvent.mNativeCharactersIgnoringModifiers.Assign(nativeCharsIgnoringModifiers);
+  } else if ([aNativeKeyEvent type] == NSFlagsChanged) {
+    aKeyEvent.mNativeKeyCode = [aNativeKeyEvent keyCode];
+    aKeyEvent.mNativeModifierFlags = [aNativeKeyEvent modifierFlags];
+  }
+
   aKeyEvent.refPoint = LayoutDeviceIntPoint(0, 0);
 
   // If a keyboard layout override is set, we also need to force the keyboard
   // type to something ANSI to avoid test failures on machines with JIS
   // keyboards (since the pair of keyboard layout and physical keyboard type
   // form the actual key layout).  This assumes that the test setting the
   // override was written assuming an ANSI keyboard.
   UInt32 kbType = mOverrideKeyboard ? eKbdType_ANSI : ::LMGetKbdType();
@@ -1636,27 +1624,22 @@ void
 TextInputHandler::HandleKeyUpEvent(NSEvent* aNativeEvent)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   PR_LOG(gLog, PR_LOG_ALWAYS,
     ("%p TextInputHandler::HandleKeyUpEvent, aNativeEvent=%p, "
      "type=%s, keyCode=%lld (0x%X), modifierFlags=0x%X, characters=\"%s\", "
      "charactersIgnoringModifiers=\"%s\", "
-     "mIgnoreNextKeyUpEvent=%s, IsIMEComposing()=%s",
+     "IsIMEComposing()=%s",
      this, aNativeEvent, GetNativeKeyEventType(aNativeEvent),
      [aNativeEvent keyCode], [aNativeEvent keyCode],
      [aNativeEvent modifierFlags], GetCharacters([aNativeEvent characters]),
      GetCharacters([aNativeEvent charactersIgnoringModifiers]),
-     TrueOrFalse(mIgnoreNextKeyUpEvent), TrueOrFalse(IsIMEComposing())));
-
-  if (mIgnoreNextKeyUpEvent) {
-    mIgnoreNextKeyUpEvent = false;
-    return;
-  }
+     TrueOrFalse(IsIMEComposing())));
 
   if (Destroyed()) {
     PR_LOG(gLog, PR_LOG_ALWAYS,
       ("%p TextInputHandler::HandleKeyUpEvent, "
        "widget has been already destroyed", this));
     return;
   }
 
@@ -2006,29 +1989,29 @@ TextInputHandler::DispatchKeyEventForFla
      TrueOrFalse(aDispatchKeyDown), TrueOrFalse(IsIMEComposing())));
 
   if ([aNativeEvent type] != NSFlagsChanged || IsIMEComposing()) {
     return;
   }
 
   uint32_t message = aDispatchKeyDown ? NS_KEY_DOWN : NS_KEY_UP;
 
-  NPCocoaEvent cocoaEvent;
-
   // Fire a key event.
   WidgetKeyboardEvent keyEvent(true, message, mWidget);
   InitKeyEvent(aNativeEvent, keyEvent);
 
-  // create event for use by plugins
-  if ([mView isPluginView]) {
-    if ([mView pluginEventModel] == NPEventModelCocoa) {
-      ConvertCocoaKeyEventToNPCocoaEvent(aNativeEvent, cocoaEvent);
-      keyEvent.mPluginEvent.Copy(cocoaEvent);
-    }
-  }
+  // Attach a plugin event, in case keyEvent gets dispatched to a plugin.  Only
+  // one field is needed -- the type.  The other fields can be constructed as
+  // the need arises.  But Gecko doesn't have anything equivalent to the
+  // NPCocoaEventFlagsChanged type, and this needs to be passed accurately to
+  // any plugin to which this event is sent.
+  NPCocoaEvent cocoaEvent;
+  nsCocoaUtils::InitNPCocoaEvent(&cocoaEvent);
+  cocoaEvent.type = NPCocoaEventFlagsChanged;
+  keyEvent.mPluginEvent.Copy(cocoaEvent);
 
   DispatchEvent(keyEvent);
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 void
 TextInputHandler::InsertText(NSAttributedString* aAttrString,
@@ -3234,17 +3217,17 @@ IMEInputHandler::GetValidAttributesForMa
 /******************************************************************************
  *
  *  IMEInputHandler implementation #2
  *
  ******************************************************************************/
 
 IMEInputHandler::IMEInputHandler(nsChildView* aWidget,
                                  NSView<mozView> *aNativeView) :
-  PluginTextInputHandler(aWidget, aNativeView),
+  TextInputHandlerBase(aWidget, aNativeView),
   mPendingMethods(0), mIMECompositionString(nullptr),
   mIsIMEComposing(false), mIsIMEEnabled(true),
   mIsASCIICapableOnly(false), mIgnoreIMECommit(false),
   mIsInFocusProcessing(false), mIMEHasFocus(false)
 {
   InitStaticMembers();
 
   mMarkedRange.location = NSNotFound;
@@ -3302,20 +3285,16 @@ IMEInputHandler::OnDestroyWidget(nsChild
      TrueOrFalse(IsIMEComposing())));
 
   // If we're not focused, the focused IMEInputHandler may have been
   // created by another widget/nsChildView.
   if (sFocusedIMEHandler && sFocusedIMEHandler != this) {
     sFocusedIMEHandler->OnDestroyWidget(aDestroyingWidget);
   }
 
-  if (!PluginTextInputHandler::OnDestroyWidget(aDestroyingWidget)) {
-    return false;
-  }
-
   if (IsIMEComposing()) {
     // If our view is in the composition, we should clean up it.
     CancelIMEComposition();
     OnEndIMEComposition();
   }
 
   mSelectedRange.location = NSNotFound; // Marking dirty
   mIMEHasFocus = false;
@@ -3628,597 +3607,16 @@ IMEInputHandler::OpenSystemPreferredLang
 }
 
 
 #pragma mark -
 
 
 /******************************************************************************
  *
- *  PluginTextInputHandler implementation
- *
- ******************************************************************************/
-
-PluginTextInputHandler::PluginTextInputHandler(nsChildView* aWidget,
-                                               NSView<mozView> *aNativeView) :
-  TextInputHandlerBase(aWidget, aNativeView),
-  mIgnoreNextKeyUpEvent(false),
-#ifndef __LP64__
-  mPluginTSMDoc(0), mPluginTSMInComposition(false),
-#endif // #ifndef __LP64__
-  mPluginComplexTextInputRequested(false)
-{
-}
-
-PluginTextInputHandler::~PluginTextInputHandler()
-{
-#ifndef __LP64__
-  if (mPluginTSMDoc) {
-    ::DeleteTSMDocument(mPluginTSMDoc);
-  }
-#endif // #ifndef __LP64__
-}
-
-/* static */ void
-PluginTextInputHandler::ConvertCocoaKeyEventToNPCocoaEvent(
-                          NSEvent* aCocoaEvent,
-                          NPCocoaEvent& aPluginEvent)
-{
-  nsCocoaUtils::InitNPCocoaEvent(&aPluginEvent);
-  NSEventType nativeType = [aCocoaEvent type];
-  switch (nativeType) {
-    case NSKeyDown:
-      aPluginEvent.type = NPCocoaEventKeyDown;
-      break;
-    case NSKeyUp:
-      aPluginEvent.type = NPCocoaEventKeyUp;
-      break;
-    case NSFlagsChanged:
-      aPluginEvent.type = NPCocoaEventFlagsChanged;
-      break;
-    default:
-      NS_WARNING("Asked to convert key event of unknown type to Cocoa plugin event!");
-  }
-  aPluginEvent.data.key.modifierFlags = [aCocoaEvent modifierFlags];
-  aPluginEvent.data.key.keyCode = [aCocoaEvent keyCode];
-  // don't try to access character data for flags changed events,
-  // it will raise an exception
-  if (nativeType != NSFlagsChanged) {
-    aPluginEvent.data.key.characters = (NPNSString*)[aCocoaEvent characters];
-    aPluginEvent.data.key.charactersIgnoringModifiers =
-      (NPNSString*)[aCocoaEvent charactersIgnoringModifiers];
-    aPluginEvent.data.key.isARepeat = [aCocoaEvent isARepeat];
-  }
-}
-
-#ifndef __LP64__
-
-EventHandlerRef PluginTextInputHandler::sPluginKeyEventsHandler = NULL;
-
-/* static */ void
-PluginTextInputHandler::InstallPluginKeyEventsHandler()
-{
-  if (sPluginKeyEventsHandler) {
-    return;
-  }
-  static const EventTypeSpec sTSMEvents[] =
-    { { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } };
-  ::InstallEventHandler(::GetEventDispatcherTarget(),
-                        ::NewEventHandlerUPP(PluginKeyEventsHandler),
-                        GetEventTypeCount(sTSMEvents),
-                        sTSMEvents,
-                        NULL,
-                        &sPluginKeyEventsHandler);
-}
-
-/* static */ void
-PluginTextInputHandler::RemovePluginKeyEventsHandler()
-{
-  if (!sPluginKeyEventsHandler) {
-    return;
-  }
-  ::RemoveEventHandler(sPluginKeyEventsHandler);
-  sPluginKeyEventsHandler = NULL;
-}
-
-/* static */ void
-PluginTextInputHandler::SwizzleMethods()
-{
-  Class IMKInputSessionClass = ::NSClassFromString(@"IMKInputSession");
-  nsToolkit::SwizzleMethods(IMKInputSessionClass, @selector(handleEvent:),
-    @selector(PluginTextInputHandler_IMKInputSession_handleEvent:));
-  nsToolkit::SwizzleMethods(IMKInputSessionClass, @selector(commitComposition),
-    @selector(PluginTextInputHandler_IMKInputSession_commitComposition));
-  nsToolkit::SwizzleMethods(IMKInputSessionClass, @selector(finishSession),
-    @selector(PluginTextInputHandler_IMKInputSession_finishSession));
-}
-
-/* static */ OSStatus
-PluginTextInputHandler::PluginKeyEventsHandler(EventHandlerCallRef aHandlerRef,
-                                               EventRef aEvent,
-                                               void *aUserData)
-{
-  nsAutoreleasePool localPool;
-
-  TSMDocumentID activeDoc = ::TSMGetActiveDocument();
-  NS_ENSURE_TRUE(activeDoc, eventNotHandledErr);
-
-  ChildView *target = nil;
-  OSStatus status = ::TSMGetDocumentProperty(activeDoc,
-                                             kFocusedChildViewTSMDocPropertyTag,
-                                             sizeof(ChildView *), nil, &target);
-  NS_ENSURE_TRUE(status == noErr, eventNotHandledErr);
-  NS_ENSURE_TRUE(target, eventNotHandledErr);
-
-  EventRef keyEvent = NULL;
-  status = ::GetEventParameter(aEvent, kEventParamTextInputSendKeyboardEvent,
-                               typeEventRef, NULL, sizeof(EventRef), NULL,
-                               &keyEvent);
-  NS_ENSURE_TRUE(status == noErr, eventNotHandledErr);
-  NS_ENSURE_TRUE(keyEvent, eventNotHandledErr);
-
-  nsIWidget* widget = [target widget];
-  NS_ENSURE_TRUE(widget, eventNotHandledErr);
-  TextInputHandler*  handler =
-    static_cast<nsChildView*>(widget)->GetTextInputHandler();
-  NS_ENSURE_TRUE(handler, eventNotHandledErr);
-  handler->HandleCarbonPluginKeyEvent(keyEvent);
-
-  return noErr;
-}
-
-// Called from PluginKeyEventsHandler() (a handler for Carbon TSM events) to
-// process a Carbon key event for the currently focused plugin.  Both Unicode
-// characters and "Mac encoding characters" (in the MBCS or "multibyte
-// character system") are (or should be) available from aKeyEvent, but here we
-// use the MCBS characters.  This is how the WebKit does things, and seems to
-// be what plugins expect.
-void
-PluginTextInputHandler::HandleCarbonPluginKeyEvent(EventRef aKeyEvent)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
-  if (Destroyed()) {
-    return;
-  }
-
-  NS_ASSERTION(mView, "mView must not be NULL");
-
-  nsRefPtr<nsChildView> kungFuDeathGrip(mWidget);
-
-  if ([mView pluginEventModel] == NPEventModelCocoa) {
-    UInt32 size;
-    OSStatus status =
-      ::GetEventParameter(aKeyEvent, kEventParamKeyUnicodes, typeUnicodeText,
-                          NULL, 0, &size, NULL);
-    NS_ENSURE_TRUE(status == noErr, );
-
-    UniChar* chars = (UniChar*)malloc(size);
-    NS_ENSURE_TRUE(chars, );
-
-    status = ::GetEventParameter(aKeyEvent, kEventParamKeyUnicodes,
-                                 typeUnicodeText, NULL, size, NULL, chars);
-    if (status != noErr) {
-      free(chars);
-      return;
-    }
-
-    CFStringRef text =
-      ::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, chars,
-                                           (size / sizeof(UniChar)),
-                                           kCFAllocatorNull);
-    if (!text) {
-      free(chars);
-      return;
-    }
-
-    NPCocoaEvent cocoaTextEvent;
-    nsCocoaUtils::InitNPCocoaEvent(&cocoaTextEvent);
-    cocoaTextEvent.type = NPCocoaEventTextInput;
-    cocoaTextEvent.data.text.text = (NPNSString*)text;
-
-    WidgetPluginEvent pluginEvent(true, NS_PLUGIN_INPUT_EVENT, mWidget);
-    nsCocoaUtils::InitPluginEvent(pluginEvent, cocoaTextEvent);
-    DispatchEvent(pluginEvent);
-
-    ::CFRelease(text);
-    free(chars);
-
-    return;
-  }
-
-  UInt32 numCharCodes;
-  OSStatus status = ::GetEventParameter(aKeyEvent, kEventParamKeyMacCharCodes,
-                                        typeChar, NULL, 0, &numCharCodes, NULL);
-  NS_ENSURE_TRUE(status == noErr, );
-
-  nsAutoTArray<unsigned char, 3> charCodes;
-  charCodes.SetLength(numCharCodes);
-  status = ::GetEventParameter(aKeyEvent, kEventParamKeyMacCharCodes,
-                               typeChar, NULL, numCharCodes, NULL,
-                               charCodes.Elements());
-  NS_ENSURE_TRUE(status == noErr, );
-
-  UInt32 modifiers;
-  status = ::GetEventParameter(aKeyEvent, kEventParamKeyModifiers,
-                               typeUInt32, NULL, sizeof(modifiers), NULL,
-                               &modifiers);
-  NS_ENSURE_TRUE(status == noErr, );
-
-  NSUInteger cocoaModifiers = 0;
-  if (modifiers & shiftKey) {
-    cocoaModifiers |= NSShiftKeyMask;
-  }
-  if (modifiers & controlKey) {
-    cocoaModifiers |= NSControlKeyMask;
-  }
-  if (modifiers & optionKey) {
-    cocoaModifiers |= NSAlternateKeyMask;
-  }
-  if (modifiers & cmdKey) { // Should never happen
-    cocoaModifiers |= NSCommandKeyMask;
-  }
-
-  UInt32 macKeyCode;
-  status = ::GetEventParameter(aKeyEvent, kEventParamKeyCode,
-                               typeUInt32, NULL, sizeof(macKeyCode), NULL,
-                               &macKeyCode);
-  NS_ENSURE_TRUE(status == noErr, );
-
-  TISInputSourceWrapper& currentInputSource =
-    TISInputSourceWrapper::CurrentInputSource();
-
-  EventRef cloneEvent = ::CopyEvent(aKeyEvent);
-  for (uint32_t i = 0; i < numCharCodes; ++i) {
-    status = ::SetEventParameter(cloneEvent, kEventParamKeyMacCharCodes,
-                                 typeChar, 1, charCodes.Elements() + i);
-    NS_ENSURE_TRUE(status == noErr, );
-
-    EventRecord eventRec;
-    if (::ConvertEventRefToEventRecord(cloneEvent, &eventRec)) {
-      WidgetKeyboardEvent keydownEvent(true, NS_KEY_DOWN, mWidget);
-      nsCocoaUtils::InitInputEvent(keydownEvent, cocoaModifiers);
-
-      uint32_t keyCode =
-        currentInputSource.ComputeGeckoKeyCode(macKeyCode, ::LMGetKbdType(),
-                                               keydownEvent.IsMeta());
-      uint32_t charCode(charCodes.ElementAt(i));
-
-      keydownEvent.time = PR_IntervalNow();
-      keydownEvent.mPluginEvent.Copy(eventRec);
-      if (IsSpecialGeckoKey(macKeyCode)) {
-        keydownEvent.keyCode = keyCode;
-      } else {
-        // XXX This is wrong. charCode must be 0 for keydown event.
-        keydownEvent.charCode = charCode;
-        keydownEvent.isChar   = true;
-      }
-      DispatchEvent(keydownEvent);
-      if (Destroyed()) {
-        break;
-      }
-    }
-  }
-
-  ::ReleaseEvent(cloneEvent);
-
-  NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-void
-PluginTextInputHandler::ActivatePluginTSMDocument()
-{
-  if (!mPluginTSMDoc) {
-    // Create a TSM document that supports both non-Unicode and Unicode input.
-    // Though ProcessPluginKeyEvent() only sends Mac char codes to
-    // the plugin, this makes the input window behave better when it contains
-    // more than one kind of input (say Hiragana and Romaji).  This is what
-    // the OS does when it creates a TSM document for use by an
-    // NSTSMInputContext class.
-    InterfaceTypeList supportedServices;
-    supportedServices[0] = kTextServiceDocumentInterfaceType;
-    supportedServices[1] = kUnicodeDocumentInterfaceType;
-    ::NewTSMDocument(2, supportedServices, &mPluginTSMDoc, 0);
-    // We'll need to use the "input window".
-    ::UseInputWindow(mPluginTSMDoc, YES);
-    ::ActivateTSMDocument(mPluginTSMDoc);
-  } else if (::TSMGetActiveDocument() != mPluginTSMDoc) {
-    ::ActivateTSMDocument(mPluginTSMDoc);
-  }
-}
-
-#endif // #ifndef __LP64__
-
-void
-PluginTextInputHandler::HandleKeyDownEventForPlugin(NSEvent* aNativeKeyEvent)
-{
-  if (Destroyed()) {
-    return;
-  }
-
-  NS_ASSERTION(mView, "mView must not be NULL");
-
-#ifdef __LP64__
-
-  if ([mView pluginEventModel] != NPEventModelCocoa) {
-    return;
-  }
-
-  ComplexTextInputPanel* ctiPanel =
-    [ComplexTextInputPanel sharedComplexTextInputPanel];
-  [ctiPanel adjustTo:mView];
-
-  // If a composition is in progress then simply let the input panel continue
-  // it.
-  if (IsInPluginComposition()) {
-    // Don't send key up events for key downs associated with compositions.
-    mIgnoreNextKeyUpEvent = true;
-
-    NSString* textString = nil;
-    [ctiPanel interpretKeyEvent:aNativeKeyEvent string:&textString];
-    if (textString) {
-      DispatchCocoaNPAPITextEvent(textString);
-    }
-
-    return;
-  }
-
-  // Reset complex text input request flag.
-  mPluginComplexTextInputRequested = false;
-
-  // Send key down event to the plugin.
-  WidgetPluginEvent pluginEvent(true, NS_PLUGIN_INPUT_EVENT, mWidget);
-  NPCocoaEvent cocoaEvent;
-  ConvertCocoaKeyEventToNPCocoaEvent(aNativeKeyEvent, cocoaEvent);
-  nsCocoaUtils::InitPluginEvent(pluginEvent, cocoaEvent);
-  DispatchEvent(pluginEvent);
-  if (Destroyed()) {
-    return;
-  }
-
-  // Start complex text composition if requested.
-  if (mPluginComplexTextInputRequested) {
-    // Don't send key up events for key downs associated with compositions.
-    mIgnoreNextKeyUpEvent = true;
-
-    NSString* textString = nil;
-    [ctiPanel interpretKeyEvent:aNativeKeyEvent string:&textString];
-    if (textString) {
-      DispatchCocoaNPAPITextEvent(textString);
-    }
-  }
-
-#else // #ifdef __LP64__
-
-  bool wasInComposition = false;
-  if ([mView pluginEventModel] == NPEventModelCocoa) {
-    if (IsInPluginComposition()) {
-      wasInComposition = true;
-
-      // Don't send key up events for key downs associated with compositions.
-      mIgnoreNextKeyUpEvent = true;
-    } else {
-      // Reset complex text input request flag.
-      mPluginComplexTextInputRequested = false;
-
-      // Send key down event to the plugin.
-      WidgetPluginEvent pluginEvent(true, NS_PLUGIN_INPUT_EVENT, mWidget);
-      NPCocoaEvent cocoaEvent;
-      ConvertCocoaKeyEventToNPCocoaEvent(aNativeKeyEvent, cocoaEvent);
-      nsCocoaUtils::InitPluginEvent(pluginEvent, cocoaEvent);
-      DispatchEvent(pluginEvent);
-      if (Destroyed()) {
-        return;
-      }
-
-      // Only continue if plugin wants complex text input.
-      if (!mPluginComplexTextInputRequested) {
-        return;
-      }
-
-      // Don't send key up events for key downs associated with compositions.
-      mIgnoreNextKeyUpEvent = true;
-    }
-
-    // Don't send complex text input to a plugin in Cocoa event mode if
-    // either the Control key or the Command key is pressed -- even if the
-    // plugin has requested it, or we are already in IME composition.  This
-    // conforms to our behavior in 64-bit mode and fixes bug 619217.
-    NSUInteger modifierFlags = [aNativeKeyEvent modifierFlags];
-    if ((modifierFlags & NSControlKeyMask) ||
-        (modifierFlags & NSCommandKeyMask)) {
-      return;
-    }
-  }
-
-  // This will take care of all Carbon plugin events and also send Cocoa plugin
-  // text events when NSInputContext is not available (ifndef NP_NO_CARBON).
-  ActivatePluginTSMDocument();
-
-  // We use the active TSM document to pass a pointer to ourselves (the
-  // currently focused ChildView) to PluginKeyEventsHandler().  Because this
-  // pointer is weak, we should retain and release ourselves around the call
-  // to TSMProcessRawKeyEvent().
-  nsAutoRetainCocoaObject kungFuDeathGrip(mView);
-  ::TSMSetDocumentProperty(mPluginTSMDoc,
-                           kFocusedChildViewTSMDocPropertyTag,
-                           sizeof(ChildView *), &mView);
-  ::TSMProcessRawKeyEvent([aNativeKeyEvent _eventRef]);
-  ::TSMRemoveDocumentProperty(mPluginTSMDoc,
-                              kFocusedChildViewTSMDocPropertyTag);
-
-#endif // #ifdef __LP64__ else
-}
-
-void
-PluginTextInputHandler::HandleKeyUpEventForPlugin(NSEvent* aNativeKeyEvent)
-{
-  if (mIgnoreNextKeyUpEvent) {
-    mIgnoreNextKeyUpEvent = false;
-    return;
-  }
-
-  if (Destroyed()) {
-    return;
-  }
-
-  NS_ASSERTION(mView, "mView must not be NULL");
-
-  NPEventModel eventModel = [mView pluginEventModel];
-  if (eventModel == NPEventModelCocoa) {
-    // Don't send key up events to Cocoa plugins during composition.
-    if (IsInPluginComposition()) {
-      return;
-    }
-
-    WidgetKeyboardEvent keyupEvent(true, NS_KEY_UP, mWidget);
-    InitKeyEvent(aNativeKeyEvent, keyupEvent);
-    NPCocoaEvent pluginEvent;
-    ConvertCocoaKeyEventToNPCocoaEvent(aNativeKeyEvent, pluginEvent);
-    keyupEvent.mPluginEvent.Copy(pluginEvent);
-    DispatchEvent(keyupEvent);
-    return;
-  }
-}
-
-bool
-PluginTextInputHandler::IsInPluginComposition()
-{
-  return
-#ifdef __LP64__
-    [[ComplexTextInputPanel sharedComplexTextInputPanel] inComposition] != NO;
-#else // #ifdef __LP64__
-    mPluginTSMInComposition;
-#endif // #ifdef __LP64__ else
-}
-
-bool
-PluginTextInputHandler::DispatchCocoaNPAPITextEvent(NSString* aString)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
-  NPCocoaEvent cocoaTextEvent;
-  nsCocoaUtils::InitNPCocoaEvent(&cocoaTextEvent);
-  cocoaTextEvent.type = NPCocoaEventTextInput;
-  cocoaTextEvent.data.text.text = (NPNSString*)aString;
-
-  WidgetPluginEvent pluginEvent(true, NS_PLUGIN_INPUT_EVENT, mWidget);
-  nsCocoaUtils::InitPluginEvent(pluginEvent, cocoaTextEvent);
-  return DispatchEvent(pluginEvent);
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
-}
-
-
-#pragma mark -
-
-
-#ifndef __LP64__
-
-/******************************************************************************
- *
- *  PluginTextInputHandler_IMKInputSession_* implementation
- *
- ******************************************************************************/
-
-// IMKInputSession is an undocumented class in the HIToolbox framework.  It's
-// present on both Leopard and SnowLeopard, and is used at a low level to
-// process IME input regardless of which high-level API is used (Text Services
-// Manager or Cocoa).  It works the same way in both 32-bit and 64-bit code.
-@interface NSObject (IMKInputSessionMethodSwizzling)
-- (BOOL)PluginTextInputHandler_IMKInputSession_handleEvent:(EventRef)theEvent;
-- (void)PluginTextInputHandler_IMKInputSession_commitComposition;
-- (void)PluginTextInputHandler_IMKInputSession_finishSession;
-@end
-
-@implementation NSObject (IMKInputSessionMethodSwizzling)
-
-- (BOOL)PluginTextInputHandler_IMKInputSession_handleEvent:(EventRef)theEvent
-{
-  [self retain];
-  BOOL retval =
-    [self PluginTextInputHandler_IMKInputSession_handleEvent:theEvent];
-  NSUInteger retainCount = [self retainCount];
-  [self release];
-  // Return without doing anything if we've been deleted.
-  if (retainCount == 1) {
-    return retval;
-  }
-
-  NSWindow *mainWindow = [NSApp mainWindow];
-  NSResponder *firstResponder = [mainWindow firstResponder];
-  if (![firstResponder isKindOfClass:[ChildView class]]) {
-    return retval;
-  }
-
-  // 'charactersEntered' is the length (in bytes) of currently "marked text"
-  // -- text that's been entered in IME but not yet committed.  If it's
-  // non-zero we're composing text in an IME session; if it's zero we're
-  // not in an IME session.
-  NSInteger entered = 0;
-  object_getInstanceVariable(self, "charactersEntered",
-                             (void **) &entered);
-  nsIWidget* widget = [(ChildView*)firstResponder widget];
-  NS_ENSURE_TRUE(widget, retval);
-  TextInputHandler* handler =
-    static_cast<nsChildView*>(widget)->GetTextInputHandler();
-  NS_ENSURE_TRUE(handler, retval);
-  handler->SetPluginTSMInComposition(entered != 0);
-
-  return retval;
-}
-
-// This method is called whenever IME input is committed as a result of an
-// "abnormal" termination -- for example when changing the keyboard focus from
-// one input field to another.
-- (void)PluginTextInputHandler_IMKInputSession_commitComposition
-{
-  NSWindow *mainWindow = [NSApp mainWindow];
-  NSResponder *firstResponder = [mainWindow firstResponder];
-  if ([firstResponder isKindOfClass:[ChildView class]]) {
-    nsIWidget* widget = [(ChildView*)firstResponder widget];
-    if (widget) {
-      TextInputHandler* handler =
-        static_cast<nsChildView*>(widget)->GetTextInputHandler();
-      if (handler) {
-        handler->SetPluginTSMInComposition(false);
-      }
-    }
-  }
-  [self PluginTextInputHandler_IMKInputSession_commitComposition];
-}
-
-// This method is called just before we're deallocated.
-- (void)PluginTextInputHandler_IMKInputSession_finishSession
-{
-  NSWindow *mainWindow = [NSApp mainWindow];
-  NSResponder *firstResponder = [mainWindow firstResponder];
-  if ([firstResponder isKindOfClass:[ChildView class]]) {
-    nsIWidget* widget = [(ChildView*)firstResponder widget];
-    if (widget) {
-      TextInputHandler* handler =
-        static_cast<nsChildView*>(widget)->GetTextInputHandler();
-      if (handler) {
-        handler->SetPluginTSMInComposition(false);
-      }
-    }
-  }
-  [self PluginTextInputHandler_IMKInputSession_finishSession];
-}
-
-@end
-
-#endif // #ifndef __LP64__
-
-
-#pragma mark -
-
-
-/******************************************************************************
- *
  *  TextInputHandlerBase implementation
  *
  ******************************************************************************/
 
 int32_t TextInputHandlerBase::sSecureEventInputCount = 0;
 
 TextInputHandlerBase::TextInputHandlerBase(nsChildView* aWidget,
                                            NSView<mozView> *aNativeView) :
--- a/widget/cocoa/moz.build
+++ b/widget/cocoa/moz.build
@@ -13,16 +13,17 @@ XPIDL_MODULE = 'widget_cocoa'
 EXPORTS += [
     'mozView.h',
     'nsChangeObserver.h',
     'nsCocoaFeatures.h',
     'nsCocoaUtils.h',
 ]
 
 UNIFIED_SOURCES += [
+    'ComplexTextInputPanel.mm',
     'GfxInfo.mm',
     'NativeKeyBindings.mm',
     'nsAppShell.mm',
     'nsBidiKeyboard.mm',
     'nsCocoaFeatures.mm',
     'nsCocoaUtils.mm',
     'nsCocoaWindow.mm',
     'nsColorPicker.mm',
@@ -60,21 +61,16 @@ UNIFIED_SOURCES += [
 ]
 
 # These files cannot be built in unified mode because they cause symbol conflicts
 SOURCES += [
     'nsChildView.mm',
     'nsClipboard.mm',
 ]
 
-if CONFIG['TARGET_CPU'] == 'x86_64':
-    UNIFIED_SOURCES += [
-        'ComplexTextInputPanel.mm',
-    ]
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/layout/forms',
     '/layout/generic',
     '/layout/xul',
     '/widget',
--- a/widget/cocoa/mozView.h
+++ b/widget/cocoa/mozView.h
@@ -1,18 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozView_h_
 #define mozView_h_
 
-#include "npapi.h"
-
 #undef DARWIN
 #import <Cocoa/Cocoa.h>
 class nsIWidget;
 
 namespace mozilla {
 namespace widget{
 class TextInputHandler;
 } // namespace widget
@@ -41,28 +39,22 @@ class TextInputHandler;
 - (void)setNeedsPendingDisplay;
 - (void)setNeedsPendingDisplayInRect:(NSRect)invalidRect;
 
   // called when our corresponding Gecko view goes away
 - (void)widgetDestroyed;
 
 - (BOOL)isDragInProgress;
 
-  // Gets the plugin event model for the view
-- (NPEventModel)pluginEventModel;
-
   // Checks whether the view is first responder or not
 - (BOOL)isFirstResponder;
 
   // Call when you dispatch an event which may cause to open context menu.
 - (void)maybeInitContextMenuTracking;
 
-  // Checks whether the view is for plugin or not
-- (BOOL)isPluginView;
-
 @end
 
 // An informal protocol implemented by the NSWindow of the host application.
 // 
 // It's used to prevent re-entrant calls to -makeKeyAndOrderFront: when gecko
 // focus/activate events propagate out to the embedder's
 // nsIEmbeddingSiteWindow::SetFocus implementation.
 @interface NSObject(mozWindow)
--- a/widget/cocoa/nsAppShell.mm
+++ b/widget/cocoa/nsAppShell.mm
@@ -290,20 +290,16 @@ nsAppShell::Init()
   
   mCFRunLoopSource = ::CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
   NS_ENSURE_STATE(mCFRunLoopSource);
 
   ::CFRunLoopAddSource(mCFRunLoop, mCFRunLoopSource, kCFRunLoopCommonModes);
 
   rv = nsBaseAppShell::Init();
 
-#ifndef __LP64__
-  TextInputHandler::InstallPluginKeyEventsHandler();
-#endif
-
   if (!gAppShellMethodsSwizzled) {
     // We should only replace the original terminate: method if we're not
     // running in a Cocoa embedder. See bug 604901.
     if (!mRunningCocoaEmbedded) {
       nsToolkit::SwizzleMethods([NSApplication class], @selector(terminate:),
                                 @selector(nsAppShell_NSApplication_terminate:));
     }
     gAppShellMethodsSwizzled = true;
@@ -667,20 +663,16 @@ nsAppShell::Exit(void)
   // But we should also complain about it (since it isn't quite kosher).
   if (mTerminated) {
     NS_WARNING("nsAppShell::Exit() called redundantly");
     return NS_OK;
   }
 
   mTerminated = true;
 
-#ifndef __LP64__
-  TextInputHandler::RemovePluginKeyEventsHandler();
-#endif
-
   // Quoting from Apple's doc on the [NSApplication stop:] method (from their
   // doc on the NSApplication class):  "If this method is invoked during a
   // modal event loop, it will break that loop but not the main event loop."
   // nsAppShell::Exit() shouldn't be called from a modal event loop.  So if
   // it is we complain about it (to users of debug builds) and call [NSApp
   // stop:] one extra time.  (I'm not sure if modal event loops can be nested
   // -- Apple's docs don't say one way or the other.  But the return value
   // of [NSApp _isRunningModal] doesn't change immediately after a call to
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -11,87 +11,36 @@
 #ifdef ACCESSIBILITY
 #include "mozilla/a11y/Accessible.h"
 #include "mozAccessibleProtocol.h"
 #endif
 
 #include "nsAutoPtr.h"
 #include "nsISupports.h"
 #include "nsBaseWidget.h"
-#include "nsIPluginInstanceOwner.h"
-#include "nsIPluginWidget.h"
 #include "nsWeakPtr.h"
 #include "TextInputHandler.h"
 #include "nsCocoaUtils.h"
 #include "gfxQuartzSurface.h"
 #include "GLContextTypes.h"
 #include "mozilla/Mutex.h"
 #include "nsRegion.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/UniquePtr.h"
 
 #include "nsString.h"
 #include "nsIDragService.h"
 
-#include "npapi.h"
-
 #import <Carbon/Carbon.h>
 #import <Cocoa/Cocoa.h>
 #import <AppKit/NSOpenGL.h>
 
-// The header files QuickdrawAPI.h and QDOffscreen.h are missing on OS X 10.7
-// and up (though the QuickDraw APIs defined in them are still present) -- so
-// we need to supply the relevant parts of their contents here.  It's likely
-// that Apple will eventually remove the APIs themselves (probably in OS X
-// 10.8), so we need to make them weak imports, and test for their presence
-// before using them.
-#ifdef __cplusplus
-extern "C" {
-#endif
-  #if !defined(__QUICKDRAWAPI__)
-
-  extern void SetPort(GrafPtr port)
-    __attribute__((weak_import));
-  extern void SetOrigin(short h, short v)
-    __attribute__((weak_import));
-  extern RgnHandle NewRgn(void)
-    __attribute__((weak_import));
-  extern void DisposeRgn(RgnHandle rgn)
-    __attribute__((weak_import));
-  extern void RectRgn(RgnHandle rgn, const Rect * r)
-    __attribute__((weak_import));
-  extern GDHandle GetMainDevice(void)
-    __attribute__((weak_import));
-  extern Boolean IsPortOffscreen(CGrafPtr port)
-    __attribute__((weak_import));
-  extern void SetPortVisibleRegion(CGrafPtr port, RgnHandle visRgn)
-    __attribute__((weak_import));
-  extern void SetPortClipRegion(CGrafPtr port, RgnHandle clipRgn)
-    __attribute__((weak_import));
-  extern CGrafPtr GetQDGlobalsThePort(void)
-    __attribute__((weak_import));
-
-  #endif /* __QUICKDRAWAPI__ */
-
-  #if !defined(__QDOFFSCREEN__)
-
-  extern void GetGWorld(CGrafPtr *  port, GDHandle *  gdh)
-    __attribute__((weak_import));
-  extern void SetGWorld(CGrafPtr port, GDHandle gdh)
-    __attribute__((weak_import));
-
-  #endif /* __QDOFFSCREEN__ */
-#ifdef __cplusplus
-}
-#endif
-
 class gfxASurface;
 class nsChildView;
 class nsCocoaWindow;
-union nsPluginPort;
 
 namespace {
 class GLPresenter;
 class RectTextureImage;
 }
 
 namespace mozilla {
 class VibrancyManager;
@@ -226,20 +175,16 @@ typedef NSInteger NSEventGestureAxis;
   // reference.  Ideally, this should be a strong reference but a ChildView
   // object can live longer than the mGeckoChild that owns it.  And if
   // mTextInputHandler were a strong reference, this would make it difficult
   // for Gecko's leak detector to detect leaked TextInputHandler objects.
   // This is initialized by [mozView installTextInputHandler:aHandler] and
   // cleared by [mozView uninstallTextInputHandler].
   mozilla::widget::TextInputHandler* mTextInputHandler;  // [WEAK]
 
-  BOOL mIsPluginView;
-  NPEventModel mPluginEventModel;
-  NPDrawingModel mPluginDrawingModel;
-
   // when mouseDown: is called, we store its event here (strong)
   NSEvent* mLastMouseDownEvent;
 
   // Whether the last mouse down event was blocked from Gecko.
   BOOL mBlockedLastMouseDown;
 
   // when acceptsFirstMouse: is called, we store the event here (strong)
   NSEvent* mClickThroughMouseDownEvent;
@@ -321,22 +266,16 @@ typedef NSInteger NSEventGestureAxis;
 
 - (void)sendMouseEnterOrExitEvent:(NSEvent*)aEvent
                             enter:(BOOL)aEnter
                              type:(mozilla::WidgetMouseEvent::exitType)aType;
 
 - (void)updateGLContext;
 - (void)_surfaceNeedsUpdate:(NSNotification*)notification;
 
-- (BOOL)isPluginView;
-
-// Are we processing an NSLeftMouseDown event that will fail to click through?
-// If so, we shouldn't focus or unfocus a plugin.
-- (BOOL)isInFailingLeftClickThrough;
-
 - (void)setGLContext:(NSOpenGLContext *)aGLContext;
 - (bool)preRender:(NSOpenGLContext *)aGLContext;
 - (void)postRender:(NSOpenGLContext *)aGLContext;
 
 - (BOOL)isCoveringTitlebar;
 
 - (NSColor*)vibrancyFillColorForWidgetType:(uint8_t)aWidgetType;
 - (NSColor*)vibrancyFontSmoothingBackgroundColorForWidgetType:(uint8_t)aWidgetType;
@@ -385,46 +324,38 @@ public:
   static void OnDestroyWindow(NSWindow* aWindow);
   static BOOL WindowAcceptsEvent(NSWindow* aWindow, NSEvent* aEvent,
                                  ChildView* aView, BOOL isClickThrough = NO);
   static void MouseExitedWindow(NSEvent* aEvent);
   static void MouseEnteredWindow(NSEvent* aEvent);
   static void ReEvaluateMouseEnterState(NSEvent* aEvent = nil, ChildView* aOldView = nil);
   static void ResendLastMouseMoveEvent();
   static ChildView* ViewForEvent(NSEvent* aEvent);
-  static void AttachPluginEvent(mozilla::WidgetMouseEventBase& aMouseEvent,
-                                ChildView* aView,
-                                NSEvent* aNativeMouseEvent,
-                                int aPluginEventType,
-                                void* aPluginEventHolder);
 
   static ChildView* sLastMouseEventView;
   static NSEvent* sLastMouseMoveEvent;
   static NSWindow* sWindowUnderMouse;
   static NSPoint sLastScrollEventScreenLocation;
 };
 
 //-------------------------------------------------------------------------
 //
 // nsChildView
 //
 //-------------------------------------------------------------------------
 
-class nsChildView : public nsBaseWidget,
-                    public nsIPluginWidget
+class nsChildView : public nsBaseWidget
 {
 private:
   typedef nsBaseWidget Inherited;
   typedef mozilla::layers::APZCTreeManager APZCTreeManager;
 
 public:
   nsChildView();
 
-  NS_DECL_ISUPPORTS_INHERITED
-
   // nsIWidget interface
   NS_IMETHOD              Create(nsIWidget *aParent,
                                  nsNativeWidget aNativeParent,
                                  const nsIntRect &aRect,
                                  nsDeviceContext *aContext,
                                  nsWidgetInitData *aInitData = nullptr);
 
   NS_IMETHOD              Destroy();
@@ -510,29 +441,16 @@ public:
                       DoCommandCallback aCallback,
                       void* aCallbackData,
                       uint32_t aGeckoKeyCode,
                       uint32_t aCocoaKeyCode);
   virtual nsIMEUpdatePreference GetIMEUpdatePreference() MOZ_OVERRIDE;
   NS_IMETHOD        GetToggledKeyState(uint32_t aKeyCode,
                                        bool* aLEDState);
 
-  // nsIPluginWidget
-  // outClipRect and outOrigin are in display pixels (not device pixels)
-  NS_IMETHOD        GetPluginClipRect(nsIntRect& outClipRect, nsIntPoint& outOrigin, bool& outWidgetVisible);
-  NS_IMETHOD        StartDrawPlugin();
-  NS_IMETHOD        EndDrawPlugin();
-  NS_IMETHOD        SetPluginInstanceOwner(nsIPluginInstanceOwner* aInstanceOwner);
-
-  NS_IMETHOD        SetPluginEventModel(int inEventModel);
-  NS_IMETHOD        GetPluginEventModel(int* outEventModel);
-  NS_IMETHOD        SetPluginDrawingModel(int inDrawingModel);
-
-  NS_IMETHOD        StartComplexTextInputForCurrentEvent();
-
   virtual nsTransparencyMode GetTransparencyMode();
   virtual void                SetTransparencyMode(nsTransparencyMode aMode);
 
   virtual nsresult SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout,
                                             int32_t aNativeKeyCode,
                                             uint32_t aModifierFlags,
                                             const nsAString& aCharacters,
                                             const nsAString& aUnmodifiedCharacters);
@@ -563,29 +481,24 @@ public:
   virtual void PostRender(LayerManagerComposite* aManager) MOZ_OVERRIDE;
   virtual void DrawWindowOverlay(LayerManagerComposite* aManager, nsIntRect aRect) MOZ_OVERRIDE;
 
   virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries);
 
   virtual void UpdateWindowDraggingRegion(const nsIntRegion& aRegion) MOZ_OVERRIDE;
   const nsIntRegion& GetDraggableRegion() { return mDraggableRegion; }
 
-  void              HidePlugin();
-  void              UpdatePluginPort();
-
   void              ResetParent();
 
   static bool DoHasPendingInputEvent();
   static uint32_t GetCurrentInputEventCount();
   static void UpdateCurrentInputEventCount();
 
   NSView<mozView>* GetEditorView();
 
-  bool IsPluginView() { return (mWindowType == eWindowType_plugin); }
-
   nsCocoaWindow*    GetXULWindowWidget();
 
   NS_IMETHOD        ReparentNativeWidget(nsIWidget* aNewParent);
 
   mozilla::widget::TextInputHandler* GetTextInputHandler()
   {
     return mTextInputHandler;
   }
@@ -705,31 +618,24 @@ protected:
   // Cached value of [mView backingScaleFactor], to avoid sending two obj-c
   // messages (respondsToSelector, backingScaleFactor) every time we need to
   // use it.
   // ** We'll need to reinitialize this if the backing resolution changes. **
   mutable CGFloat       mBackingScaleFactor;
 
   bool                  mVisible;
   bool                  mDrawing;
-  bool                  mPluginDrawing;
   bool                  mIsDispatchPaint; // Is a paint event being dispatched
 
-  NP_CGContext          mPluginCGContext;
-  nsIPluginInstanceOwner* mPluginInstanceOwner; // [WEAK]
-
   // Used in OMTC BasicLayers mode. Presents the BasicCompositor result
   // surface to the screen using an OpenGL context.
   nsAutoPtr<GLPresenter> mGLPresenter;
 
   nsRefPtr<APZCTreeManager> mAPZCTreeManager;
 
   mozilla::UniquePtr<mozilla::VibrancyManager> mVibrancyManager;
 
   static uint32_t sLastInputEventCount;
 
   void ReleaseTitlebarCGContext();
 };
 
-void NS_InstallPluginKeyEventsHandler();
-void NS_RemovePluginKeyEventsHandler();
-
 #endif // nsChildView_h_
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -26,32 +26,28 @@
 #include "nsFontMetrics.h"
 #include "nsIRollupListener.h"
 #include "nsViewManager.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIFile.h"
 #include "nsILocalFileMac.h"
 #include "nsGfxCIID.h"
 #include "nsIDOMSimpleGestureEvent.h"
-#include "nsNPAPIPluginInstance.h"
 #include "nsThemeConstants.h"
 #include "nsIWidgetListener.h"
 #include "nsIPresShell.h"
 
 #include "nsDragService.h"
 #include "nsClipboard.h"
 #include "nsCursorManager.h"
 #include "nsWindowMap.h"
 #include "nsCocoaFeatures.h"
 #include "nsCocoaUtils.h"
 #include "nsMenuUtilsX.h"
 #include "nsMenuBarX.h"
-#ifdef __LP64__
-#include "ComplexTextInputPanel.h"
-#endif
 #include "NativeKeyBindings.h"
 
 #include "gfxContext.h"
 #include "gfxQuartzSurface.h"
 #include "gfxUtils.h"
 #include "nsRegion.h"
 #include "Layers.h"
 #include "ClientLayerManager.h"
@@ -153,21 +149,16 @@ static uint32_t gNumberOfWidgetsNeedingE
 // set up a gecko mouse event based on a cocoa mouse event
 - (void) convertCocoaMouseWheelEvent:(NSEvent*)aMouseEvent
                         toGeckoEvent:(WidgetWheelEvent*)outWheelEvent;
 - (void) convertCocoaMouseEvent:(NSEvent*)aMouseEvent
                    toGeckoEvent:(WidgetInputEvent*)outGeckoEvent;
 
 - (NSMenu*)contextMenu;
 
-- (void)setIsPluginView:(BOOL)aIsPlugin;
-- (void)setPluginEventModel:(NPEventModel)eventModel;
-- (void)setPluginDrawingModel:(NPDrawingModel)drawingModel;
-- (NPDrawingModel)pluginDrawingModel;
-
 - (BOOL)isRectObscuredBySubview:(NSRect)inRect;
 
 - (void)processPendingRedraws;
 
 - (void)drawRect:(NSRect)aRect inContext:(CGContextRef)aContext;
 - (nsIntRegion)nativeDirtyRegionWithBoundingRect:(NSRect)aRect;
 - (BOOL)isUsingMainThreadOpenGL;
 - (BOOL)isUsingOpenGL;
@@ -457,23 +448,19 @@ nsChildView::nsChildView() : nsBaseWidge
 , mShowsResizeIndicator(false)
 , mHasRoundedBottomCorners(false)
 , mIsCoveringTitlebar(false)
 , mIsFullscreen(false)
 , mTitlebarCGContext(nullptr)
 , mBackingScaleFactor(0.0)
 , mVisible(false)
 , mDrawing(false)
-, mPluginDrawing(false)
 , mIsDispatchPaint(false)
-, mPluginInstanceOwner(nullptr)
 {
   EnsureLogInitialized();
-
-  memset(&mPluginCGContext, 0, sizeof(mPluginCGContext));
 }
 
 nsChildView::~nsChildView()
 {
   ReleaseTitlebarCGContext();
 
   // Notify the children that we're gone.  childView->ResetParent() can change
   // our list of children while it's being iterated, so the way we iterate the
@@ -511,18 +498,16 @@ void
 nsChildView::ReleaseTitlebarCGContext()
 {
   if (mTitlebarCGContext) {
     CGContextRelease(mTitlebarCGContext);
     mTitlebarCGContext = nullptr;
   }
 }
 
-NS_IMPL_ISUPPORTS_INHERITED(nsChildView, nsBaseWidget, nsIPluginWidget)
-
 nsresult nsChildView::Create(nsIWidget *aParent,
                              nsNativeWidget aNativeParent,
                              const nsIntRect &aRect,
                              nsDeviceContext *aContext,
                              nsWidgetInitData *aInitData)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
@@ -538,18 +523,16 @@ nsresult nsChildView::Create(nsIWidget *
 #ifdef __LP64__
     if (nsCocoaFeatures::OnLionOrLater()) {
       nsToolkit::SwizzleMethods([NSEvent class], @selector(addLocalMonitorForEventsMatchingMask:handler:),
                                 @selector(nsChildView_NSEvent_addLocalMonitorForEventsMatchingMask:handler:),
                                 true);
       nsToolkit::SwizzleMethods([NSEvent class], @selector(removeMonitor:),
                                 @selector(nsChildView_NSEvent_removeMonitor:), true);
     }
-#else
-    TextInputHandler::SwizzleMethods();
 #endif
     gChildViewMethodsSwizzled = true;
   }
 
   mBounds = aRect;
 
   // Ensure that the toolkit is created.
   nsToolkit::GetToolkit();
@@ -576,18 +559,16 @@ nsresult nsChildView::Create(nsIWidget *
   // that NS_NATIVE_WIDGET is the NSView.
   CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(mParentView);
   NSRect r = nsCocoaUtils::DevPixelsToCocoaPoints(mBounds, scaleFactor);
   mView = [(NSView<mozView>*)CreateCocoaView(r) retain];
   if (!mView) {
     return NS_ERROR_FAILURE;
   }
 
-  [(ChildView*)mView setIsPluginView:(mWindowType == eWindowType_plugin)];
-
   // If this view was created in a Gecko view hierarchy, the initial state
   // is hidden.  If the view is attached only to a native NSView but has
   // no Gecko parent (as in embedding), the initial state is visible.
   if (mParentWidget)
     [mView setHidden:YES];
   else
     mVisible = true;
 
@@ -734,28 +715,16 @@ void* nsChildView::GetNativeData(uint32_
 
     case NS_NATIVE_OFFSETX:
       retVal = 0;
       break;
 
     case NS_NATIVE_OFFSETY:
       retVal = 0;
       break;
-
-    case NS_NATIVE_PLUGIN_PORT:
-    case NS_NATIVE_PLUGIN_PORT_CG:
-    {
-      // The NP_CGContext pointer should always be NULL in the Cocoa event model.
-      if ([(ChildView*)mView pluginEventModel] == NPEventModelCocoa)
-        return nullptr;
-
-      UpdatePluginPort();
-      retVal = (void*)&mPluginCGContext;
-      break;
-    }
   }
 
   return retVal;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL;
 }
 
 #pragma mark -
@@ -795,60 +764,16 @@ bool nsChildView::IsVisible() const
   // mVisible does not accurately reflect the state of a hidden tabbed view
   // so verify that the view has a window as well
   // then check native widget hierarchy visibility
   return ([mView window] != nil) && !NSIsEmptyRect([mView visibleRect]);
 
   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
 }
 
-void nsChildView::HidePlugin()
-{
-  NS_ASSERTION(mWindowType == eWindowType_plugin,
-               "HidePlugin called on non-plugin view");
-}
-
-void nsChildView::UpdatePluginPort()
-{
-  NS_ASSERTION(mWindowType == eWindowType_plugin,
-               "UpdatePluginPort called on non-plugin view");
-
-  // [NSGraphicsContext currentContext] is supposed to "return the
-  // current graphics context of the current thread."  But sometimes
-  // (when called while mView isn't focused for drawing) it returns a
-  // graphics context for the wrong window.  [window graphicsContext]
-  // (which "provides the graphics context associated with the window
-  // for the current thread") seems always to return the "right"
-  // graphics context.  See bug 500130.
-  mPluginCGContext.context = NULL;
-  mPluginCGContext.window = NULL;
-}
-
-static void HideChildPluginViews(NSView* aView)
-{
-  NSArray* subviews = [aView subviews];
-
-  for (unsigned int i = 0; i < [subviews count]; ++i) {
-    NSView* view = [subviews objectAtIndex: i];
-
-    if (![view isKindOfClass:[ChildView class]])
-      continue;
-
-    ChildView* childview = static_cast<ChildView*>(view);
-    if ([childview isPluginView]) {
-      nsChildView* widget = static_cast<nsChildView*>([childview widget]);
-      if (widget) {
-        widget->HidePlugin();
-      }
-    } else {
-      HideChildPluginViews(view);
-    }
-  }
-}
-
 // Some NSView methods (e.g. setFrame and setHidden) invalidate the view's
 // bounds in our window. However, we don't want these invalidations because
 // they are unnecessary and because they actually slow us down since we
 // block on the compositor inside drawRect.
 // When we actually need something invalidated, there will be an explicit call
 // to Invalidate from Gecko, so turning these automatic invalidations off
 // won't hurt us in the non-OMTC case.
 // The invalidations inside these NSView methods happen via a call to the
@@ -878,18 +803,16 @@ NS_IMETHODIMP nsChildView::Show(bool aSt
     // no pool in place.
     nsAutoreleasePool localPool;
 
     ManipulateViewWithoutNeedingDisplay(mView, ^{
       [mView setHidden:!aState];
     });
 
     mVisible = aState;
-    if (!mVisible && IsPluginView())
-      HidePlugin();
   }
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 // Change the parent of this widget
 NS_IMETHODIMP
@@ -1037,17 +960,16 @@ NS_IMETHODIMP nsChildView::GetBounds(nsI
 }
 
 NS_IMETHODIMP nsChildView::GetClientBounds(nsIntRect &aRect)
 {
   GetBounds(aRect);
   if (!mParentWidget) {
     // For top level widgets we want the position on screen, not the position
     // of this view inside the window.
-    MOZ_ASSERT(mWindowType != eWindowType_plugin, "plugin widgets should have parents");
     aRect.MoveTo(WidgetToScreenOffset());
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP nsChildView::GetScreenBounds(nsIntRect &aRect)
 {
   GetBounds(aRect);
@@ -1088,23 +1010,16 @@ nsChildView::BackingScaleFactorChanged()
   mBackingScaleFactor = newScale;
 
   if (mWidgetListener && !mWidgetListener->GetXULWindow()) {
     nsIPresShell* presShell = mWidgetListener->GetPresShell();
     if (presShell) {
       presShell->BackingScaleFactorChanged();
     }
   }
-
-  if (IsPluginView()) {
-    nsEventStatus status = nsEventStatus_eIgnore;
-    WidgetGUIEvent guiEvent(true, NS_PLUGIN_RESOLUTION_CHANGED, this);
-    guiEvent.time = PR_IntervalNow();
-    DispatchEvent(&guiEvent, status);
-  }
 }
 
 int32_t
 nsChildView::RoundsWidgetCoordinatesTo()
 {
   if (BackingScaleFactor() == 2.0) {
     return 2;
   }
@@ -1234,218 +1149,16 @@ bool nsChildView::ShowsResizeIndicator(n
     corner = [topLevelView convertPoint:corner toView:mView];
     aResizerRect->SetRect(NSToIntRound(corner.x) - resizeIndicatorWidth,
                           NSToIntRound(corner.y) - resizeIndicatorHeight,
                           resizeIndicatorWidth, resizeIndicatorHeight);
   }
   return true;
 }
 
-// In QuickDraw mode the coordinate system used here should be that of the
-// browser window's content region (defined as everything but the 22-pixel
-// high titlebar).  But in CoreGraphics mode the coordinate system should be
-// that of the browser window as a whole (including its titlebar).  Both
-// coordinate systems have a top-left origin.  See bmo bug 474491.
-//
-// There's a bug in this method's code -- it currently uses the QuickDraw
-// coordinate system for both the QuickDraw and CoreGraphics drawing modes.
-// This bug is fixed by the patch for bug 474491.  But the Flash plugin (both
-// version 10.0.12.36 from Adobe and version 9.0 r151 from Apple) has Mozilla-
-// specific code to work around this bug, which breaks when we fix it (see bmo
-// bug 477077).  So we'll need to coordinate releasing a fix for this bug with
-// Adobe and other major plugin vendors that support the CoreGraphics mode.
-//
-// outClipRect and outOrigin are in display pixels, not device pixels.
-NS_IMETHODIMP nsChildView::GetPluginClipRect(nsIntRect& outClipRect, nsIntPoint& outOrigin, bool& outWidgetVisible)
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  NS_ASSERTION(mWindowType == eWindowType_plugin,
-               "GetPluginClipRect must only be called on a plugin widget");
-  if (mWindowType != eWindowType_plugin) return NS_ERROR_FAILURE;
-
-  NSWindow* window = [mView window];
-  if (!window) return NS_ERROR_FAILURE;
-
-  NSPoint viewOrigin = [mView convertPoint:NSZeroPoint toView:nil];
-  NSRect frame = [[window contentView] frame];
-  viewOrigin.y = frame.size.height - viewOrigin.y;
-
-  // set up the clipping region for plugins.
-  NSRect visibleBounds = [mView visibleRect];
-  NSPoint clipOrigin   = [mView convertPoint:visibleBounds.origin toView:nil];
-
-  // Convert from cocoa to QuickDraw coordinates
-  clipOrigin.y = frame.size.height - clipOrigin.y;
-
-  outClipRect.x = NSToIntRound(clipOrigin.x);
-  outClipRect.y = NSToIntRound(clipOrigin.y);
-
-  // need to convert view's origin to window coordinates.
-  // then, encode as "SetOrigin" ready values.
-  outOrigin.x = -NSToIntRound(viewOrigin.x);
-  outOrigin.y = -NSToIntRound(viewOrigin.y);
-
-  if (IsVisible() && [mView window] != nil) {
-    outClipRect.width  = NSToIntRound(visibleBounds.origin.x + visibleBounds.size.width) - NSToIntRound(visibleBounds.origin.x);
-    outClipRect.height = NSToIntRound(visibleBounds.origin.y + visibleBounds.size.height) - NSToIntRound(visibleBounds.origin.y);
-
-    if (mClipRects) {
-      nsIntRect clipBounds;
-      for (uint32_t i = 0; i < mClipRectCount; ++i) {
-        NSRect cocoaPoints = DevPixelsToCocoaPoints(mClipRects[i]);
-        clipBounds.UnionRect(clipBounds, nsIntRect(NSToIntRound(cocoaPoints.origin.x),
-                                                   NSToIntRound(cocoaPoints.origin.y),
-                                                   NSToIntRound(cocoaPoints.size.width),
-                                                   NSToIntRound(cocoaPoints.size.height)));
-      }
-      outClipRect.IntersectRect(outClipRect, clipBounds - outOrigin);
-    }
-
-    // XXXroc should this be !outClipRect.IsEmpty()?
-    outWidgetVisible = true;
-  }
-  else {
-    outClipRect.width = 0;
-    outClipRect.height = 0;
-    outWidgetVisible = false;
-  }
-
-  return NS_OK;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsChildView::StartDrawPlugin()
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
-
-  NS_ASSERTION(mWindowType == eWindowType_plugin,
-               "StartDrawPlugin must only be called on a plugin widget");
-  if (mWindowType != eWindowType_plugin) return NS_ERROR_FAILURE;
-
-  // This code is necessary for CoreGraphics in 32-bit builds.
-  // See comments below about why. In 64-bit CoreGraphics mode we will not keep
-  // this region up to date, plugins should not depend on it.
-#ifndef __LP64__
-  NSWindow* window = [mView window];
-  if (!window)
-    return NS_ERROR_FAILURE;
-
-  // In QuickDraw drawing mode we used to prevent reentrant handling of any
-  // plugin event. But in CoreGraphics drawing mode only do this if the current
-  // plugin event isn't an update/paint event.  This allows popupcontextmenu()
-  // to work properly from a plugin that supports the Cocoa event model,
-  // without regressing bug 409615.  See bug 435041.  (StartDrawPlugin() and
-  // EndDrawPlugin() wrap every call to nsIPluginInstance::HandleEvent() --
-  // not just calls that "draw" or paint.)
-  if (mIsDispatchPaint && mPluginDrawing) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // It appears that the WindowRef from which we get the plugin port undergoes the
-  // traditional BeginUpdate/EndUpdate cycle, which, if you recall, sets the visible
-  // region to the intersection of the visible region and the update region. Since
-  // we don't know here if we're being drawn inside a BeginUpdate/EndUpdate pair
-  // (which seem to occur in [NSWindow display]), and we don't want to have the burden
-  // of correctly doing Carbon invalidates of the plugin rect, we manually set the
-  // visible region to be the entire port every time. It is necessary to set up our
-  // window's port even for CoreGraphics plugins, because they may still use Carbon
-  // internally (see bug #420527 for details).
-  //
-  // Don't use this code if any of the QuickDraw APIs it currently requires are
-  // missing (as they probably will be on OS X 10.8 and up).
-  if (::NewRgn && ::GetQDGlobalsThePort && ::GetGWorld && ::SetGWorld &&
-      ::IsPortOffscreen && ::GetMainDevice && ::SetOrigin && ::RectRgn &&
-      ::SetPortVisibleRegion && ::SetPortClipRegion && ::DisposeRgn) {
-    RgnHandle pluginRegion = ::NewRgn();
-    if (pluginRegion) {
-      CGrafPtr port = ::GetWindowPort(WindowRef([window windowRef]));
-      bool portChanged = (port != CGrafPtr(::GetQDGlobalsThePort()));
-      CGrafPtr oldPort;
-      GDHandle oldDevice;
-
-      if (portChanged) {
-        ::GetGWorld(&oldPort, &oldDevice);
-        ::SetGWorld(port, ::IsPortOffscreen(port) ? nullptr : ::GetMainDevice());
-      }
-
-      ::SetOrigin(0, 0);
-
-      nsIntRect clipRect; // this is in native window coordinates
-      nsIntPoint origin;
-      bool visible;
-      GetPluginClipRect(clipRect, origin, visible);
-
-      // XXX if we're not visible, set an empty clip region?
-      Rect pluginRect;
-      ConvertGeckoRectToMacRect(clipRect, pluginRect);
-
-      ::RectRgn(pluginRegion, &pluginRect);
-      ::SetPortVisibleRegion(port, pluginRegion);
-      ::SetPortClipRegion(port, pluginRegion);
-
-      // now set up the origin for the plugin
-      ::SetOrigin(origin.x, origin.y);
-
-      ::DisposeRgn(pluginRegion);
-
-      if (portChanged) {
-        ::SetGWorld(oldPort, oldDevice);
-      }
-    }
-  }
-#endif
-
-  mPluginDrawing = true;
-  return NS_OK;
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
-}
-
-NS_IMETHODIMP nsChildView::EndDrawPlugin()
-{
-  NS_ASSERTION(mWindowType == eWindowType_plugin,
-               "EndDrawPlugin must only be called on a plugin widget");
-  if (mWindowType != eWindowType_plugin) return NS_ERROR_FAILURE;
-
-  mPluginDrawing = false;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsChildView::SetPluginInstanceOwner(nsIPluginInstanceOwner* aInstanceOwner)
-{
-  mPluginInstanceOwner = aInstanceOwner;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsChildView::SetPluginEventModel(int inEventModel)
-{
-  [(ChildView*)mView setPluginEventModel:(NPEventModel)inEventModel];
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsChildView::GetPluginEventModel(int* outEventModel)
-{
-  *outEventModel = [(ChildView*)mView pluginEventModel];
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsChildView::SetPluginDrawingModel(int inDrawingModel)
-{
-  [(ChildView*)mView setPluginDrawingModel:(NPDrawingModel)inDrawingModel];
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsChildView::StartComplexTextInputForCurrentEvent()
-{
-  return mTextInputHandler->StartComplexTextInputForCurrentEvent();
-}
-
 nsresult nsChildView::SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout,
                                                int32_t aNativeKeyCode,
                                                uint32_t aModifierFlags,
                                                const nsAString& aCharacters,
                                                const nsAString& aUnmodifiedCharacters)
 {
   return mTextInputHandler->SynthesizeNativeKeyEvent(aNativeKeyboardLayout,
                                                      aNativeKeyCode,
@@ -1455,18 +1168,20 @@ nsresult nsChildView::SynthesizeNativeKe
 }
 
 nsresult nsChildView::SynthesizeNativeMouseEvent(nsIntPoint aPoint,
                                                  uint32_t aNativeMessage,
                                                  uint32_t aModifierFlags)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
-  NSPoint pt =
-    nsCocoaUtils::DevPixelsToCocoaPoints(aPoint, BackingScaleFactor());
+  // We want Cocoa 'points' (where there is a 1:1 mapping from pixels on low-DPI
+  // devices and a 4:1 mapping from pixels on retina devices).  These correspond
+  // to Gecko device pixels, which is what we are given.
+  NSPoint pt = NSMakePoint(aPoint.x, aPoint.y);
 
   // Move the mouse cursor to the requested position and reconnect it to the mouse.
   CGWarpMouseCursorPosition(NSPointToCGPoint(pt));
   CGAssociateMouseAndMouseCursorPosition(true);
 
   // aPoint is given with the origin on the top left, but convertScreenToBase
   // expects a point in a coordinate system that has its origin on the bottom left.
   NSPoint screenPoint = NSMakePoint(pt.x, nsCocoaUtils::FlippedScreenY(pt.y));
@@ -1689,39 +1404,16 @@ inline uint16_t COLOR8TOCOLOR16(uint8_t 
   // return (color8 == 0xFF ? 0xFFFF : (color8 << 8));
   return (color8 << 8) | color8;  /* (color8 * 257) == (color8 * 0x0101) */
 }
 
 #pragma mark -
 
 nsresult nsChildView::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
 {
-  for (uint32_t i = 0; i < aConfigurations.Length(); ++i) {
-    const Configuration& config = aConfigurations[i];
-    nsChildView* child = static_cast<nsChildView*>(config.mChild);
-#ifdef DEBUG
-    nsWindowType kidType = child->WindowType();
-#endif
-    NS_ASSERTION(kidType == eWindowType_plugin,
-                 "Configured widget is not a plugin type");
-    NS_ASSERTION(child->GetParent() == this,
-                 "Configured widget is not a child of the right widget");
-
-    // nsIWidget::Show() doesn't get called on plugin widgets unless we call
-    // it from here.  See bug 592563.
-    child->Show(!config.mClipRegion.IsEmpty());
-
-    child->Resize(
-        config.mBounds.x, config.mBounds.y,
-        config.mBounds.width, config.mBounds.height,
-        false);
-
-    // Store the clip region here in case GetPluginClipRect needs it.
-    child->StoreWindowClipRegion(config.mClipRegion);
-  }
   return NS_OK;
 }
 
 // Invokes callback and ProcessEvent methods on Event Listener object
 NS_IMETHODIMP nsChildView::DispatchEvent(WidgetGUIEvent* event,
                                          nsEventStatus& aStatus)
 {
 #ifdef DEBUG
@@ -3221,31 +2913,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
 
 // initWithFrame:geckoChild:
 - (id)initWithFrame:(NSRect)inFrame geckoChild:(nsChildView*)inChild
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
   if ((self = [super initWithFrame:inFrame])) {
     mGeckoChild = inChild;
-    mIsPluginView = NO;
-#ifndef NP_NO_CARBON
-    // We don't support the Carbon event model but it's still the default
-    // model for i386 per NPAPI.
-    mPluginEventModel = NPEventModelCarbon;
-#else
-    mPluginEventModel = NPEventModelCocoa;
-#endif
-#ifndef NP_NO_QUICKDRAW
-    // We don't support the Quickdraw drawing model any more but it's still
-    // the default model for i386 per NPAPI.
-    mPluginDrawingModel = NPDrawingModelQuickDraw;
-#else
-    mPluginDrawingModel = NPDrawingModelCoreGraphics;
-#endif
     mPendingDisplay = NO;
     mBlockedLastMouseDown = NO;
     mExpectingWheelStop = NO;
 
     mLastMouseDownEvent = nil;
     mClickThroughMouseDownEvent = nil;
     mDragService = nullptr;
 
@@ -3268,24 +2945,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
 
     mTopLeftCornerMask = NULL;
   }
 
   // register for things we'll take from other applications
   [ChildView registerViewForDraggedTypes:self];
 
   [[NSNotificationCenter defaultCenter] addObserver:self
-                                           selector:@selector(windowBecameMain:)
-                                               name:NSWindowDidBecomeMainNotification
-                                             object:nil];
-  [[NSNotificationCenter defaultCenter] addObserver:self
-                                           selector:@selector(windowResignedMain:)
-                                               name:NSWindowDidResignMainNotification
-                                             object:nil];
-  [[NSNotificationCenter defaultCenter] addObserver:self
                                            selector:@selector(systemMetricsChanged)
                                                name:NSControlTintDidChangeNotification
                                              object:nil];
   [[NSNotificationCenter defaultCenter] addObserver:self
                                            selector:@selector(systemMetricsChanged)
                                                name:NSSystemColorsDidChangeNotification
                                              object:nil];
   // TODO: replace the string with the constant once we build with the 10.7 SDK
@@ -3392,56 +3061,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
   [[NSNotificationCenter defaultCenter] removeObserver:self];
   [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
 
   [super dealloc];
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
-- (void)updatePluginTopLevelWindowStatus:(BOOL)hasMain
-{
-  if (!mGeckoChild)
-    return;
-
-  WidgetPluginEvent pluginEvent(true, NS_PLUGIN_FOCUS_EVENT, mGeckoChild);
-  NPCocoaEvent cocoaEvent;
-  nsCocoaUtils::InitNPCocoaEvent(&cocoaEvent);
-  cocoaEvent.type = NPCocoaEventWindowFocusChanged;
-  cocoaEvent.data.focus.hasFocus = hasMain;
-  nsCocoaUtils::InitPluginEvent(pluginEvent, cocoaEvent);
-  mGeckoChild->DispatchWindowEvent(pluginEvent);
-}
-
-- (void)windowBecameMain:(NSNotification*)inNotification
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
-  if (mIsPluginView && mPluginEventModel == NPEventModelCocoa) {
-    if ((NSWindow*)[inNotification object] == [self window]) {
-      [self updatePluginTopLevelWindowStatus:YES];
-    }
-  }
-
-  NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-- (void)windowResignedMain:(NSNotification*)inNotification
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
-  if (mIsPluginView && mPluginEventModel == NPEventModelCocoa) {
-    if ((NSWindow*)[inNotification object] == [self window]) {
-      [self updatePluginTopLevelWindowStatus:NO];
-    }
-  }
-
-  NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
 - (void)widgetDestroyed
 {
   if (mTextInputHandler) {
     mTextInputHandler->OnDestroyWidget(mGeckoChild);
     mTextInputHandler = nullptr;
   }
   mGeckoChild = nullptr;
 
@@ -3563,100 +3192,17 @@ NSEvent* gLastDragMouseDownEvent = nil;
 // than the bottomLeft corner (standard cocoa origin).
 - (BOOL)isFlipped
 {
   return YES;
 }
 
 - (BOOL)isOpaque
 {
-  return [[self window] isOpaque] && !mIsPluginView;
-}
-
--(void)setIsPluginView:(BOOL)aIsPlugin
-{
-  mIsPluginView = aIsPlugin;
-}
-
--(BOOL)isPluginView
-{
-  return mIsPluginView;
-}
-
-- (NSView *)hitTest:(NSPoint)aPoint
-{
-  NSView* target = [super hitTest:aPoint];
-  if ((target == self) && [self isPluginView] && mGeckoChild) {
-    nsAutoRetainCocoaObject kungFuDeathGrip(self);
-
-    NSPoint cocoaLoc = [[self superview] convertPoint:aPoint toView:self];
-    LayoutDeviceIntPoint widgetLoc = LayoutDeviceIntPoint::FromUntyped(
-      mGeckoChild->CocoaPointsToDevPixels(cocoaLoc));
-
-    WidgetQueryContentEvent hitTest(true, NS_QUERY_DOM_WIDGET_HITTEST,
-                                    mGeckoChild);
-    hitTest.InitForQueryDOMWidgetHittest(widgetLoc);
-    // This might destroy our widget.
-    mGeckoChild->DispatchWindowEvent(hitTest);
-    if (!mGeckoChild) {
-      return nil;
-    }
-    if (hitTest.mSucceeded && !hitTest.mReply.mWidgetIsHit) {
-      return nil;
-    }
-  }
-  return target;
-}
-
-// Are we processing an NSLeftMouseDown event that will fail to click through?
-// If so, we shouldn't focus or unfocus a plugin.
-- (BOOL)isInFailingLeftClickThrough
-{
-  if (!mGeckoChild)
-    return NO;
-
-  if (!mClickThroughMouseDownEvent ||
-      [mClickThroughMouseDownEvent type] != NSLeftMouseDown)
-    return NO;
-
-  BOOL retval =
-    !ChildViewMouseTracker::WindowAcceptsEvent([self window],
-                                               mClickThroughMouseDownEvent,
-                                               self, true);
-
-  // If we return YES here, this will result in us not being focused,
-  // which will stop us receiving mClickThroughMouseDownEvent in
-  // [ChildView mouseDown:].  So we need to release and null-out
-  // mClickThroughMouseDownEvent here.
-  if (retval) {
-    [mClickThroughMouseDownEvent release];
-    mClickThroughMouseDownEvent = nil;
-  }
-
-  return retval;
-}
-
-- (void)setPluginEventModel:(NPEventModel)eventModel
-{
-  mPluginEventModel = eventModel;
-}
-
-- (void)setPluginDrawingModel:(NPDrawingModel)drawingModel
-{
-  mPluginDrawingModel = drawingModel;
-}
-
-- (NPEventModel)pluginEventModel
-{
-  return mPluginEventModel;
-}
-
-- (NPDrawingModel)pluginDrawingModel
-{
-  return mPluginDrawingModel;
+  return [[self window] isOpaque];
 }
 
 - (void)sendFocusEvent:(uint32_t)eventType
 {
   if (!mGeckoChild)
     return;
 
   nsEventStatus status = nsEventStatus_eIgnore;
@@ -3681,38 +3227,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
     // inactive because at that point we've already been made active.
     // Unfortunately, acceptsFirstMouse is called for PopupWindows even when
     // their parent window is active, so ignore this on them for now.
     mClickThroughMouseDownEvent = [aEvent retain];
   }
   return YES;
 }
 
-- (void)viewWillMoveToWindow:(NSWindow *)newWindow
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
-  if (!newWindow)
-    HideChildPluginViews(self);
-
-  [super viewWillMoveToWindow:newWindow];
-
-  NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
-- (void)viewDidMoveToWindow
-{
-  if (mPluginEventModel == NPEventModelCocoa &&
-      [self window] && [self isPluginView] && mGeckoChild) {
-    mGeckoChild->UpdatePluginPort();
-  }
-
-  [super viewDidMoveToWindow];
-}
-
 - (void)scrollRect:(NSRect)aRect by:(NSSize)offset
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   // Update any pending dirty rects to reflect the new scroll position
   if (mPendingDirtyRects) {
     unsigned int count = [mPendingDirtyRects count];
     for (unsigned int i = 0; i < count; ++i) {
@@ -3821,20 +3345,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
   }
 }
 
 - (void)drawRect:(NSRect)aRect inContext:(CGContextRef)aContext
 {
   if (!mGeckoChild || !mGeckoChild->IsVisible())
     return;
 
-  // Don't ever draw plugin views explicitly; they'll be drawn as part of their parent widget.
-  if (mIsPluginView)
-    return;
-
 #ifdef DEBUG_UPDATE
   nsIntRect geckoBounds;
   mGeckoChild->GetBounds(geckoBounds);
 
   fprintf (stderr, "---- Update[%p][%p] [%f %f %f %f] cgc: %p\n  gecko bounds: [%d %d %d %d]\n",
            self, mGeckoChild,
            aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height, aContext,
            geckoBounds.x, geckoBounds.y, geckoBounds.width, geckoBounds.height);
@@ -4919,26 +4439,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
   }
   geckoEvent.clickCount = clickCount;
 
   if (modifierFlags & NSControlKeyMask)
     geckoEvent.button = WidgetMouseEvent::eRightButton;
   else
     geckoEvent.button = WidgetMouseEvent::eLeftButton;
 
-  // Create event for use by plugins.
-  // This is going to our child view so we don't need to look up the destination
-  // event type.
-  NPCocoaEvent cocoaEvent;
-  ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent,
-                                           NPCocoaEventMouseDown,
-                                           &cocoaEvent);
-  // Don't lose possible changes made above to clickCount
-  cocoaEvent.data.mouse.clickCount = clickCount;
-
   mGeckoChild->DispatchWindowEvent(geckoEvent);
   mBlockedLastMouseDown = NO;
 
   // XXX maybe call markedTextSelectionChanged:client: here?
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
@@ -4946,33 +4456,24 @@ NSEvent* gLastDragMouseDownEvent = nil;
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   if (!mGeckoChild || mBlockedLastMouseDown)
     return;
 
   nsAutoRetainCocoaObject kungFuDeathGrip(self);
 
-  NPCocoaEvent cocoaEvent;
-
   WidgetMouseEvent geckoEvent(true, NS_MOUSE_BUTTON_UP, mGeckoChild,
                               WidgetMouseEvent::eReal);
   [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
   if ([theEvent modifierFlags] & NSControlKeyMask)
     geckoEvent.button = WidgetMouseEvent::eRightButton;
   else
     geckoEvent.button = WidgetMouseEvent::eLeftButton;
 
-  // Create event for use by plugins.
-  // This is going to our child view so we don't need to look up the destination
-  // event type.
-  ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent,
-                                           NPCocoaEventMouseUp,
-                                           &cocoaEvent);
-
   // This might destroy our widget (and null out mGeckoChild).
   bool defaultPrevented = mGeckoChild->DispatchWindowEvent(geckoEvent);
 
   // Check to see if we are double-clicking in the titlebar.
   CGFloat locationInTitlebar = [[self window] frame].size.height - [theEvent locationInWindow].y;
   LayoutDeviceIntPoint pos = geckoEvent.refPoint;
   if (!defaultPrevented && [theEvent clickCount] == 2 &&
       mGeckoChild->GetDraggableRegion().Contains(pos.x, pos.y) &&
@@ -4982,23 +4483,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
     if ([self shouldZoomOnDoubleClick]) {
       [[self window] performZoom:nil];
     } else if ([self shouldMinimizeOnTitlebarDoubleClick]) {
       NSButton *minimizeButton = [[self window] standardWindowButton:NSWindowMiniaturizeButton];
       [minimizeButton performClick:self];
     }
   }
 
-  // If our mouse-up event's location is over some other object (as might
-  // happen if it came at the end of a dragging operation), also send our
-  // Gecko frame a mouse-exit event.
-  if (mGeckoChild && mIsPluginView) {
-    ChildViewMouseTracker::ReEvaluateMouseEnterState(theEvent, self);
-  }
-
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 - (void)sendMouseEnterOrExitEvent:(NSEvent*)aEvent
                             enter:(BOOL)aEnter
                              type:(WidgetMouseEvent::exitType)aType
 {
   if (!mGeckoChild)
@@ -5007,25 +4501,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
   NSPoint windowEventLocation = nsCocoaUtils::EventLocationForWindow(aEvent, [self window]);
   NSPoint localEventLocation = [self convertPoint:windowEventLocation fromView:nil];
 
   uint32_t msg = aEnter ? NS_MOUSE_ENTER : NS_MOUSE_EXIT;
   WidgetMouseEvent event(true, msg, mGeckoChild, WidgetMouseEvent::eReal);
   event.refPoint = LayoutDeviceIntPoint::FromUntyped(
     mGeckoChild->CocoaPointsToDevPixels(localEventLocation));
 
-  // Create event for use by plugins.
-  // This is going to our child view so we don't need to look up the destination
-  // event type.
-  NPCocoaEvent cocoaEvent;
-  ChildViewMouseTracker::AttachPluginEvent(event, self, aEvent,
-                                           (msg == NS_MOUSE_ENTER) ?
-                                             NPCocoaEventMouseEntered : NPCocoaEventMouseExited,
-                                           &cocoaEvent);
-
   event.exit = aType;
 
   nsEventStatus status; // ignored
   mGeckoChild->DispatchEvent(&event, status);
 }
 
 - (void)updateWindowDraggableState
 {
@@ -5106,48 +4591,34 @@ NewCGSRegionFromRegion(const nsIntRegion
 
   if (!mGeckoChild)
     return;
 
   WidgetMouseEvent geckoEvent(true, NS_MOUSE_MOVE, mGeckoChild,
                               WidgetMouseEvent::eReal);
   [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
 
-  // Create event for use by plugins.
-  // This is going to our child view so we don't need to look up the destination
-  // event type.
-  NPCocoaEvent cocoaEvent;
-  ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent,
-                                           NPCocoaEventMouseMoved,
-                                           &cocoaEvent);
   mGeckoChild->DispatchWindowEvent(geckoEvent);
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 - (void)mouseDragged:(NSEvent*)theEvent
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   if (!mGeckoChild)
     return;
 
   gLastDragView = self;
 
-  NPCocoaEvent cocoaEvent;
-
   WidgetMouseEvent geckoEvent(true, NS_MOUSE_MOVE, mGeckoChild,
                               WidgetMouseEvent::eReal);
   [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
 
-  // create event for use by plugins
-  ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent,
-                                           NPCocoaEventMouseDragged,
-                                           &cocoaEvent);
-
   mGeckoChild->DispatchWindowEvent(geckoEvent);
 
   // Note, sending the above event might have destroyed our widget since we didn't retain.
   // Fine so long as we don't access any local variables from here on.
   gLastDragView = nil;
 
   // XXX maybe call markedTextSelectionChanged:client: here?
 
@@ -5166,22 +4637,16 @@ NewCGSRegionFromRegion(const nsIntRegion
 
   // The right mouse went down, fire off a right mouse down event to gecko
   WidgetMouseEvent geckoEvent(true, NS_MOUSE_BUTTON_DOWN, mGeckoChild,
                               WidgetMouseEvent::eReal);
   [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
   geckoEvent.button = WidgetMouseEvent::eRightButton;
   geckoEvent.clickCount = [theEvent clickCount];
 
-  // create event for use by plugins
-  NPCocoaEvent cocoaEvent;
-  ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent,
-                                           NPCocoaEventMouseDown,
-                                           &cocoaEvent);
-
   mGeckoChild->DispatchWindowEvent(geckoEvent);
   if (!mGeckoChild)
     return;
 
   // Let the superclass do the context menu stuff.
   [super rightMouseDown:theEvent];
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
@@ -5189,58 +4654,38 @@ NewCGSRegionFromRegion(const nsIntRegion
 
 - (void)rightMouseUp:(NSEvent *)theEvent
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   if (!mGeckoChild)
     return;
 
-  NPCocoaEvent cocoaEvent;
-
   WidgetMouseEvent geckoEvent(true, NS_MOUSE_BUTTON_UP, mGeckoChild,
                               WidgetMouseEvent::eReal);
   [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
   geckoEvent.button = WidgetMouseEvent::eRightButton;
   geckoEvent.clickCount = [theEvent clickCount];
 
-  // create event for use by plugins
-  ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent,
-                                           NPCocoaEventMouseUp,
-                                           &cocoaEvent);
-
   nsAutoRetainCocoaObject kungFuDeathGrip(self);
   mGeckoChild->DispatchWindowEvent(geckoEvent);
 
-  // If our mouse-up event's location is over some other object (as might
-  // happen if it came at the end of a dragging operation), also send our
-  // Gecko frame a mouse-exit event.
-  if (mGeckoChild && mIsPluginView) {
-    ChildViewMouseTracker::ReEvaluateMouseEnterState(theEvent, self);
-  }
-
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 - (void)rightMouseDragged:(NSEvent*)theEvent
 {
   if (!mGeckoChild)
     return;
 
   WidgetMouseEvent geckoEvent(true, NS_MOUSE_MOVE, mGeckoChild,
                               WidgetMouseEvent::eReal);
   [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
   geckoEvent.button = WidgetMouseEvent::eRightButton;
 
-  // create event for use by plugins
-  NPCocoaEvent cocoaEvent;
-  ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent,
-                                           NPCocoaEventMouseDragged,
-                                           &cocoaEvent);
-
   // send event into Gecko by going directly to the
   // the widget.
   mGeckoChild->DispatchWindowEvent(geckoEvent);
 }
 
 - (void)otherMouseDown:(NSEvent *)theEvent
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
@@ -5255,70 +4700,45 @@ NewCGSRegionFromRegion(const nsIntRegion
     return;
 
   WidgetMouseEvent geckoEvent(true, NS_MOUSE_BUTTON_DOWN, mGeckoChild,
                               WidgetMouseEvent::eReal);
   [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
   geckoEvent.button = WidgetMouseEvent::eMiddleButton;
   geckoEvent.clickCount = [theEvent clickCount];
 
-  // create event for use by plugins
-  NPCocoaEvent cocoaEvent;
-  ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent,
-                                           NPCocoaEventMouseDown,
-                                           &cocoaEvent);
-
   mGeckoChild->DispatchWindowEvent(geckoEvent);
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 - (void)otherMouseUp:(NSEvent *)theEvent
 {
   if (!mGeckoChild)
     return;
 
   WidgetMouseEvent geckoEvent(true, NS_MOUSE_BUTTON_UP, mGeckoChild,
                               WidgetMouseEvent::eReal);
   [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
   geckoEvent.button = WidgetMouseEvent::eMiddleButton;
 
-  // create event for use by plugins
-  NPCocoaEvent cocoaEvent;
-  ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent,
-                                           NPCocoaEventMouseUp,
-                                           &cocoaEvent);
-
   nsAutoRetainCocoaObject kungFuDeathGrip(self);
   mGeckoChild->DispatchWindowEvent(geckoEvent);
-
-  // If our mouse-up event's location is over some other object (as might
-  // happen if it came at the end of a dragging operation), also send our
-  // Gecko frame a mouse-exit event.
-  if (mGeckoChild && mIsPluginView) {
-    ChildViewMouseTracker::ReEvaluateMouseEnterState(theEvent, self);
-  }
 }
 
 - (void)otherMouseDragged:(NSEvent*)theEvent
 {
   if (!mGeckoChild)
     return;
 
   WidgetMouseEvent geckoEvent(true, NS_MOUSE_MOVE, mGeckoChild,
                               WidgetMouseEvent::eReal);
   [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
   geckoEvent.button = WidgetMouseEvent::eMiddleButton;
 
-  // create event for use by plugins
-  NPCocoaEvent cocoaEvent;
-  ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent,
-                                           NPCocoaEventMouseDragged,
-                                           &cocoaEvent);
-
   // send event into Gecko by going directly to the
   // the widget.
   mGeckoChild->DispatchWindowEvent(geckoEvent);
 }
 
 static int32_t RoundUp(double aDouble)
 {
   return aDouble < 0 ? static_cast<int32_t>(floor(aDouble)) :
@@ -5397,21 +4817,16 @@ static int32_t RoundUp(double aDouble)
   //       revert the sign.
   // wheelEvent.deltaZ = [theEvent deltaZ];
 
   if (!wheelEvent.deltaX && !wheelEvent.deltaY && !wheelEvent.deltaZ) {
     // No sense in firing off a Gecko event.
     return;
   }
 
-  NPCocoaEvent cocoaEvent;
-  ChildViewMouseTracker::AttachPluginEvent(wheelEvent, self, theEvent,
-                                           NPCocoaEventScrollWheel,
-                                           &cocoaEvent);
-
   mGeckoChild->DispatchWindowEvent(wheelEvent);
   if (!mGeckoChild) {
     return;
   }
 
 #ifdef __LP64__
   // overflowDeltaX and overflowDeltaY tell us when the user has tried to
   // scroll past the edge of a page (in those cases it's non-zero).
@@ -5521,17 +4936,17 @@ static int32_t RoundUp(double aDouble)
     }
   }
 }
 
 -(NSMenu*)menuForEvent:(NSEvent*)theEvent
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
-  if (!mGeckoChild || [self isPluginView])
+  if (!mGeckoChild)
     return nil;
 
   nsAutoRetainCocoaObject kungFuDeathGrip(self);
 
   [self maybeRollup:theEvent];
   if (!mGeckoChild)
     return nil;
 
@@ -5865,26 +5280,16 @@ static int32_t RoundUp(double aDouble)
   NS_ENSURE_TRUE(mTextInputHandler, [[self window] level]);
   return mTextInputHandler->GetWindowLevel();
 
   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSNormalWindowLevel);
 }
 
 #pragma mark -
 
-#ifdef __LP64__
-- (NSTextInputContext *)inputContext
-{
-  if (mIsPluginView && mPluginEventModel == NPEventModelCocoa)
-    return [[ComplexTextInputPanel sharedComplexTextInputPanel] inputContext];
-  else
-    return [super inputContext];
-}
-#endif
-
 // This is a private API that Cocoa uses.
 // Cocoa will call this after the menu system returns "NO" for "performKeyEquivalent:".
 // We want all they key events we can get so just return YES. In particular, this fixes
 // ctrl-tab - we don't get a "keyDown:" call for that without this.
 - (BOOL)_wantsKeyDownForEvent:(NSEvent*)event
 {
   return YES;
 }
@@ -5909,28 +5314,17 @@ static int32_t RoundUp(double aDouble)
   if (mGeckoChild && mTextInputHandler && mTextInputHandler->IsFocused()) {
 #ifdef MOZ_CRASHREPORTER
     NSWindow* window = [self window];
     NSString* info = [NSString stringWithFormat:@"\nview [%@], window [%@], key event [%@], window is key %i, is fullscreen %i, app is active %i",
                       self, window, theEvent, [window isKeyWindow], ([window styleMask] & (1 << 14)) != 0,
                       [NSApp isActive]];
     nsAutoCString additionalInfo([info UTF8String]);
 #endif
-    if (mIsPluginView) {
-      if (TextInputHandler::IsSecureEventInputEnabled()) {
-        #define CRASH_MESSAGE "While a plugin has focus, we must not be in secure mode"
-#ifdef MOZ_CRASHREPORTER
-        CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("\nBug 893973: ") +
-                                                   NS_LITERAL_CSTRING(CRASH_MESSAGE));
-        CrashReporter::AppendAppNotesToCrashReport(additionalInfo);
-#endif
-        MOZ_CRASH(CRASH_MESSAGE);
-        #undef CRASH_MESSAGE
-      }
-    } else if (mGeckoChild->GetInputContext().IsPasswordEditor() &&
+    if (mGeckoChild->GetInputContext().IsPasswordEditor() &&
                !TextInputHandler::IsSecureEventInputEnabled()) {
       #define CRASH_MESSAGE "A password editor has focus, but not in secure input mode"
 #ifdef MOZ_CRASHREPORTER
       CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("\nBug 893973: ") +
                                                  NS_LITERAL_CSTRING(CRASH_MESSAGE));
       CrashReporter::AppendAppNotesToCrashReport(additionalInfo);
 #endif
       MOZ_CRASH(CRASH_MESSAGE);
@@ -5944,21 +5338,16 @@ static int32_t RoundUp(double aDouble)
       CrashReporter::AppendAppNotesToCrashReport(additionalInfo);
 #endif
       MOZ_CRASH(CRASH_MESSAGE);
       #undef CRASH_MESSAGE
     }
   }
 #endif // #if !defined(RELEASE_BUILD) || defined(DEBUG)
 
-  if (mGeckoChild && mTextInputHandler && mIsPluginView) {
-    mTextInputHandler->HandleKeyDownEventForPlugin(theEvent);
-    return;
-  }
-
   nsAutoRetainCocoaObject kungFuDeathGrip(self);
   bool handled = false;
   if (mGeckoChild && mTextInputHandler) {
     handled = mTextInputHandler->HandleKeyDownEvent(theEvent);
   }
 
   // We always allow keyboard events to propagate to keyDown: but if they are not
   // handled we give special Application menu items a chance to act.
@@ -5972,21 +5361,16 @@ static int32_t RoundUp(double aDouble)
 - (void)keyUp:(NSEvent*)theEvent
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   NS_ENSURE_TRUE(mGeckoChild, );
 
   nsAutoRetainCocoaObject kungFuDeathGrip(self);
 
-  if (mIsPluginView) {
-    mTextInputHandler->HandleKeyUpEventForPlugin(theEvent);
-    return;
-  }
-
   mTextInputHandler->HandleKeyUpEvent(theEvent);
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 - (void)flagsChanged:(NSEvent*)theEvent
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
@@ -6026,70 +5410,27 @@ static int32_t RoundUp(double aDouble)
     return YES;
 
   WidgetMouseEvent geckoEvent(true, NS_MOUSE_ACTIVATE, mGeckoChild,
                               WidgetMouseEvent::eReal);
   [self convertCocoaMouseEvent:aEvent toGeckoEvent:&geckoEvent];
   return !mGeckoChild->DispatchWindowEvent(geckoEvent);
 }
 
-// Returns NO if the plugin shouldn't be focused/unfocused.
-- (BOOL)updatePluginFocusStatus:(BOOL)getFocus
-{
-  if (!mGeckoChild)
-    return NO;
-
-  if (mPluginEventModel == NPEventModelCocoa) {
-    WidgetPluginEvent pluginEvent(true, NS_PLUGIN_FOCUS_EVENT, mGeckoChild);
-    NPCocoaEvent cocoaEvent;
-    nsCocoaUtils::InitNPCocoaEvent(&cocoaEvent);
-    cocoaEvent.type = NPCocoaEventFocusChanged;
-    cocoaEvent.data.focus.hasFocus = getFocus;
-    nsCocoaUtils::InitPluginEvent(pluginEvent, cocoaEvent);
-    mGeckoChild->DispatchWindowEvent(pluginEvent);
-
-    if (getFocus)
-      [self sendFocusEvent:NS_PLUGIN_FOCUS];
-  }
-
-  return YES;
-}
-
 // We must always call through to our superclass, even when mGeckoChild is
 // nil -- otherwise the keyboard focus can end up in the wrong NSView.
 - (BOOL)becomeFirstResponder
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
 
-  if (mIsPluginView) {
-    if (![self updatePluginFocusStatus:YES])
-      return NO;
-  }
-
   return [super becomeFirstResponder];
 
   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(YES);
 }
 
-// We must always call through to our superclass, even when mGeckoChild is
-// nil -- otherwise the keyboard focus can end up in the wrong NSView.
-- (BOOL)resignFirstResponder
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
-
-  if (mIsPluginView) {
-    if (![self updatePluginFocusStatus:NO])
-      return NO;
-  }
-
-  return [super resignFirstResponder];
-
-  NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(YES);
-}
-
 - (void)viewsWindowDidBecomeKey
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   if (!mGeckoChild)
     return;
 
   nsAutoRetainCocoaObject kungFuDeathGrip(self);
@@ -6866,66 +6207,16 @@ ChildViewMouseTracker::ViewForEvent(NSEv
 
   ChildView* childView = (ChildView*)view;
   // If childView is being destroyed return nil.
   if (![childView widget])
     return nil;
   return WindowAcceptsEvent(window, aEvent, childView) ? childView : nil;
 }
 
-void
-ChildViewMouseTracker::AttachPluginEvent(WidgetMouseEventBase& aMouseEvent,
-                                         ChildView* aView,
-                                         NSEvent* aNativeMouseEvent,
-                                         int aPluginEventType,
-                                         void* aPluginEventHolder)
-{
-  if (![aView isPluginView] ||
-      [aView pluginEventModel] != NPEventModelCocoa) {
-    return;
-  }
-
-  NPCocoaEvent* cocoaEvent = (NPCocoaEvent*)aPluginEventHolder;
-  nsCocoaUtils::InitNPCocoaEvent(cocoaEvent);
-  NSPoint point = [aView convertPoint:[aNativeMouseEvent locationInWindow]
-                             fromView:nil];
-  NPCocoaEventType type = (NPCocoaEventType)aPluginEventType;
-  // XXX We should consider dropping this code, which causes data.mouse.pluginX
-  // and data.mouse.pluginY to be set to '5' for mouse-entered and mouse-exited
-  // events.  But note that it's been in the tree since the Cocoa NPAPI event
-  // model was first implemented four years ago, without any known complaints.
-  //
-  // Similar code first appeared (without explanation) in a very early version
-  // ("fix 0.3") of the patch for bug 435041 ("Implement Cocoa NPAPI event
-  // model for Mac OS X").  But there's no trace of it in the WebKit code that
-  // was used as a model for much of that patch.
-#if (0)
-  if (type == NPCocoaEventMouseEntered ||
-      type == NPCocoaEventMouseExited) {
-    point.x = point.y = 5;
-  }
-#endif
-  NSUInteger clickCount = 0;
-  if (type != NPCocoaEventMouseEntered &&
-      type != NPCocoaEventMouseExited &&
-      type != NPCocoaEventScrollWheel) {
-    clickCount = [aNativeMouseEvent clickCount];
-  }
-  cocoaEvent->type = type;
-  cocoaEvent->data.mouse.modifierFlags = [aNativeMouseEvent modifierFlags];
-  cocoaEvent->data.mouse.pluginX = point.x;
-  cocoaEvent->data.mouse.pluginY = point.y;
-  cocoaEvent->data.mouse.buttonNumber = [aNativeMouseEvent buttonNumber];
-  cocoaEvent->data.mouse.clickCount = clickCount;
-  cocoaEvent->data.mouse.deltaX = [aNativeMouseEvent deltaX];
-  cocoaEvent->data.mouse.deltaY = [aNativeMouseEvent deltaY];
-  cocoaEvent->data.mouse.deltaZ = [aNativeMouseEvent deltaZ];
-  aMouseEvent.mPluginEvent.Copy(*cocoaEvent);
-}
-
 BOOL
 ChildViewMouseTracker::WindowAcceptsEvent(NSWindow* aWindow, NSEvent* aEvent,
                                           ChildView* aView, BOOL aIsClickThrough)
 {
   // Right mouse down events may get through to all windows, even to a top level
   // window with an open sheet.
   if (!aWindow || [aEvent type] == NSRightMouseDown)
     return YES;
--- a/widget/cocoa/nsCocoaFeatures.h
+++ b/widget/cocoa/nsCocoaFeatures.h
@@ -17,17 +17,16 @@ public:
   static int32_t OSXVersion();
   static int32_t OSXVersionMajor();
   static int32_t OSXVersionMinor();
   static int32_t OSXVersionBugFix();
   static bool OnLionOrLater();
   static bool OnMountainLionOrLater();
   static bool OnMavericksOrLater();
   static bool OnYosemiteOrLater();
-  static bool SupportCoreAnimationPlugins();
   static bool AccelerateByDefault();
 
   static bool IsAtLeastVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix=0);
 
   // These are utilities that do not change or depend on the value of mOSXVersion
   // and instead just encapsulate the encoding algorithm.  Note that GetVersion
   // actually adjusts to the lowest supported OS, so it will always return
   // a "supported" version.  GetSystemVersion does not make any modifications.
--- a/widget/cocoa/nsCocoaFeatures.mm
+++ b/widget/cocoa/nsCocoaFeatures.mm
@@ -144,24 +144,16 @@ nsCocoaFeatures::OSXVersionMinor()
 
 /* static */ int32_t
 nsCocoaFeatures::OSXVersionBugFix()
 {
     return ExtractBugFixVersion(OSXVersion());
 }
 
 /* static */ bool
-nsCocoaFeatures::SupportCoreAnimationPlugins()
-{
-    // Disallow Core Animation on 10.5 because of crashes.
-    // See Bug 711564.
-    return (OSXVersion() >= MAC_OS_X_VERSION_10_6_HEX);
-}
-
-/* static */ bool
 nsCocoaFeatures::OnLionOrLater()
 {
     return (OSXVersion() >= MAC_OS_X_VERSION_10_7_HEX);
 }
 
 /* static */ bool
 nsCocoaFeatures::OnMountainLionOrLater()
 {
--- a/widget/cocoa/nsCocoaUtils.h
+++ b/widget/cocoa/nsCocoaUtils.h
@@ -316,21 +316,16 @@ public:
                                             NSEvent *aEvent);
 
   /**
    * Initializes aNPCocoaEvent.
    */
   static void InitNPCocoaEvent(NPCocoaEvent* aNPCocoaEvent);
 
   /**
-   * Initializes aPluginEvent for aCocoaEvent.
-   */
-  static void InitPluginEvent(mozilla::WidgetPluginEvent &aPluginEvent,
-                              NPCocoaEvent &aCocoaEvent);
-  /**
    * Initializes WidgetInputEvent for aNativeEvent or aModifiers.
    */
   static void InitInputEvent(mozilla::WidgetInputEvent &aInputEvent,
                              NSEvent* aNativeEvent);
   static void InitInputEvent(mozilla::WidgetInputEvent &aInputEvent,
                              NSUInteger aModifiers);
 
   /**
--- a/widget/cocoa/nsCocoaUtils.mm
+++ b/widget/cocoa/nsCocoaUtils.mm
@@ -603,26 +603,16 @@ nsCocoaUtils::MakeNewCocoaEventWithType(
 void
 nsCocoaUtils::InitNPCocoaEvent(NPCocoaEvent* aNPCocoaEvent)
 {
   memset(aNPCocoaEvent, 0, sizeof(NPCocoaEvent));
 }
 
 // static
 void
-nsCocoaUtils::InitPluginEvent(WidgetPluginEvent &aPluginEvent,
-                              NPCocoaEvent &aCocoaEvent)
-{
-  aPluginEvent.time = PR_IntervalNow();
-  aPluginEvent.mPluginEvent.Copy(aCocoaEvent);
-  aPluginEvent.retargetToFocusedDocument = false;
-}
-
-// static
-void
 nsCocoaUtils::InitInputEvent(WidgetInputEvent& aInputEvent,
                              NSEvent* aNativeEvent)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   NSUInteger modifiers =
     aNativeEvent ? [aNativeEvent modifierFlags] : [NSEvent modifierFlags];
   InitInputEvent(aInputEvent, modifiers);
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -136,22 +136,22 @@ void nsCocoaWindow::DestroyNativeWindow(
 }
 
 nsCocoaWindow::~nsCocoaWindow()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   // Notify the children that we're gone.  Popup windows (e.g. tooltips) can
   // have nsChildView children.  'kid' is an nsChildView object if and only if
-  // its 'type' is 'eWindowType_child' or 'eWindowType_plugin'.
+  // its 'type' is 'eWindowType_child'.
   // childView->ResetParent() can change our list of children while it's
   // being iterated, so the way we iterate the list must allow for this.
   for (nsIWidget* kid = mLastChild; kid;) {
     nsWindowType kidType = kid->WindowType();
-    if (kidType == eWindowType_child || kidType == eWindowType_plugin) {
+    if (kidType == eWindowType_child) {
       nsChildView* childView = static_cast<nsChildView*>(kid);
       kid = kid->GetPrevSibling();
       childView->ResetParent();
     } else {
       nsCocoaWindow* childWindow = static_cast<nsCocoaWindow*>(kid);
       childWindow->mParent = nullptr;
       kid = kid->GetPrevSibling();
     }
@@ -2498,28 +2498,30 @@ nsCocoaWindow::ExecuteNativeKeyBinding(N
 {
   return mToplevelActiveState;
 }
 
 - (void)sendToplevelActivateEvents
 {
   if (!mToplevelActiveState && mGeckoWindow) {
     nsIWidgetListener* listener = mGeckoWindow->GetWidgetListener();
-    if (listener)
+    if (listener) {
       listener->WindowActivated();
+    }
     mToplevelActiveState = true;
   }
 }
 
 - (void)sendToplevelDeactivateEvents
 {
   if (mToplevelActiveState && mGeckoWindow) {
     nsIWidgetListener* listener = mGeckoWindow->GetWidgetListener();
-    if (listener)
+    if (listener) {
       listener->WindowDeactivated();
+    }
     mToplevelActiveState = false;
   }
 }
 
 @end
 
 static float
 GetDPI(NSWindow* aWindow)
--- a/widget/cocoa/nsMenuBarX.mm
+++ b/widget/cocoa/nsMenuBarX.mm
@@ -827,50 +827,27 @@ static BOOL gMenuItemsExecuteCommands = 
 
   // If there is no key window then just behave normally. This
   // probably means that this menu is associated with Gecko's
   // hidden window.
   if (!keyWindow) {
     return [super performKeyEquivalent:theEvent];
   }
 
-  // Plugins normally eat all keyboard commands, this hack mitigates
-  // the problem.
-  BOOL handleForPluginHack = NO;
   NSResponder *firstResponder = [keyWindow firstResponder];
-  if (firstResponder &&
-      [firstResponder isKindOfClass:[ChildView class]] &&
-      [(ChildView*)firstResponder isPluginView]) {
-    handleForPluginHack = YES;
-    // Maintain a list of cmd+key combinations that we never act on (in the
-    // browser) when the keyboard focus is in a plugin.  What a particular
-    // cmd+key combo means here (to the browser) is governed by browser.dtd,
-    // which "contains the browser main menu items".
-    UInt32 modifierFlags = [theEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask;
-    if (modifierFlags == NSCommandKeyMask) {
-      NSString *unmodchars = [theEvent charactersIgnoringModifiers];
-      if ([unmodchars length] == 1) {
-        if ([unmodchars characterAtIndex:0] == nsMenuBarX::GetLocalizedAccelKey("key_selectAll")) {
-          handleForPluginHack = NO;
-        }
-      }
-    }
-  }
 
-  gMenuItemsExecuteCommands = handleForPluginHack;
+  gMenuItemsExecuteCommands = NO;
   [super performKeyEquivalent:theEvent];
   gMenuItemsExecuteCommands = YES; // return to default
 
   // Return YES if we invoked a command and there is now no key window or we changed
   // the first responder. In this case we do not want to propagate the event because
   // we don't want it handled again.
-  if (handleForPluginHack) {
-    if (![NSApp keyWindow] || [[NSApp keyWindow] firstResponder] != firstResponder) {
-      return YES;
-    }
+  if (![NSApp keyWindow] || [[NSApp keyWindow] firstResponder] != firstResponder) {
+    return YES;
   }
 
   // Return NO so that we can handle the event via NSView's "keyDown:".
   return NO;
 }
 
 @end
 
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -326,16 +326,22 @@ struct ParamTraits<mozilla::WidgetKeyboa
     WriteParam(aMsg, aParam.mCodeValue);
     WriteParam(aMsg, aParam.keyCode);
     WriteParam(aMsg, aParam.charCode);
     WriteParam(aMsg, aParam.alternativeCharCodes);
     WriteParam(aMsg, aParam.isChar);
     WriteParam(aMsg, aParam.mIsRepeat);
     WriteParam(aMsg, aParam.location);
     WriteParam(aMsg, aParam.mUniqueId);
+#ifdef XP_MACOSX
+    WriteParam(aMsg, aParam.mNativeKeyCode);
+    WriteParam(aMsg, aParam.mNativeModifierFlags);
+    WriteParam(aMsg, aParam.mNativeCharacters);
+    WriteParam(aMsg, aParam.mNativeCharactersIgnoringModifiers);
+#endif
     // An OS-specific native event might be attached in |mNativeKeyEvent|,  but
     // that cannot be copied across process boundaries.
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
     uint32_t keyNameIndex = 0, codeNameIndex = 0;
     if (ReadParam(aMsg, aIter,
@@ -345,17 +351,24 @@ struct ParamTraits<mozilla::WidgetKeyboa
         ReadParam(aMsg, aIter, &aResult->mKeyValue) &&
         ReadParam(aMsg, aIter, &aResult->mCodeValue) &&
         ReadParam(aMsg, aIter, &aResult->keyCode) &&
         ReadParam(aMsg, aIter, &aResult->charCode) &&
         ReadParam(aMsg, aIter, &aResult->alternativeCharCodes) &&
         ReadParam(aMsg, aIter, &aResult->isChar) &&
         ReadParam(aMsg, aIter, &aResult->mIsRepeat) &&
         ReadParam(aMsg, aIter, &aResult->location) &&
-        ReadParam(aMsg, aIter, &aResult->mUniqueId))
+        ReadParam(aMsg, aIter, &aResult->mUniqueId)
+#ifdef XP_MACOSX
+        && ReadParam(aMsg, aIter, &aResult->mNativeKeyCode)
+        && ReadParam(aMsg, aIter, &aResult->mNativeModifierFlags)
+        && ReadParam(aMsg, aIter, &aResult->mNativeCharacters)
+        && ReadParam(aMsg, aIter, &aResult->mNativeCharactersIgnoringModifiers)
+#endif
+        )
     {
       aResult->mKeyNameIndex = static_cast<mozilla::KeyNameIndex>(keyNameIndex);
       aResult->mCodeNameIndex =
         static_cast<mozilla::CodeNameIndex>(codeNameIndex);
       aResult->mNativeKeyEvent = nullptr;
       return true;
     }
     return false;