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 |