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

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: for #1 comments, use default for empty update url and skip for bad update url 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
« no previous file with comments | « chrome/browser/chromeos/app_mode/startup_app_launcher.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 if (update_url.is_empty())
79 update_url = extension_urls::GetWebstoreUpdateUrl();
80 if (!update_url.is_valid()) {
81 launcher_->OnUpdateCheckNoUpdate();
82 return;
83 }
84
85 manifest_fetch_data_.reset(
86 new extensions::ManifestFetchData(update_url, 0));
87 manifest_fetch_data_->AddExtension(
88 app_id_, app->version()->GetString(), NULL, "", "");
89
90 manifest_fetcher_.reset(net::URLFetcher::Create(
91 manifest_fetch_data_->full_url(), net::URLFetcher::GET, this));
92 manifest_fetcher_->SetRequestContext(profile_->GetRequestContext());
93 manifest_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
94 net::LOAD_DO_NOT_SAVE_COOKIES |
95 net::LOAD_DISABLE_CACHE);
96 manifest_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3);
97 manifest_fetcher_->Start();
98 }
99
100 private:
101 const Extension* GetInstalledApp() {
102 ExtensionService* extension_service =
103 extensions::ExtensionSystem::Get(profile_)->extension_service();
104 return extension_service->GetInstalledExtension(app_id_);
105 }
106
107 void HandleManifestResults(const extensions::ManifestFetchData& fetch_data,
108 const UpdateManifest::Results* results) {
109 if (!results || results->list.empty()) {
110 launcher_->OnUpdateCheckNoUpdate();
111 return;
112 }
113
114 DCHECK_EQ(1u, results->list.size());
115
116 const UpdateManifest::Result& update = results->list[0];
117
118 if (update.browser_min_version.length() > 0) {
119 Version browser_version;
120 chrome::VersionInfo version_info;
121 if (version_info.is_valid())
122 browser_version = Version(version_info.Version());
123
124 Version browser_min_version(update.browser_min_version);
125 if (browser_version.IsValid() &&
126 browser_min_version.IsValid() &&
127 browser_min_version.CompareTo(browser_version) > 0) {
128 launcher_->OnUpdateCheckNoUpdate();
129 return;
130 }
131 }
132
133 const Version& existing_version = *GetInstalledApp()->version();
134 Version update_version(update.version);
135 if (existing_version.IsValid() &&
136 update_version.IsValid() &&
137 update_version.CompareTo(existing_version) <= 0) {
138 launcher_->OnUpdateCheckNoUpdate();
139 return;
140 }
141
142 launcher_->OnUpdateCheckUpdateAvailable();
143 }
144
145 // net::URLFetcherDelegate implementation.
146 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
147 DCHECK_EQ(source, manifest_fetcher_.get());
148
149 if (source->GetStatus().status() != net::URLRequestStatus::SUCCESS ||
150 source->GetResponseCode() != 200) {
151 launcher_->OnUpdateCheckNoUpdate();
152 return;
153 }
154
155 std::string data;
156 source->GetResponseAsString(&data);
157 scoped_refptr<extensions::SafeManifestParser> safe_parser(
158 new extensions::SafeManifestParser(
159 data,
160 manifest_fetch_data_.release(),
161 base::Bind(&AppUpdateChecker::HandleManifestResults,
162 AsWeakPtr())));
163 safe_parser->Start();
164 }
165
166 StartupAppLauncher* launcher_;
167 Profile* profile_;
168 const std::string app_id_;
169
170 scoped_ptr<extensions::ManifestFetchData> manifest_fetch_data_;
171 scoped_ptr<net::URLFetcher> manifest_fetcher_;
172
173 DISALLOW_COPY_AND_ASSIGN(AppUpdateChecker);
174 };
55 175
56 StartupAppLauncher::StartupAppLauncher(Profile* profile, 176 StartupAppLauncher::StartupAppLauncher(Profile* profile,
57 const std::string& app_id, 177 const std::string& app_id,
58 StartupAppLauncher::Delegate* delegate) 178 StartupAppLauncher::Delegate* delegate)
59 : profile_(profile), 179 : profile_(profile),
60 app_id_(app_id), 180 app_id_(app_id),
61 delegate_(delegate), 181 delegate_(delegate),
62 install_attempted_(false), 182 install_attempted_(false),
63 ready_to_launch_(false) { 183 ready_to_launch_(false) {
64 DCHECK(profile_); 184 DCHECK(profile_);
65 DCHECK(Extension::IdIsValid(app_id_)); 185 DCHECK(Extension::IdIsValid(app_id_));
66 } 186 }
67 187
68 StartupAppLauncher::~StartupAppLauncher() { 188 StartupAppLauncher::~StartupAppLauncher() {
69 // StartupAppLauncher can be deleted at anytime during the launch process 189 // StartupAppLauncher can be deleted at anytime during the launch process
70 // through a user bailout shortcut. 190 // through a user bailout shortcut.
71 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_) 191 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
72 ->RemoveObserver(this); 192 ->RemoveObserver(this);
73 } 193 }
74 194
75 void StartupAppLauncher::Initialize() { 195 void StartupAppLauncher::Initialize() {
76 StartLoadingOAuthFile(); 196 StartLoadingOAuthFile();
77 } 197 }
78 198
79 void StartupAppLauncher::ContinueWithNetworkReady() { 199 void StartupAppLauncher::ContinueWithNetworkReady() {
80 // Starts install if it is not started. 200 // Starts install if it is not started.
81 if (!install_attempted_) { 201 if (!install_attempted_) {
82 install_attempted_ = true; 202 install_attempted_ = true;
83 BeginInstall(); 203 MaybeInstall();
84 } 204 }
85 } 205 }
86 206
87 void StartupAppLauncher::StartLoadingOAuthFile() { 207 void StartupAppLauncher::StartLoadingOAuthFile() {
88 delegate_->OnLoadingOAuthFile(); 208 delegate_->OnLoadingOAuthFile();
89 209
90 KioskOAuthParams* auth_params = new KioskOAuthParams(); 210 KioskOAuthParams* auth_params = new KioskOAuthParams();
91 BrowserThread::PostBlockingPoolTaskAndReply( 211 BrowserThread::PostBlockingPoolTaskAndReply(
92 FROM_HERE, 212 FROM_HERE,
93 base::Bind(&StartupAppLauncher::LoadOAuthFileOnBlockingPool, 213 base::Bind(&StartupAppLauncher::LoadOAuthFileOnBlockingPool,
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 ->RemoveObserver(this); 296 ->RemoveObserver(this);
177 InitializeNetwork(); 297 InitializeNetwork();
178 } 298 }
179 299
180 void StartupAppLauncher::OnRefreshTokensLoaded() { 300 void StartupAppLauncher::OnRefreshTokensLoaded() {
181 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_) 301 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
182 ->RemoveObserver(this); 302 ->RemoveObserver(this);
183 InitializeNetwork(); 303 InitializeNetwork();
184 } 304 }
185 305
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() { 306 void StartupAppLauncher::LaunchApp() {
198 if (!ready_to_launch_) { 307 if (!ready_to_launch_) {
199 NOTREACHED(); 308 NOTREACHED();
200 LOG(ERROR) << "LaunchApp() called but launcher is not initialized."; 309 LOG(ERROR) << "LaunchApp() called but launcher is not initialized.";
201 } 310 }
202 311
203 const Extension* extension = extensions::ExtensionSystem::Get(profile_)-> 312 const Extension* extension = extensions::ExtensionSystem::Get(profile_)->
204 extension_service()->GetInstalledExtension(app_id_); 313 extension_service()->GetInstalledExtension(app_id_);
205 CHECK(extension); 314 CHECK(extension);
206 315
(...skipping 11 matching lines...) Expand all
218 UserManager::Get()->SessionStarted(); 327 UserManager::Get()->SessionStarted();
219 328
220 content::NotificationService::current()->Notify( 329 content::NotificationService::current()->Notify(
221 chrome::NOTIFICATION_KIOSK_APP_LAUNCHED, 330 chrome::NOTIFICATION_KIOSK_APP_LAUNCHED,
222 content::NotificationService::AllSources(), 331 content::NotificationService::AllSources(),
223 content::NotificationService::NoDetails()); 332 content::NotificationService::NoDetails());
224 333
225 OnLaunchSuccess(); 334 OnLaunchSuccess();
226 } 335 }
227 336
228 void StartupAppLauncher::BeginInstall() { 337 void StartupAppLauncher::OnLaunchSuccess() {
338 delegate_->OnLaunchSucceeded();
339 }
340
341 void StartupAppLauncher::OnLaunchFailure(KioskAppLaunchError::Error error) {
342 LOG(ERROR) << "App launch failed, error: " << error;
343 DCHECK_NE(KioskAppLaunchError::NONE, error);
344
345 delegate_->OnLaunchFailed(error);
346 }
347
348 void StartupAppLauncher::MaybeInstall() {
229 delegate_->OnInstallingApp(); 349 delegate_->OnInstallingApp();
230 350
231 if (IsAppInstalled(profile_, app_id_)) { 351 update_checker_.reset(new AppUpdateChecker(this));
232 OnReadyToLaunch(); 352 update_checker_->Start();
233 return; 353 }
234 }
235 354
355 void StartupAppLauncher::OnUpdateCheckNotInstalled() {
356 BeginInstall();
357 }
358
359 void StartupAppLauncher::OnUpdateCheckUpdateAvailable() {
360 // Uninstall to force a re-install.
361 // TODO(xiyuan): Find a better way. Either download CRX and install it
362 // directly or integrate with ExtensionUpdater in someway.
363 ExtensionService* extension_service =
364 extensions::ExtensionSystem::Get(profile_)->extension_service();
365 extension_service->UninstallExtension(app_id_, false, NULL);
366
367 OnUpdateCheckNotInstalled();
368 }
369
370 void StartupAppLauncher::OnUpdateCheckNoUpdate() {
371 OnReadyToLaunch();
372 }
373
374 void StartupAppLauncher::BeginInstall() {
236 installer_ = new WebstoreStartupInstaller( 375 installer_ = new WebstoreStartupInstaller(
237 app_id_, 376 app_id_,
238 profile_, 377 profile_,
239 false, 378 false,
240 base::Bind(&StartupAppLauncher::InstallCallback, AsWeakPtr())); 379 base::Bind(&StartupAppLauncher::InstallCallback, AsWeakPtr()));
241 installer_->BeginInstall(); 380 installer_->BeginInstall();
242 } 381 }
243 382
244 void StartupAppLauncher::InstallCallback(bool success, 383 void StartupAppLauncher::InstallCallback(bool success,
245 const std::string& error) { 384 const std::string& error) {
246 installer_ = NULL; 385 installer_ = NULL;
247 if (success) { 386 if (success) {
248 // Finish initialization after the callback returns. 387 // Finish initialization after the callback returns.
249 // So that the app finishes its installation. 388 // So that the app finishes its installation.
250 BrowserThread::PostTask( 389 BrowserThread::PostTask(
251 BrowserThread::UI, 390 BrowserThread::UI,
252 FROM_HERE, 391 FROM_HERE,
253 base::Bind(&StartupAppLauncher::OnReadyToLaunch, 392 base::Bind(&StartupAppLauncher::OnReadyToLaunch,
254 AsWeakPtr())); 393 AsWeakPtr()));
394
395 // Schedule app data update after installation.
396 BrowserThread::PostTask(
397 BrowserThread::UI,
398 FROM_HERE,
399 base::Bind(&StartupAppLauncher::UpdateAppData,
400 AsWeakPtr()));
255 return; 401 return;
256 } 402 }
257 403
258 LOG(ERROR) << "App install failed: " << error; 404 LOG(ERROR) << "App install failed: " << error;
259 OnLaunchFailure(KioskAppLaunchError::UNABLE_TO_INSTALL); 405 OnLaunchFailure(KioskAppLaunchError::UNABLE_TO_INSTALL);
260 } 406 }
261 407
262 void StartupAppLauncher::OnReadyToLaunch() { 408 void StartupAppLauncher::OnReadyToLaunch() {
263 ready_to_launch_ = true; 409 ready_to_launch_ = true;
264 delegate_->OnReadyToLaunch(); 410 delegate_->OnReadyToLaunch();
265 } 411 }
266 412
413 void StartupAppLauncher::UpdateAppData() {
414 KioskAppManager::Get()->ClearAppData(app_id_);
415 KioskAppManager::Get()->UpdateAppDataFromProfile(app_id_, profile_, NULL);
416 }
417
267 } // namespace chromeos 418 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/app_mode/startup_app_launcher.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698