| 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 |