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 |