OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/api/declarative/rules_registry_storage_deleg
ate.h" | 5 #include "chrome/browser/extensions/api/declarative/rules_registry_storage_deleg
ate.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "chrome/browser/extensions/extension_system.h" | 8 #include "chrome/browser/extensions/extension_system.h" |
9 #include "chrome/browser/extensions/state_store.h" | 9 #include "chrome/browser/extensions/state_store.h" |
10 #include "chrome/common/chrome_notification_types.h" | 10 #include "chrome/common/chrome_notification_types.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 return rules; | 45 return rules; |
46 } | 46 } |
47 | 47 |
48 } // namespace | 48 } // namespace |
49 | 49 |
50 // This class coordinates information between the UI and RulesRegistry threads. | 50 // This class coordinates information between the UI and RulesRegistry threads. |
51 // It may outlive the RulesRegistry, which owns the delegate. Methods/variables | 51 // It may outlive the RulesRegistry, which owns the delegate. Methods/variables |
52 // should be used on the UI thread unless otherwise noted. | 52 // should be used on the UI thread unless otherwise noted. |
53 class RulesRegistryStorageDelegate::Inner | 53 class RulesRegistryStorageDelegate::Inner |
54 : public content::NotificationObserver, | 54 : public content::NotificationObserver, |
55 public base::RefCountedThreadSafe< | 55 public base::RefCountedThreadSafe<Inner> { |
56 Inner, content::BrowserThread::DeleteOnUIThread> { | |
57 public: | 56 public: |
58 Inner(Profile* profile, | 57 Inner(Profile* profile, |
59 RulesRegistryWithCache* rules_registry, | 58 RulesRegistryWithCache* rules_registry, |
60 const std::string& storage_key); | 59 const std::string& storage_key); |
61 | 60 |
62 private: | 61 private: |
| 62 friend class base::RefCountedThreadSafe<Inner>; |
63 friend class RulesRegistryStorageDelegate; | 63 friend class RulesRegistryStorageDelegate; |
64 friend struct content::BrowserThread::DeleteOnThread< | |
65 content::BrowserThread::UI>; | |
66 friend class base::DeleteHelper<Inner>; | |
67 | 64 |
68 ~Inner(); | 65 ~Inner(); |
69 | 66 |
70 // NotificationObserver | 67 // NotificationObserver |
71 virtual void Observe( | 68 virtual void Observe( |
72 int type, | 69 int type, |
73 const content::NotificationSource& source, | 70 const content::NotificationSource& source, |
74 const content::NotificationDetails& details) OVERRIDE; | 71 const content::NotificationDetails& details) OVERRIDE; |
75 | 72 |
76 // Read/write a list of rules serialized to Values. | 73 // Read/write a list of rules serialized to Values. |
77 void ReadFromStorage(const std::string& extension_id); | 74 void ReadFromStorage(const std::string& extension_id); |
78 void ReadFromStorageCallback(const std::string& extension_id, | 75 void ReadFromStorageCallback(const std::string& extension_id, |
79 scoped_ptr<base::Value> value); | 76 scoped_ptr<base::Value> value); |
80 void WriteToStorage(const std::string& extension_id, | 77 void WriteToStorage(const std::string& extension_id, |
81 scoped_ptr<base::Value> value); | 78 scoped_ptr<base::Value> value); |
82 | 79 |
83 // Check if we are done reading all data from storage on startup, and notify | 80 // Check if we are done reading all data from storage on startup, and notify |
84 // the RulesRegistry on its thread if so. The notification is delivered | 81 // the RulesRegistry on its thread if so. The notification is delivered |
85 // exactly once. | 82 // exactly once. |
86 void CheckIfReady(); | 83 void CheckIfReady(); |
87 | 84 |
88 // Deserialize the rules from the given Value object and add them to the | 85 // Deserialize the rules from the given Value object and add them to the |
89 // RulesRegistry. | 86 // RulesRegistry. |
90 void ReadFromStorageOnRegistryThread(const std::string& extension_id, | 87 void ReadFromStorageOnRegistryThread(const std::string& extension_id, |
91 scoped_ptr<base::Value> value); | 88 scoped_ptr<base::Value> value); |
92 | 89 |
93 // Notify the RulesRegistry that we are now ready. | 90 // Notify the RulesRegistry that we are now ready. |
94 void NotifyReadyOnRegistryThread(); | 91 void NotifyReadyOnRegistryThread(); |
95 | 92 |
96 content::NotificationRegistrar registrar_; | 93 scoped_ptr<content::NotificationRegistrar> registrar_; |
97 Profile* profile_; | 94 Profile* profile_; |
98 | 95 |
99 // The key under which rules are stored. | 96 // The key under which rules are stored. |
100 const std::string storage_key_; | 97 const std::string storage_key_; |
101 | 98 |
102 // A set of extension IDs that have rules we are reading from storage. | 99 // A set of extension IDs that have rules we are reading from storage. |
103 std::set<std::string> waiting_for_extensions_; | 100 std::set<std::string> waiting_for_extensions_; |
104 | 101 |
105 // The thread that our RulesRegistry lives on. | 102 // The thread that our RulesRegistry lives on. |
106 content::BrowserThread::ID rules_registry_thread_; | 103 content::BrowserThread::ID rules_registry_thread_; |
107 | 104 |
108 // The following are only accessible on rules_registry_thread_. | 105 // The following are only accessible on rules_registry_thread_. |
109 | 106 |
110 // The RulesRegistry whose delegate we are. | 107 // The RulesRegistry whose delegate we are. |
111 RulesRegistryWithCache* rules_registry_; | 108 RulesRegistryWithCache* rules_registry_; |
112 | 109 |
113 // True when we have finished reading from storage for all extensions that | 110 // True when we have finished reading from storage for all extensions that |
114 // are loaded on startup. | 111 // are loaded on startup. |
115 bool ready_; | 112 bool ready_; |
116 }; | 113 }; |
117 | 114 |
118 RulesRegistryStorageDelegate::RulesRegistryStorageDelegate() { | 115 RulesRegistryStorageDelegate::RulesRegistryStorageDelegate() { |
119 } | 116 } |
120 | 117 |
121 RulesRegistryStorageDelegate::~RulesRegistryStorageDelegate() { | 118 RulesRegistryStorageDelegate::~RulesRegistryStorageDelegate() { |
122 // RulesRegistry owns us, which means it has been deleted. | 119 // RulesRegistry owns us, which means it has been deleted. |
123 inner_->rules_registry_ = NULL; | 120 inner_->rules_registry_ = NULL; |
124 } | 121 } |
125 | 122 |
126 void RulesRegistryStorageDelegate::Init(Profile* profile, | 123 void RulesRegistryStorageDelegate::InitOnUIThread( |
127 RulesRegistryWithCache* rules_registry, | 124 Profile* profile, |
128 const std::string& storage_key) { | 125 RulesRegistryWithCache* rules_registry, |
| 126 const std::string& storage_key) { |
129 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 127 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
130 extensions::StateStore* store = ExtensionSystem::Get(profile)->state_store(); | 128 extensions::StateStore* store = ExtensionSystem::Get(profile)->state_store(); |
131 if (store) | 129 if (store) |
132 store->RegisterKey(storage_key); | 130 store->RegisterKey(storage_key); |
133 inner_ = new Inner(profile, rules_registry, storage_key); | 131 inner_ = new Inner(profile, rules_registry, storage_key); |
134 } | 132 } |
135 | 133 |
| 134 void RulesRegistryStorageDelegate::CleanupOnUIThread() { |
| 135 // The registrar must be deleted on the UI thread. |
| 136 inner_->registrar_.reset(); |
| 137 } |
| 138 |
136 bool RulesRegistryStorageDelegate::IsReady() { | 139 bool RulesRegistryStorageDelegate::IsReady() { |
137 DCHECK(content::BrowserThread::CurrentlyOn(inner_->rules_registry_thread_)); | 140 DCHECK(content::BrowserThread::CurrentlyOn(inner_->rules_registry_thread_)); |
138 return inner_->ready_; | 141 return inner_->ready_; |
139 } | 142 } |
140 | 143 |
141 void RulesRegistryStorageDelegate::OnRulesChanged( | 144 void RulesRegistryStorageDelegate::OnRulesChanged( |
142 RulesRegistryWithCache* rules_registry, | 145 RulesRegistryWithCache* rules_registry, |
143 const std::string& extension_id) { | 146 const std::string& extension_id) { |
144 DCHECK(content::BrowserThread::CurrentlyOn(inner_->rules_registry_thread_)); | 147 DCHECK(content::BrowserThread::CurrentlyOn(inner_->rules_registry_thread_)); |
145 std::vector<linked_ptr<RulesRegistry::Rule> > new_rules; | 148 std::vector<linked_ptr<RulesRegistry::Rule> > new_rules; |
146 std::string error = rules_registry->GetAllRules(extension_id, &new_rules); | 149 std::string error = rules_registry->GetAllRules(extension_id, &new_rules); |
147 DCHECK_EQ("", error); | 150 DCHECK_EQ("", error); |
148 content::BrowserThread::PostTask( | 151 content::BrowserThread::PostTask( |
149 content::BrowserThread::UI, FROM_HERE, | 152 content::BrowserThread::UI, FROM_HERE, |
150 base::Bind(&Inner::WriteToStorage, inner_.get(), extension_id, | 153 base::Bind(&Inner::WriteToStorage, inner_.get(), extension_id, |
151 base::Passed(RulesToValue(new_rules)))); | 154 base::Passed(RulesToValue(new_rules)))); |
152 } | 155 } |
153 | 156 |
154 RulesRegistryStorageDelegate::Inner::Inner( | 157 RulesRegistryStorageDelegate::Inner::Inner( |
155 Profile* profile, | 158 Profile* profile, |
156 RulesRegistryWithCache* rules_registry, | 159 RulesRegistryWithCache* rules_registry, |
157 const std::string& storage_key) | 160 const std::string& storage_key) |
158 : profile_(profile), | 161 : registrar_(new content::NotificationRegistrar()), |
| 162 profile_(profile), |
159 storage_key_(storage_key), | 163 storage_key_(storage_key), |
160 rules_registry_thread_(rules_registry->GetOwnerThread()), | 164 rules_registry_thread_(rules_registry->GetOwnerThread()), |
161 rules_registry_(rules_registry), | 165 rules_registry_(rules_registry), |
162 ready_(false) { | 166 ready_(false) { |
163 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, | 167 registrar_->Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, |
164 content::Source<Profile>(profile)); | 168 content::Source<Profile>(profile)); |
165 registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY, | 169 registrar_->Add(this, chrome::NOTIFICATION_EXTENSIONS_READY, |
166 content::Source<Profile>(profile)); | 170 content::Source<Profile>(profile)); |
167 } | 171 } |
168 | 172 |
169 RulesRegistryStorageDelegate::Inner::~Inner() {} | 173 RulesRegistryStorageDelegate::Inner::~Inner() { |
| 174 DCHECK(!registrar_.get()); |
| 175 } |
170 | 176 |
171 void RulesRegistryStorageDelegate::Inner::Observe( | 177 void RulesRegistryStorageDelegate::Inner::Observe( |
172 int type, | 178 int type, |
173 const content::NotificationSource& source, | 179 const content::NotificationSource& source, |
174 const content::NotificationDetails& details) { | 180 const content::NotificationDetails& details) { |
| 181 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
175 if (type == chrome::NOTIFICATION_EXTENSION_LOADED) { | 182 if (type == chrome::NOTIFICATION_EXTENSION_LOADED) { |
176 const extensions::Extension* extension = | 183 const extensions::Extension* extension = |
177 content::Details<const extensions::Extension>(details).ptr(); | 184 content::Details<const extensions::Extension>(details).ptr(); |
178 // TODO(mpcomplete): This API check should generalize to any use of | 185 // TODO(mpcomplete): This API check should generalize to any use of |
179 // declarative rules, not just webRequest. | 186 // declarative rules, not just webRequest. |
180 if (extension->HasAPIPermission( | 187 if (extension->HasAPIPermission( |
181 APIPermission::kDeclarativeWebRequest)) { | 188 APIPermission::kDeclarativeWebRequest)) { |
182 ReadFromStorage(extension->id()); | 189 ReadFromStorage(extension->id()); |
183 } | 190 } |
184 } else if (type == chrome::NOTIFICATION_EXTENSIONS_READY) { | 191 } else if (type == chrome::NOTIFICATION_EXTENSIONS_READY) { |
185 CheckIfReady(); | 192 CheckIfReady(); |
186 } | 193 } |
187 } | 194 } |
188 | 195 |
189 void RulesRegistryStorageDelegate::Inner::ReadFromStorage( | 196 void RulesRegistryStorageDelegate::Inner::ReadFromStorage( |
190 const std::string& extension_id) { | 197 const std::string& extension_id) { |
| 198 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
191 extensions::StateStore* store = ExtensionSystem::Get(profile_)->state_store(); | 199 extensions::StateStore* store = ExtensionSystem::Get(profile_)->state_store(); |
192 if (store) { | 200 if (store) { |
193 waiting_for_extensions_.insert(extension_id); | 201 waiting_for_extensions_.insert(extension_id); |
194 store->GetExtensionValue(extension_id, storage_key_, | 202 store->GetExtensionValue(extension_id, storage_key_, |
195 base::Bind(&Inner::ReadFromStorageCallback, this, extension_id)); | 203 base::Bind(&Inner::ReadFromStorageCallback, this, extension_id)); |
196 } | 204 } |
197 } | 205 } |
198 | 206 |
199 void RulesRegistryStorageDelegate::Inner::ReadFromStorageCallback( | 207 void RulesRegistryStorageDelegate::Inner::ReadFromStorageCallback( |
200 const std::string& extension_id, scoped_ptr<base::Value> value) { | 208 const std::string& extension_id, scoped_ptr<base::Value> value) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 void RulesRegistryStorageDelegate::Inner::NotifyReadyOnRegistryThread() { | 246 void RulesRegistryStorageDelegate::Inner::NotifyReadyOnRegistryThread() { |
239 DCHECK(content::BrowserThread::CurrentlyOn(rules_registry_thread_)); | 247 DCHECK(content::BrowserThread::CurrentlyOn(rules_registry_thread_)); |
240 if (ready_) | 248 if (ready_) |
241 return; // we've already notified our readiness | 249 return; // we've already notified our readiness |
242 | 250 |
243 ready_ = true; | 251 ready_ = true; |
244 rules_registry_->OnReady(); | 252 rules_registry_->OnReady(); |
245 } | 253 } |
246 | 254 |
247 } // namespace extensions | 255 } // namespace extensions |
OLD | NEW |