This commit is contained in:
Honza Bambas 2010-12-22 18:26:25 +01:00
Родитель 44943a56b7 d6b969e275
Коммит ad4f1f8514
12 изменённых файлов: 515 добавлений и 9 удалений

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

@ -43,13 +43,15 @@ relativesrcdir = testing/mochitest
include $(DEPTH)/config/autoconf.mk include $(DEPTH)/config/autoconf.mk
DIRS = MochiKit \ DIRS = \
static \ MochiKit \
dynamic \ static \
tests \ dynamic \
chrome \ tests \
ssltunnel \ chrome \
$(NULL) ssltunnel \
specialpowers \
$(NULL)
NO_JS_MANIFEST = 1 NO_JS_MANIFEST = 1

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

@ -463,11 +463,27 @@ class Mochitest(object):
""" """
return self.getFullPath(logFile) return self.getFullPath(logFile)
def installSpecialPowersExtension(self, options):
""" install the Special Powers extension for special testing capabilities """
extensionSource = os.path.normpath(os.path.join(self.SCRIPT_DIRECTORY, "specialpowers"))
self.automation.log.info("INFO | runtests.py | Installing extension at %s to %s." %
(extensionSource, options.profilePath))
self.automation.installExtension(extensionSource, options.profilePath, "special-powers@mozilla.org")
self.automation.log.info("INFO | runtests.py | Done installing extension.")
def buildProfile(self, options): def buildProfile(self, options):
""" create the profile and add optional chrome bits and files if requested """ """ create the profile and add optional chrome bits and files if requested """
self.automation.initializeProfile(options.profilePath, options.extraPrefs, useServerLocations = True) self.automation.initializeProfile(options.profilePath, options.extraPrefs, useServerLocations = True)
manifest = self.addChromeToProfile(options) manifest = self.addChromeToProfile(options)
self.copyExtraFilesToProfile(options) self.copyExtraFilesToProfile(options)
# We only need special powers in non-chrome harnesses
if (not options.browserChrome and
not options.chrome and
not options.a11y):
self.installSpecialPowersExtension(options)
return manifest return manifest
def buildBrowserEnv(self, options): def buildBrowserEnv(self, options):
@ -579,6 +595,7 @@ class Mochitest(object):
manifest = self.buildProfile(options) manifest = self.buildProfile(options)
if manifest is None: if manifest is None:
return 1 return 1
self.startWebServer(options) self.startWebServer(options)
self.startWebSocketServer(options) self.startWebSocketServer(options)

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

@ -0,0 +1,65 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2010
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = testing/mochitest/specialpowers
include $(DEPTH)/config/autoconf.mk
NO_JS_MANIFEST = 1
MOZ_CHROME_FILE_FORMAT = flat
DIST_FILES = \
install.rdf \
chrome.manifest \
$(NULL)
EXTRA_COMPONENTS = components/SpecialPowersObserver.js
XPI_NAME=specialpowers
DEST_DIR=testing/mochitest
# Used in install.rdf
USE_EXTENSION_MANIFEST=1
include $(topsrcdir)/config/rules.mk
libs::
(cd $(DIST)/xpi-stage && tar $(TAR_CREATE_FLAGS) - specialpowers) | (cd $(DEPTH)/_tests/$(DEST_DIR) && tar -xf -)

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

@ -0,0 +1,4 @@
content specialpowers chrome/specialpowers/content/
component {59a52458-13e0-4d93-9d85-a637344f29a1} components/SpecialPowersObserver.js
contract @mozilla.org/special-powers-observer;1 {59a52458-13e0-4d93-9d85-a637344f29a1}
category profile-after-change @mozilla.org/special-powers-observer;1 @mozilla.org/special-powers-observer;1

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

@ -0,0 +1,160 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Special Powers code
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jesse Ruderman <jruderman@mozilla.com>
* Robert Sayre <sayrer@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK *****/
// Based on:
// https://bugzilla.mozilla.org/show_bug.cgi?id=549539
// https://bug549539.bugzilla.mozilla.org/attachment.cgi?id=429661
// https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_1.9.3
// http://mxr.mozilla.org/mozilla-central/source/toolkit/components/console/hudservice/HUDService.jsm#3240
// https://developer.mozilla.org/en/how_to_build_an_xpcom_component_in_javascript
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
const Cc = Components.classes;
const Ci = Components.interfaces;
const CHILD_SCRIPT = "chrome://specialpowers/content/specialpowers.js"
/**
* Special Powers Exception - used to throw exceptions nicely
**/
function SpecialPowersException(aMsg) {
this.message = aMsg;
this.name = "SpecialPowersException";
}
SpecialPowersException.prototype.toString = function() {
return this.name + ': "' + this.message + '"';
};
/* XPCOM gunk */
function SpecialPowersObserver() {}
SpecialPowersObserver.prototype = {
classDescription: "Special powers Observer for use in testing.",
classID: Components.ID("{59a52458-13e0-4d93-9d85-a637344f29a1}"),
contractID: "@mozilla.org/special-powers-observer;1",
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIObserver]),
_xpcom_categories: [{category: "profile-after-change", service: true }],
isFrameScriptLoaded: false,
observe: function(aSubject, aTopic, aData)
{
if (aTopic == "profile-after-change") {
this.init();
} else if (!this.isFrameScriptLoaded &&
aTopic == "chrome-document-global-created") {
var messageManager = Cc["@mozilla.org/globalmessagemanager;1"].
getService(Ci.nsIChromeFrameMessageManager);
// Register for any messages our API needs us to handle
messageManager.addMessageListener("SPPrefService", this);
messageManager.loadFrameScript(CHILD_SCRIPT, true);
this.isFrameScriptLoaded = true;
} else if (aTopic == "xpcom-shutdown") {
this.uninit();
}
},
init: function()
{
var obs = Services.obs;
obs.addObserver(this, "xpcom-shutdown", false);
obs.addObserver(this, "chrome-document-global-created", false);
},
uninit: function()
{
var obs = Services.obs;
obs.removeObserver(this, "chrome-document-global-created", false);
},
/**
* messageManager callback function
* This will get requests from our API in the window and process them in chrome for it
**/
receiveMessage: function(aMessage) {
switch(aMessage.name) {
case "SPPrefService":
var prefs = Services.prefs;
var prefType = aMessage.json.prefType.toUpperCase();
var prefName = aMessage.json.prefName;
var prefValue = "prefValue" in aMessage.json ? aMessage.json.prefValue : null;
if (aMessage.json.op == "get") {
if (!prefName || !prefType)
throw new SpecialPowersException("Invalid parameters for get in SPPrefService");
} else if (aMessage.json.op == "set") {
if (!prefName || !prefType || prefValue === null)
throw new SpecialPowersException("Invalid parameters for set in SPPrefService");
} else {
throw new SpecialPowersException("Invalid operation for SPPrefService");
}
// Now we make the call
switch(prefType) {
case "BOOL":
if (aMessage.json.op == "get")
return(prefs.getBoolPref(prefName));
else
return(prefs.setBoolPref(prefName, prefValue));
case "INT":
if (aMessage.json.op == "get")
return(prefs.getIntPref(prefName));
else
return(prefs.setIntPref(prefName, prefValue));
case "CHAR":
if (aMessage.json.op == "get")
return(prefs.getCharPref(prefName));
else
return(prefs.setCharPref(prefName, prefValue));
case "COMPLEX":
if (aMessage.json.op == "get")
return(prefs.getComplexValue(prefName, prefValue[0]));
else
return(prefs.setComplexValue(prefName, prefValue[0], prefValue[1]));
}
break;
default:
throw new SpecialPowersException("Unrecognized Special Powers API");
}
}
};
const NSGetFactory = XPCOMUtils.generateNSGetFactory([SpecialPowersObserver]);

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

@ -0,0 +1,144 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Special Powers code
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Clint Talbert cmtalbert@gmail.com
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK *****/
/* This code is loaded in every child process that is started by mochitest in
* order to be used as a replacement for UniversalXPConnect
*/
function SpecialPowers() {}
var SpecialPowers = {
sanityCheck: function() { return "foo"; },
// Mimic the get*Pref API
getBoolPref: function(aPrefName) {
return (this._getPref(aPrefName, 'BOOL'));
},
getIntPref: function(aPrefName) {
return (this._getPref(aPrefName, 'INT'));
},
getCharPref: function(aPrefName) {
return (this._getPref(aPrefName, 'CHAR'));
},
getComplexValue: function(aPrefName, aIid) {
return (this._getPref(aPrefName, 'COMPLEX', aIid));
},
// Mimic the set*Pref API
setBoolPref: function(aPrefName, aValue) {
return (this._setPref(aPrefName, 'BOOL', aValue));
},
setIntPref: function(aPrefName, aValue) {
return (this._setPref(aPrefName, 'INT', aValue));
},
setCharPref: function(aPrefName, aValue) {
return (this._setPref(aPrefName, 'CHAR', aValue));
},
setComplexValue: function(aPrefName, aIid, aValue) {
return (this._setPref(aPrefName, 'COMPLEX', aValue, aIid));
},
// Private pref functions to communicate to chrome
_getPref: function(aPrefName, aPrefType, aIid) {
var msg = {};
if (aIid) {
// Overloading prefValue to handle complex prefs
msg = {'op':'get', 'prefName': aPrefName, 'prefType':aPrefType, 'prefValue':[aIid]};
} else {
msg = {'op':'get', 'prefName': aPrefName,'prefType': aPrefType};
}
return(sendSyncMessage('SPPrefService', msg)[0]);
},
_setPref: function(aPrefName, aPrefType, aValue, aIid) {
var msg = {};
if (aIid) {
msg = {'op':'set','prefName':aPrefName, 'prefType': aPrefType, 'prefValue': [aIid,aValue]};
} else {
msg = {'op':'set', 'prefName': aPrefName, 'prefType': aPrefType, 'prefValue': aValue};
}
return(sendSyncMessage('SPPrefService', msg)[0]);
}
}
// Attach our API to the window
function attachSpecialPwrToWindow(aSubject) {
try {
if ((aSubject !== null) &&
(aSubject !== undefined) &&
(aSubject.wrappedJSObject) &&
!(aSubject.wrappedJSObject.SpecialPowers)) {
aSubject.wrappedJSObject.SpecialPowers = SpecialPowers;
}
} catch(ex) {
dump("TEST-INFO | specialpowers.js | Failed to attach specialpowers to window exception: " + ex + "\n");
}
}
// In true IPC, this loads in the child process so we need our own observer here
// to ensure we actually get attached, otherwise we'll miss content-document-global-created
// notifications
// NOTE: The observers are GC'd when the window dies, so while this looks like it should
// leak, it actually doesn't. And if you add in an observer for dom-window-destroyed or
// xpcom-shutdown and upon capturing either of those notifications you unregister the
// content-document-global-created observer, then in the child process you will never
// be able to capture another content-document-global-created on the next page load. Essentially,
// this is registered inside the child process once by our SpecialPowersObserver, and after that,
// we will no longer trip that chrome code again.
function frameScriptObserver() {
// Then we need to register the observers
this.register();
}
frameScriptObserver.prototype = {
observe: function(aSubject, aTopic, aData) {
if (aTopic == "content-document-global-created") {
attachSpecialPwrToWindow(aSubject);
}
},
register: function() {
var obsSvc = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
obsSvc.addObserver(this, "content-document-global-created", false);
},
unregister: function() {
var obsSvc = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
obsSvc.removeObserver(this, "content-document-global-created");
}
};
// VERY IMPORTANT: Only add observers if they are needed
if (content && !content.wrappedJSObject.SpecialPowers)
var frameScriptObsv = new frameScriptObserver();

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

@ -0,0 +1,26 @@
<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>special-powers@mozilla.org</em:id>
<em:version>2010.07.23</em:version>
<em:type>2</em:type>
<!-- Target Application this extension can install into,
with minimum and maximum supported versions. -->
<em:targetApplication>
<Description>
<em:id>toolkit@mozilla.org</em:id>
#expand <em:minVersion>__MOZILLA_VERSION_U__</em:minVersion>
#expand <em:maxVersion>__MOZILLA_VERSION_U__</em:maxVersion>
</Description>
</em:targetApplication>
<!-- Front End MetaData -->
<em:name>Special Powers</em:name>
<em:description>Special powers for use in testing.</em:description>
<em:creator>Mozilla</em:creator>
</Description>
</RDF>

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

@ -0,0 +1,3 @@
specialpowers.jar:
% content specialpowers %content/
content/specialpowers.js (content/specialpowers.js)

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

@ -53,8 +53,11 @@ PARALLEL_DIRS = \
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk
_TEST_FILES = \ _TEST_FILES = \
test_sanity.html \ test_sanity.html \
$(NULL) test_SpecialPowersExtension.html \
test_SpecialPowersExtension2.html \
file_SpecialPowersFrame1.html \
$(NULL)
# Copy the sanity tests into a subdirectory, so the top level is all dirs # Copy the sanity tests into a subdirectory, so the top level is all dirs
# in the test screen. # in the test screen.

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

@ -0,0 +1,15 @@
<html>
<head>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/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>
<div id="content" style="display: none">
<script type="text/javascript">
is(SpecialPowers.sanityCheck(), "foo", "Check Special Powers in iframe");
</script>
</div>
</body>
</html>

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

@ -0,0 +1,46 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for SpecialPowers extension</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/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 onload="starttest();">
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
dump("\nSPECIALPTEST:::Test script loaded " + (new Date).getTime() + "\n");
SimpleTest.waitForExplicitFinish();
function starttest(){
dump("\nSPECIALPTEST:::Test script running after load " + (new Date).getTime() + "\n");
/** Test for SpecialPowers extension **/
is(SpecialPowers.sanityCheck(), "foo", "check to see whether the Special Powers extension is installed.");
// Test a sync call into chrome
SpecialPowers.setBoolPref('extensions.checkCompatibility', true);
is(SpecialPowers.getBoolPref('extensions.checkCompatibility'), true, "Check to see if we can set a preference properly");
// Test a int pref
SpecialPowers.setIntPref('extensions.foobar', 42);
is(SpecialPowers.getIntPref('extensions.foobar'), 42, "Check int pref");
// Test a string pref
SpecialPowers.setCharPref("extensions.foobaz", "hi there");
is(SpecialPowers.getCharPref("extensions.foobaz"), "hi there", "Check string pref");
// Test Complex Pref - TODO: Without chrome access, I don't know how you'd actually
// set this preference since you have to create an XPCOM object.
// Leaving untested for now.
SimpleTest.finish();
}
//starttest();
</script>
</pre>
</body>
</html>

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

@ -0,0 +1,21 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for SpecialPowers extension</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/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>
<div id="content" class="testbody">
<script type="text/javascript">
dump("\nSPECIALPTEST2:::Loading test2 file now " + (new Date).getTime() + "\n");
is(SpecialPowers.sanityCheck(), "foo", "Special Powers top level");
</script>
<iframe id="frame1" src="file_SpecialPowersFrame1.html">
</iframe>
</div>
</body>
</html>