Bug 1045660 - Remember last selected runtime in WebIDE. r=jryans
authorAlexandre Poirot <poirot.alex@gmail.com>
Thu, 18 Sep 2014 07:27:00 -0400
changeset 206478 9119c622fdf3719a733af44258728b1cd83b9609
parent 206477 c10eea79e5596b7a5b20ca44707567c1356fd0b9
child 206479 9e88f96e430fdfd9db73daec11cbd957dd21a00f
push id27528
push userryanvm@gmail.com
push dateMon, 22 Sep 2014 19:27:54 +0000
treeherdermozilla-central@d8688cafc752 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjryans
bugs1045660
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1045660 - Remember last selected runtime in WebIDE. r=jryans
browser/devtools/webide/content/webide.js
browser/devtools/webide/modules/app-manager.js
browser/devtools/webide/modules/runtimes.js
browser/devtools/webide/test/chrome.ini
browser/devtools/webide/test/test_autoconnect_runtime.html
browser/devtools/webide/webide-prefs.js
--- a/browser/devtools/webide/content/webide.js
+++ b/browser/devtools/webide/content/webide.js
@@ -70,16 +70,18 @@ let UI = {
     let autoInstallADBHelper = Services.prefs.getBoolPref("devtools.webide.autoinstallADBHelper");
     if (autoInstallADBHelper && !Devices.helperAddonInstalled) {
       GetAvailableAddons().then(addons => {
         addons.adb.install();
       }, console.error);
     }
     Services.prefs.setBoolPref("devtools.webide.autoinstallADBHelper", false);
 
+    this.lastConnectedRuntime = Services.prefs.getCharPref("devtools.webide.lastConnectedRuntime");
+
     this.setupDeck();
   },
 
   openLastProject: function() {
     let lastProjectLocation = Services.prefs.getCharPref("devtools.webide.lastprojectlocation");
     let shouldRestore = Services.prefs.getBoolPref("devtools.webide.restoreLastProject");
     if (lastProjectLocation && shouldRestore) {
       let lastProject = AppProjects.get(lastProjectLocation);
@@ -120,16 +122,17 @@ let UI = {
     }
   },
 
   appManagerUpdate: function(event, what, details) {
     // Got a message from app-manager.js
     switch (what) {
       case "runtimelist":
         this.updateRuntimeList();
+        this.autoConnectRuntime();
         break;
       case "connection":
         this.updateRuntimeButton();
         this.updateCommands();
         break;
       case "project":
         this.updateTitle();
         this.destroyToolbox();
@@ -140,16 +143,17 @@ let UI = {
         break;
       case "project-is-not-running":
       case "project-is-running":
       case "list-tabs-response":
         this.updateCommands();
         break;
       case "runtime":
         this.updateRuntimeButton();
+        this.saveLastConnectedRuntime();
         break;
       case "project-validated":
         this.updateTitle();
         this.updateCommands();
         this.updateProjectButton();
         this.updateProjectEditorHeader();
         break;
       case "install-progress":
@@ -338,32 +342,71 @@ let UI = {
           this.hidePanels();
           this.dismissErrorNotification();
           this.connectToRuntime(r);
         }, true);
       }
     }
   },
 
+  autoConnectRuntime: function () {
+    // Automatically reconnect to the previously selected runtime,
+    // if available and has an ID
+    if (AppManager.selectedRuntime || !this.lastConnectedRuntime) {
+      return;
+    }
+    let [_, type, id] = this.lastConnectedRuntime.match(/^(\w+):(.+)$/);
+
+    type = type.toLowerCase();
+
+    // Local connection is mapped to AppManager.runtimeList.custom array
+    if (type == "local") {
+      type = "custom";
+    }
+
+    // We support most runtimes except simulator, that needs to be manually
+    // launched
+    if (type == "usb" || type == "wifi" || type == "custom") {
+      for (let runtime of AppManager.runtimeList[type]) {
+        // Some runtimes do not expose getID function and don't support
+        // autoconnect (like remote connection)
+        if (typeof(runtime.getID) == "function" && runtime.getID() == id) {
+          this.connectToRuntime(runtime);
+        }
+      }
+    }
+  },
+
   connectToRuntime: function(runtime) {
     let name = runtime.getName();
     let promise = AppManager.connectToRuntime(runtime);
     return this.busyUntil(promise, "connecting to runtime");
   },
 
   updateRuntimeButton: function() {
     let labelNode = document.querySelector("#runtime-panel-button > .panel-button-label");
     if (!AppManager.selectedRuntime) {
       labelNode.setAttribute("value", Strings.GetStringFromName("runtimeButton_label"));
     } else {
       let name = AppManager.selectedRuntime.getName();
       labelNode.setAttribute("value", name);
     }
   },
 
+  saveLastConnectedRuntime: function () {
+    if (AppManager.selectedRuntime &&
+        typeof(AppManager.selectedRuntime.getID) === "function") {
+      this.lastConnectedRuntime = AppManager.selectedRuntime.type + ":" + AppManager.selectedRuntime.getID();
+    } else {
+      this.lastConnectedRuntime = "";
+    }
+    Services.prefs.setCharPref("devtools.webide.lastConnectedRuntime",
+                               this.lastConnectedRuntime);
+  },
+
   /********** PROJECTS **********/
 
   // Panel & button
 
   updateProjectButton: function() {
     let buttonNode = document.querySelector("#project-panel-button");
     let labelNode = buttonNode.querySelector(".panel-button-label");
     let imageNode = buttonNode.querySelector(".panel-button-image");
--- a/browser/devtools/webide/modules/app-manager.js
+++ b/browser/devtools/webide/modules/app-manager.js
@@ -646,17 +646,25 @@ exports.AppManager = AppManager = {
     Devices.off("addon-status-updated", this._updateUSBRuntimes);
   },
   _updateUSBRuntimes: function() {
     this.runtimeList.usb = [];
     for (let id of Devices.available()) {
       let r = new USBRuntime(id);
       this.runtimeList.usb.push(r);
       r.updateNameFromADB().then(
-        () => this.update("runtimelist"), () => {});
+        () => {
+          this.update("runtimelist");
+          // Also update the runtime button label, if the currently selected
+          // runtime name changes
+          if (r == this.selectedRuntime) {
+            this.update("runtime");
+          }
+        },
+        () => {});
     }
     this.update("runtimelist");
   },
 
   get isWiFiScanningEnabled() {
     return Services.prefs.getBoolPref(WIFI_SCANNING_PREF);
   },
   scanForWiFiRuntimes: function() {
--- a/browser/devtools/webide/modules/runtimes.js
+++ b/browser/devtools/webide/modules/runtimes.js
@@ -126,16 +126,19 @@ let gLocalRuntime = {
     connection.host = null; // Force Pipe transport
     connection.port = null;
     connection.connect();
     return promise.resolve();
   },
   getName: function() {
     return Strings.GetStringFromName("local_runtime");
   },
+  getID: function () {
+    return "local";
+  }
 }
 
 let gRemoteRuntime = {
   type: RuntimeTypes.remote,
   connect: function(connection) {
     let win = Services.wm.getMostRecentWindow("devtools:webide");
     if (!win) {
       return promise.reject();
--- a/browser/devtools/webide/test/chrome.ini
+++ b/browser/devtools/webide/test/chrome.ini
@@ -26,8 +26,9 @@ support-files =
 
 [test_basic.html]
 [test_newapp.html]
 [test_import.html]
 [test_runtime.html]
 [test_manifestUpdate.html]
 [test_addons.html]
 [test_deviceinfo.html]
+[test_autoconnect_runtime.html]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webide/test/test_autoconnect_runtime.html
@@ -0,0 +1,91 @@
+<!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");
+          DebuggerServer.init(function () { return true; });
+          DebuggerServer.addBrowserActors();
+
+          let win = yield openWebIDE();
+
+          let fakeRuntime = {
+            type: "USB",
+            connect: function(connection) {
+              ok(connection, win.AppManager.connection, "connection is valid");
+              connection.host = null; // force connectPipe
+              connection.connect();
+              return promise.resolve();
+            },
+
+            getID: function() {
+              return "fakeRuntime";
+            },
+
+            getName: function() {
+              return "fakeRuntime";
+            }
+          };
+          win.AppManager.runtimeList.usb.push(fakeRuntime);
+          win.AppManager.update("runtimelist");
+
+          let panelNode = win.document.querySelector("#runtime-panel");
+          let items = panelNode.querySelectorAll(".runtime-panel-item-usb");
+          is(items.length, 1, "Found one runtime button");
+
+          let deferred = promise.defer();
+          win.AppManager.connection.once(
+              win.Connection.Events.CONNECTED,
+              () => deferred.resolve());
+          items[0].click();
+
+          ok(win.document.querySelector("window").className, "busy", "UI is busy");
+          yield win.UI._busyPromise;
+          is(Object.keys(DebuggerServer._connections).length, 1, "Connected");
+
+          yield nextTick();
+
+          yield closeWebIDE(win);
+
+          is(Object.keys(DebuggerServer._connections).length, 0, "Disconnected");
+
+          win = yield openWebIDE();
+
+          win.AppManager.runtimeList.usb.push(fakeRuntime);
+          win.AppManager.update("runtimelist");
+
+          yield waitForUpdate(win, "list-tabs-response");
+
+          is(Object.keys(DebuggerServer._connections).length, 1, "Automatically reconnected");
+
+          yield win.Cmds.disconnectRuntime();
+
+          yield closeWebIDE(win);
+
+          DebuggerServer.destroy();
+
+          SimpleTest.finish();
+        });
+      }
+
+
+    </script>
+  </body>
+</html>
--- a/browser/devtools/webide/webide-prefs.js
+++ b/browser/devtools/webide/webide-prefs.js
@@ -10,8 +10,9 @@ pref("devtools.webide.lastprojectlocatio
 pref("devtools.webide.restoreLastProject", true);
 pref("devtools.webide.enableLocalRuntime", false);
 pref("devtools.webide.addonsURL", "https://ftp.mozilla.org/pub/mozilla.org/labs/fxos-simulator/index.json");
 pref("devtools.webide.simulatorAddonsURL", "https://ftp.mozilla.org/pub/mozilla.org/labs/fxos-simulator/#VERSION#/#OS#/fxos_#SLASHED_VERSION#_simulator-#OS#-latest.xpi");
 pref("devtools.webide.simulatorAddonID", "fxos_#SLASHED_VERSION#_simulator@mozilla.org");
 pref("devtools.webide.adbAddonURL", "https://ftp.mozilla.org/pub/mozilla.org/labs/fxos-simulator/adb-helper/#OS#/adbhelper-#OS#-latest.xpi");
 pref("devtools.webide.adbAddonID", "adbhelper@mozilla.org");
 pref("devtools.webide.monitorWebSocketURL", "ws://localhost:9000");
+pref("devtools.webide.lastConnectedRuntime", "");