diff options
author | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-12 21:27:44 +0000 |
---|---|---|
committer | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-12 21:27:44 +0000 |
commit | d7c7c98acae8978ab65c00b403e538cd7719ddb0 (patch) | |
tree | fe09c0b57954aa503154ebe71dad354e50d0abf6 /content | |
parent | fb29e6cfbf74a41c684d2196d9a8f75dd720ee6c (diff) | |
download | chromium_src-d7c7c98acae8978ab65c00b403e538cd7719ddb0.zip chromium_src-d7c7c98acae8978ab65c00b403e538cd7719ddb0.tar.gz chromium_src-d7c7c98acae8978ab65c00b403e538cd7719ddb0.tar.bz2 |
Support partitioning of storage contexts based on render_id.
This modifies BrowserContext to support having multiple storage partitions based on the child process id. The embedder is given a function that allows it to map a child process id into different storage buckets.
R=creis,nasko,jam
TBR=marja
BUG=85121
TEST=add an isolated app that covers a path like http://www.example.com/isolated/. On that page, add an entry to local storage. Access another page on www.example.com that is not isolated. Check that it cannot see the previously set entry. Repeat test in the reverse direction.
Review URL: https://chromiumcodereview.appspot.com/10600009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@146443 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/browser/browser_context.cc | 239 | ||||
-rw-r--r-- | content/browser/renderer_host/render_message_filter.cc | 3 | ||||
-rw-r--r-- | content/browser/renderer_host/render_process_host_impl.cc | 2 | ||||
-rw-r--r-- | content/browser/renderer_host/render_view_host_impl.cc | 3 | ||||
-rw-r--r-- | content/browser/storage_partition.cc | 104 | ||||
-rw-r--r-- | content/browser/storage_partition.h | 77 | ||||
-rw-r--r-- | content/browser/storage_partition_map.cc | 94 | ||||
-rw-r--r-- | content/browser/storage_partition_map.h | 49 | ||||
-rw-r--r-- | content/browser/web_contents/navigation_controller_impl.cc | 2 | ||||
-rw-r--r-- | content/browser/worker_host/worker_process_host.cc | 3 | ||||
-rw-r--r-- | content/common/child_process_host_impl.cc | 10 | ||||
-rw-r--r-- | content/common/child_process_host_impl.h | 4 | ||||
-rw-r--r-- | content/content_browser.gypi | 50 | ||||
-rw-r--r-- | content/public/browser/browser_context.h | 4 | ||||
-rw-r--r-- | content/public/browser/content_browser_client.cc | 6 | ||||
-rw-r--r-- | content/public/browser/content_browser_client.h | 15 |
16 files changed, 505 insertions, 160 deletions
diff --git a/content/browser/browser_context.cc b/content/browser/browser_context.cc index 19dcf23..fbf5a00 100644 --- a/content/browser/browser_context.cc +++ b/content/browser/browser_context.cc @@ -5,119 +5,78 @@ #include "content/public/browser/browser_context.h" #include "content/browser/appcache/chrome_appcache_service.h" +#include "webkit/database/database_tracker.h" #include "content/browser/dom_storage/dom_storage_context_impl.h" #include "content/browser/download/download_file_manager.h" #include "content/browser/download/download_manager_impl.h" -#include "content/browser/fileapi/browser_file_system_helper.h" #include "content/browser/in_process_webkit/indexed_db_context_impl.h" #include "content/browser/renderer_host/resource_dispatcher_host_impl.h" -#include "content/browser/resource_context_impl.h" +#include "content/public/browser/resource_context.h" +#include "content/browser/storage_partition.h" +#include "content/browser/storage_partition_map.h" +#include "content/common/child_process_host_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" -#include "content/public/common/content_constants.h" #include "net/base/server_bound_cert_service.h" #include "net/base/server_bound_cert_store.h" #include "net/cookies/cookie_monster.h" #include "net/cookies/cookie_store.h" #include "net/url_request/url_request_context.h" -#include "webkit/database/database_tracker.h" -#include "webkit/quota/quota_manager.h" -using appcache::AppCacheService; using base::UserDataAdapter; -using content::BrowserThread; -using fileapi::FileSystemContext; -using quota::QuotaManager; -using webkit_database::DatabaseTracker; // Key names on BrowserContext. -static const char* kAppCacheServicKeyName = "content_appcache_service_tracker"; -static const char* kDatabaseTrackerKeyName = "content_database_tracker"; -static const char* kDOMStorageContextKeyName = "content_dom_storage_context"; static const char* kDownloadManagerKeyName = "download_manager"; -static const char* kFileSystemContextKeyName = "content_file_system_context"; -static const char* kIndexedDBContextKeyName = "content_indexed_db_context"; -static const char* kQuotaManagerKeyName = "content_quota_manager"; +static const char* kStorageParitionMapKeyName = "content_storage_partition_map"; namespace content { namespace { -void CreateQuotaManagerAndClients(BrowserContext* context) { - // Ensure that these methods are called on the UI thread, except for unittests - // where a UI thread might not have been created. - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || - !BrowserThread::IsMessageLoopValid(BrowserThread::UI)); - if (context->GetUserData(kQuotaManagerKeyName)) { - DCHECK(context->GetUserData(kDatabaseTrackerKeyName)); - DCHECK(context->GetUserData(kDOMStorageContextKeyName)); - DCHECK(context->GetUserData(kFileSystemContextKeyName)); - DCHECK(context->GetUserData(kIndexedDBContextKeyName)); - return; +StoragePartition* GetStoragePartition(BrowserContext* browser_context, + int renderer_child_id) { + StoragePartitionMap* partition_map = static_cast<StoragePartitionMap*>( + browser_context->GetUserData(kStorageParitionMapKeyName)); + if (!partition_map) { + partition_map = new StoragePartitionMap(browser_context); + browser_context->SetUserData(kStorageParitionMapKeyName, partition_map); } - // All of the clients have to be created and registered with the - // QuotaManager prior to the QuotaManger being used. So we do them - // all together here prior to handing out a reference to anything - // that utlizes the QuotaManager. - scoped_refptr<QuotaManager> quota_manager = new quota::QuotaManager( - context->IsOffTheRecord(), context->GetPath(), - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB), - context->GetSpecialStoragePolicy()); - context->SetUserData(kQuotaManagerKeyName, - new UserDataAdapter<QuotaManager>(quota_manager)); - - // Each consumer is responsible for registering its QuotaClient during - // its construction. - scoped_refptr<FileSystemContext> filesystem_context = CreateFileSystemContext( - context->GetPath(), context->IsOffTheRecord(), - context->GetSpecialStoragePolicy(), quota_manager->proxy()); - context->SetUserData( - kFileSystemContextKeyName, - new UserDataAdapter<FileSystemContext>(filesystem_context)); - - scoped_refptr<DatabaseTracker> db_tracker = new DatabaseTracker( - context->GetPath(), context->IsOffTheRecord(), - context->GetSpecialStoragePolicy(), quota_manager->proxy(), - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); - context->SetUserData(kDatabaseTrackerKeyName, - new UserDataAdapter<DatabaseTracker>(db_tracker)); - - FilePath path = context->IsOffTheRecord() ? FilePath() : context->GetPath(); - scoped_refptr<DOMStorageContextImpl> dom_storage_context = - new DOMStorageContextImpl(path, context->GetSpecialStoragePolicy()); - context->SetUserData( - kDOMStorageContextKeyName, - new UserDataAdapter<DOMStorageContextImpl>(dom_storage_context)); - - scoped_refptr<IndexedDBContext> indexed_db_context = new IndexedDBContextImpl( - path, context->GetSpecialStoragePolicy(), quota_manager->proxy(), - BrowserThread::GetMessageLoopProxyForThread( - BrowserThread::WEBKIT_DEPRECATED)); - context->SetUserData( - kIndexedDBContextKeyName, - new UserDataAdapter<IndexedDBContext>(indexed_db_context)); - - scoped_refptr<ChromeAppCacheService> appcache_service = - new ChromeAppCacheService(quota_manager->proxy()); - context->SetUserData( - kAppCacheServicKeyName, - new UserDataAdapter<ChromeAppCacheService>(appcache_service)); - - InitializeResourceContext(context); - - // Check first to avoid memory leak in unittests. - if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&ChromeAppCacheService::InitializeOnIOThread, - appcache_service, - context->IsOffTheRecord() ? FilePath() : - context->GetPath().Append(content::kAppCacheDirname), - context->GetResourceContext(), - make_scoped_refptr(context->GetSpecialStoragePolicy()))); + const std::string& partition_id = + GetContentClient()->browser()->GetStoragePartitionIdForChildProcess( + browser_context, + renderer_child_id); + + return partition_map->Get(partition_id); +} + +// Run |callback| on each storage partition in |browser_context|. +void ForEachStoragePartition( + BrowserContext* browser_context, + const base::Callback<void(StoragePartition*)>& callback) { + StoragePartitionMap* partition_map = static_cast<StoragePartitionMap*>( + browser_context->GetUserData(kStorageParitionMapKeyName)); + if (!partition_map) { + return; } + + partition_map->ForEach(callback); +} + +// Used to convert a callback meant to take a DOMStorageContextImpl* into one +// that can take a StoragePartition*. +void ProcessDOMStorageContext( + const base::Callback<void(DOMStorageContextImpl*)>& callback, + StoragePartition* partition) { + callback.Run(partition->dom_storage_context()); +} + +// Run |callback| on each DOMStorageContextImpl in |browser_context|. +void ForEachDOMStorageContext( + BrowserContext* browser_context, + const base::Callback<void(DOMStorageContextImpl*)>& callback) { + ForEachStoragePartition(browser_context, + base::Bind(&ProcessDOMStorageContext, callback)); } void SaveSessionStateOnIOThread(ResourceContext* resource_context) { @@ -138,9 +97,10 @@ void PurgeMemoryOnIOThread(ResourceContext* resource_context) { ResourceContext::GetAppCacheService(resource_context)->PurgeMemory(); } -DOMStorageContextImpl* GetDOMStorageContextImpl(BrowserContext* context) { +DOMStorageContextImpl* GetDefaultDOMStorageContextImpl( + BrowserContext* context) { return static_cast<DOMStorageContextImpl*>( - BrowserContext::GetDOMStorageContext(context)); + BrowserContext::GetDefaultDOMStorageContext(context)); } } // namespace @@ -170,42 +130,71 @@ DownloadManager* BrowserContext::GetDownloadManager( context, kDownloadManagerKeyName); } -QuotaManager* BrowserContext::GetQuotaManager(BrowserContext* context) { - CreateQuotaManagerAndClients(context); - return UserDataAdapter<QuotaManager>::Get(context, kQuotaManagerKeyName); +quota::QuotaManager* BrowserContext::GetQuotaManager( + BrowserContext* browser_context) { + // TODO(ajwong): Change this API to require a process id instead of using + // kInvalidChildProcessId. + StoragePartition* partition = + GetStoragePartition(browser_context, + ChildProcessHostImpl::kInvalidChildProcessId); + return partition->quota_manager(); +} + +DOMStorageContext* BrowserContext::GetDefaultDOMStorageContext( + BrowserContext* browser_context) { + // TODO(ajwong): Force all users to know which process id they are performing + // actions on behalf of, migrate them to GetDOMStorageContext(), and then + // delete this function. + return GetDOMStorageContext(browser_context, + ChildProcessHostImpl::kInvalidChildProcessId); } DOMStorageContext* BrowserContext::GetDOMStorageContext( - BrowserContext* context) { - CreateQuotaManagerAndClients(context); - return UserDataAdapter<DOMStorageContextImpl>::Get( - context, kDOMStorageContextKeyName); + BrowserContext* browser_context, + int render_child_id) { + StoragePartition* partition = + GetStoragePartition(browser_context, render_child_id); + return partition->dom_storage_context(); } -IndexedDBContext* BrowserContext::GetIndexedDBContext(BrowserContext* context) { - CreateQuotaManagerAndClients(context); - return UserDataAdapter<IndexedDBContext>::Get( - context, kIndexedDBContextKeyName); +IndexedDBContext* BrowserContext::GetIndexedDBContext( + BrowserContext* browser_context) { + // TODO(ajwong): Change this API to require a process id instead of using + // kInvalidChildProcessId. + StoragePartition* partition = + GetStoragePartition(browser_context, + ChildProcessHostImpl::kInvalidChildProcessId); + return partition->indexed_db_context(); } -DatabaseTracker* BrowserContext::GetDatabaseTracker(BrowserContext* context) { - CreateQuotaManagerAndClients(context); - return UserDataAdapter<DatabaseTracker>::Get( - context, kDatabaseTrackerKeyName); +webkit_database::DatabaseTracker* BrowserContext::GetDatabaseTracker( + BrowserContext* browser_context) { + // TODO(ajwong): Change this API to require a process id instead of using + // kInvalidChildProcessId. + StoragePartition* partition = + GetStoragePartition(browser_context, + ChildProcessHostImpl::kInvalidChildProcessId); + return partition->database_tracker(); } -AppCacheService* BrowserContext::GetAppCacheService( +appcache::AppCacheService* BrowserContext::GetAppCacheService( BrowserContext* browser_context) { - CreateQuotaManagerAndClients(browser_context); - return UserDataAdapter<ChromeAppCacheService>::Get( - browser_context, kAppCacheServicKeyName); + // TODO(ajwong): Change this API to require a process id instead of using + // kInvalidChildProcessId. + StoragePartition* partition = + GetStoragePartition(browser_context, + ChildProcessHostImpl::kInvalidChildProcessId); + return partition->appcache_service(); } -FileSystemContext* BrowserContext::GetFileSystemContext( +fileapi::FileSystemContext* BrowserContext::GetFileSystemContext( BrowserContext* browser_context) { - CreateQuotaManagerAndClients(browser_context); - return UserDataAdapter<FileSystemContext>::Get( - browser_context, kFileSystemContextKeyName); + // TODO(ajwong): Change this API to require a process id instead of using + // kInvalidChildProcessId. + StoragePartition* partition = + GetStoragePartition(browser_context, + ChildProcessHostImpl::kInvalidChildProcessId); + return partition->filesystem_context(); } void BrowserContext::EnsureResourceContextInitialized(BrowserContext* context) { @@ -213,9 +202,9 @@ void BrowserContext::EnsureResourceContextInitialized(BrowserContext* context) { // necessary, which initializes ResourceContext. The reason we don't call // ResourceContext::InitializeResourceContext directly here is that if // ResourceContext ends up initializing it will call back into BrowserContext - // and when that call return it'll end rewriting its UserData map (with the + // and when that call returns it'll end rewriting its UserData map (with the // same value) but this causes a race condition. See http://crbug.com/115678. - CreateQuotaManagerAndClients(context); + GetStoragePartition(context, ChildProcessHostImpl::kInvalidChildProcessId); } void BrowserContext::SaveSessionState(BrowserContext* browser_context) { @@ -228,7 +217,10 @@ void BrowserContext::SaveSessionState(BrowserContext* browser_context) { browser_context->GetResourceContext())); } - GetDOMStorageContextImpl(browser_context)->SetForceKeepSessionState(); + // TODO(ajwong): This is the only usage of GetDefaultDOMStorageContextImpl(). + // After we migrate this to support multiple DOMStorageContexts, don't forget + // to remove the GetDefaultDOMStorageContextImpl() function as well. + GetDefaultDOMStorageContextImpl(browser_context)->SetForceKeepSessionState(); if (BrowserThread::IsMessageLoopValid(BrowserThread::WEBKIT_DEPRECATED)) { IndexedDBContextImpl* indexed_db = static_cast<IndexedDBContextImpl*>( @@ -248,22 +240,11 @@ void BrowserContext::PurgeMemory(BrowserContext* browser_context) { browser_context->GetResourceContext())); } - GetDOMStorageContextImpl(browser_context)->PurgeMemory(); + ForEachDOMStorageContext(browser_context, + base::Bind(&DOMStorageContextImpl::PurgeMemory)); } BrowserContext::~BrowserContext() { - // These message loop checks are just to avoid leaks in unittests. - if (GetUserData(kDatabaseTrackerKeyName) && - BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) { - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - base::Bind(&webkit_database::DatabaseTracker::Shutdown, - GetDatabaseTracker(this))); - } - - if (GetUserData(kDOMStorageContextKeyName)) - GetDOMStorageContextImpl(this)->Shutdown(); - if (GetUserData(kDownloadManagerKeyName)) GetDownloadManager(this)->Shutdown(); } diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index 3d42451..0238bd3 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc @@ -286,7 +286,8 @@ RenderMessageFilter::RenderMessageFilter( render_widget_helper_(render_widget_helper), incognito_(browser_context->IsOffTheRecord()), dom_storage_context_(static_cast<DOMStorageContextImpl*>( - BrowserContext::GetDOMStorageContext(browser_context))), + BrowserContext::GetDOMStorageContext(browser_context, + render_process_id_))), render_process_id_(render_process_id), cpu_usage_(0), media_observer_(media_observer) { diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 1531d1abb..a8d2772 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -540,7 +540,7 @@ void RenderProcessHostImpl::CreateMessageFilters() { channel_->AddFilter(new ClipboardMessageFilter()); channel_->AddFilter(new DOMStorageMessageFilter(GetID(), static_cast<DOMStorageContextImpl*>( - BrowserContext::GetDOMStorageContext(browser_context)))); + BrowserContext::GetDOMStorageContext(browser_context, GetID())))); channel_->AddFilter(new IndexedDBDispatcherHost(GetID(), static_cast<IndexedDBContextImpl*>( BrowserContext::GetIndexedDBContext(browser_context)))); diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 01f881b..19dddf8 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc @@ -174,7 +174,8 @@ RenderViewHostImpl::RenderViewHostImpl( render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING) { if (!session_storage_namespace_) { DOMStorageContext* dom_storage_context = - BrowserContext::GetDOMStorageContext(GetProcess()->GetBrowserContext()); + BrowserContext::GetDOMStorageContext(GetProcess()->GetBrowserContext(), + instance->GetProcess()->GetID()); session_storage_namespace_ = new SessionStorageNamespaceImpl( static_cast<DOMStorageContextImpl*>(dom_storage_context)); } diff --git a/content/browser/storage_partition.cc b/content/browser/storage_partition.cc new file mode 100644 index 0000000..b6ed8c2 --- /dev/null +++ b/content/browser/storage_partition.cc @@ -0,0 +1,104 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/storage_partition.h" + +#include "content/browser/appcache/chrome_appcache_service.h" +#include "content/browser/dom_storage/dom_storage_context_impl.h" +#include "content/browser/fileapi/browser_file_system_helper.h" +#include "content/browser/in_process_webkit/indexed_db_context_impl.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" +#include "webkit/database/database_tracker.h" +#include "webkit/quota/quota_manager.h" + +namespace content { + +StoragePartition::StoragePartition( + const FilePath& partition_path, + quota::QuotaManager* quota_manager, + ChromeAppCacheService* appcache_service, + fileapi::FileSystemContext* filesystem_context, + webkit_database::DatabaseTracker* database_tracker, + DOMStorageContextImpl* dom_storage_context, + IndexedDBContext* indexed_db_context) + : partition_path_(partition_path), + quota_manager_(quota_manager), + appcache_service_(appcache_service), + filesystem_context_(filesystem_context), + database_tracker_(database_tracker), + dom_storage_context_(dom_storage_context), + indexed_db_context_(indexed_db_context) { +} + +StoragePartition::~StoragePartition() { + // These message loop checks are just to avoid leaks in unittests. + if (database_tracker() && + BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) { + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + base::Bind(&webkit_database::DatabaseTracker::Shutdown, + database_tracker())); + } + + if (dom_storage_context()) + dom_storage_context()->Shutdown(); +} + +// TODO(ajwong): Break the direct dependency on |context|. We only +// need 3 pieces of info from it. +StoragePartition* StoragePartition::Create(BrowserContext* context, + const FilePath& partition_path) { + // Ensure that these methods are called on the UI thread, except for + // unittests where a UI thread might not have been created. + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || + !BrowserThread::IsMessageLoopValid(BrowserThread::UI)); + + // All of the clients have to be created and registered with the + // QuotaManager prior to the QuotaManger being used. We do them + // all together here prior to handing out a reference to anything + // that utilizes the QuotaManager. + scoped_refptr<quota::QuotaManager> quota_manager = + new quota::QuotaManager( + context->IsOffTheRecord(), partition_path, + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB), + context->GetSpecialStoragePolicy()); + + // Each consumer is responsible for registering its QuotaClient during + // its construction. + scoped_refptr<fileapi::FileSystemContext> filesystem_context = + CreateFileSystemContext(partition_path, context->IsOffTheRecord(), + context->GetSpecialStoragePolicy(), + quota_manager->proxy()); + + scoped_refptr<webkit_database::DatabaseTracker> database_tracker = + new webkit_database::DatabaseTracker( + partition_path, context->IsOffTheRecord(), + context->GetSpecialStoragePolicy(), quota_manager->proxy(), + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); + + FilePath path = context->IsOffTheRecord() ? FilePath() : partition_path; + scoped_refptr<DOMStorageContextImpl> dom_storage_context = + new DOMStorageContextImpl(path, context->GetSpecialStoragePolicy()); + + scoped_refptr<IndexedDBContextImpl> indexed_db_context = + new IndexedDBContextImpl(path, context->GetSpecialStoragePolicy(), + quota_manager->proxy(), + BrowserThread::GetMessageLoopProxyForThread( + BrowserThread::WEBKIT_DEPRECATED)); + + scoped_refptr<ChromeAppCacheService> appcache_service = + new ChromeAppCacheService(quota_manager->proxy()); + + return new StoragePartition(partition_path, + quota_manager, + appcache_service, + filesystem_context, + database_tracker, + dom_storage_context, + indexed_db_context); +} + +} // namespace content diff --git a/content/browser/storage_partition.h b/content/browser/storage_partition.h new file mode 100644 index 0000000..ee6885e --- /dev/null +++ b/content/browser/storage_partition.h @@ -0,0 +1,77 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_STORAGE_PARTITION_H_ +#define CONTENT_BROWSER_STORAGE_PARTITION_H_ + +#include "base/file_path.h" +#include "base/memory/ref_counted.h" + +namespace fileapi { +class FileSystemContext; +} + +namespace quota { +class QuotaManager; +} + +namespace webkit_database { +class DatabaseTracker; +} + +class ChromeAppCacheService; +class DOMStorageContextImpl; + +namespace content { + +class BrowserContext; +class IndexedDBContext; + +// Defines the what persistent state a child process can access. +// +// The StoragePartition defines the view each child process has of the +// persistent state inside the BrowserContext. This is used to implement +// isolated storage where a renderer with isolated storage cannot see +// the cookies, localStorage, etc., that normal web renderers have access to. +class StoragePartition { + public: + ~StoragePartition(); + + // TODO(ajwong): Break the direct dependency on |context|. We only + // need 3 pieces of info from it. + static StoragePartition* Create(BrowserContext* context, + const FilePath& partition_path); + + quota::QuotaManager* quota_manager() { return quota_manager_; } + ChromeAppCacheService* appcache_service() { return appcache_service_; } + fileapi::FileSystemContext* filesystem_context() { + return filesystem_context_; + } + webkit_database::DatabaseTracker* database_tracker() { + return database_tracker_; + } + DOMStorageContextImpl* dom_storage_context() { return dom_storage_context_; } + IndexedDBContext* indexed_db_context() { return indexed_db_context_; } + + private: + StoragePartition(const FilePath& partition_path, + quota::QuotaManager* quota_manager, + ChromeAppCacheService* appcache_service, + fileapi::FileSystemContext* filesystem_context, + webkit_database::DatabaseTracker* database_tracker, + DOMStorageContextImpl* dom_storage_context, + IndexedDBContext* indexed_db_context); + + FilePath partition_path_; + scoped_refptr<quota::QuotaManager> quota_manager_; + scoped_refptr<ChromeAppCacheService> appcache_service_; + scoped_refptr<fileapi::FileSystemContext> filesystem_context_; + scoped_refptr<webkit_database::DatabaseTracker> database_tracker_; + scoped_refptr<DOMStorageContextImpl> dom_storage_context_; + scoped_refptr<IndexedDBContext> indexed_db_context_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_STORAGE_PARTITION_H_ diff --git a/content/browser/storage_partition_map.cc b/content/browser/storage_partition_map.cc new file mode 100644 index 0000000..2611370 --- /dev/null +++ b/content/browser/storage_partition_map.cc @@ -0,0 +1,94 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/storage_partition_map.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/file_path.h" +#include "base/stl_util.h" +#include "base/string_util.h" +#include "content/browser/appcache/chrome_appcache_service.h" +#include "content/browser/resource_context_impl.h" +#include "content/browser/storage_partition.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/common/content_constants.h" + +namespace content { + +// Dirname for storing persistent data for renderers with isolated storage. +const FilePath::CharType kStoragePartitionDirName[] = + FILE_PATH_LITERAL("Storage Partitions"); + +StoragePartitionMap::StoragePartitionMap( + BrowserContext* browser_context) + : browser_context_(browser_context) { +} + +StoragePartitionMap::~StoragePartitionMap() { + STLDeleteContainerPairSecondPointers(partitions_.begin(), + partitions_.end()); +} + +StoragePartition* StoragePartitionMap::Get(const std::string& partition_id) { + // Find the previously created partition if it's available. + std::map<std::string, StoragePartition*>::const_iterator it = + partitions_.find(partition_id); + if (it != partitions_.end()) + return it->second; + + // There was no previous partition, so let's make a new one. + FilePath partition_path = browser_context_->GetPath(); + if (!partition_id.empty()) { + // TODO(ajwong): This should check the pth is valid? + CHECK(IsStringASCII(partition_id)); + partition_path = partition_path.Append(kStoragePartitionDirName) + .AppendASCII(partition_id); + } + + StoragePartition* storage_partition = + StoragePartition::Create(browser_context_, partition_path); + partitions_[partition_id] = storage_partition; + + PostCreateInitialization(storage_partition, partition_path); + + // TODO(ajwong): We need to remove this conditional by making + // InitializeResourceContext() understand having different partition data + // based on the renderer_id. + if (partition_id.empty()) { + InitializeResourceContext(browser_context_); + } + + return storage_partition; +} + +void StoragePartitionMap::ForEach( + const base::Callback<void(StoragePartition*)>& callback) { + for (std::map<std::string, StoragePartition*>::const_iterator it = + partitions_.begin(); + it != partitions_.end(); + ++it) { + callback.Run(it->second); + } +} + +void StoragePartitionMap::PostCreateInitialization( + StoragePartition* partition, + const FilePath& partition_path) { + // Check first to avoid memory leak in unittests. + if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&ChromeAppCacheService::InitializeOnIOThread, + partition->appcache_service(), + browser_context_->IsOffTheRecord() ? FilePath() : + partition_path.Append(kAppCacheDirname), + browser_context_->GetResourceContext(), + make_scoped_refptr( + browser_context_->GetSpecialStoragePolicy()))); + } +} + +} // namespace content diff --git a/content/browser/storage_partition_map.h b/content/browser/storage_partition_map.h new file mode 100644 index 0000000..bcebac1 --- /dev/null +++ b/content/browser/storage_partition_map.h @@ -0,0 +1,49 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_STORAGE_PARTITION_MAP_H_ +#define CONTENT_BROWSER_STORAGE_PARTITION_MAP_H_ + +#include <map> +#include <string> + +#include "base/callback_forward.h" +#include "base/supports_user_data.h" + +class FilePath; + +namespace content { + +class BrowserContext; +class StoragePartition; + +// A std::string to StoragePartition map for use with SupportsUserData APIs. +class StoragePartitionMap : public base::SupportsUserData::Data { + public: + explicit StoragePartitionMap(BrowserContext* browser_context); + + virtual ~StoragePartitionMap(); + + // This map retains ownership of the returned StoragePartition objects. + StoragePartition* Get(const std::string& partition_id); + + void ForEach(const base::Callback<void(StoragePartition*)>& callback); + + private: + // This must always be called *after* |partition| has been added to the + // partitions_. + // + // TODO(ajwong): Is there a way to make it so that Get()'s implementation + // doesn't need to be aware of this ordering? Revisit when refactoring + // ResourceContext and AppCache to respect storage partitions. + void PostCreateInitialization(StoragePartition* partition, + const FilePath& partition_path); + + BrowserContext* browser_context_; // Not Owned. + std::map<std::string, StoragePartition*> partitions_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_STORAGE_PARTITION_MAP_H_ diff --git a/content/browser/web_contents/navigation_controller_impl.cc b/content/browser/web_contents/navigation_controller_impl.cc index d985605..dc49e94 100644 --- a/content/browser/web_contents/navigation_controller_impl.cc +++ b/content/browser/web_contents/navigation_controller_impl.cc @@ -194,7 +194,7 @@ NavigationControllerImpl::NavigationControllerImpl( if (!session_storage_namespace_) { session_storage_namespace_ = new SessionStorageNamespaceImpl( static_cast<DOMStorageContextImpl*>( - BrowserContext::GetDOMStorageContext(browser_context_))); + BrowserContext::GetDefaultDOMStorageContext(browser_context_))); } } diff --git a/content/browser/worker_host/worker_process_host.cc b/content/browser/worker_host/worker_process_host.cc index 8a3882b..dc4a8bc 100644 --- a/content/browser/worker_host/worker_process_host.cc +++ b/content/browser/worker_host/worker_process_host.cc @@ -622,7 +622,8 @@ bool WorkerProcessHost::WorkerInstance::Matches( if (closed_) return false; - // Have to match the same ResourceContext. + // ResourceContext equivalence is being used as a proxy to ensure we only + // matched shared workers within the same BrowserContext. if (resource_context_ != resource_context) return false; diff --git a/content/common/child_process_host_impl.cc b/content/common/child_process_host_impl.cc index f1e330c..2de8840 100644 --- a/content/common/child_process_host_impl.cc +++ b/content/common/child_process_host_impl.cc @@ -77,6 +77,8 @@ FilePath TransformPathForFeature(const FilePath& path, namespace content { +int ChildProcessHostImpl::kInvalidChildProcessId = -1; + // static ChildProcessHost* ChildProcessHost::Create(ChildProcessHostDelegate* delegate) { return new ChildProcessHostImpl(delegate); @@ -208,8 +210,14 @@ void ChildProcessHostImpl::AllocateSharedMemory( int ChildProcessHostImpl::GenerateChildProcessUniqueId() { // This function must be threadsafe. + // + // TODO(ajwong): Why not StaticAtomicSequenceNumber? static base::subtle::Atomic32 last_unique_child_id = 0; - return base::subtle::NoBarrier_AtomicIncrement(&last_unique_child_id, 1); + int id = base::subtle::NoBarrier_AtomicIncrement(&last_unique_child_id, 1); + + CHECK_NE(kInvalidChildProcessId, id); + + return id; } bool ChildProcessHostImpl::OnMessageReceived(const IPC::Message& msg) { diff --git a/content/common/child_process_host_impl.h b/content/common/child_process_host_impl.h index 0d4f3d5..3216acf 100644 --- a/content/common/child_process_host_impl.h +++ b/content/common/child_process_host_impl.h @@ -31,6 +31,10 @@ class CONTENT_EXPORT ChildProcessHostImpl : public ChildProcessHost, public: virtual ~ChildProcessHostImpl(); + // This value is guaranteed to never be returned by + // GenerateChildProcessUniqueId() below. + static int kInvalidChildProcessId; + // Public and static for reuse by RenderMessageFilter. static void AllocateSharedMemory( uint32 buffer_size, base::ProcessHandle child_process, diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 54115b9..ae9d1db 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -268,9 +268,9 @@ 'browser/device_orientation/data_fetcher.h', 'browser/device_orientation/data_fetcher_impl_android.cc', 'browser/device_orientation/data_fetcher_impl_android.h', + 'browser/device_orientation/orientation.h', 'browser/device_orientation/orientation_message_filter.cc', 'browser/device_orientation/orientation_message_filter.h', - 'browser/device_orientation/orientation.h', 'browser/device_orientation/provider.cc', 'browser/device_orientation/provider.h', 'browser/device_orientation/provider_impl.cc', @@ -292,6 +292,8 @@ 'browser/download/download_file_impl.h', 'browser/download/download_file_manager.cc', 'browser/download/download_file_manager.h', + 'browser/download/download_interrupt_reasons_impl.cc', + 'browser/download/download_interrupt_reasons_impl.h', 'browser/download/download_item_factory.h', 'browser/download/download_item_impl.cc', 'browser/download/download_item_impl.h', @@ -309,8 +311,6 @@ 'browser/download/drag_download_file.h', 'browser/download/drag_download_util.cc', 'browser/download/drag_download_util.h', - 'browser/download/download_interrupt_reasons_impl.cc', - 'browser/download/download_interrupt_reasons_impl.h', 'browser/download/mhtml_generation_manager.cc', 'browser/download/mhtml_generation_manager.h', 'browser/download/save_file.cc', @@ -373,10 +373,10 @@ 'browser/geolocation/location_api_adapter_android.h', 'browser/geolocation/location_arbitrator.cc', 'browser/geolocation/location_arbitrator.h', - 'browser/geolocation/location_provider.cc', - 'browser/geolocation/location_provider.h', 'browser/geolocation/location_provider_android.cc', 'browser/geolocation/location_provider_android.h', + 'browser/geolocation/location_provider.cc', + 'browser/geolocation/location_provider.h', 'browser/geolocation/network_location_provider.cc', 'browser/geolocation/network_location_provider.h', 'browser/geolocation/network_location_request.cc', @@ -465,8 +465,8 @@ 'browser/plugin_process_host_mac.cc', 'browser/plugin_service_impl.cc', 'browser/plugin_service_impl.h', - 'browser/power_save_blocker.h', 'browser/power_save_blocker_android.cc', + 'browser/power_save_blocker.h', 'browser/power_save_blocker_linux.cc', 'browser/power_save_blocker_mac.cc', 'browser/power_save_blocker_win.cc', @@ -484,16 +484,16 @@ 'browser/renderer_host/accelerated_surface_container_manager_mac.h', 'browser/renderer_host/async_resource_handler.cc', 'browser/renderer_host/async_resource_handler.h', + 'browser/renderer_host/backing_store_aura.cc', + 'browser/renderer_host/backing_store_aura.h', 'browser/renderer_host/backing_store.cc', - 'browser/renderer_host/backing_store.h', 'browser/renderer_host/backing_store_gtk.cc', 'browser/renderer_host/backing_store_gtk.h', + 'browser/renderer_host/backing_store.h', 'browser/renderer_host/backing_store_mac.h', 'browser/renderer_host/backing_store_mac.mm', 'browser/renderer_host/backing_store_manager.cc', 'browser/renderer_host/backing_store_manager.h', - 'browser/renderer_host/backing_store_aura.cc', - 'browser/renderer_host/backing_store_aura.h', 'browser/renderer_host/backing_store_win.cc', 'browser/renderer_host/backing_store_win.h', 'browser/renderer_host/buffered_resource_handler.cc', @@ -532,10 +532,10 @@ 'browser/renderer_host/java/java_bound_object.h', 'browser/renderer_host/java/java_bridge_channel_host.cc', 'browser/renderer_host/java/java_bridge_channel_host.h', - 'browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc', - 'browser/renderer_host/java/java_bridge_dispatcher_host_manager.h', 'browser/renderer_host/java/java_bridge_dispatcher_host.cc', 'browser/renderer_host/java/java_bridge_dispatcher_host.h', + 'browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc', + 'browser/renderer_host/java/java_bridge_dispatcher_host_manager.h', 'browser/renderer_host/java/java_method.cc', 'browser/renderer_host/java/java_method.h', 'browser/renderer_host/java/java_type.cc', @@ -543,8 +543,8 @@ 'browser/renderer_host/layered_resource_handler.cc', 'browser/renderer_host/layered_resource_handler.h', 'browser/renderer_host/media/audio_input_device_manager.cc', - 'browser/renderer_host/media/audio_input_device_manager.h', 'browser/renderer_host/media/audio_input_device_manager_event_handler.h', + 'browser/renderer_host/media/audio_input_device_manager.h', 'browser/renderer_host/media/audio_input_renderer_host.cc', 'browser/renderer_host/media/audio_input_renderer_host.h', 'browser/renderer_host/media/audio_input_sync_writer.cc', @@ -563,16 +563,16 @@ 'browser/renderer_host/media/media_stream_requester.h', 'browser/renderer_host/media/media_stream_settings_requester.h', 'browser/renderer_host/media/video_capture_controller.cc', - 'browser/renderer_host/media/video_capture_controller.h', 'browser/renderer_host/media/video_capture_controller_event_handler.cc', 'browser/renderer_host/media/video_capture_controller_event_handler.h', + 'browser/renderer_host/media/video_capture_controller.h', 'browser/renderer_host/media/video_capture_host.cc', 'browser/renderer_host/media/video_capture_host.h', 'browser/renderer_host/media/video_capture_manager.cc', 'browser/renderer_host/media/video_capture_manager.h', - 'browser/renderer_host/native_web_keyboard_event.cc', 'browser/renderer_host/native_web_keyboard_event_android.cc', 'browser/renderer_host/native_web_keyboard_event_aura.cc', + 'browser/renderer_host/native_web_keyboard_event.cc', 'browser/renderer_host/native_web_keyboard_event_gtk.cc', 'browser/renderer_host/native_web_keyboard_event_mac.mm', 'browser/renderer_host/native_web_keyboard_event_win.cc', @@ -614,18 +614,18 @@ 'browser/renderer_host/render_widget_host_impl.cc', 'browser/renderer_host/render_widget_host_impl.h', 'browser/renderer_host/render_widget_host_mac.cc', - 'browser/renderer_host/render_widget_host_view_base.cc', - 'browser/renderer_host/render_widget_host_view_base.h', 'browser/renderer_host/render_widget_host_view_android.cc', 'browser/renderer_host/render_widget_host_view_android.h', 'browser/renderer_host/render_widget_host_view_aura.cc', 'browser/renderer_host/render_widget_host_view_aura.h', + 'browser/renderer_host/render_widget_host_view_base.cc', + 'browser/renderer_host/render_widget_host_view_base.h', 'browser/renderer_host/render_widget_host_view_gtk.cc', 'browser/renderer_host/render_widget_host_view_gtk.h', - 'browser/renderer_host/render_widget_host_view_mac.h', - 'browser/renderer_host/render_widget_host_view_mac.mm', 'browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h', 'browser/renderer_host/render_widget_host_view_mac_editcommand_helper.mm', + 'browser/renderer_host/render_widget_host_view_mac.h', + 'browser/renderer_host/render_widget_host_view_mac.mm', 'browser/renderer_host/render_widget_host_view_win.cc', 'browser/renderer_host/render_widget_host_view_win.h', 'browser/renderer_host/resource_dispatcher_host_impl.cc', @@ -633,8 +633,8 @@ 'browser/renderer_host/resource_handler.cc', 'browser/renderer_host/resource_handler.h', 'browser/renderer_host/resource_loader.cc', - 'browser/renderer_host/resource_loader.h', 'browser/renderer_host/resource_loader_delegate.h', + 'browser/renderer_host/resource_loader.h', 'browser/renderer_host/resource_message_filter.cc', 'browser/renderer_host/resource_message_filter.h', 'browser/renderer_host/resource_request_info_impl.cc', @@ -645,9 +645,9 @@ 'browser/renderer_host/socket_stream_host.h', 'browser/renderer_host/sync_resource_handler.cc', 'browser/renderer_host/sync_resource_handler.h', - 'browser/renderer_host/tap_suppression_controller.h', - 'browser/renderer_host/tap_suppression_controller.cc', 'browser/renderer_host/tap_suppression_controller_aura.cc', + 'browser/renderer_host/tap_suppression_controller.cc', + 'browser/renderer_host/tap_suppression_controller.h', 'browser/renderer_host/text_input_client_mac.h', 'browser/renderer_host/text_input_client_mac.mm', 'browser/renderer_host/text_input_client_message_filter.h', @@ -706,10 +706,14 @@ 'browser/ssl/ssl_host_state.h', 'browser/ssl/ssl_manager.cc', 'browser/ssl/ssl_manager.h', - 'browser/ssl/ssl_policy.cc', - 'browser/ssl/ssl_policy.h', 'browser/ssl/ssl_policy_backend.cc', 'browser/ssl/ssl_policy_backend.h', + 'browser/ssl/ssl_policy.cc', + 'browser/ssl/ssl_policy.h', + 'browser/storage_partition.cc', + 'browser/storage_partition.h', + 'browser/storage_partition_map.cc', + 'browser/storage_partition_map.h', 'browser/ssl/ssl_request_info.cc', 'browser/ssl/ssl_request_info.h', 'browser/system_message_window_win.cc', diff --git a/content/public/browser/browser_context.h b/content/public/browser/browser_context.h index f92d6b4..9f003d8 100644 --- a/content/public/browser/browser_context.h +++ b/content/public/browser/browser_context.h @@ -49,8 +49,10 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData { public: static DownloadManager* GetDownloadManager(BrowserContext* browser_context); static quota::QuotaManager* GetQuotaManager(BrowserContext* browser_context); - static DOMStorageContext* GetDOMStorageContext( + static DOMStorageContext* GetDefaultDOMStorageContext( BrowserContext* browser_context); + static DOMStorageContext* GetDOMStorageContext( + BrowserContext* browser_context, int renderer_child_id); static IndexedDBContext* GetIndexedDBContext(BrowserContext* browser_context); static webkit_database::DatabaseTracker* GetDatabaseTracker( BrowserContext* browser_context); diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index 6c28657..8717398 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc @@ -147,6 +147,12 @@ net::URLRequestContext* ContentBrowserClient::OverrideRequestContextForURL( return NULL; } +std::string ContentBrowserClient::GetStoragePartitionIdForChildProcess( + content::BrowserContext* browser_context, + int child_process_id) { + return std::string(); +} + MediaObserver* ContentBrowserClient::GetMediaObserver() { return NULL; } diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index d4030c7..9fb5a4d 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h @@ -239,13 +239,26 @@ class CONTENT_EXPORT ContentBrowserClient { ResourceContext* context, const std::vector<std::pair<int, int> >& render_views); - // Allows the embedder to override the request context based on the URL for + // Allow the embedder to override the request context based on the URL for // certain operations, like cookie access. Returns NULL to indicate the // regular request context should be used. // This is called on the IO thread. virtual net::URLRequestContext* OverrideRequestContextForURL( const GURL& url, ResourceContext* context); + // Allow the embedder to specify storage parititon id associated with a child + // process. + // + // Child processes that have different storage partition identifiers will + // behave as if they belong to different web browsers and not be able to + // access each other's cookies, local storage, etc. IDs must only fit the + // pattern [a-z0-9]* (lowercase letters or digits). + // + // Returns the empty string for the regular storage partition. + virtual std::string GetStoragePartitionIdForChildProcess( + content::BrowserContext* browser_context, + int child_process_id); + // Create and return a new quota permission context. virtual QuotaPermissionContext* CreateQuotaPermissionContext(); |