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

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

Issue 10560013: Persist declarative rules to the extension state store. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: comments Created 8 years, 6 months 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 | Annotate | Revision Log
OLDNEW
(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 #include "chrome/browser/extensions/api/declarative/rules_registry_storage_deleg ate.h"
6
7 #include "base/bind.h"
8 #include "chrome/browser/extensions/extension_system.h"
9 #include "chrome/browser/extensions/state_store.h"
10 #include "chrome/common/chrome_notification_types.h"
11 #include "chrome/common/extensions/extension.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/notification_details.h"
14 #include "content/public/browser/notification_source.h"
15
16 namespace extensions {
17
18 namespace {
19
20 scoped_ptr<base::Value> RulesToValue(
21 const std::vector<linked_ptr<RulesRegistry::Rule> >& rules) {
22 scoped_ptr<base::ListValue> list(new base::ListValue());
23 for (size_t i = 0; i < rules.size(); ++i)
24 list->Append(rules[i]->ToValue().release());
25 return scoped_ptr<base::Value>(list.release());
battre 2012/06/15 22:56:49 nit: how about return list.PassAs<base::Value>();
Matt Perry 2012/06/18 21:01:01 Cool, thanks!
26 }
27
28 std::vector<linked_ptr<RulesRegistry::Rule> > RulesFromValue(
29 base::Value* value) {
30 std::vector<linked_ptr<RulesRegistry::Rule> > rules;
31
32 base::ListValue* list = NULL;
33 if (!value || !value->GetAsList(&list))
34 return rules;
35
36 for (size_t i = 0; i < list->GetSize(); ++i) {
37 base::DictionaryValue* dict = NULL;
38 if (!list->GetDictionary(i, &dict))
39 continue;
40 linked_ptr<RulesRegistry::Rule> rule(new RulesRegistry::Rule());
41 if (RulesRegistry::Rule::Populate(*dict, rule.get()))
42 rules.push_back(rule);
43 }
44
45 return rules;
46 }
47
48 } // namespace
49
50 // This class coordinates information between the UI and RulesRegistry threads.
51 // It may outlive the RulesRegistry, which owns the delegate. Methods/variables
52 // should be used on the UI thread unless otherwise noted.
53 class RulesRegistryStorageDelegate::Inner
54 : public content::NotificationObserver,
55 public base::RefCountedThreadSafe<
56 Inner, content::BrowserThread::DeleteOnUIThread> {
57 public:
58 Inner(Profile* profile,
59 RulesRegistryWithCache* rules_registry,
60 const std::string& storage_key);
61
62 private:
63 friend class RulesRegistryStorageDelegate;
64 friend struct content::BrowserThread::DeleteOnThread<
65 content::BrowserThread::UI>;
66 friend class base::DeleteHelper<Inner>;
67
68 ~Inner();
69
70 // NotificationObserver
71 virtual void Observe(
72 int type,
73 const content::NotificationSource& source,
74 const content::NotificationDetails& details) OVERRIDE;
75
76 // Read/write a list of rules serialized to Values.
77 void ReadFromStorage(const std::string& extension_id,
78 scoped_ptr<base::Value> value);
79 void WriteToStorage(const std::string& extension_id,
80 scoped_ptr<base::Value> value);
81
82 // Check if we are done reading all data from storage, and notify the
83 // RulesRegistry if so.
battre 2012/06/15 22:56:49 add comment how this notification happens?
Matt Perry 2012/06/18 21:01:01 I'm not sure I understand what you mean. I added a
84 void CheckIfReady();
85
86 // Deserialize the rules from the given Value object and add them to the
87 // RulesRegistry.
88 void ReadFromStorageOnRegistryThread(const std::string& extension_id,
89 scoped_ptr<base::Value> value);
90
91 // Notify the RulesRegistry that we are now ready.
92 void NotifyReadyOnRegistryThread();
93
94 content::NotificationRegistrar registrar_;
95 Profile* profile_;
96
97 // The key under which rules are stored.
98 const std::string storage_key_;
99
100 // A set of extension IDs that have rules we are reading from storage.
101 std::set<std::string> waiting_for_extensions_;
102
103 // The thread that our RulesRegistry lives on.
104 content::BrowserThread::ID rules_registry_thread_;
105
106 // The following are only accessible on rules_registry_thread_.
107
108 // The RulesRegistry whose delegate we are.
109 RulesRegistryWithCache* rules_registry_;
110
111 // True when we have finished reading from storage for all extensions that
112 // are loaded on startup.
113 bool ready_;
114 };
115
116 RulesRegistryStorageDelegate::RulesRegistryStorageDelegate() {
117 }
118
119 RulesRegistryStorageDelegate::~RulesRegistryStorageDelegate() {
120 // RulesRegistry owns us, which means it has been deleted.
121 inner_->rules_registry_ = NULL;
122 }
123
124 void RulesRegistryStorageDelegate::Init(Profile* profile,
125 RulesRegistryWithCache* rules_registry,
126 const std::string& storage_key) {
battre 2012/06/15 22:56:49 nit: indent
Matt Perry 2012/06/18 21:01:01 Done.
127 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
128 inner_ = new Inner(profile, rules_registry, storage_key);
129 }
130
131 bool RulesRegistryStorageDelegate::IsReady() {
132 DCHECK(content::BrowserThread::CurrentlyOn(inner_->rules_registry_thread_));
133 return inner_->ready_;
battre 2012/06/15 22:56:49 this contradicts the comment "Methods/variables sh
Matt Perry 2012/06/18 21:01:01 Are you referring to ready_? ready_'s definition f
134 }
135
136 void RulesRegistryStorageDelegate::OnRulesChanged(
137 RulesRegistryWithCache* rules_registry,
138 const std::string& extension_id) {
139 DCHECK(content::BrowserThread::CurrentlyOn(inner_->rules_registry_thread_));
140 std::vector<linked_ptr<RulesRegistry::Rule> > new_rules;
141 std::string error = rules_registry->GetAllRules(extension_id, &new_rules);
142 DCHECK_EQ("", error);
143 content::BrowserThread::PostTask(
144 content::BrowserThread::UI, FROM_HERE,
145 base::Bind(&Inner::WriteToStorage, inner_.get(), extension_id,
146 base::Passed(RulesToValue(new_rules))));
147 }
148
149 RulesRegistryStorageDelegate::Inner::Inner(Profile* profile,
150 RulesRegistryWithCache* rules_registry,
151 const std::string& storage_key)
battre 2012/06/15 22:56:49 nit: indent
Matt Perry 2012/06/18 21:01:01 Done.
152 : profile_(profile),
153 storage_key_(storage_key),
154 rules_registry_thread_(rules_registry->GetOwnerThread()),
155 rules_registry_(rules_registry),
156 ready_(false) {
157 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
158 content::Source<Profile>(profile));
159 registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY,
160 content::Source<Profile>(profile));
161 }
162
163 RulesRegistryStorageDelegate::Inner::~Inner() {}
164
165 void RulesRegistryStorageDelegate::Inner::Observe(
166 int type,
167 const content::NotificationSource& source,
168 const content::NotificationDetails& details) {
169 if (type == chrome::NOTIFICATION_EXTENSION_LOADED) {
170 const extensions::Extension* extension =
171 content::Details<const extensions::Extension>(details).ptr();
172 extensions::StateStore* store =
173 ExtensionSystem::Get(profile_)->state_store();
174 if (store && extension->HasAPIPermission(
175 ExtensionAPIPermission::kDeclarativeWebRequest)) {
Matt Perry 2012/06/15 21:54:41 Is there a better way to check if an extension is
battre 2012/06/15 22:56:49 "declarative" (and ExtensionAPIPermission::kDeclar
Matt Perry 2012/06/18 21:01:01 I'll leave as-is for now but add a TODO.
176 waiting_for_extensions_.insert(extension->id());
177 store->GetExtensionValue(extension->id(), storage_key_,
178 base::Bind(&Inner::ReadFromStorage, this, extension->id()));
battre 2012/06/15 22:56:49 What do you think of moving 177-178 into a functio
Matt Perry 2012/06/18 21:01:01 Done.
179 }
180 } else if (type == chrome::NOTIFICATION_EXTENSIONS_READY) {
181 CheckIfReady();
182 }
183 }
184
185 void RulesRegistryStorageDelegate::Inner::ReadFromStorage(
186 const std::string& extension_id, scoped_ptr<base::Value> value) {
187 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
188 content::BrowserThread::PostTask(
189 rules_registry_thread_, FROM_HERE,
190 base::Bind(&Inner::ReadFromStorageOnRegistryThread, this,
191 extension_id, base::Passed(value.Pass())));
192
193 waiting_for_extensions_.erase(extension_id);
194 CheckIfReady();
195 }
196
197 void RulesRegistryStorageDelegate::Inner::WriteToStorage(
198 const std::string& extension_id, scoped_ptr<base::Value> value) {
199 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
200 StateStore* store = ExtensionSystem::Get(profile_)->state_store();
201 if (store)
202 store->SetExtensionValue(extension_id, storage_key_, value.Pass());
203 }
204
205 void RulesRegistryStorageDelegate::Inner::CheckIfReady() {
206 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
207 if (!waiting_for_extensions_.empty())
208 return;
209
210 if (ready_)
battre 2012/06/15 22:56:49 access to ready_ on UI thread
Matt Perry 2012/06/18 21:01:01 Doh! Good catch.
211 return; // we've already notified our readiness
battre 2012/06/15 22:56:49 This behavior (call callback only once) is not ref
Matt Perry 2012/06/18 21:01:01 Added comments to CheckIfReady and OnReady.
212
213 content::BrowserThread::PostTask(
214 rules_registry_thread_, FROM_HERE,
215 base::Bind(&Inner::NotifyReadyOnRegistryThread, this));
216 }
217
218 void RulesRegistryStorageDelegate::Inner::ReadFromStorageOnRegistryThread(
219 const std::string& extension_id, scoped_ptr<base::Value> value) {
220 DCHECK(content::BrowserThread::CurrentlyOn(rules_registry_thread_));
221 if (!rules_registry_)
222 return; // registry went away
223
224 rules_registry_->AddRules(extension_id, RulesFromValue(value.get()));
225 }
226
227 void RulesRegistryStorageDelegate::Inner::NotifyReadyOnRegistryThread() {
228 DCHECK(content::BrowserThread::CurrentlyOn(rules_registry_thread_));
229 ready_ = true;
battre 2012/06/15 22:56:49 access to ready_ on rules_registry_thread_
Matt Perry 2012/06/18 21:01:01 That is the intended thread.
230 rules_registry_->OnReady();
231 }
232
233 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698