OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "extensions/browser/api/declarative_net_request/rules_monitor.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/callback.h" |
| 9 #include "base/files/file.h" |
| 10 #include "base/files/file_util.h" |
| 11 #include "base/files/memory_mapped_file.h" |
| 12 #include "base/location.h" |
| 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/metrics/histogram_macros.h" |
| 15 #include "base/sequenced_task_runner.h" |
| 16 #include "base/strings/stringprintf.h" |
| 17 #include "base/threading/thread_restrictions.h" |
| 18 #include "content/public/browser/browser_context.h" |
| 19 #include "content/public/browser/browser_thread.h" |
| 20 #include "extensions/browser/api/declarative_net_request/matcher_util.h" |
| 21 #include "extensions/browser/extension_registry.h" |
| 22 #include "extensions/browser/extension_system.h" |
| 23 #include "extensions/browser/extension_util.h" |
| 24 #include "extensions/browser/info_map.h" |
| 25 #include "extensions/common/api/declarative_net_request/indexed_rule.h" |
| 26 #include "extensions/common/extension_id.h" |
| 27 #include "extensions/common/file_util.h" |
| 28 |
| 29 namespace extensions { |
| 30 namespace declarative_net_request { |
| 31 |
| 32 namespace { |
| 33 |
| 34 // Can't seem to use a raw pointer for InfoMap here as recommended in |
| 35 // https://chromium.googlesource.com/chromium/src/+/master/docs/design/threading
.md. |
| 36 void LoadRulesetOnIOThread( |
| 37 std::string extension_id, |
| 38 std::unique_ptr<ExtensionIndexedRulesetMatcher> ruleset_matcher, |
| 39 scoped_refptr<InfoMap> info_map) { |
| 40 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 41 info_map->ruleset_manager()->AddRuleset(std::move(extension_id), |
| 42 std::move(ruleset_matcher)); |
| 43 } |
| 44 |
| 45 void UnloadRulesetOnIOThread(std::string extension_id, |
| 46 scoped_refptr<InfoMap> info_map) { |
| 47 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 48 info_map->ruleset_manager()->RemoveRuleset(std::move(extension_id)); |
| 49 } |
| 50 |
| 51 // The |extension_id| here doesn't tell us about the associated BrowserContext. |
| 52 // But |info_map| does. |
| 53 void LoadRulesetOnFileThread(std::string extension_id, |
| 54 base::FilePath indexed_file_path, |
| 55 scoped_refptr<InfoMap> info_map) { |
| 56 // TODO not sure if this is exactly the file thread, but CrxInstaller uses the |
| 57 // same terminology. TODO is passing extension pointer safe Or would it |
| 58 // require to add ref. |
| 59 base::ThreadRestrictions::AssertIOAllowed(); |
| 60 |
| 61 // This can also me made a movable type, hence preventing dynamic allocation. |
| 62 std::unique_ptr<ExtensionIndexedRulesetMatcher> ruleset_matcher = |
| 63 CreateVerifiedExtensionIndexedRulesetMatcher(indexed_file_path); |
| 64 |
| 65 if (!ruleset_matcher) |
| 66 return; |
| 67 |
| 68 base::OnceClosure task = |
| 69 base::BindOnce(&LoadRulesetOnIOThread, std::move(extension_id), |
| 70 std::move(ruleset_matcher), info_map); |
| 71 |
| 72 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, |
| 73 std::move(task)); |
| 74 } |
| 75 |
| 76 } // namespace |
| 77 |
| 78 RulesMonitor::RulesMonitor(content::BrowserContext* browser_context, |
| 79 base::SequencedTaskRunner* task_runner, |
| 80 InfoMap* info_map) |
| 81 : browser_context_(browser_context), |
| 82 registry_observer_(this), |
| 83 file_task_runner_(task_runner), |
| 84 info_map_(info_map) { |
| 85 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 86 DCHECK(file_task_runner_); |
| 87 DCHECK(info_map_); |
| 88 |
| 89 registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); |
| 90 } |
| 91 |
| 92 RulesMonitor::~RulesMonitor() = default; |
| 93 |
| 94 void RulesMonitor::OnExtensionLoaded(content::BrowserContext* browser_context, |
| 95 const Extension* extension) { |
| 96 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 97 DCHECK_EQ(browser_context_, browser_context); |
| 98 DCHECK(file_task_runner_); |
| 99 DCHECK(info_map_); |
| 100 // TODO why aren't we getting notification for the associated incognito |
| 101 // browser context? |
| 102 |
| 103 if (!util::HasIndexedRuleset(extension)) |
| 104 return; |
| 105 |
| 106 base::OnceClosure task = |
| 107 base::BindOnce(&LoadRulesetOnFileThread, extension->id(), |
| 108 file_util::GetIndexedRulesetPath(extension->path()), |
| 109 make_scoped_refptr(info_map_)); |
| 110 file_task_runner_->PostTask(FROM_HERE, std::move(task)); |
| 111 } |
| 112 |
| 113 void RulesMonitor::OnExtensionUnloaded(content::BrowserContext* browser_context, |
| 114 const Extension* extension, |
| 115 UnloadedExtensionReason reason) { |
| 116 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 117 DCHECK_EQ(browser_context_, browser_context); |
| 118 DCHECK(file_task_runner_); |
| 119 DCHECK(info_map_); |
| 120 |
| 121 if (!util::HasIndexedRuleset(extension)) |
| 122 return; |
| 123 |
| 124 base::OnceClosure task = base::BindOnce( |
| 125 &UnloadRulesetOnIOThread, extension->id(), make_scoped_refptr(info_map_)); |
| 126 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, |
| 127 std::move(task)); |
| 128 } |
| 129 |
| 130 } // namespace declarative_net_request |
| 131 } // namespace extensions |
OLD | NEW |