Index: extensions/browser/content_verifier.cc |
diff --git a/extensions/browser/content_verifier.cc b/extensions/browser/content_verifier.cc |
index 1bfa1f42aee94930426f4a126f1325e12e75db8a..52321c9267ac9e6cdc3e366a47584026e7b58d66 100644 |
--- a/extensions/browser/content_verifier.cc |
+++ b/extensions/browser/content_verifier.cc |
@@ -12,6 +12,7 @@ |
#include "extensions/browser/content_hash_fetcher.h" |
#include "extensions/browser/content_hash_reader.h" |
#include "extensions/browser/content_verifier_delegate.h" |
+#include "extensions/browser/content_verifier_io_data.h" |
#include "extensions/browser/extension_registry.h" |
#include "extensions/common/constants.h" |
#include "extensions/common/extension_l10n_util.h" |
@@ -20,51 +21,60 @@ namespace extensions { |
ContentVerifier::ContentVerifier(content::BrowserContext* context, |
ContentVerifierDelegate* delegate) |
- : context_(context), |
+ : shutdown_(false), |
+ context_(context), |
delegate_(delegate), |
fetcher_(new ContentHashFetcher( |
context, |
delegate, |
- base::Bind(&ContentVerifier::OnFetchComplete, this))) { |
+ base::Bind(&ContentVerifier::OnFetchComplete, this))), |
+ observer_(this), |
+ io_data_(new ContentVerifierIOData) { |
} |
ContentVerifier::~ContentVerifier() { |
} |
void ContentVerifier::Start() { |
- fetcher_->Start(); |
+ ExtensionRegistry* registry = ExtensionRegistry::Get(context_); |
+ observer_.Add(registry); |
} |
void ContentVerifier::Shutdown() { |
+ shutdown_ = true; |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::IO, |
+ FROM_HERE, |
+ base::Bind(&ContentVerifierIOData::Clear, io_data_)); |
+ observer_.RemoveAll(); |
fetcher_.reset(); |
- delegate_.reset(); |
} |
ContentVerifyJob* ContentVerifier::CreateJobFor( |
const std::string& extension_id, |
const base::FilePath& extension_root, |
const base::FilePath& relative_path) { |
- if (!fetcher_ || !delegate_) |
- return NULL; |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
- ExtensionRegistry* registry = ExtensionRegistry::Get(context_); |
- const Extension* extension = |
- registry->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING); |
+ const ContentVerifierIOData::ExtensionData* data = |
+ io_data_->GetData(extension_id); |
+ if (!data) |
+ return NULL; |
std::set<base::FilePath> paths; |
paths.insert(relative_path); |
- if (!ShouldVerifyAnyPaths(extension, paths)) |
+ if (!ShouldVerifyAnyPaths(extension_id, extension_root, paths)) |
return NULL; |
// TODO(asargent) - we can probably get some good performance wins by having |
// a cache of ContentHashReader's that we hold onto past the end of each job. |
return new ContentVerifyJob( |
new ContentHashReader(extension_id, |
- *extension->version(), |
+ data->version, |
extension_root, |
relative_path, |
delegate_->PublicKey()), |
- base::Bind(&ContentVerifier::VerifyFailed, this, extension->id())); |
+ base::Bind(&ContentVerifier::VerifyFailed, this, extension_id)); |
} |
void ContentVerifier::VerifyFailed(const std::string& extension_id, |
@@ -76,6 +86,8 @@ void ContentVerifier::VerifyFailed(const std::string& extension_id, |
base::Bind(&ContentVerifier::VerifyFailed, this, extension_id, reason)); |
return; |
} |
+ if (shutdown_) |
+ return; |
VLOG(1) << "VerifyFailed " << extension_id << " reason:" << reason; |
@@ -83,11 +95,7 @@ void ContentVerifier::VerifyFailed(const std::string& extension_id, |
const Extension* extension = |
registry->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING); |
- if (!delegate_ || !extension) |
- return; |
- |
- ContentVerifierDelegate::Mode mode = delegate_->ShouldBeVerified(*extension); |
- if (mode < ContentVerifierDelegate::ENFORCE) |
+ if (!extension) |
return; |
if (reason == ContentVerifyJob::MISSING_ALL_HASHES) { |
@@ -99,11 +107,57 @@ void ContentVerifier::VerifyFailed(const std::string& extension_id, |
} |
} |
+void ContentVerifier::OnExtensionLoaded( |
+ content::BrowserContext* browser_context, |
+ const Extension* extension) { |
+ if (shutdown_) |
+ return; |
+ |
+ ContentVerifierDelegate::Mode mode = delegate_->ShouldBeVerified(*extension); |
+ if (mode != ContentVerifierDelegate::NONE) { |
+ scoped_ptr<ContentVerifierIOData::ExtensionData> data( |
+ new ContentVerifierIOData::ExtensionData( |
+ delegate_->GetBrowserImagePaths(extension), |
+ extension->version() ? *extension->version() : base::Version())); |
+ content::BrowserThread::PostTask(content::BrowserThread::IO, |
+ FROM_HERE, |
+ base::Bind(&ContentVerifierIOData::AddData, |
+ io_data_, |
+ extension->id(), |
+ base::Passed(&data))); |
+ fetcher_->ExtensionLoaded(extension); |
+ } |
+} |
+ |
+void ContentVerifier::OnExtensionUnloaded( |
+ content::BrowserContext* browser_context, |
+ const Extension* extension, |
+ UnloadedExtensionInfo::Reason reason) { |
+ if (shutdown_) |
+ return; |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::IO, |
+ FROM_HERE, |
+ base::Bind( |
+ &ContentVerifierIOData::RemoveData, io_data_, extension->id())); |
+ if (fetcher_) |
+ fetcher_->ExtensionUnloaded(extension); |
+} |
+ |
+void ContentVerifier::OnFetchCompleteHelper(const std::string& extension_id, |
+ bool shouldVerifyAnyPathsResult) { |
+ if (shouldVerifyAnyPathsResult) |
+ delegate_->VerifyFailed(extension_id); |
+} |
+ |
void ContentVerifier::OnFetchComplete( |
const std::string& extension_id, |
bool success, |
bool was_force_check, |
const std::set<base::FilePath>& hash_mismatch_paths) { |
+ if (shutdown_) |
+ return; |
+ |
VLOG(1) << "OnFetchComplete " << extension_id << " success:" << success; |
ExtensionRegistry* registry = ExtensionRegistry::Get(context_); |
@@ -113,34 +167,38 @@ void ContentVerifier::OnFetchComplete( |
return; |
ContentVerifierDelegate::Mode mode = delegate_->ShouldBeVerified(*extension); |
- if (mode < ContentVerifierDelegate::ENFORCE) |
- return; |
- |
- if (!success && mode < ContentVerifierDelegate::ENFORCE_STRICT) |
- return; |
- |
- if ((was_force_check && !success) || |
- ShouldVerifyAnyPaths(extension, hash_mismatch_paths)) |
+ if (was_force_check && !success && |
+ mode == ContentVerifierDelegate::ENFORCE_STRICT) { |
+ // We weren't able to get verified_contents.json or weren't able to compute |
+ // hashes. |
delegate_->VerifyFailed(extension_id); |
+ } else { |
+ content::BrowserThread::PostTaskAndReplyWithResult( |
+ content::BrowserThread::IO, |
+ FROM_HERE, |
+ base::Bind(&ContentVerifier::ShouldVerifyAnyPaths, |
+ this, |
+ extension_id, |
+ extension->path(), |
+ hash_mismatch_paths), |
+ base::Bind( |
+ &ContentVerifier::OnFetchCompleteHelper, this, extension_id)); |
+ } |
} |
bool ContentVerifier::ShouldVerifyAnyPaths( |
- const Extension* extension, |
+ const std::string& extension_id, |
+ const base::FilePath& extension_root, |
const std::set<base::FilePath>& relative_paths) { |
- if (!delegate_ || !extension || !extension->version()) |
- return false; |
- |
- ContentVerifierDelegate::Mode mode = delegate_->ShouldBeVerified(*extension); |
- if (mode < ContentVerifierDelegate::ENFORCE) |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
+ const ContentVerifierIOData::ExtensionData* data = |
+ io_data_->GetData(extension_id); |
+ if (!data) |
return false; |
- // Images used in the browser get transcoded during install, so skip |
- // checking them for now. TODO(asargent) - see if we can cache this list |
- // for a given extension id/version pair. |
- std::set<base::FilePath> browser_images = |
- delegate_->GetBrowserImagePaths(extension); |
+ const std::set<base::FilePath>& browser_images = data->browser_image_paths; |
- base::FilePath locales_dir = extension->path().Append(kLocaleFolder); |
+ base::FilePath locales_dir = extension_root.Append(kLocaleFolder); |
scoped_ptr<std::set<std::string> > all_locales; |
for (std::set<base::FilePath>::const_iterator i = relative_paths.begin(); |
@@ -154,7 +212,7 @@ bool ContentVerifier::ShouldVerifyAnyPaths( |
if (ContainsKey(browser_images, relative_path)) |
continue; |
- base::FilePath full_path = extension->path().Append(relative_path); |
+ base::FilePath full_path = extension_root.Append(relative_path); |
if (locales_dir.IsParent(full_path)) { |
if (!all_locales) { |
// TODO(asargent) - see if we can cache this list longer to avoid |