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

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

Issue 10695130: Fix a memory leak in RulesRegistryStorageDelegate. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698