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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 #include "chrome/browser/signin/signin_manager_factory.h" | 26 #include "chrome/browser/signin/signin_manager_factory.h" |
27 #include "chrome/browser/signin/signin_names_io_thread.h" | 27 #include "chrome/browser/signin/signin_names_io_thread.h" |
28 #include "chrome/browser/sync/profile_sync_service.h" | 28 #include "chrome/browser/sync/profile_sync_service.h" |
29 #include "chrome/browser/sync/profile_sync_service_factory.h" | 29 #include "chrome/browser/sync/profile_sync_service_factory.h" |
30 #include "chrome/browser/tab_contents/tab_util.h" | 30 #include "chrome/browser/tab_contents/tab_util.h" |
31 #include "chrome/browser/ui/browser_finder.h" | 31 #include "chrome/browser/ui/browser_finder.h" |
32 #include "chrome/browser/ui/browser_window.h" | 32 #include "chrome/browser/ui/browser_window.h" |
33 #include "chrome/browser/ui/sync/one_click_signin_histogram.h" | 33 #include "chrome/browser/ui/sync/one_click_signin_histogram.h" |
34 #include "chrome/browser/ui/sync/one_click_signin_sync_starter.h" | 34 #include "chrome/browser/ui/sync/one_click_signin_sync_starter.h" |
35 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 35 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
| 36 #include "chrome/common/chrome_notification_types.h" |
36 #include "chrome/common/chrome_switches.h" | 37 #include "chrome/common/chrome_switches.h" |
37 #include "chrome/common/chrome_version_info.h" | 38 #include "chrome/common/chrome_version_info.h" |
38 #include "chrome/common/net/url_util.h" | 39 #include "chrome/common/net/url_util.h" |
39 #include "chrome/common/pref_names.h" | 40 #include "chrome/common/pref_names.h" |
40 #include "chrome/common/url_constants.h" | 41 #include "chrome/common/url_constants.h" |
41 #include "content/public/browser/browser_thread.h" | 42 #include "content/public/browser/browser_thread.h" |
42 #include "content/public/browser/page_navigator.h" | 43 #include "content/public/browser/page_navigator.h" |
43 #include "content/public/browser/web_contents.h" | 44 #include "content/public/browser/web_contents.h" |
44 #include "content/public/browser/web_contents_view.h" | 45 #include "content/public/browser/web_contents_view.h" |
45 #include "content/public/common/frame_navigate_params.h" | 46 #include "content/public/common/frame_navigate_params.h" |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 | 368 |
368 // static | 369 // static |
369 void OneClickSigninHelper::AssociateWithRequestForTesting( | 370 void OneClickSigninHelper::AssociateWithRequestForTesting( |
370 base::SupportsUserData* request, | 371 base::SupportsUserData* request, |
371 const std::string& email) { | 372 const std::string& email) { |
372 OneClickSigninRequestUserData::AssociateWithRequest(request, email); | 373 OneClickSigninRequestUserData::AssociateWithRequest(request, email); |
373 } | 374 } |
374 | 375 |
375 // static | 376 // static |
376 bool OneClickSigninHelper::CanOffer(content::WebContents* web_contents, | 377 bool OneClickSigninHelper::CanOffer(content::WebContents* web_contents, |
| 378 CanOfferFor can_offer_for, |
377 const std::string& email, | 379 const std::string& email, |
378 bool check_connected) { | 380 int* error_message_id) { |
379 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 381 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
380 | 382 |
| 383 if (error_message_id) |
| 384 *error_message_id = 0; |
| 385 |
381 if (!web_contents) | 386 if (!web_contents) |
382 return false; | 387 return false; |
383 | 388 |
384 if (web_contents->GetBrowserContext()->IsOffTheRecord()) | 389 if (web_contents->GetBrowserContext()->IsOffTheRecord()) |
385 return false; | 390 return false; |
386 | 391 |
387 if (!ProfileSyncService::IsSyncEnabled()) | 392 if (!ProfileSyncService::IsSyncEnabled()) |
388 return false; | 393 return false; |
389 | 394 |
390 Profile* profile = | 395 Profile* profile = |
391 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 396 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
392 if (!profile) | 397 if (!profile) |
393 return false; | 398 return false; |
394 | 399 |
395 if (!profile->GetPrefs()->GetBoolean(prefs::kReverseAutologinEnabled)) | 400 if (can_offer_for == CAN_OFFER_FOR_INTERSTITAL_ONLY && |
| 401 !profile->GetPrefs()->GetBoolean(prefs::kReverseAutologinEnabled)) |
396 return false; | 402 return false; |
397 | 403 |
398 if (!SigninManager::AreSigninCookiesAllowed(profile)) | 404 if (!SigninManager::AreSigninCookiesAllowed(profile)) |
399 return false; | 405 return false; |
400 | 406 |
401 if (check_connected) { | 407 if (!email.empty()) { |
402 SigninManager* manager = | 408 SigninManager* manager = |
403 SigninManagerFactory::GetForProfile(profile); | 409 SigninManagerFactory::GetForProfile(profile); |
404 if (!manager) | 410 if (!manager) |
405 return false; | 411 return false; |
406 | 412 |
407 if (!manager->GetAuthenticatedUsername().empty()) | 413 if (!manager->GetAuthenticatedUsername().empty()) { |
| 414 if (error_message_id) |
| 415 *error_message_id = IDS_SYNC_SETUP_ERROR; |
408 return false; | 416 return false; |
| 417 } |
409 | 418 |
410 // Make sure this username is not prohibited by policy. | 419 // Make sure this username is not prohibited by policy. |
411 if (!manager->IsAllowedUsername(email)) | 420 if (!manager->IsAllowedUsername(email)) { |
| 421 if (error_message_id) |
| 422 *error_message_id = IDS_SYNC_LOGIN_NAME_PROHIBITED; |
412 return false; | 423 return false; |
| 424 } |
413 | 425 |
414 // If some profile, not just the current one, is already connected to this | 426 // If some profile, not just the current one, is already connected to this |
415 // account, don't show the infobar. | 427 // account, don't show the infobar. |
416 if (g_browser_process) { | 428 if (g_browser_process) { |
417 ProfileManager* manager = g_browser_process->profile_manager(); | 429 ProfileManager* manager = g_browser_process->profile_manager(); |
418 if (manager) { | 430 if (manager) { |
419 string16 email16 = UTF8ToUTF16(email); | 431 string16 email16 = UTF8ToUTF16(email); |
420 ProfileInfoCache& cache = manager->GetProfileInfoCache(); | 432 ProfileInfoCache& cache = manager->GetProfileInfoCache(); |
421 | 433 |
422 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) { | 434 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) { |
423 if (email16 == cache.GetUserNameOfProfileAtIndex(i)) | 435 if (email16 == cache.GetUserNameOfProfileAtIndex(i)) { |
| 436 if (error_message_id) |
| 437 *error_message_id = IDS_SYNC_USER_NAME_IN_USE_ERROR; |
424 return false; | 438 return false; |
| 439 } |
425 } | 440 } |
426 } | 441 } |
427 } | 442 } |
428 | 443 |
429 // If email was already rejected by this profile for one-click sign-in. | 444 // If email was already rejected by this profile for one-click sign-in. |
430 if (!email.empty()) { | 445 if (can_offer_for == CAN_OFFER_FOR_INTERSTITAL_ONLY) { |
431 const ListValue* rejected_emails = profile->GetPrefs()->GetList( | 446 const ListValue* rejected_emails = profile->GetPrefs()->GetList( |
432 prefs::kReverseAutologinRejectedEmailList); | 447 prefs::kReverseAutologinRejectedEmailList); |
433 if (!rejected_emails->empty()) { | 448 if (!rejected_emails->empty()) { |
434 const scoped_ptr<Value> email_value(new base::StringValue(email)); | 449 const scoped_ptr<Value> email_value(new base::StringValue(email)); |
435 base::ListValue::const_iterator iter = rejected_emails->Find( | 450 base::ListValue::const_iterator iter = rejected_emails->Find( |
436 *email_value); | 451 *email_value); |
437 if (iter != rejected_emails->end()) | 452 if (iter != rejected_emails->end()) |
438 return false; | 453 return false; |
439 } | 454 } |
440 } | 455 } |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
658 SyncPromoUI::Source source, | 673 SyncPromoUI::Source source, |
659 int child_id, | 674 int child_id, |
660 int route_id) { | 675 int route_id) { |
661 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 676 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
662 | 677 |
663 content::WebContents* web_contents = tab_util::GetWebContentsByID(child_id, | 678 content::WebContents* web_contents = tab_util::GetWebContentsByID(child_id, |
664 route_id); | 679 route_id); |
665 | 680 |
666 // TODO(mathp): The appearance of this infobar should be tested using a | 681 // TODO(mathp): The appearance of this infobar should be tested using a |
667 // browser_test. | 682 // browser_test. |
668 if (!web_contents || !CanOffer(web_contents, email, !email.empty())) { | 683 OneClickSigninHelper* helper = |
| 684 OneClickSigninHelper::FromWebContents(web_contents); |
| 685 int error_message_id = 0; |
| 686 |
| 687 CanOfferFor can_offer_for = |
| 688 (auto_accept != AUTO_ACCEPT_EXPLICIT && |
| 689 helper->auto_accept_ != AUTO_ACCEPT_EXPLICIT) ? |
| 690 CAN_OFFER_FOR_INTERSTITAL_ONLY : CAN_OFFER_FOR_ALL; |
| 691 |
| 692 if (!web_contents || !CanOffer(web_contents, can_offer_for, email, |
| 693 &error_message_id)) { |
669 VLOG(1) << "OneClickSigninHelper::ShowInfoBarUIThread: not offering"; | 694 VLOG(1) << "OneClickSigninHelper::ShowInfoBarUIThread: not offering"; |
| 695 if (helper && helper->error_message_.empty() && error_message_id != 0) |
| 696 helper->error_message_ = l10n_util::GetStringUTF8(error_message_id); |
| 697 |
670 return; | 698 return; |
671 } | 699 } |
672 | 700 |
673 // Save the email in the one-click signin manager. The manager may | 701 // Save the email in the one-click signin manager. The manager may |
674 // not exist if the contents is incognito or if the profile is already | 702 // not exist if the contents is incognito or if the profile is already |
675 // connected to a Google account. | 703 // connected to a Google account. |
676 OneClickSigninHelper* helper = | |
677 OneClickSigninHelper::FromWebContents(web_contents); | |
678 if (helper) { | 704 if (helper) { |
679 if (!session_index.empty()) | 705 if (!session_index.empty()) |
680 helper->session_index_ = session_index; | 706 helper->session_index_ = session_index; |
681 | 707 |
682 if (!email.empty()) | 708 if (!email.empty()) |
683 helper->email_ = email; | 709 helper->email_ = email; |
684 | 710 |
685 helper->auto_accept_ = auto_accept; | 711 if (auto_accept != NO_AUTO_ACCEPT) { |
686 helper->source_ = source; | 712 helper->auto_accept_ = auto_accept; |
| 713 helper->source_ = source; |
| 714 } |
687 } | 715 } |
688 } | 716 } |
689 | 717 |
| 718 void OneClickSigninHelper::RedirectToNTP() { |
| 719 // Redirect to NTP with sign in bubble visible. |
| 720 content::WebContents* contents = web_contents(); |
| 721 Profile* profile = |
| 722 Profile::FromBrowserContext(contents->GetBrowserContext()); |
| 723 PrefService* pref_service = profile->GetPrefs(); |
| 724 pref_service->SetBoolean(prefs::kSyncPromoShowNTPBubble, true); |
| 725 pref_service->SetString(prefs::kSyncPromoErrorMessage, error_message_); |
| 726 |
| 727 contents->GetController().LoadURL(GURL(chrome::kChromeUINewTabURL), |
| 728 content::Referrer(), |
| 729 content::PAGE_TRANSITION_AUTO_TOPLEVEL, |
| 730 std::string()); |
| 731 |
| 732 error_message_.clear(); |
| 733 signin_tracker_.reset(); |
| 734 } |
| 735 |
| 736 void OneClickSigninHelper::CleanTransientState() { |
| 737 email_.clear(); |
| 738 password_.clear(); |
| 739 auto_accept_ = NO_AUTO_ACCEPT; |
| 740 source_ = SyncPromoUI::SOURCE_UNKNOWN; |
| 741 } |
| 742 |
690 void OneClickSigninHelper::DidNavigateAnyFrame( | 743 void OneClickSigninHelper::DidNavigateAnyFrame( |
691 const content::LoadCommittedDetails& details, | 744 const content::LoadCommittedDetails& details, |
692 const content::FrameNavigateParams& params) { | 745 const content::FrameNavigateParams& params) { |
693 // We only need to scrape the password for Gaia logins. | 746 // We only need to scrape the password for Gaia logins. |
694 const content::PasswordForm& form = params.password_form; | 747 const content::PasswordForm& form = params.password_form; |
695 if (form.origin.is_valid() && | 748 if (form.origin.is_valid() && |
696 gaia::IsGaiaSignonRealm(GURL(form.signon_realm))) { | 749 gaia::IsGaiaSignonRealm(GURL(form.signon_realm))) { |
697 VLOG(1) << "OneClickSigninHelper::DidNavigateAnyFrame: got password"; | 750 VLOG(1) << "OneClickSigninHelper::DidNavigateAnyFrame: got password"; |
698 password_ = UTF16ToUTF8(params.password_form.password_value); | 751 password_ = UTF16ToUTF8(params.password_form.password_value); |
699 } | 752 } |
700 } | 753 } |
701 | 754 |
702 void OneClickSigninHelper::DidStopLoading( | 755 void OneClickSigninHelper::DidStopLoading( |
703 content::RenderViewHost* render_view_host) { | 756 content::RenderViewHost* render_view_host) { |
| 757 // If the user left the sign in process, clear all members. |
| 758 // TODO(rogerta): might need to allow some youtube URLs. |
| 759 content::WebContents* contents = web_contents(); |
| 760 if (!gaia::IsGaiaSignonRealm(contents->GetURL().GetOrigin())) { |
| 761 CleanTransientState(); |
| 762 return; |
| 763 } |
| 764 |
| 765 if (!error_message_.empty()) { |
| 766 RedirectToNTP(); |
| 767 return; |
| 768 } |
| 769 |
704 if (email_.empty() || password_.empty()) | 770 if (email_.empty() || password_.empty()) |
705 return; | 771 return; |
706 | 772 |
707 content::WebContents* contents = web_contents(); | |
708 Browser* browser = chrome::FindBrowserWithWebContents(contents); | 773 Browser* browser = chrome::FindBrowserWithWebContents(contents); |
709 InfoBarTabHelper* infobar_tab_helper = | 774 InfoBarTabHelper* infobar_tab_helper = |
710 InfoBarTabHelper::FromWebContents(contents); | 775 InfoBarTabHelper::FromWebContents(contents); |
711 | 776 |
712 switch (auto_accept_) { | 777 switch (auto_accept_) { |
713 case AUTO_ACCEPT: | 778 case AUTO_ACCEPT: |
714 browser->window()->ShowOneClickSigninBubble( | 779 browser->window()->ShowOneClickSigninBubble( |
715 base::Bind(&StartSync, browser, auto_accept_, session_index_, | 780 base::Bind(&StartSync, browser, auto_accept_, session_index_, |
716 email_, password_)); | 781 email_, password_)); |
717 break; | 782 break; |
(...skipping 25 matching lines...) Expand all Loading... |
743 // If this explicit sign in is not from settings page, show the NTP after | 808 // If this explicit sign in is not from settings page, show the NTP after |
744 // sign in completes. In the case of the settings page, it will get closed | 809 // sign in completes. In the case of the settings page, it will get closed |
745 // by SyncSetupHandler. | 810 // by SyncSetupHandler. |
746 if (auto_accept_ == AUTO_ACCEPT_EXPLICIT && | 811 if (auto_accept_ == AUTO_ACCEPT_EXPLICIT && |
747 source_ != SyncPromoUI::SOURCE_SETTINGS) { | 812 source_ != SyncPromoUI::SOURCE_SETTINGS) { |
748 Profile* profile = | 813 Profile* profile = |
749 Profile::FromBrowserContext(contents->GetBrowserContext()); | 814 Profile::FromBrowserContext(contents->GetBrowserContext()); |
750 signin_tracker_.reset(new SigninTracker(profile, this)); | 815 signin_tracker_.reset(new SigninTracker(profile, this)); |
751 } | 816 } |
752 | 817 |
753 email_.clear(); | 818 CleanTransientState(); |
754 password_.clear(); | |
755 auto_accept_ = NO_AUTO_ACCEPT; | |
756 source_ = SyncPromoUI::SOURCE_UNKNOWN; | |
757 } | 819 } |
758 | 820 |
759 void OneClickSigninHelper::GaiaCredentialsValid() { | 821 void OneClickSigninHelper::GaiaCredentialsValid() { |
760 // Redirect to NTP with sign in bubble visible. | |
761 content::WebContents* contents = web_contents(); | |
762 Profile* profile = | |
763 Profile::FromBrowserContext(contents->GetBrowserContext()); | |
764 PrefService* pref_service = profile->GetPrefs(); | |
765 pref_service->SetBoolean(prefs::kSyncPromoShowNTPBubble, true); | |
766 | |
767 contents->GetController().LoadURL(GURL(chrome::kChromeUINewTabURL), | |
768 content::Referrer(), | |
769 content::PAGE_TRANSITION_AUTO_TOPLEVEL, | |
770 std::string()); | |
771 } | 822 } |
772 | 823 |
773 void OneClickSigninHelper::SigninFailed(const GoogleServiceAuthError& error) { | 824 void OneClickSigninHelper::SigninFailed(const GoogleServiceAuthError& error) { |
774 signin_tracker_.reset(); | 825 if (error_message_.empty() && !error.error_message().empty()) |
| 826 error_message_ = error.error_message(); |
| 827 |
| 828 if (error_message_.empty()) { |
| 829 switch (error.state()) { |
| 830 case GoogleServiceAuthError::NONE: |
| 831 error_message_.clear(); |
| 832 break; |
| 833 case GoogleServiceAuthError::SERVICE_UNAVAILABLE: |
| 834 error_message_ = l10n_util::GetStringUTF8(IDS_SYNC_UNRECOVERABLE_ERROR); |
| 835 break; |
| 836 default: |
| 837 error_message_ = l10n_util::GetStringUTF8(IDS_SYNC_ERROR_SIGNING_IN); |
| 838 break; |
| 839 } |
| 840 } |
| 841 |
| 842 RedirectToNTP(); |
775 } | 843 } |
776 | 844 |
777 void OneClickSigninHelper::SigninSuccess() { | 845 void OneClickSigninHelper::SigninSuccess() { |
778 signin_tracker_.reset(); | 846 RedirectToNTP(); |
779 } | 847 } |
OLD | NEW |