OLD | NEW |
---|---|
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 Loading... | |
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_: null, |
(...skipping 29 matching lines...) Expand all Loading... | |
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 this.channelMain_ = new Channel(); |
83 this.channelMain_.init(port); | 98 this.channelMain_.init(port); |
99 | |
100 // Registers for desktop related messages. | |
101 this.channelMain_.registerMessage( | |
102 'initDesktopFlow', this.onInitDesktopFlow_.bind(this)); | |
103 | |
104 // Registers for SAML related messages. | |
84 this.channelMain_.registerMessage( | 105 this.channelMain_.registerMessage( |
85 'setGaiaUrl', this.onSetGaiaUrl_.bind(this)); | 106 'setGaiaUrl', this.onSetGaiaUrl_.bind(this)); |
86 this.channelMain_.registerMessage( | 107 this.channelMain_.registerMessage( |
87 'resetAuth', this.onResetAuth_.bind(this)); | 108 'resetAuth', this.onResetAuth_.bind(this)); |
88 this.channelMain_.registerMessage( | 109 this.channelMain_.registerMessage( |
89 'startAuth', this.onAuthStarted_.bind(this)); | 110 'startAuth', this.onAuthStarted_.bind(this)); |
90 this.channelMain_.registerMessage( | 111 this.channelMain_.registerMessage( |
91 'getScrapedPasswords', | 112 'getScrapedPasswords', |
92 this.onGetScrapedPasswords_.bind(this)); | 113 this.onGetScrapedPasswords_.bind(this)); |
93 }, | 114 }, |
94 | 115 |
95 /** | 116 /** |
96 * Sets up the communication channel with the injected script. | 117 * Sets up the communication channel with the injected script. |
97 */ | 118 */ |
98 setupForInjected_: function(port) { | 119 setupForInjected_: function(port) { |
99 this.channelInjected_ = new Channel(); | 120 this.channelInjected_ = new Channel(); |
100 this.channelInjected_.init(port); | 121 this.channelInjected_.init(port); |
101 this.channelInjected_.registerMessage( | 122 this.channelInjected_.registerMessage( |
102 'apiCall', this.onAPICall_.bind(this)); | 123 'apiCall', this.onAPICall_.bind(this)); |
103 this.channelInjected_.registerMessage( | 124 this.channelInjected_.registerMessage( |
104 'updatePassword', this.onUpdatePassword_.bind(this)); | 125 'updatePassword', this.onUpdatePassword_.bind(this)); |
105 this.channelInjected_.registerMessage( | 126 this.channelInjected_.registerMessage( |
106 'pageLoaded', this.onPageLoaded_.bind(this)); | 127 'pageLoaded', this.onPageLoaded_.bind(this)); |
107 }, | 128 }, |
108 | 129 |
109 /** | 130 /** |
131 * Handler for 'initDesktopFlow' signal sent from the main script. | |
132 * Only called in desktop mode. | |
133 */ | |
134 onInitDesktopFlow_: function(msg) { | |
135 this.gaiaUrl_ = msg.gaiaUrl; | |
136 this.continueUrl_ = msg.continueUrl; | |
137 this.isConstrainedWindow_ = msg.isConstrainedWindow; | |
138 | |
139 var urls = []; | |
140 var filter = {urls: urls, types: ['sub_frame']}; | |
141 var optExtraInfoSpec = []; | |
142 if (msg.isConstrainedWindow) { | |
143 urls.push('<all_urls>'); | |
144 optExtraInfoSpec.push('responseHeaders'); | |
145 } else { | |
146 urls.push(this.continueUrl_ + '*'); | |
147 } | |
148 | |
149 chrome.webRequest.onCompleted.addListener( | |
150 this.onRequestCompletedInDesktopMode_.bind(this), | |
151 filter, optExtraInfoSpec); | |
152 chrome.webRequest.onHeadersReceived.addListener( | |
153 this.onHeadersReceivedInDesktopMode_.bind(this), | |
154 {urls: [this.gaiaUrl_ + '*'], types: ['sub_frame']}, | |
155 ['responseHeaders']); | |
156 }, | |
157 | |
158 /** | |
159 * Event listener for webRequest.onCompleted in desktop mode. | |
160 */ | |
161 onRequestCompletedInDesktopMode_: function(details) { | |
162 var msg; | |
163 if (details.url.lastIndexOf(this.continueUrl_, 0) == 0) { | |
164 var skipForNow = false; | |
165 if (details.url.indexOf('ntp=1') >= 0) { | |
166 skipForNow = true; | |
167 } | |
168 var msg = { | |
169 'name': 'completeLogin', | |
170 'email': this.email_, | |
171 'sessionIndex': this.sessionIndex_, | |
172 'skipForNow': skipForNow | |
173 }; | |
174 } else { | |
175 var headers = details.responseHeaders; | |
176 for (var i = 0; headers && i < headers.length; ++i) { | |
177 if (headers[i].name.toLowerCase() == 'google-accounts-embedded') { | |
178 return; | |
179 } | |
180 } | |
181 msg = { | |
182 'name': 'switchToFullTab', | |
183 'url': details.url | |
184 }; | |
185 } | |
186 | |
187 this.channelMain_.send(msg); | |
188 }, | |
189 | |
190 /** | |
191 * Event listener for webRequest.onHeadersReceived in desktop mode. | |
192 */ | |
193 onHeadersReceivedInDesktopMode_: function(details) { | |
194 var headers = details.responseHeaders; | |
195 for (var i = 0; headers && i < headers.length; ++i) { | |
196 if (headers[i].name.toLowerCase() == 'google-accounts-signin') { | |
197 var headerValues = headers[i].value.toLowerCase().split(','); | |
198 var signinDetails = {}; | |
199 headerValues.forEach(function(e) { | |
200 var pair = e.split('='); | |
201 signinDetails[pair[0].trim()] = pair[1].trim(); | |
202 }); | |
203 this.email_ = signinDetails['email'].slice(1, -1); // Remove "" around. | |
204 this.sessionIndex_ = signinDetails['sessionindex']; | |
205 return; | |
206 } | |
207 } | |
208 }, | |
209 | |
210 /** | |
110 * Handler for 'setGaiaUrl' signal sent from the main script. | 211 * Handler for 'setGaiaUrl' signal sent from the main script. |
111 */ | 212 */ |
112 onSetGaiaUrl_: function(msg) { | 213 onSetGaiaUrl_: function(msg) { |
113 this.gaiaUrl_ = msg.gaiaUrl; | 214 this.gaiaUrl_ = msg.gaiaUrl; |
114 | 215 |
115 // Set request header to let Gaia know that saml support is on. | 216 // Set request header to let Gaia know that saml support is on. |
116 chrome.webRequest.onBeforeSendHeaders.addListener( | 217 chrome.webRequest.onBeforeSendHeaders.addListener( |
117 function(details) { | 218 function(details) { |
118 details.requestHeaders.push({ | 219 details.requestHeaders.push({ |
119 name: 'X-Cros-Auth-Ext-Support', | 220 name: 'X-Cros-Auth-Ext-Support', |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
164 this.passwordStore_[msg.id] = msg.password; | 265 this.passwordStore_[msg.id] = msg.password; |
165 }, | 266 }, |
166 | 267 |
167 onPageLoaded_: function(msg) { | 268 onPageLoaded_: function(msg) { |
168 this.channelMain_.send({name: 'onAuthPageLoaded', url: msg.url}); | 269 this.channelMain_.send({name: 'onAuthPageLoaded', url: msg.url}); |
169 } | 270 } |
170 }; | 271 }; |
171 | 272 |
172 var backgroundBridge = new BackgroundBridge(); | 273 var backgroundBridge = new BackgroundBridge(); |
173 backgroundBridge.run(); | 274 backgroundBridge.run(); |
275 | |
nasko
2014/01/27 17:21:50
nit: no need for blank line.
guohui
2014/01/29 12:50:51
Done.
| |
OLD | NEW |