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

Side by Side Diff: chrome/browser/browser_process_impl.cc

Issue 2788813002: Try to flush DOMStorage too when ending the browsing session.
Patch Set: fixes 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
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/browser_process_impl.h" 5 #include "chrome/browser/browser_process_impl.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <iterator>
10 #include <map> 11 #include <map>
11 #include <utility> 12 #include <utility>
12 #include <vector> 13 #include <vector>
13 14
14 #include "base/atomic_ref_count.h" 15 #include "base/atomic_ref_count.h"
15 #include "base/bind.h" 16 #include "base/bind.h"
16 #include "base/bind_helpers.h" 17 #include "base/bind_helpers.h"
17 #include "base/command_line.h" 18 #include "base/command_line.h"
18 #include "base/debug/crash_logging.h" 19 #include "base/debug/crash_logging.h"
19 #include "base/debug/leak_annotations.h" 20 #include "base/debug/leak_annotations.h"
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 // 392 //
392 // This is important also because in various places, the 393 // This is important also because in various places, the
393 // IOThread object being NULL is considered synonymous with the 394 // IOThread object being NULL is considered synonymous with the
394 // IO thread having stopped. 395 // IO thread having stopped.
395 io_thread_.reset(); 396 io_thread_.reset();
396 } 397 }
397 #endif // !defined(OS_ANDROID) 398 #endif // !defined(OS_ANDROID)
398 399
399 namespace { 400 namespace {
400 401
402 using TaskRunnerVector = std::vector<scoped_refptr<base::SequencedTaskRunner>>;
403
401 // Used at the end of session to block the UI thread for completion of sentinel 404 // Used at the end of session to block the UI thread for completion of sentinel
402 // tasks on the set of threads used to persist profile data and local state. 405 // tasks on the set of threads used to persist profile data and local state.
403 // This is done to ensure that the data has been persisted to disk before 406 // This is done to ensure that the data has been persisted to disk before
404 // continuing. 407 // continuing.
405 class RundownTaskCounter : 408 class RundownTaskCounter :
406 public base::RefCountedThreadSafe<RundownTaskCounter> { 409 public base::RefCountedThreadSafe<RundownTaskCounter> {
407 public: 410 public:
408 RundownTaskCounter(); 411 RundownTaskCounter();
409 412
410 // Posts a rundown task to |task_runner|, can be invoked an arbitrary number 413 // Posts a rundown task to |task_runner|, can be invoked an arbitrary number
411 // of times before calling TimedWait. 414 // of times before calling TimedWait.
412 void Post(base::SequencedTaskRunner* task_runner); 415 void Post(base::SequencedTaskRunner* task_runner);
413 416
417 // Posts a rundown task to each runner in |runners|, where the rundown task
418 // for runner[n+1] is posted during rundown task execution for runner[n].
419 void PostSerially(TaskRunnerVector runners);
420
414 // Waits until the count is zero or |end_time| is reached. 421 // Waits until the count is zero or |end_time| is reached.
415 // This can only be called once per instance. Returns true if a count of zero 422 // This can only be called once per instance. Returns true if a count of zero
416 // is reached or false if the |end_time| is reached. It is valid to pass an 423 // is reached or false if the |end_time| is reached. It is valid to pass an
417 // |end_time| in the past. 424 // |end_time| in the past.
418 bool TimedWaitUntil(const base::TimeTicks& end_time); 425 bool TimedWaitUntil(const base::TimeTicks& end_time);
419 426
420 private: 427 private:
421 friend class base::RefCountedThreadSafe<RundownTaskCounter>; 428 friend class base::RefCountedThreadSafe<RundownTaskCounter>;
422 ~RundownTaskCounter() {} 429 ~RundownTaskCounter() {}
423 430
424 // Decrements the counter and releases the waitable event on transition to 431 // Decrements the counter and releases the waitable event on transition to
425 // zero. 432 // zero.
426 void Decrement(); 433 void Decrement();
427 434
435 void RundownSerially(TaskRunnerVector::const_iterator it,
436 TaskRunnerVector runner);
437
428 // The count starts at one to defer the possibility of one->zero transitions 438 // The count starts at one to defer the possibility of one->zero transitions
429 // until TimedWait is called. 439 // until TimedWait is called.
430 base::AtomicRefCount count_; 440 base::AtomicRefCount count_;
431 base::WaitableEvent waitable_event_; 441 base::WaitableEvent waitable_event_;
432 442
433 DISALLOW_COPY_AND_ASSIGN(RundownTaskCounter); 443 DISALLOW_COPY_AND_ASSIGN(RundownTaskCounter);
434 }; 444 };
435 445
436 RundownTaskCounter::RundownTaskCounter() 446 RundownTaskCounter::RundownTaskCounter()
437 : count_(1), 447 : count_(1),
438 waitable_event_(base::WaitableEvent::ResetPolicy::MANUAL, 448 waitable_event_(base::WaitableEvent::ResetPolicy::MANUAL,
439 base::WaitableEvent::InitialState::NOT_SIGNALED) {} 449 base::WaitableEvent::InitialState::NOT_SIGNALED) {}
440 450
441 void RundownTaskCounter::Post(base::SequencedTaskRunner* task_runner) { 451 void RundownTaskCounter::Post(base::SequencedTaskRunner* task_runner) {
442 // As the count starts off at one, it should never get to zero unless 452 // As the count starts off at one, it should never get to zero unless
443 // TimedWait has been called. 453 // TimedWait has been called.
444 DCHECK(!base::AtomicRefCountIsZero(&count_)); 454 DCHECK(!base::AtomicRefCountIsZero(&count_));
445 455
446 base::AtomicRefCountInc(&count_); 456 base::AtomicRefCountInc(&count_);
447 457
448 // The task must be non-nestable to guarantee that it runs after all tasks 458 // The task must be non-nestable to guarantee that it runs after all tasks
449 // currently scheduled on |task_runner| have completed. 459 // currently scheduled on |task_runner| have completed.
450 task_runner->PostNonNestableTask(FROM_HERE, 460 task_runner->PostNonNestableTask(FROM_HERE,
451 base::Bind(&RundownTaskCounter::Decrement, this)); 461 base::Bind(&RundownTaskCounter::Decrement, this));
452 } 462 }
453 463
464 void RundownTaskCounter::PostSerially(TaskRunnerVector runners) {
465 if (runners.empty())
466 return;
467 base::AtomicRefCountInc(&count_);
468 TaskRunnerVector::const_iterator it = runners.begin();
469 (*it)->PostNonNestableTask(
470 FROM_HERE, base::Bind(&RundownTaskCounter::RundownSerially, this, it + 1,
471 base::Passed(&runners)));
472 }
473
454 void RundownTaskCounter::Decrement() { 474 void RundownTaskCounter::Decrement() {
455 if (!base::AtomicRefCountDec(&count_)) 475 if (!base::AtomicRefCountDec(&count_))
456 waitable_event_.Signal(); 476 waitable_event_.Signal();
457 } 477 }
458 478
459 bool RundownTaskCounter::TimedWaitUntil(const base::TimeTicks& end_time) { 479 bool RundownTaskCounter::TimedWaitUntil(const base::TimeTicks& end_time) {
460 // Decrement the excess count from the constructor. 480 // Decrement the excess count from the constructor.
461 Decrement(); 481 Decrement();
462 482
463 return waitable_event_.TimedWaitUntil(end_time); 483 return waitable_event_.TimedWaitUntil(end_time);
464 } 484 }
465 485
486 void RundownTaskCounter::RundownSerially(TaskRunnerVector::const_iterator it,
487 TaskRunnerVector runners) {
488 if (it == runners.end()) {
489 Decrement();
490 return;
491 }
492 (*it)->PostNonNestableTask(
493 FROM_HERE, base::Bind(&RundownTaskCounter::RundownSerially, this, it + 1,
494 base::Passed(&runners)));
495 }
496
466 } // namespace 497 } // namespace
467 498
468 void BrowserProcessImpl::EndSession() { 499 void BrowserProcessImpl::EndSession() {
469 // Mark all the profiles as clean. 500 // Mark all the profiles as clean.
470 ProfileManager* pm = profile_manager(); 501 ProfileManager* pm = profile_manager();
471 std::vector<Profile*> profiles(pm->GetLoadedProfiles()); 502 std::vector<Profile*> profiles(pm->GetLoadedProfiles());
472 scoped_refptr<RundownTaskCounter> rundown_counter(new RundownTaskCounter()); 503 scoped_refptr<RundownTaskCounter> rundown_counter(new RundownTaskCounter());
473 const bool pref_service_enabled = 504 const bool pref_service_enabled =
474 base::FeatureList::IsEnabled(features::kPrefService); 505 base::FeatureList::IsEnabled(features::kPrefService);
475 std::vector<scoped_refptr<base::SequencedTaskRunner>> profile_writer_runners; 506 std::vector<scoped_refptr<base::SequencedTaskRunner>> profile_writer_runners;
476 for (size_t i = 0; i < profiles.size(); ++i) { 507 for (Profile* profile : profiles) {
477 Profile* profile = profiles[i];
478 profile->SetExitType(Profile::EXIT_SESSION_ENDED); 508 profile->SetExitType(Profile::EXIT_SESSION_ENDED);
479 if (profile->GetPrefs()) { 509 if (profile->GetPrefs()) {
480 profile->GetPrefs()->CommitPendingWrite(); 510 profile->GetPrefs()->CommitPendingWrite();
481 if (pref_service_enabled) { 511 if (pref_service_enabled) {
482 rundown_counter->Post(content::BrowserThread::GetTaskRunnerForThread( 512 rundown_counter->Post(content::BrowserThread::GetTaskRunnerForThread(
483 content::BrowserThread::IO) 513 content::BrowserThread::IO)
484 .get()); 514 .get());
485 profile_writer_runners.push_back(profile->GetIOTaskRunner()); 515 profile_writer_runners.push_back(profile->GetIOTaskRunner());
486 } else { 516 } else {
487 rundown_counter->Post(profile->GetIOTaskRunner().get()); 517 rundown_counter->Post(profile->GetIOTaskRunner().get());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 // On Windows, we previously posted a message to FILE and then ran a nested 550 // On Windows, we previously posted a message to FILE and then ran a nested
521 // message loop, waiting for that message to be processed until quitting. 551 // message loop, waiting for that message to be processed until quitting.
522 // However, doing so means that other messages will also be processed. In 552 // However, doing so means that other messages will also be processed. In
523 // particular, if the GPU process host notices that the GPU has been killed 553 // particular, if the GPU process host notices that the GPU has been killed
524 // during shutdown, it races exiting the nested loop with the process host 554 // during shutdown, it races exiting the nested loop with the process host
525 // blocking the message loop attempting to re-establish a connection to the 555 // blocking the message loop attempting to re-establish a connection to the
526 // GPU process synchronously. Because the system may not be allowing 556 // GPU process synchronously. Because the system may not be allowing
527 // processes to launch, this can result in a hang. See 557 // processes to launch, this can result in a hang. See
528 // http://crbug.com/318527. 558 // http://crbug.com/318527.
529 const base::TimeTicks end_time = base::TimeTicks::Now() + kEndSessionTimeout; 559 const base::TimeTicks end_time = base::TimeTicks::Now() + kEndSessionTimeout;
530 const bool timed_out = !rundown_counter->TimedWaitUntil(end_time); 560 if (!rundown_counter->TimedWaitUntil(end_time))
531 if (timed_out || !pref_service_enabled)
532 return; 561 return;
533 562
534 scoped_refptr<RundownTaskCounter> profile_write_rundown_counter( 563 if (pref_service_enabled) {
564 scoped_refptr<RundownTaskCounter> profile_write_rundown_counter(
565 new RundownTaskCounter());
566 for (auto& profile_writer_runner : profile_writer_runners)
567 profile_write_rundown_counter->Post(profile_writer_runner.get());
568 if (!profile_write_rundown_counter->TimedWaitUntil(end_time))
569 return;
570 }
571
572 // Time permitting, give other storage systems a chance to flush caches.
573 auto flush_function = [](scoped_refptr<RundownTaskCounter> rundown_counter,
574 content::StoragePartition* partition) {
575 rundown_counter->PostSerially(partition->Flush());
576 };
577 scoped_refptr<RundownTaskCounter> flush_storage_rundown_counter(
535 new RundownTaskCounter()); 578 new RundownTaskCounter());
536 for (auto& profile_writer_runner : profile_writer_runners) 579 for (Profile* profile : profiles) {
537 profile_write_rundown_counter->Post(profile_writer_runner.get()); 580 content::BrowserContext::ForEachStoragePartition(
538 profile_write_rundown_counter->TimedWaitUntil(end_time); 581 profile,
582 base::BindRepeating(flush_function, flush_storage_rundown_counter));
583 }
584 flush_storage_rundown_counter->TimedWaitUntil(end_time);
539 #else 585 #else
540 NOTIMPLEMENTED(); 586 NOTIMPLEMENTED();
541 #endif 587 #endif
542 } 588 }
543 589
544 metrics_services_manager::MetricsServicesManager* 590 metrics_services_manager::MetricsServicesManager*
545 BrowserProcessImpl::GetMetricsServicesManager() { 591 BrowserProcessImpl::GetMetricsServicesManager() {
546 DCHECK(CalledOnValidThread()); 592 DCHECK(CalledOnValidThread());
547 if (!metrics_services_manager_) { 593 if (!metrics_services_manager_) {
548 metrics_services_manager_.reset( 594 metrics_services_manager_.reset(
(...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after
1435 } 1481 }
1436 1482
1437 void BrowserProcessImpl::OnAutoupdateTimer() { 1483 void BrowserProcessImpl::OnAutoupdateTimer() {
1438 if (CanAutorestartForUpdate()) { 1484 if (CanAutorestartForUpdate()) {
1439 DLOG(WARNING) << "Detected update. Restarting browser."; 1485 DLOG(WARNING) << "Detected update. Restarting browser.";
1440 RestartBackgroundInstance(); 1486 RestartBackgroundInstance();
1441 } 1487 }
1442 } 1488 }
1443 1489
1444 #endif // (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) 1490 #endif // (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698