зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to b2g-inbound
This commit is contained in:
Коммит
c4d7176ff2
|
@ -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);
|
||||
let { CustomizableUI } = this.window;
|
||||
let { id } = node;
|
||||
|
||||
let placement = CustomizableUI.getPlacementOfWidget(id);
|
||||
|
||||
if (!placement) {
|
||||
if (haveInserted(node.id)) {
|
||||
if (haveInserted(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;
|
||||
saveInserted(id);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// if widget isn't in any toolbar, add it to the addon-bar
|
||||
let needToPropagateCurrentset = false;
|
||||
if (!container) {
|
||||
if (haveInserted(node.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();
|
||||
}
|
||||
|
||||
// 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/preferences/event-target').PrefsTarget({
|
||||
branchName: "devtools.errorconsole."
|
||||
}).on("deprecation_warnings", function() {
|
||||
if (!getPref(DEPRECATE_PREF, false)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
loader.require('sdk/addon-page');
|
||||
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();
|
||||
done();
|
||||
return undefined;
|
||||
});
|
||||
setPref(DEPRECATE_PREF, false);
|
||||
setPref(DEPRECATE_PREF, true);
|
||||
};
|
||||
|
||||
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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
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");
|
||||
}
|
||||
|
||||
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() {
|
||||
|
||||
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)
|
||||
focus(window).then(nextTest);
|
||||
},
|
||||
function(w) {
|
||||
return focus(window).then(w => {
|
||||
assert.strictEqual(w, window, 'require("sdk/window/helpers").focus on window works');
|
||||
}).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() {
|
||||
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() {
|
||||
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) {
|
||||
|
@ -217,8 +203,8 @@ exports.testWindowIteratorIgnoresPrivateWindows = function(assert, done) {
|
|||
"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">
|
||||
|
|
Двоичные данные
browser/themes/linux/devtools/layout-background-grid.png
Двоичные данные
browser/themes/linux/devtools/layout-background-grid.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 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;
|
||||
}
|
||||
}
|
||||
|
|
Двоичные данные
browser/themes/osx/devtools/layout-background-grid.png
Двоичные данные
browser/themes/osx/devtools/layout-background-grid.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 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);
|
||||
}
|
||||
|
|
Двоичные данные
browser/themes/windows/devtools/layout-background-grid.png
Двоичные данные
browser/themes/windows/devtools/layout-background-grid.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 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));
|
||||
}
|
||||
},
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче