Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: chrome/browser/extensions/api/declarative/rules_cache_delegate.cc

Issue 49693003: Refactor RulesRegistryWithCache to RulesRegistry (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Tests mostly work Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 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 "chrome/browser/extensions/api/declarative/rules_cache_delegate.h"
6
7 #include "chrome/browser/chrome_notification_types.h"
8 #include "chrome/browser/extensions/api/declarative/rules_registry.h"
9 #include "chrome/browser/extensions/extension_info_map.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/extensions/extension_system.h"
12 #include "chrome/browser/extensions/extension_util.h"
13 #include "chrome/browser/extensions/state_store.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "content/public/browser/notification_details.h"
16 #include "content/public/browser/notification_source.h"
17
18 namespace {
19
20 // Returns the key to use for storing declarative rules in the state store.
21 std::string GetDeclarativeRuleStorageKey(const std::string& event_name,
22 bool incognito) {
23 if (incognito)
24 return "declarative_rules.incognito." + event_name;
25 else
26 return "declarative_rules." + event_name;
27 }
28
29 } // namespace
30
31 namespace extensions {
32
33 // RulesCacheDelegate
34
35 const char RulesCacheDelegate::kRulesStoredKey[] =
36 "has_declarative_rules";
37
38 RulesCacheDelegate::RulesCacheDelegate(
39 Profile* profile,
40 const std::string& event_name,
41 content::BrowserThread::ID rules_registry_thread,
42 base::WeakPtr<RulesRegistry> registry,
43 bool log_storage_init_delay)
44 : profile_(profile),
45 storage_key_(GetDeclarativeRuleStorageKey(event_name,
46 profile->IsOffTheRecord())),
47 rules_stored_key_(GetRulesStoredKey(event_name,
48 profile->IsOffTheRecord())),
49 log_storage_init_delay_(log_storage_init_delay),
50 registry_(registry),
51 rules_registry_thread_(rules_registry_thread),
52 notified_registry_(false),
53 weak_ptr_factory_(this) {}
54
55 RulesCacheDelegate::~RulesCacheDelegate() {}
56
57 // Returns the key to use for storing whether the rules have been stored.
58 // static
59 std::string RulesCacheDelegate::GetRulesStoredKey(const std::string& event_name,
60 bool incognito) {
61 std::string result(kRulesStoredKey);
62 result += incognito ? ".incognito." : ".";
63 return result + event_name;
64 }
65
66 // This is called from the constructor of RulesRegistry, so it is
67 // important that it both
68 // 1. calls no (in particular virtual) methods of the rules registry, and
69 // 2. does not create scoped_refptr holding the registry. (A short-lived
70 // scoped_refptr might delete the rules registry before it is constructed.)
71 void RulesCacheDelegate::Init() {
72 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
73
74 ExtensionSystem& system = *ExtensionSystem::Get(profile_);
75 extensions::StateStore* store = system.rules_store();
76 if (store)
77 store->RegisterKey(storage_key_);
78
79 registrar_.Add(this,
80 chrome::NOTIFICATION_EXTENSION_LOADED,
81 content::Source<Profile>(profile_->GetOriginalProfile()));
82
83 if (profile_->IsOffTheRecord())
84 log_storage_init_delay_ = false;
85
86 system.ready().Post(
87 FROM_HERE,
88 base::Bind(&RulesCacheDelegate::ReadRulesForInstalledExtensions,
89 GetWeakPtr()));
90 system.ready().Post(FROM_HERE,
91 base::Bind(&RulesCacheDelegate::CheckIfReady,
92 GetWeakPtr()));
93 }
94
95 void RulesCacheDelegate::WriteToStorage(const std::string& extension_id,
96 scoped_ptr<base::Value> value) {
97 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
98 if (!profile_)
99 return;
100
101 const base::ListValue* rules = NULL;
102 CHECK(value->GetAsList(&rules));
103 bool rules_stored_previously = GetDeclarativeRulesStored(extension_id);
104 bool store_rules = !rules->empty();
105 SetDeclarativeRulesStored(extension_id, store_rules);
106 if (!rules_stored_previously && !store_rules)
107 return;
108
109 StateStore* store = ExtensionSystem::Get(profile_)->rules_store();
110 if (store)
111 store->SetExtensionValue(extension_id, storage_key_, value.Pass());
112 }
113
114 void RulesCacheDelegate::Observe(
115 int type,
116 const content::NotificationSource& source,
117 const content::NotificationDetails& details) {
118 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
119 DCHECK(type == chrome::NOTIFICATION_EXTENSION_LOADED);
120
121 const extensions::Extension* extension =
122 content::Details<const extensions::Extension>(details).ptr();
123 // TODO(mpcomplete): This API check should generalize to any use of
124 // declarative rules, not just webRequest.
125 if (extension->HasAPIPermission(APIPermission::kDeclarativeContent) ||
126 extension->HasAPIPermission(APIPermission::kDeclarativeWebRequest)) {
127 ExtensionInfoMap* extension_info_map =
128 ExtensionSystem::Get(profile_)->info_map();
129 if (profile_->IsOffTheRecord() &&
130 !extension_info_map->IsIncognitoEnabled(extension->id())) {
131 // Ignore this extension.
132 } else {
133 ReadFromStorage(extension->id());
134 }
135 }
136 }
137
138 void RulesCacheDelegate::CheckIfReady() {
139 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
140 if (notified_registry_ || !waiting_for_extensions_.empty())
141 return;
142
143 content::BrowserThread::PostTask(
144 rules_registry_thread_,
145 FROM_HERE,
146 base::Bind(
147 &RulesRegistry::MarkReady, registry_, storage_init_time_));
148 notified_registry_ = true;
149 }
150
151 void RulesCacheDelegate::ReadRulesForInstalledExtensions() {
152 ExtensionSystem& system = *ExtensionSystem::Get(profile_);
153 ExtensionService* extension_service = system.extension_service();
154 DCHECK(extension_service);
155 // In an OTR profile, we start on top of a normal profile already, so the
156 // extension service should be ready.
157 DCHECK(!profile_->IsOffTheRecord() || extension_service->is_ready());
158 if (extension_service->is_ready()) {
159 const ExtensionSet* extensions = extension_service->extensions();
160 for (ExtensionSet::const_iterator i = extensions->begin();
161 i != extensions->end();
162 ++i) {
163 bool needs_apis_storing_rules =
164 (*i)->HasAPIPermission(APIPermission::kDeclarativeContent) ||
165 (*i)->HasAPIPermission(APIPermission::kDeclarativeWebRequest);
166 bool respects_off_the_record =
167 !(profile_->IsOffTheRecord()) ||
168 extension_util::IsIncognitoEnabled((*i)->id(), extension_service);
169 if (needs_apis_storing_rules && respects_off_the_record)
170 ReadFromStorage((*i)->id());
171 }
172 }
173 }
174
175 void RulesCacheDelegate::ReadFromStorage(const std::string& extension_id) {
176 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
177 if (!profile_)
178 return;
179
180 if (log_storage_init_delay_ && storage_init_time_.is_null())
181 storage_init_time_ = base::Time::Now();
182
183 if (!GetDeclarativeRulesStored(extension_id)) {
184 ExtensionSystem::Get(profile_)->ready().Post(
185 FROM_HERE, base::Bind(&RulesCacheDelegate::CheckIfReady, GetWeakPtr()));
186 return;
187 }
188
189 extensions::StateStore* store = ExtensionSystem::Get(profile_)->rules_store();
190 if (!store)
191 return;
192 waiting_for_extensions_.insert(extension_id);
193 store->GetExtensionValue(
194 extension_id,
195 storage_key_,
196 base::Bind(&RulesCacheDelegate::ReadFromStorageCallback,
197 weak_ptr_factory_.GetWeakPtr(),
198 extension_id));
199 }
200
201 void RulesCacheDelegate::ReadFromStorageCallback(
202 const std::string& extension_id,
203 scoped_ptr<base::Value> value) {
204 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
205 content::BrowserThread::PostTask(
206 rules_registry_thread_,
207 FROM_HERE,
208 base::Bind(&RulesRegistry::DeserializeAndAddRules,
209 registry_,
210 extension_id,
211 base::Passed(&value)));
212
213 waiting_for_extensions_.erase(extension_id);
214
215 if (waiting_for_extensions_.empty())
216 ExtensionSystem::Get(profile_)->ready().Post(
217 FROM_HERE, base::Bind(&RulesCacheDelegate::CheckIfReady, GetWeakPtr()));
218 }
219
220 bool RulesCacheDelegate::GetDeclarativeRulesStored(
221 const std::string& extension_id) const {
222 CHECK(profile_);
223 const ExtensionScopedPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
224
225 bool rules_stored = true;
226 if (extension_prefs->ReadPrefAsBoolean(
227 extension_id, rules_stored_key_, &rules_stored))
228 return rules_stored;
229
230 // Safe default -- if we don't know that the rules are not stored, we force
231 // a read by returning true.
232 return true;
233 }
234
235 void RulesCacheDelegate::SetDeclarativeRulesStored(
236 const std::string& extension_id,
237 bool rules_stored) {
238 CHECK(profile_);
239 ExtensionScopedPrefs* extension_prefs = ExtensionPrefs::Get(profile_);
240 extension_prefs->UpdateExtensionPref(
241 extension_id,
242 rules_stored_key_,
243 new base::FundamentalValue(rules_stored));
244 }
245
246 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698