| Index: content/browser/memory/memory_coordinator.cc
|
| diff --git a/content/browser/memory/memory_coordinator.cc b/content/browser/memory/memory_coordinator.cc
|
| index 622d8b92aaaa6c928d8672675d878e05637adc44..f6e74e95cca719aa6cb03a4b6d056dd4778028eb 100644
|
| --- a/content/browser/memory/memory_coordinator.cc
|
| +++ b/content/browser/memory/memory_coordinator.cc
|
| @@ -16,32 +16,43 @@ namespace content {
|
| // for the role of this class.
|
| class MemoryCoordinatorHandleImpl : public mojom::MemoryCoordinatorHandle {
|
| public:
|
| - MemoryCoordinatorHandleImpl(mojom::MemoryCoordinatorHandleRequest request)
|
| - : binding_(this, std::move(request)) {
|
| - }
|
| + MemoryCoordinatorHandleImpl(mojom::MemoryCoordinatorHandleRequest request,
|
| + MemoryCoordinator* coordinator,
|
| + int render_process_id);
|
| + ~MemoryCoordinatorHandleImpl() override;
|
|
|
| // mojom::MemoryCoordinatorHandle:
|
| - void AddChild(mojom::ChildMemoryCoordinatorPtr child) override {
|
| - DCHECK(!child_.is_bound());
|
| - child_ = std::move(child);
|
| - }
|
| + void AddChild(mojom::ChildMemoryCoordinatorPtr child) override;
|
|
|
| mojom::ChildMemoryCoordinatorPtr& child() { return child_; }
|
| mojo::Binding<mojom::MemoryCoordinatorHandle>& binding() { return binding_; }
|
|
|
| private:
|
| + MemoryCoordinator* coordinator_;
|
| + int render_process_id_;
|
| mojom::ChildMemoryCoordinatorPtr child_;
|
| mojo::Binding<mojom::MemoryCoordinatorHandle> binding_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(MemoryCoordinatorHandleImpl);
|
| };
|
|
|
| -// static
|
| -MemoryCoordinator* MemoryCoordinator::GetInstance() {
|
| - if (!base::FeatureList::IsEnabled(features::kMemoryCoordinator))
|
| - return nullptr;
|
| - return base::Singleton<MemoryCoordinator,
|
| - base::LeakySingletonTraits<MemoryCoordinator>>::get();
|
| +MemoryCoordinatorHandleImpl::MemoryCoordinatorHandleImpl(
|
| + mojom::MemoryCoordinatorHandleRequest request,
|
| + MemoryCoordinator* coordinator,
|
| + int render_process_id)
|
| + : coordinator_(coordinator),
|
| + render_process_id_(render_process_id),
|
| + binding_(this, std::move(request)) {
|
| + DCHECK(coordinator_);
|
| +}
|
| +
|
| +MemoryCoordinatorHandleImpl::~MemoryCoordinatorHandleImpl() {}
|
| +
|
| +void MemoryCoordinatorHandleImpl::AddChild(
|
| + mojom::ChildMemoryCoordinatorPtr child) {
|
| + DCHECK(!child_.is_bound());
|
| + child_ = std::move(child);
|
| + coordinator_->OnChildAdded(render_process_id_);
|
| }
|
|
|
| MemoryCoordinator::MemoryCoordinator()
|
| @@ -54,7 +65,8 @@ void MemoryCoordinator::CreateHandle(
|
| int render_process_id,
|
| mojom::MemoryCoordinatorHandleRequest request) {
|
| std::unique_ptr<MemoryCoordinatorHandleImpl> handle(
|
| - new MemoryCoordinatorHandleImpl(std::move(request)));
|
| + new MemoryCoordinatorHandleImpl(std::move(request), this,
|
| + render_process_id));
|
| handle->binding().set_connection_error_handler(
|
| base::Bind(&MemoryCoordinator::OnConnectionError, base::Unretained(this),
|
| render_process_id));
|
| @@ -76,10 +88,19 @@ bool MemoryCoordinator::SetMemoryState(int render_process_id,
|
| if (iter == children_.end())
|
| return false;
|
|
|
| + // Can't send a message to a child that isn't bound.
|
| + if (!iter->second.handle->child().is_bound())
|
| + return false;
|
| +
|
| // A nop doesn't need to be sent, but is considered successful.
|
| if (iter->second.memory_state == memory_state)
|
| return true;
|
|
|
| + // Can't throttle the given renderer.
|
| + if (memory_state == mojom::MemoryState::THROTTLED &&
|
| + !CanThrottleRenderer(render_process_id))
|
| + return false;
|
| +
|
| // Can't suspend the given renderer.
|
| if (memory_state == mojom::MemoryState::SUSPENDED &&
|
| !CanSuspendRenderer(render_process_id))
|
| @@ -104,7 +125,8 @@ void MemoryCoordinator::AddChildForTesting(
|
| mojom::MemoryCoordinatorHandlePtr mch;
|
| auto request = mojo::GetProxy(&mch);
|
| std::unique_ptr<MemoryCoordinatorHandleImpl> handle(
|
| - new MemoryCoordinatorHandleImpl(std::move(request)));
|
| + new MemoryCoordinatorHandleImpl(std::move(request), this,
|
| + dummy_render_process_id));
|
| handle->AddChild(std::move(child));
|
| CreateChildInfoMapEntry(dummy_render_process_id, std::move(handle));
|
| }
|
| @@ -113,6 +135,16 @@ void MemoryCoordinator::OnConnectionError(int render_process_id) {
|
| children_.erase(render_process_id);
|
| }
|
|
|
| +bool MemoryCoordinator::CanThrottleRenderer(int render_process_id) {
|
| + // If there is no delegate (i.e. tests), renderers are always throttleable.
|
| + // TODO(bashi): We check |delegate_| to avoid calling FromID() on a
|
| + // wrong thread in tests. Figure out a better way to handle tests.
|
| + if (!delegate_)
|
| + return true;
|
| + auto* render_process_host = RenderProcessHost::FromID(render_process_id);
|
| + return render_process_host->IsProcessBackgrounded();
|
| +}
|
| +
|
| bool MemoryCoordinator::CanSuspendRenderer(int render_process_id) {
|
| // If there is no delegate (i.e. tests), renderers are always suspendable.
|
| if (!delegate_)
|
|
|