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

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: Don't check title1.html ids 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 = this.getTabIdFromPort_(port);
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 = null;
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 msg = {
180 'name': 'completeLogin',
181 'email': this.email_,
182 'sessionIndex': this.sessionIndex_,
183 'skipForNow': skipForNow
184 };
185 } else if (this.isConstrainedWindow_) {
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 if (msg != null)
199 this.channelMain_[details.tabId].send(msg);
200 },
201
202 /**
203 * Event listener for webRequest.onHeadersReceived in desktop mode.
204 */
205 onHeadersReceivedInDesktopMode_: function(details) {
206 var headers = details.responseHeaders;
207 for (var i = 0; headers && i < headers.length; ++i) {
208 if (headers[i].name.toLowerCase() == 'google-accounts-signin') {
209 var headerValues = headers[i].value.toLowerCase().split(',');
210 var signinDetails = {};
211 headerValues.forEach(function(e) {
212 var pair = e.split('=');
213 signinDetails[pair[0].trim()] = pair[1].trim();
214 });
215 this.email_ = signinDetails['email'].slice(1, -1); // Remove "" around.
216 this.sessionIndex_ = signinDetails['sessionindex'];
217 return;
218 }
219 }
220 },
221
222 /**
110 * Handler for 'setGaiaUrl' signal sent from the main script. 223 * Handler for 'setGaiaUrl' signal sent from the main script.
111 */ 224 */
112 onSetGaiaUrl_: function(msg) { 225 onSetGaiaUrl_: function(msg) {
113 this.gaiaUrl_ = msg.gaiaUrl; 226 this.gaiaUrl_ = msg.gaiaUrl;
114 227
115 // Set request header to let Gaia know that saml support is on. 228 // Set request header to let Gaia know that saml support is on.
116 chrome.webRequest.onBeforeSendHeaders.addListener( 229 chrome.webRequest.onBeforeSendHeaders.addListener(
117 function(details) { 230 function(details) {
118 details.requestHeaders.push({ 231 details.requestHeaders.push({
119 name: 'X-Cros-Auth-Ext-Support', 232 name: 'X-Cros-Auth-Ext-Support',
(...skipping 26 matching lines...) Expand all
146 * @return {Array.<string>} The array with de-duped scraped passwords. 259 * @return {Array.<string>} The array with de-duped scraped passwords.
147 */ 260 */
148 onGetScrapedPasswords_: function() { 261 onGetScrapedPasswords_: function() {
149 var passwords = {}; 262 var passwords = {};
150 for (var property in this.passwordStore_) { 263 for (var property in this.passwordStore_) {
151 passwords[this.passwordStore_[property]] = true; 264 passwords[this.passwordStore_[property]] = true;
152 } 265 }
153 return Object.keys(passwords); 266 return Object.keys(passwords);
154 }, 267 },
155 268
156 onAPICall_: function(msg) { 269 onAPICall_: function(tabId, msg) {
157 this.channelMain_.send(msg); 270 if (tabId in this.channelMain_) {
271 this.channelMain_[tabId].send(msg);
272 }
158 }, 273 },
159 274
160 onUpdatePassword_: function(msg) { 275 onUpdatePassword_: function(msg) {
161 if (!this.authStarted_) 276 if (!this.authStarted_)
162 return; 277 return;
163 278
164 this.passwordStore_[msg.id] = msg.password; 279 this.passwordStore_[msg.id] = msg.password;
165 }, 280 },
166 281
167 onPageLoaded_: function(msg) { 282 onPageLoaded_: function(tabId, msg) {
168 this.channelMain_.send({name: 'onAuthPageLoaded', url: msg.url}); 283 if (tabId in this.channelMain_) {
284 this.channelMain_[tabId].send({name: 'onAuthPageLoaded', url: msg.url});
285 }
169 } 286 }
170 }; 287 };
171 288
172 var backgroundBridge = new BackgroundBridge(); 289 var backgroundBridge = new BackgroundBridge();
173 backgroundBridge.run(); 290 backgroundBridge.run();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698