OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/ui/sync/one_click_signin_helper.h" | 5 #include "chrome/browser/ui/sync/one_click_signin_helper.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <functional> | 8 #include <functional> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
116 break; | 116 break; |
117 default: | 117 default: |
118 NOTREACHED() << "Invalid auto_accept: " << auto_accept; | 118 NOTREACHED() << "Invalid auto_accept: " << auto_accept; |
119 break; | 119 break; |
120 } | 120 } |
121 | 121 |
122 UMA_HISTOGRAM_ENUMERATION("AutoLogin.Reverse", action, | 122 UMA_HISTOGRAM_ENUMERATION("AutoLogin.Reverse", action, |
123 one_click_signin::HISTOGRAM_MAX); | 123 one_click_signin::HISTOGRAM_MAX); |
124 } | 124 } |
125 | 125 |
126 void ClearPendingEmailOnIOThread(content::ResourceContext* context) { | |
127 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); | |
128 DCHECK(io_data); | |
129 if (io_data) | |
tim (not reviewing)
2013/01/23 02:07:52
Is there a reason you're handling this this way?
Roger Tawa OOO till Jul 10th
2013/01/25 20:14:10
Done.
| |
130 io_data->set_reverse_autologin_pending_email(""); | |
tim (not reviewing)
2013/01/23 02:07:52
nit - prefer std::string() to "", as it is more ex
Roger Tawa OOO till Jul 10th
2013/01/25 20:14:10
Done.
Roger Tawa OOO till Jul 10th
2013/01/25 20:14:10
Done.
| |
131 } | |
132 | |
126 // Determines the source of the sign in and the continue URL. Its either one | 133 // Determines the source of the sign in and the continue URL. Its either one |
127 // of the known sign in access point (first run, NTP, menu, settings) or its | 134 // of the known sign in access point (first run, NTP, menu, settings) or its |
128 // an implicit sign in via another Google property. In the former case, | 135 // an implicit sign in via another Google property. In the former case, |
129 // "service" is also checked to make sure its "chromiumsync". | 136 // "service" is also checked to make sure its "chromiumsync". |
130 SyncPromoUI::Source GetSigninSource(const GURL& url, GURL* continue_url) { | 137 SyncPromoUI::Source GetSigninSource(const GURL& url, GURL* continue_url) { |
131 std::string value; | 138 std::string value; |
132 chrome_common_net::GetValueForKeyInQuery(url, "service", &value); | 139 chrome_common_net::GetValueForKeyInQuery(url, "service", &value); |
133 bool possibly_an_explicit_signin = value == "chromiumsync"; | 140 bool possibly_an_explicit_signin = value == "chromiumsync"; |
134 | 141 |
135 // Find the final continue URL for this sign in. In some cases, Gaia can | 142 // Find the final continue URL for this sign in. In some cases, Gaia can |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
174 } | 181 } |
175 | 182 |
176 GURL origin = url.GetOrigin(); | 183 GURL origin = url.GetOrigin(); |
177 if (origin == GURL("https://accounts.youtube.com") || | 184 if (origin == GURL("https://accounts.youtube.com") || |
178 origin == GURL("https://accounts.blogger.com")) | 185 origin == GURL("https://accounts.blogger.com")) |
179 return true; | 186 return true; |
180 | 187 |
181 return false; | 188 return false; |
182 } | 189 } |
183 | 190 |
184 // This class is associated as user data with a given URLRequest object, in | |
185 // order to pass information from one response to another during the process | |
186 // of signing the user into their Gaia account. This class is only meant | |
187 // to be used from the IO thread. | |
188 class OneClickSigninRequestUserData : public base::SupportsUserData::Data { | |
189 public: | |
190 const std::string& email() const { return email_; } | |
191 | |
192 // Associates signin information with the request. Overwrites existing | |
193 // information if any. | |
194 static void AssociateWithRequest(base::SupportsUserData* request, | |
195 const std::string& email); | |
196 | |
197 // Gets the one-click sign in information associated with the request. | |
198 static OneClickSigninRequestUserData* FromRequest( | |
199 base::SupportsUserData* request); | |
200 | |
201 private: | |
202 // Key used when setting this object on the request. | |
203 static const void* const kUserDataKey; | |
204 | |
205 explicit OneClickSigninRequestUserData(const std::string& email) | |
206 : email_(email) { | |
207 } | |
208 | |
209 std::string email_; | |
210 | |
211 DISALLOW_COPY_AND_ASSIGN(OneClickSigninRequestUserData); | |
212 }; | |
213 | |
214 // static | |
215 void OneClickSigninRequestUserData::AssociateWithRequest( | |
216 base::SupportsUserData* request, | |
217 const std::string& email) { | |
218 request->SetUserData(kUserDataKey, new OneClickSigninRequestUserData(email)); | |
219 } | |
220 | |
221 // static | |
222 OneClickSigninRequestUserData* OneClickSigninRequestUserData::FromRequest( | |
223 base::SupportsUserData* request) { | |
224 return static_cast<OneClickSigninRequestUserData*>( | |
225 request->GetUserData(kUserDataKey)); | |
226 } | |
227 | |
228 const void* const OneClickSigninRequestUserData::kUserDataKey = | |
229 static_cast<const void* const>( | |
230 &OneClickSigninRequestUserData::kUserDataKey); | |
231 | |
232 } // namespace | 191 } // namespace |
233 | 192 |
234 // The infobar asking the user if they want to use one-click sign in. | 193 // The infobar asking the user if they want to use one-click sign in. |
235 // TODO(rogerta): once we move to a web-based sign in flow, we can get rid | 194 // TODO(rogerta): once we move to a web-based sign in flow, we can get rid |
236 // of this infobar. | 195 // of this infobar. |
237 class OneClickInfoBarDelegateImpl : public OneClickSigninInfoBarDelegate { | 196 class OneClickInfoBarDelegateImpl : public OneClickSigninInfoBarDelegate { |
238 public: | 197 public: |
239 // Creates a one click signin delegate and adds it to |infobar_service|. | 198 // Creates a one click signin delegate and adds it to |infobar_service|. |
240 static void Create(InfoBarService* infobar_service, | 199 static void Create(InfoBarService* infobar_service, |
241 const std::string& session_index, | 200 const std::string& session_index, |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
402 OneClickSigninHelper::OneClickSigninHelper(content::WebContents* web_contents) | 361 OneClickSigninHelper::OneClickSigninHelper(content::WebContents* web_contents) |
403 : content::WebContentsObserver(web_contents), | 362 : content::WebContentsObserver(web_contents), |
404 auto_accept_(AUTO_ACCEPT_NONE), | 363 auto_accept_(AUTO_ACCEPT_NONE), |
405 source_(SyncPromoUI::SOURCE_UNKNOWN) { | 364 source_(SyncPromoUI::SOURCE_UNKNOWN) { |
406 } | 365 } |
407 | 366 |
408 OneClickSigninHelper::~OneClickSigninHelper() { | 367 OneClickSigninHelper::~OneClickSigninHelper() { |
409 } | 368 } |
410 | 369 |
411 // static | 370 // static |
412 void OneClickSigninHelper::AssociateWithRequestForTesting( | |
413 base::SupportsUserData* request, | |
414 const std::string& email) { | |
415 OneClickSigninRequestUserData::AssociateWithRequest(request, email); | |
416 } | |
417 | |
418 // static | |
419 bool OneClickSigninHelper::CanOffer(content::WebContents* web_contents, | 371 bool OneClickSigninHelper::CanOffer(content::WebContents* web_contents, |
420 CanOfferFor can_offer_for, | 372 CanOfferFor can_offer_for, |
421 const std::string& email, | 373 const std::string& email, |
422 int* error_message_id) { | 374 int* error_message_id) { |
423 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 375 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
424 VLOG(1) << "OneClickSigninHelper::CanOffer"; | 376 VLOG(1) << "OneClickSigninHelper::CanOffer"; |
425 | 377 |
426 if (error_message_id) | 378 if (error_message_id) |
427 *error_message_id = 0; | 379 *error_message_id = 0; |
428 | 380 |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
557 | 509 |
558 if (!SigninManager::AreSigninCookiesAllowed(io_data->GetCookieSettings())) | 510 if (!SigninManager::AreSigninCookiesAllowed(io_data->GetCookieSettings())) |
559 return DONT_OFFER; | 511 return DONT_OFFER; |
560 | 512 |
561 // The checks below depend on chrome already knowing what account the user | 513 // The checks below depend on chrome already knowing what account the user |
562 // signed in with. This happens only after receiving the response containing | 514 // signed in with. This happens only after receiving the response containing |
563 // the Google-Accounts-SignIn header. Until then, if there is even a chance | 515 // the Google-Accounts-SignIn header. Until then, if there is even a chance |
564 // that we want to connect the profile, chrome needs to tell Gaia that | 516 // that we want to connect the profile, chrome needs to tell Gaia that |
565 // it should offer the interstitial. Therefore missing one click data on | 517 // it should offer the interstitial. Therefore missing one click data on |
566 // the request means can offer is true. | 518 // the request means can offer is true. |
567 OneClickSigninRequestUserData* one_click_data = | 519 const std::string& pending_email = io_data->reverse_autologin_pending_email(); |
568 OneClickSigninRequestUserData::FromRequest(request); | 520 if (!pending_email.empty()) { |
569 if (one_click_data) { | 521 if (!SigninManager::IsAllowedUsername(pending_email, |
570 if (!SigninManager::IsAllowedUsername(one_click_data->email(), | |
571 io_data->google_services_username_pattern()->GetValue())) { | 522 io_data->google_services_username_pattern()->GetValue())) { |
572 return DONT_OFFER; | 523 return DONT_OFFER; |
573 } | 524 } |
574 | 525 |
575 std::vector<std::string> rejected_emails = | 526 std::vector<std::string> rejected_emails = |
576 io_data->one_click_signin_rejected_email_list()->GetValue(); | 527 io_data->one_click_signin_rejected_email_list()->GetValue(); |
577 if (std::count_if(rejected_emails.begin(), rejected_emails.end(), | 528 if (std::count_if(rejected_emails.begin(), rejected_emails.end(), |
578 std::bind2nd(std::equal_to<std::string>(), | 529 std::bind2nd(std::equal_to<std::string>(), |
579 one_click_data->email())) > 0) { | 530 pending_email)) > 0) { |
580 return DONT_OFFER; | 531 return DONT_OFFER; |
581 } | 532 } |
582 | 533 |
583 if (io_data->signin_names()->GetEmails().count( | 534 if (io_data->signin_names()->GetEmails().count( |
584 UTF8ToUTF16(one_click_data->email())) > 0) { | 535 UTF8ToUTF16(pending_email)) > 0) { |
585 return DONT_OFFER; | 536 return DONT_OFFER; |
586 } | 537 } |
587 } | 538 } |
588 | 539 |
589 return CAN_OFFER; | 540 return CAN_OFFER; |
590 } | 541 } |
591 | 542 |
592 // static | 543 // static |
593 void OneClickSigninHelper::InitializeFieldTrial() { | 544 void OneClickSigninHelper::InitializeFieldTrial() { |
594 scoped_refptr<base::FieldTrial> trial( | 545 scoped_refptr<base::FieldTrial> trial( |
595 base::FieldTrialList::FactoryGetFieldTrial("OneClickSignIn", 100, | 546 base::FieldTrialList::FactoryGetFieldTrial("OneClickSignIn", 100, |
596 "Standard", 2013, 9, 1, NULL)); | 547 "Standard", 2013, 9, 1, NULL)); |
597 | 548 |
598 // For dev and beta, we'll give half the people the new experience. For | 549 // For dev and beta, we'll give half the people the new experience. For |
599 // stable, only 1%. These numbers are overridable on the server. | 550 // stable, only 1%. These numbers are overridable on the server. |
600 const bool kIsStableChannel = | 551 const bool kIsStableChannel = |
601 chrome::VersionInfo::GetChannel() == chrome::VersionInfo::CHANNEL_STABLE; | 552 chrome::VersionInfo::GetChannel() == chrome::VersionInfo::CHANNEL_STABLE; |
602 const int kBlueOnWhiteGroup = trial->AppendGroup("BlueOnWhite", | 553 const int kBlueOnWhiteGroup = trial->AppendGroup("BlueOnWhite", |
603 kIsStableChannel ? 1 : 50); | 554 kIsStableChannel ? 1 : 50); |
604 use_blue_on_white = trial->group() == kBlueOnWhiteGroup; | 555 use_blue_on_white = trial->group() == kBlueOnWhiteGroup; |
605 } | 556 } |
606 | 557 |
607 // static | 558 // static |
608 void OneClickSigninHelper::ShowInfoBarIfPossible(net::URLRequest* request, | 559 void OneClickSigninHelper::ShowInfoBarIfPossible(net::URLRequest* request, |
560 ProfileIOData* io_data, | |
609 int child_id, | 561 int child_id, |
610 int route_id) { | 562 int route_id) { |
611 std::string google_chrome_signin_value; | 563 std::string google_chrome_signin_value; |
612 std::string google_accounts_signin_value; | 564 std::string google_accounts_signin_value; |
613 request->GetResponseHeaderByName("Google-Chrome-SignIn", | 565 request->GetResponseHeaderByName("Google-Chrome-SignIn", |
614 &google_chrome_signin_value); | 566 &google_chrome_signin_value); |
615 request->GetResponseHeaderByName("Google-Accounts-SignIn", | 567 request->GetResponseHeaderByName("Google-Accounts-SignIn", |
616 &google_accounts_signin_value); | 568 &google_accounts_signin_value); |
617 | 569 |
618 if (!google_accounts_signin_value.empty() || | 570 if (!google_accounts_signin_value.empty() || |
(...skipping 25 matching lines...) Expand all Loading... | |
644 TrimString(value, "\"", &email); | 596 TrimString(value, "\"", &email); |
645 } else if (key == "sessionindex") { | 597 } else if (key == "sessionindex") { |
646 session_index = value; | 598 session_index = value; |
647 } | 599 } |
648 } | 600 } |
649 | 601 |
650 // Later in the chain of this request, we'll need to check the email address | 602 // Later in the chain of this request, we'll need to check the email address |
651 // in the IO thread (see CanOfferOnIOThread). So save the email address as | 603 // in the IO thread (see CanOfferOnIOThread). So save the email address as |
652 // user data on the request (only for web-based flow). | 604 // user data on the request (only for web-based flow). |
653 if (SyncPromoUI::UseWebBasedSigninFlow() && !email.empty()) | 605 if (SyncPromoUI::UseWebBasedSigninFlow() && !email.empty()) |
654 OneClickSigninRequestUserData::AssociateWithRequest(request, email); | 606 io_data->set_reverse_autologin_pending_email(email); |
655 | 607 |
656 if (!email.empty() || !session_index.empty()) { | 608 if (!email.empty() || !session_index.empty()) { |
657 VLOG(1) << "OneClickSigninHelper::ShowInfoBarIfPossible:" | 609 VLOG(1) << "OneClickSigninHelper::ShowInfoBarIfPossible:" |
658 << " email=" << email | 610 << " email=" << email |
659 << " sessionindex=" << session_index; | 611 << " sessionindex=" << session_index; |
660 } | 612 } |
661 | 613 |
662 // Parse Google-Chrome-SignIn. | 614 // Parse Google-Chrome-SignIn. |
663 AutoAccept auto_accept = AUTO_ACCEPT_NONE; | 615 AutoAccept auto_accept = AUTO_ACCEPT_NONE; |
664 SyncPromoUI::Source source = SyncPromoUI::SOURCE_UNKNOWN; | 616 SyncPromoUI::Source source = SyncPromoUI::SOURCE_UNKNOWN; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
723 | 675 |
724 // TODO(mathp): The appearance of this infobar should be tested using a | 676 // TODO(mathp): The appearance of this infobar should be tested using a |
725 // browser_test. | 677 // browser_test. |
726 OneClickSigninHelper* helper = | 678 OneClickSigninHelper* helper = |
727 OneClickSigninHelper::FromWebContents(web_contents); | 679 OneClickSigninHelper::FromWebContents(web_contents); |
728 if (!helper) | 680 if (!helper) |
729 return; | 681 return; |
730 | 682 |
731 int error_message_id = 0; | 683 int error_message_id = 0; |
732 | 684 |
733 CanOfferFor can_offer_for = | |
734 (auto_accept != AUTO_ACCEPT_EXPLICIT && | |
735 helper->auto_accept_ != AUTO_ACCEPT_EXPLICIT) ? | |
736 CAN_OFFER_FOR_INTERSTITAL_ONLY : CAN_OFFER_FOR_ALL; | |
737 | |
738 if (!web_contents || !CanOffer(web_contents, can_offer_for, email, | |
739 &error_message_id)) { | |
740 VLOG(1) << "OneClickSigninHelper::ShowInfoBarUIThread: not offering"; | |
741 if (helper && helper->error_message_.empty() && error_message_id != 0) | |
742 helper->error_message_ = l10n_util::GetStringUTF8(error_message_id); | |
743 | |
744 return; | |
745 } | |
746 | |
747 // Save the email in the one-click signin manager. The manager may | 685 // Save the email in the one-click signin manager. The manager may |
748 // not exist if the contents is incognito or if the profile is already | 686 // not exist if the contents is incognito or if the profile is already |
749 // connected to a Google account. | 687 // connected to a Google account. |
750 if (!session_index.empty()) | 688 if (!session_index.empty()) |
751 helper->session_index_ = session_index; | 689 helper->session_index_ = session_index; |
752 | 690 |
753 if (!email.empty()) | 691 if (!email.empty()) |
754 helper->email_ = email; | 692 helper->email_ = email; |
755 | 693 |
756 if (auto_accept != AUTO_ACCEPT_NONE) { | 694 if (auto_accept != AUTO_ACCEPT_NONE) { |
757 helper->auto_accept_ = auto_accept; | 695 helper->auto_accept_ = auto_accept; |
758 helper->source_ = source; | 696 helper->source_ = source; |
759 } | 697 } |
760 | 698 |
699 CanOfferFor can_offer_for = | |
700 (auto_accept != AUTO_ACCEPT_EXPLICIT && | |
701 helper->auto_accept_ != AUTO_ACCEPT_EXPLICIT) ? | |
702 CAN_OFFER_FOR_INTERSTITAL_ONLY : CAN_OFFER_FOR_ALL; | |
703 | |
704 if (!web_contents || !CanOffer(web_contents, can_offer_for, email, | |
705 &error_message_id)) { | |
706 VLOG(1) << "OneClickSigninHelper::ShowInfoBarUIThread: not offering"; | |
707 if (helper && helper->error_message_.empty() && error_message_id != 0) | |
708 helper->error_message_ = l10n_util::GetStringUTF8(error_message_id); | |
709 | |
710 return; | |
711 } | |
712 | |
761 if (continue_url.is_valid()) { | 713 if (continue_url.is_valid()) { |
762 // When Gaia finally redirects to the continue URL, Gaia will add some | 714 // When Gaia finally redirects to the continue URL, Gaia will add some |
763 // extra query parameters. So ignore the parameters when checking to see | 715 // extra query parameters. So ignore the parameters when checking to see |
764 // if the user has continued. | 716 // if the user has continued. |
765 GURL::Replacements replacements; | 717 GURL::Replacements replacements; |
766 replacements.ClearQuery(); | 718 replacements.ClearQuery(); |
767 helper->continue_url_ = continue_url.ReplaceComponents(replacements); | 719 helper->continue_url_ = continue_url.ReplaceComponents(replacements); |
768 } | 720 } |
769 } | 721 } |
770 | 722 |
(...skipping 17 matching lines...) Expand all Loading... | |
788 signin_tracker_.reset(); | 740 signin_tracker_.reset(); |
789 } | 741 } |
790 | 742 |
791 void OneClickSigninHelper::CleanTransientState() { | 743 void OneClickSigninHelper::CleanTransientState() { |
792 VLOG(1) << "OneClickSigninHelper::CleanTransientState"; | 744 VLOG(1) << "OneClickSigninHelper::CleanTransientState"; |
793 email_.clear(); | 745 email_.clear(); |
794 password_.clear(); | 746 password_.clear(); |
795 auto_accept_ = AUTO_ACCEPT_NONE; | 747 auto_accept_ = AUTO_ACCEPT_NONE; |
796 source_ = SyncPromoUI::SOURCE_UNKNOWN; | 748 source_ = SyncPromoUI::SOURCE_UNKNOWN; |
797 continue_url_ = GURL(); | 749 continue_url_ = GURL(); |
750 | |
751 // Post to IO thread to clear pending email. | |
752 Profile* profile = | |
753 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); | |
754 content::BrowserThread::PostTask( | |
755 content::BrowserThread::IO, FROM_HERE, | |
756 base::Bind(&ClearPendingEmailOnIOThread, | |
757 base::Unretained(profile->GetResourceContext()))); | |
798 } | 758 } |
799 | 759 |
800 void OneClickSigninHelper::DidNavigateAnyFrame( | 760 void OneClickSigninHelper::DidNavigateAnyFrame( |
801 const content::LoadCommittedDetails& details, | 761 const content::LoadCommittedDetails& details, |
802 const content::FrameNavigateParams& params) { | 762 const content::FrameNavigateParams& params) { |
803 // We only need to scrape the password for Gaia logins. | 763 // We only need to scrape the password for Gaia logins. |
804 const content::PasswordForm& form = params.password_form; | 764 const content::PasswordForm& form = params.password_form; |
805 if (form.origin.is_valid() && | 765 if (form.origin.is_valid() && |
806 gaia::IsGaiaSignonRealm(GURL(form.signon_realm))) { | 766 gaia::IsGaiaSignonRealm(GURL(form.signon_realm))) { |
807 VLOG(1) << "OneClickSigninHelper::DidNavigateAnyFrame: got password"; | 767 VLOG(1) << "OneClickSigninHelper::DidNavigateAnyFrame: got password"; |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
971 break; | 931 break; |
972 } | 932 } |
973 } | 933 } |
974 | 934 |
975 RedirectToNTP(); | 935 RedirectToNTP(); |
976 } | 936 } |
977 | 937 |
978 void OneClickSigninHelper::SigninSuccess() { | 938 void OneClickSigninHelper::SigninSuccess() { |
979 RedirectToNTP(); | 939 RedirectToNTP(); |
980 } | 940 } |
OLD | NEW |