| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "content/browser/memory/memory_coordinator_impl.h" | 5 #include "content/browser/memory/memory_coordinator_impl.h" |
| 6 | 6 |
| 7 #include "base/memory/memory_coordinator_client_registry.h" | 7 #include "base/memory/memory_coordinator_client_registry.h" |
| 8 #include "base/memory/memory_coordinator_proxy.h" | 8 #include "base/memory/memory_coordinator_proxy.h" |
| 9 #include "base/memory/memory_pressure_monitor.h" | 9 #include "base/memory/memory_pressure_monitor.h" |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 | 59 |
| 60 // A mock MemoryCoordinatorClient, for testing interaction between MC and | 60 // A mock MemoryCoordinatorClient, for testing interaction between MC and |
| 61 // clients. | 61 // clients. |
| 62 class MockMemoryCoordinatorClient : public base::MemoryCoordinatorClient { | 62 class MockMemoryCoordinatorClient : public base::MemoryCoordinatorClient { |
| 63 public: | 63 public: |
| 64 void OnMemoryStateChange(base::MemoryState state) override { | 64 void OnMemoryStateChange(base::MemoryState state) override { |
| 65 did_state_changed_ = true; | 65 did_state_changed_ = true; |
| 66 state_ = state; | 66 state_ = state; |
| 67 } | 67 } |
| 68 | 68 |
| 69 void OnPurgeMemory() override { ++purge_memory_calls_; } |
| 70 |
| 69 bool did_state_changed() const { return did_state_changed_; } | 71 bool did_state_changed() const { return did_state_changed_; } |
| 70 base::MemoryState state() const { return state_; } | 72 base::MemoryState state() const { return state_; } |
| 73 int purge_memory_calls() const { return purge_memory_calls_; } |
| 71 | 74 |
| 72 private: | 75 private: |
| 73 bool did_state_changed_ = false; | 76 bool did_state_changed_ = false; |
| 74 base::MemoryState state_ = base::MemoryState::NORMAL; | 77 base::MemoryState state_ = base::MemoryState::NORMAL; |
| 78 int purge_memory_calls_ = 0; |
| 75 }; | 79 }; |
| 76 | 80 |
| 77 class MockMemoryMonitor : public MemoryMonitor { | 81 class MockMemoryMonitor : public MemoryMonitor { |
| 78 public: | 82 public: |
| 79 MockMemoryMonitor() {} | 83 MockMemoryMonitor() {} |
| 80 ~MockMemoryMonitor() override {} | 84 ~MockMemoryMonitor() override {} |
| 81 | 85 |
| 82 void SetFreeMemoryUntilCriticalMB(int free_memory) { | 86 void SetFreeMemoryUntilCriticalMB(int free_memory) { |
| 83 free_memory_ = free_memory; | 87 free_memory_ = free_memory; |
| 84 } | 88 } |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 EXPECT_EQ(2, delegate->discard_tab_count()); | 563 EXPECT_EQ(2, delegate->discard_tab_count()); |
| 560 | 564 |
| 561 // Back to NORMAL. Tab discarding should stop. | 565 // Back to NORMAL. Tab discarding should stop. |
| 562 GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(50); | 566 GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(50); |
| 563 task_runner_->FastForwardBy(interval); | 567 task_runner_->FastForwardBy(interval); |
| 564 EXPECT_EQ(2, delegate->discard_tab_count()); | 568 EXPECT_EQ(2, delegate->discard_tab_count()); |
| 565 task_runner_->FastForwardBy(interval); | 569 task_runner_->FastForwardBy(interval); |
| 566 EXPECT_EQ(2, delegate->discard_tab_count()); | 570 EXPECT_EQ(2, delegate->discard_tab_count()); |
| 567 } | 571 } |
| 568 | 572 |
| 573 TEST_F(MemoryCoordinatorImplTest, OnWarningCondition) { |
| 574 MockMemoryCoordinatorClient client; |
| 575 base::MemoryCoordinatorClientRegistry::GetInstance()->Register(&client); |
| 576 auto* child1 = coordinator_->CreateChildMemoryCoordinator(1); |
| 577 auto* child2 = coordinator_->CreateChildMemoryCoordinator(2); |
| 578 base::TimeDelta interval = base::TimeDelta::FromSeconds(31); |
| 579 |
| 580 // child1: Foreground, child2: Background |
| 581 coordinator_->OnChildVisibilityChanged(1, true); |
| 582 coordinator_->OnChildVisibilityChanged(2, false); |
| 583 |
| 584 // Note: we never ask foreground processes (including the browser process) to |
| 585 // purge memory on WARNING condition. |
| 586 |
| 587 // Don't ask the background child to purge until the child remains |
| 588 // backgrounded for a certain period of time. |
| 589 coordinator_->OnWarningCondition(); |
| 590 RunUntilIdle(); |
| 591 EXPECT_EQ(0, client.purge_memory_calls()); |
| 592 EXPECT_EQ(0, child1->purge_memory_calls()); |
| 593 EXPECT_EQ(0, child2->purge_memory_calls()); |
| 594 |
| 595 // After a certain period of time is passed, request the child to purge |
| 596 // memory. |
| 597 task_runner_->FastForwardBy(interval); |
| 598 coordinator_->OnWarningCondition(); |
| 599 task_runner_->RunUntilIdle(); |
| 600 RunUntilIdle(); |
| 601 EXPECT_EQ(0, client.purge_memory_calls()); |
| 602 EXPECT_EQ(0, child1->purge_memory_calls()); |
| 603 EXPECT_EQ(1, child2->purge_memory_calls()); |
| 604 |
| 605 // Don't purge memory more than once when the child stays backgrounded. |
| 606 task_runner_->FastForwardBy(interval); |
| 607 coordinator_->OnWarningCondition(); |
| 608 RunUntilIdle(); |
| 609 EXPECT_EQ(0, client.purge_memory_calls()); |
| 610 EXPECT_EQ(0, child1->purge_memory_calls()); |
| 611 EXPECT_EQ(1, child2->purge_memory_calls()); |
| 612 |
| 613 // The background child goes to foreground, goes to background, then a |
| 614 // certain period of time is passed. Another purging request should be sent. |
| 615 coordinator_->OnChildVisibilityChanged(2, true); |
| 616 coordinator_->OnChildVisibilityChanged(2, false); |
| 617 task_runner_->FastForwardBy(interval); |
| 618 coordinator_->OnWarningCondition(); |
| 619 RunUntilIdle(); |
| 620 EXPECT_EQ(0, client.purge_memory_calls()); |
| 621 EXPECT_EQ(0, child1->purge_memory_calls()); |
| 622 EXPECT_EQ(2, child2->purge_memory_calls()); |
| 623 |
| 624 base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client); |
| 625 } |
| 626 |
| 627 TEST_F(MemoryCoordinatorImplTest, OnCriticalCondition) { |
| 628 MockMemoryCoordinatorClient client; |
| 629 base::MemoryCoordinatorClientRegistry::GetInstance()->Register(&client); |
| 630 auto* child1 = coordinator_->CreateChildMemoryCoordinator(1); |
| 631 auto* child2 = coordinator_->CreateChildMemoryCoordinator(2); |
| 632 auto* delegate = coordinator_->GetDelegate(); |
| 633 base::TimeDelta interval = base::TimeDelta::FromSeconds(31); |
| 634 |
| 635 // child1: Foreground, child2: Background |
| 636 coordinator_->OnChildVisibilityChanged(1, true); |
| 637 coordinator_->OnChildVisibilityChanged(2, false); |
| 638 |
| 639 // Purge memory from all children regardless of their visibility. |
| 640 task_runner_->FastForwardBy(interval); |
| 641 coordinator_->OnCriticalCondition(); |
| 642 RunUntilIdle(); |
| 643 task_runner_->FastForwardBy(interval); |
| 644 coordinator_->OnCriticalCondition(); |
| 645 RunUntilIdle(); |
| 646 EXPECT_EQ(2, delegate->discard_tab_count()); |
| 647 EXPECT_EQ(0, client.purge_memory_calls()); |
| 648 EXPECT_EQ(1, child1->purge_memory_calls()); |
| 649 EXPECT_EQ(1, child2->purge_memory_calls()); |
| 650 |
| 651 // Purge memory from browser process only after we asked all children to |
| 652 // purge memory. |
| 653 task_runner_->FastForwardBy(interval); |
| 654 coordinator_->OnCriticalCondition(); |
| 655 RunUntilIdle(); |
| 656 EXPECT_EQ(3, delegate->discard_tab_count()); |
| 657 EXPECT_EQ(1, client.purge_memory_calls()); |
| 658 EXPECT_EQ(1, child1->purge_memory_calls()); |
| 659 EXPECT_EQ(1, child2->purge_memory_calls()); |
| 660 |
| 661 // Don't request purging for a certain period of time if we already requested. |
| 662 task_runner_->FastForwardBy(interval); |
| 663 coordinator_->OnCriticalCondition(); |
| 664 RunUntilIdle(); |
| 665 EXPECT_EQ(4, delegate->discard_tab_count()); |
| 666 EXPECT_EQ(1, client.purge_memory_calls()); |
| 667 EXPECT_EQ(1, child1->purge_memory_calls()); |
| 668 EXPECT_EQ(1, child2->purge_memory_calls()); |
| 669 |
| 670 base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client); |
| 671 } |
| 672 |
| 569 #if defined(OS_ANDROID) | 673 #if defined(OS_ANDROID) |
| 570 // TODO(jcivelli): Broken on Android. http://crbug.com/678665 | 674 // TODO(jcivelli): Broken on Android. http://crbug.com/678665 |
| 571 #define MAYBE_GetStateForProcess DISABLED_GetStateForProcess | 675 #define MAYBE_GetStateForProcess DISABLED_GetStateForProcess |
| 572 #else | 676 #else |
| 573 #define MAYBE_GetStateForProcess GetStateForProcess | 677 #define MAYBE_GetStateForProcess GetStateForProcess |
| 574 #endif | 678 #endif |
| 575 TEST_F(MemoryCoordinatorImplTest, MAYBE_GetStateForProcess) { | 679 TEST_F(MemoryCoordinatorImplTest, MAYBE_GetStateForProcess) { |
| 576 EXPECT_EQ(base::MemoryState::UNKNOWN, | 680 EXPECT_EQ(base::MemoryState::UNKNOWN, |
| 577 coordinator_->GetStateForProcess(base::kNullProcessHandle)); | 681 coordinator_->GetStateForProcess(base::kNullProcessHandle)); |
| 578 EXPECT_EQ(base::MemoryState::NORMAL, | 682 EXPECT_EQ(base::MemoryState::NORMAL, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 598 | 702 |
| 599 EXPECT_TRUE( | 703 EXPECT_TRUE( |
| 600 coordinator_->SetChildMemoryState(1, MemoryState::THROTTLED)); | 704 coordinator_->SetChildMemoryState(1, MemoryState::THROTTLED)); |
| 601 EXPECT_EQ(base::MemoryState::THROTTLED, | 705 EXPECT_EQ(base::MemoryState::THROTTLED, |
| 602 coordinator_->GetStateForProcess(process1.Handle())); | 706 coordinator_->GetStateForProcess(process1.Handle())); |
| 603 EXPECT_EQ(base::MemoryState::NORMAL, | 707 EXPECT_EQ(base::MemoryState::NORMAL, |
| 604 coordinator_->GetStateForProcess(process2.Handle())); | 708 coordinator_->GetStateForProcess(process2.Handle())); |
| 605 } | 709 } |
| 606 | 710 |
| 607 } // namespace content | 711 } // namespace content |
| OLD | NEW |