This commit is contained in:
Wes Kocher 2014-03-20 19:47:40 -07:00
Родитель 6bab98e345 97b94e3bc0
Коммит c4d7176ff2
50 изменённых файлов: 307 добавлений и 622 удалений

Просмотреть файл

@ -6,8 +6,7 @@ Before proceeding, please make sure you've installed Python 2.5,
http://python.org/download/
Note that Python 3 is not supported on any platform, and Python 2.7.6
is not supported on Windows.
Note that Python 3 is not supported.
For Windows users, MozillaBuild (https://wiki.mozilla.org/MozillaBuild)
will install the correct version of Python and the MSYS package, which

Просмотреть файл

@ -4,18 +4,6 @@
"use strict";
const { Cu } = require("chrome");
// Because Firefox Holly, we still need to check if `CustomizableUI` is
// available. Once Australis will officially land, we can safely remove it.
// See Bug 959142
try {
Cu.import("resource:///modules/CustomizableUI.jsm", {});
}
catch (e) {
throw Error("Unsupported Application: The module" + module.id +
" does not support this application.");
}
const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
const { receive } = require("../event/utils");
const { InputPort } = require("./system");

Просмотреть файл

@ -138,6 +138,8 @@ function display(panel, options, anchor) {
// menu panel.
// In such cases clicking this widget will hide the overflow/menu panel,
// and the widget's panel will show instead.
// If `CustomizableUI` is not available, it means the anchor is not in a
// chrome browser window, and therefore there is no need for this check.
if (CustomizableUI) {
let node = anchor;
({anchor}) = CustomizableUI.getWidget(anchor.id).forWindow(window);

Просмотреть файл

@ -10,17 +10,6 @@ module.metadata = {
}
};
// Because Firefox Holly, we still need to check if `CustomizableUI` is
// available. Once Australis will officially land, we can safely remove it.
// See Bug 959142
try {
require('chrome').Cu.import('resource:///modules/CustomizableUI.jsm', {});
}
catch (e) {
throw Error('Unsupported Application: The module ' + module.id +
' does not support this application.');
}
const { Class } = require('../../core/heritage');
const { merge } = require('../../util/object');
const { Disposable } = require('../../core/disposable');

Просмотреть файл

@ -10,17 +10,6 @@ module.metadata = {
}
};
// Because Firefox Holly, we still need to check if `CustomizableUI` is
// available. Once Australis will officially land, we can safely remove it.
// See Bug 959142
try {
require('chrome').Cu.import('resource:///modules/CustomizableUI.jsm', {});
}
catch (e) {
throw Error('Unsupported Application: The module ' + module.id +
' does not support this application.');
}
const { Class } = require('../../core/heritage');
const { merge } = require('../../util/object');
const { Disposable } = require('../../core/disposable');

Просмотреть файл

@ -10,17 +10,6 @@ module.metadata = {
}
};
// Because Firefox Holly, we still need to check if `CustomizableUI` is
// available. Once Australis will officially land, we can safely remove it.
// See Bug 959142
try {
require("chrome").Cu.import("resource:///modules/CustomizableUI.jsm", {});
}
catch (e) {
throw Error("Unsupported Application: The module" + module.id +
" does not support this application.");
}
require("./frame/view");
const { Frame } = require("./frame/model");

Просмотреть файл

@ -10,17 +10,6 @@ module.metadata = {
}
};
// Because Firefox Holly, we still need to check if `CustomizableUI` is
// available. Once Australis will officially land, we can safely remove it.
// See Bug 959142
try {
require("chrome").Cu.import("resource:///modules/CustomizableUI.jsm", {});
}
catch (e) {
throw Error("Unsupported Application: The module" + module.id +
" does not support this application.");
}
const { Toolbar } = require("./toolbar/model");
require("./toolbar/view");

Просмотреть файл

@ -620,76 +620,21 @@ BrowserWindow.prototype = {
let palette = toolbox.palette;
palette.appendChild(node);
if (this.window.CustomizableUI) {
let placement = this.window.CustomizableUI.getPlacementOfWidget(node.id);
if (!placement) {
if (haveInserted(node.id)) {
return;
}
placement = {area: 'nav-bar', position: undefined};
saveInserted(node.id);
}
this.window.CustomizableUI.addWidgetToArea(node.id, placement.area, placement.position);
this.window.CustomizableUI.ensureWidgetPlacedInWindow(node.id, this.window);
return;
}
let { CustomizableUI } = this.window;
let { id } = node;
// Search for widget toolbar by reading toolbar's currentset attribute
let container = null;
let toolbars = this.doc.getElementsByTagName("toolbar");
let id = node.getAttribute("id");
for (let i = 0, l = toolbars.length; i < l; i++) {
let toolbar = toolbars[i];
if (toolbar.getAttribute("currentset").indexOf(id) == -1)
continue;
container = toolbar;
}
let placement = CustomizableUI.getPlacementOfWidget(id);
// if widget isn't in any toolbar, add it to the addon-bar
let needToPropagateCurrentset = false;
if (!container) {
if (haveInserted(node.id)) {
if (!placement) {
if (haveInserted(id))
return;
}
container = this.doc.getElementById("addon-bar");
saveInserted(node.id);
needToPropagateCurrentset = true;
// TODO: find a way to make the following code work when we use "cfx run":
// http://mxr.mozilla.org/mozilla-central/source/browser/base/content/browser.js#8586
// until then, force display of addon bar directly from sdk code
// https://bugzilla.mozilla.org/show_bug.cgi?id=627484
if (container.collapsed)
this.window.toggleAddonBar();
placement = {area: 'nav-bar', position: undefined};
saveInserted(id);
}
// Now retrieve a reference to the next toolbar item
// by reading currentset attribute on the toolbar
let nextNode = null;
let currentSet = container.getAttribute("currentset");
let ids = (currentSet == "__empty") ? [] : currentSet.split(",");
let idx = ids.indexOf(id);
if (idx != -1) {
for (let i = idx; i < ids.length; i++) {
nextNode = this.doc.getElementById(ids[i]);
if (nextNode)
break;
}
}
// Finally insert our widget in the right toolbar and in the right position
container.insertItem(id, nextNode, null, false);
// Update DOM in order to save position: which toolbar, and which position
// in this toolbar. But only do this the first time we add it to the toolbar
// Otherwise, this code will collide with other instance of Widget module
// during Firefox startup. See bug 685929.
if (ids.indexOf(id) == -1) {
let set = container.currentSet;
container.setAttribute("currentset", set);
// Save DOM attribute in order to save position on new window opened
this.window.document.persist(container.id, "currentset");
browserManager.propagateCurrentset(container.id, set);
}
CustomizableUI.addWidgetToArea(id, placement.area, placement.position);
CustomizableUI.ensureWidgetPlacedInWindow(id, this.window);
}
}
@ -756,9 +701,8 @@ WidgetChrome.prototype._createNode = function WC__createNode() {
// For use in styling by the browser
node.setAttribute("sdkstylewidget", "true");
// Mark wide widgets as such:
if (this.window.CustomizableUI &&
this._widget.width > AUSTRALIS_PANEL_WIDE_WIDGET_CUTOFF) {
if (this._widget.width > AUSTRALIS_PANEL_WIDE_WIDGET_CUTOFF) {
node.classList.add("panel-wide-item");
}

Просмотреть файл

@ -224,17 +224,11 @@ const Sandbox = iced(function Sandbox(options) {
wantGlobalProperties: 'wantGlobalProperties' in options ?
options.wantGlobalProperties : [],
sandboxPrototype: 'prototype' in options ? options.prototype : {},
sameGroupAs: 'sandbox' in options ? options.sandbox : null,
invisibleToDebugger: 'invisibleToDebugger' in options ?
options.invisibleToDebugger : false,
metadata: 'metadata' in options ? options.metadata : {}
};
// Make `options.sameGroupAs` only if `sandbox` property is passed,
// otherwise `Cu.Sandbox` will throw.
if (!options.sameGroupAs)
delete options.sameGroupAs;
let sandbox = Cu.Sandbox(options.principal, options);
// Each sandbox at creation gets set of own properties that will be shadowing
@ -291,9 +285,6 @@ const load = iced(function load(loader, module) {
let sandbox = sandboxes[module.uri] = Sandbox({
name: module.uri,
// Get an existing module sandbox, if any, so we can reuse its compartment
// when creating the new one to reduce memory consumption.
sandbox: sandboxes[keys(sandboxes).shift()],
prototype: create(globals, descriptors),
wantXrays: false,
wantGlobalProperties: module.id == "sdk/indexed-db" ? ["indexedDB"] : [],

Просмотреть файл

@ -11,7 +11,8 @@ const { setTimeout } = require('sdk/timers');
const app = require("sdk/system/xul-app");
const tabs = require('sdk/tabs');
const isAustralis = "gCustomizeMode" in windows.activeBrowserWindow;
const { set: setPref } = require("sdk/preferences/service");
const { set: setPref, get: getPref } = require("sdk/preferences/service");
const { PrefsTarget } = require("sdk/preferences/event-target");
const { defer } = require('sdk/core/promise');
const DEPRECATE_PREF = "devtools.errorconsole.deprecation_warnings";
@ -42,20 +43,31 @@ function isChromeVisible(window) {
// module.metadata.engines
if (app.is('Firefox')) {
exports['test add-on page deprecation message'] = function(assert) {
exports['test add-on page deprecation message'] = function(assert, done) {
let { loader, messages } = LoaderWithHookedConsole(module);
loader.require('sdk/addon-page');
loader.require('sdk/preferences/event-target').PrefsTarget({
branchName: "devtools.errorconsole."
}).on("deprecation_warnings", function() {
if (!getPref(DEPRECATE_PREF, false)) {
return undefined;
}
loader.require('sdk/addon-page');
assert.equal(messages.length, 1, "only one error is dispatched");
assert.equal(messages[0].type, "error", "the console message is an error");
let msg = messages[0].msg;
assert.ok(msg.indexOf("DEPRECATED") === 0,
"The message is deprecation message");
loader.unload();
done();
return undefined;
});
setPref(DEPRECATE_PREF, false);
setPref(DEPRECATE_PREF, true);
assert.equal(messages.length, 1, "only one error is dispatched");
assert.equal(messages[0].type, "error", "the console message is an error");
let msg = messages[0].msg;
assert.ok(msg.indexOf("DEPRECATED") === 0,
"The message is deprecation message");
loader.unload();
};
exports['test that add-on page has no chrome'] = function(assert, done) {

Просмотреть файл

@ -921,7 +921,6 @@ exports['test unique tab ids'] = function(assert, done) {
var { all, defer } = require('sdk/core/promise');
function openWindow() {
// console.log('in openWindow');
let deferred = defer();
let win = windows.open({
url: "data:text/html;charset=utf-8,<html>foo</html>",

Просмотреть файл

@ -260,8 +260,7 @@ exports["test Object Listener 2"] = createProxyTest("", function (helper) {
let html = '<input id="input" type="text" /><input id="input3" type="checkbox" />' +
'<input id="input2" type="checkbox" />';
/* Disable test to keep tree green until Bug 756214 is fixed.
exports.testStringOverload = createProxyTest(html, function (helper, test) {
exports.testStringOverload = createProxyTest(html, function (helper, assert) {
// Proxy - toString error
let originalString = "string";
let p = Proxy.create({
@ -271,10 +270,10 @@ exports.testStringOverload = createProxyTest(html, function (helper, test) {
return originalString[name];
}
});
assert.okRaises(function () {
assert.throws(function () {
p.toString();
},
/String.prototype.toString called on incompatible Proxy/,
/toString method called on incompatible Proxy/,
"toString can't be called with this being the proxy");
assert.equal(p.binded(), "string", "but it works if we bind this to the original string");
@ -296,7 +295,6 @@ exports.testStringOverload = createProxyTest(html, function (helper, test) {
}
);
});
*/
exports["test MozMatchedSelector"] = createProxyTest("", function (helper) {
helper.createWorker(
@ -517,8 +515,6 @@ exports["test Window Frames"] = createProxyTest(html, function (helper) {
let iframe = document.getElementById("iframe");
//assert(window.frames.length == 1, "The iframe is reported in window.frames check1");
//assert(window.frames[0] == iframe.contentWindow, "The iframe is reported in window.frames check2");
//console.log(window.test+ "-"+iframe.contentWindow);
//console.log(window);
assert(window.test == iframe.contentWindow, "window[frameName] is valid");
done();
}

Просмотреть файл

@ -76,7 +76,7 @@ exports["test:communication with worker global scope"] = function(assert, done)
let window = makeWindow();
let contentSymbiont;
console.log(window)
assert.ok(!!window, 'there is a window');
function onMessage1(message) {
assert.equal(message, 1, "Program gets message via onMessage.");

Просмотреть файл

@ -543,7 +543,6 @@ exports.testPageReload = function (assert, done) {
label: "item",
contentScript: 'self.postMessage("loaded"); self.on("detach", function () { console.log("saw detach"); self.postMessage("detach") });',
onMessage: function (msg) {
console.log("Saw " + msg)
switch (msg) {
case "loaded":
assert.ok(loadExpected, "Should have seen the load event at the right time");
@ -3490,7 +3489,7 @@ exports.testPredicateContextTargetSrcSet = function (assert, done) {
let test = new TestHelper(assert, done);
let loader = test.newLoader();
let image;
let items = [loader.cm.Item({
label: "item",
context: loader.cm.PredicateContext(function (data) {
@ -3512,7 +3511,7 @@ exports.testPredicateContextTargetSrcSet = function (assert, done) {
exports.testPredicateContextTargetSrcNotSet = function (assert, done) {
let test = new TestHelper(assert, done);
let loader = test.newLoader();
let items = [loader.cm.Item({
label: "item",
context: loader.cm.PredicateContext(function (data) {
@ -3535,7 +3534,7 @@ exports.testPredicateContextTargetLinkSet = function (assert, done) {
let test = new TestHelper(assert, done);
let loader = test.newLoader();
let image;
let items = [loader.cm.Item({
label: "item",
context: loader.cm.PredicateContext(function (data) {
@ -3556,7 +3555,7 @@ exports.testPredicateContextTargetLinkSet = function (assert, done) {
exports.testPredicateContextTargetLinkNotSet = function (assert, done) {
let test = new TestHelper(assert, done);
let loader = test.newLoader();
let items = [loader.cm.Item({
label: "item",
context: loader.cm.PredicateContext(function (data) {
@ -3578,7 +3577,7 @@ exports.testPredicateContextTargetValueSet = function (assert, done) {
let test = new TestHelper(assert, done);
let loader = test.newLoader();
let image;
let items = [loader.cm.Item({
label: "item",
context: loader.cm.PredicateContext(function (data) {
@ -3599,7 +3598,7 @@ exports.testPredicateContextTargetValueSet = function (assert, done) {
exports.testPredicateContextTargetValueNotSet = function (assert, done) {
let test = new TestHelper(assert, done);
let loader = test.newLoader();
let items = [loader.cm.Item({
label: "item",
context: loader.cm.PredicateContext(function (data) {

Просмотреть файл

@ -440,23 +440,24 @@ exports["test debounce"] = (assert, done) => {
exports["test throttle"] = (assert, done) => {
let called = 0;
let attempt = 0;
let throttledFn = throttle(() => called++, 100);
let atleast100ms = false;
let throttledFn = throttle(() => {
called++;
if (called === 2) {
assert.equal(attempt, 10, "called twice, but attempted 10 times");
fn();
}
if (called === 3) {
assert.ok(atleast100ms, "atleast 100ms have passed");
assert.equal(attempt, 11, "called third, waits for delay to happen");
done();
}
}, 200);
let fn = () => ++attempt && throttledFn();
new Array(11).join(0).split("").forEach((_, i) => {
setTimeout(fn, 20 * (i+1));
});
setTimeout(() => atleast100ms = true, 100);
setTimeout(() => {
assert.equal(called, 1, "function called atleast once during first throttle period");
assert.ok(attempt >= 2, "function attempted to be called several times during first period");
}, 50);
setTimeout(() => {
assert.equal(called, 3, "function called again during second throttle period");
assert.equal(attempt, 10, "function attempted to be called several times during second period");
done();
}, 300);
new Array(11).join(0).split("").forEach(fn);
};
require('test').run(exports);

Просмотреть файл

@ -532,7 +532,7 @@ exports.testContentScriptWhenForNewTabs = function(assert, done) {
handleReadyState(url, 'start', {
onLoading: (tab) => {
assert.pass("PageMod is attached while document is loading");
if (++count === 3)
if (++count === 3)
tab.close(done);
},
onInteractive: () => assert.fail("onInteractive should not be called with 'start'."),
@ -542,7 +542,7 @@ exports.testContentScriptWhenForNewTabs = function(assert, done) {
handleReadyState(url, 'ready', {
onInteractive: (tab) => {
assert.pass("PageMod is attached while document is interactive");
if (++count === 3)
if (++count === 3)
tab.close(done);
},
onLoading: () => assert.fail("onLoading should not be called with 'ready'."),
@ -552,7 +552,7 @@ exports.testContentScriptWhenForNewTabs = function(assert, done) {
handleReadyState(url, 'end', {
onComplete: (tab) => {
assert.pass("PageMod is attached when document is complete");
if (++count === 3)
if (++count === 3)
tab.close(done);
},
onLoading: () => assert.fail("onLoading should not be called with 'end'."),
@ -575,7 +575,7 @@ exports.testContentScriptWhenOnTabOpen = function(assert, done) {
handleReadyState(url, 'start', {
onLoading: () => {
assert.pass("PageMod is attached while document is loading");
if (++count === 3)
if (++count === 3)
tab.close(done);
},
onInteractive: () => assert.fail("onInteractive should not be called with 'start'."),
@ -585,7 +585,7 @@ exports.testContentScriptWhenOnTabOpen = function(assert, done) {
handleReadyState(url, 'ready', {
onInteractive: () => {
assert.pass("PageMod is attached while document is interactive");
if (++count === 3)
if (++count === 3)
tab.close(done);
},
onLoading: () => assert.fail("onLoading should not be called with 'ready'."),
@ -595,7 +595,7 @@ exports.testContentScriptWhenOnTabOpen = function(assert, done) {
handleReadyState(url, 'end', {
onComplete: () => {
assert.pass("PageMod is attached when document is complete");
if (++count === 3)
if (++count === 3)
tab.close(done);
},
onLoading: () => assert.fail("onLoading should not be called with 'end'."),
@ -619,7 +619,7 @@ exports.testContentScriptWhenOnTabReady = function(assert, done) {
handleReadyState(url, 'start', {
onInteractive: () => {
assert.pass("PageMod is attached while document is interactive");
if (++count === 3)
if (++count === 3)
tab.close(done);
},
onLoading: () => assert.fail("onLoading should not be called with 'start'."),
@ -629,7 +629,7 @@ exports.testContentScriptWhenOnTabReady = function(assert, done) {
handleReadyState(url, 'ready', {
onInteractive: () => {
assert.pass("PageMod is attached while document is interactive");
if (++count === 3)
if (++count === 3)
tab.close(done);
},
onLoading: () => assert.fail("onLoading should not be called with 'ready'."),
@ -639,7 +639,7 @@ exports.testContentScriptWhenOnTabReady = function(assert, done) {
handleReadyState(url, 'end', {
onComplete: () => {
assert.pass("PageMod is attached when document is complete");
if (++count === 3)
if (++count === 3)
tab.close(done);
},
onLoading: () => assert.fail("onLoading should not be called with 'end'."),
@ -663,7 +663,7 @@ exports.testContentScriptWhenOnTabLoad = function(assert, done) {
handleReadyState(url, 'start', {
onComplete: () => {
assert.pass("PageMod is attached when document is complete");
if (++count === 3)
if (++count === 3)
tab.close(done);
},
onLoading: () => assert.fail("onLoading should not be called with 'start'."),
@ -673,7 +673,7 @@ exports.testContentScriptWhenOnTabLoad = function(assert, done) {
handleReadyState(url, 'ready', {
onComplete: () => {
assert.pass("PageMod is attached when document is complete");
if (++count === 3)
if (++count === 3)
tab.close(done);
},
onLoading: () => assert.fail("onLoading should not be called with 'ready'."),
@ -683,7 +683,7 @@ exports.testContentScriptWhenOnTabLoad = function(assert, done) {
handleReadyState(url, 'end', {
onComplete: () => {
assert.pass("PageMod is attached when document is complete");
if (++count === 3)
if (++count === 3)
tab.close(done);
},
onLoading: () => assert.fail("onLoading should not be called with 'end'."),
@ -764,7 +764,6 @@ exports.testAutomaticDestroy = function(assert, done) {
};
exports.testAttachToTabsOnly = function(assert, done) {
let { PageMod } = require('sdk/page-mod');
let openedTab = null; // Tab opened in openTabWithIframe()
let workerCount = 0;
@ -789,6 +788,7 @@ exports.testAttachToTabsOnly = function(assert, done) {
});
function openHiddenFrame() {
assert.pass('Open iframe in hidden window');
let hiddenFrames = require('sdk/frame/hidden-frame');
let hiddenFrame = hiddenFrames.add(hiddenFrames.HiddenFrame({
onReady: function () {
@ -810,6 +810,7 @@ exports.testAttachToTabsOnly = function(assert, done) {
}
function openToplevelWindow() {
assert.pass('Open toplevel window');
let win = open('data:text/html;charset=utf-8,bar');
win.addEventListener('DOMContentLoaded', function onload() {
win.removeEventListener('DOMContentLoaded', onload, false);
@ -819,6 +820,7 @@ exports.testAttachToTabsOnly = function(assert, done) {
}
function openBrowserIframe() {
assert.pass('Open iframe in browser window');
let window = require('sdk/deprecated/window-utils').activeBrowserWindow;
let document = window.document;
let iframe = document.createElement('iframe');
@ -834,6 +836,7 @@ exports.testAttachToTabsOnly = function(assert, done) {
// Only these three documents will be accepted by the page-mod
function openTabWithIframes() {
assert.pass('Open iframes in a tab');
let subContent = '<iframe src="data:text/html;charset=utf-8,sub frame" />'
let content = '<iframe src="data:text/html;charset=utf-8,' +
encodeURIComponent(subContent) + '" />';
@ -1368,6 +1371,8 @@ exports.testWorkerTabClose = function(assert, done) {
include: "about:",
contentScript: '',
onAttach: function(worker) {
assert.pass("The page-mod was attached");
worker.tab.close(function () {
// On Fennec, tab is completely destroyed right after close event is
// dispatch, so we need to wait for the next event loop cycle to

Просмотреть файл

@ -123,7 +123,6 @@ exports['test the weird objects, that they get parsed properly'] = function(asse
exports['test non munge test cases'] = function(assert) {
qsNoMungeTestCases.forEach(function(testCase) {
//console.log(testCase[0], JSON.stringify(testCase[1]), qs.stringify(testCase[1], '&', '=', false));
assert.deepEqual(testCase[0], qs.stringify(testCase[1], '&', '=', false),
'stringify ' + JSON.stringify(testCase[1]) + ' -> & =');
});

Просмотреть файл

@ -859,19 +859,4 @@ exports['test button after destroy'] = function(assert) {
loader.unload();
};
// If the module doesn't support the app we're being run in, require() will
// throw. In that case, remove all tests above from exports, and add one dummy
// test that passes.
try {
require('sdk/ui/button/action');
}
catch (err) {
if (!/^Unsupported Application/.test(err.message))
throw err;
module.exports = {
'test Unsupported Application': assert => assert.pass(err.message)
}
}
require('sdk/test').run(exports);

Просмотреть файл

@ -1058,19 +1058,4 @@ exports['test buttons can have anchored panels'] = function(assert, done) {
button.click();
}
// If the module doesn't support the app we're being run in, require() will
// throw. In that case, remove all tests above from exports, and add one dummy
// test that passes.
try {
require('sdk/ui/button/toggle');
}
catch (err) {
if (!/^Unsupported Application/.test(err.message))
throw err;
module.exports = {
'test Unsupported Application': assert => assert.pass(err.message)
}
}
require('sdk/test').run(exports);

Просмотреть файл

@ -28,8 +28,6 @@ try {
jetpackID = require("sdk/self").id;
} catch(e) {}
const australis = !!require("sdk/window/utils").getMostRecentBrowserWindow().CustomizableUI;
function openNewWindowTab(url, options) {
return open('chrome://browser/content/browser.xul', {
features: {
@ -49,23 +47,19 @@ exports.testConstructor = function(assert, done) {
let browserWindow = windowUtils.activeBrowserWindow;
let doc = browserWindow.document;
let AddonsMgrListener;
if (australis) {
AddonsMgrListener = {
onInstalling: () => {},
onInstalled: () => {},
onUninstalling: () => {},
onUninstalled: () => {}
};
}
else {
AddonsMgrListener = browserWindow.AddonsMgrListener;
}
function container() australis ? doc.getElementById("nav-bar") : doc.getElementById("addon-bar");
function getWidgets() container() ? container().querySelectorAll('[id^="widget\:"]') : [];
function widgetCount() getWidgets().length;
AddonsMgrListener = {
onInstalling: () => {},
onInstalled: () => {},
onUninstalling: () => {},
onUninstalled: () => {}
};
let container = () => doc.getElementById("nav-bar");
let getWidgets = () => container() ? container().querySelectorAll('[id^="widget\:"]') : [];
let widgetCount = () => getWidgets().length;
let widgetStartCount = widgetCount();
function widgetNode(index) getWidgets()[index];
let widgetNode = (index) => getWidgets()[index];
// Test basic construct/destroy
AddonsMgrListener.onInstalling();
@ -172,38 +166,13 @@ exports.testConstructor = function(assert, done) {
w3.destroy();
AddonsMgrListener.onUninstalled();
// Test concurrent widget module instances on addon-bar hiding
if (!australis) {
let loader = Loader(module);
let anotherWidgetsInstance = loader.require("sdk/widget");
assert.ok(container().collapsed, "UI is hidden when no widgets");
AddonsMgrListener.onInstalling();
let w1 = widgets.Widget({id: "ui-unhide", label: "foo", content: "bar"});
// Ideally we would let AddonsMgrListener display the addon bar
// But, for now, addon bar is immediatly displayed by sdk code
// https://bugzilla.mozilla.org/show_bug.cgi?id=627484
assert.ok(!container().collapsed, "UI is already visible when we just added the widget");
AddonsMgrListener.onInstalled();
assert.ok(!container().collapsed, "UI become visible when we notify AddonsMgrListener about end of addon installation");
let w2 = anotherWidgetsInstance.Widget({id: "ui-stay-open", label: "bar", content: "foo"});
assert.ok(!container().collapsed, "UI still visible when we add a second widget");
AddonsMgrListener.onUninstalling();
w1.destroy();
AddonsMgrListener.onUninstalled();
assert.ok(!container().collapsed, "UI still visible when we remove one of two widgets");
AddonsMgrListener.onUninstalling();
w2.destroy();
assert.ok(!container().collapsed, "UI is still visible when we have removed all widget but still not called onUninstalled");
AddonsMgrListener.onUninstalled();
assert.ok(container().collapsed, "UI is hidden when we have removed all widget and called onUninstalled");
}
// Helper for testing a single widget.
// Confirms proper addition and content setup.
function testSingleWidget(widgetOptions) {
// We have to display which test is being run, because here we do not
// use the regular test framework but rather a custom one that iterates
// the `tests` array.
console.info("executing: " + widgetOptions.id);
assert.pass("executing: " + widgetOptions.id);
let startCount = widgetCount();
let widget = widgets.Widget(widgetOptions);
@ -530,13 +499,13 @@ exports.testConstructor = function(assert, done) {
// test multiple windows
tests.push(function testMultipleWindows() {
console.log('executing test multiple windows');
assert.pass('executing test multiple windows');
openNewWindowTab("about:blank", { inNewWindow: true, onLoad: function(e) {
let browserWindow = e.target.defaultView;
assert.ok(browserWindow, 'window was opened');
let doc = browserWindow.document;
function container() australis ? doc.getElementById("nav-bar") : doc.getElementById("addon-bar");
function widgetCount2() container() ? container().querySelectorAll('[id^="widget\:"]').length : 0;
let container = () => doc.getElementById("nav-bar");
let widgetCount2 = () => container() ? container().querySelectorAll('[id^="widget\:"]').length : 0;
let widgetStartCount2 = widgetCount2();
let w1Opts = {id:"first-multi-window", label: "first widget", content: "first content"};
@ -777,17 +746,7 @@ exports.testPanelWidget3 = function testPanelWidget3(assert, done) {
};
exports.testWidgetWithPanelInMenuPanel = function(assert, done) {
let CustomizableUI;
try {
({CustomizableUI}) = Cu.import("resource:///modules/CustomizableUI.jsm", {});
}
catch (e) {
assert.pass("Test skipped: no CustomizableUI object found.");
done();
return;
}
const { CustomizableUI } = Cu.import("resource:///modules/CustomizableUI.jsm", {});
const widgets = require("sdk/widget");
let widget1 = widgets.Widget({
@ -1141,15 +1100,8 @@ exports.testReinsertion = function(assert, done) {
});
let realWidgetId = "widget:" + jetpackID + "-" + WIDGETID;
// Remove the widget:
if (australis) {
browserWindow.CustomizableUI.removeWidgetFromArea(realWidgetId);
} else {
let widget = browserWindow.document.getElementById(realWidgetId);
let container = widget.parentNode;
container.currentSet = container.currentSet.replace("," + realWidgetId, "");
container.setAttribute("currentset", container.currentSet);
container.ownerDocument.persist(container.id, "currentset");
}
browserWindow.CustomizableUI.removeWidgetFromArea(realWidgetId);
openNewWindowTab("about:blank", { inNewWindow: true, onLoad: function(e) {
assert.equal(e.target.defaultView.document.getElementById(realWidgetId), null);
@ -1157,91 +1109,4 @@ exports.testReinsertion = function(assert, done) {
}});
};
if (!australis) {
exports.testNavigationBarWidgets = function testNavigationBarWidgets(assert, done) {
let w1 = widgets.Widget({id: "1st", label: "1st widget", content: "1"});
let w2 = widgets.Widget({id: "2nd", label: "2nd widget", content: "2"});
let w3 = widgets.Widget({id: "3rd", label: "3rd widget", content: "3"});
// First wait for all 3 widgets to be added to the current browser window
let firstAttachCount = 0;
function onAttachFirstWindow(widget) {
if (++firstAttachCount<3)
return;
onWidgetsReady();
}
w1.once("attach", onAttachFirstWindow);
w2.once("attach", onAttachFirstWindow);
w3.once("attach", onAttachFirstWindow);
function getWidgetNode(toolbar, position) {
return toolbar.getElementsByTagName("toolbaritem")[position];
}
function openBrowserWindow() {
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
let urlString = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
urlString.data = "about:blank";
return ww.openWindow(null, "chrome://browser/content/browser.xul",
"_blank", "chrome,all,dialog=no", urlString);
}
// Then move them before openeing a new browser window
function onWidgetsReady() {
// Hack to move 2nd and 3rd widgets manually to the navigation bar right after
// the search box.
let browserWindow = windowUtils.activeBrowserWindow;
let doc = browserWindow.document;
let addonBar = doc.getElementById("addon-bar");
let w2ToolbarItem = getWidgetNode(addonBar, 1);
let w3ToolbarItem = getWidgetNode(addonBar, 2);
let navBar = doc.getElementById("nav-bar");
let searchBox = doc.getElementById("search-container");
// Insert 3rd at the right of search box by adding it before its right sibling
navBar.insertItem(w3ToolbarItem.id, searchBox.nextSibling, null, false);
// Then insert 2nd before 3rd
navBar.insertItem(w2ToolbarItem.id, w3ToolbarItem, null, false);
// Widget and Firefox codes rely on this `currentset` attribute,
// so ensure it is correctly saved
navBar.setAttribute("currentset", navBar.currentSet);
doc.persist(navBar.id, "currentset");
// Update addonbar too as we removed widget from there.
// Otherwise, widgets may still be added to this toolbar.
addonBar.setAttribute("currentset", addonBar.currentSet);
doc.persist(addonBar.id, "currentset");
// Wait for all widget to be attached to this new window before checking
// their position
let attachCount = 0;
let browserWindow2;
function onAttach(widget) {
if (++attachCount < 3)
return;
let doc = browserWindow2.document;
let addonBar = doc.getElementById("addon-bar");
let searchBox = doc.getElementById("search-container");
// Ensure that 1st is in addon bar
assert.equal(getWidgetNode(addonBar, 0).getAttribute("label"), w1.label);
// And that 2nd and 3rd keep their original positions in navigation bar,
// i.e. right after search box
assert.equal(searchBox.nextSibling.getAttribute("label"), w2.label);
assert.equal(searchBox.nextSibling.nextSibling.getAttribute("label"), w3.label);
w1.destroy();
w2.destroy();
w3.destroy();
close(browserWindow2).then(done);
}
w1.on("attach", onAttach);
w2.on("attach", onAttach);
w3.on("attach", onAttach);
browserWindow2 = openBrowserWindow(browserWindow);
}
};
}
require("sdk/test").run(exports);

Просмотреть файл

@ -18,6 +18,14 @@ const { open, close, focus } = require('sdk/window/helpers');
const WM = Cc['@mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator);
const { isPrivate } = require('sdk/private-browsing');
const { fromIterator: toArray } = require('sdk/util/array');
const { defer } = require('sdk/core/promise');
const { setTimeout } = require('sdk/timers');
function tick() {
let deferred = defer();
setTimeout(deferred.resolve);
return deferred.promise;
}
function makeEmptyBrowserWindow(options) {
options = options || {};
@ -64,31 +72,26 @@ exports.testWindowTrackerIgnoresPrivateWindows = function(assert, done) {
assert.equal(getWindowTitle(window), window.document.title,
'getWindowTitle works');
close(window).then(function() {
makeEmptyBrowserWindow().then(function(window) {
return close(window).then(function() {
return makeEmptyBrowserWindow().then(function(window) {
myNonPrivateWindow = window;
assert.pass('opened new window');
window.close();
return close(window);
});
});
});
}).then(null, assert.fail);
};
// Test setting activeWIndow and onFocus for private windows
exports.testSettingActiveWindowDoesNotIgnorePrivateWindow = function(assert, done) {
let browserWindow = WM.getMostRecentWindow("navigator:browser");
let testSteps;
assert.equal(windowUtils.activeBrowserWindow, browserWindow,
"Browser window is the active browser window.");
assert.ok(!isPrivate(browserWindow), "Browser window is not private.");
// make a new private window
makeEmptyBrowserWindow({
private: true
}).then(focus).then(function(window) {
let continueAfterFocus = function(window) onFocus(window).then(nextTest);
makeEmptyBrowserWindow({ private: true }).then(focus).then(window => {
// PWPB case
if (isWindowPBSupported) {
assert.ok(isPrivate(window), "window is private");
@ -104,59 +107,42 @@ exports.testSettingActiveWindowDoesNotIgnorePrivateWindow = function(assert, don
assert.notStrictEqual(browserWindow, window,
"The window is not the old browser window");
testSteps = [
function() {
// test setting a non private window
continueAfterFocus(windowUtils.activeWindow = browserWindow);
},
function() {
assert.strictEqual(windowUtils.activeWindow, browserWindow,
"Correct active window [1]");
assert.strictEqual(windowUtils.activeBrowserWindow, browserWindow,
"Correct active browser window [1]");
// test focus(window)
focus(window).then(nextTest);
},
function(w) {
return onFocus(windowUtils.activeWindow = browserWindow).then(_ => {
assert.strictEqual(windowUtils.activeWindow, browserWindow,
"Correct active window [1]");
assert.strictEqual(windowUtils.activeBrowserWindow, browserWindow,
"Correct active browser window [1]");
// test focus(window)
return focus(window).then(w => {
assert.strictEqual(w, window, 'require("sdk/window/helpers").focus on window works');
assert.strictEqual(windowUtils.activeBrowserWindow, window,
"Correct active browser window [2]");
assert.strictEqual(windowUtils.activeWindow, window,
"Correct active window [2]");
}).then(tick);
}).then(_ => {
assert.strictEqual(windowUtils.activeBrowserWindow, window,
"Correct active browser window [2]");
assert.strictEqual(windowUtils.activeWindow, window,
"Correct active window [2]");
// test setting a private window
continueAfterFocus(windowUtils.activeWindow = window);
},
function() {
assert.deepEqual(windowUtils.activeBrowserWindow, window,
"Correct active browser window [3]");
assert.deepEqual(windowUtils.activeWindow, window,
"Correct active window [3]");
// test setting a private window
return onFocus(windowUtils.activeWindow = window);
}).then(function() {
assert.deepEqual(windowUtils.activeBrowserWindow, window,
"Correct active browser window [3]");
assert.deepEqual(windowUtils.activeWindow, window,
"Correct active window [3]");
// just to get back to original state
continueAfterFocus(windowUtils.activeWindow = browserWindow);
},
function() {
assert.deepEqual(windowUtils.activeBrowserWindow, browserWindow,
"Correct active browser window when pb mode is supported [4]");
assert.deepEqual(windowUtils.activeWindow, browserWindow,
"Correct active window when pb mode is supported [4]");
// just to get back to original state
return onFocus(windowUtils.activeWindow = browserWindow);
}).then(_ => {
assert.deepEqual(windowUtils.activeBrowserWindow, browserWindow,
"Correct active browser window when pb mode is supported [4]");
assert.deepEqual(windowUtils.activeWindow, browserWindow,
"Correct active window when pb mode is supported [4]");
close(window).then(done);
}
];
function nextTest() {
let args = arguments;
if (testSteps.length) {
require('sdk/timers').setTimeout(function() {
(testSteps.shift()).apply(null, args);
}, 0);
}
}
nextTest();
});
return close(window);
})
}).then(done).then(null, assert.fail);
};
exports.testActiveWindowDoesNotIgnorePrivateWindow = function(assert, done) {
@ -195,8 +181,8 @@ exports.testActiveWindowDoesNotIgnorePrivateWindow = function(assert, done) {
assert.equal(isPrivate(window), false, "window is not private");
}
close(window).then(done);
});
return close(window);
}).then(done).then(null, assert.fail);
}
exports.testWindowIteratorIgnoresPrivateWindows = function(assert, done) {
@ -214,11 +200,11 @@ exports.testWindowIteratorIgnoresPrivateWindows = function(assert, done) {
else {
assert.equal(isWindowPrivate(window), false, "window is not private");
assert.ok(toArray(windowUtils.windowIterator()).indexOf(window) > -1,
"window is in windowIterator()");
"window is in windowIterator()");
}
close(window).then(done);
});
return close(window);
}).then(done).then(null, assert.fail);
};
require("test").run(exports);
require("sdk/test").run(exports);

Просмотреть файл

@ -388,12 +388,14 @@ let LightweightThemeListener = {
});
Services.obs.addObserver(this, "lightweight-theme-styling-update", false);
Services.obs.addObserver(this, "lightweight-theme-optimized", false);
if (document.documentElement.hasAttribute("lwtheme"))
this.updateStyleSheet(document.documentElement.style.backgroundImage);
},
uninit: function () {
Services.obs.removeObserver(this, "lightweight-theme-styling-update");
Services.obs.removeObserver(this, "lightweight-theme-optimized");
},
/**
@ -433,7 +435,11 @@ let LightweightThemeListener = {
// nsIObserver
observe: function (aSubject, aTopic, aData) {
if (aTopic != "lightweight-theme-styling-update" || !this.styleSheet)
if ((aTopic != "lightweight-theme-styling-update" && aTopic != "lightweight-theme-optimized") ||
!this.styleSheet)
return;
if (aTopic == "lightweight-theme-optimized" && aSubject != window)
return;
let themeData = JSON.parse(aData);

Просмотреть файл

@ -922,6 +922,12 @@
oncommand="window.minimize();"/>
<toolbarbutton id="restore-button"
#ifdef XP_MACOSX
# Prior to 10.7 there wasn't a native fullscreen button so we use #restore-button
# to exit fullscreen and want it to behave like other toolbar buttons.
class="toolbarbutton-1"
cui-areatype="toolbar"
#endif
tooltiptext="&fullScreenRestore.tooltip;"
oncommand="BrowserFullScreen();"/>

Просмотреть файл

@ -11,7 +11,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "FormHistory",
XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
"resource://gre/modules/Downloads.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/commonjs/sdk/core/promise.js");
"resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",

Просмотреть файл

@ -120,7 +120,9 @@ var gSanitizePromptDialog = {
this.bundleBrowser.getString("sanitizeButtonClearing"));
docElt.getButton("cancel").disabled = true;
try {
s.sanitize().then(window.close, window.close);
s.sanitize().then(null, Components.utils.reportError)
.then(() => window.close())
.then(null, Components.utils.reportError);
} catch (er) {
Components.utils.reportError("Exception during sanitize: " + er);
return true; // We *do* want to close immediately on error.

Просмотреть файл

@ -3,7 +3,7 @@
*/
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/commonjs/sdk/core/promise.js");
"resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");

Просмотреть файл

@ -3,7 +3,7 @@
*/
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/commonjs/sdk/core/promise.js");
"resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AboutHomeUtils",

Просмотреть файл

@ -139,7 +139,8 @@ var gAllTests = [
this.selectDuration(Sanitizer.TIMESPAN_HOUR);
this.checkPrefCheckbox("history", true);
this.acceptDialog();
};
wh.onunload = function () {
intPrefIs("sanitize.timeSpan", Sanitizer.TIMESPAN_HOUR,
"timeSpan pref should be hour after accepting dialog with " +
"hour selected");
@ -149,8 +150,7 @@ var gAllTests = [
boolPrefIs("cpd.downloads", true,
"downloads pref should be true after accepting dialog with " +
"history checkbox checked");
};
wh.onunload = function () {
// History visits and downloads within one hour should be cleared.
yield promiseHistoryClearedState(uris, true);
yield ensureDownloadsClearedState(downloadIDs, true);
@ -224,7 +224,8 @@ var gAllTests = [
this.checkPrefCheckbox("history", false);
this.checkPrefCheckbox("formdata", true);
this.acceptDialog();
};
wh.onunload = function () {
intPrefIs("sanitize.timeSpan", Sanitizer.TIMESPAN_HOUR,
"timeSpan pref should be hour after accepting dialog with " +
"hour selected");
@ -234,8 +235,7 @@ var gAllTests = [
boolPrefIs("cpd.downloads", false,
"downloads pref should be false after accepting dialog with " +
"history checkbox unchecked");
};
wh.onunload = function () {
// Of the three only form entries should be cleared.
yield promiseHistoryClearedState(uris, false);
yield ensureDownloadsClearedState(downloadIDs, false);
@ -288,12 +288,12 @@ var gAllTests = [
this.checkDetails(true);
this.acceptDialog();
};
wh.onunload = function () {
intPrefIs("sanitize.timeSpan", Sanitizer.TIMESPAN_EVERYTHING,
"timeSpan pref should be everything after accepting dialog " +
"with everything selected");
};
wh.onunload = function () {
yield promiseHistoryClearedState(uris, true);
};
wh.open();
@ -325,12 +325,12 @@ var gAllTests = [
this.selectDuration(Sanitizer.TIMESPAN_EVERYTHING);
this.checkPrefCheckbox("history", true);
this.acceptDialog();
};
wh.onunload = function () {
intPrefIs("sanitize.timeSpan", Sanitizer.TIMESPAN_EVERYTHING,
"timeSpan pref should be everything after accepting dialog " +
"with everything selected");
};
wh.onunload = function () {
yield promiseHistoryClearedState(uris, true);
};
wh.open();
@ -582,7 +582,8 @@ var gAllTests = [
this.uncheckAllCheckboxes();
this.checkPrefCheckbox("offlineApps", true);
this.acceptDialog();
};
wh.onunload = function () {
// Check if the cache has been deleted
var size = -1;
var visitor = {
@ -643,7 +644,8 @@ var gAllTests = [
this.uncheckAllCheckboxes();
this.checkPrefCheckbox("siteSettings", true);
this.acceptDialog();
};
wh.onunload = function () {
// Check all has been deleted (privileges, data, cache)
var pm = Cc["@mozilla.org/permissionmanager;1"]
.getService(Ci.nsIPermissionManager);

Просмотреть файл

@ -1,7 +1,7 @@
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/commonjs/sdk/core/promise.js");
"resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",

Просмотреть файл

@ -1,7 +1,7 @@
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/commonjs/sdk/core/promise.js");
"resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",

Просмотреть файл

@ -5,7 +5,7 @@
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/commonjs/sdk/core/promise.js");
"resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",

Просмотреть файл

@ -5,7 +5,7 @@
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/commonjs/sdk/core/promise.js");
"resource://gre/modules/Promise.jsm");
// We need to cache this before test runs...
let cachedLeftPaneFolderIdGetter;

Просмотреть файл

@ -30,8 +30,8 @@
<div id="main">
<div id="margins" data-box="margin" tooltip="&margins.tooltip;">
<div id="borders" data-box="border" tooltip="&borders.tooltip;">
<div id="margins" data-box="margin" tooltip="&margin.tooltip;">
<div id="borders" data-box="border" tooltip="&border.tooltip;">
<div id="padding" data-box="padding" tooltip="&padding.tooltip;">
<div id="content" data-box="content" tooltip="&content.tooltip;">
</div>

Просмотреть файл

@ -17,7 +17,7 @@
- the corresponding box is hovered. -->
<!ENTITY title "Box Model">
<!ENTITY margins.tooltip "margins">
<!ENTITY borders.tooltip "borders">
<!ENTITY margin.tooltip "margin">
<!ENTITY border.tooltip "border">
<!ENTITY padding.tooltip "padding">
<!ENTITY content.tooltip "content">

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.1 KiB

Просмотреть файл

@ -1,46 +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/. */
.theme-dark .theme-sidebar {
background-image: url(layout-background-grid.png);
}
.theme-sidebar {
color: hsl(210,53%,45%) !important;
box-sizing: border-box;
}
#main {
background-color: white;
border-color: hsla(210,100%,85%,0.7);
border-style: dotted;
}
#content {
background-color: #80d4ff;
border-color: hsl(210,100%,85%);
border-style: dotted;
}
#padding,
#margins {
border-color: hsla(210,100%,85%,0.2);
outline: dotted 1px hsl(210,100%,85%);
}
#padding {
background-color: #66cc52;
}
#borders {
background-color: #ffe431;
border-style: dotted;
border-color: hsl(210,100%,85%);
box-shadow: 0 0 8px #000;
}
#margins {
background-color: #d89b28;
opacity: 0.6;
}

Просмотреть файл

@ -220,8 +220,7 @@ browser.jar:
skin/classic/browser/devtools/background-noise-toolbar.png (devtools/background-noise-toolbar.png)
skin/classic/browser/devtools/noise.png (devtools/noise.png)
skin/classic/browser/devtools/dropmarker.png (devtools/dropmarker.png)
skin/classic/browser/devtools/layout-background-grid.png (devtools/layout-background-grid.png)
skin/classic/browser/devtools/layoutview.css (devtools/layoutview.css)
skin/classic/browser/devtools/layoutview.css (../shared/devtools/layoutview.css)
skin/classic/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png)
skin/classic/browser/devtools/debugger-expand.png (../shared/devtools/images/debugger-expand.png)
skin/classic/browser/devtools/debugger-pause.png (../shared/devtools/images/debugger-pause.png)

Просмотреть файл

@ -448,8 +448,7 @@ toolbarpaletteitem[place="palette"] > #personal-bookmarks > #bookmarks-toolbar-p
toolbar .toolbarbutton-1:not([type="menu-button"]),
.toolbarbutton-1 > .toolbarbutton-menubutton-button,
.toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker,
#restore-button {
.toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
-moz-box-orient: vertical;
height: 24px;
padding: 0;
@ -458,24 +457,21 @@ toolbar .toolbarbutton-1:not([type="menu-button"]),
toolbar .toolbarbutton-1:not(:-moz-any([type="menu-button"],#back-button,#forward-button)),
toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-button,
toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker,
#restore-button {
toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
border: 1px solid transparent;
border-radius: @toolbarbuttonCornerRadius@;
transition-property: background, border-color;
transition-duration: 250ms;
}
toolbar .toolbarbutton-1:not(:-moz-any([type="menu-button"],#back-button,#forward-button)),
#restore-button {
toolbar .toolbarbutton-1:not(:-moz-any([type="menu-button"],#back-button,#forward-button)) {
padding: 0 4px;
}
toolbar .toolbarbutton-1:not(:-moz-any([type="menu-button"],[disabled],[open],#back-button,#forward-button)):hover,
toolbar .toolbarbutton-1[type="menu-button"]:not([disabled]):-moz-any(:hover,[open]) > .toolbarbutton-menubutton-button,
toolbar .toolbarbutton-1[type="menu-button"]:not([disabled]):-moz-any(:hover,[open]) > .toolbarbutton-menubutton-dropmarker,
toolbar .toolbaritem-combined-buttons:hover > .toolbarbutton-combined,
#restore-button:not([disabled]):hover {
toolbar .toolbaritem-combined-buttons:hover > .toolbarbutton-combined {
border-color: hsla(0,0%,0%,.2);
box-shadow: 0 1px 0 hsla(0,0%,100%,.5),
0 1px 0 hsla(0,0%,100%,.5) inset;
@ -483,16 +479,14 @@ toolbar .toolbaritem-combined-buttons:hover > .toolbarbutton-combined,
toolbar .toolbarbutton-1:not(:-moz-any([type="menu-button"],[disabled],[open],#back-button,#forward-button)):hover,
toolbar .toolbarbutton-1[type="menu-button"]:not(:-moz-any([disabled],[open]))[buttonover] > .toolbarbutton-menubutton-button,
toolbar .toolbarbutton-1[type="menu-button"]:not(:-moz-any([disabled],[open],[buttonover])):hover > .toolbarbutton-menubutton-dropmarker,
#restore-button:not([disabled]):hover {
toolbar .toolbarbutton-1[type="menu-button"]:not(:-moz-any([disabled],[open],[buttonover])):hover > .toolbarbutton-menubutton-dropmarker {
background: hsla(0,0%,100%,.1) linear-gradient(hsla(0,0%,100%,.3), hsla(0,0%,100%,.1)) padding-box;
}
toolbar .toolbarbutton-1:not(:-moz-any([type="menu-button"],[disabled],#back-button,#forward-button)):-moz-any(:hover:active,[open],[checked]),
toolbar .toolbarbutton-1[type="menu-button"]:not(:-moz-any([disabled],[open]))[buttonover]:active > .toolbarbutton-menubutton-button,
toolbar .toolbarbutton-1[type="menu-button"]:not(:-moz-any([disabled],[open],[buttonover])):hover:active > .toolbarbutton-menubutton-dropmarker,
toolbar .toolbarbutton-1[type="menu-button"][open] > .toolbarbutton-menubutton-dropmarker,
#restore-button:not([disabled]):hover:active {
toolbar .toolbarbutton-1[type="menu-button"][open] > .toolbarbutton-menubutton-dropmarker {
background: hsla(0,0%,0%,.02) linear-gradient(hsla(0,0%,0%,.12), hsla(0,0%,0%,0)) border-box;
border-color: hsla(0,0%,0%,.3);
box-shadow: 0 1px 0 hsla(0,0%,100%,.5),
@ -519,8 +513,7 @@ toolbar .toolbarbutton-1[type="menu-button"] {
margin: 0;
}
.toolbarbutton-1,
#restore-button {
.toolbarbutton-1 {
margin: 0 4px;
}
@ -668,6 +661,7 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-ic
-moz-image-region: rect(18px, 414px, 36px, 396px);
}
#restore-button@toolbarButtonPressed@,
#fullscreen-button@toolbarButtonPressed@ {
-moz-image-region: rect(18px, 432px, 36px, 414px);
}
@ -911,10 +905,12 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-ic
-moz-image-region: rect(36px, 828px, 72px, 792px);
}
#restore-button,
#fullscreen-button[cui-areatype="toolbar"] {
-moz-image-region: rect(0, 864px, 36px, 828px);
}
#restore-button:hover:active:not([disabled="true"]),
#fullscreen-button[cui-areatype="toolbar"]:hover:active:not([disabled="true"]) {
-moz-image-region: rect(36px, 864px, 72px, 828px);
}
@ -1229,8 +1225,7 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-ic
}
toolbar .toolbarbutton-1:not([type="menu-button"]),
toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-button,
#restore-button {
toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-button {
min-width: 28px;
}
@ -1246,8 +1241,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
#main-window:not([customizing]) .toolbarbutton-1[disabled="true"] > .toolbarbutton-icon,
#main-window:not([customizing]) .toolbarbutton-1[disabled="true"] > .toolbarbutton-badge-container > .toolbarbutton-icon,
#main-window:not([customizing]) .toolbarbutton-1 > .toolbarbutton-menubutton-button[disabled="true"] > .toolbarbutton-icon,
#restore-button[disabled="true"] > .toolbarbutton-icon {
#main-window:not([customizing]) .toolbarbutton-1 > .toolbarbutton-menubutton-button[disabled="true"] > .toolbarbutton-icon {
opacity: .4;
}
@ -1255,13 +1249,11 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
#main-window:not([customizing]) .toolbarbutton-1[disabled="true"] > .toolbarbutton-icon,
#main-window:not([customizing]) .toolbarbutton-1[disabled="true"] > .toolbarbutton-badge-container > .toolbarbutton-icon,
#main-window:not([customizing]) .toolbarbutton-1 > .toolbarbutton-menubutton-button[disabled="true"] > .toolbarbutton-icon,
#restore-button[disabled="true"] > .toolbarbutton-icon,
#main-window:not([customizing]) .toolbarbutton-1[disabled="true"] > .toolbarbutton-menu-dropmarker,
#main-window:not([customizing]) .toolbarbutton-1[disabled="true"] > .toolbarbutton-menubutton-dropmarker,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-icon,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-text,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-badge-container > .toolbarbutton-icon,
#restore-button:not(:hover):-moz-window-inactive > .toolbarbutton-icon,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-menu-dropmarker,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
@ -1270,8 +1262,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
#main-window:not([customizing]) .toolbarbutton-1:-moz-window-inactive[disabled="true"] > .toolbarbutton-icon,
#main-window:not([customizing]) .toolbarbutton-1:-moz-window-inactive[disabled="true"] > .toolbarbutton-badge-container > .toolbarbutton-icon,
#main-window:not([customizing]) .toolbarbutton-1:-moz-window-inactive > .toolbarbutton-menubutton-button[disabled="true"] > .toolbarbutton-icon,
#restore-button:-moz-window-inactive[disabled="true"] > .toolbarbutton-icon {
#main-window:not([customizing]) .toolbarbutton-1:-moz-window-inactive > .toolbarbutton-menubutton-button[disabled="true"] > .toolbarbutton-icon {
opacity: .25;
}
}

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.1 KiB

Просмотреть файл

@ -1,46 +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/. */
.theme-dark .theme-sidebar {
background-image: url(layout-background-grid.png);
}
.theme-sidebar {
color: hsl(210,53%,45%) !important;
box-sizing: border-box;
}
#main {
background-color: white;
border-color: hsla(210,100%,85%,0.7);
border-style: dotted;
}
#content {
background-color: #80d4ff;
border-color: hsl(210,100%,85%);
border-style: dotted;
}
#padding,
#margins {
border-color: hsla(210,100%,85%,0.2);
outline: dotted 1px hsl(210,100%,85%);
}
#padding {
background-color: #66cc52;
}
#borders {
background-color: #ffe431;
border-style: dotted;
border-color: hsl(210,100%,85%);
box-shadow: 0 0 8px #000;
}
#margins {
background-color: #d89b28;
opacity: 0.6;
}

Просмотреть файл

@ -339,8 +339,7 @@ browser.jar:
skin/classic/browser/devtools/background-noise-toolbar.png (devtools/background-noise-toolbar.png)
skin/classic/browser/devtools/noise.png (devtools/noise.png)
skin/classic/browser/devtools/dropmarker.png (devtools/dropmarker.png)
skin/classic/browser/devtools/layout-background-grid.png (devtools/layout-background-grid.png)
skin/classic/browser/devtools/layoutview.css (devtools/layoutview.css)
skin/classic/browser/devtools/layoutview.css (../shared/devtools/layoutview.css)
skin/classic/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png)
skin/classic/browser/devtools/debugger-expand.png (../shared/devtools/images/debugger-expand.png)
skin/classic/browser/devtools/debugger-pause.png (../shared/devtools/images/debugger-pause.png)

Просмотреть файл

@ -1,5 +1,12 @@
%filter substitution
%define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #cut-button, #copy-button, #paste-button, #fullscreen-button, #zoom-out-button, #zoom-reset-button, #zoom-in-button, #sync-button, #feed-button, #tabview-button, #webrtc-status-button, #social-share-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #switch-to-metro-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button, #email-link-button, #sidebar-button
%ifdef XP_MACOSX
% Prior to 10.7 there wasn't a native fullscreen button so we use #restore-button to exit fullscreen
% and want it to behave like other toolbar buttons.
%define primaryToolbarButtons @primaryToolbarButtons@, #restore-button
%endif
%define inAnyPanel :-moz-any(:not([cui-areatype="toolbar"]), [overflowedItem=true])
%define nestedButtons #zoom-out-button, #zoom-in-button, #cut-button, #copy-button, #paste-button

Просмотреть файл

@ -2,12 +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/. */
.theme-dark .theme-sidebar {
background-image: url(layout-background-grid.png);
}
.theme-sidebar {
color: hsl(210,53%,45%) !important;
box-sizing: border-box;
}
@ -15,6 +10,7 @@
background-color: white;
border-color: hsla(210,100%,85%,0.7);
border-style: dotted;
color: hsl(210,53%,45%);
}
#content {
@ -37,7 +33,6 @@
background-color: #ffe431;
border-style: dotted;
border-color: hsl(210,100%,85%);
box-shadow: 0 0 8px #000;
}
#margins {

Просмотреть файл

@ -88,6 +88,9 @@
-moz-image-region: rect(0, 414px, 18px, 396px);
}
%ifdef XP_MACOSX
#restore-button,
%endif
#fullscreen-button[cui-areatype="toolbar"] {
-moz-image-region: rect(0, 432px, 18px, 414px);
}

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.1 KiB

Просмотреть файл

@ -251,8 +251,7 @@ browser.jar:
skin/classic/browser/devtools/background-noise-toolbar.png (devtools/background-noise-toolbar.png)
skin/classic/browser/devtools/noise.png (devtools/noise.png)
skin/classic/browser/devtools/dropmarker.png (devtools/dropmarker.png)
skin/classic/browser/devtools/layout-background-grid.png (devtools/layout-background-grid.png)
skin/classic/browser/devtools/layoutview.css (devtools/layoutview.css)
skin/classic/browser/devtools/layoutview.css (../shared/devtools/layoutview.css)
skin/classic/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png)
skin/classic/browser/devtools/debugger-expand.png (../shared/devtools/images/debugger-expand.png)
skin/classic/browser/devtools/debugger-pause.png (../shared/devtools/images/debugger-pause.png)
@ -587,8 +586,7 @@ browser.jar:
skin/classic/aero/browser/devtools/background-noise-toolbar.png (devtools/background-noise-toolbar.png)
skin/classic/aero/browser/devtools/noise.png (devtools/noise.png)
skin/classic/aero/browser/devtools/dropmarker.png (devtools/dropmarker.png)
skin/classic/aero/browser/devtools/layout-background-grid.png (devtools/layout-background-grid.png)
skin/classic/aero/browser/devtools/layoutview.css (devtools/layoutview.css)
skin/classic/aero/browser/devtools/layoutview.css (../shared/devtools/layoutview.css)
skin/classic/aero/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png)
skin/classic/aero/browser/devtools/debugger-expand.png (../shared/devtools/images/debugger-expand.png)
skin/classic/aero/browser/devtools/debugger-pause.png (../shared/devtools/images/debugger-pause.png)

Просмотреть файл

@ -20,9 +20,12 @@ public class FxAccountSchedulePolicy implements SchedulePolicy {
// Our poll intervals are used to trigger automatic background syncs
// in the absence of user activity.
// If we're waiting for the user to click on a verification link, we
// sync very often in order to detect a change in state.
//
// We also receive sync requests as a result of network tickles, so
// these intervals are long, with the exception of the rapid polling
// while we wait for verification: if we're waiting for the user to
// click on a verification link, we sync very often in order to detect
// a change in state.
//
// In the case of unverified -> unverified (no transition), this should be
// very close to a single HTTP request (with the SyncAdapter overhead, of
@ -37,24 +40,37 @@ public class FxAccountSchedulePolicy implements SchedulePolicy {
// If we're in some kind of error state, there's no point trying often.
// This is not the same as a server-imposed backoff, which will be
// reflected dynamically.
public static final long POLL_INTERVAL_ERROR_STATE = 24 * 60 * 60; // 24 hours.
public static final long POLL_INTERVAL_ERROR_STATE_SEC = 24 * 60 * 60; // 24 hours.
// If we're the only device, just sync a few times a day in case that
// If we're the only device, just sync once or twice a day in case that
// changes.
public static final long POLL_INTERVAL_SINGLE_DEVICE_SEC = 8 * 60 * 60; // 8 hours.
public static final long POLL_INTERVAL_SINGLE_DEVICE_SEC = 18 * 60 * 60; // 18 hours.
// And if we know there are other devices, let's sync often enough that
// we'll likely be caught up (even if not completely) by the time you
// next use this device.
public static final long POLL_INTERVAL_MULTI_DEVICE_SEC = 30 * 60; // 30 minutes.
// Never sync more frequently than this, unless forced.
public static final long POLL_INTERVAL_MINIMUM_SEC = 45; // 45 seconds.
// we'll be more likely to be caught up (even if not completely) by the
// time you next use this device. This is also achieved via Android's
// network tickles.
public static final long POLL_INTERVAL_MULTI_DEVICE_SEC = 12 * 60 * 60; // 12 hours.
// This is used solely as an optimization for backoff handling, so it's not
// persisted.
private static volatile long POLL_INTERVAL_CURRENT_SEC = POLL_INTERVAL_SINGLE_DEVICE_SEC;
// Never sync more frequently than this, unless forced.
// This is to avoid overly-frequent syncs during active browsing.
public static final long RATE_LIMIT_FUNDAMENTAL_SEC = 90; // 90 seconds.
/**
* We are prompted to sync by several inputs:
* * Periodic syncs that we schedule at long intervals. See the POLL constants.
* * Network-tickle-based syncs that Android starts.
* * Upload-only syncs that are caused by local database writes.
*
* We rate-limit periodic and network-sourced events with this constant.
* We rate limit <b>both</b> with {@link FxAccountSchedulePolicy#RATE_LIMIT_FUNDAMENTAL_SEC}.
*/
public static final long RATE_LIMIT_BACKGROUND_SEC = 60 * 60; // 1 hour.
private final AndroidFxAccount account;
private final Context context;
@ -101,7 +117,7 @@ public class FxAccountSchedulePolicy implements SchedulePolicy {
switch (needed) {
case NeedsPassword:
case NeedsUpgrade:
requestPeriodicSync(POLL_INTERVAL_ERROR_STATE);
requestPeriodicSync(POLL_INTERVAL_ERROR_STATE_SEC);
break;
case NeedsVerification:
requestPeriodicSync(POLL_INTERVAL_PENDING_VERIFICATION);
@ -117,14 +133,14 @@ public class FxAccountSchedulePolicy implements SchedulePolicy {
public void onUpgradeRequired() {
// TODO: this shouldn't occur in FxA, but when we upgrade we
// need to reduce the interval again.
requestPeriodicSync(POLL_INTERVAL_ERROR_STATE);
requestPeriodicSync(POLL_INTERVAL_ERROR_STATE_SEC);
}
@Override
public void onUnauthorized() {
// TODO: this shouldn't occur in FxA, but when we fix our credentials
// we need to reduce the interval again.
requestPeriodicSync(POLL_INTERVAL_ERROR_STATE);
requestPeriodicSync(POLL_INTERVAL_ERROR_STATE_SEC);
}
@Override
@ -147,8 +163,14 @@ public class FxAccountSchedulePolicy implements SchedulePolicy {
}
}
/**
* Accepts two {@link BackoffHandler} instances as input. These are used
* respectively to track fundamental rate limiting, and to separately
* rate-limit periodic and network-tickled syncs.
*/
@Override
public void configureBackoffMillisBeforeSyncing(BackoffHandler backoffHandler) {
backoffHandler.setEarliestNextRequest(delay(POLL_INTERVAL_MINIMUM_SEC * 1000));
public void configureBackoffMillisBeforeSyncing(BackoffHandler fundamentalRateHandler, BackoffHandler backgroundRateHandler) {
fundamentalRateHandler.setEarliestNextRequest(delay(RATE_LIMIT_FUNDAMENTAL_SEC * 1000));
backgroundRateHandler.setEarliestNextRequest(delay(RATE_LIMIT_BACKGROUND_SEC * 1000));
}
}

Просмотреть файл

@ -65,8 +65,9 @@ public class FxAccountSyncAdapter extends AbstractThreadedSyncAdapter {
// Tracks the last seen storage hostname for backoff purposes.
private static final String PREF_BACKOFF_STORAGE_HOST = "backoffStorageHost";
// Used to do cheap in-memory rate limiting.
private static final int MINIMUM_SYNC_DELAY_MILLIS = 5000;
// Used to do cheap in-memory rate limiting. Don't sync again if we
// successfully synced within this duration.
private static final int MINIMUM_SYNC_DELAY_MILLIS = 15 * 1000; // 15 seconds.
private volatile long lastSyncRealtimeMillis = 0L;
protected final ExecutorService executor;
@ -190,6 +191,15 @@ public class FxAccountSyncAdapter extends AbstractThreadedSyncAdapter {
setSyncResultSoftError();
latch.countDown();
}
/**
* Simply don't sync, without setting any error flags.
* This is the appropriate behavior when a routine backoff has not yet
* been met.
*/
public void rejectSync() {
latch.countDown();
}
}
protected static class SessionCallback implements BaseGlobalSessionCallback {
@ -411,6 +421,7 @@ public class FxAccountSyncAdapter extends AbstractThreadedSyncAdapter {
Logger.setThreadLogTag(FxAccountConstants.GLOBAL_LOG_TAG);
Logger.resetLogging();
// This applies even to forced syncs, but only on success.
if (this.lastSyncRealtimeMillis > 0L &&
(this.lastSyncRealtimeMillis + MINIMUM_SYNC_DELAY_MILLIS) > SystemClock.elapsedRealtime()) {
Logger.info(LOG_TAG, "Not syncing FxAccount " + Utils.obfuscateEmail(account.name) +
@ -444,18 +455,34 @@ public class FxAccountSyncAdapter extends AbstractThreadedSyncAdapter {
// This will be the same chunk of SharedPreferences that we pass through to GlobalSession/SyncConfiguration.
final SharedPreferences sharedPrefs = fxAccount.getSyncPrefs();
// Check for a backoff right here.
final BackoffHandler schedulerBackoffHandler = new PrefsBackoffHandler(sharedPrefs, "scheduler");
if (!shouldPerformSync(schedulerBackoffHandler, "scheduler", extras)) {
Logger.info(LOG_TAG, "Not syncing (scheduler).");
syncDelegate.postponeSync(schedulerBackoffHandler.delayMilliseconds());
final BackoffHandler backgroundBackoffHandler = new PrefsBackoffHandler(sharedPrefs, "background");
final BackoffHandler rateLimitBackoffHandler = new PrefsBackoffHandler(sharedPrefs, "rate");
// If this sync was triggered by user action, this will be true.
final boolean isImmediate = (extras != null) &&
(extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, false) ||
extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false));
// If it's not an immediate sync, it must be either periodic or tickled.
// Check our background rate limiter.
if (!isImmediate) {
if (!shouldPerformSync(backgroundBackoffHandler, "background", extras)) {
syncDelegate.rejectSync();
return;
}
}
// Regardless, let's make sure we're not syncing too often.
if (!shouldPerformSync(rateLimitBackoffHandler, "rate", extras)) {
syncDelegate.postponeSync(rateLimitBackoffHandler.delayMilliseconds());
return;
}
final SchedulePolicy schedulePolicy = new FxAccountSchedulePolicy(context, fxAccount);
// Set a small scheduled 'backoff' to rate-limit the next sync.
schedulePolicy.configureBackoffMillisBeforeSyncing(schedulerBackoffHandler);
// Set a small scheduled 'backoff' to rate-limit the next sync,
// and extend the background delay even further into the future.
schedulePolicy.configureBackoffMillisBeforeSyncing(rateLimitBackoffHandler, backgroundBackoffHandler);
final String audience = fxAccount.getAudience();
final String authServerEndpoint = fxAccount.getAccountServerURI();

Просмотреть файл

@ -26,9 +26,10 @@ public interface SchedulePolicy {
* mutated, and additional side-effects (such as scheduling periodic syncs) can
* occur.
*
* @param backoffHandler the backoff handler to configure.
* @param rateHandler the backoff handler to configure for basic rate limiting.
* @param backgroundHandler the backoff handler to configure for background operations.
*/
public abstract void configureBackoffMillisBeforeSyncing(BackoffHandler backoffHandler);
public abstract void configureBackoffMillisBeforeSyncing(BackoffHandler rateHandler, BackoffHandler backgroundHandler);
/**
* We received an explicit backoff instruction, typically from a server.

Просмотреть файл

@ -5,6 +5,7 @@
this.EXPORTED_SYMBOLS = ["LightweightThemeConsumer"];
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeImageOptimizer",
"resource://gre/modules/addons/LightweightThemeImageOptimizer.jsm");
@ -41,7 +42,9 @@ LightweightThemeConsumer.prototype = {
_lastData: null,
_lastScreenWidth: null,
_lastScreenHeight: null,
// Whether the active lightweight theme should be shown on the window.
_enabled: true,
// Whether a lightweight theme is enabled.
_active: false,
enable: function() {
@ -70,7 +73,11 @@ LightweightThemeConsumer.prototype = {
if (this._lastScreenWidth != width || this._lastScreenHeight != height) {
this._lastScreenWidth = width;
this._lastScreenHeight = height;
if (!this._active)
return;
this._update(this._lastData);
Services.obs.notifyObservers(this._win, "lightweight-theme-optimized",
JSON.stringify(this._lastData));
}
},