summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorjoedow <joedow@chromium.org>2016-02-20 09:44:06 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-20 17:45:40 +0000
commitdadef9885e92560dfc56d7e4e227b2a5c421c02f (patch)
treec5094be421d4b1fb5dd2d5bcc6f4a3a6126c4d32 /remoting
parent46f64281f07fa102c1e0284c45826a4471b69572 (diff)
downloadchromium_src-dadef9885e92560dfc56d7e4e227b2a5c421c02f.zip
chromium_src-dadef9885e92560dfc56d7e4e227b2a5c421c02f.tar.gz
chromium_src-dadef9885e92560dfc56d7e4e227b2a5c421c02f.tar.bz2
Updating webapp to send securityKey capability.
This change updates the CRD webapp to send the securityKey capability to the host if the appropriate gnubby extension exists (which we would use to resolve gnubby requests). The only interesting bit in this change is that there is no synchronous API to check for extension existence in Chrome (that I could find) so we need to use a promise to wait for either a disconnect message or a response to a Hello message to determine if the extension exists. BUG=585835 Review URL: https://codereview.chromium.org/1707163002 Cr-Commit-Position: refs/heads/master@{#376654}
Diffstat (limited to 'remoting')
-rw-r--r--remoting/host/security_key/gnubby_extension.cc2
-rw-r--r--remoting/remoting_webapp_files.gypi1
-rw-r--r--remoting/webapp/base/js/client_session.js3
-rw-r--r--remoting/webapp/crd/js/cast_extension_handler.js2
-rw-r--r--remoting/webapp/crd/js/desktop_remoting_activity.js7
-rw-r--r--remoting/webapp/crd/js/gnubby_auth_handler.js99
-rw-r--r--remoting/webapp/crd/js/gnubby_auth_handler_unittest.js193
-rw-r--r--remoting/webapp/crd/js/me2me_activity.js25
-rw-r--r--remoting/webapp/crd/js/remoting_activity_test_driver.js5
-rw-r--r--remoting/webapp/crd/js/video_frame_recorder.js2
-rw-r--r--remoting/webapp/files.gni1
11 files changed, 303 insertions, 37 deletions
diff --git a/remoting/host/security_key/gnubby_extension.cc b/remoting/host/security_key/gnubby_extension.cc
index d225f31..156ffac 100644
--- a/remoting/host/security_key/gnubby_extension.cc
+++ b/remoting/host/security_key/gnubby_extension.cc
@@ -8,7 +8,7 @@
namespace {
// TODO(joedow): Update this once clients support sending a gnubby capabililty.
-// Tracked via: crbug.com/585835
+// Tracked via: crbug.com/587485
const char kCapability[] = "";
}
diff --git a/remoting/remoting_webapp_files.gypi b/remoting/remoting_webapp_files.gypi
index cab6a2a..4a98cbb 100644
--- a/remoting/remoting_webapp_files.gypi
+++ b/remoting/remoting_webapp_files.gypi
@@ -113,6 +113,7 @@
'webapp/crd/js/combined_host_list_api_unittest.js',
'webapp/crd/js/gcd_client_unittest.js',
'webapp/crd/js/gcd_client_with_mock_xhr_unittest.js',
+ "webapp/crd/js/gnubby_auth_handler_unittest.js",
'webapp/crd/js/host_controller_unittest.js',
'webapp/crd/js/host_daemon_facade_unittest.js',
'webapp/crd/js/host_table_entry_unittest.js',
diff --git a/remoting/webapp/base/js/client_session.js b/remoting/webapp/base/js/client_session.js
index 8fbbdce..882a763 100644
--- a/remoting/webapp/base/js/client_session.js
+++ b/remoting/webapp/base/js/client_session.js
@@ -261,6 +261,9 @@ remoting.ClientSession.Capability = {
// Indicates desktop shape support.
DESKTOP_SHAPE: 'desktopShape',
+
+ // Indicates whether the client supports security key request forwarding.
+ SECURITY_KEY: 'securityKey',
};
/**
diff --git a/remoting/webapp/crd/js/cast_extension_handler.js b/remoting/webapp/crd/js/cast_extension_handler.js
index 72cac12..cf01bed 100644
--- a/remoting/webapp/crd/js/cast_extension_handler.js
+++ b/remoting/webapp/crd/js/cast_extension_handler.js
@@ -44,7 +44,7 @@ remoting.CastExtensionHandler = function() {
/** @private {string} */
remoting.CastExtensionHandler.EXTENSION_TYPE = 'cast_message';
-/** @return {Array<string>} */
+/** @override @return {Array<string>} */
remoting.CastExtensionHandler.prototype.getExtensionTypes = function() {
return [remoting.CastExtensionHandler.EXTENSION_TYPE];
};
diff --git a/remoting/webapp/crd/js/desktop_remoting_activity.js b/remoting/webapp/crd/js/desktop_remoting_activity.js
index cf516a8..a5a39c8 100644
--- a/remoting/webapp/crd/js/desktop_remoting_activity.js
+++ b/remoting/webapp/crd/js/desktop_remoting_activity.js
@@ -16,20 +16,23 @@ var remoting = remoting || {};
*
* @param {remoting.Activity} parentActivity
* @param {remoting.SessionLogger} logger
+ * @param {Array<string>=} opt_additionalCapabilities
* @implements {remoting.ClientSession.EventHandler}
* @implements {base.Disposable}
* @constructor
*/
-remoting.DesktopRemotingActivity = function(parentActivity, logger) {
+remoting.DesktopRemotingActivity = function(
+ parentActivity, logger, opt_additionalCapabilities) {
/** @private */
this.parentActivity_ = parentActivity;
/** @private {remoting.DesktopConnectedView} */
this.connectedView_ = null;
+ opt_additionalCapabilities = opt_additionalCapabilities || [];
/** @private */
this.sessionFactory_ = new remoting.ClientSessionFactory(
document.querySelector('#client-container .client-plugin-container'),
- [/* No special capabilities required. */]);
+ opt_additionalCapabilities);
/** @private {remoting.ClientSession} */
this.session_ = null;
diff --git a/remoting/webapp/crd/js/gnubby_auth_handler.js b/remoting/webapp/crd/js/gnubby_auth_handler.js
index 724bbdc..a8cb834 100644
--- a/remoting/webapp/crd/js/gnubby_auth_handler.js
+++ b/remoting/webapp/crd/js/gnubby_auth_handler.js
@@ -20,12 +20,71 @@ var remoting = remoting || {};
remoting.GnubbyAuthHandler = function() {
/** @private {?function(string,string)} */
this.sendMessageToHostCallback_ = null;
+
+ /** @private {string} */
+ this.gnubbyExtensionId_ = '';
+
+ /** @private {Promise} */
+ this.gnubbyExtensionPromise_ = null;
};
-/** @private {string} */
+/** @private @const {string} */
remoting.GnubbyAuthHandler.EXTENSION_TYPE = 'gnubby-auth';
-/** @return {Array<string>} */
+/** @private @const {string} */
+remoting.GnubbyAuthHandler.GNUBBY_DEV_EXTENSION_ID =
+ 'dlfcjilkjfhdnfiecknlnddkmmiofjbg';
+
+/** @private @const {string} */
+remoting.GnubbyAuthHandler.GNUBBY_STABLE_EXTENSION_ID =
+ 'beknehfpfkghjoafdifaflglpjkojoco';
+
+/**
+ * Determines whether any supported Gnubby extensions are installed.
+ *
+ * @return {Promise<boolean>} Promise that resolves after we have either found
+ * an extension or checked for the known extensions IDs without success.
+ * Returns true if an applicable gnubby extension was found.
+ */
+remoting.GnubbyAuthHandler.prototype.isGnubbyExtensionInstalled = function() {
+ if (this.gnubbyExtensionPromise_) {
+ return this.gnubbyExtensionPromise_;
+ }
+
+ var findGnubbyExtension = function(extensionId, resolve, reject) {
+ var message_callback = function(response) {
+ if (response) {
+ this.gnubbyExtensionId_ = extensionId;
+ resolve(true);
+ } else {
+ reject();
+ }
+ }.bind(this)
+
+ chrome.runtime.sendMessage(extensionId, "HELLO", message_callback);
+ }
+
+ var findDevGnubbyExtension = findGnubbyExtension.bind(this,
+ remoting.GnubbyAuthHandler.GNUBBY_DEV_EXTENSION_ID)
+
+ var findStableGnubbyExtension = findGnubbyExtension.bind(this,
+ remoting.GnubbyAuthHandler.GNUBBY_STABLE_EXTENSION_ID)
+
+ this.gnubbyExtensionPromise_ = new Promise(
+ findStableGnubbyExtension
+ ).catch(function () {
+ return new Promise(findDevGnubbyExtension);
+ }
+ ).catch(function () {
+ // If no extensions are found, return false.
+ return Promise.resolve(false);
+ }
+ );
+
+ return this.gnubbyExtensionPromise_;
+};
+
+/** @override @return {Array<string>} */
remoting.GnubbyAuthHandler.prototype.getExtensionTypes = function() {
return [remoting.GnubbyAuthHandler.EXTENSION_TYPE];
};
@@ -100,37 +159,19 @@ remoting.GnubbyAuthHandler.prototype.callback_ =
};
/**
- * Send data to the gnubbyd extension.
+ * Send data to the installed gnubbyd extension.
* @param {Object} jsonObject The JSON object to send to the gnubbyd extension.
* @param {function(Object)} callback The callback to invoke with reply data.
* @private
*/
remoting.GnubbyAuthHandler.prototype.sendMessageToGnubbyd_ =
function(jsonObject, callback) {
- var kGnubbydDevExtensionId = 'dlfcjilkjfhdnfiecknlnddkmmiofjbg';
-
- chrome.runtime.sendMessage(
- kGnubbydDevExtensionId,
- jsonObject,
- onGnubbydDevReply_.bind(this, jsonObject, callback));
+ this.isGnubbyExtensionInstalled().then(
+ function (extensionInstalled) {
+ if (extensionInstalled) {
+ chrome.runtime.sendMessage(
+ this.gnubbyExtensionId_, jsonObject, callback);
+ }
+ }.bind(this)
+ );
};
-
-/**
- * Callback invoked as a result of sending a message to the gnubbyd-dev
- * extension. If that extension is not installed, reply will be undefined;
- * otherwise it will be the JSON response object.
- * @param {Object} jsonObject The JSON object to send to the gnubbyd extension.
- * @param {function(Object)} callback The callback to invoke with reply data.
- * @param {Object} reply The reply from the extension (or Chrome, if the
- * extension does not exist.
- * @private
- */
-function onGnubbydDevReply_(jsonObject, callback, reply) {
- var kGnubbydStableExtensionId = 'beknehfpfkghjoafdifaflglpjkojoco';
-
- if (reply) {
- callback(reply);
- } else {
- chrome.runtime.sendMessage(kGnubbydStableExtensionId, jsonObject, callback);
- }
-}
diff --git a/remoting/webapp/crd/js/gnubby_auth_handler_unittest.js b/remoting/webapp/crd/js/gnubby_auth_handler_unittest.js
new file mode 100644
index 0000000..7b63da0
--- /dev/null
+++ b/remoting/webapp/crd/js/gnubby_auth_handler_unittest.js
@@ -0,0 +1,193 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview
+ */
+
+(function() {
+
+'use strict';
+
+/** @const {string} */
+var EXTENSION_TYPE = 'gnubby-auth';
+
+/** @const {string} */
+var GNUBBY_DEV_EXTENSION_ID = 'dlfcjilkjfhdnfiecknlnddkmmiofjbg';
+
+/** @const {string} */
+var GNUBBY_STABLE_EXTENSION_ID = 'beknehfpfkghjoafdifaflglpjkojoco';
+
+/** @type {sinon.TestStub} */
+var sendMessageStub = null;
+
+/** @type {remoting.GnubbyAuthHandler} */
+var gnubbyAuthHandler = null;
+
+var sendMessageHandler = null;
+
+/** @const */
+var messageData = {
+ 'type': 'data',
+ 'data': ['Blergh!', 'Blargh!', 'Bleh!'],
+ 'connectionId': 42,
+};
+
+/** @const {string} */
+var messageJSON = JSON.stringify(messageData);
+
+QUnit.module('GnubbyAuthHandler', {
+ beforeEach: function(/** QUnit.Assert */ assert) {
+ // Configurable handler used for test customization.
+ sendMessageStub = sinon.stub(chromeMocks.runtime, 'sendMessage',
+ function(extensionId, message, responseCallback) {
+ sendMessageHandler(extensionId, message, responseCallback);
+ }
+ );
+ },
+ afterEach: function(/** QUnit.Assert */ assert) {
+ gnubbyAuthHandler = null;
+ sendMessageStub.restore();
+ }
+});
+
+QUnit.test(
+ 'isGnubbyExtensionInstalled() with no gnubby extensions installed',
+ function(assert) {
+ assert.expect(1);
+ var done = assert.async();
+
+ gnubbyAuthHandler = new remoting.GnubbyAuthHandler();
+ sendMessageHandler = function(extensionId, message, responseCallback) {
+ Promise.resolve().then(function() { responseCallback(null); });
+ }
+
+ gnubbyAuthHandler.isGnubbyExtensionInstalled().then(
+ function(isInstalled) {
+ assert.ok(!isInstalled);
+ done();
+ }
+ );
+});
+
+QUnit.test(
+ 'isGnubbyExtensionInstalled() with Dev gnubby extensions installed',
+ function(assert) {
+ assert.expect(1);
+ var done = assert.async();
+
+ sendMessageHandler = function(extensionId, message, responseCallback) {
+ var response = null;
+ if (extensionId === GNUBBY_DEV_EXTENSION_ID) {
+ response = { data: "W00t!" };
+ }
+ Promise.resolve().then(function() { responseCallback(response); });
+ };
+
+ gnubbyAuthHandler = new remoting.GnubbyAuthHandler();
+ gnubbyAuthHandler.isGnubbyExtensionInstalled().then(
+ function(isInstalled) {
+ assert.ok(isInstalled);
+ done();
+ }
+ );
+});
+
+QUnit.test(
+ 'isGnubbyExtensionInstalled() with Stable gnubby extensions installed',
+ function(assert) {
+ assert.expect(1);
+ var done = assert.async();
+
+ sendMessageHandler = function(extensionId, message, responseCallback) {
+ var response = null;
+ if (extensionId === GNUBBY_STABLE_EXTENSION_ID) {
+ response = { data: "W00t!" };
+ }
+ Promise.resolve().then(function() { responseCallback(response); });
+ };
+
+ gnubbyAuthHandler = new remoting.GnubbyAuthHandler();
+ gnubbyAuthHandler.isGnubbyExtensionInstalled().then(
+ function(isInstalled) {
+ assert.ok(isInstalled);
+ done();
+ }
+ );
+});
+
+QUnit.test('startExtension() sends message to host.',
+ function(assert) {
+ assert.expect(3);
+ var done = assert.async();
+
+ var sendMessageToHostCallback = function(extensionType, message) {
+ assert.equal(extensionType, EXTENSION_TYPE);
+ var messageObject = JSON.parse(message);
+ assert.equal('control', messageObject['type']);
+ assert.equal('auth-v1', messageObject['option']);
+ done();
+ }
+ gnubbyAuthHandler = new remoting.GnubbyAuthHandler();
+ gnubbyAuthHandler.startExtension(sendMessageToHostCallback);
+});
+
+QUnit.test(
+ 'onExtensionMessage() sends message to stable gnubby extension.',
+ function(assert) {
+ assert.expect(6);
+ var done1 = assert.async();
+ var done2 = assert.async();
+
+ var isGnubbyExtensionInstalledHandler =
+ function(extensionId, message, responseCallback) {
+ if (extensionId === GNUBBY_STABLE_EXTENSION_ID) {
+ Promise.resolve().then(function() {
+ responseCallback({ data: "W00t!" });
+ });
+ }
+ };
+
+ var onExtensionMessageHandler =
+ function(extensionId, message, responseCallback) {
+ assert.equal(extensionId, GNUBBY_STABLE_EXTENSION_ID,
+ 'Expected the stable gnubby extension ID.');
+ Promise.resolve().then(function() { responseCallback(message); });
+ };
+
+ var sendMessageToHostCallback = function(extensionType, message) {
+ assert.equal(extensionType, EXTENSION_TYPE);
+ var messageObject = JSON.parse(message);
+ var messageType = messageObject['type'];
+ if (messageType === 'control') {
+ // This is the first control message sent to the host.
+ done1();
+ } else if (messageType === 'data') {
+ // Response from gnubby extension.
+ assert.equal(messageData.connectionId, messageObject['connectionId']);
+ assert.deepEqual(messageData.data, messageObject['data']);
+ done2();
+ } else {
+ assert.ok(false);
+ }
+ };
+
+ gnubbyAuthHandler = new remoting.GnubbyAuthHandler();
+ gnubbyAuthHandler.startExtension(sendMessageToHostCallback);
+
+ sendMessageHandler = isGnubbyExtensionInstalledHandler;
+ return gnubbyAuthHandler.isGnubbyExtensionInstalled().then(
+ function(isInstalled) {
+ assert.ok(isInstalled);
+ // The promise has completed for isGnubbyExtensionInstalled() so now we
+ // can switch the handler out to work with the onExtensionMessage call.
+ sendMessageHandler = onExtensionMessageHandler;
+ return Promise.resolve().then(function() {
+ gnubbyAuthHandler.onExtensionMessage(EXTENSION_TYPE, messageData);
+ });
+ }
+ );
+});
+
+})();
diff --git a/remoting/webapp/crd/js/me2me_activity.js b/remoting/webapp/crd/js/me2me_activity.js
index aa43d8a..66530a0 100644
--- a/remoting/webapp/crd/js/me2me_activity.js
+++ b/remoting/webapp/crd/js/me2me_activity.js
@@ -39,6 +39,12 @@ remoting.Me2MeActivity = function(host, hostList) {
/** @private {remoting.DesktopRemotingActivity} */
this.desktopActivity_ = null;
+
+ /** @private {remoting.GnubbyAuthHandler} */
+ this.gnubbyAuthHandler_ = new remoting.GnubbyAuthHandler();
+
+ /** @private {Array<string>} */
+ this.additionalCapabilities_ = [];
};
remoting.Me2MeActivity.prototype.dispose = function() {
@@ -74,6 +80,16 @@ remoting.Me2MeActivity.prototype.start = function() {
// User cancels out of the Host upgrade dialog. Report it as bad version.
throw new remoting.Error(remoting.Error.Tag.BAD_VERSION);
})).then(
+ this.gnubbyAuthHandler_.isGnubbyExtensionInstalled.bind(
+ this.gnubbyAuthHandler_)
+ ).then(
+ function (extensionInstalled) {
+ if (extensionInstalled) {
+ this.additionalCapabilities_.push(
+ remoting.ClientSession.Capability.SECURITY_KEY);
+ }
+ }.bind(this)
+ ).then(
this.connect_.bind(this)
).catch(remoting.Error.handler(handleError));
};
@@ -124,8 +140,9 @@ remoting.Me2MeActivity.prototype.reconnect_ = function(entryPoint) {
*/
remoting.Me2MeActivity.prototype.connect_ = function() {
base.dispose(this.desktopActivity_);
- this.desktopActivity_ =
- new remoting.DesktopRemotingActivity(this, this.logger_);
+
+ this.desktopActivity_ = new remoting.DesktopRemotingActivity(
+ this, this.logger_, this.additionalCapabilities_);
this.desktopActivity_.getConnectingDialog().show();
this.desktopActivity_.start(this.host_, this.createCredentialsProvider_());
};
@@ -240,7 +257,9 @@ remoting.Me2MeActivity.prototype.onConnected = function(connectionInfo) {
if (plugin.hasCapability(remoting.ClientSession.Capability.CAST)) {
plugin.extensions().register(new remoting.CastExtensionHandler());
}
- plugin.extensions().register(new remoting.GnubbyAuthHandler());
+ // TODO(joedow): Do not register the GnubbyAuthHandler extension if the host
+ // does not support security key forwarding.
+ plugin.extensions().register(this.gnubbyAuthHandler_);
this.pinDialog_.requestPairingIfNecessary(connectionInfo.plugin());
// Drop the session after 30s of suspension. If this timeout is too short, we
diff --git a/remoting/webapp/crd/js/remoting_activity_test_driver.js b/remoting/webapp/crd/js/remoting_activity_test_driver.js
index 92b22aa..3771371 100644
--- a/remoting/webapp/crd/js/remoting_activity_test_driver.js
+++ b/remoting/webapp/crd/js/remoting_activity_test_driver.js
@@ -97,6 +97,10 @@ remoting.BaseTestDriver = function(mockHTML) {
sinon.stub(remoting.NetworkConnectivityDetector, 'create', function(){
return new MockNetworkConnectivityDetector();
});
+ /** @private */
+ this.isGnubbyExtensionInstalledStub_ = sinon.stub(
+ remoting.GnubbyAuthHandler.prototype, 'isGnubbyExtensionInstalled',
+ function() { return Promise.resolve(false); });
/**
* Use fake timers to prevent the generation of session ID expiration events.
@@ -125,6 +129,7 @@ remoting.BaseTestDriver.prototype.dispose = function() {
this.eventWriterMock_.restore();
this.desktopConnectedViewCreateStub_.restore();
this.createNetworkConnectivityDetectorStub_.restore();
+ this.isGnubbyExtensionInstalledStub_.restore();
if (Boolean(this.mockConnection_)) {
this.mockConnection_.restore();
this.mockConnection_ = null;
diff --git a/remoting/webapp/crd/js/video_frame_recorder.js b/remoting/webapp/crd/js/video_frame_recorder.js
index 1b53b5c..6064c4a 100644
--- a/remoting/webapp/crd/js/video_frame_recorder.js
+++ b/remoting/webapp/crd/js/video_frame_recorder.js
@@ -27,7 +27,7 @@ remoting.VideoFrameRecorder = function() {
/** @private {string} */
remoting.VideoFrameRecorder.EXTENSION_TYPE = 'video-recorder';
-/** @return {Array<string>} */
+/** @override @return {Array<string>} */
remoting.VideoFrameRecorder.prototype.getExtensionTypes = function() {
return [remoting.VideoFrameRecorder.EXTENSION_TYPE];
};
diff --git a/remoting/webapp/files.gni b/remoting/webapp/files.gni
index 7f43734..df837ae 100644
--- a/remoting/webapp/files.gni
+++ b/remoting/webapp/files.gni
@@ -110,6 +110,7 @@ remoting_webapp_unittests_js_files = [
"crd/js/combined_host_list_api_unittest.js",
"crd/js/gcd_client_unittest.js",
"crd/js/gcd_client_with_mock_xhr_unittest.js",
+ "crd/js/gnubby_auth_handler_unittest.js",
"crd/js/host_controller_unittest.js",
"crd/js/host_daemon_facade_unittest.js",
"crd/js/host_table_entry_unittest.js",