// 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 "content/public/browser/service_process_host.h"

#include <string.h>

#include "base/memory/shared_memory_mapping.h"
#include "base/memory/unsafe_shared_memory_region.h"
#include "base/process/process.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/content_browser_test.h"
#include "services/test/echo/public/mojom/echo.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

#if BUILDFLAG(IS_WIN)
#include <windows.h>

#include "base/base_paths.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "content/public/browser/service_process_host_passkeys.h"
#endif

namespace content {

#if BUILDFLAG(IS_WIN)
using LoadStatus = echo::mojom::EchoService::LoadStatus;
namespace {
// This is used as the module name to load, and to make the DLL filename.
constexpr const wchar_t* kEchoPreloadLibrary = L"echo_preload_library";

// DLL path relative to current executable.
base::FilePath GetDllPath(std::wstring mod_name) {
  mod_name.append(L".dll");
  auto exe_dir = base::PathService::CheckedGet(base::BasePathKey::DIR_EXE);
  return exe_dir.Append(mod_name);
}
}  // namespace
#endif  // BUILDFLAG(IS_WIN)

constexpr char kTestUrl[] = "https://foo.bar";

using ServiceProcessHostBrowserTest = ContentBrowserTest;

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

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

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

  void WaitForLaunch() { launch_loop_.Run(); }
  void WaitForDeath() { death_loop_.Run(); }
  void WaitForCrash() { crash_loop_.Run(); }

  // Valid after WaitForLaunch.
  base::ProcessId pid() const { return process_.Pid(); }

 private:
  // ServiceProcessHost::Observer:
  void OnServiceProcessLaunched(const ServiceProcessInfo& info) override {
    if (info.IsService<echo::mojom::EchoService>()) {
      process_ = info.GetProcess().Duplicate();
      launch_loop_.Quit();
    }
  }

  void OnServiceProcessTerminatedNormally(
      const ServiceProcessInfo& info) override {
    if (info.IsService<echo::mojom::EchoService>())
      death_loop_.Quit();
  }

  void OnServiceProcessCrashed(const ServiceProcessInfo& info) override {
    if (info.IsService<echo::mojom::EchoService>()) {
      ASSERT_EQ(info.site(), GURL(kTestUrl));
      crash_loop_.Quit();
    }
  }

  base::RunLoop launch_loop_;
  base::RunLoop death_loop_;
  base::RunLoop crash_loop_;
  base::Process process_;
};

IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, Launch) {
  EchoServiceProcessObserver observer;
  base::ProcessId pid_from_callback = base::kNullProcessId;
  base::RunLoop pid_loop;
  auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>(
      ServiceProcessHost::Options()
          .WithProcessCallback(
              base::BindLambdaForTesting([&](const base::Process& process) {
                pid_from_callback = process.Pid();
                pid_loop.Quit();
              }))
          .Pass());
  observer.WaitForLaunch();
  pid_loop.Run();
  EXPECT_EQ(pid_from_callback, observer.pid());
  EXPECT_NE(base::kNullProcessId, pid_from_callback);

  const std::string kTestString =
      "Aurora borealis! At this time of year? At this time of day? "
      "In this part of the country? Localized entirely within your kitchen?";
  base::RunLoop loop;
  echo_service->EchoString(
      kTestString,
      base::BindLambdaForTesting([&](const std::string& echoed_input) {
        EXPECT_EQ(kTestString, echoed_input);
        loop.Quit();
      }));
  loop.Run();
}

IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, LocalDisconnectQuits) {
  EchoServiceProcessObserver observer;
  auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>();
  observer.WaitForLaunch();
  echo_service.reset();
  observer.WaitForDeath();
}

IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, RemoteDisconnectQuits) {
  EchoServiceProcessObserver observer;
  auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>();
  observer.WaitForLaunch();
  echo_service->Quit();
  observer.WaitForDeath();
}

IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, AllMessagesReceived) {
  // Verifies that messages sent right before disconnection are always received
  // and dispatched by the service before it self-terminates.
  EchoServiceProcessObserver observer;
  auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>();

  const size_t kBufferSize = 256;
  const std::string kMessages[] = {
      "I thought we were having steamed clams.",
      "D'oh, no! I said steamed hams. That's what I call hamburgers.",
      "You call hamburgers, \"steamed hams?\"",
      "Yes. It's a regional dialect."};
  auto region = base::UnsafeSharedMemoryRegion::Create(kBufferSize);
  base::WritableSharedMemoryMapping mapping = region.Map();
  memset(mapping.memory(), 0, kBufferSize);

  // Send several messages, since it helps to verify a lack of raciness between
  // service-side message dispatch and service termination.
  for (const auto& message : kMessages) {
    ASSERT_LE(message.size(), kBufferSize);
    echo_service->EchoStringToSharedMemory(message, region.Duplicate());
  }
  echo_service.reset();
  observer.WaitForDeath();

  const std::string& kLastMessage = kMessages[std::size(kMessages) - 1];
  EXPECT_EQ(0,
            memcmp(mapping.memory(), kLastMessage.data(), kLastMessage.size()));
}

IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, ObserveCrash) {
  EchoServiceProcessObserver observer;
  auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>(
      ServiceProcessHost::Options().WithSite(GURL(kTestUrl)).Pass());
  observer.WaitForLaunch();
  echo_service->Crash();
  observer.WaitForCrash();
}

IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, IdleTimeout) {
  EchoServiceProcessObserver observer;
  auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>();

  base::RunLoop wait_for_idle_loop;
  constexpr auto kTimeout = base::Seconds(1);
  echo_service.set_idle_handler(kTimeout, base::BindLambdaForTesting([&] {
                                  wait_for_idle_loop.Quit();
                                  echo_service.reset();
                                }));

  // Send a message and wait for the reply. Once the message is sent we should
  // observe at least |kTimeout| time elapsing before the RunLoop quits, because
  // the service process must wait at least that long to report itself as idle.
  base::ElapsedTimer timer;
  const std::string kTestString =
      "Yes, and you call them steamed hams despite the fact that they are "
      "obviously grilled.";
  echo_service->EchoString(
      kTestString,
      base::BindLambdaForTesting([&](const std::string& echoed_input) {
        EXPECT_EQ(kTestString, echoed_input);
      }));
  wait_for_idle_loop.Run();
  EXPECT_GE(timer.Elapsed(), kTimeout);

  // And since the idle handler resets |echo_service|, we should imminently see
  // normal service process termination.
  observer.WaitForDeath();
}

#if BUILDFLAG(IS_WIN)
IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, PreloadLibraryNotSet) {
  EchoServiceProcessObserver observer;
  auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>(
      ServiceProcessHost::Options().Pass());
  observer.WaitForLaunch();

  base::RunLoop loop;
  echo_service->LoadNativeLibrary(
      GetDllPath(kEchoPreloadLibrary), /*call_sec32_delayload=*/false,
      base::BindLambdaForTesting([&](LoadStatus status, uint32_t result) {
        EXPECT_EQ(LoadStatus::kFailedLoadLibrary, status);
        EXPECT_EQ(DWORD{ERROR_ACCESS_DENIED}, result);
        loop.Quit();
      }));
  loop.Run();
}

IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, PreloadLibraryPreloaded) {
  std::vector<base::FilePath> preloads;
  preloads.push_back(GetDllPath(kEchoPreloadLibrary));

  EchoServiceProcessObserver observer;
  auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>(
      ServiceProcessHost::Options()
          .WithPreloadedLibraries(
              preloads, ServiceProcessHostPreloadLibraries::GetPassKey())
          .Pass());
  observer.WaitForLaunch();

  base::RunLoop loop;
  echo_service->LoadNativeLibrary(
      GetDllPath(kEchoPreloadLibrary),
      /*call_sec32_delayload=*/true,
      base::BindLambdaForTesting([&](LoadStatus status, uint32_t result) {
        EXPECT_EQ(LoadStatus::kSuccess, status);
        EXPECT_EQ(0u, result);
        loop.Quit();
      }));
  loop.Run();
}

IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, PreloadLibraryMultiple) {
  std::vector<base::FilePath> preloads;
  // dbghelp is a placeholder - it will likely be loaded already - this test is
  // validating that multiple libraries can be sent into the child.
  preloads.push_back(GetDllPath(L"dbghelp"));
  preloads.push_back(GetDllPath(kEchoPreloadLibrary));

  EchoServiceProcessObserver observer;
  auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>(
      ServiceProcessHost::Options()
          .WithPreloadedLibraries(
              preloads, ServiceProcessHostPreloadLibraries::GetPassKey())
          .Pass());
  observer.WaitForLaunch();

  base::RunLoop loop;
  echo_service->LoadNativeLibrary(
      GetDllPath(kEchoPreloadLibrary), /*call_sec32_delayload=*/false,
      base::BindLambdaForTesting([&](LoadStatus status, uint32_t result) {
        EXPECT_EQ(LoadStatus::kSuccess, status);
        EXPECT_EQ(0u, result);
        loop.Quit();
      }));
  loop.Run();
}

IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, PreloadLibraryModName) {
  std::vector<base::FilePath> preloads;
  preloads.push_back(GetDllPath(kEchoPreloadLibrary));

  EchoServiceProcessObserver observer;
  auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>(
      ServiceProcessHost::Options()
          .WithPreloadedLibraries(
              preloads, ServiceProcessHostPreloadLibraries::GetPassKey())
          .Pass());
  observer.WaitForLaunch();

  base::RunLoop loop;
  // Once preloaded can people simply provide the module name?
  echo_service->LoadNativeLibrary(
      base::FilePath(kEchoPreloadLibrary), /*call_sec32_delayload=*/false,
      base::BindLambdaForTesting([&](LoadStatus status, uint32_t result) {
        EXPECT_EQ(LoadStatus::kSuccess, status);
        EXPECT_EQ(0u, result);
        loop.Quit();
      }));
  loop.Run();
}

// This test causes a CHECK in the child at startup.
IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, PreloadLibraryBadPath) {
  std::vector<base::FilePath> preloads;
  preloads.push_back(GetDllPath(L"this-is-not-a-library"));

  EchoServiceProcessObserver observer;
  auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>(
      ServiceProcessHost::Options()
          .WithSite(GURL(kTestUrl))  // For WaitForCrash().
          .WithPreloadedLibraries(
              preloads, ServiceProcessHostPreloadLibraries::GetPassKey())
          .Pass());
  observer.WaitForLaunch();
  observer.WaitForCrash();
}

// This test calls a function that verifies that user32 is loaded.
IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, PinUser32) {
  EchoServiceProcessObserver observer;
  auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>(
      ServiceProcessHost::Options()
          .WithPinUser32(ServiceProcessHostPinUser32::GetPassKey())
          .Pass());
  observer.WaitForLaunch();

  base::RunLoop loop;
  echo_service->CallUser32(
      std::string("lowercase"),
      base::BindLambdaForTesting([&](const std::string& upper) {
        EXPECT_EQ(upper, std::string("LOWERCASE"));
        loop.Quit();
      }));
  loop.Run();
}
#endif  // BUILDFLAG(IS_WIN)

}  // namespace content
