Merge mozilla-central and fx-team

This commit is contained in:
Ed Morley 2013-08-29 11:51:28 +01:00
commit d1c90b0f21
39 changed files with 640 additions and 264 deletions

View File

@ -820,6 +820,8 @@ pref("browser.sessionstore.resume_session_once", false);
// minimal interval between two save operations in milliseconds
pref("browser.sessionstore.interval", 15000);
// interval when device is unplugged
pref("browser.sessionstore.interval_battery", 60000);
// maximum amount of POSTDATA to be saved in bytes per history entry (-1 = all of it)
// (NB: POSTDATA will be saved either entirely or not at all)
pref("browser.sessionstore.postdata", 0);

View File

@ -480,9 +480,6 @@ function HistoryMenu(aPopupShowingEvent) {
// Defining the prototype inheritance in the prototype itself would cause
// browser.js to halt on "PlacesMenu is not defined" error.
this.__proto__.__proto__ = PlacesMenu.prototype;
XPCOMUtils.defineLazyServiceGetter(this, "_ss",
"@mozilla.org/browser/sessionstore;1",
"nsISessionStore");
PlacesMenu.call(this, aPopupShowingEvent,
"place:sort=4&maxResults=15");
}
@ -493,7 +490,7 @@ HistoryMenu.prototype = {
var undoMenu = this._rootElt.getElementsByClassName("recentlyClosedTabsMenu")[0];
// no restorable tabs, so disable menu
if (this._ss.getClosedTabCount(window) == 0)
if (SessionStore.getClosedTabCount(window) == 0)
undoMenu.setAttribute("disabled", true);
else
undoMenu.removeAttribute("disabled");
@ -525,7 +522,7 @@ HistoryMenu.prototype = {
undoPopup.removeChild(undoPopup.firstChild);
// no restorable tabs, so make sure menu is disabled, and return
if (this._ss.getClosedTabCount(window) == 0) {
if (SessionStore.getClosedTabCount(window) == 0) {
undoMenu.setAttribute("disabled", true);
return;
}
@ -534,7 +531,7 @@ HistoryMenu.prototype = {
undoMenu.removeAttribute("disabled");
// populate menu
var undoItems = JSON.parse(this._ss.getClosedTabData(window));
var undoItems = JSON.parse(SessionStore.getClosedTabData(window));
for (var i = 0; i < undoItems.length; i++) {
var m = document.createElement("menuitem");
m.setAttribute("label", undoItems[i].title);
@ -580,7 +577,7 @@ HistoryMenu.prototype = {
var undoMenu = this._rootElt.getElementsByClassName("recentlyClosedWindowsMenu")[0];
// no restorable windows, so disable menu
if (this._ss.getClosedWindowCount() == 0)
if (SessionStore.getClosedWindowCount() == 0)
undoMenu.setAttribute("disabled", true);
else
undoMenu.removeAttribute("disabled");
@ -601,7 +598,7 @@ HistoryMenu.prototype = {
undoPopup.removeChild(undoPopup.firstChild);
// no restorable windows, so make sure menu is disabled, and return
if (this._ss.getClosedWindowCount() == 0) {
if (SessionStore.getClosedWindowCount() == 0) {
undoMenu.setAttribute("disabled", true);
return;
}
@ -610,7 +607,7 @@ HistoryMenu.prototype = {
undoMenu.removeAttribute("disabled");
// populate menu
let undoItems = JSON.parse(this._ss.getClosedWindowData());
let undoItems = JSON.parse(SessionStore.getClosedWindowData());
for (let i = 0; i < undoItems.length; i++) {
let undoItem = undoItems[i];
let otherTabsCount = undoItem.tabs.length - 1;

View File

@ -67,15 +67,13 @@ let TabView = {
if (this.firstUseExperienced) {
// ___ visibility
let sessionstore =
Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
let data = sessionstore.getWindowValue(window, this.VISIBILITY_IDENTIFIER);
let data = SessionStore.getWindowValue(window, this.VISIBILITY_IDENTIFIER);
if (data && data == "true") {
this.show();
} else {
try {
data = sessionstore.getWindowValue(window, this.GROUPS_IDENTIFIER);
data = SessionStore.getWindowValue(window, this.GROUPS_IDENTIFIER);
if (data) {
let parsedData = JSON.parse(data);
this.updateGroupNumberBroadcaster(parsedData.totalNumber || 1);

View File

@ -620,7 +620,7 @@
<method name="handleEvent">
<parameter name="aEvent"/>
<body><![CDATA[
if (aEvent.type == "resize" && aEvent.eventPhase == aEvent.AT_TARGET) {
if (aEvent.type == "resize" && aEvent.eventPhase == aEvent.BUBBLING_PHASE) {
this.resize();
}
]]></body>

View File

@ -1,7 +1,5 @@
function numClosedTabs()
Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore).
getClosedTabCount(window);
SessionStore.getClosedTabCount(window);
function isUndoCloseEnabled() {
updateTabContextMenu();

View File

@ -1,8 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const ss = Cc["@mozilla.org/browser/sessionstore;1"]
.getService(Ci.nsISessionStore);
const URL = "http://mochi.test:8888/browser/";
const PREF = "browser.sessionstore.restore_on_demand";
@ -36,12 +34,12 @@ function preparePendingTab(aCallback) {
let tab = gBrowser.addTab(URL);
whenLoaded(tab.linkedBrowser, function () {
let state = ss.getTabState(tab);
let state = SessionStore.getTabState(tab);
gBrowser.removeTab(tab);
tab = gBrowser.addTab("about:blank");
whenLoaded(tab.linkedBrowser, function () {
ss.setTabState(tab, state);
SessionStore.setTabState(tab, state);
ok(tab.hasAttribute("pending"), "tab should be pending");
aCallback(tab);
});

View File

@ -1,7 +1,5 @@
function numClosedTabs()
Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore).
getNumberOfTabsClosedLast(window);
SessionStore.getNumberOfTabsClosedLast(window);
var originalTab;
var tab1Loaded = false;

View File

@ -29,15 +29,48 @@ XPCOMUtils.defineLazyGetter(this, "gInterval", function () {
Services.prefs.addObserver(PREF, () => {
this.gInterval = Services.prefs.getIntPref(PREF);
// Cancel any pending runs and call runDelayed() with
// zero to apply the newly configured interval.
SessionSaverInternal.cancel();
SessionSaverInternal.runDelayed(0);
if (isBatteryCharging()) {
// Cancel any pending runs and call runDelayed()
// to apply the newly configured interval.
SessionSaverInternal.cancel();
SessionSaverInternal.runDelayed(0);
}
}, false);
return Services.prefs.getIntPref(PREF);
});
XPCOMUtils.defineLazyGetter(this, "gIntervalBattery", function () {
const PREF = "browser.sessionstore.interval_battery";
// Observer that updates the cached value when the preference changes.
Services.prefs.addObserver(PREF, () => {
this.gIntervalBattery = Services.prefs.getIntPref(PREF);
if (!isBatteryCharging()) {
// Cancel any pending runs and call runDelayed()
// to apply the newly configured interval.
SessionSaverInternal.cancel();
SessionSaverInternal.runDelayed(0);
}
}, false);
return Services.prefs.getIntPref(PREF);
});
// Check if battery is charging
function isBatteryCharging() {
return Services.appShell.hiddenDOMWindow.navigator.battery.charging;
}
// Get the current session store interval based on battery status
function getInterval() {
if (isBatteryCharging()) {
return gInterval;
}
return gIntervalBattery;
}
// Wrap a string as a nsISupports.
function createSupportsString(data) {
let string = Cc["@mozilla.org/supports-string;1"]
@ -148,7 +181,7 @@ let SessionSaverInternal = {
}
// Interval until the next disk operation is allowed.
delay = Math.max(this._lastSaveTime + gInterval - Date.now(), delay, 0);
delay = Math.max(this._lastSaveTime + getInterval() - Date.now(), delay, 0);
// Schedule a state save.
this._timeoutID = setTimeout(() => this._saveState(), delay);

View File

@ -0,0 +1,149 @@
const {Cc,Ci,Cu} = require("chrome");
const ObservableObject = require("devtools/shared/observable-object");
const promise = require("sdk/core/promise");
const {EventEmitter} = Cu.import("resource:///modules/devtools/shared/event-emitter.js");
/**
* IndexedDB wrapper that just save project objects
*
* The only constraint is that project objects have to have
* a unique `location` object.
*/
const global = this;
const IDB = {
_db: null,
open: function () {
let deferred = promise.defer();
var idbManager = Cc["@mozilla.org/dom/indexeddb/manager;1"]
.getService(Ci.nsIIndexedDatabaseManager);
idbManager.initWindowless(global);
let request = global.indexedDB.open("AppProjects", 5);
request.onerror = function(event) {
deferred.reject("Unable to open AppProjects indexedDB. " +
"Error code: " + event.target.errorCode);
};
request.onupgradeneeded = function(event) {
let db = event.target.result;
db.createObjectStore("projects", { keyPath: "location" });
};
request.onsuccess = function() {
let db = IDB._db = request.result;
let objectStore = db.transaction("projects").objectStore("projects");
let projects = []
objectStore.openCursor().onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
projects.push(cursor.value);
cursor.continue();
} else {
deferred.resolve(projects);
}
};
};
return deferred.promise;
},
add: function(project) {
let deferred = promise.defer();
var transaction = IDB._db.transaction(["projects"], "readwrite");
var objectStore = transaction.objectStore("projects");
var request = objectStore.add(project);
request.onerror = function(event) {
deferred.reject("Unable to add project to the AppProjects indexedDB: " +
this.error.name + " - " + this.error.message );
};
request.onsuccess = function() {
deferred.resolve();
};
return deferred.promise;
},
remove: function(location) {
let deferred = promise.defer();
let request = IDB._db.transaction(["projects"], "readwrite")
.objectStore("projects")
.delete(location);
request.onsuccess = function(event) {
deferred.resolve();
};
request.onerror = function() {
deferred.reject("Unable to delete project to the AppProjects indexedDB: " +
this.error.name + " - " + this.error.message );
};
return deferred.promise;
}
};
const store = new ObservableObject({ projects:[] });
IDB.open().then(function (projects) {
store.object.projects = projects;
AppProjects.emit("ready", store.object.projects);
});
const AppProjects = {
addPackaged: function(folder) {
let project = {
type: "packaged",
location: folder.path
};
return IDB.add(project).then(function () {
store.object.projects.push(project);
// return the added objects (proxified)
return store.object.projects[store.object.projects.length - 1];
});
},
addHosted: function(manifestURL) {
let project = {
type: "hosted",
location: manifestURL
};
return IDB.add(project).then(function () {
store.object.projects.push(project);
// return the added objects (proxified)
return store.object.projects[store.object.projects.length - 1];
});
},
remove: function(location) {
return IDB.remove(location).then(function () {
let projects = store.object.projects;
for (let i = 0; i < projects.length; i++) {
if (projects[i].location == location) {
projects.splice(i, 1);
return;
}
}
throw new Error("Unable to find project in AppProjects store");
});
},
get: function(location) {
let projects = store.object.projects;
for (let i = 0; i < projects.length; i++) {
if (projects[i].location == location) {
return projects[i];
}
}
return null;
},
store: store
};
EventEmitter.decorate(AppProjects);
exports.AppProjects = AppProjects;

View File

@ -14,6 +14,8 @@ MOCHITEST_CHROME_FILES = \
test_template.html \
test_connection_store.html \
test_device_store.html \
test_projects_store.html \
hosted_app.manifest \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,3 @@
{
"name": "My hosted app"
}

View File

@ -0,0 +1,60 @@
<!DOCTYPE html>
<!--
Bug 907206 - data store for local apps
-->
<html>
<head>
<meta charset="utf8">
<title></title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript;version=1.8">
const Cu = Components.utils;
window.onload = function() {
SimpleTest.waitForExplicitFinish();
const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const {require} = devtools;
const { AppProjects } = require("devtools/app-manager/app-projects");
function testHosted(projects) {
let manifestURL = document.location.href.replace("test_projects_store.html", "hosted_app/webapp.manifest");
AppProjects.addHosted(manifestURL)
.then(function (app) {
is(projects.length, 1,
"Hosted app has been added");
is(projects[0], app);
is(app.type, "hosted", "valid type");
is(app.location, manifestURL, "valid location");
is(AppProjects.get(manifestURL), app,
"get() returns the same app object");
AppProjects.remove(manifestURL)
.then(function () {
is(projects.length, 0,
"Hosted app has been removed");
SimpleTest.finish();
});
});
}
AppProjects.once("ready", function (event, projects) {
is(projects, AppProjects.store.object.projects,
"The ready event data is the store projects list");
testHosted(projects);
});
}
</script>
</body>
</html>

View File

@ -11,10 +11,10 @@ const DBG_XUL = "chrome://browser/content/devtools/debugger.xul";
const CHROME_DEBUGGER_PROFILE_NAME = "-chrome-debugger";
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
Cu.import("resource://gre/modules/devtools/Loader.jsm");
let require = devtools.require;
let Telemetry = require("devtools/shared/telemetry");
this.EXPORTED_SYMBOLS = ["BrowserDebuggerProcess"];
@ -50,11 +50,21 @@ BrowserDebuggerProcess.prototype = {
* Initializes the debugger server.
*/
_initServer: function() {
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
if (!this.loader) {
// Create a separate loader instance, so that we can be sure to receive a
// separate instance of the DebuggingServer from the rest of the devtools.
// This allows us to safely use the tools against even the actors and
// DebuggingServer itself.
this.loader = new DevToolsLoader();
this.loader.main("devtools/server/main");
this.debuggerServer = this.loader.DebuggerServer;
}
DebuggerServer.openListener(Prefs.chromeDebuggingPort);
if (!this.debuggerServer.initialized) {
this.debuggerServer.init();
this.debuggerServer.addBrowserActors();
}
this.debuggerServer.openListener(Prefs.chromeDebuggingPort);
},
/**
@ -136,6 +146,8 @@ BrowserDebuggerProcess.prototype = {
this._telemetry.toolClosed("jsbrowserdebugger");
this.debuggerServer.destroy();
dumpn("Chrome debugger is now closed...");
if (typeof this._closeCallback == "function") {
this._closeCallback.call({}, this);

View File

@ -51,6 +51,7 @@ function isObject(x) {
function Handler(emitter) {
this._emitter = emitter;
this._wrappers = new WeakMap();
this._values = new WeakMap();
this._paths = new WeakMap();
}
@ -61,11 +62,15 @@ Handler.prototype = {
path = this._paths.get(target).concat(key);
} else if (this._wrappers.has(value)) {
path = this._paths.get(value);
} else if (this._paths.has(value)) {
path = this._paths.get(value);
value = this._values.get(value);
} else {
path = this._paths.get(target).concat(key);
this._paths.set(value, path);
let wrapper = new Proxy(value, this);
this._wrappers.set(wrapper, value);
this._values.set(value, wrapper);
value = wrapper;
}
return [value, path];

View File

@ -77,6 +77,7 @@ function test() {
oe.object.foo[1] = oe.object.bar;
is(index, expected.length, "Event count is right");
is(oe.object.bar, oe.object.bar, "Object attributes are wrapped only once");
finish();
}

View File

@ -18,12 +18,9 @@
}
.side-menu-widget-item-checkbox {
-moz-appearance: none;
-moz-appearance: none;
-moz-margin-end: -6px;
padding: 0;
margin-top: 4px;
margin-bottom: -4px;
-moz-margin-start: 4px;
-moz-margin-end: -4px;
opacity: 0;
transition: opacity .15s ease 0s;
}

View File

@ -316,10 +316,6 @@ box.requests-menu-status[code^="5"] {
background: rgba(255,255,255,0.05);
}
.side-menu-widget-item-contents {
padding: 0;
}
/* Network request details */
#details-pane {

View File

@ -304,19 +304,20 @@
}
.side-menu-widget-item {
border-top: 1px solid hsla(210,16%,76%,.1);
border-bottom: 1px solid hsla(210,8%,5%,.25);
border-top: 1px solid hsla(210,8%,5%,.25);
border-bottom: 1px solid hsla(210,16%,76%,.1);
margin-top: -1px;
margin-bottom: -1px;
cursor: pointer;
}
.side-menu-widget-item:last-of-type {
box-shadow: 0 1px 0 hsla(210,16%,76%,.1);
box-shadow: inset 0 -1px 0 hsla(210,8%,5%,.25);
}
.side-menu-widget-item.selected {
background: linear-gradient(hsl(206,61%,40%), hsl(206,61%,31%)) repeat-x top left !important;
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15),
inset 0 -1px 0 hsla(210,40%,83%,.05);
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15);
}
.side-menu-widget-item.selected > .side-menu-widget-item-arrow {
@ -334,21 +335,14 @@
background-position: center left, top left;
}
.side-menu-widget-item-arrow {
-moz-margin-start: -8px;
width: 8px;
}
.side-menu-widget-item-contents {
.side-menu-widget-item-label {
padding: 4px 0px;
}
.side-menu-widget-item label {
cursor: inherit;
}
.side-menu-widget-item-other:first-of-type {
border-top-left-radius: 4px;
.side-menu-widget-item-arrow {
-moz-margin-start: -8px;
width: 8px;
}
.side-menu-widget-item-other {
@ -361,17 +355,8 @@
inset 0 -1px 0 hsla(210,40%,83%,.07);
}
.side-menu-widget-item.selected .side-menu-widget-item-other:first-of-type {
border-top: 1px dotted #333;
margin-top: 3px;
}
.side-menu-widget-item-other:first-of-type {
margin-top: 4px;
}
.side-menu-widget-item-other:last-of-type {
margin-bottom: -4px;
border-top-left-radius: 4px;
}
.side-menu-widget-item-other > label {

View File

@ -20,12 +20,9 @@
}
.side-menu-widget-item-checkbox {
-moz-appearance: none;
-moz-appearance: none;
-moz-margin-end: -6px;
padding: 0;
margin-top: 4px;
margin-bottom: -4px;
-moz-margin-start: 4px;
-moz-margin-end: -4px;
opacity: 0;
transition: opacity .15s ease-out 0s;
}

View File

@ -316,10 +316,6 @@ box.requests-menu-status[code^="5"] {
background: rgba(255,255,255,0.05);
}
.side-menu-widget-item-contents {
padding: 0;
}
/* Network request details */
#details-pane {

View File

@ -304,19 +304,20 @@
}
.side-menu-widget-item {
border-top: 1px solid hsla(210,16%,76%,.1);
border-bottom: 1px solid hsla(210,8%,5%,.25);
border-top: 1px solid hsla(210,8%,5%,.25);
border-bottom: 1px solid hsla(210,16%,76%,.1);
margin-top: -1px;
margin-bottom: -1px;
cursor: pointer;
}
.side-menu-widget-item:last-of-type {
box-shadow: 0 1px 0 hsla(210,16%,76%,.1);
box-shadow: inset 0 -1px 0 hsla(210,8%,5%,.25);
}
.side-menu-widget-item.selected {
background: linear-gradient(hsl(206,61%,40%), hsl(206,61%,31%)) repeat-x top left !important;
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15),
inset 0 -1px 0 hsla(210,40%,83%,.05);
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15);
}
.side-menu-widget-item.selected > .side-menu-widget-item-arrow {
@ -334,21 +335,14 @@
background-position: center left, top left;
}
.side-menu-widget-item-arrow {
-moz-margin-start: -8px;
width: 8px;
}
.side-menu-widget-item-contents {
.side-menu-widget-item-label {
padding: 4px 0px;
}
.side-menu-widget-item label {
cursor: inherit;
}
.side-menu-widget-item-other:first-of-type {
border-top-left-radius: 4px;
.side-menu-widget-item-arrow {
-moz-margin-start: -8px;
width: 8px;
}
.side-menu-widget-item-other {
@ -361,17 +355,8 @@
inset 0 -1px 0 hsla(210,40%,83%,.07);
}
.side-menu-widget-item.selected .side-menu-widget-item-other:first-of-type {
border-top: 1px dotted #333;
margin-top: 3px;
}
.side-menu-widget-item-other:first-of-type {
margin-top: 4px;
}
.side-menu-widget-item-other:last-of-type {
margin-bottom: -4px;
border-top-left-radius: 4px;
}
.side-menu-widget-item-other > label {

View File

@ -18,12 +18,9 @@
}
.side-menu-widget-item-checkbox {
-moz-appearance: none;
-moz-appearance: none;
-moz-margin-end: -6px;
padding: 0;
margin-top: 4px;
margin-bottom: -4px;
-moz-margin-start: 4px;
-moz-margin-end: -4px;
opacity: 0;
transition: opacity .15s ease 0s;
}

View File

@ -316,10 +316,6 @@ box.requests-menu-status[code^="5"] {
background: rgba(255,255,255,0.05);
}
.side-menu-widget-item-contents {
padding: 0;
}
/* Network request details */
#details-pane {

View File

@ -308,19 +308,20 @@
}
.side-menu-widget-item {
border-top: 1px solid hsla(210,16%,76%,.1);
border-bottom: 1px solid hsla(210,8%,5%,.25);
border-top: 1px solid hsla(210,8%,5%,.25);
border-bottom: 1px solid hsla(210,16%,76%,.1);
margin-top: -1px;
margin-bottom: -1px;
cursor: pointer;
}
.side-menu-widget-item:last-of-type {
box-shadow: 0 1px 0 hsla(210,16%,76%,.1);
box-shadow: inset 0 -1px 0 hsla(210,8%,5%,.25);
}
.side-menu-widget-item.selected {
background: linear-gradient(hsl(206,61%,40%), hsl(206,61%,31%)) repeat-x top left !important;
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15),
inset 0 -1px 0 hsla(210,40%,83%,.05);
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15);
}
.side-menu-widget-item.selected > .side-menu-widget-item-arrow {
@ -338,21 +339,14 @@
background-position: center left, top left;
}
.side-menu-widget-item-arrow {
-moz-margin-start: -8px;
width: 8px;
}
.side-menu-widget-item-contents {
.side-menu-widget-item-label {
padding: 4px 0px;
}
.side-menu-widget-item label {
cursor: inherit;
}
.side-menu-widget-item-other:first-of-type {
border-top-left-radius: 4px;
.side-menu-widget-item-arrow {
-moz-margin-start: -8px;
width: 8px;
}
.side-menu-widget-item-other {
@ -365,17 +359,8 @@
inset 0 -1px 0 hsla(210,40%,83%,.07);
}
.side-menu-widget-item.selected .side-menu-widget-item-other:first-of-type {
border-top: 1px dotted #333;
margin-top: 3px;
}
.side-menu-widget-item-other:first-of-type {
margin-top: 4px;
}
.side-menu-widget-item-other:last-of-type {
margin-bottom: -4px;
border-top-left-radius: 4px;
}
.side-menu-widget-item-other > label {

View File

@ -78,7 +78,7 @@ var SelectionHandler = {
} else if (this._activeType == this.TYPE_CURSOR) {
// attachCaret() is called in the "Gesture:SingleTap" handler in BrowserEventHandler
// We're guaranteed to call this first, because this observer was added last
this._closeSelection();
this._deactivate();
}
break;
}
@ -159,7 +159,7 @@ var SelectionHandler = {
case "compositionend":
if (this._activeType == this.TYPE_CURSOR) {
this._closeSelection();
this._deactivate();
}
break;
}
@ -216,25 +216,25 @@ var SelectionHandler = {
this._closeSelection();
this._initTargetInfo(aElement);
this._activeType = this.TYPE_SELECTION;
// Clear any existing selection from the document
this._contentWindow.getSelection().removeAllRanges();
if (!this._domWinUtils.selectAtPoint(aX, aY, Ci.nsIDOMWindowUtils.SELECT_WORDNOSPACE)) {
this._closeSelection();
this._deactivate();
return;
}
let selection = this._getSelection();
// If the range didn't have any text, let's bail
if (!selection || selection.rangeCount == 0) {
this._closeSelection();
this._deactivate();
return;
}
// Add a listener to end the selection if it's removed programatically
selection.QueryInterface(Ci.nsISelectionPrivate).addSelectionListener(this);
this._activeType = this.TYPE_SELECTION;
// Initialize the cache
this._cache = { start: {}, end: {}};
@ -498,16 +498,23 @@ var SelectionHandler = {
if (this._activeType == this.TYPE_NONE)
return;
if (this._activeType == this.TYPE_SELECTION) {
let selection = this._getSelection();
if (selection) {
// Remove our listener before we clear the selection
selection.QueryInterface(Ci.nsISelectionPrivate).removeSelectionListener(this);
// Clear selection without clearing the anchorNode or focusNode
selection.collapseToStart();
}
}
if (this._activeType == this.TYPE_SELECTION)
this._clearSelection();
this._deactivate();
},
_clearSelection: function sh_clearSelection() {
let selection = this._getSelection();
if (selection) {
// Remove our listener before we clear the selection
selection.QueryInterface(Ci.nsISelectionPrivate).removeSelectionListener(this);
// Clear selection without clearing the anchorNode or focusNode
selection.collapseToStart();
}
},
_deactivate: function sh_deactivate() {
this._activeType = this.TYPE_NONE;
sendMessageToJava({ type: "TextSelection:HideHandles" });

View File

@ -43,7 +43,7 @@ function getThumbnailModifiedTime(url) {
/* Check functionality of a normal "captureIfStale" request */
function simpleCaptureTest() {
let numNotifications = 0;
const URL = "data:text/html;charset=utf-8,<body%20bgcolor=ff0000></body>";
const URL = "http://mochi.test:8888/browser/toolkit/components/thumbnails/test/thumbnails_update.sjs?simple";
function observe(subject, topic, data) {
is(topic, "page-thumbnail:create", "got expected topic");
@ -56,7 +56,7 @@ function simpleCaptureTest() {
}
Services.obs.addObserver(observe, "page-thumbnail:create", false);
// Create a tab with a red background.
// Create a tab - we don't care what the content is.
yield addTab(URL);
let browser = gBrowser.selectedBrowser;

View File

@ -1,7 +1,14 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// This server-side script primarily must return different *content* for the
// This server-side script is used for browser_thumbnails_update. One of the
// main things it must do in all cases is ensure a Cache-Control: no-store
// header, so the foreground capture doesn't interfere with the testing.
// If the querystring is "simple", then all it does it return some content -
// it doesn't really matter what that content is.
// Otherwise, its main role is that it must return different *content* for the
// second request than it did for the first.
// Also, it should be able to return an error response when requested for the
// second response.
@ -16,6 +23,16 @@ function handleRequest(aRequest, aResponse) {
// so set as a "no-store" response.
aResponse.setHeader("Cache-Control", "no-store");
// for the simple test - just return some content.
if (aRequest.queryString == "simple") {
aResponse.write("<html><body></body></html>");
aResponse.setStatusLine(aRequest.httpVersion, 200, "Its simply OK");
return;
}
// it's one of the more complex tests where the first request for the given
// URL must return different content than the second, and possibly an error
// response for the second
let doneError = getState(aRequest.queryString);
if (!doneError) {
// first request - return a response with a green body and 200 response.

View File

@ -21,7 +21,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "console", "resource://gre/modules/devto
let loader = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {}).Loader;
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
this.EXPORTED_SYMBOLS = ["devtools"];
this.EXPORTED_SYMBOLS = ["DevToolsLoader", "devtools"];
/**
* Providers are different strategies for loading the devtools.
@ -36,11 +36,11 @@ let loaderGlobals = {
lazyImporter: XPCOMUtils.defineLazyModuleGetter.bind(XPCOMUtils),
lazyServiceGetter: XPCOMUtils.defineLazyServiceGetter.bind(XPCOMUtils)
}
}
};
// Used when the tools should be loaded from the Firefox package itself (the default)
var BuiltinProvider = {
load: function(done) {
load: function() {
this.loader = new loader.Loader({
modules: {
"toolkit/loader": loader
@ -78,7 +78,7 @@ var SrcdirProvider = {
return Services.io.newFileURI(file).spec;
},
load: function(done) {
load: function() {
let srcdir = Services.prefs.getComplexValue("devtools.loader.srcdir",
Ci.nsISupportsString);
srcdir = OS.Path.normalize(srcdir.data.trim());
@ -182,9 +182,15 @@ var SrcdirProvider = {
/**
* The main devtools API.
* In addition to a few loader-related details, this object will also include all
* exports from the main module.
* exports from the main module. The standard instance of this loader is
* exported as |devtools| below, but if a fresh copy of the loader is needed,
* then a new one can also be created.
*/
this.devtools = {
this.DevToolsLoader = function DevToolsLoader() {
this._chooseProvider();
};
DevToolsLoader.prototype = {
_provider: null,
/**
@ -267,5 +273,5 @@ this.devtools = {
},
};
// Now load the tools.
devtools._chooseProvider();
// Export the standard instance of DevToolsLoader used by the tools.
this.devtools = new DevToolsLoader();

View File

@ -6,7 +6,7 @@
"use strict";
const {Cu} = require("chrome");
const {Cc, Ci, Cu} = require("chrome");
const {setTimeout, clearTimeout} = require('sdk/timers');
const EventEmitter = require("devtools/shared/event-emitter");
@ -25,6 +25,7 @@ Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
* Methods:
* Connection createConnection(host, port)
* void destroyConnection(connection)
* Number getFreeTCPPort()
*
* Properties:
* Array connections
@ -46,6 +47,7 @@ Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
* port Port
* logs Current logs. "newlog" event notifies new available logs
* store Reference to a local data store (see below)
* keepConnecting Should the connection keep trying connecting
* status Connection status:
* Connection.Status.CONNECTED
* Connection.Status.DISCONNECTED
@ -86,6 +88,14 @@ let ConnectionManager = {
get connections() {
return [c for (c of this._connections)];
},
getFreeTCPPort: function () {
let serv = Cc['@mozilla.org/network/server-socket;1']
.createInstance(Ci.nsIServerSocket);
serv.init(-1, true, -1);
let port = serv.port;
serv.close();
return port;
},
}
EventEmitter.decorate(ConnectionManager);
@ -101,6 +111,7 @@ function Connection(host, port) {
this._onDisconnected = this._onDisconnected.bind(this);
this._onConnected = this._onConnected.bind(this);
this._onTimeout = this._onTimeout.bind(this);
this.keepConnecting = false;
}
Connection.Status = {
@ -180,15 +191,7 @@ Connection.prototype = {
let delay = Services.prefs.getIntPref("devtools.debugger.remote-timeout");
this._timeoutID = setTimeout(this._onTimeout, delay);
let transport;
if (!this._host) {
transport = DebuggerServer.connectPipe();
} else {
transport = debuggerSocketConnect(this._host, this._port);
}
this._client = new DebuggerClient(transport);
this._client.addOneTimeListener("closed", this._onDisconnected);
this._client.connect(this._onConnected);
this._clientConnect();
} else {
let msg = "Can't connect. Client is not fully disconnected";
this.log(msg);
@ -199,6 +202,7 @@ Connection.prototype = {
destroy: function() {
this.log("killing connection");
clearTimeout(this._timeoutID);
this.keepConnecting = false;
if (this._client) {
this._client.close();
this._client = null;
@ -206,6 +210,18 @@ Connection.prototype = {
this._setStatus(Connection.Status.DESTROYED);
},
_clientConnect: function () {
let transport;
if (!this._host) {
transport = DebuggerServer.connectPipe();
} else {
transport = debuggerSocketConnect(this._host, this._port);
}
this._client = new DebuggerClient(transport);
this._client.addOneTimeListener("closed", this._onDisconnected);
this._client.connect(this._onConnected);
},
get status() {
return this._status
},
@ -219,6 +235,13 @@ Connection.prototype = {
},
_onDisconnected: function() {
this._client = null;
if (this._status == Connection.Status.CONNECTING && this.keepConnecting) {
setTimeout(() => this._clientConnect(), 0);
return;
}
clearTimeout(this._timeoutID);
switch (this.status) {
case Connection.Status.CONNECTED:
@ -230,7 +253,6 @@ Connection.prototype = {
default:
this.log("disconnected");
}
this._client = null;
this._setStatus(Connection.Status.DISCONNECTED);
},
@ -242,7 +264,7 @@ Connection.prototype = {
_onTimeout: function() {
this.log("connection timeout");
this.emit(Connection.Events.TIMEOUT, str);
this.emit(Connection.Events.TIMEOUT);
this.disconnect();
},
}

View File

@ -1675,20 +1675,20 @@ eventSource(ThreadClient.prototype);
function TraceClient(aClient, aActor) {
this._client = aClient;
this._actor = aActor;
this._traces = Object.create(null);
this._activeTraces = 0;
this._activeTraces = new Set();
this._waitingPackets = new Map();
this._expectedPacket = 0;
this._client.addListener(UnsolicitedNotifications.enteredFrame,
this.onEnteredFrame.bind(this));
this._client.addListener(UnsolicitedNotifications.exitedFrame,
this.onExitedFrame.bind(this));
this.onPacket = this.onPacket.bind(this);
this._client.addListener(UnsolicitedNotifications.enteredFrame, this.onPacket);
this._client.addListener(UnsolicitedNotifications.exitedFrame, this.onPacket);
this.request = this._client.request;
}
TraceClient.prototype = {
get actor() { return this._actor; },
get tracing() { return this._activeTraces > 0; },
get tracing() { return this._activeTraces.size > 0; },
get _transport() { return this._client._transport; },
@ -1720,15 +1720,11 @@ TraceClient.prototype = {
return aResponse;
}
let name = aResponse.name;
if (!this._traces[name] || !this._traces[name].active) {
this._activeTraces++;
if (!this.tracing) {
this._waitingPackets.clear();
this._expectedPacket = 0;
}
this._traces[name] = {
active: true
};
this._activeTraces.add(aResponse.name);
return aResponse;
},
@ -1754,8 +1750,7 @@ TraceClient.prototype = {
return aResponse;
}
this._traces[aResponse.name].active = false;
this._activeTraces--;
this._activeTraces.delete(aResponse.name);
return aResponse;
},
@ -1763,17 +1758,24 @@ TraceClient.prototype = {
}),
/**
* Called when the trace actor notifies that a frame has been entered.
* Called when the trace actor notifies that a frame has been
* entered or exited.
*
* @param aEvent string
* The type of the unsolicited packet (enteredFrame|exitedFrame).
*
* @param aPacket object
* Packet received over the RDP from the trace actor.
*/
onEnteredFrame: function JSTC_onEnteredFrame(aEvent, aResponse) {
this.notify("enteredFrame", aResponse);
},
onPacket: function JSTC_onPacket(aEvent, aPacket) {
this._waitingPackets.set(aPacket.sequence, aPacket);
/**
* Called when the trace actor notifies that a frame has been exited.
*/
onExitedFrame: function JSTC_onExitedFrame(aEvent, aResponse) {
this.notify("exitedFrame", aResponse);
while (this._waitingPackets.has(this._expectedPacket)) {
let packet = this._waitingPackets.get(this._expectedPacket);
this._waitingPackets.delete(this._expectedPacket);
this.notify(packet.type, packet);
this._expectedPacket++;
}
}
};

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/**
* Loads the remote debugging protocol code into a sandbox, in order to
* shield it from the debuggee. This way, when debugging chrome globals,
@ -15,30 +16,11 @@ const Ci = Components.interfaces;
const Cc = Components.classes;
const Cu = Components.utils;
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
this.EXPORTED_SYMBOLS = ["DebuggerServer", "ActorPool"];
var loadSubScript =
"function loadSubScript(aURL)\n" +
"{\n" +
"const Ci = Components.interfaces;\n" +
"const Cc = Components.classes;\n" +
" try {\n" +
" let loader = Cc[\"@mozilla.org/moz/jssubscript-loader;1\"]\n" +
" .getService(Ci.mozIJSSubScriptLoader);\n" +
" loader.loadSubScript(aURL, this);\n" +
" } catch(e) {\n" +
" dump(\"Error loading: \" + aURL + \": \" + e + \" - \" + e.stack + \"\\n\");\n" +
" throw e;\n" +
" }\n" +
"}";
let server = devtools.require("devtools/server/main");
// Load the debugging server in a sandbox with its own compartment.
var systemPrincipal = Cc["@mozilla.org/systemprincipal;1"]
.createInstance(Ci.nsIPrincipal);
var gGlobal = Cu.Sandbox(systemPrincipal);
Cu.evalInSandbox(loadSubScript, gGlobal, "1.8");
gGlobal.loadSubScript("resource://gre/modules/devtools/server/main.js");
this.DebuggerServer = gGlobal.DebuggerServer;
this.ActorPool = gGlobal.ActorPool;
this.DebuggerServer = server.DebuggerServer;
this.ActorPool = server.ActorPool;

View File

@ -10,11 +10,7 @@
* debugging global.
*/
const Ci = Components.interfaces;
const Cc = Components.classes;
const CC = Components.Constructor;
const Cu = Components.utils;
const Cr = Components.results;
const { Ci, Cc, CC, Cu, Cr, components: Components } = require("chrome");
const DBG_STRINGS_URI = "chrome://global/locale/devtools/debugger.properties";
Cu.import("resource://gre/modules/Services.jsm");
@ -25,7 +21,24 @@ const promptConnections = Services.prefs.getBoolPref("devtools.debugger.prompt-c
Cu.import("resource://gre/modules/jsdebugger.jsm");
addDebuggerToGlobal(this);
function loadSubScript(aURL)
{
try {
let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader);
loader.loadSubScript(aURL, this);
} catch(e) {
let errorStr = "Error loading: " + aURL + ": " + e + " - " + e.stack + "\n";
dump(errorStr);
Cu.reportError(errorStr);
throw e;
}
}
let loaderRequire = require;
this.require = null;
loadSubScript.call(this, "resource://gre/modules/commonjs/sdk/core/promise.js");
this.require = loaderRequire;
Cu.import("resource://gre/modules/devtools/SourceMap.jsm");
@ -259,9 +272,7 @@ var DebuggerServer = {
}
let moduleAPI = ModuleAPI();
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
let mod = devtools.require(id);
let mod = require(id);
mod.register(moduleAPI);
gRegisteredModules[id] = { module: mod, api: moduleAPI };
},
@ -607,6 +618,7 @@ var DebuggerServer = {
}
};
exports.DebuggerServer = DebuggerServer;
/**
* Construct an ActorPool.
@ -622,6 +634,8 @@ function ActorPool(aConnection)
this._actors = {};
}
exports.ActorPool = ActorPool;
ActorPool.prototype = {
/**
* Add an actor to the actor pool. If the actor doesn't have an ID,

View File

@ -20,6 +20,7 @@ window.onload = function() {
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
Cu.import("resource://gre/modules/devtools/Loader.jsm");
Cu.import("resource://gre/modules/Services.jsm");
DebuggerServer.init(function () { return true; });
DebuggerServer.addBrowserActors();
@ -43,7 +44,7 @@ window.onload = function() {
var c = c2;
var eventsRef = "connecting connected disconnecting disconnected host-changed disconnected destroyed";
var eventsRef = "connecting connected disconnecting disconnected host-changed disconnected timeout destroyed";
var events = [];
var s = Connection.Status;
@ -70,7 +71,7 @@ window.onload = function() {
function testError() {
c.once(Connection.Events.DISCONNECTED, function(e) {
events.push(e);
ConnectionManager.destroyConnection(c);
testKeepConnecting();
});
c.once(Connection.Events.HOST_CHANGED, function(e) {
events.push(e);
@ -80,6 +81,24 @@ window.onload = function() {
c.host = "localhost";
}
function testKeepConnecting() {
// ensure that keepConnecting keep trying connecting
// until the connection attempts timeout
var originalTimeout = Services.prefs.getIntPref("devtools.debugger.remote-timeout");
Services.prefs.setIntPref("devtools.debugger.remote-timeout", 1000);
c.once("timeout", function (e) {
events.push(e);
Services.prefs.setIntPref("devtools.debugger.remote-timeout", originalTimeout);
ConnectionManager.destroyConnection(c);
});
c.keepConnecting = true;
var port = ConnectionManager.getFreeTCPPort();
ok(parseInt(port), "Free TCP port looks like a port number");
c.port = port;
c.host = "locahost";
c.connect();
}
function finish() {
is(events.join(" "), eventsRef, "Events received in the right order");
DebuggerServer.destroy();

View File

@ -0,0 +1,101 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that TraceClient emits enteredFrame and exitedFrame events in
* order when receiving packets out of order.
*/
let {defer, resolve} = devtools.require("sdk/core/promise");
var gDebuggee;
var gClient;
var gTraceClient;
function run_test()
{
initTestTracerServer();
gDebuggee = addTestGlobal("test-tracer-actor");
gClient = new DebuggerClient(DebuggerServer.connectPipe());
gClient.connect(function() {
attachTestTab(gClient, "test-tracer-actor", function(aResponse, aTabClient) {
gClient.attachTracer(aResponse.traceActor, function(aResponse, aTraceClient) {
gTraceClient = aTraceClient;
test_packet_order();
});
});
});
do_test_pending();
}
function test_packet_order()
{
let sequence = 0;
function check_packet(aEvent, aPacket) {
do_check_eq(aPacket.sequence, sequence,
'packet should have sequence number ' + sequence);
sequence++;
}
gTraceClient.addListener("enteredFrame", check_packet);
gTraceClient.addListener("exitedFrame", check_packet);
start_trace()
.then(mock_packets)
.then(start_trace)
.then(mock_packets.bind(null, 14))
.then(stop_trace)
.then(stop_trace)
.then(function() {
// All traces were stopped, so the sequence number resets
sequence = 0;
return resolve();
})
.then(start_trace)
.then(mock_packets)
.then(stop_trace)
.then(function() {
finishClient(gClient);
});
}
function start_trace()
{
let deferred = defer();
gTraceClient.startTrace([], null, function() { deferred.resolve(); });
return deferred.promise;
}
function stop_trace()
{
let deferred = defer();
gTraceClient.stopTrace(null, function() { deferred.resolve(); });
return deferred.promise;
}
function mock_packets(s = 0)
{
gTraceClient.onPacket("", { type: "exitedFrame", sequence: s + 5 });
gTraceClient.onPacket("", { type: "enteredFrame", sequence: s + 3 });
gTraceClient.onPacket("", { type: "exitedFrame", sequence: s + 2 });
gTraceClient.onPacket("", { type: "enteredFrame", sequence: s + 4 });
gTraceClient.onPacket("", { type: "enteredFrame", sequence: s + 1 });
gTraceClient.onPacket("", { type: "enteredFrame", sequence: s + 7 });
gTraceClient.onPacket("", { type: "enteredFrame", sequence: s + 8 });
// Triggers 0-5
gTraceClient.onPacket("", { type: "enteredFrame", sequence: s + 0 });
gTraceClient.onPacket("", { type: "exitedFrame", sequence: s + 9 });
gTraceClient.onPacket("", { type: "exitedFrame", sequence: s + 10 });
// Triggers 6-10
gTraceClient.onPacket("", { type: "exitedFrame", sequence: s + 6 });
// Each following packet is expected; event is fired immediately
gTraceClient.onPacket("", { type: "enteredFrame", sequence: s + 11 });
gTraceClient.onPacket("", { type: "exitedFrame", sequence: s + 12 });
gTraceClient.onPacket("", { type: "exitedFrame", sequence: s + 13 });
}

View File

@ -166,3 +166,4 @@ reason = bug 820380
[test_trace_actor-04.js]
[test_trace_actor-05.js]
[test_trace_actor-06.js]
[test_trace_client-01.js]

View File

@ -192,7 +192,11 @@ DebuggerTransport.prototype = {
dumpn("Got: " + packet);
let self = this;
Services.tm.currentThread.dispatch(makeInfallible(function() {
self.hooks.onPacket(parsed);
// Ensure the hooks are still around by the time this runs (they will go
// away when the transport is closed).
if (self.hooks) {
self.hooks.onPacket(parsed);
}
}, "DebuggerTransport instance's this.hooks.onPacket"), 0);
return true;

View File

@ -11,9 +11,8 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/AddonManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
"resource://gre/modules/AddonManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository",
"resource://gre/modules/AddonRepository.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",

View File

@ -4,8 +4,6 @@
* 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/. */
var args
var XPInstallConfirm = {};
XPInstallConfirm.init = function XPInstallConfirm_init()
@ -15,9 +13,12 @@ XPInstallConfirm.init = function XPInstallConfirm_init()
var _focused;
var _timeout;
// Default to cancelling the install when the window unloads
XPInstallConfirm._installOK = false;
var bundle = document.getElementById("xpinstallConfirmStrings");
args = window.arguments[0].wrappedJSObject;
let args = window.arguments[0].wrappedJSObject;
var _installCountdownLength = 5;
try {
@ -122,6 +123,17 @@ XPInstallConfirm.init = function XPInstallConfirm_init()
document.removeEventListener("focus", myfocus, true);
document.removeEventListener("blur", myblur, true);
window.removeEventListener("unload", myUnload, false);
// Now perform the desired action - either install the
// addons or cancel the installations
if (XPInstallConfirm._installOK) {
for (let install of args.installs)
install.install();
}
else {
for (let install of args.installs)
install.cancel();
}
}
if (_installCountdownLength > 0) {
@ -142,14 +154,14 @@ XPInstallConfirm.onOK = function XPInstallConfirm_onOk()
getService(Components.interfaces.nsITelemetry).
getHistogramById("SECURITY_UI").
add(Components.interfaces.nsISecurityUITelemetry.WARNING_CONFIRM_ADDON_INSTALL_CLICK_THROUGH);
for (let install of args.installs)
install.install();
// Perform the install or cancel after the window has unloaded
XPInstallConfirm._installOK = true;
return true;
}
XPInstallConfirm.onCancel = function XPInstallConfirm_onCancel()
{
for (let install of args.installs)
install.cancel();
// Perform the install or cancel after the window has unloaded
XPInstallConfirm._installOK = false;
return true;
}

View File

@ -64,7 +64,7 @@ treechildren:-moz-locale-dir(rtl)::-moz-tree-twisty(hover, open) {
}
@media (-moz-windows-default-theme) {
treechildren::-moz-tree-row {
treechildren:not(.autocomplete-treebody)::-moz-tree-row {
height: 1.8em;
color: -moz-FieldText;
-moz-margin-start: 1px;
@ -77,7 +77,7 @@ treechildren:-moz-locale-dir(rtl)::-moz-tree-twisty(hover, open) {
-moz-outline-radius: 3px;
}
treechildren::-moz-tree-row(selected) {
treechildren:not(.autocomplete-treebody)::-moz-tree-row(selected) {
-moz-border-top-colors: @selectedBorderColor@ @whiteOpacityBorderColor@;
-moz-border-right-colors: @selectedBorderColor@ @whiteOpacityBorderColor@;
-moz-border-left-colors: @selectedBorderColor@ @whiteOpacityBorderColor@;
@ -87,7 +87,7 @@ treechildren:-moz-locale-dir(rtl)::-moz-tree-twisty(hover, open) {
outline: 1px solid @whiteOpacityBorderColor@;
}
treechildren::-moz-tree-row(current, focus) {
treechildren:not(.autocomplete-treebody)::-moz-tree-row(current, focus) {
border-style: solid;
-moz-border-top-colors: @hoverAndFocusBorderColor@ @whiteOpacityBorderColor@;
-moz-border-right-colors: @hoverAndFocusBorderColor@ @whiteOpacityBorderColor@;
@ -96,7 +96,7 @@ treechildren:-moz-locale-dir(rtl)::-moz-tree-twisty(hover, open) {
outline: 1px solid @whiteOpacityBorderColor@;
}
treechildren::-moz-tree-row(selected, focus),
treechildren:not(.autocomplete-treebody)::-moz-tree-row(selected, focus),
treechildren::-moz-tree-row(dropOn) {
-moz-border-top-colors: @selectedFocusBorderColor@ @whiteOpacityBorderColor@;
-moz-border-right-colors: @selectedFocusBorderColor@ @whiteOpacityBorderColor@;
@ -106,7 +106,7 @@ treechildren:-moz-locale-dir(rtl)::-moz-tree-twisty(hover, open) {
background-color: transparent;
}
treechildren::-moz-tree-row(selected, current, focus) {
treechildren:not(.autocomplete-treebody)::-moz-tree-row(selected, current, focus) {
border-style: solid;
-moz-border-top-colors: @hoverAndFocusBorderColor@ @whiteOpacityBorderColor@;
-moz-border-right-colors: @hoverAndFocusBorderColor@ @whiteOpacityBorderColor@;
@ -115,7 +115,7 @@ treechildren:-moz-locale-dir(rtl)::-moz-tree-twisty(hover, open) {
background-image: linear-gradient(@hoverAndCurrentFocusGradientColor1@, @hoverAndCurrentFocusGradientColor2@);
}
treechildren::-moz-tree-row(hover) {
treechildren:not(.autocomplete-treebody)::-moz-tree-row(hover) {
-moz-border-top-colors: @hoverBorderColor@ @whiteOpacityBorderColor@;
-moz-border-right-colors: @hoverBorderColor@ @whiteOpacityBorderColor@;
-moz-border-left-colors: @hoverBorderColor@ @whiteOpacityBorderColor@;
@ -124,7 +124,7 @@ treechildren:-moz-locale-dir(rtl)::-moz-tree-twisty(hover, open) {
outline: 1px solid @whiteOpacityBorderColor@;
}
treechildren::-moz-tree-row(hover, current) {
treechildren:not(.autocomplete-treebody)::-moz-tree-row(hover, current) {
-moz-border-top-colors: @hoverAndFocusBorderColor@ @whiteOpacityBorderColor@;
-moz-border-right-colors: @hoverAndFocusBorderColor@ @whiteOpacityBorderColor@;
-moz-border-left-colors: @hoverAndFocusBorderColor@ @whiteOpacityBorderColor@;
@ -132,7 +132,7 @@ treechildren:-moz-locale-dir(rtl)::-moz-tree-twisty(hover, open) {
background-image: linear-gradient(@hoverGradientColor1@, @hoverGradientColor2@);
}
treechildren::-moz-tree-row(hover, selected) {
treechildren:not(.autocomplete-treebody)::-moz-tree-row(hover, selected) {
-moz-border-top-colors: @hoverAndFocusBorderColor@ @whiteOpacityBorderColor@;
-moz-border-right-colors: @hoverAndFocusBorderColor@ @whiteOpacityBorderColor@;
-moz-border-left-colors: @hoverAndFocusBorderColor@ @whiteOpacityBorderColor@;
@ -154,45 +154,45 @@ treechildren:-moz-locale-dir(rtl)::-moz-tree-twisty(hover, open) {
border-radius: 0;
}
treechildren::-moz-tree-cell-text {
treechildren:not(.autocomplete-treebody)::-moz-tree-cell-text {
padding-bottom: initial;
border-color: transparent;
background-color: transparent;
}
treechildren::-moz-tree-cell-text(selected, focus) {
treechildren:not(.autocomplete-treebody)::-moz-tree-cell-text(selected, focus) {
color: -moz-DialogText;
}
@media (-moz-os-version: windows-win8) {
treechildren::-moz-tree-row {
treechildren:not(.autocomplete-treebody)::-moz-tree-row {
border-width: 1px;
border-radius: 0;
-moz-outline-radius: 0;
}
treechildren::-moz-tree-row(selected) {
treechildren:not(.autocomplete-treebody)::-moz-tree-row(selected) {
background-image: linear-gradient(@selectedGradientColor2@, @selectedGradientColor2@);
}
treechildren::-moz-tree-row(selected, focus),
treechildren:not(.autocomplete-treebody)::-moz-tree-row(selected, focus),
treechildren::-moz-tree-row(dropOn) {
background-image: linear-gradient(@selectedFocusGradientColor2@, @selectedFocusGradientColor2@);
}
treechildren::-moz-tree-row(selected, current, focus) {
treechildren:not(.autocomplete-treebody)::-moz-tree-row(selected, current, focus) {
background-image: linear-gradient(@hoverAndCurrentFocusGradientColor2@, @hoverAndCurrentFocusGradientColor2@);
}
treechildren::-moz-tree-row(hover) {
treechildren:not(.autocomplete-treebody)::-moz-tree-row(hover) {
background-image: linear-gradient(@hoverGradientColor2@, @hoverGradientColor2@);
}
treechildren::-moz-tree-row(hover, current) {
treechildren:not(.autocomplete-treebody)::-moz-tree-row(hover, current) {
background-image: linear-gradient(@hoverGradientColor2@, @hoverGradientColor2@);
}
treechildren::-moz-tree-row(hover, selected) {
treechildren:not(.autocomplete-treebody)::-moz-tree-row(hover, selected) {
background-image: linear-gradient(@hoverAndCurrentFocusGradientColor2@, @hoverAndCurrentFocusGradientColor2@);
}
}