OLD | NEW |
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 <list> |
| 8 |
7 #include "base/base_paths.h" | 9 #include "base/base_paths.h" |
8 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/callback.h" |
9 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
10 #include "base/file_path.h" | 13 #include "base/file_path.h" |
11 #include "base/file_util.h" | 14 #include "base/file_util.h" |
12 #include "base/json/json_file_value_serializer.h" | 15 #include "base/json/json_file_value_serializer.h" |
13 #include "base/logging.h" | 16 #include "base/logging.h" |
14 #include "base/path_service.h" | 17 #include "base/path_service.h" |
15 #include "base/string_util.h" | 18 #include "base/string_util.h" |
16 #include "base/values.h" | 19 #include "base/values.h" |
17 #include "base/version.h" | 20 #include "base/version.h" |
18 #include "base/win/windows_version.h" | 21 #include "base/win/windows_version.h" |
19 #include "build/build_config.h" | 22 #include "build/build_config.h" |
20 #include "chrome/browser/component_updater/component_updater_service.h" | 23 #include "chrome/browser/component_updater/component_updater_service.h" |
21 #include "chrome/common/chrome_paths.h" | 24 #include "chrome/common/chrome_paths.h" |
22 #include "content/public/browser/browser_thread.h" | 25 #include "content/public/browser/browser_thread.h" |
23 | 26 |
24 using content::BrowserThread; | 27 using content::BrowserThread; |
25 | 28 |
26 namespace { | 29 namespace { |
27 | 30 |
28 // If PNaCl isn't installed yet, but a user is running chrome with | 31 // Time in seconds to wait for CheckUpdatesForPnacl to complete |
29 // --enable-pnacl, this is the amount of time to wait before starting | 32 // before considering the update failed. |
30 // a background install. | 33 int kPnaclInstallerTimeout = 45; |
31 const int kInitialDelaySeconds = 10; | |
32 | 34 |
33 // One of the Pnacl component files, for checking that expected files exist. | 35 // One of the Pnacl component files, for checking that expected files exist. |
34 // TODO(jvoung): perhaps replace this with a list of the expected files in the | 36 // TODO(jvoung): perhaps replace this with a list of the expected files in the |
35 // manifest.json. Use that to check that everything is unpacked. | 37 // manifest.json. Use that to check that everything is unpacked. |
36 // However, that would make startup detection even slower (need to check for | 38 // However, that would make startup detection even slower (need to check for |
37 // more than one file!). | 39 // more than one file!). |
38 const char kPnaclCompilerFileName[] = "llc_nexe"; | 40 const char kPnaclCompilerFileName[] = "llc_nexe"; |
39 | 41 |
40 // Name of the Pnacl component specified in the manifest. | 42 // Name of the Pnacl component specified in the manifest. |
41 const char kPnaclManifestNamePrefix[] = "PNaCl"; | 43 const char kPnaclManifestNamePrefix[] = "PNaCl"; |
(...skipping 23 matching lines...) Expand all Loading... |
65 // Sanitize characters given by PnaclArch so that they can be used | 67 // Sanitize characters given by PnaclArch so that they can be used |
66 // in path names. This should only be characters in the set: [a-z0-9_]. | 68 // in path names. This should only be characters in the set: [a-z0-9_]. |
67 // Keep in sync with chrome/browser/nacl_host/pnacl_file_host. | 69 // Keep in sync with chrome/browser/nacl_host/pnacl_file_host. |
68 std::string SanitizeForPath(const std::string& input) { | 70 std::string SanitizeForPath(const std::string& input) { |
69 std::string result; | 71 std::string result; |
70 ReplaceChars(input, "-", "_", &result); | 72 ReplaceChars(input, "-", "_", &result); |
71 return result; | 73 return result; |
72 } | 74 } |
73 | 75 |
74 // Set the component's hash to the arch-specific PNaCl package. | 76 // Set the component's hash to the arch-specific PNaCl package. |
75 void SetPnaclHash(CrxComponent* component) { | 77 void SetPnaclHash(std::vector<uint8>* pk_hash) { |
76 #if defined(ARCH_CPU_X86_FAMILY) | 78 #if defined(ARCH_CPU_X86_FAMILY) |
77 // Define both x86_32 and x86_64, and choose below. | 79 // Define both x86_32 and x86_64, and choose below. |
78 static const uint8 x86_sha256_hash[][32] = { | 80 static const uint8 x86_sha256_hash[][32] = { |
79 { // This corresponds to AppID (x86-32): aealhdcgieaiikaifafholmmeooeeioj | 81 { // This corresponds to AppID (x86-32): aealhdcgieaiikaifafholmmeooeeioj |
80 0x04, 0x0b, 0x73, 0x26, 0x84, 0x08, 0x8a, 0x08, 0x50, 0x57, | 82 0x04, 0x0b, 0x73, 0x26, 0x84, 0x08, 0x8a, 0x08, 0x50, 0x57, |
81 0xeb, 0xcc, 0x4e, 0xe4, 0x48, 0xe9, 0x44, 0x2c, 0xc8, 0xa6, 0xd6, | 83 0xeb, 0xcc, 0x4e, 0xe4, 0x48, 0xe9, 0x44, 0x2c, 0xc8, 0xa6, 0xd6, |
82 0x96, 0x11, 0xd4, 0x2a, 0xc5, 0x26, 0x64, 0x34, 0x76, 0x3d, 0x14}, | 84 0x96, 0x11, 0xd4, 0x2a, 0xc5, 0x26, 0x64, 0x34, 0x76, 0x3d, 0x14}, |
83 { // This corresponds to AppID (x86-64): knlfebnofcjjnkpkapbgfphaagefndik | 85 { // This corresponds to AppID (x86-64): knlfebnofcjjnkpkapbgfphaagefndik |
84 0xad, 0xb5, 0x41, 0xde, 0x52, 0x99, 0xda, 0xfa, 0x0f, 0x16, | 86 0xad, 0xb5, 0x41, 0xde, 0x52, 0x99, 0xda, 0xfa, 0x0f, 0x16, |
85 0x5f, 0x70, 0x06, 0x45, 0xd3, 0x8a, 0x32, 0x20, 0x84, 0x57, 0x5c, | 87 0x5f, 0x70, 0x06, 0x45, 0xd3, 0x8a, 0x32, 0x20, 0x84, 0x57, 0x5c, |
86 0x1f, 0xef, 0xb4, 0x42, 0x32, 0xce, 0x4a, 0x3c, 0x2d, 0x7e, 0x3a} | 88 0x1f, 0xef, 0xb4, 0x42, 0x32, 0xce, 0x4a, 0x3c, 0x2d, 0x7e, 0x3a} |
87 }; | 89 }; |
88 | 90 |
89 #if defined(ARCH_CPU_X86_64) | 91 #if defined(ARCH_CPU_X86_64) |
90 component->pk_hash.assign( | 92 pk_hash->assign( |
91 x86_sha256_hash[1], | 93 x86_sha256_hash[1], |
92 &x86_sha256_hash[1][sizeof(x86_sha256_hash[1])]); | 94 &x86_sha256_hash[1][sizeof(x86_sha256_hash[1])]); |
93 #elif defined(OS_WIN) | 95 #elif defined(OS_WIN) |
94 bool x86_64 = (base::win::OSInfo::GetInstance()->wow64_status() == | 96 bool x86_64 = (base::win::OSInfo::GetInstance()->wow64_status() == |
95 base::win::OSInfo::WOW64_ENABLED); | 97 base::win::OSInfo::WOW64_ENABLED); |
96 if (x86_64) { | 98 if (x86_64) { |
97 component->pk_hash.assign( | 99 pk_hash->assign( |
98 x86_sha256_hash[1], | 100 x86_sha256_hash[1], |
99 &x86_sha256_hash[1][sizeof(x86_sha256_hash[1])]); | 101 &x86_sha256_hash[1][sizeof(x86_sha256_hash[1])]); |
100 } else { | 102 } else { |
101 component->pk_hash.assign( | 103 pk_hash->assign( |
102 x86_sha256_hash[0], | 104 x86_sha256_hash[0], |
103 &x86_sha256_hash[0][sizeof(x86_sha256_hash[0])]); | 105 &x86_sha256_hash[0][sizeof(x86_sha256_hash[0])]); |
104 } | 106 } |
105 #else | 107 #else |
106 component->pk_hash.assign( | 108 pk_hash->assign( |
107 x86_sha256_hash[0], | 109 x86_sha256_hash[0], |
108 &x86_sha256_hash[0][sizeof(x86_sha256_hash[0])]); | 110 &x86_sha256_hash[0][sizeof(x86_sha256_hash[0])]); |
109 #endif | 111 #endif |
110 #elif defined(ARCH_CPU_ARMEL) | 112 #elif defined(ARCH_CPU_ARMEL) |
111 // This corresponds to AppID: jgobdlakdbanalhiagkdgcnofkbebejj | 113 // This corresponds to AppID: jgobdlakdbanalhiagkdgcnofkbebejj |
112 static const uint8 arm_sha256_hash[] = { | 114 static const uint8 arm_sha256_hash[] = { |
113 0x96, 0xe1, 0x3b, 0x0a, 0x31, 0x0d, 0x0b, 0x78, 0x06, 0xa3, | 115 0x96, 0xe1, 0x3b, 0x0a, 0x31, 0x0d, 0x0b, 0x78, 0x06, 0xa3, |
114 0x62, 0xde, 0x5a, 0x14, 0x14, 0x99, 0xd4, 0xd9, 0x01, 0x85, 0xc6, | 116 0x62, 0xde, 0x5a, 0x14, 0x14, 0x99, 0xd4, 0xd9, 0x01, 0x85, 0xc6, |
115 0x9a, 0xd2, 0x51, 0x90, 0xa4, 0xb4, 0x94, 0xbd, 0xb8, 0x8b, 0xe8}; | 117 0x9a, 0xd2, 0x51, 0x90, 0xa4, 0xb4, 0x94, 0xbd, 0xb8, 0x8b, 0xe8}; |
116 | 118 |
117 component->pk_hash.assign(arm_sha256_hash, | 119 pk_hash->assign(arm_sha256_hash, |
118 &arm_sha256_hash[sizeof(arm_sha256_hash)]); | 120 &arm_sha256_hash[sizeof(arm_sha256_hash)]); |
119 #elif defined(ARCH_CPU_MIPSEL) | 121 #elif defined(ARCH_CPU_MIPSEL) |
120 // This is a dummy CRX hash for MIPS, so that it will at least compile. | 122 // This is a dummy CRX hash for MIPS, so that it will at least compile. |
121 static const uint8 mips32_sha256_hash[] = { | 123 static const uint8 mips32_sha256_hash[] = { |
122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | 126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
125 | 127 |
126 component->pk_hash.assign(mips32_sha256_hash, | 128 pk_hash->assign(mips32_sha256_hash, |
127 &mips32_sha256_hash[sizeof(mips32_sha256_hash)]); | 129 &mips32_sha256_hash[sizeof(mips32_sha256_hash)]); |
128 #else | 130 #else |
129 #error "Add support for your architecture to Pnacl Component Installer." | 131 #error "Add support for your architecture to Pnacl Component Installer." |
130 #endif | 132 #endif |
131 } | 133 } |
132 | 134 |
133 | 135 |
134 // If we don't have Pnacl installed, this is the version we claim. | 136 // If we don't have Pnacl installed, this is the version we claim. |
135 const char kNullVersion[] = "0.0.0.0"; | 137 const char kNullVersion[] = "0.0.0.0"; |
136 | 138 |
137 // Pnacl components have the version encoded in the path itself: | 139 // Pnacl components have the version encoded in the path itself: |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 public: | 234 public: |
233 explicit PnaclComponentInstaller(const Version& version); | 235 explicit PnaclComponentInstaller(const Version& version); |
234 | 236 |
235 virtual ~PnaclComponentInstaller() {} | 237 virtual ~PnaclComponentInstaller() {} |
236 | 238 |
237 virtual void OnUpdateError(int error) OVERRIDE; | 239 virtual void OnUpdateError(int error) OVERRIDE; |
238 | 240 |
239 virtual bool Install(base::DictionaryValue* manifest, | 241 virtual bool Install(base::DictionaryValue* manifest, |
240 const base::FilePath& unpack_path) OVERRIDE; | 242 const base::FilePath& unpack_path) OVERRIDE; |
241 | 243 |
| 244 typedef base::Callback<void(bool)> InstallCallback; |
| 245 void AddInstallCallback(const InstallCallback& cb); |
| 246 |
242 private: | 247 private: |
| 248 // Cancel a particular callback after a timeout. |
| 249 void CancelCallback(int callback_num); |
| 250 |
| 251 void NotifyInstallError(); |
| 252 |
| 253 void NotifyInstallSuccess(); |
| 254 |
243 Version current_version_; | 255 Version current_version_; |
| 256 |
| 257 // Counter for issue identifiers to each callback. |
| 258 int callback_nums_; |
| 259 |
| 260 // List of callbacks to issue when an install completes successfully. |
| 261 std::list<std::pair<InstallCallback, int> > install_callbacks_; |
244 }; | 262 }; |
245 | 263 |
246 PnaclComponentInstaller::PnaclComponentInstaller( | 264 PnaclComponentInstaller::PnaclComponentInstaller( |
247 const Version& version) : current_version_(version) { | 265 const Version& version) : current_version_(version), callback_nums_(0) { |
248 DCHECK(version.IsValid()); | 266 DCHECK(version.IsValid()); |
249 } | 267 } |
250 | 268 |
251 void PnaclComponentInstaller::OnUpdateError(int error) { | 269 void PnaclComponentInstaller::OnUpdateError(int error) { |
252 NOTREACHED() << "Pnacl update error: " << error; | 270 NOTREACHED() << "Pnacl update error: " << error; |
253 } | 271 } |
254 | 272 |
255 namespace { | 273 namespace { |
256 | 274 |
257 bool PathContainsPnacl(const base::FilePath& base_path) { | 275 bool PathContainsPnacl(const base::FilePath& base_path) { |
258 // Check that at least one of the compiler files exists, for the current ISA. | 276 // Check that at least one of the compiler files exists, for the current ISA. |
259 std::string expected_filename("pnacl_public_"); | 277 std::string expected_filename("pnacl_public_"); |
260 std::string arch = PnaclArch(); | 278 std::string arch = PnaclArch(); |
261 expected_filename = expected_filename + SanitizeForPath(arch) + | 279 expected_filename = expected_filename + SanitizeForPath(arch) + |
262 "_" + kPnaclCompilerFileName; | 280 "_" + kPnaclCompilerFileName; |
263 return file_util::PathExists(base_path.AppendASCII(expected_filename)); | 281 return file_util::PathExists(base_path.AppendASCII(expected_filename)); |
264 } | 282 } |
265 | 283 |
| 284 CrxComponent GetPnaclComponentWithVersion(const Version& current_version) { |
| 285 // Note: the source is the default of BANDAID, even though the |
| 286 // crxes are hosted from CWS. |
| 287 LOG(WARNING) << "GetPnaclComponentWithVersion!!\n"; |
| 288 CrxComponent pnacl; |
| 289 pnacl.name = "pnacl"; |
| 290 // We need a singleton installer... or singleton component, |
| 291 // so that the correct installer's Install() hook gets called. |
| 292 // Or the component updater service needs to be able to look up |
| 293 // the component by id instead. |
| 294 pnacl.installer = new PnaclComponentInstaller(current_version); |
| 295 pnacl.version = current_version; |
| 296 SetPnaclHash(&pnacl.pk_hash); |
| 297 return pnacl; |
| 298 } |
| 299 |
266 } // namespace | 300 } // namespace |
267 | 301 |
268 bool PnaclComponentInstaller::Install(base::DictionaryValue* manifest, | 302 bool PnaclComponentInstaller::Install(base::DictionaryValue* manifest, |
269 const base::FilePath& unpack_path) { | 303 const base::FilePath& unpack_path) { |
| 304 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
270 scoped_ptr<base::DictionaryValue> pnacl_manifest( | 305 scoped_ptr<base::DictionaryValue> pnacl_manifest( |
271 ReadPnaclManifest(unpack_path)); | 306 ReadPnaclManifest(unpack_path)); |
272 if (pnacl_manifest == NULL) { | 307 if (pnacl_manifest == NULL) { |
273 LOG(WARNING) << "Failed to read pnacl manifest."; | 308 LOG(WARNING) << "Failed to read pnacl manifest."; |
| 309 NotifyInstallError(); |
274 return false; | 310 return false; |
275 } | 311 } |
276 | 312 |
277 Version version; | 313 Version version; |
278 if (!CheckPnaclComponentManifest(manifest, | 314 if (!CheckPnaclComponentManifest(manifest, |
279 pnacl_manifest.get(), | 315 pnacl_manifest.get(), |
280 &version)) { | 316 &version)) { |
281 LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing."; | 317 LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing."; |
| 318 NotifyInstallError(); |
282 return false; | 319 return false; |
283 } | 320 } |
284 | 321 |
285 // Don't install if the current version is actually newer. | 322 // Don't install if the current version is actually newer. |
286 if (current_version_.CompareTo(version) > 0) | 323 if (current_version_.CompareTo(version) > 0) { |
| 324 NotifyInstallError(); |
287 return false; | 325 return false; |
| 326 } |
288 | 327 |
289 if (!PathContainsPnacl(unpack_path)) { | 328 if (!PathContainsPnacl(unpack_path)) { |
290 LOG(WARNING) << "PathContainsPnacl check failed, not installing."; | 329 LOG(WARNING) << "PathContainsPnacl check failed, not installing."; |
| 330 NotifyInstallError(); |
291 return false; | 331 return false; |
292 } | 332 } |
293 | 333 |
294 // Passed the basic tests. Time to install it. | 334 // Passed the basic tests. Time to install it. |
295 base::FilePath path = | 335 base::FilePath path = |
296 GetPnaclBaseDirectory().AppendASCII(version.GetString()); | 336 GetPnaclBaseDirectory().AppendASCII(version.GetString()); |
297 if (file_util::PathExists(path)) { | 337 if (file_util::PathExists(path)) { |
298 LOG(WARNING) << "Target path already exists, not installing."; | 338 LOG(WARNING) << "Target path already exists, not installing."; |
| 339 NotifyInstallError(); |
299 return false; | 340 return false; |
300 } | 341 } |
301 if (!file_util::Move(unpack_path, path)) { | 342 if (!file_util::Move(unpack_path, path)) { |
302 LOG(WARNING) << "Move failed, not installing."; | 343 LOG(WARNING) << "Move failed, not installing."; |
| 344 NotifyInstallError(); |
303 return false; | 345 return false; |
304 } | 346 } |
305 | 347 |
306 // Installation is done. Now tell the rest of chrome (just the path service | 348 // Installation is done. Now tell the rest of chrome. |
307 // for now). TODO(jvoung): we need notifications if someone surfed to a | 349 // - The path service. |
308 // Pnacl webpage and Pnacl was just installed at this time. They should | 350 // - Callbacks that requested an update. |
309 // then be able to reload the page and retry (or something). | |
310 // See: http://code.google.com/p/chromium/issues/detail?id=107438 | |
311 current_version_ = version; | 351 current_version_ = version; |
312 | 352 NotifyInstallSuccess(); |
313 PathService::Override(chrome::DIR_PNACL_COMPONENT, path); | 353 PathService::Override(chrome::DIR_PNACL_COMPONENT, path); |
314 return true; | 354 return true; |
315 } | 355 } |
316 | 356 |
317 namespace { | 357 void PnaclComponentInstaller::AddInstallCallback( |
| 358 const InstallCallback& cb) { |
| 359 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 360 int num = ++callback_nums_; |
| 361 install_callbacks_.push_back(std::make_pair(cb, num)); |
318 | 362 |
319 void DoCheckForUpdate(ComponentUpdateService* cus, | 363 // Set a timeout. If the install doesn't complete within a minute, |
320 const CrxComponent& pnacl) { | 364 // assume that the update failed and cancel the callback. |
321 if (cus->CheckForUpdateSoon(pnacl) != ComponentUpdateService::kOk) { | 365 // Do this on the same thread that would have checked the callbacks. |
322 LOG(WARNING) << "Pnacl check for update failed."; | 366 BrowserThread::PostDelayedTask( |
| 367 BrowserThread::FILE, FROM_HERE, |
| 368 base::Bind(&PnaclComponentInstaller::CancelCallback, |
| 369 // Why unretained? The installer should have |
| 370 // the same lifetime as the component updater service, |
| 371 // which lives until process shutdown. |
| 372 base::Unretained(this), |
| 373 num), |
| 374 base::TimeDelta::FromSeconds(kPnaclInstallerTimeout)); |
| 375 } |
| 376 |
| 377 void PnaclComponentInstaller::CancelCallback(int num) { |
| 378 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 379 for (std::list<std::pair<InstallCallback, int> >::iterator |
| 380 i = install_callbacks_.begin(), |
| 381 e = install_callbacks_.end(); i != e; ++i) { |
| 382 if (i->second == num) { |
| 383 BrowserThread::PostTask( |
| 384 BrowserThread::UI, FROM_HERE, |
| 385 base::Bind(i->first, false)); |
| 386 install_callbacks_.erase(i); |
| 387 return; |
| 388 } |
323 } | 389 } |
324 } | 390 } |
325 | 391 |
| 392 void PnaclComponentInstaller::NotifyInstallError() { |
| 393 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 394 while (!install_callbacks_.empty()) { |
| 395 BrowserThread::PostTask( |
| 396 BrowserThread::UI, FROM_HERE, |
| 397 base::Bind(install_callbacks_.front().first, false)); |
| 398 install_callbacks_.pop_front(); |
| 399 } |
| 400 } |
| 401 |
| 402 void PnaclComponentInstaller::NotifyInstallSuccess() { |
| 403 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 404 while (!install_callbacks_.empty()) { |
| 405 BrowserThread::PostTask( |
| 406 BrowserThread::UI, FROM_HERE, |
| 407 base::Bind(install_callbacks_.front().first, true)); |
| 408 install_callbacks_.pop_front(); |
| 409 } |
| 410 } |
| 411 |
| 412 namespace { |
| 413 |
326 // Finally, do the registration with the right version number. | 414 // Finally, do the registration with the right version number. |
327 void FinishPnaclUpdateRegistration(ComponentUpdateService* cus, | 415 void FinishPnaclUpdateRegistration(ComponentUpdateService* cus, |
328 const Version& current_version) { | 416 const CrxComponent& pnacl) { |
329 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 417 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
330 // Note: the source is the default of BANDAID, even though the | |
331 // crxes are hosted from CWS. | |
332 CrxComponent pnacl; | |
333 pnacl.name = "pnacl"; | |
334 pnacl.installer = new PnaclComponentInstaller(current_version); | |
335 pnacl.version = current_version; | |
336 SetPnaclHash(&pnacl); | |
337 if (cus->RegisterComponent(pnacl) != ComponentUpdateService::kOk) { | 418 if (cus->RegisterComponent(pnacl) != ComponentUpdateService::kOk) { |
338 NOTREACHED() << "Pnacl component registration failed."; | 419 NOTREACHED() << "Pnacl component registration failed."; |
339 } | 420 } |
340 | |
341 // If PNaCl is not yet installed but it is requested by --enable-pnacl, | |
342 // we want it to be available "soon", so kick off an update check | |
343 // earlier than usual. | |
344 Version null_version(kNullVersion); | |
345 if (current_version.Equals(null_version)) { | |
346 BrowserThread::PostDelayedTask( | |
347 BrowserThread::UI, FROM_HERE, | |
348 base::Bind(DoCheckForUpdate, cus, pnacl), | |
349 base::TimeDelta::FromSeconds(kInitialDelaySeconds)); | |
350 } | |
351 } | 421 } |
352 | 422 |
353 // Check if there is an existing version on disk first to know when | 423 // Check if there is an existing version on disk first to know when |
354 // a hosted version is actually newer. | 424 // a hosted version is actually newer. |
355 void StartPnaclUpdateRegistration(ComponentUpdateService* cus) { | 425 void StartPnaclUpdateRegistration(ComponentUpdateService* cus) { |
356 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 426 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
357 base::FilePath path = GetPnaclBaseDirectory(); | 427 base::FilePath path = GetPnaclBaseDirectory(); |
358 if (!file_util::PathExists(path)) { | 428 if (!file_util::PathExists(path)) { |
359 if (!file_util::CreateDirectory(path)) { | 429 if (!file_util::CreateDirectory(path)) { |
360 NOTREACHED() << "Could not create base Pnacl directory."; | 430 NOTREACHED() << "Could not create base Pnacl directory."; |
361 return; | 431 return; |
362 } | 432 } |
363 } | 433 } |
364 | 434 |
365 Version version(kNullVersion); | 435 Version version(kNullVersion); |
366 std::vector<base::FilePath> older_dirs; | 436 std::vector<base::FilePath> older_dirs; |
367 if (GetLatestPnaclDirectory(&path, &version, &older_dirs)) { | 437 if (GetLatestPnaclDirectory(&path, &version, &older_dirs)) { |
368 if (!PathContainsPnacl(path)) { | 438 if (!PathContainsPnacl(path)) { |
369 version = Version(kNullVersion); | 439 version = Version(kNullVersion); |
370 } else { | 440 } else { |
371 PathService::Override(chrome::DIR_PNACL_COMPONENT, path); | 441 PathService::Override(chrome::DIR_PNACL_COMPONENT, path); |
372 } | 442 } |
373 } | 443 } |
374 | 444 |
375 BrowserThread::PostTask( | 445 BrowserThread::PostTask( |
376 BrowserThread::UI, FROM_HERE, | 446 BrowserThread::UI, FROM_HERE, |
377 base::Bind(&FinishPnaclUpdateRegistration, cus, version)); | 447 base::Bind(&FinishPnaclUpdateRegistration, |
| 448 cus, |
| 449 GetPnaclComponentWithVersion(version))); |
378 | 450 |
379 // Remove older versions of PNaCl. | 451 // Remove older versions of PNaCl. |
380 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin(); | 452 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin(); |
381 iter != older_dirs.end(); ++iter) { | 453 iter != older_dirs.end(); ++iter) { |
382 file_util::Delete(*iter, true); | 454 file_util::Delete(*iter, true); |
383 } | 455 } |
384 } | 456 } |
385 | 457 |
386 } // namespace | 458 } // namespace |
387 | 459 |
388 void RegisterPnaclComponent(ComponentUpdateService* cus) { | 460 void RegisterPnaclComponent(ComponentUpdateService* cus) { |
389 BrowserThread::PostTask( | 461 BrowserThread::PostTask( |
390 BrowserThread::FILE, FROM_HERE, | 462 BrowserThread::FILE, FROM_HERE, |
391 base::Bind(&StartPnaclUpdateRegistration, cus)); | 463 base::Bind(&StartPnaclUpdateRegistration, cus)); |
392 } | 464 } |
| 465 |
| 466 void CheckUpdatesForPnacl(ComponentUpdateService* cus, |
| 467 const base::Callback<void(bool)>& installed) { |
| 468 std::vector<uint8> pk_hash; |
| 469 SetPnaclHash(&pk_hash); |
| 470 CrxComponent pnacl; |
| 471 if (!cus->FindRegisteredComponent(pk_hash, &pnacl)) { |
| 472 installed.Run(false); |
| 473 return; |
| 474 } |
| 475 ComponentUpdateService::Status status = cus->CheckForUpdateSoon(pnacl); |
| 476 if (status != ComponentUpdateService::kOk) { |
| 477 installed.Run(false); |
| 478 return; |
| 479 } |
| 480 PnaclComponentInstaller* installer = |
| 481 static_cast<PnaclComponentInstaller*>(pnacl.installer); |
| 482 BrowserThread::PostTask( |
| 483 BrowserThread::FILE, FROM_HERE, |
| 484 base::Bind( |
| 485 &PnaclComponentInstaller::AddInstallCallback, |
| 486 // Why unretained? The installer should have |
| 487 // the same lifetime as the component updater service, |
| 488 // which lives until process shutdown. |
| 489 base::Unretained(installer), |
| 490 installed)); |
| 491 } |
OLD | NEW |