Bug 751809 - Fix OSX focus issue with click-to-play. r=josh
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -3772,16 +3772,22 @@ void nsPluginInstanceOwner::SetFrame(nsO
for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
nsIScrollableFrame* sf = do_QueryFrame(f);
if (sf) {
sf->AddScrollPositionListener(this);
}
}
}
#endif
+
+ nsFocusManager* fm = nsFocusManager::GetFocusManager();
+ const nsIContent* content = aFrame->GetContent();
+ if (fm && content) {
+ mContentFocused = (content == fm->GetFocusedContent());
+ }
}
}
nsObjectFrame* nsPluginInstanceOwner::GetFrame()
{
return mObjectFrame;
}
--- a/dom/plugins/test/mochitest/Makefile.in
+++ b/dom/plugins/test/mochitest/Makefile.in
@@ -59,16 +59,17 @@ MOCHITEST_FILES = \
crashing_subpage.html \
test_GCrace.html \
test_propertyAndMethod.html \
test_bug539565-1.html \
test_bug539565-2.html \
test_bug771202.html \
file_bug771202.html \
test_bug777098.html \
+ test_bug751809.html \
test_enumerate.html \
test_npruntime_construct.html \
307-xo-redirect.sjs \
test_redirect_handling.html \
test_zero_opacity.html \
test_NPPVpluginWantsAllNetworkStreams.html \
test_npruntime_npnsetexception.html \
test_NPNVdocumentOrigin.html \
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_bug751809.html
@@ -0,0 +1,92 @@
+<html>
+<head>
+ <title>Bug 751809</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<body>
+ <script type="application/javascript">
+
+ SimpleTest.waitForExplicitFinish();
+ netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+ const Ci = Components.interfaces;
+ const utils = window.QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIDOMWindowUtils);
+
+ function waitForCondition(condition, nextTest, errorMsg) {
+ var tries = 0;
+ var interval = setInterval(function() {
+ if (tries >= 30) {
+ ok(false, errorMsg);
+ moveOn();
+ }
+ if (condition()) {
+ moveOn();
+ }
+ tries++;
+ }, 100);
+ var moveOn = function() { clearInterval(interval); nextTest(); };
+ }
+
+ function startFocusTest() {
+ var plugin = document.getElementById('plugin');
+ ok(plugin, "Got plugin element.");
+
+ var condition = function() plugin.getBoundingClientRect().width == 400;
+ waitForCondition(condition, afterPluginInsertion, "Waited too long for plugin to show up in page");
+ }
+
+ function afterPluginInsertion() {
+ var plugin = document.getElementById('plugin');
+ var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+ ok(!objLoadingContent.activated, "plugin should not be activated");
+
+ SimpleTest.waitForFocus(afterWindowFocus);
+ }
+
+ function afterWindowFocus() {
+ var plugin = document.getElementById('plugin');
+ var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+
+ synthesizeMouseAtCenter(plugin, {}, window);
+ var condition = function() objLoadingContent.activated;
+ waitForCondition(condition, afterPluginActivation, "Waited too long for plugin to activate");
+ }
+
+ function afterPluginActivation() {
+ var plugin = document.getElementById('plugin');
+ var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+ ok(objLoadingContent.activated, "plugin should be activated now");
+ try {
+ is(plugin.getMouseUpEventCount(), 0, "Plugin should not have received mouse events yet.");
+ } catch(e) {
+ ok(false, "plugin.getMouseUpEventCount() shouldn't throw");
+ }
+
+ synthesizeMouseAtCenter(plugin, {}, window);
+ var condition = function() plugin.getMouseUpEventCount() > 0;
+ waitForCondition(condition, afterFirstClick, "Waited too long for plugin to receive the mouse click");
+ }
+
+ function afterFirstClick() {
+ var plugin = document.getElementById('plugin');
+ try {
+ is(plugin.getMouseUpEventCount(), 1, "Plugin should have received 1 mouse up event.");
+ } catch(e) {
+ ok(false, "plugin.getMouseUpEventCount() shouldn't throw");
+ }
+
+ SpecialPowers.clearUserPref("plugins.click_to_play");
+ SimpleTest.finish();
+ }
+
+ SpecialPowers.setBoolPref("plugins.click_to_play", true);
+ document.write('<embed id="plugin" type="application/x-test" width="400" height="400" drawmode="solid" color="FF00FFFF"></embed>');
+ SimpleTest.executeSoon(startFocusTest);
+
+ </script>
+</body>
+</html>
--- a/dom/plugins/test/testplugin/nptest.cpp
+++ b/dom/plugins/test/testplugin/nptest.cpp
@@ -158,16 +158,17 @@ static bool getEventModel(NPObject* npob
static bool getReflector(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool isVisible(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool getWindowPosition(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool constructObject(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool setSitesWithData(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool setSitesWithDataCapabilities(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool getLastKeyText(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool getNPNVdocumentOrigin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+static bool getMouseUpEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static const NPUTF8* sPluginMethodIdentifierNames[] = {
"npnEvaluateTest",
"npnInvokeTest",
"npnInvokeDefaultTest",
"setUndefinedValueTest",
"identifierToStringTest",
"timerTest",
@@ -217,17 +218,18 @@ static const NPUTF8* sPluginMethodIdenti
"getEventModel",
"getReflector",
"isVisible",
"getWindowPosition",
"constructObject",
"setSitesWithData",
"setSitesWithDataCapabilities",
"getLastKeyText",
- "getNPNVdocumentOrigin"
+ "getNPNVdocumentOrigin",
+ "getMouseUpEventCount"
};
static NPIdentifier sPluginMethodIdentifiers[ARRAY_LENGTH(sPluginMethodIdentifierNames)];
static const ScriptableFunction sPluginMethodFunctions[] = {
npnEvaluateTest,
npnInvokeTest,
npnInvokeDefaultTest,
setUndefinedValueTest,
identifierToStringTest,
@@ -278,17 +280,18 @@ static const ScriptableFunction sPluginM
getEventModel,
getReflector,
isVisible,
getWindowPosition,
constructObject,
setSitesWithData,
setSitesWithDataCapabilities,
getLastKeyText,
- getNPNVdocumentOrigin
+ getNPNVdocumentOrigin,
+ getMouseUpEventCount
};
STATIC_ASSERT(ARRAY_LENGTH(sPluginMethodIdentifierNames) ==
ARRAY_LENGTH(sPluginMethodFunctions));
static const NPUTF8* sPluginPropertyIdentifierNames[] = {
"propertyAndMethod"
};
@@ -772,16 +775,17 @@ NPP_New(NPMIMEType pluginType, NPP insta
instanceData->focusState = ACTIVATION_STATE_UNKNOWN;
instanceData->focusEventCount = 0;
instanceData->eventModel = 0;
instanceData->closeStream = false;
instanceData->wantsAllStreams = false;
instanceData->asyncDrawing = AD_NONE;
instanceData->frontBuffer = NULL;
instanceData->backBuffer = NULL;
+ instanceData->mouseUpEventCount = 0;
instance->pdata = instanceData;
TestNPObject* scriptableObject = (TestNPObject*)NPN_CreateObject(instance, &sNPClass);
if (!scriptableObject) {
printf("NPN_CreateObject failed to create an object, can't create a plugin instance\n");
free(instanceData);
return NPERR_GENERIC_ERROR;
}
@@ -3644,8 +3648,20 @@ bool getNPNVdocumentOrigin(NPObject* npo
NPError err = NPN_GetValue(npp, NPNVdocumentOrigin, &origin);
if (err != NPERR_NO_ERROR) {
return false;
}
STRINGZ_TO_NPVARIANT(origin, *result);
return true;
}
+
+bool getMouseUpEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
+{
+ if (argCount != 0) {
+ return false;
+ }
+
+ NPP npp = static_cast<TestNPObject*>(npobj)->npp;
+ InstanceData* id = static_cast<InstanceData*>(npp->pdata);
+ INT32_TO_NPVARIANT(id->mouseUpEventCount, *result);
+ return true;
+}
--- a/dom/plugins/test/testplugin/nptest.h
+++ b/dom/plugins/test/testplugin/nptest.h
@@ -145,13 +145,14 @@ typedef struct InstanceData {
int32_t focusEventCount;
int32_t eventModel;
bool closeStream;
std::string lastKeyText;
bool wantsAllStreams;
AsyncDrawing asyncDrawing;
NPAsyncSurface *frontBuffer;
NPAsyncSurface *backBuffer;
+ int32_t mouseUpEventCount;
} InstanceData;
void notifyDidPaint(InstanceData* instanceData);
#endif // nptest_h_
--- a/dom/plugins/test/testplugin/nptest_gtk2.cpp
+++ b/dom/plugins/test/testplugin/nptest_gtk2.cpp
@@ -249,16 +249,19 @@ MotionEvent(GtkWidget* widget, GdkEventM
static gboolean
ButtonEvent(GtkWidget* widget, GdkEventButton* event,
gpointer user_data)
{
InstanceData* instanceData = static_cast<InstanceData*>(user_data);
instanceData->lastMouseX = event->x;
instanceData->lastMouseY = event->y;
+ if (event->type == GDK_BUTTON_RELEASE) {
+ instanceData->mouseUpEventCount++;
+ }
return TRUE;
}
static gboolean
DeleteWidget(GtkWidget* widget, GdkEvent* event, gpointer user_data)
{
InstanceData* instanceData = static_cast<InstanceData*>(user_data);
// Some plugins do not expect the plug to be removed from the socket before
@@ -413,16 +416,19 @@ pluginHandleEvent(InstanceData* instance
instanceData->lastMouseY = motion->y;
break;
}
case ButtonPress:
case ButtonRelease: {
XButtonEvent* button = &nsEvent->xbutton;
instanceData->lastMouseX = button->x;
instanceData->lastMouseY = button->y;
+ if (nsEvent->type == ButtonRelease) {
+ instanceData->mouseUpEventCount++;
+ }
break;
}
default:
break;
}
#endif
return 0;
--- a/dom/plugins/test/testplugin/nptest_macosx.mm
+++ b/dom/plugins/test/testplugin/nptest_macosx.mm
@@ -271,16 +271,19 @@ pluginHandleEvent(InstanceData* instance
case osEvt:
{
Rect globalBounds = {0};
WindowRef nativeWindow = static_cast<WindowRef>(static_cast<NP_CGContext*>(w->window)->window);
if (nativeWindow)
::GetWindowBounds(nativeWindow, kWindowStructureRgn, &globalBounds);
instanceData->lastMouseX = carbonEvent->where.h - w->x - globalBounds.left;
instanceData->lastMouseY = carbonEvent->where.v - w->y - globalBounds.top;
+ if (carbonEvent->what == mouseUp) {
+ instanceData->mouseUpEventCount++;
+ }
break;
}
default:
return kNPEventNotHandled;
}
return kNPEventHandled;
}
@@ -294,16 +297,19 @@ pluginHandleEvent(InstanceData* instance
case NPCocoaEventDrawRect:
pluginDraw(instanceData, cocoaEvent);
break;
case NPCocoaEventMouseDown:
case NPCocoaEventMouseUp:
case NPCocoaEventMouseMoved:
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 ?
ACTIVATION_STATE_ACTIVATED : ACTIVATION_STATE_DEACTIVATED;
instanceData->topLevelWindowActivationEventCount = instanceData->topLevelWindowActivationEventCount + 1;
break;
case NPCocoaEventFocusChanged:
instanceData->focusState = cocoaEvent->data.focus.hasFocus ?
--- a/dom/plugins/test/testplugin/nptest_qt.cpp
+++ b/dom/plugins/test/testplugin/nptest_qt.cpp
@@ -188,16 +188,17 @@ pluginHandleEvent(InstanceData* instance
////printf("ButtonPress\n");
break;
}
case ButtonRelease: {
//printf("ButtonRelease\n");
XButtonEvent* button = &nsEvent->xbutton;
instanceData->lastMouseX = button->x;
instanceData->lastMouseY = button->y;
+ instanceData->mouseUpEventCount++;
break;
}
default:
break;
}
#endif
return 0;
--- a/dom/plugins/test/testplugin/nptest_windows.cpp
+++ b/dom/plugins/test/testplugin/nptest_windows.cpp
@@ -597,16 +597,19 @@ handleEventInternal(InstanceData* instan
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP: {
int x = instanceData->hasWidget ? 0 : instanceData->winX;
int y = instanceData->hasWidget ? 0 : instanceData->winY;
instanceData->lastMouseX = GET_X_LPARAM(pe->lParam) - x;
instanceData->lastMouseY = GET_Y_LPARAM(pe->lParam) - y;
+ if ((UINT)pe->event == WM_LBUTTONUP) {
+ instanceData->mouseUpEventCount++;
+ }
return true;
}
case WM_KEYDOWN:
instanceData->lastKeyText.erase();
*result = 0;
return true;