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