зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1022797 - Device settings support. r=jryans
This commit is contained in:
Родитель
a126821e99
Коммит
c8eb489595
|
@ -3,25 +3,24 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const Cu = Components.utils;
|
||||
const {Services} = Cu.import("resource://gre/modules/Services.jsm");
|
||||
const {require} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm");
|
||||
const {AppManager} = require("devtools/webide/app-manager");
|
||||
const {Connection} = require("devtools/client/connection-manager");
|
||||
const Strings = Services.strings.createBundle("chrome://browser/locale/devtools/webide.properties");
|
||||
const ConfigView = require("devtools/webide/config-view");
|
||||
|
||||
let devicePrefsKeys = {};
|
||||
let table;
|
||||
let configView = new ConfigView(window);
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
document.getElementById("close").onclick = CloseUI;
|
||||
AppManager.on("app-manager-update", OnAppManagerUpdate);
|
||||
document.getElementById("device-preferences").onchange = UpdatePref;
|
||||
document.getElementById("device-preferences").onclick = CheckReset;
|
||||
document.getElementById("search-bar").onkeyup = document.getElementById("search-bar").onclick = SearchPref;
|
||||
document.getElementById("custom-value").onclick = UpdateNewPref;
|
||||
document.getElementById("custom-value-type").onchange = ClearNewPrefs;
|
||||
document.getElementById("add-custom-preference").onkeyup = CheckNewPrefSubmit;
|
||||
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);
|
||||
|
||||
|
@ -40,280 +39,49 @@ function OnAppManagerUpdate(event, what) {
|
|||
}
|
||||
}
|
||||
|
||||
function RenderByType(input, name, value, customType) {
|
||||
value = customType || typeof value;
|
||||
|
||||
switch (value) {
|
||||
case "boolean":
|
||||
input.setAttribute("data-type", "boolean");
|
||||
input.setAttribute("type", "checkbox");
|
||||
break;
|
||||
case "number":
|
||||
input.setAttribute("data-type", "number");
|
||||
input.setAttribute("type", "number");
|
||||
break;
|
||||
default:
|
||||
input.setAttribute("data-type", "string");
|
||||
input.setAttribute("type", "text");
|
||||
break;
|
||||
}
|
||||
return input;
|
||||
function CheckNewFieldSubmit(event) {
|
||||
configView.checkNewFieldSubmit(event);
|
||||
}
|
||||
|
||||
let defaultPref; // Used by tests
|
||||
function ResetToDefault(name, input, button) {
|
||||
AppManager.preferenceFront.clearUserPref(name);
|
||||
let dataType = input.getAttribute("data-type");
|
||||
let tr = document.getElementById("row-" + name);
|
||||
|
||||
switch (dataType) {
|
||||
case "boolean":
|
||||
defaultPref = AppManager.preferenceFront.getBoolPref(name);
|
||||
defaultPref.then(boolean => {
|
||||
input.checked = boolean;
|
||||
}, () => {
|
||||
input.checked = false;
|
||||
tr.parentNode.removeChild(tr);
|
||||
});
|
||||
|
||||
break;
|
||||
case "number":
|
||||
defaultPref = AppManager.preferenceFront.getIntPref(name);
|
||||
defaultPref.then(number => {
|
||||
input.value = number;
|
||||
}, () => {
|
||||
tr.parentNode.removeChild(tr);
|
||||
});
|
||||
break;
|
||||
default:
|
||||
defaultPref = AppManager.preferenceFront.getCharPref(name);
|
||||
defaultPref.then(string => {
|
||||
input.value = string;
|
||||
}, () => {
|
||||
tr.parentNode.removeChild(tr);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
button.classList.add("hide");
|
||||
function UpdateNewField() {
|
||||
configView.updateNewField();
|
||||
}
|
||||
|
||||
function SaveByType(options) {
|
||||
let prefName = options.id;
|
||||
let inputType = options.type;
|
||||
let value = options.value;
|
||||
let input = document.getElementById(prefName);
|
||||
|
||||
switch (inputType) {
|
||||
case "boolean":
|
||||
AppManager.preferenceFront.setBoolPref(prefName, input.checked);
|
||||
break;
|
||||
case "number":
|
||||
AppManager.preferenceFront.setIntPref(prefName, value);
|
||||
break;
|
||||
default:
|
||||
AppManager.preferenceFront.setCharPref(prefName, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function CheckNewPrefSubmit(event) {
|
||||
if (event.keyCode === 13) {
|
||||
document.getElementById("custom-value").click();
|
||||
}
|
||||
}
|
||||
|
||||
function ClearNewPrefs() {
|
||||
let customTextEl = table.querySelector("#custom-value-text");
|
||||
if (customTextEl.checked) {
|
||||
customTextEl.checked = false;
|
||||
} else {
|
||||
customTextEl.value = "";
|
||||
}
|
||||
|
||||
UpdateFieldType();
|
||||
}
|
||||
|
||||
function UpdateFieldType() {
|
||||
let customValueType = table.querySelector("#custom-value-type").value;
|
||||
let customTextEl = table.querySelector("#custom-value-text");
|
||||
let customText = customTextEl.value;
|
||||
|
||||
if (customValueType.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (customValueType) {
|
||||
case "boolean":
|
||||
customTextEl.type = "checkbox";
|
||||
customText = customTextEl.checked;
|
||||
break;
|
||||
case "number":
|
||||
customText = parseInt(customText, 10) || 0;
|
||||
customTextEl.type = "number";
|
||||
break;
|
||||
default:
|
||||
customTextEl.type = "text";
|
||||
break;
|
||||
}
|
||||
|
||||
return customValueType;
|
||||
}
|
||||
|
||||
function UpdateNewPref(event) {
|
||||
let customValueType = UpdateFieldType();
|
||||
|
||||
if (!customValueType) {
|
||||
return;
|
||||
}
|
||||
|
||||
let customRow = table.querySelector("tr:nth-of-type(2)");
|
||||
let customTextEl = table.querySelector("#custom-value-text");
|
||||
let customTextNameEl = table.querySelector("#custom-value-name");
|
||||
|
||||
if (customTextEl.validity.valid) {
|
||||
let customText = customTextEl.value;
|
||||
|
||||
if (customValueType === "boolean") {
|
||||
customText = customTextEl.checked;
|
||||
}
|
||||
let customTextName = customTextNameEl.value.replace(/[^A-Za-z0-9\.\-_]/gi, "");
|
||||
GenerateField(customTextName, customText, true, customValueType, customRow);
|
||||
SaveByType({
|
||||
id: customTextName,
|
||||
type: customValueType,
|
||||
value: customText
|
||||
});
|
||||
customTextNameEl.value = "";
|
||||
ClearNewPrefs();
|
||||
}
|
||||
function ClearNewFields() {
|
||||
configView.clearNewFields();
|
||||
}
|
||||
|
||||
function CheckReset(event) {
|
||||
if (event.target.classList.contains("reset")) {
|
||||
let btnId = event.target.getAttribute("data-id");
|
||||
let input = document.getElementById(btnId);
|
||||
ResetToDefault(btnId, input, event.target);
|
||||
}
|
||||
configView.checkReset(event);
|
||||
}
|
||||
|
||||
function UpdatePref(event) {
|
||||
if (event.target) {
|
||||
let inputType = event.target.getAttribute("data-type");
|
||||
let inputValue = event.target.checked || event.target.value;
|
||||
|
||||
if (event.target.nodeName == "input" &&
|
||||
event.target.validity.valid &&
|
||||
event.target.classList.contains("editable")) {
|
||||
let id = event.target.id;
|
||||
if (inputType == "boolean") {
|
||||
if (event.target.checked) {
|
||||
inputValue = true;
|
||||
} else {
|
||||
inputValue = false;
|
||||
}
|
||||
}
|
||||
SaveByType({
|
||||
id: id,
|
||||
type: inputType,
|
||||
value: inputValue
|
||||
});
|
||||
document.getElementById("btn-" + id).classList.remove("hide");
|
||||
}
|
||||
}
|
||||
function UpdateField(event) {
|
||||
configView.updateField(event);
|
||||
}
|
||||
|
||||
function GenerateField(name, value, hasUserValue, customType, newPreferenceRow) {
|
||||
if (name.length < 1) {
|
||||
return;
|
||||
}
|
||||
let sResetDefault = Strings.GetStringFromName("devicepreferences_reset_default");
|
||||
devicePrefsKeys[name] = true;
|
||||
let input = document.createElement("input");
|
||||
let tr = document.createElement("tr");
|
||||
tr.setAttribute("id", "row-" + name);
|
||||
tr.classList.add("edit-row");
|
||||
let td = document.createElement("td");
|
||||
td.classList.add("preference-name");
|
||||
td.textContent = name;
|
||||
tr.appendChild(td);
|
||||
td = document.createElement("td");
|
||||
input.classList.add("editable");
|
||||
input.setAttribute("id", name);
|
||||
input = RenderByType(input, name, value, customType);
|
||||
if (customType === "boolean" || input.type === "checkbox") {
|
||||
input.checked = value;
|
||||
} else {
|
||||
input.value = value;
|
||||
}
|
||||
td.appendChild(input);
|
||||
tr.appendChild(td);
|
||||
td = document.createElement("td");
|
||||
td.setAttribute("id", "td-" + name);
|
||||
|
||||
let button = document.createElement("button");
|
||||
button.setAttribute("data-id", name);
|
||||
button.setAttribute("id", "btn-" + name);
|
||||
button.classList.add("reset");
|
||||
button.textContent = sResetDefault;
|
||||
td.appendChild(button);
|
||||
if (!hasUserValue) {
|
||||
button.classList.add("hide");
|
||||
}
|
||||
tr.appendChild(td);
|
||||
|
||||
// If this is a new preference, add it to the top of the table.
|
||||
if (newPreferenceRow) {
|
||||
let existingPref = table.querySelector("#" + name);
|
||||
if (!existingPref) {
|
||||
table.insertBefore(tr, newPreferenceRow);
|
||||
} else {
|
||||
existingPref.value = value;
|
||||
}
|
||||
} else {
|
||||
table.appendChild(tr);
|
||||
}
|
||||
}
|
||||
|
||||
function SearchPref(event) {
|
||||
if (event.target.value.length) {
|
||||
let stringMatch = new RegExp(event.target.value, "i");
|
||||
|
||||
for (let key in devicePrefsKeys) {
|
||||
let row = document.getElementById("row-" + key);
|
||||
if (key.match(stringMatch)) {
|
||||
row.classList.remove("hide");
|
||||
} else if (row) {
|
||||
row.classList.add("hide");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var trs = document.getElementsByTagName("tr");
|
||||
|
||||
for (let i = 0; i < trs.length; i++) {
|
||||
trs[i].classList.remove("hide");
|
||||
}
|
||||
}
|
||||
function SearchField(event) {
|
||||
configView.search(event);
|
||||
}
|
||||
|
||||
let getAllPrefs; // Used by tests
|
||||
function BuildUI() {
|
||||
table = document.querySelector("table");
|
||||
let trs = table.querySelectorAll("tr:not(#add-custom-preference)");
|
||||
|
||||
for (var i = 0; i < trs.length; i++) {
|
||||
table.removeChild(trs[i]);
|
||||
}
|
||||
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();
|
||||
getAllPrefs.then(json => {
|
||||
let devicePrefs = Object.keys(json);
|
||||
devicePrefs.sort();
|
||||
for (let i = 0; i < devicePrefs.length; i++) {
|
||||
GenerateField(devicePrefs[i], json[devicePrefs[i]].value, json[devicePrefs[i]].hasUserValue);
|
||||
let deviceItems = Object.keys(json);
|
||||
deviceItems.sort();
|
||||
configView.keys = deviceItems;
|
||||
for (let i = 0; i < configView.keys.length; i++) {
|
||||
let key = configView.keys[i];
|
||||
configView.generateField(key, json[key].value, json[key].hasUserValue);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/devicepreferences.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>
|
||||
|
@ -21,27 +21,27 @@
|
|||
<div id="controls">
|
||||
<a id="close">&deck_close;</a>
|
||||
</div>
|
||||
<h1>&devicepreferences_title;</h1>
|
||||
<h1>&devicepreference_title;</h1>
|
||||
<div id="search">
|
||||
<input type="text" id="search-bar" placeholder="&devicepreferences_search;"/>
|
||||
<input type="text" id="search-bar" placeholder="&devicepreference_search;"/>
|
||||
</div>
|
||||
</header>
|
||||
<table id="device-preferences">
|
||||
<tr id="add-custom-preference">
|
||||
<table id="device-fields">
|
||||
<tr id="add-custom-field">
|
||||
<td>
|
||||
<select id="custom-value-type">
|
||||
<option value="" selected="selected">&devicepreferences_typenone;</option>
|
||||
<option value="boolean">&devicepreferences_typeboolean;</option>
|
||||
<option value="number">&devicepreferences_typenumber;</option>
|
||||
<option value="string">&devicepreferences_typestring;</option>
|
||||
<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="&devicepreferences_newname;"/>
|
||||
<input type="text" id="custom-value-name" placeholder="&devicepreference_newname;"/>
|
||||
</td>
|
||||
<td class="custom-input">
|
||||
<input type="text" id="custom-value-text" placeholder="&devicepreferences_newtext;"/>
|
||||
<input type="text" id="custom-value-text" placeholder="&devicepreference_newtext;"/>
|
||||
</td>
|
||||
<td>
|
||||
<button id="custom-value" class="new-editable">&devicepreferences_addnew;</button>
|
||||
<button id="custom-value" class="new-editable">&devicepreference_addnew;</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const Cu = Components.utils;
|
||||
const {require} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm");
|
||||
const {AppManager} = require("devtools/webide/app-manager");
|
||||
const {Connection} = require("devtools/client/connection-manager");
|
||||
const ConfigView = require("devtools/webide/config-view");
|
||||
|
||||
let 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 == "list-tabs-response") {
|
||||
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);
|
||||
}
|
||||
|
||||
let 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()
|
||||
getAllSettings.then(json => {
|
||||
let deviceItems = Object.keys(json);
|
||||
deviceItems.sort();
|
||||
configView.keys = deviceItems;
|
||||
for (let i = 0; i < configView.keys.length; i++) {
|
||||
let key = configView.keys[i];
|
||||
configView.generateField(key, json[key].value, json[key].hasUserValue);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
CloseUI();
|
||||
}
|
||||
}
|
|
@ -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://browser/locale/devtools/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/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>
|
|
@ -22,3 +22,5 @@ webide.jar:
|
|||
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)
|
||||
|
|
|
@ -806,6 +806,7 @@ let UI = {
|
|||
document.querySelector("#cmd_stop").setAttribute("disabled", "true");
|
||||
document.querySelector("#cmd_toggleToolbox").setAttribute("disabled", "true");
|
||||
document.querySelector("#cmd_showDevicePrefs").setAttribute("disabled", "true");
|
||||
document.querySelector("#cmd_showSettings").setAttribute("disabled", "true");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -870,6 +871,7 @@ let UI = {
|
|||
let detailsCmd = document.querySelector("#cmd_showRuntimeDetails");
|
||||
let disconnectCmd = document.querySelector("#cmd_disconnectRuntime");
|
||||
let devicePrefsCmd = document.querySelector("#cmd_showDevicePrefs");
|
||||
let settingsCmd = document.querySelector("#cmd_showSettings");
|
||||
|
||||
let box = document.querySelector("#runtime-actions");
|
||||
|
||||
|
@ -883,6 +885,9 @@ let UI = {
|
|||
if (AppManager.preferenceFront) {
|
||||
devicePrefsCmd.removeAttribute("disabled");
|
||||
}
|
||||
if (AppManager.settingsFront) {
|
||||
settingsCmd.removeAttribute("disabled");
|
||||
}
|
||||
disconnectCmd.removeAttribute("disabled");
|
||||
runtimePanelButton.setAttribute("active", "true");
|
||||
} else {
|
||||
|
@ -891,6 +896,7 @@ let UI = {
|
|||
screenshotCmd.setAttribute("disabled", "true");
|
||||
disconnectCmd.setAttribute("disabled", "true");
|
||||
devicePrefsCmd.setAttribute("disabled", "true");
|
||||
settingsCmd.setAttribute("disabled", "true");
|
||||
runtimePanelButton.removeAttribute("active");
|
||||
}
|
||||
|
||||
|
@ -1248,6 +1254,10 @@ let Cmds = {
|
|||
UI.selectDeckPanel("devicepreferences");
|
||||
},
|
||||
|
||||
showSettings: function() {
|
||||
UI.selectDeckPanel("devicesettings");
|
||||
},
|
||||
|
||||
showMonitor: function() {
|
||||
UI.selectDeckPanel("monitor");
|
||||
},
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
<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()"/>
|
||||
|
@ -83,6 +84,7 @@
|
|||
<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>
|
||||
|
@ -179,6 +181,7 @@
|
|||
<toolbarbutton class="panel-item" id="runtime-details" command="cmd_showRuntimeDetails"/>
|
||||
<toolbarbutton class="panel-item" id="runtime-permissions" command="cmd_showPermissionsTable"/>
|
||||
<toolbarbutton class="panel-item" id="runtime-preferences" command="cmd_showDevicePrefs"/>
|
||||
<toolbarbutton class="panel-item" id="runtime-preferences" command="cmd_showSettings"/>
|
||||
<toolbarbutton class="panel-item" id="runtime-screenshot" command="cmd_takeScreenshot"/>
|
||||
<toolbarbutton class="panel-item" id="runtime-disconnect" command="cmd_disconnectRuntime"/>
|
||||
</vbox>
|
||||
|
@ -197,6 +200,7 @@
|
|||
<iframe id="deck-panel-runtimedetails" flex="1" src="runtimedetails.xhtml"/>
|
||||
<iframe id="deck-panel-monitor" flex="1" lazysrc="monitor.xhtml"/>
|
||||
<iframe id="deck-panel-devicepreferences" flex="1" src="devicepreferences.xhtml"/>
|
||||
<iframe id="deck-panel-devicesettings" flex="1" src="devicesettings.xhtml"/>
|
||||
</deck>
|
||||
<splitter hidden="true" class="devtools-horizontal-splitter" orient="vertical"/>
|
||||
<!-- toolbox iframe will be inserted here -->
|
||||
|
|
|
@ -18,6 +18,7 @@ const {ConnectionManager, Connection} = require("devtools/client/connection-mana
|
|||
const {AppActorFront} = require("devtools/app-actor-front");
|
||||
const {getDeviceFront} = require("devtools/server/actors/device");
|
||||
const {getPreferenceFront} = require("devtools/server/actors/preference");
|
||||
const {getSettingsFront} = require("devtools/server/actors/settings");
|
||||
const {setTimeout} = require("sdk/timers");
|
||||
const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
const {RuntimeScanners, RuntimeTypes} = require("devtools/webide/runtimes");
|
||||
|
@ -415,6 +416,13 @@ let AppManager = exports.AppManager = {
|
|||
return getPreferenceFront(this.connection.client, this._listTabsResponse);
|
||||
},
|
||||
|
||||
get settingsFront() {
|
||||
if (!this._listTabsResponse) {
|
||||
return null;
|
||||
}
|
||||
return getSettingsFront(this.connection.client, this._listTabsResponse);
|
||||
},
|
||||
|
||||
disconnectRuntime: function() {
|
||||
if (!this.connected) {
|
||||
return promise.resolve();
|
||||
|
|
|
@ -0,0 +1,360 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const {Cu} = require("chrome");
|
||||
|
||||
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm");
|
||||
const EventEmitter = require("devtools/toolkit/event-emitter");
|
||||
const {Services} = Cu.import("resource://gre/modules/Services.jsm");
|
||||
const Strings = Services.strings.createBundle("chrome://browser/locale/devtools/webide.properties");
|
||||
|
||||
let ConfigView;
|
||||
|
||||
module.exports = ConfigView = function(window) {
|
||||
EventEmitter.decorate(this);
|
||||
this._doc = window.document;
|
||||
this._keys = [];
|
||||
return this;
|
||||
};
|
||||
|
||||
ConfigView.prototype = {
|
||||
_renderByType: function(input, name, value, customType) {
|
||||
value = customType || typeof value;
|
||||
|
||||
switch (value) {
|
||||
case "boolean":
|
||||
input.setAttribute("data-type", "boolean");
|
||||
input.setAttribute("type", "checkbox");
|
||||
break;
|
||||
case "number":
|
||||
input.setAttribute("data-type", "number");
|
||||
input.setAttribute("type", "number");
|
||||
break;
|
||||
case "object":
|
||||
input.setAttribute("data-type", "object");
|
||||
input.setAttribute("type", "text");
|
||||
break;
|
||||
default:
|
||||
input.setAttribute("data-type", "string");
|
||||
input.setAttribute("type", "text");
|
||||
break;
|
||||
}
|
||||
return input;
|
||||
},
|
||||
|
||||
set front(front) {
|
||||
this._front = front;
|
||||
},
|
||||
|
||||
set keys(keys) {
|
||||
this._keys = keys;
|
||||
},
|
||||
|
||||
get keys() {
|
||||
return this._keys;
|
||||
},
|
||||
|
||||
set kind(kind) {
|
||||
this._kind = kind;
|
||||
},
|
||||
|
||||
set includeTypeName(include) {
|
||||
this._includeTypeName = include;
|
||||
},
|
||||
|
||||
search: function(event) {
|
||||
if (event.target.value.length) {
|
||||
let stringMatch = new RegExp(event.target.value, "i");
|
||||
|
||||
for (let i = 0; i < this._keys.length; i++) {
|
||||
let key = this._keys[i];
|
||||
let row = this._doc.getElementById("row-" + key);
|
||||
if (key.match(stringMatch)) {
|
||||
row.classList.remove("hide");
|
||||
} else if (row) {
|
||||
row.classList.add("hide");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var trs = this._doc.getElementById("device-fields").querySelectorAll("tr");
|
||||
|
||||
for (let i = 0; i < trs.length; i++) {
|
||||
trs[i].classList.remove("hide");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
generateField: function(name, value, hasUserValue, customType, newRow) {
|
||||
let table = this._doc.querySelector("table");
|
||||
let sResetDefault = Strings.GetStringFromName("device_reset_default");
|
||||
|
||||
if (this._keys.indexOf(name) === -1) {
|
||||
this._keys.push(name);
|
||||
}
|
||||
|
||||
let input = this._doc.createElement("input");
|
||||
let tr = this._doc.createElement("tr");
|
||||
tr.setAttribute("id", "row-" + name);
|
||||
tr.classList.add("edit-row");
|
||||
let td = this._doc.createElement("td");
|
||||
td.classList.add("field-name");
|
||||
td.textContent = name;
|
||||
tr.appendChild(td);
|
||||
td = this._doc.createElement("td");
|
||||
input.classList.add("editable");
|
||||
input.setAttribute("id", name);
|
||||
input = this._renderByType(input, name, value, customType);
|
||||
|
||||
if (customType === "boolean" || input.type === "checkbox") {
|
||||
input.checked = value;
|
||||
} else {
|
||||
if (typeof value === "object") {
|
||||
value = JSON.stringify(value);
|
||||
}
|
||||
input.value = value;
|
||||
}
|
||||
|
||||
td.appendChild(input);
|
||||
tr.appendChild(td);
|
||||
td = this._doc.createElement("td");
|
||||
td.setAttribute("id", "td-" + name);
|
||||
|
||||
let button = this._doc.createElement("button");
|
||||
button.setAttribute("data-id", name);
|
||||
button.setAttribute("id", "btn-" + name);
|
||||
button.classList.add("reset");
|
||||
button.textContent = sResetDefault;
|
||||
td.appendChild(button);
|
||||
|
||||
if (!hasUserValue) {
|
||||
button.classList.add("hide");
|
||||
}
|
||||
|
||||
tr.appendChild(td);
|
||||
|
||||
// If this is a new field, add it to the top of the table.
|
||||
if (newRow) {
|
||||
let existing = table.querySelector("#" + name);
|
||||
|
||||
if (!existing) {
|
||||
table.insertBefore(tr, newRow);
|
||||
} else {
|
||||
existing.value = value;
|
||||
}
|
||||
} else {
|
||||
table.appendChild(tr);
|
||||
}
|
||||
},
|
||||
|
||||
resetTable: function() {
|
||||
let table = this._doc.querySelector("table");
|
||||
let trs = table.querySelectorAll("tr:not(#add-custom-field)");
|
||||
|
||||
for (var i = 0; i < trs.length; i++) {
|
||||
table.removeChild(trs[i]);
|
||||
}
|
||||
|
||||
return table;
|
||||
},
|
||||
|
||||
_getCallType: function(type, name) {
|
||||
let frontName = "get";
|
||||
|
||||
if (this._includeTypeName) {
|
||||
frontName += type;
|
||||
}
|
||||
|
||||
return this._front[frontName + this._kind](name);
|
||||
},
|
||||
|
||||
_setCallType: function(type, name, value) {
|
||||
let frontName = "set";
|
||||
|
||||
if (this._includeTypeName) {
|
||||
frontName += type;
|
||||
}
|
||||
|
||||
return this._front[frontName + this._kind](name, value);
|
||||
},
|
||||
|
||||
_saveByType: function(options) {
|
||||
let fieldName = options.id;
|
||||
let inputType = options.type;
|
||||
let value = options.value;
|
||||
let input = this._doc.getElementById(fieldName);
|
||||
|
||||
switch(inputType) {
|
||||
case "boolean":
|
||||
this._setCallType("Bool", fieldName, input.checked);
|
||||
break;
|
||||
case "number":
|
||||
this._setCallType("Int", fieldName, value);
|
||||
break;
|
||||
case "object":
|
||||
try {
|
||||
value = JSON.parse(value);
|
||||
} catch(e) {}
|
||||
this._setCallType("Object", fieldName, value);
|
||||
break;
|
||||
default:
|
||||
this._setCallType("Char", fieldName, value);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
updateField: function(event) {
|
||||
if (event.target) {
|
||||
let inputType = event.target.getAttribute("data-type");
|
||||
let inputValue = event.target.checked || event.target.value;
|
||||
|
||||
if (event.target.nodeName == "input" &&
|
||||
event.target.validity.valid &&
|
||||
event.target.classList.contains("editable")) {
|
||||
let id = event.target.id;
|
||||
if (inputType === "boolean") {
|
||||
if (event.target.checked) {
|
||||
inputValue = true;
|
||||
} else {
|
||||
inputValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
this._saveByType({
|
||||
id: id,
|
||||
type: inputType,
|
||||
value: inputValue
|
||||
});
|
||||
this._doc.getElementById("btn-" + id).classList.remove("hide");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_resetToDefault: function(name, input, button) {
|
||||
this._front["clearUser" + this._kind](name);
|
||||
let dataType = input.getAttribute("data-type");
|
||||
let tr = this._doc.getElementById("row-" + name);
|
||||
|
||||
switch (dataType) {
|
||||
case "boolean":
|
||||
this._defaultField = this._getCallType("Bool", name);
|
||||
this._defaultField.then(boolean => {
|
||||
input.checked = boolean;
|
||||
}, () => {
|
||||
input.checked = false;
|
||||
tr.parentNode.removeChild(tr);
|
||||
});
|
||||
break;
|
||||
case "number":
|
||||
this._defaultField = this._getCallType("Int", name);
|
||||
this._defaultField.then(number => {
|
||||
input.value = number;
|
||||
}, () => {
|
||||
tr.parentNode.removeChild(tr);
|
||||
});
|
||||
break;
|
||||
case "object":
|
||||
this._defaultField = this._getCallType("Object", name);
|
||||
this._defaultField.then(object => {
|
||||
input.value = JSON.stringify(object);
|
||||
}, () => {
|
||||
tr.parentNode.removeChild(tr);
|
||||
});
|
||||
break;
|
||||
default:
|
||||
this._defaultField = this._getCallType("Char", name);
|
||||
this._defaultField.then(string => {
|
||||
input.value = string;
|
||||
}, () => {
|
||||
tr.parentNode.removeChild(tr);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
button.classList.add("hide");
|
||||
},
|
||||
|
||||
checkReset: function(event) {
|
||||
if (event.target.classList.contains("reset")) {
|
||||
let btnId = event.target.getAttribute("data-id");
|
||||
let input = this._doc.getElementById(btnId);
|
||||
this._resetToDefault(btnId, input, event.target);
|
||||
}
|
||||
},
|
||||
|
||||
updateFieldType: function() {
|
||||
let table = this._doc.querySelector("table");
|
||||
let customValueType = table.querySelector("#custom-value-type").value;
|
||||
let customTextEl = table.querySelector("#custom-value-text");
|
||||
let customText = customTextEl.value;
|
||||
|
||||
if (customValueType.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (customValueType) {
|
||||
case "boolean":
|
||||
customTextEl.type = "checkbox";
|
||||
customText = customTextEl.checked;
|
||||
break;
|
||||
case "number":
|
||||
customText = parseInt(customText, 10) || 0;
|
||||
customTextEl.type = "number";
|
||||
break;
|
||||
default:
|
||||
customTextEl.type = "text";
|
||||
break;
|
||||
}
|
||||
|
||||
return customValueType;
|
||||
},
|
||||
|
||||
clearNewFields: function() {
|
||||
let table = this._doc.querySelector("table");
|
||||
let customTextEl = table.querySelector("#custom-value-text");
|
||||
if (customTextEl.checked) {
|
||||
customTextEl.checked = false;
|
||||
} else {
|
||||
customTextEl.value = "";
|
||||
}
|
||||
|
||||
this.updateFieldType();
|
||||
},
|
||||
|
||||
updateNewField: function() {
|
||||
let table = this._doc.querySelector("table");
|
||||
let customValueType = this.updateFieldType();
|
||||
|
||||
if (!customValueType) {
|
||||
return;
|
||||
}
|
||||
|
||||
let customRow = table.querySelector("tr:nth-of-type(2)");
|
||||
let customTextEl = table.querySelector("#custom-value-text");
|
||||
let customTextNameEl = table.querySelector("#custom-value-name");
|
||||
|
||||
if (customTextEl.validity.valid) {
|
||||
let customText = customTextEl.value;
|
||||
|
||||
if (customValueType === "boolean") {
|
||||
customText = customTextEl.checked;
|
||||
}
|
||||
|
||||
let customTextName = customTextNameEl.value.replace(/[^A-Za-z0-9\.\-_]/gi, "");
|
||||
this.generateField(customTextName, customText, true, customValueType, customRow);
|
||||
this._saveByType({
|
||||
id: customTextName,
|
||||
type: customValueType,
|
||||
value: customText
|
||||
});
|
||||
customTextNameEl.value = "";
|
||||
this.clearNewFields();
|
||||
}
|
||||
},
|
||||
|
||||
checkNewFieldSubmit: function(event) {
|
||||
if (event.keyCode === 13) {
|
||||
this._doc.getElementById("custom-value").click();
|
||||
}
|
||||
}
|
||||
};
|
|
@ -17,8 +17,9 @@ EXTRA_JS_MODULES.devtools.webide += [
|
|||
'modules/addons.js',
|
||||
'modules/app-manager.js',
|
||||
'modules/build.js',
|
||||
'modules/config-view.js',
|
||||
'modules/remote-resources.js',
|
||||
'modules/runtimes.js',
|
||||
'modules/tab-store.js',
|
||||
'modules/utils.js',
|
||||
'modules/utils.js'
|
||||
]
|
||||
|
|
|
@ -32,6 +32,7 @@ support-files =
|
|||
build_app_windows2/manifest.webapp
|
||||
build_app_windows2/package.json
|
||||
build_app_windows2/stage/empty-directory
|
||||
device_front_shared.js
|
||||
head.js
|
||||
hosted_app.manifest
|
||||
templates.json
|
||||
|
@ -47,6 +48,7 @@ support-files =
|
|||
[test_autoconnect_runtime.html]
|
||||
[test_telemetry.html]
|
||||
[test_device_preferences.html]
|
||||
[test_device_settings.html]
|
||||
[test_fullscreenToolbox.html]
|
||||
[test_zoom.html]
|
||||
[test_build.html]
|
||||
|
|
|
@ -0,0 +1,219 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
let customName;
|
||||
let customValue;
|
||||
let customValueType;
|
||||
let customBtn;
|
||||
let newField;
|
||||
let change;
|
||||
let doc;
|
||||
let iframe;
|
||||
let resetBtn;
|
||||
let found = false;
|
||||
|
||||
function setDocument(frame) {
|
||||
iframe = frame;
|
||||
doc = iframe.contentWindow.document;
|
||||
}
|
||||
|
||||
function fieldChange(fields, id) {
|
||||
// Trigger existing field change
|
||||
for (let field of fields) {
|
||||
if (field.id == id) {
|
||||
let button = doc.getElementById("btn-" + id);
|
||||
found = true;
|
||||
ok(button.classList.contains("hide"), "Default field detected");
|
||||
field.value = "custom";
|
||||
field.click();
|
||||
ok(!button.classList.contains("hide"), "Custom field detected");
|
||||
break;
|
||||
}
|
||||
}
|
||||
ok(found, "Found " + id + " line");
|
||||
}
|
||||
|
||||
function addNewField() {
|
||||
found = false;
|
||||
customName = doc.querySelector("#custom-value-name");
|
||||
customValue = doc.querySelector("#custom-value-text");
|
||||
customValueType = doc.querySelector("#custom-value-type");
|
||||
customBtn = doc.querySelector("#custom-value");
|
||||
change = doc.createEvent("HTMLEvents");
|
||||
change.initEvent("change", false, true);
|
||||
|
||||
// Add a new custom string
|
||||
customValueType.value = "string";
|
||||
customValueType.dispatchEvent(change);
|
||||
customName.value = "new-string-field!";
|
||||
customValue.value = "test";
|
||||
customBtn.click();
|
||||
let newField = doc.querySelector("#new-string-field");
|
||||
if (newField) {
|
||||
found = true;
|
||||
is(newField.type, "text", "Custom type is a string");
|
||||
is(newField.value, "test", "Custom string new value is correct");
|
||||
}
|
||||
ok(found, "Found new string field line");
|
||||
is(customName.value, "", "Custom string name reset");
|
||||
is(customValue.value, "", "Custom string value reset");
|
||||
}
|
||||
|
||||
function addNewFieldWithEnter() {
|
||||
// Add a new custom value with the <enter> key
|
||||
found = false;
|
||||
customName.value = "new-string-field-two";
|
||||
customValue.value = "test";
|
||||
let newAddField = doc.querySelector("#add-custom-field");
|
||||
let enter = doc.createEvent("KeyboardEvent");
|
||||
enter.initKeyEvent(
|
||||
"keyup", true, true, null, false, false, false, false, 13, 0);
|
||||
newAddField.dispatchEvent(enter);
|
||||
newField = doc.querySelector("#new-string-field-two");
|
||||
if (newField) {
|
||||
found = true;
|
||||
is(newField.type, "text", "Custom type is a string");
|
||||
is(newField.value, "test", "Custom string new value is correct");
|
||||
}
|
||||
ok(found, "Found new string field line");
|
||||
is(customName.value, "", "Custom string name reset");
|
||||
is(customValue.value, "", "Custom string value reset");
|
||||
}
|
||||
|
||||
function editExistingField() {
|
||||
// Edit existing custom string preference
|
||||
newField.value = "test2";
|
||||
newField.click();
|
||||
is(newField.value, "test2", "Custom string existing value is correct");
|
||||
}
|
||||
|
||||
function addNewFieldInteger() {
|
||||
// Add a new custom integer preference with a valid integer
|
||||
customValueType.value = "number";
|
||||
customValueType.dispatchEvent(change);
|
||||
customName.value = "new-integer-field";
|
||||
customValue.value = 1;
|
||||
found = false;
|
||||
|
||||
customBtn.click();
|
||||
newField = doc.querySelector("#new-integer-field");
|
||||
if (newField) {
|
||||
found = true;
|
||||
is(newField.type, "number", "Custom type is a number");
|
||||
is(newField.value, 1, "Custom integer value is correct");
|
||||
}
|
||||
ok(found, "Found new integer field line");
|
||||
is(customName.value, "", "Custom integer name reset");
|
||||
is(customValue.value, 0, "Custom integer value reset");
|
||||
}
|
||||
|
||||
let editFieldInteger = Task.async(function*() {
|
||||
// Edit existing custom integer preference
|
||||
newField.value = 3;
|
||||
newField.click();
|
||||
is(newField.value, 3, "Custom integer existing value is correct");
|
||||
|
||||
// Reset a custom field
|
||||
let resetBtn = doc.querySelector("#btn-new-integer-field");
|
||||
resetBtn.click();
|
||||
|
||||
try {
|
||||
yield iframe.contentWindow.configView._defaultField;
|
||||
} catch(err) {
|
||||
let fieldRow = doc.querySelector("#row-new-integer-field");
|
||||
if (!fieldRow) {
|
||||
found = false;
|
||||
}
|
||||
ok(!found, "Custom field removed");
|
||||
}
|
||||
});
|
||||
|
||||
let resetExistingField = Task.async(function*(id) {
|
||||
let existing = doc.getElementById(id);
|
||||
existing.click();
|
||||
is(existing.checked, false, "Existing boolean value is correct");
|
||||
resetBtn = doc.getElementById("btn-" + id);
|
||||
resetBtn.click();
|
||||
|
||||
yield iframe.contentWindow.configView._defaultField;
|
||||
|
||||
ok(resetBtn.classList.contains("hide"), true, "Reset button hidden");
|
||||
is(existing.checked, true, "Existing field reset");
|
||||
});
|
||||
|
||||
let resetNewField = Task.async(function*(id) {
|
||||
let custom = doc.getElementById(id);
|
||||
custom.click();
|
||||
is(custom.value, "test", "New string value is correct");
|
||||
resetBtn = doc.getElementById("btn-" + id);
|
||||
resetBtn.click();
|
||||
|
||||
yield iframe.contentWindow.configView._defaultField;
|
||||
|
||||
ok(resetBtn.classList.contains("hide"), true, "Reset button hidden");
|
||||
});
|
||||
|
||||
function addNewFieldBoolean() {
|
||||
customValueType.value = "boolean";
|
||||
customValueType.dispatchEvent(change);
|
||||
customName.value = "new-boolean-field";
|
||||
customValue.checked = true;
|
||||
found = false;
|
||||
customBtn.click();
|
||||
newField = doc.querySelector("#new-boolean-field");
|
||||
if (newField) {
|
||||
found = true;
|
||||
is(newField.type, "checkbox", "Custom type is a checkbox");
|
||||
is(newField.checked, true, "Custom boolean value is correctly true");
|
||||
}
|
||||
ok(found, "Found new boolean field line");
|
||||
|
||||
// Mouse event trigger
|
||||
var mouseClick = new MouseEvent("click", {
|
||||
canBubble: true,
|
||||
cancelable: true,
|
||||
view: doc.parent,
|
||||
});
|
||||
|
||||
found = false;
|
||||
customValueType.value = "boolean";
|
||||
customValueType.dispatchEvent(change);
|
||||
customName.value = "new-boolean-field2";
|
||||
customValue.dispatchEvent(mouseClick);
|
||||
customBtn.dispatchEvent(mouseClick);
|
||||
newField = doc.querySelector("#new-boolean-field2");
|
||||
if (newField) {
|
||||
found = true;
|
||||
is(newField.checked, true, "Custom boolean value is correctly false");
|
||||
}
|
||||
ok(found, "Found new second boolean field line");
|
||||
|
||||
is(customName.value, "", "Custom boolean name reset");
|
||||
is(customValue.checked, false, "Custom boolean value reset");
|
||||
|
||||
newField.click();
|
||||
is(newField.checked, false, "Custom boolean existing value is correct");
|
||||
}
|
||||
|
||||
function searchFields(deck, keyword) {
|
||||
// Search for a non-existent field
|
||||
let searchField = doc.querySelector("#search-bar");
|
||||
searchField.value = "![o_O]!";
|
||||
searchField.click();
|
||||
|
||||
let fieldsTotal = doc.querySelectorAll("tr.edit-row").length;
|
||||
let hiddenFields = doc.querySelectorAll("tr.hide");
|
||||
is(hiddenFields.length, fieldsTotal, "Search keyword not found");
|
||||
|
||||
// Search for existing fields
|
||||
searchField.value = keyword;
|
||||
searchField.click();
|
||||
hiddenFields = doc.querySelectorAll("tr.hide");
|
||||
isnot(hiddenFields.length, fieldsTotal, "Search keyword found");
|
||||
|
||||
doc.querySelector("#close").click();
|
||||
|
||||
ok(!deck.selectedPanel, "No panel selected");
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="head.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="device_front_shared.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
|
||||
|
@ -49,190 +50,34 @@
|
|||
yield prefIframe.contentWindow.getAllPrefs;
|
||||
yield nextTick();
|
||||
|
||||
let doc = prefIframe.contentWindow.document;
|
||||
setDocument(prefIframe);
|
||||
|
||||
let fields = doc.querySelectorAll(".editable");
|
||||
let preference = "accessibility.blockautorefresh";
|
||||
let found = false;
|
||||
|
||||
// Trigger existing field change
|
||||
for (let field of fields) {
|
||||
if (field.id == preference) {
|
||||
let button = doc.getElementById("btn-" + preference);
|
||||
found = true;
|
||||
ok(button.classList.contains("hide"), "Default field detected");
|
||||
field.value = "custom";
|
||||
field.click();
|
||||
ok(!button.classList.contains("hide"), "Custom field detected");
|
||||
break;
|
||||
}
|
||||
}
|
||||
ok(found, "Found accessibility preference line");
|
||||
fieldChange(fields, preference);
|
||||
|
||||
// Add new preferences
|
||||
found = false;
|
||||
let customName = doc.querySelector("#custom-value-name");
|
||||
let customValue = doc.querySelector("#custom-value-text");
|
||||
let customValueType = doc.querySelector("#custom-value-type");
|
||||
let customBtn = doc.querySelector("#custom-value");
|
||||
let change = doc.createEvent("HTMLEvents");
|
||||
change.initEvent("change", false, true);
|
||||
addNewField();
|
||||
|
||||
// Add a new custom string preference
|
||||
customValueType.value = "string";
|
||||
customValueType.dispatchEvent(change);
|
||||
customName.value = "new-string-pref!";
|
||||
customValue.value = "test";
|
||||
customBtn.click();
|
||||
let newPref = doc.querySelector("#new-string-pref");
|
||||
if (newPref) {
|
||||
found = true;
|
||||
is(newPref.type, "text", "Custom type is a string");
|
||||
is(newPref.value, "test", "Custom string new value is correct");
|
||||
}
|
||||
ok(found, "Found new string preference line");
|
||||
is(customName.value, "", "Custom string name reset");
|
||||
is(customValue.value, "", "Custom string value reset");
|
||||
addNewFieldWithEnter();
|
||||
|
||||
// Add a new custom value with the <enter> key
|
||||
found = false;
|
||||
customName.value = "new-string-pref-two";
|
||||
customValue.value = "test";
|
||||
let newField = doc.querySelector("#add-custom-preference");
|
||||
let enter = doc.createEvent("KeyboardEvent");
|
||||
enter.initKeyEvent(
|
||||
"keyup", true, true, null, false, false, false, false, 13, 0);
|
||||
newField.dispatchEvent(enter);
|
||||
newPref = doc.querySelector("#new-string-pref-two");
|
||||
if (newPref) {
|
||||
found = true;
|
||||
is(newPref.type, "text", "Custom type is a string");
|
||||
is(newPref.value, "test", "Custom string new value is correct");
|
||||
}
|
||||
ok(found, "Found new string preference line");
|
||||
is(customName.value, "", "Custom string name reset");
|
||||
is(customValue.value, "", "Custom string value reset");
|
||||
editExistingField();
|
||||
|
||||
// Edit existing custom string preference
|
||||
newPref.value = "test2";
|
||||
newPref.click();
|
||||
is(newPref.value, "test2", "Custom string existing value is correct");
|
||||
addNewFieldInteger();
|
||||
|
||||
// Add a new custom integer preference with a valid integer
|
||||
customValueType.value = "number";
|
||||
customValueType.dispatchEvent(change);
|
||||
customName.value = "new-integer-pref";
|
||||
customValue.value = 1;
|
||||
found = false;
|
||||
yield editFieldInteger();
|
||||
|
||||
customBtn.click();
|
||||
newPref = doc.querySelector("#new-integer-pref");
|
||||
if (newPref) {
|
||||
found = true;
|
||||
is(newPref.type, "number", "Custom type is a number");
|
||||
is(newPref.value, 1, "Custom integer value is correct");
|
||||
}
|
||||
ok(found, "Found new integer preference line");
|
||||
is(customName.value, "", "Custom integer name reset");
|
||||
is(customValue.value, 0, "Custom integer value reset");
|
||||
yield resetExistingField("accessibility.accesskeycausesactivation");
|
||||
|
||||
// Edit existing custom integer preference
|
||||
newPref.value = 3;
|
||||
newPref.click();
|
||||
is(newPref.value, 3, "Custom integer existing value is correct");
|
||||
addNewFieldBoolean();
|
||||
|
||||
// Reset a custom preference
|
||||
let resetBtn = doc.querySelector("#btn-new-integer-pref");
|
||||
resetBtn.click();
|
||||
|
||||
try {
|
||||
yield prefIframe.contentWindow.defaultPref;
|
||||
} catch(err) {
|
||||
let prefRow = doc.querySelector("#row-new-integer-pref");
|
||||
if (!prefRow) {
|
||||
found = false;
|
||||
}
|
||||
ok(!found, "Custom preference removed");
|
||||
}
|
||||
|
||||
// Reset an existing preference
|
||||
let existingPref = doc.getElementById("accessibility.accesskeycausesactivation");
|
||||
existingPref.click();
|
||||
is(existingPref.checked, false, "Existing boolean value is correct");
|
||||
resetBtn = doc.getElementById("btn-accessibility.accesskeycausesactivation");
|
||||
resetBtn.click();
|
||||
|
||||
yield prefIframe.contentWindow.defaultPref;
|
||||
|
||||
ok(resetBtn.classList.contains("hide"), true, "Reset button hidden");
|
||||
is(existingPref.checked, true, "Existing preference reset");
|
||||
|
||||
// Add a new custom boolean preference
|
||||
customValueType.value = "boolean";
|
||||
customValueType.dispatchEvent(change);
|
||||
customName.value = "new-boolean-pref";
|
||||
customValue.checked = true;
|
||||
found = false;
|
||||
customBtn.click();
|
||||
newPref = doc.querySelector("#new-boolean-pref");
|
||||
if (newPref) {
|
||||
found = true;
|
||||
is(newPref.type, "checkbox", "Custom type is a checkbox");
|
||||
is(newPref.checked, true, "Custom boolean value is correctly true");
|
||||
}
|
||||
ok(found, "Found new boolean preference line");
|
||||
|
||||
// Mouse event trigger
|
||||
var mouseClick = new MouseEvent("click", {
|
||||
canBubble: true,
|
||||
cancelable: true,
|
||||
view: doc.parent,
|
||||
});
|
||||
|
||||
found = false;
|
||||
customValueType.value = "boolean";
|
||||
customValueType.dispatchEvent(change);
|
||||
customName.value = "new-boolean-pref2";
|
||||
customValue.dispatchEvent(mouseClick);
|
||||
customBtn.dispatchEvent(mouseClick);
|
||||
newPref = doc.querySelector("#new-boolean-pref2");
|
||||
if (newPref) {
|
||||
found = true;
|
||||
is(newPref.checked, true, "Custom boolean value is correctly false");
|
||||
}
|
||||
ok(found, "Found new second boolean preference line");
|
||||
|
||||
is(customName.value, "", "Custom boolean name reset");
|
||||
is(customValue.checked, false, "Custom boolean value reset");
|
||||
|
||||
// Edit existing custom boolean preference
|
||||
newPref.click();
|
||||
is(newPref.checked, false, "Custom boolean existing value is correct");
|
||||
|
||||
// Search for a non-existent field
|
||||
let searchField = doc.querySelector("#search-bar");
|
||||
searchField.value = "![o_O]!";
|
||||
searchField.click();
|
||||
|
||||
let preferencesTotal = doc.querySelectorAll("tr.edit-row").length;
|
||||
let hiddenPreferences = doc.querySelectorAll("tr.hide");
|
||||
is(hiddenPreferences.length, preferencesTotal, "Search keyword not found");
|
||||
|
||||
// Search for existing fields
|
||||
searchField.value = "debugger";
|
||||
searchField.click();
|
||||
hiddenPreferences = doc.querySelectorAll("tr.hide");
|
||||
isnot(hiddenPreferences.length, preferencesTotal, "Search keyword found");
|
||||
|
||||
doc.querySelector("#close").click();
|
||||
|
||||
ok(!deck.selectedPanel, "No panel selected");
|
||||
searchFields(deck, "debugger");
|
||||
|
||||
DebuggerServer.destroy();
|
||||
|
||||
yield closeWebIDE(win);
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
}).then(null, e => {
|
||||
ok(false, "Exception: " + e);
|
||||
SimpleTest.finish();
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title></title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="head.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="device_front_shared.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.onload = function() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
Task.spawn(function*() {
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
|
||||
|
||||
if (SpecialPowers.isMainProcess()) {
|
||||
Cu.import("resource://gre/modules/SettingsRequestManager.jsm");
|
||||
}
|
||||
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
|
||||
let win = yield openWebIDE();
|
||||
|
||||
let settingIframe = win.document.querySelector("#deck-panel-devicesettings");
|
||||
|
||||
yield documentIsLoaded(settingIframe.contentWindow.document);
|
||||
|
||||
win.AppManager.update("runtimelist");
|
||||
|
||||
yield connectToLocalRuntime(win);
|
||||
|
||||
yield nextTick();
|
||||
|
||||
let settings = win.document.querySelector("#cmd_showSettings");
|
||||
|
||||
ok(!settings.hasAttribute("disabled"), "device settings cmd enabled");
|
||||
|
||||
let deck = win.document.querySelector("#deck");
|
||||
|
||||
win.Cmds.showSettings();
|
||||
is(deck.selectedPanel, settingIframe, "device settings iframe selected");
|
||||
|
||||
yield settingIframe.contentWindow.getAllSettings;
|
||||
yield nextTick();
|
||||
|
||||
setDocument(settingIframe);
|
||||
|
||||
let fields = doc.querySelectorAll(".editable");
|
||||
|
||||
addNewField();
|
||||
|
||||
addNewFieldWithEnter();
|
||||
|
||||
editExistingField();
|
||||
|
||||
addNewFieldInteger();
|
||||
|
||||
yield editFieldInteger();
|
||||
|
||||
yield resetNewField("new-string-field");
|
||||
|
||||
addNewFieldBoolean();
|
||||
|
||||
searchFields(deck, "new-boolean-field2");
|
||||
|
||||
DebuggerServer.destroy();
|
||||
|
||||
yield closeWebIDE(win);
|
||||
|
||||
SimpleTest.finish();
|
||||
}).then(null, e => {
|
||||
ok(false, "Exception: " + e);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -14,7 +14,7 @@ html, body {
|
|||
display: none;
|
||||
}
|
||||
|
||||
#device-preferences {
|
||||
#device-fields {
|
||||
font-family: sans-serif;
|
||||
padding-left: 6px;
|
||||
width: 100%;
|
||||
|
@ -37,31 +37,34 @@ header {
|
|||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
#device-preferences td {
|
||||
#device-fields td {
|
||||
background-color: #f1f1f1;
|
||||
border-bottom: 1px solid #ccc;
|
||||
border-right: 1px solid #fff;
|
||||
width: 33.3%;
|
||||
}
|
||||
|
||||
#device-preferences td.preference-name {
|
||||
#device-fields td:first-child {
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
#device-fields td.preference-name, #device-fields td.setting-name {
|
||||
width: 50%;
|
||||
min-width: 400px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
#device-preferences button {
|
||||
#device-fields button {
|
||||
display: inline-block;
|
||||
font-family: sans-serif;
|
||||
font-size: 0.7rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#device-preferences tr.hide, #device-preferences button.hide {
|
||||
#device-fields tr.hide, #device-fields button.hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#device-preferences .custom-input {
|
||||
#device-fields .custom-input {
|
||||
width: 300px;
|
||||
}
|
||||
|
|
@ -15,4 +15,4 @@ webide.jar:
|
|||
skin/runtimedetails.css (runtimedetails.css)
|
||||
skin/permissionstable.css (permissionstable.css)
|
||||
skin/monitor.css (monitor.css)
|
||||
skin/devicepreferences.css (devicepreferences.css)
|
||||
skin/config-view.css (config-view.css)
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
<!ENTITY runtimeMenu_showMonitor_accesskey "M">
|
||||
<!ENTITY runtimeMenu_showDevicePrefs_label "Device Preferences">
|
||||
<!ENTITY runtimeMenu_showDevicePrefs_accesskey "D">
|
||||
<!ENTITY runtimeMenu_showSettings_label "Device Settings">
|
||||
<!ENTITY runtimeMenu_showSettings_accesskey "s">
|
||||
|
||||
<!ENTITY viewMenu_label "View">
|
||||
<!ENTITY viewMenu_accesskey "V">
|
||||
|
@ -147,16 +149,26 @@
|
|||
<!ENTITY runtimedetails_requestPrivileges "request higher privileges">
|
||||
<!ENTITY runtimedetails_privilegesWarning "(Will reboot device. Requires root access.)">
|
||||
|
||||
<!-- Device Preferences and Settings -->
|
||||
<!ENTITY device_typeboolean "Boolean">
|
||||
<!ENTITY device_typenumber "Integer">
|
||||
<!ENTITY device_typestring "String">
|
||||
<!ENTITY device_typeobject "Object">
|
||||
<!ENTITY device_typenone "Select a type">
|
||||
|
||||
<!-- Device Preferences -->
|
||||
<!ENTITY devicepreferences_title "Device Preferences">
|
||||
<!ENTITY devicepreferences_search "Search preferences">
|
||||
<!ENTITY devicepreferences_newname "New preference name">
|
||||
<!ENTITY devicepreferences_newtext "Preference value">
|
||||
<!ENTITY devicepreferences_addnew "Add new preference">
|
||||
<!ENTITY devicepreferences_typeboolean "Boolean">
|
||||
<!ENTITY devicepreferences_typenumber "Integer">
|
||||
<!ENTITY devicepreferences_typestring "String">
|
||||
<!ENTITY devicepreferences_typenone "Select a type">
|
||||
<!ENTITY devicepreference_title "Device Preferences">
|
||||
<!ENTITY devicepreference_search "Search preferences">
|
||||
<!ENTITY devicepreference_newname "New preference name">
|
||||
<!ENTITY devicepreference_newtext "Preference value">
|
||||
<!ENTITY devicepreference_addnew "Add new preference">
|
||||
|
||||
<!-- Device Settings -->
|
||||
<!ENTITY devicesetting_title "Device Settings">
|
||||
<!ENTITY devicesetting_search "Search settings">
|
||||
<!ENTITY devicesetting_newname "New setting name">
|
||||
<!ENTITY devicesetting_newtext "Setting value">
|
||||
<!ENTITY devicesetting_addnew "Add new setting">
|
||||
|
||||
<!-- Monitor -->
|
||||
<!ENTITY monitor_title "Monitor">
|
||||
|
|
|
@ -75,5 +75,5 @@ status_warning=WARNINGS
|
|||
status_error=ERRORS
|
||||
status_unknown=UNKNOWN
|
||||
|
||||
# Preferences
|
||||
devicepreferences_reset_default=Reset to default
|
||||
# Device preferences and settings
|
||||
device_reset_default=Reset to default
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const {Cc, Ci, Cu, CC} = require("chrome");
|
||||
const protocol = require("devtools/server/protocol");
|
||||
const {Arg, method, RetVal} = protocol;
|
||||
const {DebuggerServer} = require("devtools/server/main");
|
||||
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let defaultSettings = {};
|
||||
let settingsFile;
|
||||
|
||||
exports.register = function(handle) {
|
||||
handle.addGlobalActor(SettingsActor, "settingsActor");
|
||||
};
|
||||
|
||||
exports.unregister = function(handle) {
|
||||
};
|
||||
|
||||
function getDefaultSettings() {
|
||||
let chan = NetUtil.newChannel(settingsFile);
|
||||
let stream = chan.open();
|
||||
// Obtain a converter to read from a UTF-8 encoded input stream.
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
let rawstr = converter.ConvertToUnicode(NetUtil.readInputStreamToString(
|
||||
stream,
|
||||
stream.available()) || "");
|
||||
|
||||
try {
|
||||
defaultSettings = JSON.parse(rawstr);
|
||||
} catch(e) { }
|
||||
stream.close();
|
||||
}
|
||||
|
||||
function loadSettingsFile() {
|
||||
// Loading resource://app/defaults/settings.json doesn't work because
|
||||
// settings.json is not in the omnijar.
|
||||
// So we look for the app dir instead and go from here...
|
||||
if (settingsFile) {
|
||||
return;
|
||||
}
|
||||
settingsFile = FileUtils.getFile("DefRt", ["settings.json"], false);
|
||||
if (!settingsFile || (settingsFile && !settingsFile.exists())) {
|
||||
// On b2g desktop builds the settings.json file is moved in the
|
||||
// profile directory by the build system.
|
||||
settingsFile = FileUtils.getFile("ProfD", ["settings.json"], false);
|
||||
if (!settingsFile || (settingsFile && !settingsFile.exists())) {
|
||||
console.log("settings.json file does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsFile.exists()) {
|
||||
getDefaultSettings();
|
||||
}
|
||||
}
|
||||
|
||||
let SettingsActor = exports.SettingsActor = protocol.ActorClass({
|
||||
typeName: "settings",
|
||||
|
||||
_getSettingsService: function() {
|
||||
let win = Services.wm.getMostRecentWindow(DebuggerServer.chromeWindowType);
|
||||
return win.navigator.mozSettings;
|
||||
},
|
||||
|
||||
getSetting: method(function(name) {
|
||||
let deferred = promise.defer();
|
||||
let lock = this._getSettingsService().createLock();
|
||||
let req = lock.get(name);
|
||||
req.onsuccess = function() {
|
||||
deferred.resolve(req.result[name]);
|
||||
};
|
||||
req.onerror = function() {
|
||||
deferred.reject(req.error);
|
||||
};
|
||||
return deferred.promise;
|
||||
}, {
|
||||
request: { value: Arg(0) },
|
||||
response: { value: RetVal("json") }
|
||||
}),
|
||||
|
||||
setSetting: method(function(name, value) {
|
||||
let deferred = promise.defer();
|
||||
let data = {};
|
||||
data[name] = value;
|
||||
let lock = this._getSettingsService().createLock();
|
||||
let req = lock.set(data);
|
||||
req.onsuccess = function() {
|
||||
deferred.resolve(true);
|
||||
};
|
||||
req.onerror = function() {
|
||||
deferred.reject(req.error);
|
||||
};
|
||||
return deferred.promise;
|
||||
}, {
|
||||
request: { name: Arg(0), value: Arg(1) },
|
||||
response: {}
|
||||
}),
|
||||
|
||||
_hasUserSetting: function(name, value) {
|
||||
if (typeof value === "object") {
|
||||
return JSON.stringify(defaultSettings[name]) !== JSON.stringify(value);
|
||||
}
|
||||
return (defaultSettings[name] !== value);
|
||||
},
|
||||
|
||||
getAllSettings: method(function() {
|
||||
loadSettingsFile();
|
||||
let settings = {};
|
||||
let self = this;
|
||||
|
||||
let deferred = promise.defer();
|
||||
let lock = this._getSettingsService().createLock();
|
||||
let req = lock.get("*");
|
||||
|
||||
req.onsuccess = function() {
|
||||
for (var name in req.result) {
|
||||
settings[name] = {
|
||||
value: req.result[name],
|
||||
hasUserValue: self._hasUserSetting(name, req.result[name])
|
||||
};
|
||||
}
|
||||
deferred.resolve(settings);
|
||||
};
|
||||
req.onfailure = function() {
|
||||
deferred.reject(req.error);
|
||||
};
|
||||
|
||||
return deferred.promise;
|
||||
}, {
|
||||
request: {},
|
||||
response: { value: RetVal("json") }
|
||||
}),
|
||||
|
||||
clearUserSetting: method(function(name) {
|
||||
loadSettingsFile();
|
||||
try {
|
||||
this.setSetting(name, defaultSettings[name]);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}, {
|
||||
request: { name: Arg(0) },
|
||||
response: {}
|
||||
})
|
||||
});
|
||||
|
||||
let SettingsFront = protocol.FrontClass(SettingsActor, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client);
|
||||
this.actorID = form.settingsActor;
|
||||
this.manage(this);
|
||||
},
|
||||
});
|
||||
|
||||
const _knownSettingsFronts = new WeakMap();
|
||||
|
||||
exports.getSettingsFront = function(client, form) {
|
||||
if (!form.settingsActor) {
|
||||
return null;
|
||||
}
|
||||
if (_knownSettingsFronts.has(client)) {
|
||||
return _knownSettingsFronts.get(client);
|
||||
}
|
||||
let front = new SettingsFront(client, form);
|
||||
_knownSettingsFronts.set(client, front);
|
||||
return front;
|
||||
};
|
||||
|
||||
// For tests
|
||||
exports._setDefaultSettings = function(settings) {
|
||||
defaultSettings = settings || {};
|
||||
};
|
|
@ -376,7 +376,14 @@ var DebuggerServer = {
|
|||
type: { global: true }
|
||||
});
|
||||
}
|
||||
|
||||
let win = Services.wm.getMostRecentWindow(DebuggerServer.chromeWindowType);
|
||||
if (win && win.navigator.mozSettings) {
|
||||
this.registerModule("devtools/server/actors/settings", {
|
||||
prefix: "settings",
|
||||
constructor: "SettingsActor",
|
||||
type: { global: true }
|
||||
});
|
||||
}
|
||||
this.registerModule("devtools/server/actors/webapps", {
|
||||
prefix: "webapps",
|
||||
constructor: "WebappsActor",
|
||||
|
|
|
@ -55,6 +55,7 @@ EXTRA_JS_MODULES.devtools.server.actors += [
|
|||
'actors/profiler.js',
|
||||
'actors/root.js',
|
||||
'actors/script.js',
|
||||
'actors/settings.js',
|
||||
'actors/storage.js',
|
||||
'actors/string.js',
|
||||
'actors/styleeditor.js',
|
||||
|
|
|
@ -71,6 +71,7 @@ skip-if = buildapp == 'mulet'
|
|||
[test_memory_census.html]
|
||||
[test_memory_gc_01.html]
|
||||
[test_preference.html]
|
||||
[test_settings.html]
|
||||
[test_connectToChild.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_attachProcess.html]
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Bug 1022797 - Settings support from WebIDE
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test Settings Actor</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/MochiKit/MochiKit.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script>
|
||||
|
||||
function runTests() {
|
||||
var Cu = Components.utils;
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
|
||||
|
||||
if (SpecialPowers.isMainProcess()) {
|
||||
Cu.import("resource://gre/modules/SettingsRequestManager.jsm");
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var {getSettingsFront, _setDefaultSettings} = devtools.require("devtools/server/actors/settings");
|
||||
|
||||
DebuggerServer.init(function () { return true; });
|
||||
DebuggerServer.addBrowserActors();
|
||||
|
||||
var client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
client.connect(function onConnect() {
|
||||
client.listTabs(function onListTabs(aResponse) {
|
||||
var s = getSettingsFront(client, aResponse);
|
||||
|
||||
var settings = {};
|
||||
var resetSettings = {};
|
||||
var fakeSettings = {
|
||||
"wifi.enabled": true,
|
||||
"audio.volume.alarm": 15,
|
||||
"app.reportCrashes": "ask",
|
||||
"app.someObject": { active: true }
|
||||
};
|
||||
var localSetting = {
|
||||
"wifi.enabled": false,
|
||||
"audio.volume.alarm": 0,
|
||||
"app.reportCrashes": "none",
|
||||
"app.someObject": {}
|
||||
};
|
||||
|
||||
function checkValues() {
|
||||
is(settings.allSettings["wifi.enabled"].hasUserValue, false, "original unchanged bool setting");
|
||||
is(settings.allSettings["audio.volume.alarm"].hasUserValue, false, "original unchanged int setting");
|
||||
is(settings.allSettings["app.reportCrashes"].hasUserValue, false, "original unchanged string setting");
|
||||
is(settings.allSettings["app.someObject"].hasUserValue, false, "original unchanged object setting");
|
||||
|
||||
is(settings.allSettings["wifi.enabled"].value, fakeSettings["wifi.enabled"], "original read/write bool setting");
|
||||
is(settings.allSettings["audio.volume.alarm"].value, fakeSettings["audio.volume.alarm"], "original read/write int setting");
|
||||
is(settings.allSettings["app.reportCrashes"].value, fakeSettings["app.reportCrashes"], "original read/write string setting");
|
||||
is(JSON.stringify(settings.allSettings["app.someObject"].value), JSON.stringify(fakeSettings["app.someObject"]), "original read/write object setting");
|
||||
|
||||
is(settings.allUpdatedSettings["wifi.enabled"].hasUserValue, true, "updated user-changed bool setting");
|
||||
is(settings.allUpdatedSettings["audio.volume.alarm"].hasUserValue, true, "updated user-changed int setting");
|
||||
is(settings.allUpdatedSettings["app.reportCrashes"].hasUserValue, true, "updated user-changed string setting");
|
||||
is(settings.allUpdatedSettings["app.someObject"].hasUserValue, true, "updated user-changed object setting");
|
||||
|
||||
is(settings["wifi.enabled"], localSetting["wifi.enabled"], "updated bool setting");
|
||||
is(settings["audio.volume.alarm"], localSetting["audio.volume.alarm"], "updated int setting");
|
||||
is(settings["app.reportCrashes"], localSetting["app.reportCrashes"], "updated string setting");
|
||||
is(JSON.stringify(settings["app.someObject"]), JSON.stringify(localSetting["app.someObject"]), "updated object as string setting");
|
||||
|
||||
is(resetSettings["wifi.enabled"], fakeSettings["wifi.enabled"], "reset to original bool setting");
|
||||
is(resetSettings["audio.volume.alarm"], fakeSettings["audio.volume.alarm"], "reset to original int setting");
|
||||
is(resetSettings["app.reportCrashes"], fakeSettings["app.reportCrashes"], "reset to original string setting");
|
||||
is(JSON.stringify(resetSettings["app.someObject"]), JSON.stringify(fakeSettings["app.someObject"]), "reset to original object setting");
|
||||
|
||||
client.close(() => {
|
||||
DebuggerServer.destroy();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
// settings.json doesn't exist outside of b2g so we will fake it.
|
||||
_setDefaultSettings(fakeSettings);
|
||||
s.setSetting("wifi.enabled", fakeSettings["wifi.enabled"])
|
||||
.then(() => s.setSetting("audio.volume.alarm", fakeSettings["audio.volume.alarm"]))
|
||||
.then(() => s.setSetting("app.reportCrashes", fakeSettings["app.reportCrashes"]))
|
||||
.then(() => s.setSetting("app.someObject", fakeSettings["app.someObject"]))
|
||||
.then(() => s.getAllSettings().then(json => settings.allSettings = json))
|
||||
.then(() => s.setSetting("wifi.enabled", localSetting["wifi.enabled"]))
|
||||
.then(() => s.setSetting("audio.volume.alarm", localSetting["audio.volume.alarm"]))
|
||||
.then(() => s.setSetting("app.reportCrashes", localSetting["app.reportCrashes"]))
|
||||
.then(() => s.setSetting("app.someObject", localSetting["app.someObject"]))
|
||||
.then(() => s.getAllSettings().then(json => settings.allUpdatedSettings = json))
|
||||
.then(() => s.getSetting("wifi.enabled")).then(value => settings["wifi.enabled"] = value)
|
||||
.then(() => s.getSetting("audio.volume.alarm")).then(value => settings["audio.volume.alarm"] = value)
|
||||
.then(() => s.getSetting("app.reportCrashes")).then(value => settings["app.reportCrashes"] = value)
|
||||
.then(() => s.getSetting("app.someObject")).then(value => settings["app.someObject"] = value)
|
||||
.then(() => s.clearUserSetting("wifi.enabled")).then(() => {
|
||||
s.getSetting("wifi.enabled").then(value => resetSettings["wifi.enabled"] = value);
|
||||
})
|
||||
.then(() => s.clearUserSetting("audio.volume.alarm")).then(() => {
|
||||
s.getSetting("audio.volume.alarm").then(value => resetSettings["audio.volume.alarm"] = value);
|
||||
})
|
||||
.then(() => s.clearUserSetting("app.reportCrashes")).then(() => {
|
||||
s.getSetting("app.reportCrashes").then(value => resetSettings["app.reportCrashes"] = value);
|
||||
})
|
||||
.then(() => s.clearUserSetting("app.someObject")).then(() => {
|
||||
s.getSetting("app.someObject").then(value => {
|
||||
resetSettings["app.someObject"] = value
|
||||
}).then(checkValues);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
window.onload = function () {
|
||||
runTests();
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче