mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge fx-team to mozilla-central a=merge
This commit is contained in:
commit
2550f09581
@ -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)
|
||||
|
||||
|
@ -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]
|
||||
|
39
browser/devtools/shared/test/browser_prefs-02.js
Normal file
39
browser/devtools/shared/test/browser_prefs-02.js
Normal file
@ -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)
|
||||
|
49
browser/devtools/webide/content/project-listing.js
Normal file
49
browser/devtools/webide/content/project-listing.js
Normal file
@ -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();
|
||||
}
|
33
browser/devtools/webide/content/project-listing.xhtml
Normal file
33
browser/devtools/webide/content/project-listing.xhtml
Normal file
@ -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>
|
39
browser/devtools/webide/content/project-panel.js
Normal file
39
browser/devtools/webide/content/project-panel.js
Normal file
@ -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,14 +542,16 @@ let UI = {
|
||||
|
||||
let project = AppManager.selectedProject;
|
||||
|
||||
if (!project) {
|
||||
buttonNode.classList.add("no-project");
|
||||
labelNode.setAttribute("value", Strings.GetStringFromName("projectButton_label"));
|
||||
imageNode.removeAttribute("src");
|
||||
} else {
|
||||
buttonNode.classList.remove("no-project");
|
||||
labelNode.setAttribute("value", project.name);
|
||||
imageNode.setAttribute("src", project.icon);
|
||||
if (!projectList.sidebarsEnabled) {
|
||||
if (!project) {
|
||||
buttonNode.classList.add("no-project");
|
||||
labelNode.setAttribute("value", Strings.GetStringFromName("projectButton_label"));
|
||||
imageNode.removeAttribute("src");
|
||||
} else {
|
||||
buttonNode.classList.remove("no-project");
|
||||
labelNode.setAttribute("value", project.name);
|
||||
imageNode.setAttribute("src", project.icon);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -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,18 +193,26 @@
|
||||
</popupset>
|
||||
|
||||
<notificationbox flex="1" id="notificationbox">
|
||||
<deck flex="1" id="deck" selectedIndex="-1">
|
||||
<iframe id="deck-panel-details" flex="1" src="details.xhtml"/>
|
||||
<iframe id="deck-panel-projecteditor" flex="1"/>
|
||||
<iframe id="deck-panel-addons" flex="1" src="addons.xhtml"/>
|
||||
<iframe id="deck-panel-prefs" flex="1" src="prefs.xhtml"/>
|
||||
<iframe id="deck-panel-permissionstable" flex="1" lazysrc="permissionstable.xhtml"/>
|
||||
<iframe id="deck-panel-runtimedetails" flex="1" lazysrc="runtimedetails.xhtml"/>
|
||||
<iframe id="deck-panel-monitor" flex="1" lazysrc="monitor.xhtml"/>
|
||||
<iframe id="deck-panel-devicepreferences" flex="1" lazysrc="devicepreferences.xhtml"/>
|
||||
<iframe id="deck-panel-devicesettings" flex="1" lazysrc="devicesettings.xhtml"/>
|
||||
<iframe id="deck-panel-logs" flex="1" src="logs.xhtml"/>
|
||||
</deck>
|
||||
<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"/>
|
||||
<iframe id="deck-panel-addons" flex="1" src="addons.xhtml"/>
|
||||
<iframe id="deck-panel-prefs" flex="1" src="prefs.xhtml"/>
|
||||
<iframe id="deck-panel-permissionstable" flex="1" lazysrc="permissionstable.xhtml"/>
|
||||
<iframe id="deck-panel-runtimedetails" flex="1" lazysrc="runtimedetails.xhtml"/>
|
||||
<iframe id="deck-panel-monitor" flex="1" lazysrc="monitor.xhtml"/>
|
||||
<iframe id="deck-panel-devicepreferences" flex="1" lazysrc="devicepreferences.xhtml"/>
|
||||
<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) {
|
||||
|
299
browser/devtools/webide/modules/project-list.js
Normal file
299
browser/devtools/webide/modules/project-list.js
Normal file
@ -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) {
|
||||
|
4
browser/devtools/webide/test/sidebars/browser.ini
Normal file
4
browser/devtools/webide/test/sidebars/browser.ini
Normal file
@ -0,0 +1,4 @@
|
||||
[DEFAULT]
|
||||
subsuite = devtools
|
||||
support-files =
|
||||
../head.js
|
8
browser/devtools/webide/test/sidebars/chrome.ini
Normal file
8
browser/devtools/webide/test/sidebars/chrome.ini
Normal file
@ -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>
|
||||
|
79
browser/devtools/webide/test/sidebars/test_import.html
Normal file
79
browser/devtools/webide/test/sidebars/test_import.html
Normal file
@ -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>
|
145
browser/devtools/webide/test/sidebars/test_runtime.html
Normal file
145
browser/devtools/webide/test/sidebars/test_runtime.html
Normal file
@ -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,60 +18,60 @@
|
||||
window.onload = function() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
Task.spawn(function* () {
|
||||
let win = yield openWebIDE();
|
||||
let packagedAppLocation = getTestFilePath("app");
|
||||
Task.spawn(function*() {
|
||||
let win = yield openWebIDE();
|
||||
let packagedAppLocation = getTestFilePath("app");
|
||||
|
||||
yield win.AppProjects.load();
|
||||
is(win.AppProjects.store.object.projects.length, 0, "IDB is empty");
|
||||
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");
|
||||
info("to call importPackagedApp(" + packagedAppLocation + ")");
|
||||
ok(!win.UI._busyPromise, "UI is not busy");
|
||||
|
||||
yield win.Cmds.importPackagedApp(packagedAppLocation);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
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");
|
||||
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();
|
||||
yield nextTick();
|
||||
|
||||
let hostedAppManifest = TEST_BASE + "hosted_app.manifest";
|
||||
yield win.Cmds.importHostedApp(hostedAppManifest);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
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");
|
||||
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();
|
||||
yield nextTick();
|
||||
|
||||
hostedAppManifest = TEST_BASE + "/app";
|
||||
yield win.Cmds.importHostedApp(hostedAppManifest);
|
||||
yield waitForUpdate(win, "project-validated");
|
||||
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");
|
||||
project = win.AppManager.selectedProject;
|
||||
ok(project.location.endsWith('manifest.webapp'), "The manifest was found and the project was updated");
|
||||
|
||||
info("opening panel");
|
||||
yield win.Cmds.showProjectPanel();
|
||||
info("panel open");
|
||||
info("opening panel");
|
||||
yield win.Cmds.showProjectPanel();
|
||||
info("panel open");
|
||||
|
||||
let panelNode = win.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].getAttribute("label"), "A name (in app directory)", "Panel label is correct");
|
||||
is(items[4].getAttribute("label"), "hosted manifest name property", "Panel label is correct");
|
||||
let panelNode = win.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].getAttribute("label"), "A name (in app directory)", "Panel label is correct");
|
||||
is(items[4].getAttribute("label"), "hosted manifest name property", "Panel label is correct");
|
||||
|
||||
yield closeWebIDE(win);
|
||||
yield closeWebIDE(win);
|
||||
|
||||
yield removeAllProjects();
|
||||
yield removeAllProjects();
|
||||
|
||||
SimpleTest.finish();
|
||||
SimpleTest.finish();
|
||||
}).then(null, e => {
|
||||
ok(false, "Exception: " + e);
|
||||
SimpleTest.finish();
|
||||
|
@ -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)
|
||||
|
41
browser/devtools/webide/themes/project-listing.css
Normal file
41
browser/devtools/webide/themes/project-listing.css
Normal file
@ -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;
|
||||
|
@ -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,22 +140,26 @@ public class ReadingListPanel extends HomeFragment {
|
||||
mEmptyView = emptyViewStub.inflate();
|
||||
|
||||
final TextView emptyHint = (TextView) mEmptyView.findViewById(R.id.home_empty_hint);
|
||||
String readingListHint = emptyHint.getText().toString();
|
||||
if (HardwareUtils.isLowMemoryPlatform()) {
|
||||
emptyHint.setVisibility(View.GONE);
|
||||
} else {
|
||||
String readingListHint = emptyHint.getText().toString();
|
||||
|
||||
// Use an ImageSpan to include the reader icon in the "Tip".
|
||||
int imageSpanIndex = readingListHint.indexOf(MATCH_STRING);
|
||||
if (imageSpanIndex != -1) {
|
||||
final ImageSpan readingListIcon = new ImageSpan(getActivity(), R.drawable.reader_cropped, ImageSpan.ALIGN_BOTTOM);
|
||||
final SpannableStringBuilder hintBuilder = new SpannableStringBuilder(readingListHint);
|
||||
// Use an ImageSpan to include the reader icon in the "Tip".
|
||||
int imageSpanIndex = readingListHint.indexOf(MATCH_STRING);
|
||||
if (imageSpanIndex != -1) {
|
||||
final ImageSpan readingListIcon = new ImageSpan(getActivity(), R.drawable.reader_cropped, ImageSpan.ALIGN_BOTTOM);
|
||||
final SpannableStringBuilder hintBuilder = new SpannableStringBuilder(readingListHint);
|
||||
|
||||
// Add additional spacing.
|
||||
hintBuilder.insert(imageSpanIndex + MATCH_STRING.length(), " ");
|
||||
hintBuilder.insert(imageSpanIndex, " ");
|
||||
// Add additional spacing.
|
||||
hintBuilder.insert(imageSpanIndex + MATCH_STRING.length(), " ");
|
||||
hintBuilder.insert(imageSpanIndex, " ");
|
||||
|
||||
// Add icon.
|
||||
hintBuilder.setSpan(readingListIcon, imageSpanIndex + 1, imageSpanIndex + MATCH_STRING.length() + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
// Add icon.
|
||||
hintBuilder.setSpan(readingListIcon, imageSpanIndex + 1, imageSpanIndex + MATCH_STRING.length() + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
|
||||
emptyHint.setText(hintBuilder, TextView.BufferType.SPANNABLE);
|
||||
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
|
@ -9,11 +9,13 @@
|
||||
*/
|
||||
|
||||
importScripts("resource://gre/modules/workers/require.js",
|
||||
"resource://gre/modules/reader/JSDOMParser.js",
|
||||
"resource://gre/modules/reader/Readability.js");
|
||||
"resource://gre/modules/reader/JSDOMParser.js",
|
||||
"resource://gre/modules/reader/Readability.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) {
|
||||
dump("ReaderWorker: " + args.join(" ") + "\n");
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user