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 |