blob: 5bfab9fdef3ecc98a1fd2d9072bd05cd85a925d4 [file] [log] [blame]
// 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
* Client for the GCD REST API.
* TODO: Add link to GCD docs.
*/
/** @suppress {duplicate} */
var remoting = remoting || {};
/**
* Namespace for GCD definitions
* @type {Object}
*/
remoting.gcd = remoting.gcd || {};
/**
* @typedef {{
* id: string,
* robotAccountEmail: string,
* robotAccountAuthorizationCode: string,
* deviceId: string,
* deviceDraft: Object
* }}
*/
remoting.gcd.RegistrationTicket;
/**
* TODO: Flesh out with typical fields.
* @typedef {{
* id:string,
* name:string,
* state:(!Object|undefined),
* tags:(!Array<string>|undefined)
* }}
*/
remoting.gcd.Device;
/**
* @typedef {!Object}
*/
remoting.gcd.DevicePatch;
/**
* @typedef {{
* devices: (Array<remoting.gcd.Device>|undefined)
* }}
*/
remoting.gcd.DeviceListResponse;
(function() {
'use strict';
/**
* Interprets an HTTP response as a JSON object with a specific value
* in the 'kind' field.
* @param {remoting.Xhr.Response} response
* @param {string} expectedKind
* @return {!Object}
* @throws {remoting.Error}
*/
var responseAsObject = function(response, expectedKind) {
if (typeof response.getJson() != 'object') {
console.error(
'invalid response; expected object, got:', response.getJson());
throw remoting.Error.unexpected();
}
var obj = base.assertObject(response.getJson());
var kind = base.getStringAttr(obj, 'kind');
if (kind != expectedKind) {
console.error(
'invalid resonse kind; expected ' + expectedKind + ', got ' + kind);
throw remoting.Error.unexpected();
}
return obj;
};
/**
* Interprets an HTTP response as containing a GCD registration ticket.
* @param {remoting.Xhr.Response} response
* @return {!remoting.gcd.RegistrationTicket}
* @throws {remoting.Error}
*/
var responseAsGcdRegistrationTicket = function(response) {
return /** @type {!remoting.gcd.RegistrationTicket} */ (
responseAsObject(
response, 'clouddevices#registrationTicket'));
};
/**
* Interprets an HTTP response as containing a GCD device defintion.
* @param {remoting.Xhr.Response} response
* @return {!remoting.gcd.Device}
* @throws {remoting.Error}
*/
var responseAsGcdDevice = function(response) {
return /** @type {!remoting.gcd.Device} */ (
responseAsObject(response, 'clouddevices#device'));
};
/**
* Interprets an HTTP response as containing a GCD device list.
* @param {remoting.Xhr.Response} response
* @return {!remoting.gcd.DeviceListResponse}
* @throws {remoting.Error}
*/
var responseAsGcdDeviceListResponse = function(response) {
return /** @type {!remoting.gcd.DeviceListResponse} */ (
responseAsObject(response, 'clouddevices#devicesListResponse'));
};
/**
* Creates a new client using a specific API key, and optionall a
* specific base URL, and OAuth2 client ID.
* @param {{
* apiKey: string,
* apiBaseUrl: (string|undefined)
* }} options
* @constructor
*/
remoting.gcd.Client = function(options) {
/** @const */
this.apiKey_ = options.apiKey;
/** @const */
this.apiBaseUrl_ = options.apiBaseUrl ||
'https://www.googleapis.com/clouddevices/v1';
};
/**
* Creates a new registration ticket.
* TODO: Add link to GCD docs.
* @return {!Promise<remoting.gcd.RegistrationTicket>}
*/
remoting.gcd.Client.prototype.insertRegistrationTicket = function() {
return new remoting.Xhr({
method: 'POST',
url: this.apiBaseUrl_ + '/registrationTickets',
jsonContent: { 'userEmail': 'me' },
useIdentity: true,
acceptJson: true
}).start().then(function(/** remoting.Xhr.Response */ response) {
if (response.isError()) {
console.error('error creating registration ticket');
throw remoting.Error.unexpected();
}
return responseAsGcdRegistrationTicket(response);
});
};
/**
* Updates an existing registration ticket using patch semantics.
* TODO: Add link to GCD docs.
* @param {string} ticketId
* @param {!Object<*>} deviceDraft
* @param {string} oauthClientId
* @return {!Promise<remoting.gcd.RegistrationTicket>}
*/
remoting.gcd.Client.prototype.patchRegistrationTicket = function(
ticketId, deviceDraft, oauthClientId) {
return new remoting.Xhr({
method: 'PATCH',
url: this.apiBaseUrl_ + '/registrationTickets/' +
encodeURIComponent(ticketId),
urlParams: {
'key': this.apiKey_
},
jsonContent: {
'deviceDraft': deviceDraft,
'oauthClientId': oauthClientId
},
acceptJson: true
}).start().then(function(response) {
if (response.isError()) {
console.error('error patching registration ticket');
throw remoting.Error.unexpected();
}
return responseAsGcdRegistrationTicket(response);
});
};
/**
* Finalizes device registration and returns its credentials.
* TODO: Add link to GCD docs.
* @param {string} ticketId
* @return {!Promise<remoting.gcd.RegistrationTicket>}
*/
remoting.gcd.Client.prototype.finalizeRegistrationTicket = function(ticketId) {
return new remoting.Xhr({
method: 'POST',
url: this.apiBaseUrl_ + '/registrationTickets/' +
encodeURIComponent(ticketId) + '/finalize',
urlParams: {
'key': this.apiKey_
},
acceptJson: true
}).start().then(function(response) {
if (response.isError()) {
console.error('error finalizing registration ticket');
throw remoting.Error.unexpected();
}
return responseAsGcdRegistrationTicket(response);
});
};
/**
* Lists devices user has access to.
* TODO: Add link to GCD docs.
* @return {!Promise<!Array<remoting.gcd.Device>>}
*/
remoting.gcd.Client.prototype.listDevices = function() {
return new remoting.Xhr({
method: 'GET',
url: this.apiBaseUrl_ + '/devices',
useIdentity: true,
acceptJson: true
}).start().then(function(response) {
if (response.isError()) {
console.error('error getting device list');
throw remoting.Error.unexpected();
}
var hosts = responseAsGcdDeviceListResponse(response);
return hosts.devices || [];
});
};
/**
* Deletes a device from the system.
* TODO: Add link to GCD docs.
* @param {string} deviceId
* @return {!Promise<boolean>} Promise that resolves to true if the
* device was deleted, false if there was no such device ID.
*/
remoting.gcd.Client.prototype.deleteDevice = function(deviceId) {
return new remoting.Xhr({
method: 'DELETE',
url: this.apiBaseUrl_ + '/devices/' + deviceId,
useIdentity: true
}).start().then(function(response) {
if (response.status == 404) {
return false;
}
if (response.isError()) {
console.error('error deleting device');
throw remoting.Error.unexpected();
}
return true;
});
};
/**
* Updates a device data using patch semantics.
* TODO: Add link to GCD docs.
* @param {string} deviceId
* @param {!Object<*>} patch
* @return {!Promise<remoting.gcd.Device>}
*/
remoting.gcd.Client.prototype.patchDevice = function(deviceId, patch) {
return new remoting.Xhr({
method: 'PATCH',
url: this.apiBaseUrl_ + '/devices/' + deviceId,
jsonContent: patch,
useIdentity: true,
acceptJson: true
}).start().then(function(response) {
if (response.isError()) {
console.error('error patching device');
throw remoting.Error.unexpected();
}
return responseAsGcdDevice(response);
});
};
})();