Chromium Code Reviews| Index: chrome/browser/resources/gaia_auth/background.js |
| diff --git a/chrome/browser/resources/gaia_auth/background.js b/chrome/browser/resources/gaia_auth/background.js |
| index 3baafc2c332103425c7787c50207c86f61b67886..afa667838eb13a3c21855c1efbb8b5c390e2f9e8 100644 |
| --- a/chrome/browser/resources/gaia_auth/background.js |
| +++ b/chrome/browser/resources/gaia_auth/background.js |
| @@ -58,10 +58,10 @@ BackgroundBridgeManager.prototype = { |
| chrome.webRequest.onHeadersReceived.addListener( |
| function(details) { |
| if (this.bridges_[details.tabId]) |
| - this.bridges_[details.tabId].onHeadersReceived(details); |
| + return this.bridges_[details.tabId].onHeadersReceived(details); |
| }.bind(this), |
| {urls: ['*://*/*'], types: ['sub_frame']}, |
| - ['responseHeaders']); |
| + ['blocking', 'responseHeaders']); |
| chrome.webRequest.onCompleted.addListener( |
| function(details) { |
| @@ -260,31 +260,79 @@ BackgroundBridge.prototype = { |
| /** |
| * Handler or webRequest.onHeadersReceived. It reads the authenticated user |
| * email from google-accounts-signin-header. |
| + * @return {!Object} Modified request headers. |
| */ |
| onHeadersReceived: function(details) { |
| - if (!this.isDesktopFlow_ || |
| - !this.gaiaUrl_ || |
| - details.url.lastIndexOf(this.gaiaUrl_) != 0) { |
| + var headers = details.responseHeaders; |
| + |
| + if (this.isDesktopFlow_ && |
| + this.gaiaUrl_ && |
| + details.url.lastIndexOf(this.gaiaUrl_) == 0) { |
| // TODO(xiyuan, guohui): CrOS should reuse the logic below for reading the |
| // email for SAML users and cut off the /ListAccount call. |
| - return; |
| + for (var i = 0; headers && i < headers.length; ++i) { |
| + if (headers[i].name.toLowerCase() == 'google-accounts-signin') { |
| + var headerValues = headers[i].value.toLowerCase().split(','); |
| + var signinDetails = {}; |
| + headerValues.forEach(function(e) { |
| + var pair = e.split('='); |
| + signinDetails[pair[0].trim()] = pair[1].trim(); |
| + }); |
| + // Remove "" around. |
| + this.email_ = signinDetails['email'].slice(1, -1); |
| + this.sessionIndex_ = signinDetails['sessionindex']; |
| + break; |
| + } |
| + } |
| } |
| - var headers = details.responseHeaders; |
| - for (var i = 0; headers && i < headers.length; ++i) { |
| - if (headers[i].name.toLowerCase() == 'google-accounts-signin') { |
| - var headerValues = headers[i].value.toLowerCase().split(','); |
| - var signinDetails = {}; |
| - headerValues.forEach(function(e) { |
| - var pair = e.split('='); |
| - signinDetails[pair[0].trim()] = pair[1].trim(); |
| - }); |
| - // Remove "" around. |
| - this.email_ = signinDetails['email'].slice(1, -1); |
| - this.sessionIndex_ = signinDetails['sessionindex']; |
| - return; |
| + if (!this.isDesktopFlow_) { |
| + // Check whether GAIA headers indicating the start or end of a SAML |
| + // redirect are present. If so, synthesize cookies to mark these points. |
| + for (var i = 0; headers && i < headers.length; ++i) { |
| + if (headers[i].name.toLowerCase() == 'google-accounts-saml') { |
| + var action = headers[i].value.toLowerCase(); |
| + if (action == 'start') { |
| + // GAIA is redirecting to a SAML IdP. Any cookies contained in the |
| + // current |headers| were set by GAIA. Any cookies set in future |
| + // requests will be coming from the IdP. Append a cookie to the |
| + // current |headers| that marks the point at which the redirect |
| + // occurred. |
| + headers.push({name: 'Set-Cookie', |
| + value: 'google-accounts-saml-start=now'}); |
| + return {responseHeaders: headers}; |
| + } else if (action == 'end') { |
| + // The SAML IdP has redirected back to GAIA. Any cookies contained |
| + // in the current |headers| were already set by GAIA, not the IdP. A |
| + // cookie that marks the point at which the redirect occurred must |
| + // therefore be prepended to the |headers|. |
| + // |
| + // Due to limitations in the webRequest API, it is not possible to |
| + // prepend headers. It is only possible to delete and append headers |
|
xiyuan
2014/08/06 21:20:11
It took me a while to understand why we need to do
bartfab (slow)
2014/08/07 11:59:45
Done.
|
| + // but the same header cannot both be deleted and appended again. To |
| + // work around this, all headers that set cookies are deleted and |
| + // then appended again with a trailing semicolon. The trailing |
| + // semicolon is ignored by Chrome, causing the modified header to |
| + // actually set exactly the same cookie. |
| + var otherHeaders = []; |
| + var cookies = [{name: 'Set-Cookie', |
| + value: 'google-accounts-saml-end=now'}]; |
| + for (var j = 0; j < headers.length; ++j) { |
| + if (headers[j].name.toLowerCase().indexOf('set-cookie') == 0) { |
| + var header = headers[j]; |
| + header.value += ';'; |
| + cookies.push(header); |
| + } else { |
| + otherHeaders.push(headers[j]); |
| + } |
| + } |
| + return {responseHeaders: otherHeaders.concat(cookies)}; |
| + } |
| + } |
| } |
| } |
| + |
| + return {}; |
| }, |
| /** |