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

Side by Side Diff: chrome/browser/browsing_data/browsing_data_remover_impl.cc

Issue 2827523003: Move BrowsingDataRemover to content/ (Closed)
Patch Set: Rebase over codereview.chromium.org/2815913005 Created 3 years, 8 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
(Empty)
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 "chrome/browser/browsing_data/browsing_data_remover_impl.h"
6
7 #include <map>
8 #include <set>
9 #include <string>
10 #include <utility>
11
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "base/callback.h"
15 #include "base/logging.h"
16 #include "base/memory/ptr_util.h"
17 #include "base/metrics/histogram_macros.h"
18 #include "base/metrics/user_metrics.h"
19 #include "chrome/browser/browsing_data/browsing_data_remover_delegate.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/common/pref_names.h"
22 #include "components/prefs/pref_service.h"
23 #include "content/public/browser/browser_context.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/browsing_data_filter_builder.h"
26 #include "content/public/browser/content_browser_client.h"
27 #include "content/public/browser/download_manager.h"
28 #include "content/public/browser/notification_service.h"
29 #include "content/public/browser/storage_partition.h"
30 #include "net/base/net_errors.h"
31 #include "net/cookies/cookie_store.h"
32 #include "net/http/http_network_session.h"
33 #include "net/http/http_transaction_factory.h"
34 #include "net/http/transport_security_state.h"
35 #include "net/ssl/channel_id_service.h"
36 #include "net/ssl/channel_id_store.h"
37 #include "net/url_request/url_request_context.h"
38 #include "net/url_request/url_request_context_getter.h"
39 #include "ppapi/features/features.h"
40 #include "storage/browser/quota/special_storage_policy.h"
41 #include "url/origin.h"
42
43 using base::UserMetricsAction;
44 using content::BrowserContext;
45 using content::BrowserThread;
46 using content::BrowsingDataFilterBuilder;
47 using content::DOMStorageContext;
48
49 namespace {
50
51 // Returns whether |origin| matches |origin_type_mask| given the special
52 // storage |policy|; and if |predicate| is not null, then also whether
53 // it matches |predicate|. If |origin_type_mask| contains embedder-specific
54 // datatypes, |embedder_matcher| must not be null; the decision for those
55 // datatypes will be delegated to it.
56 bool DoesOriginMatchMaskAndURLs(
57 int origin_type_mask,
58 const base::Callback<bool(const GURL&)>& predicate,
59 const BrowsingDataRemoverDelegate::EmbedderOriginTypeMatcher&
60 embedder_matcher,
61 const GURL& origin,
62 storage::SpecialStoragePolicy* policy) {
63 if (!predicate.is_null() && !predicate.Run(origin))
64 return false;
65
66 const std::vector<std::string>& schemes = url::GetWebStorageSchemes();
67 bool is_web_scheme =
68 (std::find(schemes.begin(), schemes.end(), origin.GetOrigin().scheme()) !=
69 schemes.end());
70
71 // If a websafe origin is unprotected, it matches iff UNPROTECTED_WEB.
72 if ((!policy || !policy->IsStorageProtected(origin.GetOrigin())) &&
73 is_web_scheme &&
74 (origin_type_mask & BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB)) {
75 return true;
76 }
77 origin_type_mask &= ~BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB;
78
79 // Hosted applications (protected and websafe origins) iff PROTECTED_WEB.
80 if (policy && policy->IsStorageProtected(origin.GetOrigin()) &&
81 is_web_scheme &&
82 (origin_type_mask & BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB)) {
83 return true;
84 }
85 origin_type_mask &= ~BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB;
86
87 DCHECK(embedder_matcher || !origin_type_mask)
88 << "The mask contains embedder-defined origin types, but there is no "
89 << "embedder delegate matcher to process them.";
90
91 if (!embedder_matcher.is_null())
92 return embedder_matcher.Run(origin_type_mask, origin, policy);
93
94 return false;
95 }
96
97 void ClearHttpAuthCacheOnIOThread(
98 scoped_refptr<net::URLRequestContextGetter> context_getter,
99 base::Time delete_begin) {
100 DCHECK_CURRENTLY_ON(BrowserThread::IO);
101
102 net::HttpNetworkSession* http_session = context_getter->GetURLRequestContext()
103 ->http_transaction_factory()
104 ->GetSession();
105 DCHECK(http_session);
106 http_session->http_auth_cache()->ClearEntriesAddedWithin(base::Time::Now() -
107 delete_begin);
108 http_session->CloseAllConnections();
109 }
110
111 void OnClearedChannelIDsOnIOThread(net::URLRequestContextGetter* rq_context,
112 const base::Closure& callback) {
113 DCHECK_CURRENTLY_ON(BrowserThread::IO);
114
115 // Need to close open SSL connections which may be using the channel ids we
116 // are deleting.
117 // TODO(mattm): http://crbug.com/166069 Make the server bound cert
118 // service/store have observers that can notify relevant things directly.
119 rq_context->GetURLRequestContext()
120 ->ssl_config_service()
121 ->NotifySSLConfigChange();
122 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
123 }
124
125 void ClearChannelIDsOnIOThread(
126 const base::Callback<bool(const std::string&)>& domain_predicate,
127 base::Time delete_begin,
128 base::Time delete_end,
129 scoped_refptr<net::URLRequestContextGetter> rq_context,
130 const base::Closure& callback) {
131 DCHECK_CURRENTLY_ON(BrowserThread::IO);
132 net::ChannelIDService* channel_id_service =
133 rq_context->GetURLRequestContext()->channel_id_service();
134 channel_id_service->GetChannelIDStore()->DeleteForDomainsCreatedBetween(
135 domain_predicate, delete_begin, delete_end,
136 base::Bind(&OnClearedChannelIDsOnIOThread,
137 base::RetainedRef(std::move(rq_context)), callback));
138 }
139
140 } // namespace
141
142 BrowsingDataRemoverImpl::SubTask::SubTask(const base::Closure& forward_callback)
143 : is_pending_(false),
144 forward_callback_(forward_callback),
145 weak_ptr_factory_(this) {
146 DCHECK(!forward_callback_.is_null());
147 }
148
149 BrowsingDataRemoverImpl::SubTask::~SubTask() {}
150
151 void BrowsingDataRemoverImpl::SubTask::Start() {
152 DCHECK_CURRENTLY_ON(BrowserThread::UI);
153 DCHECK(!is_pending_);
154 is_pending_ = true;
155 }
156
157 base::Closure BrowsingDataRemoverImpl::SubTask::GetCompletionCallback() {
158 return base::Bind(&BrowsingDataRemoverImpl::SubTask::CompletionCallback,
159 weak_ptr_factory_.GetWeakPtr());
160 }
161
162 void BrowsingDataRemoverImpl::SubTask::CompletionCallback() {
163 DCHECK_CURRENTLY_ON(BrowserThread::UI);
164 DCHECK(is_pending_);
165 is_pending_ = false;
166 forward_callback_.Run();
167 }
168
169 BrowsingDataRemoverImpl::BrowsingDataRemoverImpl(
170 content::BrowserContext* browser_context)
171 : browser_context_(browser_context),
172 remove_mask_(-1),
173 origin_type_mask_(-1),
174 is_removing_(false),
175 sub_task_forward_callback_(
176 base::Bind(&BrowsingDataRemoverImpl::NotifyIfDone,
177 base::Unretained(this))),
178 synchronous_clear_operations_(sub_task_forward_callback_),
179 clear_embedder_data_(sub_task_forward_callback_),
180 clear_cache_(sub_task_forward_callback_),
181 clear_channel_ids_(sub_task_forward_callback_),
182 clear_http_auth_cache_(sub_task_forward_callback_),
183 clear_storage_partition_data_(sub_task_forward_callback_),
184 storage_partition_for_testing_(nullptr),
185 weak_ptr_factory_(this) {
186 DCHECK(browser_context_);
187 }
188
189 BrowsingDataRemoverImpl::~BrowsingDataRemoverImpl() {
190 if (!task_queue_.empty()) {
191 VLOG(1) << "BrowsingDataRemoverImpl shuts down with " << task_queue_.size()
192 << " pending tasks";
193 }
194
195 // If we are still removing data, notify observers that their task has been
196 // (albeit unsucessfuly) processed, so they can unregister themselves.
197 // TODO(bauerb): If it becomes a problem that browsing data might not actually
198 // be fully cleared when an observer is notified, add a success flag.
199 while (!task_queue_.empty()) {
200 if (observer_list_.HasObserver(task_queue_.front().observer))
201 task_queue_.front().observer->OnBrowsingDataRemoverDone();
202 task_queue_.pop();
203 }
204 }
205
206 void BrowsingDataRemoverImpl::Shutdown() {
207 embedder_delegate_.reset();
208 }
209
210 void BrowsingDataRemoverImpl::SetRemoving(bool is_removing) {
211 DCHECK_NE(is_removing_, is_removing);
212 is_removing_ = is_removing;
213 }
214
215 void BrowsingDataRemoverImpl::SetEmbedderDelegate(
216 std::unique_ptr<BrowsingDataRemoverDelegate> embedder_delegate) {
217 embedder_delegate_ = std::move(embedder_delegate);
218 }
219
220 BrowsingDataRemoverDelegate*
221 BrowsingDataRemoverImpl::GetEmbedderDelegate() const {
222 return embedder_delegate_.get();
223 }
224
225 bool BrowsingDataRemoverImpl::DoesOriginMatchMask(
226 int origin_type_mask,
227 const GURL& origin,
228 storage::SpecialStoragePolicy* policy) const {
229 BrowsingDataRemoverDelegate::EmbedderOriginTypeMatcher embedder_matcher;
230 if (embedder_delegate_)
231 embedder_matcher = embedder_delegate_->GetOriginTypeMatcher();
232
233 return DoesOriginMatchMaskAndURLs(origin_type_mask,
234 base::Callback<bool(const GURL&)>(),
235 embedder_matcher, origin, policy);
236 }
237
238 void BrowsingDataRemoverImpl::Remove(const base::Time& delete_begin,
239 const base::Time& delete_end,
240 int remove_mask,
241 int origin_type_mask) {
242 RemoveInternal(delete_begin, delete_end, remove_mask, origin_type_mask,
243 std::unique_ptr<BrowsingDataFilterBuilder>(), nullptr);
244 }
245
246 void BrowsingDataRemoverImpl::RemoveAndReply(
247 const base::Time& delete_begin,
248 const base::Time& delete_end,
249 int remove_mask,
250 int origin_type_mask,
251 Observer* observer) {
252 DCHECK(observer);
253 RemoveInternal(delete_begin, delete_end, remove_mask, origin_type_mask,
254 std::unique_ptr<BrowsingDataFilterBuilder>(), observer);
255 }
256
257 void BrowsingDataRemoverImpl::RemoveWithFilter(
258 const base::Time& delete_begin,
259 const base::Time& delete_end,
260 int remove_mask,
261 int origin_type_mask,
262 std::unique_ptr<BrowsingDataFilterBuilder> filter_builder) {
263 DCHECK(filter_builder);
264 RemoveInternal(delete_begin, delete_end, remove_mask, origin_type_mask,
265 std::move(filter_builder), nullptr);
266 }
267
268 void BrowsingDataRemoverImpl::RemoveWithFilterAndReply(
269 const base::Time& delete_begin,
270 const base::Time& delete_end,
271 int remove_mask,
272 int origin_type_mask,
273 std::unique_ptr<BrowsingDataFilterBuilder> filter_builder,
274 Observer* observer) {
275 DCHECK(filter_builder);
276 DCHECK(observer);
277 RemoveInternal(delete_begin, delete_end, remove_mask, origin_type_mask,
278 std::move(filter_builder), observer);
279 }
280
281 void BrowsingDataRemoverImpl::RemoveInternal(
282 const base::Time& delete_begin,
283 const base::Time& delete_end,
284 int remove_mask,
285 int origin_type_mask,
286 std::unique_ptr<BrowsingDataFilterBuilder> filter_builder,
287 Observer* observer) {
288 DCHECK(!observer || observer_list_.HasObserver(observer))
289 << "Every observer must register itself (by calling AddObserver()) "
290 << "before observing a removal task.";
291
292 // Remove() and RemoveAndReply() pass a null pointer to indicate no filter.
293 // No filter is equivalent to one that |IsEmptyBlacklist()|.
294 if (!filter_builder) {
295 filter_builder = BrowsingDataFilterBuilder::Create(
296 BrowsingDataFilterBuilder::BLACKLIST);
297 DCHECK(filter_builder->IsEmptyBlacklist());
298 }
299
300 task_queue_.emplace(
301 delete_begin,
302 delete_end,
303 remove_mask,
304 origin_type_mask,
305 std::move(filter_builder),
306 observer);
307
308 // If this is the only scheduled task, execute it immediately. Otherwise,
309 // it will be automatically executed when all tasks scheduled before it
310 // finish.
311 if (task_queue_.size() == 1) {
312 SetRemoving(true);
313 RunNextTask();
314 }
315 }
316
317 void BrowsingDataRemoverImpl::RunNextTask() {
318 DCHECK(!task_queue_.empty());
319 const RemovalTask& removal_task = task_queue_.front();
320
321 RemoveImpl(removal_task.delete_begin,
322 removal_task.delete_end,
323 removal_task.remove_mask,
324 *removal_task.filter_builder,
325 removal_task.origin_type_mask);
326 }
327
328 void BrowsingDataRemoverImpl::RemoveImpl(
329 const base::Time& delete_begin,
330 const base::Time& delete_end,
331 int remove_mask,
332 const BrowsingDataFilterBuilder& filter_builder,
333 int origin_type_mask) {
334 // =============== README before adding more storage backends ===============
335 //
336 // If you're adding a data storage backend that is included among
337 // RemoveDataMask::FILTERABLE_DATATYPES, you must do one of the following:
338 // 1. Support one of the filters generated by |filter_builder|.
339 // 2. Add a comment explaining why is it acceptable in your case to delete all
340 // data without filtering URLs / origins / domains.
341 // 3. Do not support partial deletion, i.e. only delete your data if
342 // |filter_builder.IsEmptyBlacklist()|. Add a comment explaining why this
343 // is acceptable.
344 synchronous_clear_operations_.Start();
345
346 // crbug.com/140910: Many places were calling this with base::Time() as
347 // delete_end, even though they should've used base::Time::Max().
348 DCHECK_NE(base::Time(), delete_end);
349
350 delete_begin_ = delete_begin;
351 delete_end_ = delete_end;
352 remove_mask_ = remove_mask;
353 origin_type_mask_ = origin_type_mask;
354
355 // Record the combined deletion of cookies and cache.
356 CookieOrCacheDeletionChoice choice = NEITHER_COOKIES_NOR_CACHE;
357 if (remove_mask & DATA_TYPE_COOKIES &&
358 origin_type_mask_ & ORIGIN_TYPE_UNPROTECTED_WEB) {
359 choice =
360 remove_mask & DATA_TYPE_CACHE ? BOTH_COOKIES_AND_CACHE : ONLY_COOKIES;
361 } else if (remove_mask & DATA_TYPE_CACHE) {
362 choice = ONLY_CACHE;
363 }
364
365 UMA_HISTOGRAM_ENUMERATION(
366 "History.ClearBrowsingData.UserDeletedCookieOrCache",
367 choice, MAX_CHOICE_VALUE);
368
369 // Managed devices and supervised users can have restrictions on history
370 // deletion.
371 // TODO(crbug.com/668114): This should be provided via ContentBrowserClient
372 // once BrowsingDataRemoverImpl moves to content.
373 PrefService* prefs =
374 Profile::FromBrowserContext(browser_context_)->GetPrefs();
375 bool may_delete_history =
376 prefs->GetBoolean(prefs::kAllowDeletingBrowserHistory);
377
378 //////////////////////////////////////////////////////////////////////////////
379 // INITIALIZATION
380 base::Callback<bool(const GURL& url)> filter =
381 filter_builder.BuildGeneralFilter();
382
383 //////////////////////////////////////////////////////////////////////////////
384 // DATA_TYPE_DOWNLOADS
385 if ((remove_mask & DATA_TYPE_DOWNLOADS) && may_delete_history) {
386 base::RecordAction(UserMetricsAction("ClearBrowsingData_Downloads"));
387 content::DownloadManager* download_manager =
388 BrowserContext::GetDownloadManager(browser_context_);
389 download_manager->RemoveDownloadsByURLAndTime(filter,
390 delete_begin_, delete_end_);
391 }
392
393 //////////////////////////////////////////////////////////////////////////////
394 // DATA_TYPE_CHANNEL_IDS
395 // Channel IDs are not separated for protected and unprotected web
396 // origins. We check the origin_type_mask_ to prevent unintended deletion.
397 if (remove_mask & DATA_TYPE_CHANNEL_IDS &&
398 origin_type_mask_ & ORIGIN_TYPE_UNPROTECTED_WEB) {
399 base::RecordAction(UserMetricsAction("ClearBrowsingData_ChannelIDs"));
400 // Since we are running on the UI thread don't call GetURLRequestContext().
401 scoped_refptr<net::URLRequestContextGetter> rq_context =
402 content::BrowserContext::GetDefaultStoragePartition(browser_context_)->
403 GetURLRequestContext();
404 clear_channel_ids_.Start();
405 BrowserThread::PostTask(
406 BrowserThread::IO, FROM_HERE,
407 base::BindOnce(&ClearChannelIDsOnIOThread,
408 filter_builder.BuildChannelIDFilter(), delete_begin_,
409 delete_end_, std::move(rq_context),
410 clear_channel_ids_.GetCompletionCallback()));
411 }
412
413 //////////////////////////////////////////////////////////////////////////////
414 // STORAGE PARTITION DATA
415 uint32_t storage_partition_remove_mask = 0;
416
417 // We ignore the DATA_TYPE_COOKIES request if UNPROTECTED_WEB is not set,
418 // so that callers who request DATA_TYPE_SITE_DATA with another origin type
419 // don't accidentally remove the cookies that are associated with the
420 // UNPROTECTED_WEB origin. This is necessary because cookies are not separated
421 // between UNPROTECTED_WEB and other origin types.
422 if (remove_mask & DATA_TYPE_COOKIES &&
423 origin_type_mask_ & ORIGIN_TYPE_UNPROTECTED_WEB) {
424 storage_partition_remove_mask |=
425 content::StoragePartition::REMOVE_DATA_MASK_COOKIES;
426 }
427 if (remove_mask & DATA_TYPE_LOCAL_STORAGE) {
428 storage_partition_remove_mask |=
429 content::StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE;
430 }
431 if (remove_mask & DATA_TYPE_INDEXED_DB) {
432 storage_partition_remove_mask |=
433 content::StoragePartition::REMOVE_DATA_MASK_INDEXEDDB;
434 }
435 if (remove_mask & DATA_TYPE_WEB_SQL) {
436 storage_partition_remove_mask |=
437 content::StoragePartition::REMOVE_DATA_MASK_WEBSQL;
438 }
439 if (remove_mask & DATA_TYPE_APP_CACHE) {
440 storage_partition_remove_mask |=
441 content::StoragePartition::REMOVE_DATA_MASK_APPCACHE;
442 }
443 if (remove_mask & DATA_TYPE_SERVICE_WORKERS) {
444 storage_partition_remove_mask |=
445 content::StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS;
446 }
447 if (remove_mask & DATA_TYPE_CACHE_STORAGE) {
448 storage_partition_remove_mask |=
449 content::StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE;
450 }
451 if (remove_mask & DATA_TYPE_FILE_SYSTEMS) {
452 storage_partition_remove_mask |=
453 content::StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS;
454 }
455
456 // Content Decryption Modules used by Encrypted Media store licenses in a
457 // private filesystem. These are different than content licenses used by
458 // Flash (which are deleted father down in this method).
459 if (remove_mask & DATA_TYPE_MEDIA_LICENSES) {
460 storage_partition_remove_mask |=
461 content::StoragePartition::REMOVE_DATA_MASK_PLUGIN_PRIVATE_DATA;
462 }
463
464 content::StoragePartition* storage_partition;
465 if (storage_partition_for_testing_) {
466 storage_partition = storage_partition_for_testing_;
467 } else {
468 storage_partition =
469 BrowserContext::GetDefaultStoragePartition(browser_context_);
470 }
471
472 if (storage_partition_remove_mask) {
473 clear_storage_partition_data_.Start();
474
475 uint32_t quota_storage_remove_mask =
476 ~content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT;
477
478 if (delete_begin_ == base::Time() ||
479 ((origin_type_mask_ & ~ORIGIN_TYPE_UNPROTECTED_WEB) != 0)) {
480 // If we're deleting since the beginning of time, or we're removing
481 // protected origins, then remove persistent quota data.
482 quota_storage_remove_mask |=
483 content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT;
484 }
485
486 // If cookies are supposed to be conditionally deleted from the storage
487 // partition, create a cookie matcher function.
488 content::StoragePartition::CookieMatcherFunction cookie_matcher;
489 if (!filter_builder.IsEmptyBlacklist() &&
490 (storage_partition_remove_mask &
491 content::StoragePartition::REMOVE_DATA_MASK_COOKIES)) {
492 cookie_matcher = filter_builder.BuildCookieFilter();
493 }
494
495 BrowsingDataRemoverDelegate::EmbedderOriginTypeMatcher embedder_matcher;
496 if (embedder_delegate_)
497 embedder_matcher = embedder_delegate_->GetOriginTypeMatcher();
498
499 storage_partition->ClearData(
500 storage_partition_remove_mask, quota_storage_remove_mask,
501 base::Bind(&DoesOriginMatchMaskAndURLs, origin_type_mask_, filter,
502 embedder_matcher),
503 cookie_matcher, delete_begin_, delete_end_,
504 clear_storage_partition_data_.GetCompletionCallback());
505 }
506
507 //////////////////////////////////////////////////////////////////////////////
508 // CACHE
509 if (remove_mask & DATA_TYPE_CACHE) {
510 base::RecordAction(UserMetricsAction("ClearBrowsingData_Cache"));
511
512 // TODO(msramek): Clear the cache of all renderers.
513
514 clear_cache_.Start();
515 storage_partition->ClearHttpAndMediaCaches(
516 delete_begin, delete_end,
517 filter_builder.IsEmptyBlacklist() ? base::Callback<bool(const GURL&)>()
518 : filter,
519 clear_cache_.GetCompletionCallback());
520
521 // Tell the shader disk cache to clear.
522 base::RecordAction(UserMetricsAction("ClearBrowsingData_ShaderCache"));
523 storage_partition_remove_mask |=
524 content::StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE;
525 }
526
527 //////////////////////////////////////////////////////////////////////////////
528 // Auth cache.
529 if (remove_mask & DATA_TYPE_COOKIES) {
530 scoped_refptr<net::URLRequestContextGetter> request_context =
531 BrowserContext::GetDefaultStoragePartition(browser_context_)
532 ->GetURLRequestContext();
533 clear_http_auth_cache_.Start();
534 BrowserThread::PostTaskAndReply(
535 BrowserThread::IO, FROM_HERE,
536 base::BindOnce(&ClearHttpAuthCacheOnIOThread,
537 std::move(request_context), delete_begin_),
538 clear_http_auth_cache_.GetCompletionCallback());
539 }
540
541 //////////////////////////////////////////////////////////////////////////////
542 // Embedder data.
543 if (embedder_delegate_) {
544 clear_embedder_data_.Start();
545 embedder_delegate_->RemoveEmbedderData(
546 delete_begin_,
547 delete_end_,
548 remove_mask,
549 filter_builder,
550 origin_type_mask,
551 clear_embedder_data_.GetCompletionCallback());
552 }
553
554 // Notify in case all actions taken were synchronous.
555 synchronous_clear_operations_.GetCompletionCallback().Run();
556 }
557
558 void BrowsingDataRemoverImpl::AddObserver(Observer* observer) {
559 observer_list_.AddObserver(observer);
560 }
561
562 void BrowsingDataRemoverImpl::RemoveObserver(Observer* observer) {
563 observer_list_.RemoveObserver(observer);
564 }
565
566 void BrowsingDataRemoverImpl::SetWouldCompleteCallbackForTesting(
567 const base::Callback<void(const base::Closure& continue_to_completion)>&
568 callback) {
569 would_complete_callback_ = callback;
570 }
571
572 void BrowsingDataRemoverImpl::OverrideStoragePartitionForTesting(
573 content::StoragePartition* storage_partition) {
574 storage_partition_for_testing_ = storage_partition;
575 }
576
577 const base::Time& BrowsingDataRemoverImpl::GetLastUsedBeginTime() {
578 return delete_begin_;
579 }
580
581 const base::Time& BrowsingDataRemoverImpl::GetLastUsedEndTime() {
582 return delete_end_;
583 }
584
585 int BrowsingDataRemoverImpl::GetLastUsedRemovalMask() {
586 return remove_mask_;
587 }
588
589 int BrowsingDataRemoverImpl::GetLastUsedOriginTypeMask() {
590 return origin_type_mask_;
591 }
592
593 BrowsingDataRemoverImpl::RemovalTask::RemovalTask(
594 const base::Time& delete_begin,
595 const base::Time& delete_end,
596 int remove_mask,
597 int origin_type_mask,
598 std::unique_ptr<BrowsingDataFilterBuilder> filter_builder,
599 Observer* observer)
600 : delete_begin(delete_begin),
601 delete_end(delete_end),
602 remove_mask(remove_mask),
603 origin_type_mask(origin_type_mask),
604 filter_builder(std::move(filter_builder)),
605 observer(observer) {}
606
607 BrowsingDataRemoverImpl::RemovalTask::~RemovalTask() {}
608
609 bool BrowsingDataRemoverImpl::AllDone() {
610 return !synchronous_clear_operations_.is_pending() &&
611 !clear_embedder_data_.is_pending() &&
612 !clear_cache_.is_pending() &&
613 !clear_channel_ids_.is_pending() &&
614 !clear_http_auth_cache_.is_pending() &&
615 !clear_storage_partition_data_.is_pending();
616 }
617
618 void BrowsingDataRemoverImpl::Notify() {
619 // Some tests call |RemoveImpl| directly, without using the task scheduler.
620 // TODO(msramek): Improve those tests so we don't have to do this. Tests
621 // relying on |RemoveImpl| do so because they need to pass in
622 // BrowsingDataFilterBuilder while still keeping ownership of it. Making
623 // BrowsingDataFilterBuilder copyable would solve this.
624 if (!is_removing_) {
625 DCHECK(task_queue_.empty());
626 return;
627 }
628
629 // Inform the observer of the current task unless it has unregistered
630 // itself in the meantime.
631 DCHECK(!task_queue_.empty());
632
633 if (task_queue_.front().observer != nullptr &&
634 observer_list_.HasObserver(task_queue_.front().observer)) {
635 task_queue_.front().observer->OnBrowsingDataRemoverDone();
636 }
637
638 task_queue_.pop();
639
640 if (task_queue_.empty()) {
641 // All removal tasks have finished. Inform the observers that we're idle.
642 SetRemoving(false);
643 return;
644 }
645
646 // Yield to the UI thread before executing the next removal task.
647 // TODO(msramek): Consider also adding a backoff if too many tasks
648 // are scheduled.
649 BrowserThread::PostTask(
650 BrowserThread::UI, FROM_HERE,
651 base::BindOnce(&BrowsingDataRemoverImpl::RunNextTask, GetWeakPtr()));
652 }
653
654 void BrowsingDataRemoverImpl::NotifyIfDone() {
655 // TODO(brettw) http://crbug.com/305259: This should also observe session
656 // clearing (what about other things such as passwords, etc.?) and wait for
657 // them to complete before continuing.
658
659 if (!AllDone())
660 return;
661
662 if (!would_complete_callback_.is_null()) {
663 would_complete_callback_.Run(
664 base::Bind(&BrowsingDataRemoverImpl::Notify, GetWeakPtr()));
665 return;
666 }
667
668 Notify();
669 }
670
671 base::WeakPtr<BrowsingDataRemoverImpl> BrowsingDataRemoverImpl::GetWeakPtr() {
672 DCHECK_CURRENTLY_ON(BrowserThread::UI);
673 base::WeakPtr<BrowsingDataRemoverImpl> weak_ptr =
674 weak_ptr_factory_.GetWeakPtr();
675
676 // Immediately bind the weak pointer to the UI thread. This makes it easier
677 // to discover potential misuse on the IO thread.
678 weak_ptr.get();
679
680 return weak_ptr;
681 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698