Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012 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. | |
| 4 | |
| 5 cr.define('cloudprint', function() { | |
| 6 'use strict'; | |
| 7 | |
| 8 /** | |
| 9 * API to the Google Cloud Print service. | |
| 10 * @param {string} baseUrl Base part of the Google Cloud Print service URL | |
| 11 * with no trailing slash. For example, | |
| 12 * 'https://www.google.com/cloudprint'. | |
| 13 * @constructor | |
| 14 * @extends {cr.EventTarget} | |
| 15 */ | |
| 16 function CloudPrintInterface(baseUrl) { | |
| 17 /** | |
| 18 * The base URL of the Google Cloud Print API. | |
| 19 * @type {string} | |
| 20 * @private | |
| 21 */ | |
| 22 this.baseURL_ = baseUrl; | |
| 23 | |
| 24 /** | |
| 25 * Last received XSRF token. Sent as a parameter in every request. | |
| 26 * @type {string} | |
| 27 * @private | |
| 28 */ | |
| 29 this.xsrfToken_ = ''; | |
| 30 }; | |
| 31 | |
| 32 /** | |
| 33 * Event types dispatched by the interface. | |
| 34 * @enum {string} | |
| 35 */ | |
| 36 CloudPrintInterface.EventType = { | |
| 37 ERROR: 'cloudprint.CloudPrintInterface.ERROR', | |
| 38 PRINTER_DONE: 'cloudprint.CloudPrintInterface.PRINTER_DONE', | |
| 39 SEARCH_DONE: 'cloudprint.CloudPrintInterface.SEARCH_DONE', | |
| 40 SUBMIT_DONE: 'cloudprint.CloudPrintInterface.SUBMIT_DONE' | |
| 41 }; | |
| 42 | |
| 43 /** | |
| 44 * Content type header value for a URL encoded HTTP request. | |
| 45 * @type {string} | |
| 46 * @private | |
| 47 */ | |
| 48 CloudPrintInterface.URL_ENCODED_CONTENT_TYPE_ = | |
| 49 'application/x-www-form-urlencoded'; | |
| 50 | |
| 51 /** | |
| 52 * Content type header value for a multipart HTTP request. | |
| 53 * @type {string} | |
| 54 * @private | |
| 55 */ | |
| 56 CloudPrintInterface.MULTIPART_CONTENT_TYPE_ = | |
| 57 'multipart/form-data; boundary=----CloudPrintFormBoundaryjc9wuprokl8i'; | |
| 58 | |
| 59 /** | |
| 60 * Enumeration of JSON response fields from Google Cloud Print API. | |
| 61 * @enum {string} | |
| 62 * @private | |
| 63 */ | |
| 64 CloudPrintInterface.JsonFields_ = { | |
| 65 PRINTER: 'printer' | |
| 66 }; | |
| 67 | |
| 68 CloudPrintInterface.prototype = { | |
| 69 __proto__: cr.EventTarget.prototype, | |
| 70 | |
| 71 /** | |
| 72 * Sends a Google Cloud Print search API request. | |
| 73 * @param {boolean} isRecent Whether to search for only recently used | |
| 74 * printers. | |
| 75 */ | |
| 76 search: function(isRecent) { | |
| 77 var params = {}; | |
| 78 if (isRecent) { | |
| 79 params['q'] = '^recent'; | |
| 80 } | |
| 81 this.sendRequest_('GET', 'search', params, null, this.onSearchDone_); | |
| 82 }, | |
| 83 | |
| 84 /** | |
| 85 * Sends a Google Cloud Print submit API request. | |
| 86 * @param {string} body Body of the HTTP post request to send. | |
| 87 */ | |
| 88 submit: function(body) { | |
| 89 this.sendRequest_('POST', 'submit', null, body, this.onSubmitDone_); | |
| 90 }, | |
| 91 | |
| 92 /** | |
| 93 * Sends a Google Cloud Print printer API request. | |
| 94 * @param {string} printerId ID of the printer to lookup. | |
| 95 */ | |
| 96 printer: function(printerId) { | |
| 97 var params = {'printerid': printerId}; | |
|
kmadhusu
2012/05/18 20:13:46
nit: single quote is not required.
| |
| 98 this.sendRequest_('GET', 'printer', params, null, this.onPrinterDone_); | |
| 99 }, | |
| 100 | |
| 101 /** | |
| 102 * Creates an object that represents a Google Cloud Print print ticket. | |
| 103 * @param {!print_preview.Destination} destination Destination to print to. | |
| 104 * @param {!print_preview.PrintTicketStore} printTicketStore Used to create | |
| 105 * the state of the print ticket. | |
| 106 * @return {object} Google Cloud Print print ticket. | |
| 107 */ | |
| 108 createPrintTicket: function(destination, printTicketStore) { | |
| 109 if (destination.isLocal) { | |
| 110 throw Error( | |
|
kmadhusu
2012/05/18 20:13:46
throw Error ()... => logError(msg)?
| |
| 111 'Trying to create a Google Cloud Print print ticket for a local ' + | |
| 112 'destination'); | |
| 113 } | |
| 114 if (!destination.capabilities) { | |
| 115 throw Error( | |
| 116 'Trying to create a Google Cloud Print print ticket for a ' + | |
| 117 'destination with no print capabilities'); | |
| 118 } | |
| 119 | |
| 120 var ticketItems = []; | |
| 121 | |
| 122 if (destination.capabilities.collateCapability) { | |
| 123 var collateCap = destination.capabilities.collateCapability; | |
| 124 var ticketItem = { | |
| 125 'name': collateCap.id, | |
| 126 'type': collateCap.type, | |
| 127 'options': [{'name': printTicketStore.isCollateEnabled() ? | |
| 128 collateCap.collateOption : collateCap.noCollateOption}] | |
| 129 }; | |
| 130 ticketItems.push(ticketItem); | |
| 131 } | |
| 132 | |
| 133 if (destination.capabilities.colorCapability) { | |
| 134 var colorCap = destination.capabilities.colorCapability; | |
| 135 var ticketItem = { | |
| 136 'name': colorCap.id, | |
| 137 'type': colorCap.type, | |
| 138 'options': [{'name': printTicketStore.isColorEnabled() ? | |
| 139 colorCap.colorOption : colorCap.bwOption}] | |
| 140 }; | |
| 141 ticketItems.push(ticketItem); | |
| 142 } | |
| 143 | |
| 144 if (destination.capabilities.copiesCapability) { | |
| 145 var copiesCap = destination.capabilities.copiesCapability; | |
| 146 var ticketItem = { | |
| 147 'name': copiesCap.id, | |
| 148 'type': copiesCap.type, | |
| 149 'value': printTicketStore.getCopies() | |
| 150 }; | |
| 151 ticketItems.push(ticketItem); | |
| 152 } | |
| 153 | |
| 154 if (destination.capabilities.duplexCapability) { | |
| 155 var duplexCap = destination.capabilities.duplexCapability; | |
| 156 var ticketItem = { | |
| 157 'name': duplexCap.id, | |
| 158 'type': duplexCap.type, | |
| 159 'options': [{'name': printTicketStore.isDuplexEnabled() ? | |
| 160 duplexCap.longEdgeOption : duplexCap.simplexOption}] | |
| 161 }; | |
| 162 ticketItems.push(ticketItem); | |
| 163 } | |
| 164 | |
| 165 return { | |
| 166 'capabilities': ticketItems | |
| 167 }; | |
| 168 }, | |
| 169 | |
| 170 /** | |
| 171 * Sends a request to the Google Cloud Print API. | |
| 172 * @param {string} method HTTP method of the request. | |
| 173 * @param {string} action Google Cloud Print action to perform. | |
| 174 * @param {Object} params HTTP parameters to include in the request. | |
| 175 * @param {string} body HTTP multi-part encoded body. | |
| 176 * @param {function(Object)} successCallback Callback to invoke when request | |
| 177 * completes successfully. | |
| 178 */ | |
| 179 sendRequest_: function(method, action, params, body, successCallback) { | |
| 180 if (!this.xsrfToken_) { | |
| 181 // TODO Should throw an error if not a read-only action or issue an | |
| 182 // xsrf token request. | |
| 183 } | |
| 184 var url = this.baseURL_ + '/' + action + '?xsrf=' + this.xsrfToken_; | |
| 185 | |
| 186 if (params) { | |
| 187 for (var paramName in params) { | |
| 188 url += '&' + paramName + '=' + encodeURIComponent(params[paramName]); | |
| 189 } | |
| 190 } | |
| 191 | |
| 192 var headers = {}; | |
| 193 headers['X-CloudPrint-Proxy'] = 'ChromePrintPreview'; | |
| 194 if (method == 'GET') { | |
| 195 headers['Content-Type'] = CloudPrintInterface.URL_ENCODED_CONTENT_TYPE_; | |
| 196 } else if (method == 'POST') { | |
| 197 headers['Content-Type'] = CloudPrintInterface.MULTIPART_CONTENT_TYPE_; | |
| 198 } | |
| 199 | |
| 200 var xhr = new XMLHttpRequest(); | |
| 201 xhr.onreadystatechange = this.onReadyStateChange_.bind( | |
| 202 this, xhr, successCallback.bind(this)); | |
| 203 xhr.open(method, url, true); | |
| 204 xhr.withCredentials = true; | |
| 205 for (var header in headers) { | |
| 206 xhr.setRequestHeader(header, headers[header]); | |
| 207 } | |
| 208 xhr.send(body); | |
| 209 }, | |
| 210 | |
| 211 /** | |
| 212 * Dispatches an ERROR event with the given error message. | |
| 213 * @param {string} message Error message to include in the ERROR event. | |
| 214 * @private | |
| 215 */ | |
| 216 dispatchErrorEvent_: function(message) { | |
| 217 var errorEvent = new cr.Event(CloudPrintInterface.EventType.ERROR); | |
| 218 errorEvent.message = message; | |
| 219 this.dispatchEvent(errorEvent); | |
| 220 }, | |
| 221 | |
| 222 /** | |
| 223 * Called when the ready-state of a XML http request changes. | |
| 224 * Calls the successCallback with the result or dispatches an ERROR event. | |
| 225 * @param {XMLHttpRequest} xhr XML http request that changed. | |
| 226 * @param {function(Object)} successCallback Callback to call if the request | |
| 227 * was successful. | |
| 228 * @private | |
| 229 */ | |
| 230 onReadyStateChange_: function(xhr, successCallback) { | |
| 231 if (xhr.readyState == 4) { | |
| 232 if (xhr.status == 200) { | |
| 233 var result = JSON.parse(xhr.responseText); | |
| 234 if (result['success']) { | |
| 235 this.xsrfToken_ = result['xsrf_token']; | |
| 236 successCallback(result); | |
| 237 } else { | |
| 238 this.dispatchErrorEvent_(result['message']); | |
| 239 } | |
| 240 } else { | |
| 241 this.dispatchErrorEvent_(xhr.status + ''); | |
| 242 } | |
| 243 } | |
| 244 }, | |
| 245 | |
| 246 /** | |
| 247 * Called when the search request completes successfully. | |
| 248 * @param {Object} result JSON response. | |
| 249 * @private | |
| 250 */ | |
| 251 onSearchDone_: function(result) { | |
| 252 var printerListJson = result['printers'] || []; | |
| 253 var printerList = []; | |
| 254 for (var printerJson, i = 0; printerJson = printerListJson[i]; i++) { | |
| 255 try { | |
| 256 printerList.push(cloudprint.CloudDestinationParser.parse( | |
| 257 printerJson)); | |
| 258 } catch (err) { | |
| 259 logError('Unable to parse cloud print destination: ' + err); | |
| 260 } | |
| 261 } | |
| 262 var isRecent = result['request']['params']['q'] == '^recent'; | |
| 263 var searchDoneEvent = | |
| 264 new cr.Event(CloudPrintInterface.EventType.SEARCH_DONE); | |
| 265 searchDoneEvent.printers = printerList; | |
| 266 searchDoneEvent.isRecent = isRecent; | |
| 267 searchDoneEvent.email = result['request']['user']; | |
| 268 this.dispatchEvent(searchDoneEvent); | |
| 269 }, | |
| 270 | |
| 271 /** | |
| 272 * Called when the submit request completes successfully. | |
| 273 * @param {Object} result JSON response. | |
| 274 * @private | |
| 275 */ | |
| 276 onSubmitDone_: function(result) { | |
| 277 this.dispatchEvent( | |
| 278 new cr.Event(CloudPrintInterface.EventType.SUBMIT_DONE)); | |
| 279 }, | |
| 280 | |
| 281 /** | |
| 282 * Called when the printer request completes successfully. | |
| 283 * @param {Object} result JSON response. | |
| 284 * @private | |
| 285 */ | |
| 286 onPrinterDone_: function(result) { | |
| 287 // TODO Better error handling here. | |
| 288 var printerJson = result['printers'][0]; | |
| 289 var printer; | |
| 290 try { | |
| 291 printer = cloudprint.CloudDestinationParser.parse(printerJson); | |
| 292 } catch (err) { | |
| 293 throw Error('Failed to parse cloud print destination: ' + | |
| 294 JSON.stringify(printerJson)); | |
| 295 return; | |
| 296 } | |
| 297 var printerDoneEvent = new cr.Event( | |
| 298 CloudPrintInterface.EventType.PRINTER_DONE); | |
| 299 printerDoneEvent.printer = printer; | |
| 300 this.dispatchEvent(printerDoneEvent); | |
| 301 } | |
| 302 }; | |
| 303 | |
| 304 // Export | |
| 305 return { | |
| 306 CloudPrintInterface: CloudPrintInterface | |
| 307 }; | |
| 308 }); | |
| OLD | NEW |