| 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 "base/atomicops.h" | 7 #include "base/atomicops.h" |
| 8 #include "base/base_paths.h" | 8 #include "base/base_paths.h" |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 } | 83 } |
| 84 | 84 |
| 85 // Tell the rest of the world where to find the platform-specific PNaCl files. | 85 // Tell the rest of the world where to find the platform-specific PNaCl files. |
| 86 void OverrideDirPnaclComponent(const base::FilePath& base_path) { | 86 void OverrideDirPnaclComponent(const base::FilePath& base_path) { |
| 87 PathService::Override(chrome::DIR_PNACL_COMPONENT, | 87 PathService::Override(chrome::DIR_PNACL_COMPONENT, |
| 88 GetPlatformDir(base_path)); | 88 GetPlatformDir(base_path)); |
| 89 } | 89 } |
| 90 | 90 |
| 91 bool GetLatestPnaclDirectory(PnaclComponentInstaller* pci, | 91 bool GetLatestPnaclDirectory(PnaclComponentInstaller* pci, |
| 92 base::FilePath* latest_dir, | 92 base::FilePath* latest_dir, |
| 93 Version* latest_version, | 93 base::Version* latest_version, |
| 94 std::vector<base::FilePath>* older_dirs) { | 94 std::vector<base::FilePath>* older_dirs) { |
| 95 // Enumerate all versions starting from the base directory. | 95 // Enumerate all versions starting from the base directory. |
| 96 base::FilePath base_dir = pci->GetPnaclBaseDirectory(); | 96 base::FilePath base_dir = pci->GetPnaclBaseDirectory(); |
| 97 bool found = false; | 97 bool found = false; |
| 98 base::FileEnumerator | 98 base::FileEnumerator |
| 99 file_enumerator(base_dir, false, base::FileEnumerator::DIRECTORIES); | 99 file_enumerator(base_dir, false, base::FileEnumerator::DIRECTORIES); |
| 100 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); | 100 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); |
| 101 path = file_enumerator.Next()) { | 101 path = file_enumerator.Next()) { |
| 102 Version version(path.BaseName().MaybeAsASCII()); | 102 base::Version version(path.BaseName().MaybeAsASCII()); |
| 103 if (!version.IsValid()) | 103 if (!version.IsValid()) |
| 104 continue; | 104 continue; |
| 105 if (found) { | 105 if (found) { |
| 106 if (version.CompareTo(*latest_version) > 0) { | 106 if (version.CompareTo(*latest_version) > 0) { |
| 107 older_dirs->push_back(*latest_dir); | 107 older_dirs->push_back(*latest_dir); |
| 108 *latest_dir = path; | 108 *latest_dir = path; |
| 109 *latest_version = version; | 109 *latest_version = version; |
| 110 } else { | 110 } else { |
| 111 older_dirs->push_back(path); | 111 older_dirs->push_back(path); |
| 112 } | 112 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 FILE_PATH_LITERAL("manifest.json")); | 148 FILE_PATH_LITERAL("manifest.json")); |
| 149 if (!base::PathExists(manifest_path)) | 149 if (!base::PathExists(manifest_path)) |
| 150 return NULL; | 150 return NULL; |
| 151 return ReadJSONManifest(manifest_path); | 151 return ReadJSONManifest(manifest_path); |
| 152 } | 152 } |
| 153 | 153 |
| 154 // Check that the component's manifest is for PNaCl, and check the | 154 // Check that the component's manifest is for PNaCl, and check the |
| 155 // PNaCl manifest indicates this is the correct arch-specific package. | 155 // PNaCl manifest indicates this is the correct arch-specific package. |
| 156 bool CheckPnaclComponentManifest(const base::DictionaryValue& manifest, | 156 bool CheckPnaclComponentManifest(const base::DictionaryValue& manifest, |
| 157 const base::DictionaryValue& pnacl_manifest, | 157 const base::DictionaryValue& pnacl_manifest, |
| 158 Version* version_out) { | 158 base::Version* version_out) { |
| 159 // Make sure we have the right |manifest| file. | 159 // Make sure we have the right |manifest| file. |
| 160 std::string name; | 160 std::string name; |
| 161 if (!manifest.GetStringASCII("name", &name)) { | 161 if (!manifest.GetStringASCII("name", &name)) { |
| 162 LOG(WARNING) << "'name' field is missing from manifest!"; | 162 LOG(WARNING) << "'name' field is missing from manifest!"; |
| 163 return false; | 163 return false; |
| 164 } | 164 } |
| 165 // For the webstore, we've given different names to each of the | 165 // For the webstore, we've given different names to each of the |
| 166 // architecture specific packages (and test/QA vs not test/QA) | 166 // architecture specific packages (and test/QA vs not test/QA) |
| 167 // so only part of it is the same. | 167 // so only part of it is the same. |
| 168 if (name.find(kPnaclManifestName) == std::string::npos) { | 168 if (name.find(kPnaclManifestName) == std::string::npos) { |
| 169 LOG(WARNING) << "'name' field in manifest is invalid (" | 169 LOG(WARNING) << "'name' field in manifest is invalid (" |
| 170 << name << ") -- missing (" | 170 << name << ") -- missing (" |
| 171 << kPnaclManifestName << ")"; | 171 << kPnaclManifestName << ")"; |
| 172 return false; | 172 return false; |
| 173 } | 173 } |
| 174 | 174 |
| 175 std::string proposed_version; | 175 std::string proposed_version; |
| 176 if (!manifest.GetStringASCII("version", &proposed_version)) { | 176 if (!manifest.GetStringASCII("version", &proposed_version)) { |
| 177 LOG(WARNING) << "'version' field is missing from manifest!"; | 177 LOG(WARNING) << "'version' field is missing from manifest!"; |
| 178 return false; | 178 return false; |
| 179 } | 179 } |
| 180 Version version(proposed_version.c_str()); | 180 base::Version version(proposed_version.c_str()); |
| 181 if (!version.IsValid()) { | 181 if (!version.IsValid()) { |
| 182 LOG(WARNING) << "'version' field in manifest is invalid " | 182 LOG(WARNING) << "'version' field in manifest is invalid " |
| 183 << version.GetString(); | 183 << version.GetString(); |
| 184 return false; | 184 return false; |
| 185 } | 185 } |
| 186 | 186 |
| 187 // Now check the |pnacl_manifest|. | 187 // Now check the |pnacl_manifest|. |
| 188 std::string arch; | 188 std::string arch; |
| 189 if (!pnacl_manifest.GetStringASCII("pnacl-arch", &arch)) { | 189 if (!pnacl_manifest.GetStringASCII("pnacl-arch", &arch)) { |
| 190 LOG(WARNING) << "'pnacl-arch' field is missing from pnacl-manifest!"; | 190 LOG(WARNING) << "'pnacl-arch' field is missing from pnacl-manifest!"; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 | 252 |
| 253 bool PnaclComponentInstaller::Install(const base::DictionaryValue& manifest, | 253 bool PnaclComponentInstaller::Install(const base::DictionaryValue& manifest, |
| 254 const base::FilePath& unpack_path) { | 254 const base::FilePath& unpack_path) { |
| 255 scoped_ptr<base::DictionaryValue> pnacl_manifest( | 255 scoped_ptr<base::DictionaryValue> pnacl_manifest( |
| 256 ReadPnaclManifest(unpack_path)); | 256 ReadPnaclManifest(unpack_path)); |
| 257 if (pnacl_manifest == NULL) { | 257 if (pnacl_manifest == NULL) { |
| 258 LOG(WARNING) << "Failed to read pnacl manifest."; | 258 LOG(WARNING) << "Failed to read pnacl manifest."; |
| 259 return false; | 259 return false; |
| 260 } | 260 } |
| 261 | 261 |
| 262 Version version; | 262 base::Version version; |
| 263 if (!CheckPnaclComponentManifest(manifest, *pnacl_manifest, &version)) { | 263 if (!CheckPnaclComponentManifest(manifest, *pnacl_manifest, &version)) { |
| 264 LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing."; | 264 LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing."; |
| 265 return false; | 265 return false; |
| 266 } | 266 } |
| 267 | 267 |
| 268 // Don't install if the current version is actually newer. | 268 // Don't install if the current version is actually newer. |
| 269 if (current_version().CompareTo(version) > 0) { | 269 if (current_version().CompareTo(version) > 0) { |
| 270 return false; | 270 return false; |
| 271 } | 271 } |
| 272 | 272 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 290 OverrideDirPnaclComponent(path); | 290 OverrideDirPnaclComponent(path); |
| 291 return true; | 291 return true; |
| 292 } | 292 } |
| 293 | 293 |
| 294 // Given |file|, which can be a path like "_platform_specific/arm/pnacl_foo", | 294 // Given |file|, which can be a path like "_platform_specific/arm/pnacl_foo", |
| 295 // returns the assumed install path. The path separator in |file| is '/' | 295 // returns the assumed install path. The path separator in |file| is '/' |
| 296 // for all platforms. Caller is responsible for checking that the | 296 // for all platforms. Caller is responsible for checking that the |
| 297 // |installed_file| actually exists. | 297 // |installed_file| actually exists. |
| 298 bool PnaclComponentInstaller::GetInstalledFile( | 298 bool PnaclComponentInstaller::GetInstalledFile( |
| 299 const std::string& file, base::FilePath* installed_file) { | 299 const std::string& file, base::FilePath* installed_file) { |
| 300 if (current_version().Equals(Version(kNullVersion))) | 300 if (current_version().Equals(base::Version(kNullVersion))) |
| 301 return false; | 301 return false; |
| 302 | 302 |
| 303 *installed_file = GetPnaclBaseDirectory().AppendASCII( | 303 *installed_file = GetPnaclBaseDirectory().AppendASCII( |
| 304 current_version().GetString()).AppendASCII(file); | 304 current_version().GetString()).AppendASCII(file); |
| 305 return true; | 305 return true; |
| 306 } | 306 } |
| 307 | 307 |
| 308 CrxComponent PnaclComponentInstaller::GetCrxComponent() { | 308 CrxComponent PnaclComponentInstaller::GetCrxComponent() { |
| 309 CrxComponent pnacl_component; | 309 CrxComponent pnacl_component; |
| 310 pnacl_component.version = current_version(); | 310 pnacl_component.version = current_version(); |
| 311 pnacl_component.name = "pnacl"; | 311 pnacl_component.name = "pnacl"; |
| 312 pnacl_component.installer = this; | 312 pnacl_component.installer = this; |
| 313 pnacl_component.fingerprint = current_fingerprint(); | 313 pnacl_component.fingerprint = current_fingerprint(); |
| 314 SetPnaclHash(&pnacl_component); | 314 SetPnaclHash(&pnacl_component); |
| 315 | 315 |
| 316 return pnacl_component; | 316 return pnacl_component; |
| 317 } | 317 } |
| 318 | 318 |
| 319 namespace { | 319 namespace { |
| 320 | 320 |
| 321 void FinishPnaclUpdateRegistration(const Version& current_version, | 321 void FinishPnaclUpdateRegistration(const base::Version& current_version, |
| 322 const std::string& current_fingerprint, | 322 const std::string& current_fingerprint, |
| 323 PnaclComponentInstaller* pci) { | 323 PnaclComponentInstaller* pci) { |
| 324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 325 pci->set_current_version(current_version); | 325 pci->set_current_version(current_version); |
| 326 CheckVersionCompatiblity(current_version); | 326 CheckVersionCompatiblity(current_version); |
| 327 pci->set_current_fingerprint(current_fingerprint); | 327 pci->set_current_fingerprint(current_fingerprint); |
| 328 CrxComponent pnacl_component = pci->GetCrxComponent(); | 328 CrxComponent pnacl_component = pci->GetCrxComponent(); |
| 329 | 329 |
| 330 ComponentUpdateService::Status status = | 330 ComponentUpdateService::Status status = |
| 331 pci->cus()->RegisterComponent(pnacl_component); | 331 pci->cus()->RegisterComponent(pnacl_component); |
| 332 if (status != ComponentUpdateService::kOk | 332 if (status != ComponentUpdateService::kOk |
| 333 && status != ComponentUpdateService::kReplaced) { | 333 && status != ComponentUpdateService::kReplaced) { |
| 334 NOTREACHED() << "Pnacl component registration failed."; | 334 NOTREACHED() << "Pnacl component registration failed."; |
| 335 } | 335 } |
| 336 } | 336 } |
| 337 | 337 |
| 338 // Check if there is an existing version on disk first to know when | 338 // Check if there is an existing version on disk first to know when |
| 339 // a hosted version is actually newer. | 339 // a hosted version is actually newer. |
| 340 void StartPnaclUpdateRegistration(PnaclComponentInstaller* pci) { | 340 void StartPnaclUpdateRegistration(PnaclComponentInstaller* pci) { |
| 341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 342 base::FilePath path = pci->GetPnaclBaseDirectory(); | 342 base::FilePath path = pci->GetPnaclBaseDirectory(); |
| 343 if (!base::PathExists(path)) { | 343 if (!base::PathExists(path)) { |
| 344 if (!base::CreateDirectory(path)) { | 344 if (!base::CreateDirectory(path)) { |
| 345 NOTREACHED() << "Could not create base Pnacl directory."; | 345 NOTREACHED() << "Could not create base Pnacl directory."; |
| 346 return; | 346 return; |
| 347 } | 347 } |
| 348 } | 348 } |
| 349 | 349 |
| 350 Version current_version(kNullVersion); | 350 base::Version current_version(kNullVersion); |
| 351 std::string current_fingerprint; | 351 std::string current_fingerprint; |
| 352 std::vector<base::FilePath> older_dirs; | 352 std::vector<base::FilePath> older_dirs; |
| 353 if (GetLatestPnaclDirectory(pci, &path, ¤t_version, &older_dirs)) { | 353 if (GetLatestPnaclDirectory(pci, &path, ¤t_version, &older_dirs)) { |
| 354 scoped_ptr<base::DictionaryValue> manifest( | 354 scoped_ptr<base::DictionaryValue> manifest( |
| 355 ReadComponentManifest(path)); | 355 ReadComponentManifest(path)); |
| 356 scoped_ptr<base::DictionaryValue> pnacl_manifest( | 356 scoped_ptr<base::DictionaryValue> pnacl_manifest( |
| 357 ReadPnaclManifest(path)); | 357 ReadPnaclManifest(path)); |
| 358 Version manifest_version; | 358 base::Version manifest_version; |
| 359 // Check that the component manifest and PNaCl manifest files | 359 // Check that the component manifest and PNaCl manifest files |
| 360 // are legit, and that the indicated version matches the one | 360 // are legit, and that the indicated version matches the one |
| 361 // encoded within the path name. | 361 // encoded within the path name. |
| 362 if (manifest == NULL || pnacl_manifest == NULL | 362 if (manifest == NULL || pnacl_manifest == NULL |
| 363 || !CheckPnaclComponentManifest(*manifest, | 363 || !CheckPnaclComponentManifest(*manifest, |
| 364 *pnacl_manifest, | 364 *pnacl_manifest, |
| 365 &manifest_version) | 365 &manifest_version) |
| 366 || !current_version.Equals(manifest_version)) { | 366 || !current_version.Equals(manifest_version)) { |
| 367 current_version = Version(kNullVersion); | 367 current_version = base::Version(kNullVersion); |
| 368 } else { | 368 } else { |
| 369 OverrideDirPnaclComponent(path); | 369 OverrideDirPnaclComponent(path); |
| 370 base::ReadFileToString(path.AppendASCII("manifest.fingerprint"), | 370 base::ReadFileToString(path.AppendASCII("manifest.fingerprint"), |
| 371 ¤t_fingerprint); | 371 ¤t_fingerprint); |
| 372 } | 372 } |
| 373 } | 373 } |
| 374 | 374 |
| 375 // If updates are disabled, only discover the current version | 375 // If updates are disabled, only discover the current version |
| 376 // and OverrideDirPnaclComponent. That way, developers can use | 376 // and OverrideDirPnaclComponent. That way, developers can use |
| 377 // a pinned version. Do not actually finish registration with | 377 // a pinned version. Do not actually finish registration with |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 } | 456 } |
| 457 | 457 |
| 458 | 458 |
| 459 namespace pnacl { | 459 namespace pnacl { |
| 460 | 460 |
| 461 bool NeedsOnDemandUpdate() { | 461 bool NeedsOnDemandUpdate() { |
| 462 return base::subtle::NoBarrier_Load(&needs_on_demand_update) != 0; | 462 return base::subtle::NoBarrier_Load(&needs_on_demand_update) != 0; |
| 463 } | 463 } |
| 464 | 464 |
| 465 } // namespace pnacl | 465 } // namespace pnacl |
| OLD | NEW |