1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 * API implementation that combines two other implementations.
10 /** @suppress {duplicate} */
11 var remoting
= remoting
|| {};
18 * Amount of time to wait for GCD results after legacy registry has
21 var GCD_TIMEOUT_MS
= 1000;
25 * @param {!remoting.HostListApi} legacyImpl
26 * @param {!remoting.HostListApi} gcdImpl
27 * @implements {remoting.HostListApi}
29 remoting
.CombinedHostListApi = function(legacyImpl
, gcdImpl
) {
30 /** @const {!remoting.HostListApi} */
31 this.legacyImpl_
= legacyImpl
;
33 /** @const {!remoting.HostListApi} */
34 this.gcdImpl_
= gcdImpl
;
37 * List of host IDs most recently retrieved from |legacyImpl_|.
38 * @type {!Set<string>}
40 this.legacyIds_
= new Set();
43 * List of host IDs most recently retrieved |gcdImpl_|.
44 * @type {!Set<string>}
46 this.gcdIds_
= new Set();
50 remoting
.CombinedHostListApi
.prototype.register = function(
51 hostName
, publicKey
, hostClientId
) {
53 // First, register the new host with GCD, which will create a
54 // service account and generate a host ID.
55 return this.gcdImpl_
.register(hostName
, publicKey
, hostClientId
).then(
56 function(gcdRegResult
) {
57 // After the GCD registration has been created, copy the
58 // registration to the legacy directory so that clients not yet
59 // upgraded to use GCD can see the new host.
61 // This is an ugly hack for multiple reasons:
63 // 1. It completely ignores |this.legacyImpl_|, complicating
66 // 2. It relies on the fact that, when |hostClientId| is null,
67 // the legacy directory will "register" a host without
68 // creating a service account. This is an obsolete feature
69 // of the legacy directory that is being revived for a new
72 // 3. It assumes the device ID generated by GCD is usable as a
73 // host ID by the legacy directory. Fortunately both systems
75 return remoting
.LegacyHostListApi
.registerWithHostId(
76 gcdRegResult
.hostId
, hostName
, publicKey
, null).then(
78 // On success, return the result from GCD, ignoring
79 // the result returned by the legacy directory.
80 that
.gcdIds_
.add(gcdRegResult
.hostId
);
81 that
.legacyIds_
.add(gcdRegResult
.hostId
);
86 'Error copying host GCD host registration ' +
87 'to legacy directory: ' + error
);
95 remoting
.CombinedHostListApi
.prototype.get = function() {
96 // Fetch the host list from both directories and merge hosts that
99 var legacyPromise
= this.legacyImpl_
.get();
100 var gcdPromise
= this.gcdImpl_
.get();
101 return legacyPromise
.then(function(legacyHosts
) {
102 // If GCD is too slow, just act as if it had returned an empty
104 var timeoutPromise
= base
.Promise
.withTimeout(
105 gcdPromise
, GCD_TIMEOUT_MS
, []);
107 // Combine host information from both directories. In the case of
108 // conflicting information, prefer information from whichever
109 // directory claims to have newer information.
110 return timeoutPromise
.then(function(gcdHosts
) {
111 // Update |that.gcdIds_| and |that.legacyIds_|.
112 that
.gcdIds_
= new Set();
113 that
.legacyIds_
= new Set();
114 gcdHosts
.forEach(function(host
) {
115 that
.gcdIds_
.add(host
.hostId
);
117 legacyHosts
.forEach(function(host
) {
118 that
.legacyIds_
.add(host
.hostId
);
122 * A mapping from host IDs to the host data that will be
123 * returned from this method.
124 * @type {!Map<string,!remoting.Host>}
126 var hostMap
= new Map();
128 // Add legacy hosts to the output; some of these may be replaced
130 legacyHosts
.forEach(function(host
) {
131 hostMap
.set(host
.hostId
, host
);
134 // Add GCD hosts to the output, possibly replacing some legacy
135 // host data with newer data from GCD.
136 gcdHosts
.forEach(function(gcdHost
) {
137 var hostId
= gcdHost
.hostId
;
138 var legacyHost
= hostMap
.get(hostId
);
139 if (!legacyHost
|| legacyHost
.updatedTime
<= gcdHost
.updatedTime
) {
140 hostMap
.set(hostId
, gcdHost
);
144 // Convert the result to an Array.
145 // TODO(jrw): Use Array.from once it becomes available.
147 hostMap
.forEach(function(host
) {
156 remoting
.CombinedHostListApi
.prototype.put
=
157 function(hostId
, hostName
, hostPublicKey
) {
158 var legacyPromise
= Promise
.resolve();
159 if (this.legacyIds_
.has(hostId
)) {
160 legacyPromise
= this.legacyImpl_
.put(hostId
, hostName
, hostPublicKey
);
162 var gcdPromise
= Promise
.resolve();
163 if (this.gcdIds_
.has(hostId
)) {
164 gcdPromise
= this.gcdImpl_
.put(hostId
, hostName
, hostPublicKey
);
166 return legacyPromise
.then(function() {
167 // If GCD is too slow, just ignore it and return result from the
169 return base
.Promise
.withTimeout(
170 gcdPromise
, GCD_TIMEOUT_MS
);
175 remoting
.CombinedHostListApi
.prototype.remove = function(hostId
) {
176 var legacyPromise
= Promise
.resolve();
177 if (this.legacyIds_
.has(hostId
)) {
178 legacyPromise
= this.legacyImpl_
.remove(hostId
);
180 var gcdPromise
= Promise
.resolve();
181 if (this.gcdIds_
.has(hostId
)) {
182 gcdPromise
= this.gcdImpl_
.remove(hostId
);
184 return legacyPromise
.then(function() {
185 // If GCD is too slow, just ignore it and return result from the
187 return base
.Promise
.withTimeout(
188 gcdPromise
, GCD_TIMEOUT_MS
);
193 remoting
.CombinedHostListApi
.prototype.getSupportHost = function(supportId
) {
194 return this.legacyImpl_
.getSupportHost(supportId
);