| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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) |
| OLD | NEW |