Index: extensions/browser/content_verifier.cc |
diff --git a/extensions/browser/content_verifier.cc b/extensions/browser/content_verifier.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..879ee2511fdbc340492f96173ba2522616758628 |
--- /dev/null |
+++ b/extensions/browser/content_verifier.cc |
@@ -0,0 +1,125 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "extensions/browser/content_verifier.h" |
+ |
+#include <algorithm> |
+ |
+#include "base/command_line.h" |
+#include "base/files/file_path.h" |
+#include "base/metrics/field_trial.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "extensions/browser/extension_registry.h" |
+#include "extensions/common/switches.h" |
+ |
+namespace { |
+ |
+const char kExperimentName[] = "ExtensionContentVerification"; |
+ |
+} // namespace |
+ |
+namespace extensions { |
+ |
+ContentVerifier::ContentVerifier(content::BrowserContext* context, |
+ const ContentVerifierFilter& filter) |
+ : mode_(GetMode()), |
+ filter_(filter), |
+ context_(context), |
+ observers_(new ObserverListThreadSafe<ContentVerifierObserver>) { |
+} |
+ |
+ContentVerifier::~ContentVerifier() { |
+} |
+ |
+void ContentVerifier::Start() { |
+} |
+ |
+void ContentVerifier::Shutdown() { |
+ filter_.Reset(); |
+} |
+ |
+ContentVerifyJob* ContentVerifier::CreateJobFor( |
+ const std::string& extension_id, |
+ const base::FilePath& extension_root, |
+ const base::FilePath& relative_path) { |
+ if (filter_.is_null()) |
+ return NULL; |
+ |
+ ExtensionRegistry* registry = ExtensionRegistry::Get(context_); |
+ const Extension* extension = |
+ registry->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING); |
+ |
+ if (!extension || !filter_.Run(extension)) |
+ return NULL; |
+ |
+ return new ContentVerifyJob( |
+ extension_id, |
+ base::Bind(&ContentVerifier::VerifyFailed, this, extension->id())); |
+} |
+ |
+void ContentVerifier::VerifyFailed(const std::string& extension_id, |
+ ContentVerifyJob::FailureReason reason) { |
+ if (mode_ < ENFORCE) |
+ return; |
+ |
+ if (reason == ContentVerifyJob::NO_HASHES && mode_ < ENFORCE_STRICT) { |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&ContentVerifier::RequestFetch, this, extension_id)); |
+ return; |
+ } |
+ |
+ // The magic of ObserverListThreadSafe will make sure that observers get |
+ // called on the same threads that they called AddObserver on. |
+ observers_->Notify(&ContentVerifierObserver::ContentVerifyFailed, |
+ extension_id); |
+} |
+ |
+void ContentVerifier::AddObserver(ContentVerifierObserver* observer) { |
+ observers_->AddObserver(observer); |
+} |
+ |
+void ContentVerifier::RemoveObserver(ContentVerifierObserver* observer) { |
+ observers_->RemoveObserver(observer); |
+} |
+ |
+void ContentVerifier::RequestFetch(const std::string& extension_id) { |
+} |
+ |
+// static |
+ContentVerifier::Mode ContentVerifier::GetMode() { |
+ Mode experiment_value = NONE; |
+ const std::string group = base::FieldTrialList::FindFullName(kExperimentName); |
+ if (group == "EnforceStrict") |
+ experiment_value = ENFORCE_STRICT; |
+ else if (group == "Enforce") |
+ experiment_value = ENFORCE; |
+ else if (group == "Bootstrap") |
+ experiment_value = BOOTSTRAP; |
+ |
+ Mode cmdline_value = NONE; |
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
+ if (command_line->HasSwitch(switches::kExtensionContentVerification)) { |
+ std::string switch_value = command_line->GetSwitchValueASCII( |
+ switches::kExtensionContentVerification); |
+ if (switch_value == switches::kExtensionContentVerificationBootstrap) |
+ cmdline_value = BOOTSTRAP; |
+ else if (switch_value == switches::kExtensionContentVerificationEnforce) |
+ cmdline_value = ENFORCE; |
+ else if (switch_value == |
+ switches::kExtensionContentVerificationEnforceStrict) |
+ cmdline_value = ENFORCE_STRICT; |
+ else |
+ // If no value was provided (or the wrong one), just default to enforce. |
+ cmdline_value = ENFORCE; |
+ } |
+ |
+ // We don't want to allow the command-line flags to eg disable enforcement if |
+ // the experiment group says it should be on, or malware may just modify the |
+ // command line flags. So return the more restrictive of the 2 values. |
+ return std::max(experiment_value, cmdline_value); |
+} |
+ |
+} // namespace extensions |