diff options
author | rogerta@chromium.org <rogerta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-12 18:33:12 +0000 |
---|---|---|
committer | rogerta@chromium.org <rogerta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-12 18:33:12 +0000 |
commit | 0cf5d280b3c224a200c7a9d4f26dc2916184860b (patch) | |
tree | 64b1ab41c41ca7f6ba3a5e3dd35449a669fe2d20 | |
parent | 57274d514de1df72f23bc3adbdea9b073de5a678 (diff) | |
download | chromium_src-0cf5d280b3c224a200c7a9d4f26dc2916184860b.zip chromium_src-0cf5d280b3c224a200c7a9d4f26dc2916184860b.tar.gz chromium_src-0cf5d280b3c224a200c7a9d4f26dc2916184860b.tar.bz2 |
Add SAML support for chrome sign in.
BUG=222924
Review URL: https://chromiumcodereview.appspot.com/13069006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@193970 0039d316-1c4b-4281-b951-d872f2087c98
14 files changed, 101 insertions, 42 deletions
diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h index 1cf2de6..b975952 100644 --- a/chrome/browser/ui/browser_window.h +++ b/chrome/browser/ui/browser_window.h @@ -214,7 +214,8 @@ class BrowserWindow : public BaseWindow { #if defined(ENABLE_ONE_CLICK_SIGNIN) enum OneClickSigninBubbleType { ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE, - ONE_CLICK_SIGNIN_BUBBLE_TYPE_MODAL_DIALOG + ONE_CLICK_SIGNIN_BUBBLE_TYPE_MODAL_DIALOG, + ONE_CLICK_SIGNIN_BUBBLE_TYPE_SAML_MODAL_DIALOG }; // Callback type used with the ShowOneClickSigninBubble() method. If the @@ -223,9 +224,11 @@ class BrowserWindow : public BaseWindow { typedef base::Callback<void(OneClickSigninSyncStarter::StartSyncMode)> StartSyncCallback; - // Shows the one-click sign in bubble. + // Shows the one-click sign in bubble. |email| holds the full email address + // of the account that has signed in. virtual void ShowOneClickSigninBubble( OneClickSigninBubbleType type, + const string16& email, const StartSyncCallback& start_sync_callback) = 0; #endif diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.h b/chrome/browser/ui/cocoa/browser_window_cocoa.h index f877d0d..afae112 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.h +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.h @@ -99,6 +99,7 @@ class BrowserWindowCocoa : #if defined(ENABLE_ONE_CLICK_SIGNIN) virtual void ShowOneClickSigninBubble( OneClickSigninBubbleType type, + const string16& email, const StartSyncCallback& start_sync_callback) OVERRIDE; #endif virtual bool IsDownloadShelfVisible() const OVERRIDE; diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm index eac9183..a199f22 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm @@ -479,6 +479,7 @@ void BrowserWindowCocoa::ShowChromeToMobileBubble() { #if defined(ENABLE_ONE_CLICK_SIGNIN) void BrowserWindowCocoa::ShowOneClickSigninBubble( OneClickSigninBubbleType type, + const string16& email, const StartSyncCallback& start_sync_callback) { if (type == ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE) { scoped_nsobject<OneClickSigninBubbleController> bubble_controller( diff --git a/chrome/browser/ui/gtk/browser_window_gtk.cc b/chrome/browser/ui/gtk/browser_window_gtk.cc index 7ad63e8..29a2329 100644 --- a/chrome/browser/ui/gtk/browser_window_gtk.cc +++ b/chrome/browser/ui/gtk/browser_window_gtk.cc @@ -971,6 +971,7 @@ void BrowserWindowGtk::ShowChromeToMobileBubble() { #if defined(ENABLE_ONE_CLICK_SIGNIN) void BrowserWindowGtk::ShowOneClickSigninBubble( OneClickSigninBubbleType type, + const string16& email, const StartSyncCallback& start_sync_callback) { new OneClickSigninBubbleGtk(this, type, start_sync_callback); } diff --git a/chrome/browser/ui/gtk/browser_window_gtk.h b/chrome/browser/ui/gtk/browser_window_gtk.h index 61dcbb3..a8aac20 100644 --- a/chrome/browser/ui/gtk/browser_window_gtk.h +++ b/chrome/browser/ui/gtk/browser_window_gtk.h @@ -133,6 +133,7 @@ class BrowserWindowGtk #if defined(ENABLE_ONE_CLICK_SIGNIN) virtual void ShowOneClickSigninBubble( OneClickSigninBubbleType type, + const string16& email, const StartSyncCallback& start_sync_callback) OVERRIDE; #endif virtual bool IsDownloadShelfVisible() const OVERRIDE; diff --git a/chrome/browser/ui/sync/one_click_signin_helper.cc b/chrome/browser/ui/sync/one_click_signin_helper.cc index 62ba977..bce0995 100644 --- a/chrome/browser/ui/sync/one_click_signin_helper.cc +++ b/chrome/browser/ui/sync/one_click_signin_helper.cc @@ -79,6 +79,11 @@ DEFINE_WEB_CONTENTS_USER_DATA_KEY(OneClickSigninHelper); namespace { +// Maximum number of navigations away from the set of valid Gaia URLs before +// clearing the internal state of the helper. This is necessary to support +// SAML-based accounts, but causes bug crbug.com/181163. +const int kMaxNavigationsSince = 10; + // Set to true if this chrome instance is in the blue-button-on-white-bar // experimental group. bool use_blue_on_white = false; @@ -515,6 +520,7 @@ bool OneClickInfoBarDelegateImpl::Accept() { chrome::FindBrowserWithWebContents(web_contents)->window()-> ShowOneClickSigninBubble( BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE, + UTF8ToUTF16(email_), base::Bind(&StartSync, StartSyncArgs(profile, browser, OneClickSigninHelper::AUTO_ACCEPT_NONE, @@ -572,7 +578,9 @@ OneClickSigninHelper::OneClickSigninHelper(content::WebContents* web_contents) auto_accept_(AUTO_ACCEPT_NONE), source_(SyncPromoUI::SOURCE_UNKNOWN), switched_to_advanced_(false), - original_source_(SyncPromoUI::SOURCE_UNKNOWN) { + original_source_(SyncPromoUI::SOURCE_UNKNOWN), + untrusted_navigations_since_signin_visit_(0), + is_trusted_(true) { } OneClickSigninHelper::~OneClickSigninHelper() { @@ -625,16 +633,6 @@ bool OneClickSigninHelper::CanOffer(content::WebContents* web_contents, if (!manager) return false; - // Only allow the dedicated signin process to sign the user into - // Chrome without intervention, because it doesn't load any untrusted - // pages. In the interstitial case, since chrome will display a modal - // dialog, we don't need to make this check. - if (can_offer_for == CAN_OFFER_FOR_ALL && - !manager->IsSigninProcess( - web_contents->GetRenderProcessHost()->GetID())) { - return false; - } - // If the signin manager already has an authenticated name, then this is a // re-auth scenario. Make sure the email just signed in corresponds to the // the one sign in manager expects. @@ -950,6 +948,16 @@ void OneClickSigninHelper::ShowInfoBarUIThread( return; } + // Only allow the dedicated signin process to sign the user into + // Chrome without intervention, because it doesn't load any untrusted + // pages. If at any point an untrusted page is detected, chrome will + // show a modal dialog asking the user to confirm. + Profile* profile = + Profile::FromBrowserContext(web_contents->GetBrowserContext()); + SigninManager* manager = profile ? + SigninManagerFactory::GetForProfile(profile) : NULL; + helper->is_trusted_ &= manager && manager->IsSigninProcess(child_id); + // Save the email in the one-click signin manager. The manager may // not exist if the contents is incognito or if the profile is already // connected to a Google account. @@ -1015,6 +1023,8 @@ void OneClickSigninHelper::CleanTransientState() { switched_to_advanced_ = false; original_source_ = SyncPromoUI::SOURCE_UNKNOWN; continue_url_ = GURL(); + untrusted_navigations_since_signin_visit_ = 0; + is_trusted_ = true; // Post to IO thread to clear pending email. Profile* profile = @@ -1071,7 +1081,8 @@ void OneClickSigninHelper::NavigateToPendingEntry( continue_url_.is_valid() && url.ReplaceComponents(replacements) != continue_url_.ReplaceComponents(replacements)) { - CleanTransientState(); + if (++untrusted_navigations_since_signin_visit_ > kMaxNavigationsSince) + CleanTransientState(); } } @@ -1126,6 +1137,12 @@ void OneClickSigninHelper::DidStopLoading( SyncPromoUI::SetUserSkippedSyncPromo(profile); RedirectToNtpOrAppsPage(false); } + + if (!continue_url_match && !IsValidGaiaSigninRedirectOrResponseURL(url) && + ++untrusted_navigations_since_signin_visit_ > kMaxNavigationsSince) { + CleanTransientState(); + } + return; } @@ -1211,6 +1228,7 @@ void OneClickSigninHelper::DidStopLoading( SigninManager::DisableOneClickSignIn(profile); browser->window()->ShowOneClickSigninBubble( bubble_type, + UTF8ToUTF16(email_), base::Bind(&StartSync, StartSyncArgs(profile, browser, auto_accept_, session_index_, email_, password_, @@ -1240,11 +1258,22 @@ void OneClickSigninHelper::DidStopLoading( OneClickSigninSyncStarter::CONFIGURE_SYNC_FIRST : OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS; - // If the new email address is different from the email address that - // just signed in, show a confirmation dialog. std::string last_email = profile->GetPrefs()->GetString(prefs::kGoogleServicesLastUsername); - if (!last_email.empty() && last_email != email_) { + + if (!is_trusted_) { + // The user has navigated away from valid Gaia URLs during sign in, + // verify this sign in is desired. + browser->window()->ShowOneClickSigninBubble( + BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_SAML_MODAL_DIALOG, + UTF8ToUTF16(email_), + base::Bind(&StartSync, + StartSyncArgs(profile, browser, auto_accept_, + session_index_, email_, password_, + force_same_tab_navigation))); + } else if (!last_email.empty() && last_email != email_) { + // If the new email address is different from the email address that + // just signed in, show a confirmation dialog. ConfirmEmailDialogDelegate::AskForConfirmation( contents, last_email, diff --git a/chrome/browser/ui/sync/one_click_signin_helper.h b/chrome/browser/ui/sync/one_click_signin_helper.h index f69cfeb..e4da000 100644 --- a/chrome/browser/ui/sync/one_click_signin_helper.h +++ b/chrome/browser/ui/sync/one_click_signin_helper.h @@ -226,6 +226,17 @@ class OneClickSigninHelper std::string error_message_; scoped_ptr<SigninTracker> signin_tracker_; + // Number of navigations since starting a sign in that is outside the + // the set of trusted Gaia URLs. Sign in attempts that include visits to + // one more untrusted will cause a modal dialog to appear asking the user + // to confirm, similar to the interstitial flow. + int untrusted_navigations_since_signin_visit_; + + // Whether a Gaia URL during the sign in process was not handled by the + // dedicated sign in process. This is set to false if at least one such + // URL is detected. + bool is_trusted_; + DISALLOW_COPY_AND_ASSIGN(OneClickSigninHelper); }; diff --git a/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc b/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc index 5cf366e..9b44ad3 100644 --- a/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc +++ b/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc @@ -631,22 +631,6 @@ TEST_F(OneClickSigninHelperTest, CanOfferNoSigninCookies) { EXPECT_EQ("", error_message); } -TEST_F(OneClickSigninHelperTest, CanOfferUntrustedProcess) { - content::MockRenderProcessHost trusted(browser_context_.get()); - ASSERT_NE(trusted.GetID(), process()->GetID()); - // Make sure the RenderProcessHost used by the test is untrusted. - SetTrustedSigninProcessID(trusted.GetID()); - CreateSigninManager(false, std::string()); - - EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)). - WillRepeatedly(Return(true)); - - EnableOneClick(true); - EXPECT_FALSE(OneClickSigninHelper::CanOffer( - web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL, - "user@gmail.com", NULL)); -} - TEST_F(OneClickSigninHelperTest, CanOfferDisabledByPolicy) { CreateSigninManager(false, std::string()); diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 1a0b424..732d71a 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc @@ -1233,8 +1233,10 @@ void BrowserView::ShowChromeToMobileBubble() { #if defined(ENABLE_ONE_CLICK_SIGNIN) void BrowserView::ShowOneClickSigninBubble( OneClickSigninBubbleType type, + const string16& email, const StartSyncCallback& start_sync_callback) { - OneClickSigninBubbleView::ShowBubble(type, toolbar_, start_sync_callback); + OneClickSigninBubbleView::ShowBubble(type, email, toolbar_, + start_sync_callback); } #endif diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index 813acb3..6d273dc 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h @@ -317,6 +317,7 @@ class BrowserView : public BrowserWindow, #if defined(ENABLE_ONE_CLICK_SIGNIN) virtual void ShowOneClickSigninBubble( OneClickSigninBubbleType type, + const string16& email, const StartSyncCallback& start_sync_callback) OVERRIDE; #endif // TODO(beng): Not an override, move somewhere else. diff --git a/chrome/browser/ui/views/sync/one_click_signin_bubble_view.cc b/chrome/browser/ui/views/sync/one_click_signin_bubble_view.cc index dc77815..ca70433 100644 --- a/chrome/browser/ui/views/sync/one_click_signin_bubble_view.cc +++ b/chrome/browser/ui/views/sync/one_click_signin_bubble_view.cc @@ -7,6 +7,7 @@ #include "base/callback_helpers.h" #include "base/logging.h" #include "base/message_loop.h" +#include "base/utf_string_conversions.h" #include "chrome/browser/google/google_util.h" #include "chrome/browser/ui/browser.h" #include "chrome/common/url_constants.h" @@ -47,6 +48,7 @@ class OneClickSigninDialogView : public OneClickSigninBubbleView { OneClickSigninDialogView( content::WebContents* web_content, views::View* anchor_view, + const string16& email, const BrowserWindow::StartSyncCallback& start_sync_callback); private: @@ -62,6 +64,7 @@ class OneClickSigninDialogView : public OneClickSigninBubbleView { // Overridden from views::LinkListener: virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; + const string16 email_; content::WebContents* web_content_; views::Link* learn_more_link_; views::ImageButton* close_button_; @@ -72,8 +75,10 @@ class OneClickSigninDialogView : public OneClickSigninBubbleView { OneClickSigninDialogView::OneClickSigninDialogView( content::WebContents* web_content, views::View* anchor_view, + const string16& email, const BrowserWindow::StartSyncCallback& start_sync_callback) : OneClickSigninBubbleView(anchor_view, start_sync_callback), + email_(email), web_content_(web_content), learn_more_link_(NULL), close_button_(NULL) { @@ -102,8 +107,10 @@ void OneClickSigninDialogView::InitContent(views::GridLayout* layout) { { layout->StartRow(0, COLUMN_SET_TITLE_BAR); - views::Label* label = new views::Label( - l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_TITLE)); + views::Label* label = new views::Label(email_.empty() ? + l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_TITLE) : + l10n_util::GetStringFUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_TITLE_NEW, + email_)); label->SetHorizontalAlignment(gfx::ALIGN_LEFT); label->SetFont(label->font().DeriveFont(3, gfx::Font::BOLD)); layout->AddView(label); @@ -123,8 +130,10 @@ void OneClickSigninDialogView::InitContent(views::GridLayout* layout) { { layout->StartRow(0, COLUMN_SET_FILL_ALIGN); - views::Label* label = new views::Label( - l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_MESSAGE)); + views::Label* label = new views::Label(email_.empty() ? + l10n_util::GetStringUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_MESSAGE) : + l10n_util::GetStringFUTF16(IDS_ONE_CLICK_SIGNIN_DIALOG_MESSAGE_NEW, + email_)); label->SetMultiLine(true); label->SetHorizontalAlignment(gfx::ALIGN_LEFT); label->SizeToFit(kMinimumDialogLabelWidth); @@ -197,15 +206,28 @@ OneClickSigninBubbleView* OneClickSigninBubbleView::bubble_view_ = NULL; // static void OneClickSigninBubbleView::ShowBubble( BrowserWindow::OneClickSigninBubbleType type, + const string16& email, ToolbarView* toolbar_view, const BrowserWindow::StartSyncCallback& start_sync) { if (IsShowing()) return; - bubble_view_ = type == BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE ? - new OneClickSigninBubbleView(toolbar_view->app_menu(), start_sync) : - new OneClickSigninDialogView(toolbar_view->GetWebContents(), - toolbar_view->location_bar(), start_sync); + switch (type) { + case BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE: + bubble_view_ = new OneClickSigninBubbleView(toolbar_view->app_menu(), + start_sync); + break; + case BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_MODAL_DIALOG: + bubble_view_ = new OneClickSigninDialogView( + toolbar_view->GetWebContents(), toolbar_view->location_bar(), + string16(), start_sync); + break; + case BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_SAML_MODAL_DIALOG: + bubble_view_ = new OneClickSigninDialogView( + toolbar_view->GetWebContents(), toolbar_view->location_bar(), + email, start_sync); + break; + } views::BubbleDelegateView::CreateBubble(bubble_view_)->Show(); } diff --git a/chrome/browser/ui/views/sync/one_click_signin_bubble_view.h b/chrome/browser/ui/views/sync/one_click_signin_bubble_view.h index 25e27df..e8a2c9f 100644 --- a/chrome/browser/ui/views/sync/one_click_signin_bubble_view.h +++ b/chrome/browser/ui/views/sync/one_click_signin_bubble_view.h @@ -36,6 +36,7 @@ class OneClickSigninBubbleView : public views::BubbleDelegateView, // will be placed visually beneath |anchor_view|. |start_sync| is called // to start sync. static void ShowBubble(BrowserWindow::OneClickSigninBubbleType type, + const string16& email, ToolbarView* toolbar_view, const BrowserWindow::StartSyncCallback& start_sync); diff --git a/chrome/browser/ui/views/sync/one_click_signin_bubble_view_browsertest.cc b/chrome/browser/ui/views/sync/one_click_signin_bubble_view_browsertest.cc index d77cf0dd..98f22ef 100644 --- a/chrome/browser/ui/views/sync/one_click_signin_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/sync/one_click_signin_bubble_view_browsertest.cc @@ -22,6 +22,7 @@ class OneClickSigninBubbleViewBrowserTest : public InProcessBrowserTest { OneClickSigninBubbleView* ShowOneClickSigninBubble() { browser()->window()->ShowOneClickSigninBubble( BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE, + string16(), base::Bind(&OneClickSigninBubbleViewBrowserTest::OnStartSync, this)); content::RunAllPendingInMessageLoop(); diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h index 006eb1a..a9a1393 100644 --- a/chrome/test/base/test_browser_window.h +++ b/chrome/test/base/test_browser_window.h @@ -100,6 +100,7 @@ class TestBrowserWindow : public BrowserWindow { #if defined(ENABLE_ONE_CLICK_SIGNIN) virtual void ShowOneClickSigninBubble( OneClickSigninBubbleType type, + const string16& email, const StartSyncCallback& start_sync_callback) OVERRIDE {} #endif virtual bool IsDownloadShelfVisible() const OVERRIDE; |