Merge m-c to inbound.

This commit is contained in:
Ryan VanderMeulen 2012-09-23 15:26:30 -04:00
commit 819db48846
28 changed files with 737 additions and 337 deletions

View File

@ -202,8 +202,16 @@ DebuggerUI.prototype = {
label: L10N.getStr("confirmTabSwitch.buttonOpen"),
accessKey: L10N.getStr("confirmTabSwitch.buttonOpen.accessKey"),
callback: function DUI_notificationButtonOpen() {
this.findDebugger().close();
this.toggleDebugger();
let scriptDebugger = this.findDebugger();
let targetWindow = scriptDebugger.globalUI.chromeWindow;
scriptDebugger.close();
let self = this;
targetWindow.addEventListener("Debugger:Shutdown", function toggle() {
targetWindow.removeEventListener("Debugger:Shutdown", toggle, false);
Services.tm.currentThread.dispatch({ run: function() {
self.toggleDebugger();
}}, 0);
}, false);
}.bind(this)
}];

View File

@ -61,31 +61,45 @@ p + p { left: 22px }
</style>
<!-- link directives -->
<link rel="stylesheet" href="ccd.sjs?IA1lq">
<link rel="stylesheet" href="ccd.sjs?IA2lq">
<link rel="stylesheet" href="ccd.sjs?IA3lq">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/ccd.sjs?IB1lq">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/ccd.sjs?IB2lq">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/ccd.sjs?IB3lq">
<link rel="stylesheet" href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?IC1lq">
<link rel="stylesheet" href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?IC2lq">
<link rel="stylesheet" href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?IC3lq">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/redirect.sjs?ccd.sjs?ID1lq">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/redirect.sjs?ccd.sjs?ID2lq">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/redirect.sjs?ccd.sjs?ID3lq">
<link rel="stylesheet" href="ccd.sjs?JA1lq">
<link rel="stylesheet" href="ccd.sjs?JA2lq">
<link rel="stylesheet" href="ccd.sjs?JA3lq">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/ccd.sjs?JB1lq">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/ccd.sjs?JB2lq">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/ccd.sjs?JB3lq">
<link rel="stylesheet" href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?JC1lq">
<link rel="stylesheet" href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?JC2lq">
<link rel="stylesheet" href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?JC3lq">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/redirect.sjs?http://mochi.test:8888/tests/layout/style/test/ccd.sjs?JD1lq">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/redirect.sjs?http://mochi.test:8888/tests/layout/style/test/ccd.sjs?JD2lq">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/redirect.sjs?http://mochi.test:8888/tests/layout/style/test/ccd.sjs?JD3lq">
<link rel="stylesheet" data-href="ccd.sjs?IA1lq">
<link rel="stylesheet" data-href="ccd.sjs?IA2lq">
<link rel="stylesheet" data-href="ccd.sjs?IA3lq">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/ccd.sjs?IB1lq">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/ccd.sjs?IB2lq">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/ccd.sjs?IB3lq">
<link rel="stylesheet" data-href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?IC1lq">
<link rel="stylesheet" data-href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?IC2lq">
<link rel="stylesheet" data-href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?IC3lq">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/redirect.sjs?ccd.sjs?ID1lq">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/redirect.sjs?ccd.sjs?ID2lq">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/redirect.sjs?ccd.sjs?ID3lq">
<link rel="stylesheet" data-href="ccd.sjs?JA1lq">
<link rel="stylesheet" data-href="ccd.sjs?JA2lq">
<link rel="stylesheet" data-href="ccd.sjs?JA3lq">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/ccd.sjs?JB1lq">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/ccd.sjs?JB2lq">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/ccd.sjs?JB3lq">
<link rel="stylesheet" data-href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?JC1lq">
<link rel="stylesheet" data-href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?JC2lq">
<link rel="stylesheet" data-href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?JC3lq">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/redirect.sjs?http://mochi.test:8888/tests/layout/style/test/ccd.sjs?JD1lq">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/redirect.sjs?http://mochi.test:8888/tests/layout/style/test/ccd.sjs?JD2lq">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/redirect.sjs?http://mochi.test:8888/tests/layout/style/test/ccd.sjs?JD3lq">
<script>
// attach onload and onerror handlers to every link tag, then activate
// them. see audit logic in test_css_cross_domain.html
function setCompleted() {
this.dataset.completed = true;
}
var links = document.getElementsByTagName("link");
for (var i = 0; i < links.length; i++) {
links[i].dataset.completed = false;
links[i].addEventListener("load", setCompleted);
links[i].addEventListener("error", setCompleted);
links[i].href = links[i].dataset.href;
}
</script>
</head><body>
<div></div>
<div></div>
@ -121,4 +135,5 @@ p + p { left: 22px }
<div><p id="JD1i"></p><p id="JD1l"></p></div>
<div><p id="JD2i"></p><p id="JD2l"></p></div>
<div><p id="JD3i"></p><p id="JD3l"></p></div>
</body></html>

View File

@ -60,31 +60,45 @@ p + p { left: 22px }
</style>
<!-- link directives -->
<link rel="stylesheet" href="ccd.sjs?IA1ls">
<link rel="stylesheet" href="ccd.sjs?IA2ls">
<link rel="stylesheet" href="ccd.sjs?IA3ls">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/ccd.sjs?IB1ls">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/ccd.sjs?IB2ls">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/ccd.sjs?IB3ls">
<link rel="stylesheet" href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?IC1ls">
<link rel="stylesheet" href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?IC2ls">
<link rel="stylesheet" href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?IC3ls">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/redirect.sjs?ccd.sjs?ID1ls">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/redirect.sjs?ccd.sjs?ID2ls">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/redirect.sjs?ccd.sjs?ID3ls">
<link rel="stylesheet" href="ccd.sjs?JA1ls">
<link rel="stylesheet" href="ccd.sjs?JA2ls">
<link rel="stylesheet" href="ccd.sjs?JA3ls">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/ccd.sjs?JB1ls">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/ccd.sjs?JB2ls">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/ccd.sjs?JB3ls">
<link rel="stylesheet" href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?JC1ls">
<link rel="stylesheet" href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?JC2ls">
<link rel="stylesheet" href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?JC3ls">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/redirect.sjs?http://mochi.test:8888/tests/layout/style/test/ccd.sjs?JD1ls">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/redirect.sjs?http://mochi.test:8888/tests/layout/style/test/ccd.sjs?JD2ls">
<link rel="stylesheet" href="http://example.org/tests/layout/style/test/redirect.sjs?http://mochi.test:8888/tests/layout/style/test/ccd.sjs?JD3ls">
<link rel="stylesheet" data-href="ccd.sjs?IA1ls">
<link rel="stylesheet" data-href="ccd.sjs?IA2ls">
<link rel="stylesheet" data-href="ccd.sjs?IA3ls">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/ccd.sjs?IB1ls">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/ccd.sjs?IB2ls">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/ccd.sjs?IB3ls">
<link rel="stylesheet" data-href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?IC1ls">
<link rel="stylesheet" data-href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?IC2ls">
<link rel="stylesheet" data-href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?IC3ls">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/redirect.sjs?ccd.sjs?ID1ls">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/redirect.sjs?ccd.sjs?ID2ls">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/redirect.sjs?ccd.sjs?ID3ls">
<link rel="stylesheet" data-href="ccd.sjs?JA1ls">
<link rel="stylesheet" data-href="ccd.sjs?JA2ls">
<link rel="stylesheet" data-href="ccd.sjs?JA3ls">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/ccd.sjs?JB1ls">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/ccd.sjs?JB2ls">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/ccd.sjs?JB3ls">
<link rel="stylesheet" data-href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?JC1ls">
<link rel="stylesheet" data-href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?JC2ls">
<link rel="stylesheet" data-href="redirect.sjs?http://example.org/tests/layout/style/test/ccd.sjs?JC3ls">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/redirect.sjs?http://mochi.test:8888/tests/layout/style/test/ccd.sjs?JD1ls">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/redirect.sjs?http://mochi.test:8888/tests/layout/style/test/ccd.sjs?JD2ls">
<link rel="stylesheet" data-href="http://example.org/tests/layout/style/test/redirect.sjs?http://mochi.test:8888/tests/layout/style/test/ccd.sjs?JD3ls">
<script>
// attach onload and onerror handlers to every link tag, then activate
// them. see audit logic in test_css_cross_domain.html
function setCompleted() {
this.dataset.completed = true;
}
var links = document.getElementsByTagName("link");
for (var i = 0; i < links.length; i++) {
links[i].dataset.completed = false;
links[i].addEventListener("load", setCompleted);
links[i].addEventListener("error", setCompleted);
links[i].href = links[i].dataset.href;
}
</script>
</head><body>
<div></div>
<div></div>

View File

@ -79,8 +79,18 @@
/** Test for Bug 524223 **/
function check_iframe(ifr) {
var doc = ifr.contentDocument;
var i;
// Check that all links have in fact either loaded or errored.
// Doesn't seem to be possible to do this for @import, but this is
// just a diagnostic, anyway. See corresponding code in ccd-*.html.
var links = doc.getElementsByTagName("link");
for (i = 0; i < links.length; i++) {
ok(links[i].dataset.completed, ifr.id + " " + links[i].href + " loaded");
}
var cases = doc.getElementsByTagName("p");
for (var i = 0; i < cases.length; i++) {
for (i = 0; i < cases.length; i++) {
var color = doc.defaultView.getComputedStyle(cases[i], "")
.getPropertyValue("background-color");
@ -88,10 +98,22 @@ function check_iframe(ifr) {
}
}
var quirks = document.getElementById("quirks");
var standards = document.getElementById("standards");
var quirks_loaded = false;
var standards_loaded = false;
SimpleTest.waitForExplicitFinish();
quirks.onload = function() { quirks_loaded = true; }
standards.onload = function() { standards_loaded = true; }
window.onload = function() {
check_iframe(document.getElementById("quirks"));
check_iframe(document.getElementById("standards"));
ok(quirks_loaded, "quirks frame loaded");
ok(standards_loaded, "standards frame loaded");
check_iframe(quirks);
check_iframe(standards);
SimpleTest.finish();
};
</script>

View File

@ -4,10 +4,20 @@
let EXPORTED_SYMBOLS = ["LightweightThemeConsumer"];
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeImageOptimizer",
"resource://gre/modules/LightweightThemeImageOptimizer.jsm");
function LightweightThemeConsumer(aDocument) {
this._doc = aDocument;
this._win = aDocument.defaultView;
this._footerId = aDocument.documentElement.getAttribute("lightweightthemesfooter");
let screen = this._win.screen;
this._lastScreenWidth = screen.width;
this._lastScreenHeight = screen.height;
Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService)
.addObserver(this, "lightweight-theme-styling-update", false);
@ -15,9 +25,14 @@ function LightweightThemeConsumer(aDocument) {
var temp = {};
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", temp);
this._update(temp.LightweightThemeManager.currentThemeForDisplay);
this._win.addEventListener("resize", this);
}
LightweightThemeConsumer.prototype = {
_lastData: null,
_lastScreenWidth: null,
_lastScreenHeight: null,
observe: function (aSubject, aTopic, aData) {
if (aTopic != "lightweight-theme-styling-update")
return;
@ -25,18 +40,32 @@ LightweightThemeConsumer.prototype = {
this._update(JSON.parse(aData));
},
handleEvent: function (aEvent) {
let {width, height} = this._win.screen;
if (this._lastScreenWidth != width || this._lastScreenHeight != height) {
this._lastScreenWidth = width;
this._lastScreenHeight = height;
this._update(this._lastData);
}
},
destroy: function () {
Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService)
.removeObserver(this, "lightweight-theme-styling-update");
this._doc = null;
this._win.removeEventListener("resize", this);
this._win = this._doc = null;
},
_update: function (aData) {
if (!aData)
aData = { headerURL: "", footerURL: "", textcolor: "", accentcolor: "" };
this._lastData = aData;
aData = LightweightThemeImageOptimizer.optimize(aData, this._win.screen);
var root = this._doc.documentElement;
var active = !!aData.headerURL;

View File

@ -375,8 +375,10 @@ DebuggerClient.prototype = {
try {
if (!aPacket.from) {
Cu.reportError("Server did not specify an actor, dropping packet: " +
JSON.stringify(aPacket));
let msg = "Server did not specify an actor, dropping packet: " +
JSON.stringify(aPacket);
Cu.reportError(msg);
dumpn(msg);
return;
}

View File

@ -164,9 +164,8 @@ DebuggerTransport.prototype = {
try {
dumpn("Got: " + packet);
let thr = Cc["@mozilla.org/thread-manager;1"].getService().currentThread;
let self = this;
thr.dispatch({run: function() {
Services.tm.currentThread.dispatch({run: function() {
self.hooks.onPacket(parsed);
}}, 0);
} catch(e) {
@ -177,3 +176,82 @@ DebuggerTransport.prototype = {
return true;
}
}
/**
* An adapter that handles data transfers between the debugger client and
* server when they both run in the same process. It presents the same API as
* DebuggerTransport, but instead of transmitting serialized messages across a
* connection it merely calls the packet dispatcher of the other side.
*
* @param aOther LocalDebuggerTransport
* The other endpoint for this debugger connection.
*
* @see DebuggerTransport
*/
function LocalDebuggerTransport(aOther)
{
this.other = aOther;
this.hooks = null;
}
LocalDebuggerTransport.prototype = {
/**
* Transmit a message by directly calling the onPacket handler of the other
* endpoint.
*/
send: function LDT_send(aPacket) {
try {
// Avoid the cost of uneval() when logging is disabled.
if (wantLogging) {
dumpn("Got: " + uneval(aPacket));
}
this._deepFreeze(aPacket);
let self = this;
Services.tm.currentThread.dispatch({run: function() {
self.other.hooks.onPacket(aPacket);
}}, 0);
} catch(e) {
dumpn("Error handling incoming packet: " + e + " - " + e.stack);
dumpn("Packet was: " + aPacket);
}
},
/**
* Close the transport.
*/
close: function LDT_close() {
if (this.other) {
// Remove the reference to the other endpoint before calling close(), to
// avoid infinite recursion.
let other = this.other;
delete this.other;
other.close();
}
this.hooks.onClosed();
},
/**
* An empty method for emulating the DebuggerTransport API.
*/
ready: function LDT_ready() {},
/**
* Helper function that makes an object fully immutable.
*/
_deepFreeze: function LDT_deepFreeze(aObject) {
Object.freeze(aObject);
for (let prop in aObject) {
// Freeze the properties that are objects, not on the prototype, and not
// already frozen. Note that this might leave an unfrozen reference
// somewhere in the object if there is an already frozen object containing
// an unfrozen object.
if (aObject.hasOwnProperty(prop) && typeof aObject === "object" &&
!Object.isFrozen(aObject)) {
this._deepFreeze(o[prop]);
}
}
}
}

View File

@ -72,11 +72,19 @@ var DebuggerServer = {
LONG_STRING_INITIAL_LENGTH: 1000,
/**
* Prompt the user to accept or decline the incoming connection.
* A handler function that prompts the user to accept or decline the incoming
* connection.
*/
_allowConnection: null,
/**
* Prompt the user to accept or decline the incoming connection. This is the
* default implementation that products embedding the debugger server may
* choose to override.
*
* @return true if the connection should be permitted, false otherwise
*/
_allowConnection: function DH__allowConnection() {
_defaultAllowConnection: function DH__defaultAllowConnection() {
let title = L10N.getStr("remoteIncomingPromptTitle");
let msg = L10N.getStr("remoteIncomingPromptMessage");
let disableButton = L10N.getStr("remoteIncomingPromptDisable");
@ -133,9 +141,9 @@ var DebuggerServer = {
this._connections = {};
this._nextConnID = 0;
this._transportInitialized = true;
if (aAllowConnectionCallback) {
this._allowConnection = aAllowConnectionCallback;
}
this._allowConnection = aAllowConnectionCallback ?
aAllowConnectionCallback :
this._defaultAllowConnection;
},
get initialized() { return !!this.globalActorFactories; },
@ -149,9 +157,12 @@ var DebuggerServer = {
*/
destroy: function DH_destroy() {
if (Object.keys(this._connections).length == 0) {
dumpn("Shutting down debugger server.");
this.closeListener();
delete this.globalActorFactories;
delete this.tabActorFactories;
delete this._allowConnection;
this._transportInitialized = false;
dumpn("Debugger server is shut down.");
}
},
@ -220,8 +231,6 @@ var DebuggerServer = {
* number of open connections.
*/
closeListener: function DH_closeListener(aForce) {
this._checkInit();
if (!this._listener || this._socketConnections == 0) {
return false;
}
@ -238,8 +247,9 @@ var DebuggerServer = {
},
/**
* Creates a new connection to the local debugger speaking over an
* nsIPipe.
* Creates a new connection to the local debugger speaking over a fake
* transport. This connection results in straightforward calls to the onPacket
* handlers of each side.
*
* @returns a client-side DebuggerTransport for communicating with
* the newly-created connection.
@ -247,16 +257,12 @@ var DebuggerServer = {
connectPipe: function DH_connectPipe() {
this._checkInit();
let toServer = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
toServer.init(true, true, 0, 0, null);
let toClient = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
toClient.init(true, true, 0, 0, null);
let serverTransport = new DebuggerTransport(toServer.inputStream,
toClient.outputStream);
let serverTransport = new LocalDebuggerTransport;
let clientTransport = new LocalDebuggerTransport(serverTransport);
serverTransport.other = clientTransport;
this._onConnection(serverTransport);
return new DebuggerTransport(toClient.inputStream, toServer.outputStream);
return clientTransport;
},

View File

@ -7,7 +7,7 @@ Cu.import("resource:///modules/devtools/dbg-client.jsm");
function run_test()
{
// Allow incoming connections.
DebuggerServer.init(function () { return true; });
DebuggerServer.init(function () true);
DebuggerServer.addActors("resource://test/testactors.js");
add_test(test_socket_conn);
@ -59,10 +59,35 @@ function test_socket_conn()
function test_socket_shutdown()
{
do_check_eq(DebuggerServer._socketConnections, 1);
do_check_true(DebuggerServer.closeListener());
let count = 0;
wait_for_server_shutdown(count);
}
function wait_for_server_shutdown(aCount)
{
do_timeout(100, function() {
dump("count: "+aCount+" ");
if (++aCount > 20) {
do_throw("Timed out waiting for the server to shut down.");
return;
}
if (DebuggerServer.initialized) {
wait_for_server_shutdown(aCount);
return;
}
real_test_socket_shutdown(aCount);
});
}
function real_test_socket_shutdown()
{
// After the last conection was closed, the server must be initialized again.
// Allow incoming connections.
DebuggerServer.init(function () true);
DebuggerServer.addActors("resource://test/testactors.js");
do_check_eq(DebuggerServer._socketConnections, 0);
// Make sure closing the listener twice does nothing.
// Make sure closing a non-started listener does nothing.
do_check_false(DebuggerServer.closeListener());
do_check_eq(DebuggerServer._socketConnections, 0);

View File

@ -0,0 +1,186 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let EXPORTED_SYMBOLS = ["LightweightThemeImageOptimizer"];
const Cu = Components.utils;
const Ci = Components.interfaces;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
const ORIGIN_TOP_RIGHT = 1;
const ORIGIN_BOTTOM_LEFT = 2;
let LightweightThemeImageOptimizer = {
optimize: function LWTIO_optimize(aThemeData, aScreen) {
let data = Utils.createCopy(aThemeData);
if (!data.headerURL) {
return data;
}
data.headerURL = ImageCropper.getCroppedImageURL(
data.headerURL, aScreen, ORIGIN_TOP_RIGHT);
if (data.footerURL) {
data.footerURL = ImageCropper.getCroppedImageURL(
data.footerURL, aScreen, ORIGIN_BOTTOM_LEFT);
}
return data;
},
purge: function LWTIO_purge() {
let dir = FileUtils.getDir("ProfD", ["lwtheme"]);
dir.followLinks = false;
try {
dir.remove(true);
} catch (e) {}
}
};
Object.freeze(LightweightThemeImageOptimizer);
let ImageCropper = {
_inProgress: {},
getCroppedImageURL:
function ImageCropper_getCroppedImageURL(aImageURL, aScreen, aOrigin) {
// We can crop local files, only.
if (!aImageURL.startsWith("file://")) {
return aImageURL;
}
// Generate the cropped image's file name using its
// base name and the current screen size.
let uri = Services.io.newURI(aImageURL, null, null);
let file = uri.QueryInterface(Ci.nsIFileURL).file;
// Make sure the source file exists.
if (!file.exists()) {
return aImageURL;
}
let fileName = file.leafName + "-" + aScreen.width + "x" + aScreen.height;
let croppedFile = FileUtils.getFile("ProfD", ["lwtheme", fileName]);
// If we have a local file that is not in progress, return it.
if (croppedFile.exists() && !(croppedFile.path in this._inProgress)) {
let fileURI = Services.io.newFileURI(croppedFile);
// Copy the query part to avoid wrong caching.
fileURI.QueryInterface(Ci.nsIURL).query = uri.query;
return fileURI.spec;
}
// Crop the given image in the background.
this._crop(uri, croppedFile, aScreen, aOrigin);
// Return the original image while we're waiting for the cropped version
// to be written to disk.
return aImageURL;
},
_crop: function ImageCropper_crop(aURI, aTargetFile, aScreen, aOrigin) {
let inProgress = this._inProgress;
inProgress[aTargetFile.path] = true;
function resetInProgress() {
delete inProgress[aTargetFile.path];
}
ImageFile.read(aURI, function (aInputStream, aContentType) {
if (aInputStream && aContentType) {
let image = ImageTools.decode(aInputStream, aContentType);
if (image && image.width && image.height) {
let stream = ImageTools.encode(image, aScreen, aOrigin, aContentType);
if (stream) {
ImageFile.write(aTargetFile, stream, resetInProgress);
return;
}
}
}
resetInProgress();
});
}
};
let ImageFile = {
read: function ImageFile_read(aURI, aCallback) {
this._netUtil.asyncFetch(aURI, function (aInputStream, aStatus, aRequest) {
if (Components.isSuccessCode(aStatus) && aRequest instanceof Ci.nsIChannel) {
let channel = aRequest.QueryInterface(Ci.nsIChannel);
aCallback(aInputStream, channel.contentType);
} else {
aCallback();
}
});
},
write: function ImageFile_write(aFile, aInputStream, aCallback) {
let fos = FileUtils.openSafeFileOutputStream(aFile);
this._netUtil.asyncCopy(aInputStream, fos, function (aResult) {
FileUtils.closeSafeFileOutputStream(fos);
// Remove the file if writing was not successful.
if (!Components.isSuccessCode(aResult)) {
try {
aFile.remove(false);
} catch (e) {}
}
aCallback();
});
}
};
XPCOMUtils.defineLazyModuleGetter(ImageFile, "_netUtil",
"resource://gre/modules/NetUtil.jsm", "NetUtil");
let ImageTools = {
decode: function ImageTools_decode(aInputStream, aContentType) {
let outParam = {value: null};
try {
this._imgTools.decodeImageData(aInputStream, aContentType, outParam);
} catch (e) {}
return outParam.value;
},
encode: function ImageTools_encode(aImage, aScreen, aOrigin, aContentType) {
let stream;
let width = Math.min(aImage.width, aScreen.width);
let height = Math.min(aImage.height, aScreen.height);
let x = aOrigin == ORIGIN_TOP_RIGHT ? aImage.width - width : 0;
try {
stream = this._imgTools.encodeCroppedImage(aImage, aContentType, x, 0,
width, height);
} catch (e) {}
return stream;
}
};
XPCOMUtils.defineLazyServiceGetter(ImageTools, "_imgTools",
"@mozilla.org/image/tools;1", "imgITools");
let Utils = {
createCopy: function Utils_createCopy(aData) {
let copy = {};
for (let [k, v] in Iterator(aData)) {
copy[k] = v;
}
return copy;
}
};

View File

@ -9,6 +9,7 @@ var EXPORTED_SYMBOLS = ["LightweightThemeManager"];
const Cc = Components.classes;
const Ci = Components.interfaces;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/AddonManager.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
@ -38,6 +39,9 @@ const PERSIST_FILES = {
footerURL: "lightweighttheme-footer"
};
XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeImageOptimizer",
"resource://gre/modules/LightweightThemeImageOptimizer.jsm");
__defineGetter__("_prefs", function () {
delete this._prefs;
return this._prefs = Services.prefs.getBranch("lightweightThemes.");
@ -227,8 +231,12 @@ var LightweightThemeManager = {
let usedThemes = _usedThemesExceptId(aData.id);
usedThemes.unshift(aData);
_updateUsedThemes(usedThemes);
if (PERSIST_ENABLED)
_persistImages(aData);
if (PERSIST_ENABLED) {
LightweightThemeImageOptimizer.purge();
_persistImages(aData, function () {
_notifyWindows(this.currentThemeForDisplay);
}.bind(this));
}
}
_prefs.setBoolPref("isThemeSelected", aData != null);
@ -716,17 +724,24 @@ function _prefObserver(aSubject, aTopic, aData) {
}
}
function _persistImages(aData) {
function _persistImages(aData, aCallback) {
function onSuccess(key) function () {
let current = LightweightThemeManager.currentTheme;
if (current && current.id == aData.id)
if (current && current.id == aData.id) {
_prefs.setBoolPref("persisted." + key, true);
}
if (--numFilesToPersist == 0 && aCallback) {
aCallback();
}
};
let numFilesToPersist = 0;
for (let key in PERSIST_FILES) {
_prefs.setBoolPref("persisted." + key, false);
if (aData[key])
if (aData[key]) {
numFilesToPersist++;
_persistImage(aData[key], PERSIST_FILES[key], onSuccess(key));
}
}
}

View File

@ -55,6 +55,7 @@ EXTRA_JS_MODULES = \
AddonRepository.jsm \
AddonUpdateChecker.jsm \
ChromeManifestParser.jsm \
LightweightThemeImageOptimizer.jsm \
LightweightThemeManager.jsm \
PluginProvider.jsm \
SpellCheckDictionaryBootstrap.js \

View File

@ -280,23 +280,31 @@ var gEventManager = {
initialize: function gEM_initialize() {
var self = this;
["onEnabling", "onEnabled", "onDisabling", "onDisabled", "onUninstalling",
"onUninstalled", "onInstalled", "onOperationCancelled",
"onUpdateAvailable", "onUpdateFinished", "onCompatibilityUpdateAvailable",
"onPropertyChanged"].forEach(function(aEvent) {
self[aEvent] = function initialize_delegateAddonEvent(...aArgs) {
self.delegateAddonEvent(aEvent, aArgs);
const ADDON_EVENTS = ["onEnabling", "onEnabled", "onDisabling",
"onDisabled", "onUninstalling", "onUninstalled",
"onInstalled", "onOperationCancelled",
"onUpdateAvailable", "onUpdateFinished",
"onCompatibilityUpdateAvailable",
"onPropertyChanged"];
for (let evt of ADDON_EVENTS) {
let event = evt;
self[event] = function initialize_delegateAddonEvent(...aArgs) {
self.delegateAddonEvent(event, aArgs);
};
});
}
["onNewInstall", "onDownloadStarted", "onDownloadEnded", "onDownloadFailed",
"onDownloadProgress", "onDownloadCancelled", "onInstallStarted",
"onInstallEnded", "onInstallFailed", "onInstallCancelled",
"onExternalInstall"].forEach(function(aEvent) {
self[aEvent] = function initialize_delegateInstallEvent(...aArgs) {
self.delegateInstallEvent(aEvent, aArgs);
const INSTALL_EVENTS = ["onNewInstall", "onDownloadStarted",
"onDownloadEnded", "onDownloadFailed",
"onDownloadProgress", "onDownloadCancelled",
"onInstallStarted", "onInstallEnded",
"onInstallFailed", "onInstallCancelled",
"onExternalInstall"];
for (let evt of INSTALL_EVENTS) {
let event = evt;
self[event] = function initialize_delegateInstallEvent(...aArgs) {
self.delegateInstallEvent(event, aArgs);
};
});
}
AddonManager.addManagerListener(this);
AddonManager.addInstallListener(this);
@ -710,10 +718,10 @@ var gViewController = {
isEnabled: function cmd_resetAddonAutoUpdate_isEnabled() true,
doCommand: function cmd_resetAddonAutoUpdate_doCommand() {
AddonManager.getAllAddons(function cmd_resetAddonAutoUpdate_getAllAddons(aAddonList) {
aAddonList.forEach(function(aAddon) {
if ("applyBackgroundUpdates" in aAddon)
aAddon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT;
});
for (let addon of aAddonList) {
if ("applyBackgroundUpdates" in addon)
addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT;
}
});
}
},
@ -837,13 +845,13 @@ var gViewController = {
};
AddonManager.getAddonsByTypes(null, function cmd_findAllUpdates_getAddonsByTypes(aAddonList) {
aAddonList.forEach(function(aAddon) {
if (aAddon.permissions & AddonManager.PERM_CAN_UPGRADE) {
for (let addon of aAddonList) {
if (addon.permissions & AddonManager.PERM_CAN_UPGRADE) {
pendingChecks++;
aAddon.findUpdates(updateCheckListener,
AddonManager.UPDATE_WHEN_USER_REQUESTED);
addon.findUpdates(updateCheckListener,
AddonManager.UPDATE_WHEN_USER_REQUESTED);
}
});
}
if (pendingChecks == 0)
updateStatus();
@ -1373,9 +1381,8 @@ function sortList(aList, aSortBy, aAscending) {
while (aList.listChild)
aList.removeChild(aList.lastChild);
elements.forEach(function(aElement) {
aList.appendChild(aElement);
});
for (let element of elements)
aList.appendChild(element);
}
function getAddonsAndInstalls(aType, aCallback) {
@ -1412,7 +1419,8 @@ function doPendingUninstalls(aListBox) {
listitem = listitem.nextSibling;
}
items.forEach(function(aAddon) { aAddon.uninstall(); });
for (let addon of items)
addon.uninstall();
}
var gCategories = {
@ -1783,22 +1791,22 @@ var gDiscoverView = {
gPendingInitializations++;
AddonManager.getAllAddons(function initialize_getAllAddons(aAddons) {
var list = {};
aAddons.forEach(function(aAddon) {
for (let addon of aAddons) {
var prefName = PREF_GETADDONS_CACHE_ID_ENABLED.replace("%ID%",
aAddon.id);
addon.id);
try {
if (!Services.prefs.getBoolPref(prefName))
return;
continue;
} catch (e) { }
list[aAddon.id] = {
name: aAddon.name,
version: aAddon.version,
type: aAddon.type,
userDisabled: aAddon.userDisabled,
isCompatible: aAddon.isCompatible,
isBlocklisted: aAddon.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED
list[addon.id] = {
name: addon.name,
version: addon.version,
type: addon.type,
userDisabled: addon.userDisabled,
isCompatible: addon.isCompatible,
isBlocklisted: addon.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED
}
});
}
setURL(url + "#" + JSON.stringify(list));
});
@ -1970,9 +1978,8 @@ var gDiscoverView = {
var listeners = this._loadListeners;
this._loadListeners = [];
listeners.forEach(function(aListener) {
aListener();
});
for (let listener of listeners)
listener();
},
onProgressChange: function gDiscoverView_onProgressChange() { },
@ -2062,32 +2069,32 @@ var gSearchView = {
var elements = [];
function createSearchResults(aObjsList, aIsInstall, aIsRemote) {
aObjsList.forEach(function(aObj, aIndex) {
let score = aObjsList.length - aIndex;
for (let index in aObjsList) {
let obj = aObjsList[index];
let score = aObjsList.length - index;
if (!aIsRemote && aQuery.length > 0) {
score = self.getMatchScore(aObj, aQuery);
score = self.getMatchScore(obj, aQuery);
if (score == 0)
return;
continue;
}
let item = createItem(aObj, aIsInstall, aIsRemote);
let item = createItem(obj, aIsInstall, aIsRemote);
item.setAttribute("relevancescore", score);
if (aIsRemote) {
gCachedAddons[aObj.id] = aObj;
if (aObj.purchaseURL)
gCachedAddons[obj.id] = obj;
if (obj.purchaseURL)
self._sorters.showprice = true;
}
elements.push(item);
});
}
}
function finishSearch(createdCount) {
if (elements.length > 0) {
sortElements(elements, [self._sorters.sortBy], self._sorters.ascending);
elements.forEach(function(aElement) {
self._listBox.insertBefore(aElement, self._listBox.lastChild);
});
for (let element of elements)
self._listBox.insertBefore(element, self._listBox.lastChild);
self.updateListAttributes();
}
@ -2361,9 +2368,8 @@ var gListView = {
self.showEmptyNotice(elements.length == 0);
if (elements.length > 0) {
sortElements(elements, ["uiState", "name"], true);
elements.forEach(function(aElement) {
self._listBox.appendChild(aElement);
});
for (let element of elements)
self._listBox.appendChild(element);
}
gEventManager.registerInstallListener(self);
@ -2745,10 +2751,12 @@ var gDetailView = {
this.node.removeAttribute("notification");
var pending = null;
["enable", "disable", "install", "uninstall", "upgrade"].forEach(function(aOp) {
if (isPending(this._addon, aOp))
pending = aOp;
}, this);
const PENDING_OPERATIONS = ["enable", "disable", "install", "uninstall",
"upgrade"];
for (let op of PENDING_OPERATIONS) {
if (isPending(this._addon, op))
pending = op;
}
this.node.setAttribute("pending", pending);
document.getElementById("detail-pending").textContent = gStrings.ext.formatStringFromName(
@ -3054,19 +3062,18 @@ var gUpdatesView = {
var elements = [];
let threshold = Date.now() - UPDATES_RECENT_TIMESPAN;
aAddonsList.forEach(function(aAddon) {
if (!aAddon.updateDate || aAddon.updateDate.getTime() < threshold)
return;
for (let addon of aAddonsList) {
if (!addon.updateDate || addon.updateDate.getTime() < threshold)
continue;
elements.push(createItem(aAddon));
});
elements.push(createItem(addon));
}
self.showEmptyNotice(elements.length == 0);
if (elements.length > 0) {
sortElements(elements, [self._sorters.sortBy], self._sorters.ascending);
elements.forEach(function(aElement) {
self._listBox.appendChild(aElement);
});
for (let element of elements)
self._listBox.appendChild(element);
}
gViewController.notifyViewChanged();
@ -3095,25 +3102,24 @@ var gUpdatesView = {
var elements = [];
aInstallsList.forEach(function(aInstall) {
if (!self.isManualUpdate(aInstall))
return;
for (let install of aInstallsList) {
if (!self.isManualUpdate(install))
continue;
let item = createItem(aInstall.existingAddon);
let item = createItem(install.existingAddon);
item.setAttribute("upgrade", true);
item.addEventListener("IncludeUpdateChanged", function item_onIncludeUpdateChanged() {
self.maybeDisableUpdateSelected();
}, false);
elements.push(item);
});
}
self.showEmptyNotice(elements.length == 0);
if (elements.length > 0) {
self._updateSelected.hidden = false;
sortElements(elements, [self._sorters.sortBy], self._sorters.ascending);
elements.forEach(function(aElement) {
self._listBox.appendChild(aElement);
});
for (let element of elements)
self._listBox.appendChild(element);
}
// ensure badge count is in sync

View File

@ -1137,10 +1137,12 @@
this.removeAttribute("notification");
var pending = null;
["enable", "disable", "install", "uninstall", "upgrade"].forEach(function(aOp) {
if (this.isPending(aOp))
pending = aOp;
}, this);
const PENDING_OPERATIONS = ["enable", "disable", "install",
"uninstall", "upgrade"];
for (let op of PENDING_OPERATIONS) {
if (this.isPending(op))
pending = op;
}
this.setAttribute("pending", pending);
this._pending.textContent = gStrings.ext.formatStringFromName(

View File

@ -100,18 +100,18 @@ var gChecking = {
AddonRepository.repopulateCache(ids, function() {
AddonManagerPrivate.updateAddonRepositoryData(function() {
aAddons.forEach(function(aAddon) {
for (let addonItem of aAddons) {
// Ignore disabled themes
if (aAddon.type != "theme" || !aAddon.userDisabled) {
gAddons[aAddon.id] = {
addon: aAddon,
if (addonItem.type != "theme" || !addonItem.userDisabled) {
gAddons[addonItem.id] = {
addon: addonItem,
install: null,
wasActive: aAddon.isActive
wasActive: addonItem.isActive
}
}
aAddon.findUpdates(self, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED);
});
addonItem.findUpdates(self, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED);
}
});
});
});
@ -144,25 +144,25 @@ var gChecking = {
let rows = document.getElementById("select-rows");
let lastAddon = null;
addons.forEach(function(aEntry) {
for (let entry of addons) {
if (lastAddon &&
orderForScope(aEntry.addon.scope) != orderForScope(lastAddon.scope)) {
orderForScope(entry.addon.scope) != orderForScope(lastAddon.scope)) {
let separator = document.createElement("separator");
rows.appendChild(separator);
}
let row = document.createElement("row");
row.setAttribute("id", aEntry.addon.id);
row.setAttribute("id", entry.addon.id);
row.setAttribute("class", "addon");
rows.appendChild(row);
row.setAddon(aEntry.addon, aEntry.install, aEntry.wasActive,
isAddonDistroInstalled(aEntry.addon.id));
row.setAddon(entry.addon, entry.install, entry.wasActive,
isAddonDistroInstalled(entry.addon.id));
if (aEntry.install)
aEntry.install.addListener(gUpdate);
if (entry.install)
entry.install.addListener(gUpdate);
lastAddon = aEntry.addon;
});
lastAddon = entry.addon;
}
showView(gSelect);
}

View File

@ -172,9 +172,8 @@ var gVersionInfoPage = {
return;
}
gUpdateWizard.addons.forEach(function(aAddon) {
aAddon.findUpdates(gVersionInfoPage, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED);
}, this);
for (let addon of gUpdateWizard.addons)
addon.findUpdates(gVersionInfoPage, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED);
});
});
});
@ -237,11 +236,11 @@ var gMismatchPage = {
document.documentElement.getButton("next").focus();
var incompatible = document.getElementById("mismatch.incompatible");
gUpdateWizard.addons.forEach(function(aAddon) {
for (let addon of gUpdateWizard.addons) {
var listitem = document.createElement("listitem");
listitem.setAttribute("label", aAddon.name + " " + aAddon.version);
listitem.setAttribute("label", addon.name + " " + addon.version);
incompatible.appendChild(listitem);
});
}
}
};
@ -263,9 +262,8 @@ var gUpdatePage = {
gUpdateWizard.errorItems = [];
this._totalCount = gUpdateWizard.addons.length;
gUpdateWizard.addons.forEach(function(aAddon) {
aAddon.findUpdates(this, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED);
}, this);
for (let addon of gUpdateWizard.addons)
addon.findUpdates(this, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED);
},
onAllUpdatesFinished: function() {
@ -310,12 +308,12 @@ var gFoundPage = {
var foundUpdates = document.getElementById("found.updates");
var itemCount = gUpdateWizard.addonsToUpdate.length;
gUpdateWizard.addonsToUpdate.forEach(function(aInstall) {
var listItem = foundUpdates.appendItem(aInstall.name + " " + aInstall.version);
for (let install of gUpdateWizard.addonsToUpdate) {
let listItem = foundUpdates.appendItem(install.name + " " + install.version);
listItem.setAttribute("type", "checkbox");
listItem.setAttribute("checked", "true");
listItem.install = aInstall;
});
listItem.install = install;
}
if (!gUpdateWizard.xpinstallEnabled) {
document.getElementById("xpinstallDisabledAlert").hidden = false;

View File

@ -142,16 +142,14 @@ XPInstallConfirm.onOK = function ()
getService(Components.interfaces.nsITelemetry).
getHistogramById("SECURITY_UI").
add(Components.interfaces.nsISecurityUITelemetry.WARNING_CONFIRM_ADDON_INSTALL_CLICK_THROUGH);
args.installs.forEach(function(install) {
for (let install of args.installs)
install.install();
});
return true;
}
XPInstallConfirm.onCancel = function ()
{
args.installs.forEach(function(install) {
for (let install of args.installs)
install.cancel();
});
return true;
}

View File

@ -14,10 +14,10 @@ var gProvider;
function parseParams(aQuery) {
let params = {};
aQuery.split("&").forEach(function(aParam) {
let [key, value] = aParam.split("=");
for (let param of aQuery.split("&")) {
let [key, value] = param.split("=");
params[key] = value;
});
}
return params;
}

View File

@ -37,9 +37,8 @@ function test() {
function end_test() {
// Test generates a lot of available installs so just cancel them all
AddonManager.getAllInstalls(function(aInstalls) {
aInstalls.forEach(function(aInstall) {
aInstall.cancel();
});
for (let install of aInstalls)
install.cancel();
finish();
});
@ -51,20 +50,21 @@ function install_test_addons(aCallback) {
// Use a blank update URL
Services.prefs.setCharPref(PREF_UPDATEURL, TESTROOT + "missing.rdf");
["browser_bug557956_1",
"browser_bug557956_2",
"browser_bug557956_3",
"browser_bug557956_4",
"browser_bug557956_5",
"browser_bug557956_6",
"browser_bug557956_7",
"browser_bug557956_8_1",
"browser_bug557956_9_1",
"browser_bug557956_10"].forEach(function(aName) {
AddonManager.getInstallForURL(TESTROOT + "addons/" + aName + ".xpi", function(aInstall) {
let names = ["browser_bug557956_1",
"browser_bug557956_2",
"browser_bug557956_3",
"browser_bug557956_4",
"browser_bug557956_5",
"browser_bug557956_6",
"browser_bug557956_7",
"browser_bug557956_8_1",
"browser_bug557956_9_1",
"browser_bug557956_10"];
for (let name of names) {
AddonManager.getInstallForURL(TESTROOT + "addons/" + name + ".xpi", function(aInstall) {
installs.push(aInstall);
}, "application/x-xpinstall");
});
}
var listener = {
installCount: 0,
@ -80,10 +80,10 @@ function install_test_addons(aCallback) {
}
};
installs.forEach(function(aInstall) {
aInstall.addListener(listener);
aInstall.install();
});
for (let install of installs) {
install.addListener(listener);
install.install();
}
}
function uninstall_test_addons(aCallback) {
@ -98,10 +98,10 @@ function uninstall_test_addons(aCallback) {
"addon9@tests.mozilla.org",
"addon10@tests.mozilla.org"],
function(aAddons) {
aAddons.forEach(function(aAddon) {
if (aAddon)
aAddon.uninstall();
});
for (let addon of aAddons) {
if (addon)
addon.uninstall();
}
aCallback();
});
}
@ -353,9 +353,8 @@ add_test(function() {
"addon9@tests.mozilla.org",
"addon10@tests.mozilla.org"],
function(aAddons) {
aAddons.forEach(function(aAddon) {
aAddon.userDisabled = true;
});
for (let addon of aAddons)
addon.userDisabled = true;
// These add-ons were inactive in the old application
var inactiveAddonIds = [
@ -389,9 +388,8 @@ add_test(function() {
"addon9@tests.mozilla.org",
"addon10@tests.mozilla.org"],
function(aAddons) {
aAddons.forEach(function(aAddon) {
aAddon.uninstall();
});
for (let addon of aAddons)
addon.uninstall();
// These add-ons were inactive in the old application
var inactiveAddonIds = [
@ -450,12 +448,13 @@ add_test(function() {
"addon9@tests.mozilla.org",
"addon10@tests.mozilla.org"],
function(aAddons) {
aAddons.forEach(function(aAddon) {
if (aAddon.id == "addon10@tests.mozilla.org")
is(aAddon.isCompatible, true, "Addon10 should be compatible before compat overrides are refreshed");
for (let addon of aAddons) {
if (addon.id == "addon10@tests.mozilla.org")
is(addon.isCompatible, true, "Addon10 should be compatible before compat overrides are refreshed");
else
aAddon.uninstall();
});
addon.uninstall();
}
Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, TESTROOT + "browser_bug557956.xml");
Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true);

View File

@ -84,17 +84,16 @@ function test_confirmation(aWindow, aExpectedURLs) {
var list = aWindow.document.getElementById("itemList");
is(list.childNodes.length, aExpectedURLs.length, "Should be the right number of installs");
aExpectedURLs.forEach(function(aURL) {
var node = list.firstChild;
while (node) {
if (node.url == aURL) {
ok(true, "Should have seen " + aURL + " in the list");
return;
for (let url of aExpectedURLs) {
let found = false;
for (let node of list.children) {
if (node.url == url) {
found = true;
break;
}
node = node.nextSibling;
}
ok(false, "Should have seen " + aURL + " in the list");
});
ok(found, "Should have seen " + url + " in the list");
}
aWindow.document.documentElement.cancelDialog();
}

View File

@ -29,9 +29,8 @@ function test() {
function end_test() {
// Test generates a lot of available installs so just cancel them all
AddonManager.getAllInstalls(function(aInstalls) {
aInstalls.forEach(function(aInstall) {
aInstall.cancel();
});
for (let install of aInstalls)
install.cancel();
close_manager(gManagerWindow, finish);
});

View File

@ -17,14 +17,14 @@ function test() {
});
let allCompatible = true;
aAddons.forEach(function checkCompatibility(a) {
for (let a of aAddons) {
// Ignore plugins.
if (a.type == "plugin")
return;
continue;
ok(a.isCompatible, a.type + " " + a.name + " " + a.version + " should be compatible");
allCompatible = allCompatible && a.isCompatible;
});
}
// Add a reminder.
if (!allCompatible)
ok(false, "As this test failed, test browser_bug557956.js should have failed, too.");

View File

@ -130,24 +130,23 @@ function testHash(aBrowser, aTestAddonVisible, aCallback) {
// Test against all the add-ons the manager knows about since plugins and
// app extensions may exist
AddonManager.getAllAddons(function(aAddons) {
aAddons.forEach(function(aAddon) {
if (!(aAddon.id in data)) {
for (let addon of aAddons) {
if (!(addon.id in data)) {
// Test add-ons will have shown an error if necessary above
if (aAddon.id.substring(6) != "@tests.mozilla.org")
ok(false, "Add-on " + aAddon.id + " was not included in the data");
return;
if (addon.id.substring(6) != "@tests.mozilla.org")
ok(false, "Add-on " + addon.id + " was not included in the data");
continue;
}
info("Testing data for add-on " + aAddon.id);
var addonData = data[aAddon.id];
is(addonData.name, aAddon.name, "Name should be correct");
is(addonData.version, aAddon.version, "Version should be correct");
is(addonData.type, aAddon.type, "Type should be correct");
is(addonData.userDisabled, aAddon.userDisabled, "userDisabled should be correct");
is(addonData.isBlocklisted, aAddon.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED, "blocklisted should be correct");
is(addonData.isCompatible, aAddon.isCompatible, "isCompatible should be correct");
});
info("Testing data for add-on " + addon.id);
var addonData = data[addon.id];
is(addonData.name, addon.name, "Name should be correct");
is(addonData.version, addon.version, "Version should be correct");
is(addonData.type, addon.type, "Type should be correct");
is(addonData.userDisabled, addon.userDisabled, "userDisabled should be correct");
is(addonData.isBlocklisted, addon.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED, "blocklisted should be correct");
is(addonData.isCompatible, addon.isCompatible, "isCompatible should be correct");
}
aCallback();
});
}

View File

@ -105,17 +105,16 @@ function test_confirmation(aWindow, aExpectedURLs) {
var list = aWindow.document.getElementById("itemList");
is(list.childNodes.length, aExpectedURLs.length, "Should be the right number of installs");
aExpectedURLs.forEach(function(aURL) {
var node = list.firstChild;
while (node) {
if (node.url == aURL) {
ok(true, "Should have seen " + aURL + " in the list");
return;
for (let url of aExpectedURLs) {
let found = false;
for (let node of list.children) {
if (node.url == url) {
found = true;
break;
}
node = node.nextSibling;
}
ok(false, "Should have seen " + aURL + " in the list");
});
ok(found, "Should have seen " + url + " in the list");
}
aWindow.document.documentElement.cancelDialog();
}

View File

@ -61,7 +61,8 @@ function test() {
sourceURI: "http://example.com/fail-install1.xpi"
}]);
installs.forEach(function(aInstall) { aInstall.install(); });
for (let install of installs )
install.install();
open_manager("addons://list/extension", function(aWindow) {
gManagerWindow = aWindow;

View File

@ -103,26 +103,27 @@ function test() {
Services.prefs.setBoolPref("extensions.installedDistroAddon.test12@tests.mozilla.org", true);
Services.prefs.setBoolPref("extensions.installedDistroAddon.test15@tests.mozilla.org", true);
ADDONS.forEach(function(aAddon, aPos) {
var addon = new MockAddon("test" + aPos + "@tests.mozilla.org",
"Test Add-on " + aPos, "extension");
for (let pos in ADDONS) {
let addonItem = ADDONS[pos];
let addon = new MockAddon("test" + pos + "@tests.mozilla.org",
"Test Add-on " + pos, "extension");
addon.version = "1.0";
addon.userDisabled = aAddon[0];
addon.appDisabled = aAddon[1];
addon.isActive = aAddon[3];
addon.applyBackgroundUpdates = aAddon[5] ? AddonManager.AUTOUPDATE_ENABLE
addon.userDisabled = addonItem[0];
addon.appDisabled = addonItem[1];
addon.isActive = addonItem[3];
addon.applyBackgroundUpdates = addonItem[5] ? AddonManager.AUTOUPDATE_ENABLE
: AddonManager.AUTOUPDATE_DISABLE;
addon.scope = aAddon[6];
addon.scope = addonItem[6];
// Remove the upgrade permission from non-profile add-ons
if (addon.scope != AddonManager.SCOPE_PROFILE)
addon._permissions -= AddonManager.PERM_CAN_UPGRADE;
addon.findUpdates = function(aListener, aReason, aAppVersion, aPlatformVersion) {
addon.appDisabled = aAddon[2];
addon.appDisabled = addonItem[2];
addon.isActive = addon.shouldBeActive;
if (aAddon[4]) {
if (addonItem[4]) {
var newAddon = new MockAddon(this.id, this.name, "extension");
newAddon.version = "2.0";
var install = new MockInstall(this.name, this.type, newAddon);
@ -134,7 +135,7 @@ function test() {
};
gProvider.addAddon(addon);
});
}
gWin = Services.ww.openWindow(null,
"chrome://mozapps/content/extensions/selectAddons.xul",

View File

@ -212,9 +212,8 @@ function set_order(aSortBy, aAscending) {
node = node.nextSibling;
}
gManagerWindow.sortElements(elements, ["uiState", aSortBy], aAscending);
elements.forEach(function(aElement) {
list.appendChild(aElement);
});
for (let element of elements)
list.appendChild(element);
}
function check_order(aExpectedOrder) {

View File

@ -69,35 +69,35 @@ var gRestorePrefs = [{name: PREF_LOGGING_ENABLED},
{name: PREF_STRICT_COMPAT},
{name: PREF_CHECK_COMPATIBILITY}];
gRestorePrefs.forEach(function(aPref) {
if (!Services.prefs.prefHasUserValue(aPref.name)) {
aPref.type = "clear";
return;
for (let pref of gRestorePrefs) {
if (!Services.prefs.prefHasUserValue(pref.name)) {
pref.type = "clear";
continue;
}
aPref.type = Services.prefs.getPrefType(aPref.name);
if (aPref.type == Services.prefs.PREF_BOOL)
aPref.value = Services.prefs.getBoolPref(aPref.name);
else if (aPref.type == Services.prefs.PREF_INT)
aPref.value = Services.prefs.getIntPref(aPref.name);
else if (aPref.type == Services.prefs.PREF_STRING)
aPref.value = Services.prefs.getCharPref(aPref.name);
});
pref.type = Services.prefs.getPrefType(pref.name);
if (pref.type == Services.prefs.PREF_BOOL)
pref.value = Services.prefs.getBoolPref(pref.name);
else if (pref.type == Services.prefs.PREF_INT)
pref.value = Services.prefs.getIntPref(pref.name);
else if (pref.type == Services.prefs.PREF_STRING)
pref.value = Services.prefs.getCharPref(pref.name);
}
// Turn logging on for all tests
Services.prefs.setBoolPref(PREF_LOGGING_ENABLED, true);
registerCleanupFunction(function() {
// Restore prefs
gRestorePrefs.forEach(function(aPref) {
if (aPref.type == "clear")
Services.prefs.clearUserPref(aPref.name);
else if (aPref.type == Services.prefs.PREF_BOOL)
Services.prefs.setBoolPref(aPref.name, aPref.value);
else if (aPref.type == Services.prefs.PREF_INT)
Services.prefs.setIntPref(aPref.name, aPref.value);
else if (aPref.type == Services.prefs.PREF_STRING)
Services.prefs.setCharPref(aPref.name, aPref.value);
});
for (let pref of gRestorePrefs) {
if (pref.type == "clear")
Services.prefs.clearUserPref(pref.name);
else if (pref.type == Services.prefs.PREF_BOOL)
Services.prefs.setBoolPref(pref.name, pref.value);
else if (pref.type == Services.prefs.PREF_INT)
Services.prefs.setIntPref(pref.name, pref.value);
else if (pref.type == Services.prefs.PREF_STRING)
Services.prefs.setCharPref(pref.name, pref.value);
}
// Throw an error if the add-ons manager window is open anywhere
var windows = Services.wm.getEnumerator("Addons:Manager");
@ -122,13 +122,13 @@ registerCleanupFunction(function() {
// We can for now know that getAllInstalls actually calls its callback before
// it returns so this will complete before the next test start.
AddonManager.getAllInstalls(function(aInstalls) {
aInstalls.forEach(function(aInstall) {
if (aInstall instanceof MockInstall)
return;
for (let install of aInstalls) {
if (install instanceof MockInstall)
continue;
ok(false, "Should not have seen an install of " + aInstall.sourceURI.spec + " in state " + aInstall.state);
aInstall.cancel();
});
ok(false, "Should not have seen an install of " + install.sourceURI.spec + " in state " + install.state);
install.cancel();
}
});
});
@ -663,20 +663,20 @@ MockProvider.prototype = {
*/
createAddons: function MP_createAddons(aAddonProperties) {
var newAddons = [];
aAddonProperties.forEach(function(aAddonProp) {
var addon = new MockAddon(aAddonProp.id);
for (var prop in aAddonProp) {
for (let addonProp of aAddonProperties) {
let addon = new MockAddon(addonProp.id);
for (let prop in addonProp) {
if (prop == "id")
continue;
if (prop == "applyBackgroundUpdates") {
addon._applyBackgroundUpdates = aAddonProp[prop];
addon._applyBackgroundUpdates = addonProp[prop];
continue;
}
if (prop == "appDisabled") {
addon._appDisabled = aAddonProp[prop];
addon._appDisabled = addonProp[prop];
continue;
}
addon[prop] = aAddonProp[prop];
addon[prop] = addonProp[prop];
}
if (!addon.optionsType && !!addon.optionsURL)
addon.optionsType = AddonManager.OPTIONS_TYPE_DIALOG;
@ -686,7 +686,7 @@ MockProvider.prototype = {
this.addAddon(addon);
newAddons.push(addon);
}, this);
}
return newAddons;
},
@ -701,25 +701,25 @@ MockProvider.prototype = {
*/
createInstalls: function MP_createInstalls(aInstallProperties) {
var newInstalls = [];
aInstallProperties.forEach(function(aInstallProp) {
var install = new MockInstall(aInstallProp.name || null,
aInstallProp.type || null,
for (let installProp of aInstallProperties) {
let install = new MockInstall(installProp.name || null,
installProp.type || null,
null);
for (var prop in aInstallProp) {
for (let prop in installProp) {
switch (prop) {
case "name":
case "type":
break;
case "sourceURI":
install[prop] = NetUtil.newURI(aInstallProp[prop]);
install[prop] = NetUtil.newURI(installProp[prop]);
break;
default:
install[prop] = aInstallProp[prop];
install[prop] = installProp[prop];
}
}
this.addInstall(install);
newInstalls.push(install);
}, this);
}
return newInstalls;
},
@ -737,9 +737,8 @@ MockProvider.prototype = {
* Called when the provider should shutdown.
*/
shutdown: function MP_shutdown() {
this.callbackTimers.forEach(function(aTimer) {
aTimer.cancel();
});
for (let timer of this.callbackTimers)
timer.cancel();
this.callbackTimers = [];
this.started = false;
@ -1218,16 +1217,16 @@ MockInstall.prototype = {
// Call test listeners after standard listeners to remove race condition
// between standard and test listeners
this.testListeners.forEach(function(aListener) {
for (let listener of this.testListeners) {
try {
if (aMethod in aListener)
if (aListener[aMethod].call(aListener, this, this.addon) === false)
if (aMethod in listener)
if (listener[aMethod].call(listener, this, this.addon) === false)
result = false;
}
catch (e) {
ok(false, "Test listener threw exception: " + e);
}
}, this);
}
return result;
}