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

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

Issue 137343003: kiosk: Do update check during launch. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 11 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/login/user_manager.h" 16 #include "chrome/browser/chromeos/login/user_manager.h"
17 #include "chrome/browser/extensions/extension_service.h" 17 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/extensions/extension_system.h" 18 #include "chrome/browser/extensions/extension_system.h"
19 #include "chrome/browser/extensions/updater/manifest_fetch_data.h"
20 #include "chrome/browser/extensions/updater/safe_manifest_parser.h"
19 #include "chrome/browser/extensions/webstore_startup_installer.h" 21 #include "chrome/browser/extensions/webstore_startup_installer.h"
20 #include "chrome/browser/lifetime/application_lifetime.h" 22 #include "chrome/browser/lifetime/application_lifetime.h"
21 #include "chrome/browser/signin/profile_oauth2_token_service.h" 23 #include "chrome/browser/signin/profile_oauth2_token_service.h"
22 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 24 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
23 #include "chrome/browser/ui/extensions/application_launch.h" 25 #include "chrome/browser/ui/extensions/application_launch.h"
24 #include "chrome/common/chrome_paths.h" 26 #include "chrome/common/chrome_paths.h"
25 #include "chrome/common/chrome_switches.h" 27 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/chrome_version_info.h"
29 #include "chrome/common/extensions/manifest_url_handler.h"
26 #include "content/public/browser/browser_thread.h" 30 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/notification_service.h" 31 #include "content/public/browser/notification_service.h"
28 #include "extensions/common/extension.h" 32 #include "extensions/common/extension.h"
29 #include "extensions/common/manifest_handlers/kiosk_mode_info.h" 33 #include "extensions/common/manifest_handlers/kiosk_mode_info.h"
30 #include "google_apis/gaia/gaia_auth_consumer.h" 34 #include "google_apis/gaia/gaia_auth_consumer.h"
31 #include "google_apis/gaia/gaia_constants.h" 35 #include "google_apis/gaia/gaia_constants.h"
36 #include "net/base/load_flags.h"
37 #include "net/url_request/url_fetcher.h"
38 #include "net/url_request/url_fetcher_delegate.h"
39 #include "net/url_request/url_request_context_getter.h"
40 #include "net/url_request/url_request_status.h"
41 #include "url/gurl.h"
32 42
33 using content::BrowserThread; 43 using content::BrowserThread;
34 using extensions::Extension; 44 using extensions::Extension;
35 using extensions::WebstoreStartupInstaller; 45 using extensions::WebstoreStartupInstaller;
36 46
37 namespace chromeos { 47 namespace chromeos {
38 48
39 namespace { 49 namespace {
40 50
41 const char kOAuthRefreshToken[] = "refresh_token"; 51 const char kOAuthRefreshToken[] = "refresh_token";
42 const char kOAuthClientId[] = "client_id"; 52 const char kOAuthClientId[] = "client_id";
43 const char kOAuthClientSecret[] = "client_secret"; 53 const char kOAuthClientSecret[] = "client_secret";
44 54
45 const base::FilePath::CharType kOAuthFileName[] = 55 const base::FilePath::CharType kOAuthFileName[] =
46 FILE_PATH_LITERAL("kiosk_auth"); 56 FILE_PATH_LITERAL("kiosk_auth");
47 57
48 bool IsAppInstalled(Profile* profile, const std::string& app_id) {
49 return extensions::ExtensionSystem::Get(profile)->extension_service()->
50 GetInstalledExtension(app_id);
51 }
52
53 } // namespace 58 } // namespace
54 59
60 class StartupAppLauncher::AppUpdateChecker
61 : public base::SupportsWeakPtr<AppUpdateChecker>,
62 public net::URLFetcherDelegate {
63 public:
64 explicit AppUpdateChecker(StartupAppLauncher* launcher)
65 : launcher_(launcher),
66 profile_(launcher->profile_),
67 app_id_(launcher->app_id_) {}
68 virtual ~AppUpdateChecker() {}
69
70 void Start() {
71 const Extension* app = GetInstalledApp();
72 if (!app) {
73 launcher_->OnUpdateCheckNotInstalled();
74 return;
75 }
76
77 GURL update_url = extensions::ManifestURL::GetUpdateURL(app);
78 manifest_fetch_data_.reset(
79 new extensions::ManifestFetchData(update_url, 0));
80 manifest_fetch_data_->AddExtension(
81 app_id_, app->version()->GetString(), NULL, "", "");
82
83 manifest_fetcher_.reset(net::URLFetcher::Create(
84 manifest_fetch_data_->full_url(), net::URLFetcher::GET, this));
85 manifest_fetcher_->SetRequestContext(profile_->GetRequestContext());
86 manifest_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
87 net::LOAD_DO_NOT_SAVE_COOKIES |
88 net::LOAD_DISABLE_CACHE);
89 manifest_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3);
90 manifest_fetcher_->Start();
91 }
92
93 private:
94 const Extension* GetInstalledApp() {
95 ExtensionService* extension_service =
96 extensions::ExtensionSystem::Get(profile_)->extension_service();
97 return extension_service->GetInstalledExtension(app_id_);
98 }
99
100 void HandleManifestResults(const extensions::ManifestFetchData& fetch_data,
101 const UpdateManifest::Results* results) {
102 if (!results || results->list.empty()) {
103 launcher_->OnUpdateCheckNoUpdate();
104 return;
105 }
106
107 DCHECK_EQ(1u, results->list.size());
108
109 const UpdateManifest::Result& update = results->list[0];
110
111 if (update.browser_min_version.length() > 0) {
112 Version browser_version;
113 chrome::VersionInfo version_info;
114 if (version_info.is_valid())
115 browser_version = Version(version_info.Version());
116
117 Version browser_min_version(update.browser_min_version);
118 if (browser_version.IsValid() &&
119 browser_min_version.IsValid() &&
120 browser_min_version.CompareTo(browser_version) > 0) {
121 launcher_->OnUpdateCheckNoUpdate();
122 return;
123 }
124 }
125
126 const Version& existing_version = *GetInstalledApp()->version();
127 Version update_version(update.version);
128 if (existing_version.IsValid() &&
129 update_version.IsValid() &&
130 update_version.CompareTo(existing_version) <= 0) {
131 launcher_->OnUpdateCheckNoUpdate();
132 return;
133 }
134
135 launcher_->OnUpdateCheckUpdateAvailable();
136 }
137
138 // net::URLFetcherDelegate implementation.
139 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
140 DCHECK_EQ(source, manifest_fetcher_.get());
141
142 if (source->GetStatus().status() != net::URLRequestStatus::SUCCESS ||
143 source->GetResponseCode() != 200) {
144 launcher_->OnUpdateCheckNoUpdate();
145 return;
146 }
147
148 std::string data;
149 source->GetResponseAsString(&data);
150 scoped_refptr<extensions::SafeManifestParser> safe_parser(
151 new extensions::SafeManifestParser(
152 data,
153 manifest_fetch_data_.release(),
154 base::Bind(&AppUpdateChecker::HandleManifestResults,
155 AsWeakPtr())));
156 safe_parser->Start();
157 }
158
159 StartupAppLauncher* launcher_;
160 Profile* profile_;
161 const std::string app_id_;
162
163 scoped_ptr<extensions::ManifestFetchData> manifest_fetch_data_;
164 scoped_ptr<net::URLFetcher> manifest_fetcher_;
165
166 DISALLOW_COPY_AND_ASSIGN(AppUpdateChecker);
167 };
55 168
56 StartupAppLauncher::StartupAppLauncher(Profile* profile, 169 StartupAppLauncher::StartupAppLauncher(Profile* profile,
57 const std::string& app_id, 170 const std::string& app_id,
58 StartupAppLauncher::Delegate* delegate) 171 StartupAppLauncher::Delegate* delegate)
59 : profile_(profile), 172 : profile_(profile),
60 app_id_(app_id), 173 app_id_(app_id),
61 delegate_(delegate), 174 delegate_(delegate),
62 install_attempted_(false), 175 install_attempted_(false),
63 ready_to_launch_(false) { 176 ready_to_launch_(false) {
64 DCHECK(profile_); 177 DCHECK(profile_);
65 DCHECK(Extension::IdIsValid(app_id_)); 178 DCHECK(Extension::IdIsValid(app_id_));
66 } 179 }
67 180
68 StartupAppLauncher::~StartupAppLauncher() { 181 StartupAppLauncher::~StartupAppLauncher() {
69 // StartupAppLauncher can be deleted at anytime during the launch process 182 // StartupAppLauncher can be deleted at anytime during the launch process
70 // through a user bailout shortcut. 183 // through a user bailout shortcut.
71 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_) 184 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
72 ->RemoveObserver(this); 185 ->RemoveObserver(this);
73 } 186 }
74 187
75 void StartupAppLauncher::Initialize() { 188 void StartupAppLauncher::Initialize() {
76 StartLoadingOAuthFile(); 189 StartLoadingOAuthFile();
77 } 190 }
78 191
79 void StartupAppLauncher::ContinueWithNetworkReady() { 192 void StartupAppLauncher::ContinueWithNetworkReady() {
80 // Starts install if it is not started. 193 // Starts install if it is not started.
81 if (!install_attempted_) { 194 if (!install_attempted_) {
82 install_attempted_ = true; 195 install_attempted_ = true;
83 BeginInstall(); 196 MaybeInstall();
84 } 197 }
85 } 198 }
86 199
87 void StartupAppLauncher::StartLoadingOAuthFile() { 200 void StartupAppLauncher::StartLoadingOAuthFile() {
88 delegate_->OnLoadingOAuthFile(); 201 delegate_->OnLoadingOAuthFile();
89 202
90 KioskOAuthParams* auth_params = new KioskOAuthParams(); 203 KioskOAuthParams* auth_params = new KioskOAuthParams();
91 BrowserThread::PostBlockingPoolTaskAndReply( 204 BrowserThread::PostBlockingPoolTaskAndReply(
92 FROM_HERE, 205 FROM_HERE,
93 base::Bind(&StartupAppLauncher::LoadOAuthFileOnBlockingPool, 206 base::Bind(&StartupAppLauncher::LoadOAuthFileOnBlockingPool,
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 ->RemoveObserver(this); 289 ->RemoveObserver(this);
177 InitializeNetwork(); 290 InitializeNetwork();
178 } 291 }
179 292
180 void StartupAppLauncher::OnRefreshTokensLoaded() { 293 void StartupAppLauncher::OnRefreshTokensLoaded() {
181 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_) 294 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
182 ->RemoveObserver(this); 295 ->RemoveObserver(this);
183 InitializeNetwork(); 296 InitializeNetwork();
184 } 297 }
185 298
186 void StartupAppLauncher::OnLaunchSuccess() {
187 delegate_->OnLaunchSucceeded();
188 }
189
190 void StartupAppLauncher::OnLaunchFailure(KioskAppLaunchError::Error error) {
191 LOG(ERROR) << "App launch failed, error: " << error;
192 DCHECK_NE(KioskAppLaunchError::NONE, error);
193
194 delegate_->OnLaunchFailed(error);
195 }
196
197 void StartupAppLauncher::LaunchApp() { 299 void StartupAppLauncher::LaunchApp() {
198 if (!ready_to_launch_) { 300 if (!ready_to_launch_) {
199 NOTREACHED(); 301 NOTREACHED();
200 LOG(ERROR) << "LaunchApp() called but launcher is not initialized."; 302 LOG(ERROR) << "LaunchApp() called but launcher is not initialized.";
201 } 303 }
202 304
203 const Extension* extension = extensions::ExtensionSystem::Get(profile_)-> 305 const Extension* extension = extensions::ExtensionSystem::Get(profile_)->
204 extension_service()->GetInstalledExtension(app_id_); 306 extension_service()->GetInstalledExtension(app_id_);
205 CHECK(extension); 307 CHECK(extension);
206 308
(...skipping 11 matching lines...) Expand all
218 UserManager::Get()->SessionStarted(); 320 UserManager::Get()->SessionStarted();
219 321
220 content::NotificationService::current()->Notify( 322 content::NotificationService::current()->Notify(
221 chrome::NOTIFICATION_KIOSK_APP_LAUNCHED, 323 chrome::NOTIFICATION_KIOSK_APP_LAUNCHED,
222 content::NotificationService::AllSources(), 324 content::NotificationService::AllSources(),
223 content::NotificationService::NoDetails()); 325 content::NotificationService::NoDetails());
224 326
225 OnLaunchSuccess(); 327 OnLaunchSuccess();
226 } 328 }
227 329
228 void StartupAppLauncher::BeginInstall() { 330 void StartupAppLauncher::OnLaunchSuccess() {
331 delegate_->OnLaunchSucceeded();
332 }
333
334 void StartupAppLauncher::OnLaunchFailure(KioskAppLaunchError::Error error) {
335 LOG(ERROR) << "App launch failed, error: " << error;
336 DCHECK_NE(KioskAppLaunchError::NONE, error);
337
338 delegate_->OnLaunchFailed(error);
339 }
340
341 void StartupAppLauncher::MaybeInstall() {
229 delegate_->OnInstallingApp(); 342 delegate_->OnInstallingApp();
230 343
231 if (IsAppInstalled(profile_, app_id_)) { 344 update_checker_.reset(new AppUpdateChecker(this));
232 OnReadyToLaunch(); 345 update_checker_->Start();
233 return; 346 }
234 }
235 347
348 void StartupAppLauncher::OnUpdateCheckNotInstalled() {
349 BeginInstall();
350 }
351
352 void StartupAppLauncher::OnUpdateCheckUpdateAvailable() {
353 // Uninstall to force a re-install.
354 // TODO(xiyuan): Find a better way. Either download CRX and install it
355 // directly or integrate with ExtensionUpdater in someway.
356 ExtensionService* extension_service =
357 extensions::ExtensionSystem::Get(profile_)->extension_service();
358 extension_service->UninstallExtension(app_id_, false, NULL);
359
360 OnUpdateCheckNotInstalled();
361 }
362
363 void StartupAppLauncher::OnUpdateCheckNoUpdate() {
364 OnReadyToLaunch();
365 }
366
367 void StartupAppLauncher::BeginInstall() {
236 installer_ = new WebstoreStartupInstaller( 368 installer_ = new WebstoreStartupInstaller(
237 app_id_, 369 app_id_,
238 profile_, 370 profile_,
239 false, 371 false,
240 base::Bind(&StartupAppLauncher::InstallCallback, AsWeakPtr())); 372 base::Bind(&StartupAppLauncher::InstallCallback, AsWeakPtr()));
241 installer_->BeginInstall(); 373 installer_->BeginInstall();
242 } 374 }
243 375
244 void StartupAppLauncher::InstallCallback(bool success, 376 void StartupAppLauncher::InstallCallback(bool success,
245 const std::string& error) { 377 const std::string& error) {
246 installer_ = NULL; 378 installer_ = NULL;
247 if (success) { 379 if (success) {
248 // Finish initialization after the callback returns. 380 // Finish initialization after the callback returns.
249 // So that the app finishes its installation. 381 // So that the app finishes its installation.
250 BrowserThread::PostTask( 382 BrowserThread::PostTask(
251 BrowserThread::UI, 383 BrowserThread::UI,
252 FROM_HERE, 384 FROM_HERE,
253 base::Bind(&StartupAppLauncher::OnReadyToLaunch, 385 base::Bind(&StartupAppLauncher::OnReadyToLaunch,
254 AsWeakPtr())); 386 AsWeakPtr()));
387
388 // Schedule app data update after installation.
389 BrowserThread::PostTask(
390 BrowserThread::UI,
391 FROM_HERE,
392 base::Bind(&StartupAppLauncher::UpdateAppData,
393 AsWeakPtr()));
255 return; 394 return;
256 } 395 }
257 396
258 LOG(ERROR) << "App install failed: " << error; 397 LOG(ERROR) << "App install failed: " << error;
259 OnLaunchFailure(KioskAppLaunchError::UNABLE_TO_INSTALL); 398 OnLaunchFailure(KioskAppLaunchError::UNABLE_TO_INSTALL);
260 } 399 }
261 400
262 void StartupAppLauncher::OnReadyToLaunch() { 401 void StartupAppLauncher::OnReadyToLaunch() {
263 ready_to_launch_ = true; 402 ready_to_launch_ = true;
264 delegate_->OnReadyToLaunch(); 403 delegate_->OnReadyToLaunch();
265 } 404 }
266 405
406 void StartupAppLauncher::UpdateAppData() {
Tim Song 2014/01/13 23:41:08 Can't hurt to call ClearAppData here as well.
xiyuan 2014/01/14 00:15:07 Done.
407 KioskAppManager::Get()->UpdateAppDataFromProfile(app_id_, profile_, NULL);
408 }
409
267 } // namespace chromeos 410 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698