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

#include <limits>

#include "base/base_paths.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/callback_helpers.h"
#include "base/path_service.h"
#include "base/task/sequenced_task_runner.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "content/public/browser/service_process_host.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 "mojo/public/cpp/bindings/remote.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
#include "services/data_decoder/public/cpp/decode_image.h"
#include "services/data_decoder/public/mojom/data_decoder_service.mojom.h"
#include "services/data_decoder/public/mojom/image_decoder.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"

using ::testing::Pair;
using ::testing::UnorderedElementsAre;

namespace content {

namespace {

// Populates `output` and returns true on success (i.e. if `relative_path`
// exists and can be read into `output`).  Otherwise returns false.
bool ReadTestFile(const base::FilePath& relative_path,
                  std::vector<uint8_t>& output) {
  base::FilePath source_root_dir;
  if (!base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &source_root_dir)) {
    return false;
  }

  std::string file_contents_as_string;
  {
    base::ScopedAllowBlockingForTesting allow_file_io_for_testing;
    base::FilePath absolute_path = source_root_dir.Append(relative_path);
    if (!base::ReadFileToString(absolute_path, &file_contents_as_string))
      return false;
  }

  // Convert chars to uint8_ts.
  for (const char& c : file_contents_as_string)
    output.push_back(c);

  return true;
}

// Populates `out_measurement_value` and returns true on success (i.e. if the
// `metric_name` has a single measurement in `histograms`).  Otherwise returns
// false.
bool GetSingleMeasurement(const base::HistogramTester& histograms,
                          const char* metric_name,
                          base::TimeDelta& out_measurement_value) {
  DCHECK(metric_name);

  std::vector<base::Bucket> buckets = histograms.GetAllSamples(metric_name);
  if (buckets.size() != 1u)
    return false;

  EXPECT_EQ(1u, buckets.size());
  out_measurement_value = base::Milliseconds(buckets.front().min);
  return true;
}

}  // namespace

using DataDecoderBrowserTest = ContentBrowserTest;

class ServiceProcessObserver : public ServiceProcessHost::Observer {
 public:
  ServiceProcessObserver() { ServiceProcessHost::AddObserver(this); }

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

  ~ServiceProcessObserver() override {
    ServiceProcessHost::RemoveObserver(this);
  }

  int instances_started() const { return instances_started_; }

  void WaitForNextLaunch() {
    launch_wait_loop_.emplace();
    launch_wait_loop_->Run();
  }

  void OnServiceProcessLaunched(const ServiceProcessInfo& info) override {
    if (info.IsService<data_decoder::mojom::DataDecoderService>()) {
      ++instances_started_;
      if (launch_wait_loop_)
        launch_wait_loop_->Quit();
    }
  }

 private:
  std::optional<base::RunLoop> launch_wait_loop_;
  int instances_started_ = 0;
};

IN_PROC_BROWSER_TEST_F(DataDecoderBrowserTest, Launch) {
  ServiceProcessObserver observer;

  // Verifies that the DataDecoder client object launches a service process as
  // needed.
  data_decoder::DataDecoder decoder;

  // |GetService()| must always ensure a connection to the service on all
  // platforms, so we use it instead of a more specific API whose behavior may
  // vary across platforms.
  decoder.GetService();

  observer.WaitForNextLaunch();
  EXPECT_EQ(1, observer.instances_started());
}

IN_PROC_BROWSER_TEST_F(DataDecoderBrowserTest, LaunchIsolated) {
  ServiceProcessObserver observer;

  // Verifies that separate DataDecoder client objects will launch separate
  // service processes. We also bind an ImageDecoder interface to ensure that
  // the instances don't go idle.
  data_decoder::DataDecoder decoder1;
  mojo::Remote<data_decoder::mojom::ImageDecoder> image_decoder1;
  decoder1.GetService()->BindImageDecoder(
      image_decoder1.BindNewPipeAndPassReceiver());
  observer.WaitForNextLaunch();
  EXPECT_EQ(1, observer.instances_started());

  data_decoder::DataDecoder decoder2;
  mojo::Remote<data_decoder::mojom::ImageDecoder> image_decoder2;
  decoder2.GetService()->BindImageDecoder(
      image_decoder2.BindNewPipeAndPassReceiver());
  observer.WaitForNextLaunch();
  EXPECT_EQ(2, observer.instances_started());

  // Both interfaces should be connected end-to-end.
  image_decoder1.FlushForTesting();
  image_decoder2.FlushForTesting();
  EXPECT_TRUE(image_decoder1.is_connected());
  EXPECT_TRUE(image_decoder2.is_connected());
}

IN_PROC_BROWSER_TEST_F(DataDecoderBrowserTest, DecodeImageIsolated) {
  std::vector<uint8_t> file_contents;
  base::FilePath content_test_data_path = GetTestDataFilePath();
  base::FilePath png_path =
      content_test_data_path.AppendASCII("site_isolation/png-corp.png");
  ASSERT_TRUE(ReadTestFile(png_path, file_contents));

  base::HistogramTester histograms;
  {
    base::RunLoop run_loop;
    data_decoder::DecodeImageCallback callback =
        base::BindLambdaForTesting([&](const SkBitmap& decoded_bitmap) {
          EXPECT_EQ(100, decoded_bitmap.width());
          EXPECT_EQ(100, decoded_bitmap.height());
          run_loop.Quit();
        });
    data_decoder::DecodeImageIsolated(
        file_contents, data_decoder::mojom::ImageCodec::kDefault,
        false,                                 // shrink_to_fit
        std::numeric_limits<uint32_t>::max(),  // max_size_in_bytes
        gfx::Size(),                           // desired_image_frame_size
        std::move(callback));
    run_loop.Run();
  }

  FetchHistogramsFromChildProcesses();
  EXPECT_THAT(
      histograms.GetTotalCountsForPrefix("Security.DataDecoder"),
      UnorderedElementsAre(
          Pair("Security.DataDecoder.Image.Isolated.EndToEndTime", 1),
          Pair("Security.DataDecoder.Image.Isolated.ProcessOverhead", 1),
          Pair("Security.DataDecoder.Image.DecodingTime", 1)));

  base::TimeDelta end_to_end_duration_estimate;
  EXPECT_TRUE(GetSingleMeasurement(
      histograms, "Security.DataDecoder.Image.Isolated.EndToEndTime",
      end_to_end_duration_estimate));

  base::TimeDelta overhead_estimate;
  EXPECT_TRUE(GetSingleMeasurement(
      histograms, "Security.DataDecoder.Image.Isolated.ProcessOverhead",
      overhead_estimate));

  base::TimeDelta decoding_duration_estimate;
  EXPECT_TRUE(GetSingleMeasurement(histograms,
                                   "Security.DataDecoder.Image.DecodingTime",
                                   decoding_duration_estimate));

  EXPECT_LE(decoding_duration_estimate, end_to_end_duration_estimate);
  EXPECT_LE(overhead_estimate, end_to_end_duration_estimate);
}

IN_PROC_BROWSER_TEST_F(DataDecoderBrowserTest, DecodeImage) {
  std::vector<uint8_t> file_contents;
  base::FilePath content_test_data_path = GetTestDataFilePath();
  base::FilePath png_path =
      content_test_data_path.AppendASCII("site_isolation/png-corp.png");
  ASSERT_TRUE(ReadTestFile(png_path, file_contents));

  base::HistogramTester histograms;
  {
    base::RunLoop run_loop;
    data_decoder::DecodeImageCallback callback =
        base::BindLambdaForTesting([&](const SkBitmap& decoded_bitmap) {
          EXPECT_EQ(100, decoded_bitmap.width());
          EXPECT_EQ(100, decoded_bitmap.height());
          run_loop.Quit();
        });

    data_decoder::DataDecoder decoder;
    data_decoder::DecodeImage(
        &decoder, file_contents, data_decoder::mojom::ImageCodec::kDefault,
        false,                                 // shrink_to_fit
        std::numeric_limits<uint32_t>::max(),  // max_size_in_bytes
        gfx::Size(),                           // desired_image_frame_size
        std::move(callback));
    run_loop.Run();
  }

  FetchHistogramsFromChildProcesses();
  EXPECT_THAT(
      histograms.GetTotalCountsForPrefix("Security.DataDecoder"),
      UnorderedElementsAre(
          Pair("Security.DataDecoder.Image.Reusable.EndToEndTime", 1),
          Pair("Security.DataDecoder.Image.Reusable.ProcessOverhead", 1),
          Pair("Security.DataDecoder.Image.DecodingTime", 1)));

  base::TimeDelta end_to_end_duration_estimate;
  EXPECT_TRUE(GetSingleMeasurement(
      histograms, "Security.DataDecoder.Image.Reusable.EndToEndTime",
      end_to_end_duration_estimate));

  base::TimeDelta overhead_estimate;
  EXPECT_TRUE(GetSingleMeasurement(
      histograms, "Security.DataDecoder.Image.Reusable.ProcessOverhead",
      overhead_estimate));

  base::TimeDelta decoding_duration_estimate;
  EXPECT_TRUE(GetSingleMeasurement(histograms,
                                   "Security.DataDecoder.Image.DecodingTime",
                                   decoding_duration_estimate));

  EXPECT_LE(decoding_duration_estimate, end_to_end_duration_estimate);
  EXPECT_LE(overhead_estimate, end_to_end_duration_estimate);
}

IN_PROC_BROWSER_TEST_F(DataDecoderBrowserTest,
                       NoCallbackAfterDestruction_Json) {
  base::RunLoop run_loop;

  auto decoder = std::make_unique<data_decoder::DataDecoder>();
  auto* raw_decoder = decoder.get();

  // Android's in-process parser can complete synchronously, so queue the
  // delete task first unlike in the other tests.
  base::SequencedTaskRunner::GetCurrentDefault()->DeleteSoon(
      FROM_HERE, std::move(decoder));

  bool got_callback = false;
  raw_decoder->ParseJson(
      "[1, 2, 3]",
      base::BindOnce(
          [](bool* got_callback, base::ScopedClosureRunner quit_closure_runner,
             data_decoder::DataDecoder::ValueOrError result) {
            *got_callback = true;
          },
          // Pass the quit closure as a ScopedClosureRunner, so that the loop
          // is quit if the callback is destroyed un-run or after it runs.
          &got_callback, base::ScopedClosureRunner(run_loop.QuitClosure())));

  run_loop.Run();

  EXPECT_FALSE(got_callback);
}

IN_PROC_BROWSER_TEST_F(DataDecoderBrowserTest, NoCallbackAfterDestruction_Xml) {
  base::RunLoop run_loop;

  auto decoder = std::make_unique<data_decoder::DataDecoder>();
  bool got_callback = false;
  decoder->ParseXml(
      "<marquee>hello world</marquee>",
      data_decoder::mojom::XmlParser::WhitespaceBehavior::kIgnore,
      base::BindOnce(
          [](bool* got_callback, base::ScopedClosureRunner quit_closure_runner,
             data_decoder::DataDecoder::ValueOrError result) {
            *got_callback = true;
          },
          // Pass the quit closure as a ScopedClosureRunner, so that the loop
          // is quit if the callback is destroyed un-run or after it runs.
          &got_callback, base::ScopedClosureRunner(run_loop.QuitClosure())));

  base::SequencedTaskRunner::GetCurrentDefault()->DeleteSoon(
      FROM_HERE, std::move(decoder));
  run_loop.Run();

  EXPECT_FALSE(got_callback);
}

IN_PROC_BROWSER_TEST_F(DataDecoderBrowserTest,
                       NoCallbackAfterDestruction_Gzip) {
  base::RunLoop run_loop;

  auto decoder = std::make_unique<data_decoder::DataDecoder>();
  bool got_callback = false;
  decoder->GzipCompress(
      {{0x1, 0x1, 0x1, 0x1, 0x1, 0x1}},
      base::BindOnce(
          [](bool* got_callback, base::ScopedClosureRunner quit_closure_runner,
             base::expected<mojo_base::BigBuffer, std::string> result) {
            *got_callback = true;
          },
          // Pass the quit closure as a ScopedClosureRunner, so that the loop
          // is quit if the callback is destroyed un-run or after it runs.
          &got_callback, base::ScopedClosureRunner(run_loop.QuitClosure())));

  base::SequencedTaskRunner::GetCurrentDefault()->DeleteSoon(
      FROM_HERE, std::move(decoder));
  run_loop.Run();

  EXPECT_FALSE(got_callback);
}

}  // namespace content
