Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(234)

Side by Side Diff: chrome/browser/chromeos/app_mode/startup_app_launcher.cc

Issue 300843013: Install and launch kiosk app from cached crx file at start up. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove the useless offline_enabled_app_profile testing data. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/app_mode/startup_app_launcher.h" 5 #include "chrome/browser/chromeos/app_mode/startup_app_launcher.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
9 #include "base/json/json_file_value_serializer.h" 9 #include "base/json/json_file_value_serializer.h"
10 #include "base/path_service.h" 10 #include "base/path_service.h"
11 #include "base/time/time.h" 11 #include "base/time/time.h"
12 #include "base/values.h" 12 #include "base/values.h"
13 #include "chrome/browser/chrome_notification_types.h" 13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/chromeos/app_mode/app_session_lifetime.h" 14 #include "chrome/browser/chromeos/app_mode/app_session_lifetime.h"
15 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" 15 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
16 #include "chrome/browser/chromeos/app_mode/kiosk_diagnosis_runner.h" 16 #include "chrome/browser/chromeos/app_mode/kiosk_diagnosis_runner.h"
17 #include "chrome/browser/chromeos/login/session/user_session_manager.h" 17 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
18 #include "chrome/browser/chromeos/login/users/user_manager.h" 18 #include "chrome/browser/chromeos/login/users/user_manager.h"
19 #include "chrome/browser/extensions/extension_service.h" 19 #include "chrome/browser/extensions/extension_service.h"
20 #include "chrome/browser/extensions/install_tracker.h"
21 #include "chrome/browser/extensions/install_tracker_factory.h"
20 #include "chrome/browser/extensions/updater/extension_updater.h" 22 #include "chrome/browser/extensions/updater/extension_updater.h"
21 #include "chrome/browser/extensions/webstore_startup_installer.h"
22 #include "chrome/browser/lifetime/application_lifetime.h" 23 #include "chrome/browser/lifetime/application_lifetime.h"
23 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 24 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
24 #include "chrome/browser/signin/signin_manager_factory.h" 25 #include "chrome/browser/signin/signin_manager_factory.h"
25 #include "chrome/browser/ui/extensions/application_launch.h" 26 #include "chrome/browser/ui/extensions/application_launch.h"
26 #include "chrome/common/chrome_paths.h" 27 #include "chrome/common/chrome_paths.h"
27 #include "chrome/common/chrome_switches.h" 28 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/chrome_version_info.h" 29 #include "chrome/common/chrome_version_info.h"
29 #include "chrome/common/extensions/manifest_url_handler.h" 30 #include "chrome/common/extensions/manifest_url_handler.h"
30 #include "components/signin/core/browser/profile_oauth2_token_service.h" 31 #include "components/signin/core/browser/profile_oauth2_token_service.h"
31 #include "components/signin/core/browser/signin_manager.h" 32 #include "components/signin/core/browser/signin_manager.h"
32 #include "content/public/browser/browser_thread.h" 33 #include "content/public/browser/browser_thread.h"
33 #include "content/public/browser/notification_service.h" 34 #include "content/public/browser/notification_service.h"
34 #include "extensions/browser/extension_system.h" 35 #include "extensions/browser/extension_system.h"
35 #include "extensions/common/extension.h" 36 #include "extensions/common/extension.h"
36 #include "extensions/common/manifest_handlers/kiosk_mode_info.h" 37 #include "extensions/common/manifest_handlers/kiosk_mode_info.h"
37 #include "extensions/common/manifest_handlers/offline_enabled_info.h" 38 #include "extensions/common/manifest_handlers/offline_enabled_info.h"
38 #include "google_apis/gaia/gaia_auth_consumer.h" 39 #include "google_apis/gaia/gaia_auth_consumer.h"
39 #include "google_apis/gaia/gaia_constants.h" 40 #include "google_apis/gaia/gaia_constants.h"
40 #include "net/base/load_flags.h" 41 #include "net/base/load_flags.h"
41 #include "net/url_request/url_fetcher.h" 42 #include "net/url_request/url_fetcher.h"
42 #include "net/url_request/url_fetcher_delegate.h" 43 #include "net/url_request/url_fetcher_delegate.h"
43 #include "net/url_request/url_request_context_getter.h" 44 #include "net/url_request/url_request_context_getter.h"
44 #include "net/url_request/url_request_status.h" 45 #include "net/url_request/url_request_status.h"
45 #include "url/gurl.h" 46 #include "url/gurl.h"
46 47
47 using content::BrowserThread; 48 using content::BrowserThread;
48 using extensions::Extension; 49 using extensions::Extension;
49 using extensions::WebstoreStartupInstaller;
50 50
51 namespace chromeos { 51 namespace chromeos {
52 52
53 namespace { 53 namespace {
54 54
55 const char kOAuthRefreshToken[] = "refresh_token"; 55 const char kOAuthRefreshToken[] = "refresh_token";
56 const char kOAuthClientId[] = "client_id"; 56 const char kOAuthClientId[] = "client_id";
57 const char kOAuthClientSecret[] = "client_secret"; 57 const char kOAuthClientSecret[] = "client_secret";
58 58
59 const base::FilePath::CharType kOAuthFileName[] = 59 const base::FilePath::CharType kOAuthFileName[] =
60 FILE_PATH_LITERAL("kiosk_auth"); 60 FILE_PATH_LITERAL("kiosk_auth");
61 61
62 const int kMaxInstallAttempt = 5; 62 const int kMaxLaunchAttempt = 5;
63 63
64 } // namespace 64 } // namespace
65 65
66 StartupAppLauncher::StartupAppLauncher(Profile* profile, 66 StartupAppLauncher::StartupAppLauncher(Profile* profile,
67 const std::string& app_id, 67 const std::string& app_id,
68 bool diagnostic_mode, 68 bool diagnostic_mode,
69 StartupAppLauncher::Delegate* delegate) 69 StartupAppLauncher::Delegate* delegate)
70 : profile_(profile), 70 : profile_(profile),
71 app_id_(app_id), 71 app_id_(app_id),
72 diagnostic_mode_(diagnostic_mode), 72 diagnostic_mode_(diagnostic_mode),
73 delegate_(delegate), 73 delegate_(delegate),
74 network_ready_handled_(false), 74 network_ready_handled_(false),
75 install_attempt_(0), 75 launch_attempt_(0),
76 ready_to_launch_(false) { 76 ready_to_launch_(false),
77 wait_for_crx_update_(false) {
77 DCHECK(profile_); 78 DCHECK(profile_);
78 DCHECK(Extension::IdIsValid(app_id_)); 79 DCHECK(Extension::IdIsValid(app_id_));
80 KioskAppManager::Get()->AddObserver(this);
79 } 81 }
80 82
81 StartupAppLauncher::~StartupAppLauncher() { 83 StartupAppLauncher::~StartupAppLauncher() {
84 KioskAppManager::Get()->RemoveObserver(this);
85
82 // StartupAppLauncher can be deleted at anytime during the launch process 86 // StartupAppLauncher can be deleted at anytime during the launch process
83 // through a user bailout shortcut. 87 // through a user bailout shortcut.
84 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_) 88 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
85 ->RemoveObserver(this); 89 ->RemoveObserver(this);
86 } 90 }
87 91
88 void StartupAppLauncher::Initialize() { 92 void StartupAppLauncher::Initialize() {
89 StartLoadingOAuthFile(); 93 StartLoadingOAuthFile();
90 } 94 }
91 95
92 void StartupAppLauncher::ContinueWithNetworkReady() { 96 void StartupAppLauncher::ContinueWithNetworkReady() {
93 // Starts install if it is not started.
94 if (!network_ready_handled_) { 97 if (!network_ready_handled_) {
95 network_ready_handled_ = true; 98 network_ready_handled_ = true;
96 MaybeInstall(); 99 // The network might not be ready when KioskAppManager tries to update
100 // external cache initially. Update the external cache now that the network
101 // is ready for sure.
102 wait_for_crx_update_ = true;
103 KioskAppManager::Get()->UpdateExternalCache();
97 } 104 }
98 } 105 }
99 106
100 void StartupAppLauncher::StartLoadingOAuthFile() { 107 void StartupAppLauncher::StartLoadingOAuthFile() {
101 delegate_->OnLoadingOAuthFile(); 108 delegate_->OnLoadingOAuthFile();
102 109
103 KioskOAuthParams* auth_params = new KioskOAuthParams(); 110 KioskOAuthParams* auth_params = new KioskOAuthParams();
104 BrowserThread::PostBlockingPoolTaskAndReply( 111 BrowserThread::PostBlockingPoolTaskAndReply(
105 FROM_HERE, 112 FROM_HERE,
106 base::Bind(&StartupAppLauncher::LoadOAuthFileOnBlockingPool, 113 base::Bind(&StartupAppLauncher::LoadOAuthFileOnBlockingPool,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 } 152 }
146 153
147 // If we are restarting chrome (i.e. on crash), we need to initialize 154 // If we are restarting chrome (i.e. on crash), we need to initialize
148 // OAuth2TokenService as well. 155 // OAuth2TokenService as well.
149 InitializeTokenService(); 156 InitializeTokenService();
150 } 157 }
151 158
152 void StartupAppLauncher::RestartLauncher() { 159 void StartupAppLauncher::RestartLauncher() {
153 // If the installer is still running in the background, we don't need to 160 // If the installer is still running in the background, we don't need to
154 // restart the launch process. We will just wait until it completes and 161 // restart the launch process. We will just wait until it completes and
155 // lunches the kiosk app. 162 // launches the kiosk app.
156 if (installer_ != NULL) { 163 if (extensions::ExtensionSystem::Get(profile_)
164 ->extension_service()
165 ->pending_extension_manager()
166 ->IsIdPending(app_id_)) {
157 LOG(WARNING) << "Installer still running"; 167 LOG(WARNING) << "Installer still running";
158 return; 168 return;
159 } 169 }
160 170
161 MaybeInitializeNetwork(); 171 MaybeInitializeNetwork();
162 } 172 }
163 173
164 void StartupAppLauncher::MaybeInitializeNetwork() { 174 void StartupAppLauncher::MaybeInitializeNetwork() {
165 network_ready_handled_ = false; 175 network_ready_handled_ = false;
166 176
167 const Extension* extension = extensions::ExtensionSystem::Get(profile_)-> 177 const Extension* extension = extensions::ExtensionSystem::Get(profile_)->
168 extension_service()->GetInstalledExtension(app_id_); 178 extension_service()->GetInstalledExtension(app_id_);
169 const bool requires_network = !extension || 179 bool crx_cached = KioskAppManager::Get()->HasCachedCrx(app_id_);
170 !extensions::OfflineEnabledInfo::IsOfflineEnabled(extension); 180 const bool requires_network =
181 (!extension && !crx_cached) ||
182 (extension &&
183 !extensions::OfflineEnabledInfo::IsOfflineEnabled(extension));
171 184
172 if (requires_network) { 185 if (requires_network) {
173 delegate_->InitializeNetwork(); 186 delegate_->InitializeNetwork();
174 return; 187 return;
175 } 188 }
176 189
177 // Offline enabled app attempts update if network is ready. Otherwise, 190 // Update the offline enabled crx cache if the network is ready;
178 // go directly to launch. 191 // or just install the app.
179 if (delegate_->IsNetworkReady()) 192 if (delegate_->IsNetworkReady())
180 ContinueWithNetworkReady(); 193 ContinueWithNetworkReady();
181 else 194 else
182 OnReadyToLaunch(); 195 BeginInstall();
183 } 196 }
184 197
185 void StartupAppLauncher::InitializeTokenService() { 198 void StartupAppLauncher::InitializeTokenService() {
186 delegate_->OnInitializingTokenService(); 199 delegate_->OnInitializingTokenService();
187 200
188 ProfileOAuth2TokenService* profile_token_service = 201 ProfileOAuth2TokenService* profile_token_service =
189 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); 202 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
190 SigninManagerBase* signin_manager = 203 SigninManagerBase* signin_manager =
191 SigninManagerFactory::GetForProfile(profile_); 204 SigninManagerFactory::GetForProfile(profile_);
192 const std::string primary_account_id = 205 const std::string primary_account_id =
(...skipping 28 matching lines...) Expand all
221 ->RemoveObserver(this); 234 ->RemoveObserver(this);
222 MaybeInitializeNetwork(); 235 MaybeInitializeNetwork();
223 } 236 }
224 237
225 void StartupAppLauncher::OnRefreshTokensLoaded() { 238 void StartupAppLauncher::OnRefreshTokensLoaded() {
226 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_) 239 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
227 ->RemoveObserver(this); 240 ->RemoveObserver(this);
228 MaybeInitializeNetwork(); 241 MaybeInitializeNetwork();
229 } 242 }
230 243
244 void StartupAppLauncher::MaybeLaunchApp() {
245 // Check if the app is offline enabled.
246 const Extension* extension = extensions::ExtensionSystem::Get(profile_)
247 ->extension_service()
248 ->GetInstalledExtension(app_id_);
249 DCHECK(extension);
250 const bool offline_enabled =
251 extensions::OfflineEnabledInfo::IsOfflineEnabled(extension);
252 if (offline_enabled || delegate_->IsNetworkReady()) {
253 BrowserThread::PostTask(
254 BrowserThread::UI,
255 FROM_HERE,
256 base::Bind(&StartupAppLauncher::OnReadyToLaunch, AsWeakPtr()));
257 } else {
258 ++launch_attempt_;
259 if (launch_attempt_ < kMaxLaunchAttempt) {
260 BrowserThread::PostTask(
261 BrowserThread::UI,
262 FROM_HERE,
263 base::Bind(&StartupAppLauncher::MaybeInitializeNetwork, AsWeakPtr()));
264 return;
265 }
266 OnLaunchFailure(KioskAppLaunchError::UNABLE_TO_LAUNCH);
267 }
268 }
269
270 void StartupAppLauncher::OnFinishCrxInstall(const std::string& extension_id,
271 bool success) {
272 if (extension_id != app_id_)
273 return;
274
275 extensions::InstallTracker* tracker =
276 extensions::InstallTrackerFactory::GetForProfile(profile_);
277 tracker->RemoveObserver(this);
278 if (delegate_->IsShowingNetworkConfigScreen()) {
279 LOG(WARNING) << "Showing network config screen";
280 return;
281 }
282
283 if (success) {
284 MaybeLaunchApp();
285 return;
286 }
287
288 LOG(ERROR) << "Failed to install the kiosk application app_id: "
289 << extension_id;
290 OnLaunchFailure(KioskAppLaunchError::UNABLE_TO_INSTALL);
291 }
292
293 void StartupAppLauncher::OnKioskExtensionLoadedInCache(
294 const std::string& app_id) {
295 OnKioskAppDataLoadStatusChanged(app_id);
296 }
297
298 void StartupAppLauncher::OnKioskExtensionDownloadFailed(
299 const std::string& app_id) {
300 OnKioskAppDataLoadStatusChanged(app_id);
301 }
302
303 void StartupAppLauncher::OnKioskAppDataLoadStatusChanged(
304 const std::string& app_id) {
305 if (app_id != app_id_ || !wait_for_crx_update_)
306 return;
307
308 wait_for_crx_update_ = false;
309 if (KioskAppManager::Get()->HasCachedCrx(app_id_))
310 BeginInstall();
311 else
312 OnLaunchFailure(KioskAppLaunchError::UNABLE_TO_DOWNLOAD);
313 }
314
231 void StartupAppLauncher::LaunchApp() { 315 void StartupAppLauncher::LaunchApp() {
232 if (!ready_to_launch_) { 316 if (!ready_to_launch_) {
233 NOTREACHED(); 317 NOTREACHED();
234 LOG(ERROR) << "LaunchApp() called but launcher is not initialized."; 318 LOG(ERROR) << "LaunchApp() called but launcher is not initialized.";
235 } 319 }
236 320
237 const Extension* extension = extensions::ExtensionSystem::Get(profile_)-> 321 const Extension* extension = extensions::ExtensionSystem::Get(profile_)->
238 extension_service()->GetInstalledExtension(app_id_); 322 extension_service()->GetInstalledExtension(app_id_);
239 CHECK(extension); 323 CHECK(extension);
240 324
(...skipping 25 matching lines...) Expand all
266 delegate_->OnLaunchSucceeded(); 350 delegate_->OnLaunchSucceeded();
267 } 351 }
268 352
269 void StartupAppLauncher::OnLaunchFailure(KioskAppLaunchError::Error error) { 353 void StartupAppLauncher::OnLaunchFailure(KioskAppLaunchError::Error error) {
270 LOG(ERROR) << "App launch failed, error: " << error; 354 LOG(ERROR) << "App launch failed, error: " << error;
271 DCHECK_NE(KioskAppLaunchError::NONE, error); 355 DCHECK_NE(KioskAppLaunchError::NONE, error);
272 356
273 delegate_->OnLaunchFailed(error); 357 delegate_->OnLaunchFailed(error);
274 } 358 }
275 359
276 void StartupAppLauncher::MaybeInstall() {
277 delegate_->OnInstallingApp();
278
279 ExtensionService* extension_service =
280 extensions::ExtensionSystem::Get(profile_)->extension_service();
281 if (!extension_service->GetInstalledExtension(app_id_)) {
282 BeginInstall();
283 return;
284 }
285
286 extensions::ExtensionUpdater::CheckParams check_params;
287 check_params.ids.push_back(app_id_);
288 check_params.install_immediately = true;
289 check_params.callback =
290 base::Bind(&StartupAppLauncher::OnUpdateCheckFinished, AsWeakPtr());
291 extension_service->updater()->CheckNow(check_params);
292 }
293
294 void StartupAppLauncher::OnUpdateCheckFinished() { 360 void StartupAppLauncher::OnUpdateCheckFinished() {
295 OnReadyToLaunch(); 361 OnReadyToLaunch();
296 UpdateAppData(); 362 UpdateAppData();
297 } 363 }
298 364
299 void StartupAppLauncher::BeginInstall() { 365 void StartupAppLauncher::BeginInstall() {
300 installer_ = new WebstoreStartupInstaller( 366 KioskAppManager::Get()->InstallFromCache(app_id_);
301 app_id_, 367 if (extensions::ExtensionSystem::Get(profile_)
302 profile_, 368 ->extension_service()
303 false, 369 ->pending_extension_manager()
304 base::Bind(&StartupAppLauncher::InstallCallback, AsWeakPtr())); 370 ->IsIdPending(app_id_)) {
305 installer_->BeginInstall(); 371 delegate_->OnInstallingApp();
306 } 372 // Observe the crx installation events.
307 373 extensions::InstallTracker* tracker =
308 void StartupAppLauncher::InstallCallback(bool success, 374 extensions::InstallTrackerFactory::GetForProfile(profile_);
309 const std::string& error) { 375 tracker->AddObserver(this);
310 installer_ = NULL;
311 if (delegate_->IsShowingNetworkConfigScreen()) {
312 LOG(WARNING) << "Showing network config screen";
313 return; 376 return;
314 } 377 }
315 378
316 if (success) { 379 if (extensions::ExtensionSystem::Get(profile_)
317 // Finish initialization after the callback returns. 380 ->extension_service()
318 // So that the app finishes its installation. 381 ->GetInstalledExtension(app_id_)) {
319 BrowserThread::PostTask( 382 // Launch the app.
320 BrowserThread::UI, 383 OnReadyToLaunch();
321 FROM_HERE, 384 } else {
322 base::Bind(&StartupAppLauncher::OnReadyToLaunch, 385 // The extension is skipped for installation due to some error.
323 AsWeakPtr())); 386 OnLaunchFailure(KioskAppLaunchError::UNABLE_TO_INSTALL);
324 return;
325 } 387 }
326
327 LOG(ERROR) << "App install failed: " << error
328 << ", for attempt " << install_attempt_;
329
330 ++install_attempt_;
331 if (install_attempt_ < kMaxInstallAttempt) {
332 BrowserThread::PostTask(
333 BrowserThread::UI,
334 FROM_HERE,
335 base::Bind(&StartupAppLauncher::MaybeInitializeNetwork,
336 AsWeakPtr()));
337 return;
338 }
339
340 OnLaunchFailure(KioskAppLaunchError::UNABLE_TO_INSTALL);
341 } 388 }
342 389
343 void StartupAppLauncher::OnReadyToLaunch() { 390 void StartupAppLauncher::OnReadyToLaunch() {
344 ready_to_launch_ = true; 391 ready_to_launch_ = true;
345 delegate_->OnReadyToLaunch(); 392 delegate_->OnReadyToLaunch();
346 } 393 }
347 394
348 void StartupAppLauncher::UpdateAppData() { 395 void StartupAppLauncher::UpdateAppData() {
349 KioskAppManager::Get()->ClearAppData(app_id_); 396 KioskAppManager::Get()->ClearAppData(app_id_);
350 KioskAppManager::Get()->UpdateAppDataFromProfile(app_id_, profile_, NULL); 397 KioskAppManager::Get()->UpdateAppDataFromProfile(app_id_, profile_, NULL);
351 } 398 }
352 399
353 } // namespace chromeos 400 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/app_mode/startup_app_launcher.h ('k') | chrome/browser/chromeos/extensions/external_cache.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698