| Index: services/resource_coordinator/coordination_unit.cc
|
| diff --git a/services/resource_coordinator/coordination_unit.cc b/services/resource_coordinator/coordination_unit.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..854b4fa74344f2577f1559c9463b29b1f2dc402a
|
| --- /dev/null
|
| +++ b/services/resource_coordinator/coordination_unit.cc
|
| @@ -0,0 +1,183 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "services/resource_coordinator/coordination_unit.h"
|
| +
|
| +#include "base/hash.h"
|
| +#include "base/lazy_instance.h"
|
| +#include "base/logging.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "mojo/public/cpp/bindings/strong_binding.h"
|
| +#include "services/service_manager/public/cpp/connection.h"
|
| +
|
| +namespace resource_coordinator {
|
| +
|
| +namespace {
|
| +
|
| +base::LazyInstance<std::unordered_map<int64_t, CoordinationUnit*>>::Leaky
|
| + g_cu_map = LAZY_INSTANCE_INITIALIZER;
|
| +
|
| +int64_t CUIDHash(mojom::CoordinationUnitIDPtr id) {
|
| + // TODO: hash the type into the upper 32 bits.
|
| + return base::Hash(id->id);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +CoordinationUnit::CoordinationUnit(mojom::CoordinationUnitIDPtr options) {
|
| + // LOG(ERROR) << "CoordinationUnit::CoordinationUnit(0x" << this << ")";
|
| + // LOG(ERROR) << "id(" << options->type << ":" << options->id << ")";
|
| +
|
| + type_ = options->type;
|
| + id_ = options->id;
|
| + id_hash_ = CUIDHash(std::move(options));
|
| + g_cu_map.Get().insert(std::make_pair(id_hash_, this));
|
| +}
|
| +
|
| +CoordinationUnit::~CoordinationUnit() {
|
| + // LOG(ERROR) << "CoordinationUnit::~CoordinationUnit(0x" << this << ")";
|
| + g_cu_map.Get().erase(id_hash_);
|
| +
|
| + for (auto* child : children_) {
|
| + child->RemoveParent(this);
|
| + }
|
| +
|
| + for (auto* parent : parents_) {
|
| + parent->RemoveChild(this);
|
| + }
|
| +}
|
| +
|
| +bool CoordinationUnit::SelfOrParentHasFlagSet(StateFlags state) {
|
| + const base::Optional<bool>& state_flag = state_flags_[state];
|
| + if (state_flag && *state_flag)
|
| + return true;
|
| +
|
| + for (auto* parent : parents_) {
|
| + if (parent->SelfOrParentHasFlagSet(state))
|
| + return true;
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| +void CoordinationUnit::RecalcPolicy() {
|
| + if (!policy_callback_)
|
| + return;
|
| +
|
| + bool background_priority = !SelfOrParentHasFlagSet(TAB_VISIBLE) &&
|
| + !SelfOrParentHasFlagSet(AUDIO_PLAYING);
|
| +
|
| + // LOG(ERROR) << "Should background: " << background_priority;
|
| +
|
| + for (auto* child : children_) {
|
| + child->RecalcPolicy();
|
| + }
|
| +
|
| + // Send the priority to the client if it's new or changed.
|
| + if (!current_policy_)
|
| + current_policy_ = mojom::Policy::New();
|
| + else if (current_policy_->use_background_priority == background_priority)
|
| + return;
|
| +
|
| + mojom::PolicyPtr policy = mojom::Policy::New();
|
| + policy->use_background_priority = background_priority;
|
| + current_policy_->use_background_priority = background_priority;
|
| +
|
| + policy_callback_->SetPolicy(std::move(policy));
|
| +}
|
| +
|
| +void CoordinationUnit::SendEvent(mojom::EventPtr event) {
|
| + // LOG(ERROR) << "CoordinationUnit::SendEvent(0x" << this << "): " <<
|
| + // event->type;
|
| +
|
| + switch (event->type) {
|
| + case mojom::EventType::ON_WEBCONTENTS_SHOWN:
|
| + state_flags_[TAB_VISIBLE] = true;
|
| + break;
|
| + case mojom::EventType::ON_WEBCONTENTS_HIDDEN:
|
| + state_flags_[TAB_VISIBLE] = false;
|
| + break;
|
| + case mojom::EventType::ON_PROCESS_AUDIO_STARTED:
|
| + state_flags_[AUDIO_PLAYING] = true;
|
| + break;
|
| + case mojom::EventType::ON_PROCESS_AUDIO_STOPPED:
|
| + state_flags_[AUDIO_PLAYING] = false;
|
| + break;
|
| + default:
|
| + return;
|
| + }
|
| +
|
| + RecalcPolicy();
|
| +}
|
| +
|
| +void CoordinationUnit::GetID(const GetIDCallback& callback) {
|
| + mojom::CoordinationUnitIDPtr id = mojom::CoordinationUnitID::New();
|
| + id->type = type_;
|
| + id->id = id_;
|
| + callback.Run(std::move(id));
|
| +}
|
| +
|
| +void CoordinationUnit::Duplicate(mojom::CoordinationUnitRequest request) {
|
| + // LOG(ERROR) << "CoordinationUnit::Duplicate(0x" << this << ")";
|
| + bindings_.AddBinding(this, std::move(request));
|
| +}
|
| +
|
| +void CoordinationUnit::AddChild(mojom::CoordinationUnitIDPtr child_id) {
|
| + // LOG(ERROR) << "CoordinationUnit::AddChild(" << type_ << ":" << id_ << " ->
|
| + // "
|
| + // << child_id->type << ":" << child_id->id << ")";
|
| +
|
| + auto child_iter = g_cu_map.Get().find(CUIDHash(std::move(child_id)));
|
| + if (child_iter != g_cu_map.Get().end()) {
|
| + CoordinationUnit* child = child_iter->second;
|
| + // TODO: Ensure we're staying a DAG and not adding any cycles here.
|
| + if (AddChild(child)) {
|
| + child->AddParent(this);
|
| + }
|
| + }
|
| +}
|
| +
|
| +bool CoordinationUnit::AddChild(CoordinationUnit* child) {
|
| + if (children_.find(child) != children_.end())
|
| + return false;
|
| +
|
| + children_.insert(child);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void CoordinationUnit::RemoveChild(CoordinationUnit* child) {
|
| + size_t children_removed = children_.erase(child);
|
| + CHECK_EQ(1u, children_removed);
|
| +}
|
| +
|
| +void CoordinationUnit::AddParent(CoordinationUnit* parent) {
|
| + DCHECK(parents_.find(parent) == parents_.end());
|
| + parents_.insert(parent);
|
| +
|
| + RecalcPolicy();
|
| +}
|
| +
|
| +void CoordinationUnit::RemoveParent(CoordinationUnit* parent) {
|
| + size_t parents_removed = parents_.erase(parent);
|
| + CHECK_EQ(1u, parents_removed);
|
| +
|
| + RecalcPolicy();
|
| +}
|
| +
|
| +void CoordinationUnit::SetPolicyCallback(mojom::PolicyCallbackPtr callback) {
|
| + callback.set_connection_error_handler(base::Bind(
|
| + &CoordinationUnit::UnregisterPolicyCallback, base::Unretained(this)));
|
| +
|
| + policy_callback_ = std::move(callback);
|
| +
|
| + RecalcPolicy();
|
| +}
|
| +
|
| +void CoordinationUnit::UnregisterPolicyCallback() {
|
| + policy_callback_.reset();
|
| + current_policy_.reset();
|
| +}
|
| +
|
| +} // namespace resource_coordinator
|
|
|