mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to inbound.
This commit is contained in:
commit
49b4423e2d
1
.hgtags
1
.hgtags
@ -91,3 +91,4 @@ fd72dbbd692012224145be1bf13df1d7675fd277 FIREFOX_AURORA_17_BASE
|
||||
cf8750abee06cde395c659f8ecd8ae019d7512e3 FIREFOX_AURORA_19_BASE
|
||||
5bb309998e7050c9ee80b0147de1e473f008e221 FIREFOX_AURORA_20_BASE
|
||||
cc37417e2c284aed960f98ffa479de4ccdd5c7c3 FIREFOX_AURORA_21_BASE
|
||||
1c070ab0f9db59f13423b9c1db60419f7a9098f9 FIREFOX_AURORA_22_BASE
|
||||
|
2
b2g/confvars.sh
Executable file → Normal file
2
b2g/confvars.sh
Executable file → Normal file
@ -5,7 +5,7 @@
|
||||
MOZ_APP_BASENAME=B2G
|
||||
MOZ_APP_VENDOR=Mozilla
|
||||
|
||||
MOZ_APP_VERSION=22.0a1
|
||||
MOZ_APP_VERSION=23.0a1
|
||||
MOZ_APP_UA_NAME=Firefox
|
||||
|
||||
MOZ_UA_OS_AGNOSTIC=1
|
||||
|
@ -1 +1 @@
|
||||
22.0a1
|
||||
23.0a1
|
||||
|
@ -14,3 +14,4 @@ Cu.import("resource:///modules/devtools/CmdInspect.jsm");
|
||||
Cu.import("resource:///modules/devtools/CmdResize.jsm");
|
||||
Cu.import("resource:///modules/devtools/CmdTilt.jsm");
|
||||
Cu.import("resource:///modules/devtools/CmdScratchpad.jsm");
|
||||
Cu.import("resource:///modules/devtools/cmd-profiler.jsm");
|
||||
|
@ -22,8 +22,8 @@ function DebuggerPanel(iframeWindow, toolbox) {
|
||||
this.panelWin = iframeWindow;
|
||||
this._toolbox = toolbox;
|
||||
|
||||
this._controller = this.panelWin.DebuggerController;
|
||||
this._view = this.panelWin.DebuggerView;
|
||||
this._controller = this.panelWin.DebuggerController;
|
||||
this._controller._target = this.target;
|
||||
this._bkp = this._controller.Breakpoints;
|
||||
|
||||
@ -32,48 +32,38 @@ function DebuggerPanel(iframeWindow, toolbox) {
|
||||
|
||||
DebuggerPanel.prototype = {
|
||||
/**
|
||||
* open is effectively an asynchronous constructor
|
||||
* Open is effectively an asynchronous constructor.
|
||||
*
|
||||
* @return object
|
||||
* A Promise that is resolved when the Debugger completes opening.
|
||||
*/
|
||||
open: function DebuggerPanel_open() {
|
||||
let deferred = Promise.defer();
|
||||
let promise;
|
||||
|
||||
this._ensureOnlyOneRunningDebugger();
|
||||
|
||||
let onDebuggerLoaded = function () {
|
||||
this.panelWin.removeEventListener("Debugger:Loaded",
|
||||
onDebuggerLoaded, true);
|
||||
this._isReady = true;
|
||||
this.emit("ready");
|
||||
deferred.resolve(this);
|
||||
}.bind(this);
|
||||
|
||||
let onDebuggerConnected = function () {
|
||||
this.panelWin.removeEventListener("Debugger:Connected",
|
||||
onDebuggerConnected, true);
|
||||
this.emit("connected");
|
||||
}.bind(this);
|
||||
|
||||
this.panelWin.addEventListener("Debugger:Loaded", onDebuggerLoaded, true);
|
||||
this.panelWin.addEventListener("Debugger:Connected",
|
||||
onDebuggerConnected, true);
|
||||
|
||||
// Remote debugging gets the debuggee from a RemoteTarget object.
|
||||
if (this.target.isRemote) {
|
||||
this.panelWin._remoteFlag = true;
|
||||
return deferred.promise;
|
||||
// Local debugging needs to make the target remote.
|
||||
if (!this.target.isRemote) {
|
||||
promise = this.target.makeRemote();
|
||||
} else {
|
||||
promise = Promise.resolve(this.target);
|
||||
}
|
||||
|
||||
// Local debugging needs to convert the TabTarget to a RemoteTarget.
|
||||
return this.target.makeRemote().then(function success() {
|
||||
return deferred.promise;
|
||||
});
|
||||
return promise
|
||||
.then(() => this._controller.startupDebugger())
|
||||
.then(() => this._controller.connect())
|
||||
.then(() => {
|
||||
this.isReady = true;
|
||||
this.emit("ready");
|
||||
return this;
|
||||
})
|
||||
.then(null, function onError(aReason) {
|
||||
Cu.reportError("DebuggerPanel open failed. " +
|
||||
reason.error + ": " + reason.message);
|
||||
});
|
||||
},
|
||||
|
||||
// DevToolPanel API
|
||||
get target() this._toolbox.target,
|
||||
|
||||
get isReady() this._isReady,
|
||||
|
||||
destroy: function() {
|
||||
this.emit("destroyed");
|
||||
return Promise.resolve(null);
|
||||
|
@ -38,6 +38,9 @@ Cu.import("resource:///modules/devtools/SideMenuWidget.jsm");
|
||||
Cu.import("resource:///modules/devtools/VariablesView.jsm");
|
||||
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Parser",
|
||||
"resource:///modules/devtools/Parser.jsm");
|
||||
|
||||
@ -51,158 +54,126 @@ let DebuggerController = {
|
||||
initialize: function DC_initialize() {
|
||||
dumpn("Initializing the DebuggerController");
|
||||
|
||||
this._startupDebugger = this._startupDebugger.bind(this);
|
||||
this._shutdownDebugger = this._shutdownDebugger.bind(this);
|
||||
this.startupDebugger = this.startupDebugger.bind(this);
|
||||
this.shutdownDebugger = this.shutdownDebugger.bind(this);
|
||||
this._onTabNavigated = this._onTabNavigated.bind(this);
|
||||
this._onTabDetached = this._onTabDetached.bind(this);
|
||||
|
||||
window.addEventListener("DOMContentLoaded", this._startupDebugger, true);
|
||||
window.addEventListener("unload", this._shutdownDebugger, true);
|
||||
// Chrome debugging lives in a different process and needs to handle
|
||||
// debugger startup and shutdown by itself.
|
||||
if (window._isChromeDebugger) {
|
||||
window.addEventListener("DOMContentLoaded", this.startupDebugger, true);
|
||||
window.addEventListener("unload", this.shutdownDebugger, true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes the view and connects a debugger client to the server.
|
||||
* Initializes the view.
|
||||
*
|
||||
* @return object
|
||||
* A promise that is resolved when the debugger finishes startup.
|
||||
*/
|
||||
_startupDebugger: function DC__startupDebugger() {
|
||||
startupDebugger: function DC_startupDebugger() {
|
||||
if (this._isInitialized) {
|
||||
return;
|
||||
}
|
||||
this._isInitialized = true;
|
||||
window.removeEventListener("DOMContentLoaded", this._startupDebugger, true);
|
||||
window.removeEventListener("DOMContentLoaded", this.startupDebugger, true);
|
||||
|
||||
DebuggerView.initialize(function() {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
DebuggerView.initialize(() => {
|
||||
DebuggerView._isInitialized = true;
|
||||
|
||||
window.dispatchEvent(document, "Debugger:Loaded");
|
||||
this._connect();
|
||||
}.bind(this));
|
||||
// Chrome debugging needs to initiate the connection by itself.
|
||||
if (window._isChromeDebugger) {
|
||||
this.connect().then(deferred.resolve);
|
||||
} else {
|
||||
deferred.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroys the view and disconnects the debugger client from the server.
|
||||
*
|
||||
* @return object
|
||||
* A promise that is resolved when the debugger finishes shutdown.
|
||||
*/
|
||||
_shutdownDebugger: function DC__shutdownDebugger() {
|
||||
shutdownDebugger: function DC__shutdownDebugger() {
|
||||
if (this._isDestroyed || !DebuggerView._isInitialized) {
|
||||
return;
|
||||
}
|
||||
this._isDestroyed = true;
|
||||
window.removeEventListener("unload", this._shutdownDebugger, true);
|
||||
window.removeEventListener("unload", this.shutdownDebugger, true);
|
||||
|
||||
DebuggerView.destroy(function() {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
DebuggerView.destroy(() => {
|
||||
DebuggerView._isDestroyed = true;
|
||||
this.SourceScripts.disconnect();
|
||||
this.StackFrames.disconnect();
|
||||
this.ThreadState.disconnect();
|
||||
|
||||
this._disconnect();
|
||||
window.dispatchEvent(document, "Debugger:Unloaded");
|
||||
this.disconnect();
|
||||
deferred.resolve();
|
||||
|
||||
// Chrome debugging needs to close its parent process on shutdown.
|
||||
window._isChromeDebugger && this._quitApp();
|
||||
}.bind(this));
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Prepares the hostname and port number for a remote debugger connection
|
||||
* and handles connection retries and timeouts.
|
||||
* XXX: remove all this (bug 823577)
|
||||
* @return boolean
|
||||
* True if connection should proceed normally, false otherwise.
|
||||
*/
|
||||
_prepareConnection: function DC__prepareConnection() {
|
||||
// If we exceeded the total number of connection retries, bail.
|
||||
if (this._remoteConnectionTry === Prefs.remoteConnectionRetries) {
|
||||
Services.prompt.alert(null,
|
||||
L10N.getStr("remoteDebuggerPromptTitle"),
|
||||
L10N.getStr("remoteDebuggerConnectionFailedMessage"));
|
||||
|
||||
// If the connection was not established before a certain number of
|
||||
// retries, close the remote debugger.
|
||||
this._shutdownDebugger();
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: This is ugly, need to rethink the design for the UI in #751677.
|
||||
if (!Prefs.remoteAutoConnect) {
|
||||
let prompt = new RemoteDebuggerPrompt();
|
||||
let result = prompt.show(!!this._remoteConnectionTimeout);
|
||||
|
||||
// If the connection was not established before the user canceled the
|
||||
// prompt, close the remote debugger.
|
||||
if (!result) {
|
||||
this._shutdownDebugger();
|
||||
return false;
|
||||
}
|
||||
|
||||
Prefs.remoteHost = prompt.remote.host;
|
||||
Prefs.remotePort = prompt.remote.port;
|
||||
Prefs.remoteAutoConnect = prompt.remote.auto;
|
||||
}
|
||||
|
||||
// If this debugger is connecting remotely to a server, we need to check
|
||||
// after a while if the connection actually succeeded.
|
||||
this._remoteConnectionTry = ++this._remoteConnectionTry || 1;
|
||||
this._remoteConnectionTimeout = window.setTimeout(function() {
|
||||
// If we couldn't connect to any server yet, try again...
|
||||
if (!this.activeThread) {
|
||||
this._onRemoteConnectionTimeout();
|
||||
this._connect();
|
||||
}
|
||||
}.bind(this), Prefs.remoteTimeout);
|
||||
|
||||
// Proceed with the connection normally.
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a remote connection timeout occurs.
|
||||
*/
|
||||
_onRemoteConnectionTimeout: function DC__onRemoteConnectionTimeout() {
|
||||
Cu.reportError("Couldn't connect to " +
|
||||
Prefs.remoteHost + ":" + Prefs.remotePort);
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes a debugger client and connects it to the debugger server,
|
||||
* wiring event handlers as necessary.
|
||||
*
|
||||
* @return object
|
||||
* A promise that is resolved when the debugger finishes connecting.
|
||||
*/
|
||||
_connect: function DC__connect() {
|
||||
function callback() {
|
||||
window.dispatchEvent(document, "Debugger:Connected");
|
||||
}
|
||||
connect: function DC_connect() {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
if (!window._isChromeDebugger) {
|
||||
let client = this.client = this._target.client;
|
||||
this._target.on("close", this._onTabDetached);
|
||||
this._target.on("navigate", this._onTabNavigated);
|
||||
this._target.on("will-navigate", this._onTabNavigated);
|
||||
let target = this._target;
|
||||
let { client, form } = target;
|
||||
target.on("close", this._onTabDetached);
|
||||
target.on("navigate", this._onTabNavigated);
|
||||
target.on("will-navigate", this._onTabNavigated);
|
||||
|
||||
if (this._target.chrome) {
|
||||
let dbg = this._target.form.chromeDebugger;
|
||||
this._startChromeDebugging(client, dbg, callback);
|
||||
if (target.chrome) {
|
||||
this._startChromeDebugging(client, form.chromeDebugger, deferred.resolve);
|
||||
} else {
|
||||
this._startDebuggingTab(client, this._target.form, callback);
|
||||
this._startDebuggingTab(client, form, deferred.resolve);
|
||||
}
|
||||
return;
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
// Chrome debugging needs to make the connection to the debuggee.
|
||||
let transport = debuggerSocketConnect(Prefs.chromeDebuggingHost,
|
||||
Prefs.chromeDebuggingPort);
|
||||
|
||||
let client = this.client = new DebuggerClient(transport);
|
||||
let client = new DebuggerClient(transport);
|
||||
client.addListener("tabNavigated", this._onTabNavigated);
|
||||
client.addListener("tabDetached", this._onTabDetached);
|
||||
|
||||
client.connect(function(aType, aTraits) {
|
||||
client.listTabs(function(aResponse) {
|
||||
this._startChromeDebugging(client, aResponse.chromeDebugger, callback);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
client.connect((aType, aTraits) => {
|
||||
client.listTabs((aResponse) => {
|
||||
this._startChromeDebugging(client, aResponse.chromeDebugger, deferred.resolve);
|
||||
});
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Disconnects the debugger client and removes event handlers as necessary.
|
||||
*/
|
||||
_disconnect: function DC__disconnect() {
|
||||
disconnect: function DC_disconnect() {
|
||||
// Return early if the client didn't even have a chance to instantiate.
|
||||
if (!this.client) {
|
||||
return;
|
||||
@ -249,7 +220,7 @@ let DebuggerController = {
|
||||
* Called when the debugged tab is closed.
|
||||
*/
|
||||
_onTabDetached: function DC__onTabDetached() {
|
||||
this._shutdownDebugger();
|
||||
this.shutdownDebugger();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -259,6 +230,8 @@ let DebuggerController = {
|
||||
* The debugger client.
|
||||
* @param object aTabGrip
|
||||
* The remote protocol grip of the tab.
|
||||
* @param function aCallback
|
||||
* A function to invoke once the client attached to the active thread.
|
||||
*/
|
||||
_startDebuggingTab: function DC__startDebuggingTab(aClient, aTabGrip, aCallback) {
|
||||
if (!aClient) {
|
||||
@ -267,14 +240,14 @@ let DebuggerController = {
|
||||
}
|
||||
this.client = aClient;
|
||||
|
||||
aClient.attachTab(aTabGrip.actor, function(aResponse, aTabClient) {
|
||||
aClient.attachTab(aTabGrip.actor, (aResponse, aTabClient) => {
|
||||
if (!aTabClient) {
|
||||
Cu.reportError("No tab client found!");
|
||||
return;
|
||||
}
|
||||
this.tabClient = aTabClient;
|
||||
|
||||
aClient.attachThread(aResponse.threadActor, function(aResponse, aThreadClient) {
|
||||
aClient.attachThread(aResponse.threadActor, (aResponse, aThreadClient) => {
|
||||
if (!aThreadClient) {
|
||||
Cu.reportError("Couldn't attach to thread: " + aResponse.error);
|
||||
return;
|
||||
@ -289,8 +262,8 @@ let DebuggerController = {
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
@ -300,6 +273,8 @@ let DebuggerController = {
|
||||
* The debugger client.
|
||||
* @param object aChromeDebugger
|
||||
* The remote protocol grip of the chrome debugger.
|
||||
* @param function aCallback
|
||||
* A function to invoke once the client attached to the active thread.
|
||||
*/
|
||||
_startChromeDebugging: function DC__startChromeDebugging(aClient, aChromeDebugger, aCallback) {
|
||||
if (!aClient) {
|
||||
@ -308,7 +283,7 @@ let DebuggerController = {
|
||||
}
|
||||
this.client = aClient;
|
||||
|
||||
aClient.attachThread(aChromeDebugger, function(aResponse, aThreadClient) {
|
||||
aClient.attachThread(aChromeDebugger, (aResponse, aThreadClient) => {
|
||||
if (!aThreadClient) {
|
||||
Cu.reportError("Couldn't attach to thread: " + aResponse.error);
|
||||
return;
|
||||
@ -323,7 +298,7 @@ let DebuggerController = {
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -20,44 +20,31 @@ function test()
|
||||
{
|
||||
let scriptShown = false;
|
||||
let framesAdded = false;
|
||||
let resumed = false;
|
||||
let testStarted = false;
|
||||
|
||||
gTab = addTab(TAB_URL, function onAddTab() {
|
||||
info("tab added");
|
||||
gDebuggee = gTab.linkedBrowser.contentWindow.wrappedJSObject;
|
||||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.panelWin;
|
||||
resumed = true;
|
||||
|
||||
let target = TargetFactory.forTab(gTab);
|
||||
|
||||
gDevTools.showToolbox(target, "jsdebugger").then(function(toolbox) {
|
||||
info("jsdebugger panel opened");
|
||||
gPane = toolbox.getCurrentPanel();
|
||||
gDebugger = gPane.panelWin;
|
||||
gDebugger.addEventListener("Debugger:AfterSourcesAdded", onAfterSourcesAdded);
|
||||
});
|
||||
});
|
||||
|
||||
function onAfterSourcesAdded()
|
||||
{
|
||||
info("scripts added");
|
||||
gDebugger.removeEventListener("Debugger:AfterSourcesAdded",onAfterSourcesAdded);
|
||||
gDebugger.addEventListener("Debugger:SourceShown", onSourceShown);
|
||||
|
||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded",
|
||||
function onFramesAdded() {
|
||||
info("frames added");
|
||||
framesAdded = true;
|
||||
executeSoon(startTest);
|
||||
});
|
||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
||||
framesAdded = true;
|
||||
executeSoon(startTest);
|
||||
});
|
||||
|
||||
executeSoon(function() {
|
||||
gDebuggee.firstCall();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function onSourceShown(aEvent)
|
||||
{
|
||||
scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
|
||||
info("script shown " + aEvent.detail.url);
|
||||
executeSoon(startTest);
|
||||
}
|
||||
|
||||
@ -66,7 +53,6 @@ function test()
|
||||
if (scriptShown && framesAdded && !testStarted) {
|
||||
gDebugger.removeEventListener("Debugger:SourceShown", onSourceShown);
|
||||
testStarted = true;
|
||||
info("test started");
|
||||
Services.tm.currentThread.dispatch({ run: performTest }, 0);
|
||||
}
|
||||
}
|
||||
@ -171,7 +157,8 @@ function test()
|
||||
{
|
||||
info("add a breakpoint to the second script which is not selected");
|
||||
|
||||
is(Object.keys(gBreakpoints).length, 0, "no breakpoints in the debugger");
|
||||
is(Object.keys(gBreakpoints).length, 0,
|
||||
"no breakpoints in the debugger");
|
||||
ok(!gPane.getBreakpoint(gSources.selectedValue, 6),
|
||||
"getBreakpoint(selectedScript, 6) returns no breakpoint");
|
||||
isnot(gSources.values[0], gSources.selectedValue,
|
||||
@ -204,7 +191,9 @@ function test()
|
||||
executeSoon(function() {
|
||||
ok(aBreakpointClient.actor in gBreakpoints,
|
||||
"breakpoint2 client found in the list of debugger breakpoints");
|
||||
is(Object.keys(gBreakpoints).length, 1, "one breakpoint in the debugger");
|
||||
|
||||
is(Object.keys(gBreakpoints).length, 1,
|
||||
"one breakpoint in the debugger");
|
||||
is(gPane.getBreakpoint(gSources.values[0], 5), aBreakpointClient,
|
||||
"getBreakpoint(locations[0], 5) returns the correct breakpoint");
|
||||
|
||||
@ -229,7 +218,7 @@ function test()
|
||||
is(aEvent.added[0].line, 4, "editor breakpoint line is correct");
|
||||
|
||||
is(gEditor.getBreakpoints().length, 1,
|
||||
"editor.getBreakpoints().length is correct");
|
||||
"editor.getBreakpoints().length is correct");
|
||||
}
|
||||
|
||||
function onEditorTextChanged()
|
||||
|
@ -27,54 +27,52 @@ function test() {
|
||||
}]);
|
||||
}
|
||||
|
||||
let testCommands = function(dbg, cmd) {
|
||||
// Wait for the initial resume...
|
||||
dbg._controller.activeThread.addOneTimeListener("resumed", function() {
|
||||
info("Starting tests");
|
||||
// Wait for the initial resume...
|
||||
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
|
||||
info("Starting tests");
|
||||
|
||||
let contentDoc = content.window.document;
|
||||
let output = contentDoc.querySelector("input[type=text]");
|
||||
let btnDoit = contentDoc.querySelector("input[type=button]");
|
||||
let contentDoc = content.window.document;
|
||||
let output = contentDoc.querySelector("input[type=text]");
|
||||
let btnDoit = contentDoc.querySelector("input[type=button]");
|
||||
|
||||
helpers.audit(options, [{
|
||||
setup: "dbg list",
|
||||
exec: { output: /browser_dbg_cmd.html/ }
|
||||
}]);
|
||||
helpers.audit(options, [{
|
||||
setup: "dbg list",
|
||||
exec: { output: /browser_dbg_cmd.html/ }
|
||||
}]);
|
||||
|
||||
cmd("dbg interrupt", function() {
|
||||
ok(true, "debugger is paused");
|
||||
dbg._controller.activeThread.addOneTimeListener("resumed", function() {
|
||||
ok(true, "debugger continued");
|
||||
dbg._controller.activeThread.addOneTimeListener("paused", function() {
|
||||
cmd("dbg interrupt", function() {
|
||||
ok(true, "debugger is paused");
|
||||
dbg._controller.activeThread.addOneTimeListener("resumed", function() {
|
||||
ok(true, "debugger continued");
|
||||
dbg._controller.activeThread.addOneTimeListener("paused", function() {
|
||||
cmd("dbg step in", function() {
|
||||
cmd("dbg step in", function() {
|
||||
cmd("dbg step in", function() {
|
||||
cmd("dbg step in", function() {
|
||||
is(output.value, "step in", "debugger stepped in");
|
||||
cmd("dbg step over", function() {
|
||||
is(output.value, "step over", "debugger stepped over");
|
||||
cmd("dbg step out", function() {
|
||||
is(output.value, "step out", "debugger stepped out");
|
||||
is(output.value, "step in", "debugger stepped in");
|
||||
cmd("dbg step over", function() {
|
||||
is(output.value, "step over", "debugger stepped over");
|
||||
cmd("dbg step out", function() {
|
||||
is(output.value, "step out", "debugger stepped out");
|
||||
cmd("dbg continue", function() {
|
||||
cmd("dbg continue", function() {
|
||||
cmd("dbg continue", function() {
|
||||
is(output.value, "dbg continue", "debugger continued");
|
||||
is(output.value, "dbg continue", "debugger continued");
|
||||
|
||||
helpers.audit(options, [{
|
||||
setup: "dbg close",
|
||||
completed: false,
|
||||
exec: { output: "" }
|
||||
}]);
|
||||
helpers.audit(options, [{
|
||||
setup: "dbg close",
|
||||
completed: false,
|
||||
exec: { output: "" }
|
||||
}]);
|
||||
|
||||
let toolbox = gDevTools.getToolbox(options.target);
|
||||
if (!toolbox) {
|
||||
let toolbox = gDevTools.getToolbox(options.target);
|
||||
if (!toolbox) {
|
||||
ok(true, "Debugger was closed.");
|
||||
deferred.resolve();
|
||||
} else {
|
||||
toolbox.on("destroyed", function () {
|
||||
ok(true, "Debugger was closed.");
|
||||
deferred.resolve();
|
||||
} else {
|
||||
toolbox.on("destroyed", function () {
|
||||
ok(true, "Debugger was closed.");
|
||||
deferred.resolve();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -82,22 +80,16 @@ function test() {
|
||||
});
|
||||
});
|
||||
});
|
||||
EventUtils.sendMouseEvent({type:"click"}, btnDoit);
|
||||
});
|
||||
|
||||
helpers.audit(options, [{
|
||||
setup: "dbg continue",
|
||||
exec: { output: "" }
|
||||
}]);
|
||||
EventUtils.sendMouseEvent({type:"click"}, btnDoit);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
if (dbg._controller.activeThread) {
|
||||
testCommands(dbg, cmd);
|
||||
} else {
|
||||
dbg.once("connected", testCommands.bind(null, dbg, cmd));
|
||||
}
|
||||
helpers.audit(options, [{
|
||||
setup: "dbg continue",
|
||||
exec: { output: "" }
|
||||
}]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -48,20 +48,19 @@ function test() {
|
||||
openDone.then(function(toolbox) {
|
||||
let dbg = toolbox.getCurrentPanel();
|
||||
ok(dbg, "DebuggerPanel exists");
|
||||
dbg.once("connected", function() {
|
||||
// Wait for the initial resume...
|
||||
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
|
||||
dbg._view.Variables.lazyEmpty = false;
|
||||
|
||||
client = dbg.panelWin.gClient;
|
||||
client.activeThread.addOneTimeListener("framesadded", function() {
|
||||
line0 = '' + options.window.wrappedJSObject.line0;
|
||||
deferred.resolve();
|
||||
});
|
||||
// Wait for the initial resume...
|
||||
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
|
||||
info("Starting tests");
|
||||
|
||||
// Trigger newScript notifications using eval.
|
||||
content.wrappedJSObject.firstCall();
|
||||
client = dbg.panelWin.gClient;
|
||||
client.activeThread.addOneTimeListener("framesadded", function() {
|
||||
line0 = '' + options.window.wrappedJSObject.line0;
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
// Trigger newScript notifications using eval.
|
||||
content.wrappedJSObject.firstCall();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -13,9 +13,15 @@
|
||||
<body>
|
||||
<p>Peanut butter jelly time!</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
function inline() {
|
||||
}
|
||||
<script type="text/javascript;version=1.8">
|
||||
function inline() {}
|
||||
let arrow = () => {}
|
||||
|
||||
let foo = bar => {}
|
||||
let foo2 = bar2 = baz2 => 42;
|
||||
|
||||
setTimeout((foo, bar, baz) => {});
|
||||
setTimeout((foo, bar, baz) => 42);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
@ -83,7 +83,11 @@ function htmlSearch(callback) {
|
||||
executeSoon(function() {
|
||||
let expectedResults = [
|
||||
["inline", "-02.html", "", 16, 15],
|
||||
]
|
||||
["arrow", "-02.html", "", 17, 10],
|
||||
["foo", "-02.html", "", 19, 10],
|
||||
["foo2", "-02.html", "", 20, 10],
|
||||
["bar2", "-02.html", "", 20, 17]
|
||||
];
|
||||
|
||||
for (let [label, value, description, line, col] of expectedResults) {
|
||||
is(gFilteredFunctions.selectedItem.label,
|
||||
@ -118,7 +122,7 @@ function htmlSearch(callback) {
|
||||
}
|
||||
});
|
||||
|
||||
write("@inline");
|
||||
write("@");
|
||||
}
|
||||
|
||||
function firstSearch(callback) {
|
||||
@ -148,7 +152,7 @@ function firstSearch(callback) {
|
||||
["a_test", "-01.js", "foo.sub.sub", 31, 6],
|
||||
["n_test" + s + "z", "-01.js", "foo.sub.sub", 33, 6],
|
||||
["test_SAME_NAME", "-01.js", "foo.sub.sub.sub", 36, 8]
|
||||
]
|
||||
];
|
||||
|
||||
for (let [label, value, description, line, col] of expectedResults) {
|
||||
is(gFilteredFunctions.selectedItem.label,
|
||||
@ -213,7 +217,7 @@ function secondSearch(callback) {
|
||||
["x", "-02.js", "", 19, 31],
|
||||
["y", "-02.js", "", 19, 40],
|
||||
["z", "-02.js", "", 19, 49]
|
||||
]
|
||||
];
|
||||
|
||||
for (let [label, value, description, line, col] of expectedResults) {
|
||||
is(gFilteredFunctions.selectedItem.label,
|
||||
|
@ -156,12 +156,10 @@ function wait_for_connect_and_resume(aOnDebugging, aTab) {
|
||||
|
||||
gDevTools.showToolbox(target, "jsdebugger").then(function(toolbox) {
|
||||
let dbg = toolbox.getCurrentPanel();
|
||||
dbg.once("connected", function dbgConnected() {
|
||||
|
||||
// Wait for the initial resume...
|
||||
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
|
||||
aOnDebugging();
|
||||
});
|
||||
// Wait for the initial resume...
|
||||
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
|
||||
aOnDebugging();
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -176,16 +174,16 @@ function debug_tab_pane(aURL, aOnDebugging, aBeforeTabAdded) {
|
||||
let debuggee = gBrowser.selectedTab.linkedBrowser.contentWindow.wrappedJSObject;
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
|
||||
info("Opening Debugger");
|
||||
gDevTools.showToolbox(target, "jsdebugger").then(function(toolbox) {
|
||||
let dbg = toolbox.getCurrentPanel();
|
||||
dbg.once("connected", function() {
|
||||
|
||||
// Wait for the initial resume...
|
||||
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
|
||||
dbg._view.Variables.lazyEmpty = false;
|
||||
dbg._view.Variables.lazyAppend = false;
|
||||
aOnDebugging(tab, debuggee, dbg);
|
||||
});
|
||||
// Wait for the initial resume...
|
||||
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
|
||||
info("Debugger has started");
|
||||
dbg._view.Variables.lazyEmpty = false;
|
||||
dbg._view.Variables.lazyAppend = false;
|
||||
aOnDebugging(tab, debuggee, dbg);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -200,17 +198,16 @@ function debug_remote(aURL, aOnDebugging, aBeforeTabAdded) {
|
||||
let tab = addTab(aURL, function() {
|
||||
let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
|
||||
|
||||
info("Opening Remote Debugger");
|
||||
let win = DebuggerUI.toggleRemoteDebugger();
|
||||
win._dbgwin.addEventListener("Debugger:Connected", function dbgConnected() {
|
||||
win._dbgwin.removeEventListener("Debugger:Connected", dbgConnected, true);
|
||||
|
||||
// Wait for the initial resume...
|
||||
win.panelWin.gClient.addOneTimeListener("resumed", function() {
|
||||
win._dbgwin.DebuggerView.Variables.lazyEmpty = false;
|
||||
win._dbgwin.DebuggerView.Variables.lazyAppend = false;
|
||||
aOnDebugging(tab, debuggee, win);
|
||||
});
|
||||
}, true);
|
||||
// Wait for the initial resume...
|
||||
win.panelWin.gClient.addOneTimeListener("resumed", function() {
|
||||
info("Remote Debugger has started");
|
||||
win._dbgwin.DebuggerView.Variables.lazyEmpty = false;
|
||||
win._dbgwin.DebuggerView.Variables.lazyAppend = false;
|
||||
aOnDebugging(tab, debuggee, win);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -219,10 +216,10 @@ function debug_chrome(aURL, aOnClosing, aOnDebugging) {
|
||||
let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
|
||||
|
||||
info("Opening Browser Debugger");
|
||||
DebuggerUI.toggleChromeDebugger(aOnClosing, function dbgRan(process) {
|
||||
info("Browser Debugger has started");
|
||||
let win = DebuggerUI.toggleChromeDebugger(aOnClosing, function(process) {
|
||||
|
||||
// Wait for the remote debugging process to start...
|
||||
// The remote debugging process has started...
|
||||
info("Browser Debugger has started");
|
||||
aOnDebugging(tab, debuggee, process);
|
||||
});
|
||||
});
|
||||
|
@ -142,7 +142,7 @@ ProfilerConnection.prototype = {
|
||||
*/
|
||||
function ProfilerController(target) {
|
||||
this.profiler = new ProfilerConnection(target.client);
|
||||
this.pool = {};
|
||||
this.profiles = new Map();
|
||||
|
||||
// Chrome debugging targets have already obtained a reference to the
|
||||
// profiler actor.
|
||||
@ -210,12 +210,14 @@ ProfilerController.prototype = {
|
||||
* argument: an error object (may be null).
|
||||
*/
|
||||
start: function PC_start(name, cb) {
|
||||
if (this.pool[name]) {
|
||||
if (this.profiles.has(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let profile = this.pool[name] = makeProfile(name);
|
||||
let profiler = this.profiler;
|
||||
let profile = makeProfile(name);
|
||||
this.profiles.set(name, profile);
|
||||
|
||||
|
||||
// If profile is already running, no need to do anything.
|
||||
if (this.isProfileRecording(profile)) {
|
||||
@ -251,15 +253,15 @@ ProfilerController.prototype = {
|
||||
*/
|
||||
stop: function PC_stop(name, cb) {
|
||||
let profiler = this.profiler;
|
||||
let profile = this.pool[name];
|
||||
let profile = this.profiles.get(name);
|
||||
|
||||
if (!profile || !this.isProfileRecording(profile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let isRecording = function () {
|
||||
for (let name in this.pool) {
|
||||
if (this.isProfileRecording(this.pool[name])) {
|
||||
for (let [ name, profile ] of this.profiles) {
|
||||
if (this.isProfileRecording(profile)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -44,15 +44,19 @@ XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
* @param ProfilerPanel panel
|
||||
* A reference to the container panel.
|
||||
*/
|
||||
function ProfileUI(uid, panel) {
|
||||
function ProfileUI(uid, name, panel) {
|
||||
let doc = panel.document;
|
||||
let win = panel.window;
|
||||
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
this.isReady = false;
|
||||
this.isStarted = false;
|
||||
this.isFinished = false;
|
||||
|
||||
this.panel = panel;
|
||||
this.uid = uid;
|
||||
this.name = name;
|
||||
|
||||
this.iframe = doc.createElement("iframe");
|
||||
this.iframe.setAttribute("flex", "1");
|
||||
@ -70,9 +74,6 @@ function ProfileUI(uid, panel) {
|
||||
return;
|
||||
}
|
||||
|
||||
let label = doc.querySelector("li#profile-" + this.uid + " > h1");
|
||||
let name = label.textContent.replace(/\s\*$/, "");
|
||||
|
||||
switch (event.data.status) {
|
||||
case "loaded":
|
||||
if (this.panel._runningUid !== null) {
|
||||
@ -87,26 +88,10 @@ function ProfileUI(uid, panel) {
|
||||
this.emit("ready");
|
||||
break;
|
||||
case "start":
|
||||
// Start profiling and, once started, notify the underlying page
|
||||
// so that it could update the UI. Also, once started, we add a
|
||||
// star to the profile name to indicate which profile is currently
|
||||
// running.
|
||||
this.panel.startProfiling(name, function onStart() {
|
||||
label.textContent = name + " *";
|
||||
this.panel.broadcast(this.uid, {task: "onStarted"});
|
||||
this.emit("started");
|
||||
}.bind(this));
|
||||
|
||||
this.start();
|
||||
break;
|
||||
case "stop":
|
||||
// Stop profiling and, once stopped, notify the underlying page so
|
||||
// that it could update the UI and remove a star from the profile
|
||||
// name.
|
||||
this.panel.stopProfiling(name, function onStop() {
|
||||
label.textContent = name;
|
||||
this.panel.broadcast(this.uid, {task: "onStopped"});
|
||||
this.emit("stopped");
|
||||
}.bind(this));
|
||||
this.stop();
|
||||
break;
|
||||
case "disabled":
|
||||
this.emit("disabled");
|
||||
@ -169,6 +154,56 @@ ProfileUI.prototype = {
|
||||
poll();
|
||||
},
|
||||
|
||||
/**
|
||||
* Update profile's label in the sidebar.
|
||||
*
|
||||
* @param string text
|
||||
* New text for the label.
|
||||
*/
|
||||
updateLabel: function PUI_udpateLabel(text) {
|
||||
let doc = this.panel.document;
|
||||
let label = doc.querySelector("li#profile-" + this.uid + "> h1");
|
||||
label.textContent = text;
|
||||
},
|
||||
|
||||
/**
|
||||
* Start profiling and, once started, notify the underlying page
|
||||
* so that it could update the UI. Also, once started, we add a
|
||||
* star to the profile name to indicate which profile is currently
|
||||
* running.
|
||||
*/
|
||||
start: function PUI_start() {
|
||||
if (this.isStarted || this.isFinished) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.panel.startProfiling(this.name, function onStart() {
|
||||
this.isStarted = true;
|
||||
this.updateLabel(this.name + " *");
|
||||
this.panel.broadcast(this.uid, {task: "onStarted"});
|
||||
this.emit("started");
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Stop profiling and, once stopped, notify the underlying page so
|
||||
* that it could update the UI and remove a star from the profile
|
||||
* name.
|
||||
*/
|
||||
stop: function PUI_stop() {
|
||||
if (!this.isStarted || this.isFinished) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.panel.stopProfiling(this.name, function onStop() {
|
||||
this.isStarted = false;
|
||||
this.isFinished = true;
|
||||
this.updateLabel(this.name);
|
||||
this.panel.broadcast(this.uid, {task: "onStopped"});
|
||||
this.emit("stopped");
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroys the ProfileUI instance.
|
||||
*/
|
||||
@ -276,7 +311,9 @@ ProfilerPanel.prototype = {
|
||||
|
||||
this.controller.connect(function onConnect() {
|
||||
let create = this.document.getElementById("profiler-create");
|
||||
create.addEventListener("click", this.createProfile.bind(this), false);
|
||||
create.addEventListener("click", function (ev) {
|
||||
this.createProfile()
|
||||
}.bind(this), false);
|
||||
create.removeAttribute("disabled");
|
||||
|
||||
let profile = this.createProfile();
|
||||
@ -303,13 +340,21 @@ ProfilerPanel.prototype = {
|
||||
* the newly created profile, they have do to switch
|
||||
* explicitly.
|
||||
*
|
||||
* @param string name
|
||||
* (optional) name of the new profile
|
||||
*
|
||||
* @return ProfilerPanel
|
||||
*/
|
||||
createProfile: function PP_addProfile() {
|
||||
createProfile: function PP_createProfile(name) {
|
||||
if (name && this.getProfileByName(name)) {
|
||||
return this.getProfileByName(name);
|
||||
}
|
||||
|
||||
let uid = ++this._uid;
|
||||
let list = this.document.getElementById("profiles-list");
|
||||
let item = this.document.createElement("li");
|
||||
let wrap = this.document.createElement("h1");
|
||||
name = name || L10N.getFormatStr("profiler.profileName", [uid]);
|
||||
|
||||
item.setAttribute("id", "profile-" + uid);
|
||||
item.setAttribute("data-uid", uid);
|
||||
@ -318,12 +363,12 @@ ProfilerPanel.prototype = {
|
||||
}.bind(this), false);
|
||||
|
||||
wrap.className = "profile-name";
|
||||
wrap.textContent = L10N.getFormatStr("profiler.profileName", [uid]);
|
||||
wrap.textContent = name;
|
||||
|
||||
item.appendChild(wrap);
|
||||
list.appendChild(item);
|
||||
|
||||
let profile = new ProfileUI(uid, this);
|
||||
let profile = new ProfileUI(uid, name, this);
|
||||
this.profiles.set(uid, profile);
|
||||
|
||||
this.emit("profileCreated", uid);
|
||||
@ -424,6 +469,40 @@ ProfilerPanel.prototype = {
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Lookup an individual profile by its name.
|
||||
*
|
||||
* @param string name name of the profile
|
||||
* @return profile object or null
|
||||
*/
|
||||
getProfileByName: function PP_getProfileByName(name) {
|
||||
if (!this.profiles) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (let [ uid, profile ] of this.profiles) {
|
||||
if (profile.name === name) {
|
||||
return profile;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Lookup an individual profile by its UID.
|
||||
*
|
||||
* @param number uid UID of the profile
|
||||
* @return profile object or null
|
||||
*/
|
||||
getProfileByUID: function PP_getProfileByUID(uid) {
|
||||
if (!this.profiles) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.profiles.get(uid) || null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Broadcast messages to all Cleopatra instances.
|
||||
*
|
||||
|
211
browser/devtools/profiler/cmd-profiler.jsm
Normal file
211
browser/devtools/profiler/cmd-profiler.jsm
Normal file
@ -0,0 +1,211 @@
|
||||
/* 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/. */
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
this.EXPORTED_SYMBOLS = [];
|
||||
|
||||
Cu.import("resource:///modules/devtools/gcli.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/Require.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
|
||||
"resource:///modules/devtools/gDevTools.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "console",
|
||||
"resource://gre/modules/devtools/Console.jsm");
|
||||
|
||||
var Promise = require('util/promise');
|
||||
|
||||
/*
|
||||
* 'profiler' command. Doesn't do anything.
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "profiler",
|
||||
description: gcli.lookup("profilerDesc"),
|
||||
manual: gcli.lookup("profilerManual")
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler open' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "profiler open",
|
||||
description: gcli.lookup("profilerOpenDesc"),
|
||||
params: [],
|
||||
|
||||
exec: function (args, context) {
|
||||
return gDevTools.showToolbox(context.environment.target, "jsprofiler")
|
||||
.then(function () null);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler close' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "profiler close",
|
||||
description: gcli.lookup("profilerCloseDesc"),
|
||||
params: [],
|
||||
|
||||
exec: function (args, context) {
|
||||
return gDevTools.closeToolbox(context.environment.target)
|
||||
.then(function () null);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler start' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "profiler start",
|
||||
description: gcli.lookup("profilerStartDesc"),
|
||||
returnType: "string",
|
||||
|
||||
params: [
|
||||
{
|
||||
name: "name",
|
||||
type: "string"
|
||||
}
|
||||
],
|
||||
|
||||
exec: function (args, context) {
|
||||
function start() {
|
||||
let name = args.name;
|
||||
let panel = getPanel(context, "jsprofiler");
|
||||
let profile = panel.getProfileByName(name) || panel.createProfile(name);
|
||||
|
||||
if (profile.isStarted) {
|
||||
throw gcli.lookup("profilerAlreadyStarted");
|
||||
}
|
||||
|
||||
if (profile.isFinished) {
|
||||
throw gcli.lookup("profilerAlradyFinished");
|
||||
}
|
||||
|
||||
panel.switchToProfile(profile, function () profile.start());
|
||||
return gcli.lookup("profilerStarting");
|
||||
}
|
||||
|
||||
return gDevTools.showToolbox(context.environment.target, "jsprofiler")
|
||||
.then(start);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler stop' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "profiler stop",
|
||||
description: gcli.lookup("profilerStopDesc"),
|
||||
returnType: "string",
|
||||
|
||||
params: [
|
||||
{
|
||||
name: "name",
|
||||
type: "string"
|
||||
}
|
||||
],
|
||||
|
||||
exec: function (args, context) {
|
||||
function stop() {
|
||||
let panel = getPanel(context, "jsprofiler");
|
||||
let profile = panel.getProfileByName(args.name);
|
||||
|
||||
if (!profile) {
|
||||
throw gcli.lookup("profilerNotFound");
|
||||
}
|
||||
|
||||
if (profile.isFinished) {
|
||||
throw gcli.lookup("profilerAlreadyFinished");
|
||||
}
|
||||
|
||||
if (!profile.isStarted) {
|
||||
throw gcli.lookup("profilerNotStarted");
|
||||
}
|
||||
|
||||
panel.switchToProfile(profile, function () profile.stop());
|
||||
return gcli.lookup("profilerStopping");
|
||||
}
|
||||
|
||||
return gDevTools.showToolbox(context.environment.target, "jsprofiler")
|
||||
.then(stop);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler list' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "profiler list",
|
||||
description: gcli.lookup("profilerListDesc"),
|
||||
returnType: "dom",
|
||||
params: [],
|
||||
|
||||
exec: function (args, context) {
|
||||
let panel = getPanel(context, "jsprofiler");
|
||||
|
||||
if (!panel) {
|
||||
throw gcli.lookup("profilerNotReady");
|
||||
}
|
||||
|
||||
let doc = panel.document;
|
||||
let div = createXHTMLElement(doc, "div");
|
||||
let ol = createXHTMLElement(doc, "ol");
|
||||
|
||||
for ([ uid, profile] of panel.profiles) {
|
||||
let li = createXHTMLElement(doc, "li");
|
||||
li.textContent = profile.name;
|
||||
if (profile.isStarted) {
|
||||
li.textContent += " *";
|
||||
}
|
||||
ol.appendChild(li);
|
||||
}
|
||||
|
||||
div.appendChild(ol);
|
||||
return div;
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler show' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "profiler show",
|
||||
description: gcli.lookup("profilerShowDesc"),
|
||||
|
||||
params: [
|
||||
{
|
||||
name: "name",
|
||||
type: "string"
|
||||
}
|
||||
],
|
||||
|
||||
exec: function (args, context) {
|
||||
let panel = getPanel(context, "jsprofiler");
|
||||
|
||||
if (!panel) {
|
||||
throw gcli.lookup("profilerNotReady");
|
||||
}
|
||||
|
||||
let profile = panel.getProfileByName(args.name);
|
||||
if (!profile) {
|
||||
throw gcli.lookup("profilerNotFound");
|
||||
}
|
||||
|
||||
panel.switchToProfile(profile);
|
||||
}
|
||||
});
|
||||
|
||||
function getPanel(context, id) {
|
||||
if (context == null) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let toolbox = gDevTools.getToolbox(context.environment.target);
|
||||
return toolbox == null ? undefined : toolbox.getPanel(id);
|
||||
}
|
||||
|
||||
function createXHTMLElement(document, tagname) {
|
||||
return document.createElementNS("http://www.w3.org/1999/xhtml", tagname);
|
||||
}
|
@ -14,6 +14,7 @@ MOCHITEST_BROWSER_TESTS = \
|
||||
browser_profiler_profiles.js \
|
||||
browser_profiler_remote.js \
|
||||
browser_profiler_bug_834878_source_buttons.js \
|
||||
browser_profiler_cmd.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
|
125
browser/devtools/profiler/test/browser_profiler_cmd.js
Normal file
125
browser/devtools/profiler/test/browser_profiler_cmd.js
Normal file
@ -0,0 +1,125 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const URL = "data:text/html;charset=utf8,<p>JavaScript Profiler test</p>";
|
||||
|
||||
let gTarget, gPanel, gOptions;
|
||||
|
||||
function cmd(typed, expected="") {
|
||||
helpers.audit(gOptions, [{
|
||||
setup: typed,
|
||||
exec: { output: expected }
|
||||
}]);
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
helpers.addTabWithToolbar(URL, function (options) {
|
||||
gOptions = options;
|
||||
gTarget = options.target;
|
||||
|
||||
return gDevTools.showToolbox(options.target, "jsprofiler")
|
||||
.then(setupGlobals)
|
||||
.then(testProfilerStart)
|
||||
.then(testProfilerList)
|
||||
.then(testProfilerStop)
|
||||
.then(testProfilerClose)
|
||||
}).then(finishUp);
|
||||
}
|
||||
|
||||
function setupGlobals() {
|
||||
let deferred = Promise.defer();
|
||||
gPanel = gDevTools.getToolbox(gTarget).getPanel("jsprofiler");
|
||||
deferred.resolve();
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function testProfilerStart() {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
gPanel.once("started", function () {
|
||||
is(gPanel.profiles.size, 2, "There are two profiles");
|
||||
ok(!gPanel.getProfileByName("Profile 1").isStarted, "Profile 1 wasn't started");
|
||||
ok(gPanel.getProfileByName("Profile 2").isStarted, "Profile 2 was started");
|
||||
cmd('profiler start "Profile 2"', "This profile has already been started");
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
cmd("profiler start", "Starting...");
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function testProfilerList() {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
cmd("profiler list", /^.*Profile\s1.*Profile\s2\s\*.*$/);
|
||||
deferred.resolve();
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function testProfilerStop() {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
gPanel.once("stopped", function () {
|
||||
ok(!gPanel.getProfileByName("Profile 2").isStarted, "Profile 2 was stopped");
|
||||
ok(gPanel.getProfileByName("Profile 2").isFinished, "Profile 2 was stopped");
|
||||
cmd('profiler stop "Profile 2"', "This profile has already been completed. " +
|
||||
"Use 'profile show' command to see its results");
|
||||
cmd('profiler stop "Profile 1"', "This profile has not been started yet. " +
|
||||
"Use 'profile start' to start profliling");
|
||||
cmd('profiler stop "invalid"', "Profile not found")
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
cmd('profiler stop "Profile 2"', "Stopping...");
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function testProfilerShow() {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
is(gPanel.getProfileByName("Profile 2").uid, gPanel.activeProfile.uid,
|
||||
"Profile 2 is active");
|
||||
|
||||
gPanel.once("profileSwitched", function () {
|
||||
is(gPanel.getProfileByName("Profile 1").uid, gPanel.activeProfile.uid,
|
||||
"Profile 1 is active");
|
||||
cmd('profile show "invalid"', "Profile not found");
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
cmd('profile show "Profile 1"');
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function testProfilerClose() {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
helpers.audit(gOptions, [{
|
||||
setup: "profiler close",
|
||||
completed: false,
|
||||
exec: { output: "" }
|
||||
}]);
|
||||
|
||||
let toolbox = gDevTools.getToolbox(gOptions.target);
|
||||
if (!toolbox) {
|
||||
ok(true, "Profiler was closed.");
|
||||
deferred.resolve();
|
||||
} else {
|
||||
toolbox.on("destroyed", function () {
|
||||
ok(true, "Profiler was closed.");
|
||||
deferred.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function finishUp() {
|
||||
gTarget = null;
|
||||
gPanel = null;
|
||||
gOptions = null;
|
||||
finish();
|
||||
}
|
@ -37,6 +37,26 @@ function onProfileCreated(name, uid) {
|
||||
}
|
||||
|
||||
function onProfileSwitched(name, uid) {
|
||||
gPanel.once("profileCreated", onNamedProfileCreated);
|
||||
gPanel.once("profileSwitched", onNamedProfileSwitched);
|
||||
|
||||
ok(gPanel.activeProfile.uid === uid, "Switched to a new profile");
|
||||
gPanel.createProfile("Custom Profile");
|
||||
}
|
||||
|
||||
function onNamedProfileCreated(name, uid) {
|
||||
is(gPanel.profiles.size, 3, "There are three profiles now");
|
||||
is(gPanel.getProfileByUID(uid).name, "Custom Profile", "Name is correct");
|
||||
|
||||
let label = gPanel.document.querySelector("li#profile-" + uid + "> h1");
|
||||
is(label.textContent, "Custom Profile", "Name is correct on the label");
|
||||
|
||||
let btn = gPanel.document.getElementById("profile-" + uid);
|
||||
ok(btn, "Profile item has been added to the sidebar");
|
||||
btn.click();
|
||||
}
|
||||
|
||||
function onNamedProfileSwitched(name, uid) {
|
||||
ok(gPanel.activeProfile.uid === uid, "Switched to a new profile");
|
||||
|
||||
tearDown(gTab, function onTearDown() {
|
||||
|
@ -14,7 +14,12 @@ let gDevTools = temp.gDevTools;
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm", temp);
|
||||
let DebuggerServer = temp.DebuggerServer;
|
||||
|
||||
// Import the GCLI test helper
|
||||
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
|
||||
Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
helpers = null;
|
||||
Services.prefs.clearUserPref(PROFILER_ENABLED);
|
||||
Services.prefs.clearUserPref(REMOTE_ENABLED);
|
||||
DebuggerServer.destroy();
|
||||
|
@ -264,6 +264,34 @@ SyntaxTree.prototype = {
|
||||
inferredLocation: inferredLocation
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback invoked for each arrow expression node.
|
||||
* @param Node aNode
|
||||
*/
|
||||
onArrowExpression: function STW_onArrowExpression(aNode) {
|
||||
let parent = aNode._parent;
|
||||
let inferredName, inferredChain, inferredLocation;
|
||||
|
||||
// Infer the function's name from an enclosing syntax tree node.
|
||||
let inferredInfo = ParserHelpers.inferFunctionExpressionInfo(aNode);
|
||||
inferredName = inferredInfo.name;
|
||||
inferredChain = inferredInfo.chain;
|
||||
inferredLocation = inferredInfo.loc;
|
||||
|
||||
// Current node may be part of a larger assignment expression stack.
|
||||
if (parent.type == "AssignmentExpression") {
|
||||
this.onFunctionExpression(parent);
|
||||
}
|
||||
|
||||
if (inferredName && inferredName.toLowerCase().contains(lowerCaseToken)) {
|
||||
store.push({
|
||||
inferredName: inferredName,
|
||||
inferredChain: inferredChain,
|
||||
inferredLocation: inferredLocation
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -1528,6 +1556,45 @@ let SyntaxTreeVisitor = {
|
||||
this[aNode.body.type](aNode.body, aNode, aCallbacks);
|
||||
},
|
||||
|
||||
/**
|
||||
* An arrow expression.
|
||||
*
|
||||
* interface ArrowExpression <: Function, Expression {
|
||||
* type: "ArrowExpression";
|
||||
* params: [ Pattern ];
|
||||
* defaults: [ Expression ];
|
||||
* rest: Identifier | null;
|
||||
* body: BlockStatement | Expression;
|
||||
* generator: boolean;
|
||||
* expression: boolean;
|
||||
* }
|
||||
*/
|
||||
ArrowExpression: function STV_ArrowExpression(aNode, aParent, aCallbacks) {
|
||||
aNode._parent = aParent;
|
||||
|
||||
if (this.break) {
|
||||
return;
|
||||
}
|
||||
if (aCallbacks.onNode) {
|
||||
if (aCallbacks.onNode(aNode, aParent) === false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (aCallbacks.onArrowExpression) {
|
||||
aCallbacks.onArrowExpression(aNode);
|
||||
}
|
||||
for (let param of aNode.params) {
|
||||
this[param.type](param, aNode, aCallbacks);
|
||||
}
|
||||
for (let _default of aNode.defaults) {
|
||||
this[_default.type](_default, aNode, aCallbacks);
|
||||
}
|
||||
if (aNode.rest) {
|
||||
this[aNode.rest.type](aNode.rest, aNode, aCallbacks);
|
||||
}
|
||||
this[aNode.body.type](aNode.body, aNode, aCallbacks);
|
||||
},
|
||||
|
||||
/**
|
||||
* A sequence expression, i.e., a comma-separated sequence of expressions.
|
||||
*
|
||||
|
@ -555,6 +555,16 @@ StyleEditorChrome.prototype = {
|
||||
editor.enableStyleSheet(editor.styleSheet.disabled);
|
||||
});
|
||||
|
||||
wire(aSummary, ".stylesheet-name", {
|
||||
events: {
|
||||
"keypress": function onStylesheetNameActivate(aEvent) {
|
||||
if (aEvent.keyCode == aEvent.DOM_VK_RETURN) {
|
||||
this._view.activeSummary = aSummary;
|
||||
}
|
||||
}.bind(this)
|
||||
}
|
||||
});
|
||||
|
||||
wire(aSummary, ".stylesheet-saveButton", function onSaveButton(aEvent) {
|
||||
aEvent.stopPropagation();
|
||||
aEvent.target.blur();
|
||||
|
@ -80,13 +80,13 @@
|
||||
title="&visibilityToggle.tooltip;"
|
||||
accesskey="&saveButton.accesskey;"></a>
|
||||
<hgroup class="stylesheet-info">
|
||||
<h1><a class="stylesheet-name" href="#"><xul:label crop="start"/></a></h1>
|
||||
<h1><a class="stylesheet-name" tabindex="0"><xul:label crop="start"/></a></h1>
|
||||
<div class="stylesheet-more">
|
||||
<h3 class="stylesheet-title"></h3>
|
||||
<h3 class="stylesheet-rule-count"></h3>
|
||||
<h3 class="stylesheet-error-message"></h3>
|
||||
<xul:spacer/>
|
||||
<h3><a class="stylesheet-saveButton" href="#"
|
||||
<h3><a class="stylesheet-saveButton"
|
||||
title="&saveButton.tooltip;"
|
||||
accesskey="&saveButton.accesskey;">&saveButton.label;</a></h3>
|
||||
</div>
|
||||
|
@ -29,6 +29,7 @@ _BROWSER_TEST_FILES = \
|
||||
browser_styleeditor_sv_keynav.js \
|
||||
browser_styleeditor_sv_resize.js \
|
||||
browser_styleeditor_bug_826982_location_changed.js \
|
||||
browser_styleeditor_bug_851132_middle_click.js \
|
||||
head.js \
|
||||
helpers.js \
|
||||
four.html \
|
||||
|
@ -0,0 +1,60 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const TESTCASE_URI = TEST_BASE + "four.html";
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
addTabAndLaunchStyleEditorChromeWhenLoaded(function (aChrome) {
|
||||
run(aChrome);
|
||||
});
|
||||
|
||||
content.location = TESTCASE_URI;
|
||||
}
|
||||
|
||||
let gSEChrome, timeoutID;
|
||||
|
||||
function run(aChrome) {
|
||||
gSEChrome = aChrome;
|
||||
gBrowser.tabContainer.addEventListener("TabOpen", onTabAdded, false);
|
||||
aChrome.editors[0].addActionListener({onAttach: onEditor0Attach});
|
||||
aChrome.editors[1].addActionListener({onAttach: onEditor1Attach});
|
||||
}
|
||||
|
||||
function getStylesheetNameLinkFor(aEditor) {
|
||||
return gSEChrome.getSummaryElementForEditor(aEditor).querySelector(".stylesheet-name");
|
||||
}
|
||||
|
||||
function onEditor0Attach(aEditor) {
|
||||
waitForFocus(function () {
|
||||
// left mouse click should focus editor 1
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
getStylesheetNameLinkFor(gSEChrome.editors[1]),
|
||||
{button: 0},
|
||||
gChromeWindow);
|
||||
}, gChromeWindow);
|
||||
}
|
||||
|
||||
function onEditor1Attach(aEditor) {
|
||||
ok(aEditor.sourceEditor.hasFocus(),
|
||||
"left mouse click has given editor 1 focus");
|
||||
|
||||
// right mouse click should not open a new tab
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
getStylesheetNameLinkFor(gSEChrome.editors[2]),
|
||||
{button: 1},
|
||||
gChromeWindow);
|
||||
|
||||
setTimeout(finish, 0);
|
||||
}
|
||||
|
||||
function onTabAdded() {
|
||||
ok(false, "middle mouse click has opened a new tab");
|
||||
finish();
|
||||
}
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", onTabAdded, false);
|
||||
gSEChrome = null;
|
||||
});
|
@ -525,6 +525,9 @@
|
||||
@BINPATH@/components/TCPSocketParentIntermediary.js
|
||||
@BINPATH@/components/TCPSocket.manifest
|
||||
|
||||
@BINPATH@/components/AppProtocolHandler.js
|
||||
@BINPATH@/components/AppProtocolHandler.manifest
|
||||
|
||||
#ifdef MOZ_WEBRTC
|
||||
@BINPATH@/components/PeerConnection.js
|
||||
@BINPATH@/components/PeerConnection.manifest
|
||||
|
@ -1060,3 +1060,69 @@ paintflashingManual=Draw repainted areas in different colors
|
||||
# LOCALIZATION NOTE (paintflashingTooltip) A string displayed as the
|
||||
# tooltip of button in devtools toolbox which toggles paint flashing.
|
||||
paintflashingTooltip=Highlight painted area
|
||||
|
||||
# LOCALIZATION NOTE (profilerDesc) A very short string used to describe the
|
||||
# function of the profiler command.
|
||||
profilerDesc=Manage profiler
|
||||
|
||||
# LOCALIZATION NOTE (profilerManual) A longer description describing the
|
||||
# set of commands that control the profiler.
|
||||
profilerManual=Commands to start or stop a JavaScript profiler
|
||||
|
||||
# LOCALIZATION NOTE (profilerOpen) A very short string used to describe the function
|
||||
# of the profiler open command.
|
||||
profilerOpenDesc=Open the profiler
|
||||
|
||||
# LOCALIZATION NOTE (profilerClose) A very short string used to describe the function
|
||||
# of the profiler close command.
|
||||
profilerCloseDesc=Close the profiler
|
||||
|
||||
# LOCALIZATION NOTE (profilerStart) A very short string used to describe the function
|
||||
# of the profiler start command.
|
||||
profilerStartDesc=Start profiling
|
||||
|
||||
# LOCALIZATION NOTE (profilerStop) A very short string used to describe the function
|
||||
# of the profiler stop command.
|
||||
profilerStopDesc=Stop profiling
|
||||
|
||||
# LOCALIZATION NOTE (profilerList) A very short string used to describe the function
|
||||
# of the profiler list command.
|
||||
profilerListDesc=List all profiles
|
||||
|
||||
# LOCALIZATION NOTE (profilerShow) A very short string used to describe the function
|
||||
# of the profiler show command.
|
||||
profilerShowDesc=Show individual profile
|
||||
|
||||
# LOCALIZATION NOTE (profilerAlreadyStarted) A message that is displayed whenever
|
||||
# an operation cannot be completed because the profile in question has already
|
||||
# been started.
|
||||
profilerAlreadyStarted=This profile has already been started
|
||||
|
||||
# LOCALIZATION NOTE (profilerAlreadyFinished) A message that is displayed whenever
|
||||
# an operation cannot be completed because the profile in question has already
|
||||
# been finished. It also contains a hint to use the 'profile show' command to see
|
||||
# the profiling results.
|
||||
profilerAlreadyFinished=This profile has already been completed. Use 'profile show' command to see its results
|
||||
|
||||
# LOCALIZATION NOTE (profilerNotFound) A message that is displayed whenever
|
||||
# an operation cannot be completed because the profile in question could not be
|
||||
# found.
|
||||
profilerNotFound=Profile not found
|
||||
|
||||
# LOCALIZATION NOTE (profilerNotStarted) A message that is displayed whenever
|
||||
# an operation cannot be completed because the profile in question has not been
|
||||
# started yet. It also contains a hint to use the 'profile start' command to
|
||||
# start the profiler.
|
||||
profilerNotStarted=This profile has not been started yet. Use 'profile start' to start profliling
|
||||
|
||||
# LOCALIZATION NOTE (profilerStarting) A very short string that indicates that
|
||||
# we're starting the profiler.
|
||||
profilerStarting=Starting...
|
||||
|
||||
# LOCALIZATION NOTE (profilerStopping) A very short string that indicates that
|
||||
# we're stopping the profiler.
|
||||
profilerStopping=Stopping...
|
||||
|
||||
# LOCALIZATION NOTE (profilerNotReady) A message that is displayed whenever
|
||||
# an operation cannot be completed because the profiler has not been opened yet.
|
||||
profilerNotReady=For this command to work you need to open the profiler first
|
@ -10,4 +10,4 @@
|
||||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
22.0a1
|
||||
23.0a1
|
||||
|
@ -10,4 +10,4 @@
|
||||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
22.0a1
|
||||
23.0a1
|
||||
|
2
mobile/android/confvars.sh
Executable file → Normal file
2
mobile/android/confvars.sh
Executable file → Normal file
@ -5,7 +5,7 @@
|
||||
MOZ_APP_BASENAME=Fennec
|
||||
MOZ_APP_VENDOR=Mozilla
|
||||
|
||||
MOZ_APP_VERSION=22.0a1
|
||||
MOZ_APP_VERSION=23.0a1
|
||||
MOZ_APP_UA_NAME=Firefox
|
||||
|
||||
MOZ_BRANDING_DIRECTORY=mobile/android/branding/unofficial
|
||||
|
@ -10,7 +10,7 @@ VPATH := @srcdir@
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
# Definitions used by constants.js.
|
||||
weave_version := 1.24.0
|
||||
weave_version := 1.25.0
|
||||
weave_id := {340c2bbc-ce74-4362-90b5-7c26312808ef}
|
||||
|
||||
# Preprocess files.
|
||||
|
@ -298,6 +298,7 @@ LoginManager.prototype = {
|
||||
|
||||
switch (event.type) {
|
||||
case "DOMContentLoaded":
|
||||
event.target.removeEventListener(event.type, this, false);
|
||||
this._pwmgr._fillDocument(event.target);
|
||||
return;
|
||||
|
||||
|
@ -2234,6 +2234,9 @@ this.AddonManager = {
|
||||
OPTIONS_TYPE_INLINE: 2,
|
||||
// Options will be displayed in a new tab, if possible
|
||||
OPTIONS_TYPE_TAB: 3,
|
||||
// Same as OPTIONS_TYPE_INLINE, but no Preferences button will be shown.
|
||||
// Used to indicate that only non-interactive information will be shown.
|
||||
OPTIONS_TYPE_INLINE_INFO: 4,
|
||||
|
||||
// Constants for displayed or hidden options notifications
|
||||
// Options notification will be displayed
|
||||
|
@ -392,6 +392,7 @@ function UpdateParser(aId, aUpdateKey, aUrl, aObserver) {
|
||||
this.id = aId;
|
||||
this.updateKey = aUpdateKey;
|
||||
this.observer = aObserver;
|
||||
this.url = aUrl;
|
||||
|
||||
this.timer = Cc["@mozilla.org/timer;1"].
|
||||
createInstance(Ci.nsITimer);
|
||||
@ -408,7 +409,7 @@ function UpdateParser(aId, aUpdateKey, aUrl, aObserver) {
|
||||
try {
|
||||
this.request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
|
||||
createInstance(Ci.nsIXMLHttpRequest);
|
||||
this.request.open("GET", aUrl, true);
|
||||
this.request.open("GET", this.url, true);
|
||||
this.request.channel.notificationCallbacks = new CertUtils.BadCertHandler(!requireBuiltIn);
|
||||
this.request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
|
||||
this.request.overrideMimeType("text/xml");
|
||||
@ -428,6 +429,7 @@ UpdateParser.prototype = {
|
||||
observer: null,
|
||||
request: null,
|
||||
timer: null,
|
||||
url: null,
|
||||
|
||||
/**
|
||||
* Called when the manifest has been successfully loaded.
|
||||
@ -454,14 +456,15 @@ UpdateParser.prototype = {
|
||||
}
|
||||
|
||||
if (!Components.isSuccessCode(request.status)) {
|
||||
WARN("Request failed: " + request.status);
|
||||
WARN("Request failed: " + this.url + " - " + request.status);
|
||||
this.notifyError(AddonUpdateChecker.ERROR_DOWNLOAD_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
let channel = request.channel;
|
||||
if (channel instanceof Ci.nsIHttpChannel && !channel.requestSucceeded) {
|
||||
WARN("Request failed: " + channel.responseStatus + ": " + channel.responseStatusText);
|
||||
WARN("Request failed: " + this.url + " - " + channel.responseStatus +
|
||||
": " + channel.responseStatusText);
|
||||
this.notifyError(AddonUpdateChecker.ERROR_DOWNLOAD_ERROR);
|
||||
return;
|
||||
}
|
||||
@ -502,12 +505,13 @@ UpdateParser.prototype = {
|
||||
this.timer = null;
|
||||
|
||||
if (!Components.isSuccessCode(this.request.status)) {
|
||||
WARN("Request failed: " + this.request.status);
|
||||
WARN("Request failed: " + this.url + " - " + this.request.status);
|
||||
}
|
||||
else if (this.request.channel instanceof Ci.nsIHttpChannel) {
|
||||
try {
|
||||
if (this.request.channel.requestSucceeded) {
|
||||
WARN("Request failed: " + this.request.channel.responseStatus + ": " +
|
||||
WARN("Request failed: " + this.url + " - " +
|
||||
this.request.channel.responseStatus + ": " +
|
||||
this.request.channel.responseStatusText);
|
||||
}
|
||||
}
|
||||
|
@ -420,7 +420,7 @@ function PluginWrapper(aId, aName, aDescription, aTags) {
|
||||
}
|
||||
|
||||
PluginWrapper.prototype = {
|
||||
optionsType: AddonManager.OPTIONS_TYPE_INLINE,
|
||||
optionsType: AddonManager.OPTIONS_TYPE_INLINE_INFO,
|
||||
optionsURL: "chrome://mozapps/content/extensions/pluginPrefs.xul",
|
||||
|
||||
get updateDate() {
|
||||
|
@ -760,7 +760,8 @@ function loadManifestFromRDF(aUri, aStream) {
|
||||
if (addon.optionsType &&
|
||||
addon.optionsType != AddonManager.OPTIONS_TYPE_DIALOG &&
|
||||
addon.optionsType != AddonManager.OPTIONS_TYPE_INLINE &&
|
||||
addon.optionsType != AddonManager.OPTIONS_TYPE_TAB) {
|
||||
addon.optionsType != AddonManager.OPTIONS_TYPE_TAB &&
|
||||
addon.optionsType != AddonManager.OPTIONS_TYPE_INLINE_INFO) {
|
||||
throw new Error("Install manifest specifies unknown type: " + addon.optionsType);
|
||||
}
|
||||
}
|
||||
@ -1681,8 +1682,6 @@ var XPIProvider = {
|
||||
// of XPCOM
|
||||
Services.obs.addObserver({
|
||||
observe: function shutdownObserver(aSubject, aTopic, aData) {
|
||||
Services.prefs.setCharPref(PREF_BOOTSTRAP_ADDONS,
|
||||
JSON.stringify(XPIProvider.bootstrappedAddons));
|
||||
for (let id in XPIProvider.bootstrappedAddons) {
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
file.persistentDescriptor = XPIProvider.bootstrappedAddons[id].descriptor;
|
||||
@ -1789,6 +1788,14 @@ var XPIProvider = {
|
||||
Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Persists changes to XPIProvider.bootstrappedAddons to it's store (a pref).
|
||||
*/
|
||||
persistBootstrappedAddons: function XPI_persistBootstrappedAddons() {
|
||||
Services.prefs.setCharPref(PREF_BOOTSTRAP_ADDONS,
|
||||
JSON.stringify(this.bootstrappedAddons));
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a list of currently active add-ons to the next crash report.
|
||||
*/
|
||||
@ -2939,6 +2946,7 @@ var XPIProvider = {
|
||||
// Cache the new install location states
|
||||
let cache = JSON.stringify(this.getInstallLocationStates());
|
||||
Services.prefs.setCharPref(PREF_INSTALL_CACHE, cache);
|
||||
this.persistBootstrappedAddons();
|
||||
|
||||
// Clear out any cached migration data.
|
||||
XPIDatabase.migrateData = null;
|
||||
@ -3680,6 +3688,7 @@ var XPIProvider = {
|
||||
type: aType,
|
||||
descriptor: aFile.persistentDescriptor
|
||||
};
|
||||
this.persistBootstrappedAddons();
|
||||
this.addAddonsToCrashReporter();
|
||||
|
||||
// Locales only contain chrome and can't have bootstrap scripts
|
||||
@ -3747,6 +3756,7 @@ var XPIProvider = {
|
||||
unloadBootstrapScope: function XPI_unloadBootstrapScope(aId) {
|
||||
delete this.bootstrapScopes[aId];
|
||||
delete this.bootstrappedAddons[aId];
|
||||
this.persistBootstrappedAddons();
|
||||
this.addAddonsToCrashReporter();
|
||||
},
|
||||
|
||||
@ -5952,6 +5962,7 @@ function AddonWrapper(aAddon) {
|
||||
case AddonManager.OPTIONS_TYPE_TAB:
|
||||
return hasOptionsURL ? aAddon.optionsType : null;
|
||||
case AddonManager.OPTIONS_TYPE_INLINE:
|
||||
case AddonManager.OPTIONS_TYPE_INLINE_INFO:
|
||||
return (hasOptionsXUL || hasOptionsURL) ? aAddon.optionsType : null;
|
||||
}
|
||||
return null;
|
||||
|
@ -891,6 +891,8 @@ var gViewController = {
|
||||
aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE) {
|
||||
return false;
|
||||
}
|
||||
if (aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE_INFO)
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
doCommand: function cmd_showItemPreferences_doCommand(aAddon) {
|
||||
@ -1162,6 +1164,11 @@ var gViewController = {
|
||||
onEvent: function gVC_onEvent() {}
|
||||
};
|
||||
|
||||
function hasInlineOptions(aAddon) {
|
||||
return (aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE ||
|
||||
aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE_INFO);
|
||||
}
|
||||
|
||||
function openOptionsInTab(optionsURL) {
|
||||
var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
@ -2727,7 +2734,7 @@ var gDetailView = {
|
||||
AddonManager.removeManagerListener(this);
|
||||
this.clearLoading();
|
||||
if (this._addon) {
|
||||
if (this._addon.optionsType == AddonManager.OPTIONS_TYPE_INLINE) {
|
||||
if (hasInlineOptions(this._addon)) {
|
||||
Services.obs.notifyObservers(document,
|
||||
AddonManager.OPTIONS_NOTIFICATION_HIDDEN,
|
||||
this._addon.id);
|
||||
@ -2849,7 +2856,7 @@ var gDetailView = {
|
||||
|
||||
fillSettingsRows: function gDetailView_fillSettingsRows(aScrollToPreferences, aCallback) {
|
||||
this.emptySettingsRows();
|
||||
if (this._addon.optionsType != AddonManager.OPTIONS_TYPE_INLINE) {
|
||||
if (!hasInlineOptions(this._addon)) {
|
||||
if (aCallback)
|
||||
aCallback();
|
||||
return;
|
||||
@ -2970,8 +2977,7 @@ var gDetailView = {
|
||||
|
||||
onDisabling: function gDetailView_onDisabling(aNeedsRestart) {
|
||||
this.updateState();
|
||||
if (!aNeedsRestart &&
|
||||
this._addon.optionsType == AddonManager.OPTIONS_TYPE_INLINE) {
|
||||
if (!aNeedsRestart && hasInlineOptions(this._addon)) {
|
||||
Services.obs.notifyObservers(document,
|
||||
AddonManager.OPTIONS_NOTIFICATION_HIDDEN,
|
||||
this._addon.id);
|
||||
|
@ -1237,7 +1237,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
this._preferencesBtn.hidden = !this.mAddon.optionsURL;
|
||||
this._preferencesBtn.hidden = (!this.mAddon.optionsURL) ||
|
||||
this.mAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE_INFO;
|
||||
|
||||
if (this.hasPermission("enable")) {
|
||||
this._enableBtn.hidden = false;
|
||||
|
@ -58,6 +58,7 @@ MOCHITEST_BROWSER_MAIN = \
|
||||
browser_openDialog.js \
|
||||
browser_types.js \
|
||||
browser_inlinesettings.js \
|
||||
browser_inlinesettings_info.js \
|
||||
browser_tabsettings.js \
|
||||
browser_pluginprefs.js \
|
||||
$(NULL)
|
||||
|
8
toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info/bootstrap.js
vendored
Normal file
8
toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1_info/bootstrap.js
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
function install (params, aReason) {
|
||||
}
|
||||
function uninstall (params, aReason) {
|
||||
}
|
||||
function startup (params, aReason) {
|
||||
}
|
||||
function shutdown (params, aReason) {
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" ?>
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>inlinesettings1@tests.mozilla.org</em:id>
|
||||
<em:name>Inline Settings (Bootstrap)</em:name>
|
||||
<em:version>1</em:version>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
<em:optionsType>4</em:optionsType>
|
||||
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>toolkit@mozilla.org</em:id>
|
||||
<em:minVersion>0</em:minVersion>
|
||||
<em:maxVersion>*</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
</Description>
|
||||
|
||||
</RDF>
|
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" ?>
|
||||
<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<setting pref="extensions.inlinesettings1.bool" type="bool" title="Bool" checkboxlabel="Check box label"/>
|
||||
<setting pref="extensions.inlinesettings1.boolint" type="boolint" on="1" off="2" title="BoolInt"/>
|
||||
<setting pref="extensions.inlinesettings1.integer" type="integer" title="Integer"/>
|
||||
<setting pref="extensions.inlinesettings1.string" type="string" title="String"/>
|
||||
<setting type="control" title="Menulist">
|
||||
<menulist sizetopopup="always" oncommand="window._testValue = this.value;">
|
||||
<menupopup>
|
||||
<menuitem label="Alpha" value="1" />
|
||||
<menuitem label="Bravo" value="2" />
|
||||
<menuitem label="Charlie" value="3" />
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</setting>
|
||||
<setting pref="extensions.inlinesettings1.color" type="color" title="Color"/>
|
||||
<setting pref="extensions.inlinesettings1.file" type="file" title="File"/>
|
||||
<setting pref="extensions.inlinesettings1.directory" type="directory" title="Directory"/>
|
||||
</vbox>
|
@ -0,0 +1,570 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests various aspects of the details view
|
||||
|
||||
var gManagerWindow;
|
||||
var gCategoryUtilities;
|
||||
var gProvider;
|
||||
|
||||
const SETTINGS_ROWS = 8;
|
||||
|
||||
var MockFilePicker = SpecialPowers.MockFilePicker;
|
||||
MockFilePicker.init(window);
|
||||
|
||||
var observer = {
|
||||
lastDisplayed: null,
|
||||
callback: null,
|
||||
checkDisplayed: function(aExpected) {
|
||||
is(this.lastDisplayed, aExpected, "'addon-options-displayed' notification should have fired");
|
||||
this.lastDisplayed = null;
|
||||
},
|
||||
checkNotDisplayed: function() {
|
||||
is(this.lastDisplayed, null, "'addon-options-displayed' notification should not have fired");
|
||||
},
|
||||
lastHidden: null,
|
||||
checkHidden: function(aExpected) {
|
||||
is(this.lastHidden, aExpected, "'addon-options-hidden' notification should have fired");
|
||||
this.lastHidden = null;
|
||||
},
|
||||
checkNotHidden: function() {
|
||||
is(this.lastHidden, null, "'addon-options-hidden' notification should not have fired");
|
||||
},
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == AddonManager.OPTIONS_NOTIFICATION_DISPLAYED) {
|
||||
this.lastDisplayed = aData;
|
||||
// Test if the binding has applied before the observers are notified. We test the second setting here,
|
||||
// because the code operates on the first setting and we want to check it applies to all.
|
||||
var setting = aSubject.querySelector("rows > setting[first-row] ~ setting");
|
||||
var input = gManagerWindow.document.getAnonymousElementByAttribute(setting, "class", "preferences-title");
|
||||
isnot(input, null, "XBL binding should be applied");
|
||||
|
||||
// Add some extra height to the scrolling pane to ensure that it needs to scroll when appropriate.
|
||||
gManagerWindow.document.getElementById("detail-controls").style.marginBottom = "1000px";
|
||||
|
||||
if (this.callback) {
|
||||
var tempCallback = this.callback;
|
||||
this.callback = null;
|
||||
tempCallback();
|
||||
}
|
||||
} else if (aTopic == AddonManager.OPTIONS_NOTIFICATION_HIDDEN) {
|
||||
this.lastHidden = aData;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function installAddon(aCallback) {
|
||||
AddonManager.getInstallForURL(TESTROOT + "addons/browser_inlinesettings1_info.xpi",
|
||||
function(aInstall) {
|
||||
aInstall.addListener({
|
||||
onInstallEnded: function() {
|
||||
executeSoon(aCallback);
|
||||
}
|
||||
});
|
||||
aInstall.install();
|
||||
}, "application/x-xpinstall");
|
||||
}
|
||||
|
||||
function checkScrolling(aShouldHaveScrolled) {
|
||||
var detailView = gManagerWindow.document.getElementById("detail-view");
|
||||
var boxObject = detailView.boxObject;
|
||||
boxObject.QueryInterface(Ci.nsIScrollBoxObject);
|
||||
ok(detailView.scrollHeight > boxObject.height, "Page should require scrolling");
|
||||
if (aShouldHaveScrolled)
|
||||
isnot(detailView.scrollTop, 0, "Page should have scrolled");
|
||||
else
|
||||
is(detailView.scrollTop, 0, "Page should not have scrolled");
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gProvider = new MockProvider();
|
||||
|
||||
gProvider.createAddons([{
|
||||
id: "inlinesettings2@tests.mozilla.org",
|
||||
name: "Inline Settings (Regular)",
|
||||
version: "1",
|
||||
optionsURL: CHROMEROOT + "options.xul",
|
||||
optionsType: AddonManager.OPTIONS_TYPE_INLINE_INFO,
|
||||
operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_DISABLE,
|
||||
},{
|
||||
id: "inlinesettings3@tests.mozilla.org",
|
||||
name: "Inline Settings (More Options)",
|
||||
description: "Tests for option types introduced after Mozilla 7.0",
|
||||
version: "1",
|
||||
optionsURL: CHROMEROOT + "more_options.xul",
|
||||
optionsType: AddonManager.OPTIONS_TYPE_INLINE_INFO
|
||||
},{
|
||||
id: "noninlinesettings@tests.mozilla.org",
|
||||
name: "Non-Inline Settings",
|
||||
version: "1",
|
||||
optionsURL: CHROMEROOT + "addon_prefs.xul"
|
||||
}]);
|
||||
|
||||
installAddon(function () {
|
||||
open_manager("addons://list/extension", function(aWindow) {
|
||||
gManagerWindow = aWindow;
|
||||
gCategoryUtilities = new CategoryUtilities(gManagerWindow);
|
||||
|
||||
Services.obs.addObserver(observer,
|
||||
AddonManager.OPTIONS_NOTIFICATION_DISPLAYED,
|
||||
false);
|
||||
Services.obs.addObserver(observer,
|
||||
AddonManager.OPTIONS_NOTIFICATION_HIDDEN,
|
||||
false);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function end_test() {
|
||||
Services.obs.removeObserver(observer,
|
||||
AddonManager.OPTIONS_NOTIFICATION_DISPLAYED);
|
||||
|
||||
Services.prefs.clearUserPref("extensions.inlinesettings1.bool");
|
||||
Services.prefs.clearUserPref("extensions.inlinesettings1.boolint");
|
||||
Services.prefs.clearUserPref("extensions.inlinesettings1.integer");
|
||||
Services.prefs.clearUserPref("extensions.inlinesettings1.string");
|
||||
Services.prefs.clearUserPref("extensions.inlinesettings1.color");
|
||||
Services.prefs.clearUserPref("extensions.inlinesettings1.file");
|
||||
Services.prefs.clearUserPref("extensions.inlinesettings1.directory");
|
||||
Services.prefs.clearUserPref("extensions.inlinesettings3.radioBool");
|
||||
Services.prefs.clearUserPref("extensions.inlinesettings3.radioInt");
|
||||
Services.prefs.clearUserPref("extensions.inlinesettings3.radioString");
|
||||
Services.prefs.clearUserPref("extensions.inlinesettings3.menulist");
|
||||
|
||||
MockFilePicker.cleanup();
|
||||
|
||||
close_manager(gManagerWindow, function() {
|
||||
observer.checkHidden("inlinesettings2@tests.mozilla.org");
|
||||
Services.obs.removeObserver(observer,
|
||||
AddonManager.OPTIONS_NOTIFICATION_HIDDEN);
|
||||
|
||||
AddonManager.getAddonByID("inlinesettings1@tests.mozilla.org", function(aAddon) {
|
||||
aAddon.uninstall();
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Addon with options.xul
|
||||
add_test(function() {
|
||||
var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org");
|
||||
is(addon.mAddon.optionsType, AddonManager.OPTIONS_TYPE_INLINE_INFO, "Options should be inline info type");
|
||||
addon.parentNode.ensureElementIsVisible(addon);
|
||||
|
||||
var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn");
|
||||
is_element_hidden(button, "Preferences button should be hidden");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
// Addon with inline preferences as optionsURL
|
||||
add_test(function() {
|
||||
var addon = get_addon_element(gManagerWindow, "inlinesettings2@tests.mozilla.org");
|
||||
is(addon.mAddon.optionsType, AddonManager.OPTIONS_TYPE_INLINE_INFO, "Options should be inline info type");
|
||||
addon.parentNode.ensureElementIsVisible(addon);
|
||||
|
||||
var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn");
|
||||
is_element_hidden(button, "Preferences button should be hidden");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
// Addon with non-inline preferences as optionsURL
|
||||
add_test(function() {
|
||||
var addon = get_addon_element(gManagerWindow, "noninlinesettings@tests.mozilla.org");
|
||||
is(addon.mAddon.optionsType, AddonManager.OPTIONS_TYPE_DIALOG, "Options should be dialog type");
|
||||
addon.parentNode.ensureElementIsVisible(addon);
|
||||
|
||||
var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn");
|
||||
is_element_visible(button, "Preferences button should be visible");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
// Addon with options.xul, also a test for the setting.xml bindings
|
||||
add_test(function() {
|
||||
var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org");
|
||||
addon.parentNode.ensureElementIsVisible(addon);
|
||||
|
||||
var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn");
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
|
||||
wait_for_view_load(gManagerWindow, function() {
|
||||
observer.checkDisplayed("inlinesettings1@tests.mozilla.org");
|
||||
|
||||
var grid = gManagerWindow.document.getElementById("detail-grid");
|
||||
var settings = grid.querySelectorAll("rows > setting");
|
||||
is(settings.length, SETTINGS_ROWS, "Grid should have settings children");
|
||||
|
||||
ok(settings[0].hasAttribute("first-row"), "First visible row should have first-row attribute");
|
||||
Services.prefs.setBoolPref("extensions.inlinesettings1.bool", false);
|
||||
var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[0], "anonid", "input");
|
||||
isnot(input.checked, true, "Checkbox should have initial value");
|
||||
is(input.label, "Check box label", "Checkbox should be labelled");
|
||||
EventUtils.synthesizeMouseAtCenter(input, { clickCount: 1 }, gManagerWindow);
|
||||
is(input.checked, true, "Checkbox should have updated value");
|
||||
is(Services.prefs.getBoolPref("extensions.inlinesettings1.bool"), true, "Bool pref should have been updated");
|
||||
EventUtils.synthesizeMouseAtCenter(input, { clickCount: 1 }, gManagerWindow);
|
||||
isnot(input.checked, true, "Checkbox should have updated value");
|
||||
is(Services.prefs.getBoolPref("extensions.inlinesettings1.bool"), false, "Bool pref should have been updated");
|
||||
|
||||
ok(!settings[1].hasAttribute("first-row"), "Not the first row");
|
||||
Services.prefs.setIntPref("extensions.inlinesettings1.boolint", 0);
|
||||
var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[1], "anonid", "input");
|
||||
isnot(input.checked, true, "Checkbox should have initial value");
|
||||
EventUtils.synthesizeMouseAtCenter(input, { clickCount: 1 }, gManagerWindow);
|
||||
is(input.checked, true, "Checkbox should have updated value");
|
||||
is(Services.prefs.getIntPref("extensions.inlinesettings1.boolint"), 1, "BoolInt pref should have been updated");
|
||||
EventUtils.synthesizeMouseAtCenter(input, { clickCount: 1 }, gManagerWindow);
|
||||
isnot(input.checked, true, "Checkbox should have updated value");
|
||||
is(Services.prefs.getIntPref("extensions.inlinesettings1.boolint"), 2, "BoolInt pref should have been updated");
|
||||
|
||||
ok(!settings[2].hasAttribute("first-row"), "Not the first row");
|
||||
Services.prefs.setIntPref("extensions.inlinesettings1.integer", 0);
|
||||
var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[2], "anonid", "input");
|
||||
is(input.value, "0", "Number box should have initial value");
|
||||
input.select();
|
||||
EventUtils.synthesizeKey("1", {}, gManagerWindow);
|
||||
EventUtils.synthesizeKey("3", {}, gManagerWindow);
|
||||
is(input.value, "13", "Number box should have updated value");
|
||||
is(Services.prefs.getIntPref("extensions.inlinesettings1.integer"), 13, "Integer pref should have been updated");
|
||||
EventUtils.synthesizeKey("VK_DOWN", {}, gManagerWindow);
|
||||
is(input.value, "12", "Number box should have updated value");
|
||||
is(Services.prefs.getIntPref("extensions.inlinesettings1.integer"), 12, "Integer pref should have been updated");
|
||||
|
||||
ok(!settings[3].hasAttribute("first-row"), "Not the first row");
|
||||
Services.prefs.setCharPref("extensions.inlinesettings1.string", "foo");
|
||||
var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[3], "anonid", "input");
|
||||
is(input.value, "foo", "Text box should have initial value");
|
||||
input.select();
|
||||
EventUtils.synthesizeKey("b", {}, gManagerWindow);
|
||||
EventUtils.synthesizeKey("a", {}, gManagerWindow);
|
||||
EventUtils.synthesizeKey("r", {}, gManagerWindow);
|
||||
is(input.value, "bar", "Text box should have updated value");
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings1.string"), "bar", "String pref should have been updated");
|
||||
|
||||
ok(!settings[4].hasAttribute("first-row"), "Not the first row");
|
||||
var input = settings[4].firstElementChild;
|
||||
is(input.value, "1", "Menulist should have initial value");
|
||||
input.focus();
|
||||
EventUtils.synthesizeKey("b", {}, gManagerWindow);
|
||||
is(input.value, "2", "Menulist should have updated value");
|
||||
is(gManagerWindow._testValue, "2", "Menulist oncommand handler should've updated the test value");
|
||||
delete gManagerWindow._testValue;
|
||||
|
||||
ok(!settings[5].hasAttribute("first-row"), "Not the first row");
|
||||
Services.prefs.setCharPref("extensions.inlinesettings1.color", "#FF0000");
|
||||
input = gManagerWindow.document.getAnonymousElementByAttribute(settings[5], "anonid", "input");
|
||||
is(input.color, "#FF0000", "Color picker should have initial value");
|
||||
input.focus();
|
||||
EventUtils.synthesizeKey("VK_RIGHT", {}, gManagerWindow);
|
||||
EventUtils.synthesizeKey("VK_RIGHT", {}, gManagerWindow);
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, gManagerWindow);
|
||||
input.hidePopup();
|
||||
is(input.color, "#FF9900", "Color picker should have updated value");
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings1.color"), "#FF9900", "Color pref should have been updated");
|
||||
|
||||
try {
|
||||
ok(!settings[6].hasAttribute("first-row"), "Not the first row");
|
||||
var button = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "button");
|
||||
input = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "input");
|
||||
is(input.value, "", "Label value should be empty");
|
||||
is(input.tooltipText, "", "Label tooltip should be empty");
|
||||
|
||||
var profD = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
var curProcD = Services.dirsvc.get("CurProcD", Ci.nsIFile);
|
||||
|
||||
MockFilePicker.returnFiles = [profD];
|
||||
MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
is(MockFilePicker.mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file");
|
||||
is(input.value, profD.path, "Label value should match file chosen");
|
||||
is(input.tooltipText, profD.path, "Label tooltip should match file chosen");
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should match file chosen");
|
||||
|
||||
MockFilePicker.returnFiles = [curProcD];
|
||||
MockFilePicker.returnValue = Ci.nsIFilePicker.returnCancel;
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
is(MockFilePicker.mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file");
|
||||
is(input.value, profD.path, "Label value should not have changed");
|
||||
is(input.tooltipText, profD.path, "Label tooltip should not have changed");
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should not have changed");
|
||||
|
||||
ok(!settings[7].hasAttribute("first-row"), "Not the first row");
|
||||
button = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "button");
|
||||
input = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "input");
|
||||
is(input.value, "", "Label value should be empty");
|
||||
is(input.tooltipText, "", "Label tooltip should be empty");
|
||||
|
||||
MockFilePicker.returnFiles = [profD];
|
||||
MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
is(MockFilePicker.mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory");
|
||||
is(input.value, profD.path, "Label value should match file chosen");
|
||||
is(input.tooltipText, profD.path, "Label tooltip should match file chosen");
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should match file chosen");
|
||||
|
||||
MockFilePicker.returnFiles = [curProcD];
|
||||
MockFilePicker.returnValue = Ci.nsIFilePicker.returnCancel;
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
is(MockFilePicker.mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory");
|
||||
is(input.value, profD.path, "Label value should not have changed");
|
||||
is(input.tooltipText, profD.path, "Label tooltip should not have changed");
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should not have changed");
|
||||
|
||||
} finally {
|
||||
button = gManagerWindow.document.getElementById("detail-prefs-btn");
|
||||
is_element_hidden(button, "Preferences button should not be visible");
|
||||
|
||||
gCategoryUtilities.openType("extension", run_next_test);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Tests for the setting.xml bindings introduced after Mozilla 7
|
||||
add_test(function() {
|
||||
observer.checkHidden("inlinesettings1@tests.mozilla.org");
|
||||
|
||||
var addon = get_addon_element(gManagerWindow, "inlinesettings3@tests.mozilla.org");
|
||||
addon.parentNode.ensureElementIsVisible(addon);
|
||||
|
||||
var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn");
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
|
||||
wait_for_view_load(gManagerWindow, function() {
|
||||
observer.checkDisplayed("inlinesettings3@tests.mozilla.org");
|
||||
|
||||
var grid = gManagerWindow.document.getElementById("detail-grid");
|
||||
var settings = grid.querySelectorAll("rows > setting");
|
||||
is(settings.length, 4, "Grid should have settings children");
|
||||
|
||||
ok(settings[0].hasAttribute("first-row"), "First visible row should have first-row attribute");
|
||||
Services.prefs.setBoolPref("extensions.inlinesettings3.radioBool", false);
|
||||
var radios = settings[0].getElementsByTagName("radio");
|
||||
isnot(radios[0].selected, true, "Correct radio button should be selected");
|
||||
is(radios[1].selected, true, "Correct radio button should be selected");
|
||||
EventUtils.synthesizeMouseAtCenter(radios[0], { clickCount: 1 }, gManagerWindow);
|
||||
is(Services.prefs.getBoolPref("extensions.inlinesettings3.radioBool"), true, "Radio pref should have been updated");
|
||||
EventUtils.synthesizeMouseAtCenter(radios[1], { clickCount: 1 }, gManagerWindow);
|
||||
is(Services.prefs.getBoolPref("extensions.inlinesettings3.radioBool"), false, "Radio pref should have been updated");
|
||||
|
||||
ok(!settings[1].hasAttribute("first-row"), "Not the first row");
|
||||
Services.prefs.setIntPref("extensions.inlinesettings3.radioInt", 5);
|
||||
var radios = settings[1].getElementsByTagName("radio");
|
||||
isnot(radios[0].selected, true, "Correct radio button should be selected");
|
||||
is(radios[1].selected, true, "Correct radio button should be selected");
|
||||
isnot(radios[2].selected, true, "Correct radio button should be selected");
|
||||
EventUtils.synthesizeMouseAtCenter(radios[0], { clickCount: 1 }, gManagerWindow);
|
||||
is(Services.prefs.getIntPref("extensions.inlinesettings3.radioInt"), 4, "Radio pref should have been updated");
|
||||
EventUtils.synthesizeMouseAtCenter(radios[2], { clickCount: 1 }, gManagerWindow);
|
||||
is(Services.prefs.getIntPref("extensions.inlinesettings3.radioInt"), 6, "Radio pref should have been updated");
|
||||
|
||||
ok(!settings[2].hasAttribute("first-row"), "Not the first row");
|
||||
Services.prefs.setCharPref("extensions.inlinesettings3.radioString", "juliet");
|
||||
var radios = settings[2].getElementsByTagName("radio");
|
||||
isnot(radios[0].selected, true, "Correct radio button should be selected");
|
||||
is(radios[1].selected, true, "Correct radio button should be selected");
|
||||
isnot(radios[2].selected, true, "Correct radio button should be selected");
|
||||
EventUtils.synthesizeMouseAtCenter(radios[0], { clickCount: 1 }, gManagerWindow);
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings3.radioString"), "india", "Radio pref should have been updated");
|
||||
EventUtils.synthesizeMouseAtCenter(radios[2], { clickCount: 1 }, gManagerWindow);
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings3.radioString"), "kilo", "Radio pref should have been updated");
|
||||
|
||||
ok(!settings[3].hasAttribute("first-row"), "Not the first row");
|
||||
Services.prefs.setIntPref("extensions.inlinesettings3.menulist", 8);
|
||||
var input = settings[3].firstElementChild;
|
||||
is(input.value, "8", "Menulist should have initial value");
|
||||
input.focus();
|
||||
EventUtils.synthesizeKey("n", {}, gManagerWindow);
|
||||
is(input.value, "9", "Menulist should have updated value");
|
||||
is(Services.prefs.getIntPref("extensions.inlinesettings3.menulist"), 9, "Menulist pref should have been updated");
|
||||
|
||||
button = gManagerWindow.document.getElementById("detail-prefs-btn");
|
||||
is_element_hidden(button, "Preferences button should not be visible");
|
||||
|
||||
gCategoryUtilities.openType("extension", run_next_test);
|
||||
});
|
||||
});
|
||||
|
||||
// Addon with inline preferences as optionsURL
|
||||
add_test(function() {
|
||||
observer.checkHidden("inlinesettings3@tests.mozilla.org");
|
||||
|
||||
var addon = get_addon_element(gManagerWindow, "inlinesettings2@tests.mozilla.org");
|
||||
addon.parentNode.ensureElementIsVisible(addon);
|
||||
|
||||
var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn");
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
|
||||
wait_for_view_load(gManagerWindow, function() {
|
||||
observer.checkDisplayed("inlinesettings2@tests.mozilla.org");
|
||||
|
||||
var grid = gManagerWindow.document.getElementById("detail-grid");
|
||||
var settings = grid.querySelectorAll("rows > setting");
|
||||
is(settings.length, 5, "Grid should have settings children");
|
||||
|
||||
var node = settings[0];
|
||||
node = settings[0];
|
||||
is_element_hidden(node, "Unsupported settings should not be visible");
|
||||
ok(!node.hasAttribute("first-row"), "Hidden row is not the first row");
|
||||
|
||||
node = settings[1];
|
||||
is(node.nodeName, "setting", "Should be a setting node");
|
||||
ok(node.hasAttribute("first-row"), "First visible row should have first-row attribute");
|
||||
var description = gManagerWindow.document.getAnonymousElementByAttribute(node, "class", "preferences-description");
|
||||
is(description.textContent, "Description Attribute", "Description node should contain description");
|
||||
|
||||
node = settings[2];
|
||||
is(node.nodeName, "setting", "Should be a setting node");
|
||||
ok(!node.hasAttribute("first-row"), "Not the first row");
|
||||
description = gManagerWindow.document.getAnonymousElementByAttribute(node, "class", "preferences-description");
|
||||
is(description.textContent, "Description Text Node", "Description node should contain description");
|
||||
|
||||
node = settings[3];
|
||||
is(node.nodeName, "setting", "Should be a setting node");
|
||||
ok(!node.hasAttribute("first-row"), "Not the first row");
|
||||
description = gManagerWindow.document.getAnonymousElementByAttribute(node, "class", "preferences-description");
|
||||
is(description.textContent, "This is a test, all this text should be visible", "Description node should contain description");
|
||||
var button = node.firstElementChild;
|
||||
isnot(button, null, "There should be a button");
|
||||
|
||||
node = settings[4];
|
||||
is_element_hidden(node, "Unsupported settings should not be visible");
|
||||
ok(!node.hasAttribute("first-row"), "Hidden row is not the first row");
|
||||
|
||||
var button = gManagerWindow.document.getElementById("detail-prefs-btn");
|
||||
is_element_hidden(button, "Preferences button should not be visible");
|
||||
|
||||
gCategoryUtilities.openType("extension", run_next_test);
|
||||
});
|
||||
});
|
||||
|
||||
// Addon with non-inline preferences as optionsURL
|
||||
add_test(function() {
|
||||
observer.checkHidden("inlinesettings2@tests.mozilla.org");
|
||||
|
||||
var addon = get_addon_element(gManagerWindow, "noninlinesettings@tests.mozilla.org");
|
||||
addon.parentNode.ensureElementIsVisible(addon);
|
||||
|
||||
var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn");
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
|
||||
wait_for_view_load(gManagerWindow, function() {
|
||||
observer.checkNotDisplayed();
|
||||
|
||||
var grid = gManagerWindow.document.getElementById("detail-grid");
|
||||
var settings = grid.querySelectorAll("rows > setting");
|
||||
is(settings.length, 0, "Grid should not have settings children");
|
||||
|
||||
var button = gManagerWindow.document.getElementById("detail-prefs-btn");
|
||||
is_element_visible(button, "Preferences button should be visible");
|
||||
|
||||
gCategoryUtilities.openType("extension", run_next_test);
|
||||
});
|
||||
});
|
||||
|
||||
// Addon with options.xul, disabling and enabling should hide and show settings UI
|
||||
add_test(function() {
|
||||
observer.checkNotHidden();
|
||||
|
||||
var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org");
|
||||
addon.parentNode.ensureElementIsVisible(addon);
|
||||
|
||||
var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn");
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
|
||||
wait_for_view_load(gManagerWindow, function() {
|
||||
observer.checkDisplayed("inlinesettings1@tests.mozilla.org");
|
||||
is(gManagerWindow.gViewController.currentViewId,
|
||||
"addons://detail/inlinesettings1%40tests.mozilla.org",
|
||||
"Current view should not scroll to preferences");
|
||||
checkScrolling(false);
|
||||
|
||||
var grid = gManagerWindow.document.getElementById("detail-grid");
|
||||
var settings = grid.querySelectorAll("rows > setting");
|
||||
is(settings.length, SETTINGS_ROWS, "Grid should have settings children");
|
||||
|
||||
// disable
|
||||
var button = gManagerWindow.document.getElementById("detail-disable-btn");
|
||||
button.focus(); // make sure it's in view
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
|
||||
observer.checkHidden("inlinesettings1@tests.mozilla.org");
|
||||
|
||||
settings = grid.querySelectorAll("rows > setting");
|
||||
is(settings.length, 0, "Grid should not have settings children");
|
||||
|
||||
gCategoryUtilities.openType("extension", function() {
|
||||
var addon = get_addon_element(gManagerWindow, "inlinesettings1@tests.mozilla.org");
|
||||
addon.parentNode.ensureElementIsVisible(addon);
|
||||
|
||||
var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "preferences-btn");
|
||||
is_element_hidden(button, "Preferences button should not be visible");
|
||||
|
||||
button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn");
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
|
||||
wait_for_view_load(gManagerWindow, function() {
|
||||
var grid = gManagerWindow.document.getElementById("detail-grid");
|
||||
var settings = grid.querySelectorAll("rows > setting");
|
||||
is(settings.length, 0, "Grid should not have settings children");
|
||||
|
||||
// enable
|
||||
var button = gManagerWindow.document.getElementById("detail-enable-btn");
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
|
||||
observer.callback = function() {
|
||||
observer.checkDisplayed("inlinesettings1@tests.mozilla.org");
|
||||
|
||||
settings = grid.querySelectorAll("rows > setting");
|
||||
is(settings.length, SETTINGS_ROWS, "Grid should have settings children");
|
||||
|
||||
gCategoryUtilities.openType("extension", run_next_test);
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Addon with options.xul that requires a restart to disable,
|
||||
// disabling and enabling should not hide and show settings UI.
|
||||
add_test(function() {
|
||||
observer.checkHidden("inlinesettings1@tests.mozilla.org");
|
||||
|
||||
var addon = get_addon_element(gManagerWindow, "inlinesettings2@tests.mozilla.org");
|
||||
addon.parentNode.ensureElementIsVisible(addon);
|
||||
|
||||
var button = gManagerWindow.document.getAnonymousElementByAttribute(addon, "anonid", "details-btn");
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
|
||||
wait_for_view_load(gManagerWindow, function() {
|
||||
observer.checkDisplayed("inlinesettings2@tests.mozilla.org");
|
||||
|
||||
var grid = gManagerWindow.document.getElementById("detail-grid");
|
||||
var settings = grid.querySelectorAll("rows > setting");
|
||||
ok(settings.length > 0, "Grid should have settings children");
|
||||
|
||||
// disable
|
||||
var button = gManagerWindow.document.getElementById("detail-disable-btn");
|
||||
button.focus(); // make sure it's in view
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
observer.checkNotHidden();
|
||||
|
||||
settings = grid.querySelectorAll("rows > setting");
|
||||
ok(settings.length > 0, "Grid should still have settings children");
|
||||
|
||||
// cancel pending disable
|
||||
button = gManagerWindow.document.getElementById("detail-enable-btn");
|
||||
button.focus(); // make sure it's in view
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
observer.checkNotDisplayed();
|
||||
|
||||
gCategoryUtilities.openType("extension", run_next_test);
|
||||
});
|
||||
});
|
@ -35,11 +35,13 @@ add_test(function() {
|
||||
|
||||
AddonManager.getAddonByID(testPluginId, function(testPlugin) {
|
||||
let pluginEl = get_addon_element(gManagerWindow, testPluginId);
|
||||
is(pluginEl.mAddon.optionsType, AddonManager.OPTIONS_TYPE_INLINE, "Options should be inline type");
|
||||
is(pluginEl.mAddon.optionsType, AddonManager.OPTIONS_TYPE_INLINE_INFO, "Options should be inline info type");
|
||||
pluginEl.parentNode.ensureElementIsVisible(pluginEl);
|
||||
|
||||
let button = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "preferences-btn");
|
||||
is_element_visible(button, "Preferences button should be visible");
|
||||
is_element_hidden(button, "Preferences button should be hidden");
|
||||
|
||||
button = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn");
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
|
||||
wait_for_view_load(gManagerWindow, function() {
|
||||
|
@ -101,6 +101,39 @@ function getUninstallNewVersion() {
|
||||
return Services.prefs.getIntPref("bootstraptest.uninstall_newversion");
|
||||
}
|
||||
|
||||
function do_check_bootstrappedPref(aCallback) {
|
||||
let data = "{}";
|
||||
try {
|
||||
// This is ok to fail, as the pref won't exist on a fresh profile.
|
||||
data = Services.prefs.getCharPref("extensions.bootstrappedAddons");
|
||||
} catch (e) {}
|
||||
data = JSON.parse(data);
|
||||
|
||||
AddonManager.getAddonsByTypes(["extension"], function(aAddons) {
|
||||
for (let addon of aAddons) {
|
||||
if (!addon.id.endsWith("@tests.mozilla.org"))
|
||||
continue;
|
||||
if (!addon.isActive)
|
||||
continue;
|
||||
if (addon.operationsRequiringRestart != AddonManager.OP_NEEDS_RESTART_NONE)
|
||||
continue;
|
||||
|
||||
do_check_true(addon.id in data);
|
||||
let addonData = data[addon.id];
|
||||
delete data[addon.id];
|
||||
|
||||
do_check_eq(addonData.version, addon.version);
|
||||
do_check_eq(addonData.type, addon.type);
|
||||
let file = addon.getResourceURI().QueryInterface(Components.interfaces.nsIFileURL).file;
|
||||
do_check_eq(addonData.descriptor, file.persistentDescriptor);
|
||||
}
|
||||
do_check_eq(Object.keys(data).length, 0);
|
||||
|
||||
aCallback();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
|
||||
@ -120,7 +153,7 @@ function run_test() {
|
||||
file.leafName = "extensions.ini";
|
||||
do_check_false(file.exists());
|
||||
|
||||
run_test_1();
|
||||
do_check_bootstrappedPref(run_test_1);
|
||||
}
|
||||
|
||||
// Tests that installing doesn't require a restart
|
||||
@ -161,8 +194,11 @@ function run_test_1() {
|
||||
do_check_eq(getActiveVersion(), -1);
|
||||
|
||||
waitForPref("bootstraptest.active_version", function() {
|
||||
check_test_1(addon.syncGUID);
|
||||
do_check_bootstrappedPref(function() {
|
||||
check_test_1(addon.syncGUID);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
install.install();
|
||||
});
|
||||
@ -243,7 +279,7 @@ function run_test_2() {
|
||||
do_check_true(newb1.userDisabled);
|
||||
do_check_false(newb1.isActive);
|
||||
|
||||
run_test_3();
|
||||
do_check_bootstrappedPref(run_test_3);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -273,7 +309,7 @@ function run_test_3() {
|
||||
do_check_true(b1.userDisabled);
|
||||
do_check_false(b1.isActive);
|
||||
|
||||
run_test_4();
|
||||
do_check_bootstrappedPref(run_test_4);
|
||||
});
|
||||
}
|
||||
|
||||
@ -310,7 +346,7 @@ function run_test_4() {
|
||||
do_check_false(newb1.userDisabled);
|
||||
do_check_true(newb1.isActive);
|
||||
|
||||
run_test_5();
|
||||
do_check_bootstrappedPref(run_test_5);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -338,7 +374,7 @@ function run_test_5() {
|
||||
do_check_true(b1.isActive);
|
||||
do_check_false(isExtensionInAddonsList(profileDir, b1.id));
|
||||
|
||||
run_test_6();
|
||||
do_check_bootstrappedPref(run_test_6);
|
||||
});
|
||||
}
|
||||
|
||||
@ -390,7 +426,7 @@ function check_test_6() {
|
||||
do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
|
||||
do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0");
|
||||
|
||||
run_test_7();
|
||||
do_check_bootstrappedPref(run_test_7);
|
||||
});
|
||||
}
|
||||
|
||||
@ -408,7 +444,7 @@ function run_test_7() {
|
||||
AddonManager.OP_NEEDS_RESTART_UNINSTALL, 0);
|
||||
b1.uninstall();
|
||||
|
||||
check_test_7();
|
||||
do_check_bootstrappedPref(check_test_7);
|
||||
});
|
||||
}
|
||||
|
||||
@ -428,7 +464,7 @@ function check_test_7() {
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(newb1) {
|
||||
do_check_eq(newb1, null);
|
||||
|
||||
run_test_8();
|
||||
do_check_bootstrappedPref(run_test_8);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -455,7 +491,7 @@ function run_test_8() {
|
||||
do_check_eq(getStartupOldVersion(), 0);
|
||||
do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
|
||||
|
||||
run_test_9();
|
||||
do_check_bootstrappedPref(run_test_9);
|
||||
});
|
||||
}
|
||||
|
||||
@ -471,7 +507,7 @@ function run_test_9() {
|
||||
do_check_eq(b1, null);
|
||||
do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
|
||||
|
||||
run_test_10();
|
||||
do_check_bootstrappedPref(run_test_10);
|
||||
});
|
||||
}
|
||||
|
||||
@ -573,7 +609,7 @@ function check_test_10_pt2() {
|
||||
do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
|
||||
do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0");
|
||||
|
||||
run_test_11();
|
||||
do_check_bootstrappedPref(run_test_11);
|
||||
});
|
||||
}
|
||||
|
||||
@ -609,7 +645,7 @@ function check_test_11() {
|
||||
do_check_eq(getActiveVersion(), 0);
|
||||
do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
|
||||
|
||||
run_test_12();
|
||||
do_check_bootstrappedPref(run_test_12);
|
||||
}
|
||||
|
||||
// Tests that bootstrapped extensions are correctly loaded even if the app is
|
||||
@ -637,7 +673,7 @@ function run_test_12() {
|
||||
b1.uninstall();
|
||||
restartManager();
|
||||
|
||||
run_test_13();
|
||||
do_check_bootstrappedPref(run_test_13);
|
||||
});
|
||||
}
|
||||
|
||||
@ -700,10 +736,12 @@ function check_test_13() {
|
||||
do_check_eq(getActiveVersion(), 0); // Should not have called startup though
|
||||
do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0");
|
||||
|
||||
b1.uninstall();
|
||||
restartManager();
|
||||
do_check_bootstrappedPref(function() {
|
||||
b1.uninstall();
|
||||
restartManager();
|
||||
|
||||
run_test_14();
|
||||
run_test_14();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -729,9 +767,11 @@ function run_test_14() {
|
||||
do_check_eq(getActiveVersion(), 0); // Should not have called startup though
|
||||
do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0");
|
||||
|
||||
b1.uninstall();
|
||||
do_check_bootstrappedPref(function() {
|
||||
b1.uninstall();
|
||||
|
||||
run_test_15();
|
||||
run_test_15();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -788,20 +828,22 @@ function check_test_15() {
|
||||
do_check_eq(getInstalledVersion(), 2);
|
||||
do_check_eq(getActiveVersion(), 0);
|
||||
|
||||
restartManager();
|
||||
do_check_bootstrappedPref(function() {
|
||||
restartManager();
|
||||
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
|
||||
do_check_neq(b1, null);
|
||||
do_check_eq(b1.version, "2.0");
|
||||
do_check_false(b1.appDisabled);
|
||||
do_check_true(b1.userDisabled);
|
||||
do_check_false(b1.isActive);
|
||||
do_check_eq(getInstalledVersion(), 2);
|
||||
do_check_eq(getActiveVersion(), 0);
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
|
||||
do_check_neq(b1, null);
|
||||
do_check_eq(b1.version, "2.0");
|
||||
do_check_false(b1.appDisabled);
|
||||
do_check_true(b1.userDisabled);
|
||||
do_check_false(b1.isActive);
|
||||
do_check_eq(getInstalledVersion(), 2);
|
||||
do_check_eq(getActiveVersion(), 0);
|
||||
|
||||
b1.uninstall();
|
||||
b1.uninstall();
|
||||
|
||||
run_test_16();
|
||||
run_test_16();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -872,7 +914,7 @@ function run_test_17() {
|
||||
do_check_eq(b1.version, "1.0");
|
||||
do_check_true(b1.isActive);
|
||||
|
||||
run_test_18();
|
||||
do_check_bootstrappedPref(run_test_18);
|
||||
});
|
||||
}
|
||||
|
||||
@ -899,7 +941,7 @@ function run_test_18() {
|
||||
do_check_eq(getInstallOldVersion(), 1);
|
||||
do_check_eq(getStartupOldVersion(), 1);
|
||||
|
||||
run_test_19();
|
||||
do_check_bootstrappedPref(run_test_19);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -942,7 +984,7 @@ function check_test_19() {
|
||||
do_check_eq(getInstallOldVersion(), 0);
|
||||
do_check_eq(getStartupOldVersion(), 0);
|
||||
|
||||
run_test_20();
|
||||
do_check_bootstrappedPref(run_test_20);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1011,11 +1053,12 @@ function run_test_21() {
|
||||
do_check_eq(getStartupReason(), APP_STARTUP);
|
||||
do_check_eq(getStartupOldVersion(), 0);
|
||||
|
||||
manuallyUninstall(userExtDir, "bootstrap1@tests.mozilla.org");
|
||||
do_check_bootstrappedPref(function() {
|
||||
manuallyUninstall(userExtDir, "bootstrap1@tests.mozilla.org");
|
||||
|
||||
restartManager();
|
||||
|
||||
run_test_22();
|
||||
restartManager();
|
||||
run_test_22();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -1069,9 +1112,11 @@ function run_test_22() {
|
||||
do_check_eq(getStartupReason(), APP_STARTUP);
|
||||
do_check_eq(getStartupOldVersion(), 0);
|
||||
|
||||
b1.uninstall();
|
||||
do_check_bootstrappedPref(function() {
|
||||
b1.uninstall();
|
||||
|
||||
run_test_23();
|
||||
run_test_23();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -1115,7 +1160,7 @@ function run_test_23() {
|
||||
"onInstallEnded",
|
||||
], function() {
|
||||
do_check_true(addon.hasResource("install.rdf"));
|
||||
check_test_23();
|
||||
do_check_bootstrappedPref(check_test_23);
|
||||
});
|
||||
});
|
||||
install.install();
|
||||
@ -1171,35 +1216,35 @@ function run_test_24() {
|
||||
do_check_eq(getActiveVersion(), 1);
|
||||
do_check_eq(getInstalledVersion2(), 1);
|
||||
do_check_eq(getActiveVersion2(), 1);
|
||||
|
||||
|
||||
resetPrefs();
|
||||
|
||||
|
||||
restartManager();
|
||||
|
||||
|
||||
do_check_eq(getInstalledVersion(), -1);
|
||||
do_check_eq(getActiveVersion(), 1);
|
||||
do_check_eq(getInstalledVersion2(), -1);
|
||||
do_check_eq(getActiveVersion2(), 1);
|
||||
|
||||
|
||||
shutdownManager();
|
||||
|
||||
|
||||
do_check_eq(getInstalledVersion(), -1);
|
||||
do_check_eq(getActiveVersion(), 0);
|
||||
do_check_eq(getInstalledVersion2(), -1);
|
||||
do_check_eq(getActiveVersion2(), 0);
|
||||
|
||||
|
||||
// Break the preferece
|
||||
let bootstrappedAddons = JSON.parse(Services.prefs.getCharPref("extensions.bootstrappedAddons"));
|
||||
bootstrappedAddons["bootstrap1@tests.mozilla.org"].descriptor += "foo";
|
||||
Services.prefs.setCharPref("extensions.bootstrappedAddons", JSON.stringify(bootstrappedAddons));
|
||||
|
||||
|
||||
startupManager(false);
|
||||
|
||||
|
||||
do_check_eq(getInstalledVersion(), -1);
|
||||
do_check_eq(getActiveVersion(), 1);
|
||||
do_check_eq(getInstalledVersion2(), -1);
|
||||
do_check_eq(getActiveVersion2(), 1);
|
||||
|
||||
|
||||
run_test_25();
|
||||
});
|
||||
});
|
||||
@ -1212,32 +1257,32 @@ function run_test_25() {
|
||||
waitForPref("bootstraptest.active_version", function() {
|
||||
do_check_eq(getInstalledVersion(), 1);
|
||||
do_check_eq(getActiveVersion(), 1);
|
||||
|
||||
|
||||
installAllFiles([do_get_addon("test_bootstrap1_4")], function() {
|
||||
// Needs a restart to complete this so the old version stays running
|
||||
do_check_eq(getInstalledVersion(), 1);
|
||||
do_check_eq(getActiveVersion(), 1);
|
||||
|
||||
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
|
||||
do_check_neq(b1, null);
|
||||
do_check_eq(b1.version, "1.0");
|
||||
do_check_true(b1.isActive);
|
||||
do_check_true(hasFlag(b1.pendingOperations, AddonManager.PENDING_UPGRADE));
|
||||
|
||||
|
||||
restartManager();
|
||||
|
||||
|
||||
do_check_eq(getInstalledVersion(), 0);
|
||||
do_check_eq(getUninstallReason(), ADDON_UPGRADE);
|
||||
do_check_eq(getUninstallNewVersion(), 4);
|
||||
do_check_eq(getActiveVersion(), 0);
|
||||
|
||||
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
|
||||
do_check_neq(b1, null);
|
||||
do_check_eq(b1.version, "4.0");
|
||||
do_check_true(b1.isActive);
|
||||
do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
|
||||
|
||||
run_test_26();
|
||||
|
||||
do_check_bootstrappedPref(run_test_26);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1272,7 +1317,7 @@ function run_test_26() {
|
||||
do_check_true(b1.isActive);
|
||||
do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
|
||||
|
||||
run_test_27();
|
||||
do_check_bootstrappedPref(run_test_27);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1314,7 +1359,7 @@ function run_test_27() {
|
||||
do_check_false(b1.isActive);
|
||||
do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
|
||||
|
||||
run_test_28();
|
||||
do_check_bootstrappedPref(run_test_28);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1351,7 +1396,7 @@ function run_test_28() {
|
||||
do_check_eq(getInstalledVersion(), 1);
|
||||
do_check_eq(getActiveVersion(), 1);
|
||||
|
||||
do_test_finished();
|
||||
do_check_bootstrappedPref(do_test_finished);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -330,6 +330,18 @@ function run_test() {
|
||||
name: "Test Addon 25"
|
||||
}, profileDir);
|
||||
|
||||
writeInstallRDFForExtension({
|
||||
id: "addon26@tests.mozilla.org",
|
||||
version: "1.0",
|
||||
optionsType: "4",
|
||||
targetApplications: [{
|
||||
id: "xpcshell@tests.mozilla.org",
|
||||
minVersion: "1",
|
||||
maxVersion: "1"
|
||||
}],
|
||||
name: "Test Addon 26"
|
||||
}, profileDir, null, "options.xul");
|
||||
|
||||
do_test_pending();
|
||||
startupManager();
|
||||
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
|
||||
@ -356,10 +368,11 @@ function run_test() {
|
||||
"addon22@tests.mozilla.org",
|
||||
"addon23@tests.mozilla.org",
|
||||
"addon24@tests.mozilla.org",
|
||||
"addon25@tests.mozilla.org"],
|
||||
"addon25@tests.mozilla.org",
|
||||
"addon26@tests.mozilla.org"],
|
||||
function([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
|
||||
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20,
|
||||
a21, a22, a23, a24, a25]) {
|
||||
a21, a22, a23, a24, a25, a26]) {
|
||||
|
||||
do_check_neq(a1, null);
|
||||
do_check_eq(a1.id, "addon1@tests.mozilla.org");
|
||||
@ -540,6 +553,10 @@ function run_test() {
|
||||
do_check_eq(a25.optionsType, null);
|
||||
do_check_eq(a25.optionsURL, null);
|
||||
|
||||
do_check_neq(a26, null);
|
||||
do_check_eq(a26.optionsType, AddonManager.OPTIONS_TYPE_INLINE_INFO);
|
||||
do_check_neq(a26.optionsURL, null);
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
||||
|
@ -292,6 +292,12 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
#header-search {
|
||||
width: 12em;
|
||||
}
|
||||
}
|
||||
|
||||
.view-header {
|
||||
padding: 4px;
|
||||
margin: 0;
|
||||
|
@ -316,6 +316,12 @@
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
#header-search {
|
||||
width: 12em;
|
||||
}
|
||||
}
|
||||
|
||||
#header-search[focused] {
|
||||
box-shadow: @focusRingShadow@, inset 0 1px 1px rgba(0,0,0,0.15);
|
||||
border-color: -moz-mac-focusring;
|
||||
|
@ -289,6 +289,12 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
#header-search {
|
||||
width: 12em;
|
||||
}
|
||||
}
|
||||
|
||||
@media (-moz-windows-default-theme) {
|
||||
#header-search {
|
||||
-moz-appearance: none;
|
||||
|
@ -21,7 +21,7 @@ namespace mozilla {
|
||||
*/
|
||||
struct Module
|
||||
{
|
||||
static const unsigned int kVersion = 22;
|
||||
static const unsigned int kVersion = 23;
|
||||
|
||||
struct CIDEntry;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user