| Index: chrome/browser/resources/print_preview/cloud_print_interface.js
|
| diff --git a/chrome/browser/resources/print_preview/cloud_print_interface.js b/chrome/browser/resources/print_preview/cloud_print_interface.js
|
| index 71906609e34f38e0294056e4763df5003bd7bf08..a31ecdee90ac5e0e467f3986a8e5c85705a51199 100644
|
| --- a/chrome/browser/resources/print_preview/cloud_print_interface.js
|
| +++ b/chrome/browser/resources/print_preview/cloud_print_interface.js
|
| @@ -47,11 +47,12 @@ cr.define('cloudprint', function() {
|
| this.userSessionIndex_ = {};
|
|
|
| /**
|
| - * Last received XSRF token. Sent as a parameter in every request.
|
| - * @type {string}
|
| + * Stores last received XSRF tokens for each user account. Sent as
|
| + * a parameter with every request.
|
| + * @type {!Object.<string, string>}
|
| * @private
|
| */
|
| - this.xsrfToken_ = '';
|
| + this.xsrfTokens_ = {};
|
|
|
| /**
|
| * Pending requests delayed until we get access token.
|
| @@ -168,35 +169,33 @@ cr.define('cloudprint', function() {
|
|
|
| /**
|
| * Sends Google Cloud Print search API request.
|
| + * @param {string=} opt_account Account the search is sent for. When
|
| + * omitted, the search is done on behalf of the primary user.
|
| * @param {print_preview.Destination.Origin=} opt_origin When specified,
|
| * searches destinations for {@code opt_origin} only, otherwise starts
|
| * searches for all origins.
|
| */
|
| - search: function(opt_origin) {
|
| + search: function(opt_account, opt_origin) {
|
| + var account = opt_account || '';
|
| var origins =
|
| opt_origin && [opt_origin] || CloudPrintInterface.CLOUD_ORIGINS_;
|
| - // Terminate outstanding search requests for all requested origins.
|
| - this.outstandingCloudSearchRequests_ =
|
| - this.outstandingCloudSearchRequests_.filter(function(request) {
|
| - if (origins.indexOf(request.origin) >= 0) {
|
| - request.xhr.abort();
|
| - return false;
|
| - }
|
| - return true;
|
| - });
|
| - this.search_(true, origins);
|
| - this.search_(false, origins);
|
| + this.abortSearchRequests_(origins);
|
| + this.search_(true, account, origins);
|
| + this.search_(false, account, origins);
|
| },
|
|
|
| /**
|
| * Sends Google Cloud Print search API requests.
|
| * @param {boolean} isRecent Whether to search for only recently used
|
| * printers.
|
| + * @param {string} account Account the search is sent for. It matters for
|
| + * COOKIES origin only, and can be empty (sent on behalf of the primary
|
| + * user in this case).
|
| * @param {!Array.<!print_preview.Destination.Origin>} origins Origins to
|
| * search printers for.
|
| * @private
|
| */
|
| - search_: function(isRecent, origins) {
|
| + search_: function(isRecent, account, origins) {
|
| var params = [
|
| new HttpParam('connection_status', 'ALL'),
|
| new HttpParam('client', 'chrome'),
|
| @@ -206,9 +205,13 @@ cr.define('cloudprint', function() {
|
| params.push(new HttpParam('q', '^recent'));
|
| }
|
| origins.forEach(function(origin) {
|
| - var cpRequest =
|
| - this.buildRequest_('GET', 'search', params, origin,
|
| - this.onSearchDone_.bind(this, isRecent));
|
| + var cpRequest = this.buildRequest_(
|
| + 'GET',
|
| + 'search',
|
| + params,
|
| + origin,
|
| + account,
|
| + this.onSearchDone_.bind(this, isRecent));
|
| this.outstandingCloudSearchRequests_.push(cpRequest);
|
| this.sendOrQueueRequest_(cpRequest);
|
| }, this);
|
| @@ -241,9 +244,13 @@ cr.define('cloudprint', function() {
|
| '__google__chrome_version=' + chromeVersion),
|
| new HttpParam('tag', '__google__os=' + navigator.platform)
|
| ];
|
| - var cpRequest = this.buildRequest_('POST', 'submit', params,
|
| - destination.origin,
|
| - this.onSubmitDone_.bind(this));
|
| + var cpRequest = this.buildRequest_(
|
| + 'POST',
|
| + 'submit',
|
| + params,
|
| + destination.origin,
|
| + destination.account,
|
| + this.onSubmitDone_.bind(this));
|
| this.sendOrQueueRequest_(cpRequest);
|
| },
|
|
|
| @@ -251,37 +258,46 @@ cr.define('cloudprint', function() {
|
| * Sends a Google Cloud Print printer API request.
|
| * @param {string} printerId ID of the printer to lookup.
|
| * @param {!print_preview.Destination.Origin} origin Origin of the printer.
|
| + * @param {string=} account Account this printer is registered for. When
|
| + * provided for COOKIES {@code origin}, and users sessions are still not
|
| + * known, will be checked against the response (both success and failure
|
| + * to get printer) and, if the active user account is not the one
|
| + * requested, {@code account} is activated and printer request reissued.
|
| */
|
| - printer: function(printerId, origin) {
|
| + printer: function(printerId, origin, account) {
|
| var params = [
|
| new HttpParam('printerid', printerId),
|
| new HttpParam('use_cdd', 'true'),
|
| new HttpParam('printer_connection_status', 'true')
|
| ];
|
| - var cpRequest =
|
| - this.buildRequest_('GET', 'printer', params, origin,
|
| - this.onPrinterDone_.bind(this, printerId));
|
| - this.sendOrQueueRequest_(cpRequest);
|
| + this.sendOrQueueRequest_(this.buildRequest_(
|
| + 'GET',
|
| + 'printer',
|
| + params,
|
| + origin,
|
| + account,
|
| + this.onPrinterDone_.bind(this, printerId)));
|
| },
|
|
|
| /**
|
| * Sends a Google Cloud Print update API request to accept (or reject) the
|
| * terms-of-service of the given printer.
|
| - * @param {string} printerId ID of the printer to accept the
|
| - * terms-of-service for.
|
| - * @param {!print_preview.Destination.Origin} origin Origin of the printer.
|
| - * @param {boolean} isAccepted Whether the user accepted the
|
| - * terms-of-service.
|
| + * @param {!print_preview.Destination} destination Destination to accept ToS
|
| + * for.
|
| + * @param {boolean} isAccepted Whether the user accepted ToS or not.
|
| */
|
| - updatePrinterTosAcceptance: function(printerId, origin, isAccepted) {
|
| + updatePrinterTosAcceptance: function(destination, isAccepted) {
|
| var params = [
|
| - new HttpParam('printerid', printerId),
|
| + new HttpParam('printerid', destination.id),
|
| new HttpParam('is_tos_accepted', isAccepted)
|
| ];
|
| - var cpRequest =
|
| - this.buildRequest_('POST', 'update', params, origin,
|
| - this.onUpdatePrinterTosAcceptanceDone_.bind(this));
|
| - this.sendOrQueueRequest_(cpRequest);
|
| + this.sendOrQueueRequest_(this.buildRequest_(
|
| + 'POST',
|
| + 'update',
|
| + params,
|
| + destination.origin,
|
| + destination.account,
|
| + this.onUpdatePrinterTosAcceptanceDone_.bind(this)));
|
| },
|
|
|
| /**
|
| @@ -302,25 +318,28 @@ cr.define('cloudprint', function() {
|
| * @param {Array.<!HttpParam>} params HTTP parameters to include in the
|
| * request.
|
| * @param {!print_preview.Destination.Origin} origin Origin for destination.
|
| + * @param {?string} account Account the request is sent for. Can be
|
| + * {@code null} or empty string if the request is not cookie bound or
|
| + * is sent on behalf of the primary user.
|
| * @param {function(number, Object, !print_preview.Destination.Origin)}
|
| * callback Callback to invoke when request completes.
|
| * @return {!CloudPrintRequest} Partially prepared request.
|
| * @private
|
| */
|
| - buildRequest_: function(method, action, params, origin, callback) {
|
| + buildRequest_: function(method, action, params, origin, account, callback) {
|
| var url = this.baseUrl_ + '/' + action + '?xsrf=';
|
| if (origin == print_preview.Destination.Origin.COOKIES) {
|
| - if (!this.xsrfToken_) {
|
| + var xsrfToken = this.xsrfTokens_[account];
|
| + if (!xsrfToken) {
|
| // TODO(rltoscano): Should throw an error if not a read-only action or
|
| // issue an xsrf token request.
|
| } else {
|
| - url = url + this.xsrfToken_;
|
| + url = url + xsrfToken;
|
| }
|
| - params = params || [];
|
| - if (this.userInfo_.activeUser) {
|
| - var index = this.userSessionIndex_[this.userInfo_.activeUser] || 0;
|
| + if (account) {
|
| + var index = this.userSessionIndex_[account] || 0;
|
| if (index > 0) {
|
| - params.push(new HttpParam('user', index));
|
| + url += '&user=' + index;
|
| }
|
| }
|
| }
|
| @@ -356,7 +375,7 @@ cr.define('cloudprint', function() {
|
| xhr.setRequestHeader(header, headers[header]);
|
| }
|
|
|
| - return new CloudPrintRequest(xhr, body, origin, callback);
|
| + return new CloudPrintRequest(xhr, body, origin, account, callback);
|
| },
|
|
|
| /**
|
| @@ -407,6 +426,39 @@ cr.define('cloudprint', function() {
|
| },
|
|
|
| /**
|
| + * Updates user info and session index from the {@code request} response.
|
| + * @param {!CloudPrintRequest} request Request to extract user info from.
|
| + * @private
|
| + */
|
| + setUsers_: function(request) {
|
| + if (request.origin == print_preview.Destination.Origin.COOKIES) {
|
| + var users = request.result['request']['users'] || [];
|
| + this.userSessionIndex_ = {};
|
| + for (var i = 0; i < users.length; i++) {
|
| + this.userSessionIndex_[users[i]] = i;
|
| + }
|
| + this.userInfo_.setUsers(request.result['request']['user'], users);
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Terminates search requests for requested {@code origins}.
|
| + * @param {!Array.<print_preview.Destination.Origin>} origins Origins
|
| + * to terminate search requests for.
|
| + * @private
|
| + */
|
| + abortSearchRequests_: function(origins) {
|
| + this.outstandingCloudSearchRequests_ =
|
| + this.outstandingCloudSearchRequests_.filter(function(request) {
|
| + if (origins.indexOf(request.origin) >= 0) {
|
| + request.xhr.abort();
|
| + return false;
|
| + }
|
| + return true;
|
| + });
|
| + },
|
| +
|
| + /**
|
| * Called when a native layer receives access token.
|
| * @param {Event} evt Contains the authentication type and access token.
|
| * @private
|
| @@ -424,7 +476,7 @@ cr.define('cloudprint', function() {
|
| 'Bearer ' + event.accessToken);
|
| this.sendRequest_(request);
|
| } else { // No valid token.
|
| - // Without abort status does not exists.
|
| + // Without abort status does not exist.
|
| request.xhr.abort();
|
| request.callback(request);
|
| }
|
| @@ -444,7 +496,8 @@ cr.define('cloudprint', function() {
|
| request.result = JSON.parse(request.xhr.responseText);
|
| if (request.origin == print_preview.Destination.Origin.COOKIES &&
|
| request.result['success']) {
|
| - this.xsrfToken_ = request.result['xsrf_token'];
|
| + this.xsrfTokens_[request.result['request']['user']] =
|
| + request.result['xsrf_token'];
|
| }
|
| }
|
| request.status = request.xhr.status;
|
| @@ -460,15 +513,24 @@ cr.define('cloudprint', function() {
|
| * @private
|
| */
|
| onSearchDone_: function(isRecent, request) {
|
| + var lastRequestForThisOrigin = true;
|
| this.outstandingCloudSearchRequests_ =
|
| this.outstandingCloudSearchRequests_.filter(function(item) {
|
| + if (item != request && item.origin == request.origin) {
|
| + lastRequestForThisOrigin = false;
|
| + }
|
| return item != request;
|
| });
|
| + var activeUser = '';
|
| + if (request.origin == print_preview.Destination.Origin.COOKIES) {
|
| + activeUser =
|
| + request.result &&
|
| + request.result['request'] &&
|
| + request.result['request']['user'];
|
| + }
|
| + var event = null;
|
| if (request.xhr.status == 200 && request.result['success']) {
|
| - var activeUser = '';
|
| - if (request.origin == print_preview.Destination.Origin.COOKIES) {
|
| - activeUser = request.result['request']['user'];
|
| - }
|
| + // Extract printers.
|
| var printerListJson = request.result['printers'] || [];
|
| var printerList = [];
|
| printerListJson.forEach(function(printerJson) {
|
| @@ -479,25 +541,21 @@ cr.define('cloudprint', function() {
|
| console.error('Unable to parse cloud print destination: ' + err);
|
| }
|
| });
|
| - var searchDoneEvent =
|
| - new Event(CloudPrintInterface.EventType.SEARCH_DONE);
|
| - searchDoneEvent.printers = printerList;
|
| - searchDoneEvent.origin = request.origin;
|
| - searchDoneEvent.isRecent = isRecent;
|
| - if (request.origin == print_preview.Destination.Origin.COOKIES) {
|
| - var users = request.result['request']['users'] || [];
|
| - this.userSessionIndex_ = {};
|
| - for (var i = 0; i < users.length; i++) {
|
| - this.userSessionIndex_[users[i]] = i;
|
| - }
|
| - this.userInfo_.setUsers(activeUser, users);
|
| - }
|
| - this.dispatchEvent(searchDoneEvent);
|
| + // Extract and store users.
|
| + this.setUsers_(request);
|
| + // Dispatch SEARCH_DONE event.
|
| + event = new Event(CloudPrintInterface.EventType.SEARCH_DONE);
|
| + event.origin = request.origin;
|
| + event.printers = printerList;
|
| + event.isRecent = isRecent;
|
| } else {
|
| - var errorEvent = this.createErrorEvent_(
|
| - CloudPrintInterface.EventType.SEARCH_FAILED, request);
|
| - this.dispatchEvent(errorEvent);
|
| + event = this.createErrorEvent_(
|
| + CloudPrintInterface.EventType.SEARCH_FAILED,
|
| + request);
|
| }
|
| + event.user = activeUser;
|
| + event.searchDone = lastRequestForThisOrigin;
|
| + this.dispatchEvent(event);
|
| },
|
|
|
| /**
|
| @@ -525,6 +583,29 @@ cr.define('cloudprint', function() {
|
| * @private
|
| */
|
| onPrinterDone_: function(destinationId, request) {
|
| + // Special handling of the first printer request. It does not matter at
|
| + // this point, whether printer was found or not.
|
| + if (request.origin == print_preview.Destination.Origin.COOKIES &&
|
| + request.result &&
|
| + request.account &&
|
| + request.result['request']['user'] &&
|
| + request.result['request']['users'] &&
|
| + request.account != request.result['request']['user']) {
|
| + this.setUsers_(request);
|
| + // In case the user account is known, but not the primary one,
|
| + // activate it.
|
| + if (this.userSessionIndex_[request.account] > 0) {
|
| + this.userInfo_.activeUser = request.account;
|
| + // Repeat the request for the newly activated account.
|
| + this.printer(
|
| + request.result['request']['params']['printerid'],
|
| + request.origin,
|
| + request.account);
|
| + // Stop processing this request, wait for the new response.
|
| + return;
|
| + }
|
| + }
|
| + // Process response.
|
| if (request.xhr.status == 200 && request.result['success']) {
|
| var activeUser = '';
|
| if (request.origin == print_preview.Destination.Origin.COOKIES) {
|
| @@ -574,11 +655,14 @@ cr.define('cloudprint', function() {
|
| * @param {!XMLHttpRequest} xhr Partially prepared http request.
|
| * @param {string} body Data to send with POST requests.
|
| * @param {!print_preview.Destination.Origin} origin Origin for destination.
|
| + * @param {?string} account Account the request is sent for. Can be
|
| + * {@code null} or empty string if the request is not cookie bound or
|
| + * is sent on behalf of the primary user.
|
| * @param {function(!CloudPrintRequest)} callback Callback to invoke when
|
| * request completes.
|
| * @constructor
|
| */
|
| - function CloudPrintRequest(xhr, body, origin, callback) {
|
| + function CloudPrintRequest(xhr, body, origin, account, callback) {
|
| /**
|
| * Partially prepared http request.
|
| * @type {!XMLHttpRequest}
|
| @@ -598,6 +682,12 @@ cr.define('cloudprint', function() {
|
| this.origin = origin;
|
|
|
| /**
|
| + * User account this request is expected to be executed for.
|
| + * @type {?string}
|
| + */
|
| + this.account = account;
|
| +
|
| + /**
|
| * Callback to invoke when request completes.
|
| * @type {function(!CloudPrintRequest)}
|
| */
|
|
|