You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ag...@apache.org on 2014/12/31 06:56:54 UTC

[04/13] cordova-app-harness git commit: Enhancements to new adbkit integration.

Enhancements to new adbkit integration.

- Fix jshint errors
- Fix process never exiting after pushing
- Expose a symbol for detecting connected devices
- Destroy socket if it's not picked up by the connection
- Disable multiple connections per-host since we were just returning the same socket for each call to createSocket


Project: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/commit/60211b80
Tree: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/tree/60211b80
Diff: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/diff/60211b80

Branch: refs/heads/master
Commit: 60211b80bc0978d1d9483964e8bb1557447dac38
Parents: a2260d1
Author: Andrew Grieve <ag...@chromium.org>
Authored: Wed Nov 5 14:54:08 2014 -0500
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Wed Dec 31 00:41:44 2014 -0500

----------------------------------------------------------------------
 .../cordova-harness-client/harnessclient.js     | 144 +++++++++++--------
 1 file changed, 86 insertions(+), 58 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/60211b80/harness-push/node_modules/cordova-harness-client/harnessclient.js
----------------------------------------------------------------------
diff --git a/harness-push/node_modules/cordova-harness-client/harnessclient.js b/harness-push/node_modules/cordova-harness-client/harnessclient.js
index cf59ebe..0919087 100644
--- a/harness-push/node_modules/cordova-harness-client/harnessclient.js
+++ b/harness-push/node_modules/cordova-harness-client/harnessclient.js
@@ -20,58 +20,85 @@
 var http = require('http');
 var url = require('url');
 var fs = require('fs');
-var adb = require('adbkit');
+var adbkit = require('adbkit');
 var Q = require('q');
 var AgentKeepAlive = require('agentkeepalive');
 var PushSession = require('./pushsession');
 
 var httpAgent = new AgentKeepAlive({
-    maxSockets: 5,
-    maxFreeSockets: 5,
+    maxSockets: 1, // Must be set to 1 unless we refactor to allow multiple sockets through adbkit.
+    maxFreeSockets: 1,
     keepAliveMsecs: 3000000
 });
 
-function doRequest(method, target, action, options) {
-    var deferred = Q.defer();
+// Client creation is cheap. No IO done until first command.
+var adbClient = adbkit.createClient();
 
-    var client = adb.createClient();
-    client.listDevices()
+function HarnessClient(target) {
+    this.target = target;
+}
+
+HarnessClient.detectAdbTargets = function() {
+    return adbClient.listDevices()
+    .then(function(devices) {
+        devices.sort(function(a,b) {
+            return a.type < b.type ? -1 :
+                   a.type > b.type ? 1 :
+                   0;
+        });
+        return devices.map(function(d) { return 'adb:' + d.id });
+    }, function() {
+        return Q.reject('Could not run adb command.');
+    });
+};
+
+HarnessClient.prototype.autoDetectTarget = function() {
+    return HarnessClient.detectAdbTargets()
     .then(function(devices) {
         if (devices.length === 0) {
-            deferred.reject('No devices detected.');
-            return;
+            return '127.0.0.1:2424';
         }
+        return devices[0];
+    }, function() {
+        return Q.reject('Could not run adb command.');
+    });
+};
 
-        // We use the first device.
-        var device = devices[0];
-
-        // Open a TCP connection to port 2424.
-        client.openTcp(device.id, 2424)
-        .then(function(socket) {
-            // Override the function that creates a socket, instead using the existing socket.
-            // This function is identical to the one found in agentkeepalive, except that it doesn't create a new socket.
-            AgentKeepAlive.prototype.createSocket = function(req, options) {
-                var self = this;
-                socket._requestCount = 0;
-                if (self.keepAliveMsecs) {
-                    socket._maxKeepAliveTimeout = function () {
-                        debug('maxKeepAliveTimeout, socket destroy()');
-                        socket.destroy();
-                        self.timeoutSocketCount++;
-                    };
-                    socket.setTimeout(self.keepAliveMsecs, socket._maxKeepAliveTimeout);
-                    // Disable Nagle's algorithm: http://blog.caustik.com/2012/04/08/scaling-node-js-to-100k-concurrent-connections/
-                    socket.setNoDelay(true);
-                }
-                this.createSocketCount++;
-                return socket;
-            };
-        }, function(error) {
-            deferred.reject('\nCould not connect to the device. Make sure you have the Chrome App Developer Tool for Mobile open.');
-        }).then(function() {
-            var targetParts = target.split(':');
-            var host = targetParts[0];
-            var port = +(targetParts[1] || 2424);
+HarnessClient.prototype.doRequest = function(method, action, options) {
+    var self = this;
+    return Q.when().then(function() {
+        return self.target || self.autoDetectTarget();
+    }).catch(function() {
+        return '127.0.0.1:2424';
+    }).then(function(target) {
+        self.target = target;
+        var targetParts = target.split(':');
+        var host = targetParts[0];
+        var port = +(targetParts[1] || 2424);
+        var deviceId = null;
+        if (host == 'adb') {
+            deviceId = targetParts[1];
+            port = +(targetParts[2] || 2424);
+            host = 'adb_' + deviceId;
+        }
+        // If using adb, try to open a socket.
+        return Q.when().then(function() {
+            return deviceId && adbClient.openTcp(deviceId, port);
+        }).catch(function() {
+            return Q.reject('Could not connect to device. Make sure you have the Chrome App Developer Tool for Mobile open.');
+        }).then(function(adbSocket) {
+            var deferred = Q.defer();
+
+            if (adbSocket) {
+                // Override the function that creates a socket, instead using the existing socket.
+                // This function is identical to the one found in agentkeepalive, except that it doesn't create a new socket.
+                httpAgent.createConnection = function() {
+                    return adbSocket;
+                };
+            } else {
+                // Revert to prototype implementation.
+                delete httpAgent.createSocket;
+            }
             options = options || {};
 
             var queryParams = {};
@@ -138,9 +165,15 @@ function doRequest(method, target, action, options) {
             req.on('error', function(e) {
                 deferred.reject(e);
             });
-            // Disable timeouts for packapk until we can optimize it :(.
             req.on('socket', function(socket) {
+                // Disable timeouts for packapk until we can optimize it :(.
                 socket.setTimeout(0);
+                // Check if for some reason our adb socket was not used.
+                if (adbSocket && adbSocket != socket) {
+                  console.log('destroying');
+                    delete httpAgent.createSocket;
+                    adbSocket.destroy();
+                }
             });
 
             if (body) {
@@ -187,46 +220,41 @@ function doRequest(method, target, action, options) {
                     deferred.resolve({res:res, body:body});
                 });
             });
+            return deferred.promise;
         });
     });
-
-    return deferred.promise;
-}
-
-function HarnessClient(target) {
-    this.target = target || '127.0.0.1';
-}
+};
 
 HarnessClient.prototype.info = function() {
-    return doRequest('GET', this.target, '/info', { expectJson: true });
+    return this.doRequest('GET', '/info', { expectJson: true });
 };
 
 HarnessClient.prototype.assetmanifest = function(/* optional */ appId) {
-    return doRequest('GET', this.target, '/assetmanifest', {expectJson: true, appId: appId});
+    return this.doRequest('GET', '/assetmanifest', {expectJson: true, appId: appId});
 };
 
 HarnessClient.prototype.menu = function() {
-    return doRequest('POST', this.target, '/menu');
+    return this.doRequest('POST', '/menu');
 };
 
 HarnessClient.prototype.quit = function() {
-    return doRequest('POST', this.target, '/quit');
+    return this.doRequest('POST', '/quit');
 };
 
 HarnessClient.prototype.evalJs = function(someJs) {
-    return doRequest('POST', this.target, '/exec', { query: {code: someJs} });
+    return this.doRequest('POST', '/exec', { query: {code: someJs} });
 };
 
 HarnessClient.prototype.launch = function(/* optional */ appId) {
-    return doRequest('POST', this.target, '/launch', { appId: appId});
+    return this.doRequest('POST', '/launch', { appId: appId});
 };
 
 HarnessClient.prototype.deleteAllApps = function() {
-    return doRequest('POST', this.target, '/deleteapp', { query: {'all': 1} });
+    return this.doRequest('POST', '/deleteapp', { query: {'all': 1} });
 };
 
 HarnessClient.prototype.deleteApp = function(/* optional */ appId) {
-    return doRequest('POST', this.target, '/deleteapp', { appId: appId});
+    return this.doRequest('POST', '/deleteapp', { appId: appId});
 };
 
 HarnessClient.prototype.pushZip = function(appId, appType, zipData, /* optional */ totalPushBytes, /* optional */ manifestEtag) {
@@ -237,7 +265,7 @@ HarnessClient.prototype.pushZip = function(appId, appType, zipData, /* optional
     if (manifestEtag) {
         query['manifestEtag'] = manifestEtag;
     }
-    return doRequest('POST', this.target, '/zippush', {
+    return this.doRequest('POST', '/zippush', {
         appId: appId,
         appType: appType,
         body: zipData,
@@ -256,7 +284,7 @@ HarnessClient.prototype.pushFile = function(appId, appType, payload, etag, remot
     if (manifestEtag) {
         query['manifestEtag'] = manifestEtag;
     }
-    return doRequest('PUT', this.target, '/putfile', {
+    return this.doRequest('PUT', '/putfile', {
         appId: appId,
         appType: appType,
         body: payload,
@@ -269,7 +297,7 @@ HarnessClient.prototype.deleteFiles = function(appId, deleteList, /* optional */
     if (manifestEtag) {
         query['manifestEtag'] = manifestEtag;
     }
-    return doRequest('POST', this.target, 'deletefiles', { appId: appId, json: {'paths': deleteList}, query: query});
+    return this.doRequest('POST', 'deletefiles', { appId: appId, json: {'paths': deleteList}, query: query});
 };
 
 HarnessClient.prototype.createPushSession = function(dir) {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org