Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(693)

Side by Side Diff: chrome/browser/resources/gaia_auth/background.js

Issue 134263005: Implement inline signin with iframe (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix for various iframe bugs Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @fileoverview 6 * @fileoverview
7 * A background script of the auth extension that bridges the communication 7 * A background script of the auth extension that bridges the communication
8 * between the main and injected scripts. 8 * between the main and injected scripts.
9 * 9 *
10 * Here is an overview of the communication flow when SAML is being used: 10 * Here is an overview of the communication flow when SAML is being used:
(...skipping 14 matching lines...) Expand all
25 25
26 /** 26 /**
27 * BackgroundBridge allows the main script and the injected script to 27 * BackgroundBridge allows the main script and the injected script to
28 * collaborate. It forwards credentials API calls to the main script and 28 * collaborate. It forwards credentials API calls to the main script and
29 * maintains a list of scraped passwords. 29 * maintains a list of scraped passwords.
30 */ 30 */
31 function BackgroundBridge() { 31 function BackgroundBridge() {
32 } 32 }
33 33
34 BackgroundBridge.prototype = { 34 BackgroundBridge.prototype = {
35 // Continue URL that is set from main auth script.
36 continueUrl_: null,
37
38 // Whether the extension is loaded in a constrained window.
39 // Set from main auth script.
40 isConstrainedWindow_: null,
41
42 // Email of the newly authenticated user based on the gaia response header
43 // 'google-accounts-signin'.
44 email_: null,
45
46 // Session index of the newly authenticated user based on the gaia response
47 // header 'google-accounts-signin'.
48 sessionIndex_: null,
49
35 // Gaia URL base that is set from main auth script. 50 // Gaia URL base that is set from main auth script.
36 gaiaUrl_: null, 51 gaiaUrl_: null,
37 52
38 // Whether auth flow has started. It is used as a signal of whether the 53 // Whether auth flow has started. It is used as a signal of whether the
39 // injected script should scrape passwords. 54 // injected script should scrape passwords.
40 authStarted_: false, 55 authStarted_: false,
41 56
42 passwordStore_: {}, 57 passwordStore_: {},
43 58
44 channelMain_: null, 59 channelMain_: {},
45 channelInjected_: null, 60 channelInjected_: {},
46 61
47 run: function() { 62 run: function() {
48 chrome.runtime.onConnect.addListener(this.onConnect_.bind(this)); 63 chrome.runtime.onConnect.addListener(this.onConnect_.bind(this));
49 64
50 // Workarounds for loading SAML page in an iframe. 65 // Workarounds for loading SAML page in an iframe.
51 chrome.webRequest.onHeadersReceived.addListener( 66 chrome.webRequest.onHeadersReceived.addListener(
52 function(details) { 67 function(details) {
53 if (!this.authStarted_) 68 if (!this.authStarted_)
54 return; 69 return;
55 70
(...skipping 16 matching lines...) Expand all
72 else if (port.name == 'injected') 87 else if (port.name == 'injected')
73 this.setupForInjected_(port); 88 this.setupForInjected_(port);
74 else 89 else
75 console.error('Unexpected connection, port.name=' + port.name); 90 console.error('Unexpected connection, port.name=' + port.name);
76 }, 91 },
77 92
78 /** 93 /**
79 * Sets up the communication channel with the main script. 94 * Sets up the communication channel with the main script.
80 */ 95 */
81 setupForAuthMain_: function(port) { 96 setupForAuthMain_: function(port) {
82 this.channelMain_ = new Channel(); 97 var currentChannel = new Channel();
83 this.channelMain_.init(port); 98 currentChannel.init(port);
84 this.channelMain_.registerMessage( 99
100 // Registers for desktop related messages.
101 currentChannel.registerMessage(
102 'initDesktopFlow', this.onInitDesktopFlow_.bind(this));
103
104 // Registers for SAML related messages.
105 currentChannel.registerMessage(
85 'setGaiaUrl', this.onSetGaiaUrl_.bind(this)); 106 'setGaiaUrl', this.onSetGaiaUrl_.bind(this));
86 this.channelMain_.registerMessage( 107 currentChannel.registerMessage(
87 'resetAuth', this.onResetAuth_.bind(this)); 108 'resetAuth', this.onResetAuth_.bind(this));
88 this.channelMain_.registerMessage( 109 currentChannel.registerMessage(
89 'startAuth', this.onAuthStarted_.bind(this)); 110 'startAuth', this.onAuthStarted_.bind(this));
90 this.channelMain_.registerMessage( 111 currentChannel.registerMessage(
91 'getScrapedPasswords', 112 'getScrapedPasswords',
92 this.onGetScrapedPasswords_.bind(this)); 113 this.onGetScrapedPasswords_.bind(this));
114
115 currentChannel.send({
116 'name': 'channelConnected'
117 });
118 this.channelMain_[this.getTabIdFromPort_(port)] = currentChannel;
93 }, 119 },
94 120
95 /** 121 /**
96 * Sets up the communication channel with the injected script. 122 * Sets up the communication channel with the injected script.
97 */ 123 */
98 setupForInjected_: function(port) { 124 setupForInjected_: function(port) {
99 this.channelInjected_ = new Channel(); 125 var currentChannel = new Channel();
100 this.channelInjected_.init(port); 126 currentChannel.init(port);
101 this.channelInjected_.registerMessage( 127
102 'apiCall', this.onAPICall_.bind(this)); 128 var tabId = this.getTabIdFromPort_(port);
103 this.channelInjected_.registerMessage( 129 currentChannel.registerMessage(
130 'apiCall', this.onAPICall_.bind(this, tabId));
131 currentChannel.registerMessage(
104 'updatePassword', this.onUpdatePassword_.bind(this)); 132 'updatePassword', this.onUpdatePassword_.bind(this));
105 this.channelInjected_.registerMessage( 133 currentChannel.registerMessage(
106 'pageLoaded', this.onPageLoaded_.bind(this)); 134 'pageLoaded', this.onPageLoaded_.bind(this, tabId));
135
136 this.channelInjected_[this.getTabIdFromPort_(port)] = currentChannel;
137 },
138
139 getTabIdFromPort_: function(port) {
140 return port.sender.tab ? port.sender.tab.id : -1;
107 }, 141 },
108 142
109 /** 143 /**
144 * Handler for 'initDesktopFlow' signal sent from the main script.
145 * Only called in desktop mode.
146 */
147 onInitDesktopFlow_: function(msg) {
148 this.gaiaUrl_ = msg.gaiaUrl;
149 this.continueUrl_ = msg.continueUrl;
150 this.isConstrainedWindow_ = msg.isConstrainedWindow;
151
152 var urls = [];
153 var filter = {urls: urls, types: ['sub_frame']};
154 var optExtraInfoSpec = [];
155 if (msg.isConstrainedWindow) {
156 urls.push('<all_urls>');
157 optExtraInfoSpec.push('responseHeaders');
158 } else {
159 urls.push(this.continueUrl_ + '*');
160 }
161
162 chrome.webRequest.onCompleted.addListener(
163 this.onRequestCompletedInDesktopMode_.bind(this),
164 filter, optExtraInfoSpec);
165 chrome.webRequest.onHeadersReceived.addListener(
166 this.onHeadersReceivedInDesktopMode_.bind(this),
167 {urls: [this.gaiaUrl_ + '*'], types: ['sub_frame']},
168 ['responseHeaders']);
169 },
170
171 /**
172 * Event listener for webRequest.onCompleted in desktop mode.
173 */
174 onRequestCompletedInDesktopMode_: function(details) {
175 var msg = null;
176 if (details.url.lastIndexOf(this.continueUrl_, 0) == 0) {
177 var skipForNow = false;
178 if (details.url.indexOf('ntp=1') >= 0) {
179 skipForNow = true;
180 }
181 msg = {
182 'name': 'completeLogin',
183 'email': this.email_,
184 'sessionIndex': this.sessionIndex_,
185 'skipForNow': skipForNow
186 };
187 } else if (this.isConstrainedWindow_) {
188 var headers = details.responseHeaders;
189 for (var i = 0; headers && i < headers.length; ++i) {
190 if (headers[i].name.toLowerCase() == 'google-accounts-embedded') {
191 return;
192 }
193 }
194 msg = {
195 'name': 'switchToFullTab',
196 'url': details.url
197 };
198 }
199
200 if (msg != null)
201 this.channelMain_[details.tabId].send(msg);
202 },
203
204 /**
205 * Event listener for webRequest.onHeadersReceived in desktop mode.
206 */
207 onHeadersReceivedInDesktopMode_: function(details) {
208 var headers = details.responseHeaders;
209 for (var i = 0; headers && i < headers.length; ++i) {
210 if (headers[i].name.toLowerCase() == 'google-accounts-signin') {
211 var headerValues = headers[i].value.toLowerCase().split(',');
212 var signinDetails = {};
213 headerValues.forEach(function(e) {
214 var pair = e.split('=');
215 signinDetails[pair[0].trim()] = pair[1].trim();
216 });
217 this.email_ = signinDetails['email'].slice(1, -1); // Remove "" around.
218 this.sessionIndex_ = signinDetails['sessionindex'];
219 return;
220 }
221 }
222 },
223
224 /**
110 * Handler for 'setGaiaUrl' signal sent from the main script. 225 * Handler for 'setGaiaUrl' signal sent from the main script.
111 */ 226 */
112 onSetGaiaUrl_: function(msg) { 227 onSetGaiaUrl_: function(msg) {
113 this.gaiaUrl_ = msg.gaiaUrl; 228 this.gaiaUrl_ = msg.gaiaUrl;
114 229
115 // Set request header to let Gaia know that saml support is on. 230 // Set request header to let Gaia know that saml support is on.
116 chrome.webRequest.onBeforeSendHeaders.addListener( 231 chrome.webRequest.onBeforeSendHeaders.addListener(
117 function(details) { 232 function(details) {
118 details.requestHeaders.push({ 233 details.requestHeaders.push({
119 name: 'X-Cros-Auth-Ext-Support', 234 name: 'X-Cros-Auth-Ext-Support',
(...skipping 26 matching lines...) Expand all
146 * @return {Array.<string>} The array with de-duped scraped passwords. 261 * @return {Array.<string>} The array with de-duped scraped passwords.
147 */ 262 */
148 onGetScrapedPasswords_: function() { 263 onGetScrapedPasswords_: function() {
149 var passwords = {}; 264 var passwords = {};
150 for (var property in this.passwordStore_) { 265 for (var property in this.passwordStore_) {
151 passwords[this.passwordStore_[property]] = true; 266 passwords[this.passwordStore_[property]] = true;
152 } 267 }
153 return Object.keys(passwords); 268 return Object.keys(passwords);
154 }, 269 },
155 270
156 onAPICall_: function(msg) { 271 onAPICall_: function(tabId, msg) {
157 this.channelMain_.send(msg); 272 if (tabId in this.channelMain_) {
273 this.channelMain_[tabId].send(msg);
274 }
158 }, 275 },
159 276
160 onUpdatePassword_: function(msg) { 277 onUpdatePassword_: function(msg) {
161 if (!this.authStarted_) 278 if (!this.authStarted_)
162 return; 279 return;
163 280
164 this.passwordStore_[msg.id] = msg.password; 281 this.passwordStore_[msg.id] = msg.password;
165 }, 282 },
166 283
167 onPageLoaded_: function(msg) { 284 onPageLoaded_: function(tabId, msg) {
168 this.channelMain_.send({name: 'onAuthPageLoaded', url: msg.url}); 285 if (tabId in this.channelMain_) {
286 this.channelMain_[tabId].send({name: 'onAuthPageLoaded', url: msg.url});
287 }
169 } 288 }
170 }; 289 };
171 290
172 var backgroundBridge = new BackgroundBridge(); 291 var backgroundBridge = new BackgroundBridge();
173 backgroundBridge.run(); 292 backgroundBridge.run();
OLDNEW
« no previous file with comments | « chrome/browser/resources/component_extension_resources.grd ('k') | chrome/browser/resources/gaia_auth/desktop_injected.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698