startup_app_launcher.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/chromeos/app_mode/kiosk_diagnosis_runner.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/login/user_manager.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/extensions/updater/extension_updater.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/webstore_startup_installer.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/lifetime/application_lifetime.h"
22a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/signin/profile_oauth2_token_service.h"
23a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/signin/signin_manager.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/signin/signin_manager_factory.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/extensions/application_launch.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/chrome_paths.h"
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/chrome_switches.h"
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/chrome_version_info.h"
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/extensions/manifest_url_handler.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/notification_service.h"
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/kiosk_mode_info.h"
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/manifest_handlers/offline_enabled_info.h"
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "google_apis/gaia/gaia_auth_consumer.h"
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "google_apis/gaia/gaia_constants.h"
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/load_flags.h"
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_fetcher.h"
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h"
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_request_status.h"
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "url/gurl.h"
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::Extension;
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::WebstoreStartupInstaller;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos {
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kOAuthRefreshToken[] = "refresh_token";
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kOAuthClientId[] = "client_id";
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kOAuthClientSecret[] = "client_secret";
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const base::FilePath::CharType kOAuthFileName[] =
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FILE_PATH_LITERAL("kiosk_auth");
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int kMaxInstallAttempt = 5;
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)StartupAppLauncher::StartupAppLauncher(Profile* profile,
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                       const std::string& app_id,
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       bool diagnostic_mode,
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                       StartupAppLauncher::Delegate* delegate)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : profile_(profile),
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      app_id_(app_id),
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      diagnostic_mode_(diagnostic_mode),
72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      delegate_(delegate),
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      network_ready_handled_(false),
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      install_attempt_(0),
7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      ready_to_launch_(false) {
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(profile_);
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(Extension::IdIsValid(app_id_));
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)StartupAppLauncher::~StartupAppLauncher() {
8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // StartupAppLauncher can be deleted at anytime during the launch process
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // through a user bailout shortcut.
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      ->RemoveObserver(this);
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void StartupAppLauncher::Initialize() {
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StartLoadingOAuthFile();
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void StartupAppLauncher::ContinueWithNetworkReady() {
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Starts install if it is not started.
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!network_ready_handled_) {
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    network_ready_handled_ = true;
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MaybeInstall();
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StartupAppLauncher::StartLoadingOAuthFile() {
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  delegate_->OnLoadingOAuthFile();
1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  KioskOAuthParams* auth_params = new KioskOAuthParams();
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  BrowserThread::PostBlockingPoolTaskAndReply(
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&StartupAppLauncher::LoadOAuthFileOnBlockingPool,
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 auth_params),
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&StartupAppLauncher::OnOAuthFileLoaded,
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 AsWeakPtr(),
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Owned(auth_params)));
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static.
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StartupAppLauncher::LoadOAuthFileOnBlockingPool(
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    KioskOAuthParams* auth_params) {
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int error_code = JSONFileValueSerializer::JSON_NO_ERROR;
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string error_msg;
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath user_data_dir;
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath auth_file = user_data_dir.Append(kOAuthFileName);
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<JSONFileValueSerializer> serializer(
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new JSONFileValueSerializer(user_data_dir.Append(kOAuthFileName)));
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::Value> value(
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      serializer->Deserialize(&error_code, &error_msg));
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::DictionaryValue* dict = NULL;
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (error_code != JSONFileValueSerializer::JSON_NO_ERROR ||
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !value.get() || !value->GetAsDictionary(&dict)) {
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "Can't find auth file at " << auth_file.value();
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dict->GetString(kOAuthRefreshToken, &auth_params->refresh_token);
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dict->GetString(kOAuthClientId, &auth_params->client_id);
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dict->GetString(kOAuthClientSecret, &auth_params->client_secret);
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StartupAppLauncher::OnOAuthFileLoaded(KioskOAuthParams* auth_params) {
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  auth_params_ = *auth_params;
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Override chrome client_id and secret that will be used for identity
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // API token minting.
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!auth_params_.client_id.empty() && !auth_params_.client_secret.empty()) {
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UserManager::Get()->SetAppModeChromeClientOAuthInfo(
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            auth_params_.client_id,
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            auth_params_.client_secret);
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If we are restarting chrome (i.e. on crash), we need to initialize
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // OAuth2TokenService as well.
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InitializeTokenService();
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void StartupAppLauncher::MaybeInitializeNetwork() {
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  network_ready_handled_ = false;
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const Extension* extension = extensions::ExtensionSystem::Get(profile_)->
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      extension_service()->GetInstalledExtension(app_id_);
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const bool requires_network = !extension ||
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !extensions::OfflineEnabledInfo::IsOfflineEnabled(extension);
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (requires_network) {
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    delegate_->InitializeNetwork();
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Offline enabled app attempts update if network is ready. Otherwise,
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // go directly to launch.
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (delegate_->IsNetworkReady())
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ContinueWithNetworkReady();
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnReadyToLaunch();
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StartupAppLauncher::InitializeTokenService() {
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  delegate_->OnInitializingTokenService();
1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
175a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ProfileOAuth2TokenService* profile_token_service =
176a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SigninManagerBase* signin_manager =
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SigninManagerFactory::GetForProfile(profile_);
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const std::string primary_account_id =
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      signin_manager->GetAuthenticatedAccountId();
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (profile_token_service->RefreshTokenIsAvailable(primary_account_id) ||
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      auth_params_.refresh_token.empty()) {
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MaybeInitializeNetwork();
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Pass oauth2 refresh token from the auth file.
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // TODO(zelidrag): We should probably remove this option after M27.
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // TODO(fgorski): This can go when we have persistence implemented on PO2TS.
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Unless the code is no longer needed.
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // TODO(rogerta): Now that this CL implements token persistence in PO2TS, is
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // this code still needed?  See above two TODOs.
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    //
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // ProfileOAuth2TokenService triggers either OnRefreshTokenAvailable or
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // OnRefreshTokensLoaded. Given that we want to handle exactly one event,
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // whichever comes first, both handlers call RemoveObserver on PO2TS.
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Handling any of the two events is the only way to resume the execution
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // and enable Cleanup method to be called, self-invoking a destructor.
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    profile_token_service->AddObserver(this);
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    profile_token_service->UpdateCredentials(
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        primary_account_id,
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        auth_params_.refresh_token);
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
205a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void StartupAppLauncher::OnRefreshTokenAvailable(
206a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const std::string& account_id) {
207a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
208a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ->RemoveObserver(this);
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MaybeInitializeNetwork();
210a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
212a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void StartupAppLauncher::OnRefreshTokensLoaded() {
213a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
214a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ->RemoveObserver(this);
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MaybeInitializeNetwork();
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void StartupAppLauncher::LaunchApp() {
21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!ready_to_launch_) {
22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    NOTREACHED();
22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    LOG(ERROR) << "LaunchApp() called but launcher is not initialized.";
22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const Extension* extension = extensions::ExtensionSystem::Get(profile_)->
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extension_service()->GetInstalledExtension(app_id_);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(extension);
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!extensions::KioskModeInfo::IsKioskEnabled(extension)) {
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    OnLaunchFailure(KioskAppLaunchError::NOT_KIOSK_ENABLED);
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Always open the app in a window.
2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  OpenApplication(AppLaunchParams(profile_, extension,
235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  extensions::LAUNCH_CONTAINER_WINDOW,
236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  NEW_WINDOW));
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InitAppSession(profile_, app_id_);
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  UserManager::Get()->SessionStarted();
24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  content::NotificationService::current()->Notify(
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      chrome::NOTIFICATION_KIOSK_APP_LAUNCHED,
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      content::NotificationService::AllSources(),
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      content::NotificationService::NoDetails());
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLaunchSuccess();
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (diagnostic_mode_)
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    KioskDiagnosisRunner::Run(profile_, app_id_);
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void StartupAppLauncher::OnLaunchSuccess() {
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delegate_->OnLaunchSucceeded();
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void StartupAppLauncher::OnLaunchFailure(KioskAppLaunchError::Error error) {
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LOG(ERROR) << "App launch failed, error: " << error;
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_NE(KioskAppLaunchError::NONE, error);
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delegate_->OnLaunchFailed(error);
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void StartupAppLauncher::MaybeInstall() {
264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  delegate_->OnInstallingApp();
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtensionService* extension_service =
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      extensions::ExtensionSystem::Get(profile_)->extension_service();
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!extension_service->GetInstalledExtension(app_id_)) {
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BeginInstall();
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  extensions::ExtensionUpdater::CheckParams check_params;
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  check_params.ids.push_back(app_id_);
275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  check_params.install_immediately = true;
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  check_params.callback =
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&StartupAppLauncher::OnUpdateCheckFinished, AsWeakPtr());
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  extension_service->updater()->CheckNow(check_params);
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void StartupAppLauncher::OnUpdateCheckFinished() {
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  OnReadyToLaunch();
283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  UpdateAppData();
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void StartupAppLauncher::BeginInstall() {
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  installer_ = new WebstoreStartupInstaller(
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      app_id_,
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile_,
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      false,
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&StartupAppLauncher::InstallCallback, AsWeakPtr()));
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  installer_->BeginInstall();
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StartupAppLauncher::InstallCallback(bool success,
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         const std::string& error) {
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  installer_ = NULL;
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (success) {
29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Finish initialization after the callback returns.
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // So that the app finishes its installation.
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserThread::PostTask(
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BrowserThread::UI,
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
30458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        base::Bind(&StartupAppLauncher::OnReadyToLaunch,
30558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                   AsWeakPtr()));
306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  LOG(ERROR) << "App install failed: " << error
310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             << ", for attempt " << install_attempt_;
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ++install_attempt_;
313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (install_attempt_ < kMaxInstallAttempt) {
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    BrowserThread::PostTask(
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        BrowserThread::UI,
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        FROM_HERE,
317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::Bind(&StartupAppLauncher::MaybeInitializeNetwork,
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   AsWeakPtr()));
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLaunchFailure(KioskAppLaunchError::UNABLE_TO_INSTALL);
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void StartupAppLauncher::OnReadyToLaunch() {
32658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ready_to_launch_ = true;
327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  delegate_->OnReadyToLaunch();
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void StartupAppLauncher::UpdateAppData() {
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  KioskAppManager::Get()->ClearAppData(app_id_);
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  KioskAppManager::Get()->UpdateAppDataFromProfile(app_id_, profile_, NULL);
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}   // namespace chromeos
336