diff --git a/browser/components/loop/content/js/conversationViews.js b/browser/components/loop/content/js/conversationViews.js index a0e038ef824..947eb730512 100644 --- a/browser/components/loop/content/js/conversationViews.js +++ b/browser/components/loop/content/js/conversationViews.js @@ -330,6 +330,7 @@ loop.conversationViews = (function(mozL10n) { var errorString; switch (this.props.failureReason) { + case FAILURE_DETAILS.NO_MEDIA: case FAILURE_DETAILS.UNABLE_TO_PUBLISH_MEDIA: errorString = mozL10n.get("no_media_failure_message"); break; diff --git a/browser/components/loop/content/js/conversationViews.jsx b/browser/components/loop/content/js/conversationViews.jsx index e5a4be3163d..9f8dd046b10 100644 --- a/browser/components/loop/content/js/conversationViews.jsx +++ b/browser/components/loop/content/js/conversationViews.jsx @@ -330,6 +330,7 @@ loop.conversationViews = (function(mozL10n) { var errorString; switch (this.props.failureReason) { + case FAILURE_DETAILS.NO_MEDIA: case FAILURE_DETAILS.UNABLE_TO_PUBLISH_MEDIA: errorString = mozL10n.get("no_media_failure_message"); break; diff --git a/browser/components/loop/content/shared/js/otSdkDriver.js b/browser/components/loop/content/shared/js/otSdkDriver.js index fc725f44159..f7db5325f21 100644 --- a/browser/components/loop/content/shared/js/otSdkDriver.js +++ b/browser/components/loop/content/shared/js/otSdkDriver.js @@ -978,7 +978,7 @@ loop.OTSdkDriver = (function() { var bucket = this.mozLoop.SHARING_STATE_CHANGE[type.toUpperCase() + "_" + (enabled ? "ENABLED" : "DISABLED")]; - if (!bucket) { + if (typeof bucket === "undefined") { console.error("No sharing state bucket found for '" + type + "'"); return; } diff --git a/browser/components/loop/modules/LoopRooms.jsm b/browser/components/loop/modules/LoopRooms.jsm index 67848107732..22efbb5d63a 100644 --- a/browser/components/loop/modules/LoopRooms.jsm +++ b/browser/components/loop/modules/LoopRooms.jsm @@ -241,7 +241,7 @@ let LoopRoomsInternal = { * @param {String} roomToken The token for the room that needs encrypting. */ queueForEncryption: function(roomToken) { - if (!this.encryptionQueue.queue.includes(roomToken)) { + if (this.encryptionQueue.queue.indexOf(roomToken) == -1) { this.encryptionQueue.queue.push(roomToken); } diff --git a/browser/components/loop/test/desktop-local/conversationViews_test.js b/browser/components/loop/test/desktop-local/conversationViews_test.js index 6f12a5785b4..2dde856da29 100644 --- a/browser/components/loop/test/desktop-local/conversationViews_test.js +++ b/browser/components/loop/test/desktop-local/conversationViews_test.js @@ -939,6 +939,15 @@ describe("loop.conversationViews", function () { expect(view.getDOMNode().querySelector("h2").textContent).eql("no_media_failure_message"); }); + it("should show 'no media' for FAILURE_DETAILS.NO_MEDIA reason", function() { + view = mountTestComponent({ + cancelCall: function() {}, + failureReason: FAILURE_DETAILS.NO_MEDIA + }); + + expect(view.getDOMNode().querySelector("h2").textContent).eql("no_media_failure_message"); + }); + it("should show 'generic_failure_title' when no reason is specified", function() { view = mountTestComponent({cancelCall: function() {}}); diff --git a/browser/components/loop/test/shared/otSdkDriver_test.js b/browser/components/loop/test/shared/otSdkDriver_test.js index 50f60e0b6f0..b6bd1fa6e28 100644 --- a/browser/components/loop/test/shared/otSdkDriver_test.js +++ b/browser/components/loop/test/shared/otSdkDriver_test.js @@ -78,16 +78,16 @@ describe("loop.OTSdkDriver", function () { mozLoop = { telemetryAddValue: sinon.stub(), TWO_WAY_MEDIA_CONN_LENGTH: { - SHORTER_THAN_10S: "SHORTER_THAN_10S", - BETWEEN_10S_AND_30S: "BETWEEN_10S_AND_30S", - BETWEEN_30S_AND_5M: "BETWEEN_30S_AND_5M", - MORE_THAN_5M: "MORE_THAN_5M" + SHORTER_THAN_10S: 0, + BETWEEN_10S_AND_30S: 1, + BETWEEN_30S_AND_5M: 2, + MORE_THAN_5M: 3 }, SHARING_STATE_CHANGE: { - WINDOW_ENABLED: "WINDOW_ENABLED", - WINDOW_DISABLED: "WINDOW_DISABLED", - BROWSER_ENABLED: "BROWSER_ENABLED", - BROWSER_DISABLED: "BROWSER_DISABLED" + WINDOW_ENABLED: 0, + WINDOW_DISABLED: 1, + BROWSER_ENABLED: 2, + BROWSER_DISABLED: 3 } }; diff --git a/browser/devtools/canvasdebugger/canvasdebugger.js b/browser/devtools/canvasdebugger/canvasdebugger.js index ab769c643c8..7518b6d3bb0 100644 --- a/browser/devtools/canvasdebugger/canvasdebugger.js +++ b/browser/devtools/canvasdebugger/canvasdebugger.js @@ -190,8 +190,8 @@ EventEmitter.decorate(this); /** * DOM query helpers. */ -function $(selector, target = document) target.querySelector(selector); -function $all(selector, target = document) target.querySelectorAll(selector); +let $ = (selector, target = document) => target.querySelector(selector); +let $all = (selector, target = document) => target.querySelectorAll(selector); /** * Helper for getting an nsIURL instance out of a string. diff --git a/browser/devtools/canvasdebugger/panel.js b/browser/devtools/canvasdebugger/panel.js index 8061a9552f2..b90d4d89815 100644 --- a/browser/devtools/canvasdebugger/panel.js +++ b/browser/devtools/canvasdebugger/panel.js @@ -57,7 +57,9 @@ CanvasDebuggerPanel.prototype = { // DevToolPanel API - get target() this._toolbox.target, + get target() { + return this._toolbox.target; + }, destroy: function() { // Make sure this panel is not already destroyed. diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-01.js b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-01.js index 032d5e53956..9b6ee4e4fc7 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-01.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-01.js @@ -6,7 +6,7 @@ * You can also use this initialization format as a template for other tests. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, front } = yield initCallWatcherBackend(SIMPLE_CANVAS_URL); ok(target, "Should have a target available."); diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-02.js b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-02.js index 8a98c19cc45..bb3f00d8b67 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-02.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-02.js @@ -6,7 +6,7 @@ * and that their stack is successfully retrieved. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, front } = yield initCallWatcherBackend(SIMPLE_CANVAS_URL); let navigated = once(target, "navigate"); diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-03.js b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-03.js index 32d94d59dae..ee29b98df75 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-03.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-03.js @@ -6,7 +6,7 @@ * for a canvas context. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, front } = yield initCanvasDebuggerBackend(SIMPLE_CANVAS_URL); let navigated = once(target, "navigate"); diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-04.js b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-04.js index 0684e2e714d..d3c7d766194 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-04.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-04.js @@ -6,7 +6,7 @@ * the correct thumbnails. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, front } = yield initCanvasDebuggerBackend(SIMPLE_CANVAS_URL); let navigated = once(target, "navigate"); diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-05.js b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-05.js index 3e475ec2bb5..e13dab9a411 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-05.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-05.js @@ -6,7 +6,7 @@ * the correct "end result" screenshot. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, front } = yield initCanvasDebuggerBackend(SIMPLE_CANVAS_URL); let navigated = once(target, "navigate"); diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-06.js b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-06.js index 9a279a4d56d..511db666786 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-06.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-06.js @@ -5,7 +5,7 @@ * Tests if screenshots for arbitrary draw calls are generated properly. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, front } = yield initCanvasDebuggerBackend(SIMPLE_CANVAS_TRANSPARENT_URL); let navigated = once(target, "navigate"); diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-07.js b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-07.js index b54913b57ec..deadd817596 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-07.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-07.js @@ -6,7 +6,7 @@ * by deferring the the most recent previous draw-call. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, front } = yield initCanvasDebuggerBackend(SIMPLE_CANVAS_URL); let navigated = once(target, "navigate"); diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-08.js b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-08.js index de40f2d1b13..f3aeda1a9a5 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-08.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-08.js @@ -6,7 +6,7 @@ * forms if the method's signature does not expect an enum. Bug 999687. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, front } = yield initCanvasDebuggerBackend(SIMPLE_BITMASKS_URL); let navigated = once(target, "navigate"); diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-09.js b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-09.js index 68321c8c996..d123e3319f7 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-09.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-09.js @@ -6,7 +6,7 @@ * forms if the method's signature does not expect an enum. Bug 999687. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, front } = yield initCanvasDebuggerBackend(WEBGL_ENUM_URL); let navigated = once(target, "navigate"); diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-10.js b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-10.js index 9761b4bac7f..672ef966276 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-10.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-10.js @@ -6,7 +6,7 @@ * after generating screenshots using the actor. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, front } = yield initCanvasDebuggerBackend(WEBGL_BINDINGS_URL); loadFrameScripts(); diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-11.js b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-11.js index ac862a49065..a202b5d8cae 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-11.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-11.js @@ -6,7 +6,7 @@ * for a canvas context, and that the generated screenshots are correct. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, front } = yield initCanvasDebuggerBackend(SET_TIMEOUT_URL); let navigated = once(target, "navigate"); diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-12.js b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-12.js index 498abb25c34..86e51931ea8 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-12.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-12.js @@ -6,7 +6,7 @@ * in the event no rAF loop is found. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, front } = yield initCanvasDebuggerBackend(NO_CANVAS_URL); loadFrameScripts(); diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-highlight.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-highlight.js index 230c9d005d9..2270f0ccf7a 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-highlight.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-highlight.js @@ -5,7 +5,7 @@ * Tests if certain function calls are properly highlighted in the UI. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, $, EVENTS, SnapshotsListView, CallsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-list.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-list.js index f661199c1d0..013830224f0 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-list.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-list.js @@ -6,7 +6,7 @@ * are properly displayed in the UI. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, $, EVENTS, SnapshotsListView, CallsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-search.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-search.js index 4c7ee90200b..de2105bb827 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-search.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-search.js @@ -5,7 +5,7 @@ * Tests if filtering the items in the call list works properly. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, $, EVENTS, SnapshotsListView, CallsListView } = panel.panelWin; let searchbox = $("#calls-searchbox"); diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-01.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-01.js index 8254fe4e397..92ca163e573 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-01.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-01.js @@ -5,7 +5,7 @@ * Tests if the a function call's stack is properly displayed in the UI. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_DEEP_STACK_URL); let { window, $, $all, EVENTS, SnapshotsListView, CallsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-02.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-02.js index ee85fee4c79..bc3be3e169b 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-02.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-02.js @@ -6,7 +6,7 @@ * and jumping to source in the debugger for the topmost call item works. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_DEEP_STACK_URL); let { window, $, $all, EVENTS, SnapshotsListView, CallsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-03.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-03.js index 70b392608b3..796e329123c 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-03.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-03.js @@ -6,7 +6,7 @@ * on a function call item. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_DEEP_STACK_URL); let { window, $, $all, EVENTS, SnapshotsListView, CallsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-clear.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-clear.js index 4dbc72fd777..c800820465b 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-clear.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-clear.js @@ -5,7 +5,7 @@ * Tests if clearing the snapshots list works as expected. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, EVENTS, SnapshotsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-img-screenshots.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-img-screenshots.js index 193becb4940..e96543e10ed 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-img-screenshots.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-img-screenshots.js @@ -5,7 +5,7 @@ * Tests if screenshots are properly displayed in the UI. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, $, EVENTS, SnapshotsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-img-thumbnails-01.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-img-thumbnails-01.js index 4d0df626883..41e8f7383a4 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-img-thumbnails-01.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-img-thumbnails-01.js @@ -5,7 +5,7 @@ * Tests if thumbnails are properly displayed in the UI. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, $, $all, EVENTS, SnapshotsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-img-thumbnails-02.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-img-thumbnails-02.js index e5e56dac5df..798bc090bd7 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-img-thumbnails-02.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-img-thumbnails-02.js @@ -6,7 +6,7 @@ * function call items and their respective screenshots. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, $, $all, EVENTS, SnapshotsListView, CallsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-open.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-open.js index 20b06dbae93..59c4d4cfb71 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-open.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-open.js @@ -5,7 +5,7 @@ * Tests that the frontend UI is properly configured when opening the tool. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { $ } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-record-01.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-record-01.js index 1b317127aa5..cd0358d3c6e 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-record-01.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-record-01.js @@ -5,7 +5,7 @@ * Tests whether the frontend behaves correctly while reording a snapshot. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, EVENTS, $, SnapshotsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-record-02.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-record-02.js index f25988d25d8..aee63a5746a 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-record-02.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-record-02.js @@ -5,7 +5,7 @@ * Tests whether the frontend displays a placeholder snapshot while recording. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, EVENTS, L10N, $, SnapshotsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-record-03.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-record-03.js index 456d992bc51..c3638610ee1 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-record-03.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-record-03.js @@ -6,7 +6,7 @@ * after finishing recording. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, EVENTS, $, SnapshotsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-record-04.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-record-04.js index 9bf921887a3..0ff9ed67f5f 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-record-04.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-record-04.js @@ -8,7 +8,7 @@ * of its loop, when the recording starts before the rAFs start. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(RAF_BEGIN_URL); let { window, EVENTS, gFront, SnapshotsListView } = panel.panelWin; loadFrameScripts(); diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-reload-01.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-reload-01.js index 9ebea8d9687..cf353aa2729 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-reload-01.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-reload-01.js @@ -5,7 +5,7 @@ * Tests that the frontend UI is properly reconfigured after reloading. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, $, EVENTS } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-reload-02.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-reload-02.js index 46c67295778..2747fd13f9d 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-reload-02.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-reload-02.js @@ -5,7 +5,7 @@ * Tests that the frontend UI is properly reconfigured after reloading. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, $, $all, EVENTS, SnapshotsListView, CallsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-slider-01.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-slider-01.js index adc39c238bb..cdce00bd1d3 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-slider-01.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-slider-01.js @@ -5,7 +5,7 @@ * Tests if the slider in the calls list view works as advertised. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, $, EVENTS, SnapshotsListView, CallsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-slider-02.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-slider-02.js index 974083fc076..5074ab206a0 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-slider-02.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-slider-02.js @@ -5,7 +5,7 @@ * Tests if the slider in the calls list view works as advertised. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, $, EVENTS, gFront, SnapshotsListView, CallsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-snapshot-select-01.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-snapshot-select-01.js index 13e4ed70c26..135f3b0e4f7 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-snapshot-select-01.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-snapshot-select-01.js @@ -6,7 +6,7 @@ * respective to their recorded animation frame. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, $, EVENTS, SnapshotsListView, CallsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-snapshot-select-02.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-snapshot-select-02.js index cceb8a56889..27a03fb517d 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-snapshot-select-02.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-snapshot-select-02.js @@ -6,7 +6,7 @@ * respective to their recorded animation frame. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, $, EVENTS, SnapshotsListView, CallsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-stepping.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-stepping.js index 8eecea1db77..d76449b91ef 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-stepping.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-stepping.js @@ -5,7 +5,7 @@ * Tests if the stepping buttons in the call list toolbar work as advertised. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(SIMPLE_CANVAS_URL); let { window, $, EVENTS, SnapshotsListView, CallsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-stop-01.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-stop-01.js index 6eddbaaefad..3a74e4b44ed 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-stop-01.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-stop-01.js @@ -5,7 +5,7 @@ * Tests that you can stop a recording that does not have a rAF cycle. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(NO_CANVAS_URL); let { window, EVENTS, $, SnapshotsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-stop-02.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-stop-02.js index 1c5ec718bbb..b062fbc5e39 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-stop-02.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-stop-02.js @@ -5,7 +5,7 @@ * Tests that a recording that does not have a rAF cycle fails after timeout. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(NO_CANVAS_URL); let { window, EVENTS, $, SnapshotsListView } = panel.panelWin; diff --git a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-stop-03.js b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-stop-03.js index cdc4115ace0..70948311dd7 100644 --- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-stop-03.js +++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-stop-03.js @@ -6,7 +6,7 @@ * after timeout. */ -function ifTestingSupported() { +function* ifTestingSupported() { let { target, panel } = yield initCanvasDebuggerFrontend(RAF_NO_CANVAS_URL); let { window, EVENTS, $, SnapshotsListView } = panel.panelWin; diff --git a/browser/devtools/shared/test/browser.ini b/browser/devtools/shared/test/browser.ini index 12899fc2415..02dfc15580b 100644 --- a/browser/devtools/shared/test/browser.ini +++ b/browser/devtools/shared/test/browser.ini @@ -66,6 +66,7 @@ support-files = [browser_graphs-09f.js] [browser_graphs-10a.js] [browser_graphs-10b.js] +[browser_graphs-10c.js] [browser_graphs-11a.js] [browser_graphs-11b.js] [browser_graphs-12.js] diff --git a/browser/devtools/shared/test/browser_graphs-10c.js b/browser/devtools/shared/test/browser_graphs-10c.js new file mode 100644 index 00000000000..e802f6c1462 --- /dev/null +++ b/browser/devtools/shared/test/browser_graphs-10c.js @@ -0,0 +1,86 @@ + +// Tests that graphs properly handle resizing. + +const TEST_DATA = [{ delta: 112, value: 48 }, { delta: 213, value: 59 }, { delta: 313, value: 60 }, { delta: 413, value: 59 }, { delta: 530, value: 59 }, { delta: 646, value: 58 }, { delta: 747, value: 60 }, { delta: 863, value: 48 }, { delta: 980, value: 37 }, { delta: 1097, value: 30 }, { delta: 1213, value: 29 }, { delta: 1330, value: 23 }, { delta: 1430, value: 10 }, { delta: 1534, value: 17 }, { delta: 1645, value: 20 }, { delta: 1746, value: 22 }, { delta: 1846, value: 39 }, { delta: 1963, value: 26 }, { delta: 2080, value: 27 }, { delta: 2197, value: 35 }, { delta: 2312, value: 47 }, { delta: 2412, value: 53 }, { delta: 2514, value: 60 }, { delta: 2630, value: 37 }, { delta: 2730, value: 36 }, { delta: 2830, value: 37 }, { delta: 2946, value: 36 }, { delta: 3046, value: 40 }, { delta: 3163, value: 47 }, { delta: 3280, value: 41 }, { delta: 3380, value: 35 }, { delta: 3480, value: 27 }, { delta: 3580, value: 39 }, { delta: 3680, value: 42 }, { delta: 3780, value: 49 }, { delta: 3880, value: 55 }, { delta: 3980, value: 60 }, { delta: 4080, value: 60 }, { delta: 4180, value: 60 }]; +let {LineGraphWidget} = Cu.import("resource:///modules/devtools/Graphs.jsm", {}); +let {Promise} = devtools.require("resource://gre/modules/Promise.jsm"); + +add_task(function*() { + yield promiseTab("about:blank"); + yield performTest(); + gBrowser.removeCurrentTab(); +}); + +function* performTest() { + let [host, win, doc] = yield createHost("window"); + doc.body.setAttribute("style", "position: fixed; width: 100%; height: 100%; margin: 0;"); + + let graph = new LineGraphWidget(doc.body, "fps"); + yield graph.once("ready"); + + let refreshCount = 0; + graph.on("refresh", () => refreshCount++); + + yield testGraph(host, graph); + + is(refreshCount, 2, "The graph should've been refreshed 2 times."); + + yield graph.destroy(); + host.destroy(); +} + +function* testGraph(host, graph) { + graph.setData(TEST_DATA); + + host._window.resizeTo(500, 500); + yield graph.once("refresh"); + let oldBounds = host.frame.getBoundingClientRect(); + + is (graph._width, oldBounds.width * window.devicePixelRatio, + "The window was properly resized (1)."); + is (graph._height, oldBounds.height * window.devicePixelRatio, + "The window was properly resized (1)."); + + dragStart(graph, 100); + dragStop(graph, 400); + + is(graph.getSelection().start, 100, + "The current selection start value is correct (1)."); + is(graph.getSelection().end, 400, + "The current selection end value is correct (1)."); + + info("Making sure the selection updates when the window is resized"); + + host._window.resizeTo(250, 250); + yield graph.once("refresh"); + let newBounds = host.frame.getBoundingClientRect(); + + is (graph._width, newBounds.width * window.devicePixelRatio, + "The window was properly resized (2)."); + is (graph._height, newBounds.height * window.devicePixelRatio, + "The window was properly resized (2)."); + + let ratio = oldBounds.width / newBounds.width; + info("The window resize ratio is: " + ratio); + + is(graph.getSelection().start, Math.round(100 / ratio), + "The current selection start value is correct (2)."); + is(graph.getSelection().end, Math.round(400 / ratio), + "The current selection end value is correct (2)."); +} + +// EventUtils just doesn't work! + +function dragStart(graph, x, y = 1) { + x /= window.devicePixelRatio; + y /= window.devicePixelRatio; + graph._onMouseMove({ testX: x, testY: y }); + graph._onMouseDown({ testX: x, testY: y }); +} + +function dragStop(graph, x, y = 1) { + x /= window.devicePixelRatio; + y /= window.devicePixelRatio; + graph._onMouseMove({ testX: x, testY: y }); + graph._onMouseUp({ testX: x, testY: y }); +} diff --git a/browser/devtools/shared/widgets/Graphs.jsm b/browser/devtools/shared/widgets/Graphs.jsm index b109a491709..4be2bcf28cc 100644 --- a/browser/devtools/shared/widgets/Graphs.jsm +++ b/browser/devtools/shared/widgets/Graphs.jsm @@ -684,6 +684,13 @@ AbstractCanvasGraph.prototype = { return; } + // Handle a changed size by mapping the old selection to the new width + if (this._width && newWidth && this.hasSelection()) { + let ratio = this._width / (newWidth * this._pixelRatio); + this._selection.start = Math.round(this._selection.start / ratio); + this._selection.end = Math.round(this._selection.end / ratio); + } + bounds.width = newWidth; bounds.height = newHeight; this._iframe.setAttribute("width", bounds.width); diff --git a/browser/devtools/styleinspector/computed-view.js b/browser/devtools/styleinspector/computed-view.js index b73fdd84ecc..e52d385dafd 100644 --- a/browser/devtools/styleinspector/computed-view.js +++ b/browser/devtools/styleinspector/computed-view.js @@ -151,6 +151,7 @@ function CssHtmlTree(aStyleInspector, aPageStyle) this._onClick = this._onClick.bind(this); this._onCopy = this._onCopy.bind(this); this._onCopyColor = this._onCopyColor.bind(this); + this._onCopyImageDataUrl = this._onCopyImageDataUrl.bind(this); this._onFilterStyles = this._onFilterStyles.bind(this); this._onFilterKeyPress = this._onFilterKeyPress.bind(this); this._onClearSearch = this._onClearSearch.bind(this); @@ -328,7 +329,7 @@ CssHtmlTree.prototype = { * - type {String} One of the VIEW_NODE_XXX_TYPE const in * style-inspector-overlays * - value {Object} Depends on the type of the node - * returns null of the node isn't anything we care about + * returns null if the node isn't anything we care about */ getNodeInfo: function(node) { if (!node) { @@ -351,7 +352,7 @@ CssHtmlTree.prototype = { return { type: overlays.VIEW_NODE_SELECTOR_TYPE, value: selectorText.trim() - } + }; } // Walk up the nodes to find out where node is @@ -715,6 +716,13 @@ CssHtmlTree.prototype = { command: this._onCopyColor }); + // Copy data URI + this.menuitemCopyImageDataUrl = createMenuItem(this._contextmenu, { + label: "styleinspector.contextmenu.copyImageDataUrl", + accesskey: "styleinspector.contextmenu.copyImageDataUrl.accessKey", + command: this._onCopyImageDataUrl + }); + // Show Original Sources this.menuitemSources= createMenuItem(this._contextmenu, { label: "ruleView.contextmenu.showOrigSources", @@ -745,6 +753,7 @@ CssHtmlTree.prototype = { this.menuitemSources.setAttribute("checked", showOrig); this.menuitemCopyColor.hidden = !this._isColorPopup(); + this.menuitemCopyImageDataUrl.hidden = !this._isImageUrlPopup(); }, /** @@ -757,14 +766,12 @@ CssHtmlTree.prototype = { _isColorPopup: function () { this._colorToCopy = ""; - let trigger = this.popupNode; - if (!trigger) { + + let container = this._getPopupNodeContainer(); + if (!container) { return false; } - let container = (trigger.nodeType == trigger.TEXT_NODE) ? - trigger.parentElement : trigger; - let isColorNode = el => el.dataset && "color" in el.dataset; while (!isColorNode(container)) { @@ -778,6 +785,52 @@ CssHtmlTree.prototype = { return true; }, + /** + * Check if the context menu popup was opened with a click on an image link + * If true, save the image url to this._imageUrlToCopy + */ + _isImageUrlPopup: function () { + this._imageUrlToCopy = ""; + + let container = this._getPopupNodeContainer(); + let isImageUrlNode = this._isImageUrlNode(container); + if (isImageUrlNode) { + this._imageUrlToCopy = container.href; + } + + return isImageUrlNode; + }, + + /** + * Check if a node is an image url + * @param {DOMNode} node The node which we want information about + * @return {Boolean} true if the node is an image url + */ + _isImageUrlNode: function (node) { + let nodeInfo = this.getNodeInfo(node); + if (!nodeInfo) { + return false + } + return nodeInfo.type == overlays.VIEW_NODE_IMAGE_URL_TYPE; + }, + + /** + * Get the DOM Node container for the current popupNode. + * If popupNode is a textNode, return the parent node, otherwise return popupNode itself. + * @return {DOMNode} + */ + _getPopupNodeContainer: function () { + let container = null; + let node = this.popupNode; + + if (node) { + let isTextNode = node.nodeType == node.TEXT_NODE; + container = isTextNode ? node.parentElement : node; + } + + return container; + }, + /** * Context menu handler. */ @@ -821,6 +874,22 @@ CssHtmlTree.prototype = { clipboardHelper.copyString(this._colorToCopy); }, + /** + * Retrieve the image data for the selected image url and copy it to the clipboard + */ + _onCopyImageDataUrl: Task.async(function*() { + let message; + try { + let inspectorFront = this.inspector.inspector; + let data = yield inspectorFront.getImageDataFromURL(this._imageUrlToCopy); + message = yield data.data.string(); + } catch (e) { + message = CssHtmlTree.l10n("styleinspector.copyImageDataUrlError"); + } + + clipboardHelper.copyString(message); + }), + /** * Copy selected text. * @@ -910,6 +979,10 @@ CssHtmlTree.prototype = { this.menuitemCopyColor.removeEventListener("command", this._onCopyColor); this.menuitemCopyColor = null; + // Destroy Copy Data URI menuitem. + this.menuitemCopyImageDataUrl.removeEventListener("command", this._onCopyImageDataUrl); + this.menuitemCopyImageDataUrl = null; + // Destroy the context menu. this._contextmenu.removeEventListener("popupshowing", this._contextMenuUpdate); this._contextmenu.parentNode.removeChild(this._contextmenu); diff --git a/browser/devtools/styleinspector/rule-view.js b/browser/devtools/styleinspector/rule-view.js index 3debeeacd86..b8193624aeb 100644 --- a/browser/devtools/styleinspector/rule-view.js +++ b/browser/devtools/styleinspector/rule-view.js @@ -1123,6 +1123,7 @@ function CssRuleView(aInspector, aDoc, aStore, aPageStyle) { this._onSelectAll = this._onSelectAll.bind(this); this._onCopy = this._onCopy.bind(this); this._onCopyColor = this._onCopyColor.bind(this); + this._onCopyImageDataUrl = this._onCopyImageDataUrl.bind(this); this._onToggleOrigSources = this._onToggleOrigSources.bind(this); this._onShowMdnDocs = this._onShowMdnDocs.bind(this); this._onFilterStyles = this._onFilterStyles.bind(this); @@ -1214,6 +1215,11 @@ CssRuleView.prototype = { accesskey: "ruleView.contextmenu.copyColor.accessKey", command: this._onCopyColor }); + this.menuitemCopyImageDataUrl = createMenuItem(this._contextmenu, { + label: "styleinspector.contextmenu.copyImageDataUrl", + accesskey: "styleinspector.contextmenu.copyImageDataUrl.accessKey", + command: this._onCopyImageDataUrl + }); this.menuitemSources = createMenuItem(this._contextmenu, { label: "ruleView.contextmenu.showOrigSources", accesskey: "ruleView.contextmenu.showOrigSources.accessKey", @@ -1348,6 +1354,7 @@ CssRuleView.prototype = { } this.menuitemCopyColor.hidden = !this._isColorPopup(); + this.menuitemCopyImageDataUrl.hidden = !this._isImageUrlPopup(); this.menuitemCopy.disabled = !copy; var showOrig = Services.prefs.getBoolPref(PREF_ORIG_SOURCES); @@ -1398,7 +1405,7 @@ CssRuleView.prototype = { pseudoElement: prop.rule.pseudoElement, sheetHref: prop.rule.domRule.href }; - } else if (classes.contains("theme-link") && prop) { + } else if (classes.contains("theme-link") && !classes.contains("ruleview-rule-source") && prop) { type = overlays.VIEW_NODE_IMAGE_URL_TYPE; value = { property: getPropertyNameAndValue(node).name, @@ -1430,14 +1437,11 @@ CssRuleView.prototype = { _isColorPopup: function () { this._colorToCopy = ""; - let trigger = this.doc.popupNode; - if (!trigger) { + let container = this._getPopupNodeContainer(); + if (!container) { return false; } - let container = (trigger.nodeType == trigger.TEXT_NODE) ? - trigger.parentElement : trigger; - let isColorNode = el => el.dataset && "color" in el.dataset; while (!isColorNode(container)) { @@ -1451,6 +1455,52 @@ CssRuleView.prototype = { return true; }, + /** + * Check if the context menu popup was opened with a click on an image link + * If true, save the image url to this._imageUrlToCopy + */ + _isImageUrlPopup: function () { + this._imageUrlToCopy = ""; + + let container = this._getPopupNodeContainer(); + let isImageUrlNode = this._isImageUrlNode(container); + if (isImageUrlNode) { + this._imageUrlToCopy = container.href; + } + + return isImageUrlNode; + }, + + /** + * Check if a node is an image url + * @param {DOMNode} node The node which we want information about + * @return {Boolean} true if the node is an image url + */ + _isImageUrlNode: function (node) { + let nodeInfo = this.getNodeInfo(node); + if (!nodeInfo) { + return false + } + return nodeInfo.type == overlays.VIEW_NODE_IMAGE_URL_TYPE; + }, + + /** + * Get the DOM Node container for the current popupNode. + * If popupNode is a textNode, return the parent node, otherwise return popupNode itself. + * @return {DOMNode} + */ + _getPopupNodeContainer: function () { + let container = null; + let node = this.doc.popupNode; + + if (node) { + let isTextNode = node.nodeType == node.TEXT_NODE; + container = isTextNode ? node.parentElement : node; + } + + return container; + }, + /** * Context menu handler. */ @@ -1525,6 +1575,22 @@ CssRuleView.prototype = { clipboardHelper.copyString(this._colorToCopy); }, + /** + * Retrieve the image data for the selected image url and copy it to the clipboard + */ + _onCopyImageDataUrl: Task.async(function*() { + let message; + try { + let inspectorFront = this.inspector.inspector; + let data = yield inspectorFront.getImageDataFromURL(this._imageUrlToCopy); + message = yield data.data.string(); + } catch (e) { + message = _strings.GetStringFromName("styleinspector.copyImageDataUrlError"); + } + + clipboardHelper.copyString(message); + }), + /** * Toggle the original sources pref. */ @@ -1729,6 +1795,10 @@ CssRuleView.prototype = { this.menuitemCopyColor.removeEventListener("command", this._onCopyColor); this.menuitemCopyColor = null; + // Destroy Copy Data URI menuitem. + this.menuitemCopyImageDataUrl.removeEventListener("command", this._onCopyImageDataUrl); + this.menuitemCopyImageDataUrl = null; + this.menuitemSources.removeEventListener("command", this._onToggleOrigSources); this.menuitemSources = null; diff --git a/browser/devtools/styleinspector/style-inspector-overlays.js b/browser/devtools/styleinspector/style-inspector-overlays.js index 6f3def550b7..c2e2d0ffa13 100644 --- a/browser/devtools/styleinspector/style-inspector-overlays.js +++ b/browser/devtools/styleinspector/style-inspector-overlays.js @@ -21,6 +21,7 @@ const { SwatchFilterTooltip } = require("devtools/shared/widgets/Tooltip"); const {CssLogic} = require("devtools/styleinspector/css-logic"); +const EventEmitter = require("devtools/toolkit/event-emitter"); const {Promise:promise} = Cu.import("resource://gre/modules/Promise.jsm", {}); Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://gre/modules/Services.jsm"); @@ -59,6 +60,8 @@ function HighlightersOverlay(view) { // Only initialize the overlay if at least one of the highlighter types is // supported this.supportsHighlighters = this.highlighterUtils.supportsCustomHighlighters(); + + EventEmitter.decorate(this); } exports.HighlightersOverlay = HighlightersOverlay; @@ -124,9 +127,13 @@ HighlightersOverlay.prototype = { if (type) { this.highlighterShown = type; let node = this.view.inspector.selection.nodeFront; - this._getHighlighter(type).then(highlighter => { - highlighter.show(node); - }); + this._getHighlighter(type) + .then(highlighter => highlighter.show(node)) + .then(shown => { + if (shown) { + this.emit("highlighter-shown"); + } + }); } }, @@ -176,6 +183,7 @@ HighlightersOverlay.prototype = { promise.then(null, Cu.reportError); } this.highlighterShown = null; + this.emit("highlighter-hidden"); }); } }, diff --git a/browser/devtools/styleinspector/test/browser.ini b/browser/devtools/styleinspector/test/browser.ini index 8747e503f7f..1bfc4fdc3ea 100644 --- a/browser/devtools/styleinspector/test/browser.ini +++ b/browser/devtools/styleinspector/test/browser.ini @@ -151,6 +151,7 @@ skip-if = e10s # bug 1040670 Cannot open inline styles in viewSourceUtils [browser_ruleview_user-property-reset.js] [browser_styleinspector_context-menu-copy-color_01.js] [browser_styleinspector_context-menu-copy-color_02.js] +[browser_styleinspector_context-menu-copy-data-uri.js] [browser_styleinspector_csslogic-content-stylesheets.js] [browser_styleinspector_output-parser.js] [browser_styleinspector_refresh_when_active.js] diff --git a/browser/devtools/styleinspector/test/browser_styleinspector_context-menu-copy-data-uri.js b/browser/devtools/styleinspector/test/browser_styleinspector_context-menu-copy-data-uri.js new file mode 100644 index 00000000000..95f3523ed33 --- /dev/null +++ b/browser/devtools/styleinspector/test/browser_styleinspector_context-menu-copy-data-uri.js @@ -0,0 +1,99 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const PROPERTIES_URL = "chrome://global/locale/devtools/styleinspector.properties"; +const TEST_DATA_URI = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs="; + +// invalid URL still needs to be reachable otherwise getImageDataUrl will timeout. +// Reusing the properties bundle URL as a workaround +const INVALID_IMAGE_URI = PROPERTIES_URL; + +const ERROR_MESSAGE = Services.strings + .createBundle(PROPERTIES_URL) + .GetStringFromName("styleinspector.copyImageDataUrlError"); + +add_task(function*() { + const PAGE_CONTENT = [ + "", + "
Valid background image
", + "
Invalid background image
" + ].join("\n"); + + yield addTab("data:text/html;charset=utf8," + encodeURIComponent(PAGE_CONTENT)); + + yield startTest(); +}); + +function* startTest() { + info("Opening rule view"); + let ruleViewData = yield openRuleView(); + + info("Test valid background image URL in rule view"); + yield testCopyImageDataUrlToClipboard(ruleViewData, ".valid-background", TEST_DATA_URI); + info("Test invalid background image URL in rue view"); + yield testCopyImageDataUrlToClipboard(ruleViewData, ".invalid-background", ERROR_MESSAGE); + + info("Opening computed view"); + let computedViewData = yield openComputedView(); + + info("Test valid background image URL in computed view"); + yield testCopyImageDataUrlToClipboard(computedViewData, ".valid-background", TEST_DATA_URI); + info("Test invalid background image URL in computed view"); + yield testCopyImageDataUrlToClipboard(computedViewData, ".invalid-background", ERROR_MESSAGE); +} + +function* testCopyImageDataUrlToClipboard({view, inspector}, selector, expected) { + info("Select node in inspector panel"); + yield selectNode(selector, inspector); + + info("Retrieve background-image link for selected node in current styleinspector view"); + let property = getBackgroundImageProperty(view, selector); + let imageLink = property.valueSpan.querySelector(".theme-link"); + ok(imageLink, "Background-image link element found"); + + info("Simulate right click on the background-image URL"); + let popup = once(view._contextmenu, "popupshown"); + + // Cannot rely on synthesizeMouseAtCenter here. The image URL can be displayed on several lines. + // A click simulated at the exact center may click between the lines and miss the target + // Instead, using the top-left corner of first client rect, with an offset of 2 pixels. + let rect = imageLink.getClientRects()[0]; + let x = rect.left + 2; + let y = rect.top + 2; + + EventUtils.synthesizeMouseAtPoint(x, y, {button: 2, type: "contextmenu"}, getViewWindow(view)); + yield popup; + + info("Context menu is displayed"); + ok(!view.menuitemCopyImageDataUrl.hidden, "\"Copy Image Data-URL\" menu entry is displayed"); + + info("Click Copy Data URI and wait for clipboard"); + yield waitForClipboard(() => view.menuitemCopyImageDataUrl.click(), expected); + + info("Hide context menu"); + view._contextmenu.hidePopup(); +} + +function getBackgroundImageProperty(view, selector) { + let isRuleView = view instanceof CssRuleView; + if (isRuleView) { + return getRuleViewProperty(view, selector, "background-image"); + } else { + return getComputedViewProperty(view, "background-image"); + } +} + +/** + * Function that returns the window for a given view. + */ +function getViewWindow(view) { + let viewDocument = view.styleDocument ? view.styleDocument : view.doc; + return viewDocument.defaultView; +} diff --git a/browser/devtools/styleinspector/test/browser_styleinspector_transform-highlighter-02.js b/browser/devtools/styleinspector/test/browser_styleinspector_transform-highlighter-02.js index 3c00d30087d..64d8f0bb666 100644 --- a/browser/devtools/styleinspector/test/browser_styleinspector_transform-highlighter-02.js +++ b/browser/devtools/styleinspector/test/browser_styleinspector_transform-highlighter-02.js @@ -36,7 +36,9 @@ add_task(function*() { info("Faking a mousemove on a transform property"); ({valueSpan} = getRuleViewProperty(rView, "body", "transform")); + let onHighlighterShown = hs.once("highlighter-shown"); hs._onMouseMove({target: valueSpan}); + yield onHighlighterShown; ok(hs.promises[TYPE], "The highlighter is being initialized"); let h = yield hs.promises[TYPE]; is(h, hs.highlighters[TYPE], "The initialized highlighter is the right one"); @@ -57,7 +59,9 @@ add_task(function*() { info("Faking a mousemove on a transform property"); ({valueSpan} = getComputedViewProperty(cView, "transform")); + onHighlighterShown = hs.once("highlighter-shown"); hs._onMouseMove({target: valueSpan}); + yield onHighlighterShown; ok(hs.promises[TYPE], "The highlighter is being initialized"); h = yield hs.promises[TYPE]; is(h, hs.highlighters[TYPE], "The initialized highlighter is the right one"); diff --git a/browser/devtools/styleinspector/test/browser_styleinspector_transform-highlighter-03.js b/browser/devtools/styleinspector/test/browser_styleinspector_transform-highlighter-03.js index 7b0a25c2c37..06041c412ea 100644 --- a/browser/devtools/styleinspector/test/browser_styleinspector_transform-highlighter-03.js +++ b/browser/devtools/styleinspector/test/browser_styleinspector_transform-highlighter-03.js @@ -39,53 +39,64 @@ add_task(function*() { this.nodeFront = nodeFront; this.isShown = true; this.nbOfTimesShown ++; + return promise.resolve(true); }, hide: function() { this.nodeFront = null; this.isShown = false; + return promise.resolve(); } }; // Inject the mock highlighter in the rule-view - rView.highlighters.promises[TYPE] = { - then: function(cb) { - cb(HighlighterFront); - } - }; + let hs = rView.highlighters; + hs.promises[TYPE] = promise.resolve(HighlighterFront); let {valueSpan} = getRuleViewProperty(rView, "body", "transform"); info("Checking that the HighlighterFront's show/hide methods are called"); - rView.highlighters._onMouseMove({target: valueSpan}); + let onHighlighterShown = hs.once("highlighter-shown"); + hs._onMouseMove({target: valueSpan}); + yield onHighlighterShown; ok(HighlighterFront.isShown, "The highlighter is shown"); - rView.highlighters._onMouseLeave(); + let onHighlighterHidden = hs.once("highlighter-hidden"); + hs._onMouseLeave(); + yield onHighlighterHidden; ok(!HighlighterFront.isShown, "The highlighter is hidden"); info("Checking that hovering several times over the same property doesn't" + " show the highlighter several times"); let nb = HighlighterFront.nbOfTimesShown; - rView.highlighters._onMouseMove({target: valueSpan}); + onHighlighterShown = hs.once("highlighter-shown"); + hs._onMouseMove({target: valueSpan}); + yield onHighlighterShown; is(HighlighterFront.nbOfTimesShown, nb + 1, "The highlighter was shown once"); - rView.highlighters._onMouseMove({target: valueSpan}); - rView.highlighters._onMouseMove({target: valueSpan}); + hs._onMouseMove({target: valueSpan}); + hs._onMouseMove({target: valueSpan}); is(HighlighterFront.nbOfTimesShown, nb + 1, "The highlighter was shown once, after several mousemove"); info("Checking that the right NodeFront reference is passed"); yield selectNode("html", inspector); ({valueSpan} = getRuleViewProperty(rView, "html", "transform")); - rView.highlighters._onMouseMove({target: valueSpan}); + onHighlighterShown = hs.once("highlighter-shown"); + hs._onMouseMove({target: valueSpan}); + yield onHighlighterShown; is(HighlighterFront.nodeFront.tagName, "HTML", "The right NodeFront is passed to the highlighter (1)"); yield selectNode("body", inspector); ({valueSpan} = getRuleViewProperty(rView, "body", "transform")); - rView.highlighters._onMouseMove({target: valueSpan}); + onHighlighterShown = hs.once("highlighter-shown"); + hs._onMouseMove({target: valueSpan}); + yield onHighlighterShown; is(HighlighterFront.nodeFront.tagName, "BODY", "The right NodeFront is passed to the highlighter (2)"); info("Checking that the highlighter gets hidden when hovering a non-transform property"); ({valueSpan} = getRuleViewProperty(rView, "body", "color")); - rView.highlighters._onMouseMove({target: valueSpan}); + onHighlighterHidden = hs.once("highlighter-hidden"); + hs._onMouseMove({target: valueSpan}); + yield onHighlighterHidden; ok(!HighlighterFront.isShown, "The highlighter is hidden"); }); diff --git a/browser/devtools/styleinspector/test/browser_styleinspector_transform-highlighter-04.js b/browser/devtools/styleinspector/test/browser_styleinspector_transform-highlighter-04.js index a70eb0a477b..ae253f37ae5 100644 --- a/browser/devtools/styleinspector/test/browser_styleinspector_transform-highlighter-04.js +++ b/browser/devtools/styleinspector/test/browser_styleinspector_transform-highlighter-04.js @@ -55,7 +55,9 @@ add_task(function*() { info("Faking a mousemove on the now unoverriden property"); ({valueSpan} = getRuleViewProperty(rView, "div", "transform")); + let onHighlighterShown = hs.once("highlighter-shown"); hs._onMouseMove({target: valueSpan}); + yield onHighlighterShown; ok(hs.promises[TYPE], "The highlighter is being initialized now"); let h = yield hs.promises[TYPE]; is(h, hs.highlighters[TYPE], "The initialized highlighter is the right one"); diff --git a/configure.in b/configure.in index cd2fbb169a5..31e0b844fea 100644 --- a/configure.in +++ b/configure.in @@ -431,7 +431,7 @@ if test -z "$RUSTC" -a -n "$MOZ_RUST"; then To compile rust language sources, you must have 'rustc' in your path. See http://www.rust-lang.org/ for more information.]) fi -if test -n "$MOZ_RUST" -a -z "$_RUSTC_MAJOR_VERSION" -o \ +if test -n "$MOZ_RUST" && test -z "$_RUSTC_MAJOR_VERSION" -o \ "$_RUSTC_MAJOR_VERSION" -lt 1; then AC_MSG_ERROR([Rust compiler ${RUSTC_VERSION} is too old. To compile rust language sources please install at least diff --git a/mobile/android/base/BrowserApp.java b/mobile/android/base/BrowserApp.java index db4f93495a6..ae85e3882f6 100644 --- a/mobile/android/base/BrowserApp.java +++ b/mobile/android/base/BrowserApp.java @@ -548,6 +548,8 @@ public class BrowserApp extends GeckoApp } private void showBookmarkAddedToast() { + // This flow is from the option menu which has check to see if a bookmark was already added. + // So, it is safe here to show the toast that bookmark_added without any checks. getButtonToast().show(false, getResources().getString(R.string.bookmark_added), ButtonToast.LENGTH_SHORT, diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index a42e5aa1941..4423194c845 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -559,11 +559,12 @@ public abstract class GeckoApp ThreadUtils.postToBackgroundThread(new Runnable() { @Override public void run() { - db.addBookmark(getContentResolver(), title, url); + final boolean bookmarkAdded = db.addBookmark(getContentResolver(), title, url); + final int resId = bookmarkAdded ? R.string.bookmark_added : R.string.bookmark_already_added; ThreadUtils.postToUiThread(new Runnable() { @Override public void run() { - Toast.makeText(context, R.string.bookmark_added, Toast.LENGTH_SHORT).show(); + Toast.makeText(context, resId, Toast.LENGTH_SHORT).show(); } }); } diff --git a/mobile/android/base/db/BrowserDB.java b/mobile/android/base/db/BrowserDB.java index 344c71f4cbe..26881c76850 100644 --- a/mobile/android/base/db/BrowserDB.java +++ b/mobile/android/base/db/BrowserDB.java @@ -107,7 +107,7 @@ public interface BrowserDB { public abstract String getUrlForKeyword(ContentResolver cr, String keyword); public abstract boolean isBookmark(ContentResolver cr, String uri); - public abstract void addBookmark(ContentResolver cr, String title, String uri); + public abstract boolean addBookmark(ContentResolver cr, String title, String uri); public abstract Cursor getBookmarkForUrl(ContentResolver cr, String url); public abstract void removeBookmarksWithURL(ContentResolver cr, String uri); public abstract void registerBookmarkObserver(ContentResolver cr, ContentObserver observer); diff --git a/mobile/android/base/db/LocalBrowserDB.java b/mobile/android/base/db/LocalBrowserDB.java index ad8942c353c..9a897b185e7 100644 --- a/mobile/android/base/db/LocalBrowserDB.java +++ b/mobile/android/base/db/LocalBrowserDB.java @@ -939,9 +939,34 @@ public class LocalBrowserDB implements BrowserDB { @Override @RobocopTarget - public void addBookmark(ContentResolver cr, String title, String uri) { + public boolean addBookmark(ContentResolver cr, String title, String uri) { long folderId = getFolderIdFromGuid(cr, Bookmarks.MOBILE_FOLDER_GUID); + if (isBookmarkForUrlInFolder(cr, uri, folderId)) { + // Bookmark added already. + return false; + } + + // Add a new bookmark. addBookmarkItem(cr, title, uri, folderId); + return true; + } + + private boolean isBookmarkForUrlInFolder(ContentResolver cr, String uri, long folderId) { + final Cursor c = cr.query(bookmarksUriWithLimit(1), + new String[] { Bookmarks._ID }, + Bookmarks.URL + " = ? AND " + Bookmarks.PARENT + " = ? AND " + Bookmarks.IS_DELETED + " == 0", + new String[] { uri, String.valueOf(folderId) }, + Bookmarks.URL); + + if (c == null) { + return false; + } + + try { + return c.getCount() > 0; + } finally { + c.close(); + } } @Override diff --git a/mobile/android/base/db/StubBrowserDB.java b/mobile/android/base/db/StubBrowserDB.java index 9269fd0f139..66081d265f9 100644 --- a/mobile/android/base/db/StubBrowserDB.java +++ b/mobile/android/base/db/StubBrowserDB.java @@ -250,7 +250,8 @@ public class StubBrowserDB implements BrowserDB { } @RobocopTarget - public void addBookmark(ContentResolver cr, String title, String uri) { + public boolean addBookmark(ContentResolver cr, String title, String uri) { + return false; } @RobocopTarget diff --git a/mobile/android/base/locales/en-US/android_strings.dtd b/mobile/android/base/locales/en-US/android_strings.dtd index 6865a7c9a88..d17596412e8 100644 --- a/mobile/android/base/locales/en-US/android_strings.dtd +++ b/mobile/android/base/locales/en-US/android_strings.dtd @@ -44,6 +44,10 @@ + + diff --git a/mobile/android/base/strings.xml.in b/mobile/android/base/strings.xml.in index e45efa6b88d..5b253770f74 100644 --- a/mobile/android/base/strings.xml.in +++ b/mobile/android/base/strings.xml.in @@ -80,6 +80,7 @@ &bookmark; &bookmark_remove; &bookmark_added; + &bookmark_already_added; &bookmark_removed; &bookmark_updated; &bookmark_options; diff --git a/mobile/android/tests/browser/robocop/DatabaseHelper.java b/mobile/android/tests/browser/robocop/DatabaseHelper.java index e950af508b7..a589d351661 100644 --- a/mobile/android/tests/browser/robocop/DatabaseHelper.java +++ b/mobile/android/tests/browser/robocop/DatabaseHelper.java @@ -50,14 +50,12 @@ class DatabaseHelper { } /** - * Adds a bookmark, or updates the bookmark title if the url already exists. - * - * The LocalBrowserDB.addBookmark implementation handles updating existing bookmarks. + * Adds a bookmark. */ - protected void addOrUpdateMobileBookmark(String title, String url) { + protected void addMobileBookmark(String title, String url) { final ContentResolver resolver = mActivity.getContentResolver(); getProfileDB().addBookmark(resolver, title, url); - mAsserter.ok(true, "Inserting/updating a new bookmark", "Inserting/updating the bookmark with the title = " + title + " and the url = " + url); + mAsserter.ok(true, "Inserting a new bookmark", "Inserting the bookmark with the title = " + title + " and the url = " + url); } /** diff --git a/mobile/android/tests/browser/robocop/testBookmark.java b/mobile/android/tests/browser/robocop/testBookmark.java index 1a5c26537be..1744c3ee147 100644 --- a/mobile/android/tests/browser/robocop/testBookmark.java +++ b/mobile/android/tests/browser/robocop/testBookmark.java @@ -31,7 +31,7 @@ public class testBookmark extends AboutHomeTest { mAsserter.ok(mDatabaseHelper.isBookmark(url), "Checking that " + url + " is bookmarked by default", url + " is bookmarked"); } - mDatabaseHelper.addOrUpdateMobileBookmark(mStringHelper.ROBOCOP_BLANK_PAGE_01_TITLE, BOOKMARK_URL); + mDatabaseHelper.addMobileBookmark(mStringHelper.ROBOCOP_BLANK_PAGE_01_TITLE, BOOKMARK_URL); waitForBookmarked(true); isBookmarkDisplayed(BOOKMARK_URL); diff --git a/mobile/android/tests/browser/robocop/testBookmarkKeyword.java b/mobile/android/tests/browser/robocop/testBookmarkKeyword.java index 31e3c0c0525..363954bfaff 100644 --- a/mobile/android/tests/browser/robocop/testBookmarkKeyword.java +++ b/mobile/android/tests/browser/robocop/testBookmarkKeyword.java @@ -13,7 +13,7 @@ public class testBookmarkKeyword extends AboutHomeTest { final String keyword = "testkeyword"; // Add a bookmark, and update it to have a keyword. - mDatabaseHelper.addOrUpdateMobileBookmark(mStringHelper.ROBOCOP_BLANK_PAGE_01_TITLE, url); + mDatabaseHelper.addMobileBookmark(mStringHelper.ROBOCOP_BLANK_PAGE_01_TITLE, url); mDatabaseHelper.updateBookmark(url, mStringHelper.ROBOCOP_BLANK_PAGE_01_TITLE, keyword); // Enter the keyword in the urlbar. diff --git a/mobile/android/tests/browser/robocop/testBookmarklets.java b/mobile/android/tests/browser/robocop/testBookmarklets.java index 218d7062728..c4fdc4d6b69 100644 --- a/mobile/android/tests/browser/robocop/testBookmarklets.java +++ b/mobile/android/tests/browser/robocop/testBookmarklets.java @@ -40,7 +40,7 @@ public class testBookmarklets extends AboutHomeTest { // add the bookmarklet to the database. there's currently no way to // add this using the UI, so we go through the content provider. - mDatabaseHelper.addOrUpdateMobileBookmark(title, js); + mDatabaseHelper.addMobileBookmark(title, js); // Open about:home in the Bookmarks page openAboutHomeTab(AboutHomeTabs.BOOKMARKS); diff --git a/mobile/android/tests/browser/robocop/testBookmarksPanel.java b/mobile/android/tests/browser/robocop/testBookmarksPanel.java index 9b4508b06fc..a98bfdb30a9 100644 --- a/mobile/android/tests/browser/robocop/testBookmarksPanel.java +++ b/mobile/android/tests/browser/robocop/testBookmarksPanel.java @@ -21,7 +21,7 @@ public class testBookmarksPanel extends AboutHomeTest { initializeProfile(); // Add a mobile bookmark. - mDatabaseHelper.addOrUpdateMobileBookmark(mStringHelper.ROBOCOP_BLANK_PAGE_01_TITLE, BOOKMARK_URL); + mDatabaseHelper.addMobileBookmark(mStringHelper.ROBOCOP_BLANK_PAGE_01_TITLE, BOOKMARK_URL); openAboutHomeTab(AboutHomeTabs.BOOKMARKS); diff --git a/mobile/android/tests/browser/robocop/testClearPrivateData.java b/mobile/android/tests/browser/robocop/testClearPrivateData.java index 06d83c3cfb3..00b5306a70f 100644 --- a/mobile/android/tests/browser/robocop/testClearPrivateData.java +++ b/mobile/android/tests/browser/robocop/testClearPrivateData.java @@ -38,7 +38,7 @@ public class testClearPrivateData extends PixelTest { loadUrlAndWait(blank1); verifyUrlBarTitle(blank1); - mDatabaseHelper.addOrUpdateMobileBookmark(mStringHelper.ROBOCOP_BLANK_PAGE_02_TITLE, blank2); + mDatabaseHelper.addMobileBookmark(mStringHelper.ROBOCOP_BLANK_PAGE_02_TITLE, blank2); // Checking that the history list is not empty verifyHistoryCount(1); diff --git a/mobile/android/tests/browser/robocop/testImportFromAndroid.java b/mobile/android/tests/browser/robocop/testImportFromAndroid.java index 1a0dfe3a537..08851f2bc99 100644 --- a/mobile/android/tests/browser/robocop/testImportFromAndroid.java +++ b/mobile/android/tests/browser/robocop/testImportFromAndroid.java @@ -113,7 +113,7 @@ public class testImportFromAndroid extends AboutHomeTest { for (String url:androidBookmarks) { // Add every 3rd bookmark to Firefox Mobile if ((androidBookmarks.indexOf(url) % 3) == 0) { - mDatabaseHelper.addOrUpdateMobileBookmark("Bookmark Number" + String.valueOf(androidBookmarks.indexOf(url)), url); + mDatabaseHelper.addMobileBookmark("Bookmark Number" + String.valueOf(androidBookmarks.indexOf(url)), url); } } diff --git a/toolkit/components/aboutperformance/content/aboutPerformance.js b/toolkit/components/aboutperformance/content/aboutPerformance.js index 61e4dc31668..4cb0a7c1feb 100644 --- a/toolkit/components/aboutperformance/content/aboutPerformance.js +++ b/toolkit/components/aboutperformance/content/aboutPerformance.js @@ -23,6 +23,57 @@ const MEASURES = [ {key: "ticks", percentOfDeltaT: false, label: "Activations"}, ]; +/** + * Used to control the live updates in the performance page. + */ +let AutoUpdate = { + + /** + * The timer that is created when setInterval is called. + */ + _timerId: null, + + /** + * The dropdown DOM element. + */ + _intervalDropdown: null, + + /** + * Starts updating the performance data if the updates are paused. + */ + start: function () { + if (AutoUpdate._intervalDropdown == null){ + AutoUpdate._intervalDropdown = document.getElementById("intervalDropdown"); + } + + if (AutoUpdate._timerId == null) { + let dropdownIndex = AutoUpdate._intervalDropdown.selectedIndex; + let dropdownValue = AutoUpdate._intervalDropdown.options[dropdownIndex].value; + AutoUpdate._timerId = window.setInterval(update, dropdownValue); + } + }, + + /** + * Stops the updates if the data is updating. + */ + stop: function () { + if (AutoUpdate._timerId == null) { + return; + } + clearInterval(AutoUpdate._timerId); + AutoUpdate._timerId = null; + }, + + /** + * Updates the refresh interval when the dropdown selection is changed. + */ + updateRefreshRate: function () { + AutoUpdate.stop(); + AutoUpdate.start(); + } + +}; + let State = { /** * @type{PerformanceData} @@ -50,7 +101,7 @@ let State = { * - `deltaT`: the number of milliseconds elapsed since the data * was last displayed. */ - update: function() { + update: function () { let snapshot = PerformanceStats.getSnapshot(); let newData = new Map(); let deltas = []; @@ -237,9 +288,11 @@ function updateLiveData() { function go() { // Compute initial state immediately, then wait a little // before we start computing diffs and refreshing. - State.update(); + document.getElementById("playButton").addEventListener("click", () => AutoUpdate.start()); + document.getElementById("pauseButton").addEventListener("click", () => AutoUpdate.stop()); - window.setTimeout(() => { - window.setInterval(update, 10000); - }, 1000); -} + document.getElementById("intervalDropdown").addEventListener("change", () => AutoUpdate.updateRefreshRate()); + + State.update(); + setTimeout(update, 1000); +} \ No newline at end of file diff --git a/toolkit/components/aboutperformance/content/aboutPerformance.xhtml b/toolkit/components/aboutperformance/content/aboutPerformance.xhtml index 53203888d5d..e13aa07b132 100644 --- a/toolkit/components/aboutperformance/content/aboutPerformance.xhtml +++ b/toolkit/components/aboutperformance/content/aboutPerformance.xhtml @@ -87,6 +87,16 @@

Performance monitor

+ + + +
diff --git a/toolkit/devtools/DevToolsUtils.js b/toolkit/devtools/DevToolsUtils.js index c0ffde6354c..eeae7e2c528 100644 --- a/toolkit/devtools/DevToolsUtils.js +++ b/toolkit/devtools/DevToolsUtils.js @@ -120,7 +120,7 @@ exports.zip = function zip(a, b) { */ exports.executeSoon = function executeSoon(aFn) { if (isWorker) { - require("Timer").setTimeout(aFn, 0); + setImmediate(aFn); } else { Services.tm.mainThread.dispatch({ run: exports.makeInfallible(aFn) diff --git a/toolkit/devtools/server/actors/highlighter.js b/toolkit/devtools/server/actors/highlighter.js index 45a37c1c254..bdfbeabe809 100644 --- a/toolkit/devtools/server/actors/highlighter.js +++ b/toolkit/devtools/server/actors/highlighter.js @@ -7,7 +7,7 @@ const {Cu, Cc, Ci} = require("chrome"); const Services = require("Services"); const protocol = require("devtools/server/protocol"); -const {Arg, Option, method} = protocol; +const {Arg, Option, method, RetVal} = protocol; const events = require("sdk/event/core"); const Heritage = require("sdk/core/heritage"); const {CssLogic} = require("devtools/styleinspector/css-logic"); @@ -455,17 +455,21 @@ let CustomHighlighterActor = exports.CustomHighlighterActor = protocol.ActorClas * * @param NodeActor The node to be highlighted * @param Object Options for the custom highlighter + * @return Boolean True, if the highlighter has been successfully shown (FF41+) */ show: method(function(node, options) { if (!node || !isNodeValid(node.rawNode) || !this._highlighter) { - return; + return false; } - this._highlighter.show(node.rawNode, options); + return this._highlighter.show(node.rawNode, options); }, { request: { node: Arg(0, "domnode"), options: Arg(1, "nullable:json") + }, + response: { + value: RetVal("nullable:boolean") } }), @@ -849,7 +853,7 @@ AutoRefreshHighlighter.prototype = { let isSameOptions = this._isSameOptions(options); if (!isNodeValid(node) || (isSameNode && isSameOptions)) { - return; + return false; } this.options = options; @@ -858,9 +862,12 @@ AutoRefreshHighlighter.prototype = { this.currentNode = node; this._updateAdjustedQuads(); this._startRefreshLoop(); - this._show(); - this.emit("shown"); + let shown = this._show(); + if (shown) { + this.emit("shown"); + } + return shown; }, /** @@ -942,6 +949,7 @@ AutoRefreshHighlighter.prototype = { // To be implemented by sub classes // When called, sub classes should actually show the highlighter for // this.currentNode, potentially using options in this.options + throw new Error("Custom highlighter class had to implement _show method"); }, _update: function() { @@ -949,11 +957,13 @@ AutoRefreshHighlighter.prototype = { // When called, sub classes should update the highlighter shown for // this.currentNode // This is called as a result of a page scroll, zoom or repaint + throw new Error("Custom highlighter class had to implement _update method"); }, _hide: function() { // To be implemented by sub classes // When called, sub classes should actually hide the highlighter + throw new Error("Custom highlighter class had to implement _hide method"); }, _startRefreshLoop: function() { @@ -1229,9 +1239,10 @@ BoxModelHighlighter.prototype = Heritage.extend(AutoRefreshHighlighter.prototype this.options.region = "content"; } - this._update(); + let shown = this._update(); this._trackMutations(); this.emit("ready"); + return shown; }, /** @@ -1259,6 +1270,7 @@ BoxModelHighlighter.prototype = Heritage.extend(AutoRefreshHighlighter.prototype * Should be called whenever node size or attributes change */ _update: function() { + let shown = false; setIgnoreLayoutChanges(true); if (this._updateBoxModel()) { @@ -1268,12 +1280,15 @@ BoxModelHighlighter.prototype = Heritage.extend(AutoRefreshHighlighter.prototype this._hideInfobar(); } this._showBoxModel(); + shown = true; } else { // Nothing to highlight (0px rectangle like a