summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrogerta@chromium.org <rogerta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-12 18:33:12 +0000
committerrogerta@chromium.org <rogerta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-12 18:33:12 +0000
commit0cf5d280b3c224a200c7a9d4f26dc2916184860b (patch)
tree64b1ab41c41ca7f6ba3a5e3dd35449a669fe2d20
parent57274d514de1df72f23bc3adbdea9b073de5a678 (diff)
downloadchromium_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
-rw-r--r--chrome/browser/ui/browser_window.h7
-rw-r--r--chrome/browser/ui/cocoa/browser_window_cocoa.h1
-rw-r--r--chrome/browser/ui/cocoa/browser_window_cocoa.mm1
-rw-r--r--chrome/browser/ui/gtk/browser_window_gtk.cc1
-rw-r--r--chrome/browser/ui/gtk/browser_window_gtk.h1
-rw-r--r--chrome/browser/ui/sync/one_click_signin_helper.cc59
-rw-r--r--chrome/browser/ui/sync/one_click_signin_helper.h11
-rw-r--r--chrome/browser/ui/sync/one_click_signin_helper_unittest.cc16
-rw-r--r--chrome/browser/ui/views/frame/browser_view.cc4
-rw-r--r--chrome/browser/ui/views/frame/browser_view.h1
-rw-r--r--chrome/browser/ui/views/sync/one_click_signin_bubble_view.cc38
-rw-r--r--chrome/browser/ui/views/sync/one_click_signin_bubble_view.h1
-rw-r--r--chrome/browser/ui/views/sync/one_click_signin_bubble_view_browsertest.cc1
-rw-r--r--chrome/test/base/test_browser_window.h1
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;