Bug 982484 - Device preferences support. r=jryans
authorJennifer Fong <jen@ednapiranha.com>
Thu, 06 Nov 2014 09:36:00 -0500
changeset 226077 4bd45c680b98aff85bd4f19242c0efe39addf4bd
parent 226076 1afe68b5c5b0e6d3a1df8253491b706c42682cdb
child 226078 8b7521add52b9a6c570224c1780146b0ce5c221c
push id32
push userbmcbride@mozilla.com
push dateSun, 09 Nov 2014 12:47:32 +0000
reviewersjryans
bugs982484
milestone36.0a1
Bug 982484 - Device preferences support. r=jryans
browser/devtools/webide/content/devicepreferences.js
browser/devtools/webide/content/devicepreferences.xhtml
browser/devtools/webide/content/jar.mn
browser/devtools/webide/content/webide.js
browser/devtools/webide/content/webide.xul
browser/devtools/webide/test/chrome.ini
browser/devtools/webide/test/head.js
browser/devtools/webide/test/test_device_preferences.html
browser/devtools/webide/test/test_deviceinfo.html
browser/devtools/webide/themes/devicepreferences.css
browser/devtools/webide/themes/icons.png
browser/devtools/webide/themes/jar.mn
browser/devtools/webide/themes/webide.css
browser/locales/en-US/chrome/browser/devtools/webide.dtd
browser/locales/en-US/chrome/browser/devtools/webide.properties
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webide/content/devicepreferences.js
@@ -0,0 +1,320 @@
+/* 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 {Services} = Cu.import("resource://gre/modules/Services.jsm");
+const {require} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
+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");
+
+let devicePrefsKeys = {};
+let table;
+
+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;
+  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 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;
+}
+
+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 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 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);
+  }
+}
+
+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 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 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]);
+  }
+
+  if (AppManager.connection &&
+      AppManager.connection.status == Connection.Status.CONNECTED &&
+      AppManager.preferenceFront) {
+    AppManager.preferenceFront.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);
+      }
+    });
+  } else {
+    CloseUI();
+  }
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webide/content/devicepreferences.xhtml
@@ -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://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/devicepreferences.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>&devicepreferences_title;</h1>
+      <div id="search">
+        <input type="text" id="search-bar" placeholder="&devicepreferences_search;"/>
+      </div>
+    </header>
+    <table id="device-preferences">
+      <tr id="add-custom-preference">
+        <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>
+          </select>
+          <input type="text" id="custom-value-name" placeholder="&devicepreferences_newname;"/>
+        </td>
+        <td class="custom-input">
+          <input type="text" id="custom-value-text" placeholder="&devicepreferences_newtext;"/>
+        </td>
+        <td>
+          <button id="custom-value" class="new-editable">&devicepreferences_addnew;</button>
+        </td>
+      </tr>
+    </table>
+  </body>
+</html>
--- a/browser/devtools/webide/content/jar.mn
+++ b/browser/devtools/webide/content/jar.mn
@@ -15,8 +15,10 @@ webide.jar:
     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)
--- a/browser/devtools/webide/content/webide.js
+++ b/browser/devtools/webide/content/webide.js
@@ -760,16 +760,17 @@ let UI = {
       document.querySelector("#cmd_removeProject").setAttribute("disabled", "true");
       document.querySelector("#cmd_disconnectRuntime").setAttribute("disabled", "true");
       document.querySelector("#cmd_showPermissionsTable").setAttribute("disabled", "true");
       document.querySelector("#cmd_takeScreenshot").setAttribute("disabled", "true");
       document.querySelector("#cmd_showRuntimeDetails").setAttribute("disabled", "true");
       document.querySelector("#cmd_play").setAttribute("disabled", "true");
       document.querySelector("#cmd_stop").setAttribute("disabled", "true");
       document.querySelector("#cmd_toggleToolbox").setAttribute("disabled", "true");
+      document.querySelector("#cmd_showDevicePrefs").setAttribute("disabled", "true");
       return;
     }
 
     document.querySelector("#cmd_newApp").removeAttribute("disabled");
     document.querySelector("#cmd_importPackagedApp").removeAttribute("disabled");
     document.querySelector("#cmd_importHostedApp").removeAttribute("disabled");
     document.querySelector("#cmd_showProjectPanel").removeAttribute("disabled");
     document.querySelector("#cmd_showRuntimePanel").removeAttribute("disabled");
@@ -822,33 +823,38 @@ let UI = {
       removeCmdNode.setAttribute("disabled", "true");
     }
 
     // Runtime commands
     let screenshotCmd = document.querySelector("#cmd_takeScreenshot");
     let permissionsCmd = document.querySelector("#cmd_showPermissionsTable");
     let detailsCmd = document.querySelector("#cmd_showRuntimeDetails");
     let disconnectCmd = document.querySelector("#cmd_disconnectRuntime");
+    let devicePrefsCmd = document.querySelector("#cmd_showDevicePrefs");
 
     let box = document.querySelector("#runtime-actions");
 
     let runtimePanelButton = document.querySelector("#runtime-panel-button");
     if (AppManager.connection.status == Connection.Status.CONNECTED) {
       if (AppManager.deviceFront) {
         detailsCmd.removeAttribute("disabled");
         permissionsCmd.removeAttribute("disabled");
         screenshotCmd.removeAttribute("disabled");
       }
+      if (AppManager.preferenceFront) {
+        devicePrefsCmd.removeAttribute("disabled");
+      }
       disconnectCmd.removeAttribute("disabled");
       runtimePanelButton.setAttribute("active", "true");
     } else {
       detailsCmd.setAttribute("disabled", "true");
       permissionsCmd.setAttribute("disabled", "true");
       screenshotCmd.setAttribute("disabled", "true");
       disconnectCmd.setAttribute("disabled", "true");
+      devicePrefsCmd.setAttribute("disabled", "true");
       runtimePanelButton.removeAttribute("active");
     }
 
   },
 
   /********** TOOLBOX **********/
 
   onMessage: function(event) {
@@ -1176,16 +1182,20 @@ let Cmds = {
   showPermissionsTable: function() {
     UI.selectDeckPanel("permissionstable");
   },
 
   showRuntimeDetails: function() {
     UI.selectDeckPanel("runtimedetails");
   },
 
+  showDevicePrefs: function() {
+    UI.selectDeckPanel("devicepreferences");
+  },
+
   showMonitor: function() {
     UI.selectDeckPanel("monitor");
   },
 
   play: function() {
     let busy;
     switch(AppManager.selectedProject.type) {
       case "packaged":
--- a/browser/devtools/webide/content/webide.xul
+++ b/browser/devtools/webide/content/webide.xul
@@ -30,16 +30,17 @@
 
   <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_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;"/>
@@ -73,16 +74,17 @@
     </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;"/>
         <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;"/>
@@ -160,16 +162,17 @@
         <label class="panel-header">&runtimePanel_simulator;</label>
         <vbox id="runtime-panel-simulator"></vbox>
         <toolbarbutton class="panel-item" label="&runtimePanel_installsimulator;" id="runtime-panel-installsimulator" command="cmd_showAddons"/>
         <label class="panel-header">&runtimePanel_other;</label>
         <vbox id="runtime-panel-other"></vbox>
         <vbox flex="1" id="runtime-actions">
           <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-screenshot"  command="cmd_takeScreenshot"/>
           <toolbarbutton class="panel-item" id="runtime-disconnect"  command="cmd_disconnectRuntime"/>
         </vbox>
       </vbox>
     </panel>
 
   </popupset>
 
@@ -177,15 +180,16 @@
     <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" src="permissionstable.xhtml"/>
       <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"/>
     </deck>
     <splitter hidden="true" class="devtools-horizontal-splitter" orient="vertical"/>
     <!-- toolbox iframe will be inserted here -->
   </notificationbox>
 
 
 </window>
--- a/browser/devtools/webide/test/chrome.ini
+++ b/browser/devtools/webide/test/chrome.ini
@@ -33,8 +33,9 @@ support-files =
 [test_import.html]
 [test_duplicate_import.html]
 [test_runtime.html]
 [test_manifestUpdate.html]
 [test_addons.html]
 [test_deviceinfo.html]
 [test_autoconnect_runtime.html]
 [test_telemetry.html]
+[test_device_preferences.html]
--- a/browser/devtools/webide/test/head.js
+++ b/browser/devtools/webide/test/head.js
@@ -168,12 +168,31 @@ function removeTab(aTab, aWindow) {
     info("Tab removed and finished closing.");
     deferred.resolve();
   }, false);
 
   targetBrowser.removeTab(aTab);
   return deferred.promise;
 }
 
+function connectToLocalRuntime(aWindow) {
+  info("Loading local runtime.");
+
+  let panelNode = aWindow.document.querySelector("#runtime-panel");
+  let items = panelNode.querySelectorAll(".runtime-panel-item-other");
+  is(items.length, 2, "Found 2 custom runtime buttons");
+
+  let deferred = promise.defer();
+  aWindow.AppManager.on("app-manager-update", function onUpdate(e,w) {
+    if (w == "list-tabs-response") {
+      aWindow.AppManager.off("app-manager-update", onUpdate);
+      deferred.resolve();
+    }
+  });
+
+  items[1].click();
+  return deferred.promise;
+}
+
 function handleError(aError) {
   ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
   finish();
 }
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webide/test/test_device_preferences.html
@@ -0,0 +1,242 @@
+<!DOCTYPE html>
+
+<html>
+
+  <head>
+    <meta charset="utf8">
+    <title></title>
+    <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+    <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
+    <script type="application/javascript;version=1.8" src="head.js"></script>
+    <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+  </head>
+
+  <body>
+
+    <script type="application/javascript;version=1.8">
+      window.onload = function() {
+        SimpleTest.waitForExplicitFinish();
+
+        Task.spawn(function* () {
+          Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
+
+          if (!DebuggerServer.initialized) {
+            DebuggerServer.init(function () { return true; });
+            DebuggerServer.addBrowserActors();
+          }
+
+          let win = yield openWebIDE();
+
+          let prefIframe = win.document.querySelector("#deck-panel-devicepreferences");
+
+          yield documentIsLoaded(prefIframe.contentWindow.document);
+
+          win.AppManager.update("runtimelist");
+
+          yield connectToLocalRuntime(win);
+
+          yield nextTick();
+
+          let prefs = win.document.querySelector("#cmd_showDevicePrefs");
+
+          ok(!prefs.hasAttribute("disabled"), "device prefs cmd enabled");
+
+          let deck = win.document.querySelector("#deck");
+
+          win.Cmds.showDevicePrefs();
+          is(deck.selectedPanel, prefIframe, "device preferences iframe selected");
+
+          yield nextTick();
+
+          let doc = prefIframe.contentWindow.document;
+          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");
+
+          // 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);
+
+          // 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");
+
+          // 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");
+
+          // Edit existing custom string preference
+          newPref.value = "test2";
+          newPref.click();
+          is(newPref.value, "test2", "Custom string existing value is correct");
+
+          // 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;
+
+          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");
+
+          // Edit existing custom integer preference
+          newPref.value = 3;
+          newPref.click();
+          is(newPref.value, 3, "Custom integer existing value is correct");
+
+          // 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");
+
+          DebuggerServer.destroy();
+
+          yield closeWebIDE(win);
+
+          SimpleTest.finish();
+
+        }).then(null, e => {
+          ok(false, "Exception: " + e);
+          SimpleTest.finish();
+        });
+      }
+    </script>
+  </body>
+</html>
--- a/browser/devtools/webide/test/test_deviceinfo.html
+++ b/browser/devtools/webide/test/test_deviceinfo.html
@@ -29,33 +29,17 @@
           let win = yield openWebIDE();
 
           let permIframe = win.document.querySelector("#deck-panel-permissionstable");
           let infoIframe = win.document.querySelector("#deck-panel-runtimedetails");
 
           yield documentIsLoaded(permIframe.contentWindow.document);
           yield documentIsLoaded(infoIframe.contentWindow.document);
 
-          win.AppManager._rebuildRuntimeList();
-
-          let panelNode = win.document.querySelector("#runtime-panel");
-          let items = panelNode.querySelectorAll(".runtime-panel-item-other");
-          is(items.length, 2, "Found 2 other runtimes button");
-
-          let deferred = promise.defer();
-          win.AppManager.on("app-manager-update", function onUpdate(e,w) {
-            if (w == "list-tabs-response") {
-              win.AppManager.off("app-manager-update", onUpdate);
-              deferred.resolve();
-            }
-          });
-
-          items[1].click();
-
-          yield deferred.promise;
+          yield connectToLocalRuntime(win);
 
           yield nextTick();
 
           let perm = win.document.querySelector("#cmd_showPermissionsTable");
           let info = win.document.querySelector("#cmd_showRuntimeDetails");
 
           ok(!perm.hasAttribute("disabled"), "perm cmd enabled");
           ok(!info.hasAttribute("disabled"), "info cmd enabled");
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webide/themes/devicepreferences.css
@@ -0,0 +1,75 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+html, body {
+  background: white;
+}
+
+.action {
+  display: inline;
+}
+
+.action[hidden] {
+  display: none;
+}
+
+#device-preferences {
+  font-family: sans-serif;
+  padding-left: 6px;
+  width: 100%;
+  table-layout: auto;
+  margin-top: 110px;
+}
+
+#custom-value-name {
+  width: 70%;
+}
+
+header {
+  background-color: rgba(255, 255, 255, 0.8);
+  border-bottom: 1px solid #EEE;
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  height: 90px;
+  padding: 10px 20px;
+}
+
+#device-preferences td {
+  background-color: #f1f1f1;
+  border-bottom: 1px solid #ccc;
+  border-right: 1px solid #fff;
+  width: 33.3%;
+}
+
+#device-preferences td.preference-name {
+  width: 50%;
+  min-width: 400px;
+  word-break: break-all;
+}
+
+#device-preferences button {
+  display: inline-block;
+  font-family: sans-serif;
+  font-size: 0.7rem;
+  white-space: nowrap;
+}
+
+#device-preferences tr.hide, #device-preferences button.hide {
+  display: none;
+}
+
+#device-preferences .custom-input {
+  width: 300px;
+}
+
+#search {
+  margin-bottom: 20px;
+  width: 100%;
+}
+
+#search-bar {
+  width: 80%;
+}
index 0babd45c326ffe44e3b9b132c149900ca5b416fd..5e1dd5c64ce32bed9926e4bdb1bd8c1d0f676a63
GIT binary patch
literal 35353
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
--- a/browser/devtools/webide/themes/jar.mn
+++ b/browser/devtools/webide/themes/jar.mn
@@ -10,8 +10,9 @@ webide.jar:
   skin/newapp.css              (newapp.css)
   skin/throbber.svg            (throbber.svg)
   skin/deck.css                (deck.css)
   skin/addons.css              (addons.css)
   skin/prefs.css               (prefs.css)
   skin/runtimedetails.css      (runtimedetails.css)
   skin/permissionstable.css    (permissionstable.css)
   skin/monitor.css             (monitor.css)
+  skin/devicepreferences.css   (devicepreferences.css)
--- a/browser/devtools/webide/themes/webide.css
+++ b/browser/devtools/webide/themes/webide.css
@@ -211,30 +211,32 @@ panel > .panel-arrowcontainer > .panel-a
 
 #runtime-panel-other {
   margin-bottom: 12px;
 }
 
 #runtime-details,
 #runtime-screenshot,
 #runtime-permissions,
+#runtime-preferences,
 #runtime-disconnect,
 #runtime-panel-nousbdevice,
 #runtime-panel-noadbhelper,
 #runtime-panel-installsimulator,
 .runtime-panel-item-usb,
 .runtime-panel-item-wifi,
 .runtime-panel-item-other,
 .runtime-panel-item-simulator {
   list-style-image: url("icons.png");
 }
 
 #runtime-details                { -moz-image-region: rect(156px,438px,182px,412px) }
 #runtime-screenshot             { -moz-image-region: rect(130px,438px,156px,412px) }
 #runtime-permissions            { -moz-image-region: rect(104px,438px,130px,412px) }
+#runtime-preferences            { -moz-image-region: rect(104px,462px,129px,438px) }
 #runtime-disconnect             { -moz-image-region: rect(52px,438px,78px,412px) }
 #runtime-panel-nousbdevice      { -moz-image-region: rect(156px,438px,182px,412px) }
 #runtime-panel-noadbhelper      { -moz-image-region: rect(234px,438px,260px,412px) }
 #runtime-panel-installsimulator { -moz-image-region: rect(0px,438px,26px,412px) }
 .runtime-panel-item-usb         { -moz-image-region: rect(52px,438px,78px,412px) }
 .runtime-panel-item-wifi        { -moz-image-region: rect(208px,438px,234px,412px) }
 .runtime-panel-item-other       { -moz-image-region: rect(26px,438px,52px,412px) }
 .runtime-panel-item-simulator   { -moz-image-region: rect(0px,438px,26px,412px) }
--- a/browser/locales/en-US/chrome/browser/devtools/webide.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/webide.dtd
@@ -34,16 +34,18 @@
 <!ENTITY runtimeMenu_showPermissionTable_label "Permissions Table">
 <!ENTITY runtimeMenu_showPermissionTable_accesskey "P">
 <!ENTITY runtimeMenu_takeScreenshot_label "Screenshot">
 <!ENTITY runtimeMenu_takeScreenshot_accesskey "S">
 <!ENTITY runtimeMenu_showDetails_label "Runtime Info">
 <!ENTITY runtimeMenu_showDetails_accesskey "E">
 <!ENTITY runtimeMenu_showMonitor_label "Monitor">
 <!ENTITY runtimeMenu_showMonitor_accesskey "M">
+<!ENTITY runtimeMenu_showDevicePrefs_label "Device Preferences">
+<!ENTITY runtimeMenu_showDevicePrefs_accesskey "D">
 
 <!ENTITY viewMenu_label "View">
 <!ENTITY viewMenu_accesskey "V">
 <!ENTITY viewMenu_toggleEditor_label "Toggle Editor">
 <!ENTITY viewMenu_toggleEditor_accesskey "E">
 
 <!ENTITY projectButton_label "Open App">
 <!ENTITY runtimeButton_label "Select Runtime">
@@ -127,11 +129,22 @@
 <!ENTITY runtimedetails_title "Runtime Info">
 <!ENTITY runtimedetails_adbIsRoot "ADB is root: ">
 <!ENTITY runtimedetails_summonADBRoot "root device">
 <!ENTITY runtimedetails_ADBRootWarning "(requires unlocked bootloader)">
 <!ENTITY runtimedetails_restrictedPrivileges "DevTools restricted privileges: ">
 <!ENTITY runtimedetails_requestPrivileges "request higher privileges">
 <!ENTITY runtimedetails_privilegesWarning "(Will reboot device. Requires root access.)">
 
+<!-- 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">
+
 <!-- Monitor -->
 <!ENTITY monitor_title "Monitor">
 <!ENTITY monitor_help "Help">
--- a/browser/locales/en-US/chrome/browser/devtools/webide.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/webide.properties
@@ -67,8 +67,11 @@ runtimedetails_checkunkown=unknown
 runtimedetails_notUSBDevice=Not a USB device
 
 # Validation status
 status_tooltip=Validation status: %1$S
 status_valid=VALID
 status_warning=WARNINGS
 status_error=ERRORS
 status_unknown=UNKNOWN
+
+# Preferences
+devicepreferences_reset_default=Reset to default