| 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_component_installer.h" | 5 #include "chrome/browser/component_updater/pnacl_component_installer.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 return base_path.AppendASCII("_platform_specific").AppendASCII(arch); | 87 return base_path.AppendASCII("_platform_specific").AppendASCII(arch); |
| 88 } | 88 } |
| 89 | 89 |
| 90 // Tell the rest of the world where to find the platform-specific PNaCl files. | 90 // Tell the rest of the world where to find the platform-specific PNaCl files. |
| 91 void OverrideDirPnaclComponent(const base::FilePath& base_path) { | 91 void OverrideDirPnaclComponent(const base::FilePath& base_path) { |
| 92 PathService::Override(chrome::DIR_PNACL_COMPONENT, GetPlatformDir(base_path)); | 92 PathService::Override(chrome::DIR_PNACL_COMPONENT, GetPlatformDir(base_path)); |
| 93 } | 93 } |
| 94 | 94 |
| 95 bool GetLatestPnaclDirectory(const scoped_refptr<PnaclComponentInstaller>& pci, | 95 bool GetLatestPnaclDirectory(const scoped_refptr<PnaclComponentInstaller>& pci, |
| 96 base::FilePath* latest_dir, | 96 base::FilePath* latest_dir, |
| 97 base::Version* latest_version, | 97 Version* latest_version, |
| 98 std::vector<base::FilePath>* older_dirs) { | 98 std::vector<base::FilePath>* older_dirs) { |
| 99 // Enumerate all versions starting from the base directory. | 99 // Enumerate all versions starting from the base directory. |
| 100 base::FilePath base_dir = pci->GetPnaclBaseDirectory(); | 100 base::FilePath base_dir = pci->GetPnaclBaseDirectory(); |
| 101 bool found = false; | 101 bool found = false; |
| 102 base::FileEnumerator file_enumerator( | 102 base::FileEnumerator file_enumerator( |
| 103 base_dir, false, base::FileEnumerator::DIRECTORIES); | 103 base_dir, false, base::FileEnumerator::DIRECTORIES); |
| 104 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); | 104 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); |
| 105 path = file_enumerator.Next()) { | 105 path = file_enumerator.Next()) { |
| 106 base::Version version(path.BaseName().MaybeAsASCII()); | 106 Version version(path.BaseName().MaybeAsASCII()); |
| 107 if (!version.IsValid()) | 107 if (!version.IsValid()) |
| 108 continue; | 108 continue; |
| 109 if (found) { | 109 if (found) { |
| 110 if (version.CompareTo(*latest_version) > 0) { | 110 if (version.CompareTo(*latest_version) > 0) { |
| 111 older_dirs->push_back(*latest_dir); | 111 older_dirs->push_back(*latest_dir); |
| 112 *latest_dir = path; | 112 *latest_dir = path; |
| 113 *latest_version = version; | 113 *latest_version = version; |
| 114 } else { | 114 } else { |
| 115 older_dirs->push_back(path); | 115 older_dirs->push_back(path); |
| 116 } | 116 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 unpack_path.Append(FILE_PATH_LITERAL("manifest.json")); | 151 unpack_path.Append(FILE_PATH_LITERAL("manifest.json")); |
| 152 if (!base::PathExists(manifest_path)) | 152 if (!base::PathExists(manifest_path)) |
| 153 return NULL; | 153 return NULL; |
| 154 return ReadJSONManifest(manifest_path); | 154 return ReadJSONManifest(manifest_path); |
| 155 } | 155 } |
| 156 | 156 |
| 157 // Check that the component's manifest is for PNaCl, and check the | 157 // Check that the component's manifest is for PNaCl, and check the |
| 158 // PNaCl manifest indicates this is the correct arch-specific package. | 158 // PNaCl manifest indicates this is the correct arch-specific package. |
| 159 bool CheckPnaclComponentManifest(const base::DictionaryValue& manifest, | 159 bool CheckPnaclComponentManifest(const base::DictionaryValue& manifest, |
| 160 const base::DictionaryValue& pnacl_manifest, | 160 const base::DictionaryValue& pnacl_manifest, |
| 161 base::Version* version_out) { | 161 Version* version_out) { |
| 162 // Make sure we have the right |manifest| file. | 162 // Make sure we have the right |manifest| file. |
| 163 std::string name; | 163 std::string name; |
| 164 if (!manifest.GetStringASCII("name", &name)) { | 164 if (!manifest.GetStringASCII("name", &name)) { |
| 165 LOG(WARNING) << "'name' field is missing from manifest!"; | 165 LOG(WARNING) << "'name' field is missing from manifest!"; |
| 166 return false; | 166 return false; |
| 167 } | 167 } |
| 168 // For the webstore, we've given different names to each of the | 168 // For the webstore, we've given different names to each of the |
| 169 // architecture specific packages (and test/QA vs not test/QA) | 169 // architecture specific packages (and test/QA vs not test/QA) |
| 170 // so only part of it is the same. | 170 // so only part of it is the same. |
| 171 if (name.find(kPnaclManifestName) == std::string::npos) { | 171 if (name.find(kPnaclManifestName) == std::string::npos) { |
| 172 LOG(WARNING) << "'name' field in manifest is invalid (" << name | 172 LOG(WARNING) << "'name' field in manifest is invalid (" << name |
| 173 << ") -- missing (" << kPnaclManifestName << ")"; | 173 << ") -- missing (" << kPnaclManifestName << ")"; |
| 174 return false; | 174 return false; |
| 175 } | 175 } |
| 176 | 176 |
| 177 std::string proposed_version; | 177 std::string proposed_version; |
| 178 if (!manifest.GetStringASCII("version", &proposed_version)) { | 178 if (!manifest.GetStringASCII("version", &proposed_version)) { |
| 179 LOG(WARNING) << "'version' field is missing from manifest!"; | 179 LOG(WARNING) << "'version' field is missing from manifest!"; |
| 180 return false; | 180 return false; |
| 181 } | 181 } |
| 182 base::Version version(proposed_version.c_str()); | 182 Version version(proposed_version.c_str()); |
| 183 if (!version.IsValid()) { | 183 if (!version.IsValid()) { |
| 184 LOG(WARNING) << "'version' field in manifest is invalid " | 184 LOG(WARNING) << "'version' field in manifest is invalid " |
| 185 << version.GetString(); | 185 << version.GetString(); |
| 186 return false; | 186 return false; |
| 187 } | 187 } |
| 188 | 188 |
| 189 // Now check the |pnacl_manifest|. | 189 // Now check the |pnacl_manifest|. |
| 190 std::string arch; | 190 std::string arch; |
| 191 if (!pnacl_manifest.GetStringASCII("pnacl-arch", &arch)) { | 191 if (!pnacl_manifest.GetStringASCII("pnacl-arch", &arch)) { |
| 192 LOG(WARNING) << "'pnacl-arch' field is missing from pnacl-manifest!"; | 192 LOG(WARNING) << "'pnacl-arch' field is missing from pnacl-manifest!"; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 | 226 |
| 227 bool PnaclComponentInstaller::Install(const base::DictionaryValue& manifest, | 227 bool PnaclComponentInstaller::Install(const base::DictionaryValue& manifest, |
| 228 const base::FilePath& unpack_path) { | 228 const base::FilePath& unpack_path) { |
| 229 scoped_ptr<base::DictionaryValue> pnacl_manifest( | 229 scoped_ptr<base::DictionaryValue> pnacl_manifest( |
| 230 ReadPnaclManifest(unpack_path)); | 230 ReadPnaclManifest(unpack_path)); |
| 231 if (pnacl_manifest == NULL) { | 231 if (pnacl_manifest == NULL) { |
| 232 LOG(WARNING) << "Failed to read pnacl manifest."; | 232 LOG(WARNING) << "Failed to read pnacl manifest."; |
| 233 return false; | 233 return false; |
| 234 } | 234 } |
| 235 | 235 |
| 236 base::Version version; | 236 Version version; |
| 237 if (!CheckPnaclComponentManifest(manifest, *pnacl_manifest, &version)) { | 237 if (!CheckPnaclComponentManifest(manifest, *pnacl_manifest, &version)) { |
| 238 LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing."; | 238 LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing."; |
| 239 return false; | 239 return false; |
| 240 } | 240 } |
| 241 | 241 |
| 242 // Don't install if the current version is actually newer. | 242 // Don't install if the current version is actually newer. |
| 243 if (current_version().CompareTo(version) > 0) { | 243 if (current_version().CompareTo(version) > 0) { |
| 244 return false; | 244 return false; |
| 245 } | 245 } |
| 246 | 246 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 264 OverrideDirPnaclComponent(path); | 264 OverrideDirPnaclComponent(path); |
| 265 return true; | 265 return true; |
| 266 } | 266 } |
| 267 | 267 |
| 268 // Given |file|, which can be a path like "_platform_specific/arm/pnacl_foo", | 268 // Given |file|, which can be a path like "_platform_specific/arm/pnacl_foo", |
| 269 // returns the assumed install path. The path separator in |file| is '/' | 269 // returns the assumed install path. The path separator in |file| is '/' |
| 270 // for all platforms. Caller is responsible for checking that the | 270 // for all platforms. Caller is responsible for checking that the |
| 271 // |installed_file| actually exists. | 271 // |installed_file| actually exists. |
| 272 bool PnaclComponentInstaller::GetInstalledFile(const std::string& file, | 272 bool PnaclComponentInstaller::GetInstalledFile(const std::string& file, |
| 273 base::FilePath* installed_file) { | 273 base::FilePath* installed_file) { |
| 274 if (current_version().Equals(base::Version(kNullVersion))) | 274 if (current_version().Equals(Version(kNullVersion))) |
| 275 return false; | 275 return false; |
| 276 | 276 |
| 277 *installed_file = GetPnaclBaseDirectory() | 277 *installed_file = GetPnaclBaseDirectory() |
| 278 .AppendASCII(current_version().GetString()) | 278 .AppendASCII(current_version().GetString()) |
| 279 .AppendASCII(file); | 279 .AppendASCII(file); |
| 280 return true; | 280 return true; |
| 281 } | 281 } |
| 282 | 282 |
| 283 bool PnaclComponentInstaller::Uninstall() { | 283 bool PnaclComponentInstaller::Uninstall() { |
| 284 return false; | 284 return false; |
| 285 } | 285 } |
| 286 | 286 |
| 287 CrxComponent PnaclComponentInstaller::GetCrxComponent() { | 287 CrxComponent PnaclComponentInstaller::GetCrxComponent() { |
| 288 CrxComponent pnacl_component; | 288 CrxComponent pnacl_component; |
| 289 pnacl_component.version = current_version(); | 289 pnacl_component.version = current_version(); |
| 290 pnacl_component.name = "pnacl"; | 290 pnacl_component.name = "pnacl"; |
| 291 pnacl_component.installer = this; | 291 pnacl_component.installer = this; |
| 292 pnacl_component.fingerprint = current_fingerprint(); | 292 pnacl_component.fingerprint = current_fingerprint(); |
| 293 SetPnaclHash(&pnacl_component); | 293 SetPnaclHash(&pnacl_component); |
| 294 | 294 |
| 295 return pnacl_component; | 295 return pnacl_component; |
| 296 } | 296 } |
| 297 | 297 |
| 298 namespace { | 298 namespace { |
| 299 | 299 |
| 300 void FinishPnaclUpdateRegistration( | 300 void FinishPnaclUpdateRegistration( |
| 301 const base::Version& current_version, | 301 const Version& current_version, |
| 302 const std::string& current_fingerprint, | 302 const std::string& current_fingerprint, |
| 303 const scoped_refptr<PnaclComponentInstaller>& pci) { | 303 const scoped_refptr<PnaclComponentInstaller>& pci) { |
| 304 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 304 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 305 pci->set_current_version(current_version); | 305 pci->set_current_version(current_version); |
| 306 CheckVersionCompatiblity(current_version); | 306 CheckVersionCompatiblity(current_version); |
| 307 pci->set_current_fingerprint(current_fingerprint); | 307 pci->set_current_fingerprint(current_fingerprint); |
| 308 CrxComponent pnacl_component = pci->GetCrxComponent(); | 308 CrxComponent pnacl_component = pci->GetCrxComponent(); |
| 309 | 309 |
| 310 if (!pci->cus()->RegisterComponent(pnacl_component)) | 310 if (!pci->cus()->RegisterComponent(pnacl_component)) |
| 311 NOTREACHED() << "Pnacl component registration failed."; | 311 NOTREACHED() << "Pnacl component registration failed."; |
| 312 } | 312 } |
| 313 | 313 |
| 314 // Check if there is an existing version on disk first to know when | 314 // Check if there is an existing version on disk first to know when |
| 315 // a hosted version is actually newer. | 315 // a hosted version is actually newer. |
| 316 void StartPnaclUpdateRegistration( | 316 void StartPnaclUpdateRegistration( |
| 317 const scoped_refptr<PnaclComponentInstaller>& pci) { | 317 const scoped_refptr<PnaclComponentInstaller>& pci) { |
| 318 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 318 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 319 base::FilePath path = pci->GetPnaclBaseDirectory(); | 319 base::FilePath path = pci->GetPnaclBaseDirectory(); |
| 320 if (!base::PathExists(path)) { | 320 if (!base::PathExists(path)) { |
| 321 if (!base::CreateDirectory(path)) { | 321 if (!base::CreateDirectory(path)) { |
| 322 NOTREACHED() << "Could not create base Pnacl directory."; | 322 NOTREACHED() << "Could not create base Pnacl directory."; |
| 323 return; | 323 return; |
| 324 } | 324 } |
| 325 } | 325 } |
| 326 | 326 |
| 327 base::Version current_version(kNullVersion); | 327 Version current_version(kNullVersion); |
| 328 std::string current_fingerprint; | 328 std::string current_fingerprint; |
| 329 std::vector<base::FilePath> older_dirs; | 329 std::vector<base::FilePath> older_dirs; |
| 330 if (GetLatestPnaclDirectory(pci, &path, ¤t_version, &older_dirs)) { | 330 if (GetLatestPnaclDirectory(pci, &path, ¤t_version, &older_dirs)) { |
| 331 scoped_ptr<base::DictionaryValue> manifest(ReadComponentManifest(path)); | 331 scoped_ptr<base::DictionaryValue> manifest(ReadComponentManifest(path)); |
| 332 scoped_ptr<base::DictionaryValue> pnacl_manifest(ReadPnaclManifest(path)); | 332 scoped_ptr<base::DictionaryValue> pnacl_manifest(ReadPnaclManifest(path)); |
| 333 base::Version manifest_version; | 333 Version manifest_version; |
| 334 // Check that the component manifest and PNaCl manifest files | 334 // Check that the component manifest and PNaCl manifest files |
| 335 // are legit, and that the indicated version matches the one | 335 // are legit, and that the indicated version matches the one |
| 336 // encoded within the path name. | 336 // encoded within the path name. |
| 337 if (manifest == NULL || pnacl_manifest == NULL || | 337 if (manifest == NULL || pnacl_manifest == NULL || |
| 338 !CheckPnaclComponentManifest(*manifest, | 338 !CheckPnaclComponentManifest(*manifest, |
| 339 *pnacl_manifest, | 339 *pnacl_manifest, |
| 340 &manifest_version) || | 340 &manifest_version) || |
| 341 !current_version.Equals(manifest_version)) { | 341 !current_version.Equals(manifest_version)) { |
| 342 current_version = base::Version(kNullVersion); | 342 current_version = Version(kNullVersion); |
| 343 } else { | 343 } else { |
| 344 OverrideDirPnaclComponent(path); | 344 OverrideDirPnaclComponent(path); |
| 345 base::ReadFileToString(path.AppendASCII("manifest.fingerprint"), | 345 base::ReadFileToString(path.AppendASCII("manifest.fingerprint"), |
| 346 ¤t_fingerprint); | 346 ¤t_fingerprint); |
| 347 } | 347 } |
| 348 } | 348 } |
| 349 | 349 |
| 350 BrowserThread::PostTask(BrowserThread::UI, | 350 BrowserThread::PostTask(BrowserThread::UI, |
| 351 FROM_HERE, | 351 FROM_HERE, |
| 352 base::Bind(&FinishPnaclUpdateRegistration, | 352 base::Bind(&FinishPnaclUpdateRegistration, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 375 } // namespace component_updater | 375 } // namespace component_updater |
| 376 | 376 |
| 377 namespace pnacl { | 377 namespace pnacl { |
| 378 | 378 |
| 379 bool NeedsOnDemandUpdate() { | 379 bool NeedsOnDemandUpdate() { |
| 380 return base::subtle::NoBarrier_Load( | 380 return base::subtle::NoBarrier_Load( |
| 381 &component_updater::needs_on_demand_update) != 0; | 381 &component_updater::needs_on_demand_update) != 0; |
| 382 } | 382 } |
| 383 | 383 |
| 384 } // namespace pnacl | 384 } // namespace pnacl |
| OLD | NEW |