| 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 "extensions/browser/api/declarative/rules_registry_service.h" |    5 #include "extensions/browser/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 "content/public/browser/browser_thread.h" |   11 #include "content/public/browser/browser_thread.h" | 
|   12 #include "content/public/browser/notification_details.h" |  | 
|   13 #include "content/public/browser/notification_service.h" |  | 
|   14 #include "content/public/browser/notification_source.h" |  | 
|   15 #include "content/public/browser/notification_types.h" |  | 
|   16 #include "content/public/browser/render_process_host.h" |   12 #include "content/public/browser/render_process_host.h" | 
|   17 #include "extensions/browser/api/declarative/rules_cache_delegate.h" |   13 #include "extensions/browser/api/declarative/rules_cache_delegate.h" | 
|   18 #include "extensions/browser/api/declarative_content/content_rules_registry.h" |   14 #include "extensions/browser/api/declarative_content/content_rules_registry.h" | 
|   19 #include "extensions/browser/api/declarative_webrequest/webrequest_constants.h" |   15 #include "extensions/browser/api/declarative_webrequest/webrequest_constants.h" | 
|   20 #include "extensions/browser/api/declarative_webrequest/webrequest_rules_registr
     y.h" |   16 #include "extensions/browser/api/declarative_webrequest/webrequest_rules_registr
     y.h" | 
|   21 #include "extensions/browser/api/extensions_api_client.h" |   17 #include "extensions/browser/api/extensions_api_client.h" | 
|   22 #include "extensions/browser/api/web_request/web_request_api.h" |   18 #include "extensions/browser/api/web_request/web_request_api.h" | 
|   23 #include "extensions/browser/extension_registry.h" |   19 #include "extensions/browser/extension_registry.h" | 
|   24 #include "extensions/common/extension.h" |   20 #include "extensions/common/extension.h" | 
|   25  |   21  | 
|   26 namespace extensions { |   22 namespace extensions { | 
|   27  |   23  | 
|   28 namespace { |   24 namespace { | 
|   29  |   25  | 
|   30 // Registers |web_request_rules_registry| on the IO thread. |   26 // Registers |web_request_rules_registry| on the IO thread. | 
|   31 void RegisterToExtensionWebRequestEventRouterOnIO( |   27 void RegisterToExtensionWebRequestEventRouterOnIO( | 
|   32     content::BrowserContext* browser_context, |   28     content::BrowserContext* browser_context, | 
|   33     const RulesRegistryService::WebViewKey& webview_key, |   29     int rules_registry_id, | 
|   34     scoped_refptr<WebRequestRulesRegistry> web_request_rules_registry) { |   30     scoped_refptr<WebRequestRulesRegistry> web_request_rules_registry) { | 
|   35   ExtensionWebRequestEventRouter::GetInstance()->RegisterRulesRegistry( |   31   ExtensionWebRequestEventRouter::GetInstance()->RegisterRulesRegistry( | 
|   36       browser_context, webview_key, web_request_rules_registry); |   32       browser_context, rules_registry_id, web_request_rules_registry); | 
|   37 } |  | 
|   38  |  | 
|   39 bool IsWebView(const RulesRegistryService::WebViewKey& webview_key) { |  | 
|   40   return webview_key.embedder_process_id && webview_key.webview_instance_id; |  | 
|   41 } |   33 } | 
|   42  |   34  | 
|   43 }  // namespace |   35 }  // namespace | 
|   44  |   36  | 
 |   37 const int RulesRegistryService::kDefaultRulesRegistryID = 0; | 
 |   38 const int RulesRegistryService::kInvalidRulesRegistryID = -1; | 
 |   39  | 
|   45 RulesRegistryService::RulesRegistryService(content::BrowserContext* context) |   40 RulesRegistryService::RulesRegistryService(content::BrowserContext* context) | 
|   46     : content_rules_registry_(NULL), |   41     : current_rules_registry_id_(kDefaultRulesRegistryID), | 
 |   42       content_rules_registry_(NULL), | 
|   47       extension_registry_observer_(this), |   43       extension_registry_observer_(this), | 
|   48       browser_context_(context) { |   44       browser_context_(context) { | 
|   49   if (browser_context_) { |   45   if (browser_context_) { | 
|   50     extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); |   46     extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); | 
|   51     registrar_.Add( |   47     EnsureDefaultRulesRegistriesRegistered(kDefaultRulesRegistryID); | 
|   52         this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |  | 
|   53         content::NotificationService::AllBrowserContextsAndSources()); |  | 
|   54     EnsureDefaultRulesRegistriesRegistered(WebViewKey(0, 0)); |  | 
|   55   } |   48   } | 
|   56 } |   49 } | 
|   57  |   50  | 
|   58 RulesRegistryService::~RulesRegistryService() {} |   51 RulesRegistryService::~RulesRegistryService() {} | 
|   59  |   52  | 
 |   53 int RulesRegistryService::GetNextRulesRegistryID() { | 
 |   54   return ++current_rules_registry_id_; | 
 |   55 } | 
 |   56  | 
|   60 void RulesRegistryService::EnsureDefaultRulesRegistriesRegistered( |   57 void RulesRegistryService::EnsureDefaultRulesRegistriesRegistered( | 
|   61     const WebViewKey& webview_key) { |   58     int rules_registry_id) { | 
|   62   if (!browser_context_) |   59   if (!browser_context_) | 
|   63     return; |   60     return; | 
|   64  |  | 
|   65   RulesRegistryKey key(declarative_webrequest_constants::kOnRequest, |   61   RulesRegistryKey key(declarative_webrequest_constants::kOnRequest, | 
|   66                        webview_key); |   62                        rules_registry_id); | 
|   67   // If we can find the key in the |rule_registries_| then we have already |   63   // If we can find the key in the |rule_registries_| then we have already | 
|   68   // installed the default registries. |   64   // installed the default registries. | 
|   69   if (ContainsKey(rule_registries_, key)) |   65   if (ContainsKey(rule_registries_, key)) | 
|   70     return; |   66     return; | 
|   71  |   67  | 
|   72  |   68   // Only cache rules for regular pages. | 
|   73   RulesCacheDelegate* web_request_cache_delegate = NULL; |   69   RulesCacheDelegate* web_request_cache_delegate = NULL; | 
|   74   if (!IsWebView(webview_key)) { |   70   if (rules_registry_id == kDefaultRulesRegistryID) { | 
 |   71     // Create a RulesCacheDelegate. | 
|   75     web_request_cache_delegate = |   72     web_request_cache_delegate = | 
|   76         new RulesCacheDelegate(true /*log_storage_init_delay*/); |   73         new RulesCacheDelegate(true /*log_storage_init_delay*/); | 
|   77     cache_delegates_.push_back(web_request_cache_delegate); |   74     cache_delegates_.push_back(web_request_cache_delegate); | 
|   78   } |   75   } | 
|   79   scoped_refptr<WebRequestRulesRegistry> web_request_rules_registry( |   76   scoped_refptr<WebRequestRulesRegistry> web_request_rules_registry( | 
|   80       new WebRequestRulesRegistry(browser_context_, |   77       new WebRequestRulesRegistry(browser_context_, web_request_cache_delegate, | 
|   81                                   web_request_cache_delegate, |   78                                   rules_registry_id)); | 
|   82                                   webview_key)); |  | 
|   83  |   79  | 
|   84   RegisterRulesRegistry(web_request_rules_registry); |   80   RegisterRulesRegistry(web_request_rules_registry); | 
|   85   content::BrowserThread::PostTask( |   81   content::BrowserThread::PostTask( | 
|   86       content::BrowserThread::IO, FROM_HERE, |   82       content::BrowserThread::IO, FROM_HERE, | 
|   87       base::Bind(&RegisterToExtensionWebRequestEventRouterOnIO, |   83       base::Bind(&RegisterToExtensionWebRequestEventRouterOnIO, | 
|   88           browser_context_, webview_key, web_request_rules_registry)); |   84                  browser_context_, rules_registry_id, | 
 |   85                  web_request_rules_registry)); | 
|   89  |   86  | 
|   90   // Only create a ContentRulesRegistry for regular pages and not webviews. |   87   // Only create a ContentRulesRegistry for regular pages. | 
|   91   if (!IsWebView(webview_key)) { |   88   if (rules_registry_id == kDefaultRulesRegistryID) { | 
|   92     RulesCacheDelegate* content_rules_cache_delegate = |   89     RulesCacheDelegate* content_rules_cache_delegate = | 
|   93         new RulesCacheDelegate(false /*log_storage_init_delay*/); |   90         new RulesCacheDelegate(false /*log_storage_init_delay*/); | 
|   94     cache_delegates_.push_back(content_rules_cache_delegate); |   91     cache_delegates_.push_back(content_rules_cache_delegate); | 
|   95     scoped_refptr<ContentRulesRegistry> content_rules_registry = |   92     scoped_refptr<ContentRulesRegistry> content_rules_registry = | 
|   96         ExtensionsAPIClient::Get()->CreateContentRulesRegistry( |   93         ExtensionsAPIClient::Get()->CreateContentRulesRegistry( | 
|   97             browser_context_, content_rules_cache_delegate); |   94             browser_context_, content_rules_cache_delegate); | 
|   98     if (content_rules_registry.get() != nullptr) { |   95     if (content_rules_registry.get() != nullptr) { | 
|   99       RegisterRulesRegistry(content_rules_registry); |   96       RegisterRulesRegistry(content_rules_registry); | 
|  100       content_rules_registry_ = content_rules_registry.get(); |   97       content_rules_registry_ = content_rules_registry.get(); | 
|  101     } |   98     } | 
|  102   } |   99   } | 
|  103 } |  100 } | 
|  104  |  101  | 
|  105 void RulesRegistryService::Shutdown() { |  102 void RulesRegistryService::Shutdown() { | 
|  106   // Release the references to all registries. This would happen soon during |  103   // Release the references to all registries. This would happen soon during | 
|  107   // destruction of |*this|, but we need the ExtensionWebRequestEventRouter to |  104   // destruction of |*this|, but we need the ExtensionWebRequestEventRouter to | 
|  108   // be the last to reference the WebRequestRulesRegistry objects, so that |  105   // be the last to reference the WebRequestRulesRegistry objects, so that | 
|  109   // the posted task below causes their destruction on the IO thread, not on UI |  106   // the posted task below causes their destruction on the IO thread, not on UI | 
|  110   // where the destruction of |*this| takes place. |  107   // where the destruction of |*this| takes place. | 
|  111   // TODO(vabr): Remove once http://crbug.com/218451#c6 gets addressed. |  108   // TODO(vabr): Remove once http://crbug.com/218451#c6 gets addressed. | 
|  112   rule_registries_.clear(); |  109   rule_registries_.clear(); | 
|  113   content::BrowserThread::PostTask( |  110   content::BrowserThread::PostTask( | 
|  114       content::BrowserThread::IO, FROM_HERE, |  111       content::BrowserThread::IO, FROM_HERE, | 
|  115       base::Bind(&RegisterToExtensionWebRequestEventRouterOnIO, |  112       base::Bind(&RegisterToExtensionWebRequestEventRouterOnIO, | 
|  116           browser_context_, WebViewKey(0, 0), |  113                  browser_context_, | 
|  117           scoped_refptr<WebRequestRulesRegistry>(NULL))); |  114                  RulesRegistryService::kDefaultRulesRegistryID, | 
 |  115                  scoped_refptr<WebRequestRulesRegistry>(NULL))); | 
|  118 } |  116 } | 
|  119  |  117  | 
|  120 static base::LazyInstance<BrowserContextKeyedAPIFactory<RulesRegistryService> > |  118 static base::LazyInstance<BrowserContextKeyedAPIFactory<RulesRegistryService> > | 
|  121     g_factory = LAZY_INSTANCE_INITIALIZER; |  119     g_factory = LAZY_INSTANCE_INITIALIZER; | 
|  122  |  120  | 
|  123 // static |  121 // static | 
|  124 BrowserContextKeyedAPIFactory<RulesRegistryService>* |  122 BrowserContextKeyedAPIFactory<RulesRegistryService>* | 
|  125 RulesRegistryService::GetFactoryInstance() { |  123 RulesRegistryService::GetFactoryInstance() { | 
|  126   return g_factory.Pointer(); |  124   return g_factory.Pointer(); | 
|  127 } |  125 } | 
|  128  |  126  | 
|  129 // static |  127 // static | 
|  130 RulesRegistryService* RulesRegistryService::Get( |  128 RulesRegistryService* RulesRegistryService::Get( | 
|  131     content::BrowserContext* context) { |  129     content::BrowserContext* context) { | 
|  132   return BrowserContextKeyedAPIFactory<RulesRegistryService>::Get(context); |  130   return BrowserContextKeyedAPIFactory<RulesRegistryService>::Get(context); | 
|  133 } |  131 } | 
|  134  |  132  | 
|  135 void RulesRegistryService::RegisterRulesRegistry( |  133 void RulesRegistryService::RegisterRulesRegistry( | 
|  136     scoped_refptr<RulesRegistry> rule_registry) { |  134     scoped_refptr<RulesRegistry> rule_registry) { | 
|  137   const std::string event_name(rule_registry->event_name()); |  135   const std::string event_name(rule_registry->event_name()); | 
|  138   RulesRegistryKey key(event_name, rule_registry->webview_key()); |  136   RulesRegistryKey key(event_name, rule_registry->id()); | 
|  139   DCHECK(rule_registries_.find(key) == rule_registries_.end()); |  137   DCHECK(rule_registries_.find(key) == rule_registries_.end()); | 
|  140   rule_registries_[key] = rule_registry; |  138   rule_registries_[key] = rule_registry; | 
|  141 } |  139 } | 
|  142  |  140  | 
|  143 scoped_refptr<RulesRegistry> RulesRegistryService::GetRulesRegistry( |  141 scoped_refptr<RulesRegistry> RulesRegistryService::GetRulesRegistry( | 
|  144     const WebViewKey& webview_key, |  142     int rules_registry_id, | 
|  145     const std::string& event_name) { |  143     const std::string& event_name) { | 
|  146   EnsureDefaultRulesRegistriesRegistered(webview_key); |  144   EnsureDefaultRulesRegistriesRegistered(rules_registry_id); | 
|  147  |  145  | 
|  148   RulesRegistryKey key(event_name, webview_key); |  146   RulesRegistryKey key(event_name, rules_registry_id); | 
|  149   RulesRegistryMap::const_iterator i = rule_registries_.find(key); |  147   RulesRegistryMap::const_iterator i = rule_registries_.find(key); | 
|  150   if (i == rule_registries_.end()) |  148   if (i == rule_registries_.end()) | 
|  151     return scoped_refptr<RulesRegistry>(); |  149     return scoped_refptr<RulesRegistry>(); | 
|  152   return i->second; |  150   return i->second; | 
|  153 } |  151 } | 
|  154  |  152  | 
|  155 void RulesRegistryService::RemoveWebViewRulesRegistries(int process_id) { |  153 void RulesRegistryService::RemoveRulesRegistriesByID(int rules_registry_id) { | 
|  156   DCHECK_NE(0, process_id); |  | 
|  157  |  | 
|  158   std::set<RulesRegistryKey> registries_to_delete; |  154   std::set<RulesRegistryKey> registries_to_delete; | 
|  159   for (RulesRegistryMap::iterator it = rule_registries_.begin(); |  155   for (RulesRegistryMap::iterator it = rule_registries_.begin(); | 
|  160        it != rule_registries_.end(); ++it) { |  156        it != rule_registries_.end(); ++it) { | 
|  161     const RulesRegistryKey& key = it->first; |  157     const RulesRegistryKey& key = it->first; | 
|  162     const WebViewKey& webview_key = key.webview_key; |  158     if (key.rules_registry_id != rules_registry_id) | 
|  163     int embedder_process_id = webview_key.embedder_process_id; |  | 
|  164     // |process_id| will always be non-zero. |  | 
|  165     // |embedder_process_id| will only be non-zero if the key corresponds to a |  | 
|  166     // webview registry. |  | 
|  167     // Thus, |embedder_process_id| == |process_id| ==> the process ID is a |  | 
|  168     // webview embedder. |  | 
|  169     if (embedder_process_id != process_id) |  | 
|  170       continue; |  159       continue; | 
|  171  |  160     // Modifying a container while iterating over it can lead to badness. So we | 
|  172     // Modifying the container while iterating is bad so we'll save the keys we |  161     // save the keys in another container and delete them in another loop. | 
|  173     // wish to delete in another container, and delete them in another loop. |  | 
|  174     registries_to_delete.insert(key); |  162     registries_to_delete.insert(key); | 
|  175   } |  163   } | 
 |  164  | 
|  176   for (std::set<RulesRegistryKey>::iterator it = registries_to_delete.begin(); |  165   for (std::set<RulesRegistryKey>::iterator it = registries_to_delete.begin(); | 
|  177        it != registries_to_delete.end(); ++it) { |  166        it != registries_to_delete.end(); ++it) { | 
|  178     rule_registries_.erase(*it); |  167     rule_registries_.erase(*it); | 
|  179   } |  168   } | 
|  180 } |  169 } | 
|  181  |  170  | 
|  182 void RulesRegistryService::SimulateExtensionUninstalled( |  171 void RulesRegistryService::SimulateExtensionUninstalled( | 
|  183     const std::string& extension_id) { |  172     const std::string& extension_id) { | 
|  184   NotifyRegistriesHelper(&RulesRegistry::OnExtensionUninstalled, extension_id); |  173   NotifyRegistriesHelper(&RulesRegistry::OnExtensionUninstalled, extension_id); | 
|  185 } |  174 } | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
|  215 } |  204 } | 
|  216  |  205  | 
|  217 void RulesRegistryService::OnExtensionUninstalled( |  206 void RulesRegistryService::OnExtensionUninstalled( | 
|  218     content::BrowserContext* browser_context, |  207     content::BrowserContext* browser_context, | 
|  219     const Extension* extension, |  208     const Extension* extension, | 
|  220     extensions::UninstallReason reason) { |  209     extensions::UninstallReason reason) { | 
|  221   NotifyRegistriesHelper(&RulesRegistry::OnExtensionUninstalled, |  210   NotifyRegistriesHelper(&RulesRegistry::OnExtensionUninstalled, | 
|  222                          extension->id()); |  211                          extension->id()); | 
|  223 } |  212 } | 
|  224  |  213  | 
|  225 void RulesRegistryService::Observe( |  | 
|  226     int type, |  | 
|  227     const content::NotificationSource& source, |  | 
|  228     const content::NotificationDetails& details) { |  | 
|  229   DCHECK_EQ(content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, type); |  | 
|  230  |  | 
|  231   content::RenderProcessHost* process = |  | 
|  232       content::Source<content::RenderProcessHost>(source).ptr(); |  | 
|  233   RemoveWebViewRulesRegistries(process->GetID()); |  | 
|  234 } |  | 
|  235  |  | 
|  236 }  // namespace extensions |  214 }  // namespace extensions | 
| OLD | NEW |