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

Side by Side Diff: chrome/browser/component_updater/pnacl/pnacl_component_installer.cc

Issue 17001003: Replace early check for PNaCl with an on-demand check. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase again Created 7 years, 6 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/component_updater/pnacl/pnacl_component_installer.h" 5 #include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h"
6 6
7 #include "base/base_paths.h" 7 #include "base/base_paths.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/callback.h"
9 #include "base/command_line.h" 10 #include "base/command_line.h"
10 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
11 #include "base/file_util.h" 12 #include "base/file_util.h"
12 #include "base/files/file_enumerator.h" 13 #include "base/files/file_enumerator.h"
13 #include "base/files/file_path.h" 14 #include "base/files/file_path.h"
14 #include "base/json/json_file_value_serializer.h" 15 #include "base/json/json_file_value_serializer.h"
15 #include "base/logging.h" 16 #include "base/logging.h"
16 #include "base/path_service.h" 17 #include "base/path_service.h"
17 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
18 #include "base/values.h" 19 #include "base/values.h"
19 #include "base/version.h" 20 #include "base/version.h"
20 #include "base/win/windows_version.h" 21 #include "base/win/windows_version.h"
21 #include "build/build_config.h" 22 #include "build/build_config.h"
22 #include "chrome/browser/browser_process.h" 23 #include "chrome/browser/browser_process.h"
23 #include "chrome/browser/component_updater/component_updater_service.h" 24 #include "chrome/browser/component_updater/component_updater_service.h"
24 #include "chrome/browser/profiles/profile.h" 25 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/profiles/profile_manager.h" 26 #include "chrome/browser/profiles/profile_manager.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/omaha_query_params/omaha_query_params.h" 29 #include "chrome/common/omaha_query_params/omaha_query_params.h"
29 #include "content/public/browser/browser_thread.h" 30 #include "content/public/browser/browser_thread.h"
30 31
31 using chrome::OmahaQueryParams; 32 using chrome::OmahaQueryParams;
32 using content::BrowserThread; 33 using content::BrowserThread;
33 34
34 namespace { 35 namespace {
35 36
36 // If PNaCl isn't installed yet, but a user is running chrome with
37 // --enable-pnacl, this is the amount of time to wait before starting
38 // a background install.
39 const int kInitialDelaySeconds = 10;
40
41 // Name of the Pnacl component specified in the manifest. 37 // Name of the Pnacl component specified in the manifest.
42 const char kPnaclManifestName[] = "PNaCl Translator"; 38 const char kPnaclManifestName[] = "PNaCl Translator";
43 39
44 // Sanitize characters from Pnacl Arch value so that they can be used 40 // Sanitize characters from Pnacl Arch value so that they can be used
45 // in path names. This should only be characters in the set: [a-z0-9_]. 41 // in path names. This should only be characters in the set: [a-z0-9_].
46 // Keep in sync with chrome/browser/nacl_host/nacl_file_host. 42 // Keep in sync with chrome/browser/nacl_host/nacl_file_host.
47 std::string SanitizeForPath(const std::string& input) { 43 std::string SanitizeForPath(const std::string& input) {
48 std::string result; 44 std::string result;
49 ReplaceChars(input, "-", "_", &result); 45 ReplaceChars(input, "-", "_", &result);
50 return result; 46 return result;
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 << arch << " vs " << OmahaQueryParams::getNaclArch() << ")"; 183 << arch << " vs " << OmahaQueryParams::getNaclArch() << ")";
188 return false; 184 return false;
189 } 185 }
190 186
191 *version_out = version; 187 *version_out = version;
192 return true; 188 return true;
193 } 189 }
194 190
195 PnaclComponentInstaller::PnaclComponentInstaller() 191 PnaclComponentInstaller::PnaclComponentInstaller()
196 : per_user_(false), 192 : per_user_(false),
197 cus_(NULL) { 193 cus_(NULL),
194 callback_nums_(0) {
198 #if defined(OS_CHROMEOS) 195 #if defined(OS_CHROMEOS)
199 per_user_ = true; 196 per_user_ = true;
200 #endif 197 #endif
198 updater_observer_.reset(new PnaclUpdaterObserver(this));
201 } 199 }
202 200
203 PnaclComponentInstaller::~PnaclComponentInstaller() { 201 PnaclComponentInstaller::~PnaclComponentInstaller() {
204 } 202 }
205 203
206 void PnaclComponentInstaller::OnUpdateError(int error) { 204 void PnaclComponentInstaller::OnUpdateError(int error) {
207 NOTREACHED() << "Pnacl update error: " << error; 205 NOTREACHED() << "Pnacl update error: " << error;
208 } 206 }
209 207
210 // Pnacl components have the version encoded in the path itself: 208 // Pnacl components have the version encoded in the path itself:
(...skipping 23 matching lines...) Expand all
234 // On chromeos, we want to find the --login-profile=<foo> dir. 232 // On chromeos, we want to find the --login-profile=<foo> dir.
235 // Even though the path does vary between users, the content 233 // Even though the path does vary between users, the content
236 // changes when logging out and logging in. 234 // changes when logging out and logging in.
237 ProfileManager* pm = g_browser_process->profile_manager(); 235 ProfileManager* pm = g_browser_process->profile_manager();
238 current_profile_path_ = pm->user_data_dir().Append( 236 current_profile_path_ = pm->user_data_dir().Append(
239 pm->GetInitialProfileDir()); 237 pm->GetInitialProfileDir());
240 } 238 }
241 239
242 bool PnaclComponentInstaller::Install(const base::DictionaryValue& manifest, 240 bool PnaclComponentInstaller::Install(const base::DictionaryValue& manifest,
243 const base::FilePath& unpack_path) { 241 const base::FilePath& unpack_path) {
242 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
244 scoped_ptr<base::DictionaryValue> pnacl_manifest( 243 scoped_ptr<base::DictionaryValue> pnacl_manifest(
245 ReadPnaclManifest(unpack_path)); 244 ReadPnaclManifest(unpack_path));
246 if (pnacl_manifest == NULL) { 245 if (pnacl_manifest == NULL) {
247 LOG(WARNING) << "Failed to read pnacl manifest."; 246 LOG(WARNING) << "Failed to read pnacl manifest.";
247 NotifyInstallError();
248 return false; 248 return false;
249 } 249 }
250 250
251 Version version; 251 Version version;
252 if (!CheckPnaclComponentManifest(manifest, *pnacl_manifest, &version)) { 252 if (!CheckPnaclComponentManifest(manifest, *pnacl_manifest, &version)) {
253 LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing."; 253 LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing.";
254 NotifyInstallError();
254 return false; 255 return false;
255 } 256 }
256 257
257 // Don't install if the current version is actually newer. 258 // Don't install if the current version is actually newer.
258 if (current_version().CompareTo(version) > 0) 259 if (current_version().CompareTo(version) > 0) {
260 NotifyInstallError();
259 return false; 261 return false;
262 }
260 263
261 // Passed the basic tests. Time to install it. 264 // Passed the basic tests. Time to install it.
262 base::FilePath path = GetPnaclBaseDirectory().AppendASCII( 265 base::FilePath path = GetPnaclBaseDirectory().AppendASCII(
263 version.GetString()); 266 version.GetString());
264 if (file_util::PathExists(path)) { 267 if (file_util::PathExists(path)) {
265 LOG(WARNING) << "Target path already exists, not installing."; 268 LOG(WARNING) << "Target path already exists, not installing.";
269 NotifyInstallError();
266 return false; 270 return false;
267 } 271 }
268 if (!file_util::Move(unpack_path, path)) { 272 if (!file_util::Move(unpack_path, path)) {
269 LOG(WARNING) << "Move failed, not installing."; 273 LOG(WARNING) << "Move failed, not installing.";
274 NotifyInstallError();
270 return false; 275 return false;
271 } 276 }
272 277
273 // Installation is done. Now tell the rest of chrome (just the path service 278 // Installation is done. Now tell the rest of chrome.
274 // for now). TODO(jvoung): we need notifications if someone surfed to a 279 // - The path service.
275 // Pnacl webpage and Pnacl was just installed at this time. They should 280 // - Callbacks that requested an update.
276 // then be able to reload the page and retry (or something).
277 // See: http://code.google.com/p/chromium/issues/detail?id=107438
278 set_current_version(version); 281 set_current_version(version);
279 282 NotifyInstallSuccess();
280 OverrideDirPnaclComponent(path); 283 OverrideDirPnaclComponent(path);
281 return true; 284 return true;
282 } 285 }
283 286
284 bool PnaclComponentInstaller::GetInstalledFile( 287 bool PnaclComponentInstaller::GetInstalledFile(
285 const std::string& file, base::FilePath* installed_file) { 288 const std::string& file, base::FilePath* installed_file) {
286 return false; 289 return false;
287 } 290 }
288 291
292 void PnaclComponentInstaller::AddInstallCallback(
293 const InstallCallback& cb) {
294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
295 int num = ++callback_nums_;
296 install_callbacks_.push_back(std::make_pair(cb, num));
297 }
298
299 void PnaclComponentInstaller::CancelCallback(int num) {
300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
301 for (std::list<std::pair<InstallCallback, int> >::iterator
302 i = install_callbacks_.begin(),
303 e = install_callbacks_.end(); i != e; ++i) {
304 if (i->second == num) {
305 i->first.Run(false);
306 install_callbacks_.erase(i);
307 return;
308 }
309 }
310 }
311
312 void PnaclComponentInstaller::NotifyAllWithResult(bool status) {
313 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
314 while (!install_callbacks_.empty()) {
315 install_callbacks_.front().first.Run(status);
316 install_callbacks_.pop_front();
317 }
318 }
319
320 void PnaclComponentInstaller::NotifyInstallError() {
321 if (!install_callbacks_.empty()) {
322 BrowserThread::PostTask(
323 BrowserThread::UI, FROM_HERE,
324 base::Bind(&PnaclComponentInstaller::NotifyAllWithResult,
325 // Unretained because installer lives until process shutdown.
326 base::Unretained(this), false));
327 }
328 }
329
330 void PnaclComponentInstaller::NotifyInstallSuccess() {
331 if (!install_callbacks_.empty()) {
332 BrowserThread::PostTask(
333 BrowserThread::UI, FROM_HERE,
334 base::Bind(&PnaclComponentInstaller::NotifyAllWithResult,
335 // Unretained because installer lives until process shutdown.
336 base::Unretained(this), true));
337 }
338 }
339
289 namespace { 340 namespace {
290 341
291 void DoCheckForUpdate(ComponentUpdateService* cus,
292 const CrxComponent& pnacl) {
293 if (cus->CheckForUpdateSoon(pnacl) != ComponentUpdateService::kOk) {
294 LOG(WARNING) << "Pnacl check for update failed.";
295 }
296 }
297
298 // Finally, do the registration with the right version number.
299 void FinishPnaclUpdateRegistration(const Version& current_version, 342 void FinishPnaclUpdateRegistration(const Version& current_version,
300 PnaclComponentInstaller* pci) { 343 PnaclComponentInstaller* pci) {
301 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 344 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
302 CrxComponent pnacl_component; 345 CrxComponent pnacl_component;
303 pnacl_component.version = current_version; 346 pnacl_component.version = current_version;
304 pnacl_component.name = "pnacl"; 347 pnacl_component.name = "pnacl";
305 pnacl_component.installer = pci; 348 pnacl_component.installer = pci;
306 pci->set_current_version(current_version); 349 pci->set_current_version(current_version);
307 SetPnaclHash(&pnacl_component); 350 SetPnaclHash(&pnacl_component);
308 351
309 ComponentUpdateService::Status status = 352 ComponentUpdateService::Status status =
310 pci->cus()->RegisterComponent(pnacl_component); 353 pci->cus()->RegisterComponent(pnacl_component);
311 if (status != ComponentUpdateService::kOk 354 if (status != ComponentUpdateService::kOk
312 && status != ComponentUpdateService::kReplaced) { 355 && status != ComponentUpdateService::kReplaced) {
313 NOTREACHED() << "Pnacl component registration failed."; 356 NOTREACHED() << "Pnacl component registration failed.";
314 } 357 }
315
316 // If PNaCl is not yet installed but it is requested by --enable-pnacl,
317 // we want it to be available "soon", so kick off an update check
318 // earlier than usual.
319 Version null_version(kNullVersion);
320 if (pci->current_version().Equals(null_version)) {
321 BrowserThread::PostDelayedTask(
322 BrowserThread::UI, FROM_HERE,
323 base::Bind(DoCheckForUpdate, pci->cus(), pnacl_component),
324 base::TimeDelta::FromSeconds(kInitialDelaySeconds));
325 }
326 } 358 }
327 359
328 // Check if there is an existing version on disk first to know when 360 // Check if there is an existing version on disk first to know when
329 // a hosted version is actually newer. 361 // a hosted version is actually newer.
330 void StartPnaclUpdateRegistration(PnaclComponentInstaller* pci) { 362 void StartPnaclUpdateRegistration(PnaclComponentInstaller* pci) {
331 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
332 base::FilePath path = pci->GetPnaclBaseDirectory(); 364 base::FilePath path = pci->GetPnaclBaseDirectory();
333 if (!file_util::PathExists(path)) { 365 if (!file_util::PathExists(path)) {
334 if (!file_util::CreateDirectory(path)) { 366 if (!file_util::CreateDirectory(path)) {
335 NOTREACHED() << "Could not create base Pnacl directory."; 367 NOTREACHED() << "Could not create base Pnacl directory.";
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 BrowserThread::FILE, FROM_HERE, 414 BrowserThread::FILE, FROM_HERE,
383 base::Bind(&StartPnaclUpdateRegistration, pci)); 415 base::Bind(&StartPnaclUpdateRegistration, pci));
384 } 416 }
385 417
386 418
387 } // namespace 419 } // namespace
388 420
389 void PnaclComponentInstaller::RegisterPnaclComponent( 421 void PnaclComponentInstaller::RegisterPnaclComponent(
390 ComponentUpdateService* cus, 422 ComponentUpdateService* cus,
391 const CommandLine& command_line) { 423 const CommandLine& command_line) {
392 // Only register when given the right flag. This is important since 424 // Only register when given the right flag, for now.
393 // we do an early component updater check above (in DoCheckForUpdate).
394 if (command_line.HasSwitch(switches::kEnablePnacl)) { 425 if (command_line.HasSwitch(switches::kEnablePnacl)) {
395 cus_ = cus; 426 cus_ = cus;
396 // If per_user, create a profile observer to watch for logins. 427 // If per_user, create a profile observer to watch for logins.
397 // Only do so after cus_ is set to something non-null. 428 // Only do so after cus_ is set to something non-null.
398 if (per_user_ && !profile_observer_) { 429 if (per_user_ && !profile_observer_) {
399 profile_observer_.reset(new PnaclProfileObserver(this)); 430 profile_observer_.reset(new PnaclProfileObserver(this));
400 } 431 }
401 if (per_user_) { 432 if (per_user_) {
402 // Figure out profile information, before proceeding to look for files. 433 // Figure out profile information, before proceeding to look for files.
403 BrowserThread::PostTask( 434 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
404 BrowserThread::UI, FROM_HERE, 435 base::Bind(&GetProfileInformation, this));
405 base::Bind(&GetProfileInformation, this));
406 } else { 436 } else {
407 BrowserThread::PostTask( 437 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
408 BrowserThread::FILE, FROM_HERE, 438 base::Bind(&StartPnaclUpdateRegistration, this));
409 base::Bind(&StartPnaclUpdateRegistration, this));
410 } 439 }
411 } 440 }
412 } 441 }
413 442
414 void PnaclComponentInstaller::ReRegisterPnacl() { 443 void PnaclComponentInstaller::ReRegisterPnacl() {
415 // No need to check the commandline flags again here. 444 // No need to check the commandline flags again here.
416 // We could only have gotten here after RegisterPnaclComponent 445 // We could only have gotten here after RegisterPnaclComponent
417 // found --enable-pnacl, since that is where we create the profile_observer_, 446 // found --enable-pnacl, since that is where we create the profile_observer_,
418 // which in turn calls ReRegisterPnacl. 447 // which in turn calls ReRegisterPnacl.
419 DCHECK(per_user_); 448 DCHECK(per_user_);
420 // Figure out profile information, before proceeding to look for files. 449 // Figure out profile information, before proceeding to look for files.
421 BrowserThread::PostTask( 450 BrowserThread::PostTask(
422 BrowserThread::UI, FROM_HERE, 451 BrowserThread::UI, FROM_HERE,
423 base::Bind(&GetProfileInformation, this)); 452 base::Bind(&GetProfileInformation, this));
424 } 453 }
454
455 void RequestFirstInstall(ComponentUpdateService* cus,
456 PnaclComponentInstaller* pci,
457 const base::Callback<void(bool)>& installed) {
458 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
459 Version null_version(kNullVersion);
460 CrxComponent pnacl_component;
461 pci->set_current_version(null_version);
462 pnacl_component.version = null_version;
463 pnacl_component.name = "pnacl";
464 pnacl_component.installer = pci;
465 SetPnaclHash(&pnacl_component);
466 ComponentUpdateService::Status status = cus->CheckForUpdateSoon(
467 pnacl_component);
468 if (status != ComponentUpdateService::kOk) {
469 installed.Run(false);
470 return;
471 }
472 pci->AddInstallCallback(installed);
473 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698