mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Back out 14463b9d2d14 and 97d43d93ab55 (Bug 621363 and Bug 676274) because of mochitest-browser-chrome leaks
This commit is contained in:
parent
b1e8fddbb2
commit
fc19fcb962
@ -19,9 +19,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=648573
|
||||
|
||||
/** Test for Bug 648573 **/
|
||||
|
||||
var utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
|
||||
ok(!utils.mayHaveTouchEventListeners,
|
||||
ok(!SpecialPowers.DOMWindowUtils.mayHaveTouchEventListeners,
|
||||
"There shouldn't be any touch event listeners yet.");
|
||||
|
||||
ok("createTouch" in document, "Should have createTouch function");
|
||||
@ -103,7 +101,7 @@ for (var i = 0; i < events.length; ++i) {
|
||||
runEventTest(events[i]);
|
||||
}
|
||||
|
||||
ok(utils.mayHaveTouchEventListeners,
|
||||
ok(SpecialPowers.DOMWindowUtils.mayHaveTouchEventListeners,
|
||||
"There should be touch event listeners.");
|
||||
</script>
|
||||
</pre>
|
||||
|
@ -18,11 +18,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=662678
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 662678 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var checkMotion = function(event) {
|
||||
window.removeEventListener("devicemotion", checkMotion, true);
|
||||
|
||||
window.addEventListener("devicemotion", function(event) {
|
||||
is(event.acceleration.x, 1.5);
|
||||
is(event.acceleration.y, 1.5);
|
||||
is(event.acceleration.z, 1.5);
|
||||
@ -35,9 +32,7 @@ var checkMotion = function(event) {
|
||||
is(event.rotationRate.beta, 1.5);
|
||||
is(event.rotationRate.gamma, 1.5);
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
||||
window.addEventListener("devicemotion", checkMotion, true);
|
||||
}, true);
|
||||
|
||||
var event = DeviceMotionEvent;
|
||||
ok(!!event, "Should have seen DeviceMotionEvent!");
|
||||
@ -49,6 +44,7 @@ event.initDeviceMotionEvent('devicemotion', true, true,
|
||||
{alpha:1.5,beta:1.5,gamma:1.5},
|
||||
0);
|
||||
window.dispatchEvent(event);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
@ -20,16 +20,15 @@
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
//we need SpecialPowers for WindowSnapshot.snapshotWindow()
|
||||
var imports = [ "SimpleTest", "is", "isnot", "ok", "SpecialPowers"];
|
||||
var imports = [ "SimpleTest", "is", "isnot", "ok" ];
|
||||
for each (var name in imports) {
|
||||
window[name] = window.opener.wrappedJSObject[name];
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
var testCanvas = snapshotWindow(window);
|
||||
var testCanvas = window.opener.SpecialPowers.snapshotWindow(window);
|
||||
|
||||
var refCanvas = snapshotWindow(window);
|
||||
var refCanvas = window.opener.SpecialPowers.snapshotWindow(window);
|
||||
var ctx = refCanvas.getContext('2d');
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(0, 0, refCanvas.width, refCanvas.height);
|
||||
|
@ -27,10 +27,24 @@
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function get_pref(pref)
|
||||
{
|
||||
return SpecialPowers.getIntPref("font.size." + pref);
|
||||
}
|
||||
|
||||
function set_pref(pref, val)
|
||||
{
|
||||
SpecialPowers.setIntPref("font.size." + pref, val);
|
||||
}
|
||||
|
||||
var cs1 = getComputedStyle(document.getElementById("one"), "");
|
||||
var cs2 = getComputedStyle(document.getElementById("two"), "");
|
||||
|
||||
SpecialPowers.pushPrefEnv({'set': [['variable.x-western', 25], ['fixed.x-western', 20]]}, function() setTimeout(part1, 0));
|
||||
var oldVariable = get_pref("variable.x-western");
|
||||
var oldFixed = get_pref("fixed.x-western");
|
||||
set_pref("variable.x-western", 25);
|
||||
set_pref("fixed.x-western", 20);
|
||||
setTimeout(part1, 0);
|
||||
|
||||
function part1()
|
||||
{
|
||||
@ -38,6 +52,8 @@ function part1()
|
||||
var fs2 = cs2.fontSize.match(/(.*)px/)[1];
|
||||
ok(fs1 < fs2, "<font size=-1> shrinks relative to font-family: -moz-fixed");
|
||||
|
||||
set_pref("variable.x-western", oldVariable);
|
||||
set_pref("fixed.x-western", oldFixed);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,10 @@ function fs(idx) {
|
||||
return getComputedStyle(elts[idx], "").marginBottom;
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({'clear': [['font.minimum-size.x-western']]}, function() setTimeout(step1, 0));
|
||||
SpecialPowers.clearUserPref('font.minimum-size.x-western');
|
||||
|
||||
// preference change is async (although one setTimeout might be enough?)
|
||||
setTimeout(setTimeout, 0, step1, 0);
|
||||
|
||||
function step1() {
|
||||
is(fs(0), "0px", "at min font size 0, 0px should compute to 0px");
|
||||
@ -64,7 +67,10 @@ function step1() {
|
||||
is(fs(2), "12px", "at min font size 0, 12px should compute to 12px");
|
||||
is(fs(3), "28px", "at min font size 0, 28px should compute to 28px");
|
||||
|
||||
SpecialPowers.pushPrefEnv({'set': [['font.minimum-size.x-western', 7]]}, function() setTimeout(step2, 0));
|
||||
SpecialPowers.setIntPref('font.minimum-size.x-western', 7);
|
||||
|
||||
// preference change is async (although one setTimeout might be enough?)
|
||||
setTimeout(setTimeout, 0, step2, 0);
|
||||
}
|
||||
|
||||
function step2() {
|
||||
@ -73,7 +79,10 @@ function step2() {
|
||||
is(fs(2), "12px", "at min font size 7, 12px should compute to 12px");
|
||||
is(fs(3), "28px", "at min font size 7, 28px should compute to 28px");
|
||||
|
||||
SpecialPowers.pushPrefEnv({'set': [['font.minimum-size.x-western', 18]]}, function() setTimeout(step3, 0));
|
||||
SpecialPowers.setIntPref('font.minimum-size.x-western', 18);
|
||||
|
||||
// preference change is async (although one setTimeout might be enough?)
|
||||
setTimeout(setTimeout, 0, step3, 0);
|
||||
}
|
||||
|
||||
function step3() {
|
||||
@ -82,7 +91,9 @@ function step3() {
|
||||
is(fs(2), "18px", "at min font size 18, 12px should compute to 18px");
|
||||
is(fs(3), "28px", "at min font size 18, 28px should compute to 28px");
|
||||
|
||||
SpecialPowers.pushPrefEnv({'clear': [['font.minimum-size.x-western']]}, SimpleTest.finish);
|
||||
SpecialPowers.clearUserPref('font.minimum-size.x-western');
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
@ -69,9 +69,8 @@ function synthesizeMouseEvent(type, // string
|
||||
modifiers, // long
|
||||
ignoreWindowBounds) // boolean
|
||||
{
|
||||
var utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
utils.sendMouseEvent(type, x, y, button, clickCount,
|
||||
modifiers, ignoreWindowBounds);
|
||||
SpecialPowers.DOMWindowUtils.sendMouseEvent(type, x, y, button, clickCount,
|
||||
modifiers, ignoreWindowBounds);
|
||||
}
|
||||
|
||||
function run_test()
|
||||
|
@ -95,6 +95,7 @@ _SERV_FILES = \
|
||||
ipc.js \
|
||||
browser-harness.xul \
|
||||
redirect.html \
|
||||
redirect.js \
|
||||
$(topsrcdir)/build/pgo/server-locations.txt \
|
||||
$(topsrcdir)/netwerk/test/httpserver/httpd.js \
|
||||
mozprefs.js \
|
||||
|
@ -23,7 +23,6 @@
|
||||
-
|
||||
- Contributor(s):
|
||||
- Gavin Sharp <gavin@gavinsharp.com> (original author)
|
||||
- Joel Maher <joel.maher@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
|
||||
|
@ -12,16 +12,16 @@ window.addEventListener("load", testOnLoad, false);
|
||||
function testOnLoad() {
|
||||
window.removeEventListener("load", testOnLoad, false);
|
||||
|
||||
// Make sure to launch the test harness for the first opened window only
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
if (prefs.prefHasUserValue("testing.browserTestHarness.running"))
|
||||
return;
|
||||
|
||||
prefs.setBoolPref("testing.browserTestHarness.running", true);
|
||||
gConfig = readConfig();
|
||||
|
||||
if (gConfig.testRoot == "browser") {
|
||||
// Make sure to launch the test harness for the first opened window only
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
if (prefs.prefHasUserValue("testing.browserTestHarness.running"))
|
||||
return;
|
||||
|
||||
prefs.setBoolPref("testing.browserTestHarness.running", true);
|
||||
|
||||
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
getService(Ci.nsIWindowWatcher);
|
||||
var sstring = Cc["@mozilla.org/supports-string;1"].
|
||||
@ -30,22 +30,6 @@ function testOnLoad() {
|
||||
|
||||
ww.openWindow(window, "chrome://mochikit/content/browser-harness.xul", "browserTest",
|
||||
"chrome,centerscreen,dialog=no,resizable,titlebar,toolbar=no,width=800,height=600", sstring);
|
||||
} else {
|
||||
// This code allows us to redirect without requiring specialpowers for chrome and a11y tests.
|
||||
function messageHandler(m) {
|
||||
messageManager.removeMessageListener("chromeEvent", messageHandler);
|
||||
var url = m.json.data;
|
||||
|
||||
// Window is the [ChromeWindow] for messageManager, so we need content.window
|
||||
// Currently chrome tests are run in a content window instead of a ChromeWindow
|
||||
var webNav = content.window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation);
|
||||
webNav.loadURI(url, null, null, null, null);
|
||||
}
|
||||
|
||||
var listener = 'data:,function doLoad(e) { var data=e.getData("data");removeEventListener("contentEvent", function (e) { doLoad(e); }, false, true);sendAsyncMessage("chromeEvent", {"data":data}); };addEventListener("contentEvent", function (e) { doLoad(e); }, false, true);';
|
||||
messageManager.loadFrameScript(listener, true);
|
||||
messageManager.addMessageListener("chromeEvent", messageHandler);
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,9 +48,6 @@ function Tester(aTests, aDumper, aCallback) {
|
||||
getService(Ci.mozIJSSubScriptLoader);
|
||||
this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/EventUtils.js", this.EventUtils);
|
||||
var simpleTestScope = {};
|
||||
this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/specialpowersAPI.js", simpleTestScope);
|
||||
this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/SpecialPowersObserverAPI.js", simpleTestScope);
|
||||
this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/ChromePowers.js", simpleTestScope);
|
||||
this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/SimpleTest.js", simpleTestScope);
|
||||
this._scriptLoader.loadSubScript("chrome://mochikit/content/chrome-harness.js", simpleTestScope);
|
||||
this.SimpleTest = simpleTestScope.SimpleTest;
|
||||
|
@ -11,12 +11,6 @@
|
||||
<window>
|
||||
<script type="text/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/LogController.js"/>
|
||||
<script type="text/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/specialpowersAPI.js"/>
|
||||
<script type="text/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SpecialPowersObserverAPI.js"/>
|
||||
<script type="text/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/ChromePowers.js"/>
|
||||
<script type="text/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/TestRunner.js"/>
|
||||
<script type="text/javascript"
|
||||
|
@ -10,12 +10,10 @@ mochikit.jar:
|
||||
content/ipc-overlay.xul (ipc-overlay.xul)
|
||||
content/mozprefs.js (mozprefs.js)
|
||||
content/redirect.html (redirect.html)
|
||||
content/redirect.js (redirect.js)
|
||||
content/server.js (server.js)
|
||||
content/dynamic/getMyDirectory.sjs (dynamic/getMyDirectory.sjs)
|
||||
content/static/harness.css (static/harness.css)
|
||||
content/tests/SimpleTest/ChromePowers.js (tests/SimpleTest/ChromePowers.js)
|
||||
content/tests/SimpleTest/specialpowersAPI.js (tests/SimpleTest/specialpowersAPI.js)
|
||||
content/tests/SimpleTest/SpecialPowersObserverAPI.js (tests/SimpleTest/SpecialPowersObserverAPI.js)
|
||||
content/tests/SimpleTest/EventUtils.js (tests/SimpleTest/EventUtils.js)
|
||||
content/tests/SimpleTest/ChromeUtils.js (tests/SimpleTest/ChromeUtils.js)
|
||||
content/tests/SimpleTest/MozillaLogger.js (tests/SimpleTest/MozillaLogger.js)
|
||||
|
@ -2,16 +2,9 @@
|
||||
<head>
|
||||
<title>redirecting...</title>
|
||||
|
||||
<script type="text/javascript">
|
||||
function redirect(aURL)
|
||||
{
|
||||
var element = document.createEvent("datacontainerevent");
|
||||
element.initEvent("contentEvent", true, false);
|
||||
element.setData("data", aURL + location.search);
|
||||
element.setData("type", "loadURI");
|
||||
document.dispatchEvent(element);
|
||||
}
|
||||
<script type="text/javascript" src="redirect.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
redirect("chrome://mochikit/content/harness.xul");
|
||||
</script>
|
||||
</head>
|
||||
|
45
testing/mochitest/redirect.js
Normal file
45
testing/mochitest/redirect.js
Normal file
@ -0,0 +1,45 @@
|
||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* ***** 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 MozJSHTTP code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Robert Sayre <sayrer@gmail.com>
|
||||
* Alexander Surkov <surkov.alexander@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 ***** */
|
||||
|
||||
function redirect(aURL)
|
||||
{
|
||||
SpecialPowers.loadURI(window, aURL + location.search,
|
||||
null, null, null, null);
|
||||
}
|
@ -510,11 +510,7 @@ class Mochitest(object):
|
||||
manifest = self.addChromeToProfile(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)
|
||||
self.installSpecialPowersExtension(options)
|
||||
self.installExtensionsToProfile(options)
|
||||
return manifest
|
||||
|
||||
|
@ -50,15 +50,19 @@ const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
const CHILD_SCRIPT = "chrome://specialpowers/content/specialpowers.js"
|
||||
const CHILD_SCRIPT_API = "chrome://specialpowers/content/specialpowersAPI.js"
|
||||
const CHILD_LOGGER_SCRIPT = "chrome://specialpowers/content/MozillaLogger.js"
|
||||
|
||||
/**
|
||||
* Special Powers Exception - used to throw exceptions nicely
|
||||
**/
|
||||
function SpecialPowersException(aMsg) {
|
||||
this.message = aMsg;
|
||||
this.name = "SpecialPowersException";
|
||||
}
|
||||
|
||||
//glue to add in the observer API to this object. This allows us to share code with chrome tests
|
||||
var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Components.interfaces.mozIJSSubScriptLoader);
|
||||
loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserverAPI.js");
|
||||
|
||||
SpecialPowersException.prototype.toString = function() {
|
||||
return this.name + ': "' + this.message + '"';
|
||||
};
|
||||
|
||||
/* XPCOM gunk */
|
||||
function SpecialPowersObserver() {
|
||||
@ -67,16 +71,14 @@ function SpecialPowersObserver() {
|
||||
getService(Ci.nsIChromeFrameMessageManager);
|
||||
}
|
||||
|
||||
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 }],
|
||||
|
||||
SpecialPowersObserver.prototype = new SpecialPowersObserverAPI();
|
||||
|
||||
SpecialPowersObserver.prototype.classDescription = "Special powers Observer for use in testing.";
|
||||
SpecialPowersObserver.prototype.classID = Components.ID("{59a52458-13e0-4d93-9d85-a637344f29a1}");
|
||||
SpecialPowersObserver.prototype.contractID = "@mozilla.org/special-powers-observer;1";
|
||||
SpecialPowersObserver.prototype.QueryInterface = XPCOMUtils.generateQI([Components.interfaces.nsIObserver]);
|
||||
SpecialPowersObserver.prototype._xpcom_categories = [{category: "profile-after-change", service: true }];
|
||||
|
||||
SpecialPowersObserver.prototype.observe = function(aSubject, aTopic, aData)
|
||||
observe: function(aSubject, aTopic, aData)
|
||||
{
|
||||
switch (aTopic) {
|
||||
case "profile-after-change":
|
||||
@ -91,7 +93,6 @@ SpecialPowersObserver.prototype = new SpecialPowersObserverAPI();
|
||||
this._messageManager.addMessageListener("SPPingService", this);
|
||||
|
||||
this._messageManager.loadFrameScript(CHILD_LOGGER_SCRIPT, true);
|
||||
this._messageManager.loadFrameScript(CHILD_SCRIPT_API, true);
|
||||
this._messageManager.loadFrameScript(CHILD_SCRIPT, true);
|
||||
this._isFrameScriptLoaded = true;
|
||||
}
|
||||
@ -101,41 +102,180 @@ SpecialPowersObserver.prototype = new SpecialPowersObserverAPI();
|
||||
this.uninit();
|
||||
break;
|
||||
|
||||
default:
|
||||
this._observe(aSubject, aTopic, aData);
|
||||
case "plugin-crashed":
|
||||
case "ipc:content-shutdown":
|
||||
function addDumpIDToMessage(propertyName) {
|
||||
var id = aSubject.getPropertyAsAString(propertyName);
|
||||
if (id) {
|
||||
message.dumpIDs.push(id);
|
||||
}
|
||||
}
|
||||
|
||||
var message = { type: "crash-observed", dumpIDs: [] };
|
||||
aSubject = aSubject.QueryInterface(Ci.nsIPropertyBag2);
|
||||
if (aTopic == "plugin-crashed") {
|
||||
addDumpIDToMessage("pluginDumpID");
|
||||
addDumpIDToMessage("browserDumpID");
|
||||
} else { // ipc:content-shutdown
|
||||
addDumpIDToMessage("dumpID");
|
||||
}
|
||||
this._messageManager.sendAsyncMessage("SPProcessCrashService", message);
|
||||
break;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
SpecialPowersObserver.prototype._sendAsyncMessage = function(msgname, msg)
|
||||
{
|
||||
this._messageManager.sendAsyncMessage(msgname, msg);
|
||||
};
|
||||
|
||||
SpecialPowersObserver.prototype._receiveMessage = function(aMessage) {
|
||||
return this._receiveMessageAPI(aMessage);
|
||||
};
|
||||
|
||||
SpecialPowersObserver.prototype.init = function()
|
||||
init: function()
|
||||
{
|
||||
var obs = Services.obs;
|
||||
obs.addObserver(this, "xpcom-shutdown", false);
|
||||
obs.addObserver(this, "chrome-document-global-created", false);
|
||||
};
|
||||
},
|
||||
|
||||
SpecialPowersObserver.prototype.uninit = function()
|
||||
uninit: function()
|
||||
{
|
||||
var obs = Services.obs;
|
||||
obs.removeObserver(this, "chrome-document-global-created", false);
|
||||
this._removeProcessCrashObservers();
|
||||
};
|
||||
this.removeProcessCrashObservers();
|
||||
},
|
||||
|
||||
addProcessCrashObservers: function() {
|
||||
if (this._processCrashObserversRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
Services.obs.addObserver(this, "plugin-crashed", false);
|
||||
Services.obs.addObserver(this, "ipc:content-shutdown", false);
|
||||
this._processCrashObserversRegistered = true;
|
||||
},
|
||||
|
||||
removeProcessCrashObservers: function() {
|
||||
if (!this._processCrashObserversRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
Services.obs.removeObserver(this, "plugin-crashed");
|
||||
Services.obs.removeObserver(this, "ipc:content-shutdown");
|
||||
this._processCrashObserversRegistered = false;
|
||||
},
|
||||
|
||||
getCrashDumpDir: function() {
|
||||
if (!this._crashDumpDir) {
|
||||
var directoryService = Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIProperties);
|
||||
this._crashDumpDir = directoryService.get("ProfD", Ci.nsIFile);
|
||||
this._crashDumpDir.append("minidumps");
|
||||
}
|
||||
return this._crashDumpDir;
|
||||
},
|
||||
|
||||
deleteCrashDumpFiles: function(aFilenames) {
|
||||
var crashDumpDir = this.getCrashDumpDir();
|
||||
if (!crashDumpDir.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var success = aFilenames.length != 0;
|
||||
aFilenames.forEach(function(crashFilename) {
|
||||
var file = crashDumpDir.clone();
|
||||
file.append(crashFilename);
|
||||
if (file.exists()) {
|
||||
file.remove(false);
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
});
|
||||
return success;
|
||||
},
|
||||
|
||||
findCrashDumpFiles: function(aToIgnore) {
|
||||
var crashDumpDir = this.getCrashDumpDir();
|
||||
var entries = crashDumpDir.exists() && crashDumpDir.directoryEntries;
|
||||
if (!entries) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var crashDumpFiles = [];
|
||||
while (entries.hasMoreElements()) {
|
||||
var file = entries.getNext().QueryInterface(Ci.nsIFile);
|
||||
var path = String(file.path);
|
||||
if (path.match(/\.(dmp|extra)$/) && !aToIgnore[path]) {
|
||||
crashDumpFiles.push(path);
|
||||
}
|
||||
}
|
||||
return crashDumpFiles.concat();
|
||||
},
|
||||
|
||||
/**
|
||||
* messageManager callback function
|
||||
* This will get requests from our API in the window and process them in chrome for it
|
||||
**/
|
||||
SpecialPowersObserver.prototype.receiveMessage = function(aMessage) {
|
||||
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 if (aMessage.json.op == "clear") {
|
||||
if (!prefName)
|
||||
throw new SpecialPowersException("Invalid parameters for clear 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]));
|
||||
case "":
|
||||
if (aMessage.json.op == "clear") {
|
||||
prefs.clearUserPref(prefName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "SPProcessCrashService":
|
||||
switch (aMessage.json.op) {
|
||||
case "register-observer":
|
||||
this.addProcessCrashObservers();
|
||||
break;
|
||||
case "unregister-observer":
|
||||
this.removeProcessCrashObservers();
|
||||
break;
|
||||
case "delete-crash-dump-files":
|
||||
return this.deleteCrashDumpFiles(aMessage.json.filenames);
|
||||
case "find-crash-dump-files":
|
||||
return this.findCrashDumpFiles(aMessage.json.crashDumpFilesToIgnore);
|
||||
default:
|
||||
throw new SpecialPowersException("Invalid operation for SPProcessCrashService");
|
||||
}
|
||||
break;
|
||||
|
||||
case "SPPingService":
|
||||
if (aMessage.json.op == "ping") {
|
||||
aMessage.target
|
||||
@ -145,9 +285,11 @@ SpecialPowersObserver.prototype = new SpecialPowersObserverAPI();
|
||||
.sendAsyncMessage("SPPingService", { op: "pong" });
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return this._receiveMessage(aMessage);
|
||||
throw new SpecialPowersException("Unrecognized Special Powers API");
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([SpecialPowersObserver]);
|
||||
|
@ -38,76 +38,362 @@
|
||||
* order to be used as a replacement for UniversalXPConnect
|
||||
*/
|
||||
|
||||
var Ci = Components.interfaces;
|
||||
var Cc = Components.classes;
|
||||
|
||||
function SpecialPowers(window) {
|
||||
this.window = window;
|
||||
this.DOMWindowUtils = bindDOMWindowUtils(window);
|
||||
bindDOMWindowUtils(this, window);
|
||||
this._encounteredCrashDumpFiles = [];
|
||||
this._unexpectedCrashDumpFiles = { };
|
||||
this._crashDumpDir = null;
|
||||
this._pongHandlers = [];
|
||||
this._messageListener = this._messageReceived.bind(this);
|
||||
addMessageListener("SPPingService", this._messageListener);
|
||||
this._consoleListeners = [];
|
||||
}
|
||||
|
||||
SpecialPowers.prototype = new SpecialPowersAPI();
|
||||
|
||||
SpecialPowers.prototype.toString = function() { return "[SpecialPowers]"; };
|
||||
SpecialPowers.prototype.sanityCheck = function() { return "foo"; };
|
||||
|
||||
// This gets filled in in the constructor.
|
||||
SpecialPowers.prototype.DOMWindowUtils = undefined;
|
||||
|
||||
SpecialPowers.prototype._sendSyncMessage = function(msgname, msg) {
|
||||
return sendSyncMessage(msgname, msg);
|
||||
};
|
||||
|
||||
SpecialPowers.prototype._sendAsyncMessage = function(msgname, msg) {
|
||||
sendAsyncMessage(msgname, msg);
|
||||
};
|
||||
|
||||
SpecialPowers.prototype.registerProcessCrashObservers = function() {
|
||||
addMessageListener("SPProcessCrashService", this._messageListener);
|
||||
sendSyncMessage("SPProcessCrashService", { op: "register-observer" });
|
||||
};
|
||||
|
||||
SpecialPowers.prototype.unregisterProcessCrashObservers = function() {
|
||||
addMessageListener("SPProcessCrashService", this._messageListener);
|
||||
sendSyncMessage("SPProcessCrashService", { op: "unregister-observer" });
|
||||
};
|
||||
|
||||
SpecialPowers.prototype._messageReceived = function(aMessage) {
|
||||
switch (aMessage.name) {
|
||||
case "SPProcessCrashService":
|
||||
if (aMessage.json.type == "crash-observed") {
|
||||
var self = this;
|
||||
aMessage.json.dumpIDs.forEach(function(id) {
|
||||
self._encounteredCrashDumpFiles.push(id + ".dmp");
|
||||
self._encounteredCrashDumpFiles.push(id + ".extra");
|
||||
});
|
||||
function bindDOMWindowUtils(sp, window) {
|
||||
var util = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
// This bit of magic brought to you by the letters
|
||||
// B Z, and E, S and the number 5.
|
||||
//
|
||||
// Take all of the properties on the nsIDOMWindowUtils-implementing
|
||||
// object, and rebind them onto a new object with a stub that uses
|
||||
// apply to call them from this privileged scope. This way we don't
|
||||
// have to explicitly stub out new methods that appear on
|
||||
// nsIDOMWindowUtils.
|
||||
var proto = Object.getPrototypeOf(util);
|
||||
var target = {};
|
||||
function rebind(desc, prop) {
|
||||
if (prop in desc && typeof(desc[prop]) == "function") {
|
||||
var oldval = desc[prop];
|
||||
try {
|
||||
desc[prop] = function() { return oldval.apply(util, arguments); };
|
||||
} catch (ex) {
|
||||
dump("WARNING: Special Powers failed to rebind function: " + desc + "::" + prop + "\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case "SPPingService":
|
||||
if (aMessage.json.op == "pong") {
|
||||
var handler = this._pongHandlers.shift();
|
||||
if (handler) {
|
||||
handler();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
for (var i in proto) {
|
||||
var desc = Object.getOwnPropertyDescriptor(proto, i);
|
||||
rebind(desc, "get");
|
||||
rebind(desc, "set");
|
||||
rebind(desc, "value");
|
||||
Object.defineProperty(target, i, desc);
|
||||
}
|
||||
sp.DOMWindowUtils = target;
|
||||
}
|
||||
|
||||
SpecialPowers.prototype.executeAfterFlushingMessageQueue = function(aCallback) {
|
||||
this._pongHandlers.push(aCallback);
|
||||
sendAsyncMessage("SPPingService", { op: "ping" });
|
||||
SpecialPowers.prototype = {
|
||||
toString: function() { return "[SpecialPowers]"; },
|
||||
sanityCheck: function() { return "foo"; },
|
||||
|
||||
// This gets filled in in the constructor.
|
||||
DOMWindowUtils: undefined,
|
||||
|
||||
// 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));
|
||||
},
|
||||
|
||||
// Mimic the clearUserPref API
|
||||
clearUserPref: function(aPrefName) {
|
||||
var msg = {'op':'clear', 'prefName': aPrefName, 'prefType': ""};
|
||||
sendSyncMessage('SPPrefService', msg);
|
||||
},
|
||||
|
||||
// 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};
|
||||
}
|
||||
var val = sendSyncMessage('SPPrefService', msg);
|
||||
|
||||
if (val == null || val[0] == null)
|
||||
throw "Error getting pref";
|
||||
return val[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]);
|
||||
},
|
||||
|
||||
//XXX: these APIs really ought to be removed, they're not e10s-safe.
|
||||
// (also they're pretty Firefox-specific)
|
||||
_getTopChromeWindow: function(window) {
|
||||
return window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow)
|
||||
.QueryInterface(Ci.nsIDOMChromeWindow);
|
||||
},
|
||||
_getDocShell: function(window) {
|
||||
return window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
},
|
||||
_getMUDV: function(window) {
|
||||
return this._getDocShell(window).contentViewer
|
||||
.QueryInterface(Ci.nsIMarkupDocumentViewer);
|
||||
},
|
||||
_getAutoCompletePopup: function(window) {
|
||||
return this._getTopChromeWindow(window).document
|
||||
.getElementById("PopupAutoComplete");
|
||||
},
|
||||
addAutoCompletePopupEventListener: function(window, listener) {
|
||||
this._getAutoCompletePopup(window).addEventListener("popupshowing",
|
||||
listener,
|
||||
false);
|
||||
},
|
||||
removeAutoCompletePopupEventListener: function(window, listener) {
|
||||
this._getAutoCompletePopup(window).removeEventListener("popupshowing",
|
||||
listener,
|
||||
false);
|
||||
},
|
||||
isBackButtonEnabled: function(window) {
|
||||
return !this._getTopChromeWindow(window).document
|
||||
.getElementById("Browser:Back")
|
||||
.hasAttribute("disabled");
|
||||
},
|
||||
|
||||
addChromeEventListener: function(type, listener, capture, allowUntrusted) {
|
||||
addEventListener(type, listener, capture, allowUntrusted);
|
||||
},
|
||||
removeChromeEventListener: function(type, listener, capture) {
|
||||
removeEventListener(type, listener, capture);
|
||||
},
|
||||
|
||||
addErrorConsoleListener: function(listener) {
|
||||
var consoleListener = {
|
||||
userListener: listener,
|
||||
observe: function(consoleMessage) {
|
||||
this.userListener(consoleMessage.message);
|
||||
}
|
||||
};
|
||||
|
||||
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
|
||||
.registerListener(consoleListener);
|
||||
|
||||
this._consoleListeners.push(consoleListener);
|
||||
},
|
||||
|
||||
removeErrorConsoleListener: function(listener) {
|
||||
for (var index in this._consoleListeners) {
|
||||
var consoleListener = this._consoleListeners[index];
|
||||
if (consoleListener.userListener == listener) {
|
||||
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
|
||||
.unregisterListener(consoleListener);
|
||||
this._consoleListeners = this._consoleListeners.splice(index, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getFullZoom: function(window) {
|
||||
return this._getMUDV(window).fullZoom;
|
||||
},
|
||||
setFullZoom: function(window, zoom) {
|
||||
this._getMUDV(window).fullZoom = zoom;
|
||||
},
|
||||
getTextZoom: function(window) {
|
||||
return this._getMUDV(window).textZoom;
|
||||
},
|
||||
setTextZoom: function(window, zoom) {
|
||||
this._getMUDV(window).textZoom = zoom;
|
||||
},
|
||||
|
||||
createSystemXHR: function() {
|
||||
return Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
},
|
||||
|
||||
loadURI: function(window, uri, referrer, charset, x, y) {
|
||||
var webNav = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation);
|
||||
webNav.loadURI(uri, referrer, charset, x, y);
|
||||
},
|
||||
|
||||
snapshotWindow: function (win, withCaret) {
|
||||
var el = this.window.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
el.width = win.innerWidth;
|
||||
el.height = win.innerHeight;
|
||||
var ctx = el.getContext("2d");
|
||||
var flags = 0;
|
||||
|
||||
ctx.drawWindow(win, win.scrollX, win.scrollY,
|
||||
win.innerWidth, win.innerHeight,
|
||||
"rgb(255,255,255)",
|
||||
withCaret ? ctx.DRAWWINDOW_DRAW_CARET : 0);
|
||||
return el;
|
||||
},
|
||||
|
||||
gc: function() {
|
||||
this.DOMWindowUtils.garbageCollect();
|
||||
},
|
||||
|
||||
forceGC: function() {
|
||||
Components.utils.forceGC();
|
||||
},
|
||||
|
||||
hasContentProcesses: function() {
|
||||
try {
|
||||
var rt = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
|
||||
return rt.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
|
||||
} catch (e) {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
_xpcomabi: null,
|
||||
|
||||
get XPCOMABI() {
|
||||
if (this._xpcomabi != null)
|
||||
return this._xpcomabi;
|
||||
|
||||
var xulRuntime = Cc["@mozilla.org/xre/app-info;1"]
|
||||
.getService(Components.interfaces.nsIXULAppInfo)
|
||||
.QueryInterface(Components.interfaces.nsIXULRuntime);
|
||||
|
||||
this._xpcomabi = xulRuntime.XPCOMABI;
|
||||
return this._xpcomabi;
|
||||
},
|
||||
|
||||
registerProcessCrashObservers: function() {
|
||||
addMessageListener("SPProcessCrashService", this._messageListener);
|
||||
sendSyncMessage("SPProcessCrashService", { op: "register-observer" });
|
||||
},
|
||||
|
||||
_messageReceived: function(aMessage) {
|
||||
switch (aMessage.name) {
|
||||
case "SPProcessCrashService":
|
||||
if (aMessage.json.type == "crash-observed") {
|
||||
var self = this;
|
||||
aMessage.json.dumpIDs.forEach(function(id) {
|
||||
self._encounteredCrashDumpFiles.push(id + ".dmp");
|
||||
self._encounteredCrashDumpFiles.push(id + ".extra");
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case "SPPingService":
|
||||
if (aMessage.json.op == "pong") {
|
||||
var handler = this._pongHandlers.shift();
|
||||
if (handler) {
|
||||
handler();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
removeExpectedCrashDumpFiles: function(aExpectingProcessCrash) {
|
||||
var success = true;
|
||||
if (aExpectingProcessCrash) {
|
||||
var message = {
|
||||
op: "delete-crash-dump-files",
|
||||
filenames: this._encounteredCrashDumpFiles
|
||||
};
|
||||
if (!sendSyncMessage("SPProcessCrashService", message)[0]) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
this._encounteredCrashDumpFiles.length = 0;
|
||||
return success;
|
||||
},
|
||||
|
||||
findUnexpectedCrashDumpFiles: function() {
|
||||
var self = this;
|
||||
var message = {
|
||||
op: "find-crash-dump-files",
|
||||
crashDumpFilesToIgnore: this._unexpectedCrashDumpFiles
|
||||
};
|
||||
var crashDumpFiles = sendSyncMessage("SPProcessCrashService", message)[0];
|
||||
crashDumpFiles.forEach(function(aFilename) {
|
||||
self._unexpectedCrashDumpFiles[aFilename] = true;
|
||||
});
|
||||
return crashDumpFiles;
|
||||
},
|
||||
|
||||
executeAfterFlushingMessageQueue: function(aCallback) {
|
||||
this._pongHandlers.push(aCallback);
|
||||
sendAsyncMessage("SPPingService", { op: "ping" });
|
||||
},
|
||||
|
||||
executeSoon: function(aFunc) {
|
||||
var tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
|
||||
tm.mainThread.dispatch({
|
||||
run: function() {
|
||||
aFunc();
|
||||
}
|
||||
}, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
},
|
||||
|
||||
addSystemEventListener: function(target, type, listener, useCapture) {
|
||||
Cc["@mozilla.org/eventlistenerservice;1"].
|
||||
getService(Ci.nsIEventListenerService).
|
||||
addSystemEventListener(target, type, listener, useCapture);
|
||||
},
|
||||
removeSystemEventListener: function(target, type, listener, useCapture) {
|
||||
Cc["@mozilla.org/eventlistenerservice;1"].
|
||||
getService(Ci.nsIEventListenerService).
|
||||
removeSystemEventListener(target, type, listener, useCapture);
|
||||
},
|
||||
|
||||
setLogFile: function(path) {
|
||||
this._mfl = new MozillaFileLogger(path);
|
||||
},
|
||||
|
||||
log: function(data) {
|
||||
this._mfl.log(data);
|
||||
},
|
||||
|
||||
closeLogFile: function() {
|
||||
this._mfl.close();
|
||||
},
|
||||
};
|
||||
|
||||
// Expose everything but internal APIs (starting with underscores) to
|
||||
// web content. We cannot use Object.keys to view SpecialPowers.prototype since
|
||||
// we are using the functions from SpecialPowersAPI.prototype
|
||||
// web content.
|
||||
SpecialPowers.prototype.__exposedProps__ = {};
|
||||
for (var i in SpecialPowers.prototype) {
|
||||
if (i.charAt(0) != "_")
|
||||
SpecialPowers.prototype.__exposedProps__[i] = "r";
|
||||
for each (i in Object.keys(SpecialPowers.prototype).filter(function(v) {return v.charAt(0) != "_";})) {
|
||||
SpecialPowers.prototype.__exposedProps__[i] = "r";
|
||||
}
|
||||
|
||||
// Attach our API to the window.
|
||||
@ -115,16 +401,8 @@ function attachSpecialPowersToWindow(aWindow) {
|
||||
try {
|
||||
if ((aWindow !== null) &&
|
||||
(aWindow !== undefined) &&
|
||||
(aWindow.parent !== null) &&
|
||||
(aWindow.parent !== undefined) &&
|
||||
(aWindow.parent.wrappedJSObject.SpecialPowers) &&
|
||||
(aWindow.wrappedJSObject) &&
|
||||
!(aWindow.wrappedJSObject.SpecialPowers)) {
|
||||
aWindow.wrappedJSObject.SpecialPowers = aWindow.parent.SpecialPowers;
|
||||
}
|
||||
else if ((aWindow !== null) &&
|
||||
(aWindow !== undefined) &&
|
||||
(aWindow.wrappedJSObject) &&
|
||||
!(aWindow.wrappedJSObject.SpecialPowers)) {
|
||||
aWindow.wrappedJSObject.SpecialPowers = new SpecialPowers(aWindow);
|
||||
}
|
||||
} catch(ex) {
|
||||
@ -145,9 +423,9 @@ SpecialPowersManager.prototype = {
|
||||
handleEvent: function handleEvent(aEvent) {
|
||||
var window = aEvent.target.defaultView;
|
||||
|
||||
// only add SpecialPowers to data pages, not about:* or chrome://*
|
||||
// only add SpecialPowers to data pages, not about:*
|
||||
var uri = window.document.documentURIObject;
|
||||
if (uri.scheme === "chrome" || uri.spec.split(":")[0] == "about") {
|
||||
if (uri.spec.split(":")[0] == "about") {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,4 @@
|
||||
specialpowers.jar:
|
||||
% content specialpowers %content/
|
||||
content/specialpowers.js (content/specialpowers.js)
|
||||
content/specialpowersAPI.js (../tests/SimpleTest/specialpowersAPI.js)
|
||||
content/SpecialPowersObserverAPI.js (../tests/SimpleTest/SpecialPowersObserverAPI.js)
|
||||
content/MozillaLogger.js (../tests/SimpleTest/MozillaLogger.js)
|
||||
|
@ -1,120 +0,0 @@
|
||||
/* ***** 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) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Joel Maher <joel.maher@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 ***** */
|
||||
|
||||
function ChromePowers(window) {
|
||||
this.window = window;
|
||||
|
||||
// In the case of browser-chrome tests, we are running as a [ChromeWindow]
|
||||
// and we have no window.QueryInterface available, content.window is what we need
|
||||
if (typeof(window) == "ChromeWindow" && typeof(content.window) == "Window") {
|
||||
this.DOMWindowUtils = bindDOMWindowUtils(content.window);
|
||||
this.window = content.window
|
||||
} else {
|
||||
this.DOMWindowUtils = bindDOMWindowUtils(window);
|
||||
}
|
||||
|
||||
this.spObserver = new SpecialPowersObserverAPI();
|
||||
}
|
||||
|
||||
ChromePowers.prototype = new SpecialPowersAPI();
|
||||
|
||||
ChromePowers.prototype.toString = function() { return "[ChromePowers]"; };
|
||||
ChromePowers.prototype.sanityCheck = function() { return "foo"; };
|
||||
|
||||
// This gets filled in in the constructor.
|
||||
ChromePowers.prototype.DOMWindowUtils = undefined;
|
||||
|
||||
ChromePowers.prototype._sendSyncMessage = function(type, msg) {
|
||||
var aMessage = {'name':type, 'json': msg};
|
||||
return [this._receiveMessage(aMessage)];
|
||||
};
|
||||
|
||||
ChromePowers.prototype._sendAsyncMessage = function(type, msg) {
|
||||
var aMessage = {'name':type, 'json': msg};
|
||||
this._receiveMessage(aMessage);
|
||||
};
|
||||
|
||||
ChromePowers.prototype.registerProcessCrashObservers = function() {
|
||||
this._sendSyncMessage("SPProcessCrashService", { op: "register-observer" });
|
||||
};
|
||||
|
||||
ChromePowers.prototype.unregisterProcessCrashObservers = function() {
|
||||
this._sendSyncMessage("SPProcessCrashService", { op: "unregister-observer" });
|
||||
};
|
||||
|
||||
ChromePowers.prototype._receiveMessage = function(aMessage) {
|
||||
switch (aMessage.name) {
|
||||
case "SPProcessCrashService":
|
||||
if (aMessage.json.op == "register-observer" || aMessage.json.op == "unregister-observer") {
|
||||
// Hack out register/unregister specifically for browser-chrome leaks
|
||||
break;
|
||||
} else if (aMessage.type == "crash-observed") {
|
||||
var self = this;
|
||||
msg.dumpIDs.forEach(function(id) {
|
||||
self._encounteredCrashDumpFiles.push(id + ".dmp");
|
||||
self._encounteredCrashDumpFiles.push(id + ".extra");
|
||||
});
|
||||
}
|
||||
default:
|
||||
// All calls go here, because we need to handle SPProcessCrashService calls as well
|
||||
return this.spObserver._receiveMessageAPI(aMessage);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
ChromePowers.prototype.executeAfterFlushingMessageQueue = function(aCallback) {
|
||||
aCallback();
|
||||
};
|
||||
|
||||
// Expose everything but internal APIs (starting with underscores) to
|
||||
// web content. We cannot use Object.keys to view SpecialPowers.prototype since
|
||||
// we are using the functions from SpecialPowersAPI.prototype
|
||||
ChromePowers.prototype.__exposedProps__ = {};
|
||||
for (var i in ChromePowers.prototype) {
|
||||
if (i.charAt(0) != "_")
|
||||
ChromePowers.prototype.__exposedProps__[i] = "r";
|
||||
}
|
||||
|
||||
if ((window.parent !== null) &&
|
||||
(window.parent !== undefined) &&
|
||||
(window.parent.wrappedJSObject.SpecialPowers) &&
|
||||
!(window.wrappedJSObject.SpecialPowers)) {
|
||||
window.wrappedJSObject.SpecialPowers = window.parent.SpecialPowers;
|
||||
} else {
|
||||
window.wrappedJSObject.SpecialPowers = new ChromePowers(window);
|
||||
}
|
||||
|
@ -53,8 +53,6 @@ _SIMPLETEST_FILES = MozillaLogger.js \
|
||||
ChromeUtils.js \
|
||||
WindowSnapshot.js \
|
||||
PluginUtils.js \
|
||||
specialpowersAPI.js \
|
||||
SpecialPowersObserverAPI.js \
|
||||
$(DEPTH)/toolkit/content/tests/browser/common/mockObjects.js \
|
||||
$(DEPTH)/docshell/test/chrome/docshell_helpers.js \
|
||||
$(NULL)
|
||||
|
@ -22,11 +22,6 @@ if (parent) {
|
||||
if (!parentRunner && parent.wrappedJSObject) {
|
||||
parentRunner = parent.wrappedJSObject.TestRunner;
|
||||
}
|
||||
|
||||
//This is the case where we have ChromePowers in harness.xul and we need it in the iframe
|
||||
if (window.SpecialPowers == undefined && parent.SpecialPowers !== undefined) {
|
||||
window.SpecialPowers = parent.SpecialPowers;
|
||||
}
|
||||
}
|
||||
|
||||
// running in e10s build and need to use IPC?
|
||||
|
@ -1,234 +0,0 @@
|
||||
/* ***** 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) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jesse Ruderman <jruderman@mozilla.com>
|
||||
* Robert Sayre <sayrer@gmail.com>
|
||||
* Joel Maher <joel.maher@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 *****/
|
||||
|
||||
/**
|
||||
* 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 + '"';
|
||||
};
|
||||
|
||||
function SpecialPowersObserverAPI() {
|
||||
this._crashDumpDir = null;
|
||||
this._processCrashObserversRegistered = false;
|
||||
}
|
||||
|
||||
SpecialPowersObserverAPI.prototype = {
|
||||
|
||||
_observe: function(aSubject, aTopic, aData) {
|
||||
switch(aTopic) {
|
||||
case "plugin-crashed":
|
||||
case "ipc:content-shutdown":
|
||||
function addDumpIDToMessage(propertyName) {
|
||||
var id = aSubject.getPropertyAsAString(propertyName);
|
||||
if (id) {
|
||||
message.dumpIDs.push(id);
|
||||
}
|
||||
}
|
||||
|
||||
var message = { type: "crash-observed", dumpIDs: [] };
|
||||
aSubject = aSubject.QueryInterface(Components.interfaces.nsIPropertyBag2);
|
||||
if (aTopic == "plugin-crashed") {
|
||||
addDumpIDToMessage("pluginDumpID");
|
||||
addDumpIDToMessage("browserDumpID");
|
||||
} else { // ipc:content-shutdown
|
||||
addDumpIDToMessage("dumpID");
|
||||
}
|
||||
this._sendAsyncMessage("SPProcessCrashService", message);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_addProcessCrashObservers: function() {
|
||||
if (this._processCrashObserversRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
var obs = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
|
||||
obs.addObserver(this, "plugin-crashed", false);
|
||||
obs.addObserver(this, "ipc:content-shutdown", false);
|
||||
this._processCrashObserversRegistered = true;
|
||||
},
|
||||
|
||||
_removeProcessCrashObservers: function() {
|
||||
if (!this._processCrashObserversRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
var obs = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
|
||||
obs.removeObserver(this, "plugin-crashed");
|
||||
obs.removeObserver(this, "ipc:content-shutdown");
|
||||
this._processCrashObserversRegistered = false;
|
||||
},
|
||||
|
||||
_getCrashDumpDir: function() {
|
||||
if (!this._crashDumpDir) {
|
||||
var directoryService = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Components.interfaces.nsIProperties);
|
||||
this._crashDumpDir = directoryService.get("ProfD", Components.interfaces.nsIFile);
|
||||
this._crashDumpDir.append("minidumps");
|
||||
}
|
||||
return this._crashDumpDir;
|
||||
},
|
||||
|
||||
_deleteCrashDumpFiles: function(aFilenames) {
|
||||
var crashDumpDir = this._getCrashDumpDir();
|
||||
if (!crashDumpDir.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var success = aFilenames.length != 0;
|
||||
aFilenames.forEach(function(crashFilename) {
|
||||
var file = crashDumpDir.clone();
|
||||
file.append(crashFilename);
|
||||
if (file.exists()) {
|
||||
file.remove(false);
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
});
|
||||
return success;
|
||||
},
|
||||
|
||||
_findCrashDumpFiles: function(aToIgnore) {
|
||||
var crashDumpDir = this._getCrashDumpDir();
|
||||
var entries = crashDumpDir.exists() && crashDumpDir.directoryEntries;
|
||||
if (!entries) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var crashDumpFiles = [];
|
||||
while (entries.hasMoreElements()) {
|
||||
var file = entries.getNext().QueryInterface(Components.interfaces.nsIFile);
|
||||
var path = String(file.path);
|
||||
if (path.match(/\.(dmp|extra)$/) && !aToIgnore[path]) {
|
||||
crashDumpFiles.push(path);
|
||||
}
|
||||
}
|
||||
return crashDumpFiles.concat();
|
||||
},
|
||||
|
||||
/**
|
||||
* messageManager callback function
|
||||
* This will get requests from our API in the window and process them in chrome for it
|
||||
**/
|
||||
_receiveMessageAPI: function(aMessage) {
|
||||
switch(aMessage.name) {
|
||||
case "SPPrefService":
|
||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
|
||||
getService(Components.interfaces.nsIPrefBranch2);
|
||||
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 if (aMessage.json.op == "clear") {
|
||||
if (!prefName)
|
||||
throw new SpecialPowersException("Invalid parameters for clear 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]));
|
||||
case "":
|
||||
if (aMessage.json.op == "clear") {
|
||||
prefs.clearUserPref(prefName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "SPProcessCrashService":
|
||||
switch (aMessage.json.op) {
|
||||
case "register-observer":
|
||||
this._addProcessCrashObservers();
|
||||
break;
|
||||
case "unregister-observer":
|
||||
this._removeProcessCrashObservers();
|
||||
break;
|
||||
case "delete-crash-dump-files":
|
||||
return this._deleteCrashDumpFiles(aMessage.json.filenames);
|
||||
case "find-crash-dump-files":
|
||||
return this._findCrashDumpFiles(aMessage.json.crashDumpFilesToIgnore);
|
||||
default:
|
||||
throw new SpecialPowersException("Invalid operation for SPProcessCrashService");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new SpecialPowersException("Unrecognized Special Powers API");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -311,8 +311,6 @@ TestRunner.runNextTest = function() {
|
||||
indicator.style.backgroundColor = "red";
|
||||
}
|
||||
|
||||
SpecialPowers.unregisterProcessCrashObservers();
|
||||
|
||||
TestRunner.log("TEST-START | Shutdown"); // used by automation.py
|
||||
TestRunner.log("Passed: " + $("pass-count").innerHTML);
|
||||
TestRunner.log("Failed: " + $("fail-count").innerHTML);
|
||||
@ -385,7 +383,7 @@ TestRunner.testFinished = function(tests) {
|
||||
|
||||
SpecialPowers.executeAfterFlushingMessageQueue(function() {
|
||||
cleanUpCrashDumpFiles();
|
||||
SpecialPowers.flushPrefEnv(runNextTest);
|
||||
runNextTest();
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1,559 +0,0 @@
|
||||
/* ***** 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
|
||||
* Joel Maher joel.maher@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
|
||||
*/
|
||||
|
||||
var Ci = Components.interfaces;
|
||||
var Cc = Components.classes;
|
||||
|
||||
function SpecialPowersAPI() {
|
||||
this._consoleListeners = [];
|
||||
this._encounteredCrashDumpFiles = [];
|
||||
this._unexpectedCrashDumpFiles = { };
|
||||
this._crashDumpDir = null;
|
||||
this._mfl = null;
|
||||
this._prefEnvUndoStack = [];
|
||||
this._pendingPrefs = [];
|
||||
this._applyingPrefs = false;
|
||||
}
|
||||
|
||||
function bindDOMWindowUtils(aWindow) {
|
||||
if (!aWindow)
|
||||
return
|
||||
|
||||
var util = aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
// This bit of magic brought to you by the letters
|
||||
// B Z, and E, S and the number 5.
|
||||
//
|
||||
// Take all of the properties on the nsIDOMWindowUtils-implementing
|
||||
// object, and rebind them onto a new object with a stub that uses
|
||||
// apply to call them from this privileged scope. This way we don't
|
||||
// have to explicitly stub out new methods that appear on
|
||||
// nsIDOMWindowUtils.
|
||||
var proto = Object.getPrototypeOf(util);
|
||||
var target = {};
|
||||
function rebind(desc, prop) {
|
||||
if (prop in desc && typeof(desc[prop]) == "function") {
|
||||
var oldval = desc[prop];
|
||||
try {
|
||||
desc[prop] = function() { return oldval.apply(util, arguments); };
|
||||
} catch (ex) {
|
||||
dump("WARNING: Special Powers failed to rebind function: " + desc + "::" + prop + "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var i in proto) {
|
||||
var desc = Object.getOwnPropertyDescriptor(proto, i);
|
||||
rebind(desc, "get");
|
||||
rebind(desc, "set");
|
||||
rebind(desc, "value");
|
||||
Object.defineProperty(target, i, desc);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
function Observer(specialPowers, aTopic, aCallback, aIsPref) {
|
||||
this._sp = specialPowers;
|
||||
this._topic = aTopic;
|
||||
this._callback = aCallback;
|
||||
this._isPref = aIsPref;
|
||||
}
|
||||
|
||||
Observer.prototype = {
|
||||
_sp: null,
|
||||
_topic: null,
|
||||
_callback: null,
|
||||
_isPref: false,
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if ((!this._isPref && aTopic == this._topic) ||
|
||||
(this._isPref && aTopic == "nsPref:changed")) {
|
||||
if (aData == this._topic) {
|
||||
this.cleanup();
|
||||
/* The callback must execute asynchronously after all the preference observers have run */
|
||||
content.window.setTimeout(this._callback, 0);
|
||||
content.window.setTimeout(this._sp._finishPrefEnv, 0);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
cleanup: function() {
|
||||
if (this._isPref) {
|
||||
var os = Cc["@mozilla.org/preferences-service;1"].getService()
|
||||
.QueryInterface(Ci.nsIPrefBranch2);
|
||||
os.removeObserver(this._topic, this);
|
||||
} else {
|
||||
var os = Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(Ci.nsIObserverService)
|
||||
.QueryInterface(Ci.nsIObserverService);
|
||||
os.removeObserver(this, this._topic);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
SpecialPowersAPI.prototype = {
|
||||
|
||||
getDOMWindowUtils: function(aWindow) {
|
||||
if (aWindow == this.window && this.DOMWindowUtils != null)
|
||||
return this.DOMWindowUtils;
|
||||
|
||||
return bindDOMWindowUtils(aWindow);
|
||||
},
|
||||
|
||||
removeExpectedCrashDumpFiles: function(aExpectingProcessCrash) {
|
||||
var success = true;
|
||||
if (aExpectingProcessCrash) {
|
||||
var message = {
|
||||
op: "delete-crash-dump-files",
|
||||
filenames: this._encounteredCrashDumpFiles
|
||||
};
|
||||
if (!this._sendSyncMessage("SPProcessCrashService", message)[0]) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
this._encounteredCrashDumpFiles.length = 0;
|
||||
return success;
|
||||
},
|
||||
|
||||
findUnexpectedCrashDumpFiles: function() {
|
||||
var self = this;
|
||||
var message = {
|
||||
op: "find-crash-dump-files",
|
||||
crashDumpFilesToIgnore: this._unexpectedCrashDumpFiles
|
||||
};
|
||||
var crashDumpFiles = this._sendSyncMessage("SPProcessCrashService", message)[0];
|
||||
crashDumpFiles.forEach(function(aFilename) {
|
||||
self._unexpectedCrashDumpFiles[aFilename] = true;
|
||||
});
|
||||
return crashDumpFiles;
|
||||
},
|
||||
|
||||
/*
|
||||
* Take in a list of prefs and put the original value on the _prefEnvUndoStack so we can undo
|
||||
* preferences that we set. Note, that this is a stack of values to revert to, not
|
||||
* what we have set.
|
||||
*
|
||||
* prefs: {set|clear: [[pref, value], [pref, value, Iid], ...], set|clear: [[pref, value], ...], ...}
|
||||
* ex: {'set': [['foo.bar', 2], ['browser.magic', '0xfeedface']], 'remove': [['bad.pref']] }
|
||||
*
|
||||
* In the scenario where our prefs specify the same pref more than once, we do not guarantee
|
||||
* the behavior.
|
||||
*
|
||||
* If a preference is not changing a value, we will ignore it.
|
||||
*
|
||||
* TODO: complex values for original cleanup?
|
||||
*
|
||||
*/
|
||||
pushPrefEnv: function(inPrefs, callback) {
|
||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
|
||||
getService(Components.interfaces.nsIPrefBranch);
|
||||
|
||||
var pref_string = [];
|
||||
pref_string[prefs.PREF_INT] = "INT";
|
||||
pref_string[prefs.PREF_BOOL] = "BOOL";
|
||||
pref_string[prefs.PREF_STRING] = "STRING";
|
||||
|
||||
var pendingActions = [];
|
||||
var cleanupActions = [];
|
||||
|
||||
for (var action in inPrefs) { /* set|clear */
|
||||
for (var idx in inPrefs[action]) {
|
||||
var aPref = inPrefs[action][idx];
|
||||
var prefName = aPref[0];
|
||||
var prefValue = null;
|
||||
var prefIid = null;
|
||||
var prefType = prefs.PREF_INVALID;
|
||||
var originalValue = null;
|
||||
|
||||
if (aPref.length == 3) {
|
||||
prefValue = aPref[1];
|
||||
prefIid = aPref[2];
|
||||
} else if (aPref.length == 2) {
|
||||
prefValue = aPref[1];
|
||||
}
|
||||
|
||||
/* If pref is not found or invalid it doesn't exist. */
|
||||
if (prefs.getPrefType(prefName) != prefs.PREF_INVALID) {
|
||||
prefType = pref_string[prefs.getPrefType(prefName)];
|
||||
if ((prefs.prefHasUserValue(prefName) && action == 'clear') ||
|
||||
(action == 'set'))
|
||||
originalValue = this._getPref(prefName, prefType);
|
||||
} else if (action == 'set') {
|
||||
/* prefName doesn't exist, so 'clear' is pointless */
|
||||
if (aPref.length == 3) {
|
||||
prefType = "COMPLEX";
|
||||
} else if (aPref.length == 2) {
|
||||
if (typeof(prefValue) == "boolean")
|
||||
prefType = "BOOL";
|
||||
else if (typeof(prefValue) == "number")
|
||||
prefType = "INT";
|
||||
else if (typeof(prefValue) == "string")
|
||||
prefType = "CHAR";
|
||||
}
|
||||
}
|
||||
|
||||
/* PREF_INVALID: A non existing pref which we are clearing or invalid values for a set */
|
||||
if (prefType == prefs.PREF_INVALID)
|
||||
continue;
|
||||
|
||||
/* We are not going to set a pref if the value is the same */
|
||||
if (originalValue == prefValue)
|
||||
continue;
|
||||
|
||||
pendingActions.push({'action': action, 'type': prefType, 'name': prefName, 'value': prefValue, 'Iid': prefIid});
|
||||
|
||||
/* Push original preference value or clear into cleanup array */
|
||||
var cleanupTodo = {'action': action, 'type': prefType, 'name': prefName, 'value': originalValue, 'Iid': prefIid};
|
||||
if (originalValue == null) {
|
||||
cleanupTodo.action = 'clear';
|
||||
} else {
|
||||
cleanupTodo.action = 'set';
|
||||
}
|
||||
cleanupActions.push(cleanupTodo);
|
||||
}
|
||||
}
|
||||
|
||||
if (pendingActions.length > 0) {
|
||||
this._prefEnvUndoStack.push(cleanupActions);
|
||||
this._pendingPrefs.push([pendingActions, callback]);
|
||||
this._applyPrefs();
|
||||
} else {
|
||||
content.window.setTimeout(callback, 0);
|
||||
}
|
||||
},
|
||||
|
||||
popPrefEnv: function(callback) {
|
||||
if (this._prefEnvUndoStack.length > 0) {
|
||||
/* Each pop will have a valid block of preferences */
|
||||
this._pendingPrefs.push([this._prefEnvUndoStack.pop(), callback]);
|
||||
this._applyPrefs();
|
||||
} else {
|
||||
content.window.setTimeout(callback, 0);
|
||||
}
|
||||
},
|
||||
|
||||
flushPrefEnv: function(callback) {
|
||||
while (this._prefEnvUndoStack.length > 1)
|
||||
this.popPrefEnv(null);
|
||||
|
||||
this.popPrefEnv(callback);
|
||||
},
|
||||
|
||||
/*
|
||||
Iterate through one atomic set of pref actions and perform sets/clears as appropriate.
|
||||
All actions performed must modify the relevant pref.
|
||||
*/
|
||||
_applyPrefs: function() {
|
||||
if (this._applyingPrefs || this._pendingPrefs.length <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set lock and get prefs from the _pendingPrefs queue */
|
||||
this._applyingPrefs = true;
|
||||
var transaction = this._pendingPrefs.shift();
|
||||
var pendingActions = transaction[0];
|
||||
var callback = transaction[1];
|
||||
|
||||
var lastPref = pendingActions[pendingActions.length-1];
|
||||
this._addObserver(lastPref.name, callback, true);
|
||||
|
||||
for (var idx in pendingActions) {
|
||||
var pref = pendingActions[idx];
|
||||
if (pref.action == 'set') {
|
||||
this._setPref(pref.name, pref.type, pref.value, pref.Iid);
|
||||
} else if (pref.action == 'clear') {
|
||||
this.clearUserPref(pref.name);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_addObserver: function(aTopic, aCallback, aIsPref) {
|
||||
var observer = new Observer(this, aTopic, aCallback, aIsPref);
|
||||
|
||||
if (aIsPref) {
|
||||
var os = Cc["@mozilla.org/preferences-service;1"].getService()
|
||||
.QueryInterface(Ci.nsIPrefBranch2);
|
||||
os.addObserver(aTopic, observer, false);
|
||||
} else {
|
||||
var os = Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(Ci.nsIObserverService)
|
||||
.QueryInterface(Ci.nsIObserverService);
|
||||
os.addObserver(observer, aTopic, false);
|
||||
}
|
||||
},
|
||||
|
||||
/* called from the observer when we get a pref:changed. */
|
||||
_finishPrefEnv: function() {
|
||||
/*
|
||||
Any subsequent pref environment pushes that occurred while waiting
|
||||
for the preference update are pending, and will now be executed.
|
||||
*/
|
||||
this.wrappedJSObject.SpecialPowers._applyingPrefs = false;
|
||||
this.wrappedJSObject.SpecialPowers._applyPrefs();
|
||||
},
|
||||
|
||||
// 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));
|
||||
},
|
||||
|
||||
// Mimic the clearUserPref API
|
||||
clearUserPref: function(aPrefName) {
|
||||
var msg = {'op':'clear', 'prefName': aPrefName, 'prefType': ""};
|
||||
this._sendSyncMessage('SPPrefService', msg);
|
||||
},
|
||||
|
||||
// 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};
|
||||
}
|
||||
var val = this._sendSyncMessage('SPPrefService', msg);
|
||||
|
||||
if (val == null || val[0] == null)
|
||||
throw "Error getting pref";
|
||||
return val[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(this._sendSyncMessage('SPPrefService', msg)[0]);
|
||||
},
|
||||
|
||||
//XXX: these APIs really ought to be removed, they're not e10s-safe.
|
||||
// (also they're pretty Firefox-specific)
|
||||
_getTopChromeWindow: function(window) {
|
||||
return window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow)
|
||||
.QueryInterface(Ci.nsIDOMChromeWindow);
|
||||
},
|
||||
_getDocShell: function(window) {
|
||||
return window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
},
|
||||
_getMUDV: function(window) {
|
||||
return this._getDocShell(window).contentViewer
|
||||
.QueryInterface(Ci.nsIMarkupDocumentViewer);
|
||||
},
|
||||
_getAutoCompletePopup: function(window) {
|
||||
return this._getTopChromeWindow(window).document
|
||||
.getElementById("PopupAutoComplete");
|
||||
},
|
||||
addAutoCompletePopupEventListener: function(window, listener) {
|
||||
this._getAutoCompletePopup(window).addEventListener("popupshowing",
|
||||
listener,
|
||||
false);
|
||||
},
|
||||
removeAutoCompletePopupEventListener: function(window, listener) {
|
||||
this._getAutoCompletePopup(window).removeEventListener("popupshowing",
|
||||
listener,
|
||||
false);
|
||||
},
|
||||
isBackButtonEnabled: function(window) {
|
||||
return !this._getTopChromeWindow(window).document
|
||||
.getElementById("Browser:Back")
|
||||
.hasAttribute("disabled");
|
||||
},
|
||||
|
||||
addChromeEventListener: function(type, listener, capture, allowUntrusted) {
|
||||
addEventListener(type, listener, capture, allowUntrusted);
|
||||
},
|
||||
removeChromeEventListener: function(type, listener, capture) {
|
||||
removeEventListener(type, listener, capture);
|
||||
},
|
||||
|
||||
addErrorConsoleListener: function(listener) {
|
||||
var consoleListener = {
|
||||
userListener: listener,
|
||||
observe: function(consoleMessage) {
|
||||
this.userListener(consoleMessage.message);
|
||||
}
|
||||
};
|
||||
|
||||
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
|
||||
.registerListener(consoleListener);
|
||||
|
||||
this._consoleListeners.push(consoleListener);
|
||||
},
|
||||
|
||||
removeErrorConsoleListener: function(listener) {
|
||||
for (var index in this._consoleListeners) {
|
||||
var consoleListener = this._consoleListeners[index];
|
||||
if (consoleListener.userListener == listener) {
|
||||
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
|
||||
.unregisterListener(consoleListener);
|
||||
this._consoleListeners = this._consoleListeners.splice(index, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getFullZoom: function(window) {
|
||||
return this._getMUDV(window).fullZoom;
|
||||
},
|
||||
setFullZoom: function(window, zoom) {
|
||||
this._getMUDV(window).fullZoom = zoom;
|
||||
},
|
||||
getTextZoom: function(window) {
|
||||
return this._getMUDV(window).textZoom;
|
||||
},
|
||||
setTextZoom: function(window, zoom) {
|
||||
this._getMUDV(window).textZoom = zoom;
|
||||
},
|
||||
|
||||
createSystemXHR: function() {
|
||||
return Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
},
|
||||
|
||||
snapshotWindow: function (win, withCaret) {
|
||||
var el = this.window.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
el.width = win.innerWidth;
|
||||
el.height = win.innerHeight;
|
||||
var ctx = el.getContext("2d");
|
||||
var flags = 0;
|
||||
|
||||
ctx.drawWindow(win, win.scrollX, win.scrollY,
|
||||
win.innerWidth, win.innerHeight,
|
||||
"rgb(255,255,255)",
|
||||
withCaret ? ctx.DRAWWINDOW_DRAW_CARET : 0);
|
||||
return el;
|
||||
},
|
||||
|
||||
gc: function() {
|
||||
this.DOMWindowUtils.garbageCollect();
|
||||
},
|
||||
|
||||
forceGC: function() {
|
||||
Components.utils.forceGC();
|
||||
},
|
||||
|
||||
hasContentProcesses: function() {
|
||||
try {
|
||||
var rt = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
|
||||
return rt.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
|
||||
} catch (e) {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
_xpcomabi: null,
|
||||
|
||||
get XPCOMABI() {
|
||||
if (this._xpcomabi != null)
|
||||
return this._xpcomabi;
|
||||
|
||||
var xulRuntime = Cc["@mozilla.org/xre/app-info;1"]
|
||||
.getService(Components.interfaces.nsIXULAppInfo)
|
||||
.QueryInterface(Components.interfaces.nsIXULRuntime);
|
||||
|
||||
this._xpcomabi = xulRuntime.XPCOMABI;
|
||||
return this._xpcomabi;
|
||||
},
|
||||
|
||||
executeSoon: function(aFunc) {
|
||||
var tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
|
||||
tm.mainThread.dispatch({
|
||||
run: function() {
|
||||
aFunc();
|
||||
}
|
||||
}, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
},
|
||||
|
||||
addSystemEventListener: function(target, type, listener, useCapture) {
|
||||
Cc["@mozilla.org/eventlistenerservice;1"].
|
||||
getService(Ci.nsIEventListenerService).
|
||||
addSystemEventListener(target, type, listener, useCapture);
|
||||
},
|
||||
removeSystemEventListener: function(target, type, listener, useCapture) {
|
||||
Cc["@mozilla.org/eventlistenerservice;1"].
|
||||
getService(Ci.nsIEventListenerService).
|
||||
removeSystemEventListener(target, type, listener, useCapture);
|
||||
},
|
||||
|
||||
setLogFile: function(path) {
|
||||
this._mfl = new MozillaFileLogger(path);
|
||||
},
|
||||
|
||||
log: function(data) {
|
||||
this._mfl.log(data);
|
||||
},
|
||||
|
||||
closeLogFile: function() {
|
||||
this._mfl.close();
|
||||
},
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user