Merge fx-team to m-c
|
@ -1,7 +1,11 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
/* 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
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Disable tests below for now.
|
||||||
|
// See https://bugzilla.mozilla.org/show_bug.cgi?id=987348
|
||||||
|
/*
|
||||||
var m = require("main");
|
var m = require("main");
|
||||||
var self = require("sdk/self");
|
var self = require("sdk/self");
|
||||||
|
|
||||||
|
@ -22,3 +26,4 @@ exports.testID = function(test) {
|
||||||
test.assertEqual(self.data.url("sample.html"),
|
test.assertEqual(self.data.url("sample.html"),
|
||||||
"resource://reading-data-example-at-jetpack-dot-mozillalabs-dot-com/reading-data/data/sample.html");
|
"resource://reading-data-example-at-jetpack-dot-mozillalabs-dot-com/reading-data/data/sample.html");
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
/* 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
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Disable tests below for now.
|
||||||
|
// See https://bugzilla.mozilla.org/show_bug.cgi?id=987348
|
||||||
|
/*
|
||||||
var m = require("main");
|
var m = require("main");
|
||||||
var self = require("sdk/self");
|
var self = require("sdk/self");
|
||||||
|
|
||||||
|
@ -19,3 +23,4 @@ exports.testMain = function(test) {
|
||||||
exports.testData = function(test) {
|
exports.testData = function(test) {
|
||||||
test.assert(self.data.load("panel.js").length > 0);
|
test.assert(self.data.load("panel.js").length > 0);
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
|
@ -9,66 +9,124 @@ module.metadata = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
let { Class } = require("./heritage");
|
const { Class } = require("./heritage");
|
||||||
let { on, off } = require('../system/events');
|
const { Observer, subscribe, unsubscribe, observe } = require("./observer");
|
||||||
let unloadSubject = require('@loader/unload');
|
const { isWeak, WeakReference } = require("./reference");
|
||||||
|
const method = require("../../method/core");
|
||||||
|
|
||||||
let disposables = WeakMap();
|
const unloadSubject = require('@loader/unload');
|
||||||
|
const addonUnloadTopic = "sdk:loader:destroy";
|
||||||
|
|
||||||
function initialize(instance) {
|
|
||||||
// Create an event handler that will dispose instance on unload.
|
|
||||||
function handler(event) {
|
|
||||||
if (event.subject.wrappedJSObject === unloadSubject) {
|
|
||||||
instance.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Form weak reference between disposable instance and an unload event
|
|
||||||
// handler associated with it. This will make sure that event handler can't
|
|
||||||
// be garbage collected as long as instance is referenced. Also note that
|
|
||||||
// system events intentionally hold weak reference to an event handler, this
|
|
||||||
// will let GC claim both instance and an unload handler before actual add-on
|
|
||||||
// unload if instance contains no other references.
|
|
||||||
disposables.set(instance, handler);
|
|
||||||
on("sdk:loader:destroy", handler);
|
|
||||||
}
|
|
||||||
exports.initialize = initialize;
|
|
||||||
|
|
||||||
function dispose(instance) {
|
const uninstall = method("disposable/uninstall");
|
||||||
// Disposes given instance by removing it from weak map so that handler can
|
exports.uninstall = uninstall;
|
||||||
// be GC-ed even if references to instance are kept. Also unregister unload
|
|
||||||
// handler.
|
|
||||||
|
|
||||||
let handler = disposables.get(instance);
|
|
||||||
if (handler) off("sdk:loader:destroy", handler);
|
const shutdown = method("disposable/shutdown");
|
||||||
disposables.delete(instance);
|
exports.shutdown = shutdown;
|
||||||
}
|
|
||||||
|
const disable = method("disposable/disable");
|
||||||
|
exports.disable = disable;
|
||||||
|
|
||||||
|
const upgrade = method("disposable/upgrade");
|
||||||
|
exports.upgrade = upgrade;
|
||||||
|
|
||||||
|
const downgrade = method("disposable/downgrade");
|
||||||
|
exports.downgrade = downgrade;
|
||||||
|
|
||||||
|
const unload = method("disposable/unload");
|
||||||
|
exports.unload = unload;
|
||||||
|
|
||||||
|
const dispose = method("disposable/dispose");
|
||||||
exports.dispose = dispose;
|
exports.dispose = dispose;
|
||||||
|
dispose.define(Object, object => object.dispose());
|
||||||
|
|
||||||
|
|
||||||
|
const setup = method("disposable/setup");
|
||||||
|
exports.setup = setup;
|
||||||
|
setup.define(Object, (object, ...args) => object.setup(...args));
|
||||||
|
|
||||||
|
|
||||||
|
// Set's up disposable instance.
|
||||||
|
const setupDisposable = disposable => {
|
||||||
|
subscribe(disposable, addonUnloadTopic, isWeak(disposable));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tears down disposable instance.
|
||||||
|
const disposeDisposable = disposable => {
|
||||||
|
unsubscribe(disposable, addonUnloadTopic);
|
||||||
|
};
|
||||||
|
|
||||||
// Base type that takes care of disposing it's instances on add-on unload.
|
// Base type that takes care of disposing it's instances on add-on unload.
|
||||||
// Also makes sure to remove unload listener if it's already being disposed.
|
// Also makes sure to remove unload listener if it's already being disposed.
|
||||||
let Disposable = Class({
|
const Disposable = Class({
|
||||||
initialize: function setupDisposable() {
|
implements: [Observer],
|
||||||
|
initialize: function(...args) {
|
||||||
// First setup instance before initializing it's disposal. If instance
|
// First setup instance before initializing it's disposal. If instance
|
||||||
// fails to initialize then there is no instance to be disposed at the
|
// fails to initialize then there is no instance to be disposed at the
|
||||||
// unload.
|
// unload.
|
||||||
this.setup.apply(this, arguments);
|
setup(this, ...args);
|
||||||
initialize(this);
|
setupDisposable(this);
|
||||||
},
|
},
|
||||||
setup: function setup() {
|
destroy: function(reason) {
|
||||||
// Implement your initialize logic here.
|
|
||||||
},
|
|
||||||
dispose: function dispose() {
|
|
||||||
// Implement your cleanup logic here.
|
|
||||||
},
|
|
||||||
|
|
||||||
destroy: function destroy() {
|
|
||||||
// Destroying disposable removes unload handler so that attempt to dispose
|
// Destroying disposable removes unload handler so that attempt to dispose
|
||||||
// won't be made at unload & delegates to dispose.
|
// won't be made at unload & delegates to dispose.
|
||||||
if (disposables.has(this)) {
|
disposeDisposable(this);
|
||||||
dispose(this);
|
unload(this, reason);
|
||||||
this.dispose();
|
},
|
||||||
}
|
setup: function() {
|
||||||
|
// Implement your initialize logic here.
|
||||||
|
},
|
||||||
|
dispose: function() {
|
||||||
|
// Implement your cleanup logic here.
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
exports.Disposable = Disposable;
|
exports.Disposable = Disposable;
|
||||||
|
|
||||||
|
// Disposable instances observe add-on unload notifications in
|
||||||
|
// order to trigger `unload` on them.
|
||||||
|
observe.define(Disposable, (disposable, subject, topic, data) => {
|
||||||
|
const isUnloadTopic = topic === addonUnloadTopic;
|
||||||
|
const isUnloadSubject = subject.wrappedJSObject === unloadSubject;
|
||||||
|
if (isUnloadTopic && isUnloadSubject) {
|
||||||
|
unsubscribe(disposable, topic);
|
||||||
|
unload(disposable);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const unloaders = {
|
||||||
|
destroy: dispose,
|
||||||
|
uninstall: uninstall,
|
||||||
|
shutdown: shutdown,
|
||||||
|
disable: disable,
|
||||||
|
upgrade: upgrade,
|
||||||
|
downgrade: downgrade
|
||||||
|
}
|
||||||
|
const unloaded = new WeakMap();
|
||||||
|
unload.define(Disposable, (disposable, reason) => {
|
||||||
|
if (!unloaded.get(disposable)) {
|
||||||
|
unloaded.set(disposable, true);
|
||||||
|
// Pick an unload handler associated with an unload
|
||||||
|
// reason (falling back to destroy if not found) and
|
||||||
|
// delegate unloading to it.
|
||||||
|
const unload = unloaders[reason] || unloaders.destroy;
|
||||||
|
unload(disposable);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// If add-on is disabled munally, it's being upgraded, downgraded
|
||||||
|
// or uniststalled `dispose` is invoked to undo any changes that
|
||||||
|
// has being done by it in this session.
|
||||||
|
disable.define(Disposable, dispose);
|
||||||
|
downgrade.define(Disposable, dispose);
|
||||||
|
upgrade.define(Disposable, dispose);
|
||||||
|
uninstall.define(Disposable, dispose);
|
||||||
|
|
||||||
|
// If application is shut down no dispose is invoked as undo-ing
|
||||||
|
// changes made by instance is likely to just waste of resources &
|
||||||
|
// increase shutdown time. Although specefic components may choose
|
||||||
|
// to implement shutdown handler that does something better.
|
||||||
|
shutdown.define(Disposable, disposable => {});
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
module.metadata = {
|
||||||
|
"stability": "experimental"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const { Cc, Ci, Cr } = require("chrome");
|
||||||
|
const { Class } = require("./heritage");
|
||||||
|
const { isWeak } = require("./reference");
|
||||||
|
const method = require("../../method/core");
|
||||||
|
|
||||||
|
const { addObserver, removeObserver } = Cc['@mozilla.org/observer-service;1'].
|
||||||
|
getService(Ci.nsIObserverService);
|
||||||
|
|
||||||
|
|
||||||
|
// This is a method that will be invoked when notification observer
|
||||||
|
// subscribed to occurs.
|
||||||
|
const observe = method("observer/observe");
|
||||||
|
exports.observe = observe;
|
||||||
|
|
||||||
|
// Method to subscribe to the observer notification.
|
||||||
|
const subscribe = method("observe/subscribe");
|
||||||
|
exports.subscribe = subscribe;
|
||||||
|
|
||||||
|
|
||||||
|
// Method to unsubscribe from the observer notifications.
|
||||||
|
const unsubscribe = method("observer/unsubscribe");
|
||||||
|
exports.unsubscribe = unsubscribe;
|
||||||
|
|
||||||
|
|
||||||
|
// This is wrapper class that takes a `delegate` and produces
|
||||||
|
// instance of `nsIObserver` which will delegate to a given
|
||||||
|
// object when observer notification occurs.
|
||||||
|
const ObserverDelegee = Class({
|
||||||
|
initialize: function(delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
},
|
||||||
|
QueryInterface: function(iid) {
|
||||||
|
const isObserver = iid.equals(Ci.nsIObserver);
|
||||||
|
const isWeakReference = iid.equals(Ci.nsISupportsWeakReference);
|
||||||
|
|
||||||
|
if (!isObserver && !isWeakReference)
|
||||||
|
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
observe: function(subject, topic, data) {
|
||||||
|
observe(this.delegate, subject, topic, data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Class that can be either mixed in or inherited from in
|
||||||
|
// order to subscribe / unsubscribe for observer notifications.
|
||||||
|
const Observer = Class({});
|
||||||
|
exports.Observer = Observer;
|
||||||
|
|
||||||
|
// Weak maps that associates instance of `ObserverDelegee` with
|
||||||
|
// an actual observer. It ensures that `ObserverDelegee` instance
|
||||||
|
// won't be GC-ed until given `observer` is.
|
||||||
|
const subscribers = new WeakMap();
|
||||||
|
|
||||||
|
// Implementation of `subscribe` for `Observer` type just registers
|
||||||
|
// observer for an observer service. If `isWeak(observer)` is `true`
|
||||||
|
// observer service won't hold strong reference to a given `observer`.
|
||||||
|
subscribe.define(Observer, (observer, topic) => {
|
||||||
|
if (!subscribers.has(observer)) {
|
||||||
|
const delegee = new ObserverDelegee(observer);
|
||||||
|
subscribers.set(observer, delegee);
|
||||||
|
addObserver(delegee, topic, isWeak(observer));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Unsubscribes `observer` from observer notifications for the
|
||||||
|
// given `topic`.
|
||||||
|
unsubscribe.define(Observer, (observer, topic) => {
|
||||||
|
const delegee = subscribers.get(observer);
|
||||||
|
if (delegee) {
|
||||||
|
subscribers.delete(observer);
|
||||||
|
removeObserver(delegee, topic);
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,29 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
module.metadata = {
|
||||||
|
"stability": "experimental"
|
||||||
|
};
|
||||||
|
|
||||||
|
const method = require("../../method/core");
|
||||||
|
const { Class } = require("./heritage");
|
||||||
|
|
||||||
|
// Object that inherit or mix WeakRefence inn will register
|
||||||
|
// weak observes for system notifications.
|
||||||
|
const WeakReference = Class({});
|
||||||
|
exports.WeakReference = WeakReference;
|
||||||
|
|
||||||
|
|
||||||
|
// If `isWeak(object)` is `true` observer installed
|
||||||
|
// for such `object` will be weak, meaning that it will
|
||||||
|
// be GC-ed if nothing else but observer is observing it.
|
||||||
|
// By default everything except `WeakReference` will return
|
||||||
|
// `false`.
|
||||||
|
const isWeak = method("reference/weak?");
|
||||||
|
exports.isWeak = isWeak;
|
||||||
|
|
||||||
|
isWeak.define(Object, _ => false);
|
||||||
|
isWeak.define(WeakReference, _ => true);
|
|
@ -13,6 +13,7 @@ const { contract } = require('./util/contract');
|
||||||
const { getAttachEventType, WorkerHost } = require('./content/utils');
|
const { getAttachEventType, WorkerHost } = require('./content/utils');
|
||||||
const { Class } = require('./core/heritage');
|
const { Class } = require('./core/heritage');
|
||||||
const { Disposable } = require('./core/disposable');
|
const { Disposable } = require('./core/disposable');
|
||||||
|
const { WeakReference } = require('./core/reference');
|
||||||
const { Worker } = require('./content/worker');
|
const { Worker } = require('./content/worker');
|
||||||
const { EventTarget } = require('./event/target');
|
const { EventTarget } = require('./event/target');
|
||||||
const { on, emit, once, setListeners } = require('./event/core');
|
const { on, emit, once, setListeners } = require('./event/core');
|
||||||
|
@ -97,7 +98,8 @@ const PageMod = Class({
|
||||||
implements: [
|
implements: [
|
||||||
modContract.properties(modelFor),
|
modContract.properties(modelFor),
|
||||||
EventTarget,
|
EventTarget,
|
||||||
Disposable
|
Disposable,
|
||||||
|
WeakReference
|
||||||
],
|
],
|
||||||
extends: WorkerHost(workerFor),
|
extends: WorkerHost(workerFor),
|
||||||
setup: function PageMod(options) {
|
setup: function PageMod(options) {
|
||||||
|
@ -128,7 +130,7 @@ const PageMod = Class({
|
||||||
applyOnExistingDocuments(mod);
|
applyOnExistingDocuments(mod);
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: function destroy() {
|
dispose: function() {
|
||||||
let style = styleFor(this);
|
let style = styleFor(this);
|
||||||
if (style)
|
if (style)
|
||||||
detach(style);
|
detach(style);
|
||||||
|
|
|
@ -13,6 +13,7 @@ const { filter, pipe, map, merge: streamMerge, stripListeners } = require('./eve
|
||||||
const { detach, attach, destroy, WorkerHost } = require('./content/utils');
|
const { detach, attach, destroy, WorkerHost } = require('./content/utils');
|
||||||
const { Worker } = require('./content/worker');
|
const { Worker } = require('./content/worker');
|
||||||
const { Disposable } = require('./core/disposable');
|
const { Disposable } = require('./core/disposable');
|
||||||
|
const { WeakReference } = require('./core/reference');
|
||||||
const { EventTarget } = require('./event/target');
|
const { EventTarget } = require('./event/target');
|
||||||
const { unload } = require('./system/unload');
|
const { unload } = require('./system/unload');
|
||||||
const { events, streamEventsFrom } = require('./content/events');
|
const { events, streamEventsFrom } = require('./content/events');
|
||||||
|
@ -84,7 +85,8 @@ function isValidURL(page, url) !page.rules || page.rules.matchesAny(url)
|
||||||
const Page = Class({
|
const Page = Class({
|
||||||
implements: [
|
implements: [
|
||||||
EventTarget,
|
EventTarget,
|
||||||
Disposable
|
Disposable,
|
||||||
|
WeakReference
|
||||||
],
|
],
|
||||||
extends: WorkerHost(workerFor),
|
extends: WorkerHost(workerFor),
|
||||||
setup: function Page(options) {
|
setup: function Page(options) {
|
||||||
|
|
|
@ -21,6 +21,7 @@ const { merge } = require("./util/object");
|
||||||
const { WorkerHost, detach, attach, destroy } = require("./content/utils");
|
const { WorkerHost, detach, attach, destroy } = require("./content/utils");
|
||||||
const { Worker } = require("./content/worker");
|
const { Worker } = require("./content/worker");
|
||||||
const { Disposable } = require("./core/disposable");
|
const { Disposable } = require("./core/disposable");
|
||||||
|
const { WeakReference } = require('./core/reference');
|
||||||
const { contract: loaderContract } = require("./content/loader");
|
const { contract: loaderContract } = require("./content/loader");
|
||||||
const { contract } = require("./util/contract");
|
const { contract } = require("./util/contract");
|
||||||
const { on, off, emit, setListeners } = require("./event/core");
|
const { on, off, emit, setListeners } = require("./event/core");
|
||||||
|
@ -111,7 +112,8 @@ const Panel = Class({
|
||||||
// set and return values from model on get.
|
// set and return values from model on get.
|
||||||
panelContract.properties(modelFor),
|
panelContract.properties(modelFor),
|
||||||
EventTarget,
|
EventTarget,
|
||||||
Disposable
|
Disposable,
|
||||||
|
WeakReference
|
||||||
],
|
],
|
||||||
extends: WorkerHost(workerFor),
|
extends: WorkerHost(workerFor),
|
||||||
setup: function setup(options) {
|
setup: function setup(options) {
|
||||||
|
@ -197,7 +199,7 @@ const Panel = Class({
|
||||||
|
|
||||||
let model = modelFor(this);
|
let model = modelFor(this);
|
||||||
let view = viewFor(this);
|
let view = viewFor(this);
|
||||||
let anchorView = getNodeView(anchor || options.position);
|
let anchorView = getNodeView(anchor || options.position || model.position);
|
||||||
|
|
||||||
options = merge({
|
options = merge({
|
||||||
position: model.position,
|
position: model.position,
|
||||||
|
|
|
@ -174,10 +174,11 @@ function state(contract) {
|
||||||
state: function state(target, state) {
|
state: function state(target, state) {
|
||||||
let nativeTarget = target === 'window' ? getFocusedBrowser()
|
let nativeTarget = target === 'window' ? getFocusedBrowser()
|
||||||
: target === 'tab' ? getMostRecentTab()
|
: target === 'tab' ? getMostRecentTab()
|
||||||
|
: target === this ? null
|
||||||
: viewFor(target);
|
: viewFor(target);
|
||||||
|
|
||||||
if (!nativeTarget && target !== this && !isNil(target))
|
if (!nativeTarget && target !== this && !isNil(target))
|
||||||
throw new Error('target not allowed.');
|
throw new Error(ERR_INVALID_TARGET);
|
||||||
|
|
||||||
target = nativeTarget || target;
|
target = nativeTarget || target;
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
/* 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
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// The widget module currently supports only Firefox.
|
// The widget module currently supports only Firefox.
|
||||||
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=560716
|
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=560716
|
||||||
module.metadata = {
|
module.metadata = {
|
||||||
"stability": "stable",
|
"stability": "deprecated",
|
||||||
"engines": {
|
"engines": {
|
||||||
"Firefox": "*"
|
"Firefox": "*"
|
||||||
}
|
}
|
||||||
|
@ -39,6 +38,7 @@ const EVENTS = {
|
||||||
// normal toolbarbuttons. If they're any wider than this margin, we'll
|
// normal toolbarbuttons. If they're any wider than this margin, we'll
|
||||||
// treat them as wide widgets instead, which fill up the width of the panel:
|
// treat them as wide widgets instead, which fill up the width of the panel:
|
||||||
const AUSTRALIS_PANEL_WIDE_WIDGET_CUTOFF = 70;
|
const AUSTRALIS_PANEL_WIDE_WIDGET_CUTOFF = 70;
|
||||||
|
const AUSTRALIS_PANEL_WIDE_CLASSNAME = "panel-wide-item";
|
||||||
|
|
||||||
const { validateOptions } = require("./deprecated/api-utils");
|
const { validateOptions } = require("./deprecated/api-utils");
|
||||||
const panels = require("./panel");
|
const panels = require("./panel");
|
||||||
|
@ -55,6 +55,11 @@ const unload = require("./system/unload");
|
||||||
const { getNodeView } = require("./view/core");
|
const { getNodeView } = require("./view/core");
|
||||||
const prefs = require('./preferences/service');
|
const prefs = require('./preferences/service');
|
||||||
|
|
||||||
|
require("./util/deprecate").deprecateUsage(
|
||||||
|
"The widget module is deprecated. " +
|
||||||
|
"Please consider using the sdk/ui module instead."
|
||||||
|
);
|
||||||
|
|
||||||
// Data types definition
|
// Data types definition
|
||||||
const valid = {
|
const valid = {
|
||||||
number: { is: ["null", "undefined", "number"] },
|
number: { is: ["null", "undefined", "number"] },
|
||||||
|
@ -230,6 +235,8 @@ function haveInserted(widgetId) {
|
||||||
return prefs.has(INSERTION_PREF_ROOT + widgetId);
|
return prefs.has(INSERTION_PREF_ROOT + widgetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isWide = node => node.classList.contains(AUSTRALIS_PANEL_WIDE_CLASSNAME);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main Widget class: entry point of the widget API
|
* Main Widget class: entry point of the widget API
|
||||||
*
|
*
|
||||||
|
@ -626,7 +633,7 @@ BrowserWindow.prototype = {
|
||||||
let placement = CustomizableUI.getPlacementOfWidget(id);
|
let placement = CustomizableUI.getPlacementOfWidget(id);
|
||||||
|
|
||||||
if (!placement) {
|
if (!placement) {
|
||||||
if (haveInserted(id))
|
if (haveInserted(id) || isWide(node))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
placement = {area: 'nav-bar', position: undefined};
|
placement = {area: 'nav-bar', position: undefined};
|
||||||
|
@ -703,7 +710,7 @@ WidgetChrome.prototype._createNode = function WC__createNode() {
|
||||||
node.setAttribute("sdkstylewidget", "true");
|
node.setAttribute("sdkstylewidget", "true");
|
||||||
|
|
||||||
if (this._widget.width > AUSTRALIS_PANEL_WIDE_WIDGET_CUTOFF) {
|
if (this._widget.width > AUSTRALIS_PANEL_WIDE_WIDGET_CUTOFF) {
|
||||||
node.classList.add("panel-wide-item");
|
node.classList.add(AUSTRALIS_PANEL_WIDE_CLASSNAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO move into a stylesheet, configurable by consumers.
|
// TODO move into a stylesheet, configurable by consumers.
|
||||||
|
|
|
@ -11,8 +11,8 @@ const app = require("sdk/system/xul-app");
|
||||||
// module.metadata.engines
|
// module.metadata.engines
|
||||||
if (app.is('Firefox')) {
|
if (app.is('Firefox')) {
|
||||||
merge(module.exports,
|
merge(module.exports,
|
||||||
require('./tests/test-places-bookmarks'),
|
|
||||||
require('./tests/test-places-events'),
|
require('./tests/test-places-events'),
|
||||||
|
require('./tests/test-places-bookmarks'),
|
||||||
require('./tests/test-places-favicon'),
|
require('./tests/test-places-favicon'),
|
||||||
require('./tests/test-places-history'),
|
require('./tests/test-places-history'),
|
||||||
require('./tests/test-places-host'),
|
require('./tests/test-places-host'),
|
||||||
|
|
|
@ -18,6 +18,13 @@ const { setTimeout } = require('sdk/timers');
|
||||||
const { before, after } = require('sdk/test/utils');
|
const { before, after } = require('sdk/test/utils');
|
||||||
const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].
|
const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].
|
||||||
getService(Ci.nsINavBookmarksService);
|
getService(Ci.nsINavBookmarksService);
|
||||||
|
const { release, platform } = require('node/os');
|
||||||
|
|
||||||
|
const isOSX10_6 = (() => {
|
||||||
|
let vString = release();
|
||||||
|
return vString && /darwin/.test(platform()) && /10\.6/.test(vString);
|
||||||
|
})();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
search
|
search
|
||||||
} = require('sdk/places/history');
|
} = require('sdk/places/history');
|
||||||
|
@ -51,6 +58,14 @@ exports['test bookmark-item-added'] = function (assert, done) {
|
||||||
exports['test bookmark-item-changed'] = function (assert, done) {
|
exports['test bookmark-item-changed'] = function (assert, done) {
|
||||||
let id;
|
let id;
|
||||||
let complete = makeCompleted(done);
|
let complete = makeCompleted(done);
|
||||||
|
|
||||||
|
// Due to bug 969616 and bug 971964, disabling tests in 10.6 (happens only
|
||||||
|
// in debug builds) to prevent intermittent failures
|
||||||
|
if (isOSX10_6) {
|
||||||
|
assert.ok(true, 'skipping test in OSX 10.6');
|
||||||
|
return done();
|
||||||
|
}
|
||||||
|
|
||||||
function handler ({type, data}) {
|
function handler ({type, data}) {
|
||||||
if (type !== 'bookmark-item-changed') return;
|
if (type !== 'bookmark-item-changed') return;
|
||||||
if (data.id !== id) return;
|
if (data.id !== id) return;
|
||||||
|
@ -87,6 +102,13 @@ exports['test bookmark-item-moved'] = function (assert, done) {
|
||||||
let complete = makeCompleted(done);
|
let complete = makeCompleted(done);
|
||||||
let previousIndex, previousParentId;
|
let previousIndex, previousParentId;
|
||||||
|
|
||||||
|
// Due to bug 969616 and bug 971964, disabling tests in 10.6 (happens only
|
||||||
|
// in debug builds) to prevent intermittent failures
|
||||||
|
if (isOSX10_6) {
|
||||||
|
assert.ok(true, 'skipping test in OSX 10.6');
|
||||||
|
return done();
|
||||||
|
}
|
||||||
|
|
||||||
function handler ({type, data}) {
|
function handler ({type, data}) {
|
||||||
if (type !== 'bookmark-item-moved') return;
|
if (type !== 'bookmark-item-moved') return;
|
||||||
if (data.id !== id) return;
|
if (data.id !== id) return;
|
||||||
|
|
|
@ -5,9 +5,150 @@
|
||||||
|
|
||||||
const { Loader } = require("sdk/test/loader");
|
const { Loader } = require("sdk/test/loader");
|
||||||
const { Class } = require("sdk/core/heritage");
|
const { Class } = require("sdk/core/heritage");
|
||||||
|
const { Disposable } = require("sdk/core/disposable");
|
||||||
const { Cc, Ci, Cu } = require("chrome");
|
const { Cc, Ci, Cu } = require("chrome");
|
||||||
const { setTimeout } = require("sdk/timers");
|
const { setTimeout } = require("sdk/timers");
|
||||||
|
|
||||||
|
exports["test destroy reasons"] = assert => {
|
||||||
|
const Foo = Class({
|
||||||
|
extends: Disposable,
|
||||||
|
dispose: function() {
|
||||||
|
disposals = disposals + 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let disposals = 0;
|
||||||
|
const f1 = new Foo();
|
||||||
|
|
||||||
|
f1.destroy();
|
||||||
|
assert.equal(disposals, 1, "disposed on destroy");
|
||||||
|
f1.destroy();
|
||||||
|
assert.equal(disposals, 1, "second destroy is ignored");
|
||||||
|
|
||||||
|
disposals = 0;
|
||||||
|
const f2 = new Foo();
|
||||||
|
|
||||||
|
f2.destroy("uninstall");
|
||||||
|
assert.equal(disposals, 1, "uninstall invokes disposal");
|
||||||
|
f2.destroy("uninstall")
|
||||||
|
f2.destroy();
|
||||||
|
assert.equal(disposals, 1, "disposal happens just once");
|
||||||
|
|
||||||
|
disposals = 0;
|
||||||
|
const f3 = new Foo();
|
||||||
|
|
||||||
|
f3.destroy("shutdown");
|
||||||
|
assert.equal(disposals, 0, "shutdown doesn't invoke disposal");
|
||||||
|
f3.destroy();
|
||||||
|
assert.equal(disposals, 0, "shutdown already skipped disposal");
|
||||||
|
|
||||||
|
disposals = 0;
|
||||||
|
const f4 = new Foo();
|
||||||
|
|
||||||
|
f4.destroy("disable");
|
||||||
|
assert.equal(disposals, 1, "disable invokes disposal");
|
||||||
|
f4.destroy("disable")
|
||||||
|
f4.destroy();
|
||||||
|
assert.equal(disposals, 1, "destroy happens just once");
|
||||||
|
|
||||||
|
disposals = 0;
|
||||||
|
const f5 = new Foo();
|
||||||
|
|
||||||
|
f5.destroy("disable");
|
||||||
|
assert.equal(disposals, 1, "disable invokes disposal");
|
||||||
|
f5.destroy("disable")
|
||||||
|
f5.destroy();
|
||||||
|
assert.equal(disposals, 1, "destroy happens just once");
|
||||||
|
|
||||||
|
disposals = 0;
|
||||||
|
const f6 = new Foo();
|
||||||
|
|
||||||
|
f6.destroy("upgrade");
|
||||||
|
assert.equal(disposals, 1, "upgrade invokes disposal");
|
||||||
|
f6.destroy("upgrade")
|
||||||
|
f6.destroy();
|
||||||
|
assert.equal(disposals, 1, "destroy happens just once");
|
||||||
|
|
||||||
|
disposals = 0;
|
||||||
|
const f7 = new Foo();
|
||||||
|
|
||||||
|
f7.destroy("downgrade");
|
||||||
|
assert.equal(disposals, 1, "downgrade invokes disposal");
|
||||||
|
f7.destroy("downgrade")
|
||||||
|
f7.destroy();
|
||||||
|
assert.equal(disposals, 1, "destroy happens just once");
|
||||||
|
|
||||||
|
|
||||||
|
disposals = 0;
|
||||||
|
const f8 = new Foo();
|
||||||
|
|
||||||
|
f8.destroy("whatever");
|
||||||
|
assert.equal(disposals, 1, "unrecognized reason invokes disposal");
|
||||||
|
f8.destroy("meh")
|
||||||
|
f8.destroy();
|
||||||
|
assert.equal(disposals, 1, "destroy happens just once");
|
||||||
|
};
|
||||||
|
|
||||||
|
exports["test different unload hooks"] = assert => {
|
||||||
|
const { uninstall, shutdown, disable, upgrade,
|
||||||
|
downgrade, dispose } = require("sdk/core/disposable");
|
||||||
|
const UberUnload = Class({
|
||||||
|
extends: Disposable,
|
||||||
|
setup: function() {
|
||||||
|
this.log = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
uninstall.define(UberUnload, x => x.log.push("uninstall"));
|
||||||
|
shutdown.define(UberUnload, x => x.log.push("shutdown"));
|
||||||
|
disable.define(UberUnload, x => x.log.push("disable"));
|
||||||
|
upgrade.define(UberUnload, x => x.log.push("upgrade"));
|
||||||
|
downgrade.define(UberUnload, x => x.log.push("downgrade"));
|
||||||
|
dispose.define(UberUnload, x => x.log.push("dispose"));
|
||||||
|
|
||||||
|
const u1 = new UberUnload();
|
||||||
|
u1.destroy("uninstall");
|
||||||
|
u1.destroy();
|
||||||
|
u1.destroy("shutdown");
|
||||||
|
assert.deepEqual(u1.log, ["uninstall"], "uninstall hook invoked");
|
||||||
|
|
||||||
|
const u2 = new UberUnload();
|
||||||
|
u2.destroy("shutdown");
|
||||||
|
u2.destroy();
|
||||||
|
u2.destroy("uninstall");
|
||||||
|
assert.deepEqual(u2.log, ["shutdown"], "shutdown hook invoked");
|
||||||
|
|
||||||
|
const u3 = new UberUnload();
|
||||||
|
u3.destroy("disable");
|
||||||
|
u3.destroy();
|
||||||
|
u3.destroy("uninstall");
|
||||||
|
assert.deepEqual(u3.log, ["disable"], "disable hook invoked");
|
||||||
|
|
||||||
|
const u4 = new UberUnload();
|
||||||
|
u4.destroy("upgrade");
|
||||||
|
u4.destroy();
|
||||||
|
u4.destroy("uninstall");
|
||||||
|
assert.deepEqual(u4.log, ["upgrade"], "upgrade hook invoked");
|
||||||
|
|
||||||
|
const u5 = new UberUnload();
|
||||||
|
u5.destroy("downgrade");
|
||||||
|
u5.destroy();
|
||||||
|
u5.destroy("uninstall");
|
||||||
|
assert.deepEqual(u5.log, ["downgrade"], "downgrade hook invoked");
|
||||||
|
|
||||||
|
const u6 = new UberUnload();
|
||||||
|
u6.destroy();
|
||||||
|
u6.destroy();
|
||||||
|
u6.destroy("uninstall");
|
||||||
|
assert.deepEqual(u6.log, ["dispose"], "dispose hook invoked");
|
||||||
|
|
||||||
|
const u7 = new UberUnload();
|
||||||
|
u7.destroy("whatever");
|
||||||
|
u7.destroy();
|
||||||
|
u7.destroy("uninstall");
|
||||||
|
assert.deepEqual(u7.log, ["dispose"], "dispose hook invoked");
|
||||||
|
};
|
||||||
|
|
||||||
exports["test disposables are desposed on unload"] = function(assert) {
|
exports["test disposables are desposed on unload"] = function(assert) {
|
||||||
let loader = Loader(module);
|
let loader = Loader(module);
|
||||||
let { Disposable } = loader.require("sdk/core/disposable");
|
let { Disposable } = loader.require("sdk/core/disposable");
|
||||||
|
@ -84,6 +225,7 @@ exports["test destroyed windows dispose before unload"] = function(assert) {
|
||||||
exports["test disposables are GC-able"] = function(assert, done) {
|
exports["test disposables are GC-able"] = function(assert, done) {
|
||||||
let loader = Loader(module);
|
let loader = Loader(module);
|
||||||
let { Disposable } = loader.require("sdk/core/disposable");
|
let { Disposable } = loader.require("sdk/core/disposable");
|
||||||
|
let { WeakReference } = loader.require("sdk/core/reference");
|
||||||
|
|
||||||
let arg1 = {}
|
let arg1 = {}
|
||||||
let arg2 = 2
|
let arg2 = 2
|
||||||
|
@ -91,6 +233,7 @@ exports["test disposables are GC-able"] = function(assert, done) {
|
||||||
|
|
||||||
let Foo = Class({
|
let Foo = Class({
|
||||||
extends: Disposable,
|
extends: Disposable,
|
||||||
|
implements: [WeakReference],
|
||||||
setup: function setup(a, b) {
|
setup: function setup(a, b) {
|
||||||
assert.equal(a, arg1,
|
assert.equal(a, arg1,
|
||||||
"arguments passed to constructur is passed to setup");
|
"arguments passed to constructur is passed to setup");
|
||||||
|
@ -106,7 +249,7 @@ exports["test disposables are GC-able"] = function(assert, done) {
|
||||||
this.fooed = false
|
this.fooed = false
|
||||||
disposals = disposals + 1
|
disposals = disposals + 1
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
let foo1 = Foo(arg1, arg2)
|
let foo1 = Foo(arg1, arg2)
|
||||||
let foo2 = Foo(arg1, arg2)
|
let foo2 = Foo(arg1, arg2)
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
/* 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/. */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const { Loader } = require("sdk/test/loader");
|
||||||
|
const { isWeak, WeakReference } = require("sdk/core/reference");
|
||||||
|
const { subscribe, unsubscribe,
|
||||||
|
observe, Observer } = require("sdk/core/observer");
|
||||||
|
const { Class } = require("sdk/core/heritage");
|
||||||
|
|
||||||
|
const { Cc, Ci, Cu } = require("chrome");
|
||||||
|
const { notifyObservers } = Cc["@mozilla.org/observer-service;1"].
|
||||||
|
getService(Ci.nsIObserverService);
|
||||||
|
|
||||||
|
const message = x => ({wrappedJSObject: x});
|
||||||
|
|
||||||
|
exports["test subscribe unsubscribe"] = assert => {
|
||||||
|
const topic = Date.now().toString(32);
|
||||||
|
const Subscriber = Class({
|
||||||
|
extends: Observer,
|
||||||
|
initialize: function(observe) {
|
||||||
|
this.observe = observe;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
observe.define(Subscriber, (x, subject, _, data) =>
|
||||||
|
x.observe(subject.wrappedJSObject.x));
|
||||||
|
|
||||||
|
let xs = [];
|
||||||
|
const x = Subscriber((...rest) => xs.push(...rest));
|
||||||
|
|
||||||
|
let ys = [];
|
||||||
|
const y = Subscriber((...rest) => ys.push(...rest));
|
||||||
|
|
||||||
|
const publish = (topic, data) =>
|
||||||
|
notifyObservers(message(data), topic, null);
|
||||||
|
|
||||||
|
publish({x:0});
|
||||||
|
|
||||||
|
subscribe(x, topic);
|
||||||
|
|
||||||
|
publish(topic, {x:1});
|
||||||
|
|
||||||
|
subscribe(y, topic);
|
||||||
|
|
||||||
|
publish(topic, {x:2});
|
||||||
|
publish(topic + "!", {x: 2.5});
|
||||||
|
|
||||||
|
unsubscribe(x, topic);
|
||||||
|
|
||||||
|
publish(topic, {x:3});
|
||||||
|
|
||||||
|
subscribe(y, topic);
|
||||||
|
|
||||||
|
publish(topic, {x:4});
|
||||||
|
|
||||||
|
subscribe(x, topic);
|
||||||
|
|
||||||
|
publish(topic, {x:5});
|
||||||
|
|
||||||
|
unsubscribe(x, topic);
|
||||||
|
unsubscribe(y, topic);
|
||||||
|
|
||||||
|
publish(topic, {x:6});
|
||||||
|
|
||||||
|
assert.deepEqual(xs, [1, 2, 5]);
|
||||||
|
assert.deepEqual(ys, [2, 3, 4, 5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports["test weak observers are GC-ed on unload"] = (assert, end) => {
|
||||||
|
const topic = Date.now().toString(32);
|
||||||
|
const loader = Loader(module);
|
||||||
|
const { Observer, observe,
|
||||||
|
subscribe, unsubscribe } = loader.require("sdk/core/observer");
|
||||||
|
const { isWeak, WeakReference } = loader.require("sdk/core/reference");
|
||||||
|
|
||||||
|
const MyObserver = Class({
|
||||||
|
extends: Observer,
|
||||||
|
initialize: function(observe) {
|
||||||
|
this.observe = observe;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
observe.define(MyObserver, (x, ...rest) => x.observe(...rest));
|
||||||
|
|
||||||
|
const MyWeakObserver = Class({
|
||||||
|
extends: MyObserver,
|
||||||
|
implements: [WeakReference]
|
||||||
|
});
|
||||||
|
|
||||||
|
let xs = [];
|
||||||
|
let ys = [];
|
||||||
|
let x = new MyObserver((subject, topic, data) => {
|
||||||
|
xs.push(subject.wrappedJSObject, topic, data);
|
||||||
|
});
|
||||||
|
let y = new MyWeakObserver((subject, topic, data) => {
|
||||||
|
ys.push(subject.wrappedJSObject, topic, data);
|
||||||
|
});
|
||||||
|
|
||||||
|
subscribe(x, topic);
|
||||||
|
subscribe(y, topic);
|
||||||
|
|
||||||
|
|
||||||
|
notifyObservers(message({ foo: 1 }), topic, null);
|
||||||
|
x = null;
|
||||||
|
y = null;
|
||||||
|
loader.unload();
|
||||||
|
|
||||||
|
Cu.schedulePreciseGC(() => {
|
||||||
|
|
||||||
|
notifyObservers(message({ bar: 2 }), topic, ":)");
|
||||||
|
|
||||||
|
assert.deepEqual(xs, [{ foo: 1 }, topic, null,
|
||||||
|
{ bar: 2 }, topic, ":)"],
|
||||||
|
"non week observer is kept");
|
||||||
|
|
||||||
|
assert.deepEqual(ys, [{ foo: 1 }, topic, null],
|
||||||
|
"week observer was GC-ed");
|
||||||
|
|
||||||
|
end();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
require("sdk/test").run(exports);
|
|
@ -859,6 +859,8 @@ exports['test passing DOM node as first argument'] = function (assert, done) {
|
||||||
let shown = defer();
|
let shown = defer();
|
||||||
|
|
||||||
function onMessage(type, message) {
|
function onMessage(type, message) {
|
||||||
|
if (type != 'warn') return;
|
||||||
|
|
||||||
let warning = 'Passing a DOM node to Panel.show() method is an unsupported ' +
|
let warning = 'Passing a DOM node to Panel.show() method is an unsupported ' +
|
||||||
'feature that will be soon replaced. ' +
|
'feature that will be soon replaced. ' +
|
||||||
'See: https://bugzilla.mozilla.org/show_bug.cgi?id=878877';
|
'See: https://bugzilla.mozilla.org/show_bug.cgi?id=878877';
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
/* 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/. */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const { isWeak, WeakReference } = require("sdk/core/reference");
|
||||||
|
const { Class } = require("sdk/core/heritage");
|
||||||
|
|
||||||
|
exports["test non WeakReferences"] = assert => {
|
||||||
|
assert.equal(isWeak({}), false,
|
||||||
|
"regular objects aren't weak");
|
||||||
|
|
||||||
|
assert.equal(isWeak([]), false,
|
||||||
|
"arrays aren't weak");
|
||||||
|
};
|
||||||
|
|
||||||
|
exports["test a WeakReference"] = assert => {
|
||||||
|
assert.equal(isWeak(new WeakReference()), true,
|
||||||
|
"instances of WeakReferences are weak");
|
||||||
|
};
|
||||||
|
|
||||||
|
exports["test a subclass"] = assert => {
|
||||||
|
const SubType = Class({
|
||||||
|
extends: WeakReference,
|
||||||
|
foo: function() {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const x = new SubType();
|
||||||
|
assert.equal(isWeak(x), true,
|
||||||
|
"subtypes of WeakReferences are weak");
|
||||||
|
|
||||||
|
const SubSubType = Class({
|
||||||
|
extends: SubType
|
||||||
|
});
|
||||||
|
|
||||||
|
const y = new SubSubType();
|
||||||
|
assert.equal(isWeak(y), true,
|
||||||
|
"sub subtypes of WeakReferences are weak");
|
||||||
|
};
|
||||||
|
|
||||||
|
exports["test a mixin"] = assert => {
|
||||||
|
const Mixer = Class({
|
||||||
|
implements: [WeakReference]
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(isWeak(new Mixer()), true,
|
||||||
|
"instances with mixed WeakReference are weak");
|
||||||
|
|
||||||
|
const Mux = Class({});
|
||||||
|
const MixMux = Class({
|
||||||
|
extends: Mux,
|
||||||
|
implements: [WeakReference]
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(isWeak(new MixMux()), true,
|
||||||
|
"instances with mixed WeakReference that " +
|
||||||
|
"inheret from other are weak");
|
||||||
|
|
||||||
|
|
||||||
|
const Base = Class({});
|
||||||
|
const ReMix = Class({
|
||||||
|
extends: Base,
|
||||||
|
implements: [MixMux]
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(isWeak(new ReMix()), true,
|
||||||
|
"subtime of mix is still weak");
|
||||||
|
};
|
||||||
|
|
||||||
|
exports["test an override"] = assert => {
|
||||||
|
const SubType = Class({ extends: WeakReference });
|
||||||
|
isWeak.define(SubType, x => false);
|
||||||
|
|
||||||
|
assert.equal(isWeak(new SubType()), false,
|
||||||
|
"behavior of isWeak can still be overrided on subtype");
|
||||||
|
|
||||||
|
const Mixer = Class({ implements: [WeakReference] });
|
||||||
|
const SubMixer = Class({ extends: Mixer });
|
||||||
|
isWeak.define(SubMixer, x => false);
|
||||||
|
assert.equal(isWeak(new SubMixer()), false,
|
||||||
|
"behavior of isWeak can still be overrided on mixed type");
|
||||||
|
};
|
||||||
|
|
||||||
|
exports["test an opt-in"] = assert => {
|
||||||
|
var BaseType = Class({});
|
||||||
|
var SubType = Class({ extends: BaseType });
|
||||||
|
|
||||||
|
isWeak.define(SubType, x => true);
|
||||||
|
assert.equal(isWeak(new SubType()), true,
|
||||||
|
"isWeak can be just implemented");
|
||||||
|
|
||||||
|
var x = {};
|
||||||
|
isWeak.implement(x, x => true);
|
||||||
|
assert.equal(isWeak(x), true,
|
||||||
|
"isWeak can be implemented per instance");
|
||||||
|
};
|
||||||
|
|
||||||
|
require("sdk/test").run(exports);
|
|
@ -288,6 +288,43 @@ exports['test button global state updated'] = function(assert) {
|
||||||
loader.unload();
|
loader.unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports['test button global state set and get with state method'] = function(assert) {
|
||||||
|
let loader = Loader(module);
|
||||||
|
let { ActionButton } = loader.require('sdk/ui');
|
||||||
|
|
||||||
|
let button = ActionButton({
|
||||||
|
id: 'my-button-16',
|
||||||
|
label: 'my button',
|
||||||
|
icon: './icon.png'
|
||||||
|
});
|
||||||
|
|
||||||
|
// read the button's state
|
||||||
|
let state = button.state(button);
|
||||||
|
|
||||||
|
assert.equal(state.label, 'my button',
|
||||||
|
'label is correct');
|
||||||
|
assert.equal(state.icon, './icon.png',
|
||||||
|
'icon is correct');
|
||||||
|
assert.equal(state.disabled, false,
|
||||||
|
'disabled is correct');
|
||||||
|
|
||||||
|
// set the new button's state
|
||||||
|
button.state(button, {
|
||||||
|
label: 'New label',
|
||||||
|
icon: './new-icon.png',
|
||||||
|
disabled: true
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(button.label, 'New label',
|
||||||
|
'label is updated');
|
||||||
|
assert.equal(button.icon, './new-icon.png',
|
||||||
|
'icon is updated');
|
||||||
|
assert.equal(button.disabled, true,
|
||||||
|
'disabled is updated');
|
||||||
|
|
||||||
|
loader.unload();
|
||||||
|
}
|
||||||
|
|
||||||
exports['test button global state updated on multiple windows'] = function(assert, done) {
|
exports['test button global state updated on multiple windows'] = function(assert, done) {
|
||||||
let loader = Loader(module);
|
let loader = Loader(module);
|
||||||
let { ActionButton } = loader.require('sdk/ui');
|
let { ActionButton } = loader.require('sdk/ui');
|
||||||
|
|
|
@ -298,6 +298,43 @@ exports['test button global state updated'] = function(assert) {
|
||||||
loader.unload();
|
loader.unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports['test button global state set and get with state method'] = function(assert) {
|
||||||
|
let loader = Loader(module);
|
||||||
|
let { ToggleButton } = loader.require('sdk/ui');
|
||||||
|
|
||||||
|
let button = ToggleButton({
|
||||||
|
id: 'my-button-16',
|
||||||
|
label: 'my button',
|
||||||
|
icon: './icon.png'
|
||||||
|
});
|
||||||
|
|
||||||
|
// read the button's state
|
||||||
|
let state = button.state(button);
|
||||||
|
|
||||||
|
assert.equal(state.label, 'my button',
|
||||||
|
'label is correct');
|
||||||
|
assert.equal(state.icon, './icon.png',
|
||||||
|
'icon is correct');
|
||||||
|
assert.equal(state.disabled, false,
|
||||||
|
'disabled is correct');
|
||||||
|
|
||||||
|
// set the new button's state
|
||||||
|
button.state(button, {
|
||||||
|
label: 'New label',
|
||||||
|
icon: './new-icon.png',
|
||||||
|
disabled: true
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(button.label, 'New label',
|
||||||
|
'label is updated');
|
||||||
|
assert.equal(button.icon, './new-icon.png',
|
||||||
|
'icon is updated');
|
||||||
|
assert.equal(button.disabled, true,
|
||||||
|
'disabled is updated');
|
||||||
|
|
||||||
|
loader.unload();
|
||||||
|
};
|
||||||
|
|
||||||
exports['test button global state updated on multiple windows'] = function(assert, done) {
|
exports['test button global state updated on multiple windows'] = function(assert, done) {
|
||||||
let loader = Loader(module);
|
let loader = Loader(module);
|
||||||
let { ToggleButton } = loader.require('sdk/ui');
|
let { ToggleButton } = loader.require('sdk/ui');
|
||||||
|
@ -1027,35 +1064,62 @@ exports['test buttons can have anchored panels'] = function(assert, done) {
|
||||||
let { identify } = loader.require('sdk/ui/id');
|
let { identify } = loader.require('sdk/ui/id');
|
||||||
let { getActiveView } = loader.require('sdk/view/core');
|
let { getActiveView } = loader.require('sdk/view/core');
|
||||||
|
|
||||||
let button = ToggleButton({
|
let b1 = ToggleButton({
|
||||||
id: 'my-button-22',
|
id: 'my-button-22',
|
||||||
label: 'my button',
|
label: 'my button',
|
||||||
icon: './icon.png',
|
icon: './icon.png',
|
||||||
onChange: ({checked}) => checked && panel.show({position: button})
|
onChange: ({checked}) => checked && panel.show()
|
||||||
});
|
});
|
||||||
|
|
||||||
let panel = Panel();
|
let b2 = ToggleButton({
|
||||||
|
id: 'my-button-23',
|
||||||
|
label: 'my button',
|
||||||
|
icon: './icon.png',
|
||||||
|
onChange: ({checked}) => checked && panel.show({position: b2})
|
||||||
|
});
|
||||||
|
|
||||||
|
let panel = Panel({
|
||||||
|
position: b1
|
||||||
|
});
|
||||||
|
|
||||||
panel.once('show', () => {
|
|
||||||
let { document } = getMostRecentBrowserWindow();
|
let { document } = getMostRecentBrowserWindow();
|
||||||
let buttonNode = document.getElementById(identify(button));
|
let b1Node = document.getElementById(identify(b1));
|
||||||
|
let b2Node = document.getElementById(identify(b2));
|
||||||
let panelNode = getActiveView(panel);
|
let panelNode = getActiveView(panel);
|
||||||
|
|
||||||
assert.ok(button.state('window').checked,
|
panel.once('show', () => {
|
||||||
|
assert.ok(b1.state('window').checked,
|
||||||
'button is checked');
|
'button is checked');
|
||||||
|
|
||||||
assert.equal(panelNode.getAttribute('type'), 'arrow',
|
assert.equal(panelNode.getAttribute('type'), 'arrow',
|
||||||
'the panel is a arrow type');
|
'the panel is a arrow type');
|
||||||
|
|
||||||
assert.strictEqual(buttonNode, panelNode.anchorNode,
|
assert.strictEqual(b1Node, panelNode.anchorNode,
|
||||||
'the panel is anchored properly to the button');
|
'the panel is anchored properly to the button given in costructor');
|
||||||
|
|
||||||
|
panel.hide();
|
||||||
|
|
||||||
|
panel.once('show', () => {
|
||||||
|
assert.ok(b2.state('window').checked,
|
||||||
|
'button is checked');
|
||||||
|
|
||||||
|
assert.equal(panelNode.getAttribute('type'), 'arrow',
|
||||||
|
'the panel is a arrow type');
|
||||||
|
|
||||||
|
// test also that the button passed in `show` method, takes the precedence
|
||||||
|
// over the button set in panel's constructor.
|
||||||
|
assert.strictEqual(b2Node, panelNode.anchorNode,
|
||||||
|
'the panel is anchored properly to the button passed to show method');
|
||||||
|
|
||||||
loader.unload();
|
loader.unload();
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
button.click();
|
b2.click();
|
||||||
|
});
|
||||||
|
|
||||||
|
b1.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
require('sdk/test').run(exports);
|
require('sdk/test').run(exports);
|
||||||
|
|
|
@ -9,13 +9,11 @@ module.metadata = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const widgets = require("sdk/widget");
|
|
||||||
const { Cc, Ci, Cu } = require("chrome");
|
const { Cc, Ci, Cu } = require("chrome");
|
||||||
const { Loader } = require('sdk/test/loader');
|
const { LoaderWithHookedConsole } = require('sdk/test/loader');
|
||||||
const url = require("sdk/url");
|
const url = require("sdk/url");
|
||||||
const timer = require("sdk/timers");
|
const timer = require("sdk/timers");
|
||||||
const self = require("sdk/self");
|
const self = require("sdk/self");
|
||||||
const windowUtils = require("sdk/deprecated/window-utils");
|
|
||||||
const { getMostRecentBrowserWindow } = require('sdk/window/utils');
|
const { getMostRecentBrowserWindow } = require('sdk/window/utils');
|
||||||
const { close, open, focus } = require("sdk/window/helpers");
|
const { close, open, focus } = require("sdk/window/helpers");
|
||||||
const tabs = require("sdk/tabs/utils");
|
const tabs = require("sdk/tabs/utils");
|
||||||
|
@ -43,8 +41,24 @@ function openNewWindowTab(url, options) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.testDeprecationMessage = function(assert, done) {
|
||||||
|
let { loader } = LoaderWithHookedConsole(module, onMessage);
|
||||||
|
|
||||||
|
// Intercept all console method calls
|
||||||
|
let calls = [];
|
||||||
|
function onMessage(type, msg) {
|
||||||
|
assert.equal(type, 'error', 'the only message is an error');
|
||||||
|
assert.ok(/^DEPRECATED:/.test(msg), 'deprecated');
|
||||||
|
loader.unload();
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
loader.require('sdk/widget');
|
||||||
|
}
|
||||||
|
|
||||||
exports.testConstructor = function(assert, done) {
|
exports.testConstructor = function(assert, done) {
|
||||||
let browserWindow = windowUtils.activeBrowserWindow;
|
let { loader: loader0 } = LoaderWithHookedConsole(module);
|
||||||
|
const widgets = loader0.require("sdk/widget");
|
||||||
|
let browserWindow = getMostRecentBrowserWindow();
|
||||||
let doc = browserWindow.document;
|
let doc = browserWindow.document;
|
||||||
let AddonsMgrListener;
|
let AddonsMgrListener;
|
||||||
|
|
||||||
|
@ -78,7 +92,7 @@ exports.testConstructor = function(assert, done) {
|
||||||
assert.equal(widgetCount(), widgetStartCount, "panel has correct number of child elements after destroy");
|
assert.equal(widgetCount(), widgetStartCount, "panel has correct number of child elements after destroy");
|
||||||
|
|
||||||
// Test automatic widget destroy on unload
|
// Test automatic widget destroy on unload
|
||||||
let loader = Loader(module);
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
let widgetsFromLoader = loader.require("sdk/widget");
|
let widgetsFromLoader = loader.require("sdk/widget");
|
||||||
let widgetStartCount = widgetCount();
|
let widgetStartCount = widgetCount();
|
||||||
let w = widgetsFromLoader.Widget({ id: "destroy-on-unload", label: "foo", content: "bar" });
|
let w = widgetsFromLoader.Widget({ id: "destroy-on-unload", label: "foo", content: "bar" });
|
||||||
|
@ -192,8 +206,10 @@ exports.testConstructor = function(assert, done) {
|
||||||
let tests = [];
|
let tests = [];
|
||||||
function nextTest() {
|
function nextTest() {
|
||||||
assert.equal(widgetCount(), 0, "widget in last test property cleaned itself up");
|
assert.equal(widgetCount(), 0, "widget in last test property cleaned itself up");
|
||||||
if (!tests.length)
|
if (!tests.length) {
|
||||||
|
loader0.unload();
|
||||||
done();
|
done();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
timer.setTimeout(tests.shift(), 0);
|
timer.setTimeout(tests.shift(), 0);
|
||||||
}
|
}
|
||||||
|
@ -535,7 +551,7 @@ exports.testConstructor = function(assert, done) {
|
||||||
contentScript: "self.port.on('event', function () self.port.emit('event'))"
|
contentScript: "self.port.on('event', function () self.port.emit('event'))"
|
||||||
};
|
};
|
||||||
let widget = testSingleWidget(w1Opts);
|
let widget = testSingleWidget(w1Opts);
|
||||||
let windows = require("sdk/windows").browserWindows;
|
let windows = loader0.require("sdk/windows").browserWindows;
|
||||||
|
|
||||||
// 2/ Retrieve a WidgetView for the initial browser window
|
// 2/ Retrieve a WidgetView for the initial browser window
|
||||||
let acceptDetach = false;
|
let acceptDetach = false;
|
||||||
|
@ -627,16 +643,16 @@ exports.testConstructor = function(assert, done) {
|
||||||
id: "text-test-width",
|
id: "text-test-width",
|
||||||
label: "test widget.width",
|
label: "test widget.width",
|
||||||
content: "test width",
|
content: "test width",
|
||||||
width: 200,
|
width: 64,
|
||||||
contentScript: "self.postMessage(1)",
|
contentScript: "self.postMessage(1)",
|
||||||
contentScriptWhen: "ready",
|
contentScriptWhen: "ready",
|
||||||
onMessage: function(message) {
|
onMessage: function(message) {
|
||||||
assert.equal(this.width, 200, 'width is 200');
|
assert.equal(this.width, 64, 'width is 64');
|
||||||
|
|
||||||
let node = widgetNode(0);
|
let node = widgetNode(0);
|
||||||
assert.equal(this.width, node.style.minWidth.replace("px", ""));
|
assert.equal(this.width, node.style.minWidth.replace("px", ""));
|
||||||
assert.equal(this.width, node.firstElementChild.style.width.replace("px", ""));
|
assert.equal(this.width, node.firstElementChild.style.width.replace("px", ""));
|
||||||
this.width = 300;
|
this.width = 48;
|
||||||
assert.equal(this.width, node.style.minWidth.replace("px", ""));
|
assert.equal(this.width, node.style.minWidth.replace("px", ""));
|
||||||
assert.equal(this.width, node.firstElementChild.style.width.replace("px", ""));
|
assert.equal(this.width, node.firstElementChild.style.width.replace("px", ""));
|
||||||
|
|
||||||
|
@ -677,16 +693,18 @@ exports.testConstructor = function(assert, done) {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testWidgetWithValidPanel = function(assert, done) {
|
exports.testWidgetWithValidPanel = function(assert, done) {
|
||||||
const widgets = require("sdk/widget");
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const { Widget } = loader.require("sdk/widget");
|
||||||
|
const { Panel } = loader.require("sdk/panel");
|
||||||
|
|
||||||
let widget1 = widgets.Widget({
|
let widget1 = Widget({
|
||||||
id: "testWidgetWithValidPanel",
|
id: "testWidgetWithValidPanel",
|
||||||
label: "panel widget 1",
|
label: "panel widget 1",
|
||||||
content: "<div id='me'>foo</div>",
|
content: "<div id='me'>foo</div>",
|
||||||
contentScript: "var evt = new MouseEvent('click', {button: 0});" +
|
contentScript: "var evt = new MouseEvent('click', {button: 0});" +
|
||||||
"document.body.dispatchEvent(evt);",
|
"document.body.dispatchEvent(evt);",
|
||||||
contentScriptWhen: "end",
|
contentScriptWhen: "end",
|
||||||
panel: require("sdk/panel").Panel({
|
panel: Panel({
|
||||||
contentURL: "data:text/html;charset=utf-8,<body>Look ma, a panel!</body>",
|
contentURL: "data:text/html;charset=utf-8,<body>Look ma, a panel!</body>",
|
||||||
onShow: function() {
|
onShow: function() {
|
||||||
let { document } = getMostRecentBrowserWindow();
|
let { document } = getMostRecentBrowserWindow();
|
||||||
|
@ -697,6 +715,7 @@ exports.testWidgetWithValidPanel = function(assert, done) {
|
||||||
assert.strictEqual(panelEle.anchorNode, widgetEle, 'the panel is properly anchored to the widget');
|
assert.strictEqual(panelEle.anchorNode, widgetEle, 'the panel is properly anchored to the widget');
|
||||||
|
|
||||||
widget1.destroy();
|
widget1.destroy();
|
||||||
|
loader.unload();
|
||||||
assert.pass("panel displayed on click");
|
assert.pass("panel displayed on click");
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
@ -705,7 +724,9 @@ exports.testWidgetWithValidPanel = function(assert, done) {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testWidgetWithInvalidPanel = function(assert) {
|
exports.testWidgetWithInvalidPanel = function(assert) {
|
||||||
const widgets = require("sdk/widget");
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const widgets = loader.require("sdk/widget");
|
||||||
|
|
||||||
assert.throws(
|
assert.throws(
|
||||||
function() {
|
function() {
|
||||||
widgets.Widget({
|
widgets.Widget({
|
||||||
|
@ -716,10 +737,14 @@ exports.testWidgetWithInvalidPanel = function(assert) {
|
||||||
},
|
},
|
||||||
/^The option \"panel\" must be one of the following types: null, undefined, object$/,
|
/^The option \"panel\" must be one of the following types: null, undefined, object$/,
|
||||||
"widget.panel must be a Panel object");
|
"widget.panel must be a Panel object");
|
||||||
|
loader.unload();
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testPanelWidget3 = function testPanelWidget3(assert, done) {
|
exports.testPanelWidget3 = function testPanelWidget3(assert, done) {
|
||||||
const widgets = require("sdk/widget");
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const widgets = loader.require("sdk/widget");
|
||||||
|
const { Panel } = loader.require("sdk/panel");
|
||||||
|
|
||||||
let onClickCalled = false;
|
let onClickCalled = false;
|
||||||
let widget3 = widgets.Widget({
|
let widget3 = widgets.Widget({
|
||||||
id: "panel3",
|
id: "panel3",
|
||||||
|
@ -732,13 +757,14 @@ exports.testPanelWidget3 = function testPanelWidget3(assert, done) {
|
||||||
onClickCalled = true;
|
onClickCalled = true;
|
||||||
this.panel.show();
|
this.panel.show();
|
||||||
},
|
},
|
||||||
panel: require("sdk/panel").Panel({
|
panel: Panel({
|
||||||
contentURL: "data:text/html;charset=utf-8,<body>Look ma, a panel!</body>",
|
contentURL: "data:text/html;charset=utf-8,<body>Look ma, a panel!</body>",
|
||||||
onShow: function() {
|
onShow: function() {
|
||||||
assert.ok(
|
assert.ok(
|
||||||
onClickCalled,
|
onClickCalled,
|
||||||
"onClick called on click for widget with both panel and onClick");
|
"onClick called on click for widget with both panel and onClick");
|
||||||
widget3.destroy();
|
widget3.destroy();
|
||||||
|
loader.unload();
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -747,7 +773,9 @@ exports.testPanelWidget3 = function testPanelWidget3(assert, done) {
|
||||||
|
|
||||||
exports.testWidgetWithPanelInMenuPanel = function(assert, done) {
|
exports.testWidgetWithPanelInMenuPanel = function(assert, done) {
|
||||||
const { CustomizableUI } = Cu.import("resource:///modules/CustomizableUI.jsm", {});
|
const { CustomizableUI } = Cu.import("resource:///modules/CustomizableUI.jsm", {});
|
||||||
const widgets = require("sdk/widget");
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const widgets = loader.require("sdk/widget");
|
||||||
|
const { Panel } = loader.require("sdk/panel");
|
||||||
|
|
||||||
let widget1 = widgets.Widget({
|
let widget1 = widgets.Widget({
|
||||||
id: "panel1",
|
id: "panel1",
|
||||||
|
@ -760,7 +788,7 @@ exports.testWidgetWithPanelInMenuPanel = function(assert, done) {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
contentScriptWhen: "end",
|
contentScriptWhen: "end",
|
||||||
panel: require("sdk/panel").Panel({
|
panel: Panel({
|
||||||
contentURL: "data:text/html;charset=utf-8,<body>Look ma, a panel!</body>",
|
contentURL: "data:text/html;charset=utf-8,<body>Look ma, a panel!</body>",
|
||||||
onShow: function() {
|
onShow: function() {
|
||||||
let { document } = getMostRecentBrowserWindow();
|
let { document } = getMostRecentBrowserWindow();
|
||||||
|
@ -771,6 +799,7 @@ exports.testWidgetWithPanelInMenuPanel = function(assert, done) {
|
||||||
'the panel is anchored to the panel menu button instead of widget');
|
'the panel is anchored to the panel menu button instead of widget');
|
||||||
|
|
||||||
widget1.destroy();
|
widget1.destroy();
|
||||||
|
loader.unload();
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -797,8 +826,10 @@ exports.testWidgetWithPanelInMenuPanel = function(assert, done) {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testWidgetMessaging = function testWidgetMessaging(assert, done) {
|
exports.testWidgetMessaging = function testWidgetMessaging(assert, done) {
|
||||||
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const widgets = loader.require("sdk/widget");
|
||||||
|
|
||||||
let origMessage = "foo";
|
let origMessage = "foo";
|
||||||
const widgets = require("sdk/widget");
|
|
||||||
let widget = widgets.Widget({
|
let widget = widgets.Widget({
|
||||||
id: "widget-messaging",
|
id: "widget-messaging",
|
||||||
label: "foo",
|
label: "foo",
|
||||||
|
@ -811,6 +842,7 @@ exports.testWidgetMessaging = function testWidgetMessaging(assert, done) {
|
||||||
else {
|
else {
|
||||||
assert.equal(origMessage, message);
|
assert.equal(origMessage, message);
|
||||||
widget.destroy();
|
widget.destroy();
|
||||||
|
loader.unload();
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -818,7 +850,9 @@ exports.testWidgetMessaging = function testWidgetMessaging(assert, done) {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testWidgetViews = function testWidgetViews(assert, done) {
|
exports.testWidgetViews = function testWidgetViews(assert, done) {
|
||||||
const widgets = require("sdk/widget");
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const widgets = loader.require("sdk/widget");
|
||||||
|
|
||||||
let widget = widgets.Widget({
|
let widget = widgets.Widget({
|
||||||
id: "widget-views",
|
id: "widget-views",
|
||||||
label: "foo",
|
label: "foo",
|
||||||
|
@ -833,6 +867,7 @@ exports.testWidgetViews = function testWidgetViews(assert, done) {
|
||||||
});
|
});
|
||||||
view.on("detach", function () {
|
view.on("detach", function () {
|
||||||
assert.pass("WidgetView destroyed");
|
assert.pass("WidgetView destroyed");
|
||||||
|
loader.unload();
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -840,7 +875,10 @@ exports.testWidgetViews = function testWidgetViews(assert, done) {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testWidgetViewsUIEvents = function testWidgetViewsUIEvents(assert, done) {
|
exports.testWidgetViewsUIEvents = function testWidgetViewsUIEvents(assert, done) {
|
||||||
const widgets = require("sdk/widget");
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const widgets = loader.require("sdk/widget");
|
||||||
|
const { browserWindows } = loader.require("sdk/windows");
|
||||||
|
|
||||||
let view = null;
|
let view = null;
|
||||||
let widget = widgets.Widget({
|
let widget = widgets.Widget({
|
||||||
id: "widget-view-ui-events",
|
id: "widget-view-ui-events",
|
||||||
|
@ -856,17 +894,20 @@ exports.testWidgetViewsUIEvents = function testWidgetViewsUIEvents(assert, done)
|
||||||
onClick: function (eventView) {
|
onClick: function (eventView) {
|
||||||
assert.equal(view, eventView,
|
assert.equal(view, eventView,
|
||||||
"event first argument is equal to the WidgetView");
|
"event first argument is equal to the WidgetView");
|
||||||
let view2 = widget.getView(require("sdk/windows").browserWindows.activeWindow);
|
let view2 = widget.getView(browserWindows.activeWindow);
|
||||||
assert.equal(view, view2,
|
assert.equal(view, view2,
|
||||||
"widget.getView return the same WidgetView");
|
"widget.getView return the same WidgetView");
|
||||||
widget.destroy();
|
widget.destroy();
|
||||||
|
loader.unload();
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testWidgetViewsCustomEvents = function testWidgetViewsCustomEvents(assert, done) {
|
exports.testWidgetViewsCustomEvents = function testWidgetViewsCustomEvents(assert, done) {
|
||||||
const widgets = require("sdk/widget");
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const widgets = loader.require("sdk/widget");
|
||||||
|
|
||||||
let widget = widgets.Widget({
|
let widget = widgets.Widget({
|
||||||
id: "widget-view-custom-events",
|
id: "widget-view-custom-events",
|
||||||
label: "foo",
|
label: "foo",
|
||||||
|
@ -883,33 +924,37 @@ exports.testWidgetViewsCustomEvents = function testWidgetViewsCustomEvents(asser
|
||||||
widget.port.on("event", function (data) {
|
widget.port.on("event", function (data) {
|
||||||
assert.equal(data, "ok", "event argument is valid on Widget");
|
assert.equal(data, "ok", "event argument is valid on Widget");
|
||||||
widget.destroy();
|
widget.destroy();
|
||||||
|
loader.unload();
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testWidgetViewsTooltip = function testWidgetViewsTooltip(assert, done) {
|
exports.testWidgetViewsTooltip = function testWidgetViewsTooltip(assert, done) {
|
||||||
const widgets = require("sdk/widget");
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const widgets = loader.require("sdk/widget");
|
||||||
|
const { browserWindows } = loader.require("sdk/windows");
|
||||||
|
|
||||||
let widget = new widgets.Widget({
|
let widget = new widgets.Widget({
|
||||||
id: "widget-views-tooltip",
|
id: "widget-views-tooltip",
|
||||||
label: "foo",
|
label: "foo",
|
||||||
content: "foo"
|
content: "foo"
|
||||||
});
|
});
|
||||||
let view = widget.getView(require("sdk/windows").browserWindows.activeWindow);
|
let view = widget.getView(browserWindows.activeWindow);
|
||||||
widget.tooltip = null;
|
widget.tooltip = null;
|
||||||
assert.equal(view.tooltip, "foo",
|
assert.equal(view.tooltip, "foo",
|
||||||
"view tooltip defaults to base widget label");
|
"view tooltip defaults to base widget label");
|
||||||
assert.equal(widget.tooltip, "foo",
|
assert.equal(widget.tooltip, "foo",
|
||||||
"tooltip defaults to base widget label");
|
"tooltip defaults to base widget label");
|
||||||
widget.destroy();
|
widget.destroy();
|
||||||
|
loader.unload();
|
||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testWidgetMove = function testWidgetMove(assert, done) {
|
exports.testWidgetMove = function testWidgetMove(assert, done) {
|
||||||
let windowUtils = require("sdk/deprecated/window-utils");
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
let widgets = require("sdk/widget");
|
const widgets = loader.require("sdk/widget");
|
||||||
|
|
||||||
let browserWindow = windowUtils.activeBrowserWindow;
|
let browserWindow = getMostRecentBrowserWindow();
|
||||||
let doc = browserWindow.document;
|
let doc = browserWindow.document;
|
||||||
|
|
||||||
let label = "unique-widget-label";
|
let label = "unique-widget-label";
|
||||||
|
@ -939,6 +984,7 @@ exports.testWidgetMove = function testWidgetMove(assert, done) {
|
||||||
else {
|
else {
|
||||||
assert.equal(origMessage, message, "Got message after node move");
|
assert.equal(origMessage, message, "Got message after node move");
|
||||||
widget.destroy();
|
widget.destroy();
|
||||||
|
loader.unload();
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -953,16 +999,17 @@ consider the content change a navigation change, so doesn't load
|
||||||
the new content.
|
the new content.
|
||||||
*/
|
*/
|
||||||
exports.testWidgetWithPound = function testWidgetWithPound(assert, done) {
|
exports.testWidgetWithPound = function testWidgetWithPound(assert, done) {
|
||||||
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const widgets = loader.require("sdk/widget");
|
||||||
|
|
||||||
function getWidgetContent(widget) {
|
function getWidgetContent(widget) {
|
||||||
let windowUtils = require("sdk/deprecated/window-utils");
|
let browserWindow = getMostRecentBrowserWindow();
|
||||||
let browserWindow = windowUtils.activeBrowserWindow;
|
|
||||||
let doc = browserWindow.document;
|
let doc = browserWindow.document;
|
||||||
let widgetNode = doc.querySelector('toolbaritem[label="' + widget.label + '"]');
|
let widgetNode = doc.querySelector('toolbaritem[label="' + widget.label + '"]');
|
||||||
assert.ok(widgetNode, 'found widget node in the front-end');
|
assert.ok(widgetNode, 'found widget node in the front-end');
|
||||||
return widgetNode.firstChild.contentDocument.body.innerHTML;
|
return widgetNode.firstChild.contentDocument.body.innerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
let widgets = require("sdk/widget");
|
|
||||||
let count = 0;
|
let count = 0;
|
||||||
let widget = widgets.Widget({
|
let widget = widgets.Widget({
|
||||||
id: "1",
|
id: "1",
|
||||||
|
@ -977,6 +1024,7 @@ exports.testWidgetWithPound = function testWidgetWithPound(assert, done) {
|
||||||
else {
|
else {
|
||||||
assert.equal(getWidgetContent(widget), "foo#", "content updated to pound?");
|
assert.equal(getWidgetContent(widget), "foo#", "content updated to pound?");
|
||||||
widget.destroy();
|
widget.destroy();
|
||||||
|
loader.unload();
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -984,7 +1032,10 @@ exports.testWidgetWithPound = function testWidgetWithPound(assert, done) {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testContentScriptOptionsOption = function(assert, done) {
|
exports.testContentScriptOptionsOption = function(assert, done) {
|
||||||
let widget = require("sdk/widget").Widget({
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const { Widget } = loader.require("sdk/widget");
|
||||||
|
|
||||||
|
let widget = Widget({
|
||||||
id: "widget-script-options",
|
id: "widget-script-options",
|
||||||
label: "fooz",
|
label: "fooz",
|
||||||
content: "fooz",
|
content: "fooz",
|
||||||
|
@ -998,26 +1049,34 @@ exports.testContentScriptOptionsOption = function(assert, done) {
|
||||||
assert.equal( msg[1].b.join(), '1,2,3', 'array and numbers in contentScriptOptions' );
|
assert.equal( msg[1].b.join(), '1,2,3', 'array and numbers in contentScriptOptions' );
|
||||||
assert.equal( msg[1].c, 'string', 'string in contentScriptOptions' );
|
assert.equal( msg[1].c, 'string', 'string in contentScriptOptions' );
|
||||||
widget.destroy();
|
widget.destroy();
|
||||||
|
loader.unload();
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testOnAttachWithoutContentScript = function(assert, done) {
|
exports.testOnAttachWithoutContentScript = function(assert, done) {
|
||||||
let widget = require("sdk/widget").Widget({
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const { Widget } = loader.require("sdk/widget");
|
||||||
|
|
||||||
|
let widget = Widget({
|
||||||
id: "onAttachNoCS",
|
id: "onAttachNoCS",
|
||||||
label: "onAttachNoCS",
|
label: "onAttachNoCS",
|
||||||
content: "onAttachNoCS",
|
content: "onAttachNoCS",
|
||||||
onAttach: function (view) {
|
onAttach: function (view) {
|
||||||
assert.pass("received attach event");
|
assert.pass("received attach event");
|
||||||
widget.destroy();
|
widget.destroy();
|
||||||
|
loader.unload();
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testPostMessageOnAttach = function(assert, done) {
|
exports.testPostMessageOnAttach = function(assert, done) {
|
||||||
let widget = require("sdk/widget").Widget({
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const { Widget } = loader.require("sdk/widget");
|
||||||
|
|
||||||
|
let widget = Widget({
|
||||||
id: "onAttach",
|
id: "onAttach",
|
||||||
label: "onAttach",
|
label: "onAttach",
|
||||||
content: "onAttach",
|
content: "onAttach",
|
||||||
|
@ -1031,15 +1090,19 @@ exports.testPostMessageOnAttach = function(assert, done) {
|
||||||
onMessage: function (msg) {
|
onMessage: function (msg) {
|
||||||
assert.equal( msg, "ok", "postMessage works on `attach` event");
|
assert.equal( msg, "ok", "postMessage works on `attach` event");
|
||||||
widget.destroy();
|
widget.destroy();
|
||||||
|
loader.unload();
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testPostMessageOnLocationChange = function(assert, done) {
|
exports.testPostMessageOnLocationChange = function(assert, done) {
|
||||||
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const { Widget } = loader.require("sdk/widget");
|
||||||
|
|
||||||
let attachEventCount = 0;
|
let attachEventCount = 0;
|
||||||
let messagesCount = 0;
|
let messagesCount = 0;
|
||||||
let widget = require("sdk/widget").Widget({
|
let widget = Widget({
|
||||||
id: "onLocationChange",
|
id: "onLocationChange",
|
||||||
label: "onLocationChange",
|
label: "onLocationChange",
|
||||||
content: "onLocationChange",
|
content: "onLocationChange",
|
||||||
|
@ -1065,6 +1128,7 @@ exports.testPostMessageOnLocationChange = function(assert, done) {
|
||||||
assert.equal(msg, "ok",
|
assert.equal(msg, "ok",
|
||||||
"We receive the message sent to the 2nd document");
|
"We receive the message sent to the 2nd document");
|
||||||
widget.destroy();
|
widget.destroy();
|
||||||
|
loader.unload();
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1072,10 +1136,13 @@ exports.testPostMessageOnLocationChange = function(assert, done) {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testSVGWidget = function(assert, done) {
|
exports.testSVGWidget = function(assert, done) {
|
||||||
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const { Widget } = loader.require("sdk/widget");
|
||||||
|
|
||||||
// use of capital SVG here is intended, that was failing..
|
// use of capital SVG here is intended, that was failing..
|
||||||
let SVG_URL = fixtures.url("mofo_logo.SVG");
|
let SVG_URL = fixtures.url("mofo_logo.SVG");
|
||||||
|
|
||||||
let widget = require("sdk/widget").Widget({
|
let widget = Widget({
|
||||||
id: "mozilla-svg-logo",
|
id: "mozilla-svg-logo",
|
||||||
label: "moz foundation logo",
|
label: "moz foundation logo",
|
||||||
contentURL: SVG_URL,
|
contentURL: SVG_URL,
|
||||||
|
@ -1084,16 +1151,19 @@ exports.testSVGWidget = function(assert, done) {
|
||||||
widget.destroy();
|
widget.destroy();
|
||||||
assert.equal(data.count, 1, 'only one image');
|
assert.equal(data.count, 1, 'only one image');
|
||||||
assert.equal(data.src, SVG_URL, 'only one image');
|
assert.equal(data.src, SVG_URL, 'only one image');
|
||||||
|
loader.unload();
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testReinsertion = function(assert, done) {
|
exports.testReinsertion = function(assert, done) {
|
||||||
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const { Widget } = loader.require("sdk/widget");
|
||||||
const WIDGETID = "test-reinsertion";
|
const WIDGETID = "test-reinsertion";
|
||||||
let windowUtils = require("sdk/deprecated/window-utils");
|
let browserWindow = getMostRecentBrowserWindow();
|
||||||
let browserWindow = windowUtils.activeBrowserWindow;
|
|
||||||
let widget = require("sdk/widget").Widget({
|
let widget = Widget({
|
||||||
id: "test-reinsertion",
|
id: "test-reinsertion",
|
||||||
label: "test reinsertion",
|
label: "test reinsertion",
|
||||||
content: "Test",
|
content: "Test",
|
||||||
|
@ -1105,8 +1175,39 @@ exports.testReinsertion = function(assert, done) {
|
||||||
|
|
||||||
openNewWindowTab("about:blank", { inNewWindow: true, onLoad: function(e) {
|
openNewWindowTab("about:blank", { inNewWindow: true, onLoad: function(e) {
|
||||||
assert.equal(e.target.defaultView.document.getElementById(realWidgetId), null);
|
assert.equal(e.target.defaultView.document.getElementById(realWidgetId), null);
|
||||||
close(e.target.defaultView).then(done);
|
close(e.target.defaultView).then(_ => {
|
||||||
|
loader.unload();
|
||||||
|
done();
|
||||||
|
});
|
||||||
}});
|
}});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.testWideWidget = function testWideWidget(assert) {
|
||||||
|
let { loader } = LoaderWithHookedConsole(module);
|
||||||
|
const widgets = loader.require("sdk/widget");
|
||||||
|
const { document, CustomizableUI, gCustomizeMode, setTimeout } = getMostRecentBrowserWindow();
|
||||||
|
|
||||||
|
let wideWidget = widgets.Widget({
|
||||||
|
id: "my-wide-widget",
|
||||||
|
label: "wide-wdgt",
|
||||||
|
content: "foo",
|
||||||
|
width: 200
|
||||||
|
});
|
||||||
|
|
||||||
|
let widget = widgets.Widget({
|
||||||
|
id: "my-regular-widget",
|
||||||
|
label: "reg-wdgt",
|
||||||
|
content: "foo"
|
||||||
|
});
|
||||||
|
|
||||||
|
let wideWidgetNode = document.querySelector("toolbaritem[label=wide-wdgt]");
|
||||||
|
let widgetNode = document.querySelector("toolbaritem[label=reg-wdgt]");
|
||||||
|
|
||||||
|
assert.equal(wideWidgetNode, null,
|
||||||
|
"Wide Widget are not added to UI");
|
||||||
|
|
||||||
|
assert.notEqual(widgetNode, null,
|
||||||
|
"regular size widget are in the UI");
|
||||||
|
};
|
||||||
|
|
||||||
require("sdk/test").run(exports);
|
require("sdk/test").run(exports);
|
||||||
|
|
|
@ -131,7 +131,7 @@ def main(platform):
|
||||||
])
|
])
|
||||||
|
|
||||||
# Ship b2g-desktop, but prevent its gaia profile to be shipped in the xpi
|
# Ship b2g-desktop, but prevent its gaia profile to be shipped in the xpi
|
||||||
add_dir_to_zip(xpi_path, os.path.join(distdir, "b2g"), "b2g", ("gaia"))
|
add_dir_to_zip(xpi_path, os.path.join(distdir, "b2g"), "b2g", ("gaia", "B2G.app/Contents/MacOS/gaia"))
|
||||||
# Then ship our own gaia profile
|
# Then ship our own gaia profile
|
||||||
add_dir_to_zip(xpi_path, os.path.join(gaia_path, "profile"), "profile")
|
add_dir_to_zip(xpi_path, os.path.join(gaia_path, "profile"), "profile")
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ exports.SimulatorProcess = Class({
|
||||||
let bin = URL.toFilename(BIN_URL);
|
let bin = URL.toFilename(BIN_URL);
|
||||||
let executables = {
|
let executables = {
|
||||||
WINNT: "b2g-bin.exe",
|
WINNT: "b2g-bin.exe",
|
||||||
Darwin: "Contents/MacOS/b2g-bin",
|
Darwin: "B2G.app/Contents/MacOS/b2g-bin",
|
||||||
Linux: "b2g-bin",
|
Linux: "b2g-bin",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1182,15 +1182,14 @@
|
||||||
<svg:svg height="0">
|
<svg:svg height="0">
|
||||||
#include tab-shape.inc.svg
|
#include tab-shape.inc.svg
|
||||||
|
|
||||||
#ifndef XP_UNIX
|
#ifndef XP_MACOSX
|
||||||
<svg:clipPath id="windows-keyhole-forward-clip-path" clipPathUnits="userSpaceOnUse">
|
<svg:clipPath id="keyhole-forward-clip-path" clipPathUnits="userSpaceOnUse">
|
||||||
<svg:path d="M 0,0 a 16 16 0 0 1 0,24 l 10000,0 l 0,-24 l -10000,0 z"/>
|
<svg:path d="M 0,0 a 16 16 0 0 1 0,24 l 10000,0 l 0,-24 l -10000,0 z"/>
|
||||||
</svg:clipPath>
|
</svg:clipPath>
|
||||||
<svg:clipPath id="windows-urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse">
|
<svg:clipPath id="urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse">
|
||||||
<svg:path d="M -1,1 a 16 16 0 0 1 0,24 l 10000,0 l 0,-24 l -10000,0 z"/>
|
<svg:path d="M -1,1 a 16 16 0 0 1 0,24 l 10000,0 l 0,-24 l -10000,0 z"/>
|
||||||
</svg:clipPath>
|
</svg:clipPath>
|
||||||
#endif
|
#else
|
||||||
#ifdef XP_MACOSX
|
|
||||||
<svg:clipPath id="osx-keyhole-forward-clip-path" clipPathUnits="userSpaceOnUse">
|
<svg:clipPath id="osx-keyhole-forward-clip-path" clipPathUnits="userSpaceOnUse">
|
||||||
<svg:path d="M 0,0 a 16 16 0 0 1 0,24 l 10000,0 l 0,-24 l -10000,0 z"/>
|
<svg:path d="M 0,0 a 16 16 0 0 1 0,24 l 10000,0 l 0,-24 l -10000,0 z"/>
|
||||||
</svg:clipPath>
|
</svg:clipPath>
|
||||||
|
|
|
@ -529,7 +529,12 @@ var tests = [
|
||||||
this.notifyObj.addOptions({dismissed: true});
|
this.notifyObj.addOptions({dismissed: true});
|
||||||
this.notification = showNotification(this.notifyObj);
|
this.notification = showNotification(this.notifyObj);
|
||||||
|
|
||||||
EventUtils.synthesizeMouse(button, 1, 1, {});
|
// This test places a normal button in the notification area, which has
|
||||||
|
// standard GTK styling and dimensions. Due to the clip-path, this button
|
||||||
|
// gets clipped off, which makes it necessary to synthesize the mouse click
|
||||||
|
// a little bit downward. To be safe, I adjusted the x-offset with the same
|
||||||
|
// amount.
|
||||||
|
EventUtils.synthesizeMouse(button, 4, 4, {});
|
||||||
},
|
},
|
||||||
onShown: function(popup) {
|
onShown: function(popup) {
|
||||||
checkPopup(popup, this.notifyObj);
|
checkPopup(popup, this.notifyObj);
|
||||||
|
|
|
@ -49,6 +49,7 @@ const PanelUI = {
|
||||||
this.menuButton.addEventListener("keypress", this);
|
this.menuButton.addEventListener("keypress", this);
|
||||||
this._overlayScrollListenerBoundFn = this._overlayScrollListener.bind(this);
|
this._overlayScrollListenerBoundFn = this._overlayScrollListener.bind(this);
|
||||||
window.matchMedia("(-moz-overlay-scrollbars)").addListener(this._overlayScrollListenerBoundFn);
|
window.matchMedia("(-moz-overlay-scrollbars)").addListener(this._overlayScrollListenerBoundFn);
|
||||||
|
CustomizableUI.addListener(this);
|
||||||
this._initialized = true;
|
this._initialized = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -69,10 +70,6 @@ const PanelUI = {
|
||||||
},
|
},
|
||||||
|
|
||||||
uninit: function() {
|
uninit: function() {
|
||||||
if (!this._eventListenersAdded) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let event of this.kEvents) {
|
for (let event of this.kEvents) {
|
||||||
this.panel.removeEventListener(event, this);
|
this.panel.removeEventListener(event, this);
|
||||||
}
|
}
|
||||||
|
@ -80,6 +77,7 @@ const PanelUI = {
|
||||||
this.menuButton.removeEventListener("mousedown", this);
|
this.menuButton.removeEventListener("mousedown", this);
|
||||||
this.menuButton.removeEventListener("keypress", this);
|
this.menuButton.removeEventListener("keypress", this);
|
||||||
window.matchMedia("(-moz-overlay-scrollbars)").removeListener(this._overlayScrollListenerBoundFn);
|
window.matchMedia("(-moz-overlay-scrollbars)").removeListener(this._overlayScrollListenerBoundFn);
|
||||||
|
CustomizableUI.removeListener(this);
|
||||||
this._overlayScrollListenerBoundFn = null;
|
this._overlayScrollListenerBoundFn = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -183,6 +181,7 @@ const PanelUI = {
|
||||||
handleEvent: function(aEvent) {
|
handleEvent: function(aEvent) {
|
||||||
switch (aEvent.type) {
|
switch (aEvent.type) {
|
||||||
case "popupshowing":
|
case "popupshowing":
|
||||||
|
this._adjustLabelsForAutoHyphens();
|
||||||
// Fall through
|
// Fall through
|
||||||
case "popupshown":
|
case "popupshown":
|
||||||
// Fall through
|
// Fall through
|
||||||
|
@ -370,6 +369,26 @@ const PanelUI = {
|
||||||
"browser");
|
"browser");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onWidgetAfterDOMChange: function(aNode, aNextNode, aContainer, aWasRemoval) {
|
||||||
|
if (aContainer != this.contents) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (aWasRemoval) {
|
||||||
|
aNode.removeAttribute("auto-hyphens");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onWidgetBeforeDOMChange: function(aNode, aNextNode, aContainer, aIsRemoval) {
|
||||||
|
if (aContainer != this.contents) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!aIsRemoval &&
|
||||||
|
(this.panel.state == "open" ||
|
||||||
|
document.documentElement.hasAttribute("customizing"))) {
|
||||||
|
this._adjustLabelsForAutoHyphens(aNode);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signal that we're about to make a lot of changes to the contents of the
|
* Signal that we're about to make a lot of changes to the contents of the
|
||||||
* panels all at once. For performance, we ignore the mutations.
|
* panels all at once. For performance, we ignore the mutations.
|
||||||
|
@ -389,6 +408,22 @@ const PanelUI = {
|
||||||
this.multiView.ignoreMutations = false;
|
this.multiView.ignoreMutations = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_adjustLabelsForAutoHyphens: function(aNode) {
|
||||||
|
let toolbarButtons = aNode ? [aNode] :
|
||||||
|
this.contents.querySelectorAll(".toolbarbutton-1");
|
||||||
|
for (let node of toolbarButtons) {
|
||||||
|
let label = node.getAttribute("label");
|
||||||
|
if (!label) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (label.contains("\u00ad")) {
|
||||||
|
node.setAttribute("auto-hyphens", "off");
|
||||||
|
} else {
|
||||||
|
node.removeAttribute("auto-hyphens");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the anchor node into the open or closed state, depending
|
* Sets the anchor node into the open or closed state, depending
|
||||||
* on the state of the panel.
|
* on the state of the panel.
|
||||||
|
|
|
@ -68,6 +68,7 @@ skip-if = os == "linux"
|
||||||
[browser_948985_non_removable_defaultArea.js]
|
[browser_948985_non_removable_defaultArea.js]
|
||||||
[browser_952963_areaType_getter_no_area.js]
|
[browser_952963_areaType_getter_no_area.js]
|
||||||
[browser_956602_remove_special_widget.js]
|
[browser_956602_remove_special_widget.js]
|
||||||
|
[browser_962884_opt_in_disable_hyphens.js]
|
||||||
[browser_963639_customizing_attribute_non_customizable_toolbar.js]
|
[browser_963639_customizing_attribute_non_customizable_toolbar.js]
|
||||||
[browser_967000_button_charEncoding.js]
|
[browser_967000_button_charEncoding.js]
|
||||||
[browser_967000_button_feeds.js]
|
[browser_967000_button_feeds.js]
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
add_task(function() {
|
||||||
|
const kNormalLabel = "Character Encoding";
|
||||||
|
CustomizableUI.addWidgetToArea("characterencoding-button", CustomizableUI.AREA_NAVBAR);
|
||||||
|
let characterEncoding = document.getElementById("characterencoding-button");
|
||||||
|
const kOriginalLabel = characterEncoding.getAttribute("label");
|
||||||
|
characterEncoding.setAttribute("label", "\u00ad" + kNormalLabel);
|
||||||
|
CustomizableUI.addWidgetToArea("characterencoding-button", CustomizableUI.AREA_PANEL);
|
||||||
|
|
||||||
|
yield PanelUI.show();
|
||||||
|
|
||||||
|
is(characterEncoding.getAttribute("auto-hyphens"), "off",
|
||||||
|
"Hyphens should be disabled if the ­ character is present in the label");
|
||||||
|
let multilineText = document.getAnonymousElementByAttribute(characterEncoding, "class", "toolbarbutton-multiline-text");
|
||||||
|
let multilineTextCS = getComputedStyle(multilineText);
|
||||||
|
is(multilineTextCS.MozHyphens, "manual", "-moz-hyphens should be set to manual when the ­ character is present.")
|
||||||
|
|
||||||
|
let hiddenPanelPromise = promisePanelHidden(window);
|
||||||
|
PanelUI.toggle();
|
||||||
|
yield hiddenPanelPromise;
|
||||||
|
|
||||||
|
characterEncoding.setAttribute("label", kNormalLabel);
|
||||||
|
|
||||||
|
yield PanelUI.show();
|
||||||
|
|
||||||
|
isnot(characterEncoding.getAttribute("auto-hyphens"), "off",
|
||||||
|
"Hyphens should not be disabled if the ­ character is not present in the label");
|
||||||
|
multilineText = document.getAnonymousElementByAttribute(characterEncoding, "class", "toolbarbutton-multiline-text");
|
||||||
|
let multilineTextCS = getComputedStyle(multilineText);
|
||||||
|
is(multilineTextCS.MozHyphens, "auto", "-moz-hyphens should be set to auto by default.")
|
||||||
|
|
||||||
|
hiddenPanelPromise = promisePanelHidden(window);
|
||||||
|
PanelUI.toggle();
|
||||||
|
yield hiddenPanelPromise;
|
||||||
|
|
||||||
|
characterEncoding.setAttribute("label", "\u00ad" + kNormalLabel);
|
||||||
|
CustomizableUI.removeWidgetFromArea("characterencoding-button");
|
||||||
|
yield startCustomizing();
|
||||||
|
|
||||||
|
isnot(characterEncoding.getAttribute("auto-hyphens"), "off",
|
||||||
|
"Hyphens should not be disabled when the widget is in the palette");
|
||||||
|
|
||||||
|
gCustomizeMode.addToPanel(characterEncoding);
|
||||||
|
is(characterEncoding.getAttribute("auto-hyphens"), "off",
|
||||||
|
"Hyphens should be disabled if the ­ character is present in the label in customization mode");
|
||||||
|
let multilineText = document.getAnonymousElementByAttribute(characterEncoding, "class", "toolbarbutton-multiline-text");
|
||||||
|
let multilineTextCS = getComputedStyle(multilineText);
|
||||||
|
is(multilineTextCS.MozHyphens, "manual", "-moz-hyphens should be set to manual when the ­ character is present in customization mode.")
|
||||||
|
|
||||||
|
yield endCustomizing();
|
||||||
|
|
||||||
|
CustomizableUI.addWidgetToArea("characterencoding-button", CustomizableUI.AREA_NAVBAR);
|
||||||
|
ok(!characterEncoding.hasAttribute("auto-hyphens"),
|
||||||
|
"Removing the widget from the panel should remove the auto-hyphens attribute");
|
||||||
|
|
||||||
|
characterEncoding.setAttribute("label", kOriginalLabel);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function asyncCleanup() {
|
||||||
|
yield endCustomizing();
|
||||||
|
yield resetCustomization();
|
||||||
|
});
|
|
@ -128,6 +128,15 @@
|
||||||
#endif
|
#endif
|
||||||
<stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
|
<stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
|
||||||
|
|
||||||
|
<hbox id="header-advanced"
|
||||||
|
class="header"
|
||||||
|
hidden="true"
|
||||||
|
data-category="paneAdvanced">
|
||||||
|
<image class="header-icon"/>
|
||||||
|
<label class="header-name"
|
||||||
|
value="&paneAdvanced.title;"/>
|
||||||
|
</hbox>
|
||||||
|
|
||||||
<tabbox id="advancedPrefs" flex="1"
|
<tabbox id="advancedPrefs" flex="1"
|
||||||
data-category="paneAdvanced" hidden="true"
|
data-category="paneAdvanced" hidden="true"
|
||||||
onselect="gAdvancedPane.tabSelectionChanged();">
|
onselect="gAdvancedPane.tabSelectionChanged();">
|
||||||
|
|
|
@ -55,7 +55,19 @@
|
||||||
<key key="&focusSearch2.key;" modifiers="accel" oncommand="gApplicationsPane.focusFilterBox();"/>
|
<key key="&focusSearch2.key;" modifiers="accel" oncommand="gApplicationsPane.focusFilterBox();"/>
|
||||||
</keyset>
|
</keyset>
|
||||||
|
|
||||||
<vbox data-category="paneApplications" hidden="true" flex="1">
|
<hbox id="header-application"
|
||||||
|
class="header"
|
||||||
|
hidden="true"
|
||||||
|
data-category="paneApplications">
|
||||||
|
<image class="header-icon"/>
|
||||||
|
<label class="header-name"
|
||||||
|
value="&paneApplications.title;"/>
|
||||||
|
</hbox>
|
||||||
|
|
||||||
|
<vbox id="applicationsContent"
|
||||||
|
data-category="paneApplications"
|
||||||
|
hidden="true"
|
||||||
|
flex="1">
|
||||||
<hbox>
|
<hbox>
|
||||||
<textbox id="filter" flex="1"
|
<textbox id="filter" flex="1"
|
||||||
type="search"
|
type="search"
|
||||||
|
|
|
@ -21,6 +21,15 @@
|
||||||
<script type="application/javascript"
|
<script type="application/javascript"
|
||||||
src="chrome://browser/content/preferences/in-content/content.js"/>
|
src="chrome://browser/content/preferences/in-content/content.js"/>
|
||||||
|
|
||||||
|
<hbox id="header-content"
|
||||||
|
class="header"
|
||||||
|
hidden="true"
|
||||||
|
data-category="paneContent">
|
||||||
|
<image class="header-icon"/>
|
||||||
|
<label class="header-name"
|
||||||
|
value="&paneContent.title;"/>
|
||||||
|
</hbox>
|
||||||
|
|
||||||
<groupbox id="miscGroup" data-category="paneContent" hidden="true">
|
<groupbox id="miscGroup" data-category="paneContent" hidden="true">
|
||||||
<caption label="&popups.label;"/>
|
<caption label="&popups.label;"/>
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,14 @@
|
||||||
#endif
|
#endif
|
||||||
</preferences>
|
</preferences>
|
||||||
|
|
||||||
|
<hbox id="header-general"
|
||||||
|
class="header"
|
||||||
|
data-category="paneGeneral">
|
||||||
|
<image class="header-icon"/>
|
||||||
|
<label class="header-name"
|
||||||
|
value="&paneGeneral.title;"/>
|
||||||
|
</hbox>
|
||||||
|
|
||||||
<!-- Startup -->
|
<!-- Startup -->
|
||||||
<groupbox id="startupGroup" data-category="paneGeneral">
|
<groupbox id="startupGroup" data-category="paneGeneral">
|
||||||
<caption label="&startup.label;"/>
|
<caption label="&startup.label;"/>
|
||||||
|
|
|
@ -32,10 +32,8 @@ function init_all() {
|
||||||
|
|
||||||
let categories = document.getElementById("categories");
|
let categories = document.getElementById("categories");
|
||||||
categories.addEventListener("select", event => gotoPref(event.target.value));
|
categories.addEventListener("select", event => gotoPref(event.target.value));
|
||||||
window.addEventListener("popstate", event => selectCategory(event.state));
|
|
||||||
|
|
||||||
if (history.length > 1 && history.state) {
|
if (history.length > 1 && history.state) {
|
||||||
updateCommands();
|
|
||||||
selectCategory(history.state);
|
selectCategory(history.state);
|
||||||
} else {
|
} else {
|
||||||
history.replaceState("paneGeneral", document.title);
|
history.replaceState("paneGeneral", document.title);
|
||||||
|
@ -49,39 +47,10 @@ function selectCategory(name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function gotoPref(page) {
|
function gotoPref(page) {
|
||||||
if (history.state != page) {
|
window.history.replaceState(page, document.title);
|
||||||
window.history.pushState(page, document.title);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateCommands();
|
|
||||||
search(page, "data-category");
|
search(page, "data-category");
|
||||||
}
|
}
|
||||||
|
|
||||||
function cmd_back() {
|
|
||||||
window.history.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
function cmd_forward() {
|
|
||||||
window.history.forward();
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateCommands() {
|
|
||||||
document.getElementById("back-btn").disabled = !canGoBack();
|
|
||||||
document.getElementById("forward-btn").disabled = !canGoForward();
|
|
||||||
}
|
|
||||||
|
|
||||||
function canGoBack() {
|
|
||||||
return window.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIWebNavigation)
|
|
||||||
.canGoBack;
|
|
||||||
}
|
|
||||||
|
|
||||||
function canGoForward() {
|
|
||||||
return window.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIWebNavigation)
|
|
||||||
.canGoForward;
|
|
||||||
}
|
|
||||||
|
|
||||||
function search(aQuery, aAttribute) {
|
function search(aQuery, aAttribute) {
|
||||||
let elements = document.getElementById("mainPrefPane").children;
|
let elements = document.getElementById("mainPrefPane").children;
|
||||||
for (let element of elements) {
|
for (let element of elements) {
|
||||||
|
|
|
@ -74,15 +74,6 @@
|
||||||
src="chrome://browser/locale/preferences/applicationManager.properties"/>
|
src="chrome://browser/locale/preferences/applicationManager.properties"/>
|
||||||
</stringbundleset>
|
</stringbundleset>
|
||||||
|
|
||||||
<hbox id="header">
|
|
||||||
<toolbarbutton id="back-btn" class="nav-button header-button"
|
|
||||||
oncommand="cmd_back()" tooltiptext="&buttonBack.tooltip;"
|
|
||||||
disabled="true"/>
|
|
||||||
<toolbarbutton id="forward-btn" class="nav-button header-button"
|
|
||||||
oncommand="cmd_forward()" tooltiptext="&buttonForward.tooltip;"
|
|
||||||
disabled="true"/>
|
|
||||||
</hbox>
|
|
||||||
|
|
||||||
<hbox flex="1">
|
<hbox flex="1">
|
||||||
|
|
||||||
<!-- category list -->
|
<!-- category list -->
|
||||||
|
|
|
@ -65,6 +65,15 @@
|
||||||
|
|
||||||
</preferences>
|
</preferences>
|
||||||
|
|
||||||
|
<hbox id="header-privacy"
|
||||||
|
class="header"
|
||||||
|
hidden="true"
|
||||||
|
data-category="panePrivacy">
|
||||||
|
<image class="header-icon"/>
|
||||||
|
<label class="header-name"
|
||||||
|
value="&panePrivacy.title;"/>
|
||||||
|
</hbox>
|
||||||
|
|
||||||
<!-- Tracking -->
|
<!-- Tracking -->
|
||||||
<groupbox id="trackingGroup" data-category="panePrivacy" hidden="true" align="start">
|
<groupbox id="trackingGroup" data-category="panePrivacy" hidden="true" align="start">
|
||||||
<caption label="&tracking.label;"/>
|
<caption label="&tracking.label;"/>
|
||||||
|
|
|
@ -30,6 +30,15 @@
|
||||||
|
|
||||||
</preferences>
|
</preferences>
|
||||||
|
|
||||||
|
<hbox id="header-security"
|
||||||
|
class="header"
|
||||||
|
hidden="true"
|
||||||
|
data-category="paneSecurity">
|
||||||
|
<image class="header-icon"/>
|
||||||
|
<label class="header-name"
|
||||||
|
value="&paneSecurity.title;"/>
|
||||||
|
</hbox>
|
||||||
|
|
||||||
<!-- addons, forgery (phishing) UI -->
|
<!-- addons, forgery (phishing) UI -->
|
||||||
<groupbox id="addonsPhishingGroup" data-category="paneSecurity" hidden="true">
|
<groupbox id="addonsPhishingGroup" data-category="paneSecurity" hidden="true">
|
||||||
<caption label="&general.label;"/>
|
<caption label="&general.label;"/>
|
||||||
|
|
|
@ -28,6 +28,15 @@
|
||||||
<script type="application/javascript"
|
<script type="application/javascript"
|
||||||
src="chrome://browser/content/sync/utils.js"/>
|
src="chrome://browser/content/sync/utils.js"/>
|
||||||
|
|
||||||
|
<hbox id="header-sync"
|
||||||
|
class="header"
|
||||||
|
hidden="true"
|
||||||
|
data-category="paneSync">
|
||||||
|
<image class="header-icon"/>
|
||||||
|
<label class="header-name"
|
||||||
|
value="&paneSync.title;"/>
|
||||||
|
</hbox>
|
||||||
|
|
||||||
<deck id="weavePrefsDeck" data-category="paneSync" hidden="true">
|
<deck id="weavePrefsDeck" data-category="paneSync" hidden="true">
|
||||||
<vbox id="noAccount" align="center">
|
<vbox id="noAccount" align="center">
|
||||||
<spacer flex="1"/>
|
<spacer flex="1"/>
|
||||||
|
|
|
@ -23,6 +23,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
|
||||||
"resource:///modules/sessionstore/SessionStore.jsm");
|
"resource:///modules/sessionstore/SessionStore.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "SessionFile",
|
XPCOMUtils.defineLazyModuleGetter(this, "SessionFile",
|
||||||
"resource:///modules/sessionstore/SessionFile.jsm");
|
"resource:///modules/sessionstore/SessionFile.jsm");
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||||
|
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||||
|
|
||||||
// Minimal interval between two save operations (in milliseconds).
|
// Minimal interval between two save operations (in milliseconds).
|
||||||
XPCOMUtils.defineLazyGetter(this, "gInterval", function () {
|
XPCOMUtils.defineLazyGetter(this, "gInterval", function () {
|
||||||
|
@ -41,14 +43,6 @@ XPCOMUtils.defineLazyGetter(this, "gInterval", function () {
|
||||||
return Services.prefs.getIntPref(PREF);
|
return Services.prefs.getIntPref(PREF);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Wrap a string as a nsISupports.
|
|
||||||
function createSupportsString(data) {
|
|
||||||
let string = Cc["@mozilla.org/supports-string;1"]
|
|
||||||
.createInstance(Ci.nsISupportsString);
|
|
||||||
string.data = data;
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify observers about a given topic with a given subject.
|
// Notify observers about a given topic with a given subject.
|
||||||
function notify(subject, topic) {
|
function notify(subject, topic) {
|
||||||
Services.obs.notifyObservers(subject, topic, "");
|
Services.obs.notifyObservers(subject, topic, "");
|
||||||
|
@ -192,6 +186,14 @@ let SessionSaverInternal = {
|
||||||
// Cancel any pending timeouts.
|
// Cancel any pending timeouts.
|
||||||
this.cancel();
|
this.cancel();
|
||||||
|
|
||||||
|
if (PrivateBrowsingUtils.permanentPrivateBrowsing) {
|
||||||
|
// Don't save (or even collect) anything in permanent private
|
||||||
|
// browsing mode
|
||||||
|
|
||||||
|
this.updateLastSaveTime();
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
stopWatchStart("COLLECT_DATA_MS", "COLLECT_DATA_LONGEST_OP_MS");
|
stopWatchStart("COLLECT_DATA_MS", "COLLECT_DATA_LONGEST_OP_MS");
|
||||||
let state = SessionStore.getCurrentState(forceUpdateAllWindows);
|
let state = SessionStore.getCurrentState(forceUpdateAllWindows);
|
||||||
PrivacyFilter.filterPrivateWindowsAndTabs(state);
|
PrivacyFilter.filterPrivateWindowsAndTabs(state);
|
||||||
|
@ -242,19 +244,13 @@ let SessionSaverInternal = {
|
||||||
* Write the given state object to disk.
|
* Write the given state object to disk.
|
||||||
*/
|
*/
|
||||||
_writeState: function (state) {
|
_writeState: function (state) {
|
||||||
|
// Inform observers
|
||||||
|
notify(null, "sessionstore-state-write");
|
||||||
|
|
||||||
stopWatchStart("SERIALIZE_DATA_MS", "SERIALIZE_DATA_LONGEST_OP_MS", "WRITE_STATE_LONGEST_OP_MS");
|
stopWatchStart("SERIALIZE_DATA_MS", "SERIALIZE_DATA_LONGEST_OP_MS", "WRITE_STATE_LONGEST_OP_MS");
|
||||||
let data = JSON.stringify(state);
|
let data = JSON.stringify(state);
|
||||||
stopWatchFinish("SERIALIZE_DATA_MS", "SERIALIZE_DATA_LONGEST_OP_MS");
|
stopWatchFinish("SERIALIZE_DATA_MS", "SERIALIZE_DATA_LONGEST_OP_MS");
|
||||||
|
|
||||||
// Give observers a chance to modify session data.
|
|
||||||
data = this._notifyObserversBeforeStateWrite(data);
|
|
||||||
|
|
||||||
// Don't touch the file if an observer has deleted all state data.
|
|
||||||
if (!data) {
|
|
||||||
stopWatchCancel("WRITE_STATE_LONGEST_OP_MS");
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
// We update the time stamp before writing so that we don't write again
|
// We update the time stamp before writing so that we don't write again
|
||||||
// too soon, if saving is requested before the write completes. Without
|
// too soon, if saving is requested before the write completes. Without
|
||||||
// this update we may save repeatedly if actions cause a runDelayed
|
// this update we may save repeatedly if actions cause a runDelayed
|
||||||
|
@ -275,14 +271,4 @@ let SessionSaverInternal = {
|
||||||
|
|
||||||
return promise;
|
return promise;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify sessionstore-state-write observer and give them a
|
|
||||||
* chance to modify session data before we'll write it to disk.
|
|
||||||
*/
|
|
||||||
_notifyObserversBeforeStateWrite: function (data) {
|
|
||||||
let stateString = createSupportsString(data);
|
|
||||||
notify(stateString, "sessionstore-state-write");
|
|
||||||
return stateString.data;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1058,16 +1058,26 @@ let SessionStoreInternal = {
|
||||||
// recently something was closed.
|
// recently something was closed.
|
||||||
winData.closedAt = Date.now();
|
winData.closedAt = Date.now();
|
||||||
|
|
||||||
// Save the window if it has multiple tabs or a single saveable tab and
|
// Save non-private windows if they have at
|
||||||
// it's not private.
|
// least one saveable tab or are the last window.
|
||||||
if (!winData.isPrivate) {
|
if (!winData.isPrivate) {
|
||||||
// Remove any open private tabs the window may contain.
|
// Remove any open private tabs the window may contain.
|
||||||
PrivacyFilter.filterPrivateTabs(winData);
|
PrivacyFilter.filterPrivateTabs(winData);
|
||||||
|
|
||||||
let hasSingleTabToSave =
|
// Determine whether the window has any tabs worth saving.
|
||||||
winData.tabs.length == 1 && this._shouldSaveTabState(winData.tabs[0]);
|
let hasSaveableTabs = winData.tabs.some(this._shouldSaveTabState);
|
||||||
|
|
||||||
if (hasSingleTabToSave || winData.tabs.length > 1) {
|
// When closing windows one after the other until Firefox quits, we
|
||||||
|
// will move those closed in series back to the "open windows" bucket
|
||||||
|
// before writing to disk. If however there is only a single window
|
||||||
|
// with tabs we deem not worth saving then we might end up with a
|
||||||
|
// random closed or even a pop-up window re-opened. To prevent that
|
||||||
|
// we explicitly allow saving an "empty" window state.
|
||||||
|
let isLastWindow =
|
||||||
|
Object.keys(this._windows).length == 1 &&
|
||||||
|
!this._closedWindows.some(win => win._shouldRestore || false);
|
||||||
|
|
||||||
|
if (hasSaveableTabs || isLastWindow) {
|
||||||
// we don't want to save the busy state
|
// we don't want to save the busy state
|
||||||
delete winData.busy;
|
delete winData.busy;
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,6 @@ skip-if = true
|
||||||
[browser_394759_purge.js]
|
[browser_394759_purge.js]
|
||||||
[browser_423132.js]
|
[browser_423132.js]
|
||||||
[browser_447951.js]
|
[browser_447951.js]
|
||||||
[browser_448741.js]
|
|
||||||
[browser_454908.js]
|
[browser_454908.js]
|
||||||
[browser_456342.js]
|
[browser_456342.js]
|
||||||
[browser_461634.js]
|
[browser_461634.js]
|
||||||
|
|
|
@ -75,15 +75,13 @@ function test() {
|
||||||
// Wait for the sessionstore.js file to be written before going on.
|
// Wait for the sessionstore.js file to be written before going on.
|
||||||
// Note: we don't wait for the complete event, since if asyncCopy fails we
|
// Note: we don't wait for the complete event, since if asyncCopy fails we
|
||||||
// would timeout.
|
// would timeout.
|
||||||
Services.obs.addObserver(function (aSubject, aTopic, aData) {
|
waitForSaveState(function(writing) {
|
||||||
Services.obs.removeObserver(arguments.callee, aTopic);
|
ok(writing, "sessionstore.js is being written");
|
||||||
info("sessionstore.js is being written");
|
|
||||||
|
|
||||||
closedWindowCount = ss.getClosedWindowCount();
|
closedWindowCount = ss.getClosedWindowCount();
|
||||||
is(closedWindowCount, 0, "Correctly set window count");
|
is(closedWindowCount, 0, "Correctly set window count");
|
||||||
|
|
||||||
executeSoon(aCallback);
|
executeSoon(aCallback);
|
||||||
}, "sessionstore-state-write", false);
|
});
|
||||||
|
|
||||||
// Remove the sessionstore.js file before setting the interval to 0
|
// Remove the sessionstore.js file before setting the interval to 0
|
||||||
let profilePath = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
let profilePath = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||||
|
|
|
@ -1,62 +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/. */
|
|
||||||
|
|
||||||
function test() {
|
|
||||||
/** Test for Bug 448741 **/
|
|
||||||
|
|
||||||
waitForExplicitFinish();
|
|
||||||
|
|
||||||
let uniqueName = "bug 448741";
|
|
||||||
let uniqueValue = "as good as unique: " + Date.now();
|
|
||||||
|
|
||||||
// set a unique value on a new, blank tab
|
|
||||||
var tab = gBrowser.addTab();
|
|
||||||
tab.linkedBrowser.stop();
|
|
||||||
ss.setTabValue(tab, uniqueName, uniqueValue);
|
|
||||||
let valueWasCleaned = false;
|
|
||||||
|
|
||||||
// prevent our value from being written to disk
|
|
||||||
function cleaningObserver(aSubject, aTopic, aData) {
|
|
||||||
ok(aTopic == "sessionstore-state-write", "observed correct topic?");
|
|
||||||
ok(aSubject instanceof Ci.nsISupportsString, "subject is a string?");
|
|
||||||
ok(aSubject.data.indexOf(uniqueValue) > -1, "data contains our value?");
|
|
||||||
|
|
||||||
// find the data for the newly added tab and delete it
|
|
||||||
let state = JSON.parse(aSubject.data);
|
|
||||||
state.windows.forEach(function (winData) {
|
|
||||||
winData.tabs.forEach(function (tabData) {
|
|
||||||
if (tabData.extData && uniqueName in tabData.extData &&
|
|
||||||
tabData.extData[uniqueName] == uniqueValue) {
|
|
||||||
delete tabData.extData[uniqueName];
|
|
||||||
valueWasCleaned = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
ok(valueWasCleaned, "found and removed the specific tab value");
|
|
||||||
aSubject.data = JSON.stringify(state);
|
|
||||||
Services.obs.removeObserver(cleaningObserver, aTopic);
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure that all later observers don't see that value any longer
|
|
||||||
function checkingObserver(aSubject, aTopic, aData) {
|
|
||||||
ok(valueWasCleaned && aSubject instanceof Ci.nsISupportsString,
|
|
||||||
"ready to check the cleaned state?");
|
|
||||||
ok(aSubject.data.indexOf(uniqueValue) == -1, "data no longer contains our value?");
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
gBrowser.removeTab(tab);
|
|
||||||
Services.obs.removeObserver(checkingObserver, aTopic);
|
|
||||||
if (gPrefService.prefHasUserValue("browser.sessionstore.interval"))
|
|
||||||
gPrefService.clearUserPref("browser.sessionstore.interval");
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
// last added observers are invoked first
|
|
||||||
Services.obs.addObserver(checkingObserver, "sessionstore-state-write", false);
|
|
||||||
Services.obs.addObserver(cleaningObserver, "sessionstore-state-write", false);
|
|
||||||
|
|
||||||
// trigger an immediate save operation
|
|
||||||
gPrefService.setIntPref("browser.sessionstore.interval", 0);
|
|
||||||
}
|
|
|
@ -20,11 +20,12 @@ function testBug600545() {
|
||||||
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
||||||
});
|
});
|
||||||
|
|
||||||
// This tests the following use case:
|
// This tests the following use case: When multiple windows are open
|
||||||
// When multiple windows are open and browser.sessionstore.resume_from_crash
|
// and browser.sessionstore.resume_from_crash preference is false,
|
||||||
// preference is false, tab session data for non-active window is stripped for
|
// tab session data for non-active window is stripped for non-pinned
|
||||||
// non-pinned tabs. This occurs after "sessionstore-state-write" fires which
|
// tabs. This occurs after "sessionstore-state-write-complete"
|
||||||
// will only fire in this case if there is at least one pinned tab.
|
// fires which will only fire in this case if there is at least one
|
||||||
|
// pinned tab.
|
||||||
let state = { windows: [
|
let state = { windows: [
|
||||||
{
|
{
|
||||||
tabs: [
|
tabs: [
|
||||||
|
|
|
@ -1,125 +1,86 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
let newWin;
|
add_task(function* setup() {
|
||||||
let newTab;
|
|
||||||
|
|
||||||
function test() {
|
|
||||||
/** Test for Bug 625016 - Restore windows closed in succession to quit (non-OSX only) **/
|
/** Test for Bug 625016 - Restore windows closed in succession to quit (non-OSX only) **/
|
||||||
|
|
||||||
// We'll test this by opening a new window, waiting for the save event, then
|
// We'll test this by opening a new window, waiting for the save
|
||||||
// closing that window. We'll observe the "sessionstore-state-write" notification
|
// event, then closing that window. We'll observe the
|
||||||
// and check that the state contains no _closedWindows. We'll then add a new
|
// "sessionstore-state-write-complete" notification and check that
|
||||||
// tab and make sure that the state following that was reset and the closed
|
// the state contains no _closedWindows. We'll then add a new tab
|
||||||
// window is now in _closedWindows.
|
// and make sure that the state following that was reset and the
|
||||||
|
// closed window is now in _closedWindows.
|
||||||
|
|
||||||
waitForExplicitFinish();
|
|
||||||
requestLongerTimeout(2);
|
requestLongerTimeout(2);
|
||||||
|
|
||||||
// We speed up the interval between session saves to ensure that the test
|
yield forceSaveState();
|
||||||
// runs quickly.
|
|
||||||
Services.prefs.setIntPref("browser.sessionstore.interval", 4000);
|
|
||||||
registerCleanupFunction(function () {
|
|
||||||
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
|
||||||
});
|
|
||||||
|
|
||||||
waitForSaveState(setup);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
// We'll clear all closed windows to make sure our state is clean
|
// We'll clear all closed windows to make sure our state is clean
|
||||||
// forgetClosedWindow doesn't trigger a delayed save
|
// forgetClosedWindow doesn't trigger a delayed save
|
||||||
while (ss.getClosedWindowCount()) {
|
while (ss.getClosedWindowCount()) {
|
||||||
ss.forgetClosedWindow(0);
|
ss.forgetClosedWindow(0);
|
||||||
}
|
}
|
||||||
is(ss.getClosedWindowCount(), 0, "starting with no closed windows");
|
is(ss.getClosedWindowCount(), 0, "starting with no closed windows");
|
||||||
|
});
|
||||||
|
|
||||||
// Open a new window, which should trigger a save event soon.
|
add_task(function* new_window() {
|
||||||
waitForSaveState(onSaveState);
|
let newWin;
|
||||||
newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:rights");
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSaveState() {
|
|
||||||
try {
|
try {
|
||||||
ss.getWindowValue(newWin, "foobar");
|
newWin = yield promiseNewWindowLoaded();
|
||||||
} catch (e) {
|
let tab = newWin.gBrowser.addTab("http://example.com/browser_625016.js?" + Math.random());
|
||||||
// The window is untracked which means that the saveState() call isn't the
|
yield promiseBrowserLoaded(tab.linkedBrowser);
|
||||||
// one we're waiting for. It's most likely been triggered by an async
|
|
||||||
// collection running in the background.
|
|
||||||
waitForSaveState(onSaveState);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Double check that we have no closed windows
|
// Double check that we have no closed windows
|
||||||
is(ss.getClosedWindowCount(), 0, "no closed windows on first save");
|
is(ss.getClosedWindowCount(), 0, "no closed windows on first save");
|
||||||
|
|
||||||
Services.obs.addObserver(observe1, "sessionstore-state-write", false);
|
yield promiseWindowClosed(newWin);
|
||||||
|
newWin = null;
|
||||||
|
|
||||||
// Now close the new window, which should trigger another save event
|
let state = JSON.parse((yield promiseSaveFileContents()));
|
||||||
newWin.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
function observe1(aSubject, aTopic, aData) {
|
|
||||||
info("observe1: " + aTopic);
|
|
||||||
switch (aTopic) {
|
|
||||||
case "sessionstore-state-write":
|
|
||||||
aSubject.QueryInterface(Ci.nsISupportsString);
|
|
||||||
let state = JSON.parse(aSubject.data);
|
|
||||||
is(state.windows.length, 2,
|
is(state.windows.length, 2,
|
||||||
"observe1: 2 windows in data being writted to disk");
|
"observe1: 2 windows in data written to disk");
|
||||||
is(state._closedWindows.length, 0,
|
is(state._closedWindows.length, 0,
|
||||||
"observe1: no closed windows in data being writted to disk");
|
"observe1: no closed windows in data written to disk");
|
||||||
|
|
||||||
// The API still treats the closed window as closed, so ensure that window is there
|
// The API still treats the closed window as closed, so ensure that window is there
|
||||||
is(ss.getClosedWindowCount(), 1,
|
is(ss.getClosedWindowCount(), 1,
|
||||||
"observe1: 1 closed window according to API");
|
"observe1: 1 closed window according to API");
|
||||||
Services.obs.removeObserver(observe1, "sessionstore-state-write");
|
} finally {
|
||||||
Services.obs.addObserver(observe1, "sessionstore-state-write-complete", false);
|
if (newWin) {
|
||||||
break;
|
yield promiseWindowClosed(newWin);
|
||||||
case "sessionstore-state-write-complete":
|
|
||||||
Services.obs.removeObserver(observe1, "sessionstore-state-write-complete");
|
|
||||||
openTab();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
yield forceSaveState();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function observe2(aSubject, aTopic, aData) {
|
// We'll open a tab, which should trigger another state save which would wipe
|
||||||
info("observe2: " + aTopic);
|
// the _shouldRestore attribute from the closed window
|
||||||
switch (aTopic) {
|
add_task(function* new_tab() {
|
||||||
case "sessionstore-state-write":
|
let newTab;
|
||||||
aSubject.QueryInterface(Ci.nsISupportsString);
|
try {
|
||||||
let state = JSON.parse(aSubject.data);
|
newTab = gBrowser.addTab("about:mozilla");
|
||||||
|
|
||||||
|
let state = JSON.parse((yield promiseSaveFileContents()));
|
||||||
is(state.windows.length, 1,
|
is(state.windows.length, 1,
|
||||||
"observe2: 1 window in data being writted to disk");
|
"observe2: 1 window in data being written to disk");
|
||||||
is(state._closedWindows.length, 1,
|
is(state._closedWindows.length, 1,
|
||||||
"observe2: 1 closed window in data being writted to disk");
|
"observe2: 1 closed window in data being written to disk");
|
||||||
|
|
||||||
// The API still treats the closed window as closed, so ensure that window is there
|
// The API still treats the closed window as closed, so ensure that window is there
|
||||||
is(ss.getClosedWindowCount(), 1,
|
is(ss.getClosedWindowCount(), 1,
|
||||||
"observe2: 1 closed window according to API");
|
"observe2: 1 closed window according to API");
|
||||||
Services.obs.removeObserver(observe2, "sessionstore-state-write");
|
} finally {
|
||||||
Services.obs.addObserver(observe2, "sessionstore-state-write-complete", false);
|
|
||||||
break;
|
|
||||||
case "sessionstore-state-write-complete":
|
|
||||||
Services.obs.removeObserver(observe2, "sessionstore-state-write-complete");
|
|
||||||
done();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We'll open a tab, which should trigger another state save which would wipe
|
|
||||||
// the _shouldRestore attribute from the closed window
|
|
||||||
function openTab() {
|
|
||||||
Services.obs.addObserver(observe2, "sessionstore-state-write", false);
|
|
||||||
newTab = gBrowser.addTab("about:mozilla");
|
|
||||||
}
|
|
||||||
|
|
||||||
function done() {
|
|
||||||
gBrowser.removeTab(newTab);
|
gBrowser.removeTab(newTab);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
add_task(function* done() {
|
||||||
// The API still represents the closed window as closed, so we can clear it
|
// The API still represents the closed window as closed, so we can clear it
|
||||||
// with the API, but just to make sure...
|
// with the API, but just to make sure...
|
||||||
is(ss.getClosedWindowCount(), 1, "1 closed window according to API");
|
// is(ss.getClosedWindowCount(), 1, "1 closed window according to API");
|
||||||
|
while (ss.getClosedWindowCount()) {
|
||||||
ss.forgetClosedWindow(0);
|
ss.forgetClosedWindow(0);
|
||||||
executeSoon(finish);
|
|
||||||
}
|
}
|
||||||
|
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
||||||
|
});
|
||||||
|
|
|
@ -162,15 +162,9 @@ function waitForWindowClose(aWin, aCallback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function forceWriteState(aCallback) {
|
function forceWriteState(aCallback) {
|
||||||
Services.obs.addObserver(function observe(aSubject, aTopic, aData) {
|
return promiseSaveFileContents().then(function(data) {
|
||||||
if (aTopic == "sessionstore-state-write") {
|
aCallback(JSON.parse(data));
|
||||||
Services.obs.removeObserver(observe, aTopic);
|
});
|
||||||
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
|
||||||
aSubject.QueryInterface(Ci.nsISupportsString);
|
|
||||||
aCallback(JSON.parse(aSubject.data));
|
|
||||||
}
|
|
||||||
}, "sessionstore-state-write", false);
|
|
||||||
Services.prefs.setIntPref("browser.sessionstore.interval", 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testOnWindow(aIsPrivate, aCallback) {
|
function testOnWindow(aIsPrivate, aCallback) {
|
||||||
|
|
|
@ -24,43 +24,9 @@ let gDecoder = new TextDecoder();
|
||||||
let gSSData;
|
let gSSData;
|
||||||
let gSSBakData;
|
let gSSBakData;
|
||||||
|
|
||||||
// Wait for a state write to complete and then execute a callback.
|
|
||||||
function waitForSaveStateComplete(aSaveStateCallback) {
|
|
||||||
let topic = "sessionstore-state-write-complete";
|
|
||||||
|
|
||||||
function observer() {
|
|
||||||
Services.prefs.clearUserPref(PREF_SS_INTERVAL);
|
|
||||||
Services.obs.removeObserver(observer, topic);
|
|
||||||
executeSoon(function taskCallback() {
|
|
||||||
Task.spawn(aSaveStateCallback);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Services.obs.addObserver(observer, topic, false);
|
add_task(function* testAfterFirstWrite() {
|
||||||
}
|
|
||||||
|
|
||||||
// Register next test callback and trigger state saving change.
|
|
||||||
function nextTest(testFunc) {
|
|
||||||
waitForSaveStateComplete(testFunc);
|
|
||||||
|
|
||||||
// We set the interval for session store state saves to be zero
|
|
||||||
// to cause a save ASAP.
|
|
||||||
Services.prefs.setIntPref(PREF_SS_INTERVAL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
registerCleanupFunction(function() {
|
|
||||||
// Cleaning up after the test: removing the sessionstore.bak file.
|
|
||||||
Task.spawn(function cleanupTask() {
|
|
||||||
yield OS.File.remove(backupPath);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function test() {
|
|
||||||
waitForExplicitFinish();
|
|
||||||
nextTest(testAfterFirstWrite);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testAfterFirstWrite() {
|
|
||||||
// Ensure sessionstore.bak is not created. We start with a clean
|
// Ensure sessionstore.bak is not created. We start with a clean
|
||||||
// profile so there was nothing to move to sessionstore.bak before
|
// profile so there was nothing to move to sessionstore.bak before
|
||||||
// initially writing sessionstore.js
|
// initially writing sessionstore.js
|
||||||
|
@ -78,10 +44,10 @@ function testAfterFirstWrite() {
|
||||||
// and a backup would not be triggered again.
|
// and a backup would not be triggered again.
|
||||||
yield OS.File.move(path, backupPath);
|
yield OS.File.move(path, backupPath);
|
||||||
|
|
||||||
nextTest(testReadBackup);
|
yield forceSaveState();
|
||||||
}
|
});
|
||||||
|
|
||||||
function testReadBackup() {
|
add_task(function* testReadBackup() {
|
||||||
// Ensure sessionstore.bak is finally created.
|
// Ensure sessionstore.bak is finally created.
|
||||||
let ssExists = yield OS.File.exists(path);
|
let ssExists = yield OS.File.exists(path);
|
||||||
let ssBackupExists = yield OS.File.exists(backupPath);
|
let ssBackupExists = yield OS.File.exists(backupPath);
|
||||||
|
@ -114,10 +80,10 @@ function testReadBackup() {
|
||||||
is(ssDataRead, gSSBakData,
|
is(ssDataRead, gSSBakData,
|
||||||
"SessionFile.read read sessionstore.bak correctly.");
|
"SessionFile.read read sessionstore.bak correctly.");
|
||||||
|
|
||||||
nextTest(testBackupUnchanged);
|
yield forceSaveState();
|
||||||
}
|
});
|
||||||
|
|
||||||
function testBackupUnchanged() {
|
add_task(function* testBackupUnchanged() {
|
||||||
// Ensure sessionstore.bak is backed up only once.
|
// Ensure sessionstore.bak is backed up only once.
|
||||||
|
|
||||||
// Read sessionstore.bak data.
|
// Read sessionstore.bak data.
|
||||||
|
@ -125,6 +91,9 @@ function testBackupUnchanged() {
|
||||||
let ssBakData = gDecoder.decode(array);
|
let ssBakData = gDecoder.decode(array);
|
||||||
// Ensure the sessionstore.bak did not change.
|
// Ensure the sessionstore.bak did not change.
|
||||||
is(ssBakData, gSSBakData, "sessionstore.bak is unchanged.");
|
is(ssBakData, gSSBakData, "sessionstore.bak is unchanged.");
|
||||||
|
});
|
||||||
|
|
||||||
executeSoon(finish);
|
add_task(function* cleanup() {
|
||||||
}
|
// Cleaning up after the test: removing the sessionstore.bak file.
|
||||||
|
yield OS.File.remove(backupPath);
|
||||||
|
});
|
||||||
|
|
|
@ -243,12 +243,7 @@ function waitForTopic(aTopic, aTimeout, aCallback) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait until session restore has finished collecting its data and is
|
* Wait until session restore has finished collecting its data and is
|
||||||
* getting ready to write that data ("sessionstore-state-write").
|
* has written that data ("sessionstore-state-write-complete").
|
||||||
*
|
|
||||||
* This function is meant to be called immediately after the code
|
|
||||||
* that will trigger the saving.
|
|
||||||
*
|
|
||||||
* Note that this does not wait for the disk write to be complete.
|
|
||||||
*
|
*
|
||||||
* @param {function} aCallback If sessionstore-state-write is sent
|
* @param {function} aCallback If sessionstore-state-write is sent
|
||||||
* within buffering interval + 100 ms, the callback is passed |true|,
|
* within buffering interval + 100 ms, the callback is passed |true|,
|
||||||
|
@ -257,7 +252,7 @@ function waitForTopic(aTopic, aTimeout, aCallback) {
|
||||||
function waitForSaveState(aCallback) {
|
function waitForSaveState(aCallback) {
|
||||||
let timeout = 100 +
|
let timeout = 100 +
|
||||||
Services.prefs.getIntPref("browser.sessionstore.interval");
|
Services.prefs.getIntPref("browser.sessionstore.interval");
|
||||||
return waitForTopic("sessionstore-state-write", timeout, aCallback);
|
return waitForTopic("sessionstore-state-write-complete", timeout, aCallback);
|
||||||
}
|
}
|
||||||
function promiseSaveState() {
|
function promiseSaveState() {
|
||||||
let deferred = Promise.defer();
|
let deferred = Promise.defer();
|
||||||
|
@ -272,22 +267,30 @@ function promiseSaveState() {
|
||||||
function forceSaveState() {
|
function forceSaveState() {
|
||||||
let promise = promiseSaveState();
|
let promise = promiseSaveState();
|
||||||
const PREF = "browser.sessionstore.interval";
|
const PREF = "browser.sessionstore.interval";
|
||||||
|
let original = Services.prefs.getIntPref(PREF);
|
||||||
// Set interval to an arbitrary non-0 duration
|
// Set interval to an arbitrary non-0 duration
|
||||||
// to ensure that setting it to 0 will notify observers
|
// to ensure that setting it to 0 will notify observers
|
||||||
Services.prefs.setIntPref(PREF, 1000);
|
Services.prefs.setIntPref(PREF, 1000);
|
||||||
Services.prefs.setIntPref(PREF, 0);
|
Services.prefs.setIntPref(PREF, 0);
|
||||||
return promise.then(
|
return promise.then(
|
||||||
function onSuccess(x) {
|
function onSuccess(x) {
|
||||||
Services.prefs.clearUserPref(PREF);
|
Services.prefs.setIntPref(PREF, original);
|
||||||
return x;
|
return x;
|
||||||
},
|
},
|
||||||
function onError(x) {
|
function onError(x) {
|
||||||
Services.prefs.clearUserPref(PREF);
|
Services.prefs.setIntPref(PREF, original);
|
||||||
throw x;
|
throw x;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function promiseSaveFileContents() {
|
||||||
|
let promise = forceSaveState();
|
||||||
|
return promise.then(function() {
|
||||||
|
return OS.File.read(OS.Path.join(OS.Constants.Path.profileDir, "sessionstore.js"), { encoding: "utf-8" });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function whenBrowserLoaded(aBrowser, aCallback = next, ignoreSubFrames = true) {
|
function whenBrowserLoaded(aBrowser, aCallback = next, ignoreSubFrames = true) {
|
||||||
aBrowser.addEventListener("load", function onLoad(event) {
|
aBrowser.addEventListener("load", function onLoad(event) {
|
||||||
if (!ignoreSubFrames || event.target == aBrowser.contentDocument) {
|
if (!ignoreSubFrames || event.target == aBrowser.contentDocument) {
|
||||||
|
@ -321,6 +324,11 @@ function whenWindowLoaded(aWindow, aCallback = next) {
|
||||||
});
|
});
|
||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
|
function promiseWindowLoaded(aWindow) {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
whenWindowLoaded(aWindow, deferred.resolve);
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
function whenTabRestored(aTab, aCallback = next) {
|
function whenTabRestored(aTab, aCallback = next) {
|
||||||
aTab.addEventListener("SSTabRestored", function onRestored(aEvent) {
|
aTab.addEventListener("SSTabRestored", function onRestored(aEvent) {
|
||||||
|
|
|
@ -110,6 +110,7 @@ skip-if = true # Bug 922422
|
||||||
[browser_tabview_bug641802.js]
|
[browser_tabview_bug641802.js]
|
||||||
[browser_tabview_bug642793.js]
|
[browser_tabview_bug642793.js]
|
||||||
[browser_tabview_bug643392.js]
|
[browser_tabview_bug643392.js]
|
||||||
|
skip-if = os == 'linux'&&debug # bug 989083
|
||||||
[browser_tabview_bug644097.js]
|
[browser_tabview_bug644097.js]
|
||||||
[browser_tabview_bug648882.js]
|
[browser_tabview_bug648882.js]
|
||||||
skip-if = true # Bug 752862
|
skip-if = true # Bug 752862
|
||||||
|
|
|
@ -6,13 +6,13 @@ const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionSto
|
||||||
let state = {
|
let state = {
|
||||||
windows: [{
|
windows: [{
|
||||||
tabs: [{
|
tabs: [{
|
||||||
entries: [{ url: "about:blank" }],
|
entries: [{ url: "about:robots" }],
|
||||||
hidden: true,
|
hidden: true,
|
||||||
extData: {"tabview-tab": '{"url":"about:blank","groupID":1,"bounds":{"left":20,"top":20,"width":20,"height":20}}'}
|
extData: {"tabview-tab": '{"url":"about:robots","groupID":1,"bounds":{"left":20,"top":20,"width":20,"height":20}}'}
|
||||||
},{
|
},{
|
||||||
entries: [{ url: "about:blank" }],
|
entries: [{ url: "about:robots" }],
|
||||||
hidden: false,
|
hidden: false,
|
||||||
extData: {"tabview-tab": '{"url":"about:blank","groupID":2,"bounds":{"left":20,"top":20,"width":20,"height":20}}'},
|
extData: {"tabview-tab": '{"url":"about:robots","groupID":2,"bounds":{"left":20,"top":20,"width":20,"height":20}}'},
|
||||||
}],
|
}],
|
||||||
selected: 2,
|
selected: 2,
|
||||||
extData: {
|
extData: {
|
||||||
|
|
|
@ -4,13 +4,13 @@
|
||||||
let state = {
|
let state = {
|
||||||
windows: [{
|
windows: [{
|
||||||
tabs: [{
|
tabs: [{
|
||||||
entries: [{ url: "about:blank" }],
|
entries: [{ url: "about:robots" }],
|
||||||
hidden: true,
|
hidden: true,
|
||||||
extData: {"tabview-tab": '{"url":"about:blank","groupID":1,"bounds":{"left":120,"top":20,"width":20,"height":20}}'}
|
extData: {"tabview-tab": '{"url":"about:robots","groupID":1,"bounds":{"left":120,"top":20,"width":20,"height":20}}'}
|
||||||
},{
|
},{
|
||||||
entries: [{ url: "about:blank" }],
|
entries: [{ url: "about:robots" }],
|
||||||
hidden: false,
|
hidden: false,
|
||||||
extData: {"tabview-tab": '{"url":"about:blank","groupID":2,"bounds":{"left":20,"top":20,"width":20,"height":20}}'},
|
extData: {"tabview-tab": '{"url":"about:robots","groupID":2,"bounds":{"left":20,"top":20,"width":20,"height":20}}'},
|
||||||
}],
|
}],
|
||||||
selected: 2,
|
selected: 2,
|
||||||
extData: {
|
extData: {
|
||||||
|
|
|
@ -8,23 +8,23 @@ function test() {
|
||||||
let newState = {
|
let newState = {
|
||||||
windows: [{
|
windows: [{
|
||||||
tabs: [{
|
tabs: [{
|
||||||
entries: [{ url: "about:blank" }],
|
entries: [{ url: "about:robots" }],
|
||||||
hidden: true,
|
hidden: true,
|
||||||
attributes: {},
|
attributes: {},
|
||||||
extData: {
|
extData: {
|
||||||
"tabview-tab":
|
"tabview-tab":
|
||||||
'{"bounds":{"left":21,"top":29,"width":204,"height":153},' +
|
'{"bounds":{"left":21,"top":29,"width":204,"height":153},' +
|
||||||
'"userSize":null,"url":"about:blank","groupID":1,' +
|
'"userSize":null,"url":"about:robots","groupID":1,' +
|
||||||
'"imageData":null,"title":null}'
|
'"imageData":null,"title":null}'
|
||||||
}
|
}
|
||||||
},{
|
},{
|
||||||
entries: [{ url: "about:blank" }],
|
entries: [{ url: "about:robots" }],
|
||||||
hidden: false,
|
hidden: false,
|
||||||
attributes: {},
|
attributes: {},
|
||||||
extData: {
|
extData: {
|
||||||
"tabview-tab":
|
"tabview-tab":
|
||||||
'{"bounds":{"left":315,"top":29,"width":111,"height":84},' +
|
'{"bounds":{"left":315,"top":29,"width":111,"height":84},' +
|
||||||
'"userSize":null,"url":"about:blank","groupID":2,' +
|
'"userSize":null,"url":"about:robots","groupID":2,' +
|
||||||
'"imageData":null,"title":null}'
|
'"imageData":null,"title":null}'
|
||||||
},
|
},
|
||||||
}],
|
}],
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
ac_add_options --enable-debug
|
ac_add_options --enable-debug
|
||||||
ac_add_options --enable-trace-malloc
|
ac_add_options --enable-trace-malloc
|
||||||
ac_add_options --enable-signmar
|
ac_add_options --enable-signmar
|
||||||
ac_add_options --enable-metro
|
|
||||||
|
|
||||||
# Needed to enable breakpad in application.ini
|
# Needed to enable breakpad in application.ini
|
||||||
export MOZILLA_OFFICIAL=1
|
export MOZILLA_OFFICIAL=1
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
||||||
ac_add_options --enable-update-packaging
|
ac_add_options --enable-update-packaging
|
||||||
ac_add_options --with-l10n-base=../../l10n
|
ac_add_options --with-l10n-base=../../l10n
|
||||||
ac_add_options --enable-metro
|
|
||||||
ac_add_options --with-windows-version=601
|
ac_add_options --with-windows-version=601
|
||||||
|
|
||||||
export MOZILLA_OFFICIAL=1
|
export MOZILLA_OFFICIAL=1
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
||||||
ac_add_options --enable-update-packaging
|
ac_add_options --enable-update-packaging
|
||||||
ac_add_options --enable-jemalloc
|
ac_add_options --enable-jemalloc
|
||||||
ac_add_options --enable-metro
|
|
||||||
if [ -f /c/builds/gapi.data ]; then
|
if [ -f /c/builds/gapi.data ]; then
|
||||||
_gapi_keyfile=/c/builds/gapi.data
|
_gapi_keyfile=/c/builds/gapi.data
|
||||||
else
|
else
|
||||||
|
|
|
@ -6,7 +6,6 @@ ac_add_options --host=x86_64-pc-mingw32
|
||||||
ac_add_options --enable-debug
|
ac_add_options --enable-debug
|
||||||
ac_add_options --enable-trace-malloc
|
ac_add_options --enable-trace-malloc
|
||||||
ac_add_options --enable-signmar
|
ac_add_options --enable-signmar
|
||||||
ac_add_options --enable-metro
|
|
||||||
|
|
||||||
# Needed to enable breakpad in application.ini
|
# Needed to enable breakpad in application.ini
|
||||||
export MOZILLA_OFFICIAL=1
|
export MOZILLA_OFFICIAL=1
|
||||||
|
|
|
@ -2175,22 +2175,6 @@ Object.defineProperties(window, {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method for parsing a resource URI, like
|
|
||||||
* `resource://gre/modules/commonjs/sdk/tabs.js`, and pulling out `sdk/tabs.js`
|
|
||||||
* if it's in the SDK, or `null` otherwise.
|
|
||||||
*
|
|
||||||
* @param string url
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
function getSDKModuleName(url) {
|
|
||||||
let match = (url || "").match(/^resource:\/\/gre\/modules\/commonjs\/(.*)/);
|
|
||||||
if (match) {
|
|
||||||
return match[1];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method for debugging.
|
* Helper method for debugging.
|
||||||
* @param string
|
* @param string
|
||||||
|
|
|
@ -11,6 +11,11 @@ const SAMPLE_SIZE = 50; // no of lines
|
||||||
const INDENT_COUNT_THRESHOLD = 5; // percentage
|
const INDENT_COUNT_THRESHOLD = 5; // percentage
|
||||||
const CHARACTER_LIMIT = 250; // line character limit
|
const CHARACTER_LIMIT = 250; // line character limit
|
||||||
|
|
||||||
|
// Maps known URLs to friendly source group names
|
||||||
|
const KNOWN_SOURCE_GROUPS = {
|
||||||
|
"Add-on SDK": "resource://gre/modules/commonjs/",
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functions handling the sources UI.
|
* Functions handling the sources UI.
|
||||||
*/
|
*/
|
||||||
|
@ -49,6 +54,15 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
||||||
showArrows: true
|
showArrows: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Sort known source groups towards the end of the list
|
||||||
|
this.widget.groupSortPredicate = function(a, b) {
|
||||||
|
if ((a in KNOWN_SOURCE_GROUPS) == (b in KNOWN_SOURCE_GROUPS)) {
|
||||||
|
return a.localeCompare(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (a in KNOWN_SOURCE_GROUPS) ? 1 : -1;
|
||||||
|
};
|
||||||
|
|
||||||
this.emptyText = L10N.getStr("noSourcesText");
|
this.emptyText = L10N.getStr("noSourcesText");
|
||||||
this._blackBoxCheckboxTooltip = L10N.getStr("blackBoxCheckboxTooltip");
|
this._blackBoxCheckboxTooltip = L10N.getStr("blackBoxCheckboxTooltip");
|
||||||
|
|
||||||
|
@ -132,12 +146,6 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
||||||
let group = SourceUtils.getSourceGroup(url);
|
let group = SourceUtils.getSourceGroup(url);
|
||||||
let unicodeUrl = NetworkHelper.convertToUnicode(unescape(fullUrl));
|
let unicodeUrl = NetworkHelper.convertToUnicode(unescape(fullUrl));
|
||||||
|
|
||||||
let sdkModuleName = getSDKModuleName(url);
|
|
||||||
if (sdkModuleName) {
|
|
||||||
label = sdkModuleName;
|
|
||||||
group = "Add-on SDK";
|
|
||||||
}
|
|
||||||
|
|
||||||
let contents = document.createElement("label");
|
let contents = document.createElement("label");
|
||||||
contents.className = "plain dbg-source-item";
|
contents.className = "plain dbg-source-item";
|
||||||
contents.setAttribute("value", label);
|
contents.setAttribute("value", label);
|
||||||
|
@ -1560,7 +1568,17 @@ let SourceUtils = {
|
||||||
return cachedLabel;
|
return cachedLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
let sourceLabel = this.trimUrl(aUrl);
|
let sourceLabel = null;
|
||||||
|
|
||||||
|
for (let name of Object.keys(KNOWN_SOURCE_GROUPS)) {
|
||||||
|
if (aUrl.startsWith(KNOWN_SOURCE_GROUPS[name])) {
|
||||||
|
sourceLabel = aUrl.substring(KNOWN_SOURCE_GROUPS[name].length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sourceLabel) {
|
||||||
|
sourceLabel = this.trimUrl(aUrl);
|
||||||
|
}
|
||||||
let unicodeLabel = NetworkHelper.convertToUnicode(unescape(sourceLabel));
|
let unicodeLabel = NetworkHelper.convertToUnicode(unescape(sourceLabel));
|
||||||
this._labelsCache.set(aUrl, unicodeLabel);
|
this._labelsCache.set(aUrl, unicodeLabel);
|
||||||
return unicodeLabel;
|
return unicodeLabel;
|
||||||
|
@ -1583,14 +1601,20 @@ let SourceUtils = {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Use an nsIURL to parse all the url path parts.
|
// Use an nsIURL to parse all the url path parts.
|
||||||
let url = aUrl.split(" -> ").pop();
|
var uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL);
|
||||||
var uri = Services.io.newURI(url, null, null).QueryInterface(Ci.nsIURL);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// This doesn't look like a url, or nsIURL can't handle it.
|
// This doesn't look like a url, or nsIURL can't handle it.
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
let groupLabel = uri.prePath;
|
let groupLabel = uri.prePath;
|
||||||
|
|
||||||
|
for (let name of Object.keys(KNOWN_SOURCE_GROUPS)) {
|
||||||
|
if (aUrl.startsWith(KNOWN_SOURCE_GROUPS[name])) {
|
||||||
|
groupLabel = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let unicodeLabel = NetworkHelper.convertToUnicode(unescape(groupLabel));
|
let unicodeLabel = NetworkHelper.convertToUnicode(unescape(groupLabel));
|
||||||
this._groupsCache.set(aUrl, unicodeLabel)
|
this._groupsCache.set(aUrl, unicodeLabel)
|
||||||
return unicodeLabel;
|
return unicodeLabel;
|
||||||
|
|
|
@ -5,7 +5,18 @@
|
||||||
|
|
||||||
const ADDON4_URL = EXAMPLE_URL + "addon4.xpi";
|
const ADDON4_URL = EXAMPLE_URL + "addon4.xpi";
|
||||||
|
|
||||||
let gAddon, gClient, gThreadClient, gDebugger, gSources;
|
let gAddon, gClient, gThreadClient, gDebugger, gSources, gTitle;
|
||||||
|
|
||||||
|
function onMessage(event) {
|
||||||
|
try {
|
||||||
|
let json = JSON.parse(event.data);
|
||||||
|
switch (json.name) {
|
||||||
|
case "toolbox-title":
|
||||||
|
gTitle = json.data.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch(e) { Cu.reportError(e); }
|
||||||
|
}
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
Task.spawn(function () {
|
Task.spawn(function () {
|
||||||
|
@ -18,6 +29,8 @@ function test() {
|
||||||
let iframe = document.createElement("iframe");
|
let iframe = document.createElement("iframe");
|
||||||
document.documentElement.appendChild(iframe);
|
document.documentElement.appendChild(iframe);
|
||||||
|
|
||||||
|
window.addEventListener("message", onMessage);
|
||||||
|
|
||||||
let transport = DebuggerServer.connectPipe();
|
let transport = DebuggerServer.connectPipe();
|
||||||
gClient = new DebuggerClient(transport);
|
gClient = new DebuggerClient(transport);
|
||||||
|
|
||||||
|
@ -43,6 +56,7 @@ function test() {
|
||||||
yield closeConnection();
|
yield closeConnection();
|
||||||
yield debuggerPanel._toolbox.destroy();
|
yield debuggerPanel._toolbox.destroy();
|
||||||
iframe.remove();
|
iframe.remove();
|
||||||
|
window.removeEventListener("message", onMessage);
|
||||||
finish();
|
finish();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -62,7 +76,7 @@ function testSources(expectSecondModule) {
|
||||||
gThreadClient.getSources(({sources}) => {
|
gThreadClient.getSources(({sources}) => {
|
||||||
ok(sources.length, "retrieved sources");
|
ok(sources.length, "retrieved sources");
|
||||||
|
|
||||||
sources.forEach(source => {
|
for (let source of sources) {
|
||||||
let url = source.url.split(" -> ").pop();
|
let url = source.url.split(" -> ").pop();
|
||||||
let { label, group } = gSources.getItemByValue(source.url).attachment;
|
let { label, group } = gSources.getItemByValue(source.url).attachment;
|
||||||
|
|
||||||
|
@ -81,12 +95,19 @@ function testSources(expectSecondModule) {
|
||||||
} else {
|
} else {
|
||||||
ok(false, "Saw an unexpected source: " + url);
|
ok(false, "Saw an unexpected source: " + url);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
ok(foundAddonModule, "found JS module for the addon in the list");
|
ok(foundAddonModule, "found JS module for the addon in the list");
|
||||||
is(foundAddonModule2, expectSecondModule, "saw the second addon module");
|
is(foundAddonModule2, expectSecondModule, "saw the second addon module");
|
||||||
ok(foundAddonBootstrap, "found bootstrap script for the addon in the list");
|
ok(foundAddonBootstrap, "found bootstrap script for the addon in the list");
|
||||||
|
|
||||||
|
is(gTitle, "Debugger - Test add-on with JS Modules", "Saw the right toolbox title.");
|
||||||
|
|
||||||
|
let groups = gDebugger.document.querySelectorAll(".side-menu-widget-group-title .name");
|
||||||
|
is(groups[0].value, "jar:", "Add-on bootstrap should be the first group");
|
||||||
|
is(groups[1].value, "resource://browser_dbg_addon4", "Add-on code should be the second group");
|
||||||
|
is(groups.length, 2, "Should be only two groups.");
|
||||||
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,18 @@
|
||||||
|
|
||||||
const ADDON3_URL = EXAMPLE_URL + "addon3.xpi";
|
const ADDON3_URL = EXAMPLE_URL + "addon3.xpi";
|
||||||
|
|
||||||
let gAddon, gClient, gThreadClient, gDebugger, gSources;
|
let gAddon, gClient, gThreadClient, gDebugger, gSources, gTitle;
|
||||||
|
|
||||||
|
function onMessage(event) {
|
||||||
|
try {
|
||||||
|
let json = JSON.parse(event.data);
|
||||||
|
switch (json.name) {
|
||||||
|
case "toolbox-title":
|
||||||
|
gTitle = json.data.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch(e) { Cu.reportError(e); }
|
||||||
|
}
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
Task.spawn(function () {
|
Task.spawn(function () {
|
||||||
|
@ -19,6 +30,8 @@ function test() {
|
||||||
let iframe = document.createElement("iframe");
|
let iframe = document.createElement("iframe");
|
||||||
document.documentElement.appendChild(iframe);
|
document.documentElement.appendChild(iframe);
|
||||||
|
|
||||||
|
window.addEventListener("message", onMessage);
|
||||||
|
|
||||||
let transport = DebuggerServer.connectPipe();
|
let transport = DebuggerServer.connectPipe();
|
||||||
gClient = new DebuggerClient(transport);
|
gClient = new DebuggerClient(transport);
|
||||||
|
|
||||||
|
@ -37,6 +50,7 @@ function test() {
|
||||||
yield closeConnection();
|
yield closeConnection();
|
||||||
yield debuggerPanel._toolbox.destroy();
|
yield debuggerPanel._toolbox.destroy();
|
||||||
iframe.remove();
|
iframe.remove();
|
||||||
|
window.removeEventListener("message", onMessage);
|
||||||
finish();
|
finish();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -56,7 +70,7 @@ function testSources() {
|
||||||
gThreadClient.getSources(({sources}) => {
|
gThreadClient.getSources(({sources}) => {
|
||||||
ok(sources.length, "retrieved sources");
|
ok(sources.length, "retrieved sources");
|
||||||
|
|
||||||
sources.forEach(source => {
|
for (let source of sources) {
|
||||||
let url = source.url.split(" -> ").pop();
|
let url = source.url.split(" -> ").pop();
|
||||||
info(source.url + "\n\n\n" + url);
|
info(source.url + "\n\n\n" + url);
|
||||||
let { label, group } = gSources.getItemByValue(source.url).attachment;
|
let { label, group } = gSources.getItemByValue(source.url).attachment;
|
||||||
|
@ -80,7 +94,7 @@ function testSources() {
|
||||||
} else {
|
} else {
|
||||||
ok(false, "Saw an unexpected source: " + url);
|
ok(false, "Saw an unexpected source: " + url);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
ok(foundAddonModule, "found code for the addon in the list");
|
ok(foundAddonModule, "found code for the addon in the list");
|
||||||
ok(foundAddonBootstrap, "found bootstrap for the addon in the list");
|
ok(foundAddonBootstrap, "found bootstrap for the addon in the list");
|
||||||
|
@ -88,6 +102,14 @@ function testSources() {
|
||||||
// built-in browser SDK modules
|
// built-in browser SDK modules
|
||||||
ok(foundSDKModule > 10, "SDK modules are listed");
|
ok(foundSDKModule > 10, "SDK modules are listed");
|
||||||
|
|
||||||
|
is(gTitle, "Debugger - browser_dbg_addon3", "Saw the right toolbox title.");
|
||||||
|
|
||||||
|
let groups = gDebugger.document.querySelectorAll(".side-menu-widget-group-title .name");
|
||||||
|
is(groups[0].value, "jar:", "Add-on bootstrap should be the first group");
|
||||||
|
is(groups[1].value, "resource://jid1-ami3akps3baaeg-at-jetpack", "Add-on code should be the second group");
|
||||||
|
is(groups[2].value, "Add-on SDK", "Add-on SDK should be the third group");
|
||||||
|
is(groups.length, 3, "Should be only three groups.");
|
||||||
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -504,9 +504,9 @@ function initDebugger(aTarget, aWindow) {
|
||||||
function initAddonDebugger(aClient, aUrl, aFrame) {
|
function initAddonDebugger(aClient, aUrl, aFrame) {
|
||||||
info("Initializing an addon debugger panel.");
|
info("Initializing an addon debugger panel.");
|
||||||
|
|
||||||
return getAddonActorForUrl(aClient, aUrl).then(({actor}) => {
|
return getAddonActorForUrl(aClient, aUrl).then((addonActor) => {
|
||||||
let targetOptions = {
|
let targetOptions = {
|
||||||
form: { addonActor: actor },
|
form: { addonActor: addonActor.actor, title: addonActor.name },
|
||||||
client: aClient,
|
client: aClient,
|
||||||
chrome: true
|
chrome: true
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,7 +37,7 @@ function connect() {
|
||||||
if (addonID) {
|
if (addonID) {
|
||||||
gClient.listAddons(({addons}) => {
|
gClient.listAddons(({addons}) => {
|
||||||
let addonActor = addons.filter(addon => addon.id === addonID).pop();
|
let addonActor = addons.filter(addon => addon.id === addonID).pop();
|
||||||
openToolbox({ addonActor: addonActor.actor });
|
openToolbox({ addonActor: addonActor.actor, title: addonActor.name });
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
gClient.listTabs(openToolbox);
|
gClient.listTabs(openToolbox);
|
||||||
|
|
|
@ -878,7 +878,9 @@ Toolbox.prototype = {
|
||||||
*/
|
*/
|
||||||
focusConsoleInput: function() {
|
focusConsoleInput: function() {
|
||||||
let hud = this.getPanel("webconsole").hud;
|
let hud = this.getPanel("webconsole").hud;
|
||||||
|
if (hud && hud.jsterm) {
|
||||||
hud.jsterm.inputNode.focus();
|
hud.jsterm.inputNode.focus();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -964,7 +966,7 @@ Toolbox.prototype = {
|
||||||
toolName = toolboxStrings("toolbox.defaultTitle");
|
toolName = toolboxStrings("toolbox.defaultTitle");
|
||||||
}
|
}
|
||||||
let title = toolboxStrings("toolbox.titleTemplate",
|
let title = toolboxStrings("toolbox.titleTemplate",
|
||||||
toolName, this.target.url);
|
toolName, this.target.url || this.target.name);
|
||||||
this._host.setTitle(title);
|
this._host.setTitle(title);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -299,6 +299,9 @@ MarkupView.prototype = {
|
||||||
this.markNodeAsSelected(selection.nodeFront);
|
this.markNodeAsSelected(selection.nodeFront);
|
||||||
}
|
}
|
||||||
done();
|
done();
|
||||||
|
}, (e) => {
|
||||||
|
console.error(e);
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.unmarkSelectedNode();
|
this.unmarkSelectedNode();
|
||||||
|
@ -863,9 +866,11 @@ MarkupView.prototype = {
|
||||||
let parent = node.parentNode();
|
let parent = node.parentNode();
|
||||||
if (!container.elt.parentNode) {
|
if (!container.elt.parentNode) {
|
||||||
let parentContainer = this._containers.get(parent);
|
let parentContainer = this._containers.get(parent);
|
||||||
|
if (parentContainer) {
|
||||||
parentContainer.childrenDirty = true;
|
parentContainer.childrenDirty = true;
|
||||||
this._updateChildren(parentContainer, {expand: node});
|
this._updateChildren(parentContainer, {expand: node});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
node = parent;
|
node = parent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,10 +66,15 @@ this.SideMenuWidget = function SideMenuWidget(aNode, aOptions={}) {
|
||||||
|
|
||||||
SideMenuWidget.prototype = {
|
SideMenuWidget.prototype = {
|
||||||
/**
|
/**
|
||||||
* Specifies if groups in this container should be sorted alphabetically.
|
* Specifies if groups in this container should be sorted.
|
||||||
*/
|
*/
|
||||||
sortedGroups: true,
|
sortedGroups: true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The comparator used to sort groups.
|
||||||
|
*/
|
||||||
|
groupSortPredicate: function(a, b) a.localeCompare(b),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies that the container viewport should be "stuck" to the
|
* Specifies that the container viewport should be "stuck" to the
|
||||||
* bottom. That is, the container is automatically scrolled down to
|
* bottom. That is, the container is automatically scrolled down to
|
||||||
|
@ -342,7 +347,7 @@ SideMenuWidget.prototype = {
|
||||||
});
|
});
|
||||||
|
|
||||||
this._groupsByName.set(aName, group);
|
this._groupsByName.set(aName, group);
|
||||||
group.insertSelfAt(this.sortedGroups ? group.findExpectedIndexForSelf() : -1);
|
group.insertSelfAt(this.sortedGroups ? group.findExpectedIndexForSelf(this.groupSortPredicate) : -1);
|
||||||
|
|
||||||
return group;
|
return group;
|
||||||
},
|
},
|
||||||
|
@ -484,14 +489,14 @@ SideMenuGroup.prototype = {
|
||||||
* @return number
|
* @return number
|
||||||
* The expected index.
|
* The expected index.
|
||||||
*/
|
*/
|
||||||
findExpectedIndexForSelf: function() {
|
findExpectedIndexForSelf: function(sortPredicate) {
|
||||||
let identifier = this.identifier;
|
let identifier = this.identifier;
|
||||||
let groupsArray = this._orderedGroupElementsArray;
|
let groupsArray = this._orderedGroupElementsArray;
|
||||||
|
|
||||||
for (let group of groupsArray) {
|
for (let group of groupsArray) {
|
||||||
let name = group.getAttribute("name");
|
let name = group.getAttribute("name");
|
||||||
if (name > identifier && // Insertion sort at its best :)
|
if (sortPredicate(name, identifier) > 0 && // Insertion sort at its best :)
|
||||||
!name.contains(identifier)) { // Least significat group should be last.
|
!name.contains(identifier)) { // Least significant group should be last.
|
||||||
return groupsArray.indexOf(group);
|
return groupsArray.indexOf(group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ function testMenuFilterButton(aCategory) {
|
||||||
// Turn all the filters off, if they were on.
|
// Turn all the filters off, if they were on.
|
||||||
let menuItem = firstMenuItem;
|
let menuItem = firstMenuItem;
|
||||||
while (menuItem != null) {
|
while (menuItem != null) {
|
||||||
if (isChecked(menuItem)) {
|
if (menuItem.hasAttribute("prefKey") && isChecked(menuItem)) {
|
||||||
chooseMenuItem(menuItem);
|
chooseMenuItem(menuItem);
|
||||||
}
|
}
|
||||||
menuItem = menuItem.nextSibling;
|
menuItem = menuItem.nextSibling;
|
||||||
|
@ -89,10 +89,12 @@ function testMenuFilterButton(aCategory) {
|
||||||
menuItem = firstMenuItem;
|
menuItem = firstMenuItem;
|
||||||
while (menuItem) {
|
while (menuItem) {
|
||||||
let prefKey = menuItem.getAttribute("prefKey");
|
let prefKey = menuItem.getAttribute("prefKey");
|
||||||
|
if (prefKey) {
|
||||||
ok(!isChecked(menuItem), "menu item " + prefKey + " for category " +
|
ok(!isChecked(menuItem), "menu item " + prefKey + " for category " +
|
||||||
aCategory + " is no longer checked after clicking the button");
|
aCategory + " is no longer checked after clicking the button");
|
||||||
ok(!hud.ui.filterPrefs[prefKey], prefKey + " messages are " +
|
ok(!hud.ui.filterPrefs[prefKey], prefKey + " messages are " +
|
||||||
"off after clicking the button");
|
"off after clicking the button");
|
||||||
|
}
|
||||||
menuItem = menuItem.nextSibling;
|
menuItem = menuItem.nextSibling;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +129,8 @@ function testMenuFilterButton(aCategory) {
|
||||||
while (menuItem) {
|
while (menuItem) {
|
||||||
// The csslog menu item is already unchecked at this point.
|
// The csslog menu item is already unchecked at this point.
|
||||||
// Make sure it is not selected. See bug 971798.
|
// Make sure it is not selected. See bug 971798.
|
||||||
if (menuItem.getAttribute("prefKey") != "csslog") {
|
prefKey = menuItem.getAttribute("prefKey");
|
||||||
|
if (prefKey && prefKey != "csslog") {
|
||||||
chooseMenuItem(menuItem);
|
chooseMenuItem(menuItem);
|
||||||
}
|
}
|
||||||
menuItem = menuItem.nextSibling;
|
menuItem = menuItem.nextSibling;
|
||||||
|
@ -164,7 +167,7 @@ function testIsolateFilterButton(aCategory) {
|
||||||
aCategory + " should not be checked after isolating for " + aCategory);
|
aCategory + " should not be checked after isolating for " + aCategory);
|
||||||
ok(!hud.ui.filterPrefs[prefKey], prefKey + " messages should be " +
|
ok(!hud.ui.filterPrefs[prefKey], prefKey + " messages should be " +
|
||||||
"turned off after isolating for " + aCategory);
|
"turned off after isolating for " + aCategory);
|
||||||
} else {
|
} else if (prefKey) {
|
||||||
ok(isChecked(item), "menu item " + prefKey + " for category " +
|
ok(isChecked(item), "menu item " + prefKey + " for category " +
|
||||||
aCategory + " is checked after isolating for " + aCategory);
|
aCategory + " is checked after isolating for " + aCategory);
|
||||||
ok(hud.ui.filterPrefs[prefKey], prefKey + " messages are " +
|
ok(hud.ui.filterPrefs[prefKey], prefKey + " messages are " +
|
||||||
|
@ -184,10 +187,12 @@ function testIsolateFilterButton(aCategory) {
|
||||||
menuItems = filterButton.querySelectorAll("menuitem");
|
menuItems = filterButton.querySelectorAll("menuitem");
|
||||||
Array.forEach(menuItems, (item) => {
|
Array.forEach(menuItems, (item) => {
|
||||||
let prefKey = item.getAttribute("prefKey");
|
let prefKey = item.getAttribute("prefKey");
|
||||||
|
if (prefKey) {
|
||||||
ok(!isChecked(item), "menu item " + prefKey + " for category " +
|
ok(!isChecked(item), "menu item " + prefKey + " for category " +
|
||||||
aCategory + " is unchecked after isolating for " + aCategory);
|
aCategory + " is unchecked after isolating for " + aCategory);
|
||||||
ok(!hud.ui.filterPrefs[prefKey], prefKey + " messages are " +
|
ok(!hud.ui.filterPrefs[prefKey], prefKey + " messages are " +
|
||||||
"turned off after isolating for " + aCategory);
|
"turned off after isolating for " + aCategory);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Turn all the filters on again by clicking the button.
|
// Turn all the filters on again by clicking the button.
|
||||||
|
|
|
@ -53,6 +53,7 @@ function runSelectionTests(aInspector) {
|
||||||
inspector.toolbox.once("picker-started", () => {
|
inspector.toolbox.once("picker-started", () => {
|
||||||
info("Picker mode started, now clicking on H1 to select that node");
|
info("Picker mode started, now clicking on H1 to select that node");
|
||||||
executeSoon(() => {
|
executeSoon(() => {
|
||||||
|
h1.scrollIntoView();
|
||||||
EventUtils.synthesizeMouseAtCenter(h1, {}, content);
|
EventUtils.synthesizeMouseAtCenter(h1, {}, content);
|
||||||
inspector.toolbox.once("picker-stopped", () => {
|
inspector.toolbox.once("picker-stopped", () => {
|
||||||
info("Picker mode stopped, H1 selected, now switching to the console");
|
info("Picker mode stopped, H1 selected, now switching to the console");
|
||||||
|
|
|
@ -401,6 +401,11 @@ WebConsoleFrame.prototype = {
|
||||||
*/
|
*/
|
||||||
setSaveRequestAndResponseBodies:
|
setSaveRequestAndResponseBodies:
|
||||||
function WCF_setSaveRequestAndResponseBodies(aValue) {
|
function WCF_setSaveRequestAndResponseBodies(aValue) {
|
||||||
|
if (!this.webConsoleClient) {
|
||||||
|
// Don't continue if the webconsole disconnected.
|
||||||
|
return promise.resolve(null);
|
||||||
|
}
|
||||||
|
|
||||||
let deferred = promise.defer();
|
let deferred = promise.defer();
|
||||||
let newValue = !!aValue;
|
let newValue = !!aValue;
|
||||||
let toSet = {
|
let toSet = {
|
||||||
|
|
|
@ -104,7 +104,7 @@ function configureLogging() {
|
||||||
gLogger = Log.repository.getLogger("Browser.Experiments");
|
gLogger = Log.repository.getLogger("Browser.Experiments");
|
||||||
gLogger.addAppender(new Log.ConsoleAppender(new Log.BasicFormatter()));
|
gLogger.addAppender(new Log.ConsoleAppender(new Log.BasicFormatter()));
|
||||||
}
|
}
|
||||||
gLogger.level = gPrefs.get(PREF_LOGGING_LEVEL, 50);
|
gLogger.level = gPrefs.get(PREF_LOGGING_LEVEL, Log.Level.Warn);
|
||||||
|
|
||||||
let logDumping = gPrefs.get(PREF_LOGGING_DUMP, false);
|
let logDumping = gPrefs.get(PREF_LOGGING_DUMP, false);
|
||||||
if (logDumping != gLogDumping) {
|
if (logDumping != gLogDumping) {
|
||||||
|
@ -226,6 +226,11 @@ Experiments.Policy.prototype = {
|
||||||
return UpdateChannel.get();
|
return UpdateChannel.get();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
locale: function () {
|
||||||
|
let chrome = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry);
|
||||||
|
return chrome.getSelectedLocale("global");
|
||||||
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @return Promise<> Resolved with the payload data.
|
* @return Promise<> Resolved with the payload data.
|
||||||
*/
|
*/
|
||||||
|
@ -304,8 +309,10 @@ Experiments.Experiments.prototype = {
|
||||||
|
|
||||||
AddonManager.addAddonListener(this);
|
AddonManager.addAddonListener(this);
|
||||||
|
|
||||||
this._loadTask = Task.spawn(this._loadFromCache.bind(this)).then(
|
this._loadTask = Task.spawn(this._loadFromCache.bind(this));
|
||||||
|
this._loadTask.then(
|
||||||
() => {
|
() => {
|
||||||
|
gLogger.trace("Experiments::_loadTask finished ok");
|
||||||
this._loadTask = null;
|
this._loadTask = null;
|
||||||
this._run();
|
this._run();
|
||||||
},
|
},
|
||||||
|
@ -386,7 +393,7 @@ Experiments.Experiments.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
_telemetryStatusChanged: function () {
|
_telemetryStatusChanged: function () {
|
||||||
_toggleExperimentsEnabled(gExperimentsEnabled);
|
this._toggleExperimentsEnabled(gExperimentsEnabled);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -473,10 +480,16 @@ Experiments.Experiments.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
_run: function() {
|
_run: function() {
|
||||||
|
gLogger.trace("Experiments::_run");
|
||||||
this._checkForShutdown();
|
this._checkForShutdown();
|
||||||
if (!this._mainTask) {
|
if (!this._mainTask) {
|
||||||
this._mainTask = Task.spawn(this._main.bind(this)).then(
|
this._mainTask = Task.spawn(this._main.bind(this));
|
||||||
null,
|
this._mainTask.then(
|
||||||
|
() => {
|
||||||
|
gLogger.trace("Experiments::_main finished, scheduling next run");
|
||||||
|
this._mainTask = null;
|
||||||
|
this._scheduleNextRun();
|
||||||
|
},
|
||||||
(e) => {
|
(e) => {
|
||||||
gLogger.error("Experiments::_main caught error: " + e);
|
gLogger.error("Experiments::_main caught error: " + e);
|
||||||
this._mainTask = null;
|
this._mainTask = null;
|
||||||
|
@ -488,6 +501,7 @@ Experiments.Experiments.prototype = {
|
||||||
|
|
||||||
_main: function*() {
|
_main: function*() {
|
||||||
do {
|
do {
|
||||||
|
gLogger.trace("Experiments::_main iteration");
|
||||||
yield this._loadTask;
|
yield this._loadTask;
|
||||||
if (this._refresh) {
|
if (this._refresh) {
|
||||||
yield this._loadManifest();
|
yield this._loadManifest();
|
||||||
|
@ -500,11 +514,10 @@ Experiments.Experiments.prototype = {
|
||||||
// while we were running, go again right now.
|
// while we were running, go again right now.
|
||||||
}
|
}
|
||||||
while (this._refresh || this._terminateReason);
|
while (this._refresh || this._terminateReason);
|
||||||
this._mainTask = null;
|
|
||||||
this._scheduleNextRun();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_loadManifest: function*() {
|
_loadManifest: function*() {
|
||||||
|
gLogger.trace("Experiments::_loadManifest");
|
||||||
let uri = Services.urlFormatter.formatURLPref(PREF_BRANCH + PREF_MANIFEST_URI);
|
let uri = Services.urlFormatter.formatURLPref(PREF_BRANCH + PREF_MANIFEST_URI);
|
||||||
|
|
||||||
this._checkForShutdown();
|
this._checkForShutdown();
|
||||||
|
@ -652,6 +665,7 @@ Experiments.Experiments.prototype = {
|
||||||
* Part of the main task to save the cache to disk, called from _main.
|
* Part of the main task to save the cache to disk, called from _main.
|
||||||
*/
|
*/
|
||||||
_saveToCache: function* () {
|
_saveToCache: function* () {
|
||||||
|
gLogger.trace("Experiments::_saveToCache");
|
||||||
let path = this._cacheFilePath;
|
let path = this._cacheFilePath;
|
||||||
let textData = JSON.stringify({
|
let textData = JSON.stringify({
|
||||||
version: CACHE_VERSION,
|
version: CACHE_VERSION,
|
||||||
|
@ -670,6 +684,7 @@ Experiments.Experiments.prototype = {
|
||||||
* Task function, load the cached experiments manifest file from disk.
|
* Task function, load the cached experiments manifest file from disk.
|
||||||
*/
|
*/
|
||||||
_loadFromCache: function*() {
|
_loadFromCache: function*() {
|
||||||
|
gLogger.trace("Experiments::_loadFromCache");
|
||||||
let path = this._cacheFilePath;
|
let path = this._cacheFilePath;
|
||||||
try {
|
try {
|
||||||
let result = yield loadJSONAsync(path, { compression: "lz4" });
|
let result = yield loadJSONAsync(path, { compression: "lz4" });
|
||||||
|
@ -706,7 +721,7 @@ Experiments.Experiments.prototype = {
|
||||||
* array in the manifest
|
* array in the manifest
|
||||||
*/
|
*/
|
||||||
_updateExperiments: function (manifestObject) {
|
_updateExperiments: function (manifestObject) {
|
||||||
gLogger.trace("Experiments::updateExperiments() - experiments: " + JSON.stringify(manifestObject));
|
gLogger.trace("Experiments::_updateExperiments() - experiments: " + JSON.stringify(manifestObject));
|
||||||
|
|
||||||
if (manifestObject.version !== MANIFEST_VERSION) {
|
if (manifestObject.version !== MANIFEST_VERSION) {
|
||||||
gLogger.warning("Experiments::updateExperiments() - unsupported version " + manifestObject.version);
|
gLogger.warning("Experiments::updateExperiments() - unsupported version " + manifestObject.version);
|
||||||
|
@ -1149,9 +1164,8 @@ Experiments.ExperimentEntry.prototype = {
|
||||||
let app = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo);
|
let app = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo);
|
||||||
let runtime = Cc["@mozilla.org/xre/app-info;1"]
|
let runtime = Cc["@mozilla.org/xre/app-info;1"]
|
||||||
.getService(Ci.nsIXULRuntime);
|
.getService(Ci.nsIXULRuntime);
|
||||||
let chrome = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry);
|
|
||||||
|
|
||||||
let locale = chrome.getSelectedLocale("global");
|
let locale = this._policy.locale();
|
||||||
let channel = this._policy.updatechannel();
|
let channel = this._policy.updatechannel();
|
||||||
let data = this._manifestData;
|
let data = this._manifestData;
|
||||||
|
|
||||||
|
@ -1161,6 +1175,7 @@ Experiments.ExperimentEntry.prototype = {
|
||||||
let startSec = (this.startDate || 0) / 1000;
|
let startSec = (this.startDate || 0) / 1000;
|
||||||
|
|
||||||
gLogger.trace("ExperimentEntry::isApplicable() - now=" + now
|
gLogger.trace("ExperimentEntry::isApplicable() - now=" + now
|
||||||
|
+ ", randomValue=" + this._randomValue
|
||||||
+ ", data=" + JSON.stringify(this._manifestData));
|
+ ", data=" + JSON.stringify(this._manifestData));
|
||||||
|
|
||||||
// Not applicable if it already ran.
|
// Not applicable if it already ran.
|
||||||
|
@ -1183,11 +1198,11 @@ Experiments.ExperimentEntry.prototype = {
|
||||||
{ name: "endTime",
|
{ name: "endTime",
|
||||||
condition: () => now < data.endTime },
|
condition: () => now < data.endTime },
|
||||||
{ name: "maxStartTime",
|
{ name: "maxStartTime",
|
||||||
condition: () => !data.maxStartTime || now <= (data.maxStartTime - minActive) },
|
condition: () => !data.maxStartTime || now <= data.maxStartTime },
|
||||||
{ name: "maxActiveSeconds",
|
{ name: "maxActiveSeconds",
|
||||||
condition: () => !this._startDate || now <= (startSec + maxActive) },
|
condition: () => !this._startDate || now <= (startSec + maxActive) },
|
||||||
{ name: "appName",
|
{ name: "appName",
|
||||||
condition: () => !data.name || data.appName.indexOf(app.name) != -1 },
|
condition: () => !data.appName || data.appName.indexOf(app.name) != -1 },
|
||||||
{ name: "minBuildID",
|
{ name: "minBuildID",
|
||||||
condition: () => !data.minBuildID || app.platformBuildID >= data.minBuildID },
|
condition: () => !data.minBuildID || app.platformBuildID >= data.minBuildID },
|
||||||
{ name: "maxBuildID",
|
{ name: "maxBuildID",
|
||||||
|
@ -1201,9 +1216,9 @@ Experiments.ExperimentEntry.prototype = {
|
||||||
{ name: "locale",
|
{ name: "locale",
|
||||||
condition: () => !data.locale || data.locale.indexOf(locale) != -1 },
|
condition: () => !data.locale || data.locale.indexOf(locale) != -1 },
|
||||||
{ name: "sample",
|
{ name: "sample",
|
||||||
condition: () => !data.sample || this._randomValue <= data.sample },
|
condition: () => data.sample === undefined || this._randomValue <= data.sample },
|
||||||
{ name: "version",
|
{ name: "version",
|
||||||
condition: () => !data.version || data.appVersion.indexOf(app.version) != -1 },
|
condition: () => !data.version || data.version.indexOf(app.version) != -1 },
|
||||||
{ name: "minVersion",
|
{ name: "minVersion",
|
||||||
condition: () => !data.minVersion || versionCmp.compare(app.version, data.minVersion) >= 0 },
|
condition: () => !data.minVersion || versionCmp.compare(app.version, data.minVersion) >= 0 },
|
||||||
{ name: "maxVersion",
|
{ name: "maxVersion",
|
||||||
|
|
|
@ -3,6 +3,6 @@ contract @mozilla.org/browser/experiments-service;1 {f7800463-3b97-47f9-9341-b76
|
||||||
category update-timer ExperimentsService @mozilla.org/browser/experiments-service;1,getService,experiments-update-timer,experiments.manifest.fetchIntervalSeconds,86400
|
category update-timer ExperimentsService @mozilla.org/browser/experiments-service;1,getService,experiments-update-timer,experiments.manifest.fetchIntervalSeconds,86400
|
||||||
category profile-after-change ExperimentsService @mozilla.org/browser/experiments-service;1
|
category profile-after-change ExperimentsService @mozilla.org/browser/experiments-service;1
|
||||||
|
|
||||||
category healthreport-js-provider-default ExperimentsProvider resource://gre/browser/modules/Experiments/Experiments.jsm
|
category healthreport-js-provider-default ExperimentsProvider resource:///modules/experiments/Experiments.jsm
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,8 @@ const EXPERIMENT2_XPI_NAME = "experiment-2.xpi";
|
||||||
const EXPERIMENT3_ID = "test-experiment-3@tests.mozilla.org";
|
const EXPERIMENT3_ID = "test-experiment-3@tests.mozilla.org";
|
||||||
const EXPERIMENT4_ID = "test-experiment-4@tests.mozilla.org";
|
const EXPERIMENT4_ID = "test-experiment-4@tests.mozilla.org";
|
||||||
|
|
||||||
|
const DEFAULT_BUILDID = "2014060601";
|
||||||
|
|
||||||
const FAKE_EXPERIMENTS_1 = [
|
const FAKE_EXPERIMENTS_1 = [
|
||||||
{
|
{
|
||||||
id: "id1",
|
id: "id1",
|
||||||
|
@ -169,7 +171,7 @@ function createAppInfo(options) {
|
||||||
let platformVersion = options.platformVersion || "1.0";
|
let platformVersion = options.platformVersion || "1.0";
|
||||||
let date = options.date || new Date();
|
let date = options.date || new Date();
|
||||||
|
|
||||||
let buildID = "" + date.getYear() + date.getMonth() + date.getDate() + "01";
|
let buildID = options.buildID || DEFAULT_BUILDID;
|
||||||
|
|
||||||
gAppInfo = {
|
gAppInfo = {
|
||||||
// nsIXULAppInfo
|
// nsIXULAppInfo
|
||||||
|
|
|
@ -63,6 +63,7 @@ add_task(function* test_setup() {
|
||||||
gReporter = yield getReporter("json_payload_simple");
|
gReporter = yield getReporter("json_payload_simple");
|
||||||
yield gReporter.collectMeasurements();
|
yield gReporter.collectMeasurements();
|
||||||
let payload = yield gReporter.getJSONPayload(true);
|
let payload = yield gReporter.getJSONPayload(true);
|
||||||
|
do_register_cleanup(() => gReporter._shutdown());
|
||||||
|
|
||||||
patchPolicy(gPolicy, {
|
patchPolicy(gPolicy, {
|
||||||
updatechannel: () => "nightly",
|
updatechannel: () => "nightly",
|
||||||
|
@ -131,8 +132,3 @@ add_task(function* test_startStop() {
|
||||||
Assert.equal(maybeStop, true, "Experiment should have been stopped.");
|
Assert.equal(maybeStop, true, "Experiment should have been stopped.");
|
||||||
Assert.equal(experiment.enabled, false, "Experiment should be disabled.");
|
Assert.equal(experiment.enabled, false, "Experiment should be disabled.");
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* shutdown() {
|
|
||||||
yield gReporter._shutdown();
|
|
||||||
yield removeCacheFile();
|
|
||||||
});
|
|
||||||
|
|
|
@ -75,6 +75,7 @@ add_task(function* test_setup() {
|
||||||
gReporter = yield getReporter("json_payload_simple");
|
gReporter = yield getReporter("json_payload_simple");
|
||||||
yield gReporter.collectMeasurements();
|
yield gReporter.collectMeasurements();
|
||||||
let payload = yield gReporter.getJSONPayload(true);
|
let payload = yield gReporter.getJSONPayload(true);
|
||||||
|
do_register_cleanup(() => gReporter._shutdown());
|
||||||
|
|
||||||
gPolicy = new Experiments.Policy();
|
gPolicy = new Experiments.Policy();
|
||||||
patchPolicy(gPolicy, {
|
patchPolicy(gPolicy, {
|
||||||
|
@ -1278,9 +1279,3 @@ add_task(function* test_unexpectedUninstall() {
|
||||||
yield experiments.uninit();
|
yield experiments.uninit();
|
||||||
yield removeCacheFile();
|
yield removeCacheFile();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
add_task(function* shutdown() {
|
|
||||||
yield gReporter._shutdown();
|
|
||||||
yield removeCacheFile();
|
|
||||||
});
|
|
||||||
|
|
|
@ -76,6 +76,7 @@ add_task(function* test_setup() {
|
||||||
gReporter = yield getReporter("json_payload_simple");
|
gReporter = yield getReporter("json_payload_simple");
|
||||||
yield gReporter.collectMeasurements();
|
yield gReporter.collectMeasurements();
|
||||||
let payload = yield gReporter.getJSONPayload(true);
|
let payload = yield gReporter.getJSONPayload(true);
|
||||||
|
do_register_cleanup(() => gReporter._shutdown());
|
||||||
|
|
||||||
gPolicy = new Experiments.Policy();
|
gPolicy = new Experiments.Policy();
|
||||||
patchPolicy(gPolicy, {
|
patchPolicy(gPolicy, {
|
||||||
|
@ -264,8 +265,3 @@ add_task(function* test_cache() {
|
||||||
yield experiments.uninit();
|
yield experiments.uninit();
|
||||||
yield removeCacheFile();
|
yield removeCacheFile();
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* shutdown() {
|
|
||||||
yield gReporter._shutdown();
|
|
||||||
yield removeCacheFile();
|
|
||||||
});
|
|
||||||
|
|
|
@ -61,10 +61,13 @@ add_task(function* test_setup() {
|
||||||
gReporter = yield getReporter("json_payload_simple");
|
gReporter = yield getReporter("json_payload_simple");
|
||||||
yield gReporter.collectMeasurements();
|
yield gReporter.collectMeasurements();
|
||||||
let payload = yield gReporter.getJSONPayload(true);
|
let payload = yield gReporter.getJSONPayload(true);
|
||||||
|
do_register_cleanup(() => gReporter._shutdown());
|
||||||
|
|
||||||
patchPolicy(gPolicy, {
|
patchPolicy(gPolicy, {
|
||||||
updatechannel: () => "nightly",
|
updatechannel: () => "nightly",
|
||||||
|
locale: () => "en-US",
|
||||||
healthReportPayload: () => Promise.resolve(payload),
|
healthReportPayload: () => Promise.resolve(payload),
|
||||||
|
random: () => 0.5,
|
||||||
});
|
});
|
||||||
|
|
||||||
Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true);
|
Services.prefs.setBoolPref(PREF_EXPERIMENTS_ENABLED, true);
|
||||||
|
@ -108,10 +111,81 @@ const sanityFilter = function filter(c) {
|
||||||
add_task(function* test_simpleFields() {
|
add_task(function* test_simpleFields() {
|
||||||
let testData = [
|
let testData = [
|
||||||
// "expected applicable?", failure reason or null, manifest data
|
// "expected applicable?", failure reason or null, manifest data
|
||||||
|
|
||||||
|
// misc. environment
|
||||||
|
|
||||||
|
[false, ["appName"], {appName: []}],
|
||||||
|
[false, ["appName"], {appName: ["foo", gAppInfo.name + "-invalid"]}],
|
||||||
|
[true, null, {appName: ["not-an-app-name", gAppInfo.name]}],
|
||||||
|
|
||||||
|
[false, ["os"], {os: []}],
|
||||||
[false, ["os"], {os: ["42", "abcdef"]}],
|
[false, ["os"], {os: ["42", "abcdef"]}],
|
||||||
[true, null, {os: [gAppInfo.OS, "plan9"]}],
|
[true, null, {os: [gAppInfo.OS, "plan9"]}],
|
||||||
|
|
||||||
|
[false, ["channel"], {channel: []}],
|
||||||
|
[false, ["channel"], {channel: ["foo", gPolicy.updatechannel() + "-invalid"]}],
|
||||||
|
[true, null, {channel: ["not-a-channel", gPolicy.updatechannel()]}],
|
||||||
|
|
||||||
|
[false, ["locale"], {locale: []}],
|
||||||
|
[false, ["locale"], {locale: ["foo", gPolicy.locale + "-invalid"]}],
|
||||||
|
[true, null, {locale: ["not-a-locale", gPolicy.locale()]}],
|
||||||
|
|
||||||
|
// version
|
||||||
|
|
||||||
|
[false, ["version"], {version: []}],
|
||||||
|
[false, ["version"], {version: ["-1", gAppInfo.version + "-invalid", "asdf", "0,4", "99.99", "0.1.1.1"]}],
|
||||||
|
[true, null, {version: ["99999999.999", "-1", gAppInfo.version]}],
|
||||||
|
|
||||||
|
[false, ["minVersion"], {minVersion: "1.0.1"}],
|
||||||
|
[true, null, {minVersion: "1.0b1"}],
|
||||||
|
[true, null, {minVersion: "1.0"}],
|
||||||
|
[true, null, {minVersion: "0.9"}],
|
||||||
|
|
||||||
|
[false, ["maxVersion"], {maxVersion: "0.1"}],
|
||||||
|
[false, ["maxVersion"], {maxVersion: "0.9.9"}],
|
||||||
|
[false, ["maxVersion"], {maxVersion: "1.0b1"}],
|
||||||
|
[true, ["maxVersion"], {maxVersion: "1.0"}],
|
||||||
|
[true, ["maxVersion"], {maxVersion: "1.7pre"}],
|
||||||
|
|
||||||
|
// build id
|
||||||
|
|
||||||
|
[false, ["buildIDs"], {buildIDs: []}],
|
||||||
[false, ["buildIDs"], {buildIDs: ["not-a-build-id", gAppInfo.platformBuildID + "-invalid"]}],
|
[false, ["buildIDs"], {buildIDs: ["not-a-build-id", gAppInfo.platformBuildID + "-invalid"]}],
|
||||||
[true, null, {buildIDs: ["not-a-build-id", gAppInfo.platformBuildID]}],
|
[true, null, {buildIDs: ["not-a-build-id", gAppInfo.platformBuildID]}],
|
||||||
|
|
||||||
|
[true, null, {minBuildID: "2014060501"}],
|
||||||
|
[true, null, {minBuildID: "2014060601"}],
|
||||||
|
[false, ["minBuildID"], {minBuildID: "2014060701"}],
|
||||||
|
|
||||||
|
[false, ["maxBuildID"], {maxBuildID: "2014010101"}],
|
||||||
|
[true, null, {maxBuildID: "2014060601"}],
|
||||||
|
[true, null, {maxBuildID: "2014060901"}],
|
||||||
|
|
||||||
|
// sample
|
||||||
|
|
||||||
|
[false, ["sample"], {sample: -1 }],
|
||||||
|
[false, ["sample"], {sample: 0.0}],
|
||||||
|
[false, ["sample"], {sample: 0.1}],
|
||||||
|
[true, null, {sample: 0.5}],
|
||||||
|
[true, null, {sample: 0.6}],
|
||||||
|
[true, null, {sample: 1.0}],
|
||||||
|
[true, null, {sample: 0.5}],
|
||||||
|
|
||||||
|
// experiment control
|
||||||
|
|
||||||
|
[false, ["disabled"], {disabled: true}],
|
||||||
|
[true, null, {disabled: false}],
|
||||||
|
|
||||||
|
[false, ["frozen"], {frozen: true}],
|
||||||
|
[true, null, {frozen: false}],
|
||||||
|
|
||||||
|
[false, null, {frozen: true, disabled: true}],
|
||||||
|
[false, null, {frozen: true, disabled: false}],
|
||||||
|
[false, null, {frozen: false, disabled: true}],
|
||||||
|
[true, null, {frozen: false, disabled: false}],
|
||||||
|
|
||||||
|
// jsfilter
|
||||||
|
|
||||||
[true, null, {jsfilter: "function filter(c) { return true; }"}],
|
[true, null, {jsfilter: "function filter(c) { return true; }"}],
|
||||||
[false, ["jsfilter-false"], {jsfilter: "function filter(c) { return false; }"}],
|
[false, ["jsfilter-false"], {jsfilter: "function filter(c) { return false; }"}],
|
||||||
[true, null, {jsfilter: "function filter(c) { return 123; }"}], // truthy
|
[true, null, {jsfilter: "function filter(c) { return 123; }"}], // truthy
|
||||||
|
@ -150,18 +224,73 @@ add_task(function* test_simpleFields() {
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* test_times() {
|
add_task(function* test_times() {
|
||||||
let baseDate = new Date(2014, 5, 6, 12);
|
let now = new Date(2014, 5, 6, 12);
|
||||||
let baseTimeSec = baseDate.getTime() / 1000;
|
let nowSec = now.getTime() / 1000;
|
||||||
let testData = [
|
let testData = [
|
||||||
// "expected applicable?", rejection reason or null, fake now date, manifest data
|
// "expected applicable?", rejection reason or null, fake now date, manifest data
|
||||||
[false, "maxStartTime", baseDate,
|
|
||||||
{maxStartTime: baseTimeSec - 10 * SEC_IN_ONE_DAY}],
|
// start time
|
||||||
[false, "endTime", baseDate,
|
|
||||||
{startTime: baseTimeSec - 10 * SEC_IN_ONE_DAY,
|
[true, null, now,
|
||||||
endTime: baseTimeSec - 5 * SEC_IN_ONE_DAY}],
|
{startTime: nowSec - 5 * SEC_IN_ONE_DAY,
|
||||||
[true, null, baseDate,
|
endTime: nowSec + 10 * SEC_IN_ONE_DAY}],
|
||||||
{startTime: baseTimeSec - 5 * SEC_IN_ONE_DAY,
|
[true, null, now,
|
||||||
endTime: baseTimeSec + 10 * SEC_IN_ONE_DAY}],
|
{startTime: nowSec ,
|
||||||
|
endTime: nowSec + 10 * SEC_IN_ONE_DAY}],
|
||||||
|
[false, "startTime", now,
|
||||||
|
{startTime: nowSec + 5 * SEC_IN_ONE_DAY,
|
||||||
|
endTime: nowSec + 10 * SEC_IN_ONE_DAY}],
|
||||||
|
|
||||||
|
// end time
|
||||||
|
|
||||||
|
[false, "endTime", now,
|
||||||
|
{startTime: nowSec - 5 * SEC_IN_ONE_DAY,
|
||||||
|
endTime: nowSec - 10 * SEC_IN_ONE_DAY}],
|
||||||
|
[false, "endTime", now,
|
||||||
|
{startTime: nowSec - 5 * SEC_IN_ONE_DAY,
|
||||||
|
endTime: nowSec - 5 * SEC_IN_ONE_DAY}],
|
||||||
|
|
||||||
|
// max start time
|
||||||
|
|
||||||
|
[false, "maxStartTime", now,
|
||||||
|
{maxStartTime: nowSec - 15 * SEC_IN_ONE_DAY,
|
||||||
|
startTime: nowSec - 10 * SEC_IN_ONE_DAY,
|
||||||
|
endTime: nowSec + 10 * SEC_IN_ONE_DAY}],
|
||||||
|
[false, "maxStartTime", now,
|
||||||
|
{maxStartTime: nowSec - 1 * SEC_IN_ONE_DAY,
|
||||||
|
startTime: nowSec - 10 * SEC_IN_ONE_DAY,
|
||||||
|
endTime: nowSec + 10 * SEC_IN_ONE_DAY}],
|
||||||
|
[false, "maxStartTime", now,
|
||||||
|
{maxStartTime: nowSec - 10 * SEC_IN_ONE_DAY,
|
||||||
|
startTime: nowSec - 10 * SEC_IN_ONE_DAY,
|
||||||
|
endTime: nowSec + 10 * SEC_IN_ONE_DAY}],
|
||||||
|
[true, null, now,
|
||||||
|
{maxStartTime: nowSec,
|
||||||
|
startTime: nowSec - 10 * SEC_IN_ONE_DAY,
|
||||||
|
endTime: nowSec + 10 * SEC_IN_ONE_DAY}],
|
||||||
|
[true, null, now,
|
||||||
|
{maxStartTime: nowSec + 1 * SEC_IN_ONE_DAY,
|
||||||
|
startTime: nowSec - 10 * SEC_IN_ONE_DAY,
|
||||||
|
endTime: nowSec + 10 * SEC_IN_ONE_DAY}],
|
||||||
|
|
||||||
|
// max active seconds
|
||||||
|
|
||||||
|
[true, null, now,
|
||||||
|
{maxActiveSeconds: 5 * SEC_IN_ONE_DAY,
|
||||||
|
startTime: nowSec - 10 * SEC_IN_ONE_DAY,
|
||||||
|
endTime: nowSec + 10 * SEC_IN_ONE_DAY}],
|
||||||
|
[true, null, now,
|
||||||
|
{maxActiveSeconds: 10 * SEC_IN_ONE_DAY,
|
||||||
|
startTime: nowSec - 10 * SEC_IN_ONE_DAY,
|
||||||
|
endTime: nowSec + 10 * SEC_IN_ONE_DAY}],
|
||||||
|
[true, null, now,
|
||||||
|
{maxActiveSeconds: 15 * SEC_IN_ONE_DAY,
|
||||||
|
startTime: nowSec - 10 * SEC_IN_ONE_DAY,
|
||||||
|
endTime: nowSec + 10 * SEC_IN_ONE_DAY}],
|
||||||
|
[true, null, now,
|
||||||
|
{maxActiveSeconds: 20 * SEC_IN_ONE_DAY,
|
||||||
|
startTime: nowSec - 10 * SEC_IN_ONE_DAY,
|
||||||
|
endTime: nowSec + 10 * SEC_IN_ONE_DAY}],
|
||||||
];
|
];
|
||||||
|
|
||||||
for (let i=0; i<testData.length; ++i) {
|
for (let i=0; i<testData.length; ++i) {
|
||||||
|
@ -186,8 +315,3 @@ add_task(function* test_times() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* shutdown() {
|
|
||||||
yield gReporter._shutdown();
|
|
||||||
yield removeCacheFile();
|
|
||||||
});
|
|
||||||
|
|
|
@ -77,6 +77,3 @@ add_task(function* test_fetchInvalid() {
|
||||||
yield ex.uninit();
|
yield ex.uninit();
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* shutdown() {
|
|
||||||
yield removeCacheFile();
|
|
||||||
});
|
|
||||||
|
|
|
@ -114,6 +114,7 @@ add_task(function* test_setup() {
|
||||||
gReporter = yield getReporter("json_payload_simple");
|
gReporter = yield getReporter("json_payload_simple");
|
||||||
yield gReporter.collectMeasurements();
|
yield gReporter.collectMeasurements();
|
||||||
let payload = yield gReporter.getJSONPayload(true);
|
let payload = yield gReporter.getJSONPayload(true);
|
||||||
|
do_register_cleanup(() => gReporter._shutdown());
|
||||||
|
|
||||||
gPolicy = new Experiments.Policy();
|
gPolicy = new Experiments.Policy();
|
||||||
let dummyTimer = { cancel: () => {}, clear: () => {} };
|
let dummyTimer = { cancel: () => {}, clear: () => {} };
|
||||||
|
@ -353,8 +354,3 @@ add_task(function* test_telemetryBasics() {
|
||||||
yield experiments.uninit();
|
yield experiments.uninit();
|
||||||
yield removeCacheFile();
|
yield removeCacheFile();
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* shutdown() {
|
|
||||||
yield gReporter._shutdown();
|
|
||||||
yield removeCacheFile();
|
|
||||||
});
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
%define forwardTransitionLength 150ms
|
%define forwardTransitionLength 150ms
|
||||||
%define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-container
|
%define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-container
|
||||||
%define conditionalForwardWithUrlbarWidth 40
|
%define conditionalForwardWithUrlbarWidth 30
|
||||||
|
|
||||||
#menubar-items {
|
#menubar-items {
|
||||||
-moz-box-orient: vertical; /* for flex hack */
|
-moz-box-orient: vertical; /* for flex hack */
|
||||||
|
@ -676,23 +676,98 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
||||||
|
|
||||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
|
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
|
||||||
-moz-margin-start: -4px;
|
-moz-margin-start: -4px;
|
||||||
|
margin-top: 3px;
|
||||||
|
margin-bottom: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#forward-button[disabled] {
|
#back-button {
|
||||||
transform: scale(0);
|
padding-top: 3px;
|
||||||
opacity: 0;
|
padding-bottom: 3px;
|
||||||
pointer-events: none;
|
-moz-padding-start: 5px;
|
||||||
|
-moz-padding-end: 0;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
border-radius: 0 10000px 10000px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@conditionalForwardWithUrlbar@:not([switchingtabs]) > #forward-button {
|
#back-button:-moz-locale-dir(rtl) {
|
||||||
transition: @forwardTransitionLength@ ease-out;
|
border-radius: 10000px 0 0 10000px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#back-button > menupopup {
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#back-button > .toolbarbutton-icon {
|
||||||
|
border-radius: 10000px;
|
||||||
|
background-clip: padding-box;
|
||||||
|
padding: 6px;
|
||||||
|
border: none;
|
||||||
|
box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
|
||||||
|
0 0 0 1px hsla(0,0%,100%,.3) inset,
|
||||||
|
0 0 0 1px hsla(210,54%,20%,.25),
|
||||||
|
0 1px 0 hsla(210,54%,20%,.35);
|
||||||
|
background-image: linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.1));
|
||||||
|
transition-property: background-color, box-shadow;
|
||||||
|
transition-duration: 250ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
#back-button:not([disabled="true"]):not([open="true"]):not(:active):hover > .toolbarbutton-icon {
|
||||||
|
background-color: hsla(210,48%,96%,.75);
|
||||||
|
box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
|
||||||
|
0 0 0 1px hsla(0,0%,100%,.3) inset,
|
||||||
|
0 0 0 1px hsla(210,54%,20%,.3),
|
||||||
|
0 1px 0 hsla(210,54%,20%,.4),
|
||||||
|
0 0 4px hsla(210,54%,20%,.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#back-button:not([disabled="true"]):hover:active > .toolbarbutton-icon,
|
||||||
|
#back-button[open="true"] > .toolbarbutton-icon {
|
||||||
|
background-color: hsla(210,54%,20%,.15);
|
||||||
|
box-shadow: 0 1px 1px hsla(210,54%,20%,.1) inset,
|
||||||
|
0 0 1px hsla(210,54%,20%,.2) inset,
|
||||||
|
0 0 0 1px hsla(210,54%,20%,.4),
|
||||||
|
0 1px 0 hsla(210,54%,20%,.2);
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-window:not([customizing]) #back-button[disabled] > .toolbarbutton-icon {
|
||||||
|
box-shadow: 0 0 0 1px hsla(210,54%,20%,.55),
|
||||||
|
0 1px 0 hsla(210,54%,20%,.65) !important;
|
||||||
|
transition: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#back-button:-moz-locale-dir(rtl) > .toolbarbutton-icon,
|
#back-button:-moz-locale-dir(rtl) > .toolbarbutton-icon,
|
||||||
#forward-button:-moz-locale-dir(rtl) > .toolbarbutton-icon {
|
#forward-button:-moz-locale-dir(rtl) {
|
||||||
transform: scaleX(-1);
|
transform: scaleX(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@conditionalForwardWithUrlbar@:not([switchingtabs]) > #forward-button {
|
||||||
|
transition: opacity @forwardTransitionLength@ ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@conditionalForwardWithUrlbar@ > #forward-button[occluded-by-urlbar] {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#forward-button {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#forward-button > .toolbarbutton-icon {
|
||||||
|
background-clip: padding-box;
|
||||||
|
clip-path: url("chrome://browser/content/browser.xul#keyhole-forward-clip-path");
|
||||||
|
margin-left: -6px;
|
||||||
|
border-left-style: none;
|
||||||
|
border-radius: 0;
|
||||||
|
padding: 2px 3px 2px 9px;
|
||||||
|
border: 1px solid #9a9a9a;
|
||||||
|
}
|
||||||
|
|
||||||
/* tabview menu item */
|
/* tabview menu item */
|
||||||
|
|
||||||
#menu_tabview {
|
#menu_tabview {
|
||||||
|
@ -801,9 +876,21 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Location bar */
|
/* Location bar */
|
||||||
|
#urlbar,
|
||||||
|
.searchbar-textbox {
|
||||||
|
-moz-appearance: none;
|
||||||
|
padding: 1px;
|
||||||
|
border: 1px solid ThreeDShadow;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#urlbar[focused],
|
||||||
|
.searchbar-textbox[focused] {
|
||||||
|
border-color: Highlight;
|
||||||
|
}
|
||||||
|
|
||||||
#urlbar {
|
#urlbar {
|
||||||
-moz-appearance: textfield;
|
background-color: -moz-field;
|
||||||
padding: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.urlbar-textbox-container {
|
.urlbar-textbox-container {
|
||||||
|
@ -825,26 +912,59 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
||||||
}
|
}
|
||||||
|
|
||||||
@conditionalForwardWithUrlbar@ > #urlbar-wrapper {
|
@conditionalForwardWithUrlbar@ > #urlbar-wrapper {
|
||||||
-moz-padding-start: @conditionalForwardWithUrlbarWidth@px;
|
padding-left: @conditionalForwardWithUrlbarWidth@px;
|
||||||
-moz-margin-start: -@conditionalForwardWithUrlbarWidth@px;
|
-moz-margin-start: -@conditionalForwardWithUrlbarWidth@px;
|
||||||
position: relative;
|
position: relative;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar {
|
@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar {
|
||||||
|
-moz-border-start: none;
|
||||||
|
margin-left: 0;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
@conditionalForwardWithUrlbar@:not([switchingtabs]) > #urlbar-wrapper > #urlbar {
|
@conditionalForwardWithUrlbar@:not([switchingtabs]) > #urlbar-wrapper > #urlbar {
|
||||||
transition: margin-left @forwardTransitionLength@ ease-out,
|
transition: margin-left @forwardTransitionLength@ ease-out;
|
||||||
margin-right @forwardTransitionLength@ ease-out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar:-moz-locale-dir(ltr) {
|
@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar:-moz-locale-dir(ltr) {
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar:-moz-locale-dir(rtl) {
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper {
|
||||||
|
/* Work with margin-top to align the clip-path correctly. */
|
||||||
|
margin-top: 5px;
|
||||||
|
clip-path: url("chrome://browser/content/browser.xul#urlbar-back-button-clip-path");
|
||||||
|
}
|
||||||
|
|
||||||
|
@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar {
|
||||||
|
margin-top: -4px;
|
||||||
margin-left: -@conditionalForwardWithUrlbarWidth@px;
|
margin-left: -@conditionalForwardWithUrlbarWidth@px;
|
||||||
}
|
}
|
||||||
@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar:-moz-locale-dir(rtl) {
|
|
||||||
margin-right: -@conditionalForwardWithUrlbarWidth@px;
|
@conditionalForwardWithUrlbar@[forwarddisabled]:hover:not([switchingtabs]) > #urlbar-wrapper > #urlbar {
|
||||||
|
/* delay the hiding of the forward button when hovered to avoid accidental clicks on the url bar */
|
||||||
|
transition-delay: 100s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@conditionalForwardWithUrlbar@[forwarddisabled][switchingtabs] + #urlbar-container > #urlbar,
|
||||||
|
@conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) > #urlbar-wrapper > #urlbar {
|
||||||
|
/* when switching tabs, or when not hovered anymore, trigger a new transition
|
||||||
|
* to hide the forward button immediately */
|
||||||
|
margin-left: -@conditionalForwardWithUrlbarWidth@.01px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@conditionalForwardWithUrlbar@ > #urlbar-wrapper:-moz-locale-dir(rtl),
|
||||||
|
@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar:-moz-locale-dir(rtl) {
|
||||||
|
/* let windows-urlbar-back-button-mask clip the urlbar's right side for RTL */
|
||||||
|
transform: scaleX(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#urlbar-icons {
|
#urlbar-icons {
|
||||||
|
@ -884,41 +1004,66 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
||||||
min-width: calc(54px + 11ch);
|
min-width: calc(54px + 11ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
%include ../shared/identity-block.inc.css
|
/* identity box */
|
||||||
|
|
||||||
#page-proxy-favicon {
|
|
||||||
margin-top: 2px;
|
|
||||||
margin-bottom: 2px;
|
|
||||||
-moz-margin-start: 4px;
|
|
||||||
-moz-margin-end: 3px;
|
|
||||||
-moz-image-region: rect(0, 16px, 16px, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#identity-box:hover > #page-proxy-favicon {
|
|
||||||
-moz-image-region: rect(0, 32px, 16px, 16px);
|
|
||||||
}
|
|
||||||
|
|
||||||
#identity-box:hover:active > #page-proxy-favicon,
|
|
||||||
#identity-box[open=true] > #page-proxy-favicon {
|
|
||||||
-moz-image-region: rect(0, 48px, 16px, 32px);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Identity indicator */
|
|
||||||
#identity-box {
|
#identity-box {
|
||||||
padding: 1px;
|
padding: 1px;
|
||||||
margin: -1px;
|
|
||||||
-moz-margin-end: 0;
|
|
||||||
font-size: .9em;
|
font-size: .9em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#identity-box:-moz-locale-dir(ltr) {
|
#identity-box:-moz-locale-dir(ltr) {
|
||||||
border-top-left-radius: 2.5px;
|
border-top-left-radius: 1.5px;
|
||||||
border-bottom-left-radius: 2.5px;
|
border-bottom-left-radius: 1.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#identity-box:-moz-locale-dir(rtl) {
|
#identity-box:-moz-locale-dir(rtl) {
|
||||||
border-top-right-radius: 2.5px;
|
border-top-right-radius: 1.5px;
|
||||||
border-bottom-right-radius: 2.5px;
|
border-bottom-right-radius: 1.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#notification-popup-box:not([hidden]) + #identity-box {
|
||||||
|
-moz-padding-start: 10px;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar > #identity-box {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) {
|
||||||
|
padding-left: 5px;
|
||||||
|
transition: padding-left;
|
||||||
|
}
|
||||||
|
|
||||||
|
@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) {
|
||||||
|
padding-right: 5px;
|
||||||
|
transition: padding-right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@conditionalForwardWithUrlbar@[forwarddisabled]:hover:not([switchingtabs]) > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box {
|
||||||
|
/* forward button hiding is delayed when hovered */
|
||||||
|
transition-delay: 100s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@conditionalForwardWithUrlbar@[forwarddisabled][switchingtabs] + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr),
|
||||||
|
@conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) {
|
||||||
|
/* when not hovered anymore, trigger a new non-delayed transition to react to the forward button hiding */
|
||||||
|
padding-left: 5.01px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@conditionalForwardWithUrlbar@[forwarddisabled][switchingtabs] + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl),
|
||||||
|
@conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) {
|
||||||
|
/* when not hovered anymore, trigger a new non-delayed transition to react to the forward button hiding */
|
||||||
|
padding-right: 5.01px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#urlbar[pageproxystate="valid"] > #identity-box.chromeUI,
|
||||||
|
#urlbar[pageproxystate="valid"] > #identity-box.verifiedIdentity {
|
||||||
|
-moz-margin-end: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#identity-box.verifiedIdentity:not(:-moz-lwtheme) {
|
||||||
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
#identity-box:-moz-focusring {
|
#identity-box:-moz-focusring {
|
||||||
|
@ -931,10 +1076,27 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
||||||
-moz-padding-end: 5px;
|
-moz-padding-end: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#urlbar[pageproxystate="valid"] > #identity-box.chromeUI,
|
%include ../shared/identity-block.inc.css
|
||||||
#urlbar[pageproxystate="valid"] > #identity-box.verifiedIdentity {
|
|
||||||
background-color: #fff;
|
#page-proxy-favicon {
|
||||||
-moz-margin-end: 4px;
|
margin-top: 1px;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
-moz-margin-start: 3px;
|
||||||
|
-moz-margin-end: 2px;
|
||||||
|
-moz-image-region: rect(0, 16px, 16px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar > #identity-box > #page-proxy-favicon {
|
||||||
|
-moz-margin-end: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#identity-box:hover > #page-proxy-favicon {
|
||||||
|
-moz-image-region: rect(0, 32px, 16px, 16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#identity-box:hover:active > #page-proxy-favicon,
|
||||||
|
#identity-box[open=true] > #page-proxy-favicon {
|
||||||
|
-moz-image-region: rect(0, 48px, 16px, 32px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Identity popup icons */
|
/* Identity popup icons */
|
||||||
|
|
|
@ -105,6 +105,7 @@ browser.jar:
|
||||||
skin/classic/browser/feeds/audioFeedIcon16.png (feeds/feedIcon16.png)
|
skin/classic/browser/feeds/audioFeedIcon16.png (feeds/feedIcon16.png)
|
||||||
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css)
|
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css)
|
||||||
skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
|
skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
|
||||||
|
skin/classic/browser/fonts/ClearSans-Regular.ttf (../shared/ClearSans-Regular.ttf)
|
||||||
skin/classic/browser/newtab/newTab.css (newtab/newTab.css)
|
skin/classic/browser/newtab/newTab.css (newtab/newTab.css)
|
||||||
skin/classic/browser/newtab/controls.png (newtab/controls.png)
|
skin/classic/browser/newtab/controls.png (newtab/controls.png)
|
||||||
skin/classic/browser/places/bookmarksMenu.png (places/bookmarksMenu.png)
|
skin/classic/browser/places/bookmarksMenu.png (places/bookmarksMenu.png)
|
||||||
|
@ -134,6 +135,12 @@ browser.jar:
|
||||||
#endif
|
#endif
|
||||||
* skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
|
* skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
|
||||||
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
||||||
|
skin/classic/browser/preferences/in-content/check.png (preferences/in-content/check.png)
|
||||||
|
skin/classic/browser/preferences/in-content/icons.png (preferences/in-content/icons.png)
|
||||||
|
skin/classic/browser/preferences/in-content/header.png (preferences/in-content/header.png)
|
||||||
|
skin/classic/browser/preferences/in-content/dropdown.png (preferences/in-content/dropdown.png)
|
||||||
|
skin/classic/browser/preferences/in-content/sorter.png (preferences/in-content/sorter.png)
|
||||||
|
skin/classic/browser/preferences/in-content/dropdown-disabled.png (preferences/in-content/dropdown-disabled.png)
|
||||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||||
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
||||||
skin/classic/browser/social/services-16.png (social/services-16.png)
|
skin/classic/browser/social/services-16.png (social/services-16.png)
|
||||||
|
|
После Ширина: | Высота: | Размер: 593 B |
После Ширина: | Высота: | Размер: 250 B |
После Ширина: | Высота: | Размер: 250 B |
После Ширина: | Высота: | Размер: 11 KiB |
После Ширина: | Высота: | Размер: 12 KiB |
|
@ -2,174 +2,89 @@
|
||||||
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
- 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/. */
|
- You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
@import url("chrome://global/skin/inContentUI.css");
|
%include ../../../shared/in-content/preferences.css
|
||||||
|
|
||||||
@namespace html "http://www.w3.org/1999/xhtml";
|
button > .button-box,
|
||||||
|
menulist > .menulist-label-box {
|
||||||
#header {
|
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
caption {
|
|
||||||
font-size: 1.667rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-content {
|
|
||||||
max-width: 800px;
|
|
||||||
}
|
|
||||||
|
|
||||||
prefpane > .content-box {
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Category List */
|
|
||||||
|
|
||||||
#categories {
|
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
border: none;
|
|
||||||
-moz-margin-end: -1px;
|
|
||||||
background-color: transparent;
|
|
||||||
position: relative;
|
|
||||||
margin-top: 41px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.category {
|
button[type="menu"] > .button-box > .button-menu-dropmarker {
|
||||||
|
-moz-appearance: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
menulist:not([editable="true"]) > .menulist-dropmarker {
|
||||||
|
display: -moz-box;
|
||||||
|
margin-top: 6px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkbox {
|
||||||
|
-moz-binding: url("chrome://global/content/bindings/checkbox.xml#checkbox");
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-check {
|
||||||
|
max-height: 23px;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkbox:hover::before,
|
||||||
|
checkbox[checked]::before {
|
||||||
|
max-height: 10px;
|
||||||
|
margin-top: 7px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
-moz-margin-end: -19px;
|
||||||
|
-moz-margin-start: 4px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
radio {
|
||||||
|
-moz-binding: url("chrome://global/content/bindings/radio.xml#radio");
|
||||||
|
margin: 7px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-check {
|
||||||
|
max-height: 23px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-label-box {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
border-width: 1px;
|
|
||||||
-moz-border-end-width: 0;
|
|
||||||
border-style: solid;
|
|
||||||
border-color: transparent;
|
|
||||||
padding: 9px 4px 10px;
|
|
||||||
-moz-padding-end: 8px;
|
|
||||||
-moz-box-align: center;
|
|
||||||
overflow: hidden;
|
|
||||||
min-height: 0;
|
|
||||||
color: WindowText;
|
|
||||||
height: 52px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.category:-moz-locale-dir(ltr) {
|
radio:hover::before,
|
||||||
border-top-left-radius: 5px;
|
radio[selected]::before {
|
||||||
border-bottom-left-radius: 5px;
|
max-height: 11px;
|
||||||
}
|
margin-top: 6px;
|
||||||
|
margin-bottom: 6px;
|
||||||
.category:-moz-locale-dir(rtl) {
|
-moz-margin-end: -17px;
|
||||||
border-top-right-radius: 5px;
|
|
||||||
border-bottom-right-radius: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category[selected] {
|
|
||||||
background-color: -moz-Field;
|
|
||||||
color: -moz-FieldText;
|
|
||||||
border-color: ThreeDShadow;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-name {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
-moz-padding-end: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Maximize the size of the viewport when the window is small */
|
|
||||||
@media (max-width: 800px) {
|
|
||||||
.category-name {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-icon {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
margin: 0 6px;
|
|
||||||
-moz-margin-start: 6px;
|
-moz-margin-start: 6px;
|
||||||
-moz-margin-end: 5px;
|
|
||||||
list-style-image: url("chrome://browser/skin/preferences/Options.png");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#category-general > .category-icon {
|
.numberbox-input-box {
|
||||||
-moz-image-region: rect(0, 32px, 32px, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#category-content > .category-icon {
|
|
||||||
-moz-image-region: rect(0, 96px, 32px, 64px)
|
|
||||||
}
|
|
||||||
|
|
||||||
#category-application > .category-icon {
|
|
||||||
-moz-image-region: rect(0, 128px, 32px, 96px)
|
|
||||||
}
|
|
||||||
|
|
||||||
#category-privacy > .category-icon {
|
|
||||||
-moz-image-region: rect(0, 160px, 32px, 128px)
|
|
||||||
}
|
|
||||||
|
|
||||||
#category-security > .category-icon {
|
|
||||||
-moz-image-region: rect(0, 192px, 32px, 160px)
|
|
||||||
}
|
|
||||||
|
|
||||||
#category-advanced > .category-icon {
|
|
||||||
-moz-image-region: rect(0, 224px, 32px, 192px)
|
|
||||||
}
|
|
||||||
|
|
||||||
%ifdef MOZ_SERVICES_SYNC
|
|
||||||
#category-sync > .category-icon {
|
|
||||||
list-style-image: url("chrome://browser/skin/preferences/Options-sync.png");
|
|
||||||
}
|
|
||||||
%endif
|
|
||||||
|
|
||||||
/* Applications Pane Styles */
|
|
||||||
|
|
||||||
#applications-content {
|
|
||||||
padding: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#handlersView {
|
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
border: 1px solid ThreeDShadow;
|
border-width: 0;
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX This style is for bug 740213 and should be removed once that
|
spinbuttons {
|
||||||
bug has a solution. */
|
-moz-appearance: none;
|
||||||
description > html|a {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX Styles Below can be removed once bug 660726 lands */
|
.actionsMenu {
|
||||||
.nav-button {
|
font-family: "Clear Sans", sans-serif;
|
||||||
min-width: 0;
|
font-size: 1.25rem;
|
||||||
|
line-height: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#back-btn:-moz-locale-dir(ltr) {
|
.actionsMenu > .menulist-label-box > .menulist-icon {
|
||||||
list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=toolbar");
|
margin-top: 1px;
|
||||||
|
-moz-margin-start: 1px;
|
||||||
|
-moz-margin-end: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#forward-btn:-moz-locale-dir(ltr) {
|
.actionsMenu > .menulist-label-box > .menulist-label {
|
||||||
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=toolbar");
|
margin-top: 2px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#back-btn:-moz-locale-dir(rtl) {
|
menulist.actionsMenu > .menulist-dropmarker {
|
||||||
list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=toolbar");
|
margin-top: 11px;
|
||||||
}
|
margin-bottom: 11px;
|
||||||
|
|
||||||
#forward-btn:-moz-locale-dir(rtl) {
|
|
||||||
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=toolbar");
|
|
||||||
}
|
|
||||||
|
|
||||||
#back-btn[disabled="true"]:-moz-locale-dir(ltr) {
|
|
||||||
list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=toolbar&state=disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
#forward-btn[disabled="true"]:-moz-locale-dir(ltr) {
|
|
||||||
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=toolbar&state=disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
#back-btn[disabled="true"]:-moz-locale-dir(rtl) {
|
|
||||||
list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=toolbar&state=disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
#forward-btn[disabled="true"]:-moz-locale-dir(rtl) {
|
|
||||||
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=toolbar&state=disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-button .toolbarbutton-text {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
|
|
После Ширина: | Высота: | Размер: 154 B |
|
@ -502,7 +502,7 @@ toolbar .toolbarbutton-1[type="menu-button"]:not(:-moz-any([disabled],[open],[bu
|
||||||
toolbar .toolbarbutton-1:not(:-moz-any([type="menu-button"],[disabled],#back-button,#forward-button)):-moz-any(:hover:active,[open],[checked]),
|
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]: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"]:not(:-moz-any([disabled],[open],[buttonover])):hover:active > .toolbarbutton-menubutton-dropmarker,
|
||||||
toolbar .toolbarbutton-1[type="menu-button"][open] > .toolbarbutton-menubutton-dropmarker {
|
toolbar .toolbarbutton-1[type="menu-button"][open]:not([disabled]) > .toolbarbutton-menubutton-dropmarker {
|
||||||
background: hsla(0,0%,0%,.02) linear-gradient(hsla(0,0%,0%,.12), hsla(0,0%,0%,0)) border-box;
|
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);
|
border-color: hsla(0,0%,0%,.3);
|
||||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.5),
|
box-shadow: 0 1px 0 hsla(0,0%,100%,.5),
|
||||||
|
|
|
@ -168,6 +168,7 @@ browser.jar:
|
||||||
skin/classic/browser/feeds/videoFeedIcon16.png (feeds/feedIcon16.png)
|
skin/classic/browser/feeds/videoFeedIcon16.png (feeds/feedIcon16.png)
|
||||||
skin/classic/browser/feeds/audioFeedIcon.png (feeds/feedIcon.png)
|
skin/classic/browser/feeds/audioFeedIcon.png (feeds/feedIcon.png)
|
||||||
skin/classic/browser/feeds/audioFeedIcon16.png (feeds/feedIcon16.png)
|
skin/classic/browser/feeds/audioFeedIcon16.png (feeds/feedIcon16.png)
|
||||||
|
skin/classic/browser/fonts/ClearSans-Regular.ttf (../shared/ClearSans-Regular.ttf)
|
||||||
skin/classic/browser/newtab/newTab.css (newtab/newTab.css)
|
skin/classic/browser/newtab/newTab.css (newtab/newTab.css)
|
||||||
skin/classic/browser/newtab/controls.png (newtab/controls.png)
|
skin/classic/browser/newtab/controls.png (newtab/controls.png)
|
||||||
skin/classic/browser/newtab/controls@2x.png (newtab/controls@2x.png)
|
skin/classic/browser/newtab/controls@2x.png (newtab/controls@2x.png)
|
||||||
|
@ -223,6 +224,14 @@ browser.jar:
|
||||||
skin/classic/browser/preferences/saveFile.png (preferences/saveFile.png)
|
skin/classic/browser/preferences/saveFile.png (preferences/saveFile.png)
|
||||||
* skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
|
* skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
|
||||||
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
||||||
|
skin/classic/browser/preferences/in-content/check.png (preferences/in-content/check.png)
|
||||||
|
skin/classic/browser/preferences/in-content/check@2x.png (preferences/in-content/check@2x.png)
|
||||||
|
skin/classic/browser/preferences/in-content/icons.png (preferences/in-content/icons.png)
|
||||||
|
skin/classic/browser/preferences/in-content/icons@2x.png (preferences/in-content/icons@2x.png)
|
||||||
|
skin/classic/browser/preferences/in-content/header.png (preferences/in-content/icons@2x.png)
|
||||||
|
skin/classic/browser/preferences/in-content/sorter.png (preferences/in-content/sorter.png)
|
||||||
|
skin/classic/browser/preferences/in-content/dropdown.png (preferences/in-content/dropdown.png)
|
||||||
|
skin/classic/browser/preferences/in-content/dropdown-disabled.png (preferences/in-content/dropdown-disabled.png)
|
||||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||||
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
||||||
skin/classic/browser/social/services-16.png (social/services-16.png)
|
skin/classic/browser/social/services-16.png (social/services-16.png)
|
||||||
|
|
После Ширина: | Высота: | Размер: 593 B |
После Ширина: | Высота: | Размер: 1.2 KiB |
После Ширина: | Высота: | Размер: 250 B |
После Ширина: | Высота: | Размер: 250 B |
После Ширина: | Высота: | Размер: 12 KiB |
После Ширина: | Высота: | Размер: 30 KiB |
|
@ -2,182 +2,134 @@
|
||||||
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
- 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/. */
|
- You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
%include ../../shared.inc
|
%include ../../../shared/in-content/preferences.css
|
||||||
|
|
||||||
@import url("chrome://global/skin/inContentUI.css");
|
menulist:not([editable="true"]) > .menulist-dropmarker {
|
||||||
|
display: -moz-box;
|
||||||
@namespace html "http://www.w3.org/1999/xhtml";
|
margin-top: 1px;
|
||||||
|
margin-bottom: 1px;
|
||||||
#header {
|
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
caption {
|
checkbox:hover::before,
|
||||||
font-size: 1.667rem;
|
checkbox[checked]::before {
|
||||||
|
margin-bottom: -2px;
|
||||||
|
-moz-margin-end: -20px;
|
||||||
|
-moz-margin-start: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-content {
|
radio:hover::before,
|
||||||
max-width: 800px;
|
radio[selected]::before {
|
||||||
|
-moz-margin-end: -18px;
|
||||||
|
-moz-margin-start: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
prefpane > .content-box {
|
.numberbox-input-box {
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Category List */
|
|
||||||
|
|
||||||
#categories {
|
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
border: none;
|
border-width: 0;
|
||||||
-moz-margin-end: -1px;
|
|
||||||
background-color: transparent;
|
|
||||||
position: relative;
|
|
||||||
margin-top: 31px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.category {
|
spinbuttons {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
color: #252F3B;
|
|
||||||
border-width: 1px;
|
|
||||||
border-style: solid;
|
|
||||||
border-color: transparent;
|
|
||||||
padding: 10px 4px;
|
|
||||||
-moz-padding-end: 8px;
|
|
||||||
-moz-box-align: center;
|
|
||||||
overflow: hidden;
|
|
||||||
min-height: 0;
|
|
||||||
height: 52px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.category:-moz-locale-dir(ltr) {
|
.spinbuttons-up {
|
||||||
border-top-left-radius: 5px;
|
margin-top: 0 !important;
|
||||||
border-bottom-left-radius: 5px;
|
border-radius: 4px 4px 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category:-moz-locale-dir(rtl) {
|
.spinbuttons-down {
|
||||||
border-top-right-radius: 5px;
|
margin-bottom: 0 !important;
|
||||||
border-bottom-right-radius: 5px;
|
border-radius: 0 0 4px 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category[selected] {
|
.spinbuttons-button > .button-box {
|
||||||
background-color: rgba(255, 255, 255, 0.35);
|
-moz-padding-start: 2px !important;
|
||||||
color: -moz-dialogtext;
|
-moz-padding-end: 3px !important;
|
||||||
border-color: rgba(50, 65, 92, 0.4);
|
|
||||||
-moz-border-end-color: #C9CFD7;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-name {
|
.spinbuttons-button > .button-box > .button-text {
|
||||||
font-size: 1.5rem;
|
|
||||||
-moz-padding-end: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Maximize the size of the viewport when the window is small */
|
|
||||||
@media (max-width: 800px) {
|
|
||||||
.category-name {
|
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.actionsMenu > .menulist-label-box > .menulist-icon {
|
||||||
|
margin-top: 2px;
|
||||||
|
-moz-margin-start: 2px;
|
||||||
|
-moz-margin-end: 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
description {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-resolution: 2dppx) {
|
||||||
|
checkbox:hover::before,
|
||||||
|
checkbox[checked]::before {
|
||||||
|
background-size: cover;
|
||||||
|
background-image: -moz-image-rect(url("chrome://browser/skin/preferences/in-content/check@2x.png"), 0, 30, 30, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkbox[checked]::before {
|
||||||
|
background-image: -moz-image-rect(url("chrome://browser/skin/preferences/in-content/check@2x.png"), 0, 60, 30, 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-icon {
|
.category-icon {
|
||||||
width: 32px;
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons@2x.png");
|
||||||
height: 32px;
|
|
||||||
-moz-margin-start: 6px;
|
|
||||||
list-style-image: url("chrome://browser/skin/preferences/Options.png");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#category-general > .category-icon {
|
#category-general > .category-icon {
|
||||||
-moz-image-region: rect(0, 32px, 32px, 0);
|
-moz-image-region: rect(0, 48px, 48px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-general[selected] > .category-icon {
|
||||||
|
-moz-image-region: rect(48px, 48px, 96px, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#category-content > .category-icon {
|
#category-content > .category-icon {
|
||||||
-moz-image-region: rect(0, 96px, 32px, 64px)
|
-moz-image-region: rect(0, 96px, 48px, 48px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-content[selected] > .category-icon {
|
||||||
|
-moz-image-region: rect(48px, 96px, 96px, 48px);
|
||||||
}
|
}
|
||||||
|
|
||||||
#category-application > .category-icon {
|
#category-application > .category-icon {
|
||||||
-moz-image-region: rect(0, 128px, 32px, 96px)
|
-moz-image-region: rect(0, 144px, 48px, 96px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-application[selected] > .category-icon {
|
||||||
|
-moz-image-region: rect(48px, 144px, 96px, 96px);
|
||||||
}
|
}
|
||||||
|
|
||||||
#category-privacy > .category-icon {
|
#category-privacy > .category-icon {
|
||||||
-moz-image-region: rect(0, 160px, 32px, 128px)
|
-moz-image-region: rect(0, 192px, 48px, 144px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-privacy[selected] > .category-icon {
|
||||||
|
-moz-image-region: rect(48px, 192px, 96px, 144px);
|
||||||
}
|
}
|
||||||
|
|
||||||
#category-security > .category-icon {
|
#category-security > .category-icon {
|
||||||
-moz-image-region: rect(0, 192px, 32px, 160px)
|
-moz-image-region: rect(0, 240px, 48px, 192px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-security[selected] > .category-icon {
|
||||||
|
-moz-image-region: rect(48px, 240px, 96px, 192px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-sync > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 288px, 48px, 240px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-sync[selected] > .category-icon {
|
||||||
|
-moz-image-region: rect(48px, 288px, 96px, 240px);
|
||||||
}
|
}
|
||||||
|
|
||||||
#category-advanced > .category-icon {
|
#category-advanced > .category-icon {
|
||||||
-moz-image-region: rect(0, 224px, 32px, 192px)
|
-moz-image-region: rect(0, 336px, 48px, 288px);
|
||||||
}
|
}
|
||||||
|
|
||||||
%ifdef MOZ_SERVICES_SYNC
|
#category-advanced[selected] > .category-icon {
|
||||||
#category-sync > .category-icon {
|
-moz-image-region: rect(48px, 336px, 96px, 288px);
|
||||||
list-style-image: url("chrome://browser/skin/preferences/Options-sync.png");
|
|
||||||
}
|
}
|
||||||
%endif
|
|
||||||
|
|
||||||
/* Applications Pane Styles */
|
|
||||||
|
|
||||||
#applications-content {
|
|
||||||
padding: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#handlersView {
|
|
||||||
-moz-appearance: none;
|
|
||||||
border: 1px solid rgba(60,73,97,0.5);
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX This style is for bug 740213 and should be removed once that
|
|
||||||
bug has a solution. */
|
|
||||||
description > html|a {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX Styles Below can be removed once bug 660726 lands */
|
|
||||||
.nav-button {
|
|
||||||
list-style-image: url(chrome://mozapps/skin/extensions/navigation.png);
|
|
||||||
}
|
|
||||||
|
|
||||||
#back-btn:-moz-locale-dir(ltr),
|
|
||||||
#forward-btn:-moz-locale-dir(rtl) {
|
|
||||||
border-top-right-radius: 0;
|
|
||||||
border-bottom-right-radius: 0;
|
|
||||||
border-right: none;
|
|
||||||
-moz-image-region: rect(0, 20px, 20px, 0);
|
|
||||||
padding-right: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#back-btn:-moz-locale-dir(rtl),
|
|
||||||
#forward-btn:-moz-locale-dir(ltr) {
|
|
||||||
border-top-left-radius: 0;
|
|
||||||
border-bottom-left-radius: 0;
|
|
||||||
-moz-image-region: rect(0, 40px, 20px, 20px);
|
|
||||||
padding-left: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-button {
|
|
||||||
-moz-appearance: none;
|
|
||||||
padding: 0 4px;
|
|
||||||
margin: 0;
|
|
||||||
height: 22px;
|
|
||||||
border: 1px solid rgba(60,73,97,0.5);
|
|
||||||
border-radius: @toolbarbuttonCornerRadius@;
|
|
||||||
box-shadow: inset 0 1px rgba(255,255,255,0.25), 0 1px rgba(255,255,255,0.25);
|
|
||||||
background: linear-gradient(rgba(255,255,255,0.45), rgba(255,255,255,0));
|
|
||||||
background-clip: padding-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-button .toolbarbutton-text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-button[disabled="true"] .toolbarbutton-icon {
|
|
||||||
opacity: 0.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-button:not([disabled="true"]):active:hover,
|
|
||||||
.header-button[open="true"] {
|
|
||||||
border-color: rgba(45,54,71,0.7);
|
|
||||||
box-shadow: inset 0 0 4px rgb(45,54,71), 0 1px rgba(255,255,255,0.25);
|
|
||||||
background-image: linear-gradient(rgba(45,54,71,0.6), rgba(45,54,71,0));
|
|
||||||
}
|
}
|
||||||
|
|
После Ширина: | Высота: | Размер: 154 B |
|
@ -163,11 +163,15 @@ panelmultiview[nosubviews=true] > .panel-viewcontainer > .panel-viewstack > .pan
|
||||||
|
|
||||||
.panelUI-grid .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-multiline-text,
|
.panelUI-grid .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-multiline-text,
|
||||||
.panelUI-grid .toolbarbutton-1 > .toolbarbutton-multiline-text {
|
.panelUI-grid .toolbarbutton-1 > .toolbarbutton-multiline-text {
|
||||||
-moz-hyphens: auto;
|
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
max-height: 2.2em;
|
max-height: 2.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.panelUI-grid .toolbarbutton-1:not([auto-hyphens="off"]) > .toolbarbutton-menubutton-button > .toolbarbutton-multiline-text,
|
||||||
|
.panelUI-grid .toolbarbutton-1:not([auto-hyphens="off"]) > .toolbarbutton-multiline-text {
|
||||||
|
-moz-hyphens: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.panelUI-grid:not([customize-transitioning]) .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-multiline-text,
|
.panelUI-grid:not([customize-transitioning]) .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-multiline-text,
|
||||||
.panelUI-grid:not([customize-transitioning]) .toolbarbutton-1 > .toolbarbutton-multiline-text {
|
.panelUI-grid:not([customize-transitioning]) .toolbarbutton-1 > .toolbarbutton-multiline-text {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -0,0 +1,751 @@
|
||||||
|
%if 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/. */
|
||||||
|
%endif
|
||||||
|
@namespace html "http://www.w3.org/1999/xhtml";
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Clear Sans";
|
||||||
|
src: url("chrome://browser/skin/fonts/ClearSans-Regular.ttf");
|
||||||
|
}
|
||||||
|
|
||||||
|
page {
|
||||||
|
-moz-appearance: none;
|
||||||
|
background-image: linear-gradient(#FFFFFF, #EDEDED 100px);
|
||||||
|
}
|
||||||
|
|
||||||
|
caption {
|
||||||
|
-moz-appearance: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.caption-text {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 22px;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefpane > .content-box {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefpane {
|
||||||
|
padding: 40px 48px 48px;
|
||||||
|
font-family: "Clear Sans", sans-serif;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 22px;
|
||||||
|
color: #424E5A;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefpane > .content-box {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* groupboxes */
|
||||||
|
|
||||||
|
groupbox {
|
||||||
|
-moz-appearance: none;
|
||||||
|
border: none;
|
||||||
|
margin-top: 15px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
-moz-margin-start: 60px;
|
||||||
|
-moz-padding-start: 0;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
groupbox label {
|
||||||
|
-moz-margin-start: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tabpanels and tabs */
|
||||||
|
|
||||||
|
tabpanels {
|
||||||
|
-moz-appearance: none;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 22px;
|
||||||
|
color: #424E5A;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
tabs {
|
||||||
|
-moz-margin-start: 60px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
border-top: 2px solid;
|
||||||
|
border-bottom: 2px solid;
|
||||||
|
-moz-border-top-colors: #BBBBBB #F9F9F9;
|
||||||
|
-moz-border-bottom-colors: #F9F9F9 #BBBBBB;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs-left,
|
||||||
|
.tabs-right {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
tab {
|
||||||
|
-moz-appearance: none;
|
||||||
|
margin-top: 0;
|
||||||
|
padding: 0;
|
||||||
|
-moz-margin-end: 30px;
|
||||||
|
min-height: 60px;
|
||||||
|
background-color: transparent;
|
||||||
|
border-width: 0;
|
||||||
|
border-bottom: 3px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
tab[selected] {
|
||||||
|
border-bottom-color: #FF9500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-text {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
line-height: 22px;
|
||||||
|
color: #737980;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tab:not([selected]):hover > .tab-middle > .tab-text {
|
||||||
|
background-color: rgba(255,255,255,0.5);
|
||||||
|
border-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
tab:not([selected]):hover:active > .tab-middle > .tab-text {
|
||||||
|
background-color: rgba(0,0,0,0.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
tab[selected] > .tab-middle > .tab-text {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #424E5A;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* buttons and menulists */
|
||||||
|
|
||||||
|
button,
|
||||||
|
menulist {
|
||||||
|
-moz-appearance: none;
|
||||||
|
height: 30px;
|
||||||
|
max-height: 30px;
|
||||||
|
color: #737980;
|
||||||
|
line-height: 20px;
|
||||||
|
text-shadow: 0 1px 1px #FEFFFE;
|
||||||
|
border: 1px solid rgba(23,50,77,0.4);
|
||||||
|
-moz-border-top-colors: none !important;
|
||||||
|
-moz-border-right-colors: none !important;
|
||||||
|
-moz-border-bottom-colors: none !important;
|
||||||
|
-moz-border-left-colors: none !important;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0 1px 1px 0 #FFFFFF, inset 0 2px 2px 0 #FFFFFF;
|
||||||
|
background-color: #F1F1F1;
|
||||||
|
background-image: linear-gradient(#FFFFFF, rgba(255,255,255,0.1));
|
||||||
|
}
|
||||||
|
|
||||||
|
button:not([disabled]):hover,
|
||||||
|
menulist:not([disabled]):hover {
|
||||||
|
background-image: linear-gradient(#FFFFFF, rgba(255,255,255,0.6));
|
||||||
|
}
|
||||||
|
|
||||||
|
button:not([disabled]):hover:active,
|
||||||
|
menulist[open="true"]:not([disabled]) {
|
||||||
|
background-image: linear-gradient(rgba(255,255,255,0.1),
|
||||||
|
rgba(255,255,255,0.6));
|
||||||
|
}
|
||||||
|
|
||||||
|
button[disabled],
|
||||||
|
menulist[disabled] {
|
||||||
|
background-image: linear-gradient(rgba(255,255,255,0.5),
|
||||||
|
rgba(255,255,255,0.1));
|
||||||
|
border-color: rgba(23,50,77,0.25);
|
||||||
|
color: rgba(115,121,128,0.5);
|
||||||
|
text-shadow: 0 1px 1px #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
button > .button-box,
|
||||||
|
menulist > .menulist-label-box {
|
||||||
|
padding-right: 10px !important;
|
||||||
|
padding-left: 10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
button[type="menu"] > .button-box > .button-menu-dropmarker {
|
||||||
|
-moz-appearance: none;
|
||||||
|
margin: 1px 0;
|
||||||
|
-moz-margin-start: 10px;
|
||||||
|
padding: 0;
|
||||||
|
width: 10px;
|
||||||
|
height: 15px;
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/in-content/dropdown.png")
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinbuttons-button {
|
||||||
|
-moz-margin-start: 10px !important;
|
||||||
|
-moz-margin-end: 2px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinbuttons-up {
|
||||||
|
margin-top: 2px !important;
|
||||||
|
border-radius: 4px 4px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinbuttons-down {
|
||||||
|
margin-bottom: 2px !important;
|
||||||
|
border-radius: 0 0 4px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinbuttons-button > .button-box {
|
||||||
|
padding: 1px 5px 2px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinbuttons-up > .button-box > .button-icon {
|
||||||
|
list-style-image: url("chrome://global/skin/arrow/arrow-up.gif");
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinbuttons-up[disabled] > .button-box > .button-icon {
|
||||||
|
list-style-image: url("chrome://global/skin/arrow/arrow-up-dis.gif");
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinbuttons-down > .button-box > .button-icon {
|
||||||
|
list-style-image: url("chrome://global/skin/arrow/arrow-dn.gif");
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinbuttons-down[disabled] > .button-box > .button-icon {
|
||||||
|
list-style-image: url("chrome://global/skin/arrow/arrow-dn-dis.gif");
|
||||||
|
}
|
||||||
|
|
||||||
|
menulist:not([editable="true"]) > .menulist-dropmarker {
|
||||||
|
-moz-appearance: none;
|
||||||
|
-moz-margin-end: 10px;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/in-content/dropdown.png")
|
||||||
|
}
|
||||||
|
|
||||||
|
menulist[disabled]:not([editable="true"]) > .menulist-dropmarker {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/in-content/dropdown-disabled.png")
|
||||||
|
}
|
||||||
|
|
||||||
|
menulist > menupopup,
|
||||||
|
button[type="menu"] > menupopup {
|
||||||
|
-moz-appearance: none;
|
||||||
|
border: 1px solid rgba(23,50,77,0.4);
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
menulist > menupopup menu,
|
||||||
|
menulist > menupopup menuitem,
|
||||||
|
button[type="menu"] > menupopup menu,
|
||||||
|
button[type="menu"] > menupopup menuitem {
|
||||||
|
-moz-appearance: none;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 22px;
|
||||||
|
height: 40px;
|
||||||
|
color: #737980;
|
||||||
|
}
|
||||||
|
|
||||||
|
menulist > menupopup > menu[_moz-menuactive="true"],
|
||||||
|
menulist > menupopup > menuitem[_moz-menuactive="true"],
|
||||||
|
button[type="menu"] > menupopup > menu[_moz-menuactive="true"],
|
||||||
|
button[type="menu"] > menupopup > menuitem[_moz-menuactive="true"] {
|
||||||
|
color: #FFFFFF;
|
||||||
|
background-image: linear-gradient(#4CB1FF, #1792E5);
|
||||||
|
}
|
||||||
|
|
||||||
|
menulist > menupopup menuseparator,
|
||||||
|
button[type="menu"] > menupopup menuseparator {
|
||||||
|
-moz-appearance: none;
|
||||||
|
margin-top: 2px;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
padding: 0;
|
||||||
|
border-top: 1px solid rgba(23,50,77,0.4);
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* textboxes */
|
||||||
|
|
||||||
|
textbox {
|
||||||
|
-moz-appearance: none;
|
||||||
|
height: 30px;
|
||||||
|
color: #737980;
|
||||||
|
line-height: 20px;
|
||||||
|
text-shadow: 0 1px 1px #FEFFFE;
|
||||||
|
padding-right: 10px;
|
||||||
|
padding-left: 10px;
|
||||||
|
border: 1px solid rgba(23,50,77,0.4);
|
||||||
|
-moz-border-top-colors: none !important;
|
||||||
|
-moz-border-right-colors: none !important;
|
||||||
|
-moz-border-bottom-colors: none !important;
|
||||||
|
-moz-border-left-colors: none !important;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0 1px 1px 0 #FFFFFF, inset 0 2px 2px 0 rgba(0,0,0,0.03);
|
||||||
|
background-color: #F1F1F1;
|
||||||
|
background-image: linear-gradient(#FFFFFF, rgba(255,255,255,0.8));
|
||||||
|
}
|
||||||
|
|
||||||
|
textbox[focused] {
|
||||||
|
color: #424E5A;
|
||||||
|
border-color: #0096DC;
|
||||||
|
box-shadow: 0 0 2px 2px rgba(0,150,220,0.35), inset 0 0 2px 0 #0096DC;
|
||||||
|
}
|
||||||
|
|
||||||
|
textbox[disabled] {
|
||||||
|
color: rgba(115,121,128,0.5);
|
||||||
|
border-color: rgba(23,50,77,0.25);
|
||||||
|
background-image: linear-gradient(rgba(255,255,255,0.5), rgba(255,255,255,0.4));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Links */
|
||||||
|
|
||||||
|
.text-link,
|
||||||
|
.inline-link,
|
||||||
|
html|a.inline-link {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 22px;
|
||||||
|
color: #0096DC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-link:hover,
|
||||||
|
.inline-link:hover {
|
||||||
|
color: #4CB1FF;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-link:hover:active,
|
||||||
|
.inline-link:hover:active {
|
||||||
|
color: #FF9500;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checkboxes and radio buttons */
|
||||||
|
|
||||||
|
checkbox {
|
||||||
|
margin: 7px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-check {
|
||||||
|
-moz-appearance: none;
|
||||||
|
width: 23px;
|
||||||
|
height: 23px;
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 1px solid rgba(23,50,77,0.40);
|
||||||
|
-moz-margin-end: 10px;
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
background-image: linear-gradient(#ffffff 0%, rgba(255,255,255,0.80) 100%);
|
||||||
|
box-shadow: 0 1px 1px 0 #ffffff, inset 0 2px 0 0 rgba(0,0,0,0.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-check[checked] {
|
||||||
|
border-color: #0096dc;
|
||||||
|
box-shadow: 0 0 2px 2px rgba(0,150,220,0.35), inset 0 0 2px 0 #0096dc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-label-box {
|
||||||
|
-moz-margin-start: -1px; /* negative margin for the transparent border */
|
||||||
|
-moz-padding-start: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkbox:hover::before,
|
||||||
|
checkbox[checked]::before {
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
width: 15px;
|
||||||
|
height: 10px;
|
||||||
|
background-image: url("chrome://browser/skin/preferences/in-content/check.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
checkbox[checked]::before {
|
||||||
|
background-position: -15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-check {
|
||||||
|
-moz-appearance: none;
|
||||||
|
width: 23px;
|
||||||
|
height: 23px;
|
||||||
|
border: 1px solid rgba(23,50,77,0.40);
|
||||||
|
border-radius: 50%;
|
||||||
|
-moz-margin-end: 10px;
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
background-image: linear-gradient(#ffffff 0%, rgba(255,255,255,0.80) 100%);
|
||||||
|
box-shadow: 0 1px 1px 0 #ffffff, inset 0 2px 0 0 rgba(0,0,0,0.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-check[selected] {
|
||||||
|
border-color: #0096dc;
|
||||||
|
box-shadow: 0 0 2px 2px rgba(0,150,220,0.35), inset 0 0 2px 0 #0096dc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-label-box {
|
||||||
|
-moz-margin-start: -1px; /* negative margin for the transparent border */
|
||||||
|
-moz-margin-end: 10px;
|
||||||
|
-moz-padding-start: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
radio:hover::before,
|
||||||
|
radio[selected]::before {
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
width: 11px;
|
||||||
|
height: 11px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
background-image: linear-gradient(rgba(76,177,255,0.25) 0%, rgba(23,146,229,0.25) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
radio[selected]::before {
|
||||||
|
background-image: linear-gradient(#4cb1ff 0%, #1792e5 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Category List */
|
||||||
|
|
||||||
|
#categories {
|
||||||
|
-moz-appearance: none;
|
||||||
|
background-color: #424e5a;
|
||||||
|
-moz-border-end: 1px solid rgba(0,0,0,0.20);
|
||||||
|
padding-top: 39px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category {
|
||||||
|
-moz-appearance: none;
|
||||||
|
color: rgba(241,241,241,0.70);
|
||||||
|
border: 1px solid transparent;
|
||||||
|
-moz-border-end-width: 0;
|
||||||
|
-moz-padding-start: 14px;
|
||||||
|
-moz-padding-end: 21px;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
min-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category:hover {
|
||||||
|
background-color: rgba(255,255,255,0.15);
|
||||||
|
border-color: rgba(255,255,255,0.20);
|
||||||
|
}
|
||||||
|
|
||||||
|
.category[selected] {
|
||||||
|
background-color: rgba(0,0,0,0.20);
|
||||||
|
border-color: rgba(255,255,255,0.20);
|
||||||
|
-moz-border-start-width: 3px;
|
||||||
|
-moz-border-start-color: #ff9500;
|
||||||
|
-moz-padding-start: 12px;
|
||||||
|
color: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-name {
|
||||||
|
line-height: 22px;
|
||||||
|
font-family: "Clear Sans", sans-serif;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
-moz-padding-start: 9px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-general > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 24px, 24px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-general[selected] > .category-icon {
|
||||||
|
-moz-image-region: rect(24px, 24px, 48px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-content > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 48px, 24px, 24px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-content[selected] > .category-icon {
|
||||||
|
-moz-image-region: rect(24px, 48px, 48px, 24px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-application > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 72px, 24px, 48px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-application[selected] > .category-icon {
|
||||||
|
-moz-image-region: rect(24px, 72px, 48px, 48px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-privacy > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 96px, 24px, 72px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-privacy[selected] > .category-icon {
|
||||||
|
-moz-image-region: rect(24px, 96px, 48px, 72px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-security > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 120px, 24px, 96px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-security[selected] > .category-icon {
|
||||||
|
-moz-image-region: rect(24px, 120px, 48px, 96px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-sync > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 144px, 24px, 120px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-sync[selected] > .category-icon {
|
||||||
|
-moz-image-region: rect(24px, 144px, 48px, 120px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-advanced > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 168px, 24px, 144px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-advanced[selected] > .category-icon {
|
||||||
|
-moz-image-region: rect(24px, 168px, 48px, 144px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* header */
|
||||||
|
|
||||||
|
.header {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-icon {
|
||||||
|
width: 40px;
|
||||||
|
max-height: 40px;
|
||||||
|
-moz-margin-end: 20px;
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/in-content/header.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-name {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: 40px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header-general > .header-icon {
|
||||||
|
-moz-image-region: rect(3px, 45px, 45px, 3px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#header-content > .header-icon {
|
||||||
|
-moz-image-region: rect(3px, 93px, 45px, 51px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#header-application > .header-icon {
|
||||||
|
-moz-image-region: rect(3px, 141px, 45px, 99px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#header-privacy > .header-icon {
|
||||||
|
-moz-image-region: rect(3px, 189px, 45px, 147px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#header-security > .header-icon {
|
||||||
|
-moz-image-region: rect(3px, 237px, 45px, 195px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#header-sync > .header-icon {
|
||||||
|
-moz-image-region: rect(3px, 285px, 45px, 243px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#header-advanced > .header-icon {
|
||||||
|
-moz-image-region: rect(3px, 333px, 45px, 291px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.indent {
|
||||||
|
margin-top: 7px;
|
||||||
|
margin-bottom: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* General Pane */
|
||||||
|
|
||||||
|
filefield {
|
||||||
|
-moz-appearance: none;
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fileFieldContentBox {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fileFieldIcon {
|
||||||
|
-moz-margin-start: 10px;
|
||||||
|
-moz-margin-end: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fileFieldLabel {
|
||||||
|
-moz-margin-start: -26px;
|
||||||
|
-moz-padding-start: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chooseFolder {
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Applications Pane Styles */
|
||||||
|
|
||||||
|
#applications-content {
|
||||||
|
-moz-margin-start: 60px;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#handlersView {
|
||||||
|
-moz-appearance: none;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 22px;
|
||||||
|
color: #737980;
|
||||||
|
border: 1px solid rgba(23,50,77,0.4);
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #F1F1F1;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#typeColumn,
|
||||||
|
#actionColumn {
|
||||||
|
-moz-appearance: none;
|
||||||
|
font-family: "Clear Sans", sans-serif;
|
||||||
|
line-height: 20px;
|
||||||
|
color: #737980;
|
||||||
|
height: 36px;
|
||||||
|
padding: 0 10px;
|
||||||
|
background-color: #F7F7F7;
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
-moz-border-top-colors: none;
|
||||||
|
-moz-border-right-colors: none;
|
||||||
|
-moz-border-bottom-colors: none;
|
||||||
|
-moz-border-left-colors: none;
|
||||||
|
text-shadow: 0 1px 1px #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
#typeColumn:-moz-locale-dir(ltr),
|
||||||
|
#actionColumn:-moz-locale-dir(rtl) {
|
||||||
|
border-top-left-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#typeColumn:-moz-locale-dir(rtl),
|
||||||
|
#actionColumn:-moz-locale-dir(ltr) {
|
||||||
|
border-top-right-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#typeColumn:hover,
|
||||||
|
#actionColumn:hover {
|
||||||
|
border-color: #737980;
|
||||||
|
}
|
||||||
|
|
||||||
|
#typeColumn:hover:active,
|
||||||
|
#actionColumn:hover:active {
|
||||||
|
padding: 0 10px;
|
||||||
|
border-color: #0096DC;
|
||||||
|
box-shadow: 0 0 2px 2px rgba(0,150,220,0.35), inset 0 0 2px 0 #0096DC;
|
||||||
|
}
|
||||||
|
|
||||||
|
#typeColumn > .treecol-sortdirection[sortDirection=ascending],
|
||||||
|
#actionColumn > .treecol-sortdirection[sortDirection=ascending],
|
||||||
|
#typeColumn > .treecol-sortdirection[sortDirection=descending],
|
||||||
|
#actionColumn > .treecol-sortdirection[sortDirection=descending] {
|
||||||
|
-moz-appearance: none;
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/in-content/sorter.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
#typeColumn > .treecol-sortdirection[sortDirection=descending],
|
||||||
|
#actionColumn > .treecol-sortdirection[sortDirection=descending] {
|
||||||
|
transform: scaleY(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#handlersView > richlistitem {
|
||||||
|
min-height: 40px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.typeIcon {
|
||||||
|
-moz-margin-start: 10px !important;
|
||||||
|
-moz-margin-end: 9px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionIcon {
|
||||||
|
-moz-margin-start: 11px !important;
|
||||||
|
-moz-margin-end: 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionsMenu {
|
||||||
|
height: 40px;
|
||||||
|
max-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionsMenu > menupopup > menuitem {
|
||||||
|
-moz-padding-start: 10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionsMenu > menupopup > menuitem > .menu-iconic-left {
|
||||||
|
-moz-margin-end: 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX This style is for bug 740213 and should be removed once that
|
||||||
|
bug has a solution. */
|
||||||
|
description > html|a {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Content Pane */
|
||||||
|
|
||||||
|
#defaultFontSize {
|
||||||
|
min-width: 5.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Security Pane */
|
||||||
|
|
||||||
|
/* Add margins to this buttons to unsqueeze the checkboxed in same hbox */
|
||||||
|
#addonExceptions,
|
||||||
|
#cookieExceptions,
|
||||||
|
#passwordExceptions,
|
||||||
|
#changeMasterPassword {
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sync Pane */
|
||||||
|
|
||||||
|
#syncEnginesList {
|
||||||
|
-moz-appearance: none;
|
||||||
|
color: #737980;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid rgba(23,50,77,0.4);
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #F1F1F1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Advanced Pane */
|
||||||
|
|
||||||
|
#advancedPrefs {
|
||||||
|
padding-bottom: 0; /* no padding needed in inContent prefs */
|
||||||
|
}
|
||||||
|
|
||||||
|
#encryptionPanel {
|
||||||
|
margin-top: 15px;
|
||||||
|
-moz-margin-start: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#offlineAppsList {
|
||||||
|
-moz-appearance: none;
|
||||||
|
color: #737980;
|
||||||
|
padding: 2px;
|
||||||
|
border: 1px solid rgba(23,50,77,0.4);
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #F1F1F1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#telemetryLearnMore,
|
||||||
|
#FHRLearnMore,
|
||||||
|
#crashReporterLearnMore {
|
||||||
|
/* center the links */
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
|
@ -799,7 +799,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
||||||
border-color: hsla(210,54%,20%,.3) hsla(210,54%,20%,.35) hsla(210,54%,20%,.4);
|
border-color: hsla(210,54%,20%,.3) hsla(210,54%,20%,.35) hsla(210,54%,20%,.4);
|
||||||
box-shadow: 0 1px 1px hsla(210,54%,20%,.1) inset,
|
box-shadow: 0 1px 1px hsla(210,54%,20%,.1) inset,
|
||||||
0 0 1px hsla(210,54%,20%,.2) inset,
|
0 0 1px hsla(210,54%,20%,.2) inset,
|
||||||
/* allows windows-keyhole-forward-clip-path to be used for non-hover as well as hover: */
|
/* allows keyhole-forward-clip-path to be used for non-hover as well as hover: */
|
||||||
0 1px 0 hsla(210,54%,20%,0),
|
0 1px 0 hsla(210,54%,20%,0),
|
||||||
0 0 2px hsla(210,54%,20%,0);
|
0 0 2px hsla(210,54%,20%,0);
|
||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
|
@ -853,7 +853,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
||||||
#forward-button > .toolbarbutton-icon {
|
#forward-button > .toolbarbutton-icon {
|
||||||
background-clip: padding-box !important;
|
background-clip: padding-box !important;
|
||||||
/*mask: url(keyhole-forward-mask.svg#mask); XXX: this regresses twinopen */
|
/*mask: url(keyhole-forward-mask.svg#mask); XXX: this regresses twinopen */
|
||||||
clip-path: url(chrome://browser/content/browser.xul#windows-keyhole-forward-clip-path) !important;
|
clip-path: url(chrome://browser/content/browser.xul#keyhole-forward-clip-path) !important;
|
||||||
margin-left: -6px !important;
|
margin-left: -6px !important;
|
||||||
border-left-style: none !important;
|
border-left-style: none !important;
|
||||||
border-radius: 0 !important;
|
border-radius: 0 !important;
|
||||||
|
@ -1156,7 +1156,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
||||||
}
|
}
|
||||||
|
|
||||||
@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper {
|
@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper {
|
||||||
clip-path: url("chrome://browser/content/browser.xul#windows-urlbar-back-button-clip-path");
|
clip-path: url("chrome://browser/content/browser.xul#urlbar-back-button-clip-path");
|
||||||
}
|
}
|
||||||
|
|
||||||
@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar {
|
@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar {
|
||||||
|
|
|
@ -126,6 +126,7 @@ browser.jar:
|
||||||
skin/classic/browser/feeds/videoFeedIcon16.png (feeds/feedIcon16.png)
|
skin/classic/browser/feeds/videoFeedIcon16.png (feeds/feedIcon16.png)
|
||||||
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css)
|
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css)
|
||||||
skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
|
skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
|
||||||
|
skin/classic/browser/fonts/ClearSans-Regular.ttf (../shared/ClearSans-Regular.ttf)
|
||||||
skin/classic/browser/newtab/newTab.css (newtab/newTab.css)
|
skin/classic/browser/newtab/newTab.css (newtab/newTab.css)
|
||||||
skin/classic/browser/newtab/controls.png (newtab/controls.png)
|
skin/classic/browser/newtab/controls.png (newtab/controls.png)
|
||||||
skin/classic/browser/places/places.css (places/places.css)
|
skin/classic/browser/places/places.css (places/places.css)
|
||||||
|
@ -159,6 +160,14 @@ browser.jar:
|
||||||
skin/classic/browser/preferences/saveFile.png (preferences/saveFile.png)
|
skin/classic/browser/preferences/saveFile.png (preferences/saveFile.png)
|
||||||
* skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
|
* skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
|
||||||
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
||||||
|
skin/classic/browser/preferences/in-content/check.png (preferences/in-content/check.png)
|
||||||
|
skin/classic/browser/preferences/in-content/check@2x.png (preferences/in-content/check@2x.png)
|
||||||
|
skin/classic/browser/preferences/in-content/icons.png (preferences/in-content/icons.png)
|
||||||
|
skin/classic/browser/preferences/in-content/icons@2x.png (preferences/in-content/icons@2x.png)
|
||||||
|
skin/classic/browser/preferences/in-content/header.png (preferences/in-content/icons@2x.png)
|
||||||
|
skin/classic/browser/preferences/in-content/sorter.png (preferences/in-content/sorter.png)
|
||||||
|
skin/classic/browser/preferences/in-content/dropdown.png (preferences/in-content/dropdown.png)
|
||||||
|
skin/classic/browser/preferences/in-content/dropdown-disabled.png (preferences/in-content/dropdown-disabled.png)
|
||||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||||
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
||||||
skin/classic/browser/social/services-16.png (social/services-16.png)
|
skin/classic/browser/social/services-16.png (social/services-16.png)
|
||||||
|
@ -465,6 +474,7 @@ browser.jar:
|
||||||
skin/classic/aero/browser/feeds/videoFeedIcon16.png (feeds/feedIcon16-aero.png)
|
skin/classic/aero/browser/feeds/videoFeedIcon16.png (feeds/feedIcon16-aero.png)
|
||||||
skin/classic/aero/browser/feeds/subscribe.css (feeds/subscribe.css)
|
skin/classic/aero/browser/feeds/subscribe.css (feeds/subscribe.css)
|
||||||
skin/classic/aero/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
|
skin/classic/aero/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
|
||||||
|
skin/classic/aero/browser/fonts/ClearSans-Regular.ttf (../shared/ClearSans-Regular.ttf)
|
||||||
skin/classic/aero/browser/newtab/newTab.css (newtab/newTab.css)
|
skin/classic/aero/browser/newtab/newTab.css (newtab/newTab.css)
|
||||||
skin/classic/aero/browser/newtab/controls.png (newtab/controls.png)
|
skin/classic/aero/browser/newtab/controls.png (newtab/controls.png)
|
||||||
* skin/classic/aero/browser/places/places.css (places/places-aero.css)
|
* skin/classic/aero/browser/places/places.css (places/places-aero.css)
|
||||||
|
@ -498,6 +508,14 @@ browser.jar:
|
||||||
skin/classic/aero/browser/preferences/saveFile.png (preferences/saveFile-aero.png)
|
skin/classic/aero/browser/preferences/saveFile.png (preferences/saveFile-aero.png)
|
||||||
* skin/classic/aero/browser/preferences/preferences.css (preferences/preferences.css)
|
* skin/classic/aero/browser/preferences/preferences.css (preferences/preferences.css)
|
||||||
* skin/classic/aero/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
* skin/classic/aero/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
||||||
|
skin/classic/aero/browser/preferences/in-content/check.png (preferences/in-content/check.png)
|
||||||
|
skin/classic/aero/browser/preferences/in-content/check@2x.png (preferences/in-content/check@2x.png)
|
||||||
|
skin/classic/aero/browser/preferences/in-content/icons.png (preferences/in-content/icons.png)
|
||||||
|
skin/classic/aero/browser/preferences/in-content/icons@2x.png (preferences/in-content/icons@2x.png)
|
||||||
|
skin/classic/aero/browser/preferences/in-content/header.png (preferences/in-content/icons@2x.png)
|
||||||
|
skin/classic/aero/browser/preferences/in-content/sorter.png (preferences/in-content/sorter.png)
|
||||||
|
skin/classic/aero/browser/preferences/in-content/dropdown.png (preferences/in-content/dropdown.png)
|
||||||
|
skin/classic/aero/browser/preferences/in-content/dropdown-disabled.png (preferences/in-content/dropdown-disabled.png)
|
||||||
skin/classic/aero/browser/preferences/applications.css (preferences/applications.css)
|
skin/classic/aero/browser/preferences/applications.css (preferences/applications.css)
|
||||||
skin/classic/aero/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
skin/classic/aero/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
||||||
skin/classic/aero/browser/social/services-16.png (social/services-16.png)
|
skin/classic/aero/browser/social/services-16.png (social/services-16.png)
|
||||||
|
|
После Ширина: | Высота: | Размер: 593 B |
После Ширина: | Высота: | Размер: 1.2 KiB |