Test for bug 583109 - Add an .isVisible() method to the testplugin. test_visibility.html checks whether a visibility: hidden plugin suspends and resumes painting properly. test_xulbrowser_plugin_visibility.xul tests whether switching tabs properly suspends and resumes plugin painting. r-pending=karlt

This commit is contained in:
Benjamin Smedberg 2010-11-05 10:43:14 -04:00
parent 3c4bb23cb4
commit 3aab32a483
7 changed files with 267 additions and 5 deletions

View File

@ -111,6 +111,18 @@ _MOCHICHROME_FILES = \
test_bug479979.xul \
$(NULL)
ifneq ($(MOZ_WIDGET_TOOLKIT),cocoa)
_MOCHITEST_FILES += \
test_visibility.html \
$(NULL)
_MOCHICHROME_FILES += \
test_xulbrowser_plugin_visibility.xul \
xulbrowser_plugin_visibility.xul \
plugin_visibility_loader.html \
$(NULL)
endif
# Temporarily disable the tests on Linux, see bug 573290 and bug 583591.
ifneq ($(OS_ARCH),Linux)
ifdef MOZ_CRASHREPORTER

View File

@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body style="background-color: #88AAFF;">
<h1>This Page Has a Solid Plugin</h1>
<p><embed id="p" type="application/x-test" drawmode="solid" color="FFFF0000" width="200" height="200"></embed>

View File

@ -84,10 +84,13 @@ function doubleForDoublePass() {
if (SimpleTest.testPluginIsOOP())
return 1;
if (!Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).D2DEnabled)
return 1;
try {
if (Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).D2DEnabled)
return 2;
}
catch (e) { }
return 2;
return 1;
}
function invalidate() {

View File

@ -0,0 +1,83 @@
<!DOCTYPE html>
<html>
<head>
<title>Test whether windowless plugins receive correct visible/invisible notifications.</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<style>
.hidden { visibility: hidden; }
</style>
<body onload="startTest()">
<p id="display"></p>
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
function doubleForDoublePass() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
if (SimpleTest.testPluginIsOOP())
return 1;
try {
if (Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).D2DEnabled)
return 2;
}
catch (e) { }
return 1;
}
var didpaint = function() {
ok(false, "Plugin should not paint until it is visible!");
};
function startTest() {
ok(!p.isVisible(), "Plugin should not be visible.");
is(p.getPaintCount(), 0, "Plugin should not have painted.");
didpaint = part2;
p.style.visibility = 'visible';
}
function part2() {
ok(p.isVisible(), "Plugin should now be visible.");
is(p.getPaintCount(), 1 * doubleForDoublePass(),
"Plugin should have painted once.");
didpaint = part3;
p.setColor('FF0000FF'); // this causes an invalidate/repaint
}
function part3() {
ok(p.isVisible(), "Plugin should still be visible.");
is(p.getPaintCount(), 2 * doubleForDoublePass(),
"Plugin should have painted twice.");
didpaint = function() {
ok(false, "Plugin should not paint when it is invisible.");
};
p.style.visibility = 'hidden';
// Can we know exactly when the reflow/AsyncSetWindow actually happen?
setTimeout(part4, 500);
}
function part4() {
ok(!p.isVisible(), "Plugin should be invisible again.");
p.setColor('FF00FF00');
setTimeout(SimpleTest.finish, 500);
// wait to make sure we don't actually paint
}
</script>
<embed id="theplugin" class="hidden" type="application/x-test" drawmode="solid" color="FFFF0000" paintscript="setTimeout(didpaint, 0)"></embed>
<script type="application/javascript">
var p = document.getElementById('theplugin');
</script>

View File

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.cs" type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script>
SimpleTest.waitForExplicitFinish();
var w = window.open('xulbrowser_plugin_visibility.xul', '_blank', 'chrome,resizable=yes,width=400,height=600');
function done()
{
w.close();
SimpleTest.finish();
}
</script>
<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;" />
</window>

View File

@ -0,0 +1,119 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
orient="vertical">
<tabbox id="tabbox" flex="1">
<tabs>
<tab id="tab1" label="Tab 1" />
<tab id="tab2" label="Tab 2" />
</tabs>
<tabpanels flex="1">
<browser id="browser1" type="content-primary" flex="1" src="about:blank"/>
<browser id="browser2" type="content-primary" flex="1" src="about:blank"/>
</tabpanels>
</tabbox>
<script type="application/javascript"><![CDATA[
const ok = window.opener.wrappedJSObject.ok;
const is = window.opener.wrappedJSObject.is;
const done = window.opener.wrappedJSObject.done;
const SimpleTest = window.opener.wrappedJSObject.SimpleTest;
const nsIWebProgress = Components.interfaces.nsIWebProgress;
const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
const kURI = 'http://mochi.test:8888/chrome/modules/plugin/test/plugin_visibility_loader.html';
function doubleForDoublePass() {
if (SimpleTest.testPluginIsOOP())
return 1;
try {
if (Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).D2DEnabled)
return 2;
}
catch (e) { }
return 1;
}
function ProgressListener() {
}
ProgressListener.prototype.onStateChange =
function(progress, req, flags, status) {
if ((flags & nsIWebProgressListener.STATE_IS_WINDOW) &&
(flags & nsIWebProgressListener.STATE_STOP))
browserLoaded();
};
ProgressListener.prototype.QueryInterface = function(iid) {
if (iid.equals(nsIWebProgressListener) ||
iid.equals(Components.interfaces.nsISupportsWeakReference))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
};
var loadCount = 0;
function browserLoaded() {
++loadCount;
if (2 == loadCount)
startTest();
}
var tabbox = document.getElementById('tabbox');
var browser1 = document.getElementById('browser1');
var browser2 = document.getElementById('browser2');
function setup() {
browser1.addProgressListener(new ProgressListener(), nsIWebProgress.NOTIFY_STATE_WINDOW);
browser1.loadURI(kURI, null, null);
browser2.addProgressListener(new ProgressListener(), nsIWebProgress.NOTIFY_STATE_WINDOW);
browser2.loadURI(kURI, null, null);
}
window.addEventListener("load", setup, false);
var plugin1, plugin2;
function startTest() {
plugin1 = browser1.contentDocument.getElementById('p').wrappedJSObject;
plugin2 = browser2.contentDocument.getElementById('p').wrappedJSObject;
ok(plugin1.isVisible(), "Plugin in tab 1 should be visible.");
is(plugin1.getPaintCount(), 1 * doubleForDoublePass(),
"Plugin in tab 1 should have painted once.");
ok(!plugin2.isVisible(), "Plugin in tab 2 should not be visible.");
is(plugin2.getPaintCount(), 0,
"Plugin in tab 2 should not have painted.");
tabbox.selectedIndex = 1;
setTimeout(part2, 100);
}
function part2() {
ok(!plugin1.isVisible(), "Plugin in tab 1 should have become invisible.");
is(plugin1.getPaintCount(), 1 * doubleForDoublePass(),
"Plugin in tab 1 should not have repainted.");
ok(plugin2.isVisible(), "Plugin in tab 2 should have become visible.");
is(plugin2.getPaintCount(), 1 * doubleForDoublePass(),
"Plugin in tab 2 should have painted once.");
// Setcolor invalidates
plugin1.setColor('FF00FF00');
plugin2.setColor('FF00FF00');
setTimeout(part3, 500);
}
function part3() {
is(plugin1.getPaintCount(), 1 * doubleForDoublePass(),
"Plugin in tab 1 should not have repainted after invalidate.");
is(plugin2.getPaintCount(), 2 * doubleForDoublePass(),
"Plugin in tab 2 should have repainted after invalidate.");
done();
}
]]></script>
</window>

View File

@ -176,6 +176,7 @@ static bool getFocusState(NPObject* npobj, const NPVariant* args, uint32_t argCo
static bool getFocusEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool getEventModel(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
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 const NPUTF8* sPluginMethodIdentifierNames[] = {
"npnEvaluateTest",
@ -226,7 +227,8 @@ static const NPUTF8* sPluginMethodIdentifierNames[] = {
"getFocusState",
"getFocusEventCount",
"getEventModel",
"getReflector"
"getReflector",
"isVisible"
};
static NPIdentifier sPluginMethodIdentifiers[ARRAY_LENGTH(sPluginMethodIdentifierNames)];
static const ScriptableFunction sPluginMethodFunctions[] = {
@ -278,7 +280,8 @@ static const ScriptableFunction sPluginMethodFunctions[] = {
getFocusState,
getFocusEventCount,
getEventModel,
getReflector
getReflector,
isVisible
};
STATIC_ASSERT(ARRAY_LENGTH(sPluginMethodIdentifierNames) ==
@ -3089,3 +3092,15 @@ getReflector(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVarian
OBJECT_TO_NPVARIANT(reflector, *result);
return true;
}
bool isVisible(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
BOOLEAN_TO_NPVARIANT(id->window.clipRect.top != 0 ||
id->window.clipRect.left != 0 ||
id->window.clipRect.bottom != 0 ||
id->window.clipRect.right != 0, *result);
return true;
}