diff options
author | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-23 15:54:36 +0000 |
---|---|---|
committer | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-23 15:54:36 +0000 |
commit | 2cce7ae32e5cbde8c71c2075e5ac96f35b211d38 (patch) | |
tree | d7e1073abfe8be00fa60aa7ec35cc6d084132220 | |
parent | 3b0895b2ec5eafda9d29ab9267f46767469a16fe (diff) | |
download | chromium_src-2cce7ae32e5cbde8c71c2075e5ac96f35b211d38.zip chromium_src-2cce7ae32e5cbde8c71c2075e5ac96f35b211d38.tar.gz chromium_src-2cce7ae32e5cbde8c71c2075e5ac96f35b211d38.tar.bz2 |
Track all extension processes in ExtensionInfoMap, not just
those with bindings. This also allows us to tighten down
access in ExtensionFunctionDispatcher a bit more.
This is needed to allow us to answer questions about process
capabilities on the IO thread. For example:
http://codereview.chromium.org/%20%208312005/
Review URL: http://codereview.chromium.org/8361021
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@106876 0039d316-1c4b-4281-b951-d872f2087c98
5 files changed, 84 insertions, 54 deletions
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc index bb263fb..9641187 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.cc +++ b/chrome/browser/extensions/extension_function_dispatcher.cc @@ -523,7 +523,8 @@ void ExtensionFunctionDispatcher::DispatchOnIOThread( const Extension* extension = extension_info_map->extensions().GetByURL(params.source_url); - if (!extension_info_map->AreBindingsEnabledForProcess(render_process_id)) { + if (!extension_info_map->IsExtensionInProcess(extension->id(), + render_process_id)) { // TODO(aa): Allow content scripts access to low-threat extension APIs. // See: crbug.com/80308. LOG(ERROR) << "Extension API called from non-extension process."; diff --git a/chrome/browser/extensions/extension_info_map.cc b/chrome/browser/extensions/extension_info_map.cc index 9c14448..50d75d5 100644 --- a/chrome/browser/extensions/extension_info_map.cc +++ b/chrome/browser/extensions/extension_info_map.cc @@ -9,7 +9,7 @@ namespace { -static void CheckOnValidThread() { +void CheckOnValidThread() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); } @@ -96,20 +96,29 @@ bool ExtensionInfoMap::CanCrossIncognito(const Extension* extension) { !extension->incognito_split_mode(); } -// These are duplicated from ExtensionProcessManager so that we can have the -// information on the IO thread :(. -void ExtensionInfoMap::BindingsEnabledForProcess(int render_process_id) { - extension_bindings_process_ids_.insert(render_process_id); +void ExtensionInfoMap::RegisterExtensionProcess(const std::string& extension_id, + int process_id) { + DCHECK(!IsExtensionInProcess(extension_id, process_id)); + extension_process_ids_.insert( + ExtensionProcessIDMap::value_type(extension_id, process_id)); } -void ExtensionInfoMap::BindingsDisabledForProcess(int render_process_id) { - extension_bindings_process_ids_.erase(render_process_id); +void ExtensionInfoMap::UnregisterExtensionProcess( + const std::string& extension_id, + int process_id) { + ExtensionProcessIDMap::iterator iter = + std::find(extension_process_ids_.begin(), + extension_process_ids_.end(), + ExtensionProcessIDMap::value_type(extension_id, process_id)); + if (iter != extension_process_ids_.end()) + extension_process_ids_.erase(iter); } -bool ExtensionInfoMap::AreBindingsEnabledForProcess( - int render_process_id) const { - // Must behave logically the same as AreBindingsEnabledForProcess() in - // extension_process_manager.cc. - return extension_bindings_process_ids_.find(render_process_id) != - extension_bindings_process_ids_.end(); +bool ExtensionInfoMap::IsExtensionInProcess( + const std::string& extension_id, int process_id) const { + return std::find( + extension_process_ids_.begin(), + extension_process_ids_.end(), + ExtensionProcessIDMap::value_type(extension_id, process_id)) != + extension_process_ids_.end(); } diff --git a/chrome/browser/extensions/extension_info_map.h b/chrome/browser/extensions/extension_info_map.h index abd5019..7ca8848 100644 --- a/chrome/browser/extensions/extension_info_map.h +++ b/chrome/browser/extensions/extension_info_map.h @@ -6,7 +6,7 @@ #define CHROME_BROWSER_EXTENSIONS_EXTENSION_INFO_MAP_H_ #pragma once -#include <set> +#include <map> #include <string> #include "base/basictypes.h" @@ -50,15 +50,21 @@ class ExtensionInfoMap : public base::RefCountedThreadSafe<ExtensionInfoMap> { // sub-profile (incognito to original profile, or vice versa). bool CanCrossIncognito(const Extension* extension); - // Registers a RenderProcessHost with |render_process_id| as hosting an - // extension. - void BindingsEnabledForProcess(int render_process_id); + // Record that |extension_id| is running in |process_id|. We normally have + // this information in ExtensionProcessManager on the UI thread, but we also + // sometimes need it on the IO thread. Note that this can be any of + // (extension, packaged app, hosted app). + void RegisterExtensionProcess(const std::string& extension_id, + int process_id); - // Unregisters the RenderProcessHost with |render_process_id|. - void BindingsDisabledForProcess(int render_process_id); + // Remove any record of |extension_id| created with RegisterExtensionProcess. + // If |extension_id| is unknown, we ignore it. + void UnregisterExtensionProcess(const std::string& extension_id, + int process_id); - // True if this process host is hosting an extension with extension bindings. - bool AreBindingsEnabledForProcess(int render_process_id) const; + // Returns true if |extension_id| is running in |process_id|.. + bool IsExtensionInProcess(const std::string& extension_id, + int process_id) const; private: // Extra dynamic data related to an extension. @@ -72,8 +78,8 @@ class ExtensionInfoMap : public base::RefCountedThreadSafe<ExtensionInfoMap> { // Extra data associated with enabled extensions. ExtraDataMap extra_data_; - // The set of process ids that have extension bindings enabled. - std::set<int> extension_bindings_process_ids_; + typedef std::multimap<std::string, int> ExtensionProcessIDMap; + ExtensionProcessIDMap extension_process_ids_; }; #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INFO_MAP_H_ diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc index c2a61d8..43b86aa 100644 --- a/chrome/browser/extensions/extension_process_manager.cc +++ b/chrome/browser/extensions/extension_process_manager.cc @@ -280,20 +280,16 @@ void ExtensionProcessManager::RegisterExtensionSiteInstance( int site_instance_id = site_instance->id(); int render_process_id = site_instance->GetProcess()->id(); - process_ids_[render_process_id].insert(site_instance_id); - - // Register process hosting extensions that have access to extension bindings - // with the ExtensionInfoMap on the IO thread. - Profile* profile = - Profile::FromBrowserContext(browsing_instance_->browser_context()); - ExtensionService* service = profile->GetExtensionService(); - if (service->ExtensionBindingsAllowed(extension->url())) { - Profile* profile = Profile::FromBrowserContext( - site_instance->GetProcess()->browser_context()); + if (process_ids_[render_process_id].insert(site_instance_id).second) { + // Register process hosting extensions that have access to extension + // bindings with the ExtensionInfoMap on the IO thread. + Profile* profile = + Profile::FromBrowserContext(browsing_instance_->browser_context()); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(&ExtensionInfoMap::BindingsEnabledForProcess, + base::Bind(&ExtensionInfoMap::RegisterExtensionProcess, profile->GetExtensionInfoMap(), + extension->id(), render_process_id)); } @@ -310,27 +306,40 @@ void ExtensionProcessManager::RegisterExtensionSiteInstance( void ExtensionProcessManager::UnregisterExtensionSiteInstance( SiteInstance* site_instance) { int site_instance_id = site_instance->id(); - SiteInstanceIDMap::iterator it = extension_ids_.find(site_instance_id); - if (it != extension_ids_.end()) { - extension_ids_.erase(it++); - } - if (site_instance->HasProcess()) { - int render_process_id = site_instance->GetProcess()->id(); - ProcessIDMap::iterator host = process_ids_.find(render_process_id); - if (host != process_ids_.end()) { - host->second.erase(site_instance_id); - if (host->second.empty()) { - process_ids_.erase(host); - Profile* profile = Profile::FromBrowserContext( - site_instance->GetProcess()->browser_context()); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&ExtensionInfoMap::BindingsDisabledForProcess, - profile->GetExtensionInfoMap(), - render_process_id)); + std::string extension_id = extension_ids_[site_instance_id]; + if (!extension_id.empty()) + extension_ids_.erase(site_instance_id); + + int render_process_id = ClearSiteInstanceID(site_instance_id); + if (render_process_id == -1) + return; + + Profile* profile = Profile::FromBrowserContext( + browsing_instance_->browser_context()); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&ExtensionInfoMap::UnregisterExtensionProcess, + profile->GetExtensionInfoMap(), + extension_id, + render_process_id)); +} + +int ExtensionProcessManager::ClearSiteInstanceID(int site_instance_id) { + for (ProcessIDMap::iterator i = process_ids_.begin(); + i != process_ids_.end(); ++i) { + SiteInstanceIDSet& site_instance_id_set = i->second; + for (SiteInstanceIDSet::iterator j = site_instance_id_set.begin(); + j != site_instance_id_set.end(); ++j) { + if (*j == site_instance_id) { + int render_process_id = i->first; + site_instance_id_set.erase(j); + if (site_instance_id_set.empty()) + process_ids_.erase(i); + return render_process_id; } } } + return -1; } bool ExtensionProcessManager::IsExtensionProcess(int render_process_id) { diff --git a/chrome/browser/extensions/extension_process_manager.h b/chrome/browser/extensions/extension_process_manager.h index 41d0bbb..d99ee09 100644 --- a/chrome/browser/extensions/extension_process_manager.h +++ b/chrome/browser/extensions/extension_process_manager.h @@ -147,7 +147,8 @@ class ExtensionProcessManager : public content::NotificationObserver { SiteInstanceIDMap extension_ids_; // A map of process ID to site instance ID of the site instances it hosts. - typedef std::map<int, std::set<int> > ProcessIDMap; + typedef std::set<int> SiteInstanceIDSet; + typedef std::map<int, SiteInstanceIDSet> ProcessIDMap; ProcessIDMap process_ids_; private: @@ -169,6 +170,10 @@ class ExtensionProcessManager : public content::NotificationObserver { // Excludes background page. bool HasVisibleViews(const std::string& extension_id); + // Clears the mapping for the specified site instance. Returns the process the + // site was mapped to, or -1 if it wasn't found. + int ClearSiteInstanceID(int site_instance_id); + DISALLOW_COPY_AND_ASSIGN(ExtensionProcessManager); }; |