зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound
This commit is contained in:
Коммит
ba5885ce64
|
@ -18,7 +18,7 @@ sinclude $(topsrcdir)/config/rules.mk
|
|||
|
||||
# This can switch to just zipping the files when native jetpacks land
|
||||
$(TESTADDONS)/%.xpi: FORCE $(call mkdir_deps,$(CURDIR)/$(TESTADDONS)) $(ADDONSRC)/%
|
||||
$(PYTHON) $(srcdir)/source/bin/cfx xpi --pkgdir=$(lastword $^) --output-file=$@
|
||||
$(PYTHON) $(srcdir)/source/bin/cfx xpi --no-strip-xpi --pkgdir=$(lastword $^) --output-file=$@
|
||||
|
||||
#libs:: $(ADDONS)
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="943c8b4039f59b08ba100390e164a076a20c892e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2b87ee8e7e2ec30a9851b6b59a899006a98767ab"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -134,10 +134,10 @@
|
|||
<project name="platform/hardware/akm" path="hardware/akm" revision="6d3be412647b0eab0adff8a2768736cf4eb68039"/>
|
||||
<project groups="invensense" name="platform/hardware/invensense" path="hardware/invensense" revision="e6d9ab28b4f4e7684f6c07874ee819c9ea0002a2"/>
|
||||
<project name="platform/hardware/ril" path="hardware/ril" revision="865ce3b4a2ba0b3a31421ca671f4d6c5595f8690"/>
|
||||
<project name="kernel/common" path="kernel" revision="855c239879b1d0ba2dc783e64c32cf8a0afadfc4"/>
|
||||
<project name="kernel/common" path="kernel" revision="737e6b490870911879b80d0961297cd03e0a9028"/>
|
||||
<project name="platform/system/core" path="system/core" revision="a626f6c0ef9e88586569331bd7387b569eaa5ed2"/>
|
||||
<project name="u-boot" path="u-boot" revision="f1502910977ac88f43da7bf9277c3523ad4b0b2f"/>
|
||||
<project name="vendor/sprd/gps" path="vendor/sprd/gps" revision="6974f8e771d4d8e910357a6739ab124768891e8f"/>
|
||||
<project name="vendor/sprd/gps" path="vendor/sprd/gps" revision="4c59900937dc2e978b7b14b7f1ea617e3d5d550e"/>
|
||||
<project name="vendor/sprd/open-source" path="vendor/sprd/open-source" revision="cce8a36e1ec3d136f5eb8ec4b767d9c6ef08c427"/>
|
||||
<project name="vendor/sprd/partner" path="vendor/sprd/partner" revision="8649c7145972251af11b0639997edfecabfc7c2e"/>
|
||||
<project name="vendor/sprd/proprietories" path="vendor/sprd/proprietories" revision="d2466593022f7078aaaf69026adf3367c2adb7bb"/>
|
||||
|
|
|
@ -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="943c8b4039f59b08ba100390e164a076a20c892e"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2b87ee8e7e2ec30a9851b6b59a899006a98767ab"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
||||
|
|
|
@ -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="943c8b4039f59b08ba100390e164a076a20c892e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2b87ee8e7e2ec30a9851b6b59a899006a98767ab"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="ddf33f81e9a60f8110fcfd6b51b5dff2db676183"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="943c8b4039f59b08ba100390e164a076a20c892e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2b87ee8e7e2ec30a9851b6b59a899006a98767ab"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="943c8b4039f59b08ba100390e164a076a20c892e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2b87ee8e7e2ec30a9851b6b59a899006a98767ab"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
|
||||
<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="943c8b4039f59b08ba100390e164a076a20c892e"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2b87ee8e7e2ec30a9851b6b59a899006a98767ab"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="943c8b4039f59b08ba100390e164a076a20c892e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2b87ee8e7e2ec30a9851b6b59a899006a98767ab"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="943c8b4039f59b08ba100390e164a076a20c892e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2b87ee8e7e2ec30a9851b6b59a899006a98767ab"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="ddf33f81e9a60f8110fcfd6b51b5dff2db676183"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "943c8b4039f59b08ba100390e164a076a20c892e",
|
||||
"git_revision": "2b87ee8e7e2ec30a9851b6b59a899006a98767ab",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "c8f9d4bbb0ab4ddfb272c0ee955e640b9d122b54",
|
||||
"revision": "a3f060d46f5e179164fe9435f30878ebdf58eb49",
|
||||
"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="943c8b4039f59b08ba100390e164a076a20c892e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2b87ee8e7e2ec30a9851b6b59a899006a98767ab"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="ddf33f81e9a60f8110fcfd6b51b5dff2db676183"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="943c8b4039f59b08ba100390e164a076a20c892e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2b87ee8e7e2ec30a9851b6b59a899006a98767ab"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -1461,6 +1461,8 @@ pref("devtools.profiler.ui.show-platform-data", false);
|
|||
pref("devtools.profiler.ui.show-idle-blocks", true);
|
||||
|
||||
// The default Performance UI settings
|
||||
pref("devtools.performance.memory.sample-probability", "0.05");
|
||||
pref("devtools.performance.memory.max-log-length", 2147483647); // Math.pow(2,31) - 1
|
||||
pref("devtools.performance.timeline.hidden-markers", "[]");
|
||||
pref("devtools.performance.ui.invert-call-tree", true);
|
||||
pref("devtools.performance.ui.invert-flame-graph", false);
|
||||
|
|
|
@ -30,7 +30,7 @@ function createScheduler(options) {
|
|||
// avoid typos in the test and other footguns in the options.
|
||||
let allowedOptions = ["expectedDelay", "expectNewTimer", "syncFunction"];
|
||||
for (let key of Object.keys(options)) {
|
||||
if (!allowedOptions.includes(key)) {
|
||||
if (allowedOptions.indexOf(key) == -1) {
|
||||
throw new Error("Invalid option " + key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -329,7 +329,7 @@ PerformanceFront.prototype = {
|
|||
return 0;
|
||||
}
|
||||
yield this._request("memory", "attach");
|
||||
let memoryStartTime = yield this._request("memory", "startRecordingAllocations");
|
||||
let memoryStartTime = yield this._request("memory", "startRecordingAllocations", options);
|
||||
yield this._pullAllocationSites();
|
||||
return memoryStartTime;
|
||||
}),
|
||||
|
|
|
@ -182,7 +182,9 @@ let PerformanceController = {
|
|||
// ToolbarView, so that they may be accessible via the "gear" menu.
|
||||
// Every other pref should be registered here.
|
||||
this._nonBooleanPrefs = new ViewHelpers.Prefs("devtools.performance", {
|
||||
"hidden-markers": ["Json", "timeline.hidden-markers"]
|
||||
"hidden-markers": ["Json", "timeline.hidden-markers"],
|
||||
"memory-sample-probability": ["Float", "memory.sample-probability"],
|
||||
"memory-max-log-length": ["Int", "memory.max-log-length"]
|
||||
});
|
||||
|
||||
this._nonBooleanPrefs.registerObserver();
|
||||
|
@ -262,11 +264,13 @@ let PerformanceController = {
|
|||
let withMemory = this.getOption("enable-memory");
|
||||
let withTicks = this.getOption("enable-framerate");
|
||||
let withAllocations = this.getOption("enable-memory");
|
||||
let probability = this.getPref("memory-sample-probability");
|
||||
let maxLogLength = this.getPref("memory-max-log-length");
|
||||
|
||||
let recording = this._createRecording({ withMemory, withTicks, withAllocations });
|
||||
let recording = this._createRecording({ withMemory, withTicks, withAllocations, probability, maxLogLength });
|
||||
|
||||
this.emit(EVENTS.RECORDING_WILL_START, recording);
|
||||
yield recording.startRecording({ withTicks, withMemory, withAllocations });
|
||||
yield recording.startRecording({ withMemory, withTicks, withAllocations, probability, maxLogLength });
|
||||
this.emit(EVENTS.RECORDING_STARTED, recording);
|
||||
|
||||
this.setCurrentRecording(recording);
|
||||
|
|
|
@ -54,6 +54,7 @@ support-files =
|
|||
[browser_perf-options-enable-memory-01.js]
|
||||
[browser_perf-options-enable-memory-02.js]
|
||||
[browser_perf-options-enable-framerate.js]
|
||||
[browser_perf-options-allocations.js]
|
||||
[browser_perf-overview-render-01.js]
|
||||
[browser_perf-overview-render-02.js]
|
||||
[browser_perf-overview-render-03.js]
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
|
||||
/**
|
||||
* Tests that setting the `devtools.performance.memory.` prefs propagate to the memory actor.
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, $, gFront } = panel.panelWin;
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
|
||||
let originalProbability = Services.prefs.getCharPref("devtools.performance.memory.sample-probability");
|
||||
let originalLogLength = Services.prefs.getIntPref("devtools.performance.memory.max-log-length");
|
||||
|
||||
Services.prefs.setCharPref("devtools.performance.memory.sample-probability", "0.213");
|
||||
Services.prefs.setIntPref("devtools.performance.memory.max-log-length", 777777);
|
||||
|
||||
yield startRecording(panel);
|
||||
|
||||
let { probability, maxLogLength } = yield gFront._request("memory", "getAllocationsSettings");
|
||||
|
||||
yield stopRecording(panel);
|
||||
|
||||
is(probability, 0.213, "allocations probability option is set on memory actor");
|
||||
is(maxLogLength, 777777, "allocations max log length option is set on memory actor");
|
||||
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, false);
|
||||
Services.prefs.setCharPref("devtools.performance.memory.sample-probability", originalProbability);
|
||||
Services.prefs.setIntPref("devtools.performance.memory.max-log-length", originalLogLength);
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -58,7 +58,8 @@ skip-if = e10s # Layouthelpers test should not run in a content page.
|
|||
[browser_options-view-01.js]
|
||||
[browser_outputparser.js]
|
||||
skip-if = e10s # Test intermittently fails with e10s. Bug 1124162.
|
||||
[browser_prefs.js]
|
||||
[browser_prefs-01.js]
|
||||
[browser_prefs-02.js]
|
||||
[browser_require_basic.js]
|
||||
[browser_spectrum.js]
|
||||
[browser_theme.js]
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that ViewHelpers.Prefs work properly with custom types of Float and Json.
|
||||
|
||||
let {ViewHelpers} = Cu.import("resource:///modules/devtools/ViewHelpers.jsm", {});
|
||||
|
||||
function test() {
|
||||
let originalJson = Services.prefs.getCharPref("devtools.performance.timeline.hidden-markers");
|
||||
let originalFloat = Services.prefs.getCharPref("devtools.performance.memory.sample-probability");
|
||||
|
||||
let Prefs = new ViewHelpers.Prefs("devtools.performance", {
|
||||
"float": ["Float", "memory.sample-probability"],
|
||||
"json": ["Json", "timeline.hidden-markers"]
|
||||
});
|
||||
|
||||
Prefs.registerObserver();
|
||||
|
||||
// Float
|
||||
Services.prefs.setCharPref("devtools.performance.timeline.hidden-markers", "{\"a\":1}");
|
||||
is(Prefs.json.a, 1, "The JSON pref value is correctly casted on get.");
|
||||
|
||||
Prefs.json = { b: 2 };
|
||||
is(Prefs.json.a, undefined, "The JSON pref value is correctly casted on set (1).");
|
||||
is(Prefs.json.b, 2, "The JSON pref value is correctly casted on set (2).");
|
||||
|
||||
// Float
|
||||
Services.prefs.setCharPref("devtools.performance.memory.sample-probability", "3.14");
|
||||
is(Prefs.float, 3.14, "The float pref value is correctly casted on get.");
|
||||
|
||||
Prefs.float = 6.28;
|
||||
is(Prefs.float, 6.28, "The float pref value is correctly casted on set.");
|
||||
|
||||
Prefs.unregisterObserver();
|
||||
|
||||
Services.prefs.setCharPref("devtools.performance.timeline.hidden-markers", originalJson);
|
||||
Services.prefs.setCharPref("devtools.performance.memory.sample-probability", originalFloat);
|
||||
finish();
|
||||
}
|
|
@ -187,6 +187,7 @@ MarkerDetails.prototype = {
|
|||
|
||||
if (displayName) {
|
||||
let functionLabel = this._document.createElement("label");
|
||||
functionLabel.className = "devtools-monospace";
|
||||
functionLabel.setAttribute("value", displayName);
|
||||
hbox.appendChild(functionLabel);
|
||||
}
|
||||
|
|
|
@ -390,7 +390,8 @@ ViewHelpers.L10N.prototype = {
|
|||
* let prefs = new ViewHelpers.Prefs("root.path.to.branch", {
|
||||
* myIntPref: ["Int", "leaf.path.to.my-int-pref"],
|
||||
* myCharPref: ["Char", "leaf.path.to.my-char-pref"],
|
||||
* myJsonPref: ["Json", "leaf.path.to.my-json-pref"]
|
||||
* myJsonPref: ["Json", "leaf.path.to.my-json-pref"],
|
||||
* myFloatPref: ["Float", "leaf.path.to.my-float-pref"]
|
||||
* ...
|
||||
* });
|
||||
*
|
||||
|
@ -477,8 +478,8 @@ ViewHelpers.Prefs.prototype = {
|
|||
|
||||
/**
|
||||
* Maps a property name to a pref, defining lazy getters and setters.
|
||||
* Supported types are "Bool", "Char", "Int" and "Json" (which is basically
|
||||
* just sugar for "Char" using the standard JSON serializer).
|
||||
* Supported types are "Bool", "Char", "Int", "Float" (sugar around "Char" type and casting),
|
||||
* and "Json" (which is basically just sugar for "Char" using the standard JSON serializer).
|
||||
*
|
||||
* @param string aAccessorName
|
||||
* @param string aType
|
||||
|
@ -494,6 +495,10 @@ ViewHelpers.Prefs.prototype = {
|
|||
this._map(aAccessorName, "Char", aPrefsRoot, aPrefName, { in: JSON.parse, out: JSON.stringify });
|
||||
return;
|
||||
}
|
||||
if (aType == "Float") {
|
||||
this._map(aAccessorName, "Char", aPrefsRoot, aPrefName, { in: Number.parseFloat, out: (n) => n + ""});
|
||||
return;
|
||||
}
|
||||
|
||||
Object.defineProperty(this, aAccessorName, {
|
||||
get: () => aSerializer.in(this._get(aType, aPrefsRoot, aPrefName)),
|
||||
|
|
|
@ -28,3 +28,6 @@ webide.jar:
|
|||
content/wifi-auth.xhtml (wifi-auth.xhtml)
|
||||
content/logs.xhtml (logs.xhtml)
|
||||
content/logs.js (logs.js)
|
||||
content/project-listing.xhtml (project-listing.xhtml)
|
||||
content/project-listing.js (project-listing.js)
|
||||
content/project-panel.js (project-panel.js)
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/* 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/. */
|
||||
|
||||
const Cu = Components.utils;
|
||||
const {require} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
const {AppManager} = require("devtools/webide/app-manager");
|
||||
const ProjectList = require("devtools/webide/project-list");
|
||||
|
||||
let projectList = new ProjectList(window, window.parent);
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
AppManager.on("app-manager-update", onAppManagerUpdate);
|
||||
document.getElementById("new-app").onclick = CreateNewApp;
|
||||
document.getElementById("hosted-app").onclick = ImportHostedApp;
|
||||
document.getElementById("packaged-app").onclick = ImportPackagedApp;
|
||||
projectList.update();
|
||||
}, true);
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
projectList = null;
|
||||
AppManager.off("app-manager-update", onAppManagerUpdate);
|
||||
});
|
||||
|
||||
function onAppManagerUpdate(event, what) {
|
||||
switch (what) {
|
||||
case "list-tabs-response":
|
||||
case "runtime-apps-found":
|
||||
case "project-validated":
|
||||
case "project-removed":
|
||||
case "project":
|
||||
projectList.update();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function CreateNewApp() {
|
||||
projectList.newApp();
|
||||
}
|
||||
|
||||
function ImportHostedApp() {
|
||||
projectList.importHostedApp();
|
||||
}
|
||||
|
||||
function ImportPackagedApp() {
|
||||
projectList.importPackagedApp();
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % webideDTD SYSTEM "chrome://browser/locale/devtools/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/project-listing.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://webide/content/project-listing.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="project-panel">
|
||||
<div id="project-panel-box">
|
||||
<button class="panel-item project-panel-item-newapp" id="new-app">&projectMenu_newApp_label;</button>
|
||||
<button class="panel-item project-panel-item-openpackaged" id="packaged-app">&projectMenu_importPackagedApp_label;</button>
|
||||
<button class="panel-item project-panel-item-openhosted" id="hosted-app">&projectMenu_importHostedApp_label;</button>
|
||||
<label class="panel-header">&projectPanel_myProjects;</label>
|
||||
<div id="project-panel-projects"></div>
|
||||
<label class="panel-header" id="panel-header-runtimeapps" hidden="true">&projectPanel_runtimeApps;</label>
|
||||
<div id="project-panel-runtimeapps"/>
|
||||
<label class="panel-header" id="panel-header-tabs" hidden="true">&projectPanel_tabs;</label>
|
||||
<div id="project-panel-tabs"/>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,39 @@
|
|||
/* 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/. */
|
||||
|
||||
let ProjectPanel = {
|
||||
// TODO: Expand function to save toggle state.
|
||||
toggle: function(sidebarsEnabled, triggerPopup) {
|
||||
let deferred = promise.defer();
|
||||
let doc = document;
|
||||
|
||||
if (sidebarsEnabled) {
|
||||
doc.querySelector("#project-listing-panel").setAttribute("sidebar-displayed", true);
|
||||
doc.querySelector("#project-listing-splitter").setAttribute("sidebar-displayed", true);
|
||||
deferred.resolve();
|
||||
} else if (triggerPopup) {
|
||||
let panelNode = doc.querySelector("#project-panel");
|
||||
let panelVboxNode = doc.querySelector("#project-panel > #project-panel-box");
|
||||
let anchorNode = doc.querySelector("#project-panel-button > .panel-button-anchor");
|
||||
|
||||
window.setTimeout(() => {
|
||||
// Open the popup only when the projects are added.
|
||||
// Not doing it in the next tick can cause mis-calculations
|
||||
// of the size of the panel.
|
||||
function onPopupShown() {
|
||||
panelNode.removeEventListener("popupshown", onPopupShown);
|
||||
deferred.resolve();
|
||||
}
|
||||
|
||||
panelNode.addEventListener("popupshown", onPopupShown);
|
||||
panelNode.openPopup(anchorNode);
|
||||
panelVboxNode.scrollTop = 0;
|
||||
}, 0);
|
||||
} else {
|
||||
deferred.resolve();
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
};
|
|
@ -24,6 +24,7 @@ const utils = require("devtools/webide/utils");
|
|||
const Telemetry = require("devtools/shared/telemetry");
|
||||
const {RuntimeScanners, WiFiScanner} = require("devtools/webide/runtimes");
|
||||
const {showDoorhanger} = require("devtools/shared/doorhanger");
|
||||
const ProjectList = require("devtools/webide/project-list");
|
||||
|
||||
const Strings = Services.strings.createBundle("chrome://browser/locale/devtools/webide.properties");
|
||||
|
||||
|
@ -51,6 +52,8 @@ window.addEventListener("unload", function onUnload() {
|
|||
UI.uninit();
|
||||
});
|
||||
|
||||
let projectList;
|
||||
|
||||
let UI = {
|
||||
init: function() {
|
||||
this._telemetry = new Telemetry();
|
||||
|
@ -64,6 +67,9 @@ let UI = {
|
|||
this.appManagerUpdate = this.appManagerUpdate.bind(this);
|
||||
AppManager.on("app-manager-update", this.appManagerUpdate);
|
||||
|
||||
projectList = new ProjectList(window, window);
|
||||
ProjectPanel.toggle(projectList.sidebarsEnabled);
|
||||
|
||||
this.updateCommands();
|
||||
this.updateRuntimeList();
|
||||
|
||||
|
@ -72,6 +78,7 @@ let UI = {
|
|||
|
||||
AppProjects.load().then(() => {
|
||||
this.autoSelectProject();
|
||||
projectList.update();
|
||||
}, e => {
|
||||
console.error(e);
|
||||
this.reportError("error_appProjectsLoadFailed");
|
||||
|
@ -115,6 +122,7 @@ let UI = {
|
|||
window.removeEventListener("focus", this.onfocus, true);
|
||||
AppManager.off("app-manager-update", this.appManagerUpdate);
|
||||
AppManager.uninit();
|
||||
projectList = null;
|
||||
window.removeEventListener("message", this.onMessage);
|
||||
this.updateConnectionTelemetry();
|
||||
this._telemetry.toolClosed("webide");
|
||||
|
@ -171,6 +179,7 @@ let UI = {
|
|||
UI.openProject();
|
||||
UI.autoStartProject();
|
||||
UI.saveLastSelectedProject();
|
||||
projectList.update();
|
||||
});
|
||||
return;
|
||||
case "project-is-not-running":
|
||||
|
@ -190,12 +199,17 @@ let UI = {
|
|||
this.updateCommands();
|
||||
this.updateProjectButton();
|
||||
this.updateProjectEditorHeader();
|
||||
projectList.update();
|
||||
break;
|
||||
case "project-removed":
|
||||
projectList.update();
|
||||
break;
|
||||
case "install-progress":
|
||||
this.updateProgress(Math.round(100 * details.bytesSent / details.totalBytes));
|
||||
break;
|
||||
case "runtime-apps-found":
|
||||
this.autoSelectProject();
|
||||
projectList.update();
|
||||
break;
|
||||
case "pre-package":
|
||||
this.prePackageLog(details);
|
||||
|
@ -225,6 +239,7 @@ let UI = {
|
|||
}
|
||||
},
|
||||
|
||||
// TODO: remove hidePanel when project layout is complete - Bug 1079347
|
||||
hidePanels: function() {
|
||||
let panels = document.querySelectorAll("panel");
|
||||
for (let p of panels) {
|
||||
|
@ -527,6 +542,7 @@ let UI = {
|
|||
|
||||
let project = AppManager.selectedProject;
|
||||
|
||||
if (!projectList.sidebarsEnabled) {
|
||||
if (!project) {
|
||||
buttonNode.classList.add("no-project");
|
||||
labelNode.setAttribute("value", Strings.GetStringFromName("projectButton_label"));
|
||||
|
@ -536,6 +552,7 @@ let UI = {
|
|||
labelNode.setAttribute("value", project.name);
|
||||
imageNode.setAttribute("src", project.icon);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// ProjectEditor & details screen
|
||||
|
@ -1039,217 +1056,19 @@ let Cmds = {
|
|||
* }
|
||||
*/
|
||||
newApp: function(testOptions) {
|
||||
return UI.busyUntil(Task.spawn(function* () {
|
||||
|
||||
// Open newapp.xul, which will feed ret.location
|
||||
let ret = {location: null, testOptions: testOptions};
|
||||
window.openDialog("chrome://webide/content/newapp.xul", "newapp", "chrome,modal", ret);
|
||||
if (!ret.location)
|
||||
return;
|
||||
|
||||
// Retrieve added project
|
||||
let project = AppProjects.get(ret.location);
|
||||
|
||||
// Select project
|
||||
AppManager.selectedProject = project;
|
||||
|
||||
}), "creating new app");
|
||||
projectList.newApp(testOptions);
|
||||
},
|
||||
|
||||
importPackagedApp: function(location) {
|
||||
return UI.busyUntil(Task.spawn(function* () {
|
||||
|
||||
let directory = utils.getPackagedDirectory(window, location);
|
||||
|
||||
if (!directory) {
|
||||
// User cancelled directory selection
|
||||
return;
|
||||
}
|
||||
|
||||
yield UI.importAndSelectApp(directory);
|
||||
}), "importing packaged app");
|
||||
projectList.importPackagedApp(location);
|
||||
},
|
||||
|
||||
importHostedApp: function(location) {
|
||||
return UI.busyUntil(Task.spawn(function* () {
|
||||
|
||||
let url = utils.getHostedURL(window, location);
|
||||
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
|
||||
yield UI.importAndSelectApp(url);
|
||||
}), "importing hosted app");
|
||||
projectList.importHostedApp(location);
|
||||
},
|
||||
|
||||
showProjectPanel: function() {
|
||||
let deferred = promise.defer();
|
||||
|
||||
let panelNode = document.querySelector("#project-panel");
|
||||
let panelVboxNode = document.querySelector("#project-panel > vbox");
|
||||
let anchorNode = document.querySelector("#project-panel-button > .panel-button-anchor");
|
||||
let projectsNode = document.querySelector("#project-panel-projects");
|
||||
|
||||
while (projectsNode.hasChildNodes()) {
|
||||
projectsNode.firstChild.remove();
|
||||
}
|
||||
|
||||
AppProjects.load().then(() => {
|
||||
let projects = AppProjects.store.object.projects;
|
||||
for (let i = 0; i < projects.length; i++) {
|
||||
let project = projects[i];
|
||||
let panelItemNode = document.createElement("toolbarbutton");
|
||||
panelItemNode.className = "panel-item";
|
||||
projectsNode.appendChild(panelItemNode);
|
||||
panelItemNode.setAttribute("label", project.name || AppManager.DEFAULT_PROJECT_NAME);
|
||||
panelItemNode.setAttribute("image", project.icon || AppManager.DEFAULT_PROJECT_ICON);
|
||||
if (!project.name || !project.icon) {
|
||||
// The result of the validation process (storing names, icons, …) is not stored in
|
||||
// the IndexedDB database when App Manager v1 is used.
|
||||
// We need to run the validation again and update the name and icon of the app.
|
||||
AppManager.validateAndUpdateProject(project).then(() => {
|
||||
panelItemNode.setAttribute("label", project.name);
|
||||
panelItemNode.setAttribute("image", project.icon);
|
||||
});
|
||||
}
|
||||
panelItemNode.addEventListener("click", () => {
|
||||
UI.hidePanels();
|
||||
AppManager.selectedProject = project;
|
||||
}, true);
|
||||
}
|
||||
|
||||
window.setTimeout(() => {
|
||||
// Open the popup only when the projects are added.
|
||||
// Not doing it in the next tick can cause mis-calculations
|
||||
// of the size of the panel.
|
||||
function onPopupShown() {
|
||||
panelNode.removeEventListener("popupshown", onPopupShown);
|
||||
deferred.resolve();
|
||||
}
|
||||
panelNode.addEventListener("popupshown", onPopupShown);
|
||||
panelNode.openPopup(anchorNode);
|
||||
panelVboxNode.scrollTop = 0;
|
||||
}, 0);
|
||||
}, deferred.reject);
|
||||
|
||||
|
||||
let runtimeappsHeaderNode = document.querySelector("#panel-header-runtimeapps");
|
||||
let sortedApps = [];
|
||||
for (let [manifestURL, app] of AppManager.apps) {
|
||||
sortedApps.push(app);
|
||||
}
|
||||
sortedApps = sortedApps.sort((a, b) => {
|
||||
return a.manifest.name > b.manifest.name;
|
||||
});
|
||||
let mainProcess = AppManager.isMainProcessDebuggable();
|
||||
if (AppManager.connected && (sortedApps.length > 0 || mainProcess)) {
|
||||
runtimeappsHeaderNode.removeAttribute("hidden");
|
||||
} else {
|
||||
runtimeappsHeaderNode.setAttribute("hidden", "true");
|
||||
}
|
||||
|
||||
let runtimeAppsNode = document.querySelector("#project-panel-runtimeapps");
|
||||
while (runtimeAppsNode.hasChildNodes()) {
|
||||
runtimeAppsNode.firstChild.remove();
|
||||
}
|
||||
|
||||
if (mainProcess) {
|
||||
let panelItemNode = document.createElement("toolbarbutton");
|
||||
panelItemNode.className = "panel-item";
|
||||
panelItemNode.setAttribute("label", Strings.GetStringFromName("mainProcess_label"));
|
||||
panelItemNode.setAttribute("image", AppManager.DEFAULT_PROJECT_ICON);
|
||||
runtimeAppsNode.appendChild(panelItemNode);
|
||||
panelItemNode.addEventListener("click", () => {
|
||||
UI.hidePanels();
|
||||
AppManager.selectedProject = {
|
||||
type: "mainProcess",
|
||||
name: Strings.GetStringFromName("mainProcess_label"),
|
||||
icon: AppManager.DEFAULT_PROJECT_ICON
|
||||
};
|
||||
}, true);
|
||||
}
|
||||
|
||||
for (let i = 0; i < sortedApps.length; i++) {
|
||||
let app = sortedApps[i];
|
||||
let panelItemNode = document.createElement("toolbarbutton");
|
||||
panelItemNode.className = "panel-item";
|
||||
panelItemNode.setAttribute("label", app.manifest.name);
|
||||
panelItemNode.setAttribute("image", app.iconURL);
|
||||
runtimeAppsNode.appendChild(panelItemNode);
|
||||
panelItemNode.addEventListener("click", () => {
|
||||
UI.hidePanels();
|
||||
AppManager.selectedProject = {
|
||||
type: "runtimeApp",
|
||||
app: app.manifest,
|
||||
icon: app.iconURL,
|
||||
name: app.manifest.name
|
||||
};
|
||||
}, true);
|
||||
}
|
||||
|
||||
// Build the tab list right now, so it's fast...
|
||||
this._buildProjectPanelTabs();
|
||||
|
||||
// But re-list them and rebuild, in case any tabs navigated since the last
|
||||
// time they were listed.
|
||||
if (AppManager.connected) {
|
||||
AppManager.listTabs().then(() => {
|
||||
this._buildProjectPanelTabs();
|
||||
}).catch(console.error);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
_buildProjectPanelTabs: function() {
|
||||
let tabs = AppManager.tabStore.tabs;
|
||||
let tabsHeaderNode = document.querySelector("#panel-header-tabs");
|
||||
if (AppManager.connected && tabs.length > 0) {
|
||||
tabsHeaderNode.removeAttribute("hidden");
|
||||
} else {
|
||||
tabsHeaderNode.setAttribute("hidden", "true");
|
||||
}
|
||||
|
||||
let tabsNode = document.querySelector("#project-panel-tabs");
|
||||
while (tabsNode.hasChildNodes()) {
|
||||
tabsNode.firstChild.remove();
|
||||
}
|
||||
|
||||
for (let i = 0; i < tabs.length; i++) {
|
||||
let tab = tabs[i];
|
||||
let url;
|
||||
try {
|
||||
url = new URL(tab.url);
|
||||
} catch (e) {
|
||||
// Don't try to handle invalid URLs, especially from Valence.
|
||||
continue;
|
||||
}
|
||||
// Wanted to use nsIFaviconService here, but it only works for visited
|
||||
// tabs, so that's no help for any remote tabs. Maybe some favicon wizard
|
||||
// knows how to get high-res favicons easily, or we could offer actor
|
||||
// support for this (bug 1061654).
|
||||
tab.favicon = url.origin + "/favicon.ico";
|
||||
tab.name = tab.title || Strings.GetStringFromName("project_tab_loading");
|
||||
if (url.protocol.startsWith("http")) {
|
||||
tab.name = url.hostname + ": " + tab.name;
|
||||
}
|
||||
let panelItemNode = document.createElement("toolbarbutton");
|
||||
panelItemNode.className = "panel-item";
|
||||
panelItemNode.setAttribute("label", tab.name);
|
||||
panelItemNode.setAttribute("image", tab.favicon);
|
||||
tabsNode.appendChild(panelItemNode);
|
||||
panelItemNode.addEventListener("click", () => {
|
||||
UI.hidePanels();
|
||||
AppManager.selectedProject = {
|
||||
type: "tab",
|
||||
app: tab,
|
||||
icon: tab.favicon,
|
||||
location: tab.url,
|
||||
name: tab.name
|
||||
};
|
||||
}, true);
|
||||
}
|
||||
ProjectPanel.toggle(projectList.sidebarsEnabled, true);
|
||||
},
|
||||
|
||||
showRuntimePanel: function() {
|
||||
|
@ -1346,7 +1165,7 @@ let Cmds = {
|
|||
},
|
||||
|
||||
removeProject: function() {
|
||||
return AppManager.removeSelectedProject();
|
||||
AppManager.removeSelectedProject();
|
||||
},
|
||||
|
||||
toggleEditors: function() {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/global.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/common.css"?>
|
||||
<?xml-stylesheet href="chrome://webide/skin/webide.css"?>
|
||||
|
||||
<window id="webide" onclose="return UI.canCloseProject();"
|
||||
|
@ -26,6 +27,7 @@
|
|||
persist="screenX screenY width height sizemode">
|
||||
|
||||
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"></script>
|
||||
<script type="application/javascript" src="project-panel.js"></script>
|
||||
<script type="application/javascript" src="webide.js"></script>
|
||||
|
||||
<commandset id="mainCommandSet">
|
||||
|
@ -150,7 +152,7 @@
|
|||
|
||||
<!-- App panel -->
|
||||
<panel id="project-panel" type="arrow" position="bottomcenter topleft" consumeoutsideclicks="true" animate="false">
|
||||
<vbox flex="1">
|
||||
<vbox flex="1" id="project-panel-box">
|
||||
<toolbarbutton class="panel-item project-panel-item-newapp" command="cmd_newApp"/>
|
||||
<toolbarbutton class="panel-item project-panel-item-openpackaged" command="cmd_importPackagedApp"/>
|
||||
<toolbarbutton class="panel-item project-panel-item-openhosted" command="cmd_importHostedApp"/>
|
||||
|
@ -191,6 +193,13 @@
|
|||
</popupset>
|
||||
|
||||
<notificationbox flex="1" id="notificationbox">
|
||||
<hbox flex="1">
|
||||
<vbox id="project-listing-panel" class="project-listing" flex="1">
|
||||
<div id="project-listing-wrapper">
|
||||
<iframe id="project-listing-panel-details" flex="1" src="project-listing.xhtml"/>
|
||||
</div>
|
||||
</vbox>
|
||||
<splitter class="devtools-side-splitter" id="project-listing-splitter"/>
|
||||
<deck flex="1" id="deck" selectedIndex="-1">
|
||||
<iframe id="deck-panel-details" flex="1" src="details.xhtml"/>
|
||||
<iframe id="deck-panel-projecteditor" flex="1"/>
|
||||
|
@ -203,6 +212,7 @@
|
|||
<iframe id="deck-panel-devicesettings" flex="1" lazysrc="devicesettings.xhtml"/>
|
||||
<iframe id="deck-panel-logs" flex="1" src="logs.xhtml"/>
|
||||
</deck>
|
||||
</hbox>
|
||||
<splitter hidden="true" class="devtools-horizontal-splitter" orient="vertical"/>
|
||||
<!-- toolbox iframe will be inserted here -->
|
||||
</notificationbox>
|
||||
|
|
|
@ -327,15 +327,17 @@ let AppManager = exports.AppManager = {
|
|||
return this._selectedProject;
|
||||
},
|
||||
|
||||
removeSelectedProject: function() {
|
||||
removeSelectedProject: Task.async(function*() {
|
||||
let location = this.selectedProject.location;
|
||||
AppManager.selectedProject = null;
|
||||
// If the user cancels the removeProject operation, don't remove the project
|
||||
if (AppManager.selectedProject != null) {
|
||||
return;
|
||||
}
|
||||
return AppProjects.remove(location);
|
||||
},
|
||||
|
||||
yield AppProjects.remove(location);
|
||||
AppManager.update("project-removed");
|
||||
}),
|
||||
|
||||
packageProject: Task.async(function*(project) {
|
||||
if (!project) {
|
||||
|
|
|
@ -0,0 +1,299 @@
|
|||
/* 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/. */
|
||||
|
||||
const {Cu} = require("chrome");
|
||||
|
||||
const {Services} = Cu.import("resource://gre/modules/Services.jsm");
|
||||
const {AppProjects} = require("devtools/app-manager/app-projects");
|
||||
const {AppManager} = require("devtools/webide/app-manager");
|
||||
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
const EventEmitter = require("devtools/toolkit/event-emitter");
|
||||
const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
const utils = require("devtools/webide/utils");
|
||||
|
||||
const Strings = Services.strings.createBundle("chrome://browser/locale/devtools/webide.properties");
|
||||
|
||||
let ProjectList;
|
||||
|
||||
module.exports = ProjectList = function(window, parentWindow) {
|
||||
EventEmitter.decorate(this);
|
||||
this._doc = window.document;
|
||||
this._UI = parentWindow.UI;
|
||||
this._parentWindow = parentWindow;
|
||||
this._panelNodeEl = "toolbarbutton";
|
||||
this._sidebarsEnabled = Services.prefs.getBoolPref("devtools.webide.sidebars");
|
||||
|
||||
if (this._sidebarsEnabled) {
|
||||
this._panelNodeEl = "div";
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
ProjectList.prototype = {
|
||||
get doc() {
|
||||
return this._doc;
|
||||
},
|
||||
|
||||
get sidebarsEnabled() {
|
||||
return this._sidebarsEnabled;
|
||||
},
|
||||
|
||||
/**
|
||||
* testOptions: { chrome mochitest support
|
||||
* folder: nsIFile, where to store the app
|
||||
* index: Number, index of the app in the template list
|
||||
* name: String name of the app
|
||||
* }
|
||||
*/
|
||||
newApp: function(testOptions) {
|
||||
let parentWindow = this._parentWindow;
|
||||
return this._UI.busyUntil(Task.spawn(function*() {
|
||||
// Open newapp.xul, which will feed ret.location
|
||||
let ret = {location: null, testOptions: testOptions};
|
||||
parentWindow.openDialog("chrome://webide/content/newapp.xul", "newapp", "chrome,modal", ret);
|
||||
if (!ret.location)
|
||||
return;
|
||||
|
||||
// Retrieve added project
|
||||
let project = AppProjects.get(ret.location);
|
||||
|
||||
// Select project
|
||||
AppManager.selectedProject = project;
|
||||
}), "creating new app");
|
||||
},
|
||||
|
||||
importPackagedApp: function(location) {
|
||||
let parentWindow = this._parentWindow;
|
||||
let UI = this._UI;
|
||||
return UI.busyUntil(Task.spawn(function*() {
|
||||
let directory = utils.getPackagedDirectory(parentWindow, location);
|
||||
|
||||
if (!directory) {
|
||||
// User cancelled directory selection
|
||||
return;
|
||||
}
|
||||
|
||||
yield UI.importAndSelectApp(directory);
|
||||
}), "importing packaged app");
|
||||
},
|
||||
|
||||
importHostedApp: function(location) {
|
||||
let parentWindow = this._parentWindow;
|
||||
let UI = this._UI;
|
||||
return UI.busyUntil(Task.spawn(function*() {
|
||||
let url = utils.getHostedURL(parentWindow, location);
|
||||
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
|
||||
yield UI.importAndSelectApp(url);
|
||||
}), "importing hosted app");
|
||||
},
|
||||
|
||||
/**
|
||||
* opts: {
|
||||
* panel: Object, currenl project panel node
|
||||
* name: String, name of the project
|
||||
* icon: String path of the project icon
|
||||
* }
|
||||
*/
|
||||
_renderProjectItem: function(opts) {
|
||||
if (this._sidebarsEnabled) {
|
||||
let span = this._doc.createElement("span");
|
||||
span.textContent = opts.name;
|
||||
let icon = this._doc.createElement("img");
|
||||
icon.className = "project-image";
|
||||
icon.setAttribute("src", opts.icon);
|
||||
opts.panel.appendChild(icon);
|
||||
opts.panel.appendChild(span);
|
||||
} else {
|
||||
opts.panel.setAttribute("label", opts.name);
|
||||
opts.panel.setAttribute("image", opts.icon);
|
||||
}
|
||||
},
|
||||
|
||||
_buildProjectPanelTabs: function() {
|
||||
let tabs = AppManager.tabStore.tabs;
|
||||
let tabsHeaderNode = this._doc.querySelector("#panel-header-tabs");
|
||||
|
||||
if (AppManager.connected && tabs.length > 0) {
|
||||
tabsHeaderNode.removeAttribute("hidden");
|
||||
} else {
|
||||
tabsHeaderNode.setAttribute("hidden", "true");
|
||||
}
|
||||
|
||||
let tabsNode = this._doc.querySelector("#project-panel-tabs");
|
||||
|
||||
while (tabsNode.hasChildNodes()) {
|
||||
tabsNode.firstChild.remove();
|
||||
}
|
||||
|
||||
for (let i = 0; i < tabs.length; i++) {
|
||||
let tab = tabs[i];
|
||||
let URL = this._parentWindow.URL;
|
||||
let url;
|
||||
try {
|
||||
url = new URL(tab.url);
|
||||
} catch (e) {
|
||||
// Don't try to handle invalid URLs, especially from Valence.
|
||||
continue;
|
||||
}
|
||||
// Wanted to use nsIFaviconService here, but it only works for visited
|
||||
// tabs, so that's no help for any remote tabs. Maybe some favicon wizard
|
||||
// knows how to get high-res favicons easily, or we could offer actor
|
||||
// support for this (bug 1061654).
|
||||
tab.favicon = url.origin + "/favicon.ico";
|
||||
tab.name = tab.title || Strings.GetStringFromName("project_tab_loading");
|
||||
if (url.protocol.startsWith("http")) {
|
||||
tab.name = url.hostname + ": " + tab.name;
|
||||
}
|
||||
let panelItemNode = this._doc.createElement(this._panelNodeEl);
|
||||
panelItemNode.className = "panel-item";
|
||||
tabsNode.appendChild(panelItemNode);
|
||||
this._renderProjectItem({
|
||||
panel: panelItemNode,
|
||||
name: tab.name,
|
||||
icon: tab.favicon
|
||||
});
|
||||
panelItemNode.addEventListener("click", () => {
|
||||
if (!this._sidebarsEnabled) {
|
||||
this._UI.hidePanels();
|
||||
}
|
||||
AppManager.selectedProject = {
|
||||
type: "tab",
|
||||
app: tab,
|
||||
icon: tab.favicon,
|
||||
location: tab.url,
|
||||
name: tab.name
|
||||
};
|
||||
}, true);
|
||||
}
|
||||
},
|
||||
|
||||
update: function() {
|
||||
let deferred = promise.defer();
|
||||
let doc = this._doc;
|
||||
let panelVboxNode = doc.querySelector("#project-panel > #project-panel-box");
|
||||
let anchorNode = doc.querySelector("#project-panel-button > .panel-button-anchor");
|
||||
let projectsNode = doc.querySelector("#project-panel-projects");
|
||||
|
||||
while (projectsNode.hasChildNodes()) {
|
||||
projectsNode.firstChild.remove();
|
||||
}
|
||||
|
||||
AppProjects.load().then(() => {
|
||||
let projects = AppProjects.store.object.projects;
|
||||
for (let i = 0; i < projects.length; i++) {
|
||||
let project = projects[i];
|
||||
let panelItemNode = doc.createElement(this._panelNodeEl);
|
||||
panelItemNode.className = "panel-item";
|
||||
projectsNode.appendChild(panelItemNode);
|
||||
this._renderProjectItem({
|
||||
panel: panelItemNode,
|
||||
name: project.name || AppManager.DEFAULT_PROJECT_NAME,
|
||||
icon: project.icon|| AppManager.DEFAULT_PROJECT_ICON
|
||||
});
|
||||
if (!project.name || !project.icon) {
|
||||
// The result of the validation process (storing names, icons, …) is not stored in
|
||||
// the IndexedDB database when App Manager v1 is used.
|
||||
// We need to run the validation again and update the name and icon of the app.
|
||||
AppManager.validateAndUpdateProject(project).then(() => {
|
||||
this._renderProjectItem({
|
||||
panel: panelItemNode,
|
||||
name: project.name,
|
||||
icon: project.icon
|
||||
});
|
||||
});
|
||||
}
|
||||
panelItemNode.addEventListener("click", () => {
|
||||
if (!this._sidebarsEnabled) {
|
||||
this._UI.hidePanels();
|
||||
}
|
||||
AppManager.selectedProject = project;
|
||||
}, true);
|
||||
}
|
||||
|
||||
deferred.resolve();
|
||||
}, deferred.reject);
|
||||
|
||||
let runtimeappsHeaderNode = doc.querySelector("#panel-header-runtimeapps");
|
||||
let sortedApps = [];
|
||||
for (let [manifestURL, app] of AppManager.apps) {
|
||||
sortedApps.push(app);
|
||||
}
|
||||
sortedApps = sortedApps.sort((a, b) => {
|
||||
return a.manifest.name > b.manifest.name;
|
||||
});
|
||||
let mainProcess = AppManager.isMainProcessDebuggable();
|
||||
if (AppManager.connected && (sortedApps.length > 0 || mainProcess)) {
|
||||
runtimeappsHeaderNode.removeAttribute("hidden");
|
||||
} else {
|
||||
runtimeappsHeaderNode.setAttribute("hidden", "true");
|
||||
}
|
||||
|
||||
let runtimeAppsNode = doc.querySelector("#project-panel-runtimeapps");
|
||||
while (runtimeAppsNode.hasChildNodes()) {
|
||||
runtimeAppsNode.firstChild.remove();
|
||||
}
|
||||
|
||||
if (mainProcess) {
|
||||
let panelItemNode = doc.createElement(this._panelNodeEl);
|
||||
panelItemNode.className = "panel-item";
|
||||
this._renderProjectItem({
|
||||
panel: panelItemNode,
|
||||
name: Strings.GetStringFromName("mainProcess_label"),
|
||||
icon: AppManager.DEFAULT_PROJECT_ICON
|
||||
});
|
||||
runtimeAppsNode.appendChild(panelItemNode);
|
||||
panelItemNode.addEventListener("click", () => {
|
||||
if (!this._sidebarsEnabled) {
|
||||
this._UI.hidePanels();
|
||||
}
|
||||
AppManager.selectedProject = {
|
||||
type: "mainProcess",
|
||||
name: Strings.GetStringFromName("mainProcess_label"),
|
||||
icon: AppManager.DEFAULT_PROJECT_ICON
|
||||
};
|
||||
}, true);
|
||||
}
|
||||
|
||||
for (let i = 0; i < sortedApps.length; i++) {
|
||||
let app = sortedApps[i];
|
||||
let panelItemNode = doc.createElement(this._panelNodeEl);
|
||||
panelItemNode.className = "panel-item";
|
||||
this._renderProjectItem({
|
||||
panel: panelItemNode,
|
||||
name: app.manifest.name,
|
||||
icon: app.iconURL
|
||||
});
|
||||
runtimeAppsNode.appendChild(panelItemNode);
|
||||
panelItemNode.addEventListener("click", () => {
|
||||
if (!this._sidebarsEnabled) {
|
||||
this._UI.hidePanels();
|
||||
}
|
||||
AppManager.selectedProject = {
|
||||
type: "runtimeApp",
|
||||
app: app.manifest,
|
||||
icon: app.iconURL,
|
||||
name: app.manifest.name
|
||||
};
|
||||
}, true);
|
||||
}
|
||||
|
||||
// Build the tab list right now, so it's fast...
|
||||
this._buildProjectPanelTabs();
|
||||
|
||||
// But re-list them and rebuild, in case any tabs navigated since the last
|
||||
// time they were listed.
|
||||
if (AppManager.connected) {
|
||||
AppManager.listTabs().then(() => {
|
||||
this._buildProjectPanelTabs();
|
||||
}).catch(console.error);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
};
|
|
@ -10,14 +10,21 @@ DIRS += [
|
|||
'themes',
|
||||
]
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
'test/browser.ini',
|
||||
'test/sidebars/browser.ini'
|
||||
]
|
||||
MOCHITEST_CHROME_MANIFESTS += [
|
||||
'test/chrome.ini',
|
||||
'test/sidebars/chrome.ini'
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES.devtools.webide += [
|
||||
'modules/addons.js',
|
||||
'modules/app-manager.js',
|
||||
'modules/build.js',
|
||||
'modules/config-view.js',
|
||||
'modules/project-list.js',
|
||||
'modules/remote-resources.js',
|
||||
'modules/runtimes.js',
|
||||
'modules/simulator-process.js',
|
||||
|
|
|
@ -50,7 +50,7 @@ function connectToLocal(win) {
|
|||
function selectTabProject(win) {
|
||||
return Task.spawn(function() {
|
||||
yield win.AppManager.listTabs();
|
||||
win.Cmds.showProjectPanel();
|
||||
win.projectList.update();
|
||||
yield nextTick();
|
||||
let tabsNode = win.document.querySelector("#project-panel-tabs");
|
||||
let tabNode = tabsNode.querySelectorAll(".panel-item")[1];
|
||||
|
|
|
@ -36,6 +36,7 @@ SimpleTest.registerCleanupFunction(() => {
|
|||
Services.prefs.clearUserPref("devtools.webide.enableLocalRuntime");
|
||||
Services.prefs.clearUserPref("devtools.webide.autoinstallADBHelper");
|
||||
Services.prefs.clearUserPref("devtools.webide.autoinstallFxdtAdapters");
|
||||
Services.prefs.clearUserPref("devtools.webide.sidebars");
|
||||
});
|
||||
|
||||
function openWebIDE(autoInstallAddons) {
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[DEFAULT]
|
||||
subsuite = devtools
|
||||
support-files =
|
||||
../head.js
|
|
@ -0,0 +1,8 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
../app/index.html
|
||||
../app/manifest.webapp
|
||||
../head.js
|
||||
|
||||
[test_duplicate_import.html]
|
||||
[test_import.html]
|
|
@ -0,0 +1,75 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title></title>
|
||||
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="../head.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.onload = function() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
Task.spawn(function*() {
|
||||
Services.prefs.setBoolPref("devtools.webide.sidebars", true);
|
||||
let win = yield openWebIDE();
|
||||
let winIframe = win.document.querySelector("#project-listing-panel-details").contentWindow;
|
||||
let packagedAppLocation = getTestFilePath("../app");
|
||||
let hostedAppManifest = TEST_BASE + "hosted_app.manifest";
|
||||
|
||||
yield win.AppProjects.load();
|
||||
is(win.AppProjects.store.object.projects.length, 0, "IDB is empty");
|
||||
|
||||
info("to call importPackagedApp(" + packagedAppLocation + ")");
|
||||
yield win.projectList.importPackagedApp(packagedAppLocation);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
yield nextTick();
|
||||
|
||||
info("to call importHostedApp(" + hostedAppManifest + ")");
|
||||
yield win.projectList.importHostedApp(hostedAppManifest);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
yield nextTick();
|
||||
|
||||
info("to call importPackagedApp(" + packagedAppLocation + ") again");
|
||||
yield win.projectList.importPackagedApp(packagedAppLocation);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
|
||||
let project = win.AppManager.selectedProject;
|
||||
is(project.location, packagedAppLocation, "Correctly reselected existing packaged app.");
|
||||
yield nextTick();
|
||||
|
||||
info("to call importHostedApp(" + hostedAppManifest + ") again");
|
||||
yield win.projectList.importHostedApp(hostedAppManifest);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
project = win.AppManager.selectedProject;
|
||||
is(project.location, hostedAppManifest, "Correctly reselected existing hosted app.");
|
||||
yield nextTick();
|
||||
|
||||
let panelNode = winIframe.document.querySelector("#project-panel");
|
||||
let items = panelNode.querySelectorAll(".panel-item");
|
||||
// 3 controls, + 2 projects
|
||||
is(items.length, 5, "5 projects in panel");
|
||||
is(items[3].querySelector("span").textContent, "A name (in app directory)", "Panel text is correct");
|
||||
is(items[4].querySelector("span").textContent, "hosted manifest name property", "Panel text is correct");
|
||||
|
||||
yield closeWebIDE(win);
|
||||
|
||||
yield removeAllProjects();
|
||||
|
||||
SimpleTest.finish();
|
||||
}).then(null, e => {
|
||||
ok(false, "Exception: " + e);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title></title>
|
||||
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="../head.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.onload = function() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
Task.spawn(function*() {
|
||||
Services.prefs.setBoolPref("devtools.webide.sidebars", true);
|
||||
let win = yield openWebIDE();
|
||||
let winIframe = win.document.querySelector("#project-listing-panel-details").contentWindow;
|
||||
let packagedAppLocation = getTestFilePath("../app");
|
||||
|
||||
yield win.AppProjects.load();
|
||||
is(win.AppProjects.store.object.projects.length, 0, "IDB is empty");
|
||||
|
||||
info("to call importPackagedApp(" + packagedAppLocation + ")");
|
||||
ok(!win.UI._busyPromise, "UI is not busy");
|
||||
|
||||
yield win.projectList.importPackagedApp(packagedAppLocation);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
|
||||
let project = win.AppManager.selectedProject;
|
||||
is(project.location, packagedAppLocation, "Location is valid");
|
||||
is(project.name, "A name (in app directory)", "name field has been updated");
|
||||
is(project.manifest.launch_path, "/index.html", "manifest found. launch_path valid.");
|
||||
is(project.manifest.description, "desc", "manifest found. description valid");
|
||||
|
||||
yield nextTick();
|
||||
|
||||
let hostedAppManifest = TEST_BASE + "hosted_app.manifest";
|
||||
yield win.projectList.importHostedApp(hostedAppManifest);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
|
||||
project = win.AppManager.selectedProject;
|
||||
is(project.location, hostedAppManifest, "Location is valid");
|
||||
is(project.name, "hosted manifest name property", "name field has been updated");
|
||||
|
||||
yield nextTick();
|
||||
|
||||
hostedAppManifest = TEST_BASE + "/app";
|
||||
yield win.projectList.importHostedApp(hostedAppManifest);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
|
||||
project = win.AppManager.selectedProject;
|
||||
ok(project.location.endsWith('manifest.webapp'), "The manifest was found and the project was updated");
|
||||
|
||||
let panelNode = winIframe.document.querySelector("#project-panel");
|
||||
let items = panelNode.querySelectorAll(".panel-item");
|
||||
// 3 controls, + 2 projects
|
||||
is(items.length, 6, "6 projects in panel");
|
||||
is(items[3].querySelector("span").textContent, "A name (in app directory)", "Panel text is correct");
|
||||
is(items[4].querySelector("span").textContent, "hosted manifest name property", "Panel text is correct");
|
||||
|
||||
yield closeWebIDE(win);
|
||||
|
||||
yield removeAllProjects();
|
||||
|
||||
SimpleTest.finish();
|
||||
}).then(null, e => {
|
||||
ok(false, "Exception: " + e);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,145 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title></title>
|
||||
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="../head.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.onload = function() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
Services.prefs.setBoolPref("devtools.webide.sidebars", true);
|
||||
|
||||
let win;
|
||||
|
||||
SimpleTest.registerCleanupFunction(() => {
|
||||
Task.spawn(function*() {
|
||||
if (win) {
|
||||
yield closeWebIDE(win);
|
||||
}
|
||||
DebuggerServer.destroy();
|
||||
yield removeAllProjects();
|
||||
});
|
||||
});
|
||||
|
||||
Task.spawn(function*() {
|
||||
function isPlayActive() {
|
||||
return !win.document.querySelector("#cmd_play").hasAttribute("disabled");
|
||||
}
|
||||
|
||||
function isStopActive() {
|
||||
return !win.document.querySelector("#cmd_stop").hasAttribute("disabled");
|
||||
}
|
||||
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
|
||||
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
|
||||
win = yield openWebIDE();
|
||||
let winIframe = win.document.querySelector("#project-listing-panel-details").contentWindow;
|
||||
|
||||
win.AppManager.runtimeList.usb.push({
|
||||
connect: function(connection) {
|
||||
is(connection, win.AppManager.connection, "connection is valid");
|
||||
connection.host = null; // force connectPipe
|
||||
connection.connect();
|
||||
return promise.resolve();
|
||||
},
|
||||
|
||||
get name() {
|
||||
return "fakeRuntime";
|
||||
}
|
||||
});
|
||||
|
||||
win.AppManager.update("runtimelist");
|
||||
|
||||
let packagedAppLocation = getTestFilePath("app");
|
||||
|
||||
yield win.Cmds.importPackagedApp(packagedAppLocation);
|
||||
|
||||
let panelNode = winIframe.document.querySelector("#runtime-panel");
|
||||
let items = panelNode.querySelectorAll(".runtime-panel-item-usb");
|
||||
is(items.length, 1, "Found one runtime button");
|
||||
|
||||
let deferred = promise.defer();
|
||||
win.AppManager.connection.once(
|
||||
win.Connection.Events.CONNECTED,
|
||||
() => deferred.resolve());
|
||||
|
||||
items[0].click();
|
||||
|
||||
ok(win.document.querySelector("window").className, "busy", "UI is busy");
|
||||
yield win.UI._busyPromise;
|
||||
|
||||
is(Object.keys(DebuggerServer._connections).length, 1, "Connected");
|
||||
|
||||
yield waitForUpdate(win, "runtime-apps-found");
|
||||
|
||||
ok(isPlayActive(), "play button is enabled 1");
|
||||
ok(!isStopActive(), "stop button is disabled 1");
|
||||
let oldProject = win.AppManager.selectedProject;
|
||||
win.AppManager.selectedProject = null;
|
||||
|
||||
yield nextTick();
|
||||
|
||||
ok(!isPlayActive(), "play button is disabled 2");
|
||||
ok(!isStopActive(), "stop button is disabled 2");
|
||||
win.AppManager._selectedProject = oldProject;
|
||||
win.UI.updateCommands();
|
||||
|
||||
yield nextTick();
|
||||
|
||||
ok(isPlayActive(), "play button is enabled 3");
|
||||
ok(!isStopActive(), "stop button is disabled 3");
|
||||
|
||||
yield win.Cmds.disconnectRuntime();
|
||||
|
||||
is(Object.keys(DebuggerServer._connections).length, 0, "Disconnected");
|
||||
|
||||
ok(win.AppManager.selectedProject, "A project is still selected");
|
||||
ok(!isPlayActive(), "play button is disabled 4");
|
||||
ok(!isStopActive(), "stop button is disabled 4");
|
||||
|
||||
winIframe.document.querySelectorAll(".runtime-panel-item-other")[1].click();
|
||||
|
||||
yield waitForUpdate(win, "runtime-apps-found");
|
||||
|
||||
is(Object.keys(DebuggerServer._connections).length, 1, "Locally connected");
|
||||
|
||||
ok(win.AppManager.isMainProcessDebuggable(), "Main process available");
|
||||
|
||||
// Select main process
|
||||
yield win.Cmds.showProjectPanel();
|
||||
SimpleTest.executeSoon(() => {
|
||||
winIframe.document.querySelectorAll("#project-panel-runtimeapps .panel-item")[0].click();
|
||||
});
|
||||
|
||||
yield waitForUpdate(win, "project");
|
||||
|
||||
// Toolbox opens automatically for main process / runtime apps
|
||||
ok(win.UI.toolboxPromise, "Toolbox promise exists");
|
||||
yield win.UI.toolboxPromise;
|
||||
|
||||
ok(win.UI.toolboxIframe, "Toolbox iframe exists");
|
||||
|
||||
yield win.Cmds.disconnectRuntime();
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
let packagedAppLocation = getTestFilePath("build_app" + testSuffix + "1");
|
||||
|
||||
yield win.Cmds.importPackagedApp(packagedAppLocation);
|
||||
yield win.projectList.importPackagedApp(packagedAppLocation);
|
||||
yield waitForUpdate(win, "details");
|
||||
|
||||
let project = win.AppManager.selectedProject;
|
||||
|
@ -76,7 +76,7 @@
|
|||
// # Now test a full featured package.json
|
||||
packagedAppLocation = getTestFilePath("build_app" + testSuffix + "2");
|
||||
|
||||
yield win.Cmds.importPackagedApp(packagedAppLocation);
|
||||
yield win.projectList.importPackagedApp(packagedAppLocation);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
|
||||
project = win.AppManager.selectedProject;
|
||||
|
@ -95,7 +95,7 @@
|
|||
is(loggedMessages[3], "succeed", "log messages are correct");
|
||||
|
||||
// Switch to the package dir in order to verify the generated webapp.manifest
|
||||
yield win.Cmds.importPackagedApp(packageDir);
|
||||
yield win.projectList.importPackagedApp(packageDir);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
|
||||
project = win.AppManager.selectedProject;
|
||||
|
|
|
@ -27,17 +27,17 @@
|
|||
is(win.AppProjects.store.object.projects.length, 0, "IDB is empty");
|
||||
|
||||
info("to call importPackagedApp(" + packagedAppLocation + ")");
|
||||
yield win.Cmds.importPackagedApp(packagedAppLocation);
|
||||
yield win.projectList.importPackagedApp(packagedAppLocation);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
yield nextTick();
|
||||
|
||||
info("to call importHostedApp(" + hostedAppManifest + ")");
|
||||
yield win.Cmds.importHostedApp(hostedAppManifest);
|
||||
yield win.projectList.importHostedApp(hostedAppManifest);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
yield nextTick();
|
||||
|
||||
info("to call importPackagedApp(" + packagedAppLocation + ") again");
|
||||
yield win.Cmds.importPackagedApp(packagedAppLocation);
|
||||
yield win.projectList.importPackagedApp(packagedAppLocation);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
|
||||
let project = win.AppManager.selectedProject;
|
||||
|
@ -45,7 +45,7 @@
|
|||
yield nextTick();
|
||||
|
||||
info("to call importHostedApp(" + hostedAppManifest + ") again");
|
||||
yield win.Cmds.importHostedApp(hostedAppManifest);
|
||||
yield win.projectList.importHostedApp(hostedAppManifest);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
project = win.AppManager.selectedProject;
|
||||
is(project.location, hostedAppManifest, "Correctly reselected existing hosted app.");
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
window.onload = function() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
Task.spawn(function* () {
|
||||
Task.spawn(function*() {
|
||||
let win = yield openWebIDE();
|
||||
let packagedAppLocation = getTestFilePath("app");
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
|||
info("to call importPackagedApp(" + packagedAppLocation + ")");
|
||||
ok(!win.UI._busyPromise, "UI is not busy");
|
||||
|
||||
yield win.Cmds.importPackagedApp(packagedAppLocation);
|
||||
yield win.projectList.importPackagedApp(packagedAppLocation);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
|
||||
let project = win.AppManager.selectedProject;
|
||||
|
@ -40,7 +40,7 @@
|
|||
yield nextTick();
|
||||
|
||||
let hostedAppManifest = TEST_BASE + "hosted_app.manifest";
|
||||
yield win.Cmds.importHostedApp(hostedAppManifest);
|
||||
yield win.projectList.importHostedApp(hostedAppManifest);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
|
||||
project = win.AppManager.selectedProject;
|
||||
|
@ -50,7 +50,7 @@
|
|||
yield nextTick();
|
||||
|
||||
hostedAppManifest = TEST_BASE + "/app";
|
||||
yield win.Cmds.importHostedApp(hostedAppManifest);
|
||||
yield win.projectList.importHostedApp(hostedAppManifest);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
|
||||
project = win.AppManager.selectedProject;
|
||||
|
|
|
@ -25,13 +25,13 @@
|
|||
let AppManager = win.AppManager;
|
||||
|
||||
function isProjectMarkedAsValid() {
|
||||
let details = win.frames[0];
|
||||
let details = win.frames[1];
|
||||
return !details.document.body.classList.contains("error");
|
||||
}
|
||||
|
||||
let packagedAppLocation = getTestFilePath("app");
|
||||
|
||||
yield win.Cmds.importPackagedApp(packagedAppLocation);
|
||||
yield win.projectList.importPackagedApp(packagedAppLocation);
|
||||
yield waitForUpdate(win, "details");
|
||||
|
||||
let project = win.AppManager.selectedProject;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
Task.spawn(function* () {
|
||||
let win = yield openWebIDE();
|
||||
let tmpDir = FileUtils.getDir("TmpD", []);
|
||||
yield win.Cmds.newApp({
|
||||
yield win.projectList.newApp({
|
||||
index: 0,
|
||||
name: "webideTmpApp",
|
||||
folder: tmpDir
|
||||
|
|
|
@ -18,3 +18,4 @@ webide.jar:
|
|||
skin/config-view.css (config-view.css)
|
||||
skin/wifi-auth.css (wifi-auth.css)
|
||||
skin/logs.css (logs.css)
|
||||
skin/project-listing.css (project-listing.css)
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/* 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/. */
|
||||
|
||||
html {
|
||||
font: message-box;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.panel-item, label, #project-panel-projects {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.project-image, .panel-item span {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.project-image {
|
||||
margin-right: 10px;
|
||||
max-height: 20px;
|
||||
}
|
||||
|
||||
label {
|
||||
color: #888;
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
padding: 15px 0 5px;
|
||||
text-shadow: 1px 1px #fff;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.panel-item {
|
||||
cursor: default;
|
||||
padding: 5px 0;
|
||||
min-width: 130px;
|
||||
}
|
|
@ -151,6 +151,44 @@ panel > .panel-arrowcontainer > .panel-arrowcontent {
|
|||
max-width: 400px;
|
||||
}
|
||||
|
||||
#project-listing-panel {
|
||||
display: none;
|
||||
position: relative;
|
||||
max-width: 250px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#project-listing-wrapper {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
min-width: 100px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#project-listing-panel-details {
|
||||
height: inherit;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* TODO: remove once Bug 1079347 is complete */
|
||||
.project-listing, #project-listing-splitter {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#project-listing-splitter[sidebar-displayed], #project-listing-panel[sidebar-displayed],
|
||||
#project-listing-panel[sidebar-displayed] .project-listing {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.panel-item {
|
||||
padding: 3px 12px;
|
||||
margin: 0;
|
||||
|
@ -280,14 +318,6 @@ panel > .panel-arrowcontainer > .panel-arrowcontent {
|
|||
}
|
||||
|
||||
.devtools-horizontal-splitter {
|
||||
-moz-appearance: none;
|
||||
background-image: none;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
border-bottom: 1px solid rgba(118, 121, 125, .5);
|
||||
min-height: 3px;
|
||||
height: 3px;
|
||||
margin-top: -3px;
|
||||
position: relative;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
|
|
|
@ -32,3 +32,4 @@ pref("devtools.webide.widget.inNavbarByDefault", false);
|
|||
#endif
|
||||
pref("devtools.webide.zoom", "1");
|
||||
pref("devtools.webide.busyTimeout", 10000);
|
||||
pref("devtools.webide.sidebars", false);
|
||||
|
|
|
@ -84,6 +84,11 @@ let DirectoryLinksProvider = {
|
|||
*/
|
||||
_enhancedLinks: new Map(),
|
||||
|
||||
/**
|
||||
* A mapping from site to a list of related link objects
|
||||
*/
|
||||
_relatedLinks: new Map(),
|
||||
|
||||
get _observedPrefs() Object.freeze({
|
||||
enhanced: PREF_NEWTAB_ENHANCED,
|
||||
linksURL: PREF_DIRECTORY_SOURCE,
|
||||
|
@ -187,6 +192,14 @@ let DirectoryLinksProvider = {
|
|||
}
|
||||
},
|
||||
|
||||
_cacheRelatedLinks: function(link) {
|
||||
for (let relatedSite of link.related) {
|
||||
let relatedMap = this._relatedLinks.get(relatedSite) || new Map();
|
||||
relatedMap.set(link.url, link);
|
||||
this._relatedLinks.set(relatedSite, relatedMap);
|
||||
}
|
||||
},
|
||||
|
||||
_fetchAndCacheLinks: function DirectoryLinksProvider_fetchAndCacheLinks(uri) {
|
||||
// Replace with the same display locale used for selecting links data
|
||||
uri = uri.replace("%LOCALE%", this.locale);
|
||||
|
@ -389,24 +402,33 @@ let DirectoryLinksProvider = {
|
|||
*/
|
||||
getLinks: function DirectoryLinksProvider_getLinks(aCallback) {
|
||||
this._readDirectoryLinksFile().then(rawLinks => {
|
||||
// Reset the cache of enhanced images for this new set of links
|
||||
// Reset the cache of related tiles and enhanced images for this new set of links
|
||||
this._enhancedLinks.clear();
|
||||
this._relatedLinks.clear();
|
||||
|
||||
return rawLinks.filter(link => {
|
||||
let links = [];
|
||||
rawLinks.filter(link => {
|
||||
// Make sure the link url is allowed and images too if they exist
|
||||
return this.isURLAllowed(link.url, ALLOWED_LINK_SCHEMES) &&
|
||||
this.isURLAllowed(link.imageURI, ALLOWED_IMAGE_SCHEMES) &&
|
||||
this.isURLAllowed(link.enhancedImageURI, ALLOWED_IMAGE_SCHEMES);
|
||||
}).map((link, position) => {
|
||||
}).forEach((link, position) => {
|
||||
// Stash the enhanced image for the site
|
||||
if (link.enhancedImageURI) {
|
||||
this._enhancedLinks.set(NewTabUtils.extractSite(link.url), link);
|
||||
}
|
||||
|
||||
link.frecency = DIRECTORY_FRECENCY;
|
||||
link.lastVisitDate = rawLinks.length - position;
|
||||
return link;
|
||||
|
||||
// We cache related tiles here but do not push any of them in the links list yet.
|
||||
// The decision for which related tile to include will be made separately.
|
||||
if ("related" == link.type) {
|
||||
this._cacheRelatedLinks(link);
|
||||
return;
|
||||
}
|
||||
link.frecency = DIRECTORY_FRECENCY;
|
||||
links.push(link);
|
||||
});
|
||||
return links;
|
||||
}).catch(ex => {
|
||||
Cu.reportError(ex);
|
||||
return [];
|
||||
|
|
|
@ -175,6 +175,71 @@ function run_test() {
|
|||
});
|
||||
}
|
||||
|
||||
add_task(function test_relatedLinksMap() {
|
||||
let relatedTile1 = {
|
||||
url: "http://turbotax.com",
|
||||
type: "related",
|
||||
lastVisitDate: 4,
|
||||
related: [
|
||||
"taxact.com",
|
||||
"hrblock.com",
|
||||
"1040.com",
|
||||
"taxslayer.com"
|
||||
]
|
||||
};
|
||||
let relatedTile2 = {
|
||||
url: "http://irs.gov",
|
||||
type: "related",
|
||||
lastVisitDate: 3,
|
||||
related: [
|
||||
"taxact.com",
|
||||
"hrblock.com",
|
||||
"freetaxusa.com",
|
||||
"taxslayer.com"
|
||||
]
|
||||
};
|
||||
let relatedTile3 = {
|
||||
url: "http://hrblock.com",
|
||||
type: "related",
|
||||
lastVisitDate: 2,
|
||||
related: [
|
||||
"taxact.com",
|
||||
"freetaxusa.com",
|
||||
"1040.com",
|
||||
"taxslayer.com"
|
||||
]
|
||||
};
|
||||
let someOtherSite = {url: "http://someothersite.com", title: "Not_A_Related_Site"};
|
||||
let data = {"en-US": [relatedTile1, relatedTile2, relatedTile3, someOtherSite]};
|
||||
let dataURI = 'data:application/json,' + JSON.stringify(data);
|
||||
|
||||
yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
|
||||
let links = yield fetchData();
|
||||
|
||||
// Ensure the related tiles were not considered directory tiles.
|
||||
do_check_eq(links.length, 1);
|
||||
let expected_data = [{url: "http://someothersite.com", title: "Not_A_Related_Site", frecency: DIRECTORY_FRECENCY, lastVisitDate: 1}];
|
||||
isIdentical(links, expected_data);
|
||||
|
||||
// Check for correctly saved related tiles data.
|
||||
expected_data = {
|
||||
"taxact.com": [relatedTile1, relatedTile2, relatedTile3],
|
||||
"hrblock.com": [relatedTile1, relatedTile2],
|
||||
"1040.com": [relatedTile1, relatedTile3],
|
||||
"taxslayer.com": [relatedTile1, relatedTile2, relatedTile3],
|
||||
"freetaxusa.com": [relatedTile2, relatedTile3],
|
||||
};
|
||||
|
||||
DirectoryLinksProvider._relatedLinks.forEach((relatedLinks, site) => {
|
||||
let relatedLinksItr = relatedLinks.values();
|
||||
for (let link of expected_data[site]) {
|
||||
isIdentical(relatedLinksItr.next().value, link);
|
||||
}
|
||||
})
|
||||
|
||||
yield promiseCleanDirectoryLinksProvider();
|
||||
});
|
||||
|
||||
add_task(function test_reportSitesAction() {
|
||||
yield DirectoryLinksProvider.init();
|
||||
let deferred, expectedPath, expectedPost;
|
||||
|
|
|
@ -20,18 +20,6 @@ const TEST_DATA = [
|
|||
relSignalStrength: null
|
||||
}
|
||||
},
|
||||
// Valid rxlev with max value.
|
||||
{
|
||||
input: {
|
||||
rxlev: 63,
|
||||
rsrp: 65535,
|
||||
rssnr: 65535
|
||||
},
|
||||
expect: {
|
||||
signalStrength: -48,
|
||||
relSignalStrength: 100
|
||||
}
|
||||
},
|
||||
// Valid rxlev.
|
||||
{
|
||||
input: {
|
||||
|
@ -40,7 +28,7 @@ const TEST_DATA = [
|
|||
rssnr: 65535
|
||||
},
|
||||
expect: {
|
||||
signalStrength: -99,
|
||||
signalStrength: null,
|
||||
relSignalStrength: 100
|
||||
}
|
||||
},
|
||||
|
@ -52,9 +40,57 @@ const TEST_DATA = [
|
|||
rssnr: 65535
|
||||
},
|
||||
expect: {
|
||||
signalStrength: -111,
|
||||
signalStrength: null,
|
||||
relSignalStrength: 0
|
||||
}
|
||||
},
|
||||
// Valid rxlev with max value.
|
||||
{
|
||||
input: {
|
||||
rxlev: 63,
|
||||
rsrp: 65535,
|
||||
rssnr: 65535
|
||||
},
|
||||
expect: {
|
||||
signalStrength: null,
|
||||
relSignalStrength: 100
|
||||
}
|
||||
},
|
||||
// Valid rsrp.
|
||||
{
|
||||
input: {
|
||||
rxlev: 31,
|
||||
rsrp: 50,
|
||||
rssnr: 65535
|
||||
},
|
||||
expect: {
|
||||
signalStrength: 50,
|
||||
relSignalStrength: 100
|
||||
}
|
||||
},
|
||||
// Valid rssnr.
|
||||
{
|
||||
input: {
|
||||
rxlev: 31,
|
||||
rsrp: 65535,
|
||||
rssnr: 100
|
||||
},
|
||||
expect: {
|
||||
signalStrength: null,
|
||||
relSignalStrength: 81
|
||||
}
|
||||
},
|
||||
// Valid rsrp and rssnr.
|
||||
{
|
||||
input: {
|
||||
rxlev: 31,
|
||||
rsrp: 100,
|
||||
rssnr: 30
|
||||
},
|
||||
expect: {
|
||||
signalStrength: 100,
|
||||
relSignalStrength: 37
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
@ -47,6 +47,9 @@ let RILQUIRKS_RADIO_OFF_WO_CARD =
|
|||
let RILQUIRKS_HAVE_IPV6 =
|
||||
libcutils.property_get("ro.moz.ril.ipv6", "false") == "true";
|
||||
|
||||
let RILQUIRKS_SIGNAL_EXTRA_INT32 =
|
||||
libcutils.property_get("ro.moz.ril.signal_extra_int", "false") == "true";
|
||||
|
||||
const RADIOINTERFACELAYER_CID =
|
||||
Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
|
||||
const RADIOINTERFACE_CID =
|
||||
|
@ -1512,7 +1515,8 @@ WorkerMessenger.prototype = {
|
|||
sendStkProfileDownload:
|
||||
libcutils.property_get("ro.moz.ril.send_stk_profile_dl", "false") == "true",
|
||||
dataRegistrationOnDemand: RILQUIRKS_DATA_REGISTRATION_ON_DEMAND,
|
||||
subscriptionControl: RILQUIRKS_SUBSCRIPTION_CONTROL
|
||||
subscriptionControl: RILQUIRKS_SUBSCRIPTION_CONTROL,
|
||||
signalExtraInt: RILQUIRKS_SIGNAL_EXTRA_INT32
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -82,6 +82,8 @@ let RILQUIRKS_DATA_REGISTRATION_ON_DEMAND;
|
|||
// Ril quirk to control the uicc/data subscription.
|
||||
let RILQUIRKS_SUBSCRIPTION_CONTROL;
|
||||
|
||||
let RILQUIRKS_SIGNAL_EXTRA_INT32;
|
||||
|
||||
const TELEPHONY_REQUESTS = [
|
||||
REQUEST_GET_CURRENT_CALLS,
|
||||
REQUEST_ANSWER,
|
||||
|
@ -3376,15 +3378,12 @@ RilObject.prototype = {
|
|||
*
|
||||
* @return The object of signal strength info.
|
||||
* Or null if invalid signal input.
|
||||
*
|
||||
* TODO: Bug 982013: reconsider the format of signal strength APIs for
|
||||
* GSM/CDMA/LTE to expose details, such as rsrp and rsnnr,
|
||||
* individually.
|
||||
*/
|
||||
_processLteSignal: function(signal) {
|
||||
// Valid values are 0-63 as defined in TS 27.007 clause 8.69.
|
||||
if (signal.lteSignalStrength === undefined ||
|
||||
signal.lteSignalStrength < 0 ||
|
||||
signal.lteSignalStrength > 63) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let info = {
|
||||
voice: {
|
||||
signalStrength: null,
|
||||
|
@ -3396,16 +3395,51 @@ RilObject.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
// TODO: Bug 982013: reconsider signalStrength/relSignalStrength APIs for
|
||||
// GSM/CDMA/LTE, and take rsrp/rssnr into account for LTE case then.
|
||||
let signalStrength = -111 + signal.lteSignalStrength;
|
||||
// Referring to AOSP, use lteRSRP for signalStrength in dBm.
|
||||
let signalStrength = (signal.lteRSRP === undefined || signal.lteRSRP === 0x7FFFFFFF) ?
|
||||
null : signal.lteRSRP;
|
||||
info.voice.signalStrength = info.data.signalStrength = signalStrength;
|
||||
// 0 and 12 are referred to AOSP's implementation. These values are not
|
||||
// constants and can be customized based on different requirements.
|
||||
let signalLevel = this._processSignalLevel(signal.lteSignalStrength, 0, 12);
|
||||
info.voice.relSignalStrength = info.data.relSignalStrength = signalLevel;
|
||||
|
||||
// Referring to AOSP, first determine signalLevel based on RSRP and RSSNR,
|
||||
// then on lteSignalStrength if RSRP and RSSNR are invalid.
|
||||
let rsrpLevel = -1;
|
||||
let rssnrLevel = -1;
|
||||
if (signal.lteRSRP !== undefined &&
|
||||
signal.lteRSRP !== 0x7FFFFFFF &&
|
||||
signal.lteRSRP >= 44 &&
|
||||
signal.lteRSRP <= 140) {
|
||||
rsrpLevel = this._processSignalLevel(signal.lteRSRP * -1, -115, -85);
|
||||
}
|
||||
|
||||
if (signal.lteRSSNR !== undefined &&
|
||||
signal.lteRSSNR !== 0x7FFFFFFF &&
|
||||
signal.lteRSSNR >= -200 &&
|
||||
signal.lteRSSNR <= 300) {
|
||||
rssnrLevel = this._processSignalLevel(signal.lteRSSNR, -30, 130);
|
||||
}
|
||||
|
||||
if (rsrpLevel !== -1 && rssnrLevel !== -1) {
|
||||
info.voice.relSignalStrength = info.data.relSignalStrength =
|
||||
Math.min(rsrpLevel, rssnrLevel);
|
||||
return info;
|
||||
}
|
||||
|
||||
let level = Math.max(rsrpLevel, rssnrLevel);
|
||||
if (level !== -1) {
|
||||
info.voice.relSignalStrength = info.data.relSignalStrength = level;
|
||||
return info;
|
||||
}
|
||||
|
||||
// Valid values are 0-63 as defined in TS 27.007 clause 8.69.
|
||||
if (signal.lteSignalStrength !== undefined &&
|
||||
signal.lteSignalStrength >= 0 &&
|
||||
signal.lteSignalStrength <= 63) {
|
||||
level = this._processSignalLevel(signal.lteSignalStrength, 0, 12);
|
||||
info.voice.relSignalStrength = info.data.relSignalStrength = level;
|
||||
return info;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
_processSignalStrength: function(signal) {
|
||||
|
@ -5323,15 +5357,18 @@ RilObject.prototype[REQUEST_SIGNAL_STRENGTH] = function REQUEST_SIGNAL_STRENGTH(
|
|||
}
|
||||
|
||||
let Buf = this.context.Buf;
|
||||
let signal = {
|
||||
gsmSignalStrength: Buf.readInt32(),
|
||||
gsmBitErrorRate: Buf.readInt32(),
|
||||
cdmaDBM: Buf.readInt32(),
|
||||
cdmaECIO: Buf.readInt32(),
|
||||
evdoDBM: Buf.readInt32(),
|
||||
evdoECIO: Buf.readInt32(),
|
||||
evdoSNR: Buf.readInt32()
|
||||
};
|
||||
let signal = {};
|
||||
|
||||
signal.gsmSignalStrength = Buf.readInt32();
|
||||
signal.gsmBitErrorRate = Buf.readInt32();
|
||||
if (RILQUIRKS_SIGNAL_EXTRA_INT32) {
|
||||
Buf.readInt32();
|
||||
}
|
||||
signal.cdmaDBM = Buf.readInt32();
|
||||
signal.cdmaECIO = Buf.readInt32();
|
||||
signal.evdoDBM = Buf.readInt32();
|
||||
signal.evdoECIO = Buf.readInt32();
|
||||
signal.evdoSNR = Buf.readInt32();
|
||||
|
||||
if (!this.v5Legacy) {
|
||||
signal.lteSignalStrength = Buf.readInt32();
|
||||
|
@ -16093,6 +16130,7 @@ let ContextPool = {
|
|||
RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD = quirks.sendStkProfileDownload;
|
||||
RILQUIRKS_DATA_REGISTRATION_ON_DEMAND = quirks.dataRegistrationOnDemand;
|
||||
RILQUIRKS_SUBSCRIPTION_CONTROL = quirks.subscriptionControl;
|
||||
RILQUIRKS_SIGNAL_EXTRA_INT32 = quirks.signalExtraInt;
|
||||
},
|
||||
|
||||
setDebugFlag: function(aOptions) {
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.mozilla.gecko.db.BrowserDB;
|
|||
import org.mozilla.gecko.db.ReadingListAccessor;
|
||||
import org.mozilla.gecko.home.HomeContextMenuInfo.RemoveItemType;
|
||||
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
|
@ -139,6 +140,9 @@ public class ReadingListPanel extends HomeFragment {
|
|||
mEmptyView = emptyViewStub.inflate();
|
||||
|
||||
final TextView emptyHint = (TextView) mEmptyView.findViewById(R.id.home_empty_hint);
|
||||
if (HardwareUtils.isLowMemoryPlatform()) {
|
||||
emptyHint.setVisibility(View.GONE);
|
||||
} else {
|
||||
String readingListHint = emptyHint.getText().toString();
|
||||
|
||||
// Use an ImageSpan to include the reader icon in the "Tip".
|
||||
|
@ -156,6 +160,7 @@ public class ReadingListPanel extends HomeFragment {
|
|||
|
||||
emptyHint.setText(hintBuilder, TextView.BufferType.SPANNABLE);
|
||||
}
|
||||
}
|
||||
|
||||
mList.setEmptyView(mEmptyView);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,14 @@ import android.view.ViewConfiguration;
|
|||
public final class HardwareUtils {
|
||||
private static final String LOGTAG = "GeckoHardwareUtils";
|
||||
|
||||
// Minimum memory threshold for a device to be considered
|
||||
// a low memory platform (see isLowMemoryPlatform). This value
|
||||
// has be in sync with Gecko's equivalent threshold (defined in
|
||||
// xpcom/base/nsMemoryImpl.cpp) and should only be used in cases
|
||||
// where we can't depend on Gecko to be up and running e.g. show/hide
|
||||
// reading list capabilities in HomePager.
|
||||
private static final int LOW_MEMORY_THRESHOLD_MB = 384;
|
||||
|
||||
private static final boolean IS_AMAZON_DEVICE = Build.MANUFACTURER.equalsIgnoreCase("Amazon");
|
||||
public static final boolean IS_KINDLE_DEVICE = IS_AMAZON_DEVICE &&
|
||||
(Build.MODEL.equals("Kindle Fire") ||
|
||||
|
@ -88,4 +96,17 @@ public final class HardwareUtils {
|
|||
public static int getMemSize() {
|
||||
return SysInfo.getMemSize();
|
||||
}
|
||||
|
||||
public static boolean isLowMemoryPlatform() {
|
||||
final int memSize = getMemSize();
|
||||
|
||||
// Fallback to false if we fail to read meminfo
|
||||
// for some reason.
|
||||
if (memSize == 0) {
|
||||
Log.w(LOGTAG, "Could not compute system memory. Falling back to isLowMemoryPlatform = false.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return memSize < LOW_MEMORY_THRESHOLD_MB;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,29 +117,29 @@ body {
|
|||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.light > .header > .domain {
|
||||
.light > .container > .header > .domain {
|
||||
color: #ee7600;
|
||||
border-bottom-color: #d0d0d0;
|
||||
}
|
||||
|
||||
.light > .header > h1 {
|
||||
.light > .container > .header > h1 {
|
||||
color: #222222;
|
||||
}
|
||||
|
||||
.light > .header > .credits {
|
||||
.light > .container > .header > .credits {
|
||||
color: #898989;
|
||||
}
|
||||
|
||||
.dark > .header > .domain {
|
||||
.dark > .container > .header > .domain {
|
||||
color: #ff9400;
|
||||
border-bottom-color: #777777;
|
||||
}
|
||||
|
||||
.dark > .header > h1 {
|
||||
.dark > .container > .header > h1 {
|
||||
color: #eeeeee;
|
||||
}
|
||||
|
||||
.dark > .header > .credits {
|
||||
.dark > .container > .header > .credits {
|
||||
color: #aaaaaa;
|
||||
}
|
||||
|
||||
|
@ -163,17 +163,10 @@ body {
|
|||
font-weight: normal;
|
||||
}
|
||||
|
||||
.light > .content a,
|
||||
.light > .content a:visited,
|
||||
.light > .content a:hover,
|
||||
.light > .content a:active {
|
||||
color: #00acff !important;
|
||||
}
|
||||
|
||||
.dark > .content a,
|
||||
.dark > .content a:visited,
|
||||
.dark > .content a:hover,
|
||||
.dark > .content a:active {
|
||||
.content a,
|
||||
.content a:visited,
|
||||
.content a:hover,
|
||||
.content a:active {
|
||||
color: #00acff !important;
|
||||
}
|
||||
|
||||
|
@ -227,15 +220,15 @@ body {
|
|||
padding-top: 4px !important;
|
||||
}
|
||||
|
||||
.light > .content .caption,
|
||||
.light > .content .wp-caption-text,
|
||||
.light > .content figcaption {
|
||||
.light > .container > .content .caption,
|
||||
.light > .container > .content .wp-caption-text,
|
||||
.light > .container > .content figcaption {
|
||||
color: #898989;
|
||||
}
|
||||
|
||||
.dark > .content .caption,
|
||||
.dark > .content .wp-caption-text,
|
||||
.dark > .content figcaption {
|
||||
.dark > .container > .content .caption,
|
||||
.dark > .container > .content .wp-caption-text,
|
||||
.dark > .container > .content figcaption {
|
||||
color: #aaaaaa;
|
||||
}
|
||||
|
||||
|
@ -256,12 +249,12 @@ body {
|
|||
border-left: 2px solid !important;
|
||||
}
|
||||
|
||||
.light > .content blockquote {
|
||||
.light > .container > .content blockquote {
|
||||
color: #898989 !important;
|
||||
border-left-color: #d0d0d0 !important;
|
||||
}
|
||||
|
||||
.dark > .content blockquote {
|
||||
.dark > .container > .content blockquote {
|
||||
color: #aaaaaa !important;
|
||||
border-left-color: #777777 !important;
|
||||
}
|
||||
|
|
|
@ -1899,3 +1899,30 @@ Example
|
|||
"foobar-value"
|
||||
]
|
||||
}
|
||||
|
||||
org.mozilla.passwordmgr.passwordmgr
|
||||
-----------------------------------
|
||||
|
||||
Daily measurement reporting information about the Password Manager
|
||||
|
||||
Version 1
|
||||
^^^^^^^^^
|
||||
|
||||
Property:
|
||||
|
||||
numSavedPasswords
|
||||
number of passwords saved in the Password Manager
|
||||
|
||||
enabled
|
||||
Whether or not the user has disabled the Password Manager in prefernces
|
||||
|
||||
Example
|
||||
^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
"org.mozilla.passwordmgr.passwordmgr": {
|
||||
"_v": 1,
|
||||
"numSavedPasswords": 5,
|
||||
"enabled": 0,
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "UserAutoCompleteResult",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "AutoCompleteE10S",
|
||||
"resource://gre/modules/AutoCompleteE10S.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ "LoginManagerParent" ];
|
||||
this.EXPORTED_SYMBOLS = [ "LoginManagerParent", "PasswordsMetricsProvider" ];
|
||||
|
||||
var gDebug;
|
||||
|
||||
|
@ -51,6 +51,61 @@ function log(...pieces) {
|
|||
Services.console.logStringMessage(message);
|
||||
}
|
||||
|
||||
#ifndef ANDROID
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Metrics",
|
||||
"resource://gre/modules/Metrics.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
|
||||
this.PasswordsMetricsProvider = function() {
|
||||
Metrics.Provider.call(this);
|
||||
}
|
||||
|
||||
PasswordsMetricsProvider.prototype = Object.freeze({
|
||||
__proto__: Metrics.Provider.prototype,
|
||||
|
||||
name: "org.mozilla.passwordmgr",
|
||||
|
||||
measurementTypes: [
|
||||
PasswordsMeasurement1,
|
||||
],
|
||||
|
||||
pullOnly: true,
|
||||
|
||||
collectDailyData: function* () {
|
||||
return this.storage.enqueueTransaction(this._recordDailyPasswordData.bind(this));
|
||||
},
|
||||
|
||||
_recordDailyPasswordData: function() {
|
||||
let m = this.getMeasurement(PasswordsMeasurement1.prototype.name,
|
||||
PasswordsMeasurement1.prototype.version);
|
||||
let enabled = Services.prefs.getBoolPref("signon.rememberSignons");
|
||||
yield m.setDailyLastNumeric("enabled", enabled ? 1 : 0);
|
||||
|
||||
let loginsCount = Services.logins.countLogins("", "", "");
|
||||
yield m.setDailyLastNumeric("numSavedPasswords", loginsCount);
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
function PasswordsMeasurement1() {
|
||||
Metrics.Measurement.call(this);
|
||||
}
|
||||
|
||||
PasswordsMeasurement1.prototype = Object.freeze({
|
||||
__proto__: Metrics.Measurement.prototype,
|
||||
name: "passwordmgr",
|
||||
version: 1,
|
||||
fields: {
|
||||
enabled: {type: Metrics.Storage.FIELD_DAILY_LAST_NUMERIC},
|
||||
numSavedPasswords: {type: Metrics.Storage.FIELD_DAILY_LAST_NUMERIC},
|
||||
},
|
||||
});
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
function prefChanged() {
|
||||
gDebug = Services.prefs.getBoolPref("signon.debug");
|
||||
}
|
||||
|
@ -151,8 +206,13 @@ var LoginManagerParent = {
|
|||
}
|
||||
|
||||
var logins = Services.logins.findLogins({}, formOrigin, actionOrigin, null);
|
||||
target.sendAsyncMessage("RemoteLogins:loginsFound",
|
||||
{ requestId: requestId, logins: logins });
|
||||
// Convert the array of nsILoginInfo to vanilla JS objects since nsILoginInfo
|
||||
// doesn't support structured cloning.
|
||||
var jsLogins = JSON.parse(JSON.stringify(logins));
|
||||
target.sendAsyncMessage("RemoteLogins:loginsFound", {
|
||||
requestId: requestId,
|
||||
logins: jsLogins,
|
||||
});
|
||||
|
||||
const PWMGR_FORM_ACTION_EFFECT = Services.telemetry.getHistogramById("PWMGR_FORM_ACTION_EFFECT");
|
||||
if (logins.length == 0) {
|
||||
|
@ -206,9 +266,13 @@ var LoginManagerParent = {
|
|||
AutoCompleteE10S.showPopupWithResults(target.ownerDocument.defaultView, rect, result);
|
||||
}
|
||||
|
||||
target.messageManager.sendAsyncMessage("RemoteLogins:loginsAutoCompleted",
|
||||
{ requestId: requestId,
|
||||
logins: matchingLogins });
|
||||
// Convert the array of nsILoginInfo to vanilla JS objects since nsILoginInfo
|
||||
// doesn't support structured cloning.
|
||||
var jsLogins = JSON.parse(JSON.stringify(matchingLogins));
|
||||
target.messageManager.sendAsyncMessage("RemoteLogins:loginsAutoCompleted", {
|
||||
requestId: requestId,
|
||||
logins: jsLogins,
|
||||
});
|
||||
},
|
||||
|
||||
onFormSubmit: function(hostname, formSubmitURL,
|
||||
|
|
|
@ -31,6 +31,10 @@ EXTRA_PP_COMPONENTS += [
|
|||
'passwordmgr.manifest',
|
||||
]
|
||||
|
||||
EXTRA_PP_JS_MODULES += [
|
||||
'LoginManagerParent.jsm',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'InsecurePasswordUtils.jsm',
|
||||
'LoginHelper.jsm',
|
||||
|
|
|
@ -15,3 +15,4 @@ contract @mozilla.org/login-manager/storage/json;1 {c00c432d-a0c9-46d7-bef6-9c45
|
|||
#endif
|
||||
component {dc6c2976-0f73-4f1f-b9ff-3d72b4e28309} crypto-SDR.js
|
||||
contract @mozilla.org/login-manager/crypto/SDR;1 {dc6c2976-0f73-4f1f-b9ff-3d72b4e28309}
|
||||
category healthreport-js-provider-default PasswordsMetricsProvider resource://gre/modules/LoginManagerParent.jsm
|
|
@ -14,6 +14,8 @@ importScripts("resource://gre/modules/workers/require.js",
|
|||
|
||||
let PromiseWorker = require("resource://gre/modules/workers/PromiseWorker.js");
|
||||
|
||||
const DEBUG = false;
|
||||
|
||||
let worker = new PromiseWorker.AbstractWorker();
|
||||
worker.dispatch = function(method, args = []) {
|
||||
return Agent[method](...args);
|
||||
|
@ -25,7 +27,9 @@ worker.close = function() {
|
|||
self.close();
|
||||
};
|
||||
worker.log = function(...args) {
|
||||
if (DEBUG) {
|
||||
dump("ReaderWorker: " + args.join(" ") + "\n");
|
||||
}
|
||||
};
|
||||
|
||||
self.addEventListener("message", msg => worker.handleMessage(msg));
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<div id="container" class="container">
|
||||
<div id="reader-header" class="header">
|
||||
<a id="reader-domain" class="domain"></a>
|
||||
<div class="domain-border"></div>
|
||||
|
|
|
@ -182,6 +182,7 @@ let MemoryActor = protocol.ActorClass({
|
|||
*/
|
||||
startRecordingAllocations: method(expectState("attached", function(options = {}) {
|
||||
this._frameCache.initFrames();
|
||||
|
||||
this.dbg.memory.allocationSamplingProbability = options.probability != null
|
||||
? options.probability
|
||||
: 1.0;
|
||||
|
@ -219,6 +220,23 @@ let MemoryActor = protocol.ActorClass({
|
|||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Return settings used in `startRecordingAllocations` for `probability`
|
||||
* and `maxLogLength`. Currently only uses in tests.
|
||||
*/
|
||||
getAllocationsSettings: method(expectState("attached", function() {
|
||||
return {
|
||||
maxLogLength: this.dbg.memory.maxAllocationsLogLength,
|
||||
probability: this.dbg.memory.allocationSamplingProbability
|
||||
};
|
||||
},
|
||||
`getting allocations settings`), {
|
||||
request: {},
|
||||
response: {
|
||||
options: RetVal(0, "json")
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Get a list of the most recent allocations since the last time we got
|
||||
* allocations, as well as a summary of all allocations since we've been
|
||||
|
|
|
@ -99,12 +99,12 @@ body {
|
|||
color: #0095dd;
|
||||
}
|
||||
|
||||
.light > .header > .domain,
|
||||
.sepia > .header > .domain {
|
||||
.light > .container > .header > .domain,
|
||||
.sepia > .container > .header > .domain {
|
||||
border-bottom-color: #333333;
|
||||
}
|
||||
|
||||
.dark > .header > .domain {
|
||||
.dark > .container > .header > .domain {
|
||||
border-bottom-color: #eeeeee;
|
||||
}
|
||||
|
||||
|
@ -204,12 +204,12 @@ body {
|
|||
-moz-padding-start: 16px;
|
||||
}
|
||||
|
||||
.light > .content blockquote,
|
||||
.sepia > .content blockquote {
|
||||
.light > .container > .content blockquote,
|
||||
.sepia > .container > .content blockquote {
|
||||
-moz-border-start: 2px solid #333333;
|
||||
}
|
||||
|
||||
.dark > .content blockquote {
|
||||
.dark > .container > .content blockquote {
|
||||
-moz-border-start: 2px solid #eeeeee;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче