Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(973)

Unified Diff: remoting/webapp/crd/js/combined_host_list_api.js

Issue 1217643002: Added HostListApl implementation to connect to legacy directory and GCD. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@gcd-e2e
Patch Set: rewrote code for combining host lists Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/webapp/base/js/host.js ('k') | remoting/webapp/crd/js/combined_host_list_api_unittest.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/webapp/crd/js/combined_host_list_api.js
diff --git a/remoting/webapp/crd/js/combined_host_list_api.js b/remoting/webapp/crd/js/combined_host_list_api.js
new file mode 100644
index 0000000000000000000000000000000000000000..cbc1be84d7a940d3daa68c5d02950bb8aaff3e11
--- /dev/null
+++ b/remoting/webapp/crd/js/combined_host_list_api.js
@@ -0,0 +1,209 @@
+// Copyright 2015 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
+ * API implementation that combines two other implementations.
+ */
+
+/** @suppress {duplicate} */
+var remoting = remoting || {};
+
+(function() {
+
+'use strict';
+
+/**
+ * Amount of time to wait for GCD results after legacy registry has
+ * returned.
+ */
+var GCD_TIMEOUT_MS = 1000;
+
+/**
+ * @constructor
+ * @param {!remoting.HostListApi} legacyImpl
+ * @param {!remoting.HostListApi} gcdImpl
+ * @implements {remoting.HostListApi}
+ */
+remoting.CombinedHostListApi = function(legacyImpl, gcdImpl) {
+ /** @const {!remoting.HostListApi} */
+ this.legacyImpl_ = legacyImpl;
+
+ /** @const {!remoting.HostListApi} */
+ this.gcdImpl_ = gcdImpl;
+
+ /**
+ * List of host IDs most recently retrieved from |legacyImpl_|.
+ * @type {!Set<string>}
+ */
+ this.legacyIds_ = new Set();
+
+ /**
+ * List of host IDs most recently retrieved |gcdImpl_|.
+ * @type {!Set<string>}
+ */
+ this.gcdIds_ = new Set();
+};
+
+/** @override */
+remoting.CombinedHostListApi.prototype.register = function(
+ hostName, publicKey, hostClientId) {
+ var that = this;
+ // First, register the new host with GCD, which will create a
+ // service account and generate a host ID.
+ return this.gcdImpl_.register(hostName, publicKey, hostClientId).then(
+ function(gcdRegResult) {
+ // After the GCD registration has been created, copy the
+ // registration to the legacy directory so that clients not yet
+ // upgraded to use GCD can see the new host.
+ //
+ // This is an ugly hack for multiple reasons:
+ //
+ // 1. It completely ignores |this.legacyImpl_|, complicating
+ // unit tests.
+ //
+ // 2. It relies on the fact that, when |hostClientId| is null,
+ // the legacy directory will "register" a host without
+ // creating a service account. This is an obsolete feature
+ // of the legacy directory that is being revived for a new
+ // purpose.
+ //
+ // 3. It assumes the device ID generated by GCD is usable as a
+ // host ID by the legacy directory. Fortunately both systems
+ // use UUIDs.
+ return remoting.LegacyHostListApi.registerWithHostId(
+ gcdRegResult.hostId, hostName, publicKey, null).then(
+ function() {
+ // On success, return the result from GCD, ignoring
+ // the result returned by the legacy directory.
+ that.gcdIds_.add(gcdRegResult.hostId);
+ that.legacyIds_.add(gcdRegResult.hostId);
+ return gcdRegResult;
+ },
+ function(error) {
+ console.warn(
+ 'Error copying host GCD host registration ' +
+ 'to legacy directory: ' + error);
+ throw error;
+ }
+ );
+ });
+};
+
+/** @override */
+remoting.CombinedHostListApi.prototype.get = function() {
+ // Fetch the host list from both directories and merge hosts that
+ // have the same ID.
+ var that = this;
+ var legacyPromise = this.legacyImpl_.get();
+ var gcdPromise = this.gcdImpl_.get();
+ return legacyPromise.then(function(legacyHosts) {
+ // If GCD is too slow, just act as if it had returned an empty
+ // result set.
+ /** @type {!Promise<!Array<!remoting.Host>>} */
+ var timeoutPromise = base.Promise.withTimeout(
+ gcdPromise, GCD_TIMEOUT_MS, []);
+
+ // Combine host information from both directories. In the case of
+ // conflicting information, prefer information from whichever
+ // directory claims to have newer information.
+ return timeoutPromise.then(function(gcdHosts) {
+ // First, for each directory, build a mapping from host ID to
+ // host data, and collect a set of host IDs present in the
+ // directory.
+ /** @type {!Map<string,!remoting.Host>} */
+ var gcdHostMap = new Map();
kelvinp 2015/07/20 22:46:18 Would the following be simpler? var hostMap = new
John Williams 2015/07/21 04:54:55 That's not quite right, but I incorporated somethi
+ /** @type {!Map<string,!remoting.Host>} */
+ var legacyHostMap = new Map();
+ that.gcdIds_ = new Set();
+ that.legacyIds_ = new Set();
+ gcdHosts.forEach(function(host) {
+ that.gcdIds_.add(host.hostId);
+ gcdHostMap.set(host.hostId, host);
+ });
+ legacyHosts.forEach(function(host) {
+ that.legacyIds_.add(host.hostId);
+ legacyHostMap.set(host.hostId, host);
+ });
+
+ // Trim the host maps such that each host exists in only a
+ // single map. We iterate over |that.gcdIds_| instead of
+ // |gcdHosts| to avoid any potential issues with modifying a map
+ // while iterating over it.
+ that.gcdIds_.forEach(function(hostId) {
+ var gcdHost = gcdHostMap.get(hostId);
+ console.assert(gcdHost);
+ var legacyHost = legacyHostMap.get(hostId);
+ if (legacyHost) {
+ // The host is in both maps.
+ if (gcdHost.updatedTime >= legacyHost.updatedTime) {
+ legacyHostMap.delete(hostId);
+ } else {
+ gcdHostMap.delete(hostId);
+ }
+ }
+ });
+
+ // Build a combined list of hosts, preserving the original
+ // ordering as much as possible.
+ var hosts = [];
+ gcdHosts.forEach(function(host) {
+ if (gcdHostMap.has(host.hostId)) {
+ hosts.push(host);
+ }
+ });
+ legacyHosts.forEach(function(host) {
+ if (legacyHostMap.has(host.hostId)) {
+ hosts.push(host);
+ }
+ });
+
+ return hosts;
+ });
+ });
+};
+
+/** @override */
+remoting.CombinedHostListApi.prototype.put =
+ function(hostId, hostName, hostPublicKey) {
+ var legacyPromise = Promise.resolve();
+ if (this.legacyIds_.has(hostId)) {
+ legacyPromise = this.legacyImpl_.put(hostId, hostName, hostPublicKey);
+ }
+ var gcdPromise = Promise.resolve();
+ if (this.gcdIds_.has(hostId)) {
+ gcdPromise = this.gcdImpl_.put(hostId, hostName, hostPublicKey);
+ }
+ return legacyPromise.then(function() {
+ // If GCD is too slow, just ignore it and return result from the
+ // legacy directory.
+ return base.Promise.withTimeout(
+ gcdPromise, GCD_TIMEOUT_MS);
+ });
+};
+
+/** @override */
+remoting.CombinedHostListApi.prototype.remove = function(hostId) {
+ var legacyPromise = Promise.resolve();
+ if (this.legacyIds_.has(hostId)) {
+ legacyPromise = this.legacyImpl_.remove(hostId);
+ }
+ var gcdPromise = Promise.resolve();
+ if (this.gcdIds_.has(hostId)) {
+ gcdPromise = this.gcdImpl_.remove(hostId);
+ }
+ return legacyPromise.then(function() {
+ // If GCD is too slow, just ignore it and return result from the
+ // legacy directory.
+ return base.Promise.withTimeout(
+ gcdPromise, GCD_TIMEOUT_MS);
+ });
+};
+
+/** @override */
+remoting.CombinedHostListApi.prototype.getSupportHost = function(supportId) {
+ return this.legacyImpl_.getSupportHost(supportId);
+};
+
+})();
« no previous file with comments | « remoting/webapp/base/js/host.js ('k') | remoting/webapp/crd/js/combined_host_list_api_unittest.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698