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

Side by Side Diff: content/browser/browser_context.cc

Issue 10600009: Support partitioning of storage contexts based on render_id. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: rebased 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
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 "content/public/browser/browser_context.h" 5 #include "content/public/browser/browser_context.h"
6 6
7 #include "content/browser/appcache/chrome_appcache_service.h" 7 #include "content/browser/appcache/chrome_appcache_service.h"
8 #include "webkit/database/database_tracker.h"
8 #include "content/browser/dom_storage/dom_storage_context_impl.h" 9 #include "content/browser/dom_storage/dom_storage_context_impl.h"
9 #include "content/browser/download/download_file_manager.h" 10 #include "content/browser/download/download_file_manager.h"
10 #include "content/browser/download/download_manager_impl.h" 11 #include "content/browser/download/download_manager_impl.h"
11 #include "content/browser/fileapi/browser_file_system_helper.h"
12 #include "content/browser/in_process_webkit/indexed_db_context_impl.h" 12 #include "content/browser/in_process_webkit/indexed_db_context_impl.h"
13 #include "content/browser/renderer_host/resource_dispatcher_host_impl.h" 13 #include "content/browser/renderer_host/resource_dispatcher_host_impl.h"
14 #include "content/browser/resource_context_impl.h" 14 #include "content/public/browser/resource_context.h"
15 #include "content/browser/storage_partition.h"
16 #include "content/browser/storage_partition_map.h"
17 #include "content/common/child_process_host_impl.h"
15 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/content_browser_client.h" 19 #include "content/public/browser/content_browser_client.h"
17 #include "content/public/common/content_constants.h"
18 #include "net/base/server_bound_cert_service.h" 20 #include "net/base/server_bound_cert_service.h"
19 #include "net/base/server_bound_cert_store.h" 21 #include "net/base/server_bound_cert_store.h"
20 #include "net/cookies/cookie_monster.h" 22 #include "net/cookies/cookie_monster.h"
21 #include "net/cookies/cookie_store.h" 23 #include "net/cookies/cookie_store.h"
22 #include "net/url_request/url_request_context.h" 24 #include "net/url_request/url_request_context.h"
23 #include "webkit/database/database_tracker.h"
24 #include "webkit/quota/quota_manager.h"
25 25
26 using appcache::AppCacheService;
27 using base::UserDataAdapter; 26 using base::UserDataAdapter;
28 using content::BrowserThread;
29 using fileapi::FileSystemContext;
30 using quota::QuotaManager;
31 using webkit_database::DatabaseTracker;
32 27
33 // Key names on BrowserContext. 28 // Key names on BrowserContext.
34 static const char* kAppCacheServicKeyName = "content_appcache_service_tracker";
35 static const char* kDatabaseTrackerKeyName = "content_database_tracker";
36 static const char* kDOMStorageContextKeyName = "content_dom_storage_context";
37 static const char* kDownloadManagerKeyName = "download_manager"; 29 static const char* kDownloadManagerKeyName = "download_manager";
38 static const char* kFileSystemContextKeyName = "content_file_system_context"; 30 static const char* kStorageParitionMapKeyName = "content_storage_partition_map";
39 static const char* kIndexedDBContextKeyName = "content_indexed_db_context";
40 static const char* kQuotaManagerKeyName = "content_quota_manager";
41 31
42 namespace content { 32 namespace content {
43 33
44 namespace { 34 namespace {
45 35
46 void CreateQuotaManagerAndClients(BrowserContext* context) { 36 StoragePartition* GetStoragePartition(BrowserContext* browser_context,
47 // Ensure that these methods are called on the UI thread, except for unittests 37 int renderer_child_id) {
48 // where a UI thread might not have been created. 38 StoragePartitionMap* partition_map = static_cast<StoragePartitionMap*>(
49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || 39 browser_context->GetUserData(kStorageParitionMapKeyName));
50 !BrowserThread::IsMessageLoopValid(BrowserThread::UI)); 40 if (!partition_map) {
51 if (context->GetUserData(kQuotaManagerKeyName)) { 41 partition_map = new StoragePartitionMap(browser_context);
52 DCHECK(context->GetUserData(kDatabaseTrackerKeyName)); 42 browser_context->SetUserData(kStorageParitionMapKeyName, partition_map);
53 DCHECK(context->GetUserData(kDOMStorageContextKeyName)); 43 }
54 DCHECK(context->GetUserData(kFileSystemContextKeyName)); 44
55 DCHECK(context->GetUserData(kIndexedDBContextKeyName)); 45 const std::string& partition_id =
46 GetContentClient()->browser()->GetStoragePartitionIdForChildProcess(
47 browser_context,
48 renderer_child_id);
49
50 return partition_map->Get(partition_id);
51 }
52
53 // Run |callback| on each storage partition in |browser_context|.
54 void ForEachStoragePartition(
55 BrowserContext* browser_context,
56 const base::Callback<void(StoragePartition*)>& callback) {
57 StoragePartitionMap* partition_map = static_cast<StoragePartitionMap*>(
58 browser_context->GetUserData(kStorageParitionMapKeyName));
59 if (!partition_map) {
56 return; 60 return;
57 } 61 }
58 62
59 // All of the clients have to be created and registered with the 63 partition_map->ForEach(callback);
60 // QuotaManager prior to the QuotaManger being used. So we do them 64 }
61 // all together here prior to handing out a reference to anything
62 // that utlizes the QuotaManager.
63 scoped_refptr<QuotaManager> quota_manager = new quota::QuotaManager(
64 context->IsOffTheRecord(), context->GetPath(),
65 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
66 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB),
67 context->GetSpecialStoragePolicy());
68 context->SetUserData(kQuotaManagerKeyName,
69 new UserDataAdapter<QuotaManager>(quota_manager));
70 65
71 // Each consumer is responsible for registering its QuotaClient during 66 // Used to convert a callback meant to take a DOMStorageContextImpl* into one
72 // its construction. 67 // that can take a StoragePartition*.
73 scoped_refptr<FileSystemContext> filesystem_context = CreateFileSystemContext( 68 void ProcessDOMStorageContext(
74 context->GetPath(), context->IsOffTheRecord(), 69 const base::Callback<void(DOMStorageContextImpl*)>& callback,
75 context->GetSpecialStoragePolicy(), quota_manager->proxy()); 70 StoragePartition* partition) {
76 context->SetUserData( 71 callback.Run(partition->dom_storage_context());
77 kFileSystemContextKeyName, 72 }
78 new UserDataAdapter<FileSystemContext>(filesystem_context));
79 73
80 scoped_refptr<DatabaseTracker> db_tracker = new DatabaseTracker( 74 // Run |callback| on each DOMStorageContextImpl in |browser_context|.
81 context->GetPath(), context->IsOffTheRecord(), 75 void ForEachDOMStorageContext(
82 context->GetSpecialStoragePolicy(), quota_manager->proxy(), 76 BrowserContext* browser_context,
83 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); 77 const base::Callback<void(DOMStorageContextImpl*)>& callback) {
84 context->SetUserData(kDatabaseTrackerKeyName, 78 ForEachStoragePartition(browser_context,
85 new UserDataAdapter<DatabaseTracker>(db_tracker)); 79 base::Bind(&ProcessDOMStorageContext, callback));
86
87 FilePath path = context->IsOffTheRecord() ? FilePath() : context->GetPath();
88 scoped_refptr<DOMStorageContextImpl> dom_storage_context =
89 new DOMStorageContextImpl(path, context->GetSpecialStoragePolicy());
90 context->SetUserData(
91 kDOMStorageContextKeyName,
92 new UserDataAdapter<DOMStorageContextImpl>(dom_storage_context));
93
94 scoped_refptr<IndexedDBContext> indexed_db_context = new IndexedDBContextImpl(
95 path, context->GetSpecialStoragePolicy(), quota_manager->proxy(),
96 BrowserThread::GetMessageLoopProxyForThread(
97 BrowserThread::WEBKIT_DEPRECATED));
98 context->SetUserData(
99 kIndexedDBContextKeyName,
100 new UserDataAdapter<IndexedDBContext>(indexed_db_context));
101
102 scoped_refptr<ChromeAppCacheService> appcache_service =
103 new ChromeAppCacheService(quota_manager->proxy());
104 context->SetUserData(
105 kAppCacheServicKeyName,
106 new UserDataAdapter<ChromeAppCacheService>(appcache_service));
107
108 InitializeResourceContext(context);
109
110 // Check first to avoid memory leak in unittests.
111 if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) {
112 BrowserThread::PostTask(
113 BrowserThread::IO, FROM_HERE,
114 base::Bind(&ChromeAppCacheService::InitializeOnIOThread,
115 appcache_service,
116 context->IsOffTheRecord() ? FilePath() :
117 context->GetPath().Append(content::kAppCacheDirname),
118 context->GetResourceContext(),
119 make_scoped_refptr(context->GetSpecialStoragePolicy())));
120 }
121 } 80 }
122 81
123 void SaveSessionStateOnIOThread(ResourceContext* resource_context) { 82 void SaveSessionStateOnIOThread(ResourceContext* resource_context) {
124 resource_context->GetRequestContext()->cookie_store()->GetCookieMonster()-> 83 resource_context->GetRequestContext()->cookie_store()->GetCookieMonster()->
125 SetForceKeepSessionState(); 84 SetForceKeepSessionState();
126 resource_context->GetRequestContext()->server_bound_cert_service()-> 85 resource_context->GetRequestContext()->server_bound_cert_service()->
127 GetCertStore()->SetForceKeepSessionState(); 86 GetCertStore()->SetForceKeepSessionState();
128 ResourceContext::GetAppCacheService(resource_context)-> 87 ResourceContext::GetAppCacheService(resource_context)->
129 set_force_keep_session_state(); 88 set_force_keep_session_state();
130 } 89 }
131 90
132 void SaveSessionStateOnWebkitThread( 91 void SaveSessionStateOnWebkitThread(
133 scoped_refptr<IndexedDBContextImpl> indexed_db_context) { 92 scoped_refptr<IndexedDBContextImpl> indexed_db_context) {
134 indexed_db_context->SetForceKeepSessionState(); 93 indexed_db_context->SetForceKeepSessionState();
135 } 94 }
136 95
137 void PurgeMemoryOnIOThread(ResourceContext* resource_context) { 96 void PurgeMemoryOnIOThread(ResourceContext* resource_context) {
138 ResourceContext::GetAppCacheService(resource_context)->PurgeMemory(); 97 ResourceContext::GetAppCacheService(resource_context)->PurgeMemory();
139 } 98 }
140 99
141 DOMStorageContextImpl* GetDOMStorageContextImpl(BrowserContext* context) { 100 DOMStorageContextImpl* GetDefaultDOMStorageContextImpl(
101 BrowserContext* context) {
142 return static_cast<DOMStorageContextImpl*>( 102 return static_cast<DOMStorageContextImpl*>(
143 BrowserContext::GetDOMStorageContext(context)); 103 BrowserContext::GetDefaultDOMStorageContext(context));
144 } 104 }
145 105
146 } // namespace 106 } // namespace
147 107
148 DownloadManager* BrowserContext::GetDownloadManager( 108 DownloadManager* BrowserContext::GetDownloadManager(
149 BrowserContext* context) { 109 BrowserContext* context) {
150 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
151 if (!context->GetUserData(kDownloadManagerKeyName)) { 111 if (!context->GetUserData(kDownloadManagerKeyName)) {
152 ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get(); 112 ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
153 DCHECK(rdh); 113 DCHECK(rdh);
154 DownloadFileManager* file_manager = rdh->download_file_manager(); 114 DownloadFileManager* file_manager = rdh->download_file_manager();
155 DCHECK(file_manager); 115 DCHECK(file_manager);
156 scoped_refptr<DownloadManager> download_manager = 116 scoped_refptr<DownloadManager> download_manager =
157 new DownloadManagerImpl( 117 new DownloadManagerImpl(
158 file_manager, 118 file_manager,
159 scoped_ptr<DownloadItemFactory>(), 119 scoped_ptr<DownloadItemFactory>(),
160 GetContentClient()->browser()->GetNetLog()); 120 GetContentClient()->browser()->GetNetLog());
161 121
162 context->SetUserData( 122 context->SetUserData(
163 kDownloadManagerKeyName, 123 kDownloadManagerKeyName,
164 new UserDataAdapter<DownloadManager>(download_manager)); 124 new UserDataAdapter<DownloadManager>(download_manager));
165 download_manager->SetDelegate(context->GetDownloadManagerDelegate()); 125 download_manager->SetDelegate(context->GetDownloadManagerDelegate());
166 download_manager->Init(context); 126 download_manager->Init(context);
167 } 127 }
168 128
169 return UserDataAdapter<DownloadManager>::Get( 129 return UserDataAdapter<DownloadManager>::Get(
170 context, kDownloadManagerKeyName); 130 context, kDownloadManagerKeyName);
171 } 131 }
172 132
173 QuotaManager* BrowserContext::GetQuotaManager(BrowserContext* context) { 133 quota::QuotaManager* BrowserContext::GetQuotaManager(
174 CreateQuotaManagerAndClients(context); 134 BrowserContext* browser_context) {
175 return UserDataAdapter<QuotaManager>::Get(context, kQuotaManagerKeyName); 135 // TODO(ajwong): Change this API to require a process id instead of using
136 // kInvalidChildProcessId.
137 StoragePartition* partition =
138 GetStoragePartition(browser_context,
139 ChildProcessHostImpl::kInvalidChildProcessId);
140 return partition->quota_manager();
141 }
142
143 DOMStorageContext* BrowserContext::GetDefaultDOMStorageContext(
144 BrowserContext* browser_context) {
145 // TODO(ajwong): Force all users to know which process id they are performing
146 // actions on behalf of, migrate them to GetDOMStorageContext(), and then
147 // delete this function.
148 return GetDOMStorageContext(browser_context,
149 ChildProcessHostImpl::kInvalidChildProcessId);
176 } 150 }
177 151
178 DOMStorageContext* BrowserContext::GetDOMStorageContext( 152 DOMStorageContext* BrowserContext::GetDOMStorageContext(
179 BrowserContext* context) { 153 BrowserContext* browser_context,
180 CreateQuotaManagerAndClients(context); 154 int render_child_id) {
181 return UserDataAdapter<DOMStorageContextImpl>::Get( 155 StoragePartition* partition =
182 context, kDOMStorageContextKeyName); 156 GetStoragePartition(browser_context, render_child_id);
157 return partition->dom_storage_context();
183 } 158 }
184 159
185 IndexedDBContext* BrowserContext::GetIndexedDBContext(BrowserContext* context) { 160 IndexedDBContext* BrowserContext::GetIndexedDBContext(
186 CreateQuotaManagerAndClients(context); 161 BrowserContext* browser_context) {
187 return UserDataAdapter<IndexedDBContext>::Get( 162 // TODO(ajwong): Change this API to require a process id instead of using
188 context, kIndexedDBContextKeyName); 163 // kInvalidChildProcessId.
164 StoragePartition* partition =
165 GetStoragePartition(browser_context,
166 ChildProcessHostImpl::kInvalidChildProcessId);
167 return partition->indexed_db_context();
189 } 168 }
190 169
191 DatabaseTracker* BrowserContext::GetDatabaseTracker(BrowserContext* context) { 170 webkit_database::DatabaseTracker* BrowserContext::GetDatabaseTracker(
192 CreateQuotaManagerAndClients(context); 171 BrowserContext* browser_context) {
193 return UserDataAdapter<DatabaseTracker>::Get( 172 // TODO(ajwong): Change this API to require a process id instead of using
194 context, kDatabaseTrackerKeyName); 173 // kInvalidChildProcessId.
174 StoragePartition* partition =
175 GetStoragePartition(browser_context,
176 ChildProcessHostImpl::kInvalidChildProcessId);
177 return partition->database_tracker();
195 } 178 }
196 179
197 AppCacheService* BrowserContext::GetAppCacheService( 180 appcache::AppCacheService* BrowserContext::GetAppCacheService(
198 BrowserContext* browser_context) { 181 BrowserContext* browser_context) {
199 CreateQuotaManagerAndClients(browser_context); 182 // TODO(ajwong): Change this API to require a process id instead of using
200 return UserDataAdapter<ChromeAppCacheService>::Get( 183 // kInvalidChildProcessId.
201 browser_context, kAppCacheServicKeyName); 184 StoragePartition* partition =
185 GetStoragePartition(browser_context,
186 ChildProcessHostImpl::kInvalidChildProcessId);
187 return partition->appcache_service();
202 } 188 }
203 189
204 FileSystemContext* BrowserContext::GetFileSystemContext( 190 fileapi::FileSystemContext* BrowserContext::GetFileSystemContext(
205 BrowserContext* browser_context) { 191 BrowserContext* browser_context) {
206 CreateQuotaManagerAndClients(browser_context); 192 // TODO(ajwong): Change this API to require a process id instead of using
207 return UserDataAdapter<FileSystemContext>::Get( 193 // kInvalidChildProcessId.
208 browser_context, kFileSystemContextKeyName); 194 StoragePartition* partition =
195 GetStoragePartition(browser_context,
196 ChildProcessHostImpl::kInvalidChildProcessId);
197 return partition->filesystem_context();
209 } 198 }
210 199
211 void BrowserContext::EnsureResourceContextInitialized(BrowserContext* context) { 200 void BrowserContext::EnsureResourceContextInitialized(BrowserContext* context) {
212 // This will be enough to tickle initialization of BrowserContext if 201 // This will be enough to tickle initialization of BrowserContext if
213 // necessary, which initializes ResourceContext. The reason we don't call 202 // necessary, which initializes ResourceContext. The reason we don't call
214 // ResourceContext::InitializeResourceContext directly here is that if 203 // ResourceContext::InitializeResourceContext directly here is that if
215 // ResourceContext ends up initializing it will call back into BrowserContext 204 // ResourceContext ends up initializing it will call back into BrowserContext
216 // and when that call return it'll end rewriting its UserData map (with the 205 // and when that call returns it'll end rewriting its UserData map (with the
217 // same value) but this causes a race condition. See http://crbug.com/115678. 206 // same value) but this causes a race condition. See http://crbug.com/115678.
218 CreateQuotaManagerAndClients(context); 207 GetStoragePartition(context, ChildProcessHostImpl::kInvalidChildProcessId);
219 } 208 }
220 209
221 void BrowserContext::SaveSessionState(BrowserContext* browser_context) { 210 void BrowserContext::SaveSessionState(BrowserContext* browser_context) {
222 GetDatabaseTracker(browser_context)->SetForceKeepSessionState(); 211 GetDatabaseTracker(browser_context)->SetForceKeepSessionState();
223 212
224 if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { 213 if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) {
225 BrowserThread::PostTask( 214 BrowserThread::PostTask(
226 BrowserThread::IO, FROM_HERE, 215 BrowserThread::IO, FROM_HERE,
227 base::Bind(&SaveSessionStateOnIOThread, 216 base::Bind(&SaveSessionStateOnIOThread,
228 browser_context->GetResourceContext())); 217 browser_context->GetResourceContext()));
229 } 218 }
230 219
231 GetDOMStorageContextImpl(browser_context)->SetForceKeepSessionState(); 220 // TODO(ajwong): This is the only usage of GetDefaultDOMStorageContextImpl().
221 // After we migrate this to support multiple DOMStorageContexts, don't forget
222 // to remove the GetDefaultDOMStorageContextImpl() function as well.
223 GetDefaultDOMStorageContextImpl(browser_context)->SetForceKeepSessionState();
232 224
233 if (BrowserThread::IsMessageLoopValid(BrowserThread::WEBKIT_DEPRECATED)) { 225 if (BrowserThread::IsMessageLoopValid(BrowserThread::WEBKIT_DEPRECATED)) {
234 IndexedDBContextImpl* indexed_db = static_cast<IndexedDBContextImpl*>( 226 IndexedDBContextImpl* indexed_db = static_cast<IndexedDBContextImpl*>(
235 GetIndexedDBContext(browser_context)); 227 GetIndexedDBContext(browser_context));
236 BrowserThread::PostTask( 228 BrowserThread::PostTask(
237 BrowserThread::WEBKIT_DEPRECATED, FROM_HERE, 229 BrowserThread::WEBKIT_DEPRECATED, FROM_HERE,
238 base::Bind(&SaveSessionStateOnWebkitThread, 230 base::Bind(&SaveSessionStateOnWebkitThread,
239 make_scoped_refptr(indexed_db))); 231 make_scoped_refptr(indexed_db)));
240 } 232 }
241 } 233 }
242 234
243 void BrowserContext::PurgeMemory(BrowserContext* browser_context) { 235 void BrowserContext::PurgeMemory(BrowserContext* browser_context) {
244 if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { 236 if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) {
245 BrowserThread::PostTask( 237 BrowserThread::PostTask(
246 BrowserThread::IO, FROM_HERE, 238 BrowserThread::IO, FROM_HERE,
247 base::Bind(&PurgeMemoryOnIOThread, 239 base::Bind(&PurgeMemoryOnIOThread,
248 browser_context->GetResourceContext())); 240 browser_context->GetResourceContext()));
249 } 241 }
250 242
251 GetDOMStorageContextImpl(browser_context)->PurgeMemory(); 243 ForEachDOMStorageContext(browser_context,
244 base::Bind(&DOMStorageContextImpl::PurgeMemory));
252 } 245 }
253 246
254 BrowserContext::~BrowserContext() { 247 BrowserContext::~BrowserContext() {
255 // These message loop checks are just to avoid leaks in unittests.
256 if (GetUserData(kDatabaseTrackerKeyName) &&
257 BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) {
258 BrowserThread::PostTask(
259 BrowserThread::FILE, FROM_HERE,
260 base::Bind(&webkit_database::DatabaseTracker::Shutdown,
261 GetDatabaseTracker(this)));
262 }
263
264 if (GetUserData(kDOMStorageContextKeyName))
265 GetDOMStorageContextImpl(this)->Shutdown();
266
267 if (GetUserData(kDownloadManagerKeyName)) 248 if (GetUserData(kDownloadManagerKeyName))
268 GetDownloadManager(this)->Shutdown(); 249 GetDownloadManager(this)->Shutdown();
269 } 250 }
270 251
271 } // namespace content 252 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698