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

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: 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 this.channelMain_[this.getTabIdFromPort_(port)] = currentChannel;
116
93 }, 117 },
94 118
95 /** 119 /**
96 * Sets up the communication channel with the injected script. 120 * Sets up the communication channel with the injected script.
97 */ 121 */
98 setupForInjected_: function(port) { 122 setupForInjected_: function(port) {
99 this.channelInjected_ = new Channel(); 123 var currentChannel = new Channel();
100 this.channelInjected_.init(port); 124 currentChannel.init(port);
101 this.channelInjected_.registerMessage( 125
102 'apiCall', this.onAPICall_.bind(this)); 126 var tabId = getTabIdFromPort_(port);
xiyuan 2014/02/07 17:52:15 Sorry, this was missed from previous review. getTa
Roger Tawa OOO till Jul 10th 2014/02/07 19:36:51 Done.
103 this.channelInjected_.registerMessage( 127 currentChannel.registerMessage(
128 'apiCall', this.onAPICall_.bind(this, tabId));
129 currentChannel.registerMessage(
104 'updatePassword', this.onUpdatePassword_.bind(this)); 130 'updatePassword', this.onUpdatePassword_.bind(this));
105 this.channelInjected_.registerMessage( 131 currentChannel.registerMessage(
106 'pageLoaded', this.onPageLoaded_.bind(this)); 132 'pageLoaded', this.onPageLoaded_.bind(this, tabId));
133
134 this.channelInjected_[this.getTabIdFromPort_(port)] = currentChannel;
135 },
136
137 getTabIdFromPort_: function(port) {
138 return port.sender.tab ? port.sender.tab.id : -1;
107 }, 139 },
108 140
109 /** 141 /**
142 * Handler for 'initDesktopFlow' signal sent from the main script.
143 * Only called in desktop mode.
144 */
145 onInitDesktopFlow_: function(msg) {
146 this.gaiaUrl_ = msg.gaiaUrl;
147 this.continueUrl_ = msg.continueUrl;
148 this.isConstrainedWindow_ = msg.isConstrainedWindow;
149
150 var urls = [];
151 var filter = {urls: urls, types: ['sub_frame']};
152 var optExtraInfoSpec = [];
153 if (msg.isConstrainedWindow) {
154 urls.push('<all_urls>');
155 optExtraInfoSpec.push('responseHeaders');
156 } else {
157 urls.push(this.continueUrl_ + '*');
158 }
159
160 chrome.webRequest.onCompleted.addListener(
161 this.onRequestCompletedInDesktopMode_.bind(this),
162 filter, optExtraInfoSpec);
163 chrome.webRequest.onHeadersReceived.addListener(
164 this.onHeadersReceivedInDesktopMode_.bind(this),
165 {urls: [this.gaiaUrl_ + '*'], types: ['sub_frame']},
166 ['responseHeaders']);
167 },
168
169 /**
170 * Event listener for webRequest.onCompleted in desktop mode.
171 */
172 onRequestCompletedInDesktopMode_: function(details) {
173 var msg;
174 if (details.url.lastIndexOf(this.continueUrl_, 0) == 0) {
175 var skipForNow = false;
176 if (details.url.indexOf('ntp=1') >= 0) {
177 skipForNow = true;
178 }
179 var msg = {
180 'name': 'completeLogin',
181 'email': this.email_,
182 'sessionIndex': this.sessionIndex_,
183 'skipForNow': skipForNow
184 };
185 } else {
186 var headers = details.responseHeaders;
187 for (var i = 0; headers && i < headers.length; ++i) {
188 if (headers[i].name.toLowerCase() == 'google-accounts-embedded') {
189 return;
190 }
191 }
192 msg = {
193 'name': 'switchToFullTab',
194 'url': details.url
195 };
196 }
197
198 this.channelMain_[details.tabId].send(msg);
199 },
200
201 /**
202 * Event listener for webRequest.onHeadersReceived in desktop mode.
203 */
204 onHeadersReceivedInDesktopMode_: function(details) {
205 var headers = details.responseHeaders;
206 for (var i = 0; headers && i < headers.length; ++i) {
207 if (headers[i].name.toLowerCase() == 'google-accounts-signin') {
208 var headerValues = headers[i].value.toLowerCase().split(',');
209 var signinDetails = {};
210 headerValues.forEach(function(e) {
211 var pair = e.split('=');
212 signinDetails[pair[0].trim()] = pair[1].trim();
213 });
214 this.email_ = signinDetails['email'].slice(1, -1); // Remove "" around.
215 this.sessionIndex_ = signinDetails['sessionindex'];
216 return;
217 }
218 }
219 },
220
221 /**
110 * Handler for 'setGaiaUrl' signal sent from the main script. 222 * Handler for 'setGaiaUrl' signal sent from the main script.
111 */ 223 */
112 onSetGaiaUrl_: function(msg) { 224 onSetGaiaUrl_: function(msg) {
113 this.gaiaUrl_ = msg.gaiaUrl; 225 this.gaiaUrl_ = msg.gaiaUrl;
114 226
115 // Set request header to let Gaia know that saml support is on. 227 // Set request header to let Gaia know that saml support is on.
116 chrome.webRequest.onBeforeSendHeaders.addListener( 228 chrome.webRequest.onBeforeSendHeaders.addListener(
117 function(details) { 229 function(details) {
118 details.requestHeaders.push({ 230 details.requestHeaders.push({
119 name: 'X-Cros-Auth-Ext-Support', 231 name: 'X-Cros-Auth-Ext-Support',
(...skipping 26 matching lines...) Expand all
146 * @return {Array.<string>} The array with de-duped scraped passwords. 258 * @return {Array.<string>} The array with de-duped scraped passwords.
147 */ 259 */
148 onGetScrapedPasswords_: function() { 260 onGetScrapedPasswords_: function() {
149 var passwords = {}; 261 var passwords = {};
150 for (var property in this.passwordStore_) { 262 for (var property in this.passwordStore_) {
151 passwords[this.passwordStore_[property]] = true; 263 passwords[this.passwordStore_[property]] = true;
152 } 264 }
153 return Object.keys(passwords); 265 return Object.keys(passwords);
154 }, 266 },
155 267
156 onAPICall_: function(msg) { 268 onAPICall_: function(tabId, msg) {
157 this.channelMain_.send(msg); 269 if (tabId in this.channelMain_) {
270 this.channelMain_[tabId].send(msg);
271 }
158 }, 272 },
159 273
160 onUpdatePassword_: function(msg) { 274 onUpdatePassword_: function(msg) {
161 if (!this.authStarted_) 275 if (!this.authStarted_)
162 return; 276 return;
163 277
164 this.passwordStore_[msg.id] = msg.password; 278 this.passwordStore_[msg.id] = msg.password;
165 }, 279 },
166 280
167 onPageLoaded_: function(msg) { 281 onPageLoaded_: function(tabId, msg) {
168 this.channelMain_.send({name: 'onAuthPageLoaded', url: msg.url}); 282 if (tabId in this.channelMain_) {
283 this.channelMain_[tabId].send({name: 'onAuthPageLoaded', url: msg.url});
284 }
169 } 285 }
170 }; 286 };
171 287
172 var backgroundBridge = new BackgroundBridge(); 288 var backgroundBridge = new BackgroundBridge();
173 backgroundBridge.run(); 289 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