auto_login_infobar_delegate.cc revision f2477e01787aa58f445919b809d89e252beef54f
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/message_loop.h" 10#include "base/metrics/histogram.h" 11#include "base/prefs/pref_service.h" 12#include "base/strings/utf_string_conversions.h" 13#include "chrome/browser/browser_process.h" 14#include "chrome/browser/chrome_notification_types.h" 15#include "chrome/browser/google/google_util.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/sync/sync_promo_ui.h" 20#include "chrome/common/chrome_switches.h" 21#include "chrome/common/pref_names.h" 22#include "chrome/common/url_constants.h" 23#include "content/public/browser/navigation_controller.h" 24#include "content/public/browser/notification_details.h" 25#include "content/public/browser/notification_observer.h" 26#include "content/public/browser/notification_registrar.h" 27#include "content/public/browser/notification_source.h" 28#include "content/public/browser/notification_types.h" 29#include "content/public/browser/page_navigator.h" 30#include "content/public/browser/web_contents.h" 31#include "content/public/browser/web_contents_observer.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 42#if defined(OS_ANDROID) 43#include "chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.h" 44#endif 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 OAuth2TokenService, gets the browser cookies with the 54// TokenAuth API, and finally redirects the user to the correct page. 55class AutoLoginRedirector : public UbertokenConsumer, 56 public content::WebContentsObserver { 57 public: 58 AutoLoginRedirector(content::WebContents* web_contents, 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::WebContentsObserver 68 virtual void WebContentsDestroyed( 69 content::WebContents* web_contents) OVERRIDE; 70 71 // Redirect tab to MergeSession URL, logging the user in and navigating 72 // to the desired page. 73 void RedirectToMergeSession(const std::string& token); 74 75 const std::string args_; 76 scoped_ptr<UbertokenFetcher> ubertoken_fetcher_; 77 78 DISALLOW_COPY_AND_ASSIGN(AutoLoginRedirector); 79}; 80 81AutoLoginRedirector::AutoLoginRedirector( 82 content::WebContents* web_contents, 83 const std::string& args) 84 : content::WebContentsObserver(web_contents), 85 args_(args) { 86 ubertoken_fetcher_.reset(new UbertokenFetcher( 87 Profile::FromBrowserContext(web_contents->GetBrowserContext()), this)); 88 ubertoken_fetcher_->StartFetchingToken(); 89} 90 91AutoLoginRedirector::~AutoLoginRedirector() { 92} 93 94void AutoLoginRedirector::WebContentsDestroyed( 95 content::WebContents* web_contents) { 96 // The WebContents that started this has been destroyed. The request must be 97 // cancelled and this object must be deleted. 98 ubertoken_fetcher_.reset(); 99 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 100} 101 102void AutoLoginRedirector::OnUbertokenSuccess(const std::string& token) { 103 RedirectToMergeSession(token); 104 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 105} 106 107void AutoLoginRedirector::OnUbertokenFailure( 108 const GoogleServiceAuthError& error) { 109 LOG(WARNING) << "AutoLoginRedirector: token request failed"; 110 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 111} 112 113void AutoLoginRedirector::RedirectToMergeSession(const std::string& token) { 114 // TODO(rogerta): what is the correct page transition? 115 web_contents()->GetController().LoadURL( 116 GaiaUrls::GetInstance()->merge_session_url().Resolve( 117 "?source=chrome&uberauth=" + token + "&" + args_), 118 content::Referrer(), content::PAGE_TRANSITION_AUTO_BOOKMARK, 119 std::string()); 120} 121 122} // namespace 123 124 125// AutoLoginInfoBarDelegate --------------------------------------------------- 126 127// static 128void AutoLoginInfoBarDelegate::Create(InfoBarService* infobar_service, 129 const Params& params) { 130 infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>( 131#if defined(OS_ANDROID) 132 new AutoLoginInfoBarDelegateAndroid(infobar_service, params) 133#else 134 new AutoLoginInfoBarDelegate(infobar_service, params) 135#endif 136 )); 137} 138 139AutoLoginInfoBarDelegate::AutoLoginInfoBarDelegate( 140 InfoBarService* owner, 141 const Params& params) 142 : ConfirmInfoBarDelegate(owner), 143 params_(params), 144 button_pressed_(false) { 145 RecordHistogramAction(SHOWN); 146 registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT, 147 content::Source<Profile>(Profile::FromBrowserContext( 148 web_contents()->GetBrowserContext()))); 149} 150 151AutoLoginInfoBarDelegate::~AutoLoginInfoBarDelegate() { 152 if (!button_pressed_) 153 RecordHistogramAction(IGNORED); 154} 155 156void AutoLoginInfoBarDelegate::InfoBarDismissed() { 157 RecordHistogramAction(DISMISSED); 158 button_pressed_ = true; 159} 160 161int AutoLoginInfoBarDelegate::GetIconID() const { 162 return IDR_INFOBAR_AUTOLOGIN; 163} 164 165InfoBarDelegate::Type AutoLoginInfoBarDelegate::GetInfoBarType() const { 166 return PAGE_ACTION_TYPE; 167} 168 169AutoLoginInfoBarDelegate* 170 AutoLoginInfoBarDelegate::AsAutoLoginInfoBarDelegate() { 171 return this; 172} 173 174string16 AutoLoginInfoBarDelegate::GetMessageText() const { 175 return l10n_util::GetStringFUTF16(IDS_AUTOLOGIN_INFOBAR_MESSAGE, 176 UTF8ToUTF16(params_.username)); 177} 178 179string16 AutoLoginInfoBarDelegate::GetButtonLabel( 180 InfoBarButton button) const { 181 return l10n_util::GetStringUTF16((button == BUTTON_OK) ? 182 IDS_AUTOLOGIN_INFOBAR_OK_BUTTON : IDS_AUTOLOGIN_INFOBAR_CANCEL_BUTTON); 183} 184 185bool AutoLoginInfoBarDelegate::Accept() { 186 // AutoLoginRedirector deletes itself. 187 new AutoLoginRedirector(web_contents(), params_.header.args); 188 RecordHistogramAction(ACCEPTED); 189 button_pressed_ = true; 190 return true; 191} 192 193bool AutoLoginInfoBarDelegate::Cancel() { 194 PrefService* pref_service = Profile::FromBrowserContext( 195 web_contents()->GetBrowserContext())->GetPrefs(); 196 pref_service->SetBoolean(prefs::kAutologinEnabled, false); 197 RecordHistogramAction(REJECTED); 198 button_pressed_ = true; 199 return true; 200} 201 202void AutoLoginInfoBarDelegate::Observe( 203 int type, 204 const content::NotificationSource& source, 205 const content::NotificationDetails& details) { 206 DCHECK_EQ(chrome::NOTIFICATION_GOOGLE_SIGNED_OUT, type); 207 // owner() can be NULL when InfoBarService removes us. See 208 // |InfoBarDelegate::clear_owner|. 209 if (owner()) 210 owner()->RemoveInfoBar(this); 211} 212 213void AutoLoginInfoBarDelegate::RecordHistogramAction(Actions action) { 214 UMA_HISTOGRAM_ENUMERATION("AutoLogin.Regular", action, 215 HISTOGRAM_BOUNDING_VALUE); 216} 217