startup_app_launcher.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/app_mode/startup_app_launcher.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shell.h" 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/command_line.h" 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/files/file_path.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/json/json_file_value_serializer.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/path_service.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/time.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/values.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/app_mode/app_session_lifetime.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/login/user_manager.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/ui/app_launch_view.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_system.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/webstore_startup_installer.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/lifetime/application_lifetime.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/token_service.h" 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/token_service_factory.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/extensions/application_launch.h" 257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chrome/common/chrome_notification_types.h" 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/chrome_paths.h" 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/chrome_switches.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/extension.h" 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/kiosk_enabled_info.h" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/notification_details.h" 327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/notification_service.h" 337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/notification_source.h" 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "google_apis/gaia/gaia_auth_consumer.h" 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "google_apis/gaia/gaia_constants.h" 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread; 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::Extension; 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::WebstoreStartupInstaller; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos { 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kOAuthRefreshToken[] = "refresh_token"; 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kOAuthClientId[] = "client_id"; 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kOAuthClientSecret[] = "client_secret"; 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const base::FilePath::CharType kOAuthFileName[] = 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FILE_PATH_LITERAL("kiosk_auth"); 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Application install splash screen minimum show time in milliseconds. 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kAppInstallSplashScreenMinTimeMS = 3000; 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsAppInstalled(Profile* profile, const std::string& app_id) { 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return extensions::ExtensionSystem::Get(profile)->extension_service()-> 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetInstalledExtension(app_id); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)StartupAppLauncher::StartupAppLauncher(Profile* profile, 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& app_id) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : profile_(profile), 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) app_id_(app_id), 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) launch_splash_start_time_(0) { 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(profile_); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(Extension::IdIsValid(app_id_)); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(ash::Shell::HasInstance()); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ash::Shell::GetInstance()->AddPreTargetHandler(this); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)StartupAppLauncher::~StartupAppLauncher() { 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(ash::Shell::HasInstance()); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ash::Shell::GetInstance()->RemovePreTargetHandler(this); 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupAppLauncher::Start() { 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) launch_splash_start_time_ = base::TimeTicks::Now().ToInternalValue(); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Starting... connection = " 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << net::NetworkChangeNotifier::GetConnectionType(); 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chromeos::ShowAppLaunchSplashScreen(app_id_); 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StartLoadingOAuthFile(); 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StartupAppLauncher::StartLoadingOAuthFile() { 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) KioskOAuthParams* auth_params = new KioskOAuthParams(); 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BrowserThread::PostBlockingPoolTaskAndReply( 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&StartupAppLauncher::LoadOAuthFileOnBlockingPool, 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) auth_params), 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&StartupAppLauncher::OnOAuthFileLoaded, 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AsWeakPtr(), 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Owned(auth_params))); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static. 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StartupAppLauncher::LoadOAuthFileOnBlockingPool( 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) KioskOAuthParams* auth_params) { 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int error_code = JSONFileValueSerializer::JSON_NO_ERROR; 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string error_msg; 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath user_data_dir; 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)); 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath auth_file = user_data_dir.Append(kOAuthFileName); 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<JSONFileValueSerializer> serializer( 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new JSONFileValueSerializer(user_data_dir.Append(kOAuthFileName))); 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<base::Value> value( 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) serializer->Deserialize(&error_code, &error_msg)); 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::DictionaryValue* dict = NULL; 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (error_code != JSONFileValueSerializer::JSON_NO_ERROR || 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !value.get() || !value->GetAsDictionary(&dict)) { 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(WARNING) << "Can't find auth file at " << auth_file.value(); 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) dict->GetString(kOAuthRefreshToken, &auth_params->refresh_token); 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) dict->GetString(kOAuthClientId, &auth_params->client_id); 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) dict->GetString(kOAuthClientSecret, &auth_params->client_secret); 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StartupAppLauncher::OnOAuthFileLoaded(KioskOAuthParams* auth_params) { 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) auth_params_ = *auth_params; 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Override chrome client_id and secret that will be used for identity 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // API token minting. 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!auth_params_.client_id.empty() && !auth_params_.client_secret.empty()) { 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UserManager::Get()->SetAppModeChromeClientOAuthInfo( 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) auth_params_.client_id, 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) auth_params_.client_secret); 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If we are restarting chrome (i.e. on crash), we need to initialize 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TokenService as well. 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) InitializeTokenService(); 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StartupAppLauncher::InitializeNetwork() { 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chromeos::UpdateAppLaunchSplashScreenState( 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chromeos::APP_LAUNCH_STATE_PREPARING_NETWORK); 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Set a maximum allowed wait time for network. 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int kMaxNetworkWaitSeconds = 5 * 60; 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) network_wait_timer_.Start( 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta::FromSeconds(kMaxNetworkWaitSeconds), 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, &StartupAppLauncher::OnNetworkWaitTimedout); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::NetworkChangeNotifier::AddNetworkChangeObserver(this); 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnNetworkChanged(net::NetworkChangeNotifier::GetConnectionType()); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StartupAppLauncher::InitializeTokenService() { 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chromeos::UpdateAppLaunchSplashScreenState( 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chromeos::APP_LAUNCH_STATE_LOADING_TOKEN_SERVICE); 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TokenService* token_service = 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TokenServiceFactory::GetForProfile(profile_); 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (token_service->HasOAuthLoginToken()) { 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) InitializeNetwork(); 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registrar_.Add(this, 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chrome::NOTIFICATION_TOKEN_LOADING_FINISHED, 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::Source<TokenService>(token_service)); 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registrar_.Add(this, 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chrome::NOTIFICATION_TOKEN_AVAILABLE, 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::Source<TokenService>(token_service)); 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) token_service->Initialize(GaiaConstants::kChromeSource, profile_); 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Pass oauth2 refresh token from the auth file. 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(zelidrag): We should probably remove this option after M27. 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!auth_params_.refresh_token.empty()) { 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) token_service->UpdateCredentialsWithOAuth2( 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GaiaAuthConsumer::ClientOAuthResult( 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) auth_params_.refresh_token, 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(), // access_token 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0)); // new_expires_in_secs 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Load whatever tokens we have stored there last time around. 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) token_service->LoadTokensFromDB(); 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StartupAppLauncher::Observe( 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int type, 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const content::NotificationSource& source, 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const content::NotificationDetails& details) { 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switch (type) { 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: { 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registrar_.RemoveAll(); 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) InitializeNetwork(); 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case chrome::NOTIFICATION_TOKEN_AVAILABLE: { 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TokenService::TokenAvailableDetails* token_details = 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::Details<TokenService::TokenAvailableDetails>( 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) details).ptr(); 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (token_details->service() == 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GaiaConstants::kGaiaOAuth2LoginRefreshToken) { 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registrar_.RemoveAll(); 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) InitializeNetwork(); 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) default: 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NOTREACHED(); 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupAppLauncher::Cleanup() { 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chromeos::CloseAppLaunchSplashScreen(); 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete this; 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupAppLauncher::OnLaunchSuccess() { 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int64 time_taken_ms = (base::TimeTicks::Now() - 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks::FromInternalValue(launch_splash_start_time_)). 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InMilliseconds(); 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Enforce that we show app install splash screen for some minimum amount 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // of time. 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (time_taken_ms < kAppInstallSplashScreenMinTimeMS) { 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostDelayedTask( 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::UI, 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&StartupAppLauncher::OnLaunchSuccess, AsWeakPtr()), 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta::FromMilliseconds( 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kAppInstallSplashScreenMinTimeMS - time_taken_ms)); 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Cleanup(); 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupAppLauncher::OnLaunchFailure(KioskAppLaunchError::Error error) { 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_NE(KioskAppLaunchError::NONE, error); 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Saves the error and ends the session to go back to login screen. 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) KioskAppLaunchError::Save(error); 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome::AttemptUserExit(); 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Cleanup(); 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupAppLauncher::Launch() { 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Extension* extension = extensions::ExtensionSystem::Get(profile_)-> 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension_service()->GetInstalledExtension(app_id_); 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(extension); 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!extensions::KioskEnabledInfo::IsKioskEnabled(extension)) { 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OnLaunchFailure(KioskAppLaunchError::NOT_KIOSK_ENABLED); 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Always open the app in a window. 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome::OpenApplication(chrome::AppLaunchParams(profile_, 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension, 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension_misc::LAUNCH_WINDOW, 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NEW_WINDOW)); 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) InitAppSession(profile_, app_id_); 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::NotificationService::current()->Notify( 263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chrome::NOTIFICATION_KIOSK_APP_LAUNCHED, 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::NotificationService::AllSources(), 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::NotificationService::NoDetails()); 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnLaunchSuccess(); 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupAppLauncher::BeginInstall() { 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "BeginInstall... connection = " 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << net::NetworkChangeNotifier::GetConnectionType(); 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chromeos::UpdateAppLaunchSplashScreenState( 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chromeos::APP_LAUNCH_STATE_INSTALLING_APPLICATION); 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsAppInstalled(profile_, app_id_)) { 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Launch(); 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) installer_ = new WebstoreStartupInstaller( 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) app_id_, 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) profile_, 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) false, 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&StartupAppLauncher::InstallCallback, AsWeakPtr())); 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) installer_->BeginInstall(); 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupAppLauncher::InstallCallback(bool success, 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& error) { 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) installer_ = NULL; 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (success) { 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Schedules Launch() to be called after the callback returns. 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // So that the app finishes its installation. 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::UI, 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&StartupAppLauncher::Launch, AsWeakPtr())); 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to install app with error: " << error; 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnLaunchFailure(KioskAppLaunchError::UNABLE_TO_INSTALL); 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupAppLauncher::OnNetworkWaitTimedout() { 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "OnNetworkWaitTimedout... connection = " 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << net::NetworkChangeNotifier::GetConnectionType(); 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Timeout in waiting for online. Try the install anyway. 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BeginInstall(); 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupAppLauncher::OnNetworkChanged( 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::NetworkChangeNotifier::ConnectionType type) { 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "OnNetworkChanged... connection = " 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << net::NetworkChangeNotifier::GetConnectionType(); 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!net::NetworkChangeNotifier::IsOffline()) { 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Network up and running!"; 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) network_wait_timer_.Stop(); 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BeginInstall(); 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Network not running yet!"; 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupAppLauncher::OnKeyEvent(ui::KeyEvent* event) { 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (event->type() != ui::ET_KEY_PRESSED) 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (KioskAppManager::Get()->GetDisableBailoutShortcut()) 335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (event->key_code() != ui::VKEY_S || 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !(event->flags() & ui::EF_CONTROL_DOWN) || 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !(event->flags() & ui::EF_ALT_DOWN)) { 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnLaunchFailure(KioskAppLaunchError::USER_CANCEL); 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace chromeos 347