15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cr.define('cloudprint', function() {
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  'use strict';
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * API to the Google Cloud Print service.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} baseUrl Base part of the Google Cloud Print service URL
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     with no trailing slash. For example,
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     'https://www.google.com/cloudprint'.
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @param {!print_preview.NativeLayer} nativeLayer Native layer used to get
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   *     Auth2 tokens.
15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   * @param {!print_preview.UserInfo} userInfo User information repository.
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch   * @param {boolean} isInAppKioskMode Whether the print preview is in App
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch   *     Kiosk mode.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @constructor
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @extends {cr.EventTarget}
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  function CloudPrintInterface(
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      baseUrl, nativeLayer, userInfo, isInAppKioskMode) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * The base URL of the Google Cloud Print API.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @type {string}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @private
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this.baseUrl_ = baseUrl;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Used to get Auth2 tokens.
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @type {!print_preview.NativeLayer}
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @private
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    this.nativeLayer_ = nativeLayer;
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     * User information repository.
39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     * @type {!print_preview.UserInfo}
40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     * @private
41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     */
42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    this.userInfo_ = userInfo;
43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    /**
45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch     * Whether Print Preview is in App Kiosk mode, basically, use only printers
46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch     * available for the device.
47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch     * @type {boolean}
48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch     * @private
49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch     */
50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    this.isInAppKioskMode_ = isInAppKioskMode;
51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    /**
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     * Currently logged in users (identified by email) mapped to the Google
54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     * session index.
55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     * @type {!Object.<string, number>}
56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     * @private
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     */
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    this.userSessionIndex_ = {};
59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    /**
610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * Stores last received XSRF tokens for each user account. Sent as
620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * a parameter with every request.
630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * @type {!Object.<string, string>}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @private
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    this.xsrfTokens_ = {};
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /**
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Pending requests delayed until we get access token.
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @type {!Array.<!CloudPrintRequest>}
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @private
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    this.requestQueue_ = [];
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     * Outstanding cloud destination search requests.
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     * @type {!Array.<!CloudPrintRequest>}
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * @private
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    this.outstandingCloudSearchRequests_ = [];
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Event tracker used to keep track of native layer events.
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @type {!EventTracker}
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @private
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    this.tracker_ = new EventTracker();
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    this.addEventListeners_();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Event types dispatched by the interface.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @enum {string}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloudPrintInterface.EventType = {
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    INVITES_DONE: 'cloudprint.CloudPrintInterface.INVITES_DONE',
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    INVITES_FAILED: 'cloudprint.CloudPrintInterface.INVITES_FAILED',
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRINTER_DONE: 'cloudprint.CloudPrintInterface.PRINTER_DONE',
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRINTER_FAILED: 'cloudprint.CloudPrintInterface.PRINTER_FAILED',
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    PROCESS_INVITE_DONE: 'cloudprint.CloudPrintInterface.PROCESS_INVITE_DONE',
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    PROCESS_INVITE_FAILED:
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        'cloudprint.CloudPrintInterface.PROCESS_INVITE_FAILED',
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SEARCH_DONE: 'cloudprint.CloudPrintInterface.SEARCH_DONE',
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SEARCH_FAILED: 'cloudprint.CloudPrintInterface.SEARCH_FAILED',
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SUBMIT_DONE: 'cloudprint.CloudPrintInterface.SUBMIT_DONE',
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SUBMIT_FAILED: 'cloudprint.CloudPrintInterface.SUBMIT_FAILED',
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UPDATE_PRINTER_TOS_ACCEPTANCE_FAILED:
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'cloudprint.CloudPrintInterface.UPDATE_PRINTER_TOS_ACCEPTANCE_FAILED'
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Content type header value for a URL encoded HTTP request.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {string}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @const
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @private
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloudPrintInterface.URL_ENCODED_CONTENT_TYPE_ =
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'application/x-www-form-urlencoded';
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Multi-part POST request boundary used in communication with Google
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Cloud Print.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {string}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @const
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @private
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloudPrintInterface.MULTIPART_BOUNDARY_ =
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      '----CloudPrintFormBoundaryjc9wuprokl8i';
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Content type header value for a multipart HTTP request.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {string}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @const
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @private
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloudPrintInterface.MULTIPART_CONTENT_TYPE_ =
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'multipart/form-data; boundary=' +
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CloudPrintInterface.MULTIPART_BOUNDARY_;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Regex that extracts Chrome's version from the user-agent string.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @type {!RegExp}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @const
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @private
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloudPrintInterface.VERSION_REGEXP_ = /.*Chrome\/([\d\.]+)/i;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Enumeration of JSON response fields from Google Cloud Print API.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @enum {string}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @private
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloudPrintInterface.JsonFields_ = {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRINTER: 'printer'
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /**
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * Could Print origins used to search printers.
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @type {!Array.<!print_preview.Destination.Origin>}
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @const
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @private
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CloudPrintInterface.CLOUD_ORIGINS_ = [
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      print_preview.Destination.Origin.COOKIES,
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      print_preview.Destination.Origin.DEVICE
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // TODO(vitalybuka): Enable when implemented.
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // ready print_preview.Destination.Origin.PROFILE
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ];
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloudPrintInterface.prototype = {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __proto__: cr.EventTarget.prototype,
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** @return {string} Base URL of the Google Cloud Print service. */
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    get baseUrl() {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return this.baseUrl_;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * @return {boolean} Whether a search for cloud destinations is in progress.
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    get isCloudDestinationSearchInProgress() {
183c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return this.outstandingCloudSearchRequests_.length > 0;
184c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    },
185c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    /**
187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     * Sends Google Cloud Print search API request.
1880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * @param {string=} opt_account Account the search is sent for. When
1890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     *      omitted, the search is done on behalf of the primary user.
190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     * @param {print_preview.Destination.Origin=} opt_origin When specified,
191c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     *     searches destinations for {@code opt_origin} only, otherwise starts
192c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     *     searches for all origins.
193c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     */
1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    search: function(opt_account, opt_origin) {
1950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      var account = opt_account || '';
196c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      var origins =
197c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          opt_origin && [opt_origin] || CloudPrintInterface.CLOUD_ORIGINS_;
198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (this.isInAppKioskMode_) {
199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        origins = origins.filter(function(origin) {
200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          return origin != print_preview.Destination.Origin.COOKIES;
201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        });
202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
2030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      this.abortSearchRequests_(origins);
2040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      this.search_(true, account, origins);
2050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      this.search_(false, account, origins);
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    },
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /**
209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     * Sends Google Cloud Print search API requests.
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param {boolean} isRecent Whether to search for only recently used
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *     printers.
2120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * @param {string} account Account the search is sent for. It matters for
2130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     *     COOKIES origin only, and can be empty (sent on behalf of the primary
2140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     *     user in this case).
215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     * @param {!Array.<!print_preview.Destination.Origin>} origins Origins to
216c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     *     search printers for.
217c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     * @private
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
2190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    search_: function(isRecent, account, origins) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var params = [
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new HttpParam('connection_status', 'ALL'),
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        new HttpParam('client', 'chrome'),
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        new HttpParam('use_cdd', 'true')
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ];
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (isRecent) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        params.push(new HttpParam('q', '^recent'));
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      origins.forEach(function(origin) {
2290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        var cpRequest = this.buildRequest_(
2300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            'GET',
2310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            'search',
2320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            params,
2330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            origin,
2340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            account,
2350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            this.onSearchDone_.bind(this, isRecent));
236c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        this.outstandingCloudSearchRequests_.push(cpRequest);
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        this.sendOrQueueRequest_(cpRequest);
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }, this);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * Sends Google Cloud Print printer sharing invitations API requests.
2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * @param {string} account Account the request is sent for.
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     */
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    invites: function(account) {
2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var params = [
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new HttpParam('client', 'chrome'),
2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ];
2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      this.sendOrQueueRequest_(this.buildRequest_(
2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          'GET',
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          'invites',
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          params,
2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          print_preview.Destination.Origin.COOKIES,
2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          account,
2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          this.onInvitesDone_.bind(this)));
2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    },
2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    /**
2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * Accepts or rejects printer sharing invitation.
2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * @param {!print_preview.Invitation} invitation Invitation to process.
2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * @param {boolean} accept Whether to accept this invitation.
2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     */
2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    processInvite: function(invitation, accept) {
2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var params = [
2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new HttpParam('printerid', invitation.destination.id),
2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new HttpParam('email', invitation.scopeId),
2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new HttpParam('accept', accept),
2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new HttpParam('use_cdd', true),
2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ];
2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      this.sendOrQueueRequest_(this.buildRequest_(
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          'POST',
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          'processinvite',
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          params,
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          invitation.destination.origin,
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          invitation.destination.account,
2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          this.onProcessInviteDone_.bind(this, invitation, accept)));
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    },
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    /**
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Sends a Google Cloud Print submit API request.
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param {!print_preview.Destination} destination Cloud destination to
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *     print to.
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param {!print_preview.PrintTicketStore} printTicketStore Contains the
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *     print ticket to print.
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param {!print_preview.DocumentInfo} documentInfo Document data model.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param {string} data Base64 encoded data of the document.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    submit: function(destination, printTicketStore, documentInfo, data) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var result =
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CloudPrintInterface.VERSION_REGEXP_.exec(navigator.userAgent);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var chromeVersion = 'unknown';
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (result && result.length == 2) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        chromeVersion = result[1];
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var params = [
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new HttpParam('printerid', destination.id),
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new HttpParam('contentType', 'dataUrl'),
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        new HttpParam('title', documentInfo.title),
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        new HttpParam('ticket',
300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                      printTicketStore.createPrintTicket(destination)),
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new HttpParam('content', 'data:application/pdf;base64,' + data),
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new HttpParam('tag',
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      '__google__chrome_version=' + chromeVersion),
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new HttpParam('tag', '__google__os=' + navigator.platform)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ];
3060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      var cpRequest = this.buildRequest_(
3070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          'POST',
3080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          'submit',
3090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          params,
3100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          destination.origin,
3110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          destination.account,
3120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          this.onSubmitDone_.bind(this));
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      this.sendOrQueueRequest_(cpRequest);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Sends a Google Cloud Print printer API request.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param {string} printerId ID of the printer to lookup.
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param {!print_preview.Destination.Origin} origin Origin of the printer.
3200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * @param {string=} account Account this printer is registered for. When
3210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     *     provided for COOKIES {@code origin}, and users sessions are still not
3220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     *     known, will be checked against the response (both success and failure
3230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     *     to get printer) and, if the active user account is not the one
3240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     *     requested, {@code account} is activated and printer request reissued.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
3260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    printer: function(printerId, origin, account) {
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      var params = [
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        new HttpParam('printerid', printerId),
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        new HttpParam('use_cdd', 'true'),
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        new HttpParam('printer_connection_status', 'true')
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ];
3320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      this.sendOrQueueRequest_(this.buildRequest_(
3330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          'GET',
3340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          'printer',
3350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          params,
3360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          origin,
3370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          account,
3380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          this.onPrinterDone_.bind(this, printerId)));
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Sends a Google Cloud Print update API request to accept (or reject) the
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * terms-of-service of the given printer.
3440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * @param {!print_preview.Destination} destination Destination to accept ToS
3450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     *     for.
3460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * @param {boolean} isAccepted Whether the user accepted ToS or not.
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
3480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    updatePrinterTosAcceptance: function(destination, isAccepted) {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var params = [
3500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        new HttpParam('printerid', destination.id),
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new HttpParam('is_tos_accepted', isAccepted)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ];
3530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      this.sendOrQueueRequest_(this.buildRequest_(
3540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          'POST',
3550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          'update',
3560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          params,
3570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          destination.origin,
3580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          destination.account,
3590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          this.onUpdatePrinterTosAcceptanceDone_.bind(this)));
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    },
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
363c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch     * Adds event listeners to relevant events.
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @private
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    addEventListeners_: function() {
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      this.tracker_.add(
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          this.nativeLayer_,
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          print_preview.NativeLayer.EventType.ACCESS_TOKEN_READY,
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          this.onAccessTokenReady_.bind(this));
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Builds request to the Google Cloud Print API.
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param {string} method HTTP method of the request.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param {string} action Google Cloud Print action to perform.
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param {Array.<!HttpParam>} params HTTP parameters to include in the
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *     request.
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param {!print_preview.Destination.Origin} origin Origin for destination.
3800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * @param {?string} account Account the request is sent for. Can be
3810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     *     {@code null} or empty string if the request is not cookie bound or
3820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     *     is sent on behalf of the primary user.
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param {function(number, Object, !print_preview.Destination.Origin)}
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     *     callback Callback to invoke when request completes.
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @return {!CloudPrintRequest} Partially prepared request.
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @private
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
3880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    buildRequest_: function(method, action, params, origin, account, callback) {
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      var url = this.baseUrl_ + '/' + action + '?xsrf=';
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (origin == print_preview.Destination.Origin.COOKIES) {
3910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        var xsrfToken = this.xsrfTokens_[account];
3920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        if (!xsrfToken) {
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          // TODO(rltoscano): Should throw an error if not a read-only action or
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          // issue an xsrf token request.
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        } else {
3960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          url = url + xsrfToken;
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
3980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        if (account) {
3990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          var index = this.userSessionIndex_[account] || 0;
400c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          if (index > 0) {
4010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            url += '&user=' + index;
402c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          }
403c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        }
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var body = null;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (params) {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (method == 'GET') {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          url = params.reduce(function(partialUrl, param) {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return partialUrl + '&' + param.name + '=' +
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                encodeURIComponent(param.value);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }, url);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (method == 'POST') {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          body = params.reduce(function(partialBody, param) {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return partialBody + 'Content-Disposition: form-data; name=\"' +
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                param.name + '\"\r\n\r\n' + param.value + '\r\n--' +
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                CloudPrintInterface.MULTIPART_BOUNDARY_ + '\r\n';
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }, '--' + CloudPrintInterface.MULTIPART_BOUNDARY_ + '\r\n');
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var headers = {};
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers['X-CloudPrint-Proxy'] = 'ChromePrintPreview';
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (method == 'GET') {
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        headers['Content-Type'] = CloudPrintInterface.URL_ENCODED_CONTENT_TYPE_;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (method == 'POST') {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        headers['Content-Type'] = CloudPrintInterface.MULTIPART_CONTENT_TYPE_;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var xhr = new XMLHttpRequest();
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xhr.open(method, url, true);
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      xhr.withCredentials =
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          (origin == print_preview.Destination.Origin.COOKIES);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (var header in headers) {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xhr.setRequestHeader(header, headers[header]);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return new CloudPrintRequest(xhr, body, origin, account, callback);
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    },
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Sends a request to the Google Cloud Print API or queues if it needs to
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     *     wait OAuth2 access token.
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param {!CloudPrintRequest} request Request to send or queue.
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @private
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    sendOrQueueRequest_: function(request) {
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (request.origin == print_preview.Destination.Origin.COOKIES) {
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return this.sendRequest_(request);
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else {
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        this.requestQueue_.push(request);
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        this.nativeLayer_.startGetAccessToken(request.origin);
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    },
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Sends a request to the Google Cloud Print API.
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param {!CloudPrintRequest} request Request to send.
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @private
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    sendRequest_: function(request) {
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      request.xhr.onreadystatechange =
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          this.onReadyStateChange_.bind(this, request);
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      request.xhr.send(request.body);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Creates a Google Cloud Print interface error that is ready to dispatch.
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param {!CloudPrintInterface.EventType} type Type of the error.
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param {!CloudPrintRequest} request Request that has been completed.
4704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)     * @return {!Event} Google Cloud Print interface error event.
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @private
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    createErrorEvent_: function(type, request) {
4744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      var errorEvent = new Event(type);
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      errorEvent.status = request.xhr.status;
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (request.xhr.status == 200) {
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        errorEvent.errorCode = request.result['errorCode'];
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        errorEvent.message = request.result['message'];
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else {
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        errorEvent.errorCode = 0;
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        errorEvent.message = '';
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      errorEvent.origin = request.origin;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return errorEvent;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
4880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * Updates user info and session index from the {@code request} response.
4890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * @param {!CloudPrintRequest} request Request to extract user info from.
4900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * @private
4910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     */
4920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    setUsers_: function(request) {
4930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      if (request.origin == print_preview.Destination.Origin.COOKIES) {
4940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        var users = request.result['request']['users'] || [];
4950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        this.userSessionIndex_ = {};
4960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        for (var i = 0; i < users.length; i++) {
4970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          this.userSessionIndex_[users[i]] = i;
4980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        }
4990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        this.userInfo_.setUsers(request.result['request']['user'], users);
5000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      }
5010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    },
5020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    /**
5040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * Terminates search requests for requested {@code origins}.
5050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * @param {!Array.<print_preview.Destination.Origin>} origins Origins
5060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     *     to terminate search requests for.
5070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * @private
5080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     */
5090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    abortSearchRequests_: function(origins) {
5100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      this.outstandingCloudSearchRequests_ =
5110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          this.outstandingCloudSearchRequests_.filter(function(request) {
5120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            if (origins.indexOf(request.origin) >= 0) {
5130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch              request.xhr.abort();
5140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch              return false;
5150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            }
5160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            return true;
5170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          });
5180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    },
5190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    /**
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Called when a native layer receives access token.
5221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * @param {Event} event Contains the authentication type and access token.
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @private
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    onAccessTokenReady_: function(event) {
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // TODO(vitalybuka): remove when other Origins implemented.
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      assert(event.authType == print_preview.Destination.Origin.DEVICE);
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      this.requestQueue_ = this.requestQueue_.filter(function(request) {
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        assert(request.origin == print_preview.Destination.Origin.DEVICE);
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (request.origin != event.authType) {
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          return true;
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (event.accessToken) {
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          request.xhr.setRequestHeader('Authorization',
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       'Bearer ' + event.accessToken);
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          this.sendRequest_(request);
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        } else {  // No valid token.
5380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          // Without abort status does not exist.
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          request.xhr.abort();
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          request.callback(request);
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return false;
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }, this);
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    },
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Called when the ready-state of a XML http request changes.
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Calls the successCallback with the result or dispatches an ERROR event.
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param {!CloudPrintRequest} request Request that was changed.
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @private
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    onReadyStateChange_: function(request) {
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (request.xhr.readyState == 4) {
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (request.xhr.status == 200) {
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          request.result = JSON.parse(request.xhr.responseText);
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          if (request.origin == print_preview.Destination.Origin.COOKIES &&
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              request.result['success']) {
5580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            this.xsrfTokens_[request.result['request']['user']] =
5590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                request.result['xsrf_token'];
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        request.status = request.xhr.status;
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        request.callback(request);
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Called when the search request completes.
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param {boolean} isRecent Whether the search request was for recent
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *     destinations.
571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param {!CloudPrintRequest} request Request that has been completed.
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @private
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    onSearchDone_: function(isRecent, request) {
5750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      var lastRequestForThisOrigin = true;
576c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      this.outstandingCloudSearchRequests_ =
577c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          this.outstandingCloudSearchRequests_.filter(function(item) {
5780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            if (item != request && item.origin == request.origin) {
5790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch              lastRequestForThisOrigin = false;
5800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            }
581c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            return item != request;
582c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          });
5830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      var activeUser = '';
5840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      if (request.origin == print_preview.Destination.Origin.COOKIES) {
5850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        activeUser =
5860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            request.result &&
5870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            request.result['request'] &&
5880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            request.result['request']['user'];
5890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      }
5900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      var event = null;
591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (request.xhr.status == 200 && request.result['success']) {
5920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        // Extract printers.
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        var printerListJson = request.result['printers'] || [];
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var printerList = [];
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printerListJson.forEach(function(printerJson) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          try {
597c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            printerList.push(cloudprint.CloudDestinationParser.parse(
598c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                printerJson, request.origin, activeUser));
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } catch (err) {
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            console.error('Unable to parse cloud print destination: ' + err);
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        });
6030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        // Extract and store users.
6040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        this.setUsers_(request);
6050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        // Dispatch SEARCH_DONE event.
6060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        event = new Event(CloudPrintInterface.EventType.SEARCH_DONE);
6070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        event.origin = request.origin;
6080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        event.printers = printerList;
6090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        event.isRecent = isRecent;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
6110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        event = this.createErrorEvent_(
6120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            CloudPrintInterface.EventType.SEARCH_FAILED,
6130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            request);
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      event.user = activeUser;
6160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      event.searchDone = lastRequestForThisOrigin;
6170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      this.dispatchEvent(event);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
6211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * Called when invitations search request completes.
6221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * @param {!CloudPrintRequest} request Request that has been completed.
6231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * @private
6241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     */
6251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    onInvitesDone_: function(request) {
6261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var event = null;
6271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var activeUser =
6281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          (request.result &&
6291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci           request.result['request'] &&
6301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci           request.result['request']['user']) || '';
6311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (request.xhr.status == 200 && request.result['success']) {
6321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        // Extract invitations.
6331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        var invitationListJson = request.result['invites'] || [];
6341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        var invitationList = [];
6351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        invitationListJson.forEach(function(invitationJson) {
6361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          try {
6371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            invitationList.push(cloudprint.InvitationParser.parse(
6381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                invitationJson, activeUser));
6391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          } catch (e) {
6401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            console.error('Unable to parse invitation: ' + e);
6411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          }
6421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        });
6431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        // Dispatch INVITES_DONE event.
6441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        event = new Event(CloudPrintInterface.EventType.INVITES_DONE);
6451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        event.invitations = invitationList;
6461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      } else {
6471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        event = this.createErrorEvent_(
6481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            CloudPrintInterface.EventType.INVITES_FAILED, request);
6491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
6501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      event.user = activeUser;
6511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      this.dispatchEvent(event);
6521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    },
6531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    /**
6551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * Called when invitation processing request completes.
6561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * @param {!print_preview.Invitation} invitation Processed invitation.
6571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * @param {boolean} accept Whether this invitation was accepted or rejected.
6581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * @param {!CloudPrintRequest} request Request that has been completed.
6591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * @private
6601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     */
6611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    onProcessInviteDone_: function(invitation, accept, request) {
6621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var event = null;
6631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var activeUser =
6641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          (request.result &&
6651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci           request.result['request'] &&
6661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci           request.result['request']['user']) || '';
6671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (request.xhr.status == 200 && request.result['success']) {
6681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        event = new Event(CloudPrintInterface.EventType.PROCESS_INVITE_DONE);
6691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (accept) {
6701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          try {
6711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            event.printer = cloudprint.CloudDestinationParser.parse(
6721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                request.result['printer'], request.origin, activeUser);
6731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          } catch (e) {
6741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            console.error('Failed to parse cloud print destination: ' + e);
6751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          }
6761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
6771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      } else {
6781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        event = this.createErrorEvent_(
6791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            CloudPrintInterface.EventType.PROCESS_INVITE_FAILED, request);
6801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
6811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      event.invitation = invitation;
6821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      event.accept = accept;
6831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      event.user = activeUser;
6841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      this.dispatchEvent(event);
6851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    },
6861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    /**
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Called when the submit request completes.
689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param {!CloudPrintRequest} request Request that has been completed.
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @private
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    onSubmitDone_: function(request) {
693c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (request.xhr.status == 200 && request.result['success']) {
6944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        var submitDoneEvent = new Event(
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            CloudPrintInterface.EventType.SUBMIT_DONE);
696c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        submitDoneEvent.jobId = request.result['job']['id'];
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this.dispatchEvent(submitDoneEvent);
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var errorEvent = this.createErrorEvent_(
700c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            CloudPrintInterface.EventType.SUBMIT_FAILED, request);
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this.dispatchEvent(errorEvent);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Called when the printer request completes.
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param {string} destinationId ID of the destination that was looked up.
708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param {!CloudPrintRequest} request Request that has been completed.
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @private
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
711c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    onPrinterDone_: function(destinationId, request) {
7120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      // Special handling of the first printer request. It does not matter at
7130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      // this point, whether printer was found or not.
7140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      if (request.origin == print_preview.Destination.Origin.COOKIES &&
7150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          request.result &&
7160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          request.account &&
7170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          request.result['request']['user'] &&
7180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          request.result['request']['users'] &&
7190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          request.account != request.result['request']['user']) {
7200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        this.setUsers_(request);
7210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        // In case the user account is known, but not the primary one,
7220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        // activate it.
7230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        if (this.userSessionIndex_[request.account] > 0) {
7240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          this.userInfo_.activeUser = request.account;
7250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          // Repeat the request for the newly activated account.
7260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          this.printer(
7270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch              request.result['request']['params']['printerid'],
7280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch              request.origin,
7290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch              request.account);
7300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          // Stop processing this request, wait for the new response.
7310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          return;
7320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        }
7330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      }
7340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      // Process response.
735c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (request.xhr.status == 200 && request.result['success']) {
736c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        var activeUser = '';
737c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        if (request.origin == print_preview.Destination.Origin.COOKIES) {
738c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          activeUser = request.result['request']['user'];
739c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        }
740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        var printerJson = request.result['printers'][0];
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var printer;
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try {
743c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          printer = cloudprint.CloudDestinationParser.parse(
744c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch              printerJson, request.origin, activeUser);
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } catch (err) {
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          console.error('Failed to parse cloud print destination: ' +
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              JSON.stringify(printerJson));
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var printerDoneEvent =
7514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            new Event(CloudPrintInterface.EventType.PRINTER_DONE);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printerDoneEvent.printer = printer;
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this.dispatchEvent(printerDoneEvent);
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var errorEvent = this.createErrorEvent_(
756c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            CloudPrintInterface.EventType.PRINTER_FAILED, request);
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        errorEvent.destinationId = destinationId;
758c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        errorEvent.destinationOrigin = request.origin;
759c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        this.dispatchEvent(errorEvent, request.origin);
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Called when the update printer TOS acceptance request completes.
765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param {!CloudPrintRequest} request Request that has been completed.
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @private
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
768c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    onUpdatePrinterTosAcceptanceDone_: function(request) {
769c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (request.xhr.status == 200 && request.result['success']) {
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Do nothing.
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var errorEvent = this.createErrorEvent_(
773c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            CloudPrintInterface.EventType.SUBMIT_FAILED, request);
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this.dispatchEvent(errorEvent);
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * Data structure that holds data for Cloud Print requests.
781c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @param {!XMLHttpRequest} xhr Partially prepared http request.
782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @param {string} body Data to send with POST requests.
783c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @param {!print_preview.Destination.Origin} origin Origin for destination.
7840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch   * @param {?string} account Account the request is sent for. Can be
7850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch   *     {@code null} or empty string if the request is not cookie bound or
7860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch   *     is sent on behalf of the primary user.
787c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @param {function(!CloudPrintRequest)} callback Callback to invoke when
788c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   *     request completes.
789c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @constructor
790c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
7910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  function CloudPrintRequest(xhr, body, origin, account, callback) {
792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Partially prepared http request.
794c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @type {!XMLHttpRequest}
795c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
796c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    this.xhr = xhr;
797c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
798c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
799c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Data to send with POST requests.
800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @type {string}
801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
802c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    this.body = body;
803c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
804c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
805c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Origin for destination.
806c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @type {!print_preview.Destination.Origin}
807c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    this.origin = origin;
809c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
810c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
8110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * User account this request is expected to be executed for.
8120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     * @type {?string}
8130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch     */
8140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    this.account = account;
8150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
8160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    /**
817c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Callback to invoke when request completes.
818c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @type {function(!CloudPrintRequest)}
819c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
820c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    this.callback = callback;
821c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
822c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
823c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Result for requests.
824c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @type {Object} JSON response.
825c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    this.result = null;
827c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
828c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
829c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /**
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Data structure that represents an HTTP parameter.
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} name Name of the parameter.
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} value Value of the parameter.
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @constructor
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function HttpParam(name, value) {
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Name of the parameter.
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @type {string}
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this.name = name;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Name of the value.
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @type {string}
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this.value = value;
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Export
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return {
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloudPrintInterface: CloudPrintInterface
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)});
854