Index: extensions/browser/api/declarative_net_request/rules_monitor.cc |
diff --git a/extensions/browser/api/declarative_net_request/rules_monitor.cc b/extensions/browser/api/declarative_net_request/rules_monitor.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a930a45765fb993d3601d8a6291e2b58850cdc2b |
--- /dev/null |
+++ b/extensions/browser/api/declarative_net_request/rules_monitor.cc |
@@ -0,0 +1,131 @@ |
+// Copyright 2017 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/api/declarative_net_request/rules_monitor.h" |
+ |
+#include "base/bind.h" |
+#include "base/callback.h" |
+#include "base/files/file.h" |
+#include "base/files/file_util.h" |
+#include "base/files/memory_mapped_file.h" |
+#include "base/location.h" |
+#include "base/memory/ptr_util.h" |
+#include "base/metrics/histogram_macros.h" |
+#include "base/sequenced_task_runner.h" |
+#include "base/strings/stringprintf.h" |
+#include "base/threading/thread_restrictions.h" |
+#include "content/public/browser/browser_context.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "extensions/browser/api/declarative_net_request/matcher_util.h" |
+#include "extensions/browser/extension_registry.h" |
+#include "extensions/browser/extension_system.h" |
+#include "extensions/browser/extension_util.h" |
+#include "extensions/browser/info_map.h" |
+#include "extensions/common/api/declarative_net_request/indexed_rule.h" |
+#include "extensions/common/extension_id.h" |
+#include "extensions/common/file_util.h" |
+ |
+namespace extensions { |
+namespace declarative_net_request { |
+ |
+namespace { |
+ |
+// Can't seem to use a raw pointer for InfoMap here as recommended in |
+// https://chromium.googlesource.com/chromium/src/+/master/docs/design/threading.md. |
+void LoadRulesetOnIOThread( |
+ std::string extension_id, |
+ std::unique_ptr<ExtensionIndexedRulesetMatcher> ruleset_matcher, |
+ scoped_refptr<InfoMap> info_map) { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
+ info_map->ruleset_manager()->AddRuleset(std::move(extension_id), |
+ std::move(ruleset_matcher)); |
+} |
+ |
+void UnloadRulesetOnIOThread(std::string extension_id, |
+ scoped_refptr<InfoMap> info_map) { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
+ info_map->ruleset_manager()->RemoveRuleset(std::move(extension_id)); |
+} |
+ |
+// The |extension_id| here doesn't tell us about the associated BrowserContext. |
+// But |info_map| does. |
+void LoadRulesetOnFileThread(std::string extension_id, |
+ base::FilePath indexed_file_path, |
+ scoped_refptr<InfoMap> info_map) { |
+ // TODO not sure if this is exactly the file thread, but CrxInstaller uses the |
+ // same terminology. TODO is passing extension pointer safe Or would it |
+ // require to add ref. |
+ base::ThreadRestrictions::AssertIOAllowed(); |
+ |
+ // This can also me made a movable type, hence preventing dynamic allocation. |
+ std::unique_ptr<ExtensionIndexedRulesetMatcher> ruleset_matcher = |
+ CreateVerifiedExtensionIndexedRulesetMatcher(indexed_file_path); |
+ |
+ if (!ruleset_matcher) |
+ return; |
+ |
+ base::OnceClosure task = |
+ base::BindOnce(&LoadRulesetOnIOThread, std::move(extension_id), |
+ std::move(ruleset_matcher), info_map); |
+ |
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, |
+ std::move(task)); |
+} |
+ |
+} // namespace |
+ |
+RulesMonitor::RulesMonitor(content::BrowserContext* browser_context, |
+ base::SequencedTaskRunner* task_runner, |
+ InfoMap* info_map) |
+ : browser_context_(browser_context), |
+ registry_observer_(this), |
+ file_task_runner_(task_runner), |
+ info_map_(info_map) { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
+ DCHECK(file_task_runner_); |
+ DCHECK(info_map_); |
+ |
+ registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); |
+} |
+ |
+RulesMonitor::~RulesMonitor() = default; |
+ |
+void RulesMonitor::OnExtensionLoaded(content::BrowserContext* browser_context, |
+ const Extension* extension) { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
+ DCHECK_EQ(browser_context_, browser_context); |
+ DCHECK(file_task_runner_); |
+ DCHECK(info_map_); |
+ // TODO why aren't we getting notification for the associated incognito |
+ // browser context? |
+ |
+ if (!util::HasIndexedRuleset(extension)) |
+ return; |
+ |
+ base::OnceClosure task = |
+ base::BindOnce(&LoadRulesetOnFileThread, extension->id(), |
+ file_util::GetIndexedRulesetPath(extension->path()), |
+ make_scoped_refptr(info_map_)); |
+ file_task_runner_->PostTask(FROM_HERE, std::move(task)); |
+} |
+ |
+void RulesMonitor::OnExtensionUnloaded(content::BrowserContext* browser_context, |
+ const Extension* extension, |
+ UnloadedExtensionReason reason) { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
+ DCHECK_EQ(browser_context_, browser_context); |
+ DCHECK(file_task_runner_); |
+ DCHECK(info_map_); |
+ |
+ if (!util::HasIndexedRuleset(extension)) |
+ return; |
+ |
+ base::OnceClosure task = base::BindOnce( |
+ &UnloadRulesetOnIOThread, extension->id(), make_scoped_refptr(info_map_)); |
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, |
+ std::move(task)); |
+} |
+ |
+} // namespace declarative_net_request |
+} // namespace extensions |