OLD | NEW |
| (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_service.h" | |
10 #include "chrome/browser/extensions/extension_util.h" | |
11 #include "content/public/browser/browser_context.h" | |
12 #include "content/public/browser/notification_details.h" | |
13 #include "content/public/browser/notification_source.h" | |
14 #include "extensions/browser/extension_prefs.h" | |
15 #include "extensions/browser/extension_registry.h" | |
16 #include "extensions/browser/extension_system.h" | |
17 #include "extensions/browser/info_map.h" | |
18 #include "extensions/browser/state_store.h" | |
19 #include "extensions/common/permissions/permissions_data.h" | |
20 | |
21 namespace { | |
22 | |
23 // Returns the key to use for storing declarative rules in the state store. | |
24 std::string GetDeclarativeRuleStorageKey(const std::string& event_name, | |
25 bool incognito) { | |
26 if (incognito) | |
27 return "declarative_rules.incognito." + event_name; | |
28 else | |
29 return "declarative_rules." + event_name; | |
30 } | |
31 | |
32 | |
33 } // namespace | |
34 | |
35 namespace extensions { | |
36 | |
37 // RulesCacheDelegate | |
38 | |
39 const char RulesCacheDelegate::kRulesStoredKey[] = | |
40 "has_declarative_rules"; | |
41 | |
42 RulesCacheDelegate::RulesCacheDelegate(bool log_storage_init_delay) | |
43 : browser_context_(NULL), | |
44 log_storage_init_delay_(log_storage_init_delay), | |
45 notified_registry_(false), | |
46 weak_ptr_factory_(this) { | |
47 } | |
48 | |
49 RulesCacheDelegate::~RulesCacheDelegate() {} | |
50 | |
51 // Returns the key to use for storing whether the rules have been stored. | |
52 // static | |
53 std::string RulesCacheDelegate::GetRulesStoredKey(const std::string& event_name, | |
54 bool incognito) { | |
55 std::string result(kRulesStoredKey); | |
56 result += incognito ? ".incognito." : "."; | |
57 return result + event_name; | |
58 } | |
59 | |
60 // This is called from the constructor of RulesRegistry, so it is | |
61 // important that it both | |
62 // 1. calls no (in particular virtual) methods of the rules registry, and | |
63 // 2. does not create scoped_refptr holding the registry. (A short-lived | |
64 // scoped_refptr might delete the rules registry before it is constructed.) | |
65 void RulesCacheDelegate::Init(RulesRegistry* registry) { | |
66 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
67 | |
68 // WARNING: The first use of |registry_| will bind it to the calling thread | |
69 // so don't use this here. | |
70 registry_ = registry->GetWeakPtr(); | |
71 | |
72 browser_context_ = registry->browser_context(); | |
73 storage_key_ = | |
74 GetDeclarativeRuleStorageKey(registry->event_name(), | |
75 browser_context_->IsOffTheRecord()); | |
76 rules_stored_key_ = GetRulesStoredKey(registry->event_name(), | |
77 browser_context_->IsOffTheRecord()); | |
78 rules_registry_thread_ = registry->owner_thread(); | |
79 | |
80 ExtensionSystem& system = *ExtensionSystem::Get(browser_context_); | |
81 StateStore* store = system.rules_store(); | |
82 if (store) | |
83 store->RegisterKey(storage_key_); | |
84 | |
85 if (browser_context_->IsOffTheRecord()) | |
86 log_storage_init_delay_ = false; | |
87 | |
88 system.ready().Post( | |
89 FROM_HERE, | |
90 base::Bind(&RulesCacheDelegate::ReadRulesForInstalledExtensions, | |
91 weak_ptr_factory_.GetWeakPtr())); | |
92 system.ready().Post(FROM_HERE, | |
93 base::Bind(&RulesCacheDelegate::CheckIfReady, | |
94 weak_ptr_factory_.GetWeakPtr())); | |
95 } | |
96 | |
97 void RulesCacheDelegate::WriteToStorage(const std::string& extension_id, | |
98 scoped_ptr<base::Value> value) { | |
99 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
100 if (!browser_context_) | |
101 return; | |
102 | |
103 const base::ListValue* rules = NULL; | |
104 CHECK(value->GetAsList(&rules)); | |
105 bool rules_stored_previously = GetDeclarativeRulesStored(extension_id); | |
106 bool store_rules = !rules->empty(); | |
107 SetDeclarativeRulesStored(extension_id, store_rules); | |
108 if (!rules_stored_previously && !store_rules) | |
109 return; | |
110 | |
111 StateStore* store = ExtensionSystem::Get(browser_context_)->rules_store(); | |
112 if (store) | |
113 store->SetExtensionValue(extension_id, storage_key_, value.Pass()); | |
114 } | |
115 | |
116 void RulesCacheDelegate::CheckIfReady() { | |
117 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
118 if (notified_registry_ || !waiting_for_extensions_.empty()) | |
119 return; | |
120 | |
121 content::BrowserThread::PostTask( | |
122 rules_registry_thread_, | |
123 FROM_HERE, | |
124 base::Bind( | |
125 &RulesRegistry::MarkReady, registry_, storage_init_time_)); | |
126 notified_registry_ = true; | |
127 } | |
128 | |
129 void RulesCacheDelegate::ReadRulesForInstalledExtensions() { | |
130 ExtensionSystem& system = *ExtensionSystem::Get(browser_context_); | |
131 ExtensionService* extension_service = system.extension_service(); | |
132 DCHECK(extension_service); | |
133 // In an OTR context, we start on top of a normal context already, so the | |
134 // extension service should be ready. | |
135 DCHECK(!browser_context_->IsOffTheRecord() || extension_service->is_ready()); | |
136 if (extension_service->is_ready()) { | |
137 const ExtensionSet* extensions = extension_service->extensions(); | |
138 for (ExtensionSet::const_iterator i = extensions->begin(); | |
139 i != extensions->end(); | |
140 ++i) { | |
141 bool needs_apis_storing_rules = | |
142 (*i)->permissions_data()->HasAPIPermission( | |
143 APIPermission::kDeclarativeContent) || | |
144 (*i)->permissions_data()->HasAPIPermission( | |
145 APIPermission::kDeclarativeWebRequest); | |
146 bool respects_off_the_record = | |
147 !(browser_context_->IsOffTheRecord()) || | |
148 util::IsIncognitoEnabled((*i)->id(), browser_context_); | |
149 if (needs_apis_storing_rules && respects_off_the_record) | |
150 ReadFromStorage((*i)->id()); | |
151 } | |
152 } | |
153 } | |
154 | |
155 void RulesCacheDelegate::ReadFromStorage(const std::string& extension_id) { | |
156 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
157 if (!browser_context_) | |
158 return; | |
159 | |
160 if (log_storage_init_delay_ && storage_init_time_.is_null()) | |
161 storage_init_time_ = base::Time::Now(); | |
162 | |
163 if (!GetDeclarativeRulesStored(extension_id)) { | |
164 ExtensionSystem::Get(browser_context_)->ready().Post( | |
165 FROM_HERE, base::Bind(&RulesCacheDelegate::CheckIfReady, | |
166 weak_ptr_factory_.GetWeakPtr())); | |
167 return; | |
168 } | |
169 | |
170 StateStore* store = ExtensionSystem::Get(browser_context_)->rules_store(); | |
171 if (!store) | |
172 return; | |
173 waiting_for_extensions_.insert(extension_id); | |
174 store->GetExtensionValue( | |
175 extension_id, | |
176 storage_key_, | |
177 base::Bind(&RulesCacheDelegate::ReadFromStorageCallback, | |
178 weak_ptr_factory_.GetWeakPtr(), | |
179 extension_id)); | |
180 } | |
181 | |
182 void RulesCacheDelegate::ReadFromStorageCallback( | |
183 const std::string& extension_id, | |
184 scoped_ptr<base::Value> value) { | |
185 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
186 content::BrowserThread::PostTask( | |
187 rules_registry_thread_, | |
188 FROM_HERE, | |
189 base::Bind(&RulesRegistry::DeserializeAndAddRules, | |
190 registry_, | |
191 extension_id, | |
192 base::Passed(&value))); | |
193 | |
194 waiting_for_extensions_.erase(extension_id); | |
195 | |
196 if (waiting_for_extensions_.empty()) | |
197 ExtensionSystem::Get(browser_context_)->ready().Post( | |
198 FROM_HERE, base::Bind(&RulesCacheDelegate::CheckIfReady, | |
199 weak_ptr_factory_.GetWeakPtr())); | |
200 } | |
201 | |
202 bool RulesCacheDelegate::GetDeclarativeRulesStored( | |
203 const std::string& extension_id) const { | |
204 CHECK(browser_context_); | |
205 const ExtensionScopedPrefs* extension_prefs = | |
206 ExtensionPrefs::Get(browser_context_); | |
207 | |
208 bool rules_stored = true; | |
209 if (extension_prefs->ReadPrefAsBoolean( | |
210 extension_id, rules_stored_key_, &rules_stored)) | |
211 return rules_stored; | |
212 | |
213 // Safe default -- if we don't know that the rules are not stored, we force | |
214 // a read by returning true. | |
215 return true; | |
216 } | |
217 | |
218 void RulesCacheDelegate::SetDeclarativeRulesStored( | |
219 const std::string& extension_id, | |
220 bool rules_stored) { | |
221 CHECK(browser_context_); | |
222 DCHECK(ExtensionRegistry::Get(browser_context_) | |
223 ->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING)); | |
224 | |
225 ExtensionScopedPrefs* extension_prefs = ExtensionPrefs::Get(browser_context_); | |
226 extension_prefs->UpdateExtensionPref( | |
227 extension_id, | |
228 rules_stored_key_, | |
229 new base::FundamentalValue(rules_stored)); | |
230 } | |
231 | |
232 } // namespace extensions | |
OLD | NEW |