Merge fx-team to m-c.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
const DEVELOPER_HUD_LOG_PREFIX = 'DeveloperHUD';
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'devtools', function() {
|
||||
const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const {devtools} = Cu.import('resource://gre/modules/devtools/Loader.jsm', {});
|
||||
return devtools;
|
||||
});
|
||||
|
||||
@@ -16,15 +16,15 @@ XPCOMUtils.defineLazyGetter(this, 'DebuggerClient', function() {
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'WebConsoleUtils', function() {
|
||||
return devtools.require("devtools/toolkit/webconsole/utils").Utils;
|
||||
return devtools.require('devtools/toolkit/webconsole/utils').Utils;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'EventLoopLagFront', function() {
|
||||
return devtools.require("devtools/server/actors/eventlooplag").EventLoopLagFront;
|
||||
return devtools.require('devtools/server/actors/eventlooplag').EventLoopLagFront;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'MemoryFront', function() {
|
||||
return devtools.require("devtools/server/actors/memory").MemoryFront;
|
||||
return devtools.require('devtools/server/actors/memory').MemoryFront;
|
||||
});
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ let developerHUD = {
|
||||
* on app frames that are being tracked. A watcher must implement the
|
||||
* `trackTarget(target)` and `untrackTarget(target)` methods, register
|
||||
* observed metrics with `target.register(metric)`, and keep them up-to-date
|
||||
* with `target.update(metric, value, message)` when necessary.
|
||||
* with `target.update(metric, message)` when necessary.
|
||||
*/
|
||||
registerWatcher: function dwp_registerWatcher(watcher) {
|
||||
this._watchers.unshift(watcher);
|
||||
@@ -210,15 +210,24 @@ Target.prototype = {
|
||||
* Modify one of a target's metrics, and send out an event to notify relevant
|
||||
* parties (e.g. the developer HUD, automated tests, etc).
|
||||
*/
|
||||
update: function target_update(metric, value = 0, message) {
|
||||
update: function target_update(metric, message) {
|
||||
if (!metric.name) {
|
||||
throw new Error('Missing metric.name');
|
||||
}
|
||||
|
||||
if (!metric.value) {
|
||||
metric.value = 0;
|
||||
}
|
||||
|
||||
let metrics = this.metrics;
|
||||
metrics.set(metric, value);
|
||||
if (metrics) {
|
||||
metrics.set(metric.name, metric.value);
|
||||
}
|
||||
|
||||
let data = {
|
||||
metrics: [], // FIXME(Bug 982066) Remove this field.
|
||||
manifest: this.frame.appManifestURL,
|
||||
metric: metric,
|
||||
value: value,
|
||||
message: message
|
||||
};
|
||||
|
||||
@@ -240,7 +249,8 @@ Target.prototype = {
|
||||
* to be incremented.
|
||||
*/
|
||||
bump: function target_bump(metric, message) {
|
||||
this.update(metric, this.metrics.get(metric) + 1, message);
|
||||
metric.value = (this.metrics.get(metric.name) || 0) + 1;
|
||||
this.update(metric, message);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -248,7 +258,8 @@ Target.prototype = {
|
||||
* anymore.
|
||||
*/
|
||||
clear: function target_clear(metric) {
|
||||
this.update(metric, 0);
|
||||
metric.value = 0;
|
||||
this.update(metric);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -307,7 +318,7 @@ let consoleWatcher = {
|
||||
|
||||
// If unwatched, remove any existing widgets for that metric.
|
||||
for (let target of this._targets.values()) {
|
||||
target.clear(metric);
|
||||
target.clear({name: metric});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -345,7 +356,7 @@ let consoleWatcher = {
|
||||
|
||||
consoleListener: function cw_consoleListener(type, packet) {
|
||||
let target = this._targets.get(packet.from);
|
||||
let metric;
|
||||
let metric = {};
|
||||
let output = '';
|
||||
|
||||
switch (packet.type) {
|
||||
@@ -354,15 +365,15 @@ let consoleWatcher = {
|
||||
let pageError = packet.pageError;
|
||||
|
||||
if (pageError.warning || pageError.strict) {
|
||||
metric = 'warnings';
|
||||
metric.name = 'warnings';
|
||||
output += 'warning (';
|
||||
} else {
|
||||
metric = 'errors';
|
||||
metric.name = 'errors';
|
||||
output += 'error (';
|
||||
}
|
||||
|
||||
if (this._security.indexOf(pageError.category) > -1) {
|
||||
metric = 'security';
|
||||
metric.name = 'security';
|
||||
}
|
||||
|
||||
let {errorMessage, sourceName, category, lineNumber, columnNumber} = pageError;
|
||||
@@ -374,12 +385,12 @@ let consoleWatcher = {
|
||||
switch (packet.message.level) {
|
||||
|
||||
case 'error':
|
||||
metric = 'errors';
|
||||
metric.name = 'errors';
|
||||
output += 'error (console)';
|
||||
break;
|
||||
|
||||
case 'warn':
|
||||
metric = 'warnings';
|
||||
metric.name = 'warnings';
|
||||
output += 'warning (console)';
|
||||
break;
|
||||
|
||||
@@ -389,18 +400,22 @@ let consoleWatcher = {
|
||||
break;
|
||||
|
||||
case 'reflowActivity':
|
||||
metric = 'reflows';
|
||||
metric.name = 'reflows';
|
||||
|
||||
let {start, end, sourceURL} = packet;
|
||||
let {start, end, sourceURL, interruptible} = packet;
|
||||
metric.interruptible = interruptible;
|
||||
let duration = Math.round((end - start) * 100) / 100;
|
||||
output += 'reflow: ' + duration + 'ms';
|
||||
if (sourceURL) {
|
||||
output += ' ' + this.formatSourceURL(packet);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._watching[metric]) {
|
||||
if (!this._watching[metric.name]) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -446,7 +461,7 @@ let eventLoopLagWatcher = {
|
||||
fronts.get(target).start();
|
||||
} else {
|
||||
fronts.get(target).stop();
|
||||
target.clear('jank');
|
||||
target.clear({name: 'jank'});
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -458,7 +473,7 @@ let eventLoopLagWatcher = {
|
||||
this._fronts.set(target, front);
|
||||
|
||||
front.on('event-loop-lag', time => {
|
||||
target.update('jank', time, 'jank: ' + time + 'ms');
|
||||
target.update({name: 'jank', value: time}, 'jank: ' + time + 'ms');
|
||||
});
|
||||
|
||||
if (this._active) {
|
||||
@@ -514,7 +529,7 @@ let memoryWatcher = {
|
||||
} else {
|
||||
for (let target of this._fronts.keys()) {
|
||||
clearTimeout(this._timers.get(target));
|
||||
target.clear('memory');
|
||||
target.clear({name: 'memory'});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -550,7 +565,7 @@ let memoryWatcher = {
|
||||
}
|
||||
// TODO Also count images size (bug #976007).
|
||||
|
||||
target.update('memory', total);
|
||||
target.update({name: 'memory', value: total});
|
||||
let duration = parseInt(data.jsMilliseconds) + parseInt(data.nonJSMilliseconds);
|
||||
let timer = setTimeout(() => this.measure(target), 100 * duration);
|
||||
this._timers.set(target, timer);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
font-weight: 400;
|
||||
src: local('Fira Sans'),
|
||||
local('FiraSans'),
|
||||
url('fonts/firasans-regular.woff') format('woff');
|
||||
url('../fonts/FiraSans-Regular.woff') format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Fira Sans';
|
||||
@@ -12,7 +12,7 @@
|
||||
font-weight: 300;
|
||||
src: local('Fira Sans Light'),
|
||||
local('FiraSansLight'),
|
||||
url('fonts/firasans-light.woff') format('woff');
|
||||
url('../fonts/FiraSans-Light.woff') format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Clear Sans';
|
||||
@@ -20,6 +20,5 @@
|
||||
font-weight: 400;
|
||||
src: local('Clear Sans'),
|
||||
local('ClearSans'),
|
||||
url('fonts/clearsans-regular.woff') format('woff');
|
||||
url('../fonts/ClearSans-Regular.woff') format('woff');
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,10 @@ var StarUI = {
|
||||
if (!this._element("editBookmarkPanelContent").hidden)
|
||||
this.quitEditMode();
|
||||
|
||||
if (this._anchorToolbarButton) {
|
||||
this._anchorToolbarButton.removeAttribute("open");
|
||||
this._anchorToolbarButton = null;
|
||||
}
|
||||
this._restoreCommandsState();
|
||||
this._itemId = -1;
|
||||
if (this._batching) {
|
||||
@@ -186,6 +190,21 @@ var StarUI = {
|
||||
this._itemId = aItemId !== undefined ? aItemId : this._itemId;
|
||||
this.beginBatch();
|
||||
|
||||
if (aAnchorElement) {
|
||||
// Set the open=true attribute if the anchor is a
|
||||
// descendent of a toolbarbutton.
|
||||
let parent = aAnchorElement.parentNode;
|
||||
while (parent) {
|
||||
if (parent.localName == "toolbarbutton") {
|
||||
break;
|
||||
}
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
if (parent) {
|
||||
this._anchorToolbarButton = parent;
|
||||
parent.setAttribute("open", "true");
|
||||
}
|
||||
}
|
||||
this.panel.openPopup(aAnchorElement, aPosition);
|
||||
|
||||
gEditItemOverlay.initPanel(this._itemId,
|
||||
|
||||
@@ -237,10 +237,6 @@ let gSyncUI = {
|
||||
},
|
||||
|
||||
_getAppName: function () {
|
||||
try {
|
||||
let syncStrings = new StringBundle("chrome://browser/locale/sync.properties");
|
||||
return syncStrings.getFormattedString("sync.defaultAccountApplication", [brandName]);
|
||||
} catch (ex) {}
|
||||
let brand = new StringBundle("chrome://branding/locale/brand.properties");
|
||||
return brand.get("brandShortName");
|
||||
},
|
||||
|
||||
@@ -56,9 +56,6 @@ browser.jar:
|
||||
content/browser/aboutaccounts/main.css (content/aboutaccounts/main.css)
|
||||
content/browser/aboutaccounts/normalize.css (content/aboutaccounts/normalize.css)
|
||||
content/browser/aboutaccounts/fonts.css (content/aboutaccounts/fonts.css)
|
||||
content/browser/aboutaccounts/fonts/clearsans-regular.woff (content/aboutaccounts/fonts/clearsans-regular.woff)
|
||||
content/browser/aboutaccounts/fonts/firasans-light.woff (content/aboutaccounts/fonts/firasans-light.woff)
|
||||
content/browser/aboutaccounts/fonts/firasans-regular.woff (content/aboutaccounts/fonts/firasans-regular.woff)
|
||||
content/browser/aboutaccounts/images/fox.png (content/aboutaccounts/images/fox.png)
|
||||
content/browser/aboutaccounts/images/graphic_sync_intro.png (content/aboutaccounts/images/graphic_sync_intro.png)
|
||||
content/browser/aboutaccounts/images/graphic_sync_intro@2x.png (content/aboutaccounts/images/graphic_sync_intro@2x.png)
|
||||
@@ -77,6 +74,9 @@ browser.jar:
|
||||
* content/browser/browser-tabPreviews.xml (content/browser-tabPreviews.xml)
|
||||
* content/browser/chatWindow.xul (content/chatWindow.xul)
|
||||
content/browser/content.js (content/content.js)
|
||||
content/browser/fonts/ClearSans-Regular.woff (content/fonts/ClearSans-Regular.woff)
|
||||
content/browser/fonts/FiraSans-Regular.woff (content/fonts/FiraSans-Regular.woff)
|
||||
content/browser/fonts/FiraSans-Light.woff (content/fonts/FiraSans-Light.woff)
|
||||
content/browser/newtab/newTab.xul (content/newtab/newTab.xul)
|
||||
* content/browser/newtab/newTab.js (content/newtab/newTab.js)
|
||||
content/browser/newtab/newTab.css (content/newtab/newTab.css)
|
||||
|
||||
@@ -297,11 +297,12 @@ let CustomizableUIInternal = {
|
||||
|
||||
let areaIsKnown = gAreas.has(aName);
|
||||
let props = areaIsKnown ? gAreas.get(aName) : new Map();
|
||||
if (areaIsKnown && aProperties["type"] &&
|
||||
props.get("type") != aProperties["type"]) {
|
||||
throw new Error("An area cannot change types");
|
||||
}
|
||||
const kImmutableProperties = new Set(["type", "legacy", "overflowable"]);
|
||||
for (let key in aProperties) {
|
||||
if (areaIsKnown && kImmutableProperties.has(key) &&
|
||||
props.get(key) != aProperties[key]) {
|
||||
throw new Error("An area cannot change the property for '" + key + "'");
|
||||
}
|
||||
//XXXgijs for special items, we need to make sure they have an appropriate ID
|
||||
// so we aren't perpetually in a non-default state:
|
||||
if (key == "defaultPlacements" && Array.isArray(aProperties[key])) {
|
||||
@@ -3458,8 +3459,8 @@ function WidgetSingleWrapper(aWidget, aNode) {
|
||||
this[prop] = aWidget[prop];
|
||||
}
|
||||
|
||||
const nodeProps = ["label", "tooltiptext"];
|
||||
for (let prop of nodeProps) {
|
||||
const kNodeProps = ["label", "tooltiptext"];
|
||||
for (let prop of kNodeProps) {
|
||||
let propertyName = prop;
|
||||
// Look at the node for these, instead of the widget data, to ensure the
|
||||
// wrapper always reflects this live instance.
|
||||
|
||||
@@ -105,6 +105,6 @@ skip-if = os == "linux"
|
||||
[browser_992747_toggle_noncustomizable_toolbar.js]
|
||||
[browser_993322_widget_notoolbar.js]
|
||||
[browser_995164_registerArea_during_customize_mode.js]
|
||||
[browser_996364_defaultCollapsed.js]
|
||||
[browser_996364_registerArea_different_properties.js]
|
||||
[browser_bootstrapped_custom_toolbar.js]
|
||||
[browser_panel_toggle.js]
|
||||
|
||||
@@ -58,7 +58,19 @@ add_task(function*() {
|
||||
let otherTB = otherWin.document.createElementNS(kNSXUL, "toolbar");
|
||||
otherTB.id = TOOLBARID;
|
||||
otherTB.setAttribute("customizable", "true");
|
||||
let wasInformedCorrectlyOfAreaAppearing = false;
|
||||
let listener = {
|
||||
onAreaNodeRegistered: function(aArea, aNode) {
|
||||
if (aNode == otherTB) {
|
||||
wasInformedCorrectlyOfAreaAppearing = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
CustomizableUI.addListener(listener);
|
||||
otherWin.gNavToolbox.appendChild(otherTB);
|
||||
ok(wasInformedCorrectlyOfAreaAppearing, "Should have been told area was registered.");
|
||||
CustomizableUI.removeListener(listener);
|
||||
|
||||
ok(otherTB.querySelector("#sync-button"), "Sync button is on other toolbar, too.");
|
||||
|
||||
simulateItemDrag(syncButton, gNavToolbox.palette);
|
||||
@@ -73,18 +85,25 @@ add_task(function*() {
|
||||
ok(otherTB.querySelector("#sync-button"), "Sync button is on other toolbar, too.");
|
||||
|
||||
let wasInformedCorrectlyOfAreaDisappearing = false;
|
||||
let listener = {
|
||||
let windowClosed = null;
|
||||
listener = {
|
||||
onAreaNodeUnregistered: function(aArea, aNode, aReason) {
|
||||
if (aArea == TOOLBARID) {
|
||||
is(aNode, otherTB, "Should be informed about other toolbar");
|
||||
is(aReason, CustomizableUI.REASON_WINDOW_CLOSED, "Reason should be correct.");
|
||||
wasInformedCorrectlyOfAreaDisappearing = (aReason === CustomizableUI.REASON_WINDOW_CLOSED);
|
||||
}
|
||||
}
|
||||
},
|
||||
onWindowClosed: function(aWindow) {
|
||||
if (aWindow == otherWin) {
|
||||
windowClosed = aWindow;
|
||||
}
|
||||
},
|
||||
};
|
||||
CustomizableUI.addListener(listener);
|
||||
yield promiseWindowClosed(otherWin);
|
||||
|
||||
is(windowClosed, otherWin, "Window should have sent onWindowClosed notification.");
|
||||
ok(wasInformedCorrectlyOfAreaDisappearing, "Should be told about window closing.");
|
||||
CustomizableUI.removeListener(listener);
|
||||
// Closing the other window should not be counted against this window's customize mode:
|
||||
|
||||
@@ -1,56 +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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Calling CustomizableUI.registerArea twice with no
|
||||
// properties should not throw an exception.
|
||||
add_task(function() {
|
||||
try {
|
||||
CustomizableUI.registerArea("area-996364", {});
|
||||
CustomizableUI.registerArea("area-996364", {});
|
||||
} catch (ex) {
|
||||
ok(false, ex.message);
|
||||
}
|
||||
|
||||
CustomizableUI.unregisterArea("area-996364", true);
|
||||
});
|
||||
|
||||
add_task(function() {
|
||||
let exceptionThrown = false;
|
||||
try {
|
||||
CustomizableUI.registerArea("area-996364-2", {"type": CustomizableUI.TYPE_TOOLBAR, "defaultCollapsed": "false"});
|
||||
} catch (ex) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
ok(exceptionThrown, "defaultCollapsed is not allowed as an external property");
|
||||
|
||||
// No need to unregister the area because registration fails.
|
||||
});
|
||||
|
||||
add_task(function() {
|
||||
let exceptionThrown;
|
||||
try {
|
||||
CustomizableUI.registerArea("area-996364-3", {"type": CustomizableUI.TYPE_TOOLBAR});
|
||||
CustomizableUI.registerArea("area-996364-3", {"type": CustomizableUI.TYPE_MENU_PANEL});
|
||||
} catch (ex) {
|
||||
exceptionThrown = ex;
|
||||
}
|
||||
ok(exceptionThrown, "Exception expected, an area cannot change types: " + (exceptionThrown ? exceptionThrown : "[no exception]"));
|
||||
|
||||
CustomizableUI.unregisterArea("area-996364-3", true);
|
||||
});
|
||||
|
||||
add_task(function() {
|
||||
let exceptionThrown;
|
||||
try {
|
||||
CustomizableUI.registerArea("area-996364-4", {"type": CustomizableUI.TYPE_MENU_PANEL});
|
||||
CustomizableUI.registerArea("area-996364-4", {"type": CustomizableUI.TYPE_TOOLBAR});
|
||||
} catch (ex) {
|
||||
exceptionThrown = ex;
|
||||
}
|
||||
ok(exceptionThrown, "Exception expected, an area cannot change types: " + (exceptionThrown ? exceptionThrown : "[no exception]"));
|
||||
|
||||
CustomizableUI.unregisterArea("area-996364-4", true);
|
||||
});
|
||||
@@ -0,0 +1,112 @@
|
||||
/* 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";
|
||||
|
||||
// Calling CustomizableUI.registerArea twice with no
|
||||
// properties should not throw an exception.
|
||||
add_task(function() {
|
||||
try {
|
||||
CustomizableUI.registerArea("area-996364", {});
|
||||
CustomizableUI.registerArea("area-996364", {});
|
||||
} catch (ex) {
|
||||
ok(false, ex.message);
|
||||
}
|
||||
|
||||
CustomizableUI.unregisterArea("area-996364", true);
|
||||
});
|
||||
|
||||
add_task(function() {
|
||||
let exceptionThrown = false;
|
||||
try {
|
||||
CustomizableUI.registerArea("area-996364-2", {type: CustomizableUI.TYPE_TOOLBAR, defaultCollapsed: "false"});
|
||||
} catch (ex) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
ok(exceptionThrown, "defaultCollapsed is not allowed as an external property");
|
||||
|
||||
// No need to unregister the area because registration fails.
|
||||
});
|
||||
|
||||
add_task(function() {
|
||||
let exceptionThrown;
|
||||
try {
|
||||
CustomizableUI.registerArea("area-996364-3", {type: CustomizableUI.TYPE_TOOLBAR});
|
||||
CustomizableUI.registerArea("area-996364-3", {type: CustomizableUI.TYPE_MENU_PANEL});
|
||||
} catch (ex) {
|
||||
exceptionThrown = ex;
|
||||
}
|
||||
ok(exceptionThrown, "Exception expected, an area cannot change types: " + (exceptionThrown ? exceptionThrown : "[no exception]"));
|
||||
|
||||
CustomizableUI.unregisterArea("area-996364-3", true);
|
||||
});
|
||||
|
||||
add_task(function() {
|
||||
let exceptionThrown;
|
||||
try {
|
||||
CustomizableUI.registerArea("area-996364-4", {type: CustomizableUI.TYPE_MENU_PANEL});
|
||||
CustomizableUI.registerArea("area-996364-4", {type: CustomizableUI.TYPE_TOOLBAR});
|
||||
} catch (ex) {
|
||||
exceptionThrown = ex;
|
||||
}
|
||||
ok(exceptionThrown, "Exception expected, an area cannot change types: " + (exceptionThrown ? exceptionThrown : "[no exception]"));
|
||||
|
||||
CustomizableUI.unregisterArea("area-996364-4", true);
|
||||
});
|
||||
|
||||
add_task(function() {
|
||||
let exceptionThrown;
|
||||
try {
|
||||
CustomizableUI.registerArea("area-996899-1", { anchor: "PanelUI-menu-button",
|
||||
type: CustomizableUI.TYPE_MENU_PANEL,
|
||||
defaultPlacements: [] });
|
||||
CustomizableUI.registerArea("area-996899-1", { anchor: "home-button",
|
||||
type: CustomizableUI.TYPE_MENU_PANEL,
|
||||
defaultPlacements: [] });
|
||||
} catch (ex) {
|
||||
exceptionThrown = ex;
|
||||
}
|
||||
ok(!exceptionThrown, "Changing anchors shouldn't throw an exception: " + (exceptionThrown ? exceptionThrown : "[no exception]"));
|
||||
CustomizableUI.unregisterArea("area-996899-1", true);
|
||||
});
|
||||
|
||||
add_task(function() {
|
||||
let exceptionThrown;
|
||||
try {
|
||||
CustomizableUI.registerArea("area-996899-2", { anchor: "PanelUI-menu-button",
|
||||
type: CustomizableUI.TYPE_MENU_PANEL,
|
||||
defaultPlacements: [] });
|
||||
CustomizableUI.registerArea("area-996899-2", { anchor: "PanelUI-menu-button",
|
||||
type: CustomizableUI.TYPE_MENU_PANEL,
|
||||
defaultPlacements: ["feed-button"] });
|
||||
} catch (ex) {
|
||||
exceptionThrown = ex;
|
||||
}
|
||||
ok(!exceptionThrown, "Changing defaultPlacements shouldn't throw an exception: " + (exceptionThrown ? exceptionThrown : "[no exception]"));
|
||||
CustomizableUI.unregisterArea("area-996899-2", true);
|
||||
});
|
||||
|
||||
add_task(function() {
|
||||
let exceptionThrown;
|
||||
try {
|
||||
CustomizableUI.registerArea("area-996899-3", { legacy: true });
|
||||
CustomizableUI.registerArea("area-996899-3", { legacy: false });
|
||||
} catch (ex) {
|
||||
exceptionThrown = ex;
|
||||
}
|
||||
ok(exceptionThrown, "Changing 'legacy' should throw an exception: " + (exceptionThrown ? exceptionThrown : "[no exception]"));
|
||||
CustomizableUI.unregisterArea("area-996899-3", true);
|
||||
});
|
||||
|
||||
add_task(function() {
|
||||
let exceptionThrown;
|
||||
try {
|
||||
CustomizableUI.registerArea("area-996899-4", { overflowable: true });
|
||||
CustomizableUI.registerArea("area-996899-4", { overflowable: false });
|
||||
} catch (ex) {
|
||||
exceptionThrown = ex;
|
||||
}
|
||||
ok(exceptionThrown, "Changing 'overflowable' should throw an exception: " + (exceptionThrown ? exceptionThrown : "[no exception]"));
|
||||
CustomizableUI.unregisterArea("area-996899-4", true);
|
||||
});
|
||||
@@ -678,8 +678,6 @@ let SessionStoreInternal = {
|
||||
debug("received unknown message '" + aMessage.name + "'");
|
||||
break;
|
||||
}
|
||||
|
||||
this._clearRestoringWindows();
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -3400,6 +3398,15 @@ let SessionStoreInternal = {
|
||||
this._closedWindows.splice(spliceTo, this._closedWindows.length);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clears the set of windows that are "resurrected" before writing to disk to
|
||||
* make closing windows one after the other until shutdown work as expected.
|
||||
*
|
||||
* This function should only be called when we are sure that there has been
|
||||
* a user action that indicates the browser is actively being used and all
|
||||
* windows that have been closed before are not part of a series of closing
|
||||
* windows.
|
||||
*/
|
||||
_clearRestoringWindows: function ssi_clearRestoringWindows() {
|
||||
for (let i = 0; i < this._closedWindows.length; i++) {
|
||||
delete this._closedWindows[i]._shouldRestore;
|
||||
|
||||
@@ -115,25 +115,27 @@ function test_3() {
|
||||
is(curState.selectedWindow, 4, "Last window opened is the one selected");
|
||||
|
||||
waitForWindowClose(normalWindow, function() {
|
||||
// Load another tab before checking the written state so that
|
||||
// Pin and unpin a tab before checking the written state so that
|
||||
// the list of restoring windows gets cleared. Otherwise the
|
||||
// window we just closed would be marked as not closed.
|
||||
waitForTabLoad(aWindow, "http://www.example.com/", function() {
|
||||
forceWriteState(function(state) {
|
||||
is(state.windows.length, 2,
|
||||
"sessionstore state: 2 windows in data being written to disk");
|
||||
is(state.selectedWindow, 2,
|
||||
"Selected window is updated to match one of the saved windows");
|
||||
state.windows.forEach(function(win) {
|
||||
is(!win.isPrivate, true, "Saved window is not private");
|
||||
});
|
||||
is(state._closedWindows.length, 1,
|
||||
"sessionstore state: 1 closed window in data being written to disk");
|
||||
state._closedWindows.forEach(function(win) {
|
||||
is(!win.isPrivate, true, "Closed window is not private");
|
||||
});
|
||||
runNextTest();
|
||||
let tab = aWindow.gBrowser.tabs[0];
|
||||
aWindow.gBrowser.pinTab(tab);
|
||||
aWindow.gBrowser.unpinTab(tab);
|
||||
|
||||
forceWriteState(function(state) {
|
||||
is(state.windows.length, 2,
|
||||
"sessionstore state: 2 windows in data being written to disk");
|
||||
is(state.selectedWindow, 2,
|
||||
"Selected window is updated to match one of the saved windows");
|
||||
state.windows.forEach(function(win) {
|
||||
is(!win.isPrivate, true, "Saved window is not private");
|
||||
});
|
||||
is(state._closedWindows.length, 1,
|
||||
"sessionstore state: 1 closed window in data being written to disk");
|
||||
state._closedWindows.forEach(function(win) {
|
||||
is(!win.isPrivate, true, "Closed window is not private");
|
||||
});
|
||||
runNextTest();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
content browser_dbg_addon4 .
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="text/javascript" src="testxul.js"/>
|
||||
<label value="test.xul"/>
|
||||
</window>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="text/javascript" src="testxul2.js"/>
|
||||
<label value="test2.xul"/>
|
||||
</window>
|
||||
@@ -0,0 +1,4 @@
|
||||
// Define something in here or the script may get collected
|
||||
window.addEventListener("unload", function() {
|
||||
window.foo = "bar";
|
||||
});
|
||||
@@ -0,0 +1,4 @@
|
||||
// Define something in here or the script may get collected
|
||||
window.addEventListener("unload", function() {
|
||||
window.foo = "bar";
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
content browser_dbg_addon5 .
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="text/javascript" src="testxul.js"/>
|
||||
<label value="test.xul"/>
|
||||
</window>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="text/javascript" src="testxul2.js"/>
|
||||
<label value="test2.xul"/>
|
||||
</window>
|
||||
@@ -0,0 +1,4 @@
|
||||
// Define something in here or the script may get collected
|
||||
window.addEventListener("unload", function() {
|
||||
window.foo = "bar";
|
||||
});
|
||||
@@ -0,0 +1,4 @@
|
||||
// Define something in here or the script may get collected
|
||||
window.addEventListener("unload", function() {
|
||||
window.foo = "bar";
|
||||
});
|
||||
Binary file not shown.
Binary file not shown.
@@ -8,6 +8,8 @@ const ADDON_URL = EXAMPLE_URL + "addon5.xpi";
|
||||
function test() {
|
||||
Task.spawn(function () {
|
||||
let addon = yield addAddon(ADDON_URL);
|
||||
let tab1 = yield addTab("chrome://browser_dbg_addon5/content/test.xul");
|
||||
|
||||
let addonDebugger = yield initAddonDebugger(ADDON_URL);
|
||||
|
||||
is(addonDebugger.title, "Debugger - Test unpacked add-on with JS Modules", "Saw the right toolbox title.");
|
||||
@@ -15,33 +17,44 @@ function test() {
|
||||
// Check the inital list of sources is correct
|
||||
let groups = yield addonDebugger.getSourceGroups();
|
||||
is(groups[0].name, "browser_dbg_addon5@tests.mozilla.org", "Add-on code should be the first group");
|
||||
is(groups.length, 1, "Should be only one group.");
|
||||
is(groups[1].name, "chrome://global", "XUL code should be the second group");
|
||||
is(groups.length, 2, "Should be only two groups.");
|
||||
|
||||
let sources = groups[0].sources;
|
||||
is(sources.length, 2, "Should be two sources");
|
||||
ok(sources[0].url.endsWith("/browser_dbg_addon5@tests.mozilla.org/bootstrap.js"), "correct url for bootstrap code")
|
||||
is(sources[0].label, "bootstrap.js", "correct label for bootstrap code")
|
||||
is(sources[1].url, "resource://browser_dbg_addon5/test.jsm", "correct url for addon code")
|
||||
is(sources[1].label, "test.jsm", "correct label for addon code")
|
||||
|
||||
// Load a new module and check it appears in the list of sources
|
||||
Cu.import("resource://browser_dbg_addon5/test2.jsm", {});
|
||||
|
||||
groups = yield addonDebugger.getSourceGroups();
|
||||
is(groups[0].name, "browser_dbg_addon5@tests.mozilla.org", "Add-on code should be the first group");
|
||||
is(groups.length, 1, "Should be only one group.");
|
||||
|
||||
sources = groups[0].sources;
|
||||
is(sources.length, 3, "Should be three sources");
|
||||
ok(sources[0].url.endsWith("/browser_dbg_addon5@tests.mozilla.org/bootstrap.js"), "correct url for bootstrap code")
|
||||
is(sources[0].label, "bootstrap.js", "correct label for bootstrap code")
|
||||
is(sources[1].url, "resource://browser_dbg_addon5/test.jsm", "correct url for addon code")
|
||||
is(sources[1].label, "test.jsm", "correct label for addon code")
|
||||
is(sources[2].url, "resource://browser_dbg_addon5/test2.jsm", "correct url for addon code")
|
||||
is(sources[2].label, "test2.jsm", "correct label for addon code")
|
||||
is(sources[2].url, "chrome://browser_dbg_addon5/content/testxul.js", "correct url for addon tab code")
|
||||
is(sources[2].label, "testxul.js", "correct label for addon tab code")
|
||||
|
||||
// Load a new module and tab and check they appear in the list of sources
|
||||
Cu.import("resource://browser_dbg_addon5/test2.jsm", {});
|
||||
let tab2 = yield addTab("chrome://browser_dbg_addon5/content/test2.xul");
|
||||
|
||||
groups = yield addonDebugger.getSourceGroups();
|
||||
is(groups[0].name, "browser_dbg_addon5@tests.mozilla.org", "Add-on code should be the first group");
|
||||
is(groups[1].name, "chrome://global", "XUL code should be the second group");
|
||||
is(groups.length, 2, "Should be only two groups.");
|
||||
|
||||
sources = groups[0].sources;
|
||||
is(sources.length, 5, "Should be five sources");
|
||||
ok(sources[0].url.endsWith("/browser_dbg_addon5@tests.mozilla.org/bootstrap.js"), "correct url for bootstrap code")
|
||||
is(sources[0].label, "bootstrap.js", "correct label for bootstrap code")
|
||||
is(sources[1].url, "resource://browser_dbg_addon5/test.jsm", "correct url for addon code")
|
||||
is(sources[1].label, "test.jsm", "correct label for addon code")
|
||||
is(sources[2].url, "chrome://browser_dbg_addon5/content/testxul.js", "correct url for addon tab code")
|
||||
is(sources[2].label, "testxul.js", "correct label for addon tab code")
|
||||
is(sources[3].url, "resource://browser_dbg_addon5/test2.jsm", "correct url for addon code")
|
||||
is(sources[3].label, "test2.jsm", "correct label for addon code")
|
||||
is(sources[4].url, "chrome://browser_dbg_addon5/content/testxul2.js", "correct url for addon tab code")
|
||||
is(sources[4].label, "testxul2.js", "correct label for addon tab code")
|
||||
|
||||
Cu.unload("resource://browser_dbg_addon5/test2.jsm");
|
||||
yield addonDebugger.destroy();
|
||||
yield removeTab(tab1);
|
||||
yield removeTab(tab2);
|
||||
yield removeAddon(addon);
|
||||
finish();
|
||||
});
|
||||
|
||||
@@ -8,6 +8,8 @@ const ADDON_URL = EXAMPLE_URL + "addon4.xpi";
|
||||
function test() {
|
||||
Task.spawn(function () {
|
||||
let addon = yield addAddon(ADDON_URL);
|
||||
let tab1 = yield addTab("chrome://browser_dbg_addon4/content/test.xul");
|
||||
|
||||
let addonDebugger = yield initAddonDebugger(ADDON_URL);
|
||||
|
||||
is(addonDebugger.title, "Debugger - Test add-on with JS Modules", "Saw the right toolbox title.");
|
||||
@@ -15,33 +17,44 @@ function test() {
|
||||
// Check the inital list of sources is correct
|
||||
let groups = yield addonDebugger.getSourceGroups();
|
||||
is(groups[0].name, "browser_dbg_addon4@tests.mozilla.org", "Add-on code should be the first group");
|
||||
is(groups.length, 1, "Should be only one group.");
|
||||
is(groups[1].name, "chrome://global", "XUL code should be the second group");
|
||||
is(groups.length, 2, "Should be only two groups.");
|
||||
|
||||
let sources = groups[0].sources;
|
||||
is(sources.length, 2, "Should be two sources");
|
||||
ok(sources[0].url.endsWith("/browser_dbg_addon4@tests.mozilla.org.xpi!/bootstrap.js"), "correct url for bootstrap code")
|
||||
is(sources[0].label, "bootstrap.js", "correct label for bootstrap code")
|
||||
is(sources[1].url, "resource://browser_dbg_addon4/test.jsm", "correct url for addon code")
|
||||
is(sources[1].label, "test.jsm", "correct label for addon code")
|
||||
|
||||
// Load a new module and check it appears in the list of sources
|
||||
Cu.import("resource://browser_dbg_addon4/test2.jsm", {});
|
||||
|
||||
groups = yield addonDebugger.getSourceGroups();
|
||||
is(groups[0].name, "browser_dbg_addon4@tests.mozilla.org", "Add-on code should be the first group");
|
||||
is(groups.length, 1, "Should be only one group.");
|
||||
|
||||
sources = groups[0].sources;
|
||||
is(sources.length, 3, "Should be three sources");
|
||||
ok(sources[0].url.endsWith("/browser_dbg_addon4@tests.mozilla.org.xpi!/bootstrap.js"), "correct url for bootstrap code")
|
||||
is(sources[0].label, "bootstrap.js", "correct label for bootstrap code")
|
||||
is(sources[1].url, "resource://browser_dbg_addon4/test.jsm", "correct url for addon code")
|
||||
is(sources[1].label, "test.jsm", "correct label for addon code")
|
||||
is(sources[2].url, "resource://browser_dbg_addon4/test2.jsm", "correct url for addon code")
|
||||
is(sources[2].label, "test2.jsm", "correct label for addon code")
|
||||
is(sources[2].url, "chrome://browser_dbg_addon4/content/testxul.js", "correct url for addon tab code")
|
||||
is(sources[2].label, "testxul.js", "correct label for addon tab code")
|
||||
|
||||
// Load a new module and tab and check they appear in the list of sources
|
||||
Cu.import("resource://browser_dbg_addon4/test2.jsm", {});
|
||||
let tab2 = yield addTab("chrome://browser_dbg_addon4/content/test2.xul");
|
||||
|
||||
groups = yield addonDebugger.getSourceGroups();
|
||||
is(groups[0].name, "browser_dbg_addon4@tests.mozilla.org", "Add-on code should be the first group");
|
||||
is(groups[1].name, "chrome://global", "XUL code should be the second group");
|
||||
is(groups.length, 2, "Should be only two groups.");
|
||||
|
||||
sources = groups[0].sources;
|
||||
is(sources.length, 5, "Should be five sources");
|
||||
ok(sources[0].url.endsWith("/browser_dbg_addon4@tests.mozilla.org.xpi!/bootstrap.js"), "correct url for bootstrap code")
|
||||
is(sources[0].label, "bootstrap.js", "correct label for bootstrap code")
|
||||
is(sources[1].url, "resource://browser_dbg_addon4/test.jsm", "correct url for addon code")
|
||||
is(sources[1].label, "test.jsm", "correct label for addon code")
|
||||
is(sources[2].url, "chrome://browser_dbg_addon4/content/testxul.js", "correct url for addon tab code")
|
||||
is(sources[2].label, "testxul.js", "correct label for addon tab code")
|
||||
is(sources[3].url, "resource://browser_dbg_addon4/test2.jsm", "correct url for addon code")
|
||||
is(sources[3].label, "test2.jsm", "correct label for addon code")
|
||||
is(sources[4].url, "chrome://browser_dbg_addon4/content/testxul2.js", "correct url for addon tab code")
|
||||
is(sources[4].label, "testxul2.js", "correct label for addon tab code")
|
||||
|
||||
Cu.unload("resource://browser_dbg_addon4/test2.jsm");
|
||||
yield addonDebugger.destroy();
|
||||
yield removeTab(tab1);
|
||||
yield removeTab(tab2);
|
||||
yield removeAddon(addon);
|
||||
finish();
|
||||
});
|
||||
|
||||
@@ -118,7 +118,11 @@ function addAddon(aUrl) {
|
||||
let listener = {
|
||||
onInstallEnded: function(aAddon, aAddonInstall) {
|
||||
aInstaller.removeListener(listener);
|
||||
deferred.resolve(aAddonInstall);
|
||||
|
||||
// Wait for add-on's startup scripts to execute. See bug 997408
|
||||
executeSoon(function() {
|
||||
deferred.resolve(aAddonInstall);
|
||||
});
|
||||
}
|
||||
};
|
||||
aInstaller.addListener(listener);
|
||||
|
||||
@@ -613,6 +613,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
||||
-moz-padding-end: 5px;
|
||||
}
|
||||
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]) > .toolbarbutton-menubutton-button[open] + .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):hover > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):hover > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):hover > .toolbarbutton-badge-container > .toolbarbutton-icon,
|
||||
@@ -631,7 +632,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled=true]):hover:active > .toolbarbutton-icon,
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled=true]):-moz-any(:hover:active, [open="true"]) > .toolbarbutton-icon,
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1[open="true"] > .toolbarbutton-menubutton-dropmarker:not([disabled=true]) > .dropmarker-icon,
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-badge-container > .toolbarbutton-icon,
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-icon {
|
||||
@@ -648,6 +649,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
||||
transition: background-color 150ms;
|
||||
}
|
||||
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-button[open],
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-button:hover:active,
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:hover:active {
|
||||
padding: 3px;
|
||||
|
||||
@@ -1,150 +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/. */
|
||||
|
||||
.ruleview {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ruleview-rule-source {
|
||||
-moz-padding-start: 5px;
|
||||
cursor: pointer;
|
||||
text-align: right;
|
||||
float: right;
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.ruleview-header {
|
||||
border-top-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-top-style: solid;
|
||||
border-bottom-style: solid;
|
||||
padding: 1px 4px;
|
||||
margin-top: 4px;
|
||||
-moz-user-select: none;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.ruleview-rule-source:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.ruleview-rule,
|
||||
#noResults {
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
#noResults {
|
||||
font: message-box;
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
.ruleview-rule + .ruleview-rule {
|
||||
border-top-width: 1px;
|
||||
border-top-style: dotted;
|
||||
}
|
||||
|
||||
.ruleview-warning {
|
||||
background: url("chrome://browser/skin/devtools/alerticon-warning.png");
|
||||
-moz-margin-start: 5px;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 13px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.ruleview-ruleopen {
|
||||
-moz-padding-end: 5px;
|
||||
}
|
||||
|
||||
.ruleview-ruleclose {
|
||||
cursor: text;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.ruleview-propertylist {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.ruleview-rule:not(:hover) .ruleview-enableproperty {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.ruleview-expander {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.ruleview-newproperty {
|
||||
/* (enable checkbox width: 12px) + (expander width: 15px) */
|
||||
-moz-margin-start: 27px;
|
||||
}
|
||||
|
||||
.ruleview-namecontainer,
|
||||
.ruleview-propertycontainer,
|
||||
.ruleview-propertyname,
|
||||
.ruleview-propertyvalue {
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
.ruleview-computedlist {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ruleview-computed {
|
||||
-moz-margin-start: 35px;
|
||||
}
|
||||
|
||||
.ruleview-colorswatch {
|
||||
border-radius: 50%;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: text-top;
|
||||
-moz-margin-end: 5px;
|
||||
}
|
||||
|
||||
.ruleview-overridden {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.theme-light .ruleview-overridden {
|
||||
-moz-text-decoration-color: #667380; /* Content (Text) - Dark Grey */
|
||||
}
|
||||
|
||||
.styleinspector-propertyeditor {
|
||||
border: 1px solid #CCC;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ruleview-property {
|
||||
border-left: 2px solid transparent;
|
||||
clear: right;
|
||||
}
|
||||
|
||||
.ruleview-property > * {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.ruleview-property[dirty] {
|
||||
border-left-color: #68E268;
|
||||
}
|
||||
|
||||
.ruleview-namecontainer > .ruleview-propertyname,
|
||||
.ruleview-propertycontainer > .ruleview-propertyvalue {
|
||||
border-bottom: 1px dashed transparent;
|
||||
}
|
||||
|
||||
.ruleview-namecontainer:hover > .ruleview-propertyname,
|
||||
.ruleview-propertycontainer:hover > .ruleview-propertyvalue {
|
||||
border-bottom-color: hsl(0,0%,50%);
|
||||
}
|
||||
|
||||
.ruleview-selector {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.ruleview-selector-separator, .ruleview-selector-unmatched {
|
||||
color: #888;
|
||||
}
|
||||
@@ -105,7 +105,6 @@ browser.jar:
|
||||
skin/classic/browser/feeds/audioFeedIcon16.png (feeds/feedIcon16.png)
|
||||
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.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/controls.png (../shared/newtab/controls.png)
|
||||
skin/classic/browser/places/bookmarksMenu.png (places/bookmarksMenu.png)
|
||||
@@ -201,7 +200,7 @@ browser.jar:
|
||||
skin/classic/browser/devtools/command-console.png (../shared/devtools/images/command-console.png)
|
||||
skin/classic/browser/devtools/command-console@2x.png (../shared/devtools/images/command-console@2x.png)
|
||||
skin/classic/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
|
||||
skin/classic/browser/devtools/ruleview.css (devtools/ruleview.css)
|
||||
* skin/classic/browser/devtools/ruleview.css (../shared/devtools/ruleview.css)
|
||||
* skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
|
||||
skin/classic/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)
|
||||
skin/classic/browser/devtools/webconsole.png (devtools/webconsole.png)
|
||||
|
||||
@@ -512,6 +512,7 @@ toolbar .toolbarbutton-1:not(:-moz-any([type="menu-button"],#back-button,#forwar
|
||||
}
|
||||
|
||||
toolbar .toolbarbutton-1:not(:-moz-any([type="menu-button"],[disabled],[open],#back-button,#forward-button)):hover,
|
||||
toolbar .toolbarbutton-1[type="menu-button"]:not([disabled]) > .toolbarbutton-menubutton-button[open] + .toolbarbutton-menubutton-dropmarker,
|
||||
toolbar .toolbarbutton-1[type="menu-button"]:not([disabled]):-moz-any(:hover,[open]) > .toolbarbutton-menubutton-button,
|
||||
toolbar .toolbarbutton-1[type="menu-button"]:not([disabled]):-moz-any(:hover,[open]) > .toolbarbutton-menubutton-dropmarker,
|
||||
toolbar .toolbaritem-combined-buttons:hover > .toolbarbutton-combined {
|
||||
@@ -527,6 +528,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[type="menu-button"]:not([disabled]) > .toolbarbutton-menubutton-button[open],
|
||||
toolbar .toolbarbutton-1[type="menu-button"]:not(:-moz-any([disabled],[open]))[buttonover]:active > .toolbarbutton-menubutton-button,
|
||||
toolbar .toolbarbutton-1[type="menu-button"]:not(:-moz-any([disabled],[open],[buttonover])):hover:active > .toolbarbutton-menubutton-dropmarker,
|
||||
toolbar .toolbarbutton-1[type="menu-button"][open]:not([disabled]) > .toolbarbutton-menubutton-dropmarker {
|
||||
|
||||
@@ -169,7 +169,6 @@ browser.jar:
|
||||
skin/classic/browser/feeds/videoFeedIcon16.png (feeds/feedIcon16.png)
|
||||
skin/classic/browser/feeds/audioFeedIcon.png (feeds/feedIcon.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/controls.png (../shared/newtab/controls.png)
|
||||
skin/classic/browser/newtab/controls@2x.png (newtab/controls@2x.png)
|
||||
@@ -322,7 +321,7 @@ browser.jar:
|
||||
skin/classic/browser/devtools/command-console.png (../shared/devtools/images/command-console.png)
|
||||
skin/classic/browser/devtools/command-console@2x.png (../shared/devtools/images/command-console@2x.png)
|
||||
skin/classic/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
|
||||
skin/classic/browser/devtools/ruleview.css (devtools/ruleview.css)
|
||||
* skin/classic/browser/devtools/ruleview.css (../shared/devtools/ruleview.css)
|
||||
skin/classic/browser/devtools/commandline.css (devtools/commandline.css)
|
||||
skin/classic/browser/devtools/markup-view.css (../shared/devtools/markup-view.css)
|
||||
skin/classic/browser/devtools/editor-error.png (devtools/editor-error.png)
|
||||
|
||||
Binary file not shown.
@@ -22,6 +22,9 @@
|
||||
padding: 1px 4px;
|
||||
-moz-user-select: none;
|
||||
word-wrap: break-word;
|
||||
%ifndef XP_MACOSX
|
||||
margin-top: 4px;
|
||||
%endif
|
||||
}
|
||||
|
||||
.ruleview-rule-pseudo-element {
|
||||
@@ -123,7 +126,7 @@
|
||||
}
|
||||
|
||||
.ruleview-property {
|
||||
border-left: 2px solid transparent;
|
||||
border-left: 3px solid transparent;
|
||||
clear: right;
|
||||
}
|
||||
|
||||
@@ -131,8 +134,12 @@
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.ruleview-property[dirty] {
|
||||
border-left-color: #68E268;
|
||||
.theme-dark .ruleview-property[dirty] {
|
||||
border-left-color: #70bf53; /* Green */
|
||||
}
|
||||
|
||||
.theme-light .ruleview-property[dirty] {
|
||||
border-left-color: #2cbb0f; /* Green */
|
||||
}
|
||||
|
||||
.ruleview-namecontainer > .ruleview-propertyname,
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
@font-face {
|
||||
font-family: "Clear Sans";
|
||||
src: url("chrome://browser/skin/fonts/ClearSans-Regular.ttf");
|
||||
src: url("chrome://browser/content/fonts/ClearSans-Regular.woff") format('woff');
|
||||
}
|
||||
|
||||
page {
|
||||
|
||||
@@ -730,6 +730,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
||||
border-color: hsla(210,4%,10%,.1);
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1:not([disabled=true]) > .toolbarbutton-menubutton-button[open] + .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
|
||||
#nav-bar .toolbarbutton-1:not([disabled=true]):-moz-any(:hover,[open]) > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
|
||||
#nav-bar .toolbarbutton-1:not([disabled=true]):-moz-any(:hover,[open]) > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
|
||||
#nav-bar .toolbarbutton-1:not([disabled=true]):not([checked]):not([open]):not(:active):hover > .toolbarbutton-icon,
|
||||
@@ -799,7 +800,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
||||
}
|
||||
%endif
|
||||
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled=true]):hover:active > .toolbarbutton-icon,
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled=true]):-moz-any(:hover:active, [open]) > .toolbarbutton-icon,
|
||||
#nav-bar .toolbarbutton-1[open] > .toolbarbutton-menubutton-dropmarker:not([disabled=true]) > .dropmarker-icon,
|
||||
#nav-bar .toolbarbutton-1:not([disabled=true]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-icon,
|
||||
#nav-bar .toolbarbutton-1:not([disabled=true]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-text,
|
||||
|
||||
@@ -1,150 +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/. */
|
||||
|
||||
.ruleview {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ruleview-rule-source {
|
||||
-moz-padding-start: 5px;
|
||||
cursor: pointer;
|
||||
text-align: right;
|
||||
float: right;
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.ruleview-header {
|
||||
border-top-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-top-style: solid;
|
||||
border-bottom-style: solid;
|
||||
padding: 1px 4px;
|
||||
margin-top: 4px;
|
||||
-moz-user-select: none;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.ruleview-rule-source:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.ruleview-rule,
|
||||
#noResults {
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
#noResults {
|
||||
font: message-box;
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
.ruleview-rule + .ruleview-rule {
|
||||
border-top-width: 1px;
|
||||
border-top-style: dotted;
|
||||
}
|
||||
|
||||
.ruleview-warning {
|
||||
background: url("chrome://browser/skin/devtools/alerticon-warning.png");
|
||||
-moz-margin-start: 5px;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 13px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.ruleview-ruleopen {
|
||||
-moz-padding-end: 5px;
|
||||
}
|
||||
|
||||
.ruleview-ruleclose {
|
||||
cursor: text;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.ruleview-propertylist {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.ruleview-rule:not(:hover) .ruleview-enableproperty {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.ruleview-expander {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.ruleview-newproperty {
|
||||
/* (enable checkbox width: 12px) + (expander width: 15px) */
|
||||
-moz-margin-start: 27px;
|
||||
}
|
||||
|
||||
.ruleview-namecontainer,
|
||||
.ruleview-propertycontainer,
|
||||
.ruleview-propertyname,
|
||||
.ruleview-propertyvalue {
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
.ruleview-computedlist {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ruleview-computed {
|
||||
-moz-margin-start: 35px;
|
||||
}
|
||||
|
||||
.ruleview-colorswatch {
|
||||
border-radius: 50%;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: text-top;
|
||||
-moz-margin-end: 5px;
|
||||
}
|
||||
|
||||
.ruleview-overridden {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.theme-light .ruleview-overridden {
|
||||
-moz-text-decoration-color: #667380; /* Content (Text) - Dark Grey */
|
||||
}
|
||||
|
||||
.styleinspector-propertyeditor {
|
||||
border: 1px solid #CCC;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ruleview-property {
|
||||
border-left: 2px solid transparent;
|
||||
clear: right;
|
||||
}
|
||||
|
||||
.ruleview-property > * {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.ruleview-property[dirty] {
|
||||
border-left-color: #68E268;
|
||||
}
|
||||
|
||||
.ruleview-namecontainer > .ruleview-propertyname,
|
||||
.ruleview-propertycontainer > .ruleview-propertyvalue {
|
||||
border-bottom: 1px dashed transparent;
|
||||
}
|
||||
|
||||
.ruleview-namecontainer:hover > .ruleview-propertyname,
|
||||
.ruleview-propertycontainer:hover > .ruleview-propertyvalue {
|
||||
border-bottom-color: hsl(0,0%,50%);
|
||||
}
|
||||
|
||||
.ruleview-selector {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.ruleview-selector-separator, .ruleview-selector-unmatched {
|
||||
color: #888;
|
||||
}
|
||||
@@ -126,7 +126,6 @@ browser.jar:
|
||||
skin/classic/browser/feeds/videoFeedIcon16.png (feeds/feedIcon16.png)
|
||||
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.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/controls.png (../shared/newtab/controls.png)
|
||||
skin/classic/browser/places/places.css (places/places.css)
|
||||
@@ -226,7 +225,7 @@ browser.jar:
|
||||
* skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
|
||||
skin/classic/browser/devtools/commandline-icon.png (devtools/commandline-icon.png)
|
||||
skin/classic/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
|
||||
skin/classic/browser/devtools/ruleview.css (devtools/ruleview.css)
|
||||
* skin/classic/browser/devtools/ruleview.css (../shared/devtools/ruleview.css)
|
||||
skin/classic/browser/devtools/commandline.css (devtools/commandline.css)
|
||||
skin/classic/browser/devtools/command-paintflashing.png (../shared/devtools/images/command-paintflashing.png)
|
||||
skin/classic/browser/devtools/command-paintflashing@2x.png (../shared/devtools/images/command-paintflashing@2x.png)
|
||||
@@ -491,7 +490,6 @@ browser.jar:
|
||||
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-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/controls.png (../shared/newtab/controls.png)
|
||||
* skin/classic/aero/browser/places/places.css (places/places-aero.css)
|
||||
@@ -602,7 +600,7 @@ browser.jar:
|
||||
skin/classic/aero/browser/devtools/command-console.png (../shared/devtools/images/command-console.png)
|
||||
skin/classic/aero/browser/devtools/command-console@2x.png (../shared/devtools/images/command-console@2x.png)
|
||||
skin/classic/aero/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
|
||||
skin/classic/aero/browser/devtools/ruleview.css (devtools/ruleview.css)
|
||||
* skin/classic/aero/browser/devtools/ruleview.css (../shared/devtools/ruleview.css)
|
||||
skin/classic/aero/browser/devtools/commandline.css (devtools/commandline.css)
|
||||
skin/classic/aero/browser/devtools/markup-view.css (../shared/devtools/markup-view.css)
|
||||
skin/classic/aero/browser/devtools/editor-error.png (devtools/editor-error.png)
|
||||
|
||||
@@ -491,65 +491,7 @@ abstract public class BrowserApp extends GeckoApp
|
||||
mBrowserSearch.setUserVisibleHint(false);
|
||||
}
|
||||
|
||||
mBrowserToolbar.setOnActivateListener(new BrowserToolbar.OnActivateListener() {
|
||||
public void onActivate() {
|
||||
enterEditingMode();
|
||||
}
|
||||
});
|
||||
|
||||
mBrowserToolbar.setOnCommitListener(new BrowserToolbar.OnCommitListener() {
|
||||
public void onCommit() {
|
||||
commitEditingMode();
|
||||
}
|
||||
});
|
||||
|
||||
mBrowserToolbar.setOnDismissListener(new BrowserToolbar.OnDismissListener() {
|
||||
public void onDismiss() {
|
||||
mBrowserToolbar.cancelEdit();
|
||||
}
|
||||
});
|
||||
|
||||
mBrowserToolbar.setOnFilterListener(new BrowserToolbar.OnFilterListener() {
|
||||
public void onFilter(String searchText, AutocompleteHandler handler) {
|
||||
filterEditingMode(searchText, handler);
|
||||
}
|
||||
});
|
||||
|
||||
mBrowserToolbar.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
@Override
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if (isHomePagerVisible()) {
|
||||
mHomePager.onToolbarFocusChange(hasFocus);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mBrowserToolbar.setOnStartEditingListener(new BrowserToolbar.OnStartEditingListener() {
|
||||
public void onStartEditing() {
|
||||
// Temporarily disable doorhanger notifications.
|
||||
mDoorHangerPopup.disable();
|
||||
}
|
||||
});
|
||||
|
||||
mBrowserToolbar.setOnStopEditingListener(new BrowserToolbar.OnStopEditingListener() {
|
||||
public void onStopEditing() {
|
||||
selectTargetTabForEditingMode();
|
||||
|
||||
// Since the underlying LayerView is set visible in hideHomePager, we would
|
||||
// ordinarily want to call it first. However, hideBrowserSearch changes the
|
||||
// visibility of the HomePager and hideHomePager will take no action if the
|
||||
// HomePager is hidden, so we want to call hideBrowserSearch to restore the
|
||||
// HomePager visibility first.
|
||||
hideBrowserSearch();
|
||||
hideHomePager();
|
||||
|
||||
// Re-enable doorhanger notifications. They may trigger on the selected tab above.
|
||||
mDoorHangerPopup.enable();
|
||||
}
|
||||
});
|
||||
|
||||
// Intercept key events for gamepad shortcuts
|
||||
mBrowserToolbar.setOnKeyListener(this);
|
||||
setBrowserToolbarListeners();
|
||||
|
||||
mFindInPageBar = (FindInPageBar) findViewById(R.id.find_in_page);
|
||||
mMediaCastingBar = (MediaCastingBar) findViewById(R.id.media_casting);
|
||||
@@ -639,6 +581,68 @@ abstract public class BrowserApp extends GeckoApp
|
||||
registerEventListener("Prompt:ShowTop");
|
||||
}
|
||||
|
||||
private void setBrowserToolbarListeners() {
|
||||
mBrowserToolbar.setOnActivateListener(new BrowserToolbar.OnActivateListener() {
|
||||
public void onActivate() {
|
||||
enterEditingMode();
|
||||
}
|
||||
});
|
||||
|
||||
mBrowserToolbar.setOnCommitListener(new BrowserToolbar.OnCommitListener() {
|
||||
public void onCommit() {
|
||||
commitEditingMode();
|
||||
}
|
||||
});
|
||||
|
||||
mBrowserToolbar.setOnDismissListener(new BrowserToolbar.OnDismissListener() {
|
||||
public void onDismiss() {
|
||||
mBrowserToolbar.cancelEdit();
|
||||
}
|
||||
});
|
||||
|
||||
mBrowserToolbar.setOnFilterListener(new BrowserToolbar.OnFilterListener() {
|
||||
public void onFilter(String searchText, AutocompleteHandler handler) {
|
||||
filterEditingMode(searchText, handler);
|
||||
}
|
||||
});
|
||||
|
||||
mBrowserToolbar.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
@Override
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if (isHomePagerVisible()) {
|
||||
mHomePager.onToolbarFocusChange(hasFocus);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mBrowserToolbar.setOnStartEditingListener(new BrowserToolbar.OnStartEditingListener() {
|
||||
public void onStartEditing() {
|
||||
// Temporarily disable doorhanger notifications.
|
||||
mDoorHangerPopup.disable();
|
||||
}
|
||||
});
|
||||
|
||||
mBrowserToolbar.setOnStopEditingListener(new BrowserToolbar.OnStopEditingListener() {
|
||||
public void onStopEditing() {
|
||||
selectTargetTabForEditingMode();
|
||||
|
||||
// Since the underlying LayerView is set visible in hideHomePager, we would
|
||||
// ordinarily want to call it first. However, hideBrowserSearch changes the
|
||||
// visibility of the HomePager and hideHomePager will take no action if the
|
||||
// HomePager is hidden, so we want to call hideBrowserSearch to restore the
|
||||
// HomePager visibility first.
|
||||
hideBrowserSearch();
|
||||
hideHomePager();
|
||||
|
||||
// Re-enable doorhanger notifications. They may trigger on the selected tab above.
|
||||
mDoorHangerPopup.enable();
|
||||
}
|
||||
});
|
||||
|
||||
// Intercept key events for gamepad shortcuts
|
||||
mBrowserToolbar.setOnKeyListener(this);
|
||||
}
|
||||
|
||||
private void showBookmarkDialog() {
|
||||
final Tab tab = Tabs.getInstance().getSelectedTab();
|
||||
final Prompt ps = new Prompt(this, new Prompt.PromptCallback() {
|
||||
|
||||
@@ -8,16 +8,12 @@ package org.mozilla.gecko;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@@ -110,7 +106,6 @@ import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.webkit.MimeTypeMap;
|
||||
import android.widget.AbsoluteLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class GeckoAppShell
|
||||
{
|
||||
|
||||
@@ -23,13 +23,13 @@ import android.view.animation.Animation;
|
||||
import android.widget.ImageView;
|
||||
import android.view.Display;
|
||||
|
||||
import java.net.URL;
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
|
||||
public class WebappImpl extends GeckoApp {
|
||||
private static final String LOGTAG = "GeckoWebappImpl";
|
||||
|
||||
private URL mOrigin;
|
||||
private URI mOrigin;
|
||||
private TextView mTitlebarText = null;
|
||||
private View mTitlebar = null;
|
||||
|
||||
@@ -69,8 +69,8 @@ public class WebappImpl extends GeckoApp {
|
||||
// Try to use the origin stored in the WebappAllocator first
|
||||
String origin = WebappAllocator.getInstance(this).getAppForIndex(getIndex());
|
||||
try {
|
||||
mOrigin = new URL(origin);
|
||||
} catch (java.net.MalformedURLException ex) {
|
||||
mOrigin = new URI(origin);
|
||||
} catch (java.net.URISyntaxException ex) {
|
||||
// If we can't parse the this is an app protocol, just settle for not having an origin
|
||||
if (!origin.startsWith("app://")) {
|
||||
return;
|
||||
@@ -79,8 +79,8 @@ public class WebappImpl extends GeckoApp {
|
||||
// If that failed fall back to the origin stored in the shortcut
|
||||
Log.i(LOGTAG, "Webapp is not registered with allocator");
|
||||
try {
|
||||
mOrigin = new URL(getIntent().getData().toString());
|
||||
} catch (java.net.MalformedURLException ex2) {
|
||||
mOrigin = new URI(getIntent().getData().toString());
|
||||
} catch (java.net.URISyntaxException ex2) {
|
||||
Log.e(LOGTAG, "Unable to parse intent url: ", ex);
|
||||
}
|
||||
}
|
||||
@@ -164,11 +164,11 @@ public class WebappImpl extends GeckoApp {
|
||||
case LOCATION_CHANGE:
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
final String urlString = tab.getURL();
|
||||
final URL url;
|
||||
final URI uri;
|
||||
|
||||
try {
|
||||
url = new URL(urlString);
|
||||
} catch (java.net.MalformedURLException ex) {
|
||||
uri = new URI(urlString);
|
||||
} catch (java.net.URISyntaxException ex) {
|
||||
mTitlebarText.setText(urlString);
|
||||
|
||||
// If we can't parse the url, and its an app protocol hide
|
||||
@@ -182,10 +182,10 @@ public class WebappImpl extends GeckoApp {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mOrigin != null && mOrigin.getHost().equals(url.getHost())) {
|
||||
if (mOrigin != null && mOrigin.getHost().equals(uri.getHost())) {
|
||||
mTitlebar.setVisibility(View.GONE);
|
||||
} else {
|
||||
mTitlebarText.setText(url.getProtocol() + "://" + url.getHost());
|
||||
mTitlebarText.setText(uri.getScheme() + "://" + uri.getHost());
|
||||
mTitlebar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,32 @@
|
||||
|
||||
package org.mozilla.gecko.background.nativecode;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import android.util.Log;
|
||||
|
||||
@RobocopTarget
|
||||
public class NativeCrypto {
|
||||
static {
|
||||
System.loadLibrary("mozglue");
|
||||
try {
|
||||
System.loadLibrary("mozglue");
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
Log.wtf("NativeCrypto", "Couldn't load mozglue. Trying /data/app-lib path.");
|
||||
try {
|
||||
System.load("/data/app-lib/" + AppConstants.ANDROID_PACKAGE_NAME + "/libmozglue.so");
|
||||
} catch (Throwable ee) {
|
||||
try {
|
||||
Log.wtf("NativeCrypto", "Couldn't load mozglue: " + ee + ". Trying /data/data path.");
|
||||
System.load("/data/data/" + AppConstants.ANDROID_PACKAGE_NAME + "/lib/libmozglue.so");
|
||||
} catch (UnsatisfiedLinkError eee) {
|
||||
Log.wtf("NativeCrypto", "Failed every attempt to load mozglue. Giving up.");
|
||||
throw new RuntimeException("Unable to load mozglue", eee);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,19 +4,19 @@
|
||||
|
||||
package org.mozilla.gecko.db;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.mozilla.gecko.GeckoApp;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.NSSBridge;
|
||||
import org.mozilla.gecko.db.DBUtils;
|
||||
import org.mozilla.gecko.db.BrowserContract.Passwords;
|
||||
import org.mozilla.gecko.db.BrowserContract.DeletedPasswords;
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
import org.mozilla.gecko.db.BrowserContract.Passwords;
|
||||
import org.mozilla.gecko.mozglue.GeckoLoader;
|
||||
import org.mozilla.gecko.sqlite.MatrixBlobCursor;
|
||||
import org.mozilla.gecko.sqlite.SQLiteBridge;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Intent;
|
||||
import android.content.UriMatcher;
|
||||
@@ -76,7 +76,10 @@ public class PasswordsProvider extends SQLiteBridgeContentProvider {
|
||||
DELETED_PASSWORDS_PROJECTION_MAP.put(DeletedPasswords.ID, DeletedPasswords.ID);
|
||||
DELETED_PASSWORDS_PROJECTION_MAP.put(DeletedPasswords.GUID, DeletedPasswords.GUID);
|
||||
DELETED_PASSWORDS_PROJECTION_MAP.put(DeletedPasswords.TIME_DELETED, DeletedPasswords.TIME_DELETED);
|
||||
System.loadLibrary("mozglue");
|
||||
|
||||
// We don't use .loadMozGlue because we're in a different process,
|
||||
// and we just want to reuse code rather than use the loader lock etc.
|
||||
GeckoLoader.doLoadLibrary("mozglue");
|
||||
}
|
||||
|
||||
public PasswordsProvider() {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#filter substitution
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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
|
||||
@@ -20,6 +21,9 @@ import java.util.Locale;
|
||||
public final class GeckoLoader {
|
||||
private static final String LOGTAG = "GeckoLoader";
|
||||
|
||||
// This matches AppConstants, but we're built earlier.
|
||||
private static final String ANDROID_PACKAGE_NAME = "@ANDROID_PACKAGE_NAME@";
|
||||
|
||||
private static volatile Intent sIntent;
|
||||
private static File sCacheFile;
|
||||
private static File sGREDir;
|
||||
@@ -259,6 +263,25 @@ public final class GeckoLoader {
|
||||
loadNSSLibsNative(apkName, false);
|
||||
}
|
||||
|
||||
public static void doLoadLibrary(final String lib) {
|
||||
try {
|
||||
System.loadLibrary(lib);
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
Log.wtf(LOGTAG, "Couldn't load " + lib + ". Trying /data/app-lib path.");
|
||||
try {
|
||||
System.load("/data/app-lib/" + ANDROID_PACKAGE_NAME + "/lib" + lib + ".so");
|
||||
} catch (Throwable ee) {
|
||||
try {
|
||||
Log.wtf(LOGTAG, "Couldn't load " + lib + ": " + ee + ". Trying /data/data path.");
|
||||
System.load("/data/data/" + ANDROID_PACKAGE_NAME + "/lib/lib" + lib + ".so");
|
||||
} catch (Throwable eee) {
|
||||
Log.wtf(LOGTAG, "Failed every attempt to load " + lib + ". Giving up.");
|
||||
throw new RuntimeException("Unable to load " + lib, eee);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadMozGlue() {
|
||||
synchronized (sLibLoadingLock) {
|
||||
if (sMozGlueLoaded) {
|
||||
@@ -267,7 +290,7 @@ public final class GeckoLoader {
|
||||
sMozGlueLoaded = true;
|
||||
}
|
||||
|
||||
System.loadLibrary("mozglue");
|
||||
doLoadLibrary("mozglue");
|
||||
}
|
||||
|
||||
public static void loadGeckoLibs(Context context, String apkName) {
|
||||
|
||||
@@ -16,7 +16,8 @@ import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Stack;
|
||||
|
||||
/* Reads out of a multiple level deep jar file such as
|
||||
@@ -47,6 +48,8 @@ public final class GeckoJarReader {
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
Log.e(LOGTAG, "Exception ", ex);
|
||||
} catch (URISyntaxException ex) {
|
||||
Log.e(LOGTAG, "Exception ", ex);
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
@@ -78,6 +81,8 @@ public final class GeckoJarReader {
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
Log.e(LOGTAG, "Exception ", ex);
|
||||
} catch (URISyntaxException ex) {
|
||||
Log.e(LOGTAG, "Exception ", ex);
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
@@ -94,8 +99,8 @@ public final class GeckoJarReader {
|
||||
return text;
|
||||
}
|
||||
|
||||
private static NativeZip getZipFile(String url) throws IOException {
|
||||
URL fileUrl = new URL(url);
|
||||
private static NativeZip getZipFile(String url) throws IOException, URISyntaxException {
|
||||
URI fileUrl = new URI(url);
|
||||
return new NativeZip(fileUrl.getPath());
|
||||
}
|
||||
|
||||
|
||||
@@ -4,43 +4,14 @@
|
||||
|
||||
package org.mozilla.gecko.util;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class JSONUtils {
|
||||
private static final String LOGTAG = "JSONUtils";
|
||||
|
||||
private JSONUtils() {}
|
||||
|
||||
public static URL getURL(String name, JSONObject json) {
|
||||
String url = json.optString(name, null);
|
||||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new URL(url);
|
||||
} catch (MalformedURLException e) {
|
||||
Log.e(LOGTAG, "", new IllegalStateException(name + "=" + url, e));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void putURL(String name, URL url, JSONObject json) {
|
||||
String urlString = url.toString();
|
||||
try {
|
||||
json.put(name, urlString);
|
||||
} catch (JSONException e) {
|
||||
throw new IllegalArgumentException(name + "=" + urlString, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static UUID getUUID(String name, JSONObject json) {
|
||||
String uuid = json.optString(name, null);
|
||||
return (uuid != null) ? UUID.fromString(uuid) : null;
|
||||
|
||||
@@ -7,8 +7,6 @@ package org.mozilla.gecko.webapp;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
@@ -7,8 +7,7 @@ package org.mozilla.gecko.webapp;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URI;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@@ -19,17 +18,11 @@ import org.mozilla.gecko.GeckoThread;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Tab;
|
||||
import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.webapp.ApkResources;
|
||||
import org.mozilla.gecko.webapp.InstallHelper;
|
||||
import org.mozilla.gecko.webapp.InstallHelper.InstallCallback;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.net.Uri;
|
||||
@@ -45,7 +38,7 @@ import android.widget.TextView;
|
||||
public class WebappImpl extends GeckoApp implements InstallCallback {
|
||||
private static final String LOGTAG = "GeckoWebappImpl";
|
||||
|
||||
private URL mOrigin;
|
||||
private URI mOrigin;
|
||||
private TextView mTitlebarText = null;
|
||||
private View mTitlebar = null;
|
||||
|
||||
@@ -272,11 +265,11 @@ public class WebappImpl extends GeckoApp implements InstallCallback {
|
||||
return;
|
||||
}
|
||||
|
||||
final URL url;
|
||||
final URI uri;
|
||||
|
||||
try {
|
||||
url = new URL(urlString);
|
||||
} catch (java.net.MalformedURLException ex) {
|
||||
uri = new URI(urlString);
|
||||
} catch (java.net.URISyntaxException ex) {
|
||||
mTitlebarText.setText(urlString);
|
||||
|
||||
// If we can't parse the url, and its an app protocol hide
|
||||
@@ -290,10 +283,10 @@ public class WebappImpl extends GeckoApp implements InstallCallback {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mOrigin != null && mOrigin.getHost().equals(url.getHost())) {
|
||||
if (mOrigin != null && mOrigin.getHost().equals(uri.getHost())) {
|
||||
mTitlebar.setVisibility(View.GONE);
|
||||
} else {
|
||||
mTitlebarText.setText(url.getProtocol() + "://" + url.getHost());
|
||||
mTitlebarText.setText(uri.getScheme() + "://" + uri.getHost());
|
||||
mTitlebar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
@@ -350,8 +343,8 @@ public class WebappImpl extends GeckoApp implements InstallCallback {
|
||||
|
||||
private void setOrigin(String origin) {
|
||||
try {
|
||||
mOrigin = new URL(origin);
|
||||
} catch (java.net.MalformedURLException ex) {
|
||||
mOrigin = new URI(origin);
|
||||
} catch (java.net.URISyntaxException ex) {
|
||||
// If this isn't an app: URL, just settle for not having an origin.
|
||||
if (!origin.startsWith("app://")) {
|
||||
return;
|
||||
@@ -363,8 +356,8 @@ public class WebappImpl extends GeckoApp implements InstallCallback {
|
||||
Uri data = getIntent().getData();
|
||||
if (data != null) {
|
||||
try {
|
||||
mOrigin = new URL(data.toString());
|
||||
} catch (java.net.MalformedURLException ex2) {
|
||||
mOrigin = new URI(data.toString());
|
||||
} catch (java.net.URISyntaxException ex2) {
|
||||
Log.e(LOGTAG, "Unable to parse intent URL: ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,6 +238,7 @@ class AndroidEclipseBackend(CommonBackend):
|
||||
defines['IDE_PROJECT_FILTERED_RESOURCES'] = pretty_print(filteredResources).strip()
|
||||
else:
|
||||
defines['IDE_PROJECT_FILTERED_RESOURCES'] = ''
|
||||
defines['ANDROID_TARGET_SDK'] = self.environment.substs['ANDROID_TARGET_SDK']
|
||||
|
||||
copier = FileCopier()
|
||||
finder = FileFinder(template_directory)
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
# project structure.
|
||||
|
||||
# Project target.
|
||||
target=android-16
|
||||
target=android-@ANDROID_TARGET_SDK@
|
||||
@IDE_PROJECT_LIBRARY_SETTING@
|
||||
@IDE_PROJECT_LIBRARY_REFERENCES@
|
||||
|
||||
@@ -29,6 +29,13 @@ test_data_path = mozpath.join(test_data_path, 'data')
|
||||
|
||||
|
||||
CONFIGS = DefaultOnReadDict({
|
||||
'android_eclipse': {
|
||||
'defines': [],
|
||||
'non_global_defines': [],
|
||||
'substs': [
|
||||
('ANDROID_TARGET_SDK', '16'),
|
||||
],
|
||||
},
|
||||
'stub0': {
|
||||
'defines': [
|
||||
('MOZ_TRUE_1', '1'),
|
||||
|
||||
@@ -179,8 +179,8 @@ function summarizeObject(obj) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
let worker = null;
|
||||
let Scheduler = {
|
||||
|
||||
/**
|
||||
* |true| once we have sent at least one message to the worker.
|
||||
* This field is unaffected by resetting the worker.
|
||||
@@ -237,6 +237,25 @@ let Scheduler = {
|
||||
*/
|
||||
resetTimer: null,
|
||||
|
||||
/**
|
||||
* The worker to which to send requests.
|
||||
*
|
||||
* If the worker has never been created or has been reset, this is a
|
||||
* fresh worker, initialized with osfile_async_worker.js.
|
||||
*
|
||||
* @type {PromiseWorker}
|
||||
*/
|
||||
get worker() {
|
||||
if (!this._worker) {
|
||||
// Either the worker has never been created or it has been reset
|
||||
this._worker = new PromiseWorker(
|
||||
"resource://gre/modules/osfile/osfile_async_worker.js", LOG);
|
||||
}
|
||||
return this._worker;
|
||||
},
|
||||
|
||||
_worker: null,
|
||||
|
||||
/**
|
||||
* Prepare to kill the OS.File worker after a few seconds.
|
||||
*/
|
||||
@@ -273,10 +292,14 @@ let Scheduler = {
|
||||
|
||||
yield this.queue;
|
||||
|
||||
if (!this.launched || this.shutdown || !worker) {
|
||||
// Enter critical section: no yield in this block
|
||||
// (we want to make sure that we remain the only
|
||||
// request in the queue).
|
||||
|
||||
if (!this.launched || this.shutdown || !this._worker) {
|
||||
// Nothing to kill
|
||||
this.shutdown = this.shutdown || shutdown;
|
||||
worker = null;
|
||||
this._worker = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -285,12 +308,15 @@ let Scheduler = {
|
||||
let deferred = Promise.defer();
|
||||
this.queue = deferred.promise;
|
||||
|
||||
|
||||
// Exit critical section
|
||||
|
||||
let message = ["Meta_shutdown", [reset]];
|
||||
|
||||
try {
|
||||
Scheduler.latestReceived = [];
|
||||
Scheduler.latestSent = [Date.now(), ...message];
|
||||
let promise = worker.post(...message);
|
||||
let promise = this._worker.post(...message);
|
||||
|
||||
// Wait for result
|
||||
let resources;
|
||||
@@ -329,7 +355,7 @@ let Scheduler = {
|
||||
|
||||
// Make sure that we do not leave an invalid |worker| around.
|
||||
if (killed || shutdown) {
|
||||
worker = null;
|
||||
this._worker = null;
|
||||
}
|
||||
|
||||
this.shutdown = shutdown;
|
||||
@@ -376,19 +402,14 @@ let Scheduler = {
|
||||
if (this.shutdown) {
|
||||
LOG("OS.File is not available anymore. The following request has been rejected.",
|
||||
method, args);
|
||||
return Promise.reject(new Error("OS.File has been shut down."));
|
||||
}
|
||||
if (!worker) {
|
||||
// Either the worker has never been created or it has been reset
|
||||
worker = new PromiseWorker(
|
||||
"resource://gre/modules/osfile/osfile_async_worker.js", LOG);
|
||||
return Promise.reject(new Error("OS.File has been shut down. Rejecting post to " + method));
|
||||
}
|
||||
let firstLaunch = !this.launched;
|
||||
this.launched = true;
|
||||
|
||||
if (firstLaunch && SharedAll.Config.DEBUG) {
|
||||
// If we have delayed sending SET_DEBUG, do it now.
|
||||
worker.post("SET_DEBUG", [true]);
|
||||
this.worker.post("SET_DEBUG", [true]);
|
||||
Scheduler.Debugging.messagesSent++;
|
||||
}
|
||||
|
||||
@@ -399,7 +420,13 @@ let Scheduler = {
|
||||
options = methodArgs[methodArgs.length - 1];
|
||||
}
|
||||
Scheduler.Debugging.messagesQueued++;
|
||||
return this.push(() => Task.spawn(function*() {
|
||||
return this.push(Task.async(function*() {
|
||||
if (this.shutdown) {
|
||||
LOG("OS.File is not available anymore. The following request has been rejected.",
|
||||
method, args);
|
||||
throw new Error("OS.File has been shut down. Rejecting request to " + method);
|
||||
}
|
||||
|
||||
// Update debugging information. As |args| may be quite
|
||||
// expensive, we only keep a shortened version of it.
|
||||
Scheduler.Debugging.latestReceived = null;
|
||||
@@ -414,7 +441,7 @@ let Scheduler = {
|
||||
let isError = false;
|
||||
try {
|
||||
try {
|
||||
data = yield worker.post(method, ...args);
|
||||
data = yield this.worker.post(method, ...args);
|
||||
} finally {
|
||||
Scheduler.Debugging.messagesReceived++;
|
||||
}
|
||||
@@ -474,7 +501,7 @@ let Scheduler = {
|
||||
options.outExecutionDuration = durationMs;
|
||||
}
|
||||
return data.ok;
|
||||
}));
|
||||
}.bind(this)));
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -483,6 +510,7 @@ let Scheduler = {
|
||||
* This is only useful on first launch.
|
||||
*/
|
||||
_updateTelemetry: function() {
|
||||
let worker = this.worker;
|
||||
let workerTimeStamps = worker.workerTimeStamps;
|
||||
if (!workerTimeStamps) {
|
||||
// If the first call to OS.File results in an uncaught errors,
|
||||
@@ -1482,7 +1510,7 @@ AsyncShutdown.profileBeforeChange.addBlocker(
|
||||
let result = {
|
||||
launched: Scheduler.launched,
|
||||
shutdown: Scheduler.shutdown,
|
||||
worker: !!worker,
|
||||
worker: !!Scheduler._worker,
|
||||
pendingReset: !!Scheduler.resetTimer,
|
||||
latestSent: Scheduler.Debugging.latestSent,
|
||||
latestReceived: Scheduler.Debugging.latestReceived,
|
||||
|
||||
@@ -81,7 +81,7 @@ const EXCEPTION_NAMES = {
|
||||
LOG("Method", method, "succeeded");
|
||||
} catch (ex) {
|
||||
exn = ex;
|
||||
LOG("Error while calling agent method", exn, exn.stack || "");
|
||||
LOG("Error while calling agent method", exn, exn.moduleStack || exn.stack || "");
|
||||
}
|
||||
|
||||
if (start) {
|
||||
|
||||
@@ -156,6 +156,9 @@ this.PlacesUtils = {
|
||||
* @returns true if the node is a Bookmark folder, false otherwise
|
||||
*/
|
||||
nodeIsFolder: function PU_nodeIsFolder(aNode) {
|
||||
if (!(aNode instanceof Ci.nsINavHistoryResultNode)) {
|
||||
throw new Error("Invalid Places node");
|
||||
}
|
||||
return (aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER ||
|
||||
aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT);
|
||||
},
|
||||
@@ -167,6 +170,9 @@ this.PlacesUtils = {
|
||||
* @returns true if the node represents a bookmarked URI, false otherwise
|
||||
*/
|
||||
nodeIsBookmark: function PU_nodeIsBookmark(aNode) {
|
||||
if (!(aNode instanceof Ci.nsINavHistoryResultNode)) {
|
||||
throw new Error("Invalid Places node");
|
||||
}
|
||||
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_URI &&
|
||||
aNode.itemId != -1;
|
||||
},
|
||||
@@ -178,6 +184,9 @@ this.PlacesUtils = {
|
||||
* @returns true if the node is a Bookmark separator, false otherwise
|
||||
*/
|
||||
nodeIsSeparator: function PU_nodeIsSeparator(aNode) {
|
||||
if (!(aNode instanceof Ci.nsINavHistoryResultNode)) {
|
||||
throw new Error("Invalid Places node");
|
||||
}
|
||||
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR;
|
||||
},
|
||||
|
||||
@@ -188,6 +197,9 @@ this.PlacesUtils = {
|
||||
* @returns true if the node is a URL item, false otherwise
|
||||
*/
|
||||
nodeIsURI: function PU_nodeIsURI(aNode) {
|
||||
if (!(aNode instanceof Ci.nsINavHistoryResultNode)) {
|
||||
throw new Error("Invalid Places node");
|
||||
}
|
||||
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_URI;
|
||||
},
|
||||
|
||||
@@ -198,6 +210,9 @@ this.PlacesUtils = {
|
||||
* @returns true if the node is a Query item, false otherwise
|
||||
*/
|
||||
nodeIsQuery: function PU_nodeIsQuery(aNode) {
|
||||
if (!(aNode instanceof Ci.nsINavHistoryResultNode)) {
|
||||
throw new Error("Invalid Places node");
|
||||
}
|
||||
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY;
|
||||
},
|
||||
|
||||
@@ -357,6 +372,9 @@ this.PlacesUtils = {
|
||||
* @returns true if the node is readonly, false otherwise
|
||||
*/
|
||||
nodeIsReadOnly: function PU_nodeIsReadOnly(aNode) {
|
||||
if (!(aNode instanceof Ci.nsINavHistoryResultNode)) {
|
||||
throw new Error("Invalid Places node");
|
||||
}
|
||||
let itemId = aNode.itemId;
|
||||
if (itemId != -1) {
|
||||
return this._readOnly.indexOf(itemId) != -1;
|
||||
@@ -376,6 +394,9 @@ this.PlacesUtils = {
|
||||
* @returns true if the node is a host container, false otherwise
|
||||
*/
|
||||
nodeIsHost: function PU_nodeIsHost(aNode) {
|
||||
if (!(aNode instanceof Ci.nsINavHistoryResultNode)) {
|
||||
throw new Error("Invalid Places node");
|
||||
}
|
||||
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY &&
|
||||
aNode.parent &&
|
||||
asQuery(aNode.parent).queryOptions.resultType ==
|
||||
@@ -389,6 +410,9 @@ this.PlacesUtils = {
|
||||
* @returns true if the node is a day container, false otherwise
|
||||
*/
|
||||
nodeIsDay: function PU_nodeIsDay(aNode) {
|
||||
if (!(aNode instanceof Ci.nsINavHistoryResultNode)) {
|
||||
throw new Error("Invalid Places node");
|
||||
}
|
||||
var resultType;
|
||||
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY &&
|
||||
aNode.parent &&
|
||||
@@ -404,6 +428,9 @@ this.PlacesUtils = {
|
||||
* @returns true if the node is a tag container, false otherwise
|
||||
*/
|
||||
nodeIsTagQuery: function PU_nodeIsTagQuery(aNode) {
|
||||
if (!(aNode instanceof Ci.nsINavHistoryResultNode)) {
|
||||
throw new Error("Invalid Places node");
|
||||
}
|
||||
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY &&
|
||||
asQuery(aNode).queryOptions.resultType ==
|
||||
Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_CONTENTS;
|
||||
@@ -419,6 +446,9 @@ this.PlacesUtils = {
|
||||
Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT,
|
||||
Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY],
|
||||
nodeIsContainer: function PU_nodeIsContainer(aNode) {
|
||||
if (!(aNode instanceof Ci.nsINavHistoryResultNode)) {
|
||||
throw new Error("Invalid Places node");
|
||||
}
|
||||
return this.containerTypes.indexOf(aNode.type) != -1;
|
||||
},
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function run_test() {
|
||||
let nodeIsMethods = [
|
||||
"nodeIsFolder",
|
||||
"nodeIsBookmark",
|
||||
"nodeIsSeparator",
|
||||
"nodeIsURI",
|
||||
"nodeIsQuery",
|
||||
"nodeIsReadOnly",
|
||||
"nodeIsHost",
|
||||
"nodeIsDay",
|
||||
"nodeIsTagQuery",
|
||||
"nodeIsContainer",
|
||||
"nodeIsHistoryContainer",
|
||||
"nodeIsQuery"
|
||||
];
|
||||
for (let methodName of nodeIsMethods) {
|
||||
Assert.throws(() => PlacesUtils[methodName](true), /Invalid Places node/);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@ skip-if = true
|
||||
[test_placeURIs.js]
|
||||
[test_PlacesUtils_asyncGetBookmarkIds.js]
|
||||
[test_PlacesUtils_lazyobservers.js]
|
||||
[test_PlacesUtils_nodeIsXXX_invalidArg.js]
|
||||
[test_placesTxn.js]
|
||||
[test_preventive_maintenance.js]
|
||||
# Bug 676989: test hangs consistently on Android
|
||||
|
||||
@@ -71,7 +71,11 @@ let HighlighterActor = protocol.ActorClass({
|
||||
* XUL node to attach itself.
|
||||
*/
|
||||
_supportsBoxModelHighlighter: function() {
|
||||
return this._tabActor.browser && !!this._tabActor.browser.parentNode;
|
||||
// Note that <browser>s on Fennec also have a XUL parentNode but the box
|
||||
// model highlighter doesn't display correctly on Fennec (bug 993190)
|
||||
return this._tabActor.browser &&
|
||||
!!this._tabActor.browser.parentNode &&
|
||||
Services.appinfo.ID !== "{aa3c5121-dab2-40e2-81ca-7ea25febc110}";
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
|
||||
@@ -24,8 +24,9 @@ let addonManager = null;
|
||||
* about them.
|
||||
*/
|
||||
function mapURIToAddonID(uri, id) {
|
||||
if (Services.appinfo.ID == B2G_ID)
|
||||
if (Services.appinfo.ID == B2G_ID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!addonManager) {
|
||||
addonManager = Cc["@mozilla.org/addons/integration;1"].
|
||||
@@ -4777,6 +4778,31 @@ update(AddonThreadActor.prototype, {
|
||||
// A constant prefix that will be used to form the actor ID by the server.
|
||||
actorPrefix: "addonThread",
|
||||
|
||||
onAttach: function(aRequest) {
|
||||
if (!this.attached) {
|
||||
Services.obs.addObserver(this, "document-element-inserted", false);
|
||||
}
|
||||
return ThreadActor.prototype.onAttach.call(this, aRequest);
|
||||
},
|
||||
|
||||
disconnect: function() {
|
||||
if (this.attached) {
|
||||
Services.obs.removeObserver(this, "document-element-inserted");
|
||||
}
|
||||
return ThreadActor.prototype.disconnect.call(this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a new DOM document element is created. Check if the DOM was
|
||||
* laoded from an add-on and if so make the window a debuggee.
|
||||
*/
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
let id = {};
|
||||
if (mapURIToAddonID(aSubject.documentURIObject, id) && id.value === this.addonID) {
|
||||
this.dbg.addDebuggee(aSubject.defaultView);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Override the eligibility check for scripts and sources to make
|
||||
* sure every script and source with a URL is stored when debugging
|
||||
@@ -4784,12 +4810,14 @@ update(AddonThreadActor.prototype, {
|
||||
*/
|
||||
_allowSource: function(aSourceURL) {
|
||||
// Hide eval scripts
|
||||
if (!aSourceURL)
|
||||
if (!aSourceURL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// XPIProvider.jsm evals some code in every add-on's bootstrap.js. Hide it
|
||||
if (aSourceURL == "resource://gre/modules/addons/XPIProvider.jsm")
|
||||
if (aSourceURL == "resource://gre/modules/addons/XPIProvider.jsm") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
@@ -4836,27 +4864,50 @@ update(AddonThreadActor.prototype, {
|
||||
* @param aGlobal Debugger.Object
|
||||
*/
|
||||
_checkGlobal: function ADA_checkGlobal(aGlobal) {
|
||||
let obj = null;
|
||||
try {
|
||||
obj = aGlobal.unsafeDereference();
|
||||
}
|
||||
catch (e) {
|
||||
// Because of bug 991399 we sometimes get bad objects here. If we can't
|
||||
// dereference them then they won't be useful to us
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// This will fail for non-Sandbox objects, hence the try-catch block.
|
||||
let metadata = Cu.getSandboxMetadata(aGlobal.unsafeDereference());
|
||||
if (metadata)
|
||||
let metadata = Cu.getSandboxMetadata(obj);
|
||||
if (metadata) {
|
||||
return metadata.addonID === this.addonID;
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
if (obj instanceof Ci.nsIDOMWindow) {
|
||||
let id = {};
|
||||
if (mapURIToAddonID(obj.document.documentURIObject, id)) {
|
||||
return id.value === this.addonID;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the global for a __URI__ property and then try to map that to an
|
||||
// add-on
|
||||
let uridescriptor = aGlobal.getOwnPropertyDescriptor("__URI__");
|
||||
if (uridescriptor && "value" in uridescriptor) {
|
||||
if (uridescriptor && "value" in uridescriptor && uridescriptor.value) {
|
||||
let uri;
|
||||
try {
|
||||
let uri = Services.io.newURI(uridescriptor.value, null, null);
|
||||
let id = {};
|
||||
if (mapURIToAddonID(uri, id)) {
|
||||
return id.value === this.addonID;
|
||||
}
|
||||
uri = Services.io.newURI(uridescriptor.value, null, null);
|
||||
}
|
||||
catch (e) {
|
||||
DevToolsUtils.reportException("AddonThreadActor.prototype._checkGlobal", e);
|
||||
DevToolsUtils.reportException("AddonThreadActor.prototype._checkGlobal",
|
||||
new Error("Invalid URI: " + uridescriptor.value));
|
||||
return false;
|
||||
}
|
||||
|
||||
let id = {};
|
||||
if (mapURIToAddonID(uri, id)) {
|
||||
return id.value === this.addonID;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4864,6 +4915,11 @@ update(AddonThreadActor.prototype, {
|
||||
}
|
||||
});
|
||||
|
||||
AddonThreadActor.prototype.requestTypes = Object.create(ThreadActor.prototype.requestTypes);
|
||||
update(AddonThreadActor.prototype.requestTypes, {
|
||||
"attach": AddonThreadActor.prototype.onAttach
|
||||
});
|
||||
|
||||
/**
|
||||
* Manages the sources for a thread. Handles source maps, locations in the
|
||||
* sources, etc for ThreadActors.
|
||||
|
||||
@@ -34,6 +34,7 @@ let ShortcutUtils = {
|
||||
prettifyShortcut: function(aElemKey, aNoCloverLeaf) {
|
||||
let elemString = "";
|
||||
let elemMod = aElemKey.getAttribute("modifiers");
|
||||
let haveCloverLeaf = false;
|
||||
|
||||
if (elemMod.match("accel")) {
|
||||
if (Services.appinfo.OS == "Darwin") {
|
||||
@@ -42,8 +43,7 @@ let ShortcutUtils = {
|
||||
if (aNoCloverLeaf) {
|
||||
elemString += "Cmd-";
|
||||
} else {
|
||||
elemString += PlatformKeys.GetStringFromName("VK_META") +
|
||||
PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
|
||||
haveCloverLeaf = true;
|
||||
}
|
||||
} else {
|
||||
elemString += PlatformKeys.GetStringFromName("VK_CONTROL") +
|
||||
@@ -80,6 +80,11 @@ let ShortcutUtils = {
|
||||
PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
|
||||
}
|
||||
|
||||
if (haveCloverLeaf) {
|
||||
elemString += PlatformKeys.GetStringFromName("VK_META") +
|
||||
PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
|
||||
}
|
||||
|
||||
let key;
|
||||
let keyCode = aElemKey.getAttribute("keycode");
|
||||
if (keyCode) {
|
||||
|
||||
@@ -18,6 +18,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel",
|
||||
"resource://gre/modules/UpdateChannel.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "OS",
|
||||
"resource://gre/modules/osfile.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
|
||||
const TOOLKIT_ID = "toolkit@mozilla.org"
|
||||
const KEY_PROFILEDIR = "ProfD";
|
||||
@@ -567,8 +571,8 @@ Blocklist.prototype = {
|
||||
this._loadBlocklist();
|
||||
},
|
||||
|
||||
onXMLLoad: function Blocklist_onXMLLoad(aEvent) {
|
||||
var request = aEvent.target;
|
||||
onXMLLoad: Task.async(function* (aEvent) {
|
||||
let request = aEvent.target;
|
||||
try {
|
||||
gCertUtils.checkCert(request.channel);
|
||||
}
|
||||
@@ -576,28 +580,28 @@ Blocklist.prototype = {
|
||||
LOG("Blocklist::onXMLLoad: " + e);
|
||||
return;
|
||||
}
|
||||
var responseXML = request.responseXML;
|
||||
let responseXML = request.responseXML;
|
||||
if (!responseXML || responseXML.documentElement.namespaceURI == XMLURI_PARSE_ERROR ||
|
||||
(request.status != 200 && request.status != 0)) {
|
||||
LOG("Blocklist::onXMLLoad: there was an error during load");
|
||||
return;
|
||||
}
|
||||
var blocklistFile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_BLOCKLIST]);
|
||||
if (blocklistFile.exists())
|
||||
blocklistFile.remove(false);
|
||||
var fos = FileUtils.openSafeFileOutputStream(blocklistFile);
|
||||
fos.write(request.responseText, request.responseText.length);
|
||||
FileUtils.closeSafeFileOutputStream(fos);
|
||||
|
||||
var oldAddonEntries = this._addonEntries;
|
||||
var oldPluginEntries = this._pluginEntries;
|
||||
this._addonEntries = [];
|
||||
this._pluginEntries = [];
|
||||
this._loadBlocklistFromFile(FileUtils.getFile(KEY_PROFILEDIR,
|
||||
[FILE_BLOCKLIST]));
|
||||
|
||||
this._loadBlocklistFromString(request.responseText);
|
||||
this._blocklistUpdated(oldAddonEntries, oldPluginEntries);
|
||||
},
|
||||
|
||||
try {
|
||||
let path = OS.Path.join(OS.Constants.Path.profileDir, FILE_BLOCKLIST);
|
||||
yield OS.File.writeAtomic(path, request.responseText, {tmpPath: path + ".tmp"});
|
||||
} catch (e) {
|
||||
LOG("Blocklist::onXMLLoad: " + e);
|
||||
}
|
||||
}),
|
||||
|
||||
onXMLError: function Blocklist_onXMLError(aEvent) {
|
||||
try {
|
||||
@@ -704,17 +708,46 @@ Blocklist.prototype = {
|
||||
}
|
||||
|
||||
if (!file.exists()) {
|
||||
LOG("Blocklist::_loadBlocklistFromFile: XML File does not exist");
|
||||
LOG("Blocklist::_loadBlocklistFromFile: XML File does not exist " + file.path);
|
||||
return;
|
||||
}
|
||||
|
||||
var fileStream = Components.classes["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Components.interfaces.nsIFileInputStream);
|
||||
fileStream.init(file, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0);
|
||||
let text = "";
|
||||
let fstream = null;
|
||||
let cstream = null;
|
||||
|
||||
try {
|
||||
fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Components.interfaces.nsIFileInputStream);
|
||||
cstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
|
||||
.createInstance(Components.interfaces.nsIConverterInputStream);
|
||||
|
||||
fstream.init(file, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0);
|
||||
cstream.init(fstream, "UTF-8", 0, 0);
|
||||
|
||||
let (str = {}) {
|
||||
let read = 0;
|
||||
|
||||
do {
|
||||
read = cstream.readString(0xffffffff, str); // read as much as we can and put it in str.value
|
||||
text += str.value;
|
||||
} while (read != 0);
|
||||
}
|
||||
} catch (e) {
|
||||
LOG("Blocklist::_loadBlocklistFromFile: Failed to load XML file " + e);
|
||||
} finally {
|
||||
cstream.close();
|
||||
fstream.close();
|
||||
}
|
||||
|
||||
text && this._loadBlocklistFromString(text);
|
||||
},
|
||||
|
||||
_loadBlocklistFromString : function Blocklist_loadBlocklistFromString(text) {
|
||||
try {
|
||||
var parser = Cc["@mozilla.org/xmlextras/domparser;1"].
|
||||
createInstance(Ci.nsIDOMParser);
|
||||
var doc = parser.parseFromStream(fileStream, "UTF-8", file.fileSize, "text/xml");
|
||||
var doc = parser.parseFromString(text, "text/xml");
|
||||
if (doc.documentElement.namespaceURI != XMLURI_BLOCKLIST) {
|
||||
LOG("Blocklist::_loadBlocklistFromFile: aborting due to incorrect " +
|
||||
"XML Namespace.\r\nExpected: " + XMLURI_BLOCKLIST + "\r\n" +
|
||||
@@ -746,7 +779,6 @@ Blocklist.prototype = {
|
||||
LOG("Blocklist::_loadBlocklistFromFile: Error constructing blocklist " + e);
|
||||
return;
|
||||
}
|
||||
fileStream.close();
|
||||
},
|
||||
|
||||
_processItemNodes: function Blocklist_processItemNodes(itemNodes, prefix, handler) {
|
||||
|
||||
Reference in New Issue
Block a user