Chromium Code Reviews| 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_service.h" | 5 #include "chrome/browser/extensions/api/declarative/rules_registry_service.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/lazy_instance.h" | 8 #include "base/lazy_instance.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 11 #include "chrome/browser/chrome_notification_types.h" | 11 #include "chrome/browser/chrome_notification_types.h" |
| 12 #include "chrome/browser/extensions/api/declarative/rules_cache_delegate.h" | 12 #include "chrome/browser/extensions/api/declarative/rules_cache_delegate.h" |
| 13 #include "chrome/browser/extensions/api/declarative_content/content_rules_regist ry.h" | 13 #include "chrome/browser/extensions/api/declarative_content/content_rules_regist ry.h" |
| 14 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_consta nts.h" | |
| 14 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_ registry.h" | 15 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_ registry.h" |
| 15 #include "chrome/browser/extensions/api/web_request/web_request_api.h" | 16 #include "chrome/browser/extensions/api/web_request/web_request_api.h" |
| 16 #include "chrome/common/extensions/extension.h" | 17 #include "chrome/common/extensions/extension.h" |
| 17 #include "content/public/browser/browser_thread.h" | 18 #include "content/public/browser/browser_thread.h" |
| 18 #include "content/public/browser/notification_details.h" | 19 #include "content/public/browser/notification_details.h" |
| 20 #include "content/public/browser/notification_service.h" | |
| 19 #include "content/public/browser/notification_source.h" | 21 #include "content/public/browser/notification_source.h" |
| 22 #include "content/public/browser/render_process_host.h" | |
| 20 | 23 |
| 21 namespace extensions { | 24 namespace extensions { |
| 22 | 25 |
| 23 namespace { | 26 namespace { |
| 24 | 27 |
| 25 // Registers |web_request_rules_registry| on the IO thread. | 28 // Registers |web_request_rules_registry| on the IO thread. |
| 26 void RegisterToExtensionWebRequestEventRouterOnIO( | 29 void RegisterToExtensionWebRequestEventRouterOnIO( |
| 27 void* profile, | 30 void* profile, |
| 31 const RulesRegistryService::WebViewKey& webview_key, | |
| 28 scoped_refptr<WebRequestRulesRegistry> web_request_rules_registry) { | 32 scoped_refptr<WebRequestRulesRegistry> web_request_rules_registry) { |
| 29 ExtensionWebRequestEventRouter::GetInstance()->RegisterRulesRegistry( | 33 ExtensionWebRequestEventRouter::GetInstance()->RegisterRulesRegistry( |
| 30 profile, web_request_rules_registry); | 34 profile, webview_key, web_request_rules_registry); |
| 35 } | |
| 36 | |
| 37 bool IsWebView(const RulesRegistryService::WebViewKey& webview_key) { | |
| 38 return webview_key.first && webview_key.second; | |
| 31 } | 39 } |
| 32 | 40 |
| 33 } // namespace | 41 } // namespace |
| 34 | 42 |
| 35 RulesRegistryService::RulesRegistryService(Profile* profile) | 43 RulesRegistryService::RulesRegistryService(Profile* profile) |
| 36 : content_rules_registry_(NULL), | 44 : content_rules_registry_(NULL), |
| 37 profile_(profile) { | 45 profile_(profile) { |
| 38 if (profile) { | 46 if (profile) { |
| 39 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | 47 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| 40 content::Source<Profile>(profile->GetOriginalProfile())); | 48 content::Source<Profile>(profile->GetOriginalProfile())); |
| 41 RegisterDefaultRulesRegistries(); | 49 registrar_.Add( |
| 50 this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | |
| 51 content::NotificationService::AllBrowserContextsAndSources()); | |
| 52 RegisterDefaultRulesRegistriesIfNotAvailable(WebViewKey(0, 0)); | |
| 42 } | 53 } |
| 43 } | 54 } |
| 44 | 55 |
| 45 RulesRegistryService::~RulesRegistryService() {} | 56 RulesRegistryService::~RulesRegistryService() {} |
| 46 | 57 |
| 47 void RulesRegistryService::RegisterDefaultRulesRegistries() { | 58 void RulesRegistryService::RegisterDefaultRulesRegistriesIfNotAvailable( |
| 48 scoped_ptr<RulesCacheDelegate> web_request_cache_delegate( | 59 const WebViewKey& webview_key) { |
| 49 new RulesCacheDelegate(true /*log_storage_init_delay*/)); | 60 if (!profile_) |
| 61 return; | |
| 62 | |
| 63 RulesRegistryKey key(declarative_webrequest_constants::kOnRequest, | |
| 64 webview_key); | |
| 65 RulesRegistryMap::const_iterator i = rule_registries_.find(key); | |
|
Jeffrey Yasskin
2013/11/09 02:47:22
If you don't use this iterator again, use Contains
Fady Samuel
2013/11/10 03:39:56
Done.
| |
| 66 // If we can find the key in the |rule_registries_| then we have already | |
| 67 // installed the default registries. | |
| 68 if (i != rule_registries_.end()) | |
| 69 return; | |
| 70 | |
| 71 | |
| 72 RulesCacheDelegate* web_request_cache_delegate = NULL; | |
| 73 if (!IsWebView(webview_key)) { | |
| 74 web_request_cache_delegate = | |
| 75 new RulesCacheDelegate(true /*log_storage_init_delay*/); | |
| 76 cache_delegates_.push_back(web_request_cache_delegate); | |
| 77 } | |
| 50 scoped_refptr<WebRequestRulesRegistry> web_request_rules_registry( | 78 scoped_refptr<WebRequestRulesRegistry> web_request_rules_registry( |
| 51 new WebRequestRulesRegistry(profile_, web_request_cache_delegate.get())); | 79 new WebRequestRulesRegistry(profile_, |
| 52 cache_delegates_.push_back(web_request_cache_delegate.release()); | 80 web_request_cache_delegate, |
| 81 webview_key)); | |
| 53 | 82 |
| 54 RegisterRulesRegistry(web_request_rules_registry); | 83 RegisterRulesRegistry(web_request_rules_registry); |
| 55 content::BrowserThread::PostTask( | 84 content::BrowserThread::PostTask( |
| 56 content::BrowserThread::IO, FROM_HERE, | 85 content::BrowserThread::IO, FROM_HERE, |
| 57 base::Bind(&RegisterToExtensionWebRequestEventRouterOnIO, | 86 base::Bind(&RegisterToExtensionWebRequestEventRouterOnIO, |
| 58 profile_, web_request_rules_registry)); | 87 profile_, webview_key, web_request_rules_registry)); |
| 59 | 88 |
| 60 #if defined(ENABLE_EXTENSIONS) | 89 #if defined(ENABLE_EXTENSIONS) |
| 61 scoped_ptr<RulesCacheDelegate> content_rules_cache_delegate( | 90 // Only create a ContentRulesRegistry for regular pages and not webviews. |
| 62 new RulesCacheDelegate(false /*log_storage_init_delay*/)); | 91 if (!IsWebView(webview_key)) { |
| 63 scoped_refptr<ContentRulesRegistry> content_rules_registry( | 92 RulesCacheDelegate* content_rules_cache_delegate = |
| 64 new ContentRulesRegistry(profile_, content_rules_cache_delegate.get())); | 93 new RulesCacheDelegate(false /*log_storage_init_delay*/); |
| 65 cache_delegates_.push_back(content_rules_cache_delegate.release()); | 94 cache_delegates_.push_back(content_rules_cache_delegate); |
| 66 | 95 scoped_refptr<ContentRulesRegistry> content_rules_registry( |
| 67 RegisterRulesRegistry(content_rules_registry); | 96 new ContentRulesRegistry(profile_, content_rules_cache_delegate)); |
| 68 content_rules_registry_ = content_rules_registry.get(); | 97 RegisterRulesRegistry(content_rules_registry); |
| 98 content_rules_registry_ = content_rules_registry.get(); | |
| 99 } | |
| 69 #endif // defined(ENABLE_EXTENSIONS) | 100 #endif // defined(ENABLE_EXTENSIONS) |
| 70 } | 101 } |
| 71 | 102 |
| 72 void RulesRegistryService::Shutdown() { | 103 void RulesRegistryService::Shutdown() { |
| 73 // Release the references to all registries. This would happen soon during | 104 // Release the references to all registries. This would happen soon during |
| 74 // destruction of |*this|, but we need the ExtensionWebRequestEventRouter to | 105 // destruction of |*this|, but we need the ExtensionWebRequestEventRouter to |
| 75 // be the last to reference the WebRequestRulesRegistry objects, so that | 106 // be the last to reference the WebRequestRulesRegistry objects, so that |
| 76 // the posted task below causes their destruction on the IO thread, not on UI | 107 // the posted task below causes their destruction on the IO thread, not on UI |
| 77 // where the destruction of |*this| takes place. | 108 // where the destruction of |*this| takes place. |
| 78 // TODO(vabr): Remove once http://crbug.com/218451#c6 gets addressed. | 109 // TODO(vabr): Remove once http://crbug.com/218451#c6 gets addressed. |
| 79 rule_registries_.clear(); | 110 rule_registries_.clear(); |
| 80 content::BrowserThread::PostTask( | 111 content::BrowserThread::PostTask( |
| 81 content::BrowserThread::IO, FROM_HERE, | 112 content::BrowserThread::IO, FROM_HERE, |
| 82 base::Bind(&RegisterToExtensionWebRequestEventRouterOnIO, | 113 base::Bind(&RegisterToExtensionWebRequestEventRouterOnIO, |
| 83 profile_, scoped_refptr<WebRequestRulesRegistry>(NULL))); | 114 profile_, WebViewKey(0, 0), |
| 115 scoped_refptr<WebRequestRulesRegistry>(NULL))); | |
| 84 } | 116 } |
| 85 | 117 |
| 86 static base::LazyInstance<ProfileKeyedAPIFactory<RulesRegistryService> > | 118 static base::LazyInstance<ProfileKeyedAPIFactory<RulesRegistryService> > |
| 87 g_factory = LAZY_INSTANCE_INITIALIZER; | 119 g_factory = LAZY_INSTANCE_INITIALIZER; |
| 88 | 120 |
| 89 // static | 121 // static |
| 90 ProfileKeyedAPIFactory<RulesRegistryService>* | 122 ProfileKeyedAPIFactory<RulesRegistryService>* |
| 91 RulesRegistryService::GetFactoryInstance() { | 123 RulesRegistryService::GetFactoryInstance() { |
| 92 return &g_factory.Get(); | 124 return &g_factory.Get(); |
| 93 } | 125 } |
| 94 | 126 |
| 95 // static | 127 // static |
| 96 RulesRegistryService* RulesRegistryService::Get(Profile* profile) { | 128 RulesRegistryService* RulesRegistryService::Get(Profile* profile) { |
| 97 return ProfileKeyedAPIFactory<RulesRegistryService>::GetForProfile(profile); | 129 return ProfileKeyedAPIFactory<RulesRegistryService>::GetForProfile(profile); |
| 98 } | 130 } |
| 99 | 131 |
| 100 void RulesRegistryService::RegisterRulesRegistry( | 132 void RulesRegistryService::RegisterRulesRegistry( |
| 101 scoped_refptr<RulesRegistry> rule_registry) { | 133 scoped_refptr<RulesRegistry> rule_registry) { |
| 102 const std::string event_name(rule_registry->event_name()); | 134 const std::string event_name(rule_registry->event_name()); |
| 103 DCHECK(rule_registries_.find(event_name) == rule_registries_.end()); | 135 RulesRegistryKey key(event_name, rule_registry->webview_key()); |
| 104 rule_registries_[event_name] = rule_registry; | 136 DCHECK(rule_registries_.find(key) == rule_registries_.end()); |
| 137 rule_registries_[key] = rule_registry; | |
| 105 } | 138 } |
| 106 | 139 |
| 107 scoped_refptr<RulesRegistry> RulesRegistryService::GetRulesRegistry( | 140 scoped_refptr<RulesRegistry> RulesRegistryService::GetRulesRegistry( |
| 108 const std::string& event_name) const { | 141 const WebViewKey& webview_key, |
| 109 RulesRegistryMap::const_iterator i = rule_registries_.find(event_name); | 142 const std::string& event_name) { |
| 143 RegisterDefaultRulesRegistriesIfNotAvailable(webview_key); | |
| 144 | |
| 145 RulesRegistryKey key(event_name, webview_key); | |
| 146 RulesRegistryMap::const_iterator i = rule_registries_.find(key); | |
| 110 if (i == rule_registries_.end()) | 147 if (i == rule_registries_.end()) |
| 111 return scoped_refptr<RulesRegistry>(); | 148 return scoped_refptr<RulesRegistry>(); |
| 112 return i->second; | 149 return i->second; |
| 113 } | 150 } |
| 114 | 151 |
| 152 void RulesRegistryService::RemoveWebViewRulesRegistries(int process_id) { | |
| 153 DCHECK_NE(0, process_id); | |
| 154 | |
| 155 RulesRegistryKeySet registries_to_delete; | |
| 156 for (RulesRegistryMap::iterator it = rule_registries_.begin(); | |
| 157 it != rule_registries_.end(); ++it) { | |
| 158 const RulesRegistryKey& key = it->first; | |
| 159 const WebViewKey& webview_key = key.second; | |
| 160 int embedder_process_id = webview_key.first; | |
| 161 // |process_id| will always be non-zero. | |
| 162 // |embedder_process_id| will only be non-zero if the key corresponds to a | |
| 163 // webview registry. | |
| 164 // Thus, |embedder_process_id| == |process_id| ==> the process ID is a | |
| 165 // webview embedder. | |
| 166 if (embedder_process_id != process_id) | |
| 167 continue; | |
| 168 | |
| 169 // Modifying the container while iterating is bad so we'll save the keys we | |
| 170 // wish to delete in another container, and delete them in another loop. | |
| 171 registries_to_delete.insert(key); | |
| 172 } | |
| 173 for (RulesRegistryKeySet::iterator it = registries_to_delete.begin(); | |
| 174 it != registries_to_delete.end(); ++it) { | |
| 175 RemoveRulesRegistry(*it); | |
| 176 } | |
| 177 } | |
| 178 | |
| 115 void RulesRegistryService::SimulateExtensionUnloaded( | 179 void RulesRegistryService::SimulateExtensionUnloaded( |
| 116 const std::string& extension_id) { | 180 const std::string& extension_id) { |
| 117 OnExtensionUnloaded(extension_id); | 181 OnExtensionUnloaded(extension_id); |
| 118 } | 182 } |
| 119 | 183 |
| 120 void RulesRegistryService::OnExtensionUnloaded( | 184 void RulesRegistryService::OnExtensionUnloaded( |
| 121 const std::string& extension_id) { | 185 const std::string& extension_id) { |
| 122 RulesRegistryMap::iterator i; | 186 RulesRegistryMap::iterator i; |
| 123 for (i = rule_registries_.begin(); i != rule_registries_.end(); ++i) { | 187 for (i = rule_registries_.begin(); i != rule_registries_.end(); ++i) { |
| 124 scoped_refptr<RulesRegistry> registry = i->second; | 188 scoped_refptr<RulesRegistry> registry = i->second; |
| 125 if (content::BrowserThread::CurrentlyOn(registry->owner_thread())) { | 189 if (content::BrowserThread::CurrentlyOn(registry->owner_thread())) { |
| 126 registry->OnExtensionUnloaded(extension_id); | 190 registry->OnExtensionUnloaded(extension_id); |
| 127 } else { | 191 } else { |
| 128 content::BrowserThread::PostTask( | 192 content::BrowserThread::PostTask( |
| 129 registry->owner_thread(), | 193 registry->owner_thread(), |
| 130 FROM_HERE, | 194 FROM_HERE, |
| 131 base::Bind( | 195 base::Bind( |
| 132 &RulesRegistry::OnExtensionUnloaded, registry, extension_id)); | 196 &RulesRegistry::OnExtensionUnloaded, registry, extension_id)); |
| 133 } | 197 } |
| 134 } | 198 } |
| 135 } | 199 } |
| 136 | 200 |
| 201 void RulesRegistryService::RemoveRulesRegistry(const RulesRegistryKey& key) { | |
|
Jeffrey Yasskin
2013/11/09 02:47:22
Unless this is called from multiple places, I'd ju
Fady Samuel
2013/11/10 03:39:56
Done.
| |
| 202 rule_registries_.erase(key); | |
| 203 } | |
| 204 | |
| 137 void RulesRegistryService::Observe( | 205 void RulesRegistryService::Observe( |
| 138 int type, | 206 int type, |
| 139 const content::NotificationSource& source, | 207 const content::NotificationSource& source, |
| 140 const content::NotificationDetails& details) { | 208 const content::NotificationDetails& details) { |
| 141 switch (type) { | 209 switch (type) { |
| 142 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { | 210 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { |
| 143 const Extension* extension = | 211 const Extension* extension = |
| 144 content::Details<UnloadedExtensionInfo>(details)->extension; | 212 content::Details<UnloadedExtensionInfo>(details)->extension; |
| 145 OnExtensionUnloaded(extension->id()); | 213 OnExtensionUnloaded(extension->id()); |
| 146 break; | 214 break; |
| 147 } | 215 } |
| 216 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { | |
| 217 content::RenderProcessHost* process = | |
| 218 content::Source<content::RenderProcessHost>(source).ptr(); | |
| 219 RemoveWebViewRulesRegistries(process->GetID()); | |
| 220 break; | |
| 221 } | |
| 148 default: | 222 default: |
| 149 NOTREACHED(); | 223 NOTREACHED(); |
| 150 break; | 224 break; |
| 151 } | 225 } |
| 152 } | 226 } |
| 153 | 227 |
| 154 } // namespace extensions | 228 } // namespace extensions |
| OLD | NEW |