auto_login_infobar_delegate.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/auto_login_infobar_delegate.h" 6 7#include "base/bind.h" 8#include "base/logging.h" 9#include "base/message_loop.h" 10#include "base/metrics/histogram.h" 11#include "base/prefs/pref_service.h" 12#include "base/utf_string_conversions.h" 13#include "chrome/browser/browser_process.h" 14#include "chrome/browser/google/google_util.h" 15#include "chrome/browser/infobars/confirm_infobar_delegate.h" 16#include "chrome/browser/infobars/infobar_service.h" 17#include "chrome/browser/profiles/profile.h" 18#include "chrome/browser/signin/ubertoken_fetcher.h" 19#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h" 20#include "chrome/common/chrome_notification_types.h" 21#include "chrome/common/chrome_switches.h" 22#include "chrome/common/pref_names.h" 23#include "chrome/common/url_constants.h" 24#include "content/public/browser/navigation_controller.h" 25#include "content/public/browser/notification_details.h" 26#include "content/public/browser/notification_observer.h" 27#include "content/public/browser/notification_registrar.h" 28#include "content/public/browser/notification_source.h" 29#include "content/public/browser/notification_types.h" 30#include "content/public/browser/page_navigator.h" 31#include "content/public/browser/web_contents.h" 32#include "content/public/common/referrer.h" 33#include "google_apis/gaia/gaia_constants.h" 34#include "google_apis/gaia/gaia_urls.h" 35#include "grit/chromium_strings.h" 36#include "grit/generated_resources.h" 37#include "grit/theme_resources.h" 38#include "net/base/escape.h" 39#include "net/url_request/url_request.h" 40#include "ui/base/l10n/l10n_util.h" 41 42using content::NavigationController; 43using content::NotificationSource; 44using content::NotificationDetails; 45 46 47// AutoLoginRedirector -------------------------------------------------------- 48 49namespace { 50 51// This class is created by the AutoLoginInfoBarDelegate when the user wishes to 52// auto-login. It holds context information needed while re-issuing service 53// tokens using the TokenService, gets the browser cookies with the TokenAuth 54// API, and finally redirects the user to the correct page. 55class AutoLoginRedirector : public UbertokenConsumer, 56 public content::NotificationObserver { 57 public: 58 AutoLoginRedirector(NavigationController* navigation_controller, 59 const std::string& args); 60 virtual ~AutoLoginRedirector(); 61 62 private: 63 // Overriden from UbertokenConsumer: 64 virtual void OnUbertokenSuccess(const std::string& token) OVERRIDE; 65 virtual void OnUbertokenFailure(const GoogleServiceAuthError& error) OVERRIDE; 66 67 // Implementation of content::NotificationObserver 68 virtual void Observe(int type, 69 const content::NotificationSource& source, 70 const content::NotificationDetails& details) OVERRIDE; 71 72 // Redirect tab to MergeSession URL, logging the user in and navigating 73 // to the desired page. 74 void RedirectToMergeSession(const std::string& token); 75 76 NavigationController* navigation_controller_; 77 const std::string args_; 78 scoped_ptr<UbertokenFetcher> ubertoken_fetcher_; 79 80 // For listening to NavigationController destruction. 81 content::NotificationRegistrar registrar_; 82 83 DISALLOW_COPY_AND_ASSIGN(AutoLoginRedirector); 84}; 85 86AutoLoginRedirector::AutoLoginRedirector( 87 NavigationController* navigation_controller, 88 const std::string& args) 89 : navigation_controller_(navigation_controller), 90 args_(args) { 91 ubertoken_fetcher_.reset(new UbertokenFetcher( 92 Profile::FromBrowserContext(navigation_controller_->GetBrowserContext()), 93 this)); 94 registrar_.Add(this, 95 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 96 content::Source<content::WebContents>( 97 navigation_controller_->GetWebContents())); 98 ubertoken_fetcher_->StartFetchingToken(); 99} 100 101AutoLoginRedirector::~AutoLoginRedirector() { 102} 103 104void AutoLoginRedirector::Observe(int type, 105 const NotificationSource& source, 106 const NotificationDetails& details) { 107 DCHECK(type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED); 108 // The WebContents that started this has been destroyed. The request must be 109 // cancelled and this object must be deleted. 110 ubertoken_fetcher_.reset(); 111 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 112} 113 114void AutoLoginRedirector::OnUbertokenSuccess(const std::string& token) { 115 RedirectToMergeSession(token); 116 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 117} 118 119void AutoLoginRedirector::OnUbertokenFailure( 120 const GoogleServiceAuthError& error) { 121 LOG(WARNING) << "AutoLoginRedirector: token request failed"; 122 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 123} 124 125void AutoLoginRedirector::RedirectToMergeSession(const std::string& token) { 126 // TODO(rogerta): what is the correct page transition? 127 navigation_controller_->LoadURL( 128 GURL(GaiaUrls::GetInstance()->merge_session_url() + 129 "?source=chrome&uberauth=" + token + "&" + args_), 130 content::Referrer(), content::PAGE_TRANSITION_AUTO_BOOKMARK, 131 std::string()); 132} 133 134} // namepsace 135 136 137// AutoLoginInfoBarDelegate::Params ------------------------------------------- 138 139AutoLoginInfoBarDelegate::Params::Params() {} 140AutoLoginInfoBarDelegate::Params::~Params() {} 141 142 143// AutoLoginInfoBarDelegate --------------------------------------------------- 144 145// static 146void AutoLoginInfoBarDelegate::Create(InfoBarService* infobar_service, 147 const Params& params) { 148 infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>( 149 new AutoLoginInfoBarDelegate(infobar_service, params))); 150} 151 152string16 AutoLoginInfoBarDelegate::GetMessageText( 153 const std::string& username) const { 154 return l10n_util::GetStringFUTF16(IDS_AUTOLOGIN_INFOBAR_MESSAGE, 155 UTF8ToUTF16(username)); 156} 157 158AutoLoginInfoBarDelegate::AutoLoginInfoBarDelegate( 159 InfoBarService* owner, 160 const Params& params) 161 : ConfirmInfoBarDelegate(owner), 162 params_(params), 163 button_pressed_(false) { 164 RecordHistogramAction(HISTOGRAM_SHOWN); 165 registrar_.Add(this, 166 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT, 167 content::Source<Profile>(Profile::FromBrowserContext( 168 web_contents()->GetBrowserContext()))); 169} 170 171AutoLoginInfoBarDelegate::~AutoLoginInfoBarDelegate() { 172 if (!button_pressed_) 173 RecordHistogramAction(HISTOGRAM_IGNORED); 174} 175 176void AutoLoginInfoBarDelegate::InfoBarDismissed() { 177 RecordHistogramAction(HISTOGRAM_DISMISSED); 178 button_pressed_ = true; 179} 180 181int AutoLoginInfoBarDelegate::GetIconID() const { 182 return IDR_INFOBAR_AUTOLOGIN; 183} 184 185InfoBarDelegate::Type AutoLoginInfoBarDelegate::GetInfoBarType() const { 186 return PAGE_ACTION_TYPE; 187} 188 189AutoLoginInfoBarDelegate* 190 AutoLoginInfoBarDelegate::AsAutoLoginInfoBarDelegate() { 191 return this; 192} 193 194string16 AutoLoginInfoBarDelegate::GetMessageText() const { 195 return GetMessageText(params_.username); 196} 197 198string16 AutoLoginInfoBarDelegate::GetButtonLabel( 199 InfoBarButton button) const { 200 return l10n_util::GetStringUTF16((button == BUTTON_OK) ? 201 IDS_AUTOLOGIN_INFOBAR_OK_BUTTON : IDS_AUTOLOGIN_INFOBAR_CANCEL_BUTTON); 202} 203 204bool AutoLoginInfoBarDelegate::Accept() { 205 // AutoLoginRedirector deletes itself. 206 new AutoLoginRedirector(&web_contents()->GetController(), 207 params_.header.args); 208 RecordHistogramAction(HISTOGRAM_ACCEPTED); 209 button_pressed_ = true; 210 return true; 211} 212 213bool AutoLoginInfoBarDelegate::Cancel() { 214 Profile* profile = Profile::FromBrowserContext( 215 web_contents()->GetBrowserContext()); 216 PrefService* pref_service = profile->GetPrefs(); 217 pref_service->SetBoolean(prefs::kAutologinEnabled, false); 218 RecordHistogramAction(HISTOGRAM_REJECTED); 219 button_pressed_ = true; 220 return true; 221} 222 223void AutoLoginInfoBarDelegate::Observe(int type, 224 const NotificationSource& source, 225 const NotificationDetails& details) { 226 DCHECK_EQ(chrome::NOTIFICATION_GOOGLE_SIGNED_OUT, type); 227 // owner() can be NULL when InfoBarService removes us. See 228 // |InfoBarDelegate::clear_owner|. 229 if (owner()) 230 owner()->RemoveInfoBar(this); 231} 232 233void AutoLoginInfoBarDelegate::RecordHistogramAction(Actions action) { 234 UMA_HISTOGRAM_ENUMERATION("AutoLogin.Regular", action, HISTOGRAM_MAX); 235} 236