From 20fd7c01af27f02bc4336a40bccf192406211625 Mon Sep 17 00:00:00 2001 From: Jakub Jurovych Date: Tue, 26 Aug 2014 18:25:00 +0200 Subject: [PATCH 01/60] Bug 1052220 - Show traces' hit counts. r=fitzgen --- .../devtools/debugger/debugger-controller.js | 94 ++++++++++- browser/devtools/debugger/debugger-view.js | 8 +- browser/devtools/debugger/test/browser.ini | 4 + .../test/browser_dbg_hit-counts-01.js | 65 ++++++++ .../test/browser_dbg_hit-counts-02.js | 70 ++++++++ .../debugger/test/code_same-line-functions.js | 1 + .../test/doc_same-line-functions.html | 15 ++ browser/devtools/debugger/test/head.js | 11 ++ .../sourceeditor/codemirror/mozilla.css | 15 ++ browser/devtools/sourceeditor/debugger.js | 1 + browser/devtools/sourceeditor/editor.js | 26 +++ toolkit/devtools/server/actors/common.js | 24 +++ toolkit/devtools/server/actors/script.js | 27 +-- toolkit/devtools/server/actors/tracer.js | 44 +++-- .../server/tests/unit/test_trace_actor-05.js | 7 +- .../server/tests/unit/test_trace_actor-11.js | 124 ++++++++++++++ .../server/tests/unit/test_trace_actor-12.js | 156 ++++++++++++++++++ .../devtools/server/tests/unit/xpcshell.ini | 2 + 18 files changed, 647 insertions(+), 47 deletions(-) create mode 100644 browser/devtools/debugger/test/browser_dbg_hit-counts-01.js create mode 100644 browser/devtools/debugger/test/browser_dbg_hit-counts-02.js create mode 100644 browser/devtools/debugger/test/code_same-line-functions.js create mode 100644 browser/devtools/debugger/test/doc_same-line-functions.html create mode 100644 toolkit/devtools/server/tests/unit/test_trace_actor-11.js create mode 100644 toolkit/devtools/server/tests/unit/test_trace_actor-12.js diff --git a/browser/devtools/debugger/debugger-controller.js b/browser/devtools/debugger/debugger-controller.js index ae708d826578..d45d9a5d0783 100644 --- a/browser/devtools/debugger/debugger-controller.js +++ b/browser/devtools/debugger/debugger-controller.js @@ -1171,6 +1171,7 @@ SourceScripts.prototype = { // both in the editor and the breakpoints pane. DebuggerController.Breakpoints.updatePaneBreakpoints(); DebuggerController.Breakpoints.updateEditorBreakpoints(); + DebuggerController.HitCounts.updateEditorHitCounts(); // Make sure the events listeners are up to date. if (DebuggerView.instrumentsPaneTab == "events-tab") { @@ -1223,6 +1224,7 @@ SourceScripts.prototype = { // both in the editor and the breakpoints pane. DebuggerController.Breakpoints.updatePaneBreakpoints(); DebuggerController.Breakpoints.updateEditorBreakpoints(); + DebuggerController.HitCounts.updateEditorHitCounts(); // Signal that sources have been added. window.emit(EVENTS.SOURCES_ADDED); @@ -1488,6 +1490,7 @@ Tracer.prototype = { let fields = [ "name", "location", + "hitCount", "parameterNames", "depth", "arguments", @@ -1521,6 +1524,7 @@ Tracer.prototype = { } this._trace = null; + DebuggerController.HitCounts.clear(); aCallback(aResponse); }); }, @@ -1529,6 +1533,15 @@ Tracer.prototype = { const tracesLength = traces.length; let tracesToShow; + // Update hit counts. + for (let t of traces) { + if (t.type == "enteredFrame") { + DebuggerController.HitCounts.set(t.location, t.hitCount); + } + } + DebuggerController.HitCounts.updateEditorHitCounts(); + + // Limit number of traces to be shown in the log. if (tracesLength > TracerView.MAX_TRACES) { tracesToShow = traces.slice(tracesLength - TracerView.MAX_TRACES, tracesLength); this._stack.splice(0, this._stack.length); @@ -1537,6 +1550,7 @@ Tracer.prototype = { tracesToShow = traces; } + // Show traces in the log. for (let t of tracesToShow) { if (t.type == "enteredFrame") { this._onCall(t); @@ -1544,7 +1558,6 @@ Tracer.prototype = { this._onReturn(t); } } - DebuggerView.Tracer.commit(); }, @@ -2224,6 +2237,84 @@ Object.defineProperty(Breakpoints.prototype, "_addedOrDisabled", { } }); +/** + * Handles Tracer's hit counts. + */ +function HitCounts() { + /** + * Storage of hit counts for every location + * hitCount = _locations[url][line][column] + */ + this._hitCounts = Object.create(null); +} + +HitCounts.prototype = { + set: function({url, line, column}, aHitCount) { + if (!this._hitCounts[url]) { + this._hitCounts[url] = Object.create(null); + } + if (!this._hitCounts[url][line]) { + this._hitCounts[url][line] = Object.create(null); + } + this._hitCounts[url][line][column] = aHitCount; + }, + + /** + * Update all the hit counts in the editor view. This is invoked when the + * selected script is changed, or when new sources are received via the + * _onNewSource and _onSourcesAdded event listeners. + */ + updateEditorHitCounts: function() { + // First, remove all hit counters. + DebuggerView.editor.removeAllMarkers("hit-counts"); + + // Then, add new hit counts, just for the current source. + for (let url in this._hitCounts) { + for (let line in this._hitCounts[url]) { + for (let column in this._hitCounts[url][line]) { + this._updateEditorHitCount({url, line, column}); + } + } + } + }, + + /** + * Update a hit counter on a certain line. + */ + _updateEditorHitCount: function({url, line, column}) { + // Editor must be initialized. + if (!DebuggerView.editor) { + return; + } + + // No need to do anything if the counter's source is not being shown in the + // editor. + if (DebuggerView.Sources.selectedValue != url) { + return; + } + + // There might be more counters on the same line. We need to combine them + // into one. + let content = Object.keys(this._hitCounts[url][line]) + .sort() // Sort by key (column). + .map(a => this._hitCounts[url][line][a]) // Extract values. + .map(a => a + "\u00D7") // Format hit count (e.g. 146×). + .join("|"); + + // CodeMirror's lines are indexed from 0, while traces start from 1 + DebuggerView.editor.addContentMarker(line - 1, "hit-counts", "hit-count", + content); + }, + + /** + * Remove all hit couters and clear the storage + */ + clear: function() { + DebuggerView.editor.removeAllMarkers("hit-counts"); + this._hitCounts = Object.create(null); + } +} + /** * Localization convenience methods. */ @@ -2265,6 +2356,7 @@ DebuggerController.SourceScripts = new SourceScripts(); DebuggerController.Breakpoints = new Breakpoints(); DebuggerController.Breakpoints.DOM = new EventListeners(); DebuggerController.Tracer = new Tracer(); +DebuggerController.HitCounts = new HitCounts(); /** * Export some properties to the global scope for easier access. diff --git a/browser/devtools/debugger/debugger-view.js b/browser/devtools/debugger/debugger-view.js index f01bb3ed793b..fe6d3a133ec7 100644 --- a/browser/devtools/debugger/debugger-view.js +++ b/browser/devtools/debugger/debugger-view.js @@ -221,12 +221,17 @@ let DebuggerView = { extraKeys[shortcut] = () => DebuggerView.Filtering[func](); } + let gutters = ["breakpoints"]; + if (Services.prefs.getBoolPref("devtools.debugger.tracer")) { + gutters.unshift("hit-counts"); + } + this.editor = new Editor({ mode: Editor.modes.text, readOnly: true, lineNumbers: true, showAnnotationRuler: true, - gutters: [ "breakpoints" ], + gutters: gutters, extraKeys: extraKeys, contextMenu: "sourceEditorContextMenu" }); @@ -410,6 +415,7 @@ let DebuggerView = { // Synchronize any other components with the currently displayed source. DebuggerView.Sources.selectedValue = aSource.url; DebuggerController.Breakpoints.updateEditorBreakpoints(); + DebuggerController.HitCounts.updateEditorHitCounts(); histogram.add(Date.now() - startTime); diff --git a/browser/devtools/debugger/test/browser.ini b/browser/devtools/debugger/test/browser.ini index fb4d772072f2..91784710f90a 100644 --- a/browser/devtools/debugger/test/browser.ini +++ b/browser/devtools/debugger/test/browser.ini @@ -23,6 +23,7 @@ support-files = code_math.map code_math.min.js code_math_bogus_map.js + code_same-line-functions.js code_script-switching-01.js code_script-switching-02.js code_test-editor-mode @@ -74,6 +75,7 @@ support-files = doc_pretty-print-on-paused.html doc_random-javascript.html doc_recursion-stack.html + doc_same-line-functions.html doc_scope-variable.html doc_scope-variable-2.html doc_scope-variable-3.html @@ -161,6 +163,8 @@ skip-if = true # Bug 933950 (leaky test) [browser_dbg_function-display-name.js] [browser_dbg_global-method-override.js] [browser_dbg_globalactor.js] +[browser_dbg_hit-counts-01.js] +[browser_dbg_hit-counts-02.js] [browser_dbg_host-layout.js] [browser_dbg_iframes.js] [browser_dbg_instruments-pane-collapse.js] diff --git a/browser/devtools/debugger/test/browser_dbg_hit-counts-01.js b/browser/devtools/debugger/test/browser_dbg_hit-counts-01.js new file mode 100644 index 000000000000..5701e86c8bc9 --- /dev/null +++ b/browser/devtools/debugger/test/browser_dbg_hit-counts-01.js @@ -0,0 +1,65 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Evaluating two functions on the same line and checking for correct hit count + * for both of them in CodeMirror's gutter. + */ + +const TAB_URL = EXAMPLE_URL + "doc_same-line-functions.html"; +const CODE_URL = "code_same-line-functions.js"; + +let gTab, gDebuggee, gPanel, gDebugger; +let gEditor; + +function test() { + Task.async(function* () { + yield pushPrefs(["devtools.debugger.tracer", true]); + + initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + gTab = aTab; + gDebuggee = aDebuggee; + gPanel = aPanel; + gDebugger = gPanel.panelWin; + gEditor = gDebugger.DebuggerView.editor; + + Task.async(function* () { + yield waitForSourceShown(gPanel, CODE_URL); + yield startTracing(gPanel); + + clickButton(); + + yield waitForClientEvents(aPanel, "traces"); + + testHitCounts(); + + yield stopTracing(gPanel); + yield popPrefs(); + yield closeDebuggerAndFinish(gPanel); + })(); + }); + })().catch(e => { + ok(false, "Got an error: " + e.message + "\n" + e.stack); + }); +} + +function clickButton() { + EventUtils.sendMouseEvent({ type: "click" }, + gDebuggee.document.querySelector("button"), + gDebuggee); +} + +function testHitCounts() { + let marker = gEditor.getMarker(0, 'hit-counts'); + + is(marker.innerHTML, "1\u00D7|1\u00D7", + "Both functions should be hit only once."); +} + +registerCleanupFunction(function() { + gTab = null; + gDebuggee = null; + gPanel = null; + gDebugger = null; + gEditor = null; +}); \ No newline at end of file diff --git a/browser/devtools/debugger/test/browser_dbg_hit-counts-02.js b/browser/devtools/debugger/test/browser_dbg_hit-counts-02.js new file mode 100644 index 000000000000..00722dca99e0 --- /dev/null +++ b/browser/devtools/debugger/test/browser_dbg_hit-counts-02.js @@ -0,0 +1,70 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * When tracing is stopped all hit counters should be cleared. + */ + +const TAB_URL = EXAMPLE_URL + "doc_same-line-functions.html"; +const CODE_URL = "code_same-line-functions.js"; + +let gTab, gDebuggee, gPanel, gDebugger; +let gEditor; + +function test() { + Task.async(function* () { + yield pushPrefs(["devtools.debugger.tracer", true]); + + initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + gTab = aTab; + gDebuggee = aDebuggee; + gPanel = aPanel; + gDebugger = gPanel.panelWin; + gEditor = gDebugger.DebuggerView.editor; + + Task.async(function* () { + yield waitForSourceShown(gPanel, CODE_URL); + yield startTracing(gPanel); + + clickButton(); + + yield waitForClientEvents(aPanel, "traces"); + + testHitCountsBeforeStopping(); + + yield stopTracing(gPanel); + + testHitCountsAfterStopping(); + + yield popPrefs(); + yield closeDebuggerAndFinish(gPanel); + })(); + }); + })().catch(e => { + ok(false, "Got an error: " + e.message + "\n" + e.stack); + }); +} + +function clickButton() { + EventUtils.sendMouseEvent({ type: "click" }, + gDebuggee.document.querySelector("button"), + gDebuggee); +} + +function testHitCountsBeforeStopping() { + let marker = gEditor.getMarker(0, 'hit-counts'); + ok(marker, "A counter should exists."); +} + +function testHitCountsAfterStopping() { + let marker = gEditor.getMarker(0, 'hit-counts'); + is(marker, undefined, "A counter should be cleared."); +} + +registerCleanupFunction(function() { + gTab = null; + gDebuggee = null; + gPanel = null; + gDebugger = null; + gEditor = null; +}); \ No newline at end of file diff --git a/browser/devtools/debugger/test/code_same-line-functions.js b/browser/devtools/debugger/test/code_same-line-functions.js new file mode 100644 index 000000000000..58643f59d463 --- /dev/null +++ b/browser/devtools/debugger/test/code_same-line-functions.js @@ -0,0 +1 @@ +function first() { var a = "first"; second(); function second() { var a = "second"; } } \ No newline at end of file diff --git a/browser/devtools/debugger/test/doc_same-line-functions.html b/browser/devtools/debugger/test/doc_same-line-functions.html new file mode 100644 index 000000000000..dbdf2644d330 --- /dev/null +++ b/browser/devtools/debugger/test/doc_same-line-functions.html @@ -0,0 +1,15 @@ + + + + + + + Debugger Tracer test page + + + + + + + diff --git a/browser/devtools/debugger/test/head.js b/browser/devtools/debugger/test/head.js index dfc21bc0334a..925865d7e749 100644 --- a/browser/devtools/debugger/test/head.js +++ b/browser/devtools/debugger/test/head.js @@ -926,3 +926,14 @@ function doInterrupt(aPanel) { return rdpInvoke(threadClient, threadClient.interrupt); } +function pushPrefs(...aPrefs) { + let deferred = promise.defer(); + SpecialPowers.pushPrefEnv({"set": aPrefs}, deferred.resolve); + return deferred.promise; +} + +function popPrefs() { + let deferred = promise.defer(); + SpecialPowers.popPrefEnv(deferred.resolve); + return deferred.promise; +} \ No newline at end of file diff --git a/browser/devtools/sourceeditor/codemirror/mozilla.css b/browser/devtools/sourceeditor/codemirror/mozilla.css index 31ae8e55d445..bd09bb23f421 100644 --- a/browser/devtools/sourceeditor/codemirror/mozilla.css +++ b/browser/devtools/sourceeditor/codemirror/mozilla.css @@ -7,6 +7,10 @@ width: 16px; } +.hit-counts { + width: 6px; +} + .error, .breakpoint, .debugLocation, .breakpoint-debugLocation { display: inline-block; margin-left: 5px; @@ -17,6 +21,17 @@ background-size: contain; } +.hit-count { + display: inline-block; + height: 12px; + border: solid rgba(0,0,0,0.2); + border-width: 1px 1px 1px 0; + border-radius: 0 3px 3px 0; + padding: 0 3px; + font-size: 10px; + pointer-events: none; +} + .error { background-image: url("chrome://browser/skin/devtools/editor-error.png"); opacity: 0.75; diff --git a/browser/devtools/sourceeditor/debugger.js b/browser/devtools/sourceeditor/debugger.js index 607e591e3240..35919fed7451 100644 --- a/browser/devtools/sourceeditor/debugger.js +++ b/browser/devtools/sourceeditor/debugger.js @@ -115,6 +115,7 @@ function hasBreakpoint(ctx, line) { let markers = cm.lineInfo(line).gutterMarkers; return markers != null && + markers.breakpoints && markers.breakpoints.classList.contains("breakpoint"); } diff --git a/browser/devtools/sourceeditor/editor.js b/browser/devtools/sourceeditor/editor.js index ddf7f31a0f1d..23225b280995 100644 --- a/browser/devtools/sourceeditor/editor.js +++ b/browser/devtools/sourceeditor/editor.js @@ -618,6 +618,32 @@ Editor.prototype = { cm.lineInfo(line).gutterMarkers[gutterName].classList.remove(markerClass); }, + /** + * Adds a marker with a specified class and an HTML content to a line's + * gutter. If another marker exists on that line, it is overwritten by a new + * marker. + */ + addContentMarker: function (line, gutterName, markerClass, content) { + let cm = editors.get(this); + let info = cm.lineInfo(line); + if (!info) + return; + + let marker = cm.getWrapperElement().ownerDocument.createElement("div"); + marker.className = markerClass; + marker.innerHTML = content; + cm.setGutterMarker(info.line, gutterName, marker); + }, + + /** + * The reverse of addContentMarker. Removes any line's markers in the + * specified gutter. + */ + removeContentMarker: function (line, gutterName) { + let cm = editors.get(this); + cm.setGutterMarker(info.line, gutterName, null); + }, + getMarker: function(line, gutterName) { let cm = editors.get(this); let info = cm.lineInfo(line); diff --git a/toolkit/devtools/server/actors/common.js b/toolkit/devtools/server/actors/common.js index 8d3362c02ff6..d8f60a2b2b1e 100644 --- a/toolkit/devtools/server/actors/common.js +++ b/toolkit/devtools/server/actors/common.js @@ -166,3 +166,27 @@ ActorPool.prototype = { exports.ActorPool = ActorPool; +// TODO bug 863089: use Debugger.Script.prototype.getOffsetColumn when it is +// implemented. +exports.getOffsetColumn = function getOffsetColumn(aOffset, aScript) { + let bestOffsetMapping = null; + for (let offsetMapping of aScript.getAllColumnOffsets()) { + if (!bestOffsetMapping || + (offsetMapping.offset <= aOffset && + offsetMapping.offset > bestOffsetMapping.offset)) { + bestOffsetMapping = offsetMapping; + } + } + + if (!bestOffsetMapping) { + // XXX: Try not to completely break the experience of using the debugger for + // the user by assuming column 0. Simultaneously, report the error so that + // there is a paper trail if the assumption is bad and the debugging + // experience becomes wonky. + reportError(new Error("Could not find a column for offset " + aOffset + + " in the script " + aScript)); + return 0; + } + + return bestOffsetMapping.columnNumber; +} diff --git a/toolkit/devtools/server/actors/script.js b/toolkit/devtools/server/actors/script.js index acce9a78dfcf..58f79b3b6c8d 100644 --- a/toolkit/devtools/server/actors/script.js +++ b/toolkit/devtools/server/actors/script.js @@ -8,7 +8,7 @@ const Services = require("Services"); const { Cc, Ci, Cu, components, ChromeWorker } = require("chrome"); -const { ActorPool } = require("devtools/server/actors/common"); +const { ActorPool, getOffsetColumn } = require("devtools/server/actors/common"); const { DebuggerServer } = require("devtools/server/main"); const DevToolsUtils = require("devtools/toolkit/DevToolsUtils"); const { dbg_assert, dumpn, update } = DevToolsUtils; @@ -5226,31 +5226,6 @@ exports.ThreadSources = ThreadSources; // Utility functions. -// TODO bug 863089: use Debugger.Script.prototype.getOffsetColumn when it is -// implemented. -function getOffsetColumn(aOffset, aScript) { - let bestOffsetMapping = null; - for (let offsetMapping of aScript.getAllColumnOffsets()) { - if (!bestOffsetMapping || - (offsetMapping.offset <= aOffset && - offsetMapping.offset > bestOffsetMapping.offset)) { - bestOffsetMapping = offsetMapping; - } - } - - if (!bestOffsetMapping) { - // XXX: Try not to completely break the experience of using the debugger for - // the user by assuming column 0. Simultaneously, report the error so that - // there is a paper trail if the assumption is bad and the debugging - // experience becomes wonky. - reportError(new Error("Could not find a column for offset " + aOffset - + " in the script " + aScript)); - return 0; - } - - return bestOffsetMapping.columnNumber; -} - /** * Return the non-source-mapped location of the given Debugger.Frame. If the * frame does not have a script, the location's properties are all null. diff --git a/toolkit/devtools/server/actors/tracer.js b/toolkit/devtools/server/actors/tracer.js index bc6f6c1cf9cf..c11b75a206b7 100644 --- a/toolkit/devtools/server/actors/tracer.js +++ b/toolkit/devtools/server/actors/tracer.js @@ -8,6 +8,7 @@ const { Cu } = require("chrome"); const { DebuggerServer } = require("devtools/server/main"); const { DevToolsUtils } = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {}); const Debugger = require("Debugger"); +const { getOffsetColumn } = require("devtools/server/actors/common"); // TODO bug 943125: remove this polyfill and use Debugger.Frame.prototype.depth // once it is implemented. @@ -60,6 +61,7 @@ const TRACE_TYPES = new Set([ "yield", "name", "location", + "hitCount", "callsite", "parameterNames", "arguments", @@ -81,6 +83,7 @@ function TracerActor(aConn, aParent) this._sequence = 0; this._bufferSendTimer = null; this._buffer = []; + this._hitCounts = new WeakMap(); // Keep track of how many different trace requests have requested what kind of // tracing info. This way we can minimize the amount of data we are collecting @@ -236,6 +239,11 @@ TracerActor.prototype = { this._requestsForTraceType[traceType]--; } + // Clear hit counts if no trace is requesting them. + if (!this._requestsForTraceType.hitCount) { + this._hitCounts.clear(); + } + if (this.idle) { this.dbg.enabled = false; } @@ -272,16 +280,26 @@ TracerActor.prototype = { : "(" + aFrame.type + ")"; } - if (this._requestsForTraceType.location && aFrame.script) { - // We should return the location of the start of the script, but - // Debugger.Script does not provide complete start locations (bug - // 901138). Instead, return the current offset (the location of the first - // statement in the function). - packet.location = { - url: aFrame.script.url, - line: aFrame.script.startLine, - column: getOffsetColumn(aFrame.offset, aFrame.script) - }; + if (aFrame.script) { + if (this._requestsForTraceType.hitCount) { + // Increment hit count. + let previousHitCount = this._hitCounts.get(aFrame.script) || 0; + this._hitCounts.set(aFrame.script, previousHitCount + 1); + + packet.hitCount = this._hitCounts.get(aFrame.script); + } + + if (this._requestsForTraceType.location) { + // We should return the location of the start of the script, but + // Debugger.Script does not provide complete start locations (bug + // 901138). Instead, return the current offset (the location of the first + // statement in the function). + packet.location = { + url: aFrame.script.url, + line: aFrame.script.startLine, + column: getOffsetColumn(aFrame.offset, aFrame.script) + }; + } } if (this._parent.threadActor && aFrame.script) { @@ -497,12 +515,6 @@ MapStack.prototype = { } }; -// TODO bug 863089: use Debugger.Script.prototype.getOffsetColumn when -// it is implemented. -function getOffsetColumn(aOffset, aScript) { - return 0; -} - // Serialization helper functions. Largely copied from script.js and modified // for use in serialization rather than object actor requests. diff --git a/toolkit/devtools/server/tests/unit/test_trace_actor-05.js b/toolkit/devtools/server/tests/unit/test_trace_actor-05.js index a46235b51a4c..9ab3f54f7168 100644 --- a/toolkit/devtools/server/tests/unit/test_trace_actor-05.js +++ b/toolkit/devtools/server/tests/unit/test_trace_actor-05.js @@ -88,9 +88,10 @@ function test_enter_exit_frame() do_check_eq(traces[1].name, "foo"); // XXX: foo's definition is at tracerlocations.js:3:0, but Debugger.Script - // does not provide complete definition locations (bug 901138). |column| - // will always be 0 until we can get bug 863089 fixed. - check_location(traces[1].location, { url: url, line: 3, column: 0 }); + // does not provide complete definition locations (bug 901138). Therefore, + // we use the first statement in the function (tracerlocations.js:4:2) for + // a column approximation. + check_location(traces[1].location, { url: url, line: 3, column: 2 }); check_location(traces[1].callsite, { url: url, line: 8, column: 0 }); do_check_eq(typeof traces[1].parameterNames, "object"); diff --git a/toolkit/devtools/server/tests/unit/test_trace_actor-11.js b/toolkit/devtools/server/tests/unit/test_trace_actor-11.js new file mode 100644 index 000000000000..a36b981e7b39 --- /dev/null +++ b/toolkit/devtools/server/tests/unit/test_trace_actor-11.js @@ -0,0 +1,124 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test that hit counts from tracer count function frames correctly, even after + * restarting the trace. + */ + +var gDebuggee; +var gClient; +var gTraceClient; + +function run_test() +{ + initTestTracerServer(); + gDebuggee = addTestGlobal("test-tracer-actor"); + gClient = new DebuggerClient(DebuggerServer.connectPipe()); + gClient.connect(function() { + attachTestTab(gClient, "test-tracer-actor", function(aResponse, aTabClient) { + gClient.attachTracer(aResponse.traceActor, function(aResponse, aTraceClient) { + gTraceClient = aTraceClient; + test_hit_counts(); + }); + }); + }); + do_test_pending(); +} + +function test_hit_counts() +{ + start_trace() + .then(eval_code) + .then(listen_to_traces) + .then(stop_trace) + .then(start_trace) // Restart tracing. + .then(eval_code) + .then(listen_to_traces) + .then(stop_trace) + .then(function() { + finishClient(gClient); + }).then(null, error => { + do_check_true(false, "Should not get an error, got: " + DevToolsUtils.safeErrorString(error)); + }); +} + +function listen_to_traces() { + const tracesStopped = promise.defer(); + gClient.addListener("traces", (aEvent, { traces }) => { + for (let t of traces) { + check_trace(t); + } + tracesStopped.resolve(); + }); + return tracesStopped.promise; +} + +function start_trace() +{ + let deferred = promise.defer(); + gTraceClient.startTrace(["depth", "name", "location", "hitCount"], null, function() { deferred.resolve(); }); + return deferred.promise; +} + +function eval_code() +{ + gDebuggee.eval("(" + function iife() { + [1, 2, 3].forEach(function noop() { + for (let x of [1]) {} + }); + } + ")()"); +} + +function stop_trace() +{ + let deferred = promise.defer(); + gTraceClient.stopTrace(null, function() { deferred.resolve(); }); + return deferred.promise; +} + +function check_trace({ type, sequence, depth, name, location, hitCount }) +{ + if (location) { + do_check_true(location.url !== "self-hosted"); + } + + switch(sequence) { + case 0: + do_check_eq(name, "(eval)"); + do_check_eq(hitCount, 1); + break; + + case 1: + do_check_eq(name, "iife"); + do_check_eq(hitCount, 1); + break; + + case 2: + do_check_eq(hitCount, 1); + do_check_eq(name, "noop"); + break; + + case 4: + do_check_eq(hitCount, 2); + do_check_eq(name, "noop"); + break; + + case 6: + do_check_eq(hitCount, 3); + do_check_eq(name, "noop"); + break; + + case 3: + case 5: + case 7: + case 8: + case 9: + do_check_eq(type, "exitedFrame"); + break; + + default: + // Should have covered all sequences. + do_check_true(false); + } +} diff --git a/toolkit/devtools/server/tests/unit/test_trace_actor-12.js b/toolkit/devtools/server/tests/unit/test_trace_actor-12.js new file mode 100644 index 000000000000..3bcf22a7f0bc --- /dev/null +++ b/toolkit/devtools/server/tests/unit/test_trace_actor-12.js @@ -0,0 +1,156 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test that hit counts are correct even if we start tracing other things first + * and then start tracing hit counts. + */ + +var gDebuggee; +var gClient; +var gTraceClient; + +function run_test() +{ + initTestTracerServer(); + gDebuggee = addTestGlobal("test-tracer-actor"); + gClient = new DebuggerClient(DebuggerServer.connectPipe()); + gClient.connect(function() { + attachTestTab(gClient, "test-tracer-actor", function(aResponse, aTabClient) { + gClient.attachTracer(aResponse.traceActor, function(aResponse, aTraceClient) { + gTraceClient = aTraceClient; + test_hit_counts(); + }); + }); + }); + do_test_pending(); +} + +function test_hit_counts() +{ + const tracesStopped = promise.defer(); + gClient.addListener("traces", (aEvent, { traces }) => { + for (let t of traces) { + check_trace(t); + } + tracesStopped.resolve(); + }); + + start_trace_without_hit_counts() + .then(eval_code) + .then(start_trace_hit_counts) + .then(eval_code) + .then(() => tracesStopped.promise) + .then(stop_trace) + .then(function() { + finishClient(gClient); + }).then(null, error => { + do_check_true(false, + "Should not get an error, got: " + DevToolsUtils.safeErrorString(error)); + }); +} + +function listen_to_traces() { + const tracesStopped = promise.defer(); + gClient.addListener("traces", (aEvent, { traces }) => { + for (let t of traces) { + check_trace(t); + } + tracesStopped.resolve(); + }); + return tracesStopped; +} + +function start_trace_without_hit_counts() +{ + let deferred = promise.defer(); + gTraceClient.startTrace(["depth", "name", "location"], null, + function() { deferred.resolve(); }); + return deferred.promise; +} + +function start_trace_hit_counts() +{ + let deferred = promise.defer(); + gTraceClient.startTrace(["hitCount"], null, + function() { deferred.resolve(); }); + return deferred.promise; +} + +function eval_code() +{ + gDebuggee.eval("(" + function iife() { + [1, 2, 3].forEach(function noop() { + for (let x of [1]) {} + }); + } + ")()"); +} + +function stop_trace() +{ + let deferred = promise.defer(); + gTraceClient.stopTrace(null, function() { deferred.resolve(); }); + return deferred.promise; +} + +function check_trace({ type, sequence, depth, name, location, hitCount }) +{ + if (location) { + do_check_true(location.url !== "self-hosted"); + } + + switch(sequence) { + + // First evaluation (before tracing hit counts). + case 0: + case 1: + case 2: + case 4: + case 6: + do_check_eq(hitCount, undefined); + break; + + // Second evaluation (after tracing hit counts). + case 10: + do_check_eq(name, "(eval)"); + do_check_eq(hitCount, 1); + break; + + case 11: + do_check_eq(name, "iife"); + do_check_eq(hitCount, 1); + break; + + case 12: + do_check_eq(hitCount, 1); + do_check_eq(name, "noop"); + break; + + case 14: + do_check_eq(hitCount, 2); + do_check_eq(name, "noop"); + break; + + case 16: + do_check_eq(hitCount, 3); + do_check_eq(name, "noop"); + break; + + case 3: + case 5: + case 7: + case 8: + case 9: + case 13: + case 15: + case 17: + case 18: + case 19: + do_check_eq(type, "exitedFrame"); + break; + + default: + // Should have covered all sequences. + do_check_true(false); + } +} diff --git a/toolkit/devtools/server/tests/unit/xpcshell.ini b/toolkit/devtools/server/tests/unit/xpcshell.ini index b5d98195a890..efd1ffb278a6 100644 --- a/toolkit/devtools/server/tests/unit/xpcshell.ini +++ b/toolkit/devtools/server/tests/unit/xpcshell.ini @@ -197,6 +197,8 @@ reason = bug 820380 [test_trace_actor-08.js] [test_trace_actor-09.js] [test_trace_actor-10.js] +[test_trace_actor-11.js] +[test_trace_actor-12.js] [test_ignore_caught_exceptions.js] [test_requestTypes.js] reason = bug 937197 From b9fc69218b7d734be165166ccea4b7cfe58d2f19 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Tue, 26 Aug 2014 12:37:00 +0200 Subject: [PATCH 02/60] Bug 1053468 - When setting a breakpoint, only resume if we actually interrupted. r=past --- toolkit/devtools/client/dbg-client.jsm | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/toolkit/devtools/client/dbg-client.jsm b/toolkit/devtools/client/dbg-client.jsm index bca633ca4307..6812b4722549 100644 --- a/toolkit/devtools/client/dbg-client.jsm +++ b/toolkit/devtools/client/dbg-client.jsm @@ -1792,7 +1792,13 @@ ThreadClient.prototype = { aOnResponse(aResponse); return; } - doSetBreakpoint(this.resume.bind(this)); + + const { type, why } = aResponse; + const cleanUp = type == "paused" && why.type == "interrupted" + ? () => this.resume() + : noop; + + doSetBreakpoint(cleanUp); }); }, From 64064608885da3a9b9cdaa0a3c2b7dc4d2de1f3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Ko=C5=82odziejski?= Date: Tue, 26 Aug 2014 16:52:00 +0200 Subject: [PATCH 03/60] Bug 950546 - Make color analyzer deterministic by breaking ties via comparing original colors. r=MattN --- toolkit/components/places/ColorAnalyzer_worker.js | 4 ++-- .../places/tests/browser/browser_colorAnalyzer.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/toolkit/components/places/ColorAnalyzer_worker.js b/toolkit/components/places/ColorAnalyzer_worker.js index c1ab2a29f1b8..01fce06375f9 100644 --- a/toolkit/components/places/ColorAnalyzer_worker.js +++ b/toolkit/components/places/ColorAnalyzer_worker.js @@ -119,7 +119,7 @@ onmessage = function(event) { // only send back the most desirable colors mergedColors.sort(function(a, b) { - return b.desirability - a.desirability; + return b.desirability != a.desirability ? b.desirability - a.desirability : b.color - a.color; }); mergedColors = mergedColors.map(function(metadata) { return metadata.color; @@ -216,7 +216,7 @@ function mergeColors(colorFrequencies, numPixels, threshold) { } function descendingFreqSort(a, b) { - return b.freq - a.freq; + return b.freq != a.freq ? b.freq - a.freq : b.color - a.color; } /** diff --git a/toolkit/components/places/tests/browser/browser_colorAnalyzer.js b/toolkit/components/places/tests/browser/browser_colorAnalyzer.js index 88bc42515800..c5cbbaf5f88f 100644 --- a/toolkit/components/places/tests/browser/browser_colorAnalyzer.js +++ b/toolkit/components/places/tests/browser/browser_colorAnalyzer.js @@ -330,13 +330,13 @@ tests.push(function test_categoryDiscover() { }); tests.push(function test_localeGeneric() { - frcTest(filePrefix + "localeGeneric.png", 0x00A400, - "localeGeneric analysis returns orange"); + frcTest(filePrefix + "localeGeneric.png", 0x3EC23E, + "localeGeneric analysis returns green"); }); tests.push(function test_dictionaryGeneric() { - frcTest(filePrefix + "dictionaryGeneric-16.png", 0x502E1E, - "dictionaryGeneric-16 analysis returns blue"); + frcTest(filePrefix + "dictionaryGeneric-16.png", 0x854C30, + "dictionaryGeneric-16 analysis returns brown"); }); tests.push(function test_extensionGeneric() { From 2fe6154d4cc000950ddd8765b388d36fe5efadd1 Mon Sep 17 00:00:00 2001 From: Alex Bardas Date: Wed, 27 Aug 2014 19:04:00 +0200 Subject: [PATCH 04/60] Bug 1058039 - Make sure that .addon-control subitem elements from Plugin Add-on Manager are not hidden (otherwise the state menu selectbox will not inherit a good width). r=Unfocused --- .../browser/browser_plugin_enabled_state_locked.js | 4 ++++ toolkit/themes/linux/mozapps/extensions/extensions.css | 6 +++--- toolkit/themes/osx/mozapps/extensions/extensions.css | 10 +++++++--- .../themes/windows/mozapps/extensions/extensions.css | 6 +++--- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js b/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js index 2eb8434e31a8..b32d74336581 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js +++ b/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js @@ -57,10 +57,14 @@ function checkStateMenu(locked) { Assert.equal(Services.prefs.prefIsLocked(getTestPluginPref()), locked, "Preference lock state should be correct."); let menuList = gManagerWindow.document.getAnonymousElementByAttribute(gPluginElement, "anonid", "state-menulist"); + // State menu should always have a selected item which must be visible + let selectedMenuItem = menuList.querySelector(".addon-control[selected=\"true\"]"); is_element_visible(menuList, "State menu should be visible."); Assert.equal(menuList.disabled, locked, "State menu should" + (locked === true ? "" : " not") + " be disabled."); + + is_element_visible(selectedMenuItem, "State menu's selected item should be visible."); } function checkStateMenuDetail(locked) { diff --git a/toolkit/themes/linux/mozapps/extensions/extensions.css b/toolkit/themes/linux/mozapps/extensions/extensions.css index a1f344161672..cf5f6baf006c 100644 --- a/toolkit/themes/linux/mozapps/extensions/extensions.css +++ b/toolkit/themes/linux/mozapps/extensions/extensions.css @@ -880,12 +880,12 @@ setting[type="radio"] > radiogroup { /*** buttons ***/ -.addon-control[disabled="true"] { +.addon-control[disabled="true"]:not(.no-auto-hide) { display: none; } -.addon-control.no-auto-hide { - display: block; +.no-auto-hide .addon-control { + display: block !important; } .addon-control.enable { diff --git a/toolkit/themes/osx/mozapps/extensions/extensions.css b/toolkit/themes/osx/mozapps/extensions/extensions.css index 1d8fe5936b67..89b18303cca5 100644 --- a/toolkit/themes/osx/mozapps/extensions/extensions.css +++ b/toolkit/themes/osx/mozapps/extensions/extensions.css @@ -1104,12 +1104,16 @@ setting[type="radio"] > radiogroup { /*** buttons ***/ -.addon-control[disabled="true"] { +.addon-control[disabled="true"]:not(.no-auto-hide) { display: none; } -.addon-control.no-auto-hide { - display: block; +.no-auto-hide .addon-control { + display: block !important; +} + +.no-auto-hide > .menulist-dropmarker { + -moz-padding-start: 0px !important; } button.button-link { diff --git a/toolkit/themes/windows/mozapps/extensions/extensions.css b/toolkit/themes/windows/mozapps/extensions/extensions.css index 7dbaa055b794..d43df7966ca5 100644 --- a/toolkit/themes/windows/mozapps/extensions/extensions.css +++ b/toolkit/themes/windows/mozapps/extensions/extensions.css @@ -1120,12 +1120,12 @@ menulist { /* Fixes some styling inconsistencies */ /*** buttons ***/ -.addon-control[disabled="true"] { +.addon-control[disabled="true"]:not(.no-auto-hide) { display: none; } -.addon-control.no-auto-hide { - display: block; +.no-auto-hide .addon-control { + display: block !important; } button.button-link { From ff011f4a544cf14f4eb6902c87fcf04a69cb5ab5 Mon Sep 17 00:00:00 2001 From: Eric Edens Date: Wed, 27 Aug 2014 13:42:26 -0500 Subject: [PATCH 05/60] Bug 1046972 - Hide settings button when keyboard is active. r=margaret --- .../java/org/mozilla/search/MainActivity.java | 32 +++++++++++++++++-- .../org/mozilla/search/PreSearchFragment.java | 8 ----- .../res/layout/search_activity_main.xml | 11 +++++++ .../res/layout/search_fragment_pre_search.xml | 10 ------ 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/mobile/android/search/java/org/mozilla/search/MainActivity.java b/mobile/android/search/java/org/mozilla/search/MainActivity.java index 37fc8f10ad12..debd32e46eff 100644 --- a/mobile/android/search/java/org/mozilla/search/MainActivity.java +++ b/mobile/android/search/java/org/mozilla/search/MainActivity.java @@ -59,6 +59,8 @@ public class MainActivity extends FragmentActivity implements AcceptsSearchQuery private View preSearch; private View postSearch; + private View settingsButton; + private View suggestions; private SuggestionsFragment suggestionsFragment; @@ -119,6 +121,16 @@ public class MainActivity extends FragmentActivity implements AcceptsSearchQuery preSearch = findViewById(R.id.presearch); postSearch = findViewById(R.id.postsearch); + settingsButton = findViewById(R.id.settings_button); + + // Apply click handler to settings button. + settingsButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startActivity(new Intent(MainActivity.this, SearchPreferenceActivity.class)); + } + }); + suggestions = findViewById(R.id.suggestions); suggestionsFragment = (SuggestionsFragment) getSupportFragmentManager().findFragmentById(R.id.suggestions); @@ -155,6 +167,7 @@ public class MainActivity extends FragmentActivity implements AcceptsSearchQuery editText = null; preSearch = null; postSearch = null; + settingsButton = null; suggestionsFragment = null; suggestions = null; animationText = null; @@ -195,7 +208,7 @@ public class MainActivity extends FragmentActivity implements AcceptsSearchQuery @Override public void onSuggest(String query) { - editText.setText(query); + editText.setText(query); } @Override @@ -223,8 +236,8 @@ public class MainActivity extends FragmentActivity implements AcceptsSearchQuery /** * Animates search suggestion to search bar. This animation has 2 main parts: * - * 1) Vertically translate query text from suggestion card to search bar. - * 2) Expand suggestion card to fill the results view area. + * 1) Vertically translate query text from suggestion card to search bar. + * 2) Expand suggestion card to fill the results view area. * * @param query * @param suggestionAnimation @@ -296,6 +309,8 @@ public class MainActivity extends FragmentActivity implements AcceptsSearchQuery } this.editState = editState; + updateSettingsButtonVisibility(); + editText.setActive(editState == EditState.EDITING); suggestions.setVisibility(editState == EditState.EDITING ? View.VISIBLE : View.INVISIBLE); } @@ -306,10 +321,21 @@ public class MainActivity extends FragmentActivity implements AcceptsSearchQuery } this.searchState = searchState; + updateSettingsButtonVisibility(); + preSearch.setVisibility(searchState == SearchState.PRESEARCH ? View.VISIBLE : View.INVISIBLE); postSearch.setVisibility(searchState == SearchState.POSTSEARCH ? View.VISIBLE : View.INVISIBLE); } + private void updateSettingsButtonVisibility() { + // Show button on launch screen when keyboard is down. + if (searchState == SearchState.PRESEARCH && editState == EditState.WAITING) { + settingsButton.setVisibility(View.VISIBLE); + } else { + settingsButton.setVisibility(View.INVISIBLE); + } + } + @Override public void onBackPressed() { if (editState == EditState.EDITING) { diff --git a/mobile/android/search/java/org/mozilla/search/PreSearchFragment.java b/mobile/android/search/java/org/mozilla/search/PreSearchFragment.java index 546ce1612469..24a19e316157 100644 --- a/mobile/android/search/java/org/mozilla/search/PreSearchFragment.java +++ b/mobile/android/search/java/org/mozilla/search/PreSearchFragment.java @@ -5,7 +5,6 @@ package org.mozilla.search; import android.app.Activity; -import android.content.Intent; import android.database.Cursor; import android.graphics.Rect; import android.net.Uri; @@ -115,13 +114,6 @@ public class PreSearchFragment extends Fragment { } }); - // Apply click handler to settings button. - mainView.findViewById(R.id.settings_button).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - startActivity(new Intent(getActivity(), SearchPreferenceActivity.class)); - } - }); return mainView; } diff --git a/mobile/android/search/res/layout/search_activity_main.xml b/mobile/android/search/res/layout/search_activity_main.xml index 6572b1aa78e1..1e924d5836b9 100644 --- a/mobile/android/search/res/layout/search_activity_main.xml +++ b/mobile/android/search/res/layout/search_activity_main.xml @@ -42,6 +42,17 @@ android:layout_marginTop="@dimen/search_bar_height" android:layout_gravity="top"/> + + + - - From b4f9646fcd1539f52ca5687df3f0142bb53b555a Mon Sep 17 00:00:00 2001 From: Eric Edens Date: Wed, 27 Aug 2014 14:10:16 -0500 Subject: [PATCH 06/60] Bug 1057390: Clear focus when keyboard is dismissed. r=margaret --- .../search/ui/BackCaptureEditText.java | 36 +++++++++++++++++++ .../search/res/layout/clearable_edit_text.xml | 2 +- .../search/search_activity_sources.mozbuild | 1 + 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 mobile/android/search/java/org/mozilla/search/ui/BackCaptureEditText.java diff --git a/mobile/android/search/java/org/mozilla/search/ui/BackCaptureEditText.java b/mobile/android/search/java/org/mozilla/search/ui/BackCaptureEditText.java new file mode 100644 index 000000000000..727ad8105708 --- /dev/null +++ b/mobile/android/search/java/org/mozilla/search/ui/BackCaptureEditText.java @@ -0,0 +1,36 @@ +/* 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/. */ + +package org.mozilla.search.ui; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.KeyEvent; +import android.widget.EditText; + +/** + * An EditText subclass that loses focus when the keyboard + * is dismissed. + */ +public class BackCaptureEditText extends EditText { + public BackCaptureEditText(Context context) { + super(context); + } + + public BackCaptureEditText(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public BackCaptureEditText(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public boolean onKeyPreIme(int keyCode, KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { + clearFocus(); + } + return super.onKeyPreIme(keyCode, event); + } +} diff --git a/mobile/android/search/res/layout/clearable_edit_text.xml b/mobile/android/search/res/layout/clearable_edit_text.xml index abbc5e91dbd1..b0f817549436 100644 --- a/mobile/android/search/res/layout/clearable_edit_text.xml +++ b/mobile/android/search/res/layout/clearable_edit_text.xml @@ -4,7 +4,7 @@ - Date: Wed, 27 Aug 2014 13:15:37 -0700 Subject: [PATCH 07/60] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/8e9e9b06d936 Author: James Burke Desc: Merge pull request #23246 from karanluthra/1057798-clean-up-mozl10n-api-in-email BUG 1057798 Clean up mozL10n.{localize(), get()} use in Email app r=jrburke ======== https://hg.mozilla.org/integration/gaia-central/rev/784c003cd5f8 Author: Karan Luthra Desc: BUG 1057798 Clean up mozL10n localize() and get() use in Email app --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 61099395eee5..ca1a4cc55be5 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "d4afc0a7f72fd7793359b9575ea7c90cd54e2348", + "revision": "8e9e9b06d9367d4ab868d9522e7b9ac277960c07", "repo_path": "/integration/gaia-central" } From 896a2dbb870053c0e2b2b10d4c071c4c2e578ab0 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 13:21:31 -0700 Subject: [PATCH 08/60] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index ad2b79e819c3..c128c28aaaa9 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 2cb1ae7bc9d2..6827fbf3b96b 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 68c02c7ad203..5a3905c1ca3c 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 9c3a62ebd1cd..4734f5613fa7 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 2cb1ae7bc9d2..6827fbf3b96b 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 9a46797b6278..ba3829666116 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index e027a611e33f..dc09bad66940 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 729be0afff91..24ab84d79e13 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 1b4c63e8bce3..4c602f356612 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 27379571ba69..0549d1a156b5 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 512467b0de840b760bfb10b88ea825e6306cc784 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 13:30:31 -0700 Subject: [PATCH 09/60] Bumping gaia.json for 4 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/5337ba69bd24 Author: Aleh Zasypkin Desc: Merge pull request #23208 from azasypkin/bug-1035762-24h-format Bug 1035762 - [B2G][SMS] support 24 hour time format. r=schung ======== https://hg.mozilla.org/integration/gaia-central/rev/da36116b999d Author: Aleh Zasypkin Desc: Bug 1035762 - [B2G][SMS] support 24 hour time format. r=schung ======== https://hg.mozilla.org/integration/gaia-central/rev/f5bd849ba682 Author: Aleh Zasypkin Desc: Merge pull request #23267 from azasypkin/bug-1057996-thread-ui-tests Bug 1057996 - [Messages][Tests] ThreadUI unit tests are not run if full. r=schung ======== https://hg.mozilla.org/integration/gaia-central/rev/08c5d79c458b Author: Aleh Zasypkin Desc: Bug 1057996 - [Messages][Tests] ThreadUI unit tests are not run if full. r=schung --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index ca1a4cc55be5..39c93addb3e9 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "8e9e9b06d9367d4ab868d9522e7b9ac277960c07", + "revision": "5337ba69bd24d3e77065ccb499e9a34e2de40e1d", "repo_path": "/integration/gaia-central" } From a3066efd34ff2207c4450c1f3b1938e594ff3486 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 13:32:02 -0700 Subject: [PATCH 10/60] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index c128c28aaaa9..e10dc0109ec4 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 6827fbf3b96b..d834ac69c146 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 5a3905c1ca3c..b7e4add05046 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 4734f5613fa7..c6d7f4d6cfbd 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 6827fbf3b96b..d834ac69c146 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index ba3829666116..eb967f541d26 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index dc09bad66940..9bd9727e0f92 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 24ab84d79e13..86ffbb49251a 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 4c602f356612..d86be42f013a 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 0549d1a156b5..ddd26abdccba 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From cfdcd40096453a6defb64396fb33e5ed02f907fc Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 14:05:30 -0700 Subject: [PATCH 11/60] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/d580d431d821 Author: Kevin Grandon Desc: Merge pull request #23325 from benfrancis/1038726 Bug 1038726 - [User Story] Change Rocketbar input type to search ======== https://hg.mozilla.org/integration/gaia-central/rev/6dd20fe8484e Author: Ben Francis Desc: Bug 1038726 - [User Story] Change Rocketbar input type to search --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 39c93addb3e9..4d33d2b0f253 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "5337ba69bd24d3e77065ccb499e9a34e2de40e1d", + "revision": "d580d431d82137ec5a76aa485731a37c2b179a77", "repo_path": "/integration/gaia-central" } From 40209884e5424069be27198ab88776feed5bd9d6 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 14:07:02 -0700 Subject: [PATCH 12/60] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index e10dc0109ec4..8422e14c65c4 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index d834ac69c146..c1e52ce1be69 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index b7e4add05046..0066b4635955 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index c6d7f4d6cfbd..7272e5bcf236 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index d834ac69c146..c1e52ce1be69 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index eb967f541d26..a27839da9998 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 9bd9727e0f92..400942d36470 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 86ffbb49251a..4de3e930a345 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index d86be42f013a..2ed93d45299e 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index ddd26abdccba..d7f252bf259b 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 98332715780d795378fcc6174cf237286f204c38 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 15:25:28 -0700 Subject: [PATCH 13/60] Bumping gaia.json for 5 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/302272596232 Author: Kevin Grandon Desc: Revert "Bug 974809 - Using travis_fold for reading log easily" This reverts commit 3f94bb17884703e672d5f9eda4ad6a861dcc1a93. ======== https://hg.mozilla.org/integration/gaia-central/rev/28e1b95f42c7 Author: Kevin Grandon Desc: Revert "Revert "Bug 1059051 - Convert Keyboard-Symbols.woff to Keyboard-Symbols.ttf"" This reverts commit 7f44b868861c6ad33dc8b081c148365f6390a3eb. ======== https://hg.mozilla.org/integration/gaia-central/rev/0dede958ae13 Author: Kevin Grandon Desc: Revert "Bug 1059051 - Convert Keyboard-Symbols.woff to Keyboard-Symbols.ttf" This reverts commit 3b462c8f348c3ba01325eeb355078f665754ab7b. ======== https://hg.mozilla.org/integration/gaia-central/rev/32c97203ddbc Author: Michael Henretty Desc: Merge pull request #22396 from mnils/Bug-1047115 Bug 1047115 ======== https://hg.mozilla.org/integration/gaia-central/rev/b82c82d91916 Author: Markus Nilsson Desc: Bug 1047115 Display soft home key while the Utility Tray is open. --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 4d33d2b0f253..f21092d33dba 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "d580d431d82137ec5a76aa485731a37c2b179a77", + "revision": "302272596232723cccc9c7013c4bd0bf12be1f1d", "repo_path": "/integration/gaia-central" } From aef7201ab8d399520ff745b478df0addad941b2b Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 15:28:01 -0700 Subject: [PATCH 14/60] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 8422e14c65c4..750a1afe944c 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index c1e52ce1be69..3b34b1872664 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 0066b4635955..49ce8fddf448 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 7272e5bcf236..ec9460ebf052 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index c1e52ce1be69..3b34b1872664 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index a27839da9998..9391929812c3 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 400942d36470..c1b89437e79c 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 4de3e930a345..2f863974895e 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 2ed93d45299e..1175de5d5a7d 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index d7f252bf259b..128cf278a447 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From efd9fdf5d2f02643a20a899da36127a9c753cf46 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 15:30:29 -0700 Subject: [PATCH 15/60] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/ba59f4973827 Author: Kevin Grandon Desc: Merge pull request #23336 from KevinGrandon/bug_1052481_rocketbar_visual_refinements Bug 1052481 - [Search] Visual Refinements for Rocket Bar ======== https://hg.mozilla.org/integration/gaia-central/rev/c27ac0e89b35 Author: Kevin Grandon Desc: Bug 1052481 - [Search] Visual Refinements for Rocket Bar r=Cwiiis --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index f21092d33dba..1d105b8984f5 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "302272596232723cccc9c7013c4bd0bf12be1f1d", + "revision": "ba59f497382766979efb26cc17c76d1047b8ab73", "repo_path": "/integration/gaia-central" } From 480dfe1fac6de556e360bd900b41f8680bd0e597 Mon Sep 17 00:00:00 2001 From: Gabriel Luong Date: Wed, 27 Aug 2014 15:32:25 -0700 Subject: [PATCH 16/60] Bug 1059015 - Provide an option to the TableWidget to specify the first column to appear r=bgrins --- .../shared/test/browser_tableWidget_basic.js | 37 +++++++++++++++++-- .../devtools/shared/widgets/TableWidget.js | 20 +++++++++- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/browser/devtools/shared/test/browser_tableWidget_basic.js b/browser/devtools/shared/test/browser_tableWidget_basic.js index 4e5218a4fe1e..9d9840ec5d23 100644 --- a/browser/devtools/shared/test/browser_tableWidget_basic.js +++ b/browser/devtools/shared/test/browser_tableWidget_basic.js @@ -36,6 +36,7 @@ function test() { emptyText: "This is dummy empty text", highlightUpdated: true, removableColumns: true, + firstColumn: "col4" }); startTests(); }); @@ -126,12 +127,42 @@ function populateTable() { function testTreeItemInsertedCorrectly() { is(table.tbody.children.length, 4*2 /* double because splitters */, "4 columns exist"); - for (let i = 0; i < 4; i++) { - is(table.tbody.children[i*2].firstChild.children.length, 9 + 1 /* header */, + + // Test firstColumn option and check if the nodes are inserted correctly + is(table.tbody.children[0].firstChild.children.length, 9 + 1 /* header */, + "Correct rows in column 4"); + is(table.tbody.children[0].firstChild.firstChild.value, "Column 4", + "Correct column header value"); + + for (let i = 1; i < 4; i++) { + is(table.tbody.children[i * 2].firstChild.children.length, 9 + 1 /* header */, "Correct rows in column " + i); - is(table.tbody.children[i*2].firstChild.firstChild.value, "Column " + (i + 1), + is(table.tbody.children[i * 2].firstChild.firstChild.value, "Column " + i, "Correct column header value"); } + for (let i = 1; i < 10; i++) { + is(table.tbody.children[2].firstChild.children[i].value, "id" + i, + "Correct value in row " + i); + } + + // Remove firstColumn option and reset the table + table.clear(); + table.firstColumn = ""; + table.setColumns({ + col1: "Column 1", + col2: "Column 2", + col3: "Column 3", + col4: "Column 4" + }); + populateTable(); + + // Check if the nodes are inserted correctly without firstColumn option + for (let i = 0; i < 4; i++) { + is(table.tbody.children[i * 2].firstChild.children.length, 9 + 1 /* header */, + "Correct rows in column " + i); + is(table.tbody.children[i * 2].firstChild.firstChild.value, "Column " + (i + 1), + "Correct column header value"); + } for (let i = 1; i < 10; i++) { is(table.tbody.firstChild.firstChild.children[i].value, "id" + i, "Correct value in row " + i); diff --git a/browser/devtools/shared/widgets/TableWidget.js b/browser/devtools/shared/widgets/TableWidget.js index 8363ce68ed79..fc99401d1a0a 100644 --- a/browser/devtools/shared/widgets/TableWidget.js +++ b/browser/devtools/shared/widgets/TableWidget.js @@ -40,6 +40,7 @@ const MAX_VISIBLE_STRING_SIZE = 100; * - highlightUpdated: true to highlight the changed/added row. * - removableColumns: Whether columns are removeable. If set to true, * the context menu in the headers will not appear. + * - firstColumn: key of the first column that should appear. */ function TableWidget(node, options={}) { EventEmitter.decorate(this); @@ -48,10 +49,11 @@ function TableWidget(node, options={}) { this.window = this.document.defaultView; this._parent = node; - let {initialColumns, emptyText, uniqueId, highlightUpdated, removableColumns} = - options; + let {initialColumns, emptyText, uniqueId, highlightUpdated, removableColumns, + firstColumn} = options; this.emptyText = emptyText || ""; this.uniqueId = uniqueId || "name"; + this.firstColumn = firstColumn || ""; this.highlightUpdated = highlightUpdated || false; this.removableColumns = removableColumns || false; @@ -237,10 +239,24 @@ TableWidget.prototype = { sortOn = null; } + if (!(this.firstColumn in columns)) { + this.firstColumn = null; + } + + if (this.firstColumn) { + this.columns.set(this.firstColumn, + new Column(this, this.firstColumn, columns[this.firstColumn])); + } + for (let id in columns) { if (!sortOn) { sortOn = id; } + + if (this.firstColumn && id == this.firstColumn) { + continue; + } + this.columns.set(id, new Column(this, id, columns[id])); if (hiddenColumns.indexOf(id) > -1) { this.columns.get(id).toggleColumn(); From 560bba04fc69724f32dbf4a898d9963f0ad3339c Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Wed, 27 Aug 2014 15:32:32 -0700 Subject: [PATCH 17/60] Bug 899753 - Part 0: Add the table method to Console.{h,cpp,webidl} r=bz --- dom/base/Console.cpp | 1 + dom/base/Console.h | 4 ++++ dom/base/test/test_console.xul | 1 + dom/webidl/Console.webidl | 1 + 4 files changed, 7 insertions(+) diff --git a/dom/base/Console.cpp b/dom/base/Console.cpp index e1dc28f5ae4d..06d3ec09abf4 100644 --- a/dom/base/Console.cpp +++ b/dom/base/Console.cpp @@ -624,6 +624,7 @@ METHOD(Warn, "warn") METHOD(Error, "error") METHOD(Exception, "exception") METHOD(Debug, "debug") +METHOD(Table, "table") void Console::Trace(JSContext* aCx) diff --git a/dom/base/Console.h b/dom/base/Console.h index 6f4de097f2dc..99e051203060 100644 --- a/dom/base/Console.h +++ b/dom/base/Console.h @@ -66,6 +66,9 @@ public: void Debug(JSContext* aCx, const Sequence& aData); + void + Table(JSContext* aCx, const Sequence& aData); + void Trace(JSContext* aCx); @@ -111,6 +114,7 @@ private: MethodError, MethodException, MethodDebug, + MethodTable, MethodTrace, MethodDir, MethodGroup, diff --git a/dom/base/test/test_console.xul b/dom/base/test/test_console.xul index 4dde1fe3db8f..a2896eb3cfb0 100644 --- a/dom/base/test/test_console.xul +++ b/dom/base/test/test_console.xul @@ -15,6 +15,7 @@ ok("console" in window, "Console exists"); window.console.log(42); + ok("table" in console, "Console has the 'table' method."); window.console = 42; is(window.console, 42, "Console is replacable"); diff --git a/dom/webidl/Console.webidl b/dom/webidl/Console.webidl index 35587689cadc..a4f7af32592d 100644 --- a/dom/webidl/Console.webidl +++ b/dom/webidl/Console.webidl @@ -13,6 +13,7 @@ interface Console { void error(any... data); void _exception(any... data); void debug(any... data); + void table(any... data); void trace(); void dir(any... data); void group(any... data); From 8f203df6af7cf7c0b5557864b32ae3a2ddd71b42 Mon Sep 17 00:00:00 2001 From: Gabriel Luong Date: Wed, 27 Aug 2014 15:32:37 -0700 Subject: [PATCH 18/60] Bug 899753 - Part 1: Add the Table console output r=msucan, past --- browser/devtools/webconsole/console-output.js | 407 +++++++++++++++++- browser/devtools/webconsole/webconsole.js | 6 + .../browser/devtools/webconsole.properties | 7 + .../themes/shared/devtools/webconsole.inc.css | 15 + 4 files changed, 434 insertions(+), 1 deletion(-) diff --git a/browser/devtools/webconsole/console-output.js b/browser/devtools/webconsole/console-output.js index 66a14150cfd0..b0ecd465edca 100644 --- a/browser/devtools/webconsole/console-output.js +++ b/browser/devtools/webconsole/console-output.js @@ -10,8 +10,12 @@ const {Cc, Ci, Cu} = require("chrome"); loader.lazyImporter(this, "VariablesView", "resource:///modules/devtools/VariablesView.jsm"); loader.lazyImporter(this, "escapeHTML", "resource:///modules/devtools/VariablesView.jsm"); loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm"); -loader.lazyImporter(this, "Task","resource://gre/modules/Task.jsm"); +loader.lazyImporter(this, "Task", "resource://gre/modules/Task.jsm"); loader.lazyImporter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm"); +loader.lazyImporter(this, "ObjectClient", "resource://gre/modules/devtools/dbg-client.jsm"); + +loader.lazyRequireGetter(this, "promise"); +loader.lazyRequireGetter(this, "TableWidget", "devtools/shared/widgets/TableWidget", true); const Heritage = require("sdk/core/heritage"); const URI = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); @@ -81,6 +85,7 @@ const CONSOLE_API_LEVELS_TO_SEVERITIES = { info: "info", log: "log", trace: "log", + table: "log", debug: "log", dir: "log", group: "log", @@ -111,6 +116,12 @@ const RE_CLEANUP_STYLES = [ /['"(]*(?:chrome|resource|about|app|data|https?|ftp|file):+\/*/gi, ]; +// Maximum number of rows to display in console.table(). +const TABLE_ROW_MAX_ITEMS = 1000; + +// Maximum number of columns to display in console.table(). +const TABLE_COLUMN_MAX_ITEMS = 10; + /** * The ConsoleOutput object is used to manage output of messages in the Web * Console. @@ -1616,6 +1627,343 @@ Messages.ConsoleTrace.prototype = Heritage.extend(Messages.Simple.prototype, _renderRepeatNode: function() { }, }); // Messages.ConsoleTrace.prototype +/** + * The ConsoleTable message is used for console.table() calls. + * + * @constructor + * @extends Messages.Extended + * @param object packet + * The Console API call packet received from the server. + */ +Messages.ConsoleTable = function(packet) +{ + let options = { + className: "cm-s-mozilla", + timestamp: packet.timeStamp, + category: "webdev", + severity: CONSOLE_API_LEVELS_TO_SEVERITIES[packet.level], + private: packet.private, + filterDuplicates: false, + location: { + url: packet.filename, + line: packet.lineNumber, + }, + }; + + this._populateTableData = this._populateTableData.bind(this); + this._renderTable = this._renderTable.bind(this); + Messages.Extended.call(this, [this._renderTable], options); + + this._repeatID.consoleApiLevel = packet.level; + this._arguments = packet.arguments; +}; + +Messages.ConsoleTable.prototype = Heritage.extend(Messages.Extended.prototype, +{ + /** + * Holds the arguments the content script passed to the console.table() + * method. + * + * @private + * @type array + */ + _arguments: null, + + /** + * Array of objects that holds the data to log in the table. + * + * @private + * @type array + */ + _data: null, + + /** + * Key value pair of the id and display name for the columns in the table. + * Refer to the TableWidget API. + * + * @private + * @type object + */ + _columns: null, + + /** + * A promise that resolves when the table data is ready or null if invalid + * arguments are provided. + * + * @private + * @type promise|null + */ + _populatePromise: null, + + init: function() + { + let result = Messages.Extended.prototype.init.apply(this, arguments); + this._data = []; + this._columns = {}; + + this._populatePromise = this._populateTableData(); + + return result; + }, + + /** + * Sets the key value pair of the id and display name for the columns in the + * table. + * + * @private + * @param array|string columns + * Either a string or array containing the names for the columns in + * the output table. + */ + _setColumns: function(columns) + { + if (columns.class == "Array") { + let items = columns.preview.items; + + for (let item of items) { + if (typeof item == "string") { + this._columns[item] = item; + } + } + } else if (typeof columns == "string" && columns) { + this._columns[columns] = columns; + } + }, + + /** + * Retrieves the table data and columns from the arguments received from the + * server. + * + * @return Promise|null + * Returns a promise that resolves when the table data is ready or + * null if the arguments are invalid. + */ + _populateTableData: function() + { + let deferred = promise.defer(); + + if (this._arguments.length <= 0) { + return; + } + + let data = this._arguments[0]; + if (data.class != "Array" && data.class != "Object" && + data.class != "Map" && data.class != "Set") { + return; + } + + let hasColumnsArg = false; + if (this._arguments.length > 1) { + if (data.class == "Object" || data.class == "Array") { + this._columns["_index"] = l10n.getStr("table.index"); + } else { + this._columns["_index"] = l10n.getStr("table.iterationIndex"); + } + + this._setColumns(this._arguments[1]); + hasColumnsArg = true; + } + + if (data.class == "Object" || data.class == "Array") { + // Get the object properties, and parse the key and value properties into + // the table data and columns. + this.client = new ObjectClient(this.output.owner.jsterm.hud.proxy.client, + data); + this.client.getPrototypeAndProperties(aResponse => { + let {ownProperties} = aResponse; + let rowCount = 0; + let columnCount = 0; + + for (let index of Object.keys(ownProperties || {})) { + // Avoid outputting the length property if the data argument provided + // is an array + if (data.class == "Array" && index == "length") { + continue; + } + + if (!hasColumnsArg) { + this._columns["_index"] = l10n.getStr("table.index"); + } + + let property = ownProperties[index].value; + let item = { _index: index }; + + if (property.class == "Object" || property.class == "Array") { + let {preview} = property; + let entries = property.class == "Object" ? + preview.ownProperties : preview.items; + + for (let key of Object.keys(entries)) { + let value = property.class == "Object" ? + preview.ownProperties[key].value : preview.items[key]; + + item[key] = this._renderValueGrip(value, { concise: true }); + + if (!hasColumnsArg && !(key in this._columns) && + (++columnCount <= TABLE_COLUMN_MAX_ITEMS)) { + this._columns[key] = key; + } + } + } else { + // Display the value for any non-object data input. + item["_value"] = this._renderValueGrip(property, { concise: true }); + + if (!hasColumnsArg && !("_value" in this._columns)) { + this._columns["_value"] = l10n.getStr("table.value"); + } + } + + this._data.push(item); + + if (++rowCount == TABLE_ROW_MAX_ITEMS) { + break; + } + } + + deferred.resolve(); + }); + } else if (data.class == "Map") { + let entries = data.preview.entries; + + if (!hasColumnsArg) { + this._columns["_index"] = l10n.getStr("table.iterationIndex"); + this._columns["_key"] = l10n.getStr("table.key"); + this._columns["_value"] = l10n.getStr("table.value"); + } + + let rowCount = 0; + for (let index of Object.keys(entries || {})) { + let [key, value] = entries[index]; + let item = { + _index: index, + _key: this._renderValueGrip(key, { concise: true }), + _value: this._renderValueGrip(value, { concise: true }) + }; + + this._data.push(item); + + if (++rowCount == TABLE_ROW_MAX_ITEMS) { + break; + } + } + + deferred.resolve(); + } else if (data.class == "Set") { + let entries = data.preview.items; + + if (!hasColumnsArg) { + this._columns["_index"] = l10n.getStr("table.iterationIndex"); + this._columns["_value"] = l10n.getStr("table.value"); + } + + let rowCount = 0; + for (let index of Object.keys(entries || {})) { + let value = entries[index]; + let item = { + _index : index, + _value: this._renderValueGrip(value, { concise: true }) + }; + + this._data.push(item); + + if (++rowCount == TABLE_ROW_MAX_ITEMS) { + break; + } + } + + deferred.resolve(); + } + + return deferred.promise; + }, + + render: function() + { + Messages.Extended.prototype.render.apply(this, arguments); + this.element.setAttribute("open", true); + return this; + }, + + /** + * Render the table. + * + * @private + * @return DOMElement + */ + _renderTable: function() + { + let cmvar = this.document.createElementNS(XHTML_NS, "span"); + cmvar.className = "cm-variable"; + cmvar.textContent = "console"; + + let cmprop = this.document.createElementNS(XHTML_NS, "span"); + cmprop.className = "cm-property"; + cmprop.textContent = "table"; + + let title = this.document.createElementNS(XHTML_NS, "span"); + title.className = "message-body devtools-monospace"; + title.appendChild(cmvar); + title.appendChild(this.document.createTextNode(".")); + title.appendChild(cmprop); + title.appendChild(this.document.createTextNode("():")); + + let repeatNode = Messages.Simple.prototype._renderRepeatNode.call(this); + let location = Messages.Simple.prototype._renderLocation.call(this); + if (location) { + location.target = "jsdebugger"; + } + + let body = this.document.createElementNS(XHTML_NS, "span"); + body.className = "message-flex-body"; + body.appendChild(title); + if (repeatNode) { + body.appendChild(repeatNode); + } + if (location) { + body.appendChild(location); + } + body.appendChild(this.document.createTextNode("\n")); + + let result = this.document.createElementNS(XHTML_NS, "div"); + result.appendChild(body); + + if (this._populatePromise) { + this._populatePromise.then(() => { + if (this._data.length > 0) { + let widget = new Widgets.Table(this, this._data, this._columns).render(); + result.appendChild(widget.element); + } + + result.scrollIntoView(); + + // Release object actors + if (Array.isArray(this._arguments)) { + for (let arg of this._arguments) { + if (WebConsoleUtils.isActorGrip(arg)) { + this.output._releaseObject(arg.actor); + } + } + } + this._arguments = null; + }); + } + + return result; + }, + + _renderBody: function() + { + let body = Messages.Simple.prototype._renderBody.apply(this, arguments); + body.classList.remove("devtools-monospace", "message-body"); + return body; + }, + + // no-op for the message location and .repeats elements. + // |this._renderTable| handles customized message output. + _renderLocation: function() { }, + _renderRepeatNode: function() { }, +}); // Messages.ConsoleTable.prototype + let Widgets = {}; /** @@ -3012,6 +3360,63 @@ Widgets.Stacktrace.prototype = Heritage.extend(Widgets.BaseWidget.prototype, }); // Widgets.Stacktrace.prototype +/** + * The table widget. + * + * @constructor + * @extends Widgets.BaseWidget + * @param object message + * The owning message. + * @param array data + * Array of objects that holds the data to log in the table. + * @param object columns + * Object containing the key value pair of the id and display name for + * the columns in the table. + */ +Widgets.Table = function(message, data, columns) +{ + Widgets.BaseWidget.call(this, message); + this.data = data; + this.columns = columns; +}; + +Widgets.Table.prototype = Heritage.extend(Widgets.BaseWidget.prototype, +{ + /** + * Array of objects that holds the data to output in the table. + * @type array + */ + data: null, + + /** + * Object containing the key value pair of the id and display name for + * the columns in the table. + * @type object + */ + columns: null, + + render: function() { + if (this.element) { + return this; + } + + let result = this.element = this.document.createElementNS(XHTML_NS, "div"); + result.className = "consoletable devtools-monospace"; + + this.table = new TableWidget(result, { + initialColumns: this.columns, + uniqueId: "_index", + firstColumn: "_index" + }); + + for (let row of this.data) { + this.table.push(row); + } + + return this; + } +}); // Widgets.Table.prototype + function gSequenceId() { return gSequenceId.n++; diff --git a/browser/devtools/webconsole/webconsole.js b/browser/devtools/webconsole/webconsole.js index 611231d32b93..82ac1d5c3951 100644 --- a/browser/devtools/webconsole/webconsole.js +++ b/browser/devtools/webconsole/webconsole.js @@ -123,6 +123,7 @@ const LEVELS = { info: SEVERITY_INFO, log: SEVERITY_LOG, trace: SEVERITY_LOG, + table: SEVERITY_LOG, debug: SEVERITY_LOG, dir: SEVERITY_LOG, group: SEVERITY_LOG, @@ -1212,6 +1213,11 @@ WebConsoleFrame.prototype = { node = msg.init(this.output).render().element; break; } + case "table": { + let msg = new Messages.ConsoleTable(aMessage); + node = msg.init(this.output).render().element; + break; + } case "trace": { let msg = new Messages.ConsoleTrace(aMessage); node = msg.init(this.output).render().element; diff --git a/browser/locales/en-US/chrome/browser/devtools/webconsole.properties b/browser/locales/en-US/chrome/browser/devtools/webconsole.properties index a67eaf6e802d..d74b96e3f8e5 100644 --- a/browser/locales/en-US/chrome/browser/devtools/webconsole.properties +++ b/browser/locales/en-US/chrome/browser/devtools/webconsole.properties @@ -250,3 +250,10 @@ messageToggleDetails=Show/hide message details. # example: 1 empty slot # example: 5 empty slots emptySlotLabel=#1 empty slot;#1 empty slots + +# LOCALIZATION NOTE (table.index, table.iterationIndex, table.key, table.value): +# the column header displayed in the console table widget. +table.index=(index) +table.iterationIndex=(iteration index) +table.key=Key +table.value=Values diff --git a/browser/themes/shared/devtools/webconsole.inc.css b/browser/themes/shared/devtools/webconsole.inc.css index f471a4e87467..6ce4ce24b9ce 100644 --- a/browser/themes/shared/devtools/webconsole.inc.css +++ b/browser/themes/shared/devtools/webconsole.inc.css @@ -63,6 +63,10 @@ a { margin: 3px; } +.message-body-wrapper .table-widget-body { + overflow: visible; +} + /* The red bubble that shows the number of times a message is repeated */ .message-repeats { -moz-user-select: none; @@ -223,6 +227,13 @@ a { color: hsl(24,85%,39%); } +.theme-selected .console-string, +.theme-selected .cm-number, +.theme-selected .cm-variable, +.theme-selected .kind-ArrayLike { + color: #f5f7fa !important; /* Selection Text Color */ +} + .message[category=network] > .indent { -moz-border-end: solid #000 6px; } @@ -429,6 +440,10 @@ a { border-radius: 3px; } +.consoletable { + margin: 5px 0 0 0; +} + .theme-light .message[severity=error] .stacktrace { background-color: rgba(255, 255, 255, 0.5); } From 6ab8525ed089814bfb7ed6bb9cd333ff678027c1 Mon Sep 17 00:00:00 2001 From: Gabriel Luong Date: Wed, 27 Aug 2014 15:32:42 -0700 Subject: [PATCH 19/60] Bug 899753 - Part 2: Unit test for Table console output r=past --- browser/devtools/webconsole/console-output.js | 1 + browser/devtools/webconsole/test/browser.ini | 2 + .../test/browser_webconsole_output_table.js | 158 ++++++++++++++++++ browser/devtools/webconsole/test/head.js | 53 ++++++ .../webconsole/test/test-console-extras.html | 3 - .../webconsole/test/test-console-table.html | 52 ++++++ 6 files changed, 266 insertions(+), 3 deletions(-) create mode 100644 browser/devtools/webconsole/test/browser_webconsole_output_table.js create mode 100644 browser/devtools/webconsole/test/test-console-table.html diff --git a/browser/devtools/webconsole/console-output.js b/browser/devtools/webconsole/console-output.js index b0ecd465edca..681783a06b9f 100644 --- a/browser/devtools/webconsole/console-output.js +++ b/browser/devtools/webconsole/console-output.js @@ -1935,6 +1935,7 @@ Messages.ConsoleTable.prototype = Heritage.extend(Messages.Extended.prototype, } result.scrollIntoView(); + this.output.owner.emit("messages-table-rendered"); // Release object actors if (Array.isArray(this._arguments)) { diff --git a/browser/devtools/webconsole/test/browser.ini b/browser/devtools/webconsole/test/browser.ini index 9de33440942a..68cc675d0d3e 100644 --- a/browser/devtools/webconsole/test/browser.ini +++ b/browser/devtools/webconsole/test/browser.ini @@ -67,6 +67,7 @@ support-files = test-console-extras.html test-console-replaced-api.html test-console.html + test-console-table.html test-console-output-02.html test-console-output-03.html test-console-output-04.html @@ -305,6 +306,7 @@ skip-if = buildapp == 'mulet' [browser_webconsole_output_dom_elements_03.js] [browser_webconsole_output_dom_elements_04.js] [browser_webconsole_output_events.js] +[browser_webconsole_output_table.js] [browser_console_variables_view_highlighter.js] [browser_webconsole_start_netmon_first.js] [browser_webconsole_console_trace_duplicates.js] diff --git a/browser/devtools/webconsole/test/browser_webconsole_output_table.js b/browser/devtools/webconsole/test/browser_webconsole_output_table.js new file mode 100644 index 000000000000..d1fbdd8dfcde --- /dev/null +++ b/browser/devtools/webconsole/test/browser_webconsole_output_table.js @@ -0,0 +1,158 @@ + /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + /* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests that console.table() works as intended. + + "use strict"; + +const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console-table.html"; + +const TEST_DATA = [ + { + command: "console.table(languages1)", + data: [ + { _index: "0", name: "\"JavaScript\"", fileExtension: "Array[1]" }, + { _index: "1", name: "Object", fileExtension: "\".ts\"" }, + { _index: "2", name: "\"CoffeeScript\"", fileExtension: "\".coffee\"" } + ], + columns: { _index: "(index)", name: "name", fileExtension: "fileExtension" } + }, + { + command: "console.table(languages1, 'name')", + data: [ + { _index: "0", name: "\"JavaScript\"", fileExtension: "Array[1]" }, + { _index: "1", name: "Object", fileExtension: "\".ts\"" }, + { _index: "2", name: "\"CoffeeScript\"", fileExtension: "\".coffee\"" } + ], + columns: { _index: "(index)", name: "name" } + }, + { + command: "console.table(languages1, ['name'])", + data: [ + { _index: "0", name: "\"JavaScript\"", fileExtension: "Array[1]" }, + { _index: "1", name: "Object", fileExtension: "\".ts\"" }, + { _index: "2", name: "\"CoffeeScript\"", fileExtension: "\".coffee\"" } + ], + columns: { _index: "(index)", name: "name" } + }, + { + command: "console.table(languages2)", + data: [ + { _index: "csharp", name: "\"C#\"", paradigm: "\"object-oriented\"" }, + { _index: "fsharp", name: "\"F#\"", paradigm: "\"functional\"" } + ], + columns: { _index: "(index)", name: "name", paradigm: "paradigm" } + }, + { + command: "console.table([[1, 2], [3, 4]])", + data: [ + { _index: "0", 0: "1", 1: "2" }, + { _index: "1", 0: "3", 1: "4" } + ], + columns: { _index: "(index)", 0: "0", 1: "1" } + }, + { + command: "console.table({a: [1, 2], b: [3, 4]})", + data: [ + { _index: "a", 0: "1", 1: "2" }, + { _index: "b", 0: "3", 1: "4" } + ], + columns: { _index: "(index)", 0: "0", 1: "1" } + }, + { + command: "console.table(family)", + data: [ + { _index: "mother", firstName: "\"Susan\"", lastName: "\"Doyle\"", age: "32" }, + { _index: "father", firstName: "\"John\"", lastName: "\"Doyle\"", age: "33" }, + { _index: "daughter", firstName: "\"Lily\"", lastName: "\"Doyle\"", age: "5" }, + { _index: "son", firstName: "\"Mike\"", lastName: "\"Doyle\"", age: "8" }, + ], + columns: { _index: "(index)", firstName: "firstName", lastName: "lastName", age: "age" } + }, + { + command: "console.table(family, [])", + data: [ + { _index: "mother", firstName: "\"Susan\"", lastName: "\"Doyle\"", age: "32" }, + { _index: "father", firstName: "\"John\"", lastName: "\"Doyle\"", age: "33" }, + { _index: "daughter", firstName: "\"Lily\"", lastName: "\"Doyle\"", age: "5" }, + { _index: "son", firstName: "\"Mike\"", lastName: "\"Doyle\"", age: "8" }, + ], + columns: { _index: "(index)" } + }, + { + command: "console.table(family, ['firstName', 'lastName'])", + data: [ + { _index: "mother", firstName: "\"Susan\"", lastName: "\"Doyle\"", age: "32" }, + { _index: "father", firstName: "\"John\"", lastName: "\"Doyle\"", age: "33" }, + { _index: "daughter", firstName: "\"Lily\"", lastName: "\"Doyle\"", age: "5" }, + { _index: "son", firstName: "\"Mike\"", lastName: "\"Doyle\"", age: "8" }, + ], + columns: { _index: "(index)", firstName: "firstName", lastName: "lastName" } + }, + { + command: "console.table(mySet)", + data: [ + { _index: "0", _value: "1" }, + { _index: "1", _value: "5" }, + { _index: "2", _value: "\"some text\"" }, + { _index: "3", _value: "null" }, + { _index: "4", _value: "undefined" } + ], + columns: { _index: "(iteration index)", _value: "Values" } + }, + { + command: "console.table(myMap)", + data: [ + { _index: "0", _key: "\"a string\"", _value: "\"value associated with 'a string'\"" }, + { _index: "1", _key: "5", _value: "\"value associated with 5\"" }, + ], + columns: { _index: "(iteration index)", _key: "Key", _value: "Values" } + } +]; + +let test = asyncTest(function*() { + const {tab} = yield loadTab(TEST_URI); + let hud = yield openConsole(tab); + + for (let testdata of TEST_DATA) { + hud.jsterm.clearOutput(); + + info("Executing " + testdata.command); + + let onTableRender = once(hud.ui, "messages-table-rendered"); + hud.jsterm.execute(testdata.command); + yield onTableRender; + + let [result] = yield waitForMessages({ + webconsole: hud, + messages: [{ + name: testdata.command + " output", + consoleTable: true + }], + }); + + let node = [...result.matched][0]; + ok(node, "found trace log node"); + + let obj = node._messageObject; + ok(obj, "console.trace message object"); + + ok(obj._data, "found table data object"); + + let data = obj._data.map(entries => { + let result = {}; + + for (let key of Object.keys(entries)) { + result[key] = entries[key] instanceof HTMLElement ? + entries[key].textContent : entries[key]; + } + + return result; + }); + + is(data.toSource(), testdata.data.toSource(), "table data is correct"); + ok(obj._columns, "found table column object"); + is(obj._columns.toSource(), testdata.columns.toSource(), "table column is correct"); + } +}); diff --git a/browser/devtools/webconsole/test/head.js b/browser/devtools/webconsole/test/head.js index 352d7e88ad80..0a38806fb771 100644 --- a/browser/devtools/webconsole/test/head.js +++ b/browser/devtools/webconsole/test/head.js @@ -912,6 +912,8 @@ function openDebugger(aOptions = {}) * message. * - consoleGroup: boolean, set to |true| to match a console.group() * message. + * - consoleTable: boolean, set to |true| to match a console.table() + * message. * - longString: boolean, set to |true} to match long strings in the * message. * - collapsible: boolean, set to |true| to match messages that can @@ -970,6 +972,22 @@ function waitForMessages(aOptions) return result; } + function checkConsoleTable(aRule, aElement) + { + let elemText = aElement.textContent; + let table = aRule.consoleTable; + + if (!checkText("console.table():", elemText)) { + return false; + } + + aRule.category = CATEGORY_WEBDEV; + aRule.severity = SEVERITY_LOG; + aRule.type = Messages.ConsoleTable; + + return true; + } + function checkConsoleTrace(aRule, aElement) { let elemText = aElement.textContent; @@ -1146,6 +1164,10 @@ function waitForMessages(aOptions) return false; } + if (aRule.consoleTable && !checkConsoleTable(aRule, aElement)) { + return false; + } + if (aRule.consoleTrace && !checkConsoleTrace(aRule, aElement)) { return false; } @@ -1593,3 +1615,34 @@ function checkOutputForInputs(hud, inputTests) return Task.spawn(runner); } + +/** + * Wait for eventName on target. + * @param {Object} target An observable object that either supports on/off or + * addEventListener/removeEventListener + * @param {String} eventName + * @param {Boolean} useCapture Optional, for addEventListener/removeEventListener + * @return A promise that resolves when the event has been handled + */ +function once(target, eventName, useCapture=false) { + info("Waiting for event: '" + eventName + "' on " + target + "."); + + let deferred = promise.defer(); + + for (let [add, remove] of [ + ["addEventListener", "removeEventListener"], + ["addListener", "removeListener"], + ["on", "off"] + ]) { + if ((add in target) && (remove in target)) { + target[add](eventName, function onEvent(...aArgs) { + target[remove](eventName, onEvent, useCapture); + deferred.resolve.apply(deferred, aArgs); + }, useCapture); + break; + } + } + + return deferred.promise; +} + diff --git a/browser/devtools/webconsole/test/test-console-extras.html b/browser/devtools/webconsole/test/test-console-extras.html index ba6331242b4b..ae0b521c5b77 100644 --- a/browser/devtools/webconsole/test/test-console-extras.html +++ b/browser/devtools/webconsole/test/test-console-extras.html @@ -7,9 +7,6 @@ console.log("start"); console.clear() console.dirxml() - console.profile() - console.profileEnd() - console.table() console.log("end"); } diff --git a/browser/devtools/webconsole/test/test-console-table.html b/browser/devtools/webconsole/test/test-console-table.html new file mode 100644 index 000000000000..7a3f2333eda5 --- /dev/null +++ b/browser/devtools/webconsole/test/test-console-table.html @@ -0,0 +1,52 @@ + + + + + + Test for Bug 899753 - console.table support + + + +

Hello world!

+ + From 2a210231812090fd87ab98092240c88a488068af Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 15:37:35 -0700 Subject: [PATCH 20/60] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 750a1afe944c..8bfa0f948554 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 3b34b1872664..5ce1e627cd9b 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 49ce8fddf448..af8bcf4d9a38 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index ec9460ebf052..396d957565e7 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 3b34b1872664..5ce1e627cd9b 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 9391929812c3..75424106d05f 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index c1b89437e79c..60d4dc3ce2ca 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 2f863974895e..aec3b142b60d 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 1175de5d5a7d..f43c9797f4f5 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 128cf278a447..c3093cbf315c 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 167e2a3b9f9df65a979fb4c75a785db9803c747c Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 16:00:32 -0700 Subject: [PATCH 21/60] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/52a7b8d9b991 Author: Kevin Grandon Desc: Merge pull request #23387 from KevinGrandon/bug_1016814_duplicate_file_follow_up Bug 1016814 - Follow-up, remove duplicated component_utils.js file ======== https://hg.mozilla.org/integration/gaia-central/rev/9ff95e6951db Author: Kevin Grandon Desc: Bug 1016814 - Follow-up, remove duplicated component_utils.js file r=kgrandon --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 1d105b8984f5..61618891cfe3 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "ba59f497382766979efb26cc17c76d1047b8ab73", + "revision": "52a7b8d9b991335e9d3387a2c9dde3c05abf578e", "repo_path": "/integration/gaia-central" } From 3098b23dc3f3d5869ed5eff01e7183ad165a49f9 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Wed, 27 Aug 2014 16:04:12 -0700 Subject: [PATCH 22/60] Bug 993885 - Refactor SendTabActivity to avoid a race condition. r=mcomella --- .../setup/activities/SendTabActivity.java | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/mobile/android/base/sync/setup/activities/SendTabActivity.java b/mobile/android/base/sync/setup/activities/SendTabActivity.java index 880019a8a728..a559c1937aba 100644 --- a/mobile/android/base/sync/setup/activities/SendTabActivity.java +++ b/mobile/android/base/sync/setup/activities/SendTabActivity.java @@ -146,8 +146,7 @@ public class SendTabActivity extends LocaleAwareActivity { enableSend(false); - // will enableSend if appropriate. - updateClientList(); + // Sending will be enabled in onResume, if appropriate. } protected static SendTabData getSendTabData(Intent intent) throws IllegalArgumentException { @@ -184,14 +183,14 @@ public class SendTabActivity extends LocaleAwareActivity { * Ensure that the view's list of clients is backed by a recently populated * array adapter. */ - protected synchronized void updateClientList() { + protected synchronized void updateClientList(final TabSender sender, final ClientRecordArrayAdapter adapter) { // Fetching the client list hits the clients database, so we spin this onto // a background task. new AsyncTask>() { @Override protected Collection doInBackground(Void... params) { - return getOtherClients(); + return getOtherClients(sender); } @Override @@ -199,12 +198,12 @@ public class SendTabActivity extends LocaleAwareActivity { // We're allowed to update the UI from here. Logger.debug(LOG_TAG, "Got " + clientArray.size() + " clients."); - arrayAdapter.setClientRecordList(clientArray); + adapter.setClientRecordList(clientArray); if (clientArray.size() == 1) { - arrayAdapter.checkItem(0, true); + adapter.checkItem(0, true); } - enableSend(arrayAdapter.getNumCheckedGUIDs() > 0); + enableSend(adapter.getNumCheckedGUIDs() > 0); } }.execute(); } @@ -235,6 +234,9 @@ public class SendTabActivity extends LocaleAwareActivity { this.tabSender = new FxAccountTabSender(applicationContext, fxAccount); + // will enableSend if appropriate. + updateClientList(tabSender, this.arrayAdapter); + Logger.info(LOG_TAG, "Allowing tab send for Firefox Account."); registerDisplayURICommand(); return; @@ -244,6 +246,9 @@ public class SendTabActivity extends LocaleAwareActivity { if (syncAccounts.length > 0) { this.tabSender = new Sync11TabSender(applicationContext, syncAccounts[0], accountManager); + // will enableSend if appropriate. + updateClientList(tabSender, this.arrayAdapter); + Logger.info(LOG_TAG, "Allowing tab send for Sync account."); registerDisplayURICommand(); return; @@ -360,18 +365,18 @@ public class SendTabActivity extends LocaleAwareActivity { /** * @return a collection of client records, excluding our own. */ - protected Collection getOtherClients() { + protected Collection getOtherClients(final TabSender sender) { + if (sender == null) { + Logger.warn(LOG_TAG, "No tab sender when fetching other client IDs."); + return new ArrayList(0); + } + final Map all = getAllClients(); if (all == null) { return new ArrayList(0); } - if (this.tabSender == null) { - Logger.warn(LOG_TAG, "No tab sender when fetching other client IDs."); - return new ArrayList(0); - } - - final String ourGUID = this.tabSender.getAccountGUID(); + final String ourGUID = sender.getAccountGUID(); if (ourGUID == null) { return all.values(); } From 6136a5d928f91ea24ad29f8bdc471f7f53c88960 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 16:06:32 -0700 Subject: [PATCH 23/60] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 8bfa0f948554..b9e802348723 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 5ce1e627cd9b..0bf4e955b829 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index af8bcf4d9a38..fa6abfcc5d18 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 396d957565e7..5f172d2b587d 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 5ce1e627cd9b..0bf4e955b829 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 75424106d05f..8586308de1b2 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 60d4dc3ce2ca..8382667a21f2 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index aec3b142b60d..8b49d861ff21 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index f43c9797f4f5..daa77fc51bb8 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index c3093cbf315c..30bca9e3fa7c 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From ac2b2f0c46dc9d0998b6b575091dae9b271a79d3 Mon Sep 17 00:00:00 2001 From: Shane Caraveo Date: Wed, 27 Aug 2014 16:11:36 -0700 Subject: [PATCH 24/60] Bug 1057596 fix manifest updating and worker reload, r=markh --- .../content/test/social/browser_addons.js | 38 +++++++++++++++---- .../base/content/test/social/social_worker.js | 15 ++++++-- toolkit/components/social/SocialService.jsm | 12 ++++-- 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/browser/base/content/test/social/browser_addons.js b/browser/base/content/test/social/browser_addons.js index 116e9eef1683..4f6965b7445b 100644 --- a/browser/base/content/test/social/browser_addons.js +++ b/browser/base/content/test/social/browser_addons.js @@ -249,15 +249,37 @@ var tests = { SocialService.registerProviderListener(function providerListener(topic, origin, providers) { if (topic != "provider-update") return; - is(origin, addonManifest.origin, "provider updated") + // The worker will have reloaded and the current provider instance + // disabled, removed from the provider list. We have a reference + // here, check it is is disabled. + is(provider.enabled, false, "old provider instance is disabled") + is(origin, addonManifest.origin, "provider manifest updated") SocialService.unregisterProviderListener(providerListener); - Services.prefs.clearUserPref("social.whitelist"); - let provider = Social._getProviderFromOrigin(origin); - is(provider.manifest.version, 2, "manifest version is 2"); - Social.uninstallProvider(origin, function() { - gBrowser.removeTab(tab); - next(); - }); + + // Get the new provider instance, fetch the manifest via workerapi + // and validate that data as well. + let p = Social._getProviderFromOrigin(origin); + is(p.manifest.version, 2, "manifest version is 2"); + let port = p.getWorkerPort(); + ok(port, "got a new port"); + port.onmessage = function (e) { + let topic = e.data.topic; + switch (topic) { + case "social.manifest": + let manifest = e.data.data; + is(manifest.version, 2, "manifest version is 2"); + port.close(); + Social.uninstallProvider(origin, function() { + Services.prefs.clearUserPref("social.whitelist"); + gBrowser.removeTab(tab); + next(); + }); + break; + } + } + port.postMessage({topic: "test-init"}); + port.postMessage({topic: "manifest-get"}); + }); let port = provider.getWorkerPort(); diff --git a/browser/base/content/test/social/social_worker.js b/browser/base/content/test/social/social_worker.js index 1bea0d0ccc6a..9455e6c9577b 100644 --- a/browser/base/content/test/social/social_worker.js +++ b/browser/base/content/test/social/social_worker.js @@ -2,7 +2,7 @@ * 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/. */ -let testPort, sidebarPort, apiPort; +let testPort, sidebarPort, apiPort, updatingManifest=false; onconnect = function(e) { let port = e.ports[0]; @@ -116,12 +116,21 @@ onconnect = function(e) { if (testPort) testPort.postMessage({topic:"got-share-data-message", result: event.data.result}); break; + case "manifest-get": + apiPort.postMessage({topic: 'social.manifest-get'}); + break; case "worker.update": + updatingManifest = true; apiPort.postMessage({topic: 'social.manifest-get'}); break; case "social.manifest": - event.data.data.version = 2; - apiPort.postMessage({topic: 'social.manifest-set', data: event.data.data}); + if (updatingManifest) { + updatingManifest = false; + event.data.data.version = 2; + apiPort.postMessage({topic: 'social.manifest-set', data: event.data.data}); + } else if (testPort) { + testPort.postMessage({topic:"social.manifest", data: event.data.data}); + } break; } } diff --git a/toolkit/components/social/SocialService.jsm b/toolkit/components/social/SocialService.jsm index 9dc6c623ee02..b28a86a9cf07 100644 --- a/toolkit/components/social/SocialService.jsm +++ b/toolkit/components/social/SocialService.jsm @@ -687,7 +687,11 @@ this.SocialService = { // overwrite the existing provider then notify the front end so it can // handle any reload that might be necessary. if (ActiveProviders.has(manifest.origin)) { - let provider = new SocialProvider(manifest); + // unload the worker prior to replacing the provider instance, also + // ensures the workerapi instance is terminated. + let provider = SocialServiceInternal.providers[manifest.origin]; + provider.enabled = false; + provider = new SocialProvider(manifest); SocialServiceInternal.providers[provider.origin] = provider; // update the cache and ui, reload provider if necessary this.getOrderedProviderList(providers => { @@ -756,8 +760,10 @@ function SocialProvider(input) { SocialProvider.prototype = { reload: function() { - this._terminate(); - this._activate(); + // calling terminate/activate does not set the enabled state whereas setting + // enabled will call terminate/activate + this.enabled = false; + this.enabled = true; Services.obs.notifyObservers(null, "social:provider-reload", this.origin); }, From 2a436941d95c4c558631f9d6b0f9f652c9c1858e Mon Sep 17 00:00:00 2001 From: Chris Karlof Date: Wed, 27 Aug 2014 16:14:58 -0700 Subject: [PATCH 25/60] Bug 1056523 - Ensure sync credentials are reset during reauth flow. r=markh This patch addresses a bug in the following scenario: User has browser 1 connected to sync and open, and resets her password on browser 2. Eventually the browser detects the need to reauthenticate the user, and prompts the user. When the user entered her new password, the browserid_identity module failed to re-derive a new syncKeyBundle from the new password and happily used the old one. Chaos ensued. This patch mitigate the problem by calling resetCredentials at the start of initializeWithCurrentIdentity(), which will clear the syncKeyBundle, along with other credentials. Previously this function was only resetting this._shouldHaveSyncKeyBundle. I also removed a misleading comment about the syncKeyBundle being cleared when it wasn't. --- services/sync/modules/browserid_identity.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/services/sync/modules/browserid_identity.js b/services/sync/modules/browserid_identity.js index b489807cc8fa..277fcb3120a6 100644 --- a/services/sync/modules/browserid_identity.js +++ b/services/sync/modules/browserid_identity.js @@ -188,7 +188,11 @@ this.BrowserIDManager.prototype = { this._log.error("Could not authenticate: " + err); }); - this._shouldHaveSyncKeyBundle = false; + // initializeWithCurrentIdentity() can be called after the + // identity module was first initialized, e.g., after the + // user completes a force authentication, so we should make + // sure all credentials are reset before proceeding. + this.resetCredentials(); this._authFailureReason = null; return this._fxaService.getSignedInUser().then(accountData => { @@ -579,9 +583,10 @@ this.BrowserIDManager.prototype = { // for now assume it is just a transient network related problem. this._authFailureReason = LOGIN_FAILED_NETWORK_ERROR; } - // Drop the sync key bundle, but still expect to have one. - // This will arrange for us to be in the right 'currentAuthState' - // such that UI will show the right error. + // this._authFailureReason being set to be non-null in the above if clause + // ensures we are in the correct currentAuthState, and + // this._shouldHaveSyncKeyBundle being true ensures everything that cares knows + // that there is no authentication dance still under way. this._shouldHaveSyncKeyBundle = true; Weave.Status.login = this._authFailureReason; Services.obs.notifyObservers(null, "weave:service:login:error", null); From 1f1e0d0e331c0ba184bd1cfa5e46372ccb343708 Mon Sep 17 00:00:00 2001 From: Gabriel Luong Date: Wed, 27 Aug 2014 16:21:32 -0700 Subject: [PATCH 26/60] Bug 899753: Part 3: Add table prop to console API test r=fitzgen CLOSED TREE --- dom/tests/mochitest/general/test_consoleAPI.html | 1 + 1 file changed, 1 insertion(+) diff --git a/dom/tests/mochitest/general/test_consoleAPI.html b/dom/tests/mochitest/general/test_consoleAPI.html index f594930c4cb4..85038a3a94f3 100644 --- a/dom/tests/mochitest/general/test_consoleAPI.html +++ b/dom/tests/mochitest/general/test_consoleAPI.html @@ -37,6 +37,7 @@ function doTest() { "profileEnd": "function", "assert": "function", "count": "function", + "table": "function", "__noSuchMethod__": "function" }; From 644e8fdb2b449eba94f2ca0f920e22d1cc00b1cb Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 17:10:32 -0700 Subject: [PATCH 27/60] Bumping gaia.json for 4 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/8c87851961c5 Author: Kevin Grandon Desc: Merge pull request #23289 from KevinGrandon/bug_1052503_reland Bug 1052503 - [Rocketbar] Update loading progress bar ======== https://hg.mozilla.org/integration/gaia-central/rev/fc6e904d79fe Author: Kevin Grandon Desc: Bug 1052503 - [Rocketbar] Update loading progress bar r=benfrancis ======== https://hg.mozilla.org/integration/gaia-central/rev/050b7f8fef71 Author: punamdahiya Desc: Merge pull request #22827 from ranjithgithub/952561_BrightnessSliderIssue Bug 952651 - [Gallery][Editor] Fix exposure slider button sliding from previous position r=pdahiya ======== https://hg.mozilla.org/integration/gaia-central/rev/97ea6e6d3280 Author: ranjith.gutha Desc: Bug 952651 - [Gallery][Photo Editor] Fixed slider button sliding from previous position --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 61618891cfe3..84fa307c05d0 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "52a7b8d9b991335e9d3387a2c9dde3c05abf578e", + "revision": "8c87851961c5f5cdf3bab497621a7fb6c3888728", "repo_path": "/integration/gaia-central" } From e7437414b1c43a49ae0c30ee434d724f2946e6ba Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 17:12:01 -0700 Subject: [PATCH 28/60] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index b9e802348723..c1de65182d4b 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 0bf4e955b829..14185fb0f0c2 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index fa6abfcc5d18..a2a73a9ef4d2 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 5f172d2b587d..3192d34fdb41 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 0bf4e955b829..14185fb0f0c2 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 8586308de1b2..50a1ffbe581d 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 8382667a21f2..24275e1bc4f7 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 8b49d861ff21..51ba987ca7f3 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index daa77fc51bb8..6e712ddd00fc 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 30bca9e3fa7c..60d69f3499c1 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 180f602bfb0a926ec1e35a33ef69bab12ebd0c5d Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 17:25:30 -0700 Subject: [PATCH 29/60] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/a0dd4b73745e Author: punamdahiya Desc: Merge pull request #23221 from davidflanagan/bug1046167 Bug 1046167-[Gallery]- Limit the allowable size of progressive jpegs r=russn ======== https://hg.mozilla.org/integration/gaia-central/rev/c434cdefd79b Author: David Flanagan Desc: Bug 1046167: limit the allowable size of progressive jpegs make the pjpeg image size limit stricter than for other image sizes --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 84fa307c05d0..8737ce1fae45 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "8c87851961c5f5cdf3bab497621a7fb6c3888728", + "revision": "a0dd4b73745efbd3db3f8e8914517c7be0d048b4", "repo_path": "/integration/gaia-central" } From b90353330bf96763e3cc8b73ed6a337e1b0c5706 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 17:31:33 -0700 Subject: [PATCH 30/60] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index c1de65182d4b..1693e69a2d3e 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 14185fb0f0c2..275059008b77 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index a2a73a9ef4d2..8973721901ef 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 3192d34fdb41..b3f0609ccdeb 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 14185fb0f0c2..275059008b77 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 50a1ffbe581d..c9b764ed15ff 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 24275e1bc4f7..9bfeb28c425e 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 51ba987ca7f3..e149f8e81bd1 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 6e712ddd00fc..4c452650a063 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 60d69f3499c1..0d4162db9ea6 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From d32ac7b40da04b62032745e70cd0b5f64c12991a Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 17:40:32 -0700 Subject: [PATCH 31/60] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/f2bd86d28a6b Author: Zibi Braniecki Desc: Merge pull request #23391 from zbraniecki/1057452-wifi-status-l10nid-spelling Bug 1057452 - Fix the spelling in l10nId for Wifi link speed ======== https://hg.mozilla.org/integration/gaia-central/rev/31de6da9f207 Author: Zbigniew Braniecki Desc: Bug 1057452 - Fix the spelling in l10nId for Wifi link speed --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 8737ce1fae45..5af124c843c2 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "a0dd4b73745efbd3db3f8e8914517c7be0d048b4", + "revision": "f2bd86d28a6b5c2344cb0bc1076527f6179404c4", "repo_path": "/integration/gaia-central" } From ca7a2d1ba06a142c06b7f43077aba4271098abdd Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 17:46:39 -0700 Subject: [PATCH 32/60] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 1693e69a2d3e..7cb3b9774e5b 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 275059008b77..2a92ae346054 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 8973721901ef..78d39408ef85 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index b3f0609ccdeb..ebfffef8cb6c 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 275059008b77..2a92ae346054 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index c9b764ed15ff..c7da10259ae1 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 9bfeb28c425e..66a6475d0212 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index e149f8e81bd1..e1e027899335 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 4c452650a063..45c352e7d671 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 0d4162db9ea6..2136f7f5f19c 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From f0b76c5903e19fd499e9a2ebc9b3f6db851c1b43 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 27 Aug 2014 22:13:39 -0400 Subject: [PATCH 33/60] Bug 1055760 - Move the scroll handoff parent id from Layer to FrameMetrics. r=botond --- gfx/ipc/GfxMessageUtils.h | 2 ++ gfx/layers/FrameMetrics.h | 15 +++++++++++++++ gfx/layers/Layers.cpp | 4 ---- gfx/layers/Layers.h | 18 ------------------ gfx/layers/LayersLogging.cpp | 4 ++++ gfx/layers/apz/src/APZCTreeManager.cpp | 1 - gfx/layers/apz/src/AsyncPanZoomController.cpp | 2 +- gfx/layers/apz/src/AsyncPanZoomController.h | 8 +------- gfx/layers/ipc/LayerTransactionParent.cpp | 1 - gfx/layers/ipc/LayersMessages.ipdlh | 1 - gfx/layers/ipc/ShadowLayers.cpp | 1 - gfx/tests/gtest/TestAsyncPanZoomController.cpp | 4 +++- layout/base/nsDisplayList.cpp | 10 +++++----- 13 files changed, 31 insertions(+), 40 deletions(-) diff --git a/gfx/ipc/GfxMessageUtils.h b/gfx/ipc/GfxMessageUtils.h index 64b644c846fa..f672400013ac 100644 --- a/gfx/ipc/GfxMessageUtils.h +++ b/gfx/ipc/GfxMessageUtils.h @@ -761,6 +761,7 @@ struct ParamTraits WriteParam(aMsg, aParam.mCompositionBounds); WriteParam(aMsg, aParam.mRootCompositionSize); WriteParam(aMsg, aParam.mScrollId); + WriteParam(aMsg, aParam.mScrollParentId); WriteParam(aMsg, aParam.mResolution); WriteParam(aMsg, aParam.mCumulativeResolution); WriteParam(aMsg, aParam.mZoom); @@ -787,6 +788,7 @@ struct ParamTraits ReadParam(aMsg, aIter, &aResult->mCompositionBounds) && ReadParam(aMsg, aIter, &aResult->mRootCompositionSize) && ReadParam(aMsg, aIter, &aResult->mScrollId) && + ReadParam(aMsg, aIter, &aResult->mScrollParentId) && ReadParam(aMsg, aIter, &aResult->mResolution) && ReadParam(aMsg, aIter, &aResult->mCumulativeResolution) && ReadParam(aMsg, aIter, &aResult->mZoom) && diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index c8b5e96a0782..b1e9813628c6 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -86,6 +86,7 @@ public: , mIsRoot(false) , mHasScrollgrab(false) , mScrollId(NULL_SCROLL_ID) + , mScrollParentId(NULL_SCROLL_ID) , mScrollOffset(0, 0) , mZoom(1) , mUpdateScrollOffset(false) @@ -117,6 +118,7 @@ public: mPresShellId == aOther.mPresShellId && mIsRoot == aOther.mIsRoot && mScrollId == aOther.mScrollId && + mScrollParentId == aOther.mScrollParentId && mScrollOffset == aOther.mScrollOffset && mHasScrollgrab == aOther.mHasScrollgrab && mUpdateScrollOffset == aOther.mUpdateScrollOffset; @@ -404,6 +406,16 @@ public: mScrollId = scrollId; } + ViewID GetScrollParentId() const + { + return mScrollParentId; + } + + void SetScrollParentId(ViewID aParentId) + { + mScrollParentId = aParentId; + } + void SetRootCompositionSize(const CSSSize& aRootCompositionSize) { mRootCompositionSize = aRootCompositionSize; @@ -467,6 +479,9 @@ private: // A unique ID assigned to each scrollable frame. ViewID mScrollId; + // The ViewID of the scrollable frame to which overscroll should be handed off. + ViewID mScrollParentId; + // The position of the top-left of the CSS viewport, relative to the document // (or the document relative to the viewport, if that helps understand it). // diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index bbf7342da8a4..34cc28d3f1cd 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -170,7 +170,6 @@ Layer::Layer(LayerManager* aManager, void* aImplData) : mPrevSibling(nullptr), mImplData(aImplData), mMaskLayer(nullptr), - mScrollHandoffParentId(FrameMetrics::NULL_SCROLL_ID), mPostXScale(1.0f), mPostYScale(1.0f), mOpacity(1.0), @@ -1464,9 +1463,6 @@ Layer::PrintInfo(std::stringstream& aStream, const char* aPrefix) if (!mFrameMetrics.IsDefault()) { AppendToString(aStream, mFrameMetrics, " [metrics=", "]"); } - if (mScrollHandoffParentId != FrameMetrics::NULL_SCROLL_ID) { - aStream << nsPrintfCString(" [scrollParent=%llu]", mScrollHandoffParentId).get(); - } } // The static helper function sets the transform matrix into the packet diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index c4f522f8e23c..251177cbad27 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -829,22 +829,6 @@ public: } } - /** - * CONSTRUCTION PHASE ONLY - * Set the ViewID of the ContainerLayer to which overscroll should be handed - * off. A value of NULL_SCROLL_ID means that the default handoff-parent-finding - * behaviour should be used (i.e. walk up the layer tree to find the next - * scrollable ancestor layer). - */ - void SetScrollHandoffParentId(FrameMetrics::ViewID aScrollParentId) - { - if (mScrollHandoffParentId != aScrollParentId) { - MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ScrollHandoffParentId", this)); - mScrollHandoffParentId = aScrollParentId; - Mutated(); - } - } - /* * Compositor event handling * ========================= @@ -1174,7 +1158,6 @@ public: uint32_t GetContentFlags() { return mContentFlags; } const nsIntRegion& GetVisibleRegion() const { return mVisibleRegion; } const FrameMetrics& GetFrameMetrics() const { return mFrameMetrics; } - FrameMetrics::ViewID GetScrollHandoffParentId() const { return mScrollHandoffParentId; } const EventRegions& GetEventRegions() const { return mEventRegions; } ContainerLayer* GetParent() { return mParent; } Layer* GetNextSibling() { return mNextSibling; } @@ -1581,7 +1564,6 @@ protected: gfx::UserData mUserData; nsIntRegion mVisibleRegion; FrameMetrics mFrameMetrics; - FrameMetrics::ViewID mScrollHandoffParentId; EventRegions mEventRegions; gfx::Matrix4x4 mTransform; // A mutation of |mTransform| that we've queued to be applied at the diff --git a/gfx/layers/LayersLogging.cpp b/gfx/layers/LayersLogging.cpp index c6b177fa412f..546fa33aedba 100644 --- a/gfx/layers/LayersLogging.cpp +++ b/gfx/layers/LayersLogging.cpp @@ -125,6 +125,9 @@ AppendToString(std::stringstream& aStream, const FrameMetrics& m, AppendToString(aStream, m.mCriticalDisplayPort, " cdp="); if (!detailed) { AppendToString(aStream, m.GetScrollId(), " scrollId="); + if (m.GetScrollParentId() != FrameMetrics::NULL_SCROLL_ID) { + AppendToString(aStream, m.GetScrollParentId(), " scrollParent="); + } aStream << nsPrintfCString(" z=%.3f }", m.GetZoom().scale).get(); } else { AppendToString(aStream, m.GetDisplayPortMargins(), " dpm="); @@ -137,6 +140,7 @@ AppendToString(std::stringstream& aStream, const FrameMetrics& m, m.mTransformScale.scale).get(); aStream << nsPrintfCString(" u=(%d %lu)", m.GetScrollOffsetUpdated(), m.GetScrollGeneration()).get(); + AppendToString(aStream, m.GetScrollParentId(), " p="); aStream << nsPrintfCString(" i=(%ld %lld) }", m.GetPresShellId(), m.GetScrollId()).get(); } diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index c315d7d56bbc..4125e712569e 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -294,7 +294,6 @@ APZCTreeManager::PrepareAPZCForLayer(const Layer* aLayer, apzc->NotifyLayersUpdated(aMetrics, aState.mIsFirstPaint && (aLayersId == aState.mOriginatingLayersId)); - apzc->SetScrollHandoffParentId(aLayer->GetScrollHandoffParentId()); nsIntRegion unobscured = ComputeTouchSensitiveRegion(state->mController, aMetrics, aObscured); apzc->SetLayerHitTestData(unobscured, aAncestorTransform); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 65ede5b296db..e03517feeaf0 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -739,7 +739,6 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId, mAsyncScrollTimeoutTask(nullptr), mTouchBlockBalance(0), mTreeManager(aTreeManager), - mScrollParentId(FrameMetrics::NULL_SCROLL_ID), mAPZCId(sAsyncPanZoomControllerCount++), mSharedLock(nullptr) { @@ -2414,6 +2413,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri mFrameMetrics.mMayHaveTouchListeners = aLayerMetrics.mMayHaveTouchListeners; mFrameMetrics.mMayHaveTouchCaret = aLayerMetrics.mMayHaveTouchCaret; + mFrameMetrics.SetScrollParentId(aLayerMetrics.GetScrollParentId()); APZC_LOG_FM(aLayerMetrics, "%p got a NotifyLayersUpdated with aIsFirstPaint=%d", this, aIsFirstPaint); LogRendertraceRect(GetGuid(), "page", "brown", aLayerMetrics.mScrollableRect); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index 9ea877051415..1e02cae76fa6 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -896,12 +896,8 @@ private: * including handing off scroll to another APZC, and overscrolling. */ public: - void SetScrollHandoffParentId(FrameMetrics::ViewID aScrollParentId) { - mScrollParentId = aScrollParentId; - } - FrameMetrics::ViewID GetScrollHandoffParentId() const { - return mScrollParentId; + return mFrameMetrics.GetScrollParentId(); } /** @@ -935,8 +931,6 @@ public: bool SnapBackIfOverscrolled(); private: - FrameMetrics::ViewID mScrollParentId; - /** * A helper function for calling APZCTreeManager::DispatchScroll(). * Guards against the case where the APZC is being concurrently destroyed diff --git a/gfx/layers/ipc/LayerTransactionParent.cpp b/gfx/layers/ipc/LayerTransactionParent.cpp index bee80bffb688..717666873740 100644 --- a/gfx/layers/ipc/LayerTransactionParent.cpp +++ b/gfx/layers/ipc/LayerTransactionParent.cpp @@ -319,7 +319,6 @@ LayerTransactionParent::RecvUpdate(const InfallibleTArray& cset, layer->SetAnimations(common.animations()); layer->SetInvalidRegion(common.invalidRegion()); layer->SetFrameMetrics(common.metrics()); - layer->SetScrollHandoffParentId(common.scrollParentId()); layer->SetBackgroundColor(common.backgroundColor().value()); layer->SetContentDescription(common.contentDescription()); diff --git a/gfx/layers/ipc/LayersMessages.ipdlh b/gfx/layers/ipc/LayersMessages.ipdlh index 10777cf6bdde..211088e5816e 100644 --- a/gfx/layers/ipc/LayersMessages.ipdlh +++ b/gfx/layers/ipc/LayersMessages.ipdlh @@ -216,7 +216,6 @@ struct CommonLayerAttributes { Animation[] animations; nsIntRegion invalidRegion; FrameMetrics metrics; - ViewID scrollParentId; LayerColor backgroundColor; string contentDescription; }; diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp index 59b8a34fb2d1..2e9eab3af0c8 100644 --- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -608,7 +608,6 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray* aReplies, common.animations() = mutant->GetAnimations(); common.invalidRegion() = mutant->GetInvalidRegion(); common.metrics() = mutant->GetFrameMetrics(); - common.scrollParentId() = mutant->GetScrollHandoffParentId(); common.backgroundColor() = mutant->GetBackgroundColor(); common.contentDescription() = mutant->GetContentDescription(); attrs.specific() = null_t(); diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index 35678c6c7cac..16b72aee0258 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -1728,7 +1728,9 @@ protected: TestAsyncPanZoomController* rootApzc; void SetScrollHandoff(Layer* aChild, Layer* aParent) { - aChild->SetScrollHandoffParentId(aParent->GetFrameMetrics().GetScrollId()); + FrameMetrics metrics = aChild->GetFrameMetrics(); + metrics.SetScrollParentId(aParent->GetFrameMetrics().GetScrollId()); + aChild->SetFrameMetrics(metrics); } void CreateOverscrollHandoffLayerTree1() { diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 27841e5a78ec..2b135cdf6f1d 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -650,6 +650,7 @@ static void RecordFrameMetrics(nsIFrame* aForFrame, nsIFrame* aScrollFrame, const nsIFrame* aReferenceFrame, ContainerLayer* aRoot, + ViewID aScrollParentId, const nsRect& aViewport, bool aForceNullScrollId, bool aIsRoot, @@ -706,6 +707,7 @@ static void RecordFrameMetrics(nsIFrame* aForFrame, metrics.SetScrollId(scrollId); metrics.SetIsRoot(aIsRoot); + metrics.SetScrollParentId(aScrollParentId); // Only the root scrollable frame for a given presShell should pick up // the presShell's resolution. All the other frames are 1.0. @@ -1291,7 +1293,7 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder, RecordFrameMetrics(aForFrame, rootScrollFrame, aBuilder->FindReferenceFrameFor(aForFrame), - root, viewport, + root, FrameMetrics::NULL_SCROLL_ID, viewport, !isRoot, isRoot, containerParameters); // NS_WARNING is debug-only, so don't even bother checking the conditions in @@ -3679,9 +3681,8 @@ nsDisplaySubDocument::BuildLayer(nsDisplayListBuilder* aBuilder, mFrame->GetPosition() + mFrame->GetOffsetToCrossDoc(ReferenceFrame()); - container->SetScrollHandoffParentId(mScrollParentId); RecordFrameMetrics(mFrame, rootScrollFrame, ReferenceFrame(), - container, viewport, + container, mScrollParentId, viewport, false, isRootContentDocument, params); } @@ -3990,9 +3991,8 @@ nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder, mScrollFrame->GetPosition() + mScrollFrame->GetOffsetToCrossDoc(ReferenceFrame()); - layer->SetScrollHandoffParentId(mScrollParentId); RecordFrameMetrics(mScrolledFrame, mScrollFrame, ReferenceFrame(), layer, - viewport, false, false, params); + mScrollParentId, viewport, false, false, params); if (mList.IsOpaque()) { nsRect displayport; From b997ee23d8617cf0733e688831c8f2fbc723c891 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 27 Aug 2014 22:13:40 -0400 Subject: [PATCH 34/60] Bug 1055760 - Rearrange AlignFixedAndStickyLayers; no functional changes. r=botond --- .../composite/AsyncCompositionManager.cpp | 184 +++++++++--------- 1 file changed, 91 insertions(+), 93 deletions(-) diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index 24f52f6bc893..6e7806b332b8 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -251,108 +251,106 @@ AsyncCompositionManager::AlignFixedAndStickyLayers(Layer* aLayer, bool isStickyForSubtree = aLayer->GetIsStickyPosition() && aLayer->GetStickyScrollContainerId() == aTransformedSubtreeRoot->GetFrameMetrics().GetScrollId(); - if (aLayer != aTransformedSubtreeRoot && (isRootFixed || isStickyForSubtree)) { - // Insert a translation so that the position of the anchor point is the same - // before and after the change to the transform of aTransformedSubtreeRoot. - // This currently only works for fixed layers with 2D transforms. + bool isFixedOrSticky = (isRootFixed || isStickyForSubtree); - // Accumulate the transforms between this layer and the subtree root layer. - Matrix ancestorTransform; - if (!AccumulateLayerTransforms2D(aLayer->GetParent(), aTransformedSubtreeRoot, - ancestorTransform)) { - return; + // We want to process all the fixed and sticky children of + // aTransformedSubtreeRoot. Also, once we do encounter such a child, we don't + // need to recurse any deeper because the fixed layers are relative to their + // nearest scrollable layer. + if (aLayer == aTransformedSubtreeRoot || !isFixedOrSticky) { + // ApplyAsyncContentTransformToTree will call this function again for + // nested scrollable layers, so we don't need to recurse if the layer is + // scrollable. + if (aLayer == aTransformedSubtreeRoot || !aLayer->GetFrameMetrics().IsScrollable()) { + for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) { + AlignFixedAndStickyLayers(child, aTransformedSubtreeRoot, + aPreviousTransformForRoot, + aCurrentTransformForRoot, aFixedLayerMargins); + } } - - Matrix oldRootTransform; - Matrix newRootTransform; - if (!aPreviousTransformForRoot.Is2D(&oldRootTransform) || - !aCurrentTransformForRoot.Is2D(&newRootTransform)) { - return; - } - - // Calculate the cumulative transforms between the subtree root with the - // old transform and the current transform. - Matrix oldCumulativeTransform = ancestorTransform * oldRootTransform; - Matrix newCumulativeTransform = ancestorTransform * newRootTransform; - if (newCumulativeTransform.IsSingular()) { - return; - } - Matrix newCumulativeTransformInverse = newCumulativeTransform; - newCumulativeTransformInverse.Invert(); - - // Now work out the translation necessary to make sure the layer doesn't - // move given the new sub-tree root transform. - Matrix layerTransform; - if (!GetBaseTransform2D(aLayer, &layerTransform)) { - return; - } - - // Calculate any offset necessary, in previous transform sub-tree root - // space. This is used to make sure fixed position content respects - // content document fixed position margins. - LayerPoint offsetInOldSubtreeLayerSpace = GetLayerFixedMarginsOffset(aLayer, aFixedLayerMargins); - - // Add the above offset to the anchor point so we can offset the layer by - // and amount that's specified in old subtree layer space. - const LayerPoint& anchorInOldSubtreeLayerSpace = aLayer->GetFixedPositionAnchor(); - LayerPoint offsetAnchorInOldSubtreeLayerSpace = anchorInOldSubtreeLayerSpace + offsetInOldSubtreeLayerSpace; - - // Add the local layer transform to the two points to make the equation - // below this section more convenient. - Point anchor(anchorInOldSubtreeLayerSpace.x, anchorInOldSubtreeLayerSpace.y); - Point offsetAnchor(offsetAnchorInOldSubtreeLayerSpace.x, offsetAnchorInOldSubtreeLayerSpace.y); - Point locallyTransformedAnchor = layerTransform * anchor; - Point locallyTransformedOffsetAnchor = layerTransform * offsetAnchor; - - // Transforming the locallyTransformedAnchor by oldCumulativeTransform - // returns the layer's anchor point relative to the parent of - // aTransformedSubtreeRoot, before the new transform was applied. - // Then, applying newCumulativeTransformInverse maps that point relative - // to the layer's parent, which is the same coordinate space as - // locallyTransformedAnchor again, allowing us to subtract them and find - // out the offset necessary to make sure the layer stays stationary. - Point oldAnchorPositionInNewSpace = - newCumulativeTransformInverse * (oldCumulativeTransform * locallyTransformedOffsetAnchor); - Point translation = oldAnchorPositionInNewSpace - locallyTransformedAnchor; - - if (aLayer->GetIsStickyPosition()) { - // For sticky positioned layers, the difference between the two rectangles - // defines a pair of translation intervals in each dimension through which - // the layer should not move relative to the scroll container. To - // accomplish this, we limit each dimension of the |translation| to that - // part of it which overlaps those intervals. - const LayerRect& stickyOuter = aLayer->GetStickyScrollRangeOuter(); - const LayerRect& stickyInner = aLayer->GetStickyScrollRangeInner(); - - translation.y = IntervalOverlap(translation.y, stickyOuter.y, stickyOuter.YMost()) - - IntervalOverlap(translation.y, stickyInner.y, stickyInner.YMost()); - translation.x = IntervalOverlap(translation.x, stickyOuter.x, stickyOuter.XMost()) - - IntervalOverlap(translation.x, stickyInner.x, stickyInner.XMost()); - } - - // Finally, apply the 2D translation to the layer transform. - TranslateShadowLayer2D(aLayer, ThebesPoint(translation)); - - // The transform has now been applied, so there's no need to iterate over - // child layers. return; } - // Fixed layers are relative to their nearest scrollable layer, so when we - // encounter a scrollable layer, bail. ApplyAsyncContentTransformToTree will - // have already recursed on this layer and called AlignFixedAndStickyLayers - // on it with its own transforms. - if (aLayer->GetFrameMetrics().IsScrollable() && - aLayer != aTransformedSubtreeRoot) { + // Insert a translation so that the position of the anchor point is the same + // before and after the change to the transform of aTransformedSubtreeRoot. + // This currently only works for fixed layers with 2D transforms. + + // Accumulate the transforms between this layer and the subtree root layer. + Matrix ancestorTransform; + if (!AccumulateLayerTransforms2D(aLayer->GetParent(), aTransformedSubtreeRoot, + ancestorTransform)) { return; } - for (Layer* child = aLayer->GetFirstChild(); - child; child = child->GetNextSibling()) { - AlignFixedAndStickyLayers(child, aTransformedSubtreeRoot, - aPreviousTransformForRoot, - aCurrentTransformForRoot, aFixedLayerMargins); + Matrix oldRootTransform; + Matrix newRootTransform; + if (!aPreviousTransformForRoot.Is2D(&oldRootTransform) || + !aCurrentTransformForRoot.Is2D(&newRootTransform)) { + return; } + + // Calculate the cumulative transforms between the subtree root with the + // old transform and the current transform. + Matrix oldCumulativeTransform = ancestorTransform * oldRootTransform; + Matrix newCumulativeTransform = ancestorTransform * newRootTransform; + if (newCumulativeTransform.IsSingular()) { + return; + } + Matrix newCumulativeTransformInverse = newCumulativeTransform; + newCumulativeTransformInverse.Invert(); + + // Now work out the translation necessary to make sure the layer doesn't + // move given the new sub-tree root transform. + Matrix layerTransform; + if (!GetBaseTransform2D(aLayer, &layerTransform)) { + return; + } + + // Calculate any offset necessary, in previous transform sub-tree root + // space. This is used to make sure fixed position content respects + // content document fixed position margins. + LayerPoint offsetInOldSubtreeLayerSpace = GetLayerFixedMarginsOffset(aLayer, aFixedLayerMargins); + + // Add the above offset to the anchor point so we can offset the layer by + // and amount that's specified in old subtree layer space. + const LayerPoint& anchorInOldSubtreeLayerSpace = aLayer->GetFixedPositionAnchor(); + LayerPoint offsetAnchorInOldSubtreeLayerSpace = anchorInOldSubtreeLayerSpace + offsetInOldSubtreeLayerSpace; + + // Add the local layer transform to the two points to make the equation + // below this section more convenient. + Point anchor(anchorInOldSubtreeLayerSpace.x, anchorInOldSubtreeLayerSpace.y); + Point offsetAnchor(offsetAnchorInOldSubtreeLayerSpace.x, offsetAnchorInOldSubtreeLayerSpace.y); + Point locallyTransformedAnchor = layerTransform * anchor; + Point locallyTransformedOffsetAnchor = layerTransform * offsetAnchor; + + // Transforming the locallyTransformedAnchor by oldCumulativeTransform + // returns the layer's anchor point relative to the parent of + // aTransformedSubtreeRoot, before the new transform was applied. + // Then, applying newCumulativeTransformInverse maps that point relative + // to the layer's parent, which is the same coordinate space as + // locallyTransformedAnchor again, allowing us to subtract them and find + // out the offset necessary to make sure the layer stays stationary. + Point oldAnchorPositionInNewSpace = + newCumulativeTransformInverse * (oldCumulativeTransform * locallyTransformedOffsetAnchor); + Point translation = oldAnchorPositionInNewSpace - locallyTransformedAnchor; + + if (aLayer->GetIsStickyPosition()) { + // For sticky positioned layers, the difference between the two rectangles + // defines a pair of translation intervals in each dimension through which + // the layer should not move relative to the scroll container. To + // accomplish this, we limit each dimension of the |translation| to that + // part of it which overlaps those intervals. + const LayerRect& stickyOuter = aLayer->GetStickyScrollRangeOuter(); + const LayerRect& stickyInner = aLayer->GetStickyScrollRangeInner(); + + translation.y = IntervalOverlap(translation.y, stickyOuter.y, stickyOuter.YMost()) - + IntervalOverlap(translation.y, stickyInner.y, stickyInner.YMost()); + translation.x = IntervalOverlap(translation.x, stickyOuter.x, stickyOuter.XMost()) - + IntervalOverlap(translation.x, stickyInner.x, stickyInner.XMost()); + } + + // Finally, apply the 2D translation to the layer transform. + TranslateShadowLayer2D(aLayer, ThebesPoint(translation)); } static void From 656c80c3062555692fbd4a3e87fb2fbc90b98e56 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 27 Aug 2014 22:13:40 -0400 Subject: [PATCH 35/60] Bug 1055760 - Don't pass an out-ref for a parameter that doesn't change. r=botond --- gfx/layers/apz/src/APZCTreeManager.cpp | 6 +++--- gfx/layers/apz/src/APZCTreeManager.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index 4125e712569e..57a687e0cfc1 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -211,7 +211,7 @@ APZCTreeManager::PrepareAPZCForLayer(const Layer* aLayer, const gfx::Matrix4x4& aAncestorTransform, const nsIntRegion& aObscured, AsyncPanZoomController*& aOutParent, - AsyncPanZoomController*& aOutNextSibling, + AsyncPanZoomController* aNextSibling, TreeBuildingState& aState) { if (!aMetrics.IsScrollable()) { @@ -308,8 +308,8 @@ APZCTreeManager::PrepareAPZCForLayer(const Layer* aLayer, << "\t" << aLayer->GetContentDescription(); // Bind the APZC instance into the tree of APZCs - if (aOutNextSibling) { - aOutNextSibling->SetPrevSibling(apzc); + if (aNextSibling) { + aNextSibling->SetPrevSibling(apzc); } else if (aOutParent) { aOutParent->SetLastChild(apzc); } else { diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h index 4a418ce76360..a2f3beb25704 100644 --- a/gfx/layers/apz/src/APZCTreeManager.h +++ b/gfx/layers/apz/src/APZCTreeManager.h @@ -384,7 +384,7 @@ private: const gfx::Matrix4x4& aAncestorTransform, const nsIntRegion& aObscured, AsyncPanZoomController*& aOutParent, - AsyncPanZoomController*& aOutNextSibling, + AsyncPanZoomController* aNextSibling, TreeBuildingState& aState); /** From 23cccb3b33aaa5104ab7ab54de80e7a29267b2ae Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 27 Aug 2014 22:13:40 -0400 Subject: [PATCH 36/60] Bug 1055760 - Modify Layers API to expose multiple FrameMetrics and APZCs per layer. r=roc,BenWa --- gfx/layers/Layers.cpp | 34 +++++++++++++---- gfx/layers/Layers.h | 57 ++++++++++++++++++++++++----- gfx/layers/ipc/LayersMessages.ipdlh | 2 +- gfx/layers/ipc/ShadowLayers.cpp | 2 +- 4 files changed, 76 insertions(+), 19 deletions(-) diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 34cc28d3f1cd..c00822baf8d7 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -448,20 +448,28 @@ Layer::SetAnimations(const AnimationArray& aAnimations) } void -Layer::SetAsyncPanZoomController(AsyncPanZoomController *controller) +Layer::SetAsyncPanZoomController(uint32_t aIndex, AsyncPanZoomController *controller) { - mAPZC = controller; + MOZ_ASSERT(aIndex < GetFrameMetricsCount()); + mApzcs[aIndex] = controller; } AsyncPanZoomController* -Layer::GetAsyncPanZoomController() const +Layer::GetAsyncPanZoomController(uint32_t aIndex) const { + MOZ_ASSERT(aIndex < GetFrameMetricsCount()); #ifdef DEBUG - if (mAPZC) { - MOZ_ASSERT(GetFrameMetrics().IsScrollable()); + if (mApzcs[aIndex]) { + MOZ_ASSERT(GetFrameMetrics(aIndex).IsScrollable()); } #endif - return mAPZC; + return mApzcs[aIndex]; +} + +void +Layer::FrameMetricsChanged() +{ + mApzcs.SetLength(GetFrameMetricsCount()); } void @@ -662,6 +670,13 @@ Layer::CalculateScissorRect(const RenderTargetIntRect& aCurrentScissorRect, return currentClip.Intersect(scissor); } +const FrameMetrics& +Layer::GetFrameMetrics(uint32_t aIndex) const +{ + MOZ_ASSERT(aIndex < GetFrameMetricsCount()); + return mFrameMetrics[aIndex]; +} + const Matrix4x4 Layer::GetTransform() const { @@ -1460,8 +1475,11 @@ Layer::PrintInfo(std::stringstream& aStream, const char* aPrefix) if (mMaskLayer) { aStream << nsPrintfCString(" [mMaskLayer=%p]", mMaskLayer.get()).get(); } - if (!mFrameMetrics.IsDefault()) { - AppendToString(aStream, mFrameMetrics, " [metrics=", "]"); + for (uint32_t i = 0; i < mFrameMetrics.Length(); i++) { + if (!mFrameMetrics[i].IsDefault()) { + aStream << nsPrintfCString(" [metrics%d=", i).get(); + AppendToString(aStream, mFrameMetrics[i], "", "]"); + } } } diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 251177cbad27..36423c2b4aeb 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -818,13 +818,43 @@ public: /** * CONSTRUCTION PHASE ONLY * Set the (sub)document metrics used to render the Layer subtree - * rooted at this. + * rooted at this. Note that a layer may have multiple FrameMetrics + * objects; calling this function will remove all of them and replace + * them with the provided FrameMetrics. See the documentation for + * SetFrameMetrics(const nsTArray&) for more details. */ void SetFrameMetrics(const FrameMetrics& aFrameMetrics) { - if (mFrameMetrics != aFrameMetrics) { + if (mFrameMetrics.Length() != 1 || mFrameMetrics[0] != aFrameMetrics) { MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) FrameMetrics", this)); - mFrameMetrics = aFrameMetrics; + mFrameMetrics.ReplaceElementsAt(0, mFrameMetrics.Length(), aFrameMetrics); + FrameMetricsChanged(); + Mutated(); + } + } + + /** + * CONSTRUCTION PHASE ONLY + * Set the (sub)document metrics used to render the Layer subtree + * rooted at this. There might be multiple metrics on this layer + * because the layer may, for example, be contained inside multiple + * nested scrolling subdocuments. In general a Layer having multiple + * FrameMetrics objects is conceptually equivalent to having a stack + * of ContainerLayers that have been flattened into this Layer. + * (A pointer to additional documentation will arrive in a future patch.) + * + * Note also that there is actually a many-to-many relationship between + * Layers and FrameMetrics, because multiple Layers may have identical + * FrameMetrics objects. This happens when those layers belong to the + * same scrolling subdocument and therefore end up with the same async + * transform when they are scrolled by the APZ code. + */ + void SetFrameMetrics(const nsTArray& aMetricsArray) + { + if (mFrameMetrics != aMetricsArray) { + MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) FrameMetrics", this)); + mFrameMetrics = aMetricsArray; + FrameMetricsChanged(); Mutated(); } } @@ -1157,7 +1187,9 @@ public: const nsIntRect* GetClipRect() { return mUseClipRect ? &mClipRect : nullptr; } uint32_t GetContentFlags() { return mContentFlags; } const nsIntRegion& GetVisibleRegion() const { return mVisibleRegion; } - const FrameMetrics& GetFrameMetrics() const { return mFrameMetrics; } + const FrameMetrics& GetFrameMetrics(uint32_t aIndex) const; + uint32_t GetFrameMetricsCount() const { return mFrameMetrics.Length(); } + const nsTArray& GetAllFrameMetrics() { return mFrameMetrics; } const EventRegions& GetEventRegions() const { return mEventRegions; } ContainerLayer* GetParent() { return mParent; } Layer* GetNextSibling() { return mNextSibling; } @@ -1457,9 +1489,16 @@ public: // These functions allow attaching an AsyncPanZoomController to this layer, // and can be used anytime. - // A layer has an APZC only-if GetFrameMetrics().IsScrollable() - void SetAsyncPanZoomController(AsyncPanZoomController *controller); - AsyncPanZoomController* GetAsyncPanZoomController() const; + // A layer has an APZC at index aIndex only-if GetFrameMetrics(aIndex).IsScrollable(); + // attempting to get an APZC for a non-scrollable metrics will return null. + // The aIndex for these functions must be less than GetFrameMetricsCount(). + void SetAsyncPanZoomController(uint32_t aIndex, AsyncPanZoomController *controller); + AsyncPanZoomController* GetAsyncPanZoomController(uint32_t aIndex) const; + // The FrameMetricsChanged function is used internally to ensure the APZC array length + // matches the frame metrics array length. +private: + void FrameMetricsChanged(); +public: void ApplyPendingUpdatesForThisTransaction(); @@ -1563,7 +1602,7 @@ protected: nsRefPtr mMaskLayer; gfx::UserData mUserData; nsIntRegion mVisibleRegion; - FrameMetrics mFrameMetrics; + nsTArray mFrameMetrics; EventRegions mEventRegions; gfx::Matrix4x4 mTransform; // A mutation of |mTransform| that we've queued to be applied at the @@ -1583,7 +1622,7 @@ protected: nsIntRect mClipRect; nsIntRect mTileSourceRect; nsIntRegion mInvalidRegion; - nsRefPtr mAPZC; + nsTArray > mApzcs; uint32_t mContentFlags; bool mUseClipRect; bool mUseTileSourceRect; diff --git a/gfx/layers/ipc/LayersMessages.ipdlh b/gfx/layers/ipc/LayersMessages.ipdlh index 211088e5816e..0ac7c4fa3244 100644 --- a/gfx/layers/ipc/LayersMessages.ipdlh +++ b/gfx/layers/ipc/LayersMessages.ipdlh @@ -215,7 +215,7 @@ struct CommonLayerAttributes { // Animated colors will only honored for ColorLayers. Animation[] animations; nsIntRegion invalidRegion; - FrameMetrics metrics; + FrameMetrics[] metrics; LayerColor backgroundColor; string contentDescription; }; diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp index 2e9eab3af0c8..a83b6847fa9a 100644 --- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -607,7 +607,7 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray* aReplies, common.maskLayerParent() = nullptr; common.animations() = mutant->GetAnimations(); common.invalidRegion() = mutant->GetInvalidRegion(); - common.metrics() = mutant->GetFrameMetrics(); + common.metrics() = mutant->GetAllFrameMetrics(); common.backgroundColor() = mutant->GetBackgroundColor(); common.contentDescription() = mutant->GetContentDescription(); attrs.specific() = null_t(); From 4e8832c9dddfb987b4fb7e2fef4370f2c10df85f Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 27 Aug 2014 22:13:41 -0400 Subject: [PATCH 37/60] Bug 1055760 - Add a LayerMetricsWrapper and fix up APZCTreeManager FrameMetrics accessing. r=botond,BenWa --- gfx/layers/FrameMetrics.h | 1 + gfx/layers/LayerMetricsWrapper.h | 299 +++++++++++++++++++++++++ gfx/layers/Layers.cpp | 1 + gfx/layers/Layers.h | 3 +- gfx/layers/apz/src/APZCTreeManager.cpp | 39 ++-- gfx/layers/apz/src/APZCTreeManager.h | 6 +- gfx/layers/moz.build | 1 + 7 files changed, 329 insertions(+), 21 deletions(-) create mode 100644 gfx/layers/LayerMetricsWrapper.h diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index b1e9813628c6..bcf5e43b73f6 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -71,6 +71,7 @@ public: static const ViewID NULL_SCROLL_ID; // This container layer does not scroll. static const ViewID START_SCROLL_ID = 2; // This is the ID that scrolling subframes // will begin at. + static const FrameMetrics sNullMetrics; // We often need an empty metrics FrameMetrics() : mCompositionBounds(0, 0, 0, 0) diff --git a/gfx/layers/LayerMetricsWrapper.h b/gfx/layers/LayerMetricsWrapper.h new file mode 100644 index 000000000000..7b705b2f0409 --- /dev/null +++ b/gfx/layers/LayerMetricsWrapper.h @@ -0,0 +1,299 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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/. */ + +#ifndef GFX_LAYERMETRICSWRAPPER_H +#define GFX_LAYERMETRICSWRAPPER_H + +#include "Layers.h" + +namespace mozilla { +namespace layers { + +/** + * A wrapper class around a target Layer with that allows user code to + * walk through the FrameMetrics objects on the layer the same way it + * would walk through a ContainerLayer hierarchy. Consider the following + * layer tree: + * + * +---+ + * | A | + * +---+ + * / | \ + * / | \ + * / | \ + * +---+ +-----+ +---+ + * | B | | C | | D | + * +---+ +-----+ +---+ + * | FMn | + * | . | + * | . | + * | . | + * | FM1 | + * | FM0 | + * +-----+ + * / \ + * / \ + * +---+ +---+ + * | E | | F | + * +---+ +---+ + * + * In this layer tree, there are six layers with A being the root and B,D,E,F + * being leaf nodes. Layer C is in the middle and has n+1 FrameMetrics, labelled + * FM0...FMn. FM0 is the FrameMetrics you get by calling c->GetFrameMetrics(0) + * and FMn is the FrameMetrics you can obtain by calling + * c->GetFrameMetrics(c->GetFrameMetricsCount() - 1). This layer tree is + * conceptually equivalent to this one below: + * + * +---+ + * | A | + * +---+ + * / | \ + * / | \ + * / | \ + * +---+ +-----+ +---+ + * | B | | Cn | | D | + * +---+ +-----+ +---+ + * | + * . + * . + * . + * | + * +-----+ + * | C1 | + * +-----+ + * | + * +-----+ + * | C0 | + * +-----+ + * / \ + * / \ + * +---+ +---+ + * | E | | F | + * +---+ +---+ + * + * In this layer tree, the layer C has been expanded into a stack of container + * layers C1...Cn, where C1 has FrameMetrics FM1 and Cn has FrameMetrics Fn. + * Although in this example C (in the first layer tree) and C0 (in the second + * layer tree) are both ContainerLayers (because they have children), they + * do not have to be. They may just be ThebesLayers or ColorLayers, for example, + * which do not have any children. However, the type of C will always be the + * same as the type of C0. + * + * The LayerMetricsWrapper class allows client code to treat the first layer + * tree as though it were the second. That is, instead of client code having + * to iterate through the FrameMetrics objects directly, it can use a + * LayerMetricsWrapper to encapsulate that aspect of the layer tree and just + * walk the tree as if it were a stack of ContainerLayers. + * + * The functions on this class do different things depending on which + * simulated ContainerLayer is being wrapped. For example, if the + * LayerMetricsWrapper is pretending to be C0, the GetNextSibling() function + * will return null even though the underlying layer C does actually have + * a next sibling. The LayerMetricsWrapper pretending to be Cn will return + * D as the next sibling. + * + * Implementation notes: + * + * The AtTopLayer() and AtBottomLayer() functions in this class refer to + * Cn and C0 in the second layer tree above; that is, they are predicates + * to test if the LayerMetricsWrapper is simulating the topmost or bottommost + * layer, as those will have special behaviour. + * + * It is possible to wrap a nullptr in a LayerMetricsWrapper, in which case + * the IsValid() function will return false. This is required to allow + * LayerMetricsWrapper to be a MOZ_STACK_CLASS (desirable because it is used + * in loops and recursion). + * + * This class purposely does not expose the wrapped layer directly to avoid + * user code from accidentally calling functions directly on it. Instead + * any necessary functions should be wrapped in this class. It does expose + * the wrapped layer as a void* for printf purposes. + * + * The implementation may look like it special-cases mIndex == 0 and/or + * GetFrameMetricsCount() == 0. This is an artifact of the fact that both + * mIndex and GetFrameMetricsCount() are uint32_t and GetFrameMetricsCount() + * can return 0 but mIndex cannot store -1. This seems better than the + * alternative of making mIndex a int32_t that can store -1, but then having + * to cast to uint32_t all over the place. + */ +class MOZ_STACK_CLASS LayerMetricsWrapper { +public: + LayerMetricsWrapper() + : mLayer(nullptr) + , mIndex(0) + { + } + + explicit LayerMetricsWrapper(Layer* aRoot) + : mLayer(aRoot) + , mIndex(0) + { + if (!mLayer) { + return; + } + + mIndex = mLayer->GetFrameMetricsCount(); + if (mIndex > 0) { + mIndex--; + } + } + + explicit LayerMetricsWrapper(Layer* aLayer, uint32_t aMetricsIndex) + : mLayer(aLayer) + , mIndex(aMetricsIndex) + { + MOZ_ASSERT(mLayer); + MOZ_ASSERT(mIndex == 0 || mIndex < mLayer->GetFrameMetricsCount()); + } + + bool IsValid() const + { + return mLayer != nullptr; + } + + MOZ_EXPLICIT_CONVERSION operator bool() const + { + return IsValid(); + } + + LayerMetricsWrapper GetLastChild() const + { + MOZ_ASSERT(IsValid()); + + if (!AtBottomLayer()) { + return LayerMetricsWrapper(mLayer, mIndex - 1); + } + return LayerMetricsWrapper(mLayer->GetLastChild()); + } + + LayerMetricsWrapper GetPrevSibling() const + { + MOZ_ASSERT(IsValid()); + + if (AtTopLayer()) { + return LayerMetricsWrapper(mLayer->GetPrevSibling()); + } + return LayerMetricsWrapper(nullptr); + } + + const FrameMetrics& Metrics() const + { + MOZ_ASSERT(IsValid()); + + if (mIndex >= mLayer->GetFrameMetricsCount()) { + return FrameMetrics::sNullMetrics; + } + return mLayer->GetFrameMetrics(mIndex); + } + + AsyncPanZoomController* GetApzc() const + { + MOZ_ASSERT(IsValid()); + + if (mIndex >= mLayer->GetFrameMetricsCount()) { + return nullptr; + } + return mLayer->GetAsyncPanZoomController(mIndex); + } + + void SetApzc(AsyncPanZoomController* aApzc) const + { + MOZ_ASSERT(IsValid()); + + if (mLayer->GetFrameMetricsCount() == 0) { + MOZ_ASSERT(mIndex == 0); + MOZ_ASSERT(aApzc == nullptr); + return; + } + MOZ_ASSERT(mIndex < mLayer->GetFrameMetricsCount()); + mLayer->SetAsyncPanZoomController(mIndex, aApzc); + } + + const char* Name() const + { + MOZ_ASSERT(IsValid()); + + if (AtBottomLayer()) { + return mLayer->Name(); + } + return "DummyContainerLayer"; + } + + gfx::Matrix4x4 GetTransform() const + { + MOZ_ASSERT(IsValid()); + + if (AtBottomLayer()) { + return mLayer->GetTransform(); + } + return gfx::Matrix4x4(); + } + + RefLayer* AsRefLayer() const + { + MOZ_ASSERT(IsValid()); + + if (AtBottomLayer()) { + return mLayer->AsRefLayer(); + } + return nullptr; + } + + nsIntRegion GetVisibleRegion() const + { + MOZ_ASSERT(IsValid()); + + if (AtBottomLayer()) { + return mLayer->GetVisibleRegion(); + } + nsIntRegion region = mLayer->GetVisibleRegion(); + region.Transform(gfx::To3DMatrix(mLayer->GetTransform())); + return region; + } + + const nsIntRect* GetClipRect() const + { + MOZ_ASSERT(IsValid()); + + return mLayer->GetClipRect(); + } + + const std::string& GetContentDescription() const + { + MOZ_ASSERT(IsValid()); + + return mLayer->GetContentDescription(); + } + + // Expose an opaque pointer to the layer. Mostly used for printf + // purposes. This is not intended to be a general-purpose accessor + // for the underlying layer. + const void* GetLayer() const + { + MOZ_ASSERT(IsValid()); + + return (void*)mLayer; + } + +private: + bool AtBottomLayer() const + { + return mIndex == 0; + } + + bool AtTopLayer() const + { + return mLayer->GetFrameMetricsCount() == 0 || mIndex == mLayer->GetFrameMetricsCount() - 1; + } + +private: + Layer* mLayer; + uint32_t mIndex; +}; + +} +} + +#endif /* GFX_LAYERMETRICSWRAPPER_H */ diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index c00822baf8d7..dc4e8869d7d5 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -47,6 +47,7 @@ FILEOrDefault(FILE* aFile) typedef FrameMetrics::ViewID ViewID; const ViewID FrameMetrics::NULL_SCROLL_ID = 0; +const FrameMetrics FrameMetrics::sNullMetrics; using namespace mozilla::gfx; diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 36423c2b4aeb..3acd11226bb2 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -841,7 +841,8 @@ public: * nested scrolling subdocuments. In general a Layer having multiple * FrameMetrics objects is conceptually equivalent to having a stack * of ContainerLayers that have been flattened into this Layer. - * (A pointer to additional documentation will arrive in a future patch.) + * See the documentation in LayerMetricsWrapper.h for a more detailed + * explanation of this conceptual equivalence. * * Note also that there is actually a many-to-many relationship between * Layers and FrameMetrics, because multiple Layers may have identical diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index 57a687e0cfc1..2d8ca4991613 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -12,6 +12,7 @@ #include "mozilla/gfx/Point.h" // for Point #include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform #include "mozilla/layers/AsyncPanZoomController.h" +#include "mozilla/layers/LayerMetricsWrapper.h" #include "mozilla/MouseEvents.h" #include "mozilla/mozalloc.h" // for operator new #include "mozilla/TouchEvents.h" @@ -160,7 +161,8 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor, if (aRoot) { mApzcTreeLog << "[start]\n"; - UpdatePanZoomControllerTree(state, aRoot, + LayerMetricsWrapper root(aRoot); + UpdatePanZoomControllerTree(state, root, // aCompositor is null in gtest scenarios aCompositor ? aCompositor->RootLayerTreeId() : 0, Matrix4x4(), nullptr, nullptr, nsIntRegion()); @@ -205,7 +207,7 @@ ComputeTouchSensitiveRegion(GeckoContentController* aController, } AsyncPanZoomController* -APZCTreeManager::PrepareAPZCForLayer(const Layer* aLayer, +APZCTreeManager::PrepareAPZCForLayer(const LayerMetricsWrapper& aLayer, const FrameMetrics& aMetrics, uint64_t aLayersId, const gfx::Matrix4x4& aAncestorTransform, @@ -237,13 +239,13 @@ APZCTreeManager::PrepareAPZCForLayer(const Layer* aLayer, if (!insertResult.second) { apzc = insertResult.first->second; } - APZCTM_LOG("Found APZC %p for layer %p with identifiers %lld %lld\n", apzc, aLayer, guid.mLayersId, guid.mScrollId); + APZCTM_LOG("Found APZC %p for layer %p with identifiers %lld %lld\n", apzc, aLayer.GetLayer(), guid.mLayersId, guid.mScrollId); // If we haven't encountered a layer already with the same metrics, then we need to // do the full reuse-or-make-an-APZC algorithm, which is contained inside the block // below. if (apzc == nullptr) { - apzc = aLayer->GetAsyncPanZoomController(); + apzc = aLayer.GetApzc(); // If the content represented by the scrollable layer has changed (which may // be possible because of DLBI heuristics) then we don't want to keep using @@ -290,7 +292,7 @@ APZCTreeManager::PrepareAPZCForLayer(const Layer* aLayer, apzc->SetPrevSibling(nullptr); apzc->SetLastChild(nullptr); } - APZCTM_LOG("Using APZC %p for layer %p with identifiers %lld %lld\n", apzc, aLayer, aLayersId, aMetrics.GetScrollId()); + APZCTM_LOG("Using APZC %p for layer %p with identifiers %lld %lld\n", apzc, aLayer.GetLayer(), aLayersId, aMetrics.GetScrollId()); apzc->NotifyLayersUpdated(aMetrics, aState.mIsFirstPaint && (aLayersId == aState.mOriginatingLayersId)); @@ -303,9 +305,9 @@ APZCTreeManager::PrepareAPZCForLayer(const Layer* aLayer, mApzcTreeLog << "APZC " << guid << "\tcb=" << aMetrics.mCompositionBounds << "\tsr=" << aMetrics.mScrollableRect - << (aLayer->GetVisibleRegion().IsEmpty() ? "\tscrollinfo" : "") + << (aLayer.GetVisibleRegion().IsEmpty() ? "\tscrollinfo" : "") << (apzc->HasScrollgrab() ? "\tscrollgrab" : "") - << "\t" << aLayer->GetContentDescription(); + << "\t" << aLayer.GetContentDescription(); // Bind the APZC instance into the tree of APZCs if (aNextSibling) { @@ -376,7 +378,8 @@ APZCTreeManager::PrepareAPZCForLayer(const Layer* aLayer, AsyncPanZoomController* APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState, - Layer* aLayer, uint64_t aLayersId, + const LayerMetricsWrapper& aLayer, + uint64_t aLayersId, const gfx::Matrix4x4& aAncestorTransform, AsyncPanZoomController* aParent, AsyncPanZoomController* aNextSibling, @@ -384,12 +387,12 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState, { mTreeLock.AssertCurrentThreadOwns(); - mApzcTreeLog << aLayer->Name() << '\t'; + mApzcTreeLog << aLayer.Name() << '\t'; AsyncPanZoomController* apzc = PrepareAPZCForLayer(aLayer, - aLayer->GetFrameMetrics(), aLayersId, aAncestorTransform, + aLayer.Metrics(), aLayersId, aAncestorTransform, aObscured, aParent, aNextSibling, aState); - aLayer->SetAsyncPanZoomController(apzc); + aLayer.SetApzc(apzc); mApzcTreeLog << '\n'; @@ -400,13 +403,13 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState, // transform to layer L when we recurse into the children below. If we are at a layer // with an APZC, such as P, then we reset the ancestorTransform to just PC, to start // the new accumulation as we go down. - Matrix4x4 transform = aLayer->GetTransform(); + Matrix4x4 transform = aLayer.GetTransform(); Matrix4x4 ancestorTransform = transform; if (!apzc) { ancestorTransform = ancestorTransform * aAncestorTransform; } - uint64_t childLayersId = (aLayer->AsRefLayer() ? aLayer->AsRefLayer()->GetReferentId() : aLayersId); + uint64_t childLayersId = (aLayer.AsRefLayer() ? aLayer.AsRefLayer()->GetReferentId() : aLayersId); nsIntRegion obscured; if (aLayersId == childLayersId) { @@ -428,7 +431,7 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState, // If there's no APZC at this level, any APZCs for our child layers will // have our siblings as siblings. AsyncPanZoomController* next = apzc ? nullptr : aNextSibling; - for (Layer* child = aLayer->GetLastChild(); child; child = child->GetPrevSibling()) { + for (LayerMetricsWrapper child = aLayer.GetLastChild(); child; child = child.GetPrevSibling()) { gfx::TreeAutoIndent indent(mApzcTreeLog); next = UpdatePanZoomControllerTree(aState, child, childLayersId, ancestorTransform, aParent, next, @@ -436,10 +439,10 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState, // Each layer obscures its previous siblings, so we augment the obscured // region as we loop backwards through the children. - nsIntRegion childRegion = child->GetVisibleRegion(); - childRegion.Transform(gfx::To3DMatrix(child->GetTransform())); - if (child->GetClipRect()) { - childRegion.AndWith(*child->GetClipRect()); + nsIntRegion childRegion = child.GetVisibleRegion(); + childRegion.Transform(gfx::To3DMatrix(child.GetTransform())); + if (child.GetClipRect()) { + childRegion.AndWith(*child.GetClipRect()); } obscured.OrWith(childRegion); diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h index a2f3beb25704..01d02410cd2c 100644 --- a/gfx/layers/apz/src/APZCTreeManager.h +++ b/gfx/layers/apz/src/APZCTreeManager.h @@ -44,6 +44,7 @@ class AsyncPanZoomController; class CompositorParent; class APZPaintLogHelper; class OverscrollHandoffChain; +class LayerMetricsWrapper; /** * ****************** NOTE ON LOCK ORDERING IN APZ ************************** @@ -378,7 +379,7 @@ private: void UpdateZoomConstraintsRecursively(AsyncPanZoomController* aApzc, const ZoomConstraints& aConstraints); - AsyncPanZoomController* PrepareAPZCForLayer(const Layer* aLayer, + AsyncPanZoomController* PrepareAPZCForLayer(const LayerMetricsWrapper& aLayer, const FrameMetrics& aMetrics, uint64_t aLayersId, const gfx::Matrix4x4& aAncestorTransform, @@ -397,7 +398,8 @@ private: * code. */ AsyncPanZoomController* UpdatePanZoomControllerTree(TreeBuildingState& aState, - Layer* aLayer, uint64_t aLayersId, + const LayerMetricsWrapper& aLayer, + uint64_t aLayersId, const gfx::Matrix4x4& aAncestorTransform, AsyncPanZoomController* aParent, AsyncPanZoomController* aNextSibling, diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index 85b25b9a90f4..285c0c050f0c 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -163,6 +163,7 @@ EXPORTS.mozilla.layers += [ 'ipc/SharedBufferManagerParent.h', 'ipc/SharedPlanarYCbCrImage.h', 'ipc/SharedRGBImage.h', + 'LayerMetricsWrapper.h', 'LayersTypes.h', 'opengl/CompositingRenderTargetOGL.h', 'opengl/CompositorOGL.h', From baed559ce33325118837a6cc003de57d68a29357 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 27 Aug 2014 22:13:41 -0400 Subject: [PATCH 38/60] Bug 1055760 - Update tiling code to use LayerMetricsWrapper. r=botond,BenWa --- gfx/layers/LayerMetricsWrapper.h | 81 ++++++++++++++++++- gfx/layers/Layers.cpp | 47 ++++++----- gfx/layers/Layers.h | 4 +- gfx/layers/client/ClientLayerManager.cpp | 5 +- gfx/layers/client/ClientTiledThebesLayer.cpp | 43 ++++++---- gfx/layers/client/ClientTiledThebesLayer.h | 4 +- gfx/layers/client/TiledContentClient.cpp | 25 +++--- gfx/layers/client/TiledContentClient.h | 2 +- .../composite/AsyncCompositionManager.cpp | 11 ++- .../composite/LayerManagerComposite.cpp | 7 +- 10 files changed, 165 insertions(+), 64 deletions(-) diff --git a/gfx/layers/LayerMetricsWrapper.h b/gfx/layers/LayerMetricsWrapper.h index 7b705b2f0409..6e8771b7e4cd 100644 --- a/gfx/layers/LayerMetricsWrapper.h +++ b/gfx/layers/LayerMetricsWrapper.h @@ -120,13 +120,18 @@ namespace layers { */ class MOZ_STACK_CLASS LayerMetricsWrapper { public: + enum StartAt { + TOP, + BOTTOM, + }; + LayerMetricsWrapper() : mLayer(nullptr) , mIndex(0) { } - explicit LayerMetricsWrapper(Layer* aRoot) + explicit LayerMetricsWrapper(Layer* aRoot, StartAt aStart = StartAt::TOP) : mLayer(aRoot) , mIndex(0) { @@ -134,9 +139,19 @@ public: return; } - mIndex = mLayer->GetFrameMetricsCount(); - if (mIndex > 0) { - mIndex--; + switch (aStart) { + case StartAt::TOP: + mIndex = mLayer->GetFrameMetricsCount(); + if (mIndex > 0) { + mIndex--; + } + break; + case StartAt::BOTTOM: + mIndex = 0; + break; + default: + MOZ_ASSERT_UNREACHABLE("Unknown startAt value"); + break; } } @@ -158,6 +173,29 @@ public: return IsValid(); } + LayerMetricsWrapper GetParent() const + { + MOZ_ASSERT(IsValid()); + + if (!AtTopLayer()) { + return LayerMetricsWrapper(mLayer, mIndex + 1); + } + if (mLayer->GetParent()) { + return LayerMetricsWrapper(mLayer->GetParent(), StartAt::BOTTOM); + } + return LayerMetricsWrapper(nullptr); + } + + LayerMetricsWrapper GetFirstChild() const + { + MOZ_ASSERT(IsValid()); + + if (!AtBottomLayer()) { + return LayerMetricsWrapper(mLayer, mIndex - 1); + } + return LayerMetricsWrapper(mLayer->GetFirstChild()); + } + LayerMetricsWrapper GetLastChild() const { MOZ_ASSERT(IsValid()); @@ -178,6 +216,16 @@ public: return LayerMetricsWrapper(nullptr); } + LayerMetricsWrapper GetNextSibling() const + { + MOZ_ASSERT(IsValid()); + + if (AtTopLayer()) { + return LayerMetricsWrapper(mLayer->GetNextSibling()); + } + return LayerMetricsWrapper(nullptr); + } + const FrameMetrics& Metrics() const { MOZ_ASSERT(IsValid()); @@ -221,6 +269,13 @@ public: return "DummyContainerLayer"; } + LayerManager* Manager() const + { + MOZ_ASSERT(IsValid()); + + return mLayer->Manager(); + } + gfx::Matrix4x4 GetTransform() const { MOZ_ASSERT(IsValid()); @@ -231,6 +286,13 @@ public: return gfx::Matrix4x4(); } + const gfx::Matrix4x4& GetEffectiveTransform() const + { + MOZ_ASSERT(IsValid()); + + return mLayer->GetEffectiveTransform(); + } + RefLayer* AsRefLayer() const { MOZ_ASSERT(IsValid()); @@ -277,6 +339,17 @@ public: return (void*)mLayer; } + bool operator==(const LayerMetricsWrapper& aOther) const + { + return mLayer == aOther.mLayer + && mIndex == aOther.mIndex; + } + + bool operator!=(const LayerMetricsWrapper& aOther) const + { + return !(*this == aOther); + } + private: bool AtBottomLayer() const { diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index dc4e8869d7d5..521c03f4cee8 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -27,6 +27,7 @@ #include "mozilla/layers/Compositor.h" // for Compositor #include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/LayerManagerComposite.h" // for LayerComposite +#include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper #include "mozilla/layers/LayersMessages.h" // for TransformFunction, etc #include "nsAString.h" #include "nsCSSValue.h" // for nsCSSValue::Array, etc @@ -53,34 +54,32 @@ using namespace mozilla::gfx; //-------------------------------------------------- // LayerManager -Layer* +LayerMetricsWrapper LayerManager::GetPrimaryScrollableLayer() { if (!mRoot) { - return nullptr; + return LayerMetricsWrapper(); } - nsTArray queue; - queue.AppendElement(mRoot); + nsTArray queue; + queue.AppendElement(LayerMetricsWrapper(mRoot)); while (queue.Length()) { - Layer* layer = queue[0]; + LayerMetricsWrapper layer = queue[0]; queue.RemoveElementAt(0); - const FrameMetrics& frameMetrics = layer->GetFrameMetrics(); + const FrameMetrics& frameMetrics = layer.Metrics(); if (frameMetrics.IsScrollable()) { return layer; } - if (ContainerLayer* containerLayer = layer->AsContainerLayer()) { - Layer* child = containerLayer->GetFirstChild(); - while (child) { - queue.AppendElement(child); - child = child->GetNextSibling(); - } + LayerMetricsWrapper child = layer.GetFirstChild(); + while (child) { + queue.AppendElement(child); + child = child.GetNextSibling(); } } - return mRoot; + return LayerMetricsWrapper(mRoot); } void @@ -96,18 +95,13 @@ LayerManager::GetScrollableLayers(nsTArray& aArray) Layer* layer = queue.LastElement(); queue.RemoveElementAt(queue.Length() - 1); - const FrameMetrics& frameMetrics = layer->GetFrameMetrics(); - if (frameMetrics.IsScrollable()) { + if (layer->HasScrollableFrameMetrics()) { aArray.AppendElement(layer); continue; } - if (ContainerLayer* containerLayer = layer->AsContainerLayer()) { - Layer* child = containerLayer->GetFirstChild(); - while (child) { - queue.AppendElement(child); - child = child->GetNextSibling(); - } + for (Layer* child = layer->GetFirstChild(); child; child = child->GetNextSibling()) { + queue.AppendElement(child); } } } @@ -678,6 +672,17 @@ Layer::GetFrameMetrics(uint32_t aIndex) const return mFrameMetrics[aIndex]; } +bool +Layer::HasScrollableFrameMetrics() const +{ + for (uint32_t i = 0; i < GetFrameMetricsCount(); i++) { + if (GetFrameMetrics(i).IsScrollable()) { + return true; + } + } + return false; +} + const Matrix4x4 Layer::GetTransform() const { diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 3acd11226bb2..0719fc7e4a63 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -78,6 +78,7 @@ class AsyncPanZoomController; class ClientLayerManager; class CommonLayerAttributes; class Layer; +class LayerMetricsWrapper; class ThebesLayer; class ContainerLayer; class ImageLayer; @@ -339,7 +340,7 @@ public: * scrollable layer. * Can be called any time. */ - Layer* GetPrimaryScrollableLayer(); + LayerMetricsWrapper GetPrimaryScrollableLayer(); /** * Returns a list of all descendant layers for which @@ -1191,6 +1192,7 @@ public: const FrameMetrics& GetFrameMetrics(uint32_t aIndex) const; uint32_t GetFrameMetricsCount() const { return mFrameMetrics.Length(); } const nsTArray& GetAllFrameMetrics() { return mFrameMetrics; } + bool HasScrollableFrameMetrics() const; const EventRegions& GetEventRegions() const { return mEventRegions; } ContainerLayer* GetParent() { return mParent; } Layer* GetNextSibling() { return mNextSibling; } diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index d18db48c54bd..bbb58a5fbcbc 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -32,6 +32,7 @@ #include "gfxPrefs.h" #ifdef MOZ_WIDGET_ANDROID #include "AndroidBridge.h" +#include "LayerMetricsWrapper.h" #endif namespace mozilla { @@ -641,9 +642,9 @@ ClientLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, bool aDrawingCritical) { #ifdef MOZ_WIDGET_ANDROID - Layer* primaryScrollable = GetPrimaryScrollableLayer(); + const LayerMetricsWrapper& primaryScrollable = GetPrimaryScrollableLayer(); if (primaryScrollable) { - const FrameMetrics& metrics = primaryScrollable->GetFrameMetrics(); + const FrameMetrics& metrics = primaryScrollable.Metrics(); // This is derived from the code in // gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree. diff --git a/gfx/layers/client/ClientTiledThebesLayer.cpp b/gfx/layers/client/ClientTiledThebesLayer.cpp index ee40a0d44775..baf5ec26c654 100644 --- a/gfx/layers/client/ClientTiledThebesLayer.cpp +++ b/gfx/layers/client/ClientTiledThebesLayer.cpp @@ -13,6 +13,7 @@ #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/gfx/BaseSize.h" // for BaseSize #include "mozilla/gfx/Rect.h" // for Rect, RectTyped +#include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper #include "mozilla/layers/LayersMessages.h" #include "mozilla/mozalloc.h" // for operator delete, etc #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc @@ -63,28 +64,30 @@ ApplyParentLayerToLayerTransform(const gfx::Matrix4x4& aTransform, const ParentL } static gfx::Matrix4x4 -GetTransformToAncestorsParentLayer(Layer* aStart, Layer* aAncestor) +GetTransformToAncestorsParentLayer(Layer* aStart, const LayerMetricsWrapper& aAncestor) { gfx::Matrix4x4 transform; - Layer* ancestorParent = aAncestor->GetParent(); - for (Layer* iter = aStart; iter != ancestorParent; iter = iter->GetParent()) { - transform = transform * iter->GetTransform(); + const LayerMetricsWrapper& ancestorParent = aAncestor.GetParent(); + for (LayerMetricsWrapper iter(aStart, LayerMetricsWrapper::StartAt::BOTTOM); + ancestorParent ? iter != ancestorParent : iter.IsValid(); + iter = iter.GetParent()) { + transform = transform * iter.GetTransform(); // If the layer has a non-transient async transform then we need to apply it here // because it will get applied by the APZ in the compositor as well - const FrameMetrics& metrics = iter->GetFrameMetrics(); + const FrameMetrics& metrics = iter.Metrics(); transform = transform * gfx::Matrix4x4().Scale(metrics.mResolution.scale, metrics.mResolution.scale, 1.f); } return transform; } void -ClientTiledThebesLayer::GetAncestorLayers(Layer** aOutScrollAncestor, - Layer** aOutDisplayPortAncestor) +ClientTiledThebesLayer::GetAncestorLayers(LayerMetricsWrapper* aOutScrollAncestor, + LayerMetricsWrapper* aOutDisplayPortAncestor) { - Layer* scrollAncestor = nullptr; - Layer* displayPortAncestor = nullptr; - for (Layer* ancestor = this; ancestor; ancestor = ancestor->GetParent()) { - const FrameMetrics& metrics = ancestor->GetFrameMetrics(); + LayerMetricsWrapper scrollAncestor; + LayerMetricsWrapper displayPortAncestor; + for (LayerMetricsWrapper ancestor(this, LayerMetricsWrapper::StartAt::BOTTOM); ancestor; ancestor = ancestor.GetParent()) { + const FrameMetrics& metrics = ancestor.Metrics(); if (!scrollAncestor && metrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID) { scrollAncestor = ancestor; } @@ -120,8 +123,8 @@ ClientTiledThebesLayer::BeginPaint() // Get the metrics of the nearest scrollable layer and the nearest layer // with a displayport. - Layer* scrollAncestor = nullptr; - Layer* displayPortAncestor = nullptr; + LayerMetricsWrapper scrollAncestor; + LayerMetricsWrapper displayPortAncestor; GetAncestorLayers(&scrollAncestor, &displayPortAncestor); if (!displayPortAncestor || !scrollAncestor) { @@ -135,10 +138,10 @@ ClientTiledThebesLayer::BeginPaint() } TILING_LOG("TILING %p: Found scrollAncestor %p and displayPortAncestor %p\n", this, - scrollAncestor, displayPortAncestor); + scrollAncestor.GetLayer(), displayPortAncestor.GetLayer()); - const FrameMetrics& scrollMetrics = scrollAncestor->GetFrameMetrics(); - const FrameMetrics& displayportMetrics = displayPortAncestor->GetFrameMetrics(); + const FrameMetrics& scrollMetrics = scrollAncestor.Metrics(); + const FrameMetrics& displayportMetrics = displayPortAncestor.Metrics(); // Calculate the transform required to convert ParentLayer space of our // display port ancestor to the Layer space of this layer. @@ -183,7 +186,13 @@ ClientTiledThebesLayer::BeginPaint() bool ClientTiledThebesLayer::UseFastPath() { - const FrameMetrics& parentMetrics = GetParent()->GetFrameMetrics(); + LayerMetricsWrapper scrollAncestor; + GetAncestorLayers(&scrollAncestor, nullptr); + if (!scrollAncestor) { + return true; + } + const FrameMetrics& parentMetrics = scrollAncestor.Metrics(); + bool multipleTransactionsNeeded = gfxPrefs::UseProgressiveTilePainting() || gfxPrefs::UseLowPrecisionBuffer() || !parentMetrics.mCriticalDisplayPort.IsEmpty(); diff --git a/gfx/layers/client/ClientTiledThebesLayer.h b/gfx/layers/client/ClientTiledThebesLayer.h index f4539ee3fc49..1cd6369b2008 100644 --- a/gfx/layers/client/ClientTiledThebesLayer.h +++ b/gfx/layers/client/ClientTiledThebesLayer.h @@ -77,8 +77,8 @@ public: * scroll and have a displayport. The parameters are out-params * which hold the return values; the values passed in may be null. */ - void GetAncestorLayers(Layer** aOutScrollAncestor, - Layer** aOutDisplayPortAncestor); + void GetAncestorLayers(LayerMetricsWrapper* aOutScrollAncestor, + LayerMetricsWrapper* aOutDisplayPortAncestor); private: ClientLayerManager* ClientManager() diff --git a/gfx/layers/client/TiledContentClient.cpp b/gfx/layers/client/TiledContentClient.cpp index c6eeed1d7940..8ab6a3e53545 100644 --- a/gfx/layers/client/TiledContentClient.cpp +++ b/gfx/layers/client/TiledContentClient.cpp @@ -19,6 +19,7 @@ #include "mozilla/gfx/Rect.h" // for Rect #include "mozilla/gfx/Tools.h" // for BytesPerPixel #include "mozilla/layers/CompositableForwarder.h" +#include "mozilla/layers/LayerMetricsWrapper.h" #include "mozilla/layers/ShadowLayers.h" // for ShadowLayerForwarder #include "TextureClientPool.h" #include "nsDebug.h" // for NS_ASSERTION @@ -159,7 +160,7 @@ ComputeViewTransform(const FrameMetrics& aContentMetrics, const FrameMetrics& aC bool SharedFrameMetricsHelper::UpdateFromCompositorFrameMetrics( - Layer* aLayer, + const LayerMetricsWrapper& aLayer, bool aHasPendingNewThebesContent, bool aLowPrecision, ViewTransform& aViewTransform) @@ -167,16 +168,16 @@ SharedFrameMetricsHelper::UpdateFromCompositorFrameMetrics( MOZ_ASSERT(aLayer); CompositorChild* compositor = nullptr; - if (aLayer->Manager() && - aLayer->Manager()->AsClientLayerManager()) { - compositor = aLayer->Manager()->AsClientLayerManager()->GetCompositorChild(); + if (aLayer.Manager() && + aLayer.Manager()->AsClientLayerManager()) { + compositor = aLayer.Manager()->AsClientLayerManager()->GetCompositorChild(); } if (!compositor) { return false; } - const FrameMetrics& contentMetrics = aLayer->GetFrameMetrics(); + const FrameMetrics& contentMetrics = aLayer.Metrics(); FrameMetrics compositorMetrics; if (!compositor->LookupCompositorFrameMetrics(contentMetrics.GetScrollId(), @@ -1366,13 +1367,13 @@ ClientTiledLayerBuffer::ValidateTile(TileClient aTile, * for the compositor state. */ static LayerRect -GetCompositorSideCompositionBounds(Layer* aScrollAncestor, +GetCompositorSideCompositionBounds(const LayerMetricsWrapper& aScrollAncestor, const Matrix4x4& aTransformToCompBounds, const ViewTransform& aAPZTransform) { Matrix4x4 nonTransientAPZUntransform = Matrix4x4().Scale( - aScrollAncestor->GetFrameMetrics().mResolution.scale, - aScrollAncestor->GetFrameMetrics().mResolution.scale, + aScrollAncestor.Metrics().mResolution.scale, + aScrollAncestor.Metrics().mResolution.scale, 1.f); nonTransientAPZUntransform.Invert(); @@ -1386,7 +1387,7 @@ GetCompositorSideCompositionBounds(Layer* aScrollAncestor, transform.Invert(); return TransformTo(transform, - aScrollAncestor->GetFrameMetrics().mCompositionBounds); + aScrollAncestor.Metrics().mCompositionBounds); } bool @@ -1417,7 +1418,7 @@ ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInval TILING_LOG("TILING %p: Progressive update stale region %s\n", mThebesLayer, Stringify(staleRegion).c_str()); - Layer* scrollAncestor = nullptr; + LayerMetricsWrapper scrollAncestor; mThebesLayer->GetAncestorLayers(&scrollAncestor, nullptr); // Find out the current view transform to determine which tiles to draw @@ -1425,7 +1426,7 @@ ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInval // caused by there being an incoming, more relevant paint. ViewTransform viewTransform; #if defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_ANDROID_APZ) - FrameMetrics compositorMetrics = scrollAncestor->GetFrameMetrics(); + FrameMetrics compositorMetrics = scrollAncestor.Metrics(); bool abortPaint = false; // On Android, only the primary scrollable layer is async-scrolled, and the only one // that the Java-side code can provide details about. If we're tiling some other layer @@ -1434,7 +1435,7 @@ ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInval abortPaint = mManager->ProgressiveUpdateCallback(!staleRegion.Contains(aInvalidRegion), compositorMetrics, !drawingLowPrecision); - viewTransform = ComputeViewTransform(scrollAncestor->GetFrameMetrics(), compositorMetrics); + viewTransform = ComputeViewTransform(scrollAncestor.Metrics(), compositorMetrics); } #else MOZ_ASSERT(mSharedFrameMetricsHelper); diff --git a/gfx/layers/client/TiledContentClient.h b/gfx/layers/client/TiledContentClient.h index 04c35cd523d8..cc39ee40eecf 100644 --- a/gfx/layers/client/TiledContentClient.h +++ b/gfx/layers/client/TiledContentClient.h @@ -354,7 +354,7 @@ public: * is useful for slow-to-render pages when the display-port starts lagging * behind enough that continuing to draw it is wasted effort. */ - bool UpdateFromCompositorFrameMetrics(Layer* aLayer, + bool UpdateFromCompositorFrameMetrics(const LayerMetricsWrapper& aLayer, bool aHasPendingNewThebesContent, bool aLowPrecision, ViewTransform& aViewTransform); diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index 6e7806b332b8..d2400cdfe88c 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -21,6 +21,7 @@ #include "mozilla/gfx/ScaleFactor.h" // for ScaleFactor #include "mozilla/layers/AsyncPanZoomController.h" #include "mozilla/layers/Compositor.h" // for Compositor +#include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper #include "nsCSSPropList.h" #include "nsCoord.h" // for NSAppUnitsToFloatPixels, etc #include "nsDebug.h" // for NS_ASSERTION, etc @@ -942,7 +943,15 @@ AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame) if (!ApplyAsyncContentTransformToTree(root)) { nsAutoTArray scrollableLayers; #ifdef MOZ_WIDGET_ANDROID - scrollableLayers.AppendElement(mLayerManager->GetPrimaryScrollableLayer()); + const LayerMetricsWrapper& primaryScrollable = mLayerManager->GetPrimaryScrollableLayer(); + if (primaryScrollable) { + // Extracting the Layer* from the LayerMetricsWrapper here is ugly but + // should be only temporary. It is needed here because Fennec doesn't + // support async scrolling of nested scrollable layers (i.e. sub-APZ). + // Once Fennec switches to native APZ (bug 776030) this code will be + // eliminated entirely. + scrollableLayers.AppendElement((Layer*)primaryScrollable.GetLayer()); + } #else mLayerManager->GetScrollableLayers(scrollableLayers); #endif diff --git a/gfx/layers/composite/LayerManagerComposite.cpp b/gfx/layers/composite/LayerManagerComposite.cpp index 1f922dc8e292..3c6c294fbd76 100644 --- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -38,6 +38,7 @@ #include "mozilla/layers/Compositor.h" // for Compositor #include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/Effects.h" // for Effect, EffectChain, etc +#include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper #include "mozilla/layers/LayersTypes.h" // for etc #include "ipc/CompositorBench.h" // for CompositorBench #include "ipc/ShadowLayerUtils.h" @@ -809,12 +810,12 @@ LayerManagerComposite::ComputeRenderIntegrity() #ifdef MOZ_WIDGET_ANDROID // Use the transform on the primary scrollable layer and its FrameMetrics // to find out how much of the viewport the current displayport covers - Layer* primaryScrollable = GetPrimaryScrollableLayer(); + const LayerMetricsWrapper& primaryScrollable = GetPrimaryScrollableLayer(); if (primaryScrollable) { // This is derived from the code in // AsyncCompositionManager::TransformScrollableLayer - const FrameMetrics& metrics = primaryScrollable->GetFrameMetrics(); - Matrix4x4 transform = primaryScrollable->GetEffectiveTransform(); + const FrameMetrics& metrics = primaryScrollable.Metrics(); + Matrix4x4 transform = primaryScrollable.GetEffectiveTransform(); transform.ScalePost(metrics.mResolution.scale, metrics.mResolution.scale, 1); // Clip the screen rect to the document bounds From 81379297b8132a4cf4d46b86383200b94b2f72e8 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 27 Aug 2014 22:13:41 -0400 Subject: [PATCH 39/60] Bug 1055760 - Replace GetPrimaryScrollableLayer with functions that are more appropriate. r=BenWa --- gfx/layers/LayerMetricsWrapper.h | 7 ---- gfx/layers/Layers.cpp | 40 ++++++++++++++++--- gfx/layers/Layers.h | 14 ++++++- gfx/layers/client/ClientLayerManager.cpp | 40 +++++++++---------- gfx/layers/client/TiledContentClient.cpp | 8 ++-- .../composite/AsyncCompositionManager.cpp | 10 +---- .../composite/LayerManagerComposite.cpp | 10 +++-- 7 files changed, 77 insertions(+), 52 deletions(-) diff --git a/gfx/layers/LayerMetricsWrapper.h b/gfx/layers/LayerMetricsWrapper.h index 6e8771b7e4cd..e4eb54a73d19 100644 --- a/gfx/layers/LayerMetricsWrapper.h +++ b/gfx/layers/LayerMetricsWrapper.h @@ -286,13 +286,6 @@ public: return gfx::Matrix4x4(); } - const gfx::Matrix4x4& GetEffectiveTransform() const - { - MOZ_ASSERT(IsValid()); - - return mLayer->GetEffectiveTransform(); - } - RefLayer* AsRefLayer() const { MOZ_ASSERT(IsValid()); diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 521c03f4cee8..c95e73373c4b 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -54,11 +54,11 @@ using namespace mozilla::gfx; //-------------------------------------------------- // LayerManager -LayerMetricsWrapper -LayerManager::GetPrimaryScrollableLayer() +FrameMetrics::ViewID +LayerManager::GetRootScrollableLayerId() { if (!mRoot) { - return LayerMetricsWrapper(); + return FrameMetrics::NULL_SCROLL_ID; } nsTArray queue; @@ -69,7 +69,7 @@ LayerManager::GetPrimaryScrollableLayer() const FrameMetrics& frameMetrics = layer.Metrics(); if (frameMetrics.IsScrollable()) { - return layer; + return frameMetrics.GetScrollId(); } LayerMetricsWrapper child = layer.GetFirstChild(); @@ -79,7 +79,37 @@ LayerManager::GetPrimaryScrollableLayer() } } - return LayerMetricsWrapper(mRoot); + return FrameMetrics::NULL_SCROLL_ID; +} + +void +LayerManager::GetRootScrollableLayers(nsTArray& aArray) +{ + if (!mRoot) { + return; + } + + FrameMetrics::ViewID rootScrollableId = GetRootScrollableLayerId(); + if (rootScrollableId == FrameMetrics::NULL_SCROLL_ID) { + aArray.AppendElement(mRoot); + return; + } + + nsTArray queue; + queue.AppendElement(mRoot); + while (queue.Length()) { + Layer* layer = queue[0]; + queue.RemoveElementAt(0); + + if (LayerMetricsWrapper::TopmostScrollableMetrics(layer).GetScrollId() == rootScrollableId) { + aArray.AppendElement(layer); + continue; + } + + for (Layer* child = layer->GetFirstChild(); child; child = child->GetNextSibling()) { + queue.AppendElement(child); + } + } } void diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 0719fc7e4a63..c95cbab0bdb4 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -337,10 +337,20 @@ public: /** * Does a breadth-first search from the root layer to find the first - * scrollable layer. + * scrollable layer, and returns its ViewID. Note that there may be + * other layers in the tree which share the same ViewID. * Can be called any time. */ - LayerMetricsWrapper GetPrimaryScrollableLayer(); + FrameMetrics::ViewID GetRootScrollableLayerId(); + + /** + * Does a breadth-first search from the root layer to find the first + * scrollable layer, and returns all the layers that have that ViewID + * as the first scrollable metrics in their ancestor chain. If no + * scrollable layers are found it just returns the root of the tree if + * there is one. + */ + void GetRootScrollableLayers(nsTArray& aArray); /** * Returns a list of all descendant layers for which diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index bbb58a5fbcbc..bc7362e994d0 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -642,30 +642,26 @@ ClientLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, bool aDrawingCritical) { #ifdef MOZ_WIDGET_ANDROID - const LayerMetricsWrapper& primaryScrollable = GetPrimaryScrollableLayer(); - if (primaryScrollable) { - const FrameMetrics& metrics = primaryScrollable.Metrics(); - - // This is derived from the code in - // gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree. - CSSToLayerScale paintScale = metrics.LayersPixelsPerCSSPixel(); - const CSSRect& metricsDisplayPort = - (aDrawingCritical && !metrics.mCriticalDisplayPort.IsEmpty()) ? - metrics.mCriticalDisplayPort : metrics.mDisplayPort; - LayerRect displayPort = (metricsDisplayPort + metrics.GetScrollOffset()) * paintScale; - - ScreenPoint scrollOffset; - CSSToScreenScale zoom; - bool ret = AndroidBridge::Bridge()->ProgressiveUpdateCallback( - aHasPendingNewThebesContent, displayPort, paintScale.scale, aDrawingCritical, - scrollOffset, zoom); - aMetrics.SetScrollOffset(scrollOffset / zoom); - aMetrics.SetZoom(zoom); - return ret; - } -#endif + MOZ_ASSERT(aMetrics.IsScrollable()); + // This is derived from the code in + // gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree. + CSSToLayerScale paintScale = aMetrics.LayersPixelsPerCSSPixel(); + const CSSRect& metricsDisplayPort = + (aDrawingCritical && !aMetrics.mCriticalDisplayPort.IsEmpty()) ? + aMetrics.mCriticalDisplayPort : aMetrics.mDisplayPort; + LayerRect displayPort = (metricsDisplayPort + aMetrics.GetScrollOffset()) * paintScale; + ScreenPoint scrollOffset; + CSSToScreenScale zoom; + bool ret = AndroidBridge::Bridge()->ProgressiveUpdateCallback( + aHasPendingNewThebesContent, displayPort, paintScale.scale, aDrawingCritical, + scrollOffset, zoom); + aMetrics.SetScrollOffset(scrollOffset / zoom); + aMetrics.SetZoom(zoom); + return ret; +#else return false; +#endif } ClientLayer::~ClientLayer() diff --git a/gfx/layers/client/TiledContentClient.cpp b/gfx/layers/client/TiledContentClient.cpp index 8ab6a3e53545..bc88fc252922 100644 --- a/gfx/layers/client/TiledContentClient.cpp +++ b/gfx/layers/client/TiledContentClient.cpp @@ -1426,16 +1426,18 @@ ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInval // caused by there being an incoming, more relevant paint. ViewTransform viewTransform; #if defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_ANDROID_APZ) - FrameMetrics compositorMetrics = scrollAncestor.Metrics(); + FrameMetrics contentMetrics = scrollAncestor.Metrics(); bool abortPaint = false; // On Android, only the primary scrollable layer is async-scrolled, and the only one // that the Java-side code can provide details about. If we're tiling some other layer // then we already have all the information we need about it. - if (scrollAncestor == mManager->GetPrimaryScrollableLayer()) { + if (contentMetrics.GetScrollId() == mManager->GetRootScrollableLayerId()) { + FrameMetrics compositorMetrics = contentMetrics; + // The ProgressiveUpdateCallback updates the compositorMetrics abortPaint = mManager->ProgressiveUpdateCallback(!staleRegion.Contains(aInvalidRegion), compositorMetrics, !drawingLowPrecision); - viewTransform = ComputeViewTransform(scrollAncestor.Metrics(), compositorMetrics); + viewTransform = ComputeViewTransform(contentMetrics, compositorMetrics); } #else MOZ_ASSERT(mSharedFrameMetricsHelper); diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index d2400cdfe88c..9d7ca94693a8 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -943,15 +943,7 @@ AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame) if (!ApplyAsyncContentTransformToTree(root)) { nsAutoTArray scrollableLayers; #ifdef MOZ_WIDGET_ANDROID - const LayerMetricsWrapper& primaryScrollable = mLayerManager->GetPrimaryScrollableLayer(); - if (primaryScrollable) { - // Extracting the Layer* from the LayerMetricsWrapper here is ugly but - // should be only temporary. It is needed here because Fennec doesn't - // support async scrolling of nested scrollable layers (i.e. sub-APZ). - // Once Fennec switches to native APZ (bug 776030) this code will be - // eliminated entirely. - scrollableLayers.AppendElement((Layer*)primaryScrollable.GetLayer()); - } + mLayerManager->GetRootScrollableLayers(scrollableLayers); #else mLayerManager->GetScrollableLayers(scrollableLayers); #endif diff --git a/gfx/layers/composite/LayerManagerComposite.cpp b/gfx/layers/composite/LayerManagerComposite.cpp index 3c6c294fbd76..7c76b62e5156 100644 --- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -810,12 +810,14 @@ LayerManagerComposite::ComputeRenderIntegrity() #ifdef MOZ_WIDGET_ANDROID // Use the transform on the primary scrollable layer and its FrameMetrics // to find out how much of the viewport the current displayport covers - const LayerMetricsWrapper& primaryScrollable = GetPrimaryScrollableLayer(); - if (primaryScrollable) { + nsTArray rootScrollableLayers; + GetRootScrollableLayers(rootScrollableLayers); + if (rootScrollableLayers.Length() > 0) { // This is derived from the code in // AsyncCompositionManager::TransformScrollableLayer - const FrameMetrics& metrics = primaryScrollable.Metrics(); - Matrix4x4 transform = primaryScrollable.GetEffectiveTransform(); + Layer* rootScrollable = rootScrollableLayers[0]; + const FrameMetrics& metrics = LayerMetricsWrapper::TopmostScrollableMetrics(rootScrollable); + Matrix4x4 transform = rootScrollable->GetEffectiveTransform(); transform.ScalePost(metrics.mResolution.scale, metrics.mResolution.scale, 1); // Clip the screen rect to the document bounds From 6cf11ad811095ea25d5b9e135e870ea465a5e1e2 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 27 Aug 2014 22:13:41 -0400 Subject: [PATCH 40/60] Bug 1055760 - Update AsyncCompositionManager's async-transform application code to deal with multiple FrameMetrics. r=botond --- gfx/layers/LayerMetricsWrapper.h | 28 +++++++++++ .../composite/AsyncCompositionManager.cpp | 50 +++++++++++++++---- 2 files changed, 67 insertions(+), 11 deletions(-) diff --git a/gfx/layers/LayerMetricsWrapper.h b/gfx/layers/LayerMetricsWrapper.h index e4eb54a73d19..c11a7c582509 100644 --- a/gfx/layers/LayerMetricsWrapper.h +++ b/gfx/layers/LayerMetricsWrapper.h @@ -343,6 +343,34 @@ public: return !(*this == aOther); } + static const FrameMetrics& TopmostScrollableMetrics(Layer* aLayer) + { + for (uint32_t i = aLayer->GetFrameMetricsCount(); i > 0; i--) { + if (aLayer->GetFrameMetrics(i - 1).IsScrollable()) { + return aLayer->GetFrameMetrics(i - 1); + } + } + return FrameMetrics::sNullMetrics; + } + + static const FrameMetrics& BottommostScrollableMetrics(Layer* aLayer) + { + for (uint32_t i = 0; i < aLayer->GetFrameMetricsCount(); i++) { + if (aLayer->GetFrameMetrics(i).IsScrollable()) { + return aLayer->GetFrameMetrics(i); + } + } + return FrameMetrics::sNullMetrics; + } + + static const FrameMetrics& BottommostMetrics(Layer* aLayer) + { + if (aLayer->GetFrameMetricsCount() > 0) { + return aLayer->GetFrameMetrics(0); + } + return FrameMetrics::sNullMetrics; + } + private: bool AtBottomLayer() const { diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index 9d7ca94693a8..9da95ee76599 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -552,9 +552,21 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer) ApplyAsyncContentTransformToTree(child); } - if (AsyncPanZoomController* controller = aLayer->GetAsyncPanZoomController()) { - LayerComposite* layerComposite = aLayer->AsLayerComposite(); - Matrix4x4 oldTransform = aLayer->GetTransform(); + LayerComposite* layerComposite = aLayer->AsLayerComposite(); + Matrix4x4 oldTransform = aLayer->GetTransform(); + + Matrix4x4 combinedAsyncTransformWithoutOverscroll; + Matrix4x4 combinedAsyncTransform; + bool hasAsyncTransform = false; + LayerMargin fixedLayerMargins(0, 0, 0, 0); + + for (uint32_t i = 0; i < aLayer->GetFrameMetricsCount(); i++) { + AsyncPanZoomController* controller = aLayer->GetAsyncPanZoomController(i); + if (!controller) { + continue; + } + + hasAsyncTransform = true; ViewTransform asyncTransformWithoutOverscroll, overscrollTransform; ScreenPoint scrollOffset; @@ -562,12 +574,13 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer) scrollOffset, &overscrollTransform); - const FrameMetrics& metrics = aLayer->GetFrameMetrics(); + const FrameMetrics& metrics = aLayer->GetFrameMetrics(i); CSSToLayerScale paintScale = metrics.LayersPixelsPerCSSPixel(); CSSRect displayPort(metrics.mCriticalDisplayPort.IsEmpty() ? metrics.mDisplayPort : metrics.mCriticalDisplayPort); - LayerMargin fixedLayerMargins(0, 0, 0, 0); ScreenPoint offset(0, 0); + // XXX this call to SyncFrameMetrics is not currently being used. It will be cleaned + // up as part of bug 776030 or one of its dependencies. SyncFrameMetrics(scrollOffset, asyncTransformWithoutOverscroll.mScale.scale, metrics.mScrollableRect, mLayersUpdated, displayPort, paintScale, mIsFirstPaint, fixedLayerMargins, offset); @@ -578,8 +591,12 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer) // Apply the render offset mLayerManager->GetCompositor()->SetScreenRenderOffset(offset); - Matrix4x4 transform = AdjustAndCombineWithCSSTransform( - asyncTransformWithoutOverscroll * overscrollTransform, aLayer); + combinedAsyncTransformWithoutOverscroll *= asyncTransformWithoutOverscroll; + combinedAsyncTransform *= (asyncTransformWithoutOverscroll * overscrollTransform); + } + + if (hasAsyncTransform) { + Matrix4x4 transform = AdjustAndCombineWithCSSTransform(combinedAsyncTransform, aLayer); // GetTransform already takes the pre- and post-scale into account. Since we // will apply the pre- and post-scale again when computing the effective @@ -597,8 +614,11 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer) "overwriting animated transform!"); // Apply resolution scaling to the old transform - the layer tree as it is - // doesn't have the necessary transform to display correctly. - LayoutDeviceToLayerScale resolution = metrics.mCumulativeResolution; + // doesn't have the necessary transform to display correctly. We use the + // bottom-most scrollable metrics because that should have the most accurate + // cumulative resolution for aLayer. + LayoutDeviceToLayerScale resolution = + LayerMetricsWrapper::BottommostScrollableMetrics(aLayer).mCumulativeResolution; oldTransform.Scale(resolution.scale, resolution.scale, 1); // For the purpose of aligning fixed and sticky layers, we disregard @@ -606,7 +626,7 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer) // parameter. This ensures that the overscroll transform is not unapplied, // and therefore that the visual effect applies to fixed and sticky layers. Matrix4x4 transformWithoutOverscroll = AdjustAndCombineWithCSSTransform( - asyncTransformWithoutOverscroll, aLayer); + combinedAsyncTransformWithoutOverscroll, aLayer); AlignFixedAndStickyLayers(aLayer, aLayer, oldTransform, transformWithoutOverscroll, fixedLayerMargins); @@ -771,7 +791,15 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer) { LayerComposite* layerComposite = aLayer->AsLayerComposite(); - const FrameMetrics& metrics = aLayer->GetFrameMetrics(); + FrameMetrics metrics = LayerMetricsWrapper::TopmostScrollableMetrics(aLayer); + if (!metrics.IsScrollable()) { + // On Fennec it's possible that the there is no scrollable layer in the + // tree, and this function just gets called with the root layer. In that + // case TopmostScrollableMetrics will return an empty FrameMetrics but we + // still want to use the actual non-scrollable metrics from the layer. + metrics = LayerMetricsWrapper::BottommostMetrics(aLayer); + } + // We must apply the resolution scale before a pan/zoom transform, so we call // GetTransform here. Matrix4x4 oldTransform = aLayer->GetTransform(); From cf3bee3fd4b1744261ccf178535e6499753775e5 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 27 Aug 2014 22:13:42 -0400 Subject: [PATCH 41/60] Bug 1055760 - Update AsyncCompositionManager's scrollbar-adjusting code to deal with multiple FrameMetrics. r=botond --- gfx/layers/LayerMetricsWrapper.h | 13 ++++ .../composite/AsyncCompositionManager.cpp | 75 ++++++++----------- .../composite/AsyncCompositionManager.h | 2 +- 3 files changed, 46 insertions(+), 44 deletions(-) diff --git a/gfx/layers/LayerMetricsWrapper.h b/gfx/layers/LayerMetricsWrapper.h index c11a7c582509..40b6d6dbbf4f 100644 --- a/gfx/layers/LayerMetricsWrapper.h +++ b/gfx/layers/LayerMetricsWrapper.h @@ -173,6 +173,19 @@ public: return IsValid(); } + bool IsScrollInfoLayer() const + { + MOZ_ASSERT(IsValid()); + + // If we are not at the bottommost layer then it's + // a stack of container layers all the way down to + // mLayer, which we can ignore. We only care about + // non-container descendants. + return Metrics().IsScrollable() + && mLayer->AsContainerLayer() + && !mLayer->GetFirstChild(); + } + LayerMetricsWrapper GetParent() const { MOZ_ASSERT(IsValid()); diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index 9da95ee76599..81a92d06f90b 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -633,34 +633,20 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer) appliedTransform = true; } - if (aLayer->AsContainerLayer() && aLayer->GetScrollbarDirection() != Layer::NONE) { - ApplyAsyncTransformToScrollbar(aLayer->AsContainerLayer()); + if (aLayer->GetScrollbarDirection() != Layer::NONE) { + ApplyAsyncTransformToScrollbar(aLayer); } return appliedTransform; } static bool -LayerHasNonContainerDescendants(ContainerLayer* aContainer) +LayerIsScrollbarTarget(const LayerMetricsWrapper& aTarget, Layer* aScrollbar) { - for (Layer* child = aContainer->GetFirstChild(); - child; child = child->GetNextSibling()) { - ContainerLayer* container = child->AsContainerLayer(); - if (!container || LayerHasNonContainerDescendants(container)) { - return true; - } - } - - return false; -} - -static bool -LayerIsScrollbarTarget(Layer* aTarget, ContainerLayer* aScrollbar) -{ - AsyncPanZoomController* apzc = aTarget->GetAsyncPanZoomController(); + AsyncPanZoomController* apzc = aTarget.GetApzc(); if (!apzc) { return false; } - const FrameMetrics& metrics = aTarget->GetFrameMetrics(); + const FrameMetrics& metrics = aTarget.Metrics(); if (metrics.GetScrollId() != aScrollbar->GetScrollbarTargetContainerId()) { return false; } @@ -668,21 +654,21 @@ LayerIsScrollbarTarget(Layer* aTarget, ContainerLayer* aScrollbar) } static void -ApplyAsyncTransformToScrollbarForContent(ContainerLayer* aScrollbar, - Layer* aContent, bool aScrollbarIsChild) +ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar, + const LayerMetricsWrapper& aContent, + bool aScrollbarIsDescendant) { // We only apply the transform if the scroll-target layer has non-container // children (i.e. when it has some possibly-visible content). This is to // avoid moving scroll-bars in the situation that only a scroll information // layer has been built for a scroll frame, as this would result in a // disparity between scrollbars and visible content. - if (aContent->AsContainerLayer() && - !LayerHasNonContainerDescendants(aContent->AsContainerLayer())) { + if (aContent.IsScrollInfoLayer()) { return; } - const FrameMetrics& metrics = aContent->GetFrameMetrics(); - AsyncPanZoomController* apzc = aContent->GetAsyncPanZoomController(); + const FrameMetrics& metrics = aContent.Metrics(); + AsyncPanZoomController* apzc = aContent.GetApzc(); Matrix4x4 asyncTransform = apzc->GetCurrentAsyncTransform(); Matrix4x4 nontransientTransform = apzc->GetNontransientAsyncTransform(); @@ -717,7 +703,7 @@ ApplyAsyncTransformToScrollbarForContent(ContainerLayer* aScrollbar, Matrix4x4 transform = scrollbarTransform * aScrollbar->GetTransform(); - if (aScrollbarIsChild) { + if (aScrollbarIsDescendant) { // If the scrollbar layer is a child of the content it is a scrollbar for, then we // need to do an extra untransform to cancel out the transient async transform on // the content. This is needed because otherwise that transient async transform is @@ -730,47 +716,50 @@ ApplyAsyncTransformToScrollbarForContent(ContainerLayer* aScrollbar, // GetTransform already takes the pre- and post-scale into account. Since we // will apply the pre- and post-scale again when computing the effective // transform, we must apply the inverses here. - transform.Scale(1.0f/aScrollbar->GetPreXScale(), - 1.0f/aScrollbar->GetPreYScale(), - 1); + if (ContainerLayer* container = aScrollbar->AsContainerLayer()) { + transform.Scale(1.0f/container->GetPreXScale(), + 1.0f/container->GetPreYScale(), + 1); + } transform = transform * Matrix4x4().Scale(1.0f/aScrollbar->GetPostXScale(), 1.0f/aScrollbar->GetPostYScale(), 1); aScrollbar->AsLayerComposite()->SetShadowTransform(transform); } -static Layer* -FindScrolledLayerForScrollbar(ContainerLayer* aLayer, bool* aOutIsAncestor) +static LayerMetricsWrapper +FindScrolledLayerForScrollbar(Layer* aScrollbar, bool* aOutIsAncestor) { // XXX: once bug 967844 is implemented there might be multiple scrolled layers // that correspond to the scrollbar's scrollId. Verify that we deal with those // cases correctly. - // Search all siblings of aLayer and of its ancestors. - for (Layer* ancestor = aLayer; ancestor; ancestor = ancestor->GetParent()) { - for (Layer* scrollTarget = ancestor; + // Search all siblings of aScrollbar and of its ancestors. + LayerMetricsWrapper scrollbar(aScrollbar, LayerMetricsWrapper::StartAt::BOTTOM); + for (LayerMetricsWrapper ancestor = scrollbar; ancestor; ancestor = ancestor.GetParent()) { + for (LayerMetricsWrapper scrollTarget = ancestor; scrollTarget; - scrollTarget = scrollTarget->GetPrevSibling()) { - if (scrollTarget != aLayer && - LayerIsScrollbarTarget(scrollTarget, aLayer)) { + scrollTarget = scrollTarget.GetPrevSibling()) { + if (scrollTarget != scrollbar && + LayerIsScrollbarTarget(scrollTarget, aScrollbar)) { *aOutIsAncestor = (scrollTarget == ancestor); return scrollTarget; } } - for (Layer* scrollTarget = ancestor->GetNextSibling(); + for (LayerMetricsWrapper scrollTarget = ancestor.GetNextSibling(); scrollTarget; - scrollTarget = scrollTarget->GetNextSibling()) { - if (LayerIsScrollbarTarget(scrollTarget, aLayer)) { + scrollTarget = scrollTarget.GetNextSibling()) { + if (LayerIsScrollbarTarget(scrollTarget, aScrollbar)) { *aOutIsAncestor = false; return scrollTarget; } } } - return nullptr; + return LayerMetricsWrapper(); } void -AsyncCompositionManager::ApplyAsyncTransformToScrollbar(ContainerLayer* aLayer) +AsyncCompositionManager::ApplyAsyncTransformToScrollbar(Layer* aLayer) { // If this layer corresponds to a scrollbar, then there should be a layer that // is a previous sibling or a parent that has a matching ViewID on its FrameMetrics. @@ -780,7 +769,7 @@ AsyncCompositionManager::ApplyAsyncTransformToScrollbar(ContainerLayer* aLayer) // this case we don't need to do anything because there can't be an async // transform on the content. bool isAncestor = false; - Layer* scrollTarget = FindScrolledLayerForScrollbar(aLayer, &isAncestor); + const LayerMetricsWrapper& scrollTarget = FindScrolledLayerForScrollbar(aLayer, &isAncestor); if (scrollTarget) { ApplyAsyncTransformToScrollbarForContent(aLayer, scrollTarget, isAncestor); } diff --git a/gfx/layers/composite/AsyncCompositionManager.h b/gfx/layers/composite/AsyncCompositionManager.h index 17af6acf27c6..30e04f3e61f1 100644 --- a/gfx/layers/composite/AsyncCompositionManager.h +++ b/gfx/layers/composite/AsyncCompositionManager.h @@ -130,7 +130,7 @@ private: * Update the shadow transform for aLayer assuming that is a scrollbar, * so that it stays in sync with the content that is being scrolled by APZ. */ - void ApplyAsyncTransformToScrollbar(ContainerLayer* aLayer); + void ApplyAsyncTransformToScrollbar(Layer* aLayer); void SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, From 29bf92e1eaf16eef8fb9f015f2a6e4ecc8901edc Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 27 Aug 2014 22:13:42 -0400 Subject: [PATCH 42/60] Bug 1055760 - Update AsyncCompositionManager's fixed- and sticky-layer-adjusting code to deal with multiple FrameMetrics. r=botond --- .../composite/AsyncCompositionManager.cpp | 20 +++++++++++-------- .../composite/AsyncCompositionManager.h | 1 + 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index 81a92d06f90b..c37fec59b160 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -243,6 +243,7 @@ IntervalOverlap(gfxFloat aTranslation, gfxFloat aMin, gfxFloat aMax) void AsyncCompositionManager::AlignFixedAndStickyLayers(Layer* aLayer, Layer* aTransformedSubtreeRoot, + FrameMetrics::ViewID aTransformScrollId, const Matrix4x4& aPreviousTransformForRoot, const Matrix4x4& aCurrentTransformForRoot, const LayerMargin& aFixedLayerMargins) @@ -250,8 +251,7 @@ AsyncCompositionManager::AlignFixedAndStickyLayers(Layer* aLayer, bool isRootFixed = aLayer->GetIsFixedPosition() && !aLayer->GetParent()->GetIsFixedPosition(); bool isStickyForSubtree = aLayer->GetIsStickyPosition() && - aLayer->GetStickyScrollContainerId() == - aTransformedSubtreeRoot->GetFrameMetrics().GetScrollId(); + aLayer->GetStickyScrollContainerId() == aTransformScrollId; bool isFixedOrSticky = (isRootFixed || isStickyForSubtree); // We want to process all the fixed and sticky children of @@ -262,9 +262,9 @@ AsyncCompositionManager::AlignFixedAndStickyLayers(Layer* aLayer, // ApplyAsyncContentTransformToTree will call this function again for // nested scrollable layers, so we don't need to recurse if the layer is // scrollable. - if (aLayer == aTransformedSubtreeRoot || !aLayer->GetFrameMetrics().IsScrollable()) { + if (aLayer == aTransformedSubtreeRoot || !aLayer->HasScrollableFrameMetrics()) { for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) { - AlignFixedAndStickyLayers(child, aTransformedSubtreeRoot, + AlignFixedAndStickyLayers(child, aTransformedSubtreeRoot, aTransformScrollId, aPreviousTransformForRoot, aCurrentTransformForRoot, aFixedLayerMargins); } @@ -613,12 +613,14 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer) NS_ASSERTION(!layerComposite->GetShadowTransformSetByAnimation(), "overwriting animated transform!"); + const FrameMetrics& bottom = LayerMetricsWrapper::BottommostScrollableMetrics(aLayer); + MOZ_ASSERT(bottom.IsScrollable()); // must be true because hasAsyncTransform is true + // Apply resolution scaling to the old transform - the layer tree as it is // doesn't have the necessary transform to display correctly. We use the // bottom-most scrollable metrics because that should have the most accurate // cumulative resolution for aLayer. - LayoutDeviceToLayerScale resolution = - LayerMetricsWrapper::BottommostScrollableMetrics(aLayer).mCumulativeResolution; + LayoutDeviceToLayerScale resolution = bottom.mCumulativeResolution; oldTransform.Scale(resolution.scale, resolution.scale, 1); // For the purpose of aligning fixed and sticky layers, we disregard @@ -627,7 +629,9 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer) // and therefore that the visual effect applies to fixed and sticky layers. Matrix4x4 transformWithoutOverscroll = AdjustAndCombineWithCSSTransform( combinedAsyncTransformWithoutOverscroll, aLayer); - AlignFixedAndStickyLayers(aLayer, aLayer, oldTransform, + // Since fixed/sticky layers are relative to their nearest scrolling ancestor, + // we use the ViewID from the bottommost scrollable metrics here. + AlignFixedAndStickyLayers(aLayer, aLayer, bottom.GetScrollId(), oldTransform, transformWithoutOverscroll, fixedLayerMargins); appliedTransform = true; @@ -908,7 +912,7 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer) // Make sure fixed position layers don't move away from their anchor points // when we're asynchronously panning or zooming - AlignFixedAndStickyLayers(aLayer, aLayer, oldTransform, + AlignFixedAndStickyLayers(aLayer, aLayer, metrics.GetScrollId(), oldTransform, aLayer->GetLocalTransform(), fixedLayerMargins); } diff --git a/gfx/layers/composite/AsyncCompositionManager.h b/gfx/layers/composite/AsyncCompositionManager.h index 30e04f3e61f1..b07009cd51f5 100644 --- a/gfx/layers/composite/AsyncCompositionManager.h +++ b/gfx/layers/composite/AsyncCompositionManager.h @@ -169,6 +169,7 @@ private: * zooming. */ void AlignFixedAndStickyLayers(Layer* aLayer, Layer* aTransformedSubtreeRoot, + FrameMetrics::ViewID aTransformScrollId, const gfx::Matrix4x4& aPreviousTransformForRoot, const gfx::Matrix4x4& aCurrentTransformForRoot, const LayerMargin& aFixedLayerMargins); From 1c013ea7c829de880488956cc6f157065887e898 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 27 Aug 2014 22:13:42 -0400 Subject: [PATCH 43/60] Bug 1055760 - Update AsyncCompositionManager's animation-sampling code to deal with multiple FrameMetrics. r=botond --- gfx/layers/composite/AsyncCompositionManager.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index c37fec59b160..e8fd0d1320d4 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -505,15 +505,15 @@ SampleAnimations(Layer* aLayer, TimeStamp aPoint) } static bool -SampleAPZAnimations(Layer* aLayer, TimeStamp aPoint) +SampleAPZAnimations(const LayerMetricsWrapper& aLayer, TimeStamp aPoint) { bool activeAnimations = false; - for (Layer* child = aLayer->GetFirstChild(); child; - child = child->GetNextSibling()) { + for (LayerMetricsWrapper child = aLayer.GetFirstChild(); child; + child = child.GetNextSibling()) { activeAnimations |= SampleAPZAnimations(child, aPoint); } - if (AsyncPanZoomController* apzc = aLayer->GetAsyncPanZoomController()) { + if (AsyncPanZoomController* apzc = aLayer.GetApzc()) { activeAnimations |= apzc->AdvanceAnimations(aPoint); } @@ -960,7 +960,7 @@ AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame) // code also includes Fennec which is rendered async. Fennec uses // its own platform-specific async rendering that is done partially // in Gecko and partially in Java. - wantNextFrame |= SampleAPZAnimations(root, aCurrentFrame); + wantNextFrame |= SampleAPZAnimations(LayerMetricsWrapper(root), aCurrentFrame); if (!ApplyAsyncContentTransformToTree(root)) { nsAutoTArray scrollableLayers; #ifdef MOZ_WIDGET_ANDROID From f72e3c0ee4936358376e74231154877c94bb0f5b Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 27 Aug 2014 22:13:42 -0400 Subject: [PATCH 44/60] Bug 1055760 - Update some more bits of compositor layer code to deal with multiple FrameMetrics. r=BenWa,botond --- gfx/layers/Layers.cpp | 9 +++++++ gfx/layers/Layers.h | 1 + .../composite/ContainerLayerComposite.cpp | 24 ++++++++++++++----- .../composite/LayerManagerComposite.cpp | 8 ++++++- gfx/layers/composite/ThebesLayerComposite.cpp | 13 ---------- gfx/layers/composite/ThebesLayerComposite.h | 2 -- gfx/layers/composite/TiledContentHost.cpp | 3 ++- 7 files changed, 37 insertions(+), 23 deletions(-) diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index c95e73373c4b..e5d0f660c997 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -713,6 +713,15 @@ Layer::HasScrollableFrameMetrics() const return false; } +bool +Layer::IsScrollInfoLayer() const +{ + // A scrollable container layer with no children + return AsContainerLayer() + && HasScrollableFrameMetrics() + && !GetFirstChild(); +} + const Matrix4x4 Layer::GetTransform() const { diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index c95cbab0bdb4..305a30fd6f9b 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -1203,6 +1203,7 @@ public: uint32_t GetFrameMetricsCount() const { return mFrameMetrics.Length(); } const nsTArray& GetAllFrameMetrics() { return mFrameMetrics; } bool HasScrollableFrameMetrics() const; + bool IsScrollInfoLayer() const; const EventRegions& GetEventRegions() const { return mEventRegions; } ContainerLayer* GetParent() { return mParent; } Layer* GetNextSibling() { return mNextSibling; } diff --git a/gfx/layers/composite/ContainerLayerComposite.cpp b/gfx/layers/composite/ContainerLayerComposite.cpp index d3d3c8a3fa89..ecbb9cb88eef 100644 --- a/gfx/layers/composite/ContainerLayerComposite.cpp +++ b/gfx/layers/composite/ContainerLayerComposite.cpp @@ -23,6 +23,7 @@ #include "mozilla/layers/TextureHost.h" // for CompositingRenderTarget #include "mozilla/layers/AsyncPanZoomController.h" // for AsyncPanZoomController #include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform +#include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper #include "mozilla/mozalloc.h" // for operator delete, etc #include "nsAutoPtr.h" // for nsRefPtr #include "nsDebug.h" // for NS_ASSERTION @@ -254,10 +255,18 @@ RenderLayers(ContainerT* aContainer, // composited area. If the layer has a background color, fill these areas // with the background color by drawing a rectangle of the background color // over the entire composited area before drawing the container contents. - if (AsyncPanZoomController* apzc = aContainer->GetAsyncPanZoomController()) { - // Make sure not to do this on a "scrollinfo" layer (one with an empty visible - // region) because it's just a placeholder for APZ purposes. - if (apzc->IsOverscrolled() && !aContainer->GetVisibleRegion().IsEmpty()) { + // Make sure not to do this on a "scrollinfo" layer because it's just a + // placeholder for APZ purposes. + if (aContainer->HasScrollableFrameMetrics() && !aContainer->IsScrollInfoLayer()) { + bool overscrolled = false; + for (uint32_t i = 0; i < aContainer->GetFrameMetricsCount(); i++) { + AsyncPanZoomController* apzc = aContainer->GetAsyncPanZoomController(i); + if (apzc && apzc->IsOverscrolled()) { + overscrolled = true; + break; + } + } + if (overscrolled) { gfxRGBA color = aContainer->GetBackgroundColor(); // If the background is completely transparent, there's no point in // drawing anything for it. Hopefully the layers behind, if any, will @@ -421,8 +430,11 @@ ContainerRender(ContainerT* aContainer, } aContainer->mPrepared = nullptr; - if (aContainer->GetFrameMetrics().IsScrollable()) { - const FrameMetrics& frame = aContainer->GetFrameMetrics(); + for (uint32_t i = 0; i < aContainer->GetFrameMetricsCount(); i++) { + if (!aContainer->GetFrameMetrics(i).IsScrollable()) { + continue; + } + const FrameMetrics& frame = aContainer->GetFrameMetrics(i); LayerRect layerBounds = frame.mCompositionBounds * ParentLayerToLayerScale(1.0); gfx::Rect rect(layerBounds.x, layerBounds.y, layerBounds.width, layerBounds.height); gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height); diff --git a/gfx/layers/composite/LayerManagerComposite.cpp b/gfx/layers/composite/LayerManagerComposite.cpp index 7c76b62e5156..2ce8b0745e10 100644 --- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -797,7 +797,13 @@ LayerManagerComposite::ComputeRenderIntegrity() return 1.f; } - const FrameMetrics& rootMetrics = root->GetFrameMetrics(); + FrameMetrics rootMetrics = LayerMetricsWrapper::TopmostScrollableMetrics(root); + if (!rootMetrics.IsScrollable()) { + // The root may not have any scrollable metrics, in which case rootMetrics + // will just be an empty FrameMetrics. Instead use the actual metrics from + // the root layer. + rootMetrics = LayerMetricsWrapper(root).Metrics(); + } ParentLayerIntRect bounds = RoundedToInt(rootMetrics.mCompositionBounds); nsIntRect screenRect(bounds.x, bounds.y, diff --git a/gfx/layers/composite/ThebesLayerComposite.cpp b/gfx/layers/composite/ThebesLayerComposite.cpp index f876bd5f2249..8b1b7bc28038 100644 --- a/gfx/layers/composite/ThebesLayerComposite.cpp +++ b/gfx/layers/composite/ThebesLayerComposite.cpp @@ -172,19 +172,6 @@ ThebesLayerComposite::GenEffectChain(EffectChain& aEffect) aEffect.mPrimaryEffect = mBuffer->GenEffect(GetEffectFilter()); } -CSSToScreenScale -ThebesLayerComposite::GetEffectiveResolution() -{ - for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) { - const FrameMetrics& metrics = parent->GetFrameMetrics(); - if (metrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID) { - return metrics.GetZoom(); - } - } - - return CSSToScreenScale(1.0); -} - void ThebesLayerComposite::PrintInfo(std::stringstream& aStream, const char* aPrefix) { diff --git a/gfx/layers/composite/ThebesLayerComposite.h b/gfx/layers/composite/ThebesLayerComposite.h index 5d64fbc4c863..71defa3a5738 100644 --- a/gfx/layers/composite/ThebesLayerComposite.h +++ b/gfx/layers/composite/ThebesLayerComposite.h @@ -86,8 +86,6 @@ protected: private: gfx::Filter GetEffectFilter() { return gfx::Filter::LINEAR; } - CSSToScreenScale GetEffectiveResolution(); - private: RefPtr mBuffer; }; diff --git a/gfx/layers/composite/TiledContentHost.cpp b/gfx/layers/composite/TiledContentHost.cpp index b30cbfa4405e..1e0d23c58a26 100644 --- a/gfx/layers/composite/TiledContentHost.cpp +++ b/gfx/layers/composite/TiledContentHost.cpp @@ -9,6 +9,7 @@ #include "mozilla/gfx/Matrix.h" // for Matrix4x4 #include "mozilla/layers/Compositor.h" // for Compositor #include "mozilla/layers/Effects.h" // for TexturedEffect, Effect, etc +#include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper #include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL #include "nsAString.h" #include "nsDebug.h" // for NS_WARNING @@ -367,7 +368,7 @@ TiledContentHost::Composite(EffectChain& aEffectChain, // Background colors are only stored on scrollable layers. Grab // the one from the nearest scrollable ancestor layer. for (Layer* ancestor = GetLayer(); ancestor; ancestor = ancestor->GetParent()) { - if (ancestor->GetFrameMetrics().IsScrollable()) { + if (ancestor->HasScrollableFrameMetrics()) { backgroundColor = ancestor->GetBackgroundColor(); break; } From fe7f22ce278ee004d905835c3f5588bc0e227313 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 27 Aug 2014 22:13:43 -0400 Subject: [PATCH 45/60] Bug 1055760 - Update frame uniformity code to use the shadow transform. r=BenWa,mchang --- .../composite/ContainerLayerComposite.cpp | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/gfx/layers/composite/ContainerLayerComposite.cpp b/gfx/layers/composite/ContainerLayerComposite.cpp index ecbb9cb88eef..b076bf8898c5 100644 --- a/gfx/layers/composite/ContainerLayerComposite.cpp +++ b/gfx/layers/composite/ContainerLayerComposite.cpp @@ -121,21 +121,13 @@ static void PrintUniformityInfo(Layer* aLayer) return; } - FrameMetrics frameMetrics = aLayer->GetFrameMetrics(); - if (!frameMetrics.IsScrollable()) { + Matrix4x4 transform = aLayer->AsLayerComposite()->GetShadowTransform(); + if (!transform.Is2D()) { return; } - - AsyncPanZoomController* apzc = aLayer->GetAsyncPanZoomController(); - if (apzc) { - ViewTransform asyncTransform, overscrollTransform; - ScreenPoint scrollOffset; - apzc->SampleContentTransformForFrame(&asyncTransform, - scrollOffset, - &overscrollTransform); - printf_stderr("UniformityInfo Layer_Move %llu %p %f, %f\n", - TimeStamp::Now(), aLayer, scrollOffset.x.value, scrollOffset.y.value); - } + Point translation = transform.As2D().GetTranslation(); + printf_stderr("UniformityInfo Layer_Move %llu %p %f, %f\n", + TimeStamp::Now(), aLayer, translation.x.value, translation.y.value); } /* all of the per-layer prepared data we need to maintain */ From e0a4bd21ea079e06abc5576d9db6bde59725d980 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 27 Aug 2014 22:13:43 -0400 Subject: [PATCH 46/60] Bug 1055760 - Update SetAsyncScrollOffset test API to deal wth multiple FrameMetrics. r=roc --- dom/base/nsDOMWindowUtils.cpp | 6 +++++- gfx/layers/ipc/LayerTransactionParent.cpp | 9 ++++++++- gfx/layers/ipc/LayerTransactionParent.h | 2 +- gfx/layers/ipc/PLayerTransaction.ipdl | 3 ++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index b875903d32f8..060536d88193 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -2702,12 +2702,16 @@ nsDOMWindowUtils::SetAsyncScrollOffset(nsIDOMNode* aNode, return NS_ERROR_UNEXPECTED; } } + FrameMetrics::ViewID viewId; + if (!nsLayoutUtils::FindIDFor(element, &viewId)) { + return NS_ERROR_UNEXPECTED; + } ShadowLayerForwarder* forwarder = layer->Manager()->AsShadowForwarder(); if (!forwarder || !forwarder->HasShadowManager()) { return NS_ERROR_UNEXPECTED; } forwarder->GetShadowManager()->SendSetAsyncScrollOffset( - layer->AsShadowableLayer()->GetShadow(), aX, aY); + layer->AsShadowableLayer()->GetShadow(), viewId, aX, aY); return NS_OK; } diff --git a/gfx/layers/ipc/LayerTransactionParent.cpp b/gfx/layers/ipc/LayerTransactionParent.cpp index 717666873740..f748a3c321bf 100644 --- a/gfx/layers/ipc/LayerTransactionParent.cpp +++ b/gfx/layers/ipc/LayerTransactionParent.cpp @@ -679,6 +679,7 @@ LayerTransactionParent::RecvGetAnimationTransform(PLayerParent* aParent, bool LayerTransactionParent::RecvSetAsyncScrollOffset(PLayerParent* aLayer, + const FrameMetrics::ViewID& aId, const int32_t& aX, const int32_t& aY) { if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) { @@ -689,7 +690,13 @@ LayerTransactionParent::RecvSetAsyncScrollOffset(PLayerParent* aLayer, if (!layer) { return false; } - AsyncPanZoomController* controller = layer->GetAsyncPanZoomController(); + AsyncPanZoomController* controller = nullptr; + for (uint32_t i = 0; i < layer->GetFrameMetricsCount(); i++) { + if (layer->GetFrameMetrics(i).GetScrollId() == aId) { + controller = layer->GetAsyncPanZoomController(i); + break; + } + } if (!controller) { return false; } diff --git a/gfx/layers/ipc/LayerTransactionParent.h b/gfx/layers/ipc/LayerTransactionParent.h index dd428127e5ff..c3401d17ef63 100644 --- a/gfx/layers/ipc/LayerTransactionParent.h +++ b/gfx/layers/ipc/LayerTransactionParent.h @@ -124,7 +124,7 @@ protected: virtual bool RecvGetAnimationTransform(PLayerParent* aParent, MaybeTransform* aTransform) MOZ_OVERRIDE; - virtual bool RecvSetAsyncScrollOffset(PLayerParent* aLayer, + virtual bool RecvSetAsyncScrollOffset(PLayerParent* aLayer, const FrameMetrics::ViewID& aId, const int32_t& aX, const int32_t& aY) MOZ_OVERRIDE; virtual bool RecvGetAPZTestData(APZTestData* aOutData); diff --git a/gfx/layers/ipc/PLayerTransaction.ipdl b/gfx/layers/ipc/PLayerTransaction.ipdl index 5f3a3debcd51..99faa20c90ac 100644 --- a/gfx/layers/ipc/PLayerTransaction.ipdl +++ b/gfx/layers/ipc/PLayerTransaction.ipdl @@ -19,6 +19,7 @@ using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h using struct mozilla::void_t from "ipc/IPCMessageUtils.h"; using mozilla::layers::TextureFlags from "mozilla/layers/CompositorTypes.h"; using class mozilla::layers::APZTestData from "mozilla/layers/APZTestData.h"; +using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h"; /** * The layers protocol is spoken between thread contexts that manage @@ -83,7 +84,7 @@ parent: // The next time this layer is composited, add this async scroll offset in // CSS pixels. // Useful for testing rendering of async scrolling. - async SetAsyncScrollOffset(PLayer layer, int32_t x, int32_t y); + async SetAsyncScrollOffset(PLayer layer, ViewID id, int32_t x, int32_t y); // Drop any front buffers that might be retained on the compositor // side. From d591fbed2a579056ca5fc306da926b1fc5cbb4df Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 27 Aug 2014 22:13:43 -0400 Subject: [PATCH 47/60] Bug 1055760 - Update TestAsyncPanZoomController to deal with multiple FrameMetrics. r=botond --- .../gtest/TestAsyncPanZoomController.cpp | 99 ++++++++++--------- 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index 16b72aee0258..b5d563f06628 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -12,6 +12,7 @@ #include "mozilla/layers/GeckoContentController.h" #include "mozilla/layers/CompositorParent.h" #include "mozilla/layers/APZCTreeManager.h" +#include "mozilla/layers/LayerMetricsWrapper.h" #include "mozilla/UniquePtr.h" #include "base/task.h" #include "Layers.h" @@ -1495,7 +1496,7 @@ TEST_F(APZHitTestingTester, HitTesting1) { SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID); manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, paintSequenceNumber++); hit = GetTargetAPZC(ScreenPoint(15, 15)); - EXPECT_EQ(root->GetAsyncPanZoomController(), hit.get()); + EXPECT_EQ(root->GetAsyncPanZoomController(0), hit.get()); // expect hit point at LayerIntPoint(15, 15) EXPECT_EQ(Point(15, 15), transformToApzc * Point(15, 15)); EXPECT_EQ(Point(15, 15), transformToGecko * Point(15, 15)); @@ -1503,9 +1504,9 @@ TEST_F(APZHitTestingTester, HitTesting1) { // Now we have a sub APZC with a better fit SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID + 1); manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, paintSequenceNumber++); - EXPECT_NE(root->GetAsyncPanZoomController(), layers[3]->GetAsyncPanZoomController()); + EXPECT_NE(root->GetAsyncPanZoomController(0), layers[3]->GetAsyncPanZoomController(0)); hit = GetTargetAPZC(ScreenPoint(25, 25)); - EXPECT_EQ(layers[3]->GetAsyncPanZoomController(), hit.get()); + EXPECT_EQ(layers[3]->GetAsyncPanZoomController(0), hit.get()); // expect hit point at LayerIntPoint(25, 25) EXPECT_EQ(Point(25, 25), transformToApzc * Point(25, 25)); EXPECT_EQ(Point(25, 25), transformToGecko * Point(25, 25)); @@ -1513,20 +1514,20 @@ TEST_F(APZHitTestingTester, HitTesting1) { // At this point, layers[4] obscures layers[3] at the point (15, 15) so // hitting there should hit the root APZC hit = GetTargetAPZC(ScreenPoint(15, 15)); - EXPECT_EQ(root->GetAsyncPanZoomController(), hit.get()); + EXPECT_EQ(root->GetAsyncPanZoomController(0), hit.get()); // Now test hit testing when we have two scrollable layers SetScrollableFrameMetrics(layers[4], FrameMetrics::START_SCROLL_ID + 2); manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, paintSequenceNumber++); hit = GetTargetAPZC(ScreenPoint(15, 15)); - EXPECT_EQ(layers[4]->GetAsyncPanZoomController(), hit.get()); + EXPECT_EQ(layers[4]->GetAsyncPanZoomController(0), hit.get()); // expect hit point at LayerIntPoint(15, 15) EXPECT_EQ(Point(15, 15), transformToApzc * Point(15, 15)); EXPECT_EQ(Point(15, 15), transformToGecko * Point(15, 15)); // Hit test ouside the reach of layer[3,4] but inside root hit = GetTargetAPZC(ScreenPoint(90, 90)); - EXPECT_EQ(root->GetAsyncPanZoomController(), hit.get()); + EXPECT_EQ(root->GetAsyncPanZoomController(0), hit.get()); // expect hit point at LayerIntPoint(90, 90) EXPECT_EQ(Point(90, 90), transformToApzc * Point(90, 90)); EXPECT_EQ(Point(90, 90), transformToGecko * Point(90, 90)); @@ -1555,9 +1556,9 @@ TEST_F(APZHitTestingTester, HitTesting2) { // layers[2] has content from (20,60)-(100,100). no clipping as it's not a scrollable layer // layers[3] has content from (20,60)-(180,140), clipped by composition bounds (20,60)-(100,100) - AsyncPanZoomController* apzcroot = root->GetAsyncPanZoomController(); - AsyncPanZoomController* apzc1 = layers[1]->GetAsyncPanZoomController(); - AsyncPanZoomController* apzc3 = layers[3]->GetAsyncPanZoomController(); + AsyncPanZoomController* apzcroot = root->GetAsyncPanZoomController(0); + AsyncPanZoomController* apzc1 = layers[1]->GetAsyncPanZoomController(0); + AsyncPanZoomController* apzc3 = layers[3]->GetAsyncPanZoomController(0); // Hit an area that's clearly on the root layer but not any of the child layers. nsRefPtr hit = GetTargetAPZC(ScreenPoint(75, 25)); @@ -1670,21 +1671,21 @@ TEST_F(APZCTreeManagerTester, ScrollableThebesLayers) { AsyncPanZoomController* nullAPZC = nullptr; // so they should have the same APZC - EXPECT_EQ(nullAPZC, layers[0]->GetAsyncPanZoomController()); - EXPECT_NE(nullAPZC, layers[1]->GetAsyncPanZoomController()); - EXPECT_NE(nullAPZC, layers[2]->GetAsyncPanZoomController()); - EXPECT_EQ(layers[1]->GetAsyncPanZoomController(), layers[2]->GetAsyncPanZoomController()); + EXPECT_FALSE(layers[0]->HasScrollableFrameMetrics()); + EXPECT_NE(nullAPZC, layers[1]->GetAsyncPanZoomController(0)); + EXPECT_NE(nullAPZC, layers[2]->GetAsyncPanZoomController(0)); + EXPECT_EQ(layers[1]->GetAsyncPanZoomController(0), layers[2]->GetAsyncPanZoomController(0)); // Change the scrollId of layers[1], and verify the APZC changes SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID + 1); manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); - EXPECT_NE(layers[1]->GetAsyncPanZoomController(), layers[2]->GetAsyncPanZoomController()); + EXPECT_NE(layers[1]->GetAsyncPanZoomController(0), layers[2]->GetAsyncPanZoomController(0)); // Change the scrollId of layers[2] to match that of layers[1], ensure we get the same // APZC for both again SetScrollableFrameMetrics(layers[2], FrameMetrics::START_SCROLL_ID + 1); manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); - EXPECT_EQ(layers[1]->GetAsyncPanZoomController(), layers[2]->GetAsyncPanZoomController()); + EXPECT_EQ(layers[1]->GetAsyncPanZoomController(0), layers[2]->GetAsyncPanZoomController(0)); } TEST_F(APZHitTestingTester, ComplexMultiLayerTree) { @@ -1694,32 +1695,32 @@ TEST_F(APZHitTestingTester, ComplexMultiLayerTree) { AsyncPanZoomController* nullAPZC = nullptr; // Ensure all the scrollable layers have an APZC - EXPECT_EQ(nullAPZC, layers[0]->GetAsyncPanZoomController()); - EXPECT_NE(nullAPZC, layers[1]->GetAsyncPanZoomController()); - EXPECT_NE(nullAPZC, layers[2]->GetAsyncPanZoomController()); - EXPECT_EQ(nullAPZC, layers[3]->GetAsyncPanZoomController()); - EXPECT_NE(nullAPZC, layers[4]->GetAsyncPanZoomController()); - EXPECT_EQ(nullAPZC, layers[5]->GetAsyncPanZoomController()); - EXPECT_NE(nullAPZC, layers[6]->GetAsyncPanZoomController()); - EXPECT_NE(nullAPZC, layers[7]->GetAsyncPanZoomController()); - EXPECT_NE(nullAPZC, layers[8]->GetAsyncPanZoomController()); + EXPECT_FALSE(layers[0]->HasScrollableFrameMetrics()); + EXPECT_NE(nullAPZC, layers[1]->GetAsyncPanZoomController(0)); + EXPECT_NE(nullAPZC, layers[2]->GetAsyncPanZoomController(0)); + EXPECT_FALSE(layers[3]->HasScrollableFrameMetrics()); + EXPECT_NE(nullAPZC, layers[4]->GetAsyncPanZoomController(0)); + EXPECT_FALSE(layers[5]->HasScrollableFrameMetrics()); + EXPECT_NE(nullAPZC, layers[6]->GetAsyncPanZoomController(0)); + EXPECT_NE(nullAPZC, layers[7]->GetAsyncPanZoomController(0)); + EXPECT_NE(nullAPZC, layers[8]->GetAsyncPanZoomController(0)); // Ensure those that scroll together have the same APZCs - EXPECT_EQ(layers[1]->GetAsyncPanZoomController(), layers[2]->GetAsyncPanZoomController()); - EXPECT_EQ(layers[4]->GetAsyncPanZoomController(), layers[6]->GetAsyncPanZoomController()); + EXPECT_EQ(layers[1]->GetAsyncPanZoomController(0), layers[2]->GetAsyncPanZoomController(0)); + EXPECT_EQ(layers[4]->GetAsyncPanZoomController(0), layers[6]->GetAsyncPanZoomController(0)); // Ensure those that don't scroll together have different APZCs - EXPECT_NE(layers[1]->GetAsyncPanZoomController(), layers[4]->GetAsyncPanZoomController()); - EXPECT_NE(layers[1]->GetAsyncPanZoomController(), layers[7]->GetAsyncPanZoomController()); - EXPECT_NE(layers[1]->GetAsyncPanZoomController(), layers[8]->GetAsyncPanZoomController()); - EXPECT_NE(layers[4]->GetAsyncPanZoomController(), layers[7]->GetAsyncPanZoomController()); - EXPECT_NE(layers[4]->GetAsyncPanZoomController(), layers[8]->GetAsyncPanZoomController()); - EXPECT_NE(layers[7]->GetAsyncPanZoomController(), layers[8]->GetAsyncPanZoomController()); + EXPECT_NE(layers[1]->GetAsyncPanZoomController(0), layers[4]->GetAsyncPanZoomController(0)); + EXPECT_NE(layers[1]->GetAsyncPanZoomController(0), layers[7]->GetAsyncPanZoomController(0)); + EXPECT_NE(layers[1]->GetAsyncPanZoomController(0), layers[8]->GetAsyncPanZoomController(0)); + EXPECT_NE(layers[4]->GetAsyncPanZoomController(0), layers[7]->GetAsyncPanZoomController(0)); + EXPECT_NE(layers[4]->GetAsyncPanZoomController(0), layers[8]->GetAsyncPanZoomController(0)); + EXPECT_NE(layers[7]->GetAsyncPanZoomController(0), layers[8]->GetAsyncPanZoomController(0)); nsRefPtr hit = GetTargetAPZC(ScreenPoint(25, 25)); - EXPECT_EQ(layers[1]->GetAsyncPanZoomController(), hit.get()); + EXPECT_EQ(layers[1]->GetAsyncPanZoomController(0), hit.get()); hit = GetTargetAPZC(ScreenPoint(275, 375)); - EXPECT_EQ(layers[8]->GetAsyncPanZoomController(), hit.get()); + EXPECT_EQ(layers[8]->GetAsyncPanZoomController(0), hit.get()); hit = GetTargetAPZC(ScreenPoint(250, 100)); - EXPECT_EQ(layers[7]->GetAsyncPanZoomController(), hit.get()); + EXPECT_EQ(layers[7]->GetAsyncPanZoomController(0), hit.get()); } class APZOverscrollHandoffTester : public APZCTreeManagerTester { @@ -1728,8 +1729,8 @@ protected: TestAsyncPanZoomController* rootApzc; void SetScrollHandoff(Layer* aChild, Layer* aParent) { - FrameMetrics metrics = aChild->GetFrameMetrics(); - metrics.SetScrollParentId(aParent->GetFrameMetrics().GetScrollId()); + FrameMetrics metrics = aChild->GetFrameMetrics(0); + metrics.SetScrollParentId(aParent->GetFrameMetrics(0).GetScrollId()); aChild->SetFrameMetrics(metrics); } @@ -1745,7 +1746,7 @@ protected: SetScrollHandoff(layers[1], root); registration = MakeUnique(0, root, mcc); manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); - rootApzc = (TestAsyncPanZoomController*)root->GetAsyncPanZoomController(); + rootApzc = (TestAsyncPanZoomController*)root->GetAsyncPanZoomController(0); } void CreateOverscrollHandoffLayerTree2() { @@ -1765,7 +1766,7 @@ protected: // and this is the second layer tree for a particular test. MOZ_ASSERT(registration); manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); - rootApzc = (TestAsyncPanZoomController*)root->GetAsyncPanZoomController(); + rootApzc = (TestAsyncPanZoomController*)root->GetAsyncPanZoomController(0); } void CreateOverscrollHandoffLayerTree3() { @@ -1800,7 +1801,7 @@ protected: SetScrollHandoff(layers[1], root); registration = MakeUnique(0, root, mcc); manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); - rootApzc = (TestAsyncPanZoomController*)root->GetAsyncPanZoomController(); + rootApzc = (TestAsyncPanZoomController*)root->GetAsyncPanZoomController(0); rootApzc->GetFrameMetrics().SetHasScrollgrab(true); } }; @@ -1812,7 +1813,7 @@ TEST_F(APZOverscrollHandoffTester, DeferredInputEventProcessing) { // Set up the APZC tree. CreateOverscrollHandoffLayerTree1(); - TestAsyncPanZoomController* childApzc = (TestAsyncPanZoomController*)layers[1]->GetAsyncPanZoomController(); + TestAsyncPanZoomController* childApzc = (TestAsyncPanZoomController*)layers[1]->GetAsyncPanZoomController(0); // Enable touch-listeners so that we can separate the queueing of input // events from them being processed. @@ -1839,7 +1840,7 @@ TEST_F(APZOverscrollHandoffTester, LayerStructureChangesWhileEventsArePending) { // Set up an initial APZC tree. CreateOverscrollHandoffLayerTree1(); - TestAsyncPanZoomController* childApzc = (TestAsyncPanZoomController*)layers[1]->GetAsyncPanZoomController(); + TestAsyncPanZoomController* childApzc = (TestAsyncPanZoomController*)layers[1]->GetAsyncPanZoomController(0); // Enable touch-listeners so that we can separate the queueing of input // events from them being processed. @@ -1854,7 +1855,7 @@ TEST_F(APZOverscrollHandoffTester, LayerStructureChangesWhileEventsArePending) { CreateOverscrollHandoffLayerTree2(); nsRefPtr middle = layers[1]; childApzc->GetFrameMetrics().mMayHaveTouchListeners = true; - TestAsyncPanZoomController* middleApzc = (TestAsyncPanZoomController*)middle->GetAsyncPanZoomController(); + TestAsyncPanZoomController* middleApzc = (TestAsyncPanZoomController*)middle->GetAsyncPanZoomController(0); // Queue input events for another pan. ApzcPanNoFling(childApzc, time, 30, 90); @@ -1884,10 +1885,10 @@ TEST_F(APZOverscrollHandoffTester, SimultaneousFlings) { // Set up an initial APZC tree. CreateOverscrollHandoffLayerTree3(); - TestAsyncPanZoomController* parent1 = (TestAsyncPanZoomController*)layers[1]->GetAsyncPanZoomController(); - TestAsyncPanZoomController* child1 = (TestAsyncPanZoomController*)layers[2]->GetAsyncPanZoomController(); - TestAsyncPanZoomController* parent2 = (TestAsyncPanZoomController*)layers[3]->GetAsyncPanZoomController(); - TestAsyncPanZoomController* child2 = (TestAsyncPanZoomController*)layers[4]->GetAsyncPanZoomController(); + TestAsyncPanZoomController* parent1 = (TestAsyncPanZoomController*)layers[1]->GetAsyncPanZoomController(0); + TestAsyncPanZoomController* child1 = (TestAsyncPanZoomController*)layers[2]->GetAsyncPanZoomController(0); + TestAsyncPanZoomController* parent2 = (TestAsyncPanZoomController*)layers[3]->GetAsyncPanZoomController(0); + TestAsyncPanZoomController* child2 = (TestAsyncPanZoomController*)layers[4]->GetAsyncPanZoomController(0); // Pan on the lower child. int time = 0; @@ -1916,7 +1917,7 @@ TEST_F(APZOverscrollHandoffTester, Scrollgrab) { // Set up the layer tree CreateScrollgrabLayerTree(); - TestAsyncPanZoomController* childApzc = (TestAsyncPanZoomController*)layers[1]->GetAsyncPanZoomController(); + TestAsyncPanZoomController* childApzc = (TestAsyncPanZoomController*)layers[1]->GetAsyncPanZoomController(0); // Pan on the child, enough to fully scroll the scrollgrab parent (20 px) // and leave some more (another 15 px) for the child. @@ -1932,7 +1933,7 @@ TEST_F(APZOverscrollHandoffTester, ScrollgrabFling) { // Set up the layer tree CreateScrollgrabLayerTree(); - TestAsyncPanZoomController* childApzc = (TestAsyncPanZoomController*)layers[1]->GetAsyncPanZoomController(); + TestAsyncPanZoomController* childApzc = (TestAsyncPanZoomController*)layers[1]->GetAsyncPanZoomController(0); // Pan on the child, not enough to fully scroll the scrollgrab parent. int time = 0; From 0a357da2bf78065a7238c04bd8164dcf303d996b Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 27 Aug 2014 22:13:43 -0400 Subject: [PATCH 48/60] Bug 1055760 - Add some basic gtests for LayerMetricsWrapper tree-walking. r=BenWa --- gfx/tests/gtest/TestLayers.cpp | 128 +++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/gfx/tests/gtest/TestLayers.cpp b/gfx/tests/gtest/TestLayers.cpp index 65ceecddef7f..8917cec8c23d 100644 --- a/gfx/tests/gtest/TestLayers.cpp +++ b/gfx/tests/gtest/TestLayers.cpp @@ -6,6 +6,7 @@ #include "TestLayers.h" #include "gtest/gtest.h" #include "gmock/gmock.h" +#include "mozilla/layers/LayerMetricsWrapper.h" using namespace mozilla; using namespace mozilla::gfx; @@ -322,3 +323,130 @@ TEST(Layers, RepositionChild) { ASSERT_EQ(layers[1], layers[2]->GetNextSibling()); ASSERT_EQ(nullptr, layers[1]->GetNextSibling()); } + +TEST(LayerMetricsWrapper, SimpleTree) { + nsTArray > layers; + nsRefPtr lm; + nsRefPtr root = CreateLayerTree("c(c(c(tt)c(t)))", nullptr, nullptr, lm, layers); + LayerMetricsWrapper wrapper(root); + + ASSERT_EQ(root.get(), wrapper.GetLayer()); + wrapper = wrapper.GetFirstChild(); + ASSERT_EQ(layers[1].get(), wrapper.GetLayer()); + ASSERT_FALSE(wrapper.GetNextSibling().IsValid()); + wrapper = wrapper.GetFirstChild(); + ASSERT_EQ(layers[2].get(), wrapper.GetLayer()); + wrapper = wrapper.GetFirstChild(); + ASSERT_EQ(layers[3].get(), wrapper.GetLayer()); + ASSERT_FALSE(wrapper.GetFirstChild().IsValid()); + wrapper = wrapper.GetNextSibling(); + ASSERT_EQ(layers[4].get(), wrapper.GetLayer()); + ASSERT_FALSE(wrapper.GetNextSibling().IsValid()); + wrapper = wrapper.GetParent(); + ASSERT_EQ(layers[2].get(), wrapper.GetLayer()); + wrapper = wrapper.GetNextSibling(); + ASSERT_EQ(layers[5].get(), wrapper.GetLayer()); + ASSERT_FALSE(wrapper.GetNextSibling().IsValid()); + wrapper = wrapper.GetLastChild(); + ASSERT_EQ(layers[6].get(), wrapper.GetLayer()); + wrapper = wrapper.GetParent(); + ASSERT_EQ(layers[5].get(), wrapper.GetLayer()); + LayerMetricsWrapper layer5 = wrapper; + wrapper = wrapper.GetPrevSibling(); + ASSERT_EQ(layers[2].get(), wrapper.GetLayer()); + wrapper = wrapper.GetParent(); + ASSERT_EQ(layers[1].get(), wrapper.GetLayer()); + ASSERT_TRUE(layer5 == wrapper.GetLastChild()); + LayerMetricsWrapper rootWrapper(root); + ASSERT_TRUE(rootWrapper == wrapper.GetParent()); +} + +static FrameMetrics +MakeMetrics(FrameMetrics::ViewID aId) { + FrameMetrics metrics; + metrics.SetScrollId(aId); + return metrics; +} + +TEST(LayerMetricsWrapper, MultiFramemetricsTree) { + nsTArray > layers; + nsRefPtr lm; + nsRefPtr root = CreateLayerTree("c(c(c(tt)c(t)))", nullptr, nullptr, lm, layers); + + nsTArray metrics; + metrics.InsertElementAt(0, MakeMetrics(FrameMetrics::START_SCROLL_ID + 0)); // topmost of root layer + metrics.InsertElementAt(0, MakeMetrics(FrameMetrics::NULL_SCROLL_ID)); + metrics.InsertElementAt(0, MakeMetrics(FrameMetrics::START_SCROLL_ID + 1)); + metrics.InsertElementAt(0, MakeMetrics(FrameMetrics::START_SCROLL_ID + 2)); + metrics.InsertElementAt(0, MakeMetrics(FrameMetrics::NULL_SCROLL_ID)); + metrics.InsertElementAt(0, MakeMetrics(FrameMetrics::NULL_SCROLL_ID)); // bottom of root layer + root->SetFrameMetrics(metrics); + + metrics.Clear(); + metrics.InsertElementAt(0, MakeMetrics(FrameMetrics::START_SCROLL_ID + 3)); + layers[1]->SetFrameMetrics(metrics); + + metrics.Clear(); + metrics.InsertElementAt(0, MakeMetrics(FrameMetrics::NULL_SCROLL_ID)); + metrics.InsertElementAt(0, MakeMetrics(FrameMetrics::START_SCROLL_ID + 4)); + layers[2]->SetFrameMetrics(metrics); + + metrics.Clear(); + metrics.InsertElementAt(0, MakeMetrics(FrameMetrics::START_SCROLL_ID + 5)); + layers[4]->SetFrameMetrics(metrics); + + metrics.Clear(); + metrics.InsertElementAt(0, MakeMetrics(FrameMetrics::START_SCROLL_ID + 6)); + layers[5]->SetFrameMetrics(metrics); + + LayerMetricsWrapper wrapper(root, LayerMetricsWrapper::StartAt::TOP); + nsTArray expectedLayers; + expectedLayers.AppendElement(layers[0].get()); + expectedLayers.AppendElement(layers[0].get()); + expectedLayers.AppendElement(layers[0].get()); + expectedLayers.AppendElement(layers[0].get()); + expectedLayers.AppendElement(layers[0].get()); + expectedLayers.AppendElement(layers[0].get()); + expectedLayers.AppendElement(layers[1].get()); + expectedLayers.AppendElement(layers[2].get()); + expectedLayers.AppendElement(layers[2].get()); + expectedLayers.AppendElement(layers[3].get()); + nsTArray expectedIds; + expectedIds.AppendElement(FrameMetrics::START_SCROLL_ID + 0); + expectedIds.AppendElement(FrameMetrics::NULL_SCROLL_ID); + expectedIds.AppendElement(FrameMetrics::START_SCROLL_ID + 1); + expectedIds.AppendElement(FrameMetrics::START_SCROLL_ID + 2); + expectedIds.AppendElement(FrameMetrics::NULL_SCROLL_ID); + expectedIds.AppendElement(FrameMetrics::NULL_SCROLL_ID); + expectedIds.AppendElement(FrameMetrics::START_SCROLL_ID + 3); + expectedIds.AppendElement(FrameMetrics::NULL_SCROLL_ID); + expectedIds.AppendElement(FrameMetrics::START_SCROLL_ID + 4); + expectedIds.AppendElement(FrameMetrics::NULL_SCROLL_ID); + for (int i = 0; i < 10; i++) { + ASSERT_EQ(expectedLayers[i], wrapper.GetLayer()); + ASSERT_EQ(expectedIds[i], wrapper.Metrics().GetScrollId()); + wrapper = wrapper.GetFirstChild(); + } + ASSERT_FALSE(wrapper.IsValid()); + + wrapper = LayerMetricsWrapper(root, LayerMetricsWrapper::StartAt::BOTTOM); + for (int i = 5; i < 10; i++) { + ASSERT_EQ(expectedLayers[i], wrapper.GetLayer()); + ASSERT_EQ(expectedIds[i], wrapper.Metrics().GetScrollId()); + wrapper = wrapper.GetFirstChild(); + } + ASSERT_FALSE(wrapper.IsValid()); + + wrapper = LayerMetricsWrapper(layers[4], LayerMetricsWrapper::StartAt::BOTTOM); + ASSERT_EQ(FrameMetrics::START_SCROLL_ID + 5, wrapper.Metrics().GetScrollId()); + wrapper = wrapper.GetParent(); + ASSERT_EQ(FrameMetrics::START_SCROLL_ID + 4, wrapper.Metrics().GetScrollId()); + ASSERT_EQ(layers[2].get(), wrapper.GetLayer()); + ASSERT_FALSE(wrapper.GetNextSibling().IsValid()); + wrapper = wrapper.GetParent(); + ASSERT_EQ(FrameMetrics::NULL_SCROLL_ID, wrapper.Metrics().GetScrollId()); + ASSERT_EQ(layers[2].get(), wrapper.GetLayer()); + wrapper = wrapper.GetNextSibling(); + ASSERT_EQ(FrameMetrics::START_SCROLL_ID + 6, wrapper.Metrics().GetScrollId()); + ASSERT_EQ(layers[5].get(), wrapper.GetLayer()); +} From 761e66c1419d48ae7eef75d37c8aba17f0db58c6 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 19:30:28 -0700 Subject: [PATCH 49/60] Bumping gaia.json for 4 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/6df2384e694d Author: Ryan VanderMeulen Desc: Merge pull request #23374 from etiennesegonzac/bug-1059108-webaudio-test-fail Bug 1059108 - Use a MockAudioContext's in the AudioCompeting unit tests. ======== https://hg.mozilla.org/integration/gaia-central/rev/389fa36261e6 Author: Etienne Segonzac Desc: Bug 1059108 - Use a MockAudioContext's in the AudioCompeting unit tests. ======== https://hg.mozilla.org/integration/gaia-central/rev/d6865dc53824 Author: EragonJ Desc: Merge pull request #23315 from EragonJ/bug-1058521 Bug 1058521 - [settings] move root panel screen lock item into panels/ro... r=Arthur, Zac ======== https://hg.mozilla.org/integration/gaia-central/rev/07ffd7eb7023 Author: EragonJ Desc: Bug 1058521 - [settings] move root panel screen lock item into panels/root --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 5af124c843c2..f1eeac62e922 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "f2bd86d28a6b5c2344cb0bc1076527f6179404c4", + "revision": "6df2384e694d9ec8b0ea945e7e0c1adb23989526", "repo_path": "/integration/gaia-central" } From 90d79d44eef541ec4833b507d0cdaac4401afa64 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 19:39:19 -0700 Subject: [PATCH 50/60] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 7cb3b9774e5b..e2ccf63b35ad 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 2a92ae346054..bf8eb81ee5f2 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 78d39408ef85..a65cbd0750cb 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index ebfffef8cb6c..dd2c634d3c61 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 2a92ae346054..bf8eb81ee5f2 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index c7da10259ae1..dba1a5efb050 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 66a6475d0212..536333aefefc 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index e1e027899335..fa0f0d9743ac 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 45c352e7d671..6be6e98cb763 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 2136f7f5f19c..3b912aeff3fe 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 228f718e773a6026eb97551744449ca9dad85219 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 19:45:31 -0700 Subject: [PATCH 51/60] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/198ce093d43e Author: Timothy Guan-tin Chien Desc: Merge pull request #23258 from timdream/keyboard-switch-fail Bug 1054184 - Don't clear active targets right away, r=rudyl ======== https://hg.mozilla.org/integration/gaia-central/rev/e2191e37f5aa Author: Timothy Guan-tin Chien Desc: Bug 1054184 - Don't clear active targets right away --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index f1eeac62e922..8df6e0bcc563 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "6df2384e694d9ec8b0ea945e7e0c1adb23989526", + "revision": "198ce093d43e19535d5b682334218e80d6889be7", "repo_path": "/integration/gaia-central" } From 583ff56f7dfd2b53a44a6f068d823577712ea2b5 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 19:55:26 -0700 Subject: [PATCH 52/60] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index e2ccf63b35ad..6f66028eeaf3 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index bf8eb81ee5f2..8fb3da223218 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index a65cbd0750cb..752f61edae96 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index dd2c634d3c61..d3d8dc949a99 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index bf8eb81ee5f2..8fb3da223218 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index dba1a5efb050..ce38a0c9fb5a 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 536333aefefc..3271758f1f88 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index fa0f0d9743ac..d8cfcd4454e0 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 6be6e98cb763..8110a76428a4 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 3b912aeff3fe..6c66f642349d 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From b479b9fef1384f341e50ef5b5199f04122c86b33 Mon Sep 17 00:00:00 2001 From: Vicamo Yang Date: Thu, 28 Aug 2014 11:00:03 +0800 Subject: [PATCH 53/60] Bug 878533 - 1/3: move MozSmsFilter to webidl dictionary. r=smaug --- dom/base/nsDOMClassInfo.cpp | 11 - dom/base/nsDOMClassInfoClasses.h | 1 - dom/bindings/Bindings.conf | 1 - dom/mobilemessage/interfaces/moz.build | 1 - .../interfaces/nsIDOMSmsFilter.idl | 33 -- .../nsIMobileMessageDatabaseService.idl | 14 +- .../src/MobileMessageManager.cpp | 59 +++- dom/mobilemessage/src/MobileMessageManager.h | 4 +- dom/mobilemessage/src/SmsFilter.cpp | 292 ------------------ dom/mobilemessage/src/SmsFilter.h | 43 --- dom/mobilemessage/src/Types.h | 22 +- .../android/MobileMessageDatabaseService.cpp | 12 +- .../src/gonk/MobileMessageDB.jsm | 54 +++- .../src/gonk/MobileMessageDatabaseService.js | 9 +- dom/mobilemessage/src/ipc/SmsIPCService.cpp | 34 +- dom/mobilemessage/src/ipc/SmsParent.cpp | 28 +- dom/mobilemessage/src/ipc/SmsTypes.ipdlh | 7 +- dom/mobilemessage/src/moz.build | 2 - dom/webidl/MozMobileMessageManager.webidl | 28 +- 19 files changed, 206 insertions(+), 449 deletions(-) delete mode 100644 dom/mobilemessage/interfaces/nsIDOMSmsFilter.idl delete mode 100644 dom/mobilemessage/src/SmsFilter.cpp delete mode 100644 dom/mobilemessage/src/SmsFilter.h diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index bc21c8409b23..89d950ca0f09 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -5,8 +5,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/ArrayUtils.h" -// On top because they include basictypes.h: -#include "mozilla/dom/SmsFilter.h" #ifdef XP_WIN #undef GetClassName @@ -125,7 +123,6 @@ #include "nsIDOMMozSmsMessage.h" #include "nsIDOMMozMmsMessage.h" -#include "nsIDOMSmsFilter.h" #include "nsIDOMMozMobileMessageThread.h" #ifdef MOZ_B2G_FM @@ -348,9 +345,6 @@ static nsDOMClassInfoData sClassInfoData[] = { NS_DEFINE_CLASSINFO_DATA(MozMmsMessage, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) - NS_DEFINE_CLASSINFO_DATA(MozSmsFilter, nsDOMGenericSH, - DOM_DEFAULT_SCRIPTABLE_FLAGS) - NS_DEFINE_CLASSINFO_DATA(MozMobileMessageThread, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) @@ -422,7 +416,6 @@ static const nsConstructorFuncMapData kConstructorFuncMap[] = { NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Blob, DOMMultipartFileImpl::NewBlob) NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, DOMMultipartFileImpl::NewFile) - NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozSmsFilter, SmsFilter::NewSmsFilter) NS_DEFINE_CONSTRUCTOR_FUNC_DATA(XSLTProcessor, XSLTProcessorCtor) }; #undef NS_DEFINE_CONSTRUCTOR_FUNC_DATA @@ -913,10 +906,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozMmsMessage) DOM_CLASSINFO_MAP_END - DOM_CLASSINFO_MAP_BEGIN(MozSmsFilter, nsIDOMMozSmsFilter) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsFilter) - DOM_CLASSINFO_MAP_END - DOM_CLASSINFO_MAP_BEGIN(MozMobileMessageThread, nsIDOMMozMobileMessageThread) DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozMobileMessageThread) DOM_CLASSINFO_MAP_END diff --git a/dom/base/nsDOMClassInfoClasses.h b/dom/base/nsDOMClassInfoClasses.h index 9ee2c1f6c747..c6de41eca5f9 100644 --- a/dom/base/nsDOMClassInfoClasses.h +++ b/dom/base/nsDOMClassInfoClasses.h @@ -55,7 +55,6 @@ DOMCI_CLASS(ModalContentWindow) DOMCI_CLASS(MozSmsMessage) DOMCI_CLASS(MozMmsMessage) -DOMCI_CLASS(MozSmsFilter) DOMCI_CLASS(MozMobileMessageThread) // @font-face in CSS diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index f5531fde16a7..3e7b6dd0b28e 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -1990,7 +1990,6 @@ addExternalIface('MozObserver', nativeType='nsIObserver', notflattened=True) addExternalIface('MozRDFCompositeDataSource', nativeType='nsIRDFCompositeDataSource', notflattened=True) addExternalIface('MozRDFResource', nativeType='nsIRDFResource', notflattened=True) -addExternalIface('MozSmsFilter', headerFile='nsIDOMSmsFilter.h') addExternalIface('MozSmsMessage') addExternalIface('MozTreeBoxObject', nativeType='nsITreeBoxObject', notflattened=True) diff --git a/dom/mobilemessage/interfaces/moz.build b/dom/mobilemessage/interfaces/moz.build index 62952307a93d..e35f078b6df0 100644 --- a/dom/mobilemessage/interfaces/moz.build +++ b/dom/mobilemessage/interfaces/moz.build @@ -9,7 +9,6 @@ XPIDL_SOURCES += [ 'nsIDOMMozMmsMessage.idl', 'nsIDOMMozMobileMessageThread.idl', 'nsIDOMMozSmsMessage.idl', - 'nsIDOMSmsFilter.idl', 'nsIMmsService.idl', 'nsIMobileMessageCallback.idl', 'nsIMobileMessageCursorCallback.idl', diff --git a/dom/mobilemessage/interfaces/nsIDOMSmsFilter.idl b/dom/mobilemessage/interfaces/nsIDOMSmsFilter.idl deleted file mode 100644 index cdc67d1b1197..000000000000 --- a/dom/mobilemessage/interfaces/nsIDOMSmsFilter.idl +++ /dev/null @@ -1,33 +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/. */ - -#include "nsISupports.idl" - -[scriptable, builtinclass, uuid(17890b60-0367-45c6-9729-62e5bf349b2b)] -interface nsIDOMMozSmsFilter : nsISupports -{ - // A date that can return null. - [implicit_jscontext] - attribute jsval startDate; - - // A date that can return null. - [implicit_jscontext] - attribute jsval endDate; - - // An array of DOMString that can return null. - [implicit_jscontext] - attribute jsval numbers; - - // A DOMString that can return and be set to "sent", "received" or null. - [Null(Empty)] - attribute DOMString delivery; - - // A read flag that can return and be set to a boolean or null. - [implicit_jscontext] - attribute jsval read; - - // A thread id that can return and be set to a numeric value or null. - [implicit_jscontext] - attribute jsval threadId; -}; diff --git a/dom/mobilemessage/interfaces/nsIMobileMessageDatabaseService.idl b/dom/mobilemessage/interfaces/nsIMobileMessageDatabaseService.idl index ac7b05c3365b..831d145bd906 100644 --- a/dom/mobilemessage/interfaces/nsIMobileMessageDatabaseService.idl +++ b/dom/mobilemessage/interfaces/nsIMobileMessageDatabaseService.idl @@ -12,11 +12,10 @@ %} interface nsICursorContinueCallback; -interface nsIDOMMozSmsFilter; interface nsIMobileMessageCallback; interface nsIMobileMessageCursorCallback; -[scriptable, uuid(8439916f-abc1-4c67-aa45-8a276a0a7855)] +[scriptable, uuid(ead626bc-f5b4-47e1-921c-0b956c9298e0)] interface nsIMobileMessageDatabaseService : nsISupports { [binaryname(GetMessageMoz)] @@ -27,7 +26,16 @@ interface nsIMobileMessageDatabaseService : nsISupports in uint32_t count, in nsIMobileMessageCallback request); - nsICursorContinueCallback createMessageCursor(in nsIDOMMozSmsFilter filter, + nsICursorContinueCallback createMessageCursor(in boolean hasStartDate, + in unsigned long long startDate, + in boolean hasEndDate, + in unsigned long long endDate, + [array, size_is(numbersCount)] in wstring numbers, + in uint32_t numbersCount, + [Null(Null), Undefined(Null)] in DOMString delivery, + in boolean hasRead, + in boolean read, + in unsigned long long threadId, in boolean reverse, in nsIMobileMessageCursorCallback callback); diff --git a/dom/mobilemessage/src/MobileMessageManager.cpp b/dom/mobilemessage/src/MobileMessageManager.cpp index 087f72df41bb..c5f62a1a784a 100644 --- a/dom/mobilemessage/src/MobileMessageManager.cpp +++ b/dom/mobilemessage/src/MobileMessageManager.cpp @@ -26,7 +26,6 @@ #include "nsIObserverService.h" #include "nsISmsService.h" #include "nsServiceManagerUtils.h" // For do_GetService() -#include "SmsFilter.h" #define RECEIVED_EVENT_NAME NS_LITERAL_STRING("received") #define RETRIEVING_EVENT_NAME NS_LITERAL_STRING("retrieving") @@ -367,7 +366,7 @@ MobileMessageManager::Delete(const Sequence -MobileMessageManager::GetMessages(nsIDOMMozSmsFilter* aFilter, +MobileMessageManager::GetMessages(const MobileMessageFilter& aFilter, bool aReverse, ErrorResult& aRv) { @@ -378,16 +377,62 @@ MobileMessageManager::GetMessages(nsIDOMMozSmsFilter* aFilter, return nullptr; } - nsCOMPtr filter = aFilter; - if (!filter) { - filter = new SmsFilter(); + bool hasStartDate = !aFilter.mStartDate.IsNull(); + uint64_t startDate = 0; + if (hasStartDate) { + startDate = aFilter.mStartDate.Value(); + } + + bool hasEndDate = !aFilter.mEndDate.IsNull(); + uint64_t endDate = 0; + if (hasEndDate) { + endDate = aFilter.mEndDate.Value(); + } + + nsAutoArrayPtr ptrNumbers; + uint32_t numbersCount = 0; + if (!aFilter.mNumbers.IsNull() && + aFilter.mNumbers.Value().Length()) { + const FallibleTArray& numbers = aFilter.mNumbers.Value(); + uint32_t index; + + numbersCount = numbers.Length(); + ptrNumbers = new const char16_t* [numbersCount]; + for (index = 0; index < numbersCount; index++) { + ptrNumbers[index] = numbers[index].get(); + } + } + + nsString delivery; + delivery.SetIsVoid(true); + if (!aFilter.mDelivery.IsNull()) { + const uint32_t index = static_cast(aFilter.mDelivery.Value()); + const EnumEntry& entry = + MobileMessageFilterDeliveryValues::strings[index]; + delivery.AssignASCII(entry.value, entry.length); + } + + bool hasRead = !aFilter.mRead.IsNull(); + bool read = false; + if (hasRead) { + read = aFilter.mRead.Value(); + } + + uint64_t threadId = 0; + if (!aFilter.mThreadId.IsNull()) { + threadId = aFilter.mThreadId.Value(); } nsRefPtr cursorCallback = new MobileMessageCursorCallback(); - nsCOMPtr continueCallback; - nsresult rv = dbService->CreateMessageCursor(filter, aReverse, cursorCallback, + nsresult rv = dbService->CreateMessageCursor(hasStartDate, startDate, + hasEndDate, endDate, + ptrNumbers, numbersCount, + delivery, + hasRead, read, + threadId, + aReverse, cursorCallback, getter_AddRefs(continueCallback)); if (NS_FAILED(rv)) { aRv.Throw(rv); diff --git a/dom/mobilemessage/src/MobileMessageManager.h b/dom/mobilemessage/src/MobileMessageManager.h index d99c224c4927..58f64afd687f 100644 --- a/dom/mobilemessage/src/MobileMessageManager.h +++ b/dom/mobilemessage/src/MobileMessageManager.h @@ -14,7 +14,6 @@ class nsISmsService; class nsIDOMMozSmsMessage; class nsIDOMMozMmsMessage; -class nsIDOMMozSmsFilter; namespace mozilla { namespace dom { @@ -23,6 +22,7 @@ class DOMRequest; class DOMCursor; struct MmsParameters; struct MmsSendParameters; +struct MobileMessageFilter; struct SmsSendParameters; class MobileMessageManager MOZ_FINAL : public DOMEventTargetHelper @@ -90,7 +90,7 @@ public: ErrorResult& aRv); already_AddRefed - GetMessages(nsIDOMMozSmsFilter* aFilter, + GetMessages(const MobileMessageFilter& aFilter, bool aReverse, ErrorResult& aRv); diff --git a/dom/mobilemessage/src/SmsFilter.cpp b/dom/mobilemessage/src/SmsFilter.cpp deleted file mode 100644 index 590de2d58fa7..000000000000 --- a/dom/mobilemessage/src/SmsFilter.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "SmsFilter.h" -#include "jsapi.h" -#include "jsfriendapi.h" // For js_DateGetMsecSinceEpoch. -#include "js/Utility.h" -#include "mozilla/dom/mobilemessage/Constants.h" // For MessageType -#include "mozilla/dom/ToJSValue.h" -#include "nsDOMString.h" -#include "nsError.h" -#include "nsIDOMClassInfo.h" -#include "nsJSUtils.h" - -using namespace mozilla::dom::mobilemessage; - -DOMCI_DATA(MozSmsFilter, mozilla::dom::SmsFilter) - -namespace mozilla { -namespace dom { - -NS_INTERFACE_MAP_BEGIN(SmsFilter) - NS_INTERFACE_MAP_ENTRY(nsIDOMMozSmsFilter) - NS_INTERFACE_MAP_ENTRY(nsISupports) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozSmsFilter) -NS_INTERFACE_MAP_END - -NS_IMPL_ADDREF(SmsFilter) -NS_IMPL_RELEASE(SmsFilter) - -SmsFilter::SmsFilter() -{ - mData.startDate() = 0; - mData.endDate() = 0; - mData.delivery() = eDeliveryState_Unknown; - mData.read() = eReadState_Unknown; - mData.threadId() = 0; -} - -SmsFilter::SmsFilter(const SmsFilterData& aData) - : mData(aData) -{ -} - -/* static */ nsresult -SmsFilter::NewSmsFilter(nsISupports** aSmsFilter) -{ - NS_ADDREF(*aSmsFilter = new SmsFilter()); - return NS_OK; -} - -NS_IMETHODIMP -SmsFilter::GetStartDate(JSContext* aCx, JS::MutableHandle aStartDate) -{ - if (mData.startDate() == 0) { - aStartDate.setNull(); - return NS_OK; - } - - aStartDate.setObjectOrNull(JS_NewDateObjectMsec(aCx, mData.startDate())); - NS_ENSURE_TRUE(aStartDate.isObject(), NS_ERROR_FAILURE); - - return NS_OK; -} - -NS_IMETHODIMP -SmsFilter::SetStartDate(JSContext* aCx, JS::Handle aStartDate) -{ - if (aStartDate.isNull()) { - mData.startDate() = 0; - return NS_OK; - } - - if (!aStartDate.isObject()) { - return NS_ERROR_INVALID_ARG; - } - - JS::Rooted obj(aCx, &aStartDate.toObject()); - if (!JS_ObjectIsDate(aCx, obj)) { - return NS_ERROR_INVALID_ARG; - } - - mData.startDate() = js_DateGetMsecSinceEpoch(obj); - return NS_OK; -} - -NS_IMETHODIMP -SmsFilter::GetEndDate(JSContext* aCx, JS::MutableHandle aEndDate) -{ - if (mData.endDate() == 0) { - aEndDate.setNull(); - return NS_OK; - } - - aEndDate.setObjectOrNull(JS_NewDateObjectMsec(aCx, mData.endDate())); - NS_ENSURE_TRUE(aEndDate.isObject(), NS_ERROR_FAILURE); - - return NS_OK; -} - -NS_IMETHODIMP -SmsFilter::SetEndDate(JSContext* aCx, JS::Handle aEndDate) -{ - if (aEndDate.isNull()) { - mData.endDate() = 0; - return NS_OK; - } - - if (!aEndDate.isObject()) { - return NS_ERROR_INVALID_ARG; - } - - JS::Rooted obj(aCx, &aEndDate.toObject()); - if (!JS_ObjectIsDate(aCx, obj)) { - return NS_ERROR_INVALID_ARG; - } - - mData.endDate() = js_DateGetMsecSinceEpoch(obj); - return NS_OK; -} - -NS_IMETHODIMP -SmsFilter::GetNumbers(JSContext* aCx, JS::MutableHandle aNumbers) -{ - uint32_t length = mData.numbers().Length(); - - if (length == 0) { - aNumbers.setNull(); - return NS_OK; - } - - if (!ToJSValue(aCx, mData.numbers(), aNumbers)) { - return NS_ERROR_FAILURE; - } - - return NS_OK; -} - -NS_IMETHODIMP -SmsFilter::SetNumbers(JSContext* aCx, JS::Handle aNumbers) -{ - if (aNumbers.isNull()) { - mData.numbers().Clear(); - return NS_OK; - } - - if (!aNumbers.isObject()) { - return NS_ERROR_INVALID_ARG; - } - - JS::Rooted obj(aCx, &aNumbers.toObject()); - if (!JS_IsArrayObject(aCx, obj)) { - return NS_ERROR_INVALID_ARG; - } - - uint32_t size; - MOZ_ALWAYS_TRUE(JS_GetArrayLength(aCx, obj, &size)); - - nsTArray numbers; - - for (uint32_t i=0; i jsNumber(aCx); - if (!JS_GetElement(aCx, obj, i, &jsNumber)) { - return NS_ERROR_INVALID_ARG; - } - - if (!jsNumber.isString()) { - return NS_ERROR_INVALID_ARG; - } - - nsAutoJSString number; - if (!number.init(aCx, jsNumber.toString())) { - return NS_ERROR_FAILURE; - } - - numbers.AppendElement(number); - } - - mData.numbers().Clear(); - mData.numbers().AppendElements(numbers); - - return NS_OK; -} - -NS_IMETHODIMP -SmsFilter::GetDelivery(nsAString& aDelivery) -{ - switch (mData.delivery()) { - case eDeliveryState_Received: - aDelivery = DELIVERY_RECEIVED; - break; - case eDeliveryState_Sent: - aDelivery = DELIVERY_SENT; - break; - case eDeliveryState_Unknown: - SetDOMStringToNull(aDelivery); - break; - default: - NS_ASSERTION(false, "We shouldn't get another delivery state!"); - return NS_ERROR_UNEXPECTED; - } - - return NS_OK; -} - -NS_IMETHODIMP -SmsFilter::SetDelivery(const nsAString& aDelivery) -{ - if (aDelivery.IsEmpty()) { - mData.delivery() = eDeliveryState_Unknown; - return NS_OK; - } - - if (aDelivery.Equals(DELIVERY_RECEIVED)) { - mData.delivery() = eDeliveryState_Received; - return NS_OK; - } - - if (aDelivery.Equals(DELIVERY_SENT)) { - mData.delivery() = eDeliveryState_Sent; - return NS_OK; - } - - return NS_ERROR_INVALID_ARG; -} - -NS_IMETHODIMP -SmsFilter::GetRead(JSContext* aCx, JS::MutableHandle aRead) -{ - if (mData.read() == eReadState_Unknown) { - aRead.setNull(); - return NS_OK; - } - - aRead.setBoolean(mData.read()); - return NS_OK; -} - -NS_IMETHODIMP -SmsFilter::SetRead(JSContext* aCx, JS::Handle aRead) -{ - if (aRead.isNull()) { - mData.read() = eReadState_Unknown; - return NS_OK; - } - - if (!aRead.isBoolean()) { - return NS_ERROR_INVALID_ARG; - } - - mData.read() = aRead.toBoolean() ? eReadState_Read : eReadState_Unread; - return NS_OK; -} - -NS_IMETHODIMP -SmsFilter::GetThreadId(JSContext* aCx, JS::MutableHandle aThreadId) -{ - if (!mData.threadId()) { - aThreadId.setNull(); - return NS_OK; - } - - aThreadId.setNumber(static_cast(mData.threadId())); - return NS_OK; -} - -NS_IMETHODIMP -SmsFilter::SetThreadId(JSContext* aCx, JS::Handle aThreadId) -{ - if (aThreadId.isNull()) { - mData.threadId() = 0; - return NS_OK; - } - - if (!aThreadId.isNumber()) { - return NS_ERROR_INVALID_ARG; - } - - double number = aThreadId.toNumber(); - uint64_t integer = static_cast(number); - if (integer == 0 || integer != number) { - return NS_ERROR_INVALID_ARG; - } - mData.threadId() = integer; - - return NS_OK; -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/mobilemessage/src/SmsFilter.h b/dom/mobilemessage/src/SmsFilter.h deleted file mode 100644 index 13754ab25416..000000000000 --- a/dom/mobilemessage/src/SmsFilter.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef mozilla_dom_mobilemessage_SmsFilter_h -#define mozilla_dom_mobilemessage_SmsFilter_h - -#include "mozilla/dom/mobilemessage/SmsTypes.h" -#include "nsIDOMSmsFilter.h" -#include "mozilla/Attributes.h" - -namespace mozilla { -namespace dom { - -class SmsFilter MOZ_FINAL : public nsIDOMMozSmsFilter -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIDOMMOZSMSFILTER - - SmsFilter(); - SmsFilter(const mobilemessage::SmsFilterData& aData); - - const mobilemessage::SmsFilterData& GetData() const; - - static nsresult NewSmsFilter(nsISupports** aSmsFilter); - -private: - ~SmsFilter() {} - - mobilemessage::SmsFilterData mData; -}; - -inline const mobilemessage::SmsFilterData& -SmsFilter::GetData() const { - return mData; -} - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_mobilemessage_SmsFilter_h diff --git a/dom/mobilemessage/src/Types.h b/dom/mobilemessage/src/Types.h index 5e29d59a011f..92781062dc05 100644 --- a/dom/mobilemessage/src/Types.h +++ b/dom/mobilemessage/src/Types.h @@ -48,16 +48,7 @@ enum ReadStatus { eReadStatus_EndGuard }; -// For {Mms,Sms}FilterData.read. -enum ReadState { - eReadState_Unknown = -1, - eReadState_Unread, - eReadState_Read, - // This state should stay at the end. - eReadState_EndGuard -}; - -// For {Mms,Sms}FilterData.messageClass. +// For {Mms,Sms}MessageData.messageClass. enum MessageClass { eMessageClass_Normal = 0, eMessageClass_Class0, @@ -115,17 +106,6 @@ struct ParamTraits mozilla::dom::mobilemessage::eReadStatus_EndGuard> {}; -/** - * Read state serializer. - */ -template <> -struct ParamTraits - : public ContiguousEnumSerializer< - mozilla::dom::mobilemessage::ReadState, - mozilla::dom::mobilemessage::eReadState_Unknown, - mozilla::dom::mobilemessage::eReadState_EndGuard> -{}; - /** * Message class serializer. */ diff --git a/dom/mobilemessage/src/android/MobileMessageDatabaseService.cpp b/dom/mobilemessage/src/android/MobileMessageDatabaseService.cpp index 5c540a512f04..6bf31333b005 100644 --- a/dom/mobilemessage/src/android/MobileMessageDatabaseService.cpp +++ b/dom/mobilemessage/src/android/MobileMessageDatabaseService.cpp @@ -3,7 +3,6 @@ * 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/. */ -#include "SmsFilter.h" #include "MobileMessageDatabaseService.h" #include "AndroidBridge.h" @@ -47,7 +46,16 @@ MobileMessageDatabaseService::DeleteMessage(int32_t *aMessageIds, } NS_IMETHODIMP -MobileMessageDatabaseService::CreateMessageCursor(nsIDOMMozSmsFilter* aFilter, +MobileMessageDatabaseService::CreateMessageCursor(bool aHasStartDate, + uint64_t aStartDate, + bool aHasEndDate, + uint64_t aEndDate, + const char16_t** aNumbers, + uint32_t aNumbersCount, + const nsAString& aDelivery, + bool aHasRead, + bool aRead, + uint64_t aThreadId, bool aReverse, nsIMobileMessageCursorCallback* aCallback, nsICursorContinueCallback** aResult) diff --git a/dom/mobilemessage/src/gonk/MobileMessageDB.jsm b/dom/mobilemessage/src/gonk/MobileMessageDB.jsm index 3ba8d2ebe53b..0f853ac7340f 100644 --- a/dom/mobilemessage/src/gonk/MobileMessageDB.jsm +++ b/dom/mobilemessage/src/gonk/MobileMessageDB.jsm @@ -3105,25 +3105,47 @@ MobileMessageDB.prototype = { }, [MESSAGE_STORE_NAME, THREAD_STORE_NAME]); }, - createMessageCursor: function(filter, reverse, callback) { + createMessageCursor: function(aHasStartDate, aStartDate, aHasEndDate, + aEndDate, aNumbers, aNumbersCount, aDelivery, + aHasRead, aRead, aThreadId, aReverse, aCallback) { if (DEBUG) { debug("Creating a message cursor. Filters:" + - " startDate: " + filter.startDate + - " endDate: " + filter.endDate + - " delivery: " + filter.delivery + - " numbers: " + filter.numbers + - " read: " + filter.read + - " threadId: " + filter.threadId + - " reverse: " + reverse); + " startDate: " + (aHasStartDate ? aStartDate : "(null)") + + " endDate: " + (aHasEndDate ? aEndDate : "(null)") + + " delivery: " + aDelivery + + " numbers: " + (aNumbersCount ? aNumbers : "(null)") + + " read: " + (aHasRead ? aRead : "(null)") + + " threadId: " + aThreadId + + " reverse: " + aReverse); } - let cursor = new GetMessagesCursor(this, callback); + let filter = {}; + if (aHasStartDate) { + filter.startDate = aStartDate; + } + if (aHasEndDate) { + filter.endDate = aEndDate; + } + if (aNumbersCount) { + filter.numbers = aNumbers.slice(); + } + if (aDelivery !== null) { + filter.delivery = aDelivery; + } + if (aHasRead) { + filter.read = aRead; + } + if (aThreadId) { + filter.threadId = aThreadId; + } + + let cursor = new GetMessagesCursor(this, aCallback); let self = this; self.newTxn(READ_ONLY, function(error, txn, stores) { let collector = cursor.collector; let collect = collector.collect.bind(collector); - FilterSearcherHelper.transact(self, txn, error, filter, reverse, collect); + FilterSearcherHelper.transact(self, txn, error, filter, aReverse, collect); }, [MESSAGE_STORE_NAME, PARTICIPANT_STORE_NAME]); return cursor; @@ -3311,11 +3333,11 @@ let FilterSearcherHelper = { filterTimestamp: function(startDate, endDate, direction, txn, collect) { let range = null; if (startDate != null && endDate != null) { - range = IDBKeyRange.bound(startDate.getTime(), endDate.getTime()); + range = IDBKeyRange.bound(startDate, endDate); } else if (startDate != null) { - range = IDBKeyRange.lowerBound(startDate.getTime()); + range = IDBKeyRange.lowerBound(startDate); } else if (endDate != null) { - range = IDBKeyRange.upperBound(endDate.getTime()); + range = IDBKeyRange.upperBound(endDate); } this.filterIndex("timestamp", range, direction, txn, collect); }, @@ -3330,7 +3352,7 @@ let FilterSearcherHelper = { * @param error * Previous error while creating the transaction. * @param filter - * A SmsFilter object. + * A MobileMessageFilter dictionary. * @param reverse * A boolean value indicating whether we should filter message in * reversed order. @@ -3368,10 +3390,10 @@ let FilterSearcherHelper = { // than all numeric values. let startDate = 0, endDate = ""; if (filter.startDate != null) { - startDate = filter.startDate.getTime(); + startDate = filter.startDate; } if (filter.endDate != null) { - endDate = filter.endDate.getTime(); + endDate = filter.endDate; } let single, intersectionCollector; diff --git a/dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js b/dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js index f31a16d9f055..0b10153aadbc 100644 --- a/dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js +++ b/dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js @@ -108,8 +108,13 @@ MobileMessageDatabaseService.prototype = { this.mmdb.deleteMessage(aMessageIds, aLength, aRequest); }, - createMessageCursor: function(aFilter, aReverse, aCallback) { - return this.mmdb.createMessageCursor(aFilter, aReverse, aCallback); + createMessageCursor: function(aHasStartDate, aStartDate, aHasEndDate, + aEndDate, aNumbers, aNumbersCount, aDelivery, + aHasRead, aRead, aThreadId, aReverse, aCallback) { + return this.mmdb.createMessageCursor(aHasStartDate, aStartDate, aHasEndDate, + aEndDate, aNumbers, aNumbersCount, + aDelivery, aHasRead, aRead, aThreadId, + aReverse, aCallback); }, markMessageRead: function(aMessageId, aValue, aSendReadReport, aRequest) { diff --git a/dom/mobilemessage/src/ipc/SmsIPCService.cpp b/dom/mobilemessage/src/ipc/SmsIPCService.cpp index 83f2931947c3..bc03cc14370a 100644 --- a/dom/mobilemessage/src/ipc/SmsIPCService.cpp +++ b/dom/mobilemessage/src/ipc/SmsIPCService.cpp @@ -8,7 +8,6 @@ #include "nsXULAppAPI.h" #include "mozilla/dom/mobilemessage/SmsChild.h" #include "SmsMessage.h" -#include "SmsFilter.h" #include "nsJSUtils.h" #include "mozilla/dom/MozMobileMessageManagerBinding.h" #include "mozilla/dom/BindingUtils.h" @@ -220,13 +219,40 @@ SmsIPCService::DeleteMessage(int32_t *aMessageIds, uint32_t aSize, } NS_IMETHODIMP -SmsIPCService::CreateMessageCursor(nsIDOMMozSmsFilter* aFilter, +SmsIPCService::CreateMessageCursor(bool aHasStartDate, + uint64_t aStartDate, + bool aHasEndDate, + uint64_t aEndDate, + const char16_t** aNumbers, + uint32_t aNumbersCount, + const nsAString& aDelivery, + bool aHasRead, + bool aRead, + uint64_t aThreadId, bool aReverse, nsIMobileMessageCursorCallback* aCursorCallback, nsICursorContinueCallback** aResult) { - const SmsFilterData& data = - SmsFilterData(static_cast(aFilter)->GetData()); + SmsFilterData data; + + data.hasStartDate() = aHasStartDate; + data.startDate() = aStartDate; + data.hasEndDate() = aHasEndDate; + data.startDate() = aEndDate; + + if (aNumbersCount && aNumbers) { + nsTArray& numbers = data.numbers(); + uint32_t index; + + for (index = 0; index < aNumbersCount; index++) { + numbers.AppendElement(aNumbers[index]); + } + } + + data.delivery() = aDelivery; + data.hasRead() = aHasRead; + data.read() = aRead; + data.threadId() = aThreadId; return SendCursorRequest(CreateMessageCursorRequest(data, aReverse), aCursorCallback, aResult); diff --git a/dom/mobilemessage/src/ipc/SmsParent.cpp b/dom/mobilemessage/src/ipc/SmsParent.cpp index 6f761786045b..3762c1966790 100644 --- a/dom/mobilemessage/src/ipc/SmsParent.cpp +++ b/dom/mobilemessage/src/ipc/SmsParent.cpp @@ -14,7 +14,6 @@ #include "SmsMessage.h" #include "MmsMessage.h" #include "nsIMobileMessageDatabaseService.h" -#include "SmsFilter.h" #include "MobileMessageThread.h" #include "nsIDOMFile.h" #include "mozilla/dom/ipc/Blob.h" @@ -774,10 +773,31 @@ MobileMessageCursorParent::DoRequest(const CreateMessageCursorRequest& aRequest) nsCOMPtr dbService = do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID); if (dbService) { - nsCOMPtr filter = new SmsFilter(aRequest.filter()); - bool reverse = aRequest.reverse(); + const SmsFilterData& filter = aRequest.filter(); - rv = dbService->CreateMessageCursor(filter, reverse, this, + const nsTArray& numbers = filter.numbers(); + nsAutoArrayPtr ptrNumbers; + uint32_t numbersCount = numbers.Length(); + if (numbersCount) { + uint32_t index; + + ptrNumbers = new const char16_t* [numbersCount]; + for (index = 0; index < numbersCount; index++) { + ptrNumbers[index] = numbers[index].get(); + } + } + + rv = dbService->CreateMessageCursor(filter.hasStartDate(), + filter.startDate(), + filter.hasEndDate(), + filter.endDate(), + ptrNumbers, numbersCount, + filter.delivery(), + filter.hasRead(), + filter.read(), + filter.threadId(), + aRequest.reverse(), + this, getter_AddRefs(mContinueCallback)); } diff --git a/dom/mobilemessage/src/ipc/SmsTypes.ipdlh b/dom/mobilemessage/src/ipc/SmsTypes.ipdlh index 5cc1283310cb..a3450a258a37 100644 --- a/dom/mobilemessage/src/ipc/SmsTypes.ipdlh +++ b/dom/mobilemessage/src/ipc/SmsTypes.ipdlh @@ -77,11 +77,14 @@ union MobileMessageData struct SmsFilterData { + bool hasStartDate; uint64_t startDate; + bool hasEndDate; uint64_t endDate; nsString[] numbers; - DeliveryState delivery; - ReadState read; + nsString delivery; + bool hasRead; + bool read; uint64_t threadId; }; diff --git a/dom/mobilemessage/src/moz.build b/dom/mobilemessage/src/moz.build index d889facc77a9..e7e9ea741697 100644 --- a/dom/mobilemessage/src/moz.build +++ b/dom/mobilemessage/src/moz.build @@ -40,7 +40,6 @@ EXPORTS.mozilla.dom += [ 'DOMMobileMessageError.h', 'MmsMessage.h', 'MobileMessageManager.h', - 'SmsFilter.h', 'SmsMessage.h', ] @@ -57,7 +56,6 @@ UNIFIED_SOURCES += [ 'MobileMessageManager.cpp', 'MobileMessageService.cpp', 'MobileMessageThread.cpp', - 'SmsFilter.cpp', 'SmsMessage.cpp', 'SmsServicesFactory.cpp', ] diff --git a/dom/webidl/MozMobileMessageManager.webidl b/dom/webidl/MozMobileMessageManager.webidl index 6f92d3de1628..1111ae35f675 100644 --- a/dom/webidl/MozMobileMessageManager.webidl +++ b/dom/webidl/MozMobileMessageManager.webidl @@ -5,7 +5,6 @@ */ interface MozMmsMessage; -interface MozSmsFilter; interface MozSmsMessage; dictionary SmsSegmentInfo { @@ -51,6 +50,31 @@ dictionary MmsSendParameters { // specified under the multi-sim scenario. }; +enum MobileMessageFilterDelivery { "sent", "received" }; + +dictionary MobileMessageFilter +{ + // Close lower bound range for filtering by the message timestamp. + // Time in milliseconds since Epoch. + [EnforceRange] DOMTimeStamp? startDate = null; + + // Close upper bound range for filtering by the message timestamp. + // Time in milliseconds since Epoch. + [EnforceRange] DOMTimeStamp? endDate = null; + + // An array of string message participant addresses that any of which + // appears or matches a message's sendor or recipients addresses. + sequence? numbers = null; + + MobileMessageFilterDelivery? delivery = null; + + // Filtering by whether a message has been read or not. + boolean? read = null; + + // Filtering by a message's threadId attribute. + [EnforceRange] unsigned long long? threadId = 0; +}; + [Pref="dom.sms.enabled"] interface MozMobileMessageManager : EventTarget { @@ -111,7 +135,7 @@ interface MozMobileMessageManager : EventTarget // Iterates through Moz{Mms,Sms}Message. [Throws] - DOMCursor getMessages(optional MozSmsFilter? filter = null, + DOMCursor getMessages(optional MobileMessageFilter filter, optional boolean reverse = false); [Throws] From acdc844938cd3e5f292930dd7c86fd648747e3a3 Mon Sep 17 00:00:00 2001 From: Vicamo Yang Date: Thu, 28 Aug 2014 11:00:03 +0800 Subject: [PATCH 54/60] Bug 878533 - 2/3: fix test cases. r=gene, r=smaug --- dom/mobilemessage/tests/marionette/head.js | 11 +- .../tests/marionette/mmdb_head.js | 17 ++- .../tests/marionette/test_filter_date.js | 28 ++-- .../tests/marionette/test_filter_mixed.js | 128 ++++++++++-------- .../tests/marionette/test_filter_number.js | 3 +- .../tests/marionette/test_filter_read.js | 6 +- .../tests/marionette/test_filter_received.js | 6 +- .../tests/marionette/test_filter_sent.js | 6 +- .../tests/marionette/test_filter_unread.js | 6 +- .../tests/marionette/test_getthreads.js | 6 +- .../tests/marionette/test_invalid_address.js | 3 - .../tests/marionette/test_message_classes.js | 2 +- .../marionette/test_mmdb_full_storage.js | 2 +- .../marionette/test_mmdb_upgradeSchema_22.js | 2 +- .../marionette/test_mmsmessage_attachments.js | 3 - .../test_phone_number_normalization.js | 3 - .../test_update_thread_record_in_delete.js | 3 - .../tests/mochitest/mochitest.ini | 1 - .../tests/mochitest/test_sms_basics.html | 1 - .../tests/mochitest/test_smsfilter.html | 90 ------------ .../mochitest/general/test_interfaces.html | 2 - 21 files changed, 119 insertions(+), 210 deletions(-) delete mode 100644 dom/mobilemessage/tests/mochitest/test_smsfilter.html diff --git a/dom/mobilemessage/tests/marionette/head.js b/dom/mobilemessage/tests/marionette/head.js index aab56904164f..c78720415567 100644 --- a/dom/mobilemessage/tests/marionette/head.js +++ b/dom/mobilemessage/tests/marionette/head.js @@ -243,18 +243,17 @@ function getMessage(aId) { * Reject params: * event -- a DOMEvent * - * @param aFilter an optional MozSmsFilter instance. - * @param aReverse a boolean value indicating whether the order of the messages - * should be reversed. + * @param aFilter [optional] + * A MobileMessageFilter object. + * @param aReverse [optional] + * A boolean value indicating whether the order of the message should be + * reversed. Default: false. * * @return A deferred promise. */ function getMessages(aFilter, aReverse) { let deferred = Promise.defer(); - if (!aFilter) { - aFilter = new MozSmsFilter; - } let messages = []; let cursor = manager.getMessages(aFilter, aReverse || false); cursor.onsuccess = function(aEvent) { diff --git a/dom/mobilemessage/tests/marionette/mmdb_head.js b/dom/mobilemessage/tests/marionette/mmdb_head.js index 11d120b203d1..6537783cdd83 100644 --- a/dom/mobilemessage/tests/marionette/mmdb_head.js +++ b/dom/mobilemessage/tests/marionette/mmdb_head.js @@ -328,8 +328,21 @@ function createMmdbCursor(aMmdb, aMethodName) { * * @return A deferred promise. */ -function createMessageCursor(aMmdb, aFilter, aReverse) { - return createMmdbCursor(aMmdb, "createMessageCursor", aFilter, aReverse); +function createMessageCursor(aMmdb, aStartDate = null, aEndDate = null, + aNumbers = null, aDelivery = null, aRead = null, + aThreadId = null, aReverse = false) { + return createMmdbCursor(aMmdb, "createMessageCursor", + aStartDate !== null, + aStartDate || 0, + aEndDate !== null, + aEndDate || 0, + aNumbers || null, + aNumbers && aNumbers.length || 0, + aDelivery || null, + aRead !== null, + aRead || false, + aThreadId || 0, + aReverse || false); } /** diff --git a/dom/mobilemessage/tests/marionette/test_filter_date.js b/dom/mobilemessage/tests/marionette/test_filter_date.js index 12108dc4872d..adb731e5c198 100644 --- a/dom/mobilemessage/tests/marionette/test_filter_date.js +++ b/dom/mobilemessage/tests/marionette/test_filter_date.js @@ -24,11 +24,11 @@ function simulateIncomingSms() { } function test(aStartDate, aEndDate, aExpectedMessages) { - let filter = new MozSmsFilter(); - if (aStartDate) { + let filter = {}; + if (aStartDate !== null) { filter.startDate = aStartDate; } - if (aEndDate) { + if (aEndDate !== null) { filter.endDate = aEndDate; } @@ -64,16 +64,16 @@ startTestCommon(function testCaseMain() { // Should return all messages. // .then(() => log("Testing [startTime, )")) - .then(() => test(new Date(startTime), null, allMessages)) + .then(() => test(startTime, null, allMessages)) .then(() => log("Testing (, endTime]")) - .then(() => test(null, new Date(endTime), allMessages)) + .then(() => test(null, endTime, allMessages)) .then(() => log("Testing [startTime, endTime]")) - .then(() => test(new Date(startTime), new Date(endTime), allMessages)) + .then(() => test(startTime, endTime, allMessages)) // Should return only messages with timestamp <= startTime. // .then(() => log("Testing [, startTime)")) - .then(() => test(null, new Date(startTime), + .then(() => test(null, startTime, reduceMessages(allMessages, (function(a, b) { return b <= a; @@ -82,7 +82,7 @@ startTestCommon(function testCaseMain() { // Should return only messages with timestamp <= startTime + 1. // .then(() => log("Testing [, startTime + 1)")) - .then(() => test(null, new Date(startTime + 1), + .then(() => test(null, startTime + 1, reduceMessages(allMessages, (function(a, b) { return b <= a; @@ -91,7 +91,7 @@ startTestCommon(function testCaseMain() { // Should return only messages with timestamp >= endTime. // .then(() => log("Testing [endTime, )")) - .then(() => test(new Date(endTime), null, + .then(() => test(endTime, null, reduceMessages(allMessages, (function(a, b) { return b >= a; @@ -100,7 +100,7 @@ startTestCommon(function testCaseMain() { // Should return only messages with timestamp >= endTime - 1. // .then(() => log("Testing [endTime - 1, )")) - .then(() => test(new Date(endTime - 1), null, + .then(() => test(endTime - 1, null, reduceMessages(allMessages, (function(a, b) { return b >= a; @@ -109,11 +109,11 @@ startTestCommon(function testCaseMain() { // Should return none. // .then(() => log("Testing [endTime + 1, )")) - .then(() => test(new Date(endTime + 1), null, [])) + .then(() => test(endTime + 1, null, [])) .then(() => log("Testing [endTime + 1, endTime + 86400000]")) - .then(() => test(new Date(endTime + 1), new Date(endTime + 86400000), [])) + .then(() => test(endTime + 1, endTime + 86400000, [])) .then(() => log("Testing (, startTime - 1]")) - .then(() => test(null, new Date(startTime - 1), [])) + .then(() => test(null, startTime - 1, [])) .then(() => log("Testing [startTime - 86400000, startTime - 1]")) - .then(() => test(new Date(startTime - 86400000), new Date(startTime - 1), [])); + .then(() => test(startTime - 86400000, startTime - 1, [])); }); diff --git a/dom/mobilemessage/tests/marionette/test_filter_mixed.js b/dom/mobilemessage/tests/marionette/test_filter_mixed.js index 5c1e8ce763b5..cac2d6e4e6b1 100644 --- a/dom/mobilemessage/tests/marionette/test_filter_mixed.js +++ b/dom/mobilemessage/tests/marionette/test_filter_mixed.js @@ -59,9 +59,6 @@ let tasks = { }; function getAllMessages(callback, filter, reverse) { - if (!filter) { - filter = new MozSmsFilter; - } let messages = []; let request = manager.getMessages(filter, reverse || false); request.onsuccess = function(event) { @@ -182,9 +179,10 @@ tasks.push(function assignInvalidThreadID() { tasks.push(function testDeliveryAndNumber() { log("Checking delivery == sent && number == 5555315550"); - let filter = new MozSmsFilter(); - filter.delivery = "sent"; - filter.numbers = ["5555315550"]; + let filter = { + delivery: "sent", + numbers: ["5555315550"], + }; getAllMessages(function(messages) { // Only { delivery: "sent", receiver: "+15555315550", read: true } is(messages.length, 1, "message count"); @@ -209,9 +207,10 @@ tasks.push(function testDeliveryAndNumber() { tasks.push(function testDeliveryAndNumberNotFound() { log("Checking delivery == sent && number == INVALID_NUMBER"); - let filter = new MozSmsFilter(); - filter.delivery = "sent"; - filter.numbers = [INVALID_NUMBER]; + let filter = { + delivery: "sent", + numbers: [INVALID_NUMBER], + }; getAllMessages(function(messages) { is(messages.length, 0, "message count"); @@ -221,9 +220,10 @@ tasks.push(function testDeliveryAndNumberNotFound() { tasks.push(function testDeliveryAndRead() { log("Checking delivery == received && read == true"); - let filter = new MozSmsFilter(); - filter.delivery = "received"; - filter.read = true; + let filter = { + delivery: "received", + read: true, + } getAllMessages(function(messages) { // { delivery: "received", sender: "5555315550", read: true }, // { delivery: "received", sender: "5555315552", read: true }, @@ -250,9 +250,10 @@ tasks.push(function testDeliveryAndRead() { tasks.push(function testDeliveryAndReadNotFound() { log("Checking delivery == sent && read == false"); - let filter = new MozSmsFilter(); - filter.delivery = "sent"; - filter.read = false; + let filter = { + delivery: "sent", + read: false, + }; getAllMessages(function(messages) { is(messages.length, 0, "message count"); @@ -262,9 +263,10 @@ tasks.push(function testDeliveryAndReadNotFound() { tasks.push(function testDeliveryAndThreadId() { log("Checking delivery == received && threadId == " + threadIds[0]); - let filter = new MozSmsFilter(); - filter.delivery = "sent"; - filter.threadId = threadIds[0]; + let filter = { + delivery: "sent", + threadId: threadIds[0], + }; getAllMessages(function(messages) { // { delivery: "sent", receiver: "+15555315550", threadId: threadIds[0]} is(messages.length, 1, "message count"); @@ -287,9 +289,10 @@ tasks.push(function testDeliveryAndThreadId() { tasks.push(function testDeliveryAndThreadIdNotFound() { log("Checking delivery == sent && threadId == INVALID_THREAD_ID"); - let filter = new MozSmsFilter(); - filter.delivery = "sent"; - filter.threadId = INVALID_THREAD_ID; + let filter = { + delivery: "sent", + threadId: INVALID_THREAD_ID, + }; getAllMessages(function(messages) { is(messages.length, 0, "message count"); @@ -299,9 +302,10 @@ tasks.push(function testDeliveryAndThreadIdNotFound() { tasks.push(function testNumberAndRead() { log("Checking number == 5555315550 && read == true"); - let filter = new MozSmsFilter(); - filter.numbers = ["5555315550"]; - filter.read = true; + let filter = { + numbers: ["5555315550"], + read: true, + }; getAllMessages(function(messages) { // { delivery: "sent", receiver: "+15555315550", read: true } // { delivery: "received", sender: "5555315550", read: true } @@ -327,9 +331,10 @@ tasks.push(function testNumberAndRead() { tasks.push(function testNumberAndReadNotFound() { log("Checking number == INVALID_NUMBER && read == true"); - let filter = new MozSmsFilter(); - filter.numbers = [INVALID_NUMBER]; - filter.read = true; + let filter = { + numbers: [INVALID_NUMBER], + read: true, + }; getAllMessages(function(messages) { is(messages.length, 0, "message count"); @@ -339,9 +344,10 @@ tasks.push(function testNumberAndReadNotFound() { tasks.push(function testNumberAndThreadId() { log("Checking number == 5555315550 && threadId == " + threadIds[0]); - let filter = new MozSmsFilter(); - filter.numbers = ["5555315550"]; - filter.threadId = threadIds[0]; + let filter = { + numbers: ["5555315550"], + threadId: threadIds[0], + }; getAllMessages(function(messages) { // { delivery: "sent", receiver: "+15555315550", read: true } // { delivery: "received", sender: "5555315550", read: true } @@ -367,9 +373,10 @@ tasks.push(function testNumberAndThreadId() { tasks.push(function testNumberAndThreadIdNotFound() { log("Checking number == INVALID_NUMBER && threadId == INVALID_THREAD_ID"); - let filter = new MozSmsFilter(); - filter.numbers = [INVALID_NUMBER]; - filter.threadId = INVALID_THREAD_ID; + let filter = { + numbers: [INVALID_NUMBER], + threadId: INVALID_THREAD_ID, + }; getAllMessages(function(messages) { is(messages.length, 0, "message count"); @@ -379,8 +386,9 @@ tasks.push(function testNumberAndThreadIdNotFound() { tasks.push(function testMultipleNumbers() { log("Checking number == 5555315550 || number == 5555315551"); - let filter = new MozSmsFilter(); - filter.numbers = ["5555315550", "5555315551"]; + let filter = { + numbers: ["5555315550", "5555315551"], + }; getAllMessages(function(messages) { // { delivery: "sent", receiver: "+15555315550", read: true } // { delivery: "received", sender: "5555315550", read: true } @@ -401,8 +409,9 @@ tasks.push(function testMultipleNumbers() { tasks.push(function testMultipleNumbersNotFound() { log("Checking number == INVALID_NUMBER || number == INVALID_NUMBER2"); - let filter = new MozSmsFilter(); - filter.numbers = [INVALID_NUMBER, INVALID_NUMBER2]; + let filter = { + numbers: [INVALID_NUMBER, INVALID_NUMBER2], + }; getAllMessages(function(messages) { is(messages.length, 0, "message count"); @@ -412,9 +421,10 @@ tasks.push(function testMultipleNumbersNotFound() { tasks.push(function testDeliveryAndMultipleNumbers() { log("Checking delivery == sent && (number == 5555315550 || number == 5555315551)"); - let filter = new MozSmsFilter(); - filter.delivery = "sent"; - filter.numbers = ["5555315550", "5555315551"]; + let filter = { + delivery: "sent", + numbers: ["5555315550", "5555315551"], + }; getAllMessages(function(messages) { // { delivery: "sent", receiver: "+15555315550", read: true } // { delivery: "sent", receiver: "+15555315551", read: true } @@ -434,9 +444,10 @@ tasks.push(function testDeliveryAndMultipleNumbers() { tasks.push(function testMultipleNumbersAndRead() { log("Checking (number == 5555315550 || number == 5555315551) && read == true"); - let filter = new MozSmsFilter(); - filter.numbers = ["5555315550", "5555315551"]; - filter.read = true; + let filter = { + numbers: ["5555315550", "5555315551"], + read: true, + }; getAllMessages(function(messages) { // { delivery: "sent", receiver: "+15555315550", read: true } // { delivery: "received", sender: "5555315550", read: true } @@ -457,9 +468,10 @@ tasks.push(function testMultipleNumbersAndRead() { tasks.push(function testMultipleNumbersAndThreadId() { log("Checking (number == 5555315550 || number == 5555315551) && threadId == " + threadIds[0]); - let filter = new MozSmsFilter(); - filter.numbers = ["5555315550", "5555315551"]; - filter.threadId = threadIds[0]; + let filter = { + numbers: ["5555315550", "5555315551"], + threadId: threadIds[0], + }; getAllMessages(function(messages) { // { delivery: "sent", receiver: "+15555315550", read: true } // { delivery: "received", sender: "5555315550", read: true } @@ -479,8 +491,9 @@ tasks.push(function testMultipleNumbersAndThreadId() { tasks.push(function testNationalNumber() { log("Checking number = 5555315550"); - let filter = new MozSmsFilter(); - filter.numbers = ["5555315550"]; + let filter = { + numbers: ["5555315550"], + }; getAllMessages(function(messages) { // { delivery: "sent", receiver: "+15555315550", read: true } // { delivery: "received", sender: "5555315550", read: true } @@ -498,8 +511,9 @@ tasks.push(function testNationalNumber() { tasks.push(function testInternationalNumber() { log("Checking number = +15555315550"); - let filter = new MozSmsFilter(); - filter.numbers = ["+15555315550"]; + let filter = { + numbers: ["+15555315550"], + }; getAllMessages(function(messages) { // { delivery: "sent", receiver: "+15555315550", read: true } // { delivery: "received", sender: "5555315550", read: true } @@ -517,9 +531,10 @@ tasks.push(function testInternationalNumber() { tasks.push(function testReadAndThreadId() { log("Checking read == true && threadId == " + threadIds[0]); - let filter = new MozSmsFilter(); - filter.read = true; - filter.threadId = threadIds[0]; + let filter = { + read: true, + threadId: threadIds[0], + }; getAllMessages(function(messages) { // { delivery: "sent", receiver: "+15555315550", read: true } // { delivery: "received", sender: "5555315550", read: true } @@ -543,9 +558,10 @@ tasks.push(function testReadAndThreadId() { tasks.push(function testReadAndThreadIdNotFound() { log("Checking read == true && threadId == INVALID_THREAD_ID"); - let filter = new MozSmsFilter(); - filter.read = true; - filter.threadId = INVALID_THREAD_ID; + let filter = { + read: true, + threadId: INVALID_THREAD_ID, + }; getAllMessages(function(messages) { is(messages.length, 0, "message count"); diff --git a/dom/mobilemessage/tests/marionette/test_filter_number.js b/dom/mobilemessage/tests/marionette/test_filter_number.js index 9d37dc5536e4..0688714f76ab 100644 --- a/dom/mobilemessage/tests/marionette/test_filter_number.js +++ b/dom/mobilemessage/tests/marionette/test_filter_number.js @@ -28,8 +28,7 @@ function genFailingMms(aReceivers) { function checkMessage(aNeedle, aValidNumbers) { log(" Verifying " + aNeedle); - let filter = new MozSmsFilter(); - filter.numbers = [aNeedle]; + let filter = { numbers: [aNeedle] }; return getMessages(filter) .then(function(messages) { // Check the messages are sent to/received from aValidNumbers. diff --git a/dom/mobilemessage/tests/marionette/test_filter_read.js b/dom/mobilemessage/tests/marionette/test_filter_read.js index 5ffb0d5aa71c..cbe67c624137 100644 --- a/dom/mobilemessage/tests/marionette/test_filter_read.js +++ b/dom/mobilemessage/tests/marionette/test_filter_read.js @@ -20,9 +20,8 @@ function verifyInitialState() { function deleteAllMsgs(nextFunction) { let msgList = new Array(); - let filter = new MozSmsFilter; - let cursor = manager.getMessages(filter, false); + let cursor = manager.getMessages(); ok(cursor instanceof DOMCursor, "cursor is instanceof " + cursor.constructor); @@ -162,11 +161,10 @@ function markMsgRead(smsMsgs) { } function getMsgs() { - var filter = new MozSmsFilter(); let foundSmsList = new Array(); // Set filter for read messages - filter.read = true; + let filter = { read: true }; log("Getting the read SMS messages."); let cursor = manager.getMessages(filter, false); diff --git a/dom/mobilemessage/tests/marionette/test_filter_received.js b/dom/mobilemessage/tests/marionette/test_filter_received.js index f935ed5ed27f..6e1d4da2e97e 100644 --- a/dom/mobilemessage/tests/marionette/test_filter_received.js +++ b/dom/mobilemessage/tests/marionette/test_filter_received.js @@ -20,9 +20,8 @@ function verifyInitialState() { function deleteAllMsgs(nextFunction) { let msgList = new Array(); - let filter = new MozSmsFilter; - let cursor = manager.getMessages(filter, false); + let cursor = manager.getMessages(); ok(cursor instanceof DOMCursor, "cursor is instanceof " + cursor.constructor); @@ -174,11 +173,10 @@ function sendSms() { } function getMsgs() { - var filter = new MozSmsFilter(); let foundSmsList = new Array(); // Set filter for received messages - filter.delivery = "received"; + let filter = { delivery: "received" }; log("Getting the received SMS messages."); let cursor = manager.getMessages(filter, false); diff --git a/dom/mobilemessage/tests/marionette/test_filter_sent.js b/dom/mobilemessage/tests/marionette/test_filter_sent.js index cd9655fe39b5..e4d6f07d3be4 100644 --- a/dom/mobilemessage/tests/marionette/test_filter_sent.js +++ b/dom/mobilemessage/tests/marionette/test_filter_sent.js @@ -20,9 +20,8 @@ function verifyInitialState() { function deleteAllMsgs(nextFunction) { let msgList = new Array(); - let filter = new MozSmsFilter; - let cursor = manager.getMessages(filter, false); + let cursor = manager.getMessages(); ok(cursor instanceof DOMCursor, "cursor is instanceof " + cursor.constructor); @@ -171,11 +170,10 @@ manager.onreceived = function onreceived(event) { }; function getMsgs() { - var filter = new MozSmsFilter(); let foundSmsList = new Array(); // Set filter for sent messages - filter.delivery = "sent"; + let filter = { delivery: "sent" }; log("Getting the sent SMS messages."); let cursor = manager.getMessages(filter, false); diff --git a/dom/mobilemessage/tests/marionette/test_filter_unread.js b/dom/mobilemessage/tests/marionette/test_filter_unread.js index 6d1b041cc626..1a4afad1a323 100644 --- a/dom/mobilemessage/tests/marionette/test_filter_unread.js +++ b/dom/mobilemessage/tests/marionette/test_filter_unread.js @@ -20,9 +20,8 @@ function verifyInitialState() { function deleteAllMsgs(nextFunction) { let msgList = new Array(); - let filter = new MozSmsFilter; - let cursor = manager.getMessages(filter, false); + let cursor = manager.getMessages(); ok(cursor instanceof DOMCursor, "cursor is instanceof " + cursor.constructor); @@ -156,11 +155,10 @@ function markMsgRead() { } function getMsgs() { - var filter = new MozSmsFilter(); let foundSmsList = new Array(); // Set filter for read messages - filter.read = false; + let filter = { read: false }; log("Getting the unread SMS messages."); let cursor = manager.getMessages(filter, false); diff --git a/dom/mobilemessage/tests/marionette/test_getthreads.js b/dom/mobilemessage/tests/marionette/test_getthreads.js index 1c80903c65c9..75b363a57a50 100644 --- a/dom/mobilemessage/tests/marionette/test_getthreads.js +++ b/dom/mobilemessage/tests/marionette/test_getthreads.js @@ -56,9 +56,6 @@ let tasks = { }; function getAllMessages(callback, filter, reverse) { - if (!filter) { - filter = new MozSmsFilter; - } let messages = []; let request = manager.getMessages(filter, reverse || false); request.onsuccess = function(event) { @@ -154,8 +151,7 @@ function checkThread(bodies, lastBody, unreadCount, participants, } // Check whether the thread does contain all the messages it supposed to have. - let filter = new MozSmsFilter; - filter.threadId = thread.id; + let filter = { threadId: thread.id }; getAllMessages(function(messages) { is(messages.length, bodies.length, "messages.length and bodies.length"); diff --git a/dom/mobilemessage/tests/marionette/test_invalid_address.js b/dom/mobilemessage/tests/marionette/test_invalid_address.js index a1e1b4b8ecfd..5464c34d77af 100644 --- a/dom/mobilemessage/tests/marionette/test_invalid_address.js +++ b/dom/mobilemessage/tests/marionette/test_invalid_address.js @@ -44,9 +44,6 @@ let tasks = { let manager; function getAllMessages(callback, filter, reverse) { - if (!filter) { - filter = new MozSmsFilter; - } let messages = []; let request = manager.getMessages(filter, reverse || false); request.onsuccess = function(event) { diff --git a/dom/mobilemessage/tests/marionette/test_message_classes.js b/dom/mobilemessage/tests/marionette/test_message_classes.js index a8a332f153bd..6c067ba82a5a 100644 --- a/dom/mobilemessage/tests/marionette/test_message_classes.js +++ b/dom/mobilemessage/tests/marionette/test_message_classes.js @@ -76,7 +76,7 @@ function test_message_class_0() { "Message's sentTimestamp should be equal to SENT_TIMESTAMP"); // Make sure the message is not stored. - let cursor = manager.getMessages(null, false); + let cursor = manager.getMessages(); cursor.onsuccess = function onsuccess() { if (cursor.result) { // Here we check whether there is any message of the same sender. diff --git a/dom/mobilemessage/tests/marionette/test_mmdb_full_storage.js b/dom/mobilemessage/tests/marionette/test_mmdb_full_storage.js index a7fee738b600..ca3e4768c2ba 100644 --- a/dom/mobilemessage/tests/marionette/test_mmdb_full_storage.js +++ b/dom/mobilemessage/tests/marionette/test_mmdb_full_storage.js @@ -165,7 +165,7 @@ function testCreateMessageCursor(aMmdb) { log("testCreateMessageCursor()"); setStorageFull(true); - return createMessageCursor(aMmdb, {}, false) + return createMessageCursor(aMmdb) .then(() => setStorageFull(false)); } diff --git a/dom/mobilemessage/tests/marionette/test_mmdb_upgradeSchema_22.js b/dom/mobilemessage/tests/marionette/test_mmdb_upgradeSchema_22.js index a2177842084e..b315a4467cea 100644 --- a/dom/mobilemessage/tests/marionette/test_mmdb_upgradeSchema_22.js +++ b/dom/mobilemessage/tests/marionette/test_mmdb_upgradeSchema_22.js @@ -630,7 +630,7 @@ function doVerifyDatabase(aMmdb, aExpected) { is(aExpected.length, 0, "remaining unmatched threads"); // 5) retrieve all messages. - return createMessageCursor(aMmdb, {}) + return createMessageCursor(aMmdb) .then(function(aValues) { let [errorCode, domMessages] = aValues; is(errorCode, 0, "errorCode"); diff --git a/dom/mobilemessage/tests/marionette/test_mmsmessage_attachments.js b/dom/mobilemessage/tests/marionette/test_mmsmessage_attachments.js index 77b2ee9e2db7..8db959c98e86 100644 --- a/dom/mobilemessage/tests/marionette/test_mmsmessage_attachments.js +++ b/dom/mobilemessage/tests/marionette/test_mmsmessage_attachments.js @@ -44,9 +44,6 @@ let tasks = { let manager; function getAllMessages(callback, filter, reverse) { - if (!filter) { - filter = new MozSmsFilter; - } let messages = []; let request = manager.getMessages(filter, reverse || false); request.onsuccess = function(event) { diff --git a/dom/mobilemessage/tests/marionette/test_phone_number_normalization.js b/dom/mobilemessage/tests/marionette/test_phone_number_normalization.js index 3bf940f3f36d..b2785a1e7c98 100644 --- a/dom/mobilemessage/tests/marionette/test_phone_number_normalization.js +++ b/dom/mobilemessage/tests/marionette/test_phone_number_normalization.js @@ -52,9 +52,6 @@ let tasks = { }; function getAllMessages(callback, filter, reverse) { - if (!filter) { - filter = new MozSmsFilter; - } let messages = []; let request = manager.getMessages(filter, reverse || false); request.onsuccess = function(event) { diff --git a/dom/mobilemessage/tests/marionette/test_update_thread_record_in_delete.js b/dom/mobilemessage/tests/marionette/test_update_thread_record_in_delete.js index e9610a636aeb..a11710e91bc6 100644 --- a/dom/mobilemessage/tests/marionette/test_update_thread_record_in_delete.js +++ b/dom/mobilemessage/tests/marionette/test_update_thread_record_in_delete.js @@ -60,9 +60,6 @@ let tasks = { }; function getAllMessages(callback, filter, reverse) { - if (!filter) { - filter = new MozSmsFilter; - } let messages = []; let cursor = manager.getMessages(filter, reverse || false); cursor.onsuccess = function(event) { diff --git a/dom/mobilemessage/tests/mochitest/mochitest.ini b/dom/mobilemessage/tests/mochitest/mochitest.ini index c0edbf36c774..21a8fb33b321 100644 --- a/dom/mobilemessage/tests/mochitest/mochitest.ini +++ b/dom/mobilemessage/tests/mochitest/mochitest.ini @@ -3,4 +3,3 @@ skip-if = e10s [test_sms_basics.html] skip-if = toolkit == 'android' #Bug 909036 -[test_smsfilter.html] diff --git a/dom/mobilemessage/tests/mochitest/test_sms_basics.html b/dom/mobilemessage/tests/mochitest/test_sms_basics.html index e6a3a5c1b369..37a7ac0b42f7 100644 --- a/dom/mobilemessage/tests/mochitest/test_sms_basics.html +++ b/dom/mobilemessage/tests/mochitest/test_sms_basics.html @@ -50,7 +50,6 @@ function checkInterface(aInterface) { function test() { checkInterface("SmsMessage"); checkInterface("SmsEvent"); - checkInterface("SmsFilter"); // If sms is disabled and permission is removed, sms is disabled. SpecialPowers.pushPrefEnv({"set": [["dom.sms.enabled", false]]}, function() { diff --git a/dom/mobilemessage/tests/mochitest/test_smsfilter.html b/dom/mobilemessage/tests/mochitest/test_smsfilter.html deleted file mode 100644 index 922dc462f2d4..000000000000 --- a/dom/mobilemessage/tests/mochitest/test_smsfilter.html +++ /dev/null @@ -1,90 +0,0 @@ - - - - Test SmsFilter - - - - -

- -
-
-
- - - diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html index 61f83350e8df..f09bef561d55 100644 --- a/dom/tests/mochitest/general/test_interfaces.html +++ b/dom/tests/mochitest/general/test_interfaces.html @@ -702,8 +702,6 @@ var interfaceNamesInGlobalScope = "MozSettingsEvent", // IMPORTANT: Do not change this list without review from a DOM peer! "MozSmsEvent", -// IMPORTANT: Do not change this list without review from a DOM peer! - "MozSmsFilter", // IMPORTANT: Do not change this list without review from a DOM peer! "MozSmsMessage", // IMPORTANT: Do not change this list without review from a DOM peer! From 86d2dc257feb51eb26c7bf27d61e6b0cf5feda7c Mon Sep 17 00:00:00 2001 From: Vicamo Yang Date: Thu, 28 Aug 2014 11:00:03 +0800 Subject: [PATCH 55/60] Bug 878533 - 3/3: fix Fennec build bustage. r=blassey --- mobile/android/base/GeckoAppShell.java | 4 ++-- mobile/android/base/GeckoSmsManager.java | 20 ++++++++++---------- mobile/android/base/SmsManager.java | 2 +- widget/android/AndroidBridge.cpp | 11 ++++++++--- widget/android/GeneratedJNIWrappers.cpp | 15 +++++++++------ widget/android/GeneratedJNIWrappers.h | 2 +- 6 files changed, 31 insertions(+), 23 deletions(-) diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index 181ecc698472..b06547f8c813 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -2375,12 +2375,12 @@ public class GeckoAppShell } @WrapElementForJNI(stubName = "CreateMessageListWrapper") - public static void createMessageList(long aStartDate, long aEndDate, String[] aNumbers, int aNumbersCount, int aDeliveryState, boolean aReverse, int aRequestId) { + public static void createMessageList(long aStartDate, long aEndDate, String[] aNumbers, int aNumbersCount, String aDelivery, boolean aHasRead, boolean aRead, long aThreadId, boolean aReverse, int aRequestId) { if (SmsManager.getInstance() == null) { return; } - SmsManager.getInstance().createMessageList(aStartDate, aEndDate, aNumbers, aNumbersCount, aDeliveryState, aReverse, aRequestId); + SmsManager.getInstance().createMessageList(aStartDate, aEndDate, aNumbers, aNumbersCount, aDelivery, aHasRead, aRead, aThreadId, aReverse, aRequestId); } @WrapElementForJNI(stubName = "GetNextMessageInListWrapper") diff --git a/mobile/android/base/GeckoSmsManager.java b/mobile/android/base/GeckoSmsManager.java index a68286cbe746..fe9370298d23 100644 --- a/mobile/android/base/GeckoSmsManager.java +++ b/mobile/android/base/GeckoSmsManager.java @@ -737,22 +737,22 @@ public class GeckoSmsManager } @Override - public void createMessageList(long aStartDate, long aEndDate, String[] aNumbers, int aNumbersCount, int aDeliveryState, boolean aReverse, int aRequestId) { + public void createMessageList(long aStartDate, long aEndDate, String[] aNumbers, int aNumbersCount, String aDelivery, boolean aHasRead, boolean aRead, long aThreadId, boolean aReverse, int aRequestId) { class CreateMessageListRunnable implements Runnable { private long mStartDate; private long mEndDate; private String[] mNumbers; private int mNumbersCount; - private int mDeliveryState; + private String mDelivery; private boolean mReverse; private int mRequestId; - CreateMessageListRunnable(long aStartDate, long aEndDate, String[] aNumbers, int aNumbersCount, int aDeliveryState, boolean aReverse, int aRequestId) { + CreateMessageListRunnable(long aStartDate, long aEndDate, String[] aNumbers, int aNumbersCount, String aDelivery, boolean aHasRead, boolean aRead, long aThreadId, boolean aReverse, int aRequestId) { mStartDate = aStartDate; mEndDate = aEndDate; mNumbers = aNumbers; mNumbersCount = aNumbersCount; - mDeliveryState = aDeliveryState; + mDelivery = aDelivery; mReverse = aReverse; mRequestId = aRequestId; } @@ -766,11 +766,11 @@ public class GeckoSmsManager // TODO: should use the |selectionArgs| argument in |ContentResolver.query()|. ArrayList restrictions = new ArrayList(); - if (mStartDate != 0) { + if (mStartDate >= 0) { restrictions.add("date >= " + mStartDate); } - if (mEndDate != 0) { + if (mEndDate >= 0) { restrictions.add("date <= " + mEndDate); } @@ -785,11 +785,11 @@ public class GeckoSmsManager restrictions.add(numberRestriction); } - if (mDeliveryState == kDeliveryStateUnknown) { + if (mDelivery == null) { restrictions.add("type IN ('" + kSmsTypeSentbox + "', '" + kSmsTypeInbox + "')"); - } else if (mDeliveryState == kDeliveryStateSent) { + } else if (mDelivery == "sent") { restrictions.add("type = " + kSmsTypeSentbox); - } else if (mDeliveryState == kDeliveryStateReceived) { + } else if (mDelivery == "received") { restrictions.add("type = " + kSmsTypeInbox); } else { throw new UnexpectedDeliveryStateException(); @@ -853,7 +853,7 @@ public class GeckoSmsManager } } - if (!SmsIOThread.getInstance().execute(new CreateMessageListRunnable(aStartDate, aEndDate, aNumbers, aNumbersCount, aDeliveryState, aReverse, aRequestId))) { + if (!SmsIOThread.getInstance().execute(new CreateMessageListRunnable(aStartDate, aEndDate, aNumbers, aNumbersCount, aDelivery, aHasRead, aRead, aThreadId, aReverse, aRequestId))) { Log.e("GeckoSmsManager", "Failed to add CreateMessageListRunnable to the SmsIOThread"); notifyReadingMessageListFailed(kUnknownError, aRequestId); } diff --git a/mobile/android/base/SmsManager.java b/mobile/android/base/SmsManager.java index 28930bda8b39..0bdf07244da0 100644 --- a/mobile/android/base/SmsManager.java +++ b/mobile/android/base/SmsManager.java @@ -28,7 +28,7 @@ interface ISmsManager public void send(String aNumber, String aMessage, int aRequestId); public void getMessage(int aMessageId, int aRequestId); public void deleteMessage(int aMessageId, int aRequestId); - public void createMessageList(long aStartDate, long aEndDate, String[] aNumbers, int aNumbersCount, int aDeliveryState, boolean aReverse, int aRequestId); + public void createMessageList(long aStartDate, long aEndDate, String[] aNumbers, int aNumbersCount, String aDelivery, boolean aHasRead, boolean aRead, long aThreadId, boolean aReverse, int aRequestId); public void getNextMessageInList(int aListId, int aRequestId); public void clearMessageList(int aListId); } diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index aabc0f988bfc..f2a2647e72df 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -1161,9 +1161,14 @@ AndroidBridge::CreateMessageList(const dom::mobilemessage::SmsFilterData& aFilte env->DeleteLocalRef(elem); } - mozilla::widget::android::GeckoAppShell::CreateMessageListWrapper(aFilter.startDate(), - aFilter.endDate(), numbers, aFilter.numbers().Length(), - aFilter.delivery(), aReverse, requestId); + int64_t startDate = aFilter.hasStartDate() ? aFilter.startDate() : -1; + int64_t endDate = aFilter.hasEndDate() ? aFilter.endDate() : -1; + GeckoAppShell::CreateMessageListWrapper(startDate, endDate, + numbers, aFilter.numbers().Length(), + aFilter.delivery(), + aFilter.hasRead(), aFilter.read(), + aFilter.threadId(), + aReverse, requestId); } void diff --git a/widget/android/GeneratedJNIWrappers.cpp b/widget/android/GeneratedJNIWrappers.cpp index 72919ab68a7e..68d444fc735f 100644 --- a/widget/android/GeneratedJNIWrappers.cpp +++ b/widget/android/GeneratedJNIWrappers.cpp @@ -111,7 +111,7 @@ void GeckoAppShell::InitStubs(JNIEnv *jEnv) { jCloseNotification = getStaticMethod("closeNotification", "(Ljava/lang/String;)V"); jConnectionGetMimeType = getStaticMethod("connectionGetMimeType", "(Ljava/net/URLConnection;)Ljava/lang/String;"); jCreateInputStream = getStaticMethod("createInputStream", "(Ljava/net/URLConnection;)Ljava/io/InputStream;"); - jCreateMessageListWrapper = getStaticMethod("createMessageList", "(JJ[Ljava/lang/String;IIZI)V"); + jCreateMessageListWrapper = getStaticMethod("createMessageList", "(JJ[Ljava/lang/String;ILjava/lang/String;ZZJZI)V"); jCreateShortcut = getStaticMethod("createShortcut", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); jDeleteMessageWrapper = getStaticMethod("deleteMessage", "(II)V"); jDisableBatteryNotifications = getStaticMethod("disableBatteryNotifications", "()V"); @@ -335,21 +335,24 @@ jobject GeckoAppShell::CreateInputStream(jobject a0) { return ret; } -void GeckoAppShell::CreateMessageListWrapper(int64_t a0, int64_t a1, jobjectArray a2, int32_t a3, int32_t a4, bool a5, int32_t a6) { +void GeckoAppShell::CreateMessageListWrapper(int64_t a0, int64_t a1, jobjectArray a2, int32_t a3, const nsAString& a4, bool a5, bool a6, int64_t a7, bool a8, int32_t a9) { JNIEnv *env = AndroidBridge::GetJNIEnv(); - if (env->PushLocalFrame(1) != 0) { + if (env->PushLocalFrame(2) != 0) { AndroidBridge::HandleUncaughtException(env); MOZ_CRASH("Exception should have caused crash."); } - jvalue args[7]; + jvalue args[10]; args[0].j = a0; args[1].j = a1; args[2].l = a2; args[3].i = a3; - args[4].i = a4; + args[4].l = AndroidBridge::NewJavaString(env, a4); args[5].z = a5; - args[6].i = a6; + args[6].z = a6; + args[7].j = a7; + args[8].z = a8; + args[9].i = a9; env->CallStaticVoidMethodA(mGeckoAppShellClass, jCreateMessageListWrapper, args); AndroidBridge::HandleUncaughtException(env); diff --git a/widget/android/GeneratedJNIWrappers.h b/widget/android/GeneratedJNIWrappers.h index 25ece85dbc1b..643b1470922c 100644 --- a/widget/android/GeneratedJNIWrappers.h +++ b/widget/android/GeneratedJNIWrappers.h @@ -29,7 +29,7 @@ public: static void CloseNotification(const nsAString& a0); static jstring ConnectionGetMimeType(jobject a0); static jobject CreateInputStream(jobject a0); - static void CreateMessageListWrapper(int64_t a0, int64_t a1, jobjectArray a2, int32_t a3, int32_t a4, bool a5, int32_t a6); + static void CreateMessageListWrapper(int64_t a0, int64_t a1, jobjectArray a2, int32_t a3, const nsAString& a4, bool a5, bool a6, int64_t a7, bool a8, int32_t a9); static void CreateShortcut(const nsAString& a0, const nsAString& a1, const nsAString& a2); static void DeleteMessageWrapper(int32_t a0, int32_t a1); static void DisableBatteryNotifications(); From 1c7697d9ad336dcf8f403795d10c4508c26ee203 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 20:20:32 -0700 Subject: [PATCH 56/60] Bumping manifests a=b2g-bump --- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 752f61edae96..f53dceda15a2 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -130,7 +130,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index d3d8dc949a99..88cb002d3578 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -128,7 +128,7 @@ - + From fa4e2745dae81ae0db2ff3620b25f33c9b134d8a Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 20:25:29 -0700 Subject: [PATCH 57/60] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/2c168dab2546 Author: Rudy Lu Desc: Merge pull request #23359 from RudyLu/keyboard/Bug1019472 Bug 1019472 - [Keyboard] [ZhuYin] ZhuYin Keyboard should follow the reco... r=rudylu. ======== https://hg.mozilla.org/integration/gaia-central/rev/773aac4df6bc Author: dxue Desc: Bug 1019472 - [Keyboard] [ZhuYin] ZhuYin Keyboard should follow the recommendation --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 8df6e0bcc563..ef89fc6a032e 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "198ce093d43e19535d5b682334218e80d6889be7", + "revision": "2c168dab254623bae4b6bfcca7af5c3d3ae53de0", "repo_path": "/integration/gaia-central" } From 7a3c573149cec871ff91ecf5d485b935469d110f Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 20:36:31 -0700 Subject: [PATCH 58/60] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 6f66028eeaf3..6a4e5143eeb8 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 8fb3da223218..95306a0b9ec0 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index f53dceda15a2..713b59916fac 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 88cb002d3578..4b7af4f3b3b5 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 8fb3da223218..95306a0b9ec0 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index ce38a0c9fb5a..5a99fbd08e90 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 3271758f1f88..5f87d84a7ef1 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index d8cfcd4454e0..22e2500d9b8c 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 8110a76428a4..2e08b1505537 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 6c66f642349d..cd55722dff3c 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 0acb6bcf1caadedc7aa29d81b2623f28c13e2932 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 20:40:28 -0700 Subject: [PATCH 59/60] Bumping gaia.json for 3 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/6fa1c6e992e9 Author: Rudy Lu Desc: Merge pull request #23343 from RudyLu/keyboard/Bug1053647 Bug 1053647 - [Keyboard] Auto correct improvement. r=rudylu. ======== https://hg.mozilla.org/integration/gaia-central/rev/141af01d3491 Author: Rudy Lu Desc: Bug 1053647 - fix the failing python integration tests. ======== https://hg.mozilla.org/integration/gaia-central/rev/4c50b25742dc Author: David Flanagan Desc: Bug 1053647: delete space when reverting an autocorrection and don't insert space when user selects a word suggestion disable autocorrection when reverting a selected word suggestion --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index ef89fc6a032e..ba0c7c7bc856 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "2c168dab254623bae4b6bfcca7af5c3d3ae53de0", + "revision": "6fa1c6e992e9d7169e8e6cd8c714d1983087a87c", "repo_path": "/integration/gaia-central" } From e6ff9b4b73b0ecf26d622c4424a42975980418ce Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 27 Aug 2014 20:50:39 -0700 Subject: [PATCH 60/60] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 6a4e5143eeb8..8493d422e67a 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 95306a0b9ec0..51fcf13d8bbc 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 713b59916fac..d09ba4debaff 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 4b7af4f3b3b5..e5995c023e98 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 95306a0b9ec0..51fcf13d8bbc 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 5a99fbd08e90..e94af8846163 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 5f87d84a7ef1..29c3110eed59 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 22e2500d9b8c..1ee4bdd96e07 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 2e08b1505537..58f30bd4d2de 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index cd55722dff3c..4d468c5f5548 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - +