Web Console test for " +
+ "obeserver notifications";
+
+let created = false;
+let destroyed = false;
+
+add_task(function* () {
+ setupObserver();
+ yield openNewTabAndConsole(TEST_URI);
+ yield waitFor(() => created);
+
+ yield closeTabAndToolbox(gBrowser.selectedTab);
+ yield waitFor(() => destroyed);
+});
+
+function setupObserver() {
+ const observer = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
+
+ observe: function observe(subject, topic) {
+ subject = subject.QueryInterface(Ci.nsISupportsString);
+
+ switch (topic) {
+ case "web-console-created":
+ ok(HUDService.getHudReferenceById(subject.data), "We have a hud reference");
+ Services.obs.removeObserver(observer, "web-console-created");
+ created = true;
+ break;
+ case "web-console-destroyed":
+ ok(!HUDService.getHudReferenceById(subject.data), "We do not have a hud reference");
+ Services.obs.removeObserver(observer, "web-console-destroyed");
+ destroyed = true;
+ break;
+ }
+ },
+ };
+
+ Services.obs.addObserver(observer, "web-console-created", false);
+ Services.obs.addObserver(observer, "web-console-destroyed", false);
+}
diff --git a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_vview_close_on_esc_key.js b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_vview_close_on_esc_key.js
new file mode 100644
index 000000000000..712a990b4406
--- /dev/null
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_vview_close_on_esc_key.js
@@ -0,0 +1,46 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Check that the variables view sidebar can be closed by pressing Escape in the
+// web console.
+
+"use strict";
+
+const TEST_URI =
+ "data:text/html;charset=utf8,";
+
+add_task(function* () {
+ let hud = yield openNewTabAndConsole(TEST_URI);
+ let jsterm = hud.jsterm;
+ let vview;
+
+ yield openSidebar("fooObj", 'testProp: "testValue"');
+ vview.window.focus();
+
+ let sidebarClosed = jsterm.once("sidebar-closed");
+ EventUtils.synthesizeKey("VK_ESCAPE", {});
+ yield sidebarClosed;
+
+ function* openSidebar(objName, expectedText) {
+ yield jsterm.execute(objName);
+ info("JSTerm executed");
+
+ let msg = yield waitFor(() => findMessage(hud, "Object"));
+ ok(msg, "Message found");
+
+ let anchor = msg.querySelector("a");
+ let body = msg.querySelector(".message-body");
+ ok(anchor, "object anchor");
+ ok(body, "message body");
+ ok(body.textContent.includes(expectedText), "message text check");
+
+ msg.scrollIntoView();
+ yield EventUtils.synthesizeMouse(anchor, 2, 2, {}, hud.iframeWindow);
+
+ let vviewVar = yield jsterm.once("variablesview-fetched");
+ vview = vviewVar._variablesView;
+ ok(vview, "variables view object exists");
+ }
+});
diff --git a/devtools/client/webconsole/new-console-output/test/mochitest/head.js b/devtools/client/webconsole/new-console-output/test/mochitest/head.js
index faa2093b4a13..8957af0a1b73 100644
--- a/devtools/client/webconsole/new-console-output/test/mochitest/head.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/head.js
@@ -13,6 +13,102 @@ Services.scriptloader.loadSubScript(
this);
Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", true);
-registerCleanupFunction(() => {
+registerCleanupFunction(function* () {
Services.prefs.clearUserPref("devtools.webconsole.new-frontend-enabled");
+
+ let browserConsole = HUDService.getBrowserConsole();
+ if (browserConsole) {
+ if (browserConsole.jsterm) {
+ browserConsole.jsterm.clearOutput(true);
+ }
+ yield HUDService.toggleBrowserConsole();
+ }
});
+
+/**
+ * Add a new tab and open the toolbox in it, and select the webconsole.
+ *
+ * @param string url
+ * The URL for the tab to be opened.
+ * @return Promise
+ * Resolves when the tab has been added, loaded and the toolbox has been opened.
+ * Resolves to the toolbox.
+ */
+var openNewTabAndConsole = Task.async(function* (url) {
+ let toolbox = yield openNewTabAndToolbox(TEST_URI, "webconsole");
+ let hud = toolbox.getCurrentPanel().hud;
+ hud.jsterm._lazyVariablesView = false;
+ return hud;
+});
+
+/**
+ * Wait for messages in the web console output, resolving once they are receieved.
+ *
+ * @param object options
+ * - hud: the webconsole
+ * - messages: Array[Object]. An array of messages to match. Current supported options:
+ * - text: Exact text match in .message-body
+ */
+function waitForMessages({ hud, messages }) {
+ return new Promise(resolve => {
+ let numMatched = 0;
+ let receivedLog = hud.ui.on("new-messages", function messagesReceieved(e, newMessage) {
+ for (let message of messages) {
+ if (message.matched) {
+ continue;
+ }
+
+ if (newMessage.node.querySelector(".message-body").textContent == message.text) {
+ numMatched++;
+ message.matched = true;
+ info("Matched a message with text: " + message.text + ", still waiting for " + (messages.length - numMatched) + " messages");
+ }
+
+ if (numMatched === messages.length) {
+ hud.ui.off("new-messages", messagesReceieved);
+ resolve(receivedLog);
+ return;
+ }
+ }
+ });
+ });
+}
+
+/**
+ * Wait for a predicate to return a result.
+ *
+ * @param function condition
+ * Invoked once in a while until it returns a truthy value. This should be an
+ * idempotent function, since we have to run it a second time after it returns
+ * true in order to return the value.
+ * @param string message [optional]
+ * A message to output if the condition failes.
+ * @param number interval [optional]
+ * How often the predicate is invoked, in milliseconds.
+ * @return object
+ * A promise that is resolved with the result of the condition.
+ */
+function* waitFor(condition, message = "waitFor", interval = 100, maxTries = 50) {
+ return new Promise(resolve => {
+ BrowserTestUtils.waitForCondition(condition, message, interval, maxTries)
+ .then(resolve(condition()));
+ });
+}
+
+/**
+ * Find a message in the output.
+ *
+ * @param object hud
+ * The web console.
+ * @param string text
+ * A substring that can be found in the message.
+ * @param selector [optional]
+ * The selector to use in finding the message.
+ */
+function findMessage(hud, text, selector = ".message") {
+ const elements = Array.prototype.filter.call(
+ hud.ui.experimentalOutputNode.querySelectorAll(selector),
+ (el) => el.textContent.includes(text)
+ );
+ return elements.pop();
+}
diff --git a/devtools/client/webconsole/new-console-output/utils/messages.js b/devtools/client/webconsole/new-console-output/utils/messages.js
index b8685a16b4b3..b464a778142d 100644
--- a/devtools/client/webconsole/new-console-output/utils/messages.js
+++ b/devtools/client/webconsole/new-console-output/utils/messages.js
@@ -83,11 +83,11 @@ function transformPacket(packet) {
break;
}
- const frame = {
- source: message.filename || null,
- line: message.lineNumber || null,
- column: message.columnNumber || null
- };
+ const frame = message.filename ? {
+ source: message.filename,
+ line: message.lineNumber,
+ column: message.columnNumber,
+ } : null;
return new ConsoleMessage({
source: MESSAGE_SOURCE.CONSOLE_API,
@@ -119,11 +119,11 @@ function transformPacket(packet) {
level = MESSAGE_LEVEL.INFO;
}
- const frame = {
+ const frame = pageError.sourceName ? {
source: pageError.sourceName,
line: pageError.lineNumber,
column: pageError.columnNumber
- };
+ } : null;
return new ConsoleMessage({
source: MESSAGE_SOURCE.JAVASCRIPT,
@@ -148,13 +148,18 @@ function transformPacket(packet) {
case "evaluationResult":
default: {
- let { result } = packet;
+ let {
+ exceptionMessage: messageText,
+ result: parameters
+ } = packet;
+ const level = messageText ? MESSAGE_LEVEL.ERROR : MESSAGE_LEVEL.LOG;
return new ConsoleMessage({
source: MESSAGE_SOURCE.JAVASCRIPT,
type: MESSAGE_TYPE.RESULT,
- level: MESSAGE_LEVEL.LOG,
- parameters: result,
+ level,
+ messageText,
+ parameters,
});
}
}
diff --git a/devtools/client/webconsole/new-console-output/utils/variables-view.js b/devtools/client/webconsole/new-console-output/utils/variables-view.js
index 3697a238b4a1..3cfee875a966 100644
--- a/devtools/client/webconsole/new-console-output/utils/variables-view.js
+++ b/devtools/client/webconsole/new-console-output/utils/variables-view.js
@@ -12,6 +12,9 @@
*
* Once JSTerm is also written in React/Redux, these will be actions.
*/
-exports.openVariablesView = (object) => {
- window.jsterm.openVariablesView({objectActor: object});
+exports.openVariablesView = (objectActor) => {
+ window.jsterm.openVariablesView({
+ objectActor,
+ autofocus: true,
+ });
};
diff --git a/devtools/client/webconsole/webconsole.js b/devtools/client/webconsole/webconsole.js
index e409ca1d5ec8..ec6fa93a8d53 100644
--- a/devtools/client/webconsole/webconsole.js
+++ b/devtools/client/webconsole/webconsole.js
@@ -582,6 +582,7 @@ WebConsoleFrame.prototype = {
// XXX: We should actually stop output from happening on old output
// panel, but for now let's just hide it.
this.experimentalOutputNode = this.outputNode.cloneNode();
+ this.experimentalOutputNode.removeAttribute("tabindex");
this.outputNode.hidden = true;
this.outputNode.parentNode.appendChild(this.experimentalOutputNode);
// @TODO Once the toolbox has been converted to React, see if passing
diff --git a/devtools/server/actors/utils/TabSources.js b/devtools/server/actors/utils/TabSources.js
index 312f0a9a17d2..56e862939fcb 100644
--- a/devtools/server/actors/utils/TabSources.js
+++ b/devtools/server/actors/utils/TabSources.js
@@ -406,7 +406,10 @@ TabSources.prototype = {
* @return Promise of a SourceMapConsumer
*/
fetchSourceMap: function (aSource) {
- if (this._sourceMaps.has(aSource)) {
+ if (!this._useSourceMaps) {
+ return resolve(null);
+ }
+ else if (this._sourceMaps.has(aSource)) {
return this._sourceMaps.get(aSource);
}
else if (!aSource || !aSource.sourceMapURL) {
@@ -457,10 +460,10 @@ TabSources.prototype = {
* them from aScriptURL.
*/
_fetchSourceMap: function (aAbsSourceMapURL, aSourceURL) {
- if (!this._useSourceMaps) {
- return resolve(null);
- }
- else if (this._sourceMapCache[aAbsSourceMapURL]) {
+ assert(this._useSourceMaps,
+ "Cannot fetch sourcemaps if they are disabled");
+
+ if (this._sourceMapCache[aAbsSourceMapURL]) {
return this._sourceMapCache[aAbsSourceMapURL];
}
diff --git a/devtools/server/tests/unit/test_listsources-04.js b/devtools/server/tests/unit/test_listsources-04.js
new file mode 100644
index 000000000000..6da99a6cec1c
--- /dev/null
+++ b/devtools/server/tests/unit/test_listsources-04.js
@@ -0,0 +1,58 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Check getSources functionality with sourcemaps.
+ */
+
+const {SourceNode} = require("source-map");
+
+function run_test() {
+ run_test_with_server(DebuggerServer, function () {
+ // Bug 1304144 - This test does not run in a worker because the
+ // `rpc` method which talks to the main thread does not work.
+ // run_test_with_server(WorkerDebuggerServer, do_test_finished);
+ do_test_finished();
+ });
+ do_test_pending();
+}
+
+function run_test_with_server(server, cb) {
+ Task.spawn(function*() {
+ initTestDebuggerServer(server);
+ const debuggee = addTestGlobal("test-sources", server);
+ const client = new DebuggerClient(server.connectPipe());
+ yield client.connect();
+ const [,,threadClient] = yield attachTestTabAndResume(client, "test-sources");
+
+ yield threadClient.reconfigure({ useSourceMaps: true });
+ addSources(debuggee);
+
+ threadClient.getSources(Task.async(function* (res) {
+ do_check_true(res.sources.length === 3, "3 sources exist");
+
+ yield threadClient.reconfigure({ useSourceMaps: false });
+
+ threadClient.getSources(function(res) {
+ do_check_true(res.sources.length === 1, "1 source exist");
+ client.close().then(cb);
+ });
+ }));
+ });
+}
+
+function addSources(debuggee) {
+ let { code, map } = (new SourceNode(null, null, null, [
+ new SourceNode(1, 0, "a.js", "function a() { return 'a'; }\n"),
+ new SourceNode(1, 0, "b.js", "function b() { return 'b'; }\n"),
+ new SourceNode(1, 0, "c.js", "function c() { return 'c'; }\n"),
+ ])).toStringWithSourceMap({
+ file: "abc.js",
+ sourceRoot: "http://example.com/www/js/"
+ });
+
+ code += "//# sourceMappingURL=data:text/json;base64," + btoa(map.toString());
+
+ Components.utils.evalInSandbox(code, debuggee, "1.8",
+ "http://example.com/www/js/abc.js", 1);
+}
diff --git a/devtools/server/tests/unit/xpcshell.ini b/devtools/server/tests/unit/xpcshell.ini
index b8097ef4fb84..cd5465f94691 100644
--- a/devtools/server/tests/unit/xpcshell.ini
+++ b/devtools/server/tests/unit/xpcshell.ini
@@ -165,6 +165,7 @@ skip-if = toolkit != "gonk"
[test_listsources-01.js]
[test_listsources-02.js]
[test_listsources-03.js]
+[test_listsources-04.js]
[test_new_source-01.js]
[test_sourcemaps-01.js]
[test_sourcemaps-02.js]
diff --git a/devtools/shared/locales/en-US/styleinspector.properties b/devtools/shared/locales/en-US/styleinspector.properties
index b56f36437512..c1c9d53590f5 100644
--- a/devtools/shared/locales/en-US/styleinspector.properties
+++ b/devtools/shared/locales/en-US/styleinspector.properties
@@ -53,12 +53,6 @@ rule.pseudoElement=Pseudo-elements
# pseudo element header
rule.selectedElement=This Element
-# LOCALIZATION NOTE (helpLinkTitle): For each style property
-# the user can hover it and get a help link button which allows one to
-# quickly jump to the documentation from the Mozilla Developer Network site.
-# This is the link title shown in the hover tooltip.
-helpLinkTitle=Read the documentation for this property
-
# LOCALIZATION NOTE (rule.warning.title): When an invalid property value is
# entered into the rule view a warning icon is displayed. This text is used for
# the title attribute of the warning icon.
@@ -142,7 +136,7 @@ styleinspector.contextmenu.showMdnDocs.accessKey=D
# LOCALIZATION NOTE (styleinspector.contextmenu.addNewRule): Text displayed in the
# rule view context menu for adding a new rule to the element.
-# This should match addRuleButton.tooltip in styleinspector.dtd
+# This should match inspector.addRule.tooltip in inspector.properties
styleinspector.contextmenu.addNewRule=Add New Rule
# LOCALIZATION NOTE (styleinspector.contextmenu.addRule.accessKey): Access key for
diff --git a/dom/media/systemservices/CamerasParent.cpp b/dom/media/systemservices/CamerasParent.cpp
index c43633664745..5eda8022f9d6 100644
--- a/dom/media/systemservices/CamerasParent.cpp
+++ b/dom/media/systemservices/CamerasParent.cpp
@@ -707,9 +707,8 @@ static bool
HasCameraPermission(const nsCString& aOrigin)
{
// Name used with nsIPermissionManager
- static const char* cameraPermission = "camera";
+ static const char* cameraPermission = "MediaManagerVideo";
bool allowed = false;
- bool permanent = false;
nsresult rv;
nsCOMPtr