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

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

Issue 2175703002: Implement a task scheduler for BrowsingDataRemover (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@bdr-race-condition
Patch Set: Created 4 years, 4 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 "chrome/browser/browsing_data/browsing_data_remover.h" 5 #include "chrome/browser/browsing_data/browsing_data_remover.h"
6 6
7 #include <map> 7 #include <map>
8 #include <set> 8 #include <set>
9 #include <string> 9 #include <string>
10 10
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 domain_predicate, delete_begin, delete_end, 245 domain_predicate, delete_begin, delete_end,
246 base::Bind(&OnClearedChannelIDsOnIOThread, 246 base::Bind(&OnClearedChannelIDsOnIOThread,
247 base::RetainedRef(std::move(rq_context)), callback)); 247 base::RetainedRef(std::move(rq_context)), callback));
248 } 248 }
249 249
250 } // namespace 250 } // namespace
251 251
252 BrowsingDataRemover::CompletionInhibitor* 252 BrowsingDataRemover::CompletionInhibitor*
253 BrowsingDataRemover::completion_inhibitor_ = nullptr; 253 BrowsingDataRemover::completion_inhibitor_ = nullptr;
254 254
255 BrowsingDataRemover::RemovalTask::RemovalTask(
256 const TimeRange& time_range,
257 int remove_mask,
258 int origin_type_mask,
259 std::unique_ptr<BrowsingDataFilterBuilder> filter_builder,
260 Observer* observer)
261 : time_range(time_range),
262 remove_mask(remove_mask),
263 origin_type_mask(origin_type_mask),
264 filter_builder(std::move(filter_builder)),
265 observer(observer) {}
266
267 BrowsingDataRemover::RemovalTask::~RemovalTask() {}
268
269 BrowsingDataRemover::RemovalTask::RemovalTask(
270 RemovalTask&& removalTask) = default;
271 BrowsingDataRemover::RemovalTask& BrowsingDataRemover::RemovalTask::operator=(
272 RemovalTask&& removalTask) = default;
273
255 bool BrowsingDataRemover::TimeRange::operator==( 274 bool BrowsingDataRemover::TimeRange::operator==(
256 const BrowsingDataRemover::TimeRange& other) const { 275 const BrowsingDataRemover::TimeRange& other) const {
257 return begin == other.begin && end == other.end; 276 return begin == other.begin && end == other.end;
258 } 277 }
259 278
260 // static 279 // static
261 BrowsingDataRemover::TimeRange BrowsingDataRemover::Unbounded() { 280 BrowsingDataRemover::TimeRange BrowsingDataRemover::Unbounded() {
262 return TimeRange(base::Time(), base::Time::Max()); 281 return TimeRange(base::Time(), base::Time::Max());
263 } 282 }
264 283
(...skipping 25 matching lines...) Expand all
290 : profile_(Profile::FromBrowserContext(browser_context)), 309 : profile_(Profile::FromBrowserContext(browser_context)),
291 is_removing_(false), 310 is_removing_(false),
292 #if BUILDFLAG(ANDROID_JAVA_UI) 311 #if BUILDFLAG(ANDROID_JAVA_UI)
293 webapp_registry_(new WebappRegistry()), 312 webapp_registry_(new WebappRegistry()),
294 #endif 313 #endif
295 weak_ptr_factory_(this) { 314 weak_ptr_factory_(this) {
296 DCHECK(browser_context); 315 DCHECK(browser_context);
297 } 316 }
298 317
299 BrowsingDataRemover::~BrowsingDataRemover() { 318 BrowsingDataRemover::~BrowsingDataRemover() {
300 // If we are still removing data, notify observers so they can remove 319 if (!task_queue_.empty()) {
301 // themselves from the observer list. 320 VLOG(1) << "BrowsingDataRemover shuts down with " << task_queue_.size()
321 << " pending tasks";
322 }
323
324 // If we are still removing data, notify observers that their task has been
325 // (albeit unsucessfuly) processed, so they can unregister themselves.
302 // TODO(bauerb): If it becomes a problem that browsing data might not actually 326 // TODO(bauerb): If it becomes a problem that browsing data might not actually
303 // be fully cleared when an observer is notified, add a success flag. 327 // be fully cleared when an observer is notified, add a success flag.
304 if (is_removing_) 328 while (!task_queue_.empty()) {
305 Notify(); 329 if (observer_list_.HasObserver(task_queue_.front().observer))
330 task_queue_.front().observer->OnBrowsingDataRemoverDone();
331 task_queue_.pop();
332 }
306 } 333 }
307 334
308 void BrowsingDataRemover::Shutdown() { 335 void BrowsingDataRemover::Shutdown() {
309 history_task_tracker_.TryCancelAll(); 336 history_task_tracker_.TryCancelAll();
310 template_url_sub_.reset(); 337 template_url_sub_.reset();
311 } 338 }
312 339
313 void BrowsingDataRemover::SetRemoving(bool is_removing) { 340 void BrowsingDataRemover::SetRemoving(bool is_removing) {
314 DCHECK_NE(is_removing_, is_removing); 341 DCHECK_NE(is_removing_, is_removing);
315 is_removing_ = is_removing; 342 is_removing_ = is_removing;
316 FOR_EACH_OBSERVER(Observer, observer_list_, 343 FOR_EACH_OBSERVER(Observer, observer_list_,
317 OnBrowsingDataRemoving(is_removing)); 344 OnBrowsingDataRemoving(is_removing));
318 } 345 }
319 346
320 void BrowsingDataRemover::Remove(const TimeRange& time_range, 347 void BrowsingDataRemover::Remove(const TimeRange& time_range,
321 int remove_mask, 348 int remove_mask,
322 int origin_type_mask) { 349 int origin_type_mask) {
350 RemoveAndReply(time_range, remove_mask, origin_type_mask, nullptr);
351 }
352
353 void BrowsingDataRemover::RemoveAndReply(
354 const TimeRange& time_range,
355 int remove_mask,
356 int origin_type_mask,
357 Observer* observer) {
323 // Any instance of BrowsingDataFilterBuilder that |IsEmptyBlacklist()| 358 // Any instance of BrowsingDataFilterBuilder that |IsEmptyBlacklist()|
324 // is OK to pass here. 359 // is OK to pass here.
325 RegistrableDomainFilterBuilder builder( 360 std::unique_ptr<RegistrableDomainFilterBuilder> filter_builder =
326 RegistrableDomainFilterBuilder::BLACKLIST); 361 base::WrapUnique(new RegistrableDomainFilterBuilder(
327 DCHECK(builder.IsEmptyBlacklist()); 362 RegistrableDomainFilterBuilder::BLACKLIST));
328 RemoveImpl(time_range, remove_mask, builder, origin_type_mask); 363 DCHECK(filter_builder->IsEmptyBlacklist());
364 RemoveWithFilterAndReply(time_range, remove_mask, origin_type_mask,
365 std::move(filter_builder), observer);
329 } 366 }
330 367
331 void BrowsingDataRemover::RemoveWithFilter( 368 void BrowsingDataRemover::RemoveWithFilter(
332 const TimeRange& time_range, 369 const TimeRange& time_range,
333 int remove_mask, 370 int remove_mask,
334 int origin_type_mask, 371 int origin_type_mask,
335 const BrowsingDataFilterBuilder& filter_builder) { 372 std::unique_ptr<BrowsingDataFilterBuilder> filter_builder) {
336 RemoveImpl(time_range, remove_mask, filter_builder, origin_type_mask); 373 RemoveWithFilterAndReply(time_range, remove_mask, origin_type_mask,
374 std::move(filter_builder), nullptr);
375 }
376
377 void BrowsingDataRemover::RemoveWithFilterAndReply(
378 const TimeRange& time_range,
379 int remove_mask,
380 int origin_type_mask,
381 std::unique_ptr<BrowsingDataFilterBuilder> filter_builder,
382 Observer* observer) {
383 DCHECK(!observer || observer_list_.HasObserver(observer))
Bernhard Bauer 2016/07/26 14:51:38 If you allow the |observer| to be null, do you eve
msramek 2016/07/28 09:57:42 All methods can be reduced to the last one, as dem
Bernhard Bauer 2016/08/03 16:42:46 Hm, could we make one method that takes no observe
msramek 2016/08/03 21:16:44 Yep, that makes more sense actually. Done.
384 << "Every observer must register itself (by calling AddObserver()) "
385 << "before observing a removal task.";
386
387 task_queue_.push(RemovalTask(
Bernhard Bauer 2016/07/26 14:51:38 You could use emplace() for that.
msramek 2016/07/28 09:57:42 Done. Nice :)
388 time_range,
389 remove_mask,
390 origin_type_mask,
391 std::move(filter_builder),
392 observer));
393
394 // If this is the only scheduled task, execute it immediately. Otherwise,
395 // it will be automatically executed when all tasks scheduled before it
396 // finish.
397 if (task_queue_.size() == 1) {
398 SetRemoving(true);
399 RunNextTask();
400 }
401 }
402
403 void BrowsingDataRemover::RunNextTask() {
404 DCHECK(!task_queue_.empty());
405 const RemovalTask& removal_task = task_queue_.front();
406
407 RemoveImpl(removal_task.time_range,
408 removal_task.remove_mask,
409 *removal_task.filter_builder,
410 removal_task.origin_type_mask);
337 } 411 }
338 412
339 void BrowsingDataRemover::RemoveImpl( 413 void BrowsingDataRemover::RemoveImpl(
340 const TimeRange& time_range, 414 const TimeRange& time_range,
341 int remove_mask, 415 int remove_mask,
342 const BrowsingDataFilterBuilder& filter_builder, 416 const BrowsingDataFilterBuilder& filter_builder,
343 int origin_type_mask) { 417 int origin_type_mask) {
344 DCHECK_CURRENTLY_ON(BrowserThread::UI); 418 DCHECK_CURRENTLY_ON(BrowserThread::UI);
345 waiting_for_synchronous_clear_operations_ = true; 419 waiting_for_synchronous_clear_operations_ = true;
346 420
347 // crbug.com/140910: Many places were calling this with base::Time() as 421 // crbug.com/140910: Many places were calling this with base::Time() as
348 // delete_end, even though they should've used base::Time::Max(). 422 // delete_end, even though they should've used base::Time::Max().
349 DCHECK_NE(base::Time(), time_range.end); 423 DCHECK_NE(base::Time(), time_range.end);
350 424
351 SetRemoving(true);
352 delete_begin_ = time_range.begin; 425 delete_begin_ = time_range.begin;
353 delete_end_ = time_range.end; 426 delete_end_ = time_range.end;
354 remove_mask_ = remove_mask; 427 remove_mask_ = remove_mask;
355 origin_type_mask_ = origin_type_mask; 428 origin_type_mask_ = origin_type_mask;
356 429
357 base::Callback<bool(const GURL& url)> filter = 430 base::Callback<bool(const GURL& url)> filter =
358 filter_builder.BuildGeneralFilter(); 431 filter_builder.BuildGeneralFilter();
359 base::Callback<bool(const ContentSettingsPattern& url)> same_pattern_filter = 432 base::Callback<bool(const ContentSettingsPattern& url)> same_pattern_filter =
360 filter_builder.BuildWebsiteSettingsPatternMatchesFilter(); 433 filter_builder.BuildWebsiteSettingsPatternMatchesFilter();
361 434
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after
1099 // else notifies observers and deletes this BrowsingDataRemover. 1172 // else notifies observers and deletes this BrowsingDataRemover.
1100 TemplateURLService* model = 1173 TemplateURLService* model =
1101 TemplateURLServiceFactory::GetForProfile(profile_); 1174 TemplateURLServiceFactory::GetForProfile(profile_);
1102 model->RemoveAutoGeneratedBetween(delete_begin_, delete_end_); 1175 model->RemoveAutoGeneratedBetween(delete_begin_, delete_end_);
1103 waiting_for_clear_keyword_data_ = false; 1176 waiting_for_clear_keyword_data_ = false;
1104 template_url_sub_.reset(); 1177 template_url_sub_.reset();
1105 NotifyIfDone(); 1178 NotifyIfDone();
1106 } 1179 }
1107 1180
1108 void BrowsingDataRemover::Notify() { 1181 void BrowsingDataRemover::Notify() {
1109 SetRemoving(false); 1182 // Some tests call |RemoveImpl| directly, without using the task scheduler.
1110 FOR_EACH_OBSERVER(Observer, observer_list_, OnBrowsingDataRemoverDone()); 1183 // TODO(msramek): Improve those tests so we don't have to do this. Tests
1184 // relying on |RemoveImpl| do so because they need to pass in
1185 // BrowsingDataFilterBuilder while still keeping ownership of it. Making
1186 // BrowsingDataFilterBuilder copyable would solve this.
1187 if (!is_removing_) {
1188 DCHECK(task_queue_.empty());
1189 return;
1190 }
1191
1192 // Inform the observer of the current task unless it has unregistered
1193 // itself in the meantime.
1194 DCHECK(!task_queue_.empty());
1195
1196 if (task_queue_.front().observer != nullptr &&
1197 observer_list_.HasObserver(task_queue_.front().observer)) {
1198 task_queue_.front().observer->OnBrowsingDataRemoverDone();
1199 }
1200
1201 task_queue_.pop();
1202
1203 if (task_queue_.empty()) {
1204 // All removal tasks have finished. Inform the observers that we're idle.
1205 SetRemoving(false);
1206 return;
1207 }
1208
1209 // Yield to the UI thread before executing the next removal task.
1210 // TODO(msramek): Consider also adding a backoff if too many tasks
1211 // are scheduled.
1212 BrowserThread::PostTask(
1213 BrowserThread::UI, FROM_HERE,
1214 base::Bind(&BrowsingDataRemover::RunNextTask,
1215 weak_ptr_factory_.GetWeakPtr()));
1111 } 1216 }
1112 1217
1113 void BrowsingDataRemover::NotifyIfDone() { 1218 void BrowsingDataRemover::NotifyIfDone() {
1114 // TODO(brettw) http://crbug.com/305259: This should also observe session 1219 // TODO(brettw) http://crbug.com/305259: This should also observe session
1115 // clearing (what about other things such as passwords, etc.?) and wait for 1220 // clearing (what about other things such as passwords, etc.?) and wait for
1116 // them to complete before continuing. 1221 // them to complete before continuing.
1117 1222
1118 if (!AllDone()) 1223 if (!AllDone())
1119 return; 1224 return;
1120 1225
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
1289 waiting_for_clear_offline_page_data_ = false; 1394 waiting_for_clear_offline_page_data_ = false;
1290 NotifyIfDone(); 1395 NotifyIfDone();
1291 } 1396 }
1292 #endif 1397 #endif
1293 1398
1294 void BrowsingDataRemover::OnClearedDomainReliabilityMonitor() { 1399 void BrowsingDataRemover::OnClearedDomainReliabilityMonitor() {
1295 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1400 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1296 waiting_for_clear_domain_reliability_monitor_ = false; 1401 waiting_for_clear_domain_reliability_monitor_ = false;
1297 NotifyIfDone(); 1402 NotifyIfDone();
1298 } 1403 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698