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

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: cleanup a bit 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 // Time in seconds to wait for CheckUpdatesForPnacl to complete
37 // --enable-pnacl, this is the amount of time to wait before starting 38 // before considering the update failed.
38 // a background install. 39 int kPnaclInstallerTimeout = 60;
39 const int kInitialDelaySeconds = 10;
40 40
41 // Name of the Pnacl component specified in the manifest. 41 // Name of the Pnacl component specified in the manifest.
42 const char kPnaclManifestNamePrefix[] = "PNaCl"; 42 const char kPnaclManifestNamePrefix[] = "PNaCl";
43 43
44 // 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_].
46 // Keep in sync with chrome/browser/nacl_host/nacl_file_host.
47 std::string SanitizeForPath(const std::string& input) {
48 std::string result;
49 ReplaceChars(input, "-", "_", &result);
50 return result;
51 }
52
53 // Set the component's hash to the arch-specific PNaCl package. 44 // Set the component's hash to the arch-specific PNaCl package.
54 void SetPnaclHash(CrxComponent* component) { 45 void SetPnaclHash(CrxComponent* component) {
55 #if defined(ARCH_CPU_X86_FAMILY) 46 #if defined(ARCH_CPU_X86_FAMILY)
56 // Define both x86_32 and x86_64, and choose below. 47 // Define both x86_32 and x86_64, and choose below.
57 static const uint8 x86_sha256_hash[][32] = { 48 static const uint8 x86_sha256_hash[][32] = {
58 { // This corresponds to AppID (x86-32): aealhdcgieaiikaifafholmmeooeeioj 49 { // This corresponds to AppID (x86-32): aealhdcgieaiikaifafholmmeooeeioj
59 0x04, 0x0b, 0x73, 0x26, 0x84, 0x08, 0x8a, 0x08, 0x50, 0x57, 50 0x04, 0x0b, 0x73, 0x26, 0x84, 0x08, 0x8a, 0x08, 0x50, 0x57,
60 0xeb, 0xcc, 0x4e, 0xe4, 0x48, 0xe9, 0x44, 0x2c, 0xc8, 0xa6, 0xd6, 51 0xeb, 0xcc, 0x4e, 0xe4, 0x48, 0xe9, 0x44, 0x2c, 0xc8, 0xa6, 0xd6,
61 0x96, 0x11, 0xd4, 0x2a, 0xc5, 0x26, 0x64, 0x34, 0x76, 0x3d, 0x14}, 52 0x96, 0x11, 0xd4, 0x2a, 0xc5, 0x26, 0x64, 0x34, 0x76, 0x3d, 0x14},
62 { // This corresponds to AppID (x86-64): knlfebnofcjjnkpkapbgfphaagefndik 53 { // This corresponds to AppID (x86-64): knlfebnofcjjnkpkapbgfphaagefndik
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 << arch << " vs " << OmahaQueryParams::getNaclArch() << ")"; 203 << arch << " vs " << OmahaQueryParams::getNaclArch() << ")";
213 return false; 204 return false;
214 } 205 }
215 206
216 *version_out = version; 207 *version_out = version;
217 return true; 208 return true;
218 } 209 }
219 210
220 PnaclComponentInstaller::PnaclComponentInstaller() 211 PnaclComponentInstaller::PnaclComponentInstaller()
221 : per_user_(false), 212 : per_user_(false),
222 cus_(NULL) { 213 cus_(NULL),
214 callback_nums_(0) {
223 #if defined(OS_CHROMEOS) 215 #if defined(OS_CHROMEOS)
224 per_user_ = true; 216 per_user_ = true;
225 #endif 217 #endif
226 } 218 }
227 219
228 PnaclComponentInstaller::~PnaclComponentInstaller() { 220 PnaclComponentInstaller::~PnaclComponentInstaller() {
229 } 221 }
230 222
231 void PnaclComponentInstaller::OnUpdateError(int error) { 223 void PnaclComponentInstaller::OnUpdateError(int error) {
232 NOTREACHED() << "Pnacl update error: " << error; 224 NOTREACHED() << "Pnacl update error: " << error;
(...skipping 26 matching lines...) Expand all
259 // On chromeos, we want to find the --login-profile=<foo> dir. 251 // On chromeos, we want to find the --login-profile=<foo> dir.
260 // Even though the path does vary between users, the content 252 // Even though the path does vary between users, the content
261 // changes when logging out and logging in. 253 // changes when logging out and logging in.
262 ProfileManager* pm = g_browser_process->profile_manager(); 254 ProfileManager* pm = g_browser_process->profile_manager();
263 current_profile_path_ = pm->user_data_dir().Append( 255 current_profile_path_ = pm->user_data_dir().Append(
264 pm->GetInitialProfileDir()); 256 pm->GetInitialProfileDir());
265 } 257 }
266 258
267 bool PnaclComponentInstaller::Install(const base::DictionaryValue& manifest, 259 bool PnaclComponentInstaller::Install(const base::DictionaryValue& manifest,
268 const base::FilePath& unpack_path) { 260 const base::FilePath& unpack_path) {
261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
269 scoped_ptr<base::DictionaryValue> pnacl_manifest( 262 scoped_ptr<base::DictionaryValue> pnacl_manifest(
270 ReadPnaclManifest(unpack_path)); 263 ReadPnaclManifest(unpack_path));
271 if (pnacl_manifest == NULL) { 264 if (pnacl_manifest == NULL) {
272 LOG(WARNING) << "Failed to read pnacl manifest."; 265 LOG(WARNING) << "Failed to read pnacl manifest.";
266 NotifyInstallError();
273 return false; 267 return false;
274 } 268 }
275 269
276 Version version; 270 Version version;
277 if (!CheckPnaclComponentManifest(manifest, *pnacl_manifest, &version)) { 271 if (!CheckPnaclComponentManifest(manifest, *pnacl_manifest, &version)) {
278 LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing."; 272 LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing.";
273 NotifyInstallError();
279 return false; 274 return false;
280 } 275 }
281 276
282 // Don't install if the current version is actually newer. 277 // Don't install if the current version is actually newer.
283 if (current_version().CompareTo(version) > 0) 278 if (current_version().CompareTo(version) > 0) {
279 NotifyInstallError();
284 return false; 280 return false;
281 }
285 282
286 // Passed the basic tests. Time to install it. 283 // Passed the basic tests. Time to install it.
287 base::FilePath path = GetPnaclBaseDirectory().AppendASCII( 284 base::FilePath path = GetPnaclBaseDirectory().AppendASCII(
288 version.GetString()); 285 version.GetString());
289 if (file_util::PathExists(path)) { 286 if (file_util::PathExists(path)) {
290 LOG(WARNING) << "Target path already exists, not installing."; 287 LOG(WARNING) << "Target path already exists, not installing.";
288 NotifyInstallError();
291 return false; 289 return false;
292 } 290 }
293 if (!file_util::Move(unpack_path, path)) { 291 if (!file_util::Move(unpack_path, path)) {
294 LOG(WARNING) << "Move failed, not installing."; 292 LOG(WARNING) << "Move failed, not installing.";
293 NotifyInstallError();
295 return false; 294 return false;
296 } 295 }
297 296
298 // Installation is done. Now tell the rest of chrome (just the path service 297 // Installation is done. Now tell the rest of chrome.
299 // for now). TODO(jvoung): we need notifications if someone surfed to a 298 // - The path service.
300 // Pnacl webpage and Pnacl was just installed at this time. They should 299 // - Callbacks that requested an update.
301 // then be able to reload the page and retry (or something).
302 // See: http://code.google.com/p/chromium/issues/detail?id=107438
303 set_current_version(version); 300 set_current_version(version);
304 301 NotifyInstallSuccess();
305 PathService::Override(chrome::DIR_PNACL_COMPONENT, path); 302 PathService::Override(chrome::DIR_PNACL_COMPONENT, path);
306 return true; 303 return true;
307 } 304 }
308 305
309 namespace { 306 void PnaclComponentInstaller::AddInstallCallback(
307 const InstallCallback& cb) {
308 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
309 int num = ++callback_nums_;
310 install_callbacks_.push_back(std::make_pair(cb, num));
310 311
311 void DoCheckForUpdate(ComponentUpdateService* cus, 312 // Set a timeout. If the install doesn't complete within a minute,
312 const CrxComponent& pnacl) { 313 // assume that the update failed and cancel the callback.
313 if (cus->CheckForUpdateSoon(pnacl) != ComponentUpdateService::kOk) { 314 // Do this on the same thread that would have checked the callbacks.
314 LOG(WARNING) << "Pnacl check for update failed."; 315 BrowserThread::PostDelayedTask(
316 BrowserThread::UI, FROM_HERE,
317 base::Bind(&PnaclComponentInstaller::CancelCallback,
318 // Why unretained? The installer should have
sehr 2013/06/14 18:23:43 Perhaps a better phrasing would be "we use Unretai
jvoung (off chromium) 2013/06/14 18:57:50 Done.
319 // the same lifetime as the component updater service,
320 // which lives until process shutdown.
321 base::Unretained(this),
322 num),
323 base::TimeDelta::FromSeconds(kPnaclInstallerTimeout));
324 }
325
326 void PnaclComponentInstaller::CancelCallback(int num) {
327 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
328 for (std::list<std::pair<InstallCallback, int> >::iterator
329 i = install_callbacks_.begin(),
330 e = install_callbacks_.end(); i != e; ++i) {
331 if (i->second == num) {
332 i->first.Run(false);
333 install_callbacks_.erase(i);
334 return;
335 }
315 } 336 }
316 } 337 }
317 338
318 // Finally, do the registration with the right version number. 339 void PnaclComponentInstaller::NotifyAllWithResult(bool status) {
340 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
341 while (!install_callbacks_.empty()) {
342 install_callbacks_.front().first.Run(status);
343 install_callbacks_.pop_front();
344 }
345 }
346
347 void PnaclComponentInstaller::NotifyInstallError() {
348 BrowserThread::PostTask(
349 BrowserThread::UI, FROM_HERE,
350 base::Bind(&PnaclComponentInstaller::NotifyAllWithResult,
351 // Why unretained? The installer lives until process shutdown.
sehr 2013/06/14 18:23:43 Same comment issue here.
jvoung (off chromium) 2013/06/14 18:57:50 Done.
352 base::Unretained(this), false));
353 }
354
355
356 void PnaclComponentInstaller::NotifyInstallSuccess() {
357 BrowserThread::PostTask(
358 BrowserThread::UI, FROM_HERE,
359 base::Bind(&PnaclComponentInstaller::NotifyAllWithResult,
360 // Why unretained? The installer lives until process shutdown.
361 base::Unretained(this), true));
362 }
363
364 namespace {
365
319 void FinishPnaclUpdateRegistration(const Version& current_version, 366 void FinishPnaclUpdateRegistration(const Version& current_version,
320 PnaclComponentInstaller* pci) { 367 PnaclComponentInstaller* pci) {
321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 368 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
322 CrxComponent pnacl_component; 369 CrxComponent pnacl_component;
323 pnacl_component.version = current_version; 370 pnacl_component.version = current_version;
324 pnacl_component.name = "pnacl"; 371 pnacl_component.name = "pnacl";
325 pnacl_component.installer = pci; 372 pnacl_component.installer = pci;
326 pci->set_current_version(current_version); 373 pci->set_current_version(current_version);
327 SetPnaclHash(&pnacl_component); 374 SetPnaclHash(&pnacl_component);
328 375
329 ComponentUpdateService::Status status = 376 ComponentUpdateService::Status status =
330 pci->cus()->RegisterComponent(pnacl_component); 377 pci->cus()->RegisterComponent(pnacl_component);
331 if (status != ComponentUpdateService::kOk 378 if (status != ComponentUpdateService::kOk
332 && status != ComponentUpdateService::kReplaced) { 379 && status != ComponentUpdateService::kReplaced) {
333 NOTREACHED() << "Pnacl component registration failed."; 380 NOTREACHED() << "Pnacl component registration failed.";
334 } 381 }
335
336 // If PNaCl is not yet installed but it is requested by --enable-pnacl,
337 // we want it to be available "soon", so kick off an update check
338 // earlier than usual.
339 Version null_version(kNullVersion);
340 if (pci->current_version().Equals(null_version)) {
341 BrowserThread::PostDelayedTask(
342 BrowserThread::UI, FROM_HERE,
343 base::Bind(DoCheckForUpdate, pci->cus(), pnacl_component),
344 base::TimeDelta::FromSeconds(kInitialDelaySeconds));
345 }
346 } 382 }
347 383
348 // Check if there is an existing version on disk first to know when 384 // Check if there is an existing version on disk first to know when
349 // a hosted version is actually newer. 385 // a hosted version is actually newer.
350 void StartPnaclUpdateRegistration(PnaclComponentInstaller* pci) { 386 void StartPnaclUpdateRegistration(PnaclComponentInstaller* pci) {
351 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 387 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
352 base::FilePath path = pci->GetPnaclBaseDirectory(); 388 base::FilePath path = pci->GetPnaclBaseDirectory();
353 if (!file_util::PathExists(path)) { 389 if (!file_util::PathExists(path)) {
354 if (!file_util::CreateDirectory(path)) { 390 if (!file_util::CreateDirectory(path)) {
355 NOTREACHED() << "Could not create base Pnacl directory."; 391 NOTREACHED() << "Could not create base Pnacl directory.";
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 BrowserThread::FILE, FROM_HERE, 436 BrowserThread::FILE, FROM_HERE,
401 base::Bind(&StartPnaclUpdateRegistration, pci)); 437 base::Bind(&StartPnaclUpdateRegistration, pci));
402 } 438 }
403 439
404 440
405 } // namespace 441 } // namespace
406 442
407 void PnaclComponentInstaller::RegisterPnaclComponent( 443 void PnaclComponentInstaller::RegisterPnaclComponent(
408 ComponentUpdateService* cus, 444 ComponentUpdateService* cus,
409 const CommandLine& command_line) { 445 const CommandLine& command_line) {
410 // Only register when given the right flag. This is important since 446 // Only register when given the right flag, for now.
411 // we do an early component updater check above (in DoCheckForUpdate).
412 if (command_line.HasSwitch(switches::kEnablePnacl)) { 447 if (command_line.HasSwitch(switches::kEnablePnacl)) {
413 cus_ = cus; 448 cus_ = cus;
414 // If per_user, create a profile observer to watch for logins. 449 // If per_user, create a profile observer to watch for logins.
415 // Only do so after cus_ is set to something non-null. 450 // Only do so after cus_ is set to something non-null.
416 if (per_user_ && !profile_observer_) { 451 if (per_user_ && !profile_observer_) {
417 profile_observer_.reset(new PnaclProfileObserver(this)); 452 profile_observer_.reset(new PnaclProfileObserver(this));
418 } 453 }
419 if (per_user_) { 454 if (per_user_) {
420 // Figure out profile information, before proceeding to look for files. 455 // Figure out profile information, before proceeding to look for files.
421 BrowserThread::PostTask( 456 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
422 BrowserThread::UI, FROM_HERE, 457 base::Bind(&GetProfileInformation, this));
423 base::Bind(&GetProfileInformation, this));
424 } else { 458 } else {
425 BrowserThread::PostTask( 459 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
426 BrowserThread::FILE, FROM_HERE, 460 base::Bind(&StartPnaclUpdateRegistration, this));
427 base::Bind(&StartPnaclUpdateRegistration, this));
428 } 461 }
429 } 462 }
430 } 463 }
431 464
432 void PnaclComponentInstaller::ReRegisterPnacl() { 465 void PnaclComponentInstaller::ReRegisterPnacl() {
433 // No need to check the commandline flags again here. 466 // No need to check the commandline flags again here.
434 // We could only have gotten here after RegisterPnaclComponent 467 // We could only have gotten here after RegisterPnaclComponent
435 // found --enable-pnacl, since that is where we create the profile_observer_, 468 // found --enable-pnacl, since that is where we create the profile_observer_,
436 // which in turn calls ReRegisterPnacl. 469 // which in turn calls ReRegisterPnacl.
437 DCHECK(per_user_); 470 DCHECK(per_user_);
438 // Figure out profile information, before proceeding to look for files. 471 // Figure out profile information, before proceeding to look for files.
439 BrowserThread::PostTask( 472 BrowserThread::PostTask(
440 BrowserThread::UI, FROM_HERE, 473 BrowserThread::UI, FROM_HERE,
441 base::Bind(&GetProfileInformation, this)); 474 base::Bind(&GetProfileInformation, this));
442 } 475 }
476
477 void RequestFirstInstall(ComponentUpdateService* cus,
478 PnaclComponentInstaller* pci,
479 const base::Callback<void(bool)>& installed) {
480 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
481 Version null_version(kNullVersion);
482 CrxComponent pnacl_component;
483 pci->set_current_version(null_version);
484 pnacl_component.version = null_version;
485 pnacl_component.name = "pnacl";
486 pnacl_component.installer = pci;
487 SetPnaclHash(&pnacl_component);
488 ComponentUpdateService::Status status = cus->CheckForUpdateSoon(
489 pnacl_component);
490 if (status != ComponentUpdateService::kOk) {
491 installed.Run(false);
492 return;
493 }
494 pci->AddInstallCallback(installed);
495 }
OLDNEW
« no previous file with comments | « chrome/browser/component_updater/pnacl/pnacl_component_installer.h ('k') | chrome/browser/nacl_host/nacl_file_host.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698