зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound, a=merge
This commit is contained in:
Коммит
6eeeb31ce1
|
@ -51,9 +51,15 @@ function debug(msg) {
|
|||
|
||||
/**
|
||||
* An empirically determined amount of acceleration corresponding to a
|
||||
* shake
|
||||
* shake.
|
||||
*/
|
||||
const EXCITEMENT_THRESHOLD = 500;
|
||||
/**
|
||||
* The maximum fraction to update the excitement value per frame. This
|
||||
* corresponds to requiring shaking for approximately 10 motion events (1.6
|
||||
* seconds)
|
||||
*/
|
||||
const EXCITEMENT_FILTER_ALPHA = 0.2;
|
||||
const DEVICE_MOTION_EVENT = "devicemotion";
|
||||
const SCREEN_CHANGE_EVENT = "screenchange";
|
||||
const CAPTURE_LOGS_CONTENT_EVENT = "requestSystemLogs";
|
||||
|
@ -88,6 +94,11 @@ let LogShake = {
|
|||
*/
|
||||
captureRequested: false,
|
||||
|
||||
/**
|
||||
* The current excitement (movement) level
|
||||
*/
|
||||
excitement: 0,
|
||||
|
||||
/**
|
||||
* Map of files which have log-type information to their parsers
|
||||
*/
|
||||
|
@ -122,6 +133,9 @@ let LogShake = {
|
|||
screenEnabled: true
|
||||
}});
|
||||
|
||||
// Reset excitement to clear residual motion
|
||||
this.excitement = 0;
|
||||
|
||||
SystemAppProxy.addEventListener(CAPTURE_LOGS_CONTENT_EVENT, this, false);
|
||||
SystemAppProxy.addEventListener(SCREEN_CHANGE_EVENT, this, false);
|
||||
|
||||
|
@ -196,9 +210,12 @@ let LogShake = {
|
|||
|
||||
var acc = event.accelerationIncludingGravity;
|
||||
|
||||
var excitement = acc.x * acc.x + acc.y * acc.y + acc.z * acc.z;
|
||||
// Updates excitement by a factor of at most alpha, ignoring sudden device
|
||||
// motion. See bug #1101994 for more information.
|
||||
var newExcitement = acc.x * acc.x + acc.y * acc.y + acc.z * acc.z;
|
||||
this.excitement += (newExcitement - this.excitement) * EXCITEMENT_FILTER_ALPHA;
|
||||
|
||||
if (excitement > EXCITEMENT_THRESHOLD) {
|
||||
if (this.excitement > EXCITEMENT_THRESHOLD) {
|
||||
this.startCapture();
|
||||
}
|
||||
},
|
||||
|
|
|
@ -15,9 +15,14 @@ const Cu = Components.utils;
|
|||
Cu.import("resource://gre/modules/LogCapture.jsm");
|
||||
Cu.import("resource://gre/modules/LogShake.jsm");
|
||||
|
||||
// Force logshake to handle a device motion event with given components
|
||||
// Does not use SystemAppProxy because event needs special
|
||||
// accelerationIncludingGravity property
|
||||
const EVENTS_PER_SECOND = 6.25;
|
||||
const GRAVITY = 9.8;
|
||||
|
||||
/**
|
||||
* Force logshake to handle a device motion event with given components.
|
||||
* Does not use SystemAppProxy because event needs special
|
||||
* accelerationIncludingGravity property.
|
||||
*/
|
||||
function sendDeviceMotionEvent(x, y, z) {
|
||||
let event = {
|
||||
type: "devicemotion",
|
||||
|
@ -30,8 +35,10 @@ function sendDeviceMotionEvent(x, y, z) {
|
|||
LogShake.handleEvent(event);
|
||||
}
|
||||
|
||||
// Send a screen change event directly, does not use SystemAppProxy due to race
|
||||
// conditions.
|
||||
/**
|
||||
* Send a screen change event directly, does not use SystemAppProxy due to race
|
||||
* conditions.
|
||||
*/
|
||||
function sendScreenChangeEvent(screenEnabled) {
|
||||
let event = {
|
||||
type: "screenchange",
|
||||
|
@ -42,23 +49,41 @@ function sendScreenChangeEvent(screenEnabled) {
|
|||
LogShake.handleEvent(event);
|
||||
}
|
||||
|
||||
function debug(msg) {
|
||||
var timestamp = Date.now();
|
||||
dump("LogShake: " + timestamp + ": " + msg);
|
||||
/**
|
||||
* Mock the readLogFile function of LogCapture.
|
||||
* Used to detect whether LogShake activates.
|
||||
* @return {Array<String>} Locations that LogShake tries to read
|
||||
*/
|
||||
function mockReadLogFile() {
|
||||
let readLocations = [];
|
||||
|
||||
LogCapture.readLogFile = function(loc) {
|
||||
readLocations.push(loc);
|
||||
return null; // we don't want to provide invalid data to a parser
|
||||
};
|
||||
|
||||
// Allow inspection of readLocations by caller
|
||||
return readLocations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a series of events that corresponds to a shake
|
||||
*/
|
||||
function sendSustainedShake() {
|
||||
// Fire a series of devicemotion events that are of shake magnitude
|
||||
for (let i = 0; i < 2 * EVENTS_PER_SECOND; i++) {
|
||||
sendDeviceMotionEvent(0, 2 * GRAVITY, 2 * GRAVITY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
add_test(function test_do_log_capture_after_shaking() {
|
||||
// Enable LogShake
|
||||
LogShake.init();
|
||||
|
||||
let readLocations = [];
|
||||
LogCapture.readLogFile = function(loc) {
|
||||
readLocations.push(loc);
|
||||
return null; // we don't want to provide invalid data to a parser
|
||||
};
|
||||
let readLocations = mockReadLogFile();
|
||||
|
||||
// Fire a devicemotion event that is of shake magnitude
|
||||
sendDeviceMotionEvent(9001, 9001, 9001);
|
||||
sendSustainedShake();
|
||||
|
||||
ok(readLocations.length > 0,
|
||||
"LogShake should attempt to read at least one log");
|
||||
|
@ -71,36 +96,28 @@ add_test(function test_do_nothing_when_resting() {
|
|||
// Enable LogShake
|
||||
LogShake.init();
|
||||
|
||||
let readLocations = [];
|
||||
LogCapture.readLogFile = function(loc) {
|
||||
readLocations.push(loc);
|
||||
return null; // we don't want to provide invalid data to a parser
|
||||
};
|
||||
let readLocations = mockReadLogFile();
|
||||
|
||||
// Fire a devicemotion event that is relatively tiny
|
||||
sendDeviceMotionEvent(0, 9.8, 9.8);
|
||||
// Fire several devicemotion events that are relatively tiny
|
||||
for (let i = 0; i < 2 * EVENTS_PER_SECOND; i++) {
|
||||
sendDeviceMotionEvent(0, GRAVITY, GRAVITY);
|
||||
}
|
||||
|
||||
ok(readLocations.length === 0,
|
||||
"LogShake should not read any logs");
|
||||
|
||||
debug("test_do_nothing_when_resting: stop");
|
||||
LogShake.uninit();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_do_nothing_when_disabled() {
|
||||
debug("test_do_nothing_when_disabled: start");
|
||||
// Disable LogShake
|
||||
LogShake.uninit();
|
||||
|
||||
let readLocations = [];
|
||||
LogCapture.readLogFile = function(loc) {
|
||||
readLocations.push(loc);
|
||||
return null; // we don't want to provide invalid data to a parser
|
||||
};
|
||||
let readLocations = mockReadLogFile();
|
||||
|
||||
// Fire a devicemotion event that would normally be a shake
|
||||
sendDeviceMotionEvent(0, 9001, 9001);
|
||||
// Fire a series of events that would normally be a shake
|
||||
sendSustainedShake();
|
||||
|
||||
ok(readLocations.length === 0,
|
||||
"LogShake should not read any logs");
|
||||
|
@ -112,18 +129,13 @@ add_test(function test_do_nothing_when_screen_off() {
|
|||
// Enable LogShake
|
||||
LogShake.init();
|
||||
|
||||
|
||||
// Send an event as if the screen has been turned off
|
||||
sendScreenChangeEvent(false);
|
||||
|
||||
let readLocations = [];
|
||||
LogCapture.readLogFile = function(loc) {
|
||||
readLocations.push(loc);
|
||||
return null; // we don't want to provide invalid data to a parser
|
||||
};
|
||||
let readLocations = mockReadLogFile();
|
||||
|
||||
// Fire a devicemotion event that would normally be a shake
|
||||
sendDeviceMotionEvent(0, 9001, 9001);
|
||||
// Fire a series of events that would normally be a shake
|
||||
sendSustainedShake();
|
||||
|
||||
ok(readLocations.length === 0,
|
||||
"LogShake should not read any logs");
|
||||
|
@ -145,8 +157,8 @@ add_test(function test_do_log_capture_resilient_readLogFile() {
|
|||
throw new Error("Exception during readLogFile for: " + loc);
|
||||
};
|
||||
|
||||
// Fire a devicemotion event that is of shake magnitude
|
||||
sendDeviceMotionEvent(9001, 9001, 9001);
|
||||
// Fire a series of events that would normally be a shake
|
||||
sendSustainedShake();
|
||||
|
||||
ok(readLocations.length > 0,
|
||||
"LogShake should attempt to read at least one log");
|
||||
|
@ -168,8 +180,8 @@ add_test(function test_do_log_capture_resilient_parseLog() {
|
|||
return null;
|
||||
};
|
||||
|
||||
// Fire a devicemotion event that is of shake magnitude
|
||||
sendDeviceMotionEvent(9001, 9001, 9001);
|
||||
// Fire a series of events that would normally be a shake
|
||||
sendSustainedShake();
|
||||
|
||||
ok(readLocations.length > 0,
|
||||
"LogShake should attempt to read at least one log");
|
||||
|
@ -178,7 +190,29 @@ add_test(function test_do_log_capture_resilient_parseLog() {
|
|||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_do_nothing_when_dropped() {
|
||||
// Enable LogShake
|
||||
LogShake.init();
|
||||
|
||||
let readLocations = mockReadLogFile();
|
||||
|
||||
// We want a series of spikes to be ignored by LogShake. This roughly
|
||||
// corresponds to the compare_stairs_sock graph on bug #1101994
|
||||
|
||||
for (let i = 0; i < 10 * EVENTS_PER_SECOND; i++) {
|
||||
// Fire a devicemotion event that is at rest
|
||||
sendDeviceMotionEvent(0, 0, GRAVITY);
|
||||
// Fire a spike of motion
|
||||
sendDeviceMotionEvent(0, 2 * GRAVITY, 2 * GRAVITY);
|
||||
}
|
||||
|
||||
ok(readLocations.length === 0,
|
||||
"LogShake should not read any logs");
|
||||
|
||||
LogShake.uninit();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
debug("Starting");
|
||||
run_next_test();
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0c073eda92b099bc008488e52edb0745c5f7975e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="62ba52866f4e5ca9120dad5bfe62fc5df981dc39"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -151,7 +151,7 @@
|
|||
<project name="platform/vendor/qcom/copper" path="device/qcom/msm8974" revision="ec7bc1a26610922156d7d412b4d3de6b4adb93da"/>
|
||||
<project name="vendor_broadcom_wlan" path="vendor/broadcom/wlan" remote="b2g" revision="114b9491a8a919687da4e22fbd89fab511d6d8d7"/>
|
||||
<!-- Shinano specific things -->
|
||||
<project name="device-shinano" path="device/sony/shinano" remote="b2g" revision="a7cb315bc0704f589858feb2a34956364acacb08"/>
|
||||
<project name="device-shinano" path="device/sony/shinano" remote="b2g" revision="afb93dac826346fdeaab6f8ce5dd70eaaaec676d"/>
|
||||
<!-- Aries specific things -->
|
||||
<project name="device-aries" path="device/sony/aries" remote="b2g" revision="75c7e6ca80d0c7a53f346ecfcde2343be95808c9"/>
|
||||
<project name="device-aries" path="device/sony/aries" remote="b2g" revision="2916e2368074b5383c80bf5a0fba3fc83ba310bd"/>
|
||||
</manifest>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0c073eda92b099bc008488e52edb0745c5f7975e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="62ba52866f4e5ca9120dad5bfe62fc5df981dc39"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0c073eda92b099bc008488e52edb0745c5f7975e"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="62ba52866f4e5ca9120dad5bfe62fc5df981dc39"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0c073eda92b099bc008488e52edb0745c5f7975e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="62ba52866f4e5ca9120dad5bfe62fc5df981dc39"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="94516f787d477dc307e4566f415e0d2f0794f6b9"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0c073eda92b099bc008488e52edb0745c5f7975e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="62ba52866f4e5ca9120dad5bfe62fc5df981dc39"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0c073eda92b099bc008488e52edb0745c5f7975e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="62ba52866f4e5ca9120dad5bfe62fc5df981dc39"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0c073eda92b099bc008488e52edb0745c5f7975e"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="62ba52866f4e5ca9120dad5bfe62fc5df981dc39"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0c073eda92b099bc008488e52edb0745c5f7975e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="62ba52866f4e5ca9120dad5bfe62fc5df981dc39"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "0c073eda92b099bc008488e52edb0745c5f7975e",
|
||||
"git_revision": "62ba52866f4e5ca9120dad5bfe62fc5df981dc39",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "43b90c58070717da08d510200a0c848da68a4390",
|
||||
"revision": "e54f587baa2008376f2439fb6901fdb99a878a99",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0c073eda92b099bc008488e52edb0745c5f7975e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="62ba52866f4e5ca9120dad5bfe62fc5df981dc39"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="94516f787d477dc307e4566f415e0d2f0794f6b9"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0c073eda92b099bc008488e52edb0745c5f7975e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="62ba52866f4e5ca9120dad5bfe62fc5df981dc39"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -206,8 +206,36 @@ AppendDistroSearchDirs(nsIProperties* aDirSvc, nsCOMArray<nsIFile> &array)
|
|||
NS_IMETHODIMP
|
||||
DirectoryProvider::GetFiles(const char *aKey, nsISimpleEnumerator* *aResult)
|
||||
{
|
||||
/**
|
||||
* We want to preserve the following order, since the search service loads
|
||||
* engines in first-loaded-wins order.
|
||||
* - distro search plugin locations (Loaded by the search service using
|
||||
* NS_APP_DISTRIBUTION_SEARCH_DIR_LIST)
|
||||
*
|
||||
* - engines shipped in chrome (Loaded from jar files by the search
|
||||
* service)
|
||||
*
|
||||
* Then other locations, from NS_APP_SEARCH_DIR_LIST:
|
||||
* - extension search plugin locations (prepended below using
|
||||
* NS_NewUnionEnumerator)
|
||||
* - user search plugin locations (profile)
|
||||
* - app search plugin location (shipped engines)
|
||||
*/
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (!strcmp(aKey, NS_APP_DISTRIBUTION_SEARCH_DIR_LIST)) {
|
||||
nsCOMPtr<nsIProperties> dirSvc
|
||||
(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
|
||||
if (!dirSvc)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMArray<nsIFile> distroFiles;
|
||||
AppendDistroSearchDirs(dirSvc, distroFiles);
|
||||
|
||||
return NS_NewArrayEnumerator(aResult, distroFiles);
|
||||
}
|
||||
|
||||
if (!strcmp(aKey, NS_APP_SEARCH_DIR_LIST)) {
|
||||
nsCOMPtr<nsIProperties> dirSvc
|
||||
(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
|
||||
|
@ -216,16 +244,6 @@ DirectoryProvider::GetFiles(const char *aKey, nsISimpleEnumerator* *aResult)
|
|||
|
||||
nsCOMArray<nsIFile> baseFiles;
|
||||
|
||||
/**
|
||||
* We want to preserve the following order, since the search service loads
|
||||
* engines in first-loaded-wins order.
|
||||
* - extension search plugin locations (prepended below using
|
||||
* NS_NewUnionEnumerator)
|
||||
* - distro search plugin locations
|
||||
* - user search plugin locations (profile)
|
||||
* - app search plugin location (shipped engines)
|
||||
*/
|
||||
AppendDistroSearchDirs(dirSvc, baseFiles);
|
||||
AppendFileKey(NS_APP_USER_SEARCH_DIR, dirSvc, baseFiles);
|
||||
AppendFileKey(NS_APP_SEARCH_DIR, dirSvc, baseFiles);
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ support-files =
|
|||
[browser_cmd_pagemod_export.js]
|
||||
support-files =
|
||||
browser_cmd_pagemod_export.html
|
||||
[browser_cmd_paintflashing.js]
|
||||
[browser_cmd_pref1.js]
|
||||
[browser_cmd_pref2.js]
|
||||
[browser_cmd_pref3.js]
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that the paintflashing command correctly sets its state.
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/commandline/" +
|
||||
"test/browser_cmd_cookie.html";
|
||||
|
||||
function test() {
|
||||
return Task.spawn(testTask).then(finish, helpers.handleError);
|
||||
}
|
||||
|
||||
let tests = {
|
||||
testInput: function(options) {
|
||||
let toggleCommand = options.requisition.system.commands.get("paintflashing toggle");
|
||||
|
||||
let actions = [
|
||||
{
|
||||
command: "paintflashing on",
|
||||
isChecked: true,
|
||||
label: "checked after on"
|
||||
},
|
||||
{
|
||||
command: "paintflashing off",
|
||||
isChecked: false,
|
||||
label: "unchecked after off"
|
||||
},
|
||||
{
|
||||
command: "paintflashing toggle",
|
||||
isChecked: true,
|
||||
label: "checked after toggle"
|
||||
},
|
||||
{
|
||||
command: "paintflashing toggle",
|
||||
isChecked: false,
|
||||
label: "unchecked after toggle"
|
||||
}
|
||||
];
|
||||
|
||||
return helpers.audit(options, actions.map(spec => ({
|
||||
setup: spec.command,
|
||||
exec: {},
|
||||
post: () => is(toggleCommand.state.isChecked(), spec.isChecked, spec.label)
|
||||
})));
|
||||
},
|
||||
};
|
||||
|
||||
function* testTask() {
|
||||
let options = yield helpers.openTab(TEST_URI);
|
||||
yield helpers.openToolbar(options);
|
||||
|
||||
yield helpers.runTests(options, tests);
|
||||
|
||||
yield helpers.closeToolbar(options);
|
||||
yield helpers.closeTab(options);
|
||||
}
|
|
@ -7,23 +7,28 @@
|
|||
* Utility functions for collapsing markers into a waterfall.
|
||||
*/
|
||||
|
||||
loader.lazyRequireGetter(this, "getBlueprintFor",
|
||||
"devtools/performance/marker-utils", true);
|
||||
loader.lazyRequireGetter(this, "MarkerUtils",
|
||||
"devtools/performance/marker-utils");
|
||||
|
||||
/**
|
||||
* Collapses markers into a tree-like structure.
|
||||
* @param object markerNode
|
||||
* @param array markersList
|
||||
* @param array filter
|
||||
*/
|
||||
function collapseMarkersIntoNode({ markerNode, markersList }) {
|
||||
function collapseMarkersIntoNode({ markerNode, markersList, filter }) {
|
||||
let { getCurrentParentNode, collapseMarker, addParentNode, popParentNode } = createParentNodeFactory(markerNode);
|
||||
|
||||
for (let i = 0, len = markersList.length; i < len; i++) {
|
||||
let curr = markersList[i];
|
||||
|
||||
let parentNode = getCurrentParentNode();
|
||||
let blueprint = getBlueprintFor(curr);
|
||||
// If this marker type should not be displayed, just skip
|
||||
if (!MarkerUtils.isMarkerValid(curr, filter)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let parentNode = getCurrentParentNode();
|
||||
let blueprint = MarkerUtils.getBlueprintFor(curr);
|
||||
let collapse = blueprint.collapseFunc || (() => null);
|
||||
let peek = distance => markersList[i + distance];
|
||||
|
||||
|
|
|
@ -136,7 +136,8 @@ support-files =
|
|||
[browser_profiler_tree-view-08.js]
|
||||
[browser_profiler_tree-view-09.js]
|
||||
[browser_profiler_tree-view-10.js]
|
||||
[browser_timeline-filters.js]
|
||||
[browser_timeline-filters-01.js]
|
||||
[browser_timeline-filters-02.js]
|
||||
[browser_timeline-waterfall-background.js]
|
||||
[browser_timeline-waterfall-generic.js]
|
||||
[browser_timeline-waterfall-rerender.js]
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests markers filtering mechanism.
|
||||
*/
|
||||
|
||||
const URL = EXAMPLE_URL + "doc_innerHTML.html";
|
||||
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(URL);
|
||||
let { $, $$, EVENTS, PerformanceController, OverviewView, WaterfallView } = panel.panelWin;
|
||||
|
||||
yield startRecording(panel);
|
||||
ok(true, "Recording has started.");
|
||||
|
||||
yield waitUntil(() => {
|
||||
let markers = PerformanceController.getCurrentRecording().getMarkers();
|
||||
return markers.some(m => m.name == "Parse HTML") &&
|
||||
markers.some(m => m.name == "Javascript");
|
||||
});
|
||||
|
||||
let waterfallRendered = WaterfallView.once(EVENTS.WATERFALL_RENDERED);
|
||||
yield stopRecording(panel);
|
||||
|
||||
$("#filter-button").click();
|
||||
let filterJS = $("menuitem[marker-type=Javascript]");
|
||||
|
||||
yield waterfallRendered;
|
||||
|
||||
ok($(".waterfall-marker-bar[type=Javascript]"), "Found at least one 'Javascript' marker");
|
||||
ok(!$(".waterfall-marker-bar[type='Parse HTML']"), "Found no Parse HTML markers as they are nested still");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(filterJS, {type: "mouseup"}, panel.panelWin);
|
||||
yield Promise.all([
|
||||
WaterfallView.once(EVENTS.WATERFALL_RENDERED),
|
||||
once(filterJS, "command")
|
||||
]);
|
||||
|
||||
ok(!$(".waterfall-marker-bar[type=Javascript]"), "Javascript markers are all hidden.");
|
||||
ok($(".waterfall-marker-bar[type='Parse HTML']"),
|
||||
"Found at least one 'Parse HTML' marker still visible after hiding JS markers");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -113,6 +113,10 @@ let WaterfallView = Heritage.extend(DetailsSubview, {
|
|||
*/
|
||||
_onObservedPrefChange: function(_, prefName) {
|
||||
this._hiddenMarkers = PerformanceController.getPref("hidden-markers");
|
||||
|
||||
// Clear the cache as we'll need to recompute the collapsed
|
||||
// marker model
|
||||
this._cache = new WeakMap();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -137,6 +141,7 @@ let WaterfallView = Heritage.extend(DetailsSubview, {
|
|||
WaterfallUtils.collapseMarkersIntoNode({
|
||||
markerNode: rootMarkerNode,
|
||||
markersList: markers,
|
||||
filter: this._hiddenMarkers
|
||||
});
|
||||
|
||||
this._cache.set(markers, rootMarkerNode);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8," +
|
||||
"<p>browser_telemetry_button_paintflashing.js</p>";
|
||||
|
||||
|
@ -30,27 +32,28 @@ function* testButton(toolbox, Telemetry) {
|
|||
let button = toolbox.doc.querySelector("#command-button-paintflashing");
|
||||
ok(button, "Captain, we have the button");
|
||||
|
||||
yield delayedClicks(button, 4);
|
||||
yield* delayedClicks(toolbox, button, 4);
|
||||
checkResults("_PAINTFLASHING_", Telemetry);
|
||||
}
|
||||
|
||||
function delayedClicks(node, clicks) {
|
||||
return new Promise(resolve => {
|
||||
let clicked = 0;
|
||||
function* delayedClicks(toolbox, node, clicks) {
|
||||
for (let i = 0; i < clicks; i++) {
|
||||
yield new Promise(resolve => {
|
||||
// See TOOL_DELAY for why we need setTimeout here
|
||||
setTimeout(() => resolve(), TOOL_DELAY);
|
||||
});
|
||||
|
||||
// See TOOL_DELAY for why we need setTimeout here
|
||||
setTimeout(function delayedClick() {
|
||||
info("Clicking button " + node.id);
|
||||
node.click();
|
||||
clicked++;
|
||||
// this event will fire once the command execution starts and
|
||||
// the output object is created
|
||||
let clicked = toolbox._requisition.commandOutputManager.onOutput.once();
|
||||
|
||||
if (clicked >= clicks) {
|
||||
resolve(node);
|
||||
} else {
|
||||
setTimeout(delayedClick, TOOL_DELAY);
|
||||
}
|
||||
}, TOOL_DELAY);
|
||||
});
|
||||
info("Clicking button " + node.id);
|
||||
node.click();
|
||||
|
||||
let outputEvent = yield clicked;
|
||||
// promise gets resolved once execution finishes and output is ready
|
||||
yield outputEvent.output.promise;
|
||||
}
|
||||
}
|
||||
|
||||
function checkResults(histIdFocus, Telemetry) {
|
||||
|
|
|
@ -516,10 +516,6 @@ size. -->
|
|||
the text of a button; we expect more than one device. -->
|
||||
<!ENTITY home_remote_tabs_unhide_selected_devices "Unhide selected devices">
|
||||
|
||||
<!ENTITY private_browsing_title "Private Browsing">
|
||||
<!ENTITY private_tabs_panel_empty_desc "Your private tabs will show up here. While we don\'t keep any of your browsing history or cookies, bookmarks and files that you download will still be saved on your device.">
|
||||
<!ENTITY private_tabs_panel_learn_more "Want to learn more?">
|
||||
|
||||
<!ENTITY remote_tabs_panel_moved_title "Where did my tabs go?">
|
||||
<!ENTITY remote_tabs_panel_moved_desc "We\'ve moved your tabs from other devices into a panel on your home page that can be easily accessed every time you open a new tab.">
|
||||
<!ENTITY remote_tabs_panel_moved_link "Take me to my new panel.">
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 1.6 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 2.0 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 2.8 KiB |
|
@ -6,45 +6,20 @@
|
|||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:gecko="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<ScrollView android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<FrameLayout android:id="@+id/private_tabs_empty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout android:id="@+id/private_tabs_empty"
|
||||
style="@style/PrivateTabsPanelFrame"
|
||||
android:layout_width="@dimen/private_tabs_panel_empty_width"
|
||||
android:layout_height="@dimen/private_tabs_panel_empty_height">
|
||||
<!-- TODO: Remove the negative marginTop once we get rid of the
|
||||
browser chrome at the bottom of the tabs tray.
|
||||
Bug 1161638 -->
|
||||
<ImageView android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:src="@drawable/private_masq"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="-10dp"/>
|
||||
|
||||
<LinearLayout style="@style/TabsPanelSection.PrivateTabs.Header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView android:id="@+id/private_tabs_empty_header"
|
||||
style="@style/TabsPanelItem.TextAppearance.Header.PrivateTabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/private_browsing_title"/>
|
||||
|
||||
<TextView style="@style/TabsPanelItem.TextAppearance"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/private_tabs_panel_empty_desc"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout style="@style/TabsPanelSection.PrivateTabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView android:id="@+id/private_tabs_learn_more"
|
||||
style="@style/TabsPanelItem.TextAppearance.Linkified.LearnMore"
|
||||
android:layout_width="match_parent"
|
||||
android:text="@string/private_tabs_panel_learn_more"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
</FrameLayout>
|
||||
|
||||
<!-- Note: for an unknown reason, scrolling in the TabsLayout
|
||||
does not work unless it is laid out after the empty view. -->
|
||||
|
|
|
@ -19,34 +19,14 @@
|
|||
</style>
|
||||
|
||||
<!-- Tabs panel -->
|
||||
<style name="PrivateTabsPanelFrame">
|
||||
<item name="android:paddingLeft">16dp</item>
|
||||
<item name="android:paddingRight">16dp</item>
|
||||
<item name="android:orientation">horizontal</item>
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelSection" parent="TabsPanelSectionBase">
|
||||
<item name="android:layout_weight">1</item>
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelSection.PrivateTabs.Header">
|
||||
<item name="android:paddingTop">10dp</item>
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelItem">
|
||||
<item name="android:layout_marginBottom">20dp</item>
|
||||
<item name="android:layout_gravity">left</item>
|
||||
<item name="android:gravity">left</item>
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelItem.TextAppearance.Header.PrivateTabs">
|
||||
<item name="android:visibility">gone</item>
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelItem.TextAppearance.Linkified.LearnMore">
|
||||
<item name="android:layout_height">match_parent</item>
|
||||
<item name="android:gravity">center</item>
|
||||
<item name="android:layout_gravity">center</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -40,20 +40,8 @@
|
|||
<item name="android:layout_marginRight">20dp</item>
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelSection.PrivateTabs">
|
||||
<!-- We set values in tablet portrait. -->
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelSection.PrivateTabs.Header">
|
||||
<!-- We set values in tablet portrait. -->
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelItem" parent="TabsPanelItemBase">
|
||||
<!-- To override the values-land style. -->
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelItem.TextAppearance.Linkified.LearnMore">
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -20,9 +20,6 @@
|
|||
<dimen name="browser_toolbar_site_security_padding_vertical">21dp</dimen>
|
||||
<dimen name="browser_toolbar_site_security_padding_horizontal">8dp</dimen>
|
||||
|
||||
<dimen name="private_tabs_panel_empty_width">300dp</dimen>
|
||||
<dimen name="private_tabs_panel_empty_height">@dimen/wrap_content</dimen>
|
||||
|
||||
<dimen name="tabs_counter_size">26sp</dimen>
|
||||
<dimen name="panel_grid_view_column_width">200dp</dimen>
|
||||
|
||||
|
|
|
@ -126,36 +126,6 @@
|
|||
<item name="android:paddingRight">32dp</item>
|
||||
</style>
|
||||
|
||||
<!-- Tabs panel -->
|
||||
<style name="PrivateTabsPanelFrame">
|
||||
<item name="android:orientation">vertical</item>
|
||||
|
||||
<!-- We want to center the content on the screen, not in
|
||||
the View, so add padding to compensate for the header. -->
|
||||
<item name="android:layout_gravity">center</item>
|
||||
<item name="android:paddingBottom">@dimen/browser_toolbar_height</item>
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelSection.PrivateTabs">
|
||||
<item name="android:layout_weight">1</item>
|
||||
<item name="android:layout_marginLeft">20dp</item>
|
||||
<item name="android:layout_marginRight">20dp</item>
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelSection.PrivateTabs.Header">
|
||||
<item name="android:paddingTop">10dp</item>
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelItem.TextAppearance.Header.PrivateTabs">
|
||||
<item name="android:visibility">visible</item>
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelItem.TextAppearance.Linkified.LearnMore">
|
||||
<item name="android:layout_height">match_parent</item>
|
||||
<item name="android:gravity">center</item>
|
||||
<item name="android:layout_gravity">center</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.UrlBar.Title" parent="TextAppearance.Medium">
|
||||
<item name="android:textSize">16sp</item>
|
||||
</style>
|
||||
|
|
|
@ -140,8 +140,6 @@
|
|||
<dimen name="tabs_counter_size">22sp</dimen>
|
||||
<dimen name="tabs_panel_indicator_width">60dp</dimen>
|
||||
<dimen name="tabs_panel_list_padding">16dip</dimen>
|
||||
<dimen name="private_tabs_panel_empty_width">@dimen/match_parent</dimen>
|
||||
<dimen name="private_tabs_panel_empty_height">@dimen/match_parent</dimen>
|
||||
<dimen name="tabs_list_divider_height">2dp</dimen>
|
||||
<dimen name="tabs_strip_height">40dp</dimen>
|
||||
<dimen name="tabs_strip_button_width">100dp</dimen>
|
||||
|
|
|
@ -520,13 +520,6 @@
|
|||
</style>
|
||||
|
||||
<!-- Tabs panel -->
|
||||
<style name="PrivateTabsPanelFrame">
|
||||
<item name="android:paddingLeft">16dp</item>
|
||||
<item name="android:paddingRight">16dp</item>
|
||||
<item name="android:paddingTop">32dp</item>
|
||||
<item name="android:orientation">vertical</item>
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelSectionBase">
|
||||
<item name="android:orientation">vertical</item>
|
||||
<item name="android:layout_marginLeft">40dp</item>
|
||||
|
@ -537,14 +530,6 @@
|
|||
<!-- We set values in landscape. -->
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelSection.PrivateTabs">
|
||||
<!-- We set values on tablet. -->
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelSection.PrivateTabs.Header">
|
||||
<!-- We set values on landscape and tablet. -->
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelItemBase">
|
||||
<item name="android:layout_marginBottom">28dp</item>
|
||||
<item name="android:layout_gravity">center</item>
|
||||
|
@ -566,20 +551,12 @@
|
|||
<item name="android:layout_marginBottom">16dp</item>
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelItem.TextAppearance.Header.PrivateTabs">
|
||||
<!-- We change these values on landscape and tablet. -->
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelItem.TextAppearance.Linkified">
|
||||
<item name="android:clickable">true</item>
|
||||
<item name="android:focusable">true</item>
|
||||
<item name="android:textColor">#0292D6</item>
|
||||
</style>
|
||||
|
||||
<style name="TabsPanelItem.TextAppearance.Linkified.LearnMore">
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.RemoteTabsItemView" parent="Widget.TwoLinePageRow"/>
|
||||
|
||||
<style name="Widget.RemoteTabsClientView" parent="Widget.TwoLinePageRow">
|
||||
|
|
|
@ -418,11 +418,6 @@
|
|||
<string name="home_remote_tabs_many_hidden_devices">&home_remote_tabs_many_hidden_devices;</string>
|
||||
<string name="home_remote_tabs_hidden_devices_title">&home_remote_tabs_hidden_devices_title;</string>
|
||||
<string name="home_remote_tabs_unhide_selected_devices">&home_remote_tabs_unhide_selected_devices;</string>
|
||||
<string name="private_browsing_title">&private_browsing_title;</string>
|
||||
<string name="private_tabs_panel_empty_desc">&private_tabs_panel_empty_desc;</string>
|
||||
<string name="private_tabs_panel_learn_more">&private_tabs_panel_learn_more;</string>
|
||||
<!-- https://support.mozilla.org/%LOCALE%/kb/mobile-private-browsing-browse-web-without-saving-syncing-info -->
|
||||
<string name="private_tabs_panel_learn_more_link">https://support.mozilla.org/&formatS1;/kb/mobile-private-browsing-browse-web-without-saving-syncing-info</string>
|
||||
<string name="pin_site_dialog_hint">&pin_site_dialog_hint;</string>
|
||||
|
||||
<string name="remote_tabs_panel_moved_title">&remote_tabs_panel_moved_title;</string>
|
||||
|
|
|
@ -5,11 +5,7 @@
|
|||
|
||||
package org.mozilla.gecko.tabs;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.mozilla.gecko.Locales;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.tabs.TabsPanel.CloseAllPanelView;
|
||||
import org.mozilla.gecko.tabs.TabsPanel.TabsLayout;
|
||||
|
||||
|
@ -17,6 +13,7 @@ import android.content.Context;
|
|||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
|
@ -27,8 +24,6 @@ import android.widget.LinearLayout;
|
|||
* empty View's visibility.
|
||||
*/
|
||||
class PrivateTabsPanel extends FrameLayout implements CloseAllPanelView {
|
||||
private TabsPanel tabsPanel;
|
||||
|
||||
private final TabsLayout tabsLayout;
|
||||
|
||||
public PrivateTabsPanel(Context context, AttributeSet attrs) {
|
||||
|
@ -37,27 +32,12 @@ class PrivateTabsPanel extends FrameLayout implements CloseAllPanelView {
|
|||
LayoutInflater.from(context).inflate(R.layout.private_tabs_panel, this);
|
||||
tabsLayout = (TabsLayout) findViewById(R.id.private_tabs_layout);
|
||||
|
||||
final LinearLayout emptyTabsFrame = (LinearLayout) findViewById(R.id.private_tabs_empty);
|
||||
final ViewGroup emptyTabsFrame = (ViewGroup) findViewById(R.id.private_tabs_empty);
|
||||
tabsLayout.setEmptyView(emptyTabsFrame);
|
||||
|
||||
final View learnMore = findViewById(R.id.private_tabs_learn_more);
|
||||
learnMore.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final String locale = Locales.getLanguageTag(Locale.getDefault());
|
||||
final String url =
|
||||
getResources().getString(R.string.private_tabs_panel_learn_more_link, locale);
|
||||
Tabs.getInstance().loadUrlInTab(url);
|
||||
if (tabsPanel != null) {
|
||||
tabsPanel.autoHidePanel();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTabsPanel(TabsPanel panel) {
|
||||
tabsPanel = panel;
|
||||
tabsLayout.setTabsPanel(panel);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
const NS_APP_CACHE_PARENT_DIR = "cachePDir";
|
||||
const NS_APP_SEARCH_DIR = "SrchPlugns";
|
||||
const NS_APP_SEARCH_DIR_LIST = "SrchPluginsDL";
|
||||
const NS_APP_DISTRIBUTION_SEARCH_DIR_LIST = "SrchPluginsDistDL";
|
||||
const NS_APP_USER_SEARCH_DIR = "UsrSrchPlugns";
|
||||
const NS_XPCOM_CURRENT_PROCESS_DIR = "XCurProcD";
|
||||
const XRE_APP_DISTRIBUTION_DIR = "XREAppDist";
|
||||
|
@ -147,27 +148,32 @@ DirectoryProvider.prototype = {
|
|||
},
|
||||
|
||||
getFiles: function(prop) {
|
||||
if (prop != NS_APP_SEARCH_DIR_LIST)
|
||||
return;
|
||||
if (prop != NS_APP_SEARCH_DIR_LIST &&
|
||||
prop != NS_APP_DISTRIBUTION_SEARCH_DIR_LIST)
|
||||
return null;
|
||||
|
||||
let result = [];
|
||||
|
||||
/**
|
||||
* We want to preserve the following order, since the search service loads
|
||||
* engines in first-loaded-wins order.
|
||||
* - distro search plugin locations
|
||||
* - user search plugin locations (profile)
|
||||
* - app search plugin location (shipped engines)
|
||||
*/
|
||||
this._appendDistroSearchDirs(result);
|
||||
if (prop == NS_APP_DISTRIBUTION_SEARCH_DIR_LIST) {
|
||||
this._appendDistroSearchDirs(result);
|
||||
}
|
||||
else {
|
||||
/**
|
||||
* We want to preserve the following order, since the search service
|
||||
* loads engines in first-loaded-wins order.
|
||||
* - distro search plugin locations (loaded separately by the search
|
||||
* service)
|
||||
* - user search plugin locations (profile)
|
||||
* - app search plugin location (shipped engines)
|
||||
*/
|
||||
let appUserSearchDir = FileUtils.getDir(NS_APP_USER_SEARCH_DIR, [], false);
|
||||
if (appUserSearchDir.exists())
|
||||
result.push(appUserSearchDir);
|
||||
|
||||
let appUserSearchDir = FileUtils.getDir(NS_APP_USER_SEARCH_DIR, [], false);
|
||||
if (appUserSearchDir.exists())
|
||||
result.push(appUserSearchDir);
|
||||
|
||||
let appSearchDir = FileUtils.getDir(NS_APP_SEARCH_DIR, [], false);
|
||||
if (appSearchDir.exists())
|
||||
result.push(appSearchDir);
|
||||
let appSearchDir = FileUtils.getDir(NS_APP_SEARCH_DIR, [], false);
|
||||
if (appSearchDir.exists())
|
||||
result.push(appSearchDir);
|
||||
}
|
||||
|
||||
return {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]),
|
||||
|
|
|
@ -51,6 +51,7 @@ const MODE_TRUNCATE = 0x20;
|
|||
|
||||
// Directory service keys
|
||||
const NS_APP_SEARCH_DIR_LIST = "SrchPluginsDL";
|
||||
const NS_APP_DISTRIBUTION_SEARCH_DIR_LIST = "SrchPluginsDistDL";
|
||||
const NS_APP_USER_SEARCH_DIR = "UsrSrchPlugns";
|
||||
const NS_APP_SEARCH_DIR = "SrchPlugns";
|
||||
const NS_APP_USER_PROFILE_50_DIR = "ProfD";
|
||||
|
@ -3485,8 +3486,7 @@ SearchService.prototype = {
|
|||
cache = this._readCacheFile(cacheFile);
|
||||
}
|
||||
|
||||
let loadDirs = [], chromeURIs = [], chromeFiles = [];
|
||||
|
||||
let chromeURIs = [], chromeFiles = [];
|
||||
let loadFromJARs = false;
|
||||
try {
|
||||
loadFromJARs = Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF)
|
||||
|
@ -3496,16 +3496,33 @@ SearchService.prototype = {
|
|||
if (loadFromJARs)
|
||||
[chromeFiles, chromeURIs] = this._findJAREngines();
|
||||
|
||||
let locations = getDir(NS_APP_SEARCH_DIR_LIST, Ci.nsISimpleEnumerator);
|
||||
let distDirs = [];
|
||||
let locations;
|
||||
try {
|
||||
locations = getDir(NS_APP_DISTRIBUTION_SEARCH_DIR_LIST,
|
||||
Ci.nsISimpleEnumerator);
|
||||
} catch (e) {
|
||||
// NS_APP_DISTRIBUTION_SEARCH_DIR_LIST is defined by each app
|
||||
// so this throws during unit tests (but not xpcshell tests).
|
||||
locations = {hasMoreElements: () => false};
|
||||
}
|
||||
while (locations.hasMoreElements()) {
|
||||
let dir = locations.getNext().QueryInterface(Ci.nsIFile);
|
||||
if (dir.directoryEntries.hasMoreElements())
|
||||
distDirs.push(dir);
|
||||
}
|
||||
|
||||
let otherDirs = [];
|
||||
locations = getDir(NS_APP_SEARCH_DIR_LIST, Ci.nsISimpleEnumerator);
|
||||
while (locations.hasMoreElements()) {
|
||||
let dir = locations.getNext().QueryInterface(Ci.nsIFile);
|
||||
if (loadFromJARs && dir.equals(getDir(NS_APP_SEARCH_DIR)))
|
||||
continue;
|
||||
if (dir.directoryEntries.hasMoreElements())
|
||||
loadDirs.push(dir);
|
||||
otherDirs.push(dir);
|
||||
}
|
||||
|
||||
let toLoad = chromeFiles.concat(loadDirs);
|
||||
let toLoad = chromeFiles.concat(distDirs, otherDirs);
|
||||
|
||||
function modifiedDir(aDir) {
|
||||
return (!cache.directories || !cache.directories[aDir.path] ||
|
||||
|
@ -3528,10 +3545,12 @@ SearchService.prototype = {
|
|||
|
||||
if (!cacheEnabled || rebuildCache) {
|
||||
LOG("_loadEngines: Absent or outdated cache. Loading engines from disk.");
|
||||
loadDirs.forEach(this._loadEnginesFromDir, this);
|
||||
distDirs.forEach(this._loadEnginesFromDir, this);
|
||||
|
||||
this._loadFromChromeURLs(chromeURIs);
|
||||
|
||||
otherDirs.forEach(this._loadEnginesFromDir, this);
|
||||
|
||||
if (cacheEnabled)
|
||||
this._buildCache();
|
||||
return;
|
||||
|
@ -3561,8 +3580,7 @@ SearchService.prototype = {
|
|||
cache = yield checkForSyncCompletion(this._asyncReadCacheFile(cacheFilePath));
|
||||
}
|
||||
|
||||
let loadDirs = [], chromeURIs = [], chromeFiles = [];
|
||||
|
||||
let chromeURIs = [], chromeFiles = [];
|
||||
let loadFromJARs = false;
|
||||
try {
|
||||
loadFromJARs = Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF)
|
||||
|
@ -3575,21 +3593,25 @@ SearchService.prototype = {
|
|||
yield checkForSyncCompletion(this._asyncFindJAREngines());
|
||||
}
|
||||
|
||||
// Add the non-empty directories of NS_APP_SEARCH_DIR_LIST to
|
||||
// loadDirs...
|
||||
let locations = getDir(NS_APP_SEARCH_DIR_LIST, Ci.nsISimpleEnumerator);
|
||||
// Get the non-empty distribution directories into distDirs...
|
||||
let distDirs = [];
|
||||
let locations;
|
||||
try {
|
||||
locations = getDir(NS_APP_DISTRIBUTION_SEARCH_DIR_LIST,
|
||||
Ci.nsISimpleEnumerator);
|
||||
} catch (e) {
|
||||
// NS_APP_DISTRIBUTION_SEARCH_DIR_LIST is defined by each app
|
||||
// so this throws during unit tests (but not xpcshell tests).
|
||||
locations = {hasMoreElements: () => false};
|
||||
}
|
||||
while (locations.hasMoreElements()) {
|
||||
let dir = locations.getNext().QueryInterface(Ci.nsIFile);
|
||||
// ... but skip the application directory if we are loading from JAR.
|
||||
if (loadFromJARs && dir.equals(getDir(NS_APP_SEARCH_DIR)))
|
||||
continue;
|
||||
|
||||
let iterator = new OS.File.DirectoryIterator(dir.path,
|
||||
{ winPattern: "*.xml" });
|
||||
try {
|
||||
// Add dir to loadDirs if it contains any files.
|
||||
// Add dir to distDirs if it contains any files.
|
||||
yield checkForSyncCompletion(iterator.next());
|
||||
loadDirs.push(dir);
|
||||
distDirs.push(dir);
|
||||
} catch (ex if ex.result != Cr.NS_ERROR_ALREADY_INITIALIZED) {
|
||||
// Catch for StopIteration exception.
|
||||
} finally {
|
||||
|
@ -3597,7 +3619,32 @@ SearchService.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
let toLoad = chromeFiles.concat(loadDirs);
|
||||
// Add the non-empty directories of NS_APP_SEARCH_DIR_LIST to
|
||||
// otherDirs...
|
||||
let otherDirs = [];
|
||||
locations = getDir(NS_APP_SEARCH_DIR_LIST, Ci.nsISimpleEnumerator);
|
||||
while (locations.hasMoreElements()) {
|
||||
let dir = locations.getNext().QueryInterface(Ci.nsIFile);
|
||||
// ... but skip the application directory if we are loading from JAR.
|
||||
// Applications shipping JAR engines don't ship plain text
|
||||
// engine files anymore.
|
||||
if (loadFromJARs && dir.equals(getDir(NS_APP_SEARCH_DIR)))
|
||||
continue;
|
||||
|
||||
let iterator = new OS.File.DirectoryIterator(dir.path,
|
||||
{ winPattern: "*.xml" });
|
||||
try {
|
||||
// Add dir to otherDirs if it contains any files.
|
||||
yield checkForSyncCompletion(iterator.next());
|
||||
otherDirs.push(dir);
|
||||
} catch (ex if ex.result != Cr.NS_ERROR_ALREADY_INITIALIZED) {
|
||||
// Catch for StopIteration exception.
|
||||
} finally {
|
||||
iterator.close();
|
||||
}
|
||||
}
|
||||
|
||||
let toLoad = chromeFiles.concat(distDirs, otherDirs);
|
||||
function hasModifiedDir(aList) {
|
||||
return Task.spawn(function() {
|
||||
let modifiedDir = false;
|
||||
|
@ -3636,7 +3683,7 @@ SearchService.prototype = {
|
|||
if (!cacheEnabled || rebuildCache) {
|
||||
LOG("_asyncLoadEngines: Absent or outdated cache. Loading engines from disk.");
|
||||
let engines = [];
|
||||
for (let loadDir of loadDirs) {
|
||||
for (let loadDir of distDirs) {
|
||||
let enginesFromDir =
|
||||
yield checkForSyncCompletion(this._asyncLoadEnginesFromDir(loadDir));
|
||||
engines = engines.concat(enginesFromDir);
|
||||
|
@ -3644,6 +3691,11 @@ SearchService.prototype = {
|
|||
let enginesFromURLs =
|
||||
yield checkForSyncCompletion(this._asyncLoadFromChromeURLs(chromeURIs));
|
||||
engines = engines.concat(enginesFromURLs);
|
||||
for (let loadDir of otherDirs) {
|
||||
let enginesFromDir =
|
||||
yield checkForSyncCompletion(this._asyncLoadEnginesFromDir(loadDir));
|
||||
engines = engines.concat(enginesFromDir);
|
||||
}
|
||||
|
||||
for (let engine of engines) {
|
||||
this._addEngineToStore(engine);
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
|
||||
<ShortName>addon</ShortName>
|
||||
<Description>addon</Description>
|
||||
<InputEncoding>UTF-8</InputEncoding>
|
||||
<Url type="text/html" method="GET" template="http://searchtest.local">
|
||||
<Param name="search" value="{searchTerms}"/>
|
||||
</Url>
|
||||
</SearchPlugin>
|
|
@ -0,0 +1,8 @@
|
|||
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
|
||||
<ShortName>bug645970</ShortName>
|
||||
<Description>override</Description>
|
||||
<InputEncoding>UTF-8</InputEncoding>
|
||||
<Url type="text/html" method="GET" template="http://searchtest.local">
|
||||
<Param name="search" value="{searchTerms}"/>
|
||||
</Url>
|
||||
</SearchPlugin>
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.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>search-engine@tests.mozilla.org</em:id>
|
||||
<em:unpack>true</em:unpack>
|
||||
<em:version>1.0</em:version>
|
||||
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>toolkit@mozilla.org</em:id>
|
||||
<em:minVersion>0</em:minVersion>
|
||||
<em:maxVersion>*</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
|
||||
<!-- Front End MetaData -->
|
||||
<em:name>Search Engine</em:name>
|
||||
|
||||
</Description>
|
||||
</RDF>
|
|
@ -96,6 +96,90 @@ function configureToLoadJarEngines(loadFromJars = true)
|
|||
do_get_file("data/engine-app.xml").copyTo(dir, "app.xml");
|
||||
}
|
||||
|
||||
/**
|
||||
* Fake the installation of an add-on in the profile, by creating the
|
||||
* directory and registering it with the directory service.
|
||||
*/
|
||||
function installAddonEngine(name = "engine-addon")
|
||||
{
|
||||
const XRE_EXTENSIONS_DIR_LIST = "XREExtDL";
|
||||
const gProfD = do_get_profile().QueryInterface(Ci.nsILocalFile);
|
||||
|
||||
let dir = gProfD.clone();
|
||||
dir.append("extensions");
|
||||
if (!dir.exists())
|
||||
dir.create(dir.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
|
||||
dir.append("search-engine@tests.mozilla.org");
|
||||
dir.create(dir.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
|
||||
do_get_file("data/install.rdf").copyTo(dir, "install.rdf");
|
||||
let addonDir = dir.clone();
|
||||
dir.append("searchplugins");
|
||||
dir.create(dir.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
do_get_file("data/" + name + ".xml").copyTo(dir, "bug645970.xml");
|
||||
|
||||
Services.dirsvc.registerProvider({
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider,
|
||||
Ci.nsIDirectoryServiceProvider2]),
|
||||
|
||||
getFile: function (prop, persistant) {
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
},
|
||||
|
||||
getFiles: function (prop) {
|
||||
let result = [];
|
||||
|
||||
switch (prop) {
|
||||
case XRE_EXTENSIONS_DIR_LIST:
|
||||
result.push(addonDir);
|
||||
break;
|
||||
default:
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]),
|
||||
hasMoreElements: () => result.length > 0,
|
||||
getNext: () => result.shift()
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the engine-distribution.xml engine to a fake distribution
|
||||
* created in the profile, and registered with the directory service.
|
||||
*/
|
||||
function installDistributionEngine()
|
||||
{
|
||||
const XRE_APP_DISTRIBUTION_DIR = "XREAppDist";
|
||||
|
||||
const gProfD = do_get_profile().QueryInterface(Ci.nsILocalFile);
|
||||
|
||||
let dir = gProfD.clone();
|
||||
dir.append("distribution");
|
||||
dir.create(dir.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
let distDir = dir.clone();
|
||||
|
||||
dir.append("searchplugins");
|
||||
dir.create(dir.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
|
||||
dir.append("common");
|
||||
dir.create(dir.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
|
||||
do_get_file("data/engine-override.xml").copyTo(dir, "bug645970.xml");
|
||||
|
||||
Services.dirsvc.registerProvider({
|
||||
getFile: function(aProp, aPersistent) {
|
||||
aPersistent.value = true;
|
||||
if (aProp == XRE_APP_DISTRIBUTION_DIR)
|
||||
return distDir.clone();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean the profile of any metadata files left from a previous run.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
|
||||
removeMetadata();
|
||||
removeCacheFile();
|
||||
|
||||
do_load_manifest("data/chrome.manifest");
|
||||
|
||||
configureToLoadJarEngines();
|
||||
installAddonEngine();
|
||||
|
||||
do_check_false(Services.search.isInitialized);
|
||||
|
||||
Services.search.init(function search_initialized(aStatus) {
|
||||
do_check_true(Components.isSuccessCode(aStatus));
|
||||
do_check_true(Services.search.isInitialized);
|
||||
|
||||
// test the add-on engine is loaded in addition to our jar engine
|
||||
let engines = Services.search.getEngines();
|
||||
do_check_eq(engines.length, 2);
|
||||
|
||||
// test jar engine is loaded ok.
|
||||
let engine = Services.search.getEngineByName("addon");
|
||||
do_check_neq(engine, null);
|
||||
|
||||
do_check_eq(engine.description, "addon");
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
|
||||
removeMetadata();
|
||||
removeCacheFile();
|
||||
|
||||
do_load_manifest("data/chrome.manifest");
|
||||
|
||||
configureToLoadJarEngines();
|
||||
installAddonEngine("engine-override");
|
||||
|
||||
do_check_false(Services.search.isInitialized);
|
||||
|
||||
Services.search.init(function search_initialized(aStatus) {
|
||||
do_check_true(Components.isSuccessCode(aStatus));
|
||||
do_check_true(Services.search.isInitialized);
|
||||
|
||||
// test the add-on engine isn't overriding our jar engine
|
||||
let engines = Services.search.getEngines();
|
||||
do_check_eq(engines.length, 1);
|
||||
|
||||
// test jar engine is loaded ok.
|
||||
let engine = Services.search.getEngineByName("bug645970");
|
||||
do_check_neq(engine, null);
|
||||
|
||||
do_check_eq(engine.description, "bug645970");
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
|
||||
removeMetadata();
|
||||
removeCacheFile();
|
||||
|
||||
do_load_manifest("data/chrome.manifest");
|
||||
|
||||
configureToLoadJarEngines();
|
||||
installDistributionEngine();
|
||||
|
||||
do_check_false(Services.search.isInitialized);
|
||||
|
||||
Services.search.init(function search_initialized(aStatus) {
|
||||
do_check_true(Components.isSuccessCode(aStatus));
|
||||
do_check_true(Services.search.isInitialized);
|
||||
|
||||
// test that the engine from the distribution overrides our jar engine
|
||||
let engines = Services.search.getEngines();
|
||||
do_check_eq(engines.length, 1);
|
||||
|
||||
let engine = Services.search.getEngineByName("bug645970");
|
||||
do_check_neq(engine, null);
|
||||
|
||||
// check the engine we have is actually the one from the distribution
|
||||
do_check_eq(engine.description, "override");
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const NS_APP_USER_SEARCH_DIR = "UsrSrchPlugns";
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
|
||||
removeMetadata();
|
||||
removeCacheFile();
|
||||
|
||||
do_load_manifest("data/chrome.manifest");
|
||||
|
||||
configureToLoadJarEngines();
|
||||
|
||||
// Copy an engine in [profile]/searchplugin/ and ensure it's not
|
||||
// overriding the same file from a jar.
|
||||
// The description in the file we are copying is 'profile'.
|
||||
let dir = Services.dirsvc.get(NS_APP_USER_SEARCH_DIR, Ci.nsIFile);
|
||||
if (!dir.exists())
|
||||
dir.create(dir.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
do_get_file("data/engine-override.xml").copyTo(dir, "bug645970.xml");
|
||||
|
||||
do_check_false(Services.search.isInitialized);
|
||||
|
||||
Services.search.init(function search_initialized(aStatus) {
|
||||
do_check_true(Components.isSuccessCode(aStatus));
|
||||
do_check_true(Services.search.isInitialized);
|
||||
|
||||
// test engines from dir are not loaded.
|
||||
let engines = Services.search.getEngines();
|
||||
do_check_eq(engines.length, 1);
|
||||
|
||||
// test jar engine is loaded ok.
|
||||
let engine = Services.search.getEngineByName("bug645970");
|
||||
do_check_neq(engine, null);
|
||||
|
||||
do_check_eq(engine.description, "bug645970");
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function run_test() {
|
||||
removeMetadata();
|
||||
removeCacheFile();
|
||||
|
||||
do_load_manifest("data/chrome.manifest");
|
||||
|
||||
configureToLoadJarEngines();
|
||||
installAddonEngine();
|
||||
|
||||
do_check_false(Services.search.isInitialized);
|
||||
|
||||
// test the add-on engine is loaded in addition to our jar engine
|
||||
let engines = Services.search.getEngines();
|
||||
do_check_eq(engines.length, 2);
|
||||
|
||||
do_check_true(Services.search.isInitialized);
|
||||
|
||||
// test jar engine is loaded ok.
|
||||
let engine = Services.search.getEngineByName("addon");
|
||||
do_check_neq(engine, null);
|
||||
|
||||
do_check_eq(engine.description, "addon");
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function run_test() {
|
||||
removeMetadata();
|
||||
removeCacheFile();
|
||||
|
||||
do_load_manifest("data/chrome.manifest");
|
||||
|
||||
configureToLoadJarEngines();
|
||||
installAddonEngine("engine-override");
|
||||
|
||||
do_check_false(Services.search.isInitialized);
|
||||
|
||||
// test the add-on engine isn't overriding our jar engine
|
||||
let engines = Services.search.getEngines();
|
||||
do_check_eq(engines.length, 1);
|
||||
|
||||
do_check_true(Services.search.isInitialized);
|
||||
|
||||
// test jar engine is loaded ok.
|
||||
let engine = Services.search.getEngineByName("bug645970");
|
||||
do_check_neq(engine, null);
|
||||
|
||||
do_check_eq(engine.description, "bug645970");
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function run_test() {
|
||||
removeMetadata();
|
||||
removeCacheFile();
|
||||
|
||||
do_load_manifest("data/chrome.manifest");
|
||||
|
||||
configureToLoadJarEngines();
|
||||
installDistributionEngine();
|
||||
|
||||
do_check_false(Services.search.isInitialized);
|
||||
|
||||
// test that the engine from the distribution overrides our jar engine
|
||||
let engines = Services.search.getEngines();
|
||||
do_check_eq(engines.length, 1);
|
||||
|
||||
do_check_true(Services.search.isInitialized);
|
||||
|
||||
let engine = Services.search.getEngineByName("bug645970");
|
||||
do_check_neq(engine, null);
|
||||
|
||||
// check the engine we have is actually the one from the distribution
|
||||
do_check_eq(engine.description, "override");
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const NS_APP_USER_SEARCH_DIR = "UsrSrchPlugns";
|
||||
|
||||
function run_test() {
|
||||
removeMetadata();
|
||||
removeCacheFile();
|
||||
|
||||
do_load_manifest("data/chrome.manifest");
|
||||
|
||||
configureToLoadJarEngines();
|
||||
|
||||
// Copy an engine in [profile]/searchplugin/ and ensure it's not
|
||||
// overriding the same file from a jar.
|
||||
// The description in the file we are copying is 'profile'.
|
||||
let dir = Services.dirsvc.get(NS_APP_USER_SEARCH_DIR, Ci.nsIFile);
|
||||
if (!dir.exists())
|
||||
dir.create(dir.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
do_get_file("data/engine-override.xml").copyTo(dir, "bug645970.xml");
|
||||
|
||||
do_check_false(Services.search.isInitialized);
|
||||
|
||||
// test engines from dir are not loaded.
|
||||
let engines = Services.search.getEngines();
|
||||
do_check_eq(engines.length, 1);
|
||||
|
||||
do_check_true(Services.search.isInitialized);
|
||||
|
||||
// test jar engine is loaded ok.
|
||||
let engine = Services.search.getEngineByName("bug645970");
|
||||
do_check_neq(engine, null);
|
||||
|
||||
do_check_eq(engine.description, "bug645970");
|
||||
}
|
|
@ -8,6 +8,8 @@ support-files =
|
|||
data/engine.src
|
||||
data/engine.xml
|
||||
data/engine2.xml
|
||||
data/engine-addon.xml
|
||||
data/engine-override.xml
|
||||
data/engine-app.xml
|
||||
data/engine-fr.xml
|
||||
data/engineMaker.sjs
|
||||
|
@ -17,6 +19,7 @@ support-files =
|
|||
data/engineImages.xml
|
||||
data/ico-size-16x16-png.ico
|
||||
data/invalid-engine.xml
|
||||
data/install.rdf
|
||||
data/search-metadata.json
|
||||
data/search.json
|
||||
data/search.sqlite
|
||||
|
@ -58,9 +61,17 @@ support-files =
|
|||
[test_searchSuggest.js]
|
||||
[test_async.js]
|
||||
[test_async_app.js]
|
||||
[test_async_addon.js]
|
||||
[test_async_addon_no_override.js]
|
||||
[test_async_distribution.js]
|
||||
[test_async_profile_engine.js]
|
||||
[test_sync.js]
|
||||
[test_sync_app.js]
|
||||
[test_sync_addon.js]
|
||||
[test_sync_addon_no_override.js]
|
||||
[test_sync_distribution.js]
|
||||
[test_sync_fallback.js]
|
||||
[test_sync_delay_fallback.js]
|
||||
[test_sync_profile_engine.js]
|
||||
[test_rel_searchform.js]
|
||||
[test_selectedEngine.js]
|
||||
|
|
|
@ -112,9 +112,9 @@ exports.items = [
|
|||
}],
|
||||
exec: function*(args, context) {
|
||||
if (!args.chrome) {
|
||||
const value = yield context.updateExec("paintflashing_server --state on");
|
||||
isContentPaintFlashing = value;
|
||||
onPaintFlashingChanged(context.environment.target, value);
|
||||
const output = yield context.updateExec("paintflashing_server --state on");
|
||||
isContentPaintFlashing = output.data;
|
||||
onPaintFlashingChanged(context.environment.target, output.data);
|
||||
}
|
||||
else {
|
||||
setPaintFlashing(context.environment.chromeWindow, "on");
|
||||
|
@ -142,9 +142,9 @@ exports.items = [
|
|||
}],
|
||||
exec: function*(args, context) {
|
||||
if (!args.chrome) {
|
||||
const value = yield context.updateExec("paintflashing_server --state off");
|
||||
isContentPaintFlashing = value;
|
||||
onPaintFlashingChanged(context.environment.target, value);
|
||||
const output = yield context.updateExec("paintflashing_server --state off");
|
||||
isContentPaintFlashing = output.data;
|
||||
onPaintFlashingChanged(context.environment.target, output.data);
|
||||
}
|
||||
else {
|
||||
setPaintFlashing(context.environment.chromeWindow, "off");
|
||||
|
@ -167,9 +167,9 @@ exports.items = [
|
|||
description: l10n.lookup("paintflashingToggleDesc"),
|
||||
manual: l10n.lookup("paintflashingManual"),
|
||||
exec: function*(args, context) {
|
||||
const value = yield context.updateExec("paintflashing_server --state toggle");
|
||||
isContentPaintFlashing = value;
|
||||
onPaintFlashingChanged(context.environment.target, value);
|
||||
const output = yield context.updateExec("paintflashing_server --state toggle");
|
||||
isContentPaintFlashing = output.data;
|
||||
onPaintFlashingChanged(context.environment.target, output.data);
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -201,6 +201,8 @@ Moving right along, let's say you want to pass/return an array of Incrementors.
|
|||
response: { incrementors: RetVal("array:incrementor") }
|
||||
})
|
||||
|
||||
You can use an iterator in place of an array as an argument or return value, and the library will handle the conversion automatically.
|
||||
|
||||
Or maybe you want to return a dictionary where one item is a incrementor. To do this you need to tell the type system which members of the dictionary need custom marshallers:
|
||||
|
||||
protocol.types.addDictType("contrivedObject", {
|
||||
|
|
|
@ -109,6 +109,11 @@ function identityWrite(v) {
|
|||
if (v === undefined) {
|
||||
throw Error("undefined passed where a value is required");
|
||||
}
|
||||
// This has to handle iterator->array conversion because arrays of
|
||||
// primitive types pass through here.
|
||||
if (v && typeof (v) === "object" && Symbol.iterator in v) {
|
||||
return [...v];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
@ -190,8 +195,8 @@ types.addArrayType = function(subtype) {
|
|||
}
|
||||
return types.addType(name, {
|
||||
category: "array",
|
||||
read: (v, ctx) => v.map(i => subtype.read(i, ctx)),
|
||||
write: (v, ctx) => v.map(i => subtype.write(i, ctx))
|
||||
read: (v, ctx) => [...v].map(i => subtype.read(i, ctx)),
|
||||
write: (v, ctx) => [...v].map(i => subtype.write(i, ctx))
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -82,6 +82,19 @@ let ChildActor = protocol.ActorClass({
|
|||
}
|
||||
}),
|
||||
|
||||
getIntArray: method(function(inputArray) {
|
||||
// Test that protocol.js converts an iterator to an array.
|
||||
let f = function*() {
|
||||
for (let i of inputArray) {
|
||||
yield 2 * i;
|
||||
}
|
||||
};
|
||||
return f();
|
||||
}, {
|
||||
request: { inputArray: Arg(0, "array:number") },
|
||||
response: RetVal("array:number")
|
||||
}),
|
||||
|
||||
getSibling: method(function(id) {
|
||||
return this.parent().getChild(id);
|
||||
}, {
|
||||
|
@ -193,6 +206,18 @@ let RootActor = protocol.ActorClass({
|
|||
response: { children: RetVal("array:childActor") },
|
||||
}),
|
||||
|
||||
getChildren2: method(function(ids) {
|
||||
let f = function*() {
|
||||
for (let c of ids) {
|
||||
yield c;
|
||||
}
|
||||
};
|
||||
return f();
|
||||
}, {
|
||||
request: { ids: Arg(0, "array:childActor") },
|
||||
response: { children: RetVal("array:childActor") },
|
||||
}),
|
||||
|
||||
getManyChildren: method(function() {
|
||||
return {
|
||||
foo: "bar", // note that this isn't in the specialization array.
|
||||
|
@ -441,6 +466,34 @@ function run_test()
|
|||
do_check_eq(ret.child5.childID, "child5");
|
||||
do_check_eq(ret.more[0].childID, "child6");
|
||||
do_check_eq(ret.more[1].childID, "child7");
|
||||
}).then(() => {
|
||||
// Test accepting a generator.
|
||||
let f = function*() {
|
||||
for (let i of [1, 2, 3, 4, 5]) {
|
||||
yield i;
|
||||
}
|
||||
};
|
||||
return childFront.getIntArray(f());
|
||||
}).then((ret) => {
|
||||
do_check_eq(ret.length, 5);
|
||||
let expected = [2, 4, 6, 8, 10];
|
||||
for (let i = 0; i < 5; ++i) {
|
||||
do_check_eq(ret[i], expected[i]);
|
||||
}
|
||||
}).then(() => {
|
||||
return rootFront.getChildren(["child1", "child2"]);
|
||||
}).then(ids => {
|
||||
let f = function*() {
|
||||
for (let id of ids) {
|
||||
yield id;
|
||||
}
|
||||
};
|
||||
return rootFront.getChildren2(f());
|
||||
}).then(ret => {
|
||||
do_check_eq(ret.length, 2);
|
||||
do_check_true(ret[0] === childFront);
|
||||
do_check_true(ret[1] !== childFront);
|
||||
do_check_true(ret[1] instanceof ChildFront);
|
||||
}).then(() => {
|
||||
client.close(() => {
|
||||
do_test_finished();
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#define NS_APP_CHROME_DIR_LIST "AChromDL"
|
||||
#define NS_APP_PLUGINS_DIR_LIST "APluginsDL"
|
||||
#define NS_APP_SEARCH_DIR_LIST "SrchPluginsDL"
|
||||
#define NS_APP_DISTRIBUTION_SEARCH_DIR_LIST "SrchPluginsDistDL"
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Files and directories which exist on a per-profile basis
|
||||
|
|
Загрузка…
Ссылка в новой задаче