Bug 586656 - Serialize external "pluginEvent" structs in WidgetGUIEvent so that plugin events work in e10s - r=masayuki,jimm
authorBenoit Jacob <bjacob@mozilla.com>
Wed, 23 Jul 2014 15:55:51 -0400
changeset 195900 8581ea023552d4bfc30bfce7dd17d0c3efc5ac24
parent 195899 c3fbc38340b8eefc8ec266d9ee05d47d94dee487
child 195901 bda1cceef8d22643b72ceefe2b95d31cd4c79663
push id46729
push userbjacob@mozilla.com
push dateThu, 24 Jul 2014 17:39:50 +0000
treeherdermozilla-inbound@8581ea023552 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki, jimm
bugs586656
milestone34.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 586656 - Serialize external "pluginEvent" structs in WidgetGUIEvent so that plugin events work in e10s - r=masayuki,jimm
dom/events/EventStateManager.cpp
dom/plugins/base/nsPluginInstanceOwner.cpp
widget/BasicEvents.h
widget/android/nsWindow.cpp
widget/cocoa/TextInputHandler.mm
widget/cocoa/nsChildView.mm
widget/cocoa/nsCocoaUtils.mm
widget/gtk/nsGtkKeyUtils.cpp
widget/nsGUIEventIPC.h
widget/qt/nsWindow.cpp
widget/windows/KeyboardLayout.cpp
widget/windows/nsWindow.cpp
widget/windows/nsWindowBase.cpp
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -3600,17 +3600,17 @@ CreateMouseOrPointerWidgetEvent(WidgetMo
                            aMouseEvent->widget, WidgetMouseEvent::eReal);
     aNewEvent->relatedTarget = aRelatedContent;
   }
   aNewEvent->refPoint = aMouseEvent->refPoint;
   aNewEvent->modifiers = aMouseEvent->modifiers;
   aNewEvent->button = aMouseEvent->button;
   aNewEvent->buttons = aMouseEvent->buttons;
   aNewEvent->pressure = aMouseEvent->pressure;
-  aNewEvent->pluginEvent = aMouseEvent->pluginEvent;
+  aNewEvent->mPluginEvent = aMouseEvent->mPluginEvent;
   aNewEvent->inputSource = aMouseEvent->inputSource;
 }
 
 nsIFrame*
 EventStateManager::DispatchMouseOrPointerEvent(WidgetMouseEvent* aMouseEvent,
                                                uint32_t aMessage,
                                                nsIContent* aTargetContent,
                                                nsIContent* aRelatedContent)
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1807,17 +1807,17 @@ nsEventStatus nsPluginInstanceOwner::Pro
   nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
   if (!pluginWidget || NS_FAILED(pluginWidget->StartDrawPlugin()))
     return nsEventStatus_eIgnore;
 
   NPEventModel eventModel = GetEventModel();
 
   // If we have to synthesize an event we'll use one of these.
   NPCocoaEvent synthCocoaEvent;
-  void* event = anEvent.pluginEvent;
+  const NPCocoaEvent* event = static_cast<const NPCocoaEvent*>(anEvent.mPluginEvent);
   nsPoint pt =
   nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) -
   mObjectFrame->GetContentRectRelativeToSelf().TopLeft();
   nsPresContext* presContext = mObjectFrame->PresContext();
   // Plugin event coordinates need to be translated from device pixels
   // into "display pixels" in HiDPI modes.
   double scaleFactor = 1.0;
   GetContentsScaleFactor(&scaleFactor);
@@ -1874,17 +1874,19 @@ nsEventStatus nsPluginInstanceOwner::Pro
       pluginWidget->EndDrawPlugin();
       return nsEventStatus_eIgnore;
     }
   }
 
   int16_t response = kNPEventNotHandled;
   void* window = FixUpPluginWindow(ePluginPaintEnable);
   if (window || (eventModel == NPEventModelCocoa)) {
-    mInstance->HandleEvent(event, &response, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
+    mInstance->HandleEvent(const_cast<NPCocoaEvent*>(event),
+                           &response,
+                           NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
   }
 
   if (eventModel == NPEventModelCocoa && response == kNPEventStartIME) {
     pluginWidget->StartComplexTextInputForCurrentEvent();
   }
 
   if ((response == kNPEventHandled || response == kNPEventStartIME) &&
       !(anEvent.message == NS_MOUSE_BUTTON_DOWN &&
@@ -1893,17 +1895,17 @@ nsEventStatus nsPluginInstanceOwner::Pro
     rv = nsEventStatus_eConsumeNoDefault;
   }
 
   pluginWidget->EndDrawPlugin();
 #endif
 
 #ifdef XP_WIN
   // this code supports windowless plugins
-  NPEvent *pPluginEvent = (NPEvent*)anEvent.pluginEvent;
+  const NPEvent *pPluginEvent = static_cast<const NPEvent*>(anEvent.mPluginEvent);
   // we can get synthetic events from the EventStateManager... these
   // have no pluginEvent
   NPEvent pluginEvent;
   if (anEvent.eventStructType == NS_MOUSE_EVENT) {
     if (!pPluginEvent) {
       // XXX Should extend this list to synthesize events for more event
       // types
       pluginEvent.event = 0;
@@ -1962,17 +1964,17 @@ nsEventStatus nsPluginInstanceOwner::Pro
                    "Incorrect event type for coordinate translation");
       nsPoint pt =
         nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) -
         mObjectFrame->GetContentRectRelativeToSelf().TopLeft();
       nsPresContext* presContext = mObjectFrame->PresContext();
       nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x),
                       presContext->AppUnitsToDevPixels(pt.y));
       nsIntPoint widgetPtPx = ptPx + mObjectFrame->GetWindowOriginInPixels(true);
-      pPluginEvent->lParam = MAKELPARAM(widgetPtPx.x, widgetPtPx.y);
+      const_cast<NPEvent*>(pPluginEvent)->lParam = MAKELPARAM(widgetPtPx.x, widgetPtPx.y);
     }
   }
   else if (!pPluginEvent) {
     switch (anEvent.message) {
       case NS_FOCUS_CONTENT:
         pluginEvent.event = WM_SETFOCUS;
         pluginEvent.wParam = 0;
         pluginEvent.lParam = 0;
@@ -1990,17 +1992,19 @@ nsEventStatus nsPluginInstanceOwner::Pro
   if (pPluginEvent && !pPluginEvent->event) {
     // Don't send null events to plugins.
     NS_WARNING("nsObjectFrame ProcessEvent: trying to send null event to plugin.");
     return rv;
   }
 
   if (pPluginEvent) {
     int16_t response = kNPEventNotHandled;
-    mInstance->HandleEvent(pPluginEvent, &response, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
+    mInstance->HandleEvent(const_cast<NPEvent*>(pPluginEvent),
+                           &response,
+                           NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
     if (response == kNPEventHandled)
       rv = nsEventStatus_eConsumeNoDefault;
   }
 #endif
 
 #ifdef MOZ_X11
   // this code supports windowless plugins
   nsIWidget* widget = anEvent.widget;
@@ -2112,24 +2116,24 @@ nsEventStatus nsPluginInstanceOwner::Pro
             break;
           }
       }
       break;
 
    //XXX case NS_MOUSE_SCROLL_EVENT: not received.
 
    case NS_KEY_EVENT:
-      if (anEvent.pluginEvent)
+      if (anEvent.mPluginEvent)
         {
           XKeyEvent &event = pluginEvent.xkey;
 #ifdef MOZ_WIDGET_GTK
           event.root = GDK_ROOT_WINDOW();
           event.time = anEvent.time;
           const GdkEventKey* gdkEvent =
-            static_cast<const GdkEventKey*>(anEvent.pluginEvent);
+            static_cast<const GdkEventKey*>(anEvent.mPluginEvent);
           event.keycode = gdkEvent->hardware_keycode;
           event.state = gdkEvent->state;
           switch (anEvent.message)
             {
             case NS_KEY_DOWN:
               // Handle NS_KEY_DOWN for modifier key presses
               // For non-modifiers we get NS_KEY_PRESS
               if (gdkEvent->is_modifier)
@@ -2264,21 +2268,23 @@ nsEventStatus nsPluginInstanceOwner::Pro
       }
       break;
 
     case NS_KEY_EVENT:
      {
        const WidgetKeyboardEvent& keyEvent = *anEvent.AsKeyboardEvent();
        LOG("Firing NS_KEY_EVENT %d %d\n", keyEvent.keyCode, keyEvent.charCode);
        // pluginEvent is initialized by nsWindow::InitKeyEvent().
-       ANPEvent* pluginEvent = reinterpret_cast<ANPEvent*>(keyEvent.pluginEvent);
+       const ANPEvent* pluginEvent = static_cast<const ANPEvent*>(keyEvent.mPluginEvent);
        if (pluginEvent) {
          MOZ_ASSERT(pluginEvent->inSize == sizeof(ANPEvent));
          MOZ_ASSERT(pluginEvent->eventType == kKey_ANPEventType);
-         mInstance->HandleEvent(pluginEvent, nullptr, NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
+         mInstance->HandleEvent(const_cast<ANPEvent*>(pluginEvent),
+                                nullptr,
+                                NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
        }
      }
      break;
 
     default:
       break;
     }
     rv = nsEventStatus_eConsumeNoDefault;
@@ -2982,17 +2988,17 @@ void* nsPluginInstanceOwner::FixUpPlugin
     // 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.pluginEvent = &cocoaEvent;
+    pluginEvent.mPluginEvent.Copy(cocoaEvent);
     ProcessEvent(pluginEvent);
   }
 
   return nullptr;
 }
 
 void
 nsPluginInstanceOwner::HidePluginWindow()
--- a/widget/BasicEvents.h
+++ b/widget/BasicEvents.h
@@ -475,16 +475,21 @@ enum nsEventStructType
 // Keep this defined to the same value as the event above
 #define NS_GAMEPAD_END           (NS_GAMEPAD_START+4)
 #endif
 
 // input and beforeinput events.
 #define NS_EDITOR_EVENT_START    6100
 #define NS_EDITOR_INPUT          (NS_EDITOR_EVENT_START)
 
+namespace IPC {
+template<typename T>
+struct ParamTraits;
+}
+
 namespace mozilla {
 
 /******************************************************************************
  * mozilla::BaseEventFlags
  *
  * BaseEventFlags must be a POD struct for safe to use memcpy (including
  * in ParamTraits<BaseEventFlags>).  So don't make virtual methods, constructor,
  * destructor and operators.
@@ -833,31 +838,30 @@ public:
  ******************************************************************************/
 
 class WidgetGUIEvent : public WidgetEvent
 {
 protected:
   WidgetGUIEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget,
                  nsEventStructType aStructType) :
     WidgetEvent(aIsTrusted, aMessage, aStructType),
-    widget(aWidget), pluginEvent(nullptr)
+    widget(aWidget)
   {
   }
 
-  WidgetGUIEvent() :
-    pluginEvent(nullptr)
+  WidgetGUIEvent()
   {
   }
 
 public:
   virtual WidgetGUIEvent* AsGUIEvent() MOZ_OVERRIDE { return this; }
 
   WidgetGUIEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
     WidgetEvent(aIsTrusted, aMessage, NS_GUI_EVENT),
-    widget(aWidget), pluginEvent(nullptr)
+    widget(aWidget)
   {
   }
 
   virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
   {
     MOZ_ASSERT(eventStructType == NS_GUI_EVENT ||
                  eventStructType == NS_SVGZOOM_EVENT,
                "Duplicate() must be overridden by sub class");
@@ -866,28 +870,87 @@ public:
     result->AssignGUIEventData(*this, true);
     result->mFlags = mFlags;
     return result;
   }
 
   /// Originator of the event
   nsCOMPtr<nsIWidget> widget;
 
+  /*
+   * Explanation for this PluginEvent class:
+   *
+   * WidgetGUIEvent's mPluginEvent member used to be a void* pointer,
+   * used to reference external, OS-specific data structures.
+   *
+   * That void* pointer wasn't serializable by itself, causing
+   * certain plugin events not to function in e10s. See bug 586656.
+   *
+   * To make this serializable, we changed this void* pointer into
+   * a proper buffer, and copy these external data structures into this
+   * buffer.
+   *
+   * That buffer is PluginEvent::mBuffer below.
+   *
+   * We wrap this in that PluginEvent class providing operators to
+   * be compatible with existing code that was written around
+   * the old void* field.
+   *
+   * Ideally though, we wouldn't allow arbitrary reinterpret_cast'ing here;
+   * instead, we would at least store type information here so that
+   * this class can't be used to reinterpret one structure type into another.
+   * We can also wonder if it would be possible to properly extend
+   * WidgetGUIEvent and other Event classes to remove the need for this
+   * mPluginEvent field.
+   */
+  class PluginEvent MOZ_FINAL
+  {
+    nsTArray<uint8_t> mBuffer;
+
+    friend struct IPC::ParamTraits<mozilla::WidgetGUIEvent>;
+
+  public:
+
+    MOZ_EXPLICIT_CONVERSION operator bool() const
+    {
+      return !mBuffer.IsEmpty();
+    }
+
+    template<typename T>
+    MOZ_EXPLICIT_CONVERSION operator const T*() const
+    {
+      return mBuffer.IsEmpty()
+             ? nullptr
+             : reinterpret_cast<const T*>(mBuffer.Elements());
+    }
+
+    template <typename T>
+    void Copy(const T& other)
+    {
+      static_assert(!mozilla::IsPointer<T>::value, "Don't want a pointer!");
+      mBuffer.SetLength(sizeof(T));
+      memcpy(mBuffer.Elements(), &other, mBuffer.Length());
+    }
+
+    void Clear()
+    {
+      mBuffer.Clear();
+    }
+  };
+
   /// Event for NPAPI plugin
-  void* pluginEvent;
+  PluginEvent mPluginEvent;
 
   void AssignGUIEventData(const WidgetGUIEvent& aEvent, bool aCopyTargets)
   {
     AssignEventData(aEvent, aCopyTargets);
 
     // widget should be initialized with the constructor.
 
-    // pluginEvent shouldn't be copied because it may be referred after its
-    // instance is destroyed.
-    pluginEvent = nullptr;
+    mPluginEvent = aEvent.mPluginEvent;
   }
 };
 
 /******************************************************************************
  * mozilla::Modifier
  *
  * All modifier keys should be defined here.  This is used for managing
  * modifier states for DOM Level 3 or later.
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -1443,34 +1443,34 @@ nsWindow::InitKeyEvent(WidgetKeyboardEve
         // Android gives us \n, so filter out some control characters.
         int charCode = key.UnicodeChar();
         if (!charCode) {
             charCode = key.BaseUnicodeChar();
         }
         event.isChar = (charCode >= ' ');
         event.charCode = event.isChar ? charCode : 0;
         event.keyCode = (event.charCode > 0) ? 0 : domKeyCode;
-        event.pluginEvent = nullptr;
+        event.mPluginEvent.Clear();
     } else {
 #ifdef DEBUG
         if (event.message != NS_KEY_DOWN && event.message != NS_KEY_UP) {
             ALOG("InitKeyEvent: unexpected event.message %d", event.message);
         }
 #endif // DEBUG
 
         // Flash will want a pluginEvent for keydown and keyup events.
         ANPKeyActions action = event.message == NS_KEY_DOWN
                              ? kDown_ANPKeyAction
                              : kUp_ANPKeyAction;
         InitPluginEvent(pluginEvent, action, key);
 
         event.isChar = false;
         event.charCode = 0;
         event.keyCode = domKeyCode;
-        event.pluginEvent = pluginEvent;
+        event.mPluginEvent.Copy(*pluginEvent);
     }
 
     event.modifiers = key.DOMModifiers();
     if (gMenu) {
         event.modifiers |= MODIFIER_CONTROL;
     }
     // For keypress, if the unicode char already has modifiers applied, we
     // don't specify extra modifiers. If UnicodeChar() != BaseUnicodeChar()
--- a/widget/cocoa/TextInputHandler.mm
+++ b/widget/cocoa/TextInputHandler.mm
@@ -2024,17 +2024,17 @@ TextInputHandler::DispatchKeyEventForFla
   // 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.pluginEvent = &cocoaEvent;
+      keyEvent.mPluginEvent.Copy(cocoaEvent);
     }
   }
 
   DispatchEvent(keyEvent);
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
@@ -3885,17 +3885,17 @@ PluginTextInputHandler::HandleCarbonPlug
       nsCocoaUtils::InitInputEvent(keydownEvent, cocoaModifiers);
 
       uint32_t keyCode =
         currentInputSource.ComputeGeckoKeyCode(macKeyCode, ::LMGetKbdType(),
                                                keydownEvent.IsMeta());
       uint32_t charCode(charCodes.ElementAt(i));
 
       keydownEvent.time = PR_IntervalNow();
-      keydownEvent.pluginEvent = &eventRec;
+      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);
@@ -4075,17 +4075,17 @@ PluginTextInputHandler::HandleKeyUpEvent
     if (IsInPluginComposition()) {
       return;
     }
 
     WidgetKeyboardEvent keyupEvent(true, NS_KEY_UP, mWidget);
     InitKeyEvent(aNativeKeyEvent, keyupEvent);
     NPCocoaEvent pluginEvent;
     ConvertCocoaKeyEventToNPCocoaEvent(aNativeKeyEvent, pluginEvent);
-    keyupEvent.pluginEvent = &pluginEvent;
+    keyupEvent.mPluginEvent.Copy(pluginEvent);
     DispatchEvent(keyupEvent);
     return;
   }
 }
 
 bool
 PluginTextInputHandler::IsInPluginComposition()
 {
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -6629,17 +6629,17 @@ ChildViewMouseTracker::AttachPluginEvent
   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.pluginEvent = cocoaEvent;
+  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.
--- a/widget/cocoa/nsCocoaUtils.mm
+++ b/widget/cocoa/nsCocoaUtils.mm
@@ -602,17 +602,17 @@ nsCocoaUtils::InitNPCocoaEvent(NPCocoaEv
 }
 
 // static
 void
 nsCocoaUtils::InitPluginEvent(WidgetPluginEvent &aPluginEvent,
                               NPCocoaEvent &aCocoaEvent)
 {
   aPluginEvent.time = PR_IntervalNow();
-  aPluginEvent.pluginEvent = (void*)&aCocoaEvent;
+  aPluginEvent.mPluginEvent.Copy(aCocoaEvent);
   aPluginEvent.retargetToFocusedDocument = false;
 }
 
 // static
 void
 nsCocoaUtils::InitInputEvent(WidgetInputEvent& aInputEvent,
                              NSEvent* aNativeEvent)
 {
--- a/widget/gtk/nsGtkKeyUtils.cpp
+++ b/widget/gtk/nsGtkKeyUtils.cpp
@@ -1000,17 +1000,17 @@ KeymapWrapper::InitKeyEvent(WidgetKeyboa
     if (aKeyEvent.message == NS_KEY_PRESS) {
         keymapWrapper->InitKeypressEvent(aKeyEvent, aGdkKeyEvent);
     }
 
     // The transformations above and in gdk for the keyval are not invertible
     // so link to the GdkEvent (which will vanish soon after return from the
     // event callback) to give plugins access to hardware_keycode and state.
     // (An XEvent would be nice but the GdkEvent is good enough.)
-    aKeyEvent.pluginEvent = (void *)aGdkKeyEvent;
+    aKeyEvent.mPluginEvent.Copy(*aGdkKeyEvent);
     aKeyEvent.time = aGdkKeyEvent->time;
     aKeyEvent.mNativeKeyEvent = static_cast<void*>(aGdkKeyEvent);
     aKeyEvent.mIsRepeat = sRepeatState == REPEATING &&
         aGdkKeyEvent->hardware_keycode == sLastRepeatableHardwareKeyCode;
 }
 
 /* static */ uint32_t
 KeymapWrapper::GetCharCodeFor(const GdkEventKey *aGdkKeyEvent)
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -70,21 +70,23 @@ struct ParamTraits<mozilla::WidgetEvent>
 template<>
 struct ParamTraits<mozilla::WidgetGUIEvent>
 {
   typedef mozilla::WidgetGUIEvent paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, static_cast<mozilla::WidgetEvent>(aParam));
+    WriteParam(aMsg, aParam.mPluginEvent.mBuffer);
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
-    return ReadParam(aMsg, aIter, static_cast<mozilla::WidgetEvent*>(aResult));
+    return ReadParam(aMsg, aIter, static_cast<mozilla::WidgetEvent*>(aResult)) &&
+           ReadParam(aMsg, aIter, &aResult->mPluginEvent.mBuffer);
   }
 };
 
 template<>
 struct ParamTraits<mozilla::WidgetInputEvent>
 {
   typedef mozilla::WidgetInputEvent paramType;
 
--- a/widget/qt/nsWindow.cpp
+++ b/widget/qt/nsWindow.cpp
@@ -1119,17 +1119,17 @@ InitKeyEvent(WidgetKeyboardEvent& aEvent
     }
 
     aEvent.mCodeNameIndex = ScanCodeToDOMCodeNameIndex(aQEvent->nativeScanCode());
 
     // The transformations above and in qt for the keyval are not invertible
     // so link to the QKeyEvent (which will vanish soon after return from the
     // event callback) to give plugins access to hardware_keycode and state.
     // (An XEvent would be nice but the QKeyEvent is good enough.)
-    aEvent.pluginEvent = (void *)aQEvent;
+    aEvent.mPluginEvent.Copy(*aQEvent);
 }
 
 nsEventStatus
 nsWindow::keyPressEvent(QKeyEvent* aEvent)
 {
     LOGFOCUS(("OnKeyPressEvent [%p]\n", (void *)this));
 
     // The user has done something.
--- a/widget/windows/KeyboardLayout.cpp
+++ b/widget/windows/KeyboardLayout.cpp
@@ -1094,17 +1094,17 @@ NativeKey::DispatchKeyEvent(WidgetKeyboa
   KeyboardLayout::NotifyIdleServiceOfUserActivity();
 
   NPEvent pluginEvent;
   if (aMsgSentToPlugin &&
       mWidget->GetInputContext().mIMEState.mEnabled == IMEState::PLUGIN) {
     pluginEvent.event = aMsgSentToPlugin->message;
     pluginEvent.wParam = aMsgSentToPlugin->wParam;
     pluginEvent.lParam = aMsgSentToPlugin->lParam;
-    aKeyEvent.pluginEvent = static_cast<void*>(&pluginEvent);
+    aKeyEvent.mPluginEvent.Copy(pluginEvent);
   }
 
   return (mWidget->DispatchKeyboardEvent(&aKeyEvent) || mWidget->Destroyed());
 }
 
 bool
 NativeKey::HandleKeyDownMessage(bool* aEventDispatched) const
 {
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -3995,17 +3995,17 @@ bool nsWindow::DispatchMouseEvent(uint32
     default:
       pluginEvent.event = WM_NULL;
       break;
   }
 
   pluginEvent.wParam = wParam;     // plugins NEED raw OS event flags!
   pluginEvent.lParam = lParam;
 
-  event.pluginEvent = (void *)&pluginEvent;
+  event.mPluginEvent.Copy(pluginEvent);
 
   // call the event callback
   if (mWidgetListener) {
     if (nsToolkit::gMouseTrailer)
       nsToolkit::gMouseTrailer->Disable();
     if (aEventType == NS_MOUSE_MOVE) {
       if (nsToolkit::gMouseTrailer && !sIsInMouseCapture) {
         nsToolkit::gMouseTrailer->SetMouseTrailerWindow(mWnd);
--- a/widget/windows/nsWindowBase.cpp
+++ b/widget/windows/nsWindowBase.cpp
@@ -25,17 +25,17 @@ nsWindowBase::DispatchPluginEvent(const 
   }
   WidgetPluginEvent pluginEvent(true, NS_PLUGIN_INPUT_EVENT, this);
   nsIntPoint point(0, 0);
   InitEvent(pluginEvent, &point);
   NPEvent npEvent;
   npEvent.event = aMsg.message;
   npEvent.wParam = aMsg.wParam;
   npEvent.lParam = aMsg.lParam;
-  pluginEvent.pluginEvent = &npEvent;
+  pluginEvent.mPluginEvent.Copy(npEvent);
   pluginEvent.retargetToFocusedDocument = true;
   return DispatchWindowEvent(&pluginEvent);
 }
 
 // static
 bool
 nsWindowBase::InitTouchInjection()
 {