зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound. a=merge
This commit is contained in:
Коммит
c966517190
|
@ -41,10 +41,9 @@ const ObserverDelegee = Class({
|
||||||
this.delegate = delegate;
|
this.delegate = delegate;
|
||||||
},
|
},
|
||||||
QueryInterface: function(iid) {
|
QueryInterface: function(iid) {
|
||||||
const isObserver = iid.equals(Ci.nsIObserver);
|
if (!iid.equals(Ci.nsIObserver) &&
|
||||||
const isWeakReference = iid.equals(Ci.nsISupportsWeakReference);
|
!iid.equals(Ci.nsISupportsWeakReference) &&
|
||||||
|
!iid.equals(Ci.nsISupports))
|
||||||
if (!isObserver && !isWeakReference)
|
|
||||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -295,6 +295,9 @@ let hides = filter(panelEvents, ({type}) => type === "popuphidden");
|
||||||
let ready = filter(panelEvents, ({type, target}) =>
|
let ready = filter(panelEvents, ({type, target}) =>
|
||||||
getAttachEventType(modelFor(panelFor(target))) === type);
|
getAttachEventType(modelFor(panelFor(target))) === type);
|
||||||
|
|
||||||
|
// Panel event emitted when the contents of the panel has been loaded.
|
||||||
|
let readyToShow = filter(panelEvents, ({type}) => type === "DOMContentLoaded");
|
||||||
|
|
||||||
// Styles should be always added as soon as possible, and doesn't makes them
|
// Styles should be always added as soon as possible, and doesn't makes them
|
||||||
// depends on `contentScriptWhen`
|
// depends on `contentScriptWhen`
|
||||||
let start = filter(panelEvents, ({type}) => type === "document-element-inserted");
|
let start = filter(panelEvents, ({type}) => type === "document-element-inserted");
|
||||||
|
@ -317,6 +320,10 @@ on(ready, "data", ({target}) => {
|
||||||
let window = domPanel.getContentDocument(target).defaultView;
|
let window = domPanel.getContentDocument(target).defaultView;
|
||||||
|
|
||||||
workerFor(panel).attach(window);
|
workerFor(panel).attach(window);
|
||||||
|
});
|
||||||
|
|
||||||
|
on(readyToShow, "data", ({target}) => {
|
||||||
|
let panel = panelFor(target);
|
||||||
|
|
||||||
if (!modelFor(panel).ready) {
|
if (!modelFor(panel).ready) {
|
||||||
modelFor(panel).ready = true;
|
modelFor(panel).ready = true;
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
const { create: makeFrame } = require("sdk/frame/utils");
|
const { create: makeFrame } = require("sdk/frame/utils");
|
||||||
const { window } = require("sdk/addon/window");
|
const { window } = require("sdk/addon/window");
|
||||||
const { Loader } = require('sdk/test/loader');
|
const { Loader } = require('sdk/test/loader');
|
||||||
const loader = Loader(module);
|
|
||||||
const Worker = loader.require("sdk/content/worker").Worker;
|
|
||||||
|
|
||||||
exports.testMembranelessMode = function(assert, done) {
|
exports.testMembranelessMode = function(assert, done) {
|
||||||
|
const loader = Loader(module);
|
||||||
|
const Worker = loader.require("sdk/content/worker").Worker;
|
||||||
|
|
||||||
let url = "data:text/html;charset=utf-8," + encodeURIComponent(
|
let url = "data:text/html;charset=utf-8," + encodeURIComponent(
|
||||||
'<script>' +
|
'<script>' +
|
||||||
|
@ -48,13 +48,20 @@ exports.testMembranelessMode = function(assert, done) {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
worker.port.on("done", function () {
|
|
||||||
|
worker.port.on("done", () => {
|
||||||
|
// cleanup
|
||||||
element.parentNode.removeChild(element);
|
element.parentNode.removeChild(element);
|
||||||
|
worker.destroy();
|
||||||
|
loader.unload();
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
worker.port.on("assert", function (data) {
|
worker.port.on("assert", function (data) {
|
||||||
assert.ok(data.assertion, data.msg);
|
assert.ok(data.assertion, data.msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ exports.testBufferMain = function (assert) {
|
||||||
// invalid encoding for Buffer.toString
|
// invalid encoding for Buffer.toString
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
b.toString('invalid');
|
b.toString('invalid');
|
||||||
}, TypeError, 'invalid encoding for Buffer.toString');
|
}, RangeError, 'invalid encoding for Buffer.toString');
|
||||||
|
|
||||||
// try to toString() a 0-length slice of a buffer, both within and without the
|
// try to toString() a 0-length slice of a buffer, both within and without the
|
||||||
// valid buffer range
|
// valid buffer range
|
||||||
|
@ -248,7 +248,7 @@ exports.testBufferWrite = function (assert) {
|
||||||
|
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
b.write('test string', 0, 5, 'invalid');
|
b.write('test string', 0, 5, 'invalid');
|
||||||
}, TypeError, 'invalid encoding with buffer write throws');
|
}, RangeError, 'invalid encoding with buffer write throws');
|
||||||
// try to write a 0-length string beyond the end of b
|
// try to write a 0-length string beyond the end of b
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
b.write('', 2048);
|
b.write('', 2048);
|
||||||
|
|
|
@ -10,6 +10,7 @@ const {openWindow, closeWindow, openTab, closeTab,
|
||||||
const {when} = require("sdk/dom/events");
|
const {when} = require("sdk/dom/events");
|
||||||
const {Item, Menu, Separator, Contexts, Readers } = require("sdk/context-menu@2");
|
const {Item, Menu, Separator, Contexts, Readers } = require("sdk/context-menu@2");
|
||||||
const prefs = require("sdk/preferences/service");
|
const prefs = require("sdk/preferences/service");
|
||||||
|
const { before, after } = require('sdk/test/utils');
|
||||||
|
|
||||||
const testPageURI = require.resolve("./test-context-menu").replace(".js", ".html");
|
const testPageURI = require.resolve("./test-context-menu").replace(".js", ".html");
|
||||||
|
|
||||||
|
@ -1337,4 +1338,13 @@ if (require("@loader/options").isNative) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
before(exports, (name, assert) => {
|
||||||
|
// Make sure Java doesn't activate
|
||||||
|
prefs.set("plugin.state.java", 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(exports, (name, assert) => {
|
||||||
|
prefs.reset("plugin.state.java");
|
||||||
|
});
|
||||||
|
|
||||||
require("sdk/test").run(module.exports);
|
require("sdk/test").run(module.exports);
|
||||||
|
|
|
@ -86,8 +86,9 @@ exports["test Panel API"] = test(function*(assert) {
|
||||||
yield closeToolbox();
|
yield closeToolbox();
|
||||||
|
|
||||||
assert.equal(panel.readyState, "destroyed", "panel is destroyed");
|
assert.equal(panel.readyState, "destroyed", "panel is destroyed");
|
||||||
});
|
|
||||||
|
|
||||||
|
myTool.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
exports["test Panel communication"] = test(function*(assert) {
|
exports["test Panel communication"] = test(function*(assert) {
|
||||||
const MyPanel = Class({
|
const MyPanel = Class({
|
||||||
|
@ -150,6 +151,7 @@ exports["test Panel communication"] = test(function*(assert) {
|
||||||
yield closeToolbox();
|
yield closeToolbox();
|
||||||
|
|
||||||
assert.equal(panel.readyState, "destroyed", "panel is destroyed");
|
assert.equal(panel.readyState, "destroyed", "panel is destroyed");
|
||||||
|
myTool.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
exports["test communication with debuggee"] = test(function*(assert) {
|
exports["test communication with debuggee"] = test(function*(assert) {
|
||||||
|
@ -233,6 +235,8 @@ exports["test communication with debuggee"] = test(function*(assert) {
|
||||||
yield closeToolbox();
|
yield closeToolbox();
|
||||||
|
|
||||||
assert.equal(panel.readyState, "destroyed", "panel is destroyed");
|
assert.equal(panel.readyState, "destroyed", "panel is destroyed");
|
||||||
|
|
||||||
|
myTool.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -267,6 +271,8 @@ exports["test viewFor panel"] = test(function*(assert) {
|
||||||
assert.equal(frame.contentDocument.URL, url, "is expected iframe");
|
assert.equal(frame.contentDocument.URL, url, "is expected iframe");
|
||||||
|
|
||||||
yield closeToolbox();
|
yield closeToolbox();
|
||||||
|
|
||||||
|
myTool.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -314,6 +320,8 @@ exports["test createView panel"] = test(function*(assert) {
|
||||||
assert.equal(frame.contentDocument.URL, url, "is expected iframe");
|
assert.equal(frame.contentDocument.URL, url, "is expected iframe");
|
||||||
|
|
||||||
yield closeToolbox();
|
yield closeToolbox();
|
||||||
|
|
||||||
|
myTool.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
require("sdk/test").run(exports);
|
require("sdk/test").run(exports);
|
||||||
|
|
|
@ -12,6 +12,7 @@ const { Class } = require("sdk/core/heritage");
|
||||||
const { Cc, Ci, Cu } = require("chrome");
|
const { Cc, Ci, Cu } = require("chrome");
|
||||||
const { notifyObservers } = Cc["@mozilla.org/observer-service;1"].
|
const { notifyObservers } = Cc["@mozilla.org/observer-service;1"].
|
||||||
getService(Ci.nsIObserverService);
|
getService(Ci.nsIObserverService);
|
||||||
|
const { defer } = require("sdk/core/promise");
|
||||||
|
|
||||||
const message = x => ({wrappedJSObject: x});
|
const message = x => ({wrappedJSObject: x});
|
||||||
|
|
||||||
|
@ -120,4 +121,63 @@ exports["test weak observers are GC-ed on unload"] = (assert, end) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
require("sdk/test").run(exports);
|
exports["test weak observer unsubscribe"] = function*(assert) {
|
||||||
|
const loader = Loader(module);
|
||||||
|
const { Observer, observe, subscribe, unsubscribe } = loader.require("sdk/core/observer");
|
||||||
|
const { WeakReference } = loader.require("sdk/core/reference");
|
||||||
|
|
||||||
|
let sawNotification = false;
|
||||||
|
let firstWait = defer();
|
||||||
|
let secondWait = defer();
|
||||||
|
|
||||||
|
const WeakObserver = Class({
|
||||||
|
extends: Observer,
|
||||||
|
implements: [WeakReference],
|
||||||
|
observe: function() {
|
||||||
|
sawNotification = true;
|
||||||
|
firstWait.resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const StrongObserver = Class({
|
||||||
|
extends: Observer,
|
||||||
|
observe: function() {
|
||||||
|
secondWait.resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
observe.define(Observer, (x, ...rest) => x.observe(...rest));
|
||||||
|
|
||||||
|
let weakObserver = new WeakObserver;
|
||||||
|
let strongObserver = new StrongObserver();
|
||||||
|
subscribe(weakObserver, "test-topic");
|
||||||
|
subscribe(strongObserver, "test-wait");
|
||||||
|
|
||||||
|
notifyObservers(null, "test-topic", null);
|
||||||
|
yield firstWait.promise;
|
||||||
|
|
||||||
|
assert.ok(sawNotification, "Should have seen notification before GC");
|
||||||
|
sawNotification = false;
|
||||||
|
|
||||||
|
yield loader.require("sdk/test/memory").gc();
|
||||||
|
|
||||||
|
notifyObservers(null, "test-topic", null);
|
||||||
|
notifyObservers(null, "test-wait", null);
|
||||||
|
yield secondWait.promise;
|
||||||
|
|
||||||
|
assert.ok(sawNotification, "Should have seen notification after GC");
|
||||||
|
sawNotification = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
unsubscribe(weakObserver, "test-topic");
|
||||||
|
unsubscribe(strongObserver, "test-wait");
|
||||||
|
assert.pass("Should not have seen an exception");
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
assert.fail("Should not have seen an exception");
|
||||||
|
}
|
||||||
|
|
||||||
|
loader.unload();
|
||||||
|
};
|
||||||
|
|
||||||
|
require("sdk/test").run(exports);
|
||||||
|
|
|
@ -1297,7 +1297,6 @@ exports["test panel addon global object"] = function*(assert) {
|
||||||
exports["test panel load doesn't show"] = function*(assert) {
|
exports["test panel load doesn't show"] = function*(assert) {
|
||||||
let loader = Loader(module);
|
let loader = Loader(module);
|
||||||
|
|
||||||
let showCount = 0;
|
|
||||||
let panel = loader.require("sdk/panel").Panel({
|
let panel = loader.require("sdk/panel").Panel({
|
||||||
contentScript: "addEventListener('load', function(event) { self.postMessage('load'); });",
|
contentScript: "addEventListener('load', function(event) { self.postMessage('load'); });",
|
||||||
contentScriptWhen: "start",
|
contentScriptWhen: "start",
|
||||||
|
@ -1335,6 +1334,24 @@ exports["test panel load doesn't show"] = function*(assert) {
|
||||||
loader.unload();
|
loader.unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports["test Panel without contentURL and contentScriptWhen=start should show"] = function*(assert) {
|
||||||
|
let loader = Loader(module);
|
||||||
|
|
||||||
|
let panel = loader.require("sdk/panel").Panel({
|
||||||
|
contentScriptWhen: "start",
|
||||||
|
// No contentURL, the bug only shows up when contentURL is not explicitly set.
|
||||||
|
});
|
||||||
|
|
||||||
|
yield new Promise(resolve => {
|
||||||
|
panel.once("show", resolve);
|
||||||
|
panel.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.pass("Received show event");
|
||||||
|
|
||||||
|
loader.unload();
|
||||||
|
}
|
||||||
|
|
||||||
if (packaging.isNative) {
|
if (packaging.isNative) {
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"test skip on jpm": (assert) => assert.pass("skipping this file with jpm")
|
"test skip on jpm": (assert) => assert.pass("skipping this file with jpm")
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="cdaa0a4ac28c781709df8c318ed079e9e475503a">
|
<project name="platform_build" path="build" remote="b2g" revision="cdaa0a4ac28c781709df8c318ed079e9e475503a">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="620aecfde85a8b093247837c55de2708e22be1e1"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -118,7 +118,7 @@
|
||||||
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="9d83b3a8e72c773820ada75e5a2cd128a743cf35"/>
|
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="9d83b3a8e72c773820ada75e5a2cd128a743cf35"/>
|
||||||
<project name="platform/system/extras" path="system/extras" revision="10e78a05252b3de785f88c2d0b9ea8a428009c50"/>
|
<project name="platform/system/extras" path="system/extras" revision="10e78a05252b3de785f88c2d0b9ea8a428009c50"/>
|
||||||
<project name="platform/system/media" path="system/media" revision="7ff72c2ea2496fa50b5e8a915e56e901c3ccd240"/>
|
<project name="platform/system/media" path="system/media" revision="7ff72c2ea2496fa50b5e8a915e56e901c3ccd240"/>
|
||||||
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="3211e72ef1407171b52d8258fb92298cbd3ec651"/>
|
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="85df9b5036010d9aa057c72cdfc7c86fc51f7c10"/>
|
||||||
<project name="platform/system/netd" path="system/netd" revision="3ae56364946d4a5bf5a5f83f12f9a45a30398e33"/>
|
<project name="platform/system/netd" path="system/netd" revision="3ae56364946d4a5bf5a5f83f12f9a45a30398e33"/>
|
||||||
<project name="platform/system/security" path="system/security" revision="ee8068b9e7bfb2770635062fc9c2035be2142bd8"/>
|
<project name="platform/system/security" path="system/security" revision="ee8068b9e7bfb2770635062fc9c2035be2142bd8"/>
|
||||||
<project name="platform/system/vold" path="system/vold" revision="2e43efe1b30d0b98574d293059556aebd2f46454"/>
|
<project name="platform/system/vold" path="system/vold" revision="2e43efe1b30d0b98574d293059556aebd2f46454"/>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="620aecfde85a8b093247837c55de2708e22be1e1"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eb1795a9002eb142ac58c8d68f8f4ba094af07ca"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eb1795a9002eb142ac58c8d68f8f4ba094af07ca"/>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="620aecfde85a8b093247837c55de2708e22be1e1"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
|
||||||
|
@ -120,7 +120,7 @@
|
||||||
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="9d83b3a8e72c773820ada75e5a2cd128a743cf35"/>
|
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="9d83b3a8e72c773820ada75e5a2cd128a743cf35"/>
|
||||||
<project name="platform_system_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/>
|
<project name="platform_system_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/>
|
||||||
<project name="platform/system/extras" path="system/extras" revision="18c1180e848e7ab8691940481f5c1c8d22c37b3e"/>
|
<project name="platform/system/extras" path="system/extras" revision="18c1180e848e7ab8691940481f5c1c8d22c37b3e"/>
|
||||||
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="3211e72ef1407171b52d8258fb92298cbd3ec651"/>
|
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="85df9b5036010d9aa057c72cdfc7c86fc51f7c10"/>
|
||||||
<project name="platform/system/media" path="system/media" revision="d90b836f66bf1d9627886c96f3a2d9c3007fbb80"/>
|
<project name="platform/system/media" path="system/media" revision="d90b836f66bf1d9627886c96f3a2d9c3007fbb80"/>
|
||||||
<project name="platform/system/netd" path="system/netd" revision="56112dd7b811301b718d0643a82fd5cac9522073"/>
|
<project name="platform/system/netd" path="system/netd" revision="56112dd7b811301b718d0643a82fd5cac9522073"/>
|
||||||
<project name="platform/system/security" path="system/security" revision="f48ff68fedbcdc12b570b7699745abb6e7574907"/>
|
<project name="platform/system/security" path="system/security" revision="f48ff68fedbcdc12b570b7699745abb6e7574907"/>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="cdaa0a4ac28c781709df8c318ed079e9e475503a">
|
<project name="platform_build" path="build" remote="b2g" revision="cdaa0a4ac28c781709df8c318ed079e9e475503a">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="620aecfde85a8b093247837c55de2708e22be1e1"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -118,7 +118,7 @@
|
||||||
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="9d83b3a8e72c773820ada75e5a2cd128a743cf35"/>
|
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="9d83b3a8e72c773820ada75e5a2cd128a743cf35"/>
|
||||||
<project name="platform/system/extras" path="system/extras" revision="5356165f67f4a81c2ef28671c13697f1657590df"/>
|
<project name="platform/system/extras" path="system/extras" revision="5356165f67f4a81c2ef28671c13697f1657590df"/>
|
||||||
<project name="platform/system/media" path="system/media" revision="be0e2fe59a8043fa5200f75697df9220a99abe9d"/>
|
<project name="platform/system/media" path="system/media" revision="be0e2fe59a8043fa5200f75697df9220a99abe9d"/>
|
||||||
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="3211e72ef1407171b52d8258fb92298cbd3ec651"/>
|
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="85df9b5036010d9aa057c72cdfc7c86fc51f7c10"/>
|
||||||
<project name="platform/system/netd" path="system/netd" revision="36704b0da24debcab8090156568ac236315036bb"/>
|
<project name="platform/system/netd" path="system/netd" revision="36704b0da24debcab8090156568ac236315036bb"/>
|
||||||
<project name="platform/system/security" path="system/security" revision="583374f69f531ba68fc3dcbff1f74893d2a96406"/>
|
<project name="platform/system/security" path="system/security" revision="583374f69f531ba68fc3dcbff1f74893d2a96406"/>
|
||||||
<project name="platform/system/vold" path="system/vold" revision="d4455b8cf361f8353e8aebac15ffd64b4aedd2b9"/>
|
<project name="platform/system/vold" path="system/vold" revision="d4455b8cf361f8353e8aebac15ffd64b4aedd2b9"/>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="620aecfde85a8b093247837c55de2708e22be1e1"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eb1795a9002eb142ac58c8d68f8f4ba094af07ca"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eb1795a9002eb142ac58c8d68f8f4ba094af07ca"/>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="cdaa0a4ac28c781709df8c318ed079e9e475503a">
|
<project name="platform_build" path="build" remote="b2g" revision="cdaa0a4ac28c781709df8c318ed079e9e475503a">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="620aecfde85a8b093247837c55de2708e22be1e1"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -111,7 +111,7 @@
|
||||||
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
|
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
|
||||||
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="9d83b3a8e72c773820ada75e5a2cd128a743cf35"/>
|
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="9d83b3a8e72c773820ada75e5a2cd128a743cf35"/>
|
||||||
<project name="platform/system/extras" path="system/extras" revision="576f57b6510de59c08568b53c0fb60588be8689e"/>
|
<project name="platform/system/extras" path="system/extras" revision="576f57b6510de59c08568b53c0fb60588be8689e"/>
|
||||||
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="3211e72ef1407171b52d8258fb92298cbd3ec651"/>
|
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="85df9b5036010d9aa057c72cdfc7c86fc51f7c10"/>
|
||||||
<project name="platform/system/netd" path="system/netd" revision="a6531f7befb49b1c81bc0de7e51c5482b308e1c5"/>
|
<project name="platform/system/netd" path="system/netd" revision="a6531f7befb49b1c81bc0de7e51c5482b308e1c5"/>
|
||||||
<project name="platform/system/security" path="system/security" revision="ee8068b9e7bfb2770635062fc9c2035be2142bd8"/>
|
<project name="platform/system/security" path="system/security" revision="ee8068b9e7bfb2770635062fc9c2035be2142bd8"/>
|
||||||
<project name="platform/system/vold" path="system/vold" revision="42fa2a0f14f965970a4b629a176bbd2666edf017"/>
|
<project name="platform/system/vold" path="system/vold" revision="42fa2a0f14f965970a4b629a176bbd2666edf017"/>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
</project>
|
</project>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="620aecfde85a8b093247837c55de2708e22be1e1"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"git": {
|
"git": {
|
||||||
"git_revision": "82f286f10a41aab84a0796c89fbefe67b179994b",
|
"git_revision": "620aecfde85a8b093247837c55de2708e22be1e1",
|
||||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||||
"branch": ""
|
"branch": ""
|
||||||
},
|
},
|
||||||
"revision": "066f0e84321a010700467d1814ee0048dca7e5e1",
|
"revision": "42da22fe3d59646d07bad417e194969dd2cc891d",
|
||||||
"repo_path": "integration/gaia-central"
|
"repo_path": "integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="620aecfde85a8b093247837c55de2708e22be1e1"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
|
||||||
|
@ -120,7 +120,7 @@
|
||||||
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="9d83b3a8e72c773820ada75e5a2cd128a743cf35"/>
|
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="9d83b3a8e72c773820ada75e5a2cd128a743cf35"/>
|
||||||
<project name="platform_system_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/>
|
<project name="platform_system_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/>
|
||||||
<project name="platform/system/extras" path="system/extras" revision="18c1180e848e7ab8691940481f5c1c8d22c37b3e"/>
|
<project name="platform/system/extras" path="system/extras" revision="18c1180e848e7ab8691940481f5c1c8d22c37b3e"/>
|
||||||
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="3211e72ef1407171b52d8258fb92298cbd3ec651"/>
|
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="85df9b5036010d9aa057c72cdfc7c86fc51f7c10"/>
|
||||||
<project name="platform/system/media" path="system/media" revision="d90b836f66bf1d9627886c96f3a2d9c3007fbb80"/>
|
<project name="platform/system/media" path="system/media" revision="d90b836f66bf1d9627886c96f3a2d9c3007fbb80"/>
|
||||||
<project name="platform/system/netd" path="system/netd" revision="56112dd7b811301b718d0643a82fd5cac9522073"/>
|
<project name="platform/system/netd" path="system/netd" revision="56112dd7b811301b718d0643a82fd5cac9522073"/>
|
||||||
<project name="platform/system/security" path="system/security" revision="f48ff68fedbcdc12b570b7699745abb6e7574907"/>
|
<project name="platform/system/security" path="system/security" revision="f48ff68fedbcdc12b570b7699745abb6e7574907"/>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="7f2ee9f4cb926684883fc2a2e407045fd9db2199">
|
<project name="platform_build" path="build" remote="b2g" revision="7f2ee9f4cb926684883fc2a2e407045fd9db2199">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="620aecfde85a8b093247837c55de2708e22be1e1"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -128,7 +128,7 @@
|
||||||
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="6e18b61ee446bdd9880c07ae84197a087490c2e5"/>
|
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="6e18b61ee446bdd9880c07ae84197a087490c2e5"/>
|
||||||
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="9d83b3a8e72c773820ada75e5a2cd128a743cf35"/>
|
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="9d83b3a8e72c773820ada75e5a2cd128a743cf35"/>
|
||||||
<project name="platform/system/extras" path="system/extras" revision="18f7c51415917eb0e21b30f220db7bd0be4130a7"/>
|
<project name="platform/system/extras" path="system/extras" revision="18f7c51415917eb0e21b30f220db7bd0be4130a7"/>
|
||||||
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="3211e72ef1407171b52d8258fb92298cbd3ec651"/>
|
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="85df9b5036010d9aa057c72cdfc7c86fc51f7c10"/>
|
||||||
<project name="platform/system/media" path="system/media" revision="adf8fbacf7395858884690df5e3ce46bc75fa683"/>
|
<project name="platform/system/media" path="system/media" revision="adf8fbacf7395858884690df5e3ce46bc75fa683"/>
|
||||||
<project name="platform/system/netd" path="system/netd" revision="655392625db084a7122d65a15acf74db7f1da7f7"/>
|
<project name="platform/system/netd" path="system/netd" revision="655392625db084a7122d65a15acf74db7f1da7f7"/>
|
||||||
<project name="platform/system/security" path="system/security" revision="e6b3fdd892ad994ec3fd0b8959d630e31881801b"/>
|
<project name="platform/system/security" path="system/security" revision="e6b3fdd892ad994ec3fd0b8959d630e31881801b"/>
|
||||||
|
|
|
@ -101,7 +101,7 @@
|
||||||
<command id="Tools:WebIDE" oncommand="gDevToolsBrowser.openWebIDE();" disabled="true" hidden="true"/>
|
<command id="Tools:WebIDE" oncommand="gDevToolsBrowser.openWebIDE();" disabled="true" hidden="true"/>
|
||||||
<command id="Tools:BrowserToolbox" oncommand="BrowserToolboxProcess.init();" disabled="true" hidden="true"/>
|
<command id="Tools:BrowserToolbox" oncommand="BrowserToolboxProcess.init();" disabled="true" hidden="true"/>
|
||||||
<command id="Tools:BrowserContentToolbox" oncommand="gDevToolsBrowser.openContentProcessToolbox();" disabled="true" hidden="true"/>
|
<command id="Tools:BrowserContentToolbox" oncommand="gDevToolsBrowser.openContentProcessToolbox();" disabled="true" hidden="true"/>
|
||||||
<command id="Tools:BrowserConsole" oncommand="HUDService.toggleBrowserConsole();"/>
|
<command id="Tools:BrowserConsole" oncommand="HUDService.openBrowserConsoleOrFocus();"/>
|
||||||
<command id="Tools:Scratchpad" oncommand="Scratchpad.openScratchpad();"/>
|
<command id="Tools:Scratchpad" oncommand="Scratchpad.openScratchpad();"/>
|
||||||
<command id="Tools:ResponsiveUI" oncommand="ResponsiveUI.toggle();"/>
|
<command id="Tools:ResponsiveUI" oncommand="ResponsiveUI.toggle();"/>
|
||||||
<command id="Tools:Eyedropper" oncommand="openEyedropper();"/>
|
<command id="Tools:Eyedropper" oncommand="openEyedropper();"/>
|
||||||
|
|
|
@ -5480,30 +5480,30 @@
|
||||||
var event = document.createEvent("Events");
|
var event = document.createEvent("Events");
|
||||||
event.initEvent("select", true, true);
|
event.initEvent("select", true, true);
|
||||||
this.dispatchEvent(event);
|
this.dispatchEvent(event);
|
||||||
|
|
||||||
|
this._selectedIndex = val;
|
||||||
|
|
||||||
|
switchPromise.then(() => {
|
||||||
|
// If we cannot find the tabpanel that we were trying to switch to, then
|
||||||
|
// it must have been removed before our Promise could be resolved. In
|
||||||
|
// that case, we just cancel the tab switch.
|
||||||
|
var updatedTabIndex = Array.indexOf(this.childNodes, newPanel);
|
||||||
|
if (updatedTabIndex == -1) {
|
||||||
|
gBrowser._cancelTabSwitch(toTab);
|
||||||
|
} else {
|
||||||
|
this.setAttribute("selectedIndex", updatedTabIndex);
|
||||||
|
gBrowser._finalizeTabSwitch(toTab, fromTab);
|
||||||
|
}
|
||||||
|
}, () => {
|
||||||
|
// If the promise rejected, that means we don't want to actually
|
||||||
|
// flip the deck, so we cancel the tab switch.
|
||||||
|
// We need to nullcheck the method we're about to call because
|
||||||
|
// the binding might be dead at this point.
|
||||||
|
if (gBrowser._cancelTabSwitch)
|
||||||
|
gBrowser._cancelTabSwitch(toTab);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this._selectedIndex = val;
|
|
||||||
|
|
||||||
switchPromise.then(() => {
|
|
||||||
// If we cannot find the tabpanel that we were trying to switch to, then
|
|
||||||
// it must have been removed before our Promise could be resolved. In
|
|
||||||
// that case, we just cancel the tab switch.
|
|
||||||
var updatedTabIndex = Array.indexOf(this.childNodes, newPanel);
|
|
||||||
if (updatedTabIndex == -1) {
|
|
||||||
gBrowser._cancelTabSwitch(toTab);
|
|
||||||
} else {
|
|
||||||
this.setAttribute("selectedIndex", updatedTabIndex);
|
|
||||||
gBrowser._finalizeTabSwitch(toTab, fromTab);
|
|
||||||
}
|
|
||||||
}, () => {
|
|
||||||
// If the promise rejected, that means we don't want to actually
|
|
||||||
// flip the deck, so we cancel the tab switch.
|
|
||||||
// We need to nullcheck the method we're about to call because
|
|
||||||
// the binding might be dead at this point.
|
|
||||||
if (gBrowser._cancelTabSwitch)
|
|
||||||
gBrowser._cancelTabSwitch(toTab);
|
|
||||||
});
|
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
]]>
|
]]>
|
||||||
</setter>
|
</setter>
|
||||||
|
|
|
@ -429,7 +429,7 @@ skip-if = e10s
|
||||||
skip-if = e10s # Bug 1100664 - test relies on linkedBrowser.docShell
|
skip-if = e10s # Bug 1100664 - test relies on linkedBrowser.docShell
|
||||||
[browser_tabs_owner.js]
|
[browser_tabs_owner.js]
|
||||||
[browser_testOpenNewRemoteTabsFromNonRemoteBrowsers.js]
|
[browser_testOpenNewRemoteTabsFromNonRemoteBrowsers.js]
|
||||||
skip-if = !e10s && os == "linux" # Bug 994541 - Need OMTC enabled by default on Linux, or else we get blocked by an alert dialog when opening e10s window.
|
run-if = e10s
|
||||||
[browser_trackingUI.js]
|
[browser_trackingUI.js]
|
||||||
support-files =
|
support-files =
|
||||||
trackingPage.html
|
trackingPage.html
|
||||||
|
|
|
@ -33,9 +33,13 @@ add_task(function* () {
|
||||||
readerButton.click();
|
readerButton.click();
|
||||||
yield promiseTabLoadEvent(tab);
|
yield promiseTabLoadEvent(tab);
|
||||||
|
|
||||||
ok(gBrowser.selectedBrowser.currentURI.spec.startsWith("about:reader"), "about:reader loaded after clicking reader mode button");
|
let readerUrl = gBrowser.selectedBrowser.currentURI.spec;
|
||||||
|
ok(readerUrl.startsWith("about:reader"), "about:reader loaded after clicking reader mode button");
|
||||||
is_element_visible(readerButton, "Reader mode button is present on about:reader");
|
is_element_visible(readerButton, "Reader mode button is present on about:reader");
|
||||||
|
|
||||||
|
is(gURLBar.value, readerUrl, "gURLBar value is about:reader URL");
|
||||||
|
is(gURLBar.textValue, url.substring("http://".length), "gURLBar is displaying original article URL");
|
||||||
|
|
||||||
readerButton.click();
|
readerButton.click();
|
||||||
yield promiseTabLoadEvent(tab);
|
yield promiseTabLoadEvent(tab);
|
||||||
is(gBrowser.selectedBrowser.currentURI.spec, url, "Original page loaded after clicking active reader mode button");
|
is(gBrowser.selectedBrowser.currentURI.spec, url, "Original page loaded after clicking active reader mode button");
|
||||||
|
|
|
@ -160,6 +160,11 @@
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
let originalUrl = ReaderParent.parseReaderUrl(aValue);
|
||||||
|
if (originalUrl) {
|
||||||
|
returnValue = originalUrl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the actiontype only if the user is not overriding actions.
|
// Set the actiontype only if the user is not overriding actions.
|
||||||
|
|
|
@ -37,12 +37,6 @@ let gSubDialog = {
|
||||||
// Wait for the stylesheets injected during DOMContentLoaded to load before showing the dialog
|
// Wait for the stylesheets injected during DOMContentLoaded to load before showing the dialog
|
||||||
// otherwise there is a flicker of the stylesheet applying.
|
// otherwise there is a flicker of the stylesheet applying.
|
||||||
this._frame.addEventListener("load", this._onLoad.bind(this));
|
this._frame.addEventListener("load", this._onLoad.bind(this));
|
||||||
|
|
||||||
chromeBrowser.addEventListener("unload", function(aEvent) {
|
|
||||||
if (aEvent.target.location.href != "about:blank") {
|
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
}.bind(this), true);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
uninit: function() {
|
uninit: function() {
|
||||||
|
|
|
@ -76,7 +76,7 @@ let gTests = [{
|
||||||
dialog.document.documentElement.cancelDialog();
|
dialog.document.documentElement.cancelDialog();
|
||||||
|
|
||||||
let closingEvent = yield closingPromise;
|
let closingEvent = yield closingPromise;
|
||||||
ise(closingEvent.detail.button, "cancel", "closing event should indicate button was 'cancel'");
|
ise(closingEvent.detail.button, "cancel", "closing event should indicate button was 'accept'");
|
||||||
|
|
||||||
yield deferredClose.promise;
|
yield deferredClose.promise;
|
||||||
ise(rv.acceptCount, 0, "return value should NOT have been updated");
|
ise(rv.acceptCount, 0, "return value should NOT have been updated");
|
||||||
|
@ -118,26 +118,6 @@ let gTests = [{
|
||||||
ise(rv.acceptCount, 0, "return value should NOT have been updated");
|
ise(rv.acceptCount, 0, "return value should NOT have been updated");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
desc: "Check that 'back' navigation will close the dialog",
|
|
||||||
run: function* () {
|
|
||||||
let rv = { acceptCount: 0 };
|
|
||||||
let deferredClose = Promise.defer();
|
|
||||||
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, rv,
|
|
||||||
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
|
|
||||||
let dialog = yield dialogPromise;
|
|
||||||
|
|
||||||
// XXX Without the call to promiseDialogClosing the test causes
|
|
||||||
// intermittent failures in browser_change_app_handler.js.
|
|
||||||
let unusedClosingPromise = promiseDialogClosing(dialog);
|
|
||||||
|
|
||||||
info("cancelling the dialog");
|
|
||||||
content.gSubDialog._frame.goBack();
|
|
||||||
|
|
||||||
yield deferredClose.promise;
|
|
||||||
ise(rv.acceptCount, 0, "return value should NOT have been updated");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
desc: "Hitting escape in the dialog",
|
desc: "Hitting escape in the dialog",
|
||||||
run: function* () {
|
run: function* () {
|
||||||
|
|
|
@ -219,7 +219,7 @@ Tools.shaderEditor = {
|
||||||
tooltip: l10n("ToolboxShaderEditor.tooltip", shaderEditorStrings),
|
tooltip: l10n("ToolboxShaderEditor.tooltip", shaderEditorStrings),
|
||||||
|
|
||||||
isTargetSupported: function(target) {
|
isTargetSupported: function(target) {
|
||||||
return target.hasActor("webgl");
|
return target.hasActor("webgl") && !target.chrome;
|
||||||
},
|
},
|
||||||
|
|
||||||
build: function(iframeWindow, toolbox) {
|
build: function(iframeWindow, toolbox) {
|
||||||
|
|
|
@ -13,6 +13,7 @@ support-files =
|
||||||
doc_automation.html
|
doc_automation.html
|
||||||
doc_bug_1125817.html
|
doc_bug_1125817.html
|
||||||
doc_bug_1130901.html
|
doc_bug_1130901.html
|
||||||
|
doc_bug_1112378.html
|
||||||
440hz_sine.ogg
|
440hz_sine.ogg
|
||||||
head.js
|
head.js
|
||||||
|
|
||||||
|
@ -26,18 +27,19 @@ support-files =
|
||||||
[browser_audionode-actor-connectnode-disconnect.js]
|
[browser_audionode-actor-connectnode-disconnect.js]
|
||||||
[browser_audionode-actor-connectparam.js]
|
[browser_audionode-actor-connectparam.js]
|
||||||
skip-if = true # bug 1092571
|
skip-if = true # bug 1092571
|
||||||
[browser_audionode-actor-add-automation-event.js]
|
# [browser_audionode-actor-add-automation-event.js] bug 1134036
|
||||||
[browser_audionode-actor-get-automation-data-01.js]
|
# [browser_audionode-actor-get-automation-data-01.js] bug 1134036
|
||||||
[browser_audionode-actor-get-automation-data-02.js]
|
# [browser_audionode-actor-get-automation-data-02.js] bug 1134036
|
||||||
[browser_audionode-actor-get-automation-data-03.js]
|
# [browser_audionode-actor-get-automation-data-03.js] bug 1134036
|
||||||
[browser_callwatcher-01.js]
|
[browser_callwatcher-01.js]
|
||||||
|
[browser_callwatcher-02.js]
|
||||||
[browser_webaudio-actor-simple.js]
|
[browser_webaudio-actor-simple.js]
|
||||||
[browser_webaudio-actor-destroy-node.js]
|
[browser_webaudio-actor-destroy-node.js]
|
||||||
[browser_webaudio-actor-connect-param.js]
|
[browser_webaudio-actor-connect-param.js]
|
||||||
[browser_webaudio-actor-automation-event.js]
|
# [browser_webaudio-actor-automation-event.js] bug 1134036
|
||||||
|
|
||||||
[browser_wa_automation-view-01.js]
|
# [browser_wa_automation-view-01.js] bug 1134036
|
||||||
[browser_wa_automation-view-02.js]
|
# [browser_wa_automation-view-02.js] bug 1134036
|
||||||
[browser_wa_controller-01.js]
|
[browser_wa_controller-01.js]
|
||||||
[browser_wa_destroy-node-01.js]
|
[browser_wa_destroy-node-01.js]
|
||||||
[browser_wa_first-run.js]
|
[browser_wa_first-run.js]
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bug 1112378
|
||||||
|
* Tests to ensure that errors called on wrapped functions via call-watcher
|
||||||
|
* correctly looks like the error comes from the content, not from within the devtools.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const BUG_1112378_URL = EXAMPLE_URL + "doc_bug_1112378.html";
|
||||||
|
|
||||||
|
add_task(function*() {
|
||||||
|
let { target, panel } = yield initWebAudioEditor(BUG_1112378_URL);
|
||||||
|
let { panelWin } = panel;
|
||||||
|
let { gFront, $, $$, EVENTS, gAudioNodes } = panelWin;
|
||||||
|
|
||||||
|
loadFrameScripts();
|
||||||
|
|
||||||
|
reload(target);
|
||||||
|
|
||||||
|
yield waitForGraphRendered(panelWin, 2, 0);
|
||||||
|
|
||||||
|
let error = yield evalInDebuggee("throwError()");
|
||||||
|
is(error.lineNumber, 21, "error has correct lineNumber");
|
||||||
|
is(error.columnNumber, 11, "error has correct columnNumber");
|
||||||
|
is(error.name, "TypeError", "error has correct name");
|
||||||
|
is(error.message, "Argument 1 is not valid for any of the 2-argument overloads of AudioNode.connect.", "error has correct message");
|
||||||
|
is(error.stringified, "TypeError: Argument 1 is not valid for any of the 2-argument overloads of AudioNode.connect.", "error is stringified correctly");
|
||||||
|
ise(error.instanceof, true, "error is correctly an instanceof TypeError");
|
||||||
|
is(error.fileName, "http://example.com/browser/browser/devtools/webaudioeditor/test/doc_bug_1112378.html", "error has correct fileName");
|
||||||
|
|
||||||
|
error = yield evalInDebuggee("throwDOMException()");
|
||||||
|
is(error.lineNumber, 37, "exception has correct lineNumber");
|
||||||
|
is(error.columnNumber, 0, "exception has correct columnNumber");
|
||||||
|
is(error.code, 9, "exception has correct code");
|
||||||
|
is(error.result, 2152923145, "exception has correct result");
|
||||||
|
is(error.name, "NotSupportedError", "exception has correct name");
|
||||||
|
is(error.message, "Operation is not supported", "exception has correct message");
|
||||||
|
is(error.stringified, "NotSupportedError: Operation is not supported", "exception is stringified correctly");
|
||||||
|
ise(error.instanceof, true, "exception is correctly an instance of DOMException");
|
||||||
|
is(error.filename, "http://example.com/browser/browser/devtools/webaudioeditor/test/doc_bug_1112378.html", "exception has correct filename");
|
||||||
|
|
||||||
|
yield teardown(target);
|
||||||
|
});
|
|
@ -0,0 +1,57 @@
|
||||||
|
<!-- Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||||
|
<!doctype html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<title>Web Audio Editor test page</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<script type="text/javascript;version=1.8">
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let ctx = new AudioContext();
|
||||||
|
let osc = ctx.createOscillator();
|
||||||
|
|
||||||
|
function throwError () {
|
||||||
|
try {
|
||||||
|
osc.connect({});
|
||||||
|
} catch (e) {
|
||||||
|
return {
|
||||||
|
lineNumber: e.lineNumber,
|
||||||
|
fileName: e.fileName,
|
||||||
|
columnNumber: e.columnNumber,
|
||||||
|
message: e.message,
|
||||||
|
instanceof: e instanceof TypeError,
|
||||||
|
stringified: e.toString(),
|
||||||
|
name: e.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function throwDOMException () {
|
||||||
|
try {
|
||||||
|
osc.frequency.setValueAtTime(0, -1);
|
||||||
|
} catch (e) {
|
||||||
|
return {
|
||||||
|
lineNumber: e.lineNumber,
|
||||||
|
columnNumber: e.columnNumber,
|
||||||
|
filename: e.filename,
|
||||||
|
message: e.message,
|
||||||
|
code: e.code,
|
||||||
|
result: e.result,
|
||||||
|
instanceof: e instanceof DOMException,
|
||||||
|
stringified: e.toString(),
|
||||||
|
name: e.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -16,10 +16,13 @@ let { Promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||||
let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||||
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||||
let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
|
let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
|
||||||
|
let { generateUUID } = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
|
||||||
|
|
||||||
let { WebAudioFront } = devtools.require("devtools/server/actors/webaudio");
|
let { WebAudioFront } = devtools.require("devtools/server/actors/webaudio");
|
||||||
let TargetFactory = devtools.TargetFactory;
|
let TargetFactory = devtools.TargetFactory;
|
||||||
|
let mm = null;
|
||||||
|
|
||||||
|
const FRAME_SCRIPT_UTILS_URL = "chrome://browser/content/devtools/frame-script-utils.js";
|
||||||
const EXAMPLE_URL = "http://example.com/browser/browser/devtools/webaudioeditor/test/";
|
const EXAMPLE_URL = "http://example.com/browser/browser/devtools/webaudioeditor/test/";
|
||||||
const SIMPLE_CONTEXT_URL = EXAMPLE_URL + "doc_simple-context.html";
|
const SIMPLE_CONTEXT_URL = EXAMPLE_URL + "doc_simple-context.html";
|
||||||
const COMPLEX_CONTEXT_URL = EXAMPLE_URL + "doc_complex-context.html";
|
const COMPLEX_CONTEXT_URL = EXAMPLE_URL + "doc_complex-context.html";
|
||||||
|
@ -47,6 +50,15 @@ registerCleanupFunction(() => {
|
||||||
Cu.forceGC();
|
Cu.forceGC();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call manually in tests that use frame script utils after initializing
|
||||||
|
* the web audio editor. Call after init but before navigating to a different page.
|
||||||
|
*/
|
||||||
|
function loadFrameScripts () {
|
||||||
|
mm = gBrowser.selectedBrowser.messageManager;
|
||||||
|
mm.loadFrameScript(FRAME_SCRIPT_UTILS_URL, false);
|
||||||
|
}
|
||||||
|
|
||||||
function addTab(aUrl, aWindow) {
|
function addTab(aUrl, aWindow) {
|
||||||
info("Adding tab: " + aUrl);
|
info("Adding tab: " + aUrl);
|
||||||
|
|
||||||
|
@ -440,6 +452,33 @@ function waitForInspectorRender (panelWin, EVENTS) {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a string `script` and evaluates it directly in the content
|
||||||
|
* in potentially a different process.
|
||||||
|
*/
|
||||||
|
function evalInDebuggee (script) {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
|
||||||
|
if (!mm) {
|
||||||
|
throw new Error("`loadFrameScripts()` must be called when using MessageManager.");
|
||||||
|
}
|
||||||
|
|
||||||
|
let id = generateUUID().toString();
|
||||||
|
mm.sendAsyncMessage("devtools:test:eval", { script: script, id: id });
|
||||||
|
mm.addMessageListener("devtools:test:eval:response", handler);
|
||||||
|
|
||||||
|
function handler ({ data }) {
|
||||||
|
if (id !== data.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mm.removeMessageListener("devtools:test:eval:response", handler);
|
||||||
|
deferred.resolve(data.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of audio node properties to test against expectations of the AudioNode actor
|
* List of audio node properties to test against expectations of the AudioNode actor
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -96,8 +96,10 @@
|
||||||
<tabs>
|
<tabs>
|
||||||
<tab id="properties-tab"
|
<tab id="properties-tab"
|
||||||
label="&webAudioEditorUI.tab.properties2;"/>
|
label="&webAudioEditorUI.tab.properties2;"/>
|
||||||
|
<!-- bug 1134036
|
||||||
<tab id="automation-tab"
|
<tab id="automation-tab"
|
||||||
label="&webAudioEditorUI.tab.automation;"/>
|
label="&webAudioEditorUI.tab.automation;"/>
|
||||||
|
-->
|
||||||
</tabs>
|
</tabs>
|
||||||
<tabpanels flex="1">
|
<tabpanels flex="1">
|
||||||
<!-- Properties Panel -->
|
<!-- Properties Panel -->
|
||||||
|
|
|
@ -251,6 +251,21 @@ HUD_SERVICE.prototype =
|
||||||
return this._browserConsoleDefer.promise;
|
return this._browserConsoleDefer.promise;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens or focuses the Browser Console.
|
||||||
|
*/
|
||||||
|
openBrowserConsoleOrFocus: function HS_openBrowserConsoleOrFocus()
|
||||||
|
{
|
||||||
|
let hud = this.getBrowserConsole();
|
||||||
|
if (hud) {
|
||||||
|
hud.iframeWindow.focus();
|
||||||
|
return promise.resolve(hud);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return this.toggleBrowserConsole();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Browser Console instance, if open.
|
* Get the Browser Console instance, if open.
|
||||||
*
|
*
|
||||||
|
@ -763,7 +778,8 @@ const HUDService = new HUD_SERVICE();
|
||||||
(() => {
|
(() => {
|
||||||
let methods = ["openWebConsole", "openBrowserConsole",
|
let methods = ["openWebConsole", "openBrowserConsole",
|
||||||
"toggleBrowserConsole", "getOpenWebConsole",
|
"toggleBrowserConsole", "getOpenWebConsole",
|
||||||
"getBrowserConsole", "getHudByWindow", "getHudReferenceById"];
|
"getBrowserConsole", "getHudByWindow",
|
||||||
|
"openBrowserConsoleOrFocus", "getHudReferenceById"];
|
||||||
for (let method of methods) {
|
for (let method of methods) {
|
||||||
exports[method] = HUDService[method].bind(HUDService);
|
exports[method] = HUDService[method].bind(HUDService);
|
||||||
}
|
}
|
||||||
|
|
|
@ -377,3 +377,4 @@ skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug timeout)
|
||||||
[browser_webconsole_console_custom_styles.js]
|
[browser_webconsole_console_custom_styles.js]
|
||||||
[browser_webconsole_console_api_stackframe.js]
|
[browser_webconsole_console_api_stackframe.js]
|
||||||
[browser_webconsole_column_numbers.js]
|
[browser_webconsole_column_numbers.js]
|
||||||
|
[browser_console_open_or_focus.js]
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Test that the "browser console" menu item opens or focuses (if already open)
|
||||||
|
// the console window instead of toggling it open/close.
|
||||||
|
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let test = asyncTest(function* () {
|
||||||
|
let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||||
|
.getService(Components.interfaces.nsIWindowMediator);
|
||||||
|
let currWindow, hud, mainWindow;
|
||||||
|
|
||||||
|
mainWindow = Services.wm.getMostRecentWindow(null);
|
||||||
|
|
||||||
|
yield HUDService.openBrowserConsoleOrFocus();
|
||||||
|
|
||||||
|
hud = HUDService.getBrowserConsole();
|
||||||
|
|
||||||
|
console.log("testmessage");
|
||||||
|
yield waitForMessages({
|
||||||
|
webconsole: hud,
|
||||||
|
messages: [{
|
||||||
|
text: "testmessage"
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
|
||||||
|
currWindow = Services.wm.getMostRecentWindow(null);
|
||||||
|
is(currWindow.document.documentURI, devtools.Tools.webConsole.url,
|
||||||
|
"The Browser Console is open and has focus");
|
||||||
|
|
||||||
|
mainWindow.focus();
|
||||||
|
|
||||||
|
yield HUDService.openBrowserConsoleOrFocus();
|
||||||
|
|
||||||
|
currWindow = Services.wm.getMostRecentWindow(null);
|
||||||
|
is(currWindow.document.documentURI, devtools.Tools.webConsole.url,
|
||||||
|
"The Browser Console is open and has focus");
|
||||||
|
|
||||||
|
yield HUDService.toggleBrowserConsole();
|
||||||
|
|
||||||
|
hud = HUDService.getBrowserConsole();
|
||||||
|
ok(!hud, "Browser Console has been closed");
|
||||||
|
});
|
|
@ -23,7 +23,7 @@
|
||||||
fullscreenbutton="true"
|
fullscreenbutton="true"
|
||||||
screenX="4" screenY="4"
|
screenX="4" screenY="4"
|
||||||
width="640" height="480"
|
width="640" height="480"
|
||||||
persist="screenX screenY width height">
|
persist="screenX screenY width height sizemode">
|
||||||
|
|
||||||
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"></script>
|
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"></script>
|
||||||
<script type="application/javascript" src="webide.js"></script>
|
<script type="application/javascript" src="webide.js"></script>
|
||||||
|
|
|
@ -26,8 +26,6 @@ let ReaderParent = {
|
||||||
"Reader:ListStatusRequest",
|
"Reader:ListStatusRequest",
|
||||||
"Reader:RemoveFromList",
|
"Reader:RemoveFromList",
|
||||||
"Reader:Share",
|
"Reader:Share",
|
||||||
"Reader:ShowToast",
|
|
||||||
"Reader:ToolbarVisibility",
|
|
||||||
"Reader:SystemUIVisibility",
|
"Reader:SystemUIVisibility",
|
||||||
"Reader:UpdateReaderButton",
|
"Reader:UpdateReaderButton",
|
||||||
],
|
],
|
||||||
|
@ -70,18 +68,10 @@ let ReaderParent = {
|
||||||
// XXX: To implement.
|
// XXX: To implement.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "Reader:ShowToast":
|
|
||||||
// XXX: To implement.
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "Reader:SystemUIVisibility":
|
case "Reader:SystemUIVisibility":
|
||||||
// XXX: To implement.
|
// XXX: To implement.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "Reader:ToolbarVisibility":
|
|
||||||
// XXX: To implement.
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "Reader:UpdateReaderButton": {
|
case "Reader:UpdateReaderButton": {
|
||||||
let browser = message.target;
|
let browser = message.target;
|
||||||
if (message.data && message.data.isArticle !== undefined) {
|
if (message.data && message.data.isArticle !== undefined) {
|
||||||
|
@ -122,23 +112,37 @@ let ReaderParent = {
|
||||||
|
|
||||||
let win = event.target.ownerDocument.defaultView;
|
let win = event.target.ownerDocument.defaultView;
|
||||||
let url = win.gBrowser.selectedBrowser.currentURI.spec;
|
let url = win.gBrowser.selectedBrowser.currentURI.spec;
|
||||||
|
|
||||||
if (url.startsWith("about:reader")) {
|
if (url.startsWith("about:reader")) {
|
||||||
win.openUILinkIn(this._getOriginalUrl(url), "current");
|
let originalURL = this._getOriginalUrl(url);
|
||||||
|
if (!originalURL) {
|
||||||
|
Cu.reportError("Error finding original URL for about:reader URL: " + url);
|
||||||
|
} else {
|
||||||
|
win.openUILinkIn(originalURL, "current");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
win.openUILinkIn("about:reader?url=" + encodeURIComponent(url), "current");
|
win.openUILinkIn("about:reader?url=" + encodeURIComponent(url), "current");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
parseReaderUrl: function(url) {
|
||||||
|
if (!url.startsWith("about:reader?")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return this._getOriginalUrl(url);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns original URL from an about:reader URL.
|
* Returns original URL from an about:reader URL.
|
||||||
*
|
*
|
||||||
* @param url An about:reader URL.
|
* @param url An about:reader URL.
|
||||||
|
* @return The original URL for the article, or null if we did not find
|
||||||
|
* a properly formatted about:reader URL.
|
||||||
*/
|
*/
|
||||||
_getOriginalUrl: function(url) {
|
_getOriginalUrl: function(url) {
|
||||||
let searchParams = new URLSearchParams(url.split("?")[1]);
|
let searchParams = new URLSearchParams(url.substring("about:reader?".length));
|
||||||
if (!searchParams.has("url")) {
|
if (!searchParams.has("url")) {
|
||||||
Cu.reportError("Error finding original URL for about:reader URL: " + url);
|
return null;
|
||||||
return url;
|
|
||||||
}
|
}
|
||||||
return decodeURIComponent(searchParams.get("url"));
|
return decodeURIComponent(searchParams.get("url"));
|
||||||
},
|
},
|
||||||
|
|
|
@ -174,8 +174,7 @@ browser.jar:
|
||||||
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
||||||
* skin/classic/browser/preferences/in-content/dialog.css (preferences/in-content/dialog.css)
|
* skin/classic/browser/preferences/in-content/dialog.css (preferences/in-content/dialog.css)
|
||||||
skin/classic/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico)
|
skin/classic/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico)
|
||||||
skin/classic/browser/preferences/in-content/icons.png (../shared/incontentprefs/icons.png)
|
skin/classic/browser/preferences/in-content/icons.svg (../shared/incontentprefs/icons.svg)
|
||||||
skin/classic/browser/preferences/in-content/icons@2x.png (../shared/incontentprefs/icons@2x.png)
|
|
||||||
skin/classic/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css)
|
skin/classic/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css)
|
||||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||||
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
||||||
|
|
|
@ -280,8 +280,7 @@ browser.jar:
|
||||||
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
||||||
* skin/classic/browser/preferences/in-content/dialog.css (preferences/in-content/dialog.css)
|
* skin/classic/browser/preferences/in-content/dialog.css (preferences/in-content/dialog.css)
|
||||||
skin/classic/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico)
|
skin/classic/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico)
|
||||||
skin/classic/browser/preferences/in-content/icons.png (../shared/incontentprefs/icons.png)
|
skin/classic/browser/preferences/in-content/icons.svg (../shared/incontentprefs/icons.svg)
|
||||||
skin/classic/browser/preferences/in-content/icons@2x.png (../shared/incontentprefs/icons@2x.png)
|
|
||||||
skin/classic/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css)
|
skin/classic/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css)
|
||||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||||
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
||||||
|
|
Двоичные данные
browser/themes/shared/incontentprefs/icons.png
Двоичные данные
browser/themes/shared/incontentprefs/icons.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 4.6 KiB |
|
@ -0,0 +1,129 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
viewBox="0 0 24 24">
|
||||||
|
<style>
|
||||||
|
use:not(:target) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
use {
|
||||||
|
fill: #fbfbfb;
|
||||||
|
stroke: rgba(0,0,0,0.4);
|
||||||
|
stroke-width: .5px;
|
||||||
|
}
|
||||||
|
use[id$="-native"] {
|
||||||
|
fill: ThreeDHighlight;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<defs style="display: none;">
|
||||||
|
<g id="general-shape">
|
||||||
|
<path
|
||||||
|
d="M18.97,3H5.03C3.914,3,3,3.914,3,5.03v13.94C3,20.086,3.914,21,5.03,21H18.97c1.117,0,2.03-0.914,2.03-2.03
|
||||||
|
V5.03C21,3.914,20.086,3,18.97,3z M5.35,19.326c-0.404,0-0.731-0.327-0.731-0.731c0-0.404,0.327-0.731,0.731-0.731
|
||||||
|
c0.404,0,0.731,0.327,0.731,0.731C6.081,19,5.754,19.326,5.35,19.326z M5.35,6.168c-0.403,0-0.731-0.328-0.731-0.731
|
||||||
|
c0-0.404,0.328-0.731,0.731-0.731c0.403,0,0.731,0.327,0.731,0.731C6.081,5.84,5.753,6.168,5.35,6.168z M15.243,14.035
|
||||||
|
c0,0.229-0.186,0.416-0.414,0.416c-0.229,0-0.415,0.186-0.415,0.414v3.347c0,0.228-0.185,0.384-0.414,0.384l-4.141,0.03
|
||||||
|
c-0.227,0-0.414-0.186-0.414-0.414v-3.347c0-0.228-0.185-0.414-0.414-0.414c-0.227,0-0.414-0.187-0.414-0.416V6.582
|
||||||
|
c0-0.229,0.187-0.414,0.414-0.414h5.798c0.228,0,0.414,0.185,0.414,0.414V14.035z M18.509,19.326c-0.404,0-0.731-0.327-0.731-0.731
|
||||||
|
c0-0.404,0.327-0.731,0.731-0.731c0.404,0,0.731,0.327,0.731,0.731C19.24,19,18.913,19.326,18.509,19.326z M18.509,6.168
|
||||||
|
c-0.404,0-0.731-0.328-0.731-0.731c0-0.404,0.327-0.731,0.731-0.731c0.404,0,0.731,0.327,0.731,0.731
|
||||||
|
C19.24,5.84,18.913,6.168,18.509,6.168z"/>
|
||||||
|
<path
|
||||||
|
d="M12.757,7.824h-1.657c-0.456,0-0.828,0.373-0.828,0.828v8.282c0,0.456,0.373,0.828,0.828,0.828h1.657
|
||||||
|
c0.456,0,0.828-0.373,0.828-0.828V8.652C13.586,8.196,13.213,7.824,12.757,7.824z"/>
|
||||||
|
</g>
|
||||||
|
<g id="search-shape">
|
||||||
|
<path
|
||||||
|
d="M2,10.018c0,4.43,3.585,8.019,8.009,8.019
|
||||||
|
c1.603,0,3.095-0.473,4.348-1.285l4.806,4.81c0.58,0.583,1.523,0.583,2.105,0l0.296-0.297c0.582-0.583,0.582-1.527,0-2.11
|
||||||
|
l-4.808-4.814c0.8-1.247,1.265-2.73,1.265-4.323c0-4.43-3.587-8.018-8.012-8.018C5.585,2,2,5.589,2,10.018z M5.104,10.021
|
||||||
|
c0-2.716,2.196-4.915,4.906-4.915c2.71,0,4.908,2.199,4.908,4.915c0,2.712-2.198,4.911-4.908,4.911
|
||||||
|
C7.3,14.931,5.104,12.732,5.104,10.021z"/>
|
||||||
|
</g>
|
||||||
|
<g id="content-shape">
|
||||||
|
<path
|
||||||
|
d="M16.286,2H5.571C4.388,2,3.429,2.96,3.429,4.143v15.714
|
||||||
|
C3.429,21.04,4.388,22,5.571,22h12.857c1.185,0,2.143-0.96,2.143-2.143V6.286L16.286,2z M18.945,19.223c0,0.22-0.18,0.4-0.4,0.4
|
||||||
|
h-13.2c-0.22,0-0.4-0.18-0.4-0.4v-0.846c0-0.22,0.18-0.4,0.4-0.4h13.2c0.22,0,0.4,0.18,0.4,0.4V19.223z M18.945,15.223
|
||||||
|
c0,0.22-0.18,0.4-0.4,0.4h-13.2c-0.22,0-0.4-0.18-0.4-0.4v-0.846c0-0.22,0.18-0.4,0.4-0.4h13.2c0.22,0,0.4,0.18,0.4,0.4V15.223z
|
||||||
|
M18.945,11.229c0,0.22-0.18,0.4-0.4,0.4h-13.2c-0.22,0-0.4-0.18-0.4-0.4v-0.846c0-0.22,0.18-0.4,0.4-0.4h13.2
|
||||||
|
c0.22,0,0.4,0.18,0.4,0.4V11.229z M14.833,7.707v-4.65l4.65,4.65H14.833z"/>
|
||||||
|
</g>
|
||||||
|
<g id="applications-shape">
|
||||||
|
<path
|
||||||
|
d="M16.673,8.914C16.089,4.122,13.248,1,12,1c-1.25,0-3.986,3.122-4.767,7.914l-3.122,3.131v7.889h2.268
|
||||||
|
l2.978-3.436c0.28,0.29,0.737,1.666,1.065,1.858h3.155c0.331-0.193,0.789-1.569,1.068-1.858l3.123,3.436h2.12v-7.84L16.673,8.914z
|
||||||
|
M12.042,8.735c-0.604,0-1.279,0.06-1.818,0.165c0.478-1.453,1.345-3.117,1.781-3.117c0.435,0,1.301,1.655,1.775,3.1
|
||||||
|
C13.265,8.789,12.615,8.735,12.042,8.735z M12.524,19.145c0.076,0.196,0.119,0.602,0.119,0.86c0,0.66-0.524,1.074-0.687,1.074
|
||||||
|
c-0.163,0-0.615-0.414-0.615-1.074c0-0.257,0.045-0.664,0.119-0.86h-0.754c-0.089,0.345-0.39,1.005-0.39,1.408
|
||||||
|
c0,1.458,1.328,2.447,1.686,2.447c0.359,0,1.686-0.951,1.686-2.407c0-0.404-0.301-1.103-0.388-1.449H12.524z"/>
|
||||||
|
</g>
|
||||||
|
<g id="privacy-shape">
|
||||||
|
<path
|
||||||
|
d="M21.632,9.541c-0.083,1.403,0.246,3.079-1.597,5.498
|
||||||
|
c-1.965,2.578-3.914,2.594-4.284,2.575c-2.249-0.117-2.502-1.875-3.792-1.875c-1.13,0-2.012,1.745-3.711,1.836
|
||||||
|
c-0.37,0.02-2.319,0.042-4.284-2.536c-1.841-2.419-1.514-4.095-1.597-5.498C2.287,8.138,2,6.618,2,6.618s0.887,0.895,2.033,0.973
|
||||||
|
C5.179,7.67,5.394,7.191,7.811,6.501C10.424,5.752,12,8.814,12,8.814s1.776-3.016,4.189-2.313c2.414,0.7,2.515,1.169,3.661,1.091
|
||||||
|
C20.996,7.513,22,6.618,22,6.618S21.713,8.138,21.632,9.541z M8.117,10.129c-1.429-0.314-2.028,0.223-2.642,0.451
|
||||||
|
c-0.534,0.202-1.02,0.264-1.02,0.264s0.083,0.819,1.515,1.521c1.432,0.703,4.37,0.338,4.37,0.338S10.651,10.687,8.117,10.129z
|
||||||
|
M18.525,10.58c-0.612-0.228-1.212-0.765-2.642-0.451c-2.534,0.558-2.223,2.573-2.223,2.573s2.938,0.365,4.37-0.338
|
||||||
|
c1.432-0.702,1.515-1.521,1.515-1.521S19.059,10.782,18.525,10.58z"/>
|
||||||
|
</g>
|
||||||
|
<g id="security-shape">
|
||||||
|
<path
|
||||||
|
d="M18.909,9.783h-0.863V8.086C18.046,4.725,15.339,2,12,2
|
||||||
|
C8.661,2,5.954,4.725,5.954,8.086v1.697H5.091c-0.955,0-1.728,0.779-1.728,1.739v8.738c0,0.961,0.773,1.74,1.728,1.74h13.818
|
||||||
|
c0.954,0,1.728-0.779,1.728-1.74v-8.738C20.637,10.562,19.863,9.783,18.909,9.783z M8.545,8.086c0-1.92,1.547-3.478,3.455-3.478
|
||||||
|
c1.908,0,3.455,1.557,3.455,3.478v1.697h-6.91V8.086z M5.181,16.092l-0.909-1.2v-2.284l2.728,3.483H5.181z M8.818,16.092
|
||||||
|
l-2.773-3.657h1.727l2.864,3.657H8.818z M12,16.092l-2.773-3.657h1.727l2.864,3.657H12z M15.637,16.092l-2.773-3.657h1.727
|
||||||
|
l2.864,3.657H15.637z M19.728,16.092h-0.455l-2.773-3.657h1.727l1.501,1.916V16.092z"/>
|
||||||
|
</g>
|
||||||
|
<g id="sync-shape">
|
||||||
|
<path
|
||||||
|
d="M17.024,3.351 c-0.562,0.331 -1.311,0.879 -1.821,1.698 -0.367,0.592 -0.752,1.288 -1.08,1.914 0.987,0.413 1.862,1.095
|
||||||
|
2.476,2.029 0.614,0.957 0.929,2.122 0.83,3.351 -0.201,1.787 -1.359,3.433 -3.046,4.36 -0.696,-0.774 -1.951,-2.945
|
||||||
|
-1.951,-2.945 -0.007,0.007 -0.004,2.556 -0.871,4.334 -0.573,1.184 -1.24,2.202 -2.305,2.995 1.431,0.51 2.915,0.886
|
||||||
|
4.282,0.909 l 0.162,0.002 c 2.99,0.021 5.844,-0.48 5.844,-0.48 0,0 -1.236,-0.802 -1.808,-1.346 1.86,-1.072 3.111,-2.791
|
||||||
|
3.634,-4.708 0.283,-0.759 0.478,-1.566 0.57,-2.409 C 22.383,9.011 20.33,5.278 17.024,3.351 Z M 6.569,12.302 C 6.526,10.271
|
||||||
|
7.755,8.327 9.644,7.29 c 0.696,0.774 2.32,2.899 2.32,2.899 0,0 -0.064,-5.157 1.657,-7.973 -6.097,-0.668 -9.69,0.443
|
||||||
|
-9.69,0.443 0,0 1.763,0.607 2.333,1.136 C 6.122,3.891 5.984,3.992 5.85,4.096 4.4,5.064 3.368,6.449 2.825,7.994 2.436,8.892
|
||||||
|
2.171,9.863 2.06,10.887 1.622,14.886 3.629,18.572 6.871,20.515 7.39,20.124 7.975,19.631 8.61,18.983 9.189,18.389 9.647,17.682
|
||||||
|
10.021,16.967 8.082,16.208 6.714,14.404 6.569,12.302 Z"/>
|
||||||
|
</g>
|
||||||
|
<g id="advanced-shape">
|
||||||
|
<path
|
||||||
|
d="M19.173,16.163c0.004,0.04,0.007,0.08,0.007,0.121c0,1.748-3.197,3.165-7.14,3.165 c-3.943,0-7.14-1.417-7.14-3.165c0
|
||||||
|
-0.037,0.003-0.073,0.006-0.109C3.11,16.572,2,17.243,2,18.341C2,20.362,6.477,22,12,22 c5.523,0,10-1.638,10-3.659
|
||||||
|
C22,17.22,20.922,16.553,19.173,16.163z"/>
|
||||||
|
<path
|
||||||
|
d="M18.224,15.979c0.006-0.11-0.018-0.285-0.054-0.39c0,0-0.762-2.205-1.176-3.403
|
||||||
|
c-0.624-1.807-2.112-6.139-2.112-6.139c-0.036-0.104-0.031-0.273,0.01-0.376l0.497-1.234c0.041-0.102,0.116-0.266,0.166-0.364
|
||||||
|
l0.986-1.942c0.05-0.098,0.013-0.133-0.081-0.077L9.965,5.871c-0.095,0.056-0.203,0.186-0.24,0.29c0,0-0.252,0.7-0.412,1.144
|
||||||
|
C8.64,9.173,7.968,11.04,7.296,12.908c-0.26,0.723-0.52,1.446-0.78,2.168c-0.056,0.156-0.112,0.311-0.168,0.466
|
||||||
|
c-0.093,0.26-0.049,0.617,0.032,0.881c0.237,0.763,1.001,1.189,1.708,1.435c0.611,0.213,1.254,0.328,1.895,0.403
|
||||||
|
c0.895,0.105,1.805,0.14,2.706,0.112c1.356-0.041,2.767-0.261,4.004-0.846c0.429-0.203,0.854-0.459,1.174-0.816
|
||||||
|
c0.121-0.135,0.226-0.287,0.297-0.455C18.215,16.134,18.224,15.979,18.224,15.979z M14.063,16.131
|
||||||
|
c0.019,0.108-0.046,0.156-0.143,0.104l-1.466-0.772c-0.097-0.052-0.257-0.052-0.354,0l-1.466,0.773
|
||||||
|
c-0.097,0.052-0.162,0.004-0.143-0.104l0.28-1.636c0.019-0.109-0.031-0.261-0.109-0.338l-1.186-1.158
|
||||||
|
c-0.079-0.077-0.054-0.153,0.055-0.169l1.638-0.239c0.109-0.016,0.238-0.11,0.286-0.209l0.733-1.488
|
||||||
|
c0.049-0.099,0.128-0.099,0.177,0l0.733,1.488c0.049,0.099,0.178,0.193,0.286,0.209l1.639,0.239
|
||||||
|
c0.109,0.016,0.134,0.092,0.055,0.169l-1.186,1.158c-0.079,0.077-0.128,0.229-0.109,0.338L14.063,16.131z"/>
|
||||||
|
</g>
|
||||||
|
</defs>
|
||||||
|
<use id="general" xlink:href="#general-shape"/>
|
||||||
|
<use id="general-native" xlink:href="#general-shape"/>
|
||||||
|
<use id="search" xlink:href="#search-shape"/>
|
||||||
|
<use id="search-native" xlink:href="#search-shape"/>
|
||||||
|
<use id="content" xlink:href="#content-shape"/>
|
||||||
|
<use id="content-native" xlink:href="#content-shape"/>
|
||||||
|
<use id="applications" xlink:href="#applications-shape"/>
|
||||||
|
<use id="applications-native" xlink:href="#applications-shape"/>
|
||||||
|
<use id="privacy" xlink:href="#privacy-shape"/>
|
||||||
|
<use id="privacy-native" xlink:href="#privacy-shape"/>
|
||||||
|
<use id="security" xlink:href="#security-shape"/>
|
||||||
|
<use id="security-native" xlink:href="#security-shape"/>
|
||||||
|
<use id="sync" xlink:href="#sync-shape"/>
|
||||||
|
<use id="sync-native" xlink:href="#sync-shape"/>
|
||||||
|
<use id="advanced" xlink:href="#advanced-shape"/>
|
||||||
|
<use id="advanced-native" xlink:href="#advanced-shape"/>
|
||||||
|
</svg>
|
После Ширина: | Высота: | Размер: 8.9 KiB |
Двоичные данные
browser/themes/shared/incontentprefs/icons@2x.png
Двоичные данные
browser/themes/shared/incontentprefs/icons@2x.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 11 KiB |
|
@ -43,78 +43,36 @@ treecol {
|
||||||
visibility: collapse;
|
visibility: collapse;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-icon {
|
|
||||||
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
#category-general > .category-icon {
|
#category-general > .category-icon {
|
||||||
-moz-image-region: rect(0, 24px, 24px, 0);
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#general");
|
||||||
}
|
}
|
||||||
|
|
||||||
#category-search > .category-icon {
|
#category-search > .category-icon {
|
||||||
-moz-image-region: rect(0, 192px, 24px, 168px);
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#search");
|
||||||
}
|
}
|
||||||
|
|
||||||
#category-content > .category-icon {
|
#category-content > .category-icon {
|
||||||
-moz-image-region: rect(0, 48px, 24px, 24px);
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#content");
|
||||||
}
|
}
|
||||||
|
|
||||||
#category-application > .category-icon {
|
#category-application > .category-icon {
|
||||||
-moz-image-region: rect(0, 72px, 24px, 48px);
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#applications");
|
||||||
}
|
}
|
||||||
|
|
||||||
#category-privacy > .category-icon {
|
#category-privacy > .category-icon {
|
||||||
-moz-image-region: rect(0, 96px, 24px, 72px);
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#privacy");
|
||||||
}
|
}
|
||||||
|
|
||||||
#category-security > .category-icon {
|
#category-security > .category-icon {
|
||||||
-moz-image-region: rect(0, 120px, 24px, 96px);
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#security");
|
||||||
}
|
}
|
||||||
|
|
||||||
#category-sync > .category-icon {
|
#category-sync > .category-icon {
|
||||||
-moz-image-region: rect(0, 144px, 24px, 120px);
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#sync");
|
||||||
}
|
}
|
||||||
|
|
||||||
#category-advanced > .category-icon {
|
#category-advanced > .category-icon {
|
||||||
-moz-image-region: rect(0, 168px, 24px, 144px);
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#advanced");
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-resolution: 2dppx) {
|
|
||||||
.category-icon {
|
|
||||||
list-style-image: url("chrome://browser/skin/preferences/in-content/icons@2x.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
#category-general > .category-icon {
|
|
||||||
-moz-image-region: rect(0, 48px, 48px, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#category-search > .category-icon {
|
|
||||||
-moz-image-region: rect(0, 384px, 48px, 336px);
|
|
||||||
}
|
|
||||||
|
|
||||||
#category-content > .category-icon {
|
|
||||||
-moz-image-region: rect(0, 96px, 48px, 48px);
|
|
||||||
}
|
|
||||||
|
|
||||||
#category-application > .category-icon {
|
|
||||||
-moz-image-region: rect(0, 144px, 48px, 96px);
|
|
||||||
}
|
|
||||||
|
|
||||||
#category-privacy > .category-icon {
|
|
||||||
-moz-image-region: rect(0, 192px, 48px, 144px);
|
|
||||||
}
|
|
||||||
|
|
||||||
#category-security > .category-icon {
|
|
||||||
-moz-image-region: rect(0, 240px, 48px, 192px);
|
|
||||||
}
|
|
||||||
|
|
||||||
#category-sync > .category-icon {
|
|
||||||
-moz-image-region: rect(0, 288px, 48px, 240px);
|
|
||||||
}
|
|
||||||
|
|
||||||
#category-advanced > .category-icon {
|
|
||||||
-moz-image-region: rect(0, 336px, 48px, 288px);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 800px) {
|
@media (max-width: 800px) {
|
||||||
|
|
|
@ -202,8 +202,7 @@ browser.jar:
|
||||||
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
||||||
* skin/classic/browser/preferences/in-content/dialog.css (preferences/in-content/dialog.css)
|
* skin/classic/browser/preferences/in-content/dialog.css (preferences/in-content/dialog.css)
|
||||||
skin/classic/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico)
|
skin/classic/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico)
|
||||||
skin/classic/browser/preferences/in-content/icons.png (../shared/incontentprefs/icons.png)
|
skin/classic/browser/preferences/in-content/icons.svg (../shared/incontentprefs/icons.svg)
|
||||||
skin/classic/browser/preferences/in-content/icons@2x.png (../shared/incontentprefs/icons@2x.png)
|
|
||||||
skin/classic/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css)
|
skin/classic/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css)
|
||||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||||
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
||||||
|
@ -670,8 +669,7 @@ browser.jar:
|
||||||
* skin/classic/aero/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
* skin/classic/aero/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
||||||
* skin/classic/aero/browser/preferences/in-content/dialog.css (preferences/in-content/dialog.css)
|
* skin/classic/aero/browser/preferences/in-content/dialog.css (preferences/in-content/dialog.css)
|
||||||
skin/classic/aero/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico)
|
skin/classic/aero/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico)
|
||||||
skin/classic/aero/browser/preferences/in-content/icons.png (../shared/incontentprefs/icons.png)
|
skin/classic/aero/browser/preferences/in-content/icons.svg (../shared/incontentprefs/icons.svg)
|
||||||
skin/classic/aero/browser/preferences/in-content/icons@2x.png (../shared/incontentprefs/icons@2x.png)
|
|
||||||
skin/classic/aero/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css)
|
skin/classic/aero/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css)
|
||||||
skin/classic/aero/browser/preferences/applications.css (preferences/applications.css)
|
skin/classic/aero/browser/preferences/applications.css (preferences/applications.css)
|
||||||
skin/classic/aero/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
skin/classic/aero/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
||||||
|
|
|
@ -4,6 +4,40 @@
|
||||||
|
|
||||||
%include ../../../shared/incontentprefs/preferences.inc.css
|
%include ../../../shared/incontentprefs/preferences.inc.css
|
||||||
|
|
||||||
|
@media not all and (-moz-windows-default-theme) {
|
||||||
|
#category-general > .category-icon {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#general-native");
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-search > .category-icon {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#search-native");
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-content > .category-icon {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#content-native");
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-application > .category-icon {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#applications-native");
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-privacy > .category-icon {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#privacy-native");
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-security > .category-icon {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#security-native");
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-sync > .category-icon {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#sync-native");
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-advanced > .category-icon {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#advanced-native");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.actionsMenu > .menulist-label-box > .menulist-icon {
|
.actionsMenu > .menulist-label-box > .menulist-icon {
|
||||||
-moz-margin-end: 9px;
|
-moz-margin-end: 9px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,41 +53,38 @@ struct SavedFrame::Lookup {
|
||||||
JSAtom *functionDisplayName;
|
JSAtom *functionDisplayName;
|
||||||
SavedFrame *parent;
|
SavedFrame *parent;
|
||||||
JSPrincipals *principals;
|
JSPrincipals *principals;
|
||||||
};
|
|
||||||
|
|
||||||
class SavedFrame::AutoLookupRooter : public JS::CustomAutoRooter
|
void trace(JSTracer *trc) {
|
||||||
{
|
gc::MarkStringUnbarriered(trc, &source, "SavedFrame::Lookup::source");
|
||||||
public:
|
if (functionDisplayName) {
|
||||||
AutoLookupRooter(JSContext *cx, JSAtom *source, uint32_t line, uint32_t column,
|
gc::MarkStringUnbarriered(trc, &functionDisplayName,
|
||||||
JSAtom *functionDisplayName, SavedFrame *parent, JSPrincipals *principals)
|
|
||||||
: JS::CustomAutoRooter(cx),
|
|
||||||
value(source, line, column, functionDisplayName, parent, principals) {}
|
|
||||||
|
|
||||||
operator const SavedFrame::Lookup&() const { return value; }
|
|
||||||
SavedFrame::Lookup &get() { return value; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual void trace(JSTracer *trc) {
|
|
||||||
gc::MarkStringUnbarriered(trc, &value.source, "SavedFrame::Lookup::source");
|
|
||||||
if (value.functionDisplayName) {
|
|
||||||
gc::MarkStringUnbarriered(trc, &value.functionDisplayName,
|
|
||||||
"SavedFrame::Lookup::functionDisplayName");
|
"SavedFrame::Lookup::functionDisplayName");
|
||||||
}
|
}
|
||||||
if (value.parent)
|
if (parent) {
|
||||||
gc::MarkObjectUnbarriered(trc, &value.parent, "SavedFrame::Lookup::parent");
|
gc::MarkObjectUnbarriered(trc, &parent,
|
||||||
|
"SavedFrame::Lookup::parent");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SavedFrame::Lookup value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SavedFrame::HandleLookup
|
class MOZ_STACK_CLASS SavedFrame::AutoLookupVector : public JS::CustomAutoRooter {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
MOZ_IMPLICIT HandleLookup(SavedFrame::AutoLookupRooter &lookup) : ref(lookup) { }
|
explicit AutoLookupVector(JSContext *cx)
|
||||||
SavedFrame::Lookup *operator->() { return &ref.get(); }
|
: JS::CustomAutoRooter(cx),
|
||||||
operator const SavedFrame::Lookup&() const { return ref; }
|
lookups(cx)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
typedef Vector<Lookup, 20> LookupVector;
|
||||||
|
inline LookupVector *operator->() { return &lookups; }
|
||||||
|
inline Lookup &operator[](size_t i) { return lookups[i]; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SavedFrame::AutoLookupRooter &ref;
|
LookupVector lookups;
|
||||||
|
|
||||||
|
virtual void trace(JSTracer *trc) {
|
||||||
|
for (size_t i = 0; i < lookups.length(); i++)
|
||||||
|
lookups[i].trace(trc);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* static */ HashNumber
|
/* static */ HashNumber
|
||||||
|
@ -580,12 +577,14 @@ SavedStacks::insertFrames(JSContext *cx, FrameIter &iter, MutableHandleSavedFram
|
||||||
// SavedFrame objects at that time.
|
// SavedFrame objects at that time.
|
||||||
//
|
//
|
||||||
// To avoid making many copies of FrameIter (whose copy constructor is
|
// To avoid making many copies of FrameIter (whose copy constructor is
|
||||||
// relatively slow), we save the subset of FrameIter's data that is relevant
|
// relatively slow), we use a vector of `SavedFrame::Lookup` objects, which
|
||||||
// to our needs in a FrameState object, and maintain a vector of FrameState
|
// only contain the FrameIter data we need. The `SavedFrame::Lookup`
|
||||||
// objects instead of a vector of FrameIter objects.
|
// objects are partially initialized with everything except their parent
|
||||||
|
// pointers on the first pass, and then we fill in the parent pointers as we
|
||||||
|
// return in the second pass.
|
||||||
|
|
||||||
// Accumulate the vector of FrameState objects in |stackState|.
|
// Accumulate the vector of Lookup objects in |stackChain|.
|
||||||
AutoFrameStateVector stackState(cx);
|
SavedFrame::AutoLookupVector stackChain(cx);
|
||||||
while (!iter.done()) {
|
while (!iter.done()) {
|
||||||
AutoLocationValueRooter location(cx);
|
AutoLocationValueRooter location(cx);
|
||||||
|
|
||||||
|
@ -595,12 +594,18 @@ SavedStacks::insertFrames(JSContext *cx, FrameIter &iter, MutableHandleSavedFram
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
// Use growByUninitialized and placement-new instead of just append.
|
||||||
FrameState frameState(iter);
|
// We'd ideally like to use an emplace method once Vector supports it.
|
||||||
frameState.location = location.get();
|
if (!stackChain->growByUninitialized(1))
|
||||||
if (!stackState->append(frameState))
|
return false;
|
||||||
return false;
|
new (&stackChain->back()) SavedFrame::Lookup(
|
||||||
}
|
location->source,
|
||||||
|
location->line,
|
||||||
|
location->column,
|
||||||
|
iter.isNonEvalFunctionFrame() ? iter.functionDisplayAtom() : nullptr,
|
||||||
|
nullptr,
|
||||||
|
iter.compartment()->principals
|
||||||
|
);
|
||||||
|
|
||||||
++iter;
|
++iter;
|
||||||
|
|
||||||
|
@ -617,18 +622,13 @@ SavedStacks::insertFrames(JSContext *cx, FrameIter &iter, MutableHandleSavedFram
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate through |stackState| in reverse order and get or create the
|
// Iterate through |stackChain| in reverse order and get or create the
|
||||||
// actual SavedFrame instances.
|
// actual SavedFrame instances.
|
||||||
RootedSavedFrame parentFrame(cx, nullptr);
|
RootedSavedFrame parentFrame(cx, nullptr);
|
||||||
for (size_t i = stackState->length(); i != 0; i--) {
|
for (size_t i = stackChain->length(); i != 0; i--) {
|
||||||
SavedFrame::AutoLookupRooter lookup(cx,
|
SavedFrame::AutoLookupRooter lookup(cx, &stackChain[i-1]);
|
||||||
stackState[i-1].location.source,
|
lookup->parent = parentFrame;
|
||||||
stackState[i-1].location.line,
|
parentFrame.set(getOrCreateSavedFrame(cx, lookup));
|
||||||
stackState[i-1].location.column,
|
|
||||||
stackState[i-1].name,
|
|
||||||
parentFrame,
|
|
||||||
stackState[i-1].principals);
|
|
||||||
parentFrame = getOrCreateSavedFrame(cx, lookup);
|
|
||||||
if (!parentFrame)
|
if (!parentFrame)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -640,7 +640,8 @@ SavedStacks::insertFrames(JSContext *cx, FrameIter &iter, MutableHandleSavedFram
|
||||||
SavedFrame *
|
SavedFrame *
|
||||||
SavedStacks::getOrCreateSavedFrame(JSContext *cx, SavedFrame::HandleLookup lookup)
|
SavedStacks::getOrCreateSavedFrame(JSContext *cx, SavedFrame::HandleLookup lookup)
|
||||||
{
|
{
|
||||||
DependentAddPtr<SavedFrame::Set> p(cx, frames, lookup);
|
const SavedFrame::Lookup &lookupInstance = *lookup;
|
||||||
|
DependentAddPtr<SavedFrame::Set> p(cx, frames, lookupInstance);
|
||||||
if (p)
|
if (p)
|
||||||
return *p;
|
return *p;
|
||||||
|
|
||||||
|
@ -648,7 +649,7 @@ SavedStacks::getOrCreateSavedFrame(JSContext *cx, SavedFrame::HandleLookup looku
|
||||||
if (!frame)
|
if (!frame)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (!p.add(cx, frames, lookup, frame))
|
if (!p.add(cx, frames, lookupInstance, frame))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
|
@ -778,31 +779,6 @@ SavedStacks::chooseSamplingProbability(JSContext *cx)
|
||||||
allocationSamplingProbability = allocationTrackingDbg->allocationSamplingProbability;
|
allocationSamplingProbability = allocationTrackingDbg->allocationSamplingProbability;
|
||||||
}
|
}
|
||||||
|
|
||||||
SavedStacks::FrameState::FrameState(const FrameIter &iter)
|
|
||||||
: principals(iter.compartment()->principals),
|
|
||||||
name(iter.isNonEvalFunctionFrame() ? iter.functionDisplayAtom() : nullptr),
|
|
||||||
location()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SavedStacks::FrameState::FrameState(const FrameState &fs)
|
|
||||||
: principals(fs.principals),
|
|
||||||
name(fs.name),
|
|
||||||
location(fs.location)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SavedStacks::FrameState::~FrameState()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SavedStacks::FrameState::trace(JSTracer *trc) {
|
|
||||||
if (name)
|
|
||||||
gc::MarkStringUnbarriered(trc, &name, "SavedStacks::FrameState::name");
|
|
||||||
location.trace(trc);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SavedStacksMetadataCallback(JSContext *cx, JSObject **pmetadata)
|
SavedStacksMetadataCallback(JSContext *cx, JSObject **pmetadata)
|
||||||
{
|
{
|
||||||
|
|
|
@ -55,8 +55,9 @@ class SavedFrame : public NativeObject {
|
||||||
HashPolicy,
|
HashPolicy,
|
||||||
SystemAllocPolicy> Set;
|
SystemAllocPolicy> Set;
|
||||||
|
|
||||||
class AutoLookupRooter;
|
typedef RootedGeneric<Lookup*> AutoLookupRooter;
|
||||||
class HandleLookup;
|
typedef AutoLookupRooter &HandleLookup;
|
||||||
|
class AutoLookupVector;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool finishSavedFrameInit(JSContext *cx, HandleObject ctor, HandleObject proto);
|
static bool finishSavedFrameInit(JSContext *cx, HandleObject ctor, HandleObject proto);
|
||||||
|
@ -221,44 +222,6 @@ class SavedStacks {
|
||||||
|
|
||||||
void sweepPCLocationMap();
|
void sweepPCLocationMap();
|
||||||
bool getLocation(JSContext *cx, const FrameIter &iter, MutableHandleLocationValue locationp);
|
bool getLocation(JSContext *cx, const FrameIter &iter, MutableHandleLocationValue locationp);
|
||||||
|
|
||||||
struct FrameState
|
|
||||||
{
|
|
||||||
FrameState() : principals(nullptr), name(nullptr), location() { }
|
|
||||||
explicit FrameState(const FrameIter &iter);
|
|
||||||
FrameState(const FrameState &fs);
|
|
||||||
|
|
||||||
~FrameState();
|
|
||||||
|
|
||||||
void trace(JSTracer *trc);
|
|
||||||
|
|
||||||
// Note: we don't have to hold/drop principals, because we're
|
|
||||||
// only alive while the stack is being walked and during this
|
|
||||||
// time the principals are kept alive by the stack itself.
|
|
||||||
JSPrincipals *principals;
|
|
||||||
JSAtom *name;
|
|
||||||
LocationValue location;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MOZ_STACK_CLASS AutoFrameStateVector : public JS::CustomAutoRooter {
|
|
||||||
public:
|
|
||||||
explicit AutoFrameStateVector(JSContext *cx)
|
|
||||||
: JS::CustomAutoRooter(cx),
|
|
||||||
frames(cx)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
typedef Vector<FrameState, 20> FrameStateVector;
|
|
||||||
inline FrameStateVector *operator->() { return &frames; }
|
|
||||||
inline FrameState &operator[](size_t i) { return frames[i]; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
FrameStateVector frames;
|
|
||||||
|
|
||||||
virtual void trace(JSTracer *trc) {
|
|
||||||
for (size_t i = 0; i < frames.length(); i++)
|
|
||||||
frames[i].trace(trc);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool SavedStacksMetadataCallback(JSContext *cx, JSObject **pmetadata);
|
bool SavedStacksMetadataCallback(JSContext *cx, JSObject **pmetadata);
|
||||||
|
|
|
@ -5,8 +5,10 @@
|
||||||
|
|
||||||
package org.mozilla.gecko;
|
package org.mozilla.gecko;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
@ -114,6 +116,8 @@ import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Base64;
|
||||||
|
import android.util.Base64OutputStream;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.InputDevice;
|
import android.view.InputDevice;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
@ -766,6 +770,7 @@ public class BrowserApp extends GeckoApp
|
||||||
"Accounts:Create",
|
"Accounts:Create",
|
||||||
"CharEncoding:Data",
|
"CharEncoding:Data",
|
||||||
"CharEncoding:State",
|
"CharEncoding:State",
|
||||||
|
"Favicon:CacheLoad",
|
||||||
"Feedback:LastUrl",
|
"Feedback:LastUrl",
|
||||||
"Feedback:MaybeLater",
|
"Feedback:MaybeLater",
|
||||||
"Feedback:OpenPlayStore",
|
"Feedback:OpenPlayStore",
|
||||||
|
@ -774,8 +779,7 @@ public class BrowserApp extends GeckoApp
|
||||||
"Reader:Share",
|
"Reader:Share",
|
||||||
"Settings:Show",
|
"Settings:Show",
|
||||||
"Telemetry:Gather",
|
"Telemetry:Gather",
|
||||||
"Updater:Launch",
|
"Updater:Launch");
|
||||||
"BrowserToolbar:Visibility");
|
|
||||||
|
|
||||||
Distribution distribution = Distribution.init(this);
|
Distribution distribution = Distribution.init(this);
|
||||||
|
|
||||||
|
@ -1309,6 +1313,7 @@ public class BrowserApp extends GeckoApp
|
||||||
"Accounts:Create",
|
"Accounts:Create",
|
||||||
"CharEncoding:Data",
|
"CharEncoding:Data",
|
||||||
"CharEncoding:State",
|
"CharEncoding:State",
|
||||||
|
"Favicon:CacheLoad",
|
||||||
"Feedback:LastUrl",
|
"Feedback:LastUrl",
|
||||||
"Feedback:MaybeLater",
|
"Feedback:MaybeLater",
|
||||||
"Feedback:OpenPlayStore",
|
"Feedback:OpenPlayStore",
|
||||||
|
@ -1317,8 +1322,7 @@ public class BrowserApp extends GeckoApp
|
||||||
"Reader:Share",
|
"Reader:Share",
|
||||||
"Settings:Show",
|
"Settings:Show",
|
||||||
"Telemetry:Gather",
|
"Telemetry:Gather",
|
||||||
"Updater:Launch",
|
"Updater:Launch");
|
||||||
"BrowserToolbar:Visibility");
|
|
||||||
|
|
||||||
if (AppConstants.MOZ_ANDROID_BEAM) {
|
if (AppConstants.MOZ_ANDROID_BEAM) {
|
||||||
NfcAdapter nfc = NfcAdapter.getDefaultAdapter(this);
|
NfcAdapter nfc = NfcAdapter.getDefaultAdapter(this);
|
||||||
|
@ -1534,17 +1538,6 @@ public class BrowserApp extends GeckoApp
|
||||||
return (mTabsPanel != null && mTabsPanel.isSideBar());
|
return (mTabsPanel != null && mTabsPanel.isSideBar());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setBrowserToolbarVisible(final boolean visible) {
|
|
||||||
ThreadUtils.postToUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (mDynamicToolbar.isEnabled()) {
|
|
||||||
mDynamicToolbar.setVisible(visible, VisibilityTransition.IMMEDIATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isSideBar() {
|
private boolean isSideBar() {
|
||||||
return (HardwareUtils.isTablet() && getOrientation() == Configuration.ORIENTATION_LANDSCAPE);
|
return (HardwareUtils.isTablet() && getOrientation() == Configuration.ORIENTATION_LANDSCAPE);
|
||||||
}
|
}
|
||||||
|
@ -1634,6 +1627,10 @@ public class BrowserApp extends GeckoApp
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
} else if ("Favicon:CacheLoad".equals(event)) {
|
||||||
|
final String url = message.getString("url");
|
||||||
|
getFaviconFromCache(callback, url);
|
||||||
|
|
||||||
} else if ("Feedback:LastUrl".equals(event)) {
|
} else if ("Feedback:LastUrl".equals(event)) {
|
||||||
getLastUrl(callback);
|
getLastUrl(callback);
|
||||||
|
|
||||||
|
@ -1705,15 +1702,58 @@ public class BrowserApp extends GeckoApp
|
||||||
}
|
}
|
||||||
} else if ("Updater:Launch".equals(event)) {
|
} else if ("Updater:Launch".equals(event)) {
|
||||||
handleUpdaterLaunch();
|
handleUpdaterLaunch();
|
||||||
|
|
||||||
} else if ("BrowserToolbar:Visibility".equals(event)) {
|
|
||||||
setBrowserToolbarVisible(message.getBoolean("visible"));
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
super.handleMessage(event, message, callback);
|
super.handleMessage(event, message, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void getFaviconFromCache(final EventCallback callback, final String url) {
|
||||||
|
final OnFaviconLoadedListener listener = new OnFaviconLoadedListener() {
|
||||||
|
@Override
|
||||||
|
public void onFaviconLoaded(final String url, final String faviconURL, final Bitmap favicon) {
|
||||||
|
ThreadUtils.assertOnUiThread();
|
||||||
|
// Convert Bitmap to Base64 data URI in background.
|
||||||
|
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
ByteArrayOutputStream out = null;
|
||||||
|
Base64OutputStream b64 = null;
|
||||||
|
|
||||||
|
// Failed to load favicon from local.
|
||||||
|
if (favicon == null) {
|
||||||
|
callback.sendError("Failed to get favicon from cache");
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
out = new ByteArrayOutputStream();
|
||||||
|
out.write("data:image/png;base64,".getBytes());
|
||||||
|
b64 = new Base64OutputStream(out, Base64.NO_WRAP);
|
||||||
|
favicon.compress(Bitmap.CompressFormat.PNG, 100, b64);
|
||||||
|
callback.sendSuccess(new String(out.toByteArray()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w(LOGTAG, "Failed to convert to base64 data URI");
|
||||||
|
callback.sendError("Failed to convert favicon to a base64 data URI");
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (out != null) {
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
if (b64 != null) {
|
||||||
|
b64.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w(LOGTAG, "Failed to close the streams");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Favicons.getSizedFaviconForPageFromLocal(getContext(),
|
||||||
|
url,
|
||||||
|
listener);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use a dummy Intent to do a default browser check.
|
* Use a dummy Intent to do a default browser check.
|
||||||
*
|
*
|
||||||
|
|
|
@ -392,7 +392,7 @@ public abstract class GeckoApp
|
||||||
onPreparePanel(featureId, mMenuPanel, mMenu);
|
onPreparePanel(featureId, mMenuPanel, mMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mMenuPanel;
|
return mMenuPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onCreatePanelView(featureId);
|
return super.onCreatePanelView(featureId);
|
||||||
|
@ -505,7 +505,7 @@ public abstract class GeckoApp
|
||||||
mMenuPanel.addView((GeckoMenu) mMenu);
|
mMenuPanel.addView((GeckoMenu) mMenu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||||
// Handle hardware menu key presses separately so that we can show a custom menu in some cases.
|
// Handle hardware menu key presses separately so that we can show a custom menu in some cases.
|
||||||
|
@ -839,7 +839,11 @@ public abstract class GeckoApp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onToastHidden(ButtonToast.ReasonHidden reason) {
|
public void onToastHidden(ButtonToast.ReasonHidden reason) {
|
||||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Toast:Hidden", buttonId));
|
if (reason == ButtonToast.ReasonHidden.TIMEOUT ||
|
||||||
|
reason == ButtonToast.ReasonHidden.TOUCH_OUTSIDE ||
|
||||||
|
reason == ButtonToast.ReasonHidden.REPLACED) {
|
||||||
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Toast:Hidden", buttonId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1059,7 +1063,7 @@ public abstract class GeckoApp
|
||||||
public void requestRender() {
|
public void requestRender() {
|
||||||
mLayerView.requestRender();
|
mLayerView.requestRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void hidePlugins(Tab tab) {
|
public void hidePlugins(Tab tab) {
|
||||||
for (Layer layer : tab.getPluginLayers()) {
|
for (Layer layer : tab.getPluginLayers()) {
|
||||||
if (layer instanceof PluginLayer) {
|
if (layer instanceof PluginLayer) {
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
package org.mozilla.gecko;
|
package org.mozilla.gecko;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
|
import android.text.format.DateUtils;
|
||||||
import org.mozilla.gecko.db.RemoteClient;
|
import org.mozilla.gecko.db.RemoteClient;
|
||||||
import org.mozilla.gecko.db.RemoteTab;
|
import org.mozilla.gecko.db.RemoteTab;
|
||||||
import org.mozilla.gecko.home.TwoLinePageRow;
|
import org.mozilla.gecko.home.TwoLinePageRow;
|
||||||
|
@ -20,6 +20,12 @@ import android.widget.BaseExpandableListAdapter;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An adapter that populates group and child views with remote client and tab
|
* An adapter that populates group and child views with remote client and tab
|
||||||
* data maintained in a monolithic static array.
|
* data maintained in a monolithic static array.
|
||||||
|
@ -28,6 +34,15 @@ import android.widget.TextView;
|
||||||
* specialization to home fragment styles.
|
* specialization to home fragment styles.
|
||||||
*/
|
*/
|
||||||
public class RemoteTabsExpandableListAdapter extends BaseExpandableListAdapter {
|
public class RemoteTabsExpandableListAdapter extends BaseExpandableListAdapter {
|
||||||
|
/**
|
||||||
|
* If a device claims to have synced before this date, we will assume it has never synced.
|
||||||
|
*/
|
||||||
|
private static final Date EARLIEST_VALID_SYNCED_DATE;
|
||||||
|
static {
|
||||||
|
final Calendar c = GregorianCalendar.getInstance();
|
||||||
|
c.set(2000, Calendar.JANUARY, 1, 0, 0, 0);
|
||||||
|
EARLIEST_VALID_SYNCED_DATE = c.getTime();
|
||||||
|
}
|
||||||
protected final ArrayList<RemoteClient> clients;
|
protected final ArrayList<RemoteClient> clients;
|
||||||
private final boolean showGroupIndicator;
|
private final boolean showGroupIndicator;
|
||||||
protected int groupLayoutId;
|
protected int groupLayoutId;
|
||||||
|
@ -156,7 +171,7 @@ public class RemoteTabsExpandableListAdapter extends BaseExpandableListAdapter {
|
||||||
// It's OK to access the DB on the main thread here, as we're just
|
// It's OK to access the DB on the main thread here, as we're just
|
||||||
// getting a string.
|
// getting a string.
|
||||||
final GeckoProfile profile = GeckoProfile.get(context);
|
final GeckoProfile profile = GeckoProfile.get(context);
|
||||||
holder.lastModifiedView.setText(profile.getDB().getTabsAccessor().getLastSyncedString(context, now, client.lastModified));
|
holder.lastModifiedView.setText(this.getLastSyncedString(context, now, client.lastModified));
|
||||||
|
|
||||||
// These views exists only in some of our group views: they are present
|
// These views exists only in some of our group views: they are present
|
||||||
// for the home panel groups and not for the tabs panel groups.
|
// for the home panel groups and not for the tabs panel groups.
|
||||||
|
@ -215,4 +230,19 @@ public class RemoteTabsExpandableListAdapter extends BaseExpandableListAdapter {
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a relative "Last synced" time span for the given tab record.
|
||||||
|
*
|
||||||
|
* @param now local time.
|
||||||
|
* @param time to format string for.
|
||||||
|
* @return string describing time span
|
||||||
|
*/
|
||||||
|
public String getLastSyncedString(Context context, long now, long time) {
|
||||||
|
if (new Date(time).before(EARLIEST_VALID_SYNCED_DATE)) {
|
||||||
|
return context.getString(R.string.remote_tabs_never_synced);
|
||||||
|
}
|
||||||
|
final CharSequence relativeTimeSpanString = DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS);
|
||||||
|
return context.getResources().getString(R.string.remote_tabs_last_synced, relativeTimeSpanString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -798,7 +798,12 @@ sync_java_files = [
|
||||||
'background/fxa/FxAccountClientException.java',
|
'background/fxa/FxAccountClientException.java',
|
||||||
'background/fxa/FxAccountRemoteError.java',
|
'background/fxa/FxAccountRemoteError.java',
|
||||||
'background/fxa/FxAccountUtils.java',
|
'background/fxa/FxAccountUtils.java',
|
||||||
|
'background/fxa/oauth/FxAccountAbstractClient.java',
|
||||||
|
'background/fxa/oauth/FxAccountAbstractClientException.java',
|
||||||
|
'background/fxa/oauth/FxAccountOAuthClient10.java',
|
||||||
|
'background/fxa/oauth/FxAccountOAuthRemoteError.java',
|
||||||
'background/fxa/PasswordStretcher.java',
|
'background/fxa/PasswordStretcher.java',
|
||||||
|
'background/fxa/profile/FxAccountProfileClient10.java',
|
||||||
'background/fxa/QuickPasswordStretcher.java',
|
'background/fxa/QuickPasswordStretcher.java',
|
||||||
'background/fxa/SkewHandler.java',
|
'background/fxa/SkewHandler.java',
|
||||||
'background/healthreport/AndroidConfigurationProvider.java',
|
'background/healthreport/AndroidConfigurationProvider.java',
|
||||||
|
@ -835,7 +840,9 @@ sync_java_files = [
|
||||||
'browserid/MockMyIDTokenFactory.java',
|
'browserid/MockMyIDTokenFactory.java',
|
||||||
'browserid/RSACryptoImplementation.java',
|
'browserid/RSACryptoImplementation.java',
|
||||||
'browserid/SigningPrivateKey.java',
|
'browserid/SigningPrivateKey.java',
|
||||||
'browserid/verifier/BrowserIDRemoteVerifierClient.java',
|
'browserid/verifier/AbstractBrowserIDRemoteVerifierClient.java',
|
||||||
|
'browserid/verifier/BrowserIDRemoteVerifierClient10.java',
|
||||||
|
'browserid/verifier/BrowserIDRemoteVerifierClient20.java',
|
||||||
'browserid/verifier/BrowserIDVerifierClient.java',
|
'browserid/verifier/BrowserIDVerifierClient.java',
|
||||||
'browserid/verifier/BrowserIDVerifierDelegate.java',
|
'browserid/verifier/BrowserIDVerifierDelegate.java',
|
||||||
'browserid/verifier/BrowserIDVerifierException.java',
|
'browserid/verifier/BrowserIDVerifierException.java',
|
||||||
|
@ -962,10 +969,12 @@ sync_java_files = [
|
||||||
'sync/middleware/MiddlewareRepository.java',
|
'sync/middleware/MiddlewareRepository.java',
|
||||||
'sync/middleware/MiddlewareRepositorySession.java',
|
'sync/middleware/MiddlewareRepositorySession.java',
|
||||||
'sync/MigrationSentinelSyncStage.java',
|
'sync/MigrationSentinelSyncStage.java',
|
||||||
|
'sync/net/AbstractBearerTokenAuthHeaderProvider.java',
|
||||||
'sync/net/AuthHeaderProvider.java',
|
'sync/net/AuthHeaderProvider.java',
|
||||||
'sync/net/BaseResource.java',
|
'sync/net/BaseResource.java',
|
||||||
'sync/net/BaseResourceDelegate.java',
|
'sync/net/BaseResourceDelegate.java',
|
||||||
'sync/net/BasicAuthHeaderProvider.java',
|
'sync/net/BasicAuthHeaderProvider.java',
|
||||||
|
'sync/net/BearerAuthHeaderProvider.java',
|
||||||
'sync/net/BrowserIDAuthHeaderProvider.java',
|
'sync/net/BrowserIDAuthHeaderProvider.java',
|
||||||
'sync/net/ConnectionMonitorThread.java',
|
'sync/net/ConnectionMonitorThread.java',
|
||||||
'sync/net/HandleProgressException.java',
|
'sync/net/HandleProgressException.java',
|
||||||
|
|
|
@ -0,0 +1,225 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
package org.mozilla.gecko.background.fxa.oauth;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
import org.mozilla.gecko.background.fxa.FxAccountClientException;
|
||||||
|
import org.mozilla.gecko.background.fxa.oauth.FxAccountAbstractClientException.FxAccountAbstractClientMalformedResponseException;
|
||||||
|
import org.mozilla.gecko.background.fxa.oauth.FxAccountAbstractClientException.FxAccountAbstractClientRemoteException;
|
||||||
|
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||||
|
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||||
|
import org.mozilla.gecko.sync.Utils;
|
||||||
|
import org.mozilla.gecko.sync.net.AuthHeaderProvider;
|
||||||
|
import org.mozilla.gecko.sync.net.BaseResource;
|
||||||
|
import org.mozilla.gecko.sync.net.BaseResourceDelegate;
|
||||||
|
import org.mozilla.gecko.sync.net.Resource;
|
||||||
|
import org.mozilla.gecko.sync.net.SyncResponse;
|
||||||
|
import org.mozilla.gecko.sync.net.SyncStorageResponse;
|
||||||
|
|
||||||
|
import ch.boye.httpclientandroidlib.HttpEntity;
|
||||||
|
import ch.boye.httpclientandroidlib.HttpHeaders;
|
||||||
|
import ch.boye.httpclientandroidlib.HttpResponse;
|
||||||
|
import ch.boye.httpclientandroidlib.client.ClientProtocolException;
|
||||||
|
import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase;
|
||||||
|
import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient;
|
||||||
|
|
||||||
|
public abstract class FxAccountAbstractClient {
|
||||||
|
protected static final String LOG_TAG = FxAccountAbstractClient.class.getSimpleName();
|
||||||
|
|
||||||
|
protected static final String ACCEPT_HEADER = "application/json;charset=utf-8";
|
||||||
|
protected static final String AUTHORIZATION_RESPONSE_TYPE = "token";
|
||||||
|
|
||||||
|
public static final String JSON_KEY_ERROR = "error";
|
||||||
|
public static final String JSON_KEY_MESSAGE = "message";
|
||||||
|
public static final String JSON_KEY_CODE = "code";
|
||||||
|
public static final String JSON_KEY_ERRNO = "errno";
|
||||||
|
|
||||||
|
protected static final String[] requiredErrorStringFields = { JSON_KEY_ERROR, JSON_KEY_MESSAGE };
|
||||||
|
protected static final String[] requiredErrorLongFields = { JSON_KEY_CODE, JSON_KEY_ERRNO };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server's URI.
|
||||||
|
* <p>
|
||||||
|
* We assume throughout that this ends with a trailing slash (and guarantee as
|
||||||
|
* much in the constructor).
|
||||||
|
*/
|
||||||
|
protected final String serverURI;
|
||||||
|
|
||||||
|
protected final Executor executor;
|
||||||
|
|
||||||
|
public FxAccountAbstractClient(String serverURI, Executor executor) {
|
||||||
|
if (serverURI == null) {
|
||||||
|
throw new IllegalArgumentException("Must provide a server URI.");
|
||||||
|
}
|
||||||
|
if (executor == null) {
|
||||||
|
throw new IllegalArgumentException("Must provide a non-null executor.");
|
||||||
|
}
|
||||||
|
this.serverURI = serverURI.endsWith("/") ? serverURI : serverURI + "/";
|
||||||
|
if (!this.serverURI.endsWith("/")) {
|
||||||
|
throw new IllegalArgumentException("Constructed serverURI must end with a trailing slash: " + this.serverURI);
|
||||||
|
}
|
||||||
|
this.executor = executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a typed value extracted from a successful response (in an
|
||||||
|
* endpoint-dependent way).
|
||||||
|
*/
|
||||||
|
public interface RequestDelegate<T> {
|
||||||
|
public void handleError(Exception e);
|
||||||
|
public void handleFailure(FxAccountAbstractClientRemoteException e);
|
||||||
|
public void handleSuccess(T result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intepret a response from the auth server.
|
||||||
|
* <p>
|
||||||
|
* Throw an appropriate exception on errors; otherwise, return the response's
|
||||||
|
* status code.
|
||||||
|
*
|
||||||
|
* @return response's HTTP status code.
|
||||||
|
* @throws FxAccountClientException
|
||||||
|
*/
|
||||||
|
public static int validateResponse(HttpResponse response) throws FxAccountAbstractClientRemoteException {
|
||||||
|
final int status = response.getStatusLine().getStatusCode();
|
||||||
|
if (status == 200) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
int code;
|
||||||
|
int errno;
|
||||||
|
String error;
|
||||||
|
String message;
|
||||||
|
ExtendedJSONObject body;
|
||||||
|
try {
|
||||||
|
body = new SyncStorageResponse(response).jsonObjectBody();
|
||||||
|
body.throwIfFieldsMissingOrMisTyped(requiredErrorStringFields, String.class);
|
||||||
|
body.throwIfFieldsMissingOrMisTyped(requiredErrorLongFields, Long.class);
|
||||||
|
code = body.getLong(JSON_KEY_CODE).intValue();
|
||||||
|
errno = body.getLong(JSON_KEY_ERRNO).intValue();
|
||||||
|
error = body.getString(JSON_KEY_ERROR);
|
||||||
|
message = body.getString(JSON_KEY_MESSAGE);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new FxAccountAbstractClientMalformedResponseException(response);
|
||||||
|
}
|
||||||
|
throw new FxAccountAbstractClientRemoteException(response, code, errno, error, message, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T> void invokeHandleError(final RequestDelegate<T> delegate, final Exception e) {
|
||||||
|
executor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
delegate.handleError(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T> void post(BaseResource resource, final ExtendedJSONObject requestBody, final RequestDelegate<T> delegate) {
|
||||||
|
try {
|
||||||
|
if (requestBody == null) {
|
||||||
|
resource.post((HttpEntity) null);
|
||||||
|
} else {
|
||||||
|
resource.post(requestBody);
|
||||||
|
}
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
invokeHandleError(delegate, e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate resource callbacks into request callbacks invoked on the provided
|
||||||
|
* executor.
|
||||||
|
* <p>
|
||||||
|
* Override <code>handleSuccess</code> to parse the body of the resource
|
||||||
|
* request and call the request callback. <code>handleSuccess</code> is
|
||||||
|
* invoked via the executor, so you don't need to delegate further.
|
||||||
|
*/
|
||||||
|
protected abstract class ResourceDelegate<T> extends BaseResourceDelegate {
|
||||||
|
protected abstract void handleSuccess(final int status, HttpResponse response, final ExtendedJSONObject body);
|
||||||
|
|
||||||
|
protected final RequestDelegate<T> delegate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a delegate for an un-authenticated resource.
|
||||||
|
*/
|
||||||
|
public ResourceDelegate(final Resource resource, final RequestDelegate<T> delegate) {
|
||||||
|
super(resource);
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthHeaderProvider getAuthHeaderProvider() {
|
||||||
|
return super.getAuthHeaderProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUserAgent() {
|
||||||
|
return FxAccountConstants.USER_AGENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleHttpResponse(HttpResponse response) {
|
||||||
|
try {
|
||||||
|
final int status = validateResponse(response);
|
||||||
|
invokeHandleSuccess(status, response);
|
||||||
|
} catch (FxAccountAbstractClientRemoteException e) {
|
||||||
|
invokeHandleFailure(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void invokeHandleFailure(final FxAccountAbstractClientRemoteException e) {
|
||||||
|
executor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
delegate.handleFailure(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void invokeHandleSuccess(final int status, final HttpResponse response) {
|
||||||
|
executor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
ExtendedJSONObject body = new SyncResponse(response).jsonObjectBody();
|
||||||
|
ResourceDelegate.this.handleSuccess(status, response, body);
|
||||||
|
} catch (Exception e) {
|
||||||
|
delegate.handleError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleHttpProtocolException(final ClientProtocolException e) {
|
||||||
|
invokeHandleError(delegate, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleHttpIOException(IOException e) {
|
||||||
|
invokeHandleError(delegate, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleTransportException(GeneralSecurityException e) {
|
||||||
|
invokeHandleError(delegate, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
|
||||||
|
super.addHeaders(request, client);
|
||||||
|
|
||||||
|
// The basics.
|
||||||
|
final Locale locale = Locale.getDefault();
|
||||||
|
request.addHeader(HttpHeaders.ACCEPT_LANGUAGE, Utils.getLanguageTag(locale));
|
||||||
|
request.addHeader(HttpHeaders.ACCEPT, ACCEPT_HEADER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
package org.mozilla.gecko.background.fxa.oauth;
|
||||||
|
|
||||||
|
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||||
|
import org.mozilla.gecko.sync.HTTPFailureException;
|
||||||
|
import org.mozilla.gecko.sync.net.SyncStorageResponse;
|
||||||
|
|
||||||
|
import ch.boye.httpclientandroidlib.HttpResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From <a href="https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md">https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md</a>.
|
||||||
|
*/
|
||||||
|
public class FxAccountAbstractClientException extends Exception {
|
||||||
|
private static final long serialVersionUID = 1953459541558266597L;
|
||||||
|
|
||||||
|
public FxAccountAbstractClientException(String detailMessage) {
|
||||||
|
super(detailMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FxAccountAbstractClientException(Exception e) {
|
||||||
|
super(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FxAccountAbstractClientRemoteException extends FxAccountAbstractClientException {
|
||||||
|
private static final long serialVersionUID = 1209313149952001097L;
|
||||||
|
|
||||||
|
public final HttpResponse response;
|
||||||
|
public final long httpStatusCode;
|
||||||
|
public final long apiErrorNumber;
|
||||||
|
public final String error;
|
||||||
|
public final String message;
|
||||||
|
public final ExtendedJSONObject body;
|
||||||
|
|
||||||
|
public FxAccountAbstractClientRemoteException(HttpResponse response, long httpStatusCode, long apiErrorNumber, String error, String message, ExtendedJSONObject body) {
|
||||||
|
super(new HTTPFailureException(new SyncStorageResponse(response)));
|
||||||
|
if (body == null) {
|
||||||
|
throw new IllegalArgumentException("body must not be null");
|
||||||
|
}
|
||||||
|
this.response = response;
|
||||||
|
this.httpStatusCode = httpStatusCode;
|
||||||
|
this.apiErrorNumber = apiErrorNumber;
|
||||||
|
this.error = error;
|
||||||
|
this.message = message;
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "<FxAccountAbstractClientRemoteException " + this.httpStatusCode + " [" + this.apiErrorNumber + "]: " + this.message + ">";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FxAccountAbstractClientMalformedResponseException extends FxAccountAbstractClientRemoteException {
|
||||||
|
private static final long serialVersionUID = 1209313149952001098L;
|
||||||
|
|
||||||
|
public FxAccountAbstractClientMalformedResponseException(HttpResponse response) {
|
||||||
|
super(response, 0, FxAccountOAuthRemoteError.UNKNOWN_ERROR, "Response malformed", "Response malformed", new ExtendedJSONObject());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
package org.mozilla.gecko.background.fxa.oauth;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||||
|
import org.mozilla.gecko.sync.net.BaseResource;
|
||||||
|
|
||||||
|
import ch.boye.httpclientandroidlib.HttpResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Talk to an fxa-oauth-server to get "implicitly granted" OAuth tokens.
|
||||||
|
* <p>
|
||||||
|
* To use this client, you will need a pre-allocated fxa-oauth-server
|
||||||
|
* "client_id" with special "implicit grant" permissions.
|
||||||
|
* <p>
|
||||||
|
* This client was written against the API documented at <a href="https://github.com/mozilla/fxa-oauth-server/blob/41538990df9e91158558ae5a8115194383ac3b05/docs/api.md">https://github.com/mozilla/fxa-oauth-server/blob/41538990df9e91158558ae5a8115194383ac3b05/docs/api.md</a>.
|
||||||
|
*/
|
||||||
|
public class FxAccountOAuthClient10 extends FxAccountAbstractClient {
|
||||||
|
protected static final String LOG_TAG = FxAccountOAuthClient10.class.getSimpleName();
|
||||||
|
|
||||||
|
protected static final String AUTHORIZATION_RESPONSE_TYPE = "token";
|
||||||
|
|
||||||
|
protected static final String JSON_KEY_ACCESS_TOKEN = "access_token";
|
||||||
|
protected static final String JSON_KEY_ASSERTION = "assertion";
|
||||||
|
protected static final String JSON_KEY_CLIENT_ID = "client_id";
|
||||||
|
protected static final String JSON_KEY_RESPONSE_TYPE = "response_type";
|
||||||
|
protected static final String JSON_KEY_SCOPE = "scope";
|
||||||
|
protected static final String JSON_KEY_STATE = "state";
|
||||||
|
protected static final String JSON_KEY_TOKEN_TYPE = "token_type";
|
||||||
|
|
||||||
|
// access_token: A string that can be used for authorized requests to service providers.
|
||||||
|
// scope: A string of space-separated permissions that this token has. May differ from requested scopes, since user can deny permissions.
|
||||||
|
// token_type: A string representing the token type. Currently will always be "bearer".
|
||||||
|
protected static final String[] AUTHORIZATION_RESPONSE_REQUIRED_STRING_FIELDS = new String[] { JSON_KEY_ACCESS_TOKEN, JSON_KEY_SCOPE, JSON_KEY_TOKEN_TYPE };
|
||||||
|
|
||||||
|
public FxAccountOAuthClient10(String serverURI, Executor executor) {
|
||||||
|
super(serverURI, executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thin container for an authorization response.
|
||||||
|
*/
|
||||||
|
public static class AuthorizationResponse {
|
||||||
|
public final String access_token;
|
||||||
|
public final String token_type;
|
||||||
|
public final String scope;
|
||||||
|
|
||||||
|
public AuthorizationResponse(String access_token, String token_type, String scope) {
|
||||||
|
this.access_token = access_token;
|
||||||
|
this.token_type = token_type;
|
||||||
|
this.scope = scope;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void authorization(String client_id, String assertion, String state, String scope,
|
||||||
|
RequestDelegate<AuthorizationResponse> delegate) {
|
||||||
|
final BaseResource resource;
|
||||||
|
try {
|
||||||
|
resource = new BaseResource(new URI(serverURI + "authorization"));
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
invokeHandleError(delegate, e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resource.delegate = new ResourceDelegate<AuthorizationResponse>(resource, delegate) {
|
||||||
|
@Override
|
||||||
|
public void handleSuccess(int status, HttpResponse response, ExtendedJSONObject body) {
|
||||||
|
try {
|
||||||
|
body.throwIfFieldsMissingOrMisTyped(AUTHORIZATION_RESPONSE_REQUIRED_STRING_FIELDS, String.class);
|
||||||
|
String access_token = body.getString(JSON_KEY_ACCESS_TOKEN);
|
||||||
|
String token_type = body.getString(JSON_KEY_TOKEN_TYPE);
|
||||||
|
String scope = body.getString(JSON_KEY_SCOPE);
|
||||||
|
delegate.handleSuccess(new AuthorizationResponse(access_token, token_type, scope));
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
delegate.handleError(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
final ExtendedJSONObject requestBody = new ExtendedJSONObject();
|
||||||
|
requestBody.put(JSON_KEY_RESPONSE_TYPE, AUTHORIZATION_RESPONSE_TYPE);
|
||||||
|
requestBody.put(JSON_KEY_CLIENT_ID, client_id);
|
||||||
|
requestBody.put(JSON_KEY_ASSERTION, assertion);
|
||||||
|
if (scope != null) {
|
||||||
|
requestBody.put(JSON_KEY_SCOPE, scope);
|
||||||
|
}
|
||||||
|
if (state != null) {
|
||||||
|
requestBody.put(JSON_KEY_STATE, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
post(resource, requestBody, delegate);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
package org.mozilla.gecko.background.fxa.oauth;
|
||||||
|
|
||||||
|
public interface FxAccountOAuthRemoteError {
|
||||||
|
public static final int ATTEMPT_TO_CREATE_AN_ACCOUNT_THAT_ALREADY_EXISTS = 101;
|
||||||
|
public static final int UNKNOWN_CLIENT_ID = 101;
|
||||||
|
public static final int INCORRECT_CLIENT_SECRET = 102;
|
||||||
|
public static final int REDIRECT_URI_DOES_NOT_MATCH_REGISTERED_VALUE = 103;
|
||||||
|
public static final int INVALID_FXA_ASSERTION = 104;
|
||||||
|
public static final int UNKNOWN_CODE = 105;
|
||||||
|
public static final int INCORRECT_CODE = 106;
|
||||||
|
public static final int EXPIRED_CODE = 107;
|
||||||
|
public static final int INVALID_TOKEN = 108;
|
||||||
|
public static final int INVALID_REQUEST_PARAMETER = 109;
|
||||||
|
public static final int UNKNOWN_ERROR = 999;
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
package org.mozilla.gecko.background.fxa.profile;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
import org.mozilla.gecko.background.fxa.oauth.FxAccountAbstractClient;
|
||||||
|
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||||
|
import org.mozilla.gecko.sync.net.AuthHeaderProvider;
|
||||||
|
import org.mozilla.gecko.sync.net.BaseResource;
|
||||||
|
import org.mozilla.gecko.sync.net.BearerAuthHeaderProvider;
|
||||||
|
|
||||||
|
import ch.boye.httpclientandroidlib.HttpResponse;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Talk to an fxa-profile-server to get profile information like name, age, gender, and avatar image.
|
||||||
|
* <p>
|
||||||
|
* This client was written against the API documented at <a href="https://github.com/mozilla/fxa-profile-server/blob/0c065619f5a2e867f813a343b4c67da3fe2c82a4/docs/API.md">https://github.com/mozilla/fxa-profile-server/blob/0c065619f5a2e867f813a343b4c67da3fe2c82a4/docs/API.md</a>.
|
||||||
|
*/
|
||||||
|
public class FxAccountProfileClient10 extends FxAccountAbstractClient {
|
||||||
|
public FxAccountProfileClient10(String serverURI, Executor executor) {
|
||||||
|
super(serverURI, executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void profile(final String token, RequestDelegate<ExtendedJSONObject> delegate) {
|
||||||
|
BaseResource resource;
|
||||||
|
try {
|
||||||
|
resource = new BaseResource(new URI(serverURI + "profile"));
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
invokeHandleError(delegate, e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resource.delegate = new ResourceDelegate<ExtendedJSONObject>(resource, delegate) {
|
||||||
|
@Override
|
||||||
|
public AuthHeaderProvider getAuthHeaderProvider() {
|
||||||
|
return new BearerAuthHeaderProvider(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleSuccess(int status, HttpResponse response, ExtendedJSONObject body) {
|
||||||
|
try {
|
||||||
|
delegate.handleSuccess(body);
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
delegate.handleError(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
resource.get();
|
||||||
|
}
|
||||||
|
}
|
|
@ -186,8 +186,8 @@ public class JSONWebTokenUtils {
|
||||||
System.out.println("Malformed certificate -- got exception trying to dump contents.");
|
System.out.println("Malformed certificate -- got exception trying to dump contents.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
System.out.println("certificate header: " + c.getString("header"));
|
System.out.println("certificate header: " + c.getObject("header").toJSONString());
|
||||||
System.out.println("certificate payload: " + c.getString("payload"));
|
System.out.println("certificate payload: " + c.getObject("payload").toJSONString());
|
||||||
System.out.println("certificate signature: " + c.getString("signature"));
|
System.out.println("certificate signature: " + c.getString("signature"));
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -244,8 +244,8 @@ public class JSONWebTokenUtils {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
dumpCertificate(a.getString("certificate"));
|
dumpCertificate(a.getString("certificate"));
|
||||||
System.out.println("assertion header: " + a.getString("header"));
|
System.out.println("assertion header: " + a.getObject("header").toJSONString());
|
||||||
System.out.println("assertion payload: " + a.getString("payload"));
|
System.out.println("assertion payload: " + a.getObject("payload").toJSONString());
|
||||||
System.out.println("assertion signature: " + a.getString("signature"));
|
System.out.println("assertion signature: " + a.getString("signature"));
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -5,29 +5,23 @@
|
||||||
package org.mozilla.gecko.browserid.verifier;
|
package org.mozilla.gecko.browserid.verifier;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.mozilla.gecko.background.common.log.Logger;
|
import org.mozilla.gecko.background.common.log.Logger;
|
||||||
import org.mozilla.gecko.browserid.verifier.BrowserIDVerifierException.BrowserIDVerifierErrorResponseException;
|
import org.mozilla.gecko.browserid.verifier.BrowserIDVerifierException.BrowserIDVerifierErrorResponseException;
|
||||||
import org.mozilla.gecko.browserid.verifier.BrowserIDVerifierException.BrowserIDVerifierMalformedResponseException;
|
import org.mozilla.gecko.browserid.verifier.BrowserIDVerifierException.BrowserIDVerifierMalformedResponseException;
|
||||||
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||||
import org.mozilla.gecko.sync.net.BaseResource;
|
|
||||||
import org.mozilla.gecko.sync.net.BaseResourceDelegate;
|
import org.mozilla.gecko.sync.net.BaseResourceDelegate;
|
||||||
import org.mozilla.gecko.sync.net.Resource;
|
import org.mozilla.gecko.sync.net.Resource;
|
||||||
import org.mozilla.gecko.sync.net.SyncResponse;
|
import org.mozilla.gecko.sync.net.SyncResponse;
|
||||||
|
|
||||||
import ch.boye.httpclientandroidlib.HttpResponse;
|
import ch.boye.httpclientandroidlib.HttpResponse;
|
||||||
import ch.boye.httpclientandroidlib.NameValuePair;
|
|
||||||
import ch.boye.httpclientandroidlib.client.ClientProtocolException;
|
import ch.boye.httpclientandroidlib.client.ClientProtocolException;
|
||||||
import ch.boye.httpclientandroidlib.client.entity.UrlEncodedFormEntity;
|
|
||||||
import ch.boye.httpclientandroidlib.message.BasicNameValuePair;
|
|
||||||
|
|
||||||
public class BrowserIDRemoteVerifierClient implements BrowserIDVerifierClient {
|
public abstract class AbstractBrowserIDRemoteVerifierClient implements BrowserIDVerifierClient {
|
||||||
|
public static final String LOG_TAG = AbstractBrowserIDRemoteVerifierClient.class.getSimpleName();
|
||||||
|
|
||||||
protected static class RemoteVerifierResourceDelegate extends BaseResourceDelegate {
|
protected static class RemoteVerifierResourceDelegate extends BaseResourceDelegate {
|
||||||
private final BrowserIDVerifierDelegate delegate;
|
private final BrowserIDVerifierDelegate delegate;
|
||||||
|
|
||||||
|
@ -93,44 +87,9 @@ public class BrowserIDRemoteVerifierClient implements BrowserIDVerifierClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String LOG_TAG = "BrowserIDRemoteVerifierClient";
|
|
||||||
|
|
||||||
public static final String DEFAULT_VERIFIER_URL = "https://verifier.login.persona.org/verify";
|
|
||||||
|
|
||||||
protected final URI verifierUri;
|
protected final URI verifierUri;
|
||||||
|
|
||||||
public BrowserIDRemoteVerifierClient(URI verifierUri) {
|
public AbstractBrowserIDRemoteVerifierClient(URI verifierUri) {
|
||||||
this.verifierUri = verifierUri;
|
this.verifierUri = verifierUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BrowserIDRemoteVerifierClient() throws URISyntaxException {
|
|
||||||
this.verifierUri = new URI(DEFAULT_VERIFIER_URL);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void verify(String audience, String assertion, final BrowserIDVerifierDelegate delegate) {
|
|
||||||
if (audience == null) {
|
|
||||||
throw new IllegalArgumentException("audience cannot be null.");
|
|
||||||
}
|
|
||||||
if (assertion == null) {
|
|
||||||
throw new IllegalArgumentException("assertion cannot be null.");
|
|
||||||
}
|
|
||||||
if (delegate == null) {
|
|
||||||
throw new IllegalArgumentException("delegate cannot be null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseResource r = new BaseResource(verifierUri);
|
|
||||||
|
|
||||||
r.delegate = new RemoteVerifierResourceDelegate(r, delegate);
|
|
||||||
|
|
||||||
List<NameValuePair> nvps = Arrays.asList(new NameValuePair[] {
|
|
||||||
new BasicNameValuePair("audience", audience),
|
|
||||||
new BasicNameValuePair("assertion", assertion) });
|
|
||||||
|
|
||||||
try {
|
|
||||||
r.post(new UrlEncodedFormEntity(nvps, "UTF-8"));
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
delegate.handleError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
package org.mozilla.gecko.browserid.verifier;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.mozilla.gecko.sync.net.BaseResource;
|
||||||
|
|
||||||
|
import ch.boye.httpclientandroidlib.NameValuePair;
|
||||||
|
import ch.boye.httpclientandroidlib.client.entity.UrlEncodedFormEntity;
|
||||||
|
import ch.boye.httpclientandroidlib.message.BasicNameValuePair;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The verifier protocol changed: version 1 posts form-encoded data; version 2
|
||||||
|
* posts JSON data.
|
||||||
|
*/
|
||||||
|
public class BrowserIDRemoteVerifierClient10 extends AbstractBrowserIDRemoteVerifierClient {
|
||||||
|
public static final String LOG_TAG = BrowserIDRemoteVerifierClient10.class.getSimpleName();
|
||||||
|
|
||||||
|
public static final String DEFAULT_VERIFIER_URL = "https://verifier.login.persona.org/verify";
|
||||||
|
|
||||||
|
public BrowserIDRemoteVerifierClient10() throws URISyntaxException {
|
||||||
|
super(new URI(DEFAULT_VERIFIER_URL));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BrowserIDRemoteVerifierClient10(URI verifierUri) {
|
||||||
|
super(verifierUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void verify(String audience, String assertion, final BrowserIDVerifierDelegate delegate) {
|
||||||
|
if (audience == null) {
|
||||||
|
throw new IllegalArgumentException("audience cannot be null.");
|
||||||
|
}
|
||||||
|
if (assertion == null) {
|
||||||
|
throw new IllegalArgumentException("assertion cannot be null.");
|
||||||
|
}
|
||||||
|
if (delegate == null) {
|
||||||
|
throw new IllegalArgumentException("delegate cannot be null.");
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseResource r = new BaseResource(verifierUri);
|
||||||
|
|
||||||
|
r.delegate = new RemoteVerifierResourceDelegate(r, delegate);
|
||||||
|
|
||||||
|
List<NameValuePair> nvps = Arrays.asList(new NameValuePair[] {
|
||||||
|
new BasicNameValuePair("audience", audience),
|
||||||
|
new BasicNameValuePair("assertion", assertion) });
|
||||||
|
|
||||||
|
try {
|
||||||
|
r.post(new UrlEncodedFormEntity(nvps, "UTF-8"));
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
delegate.handleError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
package org.mozilla.gecko.browserid.verifier;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
|
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||||
|
import org.mozilla.gecko.sync.net.BaseResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The verifier protocol changed: version 1 posts form-encoded data; version 2
|
||||||
|
* posts JSON data.
|
||||||
|
*/
|
||||||
|
public class BrowserIDRemoteVerifierClient20 extends AbstractBrowserIDRemoteVerifierClient {
|
||||||
|
public static final String LOG_TAG = BrowserIDRemoteVerifierClient20.class.getSimpleName();
|
||||||
|
|
||||||
|
public static final String DEFAULT_VERIFIER_URL = "https://verifier.accounts.firefox.com/v2";
|
||||||
|
|
||||||
|
protected static final String JSON_KEY_ASSERTION = "assertion";
|
||||||
|
protected static final String JSON_KEY_AUDIENCE = "audience";
|
||||||
|
|
||||||
|
public BrowserIDRemoteVerifierClient20() throws URISyntaxException {
|
||||||
|
super(new URI(DEFAULT_VERIFIER_URL));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BrowserIDRemoteVerifierClient20(URI verifierUri) {
|
||||||
|
super(verifierUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void verify(String audience, String assertion, final BrowserIDVerifierDelegate delegate) {
|
||||||
|
if (audience == null) {
|
||||||
|
throw new IllegalArgumentException("audience cannot be null.");
|
||||||
|
}
|
||||||
|
if (assertion == null) {
|
||||||
|
throw new IllegalArgumentException("assertion cannot be null.");
|
||||||
|
}
|
||||||
|
if (delegate == null) {
|
||||||
|
throw new IllegalArgumentException("delegate cannot be null.");
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseResource r = new BaseResource(verifierUri);
|
||||||
|
r.delegate = new RemoteVerifierResourceDelegate(r, delegate);
|
||||||
|
|
||||||
|
final ExtendedJSONObject requestBody = new ExtendedJSONObject();
|
||||||
|
requestBody.put(JSON_KEY_AUDIENCE, audience);
|
||||||
|
requestBody.put(JSON_KEY_ASSERTION, assertion);
|
||||||
|
|
||||||
|
try {
|
||||||
|
r.post(requestBody);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
delegate.handleError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -259,17 +259,4 @@ public class LocalTabsAccessor implements TabsAccessor {
|
||||||
private boolean isFilteredURL(String url) {
|
private boolean isFilteredURL(String url) {
|
||||||
return FILTERED_URL_PATTERN.matcher(url).lookingAt();
|
return FILTERED_URL_PATTERN.matcher(url).lookingAt();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a relative "Last synced" time span for the given tab record.
|
|
||||||
*
|
|
||||||
* @param now local time.
|
|
||||||
* @param time to format string for.
|
|
||||||
* @return string describing time span
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getLastSyncedString(Context context, long now, long time) {
|
|
||||||
final CharSequence relativeTimeSpanString = DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS);
|
|
||||||
return context.getResources().getString(R.string.remote_tabs_last_synced, relativeTimeSpanString);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,10 +119,6 @@ class StubTabsAccessor implements TabsAccessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void persistLocalTabs(final ContentResolver cr, final Iterable<Tab> tabs) { }
|
public synchronized void persistLocalTabs(final ContentResolver cr, final Iterable<Tab> tabs) { }
|
||||||
|
|
||||||
public String getLastSyncedString(Context context, long now, long time) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -23,5 +23,4 @@ public interface TabsAccessor {
|
||||||
public void getTabs(final Context context, final OnQueryTabsCompleteListener listener);
|
public void getTabs(final Context context, final OnQueryTabsCompleteListener listener);
|
||||||
public void getTabs(final Context context, final int limit, final OnQueryTabsCompleteListener listener);
|
public void getTabs(final Context context, final int limit, final OnQueryTabsCompleteListener listener);
|
||||||
public void persistLocalTabs(final ContentResolver cr, final Iterable<Tab> tabs);
|
public void persistLocalTabs(final ContentResolver cr, final Iterable<Tab> tabs);
|
||||||
public String getLastSyncedString(Context context, long now, long time);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,10 +51,6 @@ class JavaPanZoomController
|
||||||
// Animation stops is the velocity is below this threshold when flinging.
|
// Animation stops is the velocity is below this threshold when flinging.
|
||||||
private static final float FLING_STOPPED_THRESHOLD = 0.1f;
|
private static final float FLING_STOPPED_THRESHOLD = 0.1f;
|
||||||
|
|
||||||
// The distance the user has to pan before we recognize it as such (e.g. to avoid 1-pixel pans
|
|
||||||
// between the touch-down and touch-up of a click). In units of density-independent pixels.
|
|
||||||
public static final float PAN_THRESHOLD = 1/16f * GeckoAppShell.getDpi();
|
|
||||||
|
|
||||||
// Angle from axis within which we stay axis-locked
|
// Angle from axis within which we stay axis-locked
|
||||||
private static final double AXIS_LOCK_ANGLE = Math.PI / 6.0; // 30 degrees
|
private static final double AXIS_LOCK_ANGLE = Math.PI / 6.0; // 30 degrees
|
||||||
|
|
||||||
|
@ -479,7 +475,7 @@ class JavaPanZoomController
|
||||||
if (mTarget.getFullScreenState() == FullScreenState.NON_ROOT_ELEMENT && !mSubscroller.scrolling()) {
|
if (mTarget.getFullScreenState() == FullScreenState.NON_ROOT_ELEMENT && !mSubscroller.scrolling()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (panDistance(event) < PAN_THRESHOLD) {
|
if (panDistance(event) < PanZoomController.PAN_THRESHOLD) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cancelTouch();
|
cancelTouch();
|
||||||
|
|
|
@ -36,7 +36,7 @@ class HomeConfigPrefsBackend implements HomeConfigBackend {
|
||||||
private static final String LOGTAG = "GeckoHomeConfigBackend";
|
private static final String LOGTAG = "GeckoHomeConfigBackend";
|
||||||
|
|
||||||
// Increment this to trigger a migration.
|
// Increment this to trigger a migration.
|
||||||
private static final int VERSION = 2;
|
private static final int VERSION = 3;
|
||||||
|
|
||||||
// This key was originally used to store only an array of panel configs.
|
// This key was originally used to store only an array of panel configs.
|
||||||
private static final String PREFS_CONFIG_KEY_OLD = "home_panels";
|
private static final String PREFS_CONFIG_KEY_OLD = "home_panels";
|
||||||
|
@ -73,12 +73,7 @@ class HomeConfigPrefsBackend implements HomeConfigBackend {
|
||||||
EnumSet.of(PanelConfig.Flags.DEFAULT_PANEL)));
|
EnumSet.of(PanelConfig.Flags.DEFAULT_PANEL)));
|
||||||
|
|
||||||
panelConfigs.add(createBuiltinPanelConfig(mContext, PanelType.BOOKMARKS));
|
panelConfigs.add(createBuiltinPanelConfig(mContext, PanelType.BOOKMARKS));
|
||||||
|
panelConfigs.add(createBuiltinPanelConfig(mContext, PanelType.READING_LIST));
|
||||||
// We disable reader mode support on low memory devices. Hence the
|
|
||||||
// reading list panel should not show up on such devices.
|
|
||||||
if (!HardwareUtils.isLowMemoryPlatform()) {
|
|
||||||
panelConfigs.add(createBuiltinPanelConfig(mContext, PanelType.READING_LIST));
|
|
||||||
}
|
|
||||||
|
|
||||||
final PanelConfig historyEntry = createBuiltinPanelConfig(mContext, PanelType.HISTORY);
|
final PanelConfig historyEntry = createBuiltinPanelConfig(mContext, PanelType.HISTORY);
|
||||||
final PanelConfig recentTabsEntry = createBuiltinPanelConfig(mContext, PanelType.RECENT_TABS);
|
final PanelConfig recentTabsEntry = createBuiltinPanelConfig(mContext, PanelType.RECENT_TABS);
|
||||||
|
@ -173,6 +168,31 @@ class HomeConfigPrefsBackend implements HomeConfigBackend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks to see if the reading list panel already exists.
|
||||||
|
*
|
||||||
|
* @param jsonPanels JSONArray array representing the curent set of panel configs.
|
||||||
|
*
|
||||||
|
* @return boolean Whether or not the reading list panel exists.
|
||||||
|
*/
|
||||||
|
private static boolean readingListPanelExists(JSONArray jsonPanels) {
|
||||||
|
final int count = jsonPanels.length();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
try {
|
||||||
|
final JSONObject jsonPanelConfig = jsonPanels.getJSONObject(i);
|
||||||
|
final PanelConfig panelConfig = new PanelConfig(jsonPanelConfig);
|
||||||
|
if (panelConfig.getType() == PanelType.READING_LIST) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// It's okay to ignore this exception, since an invalid reading list
|
||||||
|
// panel config is equivalent to no reading list panel.
|
||||||
|
Log.e(LOGTAG, "Exception loading PanelConfig from JSON", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrates JSON config data storage.
|
* Migrates JSON config data storage.
|
||||||
*
|
*
|
||||||
|
@ -231,6 +251,19 @@ class HomeConfigPrefsBackend implements HomeConfigBackend {
|
||||||
addBuiltinPanelConfig(context, jsonPanels,
|
addBuiltinPanelConfig(context, jsonPanels,
|
||||||
PanelType.REMOTE_TABS, Position.FRONT, Position.BACK);
|
PanelType.REMOTE_TABS, Position.FRONT, Position.BACK);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
// Add the "Reading List" panel if it does not exist. At one time,
|
||||||
|
// the Reading List panel was shown only to devices that were not
|
||||||
|
// considered "low memory". Now, we expose the panel to all devices.
|
||||||
|
// This migration should only occur for "low memory" devices.
|
||||||
|
// Note: This will not agree with the default configuration, which
|
||||||
|
// has REMOTE_TABS after READING_LIST on some devices.
|
||||||
|
if (!readingListPanelExists(jsonPanels)) {
|
||||||
|
addBuiltinPanelConfig(context, jsonPanels,
|
||||||
|
PanelType.READING_LIST, Position.BACK, Position.BACK);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<!ENTITY no_space_to_start_error "There is not enough space available for &brandShortName; to start.">
|
<!ENTITY no_space_to_start_error "There is not enough space available for &brandShortName; to start.">
|
||||||
<!ENTITY error_loading_file "An error occurred when trying to load files required to run &brandShortName;">
|
<!ENTITY error_loading_file "An error occurred when trying to load files required to run &brandShortName;">
|
||||||
|
|
||||||
<!ENTITY onboard_start_message "Welcome to &brandShortName;!">
|
<!ENTITY onboard_start_message2 "Welcome to &brandShortName;">
|
||||||
<!ENTITY onboard_start_subtext "Committed to you, your privacy, and an Open Web">
|
<!ENTITY onboard_start_subtext2 "More privacy features and ways to customize than ever.">
|
||||||
<!ENTITY onboard_start_button_account "Sign in to &brandShortName;">
|
<!ENTITY onboard_start_button_account "Sign in to &brandShortName;">
|
||||||
<!ENTITY onboard_start_button_browser "Start Browsing">
|
<!ENTITY onboard_start_button_browser "Start Browsing">
|
||||||
|
|
||||||
|
@ -575,6 +575,8 @@ just addresses the organization to follow, e.g. "This site is run by " -->
|
||||||
"Last synced" is one of the user's other Sync clients, typically Firefox on
|
"Last synced" is one of the user's other Sync clients, typically Firefox on
|
||||||
their desktop or laptop.-->
|
their desktop or laptop.-->
|
||||||
<!ENTITY remote_tabs_last_synced "Last synced: &formatS;">
|
<!ENTITY remote_tabs_last_synced "Last synced: &formatS;">
|
||||||
|
<!-- Localization note: Used when the sync has not happend yet, showed in place of a date -->
|
||||||
|
<!ENTITY remote_tabs_never_synced "Last synced: never">
|
||||||
|
|
||||||
<!-- Find-In-Page strings -->
|
<!-- Find-In-Page strings -->
|
||||||
<!-- LOCALIZATION NOTE (find_matchcase): This is meant to appear as an icon that changes color
|
<!-- LOCALIZATION NOTE (find_matchcase): This is meant to appear as an icon that changes color
|
||||||
|
|
|
@ -669,9 +669,10 @@ if not CONFIG['MOZILLA_OFFICIAL']:
|
||||||
'org/lucasr/dspec/RawResource.java'
|
'org/lucasr/dspec/RawResource.java'
|
||||||
] ]
|
] ]
|
||||||
|
|
||||||
|
# Putting branding earlier allows branders to override default resources.
|
||||||
ANDROID_RES_DIRS += [
|
ANDROID_RES_DIRS += [
|
||||||
SRCDIR + '/resources',
|
|
||||||
TOPSRCDIR + '/' + CONFIG['MOZ_BRANDING_DIRECTORY'] + '/res',
|
TOPSRCDIR + '/' + CONFIG['MOZ_BRANDING_DIRECTORY'] + '/res',
|
||||||
|
SRCDIR + '/resources',
|
||||||
OBJDIR + '/res',
|
OBJDIR + '/res',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ import org.mozilla.gecko.overlays.service.sharemethods.SendTab;
|
||||||
import org.mozilla.gecko.overlays.service.sharemethods.ShareMethod;
|
import org.mozilla.gecko.overlays.service.sharemethods.ShareMethod;
|
||||||
import org.mozilla.gecko.sync.setup.activities.WebURLFinder;
|
import org.mozilla.gecko.sync.setup.activities.WebURLFinder;
|
||||||
import org.mozilla.gecko.mozglue.ContextUtils;
|
import org.mozilla.gecko.mozglue.ContextUtils;
|
||||||
import org.mozilla.gecko.util.HardwareUtils;
|
|
||||||
import org.mozilla.gecko.util.ThreadUtils;
|
import org.mozilla.gecko.util.ThreadUtils;
|
||||||
import org.mozilla.gecko.util.UIAsyncTask;
|
import org.mozilla.gecko.util.UIAsyncTask;
|
||||||
|
|
||||||
|
@ -214,14 +213,8 @@ public class ShareDialog extends Locales.LocaleAwareActivity implements SendTabT
|
||||||
sendTabList.setAdapter(adapter);
|
sendTabList.setAdapter(adapter);
|
||||||
sendTabList.setSendTabTargetSelectedListener(this);
|
sendTabList.setSendTabTargetSelectedListener(this);
|
||||||
|
|
||||||
// If we're a low memory device, just hide the reading list button. Otherwise, configure it.
|
|
||||||
final OverlayDialogButton readinglistBtn = (OverlayDialogButton) findViewById(R.id.overlay_share_reading_list_btn);
|
final OverlayDialogButton readinglistBtn = (OverlayDialogButton) findViewById(R.id.overlay_share_reading_list_btn);
|
||||||
|
|
||||||
if (HardwareUtils.isLowMemoryPlatform()) {
|
|
||||||
readinglistBtn.setVisibility(View.GONE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String readingListEnabledLabel = resources.getString(R.string.overlay_share_reading_list_btn_label);
|
final String readingListEnabledLabel = resources.getString(R.string.overlay_share_reading_list_btn_label);
|
||||||
final Drawable readingListEnabledIcon = resources.getDrawable(R.drawable.overlay_readinglist_icon);
|
final Drawable readingListEnabledIcon = resources.getDrawable(R.drawable.overlay_readinglist_icon);
|
||||||
readinglistBtn.setEnabledLabelAndIcon(readingListEnabledLabel, readingListEnabledIcon);
|
readinglistBtn.setEnabledLabelAndIcon(readingListEnabledLabel, readingListEnabledIcon);
|
||||||
|
|
|
@ -38,8 +38,8 @@
|
||||||
<string name="no_space_to_start_error">&no_space_to_start_error;</string>
|
<string name="no_space_to_start_error">&no_space_to_start_error;</string>
|
||||||
<string name="error_loading_file">&error_loading_file;</string>
|
<string name="error_loading_file">&error_loading_file;</string>
|
||||||
|
|
||||||
<string name="firstrun_welcome_message">&onboard_start_message;</string>
|
<string name="firstrun_welcome_message">&onboard_start_message2;</string>
|
||||||
<string name="firstrun_welcome_subtext">&onboard_start_subtext;</string>
|
<string name="firstrun_welcome_subtext">&onboard_start_subtext2;</string>
|
||||||
<string name="firstrun_welcome_button_account">&onboard_start_button_account;</string>
|
<string name="firstrun_welcome_button_account">&onboard_start_button_account;</string>
|
||||||
<string name="firstrun_welcome_button_browser">&onboard_start_button_browser;</string>
|
<string name="firstrun_welcome_button_browser">&onboard_start_button_browser;</string>
|
||||||
<string name="firstrun_empty_contentDescription"></string>
|
<string name="firstrun_empty_contentDescription"></string>
|
||||||
|
@ -387,6 +387,7 @@
|
||||||
<string name="remote_tabs_panel_moved_title">&remote_tabs_panel_moved_title;</string>
|
<string name="remote_tabs_panel_moved_title">&remote_tabs_panel_moved_title;</string>
|
||||||
<string name="remote_tabs_panel_moved_desc">&remote_tabs_panel_moved_desc;</string>
|
<string name="remote_tabs_panel_moved_desc">&remote_tabs_panel_moved_desc;</string>
|
||||||
<string name="remote_tabs_panel_moved_link">&remote_tabs_panel_moved_link;</string>
|
<string name="remote_tabs_panel_moved_link">&remote_tabs_panel_moved_link;</string>
|
||||||
|
<string name="remote_tabs_never_synced">&remote_tabs_never_synced;</string>
|
||||||
|
|
||||||
<string name="filepicker_title">&filepicker_title;</string>
|
<string name="filepicker_title">&filepicker_title;</string>
|
||||||
<string name="filepicker_audio_title">&filepicker_audio_title;</string>
|
<string name="filepicker_audio_title">&filepicker_audio_title;</string>
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
package org.mozilla.gecko.sync.net;
|
||||||
|
|
||||||
|
import ch.boye.httpclientandroidlib.Header;
|
||||||
|
import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase;
|
||||||
|
import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient;
|
||||||
|
import ch.boye.httpclientandroidlib.message.BasicHeader;
|
||||||
|
import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An <code>AuthHeaderProvider</code> that returns an Authorization header for
|
||||||
|
* bearer tokens, adding a simple prefix.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractBearerTokenAuthHeaderProvider implements AuthHeaderProvider {
|
||||||
|
protected final String header;
|
||||||
|
|
||||||
|
public AbstractBearerTokenAuthHeaderProvider(String token) {
|
||||||
|
if (token == null) {
|
||||||
|
throw new IllegalArgumentException("token must not be null.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.header = getPrefix() + " " + token;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String getPrefix();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Header getAuthHeader(HttpRequestBase request, BasicHttpContext context, DefaultHttpClient client) {
|
||||||
|
return new BasicHeader("Authorization", header);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
package org.mozilla.gecko.sync.net;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An <code>AuthHeaderProvider</code> that returns an Authorization header for
|
||||||
|
* Bearer tokens in the format expected by a Mozilla Firefox Accounts Profile Server.
|
||||||
|
* <p>
|
||||||
|
* See <a href="https://github.com/mozilla/fxa-profile-server/blob/master/docs/API.md">https://github.com/mozilla/fxa-profile-server/blob/master/docs/API.md</a>.
|
||||||
|
*/
|
||||||
|
public class BearerAuthHeaderProvider extends AbstractBearerTokenAuthHeaderProvider {
|
||||||
|
public BearerAuthHeaderProvider(String token) {
|
||||||
|
super(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getPrefix() {
|
||||||
|
return "Bearer";
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,12 +4,6 @@
|
||||||
|
|
||||||
package org.mozilla.gecko.sync.net;
|
package org.mozilla.gecko.sync.net;
|
||||||
|
|
||||||
import ch.boye.httpclientandroidlib.Header;
|
|
||||||
import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase;
|
|
||||||
import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient;
|
|
||||||
import ch.boye.httpclientandroidlib.message.BasicHeader;
|
|
||||||
import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An <code>AuthHeaderProvider</code> that returns an Authorization header for
|
* An <code>AuthHeaderProvider</code> that returns an Authorization header for
|
||||||
* BrowserID assertions in the format expected by a Mozilla Services Token
|
* BrowserID assertions in the format expected by a Mozilla Services Token
|
||||||
|
@ -17,21 +11,13 @@ import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="http://docs.services.mozilla.com/token/apis.html">http://docs.services.mozilla.com/token/apis.html</a>.
|
* See <a href="http://docs.services.mozilla.com/token/apis.html">http://docs.services.mozilla.com/token/apis.html</a>.
|
||||||
*/
|
*/
|
||||||
public class BrowserIDAuthHeaderProvider implements AuthHeaderProvider {
|
public class BrowserIDAuthHeaderProvider extends AbstractBearerTokenAuthHeaderProvider {
|
||||||
protected final String assertion;
|
|
||||||
|
|
||||||
public BrowserIDAuthHeaderProvider(String assertion) {
|
public BrowserIDAuthHeaderProvider(String assertion) {
|
||||||
if (assertion == null) {
|
super(assertion);
|
||||||
throw new IllegalArgumentException("assertion must not be null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.assertion = assertion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Header getAuthHeader(HttpRequestBase request, BasicHttpContext context, DefaultHttpClient client) {
|
protected String getPrefix() {
|
||||||
Header header = new BasicHeader("Authorization", "BrowserID " + assertion);
|
return "BrowserID";
|
||||||
|
|
||||||
return header;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -405,6 +405,7 @@ public class TabsPanel extends LinearLayout
|
||||||
int height = getVerticalPanelHeight();
|
int height = getVerticalPanelHeight();
|
||||||
dispatchLayoutChange(getWidth(), height);
|
dispatchLayoutChange(getWidth(), height);
|
||||||
}
|
}
|
||||||
|
mHeaderVisible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void prepareToDrag() {
|
public void prepareToDrag() {
|
||||||
|
@ -414,6 +415,7 @@ public class TabsPanel extends LinearLayout
|
||||||
} else {
|
} else {
|
||||||
prepareToShow(TabsPanel.Panel.NORMAL_TABS);
|
prepareToShow(TabsPanel.Panel.NORMAL_TABS);
|
||||||
}
|
}
|
||||||
|
mHeaderVisible = true;
|
||||||
if (mIsSideBar) {
|
if (mIsSideBar) {
|
||||||
prepareSidebarAnimation(getWidth());
|
prepareSidebarAnimation(getWidth());
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,14 +17,6 @@ import android.view.ViewConfiguration;
|
||||||
public final class HardwareUtils {
|
public final class HardwareUtils {
|
||||||
private static final String LOGTAG = "GeckoHardwareUtils";
|
private static final String LOGTAG = "GeckoHardwareUtils";
|
||||||
|
|
||||||
// Minimum memory threshold for a device to be considered
|
|
||||||
// a low memory platform (see isLowMemoryPlatform). This value
|
|
||||||
// has be in sync with Gecko's equivalent threshold (defined in
|
|
||||||
// xpcom/base/nsMemoryImpl.cpp) and should only be used in cases
|
|
||||||
// where we can't depend on Gecko to be up and running e.g. show/hide
|
|
||||||
// reading list capabilities in HomePager.
|
|
||||||
private static final int LOW_MEMORY_THRESHOLD_MB = 384;
|
|
||||||
|
|
||||||
private static final boolean IS_AMAZON_DEVICE = Build.MANUFACTURER.equalsIgnoreCase("Amazon");
|
private static final boolean IS_AMAZON_DEVICE = Build.MANUFACTURER.equalsIgnoreCase("Amazon");
|
||||||
public static final boolean IS_KINDLE_DEVICE = IS_AMAZON_DEVICE &&
|
public static final boolean IS_KINDLE_DEVICE = IS_AMAZON_DEVICE &&
|
||||||
(Build.MODEL.equals("Kindle Fire") ||
|
(Build.MODEL.equals("Kindle Fire") ||
|
||||||
|
@ -96,17 +88,4 @@ public final class HardwareUtils {
|
||||||
public static int getMemSize() {
|
public static int getMemSize() {
|
||||||
return SysInfo.getMemSize();
|
return SysInfo.getMemSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isLowMemoryPlatform() {
|
|
||||||
final int memSize = getMemSize();
|
|
||||||
|
|
||||||
// Fallback to false if we fail to read meminfo
|
|
||||||
// for some reason.
|
|
||||||
if (memSize == 0) {
|
|
||||||
Log.w(LOGTAG, "Could not compute system memory. Falling back to isLowMemoryPlatform = false.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return memSize < LOW_MEMORY_THRESHOLD_MB;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,11 @@ let Reader = {
|
||||||
STATUS_FETCH_FAILED_UNSUPPORTED_FORMAT: 3,
|
STATUS_FETCH_FAILED_UNSUPPORTED_FORMAT: 3,
|
||||||
STATUS_FETCHED_ARTICLE: 4,
|
STATUS_FETCHED_ARTICLE: 4,
|
||||||
|
|
||||||
|
get _hasUsedToolbar() {
|
||||||
|
delete this._hasUsedToolbar;
|
||||||
|
return this._hasUsedToolbar = Services.prefs.getBoolPref("reader.has_used_toolbar");
|
||||||
|
},
|
||||||
|
|
||||||
observe: function Reader_observe(aMessage, aTopic, aData) {
|
observe: function Reader_observe(aMessage, aTopic, aData) {
|
||||||
switch (aTopic) {
|
switch (aTopic) {
|
||||||
case "Reader:FetchContent": {
|
case "Reader:FetchContent": {
|
||||||
|
@ -103,10 +108,6 @@ let Reader = {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "Reader:ShowToast":
|
|
||||||
NativeWindow.toast.show(message.data.toast, "short");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "Reader:SystemUIVisibility":
|
case "Reader:SystemUIVisibility":
|
||||||
Messaging.sendRequest({
|
Messaging.sendRequest({
|
||||||
type: "SystemUI:Visibility",
|
type: "SystemUI:Visibility",
|
||||||
|
@ -114,11 +115,12 @@ let Reader = {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "Reader:ToolbarVisibility":
|
case "Reader:ToolbarHidden":
|
||||||
Messaging.sendRequest({
|
if (!this._hasUsedToolbar) {
|
||||||
type: "BrowserToolbar:Visibility",
|
NativeWindow.toast.show(Strings.browser.GetStringFromName("readerMode.toolbarTip"), "short");
|
||||||
visible: message.data.visible
|
Services.prefs.setBoolPref("reader.has_used_toolbar", true);
|
||||||
});
|
this._hasUsedToolbar = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "Reader:UpdateReaderButton": {
|
case "Reader:UpdateReaderButton": {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
let Ci = Components.interfaces, Cc = Components.classes, Cu = Components.utils;
|
let Ci = Components.interfaces, Cc = Components.classes, Cu = Components.utils;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm")
|
Cu.import("resource://gre/modules/Services.jsm")
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
|
@ -130,9 +131,20 @@ let Passwords = {
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
// Create item icon.
|
// Create item icon.
|
||||||
let img = document.createElement("img");
|
let img = document.createElement("div");
|
||||||
img.className = "icon";
|
img.className = "icon";
|
||||||
img.setAttribute("src", login.hostname + "/favicon.ico");
|
|
||||||
|
// Load favicon from cache.
|
||||||
|
Messaging.sendRequestForResult({
|
||||||
|
type: "Favicon:CacheLoad",
|
||||||
|
url: login.hostname,
|
||||||
|
}).then(function(faviconUrl) {
|
||||||
|
img.style.backgroundImage= "url('" + faviconUrl + "')";
|
||||||
|
img.style.visibility = "visible";
|
||||||
|
}, function(data) {
|
||||||
|
debug("Favicon cache failure : " + data);
|
||||||
|
img.style.visibility = "visible";
|
||||||
|
});
|
||||||
loginItem.appendChild(img);
|
loginItem.appendChild(img);
|
||||||
|
|
||||||
// Create item details.
|
// Create item details.
|
||||||
|
@ -192,8 +204,8 @@ let Passwords = {
|
||||||
let detailItem = document.querySelector("#login-details > .login-item");
|
let detailItem = document.querySelector("#login-details > .login-item");
|
||||||
let login = detailItem.login = listItem.login;
|
let login = detailItem.login = listItem.login;
|
||||||
let favicon = detailItem.querySelector(".icon");
|
let favicon = detailItem.querySelector(".icon");
|
||||||
favicon.setAttribute("src", login.hostname + "/favicon.ico");
|
favicon.style["background-image"] = listItem.querySelector(".icon").style["background-image"];
|
||||||
|
favicon.style.visibility = "visible";
|
||||||
document.getElementById("details-header").setAttribute("link", login.hostname);
|
document.getElementById("details-header").setAttribute("link", login.hostname);
|
||||||
|
|
||||||
document.getElementById("detail-hostname").textContent = login.hostname;
|
document.getElementById("detail-hostname").textContent = login.hostname;
|
||||||
|
@ -209,7 +221,7 @@ let Passwords = {
|
||||||
userInputs = domain.split(".").filter(part => part.length > 3);
|
userInputs = domain.split(".").filter(part => part.length > 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastChanged = new Date(login.timePasswordChanged);
|
let lastChanged = new Date(login.QueryInterface(Ci.nsILoginMetaInfo).timePasswordChanged);
|
||||||
let days = Math.round((Date.now() - lastChanged) / 1000 / 60 / 60/ 24);
|
let days = Math.round((Date.now() - lastChanged) / 1000 / 60 / 60/ 24);
|
||||||
document.getElementById("detail-age").textContent = gStringBundle.formatStringFromName("passwordsDetails.age", [days], 1);
|
document.getElementById("detail-age").textContent = gStringBundle.formatStringFromName("passwordsDetails.age", [days], 1);
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="login-details" class="list" hidden="true">
|
<div id="login-details" class="list" hidden="true">
|
||||||
<div class="login-item list-item">
|
<div class="login-item list-item">
|
||||||
<img class="icon"/>
|
<div class="icon"/>
|
||||||
<div id="details-header" class="inner">
|
<div id="details-header" class="inner">
|
||||||
<div class="details">
|
<div class="details">
|
||||||
<div id="detail-hostname" class="hostname"></div>
|
<div id="detail-hostname" class="hostname"></div>
|
||||||
|
|
|
@ -179,8 +179,7 @@ lazilyLoadedObserverScripts.forEach(function (aScript) {
|
||||||
"Reader:ListStatusRequest",
|
"Reader:ListStatusRequest",
|
||||||
"Reader:RemoveFromList",
|
"Reader:RemoveFromList",
|
||||||
"Reader:Share",
|
"Reader:Share",
|
||||||
"Reader:ShowToast",
|
"Reader:ToolbarHidden",
|
||||||
"Reader:ToolbarVisibility",
|
|
||||||
"Reader:SystemUIVisibility",
|
"Reader:SystemUIVisibility",
|
||||||
"Reader:UpdateReaderButton",
|
"Reader:UpdateReaderButton",
|
||||||
], "chrome://browser/content/Reader.js"],
|
], "chrome://browser/content/Reader.js"],
|
||||||
|
|
|
@ -365,6 +365,10 @@ getUserMedia.sharingCameraAndMicrophone.message2 = Camera and microphone are on
|
||||||
readerMode.enter = Enter Reader Mode
|
readerMode.enter = Enter Reader Mode
|
||||||
readerMode.exit = Exit Reader Mode
|
readerMode.exit = Exit Reader Mode
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (readerMode.toolbarTip):
|
||||||
|
# Tip shown to users the first time we hide the reader mode toolbar.
|
||||||
|
readerMode.toolbarTip=Tap the screen to show reader options
|
||||||
|
|
||||||
#Open in App
|
#Open in App
|
||||||
openInApp.pageAction = Open in App
|
openInApp.pageAction = Open in App
|
||||||
openInApp.ok = OK
|
openInApp.ok = OK
|
||||||
|
|
|
@ -26,7 +26,7 @@ let AppConstants = Object.freeze({
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ACCESSIBILITY:
|
ACCESSIBILITY:
|
||||||
#ifdef MOZ_ACCESSIBILITY
|
#ifdef ACCESSIBILITY
|
||||||
true,
|
true,
|
||||||
#else
|
#else
|
||||||
false,
|
false,
|
||||||
|
|
|
@ -34,7 +34,7 @@ EXTRA_JS_MODULES += [
|
||||||
for var in ('ANDROID_PACKAGE_NAME', 'MOZ_APP_VERSION'):
|
for var in ('ANDROID_PACKAGE_NAME', 'MOZ_APP_VERSION'):
|
||||||
DEFINES[var] = CONFIG[var]
|
DEFINES[var] = CONFIG[var]
|
||||||
|
|
||||||
for var in ('NIGHTLY_BUILD', 'RELEASE_BUILD', 'MOZ_ACCESSIBILITY',
|
for var in ('NIGHTLY_BUILD', 'RELEASE_BUILD', 'ACCESSIBILITY',
|
||||||
'MOZILLA_OFFICIAL', 'MOZ_OFFICIAL_BRANDING', 'MOZ_SERVICES_HEALTHREPORT',
|
'MOZILLA_OFFICIAL', 'MOZ_OFFICIAL_BRANDING', 'MOZ_SERVICES_HEALTHREPORT',
|
||||||
'MOZ_DEVICES', 'MOZ_DEVICES', 'MOZ_SAFE_BROWSING',
|
'MOZ_DEVICES', 'MOZ_DEVICES', 'MOZ_SAFE_BROWSING',
|
||||||
'MOZ_TELEMETRY_REPORTING', 'MOZ_WEBRTC'):
|
'MOZ_TELEMETRY_REPORTING', 'MOZ_WEBRTC'):
|
||||||
|
|
|
@ -83,6 +83,16 @@
|
||||||
margin: 0 5px;
|
margin: 0 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
background-image: url("resource://android/res/drawable-mdpi-v4/favicon.png");
|
||||||
|
background-position: center;
|
||||||
|
background-size: 32px 32px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
height: 32px;
|
||||||
|
width: 32px;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (min-resolution: 1.25dppx) {
|
@media screen and (min-resolution: 1.25dppx) {
|
||||||
#filter-button {
|
#filter-button {
|
||||||
background-image: url("resource://android/res/drawable-hdpi-v4/ab_search.png");
|
background-image: url("resource://android/res/drawable-hdpi-v4/ab_search.png");
|
||||||
|
@ -91,6 +101,10 @@
|
||||||
#filter-clear {
|
#filter-clear {
|
||||||
background-image: url("resource://android/res/drawable-hdpi-v4/close_edit_mode_light.png");
|
background-image: url("resource://android/res/drawable-hdpi-v4/close_edit_mode_light.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
background-image: url("resource://android/res/drawable-hdpi-v4/favicon.png");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-resolution: 2dppx) {
|
@media screen and (min-resolution: 2dppx) {
|
||||||
|
@ -101,4 +115,8 @@
|
||||||
#filter-clear {
|
#filter-clear {
|
||||||
background-image: url("resource://android/res/drawable-hdpi-v4/close_edit_mode_light.png");
|
background-image: url("resource://android/res/drawable-hdpi-v4/close_edit_mode_light.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
background-image: url("resource://android/res/drawable-xhdpi-v4/favicon.png");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,14 +175,10 @@ def parse_commit(message, jobs):
|
||||||
# Argument parser based on try flag flags
|
# Argument parser based on try flag flags
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('-b', dest='build_types')
|
parser.add_argument('-b', dest='build_types')
|
||||||
parser.add_argument('-p', dest='platforms')
|
parser.add_argument('-p', nargs='?', dest='platforms', const='all', default='all')
|
||||||
parser.add_argument('-u', dest='tests')
|
parser.add_argument('-u', nargs='?', dest='tests', const='all', default='all')
|
||||||
args, unknown = parser.parse_known_args(parts[1:])
|
args, unknown = parser.parse_known_args(parts[1:])
|
||||||
|
|
||||||
# Sanity check platforms...
|
|
||||||
if args.platforms is None:
|
|
||||||
return []
|
|
||||||
|
|
||||||
# Then builds...
|
# Then builds...
|
||||||
if args.build_types is None:
|
if args.build_types is None:
|
||||||
return []
|
return []
|
||||||
|
|
|
@ -9,13 +9,11 @@ task:
|
||||||
scopes:
|
scopes:
|
||||||
- 'docker-worker:cache:sources-gecko'
|
- 'docker-worker:cache:sources-gecko'
|
||||||
- 'docker-worker:cache:sources-gaia'
|
- 'docker-worker:cache:sources-gaia'
|
||||||
- 'docker-worker:cache:build-b2g-desktop-objects'
|
|
||||||
|
|
||||||
payload:
|
payload:
|
||||||
cache:
|
cache:
|
||||||
sources-gaia: '/home/worker/gaia'
|
sources-gaia: '/home/worker/gaia'
|
||||||
sources-gecko: '/home/worker/gecko'
|
sources-gecko: '/home/worker/gecko'
|
||||||
build-b2g-desktop-objects: '/home/worker/object-folder'
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
MOZCONFIG: 'b2g/config/mozconfigs/linux64_gecko/nightly'
|
MOZCONFIG: 'b2g/config/mozconfigs/linux64_gecko/nightly'
|
||||||
|
|
|
@ -4,6 +4,13 @@ $inherits:
|
||||||
build_type: 'debug'
|
build_type: 'debug'
|
||||||
|
|
||||||
task:
|
task:
|
||||||
|
scopes:
|
||||||
|
- 'docker-worker:cache:build-b2g-desktop-objects-debug'
|
||||||
|
|
||||||
|
payload:
|
||||||
|
cache:
|
||||||
|
build-b2g-desktop-objects-debug: '/home/worker/object-folder'
|
||||||
|
|
||||||
extra:
|
extra:
|
||||||
treeherder:
|
treeherder:
|
||||||
collection:
|
collection:
|
||||||
|
|
|
@ -4,6 +4,13 @@ $inherits:
|
||||||
build_type: 'opt'
|
build_type: 'opt'
|
||||||
|
|
||||||
task:
|
task:
|
||||||
|
scopes:
|
||||||
|
- 'docker-worker:cache:build-b2g-desktop-objects-opt'
|
||||||
|
|
||||||
|
payload:
|
||||||
|
cache:
|
||||||
|
build-b2g-desktop-objects-opt: '/home/worker/object-folder'
|
||||||
|
|
||||||
payload:
|
payload:
|
||||||
env:
|
env:
|
||||||
MOZCONFIG: 'b2g/config/mozconfigs/linux64_gecko/nightly'
|
MOZCONFIG: 'b2g/config/mozconfigs/linux64_gecko/nightly'
|
||||||
|
|
|
@ -420,13 +420,8 @@ AboutReader.prototype = {
|
||||||
this._toolbarElement.classList.toggle("toolbar-hidden");
|
this._toolbarElement.classList.toggle("toolbar-hidden");
|
||||||
this._setSystemUIVisibility(visible);
|
this._setSystemUIVisibility(visible);
|
||||||
|
|
||||||
if (!visible && !this._hasUsedToolbar) {
|
if (!visible) {
|
||||||
this._hasUsedToolbar = Services.prefs.getBoolPref("reader.has_used_toolbar");
|
this._mm.sendAsyncMessage("Reader:ToolbarHidden");
|
||||||
if (!this._hasUsedToolbar) {
|
|
||||||
this._mm.sendAsyncMessage("Reader:ShowToast", { toast: gStrings.GetStringFromName("aboutReader.toolbarTip") });
|
|
||||||
Services.prefs.setBoolPref("reader.has_used_toolbar", true);
|
|
||||||
this._hasUsedToolbar = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -434,10 +429,6 @@ AboutReader.prototype = {
|
||||||
this._setToolbarVisibility(!this._getToolbarVisibility());
|
this._setToolbarVisibility(!this._getToolbarVisibility());
|
||||||
},
|
},
|
||||||
|
|
||||||
_setBrowserToolbarVisiblity: function Reader_setBrowserToolbarVisiblity(visible) {
|
|
||||||
this._mm.sendAsyncMessage("Reader:ToolbarVisibility", { visible: visible });
|
|
||||||
},
|
|
||||||
|
|
||||||
_setSystemUIVisibility: function Reader_setSystemUIVisibility(visible) {
|
_setSystemUIVisibility: function Reader_setSystemUIVisibility(visible) {
|
||||||
this._mm.sendAsyncMessage("Reader:SystemUIVisibility", { visible: visible });
|
this._mm.sendAsyncMessage("Reader:SystemUIVisibility", { visible: visible });
|
||||||
},
|
},
|
||||||
|
|
|
@ -160,9 +160,9 @@ function getOriginActivationType(origin) {
|
||||||
|
|
||||||
let directories = Services.prefs.getCharPref("social.directories").split(',');
|
let directories = Services.prefs.getCharPref("social.directories").split(',');
|
||||||
if (directories.indexOf(origin) >= 0)
|
if (directories.indexOf(origin) >= 0)
|
||||||
return 'directory';
|
return "directory";
|
||||||
|
|
||||||
return 'foreign';
|
return "foreign";
|
||||||
}
|
}
|
||||||
|
|
||||||
let ActiveProviders = {
|
let ActiveProviders = {
|
||||||
|
@ -549,9 +549,15 @@ this.SocialService = {
|
||||||
let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
|
let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
|
||||||
let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
||||||
|
|
||||||
// internal activation does not have a host, use the manifest origin in that case
|
|
||||||
let requestingURI = Services.io.newURI(data.installType == "internal" ?
|
// foreign activation uses the activation url for origin, directory or
|
||||||
data.manifest.origin : data.url, null, null);
|
// internal (in-product) activations use the origin defined in the manifest
|
||||||
|
let url = data.installType == "foreign" ?
|
||||||
|
data.url :
|
||||||
|
data.installType == "directory" ||
|
||||||
|
data.installType == "internal" ?
|
||||||
|
data.manifest.origin : undefined;
|
||||||
|
let requestingURI = Services.io.newURI(url, null, null);
|
||||||
let productName = brandBundle.GetStringFromName("brandShortName");
|
let productName = brandBundle.GetStringFromName("brandShortName");
|
||||||
|
|
||||||
let message = browserBundle.formatStringFromName("service.install.description",
|
let message = browserBundle.formatStringFromName("service.install.description",
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
<vbox class="description" flex="1">
|
<vbox class="description" flex="1">
|
||||||
<label id="warningText">&aboutWarningText.label;</label>
|
<label id="warningText">&aboutWarningText.label;</label>
|
||||||
<checkbox id="showWarningNextTime" label="&aboutWarningCheckbox.label;" checked="true"/>
|
<checkbox id="showWarningNextTime" label="&aboutWarningCheckbox.label;" checked="true"/>
|
||||||
<hbox pack="center">
|
<hbox class="button-container">
|
||||||
<button id="warningButton" class="primary" oncommand="ShowPrefs();" label="&aboutWarningButton.label;"/>
|
<button id="warningButton" class="primary" oncommand="ShowPrefs();" label="&aboutWarningButton.label;"/>
|
||||||
</hbox>
|
</hbox>
|
||||||
</vbox>
|
</vbox>
|
||||||
|
|
|
@ -7,7 +7,7 @@ const {Cc, Ci, Cu, Cr} = require("chrome");
|
||||||
const events = require("sdk/event/core");
|
const events = require("sdk/event/core");
|
||||||
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||||
const protocol = require("devtools/server/protocol");
|
const protocol = require("devtools/server/protocol");
|
||||||
const {ContentObserver} = require("devtools/content-observer");
|
const {serializeStack, parseStack} = require("toolkit/loader");
|
||||||
|
|
||||||
const {on, once, off, emit} = events;
|
const {on, once, off, emit} = events;
|
||||||
const {method, Arg, Option, RetVal} = protocol;
|
const {method, Arg, Option, RetVal} = protocol;
|
||||||
|
@ -417,7 +417,12 @@ let CallWatcherActor = exports.CallWatcherActor = protocol.ActorClass({
|
||||||
let originalFunc = Cu.unwaiveXrays(target[name]);
|
let originalFunc = Cu.unwaiveXrays(target[name]);
|
||||||
|
|
||||||
Cu.exportFunction(function(...args) {
|
Cu.exportFunction(function(...args) {
|
||||||
let result = Cu.waiveXrays(originalFunc.apply(this, args));
|
let result;
|
||||||
|
try {
|
||||||
|
result = Cu.waiveXrays(originalFunc.apply(this, args));
|
||||||
|
} catch (e) {
|
||||||
|
throw createContentError(e, unwrappedWindow);
|
||||||
|
}
|
||||||
|
|
||||||
if (self._recording) {
|
if (self._recording) {
|
||||||
let stack = getStack(name);
|
let stack = getStack(name);
|
||||||
|
@ -693,3 +698,45 @@ function getBitToEnumValue(type, object, arg) {
|
||||||
// Cache the combined bitmask value
|
// Cache the combined bitmask value
|
||||||
return table[arg] = flags.join(" | ") || arg;
|
return table[arg] = flags.join(" | ") || arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new error from an error that originated from content but was called
|
||||||
|
* from a wrapped overridden method. This is so we can make our own error
|
||||||
|
* that does not look like it originated from the call watcher.
|
||||||
|
*
|
||||||
|
* We use toolkit/loader's parseStack and serializeStack rather than the
|
||||||
|
* parsing done in the local `getStack` function, because it does not expose
|
||||||
|
* column number, would have to change the protocol models `call-stack-items` and `call-details`
|
||||||
|
* which hurts backwards compatibility, and the local `getStack` is an optimized, hot function.
|
||||||
|
*/
|
||||||
|
function createContentError (e, win) {
|
||||||
|
let { message, name, stack } = e;
|
||||||
|
let parsedStack = parseStack(stack);
|
||||||
|
let { fileName, lineNumber, columnNumber } = parsedStack[parsedStack.length - 1];
|
||||||
|
let error;
|
||||||
|
|
||||||
|
let isDOMException = e instanceof Ci.nsIDOMDOMException;
|
||||||
|
let constructor = isDOMException ? win.DOMException : (win[e.name] || win.Error);
|
||||||
|
|
||||||
|
if (isDOMException) {
|
||||||
|
error = new constructor(message, name);
|
||||||
|
Object.defineProperties(error, {
|
||||||
|
code: { value: e.code },
|
||||||
|
columnNumber: { value: 0 }, // columnNumber is always 0 for DOMExceptions?
|
||||||
|
filename: { value: fileName }, // note the lowercase `filename`
|
||||||
|
lineNumber: { value: lineNumber },
|
||||||
|
result: { value: e.result },
|
||||||
|
stack: { value: serializeStack(parsedStack) }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Constructing an error here retains all the stack information,
|
||||||
|
// and we can add message, fileName and lineNumber via constructor, though
|
||||||
|
// need to manually add columnNumber.
|
||||||
|
error = new constructor(message, fileName, lineNumber);
|
||||||
|
Object.defineProperty(error, "columnNumber", {
|
||||||
|
value: columnNumber
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
|
@ -14,10 +14,10 @@ const protocol = require("devtools/server/protocol");
|
||||||
const { CallWatcherActor, CallWatcherFront } = require("devtools/server/actors/call-watcher");
|
const { CallWatcherActor, CallWatcherFront } = require("devtools/server/actors/call-watcher");
|
||||||
const { ThreadActor } = require("devtools/server/actors/script");
|
const { ThreadActor } = require("devtools/server/actors/script");
|
||||||
const AutomationTimeline = require("./utils/automation-timeline");
|
const AutomationTimeline = require("./utils/automation-timeline");
|
||||||
|
|
||||||
const { on, once, off, emit } = events;
|
const { on, once, off, emit } = events;
|
||||||
const { types, method, Arg, Option, RetVal } = protocol;
|
const { types, method, Arg, Option, RetVal } = protocol;
|
||||||
|
|
||||||
|
const ENABLE_AUTOMATION = false;
|
||||||
const AUTOMATION_GRANULARITY = 2000;
|
const AUTOMATION_GRANULARITY = 2000;
|
||||||
const AUTOMATION_GRANULARITY_MAX = 6000;
|
const AUTOMATION_GRANULARITY_MAX = 6000;
|
||||||
|
|
||||||
|
@ -680,7 +680,7 @@ let WebAudioActor = exports.WebAudioActor = protocol.ActorClass({
|
||||||
else if (WebAudioFront.NODE_CREATION_METHODS.has(name)) {
|
else if (WebAudioFront.NODE_CREATION_METHODS.has(name)) {
|
||||||
this._handleCreationCall(functionCall);
|
this._handleCreationCall(functionCall);
|
||||||
}
|
}
|
||||||
else if (WebAudioFront.AUTOMATION_METHODS.has(name)) {
|
else if (ENABLE_AUTOMATION && WebAudioFront.AUTOMATION_METHODS.has(name)) {
|
||||||
this._handleAutomationCall(functionCall);
|
this._handleAutomationCall(functionCall);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -26,5 +26,3 @@ aboutReader.fontTypeSample=Aa
|
||||||
# LOCALIZATION NOTE (aboutReader.fontSizeSample): String used to sample a relative font size
|
# LOCALIZATION NOTE (aboutReader.fontSizeSample): String used to sample a relative font size
|
||||||
# for the font size setting. Tapping different samples will change the font size.
|
# for the font size setting. Tapping different samples will change the font size.
|
||||||
aboutReader.fontSizeSample=A
|
aboutReader.fontSizeSample=A
|
||||||
|
|
||||||
aboutReader.toolbarTip=Tap the screen to show reader options
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
# OSX only. Default menu label when there is no xul menubar.
|
||||||
|
|
||||||
|
quitMenuitem.label=Quit
|
||||||
|
quitMenuitem.key=q
|
|
@ -38,6 +38,7 @@
|
||||||
locale/@AB_CD@/global/devtools/styleinspector.properties (%chrome/global/devtools/styleinspector.properties)
|
locale/@AB_CD@/global/devtools/styleinspector.properties (%chrome/global/devtools/styleinspector.properties)
|
||||||
locale/@AB_CD@/global/dialogOverlay.dtd (%chrome/global/dialogOverlay.dtd)
|
locale/@AB_CD@/global/dialogOverlay.dtd (%chrome/global/dialogOverlay.dtd)
|
||||||
locale/@AB_CD@/global/editMenuOverlay.dtd (%chrome/global/editMenuOverlay.dtd)
|
locale/@AB_CD@/global/editMenuOverlay.dtd (%chrome/global/editMenuOverlay.dtd)
|
||||||
|
locale/@AB_CD@/global/fallbackMenubar.properties (%chrome/global/fallbackMenubar.properties)
|
||||||
locale/@AB_CD@/global/filefield.properties (%chrome/global/filefield.properties)
|
locale/@AB_CD@/global/filefield.properties (%chrome/global/filefield.properties)
|
||||||
locale/@AB_CD@/global/filepicker.dtd (%chrome/global/filepicker.dtd)
|
locale/@AB_CD@/global/filepicker.dtd (%chrome/global/filepicker.dtd)
|
||||||
locale/@AB_CD@/global/filepicker.properties (%chrome/global/filepicker.properties)
|
locale/@AB_CD@/global/filepicker.properties (%chrome/global/filepicker.properties)
|
||||||
|
|
|
@ -77,6 +77,10 @@ ul {
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button-container > button:first-child {
|
||||||
|
-moz-margin-start: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Trees */
|
/* Trees */
|
||||||
tree {
|
tree {
|
||||||
min-height: 12em;
|
min-height: 12em;
|
||||||
|
|
|
@ -130,6 +130,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ConstructNativeMenus();
|
void ConstructNativeMenus();
|
||||||
|
void ConstructFallbackNativeMenus();
|
||||||
nsresult InsertMenuAtIndex(nsMenuX* aMenu, uint32_t aIndex);
|
nsresult InsertMenuAtIndex(nsMenuX* aMenu, uint32_t aIndex);
|
||||||
void RemoveMenuAtIndex(uint32_t aIndex);
|
void RemoveMenuAtIndex(uint32_t aIndex);
|
||||||
void HideItem(nsIDOMDocument* inDoc, const nsAString & inID, nsIContent** outHiddenNode);
|
void HideItem(nsIDOMDocument* inDoc, const nsAString & inID, nsIContent** outHiddenNode);
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
#include "nsIDOMDocument.h"
|
#include "nsIDOMDocument.h"
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
|
#include "nsIAppStartup.h"
|
||||||
|
#include "nsIStringBundle.h"
|
||||||
|
#include "nsToolkitCompsCID.h"
|
||||||
|
|
||||||
NativeMenuItemTarget* nsMenuBarX::sNativeEventTarget = nil;
|
NativeMenuItemTarget* nsMenuBarX::sNativeEventTarget = nil;
|
||||||
nsMenuBarX* nsMenuBarX::sLastGeckoMenuBarPainted = nullptr; // Weak
|
nsMenuBarX* nsMenuBarX::sLastGeckoMenuBarPainted = nullptr; // Weak
|
||||||
|
@ -80,7 +83,9 @@ nsMenuBarX::~nsMenuBarX()
|
||||||
sPrefItemContent = nullptr;
|
sPrefItemContent = nullptr;
|
||||||
|
|
||||||
// make sure we unregister ourselves as a content observer
|
// make sure we unregister ourselves as a content observer
|
||||||
UnregisterForContentChanges(mContent);
|
if (mContent) {
|
||||||
|
UnregisterForContentChanges(mContent);
|
||||||
|
}
|
||||||
|
|
||||||
// We have to manually clear the array here because clearing causes menu items
|
// We have to manually clear the array here because clearing causes menu items
|
||||||
// to call back into the menu bar to unregister themselves. We don't want to
|
// to call back into the menu bar to unregister themselves. We don't want to
|
||||||
|
@ -96,21 +101,24 @@ nsMenuBarX::~nsMenuBarX()
|
||||||
|
|
||||||
nsresult nsMenuBarX::Create(nsIWidget* aParent, nsIContent* aContent)
|
nsresult nsMenuBarX::Create(nsIWidget* aParent, nsIContent* aContent)
|
||||||
{
|
{
|
||||||
if (!aParent || !aContent)
|
if (!aParent)
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
|
|
||||||
mParentWindow = aParent;
|
mParentWindow = aParent;
|
||||||
mContent = aContent;
|
mContent = aContent;
|
||||||
|
|
||||||
AquifyMenuBar();
|
if (mContent) {
|
||||||
|
AquifyMenuBar();
|
||||||
|
|
||||||
nsresult rv = nsMenuGroupOwnerX::Create(aContent);
|
nsresult rv = nsMenuGroupOwnerX::Create(mContent);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
RegisterForContentChanges(aContent, this);
|
RegisterForContentChanges(mContent, this);
|
||||||
|
ConstructNativeMenus();
|
||||||
ConstructNativeMenus();
|
} else {
|
||||||
|
ConstructFallbackNativeMenus();
|
||||||
|
}
|
||||||
|
|
||||||
// Give this to the parent window. The parent takes ownership.
|
// Give this to the parent window. The parent takes ownership.
|
||||||
static_cast<nsCocoaWindow*>(mParentWindow)->SetMenuBar(this);
|
static_cast<nsCocoaWindow*>(mParentWindow)->SetMenuBar(this);
|
||||||
|
@ -138,6 +146,49 @@ void nsMenuBarX::ConstructNativeMenus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nsMenuBarX::ConstructFallbackNativeMenus()
|
||||||
|
{
|
||||||
|
if (sApplicationMenu) {
|
||||||
|
// Menu has already been built.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIStringBundle> stringBundle;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIStringBundleService> bundleSvc = do_GetService(NS_STRINGBUNDLE_CONTRACTID);
|
||||||
|
bundleSvc->CreateBundle("chrome://global/locale/fallbackMenubar.properties", getter_AddRefs(stringBundle));
|
||||||
|
|
||||||
|
if (!stringBundle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsXPIDLString labelUTF16;
|
||||||
|
nsXPIDLString keyUTF16;
|
||||||
|
|
||||||
|
const char16_t* labelProp = MOZ_UTF16("quitMenuitem.label");
|
||||||
|
const char16_t* keyProp = MOZ_UTF16("quitMenuitem.key");
|
||||||
|
|
||||||
|
stringBundle->GetStringFromName(labelProp, getter_Copies(labelUTF16));
|
||||||
|
stringBundle->GetStringFromName(keyProp, getter_Copies(keyUTF16));
|
||||||
|
|
||||||
|
NSString* labelStr = [NSString stringWithUTF8String:
|
||||||
|
NS_ConvertUTF16toUTF8(labelUTF16).get()];
|
||||||
|
NSString* keyStr= [NSString stringWithUTF8String:
|
||||||
|
NS_ConvertUTF16toUTF8(keyUTF16).get()];
|
||||||
|
|
||||||
|
if (!nsMenuBarX::sNativeEventTarget) {
|
||||||
|
nsMenuBarX::sNativeEventTarget = [[NativeMenuItemTarget alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
|
sApplicationMenu = [[[[NSApp mainMenu] itemAtIndex:0] submenu] retain];
|
||||||
|
NSMenuItem* quitMenuItem = [[[NSMenuItem alloc] initWithTitle:labelStr
|
||||||
|
action:@selector(menuItemHit:)
|
||||||
|
keyEquivalent:keyStr] autorelease];
|
||||||
|
[quitMenuItem setTarget:nsMenuBarX::sNativeEventTarget];
|
||||||
|
[quitMenuItem setTag:eCommand_ID_Quit];
|
||||||
|
[sApplicationMenu addItem:quitMenuItem];
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t nsMenuBarX::GetMenuCount()
|
uint32_t nsMenuBarX::GetMenuCount()
|
||||||
{
|
{
|
||||||
return mMenuArray.Length();
|
return mMenuArray.Length();
|
||||||
|
@ -878,23 +929,25 @@ static BOOL gMenuItemsExecuteCommands = YES;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tag = [sender tag];
|
||||||
|
|
||||||
if (!gMenuItemsExecuteCommands) {
|
if (!gMenuItemsExecuteCommands) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tag = [sender tag];
|
nsMenuGroupOwnerX* menuGroupOwner = nullptr;
|
||||||
|
|
||||||
MenuItemInfo* info = [sender representedObject];
|
|
||||||
if (!info)
|
|
||||||
return;
|
|
||||||
|
|
||||||
nsMenuGroupOwnerX* menuGroupOwner = [info menuGroupOwner];
|
|
||||||
if (!menuGroupOwner)
|
|
||||||
return;
|
|
||||||
|
|
||||||
nsMenuBarX* menuBar = nullptr;
|
nsMenuBarX* menuBar = nullptr;
|
||||||
if (menuGroupOwner->MenuObjectType() == eMenuBarObjectType)
|
MenuItemInfo* info = [sender representedObject];
|
||||||
menuBar = static_cast<nsMenuBarX*>(menuGroupOwner);
|
|
||||||
|
if (info) {
|
||||||
|
menuGroupOwner = [info menuGroupOwner];
|
||||||
|
if (!menuGroupOwner) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (menuGroupOwner->MenuObjectType() == eMenuBarObjectType) {
|
||||||
|
menuBar = static_cast<nsMenuBarX*>(menuGroupOwner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Do special processing if this is for an app-global command.
|
// Do special processing if this is for an app-global command.
|
||||||
if (tag == eCommand_ID_About) {
|
if (tag == eCommand_ID_About) {
|
||||||
|
@ -934,7 +987,10 @@ static BOOL gMenuItemsExecuteCommands = YES;
|
||||||
nsMenuUtilsX::DispatchCommandTo(mostSpecificContent);
|
nsMenuUtilsX::DispatchCommandTo(mostSpecificContent);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
[NSApp terminate:nil];
|
nsCOMPtr<nsIAppStartup> appStartup = do_GetService(NS_APPSTARTUP_CONTRACTID);
|
||||||
|
if (appStartup) {
|
||||||
|
appStartup->Quit(nsIAppStartup::eAttemptQuit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -418,6 +418,11 @@ nsWebShellWindow::WindowDeactivated()
|
||||||
#ifdef USE_NATIVE_MENUS
|
#ifdef USE_NATIVE_MENUS
|
||||||
static void LoadNativeMenus(nsIDOMDocument *aDOMDoc, nsIWidget *aParentWindow)
|
static void LoadNativeMenus(nsIDOMDocument *aDOMDoc, nsIWidget *aParentWindow)
|
||||||
{
|
{
|
||||||
|
nsCOMPtr<nsINativeMenuService> nms = do_GetService("@mozilla.org/widget/nativemenuservice;1");
|
||||||
|
if (!nms) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Find the menubar tag (if there is more than one, we ignore all but
|
// Find the menubar tag (if there is more than one, we ignore all but
|
||||||
// the first).
|
// the first).
|
||||||
nsCOMPtr<nsIDOMNodeList> menubarElements;
|
nsCOMPtr<nsIDOMNodeList> menubarElements;
|
||||||
|
@ -428,13 +433,13 @@ static void LoadNativeMenus(nsIDOMDocument *aDOMDoc, nsIWidget *aParentWindow)
|
||||||
nsCOMPtr<nsIDOMNode> menubarNode;
|
nsCOMPtr<nsIDOMNode> menubarNode;
|
||||||
if (menubarElements)
|
if (menubarElements)
|
||||||
menubarElements->Item(0, getter_AddRefs(menubarNode));
|
menubarElements->Item(0, getter_AddRefs(menubarNode));
|
||||||
if (!menubarNode)
|
|
||||||
return;
|
|
||||||
|
|
||||||
nsCOMPtr<nsINativeMenuService> nms = do_GetService("@mozilla.org/widget/nativemenuservice;1");
|
if (menubarNode) {
|
||||||
nsCOMPtr<nsIContent> menubarContent(do_QueryInterface(menubarNode));
|
nsCOMPtr<nsIContent> menubarContent(do_QueryInterface(menubarNode));
|
||||||
if (nms && menubarContent)
|
|
||||||
nms->CreateNativeMenuBar(aParentWindow, menubarContent);
|
nms->CreateNativeMenuBar(aParentWindow, menubarContent);
|
||||||
|
} else {
|
||||||
|
nms->CreateNativeMenuBar(aParentWindow, nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче