startup_app_launcher.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
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)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/command_line.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/files/file_path.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/json/json_file_value_serializer.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/path_service.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/values.h"
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.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/extensions/extension_service.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_system.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/webstore_startup_installer.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/lifetime/application_lifetime.h"
21a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/signin/profile_oauth2_token_service.h"
22a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/token_service.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/token_service_factory.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/extensions/application_launch.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"
2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/kiosk_mode_info.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/notification_service.h"
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "google_apis/gaia/gaia_auth_consumer.h"
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "google_apis/gaia/gaia_constants.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::Extension;
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::WebstoreStartupInstaller;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos {
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kOAuthRefreshToken[] = "refresh_token";
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kOAuthClientId[] = "client_id";
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kOAuthClientSecret[] = "client_secret";
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const base::FilePath::CharType kOAuthFileName[] =
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FILE_PATH_LITERAL("kiosk_auth");
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsAppInstalled(Profile* profile, const std::string& app_id) {
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return extensions::ExtensionSystem::Get(profile)->extension_service()->
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetInstalledExtension(app_id);
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)StartupAppLauncher::StartupAppLauncher(Profile* profile,
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const std::string& app_id)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : profile_(profile),
6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      app_id_(app_id),
6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      ready_to_launch_(false) {
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(profile_);
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(Extension::IdIsValid(app_id_));
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)StartupAppLauncher::~StartupAppLauncher() {
6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // StartupAppLauncher can be deleted at anytime during the launch process
6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // through a user bailout shortcut.
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      ->RemoveObserver(this);
7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void StartupAppLauncher::Initialize() {
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "Starting... connection = "
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           <<  net::NetworkChangeNotifier::GetConnectionType();
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StartLoadingOAuthFile();
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void StartupAppLauncher::AddObserver(Observer* observer) {
823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  observer_list_.AddObserver(observer);
833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void StartupAppLauncher::RemoveObserver(Observer* observer) {
863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  observer_list_.RemoveObserver(observer);
873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StartupAppLauncher::StartLoadingOAuthFile() {
903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observer_list_, OnLoadingOAuthFile());
913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  KioskOAuthParams* auth_params = new KioskOAuthParams();
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  BrowserThread::PostBlockingPoolTaskAndReply(
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&StartupAppLauncher::LoadOAuthFileOnBlockingPool,
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 auth_params),
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&StartupAppLauncher::OnOAuthFileLoaded,
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 AsWeakPtr(),
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Owned(auth_params)));
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static.
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StartupAppLauncher::LoadOAuthFileOnBlockingPool(
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    KioskOAuthParams* auth_params) {
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int error_code = JSONFileValueSerializer::JSON_NO_ERROR;
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string error_msg;
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath user_data_dir;
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath auth_file = user_data_dir.Append(kOAuthFileName);
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<JSONFileValueSerializer> serializer(
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new JSONFileValueSerializer(user_data_dir.Append(kOAuthFileName)));
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::Value> value(
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      serializer->Deserialize(&error_code, &error_msg));
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::DictionaryValue* dict = NULL;
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (error_code != JSONFileValueSerializer::JSON_NO_ERROR ||
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !value.get() || !value->GetAsDictionary(&dict)) {
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "Can't find auth file at " << auth_file.value();
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dict->GetString(kOAuthRefreshToken, &auth_params->refresh_token);
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dict->GetString(kOAuthClientId, &auth_params->client_id);
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dict->GetString(kOAuthClientSecret, &auth_params->client_secret);
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StartupAppLauncher::OnOAuthFileLoaded(KioskOAuthParams* auth_params) {
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  auth_params_ = *auth_params;
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Override chrome client_id and secret that will be used for identity
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // API token minting.
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!auth_params_.client_id.empty() && !auth_params_.client_secret.empty()) {
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UserManager::Get()->SetAppModeChromeClientOAuthInfo(
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            auth_params_.client_id,
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            auth_params_.client_secret);
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If we are restarting chrome (i.e. on crash), we need to initialize
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TokenService as well.
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InitializeTokenService();
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StartupAppLauncher::InitializeNetwork() {
1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observer_list_, OnInitializingNetwork());
1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // TODO(tengs): Use NetworkStateInformer instead because it can handle
14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // portal and proxy detection. We will need to do some refactoring to
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // make NetworkStateInformer more independent from the WebUI handlers.
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnNetworkChanged(net::NetworkChangeNotifier::GetConnectionType());
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StartupAppLauncher::InitializeTokenService() {
1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observer_list_, OnInitializingTokenService());
1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ProfileOAuth2TokenService* profile_token_service =
155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (profile_token_service->RefreshTokenIsAvailable(
15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          profile_token_service->GetPrimaryAccountId())) {
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    InitializeNetwork();
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // At the end of this method, the execution will be put on hold until
163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // ProfileOAuth2TokenService triggers either OnRefreshTokenAvailable or
164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // OnRefreshTokensLoaded. Given that we want to handle exactly one event,
165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // whichever comes first, both handlers call RemoveObserver on PO2TS. Handling
166a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // any of the two events is the only way to resume the execution and enable
167a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Cleanup method to be called, self-invoking a destructor. In destructor
168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // StartupAppLauncher is no longer an observer of PO2TS and there is no need
169a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // to call RemoveObserver again.
170a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  profile_token_service->AddObserver(this);
171a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
172a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  token_service->Initialize(GaiaConstants::kChromeSource, profile_);
174a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Pass oauth2 refresh token from the auth file.
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(zelidrag): We should probably remove this option after M27.
177a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // TODO(fgorski): This can go when we have persistence implemented on PO2TS.
178a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Unless the code is no longer needed.
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!auth_params_.refresh_token.empty()) {
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    token_service->UpdateCredentialsWithOAuth2(
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        GaiaAuthConsumer::ClientOAuthResult(
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            auth_params_.refresh_token,
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            std::string(),  // access_token
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            0));            // new_expires_in_secs
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Load whatever tokens we have stored there last time around.
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    token_service->LoadTokensFromDB();
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
191a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void StartupAppLauncher::OnRefreshTokenAvailable(
192a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const std::string& account_id) {
193a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
194a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ->RemoveObserver(this);
195a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  InitializeNetwork();
196a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
197a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void StartupAppLauncher::OnRefreshTokensLoaded() {
199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
200a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ->RemoveObserver(this);
201a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  InitializeNetwork();
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupAppLauncher::OnLaunchSuccess() {
2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observer_list_, OnLaunchSucceeded());
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupAppLauncher::OnLaunchFailure(KioskAppLaunchError::Error error) {
209424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  LOG(ERROR) << "App launch failed, error: " << error;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_NE(KioskAppLaunchError::NONE, error);
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observer_list_, OnLaunchFailed(error));
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void StartupAppLauncher::LaunchApp() {
21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!ready_to_launch_) {
21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    NOTREACHED();
21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    LOG(ERROR) << "LaunchApp() called but launcher is not initialized.";
21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const Extension* extension = extensions::ExtensionSystem::Get(profile_)->
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extension_service()->GetInstalledExtension(app_id_);
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(extension);
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!extensions::KioskModeInfo::IsKioskEnabled(extension)) {
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    OnLaunchFailure(KioskAppLaunchError::NOT_KIOSK_ENABLED);
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Always open the app in a window.
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chrome::OpenApplication(chrome::AppLaunchParams(profile_,
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  extension,
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  extension_misc::LAUNCH_WINDOW,
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  NEW_WINDOW));
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InitAppSession(profile_, app_id_);
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  UserManager::Get()->SessionStarted();
23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  content::NotificationService::current()->Notify(
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      chrome::NOTIFICATION_KIOSK_APP_LAUNCHED,
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      content::NotificationService::AllSources(),
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      content::NotificationService::NoDetails());
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLaunchSuccess();
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupAppLauncher::BeginInstall() {
2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observer_list_, OnInstallingApp());
2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "BeginInstall... connection = "
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           <<  net::NetworkChangeNotifier::GetConnectionType();
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (IsAppInstalled(profile_, app_id_)) {
25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    OnReadyToLaunch();
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  installer_ = new WebstoreStartupInstaller(
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      app_id_,
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile_,
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      false,
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&StartupAppLauncher::InstallCallback, AsWeakPtr()));
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  installer_->BeginInstall();
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupAppLauncher::InstallCallback(bool success,
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         const std::string& error) {
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  installer_ = NULL;
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (success) {
27058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Finish initialization after the callback returns.
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // So that the app finishes its installation.
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserThread::PostTask(
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BrowserThread::UI,
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        base::Bind(&StartupAppLauncher::OnReadyToLaunch,
27658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                   AsWeakPtr()));
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
280424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  LOG(ERROR) << "App install failed: " << error;
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLaunchFailure(KioskAppLaunchError::UNABLE_TO_INSTALL);
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void StartupAppLauncher::OnReadyToLaunch() {
28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ready_to_launch_ = true;
28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observer_list_, OnReadyToLaunch());
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupAppLauncher::OnNetworkChanged(
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net::NetworkChangeNotifier::ConnectionType type) {
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "OnNetworkChanged... connection = "
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           <<  net::NetworkChangeNotifier::GetConnectionType();
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!net::NetworkChangeNotifier::IsOffline()) {
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DVLOG(1) << "Network up and running!";
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BeginInstall();
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DVLOG(1) << "Network not running yet!";
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}   // namespace chromeos
304