This commit is contained in:
Ryan VanderMeulen 2015-02-18 20:35:37 -05:00
Родитель 86618832b4 a411359369
Коммит c966517190
97 изменённых файлов: 1692 добавлений и 512 удалений

Просмотреть файл

@ -41,10 +41,9 @@ const ObserverDelegee = Class({
this.delegate = delegate;
},
QueryInterface: function(iid) {
const isObserver = iid.equals(Ci.nsIObserver);
const isWeakReference = iid.equals(Ci.nsISupportsWeakReference);
if (!isObserver && !isWeakReference)
if (!iid.equals(Ci.nsIObserver) &&
!iid.equals(Ci.nsISupportsWeakReference) &&
!iid.equals(Ci.nsISupports))
throw Cr.NS_ERROR_NO_INTERFACE;
return this;

Просмотреть файл

@ -295,6 +295,9 @@ let hides = filter(panelEvents, ({type}) => type === "popuphidden");
let ready = filter(panelEvents, ({type, target}) =>
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
// depends on `contentScriptWhen`
let start = filter(panelEvents, ({type}) => type === "document-element-inserted");
@ -317,6 +320,10 @@ on(ready, "data", ({target}) => {
let window = domPanel.getContentDocument(target).defaultView;
workerFor(panel).attach(window);
});
on(readyToShow, "data", ({target}) => {
let panel = panelFor(target);
if (!modelFor(panel).ready) {
modelFor(panel).ready = true;

Просмотреть файл

@ -6,10 +6,10 @@
const { create: makeFrame } = require("sdk/frame/utils");
const { window } = require("sdk/addon/window");
const { Loader } = require('sdk/test/loader');
const loader = Loader(module);
const Worker = loader.require("sdk/content/worker").Worker;
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(
'<script>' +
@ -48,13 +48,20 @@ exports.testMembranelessMode = function(assert, done) {
done();
}
});
worker.port.on("done", function () {
worker.port.on("done", () => {
// cleanup
element.parentNode.removeChild(element);
worker.destroy();
loader.unload();
done();
});
worker.port.on("assert", function (data) {
assert.ok(data.assertion, data.msg);
});
}
};

Просмотреть файл

@ -60,7 +60,7 @@ exports.testBufferMain = function (assert) {
// invalid encoding for Buffer.toString
assert.throws(() => {
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
// valid buffer range
@ -248,7 +248,7 @@ exports.testBufferWrite = function (assert) {
assert.throws(() => {
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
assert.throws(function() {
b.write('', 2048);

Просмотреть файл

@ -10,6 +10,7 @@ const {openWindow, closeWindow, openTab, closeTab,
const {when} = require("sdk/dom/events");
const {Item, Menu, Separator, Contexts, Readers } = require("sdk/context-menu@2");
const prefs = require("sdk/preferences/service");
const { before, after } = require('sdk/test/utils');
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);

Просмотреть файл

@ -86,8 +86,9 @@ exports["test Panel API"] = test(function*(assert) {
yield closeToolbox();
assert.equal(panel.readyState, "destroyed", "panel is destroyed");
});
myTool.destroy();
});
exports["test Panel communication"] = test(function*(assert) {
const MyPanel = Class({
@ -150,6 +151,7 @@ exports["test Panel communication"] = test(function*(assert) {
yield closeToolbox();
assert.equal(panel.readyState, "destroyed", "panel is destroyed");
myTool.destroy();
});
exports["test communication with debuggee"] = test(function*(assert) {
@ -233,6 +235,8 @@ exports["test communication with debuggee"] = test(function*(assert) {
yield closeToolbox();
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");
yield closeToolbox();
myTool.destroy();
});
@ -314,6 +320,8 @@ exports["test createView panel"] = test(function*(assert) {
assert.equal(frame.contentDocument.URL, url, "is expected iframe");
yield closeToolbox();
myTool.destroy();
});
require("sdk/test").run(exports);

Просмотреть файл

@ -12,6 +12,7 @@ const { Class } = require("sdk/core/heritage");
const { Cc, Ci, Cu } = require("chrome");
const { notifyObservers } = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
const { defer } = require("sdk/core/promise");
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) {
let loader = Loader(module);
let showCount = 0;
let panel = loader.require("sdk/panel").Panel({
contentScript: "addEventListener('load', function(event) { self.postMessage('load'); });",
contentScriptWhen: "start",
@ -1335,6 +1334,24 @@ exports["test panel load doesn't show"] = function*(assert) {
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) {
module.exports = {
"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">
<copyfile dest="Makefile" src="core/root.mk"/>
</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="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<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/extras" path="system/extras" revision="10e78a05252b3de785f88c2d0b9ea8a428009c50"/>
<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/security" path="system/security" revision="ee8068b9e7bfb2770635062fc9c2035be2142bd8"/>
<project name="platform/system/vold" path="system/vold" revision="2e43efe1b30d0b98574d293059556aebd2f46454"/>

Просмотреть файл

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<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="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eb1795a9002eb142ac58c8d68f8f4ba094af07ca"/>

Просмотреть файл

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<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="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
<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_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/>
<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/netd" path="system/netd" revision="56112dd7b811301b718d0643a82fd5cac9522073"/>
<project name="platform/system/security" path="system/security" revision="f48ff68fedbcdc12b570b7699745abb6e7574907"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="cdaa0a4ac28c781709df8c318ed079e9e475503a">
<copyfile dest="Makefile" src="core/root.mk"/>
</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="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<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/extras" path="system/extras" revision="5356165f67f4a81c2ef28671c13697f1657590df"/>
<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/security" path="system/security" revision="583374f69f531ba68fc3dcbff1f74893d2a96406"/>
<project name="platform/system/vold" path="system/vold" revision="d4455b8cf361f8353e8aebac15ffd64b4aedd2b9"/>

Просмотреть файл

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<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="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<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">
<copyfile dest="Makefile" src="core/root.mk"/>
</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="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<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_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="9d83b3a8e72c773820ada75e5a2cd128a743cf35"/>
<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/security" path="system/security" revision="ee8068b9e7bfb2770635062fc9c2035be2142bd8"/>
<project name="platform/system/vold" path="system/vold" revision="42fa2a0f14f965970a4b629a176bbd2666edf017"/>

Просмотреть файл

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<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="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>

Просмотреть файл

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "82f286f10a41aab84a0796c89fbefe67b179994b",
"git_revision": "620aecfde85a8b093247837c55de2708e22be1e1",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "066f0e84321a010700467d1814ee0048dca7e5e1",
"revision": "42da22fe3d59646d07bad417e194969dd2cc891d",
"repo_path": "integration/gaia-central"
}

Просмотреть файл

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<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="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
<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_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/>
<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/netd" path="system/netd" revision="56112dd7b811301b718d0643a82fd5cac9522073"/>
<project name="platform/system/security" path="system/security" revision="f48ff68fedbcdc12b570b7699745abb6e7574907"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="7f2ee9f4cb926684883fc2a2e407045fd9db2199">
<copyfile dest="Makefile" src="core/root.mk"/>
</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="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<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_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="9d83b3a8e72c773820ada75e5a2cd128a743cf35"/>
<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/netd" path="system/netd" revision="655392625db084a7122d65a15acf74db7f1da7f7"/>
<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:BrowserToolbox" oncommand="BrowserToolboxProcess.init();" 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:ResponsiveUI" oncommand="ResponsiveUI.toggle();"/>
<command id="Tools:Eyedropper" oncommand="openEyedropper();"/>

Просмотреть файл

@ -5480,30 +5480,30 @@
var event = document.createEvent("Events");
event.initEvent("select", true, true);
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;
]]>
</setter>

Просмотреть файл

@ -429,7 +429,7 @@ skip-if = e10s
skip-if = e10s # Bug 1100664 - test relies on linkedBrowser.docShell
[browser_tabs_owner.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]
support-files =
trackingPage.html

Просмотреть файл

@ -33,9 +33,13 @@ add_task(function* () {
readerButton.click();
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(gURLBar.value, readerUrl, "gURLBar value is about:reader URL");
is(gURLBar.textValue, url.substring("http://".length), "gURLBar is displaying original article URL");
readerButton.click();
yield promiseTabLoadEvent(tab);
is(gBrowser.selectedBrowser.currentURI.spec, url, "Original page loaded after clicking active reader mode button");

Просмотреть файл

@ -160,6 +160,11 @@
break;
}
}
} else {
let originalUrl = ReaderParent.parseReaderUrl(aValue);
if (originalUrl) {
returnValue = originalUrl;
}
}
// 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
// otherwise there is a flicker of the stylesheet applying.
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() {

Просмотреть файл

@ -76,7 +76,7 @@ let gTests = [{
dialog.document.documentElement.cancelDialog();
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;
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");
},
},
{
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",
run: function* () {

Просмотреть файл

@ -219,7 +219,7 @@ Tools.shaderEditor = {
tooltip: l10n("ToolboxShaderEditor.tooltip", shaderEditorStrings),
isTargetSupported: function(target) {
return target.hasActor("webgl");
return target.hasActor("webgl") && !target.chrome;
},
build: function(iframeWindow, toolbox) {

Просмотреть файл

@ -13,6 +13,7 @@ support-files =
doc_automation.html
doc_bug_1125817.html
doc_bug_1130901.html
doc_bug_1112378.html
440hz_sine.ogg
head.js
@ -26,18 +27,19 @@ support-files =
[browser_audionode-actor-connectnode-disconnect.js]
[browser_audionode-actor-connectparam.js]
skip-if = true # bug 1092571
[browser_audionode-actor-add-automation-event.js]
[browser_audionode-actor-get-automation-data-01.js]
[browser_audionode-actor-get-automation-data-02.js]
[browser_audionode-actor-get-automation-data-03.js]
# [browser_audionode-actor-add-automation-event.js] bug 1134036
# [browser_audionode-actor-get-automation-data-01.js] bug 1134036
# [browser_audionode-actor-get-automation-data-02.js] bug 1134036
# [browser_audionode-actor-get-automation-data-03.js] bug 1134036
[browser_callwatcher-01.js]
[browser_callwatcher-02.js]
[browser_webaudio-actor-simple.js]
[browser_webaudio-actor-destroy-node.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-02.js]
# [browser_wa_automation-view-01.js] bug 1134036
# [browser_wa_automation-view-02.js] bug 1134036
[browser_wa_controller-01.js]
[browser_wa_destroy-node-01.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 { devtools } = Cu.import("resource://gre/modules/devtools/Loader.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 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 SIMPLE_CONTEXT_URL = EXAMPLE_URL + "doc_simple-context.html";
const COMPLEX_CONTEXT_URL = EXAMPLE_URL + "doc_complex-context.html";
@ -47,6 +50,15 @@ registerCleanupFunction(() => {
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) {
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
*/

Просмотреть файл

@ -96,8 +96,10 @@
<tabs>
<tab id="properties-tab"
label="&webAudioEditorUI.tab.properties2;"/>
<!-- bug 1134036
<tab id="automation-tab"
label="&webAudioEditorUI.tab.automation;"/>
-->
</tabs>
<tabpanels flex="1">
<!-- Properties Panel -->

Просмотреть файл

@ -251,6 +251,21 @@ HUD_SERVICE.prototype =
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.
*
@ -763,7 +778,8 @@ const HUDService = new HUD_SERVICE();
(() => {
let methods = ["openWebConsole", "openBrowserConsole",
"toggleBrowserConsole", "getOpenWebConsole",
"getBrowserConsole", "getHudByWindow", "getHudReferenceById"];
"getBrowserConsole", "getHudByWindow",
"openBrowserConsoleOrFocus", "getHudReferenceById"];
for (let method of methods) {
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_api_stackframe.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"
screenX="4" screenY="4"
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="webide.js"></script>

Просмотреть файл

@ -26,8 +26,6 @@ let ReaderParent = {
"Reader:ListStatusRequest",
"Reader:RemoveFromList",
"Reader:Share",
"Reader:ShowToast",
"Reader:ToolbarVisibility",
"Reader:SystemUIVisibility",
"Reader:UpdateReaderButton",
],
@ -70,18 +68,10 @@ let ReaderParent = {
// XXX: To implement.
break;
case "Reader:ShowToast":
// XXX: To implement.
break;
case "Reader:SystemUIVisibility":
// XXX: To implement.
break;
case "Reader:ToolbarVisibility":
// XXX: To implement.
break;
case "Reader:UpdateReaderButton": {
let browser = message.target;
if (message.data && message.data.isArticle !== undefined) {
@ -122,23 +112,37 @@ let ReaderParent = {
let win = event.target.ownerDocument.defaultView;
let url = win.gBrowser.selectedBrowser.currentURI.spec;
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 {
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.
*
* @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) {
let searchParams = new URLSearchParams(url.split("?")[1]);
let searchParams = new URLSearchParams(url.substring("about:reader?".length));
if (!searchParams.has("url")) {
Cu.reportError("Error finding original URL for about:reader URL: " + url);
return url;
return null;
}
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/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/icons.png (../shared/incontentprefs/icons.png)
skin/classic/browser/preferences/in-content/icons@2x.png (../shared/incontentprefs/icons@2x.png)
skin/classic/browser/preferences/in-content/icons.svg (../shared/incontentprefs/icons.svg)
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/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/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/icons.png (../shared/incontentprefs/icons.png)
skin/classic/browser/preferences/in-content/icons@2x.png (../shared/incontentprefs/icons@2x.png)
skin/classic/browser/preferences/in-content/icons.svg (../shared/incontentprefs/icons.svg)
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/aboutPermissions.css (preferences/aboutPermissions.css)

Двоичные данные
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

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 11 KiB

Просмотреть файл

@ -43,78 +43,36 @@ treecol {
visibility: collapse;
}
.category-icon {
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.png");
}
#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 {
-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 {
-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 {
-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 {
-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 {
-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 {
-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 {
-moz-image-region: rect(0, 168px, 24px, 144px);
}
@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);
}
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#advanced");
}
@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/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/icons.png (../shared/incontentprefs/icons.png)
skin/classic/browser/preferences/in-content/icons@2x.png (../shared/incontentprefs/icons@2x.png)
skin/classic/browser/preferences/in-content/icons.svg (../shared/incontentprefs/icons.svg)
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/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/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/icons.png (../shared/incontentprefs/icons.png)
skin/classic/aero/browser/preferences/in-content/icons@2x.png (../shared/incontentprefs/icons@2x.png)
skin/classic/aero/browser/preferences/in-content/icons.svg (../shared/incontentprefs/icons.svg)
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/aboutPermissions.css (preferences/aboutPermissions.css)

Просмотреть файл

@ -4,6 +4,40 @@
%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 {
-moz-margin-end: 9px;
}

Просмотреть файл

@ -53,41 +53,38 @@ struct SavedFrame::Lookup {
JSAtom *functionDisplayName;
SavedFrame *parent;
JSPrincipals *principals;
};
class SavedFrame::AutoLookupRooter : public JS::CustomAutoRooter
{
public:
AutoLookupRooter(JSContext *cx, JSAtom *source, uint32_t line, uint32_t column,
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,
void trace(JSTracer *trc) {
gc::MarkStringUnbarriered(trc, &source, "SavedFrame::Lookup::source");
if (functionDisplayName) {
gc::MarkStringUnbarriered(trc, &functionDisplayName,
"SavedFrame::Lookup::functionDisplayName");
}
if (value.parent)
gc::MarkObjectUnbarriered(trc, &value.parent, "SavedFrame::Lookup::parent");
if (parent) {
gc::MarkObjectUnbarriered(trc, &parent,
"SavedFrame::Lookup::parent");
}
}
SavedFrame::Lookup value;
};
class SavedFrame::HandleLookup
{
class MOZ_STACK_CLASS SavedFrame::AutoLookupVector : public JS::CustomAutoRooter {
public:
MOZ_IMPLICIT HandleLookup(SavedFrame::AutoLookupRooter &lookup) : ref(lookup) { }
SavedFrame::Lookup *operator->() { return &ref.get(); }
operator const SavedFrame::Lookup&() const { return ref; }
explicit AutoLookupVector(JSContext *cx)
: JS::CustomAutoRooter(cx),
lookups(cx)
{ }
typedef Vector<Lookup, 20> LookupVector;
inline LookupVector *operator->() { return &lookups; }
inline Lookup &operator[](size_t i) { return lookups[i]; }
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
@ -580,12 +577,14 @@ SavedStacks::insertFrames(JSContext *cx, FrameIter &iter, MutableHandleSavedFram
// SavedFrame objects at that time.
//
// To avoid making many copies of FrameIter (whose copy constructor is
// relatively slow), we save the subset of FrameIter's data that is relevant
// to our needs in a FrameState object, and maintain a vector of FrameState
// objects instead of a vector of FrameIter objects.
// relatively slow), we use a vector of `SavedFrame::Lookup` objects, which
// only contain the FrameIter data we need. The `SavedFrame::Lookup`
// 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|.
AutoFrameStateVector stackState(cx);
// Accumulate the vector of Lookup objects in |stackChain|.
SavedFrame::AutoLookupVector stackChain(cx);
while (!iter.done()) {
AutoLocationValueRooter location(cx);
@ -595,12 +594,18 @@ SavedStacks::insertFrames(JSContext *cx, FrameIter &iter, MutableHandleSavedFram
return false;
}
{
FrameState frameState(iter);
frameState.location = location.get();
if (!stackState->append(frameState))
return false;
}
// Use growByUninitialized and placement-new instead of just append.
// We'd ideally like to use an emplace method once Vector supports it.
if (!stackChain->growByUninitialized(1))
return false;
new (&stackChain->back()) SavedFrame::Lookup(
location->source,
location->line,
location->column,
iter.isNonEvalFunctionFrame() ? iter.functionDisplayAtom() : nullptr,
nullptr,
iter.compartment()->principals
);
++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.
RootedSavedFrame parentFrame(cx, nullptr);
for (size_t i = stackState->length(); i != 0; i--) {
SavedFrame::AutoLookupRooter lookup(cx,
stackState[i-1].location.source,
stackState[i-1].location.line,
stackState[i-1].location.column,
stackState[i-1].name,
parentFrame,
stackState[i-1].principals);
parentFrame = getOrCreateSavedFrame(cx, lookup);
for (size_t i = stackChain->length(); i != 0; i--) {
SavedFrame::AutoLookupRooter lookup(cx, &stackChain[i-1]);
lookup->parent = parentFrame;
parentFrame.set(getOrCreateSavedFrame(cx, lookup));
if (!parentFrame)
return false;
}
@ -640,7 +640,8 @@ SavedStacks::insertFrames(JSContext *cx, FrameIter &iter, MutableHandleSavedFram
SavedFrame *
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)
return *p;
@ -648,7 +649,7 @@ SavedStacks::getOrCreateSavedFrame(JSContext *cx, SavedFrame::HandleLookup looku
if (!frame)
return nullptr;
if (!p.add(cx, frames, lookup, frame))
if (!p.add(cx, frames, lookupInstance, frame))
return nullptr;
return frame;
@ -778,31 +779,6 @@ SavedStacks::chooseSamplingProbability(JSContext *cx)
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
SavedStacksMetadataCallback(JSContext *cx, JSObject **pmetadata)
{

Просмотреть файл

@ -55,8 +55,9 @@ class SavedFrame : public NativeObject {
HashPolicy,
SystemAllocPolicy> Set;
class AutoLookupRooter;
class HandleLookup;
typedef RootedGeneric<Lookup*> AutoLookupRooter;
typedef AutoLookupRooter &HandleLookup;
class AutoLookupVector;
private:
static bool finishSavedFrameInit(JSContext *cx, HandleObject ctor, HandleObject proto);
@ -221,44 +222,6 @@ class SavedStacks {
void sweepPCLocationMap();
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);

Просмотреть файл

@ -5,8 +5,10 @@
package org.mozilla.gecko;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.EnumSet;
@ -114,6 +116,8 @@ import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Base64;
import android.util.Base64OutputStream;
import android.util.Log;
import android.view.InputDevice;
import android.view.KeyEvent;
@ -766,6 +770,7 @@ public class BrowserApp extends GeckoApp
"Accounts:Create",
"CharEncoding:Data",
"CharEncoding:State",
"Favicon:CacheLoad",
"Feedback:LastUrl",
"Feedback:MaybeLater",
"Feedback:OpenPlayStore",
@ -774,8 +779,7 @@ public class BrowserApp extends GeckoApp
"Reader:Share",
"Settings:Show",
"Telemetry:Gather",
"Updater:Launch",
"BrowserToolbar:Visibility");
"Updater:Launch");
Distribution distribution = Distribution.init(this);
@ -1309,6 +1313,7 @@ public class BrowserApp extends GeckoApp
"Accounts:Create",
"CharEncoding:Data",
"CharEncoding:State",
"Favicon:CacheLoad",
"Feedback:LastUrl",
"Feedback:MaybeLater",
"Feedback:OpenPlayStore",
@ -1317,8 +1322,7 @@ public class BrowserApp extends GeckoApp
"Reader:Share",
"Settings:Show",
"Telemetry:Gather",
"Updater:Launch",
"BrowserToolbar:Visibility");
"Updater:Launch");
if (AppConstants.MOZ_ANDROID_BEAM) {
NfcAdapter nfc = NfcAdapter.getDefaultAdapter(this);
@ -1534,17 +1538,6 @@ public class BrowserApp extends GeckoApp
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() {
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)) {
getLastUrl(callback);
@ -1705,15 +1702,58 @@ public class BrowserApp extends GeckoApp
}
} else if ("Updater:Launch".equals(event)) {
handleUpdaterLaunch();
} else if ("BrowserToolbar:Visibility".equals(event)) {
setBrowserToolbarVisible(message.getBoolean("visible"));
} else {
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.
*

Просмотреть файл

@ -392,7 +392,7 @@ public abstract class GeckoApp
onPreparePanel(featureId, mMenuPanel, mMenu);
}
return mMenuPanel;
return mMenuPanel;
}
return super.onCreatePanelView(featureId);
@ -505,7 +505,7 @@ public abstract class GeckoApp
mMenuPanel.addView((GeckoMenu) mMenu);
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// 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
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() {
mLayerView.requestRender();
}
public void hidePlugins(Tab tab) {
for (Layer layer : tab.getPluginLayers()) {
if (layer instanceof PluginLayer) {

Просмотреть файл

@ -4,9 +4,9 @@
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.RemoteTab;
import org.mozilla.gecko.home.TwoLinePageRow;
@ -20,6 +20,12 @@ import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
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
* data maintained in a monolithic static array.
@ -28,6 +34,15 @@ import android.widget.TextView;
* specialization to home fragment styles.
*/
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;
private final boolean showGroupIndicator;
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
// getting a string.
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
// for the home panel groups and not for the tabs panel groups.
@ -215,4 +230,19 @@ public class RemoteTabsExpandableListAdapter extends BaseExpandableListAdapter {
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/FxAccountRemoteError.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/profile/FxAccountProfileClient10.java',
'background/fxa/QuickPasswordStretcher.java',
'background/fxa/SkewHandler.java',
'background/healthreport/AndroidConfigurationProvider.java',
@ -835,7 +840,9 @@ sync_java_files = [
'browserid/MockMyIDTokenFactory.java',
'browserid/RSACryptoImplementation.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/BrowserIDVerifierDelegate.java',
'browserid/verifier/BrowserIDVerifierException.java',
@ -962,10 +969,12 @@ sync_java_files = [
'sync/middleware/MiddlewareRepository.java',
'sync/middleware/MiddlewareRepositorySession.java',
'sync/MigrationSentinelSyncStage.java',
'sync/net/AbstractBearerTokenAuthHeaderProvider.java',
'sync/net/AuthHeaderProvider.java',
'sync/net/BaseResource.java',
'sync/net/BaseResourceDelegate.java',
'sync/net/BasicAuthHeaderProvider.java',
'sync/net/BearerAuthHeaderProvider.java',
'sync/net/BrowserIDAuthHeaderProvider.java',
'sync/net/ConnectionMonitorThread.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.");
return false;
}
System.out.println("certificate header: " + c.getString("header"));
System.out.println("certificate payload: " + c.getString("payload"));
System.out.println("certificate header: " + c.getObject("header").toJSONString());
System.out.println("certificate payload: " + c.getObject("payload").toJSONString());
System.out.println("certificate signature: " + c.getString("signature"));
return true;
} catch (Exception e) {
@ -244,8 +244,8 @@ public class JSONWebTokenUtils {
return false;
}
dumpCertificate(a.getString("certificate"));
System.out.println("assertion header: " + a.getString("header"));
System.out.println("assertion payload: " + a.getString("payload"));
System.out.println("assertion header: " + a.getObject("header").toJSONString());
System.out.println("assertion payload: " + a.getObject("payload").toJSONString());
System.out.println("assertion signature: " + a.getString("signature"));
return true;
} catch (Exception e) {

Просмотреть файл

@ -5,29 +5,23 @@
package org.mozilla.gecko.browserid.verifier;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.browserid.verifier.BrowserIDVerifierException.BrowserIDVerifierErrorResponseException;
import org.mozilla.gecko.browserid.verifier.BrowserIDVerifierException.BrowserIDVerifierMalformedResponseException;
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.Resource;
import org.mozilla.gecko.sync.net.SyncResponse;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.NameValuePair;
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 {
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;
public BrowserIDRemoteVerifierClient(URI verifierUri) {
public AbstractBrowserIDRemoteVerifierClient(URI 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) {
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 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 int limit, final OnQueryTabsCompleteListener listener);
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.
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
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()) {
return false;
}
if (panDistance(event) < PAN_THRESHOLD) {
if (panDistance(event) < PanZoomController.PAN_THRESHOLD) {
return false;
}
cancelTouch();

Просмотреть файл

@ -36,7 +36,7 @@ class HomeConfigPrefsBackend implements HomeConfigBackend {
private static final String LOGTAG = "GeckoHomeConfigBackend";
// 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.
private static final String PREFS_CONFIG_KEY_OLD = "home_panels";
@ -73,12 +73,7 @@ class HomeConfigPrefsBackend implements HomeConfigBackend {
EnumSet.of(PanelConfig.Flags.DEFAULT_PANEL)));
panelConfigs.add(createBuiltinPanelConfig(mContext, PanelType.BOOKMARKS));
// 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));
}
panelConfigs.add(createBuiltinPanelConfig(mContext, PanelType.READING_LIST));
final PanelConfig historyEntry = createBuiltinPanelConfig(mContext, PanelType.HISTORY);
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.
*
@ -231,6 +251,19 @@ class HomeConfigPrefsBackend implements HomeConfigBackend {
addBuiltinPanelConfig(context, jsonPanels,
PanelType.REMOTE_TABS, Position.FRONT, Position.BACK);
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 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_subtext "Committed to you, your privacy, and an Open Web">
<!ENTITY onboard_start_message2 "Welcome to &brandShortName;">
<!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_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
their desktop or laptop.-->
<!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 -->
<!-- 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'
] ]
# Putting branding earlier allows branders to override default resources.
ANDROID_RES_DIRS += [
SRCDIR + '/resources',
TOPSRCDIR + '/' + CONFIG['MOZ_BRANDING_DIRECTORY'] + '/res',
SRCDIR + '/resources',
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.sync.setup.activities.WebURLFinder;
import org.mozilla.gecko.mozglue.ContextUtils;
import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.util.UIAsyncTask;
@ -214,14 +213,8 @@ public class ShareDialog extends Locales.LocaleAwareActivity implements SendTabT
sendTabList.setAdapter(adapter);
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);
if (HardwareUtils.isLowMemoryPlatform()) {
readinglistBtn.setVisibility(View.GONE);
return;
}
final String readingListEnabledLabel = resources.getString(R.string.overlay_share_reading_list_btn_label);
final Drawable readingListEnabledIcon = resources.getDrawable(R.drawable.overlay_readinglist_icon);
readinglistBtn.setEnabledLabelAndIcon(readingListEnabledLabel, readingListEnabledIcon);

Просмотреть файл

@ -38,8 +38,8 @@
<string name="no_space_to_start_error">&no_space_to_start_error;</string>
<string name="error_loading_file">&error_loading_file;</string>
<string name="firstrun_welcome_message">&onboard_start_message;</string>
<string name="firstrun_welcome_subtext">&onboard_start_subtext;</string>
<string name="firstrun_welcome_message">&onboard_start_message2;</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_browser">&onboard_start_button_browser;</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_desc">&remote_tabs_panel_moved_desc;</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_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;
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
* BrowserID assertions in the format expected by a Mozilla Services Token
@ -17,21 +11,13 @@ import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
* <p>
* 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 {
protected final String assertion;
public class BrowserIDAuthHeaderProvider extends AbstractBearerTokenAuthHeaderProvider {
public BrowserIDAuthHeaderProvider(String assertion) {
if (assertion == null) {
throw new IllegalArgumentException("assertion must not be null.");
}
this.assertion = assertion;
super(assertion);
}
@Override
public Header getAuthHeader(HttpRequestBase request, BasicHttpContext context, DefaultHttpClient client) {
Header header = new BasicHeader("Authorization", "BrowserID " + assertion);
return header;
protected String getPrefix() {
return "BrowserID";
}
}

Просмотреть файл

@ -405,6 +405,7 @@ public class TabsPanel extends LinearLayout
int height = getVerticalPanelHeight();
dispatchLayoutChange(getWidth(), height);
}
mHeaderVisible = true;
}
public void prepareToDrag() {
@ -414,6 +415,7 @@ public class TabsPanel extends LinearLayout
} else {
prepareToShow(TabsPanel.Panel.NORMAL_TABS);
}
mHeaderVisible = true;
if (mIsSideBar) {
prepareSidebarAnimation(getWidth());
}

Просмотреть файл

@ -17,14 +17,6 @@ import android.view.ViewConfiguration;
public final class HardwareUtils {
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");
public static final boolean IS_KINDLE_DEVICE = IS_AMAZON_DEVICE &&
(Build.MODEL.equals("Kindle Fire") ||
@ -96,17 +88,4 @@ public final class HardwareUtils {
public static int 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_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) {
switch (aTopic) {
case "Reader:FetchContent": {
@ -103,10 +108,6 @@ let Reader = {
});
break;
case "Reader:ShowToast":
NativeWindow.toast.show(message.data.toast, "short");
break;
case "Reader:SystemUIVisibility":
Messaging.sendRequest({
type: "SystemUI:Visibility",
@ -114,11 +115,12 @@ let Reader = {
});
break;
case "Reader:ToolbarVisibility":
Messaging.sendRequest({
type: "BrowserToolbar:Visibility",
visible: message.data.visible
});
case "Reader:ToolbarHidden":
if (!this._hasUsedToolbar) {
NativeWindow.toast.show(Strings.browser.GetStringFromName("readerMode.toolbarTip"), "short");
Services.prefs.setBoolPref("reader.has_used_toolbar", true);
this._hasUsedToolbar = true;
}
break;
case "Reader:UpdateReaderButton": {

Просмотреть файл

@ -4,6 +4,7 @@
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/XPCOMUtils.jsm");
@ -130,9 +131,20 @@ let Passwords = {
}, true);
// Create item icon.
let img = document.createElement("img");
let img = document.createElement("div");
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);
// Create item details.
@ -192,8 +204,8 @@ let Passwords = {
let detailItem = document.querySelector("#login-details > .login-item");
let login = detailItem.login = listItem.login;
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("detail-hostname").textContent = login.hostname;
@ -209,7 +221,7 @@ let Passwords = {
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);
document.getElementById("detail-age").textContent = gStringBundle.formatStringFromName("passwordsDetails.age", [days], 1);

Просмотреть файл

@ -31,7 +31,7 @@
</div>
<div id="login-details" class="list" hidden="true">
<div class="login-item list-item">
<img class="icon"/>
<div class="icon"/>
<div id="details-header" class="inner">
<div class="details">
<div id="detail-hostname" class="hostname"></div>

Просмотреть файл

@ -179,8 +179,7 @@ lazilyLoadedObserverScripts.forEach(function (aScript) {
"Reader:ListStatusRequest",
"Reader:RemoveFromList",
"Reader:Share",
"Reader:ShowToast",
"Reader:ToolbarVisibility",
"Reader:ToolbarHidden",
"Reader:SystemUIVisibility",
"Reader:UpdateReaderButton",
], "chrome://browser/content/Reader.js"],

Просмотреть файл

@ -365,6 +365,10 @@ getUserMedia.sharingCameraAndMicrophone.message2 = Camera and microphone are on
readerMode.enter = Enter 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
openInApp.pageAction = Open in App
openInApp.ok = OK

Просмотреть файл

@ -26,7 +26,7 @@ let AppConstants = Object.freeze({
#endif
ACCESSIBILITY:
#ifdef MOZ_ACCESSIBILITY
#ifdef ACCESSIBILITY
true,
#else
false,

Просмотреть файл

@ -34,7 +34,7 @@ EXTRA_JS_MODULES += [
for var in ('ANDROID_PACKAGE_NAME', 'MOZ_APP_VERSION'):
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',
'MOZ_DEVICES', 'MOZ_DEVICES', 'MOZ_SAFE_BROWSING',
'MOZ_TELEMETRY_REPORTING', 'MOZ_WEBRTC'):

Просмотреть файл

@ -83,6 +83,16 @@
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) {
#filter-button {
background-image: url("resource://android/res/drawable-hdpi-v4/ab_search.png");
@ -91,6 +101,10 @@
#filter-clear {
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) {
@ -101,4 +115,8 @@
#filter-clear {
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
parser = argparse.ArgumentParser()
parser.add_argument('-b', dest='build_types')
parser.add_argument('-p', dest='platforms')
parser.add_argument('-u', dest='tests')
parser.add_argument('-p', nargs='?', dest='platforms', const='all', default='all')
parser.add_argument('-u', nargs='?', dest='tests', const='all', default='all')
args, unknown = parser.parse_known_args(parts[1:])
# Sanity check platforms...
if args.platforms is None:
return []
# Then builds...
if args.build_types is None:
return []

Просмотреть файл

@ -9,13 +9,11 @@ task:
scopes:
- 'docker-worker:cache:sources-gecko'
- 'docker-worker:cache:sources-gaia'
- 'docker-worker:cache:build-b2g-desktop-objects'
payload:
cache:
sources-gaia: '/home/worker/gaia'
sources-gecko: '/home/worker/gecko'
build-b2g-desktop-objects: '/home/worker/object-folder'
env:
MOZCONFIG: 'b2g/config/mozconfigs/linux64_gecko/nightly'

Просмотреть файл

@ -4,6 +4,13 @@ $inherits:
build_type: 'debug'
task:
scopes:
- 'docker-worker:cache:build-b2g-desktop-objects-debug'
payload:
cache:
build-b2g-desktop-objects-debug: '/home/worker/object-folder'
extra:
treeherder:
collection:

Просмотреть файл

@ -4,6 +4,13 @@ $inherits:
build_type: 'opt'
task:
scopes:
- 'docker-worker:cache:build-b2g-desktop-objects-opt'
payload:
cache:
build-b2g-desktop-objects-opt: '/home/worker/object-folder'
payload:
env:
MOZCONFIG: 'b2g/config/mozconfigs/linux64_gecko/nightly'

Просмотреть файл

@ -420,13 +420,8 @@ AboutReader.prototype = {
this._toolbarElement.classList.toggle("toolbar-hidden");
this._setSystemUIVisibility(visible);
if (!visible && !this._hasUsedToolbar) {
this._hasUsedToolbar = Services.prefs.getBoolPref("reader.has_used_toolbar");
if (!this._hasUsedToolbar) {
this._mm.sendAsyncMessage("Reader:ShowToast", { toast: gStrings.GetStringFromName("aboutReader.toolbarTip") });
Services.prefs.setBoolPref("reader.has_used_toolbar", true);
this._hasUsedToolbar = true;
}
if (!visible) {
this._mm.sendAsyncMessage("Reader:ToolbarHidden");
}
},
@ -434,10 +429,6 @@ AboutReader.prototype = {
this._setToolbarVisibility(!this._getToolbarVisibility());
},
_setBrowserToolbarVisiblity: function Reader_setBrowserToolbarVisiblity(visible) {
this._mm.sendAsyncMessage("Reader:ToolbarVisibility", { visible: visible });
},
_setSystemUIVisibility: function Reader_setSystemUIVisibility(visible) {
this._mm.sendAsyncMessage("Reader:SystemUIVisibility", { visible: visible });
},

Просмотреть файл

@ -160,9 +160,9 @@ function getOriginActivationType(origin) {
let directories = Services.prefs.getCharPref("social.directories").split(',');
if (directories.indexOf(origin) >= 0)
return 'directory';
return "directory";
return 'foreign';
return "foreign";
}
let ActiveProviders = {
@ -549,9 +549,15 @@ this.SocialService = {
let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.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" ?
data.manifest.origin : data.url, null, null);
// foreign activation uses the activation url for origin, directory or
// 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 message = browserBundle.formatStringFromName("service.install.description",

Просмотреть файл

@ -60,7 +60,7 @@
<vbox class="description" flex="1">
<label id="warningText">&aboutWarningText.label;</label>
<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;"/>
</hbox>
</vbox>

Просмотреть файл

@ -7,7 +7,7 @@ const {Cc, Ci, Cu, Cr} = require("chrome");
const events = require("sdk/event/core");
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
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 {method, Arg, Option, RetVal} = protocol;
@ -417,7 +417,12 @@ let CallWatcherActor = exports.CallWatcherActor = protocol.ActorClass({
let originalFunc = Cu.unwaiveXrays(target[name]);
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) {
let stack = getStack(name);
@ -693,3 +698,45 @@ function getBitToEnumValue(type, object, arg) {
// Cache the combined bitmask value
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 { ThreadActor } = require("devtools/server/actors/script");
const AutomationTimeline = require("./utils/automation-timeline");
const { on, once, off, emit } = events;
const { types, method, Arg, Option, RetVal } = protocol;
const ENABLE_AUTOMATION = false;
const AUTOMATION_GRANULARITY = 2000;
const AUTOMATION_GRANULARITY_MAX = 6000;
@ -680,7 +680,7 @@ let WebAudioActor = exports.WebAudioActor = protocol.ActorClass({
else if (WebAudioFront.NODE_CREATION_METHODS.has(name)) {
this._handleCreationCall(functionCall);
}
else if (WebAudioFront.AUTOMATION_METHODS.has(name)) {
else if (ENABLE_AUTOMATION && WebAudioFront.AUTOMATION_METHODS.has(name)) {
this._handleAutomationCall(functionCall);
}
},

Просмотреть файл

@ -26,5 +26,3 @@ aboutReader.fontTypeSample=Aa
# 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.
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/dialogOverlay.dtd (%chrome/global/dialogOverlay.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/filepicker.dtd (%chrome/global/filepicker.dtd)
locale/@AB_CD@/global/filepicker.properties (%chrome/global/filepicker.properties)

Просмотреть файл

@ -77,6 +77,10 @@ ul {
min-width: 150px;
}
.button-container > button:first-child {
-moz-margin-start: 0;
}
/* Trees */
tree {
min-height: 12em;

Просмотреть файл

@ -130,6 +130,7 @@ public:
protected:
void ConstructNativeMenus();
void ConstructFallbackNativeMenus();
nsresult InsertMenuAtIndex(nsMenuX* aMenu, uint32_t aIndex);
void RemoveMenuAtIndex(uint32_t aIndex);
void HideItem(nsIDOMDocument* inDoc, const nsAString & inID, nsIContent** outHiddenNode);

Просмотреть файл

@ -25,6 +25,9 @@
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
#include "nsIAppStartup.h"
#include "nsIStringBundle.h"
#include "nsToolkitCompsCID.h"
NativeMenuItemTarget* nsMenuBarX::sNativeEventTarget = nil;
nsMenuBarX* nsMenuBarX::sLastGeckoMenuBarPainted = nullptr; // Weak
@ -80,7 +83,9 @@ nsMenuBarX::~nsMenuBarX()
sPrefItemContent = nullptr;
// 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
// 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)
{
if (!aParent || !aContent)
if (!aParent)
return NS_ERROR_INVALID_ARG;
mParentWindow = aParent;
mContent = aContent;
AquifyMenuBar();
if (mContent) {
AquifyMenuBar();
nsresult rv = nsMenuGroupOwnerX::Create(aContent);
if (NS_FAILED(rv))
return rv;
nsresult rv = nsMenuGroupOwnerX::Create(mContent);
if (NS_FAILED(rv))
return rv;
RegisterForContentChanges(aContent, this);
ConstructNativeMenus();
RegisterForContentChanges(mContent, this);
ConstructNativeMenus();
} else {
ConstructFallbackNativeMenus();
}
// Give this to the parent window. The parent takes ownership.
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()
{
return mMenuArray.Length();
@ -878,23 +929,25 @@ static BOOL gMenuItemsExecuteCommands = YES;
return;
}
int tag = [sender tag];
if (!gMenuItemsExecuteCommands) {
return;
}
int tag = [sender tag];
MenuItemInfo* info = [sender representedObject];
if (!info)
return;
nsMenuGroupOwnerX* menuGroupOwner = [info menuGroupOwner];
if (!menuGroupOwner)
return;
nsMenuGroupOwnerX* menuGroupOwner = nullptr;
nsMenuBarX* menuBar = nullptr;
if (menuGroupOwner->MenuObjectType() == eMenuBarObjectType)
menuBar = static_cast<nsMenuBarX*>(menuGroupOwner);
MenuItemInfo* info = [sender representedObject];
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.
if (tag == eCommand_ID_About) {
@ -934,7 +987,10 @@ static BOOL gMenuItemsExecuteCommands = YES;
nsMenuUtilsX::DispatchCommandTo(mostSpecificContent);
}
else {
[NSApp terminate:nil];
nsCOMPtr<nsIAppStartup> appStartup = do_GetService(NS_APPSTARTUP_CONTRACTID);
if (appStartup) {
appStartup->Quit(nsIAppStartup::eAttemptQuit);
}
}
return;
}

Просмотреть файл

@ -418,6 +418,11 @@ nsWebShellWindow::WindowDeactivated()
#ifdef USE_NATIVE_MENUS
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
// the first).
nsCOMPtr<nsIDOMNodeList> menubarElements;
@ -428,13 +433,13 @@ static void LoadNativeMenus(nsIDOMDocument *aDOMDoc, nsIWidget *aParentWindow)
nsCOMPtr<nsIDOMNode> menubarNode;
if (menubarElements)
menubarElements->Item(0, getter_AddRefs(menubarNode));
if (!menubarNode)
return;
nsCOMPtr<nsINativeMenuService> nms = do_GetService("@mozilla.org/widget/nativemenuservice;1");
nsCOMPtr<nsIContent> menubarContent(do_QueryInterface(menubarNode));
if (nms && menubarContent)
if (menubarNode) {
nsCOMPtr<nsIContent> menubarContent(do_QueryInterface(menubarNode));
nms->CreateNativeMenuBar(aParentWindow, menubarContent);
} else {
nms->CreateNativeMenuBar(aParentWindow, nullptr);
}
}
#endif