// Copyright 2016 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 "headless/test/headless_browser_test.h"

#include <memory>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/message_loop/message_loop_current.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "build/build_config.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "headless/lib/browser/headless_browser_impl.h"
#include "headless/lib/browser/headless_web_contents_impl.h"
#include "headless/lib/headless_content_main_delegate.h"
#include "headless/public/devtools/domains/emulation.h"
#include "headless/public/devtools/domains/runtime.h"
#include "headless/public/headless_devtools_client.h"
#include "headless/public/headless_devtools_target.h"
#include "headless/public/headless_web_contents.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gl/gl_switches.h"
#include "url/gurl.h"

namespace headless {
namespace {

class SynchronousLoadObserver {
 public:
  SynchronousLoadObserver(HeadlessBrowserTest* browser_test,
                          HeadlessWebContents* web_contents)
      : web_contents_(web_contents),
        devtools_client_(HeadlessDevToolsClient::Create()) {
    web_contents_->GetDevToolsTarget()->AttachClient(devtools_client_.get());
    load_observer_.reset(new LoadObserver(
        devtools_client_.get(),
        base::Bind(&HeadlessBrowserTest::FinishAsynchronousTest,
                   base::Unretained(browser_test))));
  }

  ~SynchronousLoadObserver() {
    web_contents_->GetDevToolsTarget()->DetachClient(devtools_client_.get());
  }

  bool navigation_succeeded() const {
    return load_observer_->navigation_succeeded();
  }

 private:
  HeadlessWebContents* web_contents_;  // Not owned.
  std::unique_ptr<HeadlessDevToolsClient> devtools_client_;
  std::unique_ptr<LoadObserver> load_observer_;
};

class EvaluateHelper {
 public:
  EvaluateHelper(HeadlessBrowserTest* browser_test,
                 HeadlessWebContents* web_contents,
                 const std::string& script_to_eval)
      : browser_test_(browser_test),
        web_contents_(web_contents),
        devtools_client_(HeadlessDevToolsClient::Create()) {
    web_contents_->GetDevToolsTarget()->AttachClient(devtools_client_.get());
    devtools_client_->GetRuntime()->Evaluate(
        script_to_eval, base::BindOnce(&EvaluateHelper::OnEvaluateResult,
                                       base::Unretained(this)));
  }

  ~EvaluateHelper() {
    web_contents_->GetDevToolsTarget()->DetachClient(devtools_client_.get());
  }

  void OnEvaluateResult(std::unique_ptr<runtime::EvaluateResult> result) {
    result_ = std::move(result);
    browser_test_->FinishAsynchronousTest();
  }

  std::unique_ptr<runtime::EvaluateResult> TakeResult() {
    return std::move(result_);
  }

 private:
  HeadlessBrowserTest* browser_test_;  // Not owned.
  HeadlessWebContents* web_contents_;  // Not owned.
  std::unique_ptr<HeadlessDevToolsClient> devtools_client_;

  std::unique_ptr<runtime::EvaluateResult> result_;

  DISALLOW_COPY_AND_ASSIGN(EvaluateHelper);
};

}  // namespace

LoadObserver::LoadObserver(HeadlessDevToolsClient* devtools_client,
                           base::OnceClosure callback)
    : callback_(std::move(callback)),
      devtools_client_(devtools_client),
      navigation_succeeded_(true) {
  devtools_client_->GetNetwork()->AddObserver(this);
  devtools_client_->GetNetwork()->Enable();
  devtools_client_->GetPage()->AddObserver(this);
  devtools_client_->GetPage()->Enable();
}

LoadObserver::~LoadObserver() {
  devtools_client_->GetNetwork()->RemoveObserver(this);
  devtools_client_->GetPage()->RemoveObserver(this);
}

void LoadObserver::OnLoadEventFired(const page::LoadEventFiredParams& params) {
  std::move(callback_).Run();
}

void LoadObserver::OnResponseReceived(
    const network::ResponseReceivedParams& params) {
  if (params.GetResponse()->GetStatus() != 200 ||
      params.GetResponse()->GetUrl() == content::kUnreachableWebDataURL) {
    navigation_succeeded_ = false;
  }
}

HeadlessBrowserTest::HeadlessBrowserTest() {
#if defined(OS_MACOSX)
  // On Mac the source root is not set properly. We override it by assuming
  // that is two directories up from the execution test file.
  base::FilePath dir_exe_path;
  CHECK(base::PathService::Get(base::DIR_EXE, &dir_exe_path));
  dir_exe_path = dir_exe_path.Append("../../");
  CHECK(base::PathService::Override(base::DIR_SOURCE_ROOT, dir_exe_path));
#endif  // defined(OS_MACOSX)
  base::FilePath headless_test_data(FILE_PATH_LITERAL("headless/test/data"));
  CreateTestServer(headless_test_data);
}

void HeadlessBrowserTest::SetUp() {
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  // Enable GPU usage (i.e., SwiftShader, hardware GL on macOS) in all tests
  // since that's the default configuration of --headless.
  command_line->AppendSwitch(switches::kUseGpuInTests);
  SetUpCommandLine(command_line);
  BrowserTestBase::SetUp();
}

void HeadlessBrowserTest::SetUpWithoutGPU() {
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  SetUpCommandLine(command_line);
  BrowserTestBase::SetUp();
}

HeadlessBrowserTest::~HeadlessBrowserTest() = default;

void HeadlessBrowserTest::PreRunTestOnMainThread() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  // Pump startup related events.
  base::RunLoop().RunUntilIdle();
}

void HeadlessBrowserTest::PostRunTestOnMainThread() {
  browser()->Shutdown();
  for (content::RenderProcessHost::iterator i(
           content::RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance()) {
    i.GetCurrentValue()->FastShutdownIfPossible();
  }
}

HeadlessBrowser* HeadlessBrowserTest::browser() const {
  return HeadlessContentMainDelegate::GetInstance()->browser();
}

HeadlessBrowser::Options* HeadlessBrowserTest::options() const {
  return HeadlessContentMainDelegate::GetInstance()->browser()->options();
}

bool HeadlessBrowserTest::WaitForLoad(HeadlessWebContents* web_contents) {
  HeadlessWebContentsImpl* web_contents_impl =
      HeadlessWebContentsImpl::From(web_contents);
  content::TestNavigationObserver observer(web_contents_impl->web_contents(),
                                           1);
  observer.Wait();
  return observer.last_navigation_succeeded();
}

void HeadlessBrowserTest::WaitForLoadAndGainFocus(
    HeadlessWebContents* web_contents) {
  content::WebContents* content =
      HeadlessWebContentsImpl::From(web_contents)->web_contents();

  // To finish loading and to gain focus are two independent events. Which one
  // is issued first is undefined. The following code is waiting on both, in any
  // order.
  content::TestNavigationObserver load_observer(content, 1);
  content::FrameFocusedObserver focus_observer(content->GetMainFrame());
  load_observer.Wait();
  focus_observer.Wait();
}

std::unique_ptr<runtime::EvaluateResult> HeadlessBrowserTest::EvaluateScript(
    HeadlessWebContents* web_contents,
    const std::string& script) {
  EvaluateHelper helper(this, web_contents, script);
  RunAsynchronousTest();
  return helper.TakeResult();
}

void HeadlessBrowserTest::RunAsynchronousTest() {
  base::MessageLoopCurrent::ScopedNestableTaskAllower nestable_allower;
  EXPECT_FALSE(run_loop_);
  run_loop_ = std::make_unique<base::RunLoop>();
  PreRunAsynchronousTest();
  run_loop_->Run();
  PostRunAsynchronousTest();
  run_loop_ = nullptr;
}

void HeadlessBrowserTest::FinishAsynchronousTest() {
  run_loop_->Quit();
}

HeadlessAsyncDevTooledBrowserTest::HeadlessAsyncDevTooledBrowserTest()
    : browser_context_(nullptr),
      web_contents_(nullptr),
      render_process_exited_(false) {}

HeadlessAsyncDevTooledBrowserTest::~HeadlessAsyncDevTooledBrowserTest() =
    default;

void HeadlessAsyncDevTooledBrowserTest::DevToolsTargetReady() {
  EXPECT_TRUE(web_contents_->GetDevToolsTarget());
  web_contents_->GetDevToolsTarget()->AttachClient(devtools_client_.get());
#if defined(OS_MACOSX)
  devtools_client_->GetEmulation()->SetDeviceMetricsOverride(
      emulation::SetDeviceMetricsOverrideParams::Builder()
          .SetWidth(0)
          .SetHeight(0)
          .SetDeviceScaleFactor(1)
          .SetMobile(false)
          .Build(),
      base::BindOnce(
          [](HeadlessAsyncDevTooledBrowserTest* self) {
            self->RunDevTooledTest();
          },
          base::Unretained(this)));
#else
  RunDevTooledTest();
#endif
}

void HeadlessAsyncDevTooledBrowserTest::RenderProcessExited(
    base::TerminationStatus status,
    int exit_code) {
  if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION)
    return;

  FinishAsynchronousTest();
  render_process_exited_ = true;
  FAIL() << "Abnormal renderer termination";
}

void HeadlessAsyncDevTooledBrowserTest::RunTest() {
  devtools_client_ = HeadlessDevToolsClient::Create();
  browser_devtools_client_ = HeadlessDevToolsClient::Create();
  interceptor_ = std::make_unique<TestNetworkInterceptor>();
  HeadlessBrowserContext::Builder builder =
      browser()->CreateBrowserContextBuilder();
  CustomizeHeadlessBrowserContext(builder);
  browser_context_ = builder.Build();

  browser()->SetDefaultBrowserContext(browser_context_);
  browser()->GetDevToolsTarget()->AttachClient(browser_devtools_client_.get());

  HeadlessWebContents::Builder web_contents_builder =
      browser_context_->CreateWebContentsBuilder();
  web_contents_builder.SetEnableBeginFrameControl(GetEnableBeginFrameControl());
  CustomizeHeadlessWebContents(web_contents_builder);
  web_contents_ = web_contents_builder.Build();

  web_contents_->AddObserver(this);

  RunAsynchronousTest();
  interceptor_.reset();
  if (!render_process_exited_)
    web_contents_->GetDevToolsTarget()->DetachClient(devtools_client_.get());
  web_contents_->RemoveObserver(this);
  web_contents_->Close();
  web_contents_ = nullptr;
  browser()->GetDevToolsTarget()->DetachClient(browser_devtools_client_.get());
  browser_context_->Close();
  browser_context_ = nullptr;
}

bool HeadlessAsyncDevTooledBrowserTest::GetEnableBeginFrameControl() {
  return false;
}

void HeadlessAsyncDevTooledBrowserTest::CustomizeHeadlessBrowserContext(
    HeadlessBrowserContext::Builder& builder) {}

void HeadlessAsyncDevTooledBrowserTest::CustomizeHeadlessWebContents(
    HeadlessWebContents::Builder& builder) {}

}  // namespace headless
