mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central to mozilla-inbound
This commit is contained in:
commit
7677a80971
@ -38,6 +38,6 @@ exports.encode = function (data, charset) {
|
||||
if (isUTF8(charset))
|
||||
return btoa(unescape(encodeURIComponent(data)))
|
||||
|
||||
data = String.fromCharCode(...[(c.charCodeAt(0) & 0xff) for (c of data)]);
|
||||
data = String.fromCharCode(...Array.from(data, c => (c.charCodeAt(0) & 0xff)));
|
||||
return btoa(data);
|
||||
}
|
||||
|
@ -307,7 +307,7 @@ function getItemWorkerForWindow(item, window) {
|
||||
var RemoteItem = Class({
|
||||
initialize: function(options, manager) {
|
||||
this.id = options.id;
|
||||
this.contexts = [instantiateContext(c) for (c of options.contexts)];
|
||||
this.contexts = options.contexts.map(instantiateContext);
|
||||
this.contentScript = options.contentScript;
|
||||
this.contentScriptFile = options.contentScriptFile;
|
||||
|
||||
|
@ -90,7 +90,7 @@ function makeChildOptions(options) {
|
||||
function makeStringArray(arrayOrValue) {
|
||||
if (!arrayOrValue)
|
||||
return [];
|
||||
return [String(v) for (v of [].concat(arrayOrValue))];
|
||||
return [].concat(arrayOrValue).map(String);
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -355,7 +355,7 @@ function itemActivated(item, clickedNode) {
|
||||
function serializeItem(item) {
|
||||
return {
|
||||
id: internal(item).id,
|
||||
contexts: [c.serialize() for (c of item.context)],
|
||||
contexts: item.context.map(c => c.serialize()),
|
||||
contentScript: item.contentScript,
|
||||
contentScriptFile: item.contentScriptFile,
|
||||
};
|
||||
|
@ -380,7 +380,7 @@ TestRunner.prototype = {
|
||||
name: this.test.name,
|
||||
passed: this.test.passed,
|
||||
failed: this.test.failed,
|
||||
errors: [error for (error in this.test.errors)].join(", ")
|
||||
errors: Object.keys(this.test.errors).join(", ")
|
||||
});
|
||||
|
||||
if (this.onDone !== null) {
|
||||
|
@ -193,7 +193,7 @@ function showResults() {
|
||||
var data = ref.__url__ ? ref.__url__ : ref;
|
||||
var warning = data == "[object Object]"
|
||||
? "[object " + data.constructor.name + "(" +
|
||||
[p for (p in data)].join(", ") + ")]"
|
||||
Object.keys(data).join(", ") + ")]"
|
||||
: data;
|
||||
console.warn("LEAK", warning, info.bin);
|
||||
}
|
||||
@ -461,8 +461,7 @@ var consoleListener = {
|
||||
testConsole.error(message);
|
||||
return;
|
||||
}
|
||||
var pointless = [err for (err of POINTLESS_ERRORS)
|
||||
if (message.indexOf(err) >= 0)];
|
||||
var pointless = POINTLESS_ERRORS.filter(err => message.indexOf(err) >= 0);
|
||||
if (pointless.length == 0 && message)
|
||||
testConsole.log(message);
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ var dispatcher = _ => {
|
||||
// starting a dispatch loop, in order to ignore timers registered
|
||||
// in side effect to dispatch while also skipping immediates that
|
||||
// were removed in side effect.
|
||||
let ids = [id for ([id] of immediates)];
|
||||
let ids = [...immediates.keys()];
|
||||
for (let id of ids) {
|
||||
let immediate = immediates.get(id);
|
||||
if (immediate) {
|
||||
|
@ -65,12 +65,9 @@ exports.testBasename = function(assert) {
|
||||
|
||||
exports.testList = function(assert) {
|
||||
let list = file.list(profilePath);
|
||||
let found = [ true for (name of list)
|
||||
if (name === fileNameInProfile) ];
|
||||
let found = list.filter(name => name === fileNameInProfile);
|
||||
|
||||
if (found.length > 1)
|
||||
assert.fail("a dir can't contain two files of the same name!");
|
||||
assert.equal(found[0], true, "file.list() should work");
|
||||
assert.equal(found.length, 1, "file.list() should work");
|
||||
|
||||
assert.throws(function() {
|
||||
file.list(filePathInProfile);
|
||||
|
@ -35,7 +35,7 @@ function serializeServiceWorkerInfo(aServiceWorkerInfo) {
|
||||
}
|
||||
if (property === "principal") {
|
||||
result.principal = {
|
||||
origin: aServiceWorkerInfo.principal.origin,
|
||||
origin: aServiceWorkerInfo.principal.originNoSuffix,
|
||||
originAttributes: aServiceWorkerInfo.principal.originAttributes
|
||||
};
|
||||
return;
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9eca89f04628c99226e0d18c15d5ae11b71af0cf"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="86959c405348d27ba5686956ae3a8ffc274d3db8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9a58f2e395da17c252f61f28900b5b09aeb813bd"/>
|
||||
@ -24,7 +24,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="ce651a7711042301cbc9c6866be0eeb9e1ceab66"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9eca89f04628c99226e0d18c15d5ae11b71af0cf"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="86959c405348d27ba5686956ae3a8ffc274d3db8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9a58f2e395da17c252f61f28900b5b09aeb813bd"/>
|
||||
@ -24,7 +24,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="ce651a7711042301cbc9c6866be0eeb9e1ceab66"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
|
||||
<default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
|
||||
<!-- Gecko and Gaia -->
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="9eca89f04628c99226e0d18c15d5ae11b71af0cf"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="86959c405348d27ba5686956ae3a8ffc274d3db8"/>
|
||||
<!-- Gonk-specific things and forks -->
|
||||
<project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
|
||||
<project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
|
||||
|
@ -17,10 +17,10 @@
|
||||
</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="9eca89f04628c99226e0d18c15d5ae11b71af0cf"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="86959c405348d27ba5686956ae3a8ffc274d3db8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9a58f2e395da17c252f61f28900b5b09aeb813bd"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="ce651a7711042301cbc9c6866be0eeb9e1ceab66"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9eca89f04628c99226e0d18c15d5ae11b71af0cf"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="86959c405348d27ba5686956ae3a8ffc274d3db8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9a58f2e395da17c252f61f28900b5b09aeb813bd"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
@ -23,7 +23,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="ce651a7711042301cbc9c6866be0eeb9e1ceab66"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9eca89f04628c99226e0d18c15d5ae11b71af0cf"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="86959c405348d27ba5686956ae3a8ffc274d3db8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9a58f2e395da17c252f61f28900b5b09aeb813bd"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
@ -23,7 +23,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="ce651a7711042301cbc9c6866be0eeb9e1ceab66"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
|
||||
<default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
|
||||
<!-- Gecko and Gaia -->
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="9eca89f04628c99226e0d18c15d5ae11b71af0cf"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="86959c405348d27ba5686956ae3a8ffc274d3db8"/>
|
||||
<!-- Gonk-specific things and forks -->
|
||||
<project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
|
||||
<project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9eca89f04628c99226e0d18c15d5ae11b71af0cf"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="86959c405348d27ba5686956ae3a8ffc274d3db8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9a58f2e395da17c252f61f28900b5b09aeb813bd"/>
|
||||
@ -24,7 +24,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="ce651a7711042301cbc9c6866be0eeb9e1ceab66"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"git_revision": "9eca89f04628c99226e0d18c15d5ae11b71af0cf",
|
||||
"git_revision": "86959c405348d27ba5686956ae3a8ffc274d3db8",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "34a22433bbb6441d25de9f4dbb5f8c401e13c5cf",
|
||||
"revision": "eae17e983597fd71c6a396ed63031bb552753f41",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9eca89f04628c99226e0d18c15d5ae11b71af0cf"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="86959c405348d27ba5686956ae3a8ffc274d3db8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9a58f2e395da17c252f61f28900b5b09aeb813bd"/>
|
||||
@ -24,7 +24,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="ce651a7711042301cbc9c6866be0eeb9e1ceab66"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
|
||||
|
@ -18,10 +18,10 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9eca89f04628c99226e0d18c15d5ae11b71af0cf"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="86959c405348d27ba5686956ae3a8ffc274d3db8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9a58f2e395da17c252f61f28900b5b09aeb813bd"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="ce651a7711042301cbc9c6866be0eeb9e1ceab66"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9eca89f04628c99226e0d18c15d5ae11b71af0cf"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="86959c405348d27ba5686956ae3a8ffc274d3db8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9a58f2e395da17c252f61f28900b5b09aeb813bd"/>
|
||||
@ -24,7 +24,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="ce651a7711042301cbc9c6866be0eeb9e1ceab66"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
|
||||
|
@ -174,6 +174,7 @@
|
||||
@RESPATH@/components/dom_audiochannel.xpt
|
||||
@RESPATH@/components/dom_base.xpt
|
||||
@RESPATH@/components/dom_system.xpt
|
||||
@RESPATH@/components/dom_workers.xpt
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
@RESPATH@/components/dom_wifi.xpt
|
||||
@RESPATH@/components/dom_system_gonk.xpt
|
||||
|
@ -1478,14 +1478,14 @@ pref("browser.uiCustomization.debug", false);
|
||||
pref("browser.uiCustomization.state", "");
|
||||
|
||||
// The remote content URL shown for FxA signup. Must use HTTPS.
|
||||
pref("identity.fxaccounts.remote.signup.uri", "https://accounts.firefox.com/signup?service=sync&context=fx_desktop_v1");
|
||||
pref("identity.fxaccounts.remote.signup.uri", "https://accounts.firefox.com/signup?service=sync&context=fx_desktop_v2");
|
||||
|
||||
// The URL where remote content that forces re-authentication for Firefox Accounts
|
||||
// should be fetched. Must use HTTPS.
|
||||
pref("identity.fxaccounts.remote.force_auth.uri", "https://accounts.firefox.com/force_auth?service=sync&context=fx_desktop_v1");
|
||||
pref("identity.fxaccounts.remote.force_auth.uri", "https://accounts.firefox.com/force_auth?service=sync&context=fx_desktop_v2");
|
||||
|
||||
// The remote content URL shown for signin in. Must use HTTPS.
|
||||
pref("identity.fxaccounts.remote.signin.uri", "https://accounts.firefox.com/signin?service=sync&context=fx_desktop_v1");
|
||||
pref("identity.fxaccounts.remote.signin.uri", "https://accounts.firefox.com/signin?service=sync&context=fx_desktop_v2");
|
||||
|
||||
// The remote content URL where FxAccountsWebChannel messages originate.
|
||||
pref("identity.fxaccounts.remote.webchannel.uri", "https://accounts.firefox.com/");
|
||||
|
@ -472,18 +472,8 @@ var LoopUI;
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the menu that is shown when the menu-button' dropmarker is clicked
|
||||
// inside the notification bar.
|
||||
let menuPopup = document.createElementNS(kNSXUL, "menupopup");
|
||||
let menuItem = menuPopup.appendChild(document.createElementNS(kNSXUL, "menuitem"));
|
||||
menuItem.setAttribute("label", this._getString("infobar_menuitem_dontshowagain_label"));
|
||||
menuItem.setAttribute("accesskey", this._getString("infobar_menuitem_dontshowagain_accesskey"));
|
||||
menuItem.addEventListener("command", () => {
|
||||
// We're being told to hide the bar permanently.
|
||||
this._hideBrowserSharingInfoBar(true);
|
||||
});
|
||||
|
||||
let box = gBrowser.getNotificationBox();
|
||||
let paused = false;
|
||||
let bar = box.appendNotification(
|
||||
this._getString("infobar_screenshare_browser_message"),
|
||||
kBrowserSharingNotificationId,
|
||||
@ -491,13 +481,28 @@ var LoopUI;
|
||||
null,
|
||||
box.PRIORITY_WARNING_LOW,
|
||||
[{
|
||||
label: this._getString("infobar_button_gotit_label"),
|
||||
accessKey: this._getString("infobar_button_gotit_accesskey"),
|
||||
type: "menu-button",
|
||||
popup: menuPopup,
|
||||
anchor: "dropmarker",
|
||||
label: this._getString("infobar_button_pause_label"),
|
||||
accessKey: this._getString("infobar_button_pause_accesskey"),
|
||||
isDefault: false,
|
||||
callback: (event, buttonInfo, buttonNode) => {
|
||||
paused = !paused;
|
||||
bar.label = paused ? this._getString("infobar_screenshare_paused_browser_message") :
|
||||
this._getString("infobar_screenshare_browser_message");
|
||||
bar.classList.toggle("paused", paused);
|
||||
buttonNode.label = paused ? this._getString("infobar_button_resume_label") :
|
||||
this._getString("infobar_button_pause_label");
|
||||
buttonNode.accessKey = paused ? this._getString("infobar_button_resume_accesskey") :
|
||||
this._getString("infobar_button_pause_accesskey");
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
label: this._getString("infobar_button_stop_label"),
|
||||
accessKey: this._getString("infobar_button_stop_accesskey"),
|
||||
isDefault: true,
|
||||
callback: () => {
|
||||
this._hideBrowserSharingInfoBar();
|
||||
LoopUI.MozLoopService.hangupAllChatWindows();
|
||||
}
|
||||
}]
|
||||
);
|
||||
|
@ -202,6 +202,31 @@ DistributionCustomizer.prototype = {
|
||||
PlacesUtils.annotations.EXPIRE_NEVER);
|
||||
}
|
||||
|
||||
if (item.icon && item.iconData) {
|
||||
try {
|
||||
let faviconURI = this._makeURI(item.icon);
|
||||
PlacesUtils.favicons.replaceFaviconDataFromDataURL(
|
||||
faviconURI, item.iconData, 0,
|
||||
Services.scriptSecurityManager.getSystemPrincipal());
|
||||
|
||||
PlacesUtils.favicons.setAndFetchFaviconForPage(
|
||||
this._makeURI(item.link), faviconURI, false,
|
||||
PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null,
|
||||
Services.scriptSecurityManager.getSystemPrincipal());
|
||||
} catch(e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.keyword) {
|
||||
try {
|
||||
yield PlacesUtils.keywords.insert({ keyword: item.keyword,
|
||||
url: item.link });
|
||||
} catch(e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
||||
Cu.import("resource://gre/modules/AddonManager.jsm");
|
||||
|
||||
const INTEGER = /^[1-9]\d*$/;
|
||||
|
||||
var {
|
||||
EventManager,
|
||||
} = ExtensionUtils;
|
||||
@ -18,38 +22,48 @@ var {
|
||||
// Manages icon details for toolbar buttons in the |pageAction| and
|
||||
// |browserAction| APIs.
|
||||
global.IconDetails = {
|
||||
// Accepted icon sizes.
|
||||
SIZES: ["19", "38"],
|
||||
|
||||
// Normalizes the various acceptable input formats into an object
|
||||
// with two properties, "19" and "38", containing icon URLs.
|
||||
// with icon size as key and icon URL as value.
|
||||
//
|
||||
// If a context is specified (function is called from an extension):
|
||||
// Throws an error if an invalid icon size was provided or the
|
||||
// extension is not allowed to load the specified resources.
|
||||
//
|
||||
// If no context is specified, instead of throwing an error, this
|
||||
// function simply logs a warning message.
|
||||
normalize(details, extension, context=null, localize=false) {
|
||||
let result = {};
|
||||
|
||||
if (details.imageData) {
|
||||
let imageData = details.imageData;
|
||||
try {
|
||||
if (details.imageData) {
|
||||
let imageData = details.imageData;
|
||||
|
||||
if (imageData instanceof Cu.getGlobalForObject(imageData).ImageData) {
|
||||
imageData = {"19": imageData};
|
||||
}
|
||||
if (imageData instanceof Cu.getGlobalForObject(imageData).ImageData) {
|
||||
imageData = {"19": imageData};
|
||||
}
|
||||
|
||||
for (let size of Object.keys(imageData)) {
|
||||
if (!INTEGER.test(size)) {
|
||||
throw new Error(`Invalid icon size ${size}, must be an integer`);
|
||||
}
|
||||
|
||||
for (let size of this.SIZES) {
|
||||
if (size in imageData) {
|
||||
result[size] = this.convertImageDataToPNG(imageData[size], context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (details.path) {
|
||||
let path = details.path;
|
||||
if (typeof path != "object") {
|
||||
path = {"19": path};
|
||||
}
|
||||
if (details.path) {
|
||||
let path = details.path;
|
||||
if (typeof path != "object") {
|
||||
path = {"19": path};
|
||||
}
|
||||
|
||||
let baseURI = context ? context.uri : extension.baseURI;
|
||||
let baseURI = context ? context.uri : extension.baseURI;
|
||||
|
||||
for (let size of Object.keys(path)) {
|
||||
if (!INTEGER.test(size)) {
|
||||
throw new Error(`Invalid icon size ${size}, must be an integer`);
|
||||
}
|
||||
|
||||
for (let size of this.SIZES) {
|
||||
if (size in path) {
|
||||
let url = path[size];
|
||||
if (localize) {
|
||||
url = extension.localize(url);
|
||||
@ -60,25 +74,23 @@ global.IconDetails = {
|
||||
// The Chrome documentation specifies these parameters as
|
||||
// relative paths. We currently accept absolute URLs as well,
|
||||
// which means we need to check that the extension is allowed
|
||||
// to load them.
|
||||
try {
|
||||
Services.scriptSecurityManager.checkLoadURIStrWithPrincipal(
|
||||
extension.principal, url,
|
||||
Services.scriptSecurityManager.DISALLOW_SCRIPT);
|
||||
} catch (e) {
|
||||
if (context) {
|
||||
throw e;
|
||||
}
|
||||
// If there's no context, it's because we're handling this
|
||||
// as a manifest directive. Log a warning rather than
|
||||
// raising an error, but don't accept the URL in any case.
|
||||
extension.manifestError(`Access to URL '${url}' denied`);
|
||||
continue;
|
||||
}
|
||||
// to load them. This will throw an error if it's not allowed.
|
||||
Services.scriptSecurityManager.checkLoadURIStrWithPrincipal(
|
||||
extension.principal, url,
|
||||
Services.scriptSecurityManager.DISALLOW_SCRIPT);
|
||||
|
||||
result[size] = url;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Function is called from extension code, delegate error.
|
||||
if (context) {
|
||||
throw e;
|
||||
}
|
||||
// If there's no context, it's because we're handling this
|
||||
// as a manifest directive. Log a warning rather than
|
||||
// raising an error.
|
||||
extension.manifestError(`Invalid icon data: ${e}`);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -89,12 +101,7 @@ global.IconDetails = {
|
||||
getURL(icons, window, extension) {
|
||||
const DEFAULT = "chrome://browser/content/extension.svg";
|
||||
|
||||
// Use the higher resolution image if we're doing any up-scaling
|
||||
// for high resolution monitors.
|
||||
let res = window.devicePixelRatio;
|
||||
let size = res > 1 ? "38" : "19";
|
||||
|
||||
return icons[size] || icons["19"] || icons["38"] || DEFAULT;
|
||||
return AddonManager.getPreferredIconURL({icons: icons}, 18, window) || DEFAULT;
|
||||
},
|
||||
|
||||
convertImageDataToPNG(imageData, context) {
|
||||
|
@ -101,6 +101,29 @@ add_task(function* testDetailsObjects() {
|
||||
resolutions: {
|
||||
"1": imageData.red.url,
|
||||
"2": browser.runtime.getURL("data/a.png"), } },
|
||||
|
||||
// Various resolutions
|
||||
{ details: { "path": { "18": "a.png", "32": "a-x2.png" } },
|
||||
resolutions: {
|
||||
"1": browser.runtime.getURL("data/a.png"),
|
||||
"2": browser.runtime.getURL("data/a-x2.png"), } },
|
||||
{ details: { "path": { "16": "16.png", "100": "100.png" } },
|
||||
resolutions: {
|
||||
"1": browser.runtime.getURL("data/100.png"),
|
||||
"2": browser.runtime.getURL("data/100.png"), } },
|
||||
{ details: { "path": { "2": "2.png"} },
|
||||
resolutions: {
|
||||
"1": browser.runtime.getURL("data/2.png"),
|
||||
"2": browser.runtime.getURL("data/2.png"), } },
|
||||
{ details: { "path": {
|
||||
"6": "6.png",
|
||||
"18": "18.png",
|
||||
"32": "32.png",
|
||||
"48": "48.png",
|
||||
"128": "128.png" } },
|
||||
resolutions: {
|
||||
"1": browser.runtime.getURL("data/18.png"),
|
||||
"2": browser.runtime.getURL("data/48.png"), } },
|
||||
];
|
||||
|
||||
// Allow serializing ImageData objects for logging.
|
||||
@ -197,6 +220,62 @@ add_task(function* testDetailsObjects() {
|
||||
yield extension.unload();
|
||||
});
|
||||
|
||||
// Test that an error is thrown when providing invalid icon sizes
|
||||
add_task(function *testInvalidIconSizes() {
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"browser_action": {},
|
||||
"page_action": {},
|
||||
},
|
||||
|
||||
background: function () {
|
||||
browser.tabs.query({ active: true, currentWindow: true }, tabs => {
|
||||
var tabId = tabs[0].id;
|
||||
|
||||
for (var api of ["pageAction", "browserAction"]) {
|
||||
// helper function to run setIcon and check if it fails
|
||||
let assertSetIconThrows = function(detail, error, message) {
|
||||
try {
|
||||
detail.tabId = tabId;
|
||||
browser[api].setIcon(detail);
|
||||
|
||||
browser.test.fail("Expected an error on invalid icon size.");
|
||||
browser.test.notifyFail("setIcon with invalid icon size");
|
||||
return;
|
||||
} catch (e) {
|
||||
browser.test.succeed("setIcon with invalid icon size");
|
||||
}
|
||||
}
|
||||
|
||||
// test invalid icon size inputs
|
||||
for (var type of ["path", "imageData"]) {
|
||||
assertSetIconThrows({ [type]: { "abcdef": "test.png" } });
|
||||
assertSetIconThrows({ [type]: { "48px": "test.png" } });
|
||||
assertSetIconThrows({ [type]: { "20.5": "test.png" } });
|
||||
assertSetIconThrows({ [type]: { "5.0": "test.png" } });
|
||||
assertSetIconThrows({ [type]: { "-300": "test.png" } });
|
||||
assertSetIconThrows({ [type]: {
|
||||
"abc": "test.png",
|
||||
"5": "test.png"
|
||||
}});
|
||||
}
|
||||
|
||||
assertSetIconThrows({ imageData: { "abcdef": "test.png" }, path: {"5": "test.png"} });
|
||||
assertSetIconThrows({ path: { "abcdef": "test.png" }, imageData: {"5": "test.png"} });
|
||||
}
|
||||
|
||||
browser.test.notifyPass("setIcon with invalid icon size");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
yield Promise.all([extension.startup(), extension.awaitFinish("setIcon with invalid icon size")]);
|
||||
|
||||
yield extension.unload();
|
||||
});
|
||||
|
||||
|
||||
// Test that default icon details in the manifest.json file are handled
|
||||
// correctly.
|
||||
add_task(function *testDefaultDetails() {
|
||||
@ -294,7 +373,7 @@ add_task(function* testSecureURLsDenied() {
|
||||
|
||||
yield extension.startup();
|
||||
|
||||
yield extension.awaitFinish();
|
||||
yield extension.awaitFinish("setIcon security tests");
|
||||
yield extension.unload();
|
||||
|
||||
|
||||
@ -304,12 +383,12 @@ add_task(function* testSecureURLsDenied() {
|
||||
"javascript:true"];
|
||||
|
||||
let matchURLForbidden = url => ({
|
||||
message: new RegExp(`Loading extension.*Access to.*'${url}' denied`),
|
||||
message: new RegExp(`Loading extension.*Invalid icon data: NS_ERROR_DOM_BAD_URI`),
|
||||
});
|
||||
|
||||
// Because the underlying method throws an error on invalid data,
|
||||
// only the first invalid URL of each component will be logged.
|
||||
let messages = [matchURLForbidden(urls[0]),
|
||||
matchURLForbidden(urls[1]),
|
||||
matchURLForbidden(urls[0]),
|
||||
matchURLForbidden(urls[1])];
|
||||
|
||||
let waitForConsole = new Promise(resolve => {
|
||||
@ -330,8 +409,8 @@ add_task(function* testSecureURLsDenied() {
|
||||
},
|
||||
"page_action": {
|
||||
"default_icon": {
|
||||
"19": urls[0],
|
||||
"38": urls[1],
|
||||
"19": urls[1],
|
||||
"38": urls[0],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -440,7 +440,16 @@ loop.panel = (function(_, mozL10n) {
|
||||
this.props.dispatcher.dispatch(new sharedActions.OpenRoom({
|
||||
roomToken: this.props.room.roomToken
|
||||
}));
|
||||
this.closeWindow();
|
||||
|
||||
// Open url if needed.
|
||||
loop.request("getSelectedTabMetadata").then(function(metadata) {
|
||||
var contextURL = this.props.room.decryptedContext.urls &&
|
||||
this.props.room.decryptedContext.urls[0].location;
|
||||
if (contextURL && metadata.url !== contextURL) {
|
||||
loop.request("OpenURL", contextURL);
|
||||
}
|
||||
this.closeWindow();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
handleClick: function(e) {
|
||||
|
@ -440,7 +440,16 @@ loop.panel = (function(_, mozL10n) {
|
||||
this.props.dispatcher.dispatch(new sharedActions.OpenRoom({
|
||||
roomToken: this.props.room.roomToken
|
||||
}));
|
||||
this.closeWindow();
|
||||
|
||||
// Open url if needed.
|
||||
loop.request("getSelectedTabMetadata").then(function(metadata) {
|
||||
var contextURL = this.props.room.decryptedContext.urls &&
|
||||
this.props.room.decryptedContext.urls[0].location;
|
||||
if (contextURL && metadata.url !== contextURL) {
|
||||
loop.request("OpenURL", contextURL);
|
||||
}
|
||||
this.closeWindow();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
handleClick: function(e) {
|
||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 71 KiB |
@ -0,0 +1 @@
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"><title>FX_Hello-glyph-pause-12x12</title><desc>Created with Sketch.</desc><path d="M5 .5v11c0 .136-.05.253-.149.351-.099.099-.215.149-.351.149h-4c-.136 0-.253-.05-.352-.149-.099-.098-.148-.216-.148-.351v-11c0-.136.049-.253.148-.352.099-.098.217-.148.352-.148h4c.136 0 .252.05.351.148.099.099.149.217.149.352zm7 0v11c0 .136-.05.253-.149.351-.099.099-.216.149-.351.149h-4c-.136 0-.253-.05-.352-.149-.099-.098-.148-.216-.148-.351v-11c0-.136.049-.253.148-.352.099-.098.216-.148.352-.148h4c.136 0 .252.05.351.148.099.099.149.217.149.352z" sketch:type="MSShapeGroup" fill="#333"/></svg>
|
After Width: | Height: | Size: 718 B |
@ -0,0 +1 @@
|
||||
<svg width="11" height="12" viewBox="0 0 11 12" xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"><title>FX_Hello-glyph-play-12x12</title><desc>Created with Sketch.</desc><path d="M10.695 6.24l-10.263 5.704c-.118.066-.22.074-.305.023-.085-.052-.127-.144-.127-.278v-11.377c0-.134.043-.228.127-.278.085-.052.186-.044.305.022l10.263 5.704c.118.066.178.147.178.239 0 .094-.06.174-.178.241z" sketch:type="MSShapeGroup" fill="#fff"/></svg>
|
After Width: | Height: | Size: 473 B |
@ -0,0 +1 @@
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"><title>FX_Hello-glyph-stop-12x12</title><desc>Created with Sketch.</desc><path d="M12 .5v11c0 .136-.05.253-.149.351-.099.099-.216.149-.351.149h-11c-.136 0-.253-.05-.352-.149-.099-.098-.148-.216-.148-.351v-11c0-.136.049-.253.148-.352.099-.098.217-.148.352-.148h11c.136 0 .252.05.351.148.099.099.149.217.149.352z" sketch:type="MSShapeGroup" fill="#D92215"/></svg>
|
After Width: | Height: | Size: 499 B |
@ -89,6 +89,9 @@ browser.jar:
|
||||
content/browser/loop/shared/img/animated-spinner.svg (content/shared/img/animated-spinner.svg)
|
||||
content/browser/loop/shared/img/avatars.svg (content/shared/img/avatars.svg)
|
||||
content/browser/loop/shared/img/firefox-avatar.svg (content/shared/img/firefox-avatar.svg)
|
||||
content/browser/loop/shared/img/pause-12x12.svg (content/shared/img/pause-12x12.svg)
|
||||
content/browser/loop/shared/img/play-12x12.svg (content/shared/img/play-12x12.svg)
|
||||
content/browser/loop/shared/img/stop-12x12.svg (content/shared/img/stop-12x12.svg)
|
||||
|
||||
# Shared scripts
|
||||
content/browser/loop/shared/js/actions.js (content/shared/js/actions.js)
|
||||
|
@ -875,10 +875,11 @@ var MozLoopServiceInternal = {
|
||||
*/
|
||||
hangupAllChatWindows() {
|
||||
let isLoopURL = ({ src }) => /^about:loopconversation#/.test(src);
|
||||
[...Chat.chatboxes].filter(isLoopURL).forEach(chatbox => {
|
||||
let loopChatWindows = [...Chat.chatboxes].filter(isLoopURL);
|
||||
for (let chatbox of loopChatWindows) {
|
||||
let window = chatbox.content.contentWindow;
|
||||
window.dispatchEvent(new window.CustomEvent("LoopHangupNow"));
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -82,7 +82,10 @@ describe("loop.panel", function() {
|
||||
roomToken: "QzBbvGmIZWU",
|
||||
roomUrl: "http://sample/QzBbvGmIZWU",
|
||||
decryptedContext: {
|
||||
roomName: roomName
|
||||
roomName: roomName,
|
||||
urls: [{
|
||||
location: "http://testurl.com"
|
||||
}]
|
||||
},
|
||||
maxSize: 2,
|
||||
participants: [{
|
||||
@ -665,12 +668,23 @@ describe("loop.panel", function() {
|
||||
});
|
||||
|
||||
describe("Copy button", function() {
|
||||
var roomEntry;
|
||||
var roomEntry, openURLStub;
|
||||
|
||||
beforeEach(function() {
|
||||
// Stub to prevent warnings where no stores are set up to handle the
|
||||
// actions we are testing.
|
||||
sandbox.stub(dispatcher, "dispatch");
|
||||
openURLStub = sinon.stub();
|
||||
|
||||
LoopMochaUtils.stubLoopRequest({
|
||||
GetSelectedTabMetadata: function() {
|
||||
return {
|
||||
url: "http://invalid.com",
|
||||
description: "fakeSite"
|
||||
};
|
||||
},
|
||||
OpenURL: openURLStub
|
||||
});
|
||||
|
||||
roomEntry = mountRoomEntry({
|
||||
deleteRoom: sandbox.stub(),
|
||||
@ -717,6 +731,32 @@ describe("loop.panel", function() {
|
||||
|
||||
sinon.assert.notCalled(dispatcher.dispatch);
|
||||
});
|
||||
|
||||
it("should open a new tab with the room context if it is not the same as the currently open tab", function() {
|
||||
TestUtils.Simulate.click(roomEntry.refs.roomEntry.getDOMNode());
|
||||
sinon.assert.calledOnce(openURLStub);
|
||||
sinon.assert.calledWithExactly(openURLStub, "http://testurl.com");
|
||||
});
|
||||
|
||||
it("should not open a new tab if the context is the same as the currently open tab", function() {
|
||||
LoopMochaUtils.stubLoopRequest({
|
||||
GetSelectedTabMetadata: function() {
|
||||
return {
|
||||
url: "http://testurl.com",
|
||||
description: "fakeSite"
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
roomEntry = mountRoomEntry({
|
||||
deleteRoom: sandbox.stub(),
|
||||
isOpenedRoom: false,
|
||||
room: new loop.store.Room(roomData)
|
||||
});
|
||||
|
||||
TestUtils.Simulate.click(roomEntry.refs.roomEntry.getDOMNode());
|
||||
sinon.assert.notCalled(openURLStub);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -156,11 +156,6 @@ add_task(function* test_infoBar() {
|
||||
|
||||
let button = bar.querySelector(".notification-button");
|
||||
Assert.ok(button, "There should be a button present");
|
||||
Assert.strictEqual(button.type, "menu-button", "We're expecting a menu-button");
|
||||
Assert.strictEqual(button.getAttribute("anchor"), "dropmarker",
|
||||
"The popup should be opening anchored to the dropmarker");
|
||||
Assert.strictEqual(button.getElementsByTagNameNS(kNSXUL, "menupopup").length, 1,
|
||||
"There should be a popup attached to the button");
|
||||
};
|
||||
|
||||
testBarProps();
|
||||
@ -175,11 +170,8 @@ add_task(function* test_infoBar() {
|
||||
testBarProps();
|
||||
|
||||
// Test hiding the infoBar.
|
||||
getInfoBar().querySelector(".notification-button")
|
||||
.getElementsByTagNameNS(kNSXUL, "menuitem")[0].click();
|
||||
getInfoBar().querySelector(".notification-button-default").click();
|
||||
Assert.equal(getInfoBar(), null, "The notification should be hidden now");
|
||||
Assert.strictEqual(Services.prefs.getBoolPref(kPrefBrowserSharingInfoBar), false,
|
||||
"The pref should be set to false when the menu item is clicked");
|
||||
|
||||
gBrowser.selectedIndex = Array.indexOf(gBrowser.tabs, createdTabs[1]);
|
||||
|
||||
|
@ -7,6 +7,7 @@ const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource:///modules/MigrationUtils.jsm");
|
||||
Cu.import("resource:///modules/MSMigrationUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
@ -15,6 +16,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
const kEdgeRegistryRoot = "SOFTWARE\\Classes\\Local Settings\\Software\\" +
|
||||
"Microsoft\\Windows\\CurrentVersion\\AppContainer\\Storage\\" +
|
||||
"microsoft.microsoftedge_8wekyb3d8bbwe\\MicrosoftEdge";
|
||||
const kEdgeReadingListPath = "AC\\MicrosoftEdge\\User\\Default\\DataStore\\Data\\";
|
||||
|
||||
function EdgeTypedURLMigrator() {
|
||||
}
|
||||
@ -79,6 +81,112 @@ EdgeTypedURLMigrator.prototype = {
|
||||
},
|
||||
}
|
||||
|
||||
function EdgeReadingListMigrator() {
|
||||
}
|
||||
|
||||
EdgeReadingListMigrator.prototype = {
|
||||
type: MigrationUtils.resourceTypes.BOOKMARKS,
|
||||
|
||||
get exists() {
|
||||
return !!MSMigrationUtils.getEdgeLocalDataFolder();
|
||||
},
|
||||
|
||||
migrate(callback) {
|
||||
this._migrateReadingList(PlacesUtils.bookmarks.menuGuid).then(
|
||||
() => callback(true),
|
||||
ex => {
|
||||
Cu.reportError(ex);
|
||||
callback(false);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
_migrateReadingList: Task.async(function*(parentGuid) {
|
||||
let edgeDir = MSMigrationUtils.getEdgeLocalDataFolder();
|
||||
if (!edgeDir) {
|
||||
return;
|
||||
}
|
||||
this._readingListExtractor = Cc["@mozilla.org/profile/migrator/edgereadinglistextractor;1"].
|
||||
createInstance(Ci.nsIEdgeReadingListExtractor);
|
||||
edgeDir.appendRelativePath(kEdgeReadingListPath);
|
||||
let errorProduced = null;
|
||||
if (edgeDir.exists() && edgeDir.isReadable() && edgeDir.isDirectory()) {
|
||||
let expectedDir = edgeDir.clone();
|
||||
expectedDir.appendRelativePath("nouser1\\120712-0049");
|
||||
if (expectedDir.exists() && expectedDir.isReadable() && expectedDir.isDirectory()) {
|
||||
yield this._migrateReadingListDB(expectedDir, parentGuid).catch(ex => {
|
||||
if (!errorProduced)
|
||||
errorProduced = ex;
|
||||
});
|
||||
} else {
|
||||
let getSubdirs = someDir => {
|
||||
let subdirs = someDir.directoryEntries;
|
||||
let rv = [];
|
||||
while (subdirs.hasMoreElements()) {
|
||||
let subdir = subdirs.getNext().QueryInterface(Ci.nsIFile);
|
||||
if (subdir.isDirectory() && subdir.isReadable()) {
|
||||
rv.push(subdir);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
};
|
||||
let dirs = getSubdirs(edgeDir).map(getSubdirs);
|
||||
for (let dir of dirs) {
|
||||
yield this._migrateReadingListDB(dir, parentGuid).catch(ex => {
|
||||
if (!errorProduced)
|
||||
errorProduced = ex;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (errorProduced) {
|
||||
throw errorProduced;
|
||||
}
|
||||
}),
|
||||
_migrateReadingListDB: Task.async(function*(dbFile, parentGuid) {
|
||||
dbFile.appendRelativePath("DBStore\\spartan.edb");
|
||||
|
||||
if (!dbFile.exists() || !dbFile.isReadable() || !dbFile.isFile()) {
|
||||
return;
|
||||
}
|
||||
let readingListItems;
|
||||
try {
|
||||
readingListItems = this._readingListExtractor.extract(dbFile.path);
|
||||
} catch (ex) {
|
||||
Cu.reportError("Failed to extract Edge reading list information from " +
|
||||
"the database at " + dbFile.path + " due to the following error: " + ex);
|
||||
// Deliberately make this fail so we expose failure in the UI:
|
||||
throw ex;
|
||||
return;
|
||||
}
|
||||
if (!readingListItems.length) {
|
||||
return;
|
||||
}
|
||||
let destFolderGuid = yield this._ensureReadingListFolder(parentGuid);
|
||||
for (let i = 0; i < readingListItems.length; i++) {
|
||||
let readingListItem = readingListItems.queryElementAt(i, Ci.nsIPropertyBag2);
|
||||
let url = readingListItem.get("uri");
|
||||
let title = readingListItem.get("title");
|
||||
let time = readingListItem.get("time");
|
||||
// time is a PRTime, which is microseconds (since unix epoch), or null.
|
||||
// We need milliseconds for the date constructor, so divide by 1000:
|
||||
let dateAdded = time ? new Date(time / 1000) : new Date();
|
||||
yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: destFolderGuid, url: url, title, dateAdded
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
_ensureReadingListFolder: Task.async(function*(parentGuid) {
|
||||
if (!this.__readingListFolderGuid) {
|
||||
let folderTitle = MigrationUtils.getLocalizedString("importedEdgeReadingList");
|
||||
let folderSpec = {type: PlacesUtils.bookmarks.TYPE_FOLDER, parentGuid, title: folderTitle};
|
||||
this.__readingListFolderGuid = (yield PlacesUtils.bookmarks.insert(folderSpec)).guid;
|
||||
}
|
||||
return this.__readingListFolderGuid;
|
||||
}),
|
||||
};
|
||||
|
||||
function EdgeProfileMigrator() {
|
||||
}
|
||||
|
||||
@ -89,6 +197,7 @@ EdgeProfileMigrator.prototype.getResources = function() {
|
||||
MSMigrationUtils.getBookmarksMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE),
|
||||
MSMigrationUtils.getCookiesMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE),
|
||||
new EdgeTypedURLMigrator(),
|
||||
new EdgeReadingListMigrator(),
|
||||
];
|
||||
let windowsVaultFormPasswordsMigrator =
|
||||
MSMigrationUtils.getWindowsVaultFormPasswordsMigrator();
|
||||
|
@ -26,7 +26,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "ctypes",
|
||||
const EDGE_COOKIE_PATH_OPTIONS = ["", "#!001\\", "#!002\\"];
|
||||
const EDGE_COOKIES_SUFFIX = "MicrosoftEdge\\Cookies";
|
||||
const EDGE_FAVORITES = "AC\\MicrosoftEdge\\User\\Default\\Favorites";
|
||||
const EDGE_READINGLIST = "AC\\MicrosoftEdge\\User\\Default\\DataStore\\Data\\";
|
||||
const FREE_CLOSE_FAILED = 0;
|
||||
const INTERNET_EXPLORER_EDGE_GUID = [0x3CCD5499,
|
||||
0x4B1087A8,
|
||||
@ -376,10 +375,6 @@ Bookmarks.prototype = {
|
||||
yield MigrationUtils.createImportedBookmarksFolder(this.importedAppLabel, folderGuid);
|
||||
}
|
||||
yield this._migrateFolder(this._favoritesFolder, folderGuid);
|
||||
|
||||
if (this._migrationType == MSMigrationUtils.MIGRATION_TYPE_EDGE) {
|
||||
yield this._migrateEdgeReadingList(PlacesUtils.bookmarks.menuGuid);
|
||||
}
|
||||
}.bind(this)).then(() => aCallback(true),
|
||||
e => { Cu.reportError(e); aCallback(false) });
|
||||
},
|
||||
@ -390,6 +385,7 @@ Bookmarks.prototype = {
|
||||
// for IE, and in a similar location for Edge.
|
||||
// Until we support it, bookmarks are imported in alphabetical order.
|
||||
let entries = aSourceFolder.directoryEntries;
|
||||
let succeeded = true;
|
||||
while (entries.hasMoreElements()) {
|
||||
let entry = entries.getNext().QueryInterface(Ci.nsIFile);
|
||||
try {
|
||||
@ -439,82 +435,14 @@ Bookmarks.prototype = {
|
||||
}
|
||||
} catch (ex) {
|
||||
Components.utils.reportError("Unable to import " + this.importedAppLabel + " favorite (" + entry.leafName + "): " + ex);
|
||||
succeeded = false;
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
_migrateEdgeReadingList: Task.async(function*(parentGuid) {
|
||||
let edgeDir = getEdgeLocalDataFolder();
|
||||
if (!edgeDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._readingListExtractor = Cc["@mozilla.org/profile/migrator/edgereadinglistextractor;1"].
|
||||
createInstance(Ci.nsIEdgeReadingListExtractor);
|
||||
edgeDir.appendRelativePath(EDGE_READINGLIST);
|
||||
if (edgeDir.exists() && edgeDir.isReadable() && edgeDir.isDirectory()) {
|
||||
let expectedDir = edgeDir.clone();
|
||||
expectedDir.appendRelativePath("nouser1\\120712-0049");
|
||||
if (expectedDir.exists() && expectedDir.isReadable() && expectedDir.isDirectory()) {
|
||||
yield this._migrateEdgeReadingListDB(expectedDir, parentGuid);
|
||||
} else {
|
||||
let getSubdirs = someDir => {
|
||||
let subdirs = someDir.directoryEntries;
|
||||
let rv = [];
|
||||
while (subdirs.hasMoreElements()) {
|
||||
let subdir = subdirs.getNext().QueryInterface(Ci.nsIFile);
|
||||
if (subdir.isDirectory() && subdir.isReadable()) {
|
||||
rv.push(subdir);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
};
|
||||
let dirs = getSubdirs(edgeDir).map(getSubdirs);
|
||||
for (let dir of dirs) {
|
||||
yield this._migrateEdgeReadingListDB(dir, parentGuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
_migrateEdgeReadingListDB: Task.async(function*(dbFile, parentGuid) {
|
||||
dbFile.appendRelativePath("DBStore\\spartan.edb");
|
||||
if (!dbFile.exists() || !dbFile.isReadable() || !dbFile.isFile()) {
|
||||
return;
|
||||
}
|
||||
let readingListItems;
|
||||
try {
|
||||
readingListItems = this._readingListExtractor.extract(dbFile.path);
|
||||
} catch (ex) {
|
||||
Cu.reportError("Failed to extract Edge reading list information from " +
|
||||
"the database at " + dbPath + " due to the following error: " + ex);
|
||||
return;
|
||||
}
|
||||
if (!readingListItems.length) {
|
||||
return;
|
||||
}
|
||||
let destFolderGuid = yield this._ensureEdgeReadingListFolder(parentGuid);
|
||||
for (let i = 0; i < readingListItems.length; i++) {
|
||||
let readingListItem = readingListItems.queryElementAt(i, Ci.nsIPropertyBag2);
|
||||
let url = readingListItem.get("uri");
|
||||
let title = readingListItem.get("title");
|
||||
let time = readingListItem.get("time");
|
||||
// time is a PRTime, which is microseconds (since unix epoch), or null.
|
||||
// We need milliseconds for the date constructor, so divide by 1000:
|
||||
let dateAdded = time ? new Date(time / 1000) : new Date();
|
||||
yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: destFolderGuid, url: url, title, dateAdded
|
||||
});
|
||||
if (!succeeded) {
|
||||
throw new Error("Failed to import all bookmarks correctly.");
|
||||
}
|
||||
}),
|
||||
|
||||
_ensureEdgeReadingListFolder: Task.async(function*(parentGuid) {
|
||||
if (!this.__edgeReadingListFolderGuid) {
|
||||
let folderTitle = MigrationUtils.getLocalizedString("importedEdgeReadingList");
|
||||
let folderSpec = {type: PlacesUtils.bookmarks.TYPE_FOLDER, parentGuid, title: folderTitle};
|
||||
this.__edgeReadingListFolderGuid = (yield PlacesUtils.bookmarks.insert(folderSpec)).guid;
|
||||
}
|
||||
return this.__edgeReadingListFolderGuid;
|
||||
}),
|
||||
};
|
||||
|
||||
function Cookies(migrationType) {
|
||||
@ -948,4 +876,5 @@ var MSMigrationUtils = {
|
||||
return new WindowsVaultFormPasswords();
|
||||
},
|
||||
getTypedURLs,
|
||||
getEdgeLocalDataFolder,
|
||||
};
|
||||
|
@ -197,7 +197,13 @@ nsEdgeReadingListExtractor::ConvertJETError(const JET_ERR &aError)
|
||||
return NS_ERROR_FILE_INVALID_PATH;
|
||||
case JET_errFileNotFound:
|
||||
return NS_ERROR_FILE_NOT_FOUND;
|
||||
case JET_errDatabaseDirtyShutdown:
|
||||
return NS_ERROR_FILE_CORRUPTED;
|
||||
default:
|
||||
nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||
wchar_t* msg = new wchar_t[80];
|
||||
swprintf(msg, 80, MOZ_UTF16("Unexpected JET error from ESE database: %ld"), aError);
|
||||
consoleService->LogStringMessage(msg);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
@ -8,14 +8,20 @@ about=Test distribution file
|
||||
|
||||
[BookmarksToolbar]
|
||||
item.1.title=Toolbar Link Before
|
||||
item.1.link=http://mozilla.com/
|
||||
item.1.link=https://example.org/toolbar/before/
|
||||
item.1.keyword=e:t:b
|
||||
item.1.icon=https://example.org/favicon.png
|
||||
item.1.iconData=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==
|
||||
item.2.type=default
|
||||
item.3.title=Toolbar Link After
|
||||
item.3.link=http://mozilla.com/
|
||||
item.3.link=https://example.org/toolbar/after/
|
||||
item.3.keyword=e:t:a
|
||||
|
||||
[BookmarksMenu]
|
||||
item.1.title=Menu Link Before
|
||||
item.1.link=http://mozilla.com/
|
||||
item.1.link=https://example.org/menu/before/
|
||||
item.1.icon=https://example.org/favicon.png
|
||||
item.1.iconData=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==
|
||||
item.2.type=default
|
||||
item.3.title=Menu Link After
|
||||
item.3.link=http://mozilla.com/
|
||||
item.3.link=https://example.org/menu/after/
|
||||
|
@ -119,3 +119,34 @@ function rebuildSmartBookmarks() {
|
||||
Services.console.unregisterListener(consoleListener);
|
||||
});
|
||||
}
|
||||
|
||||
const SINGLE_TRY_TIMEOUT = 100;
|
||||
const NUMBER_OF_TRIES = 30;
|
||||
|
||||
/**
|
||||
* Similar to waitForConditionPromise, but poll for an asynchronous value
|
||||
* every SINGLE_TRY_TIMEOUT ms, for no more than tryCount times.
|
||||
*
|
||||
* @param promiseFn
|
||||
* A function to generate a promise, which resolves to the expected
|
||||
* asynchronous value.
|
||||
* @param timeoutMsg
|
||||
* The reason to reject the returned promise with.
|
||||
* @param [optional] tryCount
|
||||
* Maximum times to try before rejecting the returned promise with
|
||||
* timeoutMsg, defaults to NUMBER_OF_TRIES.
|
||||
* @return {Promise}
|
||||
* @resolves to the asynchronous value being polled.
|
||||
* @rejects if the asynchronous value is not available after tryCount attempts.
|
||||
*/
|
||||
var waitForResolvedPromise = Task.async(function* (promiseFn, timeoutMsg, tryCount=NUMBER_OF_TRIES) {
|
||||
let tries = 0;
|
||||
do {
|
||||
try {
|
||||
let value = yield promiseFn();
|
||||
return value;
|
||||
} catch (ex) {}
|
||||
yield new Promise(resolve => do_timeout(SINGLE_TRY_TIMEOUT, resolve));
|
||||
} while (++tries <= tryCount);
|
||||
throw(timeoutMsg);
|
||||
});
|
||||
|
@ -76,6 +76,16 @@ add_task(function* () {
|
||||
});
|
||||
Assert.equal(menuItem.title, "Menu Link After");
|
||||
|
||||
// Check no favicon or keyword exists for this bookmark
|
||||
yield Assert.rejects(waitForResolvedPromise(() => {
|
||||
return PlacesUtils.promiseFaviconData(menuItem.url.href);
|
||||
}, "Favicon not found", 10), /Favicon\snot\sfound/, "Favicon not found");
|
||||
|
||||
let keywordItem = yield PlacesUtils.keywords.fetch({
|
||||
url: menuItem.url.href
|
||||
});
|
||||
Assert.strictEqual(keywordItem, null);
|
||||
|
||||
// Check the custom bookmarks exist on toolbar.
|
||||
let toolbarItem = yield PlacesUtils.bookmarks.fetch({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
@ -83,6 +93,24 @@ add_task(function* () {
|
||||
});
|
||||
Assert.equal(toolbarItem.title, "Toolbar Link Before");
|
||||
|
||||
// Check the custom favicon and keyword exist for this bookmark
|
||||
let faviconItem = yield waitForResolvedPromise(() => {
|
||||
return PlacesUtils.promiseFaviconData(toolbarItem.url.href);
|
||||
}, "Favicon not found", 10);
|
||||
Assert.equal(faviconItem.uri.spec, "https://example.org/favicon.png");
|
||||
Assert.greater(faviconItem.dataLen, 0);
|
||||
Assert.equal(faviconItem.mimeType, "image/png");
|
||||
|
||||
let base64Icon = "data:image/png;base64," +
|
||||
base64EncodeString(String.fromCharCode.apply(String, faviconItem.data));
|
||||
Assert.equal(base64Icon, SMALLPNG_DATA_URI.spec);
|
||||
|
||||
keywordItem = yield PlacesUtils.keywords.fetch({
|
||||
url: toolbarItem.url.href
|
||||
});
|
||||
Assert.notStrictEqual(keywordItem, null);
|
||||
Assert.equal(keywordItem.keyword, "e:t:b");
|
||||
|
||||
toolbarItem = yield PlacesUtils.bookmarks.fetch({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
index: 1 + DEFAULT_BOOKMARKS_ON_TOOLBAR
|
||||
|
@ -1250,6 +1250,19 @@ var SessionStoreInternal = {
|
||||
// we don't want to save the busy state
|
||||
delete winData.busy;
|
||||
|
||||
// When closing windows one after the other until Firefox quits, we
|
||||
// will move those closed in series back to the "open windows" bucket
|
||||
// before writing to disk. If however there is only a single window
|
||||
// with tabs we deem not worth saving then we might end up with a
|
||||
// random closed or even a pop-up window re-opened. To prevent that
|
||||
// we explicitly allow saving an "empty" window state.
|
||||
let isLastWindow =
|
||||
Object.keys(this._windows).length == 1 &&
|
||||
!this._closedWindows.some(win => win._shouldRestore || false);
|
||||
|
||||
// clear this window from the list, since it has definitely been closed.
|
||||
delete this._windows[aWindow.__SSi];
|
||||
|
||||
// Now we have to figure out if this window is worth saving in the _closedWindows
|
||||
// Object.
|
||||
//
|
||||
@ -1265,7 +1278,7 @@ var SessionStoreInternal = {
|
||||
if (!winData.isPrivate) {
|
||||
// Remove any open private tabs the window may contain.
|
||||
PrivacyFilter.filterPrivateTabs(winData);
|
||||
this.maybeSaveClosedWindow(winData);
|
||||
this.maybeSaveClosedWindow(winData, isLastWindow);
|
||||
}
|
||||
|
||||
// The tabbrowser binding will go away once the window is closed,
|
||||
@ -1292,11 +1305,9 @@ var SessionStoreInternal = {
|
||||
// It's possible that a tab switched its privacy state at some point
|
||||
// before our flush, so we need to filter again.
|
||||
PrivacyFilter.filterPrivateTabs(winData);
|
||||
this.maybeSaveClosedWindow(winData);
|
||||
this.maybeSaveClosedWindow(winData, isLastWindow);
|
||||
}
|
||||
|
||||
// clear this window from the list
|
||||
delete this._windows[aWindow.__SSi];
|
||||
// Update the tabs data now that we've got the most
|
||||
// recent information.
|
||||
this.cleanUpWindow(aWindow, winData);
|
||||
@ -1313,7 +1324,6 @@ var SessionStoreInternal = {
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Clean up the message listeners on a window that has finally
|
||||
* gone away. Call this once you're sure you don't want to hear
|
||||
@ -1345,22 +1355,19 @@ var SessionStoreInternal = {
|
||||
*
|
||||
* @param winData
|
||||
* The data for the closed window that we might save.
|
||||
* @param isLastWindow
|
||||
* Whether or not the window being closed is the last
|
||||
* browser window. Callers of this function should pass
|
||||
* in the value of SessionStoreInternal.atLastWindow for
|
||||
* this argument, and pass in the same value if they happen
|
||||
* to call this method again asynchronously (for example, after
|
||||
* a window flush).
|
||||
*/
|
||||
maybeSaveClosedWindow(winData) {
|
||||
maybeSaveClosedWindow(winData, isLastWindow) {
|
||||
if (RunState.isRunning) {
|
||||
// Determine whether the window has any tabs worth saving.
|
||||
let hasSaveableTabs = winData.tabs.some(this._shouldSaveTabState);
|
||||
|
||||
// When closing windows one after the other until Firefox quits, we
|
||||
// will move those closed in series back to the "open windows" bucket
|
||||
// before writing to disk. If however there is only a single window
|
||||
// with tabs we deem not worth saving then we might end up with a
|
||||
// random closed or even a pop-up window re-opened. To prevent that
|
||||
// we explicitly allow saving an "empty" window state.
|
||||
let isLastWindow =
|
||||
Object.keys(this._windows).length == 1 &&
|
||||
!this._closedWindows.some(win => win._shouldRestore || false);
|
||||
|
||||
// Note that we might already have this window stored in
|
||||
// _closedWindows from a previous call to this function.
|
||||
let winIndex = this._closedWindows.indexOf(winData);
|
||||
|
@ -217,3 +217,4 @@ skip-if = os == "mac"
|
||||
[browser_send_async_message_oom.js]
|
||||
[browser_multiple_navigateAndRestore.js]
|
||||
run-if = e10s
|
||||
[browser_async_window_flushing.js]
|
||||
|
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Tests that when we close a window, it is immediately removed from the
|
||||
* _windows array.
|
||||
*/
|
||||
add_task(function* test_synchronously_remove_window_state() {
|
||||
// Depending on previous tests, we might already have some closed
|
||||
// windows stored. We'll use its length to determine whether or not
|
||||
// the window was added or not.
|
||||
let state = JSON.parse(ss.getBrowserState());
|
||||
ok(state, "Make sure we can get the state");
|
||||
let initialWindows = state.windows.length;
|
||||
|
||||
// Open a new window and send the first tab somewhere
|
||||
// interesting.
|
||||
let newWin = yield BrowserTestUtils.openNewBrowserWindow();
|
||||
let browser = newWin.gBrowser.selectedBrowser;
|
||||
browser.loadURI("http://example.com");
|
||||
yield BrowserTestUtils.browserLoaded(browser);
|
||||
yield TabStateFlusher.flush(browser);
|
||||
|
||||
state = JSON.parse(ss.getBrowserState());
|
||||
is(state.windows.length, initialWindows + 1,
|
||||
"The new window to be in the state");
|
||||
|
||||
// Now close the window, and make sure that the window was removed
|
||||
// from the windows list from the SessionState. We're specifically
|
||||
// testing the case where the window is _not_ removed in between
|
||||
// the close-initiated flush request and the flush response.
|
||||
let windowClosed = BrowserTestUtils.windowClosed(newWin);
|
||||
newWin.close();
|
||||
|
||||
state = JSON.parse(ss.getBrowserState());
|
||||
is(state.windows.length, initialWindows,
|
||||
"The new window should have been removed from the state");
|
||||
|
||||
// Wait for our window to go away
|
||||
yield windowClosed;
|
||||
});
|
@ -198,11 +198,14 @@ room_name_untitled_page=Untitled Page
|
||||
|
||||
# Infobar strings
|
||||
|
||||
infobar_screenshare_browser_message=Users in your conversation will now be able to see the contents of any tab you click on.
|
||||
infobar_button_gotit_label=Got it!
|
||||
infobar_button_gotit_accesskey=G
|
||||
infobar_menuitem_dontshowagain_label=Don't show this again
|
||||
infobar_menuitem_dontshowagain_accesskey=D
|
||||
infobar_screenshare_browser_message=You are sharing your tabs. Any tab you click on can be seen by your friends
|
||||
infobar_screenshare_paused_browser_message=Tab sharing is paused
|
||||
infobar_button_pause_label=Pause
|
||||
infobar_button_resume_label=Resume
|
||||
infobar_button_stop_label=Stop
|
||||
infobar_button_pause_accesskey=P
|
||||
infobar_button_stop_accesskey=S
|
||||
infobar_button_resume_accesskey=R
|
||||
|
||||
# Context in conversation strings
|
||||
|
||||
|
@ -1118,16 +1118,6 @@ notification[value="translation"] menulist > .menulist-dropmarker {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Loop/ Hello browser styles */
|
||||
|
||||
notification[value="loop-sharing-notification"] .button-menubutton-button {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"] .messageImage {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-shareScreen-16.png);
|
||||
}
|
||||
|
||||
#treecolAutoCompleteImage {
|
||||
max-width : 36px;
|
||||
}
|
||||
|
@ -3212,24 +3212,37 @@ menulist.translate-infobar-element > .menulist-dropmarker {
|
||||
}
|
||||
|
||||
/* Loop/ Hello browser styles */
|
||||
notification[value="loop-sharing-notification"] {
|
||||
background: #00a9dc;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"].paused {
|
||||
background: #ebebeb;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"] .notification-button {
|
||||
padding: 1px 5px;
|
||||
background: #fff;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"] .button-menubutton-button {
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
margin: 0;
|
||||
notification[value="loop-sharing-notification"].paused .notification-button {
|
||||
background: #57bd35;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"] .messageImage {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-sharingScreen-menubar.png);
|
||||
notification[value="loop-sharing-notification"].paused .notification-button:hover {
|
||||
background: #39a017;
|
||||
}
|
||||
@media (min-resolution: 2dppx) {
|
||||
notification[value="loop-sharing-notification"] .messageImage {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-sharingScreen-menubar@2x.png);
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"] .notification-button:hover,
|
||||
notification[value="loop-sharing-notification"].paused .notification-button-default:hover {
|
||||
background: #ebebeb;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"] .notification-button-default,
|
||||
notification[value="loop-sharing-notification"].paused .notification-button-default {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.popup-notification-body[popupid="addon-progress"],
|
||||
|
@ -445,3 +445,83 @@
|
||||
}
|
||||
%endif
|
||||
}
|
||||
|
||||
/* Loop notification */
|
||||
notification[value="loop-sharing-notification"] {
|
||||
-moz-appearance: none;
|
||||
height: 40px;
|
||||
background-color: #00a9dc;
|
||||
box-shadow: 0 40px 1px rgba(0,0,0,.5) inset;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"].paused {
|
||||
background-color: #ebebeb;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"] .notification-inner {
|
||||
color: #fff;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"].paused .notification-inner {
|
||||
color: #00a9dc;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"] .notification-button {
|
||||
-moz-appearance: none;
|
||||
background-color: #fff;
|
||||
border: 0;
|
||||
border-right: solid 1px #ebebeb;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
margin: 0;
|
||||
list-style-image: url(chrome://browser/content/loop/shared/img/pause-12x12.svg);
|
||||
box-shadow: 0 40px 1px rgba(0,0,0,.5) inset;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"] .notification-button:-moz-locale-dir(rtl) {
|
||||
border-right: 0;
|
||||
border-left: solid 1px #ebebeb;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"].paused .notification-button {
|
||||
background-color: #57bd35;
|
||||
color: #fff;
|
||||
list-style-image: url(chrome://browser/content/loop/shared/img/play-12x12.svg);
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"].paused .notification-button:hover {
|
||||
background-color: #39a017;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"] .notification-button:hover,
|
||||
notification[value="loop-sharing-notification"].paused .notification-button-default:hover {
|
||||
background-color: #ebebeb;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"] .notification-button-default,
|
||||
notification[value="loop-sharing-notification"].paused .notification-button-default {
|
||||
color: #d92215;
|
||||
background-color: #fff;
|
||||
border-right: 0;
|
||||
list-style-image: url(chrome://browser/content/loop/shared/img/stop-12x12.svg);
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"] .notification-button .button-icon {
|
||||
display: block;
|
||||
-moz-margin-end: 6px;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"] .button-menubutton-button {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"] .messageImage {
|
||||
list-style-image: url(chrome://browser/content/loop/shared/img/icons-16x16.svg#loop-icon-white);
|
||||
margin-inline-start: 14px;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"].paused .messageImage {
|
||||
list-style-image: url(chrome://browser/content/loop/shared/img/icons-16x16.svg#loop-icon-still);
|
||||
}
|
@ -2316,19 +2316,6 @@ notification[value="translation"] {
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
/* Loop/ Hello browser styles */
|
||||
|
||||
notification[value="loop-sharing-notification"] .button-menubutton-button {
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
notification[value="loop-sharing-notification"] .messageImage {
|
||||
list-style-image: url(chrome://browser/skin/webRTC-shareScreen-16.png);
|
||||
}
|
||||
|
||||
/* Bookmarks roots menu-items */
|
||||
#subscribeToPageMenuitem:not([disabled]),
|
||||
#subscribeToPageMenupopup,
|
||||
|
@ -28,26 +28,74 @@ namespace mozilla {
|
||||
|
||||
using dom::URLParams;
|
||||
|
||||
void OriginAttributes::InheritFromDocShellParent(const OriginAttributes& aParent)
|
||||
void
|
||||
PrincipalOriginAttributes::InheritFromDocShellToDoc(const DocShellOriginAttributes& aAttrs,
|
||||
const nsIURI* aURI)
|
||||
{
|
||||
mAppId = aParent.mAppId;
|
||||
mInBrowser = aParent.mInBrowser;
|
||||
mUserContextId = aParent.mUserContextId;
|
||||
mSignedPkg = aParent.mSignedPkg;
|
||||
mAppId = aAttrs.mAppId;
|
||||
mInBrowser = aAttrs.mInBrowser;
|
||||
|
||||
// addonId is computed from the principal URI and never propagated
|
||||
mUserContextId = aAttrs.mUserContextId;
|
||||
|
||||
// TODO:
|
||||
// Bug 1225349 - PrincipalOriginAttributes should inherit mSignedPkg
|
||||
// accordingly by URI
|
||||
mSignedPkg = aAttrs.mSignedPkg;
|
||||
}
|
||||
|
||||
bool OriginAttributes::CopyFromLoadContext(nsILoadContext* aLoadContext)
|
||||
void
|
||||
PrincipalOriginAttributes::InheritFromNecko(const NeckoOriginAttributes& aAttrs)
|
||||
{
|
||||
OriginAttributes attrs;
|
||||
bool result = aLoadContext->GetOriginAttributes(attrs);
|
||||
NS_ENSURE_TRUE(result, false);
|
||||
mAppId = aAttrs.mAppId;
|
||||
mInBrowser = aAttrs.mInBrowser;
|
||||
|
||||
mAppId = attrs.mAppId;
|
||||
mInBrowser = attrs.mInBrowser;
|
||||
mAddonId = attrs.mAddonId;
|
||||
mUserContextId = attrs.mUserContextId;
|
||||
mSignedPkg = attrs.mSignedPkg;
|
||||
return true;
|
||||
// addonId is computed from the principal URI and never propagated
|
||||
mUserContextId = aAttrs.mUserContextId;
|
||||
mSignedPkg = aAttrs.mSignedPkg;
|
||||
}
|
||||
|
||||
void
|
||||
DocShellOriginAttributes::InheritFromDocToChildDocShell(const PrincipalOriginAttributes& aAttrs)
|
||||
{
|
||||
mAppId = aAttrs.mAppId;
|
||||
mInBrowser = aAttrs.mInBrowser;
|
||||
|
||||
// addonId is computed from the principal URI and never propagated
|
||||
mUserContextId = aAttrs.mUserContextId;
|
||||
|
||||
// TODO:
|
||||
// Bug 1225353 - DocShell/NeckoOriginAttributes should inherit
|
||||
// mSignedPkg accordingly by mSignedPkgInBrowser
|
||||
mSignedPkg = aAttrs.mSignedPkg;
|
||||
}
|
||||
|
||||
void
|
||||
NeckoOriginAttributes::InheritFromDocToNecko(const PrincipalOriginAttributes& aAttrs)
|
||||
{
|
||||
mAppId = aAttrs.mAppId;
|
||||
mInBrowser = aAttrs.mInBrowser;
|
||||
|
||||
// addonId is computed from the principal URI and never propagated
|
||||
mUserContextId = aAttrs.mUserContextId;
|
||||
|
||||
// TODO:
|
||||
// Bug 1225353 - DocShell/NeckoOriginAttributes should inherit
|
||||
// mSignedPkg accordingly by mSignedPkgInBrowser
|
||||
}
|
||||
|
||||
void
|
||||
NeckoOriginAttributes::InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs)
|
||||
{
|
||||
mAppId = aAttrs.mAppId;
|
||||
mInBrowser = aAttrs.mInBrowser;
|
||||
|
||||
// addonId is computed from the principal URI and never propagated
|
||||
mUserContextId = aAttrs.mUserContextId;
|
||||
|
||||
// TODO:
|
||||
// Bug 1225353 - DocShell/NeckoOriginAttributes should inherit
|
||||
// mSignedPkg accordingly by mSignedPkgInBrowser
|
||||
}
|
||||
|
||||
void
|
||||
@ -454,7 +502,7 @@ BasePrincipal::GetUnknownAppId(bool* aUnknownAppId)
|
||||
}
|
||||
|
||||
already_AddRefed<BasePrincipal>
|
||||
BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAttrs)
|
||||
BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, const PrincipalOriginAttributes& aAttrs)
|
||||
{
|
||||
// If the URI is supposed to inherit the security context of whoever loads it,
|
||||
// we shouldn't make a codebase principal for it.
|
||||
@ -495,7 +543,7 @@ BasePrincipal::CreateCodebasePrincipal(const nsACString& aOrigin)
|
||||
"CreateCodebasePrincipal does not support nsNullPrincipal");
|
||||
|
||||
nsAutoCString originNoSuffix;
|
||||
mozilla::OriginAttributes attrs;
|
||||
mozilla::PrincipalOriginAttributes attrs;
|
||||
if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -14,26 +14,19 @@
|
||||
#include "mozilla/dom/ChromeUtilsBinding.h"
|
||||
|
||||
class nsIContentSecurityPolicy;
|
||||
class nsILoadContext;
|
||||
class nsIObjectOutputStream;
|
||||
class nsIObjectInputStream;
|
||||
class nsIURI;
|
||||
|
||||
class nsExpandedPrincipal;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Base OriginAttributes class. This has several subclass flavors, and is not
|
||||
// directly constructable itself.
|
||||
class OriginAttributes : public dom::OriginAttributesDictionary
|
||||
{
|
||||
public:
|
||||
OriginAttributes() {}
|
||||
OriginAttributes(uint32_t aAppId, bool aInBrowser)
|
||||
{
|
||||
mAppId = aAppId;
|
||||
mInBrowser = aInBrowser;
|
||||
}
|
||||
explicit OriginAttributes(const OriginAttributesDictionary& aOther)
|
||||
: OriginAttributesDictionary(aOther) {}
|
||||
|
||||
bool operator==(const OriginAttributes& aOther) const
|
||||
{
|
||||
return mAppId == aOther.mAppId &&
|
||||
@ -47,28 +40,6 @@ public:
|
||||
return !(*this == aOther);
|
||||
}
|
||||
|
||||
// The docshell often influences the origin attributes of content loaded
|
||||
// inside of it, and in some cases also influences the origin attributes of
|
||||
// content loaded in child docshells. We say that a given attribute "lives on
|
||||
// the docshell" to indicate that this attribute is specified by the docshell
|
||||
// (if any) associated with a given content document.
|
||||
//
|
||||
// In practice, this usually means that we need to store a copy of those
|
||||
// attributes on each docshell, or provide methods on the docshell to compute
|
||||
// them on-demand.
|
||||
// We could track each of these attributes individually, but since the
|
||||
// majority of the existing origin attributes currently live on the docshell,
|
||||
// it's cleaner to simply store an entire OriginAttributes struct on each
|
||||
// docshell, and selectively copy them to child docshells and content
|
||||
// principals in a manner that implements our desired semantics.
|
||||
//
|
||||
// This method is used to propagate attributes from parent to child
|
||||
// docshells.
|
||||
void InheritFromDocShellParent(const OriginAttributes& aParent);
|
||||
|
||||
// Copy from the origin attributes of the nsILoadContext.
|
||||
bool CopyFromLoadContext(nsILoadContext* aLoadContext);
|
||||
|
||||
// Serializes/Deserializes non-default values into the suffix format, i.e.
|
||||
// |!key1=value1&key2=value2|. If there are no non-default attributes, this
|
||||
// returns an empty string.
|
||||
@ -79,6 +50,92 @@ public:
|
||||
// |uri!key1=value1&key2=value2| and returns the uri without the suffix.
|
||||
bool PopulateFromOrigin(const nsACString& aOrigin,
|
||||
nsACString& aOriginNoSuffix);
|
||||
|
||||
protected:
|
||||
OriginAttributes() {}
|
||||
explicit OriginAttributes(const OriginAttributesDictionary& aOther)
|
||||
: OriginAttributesDictionary(aOther) {}
|
||||
};
|
||||
|
||||
class PrincipalOriginAttributes;
|
||||
class DocShellOriginAttributes;
|
||||
class NeckoOriginAttributes;
|
||||
|
||||
// Various classes in Gecko contain OriginAttributes members, and those
|
||||
// OriginAttributes get propagated to other classes according to certain rules.
|
||||
// For example, the OriginAttributes on the docshell affect the OriginAttributes
|
||||
// for the principal of a document loaded inside it, whose OriginAttributes in
|
||||
// turn affect those of network loads and child docshells. To codify and
|
||||
// centralize these rules, we introduce separate subclasses for the different
|
||||
// flavors, and a variety of InheritFrom* methods to implement the transfer
|
||||
// behavior.
|
||||
|
||||
// For OriginAttributes stored on principals.
|
||||
class PrincipalOriginAttributes : public OriginAttributes
|
||||
{
|
||||
public:
|
||||
PrincipalOriginAttributes() {}
|
||||
PrincipalOriginAttributes(uint32_t aAppId, bool aInBrowser)
|
||||
{
|
||||
mAppId = aAppId;
|
||||
mInBrowser = aInBrowser;
|
||||
}
|
||||
|
||||
// Inheriting OriginAttributes from docshell to document when user navigates.
|
||||
//
|
||||
// @param aAttrs Origin Attributes of the docshell.
|
||||
// @param aURI The URI of the document.
|
||||
void InheritFromDocShellToDoc(const DocShellOriginAttributes& aAttrs,
|
||||
const nsIURI* aURI);
|
||||
|
||||
// Inherit OriginAttributes from Necko.
|
||||
void InheritFromNecko(const NeckoOriginAttributes& aAttrs);
|
||||
};
|
||||
|
||||
// For OriginAttributes stored on docshells / loadcontexts / browsing contexts.
|
||||
class DocShellOriginAttributes : public OriginAttributes
|
||||
{
|
||||
public:
|
||||
DocShellOriginAttributes() {}
|
||||
DocShellOriginAttributes(uint32_t aAppId, bool aInBrowser)
|
||||
{
|
||||
mAppId = aAppId;
|
||||
mInBrowser = aInBrowser;
|
||||
}
|
||||
|
||||
// Inheriting OriginAttributes from document to child docshell when an
|
||||
// <iframe> is created.
|
||||
//
|
||||
// @param aAttrs Origin Attributes of the document.
|
||||
void
|
||||
InheritFromDocToChildDocShell(const PrincipalOriginAttributes& aAttrs);
|
||||
};
|
||||
|
||||
// For OriginAttributes stored on Necko.
|
||||
class NeckoOriginAttributes : public OriginAttributes
|
||||
{
|
||||
public:
|
||||
NeckoOriginAttributes() {}
|
||||
NeckoOriginAttributes(uint32_t aAppId, bool aInBrowser)
|
||||
{
|
||||
mAppId = aAppId;
|
||||
mInBrowser = aInBrowser;
|
||||
}
|
||||
|
||||
// Inheriting OriginAttributes from document to necko when a network request
|
||||
// is made.
|
||||
void InheritFromDocToNecko(const PrincipalOriginAttributes& aAttrs);
|
||||
|
||||
void InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs);
|
||||
};
|
||||
|
||||
// For operating on OriginAttributes not associated with any data structure.
|
||||
class GenericOriginAttributes : public OriginAttributes
|
||||
{
|
||||
public:
|
||||
GenericOriginAttributes() {}
|
||||
explicit GenericOriginAttributes(const OriginAttributesDictionary& aOther)
|
||||
: OriginAttributes(aOther) {}
|
||||
};
|
||||
|
||||
class OriginAttributesPattern : public dom::OriginAttributesPatternDictionary
|
||||
@ -168,10 +225,10 @@ public:
|
||||
|
||||
static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast<BasePrincipal*>(aPrin); }
|
||||
static already_AddRefed<BasePrincipal>
|
||||
CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAttrs);
|
||||
CreateCodebasePrincipal(nsIURI* aURI, const PrincipalOriginAttributes& aAttrs);
|
||||
static already_AddRefed<BasePrincipal> CreateCodebasePrincipal(const nsACString& aOrigin);
|
||||
|
||||
const OriginAttributes& OriginAttributesRef() { return mOriginAttributes; }
|
||||
const PrincipalOriginAttributes& OriginAttributesRef() { return mOriginAttributes; }
|
||||
uint32_t AppId() const { return mOriginAttributes.mAppId; }
|
||||
uint32_t UserContextId() const { return mOriginAttributes.mUserContextId; }
|
||||
bool IsInBrowserElement() const { return mOriginAttributes.mInBrowser; }
|
||||
@ -203,7 +260,7 @@ protected:
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> mCSP;
|
||||
nsCOMPtr<nsIContentSecurityPolicy> mPreloadCSP;
|
||||
OriginAttributes mOriginAttributes;
|
||||
PrincipalOriginAttributes mOriginAttributes;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -160,7 +160,7 @@ nsJSPrincipals::ReadKnownPrincipalType(JSContext* aCx,
|
||||
return false;
|
||||
}
|
||||
|
||||
OriginAttributes attrs;
|
||||
PrincipalOriginAttributes attrs;
|
||||
attrs.PopulateFromSuffix(suffix);
|
||||
info = ContentPrincipalInfo(attrs, spec);
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ nsNullPrincipal::CreateWithInheritedAttributes(nsIPrincipal* aInheritFrom)
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsNullPrincipal>
|
||||
nsNullPrincipal::Create(const OriginAttributes& aOriginAttributes)
|
||||
nsNullPrincipal::Create(const PrincipalOriginAttributes& aOriginAttributes)
|
||||
{
|
||||
RefPtr<nsNullPrincipal> nullPrin = new nsNullPrincipal();
|
||||
nsresult rv = nullPrin->Init(aOriginAttributes);
|
||||
@ -54,7 +54,7 @@ nsNullPrincipal::Create(const OriginAttributes& aOriginAttributes)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNullPrincipal::Init(const OriginAttributes& aOriginAttributes)
|
||||
nsNullPrincipal::Init(const PrincipalOriginAttributes& aOriginAttributes)
|
||||
{
|
||||
mOriginAttributes = aOriginAttributes;
|
||||
|
||||
|
@ -52,9 +52,9 @@ public:
|
||||
|
||||
// Returns null on failure.
|
||||
static already_AddRefed<nsNullPrincipal>
|
||||
Create(const mozilla::OriginAttributes& aOriginAttributes = mozilla::OriginAttributes());
|
||||
Create(const mozilla::PrincipalOriginAttributes& aOriginAttributes = mozilla::PrincipalOriginAttributes());
|
||||
|
||||
nsresult Init(const mozilla::OriginAttributes& aOriginAttributes = mozilla::OriginAttributes());
|
||||
nsresult Init(const mozilla::PrincipalOriginAttributes& aOriginAttributes = mozilla::PrincipalOriginAttributes());
|
||||
|
||||
virtual void GetScriptLocation(nsACString &aStr) override;
|
||||
|
||||
|
@ -85,7 +85,7 @@ nsPrincipal::~nsPrincipal()
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPrincipal::Init(nsIURI *aCodebase, const OriginAttributes& aOriginAttributes)
|
||||
nsPrincipal::Init(nsIURI *aCodebase, const PrincipalOriginAttributes& aOriginAttributes)
|
||||
{
|
||||
NS_ENSURE_STATE(!mInitialized);
|
||||
NS_ENSURE_ARG(aCodebase);
|
||||
@ -391,7 +391,7 @@ nsPrincipal::Read(nsIObjectInputStream* aStream)
|
||||
rv = aStream->ReadCString(suffix);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
OriginAttributes attrs;
|
||||
PrincipalOriginAttributes attrs;
|
||||
bool ok = attrs.PopulateFromSuffix(suffix);
|
||||
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
nsPrincipal();
|
||||
|
||||
// Init() must be called before the principal is in a usable state.
|
||||
nsresult Init(nsIURI* aCodebase, const mozilla::OriginAttributes& aOriginAttributes);
|
||||
nsresult Init(nsIURI* aCodebase, const mozilla::PrincipalOriginAttributes& aOriginAttributes);
|
||||
|
||||
virtual void GetScriptLocation(nsACString& aStr) override;
|
||||
void SetURI(nsIURI* aURI);
|
||||
|
@ -291,7 +291,7 @@ nsScriptSecurityManager::AppStatusForPrincipal(nsIPrincipal *aPrin)
|
||||
// The app could contain a cross-origin iframe - make sure that the content
|
||||
// is actually same-origin with the app.
|
||||
MOZ_ASSERT(inMozBrowser == false, "Checked this above");
|
||||
OriginAttributes attrs(appId, false);
|
||||
PrincipalOriginAttributes attrs(appId, false);
|
||||
nsCOMPtr<nsIPrincipal> appPrin = BasePrincipal::CreateCodebasePrincipal(appURI, attrs);
|
||||
NS_ENSURE_TRUE(appPrin, nsIPrincipal::APP_STATUS_NOT_INSTALLED);
|
||||
return aPrin->Equals(appPrin) ? status
|
||||
@ -362,7 +362,7 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScriptSecurityManager::MaybeSetAddonIdFromURI(OriginAttributes& aAttrs, nsIURI* aURI)
|
||||
nsScriptSecurityManager::MaybeSetAddonIdFromURI(PrincipalOriginAttributes& aAttrs, nsIURI* aURI)
|
||||
{
|
||||
nsAutoCString scheme;
|
||||
nsresult rv = aURI->GetScheme(scheme);
|
||||
@ -405,7 +405,8 @@ nsScriptSecurityManager::GetChannelURIPrincipal(nsIChannel* aChannel,
|
||||
return GetLoadContextCodebasePrincipal(uri, loadContext, aPrincipal);
|
||||
}
|
||||
|
||||
OriginAttributes attrs(UNKNOWN_APP_ID, false);
|
||||
//TODO: Bug 1211590. inherit Origin Attributes from LoadInfo.
|
||||
PrincipalOriginAttributes attrs(UNKNOWN_APP_ID, false);
|
||||
rv = MaybeSetAddonIdFromURI(attrs, uri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(uri, attrs);
|
||||
@ -1008,7 +1009,7 @@ NS_IMETHODIMP
|
||||
nsScriptSecurityManager::GetSimpleCodebasePrincipal(nsIURI* aURI,
|
||||
nsIPrincipal** aPrincipal)
|
||||
{
|
||||
OriginAttributes attrs(UNKNOWN_APP_ID, false);
|
||||
PrincipalOriginAttributes attrs(UNKNOWN_APP_ID, false);
|
||||
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
|
||||
prin.forget(aPrincipal);
|
||||
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
|
||||
@ -1018,7 +1019,7 @@ NS_IMETHODIMP
|
||||
nsScriptSecurityManager::GetNoAppCodebasePrincipal(nsIURI* aURI,
|
||||
nsIPrincipal** aPrincipal)
|
||||
{
|
||||
OriginAttributes attrs(NO_APP_ID, false);
|
||||
PrincipalOriginAttributes attrs(NO_APP_ID, false);
|
||||
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
|
||||
prin.forget(aPrincipal);
|
||||
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
|
||||
@ -1035,7 +1036,7 @@ NS_IMETHODIMP
|
||||
nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI* aURI, JS::Handle<JS::Value> aOriginAttributes,
|
||||
JSContext* aCx, nsIPrincipal** aPrincipal)
|
||||
{
|
||||
OriginAttributes attrs;
|
||||
PrincipalOriginAttributes attrs;
|
||||
if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
@ -1065,7 +1066,7 @@ NS_IMETHODIMP
|
||||
nsScriptSecurityManager::CreateNullPrincipal(JS::Handle<JS::Value> aOriginAttributes,
|
||||
JSContext* aCx, nsIPrincipal** aPrincipal)
|
||||
{
|
||||
OriginAttributes attrs;
|
||||
PrincipalOriginAttributes attrs;
|
||||
if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
@ -1099,7 +1100,7 @@ nsScriptSecurityManager::GetAppCodebasePrincipal(nsIURI* aURI,
|
||||
NS_ENSURE_TRUE(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
|
||||
NS_ERROR_INVALID_ARG);
|
||||
|
||||
OriginAttributes attrs(aAppId, aInMozBrowser);
|
||||
PrincipalOriginAttributes attrs(aAppId, aInMozBrowser);
|
||||
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
|
||||
prin.forget(aPrincipal);
|
||||
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
|
||||
@ -1111,10 +1112,13 @@ nsScriptSecurityManager::
|
||||
nsILoadContext* aLoadContext,
|
||||
nsIPrincipal** aPrincipal)
|
||||
{
|
||||
OriginAttributes attrs;
|
||||
bool result = attrs.CopyFromLoadContext(aLoadContext);
|
||||
DocShellOriginAttributes docShellAttrs;
|
||||
bool result = aLoadContext->GetOriginAttributes(docShellAttrs);;
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
|
||||
|
||||
PrincipalOriginAttributes attrs;
|
||||
attrs.InheritFromDocShellToDoc(docShellAttrs, aURI);
|
||||
|
||||
nsresult rv = MaybeSetAddonIdFromURI(attrs, aURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
|
||||
@ -1127,10 +1131,8 @@ nsScriptSecurityManager::GetDocShellCodebasePrincipal(nsIURI* aURI,
|
||||
nsIDocShell* aDocShell,
|
||||
nsIPrincipal** aPrincipal)
|
||||
{
|
||||
OriginAttributes attrs;
|
||||
nsDocShell* docShell= nsDocShell::Cast(aDocShell);
|
||||
bool result = attrs.CopyFromLoadContext(docShell);
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
|
||||
PrincipalOriginAttributes attrs;
|
||||
attrs.InheritFromDocShellToDoc(nsDocShell::Cast(aDocShell)->GetOriginAttributes(), aURI);
|
||||
|
||||
nsresult rv = MaybeSetAddonIdFromURI(attrs, aURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -28,7 +28,7 @@ class nsIStringBundle;
|
||||
class nsSystemPrincipal;
|
||||
|
||||
namespace mozilla {
|
||||
class OriginAttributes;
|
||||
class PrincipalOriginAttributes;
|
||||
} // namespace mozilla
|
||||
|
||||
/////////////////////////////
|
||||
@ -121,7 +121,7 @@ private:
|
||||
AddSitesToFileURIWhitelist(const nsCString& aSiteList);
|
||||
|
||||
// If aURI is a moz-extension:// URI, set mAddonId to the associated addon.
|
||||
nsresult MaybeSetAddonIdFromURI(mozilla::OriginAttributes& aAttrs, nsIURI* aURI);
|
||||
nsresult MaybeSetAddonIdFromURI(mozilla::PrincipalOriginAttributes& aAttrs, nsIURI* aURI);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mSystemPrincipal;
|
||||
bool mPrefInitialized;
|
||||
|
@ -4,34 +4,34 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
|
||||
using mozilla::OriginAttributes;
|
||||
using mozilla::PrincipalOriginAttributes;
|
||||
|
||||
static void
|
||||
TestSuffix(const OriginAttributes& attrs)
|
||||
TestSuffix(const PrincipalOriginAttributes& attrs)
|
||||
{
|
||||
nsAutoCString suffix;
|
||||
attrs.CreateSuffix(suffix);
|
||||
|
||||
OriginAttributes attrsFromSuffix;
|
||||
PrincipalOriginAttributes attrsFromSuffix;
|
||||
attrsFromSuffix.PopulateFromSuffix(suffix);
|
||||
|
||||
EXPECT_EQ(attrs, attrsFromSuffix);
|
||||
}
|
||||
|
||||
TEST(OriginAttributes, Suffix_default)
|
||||
TEST(PrincipalOriginAttributes, Suffix_default)
|
||||
{
|
||||
OriginAttributes attrs;
|
||||
PrincipalOriginAttributes attrs;
|
||||
TestSuffix(attrs);
|
||||
}
|
||||
|
||||
TEST(OriginAttributes, Suffix_appId_inBrowser)
|
||||
TEST(PrincipalOriginAttributes, Suffix_appId_inBrowser)
|
||||
{
|
||||
OriginAttributes attrs(1, true);
|
||||
PrincipalOriginAttributes attrs(1, true);
|
||||
TestSuffix(attrs);
|
||||
}
|
||||
|
||||
TEST(OriginAttributes, Suffix_maxAppId_inBrowser)
|
||||
TEST(PrincipalOriginAttributes, Suffix_maxAppId_inBrowser)
|
||||
{
|
||||
OriginAttributes attrs(4294967295, true);
|
||||
PrincipalOriginAttributes attrs(4294967295, true);
|
||||
TestSuffix(attrs);
|
||||
}
|
||||
|
@ -12,7 +12,8 @@ h2, h3, h4 {
|
||||
}
|
||||
|
||||
button {
|
||||
width: 100px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
#body {
|
||||
@ -80,3 +81,12 @@ label {
|
||||
.target-details {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.addon-controls {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.addon-options {
|
||||
flex: 1;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
const { loader } = Components.utils.import(
|
||||
"resource://devtools/shared/Loader.jsm", {});
|
||||
|
||||
@ -23,7 +24,15 @@ loader.lazyRequireGetter(this, "WorkersComponent",
|
||||
"devtools/client/aboutdebugging/components/workers", true);
|
||||
loader.lazyRequireGetter(this, "Services");
|
||||
|
||||
loader.lazyImporter(this, "AddonManager",
|
||||
"resource://gre/modules/AddonManager.jsm");
|
||||
|
||||
const Strings = Services.strings.createBundle(
|
||||
"chrome://devtools/locale/aboutdebugging.properties");
|
||||
|
||||
var AboutDebugging = {
|
||||
_prefListeners: [],
|
||||
|
||||
_categories: null,
|
||||
get categories() {
|
||||
// If needed, initialize the list of available categories.
|
||||
@ -72,14 +81,19 @@ var AboutDebugging = {
|
||||
let updatePref = () => {
|
||||
Services.prefs.setBoolPref(pref, element.checked);
|
||||
};
|
||||
element.addEventListener("change", updatePref, false);
|
||||
let updateCheckbox = () => {
|
||||
element.checked = Services.prefs.getBoolPref(pref);
|
||||
};
|
||||
element.addEventListener("change", updatePref, false);
|
||||
Services.prefs.addObserver(pref, updateCheckbox, false);
|
||||
this._prefListeners.push([pref, updateCheckbox]);
|
||||
updateCheckbox();
|
||||
});
|
||||
|
||||
// Link buttons to their associated actions.
|
||||
let loadAddonButton = document.getElementById("load-addon-from-file");
|
||||
loadAddonButton.addEventListener("click", this.loadAddonFromFile);
|
||||
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
@ -95,10 +109,41 @@ var AboutDebugging = {
|
||||
});
|
||||
},
|
||||
|
||||
loadAddonFromFile() {
|
||||
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
|
||||
fp.init(window,
|
||||
Strings.GetStringFromName("selectAddonFromFile"),
|
||||
Ci.nsIFilePicker.modeOpen);
|
||||
let res = fp.show();
|
||||
if (res == Ci.nsIFilePicker.returnCancel || !fp.file) {
|
||||
return;
|
||||
}
|
||||
let file = fp.file;
|
||||
// AddonManager.installTemporaryAddon accepts either
|
||||
// addon directory or final xpi file.
|
||||
if (!file.isDirectory() && !file.leafName.endsWith(".xpi")) {
|
||||
file = file.parent;
|
||||
}
|
||||
try {
|
||||
AddonManager.installTemporaryAddon(file);
|
||||
} catch(e) {
|
||||
alert("Error while installing the addon:\n" + e.message + "\n");
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
|
||||
destroy() {
|
||||
let telemetry = this._telemetry;
|
||||
telemetry.toolClosed("aboutdebugging");
|
||||
telemetry.destroy();
|
||||
|
||||
this._prefListeners.forEach(([pref, listener]) => {
|
||||
Services.prefs.removeObserver(pref, listener);
|
||||
});
|
||||
this._prefListeners = [];
|
||||
|
||||
React.unmountComponentAtNode(document.querySelector("#addons"));
|
||||
React.unmountComponentAtNode(document.querySelector("#workers"));
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -34,8 +34,13 @@
|
||||
<div class="header">
|
||||
<h1 class="header-name">&aboutDebugging.addons;</h1>
|
||||
</div>
|
||||
<input id="enable-addon-debugging" type="checkbox" data-pref="devtools.chrome.enabled"/>
|
||||
<label for="enable-addon-debugging" title="&aboutDebugging.addonDebugging.tooltip;">&aboutDebugging.addonDebugging.label;</label>
|
||||
<div class="addon-controls">
|
||||
<div class="addon-options">
|
||||
<input id="enable-addon-debugging" type="checkbox" data-pref="devtools.chrome.enabled"/>
|
||||
<label for="enable-addon-debugging" title="&aboutDebugging.addonDebugging.tooltip;">&aboutDebugging.addonDebugging.label;</label>
|
||||
</div>
|
||||
<button id="load-addon-from-file">&aboutDebugging.loadTemporaryAddon;</button>
|
||||
</div>
|
||||
<div id="addons"></div>
|
||||
</div>
|
||||
<div id="tab-workers" class="tab">
|
||||
|
13
devtools/client/aboutdebugging/moz.build
Normal file
13
devtools/client/aboutdebugging/moz.build
Normal file
@ -0,0 +1,13 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
DIRS += [
|
||||
'components',
|
||||
]
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
'test/browser.ini'
|
||||
]
|
7
devtools/client/aboutdebugging/test/addons/unpacked/bootstrap.js
vendored
Normal file
7
devtools/client/aboutdebugging/test/addons/unpacked/bootstrap.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
function startup() {
|
||||
Services.obs.notifyObservers(null, "test-devtools", null);
|
||||
}
|
||||
function shutdown() {}
|
||||
function install() {}
|
||||
function uninstall() {}
|
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
<Description about="urn:mozilla:install-manifest"
|
||||
em:id="test-devtools@mozilla.org"
|
||||
em:name="test-devtools"
|
||||
em:version="1.0"
|
||||
em:type="2"
|
||||
em:creator="Mozilla">
|
||||
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||
<em:minVersion>44.0a1</em:minVersion>
|
||||
<em:maxVersion>*</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
</Description>
|
||||
</RDF>
|
9
devtools/client/aboutdebugging/test/browser.ini
Normal file
9
devtools/client/aboutdebugging/test/browser.ini
Normal file
@ -0,0 +1,9 @@
|
||||
[DEFAULT]
|
||||
tags = devtools
|
||||
subsuite = devtools
|
||||
support-files =
|
||||
head.js
|
||||
addons/unpacked/bootstrap.js
|
||||
addons/unpacked/install.rdf
|
||||
|
||||
[browser_addons_install.js]
|
@ -0,0 +1,61 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
var {AddonManager} = Cu.import("resource://gre/modules/AddonManager.jsm", {});
|
||||
|
||||
const ADDON_ID = "test-devtools@mozilla.org";
|
||||
const ADDON_NAME = "test-devtools";
|
||||
|
||||
add_task(function *() {
|
||||
let { tab, document } = yield openAboutDebugging("addons");
|
||||
|
||||
// Mock the file picker to select a test addon
|
||||
let MockFilePicker = SpecialPowers.MockFilePicker;
|
||||
MockFilePicker.init(null);
|
||||
let file = get_supports_file("addons/unpacked/install.rdf");
|
||||
MockFilePicker.returnFiles = [file.file];
|
||||
|
||||
// Wait for a message sent by the addon's bootstrap.js file
|
||||
let promise = new Promise(done => {
|
||||
Services.obs.addObserver(function listener() {
|
||||
Services.obs.removeObserver(listener, "test-devtools", false);
|
||||
ok(true, "Addon installed and running its bootstrap.js file");
|
||||
done();
|
||||
}, "test-devtools", false);
|
||||
});
|
||||
// Trigger the file picker by clicking on the button
|
||||
document.getElementById("load-addon-from-file").click();
|
||||
|
||||
// Wait for the addon execution
|
||||
yield promise;
|
||||
|
||||
// Check that the addon appears in the UI
|
||||
let names = [...document.querySelectorAll("#addons .target-name")];
|
||||
names = names.map(element => element.textContent);
|
||||
ok(names.includes(ADDON_NAME), "The addon name appears in the list of addons: " + names);
|
||||
|
||||
// Now uninstall this addon
|
||||
yield new Promise(done => {
|
||||
AddonManager.getAddonByID(ADDON_ID, addon => {
|
||||
let listener = {
|
||||
onUninstalled: function(aUninstalledAddon) {
|
||||
if (aUninstalledAddon != addon) {
|
||||
return;
|
||||
}
|
||||
AddonManager.removeAddonListener(listener);
|
||||
done();
|
||||
}
|
||||
};
|
||||
AddonManager.addAddonListener(listener);
|
||||
addon.uninstall();
|
||||
});
|
||||
});
|
||||
|
||||
// Ensure that the UI removes the addon from the list
|
||||
names = [...document.querySelectorAll("#addons .target-name")];
|
||||
names = names.map(element => element.textContent);
|
||||
ok(!names.includes(ADDON_NAME), "After uninstall, the addon name disappears from the list of addons: " + names);
|
||||
|
||||
yield closeAboutDebugging(tab);
|
||||
});
|
78
devtools/client/aboutdebugging/test/head.js
Normal file
78
devtools/client/aboutdebugging/test/head.js
Normal file
@ -0,0 +1,78 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
var {utils: Cu, classes: Cc, interfaces: Ci} = Components;
|
||||
|
||||
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const Services = require("Services");
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
DevToolsUtils.testing = true;
|
||||
|
||||
const CHROME_ROOT = gTestPath.substr(0, gTestPath.lastIndexOf("/") + 1);
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
DevToolsUtils.testing = false;
|
||||
});
|
||||
|
||||
function openAboutDebugging() {
|
||||
info("opening about:debugging");
|
||||
return addTab("about:debugging").then(tab => {
|
||||
let browser = tab.linkedBrowser;
|
||||
return {
|
||||
tab,
|
||||
document: browser.contentDocument,
|
||||
window: browser.contentWindow
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function closeAboutDebugging(tab) {
|
||||
info("Closing about:debugging");
|
||||
return removeTab(tab);
|
||||
}
|
||||
|
||||
function addTab(aUrl, aWindow) {
|
||||
info("Adding tab: " + aUrl);
|
||||
|
||||
return new Promise(done => {
|
||||
let targetWindow = aWindow || window;
|
||||
let targetBrowser = targetWindow.gBrowser;
|
||||
|
||||
targetWindow.focus();
|
||||
let tab = targetBrowser.selectedTab = targetBrowser.addTab(aUrl);
|
||||
let linkedBrowser = tab.linkedBrowser;
|
||||
|
||||
linkedBrowser.addEventListener("load", function onLoad() {
|
||||
linkedBrowser.removeEventListener("load", onLoad, true);
|
||||
info("Tab added and finished loading: " + aUrl);
|
||||
done(tab);
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
|
||||
function removeTab(aTab, aWindow) {
|
||||
info("Removing tab.");
|
||||
|
||||
return new Promise(done => {
|
||||
let targetWindow = aWindow || window;
|
||||
let targetBrowser = targetWindow.gBrowser;
|
||||
let tabContainer = targetBrowser.tabContainer;
|
||||
|
||||
tabContainer.addEventListener("TabClose", function onClose(aEvent) {
|
||||
tabContainer.removeEventListener("TabClose", onClose, false);
|
||||
info("Tab removed and finished closing.");
|
||||
done();
|
||||
}, false);
|
||||
|
||||
targetBrowser.removeTab(aTab);
|
||||
});
|
||||
}
|
||||
|
||||
function get_supports_file(path) {
|
||||
let cr = Cc["@mozilla.org/chrome/chrome-registry;1"].
|
||||
getService(Ci.nsIChromeRegistry);
|
||||
let fileurl = cr.convertChromeURL(Services.io.newURI(CHROME_ROOT + path, null, null));
|
||||
return fileurl.QueryInterface(Ci.nsIFileURL);
|
||||
}
|
@ -565,6 +565,7 @@ function AnimationsTimeline(inspector) {
|
||||
this.onScrubberMouseUp = this.onScrubberMouseUp.bind(this);
|
||||
this.onScrubberMouseOut = this.onScrubberMouseOut.bind(this);
|
||||
this.onScrubberMouseMove = this.onScrubberMouseMove.bind(this);
|
||||
this.onAnimationSelected = this.onAnimationSelected.bind(this);
|
||||
EventEmitter.decorate(this);
|
||||
}
|
||||
|
||||
@ -633,14 +634,17 @@ AnimationsTimeline.prototype = {
|
||||
this.win = null;
|
||||
this.inspector = null;
|
||||
},
|
||||
|
||||
destroyTargetNodes: function() {
|
||||
for (let targetNode of this.targetNodes) {
|
||||
targetNode.destroy();
|
||||
}
|
||||
this.targetNodes = [];
|
||||
},
|
||||
|
||||
destroyTimeBlocks: function() {
|
||||
for (let timeBlock of this.timeBlocks) {
|
||||
timeBlock.off("selected", this.onAnimationSelected);
|
||||
timeBlock.destroy();
|
||||
}
|
||||
this.timeBlocks = [];
|
||||
@ -656,6 +660,24 @@ AnimationsTimeline.prototype = {
|
||||
this.animationsEl.innerHTML = "";
|
||||
},
|
||||
|
||||
onAnimationSelected: function(e, animation) {
|
||||
// Unselect the previously selected animation if any.
|
||||
[...this.rootWrapperEl.querySelectorAll(".animation.selected")].forEach(el => {
|
||||
el.classList.remove("selected");
|
||||
});
|
||||
|
||||
// Select the new animation.
|
||||
let index = this.animations.indexOf(animation);
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
this.rootWrapperEl.querySelectorAll(".animation")[index]
|
||||
.classList.toggle("selected");
|
||||
|
||||
// Relay the event to the parent component.
|
||||
this.emit("selected", animation);
|
||||
},
|
||||
|
||||
onScrubberMouseDown: function(e) {
|
||||
this.moveScrubberTo(e.pageX);
|
||||
this.win.addEventListener("mouseup", this.onScrubberMouseUp);
|
||||
@ -764,6 +786,8 @@ AnimationsTimeline.prototype = {
|
||||
timeBlock.init(timeBlockEl);
|
||||
timeBlock.render(animation);
|
||||
this.timeBlocks.push(timeBlock);
|
||||
|
||||
timeBlock.on("selected", this.onAnimationSelected);
|
||||
}
|
||||
// Use the document's current time to position the scrubber (if the server
|
||||
// doesn't provide it, hide the scrubber entirely).
|
||||
@ -872,15 +896,21 @@ AnimationsTimeline.prototype = {
|
||||
* UI component responsible for displaying a single animation timeline, which
|
||||
* basically looks like a rectangle that shows the delay and iterations.
|
||||
*/
|
||||
function AnimationTimeBlock() {}
|
||||
function AnimationTimeBlock() {
|
||||
EventEmitter.decorate(this);
|
||||
this.onClick = this.onClick.bind(this);
|
||||
}
|
||||
|
||||
exports.AnimationTimeBlock = AnimationTimeBlock;
|
||||
|
||||
AnimationTimeBlock.prototype = {
|
||||
init: function(containerEl) {
|
||||
this.containerEl = containerEl;
|
||||
this.containerEl.addEventListener("click", this.onClick);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.containerEl.removeEventListener("click", this.onClick);
|
||||
while (this.containerEl.firstChild) {
|
||||
this.containerEl.firstChild.remove();
|
||||
}
|
||||
@ -999,6 +1029,10 @@ AnimationTimeBlock.prototype = {
|
||||
}
|
||||
|
||||
return text;
|
||||
},
|
||||
|
||||
onClick: function() {
|
||||
this.emit("selected", this.animation);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -9,6 +9,7 @@ support-files =
|
||||
doc_simple_animation.html
|
||||
head.js
|
||||
|
||||
[browser_animation_click_selects_animation.js]
|
||||
[browser_animation_controller_exposes_document_currentTime.js]
|
||||
[browser_animation_empty_on_invalid_nodes.js]
|
||||
[browser_animation_mutations_with_same_names.js]
|
||||
|
@ -0,0 +1,47 @@
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Check that animations displayed in the timeline can be selected by clicking
|
||||
// them, and that this emits the right events and adds the right classes.
|
||||
|
||||
add_task(function*() {
|
||||
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
|
||||
let {panel} = yield openAnimationInspector();
|
||||
let timeline = panel.animationsTimelineComponent;
|
||||
|
||||
let selected = timeline.rootWrapperEl.querySelectorAll(".animation.selected");
|
||||
ok(!selected.length, "There are no animations selected by default");
|
||||
|
||||
info("Click on the first animation, expect the right event and right class");
|
||||
let animation0 = yield clickToSelect(timeline, 0);
|
||||
is(animation0, timeline.animations[0],
|
||||
"The selected event was emitted with the right animation");
|
||||
ok(isTimeBlockSelected(timeline, 0),
|
||||
"The time block has the right selected class");
|
||||
|
||||
info("Click on the second animation, expect the first one to be unselected");
|
||||
let animation1 = yield clickToSelect(timeline, 1);
|
||||
is(animation1, timeline.animations[1],
|
||||
"The selected event was emitted with the right animation");
|
||||
ok(isTimeBlockSelected(timeline, 1),
|
||||
"The second time block has the right selected class");
|
||||
ok(!isTimeBlockSelected(timeline, 0),
|
||||
"The first time block has been unselected");
|
||||
});
|
||||
|
||||
function* clickToSelect(timeline, index) {
|
||||
info("Click on animation " + index + " in the timeline");
|
||||
let onSelected = timeline.once("selected");
|
||||
let timeBlock = timeline.rootWrapperEl.querySelectorAll(".time-block")[index];
|
||||
EventUtils.sendMouseEvent({type: "click"}, timeBlock,
|
||||
timeBlock.ownerDocument.defaultView);
|
||||
return yield onSelected;
|
||||
}
|
||||
|
||||
function isTimeBlockSelected(timeline, index) {
|
||||
let animation = timeline.rootWrapperEl.querySelectorAll(".animation")[index];
|
||||
return animation.classList.contains("selected");
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
<!-- 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/. -->
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/common.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/widgets.css" type="text/css"?>
|
||||
|
@ -75,6 +75,7 @@ support-files =
|
||||
[browser_cmd_pref1.js]
|
||||
[browser_cmd_pref2.js]
|
||||
[browser_cmd_pref3.js]
|
||||
[browser_cmd_qsa.js]
|
||||
[browser_cmd_restart.js]
|
||||
[browser_cmd_rulers.js]
|
||||
[browser_cmd_screenshot.js]
|
||||
|
33
devtools/client/commandline/test/browser_cmd_qsa.js
Normal file
33
devtools/client/commandline/test/browser_cmd_qsa.js
Normal file
@ -0,0 +1,33 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests that the qsa commands work as they should.
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8,<body></body>";
|
||||
|
||||
function test() {
|
||||
helpers.addTabWithToolbar(TEST_URI, function(options) {
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
setup: 'qsa',
|
||||
check: {
|
||||
input: 'qsa',
|
||||
hints: ' [query]',
|
||||
markup: 'VVV',
|
||||
status: 'VALID'
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'qsa body',
|
||||
check: {
|
||||
input: 'qsa body',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVV',
|
||||
status: 'VALID'
|
||||
}
|
||||
}
|
||||
]);
|
||||
}).then(finish, helpers.handleError);
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
<!-- 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/. -->
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css"?>
|
||||
<?xml-stylesheet href="debugger.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/common.css" type="text/css"?>
|
||||
|
@ -6,6 +6,7 @@
|
||||
<!ENTITY % toolboxDTD SYSTEM "chrome://devtools/locale/toolbox.dtd" >
|
||||
%toolboxDTD;
|
||||
]>
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet rel="stylesheet" href="chrome://devtools/content/framework/dev-edition-promo/dev-edition-promo.css" type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="dev-edition-promo">
|
||||
|
@ -2,6 +2,7 @@
|
||||
<!-- 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/. -->
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/common.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/widgets.css" type="text/css"?>
|
||||
|
@ -7,6 +7,8 @@
|
||||
%toolboxDTD;
|
||||
]>
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
id="devtools-toolbox-window"
|
||||
macanimationtype="document"
|
||||
|
@ -7,6 +7,8 @@
|
||||
%toolboxDTD;
|
||||
]>
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
id="devtools-toolbox-window"
|
||||
macanimationtype="document"
|
||||
|
@ -2,6 +2,7 @@
|
||||
<!-- 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/. -->
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/content/inspector/inspector.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/common.css" type="text/css"?>
|
||||
|
@ -6,4 +6,5 @@
|
||||
<!ENTITY aboutDebugging.addons "Add-ons">
|
||||
<!ENTITY aboutDebugging.addonDebugging.label "Enable add-on debugging">
|
||||
<!ENTITY aboutDebugging.addonDebugging.tooltip "Turning this on will allow you to debug add-ons and various other parts of the browser chrome">
|
||||
<!ENTITY aboutDebugging.loadTemporaryAddon "Load Temporary Add-on">
|
||||
<!ENTITY aboutDebugging.workers "Workers">
|
||||
|
@ -5,6 +5,7 @@
|
||||
debug = Debug
|
||||
|
||||
extensions = Extensions
|
||||
selectAddonFromFile = Select Add-on Directory or XPI File
|
||||
serviceWorkers = Service Workers
|
||||
sharedWorkers = Shared Workers
|
||||
otherWorkers = Other Workers
|
||||
|
@ -18,7 +18,7 @@ add_task(function*() {
|
||||
markup.isDragging = true;
|
||||
|
||||
info("Simulate a mousemove on the view, at the bottom, and expect scrolling");
|
||||
let onScrolled = waitForViewScroll(markup);
|
||||
let onScrolled = waitForScrollStop(markup);
|
||||
|
||||
markup._onMouseMove({
|
||||
preventDefault: () => {},
|
||||
@ -30,7 +30,7 @@ add_task(function*() {
|
||||
ok(bottomScrollPos > 0, "The view was scrolled down");
|
||||
|
||||
info("Simulate a mousemove at the top and expect more scrolling");
|
||||
onScrolled = waitForViewScroll(markup);
|
||||
onScrolled = waitForScrollStop(markup);
|
||||
|
||||
markup._onMouseMove({
|
||||
preventDefault: () => {},
|
||||
@ -46,22 +46,28 @@ add_task(function*() {
|
||||
markup._onMouseUp();
|
||||
});
|
||||
|
||||
function waitForViewScroll(markup) {
|
||||
/**
|
||||
* Waits until the element has not scrolled for 30 consecutive frames.
|
||||
*/
|
||||
function* waitForScrollStop(markup) {
|
||||
let el = markup.doc.documentElement;
|
||||
let startPos = el.scrollTop;
|
||||
let win = markup.doc.defaultView;
|
||||
let lastScrollTop = el.scrollTop;
|
||||
let stopFrameCount = 0;
|
||||
while (stopFrameCount < 30) {
|
||||
// Wait for a frame.
|
||||
yield new Promise(resolve => win.requestAnimationFrame(resolve));
|
||||
|
||||
return new Promise(resolve => {
|
||||
let isDone = () => {
|
||||
if (el.scrollTop === startPos) {
|
||||
resolve(el.scrollTop);
|
||||
} else {
|
||||
startPos = el.scrollTop;
|
||||
// Continue checking every 50ms.
|
||||
setTimeout(isDone, 50);
|
||||
}
|
||||
};
|
||||
// Check if the element has scrolled.
|
||||
if (lastScrollTop == el.scrollTop) {
|
||||
// No scrolling since the last frame.
|
||||
stopFrameCount++;
|
||||
} else {
|
||||
// The element has scrolled. Reset the frame counter.
|
||||
stopFrameCount = 0;
|
||||
lastScrollTop = el.scrollTop;
|
||||
}
|
||||
}
|
||||
|
||||
// Start checking if the view scrolled after a while.
|
||||
setTimeout(isDone, 50);
|
||||
});
|
||||
return lastScrollTop;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
include('../templates.mozbuild')
|
||||
|
||||
DIRS += [
|
||||
'aboutdebugging/components',
|
||||
'aboutdebugging',
|
||||
'animationinspector',
|
||||
'canvasdebugger',
|
||||
'commandline',
|
||||
|
@ -2,6 +2,7 @@
|
||||
<!-- 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/. -->
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/content/netmonitor/netmonitor.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/common.css" type="text/css"?>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<!-- 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/. -->
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/common.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/widgets.css" type="text/css"?>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<!-- 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/. -->
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/common.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/widgets.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/shadereditor.css" type="text/css"?>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<!-- 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/. -->
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/common.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/widgets.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css"?>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<!-- 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/. -->
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/common.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/widgets.css" type="text/css"?>
|
||||
|
@ -238,6 +238,10 @@ body {
|
||||
background-color: var(--even-animation-timeline-background-color);
|
||||
}
|
||||
|
||||
.animation-timeline .animation.selected {
|
||||
background-color: var(--theme-selection-background-semitransparent);
|
||||
}
|
||||
|
||||
.animation-timeline .animation .target {
|
||||
width: var(--timeline-sidebar-width);
|
||||
overflow: hidden;
|
||||
@ -254,6 +258,7 @@ body {
|
||||
left: var(--timeline-sidebar-width);
|
||||
right: 0;
|
||||
height: var(--timeline-animation-height);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Animation iterations */
|
||||
|
@ -2,6 +2,7 @@
|
||||
<!-- 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/. -->
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/common.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/widgets.css" type="text/css"?>
|
||||
|
@ -158,8 +158,12 @@ WebConsoleActor.prototype =
|
||||
},
|
||||
|
||||
/**
|
||||
* The window we work with.
|
||||
* @type nsIDOMWindow
|
||||
* The window or sandbox we work with.
|
||||
* Note that even if it is named `window` it refers to the current
|
||||
* global we are debugging, which can be a Sandbox for addons
|
||||
* or browser content toolbox.
|
||||
*
|
||||
* @type nsIDOMWindow or Sandbox
|
||||
*/
|
||||
get window() {
|
||||
if (this.parentActor.isRootActor) {
|
||||
@ -736,7 +740,8 @@ WebConsoleActor.prototype =
|
||||
break;
|
||||
}
|
||||
|
||||
let requestStartTime = this.window ?
|
||||
// See `window` definition. It isn't always a DOM Window.
|
||||
let requestStartTime = this.window && this.window.performance ?
|
||||
this.window.performance.timing.requestStart : 0;
|
||||
|
||||
let cache = this.consoleAPIListener
|
||||
|
@ -69,6 +69,7 @@ exports.devtoolsModules = [
|
||||
"devtools/shared/gcli/commands/media",
|
||||
"devtools/shared/gcli/commands/pagemod",
|
||||
"devtools/shared/gcli/commands/paintflashing",
|
||||
"devtools/shared/gcli/commands/qsa",
|
||||
"devtools/shared/gcli/commands/restart",
|
||||
"devtools/shared/gcli/commands/rulers",
|
||||
"devtools/shared/gcli/commands/screenshot",
|
||||
|
@ -21,6 +21,7 @@ DevToolsModules(
|
||||
'media.js',
|
||||
'pagemod.js',
|
||||
'paintflashing.js',
|
||||
'qsa.js',
|
||||
'restart.js',
|
||||
'rulers.js',
|
||||
'screenshot.js',
|
||||
|
24
devtools/shared/gcli/commands/qsa.js
Normal file
24
devtools/shared/gcli/commands/qsa.js
Normal file
@ -0,0 +1,24 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const l10n = require("gcli/l10n");
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
item: "command",
|
||||
runAt: "server",
|
||||
name: "qsa",
|
||||
description: l10n.lookup("qsaDesc"),
|
||||
params: [{
|
||||
name: "query",
|
||||
type: "nodelist",
|
||||
description: l10n.lookup("qsaQueryDesc")
|
||||
}],
|
||||
exec: function(args, context) {
|
||||
return args.query.length;
|
||||
}
|
||||
}
|
||||
];
|
@ -57,20 +57,7 @@ using JS::ubi::AtomOrTwoByteChars;
|
||||
|
||||
/*** Cycle Collection Boilerplate *****************************************************************/
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(HeapSnapshot)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(HeapSnapshot)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(HeapSnapshot)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(HeapSnapshot)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(HeapSnapshot, mParent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(HeapSnapshot)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(HeapSnapshot)
|
||||
|
@ -1557,6 +1557,11 @@ mediaEmulateManual=View the document as if rendered on a device supporting the g
|
||||
mediaEmulateType=The media type to emulate
|
||||
mediaResetDesc=Stop emulating a CSS media type
|
||||
|
||||
# LOCALIZATION NOTE (qsaDesc, qsaQueryDesc)
|
||||
# These strings describe the 'qsa' commands and all available parameters.
|
||||
qsaDesc=Perform querySelectorAll on the current document and return number of matches
|
||||
qsaQueryDesc=CSS selectors separated by comma
|
||||
|
||||
# LOCALIZATION NOTE (injectDesc, injectManual, injectLibraryDesc, injectLoaded,
|
||||
# injectFailed) These strings describe the 'inject' commands and all available
|
||||
# parameters.
|
||||
|
@ -23,7 +23,8 @@ LoadContext::LoadContext(nsIPrincipal* aPrincipal,
|
||||
, mIsNotNull(true)
|
||||
#endif
|
||||
{
|
||||
mOriginAttributes = BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
|
||||
PrincipalOriginAttributes poa = BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
|
||||
mOriginAttributes = DocShellOriginAttributes(poa.mAppId, poa.mInBrowser);
|
||||
|
||||
if (!aOptionalBase) {
|
||||
return;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user