OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview | 6 * @fileoverview |
7 * REST API for host-list management. | 7 * REST API for host-list management. |
8 */ | 8 */ |
9 | 9 |
10 /** @suppress {duplicate} */ | 10 /** @suppress {duplicate} */ |
11 var remoting = remoting || {}; | 11 var remoting = remoting || {}; |
12 | 12 |
13 (function() { | 13 (function() { |
14 | 14 |
15 'use strict'; | 15 'use strict'; |
16 | 16 |
17 /** | 17 /** |
18 * @constructor | 18 * @constructor |
19 * @implements {remoting.HostListApi} | 19 * @implements {remoting.HostListApi} |
20 */ | 20 */ |
21 remoting.HostListApiGcdImpl = function() { | 21 remoting.GcdHostListApi = function() { |
22 this.gcd_ = new remoting.gcd.Client({ | 22 this.gcd_ = new remoting.gcd.Client({ |
23 apiKey: remoting.settings.GOOGLE_API_KEY | 23 apiKey: remoting.settings.GOOGLE_API_KEY |
24 }); | 24 }); |
25 }; | 25 }; |
26 | 26 |
27 /** @override */ | 27 /** @override */ |
28 remoting.HostListApiGcdImpl.prototype.register = function( | 28 remoting.GcdHostListApi.prototype.register = function( |
29 newHostId, hostName, publicKey, hostClientId) { | 29 hostName, publicKey, hostClientId) { |
30 var self = this; | 30 var self = this; |
31 var deviceDraft = { | 31 var deviceDraft = { |
32 channel: { | 32 channel: { |
33 supportedType: 'xmpp' | 33 supportedType: 'xmpp' |
34 }, | 34 }, |
35 deviceKind: 'vendor', | 35 deviceKind: 'vendor', |
36 name: newHostId, | 36 name: hostName, |
37 displayName: hostName, | |
38 state: { | 37 state: { |
39 'publicKey': publicKey | 38 base: { |
40 } | 39 firmwareVersion: 'none', |
| 40 localDiscoveryEnabled: false, |
| 41 localAnonymousAccessMaxRole: 'none', |
| 42 localPairingEnabled: false, |
| 43 // The leading underscore is necessary for |_publicKey| |
| 44 // because it's not a standard key defined by GCD. |
| 45 _publicKey: publicKey |
| 46 } |
| 47 }, |
| 48 'tags': [CHROMOTING_DEVICE_TAG] |
41 }; | 49 }; |
42 | 50 |
43 return /** @type {!Promise<remoting.HostListApi.RegisterResult>} */ ( | 51 return /** @type {!Promise<remoting.HostListApi.RegisterResult>} */ ( |
44 this.gcd_.insertRegistrationTicket(). | 52 this.gcd_.insertRegistrationTicket(). |
45 then(function(ticket) { | 53 then(function(ticket) { |
46 return self.gcd_.patchRegistrationTicket( | 54 return self.gcd_.patchRegistrationTicket( |
47 ticket.id, deviceDraft, hostClientId); | 55 ticket.id, deviceDraft, hostClientId); |
48 }). | 56 }). |
49 then(function(/**remoting.gcd.RegistrationTicket*/ ticket) { | 57 then(function(/**remoting.gcd.RegistrationTicket*/ ticket) { |
50 return self.gcd_.finalizeRegistrationTicket(ticket.id); | 58 return self.gcd_.finalizeRegistrationTicket(ticket.id); |
51 }). | 59 }). |
52 then(function(/**remoting.gcd.RegistrationTicket*/ ticket) { | 60 then(function(/**remoting.gcd.RegistrationTicket*/ ticket) { |
53 return { | 61 return { |
54 authCode: ticket.robotAccountAuthorizationCode, | 62 authCode: ticket.robotAccountAuthorizationCode, |
55 email: ticket.robotAccountEmail, | 63 email: ticket.robotAccountEmail, |
56 gcdId: ticket.deviceId | 64 hostId: ticket.deviceId, |
| 65 isLegacy: false |
57 }; | 66 }; |
58 }). | 67 }). |
59 catch(function(error) { | 68 catch(function(error) { |
60 console.error('Error registering device with GCD: ' + error); | 69 console.error('Error registering device with GCD: ' + error); |
61 throw new remoting.Error(remoting.Error.Tag.REGISTRATION_FAILED); | 70 throw new remoting.Error(remoting.Error.Tag.REGISTRATION_FAILED); |
62 })); | 71 })); |
63 }; | 72 }; |
64 | 73 |
65 /** @override */ | 74 /** @override */ |
66 remoting.HostListApiGcdImpl.prototype.get = function() { | 75 remoting.GcdHostListApi.prototype.get = function() { |
67 return this.gcd_.listDevices(). | 76 return this.gcd_.listDevices(). |
68 then(function(devices) { | 77 then(function(devices) { |
69 var hosts = []; | 78 var hosts = []; |
70 devices.forEach(function(device) { | 79 devices.forEach(function(device) { |
71 try { | 80 try { |
72 hosts.push(deviceToHost(device)); | 81 if (isChromotingHost(device)) { |
| 82 hosts.push(deviceToHost(device)); |
| 83 } |
73 } catch (/** @type {*} */ error) { | 84 } catch (/** @type {*} */ error) { |
74 console.warn('Invalid device spec:', error); | 85 console.warn('Invalid device spec:', error); |
75 } | 86 } |
76 }); | 87 }); |
77 return hosts; | 88 return hosts; |
78 }); | 89 }); |
79 }; | 90 }; |
80 | 91 |
81 /** @override */ | 92 /** @override */ |
82 remoting.HostListApiGcdImpl.prototype.put = | 93 remoting.GcdHostListApi.prototype.put = |
83 function(hostId, hostName, hostPublicKey) { | 94 function(hostId, hostName, hostPublicKey) { |
84 // TODO(jrw) | 95 return this.gcd_.patchDevice(hostId, { |
85 throw new Error('Not implemented'); | 96 'name': hostName |
86 }; | 97 }).then(function(device) { |
87 | 98 if (device.name != hostName) { |
88 /** @override */ | 99 console.error('error updating host name'); |
89 remoting.HostListApiGcdImpl.prototype.remove = function(hostId) { | 100 throw remoting.Error.unexpected(); |
90 var that = this; | |
91 return this.gcd_.listDevices(hostId).then(function(devices) { | |
92 var gcdId = null; | |
93 for (var i = 0; i < devices.length; i++) { | |
94 var device = devices[i]; | |
95 // The "name" field in GCD holds what Chromoting considers to be | |
96 // the host ID. | |
97 if (device.name == hostId) { | |
98 gcdId = device.id; | |
99 } | |
100 } | 101 } |
101 if (gcdId == null) { | 102 if (!device.state || device.state['_publicKey'] != hostPublicKey) { |
102 return false; | 103 // TODO(jrw): Is there any reason to believe this would ever be |
103 } else { | 104 // happen? |
104 return that.gcd_.deleteDevice(gcdId); | 105 console.error('unexpected host public key'); |
| 106 throw remoting.Error.unexpected(); |
105 } | 107 } |
| 108 // Don't return anything. |
106 }); | 109 }); |
107 }; | 110 }; |
108 | 111 |
109 /** @override */ | 112 /** @override */ |
110 remoting.HostListApiGcdImpl.prototype.getSupportHost = function(supportId) { | 113 remoting.GcdHostListApi.prototype.remove = function(hostId) { |
| 114 return this.gcd_.deleteDevice(hostId).then(function(deleted) { |
| 115 if (!deleted) { |
| 116 console.error('error deleting host from GCD'); |
| 117 throw remoting.Error.unexpected(); |
| 118 } |
| 119 // Don't return anything. |
| 120 }); |
| 121 }; |
| 122 |
| 123 /** @override */ |
| 124 remoting.GcdHostListApi.prototype.getSupportHost = function(supportId) { |
111 console.error('getSupportHost not supported by HostListApiGclImpl'); | 125 console.error('getSupportHost not supported by HostListApiGclImpl'); |
112 return Promise.reject(remoting.Error.unexpected()); | 126 return Promise.reject(remoting.Error.unexpected()); |
113 }; | 127 }; |
114 | 128 |
115 /** | 129 /** |
| 130 * Tag for distinguishing Chromoting hosts from other devices stored |
| 131 * in GCD. |
| 132 * |
| 133 * @const |
| 134 */ |
| 135 var CHROMOTING_DEVICE_TAG = '1ce4542c-dd87-4320-ba19-ac173f98c04e'; |
| 136 |
| 137 /** |
| 138 * Check whether a GCD device entry is a Chromoting host. |
| 139 * |
| 140 * @param {remoting.gcd.Device} device |
| 141 * @return {boolean} |
| 142 */ |
| 143 function isChromotingHost(device) { |
| 144 return device.tags != null && |
| 145 device.tags.indexOf(CHROMOTING_DEVICE_TAG) != -1; |
| 146 } |
| 147 |
| 148 /** |
116 * Converts a GCD device description to a Host object. | 149 * Converts a GCD device description to a Host object. |
| 150 * |
117 * @param {!Object} device | 151 * @param {!Object} device |
118 * @return {!remoting.Host} | 152 * @return {!remoting.Host} |
119 */ | 153 */ |
120 function deviceToHost(device) { | 154 function deviceToHost(device) { |
121 var statusMap = { | 155 var statusMap = { |
122 'online': 'ONLINE', | 156 'online': 'ONLINE', |
123 'offline': 'OFFLINE' | 157 'offline': 'OFFLINE' |
124 }; | 158 }; |
125 var hostId = base.getStringAttr(device, 'name'); | 159 var hostId = base.getStringAttr(device, 'id'); |
126 var host = new remoting.Host(hostId); | 160 var host = new remoting.Host(hostId); |
127 host.hostName = base.getStringAttr(device, 'displayName'); | 161 host.hostName = base.getStringAttr(device, 'name'); |
128 host.status = base.getStringAttr( | 162 host.status = base.getStringAttr( |
129 statusMap, base.getStringAttr(device, 'connectionStatus')); | 163 statusMap, base.getStringAttr(device, 'connectionStatus')); |
130 var state = base.getObjectAttr(device, 'state', {}); | 164 var state = base.getObjectAttr(device, 'state', {}); |
131 host.publicKey = base.getStringAttr(state, 'publicKey'); | 165 var baseState = base.getObjectAttr(state, 'base', {}); |
132 host.jabberId = base.getStringAttr(state, 'jabberId', ''); | 166 host.publicKey = base.getStringAttr(baseState, '_publicKey'); |
133 host.hostVersion = base.getStringAttr(state, 'hostVersion', ''); | 167 host.jabberId = base.getStringAttr(baseState, '_jabberId', ''); |
| 168 host.hostVersion = base.getStringAttr(baseState, '_hostVersion', ''); |
134 var creationTimeMs = base.getNumberAttr(device, 'creationTimeMs', 0); | 169 var creationTimeMs = base.getNumberAttr(device, 'creationTimeMs', 0); |
135 if (creationTimeMs) { | 170 if (creationTimeMs) { |
136 host.createdTime = new Date(creationTimeMs).toISOString(); | 171 host.createdTime = new Date(creationTimeMs).toISOString(); |
137 } | 172 } |
138 var lastUpdateTimeMs = base.getNumberAttr(device, 'lastUpdateTimeMs', 0); | 173 var lastUpdateTimeMs = base.getNumberAttr(device, 'lastUpdateTimeMs', 0); |
139 if (lastUpdateTimeMs) { | 174 if (lastUpdateTimeMs) { |
140 host.updatedTime = new Date(lastUpdateTimeMs).toISOString(); | 175 host.updatedTime = new Date(lastUpdateTimeMs).toISOString(); |
141 } | 176 } |
142 return host; | 177 return host; |
143 }; | 178 }; |
144 | 179 |
145 })(); | 180 })(); |
OLD | NEW |