Bug 1103120 - Part 12: Client: Receive pending auth message from server. r=past
authorJ. Ryan Stinnett <jryans@gmail.com>
Mon, 26 Jan 2015 12:47:13 -0600
changeset 225854 dd5baaca1e275d00246d69e4742f45e61b1d154a
parent 225853 5a2adc1655638a8653d9e8e7e9488793ebe7cca6
child 225855 869fb4fbada04dece6545789f59e2b68d54e03ad
push id28176
push userryanvm@gmail.com
push dateMon, 26 Jan 2015 21:48:45 +0000
treeherdermozilla-central@38e4719e71af [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspast
bugs1103120
milestone38.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 1103120 - Part 12: Client: Receive pending auth message from server. r=past
toolkit/devtools/security/auth.js
toolkit/devtools/security/socket.js
--- a/toolkit/devtools/security/auth.js
+++ b/toolkit/devtools/security/auth.js
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 let { Ci } = require("chrome");
 let Services = require("Services");
+let promise = require("promise");
 loader.lazyRequireGetter(this, "prompt",
   "devtools/toolkit/security/prompt");
 
 /**
  * A simple enum-like object with keys mirrored to values.
  * This makes comparison to a specfic value simpler without having to repeat and
  * mis-type the value.
  */
@@ -83,16 +84,34 @@ let Prompt = Authenticators.Prompt = {};
 
 Prompt.mode = "PROMPT";
 
 Prompt.Client = function() {};
 Prompt.Client.prototype = {
 
   mode: Prompt.mode,
 
+  /**
+   * Work with the server to complete any additional steps required by this
+   * authenticator's policies.
+   *
+   * Debugging commences after this hook completes successfully.
+   *
+   * @param host string
+   *        The host name or IP address of the debugger server.
+   * @param port number
+   *        The port number of the debugger server.
+   * @param encryption boolean (optional)
+   *        Whether the server requires encryption.  Defaults to false.
+   * @param transport DebuggerTransport
+   *        A transport that can be used to communicate with the server.
+   * @return A promise can be used if there is async behavior.
+   */
+  authenticate() {},
+
 };
 
 Prompt.Server = function() {};
 Prompt.Server.prototype = {
 
   mode: Prompt.mode,
 
   /**
@@ -207,16 +226,44 @@ let OOBCert = Authenticators.OOBCert = {
 
 OOBCert.mode = "OOB_CERT";
 
 OOBCert.Client = function() {};
 OOBCert.Client.prototype = {
 
   mode: OOBCert.mode,
 
+  /**
+   * Work with the server to complete any additional steps required by this
+   * authenticator's policies.
+   *
+   * Debugging commences after this hook completes successfully.
+   *
+   * @param host string
+   *        The host name or IP address of the debugger server.
+   * @param port number
+   *        The port number of the debugger server.
+   * @param encryption boolean (optional)
+   *        Whether the server requires encryption.  Defaults to false.
+   * @param transport DebuggerTransport
+   *        A transport that can be used to communicate with the server.
+   * @return A promise can be used if there is async behavior.
+   */
+  authenticate({ transport }) {
+    let deferred = promise.defer();
+    transport.hooks = {
+      onPacket(packet) {
+        let { authResult } = packet;
+        // TODO: Examine the result
+      }
+    };
+    transport.ready();
+    return deferred.promise;
+  },
+
 };
 
 OOBCert.Server = function() {};
 OOBCert.Server.prototype = {
 
   mode: OOBCert.mode,
 
   /**
--- a/toolkit/devtools/security/socket.js
+++ b/toolkit/devtools/security/socket.js
@@ -58,53 +58,100 @@ let DebuggerSocket = {};
  * Connects to a debugger server socket.
  *
  * @param host string
  *        The host name or IP address of the debugger server.
  * @param port number
  *        The port number of the debugger server.
  * @param encryption boolean (optional)
  *        Whether the server requires encryption.  Defaults to false.
+ * @param authenticator Authenticator (optional)
+ *        |Authenticator| instance matching the mode in use by the server.
+ *        Defaults to a PROMPT instance if not supplied.
  * @return promise
  *         Resolved to a DebuggerTransport instance.
  */
-DebuggerSocket.connect = Task.async(function*({ host, port, encryption }) {
-  let attempt = yield _attemptTransport({ host, port, encryption });
+DebuggerSocket.connect = Task.async(function*(settings) {
+  let { host, port, encryption, authenticator } = settings;
+  let transport = yield _getTransport(settings);
+
+  // Default to PROMPT |Authenticator| instance if not supplied
+  authenticator = authenticator || new (Authenticators.get().Client)();
+
+  yield authenticator.authenticate({
+    host,
+    port,
+    encryption,
+    transport
+  });
+  return transport;
+});
+
+/**
+ * Try very hard to create a DevTools transport, potentially making several
+ * connect attempts in the process.
+ *
+ * @param host string
+ *        The host name or IP address of the debugger server.
+ * @param port number
+ *        The port number of the debugger server.
+ * @param encryption boolean (optional)
+ *        Whether the server requires encryption.  Defaults to false.
+ * @return transport DebuggerTransport
+ *         A possible DevTools transport (if connection succeeded and streams
+ *         are actually alive and working)
+ * @return certError boolean
+ *         Flag noting if cert trouble caused the streams to fail
+ * @return s nsISocketTransport
+ *         Underlying socket transport, in case more details are needed.
+ */
+let _getTransport = Task.async(function*(settings) {
+  let { host, port, encryption } = settings;
+  let attempt = yield _attemptTransport(settings);
   if (attempt.transport) {
     return attempt.transport; // Success
   }
 
   // If the server cert failed validation, store a temporary override and make
   // a second attempt.
   if (encryption && attempt.certError) {
     _storeCertOverride(attempt.s, host, port);
   } else {
     throw new Error("Connection failed");
   }
 
-  attempt = yield _attemptTransport({ host, port, encryption });
+  attempt = yield _attemptTransport(settings);
   if (attempt.transport) {
     return attempt.transport; // Success
   }
 
   throw new Error("Connection failed even after cert override");
 });
 
 /**
- * Try to connect and create a DevTools transport.
+ * Make a single attempt to connect and create a DevTools transport.  This could
+ * fail if the remote host is unreachable, for example.  If there is security
+ * error due to the use of self-signed certs, you should make another attempt
+ * after storing a cert override.
  *
+ * @param host string
+ *        The host name or IP address of the debugger server.
+ * @param port number
+ *        The port number of the debugger server.
+ * @param encryption boolean (optional)
+ *        Whether the server requires encryption.  Defaults to false.
  * @return transport DebuggerTransport
  *         A possible DevTools transport (if connection succeeded and streams
  *         are actually alive and working)
  * @return certError boolean
  *         Flag noting if cert trouble caused the streams to fail
  * @return s nsISocketTransport
  *         Underlying socket transport, in case more details are needed.
  */
-let _attemptTransport = Task.async(function*({ host, port, encryption }){
+let _attemptTransport = Task.async(function*({ host, port, encryption }) {
   // _attemptConnect only opens the streams.  Any failures at that stage
   // aborts the connection process immedidately.
   let { s, input, output } = _attemptConnect({ host, port, encryption });
 
   // Check if the input stream is alive.  If encryption is enabled, we need to
   // watch out for cert errors by testing the input stream.
   let { alive, certError } = yield _isInputAlive(input);
   dumpv("Server cert accepted? " + !certError);