storage_partition_impl.cc revision 58e6fbe4ee35d65e14b626c557d37565bf8ad179
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
3// found in the LICENSE file.
4
5#include "content/browser/storage_partition_impl.h"
6
7#include "base/sequenced_task_runner.h"
8#include "base/strings/utf_string_conversions.h"
9#include "content/browser/browser_main_loop.h"
10#include "content/browser/fileapi/browser_file_system_helper.h"
11#include "content/browser/gpu/shader_disk_cache.h"
12#include "content/public/browser/browser_context.h"
13#include "content/public/browser/browser_thread.h"
14#include "content/public/browser/dom_storage_context.h"
15#include "content/public/browser/indexed_db_context.h"
16#include "net/base/completion_callback.h"
17#include "net/base/net_errors.h"
18#include "net/cookies/cookie_monster.h"
19#include "net/url_request/url_request_context.h"
20#include "net/url_request/url_request_context_getter.h"
21#include "webkit/browser/database/database_tracker.h"
22#include "webkit/browser/quota/quota_manager.h"
23#include "webkit/common/dom_storage/dom_storage_types.h"
24
25namespace content {
26
27namespace {
28
29void DoNothingStatusCallback(quota::QuotaStatusCode status) {
30  // Do nothing.
31}
32
33void ClearQuotaManagedOriginsOnIOThread(
34    const scoped_refptr<quota::QuotaManager>& quota_manager,
35    const std::set<GURL>& origins,
36    quota::StorageType quota_storage_type) {
37  // The QuotaManager manages all storage other than cookies, LocalStorage,
38  // and SessionStorage. This loop wipes out most HTML5 storage for the given
39  // origins.
40  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
41  std::set<GURL>::const_iterator origin;
42  for (std::set<GURL>::const_iterator origin = origins.begin();
43       origin != origins.end(); ++origin) {
44    quota_manager->DeleteOriginData(*origin, quota_storage_type,
45                                    quota::QuotaClient::kAllClientsMask,
46                                    base::Bind(&DoNothingStatusCallback));
47  }
48}
49
50void ClearOriginOnIOThread(
51    uint32 storage_mask,
52    const GURL& storage_origin,
53    const scoped_refptr<net::URLRequestContextGetter>& request_context,
54    const scoped_refptr<quota::QuotaManager>& quota_manager) {
55  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
56
57  if (storage_mask & StoragePartition::kCookies) {
58    // Handle the cookies.
59    net::CookieMonster* cookie_monster =
60        request_context->GetURLRequestContext()->cookie_store()->
61            GetCookieMonster();
62    if (cookie_monster)
63      cookie_monster->DeleteAllForHostAsync(
64          storage_origin, net::CookieMonster::DeleteCallback());
65  }
66
67  // Handle all HTML5 storage other than DOMStorageContext.
68  std::set<GURL> origins;
69  origins.insert(storage_origin);
70  if (storage_mask & StoragePartition::kQuotaManagedTemporaryStorage) {
71    ClearQuotaManagedOriginsOnIOThread(quota_manager,
72                                       origins,
73                                       quota::kStorageTypeTemporary);
74  }
75  if (storage_mask & StoragePartition::kQuotaManagedPersistentStorage) {
76    ClearQuotaManagedOriginsOnIOThread(quota_manager,
77                                       origins,
78                                       quota::kStorageTypePersistent);
79  }
80  if (storage_mask & StoragePartition::kQuotaManagedSyncableStorage) {
81    ClearQuotaManagedOriginsOnIOThread(quota_manager,
82                                       origins,
83                                       quota::kStorageTypeSyncable);
84  }
85}
86
87void ClearAllDataOnIOThread(
88    uint32 storage_mask,
89    const scoped_refptr<net::URLRequestContextGetter>& request_context,
90    const scoped_refptr<quota::QuotaManager>& quota_manager) {
91  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
92
93  if (storage_mask & StoragePartition::kCookies) {
94    // Handle the cookies.
95    net::CookieMonster* cookie_monster =
96        request_context->GetURLRequestContext()->cookie_store()->
97            GetCookieMonster();
98    if (cookie_monster)
99      cookie_monster->DeleteAllAsync(net::CookieMonster::DeleteCallback());
100  }
101
102  // Handle all HTML5 storage other than DOMStorageContext.
103  if (storage_mask & StoragePartition::kQuotaManagedTemporaryStorage) {
104    quota_manager->GetOriginsModifiedSince(
105        quota::kStorageTypeTemporary, base::Time(),
106        base::Bind(&ClearQuotaManagedOriginsOnIOThread, quota_manager));
107  }
108  if (storage_mask & StoragePartition::kQuotaManagedPersistentStorage) {
109    quota_manager->GetOriginsModifiedSince(
110        quota::kStorageTypePersistent, base::Time(),
111        base::Bind(&ClearQuotaManagedOriginsOnIOThread, quota_manager));
112  }
113  if (storage_mask & StoragePartition::kQuotaManagedSyncableStorage) {
114    quota_manager->GetOriginsModifiedSince(
115        quota::kStorageTypeSyncable, base::Time(),
116        base::Bind(&ClearQuotaManagedOriginsOnIOThread, quota_manager));
117  }
118}
119
120void ClearedShaderCacheOnIOThread(base::Closure callback) {
121  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
122  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
123}
124
125void ClearShaderCacheOnIOThread(base::FilePath path,
126    base::Time begin, base::Time end, base::Closure callback) {
127  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
128  ShaderCacheFactory::GetInstance()->ClearByPath(
129      path, begin, end,
130      base::Bind(&ClearedShaderCacheOnIOThread, callback));
131}
132
133void OnLocalStorageUsageInfo(
134    const scoped_refptr<DOMStorageContextImpl>& dom_storage_context,
135    const std::vector<dom_storage::LocalStorageUsageInfo>& infos) {
136  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
137
138  for (size_t i = 0; i < infos.size(); ++i) {
139    dom_storage_context->DeleteLocalStorage(infos[i].origin);
140  }
141}
142
143void OnSessionStorageUsageInfo(
144    const scoped_refptr<DOMStorageContextImpl>& dom_storage_context,
145    const std::vector<dom_storage::SessionStorageUsageInfo>& infos) {
146  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
147
148  for (size_t i = 0; i < infos.size(); ++i) {
149    dom_storage_context->DeleteSessionStorage(infos[i]);
150  }
151}
152
153}  // namespace
154
155StoragePartitionImpl::StoragePartitionImpl(
156    const base::FilePath& partition_path,
157    quota::QuotaManager* quota_manager,
158    ChromeAppCacheService* appcache_service,
159    fileapi::FileSystemContext* filesystem_context,
160    webkit_database::DatabaseTracker* database_tracker,
161    DOMStorageContextImpl* dom_storage_context,
162    IndexedDBContextImpl* indexed_db_context,
163    scoped_ptr<WebRTCIdentityStore> webrtc_identity_store)
164    : partition_path_(partition_path),
165      quota_manager_(quota_manager),
166      appcache_service_(appcache_service),
167      filesystem_context_(filesystem_context),
168      database_tracker_(database_tracker),
169      dom_storage_context_(dom_storage_context),
170      indexed_db_context_(indexed_db_context),
171      webrtc_identity_store_(webrtc_identity_store.Pass()) {}
172
173StoragePartitionImpl::~StoragePartitionImpl() {
174  // These message loop checks are just to avoid leaks in unittests.
175  if (GetDatabaseTracker() &&
176      BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) {
177    BrowserThread::PostTask(
178        BrowserThread::FILE, FROM_HERE,
179        base::Bind(&webkit_database::DatabaseTracker::Shutdown,
180                   GetDatabaseTracker()));
181  }
182
183  if (GetDOMStorageContext())
184    GetDOMStorageContext()->Shutdown();
185}
186
187// TODO(ajwong): Break the direct dependency on |context|. We only
188// need 3 pieces of info from it.
189StoragePartitionImpl* StoragePartitionImpl::Create(
190    BrowserContext* context,
191    bool in_memory,
192    const base::FilePath& partition_path) {
193  // Ensure that these methods are called on the UI thread, except for
194  // unittests where a UI thread might not have been created.
195  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
196         !BrowserThread::IsMessageLoopValid(BrowserThread::UI));
197
198  // All of the clients have to be created and registered with the
199  // QuotaManager prior to the QuotaManger being used. We do them
200  // all together here prior to handing out a reference to anything
201  // that utilizes the QuotaManager.
202  scoped_refptr<quota::QuotaManager> quota_manager = new quota::QuotaManager(
203      in_memory,
204      partition_path,
205      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get(),
206      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(),
207      context->GetSpecialStoragePolicy());
208
209  // Each consumer is responsible for registering its QuotaClient during
210  // its construction.
211  scoped_refptr<fileapi::FileSystemContext> filesystem_context =
212      CreateFileSystemContext(context,
213                              partition_path, in_memory,
214                              quota_manager->proxy());
215
216  scoped_refptr<webkit_database::DatabaseTracker> database_tracker =
217      new webkit_database::DatabaseTracker(
218          partition_path,
219          in_memory,
220          context->GetSpecialStoragePolicy(),
221          quota_manager->proxy(),
222          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)
223              .get());
224
225  base::FilePath path = in_memory ? base::FilePath() : partition_path;
226  scoped_refptr<DOMStorageContextImpl> dom_storage_context =
227      new DOMStorageContextImpl(path, context->GetSpecialStoragePolicy());
228
229  // BrowserMainLoop may not be initialized in unit tests. Tests will
230  // need to inject their own task runner into the IndexedDBContext.
231  base::SequencedTaskRunner* idb_task_runner =
232      BrowserThread::CurrentlyOn(BrowserThread::UI) &&
233              BrowserMainLoop::GetInstance()
234          ? BrowserMainLoop::GetInstance()->indexed_db_thread()
235                ->message_loop_proxy().get()
236          : NULL;
237  scoped_refptr<IndexedDBContextImpl> indexed_db_context =
238      new IndexedDBContextImpl(path,
239                               context->GetSpecialStoragePolicy(),
240                               quota_manager->proxy(),
241                               idb_task_runner);
242
243  scoped_refptr<ChromeAppCacheService> appcache_service =
244      new ChromeAppCacheService(quota_manager->proxy());
245
246  scoped_ptr<WebRTCIdentityStore> webrtc_identity_store(
247      new WebRTCIdentityStore());
248
249  return new StoragePartitionImpl(partition_path,
250                                  quota_manager.get(),
251                                  appcache_service.get(),
252                                  filesystem_context.get(),
253                                  database_tracker.get(),
254                                  dom_storage_context.get(),
255                                  indexed_db_context.get(),
256                                  webrtc_identity_store.Pass());
257}
258
259base::FilePath StoragePartitionImpl::GetPath() {
260  return partition_path_;
261}
262
263net::URLRequestContextGetter* StoragePartitionImpl::GetURLRequestContext() {
264  return url_request_context_.get();
265}
266
267net::URLRequestContextGetter*
268StoragePartitionImpl::GetMediaURLRequestContext() {
269  return media_url_request_context_.get();
270}
271
272quota::QuotaManager* StoragePartitionImpl::GetQuotaManager() {
273  return quota_manager_.get();
274}
275
276ChromeAppCacheService* StoragePartitionImpl::GetAppCacheService() {
277  return appcache_service_.get();
278}
279
280fileapi::FileSystemContext* StoragePartitionImpl::GetFileSystemContext() {
281  return filesystem_context_.get();
282}
283
284webkit_database::DatabaseTracker* StoragePartitionImpl::GetDatabaseTracker() {
285  return database_tracker_.get();
286}
287
288DOMStorageContextImpl* StoragePartitionImpl::GetDOMStorageContext() {
289  return dom_storage_context_.get();
290}
291
292IndexedDBContextImpl* StoragePartitionImpl::GetIndexedDBContext() {
293  return indexed_db_context_.get();
294}
295
296void StoragePartitionImpl::AsyncClearDataForOrigin(
297    uint32 storage_mask,
298    const GURL& storage_origin,
299    net::URLRequestContextGetter* request_context_getter) {
300  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
301
302  BrowserThread::PostTask(
303      BrowserThread::IO, FROM_HERE,
304      base::Bind(&ClearOriginOnIOThread,
305                 storage_mask,
306                 storage_origin,
307                 make_scoped_refptr(request_context_getter),
308                 quota_manager_));
309
310  if (storage_mask & kLocalDomStorage)
311    GetDOMStorageContext()->DeleteLocalStorage(storage_origin);
312}
313
314void StoragePartitionImpl::AsyncClearData(uint32 storage_mask) {
315  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
316
317  // We ignore the media request context because it shares the same cookie store
318  // as the main request context.
319  BrowserThread::PostTask(
320      BrowserThread::IO, FROM_HERE,
321      base::Bind(&ClearAllDataOnIOThread,
322                 storage_mask,
323                 url_request_context_,
324                 quota_manager_));
325
326  if (storage_mask & kLocalDomStorage) {
327    dom_storage_context_->GetLocalStorageUsage(
328        base::Bind(&OnLocalStorageUsageInfo, dom_storage_context_));
329  }
330
331  if (storage_mask & kSessionDomStorage) {
332    dom_storage_context_->GetSessionStorageUsage(
333        base::Bind(&OnSessionStorageUsageInfo, dom_storage_context_));
334  }
335}
336
337void StoragePartitionImpl::AsyncClearDataBetween(uint32 storage_mask,
338      const base::Time& begin, const base::Time& end,
339      const base::Closure& callback) {
340  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
341  DCHECK(storage_mask == kShaderStorage);
342
343  if (storage_mask & kShaderStorage) {
344    BrowserThread::PostTask(
345        BrowserThread::IO, FROM_HERE,
346        base::Bind(&ClearShaderCacheOnIOThread, GetPath(), begin, end,
347            callback));
348  }
349}
350
351WebRTCIdentityStore* StoragePartitionImpl::GetWebRTCIdentityStore() {
352  return webrtc_identity_store_.get();
353}
354
355void StoragePartitionImpl::SetURLRequestContext(
356    net::URLRequestContextGetter* url_request_context) {
357  url_request_context_ = url_request_context;
358}
359
360void StoragePartitionImpl::SetMediaURLRequestContext(
361    net::URLRequestContextGetter* media_url_request_context) {
362  media_url_request_context_ = media_url_request_context;
363}
364
365}  // namespace content
366