diff --git a/b2g/config/aries/sources.xml b/b2g/config/aries/sources.xml
index de02c5b4809..f00171dcb0f 100644
--- a/b2g/config/aries/sources.xml
+++ b/b2g/config/aries/sources.xml
@@ -15,7 +15,7 @@
-
+
@@ -23,7 +23,7 @@
-
+
diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml
index 135f313e197..3aa0fbef8ec 100644
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -15,7 +15,7 @@
-
+
@@ -23,7 +23,7 @@
-
+
diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml
index cba477d2bb5..bd9dcb63a1c 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 5c25f6215b7..c2c7089b4d2 100644
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -17,10 +17,10 @@
-
+
-
+
diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml
index c12c5ffd8b6..effb01c23fd 100644
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -15,7 +15,7 @@
-
+
@@ -23,7 +23,7 @@
-
+
diff --git a/b2g/config/emulator-l/sources.xml b/b2g/config/emulator-l/sources.xml
index 64218ced8d1..582eb668512 100644
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -15,7 +15,7 @@
-
+
@@ -23,7 +23,7 @@
-
+
diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml
index cba477d2bb5..bd9dcb63a1c 100644
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -19,7 +19,7 @@
-
+
diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml
index 0212b3ae013..32c9572419a 100644
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -15,7 +15,7 @@
-
+
@@ -23,7 +23,7 @@
-
+
diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json
index 47e376bfc2c..0f8885c9373 100644
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
{
"git": {
- "git_revision": "9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256",
+ "git_revision": "477b5672811ed970a7476fe6f67dba546a302dce",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
- "revision": "d5e509fd9697316bcbc267413a30478dcd4dbca9",
+ "revision": "5bab67b888d1491d1718cf1a7349bcef3114cbab",
"repo_path": "integration/gaia-central"
}
diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml
index c9d5fa79d7a..20482a65ce5 100644
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -17,10 +17,10 @@
-
+
-
+
diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml
index df7a909f06b..2f5c9c1cb9f 100644
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -15,7 +15,7 @@
-
+
@@ -23,7 +23,7 @@
-
+
diff --git a/browser/devtools/performance/modules/global.js b/browser/devtools/performance/modules/global.js
index 70f6b2926e6..2038a5fefe5 100644
--- a/browser/devtools/performance/modules/global.js
+++ b/browser/devtools/performance/modules/global.js
@@ -65,6 +65,10 @@ const CATEGORIES = [{
color: "#d99b28",
abbrev: "events",
label: L10N.getStr("category.events")
+}, {
+ color: "#8fa1b2",
+ abbrev: "tools",
+ label: L10N.getStr("category.tools")
}];
/**
@@ -81,6 +85,9 @@ const CATEGORY_MAPPINGS = {
"1024": CATEGORIES[5], // js::ProfileEntry::Category::GRAPHICS
"2048": CATEGORIES[6], // js::ProfileEntry::Category::STORAGE
"4096": CATEGORIES[7], // js::ProfileEntry::Category::EVENTS
+
+ // non-bitmasks for specially-assigned categories
+ "9000": CATEGORIES[8],
};
/**
@@ -106,17 +113,17 @@ const [CATEGORY_MASK, CATEGORY_MASK_LIST] = (function () {
return [
function (name, index) {
if (!(name in bitmasksForCategory)) {
- throw new Error(`Category abbreviation '${name}' does not exist.`);
+ throw new Error(`Category abbreviation "${name}" does not exist.`);
}
if (arguments.length == 1) {
if (bitmasksForCategory[name].length != 1) {
- throw new Error(`Expected exactly one category number for '${name}'.`);
+ throw new Error(`Expected exactly one category number for "${name}".`);
} else {
return bitmasksForCategory[name][0];
}
} else {
if (index > bitmasksForCategory[name].length) {
- throw new Error(`Index '${index}' too high for category '${name}'.`);
+ throw new Error(`Index "${index}" too high for category "${name}".`);
} else {
return bitmasksForCategory[name][index - 1];
}
@@ -125,7 +132,7 @@ const [CATEGORY_MASK, CATEGORY_MASK_LIST] = (function () {
function (name) {
if (!(name in bitmasksForCategory)) {
- throw new Error(`Category abbreviation '${name}' does not exist.`);
+ throw new Error(`Category abbreviation "${name}" does not exist.`);
}
return bitmasksForCategory[name];
}
@@ -135,11 +142,15 @@ const [CATEGORY_MASK, CATEGORY_MASK_LIST] = (function () {
// Human-readable "other" category bitmask. Older Geckos don't have all the
// necessary instrumentation in the sampling profiler backend for creating
// a categories graph, in which case we default to the "other" category.
-const CATEGORY_OTHER = CATEGORY_MASK('other');
+const CATEGORY_OTHER = CATEGORY_MASK("other");
// Human-readable JIT category bitmask. Certain pseudo-frames in a sample,
-// like "EnterJIT", don't have any associated `cateogry` information.
-const CATEGORY_JIT = CATEGORY_MASK('js');
+// like "EnterJIT", don't have any associated `category` information.
+const CATEGORY_JIT = CATEGORY_MASK("js");
+
+// Human-readable "devtools" category bitmask. Not emitted from frames themselves,
+// but used manually in the client.
+const CATEGORY_DEVTOOLS = CATEGORY_MASK("tools");
// Exported symbols.
exports.L10N = L10N;
@@ -150,3 +161,4 @@ exports.CATEGORY_MASK = CATEGORY_MASK;
exports.CATEGORY_MASK_LIST = CATEGORY_MASK_LIST;
exports.CATEGORY_OTHER = CATEGORY_OTHER;
exports.CATEGORY_JIT = CATEGORY_JIT;
+exports.CATEGORY_DEVTOOLS = CATEGORY_DEVTOOLS;
diff --git a/browser/devtools/performance/modules/logic/frame-utils.js b/browser/devtools/performance/modules/logic/frame-utils.js
index faa2b26a098..1ddaa8669c8 100644
--- a/browser/devtools/performance/modules/logic/frame-utils.js
+++ b/browser/devtools/performance/modules/logic/frame-utils.js
@@ -6,8 +6,8 @@
const { Cc, Ci, Cu, Cr } = require("chrome");
loader.lazyRequireGetter(this, "Services");
-loader.lazyRequireGetter(this, "CATEGORY_OTHER",
- "devtools/performance/global", true);
+loader.lazyRequireGetter(this, "global",
+ "devtools/performance/global");
// Character codes used in various parsing helper functions.
const CHAR_CODE_A = "a".charCodeAt(0);
@@ -162,33 +162,55 @@ function parseLocation(location, fallbackLine, fallbackColumn) {
};
/**
- * Checks if the specified function represents a chrome or content frame.
+ * Sets the properties of `isContent` and `category` on a frame.
*
- * @param string location
- * The location of the frame.
- * @param number category [optional]
- * If a chrome frame, the category.
- * @return boolean
- * True if a content frame, false if a chrome frame.
+ * @param {InflatedFrame} frame
*/
-function isContent({ location, category }) {
+function computeIsContentAndCategory(frame) {
// Only C++ stack frames have associated category information.
- if (category) {
- return false;
+ if (frame.category) {
+ return;
}
+ let location = frame.location;
+
// Locations in frames with function names look like:
// "functionName (foo://bar)".
// Look for the starting left parenthesis, then try to match a
// scheme name.
for (let i = 0; i < location.length; i++) {
if (location.charCodeAt(i) === CHAR_CODE_LPAREN) {
- return isContentScheme(location, i + 1);
+ if (isContentScheme(location, i + 1)) {
+ frame.isContent = true;
+ return;
+ }
+
+ for (let j = i + 1; j < location.length; j++) {
+ if (location.charCodeAt(j) === CHAR_CODE_R &&
+ isChromeScheme(location, j) &&
+ (location.indexOf("resource://gre/modules/devtools") !== -1 ||
+ location.indexOf("resource:///modules/devtools") !== -1)) {
+ frame.category = global.CATEGORY_DEVTOOLS;
+ return;
+ }
+ }
+
+ break;
}
}
// If there was no left parenthesis, try matching from the start.
- return isContentScheme(location, 0);
+ if (isContentScheme(location, 0)) {
+ frame.isContent = true;
+ return;
+ }
+
+ if (location === "EnterJIT") {
+ frame.category = global.CATEGORY_JIT;
+ return;
+ }
+
+ frame.category = global.CATEGORY_OTHER;
}
/**
@@ -247,10 +269,17 @@ function InflatedFrame(index, frameTable, stringTable, allocationsTable) {
this.optimizations = frame[OPTIMIZATIONS_SLOT];
this.line = frame[LINE_SLOT];
this.column = undefined;
- this.category = category;
- this.metaCategory = category || CATEGORY_OTHER;
this.allocations = allocationsTable ? allocationsTable[index] : 0;
- this.isContent = isContent(this);
+ this.category = category;
+ this.isContent = false;
+
+ // Attempt to compute if this frame is a content frame, and if not,
+ // its category.
+ //
+ // Since only C++ stack frames have associated category information,
+ // attempt to generate a useful category, fallback to the one provided
+ // by the profiling data, or fallback to an unknown category.
+ computeIsContentAndCategory(this);
};
/**
@@ -284,7 +313,7 @@ InflatedFrame.prototype.getFrameKey = function getFrameKey(options) {
// non-leaf platform frames don't give any meaningful context, and so we
// can safely filter them out.
options.isMetaCategoryOut = true;
- return this.metaCategory;
+ return this.category;
}
// Return an empty string denoting that this frame should be skipped.
@@ -418,8 +447,8 @@ function isNumeric(c) {
return c >= CHAR_CODE_0 && c <= CHAR_CODE_9;
}
+exports.computeIsContentAndCategory = computeIsContentAndCategory;
exports.parseLocation = parseLocation;
-exports.isContent = isContent;
exports.getInflatedFrameCache = getInflatedFrameCache;
exports.getOrAddInflatedFrame = getOrAddInflatedFrame;
exports.InflatedFrame = InflatedFrame;
diff --git a/browser/devtools/performance/modules/logic/tree-model.js b/browser/devtools/performance/modules/logic/tree-model.js
index 7275ee97490..ebc0ce2f6d3 100644
--- a/browser/devtools/performance/modules/logic/tree-model.js
+++ b/browser/devtools/performance/modules/logic/tree-model.js
@@ -9,12 +9,6 @@ loader.lazyRequireGetter(this, "L10N",
"devtools/performance/global", true);
loader.lazyRequireGetter(this, "CATEGORY_MAPPINGS",
"devtools/performance/global", true);
-loader.lazyRequireGetter(this, "CATEGORIES",
- "devtools/performance/global", true);
-loader.lazyRequireGetter(this, "CATEGORY_JIT",
- "devtools/performance/global", true);
-loader.lazyRequireGetter(this, "CATEGORY_OTHER",
- "devtools/performance/global", true);
loader.lazyRequireGetter(this, "JITOptimizations",
"devtools/performance/jit", true);
loader.lazyRequireGetter(this, "FrameUtils",
@@ -377,15 +371,15 @@ function FrameNode(frameKey, { location, line, category, allocations, isContent
this.key = frameKey;
this.location = location;
this.line = line;
- this.category = category;
this.allocations = allocations;
this.samples = 0;
this.duration = 0;
this.calls = [];
- this.isContent = isContent;
+ this.isContent = !!isContent;
this._optimizations = null;
this._stringTable = null;
- this.isMetaCategory = isMetaCategory;
+ this.isMetaCategory = !!isMetaCategory;
+ this.category = category;
}
FrameNode.prototype = {
@@ -462,19 +456,7 @@ FrameNode.prototype = {
* function name and source url.
*/
_computeInfo: function() {
- // "EnterJIT" pseudoframes are special, not actually on the stack.
- if (this.location == "EnterJIT") {
- this.category = CATEGORY_JIT;
- }
-
- if (this.isMetaCategory && !this.category) {
- this.category = CATEGORY_OTHER;
- }
-
- // Since only C++ stack frames have associated category information,
- // default to an "unknown" category otherwise.
let categoryData = CATEGORY_MAPPINGS[this.category] || {};
-
let parsedData = FrameUtils.parseLocation(this.location, this.line, this.column);
parsedData.nodeType = "Frame";
parsedData.categoryData = categoryData;
diff --git a/browser/devtools/performance/test/browser.ini b/browser/devtools/performance/test/browser.ini
index fd9399fb943..ac8cd1276b0 100644
--- a/browser/devtools/performance/test/browser.ini
+++ b/browser/devtools/performance/test/browser.ini
@@ -117,8 +117,6 @@ skip-if = e10s # GC events seem unreliable in multiprocess
[browser_perf-recording-selected-03.js]
[browser_perf-recording-selected-04.js]
[browser_perf-theme-toggle-01.js]
-[browser_profiler_categories.js]
-[browser_profiler_content-check.js]
[browser_profiler_tree-abstract-01.js]
[browser_profiler_tree-abstract-02.js]
[browser_profiler_tree-abstract-03.js]
diff --git a/browser/devtools/performance/test/browser_markers-timestamp.js b/browser/devtools/performance/test/browser_markers-timestamp.js
index db46a354144..86cc6d545b1 100644
--- a/browser/devtools/performance/test/browser_markers-timestamp.js
+++ b/browser/devtools/performance/test/browser_markers-timestamp.js
@@ -26,6 +26,7 @@ function* spawnTest () {
let maxMarkerTime = model._timelineStartTime + model.getDuration() + TIME_CLOSE_TO;
+ ok(markers.every(({stack}) => typeof stack === "number"), "All markers have stack references.");
ok(markers.every(({name}) => name === "TimeStamp"), "All markers found are TimeStamp markers");
ok(markers.length === 2, "found 2 TimeStamp markers");
ok(markers.every(({start}) => typeof start === "number" && start > 0 && start < maxMarkerTime),
diff --git a/browser/devtools/performance/test/unit/test_frame-utils-01.js b/browser/devtools/performance/test/unit/test_frame-utils-01.js
index ff07320113b..5ec1855e3a1 100644
--- a/browser/devtools/performance/test/unit/test_frame-utils-01.js
+++ b/browser/devtools/performance/test/unit/test_frame-utils-01.js
@@ -40,7 +40,12 @@ function run_test() {
}
add_task(function () {
- const { isContent, parseLocation } = devtools.require("devtools/performance/frame-utils");
+ const { computeIsContentAndCategory, parseLocation } = devtools.require("devtools/performance/frame-utils");
+ let isContent = (frame) => {
+ computeIsContentAndCategory(frame);
+ return frame.isContent;
+ };
+
for (let frame of CONTENT_LOCATIONS) {
ok(isContent.apply(null, frameify(frame)), `${frame[0]} should be considered a content frame.`);
diff --git a/browser/devtools/performance/test/browser_profiler_content-check.js b/browser/devtools/performance/test/unit/test_frame-utils-02.js
similarity index 53%
rename from browser/devtools/performance/test/browser_profiler_content-check.js
rename to browser/devtools/performance/test/unit/test_frame-utils-02.js
index 0f2b1b304f8..10b6f0db960 100644
--- a/browser/devtools/performance/test/browser_profiler_content-check.js
+++ b/browser/devtools/performance/test/unit/test_frame-utils-02.js
@@ -6,46 +6,53 @@
* works properly.
*/
-function test() {
+function run_test() {
+ run_next_test();
+}
+
+add_task(function () {
let FrameUtils = devtools.require("devtools/performance/frame-utils");
- ok(FrameUtils.isContent({ location: "http://foo" }),
+ let isContent = (frame) => {
+ FrameUtils.computeIsContentAndCategory(frame);
+ return frame.isContent;
+ };
+
+ ok(isContent({ location: "http://foo" }),
"Verifying content/chrome frames is working properly.");
- ok(FrameUtils.isContent({ location: "https://foo" }),
+ ok(isContent({ location: "https://foo" }),
"Verifying content/chrome frames is working properly.");
- ok(FrameUtils.isContent({ location: "file://foo" }),
+ ok(isContent({ location: "file://foo" }),
"Verifying content/chrome frames is working properly.");
- ok(!FrameUtils.isContent({ location: "chrome://foo" }),
+ ok(!isContent({ location: "chrome://foo" }),
"Verifying content/chrome frames is working properly.");
- ok(!FrameUtils.isContent({ location: "resource://foo" }),
+ ok(!isContent({ location: "resource://foo" }),
"Verifying content/chrome frames is working properly.");
- ok(!FrameUtils.isContent({ location: "chrome://foo -> http://bar" }),
+ ok(!isContent({ location: "chrome://foo -> http://bar" }),
"Verifying content/chrome frames is working properly.");
- ok(!FrameUtils.isContent({ location: "chrome://foo -> https://bar" }),
+ ok(!isContent({ location: "chrome://foo -> https://bar" }),
"Verifying content/chrome frames is working properly.");
- ok(!FrameUtils.isContent({ location: "chrome://foo -> file://bar" }),
+ ok(!isContent({ location: "chrome://foo -> file://bar" }),
"Verifying content/chrome frames is working properly.");
- ok(!FrameUtils.isContent({ location: "resource://foo -> http://bar" }),
+ ok(!isContent({ location: "resource://foo -> http://bar" }),
"Verifying content/chrome frames is working properly.");
- ok(!FrameUtils.isContent({ location: "resource://foo -> https://bar" }),
+ ok(!isContent({ location: "resource://foo -> https://bar" }),
"Verifying content/chrome frames is working properly.");
- ok(!FrameUtils.isContent({ location: "resource://foo -> file://bar" }),
+ ok(!isContent({ location: "resource://foo -> file://bar" }),
"Verifying content/chrome frames is working properly.");
- ok(!FrameUtils.isContent({ category: 1, location: "chrome://foo" }),
+ ok(!isContent({ category: 1, location: "chrome://foo" }),
"Verifying content/chrome frames is working properly.");
- ok(!FrameUtils.isContent({ category: 1, location: "resource://foo" }),
+ ok(!isContent({ category: 1, location: "resource://foo" }),
"Verifying content/chrome frames is working properly.");
- ok(!FrameUtils.isContent({ category: 1, location: "file://foo -> http://bar" }),
+ ok(!isContent({ category: 1, location: "file://foo -> http://bar" }),
"Verifying content/chrome frames is working properly.");
- ok(!FrameUtils.isContent({ category: 1, location: "file://foo -> https://bar" }),
+ ok(!isContent({ category: 1, location: "file://foo -> https://bar" }),
"Verifying content/chrome frames is working properly.");
- ok(!FrameUtils.isContent({ category: 1, location: "file://foo -> file://bar" }),
+ ok(!isContent({ category: 1, location: "file://foo -> file://bar" }),
"Verifying content/chrome frames is working properly.");
-
- finish();
-}
+});
diff --git a/browser/devtools/performance/test/browser_profiler_categories.js b/browser/devtools/performance/test/unit/test_profiler-categories.js
similarity index 56%
rename from browser/devtools/performance/test/browser_profiler_categories.js
rename to browser/devtools/performance/test/unit/test_profiler-categories.js
index e17e7cd3b9a..b5757983ba3 100644
--- a/browser/devtools/performance/test/browser_profiler_categories.js
+++ b/browser/devtools/performance/test/unit/test_profiler-categories.js
@@ -5,7 +5,11 @@
* Tests if the profiler categories are mapped correctly.
*/
-function test() {
+function run_test() {
+ run_next_test();
+}
+
+add_task(function () {
let global = devtools.require("devtools/performance/global");
let l10n = global.L10N;
let categories = global.CATEGORIES;
@@ -15,20 +19,18 @@ function test() {
ok(count,
"Should have a non-empty list of categories available.");
- ok(!categories.some(e => !e.color),
+ ok(categories.some(e => e.color),
"All categories have an associated color.");
- ok(!categories.some(e => !e.label),
+ ok(categories.every(e => e.label),
"All categories have an associated label.");
- ok(!categories.some(e => e.label != l10n.getStr("category." + e.abbrev)),
+ ok(categories.every(e => e.label === l10n.getStr("category." + e.abbrev)),
"All categories have a correctly localized label.");
- ok(!Object.keys(mappings).some(e => !Number.isInteger(Math.log2(e))),
- "All bitmask mappings keys are powers of 2.");
+ ok(Object.keys(mappings).every(e => (Number(e) >= 9000 && Number(e) <= 9999) || Number.isInteger(Math.log2(e))),
+ "All bitmask mappings keys are powers of 2, or between 9000-9999 for special categories.");
- ok(!Object.keys(mappings).some(e => categories.indexOf(mappings[e]) == -1),
+ ok(Object.keys(mappings).every(e => categories.indexOf(mappings[e]) !== -1),
"All bitmask mappings point to a category.");
-
- finish();
-}
+});
diff --git a/browser/devtools/performance/test/unit/test_tree-model-01.js b/browser/devtools/performance/test/unit/test_tree-model-01.js
index 4f95c1ad2a9..63a4842d886 100644
--- a/browser/devtools/performance/test/unit/test_tree-model-01.js
+++ b/browser/devtools/performance/test/unit/test_tree-model-01.js
@@ -26,7 +26,7 @@ add_task(function test() {
"The correct duration was calculated for the root node.");
equal(root.getInfo().functionName, "(root)",
"The correct function name was retrieved for the root node.");
- equal(root.getInfo().categoryData.toSource(), "({})",
+ equal(root.getInfo().categoryData.abbrev, "other",
"The correct empty category data was retrieved for the root node.");
equal(root.calls.length, 1,
diff --git a/browser/devtools/performance/test/unit/test_tree-model-08.js b/browser/devtools/performance/test/unit/test_tree-model-08.js
index 8b326ead8c6..f5d5c432721 100644
--- a/browser/devtools/performance/test/unit/test_tree-model-08.js
+++ b/browser/devtools/performance/test/unit/test_tree-model-08.js
@@ -13,238 +13,82 @@ add_task(function test() {
let FrameUtils = devtools.require("devtools/performance/frame-utils");
let { FrameNode } = devtools.require("devtools/performance/tree-model");
let { CATEGORY_OTHER } = devtools.require("devtools/performance/global");
+ let compute = frame => {
+ FrameUtils.computeIsContentAndCategory(frame);
+ return frame;
+ };
- let frame1 = new FrameNode("hello/<.world (http://foo/bar.js:123:987)", {
- location: "hello/<.world (http://foo/bar.js:123:987)",
- line: 456,
- isContent: FrameUtils.isContent({
- location: "hello/<.world (http://foo/bar.js:123:987)"
- })
- }, false);
-
- equal(frame1.getInfo().nodeType, "Frame",
- "The first frame node has the correct type.");
- equal(frame1.getInfo().functionName, "hello/<.world",
- "The first frame node has the correct function name.");
- equal(frame1.getInfo().fileName, "bar.js",
- "The first frame node has the correct file name.");
- equal(frame1.getInfo().hostName, "foo",
- "The first frame node has the correct host name.");
- equal(frame1.getInfo().url, "http://foo/bar.js",
- "The first frame node has the correct url.");
- equal(frame1.getInfo().line, 123,
- "The first frame node has the correct line.");
- equal(frame1.getInfo().column, 987,
- "The first frame node has the correct column.");
- equal(frame1.getInfo().categoryData.toSource(), "({})",
- "The first frame node has the correct category data.");
- equal(frame1.getInfo().isContent, true,
- "The first frame node has the correct content flag.");
-
- let frame2 = new FrameNode("hello/<.world (http://foo/bar.js#baz:123:987)", {
- location: "hello/<.world (http://foo/bar.js#baz:123:987)",
- line: 456,
- isContent: FrameUtils.isContent({
- location: "hello/<.world (http://foo/bar.js#baz:123:987)"
- })
- }, false);
-
- equal(frame2.getInfo().nodeType, "Frame",
- "The second frame node has the correct type.");
- equal(frame2.getInfo().functionName, "hello/<.world",
- "The second frame node has the correct function name.");
- equal(frame2.getInfo().fileName, "bar.js",
- "The second frame node has the correct file name.");
- equal(frame2.getInfo().hostName, "foo",
- "The second frame node has the correct host name.");
- equal(frame2.getInfo().url, "http://foo/bar.js#baz",
- "The second frame node has the correct url.");
- equal(frame2.getInfo().line, 123,
- "The second frame node has the correct line.");
- equal(frame2.getInfo().column, 987,
- "The second frame node has the correct column.");
- equal(frame2.getInfo().categoryData.toSource(), "({})",
- "The second frame node has the correct category data.");
- equal(frame2.getInfo().isContent, true,
- "The second frame node has the correct content flag.");
-
- let frame3 = new FrameNode("hello/<.world (http://foo/#bar:123:987)", {
- location: "hello/<.world (http://foo/#bar:123:987)",
- line: 456,
- isContent: FrameUtils.isContent({
- location: "hello/<.world (http://foo/#bar:123:987)"
- })
- }, false);
-
- equal(frame3.getInfo().nodeType, "Frame",
- "The third frame node has the correct type.");
- equal(frame3.getInfo().functionName, "hello/<.world",
- "The third frame node has the correct function name.");
- equal(frame3.getInfo().fileName, "/",
- "The third frame node has the correct file name.");
- equal(frame3.getInfo().hostName, "foo",
- "The third frame node has the correct host name.");
- equal(frame3.getInfo().url, "http://foo/#bar",
- "The third frame node has the correct url.");
- equal(frame3.getInfo().line, 123,
- "The third frame node has the correct line.");
- equal(frame3.getInfo().column, 987,
- "The third frame node has the correct column.");
- equal(frame3.getInfo().categoryData.toSource(), "({})",
- "The third frame node has the correct category data.");
- equal(frame3.getInfo().isContent, true,
- "The third frame node has the correct content flag.");
-
- let frame4 = new FrameNode("hello/<.world (http://foo/:123:987)", {
- location: "hello/<.world (http://foo/:123:987)",
- line: 456,
- isContent: FrameUtils.isContent({
- location: "hello/<.world (http://foo/:123:987)"
- })
- }, false);
-
- equal(frame4.getInfo().nodeType, "Frame",
- "The fourth frame node has the correct type.");
- equal(frame4.getInfo().functionName, "hello/<.world",
- "The fourth frame node has the correct function name.");
- equal(frame4.getInfo().fileName, "/",
- "The fourth frame node has the correct file name.");
- equal(frame4.getInfo().hostName, "foo",
- "The fourth frame node has the correct host name.");
- equal(frame4.getInfo().url, "http://foo/",
- "The fourth frame node has the correct url.");
- equal(frame4.getInfo().line, 123,
- "The fourth frame node has the correct line.");
- equal(frame4.getInfo().column, 987,
- "The fourth frame node has the correct column.");
- equal(frame4.getInfo().categoryData.toSource(), "({})",
- "The fourth frame node has the correct category data.");
- equal(frame4.getInfo().isContent, true,
- "The fourth frame node has the correct content flag.");
-
- let frame5 = new FrameNode("hello/<.world (resource://foo.js -> http://bar/baz.js:123:987)", {
- location: "hello/<.world (resource://foo.js -> http://bar/baz.js:123:987)",
- line: 456,
- isContent: FrameUtils.isContent({
- location: "hello/<.world (resource://foo.js -> http://bar/baz.js:123:987)"
- })
- }, false);
-
- equal(frame5.getInfo().nodeType, "Frame",
- "The fifth frame node has the correct type.");
- equal(frame5.getInfo().functionName, "hello/<.world",
- "The fifth frame node has the correct function name.");
- equal(frame5.getInfo().fileName, "baz.js",
- "The fifth frame node has the correct file name.");
- equal(frame5.getInfo().hostName, "bar",
- "The fifth frame node has the correct host name.");
- equal(frame5.getInfo().url, "http://bar/baz.js",
- "The fifth frame node has the correct url.");
- equal(frame5.getInfo().line, 123,
- "The fifth frame node has the correct line.");
- equal(frame5.getInfo().column, 987,
- "The fifth frame node has the correct column.");
- equal(frame5.getInfo().categoryData.toSource(), "({})",
- "The fifth frame node has the correct category data.");
- equal(frame5.getInfo().isContent, false,
- "The fifth frame node has the correct content flag.");
-
- let frame6 = new FrameNode("Foo::Bar::Baz", {
- location: "Foo::Bar::Baz",
- line: 456,
- category: CATEGORY_OTHER,
- isContent: FrameUtils.isContent({
+ let frames = [
+ new FrameNode("hello/<.world (http://foo/bar.js:123:987)", compute({
+ location: "hello/<.world (http://foo/bar.js:123:987)",
+ line: 456,
+ }), false),
+ new FrameNode("hello/<.world (http://foo/bar.js#baz:123:987)", compute({
+ location: "hello/<.world (http://foo/bar.js#baz:123:987)",
+ line: 456,
+ }), false),
+ new FrameNode("hello/<.world (http://foo/#bar:123:987)", compute({
+ location: "hello/<.world (http://foo/#bar:123:987)",
+ line: 456,
+ }), false),
+ new FrameNode("hello/<.world (http://foo/:123:987)", compute({
+ location: "hello/<.world (http://foo/:123:987)",
+ line: 456,
+ }), false),
+ new FrameNode("hello/<.world (resource://foo.js -> http://bar/baz.js:123:987)", compute({
+ location: "hello/<.world (resource://foo.js -> http://bar/baz.js:123:987)",
+ line: 456,
+ }), false),
+ new FrameNode("Foo::Bar::Baz", compute({
location: "Foo::Bar::Baz",
- category: CATEGORY_OTHER
- })
- }, false);
+ line: 456,
+ category: CATEGORY_OTHER,
+ }), false),
+ new FrameNode("EnterJIT", compute({
+ location: "EnterJIT",
+ }), false),
+ new FrameNode("chrome://browser/content/content.js", compute({
+ location: "chrome://browser/content/content.js",
+ line: 456,
+ column: 123
+ }), false),
+ new FrameNode("hello/<.world (resource://gre/foo.js:123:434)", compute({
+ location: "hello/<.world (resource://gre/foo.js:123:434)",
+ line: 456
+ }), false),
+ new FrameNode("main (http://localhost:8888/file.js:123:987)", compute({
+ location: "main (http://localhost:8888/file.js:123:987)",
+ line: 123,
+ }), false),
+ new FrameNode("main (resource://gre/modules/devtools/timeline.js:123)", compute({
+ location: "main (resource://gre/modules/devtools/timeline.js:123)",
+ }), false),
+ ];
- equal(frame6.getInfo().nodeType, "Frame",
- "The sixth frame node has the correct type.");
- equal(frame6.getInfo().functionName, "Foo::Bar::Baz",
- "The sixth frame node has the correct function name.");
- equal(frame6.getInfo().fileName, null,
- "The sixth frame node has the correct file name.");
- equal(frame6.getInfo().hostName, null,
- "The sixth frame node has the correct host name.");
- equal(frame6.getInfo().url, null,
- "The sixth frame node has the correct url.");
- equal(frame6.getInfo().line, 456,
- "The sixth frame node has the correct line.");
- equal(frame6.getInfo().categoryData.abbrev, "other",
- "The sixth frame node has the correct category data.");
- equal(frame6.getInfo().isContent, false,
- "The sixth frame node has the correct content flag.");
+ let fields = ["nodeType", "functionName", "fileName", "hostName", "url", "line", "column", "categoryData.abbrev", "isContent", "port"]
+ let expected = [
+ // nodeType, functionName, fileName, hostName, url, line, column, categoryData.abbrev, isContent, port
+ ["Frame", "hello/<.world", "bar.js", "foo", "http://foo/bar.js", 123, 987, void 0, true],
+ ["Frame", "hello/<.world", "bar.js", "foo", "http://foo/bar.js#baz", 123, 987, void 0, true],
+ ["Frame", "hello/<.world", "/", "foo", "http://foo/#bar", 123, 987, void 0, true],
+ ["Frame", "hello/<.world", "/", "foo", "http://foo/", 123, 987, void 0, true],
+ ["Frame", "hello/<.world", "baz.js", "bar", "http://bar/baz.js", 123, 987, "other", false],
+ ["Frame", "Foo::Bar::Baz", null, null, null, 456, void 0, "other", false],
+ ["Frame", "EnterJIT", null, null, null, null, null, "js", false],
+ ["Frame", "chrome://browser/content/content.js", null, null, null, 456, null, "other", false],
+ ["Frame", "hello/<.world", "foo.js", null, "resource://gre/foo.js", 123, 434, "other", false],
+ ["Frame", "main", "file.js", "localhost", "http://localhost:8888/file.js", 123, 987, null, true, 8888],
+ ["Frame", "main", "timeline.js", null, "resource://gre/modules/devtools/timeline.js", 123, null, "tools", false]
+ ];
- let frame7 = new FrameNode("EnterJIT", {
- location: "EnterJIT",
- isContent: FrameUtils.isContent({
- location: "EnterJIT"
- })
- }, false);
+ for (let i = 0; i < frames.length; i++) {
+ let info = frames[i].getInfo();
+ let expect = expected[i];
- equal(frame7.getInfo().nodeType, "Frame",
- "The seventh frame node has the correct type.");
- equal(frame7.getInfo().functionName, "EnterJIT",
- "The seventh frame node has the correct function name.");
- equal(frame7.getInfo().fileName, null,
- "The seventh frame node has the correct file name.");
- equal(frame7.getInfo().hostName, null,
- "The seventh frame node has the correct host name.");
- equal(frame7.getInfo().url, null,
- "The seventh frame node has the correct url.");
- equal(frame7.getInfo().line, null,
- "The seventh frame node has the correct line.");
- equal(frame7.getInfo().column, null,
- "The seventh frame node has the correct column.");
- equal(frame7.getInfo().categoryData.abbrev, "js",
- "The seventh frame node has the correct category data.");
- equal(frame7.getInfo().isContent, false,
- "The seventh frame node has the correct content flag.");
-
- let frame8 = new FrameNode("chrome://browser/content/content.js", {
- location: "chrome://browser/content/content.js",
- line: 456,
- column: 123
- }, false);
-
- equal(frame8.getInfo().hostName, null,
- "The eighth frame node has the correct host name.");
-
- let frame9 = new FrameNode("hello/<.world (resource://gre/foo.js:123:434)", {
- location: "hello/<.world (resource://gre/foo.js:123:434)",
- line: 456
- }, false);
-
- equal(frame9.getInfo().hostName, null,
- "The ninth frame node has the correct host name.");
-
- let frame10 = new FrameNode("main (http://localhost:8888/file.js:123:987)", {
- location: "main (http://localhost:8888/file.js:123:987)",
- line: 123,
- isContent: FrameUtils.isContent({
- location: "main (http://localhost:8888/file.js:123:987)"
- })
- }, false);
-
- equal(frame10.getInfo().nodeType, "Frame",
- "The tenth frame node has the correct type.");
- equal(frame10.getInfo().functionName, "main",
- "The tenth frame node has the correct function name.");
- equal(frame10.getInfo().fileName, "file.js",
- "The tenth frame node has the correct file name.");
- equal(frame10.getInfo().hostName, "localhost",
- "The tenth frame node has the correct host name.");
- equal(frame10.getInfo().url, "http://localhost:8888/file.js",
- "The tenth frame node has the correct url.");
- equal(frame10.getInfo().line, 123,
- "The tenth frame node has the correct line.");
- equal(frame10.getInfo().column, 987,
- "The tenth frame node has the correct column.");
- equal(frame10.getInfo().isContent, true,
- "The tenth frame node has the correct content flag.");
- equal(frame10.getInfo().host, "localhost:8888",
- "The tenth frame node has the correct host.");
- equal(frame10.getInfo().port, 8888,
- "The tenth frame node has the correct port.");
+ for (let j = 0; j < fields.length; j++) {
+ let field = fields[j];
+ let value = field === "categoryData.abbrev" ? info.categoryData.abbrev : info[field];
+ equal(value, expect[j], `${field} for frame #${i} is correct: ${expect[j]}`);
+ }
+ }
});
diff --git a/browser/devtools/performance/test/unit/test_tree-model-09.js b/browser/devtools/performance/test/unit/test_tree-model-09.js
new file mode 100644
index 00000000000..70a411b6f1e
--- /dev/null
+++ b/browser/devtools/performance/test/unit/test_tree-model-09.js
@@ -0,0 +1,82 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Tests that when displaying only content nodes, platform nodes are generalized.
+ */
+
+let { CATEGORY_MASK } = devtools.require("devtools/performance/global");
+
+function run_test() {
+ run_next_test();
+}
+
+add_task(function test() {
+ let { ThreadNode } = devtools.require("devtools/performance/tree-model");
+ let url = (n) => `http://content/${n}`;
+
+ // Create a root node from a given samples array.
+
+ let root = getFrameNodePath(new ThreadNode(gThread, { contentOnly: true }), "(root)");
+
+ /*
+ * should have a tree like:
+ * root
+ * - (Tools)
+ * - A
+ * - B
+ * - C
+ * - D
+ * - E
+ * - F
+ * - (Tools)
+ */
+
+ // Test the root node.
+
+ equal(root.calls.length, 2, "root has 2 children");
+ ok(getFrameNodePath(root, url("A")), "root has content child");
+ ok(getFrameNodePath(root, "9000"), "root has platform generalized child from Chrome JS");
+ equal(getFrameNodePath(root, "9000").calls.length, 0, "platform generalized child is a leaf.");
+
+ ok(getFrameNodePath(root, `${url("A")} > ${url("E")} > ${url("F")} > 9000`),
+ "a second leaf of the generalized Chrome JS exists.");
+
+ equal(getFrameNodePath(root, "9000").category,
+ getFrameNodePath(root, `${url("A")} > ${url("E")} > ${url("F")} > 9000`).category,
+ "generalized frames of same type are duplicated in top-down view");
+});
+
+let gThread = synthesizeProfileForTest([{
+ time: 5,
+ frames: [
+ { location: "(root)" },
+ { location: "http://content/A" },
+ { location: "http://content/B" },
+ { location: "http://content/C" }
+ ]
+}, {
+ time: 5 + 6,
+ frames: [
+ { location: "(root)" },
+ { location: "http://content/A" },
+ { location: "http://content/B" },
+ { location: "fn (resource://loader.js -> resource:///modules/devtools/timeline.js)" },
+ { location: "http://content/D" }
+ ]
+}, {
+ time: 5 + 6 + 7,
+ frames: [
+ { location: "(root)" },
+ { location: "http://content/A" },
+ { location: "http://content/E" },
+ { location: "http://content/F" },
+ { location: "fn (resource://loader.js -> resource://gre/modules/devtools/promise.js)" }
+ ]
+}, {
+ time: 5 + 20,
+ frames: [
+ { location: "(root)" },
+ { location: "somefn (resource://loader.js -> resource:///modules/devtools/framerate.js)" }
+ ]
+}]);
diff --git a/browser/devtools/performance/test/unit/xpcshell.ini b/browser/devtools/performance/test/unit/xpcshell.ini
index 2a63637b977..deaaa1fd707 100644
--- a/browser/devtools/performance/test/unit/xpcshell.ini
+++ b/browser/devtools/performance/test/unit/xpcshell.ini
@@ -5,7 +5,9 @@ tail =
firefox-appdir = browser
skip-if = toolkit == 'android' || toolkit == 'gonk'
+[test_profiler-categories.js]
[test_frame-utils-01.js]
+[test_frame-utils-02.js]
[test_tree-model-01.js]
[test_tree-model-02.js]
[test_tree-model-03.js]
@@ -14,3 +16,4 @@ skip-if = toolkit == 'android' || toolkit == 'gonk'
[test_tree-model-06.js]
[test_tree-model-07.js]
[test_tree-model-08.js]
+[test_tree-model-09.js]
diff --git a/browser/locales/en-US/chrome/browser/devtools/profiler.properties b/browser/locales/en-US/chrome/browser/devtools/profiler.properties
index 5bb4a1c7979..dd0a16a8d72 100644
--- a/browser/locales/en-US/chrome/browser/devtools/profiler.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/profiler.properties
@@ -82,6 +82,7 @@ category.network=Network
category.graphics=Graphics
category.storage=Storage
category.events=Input & Events
+category.tools=Tools
# LOCALIZATION NOTE (graphs.ms):
# This string is displayed in the call tree after units of time in milliseconds.
diff --git a/docshell/base/TimelineMarker.cpp b/docshell/base/TimelineMarker.cpp
index 2bae8e8e413..90f70f4b04e 100644
--- a/docshell/base/TimelineMarker.cpp
+++ b/docshell/base/TimelineMarker.cpp
@@ -15,7 +15,7 @@ TimelineMarker::TimelineMarker(nsDocShell* aDocShell, const char* aName,
MOZ_COUNT_CTOR(TimelineMarker);
MOZ_ASSERT(aName);
aDocShell->Now(&mTime);
- if (aMetaData == TRACING_INTERVAL_START) {
+ if (aMetaData == TRACING_INTERVAL_START || aMetaData == TRACING_TIMESTAMP) {
CaptureStack();
}
}
@@ -31,7 +31,9 @@ TimelineMarker::TimelineMarker(nsDocShell* aDocShell, const char* aName,
MOZ_COUNT_CTOR(TimelineMarker);
MOZ_ASSERT(aName);
aDocShell->Now(&mTime);
- if (aMetaData == TRACING_INTERVAL_START && aStackRequest != NO_STACK) {
+ if ((aMetaData == TRACING_INTERVAL_START ||
+ aMetaData == TRACING_TIMESTAMP) &&
+ aStackRequest != NO_STACK) {
CaptureStack();
}
}
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index cfa0c8b1ae6..89cc87fd55b 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -2998,6 +2998,7 @@ nsDocShell::PopProfileTimelineMarkers(
marker->mName = NS_ConvertUTF8toUTF16(startPayload->GetName());
marker->mStart = startPayload->GetTime();
marker->mEnd = startPayload->GetTime();
+ marker->mStack = startPayload->GetStack();
startPayload->AddDetails(aCx, *marker);
continue;
}
diff --git a/dom/base/Console.cpp b/dom/base/Console.cpp
index c67423b89cc..6ead4e1d8a7 100644
--- a/dom/base/Console.cpp
+++ b/dom/base/Console.cpp
@@ -1065,7 +1065,6 @@ public:
const nsAString& aCause)
: TimelineMarker(aDocShell, "TimeStamp", aMetaData, aCause)
{
- CaptureStack();
MOZ_ASSERT(aMetaData == TRACING_TIMESTAMP);
}
@@ -1075,7 +1074,6 @@ public:
if (!GetCause().IsEmpty()) {
aMarker.mCauseName.Construct(GetCause());
}
- aMarker.mEndStack = GetStack();
}
};
diff --git a/mobile/android/base/DoorHangerPopup.java b/mobile/android/base/DoorHangerPopup.java
index c1ef92f6cda..bf4ab4004e8 100644
--- a/mobile/android/base/DoorHangerPopup.java
+++ b/mobile/android/base/DoorHangerPopup.java
@@ -9,6 +9,7 @@ import java.util.HashSet;
import org.json.JSONException;
import org.json.JSONObject;
+import org.json.JSONArray;
import org.mozilla.gecko.AppConstants.Versions;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.ThreadUtils;
@@ -113,9 +114,21 @@ public class DoorHangerPopup extends AnchoredPopup
final DoorhangerConfig config = new DoorhangerConfig(tabId, id, doorhangerType, this);
config.setMessage(json.getString("message"));
- config.appendButtonsFromJSON(json.getJSONArray("buttons"));
config.setOptions(json.getJSONObject("options"));
+ final JSONArray buttonArray = json.getJSONArray("buttons");
+ int numButtons = buttonArray.length();
+ if (numButtons > 2) {
+ Log.e(LOGTAG, "Doorhanger can have a maximum of two buttons!");
+ numButtons = 2;
+ }
+
+ for (int i = 0; i < numButtons; i++) {
+ final JSONObject buttonJSON = buttonArray.getJSONObject(i);
+ final boolean isPositive = buttonJSON.optBoolean("positive", false);
+ config.setButton(buttonJSON.getString("label"), buttonJSON.getInt("callback"), isPositive);
+ }
+
return config;
}
diff --git a/mobile/android/base/Tabs.java b/mobile/android/base/Tabs.java
index 7f0dc83bdad..628c541b9f1 100644
--- a/mobile/android/base/Tabs.java
+++ b/mobile/android/base/Tabs.java
@@ -22,6 +22,7 @@ import org.mozilla.gecko.mozglue.ContextUtils.SafeIntent;
import org.mozilla.gecko.mozglue.JNITarget;
import org.mozilla.gecko.mozglue.RobocopTarget;
import org.mozilla.gecko.sync.setup.SyncAccounts;
+import org.mozilla.gecko.preferences.GeckoPreferences;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.ThreadUtils;
@@ -853,7 +854,7 @@ public class Tabs implements GeckoEventListener {
boolean external = (flags & LOADURL_EXTERNAL) != 0;
final SharedPreferences sharedPrefs = GeckoSharedPrefs.forApp(mAppContext);
- final boolean isPrivatePref = sharedPrefs.getBoolean("android.not_a_preference.openExternalURLsPrivately", false);
+ final boolean isPrivatePref = sharedPrefs.getBoolean(GeckoPreferences.PREFS_OPEN_URLS_IN_PRIVATE, false);
if (isPrivatePref && external) {
isPrivate = true;
}
diff --git a/mobile/android/base/home/BrowserSearch.java b/mobile/android/base/home/BrowserSearch.java
index 2689c53e189..1020bfbf3a6 100644
--- a/mobile/android/base/home/BrowserSearch.java
+++ b/mobile/android/base/home/BrowserSearch.java
@@ -554,7 +554,7 @@ public class BrowserSearch extends HomeFragment
ArrayList searchEngines = new ArrayList();
for (int i = 0; i < engines.length(); i++) {
final JSONObject engineJSON = engines.getJSONObject(i);
- final SearchEngine engine = new SearchEngine(engineJSON);
+ final SearchEngine engine = new SearchEngine((Context) getActivity(), engineJSON);
if (engine.name.equals(suggestEngine) && suggestTemplate != null) {
// Suggest engine should be at the front of the list.
diff --git a/mobile/android/base/home/SearchEngine.java b/mobile/android/base/home/SearchEngine.java
index 0ee241f5646..268381ae543 100644
--- a/mobile/android/base/home/SearchEngine.java
+++ b/mobile/android/base/home/SearchEngine.java
@@ -6,11 +6,14 @@
package org.mozilla.gecko.home;
import org.mozilla.gecko.gfx.BitmapUtils;
+import org.mozilla.gecko.R;
import org.json.JSONException;
import org.json.JSONObject;
+import android.content.Context;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.util.Log;
import java.util.ArrayList;
@@ -25,7 +28,7 @@ public class SearchEngine {
private final Bitmap icon;
private volatile List suggestions = new ArrayList(); // Never null.
- public SearchEngine(JSONObject engineJSON) throws JSONException {
+ public SearchEngine(final Context context, final JSONObject engineJSON) throws JSONException {
if (engineJSON == null) {
throw new IllegalArgumentException("Can't instantiate SearchEngine from null JSON.");
}
@@ -40,10 +43,14 @@ public class SearchEngine {
final String iconURI = getString(engineJSON, "iconURI");
if (iconURI == null) {
Log.w(LOG_TAG, "iconURI is null for search engine " + this.name);
- this.icon = null;
- return;
}
- this.icon = BitmapUtils.getBitmapFromDataURI(iconURI);
+ final Bitmap tempIcon = BitmapUtils.getBitmapFromDataURI(iconURI);
+
+ this.icon = (tempIcon != null) ? tempIcon : getDefaultFavicon(context);
+ }
+
+ private Bitmap getDefaultFavicon(final Context context) {
+ return BitmapFactory.decodeResource(context.getResources(), R.drawable.favicon_search);
}
private static String getString(JSONObject data, String key) throws JSONException {
diff --git a/mobile/android/base/home/SearchEngineBar.java b/mobile/android/base/home/SearchEngineBar.java
index 93759bc76b4..128e80d22b8 100644
--- a/mobile/android/base/home/SearchEngineBar.java
+++ b/mobile/android/base/home/SearchEngineBar.java
@@ -15,6 +15,7 @@ import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
+import android.widget.ImageView;
import org.mozilla.gecko.R;
import org.mozilla.gecko.widget.FaviconView;
@@ -94,9 +95,9 @@ public class SearchEngineBar extends TwoWayView
view = convertView;
}
- final FaviconView faviconView = (FaviconView) view.findViewById(R.id.search_engine_icon);
+ final ImageView faviconView = (ImageView) view.findViewById(R.id.search_engine_icon);
final SearchEngine searchEngine = searchEngines.get(position);
- faviconView.updateAndScaleImage(searchEngine.getIcon(), searchEngine.getEngineIdentifier());
+ faviconView.setImageBitmap(searchEngine.getIcon());
final View container = view.findViewById(R.id.search_engine_icon_container);
final String desc = getResources().getString(R.string.search_bar_item_desc, searchEngine.getEngineIdentifier());
diff --git a/mobile/android/base/preferences/GeckoPreferences.java b/mobile/android/base/preferences/GeckoPreferences.java
index 8a05000850a..d8ac3578449 100644
--- a/mobile/android/base/preferences/GeckoPreferences.java
+++ b/mobile/android/base/preferences/GeckoPreferences.java
@@ -127,7 +127,7 @@ OnSharedPreferenceChangeListener
private static final String PREFS_SYNC = NON_PREF_PREFIX + "sync";
private static final String PREFS_TRACKING_PROTECTION = "privacy.trackingprotection.enabled";
private static final String PREFS_TRACKING_PROTECTION_LEARN_MORE = NON_PREF_PREFIX + "trackingprotection.learn_more";
- private static final String PREFS_OPEN_URLS_IN_PRIVATE = NON_PREF_PREFIX + "openExternalURLsPrivately";
+ public static final String PREFS_OPEN_URLS_IN_PRIVATE = NON_PREF_PREFIX + "openExternalURLsPrivately";
private static final String ACTION_STUMBLER_UPLOAD_PREF = AppConstants.ANDROID_PACKAGE_NAME + ".STUMBLER_PREF";
@@ -703,9 +703,9 @@ OnSharedPreferenceChangeListener
preferences.removePreference(pref);
i--;
continue;
- } else if (AppConstants.RELEASE_BUILD &&
+ } else if (!AppConstants.NIGHTLY_BUILD &&
PREFS_OPEN_URLS_IN_PRIVATE.equals(key)) {
- // Remove UI for opening external links in private borwsing onrelease builds.
+ // Remove UI for opening external links in private browsing on non-Nightly builds.
preferences.removePreference(pref);
i--;
continue;
diff --git a/mobile/android/base/resources/drawable/action_bar_button_negative.xml b/mobile/android/base/resources/drawable/action_bar_button_negative.xml
new file mode 100644
index 00000000000..7611d70ba5f
--- /dev/null
+++ b/mobile/android/base/resources/drawable/action_bar_button_negative.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
diff --git a/mobile/android/base/resources/drawable/action_bar_button_positive.xml b/mobile/android/base/resources/drawable/action_bar_button_positive.xml
new file mode 100644
index 00000000000..ac7020b97c6
--- /dev/null
+++ b/mobile/android/base/resources/drawable/action_bar_button_positive.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
diff --git a/mobile/android/base/resources/layout/default_doorhanger.xml b/mobile/android/base/resources/layout/default_doorhanger.xml
new file mode 100644
index 00000000000..d1e57c382a0
--- /dev/null
+++ b/mobile/android/base/resources/layout/default_doorhanger.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mobile/android/base/resources/layout/doorhanger.xml b/mobile/android/base/resources/layout/doorhanger.xml
index be3c4ab88a3..777aad929e7 100644
--- a/mobile/android/base/resources/layout/doorhanger.xml
+++ b/mobile/android/base/resources/layout/doorhanger.xml
@@ -5,51 +5,41 @@
-
-
+ android:layout_height="wrap_content"/>
-
-
-
-
-
-
-
+ android:orientation="horizontal">
+
+
+
+
+
+
-
-
-
diff --git a/mobile/android/base/resources/layout/login_doorhanger.xml b/mobile/android/base/resources/layout/login_doorhanger.xml
index 51730c1e38c..29922514539 100644
--- a/mobile/android/base/resources/layout/login_doorhanger.xml
+++ b/mobile/android/base/resources/layout/login_doorhanger.xml
@@ -3,66 +3,30 @@
- 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/. -->
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/mobile/android/base/resources/layout/login_edit_dialog.xml b/mobile/android/base/resources/layout/login_edit_dialog.xml
index f8c2b211244..d725a0aa16b 100644
--- a/mobile/android/base/resources/layout/login_edit_dialog.xml
+++ b/mobile/android/base/resources/layout/login_edit_dialog.xml
@@ -25,6 +25,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/doorhanger_login_edit_toggle"
- android:paddingTop="@dimen/doorhanger_padding"/>
+ android:layout_marginTop="@dimen/doorhanger_padding"/>
diff --git a/mobile/android/base/resources/layout/search_engine_bar_item.xml b/mobile/android/base/resources/layout/search_engine_bar_item.xml
index 320ad4e7748..0b4bcc59890 100644
--- a/mobile/android/base/resources/layout/search_engine_bar_item.xml
+++ b/mobile/android/base/resources/layout/search_engine_bar_item.xml
@@ -11,7 +11,6 @@
View (browser_search at the time of this writing). -->
-
+ android:scaleType="fitCenter"/>
diff --git a/mobile/android/base/resources/layout/search_engine_row.xml b/mobile/android/base/resources/layout/search_engine_row.xml
index e4fc3df052a..103103813c3 100644
--- a/mobile/android/base/resources/layout/search_engine_row.xml
+++ b/mobile/android/base/resources/layout/search_engine_row.xml
@@ -3,10 +3,8 @@
- 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/. -->
-
+
-
+ android:minHeight="@dimen/favicon_bg"/>
+ android:layout_marginTop="@dimen/doorhanger_section_padding_small"/>
+ android:layout_marginTop="@dimen/doorhanger_section_padding_small"/>
diff --git a/mobile/android/base/resources/values/attrs.xml b/mobile/android/base/resources/values/attrs.xml
index b006dfeb5d9..43eb4e5bce6 100644
--- a/mobile/android/base/resources/values/attrs.xml
+++ b/mobile/android/base/resources/values/attrs.xml
@@ -187,8 +187,6 @@
-
-
diff --git a/mobile/android/base/resources/values/colors.xml b/mobile/android/base/resources/values/colors.xml
index 78cfcb9d3e5..6c3ed457d41 100644
--- a/mobile/android/base/resources/values/colors.xml
+++ b/mobile/android/base/resources/values/colors.xml
@@ -9,6 +9,7 @@
#E66000
#DC5600
#0096DD
+ #0082C6
#CF68FF
#222222
diff --git a/mobile/android/base/resources/values/styles.xml b/mobile/android/base/resources/values/styles.xml
index cdaf19d9b99..0f7e338aaab 100644
--- a/mobile/android/base/resources/values/styles.xml
+++ b/mobile/android/base/resources/values/styles.xml
@@ -281,6 +281,14 @@
- 18sp
+
+