OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 #include "chrome/browser/chromeos/arc/arc_auth_service.h" | 5 #include "chrome/browser/chromeos/arc/arc_auth_service.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "chrome/browser/chromeos/arc/arc_auth_ui.h" | 9 #include "chrome/browser/chromeos/arc/arc_auth_ui.h" |
10 #include "chrome/browser/chromeos/profiles/profile_helper.h" | |
10 #include "chrome/browser/profiles/profile.h" | 11 #include "chrome/browser/profiles/profile.h" |
12 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" | |
13 #include "chrome/browser/signin/signin_manager_factory.h" | |
11 #include "chrome/common/pref_names.h" | 14 #include "chrome/common/pref_names.h" |
12 #include "components/arc/arc_bridge_service.h" | 15 #include "components/arc/arc_bridge_service.h" |
13 #include "components/pref_registry/pref_registry_syncable.h" | 16 #include "components/pref_registry/pref_registry_syncable.h" |
14 #include "components/prefs/pref_service.h" | 17 #include "components/prefs/pref_service.h" |
18 #include "components/signin/core/browser/profile_oauth2_token_service.h" | |
19 #include "components/signin/core/browser/signin_manager_base.h" | |
20 #include "content/public/browser/browser_thread.h" | |
21 #include "google_apis/gaia/gaia_constants.h" | |
22 #include "net/url_request/url_request_context.h" | |
15 | 23 |
16 namespace arc { | 24 namespace arc { |
17 | 25 |
18 namespace { | 26 namespace { |
19 | 27 |
20 // Weak pointer. This class is owned by ArcServiceManager. | 28 // Weak pointer. This class is owned by ArcServiceManager. |
21 ArcAuthService* arc_auth_service = nullptr; | 29 ArcAuthService* arc_auth_service = nullptr; |
22 | 30 |
31 const int kMaxRetryCnt = 2; | |
32 const int kRetryDelayMs = 500; | |
33 | |
34 const char kSID[] = "SID"; | |
35 const char kSSID[] = "SSID"; | |
36 const char kLSID[] = "LSID"; | |
37 const char kHSID[] = "HSID"; | |
38 | |
39 const char kArcSID[] = "ARC_SID"; | |
40 const char kArcSSID[] = "ARC_SSID"; | |
41 const char kArcLSID[] = "ARC_LSID"; | |
42 const char kArcHSID[] = "ARC_HSID"; | |
43 | |
44 bool CopyCookieAsync(const std::string& source_name, | |
45 const std::string& target_name, | |
46 const GURL& url, | |
47 const net::CookieList& cookie_list, | |
48 net::CookieStore* cookie_store) { | |
49 for (const auto& cookie : cookie_list) { | |
50 if (cookie.Name() != source_name) | |
51 continue; | |
52 base::Callback<void(bool success)> cb; | |
53 cookie_store->SetCookieWithDetailsAsync( | |
54 url, target_name, cookie.Value(), cookie.Domain(), cookie.Path(), | |
55 cookie.CreationDate(), cookie.ExpiryDate(), cookie.IsSecure(), | |
56 cookie.IsHttpOnly(), cookie.IsSameSite(), | |
57 false, // enforce_strict_secure | |
58 cookie.Priority(), cb); | |
59 return true; | |
60 } | |
61 | |
62 return false; | |
63 } | |
64 | |
23 // Skip creating UI in unit tests | 65 // Skip creating UI in unit tests |
24 bool disable_ui_for_testing = false; | 66 bool disable_ui_for_testing = false; |
25 | 67 |
26 const char kStateDisable[] = "DISABLE"; | 68 const char kStateDisable[] = "DISABLE"; |
27 const char kStateFetchingCode[] = "FETCHING_CODE"; | 69 const char kStateFetchingCode[] = "FETCHING_CODE"; |
28 const char kStateNoCode[] = "NO_CODE"; | 70 const char kStateNoCode[] = "NO_CODE"; |
29 const char kStateEnable[] = "ENABLE"; | 71 const char kStateEnable[] = "ENABLE"; |
72 | |
30 } // namespace | 73 } // namespace |
31 | 74 |
32 ArcAuthService::ArcAuthService(ArcBridgeService* bridge_service) | 75 ArcAuthService::ArcAuthService(ArcBridgeService* bridge_service) |
33 : ArcService(bridge_service), binding_(this) { | 76 : ArcService(bridge_service), binding_(this) { |
34 DCHECK(!arc_auth_service); | 77 DCHECK(!arc_auth_service); |
35 arc_auth_service = this; | 78 arc_auth_service = this; |
36 | 79 |
37 arc_bridge_service()->AddObserver(this); | 80 arc_bridge_service()->AddObserver(this); |
38 } | 81 } |
39 | 82 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 FOR_EACH_OBSERVER(Observer, observer_list_, OnOptInChanged(state_)); | 132 FOR_EACH_OBSERVER(Observer, observer_list_, OnOptInChanged(state_)); |
90 } | 133 } |
91 | 134 |
92 void ArcAuthService::OnPrimaryUserProfilePrepared(Profile* profile) { | 135 void ArcAuthService::OnPrimaryUserProfilePrepared(Profile* profile) { |
93 DCHECK(profile && profile != profile_); | 136 DCHECK(profile && profile != profile_); |
94 DCHECK(thread_checker_.CalledOnValidThread()); | 137 DCHECK(thread_checker_.CalledOnValidThread()); |
95 | 138 |
96 Shutdown(); | 139 Shutdown(); |
97 | 140 |
98 profile_ = profile; | 141 profile_ = profile; |
142 signin_profile_ = chromeos::ProfileHelper::Get()->GetSigninProfile(); | |
143 CHECK(signin_profile_); | |
99 | 144 |
100 pref_change_registrar_.Init(profile_->GetPrefs()); | 145 pref_change_registrar_.Init(profile_->GetPrefs()); |
101 pref_change_registrar_.Add( | 146 pref_change_registrar_.Add( |
102 prefs::kArcEnabled, base::Bind(&ArcAuthService::OnOptInPreferenceChanged, | 147 prefs::kArcEnabled, base::Bind(&ArcAuthService::OnOptInPreferenceChanged, |
103 base::Unretained(this))); | 148 base::Unretained(this))); |
149 | |
104 OnOptInPreferenceChanged(); | 150 OnOptInPreferenceChanged(); |
105 } | 151 } |
106 | 152 |
107 void ArcAuthService::Shutdown() { | 153 void ArcAuthService::Shutdown() { |
108 ShutdownBridgeAndCloseUI(); | 154 ShutdownBridgeAndCloseUI(); |
109 profile_ = nullptr; | 155 profile_ = nullptr; |
110 pref_change_registrar_.RemoveAll(); | 156 pref_change_registrar_.RemoveAll(); |
111 } | 157 } |
112 | 158 |
159 void ArcAuthService::OnMergeSessionSuccess(const std::string& data) { | |
160 DCHECK(thread_checker_.CalledOnValidThread()); | |
161 auth_ui_ = new ArcAuthUI(signin_profile_, this); | |
162 } | |
163 | |
164 void ArcAuthService::OnMergeSessionFailure( | |
165 const GoogleServiceAuthError& error) { | |
166 DCHECK(thread_checker_.CalledOnValidThread()); | |
167 OnAuthCodeFailed(); | |
168 } | |
169 | |
170 void ArcAuthService::OnUbertokenSuccess(const std::string& token) { | |
171 DCHECK(thread_checker_.CalledOnValidThread()); | |
172 merger_fetcher_.reset( | |
173 new GaiaAuthFetcher(this, GaiaConstants::kChromeOSSource, | |
174 signin_profile_->GetRequestContext())); | |
175 merger_fetcher_->StartMergeSession(token, std::string()); | |
176 } | |
177 | |
178 void ArcAuthService::OnUbertokenFailure(const GoogleServiceAuthError& error) { | |
179 DCHECK(thread_checker_.CalledOnValidThread()); | |
180 OnAuthCodeFailed(); | |
181 } | |
182 | |
113 void ArcAuthService::OnOptInPreferenceChanged() { | 183 void ArcAuthService::OnOptInPreferenceChanged() { |
114 DCHECK(thread_checker_.CalledOnValidThread()); | 184 DCHECK(thread_checker_.CalledOnValidThread()); |
115 DCHECK(profile_); | 185 DCHECK(profile_); |
116 | 186 |
117 if (profile_->GetPrefs()->GetBoolean(prefs::kArcEnabled)) { | 187 if (profile_->GetPrefs()->GetBoolean(prefs::kArcEnabled)) { |
118 switch (state_) { | 188 switch (state_) { |
119 case State::DISABLE: | 189 case State::DISABLE: |
120 FetchAuthCode(); | 190 FetchAuthCode(); |
121 break; | 191 break; |
122 case State::NO_CODE: // Retry | 192 case State::NO_CODE: // Retry |
123 FetchAuthCode(); | 193 FetchAuthCode(); |
124 break; | 194 break; |
125 default: | 195 default: |
126 break; | 196 break; |
127 } | 197 } |
128 } else { | 198 } else { |
129 ShutdownBridgeAndCloseUI(); | 199 ShutdownBridgeAndCloseUI(); |
130 } | 200 } |
131 } | 201 } |
132 | 202 |
133 void ArcAuthService::ShutdownBridgeAndCloseUI() { | 203 void ArcAuthService::ShutdownBridgeAndCloseUI() { |
134 CloseUI(); | 204 CloseUI(); |
135 auth_fetcher_.reset(); | 205 auth_fetcher_.reset(); |
206 ubertoken_fethcher_.reset(); | |
207 merger_fetcher_.reset(); | |
136 ArcBridgeService::Get()->Shutdown(); | 208 ArcBridgeService::Get()->Shutdown(); |
209 CleanupSigninProfile(); | |
137 SetState(State::DISABLE); | 210 SetState(State::DISABLE); |
138 } | 211 } |
139 | 212 |
140 void ArcAuthService::AddObserver(Observer* observer) { | 213 void ArcAuthService::AddObserver(Observer* observer) { |
141 DCHECK(thread_checker_.CalledOnValidThread()); | 214 DCHECK(thread_checker_.CalledOnValidThread()); |
142 observer_list_.AddObserver(observer); | 215 observer_list_.AddObserver(observer); |
143 } | 216 } |
144 | 217 |
145 void ArcAuthService::RemoveObserver(Observer* observer) { | 218 void ArcAuthService::RemoveObserver(Observer* observer) { |
146 DCHECK(thread_checker_.CalledOnValidThread()); | 219 DCHECK(thread_checker_.CalledOnValidThread()); |
147 observer_list_.RemoveObserver(observer); | 220 observer_list_.RemoveObserver(observer); |
148 } | 221 } |
149 | 222 |
150 void ArcAuthService::CloseUI() { | 223 void ArcAuthService::CloseUI() { |
151 if (auth_ui_) { | 224 if (auth_ui_) { |
152 auth_ui_->Close(); | 225 auth_ui_->Close(); |
153 DCHECK(!auth_ui_); | 226 DCHECK(!auth_ui_); |
154 } | 227 } |
155 } | 228 } |
156 | 229 |
157 void ArcAuthService::SetAuthCodeAndStartArc(const std::string& auth_code) { | 230 void ArcAuthService::SetAuthCodeAndStartArc(const std::string& auth_code) { |
158 DCHECK(thread_checker_.CalledOnValidThread()); | 231 DCHECK(thread_checker_.CalledOnValidThread()); |
159 DCHECK(!auth_code.empty()); | 232 DCHECK(!auth_code.empty()); |
160 DCHECK_NE(state_, State::ENABLE); | 233 ShutdownBridgeAndCloseUI(); |
161 | 234 |
162 ShutdownBridgeAndCloseUI(); | 235 if (state_ != State::FETCHING_CODE) |
236 return; | |
163 | 237 |
164 auth_code_ = auth_code; | 238 auth_code_ = auth_code; |
165 ArcBridgeService::Get()->HandleStartup(); | 239 ArcBridgeService::Get()->HandleStartup(); |
166 | 240 |
167 SetState(State::ENABLE); | 241 SetState(State::ENABLE); |
168 } | 242 } |
169 | 243 |
244 void ArcAuthService::CleanupSigninProfile() { | |
245 DCHECK(thread_checker_.CalledOnValidThread()); | |
246 if (signin_profile_dirty_) { | |
247 chromeos::ProfileHelper::Get()->ClearSigninProfile(base::Closure()); | |
248 signin_profile_dirty_ = false; | |
249 } | |
250 } | |
251 | |
252 void ArcAuthService::StartFetcherOnUIThread() { | |
253 DCHECK(thread_checker_.CalledOnValidThread()); | |
254 if (state_ != State::FETCHING_CODE) | |
255 return; | |
256 | |
257 auth_fetcher_.reset( | |
258 new ArcAuthFetcher(signin_profile_->GetRequestContext(), this)); | |
259 } | |
260 | |
261 void ArcAuthService::CopyFromArcCookiesOnIOThread( | |
262 net::URLRequestContextGetter* context_getter, | |
263 const net::CookieList& cookie_list) { | |
264 GURL url = ArcAuthFetcher::CreateURL(); | |
265 net::CookieStore* cookie_store = | |
266 context_getter->GetURLRequestContext()->cookie_store(); | |
267 if (!CopyCookieAsync(kArcSID, kSID, url, cookie_list, cookie_store) || | |
268 !CopyCookieAsync(kArcSSID, kSSID, url, cookie_list, cookie_store) || | |
269 !CopyCookieAsync(kArcHSID, kHSID, url, cookie_list, cookie_store) || | |
270 !CopyCookieAsync(kArcLSID, kLSID, url, cookie_list, cookie_store)) { | |
271 VLOG(2) << "No ARC cookies were found, proceed to UI."; | |
272 content::BrowserThread::PostTask( | |
273 content::BrowserThread::UI, FROM_HERE, | |
274 base::Bind(&ArcAuthService::ShowUI, base::Unretained(this))); | |
275 return; | |
276 } | |
277 | |
278 content::BrowserThread::PostTask( | |
279 content::BrowserThread::UI, FROM_HERE, | |
280 base::Bind(&ArcAuthService::StartFetcherOnUIThread, | |
281 base::Unretained(this))); | |
282 } | |
283 | |
284 void ArcAuthService::CopyToArcCookiesOnIOThread( | |
285 const std::string& auth_code, | |
286 net::URLRequestContextGetter* context_getter, | |
287 const net::CookieList& cookie_list) { | |
288 const GURL url = ArcAuthFetcher::CreateURL(); | |
289 net::CookieStore* cookie_store = | |
290 context_getter->GetURLRequestContext()->cookie_store(); | |
291 | |
292 if (!CopyCookieAsync(kSID, kArcSID, url, cookie_list, cookie_store) || | |
293 !CopyCookieAsync(kSSID, kArcSSID, url, cookie_list, cookie_store) || | |
294 !CopyCookieAsync(kHSID, kArcHSID, url, cookie_list, cookie_store) || | |
295 !CopyCookieAsync(kLSID, kArcLSID, url, cookie_list, cookie_store)) { | |
296 VLOG(2) << "No required cookies were found."; | |
297 return; | |
298 } | |
299 | |
300 content::BrowserThread::PostTask( | |
301 content::BrowserThread::UI, FROM_HERE, | |
302 base::Bind(&ArcAuthService::SetAuthCodeAndStartArc, | |
303 base::Unretained(this), auth_code)); | |
304 } | |
305 | |
306 void ArcAuthService::StartCopyFromArcCookiesOnIOThread( | |
307 net::URLRequestContextGetter* context_getter_from, | |
308 net::URLRequestContextGetter* context_getter_to) { | |
309 context_getter_from->GetURLRequestContext() | |
310 ->cookie_store() | |
311 ->GetAllCookiesForURLAsync( | |
312 ArcAuthFetcher::CreateURL(), | |
313 base::Bind(&ArcAuthService::CopyFromArcCookiesOnIOThread, | |
314 base::Unretained(this), context_getter_to)); | |
315 } | |
316 | |
170 void ArcAuthService::FetchAuthCode() { | 317 void ArcAuthService::FetchAuthCode() { |
171 DCHECK(thread_checker_.CalledOnValidThread()); | 318 DCHECK(thread_checker_.CalledOnValidThread()); |
172 DCHECK(state_ == State::DISABLE || state_ == State::NO_CODE); | 319 DCHECK(state_ == State::DISABLE || state_ == State::NO_CODE); |
173 | 320 |
174 CloseUI(); | 321 CloseUI(); |
175 auth_code_.clear(); | 322 auth_code_.clear(); |
176 | 323 |
177 SetState(State::FETCHING_CODE); | 324 SetState(State::FETCHING_CODE); |
178 | 325 |
179 auth_fetcher_.reset(new ArcAuthFetcher(profile_->GetRequestContext(), this)); | 326 retry_cnt_ = 0; |
327 CopyCookiesAndStartFetching(); | |
328 } | |
329 | |
330 void ArcAuthService::CopyCookiesAndStartFetching() { | |
331 signin_profile_dirty_ = true; | |
332 // Copy cookies from user profile to signin profile. | |
333 net::URLRequestContextGetter* context_getter_from = | |
334 profile_->GetRequestContext(); | |
335 net::URLRequestContextGetter* context_getter_to = | |
336 signin_profile_->GetRequestContext(); | |
337 content::BrowserThread::PostTask( | |
338 content::BrowserThread::IO, FROM_HERE, | |
339 base::Bind(&ArcAuthService::StartCopyFromArcCookiesOnIOThread, | |
340 base::Unretained(this), context_getter_from, | |
341 context_getter_to)); | |
180 } | 342 } |
181 | 343 |
182 void ArcAuthService::OnAuthCodeFetched(const std::string& auth_code) { | 344 void ArcAuthService::OnAuthCodeFetched(const std::string& auth_code) { |
183 DCHECK_EQ(state_, State::FETCHING_CODE); | 345 DCHECK_EQ(state_, State::FETCHING_CODE); |
184 SetAuthCodeAndStartArc(auth_code); | 346 SetAuthCodeAndStartArc(auth_code); |
185 } | 347 } |
186 | 348 |
349 void ArcAuthService::ShowUI() { | |
350 DCHECK(thread_checker_.CalledOnValidThread()); | |
351 | |
352 // Get auth token to continue. | |
353 OAuth2TokenService::ScopeSet scopes; | |
354 scopes.insert(GaiaConstants::kOAuth1LoginScope); | |
xiyuan
2016/02/09 22:39:35
not used.
| |
355 ProfileOAuth2TokenService* token_service = | |
356 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); | |
357 | |
358 SigninManagerBase* signin_manager = | |
359 SigninManagerFactory::GetForProfile(profile_); | |
360 CHECK(signin_manager); | |
361 const std::string& account_id = signin_manager->GetAuthenticatedAccountId(); | |
362 | |
363 signin_profile_dirty_ = true; | |
364 ubertoken_fethcher_.reset( | |
365 new UbertokenFetcher(token_service, this, GaiaConstants::kChromeOSSource, | |
366 signin_profile_->GetRequestContext())); | |
367 ubertoken_fethcher_->StartFetchingToken(account_id); | |
368 } | |
369 | |
187 void ArcAuthService::OnAuthCodeNeedUI() { | 370 void ArcAuthService::OnAuthCodeNeedUI() { |
371 DCHECK(thread_checker_.CalledOnValidThread()); | |
188 CloseUI(); | 372 CloseUI(); |
189 if (!disable_ui_for_testing) | 373 if (disable_ui_for_testing) |
190 auth_ui_ = new ArcAuthUI(profile_, this); | 374 return; |
375 | |
376 if (retry_cnt_ >= kMaxRetryCnt) { | |
377 ShowUI(); | |
378 return; | |
379 } | |
380 | |
381 ++retry_cnt_; | |
382 content::BrowserThread::PostDelayedTask( | |
383 content::BrowserThread::UI, FROM_HERE, | |
384 base::Bind(&ArcAuthService::CopyCookiesAndStartFetching, | |
385 base::Unretained(this)), | |
386 base::TimeDelta::FromMilliseconds(kRetryDelayMs)); | |
191 } | 387 } |
192 | 388 |
193 void ArcAuthService::OnAuthCodeFailed() { | 389 void ArcAuthService::OnAuthCodeFailed() { |
194 DCHECK_EQ(state_, State::FETCHING_CODE); | 390 DCHECK_EQ(state_, State::FETCHING_CODE); |
195 CloseUI(); | 391 CloseUI(); |
196 | 392 |
197 SetState(State::NO_CODE); | 393 SetState(State::NO_CODE); |
198 } | 394 } |
199 | 395 |
396 void ArcAuthService::StartCopyToArcCookiesOnIOThread( | |
397 const std::string& auth_code, | |
398 net::URLRequestContextGetter* context_getter_from, | |
399 net::URLRequestContextGetter* context_getter_to) { | |
400 context_getter_from->GetURLRequestContext() | |
401 ->cookie_store() | |
402 ->GetAllCookiesForURLAsync( | |
403 ArcAuthFetcher::CreateURL(), | |
404 base::Bind(&ArcAuthService::CopyToArcCookiesOnIOThread, | |
405 base::Unretained(this), auth_code, context_getter_to)); | |
406 } | |
407 | |
408 void ArcAuthService::OnAuthCodeFetchedFromUI(const std::string& auth_code) { | |
409 net::URLRequestContextGetter* context_getter_to = | |
410 profile_->GetRequestContext(); | |
411 net::URLRequestContextGetter* context_getter_from = | |
412 signin_profile_->GetRequestContext(); | |
413 content::BrowserThread::PostTask( | |
414 content::BrowserThread::IO, FROM_HERE, | |
415 base::Bind(&ArcAuthService::StartCopyToArcCookiesOnIOThread, | |
416 base::Unretained(this), auth_code, context_getter_from, | |
417 context_getter_to)); | |
418 } | |
419 | |
200 void ArcAuthService::OnAuthUIClosed() { | 420 void ArcAuthService::OnAuthUIClosed() { |
201 DCHECK(auth_ui_); | 421 DCHECK(auth_ui_); |
202 auth_ui_ = nullptr; | 422 auth_ui_ = nullptr; |
423 CleanupSigninProfile(); | |
203 } | 424 } |
204 | 425 |
205 std::ostream& operator<<(std::ostream& os, const ArcAuthService::State& state) { | 426 std::ostream& operator<<(std::ostream& os, const ArcAuthService::State& state) { |
206 switch (state) { | 427 switch (state) { |
207 case ArcAuthService::State::DISABLE: | 428 case ArcAuthService::State::DISABLE: |
208 return os << kStateDisable; | 429 return os << kStateDisable; |
209 case ArcAuthService::State::FETCHING_CODE: | 430 case ArcAuthService::State::FETCHING_CODE: |
210 return os << kStateFetchingCode; | 431 return os << kStateFetchingCode; |
211 case ArcAuthService::State::NO_CODE: | 432 case ArcAuthService::State::NO_CODE: |
212 return os << kStateNoCode; | 433 return os << kStateNoCode; |
213 case ArcAuthService::State::ENABLE: | 434 case ArcAuthService::State::ENABLE: |
214 return os << kStateEnable; | 435 return os << kStateEnable; |
215 default: | 436 default: |
216 NOTREACHED(); | 437 NOTREACHED(); |
217 return os; | 438 return os; |
218 } | 439 } |
219 } | 440 } |
220 | 441 |
221 } // namespace arc | 442 } // namespace arc |
OLD | NEW |