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, ¶ms.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, ¶ms.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