mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-05 15:28:39 +09:00
Revert "Remove WebIDE devtools component."
This reverts commit 8c1500707f.
# Conflicts:
# application/basilisk/components/customizableui/CustomizableUI.jsm
This commit is contained in:
parent
4ea7de218b
commit
df89b48e30
163 changed files with 13812 additions and 0 deletions
135
devtools/client/webide/content/addons.js
Normal file
135
devtools/client/webide/content/addons.js
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/* 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/. */
|
||||
|
||||
var Cu = Components.utils;
|
||||
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const Services = require("Services");
|
||||
const {gDevTools} = require("devtools/client/framework/devtools");
|
||||
const {GetAvailableAddons, ForgetAddonsList} = require("devtools/client/webide/modules/addons");
|
||||
const Strings = Services.strings.createBundle("chrome://devtools/locale/webide.properties");
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
document.querySelector("#aboutaddons").onclick = function () {
|
||||
let browserWin = Services.wm.getMostRecentWindow(gDevTools.chromeWindowType);
|
||||
if (browserWin && browserWin.BrowserOpenAddonsMgr) {
|
||||
browserWin.BrowserOpenAddonsMgr("addons://list/extension");
|
||||
}
|
||||
};
|
||||
document.querySelector("#close").onclick = CloseUI;
|
||||
GetAvailableAddons().then(BuildUI, (e) => {
|
||||
console.error(e);
|
||||
window.alert(Strings.formatStringFromName("error_cantFetchAddonsJSON", [e], 1));
|
||||
});
|
||||
}, true);
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
ForgetAddonsList();
|
||||
}, true);
|
||||
|
||||
function CloseUI() {
|
||||
window.parent.UI.openProject();
|
||||
}
|
||||
|
||||
function BuildUI(addons) {
|
||||
BuildItem(addons.adb, "adb");
|
||||
BuildItem(addons.adapters, "adapters");
|
||||
for (let addon of addons.simulators) {
|
||||
BuildItem(addon, "simulator");
|
||||
}
|
||||
}
|
||||
|
||||
function BuildItem(addon, type) {
|
||||
|
||||
function onAddonUpdate(event, arg) {
|
||||
switch (event) {
|
||||
case "update":
|
||||
progress.removeAttribute("value");
|
||||
li.setAttribute("status", addon.status);
|
||||
status.textContent = Strings.GetStringFromName("addons_status_" + addon.status);
|
||||
break;
|
||||
case "failure":
|
||||
window.parent.UI.reportError("error_operationFail", arg);
|
||||
break;
|
||||
case "progress":
|
||||
if (arg == -1) {
|
||||
progress.removeAttribute("value");
|
||||
} else {
|
||||
progress.value = arg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let events = ["update", "failure", "progress"];
|
||||
for (let e of events) {
|
||||
addon.on(e, onAddonUpdate);
|
||||
}
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
for (let e of events) {
|
||||
addon.off(e, onAddonUpdate);
|
||||
}
|
||||
});
|
||||
|
||||
let li = document.createElement("li");
|
||||
li.setAttribute("status", addon.status);
|
||||
|
||||
let name = document.createElement("span");
|
||||
name.className = "name";
|
||||
|
||||
switch (type) {
|
||||
case "adb":
|
||||
li.setAttribute("addon", type);
|
||||
name.textContent = Strings.GetStringFromName("addons_adb_label");
|
||||
break;
|
||||
case "adapters":
|
||||
li.setAttribute("addon", type);
|
||||
try {
|
||||
name.textContent = Strings.GetStringFromName("addons_adapters_label");
|
||||
} catch (e) {
|
||||
// This code (bug 1081093) will be backported to Aurora, which doesn't
|
||||
// contain this string.
|
||||
name.textContent = "Tools Adapters Add-on";
|
||||
}
|
||||
break;
|
||||
case "simulator":
|
||||
li.setAttribute("addon", "simulator-" + addon.version);
|
||||
let stability = Strings.GetStringFromName("addons_" + addon.stability);
|
||||
name.textContent = Strings.formatStringFromName("addons_simulator_label", [addon.version, stability], 2);
|
||||
break;
|
||||
}
|
||||
|
||||
li.appendChild(name);
|
||||
|
||||
let status = document.createElement("span");
|
||||
status.className = "status";
|
||||
status.textContent = Strings.GetStringFromName("addons_status_" + addon.status);
|
||||
li.appendChild(status);
|
||||
|
||||
let installButton = document.createElement("button");
|
||||
installButton.className = "install-button";
|
||||
installButton.onclick = () => addon.install();
|
||||
installButton.textContent = Strings.GetStringFromName("addons_install_button");
|
||||
li.appendChild(installButton);
|
||||
|
||||
let uninstallButton = document.createElement("button");
|
||||
uninstallButton.className = "uninstall-button";
|
||||
uninstallButton.onclick = () => addon.uninstall();
|
||||
uninstallButton.textContent = Strings.GetStringFromName("addons_uninstall_button");
|
||||
li.appendChild(uninstallButton);
|
||||
|
||||
let progress = document.createElement("progress");
|
||||
li.appendChild(progress);
|
||||
|
||||
if (type == "adb") {
|
||||
let warning = document.createElement("p");
|
||||
warning.textContent = Strings.GetStringFromName("addons_adb_warning");
|
||||
warning.className = "warning";
|
||||
li.appendChild(warning);
|
||||
}
|
||||
|
||||
document.querySelector("ul").appendChild(li);
|
||||
}
|
||||
31
devtools/client/webide/content/addons.xhtml
Normal file
31
devtools/client/webide/content/addons.xhtml
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?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://devtools/locale/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/addons.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://webide/content/addons.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="controls">
|
||||
<a id="aboutaddons">&addons_aboutaddons;</a>
|
||||
<a id="close">&deck_close;</a>
|
||||
</div>
|
||||
|
||||
<h1>&addons_title;</h1>
|
||||
|
||||
<ul></ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
139
devtools/client/webide/content/details.js
Normal file
139
devtools/client/webide/content/details.js
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/* 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/. */
|
||||
|
||||
var Cu = Components.utils;
|
||||
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const Services = require("Services");
|
||||
const {AppManager} = require("devtools/client/webide/modules/app-manager");
|
||||
const {ProjectBuilding} = require("devtools/client/webide/modules/build");
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
document.addEventListener("visibilitychange", updateUI, true);
|
||||
AppManager.on("app-manager-update", onAppManagerUpdate);
|
||||
updateUI();
|
||||
}, true);
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
AppManager.off("app-manager-update", onAppManagerUpdate);
|
||||
}, true);
|
||||
|
||||
function onAppManagerUpdate(event, what, details) {
|
||||
if (what == "project" ||
|
||||
what == "project-validated") {
|
||||
updateUI();
|
||||
}
|
||||
}
|
||||
|
||||
function resetUI() {
|
||||
document.querySelector("#toolbar").classList.add("hidden");
|
||||
document.querySelector("#type").classList.add("hidden");
|
||||
document.querySelector("#descriptionHeader").classList.add("hidden");
|
||||
document.querySelector("#manifestURLHeader").classList.add("hidden");
|
||||
document.querySelector("#locationHeader").classList.add("hidden");
|
||||
|
||||
document.body.className = "";
|
||||
document.querySelector("#icon").src = "";
|
||||
document.querySelector("h1").textContent = "";
|
||||
document.querySelector("#description").textContent = "";
|
||||
document.querySelector("#type").textContent = "";
|
||||
document.querySelector("#manifestURL").textContent = "";
|
||||
document.querySelector("#location").textContent = "";
|
||||
|
||||
document.querySelector("#prePackageLog").hidden = true;
|
||||
|
||||
document.querySelector("#errorslist").innerHTML = "";
|
||||
document.querySelector("#warningslist").innerHTML = "";
|
||||
|
||||
}
|
||||
|
||||
function updateUI() {
|
||||
resetUI();
|
||||
|
||||
let project = AppManager.selectedProject;
|
||||
if (!project) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (project.type != "runtimeApp" && project.type != "mainProcess") {
|
||||
document.querySelector("#toolbar").classList.remove("hidden");
|
||||
document.querySelector("#locationHeader").classList.remove("hidden");
|
||||
document.querySelector("#location").textContent = project.location;
|
||||
}
|
||||
|
||||
document.body.className = project.validationStatus;
|
||||
document.querySelector("#icon").src = project.icon;
|
||||
document.querySelector("h1").textContent = project.name;
|
||||
|
||||
let manifest;
|
||||
if (project.type == "runtimeApp") {
|
||||
manifest = project.app.manifest;
|
||||
} else {
|
||||
manifest = project.manifest;
|
||||
}
|
||||
|
||||
if (manifest) {
|
||||
if (manifest.description) {
|
||||
document.querySelector("#descriptionHeader").classList.remove("hidden");
|
||||
document.querySelector("#description").textContent = manifest.description;
|
||||
}
|
||||
|
||||
document.querySelector("#type").classList.remove("hidden");
|
||||
|
||||
if (project.type == "runtimeApp") {
|
||||
let manifestURL = AppManager.getProjectManifestURL(project);
|
||||
document.querySelector("#type").textContent = manifest.type || "web";
|
||||
document.querySelector("#manifestURLHeader").classList.remove("hidden");
|
||||
document.querySelector("#manifestURL").textContent = manifestURL;
|
||||
} else if (project.type == "mainProcess") {
|
||||
document.querySelector("#type").textContent = project.name;
|
||||
} else {
|
||||
document.querySelector("#type").textContent = project.type + " " + (manifest.type || "web");
|
||||
}
|
||||
|
||||
if (project.type == "packaged") {
|
||||
let manifestURL = AppManager.getProjectManifestURL(project);
|
||||
if (manifestURL) {
|
||||
document.querySelector("#manifestURLHeader").classList.remove("hidden");
|
||||
document.querySelector("#manifestURL").textContent = manifestURL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (project.type != "runtimeApp" && project.type != "mainProcess") {
|
||||
ProjectBuilding.hasPrepackage(project).then(hasPrepackage => {
|
||||
document.querySelector("#prePackageLog").hidden = !hasPrepackage;
|
||||
});
|
||||
}
|
||||
|
||||
let errorsNode = document.querySelector("#errorslist");
|
||||
let warningsNode = document.querySelector("#warningslist");
|
||||
|
||||
if (project.errors) {
|
||||
for (let e of project.errors) {
|
||||
let li = document.createElement("li");
|
||||
li.textContent = e;
|
||||
errorsNode.appendChild(li);
|
||||
}
|
||||
}
|
||||
|
||||
if (project.warnings) {
|
||||
for (let w of project.warnings) {
|
||||
let li = document.createElement("li");
|
||||
li.textContent = w;
|
||||
warningsNode.appendChild(li);
|
||||
}
|
||||
}
|
||||
|
||||
AppManager.update("details");
|
||||
}
|
||||
|
||||
function showPrepackageLog() {
|
||||
window.top.UI.selectDeckPanel("logs");
|
||||
}
|
||||
|
||||
function removeProject() {
|
||||
AppManager.removeSelectedProject();
|
||||
}
|
||||
54
devtools/client/webide/content/details.xhtml
Normal file
54
devtools/client/webide/content/details.xhtml
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?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://devtools/locale/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/details.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://webide/content/details.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="toolbar">
|
||||
<button onclick="removeProject()">&details_removeProject_button;</button>
|
||||
<p id="validation_status">
|
||||
<span class="valid">&details_valid_header;</span>
|
||||
<span class="warning">&details_warning_header;</span>
|
||||
<span class="error">&details_error_header;</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<header>
|
||||
<img id="icon"></img>
|
||||
<div>
|
||||
<h1></h1>
|
||||
<p id="type"></p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<h3 id="descriptionHeader">&details_description;</h3>
|
||||
<p id="description"></p>
|
||||
|
||||
<h3 id="locationHeader">&details_location;</h3>
|
||||
<p id="location"></p>
|
||||
|
||||
<h3 id="manifestURLHeader">&details_manifestURL;</h3>
|
||||
<p id="manifestURL"></p>
|
||||
|
||||
<button id="prePackageLog" onclick="showPrepackageLog()" hidden="true">&details_showPrepackageLog_button;</button>
|
||||
</main>
|
||||
|
||||
<ul class="validation_messages" id="errorslist"></ul>
|
||||
<ul class="validation_messages" id="warningslist"></ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
81
devtools/client/webide/content/devicepreferences.js
Normal file
81
devtools/client/webide/content/devicepreferences.js
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/* 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/. */
|
||||
|
||||
var Cu = Components.utils;
|
||||
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const {AppManager} = require("devtools/client/webide/modules/app-manager");
|
||||
const {Connection} = require("devtools/shared/client/connection-manager");
|
||||
const ConfigView = require("devtools/client/webide/modules/config-view");
|
||||
|
||||
var configView = new ConfigView(window);
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
AppManager.on("app-manager-update", OnAppManagerUpdate);
|
||||
document.getElementById("close").onclick = CloseUI;
|
||||
document.getElementById("device-fields").onchange = UpdateField;
|
||||
document.getElementById("device-fields").onclick = CheckReset;
|
||||
document.getElementById("search-bar").onkeyup = document.getElementById("search-bar").onclick = SearchField;
|
||||
document.getElementById("custom-value").onclick = UpdateNewField;
|
||||
document.getElementById("custom-value-type").onchange = ClearNewFields;
|
||||
document.getElementById("add-custom-field").onkeyup = CheckNewFieldSubmit;
|
||||
BuildUI();
|
||||
}, true);
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
AppManager.off("app-manager-update", OnAppManagerUpdate);
|
||||
});
|
||||
|
||||
function CloseUI() {
|
||||
window.parent.UI.openProject();
|
||||
}
|
||||
|
||||
function OnAppManagerUpdate(event, what) {
|
||||
if (what == "connection" || what == "runtime-global-actors") {
|
||||
BuildUI();
|
||||
}
|
||||
}
|
||||
|
||||
function CheckNewFieldSubmit(event) {
|
||||
configView.checkNewFieldSubmit(event);
|
||||
}
|
||||
|
||||
function UpdateNewField() {
|
||||
configView.updateNewField();
|
||||
}
|
||||
|
||||
function ClearNewFields() {
|
||||
configView.clearNewFields();
|
||||
}
|
||||
|
||||
function CheckReset(event) {
|
||||
configView.checkReset(event);
|
||||
}
|
||||
|
||||
function UpdateField(event) {
|
||||
configView.updateField(event);
|
||||
}
|
||||
|
||||
function SearchField(event) {
|
||||
configView.search(event);
|
||||
}
|
||||
|
||||
var getAllPrefs; // Used by tests
|
||||
function BuildUI() {
|
||||
configView.resetTable();
|
||||
|
||||
if (AppManager.connection &&
|
||||
AppManager.connection.status == Connection.Status.CONNECTED &&
|
||||
AppManager.preferenceFront) {
|
||||
configView.front = AppManager.preferenceFront;
|
||||
configView.kind = "Pref";
|
||||
configView.includeTypeName = true;
|
||||
|
||||
getAllPrefs = AppManager.preferenceFront.getAllPrefs()
|
||||
.then(json => configView.generateDisplay(json));
|
||||
} else {
|
||||
CloseUI();
|
||||
}
|
||||
}
|
||||
49
devtools/client/webide/content/devicepreferences.xhtml
Normal file
49
devtools/client/webide/content/devicepreferences.xhtml
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<?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://devtools/locale/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/config-view.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://webide/content/devicepreferences.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div id="controls">
|
||||
<a id="close">&deck_close;</a>
|
||||
</div>
|
||||
<h1>&devicepreference_title;</h1>
|
||||
<div id="search">
|
||||
<input type="text" id="search-bar" placeholder="&devicepreference_search;"/>
|
||||
</div>
|
||||
</header>
|
||||
<table id="device-fields">
|
||||
<tr id="add-custom-field">
|
||||
<td>
|
||||
<select id="custom-value-type">
|
||||
<option value="" selected="selected">&device_typenone;</option>
|
||||
<option value="boolean">&device_typeboolean;</option>
|
||||
<option value="number">&device_typenumber;</option>
|
||||
<option value="string">&device_typestring;</option>
|
||||
</select>
|
||||
<input type="text" id="custom-value-name" placeholder="&devicepreference_newname;"/>
|
||||
</td>
|
||||
<td class="custom-input">
|
||||
<input type="text" id="custom-value-text" placeholder="&devicepreference_newtext;"/>
|
||||
</td>
|
||||
<td>
|
||||
<button id="custom-value" class="new-editable">&devicepreference_addnew;</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
81
devtools/client/webide/content/devicesettings.js
Normal file
81
devtools/client/webide/content/devicesettings.js
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/* 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/. */
|
||||
|
||||
var Cu = Components.utils;
|
||||
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const {AppManager} = require("devtools/client/webide/modules/app-manager");
|
||||
const {Connection} = require("devtools/shared/client/connection-manager");
|
||||
const ConfigView = require("devtools/client/webide/modules/config-view");
|
||||
|
||||
var configView = new ConfigView(window);
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
AppManager.on("app-manager-update", OnAppManagerUpdate);
|
||||
document.getElementById("close").onclick = CloseUI;
|
||||
document.getElementById("device-fields").onchange = UpdateField;
|
||||
document.getElementById("device-fields").onclick = CheckReset;
|
||||
document.getElementById("search-bar").onkeyup = document.getElementById("search-bar").onclick = SearchField;
|
||||
document.getElementById("custom-value").onclick = UpdateNewField;
|
||||
document.getElementById("custom-value-type").onchange = ClearNewFields;
|
||||
document.getElementById("add-custom-field").onkeyup = CheckNewFieldSubmit;
|
||||
BuildUI();
|
||||
}, true);
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
AppManager.off("app-manager-update", OnAppManagerUpdate);
|
||||
});
|
||||
|
||||
function CloseUI() {
|
||||
window.parent.UI.openProject();
|
||||
}
|
||||
|
||||
function OnAppManagerUpdate(event, what) {
|
||||
if (what == "connection" || what == "runtime-global-actors") {
|
||||
BuildUI();
|
||||
}
|
||||
}
|
||||
|
||||
function CheckNewFieldSubmit(event) {
|
||||
configView.checkNewFieldSubmit(event);
|
||||
}
|
||||
|
||||
function UpdateNewField() {
|
||||
configView.updateNewField();
|
||||
}
|
||||
|
||||
function ClearNewFields() {
|
||||
configView.clearNewFields();
|
||||
}
|
||||
|
||||
function CheckReset(event) {
|
||||
configView.checkReset(event);
|
||||
}
|
||||
|
||||
function UpdateField(event) {
|
||||
configView.updateField(event);
|
||||
}
|
||||
|
||||
function SearchField(event) {
|
||||
configView.search(event);
|
||||
}
|
||||
|
||||
var getAllSettings; // Used by tests
|
||||
function BuildUI() {
|
||||
configView.resetTable();
|
||||
|
||||
if (AppManager.connection &&
|
||||
AppManager.connection.status == Connection.Status.CONNECTED &&
|
||||
AppManager.settingsFront) {
|
||||
configView.front = AppManager.settingsFront;
|
||||
configView.kind = "Setting";
|
||||
configView.includeTypeName = false;
|
||||
|
||||
getAllSettings = AppManager.settingsFront.getAllSettings()
|
||||
.then(json => configView.generateDisplay(json));
|
||||
} else {
|
||||
CloseUI();
|
||||
}
|
||||
}
|
||||
50
devtools/client/webide/content/devicesettings.xhtml
Normal file
50
devtools/client/webide/content/devicesettings.xhtml
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
<?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://devtools/locale/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/config-view.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://webide/content/devicesettings.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div id="controls">
|
||||
<a id="close">&deck_close;</a>
|
||||
</div>
|
||||
<h1>&devicesetting_title;</h1>
|
||||
<div id="search">
|
||||
<input type="text" id="search-bar" placeholder="&devicesetting_search;"/>
|
||||
</div>
|
||||
</header>
|
||||
<table id="device-fields">
|
||||
<tr id="add-custom-field">
|
||||
<td>
|
||||
<select id="custom-value-type">
|
||||
<option value="" selected="selected">&device_typenone;</option>
|
||||
<option value="boolean">&device_typeboolean;</option>
|
||||
<option value="number">&device_typenumber;</option>
|
||||
<option value="string">&device_typestring;</option>
|
||||
<option value="object">&device_typeobject;</option>
|
||||
</select>
|
||||
<input type="text" id="custom-value-name" placeholder="&devicesetting_newname;"/>
|
||||
</td>
|
||||
<td class="custom-input">
|
||||
<input type="text" id="custom-value-text" placeholder="&devicesetting_newtext;"/>
|
||||
</td>
|
||||
<td>
|
||||
<button id="custom-value" class="new-editable">&devicesetting_addnew;</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
38
devtools/client/webide/content/jar.mn
Normal file
38
devtools/client/webide/content/jar.mn
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# 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/.
|
||||
|
||||
webide.jar:
|
||||
% content webide %content/
|
||||
content/webide.xul (webide.xul)
|
||||
content/webide.js (webide.js)
|
||||
content/newapp.xul (newapp.xul)
|
||||
content/newapp.js (newapp.js)
|
||||
content/details.xhtml (details.xhtml)
|
||||
content/details.js (details.js)
|
||||
content/addons.js (addons.js)
|
||||
content/addons.xhtml (addons.xhtml)
|
||||
content/permissionstable.js (permissionstable.js)
|
||||
content/permissionstable.xhtml (permissionstable.xhtml)
|
||||
content/runtimedetails.js (runtimedetails.js)
|
||||
content/runtimedetails.xhtml (runtimedetails.xhtml)
|
||||
content/prefs.js (prefs.js)
|
||||
content/prefs.xhtml (prefs.xhtml)
|
||||
content/monitor.xhtml (monitor.xhtml)
|
||||
content/monitor.js (monitor.js)
|
||||
content/devicepreferences.js (devicepreferences.js)
|
||||
content/devicepreferences.xhtml (devicepreferences.xhtml)
|
||||
content/devicesettings.js (devicesettings.js)
|
||||
content/devicesettings.xhtml (devicesettings.xhtml)
|
||||
content/wifi-auth.js (wifi-auth.js)
|
||||
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)
|
||||
content/runtime-panel.js (runtime-panel.js)
|
||||
content/runtime-listing.xhtml (runtime-listing.xhtml)
|
||||
content/runtime-listing.js (runtime-listing.js)
|
||||
content/simulator.js (simulator.js)
|
||||
content/simulator.xhtml (simulator.xhtml)
|
||||
70
devtools/client/webide/content/logs.js
Normal file
70
devtools/client/webide/content/logs.js
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/* 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/. */
|
||||
|
||||
var Cu = Components.utils;
|
||||
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const {AppManager} = require("devtools/client/webide/modules/app-manager");
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
|
||||
Logs.init();
|
||||
});
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
|
||||
Logs.uninit();
|
||||
});
|
||||
|
||||
const Logs = {
|
||||
init: function () {
|
||||
this.list = document.getElementById("logs");
|
||||
|
||||
Logs.onAppManagerUpdate = Logs.onAppManagerUpdate.bind(this);
|
||||
AppManager.on("app-manager-update", Logs.onAppManagerUpdate);
|
||||
|
||||
document.getElementById("close").onclick = Logs.close.bind(this);
|
||||
},
|
||||
|
||||
uninit: function () {
|
||||
AppManager.off("app-manager-update", Logs.onAppManagerUpdate);
|
||||
},
|
||||
|
||||
onAppManagerUpdate: function (event, what, details) {
|
||||
switch (what) {
|
||||
case "pre-package":
|
||||
this.prePackageLog(details);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
close: function () {
|
||||
window.parent.UI.openProject();
|
||||
},
|
||||
|
||||
prePackageLog: function (msg, details) {
|
||||
if (msg == "start") {
|
||||
this.clear();
|
||||
} else if (msg == "succeed") {
|
||||
setTimeout(function () {
|
||||
Logs.close();
|
||||
}, 1000);
|
||||
} else if (msg == "failed") {
|
||||
this.log(details);
|
||||
} else {
|
||||
this.log(msg);
|
||||
}
|
||||
},
|
||||
|
||||
clear: function () {
|
||||
this.list.innerHTML = "";
|
||||
},
|
||||
|
||||
log: function (msg) {
|
||||
let line = document.createElement("li");
|
||||
line.textContent = msg;
|
||||
this.list.appendChild(line);
|
||||
}
|
||||
};
|
||||
33
devtools/client/webide/content/logs.xhtml
Normal file
33
devtools/client/webide/content/logs.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://devtools/locale/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="resource://devtools/client/themes/common.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/logs.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://devtools/content/shared/theme-switching.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="logs.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="controls">
|
||||
<a id="close">&deck_close;</a>
|
||||
</div>
|
||||
|
||||
<h1>&logs_title;</h1>
|
||||
|
||||
<ul id="logs" class="devtools-monospace">
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
741
devtools/client/webide/content/monitor.js
Normal file
741
devtools/client/webide/content/monitor.js
Normal file
|
|
@ -0,0 +1,741 @@
|
|||
/* 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/. */
|
||||
|
||||
var Cu = Components.utils;
|
||||
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const Services = require("Services");
|
||||
const {AppManager} = require("devtools/client/webide/modules/app-manager");
|
||||
const {AppActorFront} = require("devtools/shared/apps/app-actor-front");
|
||||
const {Connection} = require("devtools/shared/client/connection-manager");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
window.addEventListener("resize", Monitor.resize);
|
||||
window.addEventListener("unload", Monitor.unload);
|
||||
|
||||
document.querySelector("#close").onclick = () => {
|
||||
window.parent.UI.openProject();
|
||||
};
|
||||
|
||||
Monitor.load();
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* The Monitor is a WebIDE tool used to display any kind of time-based data in
|
||||
* the form of graphs.
|
||||
*
|
||||
* The data can come from a Firefox OS device, simulator, or from a WebSockets
|
||||
* server running locally.
|
||||
*
|
||||
* The format of a data update is typically an object like:
|
||||
*
|
||||
* { graph: 'mygraph', curve: 'mycurve', value: 42, time: 1234 }
|
||||
*
|
||||
* or an array of such objects. For more details on the data format, see the
|
||||
* `Graph.update(data)` method.
|
||||
*/
|
||||
var Monitor = {
|
||||
|
||||
apps: new Map(),
|
||||
graphs: new Map(),
|
||||
front: null,
|
||||
socket: null,
|
||||
wstimeout: null,
|
||||
b2ginfo: false,
|
||||
b2gtimeout: null,
|
||||
|
||||
/**
|
||||
* Add new data to the graphs, create a new graph if necessary.
|
||||
*/
|
||||
update: function (data, fallback) {
|
||||
if (Array.isArray(data)) {
|
||||
data.forEach(d => Monitor.update(d, fallback));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Monitor.b2ginfo && data.graph === "USS") {
|
||||
// If we're polling b2g-info, ignore USS updates from the device's
|
||||
// USSAgents (see Monitor.pollB2GInfo()).
|
||||
return;
|
||||
}
|
||||
|
||||
if (fallback) {
|
||||
for (let key in fallback) {
|
||||
if (!data[key]) {
|
||||
data[key] = fallback[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let graph = Monitor.graphs.get(data.graph);
|
||||
if (!graph) {
|
||||
let element = document.createElement("div");
|
||||
element.classList.add("graph");
|
||||
document.body.appendChild(element);
|
||||
|
||||
graph = new Graph(data.graph, element);
|
||||
Monitor.resize(); // a scrollbar might have dis/reappeared
|
||||
Monitor.graphs.set(data.graph, graph);
|
||||
}
|
||||
graph.update(data);
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize the Monitor.
|
||||
*/
|
||||
load: function () {
|
||||
AppManager.on("app-manager-update", Monitor.onAppManagerUpdate);
|
||||
Monitor.connectToRuntime();
|
||||
Monitor.connectToWebSocket();
|
||||
},
|
||||
|
||||
/**
|
||||
* Clean up the Monitor.
|
||||
*/
|
||||
unload: function () {
|
||||
AppManager.off("app-manager-update", Monitor.onAppManagerUpdate);
|
||||
Monitor.disconnectFromRuntime();
|
||||
Monitor.disconnectFromWebSocket();
|
||||
},
|
||||
|
||||
/**
|
||||
* Resize all the graphs.
|
||||
*/
|
||||
resize: function () {
|
||||
for (let graph of Monitor.graphs.values()) {
|
||||
graph.resize();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* When WebIDE connects to a new runtime, start its data forwarders.
|
||||
*/
|
||||
onAppManagerUpdate: function (event, what, details) {
|
||||
switch (what) {
|
||||
case "runtime-global-actors":
|
||||
Monitor.connectToRuntime();
|
||||
break;
|
||||
case "connection":
|
||||
if (AppManager.connection.status == Connection.Status.DISCONNECTED) {
|
||||
Monitor.disconnectFromRuntime();
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Use an AppActorFront on a runtime to watch track its apps.
|
||||
*/
|
||||
connectToRuntime: function () {
|
||||
Monitor.pollB2GInfo();
|
||||
let client = AppManager.connection && AppManager.connection.client;
|
||||
let resp = AppManager._listTabsResponse;
|
||||
if (client && resp && !Monitor.front) {
|
||||
Monitor.front = new AppActorFront(client, resp);
|
||||
Monitor.front.watchApps(Monitor.onRuntimeAppEvent);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy our AppActorFront.
|
||||
*/
|
||||
disconnectFromRuntime: function () {
|
||||
Monitor.unpollB2GInfo();
|
||||
if (Monitor.front) {
|
||||
Monitor.front.unwatchApps(Monitor.onRuntimeAppEvent);
|
||||
Monitor.front = null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Try connecting to a local websockets server and accept updates from it.
|
||||
*/
|
||||
connectToWebSocket: function () {
|
||||
let webSocketURL = Services.prefs.getCharPref("devtools.webide.monitorWebSocketURL");
|
||||
try {
|
||||
Monitor.socket = new WebSocket(webSocketURL);
|
||||
Monitor.socket.onmessage = function (event) {
|
||||
Monitor.update(JSON.parse(event.data));
|
||||
};
|
||||
Monitor.socket.onclose = function () {
|
||||
Monitor.wstimeout = setTimeout(Monitor.connectToWebsocket, 1000);
|
||||
};
|
||||
} catch (e) {
|
||||
Monitor.wstimeout = setTimeout(Monitor.connectToWebsocket, 1000);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Used when cleaning up.
|
||||
*/
|
||||
disconnectFromWebSocket: function () {
|
||||
clearTimeout(Monitor.wstimeout);
|
||||
if (Monitor.socket) {
|
||||
Monitor.socket.onclose = () => {};
|
||||
Monitor.socket.close();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* When an app starts on the runtime, start a monitor actor for its process.
|
||||
*/
|
||||
onRuntimeAppEvent: function (type, app) {
|
||||
if (type !== "appOpen" && type !== "appClose") {
|
||||
return;
|
||||
}
|
||||
|
||||
let client = AppManager.connection.client;
|
||||
app.getForm().then(form => {
|
||||
if (type === "appOpen") {
|
||||
app.monitorClient = new MonitorClient(client, form);
|
||||
app.monitorClient.start();
|
||||
app.monitorClient.on("update", Monitor.onRuntimeUpdate);
|
||||
Monitor.apps.set(form.monitorActor, app);
|
||||
} else {
|
||||
let app = Monitor.apps.get(form.monitorActor);
|
||||
if (app) {
|
||||
app.monitorClient.stop(() => app.monitorClient.destroy());
|
||||
Monitor.apps.delete(form.monitorActor);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Accept data updates from the monitor actors of a runtime.
|
||||
*/
|
||||
onRuntimeUpdate: function (type, packet) {
|
||||
let fallback = {}, app = Monitor.apps.get(packet.from);
|
||||
if (app) {
|
||||
fallback.curve = app.manifest.name;
|
||||
}
|
||||
Monitor.update(packet.data, fallback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Bug 1047355: If possible, parsing the output of `b2g-info` has several
|
||||
* benefits over bug 1037465's multi-process USSAgent approach, notably:
|
||||
* - Works for older Firefox OS devices (pre-2.1),
|
||||
* - Doesn't need certified-apps debugging,
|
||||
* - Polling time is synchronized for all processes.
|
||||
* TODO: After bug 1043324 lands, consider removing this hack.
|
||||
*/
|
||||
pollB2GInfo: function () {
|
||||
if (AppManager.selectedRuntime) {
|
||||
let device = AppManager.selectedRuntime.device;
|
||||
if (device && device.shell) {
|
||||
device.shell("b2g-info").then(s => {
|
||||
let lines = s.split("\n");
|
||||
let line = "";
|
||||
|
||||
// Find the header row to locate NAME and USS, looks like:
|
||||
// ' NAME PID NICE USS PSS RSS VSIZE OOM_ADJ USER '.
|
||||
while (line.indexOf("NAME") < 0) {
|
||||
if (lines.length < 1) {
|
||||
// Something is wrong with this output, don't trust b2g-info.
|
||||
Monitor.unpollB2GInfo();
|
||||
return;
|
||||
}
|
||||
line = lines.shift();
|
||||
}
|
||||
let namelength = line.indexOf("NAME") + "NAME".length;
|
||||
let ussindex = line.slice(namelength).split(/\s+/).indexOf("USS");
|
||||
|
||||
// Get the NAME and USS in each following line, looks like:
|
||||
// 'Homescreen 375 18 12.6 16.3 27.1 67.8 4 app_375'.
|
||||
while (lines.length > 0 && lines[0].length > namelength) {
|
||||
line = lines.shift();
|
||||
let name = line.slice(0, namelength);
|
||||
let uss = line.slice(namelength).split(/\s+/)[ussindex];
|
||||
Monitor.update({
|
||||
curve: name.trim(),
|
||||
value: 1024 * 1024 * parseFloat(uss) // Convert MB to bytes.
|
||||
}, {
|
||||
// Note: We use the fallback object to set the graph name to 'USS'
|
||||
// so that Monitor.update() can ignore USSAgent updates.
|
||||
graph: "USS"
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Monitor.b2ginfo = true;
|
||||
Monitor.b2gtimeout = setTimeout(Monitor.pollB2GInfo, 350);
|
||||
},
|
||||
|
||||
/**
|
||||
* Polling b2g-info doesn't work or is no longer needed.
|
||||
*/
|
||||
unpollB2GInfo: function () {
|
||||
clearTimeout(Monitor.b2gtimeout);
|
||||
Monitor.b2ginfo = false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A MonitorClient is used as an actor client of a runtime's monitor actors,
|
||||
* receiving its updates.
|
||||
*/
|
||||
function MonitorClient(client, form) {
|
||||
this.client = client;
|
||||
this.actor = form.monitorActor;
|
||||
this.events = ["update"];
|
||||
|
||||
EventEmitter.decorate(this);
|
||||
this.client.registerClient(this);
|
||||
}
|
||||
MonitorClient.prototype.destroy = function () {
|
||||
this.client.unregisterClient(this);
|
||||
};
|
||||
MonitorClient.prototype.start = function () {
|
||||
this.client.request({
|
||||
to: this.actor,
|
||||
type: "start"
|
||||
});
|
||||
};
|
||||
MonitorClient.prototype.stop = function (callback) {
|
||||
this.client.request({
|
||||
to: this.actor,
|
||||
type: "stop"
|
||||
}, callback);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A Graph populates a container DOM element with an SVG graph and a legend.
|
||||
*/
|
||||
function Graph(name, element) {
|
||||
this.name = name;
|
||||
this.element = element;
|
||||
this.curves = new Map();
|
||||
this.events = new Map();
|
||||
this.ignored = new Set();
|
||||
this.enabled = true;
|
||||
this.request = null;
|
||||
|
||||
this.x = d3.time.scale();
|
||||
this.y = d3.scale.linear();
|
||||
|
||||
this.xaxis = d3.svg.axis().scale(this.x).orient("bottom");
|
||||
this.yaxis = d3.svg.axis().scale(this.y).orient("left");
|
||||
|
||||
this.xformat = d3.time.format("%I:%M:%S");
|
||||
this.yformat = this.formatter(1);
|
||||
this.yaxis.tickFormat(this.formatter(0));
|
||||
|
||||
this.line = d3.svg.line().interpolate("linear")
|
||||
.x(function (d) { return this.x(d.time); })
|
||||
.y(function (d) { return this.y(d.value); });
|
||||
|
||||
this.color = d3.scale.category10();
|
||||
|
||||
this.svg = d3.select(element).append("svg").append("g")
|
||||
.attr("transform", "translate(" + this.margin.left + "," + this.margin.top + ")");
|
||||
|
||||
this.xelement = this.svg.append("g").attr("class", "x axis").call(this.xaxis);
|
||||
this.yelement = this.svg.append("g").attr("class", "y axis").call(this.yaxis);
|
||||
|
||||
// RULERS on axes
|
||||
let xruler = this.xruler = this.svg.select(".x.axis").append("g").attr("class", "x ruler");
|
||||
xruler.append("line").attr("y2", 6);
|
||||
xruler.append("line").attr("stroke-dasharray", "1,1");
|
||||
xruler.append("text").attr("y", 9).attr("dy", ".71em");
|
||||
|
||||
let yruler = this.yruler = this.svg.select(".y.axis").append("g").attr("class", "y ruler");
|
||||
yruler.append("line").attr("x2", -6);
|
||||
yruler.append("line").attr("stroke-dasharray", "1,1");
|
||||
yruler.append("text").attr("x", -9).attr("dy", ".32em");
|
||||
|
||||
let self = this;
|
||||
|
||||
d3.select(element).select("svg")
|
||||
.on("mousemove", function () {
|
||||
let mouse = d3.mouse(this);
|
||||
self.mousex = mouse[0] - self.margin.left,
|
||||
self.mousey = mouse[1] - self.margin.top;
|
||||
|
||||
xruler.attr("transform", "translate(" + self.mousex + ",0)");
|
||||
yruler.attr("transform", "translate(0," + self.mousey + ")");
|
||||
});
|
||||
/* .on('mouseout', function() {
|
||||
self.xruler.attr('transform', 'translate(-500,0)');
|
||||
self.yruler.attr('transform', 'translate(0,-500)');
|
||||
});*/
|
||||
this.mousex = this.mousey = -500;
|
||||
|
||||
let sidebar = d3.select(this.element).append("div").attr("class", "sidebar");
|
||||
let title = sidebar.append("label").attr("class", "graph-title");
|
||||
|
||||
title.append("input")
|
||||
.attr("type", "checkbox")
|
||||
.attr("checked", "true")
|
||||
.on("click", function () { self.toggle(); });
|
||||
title.append("span").text(this.name);
|
||||
|
||||
this.legend = sidebar.append("div").attr("class", "legend");
|
||||
|
||||
this.resize = this.resize.bind(this);
|
||||
this.render = this.render.bind(this);
|
||||
this.averages = this.averages.bind(this);
|
||||
|
||||
setInterval(this.averages, 1000);
|
||||
|
||||
this.resize();
|
||||
}
|
||||
|
||||
Graph.prototype = {
|
||||
|
||||
/**
|
||||
* These margin are used to properly position the SVG graph items inside the
|
||||
* container element.
|
||||
*/
|
||||
margin: {
|
||||
top: 10,
|
||||
right: 150,
|
||||
bottom: 20,
|
||||
left: 50
|
||||
},
|
||||
|
||||
/**
|
||||
* A Graph can be collapsed by the user.
|
||||
*/
|
||||
toggle: function () {
|
||||
if (this.enabled) {
|
||||
this.element.classList.add("disabled");
|
||||
this.enabled = false;
|
||||
} else {
|
||||
this.element.classList.remove("disabled");
|
||||
this.enabled = true;
|
||||
}
|
||||
Monitor.resize();
|
||||
},
|
||||
|
||||
/**
|
||||
* If the container element is resized (e.g. because the window was resized or
|
||||
* a scrollbar dis/appeared), the graph needs to be resized as well.
|
||||
*/
|
||||
resize: function () {
|
||||
let style = getComputedStyle(this.element),
|
||||
height = parseFloat(style.height) - this.margin.top - this.margin.bottom,
|
||||
width = parseFloat(style.width) - this.margin.left - this.margin.right;
|
||||
|
||||
d3.select(this.element).select("svg")
|
||||
.attr("width", width + this.margin.left)
|
||||
.attr("height", height + this.margin.top + this.margin.bottom);
|
||||
|
||||
this.x.range([0, width]);
|
||||
this.y.range([height, 0]);
|
||||
|
||||
this.xelement.attr("transform", "translate(0," + height + ")");
|
||||
this.xruler.select("line[stroke-dasharray]").attr("y2", -height);
|
||||
this.yruler.select("line[stroke-dasharray]").attr("x2", width);
|
||||
},
|
||||
|
||||
/**
|
||||
* If the domain of the Graph's data changes (on the time axis and/or on the
|
||||
* value axis), the axes' domains need to be updated and the graph items need
|
||||
* to be rescaled in order to represent all the data.
|
||||
*/
|
||||
rescale: function () {
|
||||
let gettime = v => { return v.time; },
|
||||
getvalue = v => { return v.value; },
|
||||
ignored = c => { return this.ignored.has(c.id); };
|
||||
|
||||
let xmin = null, xmax = null, ymin = null, ymax = null;
|
||||
for (let curve of this.curves.values()) {
|
||||
if (ignored(curve)) {
|
||||
continue;
|
||||
}
|
||||
if (xmax == null || curve.xmax > xmax) {
|
||||
xmax = curve.xmax;
|
||||
}
|
||||
if (xmin == null || curve.xmin < xmin) {
|
||||
xmin = curve.xmin;
|
||||
}
|
||||
if (ymax == null || curve.ymax > ymax) {
|
||||
ymax = curve.ymax;
|
||||
}
|
||||
if (ymin == null || curve.ymin < ymin) {
|
||||
ymin = curve.ymin;
|
||||
}
|
||||
}
|
||||
for (let event of this.events.values()) {
|
||||
if (ignored(event)) {
|
||||
continue;
|
||||
}
|
||||
if (xmax == null || event.xmax > xmax) {
|
||||
xmax = event.xmax;
|
||||
}
|
||||
if (xmin == null || event.xmin < xmin) {
|
||||
xmin = event.xmin;
|
||||
}
|
||||
}
|
||||
|
||||
let oldxdomain = this.x.domain();
|
||||
if (xmin != null && xmax != null) {
|
||||
this.x.domain([xmin, xmax]);
|
||||
let newxdomain = this.x.domain();
|
||||
if (newxdomain[0] !== oldxdomain[0] || newxdomain[1] !== oldxdomain[1]) {
|
||||
this.xelement.call(this.xaxis);
|
||||
}
|
||||
}
|
||||
|
||||
let oldydomain = this.y.domain();
|
||||
if (ymin != null && ymax != null) {
|
||||
this.y.domain([ymin, ymax]).nice();
|
||||
let newydomain = this.y.domain();
|
||||
if (newydomain[0] !== oldydomain[0] || newydomain[1] !== oldydomain[1]) {
|
||||
this.yelement.call(this.yaxis);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Add new values to the graph.
|
||||
*/
|
||||
update: function (data) {
|
||||
delete data.graph;
|
||||
|
||||
let time = data.time || Date.now();
|
||||
delete data.time;
|
||||
|
||||
let curve = data.curve;
|
||||
delete data.curve;
|
||||
|
||||
// Single curve value, e.g. { curve: 'memory', value: 42, time: 1234 }.
|
||||
if ("value" in data) {
|
||||
this.push(this.curves, curve, [{time: time, value: data.value}]);
|
||||
delete data.value;
|
||||
}
|
||||
|
||||
// Several curve values, e.g. { curve: 'memory', values: [{value: 42, time: 1234}] }.
|
||||
if ("values" in data) {
|
||||
this.push(this.curves, curve, data.values);
|
||||
delete data.values;
|
||||
}
|
||||
|
||||
// Punctual event, e.g. { event: 'gc', time: 1234 },
|
||||
// event with duration, e.g. { event: 'jank', duration: 425, time: 1234 }.
|
||||
if ("event" in data) {
|
||||
this.push(this.events, data.event, [{time: time, value: data.duration}]);
|
||||
delete data.event;
|
||||
delete data.duration;
|
||||
}
|
||||
|
||||
// Remaining keys are curves, e.g. { time: 1234, memory: 42, battery: 13, temperature: 45 }.
|
||||
for (let key in data) {
|
||||
this.push(this.curves, key, [{time: time, value: data[key]}]);
|
||||
}
|
||||
|
||||
// If no render is currently pending, request one.
|
||||
if (this.enabled && !this.request) {
|
||||
this.request = requestAnimationFrame(this.render);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Insert new data into the graph's data structures.
|
||||
*/
|
||||
push: function (collection, id, values) {
|
||||
|
||||
// Note: collection is either `this.curves` or `this.events`.
|
||||
let item = collection.get(id);
|
||||
if (!item) {
|
||||
item = { id: id, values: [], xmin: null, xmax: null, ymin: 0, ymax: null, average: 0 };
|
||||
collection.set(id, item);
|
||||
}
|
||||
|
||||
for (let v of values) {
|
||||
let time = new Date(v.time), value = +v.value;
|
||||
// Update the curve/event's domain values.
|
||||
if (item.xmax == null || time > item.xmax) {
|
||||
item.xmax = time;
|
||||
}
|
||||
if (item.xmin == null || time < item.xmin) {
|
||||
item.xmin = time;
|
||||
}
|
||||
if (item.ymax == null || value > item.ymax) {
|
||||
item.ymax = value;
|
||||
}
|
||||
if (item.ymin == null || value < item.ymin) {
|
||||
item.ymin = value;
|
||||
}
|
||||
// Note: A curve's average is not computed here. Call `graph.averages()`.
|
||||
item.values.push({ time: time, value: value });
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Render the SVG graph with curves, events, crosshair and legend.
|
||||
*/
|
||||
render: function () {
|
||||
this.request = null;
|
||||
this.rescale();
|
||||
|
||||
|
||||
// DATA
|
||||
|
||||
let self = this,
|
||||
getid = d => { return d.id; },
|
||||
gettime = d => { return d.time.getTime(); },
|
||||
getline = d => { return self.line(d.values); },
|
||||
getcolor = d => { return self.color(d.id); },
|
||||
getvalues = d => { return d.values; },
|
||||
ignored = d => { return self.ignored.has(d.id); };
|
||||
|
||||
// Convert our maps to arrays for d3.
|
||||
let curvedata = [...this.curves.values()],
|
||||
eventdata = [...this.events.values()],
|
||||
data = curvedata.concat(eventdata);
|
||||
|
||||
|
||||
// CURVES
|
||||
|
||||
// Map curve data to curve elements.
|
||||
let curves = this.svg.selectAll(".curve").data(curvedata, getid);
|
||||
|
||||
// Create new curves (no element corresponding to the data).
|
||||
curves.enter().append("g").attr("class", "curve").append("path")
|
||||
.style("stroke", getcolor);
|
||||
|
||||
// Delete old curves (elements corresponding to data not present anymore).
|
||||
curves.exit().remove();
|
||||
|
||||
// Update all curves from data.
|
||||
this.svg.selectAll(".curve").select("path")
|
||||
.attr("d", d => { return ignored(d) ? "" : getline(d); });
|
||||
|
||||
let height = parseFloat(getComputedStyle(this.element).height) - this.margin.top - this.margin.bottom;
|
||||
|
||||
|
||||
// EVENTS
|
||||
|
||||
// Map event data to event elements.
|
||||
let events = this.svg.selectAll(".event-slot").data(eventdata, getid);
|
||||
|
||||
// Create new events.
|
||||
events.enter().append("g").attr("class", "event-slot");
|
||||
|
||||
// Remove old events.
|
||||
events.exit().remove();
|
||||
|
||||
// Get all occurences of an event, and map its data to them.
|
||||
let lines = this.svg.selectAll(".event-slot")
|
||||
.style("stroke", d => { return ignored(d) ? "none" : getcolor(d); })
|
||||
.selectAll(".event")
|
||||
.data(getvalues, gettime);
|
||||
|
||||
// Create new event occurrence.
|
||||
lines.enter().append("line").attr("class", "event").attr("y2", height);
|
||||
|
||||
// Delete old event occurrence.
|
||||
lines.exit().remove();
|
||||
|
||||
// Update all event occurrences from data.
|
||||
this.svg.selectAll(".event")
|
||||
.attr("transform", d => { return "translate(" + self.x(d.time) + ",0)"; });
|
||||
|
||||
|
||||
// CROSSHAIR
|
||||
|
||||
// TODO select curves and events, intersect with curves and show values/hovers
|
||||
// e.g. look like http://code.shutterstock.com/rickshaw/examples/lines.html
|
||||
|
||||
// Update crosshair labels on each axis.
|
||||
this.xruler.select("text").text(self.xformat(self.x.invert(self.mousex)));
|
||||
this.yruler.select("text").text(self.yformat(self.y.invert(self.mousey)));
|
||||
|
||||
|
||||
// LEGEND
|
||||
|
||||
// Map data to legend elements.
|
||||
let legends = this.legend.selectAll("label").data(data, getid);
|
||||
|
||||
// Update averages.
|
||||
legends.attr("title", c => { return "Average: " + self.yformat(c.average); });
|
||||
|
||||
// Create new legends.
|
||||
let newlegend = legends.enter().append("label");
|
||||
newlegend.append("input").attr("type", "checkbox").attr("checked", "true").on("click", function (c) {
|
||||
if (ignored(c)) {
|
||||
this.parentElement.classList.remove("disabled");
|
||||
self.ignored.delete(c.id);
|
||||
} else {
|
||||
this.parentElement.classList.add("disabled");
|
||||
self.ignored.add(c.id);
|
||||
}
|
||||
self.update({}); // if no re-render is pending, request one.
|
||||
});
|
||||
newlegend.append("span").attr("class", "legend-color").style("background-color", getcolor);
|
||||
newlegend.append("span").attr("class", "legend-id").text(getid);
|
||||
|
||||
// Delete old legends.
|
||||
legends.exit().remove();
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a SI value formatter with a given precision.
|
||||
*/
|
||||
formatter: function (decimals) {
|
||||
return value => {
|
||||
// Don't use sub-unit SI prefixes (milli, micro, etc.).
|
||||
if (Math.abs(value) < 1) return value.toFixed(decimals);
|
||||
// SI prefix, e.g. 1234567 will give '1.2M' at precision 1.
|
||||
let prefix = d3.formatPrefix(value);
|
||||
return prefix.scale(value).toFixed(decimals) + prefix.symbol;
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Compute the average of each time series.
|
||||
*/
|
||||
averages: function () {
|
||||
for (let c of this.curves.values()) {
|
||||
let length = c.values.length;
|
||||
if (length > 0) {
|
||||
let total = 0;
|
||||
c.values.forEach(v => total += v.value);
|
||||
c.average = (total / length);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Bisect a time serie to find the data point immediately left of `time`.
|
||||
*/
|
||||
bisectTime: d3.bisector(d => d.time).left,
|
||||
|
||||
/**
|
||||
* Get all curve values at a given time.
|
||||
*/
|
||||
valuesAt: function (time) {
|
||||
let values = { time: time };
|
||||
|
||||
for (let id of this.curves.keys()) {
|
||||
let curve = this.curves.get(id);
|
||||
|
||||
// Find the closest value just before `time`.
|
||||
let i = this.bisectTime(curve.values, time);
|
||||
if (i < 0) {
|
||||
// Curve starts after `time`, use first value.
|
||||
values[id] = curve.values[0].value;
|
||||
} else if (i > curve.values.length - 2) {
|
||||
// Curve ends before `time`, use last value.
|
||||
values[id] = curve.values[curve.values.length - 1].value;
|
||||
} else {
|
||||
// Curve has two values around `time`, interpolate.
|
||||
let v1 = curve.values[i],
|
||||
v2 = curve.values[i + 1],
|
||||
delta = (time - v1.time) / (v2.time - v1.time);
|
||||
values[id] = v1.value + (v2.value - v1.time) * delta;
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
};
|
||||
31
devtools/client/webide/content/monitor.xhtml
Normal file
31
devtools/client/webide/content/monitor.xhtml
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?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://devtools/locale/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/monitor.css" type="text/css"/>
|
||||
<script src="chrome://devtools/content/shared/vendor/d3.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="monitor.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="controls">
|
||||
<a href="https://developer.mozilla.org/docs/Tools/WebIDE/Monitor" target="_blank">&monitor_help;</a>
|
||||
<a id="close">&deck_close;</a>
|
||||
</div>
|
||||
|
||||
<h1>&monitor_title;</h1>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
7
devtools/client/webide/content/moz.build
Normal file
7
devtools/client/webide/content/moz.build
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
175
devtools/client/webide/content/newapp.js
Normal file
175
devtools/client/webide/content/newapp.js
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
var Cc = Components.classes;
|
||||
var Cu = Components.utils;
|
||||
var Ci = Components.interfaces;
|
||||
|
||||
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||
const Services = require("Services");
|
||||
const {FileUtils} = require("resource://gre/modules/FileUtils.jsm");
|
||||
const {AppProjects} = require("devtools/client/webide/modules/app-projects");
|
||||
const {AppManager} = require("devtools/client/webide/modules/app-manager");
|
||||
const {getJSON} = require("devtools/client/shared/getjson");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ZipUtils", "resource://gre/modules/ZipUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Downloads", "resource://gre/modules/Downloads.jsm");
|
||||
|
||||
const TEMPLATES_URL = "devtools.webide.templatesURL";
|
||||
|
||||
var gTemplateList = null;
|
||||
|
||||
// See bug 989619
|
||||
console.log = console.log.bind(console);
|
||||
console.warn = console.warn.bind(console);
|
||||
console.error = console.error.bind(console);
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
let projectNameNode = document.querySelector("#project-name");
|
||||
projectNameNode.addEventListener("input", canValidate, true);
|
||||
getTemplatesJSON();
|
||||
}, true);
|
||||
|
||||
function getTemplatesJSON() {
|
||||
getJSON(TEMPLATES_URL).then(list => {
|
||||
if (!Array.isArray(list)) {
|
||||
throw new Error("JSON response not an array");
|
||||
}
|
||||
if (list.length == 0) {
|
||||
throw new Error("JSON response is an empty array");
|
||||
}
|
||||
gTemplateList = list;
|
||||
let templatelistNode = document.querySelector("#templatelist");
|
||||
templatelistNode.innerHTML = "";
|
||||
for (let template of list) {
|
||||
let richlistitemNode = document.createElement("richlistitem");
|
||||
let imageNode = document.createElement("image");
|
||||
imageNode.setAttribute("src", template.icon);
|
||||
let labelNode = document.createElement("label");
|
||||
labelNode.setAttribute("value", template.name);
|
||||
let descriptionNode = document.createElement("description");
|
||||
descriptionNode.textContent = template.description;
|
||||
let vboxNode = document.createElement("vbox");
|
||||
vboxNode.setAttribute("flex", "1");
|
||||
richlistitemNode.appendChild(imageNode);
|
||||
vboxNode.appendChild(labelNode);
|
||||
vboxNode.appendChild(descriptionNode);
|
||||
richlistitemNode.appendChild(vboxNode);
|
||||
templatelistNode.appendChild(richlistitemNode);
|
||||
}
|
||||
templatelistNode.selectedIndex = 0;
|
||||
|
||||
/* Chrome mochitest support */
|
||||
let testOptions = window.arguments[0].testOptions;
|
||||
if (testOptions) {
|
||||
templatelistNode.selectedIndex = testOptions.index;
|
||||
document.querySelector("#project-name").value = testOptions.name;
|
||||
doOK();
|
||||
}
|
||||
}, (e) => {
|
||||
failAndBail("Can't download app templates: " + e);
|
||||
});
|
||||
}
|
||||
|
||||
function failAndBail(msg) {
|
||||
let promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService);
|
||||
promptService.alert(window, "error", msg);
|
||||
window.close();
|
||||
}
|
||||
|
||||
function canValidate() {
|
||||
let projectNameNode = document.querySelector("#project-name");
|
||||
let dialogNode = document.querySelector("dialog");
|
||||
if (projectNameNode.value.length > 0) {
|
||||
dialogNode.removeAttribute("buttondisabledaccept");
|
||||
} else {
|
||||
dialogNode.setAttribute("buttondisabledaccept", "true");
|
||||
}
|
||||
}
|
||||
|
||||
function doOK() {
|
||||
let projectName = document.querySelector("#project-name").value;
|
||||
|
||||
if (!projectName) {
|
||||
console.error("No project name");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!gTemplateList) {
|
||||
console.error("No template index");
|
||||
return false;
|
||||
}
|
||||
|
||||
let templatelistNode = document.querySelector("#templatelist");
|
||||
if (templatelistNode.selectedIndex < 0) {
|
||||
console.error("No template selected");
|
||||
return false;
|
||||
}
|
||||
|
||||
let folder;
|
||||
|
||||
/* Chrome mochitest support */
|
||||
let testOptions = window.arguments[0].testOptions;
|
||||
if (testOptions) {
|
||||
folder = testOptions.folder;
|
||||
} else {
|
||||
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
|
||||
fp.init(window, "Select directory where to create app directory", Ci.nsIFilePicker.modeGetFolder);
|
||||
let res = fp.show();
|
||||
if (res == Ci.nsIFilePicker.returnCancel) {
|
||||
console.error("No directory selected");
|
||||
return false;
|
||||
}
|
||||
folder = fp.file;
|
||||
}
|
||||
|
||||
// Create subfolder with fs-friendly name of project
|
||||
let subfolder = projectName.replace(/[\\/:*?"<>|]/g, "").toLowerCase();
|
||||
let win = Services.wm.getMostRecentWindow("devtools:webide");
|
||||
folder.append(subfolder);
|
||||
|
||||
try {
|
||||
folder.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
} catch (e) {
|
||||
win.UI.reportError("error_folderCreationFailed");
|
||||
window.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Download boilerplate zip
|
||||
let template = gTemplateList[templatelistNode.selectedIndex];
|
||||
let source = template.file;
|
||||
let target = folder.clone();
|
||||
target.append(subfolder + ".zip");
|
||||
|
||||
let bail = (e) => {
|
||||
console.error(e);
|
||||
window.close();
|
||||
};
|
||||
|
||||
Downloads.fetch(source, target).then(() => {
|
||||
ZipUtils.extractFiles(target, folder);
|
||||
target.remove(false);
|
||||
AppProjects.addPackaged(folder).then((project) => {
|
||||
window.arguments[0].location = project.location;
|
||||
AppManager.validateAndUpdateProject(project).then(() => {
|
||||
if (project.manifest) {
|
||||
project.manifest.name = projectName;
|
||||
AppManager.writeManifest(project).then(() => {
|
||||
AppManager.validateAndUpdateProject(project).then(
|
||||
() => {window.close();}, bail);
|
||||
}, bail);
|
||||
} else {
|
||||
bail("Manifest not found");
|
||||
}
|
||||
}, bail);
|
||||
}, bail);
|
||||
}, bail);
|
||||
|
||||
return false;
|
||||
}
|
||||
33
devtools/client/webide/content/newapp.xul
Normal file
33
devtools/client/webide/content/newapp.xul
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % webideDTD SYSTEM "chrome://devtools/locale/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/global.css"?>
|
||||
<?xml-stylesheet href="chrome://webide/skin/newapp.css"?>
|
||||
|
||||
<dialog id="webide:newapp" title="&newAppWindowTitle;"
|
||||
width="600" height="400"
|
||||
buttons="accept,cancel"
|
||||
ondialogaccept="return doOK();"
|
||||
buttondisabledaccept="true"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/javascript" src="newapp.js"></script>
|
||||
<label class="header-name" value="&newAppHeader;"/>
|
||||
|
||||
<richlistbox id="templatelist" flex="1">
|
||||
<description>&newAppLoadingTemplate;</description>
|
||||
</richlistbox>
|
||||
<vbox>
|
||||
<label class="header-name" control="project-name" value="&newAppProjectName;"/>
|
||||
<textbox id="project-name"/>
|
||||
</vbox>
|
||||
|
||||
</dialog>
|
||||
78
devtools/client/webide/content/permissionstable.js
Normal file
78
devtools/client/webide/content/permissionstable.js
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/* 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/. */
|
||||
|
||||
var Cu = Components.utils;
|
||||
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const Services = require("Services");
|
||||
const {AppManager} = require("devtools/client/webide/modules/app-manager");
|
||||
const {Connection} = require("devtools/shared/client/connection-manager");
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
document.querySelector("#close").onclick = CloseUI;
|
||||
AppManager.on("app-manager-update", OnAppManagerUpdate);
|
||||
BuildUI();
|
||||
}, true);
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
AppManager.off("app-manager-update", OnAppManagerUpdate);
|
||||
});
|
||||
|
||||
function CloseUI() {
|
||||
window.parent.UI.openProject();
|
||||
}
|
||||
|
||||
function OnAppManagerUpdate(event, what) {
|
||||
if (what == "connection" || what == "runtime-global-actors") {
|
||||
BuildUI();
|
||||
}
|
||||
}
|
||||
|
||||
function generateFields(json) {
|
||||
let table = document.querySelector("table");
|
||||
let permissionsTable = json.rawPermissionsTable;
|
||||
for (let name in permissionsTable) {
|
||||
let tr = document.createElement("tr");
|
||||
tr.className = "line";
|
||||
let td = document.createElement("td");
|
||||
td.textContent = name;
|
||||
tr.appendChild(td);
|
||||
for (let type of ["app", "privileged", "certified"]) {
|
||||
let td = document.createElement("td");
|
||||
if (permissionsTable[name][type] == json.ALLOW_ACTION) {
|
||||
td.textContent = "✓";
|
||||
td.className = "permallow";
|
||||
}
|
||||
if (permissionsTable[name][type] == json.PROMPT_ACTION) {
|
||||
td.textContent = "!";
|
||||
td.className = "permprompt";
|
||||
}
|
||||
if (permissionsTable[name][type] == json.DENY_ACTION) {
|
||||
td.textContent = "✕";
|
||||
td.className = "permdeny";
|
||||
}
|
||||
tr.appendChild(td);
|
||||
}
|
||||
table.appendChild(tr);
|
||||
}
|
||||
}
|
||||
|
||||
var getRawPermissionsTablePromise; // Used by tests
|
||||
function BuildUI() {
|
||||
let table = document.querySelector("table");
|
||||
let lines = table.querySelectorAll(".line");
|
||||
for (let line of lines) {
|
||||
line.remove();
|
||||
}
|
||||
|
||||
if (AppManager.connection &&
|
||||
AppManager.connection.status == Connection.Status.CONNECTED &&
|
||||
AppManager.deviceFront) {
|
||||
getRawPermissionsTablePromise = AppManager.deviceFront.getRawPermissionsTable()
|
||||
.then(json => generateFields(json));
|
||||
} else {
|
||||
CloseUI();
|
||||
}
|
||||
}
|
||||
36
devtools/client/webide/content/permissionstable.xhtml
Normal file
36
devtools/client/webide/content/permissionstable.xhtml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<?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://devtools/locale/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/permissionstable.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://webide/content/permissionstable.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="controls">
|
||||
<a id="close">&deck_close;</a>
|
||||
</div>
|
||||
|
||||
<h1>&permissionstable_title;</h1>
|
||||
|
||||
<table class="permissionstable">
|
||||
<tr>
|
||||
<th>&permissionstable_name_header;</th>
|
||||
<th>type:web</th>
|
||||
<th>type:privileged</th>
|
||||
<th>type:certified</th>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
108
devtools/client/webide/content/prefs.js
Normal file
108
devtools/client/webide/content/prefs.js
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Cu = Components.utils;
|
||||
const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
|
||||
// Listen to preference changes
|
||||
let inputs = document.querySelectorAll("[data-pref]");
|
||||
for (let i of inputs) {
|
||||
let pref = i.dataset.pref;
|
||||
Services.prefs.addObserver(pref, FillForm, false);
|
||||
i.addEventListener("change", SaveForm, false);
|
||||
}
|
||||
|
||||
// Buttons
|
||||
document.querySelector("#close").onclick = CloseUI;
|
||||
document.querySelector("#restore").onclick = RestoreDefaults;
|
||||
document.querySelector("#manageComponents").onclick = ShowAddons;
|
||||
|
||||
// Initialize the controls
|
||||
FillForm();
|
||||
|
||||
}, true);
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
let inputs = document.querySelectorAll("[data-pref]");
|
||||
for (let i of inputs) {
|
||||
let pref = i.dataset.pref;
|
||||
i.removeEventListener("change", SaveForm, false);
|
||||
Services.prefs.removeObserver(pref, FillForm, false);
|
||||
}
|
||||
}, true);
|
||||
|
||||
function CloseUI() {
|
||||
window.parent.UI.openProject();
|
||||
}
|
||||
|
||||
function ShowAddons() {
|
||||
window.parent.Cmds.showAddons();
|
||||
}
|
||||
|
||||
function FillForm() {
|
||||
let inputs = document.querySelectorAll("[data-pref]");
|
||||
for (let i of inputs) {
|
||||
let pref = i.dataset.pref;
|
||||
let val = GetPref(pref);
|
||||
if (i.type == "checkbox") {
|
||||
i.checked = val;
|
||||
} else {
|
||||
i.value = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function SaveForm(e) {
|
||||
let inputs = document.querySelectorAll("[data-pref]");
|
||||
for (let i of inputs) {
|
||||
let pref = i.dataset.pref;
|
||||
if (i.type == "checkbox") {
|
||||
SetPref(pref, i.checked);
|
||||
} else {
|
||||
SetPref(pref, i.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function GetPref(name) {
|
||||
let type = Services.prefs.getPrefType(name);
|
||||
switch (type) {
|
||||
case Services.prefs.PREF_STRING:
|
||||
return Services.prefs.getCharPref(name);
|
||||
case Services.prefs.PREF_INT:
|
||||
return Services.prefs.getIntPref(name);
|
||||
case Services.prefs.PREF_BOOL:
|
||||
return Services.prefs.getBoolPref(name);
|
||||
default:
|
||||
throw new Error("Unknown type");
|
||||
}
|
||||
}
|
||||
|
||||
function SetPref(name, value) {
|
||||
let type = Services.prefs.getPrefType(name);
|
||||
switch (type) {
|
||||
case Services.prefs.PREF_STRING:
|
||||
return Services.prefs.setCharPref(name, value);
|
||||
case Services.prefs.PREF_INT:
|
||||
return Services.prefs.setIntPref(name, value);
|
||||
case Services.prefs.PREF_BOOL:
|
||||
return Services.prefs.setBoolPref(name, value);
|
||||
default:
|
||||
throw new Error("Unknown type");
|
||||
}
|
||||
}
|
||||
|
||||
function RestoreDefaults() {
|
||||
let inputs = document.querySelectorAll("[data-pref]");
|
||||
for (let i of inputs) {
|
||||
let pref = i.dataset.pref;
|
||||
Services.prefs.clearUserPref(pref);
|
||||
}
|
||||
}
|
||||
112
devtools/client/webide/content/prefs.xhtml
Normal file
112
devtools/client/webide/content/prefs.xhtml
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
<?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://devtools/locale/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://webide/content/prefs.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="controls">
|
||||
<a id="restore">&prefs_restore;</a>
|
||||
<a id="manageComponents">&prefs_manage_components;</a>
|
||||
<a id="close">&deck_close;</a>
|
||||
</div>
|
||||
|
||||
<h1>&prefs_title;</h1>
|
||||
|
||||
<h2>&prefs_general_title;</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<label title="&prefs_options_showeditor_tooltip;">
|
||||
<input type="checkbox" data-pref="devtools.webide.showProjectEditor"/>
|
||||
<span>&prefs_options_showeditor;</span>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label title="&prefs_options_rememberlastproject_tooltip;">
|
||||
<input type="checkbox" data-pref="devtools.webide.restoreLastProject"/>
|
||||
<span>&prefs_options_rememberlastproject;</span>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label title="&prefs_options_autoconnectruntime_tooltip;">
|
||||
<input type="checkbox" data-pref="devtools.webide.autoConnectRuntime"/>
|
||||
<span>&prefs_options_autoconnectruntime;</span>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="text-input" title="&prefs_options_templatesurl_tooltip;">
|
||||
<span>&prefs_options_templatesurl;</span>
|
||||
<input data-pref="devtools.webide.templatesURL"/>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>&prefs_editor_title;</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<label><span>&prefs_options_tabsize;</span>
|
||||
<select data-pref="devtools.editor.tabsize">
|
||||
<option value="2">2</option>
|
||||
<option value="4">4</option>
|
||||
<option value="8">8</option>
|
||||
</select>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label title="&prefs_options_expandtab_tooltip;">
|
||||
<input type="checkbox" data-pref="devtools.editor.expandtab"/>
|
||||
<span>&prefs_options_expandtab;</span>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label title="&prefs_options_detectindentation_tooltip;">
|
||||
<input type="checkbox" data-pref="devtools.editor.detectindentation"/>
|
||||
<span>&prefs_options_detectindentation;</span>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label title="&prefs_options_autocomplete_tooltip;">
|
||||
<input type="checkbox" data-pref="devtools.editor.autocomplete"/>
|
||||
<span>&prefs_options_autocomplete;</span>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label title="&prefs_options_autoclosebrackets_tooltip;">
|
||||
<input type="checkbox" data-pref="devtools.editor.autoclosebrackets"/>
|
||||
<span>&prefs_options_autoclosebrackets;</span>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label title="&prefs_options_autosavefiles_tooltip;">
|
||||
<input type="checkbox" data-pref="devtools.webide.autosaveFiles"/>
|
||||
<span>&prefs_options_autosavefiles;</span>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label><span>&prefs_options_keybindings;</span>
|
||||
<select data-pref="devtools.editor.keymap">
|
||||
<option value="default">&prefs_options_keybindings_default;</option>
|
||||
<option value="vim">Vim</option>
|
||||
<option value="emacs">Emacs</option>
|
||||
<option value="sublime">Sublime</option>
|
||||
</select>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
42
devtools/client/webide/content/project-listing.js
Normal file
42
devtools/client/webide/content/project-listing.js
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/* 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/. */
|
||||
|
||||
/* eslint-env browser */
|
||||
|
||||
var Cu = Components.utils;
|
||||
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const ProjectList = require("devtools/client/webide/modules/project-list");
|
||||
|
||||
var projectList = new ProjectList(window, window.parent);
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad, true);
|
||||
document.getElementById("new-app").onclick = CreateNewApp;
|
||||
document.getElementById("hosted-app").onclick = ImportHostedApp;
|
||||
document.getElementById("packaged-app").onclick = ImportPackagedApp;
|
||||
document.getElementById("refresh-tabs").onclick = RefreshTabs;
|
||||
projectList.update();
|
||||
projectList.updateCommands();
|
||||
}, true);
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
projectList.destroy();
|
||||
});
|
||||
|
||||
function RefreshTabs() {
|
||||
projectList.refreshTabs();
|
||||
}
|
||||
|
||||
function CreateNewApp() {
|
||||
projectList.newApp();
|
||||
}
|
||||
|
||||
function ImportHostedApp() {
|
||||
projectList.importHostedApp();
|
||||
}
|
||||
|
||||
function ImportPackagedApp() {
|
||||
projectList.importPackagedApp();
|
||||
}
|
||||
35
devtools/client/webide/content/project-listing.xhtml
Normal file
35
devtools/client/webide/content/project-listing.xhtml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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://devtools/locale/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/panel-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;
|
||||
<button class="project-panel-item-refreshtabs refresh-icon" id="refresh-tabs" title="&projectMenu_refreshTabs_label;"></button>
|
||||
</label>
|
||||
<div id="project-panel-tabs"/>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
11
devtools/client/webide/content/project-panel.js
Normal file
11
devtools/client/webide/content/project-panel.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/* 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/. */
|
||||
|
||||
var ProjectPanel = {
|
||||
// TODO: Expand function to save toggle state.
|
||||
toggleSidebar: function () {
|
||||
document.querySelector("#project-listing-panel").setAttribute("sidebar-displayed", true);
|
||||
document.querySelector("#project-listing-splitter").setAttribute("sidebar-displayed", true);
|
||||
}
|
||||
};
|
||||
66
devtools/client/webide/content/runtime-listing.js
Normal file
66
devtools/client/webide/content/runtime-listing.js
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/* 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/. */
|
||||
|
||||
var Cu = Components.utils;
|
||||
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const RuntimeList = require("devtools/client/webide/modules/runtime-list");
|
||||
|
||||
var runtimeList = new RuntimeList(window, window.parent);
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad, true);
|
||||
document.getElementById("runtime-screenshot").onclick = TakeScreenshot;
|
||||
document.getElementById("runtime-permissions").onclick = ShowPermissionsTable;
|
||||
document.getElementById("runtime-details").onclick = ShowRuntimeDetails;
|
||||
document.getElementById("runtime-disconnect").onclick = DisconnectRuntime;
|
||||
document.getElementById("runtime-preferences").onclick = ShowDevicePreferences;
|
||||
document.getElementById("runtime-settings").onclick = ShowSettings;
|
||||
document.getElementById("runtime-panel-installsimulator").onclick = ShowAddons;
|
||||
document.getElementById("runtime-panel-noadbhelper").onclick = ShowAddons;
|
||||
document.getElementById("runtime-panel-nousbdevice").onclick = ShowTroubleShooting;
|
||||
document.getElementById("refresh-devices").onclick = RefreshScanners;
|
||||
runtimeList.update();
|
||||
runtimeList.updateCommands();
|
||||
}, true);
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
runtimeList.destroy();
|
||||
});
|
||||
|
||||
function TakeScreenshot() {
|
||||
runtimeList.takeScreenshot();
|
||||
}
|
||||
|
||||
function ShowRuntimeDetails() {
|
||||
runtimeList.showRuntimeDetails();
|
||||
}
|
||||
|
||||
function ShowPermissionsTable() {
|
||||
runtimeList.showPermissionsTable();
|
||||
}
|
||||
|
||||
function ShowDevicePreferences() {
|
||||
runtimeList.showDevicePreferences();
|
||||
}
|
||||
|
||||
function ShowSettings() {
|
||||
runtimeList.showSettings();
|
||||
}
|
||||
|
||||
function RefreshScanners() {
|
||||
runtimeList.refreshScanners();
|
||||
}
|
||||
|
||||
function DisconnectRuntime() {
|
||||
window.parent.Cmds.disconnectRuntime();
|
||||
}
|
||||
|
||||
function ShowAddons() {
|
||||
runtimeList.showAddons();
|
||||
}
|
||||
|
||||
function ShowTroubleShooting() {
|
||||
runtimeList.showTroubleShooting();
|
||||
}
|
||||
45
devtools/client/webide/content/runtime-listing.xhtml
Normal file
45
devtools/client/webide/content/runtime-listing.xhtml
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<?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://devtools/locale/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/panel-listing.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://webide/content/runtime-listing.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="runtime-panel">
|
||||
<div id="runtime-panel-box">
|
||||
<label class="panel-header">&runtimePanel_usb;
|
||||
<button class="runtime-panel-item-refreshdevices refresh-icon" id="refresh-devices" title="&runtimePanel_refreshDevices_label;"></button>
|
||||
</label>
|
||||
<button class="panel-item" id="runtime-panel-nousbdevice">&runtimePanel_nousbdevice;</button>
|
||||
<button class="panel-item" id="runtime-panel-noadbhelper">&runtimePanel_noadbhelper;</button>
|
||||
<div id="runtime-panel-usb"></div>
|
||||
<label class="panel-header" id="runtime-header-wifi">&runtimePanel_wifi;</label>
|
||||
<div id="runtime-panel-wifi"></div>
|
||||
<label class="panel-header">&runtimePanel_simulator;</label>
|
||||
<div id="runtime-panel-simulator"></div>
|
||||
<button class="panel-item" id="runtime-panel-installsimulator">&runtimePanel_installsimulator;</button>
|
||||
<label class="panel-header">&runtimePanel_other;</label>
|
||||
<div id="runtime-panel-other"></div>
|
||||
<div id="runtime-actions">
|
||||
<button class="panel-item" id="runtime-details">&runtimeMenu_showDetails_label;</button>
|
||||
<button class="panel-item" id="runtime-permissions">&runtimeMenu_showPermissionTable_label;</button>
|
||||
<button class="panel-item" id="runtime-preferences">&runtimeMenu_showDevicePrefs_label;</button>
|
||||
<button class="panel-item" id="runtime-settings">&runtimeMenu_showSettings_label;</button>
|
||||
<button class="panel-item" id="runtime-screenshot">&runtimeMenu_takeScreenshot_label;</button>
|
||||
<button class="panel-item" id="runtime-disconnect">&runtimeMenu_disconnect_label;</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
11
devtools/client/webide/content/runtime-panel.js
Normal file
11
devtools/client/webide/content/runtime-panel.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/* 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/. */
|
||||
|
||||
var RuntimePanel = {
|
||||
// TODO: Expand function to save toggle state.
|
||||
toggleSidebar: function () {
|
||||
document.querySelector("#runtime-listing-panel").setAttribute("sidebar-displayed", true);
|
||||
document.querySelector("#runtime-listing-splitter").setAttribute("sidebar-displayed", true);
|
||||
}
|
||||
};
|
||||
153
devtools/client/webide/content/runtimedetails.js
Normal file
153
devtools/client/webide/content/runtimedetails.js
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/* 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/. */
|
||||
|
||||
var Cu = Components.utils;
|
||||
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const Services = require("Services");
|
||||
const {AppManager} = require("devtools/client/webide/modules/app-manager");
|
||||
const {Connection} = require("devtools/shared/client/connection-manager");
|
||||
const {RuntimeTypes} = require("devtools/client/webide/modules/runtimes");
|
||||
const Strings = Services.strings.createBundle("chrome://devtools/locale/webide.properties");
|
||||
|
||||
const UNRESTRICTED_HELP_URL = "https://developer.mozilla.org/docs/Tools/WebIDE/Running_and_debugging_apps#Unrestricted_app_debugging_%28including_certified_apps_main_process_etc.%29";
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
document.querySelector("#close").onclick = CloseUI;
|
||||
document.querySelector("#devtools-check button").onclick = EnableCertApps;
|
||||
document.querySelector("#adb-check button").onclick = RootADB;
|
||||
document.querySelector("#unrestricted-privileges").onclick = function () {
|
||||
window.parent.UI.openInBrowser(UNRESTRICTED_HELP_URL);
|
||||
};
|
||||
AppManager.on("app-manager-update", OnAppManagerUpdate);
|
||||
BuildUI();
|
||||
CheckLockState();
|
||||
}, true);
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
AppManager.off("app-manager-update", OnAppManagerUpdate);
|
||||
});
|
||||
|
||||
function CloseUI() {
|
||||
window.parent.UI.openProject();
|
||||
}
|
||||
|
||||
function OnAppManagerUpdate(event, what) {
|
||||
if (what == "connection" || what == "runtime-global-actors") {
|
||||
BuildUI();
|
||||
CheckLockState();
|
||||
}
|
||||
}
|
||||
|
||||
function generateFields(json) {
|
||||
let table = document.querySelector("table");
|
||||
for (let name in json) {
|
||||
let tr = document.createElement("tr");
|
||||
let td = document.createElement("td");
|
||||
td.textContent = name;
|
||||
tr.appendChild(td);
|
||||
td = document.createElement("td");
|
||||
td.textContent = json[name];
|
||||
tr.appendChild(td);
|
||||
table.appendChild(tr);
|
||||
}
|
||||
}
|
||||
|
||||
var getDescriptionPromise; // Used by tests
|
||||
function BuildUI() {
|
||||
let table = document.querySelector("table");
|
||||
table.innerHTML = "";
|
||||
if (AppManager.connection &&
|
||||
AppManager.connection.status == Connection.Status.CONNECTED &&
|
||||
AppManager.deviceFront) {
|
||||
getDescriptionPromise = AppManager.deviceFront.getDescription()
|
||||
.then(json => generateFields(json));
|
||||
} else {
|
||||
CloseUI();
|
||||
}
|
||||
}
|
||||
|
||||
function CheckLockState() {
|
||||
let adbCheckResult = document.querySelector("#adb-check > .yesno");
|
||||
let devtoolsCheckResult = document.querySelector("#devtools-check > .yesno");
|
||||
let flipCertPerfButton = document.querySelector("#devtools-check button");
|
||||
let adbRootButton = document.querySelector("#adb-check button");
|
||||
let flipCertPerfAction = document.querySelector("#devtools-check > .action");
|
||||
let adbRootAction = document.querySelector("#adb-check > .action");
|
||||
|
||||
let sYes = Strings.GetStringFromName("runtimedetails_checkyes");
|
||||
let sNo = Strings.GetStringFromName("runtimedetails_checkno");
|
||||
let sUnknown = Strings.GetStringFromName("runtimedetails_checkunknown");
|
||||
let sNotUSB = Strings.GetStringFromName("runtimedetails_notUSBDevice");
|
||||
|
||||
flipCertPerfButton.setAttribute("disabled", "true");
|
||||
flipCertPerfAction.setAttribute("hidden", "true");
|
||||
adbRootAction.setAttribute("hidden", "true");
|
||||
|
||||
adbCheckResult.textContent = sUnknown;
|
||||
devtoolsCheckResult.textContent = sUnknown;
|
||||
|
||||
if (AppManager.connection &&
|
||||
AppManager.connection.status == Connection.Status.CONNECTED) {
|
||||
|
||||
// ADB check
|
||||
if (AppManager.selectedRuntime.type === RuntimeTypes.USB) {
|
||||
let device = AppManager.selectedRuntime.device;
|
||||
if (device && device.summonRoot) {
|
||||
device.isRoot().then(isRoot => {
|
||||
if (isRoot) {
|
||||
adbCheckResult.textContent = sYes;
|
||||
flipCertPerfButton.removeAttribute("disabled");
|
||||
} else {
|
||||
adbCheckResult.textContent = sNo;
|
||||
adbRootAction.removeAttribute("hidden");
|
||||
}
|
||||
}, e => console.error(e));
|
||||
} else {
|
||||
adbCheckResult.textContent = sUnknown;
|
||||
}
|
||||
} else {
|
||||
adbCheckResult.textContent = sNotUSB;
|
||||
}
|
||||
|
||||
// forbid-certified-apps check
|
||||
try {
|
||||
let prefFront = AppManager.preferenceFront;
|
||||
prefFront.getBoolPref("devtools.debugger.forbid-certified-apps").then(isForbidden => {
|
||||
if (isForbidden) {
|
||||
devtoolsCheckResult.textContent = sNo;
|
||||
flipCertPerfAction.removeAttribute("hidden");
|
||||
} else {
|
||||
devtoolsCheckResult.textContent = sYes;
|
||||
}
|
||||
}, e => console.error(e));
|
||||
} catch (e) {
|
||||
// Exception. pref actor is only accessible if forbird-certified-apps is false
|
||||
devtoolsCheckResult.textContent = sNo;
|
||||
flipCertPerfAction.removeAttribute("hidden");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function EnableCertApps() {
|
||||
let device = AppManager.selectedRuntime.device;
|
||||
// TODO: Remove `network.disable.ipc.security` once bug 1125916 is fixed.
|
||||
device.shell(
|
||||
"stop b2g && " +
|
||||
"cd /data/b2g/mozilla/*.default/ && " +
|
||||
"echo 'user_pref(\"devtools.debugger.forbid-certified-apps\", false);' >> prefs.js && " +
|
||||
"echo 'user_pref(\"dom.apps.developer_mode\", true);' >> prefs.js && " +
|
||||
"echo 'user_pref(\"network.disable.ipc.security\", true);' >> prefs.js && " +
|
||||
"echo 'user_pref(\"dom.webcomponents.enabled\", true);' >> prefs.js && " +
|
||||
"start b2g"
|
||||
);
|
||||
}
|
||||
|
||||
function RootADB() {
|
||||
let device = AppManager.selectedRuntime.device;
|
||||
device.summonRoot().then(CheckLockState, (e) => console.error(e));
|
||||
}
|
||||
46
devtools/client/webide/content/runtimedetails.xhtml
Normal file
46
devtools/client/webide/content/runtimedetails.xhtml
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?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://devtools/locale/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/runtimedetails.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://webide/content/runtimedetails.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="controls">
|
||||
<a id="close">&deck_close;</a>
|
||||
</div>
|
||||
|
||||
<h1>&runtimedetails_title;</h1>
|
||||
|
||||
<div id="devicePrivileges">
|
||||
<p id="adb-check">
|
||||
&runtimedetails_adbIsRoot;<span class="yesno"></span>
|
||||
<div class="action">
|
||||
<button>&runtimedetails_summonADBRoot;</button>
|
||||
<em>&runtimedetails_ADBRootWarning;</em>
|
||||
</div>
|
||||
</p>
|
||||
<p id="devtools-check">
|
||||
<a id="unrestricted-privileges">&runtimedetails_unrestrictedPrivileges;</a><span class="yesno"></span>
|
||||
<div class="action">
|
||||
<button>&runtimedetails_requestPrivileges;</button>
|
||||
<em>&runtimedetails_privilegesWarning;</em>
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<table></table>
|
||||
</body>
|
||||
</html>
|
||||
352
devtools/client/webide/content/simulator.js
Normal file
352
devtools/client/webide/content/simulator.js
Normal file
|
|
@ -0,0 +1,352 @@
|
|||
/* 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/. */
|
||||
|
||||
var Cu = Components.utils;
|
||||
var Ci = Components.interfaces;
|
||||
|
||||
const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const { getDevices, getDeviceString } = require("devtools/client/shared/devices");
|
||||
const { Simulators, Simulator } = require("devtools/client/webide/modules/simulators");
|
||||
const Services = require("Services");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const promise = require("promise");
|
||||
const utils = require("devtools/client/webide/modules/utils");
|
||||
|
||||
const Strings = Services.strings.createBundle("chrome://devtools/locale/webide.properties");
|
||||
|
||||
var SimulatorEditor = {
|
||||
|
||||
// Available Firefox OS Simulator addons (key: `addon.id`).
|
||||
_addons: {},
|
||||
|
||||
// Available device simulation profiles (key: `device.name`).
|
||||
_devices: {},
|
||||
|
||||
// The names of supported simulation options.
|
||||
_deviceOptions: [],
|
||||
|
||||
// The <form> element used to edit Simulator options.
|
||||
_form: null,
|
||||
|
||||
// The Simulator object being edited.
|
||||
_simulator: null,
|
||||
|
||||
// Generate the dynamic form elements.
|
||||
init() {
|
||||
let promises = [];
|
||||
|
||||
// Grab the <form> element.
|
||||
let form = this._form;
|
||||
if (!form) {
|
||||
// This is the first time we run `init()`, bootstrap some things.
|
||||
form = this._form = document.querySelector("#simulator-editor");
|
||||
form.addEventListener("change", this.update.bind(this));
|
||||
Simulators.on("configure", (e, simulator) => { this.edit(simulator); });
|
||||
// Extract the list of device simulation options we'll support.
|
||||
let deviceFields = form.querySelectorAll("*[data-device]");
|
||||
this._deviceOptions = Array.map(deviceFields, field => field.name);
|
||||
}
|
||||
|
||||
// Append a new <option> to a <select> (or <optgroup>) element.
|
||||
function opt(select, value, text) {
|
||||
let option = document.createElement("option");
|
||||
option.value = value;
|
||||
option.textContent = text;
|
||||
select.appendChild(option);
|
||||
}
|
||||
|
||||
// Generate B2G version selector.
|
||||
promises.push(Simulators.findSimulatorAddons().then(addons => {
|
||||
this._addons = {};
|
||||
form.version.innerHTML = "";
|
||||
form.version.classList.remove("custom");
|
||||
addons.forEach(addon => {
|
||||
this._addons[addon.id] = addon;
|
||||
opt(form.version, addon.id, addon.name);
|
||||
});
|
||||
opt(form.version, "custom", "");
|
||||
opt(form.version, "pick", Strings.GetStringFromName("simulator_custom_binary"));
|
||||
}));
|
||||
|
||||
// Generate profile selector.
|
||||
form.profile.innerHTML = "";
|
||||
form.profile.classList.remove("custom");
|
||||
opt(form.profile, "default", Strings.GetStringFromName("simulator_default_profile"));
|
||||
opt(form.profile, "custom", "");
|
||||
opt(form.profile, "pick", Strings.GetStringFromName("simulator_custom_profile"));
|
||||
|
||||
// Generate example devices list.
|
||||
form.device.innerHTML = "";
|
||||
form.device.classList.remove("custom");
|
||||
opt(form.device, "custom", Strings.GetStringFromName("simulator_custom_device"));
|
||||
promises.push(getDevices().then(devices => {
|
||||
devices.TYPES.forEach(type => {
|
||||
let b2gDevices = devices[type].filter(d => d.firefoxOS);
|
||||
if (b2gDevices.length < 1) {
|
||||
return;
|
||||
}
|
||||
let optgroup = document.createElement("optgroup");
|
||||
optgroup.label = getDeviceString(type);
|
||||
b2gDevices.forEach(device => {
|
||||
this._devices[device.name] = device;
|
||||
opt(optgroup, device.name, device.name);
|
||||
});
|
||||
form.device.appendChild(optgroup);
|
||||
});
|
||||
}));
|
||||
|
||||
return promise.all(promises);
|
||||
},
|
||||
|
||||
// Edit the configuration of an existing Simulator, or create a new one.
|
||||
edit(simulator) {
|
||||
// If no Simulator was given to edit, we're creating a new one.
|
||||
if (!simulator) {
|
||||
simulator = new Simulator(); // Default options.
|
||||
Simulators.add(simulator);
|
||||
}
|
||||
|
||||
this._simulator = null;
|
||||
|
||||
return this.init().then(() => {
|
||||
this._simulator = simulator;
|
||||
|
||||
// Update the form fields.
|
||||
this._form.name.value = simulator.name;
|
||||
|
||||
this.updateVersionSelector();
|
||||
this.updateProfileSelector();
|
||||
this.updateDeviceSelector();
|
||||
this.updateDeviceFields();
|
||||
|
||||
// Change visibility of 'TV Simulator Menu'.
|
||||
let tvSimMenu = document.querySelector("#tv_simulator_menu");
|
||||
tvSimMenu.style.visibility = (this._simulator.type === "television") ?
|
||||
"visible" : "hidden";
|
||||
|
||||
// Trigger any listener waiting for this update
|
||||
let change = document.createEvent("HTMLEvents");
|
||||
change.initEvent("change", true, true);
|
||||
this._form.dispatchEvent(change);
|
||||
});
|
||||
},
|
||||
|
||||
// Open the directory of TV Simulator config.
|
||||
showTVConfigDirectory() {
|
||||
let profD = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
profD.append("extensions");
|
||||
profD.append(this._simulator.addon.id);
|
||||
profD.append("profile");
|
||||
profD.append("dummy");
|
||||
let profileDir = profD.path;
|
||||
|
||||
// Show the profile directory.
|
||||
let nsLocalFile = Components.Constructor("@mozilla.org/file/local;1",
|
||||
"nsILocalFile", "initWithPath");
|
||||
new nsLocalFile(profileDir).reveal();
|
||||
},
|
||||
|
||||
// Close the configuration panel.
|
||||
close() {
|
||||
this._simulator = null;
|
||||
window.parent.UI.openProject();
|
||||
},
|
||||
|
||||
// Restore the simulator to its default configuration.
|
||||
restoreDefaults() {
|
||||
let simulator = this._simulator;
|
||||
this.version = simulator.addon.id;
|
||||
this.profile = "default";
|
||||
simulator.restoreDefaults();
|
||||
Simulators.emitUpdated();
|
||||
return this.edit(simulator);
|
||||
},
|
||||
|
||||
// Delete this simulator.
|
||||
deleteSimulator() {
|
||||
Simulators.remove(this._simulator);
|
||||
this.close();
|
||||
},
|
||||
|
||||
// Select an available option, or set the "custom" option.
|
||||
updateSelector(selector, value) {
|
||||
selector.value = value;
|
||||
if (selector.selectedIndex == -1) {
|
||||
selector.value = "custom";
|
||||
selector.classList.add("custom");
|
||||
selector[selector.selectedIndex].textContent = value;
|
||||
}
|
||||
},
|
||||
|
||||
// VERSION: Can be an installed `addon.id` or a custom binary path.
|
||||
|
||||
get version() {
|
||||
return this._simulator.options.b2gBinary || this._simulator.addon.id;
|
||||
},
|
||||
|
||||
set version(value) {
|
||||
let form = this._form;
|
||||
let simulator = this._simulator;
|
||||
let oldVer = simulator.version;
|
||||
if (this._addons[value]) {
|
||||
// `value` is a simulator addon ID.
|
||||
simulator.addon = this._addons[value];
|
||||
simulator.options.b2gBinary = null;
|
||||
} else {
|
||||
// `value` is a custom binary path.
|
||||
simulator.options.b2gBinary = value;
|
||||
// TODO (Bug 1146531) Indicate that a custom profile is now required.
|
||||
}
|
||||
// If `form.name` contains the old version, update its last occurrence.
|
||||
if (form.name.value.includes(oldVer) && simulator.version !== oldVer) {
|
||||
let regex = new RegExp("(.*)" + oldVer);
|
||||
let name = form.name.value.replace(regex, "$1" + simulator.version);
|
||||
simulator.options.name = form.name.value = Simulators.uniqueName(name);
|
||||
}
|
||||
},
|
||||
|
||||
updateVersionSelector() {
|
||||
this.updateSelector(this._form.version, this.version);
|
||||
},
|
||||
|
||||
// PROFILE. Can be "default" or a custom profile directory path.
|
||||
|
||||
get profile() {
|
||||
return this._simulator.options.gaiaProfile || "default";
|
||||
},
|
||||
|
||||
set profile(value) {
|
||||
this._simulator.options.gaiaProfile = (value == "default" ? null : value);
|
||||
},
|
||||
|
||||
updateProfileSelector() {
|
||||
this.updateSelector(this._form.profile, this.profile);
|
||||
},
|
||||
|
||||
// DEVICE. Can be an existing `device.name` or "custom".
|
||||
|
||||
get device() {
|
||||
let devices = this._devices;
|
||||
let simulator = this._simulator;
|
||||
|
||||
// Search for the name of a device matching current simulator options.
|
||||
for (let name in devices) {
|
||||
let match = true;
|
||||
for (let option of this._deviceOptions) {
|
||||
if (simulator.options[option] === devices[name][option]) {
|
||||
continue;
|
||||
}
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
if (match) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
return "custom";
|
||||
},
|
||||
|
||||
set device(name) {
|
||||
let device = this._devices[name];
|
||||
if (!device) {
|
||||
return;
|
||||
}
|
||||
let form = this._form;
|
||||
let simulator = this._simulator;
|
||||
this._deviceOptions.forEach(option => {
|
||||
simulator.options[option] = form[option].value = device[option] || null;
|
||||
});
|
||||
// TODO (Bug 1146531) Indicate when a custom profile is required (e.g. for
|
||||
// tablet, TV…).
|
||||
},
|
||||
|
||||
updateDeviceSelector() {
|
||||
this.updateSelector(this._form.device, this.device);
|
||||
},
|
||||
|
||||
// Erase any current values, trust only the `simulator.options`.
|
||||
updateDeviceFields() {
|
||||
let form = this._form;
|
||||
let simulator = this._simulator;
|
||||
this._deviceOptions.forEach(option => {
|
||||
form[option].value = simulator.options[option];
|
||||
});
|
||||
},
|
||||
|
||||
// Handle a change in our form's fields.
|
||||
update(event) {
|
||||
let simulator = this._simulator;
|
||||
if (!simulator) {
|
||||
return;
|
||||
}
|
||||
let form = this._form;
|
||||
let input = event.target;
|
||||
switch (input.name) {
|
||||
case "name":
|
||||
simulator.options.name = input.value;
|
||||
break;
|
||||
case "version":
|
||||
switch (input.value) {
|
||||
case "pick":
|
||||
let file = utils.getCustomBinary(window);
|
||||
if (file) {
|
||||
this.version = file.path;
|
||||
}
|
||||
// Whatever happens, don't stay on the "pick" option.
|
||||
this.updateVersionSelector();
|
||||
break;
|
||||
case "custom":
|
||||
this.version = input[input.selectedIndex].textContent;
|
||||
break;
|
||||
default:
|
||||
this.version = input.value;
|
||||
}
|
||||
break;
|
||||
case "profile":
|
||||
switch (input.value) {
|
||||
case "pick":
|
||||
let directory = utils.getCustomProfile(window);
|
||||
if (directory) {
|
||||
this.profile = directory.path;
|
||||
}
|
||||
// Whatever happens, don't stay on the "pick" option.
|
||||
this.updateProfileSelector();
|
||||
break;
|
||||
case "custom":
|
||||
this.profile = input[input.selectedIndex].textContent;
|
||||
break;
|
||||
default:
|
||||
this.profile = input.value;
|
||||
}
|
||||
break;
|
||||
case "device":
|
||||
this.device = input.value;
|
||||
break;
|
||||
default:
|
||||
simulator.options[input.name] = input.value || null;
|
||||
this.updateDeviceSelector();
|
||||
}
|
||||
Simulators.emitUpdated();
|
||||
},
|
||||
};
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
document.querySelector("#close").onclick = e => {
|
||||
SimulatorEditor.close();
|
||||
};
|
||||
document.querySelector("#reset").onclick = e => {
|
||||
SimulatorEditor.restoreDefaults();
|
||||
};
|
||||
document.querySelector("#remove").onclick = e => {
|
||||
SimulatorEditor.deleteSimulator();
|
||||
};
|
||||
|
||||
// We just loaded, so we probably missed the first configure request.
|
||||
SimulatorEditor.edit(Simulators._lastConfiguredSimulator);
|
||||
|
||||
document.querySelector("#open-tv-dummy-directory").onclick = e => {
|
||||
SimulatorEditor.showTVConfigDirectory();
|
||||
e.preventDefault();
|
||||
};
|
||||
});
|
||||
99
devtools/client/webide/content/simulator.xhtml
Normal file
99
devtools/client/webide/content/simulator.xhtml
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
<?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://devtools/locale/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/simulator.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://webide/content/simulator.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="controls">
|
||||
<a id="remove" class="hidden">&simulator_remove;</a>
|
||||
<a id="reset">&simulator_reset;</a>
|
||||
<a id="close">&deck_close;</a>
|
||||
</div>
|
||||
|
||||
<form id="simulator-editor">
|
||||
|
||||
<h1>&simulator_title;</h1>
|
||||
|
||||
<h2>&simulator_software;</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<label>
|
||||
<span class="label">&simulator_name;</span>
|
||||
<input type="text" name="name"/>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label>
|
||||
<span class="label">&simulator_version;</span>
|
||||
<select name="version"/>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label>
|
||||
<span class="label">&simulator_profile;</span>
|
||||
<select name="profile"/>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>&simulator_hardware;</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<label>
|
||||
<span class="label">&simulator_device;</span>
|
||||
<select name="device"/>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label>
|
||||
<span class="label">&simulator_screenSize;</span>
|
||||
<input name="width" data-device="" type="number"/>
|
||||
<span>×</span>
|
||||
<input name="height" data-device="" type="number"/>
|
||||
</label>
|
||||
</li>
|
||||
<li class="hidden">
|
||||
<label>
|
||||
<span class="label">&simulator_pixelRatio;</span>
|
||||
<input name="pixelRatio" data-device="" type="number" step="0.05"/>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- This menu is shown when simulator type is television-->
|
||||
<p id="tv_simulator_menu" style="visibility:hidden;">
|
||||
<h2>&simulator_tv_data;</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<label>
|
||||
<span class="label">&simulator_tv_data_open;</span>
|
||||
<button id="open-tv-dummy-directory">
|
||||
&simulator_tv_data_open_button;
|
||||
</button>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</p>
|
||||
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
1157
devtools/client/webide/content/webide.js
Normal file
1157
devtools/client/webide/content/webide.js
Normal file
File diff suppressed because it is too large
Load diff
178
devtools/client/webide/content/webide.xul
Normal file
178
devtools/client/webide/content/webide.xul
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % webideDTD SYSTEM "chrome://devtools/locale/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/global.css"?>
|
||||
<?xml-stylesheet href="resource://devtools/client/themes/common.css"?>
|
||||
<?xml-stylesheet href="chrome://webide/skin/webide.css"?>
|
||||
|
||||
<window id="webide" onclose="return UI.canCloseProject();"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
title="&windowTitle;"
|
||||
windowtype="devtools:webide"
|
||||
macanimationtype="document"
|
||||
fullscreenbutton="true"
|
||||
screenX="4" screenY="4"
|
||||
width="800" height="600"
|
||||
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="runtime-panel.js"></script>
|
||||
<script type="application/javascript" src="webide.js"></script>
|
||||
|
||||
<commandset id="mainCommandSet">
|
||||
<commandset id="editMenuCommands"/>
|
||||
<commandset id="webideCommands">
|
||||
<command id="cmd_quit" oncommand="Cmds.quit()"/>
|
||||
<command id="cmd_newApp" oncommand="Cmds.newApp()" label="&projectMenu_newApp_label;"/>
|
||||
<command id="cmd_importPackagedApp" oncommand="Cmds.importPackagedApp()" label="&projectMenu_importPackagedApp_label;"/>
|
||||
<command id="cmd_importHostedApp" oncommand="Cmds.importHostedApp()" label="&projectMenu_importHostedApp_label;"/>
|
||||
<command id="cmd_showDevicePrefs" label="&runtimeMenu_showDevicePrefs_label;" oncommand="Cmds.showDevicePrefs()"/>
|
||||
<command id="cmd_showSettings" label="&runtimeMenu_showSettings_label;" oncommand="Cmds.showSettings()"/>
|
||||
<command id="cmd_removeProject" oncommand="Cmds.removeProject()" label="&projectMenu_remove_label;"/>
|
||||
<command id="cmd_showProjectPanel" oncommand="Cmds.showProjectPanel()"/>
|
||||
<command id="cmd_showRuntimePanel" oncommand="Cmds.showRuntimePanel()"/>
|
||||
<command id="cmd_disconnectRuntime" oncommand="Cmds.disconnectRuntime()" label="&runtimeMenu_disconnect_label;"/>
|
||||
<command id="cmd_showMonitor" oncommand="Cmds.showMonitor()" label="&runtimeMenu_showMonitor_label;"/>
|
||||
<command id="cmd_showPermissionsTable" oncommand="Cmds.showPermissionsTable()" label="&runtimeMenu_showPermissionTable_label;"/>
|
||||
<command id="cmd_showRuntimeDetails" oncommand="Cmds.showRuntimeDetails()" label="&runtimeMenu_showDetails_label;"/>
|
||||
<command id="cmd_takeScreenshot" oncommand="Cmds.takeScreenshot()" label="&runtimeMenu_takeScreenshot_label;"/>
|
||||
<command id="cmd_toggleEditor" oncommand="Cmds.toggleEditors()" label="&viewMenu_toggleEditor_label;"/>
|
||||
<command id="cmd_showAddons" oncommand="Cmds.showAddons()"/>
|
||||
<command id="cmd_showPrefs" oncommand="Cmds.showPrefs()"/>
|
||||
<command id="cmd_showTroubleShooting" oncommand="Cmds.showTroubleShooting()"/>
|
||||
<command id="cmd_play" oncommand="Cmds.play()"/>
|
||||
<command id="cmd_stop" oncommand="Cmds.stop()" label="&projectMenu_stop_label;"/>
|
||||
<command id="cmd_toggleToolbox" oncommand="Cmds.toggleToolbox()"/>
|
||||
<command id="cmd_zoomin" label="&viewMenu_zoomin_label;" oncommand="Cmds.zoomIn()"/>
|
||||
<command id="cmd_zoomout" label="&viewMenu_zoomout_label;" oncommand="Cmds.zoomOut()"/>
|
||||
<command id="cmd_resetzoom" label="&viewMenu_resetzoom_label;" oncommand="Cmds.resetZoom()"/>
|
||||
</commandset>
|
||||
</commandset>
|
||||
|
||||
<menubar id="main-menubar">
|
||||
<menu id="menu-project" label="&projectMenu_label;" accesskey="&projectMenu_accesskey;">
|
||||
<menupopup id="menu-project-popup">
|
||||
<menuitem command="cmd_newApp" accesskey="&projectMenu_newApp_accesskey;"/>
|
||||
<menuitem command="cmd_importPackagedApp" accesskey="&projectMenu_importPackagedApp_accesskey;"/>
|
||||
<menuitem command="cmd_importHostedApp" accesskey="&projectMenu_importHostedApp_accesskey;"/>
|
||||
<menuitem id="menuitem-show_projectPanel" command="cmd_showProjectPanel" key="key_showProjectPanel" label="&projectMenu_selectApp_label;" accesskey="&projectMenu_selectApp_accesskey;"/>
|
||||
<menuseparator/>
|
||||
<menuitem command="cmd_play" key="key_play" label="&projectMenu_play_label;" accesskey="&projectMenu_play_accesskey;"/>
|
||||
<menuitem command="cmd_stop" accesskey="&projectMenu_stop_accesskey;"/>
|
||||
<menuitem command="cmd_toggleToolbox" key="key_toggleToolbox" label="&projectMenu_debug_label;" accesskey="&projectMenu_debug_accesskey;"/>
|
||||
<menuseparator/>
|
||||
<menuitem command="cmd_removeProject" accesskey="&projectMenu_remove_accesskey;"/>
|
||||
<menuseparator/>
|
||||
<menuitem command="cmd_showPrefs" label="&projectMenu_showPrefs_label;" accesskey="&projectMenu_showPrefs_accesskey;"/>
|
||||
<menuitem command="cmd_showAddons" label="&projectMenu_manageComponents_label;" accesskey="&projectMenu_manageComponents_accesskey;"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
|
||||
<menu id="menu-runtime" label="&runtimeMenu_label;" accesskey="&runtimeMenu_accesskey;">
|
||||
<menupopup id="menu-runtime-popup">
|
||||
<menuitem command="cmd_showMonitor" accesskey="&runtimeMenu_showMonitor_accesskey;"/>
|
||||
<menuitem command="cmd_takeScreenshot" accesskey="&runtimeMenu_takeScreenshot_accesskey;"/>
|
||||
<menuitem command="cmd_showPermissionsTable" accesskey="&runtimeMenu_showPermissionTable_accesskey;"/>
|
||||
<menuitem command="cmd_showRuntimeDetails" accesskey="&runtimeMenu_showDetails_accesskey;"/>
|
||||
<menuitem command="cmd_showDevicePrefs" accesskey="&runtimeMenu_showDevicePrefs_accesskey;"/>
|
||||
<menuitem command="cmd_showSettings" accesskey="&runtimeMenu_showSettings_accesskey;"/>
|
||||
<menuseparator/>
|
||||
<menuitem command="cmd_disconnectRuntime" accesskey="&runtimeMenu_disconnect_accesskey;"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
|
||||
<menu id="menu-view" label="&viewMenu_label;" accesskey="&viewMenu_accesskey;">
|
||||
<menupopup id="menu-ViewPopup">
|
||||
<menuitem command="cmd_toggleEditor" key="key_toggleEditor" accesskey="&viewMenu_toggleEditor_accesskey;"/>
|
||||
<menuseparator/>
|
||||
<menuitem command="cmd_zoomin" key="key_zoomin" accesskey="&viewMenu_zoomin_accesskey;"/>
|
||||
<menuitem command="cmd_zoomout" key="key_zoomout" accesskey="&viewMenu_zoomout_accesskey;"/>
|
||||
<menuitem command="cmd_resetzoom" key="key_resetzoom" accesskey="&viewMenu_resetzoom_accesskey;"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
|
||||
</menubar>
|
||||
|
||||
<keyset id="mainKeyset">
|
||||
<key key="&key_quit;" id="key_quit" command="cmd_quit" modifiers="accel"/>
|
||||
<key key="&key_showProjectPanel;" id="key_showProjectPanel" command="cmd_showProjectPanel" modifiers="accel"/>
|
||||
<key key="&key_play;" id="key_play" command="cmd_play" modifiers="accel"/>
|
||||
<key key="&key_toggleEditor;" id="key_toggleEditor" command="cmd_toggleEditor" modifiers="accel"/>
|
||||
<key keycode="&key_toggleToolbox;" id="key_toggleToolbox" command="cmd_toggleToolbox"/>
|
||||
<key key="&key_zoomin;" id="key_zoomin" command="cmd_zoomin" modifiers="accel"/>
|
||||
<key key="&key_zoomin2;" id="key_zoomin2" command="cmd_zoomin" modifiers="accel"/>
|
||||
<key key="&key_zoomout;" id="key_zoomout" command="cmd_zoomout" modifiers="accel"/>
|
||||
<key key="&key_resetzoom;" id="key_resetzoom" command="cmd_resetzoom" modifiers="accel"/>
|
||||
</keyset>
|
||||
|
||||
<tooltip id="aHTMLTooltip" page="true"/>
|
||||
|
||||
<toolbar id="main-toolbar">
|
||||
|
||||
<vbox flex="1">
|
||||
<hbox id="action-buttons-container" class="busy">
|
||||
<toolbarbutton id="action-button-play" class="action-button" command="cmd_play" tooltiptext="&projectMenu_play_label;"/>
|
||||
<toolbarbutton id="action-button-stop" class="action-button" command="cmd_stop" tooltiptext="&projectMenu_stop_label;"/>
|
||||
<toolbarbutton id="action-button-debug" class="action-button" command="cmd_toggleToolbox" tooltiptext="&projectMenu_debug_label;"/>
|
||||
<hbox id="action-busy" align="center">
|
||||
<html:img id="action-busy-undetermined" src="chrome://webide/skin/throbber.svg"/>
|
||||
<progressmeter id="action-busy-determined"/>
|
||||
</hbox>
|
||||
</hbox>
|
||||
|
||||
<hbox id="panel-buttons-container">
|
||||
<spacer flex="1"/>
|
||||
<toolbarbutton id="runtime-panel-button" class="panel-button">
|
||||
<image class="panel-button-image"/>
|
||||
<label class="panel-button-label" value="&runtimeButton_label;"/>
|
||||
</toolbarbutton>
|
||||
</hbox>
|
||||
|
||||
</vbox>
|
||||
</toolbar>
|
||||
|
||||
<notificationbox flex="1" id="notificationbox">
|
||||
<div flex="1" id="deck-panels">
|
||||
<vbox id="project-listing-panel" class="project-listing panel-list" flex="1">
|
||||
<div id="project-listing-wrapper" class="panel-list-wrapper">
|
||||
<iframe id="project-listing-panel-details" flex="1" src="project-listing.xhtml" tooltip="aHTMLTooltip"/>
|
||||
</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"/>
|
||||
<iframe id="deck-panel-simulator" flex="1" lazysrc="simulator.xhtml"/>
|
||||
</deck>
|
||||
<splitter class="devtools-side-splitter" id="runtime-listing-splitter"/>
|
||||
<vbox id="runtime-listing-panel" class="runtime-listing panel-list" flex="1">
|
||||
<div id="runtime-listing-wrapper" class="panel-list-wrapper">
|
||||
<iframe id="runtime-listing-panel-details" flex="1" src="runtime-listing.xhtml" tooltip="aHTMLTooltip"/>
|
||||
</div>
|
||||
</vbox>
|
||||
</div>
|
||||
<splitter hidden="true" class="devtools-horizontal-splitter" orient="vertical"/>
|
||||
<!-- toolbox iframe will be inserted here -->
|
||||
</notificationbox>
|
||||
|
||||
</window>
|
||||
44
devtools/client/webide/content/wifi-auth.js
Normal file
44
devtools/client/webide/content/wifi-auth.js
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
var Cu = Components.utils;
|
||||
const { require } =
|
||||
Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const Services = require("Services");
|
||||
const QR = require("devtools/shared/qrcode/index");
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
document.getElementById("close").onclick = () => window.close();
|
||||
document.getElementById("no-scanner").onclick = showToken;
|
||||
document.getElementById("yes-scanner").onclick = hideToken;
|
||||
buildUI();
|
||||
});
|
||||
|
||||
function buildUI() {
|
||||
let { oob } = window.arguments[0];
|
||||
createQR(oob);
|
||||
createToken(oob);
|
||||
}
|
||||
|
||||
function createQR(oob) {
|
||||
let oobData = JSON.stringify(oob);
|
||||
let imgData = QR.encodeToDataURI(oobData, "L" /* low quality */);
|
||||
document.querySelector("#qr-code img").src = imgData.src;
|
||||
}
|
||||
|
||||
function createToken(oob) {
|
||||
let token = oob.sha256.replace(/:/g, "").toLowerCase() + oob.k;
|
||||
document.querySelector("#token pre").textContent = token;
|
||||
}
|
||||
|
||||
function showToken() {
|
||||
document.querySelector("body").setAttribute("token", "true");
|
||||
}
|
||||
|
||||
function hideToken() {
|
||||
document.querySelector("body").removeAttribute("token");
|
||||
}
|
||||
45
devtools/client/webide/content/wifi-auth.xhtml
Normal file
45
devtools/client/webide/content/wifi-auth.xhtml
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<?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://devtools/locale/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<html id="devtools:wifi-auth" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/wifi-auth.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://webide/content/wifi-auth.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="controls">
|
||||
<a id="close">&deck_close;</a>
|
||||
</div>
|
||||
|
||||
<h3 id="header">&wifi_auth_header;</h3>
|
||||
<div id="scan-request">&wifi_auth_scan_request;</div>
|
||||
|
||||
<div id="qr-code">
|
||||
<div id="qr-code-wrapper">
|
||||
<img/>
|
||||
</div>
|
||||
<a id="no-scanner" class="toggle-scanner">&wifi_auth_no_scanner;</a>
|
||||
<div id="qr-size-note">
|
||||
<h5>&wifi_auth_qr_size_note;</h5>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="token">
|
||||
<div>&wifi_auth_token_request;</div>
|
||||
<pre id="token-value"/>
|
||||
<a id="yes-scanner" class="toggle-scanner">&wifi_auth_yes_scanner;</a>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue