Bug 586656 - Serialize external "pluginEvent" structs in WidgetGUIEvent so that plugin events work in e10s - r=masayuki,jimm

This commit is contained in:
Benoit Jacob 2014-07-23 15:55:51 -04:00
Родитель 192498ad38
Коммит db65b34b46
13 изменённых файлов: 103 добавлений и 32 удалений

Просмотреть файл

@ -3605,7 +3605,7 @@ CreateMouseOrPointerWidgetEvent(WidgetMouseEvent* aMouseEvent,
aNewEvent->button = aMouseEvent->button; aNewEvent->button = aMouseEvent->button;
aNewEvent->buttons = aMouseEvent->buttons; aNewEvent->buttons = aMouseEvent->buttons;
aNewEvent->pressure = aMouseEvent->pressure; aNewEvent->pressure = aMouseEvent->pressure;
aNewEvent->pluginEvent = aMouseEvent->pluginEvent; aNewEvent->mPluginEvent = aMouseEvent->mPluginEvent;
aNewEvent->inputSource = aMouseEvent->inputSource; aNewEvent->inputSource = aMouseEvent->inputSource;
} }

Просмотреть файл

@ -1812,7 +1812,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
// If we have to synthesize an event we'll use one of these. // If we have to synthesize an event we'll use one of these.
NPCocoaEvent synthCocoaEvent; NPCocoaEvent synthCocoaEvent;
void* event = anEvent.pluginEvent; const NPCocoaEvent* event = static_cast<const NPCocoaEvent*>(anEvent.mPluginEvent);
nsPoint pt = nsPoint pt =
nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) - nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) -
mObjectFrame->GetContentRectRelativeToSelf().TopLeft(); mObjectFrame->GetContentRectRelativeToSelf().TopLeft();
@ -1879,7 +1879,9 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
int16_t response = kNPEventNotHandled; int16_t response = kNPEventNotHandled;
void* window = FixUpPluginWindow(ePluginPaintEnable); void* window = FixUpPluginWindow(ePluginPaintEnable);
if (window || (eventModel == NPEventModelCocoa)) { 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) { if (eventModel == NPEventModelCocoa && response == kNPEventStartIME) {
@ -1898,7 +1900,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
#ifdef XP_WIN #ifdef XP_WIN
// this code supports windowless plugins // 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 // we can get synthetic events from the EventStateManager... these
// have no pluginEvent // have no pluginEvent
NPEvent pluginEvent; NPEvent pluginEvent;
@ -1967,7 +1969,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x), nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x),
presContext->AppUnitsToDevPixels(pt.y)); presContext->AppUnitsToDevPixels(pt.y));
nsIntPoint widgetPtPx = ptPx + mObjectFrame->GetWindowOriginInPixels(true); 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) { else if (!pPluginEvent) {
@ -1995,7 +1997,9 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
if (pPluginEvent) { if (pPluginEvent) {
int16_t response = kNPEventNotHandled; 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) if (response == kNPEventHandled)
rv = nsEventStatus_eConsumeNoDefault; rv = nsEventStatus_eConsumeNoDefault;
} }
@ -2117,14 +2121,14 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
//XXX case NS_MOUSE_SCROLL_EVENT: not received. //XXX case NS_MOUSE_SCROLL_EVENT: not received.
case NS_KEY_EVENT: case NS_KEY_EVENT:
if (anEvent.pluginEvent) if (anEvent.mPluginEvent)
{ {
XKeyEvent &event = pluginEvent.xkey; XKeyEvent &event = pluginEvent.xkey;
#ifdef MOZ_WIDGET_GTK #ifdef MOZ_WIDGET_GTK
event.root = GDK_ROOT_WINDOW(); event.root = GDK_ROOT_WINDOW();
event.time = anEvent.time; event.time = anEvent.time;
const GdkEventKey* gdkEvent = const GdkEventKey* gdkEvent =
static_cast<const GdkEventKey*>(anEvent.pluginEvent); static_cast<const GdkEventKey*>(anEvent.mPluginEvent);
event.keycode = gdkEvent->hardware_keycode; event.keycode = gdkEvent->hardware_keycode;
event.state = gdkEvent->state; event.state = gdkEvent->state;
switch (anEvent.message) switch (anEvent.message)
@ -2269,11 +2273,13 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
const WidgetKeyboardEvent& keyEvent = *anEvent.AsKeyboardEvent(); const WidgetKeyboardEvent& keyEvent = *anEvent.AsKeyboardEvent();
LOG("Firing NS_KEY_EVENT %d %d\n", keyEvent.keyCode, keyEvent.charCode); LOG("Firing NS_KEY_EVENT %d %d\n", keyEvent.keyCode, keyEvent.charCode);
// pluginEvent is initialized by nsWindow::InitKeyEvent(). // pluginEvent is initialized by nsWindow::InitKeyEvent().
ANPEvent* pluginEvent = reinterpret_cast<ANPEvent*>(keyEvent.pluginEvent); const ANPEvent* pluginEvent = static_cast<const ANPEvent*>(keyEvent.mPluginEvent);
if (pluginEvent) { if (pluginEvent) {
MOZ_ASSERT(pluginEvent->inSize == sizeof(ANPEvent)); MOZ_ASSERT(pluginEvent->inSize == sizeof(ANPEvent));
MOZ_ASSERT(pluginEvent->eventType == kKey_ANPEventType); 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; break;
@ -2987,7 +2993,7 @@ void* nsPluginInstanceOwner::FixUpPluginWindow(int32_t inPaintState)
InitializeNPCocoaEvent(&cocoaEvent); InitializeNPCocoaEvent(&cocoaEvent);
cocoaEvent.type = NPCocoaEventWindowFocusChanged; cocoaEvent.type = NPCocoaEventWindowFocusChanged;
cocoaEvent.data.focus.hasFocus = cocoaTopLevelWindow ? NS_NPAPI_CocoaWindowIsMain(cocoaTopLevelWindow) : true; cocoaEvent.data.focus.hasFocus = cocoaTopLevelWindow ? NS_NPAPI_CocoaWindowIsMain(cocoaTopLevelWindow) : true;
pluginEvent.pluginEvent = &cocoaEvent; pluginEvent.mPluginEvent.Copy(cocoaEvent);
ProcessEvent(pluginEvent); ProcessEvent(pluginEvent);
} }

Просмотреть файл

@ -480,6 +480,11 @@ enum nsEventStructType
#define NS_EDITOR_EVENT_START 6100 #define NS_EDITOR_EVENT_START 6100
#define NS_EDITOR_INPUT (NS_EDITOR_EVENT_START) #define NS_EDITOR_INPUT (NS_EDITOR_EVENT_START)
namespace IPC {
template<typename T>
struct ParamTraits;
}
namespace mozilla { namespace mozilla {
/****************************************************************************** /******************************************************************************
@ -838,12 +843,11 @@ protected:
WidgetGUIEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget, WidgetGUIEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget,
nsEventStructType aStructType) : nsEventStructType aStructType) :
WidgetEvent(aIsTrusted, aMessage, aStructType), WidgetEvent(aIsTrusted, aMessage, aStructType),
widget(aWidget), pluginEvent(nullptr) widget(aWidget)
{ {
} }
WidgetGUIEvent() : WidgetGUIEvent()
pluginEvent(nullptr)
{ {
} }
@ -852,7 +856,7 @@ public:
WidgetGUIEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) : WidgetGUIEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
WidgetEvent(aIsTrusted, aMessage, NS_GUI_EVENT), WidgetEvent(aIsTrusted, aMessage, NS_GUI_EVENT),
widget(aWidget), pluginEvent(nullptr) widget(aWidget)
{ {
} }
@ -871,8 +875,69 @@ public:
/// Originator of the event /// Originator of the event
nsCOMPtr<nsIWidget> widget; 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 /// Event for NPAPI plugin
void* pluginEvent; PluginEvent mPluginEvent;
void AssignGUIEventData(const WidgetGUIEvent& aEvent, bool aCopyTargets) void AssignGUIEventData(const WidgetGUIEvent& aEvent, bool aCopyTargets)
{ {
@ -880,9 +945,7 @@ public:
// widget should be initialized with the constructor. // widget should be initialized with the constructor.
// pluginEvent shouldn't be copied because it may be referred after its mPluginEvent = aEvent.mPluginEvent;
// instance is destroyed.
pluginEvent = nullptr;
} }
}; };

Просмотреть файл

@ -1448,7 +1448,7 @@ nsWindow::InitKeyEvent(WidgetKeyboardEvent& event, AndroidGeckoEvent& key,
event.isChar = (charCode >= ' '); event.isChar = (charCode >= ' ');
event.charCode = event.isChar ? charCode : 0; event.charCode = event.isChar ? charCode : 0;
event.keyCode = (event.charCode > 0) ? 0 : domKeyCode; event.keyCode = (event.charCode > 0) ? 0 : domKeyCode;
event.pluginEvent = nullptr; event.mPluginEvent.Clear();
} else { } else {
#ifdef DEBUG #ifdef DEBUG
if (event.message != NS_KEY_DOWN && event.message != NS_KEY_UP) { if (event.message != NS_KEY_DOWN && event.message != NS_KEY_UP) {
@ -1465,7 +1465,7 @@ nsWindow::InitKeyEvent(WidgetKeyboardEvent& event, AndroidGeckoEvent& key,
event.isChar = false; event.isChar = false;
event.charCode = 0; event.charCode = 0;
event.keyCode = domKeyCode; event.keyCode = domKeyCode;
event.pluginEvent = pluginEvent; event.mPluginEvent.Copy(*pluginEvent);
} }
event.modifiers = key.DOMModifiers(); event.modifiers = key.DOMModifiers();

Просмотреть файл

@ -2029,7 +2029,7 @@ TextInputHandler::DispatchKeyEventForFlagsChanged(NSEvent* aNativeEvent,
if ([mView isPluginView]) { if ([mView isPluginView]) {
if ([mView pluginEventModel] == NPEventModelCocoa) { if ([mView pluginEventModel] == NPEventModelCocoa) {
ConvertCocoaKeyEventToNPCocoaEvent(aNativeEvent, cocoaEvent); ConvertCocoaKeyEventToNPCocoaEvent(aNativeEvent, cocoaEvent);
keyEvent.pluginEvent = &cocoaEvent; keyEvent.mPluginEvent.Copy(cocoaEvent);
} }
} }
@ -3890,7 +3890,7 @@ PluginTextInputHandler::HandleCarbonPluginKeyEvent(EventRef aKeyEvent)
uint32_t charCode(charCodes.ElementAt(i)); uint32_t charCode(charCodes.ElementAt(i));
keydownEvent.time = PR_IntervalNow(); keydownEvent.time = PR_IntervalNow();
keydownEvent.pluginEvent = &eventRec; keydownEvent.mPluginEvent.Copy(eventRec);
if (IsSpecialGeckoKey(macKeyCode)) { if (IsSpecialGeckoKey(macKeyCode)) {
keydownEvent.keyCode = keyCode; keydownEvent.keyCode = keyCode;
} else { } else {
@ -4080,7 +4080,7 @@ PluginTextInputHandler::HandleKeyUpEventForPlugin(NSEvent* aNativeKeyEvent)
InitKeyEvent(aNativeKeyEvent, keyupEvent); InitKeyEvent(aNativeKeyEvent, keyupEvent);
NPCocoaEvent pluginEvent; NPCocoaEvent pluginEvent;
ConvertCocoaKeyEventToNPCocoaEvent(aNativeKeyEvent, pluginEvent); ConvertCocoaKeyEventToNPCocoaEvent(aNativeKeyEvent, pluginEvent);
keyupEvent.pluginEvent = &pluginEvent; keyupEvent.mPluginEvent.Copy(pluginEvent);
DispatchEvent(keyupEvent); DispatchEvent(keyupEvent);
return; return;
} }

Просмотреть файл

@ -6634,7 +6634,7 @@ ChildViewMouseTracker::AttachPluginEvent(WidgetMouseEventBase& aMouseEvent,
cocoaEvent->data.mouse.deltaX = [aNativeMouseEvent deltaX]; cocoaEvent->data.mouse.deltaX = [aNativeMouseEvent deltaX];
cocoaEvent->data.mouse.deltaY = [aNativeMouseEvent deltaY]; cocoaEvent->data.mouse.deltaY = [aNativeMouseEvent deltaY];
cocoaEvent->data.mouse.deltaZ = [aNativeMouseEvent deltaZ]; cocoaEvent->data.mouse.deltaZ = [aNativeMouseEvent deltaZ];
aMouseEvent.pluginEvent = cocoaEvent; aMouseEvent.mPluginEvent.Copy(*cocoaEvent);
} }
BOOL BOOL

Просмотреть файл

@ -607,7 +607,7 @@ nsCocoaUtils::InitPluginEvent(WidgetPluginEvent &aPluginEvent,
NPCocoaEvent &aCocoaEvent) NPCocoaEvent &aCocoaEvent)
{ {
aPluginEvent.time = PR_IntervalNow(); aPluginEvent.time = PR_IntervalNow();
aPluginEvent.pluginEvent = (void*)&aCocoaEvent; aPluginEvent.mPluginEvent.Copy(aCocoaEvent);
aPluginEvent.retargetToFocusedDocument = false; aPluginEvent.retargetToFocusedDocument = false;
} }

Просмотреть файл

@ -1005,7 +1005,7 @@ KeymapWrapper::InitKeyEvent(WidgetKeyboardEvent& aKeyEvent,
// so link to the GdkEvent (which will vanish soon after return from the // so link to the GdkEvent (which will vanish soon after return from the
// event callback) to give plugins access to hardware_keycode and state. // event callback) to give plugins access to hardware_keycode and state.
// (An XEvent would be nice but the GdkEvent is good enough.) // (An XEvent would be nice but the GdkEvent is good enough.)
aKeyEvent.pluginEvent = (void *)aGdkKeyEvent; aKeyEvent.mPluginEvent.Copy(*aGdkKeyEvent);
aKeyEvent.time = aGdkKeyEvent->time; aKeyEvent.time = aGdkKeyEvent->time;
aKeyEvent.mNativeKeyEvent = static_cast<void*>(aGdkKeyEvent); aKeyEvent.mNativeKeyEvent = static_cast<void*>(aGdkKeyEvent);
aKeyEvent.mIsRepeat = sRepeatState == REPEATING && aKeyEvent.mIsRepeat = sRepeatState == REPEATING &&

Просмотреть файл

@ -75,11 +75,13 @@ struct ParamTraits<mozilla::WidgetGUIEvent>
static void Write(Message* aMsg, const paramType& aParam) static void Write(Message* aMsg, const paramType& aParam)
{ {
WriteParam(aMsg, static_cast<mozilla::WidgetEvent>(aParam)); WriteParam(aMsg, static_cast<mozilla::WidgetEvent>(aParam));
WriteParam(aMsg, aParam.mPluginEvent.mBuffer);
} }
static bool Read(const Message* aMsg, void** aIter, paramType* aResult) 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);
} }
}; };

Просмотреть файл

@ -1124,7 +1124,7 @@ InitKeyEvent(WidgetKeyboardEvent& aEvent, QKeyEvent* aQEvent)
// so link to the QKeyEvent (which will vanish soon after return from the // so link to the QKeyEvent (which will vanish soon after return from the
// event callback) to give plugins access to hardware_keycode and state. // event callback) to give plugins access to hardware_keycode and state.
// (An XEvent would be nice but the QKeyEvent is good enough.) // (An XEvent would be nice but the QKeyEvent is good enough.)
aEvent.pluginEvent = (void *)aQEvent; aEvent.mPluginEvent.Copy(*aQEvent);
} }
nsEventStatus nsEventStatus

Просмотреть файл

@ -1099,7 +1099,7 @@ NativeKey::DispatchKeyEvent(WidgetKeyboardEvent& aKeyEvent,
pluginEvent.event = aMsgSentToPlugin->message; pluginEvent.event = aMsgSentToPlugin->message;
pluginEvent.wParam = aMsgSentToPlugin->wParam; pluginEvent.wParam = aMsgSentToPlugin->wParam;
pluginEvent.lParam = aMsgSentToPlugin->lParam; pluginEvent.lParam = aMsgSentToPlugin->lParam;
aKeyEvent.pluginEvent = static_cast<void*>(&pluginEvent); aKeyEvent.mPluginEvent.Copy(pluginEvent);
} }
return (mWidget->DispatchKeyboardEvent(&aKeyEvent) || mWidget->Destroyed()); return (mWidget->DispatchKeyboardEvent(&aKeyEvent) || mWidget->Destroyed());

Просмотреть файл

@ -4000,7 +4000,7 @@ bool nsWindow::DispatchMouseEvent(uint32_t aEventType, WPARAM wParam,
pluginEvent.wParam = wParam; // plugins NEED raw OS event flags! pluginEvent.wParam = wParam; // plugins NEED raw OS event flags!
pluginEvent.lParam = lParam; pluginEvent.lParam = lParam;
event.pluginEvent = (void *)&pluginEvent; event.mPluginEvent.Copy(pluginEvent);
// call the event callback // call the event callback
if (mWidgetListener) { if (mWidgetListener) {

Просмотреть файл

@ -30,7 +30,7 @@ nsWindowBase::DispatchPluginEvent(const MSG& aMsg)
npEvent.event = aMsg.message; npEvent.event = aMsg.message;
npEvent.wParam = aMsg.wParam; npEvent.wParam = aMsg.wParam;
npEvent.lParam = aMsg.lParam; npEvent.lParam = aMsg.lParam;
pluginEvent.pluginEvent = &npEvent; pluginEvent.mPluginEvent.Copy(npEvent);
pluginEvent.retargetToFocusedDocument = true; pluginEvent.retargetToFocusedDocument = true;
return DispatchWindowEvent(&pluginEvent); return DispatchWindowEvent(&pluginEvent);
} }