Backed out changeset 942aec7a1572 for mochitest-dt failures, r=me
authorVictor Porof <vporof@mozilla.com>
Tue, 11 Nov 2014 09:33:53 -0500
changeset 226477 8aa568ca5527eaa0a8537653b40dd039b5106668
parent 226476 ebec8f452f657971ab44f84d210acbbf0b92ccc9
child 226478 1c1e25f36e74230a0218d88b5707a3e85567b8ed
push id53
push userdglastonbury@mozilla.com
push dateWed, 12 Nov 2014 02:04:58 +0000
reviewersme
milestone36.0a1
backs out942aec7a1572dca9e2f5ebecf84a879d0eb354b9
Backed out changeset 942aec7a1572 for mochitest-dt failures, r=me
browser/devtools/shared/test/browser.ini
browser/devtools/shared/test/browser_graphs-09.js
browser/devtools/shared/test/browser_graphs-09a.js
browser/devtools/shared/test/browser_graphs-09b.js
browser/devtools/shared/test/browser_graphs-09c.js
browser/devtools/shared/widgets/Graphs.jsm
browser/devtools/timeline/moz.build
browser/devtools/timeline/test/browser.ini
browser/devtools/timeline/test/browser_timeline_overview-initial-selection-01.js
browser/devtools/timeline/test/browser_timeline_overview-initial-selection-02.js
browser/devtools/timeline/test/browser_timeline_overview-update.js
browser/devtools/timeline/test/browser_timeline_recording-without-memory.js
browser/devtools/timeline/test/browser_timeline_recording.js
browser/devtools/timeline/test/browser_timeline_waterfall-background.js
browser/devtools/timeline/test/browser_timeline_waterfall-generic.js
browser/devtools/timeline/test/browser_timeline_waterfall-styles.js
browser/devtools/timeline/timeline.js
browser/devtools/timeline/timeline.xul
browser/devtools/timeline/widgets/markers-overview.js
browser/devtools/timeline/widgets/memory-overview.js
browser/devtools/timeline/widgets/overview.js
browser/devtools/timeline/widgets/waterfall.js
browser/locales/en-US/chrome/browser/devtools/timeline.dtd
browser/locales/en-US/chrome/browser/devtools/timeline.properties
browser/themes/shared/devtools/timeline.inc.css
browser/themes/shared/devtools/widgets.inc.css
--- a/browser/devtools/shared/test/browser.ini
+++ b/browser/devtools/shared/test/browser.ini
@@ -19,19 +19,17 @@ support-files =
 [browser_graphs-02.js]
 [browser_graphs-03.js]
 [browser_graphs-04.js]
 [browser_graphs-05.js]
 [browser_graphs-06.js]
 [browser_graphs-07a.js]
 [browser_graphs-07b.js]
 [browser_graphs-08.js]
-[browser_graphs-09a.js]
-[browser_graphs-09b.js]
-[browser_graphs-09c.js]
+[browser_graphs-09.js]
 [browser_graphs-10a.js]
 [browser_graphs-10b.js]
 [browser_graphs-11a.js]
 [browser_graphs-11b.js]
 [browser_graphs-12.js]
 [browser_graphs-13.js]
 [browser_graphs-14.js]
 [browser_inplace-editor.js]
rename from browser/devtools/shared/test/browser_graphs-09a.js
rename to browser/devtools/shared/test/browser_graphs-09.js
--- a/browser/devtools/shared/test/browser_graphs-09a.js
+++ b/browser/devtools/shared/test/browser_graphs-09.js
@@ -22,47 +22,31 @@ function* performTest() {
 
   yield testGraph(graph);
 
   graph.destroy();
   host.destroy();
 }
 
 function* testGraph(graph) {
-  info("Should be able to set the graph data before waiting for the ready event.");
+  info("Should be able to set the grpah data before waiting for the ready event.");
 
   yield graph.setDataWhenReady(TEST_DATA);
   ok(graph.hasData(), "Data was set successfully.");
 
-  is(graph._gutter.hidden, false,
-    "The gutter should not be hidden because the tooltips have arrows.");
-  is(graph._maxTooltip.hidden, false,
-    "The max tooltip should not be hidden.");
-  is(graph._avgTooltip.hidden, false,
-    "The avg tooltip should not be hidden.");
-  is(graph._minTooltip.hidden, false,
-    "The min tooltip should not be hidden.");
-
-  is(graph._maxTooltip.getAttribute("with-arrows"), "true",
-    "The maximum tooltip has the correct 'with-arrows' attribute.");
-  is(graph._avgTooltip.getAttribute("with-arrows"), "true",
-    "The average tooltip has the correct 'with-arrows' attribute.");
-  is(graph._minTooltip.getAttribute("with-arrows"), "true",
-    "The minimum tooltip has the correct 'with-arrows' attribute.");
-
   is(graph._maxTooltip.querySelector("[text=info]").textContent, "max",
     "The maximum tooltip displays the correct info.");
   is(graph._avgTooltip.querySelector("[text=info]").textContent, "avg",
     "The average tooltip displays the correct info.");
   is(graph._minTooltip.querySelector("[text=info]").textContent, "min",
     "The minimum tooltip displays the correct info.");
 
   is(graph._maxTooltip.querySelector("[text=value]").textContent, "60",
     "The maximum tooltip displays the correct value.");
-  is(graph._avgTooltip.querySelector("[text=value]").textContent, "41.71",
+  is(graph._avgTooltip.querySelector("[text=value]").textContent, "41",
     "The average tooltip displays the correct value.");
   is(graph._minTooltip.querySelector("[text=value]").textContent, "10",
     "The minimum tooltip displays the correct value.");
 
   is(graph._maxTooltip.querySelector("[text=metric]").textContent, "fps",
     "The maximum tooltip displays the correct metric.");
   is(graph._avgTooltip.querySelector("[text=metric]").textContent, "fps",
     "The average tooltip displays the correct metric.");
deleted file mode 100644
--- a/browser/devtools/shared/test/browser_graphs-09b.js
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Tests that line graphs properly use the tooltips configuration properties.
-
-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 {DOMHelpers} = Cu.import("resource:///modules/devtools/DOMHelpers.jsm", {});
-let {Promise} = devtools.require("resource://gre/modules/Promise.jsm");
-let {Hosts} = devtools.require("devtools/framework/toolbox-hosts");
-
-let test = Task.async(function*() {
-  yield promiseTab("about:blank");
-  yield performTest();
-  gBrowser.removeCurrentTab();
-  finish();
-});
-
-function* performTest() {
-  let [host, win, doc] = yield createHost();
-  let graph = new LineGraphWidget(doc.body, "fps");
-  graph.withTooltipArrows = false;
-  graph.withFixedTooltipPositions = true;
-
-  yield testGraph(graph);
-
-  graph.destroy();
-  host.destroy();
-}
-
-function* testGraph(graph) {
-  yield graph.setDataWhenReady(TEST_DATA);
-
-  is(graph._gutter.hidden, true,
-    "The gutter should be hidden because the tooltips don't have arrows.");
-  is(graph._maxTooltip.hidden, false,
-    "The max tooltip should not be hidden.");
-  is(graph._avgTooltip.hidden, false,
-    "The avg tooltip should not be hidden.");
-  is(graph._minTooltip.hidden, false,
-    "The min tooltip should not be hidden.");
-
-  is(graph._maxTooltip.getAttribute("with-arrows"), "false",
-    "The maximum tooltip has the correct 'with-arrows' attribute.");
-  is(graph._avgTooltip.getAttribute("with-arrows"), "false",
-    "The average tooltip has the correct 'with-arrows' attribute.");
-  is(graph._minTooltip.getAttribute("with-arrows"), "false",
-    "The minimum tooltip has the correct 'with-arrows' attribute.");
-
-  is(parseInt(graph._maxTooltip.style.top), 8,
-    "The maximum tooltip is positioned correctly.");
-  is(parseInt(graph._avgTooltip.style.top), 8,
-    "The average tooltip is positioned correctly.");
-  is(parseInt(graph._minTooltip.style.top), 142,
-    "The minimum tooltip is positioned correctly.");
-
-  is(parseInt(graph._maxGutterLine.style.top), 22,
-    "The maximum gutter line is positioned correctly.");
-  is(parseInt(graph._avgGutterLine.style.top), 61,
-    "The average gutter line is positioned correctly.");
-  is(parseInt(graph._minGutterLine.style.top), 128,
-    "The minimum gutter line is positioned correctly.");
-}
deleted file mode 100644
--- a/browser/devtools/shared/test/browser_graphs-09c.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Tests that line graphs hide the tooltips when there's no data available.
-
-const TEST_DATA = [];
-let {LineGraphWidget} = Cu.import("resource:///modules/devtools/Graphs.jsm", {});
-let {DOMHelpers} = Cu.import("resource:///modules/devtools/DOMHelpers.jsm", {});
-let {Promise} = devtools.require("resource://gre/modules/Promise.jsm");
-let {Hosts} = devtools.require("devtools/framework/toolbox-hosts");
-
-let test = Task.async(function*() {
-  yield promiseTab("about:blank");
-  yield performTest();
-  gBrowser.removeCurrentTab();
-  finish();
-});
-
-function* performTest() {
-  let [host, win, doc] = yield createHost();
-  let graph = new LineGraphWidget(doc.body, "fps");
-
-  yield testGraph(graph);
-
-  graph.destroy();
-  host.destroy();
-}
-
-function* testGraph(graph) {
-  yield graph.setDataWhenReady(TEST_DATA);
-
-  is(graph._gutter.hidden, false,
-    "The gutter should not be hidden.");
-  is(graph._maxTooltip.hidden, true,
-    "The max tooltip should be hidden.");
-  is(graph._avgTooltip.hidden, true,
-    "The avg tooltip should be hidden.");
-  is(graph._minTooltip.hidden, true,
-    "The min tooltip should be hidden.");
-}
--- a/browser/devtools/shared/widgets/Graphs.jsm
+++ b/browser/devtools/shared/widgets/Graphs.jsm
@@ -14,17 +14,16 @@ this.EXPORTED_SYMBOLS = [
   "AbstractCanvasGraph",
   "LineGraphWidget",
   "BarGraphWidget",
   "CanvasGraphUtils"
 ];
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 const GRAPH_SRC = "chrome://browser/content/devtools/graphs-frame.xhtml";
-const L10N = new ViewHelpers.L10N();
 
 // Generic constants.
 
 const GRAPH_RESIZE_EVENTS_DRAIN = 100; // ms
 const GRAPH_WHEEL_ZOOM_SENSITIVITY = 0.00075;
 const GRAPH_WHEEL_SCROLL_SENSITIVITY = 0.1;
 const GRAPH_WHEEL_MIN_SELECTION_WIDTH = 10; // px
 
@@ -40,19 +39,18 @@ const GRAPH_STRIPE_PATTERN_WIDTH = 16; /
 const GRAPH_STRIPE_PATTERN_HEIGHT = 16; // px
 const GRAPH_STRIPE_PATTERN_LINE_WIDTH = 2; // px
 const GRAPH_STRIPE_PATTERN_LINE_SPACING = 4; // px
 
 // Line graph constants.
 
 const LINE_GRAPH_DAMPEN_VALUES = 0.85;
 const LINE_GRAPH_MIN_SQUARED_DISTANCE_BETWEEN_POINTS = 400; // 20 px
-const LINE_GRAPH_TOOLTIP_SAFE_BOUNDS = 8; // px
+const LINE_GRAPH_TOOLTIP_SAFE_BOUNDS = 10; // px
 
-const LINE_GRAPH_BACKGROUND_COLOR = "#0088cc";
 const LINE_GRAPH_STROKE_WIDTH = 1; // px
 const LINE_GRAPH_STROKE_COLOR = "rgba(255,255,255,0.9)";
 const LINE_GRAPH_HELPER_LINES_DASH = [5]; // px
 const LINE_GRAPH_HELPER_LINES_WIDTH = 1; // px
 const LINE_GRAPH_MAXIMUM_LINE_COLOR = "rgba(255,255,255,0.4)";
 const LINE_GRAPH_AVERAGE_LINE_COLOR = "rgba(255,255,255,0.7)";
 const LINE_GRAPH_MINIMUM_LINE_COLOR = "rgba(255,255,255,0.9)";
 const LINE_GRAPH_BACKGROUND_GRADIENT_START = "rgba(255,255,255,0.25)";
@@ -484,28 +482,26 @@ AbstractCanvasGraph.prototype = {
     this.emit("deselecting");
   },
 
   /**
    * Gets whether or not this graph has a selection.
    * @return boolean
    */
   hasSelection: function() {
-    return this._selection &&
-      this._selection.start != null && this._selection.end != null;
+    return this._selection.start != null && this._selection.end != null;
   },
 
   /**
    * Gets whether or not a selection is currently being made, for example
    * via a click+drag operation.
    * @return boolean
    */
   hasSelectionInProgress: function() {
-    return this._selection &&
-      this._selection.start != null && this._selection.end == null;
+    return this._selection.start != null && this._selection.end == null;
   },
 
   /**
    * Specifies whether or not mouse selection is allowed.
    * @type boolean
    */
   selectionEnabled: true,
 
@@ -551,17 +547,17 @@ AbstractCanvasGraph.prototype = {
     this._shouldRedraw = true;
   },
 
   /**
    * Gets whether or not this graph has a visible cursor.
    * @return boolean
    */
   hasCursor: function() {
-    return this._cursor && this._cursor.x != null;
+    return this._cursor.x != null;
   },
 
   /**
    * Specifies if this graph's selection is different from another one.
    *
    * @param object other
    *        The other graph's selection, as { start, end } values.
    */
@@ -1175,104 +1171,76 @@ this.LineGraphWidget = function(parent, 
     this._minGutterLine = this._createGutterLine("minimum");
     this._maxTooltip = this._createTooltip("maximum", "start", "max", metric);
     this._avgTooltip = this._createTooltip("average", "end", "avg", metric);
     this._minTooltip = this._createTooltip("minimum", "start", "min", metric);
   });
 }
 
 LineGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
-  backgroundColor: LINE_GRAPH_BACKGROUND_COLOR,
-  backgroundGradientStart: LINE_GRAPH_BACKGROUND_GRADIENT_START,
-  backgroundGradientEnd: LINE_GRAPH_BACKGROUND_GRADIENT_END,
-  strokeColor: LINE_GRAPH_STROKE_COLOR,
-  strokeWidth: LINE_GRAPH_STROKE_WIDTH,
-  maximumLineColor: LINE_GRAPH_MAXIMUM_LINE_COLOR,
-  averageLineColor: LINE_GRAPH_AVERAGE_LINE_COLOR,
-  minimumLineColor: LINE_GRAPH_MINIMUM_LINE_COLOR,
   clipheadLineColor: LINE_GRAPH_CLIPHEAD_LINE_COLOR,
   selectionLineColor: LINE_GRAPH_SELECTION_LINE_COLOR,
   selectionBackgroundColor: LINE_GRAPH_SELECTION_BACKGROUND_COLOR,
   selectionStripesColor: LINE_GRAPH_SELECTION_STRIPES_COLOR,
   regionBackgroundColor: LINE_GRAPH_REGION_BACKGROUND_COLOR,
   regionStripesColor: LINE_GRAPH_REGION_STRIPES_COLOR,
 
   /**
    * Optionally offsets the `delta` in the data source by this scalar.
    */
   dataOffsetX: 0,
 
   /**
-   * The scalar used to multiply the graph values to leave some headroom
-   * on the top.
-   */
-  dampenValuesFactor: LINE_GRAPH_DAMPEN_VALUES,
-
-  /**
    * Points that are too close too each other in the graph will not be rendered.
    * This scalar specifies the required minimum squared distance between points.
    */
   minDistanceBetweenPoints: LINE_GRAPH_MIN_SQUARED_DISTANCE_BETWEEN_POINTS,
 
   /**
-   * Specifies if min/max/avg tooltips have arrow handlers on their sides.
-   */
-  withTooltipArrows: true,
-
-  /**
-   * Specifies if min/max/avg tooltips are positioned based on the actual
-   * values, or just placed next to the graph corners.
-   */
-  withFixedTooltipPositions: false,
-
-  /**
    * Renders the graph's data source.
    * @see AbstractCanvasGraph.prototype.buildGraphImage
    */
   buildGraphImage: function() {
     let { canvas, ctx } = this._getNamedCanvas("line-graph-data");
     let width = this._width;
     let height = this._height;
 
     let totalTicks = this._data.length;
-    let firstTick = totalTicks ? this._data[0].delta : 0;
-    let lastTick = totalTicks ? this._data[totalTicks - 1].delta : 0;
+    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;
 
     for (let { delta, value } of this._data) {
       maxValue = Math.max(value, maxValue);
       minValue = Math.min(value, minValue);
       sumValues += value;
     }
 
     let dataScaleX = this.dataScaleX = width / (lastTick - this.dataOffsetX);
-    let dataScaleY = this.dataScaleY = height / maxValue * this.dampenValuesFactor;
+    let dataScaleY = this.dataScaleY = height / maxValue * LINE_GRAPH_DAMPEN_VALUES;
 
     /**
      * Calculates the squared distance between two 2D points.
      */
     function distSquared(x0, y0, x1, y1) {
       let xs = x1 - x0;
       let ys = y1 - y0;
       return xs * xs + ys * ys;
     }
 
     // Draw the graph.
 
-    ctx.fillStyle = this.backgroundColor;
-    ctx.fillRect(0, 0, width, height);
-
     let gradient = ctx.createLinearGradient(0, height / 2, 0, height);
-    gradient.addColorStop(0, this.backgroundGradientStart);
-    gradient.addColorStop(1, this.backgroundGradientEnd);
+    gradient.addColorStop(0, LINE_GRAPH_BACKGROUND_GRADIENT_START);
+    gradient.addColorStop(1, LINE_GRAPH_BACKGROUND_GRADIENT_END);
     ctx.fillStyle = gradient;
-    ctx.strokeStyle = this.strokeColor;
-    ctx.lineWidth = this.strokeWidth * this._pixelRatio;
+    ctx.strokeStyle = LINE_GRAPH_STROKE_COLOR;
+    ctx.lineWidth = LINE_GRAPH_STROKE_WIDTH * this._pixelRatio;
     ctx.beginPath();
 
     let prevX = 0;
     let prevY = 0;
 
     for (let { delta, value } of this._data) {
       let currX = (delta - this.dataOffsetX) * dataScaleX;
       let currY = height - value * dataScaleY;
@@ -1295,93 +1263,77 @@ LineGraphWidget.prototype = Heritage.ext
       }
     }
 
     ctx.fill();
     ctx.stroke();
 
     // Draw the maximum value horizontal line.
 
-    ctx.strokeStyle = this.maximumLineColor;
+    ctx.strokeStyle = LINE_GRAPH_MAXIMUM_LINE_COLOR;
     ctx.lineWidth = LINE_GRAPH_HELPER_LINES_WIDTH;
     ctx.setLineDash(LINE_GRAPH_HELPER_LINES_DASH);
     ctx.beginPath();
-    let maximumY = height - maxValue * dataScaleY;
+    let maximumY = height - maxValue * dataScaleY - ctx.lineWidth;
     ctx.moveTo(0, maximumY);
     ctx.lineTo(width, maximumY);
     ctx.stroke();
 
     // Draw the average value horizontal line.
 
-    ctx.strokeStyle = this.averageLineColor;
+    ctx.strokeStyle = LINE_GRAPH_AVERAGE_LINE_COLOR;
     ctx.lineWidth = LINE_GRAPH_HELPER_LINES_WIDTH;
     ctx.setLineDash(LINE_GRAPH_HELPER_LINES_DASH);
     ctx.beginPath();
-    let avgValue = totalTicks ? sumValues / totalTicks : 0;
-    let averageY = height - avgValue * dataScaleY;
+    let avgValue = sumValues / totalTicks;
+    let averageY = height - avgValue * dataScaleY - ctx.lineWidth;
     ctx.moveTo(0, averageY);
     ctx.lineTo(width, averageY);
     ctx.stroke();
 
     // Draw the minimum value horizontal line.
 
-    ctx.strokeStyle = this.minimumLineColor;
+    ctx.strokeStyle = LINE_GRAPH_MINIMUM_LINE_COLOR;
     ctx.lineWidth = LINE_GRAPH_HELPER_LINES_WIDTH;
     ctx.setLineDash(LINE_GRAPH_HELPER_LINES_DASH);
     ctx.beginPath();
-    let minimumY = height - minValue * dataScaleY;
+    let minimumY = height - minValue * dataScaleY - ctx.lineWidth;
     ctx.moveTo(0, minimumY);
     ctx.lineTo(width, minimumY);
     ctx.stroke();
 
     // Update the tooltips text and gutter lines.
 
-    this._maxTooltip.querySelector("[text=value]").textContent =
-      L10N.numberWithDecimals(maxValue, 2);
-    this._avgTooltip.querySelector("[text=value]").textContent =
-      L10N.numberWithDecimals(avgValue, 2);
-    this._minTooltip.querySelector("[text=value]").textContent =
-      L10N.numberWithDecimals(minValue, 2);
+    this._maxTooltip.querySelector("[text=value]").textContent = maxValue|0;
+    this._avgTooltip.querySelector("[text=value]").textContent = avgValue|0;
+    this._minTooltip.querySelector("[text=value]").textContent = minValue|0;
 
     /**
      * Constrains a value to a range.
      */
     function clamp(value, min, max) {
       if (value < min) return min;
       if (value > max) return max;
       return value;
     }
 
     let bottom = height / this._pixelRatio;
-    let maxPosY = map(maxValue * this.dampenValuesFactor, 0, maxValue, bottom, 0);
-    let avgPosY = map(avgValue * this.dampenValuesFactor, 0, maxValue, bottom, 0);
-    let minPosY = map(minValue * this.dampenValuesFactor, 0, maxValue, bottom, 0);
+    let maxPosY = map(maxValue * LINE_GRAPH_DAMPEN_VALUES, 0, maxValue, bottom, 0);
+    let avgPosY = map(avgValue * LINE_GRAPH_DAMPEN_VALUES, 0, maxValue, bottom, 0);
+    let minPosY = map(minValue * LINE_GRAPH_DAMPEN_VALUES, 0, maxValue, bottom, 0);
 
     let safeTop = LINE_GRAPH_TOOLTIP_SAFE_BOUNDS;
     let safeBottom = bottom - LINE_GRAPH_TOOLTIP_SAFE_BOUNDS;
 
-    this._maxTooltip.style.top = (this.withFixedTooltipPositions
-      ? safeTop : clamp(maxPosY, safeTop, safeBottom)) + "px";
-    this._avgTooltip.style.top = (this.withFixedTooltipPositions
-      ? safeTop : clamp(avgPosY, safeTop, safeBottom)) + "px";
-    this._minTooltip.style.top = (this.withFixedTooltipPositions
-      ? safeBottom : clamp(minPosY, safeTop, safeBottom)) + "px";
-
-    this._maxGutterLine.style.top = maxPosY + "px";
-    this._avgGutterLine.style.top = avgPosY + "px";
-    this._minGutterLine.style.top = minPosY + "px";
-
-    this._maxTooltip.setAttribute("with-arrows", this.withTooltipArrows);
-    this._avgTooltip.setAttribute("with-arrows", this.withTooltipArrows);
-    this._minTooltip.setAttribute("with-arrows", this.withTooltipArrows);
-
-    this._gutter.hidden = !this.withTooltipArrows;
-    this._maxTooltip.hidden = !totalTicks;
-    this._avgTooltip.hidden = !totalTicks;
-    this._minTooltip.hidden = !totalTicks;
+    this._maxTooltip.style.top = clamp(maxPosY, safeTop, safeBottom) + "px";
+    this._avgTooltip.style.top = clamp(avgPosY, safeTop, safeBottom) + "px";
+    this._minTooltip.style.top = clamp(minPosY, safeTop, safeBottom) + "px";
+    this._maxGutterLine.style.top = clamp(maxPosY, safeTop, safeBottom) + "px";
+    this._avgGutterLine.style.top = clamp(avgPosY, safeTop, safeBottom) + "px";
+    this._minGutterLine.style.top = clamp(minPosY, safeTop, safeBottom) + "px";
 
     return canvas;
   },
 
   /**
    * Creates the gutter node when constructing this graph.
    * @return nsIDOMNode
    */
@@ -1510,22 +1462,16 @@ BarGraphWidget.prototype = Heritage.exte
   format: null,
 
   /**
    * Optionally offsets the `delta` in the data source by this scalar.
    */
   dataOffsetX: 0,
 
   /**
-   * The scalar used to multiply the graph values to leave some headroom
-   * on the top.
-   */
-  dampenValuesFactor: BAR_GRAPH_DAMPEN_VALUES,
-
-  /**
    * Bars that are too close too each other in the graph will be combined.
    * This scalar specifies the required minimum width of each bar.
    */
   minBarsWidth: BAR_GRAPH_MIN_BARS_WIDTH,
 
   /**
    * Blocks in a bar that are too thin inside the bar will not be rendered.
    * This scalar specifies the required minimum height of each block.
@@ -1569,17 +1515,17 @@ BarGraphWidget.prototype = Heritage.exte
     let minBarsWidth = this.minBarsWidth * this._pixelRatio;
     let minBlocksHeight = this.minBlocksHeight * this._pixelRatio;
 
     let dataScaleX = this.dataScaleX = width / (lastTick - this.dataOffsetX);
     let dataScaleY = this.dataScaleY = height / this._calcMaxHeight({
       data: this._data,
       dataScaleX: dataScaleX,
       minBarsWidth: minBarsWidth
-    }) * this.dampenValuesFactor;
+    }) * BAR_GRAPH_DAMPEN_VALUES;
 
     // Draw the graph.
 
     // Iterate over the blocks, then the bars, to draw all rectangles of
     // the same color in a single pass. See the @constructor for more
     // information about the data source, and how a "bar" contains "blocks".
 
     this._blocksBoundingRects = [];
@@ -1972,23 +1918,16 @@ this.CanvasGraphUtils = {
 
   /**
    * Makes sure selections in one graph are reflected in another.
    */
   linkSelection: function(graph1, graph2) {
     if (!graph1 || !graph2) {
       return;
     }
-
-    if (graph1.hasSelection()) {
-      graph2.setSelection(graph1.getSelection());
-    } else {
-      graph2.dropSelection();
-    }
-
     graph1.on("selecting", () => {
       graph2.setSelection(graph1.getSelection());
     });
     graph2.on("selecting", () => {
       graph1.setSelection(graph2.getSelection());
     });
     graph1.on("deselecting", () => {
       graph2.dropSelection();
--- a/browser/devtools/timeline/moz.build
+++ b/browser/devtools/timeline/moz.build
@@ -1,14 +1,13 @@
 # vim: set filetype=python:
 # 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/.
 
 EXTRA_JS_MODULES.devtools.timeline += [
     'panel.js',
     'widgets/global.js',
-    'widgets/markers-overview.js',
-    'widgets/memory-overview.js',
+    'widgets/overview.js',
     'widgets/waterfall.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/timeline/test/browser.ini
+++ b/browser/devtools/timeline/test/browser.ini
@@ -4,15 +4,13 @@ support-files =
   doc_simple-test.html
   head.js
 
 [browser_timeline_aaa_run_first_leaktest.js]
 [browser_timeline_blueprint.js]
 [browser_timeline_overview-initial-selection-01.js]
 [browser_timeline_overview-initial-selection-02.js]
 [browser_timeline_overview-update.js]
-skip-if = debug # Bug 1096256
 [browser_timeline_panels.js]
-[browser_timeline_recording-without-memory.js]
 [browser_timeline_recording.js]
 [browser_timeline_waterfall-background.js]
 [browser_timeline_waterfall-generic.js]
 [browser_timeline_waterfall-styles.js]
--- a/browser/devtools/timeline/test/browser_timeline_overview-initial-selection-01.js
+++ b/browser/devtools/timeline/test/browser_timeline_overview-initial-selection-01.js
@@ -3,45 +3,39 @@
 
 /**
  * Tests if the overview has an initial selection when recording has finished
  * and there is data available.
  */
 
 let test = Task.async(function*() {
   let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
-  let { $, EVENTS, TimelineView, TimelineController } = panel.panelWin;
+  let { EVENTS, TimelineView, TimelineController } = panel.panelWin;
   let { OVERVIEW_INITIAL_SELECTION_RATIO: selectionRatio } = panel.panelWin;
 
-  $("#memory-checkbox").checked = true;
-  yield TimelineController.updateMemoryRecording();
-
   yield TimelineController.toggleRecording();
   ok(true, "Recording has started.");
 
   let updated = 0;
   panel.panelWin.on(EVENTS.OVERVIEW_UPDATED, () => updated++);
 
   ok((yield waitUntil(() => updated > 10)),
     "The overview graph was updated a bunch of times.");
   ok((yield waitUntil(() => TimelineController.getMarkers().length > 0)),
     "There are some markers available.");
-  ok((yield waitUntil(() => TimelineController.getMemory().length > 0)),
-    "There are some memory measurements available now.");
 
   yield TimelineController.toggleRecording();
   ok(true, "Recording has ended.");
 
-  let interval = TimelineController.getInterval();
   let markers = TimelineController.getMarkers();
-  let selection = TimelineView.markersOverview.getSelection();
+  let selection = TimelineView.overview.getSelection();
 
   is((selection.start) | 0,
-     ((markers[0].start - interval.startTime) * TimelineView.markersOverview.dataScaleX) | 0,
+     ((markers[0].start - markers.startTime) * TimelineView.overview.dataScaleX) | 0,
     "The initial selection start is correct.");
 
   is((selection.end - selection.start) | 0,
-     (selectionRatio * TimelineView.markersOverview.width) | 0,
+     (selectionRatio * TimelineView.overview.width) | 0,
     "The initial selection end is correct.");
 
   yield teardown(panel);
   finish();
 });
--- a/browser/devtools/timeline/test/browser_timeline_overview-initial-selection-02.js
+++ b/browser/devtools/timeline/test/browser_timeline_overview-initial-selection-02.js
@@ -3,36 +3,30 @@
 
 /**
  * Tests if the overview has no initial selection when recording has finished
  * and there is no data available.
  */
 
 let test = Task.async(function*() {
   let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
-  let { $, EVENTS, TimelineView, TimelineController } = panel.panelWin;
+  let { EVENTS, TimelineView, TimelineController } = panel.panelWin;
   let { OVERVIEW_INITIAL_SELECTION_RATIO: selectionRatio } = panel.panelWin;
 
-  $("#memory-checkbox").checked = true;
-  yield TimelineController.updateMemoryRecording();
-
   yield TimelineController.toggleRecording();
   ok(true, "Recording has started.");
 
   yield TimelineController._stopRecordingAndDiscardData();
   ok(true, "Recording has ended.");
 
   let markers = TimelineController.getMarkers();
-  let memory = TimelineController.getMemory();
-  let selection = TimelineView.markersOverview.getSelection();
+  let selection = TimelineView.overview.getSelection();
 
   is(markers.length, 0,
     "There are no markers available.");
-  is(memory.length, 0,
-    "There are no memory measurements available.");
   is(selection.start, null,
     "The initial selection start is correct.");
   is(selection.end, null,
     "The initial selection end is correct.");
 
   yield teardown(panel);
   finish();
 });
--- a/browser/devtools/timeline/test/browser_timeline_overview-update.js
+++ b/browser/devtools/timeline/test/browser_timeline_overview-update.js
@@ -1,73 +1,48 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
- * Tests if the markers and memory overviews are continuously updated.
+ * Tests if the overview graph is continuously updated.
  */
 
 let test = Task.async(function*() {
   let { target, panel } = yield initTimelinePanel("about:blank");
-  let { $, EVENTS, TimelineView, TimelineController } = panel.panelWin;
-
-  $("#memory-checkbox").checked = true;
-  yield TimelineController.updateMemoryRecording();
+  let { EVENTS, TimelineView, TimelineController } = panel.panelWin;
 
   yield DevToolsUtils.waitForTime(1000);
   yield TimelineController.toggleRecording();
   ok(true, "Recording has started.");
 
-  ok("selectionEnabled" in TimelineView.markersOverview,
-    "The selection should not be enabled for the markers overview (1).");
-  is(TimelineView.markersOverview.selectionEnabled, false,
-    "The selection should not be enabled for the markers overview (2).");
-  is(TimelineView.markersOverview.hasSelection(), false,
-    "The markers overview shouldn't have a selection before recording.");
-
-  ok("selectionEnabled" in TimelineView.memoryOverview,
-    "The selection should not be enabled for the memory overview (1).");
-  is(TimelineView.memoryOverview.selectionEnabled, false,
-    "The selection should not be enabled for the memory overview (2).");
-  is(TimelineView.memoryOverview.hasSelection(), false,
-    "The memory overview shouldn't have a selection before recording.");
+  ok("selectionEnabled" in TimelineView.overview,
+    "The selection should not be enabled for the overview graph (1).");
+  is(TimelineView.overview.selectionEnabled, false,
+    "The selection should not be enabled for the overview graph (2).");
+  is(TimelineView.overview.hasSelection(), false,
+    "The overview graph shouldn't have a selection before recording.");
 
   let updated = 0;
   panel.panelWin.on(EVENTS.OVERVIEW_UPDATED, () => updated++);
 
   ok((yield waitUntil(() => updated > 10)),
-    "The overviews were updated a bunch of times.");
+    "The overview graph was updated a bunch of times.");
 
-  ok("selectionEnabled" in TimelineView.markersOverview,
-    "The selection should still not be enabled for the markers overview (3).");
-  is(TimelineView.markersOverview.selectionEnabled, false,
-    "The selection should still not be enabled for the markers overview (4).");
-  is(TimelineView.markersOverview.hasSelection(), false,
-    "The markers overview should not have a selection while recording.");
-
-  ok("selectionEnabled" in TimelineView.memoryOverview,
-    "The selection should still not be enabled for the memory overview (3).");
-  is(TimelineView.memoryOverview.selectionEnabled, false,
-    "The selection should still not be enabled for the memory overview (4).");
-  is(TimelineView.memoryOverview.hasSelection(), false,
-    "The memory overview should not have a selection while recording.");
+  ok("selectionEnabled" in TimelineView.overview,
+    "The selection should still not be enabled for the overview graph (3).");
+  is(TimelineView.overview.selectionEnabled, false,
+    "The selection should still not be enabled for the overview graph (4).");
+  is(TimelineView.overview.hasSelection(), false,
+    "The overview graph should not have a selection while recording.");
 
   yield TimelineController.toggleRecording();
   ok(true, "Recording has ended.");
 
   is(TimelineController.getMarkers().length, 0,
     "There are no markers available.");
-  ok(TimelineController.getMemory().length >= 10,
-    "There are some memory measurements available.");
-
-  is(TimelineView.markersOverview.selectionEnabled, true,
-    "The selection should now be enabled for the markers overview.");
-  is(TimelineView.markersOverview.hasSelection(), false,
-    "The markers overview should not have a selection after recording.");
-
-  is(TimelineView.memoryOverview.selectionEnabled, true,
-    "The selection should now be enabled for the memory overview.");
-  is(TimelineView.memoryOverview.hasSelection(), false,
-    "The memory overview should not have a selection after recording.");
+  is(TimelineView.overview.selectionEnabled, true,
+    "The selection should now be enabled for the overview graph.");
+  is(TimelineView.overview.hasSelection(), false,
+    "The overview graph should not have a selection after recording.");
 
   yield teardown(panel);
   finish();
 });
deleted file mode 100644
--- a/browser/devtools/timeline/test/browser_timeline_recording-without-memory.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/**
- * Tests if the timeline actor isn't unnecessarily asked to record memory.
- */
-
-let test = Task.async(function*() {
-  let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
-  let { $, EVENTS, TimelineView, TimelineController } = panel.panelWin;
-
-  yield TimelineController.toggleRecording();
-  ok(true, "Recording has started.");
-
-  let updated = 0;
-  panel.panelWin.on(EVENTS.OVERVIEW_UPDATED, () => updated++);
-
-  ok((yield waitUntil(() => updated > 10)),
-    "The overview graph was updated a bunch of times.");
-  ok((yield waitUntil(() => TimelineController.getMarkers().length > 0)),
-    "There are some markers available.");
-
-  yield TimelineController.toggleRecording();
-  ok(true, "Recording has ended.");
-
-  let markers = TimelineController.getMarkers();
-  let memory = TimelineController.getMemory();
-
-  isnot(markers.length, 0,
-    "There are some markers available.");
-  is(memory.length, 0,
-    "There are no memory measurements available.");
-
-  yield teardown(panel);
-  finish();
-});
--- a/browser/devtools/timeline/test/browser_timeline_recording.js
+++ b/browser/devtools/timeline/test/browser_timeline_recording.js
@@ -2,39 +2,33 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Tests if the timeline can properly start and stop a recording.
  */
 
 let test = Task.async(function*() {
   let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
-  let { $, gFront, TimelineController } = panel.panelWin;
-
-  $("#memory-checkbox").checked = true;
-  yield TimelineController.updateMemoryRecording();
+  let { gFront, TimelineController } = panel.panelWin;
 
   is((yield gFront.isRecording()), false,
     "The timeline actor should not be recording when the tool starts.");
   is(TimelineController.getMarkers().length, 0,
     "There should be no markers available when the tool starts.");
 
   yield TimelineController.toggleRecording();
 
   is((yield gFront.isRecording()), true,
     "The timeline actor should be recording now.");
   ok((yield waitUntil(() => TimelineController.getMarkers().length > 0)),
     "There are some markers available now.");
-  ok((yield waitUntil(() => TimelineController.getMemory().length > 0)),
-    "There are some memory measurements available now.");
 
-  ok("startTime" in TimelineController.getInterval(),
-    "A `startTime` field was set on the recording data.");
-  ok("endTime" in TimelineController.getInterval(),
-    "An `endTime` field was set on the recording data.");
-
-  ok(TimelineController.getInterval().endTime >
-     TimelineController.getInterval().startTime,
+  ok("startTime" in TimelineController.getMarkers(),
+    "A `startTime` field was set on the markers array.");
+  ok("endTime" in TimelineController.getMarkers(),
+    "An `endTime` field was set on the markers array.");
+  ok(TimelineController.getMarkers().endTime >
+     TimelineController.getMarkers().startTime,
     "Some time has passed since the recording started.");
 
   yield teardown(panel);
   finish();
 });
--- a/browser/devtools/timeline/test/browser_timeline_waterfall-background.js
+++ b/browser/devtools/timeline/test/browser_timeline_waterfall-background.js
@@ -12,17 +12,17 @@ let test = Task.async(function*() {
 
   yield TimelineController.toggleRecording();
   ok(true, "Recording has started.");
 
   let updated = 0;
   panel.panelWin.on(EVENTS.OVERVIEW_UPDATED, () => updated++);
 
   ok((yield waitUntil(() => updated > 0)),
-    "The overview graphs were updated a bunch of times.");
+    "The overview graph was updated a bunch of times.");
   ok((yield waitUntil(() => TimelineController.getMarkers().length > 0)),
     "There are some markers available.");
 
   yield TimelineController.toggleRecording();
   ok(true, "Recording has ended.");
 
   // Test the waterfall background.
 
--- a/browser/devtools/timeline/test/browser_timeline_waterfall-generic.js
+++ b/browser/devtools/timeline/test/browser_timeline_waterfall-generic.js
@@ -11,58 +11,58 @@ let test = Task.async(function*() {
 
   yield TimelineController.toggleRecording();
   ok(true, "Recording has started.");
 
   let updated = 0;
   panel.panelWin.on(EVENTS.OVERVIEW_UPDATED, () => updated++);
 
   ok((yield waitUntil(() => updated > 0)),
-    "The overview graphs were updated a bunch of times.");
+    "The overview graph was updated a bunch of times.");
   ok((yield waitUntil(() => TimelineController.getMarkers().length > 0)),
     "There are some markers available.");
 
   yield TimelineController.toggleRecording();
   ok(true, "Recording has ended.");
 
   // Test the header container.
 
-  ok($(".waterfall-header-container"),
+  ok($(".timeline-header-container"),
     "A header container should have been created.");
 
   // Test the header sidebar (left).
 
-  ok($(".waterfall-header-container > .waterfall-sidebar"),
+  ok($(".timeline-header-sidebar"),
     "A header sidebar node should have been created.");
-  ok($(".waterfall-header-container > .waterfall-sidebar > .waterfall-header-name"),
+  ok($(".timeline-header-sidebar > .timeline-header-name"),
     "A header name label should have been created inside the sidebar.");
 
   // Test the header ticks (right).
 
-  ok($(".waterfall-header-ticks"),
+  ok($(".timeline-header-ticks"),
     "A header ticks node should have been created.");
-  ok($$(".waterfall-header-ticks > .waterfall-header-tick").length > 0,
+  ok($$(".timeline-header-ticks > .timeline-header-tick").length > 0,
     "Some header tick labels should have been created inside the tick node.");
 
   // Test the markers container.
 
-  ok($(".waterfall-marker-container"),
+  ok($(".timeline-marker-container"),
     "A marker container should have been created.");
 
   // Test the markers sidebar (left).
 
-  ok($$(".waterfall-marker-container > .waterfall-sidebar").length,
+  ok($$(".timeline-marker-sidebar").length,
     "Some marker sidebar nodes should have been created.");
-  ok($$(".waterfall-marker-container > .waterfall-sidebar:not(spacer) > .waterfall-marker-bullet").length,
+  ok($$(".timeline-marker-sidebar:not(spacer) > .timeline-marker-bullet").length,
     "Some marker color bullets should have been created inside the sidebar.");
-  ok($$(".waterfall-marker-container > .waterfall-sidebar:not(spacer) > .waterfall-marker-name").length,
+  ok($$(".timeline-marker-sidebar:not(spacer) > .timeline-marker-name").length,
     "Some marker name labels should have been created inside the sidebar.");
 
   // Test the markers waterfall (right).
 
-  ok($$(".waterfall-marker-item").length,
+  ok($$(".timeline-marker-waterfall").length,
     "Some marker waterfall nodes should have been created.");
-  ok($$(".waterfall-marker-item:not(spacer) > .waterfall-marker-bar").length,
+  ok($$(".timeline-marker-waterfall:not(spacer) > .timeline-marker-bar").length,
     "Some marker color bars should have been created inside the waterfall.");
 
   yield teardown(panel);
   finish();
 });
--- a/browser/devtools/timeline/test/browser_timeline_waterfall-styles.js
+++ b/browser/devtools/timeline/test/browser_timeline_waterfall-styles.js
@@ -22,17 +22,17 @@ let test = Task.async(function*() {
 
   yield TimelineController.toggleRecording();
   ok(true, "Recording has started.");
 
   let updated = 0;
   panel.panelWin.on(EVENTS.OVERVIEW_UPDATED, () => updated++);
 
   ok((yield waitUntil(() => updated > 0)),
-    "The overview graphs were updated a bunch of times.");
+    "The overview graph was updated a bunch of times.");
   ok((yield waitUntil(() => TimelineController.getMarkers().length > 0)),
     "There are some markers available.");
 
   yield TimelineController.toggleRecording();
   ok(true, "Recording has ended.");
 
   // Test the table sidebars.
 
--- a/browser/devtools/timeline/timeline.js
+++ b/browser/devtools/timeline/timeline.js
@@ -7,39 +7,34 @@ const { classes: Cc, interfaces: Ci, uti
 
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://gre/modules/devtools/Loader.jsm");
 
 devtools.lazyRequireGetter(this, "promise");
 devtools.lazyRequireGetter(this, "EventEmitter",
   "devtools/toolkit/event-emitter");
 
-devtools.lazyRequireGetter(this, "MarkersOverview",
-  "devtools/timeline/markers-overview", true);
-devtools.lazyRequireGetter(this, "MemoryOverview",
-  "devtools/timeline/memory-overview", true);
+devtools.lazyRequireGetter(this, "Overview",
+  "devtools/timeline/overview", true);
 devtools.lazyRequireGetter(this, "Waterfall",
   "devtools/timeline/waterfall", true);
 
-devtools.lazyImporter(this, "CanvasGraphUtils",
-  "resource:///modules/devtools/Graphs.jsm");
-
 devtools.lazyImporter(this, "PluralForm",
   "resource://gre/modules/PluralForm.jsm");
 
 const OVERVIEW_UPDATE_INTERVAL = 200;
 const OVERVIEW_INITIAL_SELECTION_RATIO = 0.15;
 
 // The panel's window global is an EventEmitter firing the following events:
 const EVENTS = {
   // When a recording is started or stopped, via the `stopwatch` button.
   RECORDING_STARTED: "Timeline:RecordingStarted",
   RECORDING_ENDED: "Timeline:RecordingEnded",
 
-  // When the overview graphs are populated with new markers.
+  // When the overview graph is populated with new markers.
   OVERVIEW_UPDATED: "Timeline:OverviewUpdated",
 
   // When the waterfall view is populated with new markers.
   WATERFALL_UPDATED: "Timeline:WaterfallUpdated"
 };
 
 /**
  * The current target and the timeline front, set by this tool's host.
@@ -63,330 +58,225 @@ let shutdownTimeline = Task.async(functi
   yield gFront.stop();
 });
 
 /**
  * Functions handling the timeline frontend controller.
  */
 let TimelineController = {
   /**
-   * Permanent storage for the markers and the memory measurements streamed by
-   * the backend, along with the start and end timestamps.
+   * Permanent storage for the markers streamed by the backend.
    */
-  _starTime: 0,
-  _endTime: 0,
   _markers: [],
-  _memory: [],
 
   /**
    * Initialization function, called when the tool is started.
    */
   initialize: function() {
     this._onRecordingTick = this._onRecordingTick.bind(this);
     this._onMarkers = this._onMarkers.bind(this);
-    this._onMemory = this._onMemory.bind(this);
     gFront.on("markers", this._onMarkers);
-    gFront.on("memory", this._onMemory);
   },
 
   /**
    * Destruction function, called when the tool is closed.
    */
   destroy: function() {
     gFront.off("markers", this._onMarkers);
-    gFront.off("memory", this._onMemory);
-  },
-
-  /**
-   * Gets the { stat, end } time interval for this recording.
-   * @return object
-   */
-  getInterval: function() {
-    return { startTime: this._startTime, endTime: this._endTime };
   },
 
   /**
    * Gets the accumulated markers in this recording.
-   * @return array
+   * @return array.
    */
   getMarkers: function() {
     return this._markers;
   },
 
   /**
-   * Gets the accumulated memory measurements in this recording.
-   * @return array
-   */
-  getMemory: function() {
-    return this._memory;
-  },
-
-  /**
-   * Updates the views to show or hide the memory recording data.
-   */
-  updateMemoryRecording: Task.async(function*() {
-    if ($("#memory-checkbox").checked) {
-      yield TimelineView.showMemoryOverview();
-    } else {
-      yield TimelineView.hideMemoryOverview();
-    }
-  }),
-
-  /**
    * Starts/stops the timeline recording and streaming.
    */
   toggleRecording: Task.async(function*() {
     let isRecording = yield gFront.isRecording();
     if (isRecording == false) {
       yield this._startRecording();
     } else {
       yield this._stopRecording();
     }
   }),
 
   /**
    * Starts the recording, updating the UI as needed.
    */
   _startRecording: function*() {
     TimelineView.handleRecordingStarted();
-
-    let withMemory = $("#memory-checkbox").checked;
-    let startTime = yield gFront.start({ withMemory });
-
+    let startTime = yield gFront.start();
     // Times must come from the actor in order to be self-consistent.
     // However, we also want to update the view with the elapsed time
     // even when the actor is not generating data.  To do this we get
     // the local time and use it to compute a reasonable elapsed time.
     // See _onRecordingTick.
     this._localStartTime = performance.now();
-    this._startTime = startTime;
-    this._endTime = startTime;
+
     this._markers = [];
-    this._memory = [];
+    this._markers.startTime = startTime;
+    this._markers.endTime = startTime;
     this._updateId = setInterval(this._onRecordingTick, OVERVIEW_UPDATE_INTERVAL);
   },
 
   /**
    * Stops the recording, updating the UI as needed.
    */
   _stopRecording: function*() {
     clearInterval(this._updateId);
 
     // Sorting markers is only important when displayed in the waterfall.
     this._markers = this._markers.sort((a,b) => (a.start > b.start));
 
-    TimelineView.handleRecordingUpdate();
+    TimelineView.handleMarkersUpdate(this._markers);
     TimelineView.handleRecordingEnded();
     yield gFront.stop();
   },
 
   /**
    * Used in tests. Stops the recording, discarding the accumulated markers and
    * updating the UI as needed.
    */
   _stopRecordingAndDiscardData: function*() {
     yield this._stopRecording();
     this._markers.length = 0;
-    this._memory.length = 0;
   },
 
   /**
    * Callback handling the "markers" event on the timeline front.
    *
    * @param array markers
    *        A list of new markers collected since the last time this
    *        function was invoked.
    * @param number endTime
    *        A time after the last marker in markers was collected.
    */
   _onMarkers: function(markers, endTime) {
     Array.prototype.push.apply(this._markers, markers);
-    this._endTime = endTime;
-  },
-
-  /**
-   * Callback handling the "memory" event on the timeline front.
-   *
-   * @param number delta
-   *        The number of milliseconds elapsed since epoch.
-   * @param object measurement
-   *        A detailed breakdown of the current memory usage.
-   */
-  _onMemory: function(delta, measurement) {
-    this._memory.push({ delta, value: measurement.total / 1024 / 1024 });
+    this._markers.endTime = endTime;
   },
 
   /**
    * Callback invoked at a fixed interval while recording.
-   * Updates the current time and the timeline overview.
+   * Updates the markers store with the current time and the timeline overview.
    */
   _onRecordingTick: function() {
     // Compute an approximate ending time for the view.  This is
     // needed to ensure that the view updates even when new data is
     // not being generated.
-    let fakeTime = this._startTime + (performance.now() - this._localStartTime);
-    if (fakeTime > this._endTime) {
-      this._endTime = fakeTime;
+    let fakeTime = this._markers.startTime + (performance.now() - this._localStartTime);
+    if (fakeTime > this._markers.endTime) {
+      this._markers.endTime = fakeTime;
     }
-    TimelineView.handleRecordingUpdate();
+    TimelineView.handleMarkersUpdate(this._markers);
   }
 };
 
 /**
  * Functions handling the timeline frontend view.
  */
 let TimelineView = {
   /**
    * Initialization function, called when the tool is started.
    */
   initialize: Task.async(function*() {
-    this.markersOverview = new MarkersOverview($("#markers-overview"));
+    this.overview = new Overview($("#timeline-overview"));
     this.waterfall = new Waterfall($("#timeline-waterfall"));
 
     this._onSelecting = this._onSelecting.bind(this);
     this._onRefresh = this._onRefresh.bind(this);
-    this.markersOverview.on("selecting", this._onSelecting);
-    this.markersOverview.on("refresh", this._onRefresh);
+    this.overview.on("selecting", this._onSelecting);
+    this.overview.on("refresh", this._onRefresh);
 
-    yield this.markersOverview.ready();
+    yield this.overview.ready();
     yield this.waterfall.recalculateBounds();
   }),
 
   /**
    * Destruction function, called when the tool is closed.
    */
   destroy: function() {
-    this.markersOverview.off("selecting", this._onSelecting);
-    this.markersOverview.off("refresh", this._onRefresh);
-    this.markersOverview.destroy();
-
-    // The memory overview graph is not always available.
-    if (this.memoryOverview) {
-      this.memoryOverview.destroy();
-    }
-  },
-
-  /**
-   * Shows the memory overview graph.
-   */
-  showMemoryOverview: Task.async(function*() {
-    this.memoryOverview = new MemoryOverview($("#memory-overview"));
-    yield this.memoryOverview.ready();
-
-    let interval = TimelineController.getInterval();
-    let memory = TimelineController.getMemory();
-    this.memoryOverview.setData({ interval, memory });
-
-    CanvasGraphUtils.linkAnimation(this.markersOverview, this.memoryOverview);
-    CanvasGraphUtils.linkSelection(this.markersOverview, this.memoryOverview);
-  }),
-
-  /**
-   * Hides the memory overview graph.
-   */
-  hideMemoryOverview: function() {
-    if (!this.memoryOverview) {
-      return;
-    }
-    this.memoryOverview.destroy();
-    this.memoryOverview = null;
+    this.overview.off("selecting", this._onSelecting);
+    this.overview.off("refresh", this._onRefresh);
+    this.overview.destroy();
   },
 
   /**
    * Signals that a recording session has started and triggers the appropriate
    * changes in the UI.
    */
   handleRecordingStarted: function() {
     $("#record-button").setAttribute("checked", "true");
-    $("#memory-checkbox").setAttribute("disabled", "true");
     $("#timeline-pane").selectedPanel = $("#recording-notice");
 
-    this.markersOverview.clearView();
-
-    // The memory overview graph is not always available.
-    if (this.memoryOverview) {
-      this.memoryOverview.clearView();
-    }
-
+    this.overview.selectionEnabled = false;
+    this.overview.dropSelection();
+    this.overview.setData([]);
     this.waterfall.clearView();
 
     window.emit(EVENTS.RECORDING_STARTED);
   },
 
   /**
    * Signals that a recording session has ended and triggers the appropriate
    * changes in the UI.
    */
   handleRecordingEnded: function() {
     $("#record-button").removeAttribute("checked");
-    $("#memory-checkbox").removeAttribute("disabled");
     $("#timeline-pane").selectedPanel = $("#timeline-waterfall");
 
-    this.markersOverview.selectionEnabled = true;
+    this.overview.selectionEnabled = true;
 
-    // The memory overview graph is not always available.
-    if (this.memoryOverview) {
-      this.memoryOverview.selectionEnabled = true;
-    }
-
-    let interval = TimelineController.getInterval();
     let markers = TimelineController.getMarkers();
-    let memory = TimelineController.getMemory();
-
     if (markers.length) {
-      let start = (markers[0].start - interval.startTime) * this.markersOverview.dataScaleX;
-      let end = start + this.markersOverview.width * OVERVIEW_INITIAL_SELECTION_RATIO;
-      this.markersOverview.setSelection({ start, end });
+      let start = (markers[0].start - markers.startTime) * this.overview.dataScaleX;
+      let end = start + this.overview.width * OVERVIEW_INITIAL_SELECTION_RATIO;
+      this.overview.setSelection({ start, end });
     } else {
-      let timeStart = interval.startTime;
-      let timeEnd = interval.endTime;
-      this.waterfall.setData(markers, timeStart, timeStart, timeEnd);
+      let duration = markers.endTime - markers.startTime;
+      this.waterfall.setData(markers, markers.startTime, markers.endTime);
     }
 
     window.emit(EVENTS.RECORDING_ENDED);
   },
 
   /**
    * Signals that a new set of markers was made available by the controller,
    * or that the overview graph needs to be updated.
+   *
+   * @param array markers
+   *        A list of new markers collected since the recording has started.
    */
-  handleRecordingUpdate: function() {
-    let interval = TimelineController.getInterval();
-    let markers = TimelineController.getMarkers();
-    let memory = TimelineController.getMemory();
-
-    this.markersOverview.setData({ interval, markers });
-
-    // The memory overview graph is not always available.
-    if (this.memoryOverview) {
-      this.memoryOverview.setData({ interval, memory });
-    }
-
+  handleMarkersUpdate: function(markers) {
+    this.overview.setData(markers);
     window.emit(EVENTS.OVERVIEW_UPDATED);
   },
 
   /**
    * Callback handling the "selecting" event on the timeline overview.
    */
   _onSelecting: function() {
-    if (!this.markersOverview.hasSelection() &&
-        !this.markersOverview.hasSelectionInProgress()) {
+    if (!this.overview.hasSelection() &&
+        !this.overview.hasSelectionInProgress()) {
       this.waterfall.clearView();
       return;
     }
-    let selection = this.markersOverview.getSelection();
-    let start = selection.start / this.markersOverview.dataScaleX;
-    let end = selection.end / this.markersOverview.dataScaleX;
+    let selection = this.overview.getSelection();
+    let start = selection.start / this.overview.dataScaleX;
+    let end = selection.end / this.overview.dataScaleX;
 
     let markers = TimelineController.getMarkers();
-    let interval = TimelineController.getInterval();
-
-    let timeStart = interval.startTime + Math.min(start, end);
-    let timeEnd = interval.startTime + Math.max(start, end);
-    this.waterfall.setData(markers, interval.startTime, timeStart, timeEnd);
+    let timeStart = markers.startTime + Math.min(start, end);
+    let timeEnd = markers.startTime + Math.max(start, end);
+    this.waterfall.setData(markers, timeStart, timeEnd);
   },
 
   /**
    * Callback handling the "refresh" event on the timeline overview.
    */
   _onRefresh: function() {
     this.waterfall.recalculateBounds();
     this._onSelecting();
--- a/browser/devtools/timeline/timeline.xul
+++ b/browser/devtools/timeline/timeline.xul
@@ -20,27 +20,23 @@
              class="devtools-toolbar">
       <hbox id="recordings-controls"
             class="devtools-toolbarbutton-group"
             align="center">
         <toolbarbutton id="record-button"
                        class="devtools-toolbarbutton"
                        oncommand="TimelineController.toggleRecording()"
                        tooltiptext="&timelineUI.recordButton.tooltip;"/>
-        <checkbox id="memory-checkbox"
-                  label="&timelineUI.memoryCheckbox.label;"
-                  oncommand="TimelineController.updateMemoryRecording()"
-                  tooltiptext="&timelineUI.memoryCheckbox.tooltip;"/>
+        <spacer flex="1"/>
         <label id="record-label"
                value="&timelineUI.recordLabel;"/>
       </hbox>
     </toolbar>
 
-    <vbox id="markers-overview"/>
-    <vbox id="memory-overview"/>
+    <vbox id="timeline-overview"/>
 
     <deck id="timeline-pane"
           flex="1">
       <hbox id="empty-notice"
             class="notice-container"
             align="center"
             pack="center"
             flex="1">
deleted file mode 100644
--- a/browser/devtools/timeline/widgets/memory-overview.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/* 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";
-
-/**
- * This file contains the "memory overview" graph, a simple representation of
- * of all the memory measurements taken while streaming the timeline data.
- */
-
-const {Cc, Ci, Cu, Cr} = require("chrome");
-
-Cu.import("resource:///modules/devtools/Graphs.jsm");
-Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
-
-loader.lazyRequireGetter(this, "L10N",
-  "devtools/timeline/global", true);
-
-const HTML_NS = "http://www.w3.org/1999/xhtml";
-
-const OVERVIEW_HEIGHT = 30; // px
-
-const OVERVIEW_BACKGROUND_COLOR = "#fff";
-const OVERVIEW_BACKGROUND_GRADIENT_START = "rgba(0,136,204,0.1)";
-const OVERVIEW_BACKGROUND_GRADIENT_END = "rgba(0,136,204,0.0)";
-const OVERVIEW_STROKE_WIDTH = 1; // px
-const OVERVIEW_STROKE_COLOR = "rgba(0,136,204,1)";
-const OVERVIEW_CLIPHEAD_LINE_COLOR = "#666";
-const OVERVIEW_SELECTION_LINE_COLOR = "#555";
-const OVERVIEW_MAXIMUM_LINE_COLOR = "rgba(0,136,204,0.4)";
-const OVERVIEW_AVERAGE_LINE_COLOR = "rgba(0,136,204,0.7)";
-const OVERVIEW_MINIMUM_LINE_COLOR = "rgba(0,136,204,0.9)";
-
-const OVERVIEW_SELECTION_BACKGROUND_COLOR = "rgba(76,158,217,0.25)";
-const OVERVIEW_SELECTION_STRIPES_COLOR = "rgba(255,255,255,0.1)";
-
-/**
- * An overview for the memory data.
- *
- * @param nsIDOMNode parent
- *        The parent node holding the overview.
- */
-function MemoryOverview(parent) {
-  LineGraphWidget.call(this, parent, L10N.getStr("graphs.memory"));
-
-  this.once("ready", () => {
-    // Populate this overview with some dummy initial data.
-    this.setData({ interval: { startTime: 0, endTime: 1000 }, memory: [] });
-  });
-}
-
-MemoryOverview.prototype = Heritage.extend(LineGraphWidget.prototype, {
-  dampenValuesFactor: 0.95,
-  fixedHeight: OVERVIEW_HEIGHT,
-  backgroundColor: OVERVIEW_BACKGROUND_COLOR,
-  backgroundGradientStart: OVERVIEW_BACKGROUND_GRADIENT_START,
-  backgroundGradientEnd: OVERVIEW_BACKGROUND_GRADIENT_END,
-  strokeColor: OVERVIEW_STROKE_COLOR,
-  strokeWidth: OVERVIEW_STROKE_WIDTH,
-  maximumLineColor: OVERVIEW_MAXIMUM_LINE_COLOR,
-  averageLineColor: OVERVIEW_AVERAGE_LINE_COLOR,
-  minimumLineColor: OVERVIEW_MINIMUM_LINE_COLOR,
-  clipheadLineColor: OVERVIEW_CLIPHEAD_LINE_COLOR,
-  selectionLineColor: OVERVIEW_SELECTION_LINE_COLOR,
-  selectionBackgroundColor: OVERVIEW_SELECTION_BACKGROUND_COLOR,
-  selectionStripesColor: OVERVIEW_SELECTION_STRIPES_COLOR,
-  withTooltipArrows: false,
-  withFixedTooltipPositions: true,
-
-  /**
-   * Disables selection and empties this graph.
-   */
-  clearView: function() {
-    this.selectionEnabled = false;
-    this.dropSelection();
-    this.setData({ interval: { startTime: 0, endTime: 0 }, memory: [] });
-  },
-
-  /**
-   * Sets the data source for this graph.
-   */
-  setData: function({ interval, memory }) {
-    this.dataOffsetX = interval.startTime;
-    LineGraphWidget.prototype.setData.call(this, memory);
-  }
-});
-
-exports.MemoryOverview = MemoryOverview;
rename from browser/devtools/timeline/widgets/markers-overview.js
rename to browser/devtools/timeline/widgets/overview.js
--- a/browser/devtools/timeline/widgets/markers-overview.js
+++ b/browser/devtools/timeline/widgets/overview.js
@@ -1,73 +1,73 @@
 /* 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";
 
 /**
- * This file contains the "markers overview" graph, which is a minimap of all
- * the timeline data. Regions inside it may be selected, determining which
- * markers are visible in the "waterfall".
+ * This file contains the "overview" graph, which is a minimap of all the
+ * timeline data. Regions inside it may be selected, determining which markers
+ * are visible in the "waterfall".
  */
 
 const {Cc, Ci, Cu, Cr} = require("chrome");
 
 Cu.import("resource:///modules/devtools/Graphs.jsm");
 Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
 
 loader.lazyRequireGetter(this, "L10N",
   "devtools/timeline/global", true);
 loader.lazyRequireGetter(this, "TIMELINE_BLUEPRINT",
   "devtools/timeline/global", true);
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 
-const OVERVIEW_HEADER_HEIGHT = 14; // px
-const OVERVIEW_BODY_HEIGHT = 55; // 11px * 5 groups
+const OVERVIEW_HEADER_HEIGHT = 20; // px
+const OVERVIEW_BODY_HEIGHT = 50; // px
 
 const OVERVIEW_BACKGROUND_COLOR = "#fff";
 const OVERVIEW_CLIPHEAD_LINE_COLOR = "#666";
 const OVERVIEW_SELECTION_LINE_COLOR = "#555";
 const OVERVIEW_SELECTION_BACKGROUND_COLOR = "rgba(76,158,217,0.25)";
 const OVERVIEW_SELECTION_STRIPES_COLOR = "rgba(255,255,255,0.1)";
 
 const OVERVIEW_HEADER_TICKS_MULTIPLE = 100; // ms
 const OVERVIEW_HEADER_TICKS_SPACING_MIN = 75; // px
 const OVERVIEW_HEADER_SAFE_BOUNDS = 50; // px
-const OVERVIEW_HEADER_BACKGROUND = "#fff";
+const OVERVIEW_HEADER_BACKGROUND = "#ebeced";
 const OVERVIEW_HEADER_TEXT_COLOR = "#18191a";
 const OVERVIEW_HEADER_TEXT_FONT_SIZE = 9; // px
 const OVERVIEW_HEADER_TEXT_FONT_FAMILY = "sans-serif";
-const OVERVIEW_HEADER_TEXT_PADDING_LEFT = 6; // px
-const OVERVIEW_HEADER_TEXT_PADDING_TOP = 1; // px
-const OVERVIEW_TIMELINE_STROKES = "#ccc";
+const OVERVIEW_HEADER_TEXT_PADDING = 6; // px
+const OVERVIEW_TIMELINE_STROKES = "#aaa";
 const OVERVIEW_MARKERS_COLOR_STOPS = [0, 0.1, 0.75, 1];
 const OVERVIEW_MARKER_DURATION_MIN = 4; // ms
-const OVERVIEW_GROUP_VERTICAL_PADDING = 5; // px
+const OVERVIEW_GROUP_VERTICAL_PADDING = 6; // px
 const OVERVIEW_GROUP_ALTERNATING_BACKGROUND = "rgba(0,0,0,0.05)";
 
 /**
- * An overview for the markers data.
+ * An overview for the timeline data.
  *
  * @param nsIDOMNode parent
  *        The parent node holding the overview.
  */
-function MarkersOverview(parent, ...args) {
-  AbstractCanvasGraph.apply(this, [parent, "markers-overview", ...args]);
+function Overview(parent, ...args) {
+  AbstractCanvasGraph.apply(this, [parent, "timeline-overview", ...args]);
   this.once("ready", () => {
-    // Set the list of names, properties and colors used to paint this overview.
     this.setBlueprint(TIMELINE_BLUEPRINT);
 
-    // Populate this overview with some dummy initial data.
-    this.setData({ interval: { startTime: 0, endTime: 1000 }, markers: [] });
+    var preview = [];
+    preview.startTime = 0;
+    preview.endTime = 1000;
+    this.setData(preview);
   });
 }
 
-MarkersOverview.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
+Overview.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
   fixedHeight: OVERVIEW_HEADER_HEIGHT + OVERVIEW_BODY_HEIGHT,
   clipheadLineColor: OVERVIEW_CLIPHEAD_LINE_COLOR,
   selectionLineColor: OVERVIEW_SELECTION_LINE_COLOR,
   selectionBackgroundColor: OVERVIEW_SELECTION_BACKGROUND_COLOR,
   selectionStripesColor: OVERVIEW_SELECTION_STRIPES_COLOR,
 
   /**
    * List of names and colors used to paint this overview.
@@ -79,97 +79,83 @@ MarkersOverview.prototype = Heritage.ext
 
     for (let type in blueprint) {
       this._paintBatches.set(type, { style: blueprint[type], batch: [] });
       this._lastGroup = Math.max(this._lastGroup, blueprint[type].group);
     }
   },
 
   /**
-   * Disables selection and empties this graph.
-   */
-  clearView: function() {
-    this.selectionEnabled = false;
-    this.dropSelection();
-    this.setData({ interval: { startTime: 0, endTime: 0 }, markers: [] });
-  },
-
-  /**
    * Renders the graph's data source.
    * @see AbstractCanvasGraph.prototype.buildGraphImage
    */
   buildGraphImage: function() {
-    let { interval, markers } = this._data;
-    let { startTime, endTime } = interval;
-
     let { canvas, ctx } = this._getNamedCanvas("overview-data");
     let canvasWidth = this._width;
     let canvasHeight = this._height;
     let safeBounds = OVERVIEW_HEADER_SAFE_BOUNDS * this._pixelRatio;
     let availableWidth = canvasWidth - safeBounds;
 
     // Group markers into separate paint batches. This is necessary to
     // draw all markers sharing the same style at once.
 
-    for (let marker of markers) {
+    for (let marker of this._data) {
       this._paintBatches.get(marker.name).batch.push(marker);
     }
 
     // Calculate each group's height, and the time-based scaling.
 
     let totalGroups = this._lastGroup + 1;
     let headerHeight = OVERVIEW_HEADER_HEIGHT * this._pixelRatio;
     let groupHeight = OVERVIEW_BODY_HEIGHT * this._pixelRatio / totalGroups;
     let groupPadding = OVERVIEW_GROUP_VERTICAL_PADDING * this._pixelRatio;
 
-    let totalTime = (endTime - startTime) || 0;
+    let totalTime = (this._data.endTime - this._data.startTime) || 0;
     let dataScale = this.dataScaleX = availableWidth / totalTime;
 
     // Draw the header and overview background.
 
     ctx.fillStyle = OVERVIEW_HEADER_BACKGROUND;
     ctx.fillRect(0, 0, canvasWidth, headerHeight);
 
     ctx.fillStyle = OVERVIEW_BACKGROUND_COLOR;
     ctx.fillRect(0, headerHeight, canvasWidth, canvasHeight);
 
     // Draw the alternating odd/even group backgrounds.
 
     ctx.fillStyle = OVERVIEW_GROUP_ALTERNATING_BACKGROUND;
     ctx.beginPath();
 
-    for (let i = 0; i < totalGroups; i += 2) {
+    for (let i = 1; i < totalGroups; i += 2) {
       let top = headerHeight + i * groupHeight;
       ctx.rect(0, top, canvasWidth, groupHeight);
     }
 
     ctx.fill();
 
     // Draw the timeline header ticks.
 
+    ctx.textBaseline = "middle";
     let fontSize = OVERVIEW_HEADER_TEXT_FONT_SIZE * this._pixelRatio;
     let fontFamily = OVERVIEW_HEADER_TEXT_FONT_FAMILY;
-    let textPaddingLeft = OVERVIEW_HEADER_TEXT_PADDING_LEFT * this._pixelRatio;
-    let textPaddingTop = OVERVIEW_HEADER_TEXT_PADDING_TOP * this._pixelRatio;
-    let tickInterval = this._findOptimalTickInterval(dataScale);
-
-    ctx.textBaseline = "middle";
     ctx.font = fontSize + "px " + fontFamily;
     ctx.fillStyle = OVERVIEW_HEADER_TEXT_COLOR;
     ctx.strokeStyle = OVERVIEW_TIMELINE_STROKES;
     ctx.beginPath();
 
+    let tickInterval = this._findOptimalTickInterval(dataScale);
+    let headerTextPadding = OVERVIEW_HEADER_TEXT_PADDING * this._pixelRatio;
+
     for (let x = 0; x < availableWidth; x += tickInterval) {
-      let lineLeft = x;
-      let textLeft = lineLeft + textPaddingLeft;
+      let left = x + headerTextPadding;
       let time = Math.round(x / dataScale);
       let label = L10N.getFormatStr("timeline.tick", time);
-      ctx.fillText(label, textLeft, headerHeight / 2 + textPaddingTop);
-      ctx.moveTo(lineLeft, 0);
-      ctx.lineTo(lineLeft, canvasHeight);
+      ctx.fillText(label, left, headerHeight / 2 + 1);
+      ctx.moveTo(x, 0);
+      ctx.lineTo(x, canvasHeight);
     }
 
     ctx.stroke();
 
     // Draw the timeline markers.
 
     for (let [, { style, batch }] of this._paintBatches) {
       let top = headerHeight + style.group * groupHeight + groupPadding / 2;
@@ -179,18 +165,18 @@ MarkersOverview.prototype = Heritage.ext
       gradient.addColorStop(OVERVIEW_MARKERS_COLOR_STOPS[0], style.stroke);
       gradient.addColorStop(OVERVIEW_MARKERS_COLOR_STOPS[1], style.fill);
       gradient.addColorStop(OVERVIEW_MARKERS_COLOR_STOPS[2], style.fill);
       gradient.addColorStop(OVERVIEW_MARKERS_COLOR_STOPS[3], style.stroke);
       ctx.fillStyle = gradient;
       ctx.beginPath();
 
       for (let { start, end } of batch) {
-        start -= interval.startTime;
-        end -= interval.startTime;
+        start -= this._data.startTime;
+        end -= this._data.startTime;
 
         let left = start * dataScale;
         let duration = Math.max(end - start, OVERVIEW_MARKER_DURATION_MIN);
         let width = Math.max(duration * dataScale, this._pixelRatio);
         ctx.rect(left, top, width, height);
       }
 
       ctx.fill();
@@ -217,9 +203,9 @@ MarkersOverview.prototype = Heritage.ext
         timingStep <<= 1;
         continue;
       }
       return scaledStep;
     }
   }
 });
 
-exports.MarkersOverview = MarkersOverview;
+exports.Overview = Overview;
--- a/browser/devtools/timeline/widgets/waterfall.js
+++ b/browser/devtools/timeline/widgets/waterfall.js
@@ -17,51 +17,51 @@ loader.lazyRequireGetter(this, "TIMELINE
 
 loader.lazyImporter(this, "setNamedTimeout",
   "resource:///modules/devtools/ViewHelpers.jsm");
 loader.lazyImporter(this, "clearNamedTimeout",
   "resource:///modules/devtools/ViewHelpers.jsm");
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 
-const WATERFALL_SIDEBAR_WIDTH = 150; // px
+const TIMELINE_IMMEDIATE_DRAW_MARKERS_COUNT = 30;
+const TIMELINE_FLUSH_OUTSTANDING_MARKERS_DELAY = 75; // ms
 
-const WATERFALL_IMMEDIATE_DRAW_MARKERS_COUNT = 30;
-const WATERFALL_FLUSH_OUTSTANDING_MARKERS_DELAY = 75; // ms
+const TIMELINE_HEADER_TICKS_MULTIPLE = 5; // ms
+const TIMELINE_HEADER_TICKS_SPACING_MIN = 50; // px
+const TIMELINE_HEADER_TEXT_PADDING = 3; // px
 
-const WATERFALL_HEADER_TICKS_MULTIPLE = 5; // ms
-const WATERFALL_HEADER_TICKS_SPACING_MIN = 50; // px
-const WATERFALL_HEADER_TEXT_PADDING = 3; // px
+const TIMELINE_MARKER_SIDEBAR_WIDTH = 150; // px
+const TIMELINE_MARKER_BAR_WIDTH_MIN = 5; // px
 
 const WATERFALL_BACKGROUND_TICKS_MULTIPLE = 5; // ms
 const WATERFALL_BACKGROUND_TICKS_SCALES = 3;
 const WATERFALL_BACKGROUND_TICKS_SPACING_MIN = 10; // px
 const WATERFALL_BACKGROUND_TICKS_COLOR_RGB = [128, 136, 144];
 const WATERFALL_BACKGROUND_TICKS_OPACITY_MIN = 32; // byte
 const WATERFALL_BACKGROUND_TICKS_OPACITY_ADD = 32; // byte
-const WATERFALL_MARKER_BAR_WIDTH_MIN = 5; // px
 
 /**
  * A detailed waterfall view for the timeline data.
  *
  * @param nsIDOMNode parent
  *        The parent node holding the waterfall.
  */
 function Waterfall(parent) {
   this._parent = parent;
   this._document = parent.ownerDocument;
   this._fragment = this._document.createDocumentFragment();
   this._outstandingMarkers = [];
 
   this._headerContents = this._document.createElement("hbox");
-  this._headerContents.className = "waterfall-header-contents";
+  this._headerContents.className = "timeline-header-contents";
   this._parent.appendChild(this._headerContents);
 
   this._listContents = this._document.createElement("vbox");
-  this._listContents.className = "waterfall-list-contents";
+  this._listContents.className = "timeline-list-contents";
   this._listContents.setAttribute("flex", "1");
   this._parent.appendChild(this._listContents);
 
   this._isRTL = this._getRTL();
 
   // Lazy require is a bit slow, and these are hot objects.
   this._l10n = L10N;
   this._blueprint = TIMELINE_BLUEPRINT;
@@ -70,31 +70,28 @@ function Waterfall(parent) {
 }
 
 Waterfall.prototype = {
   /**
    * Populates this view with the provided data source.
    *
    * @param array markers
    *        A list of markers received from the controller.
-   * @param number timeEpoch
-   *        The absolute time (in milliseconds) when the recording started.
    * @param number timeStart
    *        The time (in milliseconds) to start drawing from.
    * @param number timeEnd
    *        The time (in milliseconds) to end drawing at.
    */
-  setData: function(markers, timeEpoch, timeStart, timeEnd) {
+  setData: function(markers, timeStart, timeEnd) {
     this.clearView();
 
     let dataScale = this._waterfallWidth / (timeEnd - timeStart);
     this._drawWaterfallBackground(dataScale);
-
     // Label the header as if the first possible marker was at T=0.
-    this._buildHeader(this._headerContents, timeStart - timeEpoch, dataScale);
+    this._buildHeader(this._headerContents, timeStart - markers.startTime, dataScale);
     this._buildMarkers(this._listContents, markers, timeStart, timeEnd, dataScale);
   },
 
   /**
    * Depopulates this view.
    */
   clearView: function() {
     while (this._headerContents.hasChildNodes()) {
@@ -109,66 +106,66 @@ Waterfall.prototype = {
   },
 
   /**
    * Calculates and stores the available width for the waterfall.
    * This should be invoked every time the container window is resized.
    */
   recalculateBounds: function() {
     let bounds = this._parent.getBoundingClientRect();
-    this._waterfallWidth = bounds.width - WATERFALL_SIDEBAR_WIDTH;
+    this._waterfallWidth = bounds.width - TIMELINE_MARKER_SIDEBAR_WIDTH;
   },
 
   /**
    * Creates the header part of this view.
    *
    * @param nsIDOMNode parent
    *        The parent node holding the header.
    * @param number timeStart
    *        @see Waterfall.prototype.setData
    * @param number dataScale
    *        The time scale of the data source.
    */
   _buildHeader: function(parent, timeStart, dataScale) {
     let container = this._document.createElement("hbox");
-    container.className = "waterfall-header-container";
+    container.className = "timeline-header-container";
     container.setAttribute("flex", "1");
 
     let sidebar = this._document.createElement("hbox");
-    sidebar.className = "waterfall-sidebar theme-sidebar";
-    sidebar.setAttribute("width", WATERFALL_SIDEBAR_WIDTH);
+    sidebar.className = "timeline-header-sidebar theme-sidebar";
+    sidebar.setAttribute("width", TIMELINE_MARKER_SIDEBAR_WIDTH);
     sidebar.setAttribute("align", "center");
     container.appendChild(sidebar);
 
     let name = this._document.createElement("label");
-    name.className = "plain waterfall-header-name";
+    name.className = "plain timeline-header-name";
     name.setAttribute("value", this._l10n.getStr("timeline.records"));
     sidebar.appendChild(name);
 
     let ticks = this._document.createElement("hbox");
-    ticks.className = "waterfall-header-ticks waterfall-background-ticks";
+    ticks.className = "timeline-header-ticks";
     ticks.setAttribute("align", "center");
     ticks.setAttribute("flex", "1");
     container.appendChild(ticks);
 
     let offset = this._isRTL ? this._waterfallWidth : 0;
     let direction = this._isRTL ? -1 : 1;
     let tickInterval = this._findOptimalTickInterval({
-      ticksMultiple: WATERFALL_HEADER_TICKS_MULTIPLE,
-      ticksSpacingMin: WATERFALL_HEADER_TICKS_SPACING_MIN,
+      ticksMultiple: TIMELINE_HEADER_TICKS_MULTIPLE,
+      ticksSpacingMin: TIMELINE_HEADER_TICKS_SPACING_MIN,
       dataScale: dataScale
     });
 
     for (let x = 0; x < this._waterfallWidth; x += tickInterval) {
-      let start = x + direction * WATERFALL_HEADER_TEXT_PADDING;
+      let start = x + direction * TIMELINE_HEADER_TEXT_PADDING;
       let time = Math.round(timeStart + x / dataScale);
       let label = this._l10n.getFormatStr("timeline.tick", time);
 
       let node = this._document.createElement("label");
-      node.className = "plain waterfall-header-tick";
+      node.className = "plain timeline-header-tick";
       node.style.transform = "translateX(" + (start - offset) + "px)";
       node.setAttribute("value", label);
       ticks.appendChild(node);
     }
 
     parent.appendChild(container);
   },
 
@@ -188,32 +185,32 @@ Waterfall.prototype = {
     for (let marker of markers) {
       if (!isMarkerInRange(marker, timeStart, timeEnd)) {
         continue;
       }
       // Only build and display a finite number of markers initially, to
       // preserve a snappy UI. After a certain delay, continue building the
       // outstanding markers while there's (hopefully) no user interaction.
       let arguments_ = [this._fragment, marker, timeStart, dataScale];
-      if (processed++ < WATERFALL_IMMEDIATE_DRAW_MARKERS_COUNT) {
+      if (processed++ < TIMELINE_IMMEDIATE_DRAW_MARKERS_COUNT) {
         this._buildMarker.apply(this, arguments_);
       } else {
         this._outstandingMarkers.push(arguments_);
       }
     }
 
     // If there are no outstanding markers, add a dummy "spacer" at the end
     // to fill up any remaining available space in the UI.
     if (!this._outstandingMarkers.length) {
       this._buildMarker(this._fragment, null);
     }
     // Otherwise prepare flushing the outstanding markers after a small delay.
     else {
       this._setNamedTimeout("flush-outstanding-markers",
-        WATERFALL_FLUSH_OUTSTANDING_MARKERS_DELAY,
+        TIMELINE_FLUSH_OUTSTANDING_MARKERS_DELAY,
         () => this._buildOutstandingMarkers(parent));
     }
 
     parent.appendChild(this._fragment);
   },
 
   /**
    * Finishes building the outstanding markers in this view.
@@ -239,17 +236,17 @@ Waterfall.prototype = {
    *        The { name, start, end } marker in the data source.
    * @param timeStart
    *        @see Waterfall.prototype.setData
    * @param number dataScale
    *        @see Waterfall.prototype._buildMarkers
    */
   _buildMarker: function(parent, marker, timeStart, dataScale) {
     let container = this._document.createElement("hbox");
-    container.className = "waterfall-marker-container";
+    container.className = "timeline-marker-container";
 
     if (marker) {
       this._buildMarkerSidebar(container, marker);
       this._buildMarkerWaterfall(container, marker, timeStart, dataScale);
     } else {
       this._buildMarkerSpacer(container);
       container.setAttribute("flex", "1");
       container.setAttribute("is-spacer", "");
@@ -265,31 +262,31 @@ Waterfall.prototype = {
    *        The container node representing the marker in this view.
    * @param object marker
    *        @see Waterfall.prototype._buildMarker
    */
   _buildMarkerSidebar: function(container, marker) {
     let blueprint = this._blueprint[marker.name];
 
     let sidebar = this._document.createElement("hbox");
-    sidebar.className = "waterfall-sidebar theme-sidebar";
-    sidebar.setAttribute("width", WATERFALL_SIDEBAR_WIDTH);
+    sidebar.className = "timeline-marker-sidebar theme-sidebar";
+    sidebar.setAttribute("width", TIMELINE_MARKER_SIDEBAR_WIDTH);
     sidebar.setAttribute("align", "center");
 
     let bullet = this._document.createElement("hbox");
-    bullet.className = "waterfall-marker-bullet";
+    bullet.className = "timeline-marker-bullet";
     bullet.style.backgroundColor = blueprint.fill;
     bullet.style.borderColor = blueprint.stroke;
     bullet.setAttribute("type", marker.name);
     sidebar.appendChild(bullet);
 
     let name = this._document.createElement("label");
     name.setAttribute("crop", "end");
     name.setAttribute("flex", "1");
-    name.className = "plain waterfall-marker-name";
+    name.className = "plain timeline-marker-name";
 
     let label;
     if (marker.detail && marker.detail.causeName) {
       label = this._l10n.getFormatStr("timeline.markerDetailFormat",
                                       blueprint.label,
                                       marker.detail.causeName);
     } else {
       label = blueprint.label;
@@ -312,49 +309,48 @@ Waterfall.prototype = {
    *        @see Waterfall.prototype.setData
    * @param number dataScale
    *        @see Waterfall.prototype._buildMarkers
    */
   _buildMarkerWaterfall: function(container, marker, timeStart, dataScale) {
     let blueprint = this._blueprint[marker.name];
 
     let waterfall = this._document.createElement("hbox");
-    waterfall.className = "waterfall-marker-item waterfall-background-ticks";
-    waterfall.setAttribute("align", "center");
+    waterfall.className = "timeline-marker-waterfall";
     waterfall.setAttribute("flex", "1");
 
     let start = (marker.start - timeStart) * dataScale;
     let width = (marker.end - marker.start) * dataScale;
     let offset = this._isRTL ? this._waterfallWidth : 0;
 
     let bar = this._document.createElement("hbox");
-    bar.className = "waterfall-marker-bar";
+    bar.className = "timeline-marker-bar";
     bar.style.backgroundColor = blueprint.fill;
     bar.style.borderColor = blueprint.stroke;
     bar.style.transform = "translateX(" + (start - offset) + "px)";
     bar.setAttribute("type", marker.name);
-    bar.setAttribute("width", Math.max(width, WATERFALL_MARKER_BAR_WIDTH_MIN));
+    bar.setAttribute("width", Math.max(width, TIMELINE_MARKER_BAR_WIDTH_MIN));
     waterfall.appendChild(bar);
 
     container.appendChild(waterfall);
   },
 
   /**
    * Creates a dummy spacer as an empty marker.
    *
    * @param nsIDOMNode container
    *        The container node representing the marker.
    */
   _buildMarkerSpacer: function(container) {
     let sidebarSpacer = this._document.createElement("spacer");
-    sidebarSpacer.className = "waterfall-sidebar theme-sidebar";
-    sidebarSpacer.setAttribute("width", WATERFALL_SIDEBAR_WIDTH);
+    sidebarSpacer.className = "timeline-marker-sidebar theme-sidebar";
+    sidebarSpacer.setAttribute("width", TIMELINE_MARKER_SIDEBAR_WIDTH);
 
     let waterfallSpacer = this._document.createElement("spacer");
-    waterfallSpacer.className = "waterfall-marker-item waterfall-background-ticks";
+    waterfallSpacer.className = "timeline-marker-waterfall";
     waterfallSpacer.setAttribute("flex", "1");
 
     container.appendChild(sidebarSpacer);
     container.appendChild(waterfallSpacer);
   },
 
   /**
    * Creates the background displayed on the marker's waterfall.
--- a/browser/locales/en-US/chrome/browser/devtools/timeline.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/timeline.dtd
@@ -10,29 +10,20 @@
   - You want to make that choice consistent across the developer tools.
   - A good criteria is the language in which you'd find the best
   - documentation on web development on the web. -->
 
 <!-- LOCALIZATION NOTE (timelineUI.recordButton): This string is displayed
   -  on a button that starts a new recording. -->
 <!ENTITY timelineUI.recordButton.tooltip "Record timeline operations">
 
-<!-- LOCALIZATION NOTE (timelineUI.recordLabel): This string is displayed
+<!-- LOCALIZATION NOTE (timelineUI.recordButton): This string is displayed
   -  as a label to signal that a recording is in progress. -->
 <!ENTITY timelineUI.recordLabel "Recording…">
 
-<!-- LOCALIZATION NOTE (timelineUI.timelineUI.memoryCheckbox.label): This string
-  -  is displayed next to a checkbox determining whether or not memory
-  -  measurements are enabled. -->
-<!ENTITY timelineUI.memoryCheckbox.label "Memory">
-
-<!-- LOCALIZATION NOTE (timelineUI.timelineUI.memoryCheckbox.tooltip): This string
-  -  is displayed next to the memory checkbox -->
-<!ENTITY timelineUI.memoryCheckbox.tooltip "Enable memory measurements">
-
 <!-- LOCALIZATION NOTE (timelineUI.emptyNotice1/2): This is the label shown
   -  in the timeline view when empty. -->
 <!ENTITY timelineUI.emptyNotice1    "Click on the">
 <!ENTITY timelineUI.emptyNotice2    "button to start recording timeline events.">
 
 <!-- LOCALIZATION NOTE (timelineUI.stopNotice1/2): This is the label shown
   -  in the timeline view while recording. -->
 <!ENTITY timelineUI.stopNotice1    "Click on the">
--- a/browser/locales/en-US/chrome/browser/devtools/timeline.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/timeline.properties
@@ -36,19 +36,13 @@ timeline.records=RECORDS
 # LOCALIZATION NOTE (timeline.label.*):
 # These strings are displayed in the timeline waterfall, identifying markers.
 timeline.label.styles=Styles
 timeline.label.reflow=Reflow
 timeline.label.paint=Paint
 timeline.label.domevent=DOM Event
 timeline.label.consoleTime=Console
 
-# LOCALIZATION NOTE (graphs.memory):
-# This string is displayed in the memory graph of the Performance tool,
-# as the unit used to memory consumption. This label should be kept
-# AS SHORT AS POSSIBLE so it doesn't obstruct important parts of the graph.
-graphs.memory=MB
-
 # LOCALIZATION NOTE (timeline.markerDetailFormat):
 # Some timeline markers come with details, like a size, a name, a js function.
 # %1$S is replaced with one of the above label (timeline.label.*) and %2$S
 # with the details. For examples: Paint (200x100), or console.time (FOO)
 timeline.markerDetailFormat=%1$S (%2$S)
--- a/browser/themes/shared/devtools/timeline.inc.css
+++ b/browser/themes/shared/devtools/timeline.inc.css
@@ -43,113 +43,117 @@
   list-style-image: url(profiler-stopwatch-checked.svg);
 }
 
 #empty-notice button .button-text,
 #recording-notice button .button-text {
   display: none;
 }
 
-.theme-dark #timeline-pane {
-  border-top: 1px solid #000;
+.theme-dark #timeline-overview {
+  border-bottom: 1px solid #000;
 }
 
-.theme-light #timeline-pane {
-  border-top: 1px solid #aaa;
+.theme-light #timeline-overview {
+  border-bottom: 1px solid #aaa;
 }
 
-.waterfall-list-contents {
+.timeline-list-contents {
   /* Hack: force hardware acceleration */
   transform: translateZ(1px);
   overflow-x: hidden;
   overflow-y: auto;
 }
 
-.waterfall-background-ticks {
+.timeline-header-ticks,
+.timeline-marker-waterfall {
   /* Background created on a <canvas> in js. */
   /* @see browser/devtools/timeline/widgets/waterfall.js */
   background-image: -moz-element(#waterfall-background);
   background-repeat: repeat-y;
   background-position: -1px center;
 }
 
-.waterfall-marker-container[is-spacer] {
+.timeline-marker-waterfall {
+  overflow: hidden;
+}
+
+.timeline-marker-container[is-spacer] {
   pointer-events: none;
 }
 
-.theme-dark .waterfall-marker-container:not([is-spacer]):nth-child(2n) {
+.theme-dark .timeline-marker-container:not([is-spacer]):nth-child(2n) {
   background-color: rgba(255,255,255,0.03);
 }
 
-.theme-light .waterfall-marker-container:not([is-spacer]):nth-child(2n) {
+.theme-light .timeline-marker-container:not([is-spacer]):nth-child(2n) {
   background-color: rgba(128,128,128,0.03);
 }
 
-.theme-dark .waterfall-marker-container:hover {
+.theme-dark .timeline-marker-container:hover {
   background-color: rgba(255,255,255,0.1) !important;
 }
 
-.theme-light .waterfall-marker-container:hover {
+.theme-light .timeline-marker-container:hover {
   background-color: rgba(128,128,128,0.1) !important;
 }
 
-.waterfall-marker-item {
-  overflow: hidden;
-}
-
-.waterfall-sidebar {
+.timeline-header-sidebar,
+.timeline-marker-sidebar {
   -moz-border-end: 1px solid;
 }
 
-.theme-dark .waterfall-sidebar {
+.theme-dark .timeline-header-sidebar,
+.theme-dark .timeline-marker-sidebar {
   -moz-border-end-color: #000;
 }
 
-.theme-light .waterfall-sidebar {
+.theme-light .timeline-header-sidebar,
+.theme-light .timeline-marker-sidebar {
   -moz-border-end-color: #aaa;
 }
 
-.waterfall-marker-container:hover > .waterfall-sidebar {
+.timeline-header-sidebar {
+  padding: 5px;
+}
+
+.timeline-marker-sidebar {
+  padding: 2px;
+}
+
+.timeline-marker-container:hover > .timeline-marker-sidebar {
   background-color: transparent;
 }
 
-.waterfall-header-name {
-  padding: 4px;
-}
-
-.waterfall-header-tick {
+.timeline-header-tick {
   width: 100px;
   font-size: 9px;
   transform-origin: left center;
 }
 
-.theme-dark .waterfall-header-tick {
+.theme-dark .timeline-header-tick {
   color: #a9bacb;
 }
 
-.theme-light .waterfall-header-tick {
+.theme-light .timeline-header-tick {
   color: #292e33;
 }
 
-.waterfall-header-tick:not(:first-child) {
+.timeline-header-tick:not(:first-child) {
   -moz-margin-start: -100px !important; /* Don't affect layout. */
 }
 
-.waterfall-marker-bullet {
+.timeline-marker-bullet {
   width: 8px;
   height: 8px;
   -moz-margin-start: 8px;
   -moz-margin-end: 6px;
   border: 1px solid;
   border-radius: 1px;
 }
 
-.waterfall-marker-name {
-  font-size: 95%;
-  padding-bottom: 1px !important;
-}
-
-.waterfall-marker-bar {
-  height: 9px;
+.timeline-marker-bar {
+  margin-top: 4px;
+  margin-bottom: 4px;
   border: 1px solid;
   border-radius: 1px;
   transform-origin: left center;
 }
--- a/browser/themes/shared/devtools/widgets.inc.css
+++ b/browser/themes/shared/devtools/widgets.inc.css
@@ -933,31 +933,36 @@
 }
 
 .graph-widget-canvas[input=dragging-selection-contents] {
   cursor: grabbing;
 }
 
 /* Line graph widget */
 
+.line-graph-widget-canvas {
+  background: #0088cc;
+}
+
 .line-graph-widget-gutter {
   position: absolute;
   background: rgba(255,255,255,0.75);
   width: 10px;
   height: 100%;
   top: 0;
   left: 0;
   border-right: 1px solid rgba(255,255,255,0.25);
   pointer-events: none;
 }
 
 .line-graph-widget-gutter-line {
   position: absolute;
   width: 100%;
   border-top: 1px solid;
+  transform: translateY(-1px);
 }
 
 .line-graph-widget-gutter-line[type=maximum] {
   border-color: #2cbb0f;
 }
 
 .line-graph-widget-gutter-line[type=minimum] {
   border-color: #ed2655;
@@ -965,66 +970,55 @@
 
 .line-graph-widget-gutter-line[type=average] {
   border-color: #d97e00;
 }
 
 .line-graph-widget-tooltip {
   position: absolute;
   background: rgba(255,255,255,0.75);
+  box-shadow: 0 2px 1px rgba(0,0,0,0.1);
   border-radius: 2px;
   line-height: 15px;
   -moz-padding-start: 6px;
   -moz-padding-end: 6px;
   transform: translateY(-50%);
   font-size: 80%;
   z-index: 1;
   pointer-events: none;
 }
 
-.line-graph-widget-tooltip[with-arrows=true]::before {
+.line-graph-widget-tooltip::before {
   content: "";
   position: absolute;
   border-top: 3px solid transparent;
   border-bottom: 3px solid transparent;
   top: calc(50% - 3px);
 }
 
-.line-graph-widget-tooltip[arrow=start][with-arrows=true]::before {
+.line-graph-widget-tooltip[arrow=start]::before {
   -moz-border-end: 3px solid rgba(255,255,255,0.75);
   left: -3px;
 }
 
-.line-graph-widget-tooltip[arrow=end][with-arrows=true]::before {
+.line-graph-widget-tooltip[arrow=end]::before {
   -moz-border-start: 3px solid rgba(255,255,255,0.75);
   right: -3px;
 }
 
 .line-graph-widget-tooltip[type=maximum] {
-  left: -1px;
+  left: calc(10px + 6px);
 }
 
 .line-graph-widget-tooltip[type=minimum] {
-  left: -1px;
+  left: calc(10px + 6px);
 }
 
 .line-graph-widget-tooltip[type=average] {
-  right: -1px;
-}
-
-.line-graph-widget-tooltip[type=maximum][with-arrows=true] {
-  left: 14px;
-}
-
-.line-graph-widget-tooltip[type=minimum][with-arrows=true] {
-  left: 14px;
-}
-
-.line-graph-widget-tooltip[type=average][with-arrows=true] {
-  right: 4px;
+  right: 6px;
 }
 
 .line-graph-widget-tooltip > [text=info] {
   color: #18191a;
 }
 
 .line-graph-widget-tooltip > [text=value] {
   -moz-margin-start: 3px;