// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <utility>

#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/power_monitor/power_observer.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/spare_render_process_host_manager_impl.h"
#include "content/browser/utility_process_host.h"
#include "content/public/browser/browser_child_process_host.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/gpu_service_registry.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "content/public/common/process_type.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/shell/common/power_monitor_test.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/remote_set.h"
#include "services/device/public/mojom/power_monitor.mojom.h"

namespace content {

namespace {

void VerifyPowerStateInChildProcess(
    mojom::PowerMonitorTest* power_monitor_test,
    base::PowerStateObserver::BatteryPowerStatus expected_state) {
  base::RunLoop run_loop;
  power_monitor_test->QueryNextState(base::BindOnce(
      [](base::RunLoop* loop,
         base::PowerStateObserver::BatteryPowerStatus expected_state,
         base::PowerStateObserver::BatteryPowerStatus battery_power_status) {
        EXPECT_EQ(expected_state, battery_power_status);
        loop->Quit();
      },
      &run_loop, expected_state));
  run_loop.Run();
}

class MockPowerMonitorMessageBroadcaster : public device::mojom::PowerMonitor {
 public:
  MockPowerMonitorMessageBroadcaster() = default;

  MockPowerMonitorMessageBroadcaster(
      const MockPowerMonitorMessageBroadcaster&) = delete;
  MockPowerMonitorMessageBroadcaster& operator=(
      const MockPowerMonitorMessageBroadcaster&) = delete;

  ~MockPowerMonitorMessageBroadcaster() override = default;

  void Bind(mojo::PendingReceiver<device::mojom::PowerMonitor> receiver) {
    receivers_.Add(this, std::move(receiver));
  }

  // device::mojom::PowerMonitor:
  void AddClient(mojo::PendingRemote<device::mojom::PowerMonitorClient>
                     pending_power_monitor_client) override {
    mojo::Remote<device::mojom::PowerMonitorClient> power_monitor_client(
        std::move(pending_power_monitor_client));
    power_monitor_client->PowerStateChange(battery_power_status_);
    clients_.Add(std::move(power_monitor_client));
  }

  void OnPowerStateChange(
      base::PowerStateObserver::BatteryPowerStatus battery_power_status) {
    battery_power_status_ = battery_power_status;
    for (auto& client : clients_)
      client->PowerStateChange(battery_power_status);
  }

 private:
  base::PowerStateObserver::BatteryPowerStatus battery_power_status_ =
      base::PowerStateObserver::BatteryPowerStatus::kUnknown;

  mojo::ReceiverSet<device::mojom::PowerMonitor> receivers_;
  mojo::RemoteSet<device::mojom::PowerMonitorClient> clients_;
};

class PowerMonitorTest : public ContentBrowserTest {
 public:
  PowerMonitorTest() {
    // Intercept PowerMonitor binding requests from all types of child
    // processes.
    RenderProcessHost::InterceptBindHostReceiverForTesting(base::BindRepeating(
        &PowerMonitorTest::BindForRenderer, base::Unretained(this)));
    BrowserChildProcessHost::InterceptBindHostReceiverForTesting(
        base::BindRepeating(&PowerMonitorTest::BindForNonRenderer,
                            base::Unretained(this)));
  }

  PowerMonitorTest(const PowerMonitorTest&) = delete;
  PowerMonitorTest& operator=(const PowerMonitorTest&) = delete;

  ~PowerMonitorTest() override {
    RenderProcessHost::InterceptBindHostReceiverForTesting(
        base::NullCallback());
    BrowserChildProcessHost::InterceptBindHostReceiverForTesting(
        base::NullCallback());
  }

  void BindForRenderer(ChildProcessId render_process_id,
                       mojo::GenericPendingReceiver* receiver) {
    auto r = receiver->As<device::mojom::PowerMonitor>();
    if (!r)
      return;

    GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE,
        base::BindOnce(&PowerMonitorTest::BindForRendererOnMainThread,
                       base::Unretained(this), std::move(r),
                       render_process_id));
  }

  void BindForNonRenderer(BrowserChildProcessHost* process_host,
                          mojo::GenericPendingReceiver* receiver) {
    auto r = receiver->As<device::mojom::PowerMonitor>();
    if (!r)
      return;

    GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE,
        base::BindOnce(&PowerMonitorTest::BindForNonRendererOnMainThread,
                       base::Unretained(this),
                       process_host->GetData().process_type, std::move(r)));
  }

 protected:
  void StartUtilityProcess(
      mojo::Remote<mojom::PowerMonitorTest>* power_monitor_test,
      base::OnceClosure utility_bound_closure) {
    utility_bound_closure_ = std::move(utility_bound_closure);

    UtilityProcessHost* host = new UtilityProcessHost();
    host->SetMetricsName("test_process");
    host->SetName(u"TestProcess");
    EXPECT_TRUE(host->Start());

    host->GetChildProcess()->BindReceiver(
        power_monitor_test->BindNewPipeAndPassReceiver());
  }

  void set_renderer_bound_closure(base::OnceClosure closure) {
    renderer_bound_closure_ = std::move(closure);
  }

  void set_gpu_bound_closure(base::OnceClosure closure) {
    gpu_bound_closure_ = std::move(closure);
  }

  int request_count_from_renderer() { return request_count_from_renderer_; }
  int request_count_from_utility() { return request_count_from_utility_; }
  int request_count_from_gpu() { return request_count_from_gpu_; }

  void SimulatePowerStateChange(
      base::PowerStateObserver::BatteryPowerStatus battery_power_status) {
    power_monitor_message_broadcaster_.OnPowerStateChange(battery_power_status);
  }

 private:
  void BindForRendererOnMainThread(
      mojo::PendingReceiver<device::mojom::PowerMonitor> receiver,
      ChildProcessId render_process_id) {
    // We can receive binding requests for the spare RenderProcessHost -- this
    // might happen before the test has provided the |renderer_bound_closure_|.
    auto* render_process_host =
        content::RenderProcessHost::FromID(render_process_id);
    if (!render_process_host || render_process_host->IsSpare()) {
      return;
    }

    ASSERT_TRUE(renderer_bound_closure_);
    ++request_count_from_renderer_;
    std::move(renderer_bound_closure_).Run();

    power_monitor_message_broadcaster_.Bind(std::move(receiver));
  }

  void BindForNonRendererOnMainThread(
      int process_type,
      mojo::PendingReceiver<device::mojom::PowerMonitor> receiver) {
    if (process_type == PROCESS_TYPE_UTILITY) {
      if (utility_bound_closure_) {
        ++request_count_from_utility_;
        std::move(utility_bound_closure_).Run();
      }
    } else if (process_type == PROCESS_TYPE_GPU) {
      ++request_count_from_gpu_;

      // We ignore null gpu_bound_closure_ here for two possible scenarios:
      //  - TestRendererProcess and TestUtilityProcess also result in spinning
      //    up GPU processes as a side effect, but they do not set valid
      //    gpu_bound_closure_.
      //  - As GPU process is started during setup of browser test suite, so
      //    it's possible that TestGpuProcess execution may have not started
      //    yet when the PowerMonitor bind request comes here, in such case
      //    gpu_bound_closure_ will also be null.
      if (gpu_bound_closure_)
        std::move(gpu_bound_closure_).Run();
    }

    power_monitor_message_broadcaster_.Bind(std::move(receiver));
  }

  int request_count_from_renderer_ = 0;
  int request_count_from_utility_ = 0;
  int request_count_from_gpu_ = 0;
  base::OnceClosure renderer_bound_closure_;
  base::OnceClosure gpu_bound_closure_;
  base::OnceClosure utility_bound_closure_;

  MockPowerMonitorMessageBroadcaster power_monitor_message_broadcaster_;
};

IN_PROC_BROWSER_TEST_F(PowerMonitorTest, TestRendererProcess) {
  ASSERT_EQ(0, request_count_from_renderer());
  base::RunLoop run_loop;
  set_renderer_bound_closure(run_loop.QuitClosure());
  ASSERT_TRUE(NavigateToURL(shell(), GetTestUrl(".", "simple_page.html")));
  run_loop.Run();
  EXPECT_EQ(1, request_count_from_renderer());

  mojo::Remote<mojom::PowerMonitorTest> power_monitor_renderer;
  RenderProcessHost* rph =
      shell()->web_contents()->GetPrimaryMainFrame()->GetProcess();
  rph->BindReceiver(power_monitor_renderer.BindNewPipeAndPassReceiver());

  // Ensure that the PowerMonitorTestImpl instance has been created and is
  // observing power state changes in the child process before simulating a
  // power state change.
  power_monitor_renderer.FlushForTesting();

  SimulatePowerStateChange(
      base::PowerStateObserver::BatteryPowerStatus::kBatteryPower);
  // Verify renderer process battery_power_status changed to battery power.
  VerifyPowerStateInChildProcess(
      power_monitor_renderer.get(),
      base::PowerStateObserver::BatteryPowerStatus::kBatteryPower);

  SimulatePowerStateChange(
      base::PowerStateObserver::BatteryPowerStatus::kExternalPower);
  // Verify renderer process battery_power_status changed to external power.
  VerifyPowerStateInChildProcess(
      power_monitor_renderer.get(),
      base::PowerStateObserver::BatteryPowerStatus::kExternalPower);

  SimulatePowerStateChange(
      base::PowerStateObserver::BatteryPowerStatus::kUnknown);
  // Verify renderer process battery_power_status becomes unknown.
  VerifyPowerStateInChildProcess(
      power_monitor_renderer.get(),
      base::PowerStateObserver::BatteryPowerStatus::kUnknown);
}

IN_PROC_BROWSER_TEST_F(PowerMonitorTest, TestUtilityProcess) {
  mojo::Remote<mojom::PowerMonitorTest> power_monitor_utility;

  ASSERT_EQ(0, request_count_from_utility());
  base::RunLoop run_loop;
  StartUtilityProcess(&power_monitor_utility, run_loop.QuitClosure());
  run_loop.Run();
  EXPECT_EQ(1, request_count_from_utility());

  // Ensure that the PowerMonitorTestImpl instance has been created and is
  // observing power state changes in the child process before simulating a
  // power state change.
  power_monitor_utility.FlushForTesting();

  SimulatePowerStateChange(
      base::PowerStateObserver::BatteryPowerStatus::kBatteryPower);
  // Verify renderer process battery_power_status changed to battery power.
  VerifyPowerStateInChildProcess(
      power_monitor_utility.get(),
      base::PowerStateObserver::BatteryPowerStatus::kBatteryPower);

  SimulatePowerStateChange(
      base::PowerStateObserver::BatteryPowerStatus::kExternalPower);
  // Verify renderer process battery_power_status changed to external power.
  VerifyPowerStateInChildProcess(
      power_monitor_utility.get(),
      base::PowerStateObserver::BatteryPowerStatus::kExternalPower);
}

IN_PROC_BROWSER_TEST_F(PowerMonitorTest, TestGpuProcess) {
  // As gpu process is started automatically during the setup period of browser
  // test suite, it may have already started and bound PowerMonitor interface to
  // Device Service before execution of this TestGpuProcess test. So here we
  // do not wait for the connection if we found it has already been established.
  if (request_count_from_gpu() != 1) {
    ASSERT_EQ(0, request_count_from_gpu());
    base::RunLoop run_loop;
    set_gpu_bound_closure(run_loop.QuitClosure());
    // Wait for the connection from gpu process.
    run_loop.Run();
  }
  EXPECT_EQ(1, request_count_from_gpu());

  mojo::Remote<mojom::PowerMonitorTest> power_monitor_gpu;
  BindInterfaceInGpuProcess(power_monitor_gpu.BindNewPipeAndPassReceiver());

  // Ensure that the PowerMonitorTestImpl instance has been created and is
  // observing power state changes in the child process before simulating a
  // power state change.
  power_monitor_gpu.FlushForTesting();

  SimulatePowerStateChange(
      base::PowerStateObserver::BatteryPowerStatus::kBatteryPower);
  // Verify gpu process battery_power_status changed to battery power.
  VerifyPowerStateInChildProcess(
      power_monitor_gpu.get(),
      base::PowerStateObserver::BatteryPowerStatus::kBatteryPower);

  SimulatePowerStateChange(
      base::PowerStateObserver::BatteryPowerStatus::kExternalPower);
  // Verify gpu process battery_power_status changed to external power.
  VerifyPowerStateInChildProcess(
      power_monitor_gpu.get(),
      base::PowerStateObserver::BatteryPowerStatus::kExternalPower);
}

}  //  namespace

}  //  namespace content
