merge fx-team to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-12-22 11:42:20 +01:00
commit 54a9eaebfd
30 changed files with 350 additions and 216 deletions

View File

@ -3,12 +3,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Ci } = require('chrome');
const system = require('sdk/system/events');
const { frames } = require('sdk/remote/child');
const { WorkerChild } = require('sdk/content/worker-child');
// map observer topics to tab event names
const EVENTS = {
'content-document-global-created': 'create',
'chrome-document-global-created': 'create',
'content-document-interactive': 'ready',
'chrome-document-interactive': 'ready',
'content-document-loaded': 'load',
@ -17,12 +20,18 @@ const EVENTS = {
}
function topicListener({ subject, type }) {
let window = subject.defaultView;
if (!window)
// NOTE detect the window from the subject:
// - on *-global-created the subject is the window
// - in the other cases it is the document object
let window = subject instanceof Ci.nsIDOMWindow ? subject : subject.defaultView;
if (!window){
return;
let frame = frames.getFrameForWindow(subject.defaultView);
if (frame)
frame.port.emit('sdk/tab/event', EVENTS[type]);
}
let frame = frames.getFrameForWindow(window);
if (frame) {
let readyState = frame.content.document.readyState;
frame.port.emit('sdk/tab/event', EVENTS[type], { readyState });
}
}
for (let topic in EVENTS)
@ -31,8 +40,9 @@ for (let topic in EVENTS)
// bug 1024105 - content-page-shown notification doesn't pass persisted param
function eventListener({target, type, persisted}) {
let frame = this;
if (target === frame.content.document)
if (target === frame.content.document) {
frame.port.emit('sdk/tab/event', type, persisted);
}
}
frames.addEventListener('pageshow', eventListener, true);
@ -40,3 +50,9 @@ frames.port.on('sdk/tab/attach', (frame, options) => {
options.window = frame.content;
new WorkerChild(options);
});
// Forward the existent frames's readyState.
for (let frame of frames) {
let readyState = frame.content.document.readyState;
frame.port.emit('sdk/tab/event', 'init', { readyState });
}

View File

@ -44,6 +44,9 @@ function isClosed(tab) {
return viewsFor.get(tab).closing;
}
// private tab attribute where the remote cached value is stored
const remoteReadyStateCached = Symbol("remoteReadyStateCached");
const Tab = Class({
implements: [EventTarget],
initialize: function(tabElement, options = null) {
@ -125,8 +128,7 @@ const Tab = Class({
},
get readyState() {
// TODO: This will use CPOWs in e10s: bug 1146606
return isDestroyed(this) ? undefined : browser(this).contentDocument.readyState;
return isDestroyed(this) ? undefined : this[remoteReadyStateCached] || "uninitialized";
},
pin: function() {
@ -306,11 +308,21 @@ function tabEventListener(event, tabElement, ...args) {
removeListItem(window.tabs, tab);
// The tabs module will take care of removing from its internal list
}
else if (event == "ready" || event == "load") {
else if (event == "init" || event == "create" || event == "ready" || event == "load") {
// Ignore load events from before browser windows have fully loaded, these
// are for about:blank in the initial tab
if (isBrowser(domWindow) && !domWindow.gBrowserInit.delayedStartupFinished)
return;
// update the cached remote readyState value
let { readyState } = args[0] || {};
tab[remoteReadyStateCached] = readyState;
}
if (event == "init") {
// Do not emit events for the detected existent tabs, we only need to cache
// their current document.readyState value.
return;
}
tabEmit(tab, event, ...args);

View File

@ -9,7 +9,7 @@ const windows = require("sdk/windows").browserWindows;
const app = require("sdk/system/xul-app");
const { viewFor } = require("sdk/view/core");
const { modelFor } = require("sdk/model/core");
const { getTabId, isTab } = require("sdk/tabs/utils");
const { getBrowserForTab, getTabId, isTab } = require("sdk/tabs/utils");
const { defer } = require("sdk/lang/functional");
function tabExistenceInTabs(assert, found, tab, tabs) {
@ -202,4 +202,14 @@ exports["test tab.readyState"] = (assert, done) => {
});
}
exports["test tab.readyState for existent tabs"] = (assert) => {
assert.equal(tabs.length, 1, "tabs contains an existent tab");
for (let tab of tabs) {
let browserForTab = getBrowserForTab(viewFor(tab));
assert.equal(browserForTab.contentDocument.readyState, tab.readyState,
"tab.readyState has the same value of the associated contentDocument.readyState CPOW");
}
}
require("sdk/test").run(module.exports);

View File

@ -1950,6 +1950,16 @@ Experiments.ExperimentEntry.prototype = {
return changes;
}
// Check permissions to see if we can enable the addon.
if (!(addon.permissions & AddonManager.PERM_CAN_ENABLE)) {
throw new Error("Don't have permission to enable addon " + addon.id + ", perm=" + addon.permission);
}
// Experiment addons should not require a restart.
if (!!(addon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_ENABLE)) {
throw new Error("Experiment addon requires a restart: " + addon.id);
}
let deferred = Promise.defer();
// Else we need to enable it.
@ -1964,13 +1974,24 @@ Experiments.ExperimentEntry.prototype = {
},
};
this._log.info("Activating add-on: " + addon.id);
for (let handler of ["onDisabled", "onOperationCancelled", "onUninstalled"]) {
listener[handler] = (evtAddon) => {
if (evtAddon.id != addon.id) {
return;
}
AddonManager.removeAddonListener(listener);
deferred.reject("Failed to enable addon " + addon.id + " due to: " + handler);
};
}
this._log.info("reconcileAddonState() - Activating add-on: " + addon.id);
AddonManager.addAddonListener(listener);
addon.userDisabled = false;
yield deferred.promise;
changes |= this.ADDON_CHANGE_ENABLE;
this._log.info("Add-on has been enabled: " + addon.id);
this._log.info("reconcileAddonState() - Add-on has been enabled: " + addon.id);
return changes;
}),

View File

@ -1088,11 +1088,12 @@ AnimationTimeBlock.prototype = {
text += "\n";
// Adding the iteration count (the infinite symbol, or an integer).
// XXX: see bug 1219608 to remove this if the count is 1.
text += L10N.getStr("player.animationIterationCountLabel") + " ";
text += state.iterationCount ||
L10N.getStr("player.infiniteIterationCountText");
text += "\n";
if (state.iterationCount !== 1) {
text += L10N.getStr("player.animationIterationCountLabel") + " ";
text += state.iterationCount ||
L10N.getStr("player.infiniteIterationCountText");
text += "\n";
}
// Adding the playback rate if it's different than 1.
if (state.playbackRate !== 1) {

View File

@ -9,7 +9,7 @@
add_task(function*() {
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
let {panel} = yield openAnimationInspector();
let {panel, controller} = yield openAnimationInspector();
info("Getting the animation element from the panel");
let timelineEl = panel.animationsTimelineComponent.rootWrapperEl;
@ -17,12 +17,16 @@ add_task(function*() {
// Verify that each time-block's name element has a tooltip that looks sort of
// ok. We don't need to test the actual content.
for (let el of timeBlockNameEls) {
ok(el.hasAttribute("title"), "The tooltip is defined");
[...timeBlockNameEls].forEach((el, i) => {
ok(el.hasAttribute("title"), "The tooltip is defined for animation " + i);
let title = el.getAttribute("title");
ok(title.match(/Delay: [\d.-]+s/), "The tooltip shows the delay");
ok(title.match(/Duration: [\d.]+s/), "The tooltip shows the duration");
ok(title.match(/Repeats: /), "The tooltip shows the iterations");
}
if (controller.animationPlayers[i].state.iterationCount !== 1) {
ok(title.match(/Repeats: /), "The tooltip shows the iterations");
} else {
ok(!title.match(/Repeats: /), "The tooltip doesn't show the iterations");
}
});
});

View File

@ -25,6 +25,7 @@ support-files =
doc_inspector_search.html
doc_inspector_search-reserved.html
doc_inspector_search-suggestions.html
doc_inspector_search-svg.html
doc_inspector_select-last-selected-01.html
doc_inspector_select-last-selected-02.html
head.js
@ -108,6 +109,7 @@ skip-if = e10s # Test synthesize scrolling events in content. Also, see bug 1035
[browser_inspector_search-04.js]
[browser_inspector_search-05.js]
[browser_inspector_search-06.js]
[browser_inspector_search-07.js]
[browser_inspector_search-reserved.js]
[browser_inspector_select-docshell.js]
[browser_inspector_select-last-selected.js]

View File

@ -0,0 +1,49 @@
/* 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/ */
"use strict";
// Test that searching for classes on SVG elements does work (see bug 1219920).
const TEST_URL = TEST_URL_ROOT + "doc_inspector_search-svg.html";
// An array of (key, suggestions) pairs where key is a key to press and
// suggestions is an array of suggestions that should be shown in the popup.
const TEST_DATA = [{
key: "c",
suggestions: ["circle", ".class1", ".class2"]
}, {
key: "VK_BACK_SPACE",
suggestions: []
}, {
key: ".",
suggestions: [".class1", ".class2"]
}];
add_task(function* () {
let {inspector} = yield openInspectorForURL(TEST_URL);
let {searchBox} = inspector;
let popup = inspector.searchSuggestions.searchPopup;
yield focusSearchBoxUsingShortcut(inspector.panelWin);
for (let {key, suggestions} of TEST_DATA) {
info("Pressing " + key + " to get " + suggestions);
let command = once(searchBox, "command");
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
yield command;
info("Waiting for search query to complete and getting the suggestions");
yield inspector.searchSuggestions._lastQuery;
let actualSuggestions = popup.getItems().reverse();
is(popup.isOpen ? actualSuggestions.length : 0, suggestions.length,
"There are expected number of suggestions.");
for (let i = 0; i < suggestions.length; i++) {
is(actualSuggestions[i].label, suggestions[i],
"The suggestion at " + i + "th index is correct.");
}
}
});

View File

@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Inspector SVG Search Box Test</title>
</head>
<body>
<div class="class1"></div>
<svg>
<circle cx="0" cy="0" r="50" class="class2" />
</svg>
</body>
</html>

View File

@ -128,13 +128,16 @@ ul.children + .tag-line::before {
left: -1000em;
right: 0;
height: 100%;
z-index: -1;
z-index: 0;
}
.expander {
display: inline-block;
margin-left: -14px;
vertical-align: middle;
/* Make sure the expander still appears above the tag-state */
position: relative;
z-index: 1;
}
.child.collapsed .child {
@ -190,6 +193,12 @@ ul.children + .tag-line::before {
cursor: pointer;
}
.editor {
/* Make sure the editor still appears above the tag-state */
position: relative;
z-index: 1;
}
.editor.text {
display: inline-block;
}
@ -198,4 +207,3 @@ ul.children + .tag-line::before {
.editor.comment pre {
font: inherit;
}

View File

@ -8,6 +8,7 @@ const { Cc, Ci, Cu, Cr } = require("chrome");
loader.lazyRequireGetter(this, "Services");
loader.lazyRequireGetter(this, "global",
"devtools/client/performance/modules/global");
const demangle = require("devtools/client/shared/demangle");
// Character codes used in various parsing helper functions.
const CHAR_CODE_A = "a".charCodeAt(0);
@ -27,12 +28,14 @@ const CHAR_CODE_T = "t".charCodeAt(0);
const CHAR_CODE_U = "u".charCodeAt(0);
const CHAR_CODE_0 = "0".charCodeAt(0);
const CHAR_CODE_9 = "9".charCodeAt(0);
const CHAR_CODE_CAP_Z = "Z".charCodeAt(0);
const CHAR_CODE_LPAREN = "(".charCodeAt(0);
const CHAR_CODE_RPAREN = ")".charCodeAt(0);
const CHAR_CODE_COLON = ":".charCodeAt(0);
const CHAR_CODE_SLASH = "/".charCodeAt(0);
const CHAR_CODE_SPACE = " ".charCodeAt(0);
const CHAR_CODE_UNDERSCORE = "_".charCodeAt(0);
// The cache used in the `nsIURL` function.
const gNSURLStore = new Map();
@ -480,6 +483,13 @@ function isNumeric(c) {
return c >= CHAR_CODE_0 && c <= CHAR_CODE_9;
}
function shouldDemangle(name) {
return name && name.charCodeAt &&
name.charCodeAt(0) === CHAR_CODE_UNDERSCORE &&
name.charCodeAt(1) === CHAR_CODE_UNDERSCORE &&
name.charCodeAt(2) === CHAR_CODE_CAP_Z;
}
/**
* Calculates the relative costs of this frame compared to a root,
* and generates allocations information if specified. Uses caching
@ -513,7 +523,9 @@ function getFrameInfo (node, options) {
data.nodeType = node.nodeType;
// Frame name (function location or some meta information)
data.name = data.isMetaCategory ? data.categoryData.label : data.functionName || "";
data.name = data.isMetaCategory ? data.categoryData.label :
shouldDemangle(data.functionName) ? demangle(data.functionName) : data.functionName;
data.tooltiptext = data.isMetaCategory ? data.categoryData.label : node.location || "";
gFrameData.set(node, data);
@ -583,3 +595,4 @@ exports.parseLocation = parseLocation;
exports.getInflatedFrameCache = getInflatedFrameCache;
exports.getOrAddInflatedFrame = getOrAddInflatedFrame;
exports.InflatedFrame = InflatedFrame;
exports.shouldDemangle = shouldDemangle;

View File

@ -4,9 +4,12 @@
/**
* Tests if the profiler's tree view implementation works properly and
* creates the correct column structure after expanding some of the nodes.
* Also tests that demangling works.
*/
var { CATEGORY_MASK } = require("devtools/client/performance/modules/global");
var MANGLED_FN = "__Z3FooIiEvv";
var UNMANGLED_FN = "void Foo<int>()";
function test() {
let { ThreadNode } = require("devtools/client/performance/modules/logic/tree-model");
@ -94,12 +97,6 @@ function test() {
"The .A.B node's percentage cell displays the correct value.");
is($$sampl(2).textContent.trim(), "0",
"The .A.B node's samples cell displays the correct value.");
is($fun(".call-tree-name", $$(".call-tree-item")[2]).textContent.trim(), "B",
"The .A.B node's function cell displays the correct name.");
is($fun(".call-tree-url", $$(".call-tree-item")[2]).textContent.trim(), "baz",
"The .A.B node's function cell displays the correct url.");
ok($fun(".call-tree-url", $$(".call-tree-item")[2]).getAttribute("tooltiptext").includes("http://foo/bar/baz"),
"The .A.B node's function cell displays the correct url tooltiptext.");
is($fun(".call-tree-line", $$(".call-tree-item")[2]).textContent.trim(), ":34",
"The .A.B node's function cell displays the correct line.");
is($fun(".call-tree-host", $$(".call-tree-item")[2]).textContent.trim(), "foo",
@ -107,6 +104,16 @@ function test() {
is($fun(".call-tree-category", $$(".call-tree-item")[2]).textContent.trim(), "Styles",
"The .A.B node's function cell displays the correct category.");
// Test demangling in the profiler tree
is($fun(".call-tree-name", $$(".call-tree-item")[2]).textContent.trim(), UNMANGLED_FN,
"The mangled function name is demangled.");
ok($$(".call-tree-item")[2].getAttribute("tooltiptext").includes(MANGLED_FN),
"The mangled node's row's tooltip contains the original mangled name.");
is($fun(".call-tree-url", $$(".call-tree-item")[2]).textContent.trim(), "baz",
"The mangled node's function cell displays the correct url.");
ok($fun(".call-tree-url", $$(".call-tree-item")[2]).getAttribute("tooltiptext").includes("http://foo/bar/baz"),
"The mangled node's function cell displays the url tooltiptext.");
is($$dur(3).textContent.trim(), "5 ms",
"The .A.E node's duration cell displays the correct value.");
is($$perc(3).textContent.trim(), "25%",
@ -134,7 +141,7 @@ var gThread = synthesizeProfileForTest([{
frames: [
{ category: CATEGORY_MASK('other'), location: "(root)" },
{ category: CATEGORY_MASK('other'), location: "A (http://foo/bar/baz:12)" },
{ category: CATEGORY_MASK('css'), location: "B (http://foo/bar/baz:34)" },
{ category: CATEGORY_MASK('css'), location: `${MANGLED_FN} (http://foo/bar/baz:34)` },
{ category: CATEGORY_MASK('js'), location: "C (http://foo/bar/baz:56)" }
]
}, {
@ -142,7 +149,7 @@ var gThread = synthesizeProfileForTest([{
frames: [
{ category: CATEGORY_MASK('other'), location: "(root)" },
{ category: CATEGORY_MASK('other'), location: "A (http://foo/bar/baz:12)" },
{ category: CATEGORY_MASK('css'), location: "B (http://foo/bar/baz:34)" },
{ category: CATEGORY_MASK('css'), location: `${MANGLED_FN} (http://foo/bar/baz:34)` },
{ category: CATEGORY_MASK('gc', 1), location: "D (http://foo/bar/baz:78)" }
]
}, {
@ -150,7 +157,7 @@ var gThread = synthesizeProfileForTest([{
frames: [
{ category: CATEGORY_MASK('other'), location: "(root)" },
{ category: CATEGORY_MASK('other'), location: "A (http://foo/bar/baz:12)" },
{ category: CATEGORY_MASK('css'), location: "B (http://foo/bar/baz:34)" },
{ category: CATEGORY_MASK('css'), location: `${MANGLED_FN} (http://foo/bar/baz:34)` },
{ category: CATEGORY_MASK('gc', 1), location: "D (http://foo/bar/baz:78)" }
]
}, {

File diff suppressed because one or more lines are too long

View File

@ -20,6 +20,7 @@ DevToolsModules(
'browser-loader.js',
'css-parsing-utils.js',
'Curl.jsm',
'demangle.js',
'DeveloperToolbar.jsm',
'devices.js',
'DOMHelpers.jsm',

View File

@ -6,7 +6,24 @@
// Tests that the Filter Editor Widget parses filter values correctly (setCssValue)
const TEST_URI = "chrome://devtools/content/shared/widgets/filter-frame.xhtml";
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
const {CSSFilterEditorWidget} =
require("devtools/client/shared/widgets/FilterWidget");
const {cssTokenizer} = require("devtools/client/shared/css-parsing-utils");
const DOMUtils =
Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
// Verify that the given string consists of a valid CSS URL token.
// Return true on success, false on error.
function verifyURL(string) {
let lexer = DOMUtils.getCSSLexer(string);
let token = lexer.nextToken();
if (!token || token.tokenType !== "url") {
return false;
}
return lexer.nextToken() === null;
}
add_task(function *() {
yield addTab("about:blank");
@ -80,8 +97,18 @@ add_task(function *() {
widget.setCssValue("url(ordinary)");
is(widget.getCssValue(), "url(ordinary)",
"setCssValue should not quote ordinary unquoted URL contents");
widget.setCssValue("url(invalid\\ \\)\\ \\{\\ when\\ \\}\\ \\;\\ unquoted)");
is(widget.getCssValue(),
"url(invalid\\ \\)\\ \\{\\ when\\ \\}\\ \\;\\ unquoted)",
let quotedurl =
"url(invalid\\ \\)\\ {\\\twhen\\ }\\ ;\\ \\\\unquoted\\'\\\")";
ok(verifyURL(quotedurl), "weird URL is valid");
widget.setCssValue(quotedurl);
is(widget.getCssValue(), quotedurl,
"setCssValue should re-quote weird unquoted URL contents");
let dataurl = "url(data:image/svg+xml;utf8,<svg\\ " +
"xmlns=\\\"http://www.w3.org/2000/svg\\\"><filter\\ id=\\\"blur\\\">" +
"<feGaussianBlur\\ stdDeviation=\\\"3\\\"/></filter></svg>#blur)";
ok(verifyURL(dataurl), "data URL is valid");
widget.setCssValue(dataurl);
is(widget.getCssValue(), dataurl, "setCssValue should not mangle data urls");
});

View File

@ -2,10 +2,12 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the text displayed is the function name, file name and line number
// if applicable.
// if applicable and demangling.
var {FlameGraphUtils} = require("devtools/client/shared/widgets/FlameGraph");
var {PALLETTE_SIZE} = require("devtools/client/shared/widgets/FlameGraph");
var MANGLED_FN = "__Z3FooIiEvv";
var UNMANGLED_FN = "void Foo<int>()";
add_task(function*() {
yield addTab("about:blank");
@ -49,7 +51,7 @@ var TEST_DATA = synthesizeProfileForTest([{
frames: [{
location: "A (http://path/to/file.js:10:5)"
}, {
location: "B (http://path/to/file.js:100:5)"
location: `${MANGLED_FN} (http://path/to/file.js:100:5)`
}],
time: 50,
}]);
@ -76,31 +78,15 @@ var EXPECTED_OUTPUT = [{
blocks: []
}, {
blocks: []
}, {
blocks: []
}, {
blocks: []
}, {
blocks: []
}, {
blocks: []
}, {
blocks: []
}, {
blocks: []
}, {
blocks: []
}, {
blocks: []
}, {
blocks: [{
startTime: 0,
frameKey: "B (http://path/to/file.js:100:5)",
frameKey: `${MANGLED_FN} (http://path/to/file.js:100:5)`,
x: 0,
y: 15,
width: 50,
height: 15,
text: "B (file.js:100)"
text: `${UNMANGLED_FN} (file.js:100)`
}]
}, {
blocks: []
@ -110,4 +96,20 @@ var EXPECTED_OUTPUT = [{
blocks: []
}, {
blocks: []
}, {
blocks: []
}, {
blocks: []
}, {
blocks: []
}, {
blocks: []
}, {
blocks: []
}, {
blocks: []
}, {
blocks: []
}, {
blocks: []
}];

View File

@ -828,7 +828,7 @@ CSSFilterEditorWidget.prototype = {
// Unquoted. This approach might change the original input -- for
// example the original might be over-quoted. But, this is
// correct and probably good enough.
return filter.value.replace(/[ \t(){};]/g, "\\$&");
return filter.value.replace(/[\\ \t()"']/g, "\\$&");
},
removeAt: function(index) {

View File

@ -18,6 +18,8 @@ loader.lazyRequireGetter(this, "CATEGORY_MAPPINGS",
"devtools/client/performance/modules/global", true);
loader.lazyRequireGetter(this, "FrameUtils",
"devtools/client/performance/modules/logic/frame-utils");
loader.lazyRequireGetter(this, "demangle",
"devtools/client/shared/demangle");
loader.lazyRequireGetter(this, "AbstractCanvasGraph",
"devtools/client/shared/widgets/Graphs", true);
@ -1242,7 +1244,7 @@ var FlameGraphUtils = {
*/
_formatLabel: function (key, frame) {
let { functionName, fileName, line } = FrameUtils.parseLocation(key, frame.line);
let label = functionName;
let label = FrameUtils.shouldDemangle(functionName) ? demangle(functionName) : functionName;
if (fileName) {
label += ` (${fileName}${line != null ? (":" + line) : ""})`;

View File

@ -64,12 +64,8 @@ var AnimationPlayerActor = ActorClass({
/**
* @param {AnimationsActor} The main AnimationsActor instance
* @param {AnimationPlayer} The player object returned by getAnimationPlayers
* @param {Number} Temporary work-around used to retrieve duration and
* iteration count from computed-style rather than from waapi. This is needed
* to know which duration to get, in case there are multiple css animations
* applied to the same node.
*/
initialize: function(animationsActor, player, playerIndex) {
initialize: function(animationsActor, player) {
Actor.prototype.initialize.call(this, animationsActor.conn);
this.onAnimationMutation = this.onAnimationMutation.bind(this);
@ -77,7 +73,6 @@ var AnimationPlayerActor = ActorClass({
this.tabActor = animationsActor.tabActor;
this.player = player;
this.node = player.effect.target;
this.playerIndex = playerIndex;
let win = this.node.ownerDocument.defaultView;
this.styles = win.getComputedStyle(this.node);
@ -133,42 +128,6 @@ var AnimationPlayerActor = ActorClass({
return ANIMATION_TYPES.UNKNOWN;
},
/**
* Some of the player's properties are retrieved from the node's
* computed-styles because the Web Animations API does not provide them yet.
* But the computed-styles may contain multiple animations for a node and so
* we need to know which is the index of the current animation in the style.
* @return {Number}
*/
getPlayerIndex: function() {
let names = this.styles.animationName;
if (names === "none") {
names = this.styles.transitionProperty;
}
// If we still don't have a name, let's fall back to the provided index
// which may, by now, be wrong, but it's the best we can do until the waapi
// gives us a way to get duration, delay, ... directly.
if (!names || names === "none") {
return this.playerIndex;
}
// If there's only one name.
if (names.includes(",") === -1) {
return 0;
}
// If there are several names, retrieve the index of the animation name in
// the list.
let playerName = this.getName();
names = names.split(",").map(n => n.trim());
for (let i = 0; i < names.length; i++) {
if (names[i] === playerName) {
return i;
}
}
},
/**
* Get the name associated with the player. This is used to match
* up the player with values in the computed animation-name or
@ -187,72 +146,29 @@ var AnimationPlayerActor = ActorClass({
/**
* Get the animation duration from this player, in milliseconds.
* Note that the Web Animations API doesn't yet offer a way to retrieve this
* directly from the AnimationPlayer object, so for now, a duration is only
* returned if found in the node's computed styles.
* @return {Number}
*/
getDuration: function() {
let durationText;
if (this.styles.animationDuration !== "0s") {
durationText = this.styles.animationDuration;
} else if (this.styles.transitionDuration !== "0s") {
durationText = this.styles.transitionDuration;
} else {
return null;
}
// If the computed duration has multiple entries, we need to find the right
// one.
if (durationText.indexOf(",") !== -1) {
durationText = durationText.split(",")[this.getPlayerIndex()];
}
return parseFloat(durationText) * 1000;
return this.player.effect.getComputedTiming().duration;
},
/**
* Get the animation delay from this player, in milliseconds.
* Note that the Web Animations API doesn't yet offer a way to retrieve this
* directly from the AnimationPlayer object, so for now, a delay is only
* returned if found in the node's computed styles.
* @return {Number}
*/
getDelay: function() {
let delayText;
if (this.styles.animationDelay !== "0s") {
delayText = this.styles.animationDelay;
} else if (this.styles.transitionDelay !== "0s") {
delayText = this.styles.transitionDelay;
} else {
return 0;
}
if (delayText.indexOf(",") !== -1) {
delayText = delayText.split(",")[this.getPlayerIndex()];
}
return parseFloat(delayText) * 1000;
return this.player.effect.getComputedTiming().delay;
},
/**
* Get the animation iteration count for this player. That is, how many times
* is the animation scheduled to run.
* Note that the Web Animations API doesn't yet offer a way to retrieve this
* directly from the AnimationPlayer object, so for now, check for
* animationIterationCount in the node's computed styles, and return that.
* This style property defaults to 1 anyway.
* @return {Number}
* @return {Number} The number of iterations, or null if the animation repeats
* infinitely.
*/
getIterationCount: function() {
let iterationText = this.styles.animationIterationCount;
if (iterationText.indexOf(",") !== -1) {
iterationText = iterationText.split(",")[this.getPlayerIndex()];
}
return iterationText === "infinite"
? null
: parseInt(iterationText, 10);
let iterations = this.player.effect.getComputedTiming().iterations;
return iterations === "Infinity" ? null : iterations;
},
/**
@ -606,9 +522,7 @@ var AnimationsActor = exports.AnimationsActor = ActorClass({
// is assumed that the client is responsible for lifetimes of actors.
this.actors = [];
for (let i = 0; i < animations.length; i++) {
// XXX: for now the index is passed along as the AnimationPlayerActor uses
// it to retrieve animation information from CSS.
let actor = AnimationPlayerActor(this, animations[i], i);
let actor = AnimationPlayerActor(this, animations[i]);
this.actors.push(actor);
}
@ -686,8 +600,7 @@ var AnimationsActor = exports.AnimationsActor = ActorClass({
this.actors.splice(index, 1);
}
let actor = AnimationPlayerActor(
this, player, player.effect.target.getAnimations().indexOf(player));
let actor = AnimationPlayerActor(this, player);
this.actors.push(actor);
eventData.push({
type: "added",

View File

@ -2149,7 +2149,7 @@ var WalkerActor = protocol.ActorClass({
nodes = this._multiFrameQuerySelectorAll(query);
}
for (let node of nodes) {
for (let className of node.className.split(" ")) {
for (let className of node.classList) {
sugs.classes.set(className, (sugs.classes.get(className)|0) + 1);
}
}
@ -2218,7 +2218,7 @@ var WalkerActor = protocol.ActorClass({
sugs.ids.set(node.id, (sugs.ids.get(node.id)|0) + 1);
let tag = node.tagName.toLowerCase();
sugs.tags.set(tag, (sugs.tags.get(tag)|0) + 1);
for (let className of node.className.split(" ")) {
for (let className of node.classList) {
sugs.classes.set(className, (sugs.classes.get(className)|0) + 1);
}
}

View File

@ -699,7 +699,10 @@ public class BrowserApp extends GeckoApp
mAccountsHelper = new AccountsHelper(appContext, getProfile());
if (AppConstants.MOZ_INSTALL_TRACKING) {
AdjustConstants.getAdjustHelper().onCreate(this, AdjustConstants.MOZ_INSTALL_TRACKING_ADJUST_SDK_APP_TOKEN);
final SharedPreferences prefs = GeckoSharedPrefs.forApp(this);
if (prefs.getBoolean(GeckoPreferences.PREFS_HEALTHREPORT_UPLOAD_ENABLED, true)) {
AdjustConstants.getAdjustHelper().onCreate(this, AdjustConstants.MOZ_INSTALL_TRACKING_ADJUST_SDK_APP_TOKEN);
}
}
if (AppConstants.MOZ_ANDROID_BEAM) {
@ -900,9 +903,6 @@ public class BrowserApp extends GeckoApp
public void onResume() {
super.onResume();
// Needed for Adjust to get accurate session measurements
AdjustConstants.getAdjustHelper().onResume(this);
final String args = ContextUtils.getStringExtra(getIntent(), "args");
// If an external intent tries to start Fennec in guest mode, and it's not already
// in guest mode, this will change modes before opening the url.
@ -925,10 +925,6 @@ public class BrowserApp extends GeckoApp
@Override
public void onPause() {
super.onPause();
// Needed for Adjust to get accurate session measurements
AdjustConstants.getAdjustHelper().onPause(this);
// Register for Prompt:ShowTop so we can foreground this activity even if it's hidden.
EventDispatcher.getInstance().registerGeckoThreadListener((GeckoEventListener) this,
"Prompt:ShowTop");

View File

@ -5,12 +5,8 @@
package org.mozilla.gecko.adjust;
import org.mozilla.gecko.GeckoSharedPrefs;
import org.mozilla.gecko.preferences.GeckoPreferences;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import com.adjust.sdk.Adjust;
import com.adjust.sdk.AdjustConfig;
@ -19,10 +15,6 @@ import com.adjust.sdk.LogLevel;
public class AdjustHelper implements AdjustHelperInterface {
public void onCreate(final Context context, final String maybeAppToken) {
if (isUserOptOut(context)) {
return;
}
final String environment;
final String appToken;
final LogLevel logLevel;
@ -41,31 +33,6 @@ public class AdjustHelper implements AdjustHelperInterface {
}
public void onReceive(final Context context, final Intent intent) {
if (isUserOptOut(context)) {
return;
}
new AdjustReferrerReceiver().onReceive(context, intent);
}
public void onResume(final Context context) {
if (isUserOptOut(context)) {
return;
}
Adjust.onResume();
}
public void onPause(final Context context) {
if (isUserOptOut(context)) {
return;
}
Adjust.onPause();
}
private boolean isUserOptOut(final Context context) {
final SharedPreferences prefs = GeckoSharedPrefs.forApp(context);
return !prefs.getBoolean(GeckoPreferences.PREFS_HEALTHREPORT_UPLOAD_ENABLED, true);
}
}

View File

@ -15,6 +15,4 @@ public interface AdjustHelperInterface {
*/
void onCreate(final Context context, final String appToken);
void onReceive(final Context context, final Intent intent);
void onResume(final Context context);
void onPause(final Context context);
}

View File

@ -16,12 +16,4 @@ public class StubAdjustHelper implements AdjustHelperInterface {
public void onReceive(final Context context, final Intent intent) {
// Do nothing.
}
public void onResume(final Context context) {
// Do nothing.
}
public void onPause(final Context context) {
// Do nothing.
}
}

View File

@ -119,7 +119,6 @@ OnSharedPreferenceChangeListener
private static final String PREFS_CRASHREPORTER_ENABLED = "datareporting.crashreporter.submitEnabled";
private static final String PREFS_MENU_CHAR_ENCODING = "browser.menu.showCharacterEncoding";
private static final String PREFS_MP_ENABLED = "privacy.masterpassword.enabled";
private static final String PREFS_ZOOMED_VIEW_ENABLED = "ui.zoomedview.enabled";
private static final String PREFS_UPDATER_AUTODOWNLOAD = "app.update.autodownload";
private static final String PREFS_UPDATER_URL = "app.update.url.android";
private static final String PREFS_GEO_REPORTING = NON_PREF_PREFIX + "app.geo.reportdata";

View File

@ -31,13 +31,14 @@ constants_jar.extra_jars = [
CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
CONFIG['ANDROID_SUPPORT_V4_AAR_LIB'],
CONFIG['ANDROID_SUPPORT_V4_AAR_INTERNAL_LIB'],
CONFIG['ANDROID_APPCOMPAT_V7_AAR_LIB'],
]
if CONFIG['MOZ_INSTALL_TRACKING']:
constants_jar.sources += ['java/org/mozilla/gecko/' + x for x in [
'adjust/AdjustHelper.java',
]]
constants_jar.extra_jars = [
constants_jar.extra_jars += [
'gecko-thirdparty-adjust_sdk.jar',
]
else:

View File

@ -65,7 +65,12 @@ stumbler_jars_dir := $(DEPTH)/mobile/android/stumbler
ANDROID_CLASSPATH_JARS += \
$(wildcard $(jars_dir)/*.jar) \
$(wildcard $(stumbler_jars_dir)/*.jar) \
$(NULL)
# We don't have transitive dependencies: these are the browser jar
# dependencies inserted manually.
ANDROID_CLASSPATH_JARS += \
$(ANDROID_SUPPORT_V4_AAR_LIB) \
$(ANDROID_SUPPORT_V4_AAR_INTERNAL_LIB) \
$(ANDROID_RECYCLERVIEW_V7_AAR_LIB) \
$(ANDROID_APPCOMPAT_V7_AAR_LIB) \
$(NULL)

View File

@ -343,6 +343,11 @@ int main(int argc, char **argv) {
#if (defined(XP_WIN) || defined(XP_MACOSX)) && !defined(MAR_NSS)
rv = mar_read_entire_file(DERFilePaths[k], MAR_MAX_CERT_SIZE,
&certBuffers[k], &fileSizes[k]);
if (rv) {
fprintf(stderr, "ERROR: could not read file %s", DERFilePaths[k]);
break;
}
#else
/* It is somewhat circuitous to look up a CERTCertificate and then pass
* in its DER encoding just so we can later re-create that
@ -358,12 +363,10 @@ int main(int argc, char **argv) {
fileSizes[k] = certs[k]->derCert.len;
} else {
rv = -1;
}
#endif
if (rv) {
fprintf(stderr, "ERROR: could not read file %s", DERFilePaths[k]);
fprintf(stderr, "ERROR: could not find cert from nickname %s", certNames[k]);
break;
}
#endif
}
if (!rv) {

View File

@ -16,9 +16,11 @@ var regexes = [
/^loader\.lazyRequireGetter\(\w+, "(\w+)"/,
/^loader\.lazyServiceGetter\(\w+, "(\w+)"/,
/^XPCOMUtils\.defineLazyModuleGetter\(\w+, "(\w+)"/,
/^DevToolsUtils\.defineLazyModuleGetter\(\w+, "(\w+)"/,
/^loader\.lazyGetter\(\w+, "(\w+)"/,
/^XPCOMUtils\.defineLazyGetter\(\w+, "(\w+)"/,
/^XPCOMUtils\.defineLazyServiceGetter\(\w+, "(\w+)"/
/^XPCOMUtils\.defineLazyServiceGetter\(\w+, "(\w+)"/,
/^DevToolsUtils\.defineLazyGetter\(\w+, "(\w+)"/,
];
module.exports = {

View File

@ -4093,6 +4093,14 @@ XREMain::XRE_mainRun()
file->AppendNative(NS_LITERAL_CSTRING("override.ini"));
nsINIParser parser;
nsresult rv = parser.Init(file);
// if override.ini doesn't exist, also check for distribution.ini
if (NS_FAILED(rv)) {
bool persistent;
mDirProvider.GetFile(XRE_APP_DISTRIBUTION_DIR, &persistent,
getter_AddRefs(file));
file->AppendNative(NS_LITERAL_CSTRING("distribution.ini"));
rv = parser.Init(file);
}
if (NS_SUCCEEDED(rv)) {
nsAutoCString buf;
rv = parser.GetString("XRE", "EnableProfileMigrator", buf);