OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "extensions/browser/content_verifier.h" | 5 #include "extensions/browser/content_verifier.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <utility> | 8 #include <utility> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 const std::string& extension_id, | 106 const std::string& extension_id, |
107 const base::FilePath& extension_root, | 107 const base::FilePath& extension_root, |
108 const base::FilePath& relative_path) { | 108 const base::FilePath& relative_path) { |
109 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 109 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
110 | 110 |
111 const ContentVerifierIOData::ExtensionData* data = | 111 const ContentVerifierIOData::ExtensionData* data = |
112 io_data_->GetData(extension_id); | 112 io_data_->GetData(extension_id); |
113 if (!data) | 113 if (!data) |
114 return NULL; | 114 return NULL; |
115 | 115 |
116 base::FilePath normalized_path = NormalizeRelativePath(relative_path); | 116 base::FilePath normalized_unix_path = NormalizeRelativePath(relative_path); |
117 | 117 |
118 std::set<base::FilePath> paths; | 118 std::set<base::FilePath> unix_paths; |
119 paths.insert(normalized_path); | 119 unix_paths.insert(normalized_unix_path); |
120 if (!ShouldVerifyAnyPaths(extension_id, extension_root, paths)) | 120 if (!ShouldVerifyAnyPaths(extension_id, extension_root, unix_paths)) |
121 return NULL; | 121 return NULL; |
122 | 122 |
123 // TODO(asargent) - we can probably get some good performance wins by having | 123 // TODO(asargent) - we can probably get some good performance wins by having |
124 // a cache of ContentHashReader's that we hold onto past the end of each job. | 124 // a cache of ContentHashReader's that we hold onto past the end of each job. |
125 return new ContentVerifyJob( | 125 return new ContentVerifyJob( |
126 new ContentHashReader(extension_id, data->version, extension_root, | 126 new ContentHashReader(extension_id, data->version, extension_root, |
127 normalized_path, delegate_->GetPublicKey()), | 127 normalized_unix_path, delegate_->GetPublicKey()), |
128 base::Bind(&ContentVerifier::VerifyFailed, this, extension_id)); | 128 base::Bind(&ContentVerifier::VerifyFailed, this, extension_id)); |
129 } | 129 } |
130 | 130 |
131 void ContentVerifier::VerifyFailed(const std::string& extension_id, | 131 void ContentVerifier::VerifyFailed(const std::string& extension_id, |
132 ContentVerifyJob::FailureReason reason) { | 132 ContentVerifyJob::FailureReason reason) { |
133 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { | 133 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { |
134 content::BrowserThread::PostTask( | 134 content::BrowserThread::PostTask( |
135 content::BrowserThread::UI, | 135 content::BrowserThread::UI, |
136 FROM_HERE, | 136 FROM_HERE, |
137 base::Bind(&ContentVerifier::VerifyFailed, this, extension_id, reason)); | 137 base::Bind(&ContentVerifier::VerifyFailed, this, extension_id, reason)); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 void ContentVerifier::OnFetchCompleteHelper(const std::string& extension_id, | 210 void ContentVerifier::OnFetchCompleteHelper(const std::string& extension_id, |
211 bool shouldVerifyAnyPathsResult) { | 211 bool shouldVerifyAnyPathsResult) { |
212 if (shouldVerifyAnyPathsResult) | 212 if (shouldVerifyAnyPathsResult) |
213 delegate_->VerifyFailed(extension_id, ContentVerifyJob::MISSING_ALL_HASHES); | 213 delegate_->VerifyFailed(extension_id, ContentVerifyJob::MISSING_ALL_HASHES); |
214 } | 214 } |
215 | 215 |
216 void ContentVerifier::OnFetchComplete( | 216 void ContentVerifier::OnFetchComplete( |
217 const std::string& extension_id, | 217 const std::string& extension_id, |
218 bool success, | 218 bool success, |
219 bool was_force_check, | 219 bool was_force_check, |
220 const std::set<base::FilePath>& hash_mismatch_paths) { | 220 const std::set<base::FilePath>& hash_mismatch_unix_paths) { |
221 if (g_test_observer) | 221 if (g_test_observer) |
222 g_test_observer->OnFetchComplete(extension_id, success); | 222 g_test_observer->OnFetchComplete(extension_id, success); |
223 | 223 |
224 if (shutdown_) | 224 if (shutdown_) |
225 return; | 225 return; |
226 | 226 |
227 VLOG(1) << "OnFetchComplete " << extension_id << " success:" << success; | 227 VLOG(1) << "OnFetchComplete " << extension_id << " success:" << success; |
228 | 228 |
229 ExtensionRegistry* registry = ExtensionRegistry::Get(context_); | 229 ExtensionRegistry* registry = ExtensionRegistry::Get(context_); |
230 const Extension* extension = | 230 const Extension* extension = |
231 registry->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING); | 231 registry->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING); |
232 if (!delegate_ || !extension) | 232 if (!delegate_ || !extension) |
233 return; | 233 return; |
234 | 234 |
235 ContentVerifierDelegate::Mode mode = delegate_->ShouldBeVerified(*extension); | 235 ContentVerifierDelegate::Mode mode = delegate_->ShouldBeVerified(*extension); |
236 if (was_force_check && !success && | 236 if (was_force_check && !success && |
237 mode == ContentVerifierDelegate::ENFORCE_STRICT) { | 237 mode == ContentVerifierDelegate::ENFORCE_STRICT) { |
238 // We weren't able to get verified_contents.json or weren't able to compute | 238 // We weren't able to get verified_contents.json or weren't able to compute |
239 // hashes. | 239 // hashes. |
240 delegate_->VerifyFailed(extension_id, ContentVerifyJob::MISSING_ALL_HASHES); | 240 delegate_->VerifyFailed(extension_id, ContentVerifyJob::MISSING_ALL_HASHES); |
241 } else { | 241 } else { |
242 content::BrowserThread::PostTaskAndReplyWithResult( | 242 content::BrowserThread::PostTaskAndReplyWithResult( |
243 content::BrowserThread::IO, | 243 content::BrowserThread::IO, FROM_HERE, |
244 FROM_HERE, | 244 base::Bind(&ContentVerifier::ShouldVerifyAnyPaths, this, extension_id, |
245 base::Bind(&ContentVerifier::ShouldVerifyAnyPaths, | 245 extension->path(), hash_mismatch_unix_paths), |
246 this, | 246 base::Bind(&ContentVerifier::OnFetchCompleteHelper, this, |
247 extension_id, | 247 extension_id)); |
248 extension->path(), | |
249 hash_mismatch_paths), | |
250 base::Bind( | |
251 &ContentVerifier::OnFetchCompleteHelper, this, extension_id)); | |
252 } | 248 } |
253 } | 249 } |
254 | 250 |
255 bool ContentVerifier::ShouldVerifyAnyPaths( | 251 bool ContentVerifier::ShouldVerifyAnyPaths( |
256 const std::string& extension_id, | 252 const std::string& extension_id, |
257 const base::FilePath& extension_root, | 253 const base::FilePath& extension_root, |
258 const std::set<base::FilePath>& relative_paths) { | 254 const std::set<base::FilePath>& relative_unix_paths) { |
259 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 255 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
260 const ContentVerifierIOData::ExtensionData* data = | 256 const ContentVerifierIOData::ExtensionData* data = |
261 io_data_->GetData(extension_id); | 257 io_data_->GetData(extension_id); |
262 if (!data) | 258 if (!data) |
263 return false; | 259 return false; |
264 | 260 |
265 const std::set<base::FilePath>& browser_images = *(data->browser_image_paths); | 261 const std::set<base::FilePath>& browser_images = *(data->browser_image_paths); |
266 | 262 |
267 base::FilePath locales_dir = extension_root.Append(kLocaleFolder); | 263 base::FilePath locales_dir = extension_root.Append(kLocaleFolder); |
268 std::unique_ptr<std::set<std::string>> all_locales; | 264 std::unique_ptr<std::set<std::string>> all_locales; |
269 | 265 |
270 for (std::set<base::FilePath>::const_iterator i = relative_paths.begin(); | 266 const base::FilePath manifest_file(kManifestFilename); |
271 i != relative_paths.end(); | 267 const base::FilePath messages_file(kMessagesFilename); |
272 ++i) { | 268 for (const base::FilePath& relative_unix_path : relative_unix_paths) { |
273 const base::FilePath& relative_path = *i; | 269 if (relative_unix_path == manifest_file) |
274 | |
275 if (relative_path == base::FilePath(kManifestFilename)) | |
276 continue; | 270 continue; |
277 | 271 |
278 if (base::ContainsKey(browser_images, relative_path)) | 272 if (base::ContainsKey(browser_images, relative_unix_path)) |
279 continue; | 273 continue; |
280 | 274 |
281 base::FilePath full_path = extension_root.Append(relative_path); | 275 base::FilePath full_path = |
| 276 extension_root.Append(relative_unix_path.NormalizePathSeparators()); |
282 if (locales_dir.IsParent(full_path)) { | 277 if (locales_dir.IsParent(full_path)) { |
283 if (!all_locales) { | 278 if (!all_locales) { |
284 // TODO(asargent) - see if we can cache this list longer to avoid | 279 // TODO(asargent) - see if we can cache this list longer to avoid |
285 // having to fetch it more than once for a given run of the | 280 // having to fetch it more than once for a given run of the |
286 // browser. Maybe it can never change at runtime? (Or if it can, maybe | 281 // browser. Maybe it can never change at runtime? (Or if it can, maybe |
287 // there is an event we can listen for to know to drop our cache). | 282 // there is an event we can listen for to know to drop our cache). |
288 all_locales.reset(new std::set<std::string>); | 283 all_locales.reset(new std::set<std::string>); |
289 extension_l10n_util::GetAllLocales(all_locales.get()); | 284 extension_l10n_util::GetAllLocales(all_locales.get()); |
290 } | 285 } |
291 | 286 |
292 // Since message catalogs get transcoded during installation, we want | 287 // Since message catalogs get transcoded during installation, we want |
293 // to skip those paths. | 288 // to skip those paths. See if this path looks like |
294 if (full_path.DirName().DirName() == locales_dir && | 289 // _locales/<some locale>/messages.json - if so then skip it. |
295 !extension_l10n_util::ShouldSkipValidation( | 290 if (full_path.BaseName() == messages_file && |
296 locales_dir, full_path.DirName(), *all_locales)) | 291 full_path.DirName().DirName() == locales_dir && |
| 292 base::ContainsKey(*all_locales, |
| 293 full_path.DirName().BaseName().MaybeAsASCII())) { |
297 continue; | 294 continue; |
| 295 } |
298 } | 296 } |
299 return true; | 297 return true; |
300 } | 298 } |
301 return false; | 299 return false; |
302 } | 300 } |
303 | 301 |
304 } // namespace extensions | 302 } // namespace extensions |
OLD | NEW |