OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 #ifndef CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_RULES_REGISTRY_WITH_CACHE_H__ | |
6 #define CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_RULES_REGISTRY_WITH_CACHE_H__ | |
7 | |
8 #include "chrome/browser/extensions/api/declarative/rules_registry.h" | |
9 | |
10 #include <map> | |
11 #include <set> | |
12 #include <string> | |
13 #include <vector> | |
14 | |
15 #include "base/compiler_specific.h" | |
16 #include "base/callback_forward.h" | |
17 #include "base/gtest_prod_util.h" | |
18 #include "base/memory/scoped_ptr.h" | |
19 #include "base/memory/weak_ptr.h" | |
20 #include "content/public/browser/notification_observer.h" | |
21 #include "content/public/browser/notification_registrar.h" | |
22 #include "extensions/common/one_shot_event.h" | |
23 | |
24 class Profile; | |
25 | |
26 namespace base { | |
27 class Value; | |
28 } // namespace base | |
29 | |
30 namespace extensions { | |
31 | |
32 // A base class for RulesRegistries that takes care of storing the | |
33 // RulesRegistry::Rule objects. It contains all the methods that need to run on | |
34 // the registry thread; methods that need to run on the UI thread are separated | |
35 // in the RuleStorageOnUI object. | |
36 class RulesRegistryWithCache : public RulesRegistry { | |
37 public: | |
38 // RuleStorageOnUI implements the part of the RulesRegistry which works on | |
39 // the UI thread. It should only be used on the UI thread. It gets created | |
40 // by the RulesRegistry, but right after that it changes owner to the | |
41 // RulesRegistryService, and is deleted by the service. | |
42 // If |log_storage_init_delay| is set, the delay caused by loading and | |
43 // registering rules on initialization will be logged with UMA. | |
44 class RuleStorageOnUI : public content::NotificationObserver { | |
45 public: | |
46 // |event_name| identifies the JavaScript event for which rules are | |
47 // registered. For example, for WebRequestRulesRegistry the name is | |
48 // "declarativeWebRequest.onRequest". | |
49 RuleStorageOnUI(Profile* profile, | |
50 const std::string& event_name, | |
51 content::BrowserThread::ID rules_registry_thread, | |
52 base::WeakPtr<RulesRegistryWithCache> registry, | |
53 bool log_storage_init_delay); | |
54 | |
55 virtual ~RuleStorageOnUI(); | |
56 | |
57 // Returns a key for the state store. The associated preference is a boolean | |
58 // indicating whether there are some declarative rules stored in the rule | |
59 // store. | |
60 static std::string GetRulesStoredKey(const std::string& event_name, | |
61 bool incognito); | |
62 | |
63 // Initialize the storage functionality. | |
64 void Init(); | |
65 | |
66 void WriteToStorage(const std::string& extension_id, | |
67 scoped_ptr<base::Value> value); | |
68 | |
69 base::WeakPtr<RuleStorageOnUI> GetWeakPtr() { | |
70 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
71 return weak_ptr_factory_.GetWeakPtr(); | |
72 } | |
73 | |
74 private: | |
75 FRIEND_TEST_ALL_PREFIXES(RulesRegistryWithCacheTest, | |
76 DeclarativeRulesStored); | |
77 FRIEND_TEST_ALL_PREFIXES(RulesRegistryWithCacheTest, | |
78 RulesStoredFlagMultipleRegistries); | |
79 | |
80 static const char kRulesStoredKey[]; | |
81 | |
82 // NotificationObserver | |
83 virtual void Observe(int type, | |
84 const content::NotificationSource& source, | |
85 const content::NotificationDetails& details) OVERRIDE; | |
86 | |
87 // Check if we are done reading all data from storage on startup, and notify | |
88 // the RulesRegistry on its thread if so. The notification is delivered | |
89 // exactly once. | |
90 void CheckIfReady(); | |
91 | |
92 // Schedules retrieving rules for already loaded extensions where | |
93 // appropriate. | |
94 void ReadRulesForInstalledExtensions(); | |
95 | |
96 // Read/write a list of rules serialized to Values. | |
97 void ReadFromStorage(const std::string& extension_id); | |
98 void ReadFromStorageCallback(const std::string& extension_id, | |
99 scoped_ptr<base::Value> value); | |
100 | |
101 // Check the preferences whether the extension with |extension_id| has some | |
102 // rules stored on disk. If this information is not in the preferences, true | |
103 // is returned as a safe default value. | |
104 bool GetDeclarativeRulesStored(const std::string& extension_id) const; | |
105 // Modify the preference to |rules_stored|. | |
106 void SetDeclarativeRulesStored(const std::string& extension_id, | |
107 bool rules_stored); | |
108 | |
109 content::NotificationRegistrar registrar_; | |
110 | |
111 Profile* profile_; | |
112 | |
113 // The key under which rules are stored. | |
114 const std::string storage_key_; | |
115 | |
116 // The key under which we store whether the rules have been stored. | |
117 const std::string rules_stored_key_; | |
118 | |
119 // A set of extension IDs that have rules we are reading from storage. | |
120 std::set<std::string> waiting_for_extensions_; | |
121 | |
122 // We measure the time spent on loading rules on init. The result is logged | |
123 // with UMA once per each RuleStorageOnUI instance, unless in Incognito. | |
124 base::Time storage_init_time_; | |
125 bool log_storage_init_delay_; | |
126 | |
127 // Weak pointer to post tasks to the owning rules registry. | |
128 const base::WeakPtr<RulesRegistryWithCache> registry_; | |
129 | |
130 // The thread |registry_| lives on. | |
131 const content::BrowserThread::ID rules_registry_thread_; | |
132 | |
133 // We notified the RulesRegistry that the rules are loaded. | |
134 bool notified_registry_; | |
135 | |
136 // Use this factory to generate weak pointers bound to the UI thread. | |
137 base::WeakPtrFactory<RuleStorageOnUI> weak_ptr_factory_; | |
138 }; | |
139 | |
140 // After the RuleStorageOnUI object (the part of the registry which runs on | |
141 // the UI thread) is created, a pointer to it is passed to |*ui_part|. | |
142 // If |log_storage_init_delay| is set, the delay caused by loading and | |
143 // registering rules on initialization will be logged with UMA. | |
144 // In tests, |profile| and |ui_part| can be NULL (at the same time). In that | |
145 // case the storage functionality disabled (no RuleStorageOnUI object | |
146 // created) and the |log_storage_init_delay| flag is ignored. | |
147 RulesRegistryWithCache(Profile* profile, | |
148 const std::string& event_name, | |
149 content::BrowserThread::ID owner_thread, | |
150 bool log_storage_init_delay, | |
151 scoped_ptr<RuleStorageOnUI>* ui_part); | |
152 | |
153 const OneShotEvent& ready() const { | |
154 return ready_; | |
155 } | |
156 | |
157 // RulesRegistry implementation: | |
158 virtual std::string AddRules( | |
159 const std::string& extension_id, | |
160 const std::vector<linked_ptr<RulesRegistry::Rule> >& rules) OVERRIDE; | |
161 virtual std::string RemoveRules( | |
162 const std::string& extension_id, | |
163 const std::vector<std::string>& rule_identifiers) OVERRIDE; | |
164 virtual std::string RemoveAllRules( | |
165 const std::string& extension_id) OVERRIDE; | |
166 virtual std::string GetRules( | |
167 const std::string& extension_id, | |
168 const std::vector<std::string>& rule_identifiers, | |
169 std::vector<linked_ptr<RulesRegistry::Rule> >* out) OVERRIDE; | |
170 virtual std::string GetAllRules( | |
171 const std::string& extension_id, | |
172 std::vector<linked_ptr<RulesRegistry::Rule> >* out) OVERRIDE; | |
173 virtual void OnExtensionUnloaded(const std::string& extension_id) OVERRIDE; | |
174 | |
175 protected: | |
176 virtual ~RulesRegistryWithCache(); | |
177 | |
178 // These functions need to provide the same functionality as their | |
179 // RulesRegistry counterparts. They need to be atomic. | |
180 virtual std::string AddRulesImpl( | |
181 const std::string& extension_id, | |
182 const std::vector<linked_ptr<RulesRegistry::Rule> >& rules) = 0; | |
183 virtual std::string RemoveRulesImpl( | |
184 const std::string& extension_id, | |
185 const std::vector<std::string>& rule_identifiers) = 0; | |
186 virtual std::string RemoveAllRulesImpl( | |
187 const std::string& extension_id) = 0; | |
188 | |
189 private: | |
190 typedef std::string ExtensionId; | |
191 typedef std::string RuleId; | |
192 typedef std::pair<ExtensionId, RuleId> RulesDictionaryKey; | |
193 typedef std::map<RulesDictionaryKey, linked_ptr<RulesRegistry::Rule> > | |
194 RulesDictionary; | |
195 enum ProcessChangedRulesState { | |
196 // ProcessChangedRules can never be called, |storage_on_ui_| is NULL. | |
197 NEVER_PROCESS, | |
198 // A task to call ProcessChangedRules is scheduled for future execution. | |
199 SCHEDULED_FOR_PROCESSING, | |
200 // No task to call ProcessChangedRules is scheduled yet, but it is possible | |
201 // to schedule one. | |
202 NOT_SCHEDULED_FOR_PROCESSING | |
203 }; | |
204 | |
205 // Common processing after extension's rules have changed. | |
206 void ProcessChangedRules(const std::string& extension_id); | |
207 | |
208 // Calls ProcessChangedRules if |process_changed_rules_requested_| == | |
209 // NOT_SCHEDULED_FOR_PROCESSING. | |
210 void MaybeProcessChangedRules(const std::string& extension_id); | |
211 | |
212 // Process the callbacks once the registry gets ready. | |
213 void MarkReady(base::Time storage_init_time); | |
214 | |
215 // Deserialize the rules from the given Value object and add them to the | |
216 // RulesRegistry. | |
217 void DeserializeAndAddRules(const std::string& extension_id, | |
218 scoped_ptr<base::Value> rules); | |
219 | |
220 | |
221 RulesDictionary rules_; | |
222 | |
223 // Signaled when we have finished reading from storage for all extensions that | |
224 // are loaded on startup. | |
225 OneShotEvent ready_; | |
226 | |
227 // The factory needs to be declared before |storage_on_ui_|, so that it can | |
228 // produce a pointer as a construction argument for |storage_on_ui_|. | |
229 base::WeakPtrFactory<RulesRegistryWithCache> weak_ptr_factory_; | |
230 | |
231 // |storage_on_ui_| is owned by the registry service. If |storage_on_ui_| is | |
232 // NULL, then the storage functionality is disabled (this is used in tests). | |
233 // This registry cannot own |storage_on_ui_| because during the time after | |
234 // rules registry service shuts down on UI thread, and the registry is | |
235 // destroyed on its thread, the use of the |storage_on_ui_| would not be | |
236 // safe. The registry only ever associates with one RuleStorageOnUI instance. | |
237 const base::WeakPtr<RuleStorageOnUI> storage_on_ui_; | |
238 | |
239 ProcessChangedRulesState process_changed_rules_requested_; | |
240 | |
241 DISALLOW_COPY_AND_ASSIGN(RulesRegistryWithCache); | |
242 }; | |
243 | |
244 } // namespace extensions | |
245 | |
246 #endif // CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_RULES_REGISTRY_WITH_CACHE_H
__ | |
OLD | NEW |