15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/auto_login_prompter.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/google/google_url_tracker.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
13ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/browser/signin/profile_oauth2_token_service.h"
14ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/signin/signin_manager.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/signin/signin_manager_factory.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/tab_contents/tab_util.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/auto_login_parser/auto_login_parser.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h"
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if !defined(OS_ANDROID)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FetchUsernameThroughSigninManager(Profile* profile, std::string* output) {
33ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // In an incognito window these services are not available.
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SigninManagerBase* signin_manager =
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SigninManagerFactory::GetInstance()->GetForProfile(profile);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!signin_manager)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ProfileOAuth2TokenService* token_service =
4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!token_service || !token_service->RefreshTokenIsAvailable(
4268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          token_service->GetPrimaryAccountId())) {
4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *output = signin_manager->GetAuthenticatedUsername();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif  // !defined(OS_ANDROID)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AutoLoginPrompter::AutoLoginPrompter(WebContents* web_contents,
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     const Params& params,
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     const GURL& url)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : WebContentsObserver(web_contents),
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      params_(params),
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url_(url),
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      infobar_shown_(false) {
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!web_contents->IsLoading()) {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If the WebContents isn't loading a page, the load notification will never
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // be triggered.  Try adding the InfoBar now.
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AddInfoBarToWebContents();
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutoLoginPrompter::~AutoLoginPrompter() {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutoLoginPrompter::ShowInfoBarIfPossible(net::URLRequest* request,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              int child_id,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              int route_id) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableAutologin))
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See if the response contains the X-Auto-Login header.  If so, this was
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a request for a login page, and the server is allowing the browser to
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // suggest auto-login, if available.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Params params;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Currently we only accept GAIA credentials in Chrome.
82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!auto_login_parser::ParserHeaderInResponse(
83b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          request, auto_login_parser::ONLY_GOOGLE_COM, &params.header))
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::UI, FROM_HERE,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&ShowInfoBarUIThread,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 params, request->url(), child_id, route_id));
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutoLoginPrompter::ShowInfoBarUIThread(Params params,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const GURL& url,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            int child_id,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            int route_id) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebContents* web_contents = tab_util::GetWebContentsByID(child_id, route_id);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!web_contents)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile =
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Profile::FromBrowserContext(web_contents->GetBrowserContext());
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile->GetPrefs()->GetBoolean(prefs::kAutologinEnabled))
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On Android, the username is fetched on the Java side from the
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AccountManager provided by the platform.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FetchUsernameThroughSigninManager(profile, &params.username))
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure that |account|, if specified, matches the logged in user.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // However, |account| is usually empty.
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!params.username.empty() && !params.header.account.empty() &&
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      params.username != params.header.account)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We can't add the infobar just yet, since we need to wait for the tab to
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // finish loading.  If we don't, the info bar appears and then disappears
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // immediately.  Create an AutoLoginPrompter instance to listen for the
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // relevant notifications; it will delete itself.
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  new AutoLoginPrompter(web_contents, params, url);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutoLoginPrompter::DidStopLoading(
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::RenderViewHost* render_view_host) {
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddInfoBarToWebContents();
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete this;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutoLoginPrompter::WebContentsDestroyed(WebContents* web_contents) {
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The WebContents was destroyed before the navigation completed.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutoLoginPrompter::AddInfoBarToWebContents() {
140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!infobar_shown_)
141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    infobar_shown_ = AutoLoginInfoBarDelegate::Create(web_contents(), params_);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
143