diff --git a/browser/components/customizableui/src/CustomizableUI.jsm b/browser/components/customizableui/src/CustomizableUI.jsm index 8c9c888d0bf..d413cf6e14f 100644 --- a/browser/components/customizableui/src/CustomizableUI.jsm +++ b/browser/components/customizableui/src/CustomizableUI.jsm @@ -1929,13 +1929,21 @@ let CustomizableUIInternal = { this.notifyListeners("onWidgetCreated", widget.id); if (widget.defaultArea) { + let addToDefaultPlacements = false; let area = gAreas.get(widget.defaultArea); - //XXXgijs this won't have any effect for legacy items. Sort of OK because - // consumers can modify currentset? Maybe? - if (area.has("defaultPlacements")) { - area.get("defaultPlacements").push(widget.id); - } else { - area.set("defaultPlacements", [widget.id]); + if (widget.source == CustomizableUI.SOURCE_BUILTIN) { + addToDefaultPlacements = true; + } else if (!CustomizableUI.isBuiltinToolbar(widget.defaultArea) && + widget.defaultArea != CustomizableUI.AREA_PANEL) { + addToDefaultPlacements = true; + } + + if (addToDefaultPlacements) { + if (area.has("defaultPlacements")) { + area.get("defaultPlacements").push(widget.id); + } else { + area.set("defaultPlacements", [widget.id]); + } } } diff --git a/browser/components/customizableui/src/CustomizeMode.jsm b/browser/components/customizableui/src/CustomizeMode.jsm index ff282bb91bc..161ae63cff4 100644 --- a/browser/components/customizableui/src/CustomizeMode.jsm +++ b/browser/components/customizableui/src/CustomizeMode.jsm @@ -665,7 +665,7 @@ CustomizeMode.prototype = { if (customizationTarget && customizationTarget != areaNode) { areas.push(customizationTarget.id); } - let overflowTarget = areaNode.getAttribute("overflowtarget"); + let overflowTarget = areaNode && areaNode.getAttribute("overflowtarget"); if (overflowTarget) { areas.push(overflowTarget); } diff --git a/browser/components/customizableui/test/browser.ini b/browser/components/customizableui/test/browser.ini index d6f1cd97902..a4bf22ad941 100644 --- a/browser/components/customizableui/test/browser.ini +++ b/browser/components/customizableui/test/browser.ini @@ -94,6 +94,7 @@ skip-if = os == "linux" [browser_978084_dragEnd_after_move.js] [browser_980155_add_overflow_toolbar.js] [browser_981418-widget-onbeforecreated-handler.js] +[browser_982656_restore_defaults_builtin_widgets.js] [browser_984455_bookmarks_items_reparenting.js] skip-if = os == "linux" diff --git a/browser/components/customizableui/test/browser_982656_restore_defaults_builtin_widgets.js b/browser/components/customizableui/test/browser_982656_restore_defaults_builtin_widgets.js new file mode 100644 index 00000000000..30a20557fe8 --- /dev/null +++ b/browser/components/customizableui/test/browser_982656_restore_defaults_builtin_widgets.js @@ -0,0 +1,58 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +// Restoring default should not place addon widgets back in the toolbar +add_task(function() { + ok(CustomizableUI.inDefaultState, "Default state to begin"); + + const kWidgetId = "bug982656-add-on-widget-should-not-restore-to-default-area"; + let widgetSpec = { + id: kWidgetId, + defaultArea: CustomizableUI.AREA_NAVBAR + }; + CustomizableUI.createWidget(widgetSpec); + + ok(!CustomizableUI.inDefaultState, "Not in default state after widget added"); + is(CustomizableUI.getPlacementOfWidget(kWidgetId).area, CustomizableUI.AREA_NAVBAR, "Widget should be in navbar"); + + yield resetCustomization(); + + ok(CustomizableUI.inDefaultState, "Back in default state after reset"); + is(CustomizableUI.getPlacementOfWidget(kWidgetId), null, "Widget now in palette"); + CustomizableUI.destroyWidget(kWidgetId); +}); + + +// resetCustomization shouldn't move 3rd party widgets out of custom toolbars +add_task(function() { + const kToolbarId = "bug982656-toolbar-with-defaultset"; + const kWidgetId = "bug982656-add-on-widget-should-restore-to-default-area-when-area-is-not-builtin"; + ok(CustomizableUI.inDefaultState, "Everything should be in its default state."); + let toolbar = createToolbarWithPlacements(kToolbarId, [kWidgetId]); + ok(CustomizableUI.areas.indexOf(kToolbarId) != -1, + "Toolbar has been registered."); + is(CustomizableUI.getAreaType(kToolbarId), CustomizableUI.TYPE_TOOLBAR, + "Area should be registered as toolbar"); + + let widgetSpec = { + id: kWidgetId, + defaultArea: kToolbarId + }; + CustomizableUI.createWidget(widgetSpec); + + ok(!CustomizableUI.inDefaultState, "No longer in default state after toolbar is registered and visible."); + is(CustomizableUI.getPlacementOfWidget(kWidgetId).area, kToolbarId, "Widget should be in custom toolbar"); + + yield resetCustomization(); + debugger; + ok(CustomizableUI.inDefaultState, "Back in default state after reset"); + is(CustomizableUI.getPlacementOfWidget(kWidgetId).area, kToolbarId, "Widget still in custom toolbar"); + ok(toolbar.collapsed, "Custom toolbar should be collapsed after reset"); + + toolbar.remove(); + CustomizableUI.destroyWidget(kWidgetId); + CustomizableUI.unregisterArea(kToolbarId); +}); diff --git a/browser/devtools/shared/test/browser_graphs-01.js b/browser/devtools/shared/test/browser_graphs-01.js index bbcc3eb6137..38147731aef 100644 --- a/browser/devtools/shared/test/browser_graphs-01.js +++ b/browser/devtools/shared/test/browser_graphs-01.js @@ -20,7 +20,12 @@ function* performTest() { doc.body.setAttribute("style", "position: fixed; width: 100%; height: 100%; margin: 0;"); let graph = new LineGraphWidget(doc.body, "fps"); - yield graph.once("ready"); + + let readyEventEmitted; + graph.once("ready", () => readyEventEmitted = true); + + yield graph.ready(); + ok(readyEventEmitted, "The 'ready' event should have been emitted"); testGraph(host, graph); diff --git a/browser/devtools/shared/widgets/Graphs.jsm b/browser/devtools/shared/widgets/Graphs.jsm index 9f2a55e958f..73936a9c640 100644 --- a/browser/devtools/shared/widgets/Graphs.jsm +++ b/browser/devtools/shared/widgets/Graphs.jsm @@ -5,8 +5,9 @@ const Cu = Components.utils; -Cu.import("resource://gre/modules/devtools/event-emitter.js"); Cu.import("resource:///modules/devtools/ViewHelpers.jsm"); +const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise; +const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {}); this.EXPORTED_SYMBOLS = ["LineGraphWidget"]; @@ -116,6 +117,7 @@ GraphSelectionResizer.prototype = { this.AbstractCanvasGraph = function(parent, name, sharpness) { EventEmitter.decorate(this); + this._ready = promise.defer(); this._parent = parent; this._uid = "canvas-graph-" + Date.now(); @@ -165,6 +167,7 @@ this.AbstractCanvasGraph = function(parent, name, sharpness) { this._animationId = this._window.requestAnimationFrame(this._onAnimationFrame); + this._ready.resolve(this); this.emit("ready", this); }); } @@ -181,6 +184,13 @@ AbstractCanvasGraph.prototype = { return this._height; }, + /** + * Returns a promise resolved once this graph is ready to receive data. + */ + ready: function() { + return this._ready.promise; + }, + /** * Destroys this graph. */ @@ -501,15 +511,16 @@ AbstractCanvasGraph.prototype = { let ctx = this._ctx; ctx.clearRect(0, 0, this._width, this._height); + // Draw the graph underneath the cursor and selection. + if (this.hasData()) { + ctx.drawImage(this._cachedGraphImage, 0, 0, this._width, this._height); + } if (this.hasCursor()) { this._drawCliphead(); } if (this.hasSelection() || this.hasSelectionInProgress()) { this._drawSelection(); } - if (this.hasData()) { - ctx.drawImage(this._cachedGraphImage, 0, 0, this._width, this._height); - } this._shouldRedraw = false; }, @@ -957,24 +968,17 @@ LineGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, { let width = canvas.width = this._width; let height = canvas.height = this._height; + let totalTicks = this._data.length; + let firstTick = this._data[0].delta; + let lastTick = this._data[totalTicks - 1].delta; let maxValue = Number.MIN_SAFE_INTEGER; let minValue = Number.MAX_SAFE_INTEGER; let sumValues = 0; - let totalTicks = 0; - let firstTick; - let lastTick; for (let { delta, value } of this._data) { maxValue = Math.max(value, maxValue); minValue = Math.min(value, minValue); sumValues += value; - totalTicks++; - - if (!firstTick) { - firstTick = delta; - } else { - lastTick = delta; - } } let dataScaleX = this.dataScaleX = width / lastTick; @@ -997,7 +1001,6 @@ LineGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, { ctx.fillStyle = gradient; ctx.strokeStyle = LINE_GRAPH_STROKE_COLOR; ctx.lineWidth = LINE_GRAPH_STROKE_WIDTH; - ctx.setLineDash([]); ctx.beginPath(); let prevX = 0; diff --git a/browser/themes/linux/browser.css b/browser/themes/linux/browser.css index 82e4917ac20..06a0d7d7a2a 100644 --- a/browser/themes/linux/browser.css +++ b/browser/themes/linux/browser.css @@ -1829,14 +1829,7 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action- margin: 0 0 @tabToolbarNavbarOverlap@; } -.tabbrowser-arrowscrollbox > .scrollbutton-up { - -moz-border-start: 0; - -moz-border-end: 2px solid transparent; -} - .tabbrowser-arrowscrollbox > .scrollbutton-down { - -moz-border-start: 2px solid transparent; - -moz-border-end: 0; transition: 1s box-shadow ease-out; border-radius: 4px; } @@ -1846,20 +1839,6 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action- transition: none; } -.tabbrowser-arrowscrollbox > .scrollbutton-up:not([disabled]):-moz-locale-dir(ltr), -.tabbrowser-arrowscrollbox > .scrollbutton-down:not([disabled]):-moz-locale-dir(rtl) { - border-width: 0 2px 0 0; - border-style: solid; - border-image: url("chrome://browser/skin/tabbrowser/tab-overflow-border.png") 0 2 0 2 fill; -} - -.tabbrowser-arrowscrollbox > .scrollbutton-down:not([disabled]):-moz-locale-dir(ltr), -.tabbrowser-arrowscrollbox > .scrollbutton-up:not([disabled]):-moz-locale-dir(rtl) { - border-width: 0 0 0 2px; - border-style: solid; - border-image: url("chrome://browser/skin/tabbrowser/tab-overflow-border.png") 0 2 0 2 fill; -} - #TabsToolbar .toolbarbutton-1 { margin-bottom: @tabToolbarNavbarOverlap@; } diff --git a/browser/themes/linux/jar.mn b/browser/themes/linux/jar.mn index cf5c83a02e1..055bfbfd528 100644 --- a/browser/themes/linux/jar.mn +++ b/browser/themes/linux/jar.mn @@ -165,7 +165,7 @@ browser.jar: skin/classic/browser/tabbrowser/tab-background-end.png (tabbrowser/tab-background-end.png) skin/classic/browser/tabbrowser/tab-background-middle.png (tabbrowser/tab-background-middle.png) skin/classic/browser/tabbrowser/tab-background-start.png (tabbrowser/tab-background-start.png) - skin/classic/browser/tabbrowser/tab-overflow-border.png (tabbrowser/tab-overflow-border.png) + skin/classic/browser/tabbrowser/tab-overflow-indicator.png (../shared/tabbrowser/tab-overflow-indicator.png) # NOTE: The following two files (tab-selected-end.svg, tab-selected-start.svg) get pre-processed in # Makefile.in with a non-default marker of "%" and the result of that gets packaged. diff --git a/browser/themes/linux/tabbrowser/tab-overflow-border.png b/browser/themes/linux/tabbrowser/tab-overflow-border.png deleted file mode 100644 index 77f2462e5bf..00000000000 Binary files a/browser/themes/linux/tabbrowser/tab-overflow-border.png and /dev/null differ diff --git a/browser/themes/osx/browser.css b/browser/themes/osx/browser.css index b1f9e23899a..12e44270466 100644 --- a/browser/themes/osx/browser.css +++ b/browser/themes/osx/browser.css @@ -2971,20 +2971,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { } } -.tabbrowser-arrowscrollbox > .scrollbutton-up:not([disabled]):-moz-locale-dir(ltr), -.tabbrowser-arrowscrollbox > .scrollbutton-down:not([disabled]):-moz-locale-dir(rtl) { - border-width: 0 2px 0 0; - border-style: solid; - border-image: url("chrome://browser/skin/tabbrowser/tab-overflow-border.png") 0 2 0 2 fill; -} - -.tabbrowser-arrowscrollbox > .scrollbutton-down:not([disabled]):-moz-locale-dir(ltr), -.tabbrowser-arrowscrollbox > .scrollbutton-up:not([disabled]):-moz-locale-dir(rtl) { - border-width: 0 0 0 2px; - border-style: solid; - border-image: url("chrome://browser/skin/tabbrowser/tab-overflow-border.png") 0 2 0 2 fill; -} - /** * Tabstrip & add-on bar toolbar buttons */ diff --git a/browser/themes/osx/jar.mn b/browser/themes/osx/jar.mn index 383de7cb73d..f9c6278e5e3 100644 --- a/browser/themes/osx/jar.mn +++ b/browser/themes/osx/jar.mn @@ -277,6 +277,7 @@ browser.jar: skin/classic/browser/tabbrowser/tab-background-middle@2x.png (tabbrowser/tab-background-middle@2x.png) skin/classic/browser/tabbrowser/tab-background-start.png (tabbrowser/tab-background-start.png) skin/classic/browser/tabbrowser/tab-background-start@2x.png (tabbrowser/tab-background-start@2x.png) + skin/classic/browser/tabbrowser/tab-overflow-indicator.png (../shared/tabbrowser/tab-overflow-indicator.png) # NOTE: The following two files (tab-selected-end.svg, tab-selected-start.svg) get pre-processed in # Makefile.in with a non-default marker of "%" and the result of that gets packaged. @@ -287,7 +288,6 @@ browser.jar: skin/classic/browser/tabbrowser/tab-stroke-end@2x.png (tabbrowser/tab-stroke-end@2x.png) skin/classic/browser/tabbrowser/tab-stroke-start.png (tabbrowser/tab-stroke-start.png) skin/classic/browser/tabbrowser/tab-stroke-start@2x.png (tabbrowser/tab-stroke-start@2x.png) - skin/classic/browser/tabbrowser/tab-overflow-border.png (tabbrowser/tab-overflow-border.png) skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png) skin/classic/browser/tabbrowser/tabDragIndicator@2x.png (tabbrowser/tabDragIndicator@2x.png) skin/classic/browser/tabbrowser/tab-separator.png (tabbrowser/tab-separator.png) diff --git a/browser/themes/osx/tabbrowser/tab-overflow-border.png b/browser/themes/osx/tabbrowser/tab-overflow-border.png deleted file mode 100644 index 73c778af033..00000000000 Binary files a/browser/themes/osx/tabbrowser/tab-overflow-border.png and /dev/null differ diff --git a/browser/themes/shared/tabbrowser/tab-overflow-indicator.png b/browser/themes/shared/tabbrowser/tab-overflow-indicator.png new file mode 100644 index 00000000000..17d27c99eed Binary files /dev/null and b/browser/themes/shared/tabbrowser/tab-overflow-indicator.png differ diff --git a/browser/themes/shared/tabs.inc.css b/browser/themes/shared/tabs.inc.css index 8027dd34b17..b3360d3c960 100644 --- a/browser/themes/shared/tabs.inc.css +++ b/browser/themes/shared/tabs.inc.css @@ -130,6 +130,43 @@ -moz-padding-start: @tabCurveHalfWidth@; } +/* Tab Overflow */ +.tabbrowser-arrowscrollbox > .arrowscrollbox-overflow-start-indicator:not([collapsed]), +.tabbrowser-arrowscrollbox > .arrowscrollbox-overflow-end-indicator:not([collapsed]) { + background-image: url(chrome://browser/skin/tabbrowser/tab-overflow-indicator.png); + background-size: 100% 100%; + width: 14px; + margin-bottom: @tabToolbarNavbarOverlap@; + pointer-events: none; + position: relative; + z-index: 3; /* the selected tab's z-index + 1 */ +} + +.tabbrowser-arrowscrollbox > .arrowscrollbox-overflow-start-indicator:-moz-locale-dir(rtl), +.tabbrowser-arrowscrollbox > .arrowscrollbox-overflow-end-indicator:-moz-locale-dir(ltr) { + transform: scaleX(-1); +} + +.tabbrowser-arrowscrollbox > .arrowscrollbox-overflow-start-indicator:not([collapsed]) { + -moz-margin-start: -2px; + -moz-margin-end: -12px; +} + +.tabbrowser-arrowscrollbox > .arrowscrollbox-overflow-end-indicator:not([collapsed]) { + -moz-margin-start: -12px; + -moz-margin-end: -2px; +} + +.tabbrowser-arrowscrollbox > .arrowscrollbox-overflow-start-indicator[collapsed], +.tabbrowser-arrowscrollbox > .arrowscrollbox-overflow-end-indicator[collapsed] { + opacity: 0; +} + +.tabbrowser-arrowscrollbox > .arrowscrollbox-overflow-start-indicator, +.tabbrowser-arrowscrollbox > .arrowscrollbox-overflow-end-indicator { + transition: opacity 150ms ease; +} + .tab-background-start[selected=true]::after, .tab-background-start[selected=true]::before, .tab-background-start, diff --git a/browser/themes/windows/browser.css b/browser/themes/windows/browser.css index 3c511a807cf..0c0f35f4a09 100644 --- a/browser/themes/windows/browser.css +++ b/browser/themes/windows/browser.css @@ -1855,9 +1855,6 @@ toolbarbutton[type="socialmark"] > .toolbarbutton-icon { .tabbrowser-arrowscrollbox > .scrollbutton-down { list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-left.png"); margin: 0 0 @tabToolbarNavbarOverlap@; - padding-right: 2px; - border-right: 2px solid transparent; - background-origin: border-box; } #TabsToolbar[brighttext] > #tabbrowser-tabs > .tabbrowser-arrowscrollbox > .scrollbutton-up, @@ -1884,13 +1881,6 @@ toolbarbutton[type="socialmark"] > .toolbarbutton-icon { transition: none; } -.tabbrowser-arrowscrollbox > .scrollbutton-up:not([disabled]), -.tabbrowser-arrowscrollbox > .scrollbutton-down:not([disabled]) { - border-width: 0 2px 0 0; - border-style: solid; - border-image: url("chrome://browser/skin/tabbrowser/tab-overflow-border.png") 0 2 0 2 fill; -} - .tabs-newtab-button > .toolbarbutton-icon { margin-top: -1px; margin-bottom: -1px; diff --git a/browser/themes/windows/jar.mn b/browser/themes/windows/jar.mn index bb3a29dd8cd..72b1dde6443 100644 --- a/browser/themes/windows/jar.mn +++ b/browser/themes/windows/jar.mn @@ -196,7 +196,7 @@ browser.jar: skin/classic/browser/tabbrowser/tab-background-middle@2x.png (tabbrowser/tab-background-middle@2x.png) skin/classic/browser/tabbrowser/tab-background-end.png (tabbrowser/tab-background-end.png) skin/classic/browser/tabbrowser/tab-background-end@2x.png (tabbrowser/tab-background-end@2x.png) - skin/classic/browser/tabbrowser/tab-overflow-border.png (tabbrowser/tab-overflow-border.png) + skin/classic/browser/tabbrowser/tab-overflow-indicator.png (../shared/tabbrowser/tab-overflow-indicator.png) # NOTE: The following two files (tab-selected-end.svg, tab-selected-start.svg) get pre-processed in # Makefile.in with a non-default marker of "%" and the result of that gets packaged. @@ -601,7 +601,7 @@ browser.jar: skin/classic/aero/browser/tabbrowser/tab-background-middle@2x.png (tabbrowser/tab-background-middle@2x.png) skin/classic/aero/browser/tabbrowser/tab-background-end.png (tabbrowser/tab-background-end.png) skin/classic/aero/browser/tabbrowser/tab-background-end@2x.png (tabbrowser/tab-background-end@2x.png) - skin/classic/aero/browser/tabbrowser/tab-overflow-border.png (tabbrowser/tab-overflow-border.png) + skin/classic/aero/browser/tabbrowser/tab-overflow-indicator.png (../shared/tabbrowser/tab-overflow-indicator.png) # NOTE: The following two files (tab-selected-end.svg, tab-selected-start.svg) get pre-processed in # Makefile.in with a non-default marker of "%" and the result of that gets packaged. diff --git a/browser/themes/windows/tabbrowser/tab-overflow-border.png b/browser/themes/windows/tabbrowser/tab-overflow-border.png deleted file mode 100644 index 77f2462e5bf..00000000000 Binary files a/browser/themes/windows/tabbrowser/tab-overflow-border.png and /dev/null differ diff --git a/toolkit/content/widgets/scrollbox.xml b/toolkit/content/widgets/scrollbox.xml index 88f3df4e503..84db97fc6bf 100644 --- a/toolkit/content/widgets/scrollbox.xml +++ b/toolkit/content/widgets/scrollbox.xml @@ -27,23 +27,30 @@ + + + + @@ -454,28 +461,39 @@ @@ -535,8 +553,8 @@ return; } - this._scrollButtonUp.collapsed = true; - this._scrollButtonDown.collapsed = true; + this.setAttribute("notoverflowing", "true"); + try { // See bug 341047 and comments in overflow handler as to why // try..catch is needed here @@ -545,8 +563,7 @@ this.ensureElementIsVisible(childNodes[0], false); } catch(e) { - this._scrollButtonUp.collapsed = false; - this._scrollButtonDown.collapsed = false; + this.removeAttribute("notoverflowing"); } ]]> @@ -569,20 +586,18 @@ return; } - this._scrollButtonUp.collapsed = false; - this._scrollButtonDown.collapsed = false; + this.removeAttribute("notoverflowing"); + try { // See bug 341047, the overflow event is dispatched when the // scrollbox already is mostly destroyed. This causes some code in // _updateScrollButtonsDisabledState() to throw an error. It also - // means that the scrollbarbuttons were uncollapsed when that should - // not be happening, because the whole overflow event should not be - // happening in that case. + // means that the notoverflowing attribute was removed erroneously, + // as the whole overflow event should not be happening in that case. this._updateScrollButtonsDisabledState(); } catch(e) { - this._scrollButtonUp.collapsed = true; - this._scrollButtonDown.collapsed = true; + this.setAttribute("notoverflowing", "true"); } ]]> @@ -598,22 +613,26 @@ - + - + e >= beginAt && e <= endAt); this._ticks = null; return ticks; }, { - response: { timeline: RetVal("array:number") } + request: { + beginAt: Arg(0, "nullable:number"), + endAt: Arg(1, "nullable:number") + }, + response: { ticks: RetVal("array:number") } }), /** diff --git a/toolkit/devtools/server/tests/mochitest/chrome.ini b/toolkit/devtools/server/tests/mochitest/chrome.ini index db02177e8f3..f8bcb7d1c63 100644 --- a/toolkit/devtools/server/tests/mochitest/chrome.ini +++ b/toolkit/devtools/server/tests/mochitest/chrome.ini @@ -21,6 +21,7 @@ support-files = [test_device.html] [test_framerate_01.html] [test_framerate_02.html] +[test_framerate_03.html] [test_inspector-changeattrs.html] [test_inspector-changevalue.html] [test_inspector-hide.html] diff --git a/toolkit/devtools/server/tests/mochitest/test_framerate_03.html b/toolkit/devtools/server/tests/mochitest/test_framerate_03.html new file mode 100644 index 00000000000..affef174ec4 --- /dev/null +++ b/toolkit/devtools/server/tests/mochitest/test_framerate_03.html @@ -0,0 +1,81 @@ + + + + + + Framerate actor test + + + + +
+
+
+ +