6e5bb747076f3664be80e700029686d12b93c704
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / auto_login_infobar_delegate.cc
1 // Copyright 2014 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/google/google_util.h"
15 #include "chrome/browser/infobars/infobar.h"
16 #include "chrome/browser/infobars/infobar_service.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
19 #include "chrome/browser/signin/signin_manager_factory.h"
20 #include "chrome/browser/ui/sync/sync_promo_ui.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/common/url_constants.h"
24 #include "components/signin/core/browser/profile_oauth2_token_service.h"
25 #include "content/public/browser/navigation_controller.h"
26 #include "content/public/browser/page_navigator.h"
27 #include "content/public/browser/web_contents.h"
28 #include "content/public/browser/web_contents_observer.h"
29 #include "content/public/common/referrer.h"
30 #include "google_apis/gaia/gaia_constants.h"
31 #include "google_apis/gaia/gaia_urls.h"
32 #include "google_apis/gaia/ubertoken_fetcher.h"
33 #include "grit/chromium_strings.h"
34 #include "grit/generated_resources.h"
35 #include "grit/theme_resources.h"
36 #include "net/base/escape.h"
37 #include "net/url_request/url_request.h"
38 #include "ui/base/l10n/l10n_util.h"
39
40 #if defined(OS_ANDROID)
41 #include "chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.h"
42 #endif
43
44
45 // AutoLoginRedirector --------------------------------------------------------
46
47 namespace {
48
49 // This class is created by the AutoLoginInfoBarDelegate when the user wishes to
50 // auto-login.  It holds context information needed while re-issuing service
51 // tokens using the OAuth2TokenService, gets the browser cookies with the
52 // TokenAuth API, and finally redirects the user to the correct page.
53 class AutoLoginRedirector : public UbertokenConsumer,
54                             public content::WebContentsObserver {
55  public:
56   AutoLoginRedirector(content::WebContents* web_contents,
57                       const std::string& args);
58   virtual ~AutoLoginRedirector();
59
60  private:
61   // Overriden from UbertokenConsumer:
62   virtual void OnUbertokenSuccess(const std::string& token) OVERRIDE;
63   virtual void OnUbertokenFailure(const GoogleServiceAuthError& error) OVERRIDE;
64
65   // Implementation of content::WebContentsObserver
66   virtual void WebContentsDestroyed(
67       content::WebContents* web_contents) OVERRIDE;
68
69   // Redirect tab to MergeSession URL, logging the user in and navigating
70   // to the desired page.
71   void RedirectToMergeSession(const std::string& token);
72
73   const std::string args_;
74   scoped_ptr<UbertokenFetcher> ubertoken_fetcher_;
75
76   DISALLOW_COPY_AND_ASSIGN(AutoLoginRedirector);
77 };
78
79 AutoLoginRedirector::AutoLoginRedirector(
80     content::WebContents* web_contents,
81     const std::string& args)
82     : content::WebContentsObserver(web_contents),
83       args_(args) {
84   Profile* profile =
85       Profile::FromBrowserContext(web_contents->GetBrowserContext());
86   ProfileOAuth2TokenService* token_service =
87       ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
88   SigninManagerBase* signin_manager =
89       SigninManagerFactory::GetInstance()->GetForProfile(profile);
90   ubertoken_fetcher_.reset(new UbertokenFetcher(token_service,
91                                                 this,
92                                                 profile->GetRequestContext()));
93   ubertoken_fetcher_->StartFetchingToken(
94       signin_manager->GetAuthenticatedAccountId());
95 }
96
97 AutoLoginRedirector::~AutoLoginRedirector() {
98 }
99
100 void AutoLoginRedirector::WebContentsDestroyed(
101     content::WebContents* web_contents) {
102   // The WebContents that started this has been destroyed. The request must be
103   // cancelled and this object must be deleted.
104   ubertoken_fetcher_.reset();
105   base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
106 }
107
108 void AutoLoginRedirector::OnUbertokenSuccess(const std::string& token) {
109   RedirectToMergeSession(token);
110   base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
111 }
112
113 void AutoLoginRedirector::OnUbertokenFailure(
114     const GoogleServiceAuthError& error) {
115   LOG(WARNING) << "AutoLoginRedirector: token request failed";
116   base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
117 }
118
119 void AutoLoginRedirector::RedirectToMergeSession(const std::string& token) {
120   // TODO(rogerta): what is the correct page transition?
121   web_contents()->GetController().LoadURL(
122       GaiaUrls::GetInstance()->merge_session_url().Resolve(
123           "?source=chrome&uberauth=" + token + "&" + args_),
124       content::Referrer(), content::PAGE_TRANSITION_AUTO_BOOKMARK,
125       std::string());
126 }
127
128 }  // namespace
129
130
131 // AutoLoginInfoBarDelegate ---------------------------------------------------
132
133 // static
134 bool AutoLoginInfoBarDelegate::Create(content::WebContents* web_contents,
135                                       const Params& params) {
136   // If |web_contents| is hosted in a WebDialog, there may be no infobar
137   // service.
138   InfoBarService* infobar_service =
139     InfoBarService::FromWebContents(web_contents);
140   if (!infobar_service)
141     return false;
142
143   Profile* profile =
144       Profile::FromBrowserContext(web_contents->GetBrowserContext());
145 #if defined(OS_ANDROID)
146   typedef AutoLoginInfoBarDelegateAndroid Delegate;
147 #else
148   typedef AutoLoginInfoBarDelegate Delegate;
149 #endif
150   return !!infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
151       scoped_ptr<ConfirmInfoBarDelegate>(new Delegate(params, profile))));
152 }
153
154 AutoLoginInfoBarDelegate::AutoLoginInfoBarDelegate(const Params& params,
155                                                    Profile* profile)
156     : ConfirmInfoBarDelegate(),
157       params_(params),
158       profile_(profile),
159       button_pressed_(false) {
160   RecordHistogramAction(SHOWN);
161
162   // The AutoLogin infobar is shown in incognito mode on Android, so a
163   // SigninManager isn't guaranteed to exist for |profile_|.
164   SigninManagerBase* signin_manager =
165       SigninManagerFactory::GetInstance()->GetForProfile(profile_);
166   if (signin_manager)
167     signin_manager->AddObserver(this);
168 }
169
170 AutoLoginInfoBarDelegate::~AutoLoginInfoBarDelegate() {
171   // The AutoLogin infobar is shown in incognito mode on Android, so a
172   // SigninManager isn't guaranteed to exist for |profile_|.
173   SigninManagerBase* signin_manager =
174       SigninManagerFactory::GetInstance()->GetForProfile(profile_);
175   if (signin_manager)
176     signin_manager->RemoveObserver(this);
177
178   if (!button_pressed_)
179     RecordHistogramAction(IGNORED);
180 }
181
182 void AutoLoginInfoBarDelegate::InfoBarDismissed() {
183   RecordHistogramAction(DISMISSED);
184   button_pressed_ = true;
185 }
186
187 int AutoLoginInfoBarDelegate::GetIconID() const {
188   return IDR_INFOBAR_AUTOLOGIN;
189 }
190
191 InfoBarDelegate::Type AutoLoginInfoBarDelegate::GetInfoBarType() const {
192   return PAGE_ACTION_TYPE;
193 }
194
195 AutoLoginInfoBarDelegate*
196     AutoLoginInfoBarDelegate::AsAutoLoginInfoBarDelegate() {
197   return this;
198 }
199
200 base::string16 AutoLoginInfoBarDelegate::GetMessageText() const {
201   return l10n_util::GetStringFUTF16(IDS_AUTOLOGIN_INFOBAR_MESSAGE,
202                                     base::UTF8ToUTF16(params_.username));
203 }
204
205 base::string16 AutoLoginInfoBarDelegate::GetButtonLabel(
206     InfoBarButton button) const {
207   return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
208       IDS_AUTOLOGIN_INFOBAR_OK_BUTTON : IDS_AUTOLOGIN_INFOBAR_CANCEL_BUTTON);
209 }
210
211 bool AutoLoginInfoBarDelegate::Accept() {
212   // AutoLoginRedirector deletes itself.
213   new AutoLoginRedirector(web_contents(), params_.header.args);
214   RecordHistogramAction(ACCEPTED);
215   button_pressed_ = true;
216   return true;
217 }
218
219 bool AutoLoginInfoBarDelegate::Cancel() {
220   PrefService* pref_service = Profile::FromBrowserContext(
221       web_contents()->GetBrowserContext())->GetPrefs();
222   pref_service->SetBoolean(prefs::kAutologinEnabled, false);
223   RecordHistogramAction(REJECTED);
224   button_pressed_ = true;
225   return true;
226 }
227
228 void AutoLoginInfoBarDelegate::GoogleSignedOut(const std::string& username) {
229   infobar()->RemoveSelf();
230 }
231
232 void AutoLoginInfoBarDelegate::RecordHistogramAction(Actions action) {
233   UMA_HISTOGRAM_ENUMERATION("AutoLogin.Regular", action,
234                             HISTOGRAM_BOUNDING_VALUE);
235 }