// Copyright 2019 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 "chrome/browser/chromeos/login/screens/supervision_onboarding_screen.h"

#include <initializer_list>
#include <memory>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/strings/string_piece.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/chromeos/login/login_wizard.h"
#include "chrome/browser/chromeos/login/mixin_based_in_process_browser_test.h"
#include "chrome/browser/chromeos/login/oobe_screen.h"
#include "chrome/browser/chromeos/login/test/embedded_test_server_mixin.h"
#include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h"
#include "chrome/browser/chromeos/login/test/js_checker.h"
#include "chrome/browser/chromeos/login/test/local_policy_test_server_mixin.h"
#include "chrome/browser/chromeos/login/test/login_manager_mixin.h"
#include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
#include "chrome/browser/chromeos/login/test/user_policy_mixin.h"
#include "chrome/browser/chromeos/login/ui/login_display_host.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/supervision/onboarding_constants.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/webui/chromeos/login/supervision_onboarding_screen_handler.h"
#include "chromeos/constants/chromeos_features.h"
#include "chromeos/constants/chromeos_switches.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"

using net::test_server::BasicHttpResponse;
using net::test_server::HttpRequest;
using net::test_server::HttpResponse;

namespace chromeos {

namespace {

chromeos::OobeUI* GetOobeUI() {
  auto* host = chromeos::LoginDisplayHost::default_host();
  return host ? host->GetOobeUI() : nullptr;
}

}  // namespace

// Fake HTTP server that returns the data necessary to render the Supervision
// Onboarding pages. It provides methods to customize the HTTP responses to
// include/omit custom HTTP headers that are expected by the flow.
class FakeSupervisionServer {
 public:
  explicit FakeSupervisionServer(net::EmbeddedTestServer* test_server) {
    test_server_ = test_server;

    test_server_->RegisterRequestHandler(base::BindRepeating(
        &FakeSupervisionServer::HandleRequest, base::Unretained(this)));
  }

  ~FakeSupervisionServer() = default;

  // Sets the custom HTTP header that will be sent back in responses.
  void set_custom_http_header_value(
      const std::string& custom_http_header_value) {
    custom_http_header_value_ = custom_http_header_value;
  }

  // Stops sending the custom header in responses.
  void clear_custom_http_header_value() {
    custom_http_header_value_ = base::nullopt;
  }

  size_t GetReceivedRequestsCount() const {
    // It's safe to use the size of the access token list as a proxy to the
    // number of requests. This server asserts that all requests contain an
    // authentication header.
    return received_auth_header_values_.size();
  }

 private:
  std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request) {
    // We are not interested in other URLs hitting the server at this point.
    // This will filter bogus requests like favicon fetches and stop us from
    // handling requests that are targeting gaia.
    if (request.relative_url != supervision::kOnboardingStartPageRelativeUrl)
      return nullptr;

    UpdateVerificationData(request);
    auto response = std::make_unique<BasicHttpResponse>();
    if (custom_http_header_value_.has_value()) {
      response->AddCustomHeader(supervision::kExperimentHeaderName,
                                custom_http_header_value_.value());
    }

    response->set_code(net::HTTP_OK);
    response->set_content("Test Supervision Onboarding content");
    response->set_content_type("text/plain");
    return std::move(response);
  }

  void UpdateVerificationData(const HttpRequest& request) {
    auto auth_header =
        request.headers.find(net::HttpRequestHeaders::kAuthorization);
    ASSERT_NE(auth_header, request.headers.end());
    ASSERT_EQ(auth_header->second,
              base::StringPrintf("Bearer %s",
                                 FakeGaiaMixin::kFakeAllScopeAccessToken));

    received_auth_header_values_.push_back(auth_header->second);
  }

  net::EmbeddedTestServer* test_server_;
  std::vector<std::string> received_auth_header_values_;

  base::Optional<std::string> custom_http_header_value_ = base::nullopt;
};

class SupervisionOnboardingBaseTest : public MixinBasedInProcessBrowserTest {
 public:
  SupervisionOnboardingBaseTest() = default;
  ~SupervisionOnboardingBaseTest() override = default;

  virtual bool IsFeatureOn() const = 0;
  virtual bool IsChild() const = 0;

  void SetUp() override {
    if (IsFeatureOn()) {
      feature_list_.InitAndEnableFeature(
          features::kEnableSupervisionOnboardingScreens);
    }

    MixinBasedInProcessBrowserTest::SetUp();
  }

  void SetUpCommandLine(base::CommandLine* command_line) override {
    if (IsFeatureOn()) {
      command_line->AppendSwitchASCII(
          switches::kSupervisionOnboardingUrlPrefix,
          embedded_test_server()->base_url().spec());

      // To turn on the feature properly we also ask the server to return the
      // expected custom http header value. Tests that want to simulate other
      // server responses can call these methods again to override this
      // behavior.
      supervision_server()->set_custom_http_header_value(
          supervision::kDeviceOnboardingExperimentName);
    }

    MixinBasedInProcessBrowserTest::SetUpCommandLine(command_line);
  }

  void SetUpOnMainThread() override {
    host_resolver()->AddRule("*", "127.0.0.1");

    AccountId id =
        IsChild() ? child_user_.account_id : regular_user_.account_id;
    fake_gaia_.SetupFakeGaiaForLogin(id.GetUserEmail(), id.GetGaiaId(),
                                     FakeGaiaMixin::kFakeRefreshToken);

    LoginManagerMixin::TestUserInfo user_info =
        IsChild() ? child_user_ : regular_user_;
    UserContext user_context =
        LoginManagerMixin::CreateDefaultUserContext(user_info);
    user_context.SetRefreshToken(FakeGaiaMixin::kFakeRefreshToken);
    login_manager_.LoginAndWaitForActiveSession(user_context);

    ShowLoginWizard(OobeScreen::SCREEN_TEST_NO_WINDOW);
    WizardController::default_controller()
        ->screen_manager()
        ->DeleteScreenForTesting(SupervisionOnboardingScreenView::kScreenId);
    auto supervision_onboarding_screen =
        std::make_unique<SupervisionOnboardingScreen>(
            GetOobeUI()->GetView<SupervisionOnboardingScreenHandler>(),
            base::BindRepeating(
                &SupervisionOnboardingBaseTest::HandleScreenExit,
                base::Unretained(this)));
    supervision_onboarding_screen_ = supervision_onboarding_screen.get();
    WizardController::default_controller()
        ->screen_manager()
        ->SetScreenForTesting(std::move(supervision_onboarding_screen));

    MixinBasedInProcessBrowserTest::SetUpOnMainThread();
  }

  void ShowScreen() { supervision_onboarding_screen_->Show(); }

  void WaitForScreen() {
    OobeScreenWaiter screen_waiter(SupervisionOnboardingScreenView::kScreenId);
    screen_waiter.set_assert_next_screen();
    screen_waiter.Wait();

    test::OobeJS()
        .CreateVisibilityWaiter(
            true, {"supervision-onboarding", "supervision-onboarding-content"})
        ->Wait();
  }

  void ClickButton(const std::string& button_id) {
    std::initializer_list<base::StringPiece> button_path = {
        "supervision-onboarding", button_id};
    test::OobeJS().CreateEnabledWaiter(true, button_path)->Wait();
    test::OobeJS().TapOnPath(button_path);
  }

  void WaitForScreenExit() {
    if (screen_exited_)
      return;

    base::RunLoop run_loop;
    screen_exit_callback_ = run_loop.QuitClosure();
    run_loop.Run();
  }

  FakeSupervisionServer* supervision_server() { return &supervision_server_; }

  SupervisionOnboardingScreen* supervision_onboarding_screen_;

 private:
  void HandleScreenExit() {
    ASSERT_FALSE(screen_exited_);
    screen_exited_ = true;
    if (screen_exit_callback_)
      std::move(screen_exit_callback_).Run();
  }

  base::test::ScopedFeatureList feature_list_;
  bool screen_exited_ = false;
  base::OnceClosure screen_exit_callback_;

  const LoginManagerMixin::TestUserInfo regular_user_{
      AccountId::FromUserEmailGaiaId("test-regular-user@gmail.com",
                                     "test-regular-user-gaia-id")};
  const LoginManagerMixin::TestUserInfo child_user_{
      AccountId::FromUserEmailGaiaId("test-child-user@gmail.com",
                                     "test-child-user-gaia-id"),
      user_manager::USER_TYPE_CHILD};

  EmbeddedTestServerSetupMixin embedded_test_server_{&mixin_host_,
                                                     embedded_test_server()};
  FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()};
  LoginManagerMixin login_manager_{&mixin_host_, {regular_user_, child_user_}};
  LocalPolicyTestServerMixin local_policy_mixin_{&mixin_host_};
  UserPolicyMixin user_policy_{&mixin_host_, child_user_.account_id,
                               &local_policy_mixin_};

  FakeSupervisionServer supervision_server_{embedded_test_server()};
};

class SupervisionOnboardingRegularUserTest
    : public SupervisionOnboardingBaseTest {
 public:
  SupervisionOnboardingRegularUserTest() = default;
  ~SupervisionOnboardingRegularUserTest() override = default;

  bool IsFeatureOn() const override { return true; }

  bool IsChild() const override { return false; }
};

IN_PROC_BROWSER_TEST_F(SupervisionOnboardingRegularUserTest,
                       FlowExitsImmediately) {
  ShowScreen();

  WaitForScreenExit();
  EXPECT_EQ(0u, supervision_server()->GetReceivedRequestsCount());
}

class SupervisionOnboardingFeatureTurnedOffTest
    : public SupervisionOnboardingBaseTest {
 public:
  SupervisionOnboardingFeatureTurnedOffTest() = default;
  ~SupervisionOnboardingFeatureTurnedOffTest() override = default;

  bool IsFeatureOn() const override { return false; }

  bool IsChild() const override { return true; }
};

IN_PROC_BROWSER_TEST_F(SupervisionOnboardingFeatureTurnedOffTest,
                       FlowExitsImmediately) {
  ShowScreen();

  WaitForScreenExit();
  EXPECT_EQ(0u, supervision_server()->GetReceivedRequestsCount());
}

class SupervisionOnboardingTest : public SupervisionOnboardingBaseTest {
 public:
  SupervisionOnboardingTest() = default;
  ~SupervisionOnboardingTest() override = default;

  bool IsFeatureOn() const override { return true; }

  bool IsChild() const override { return true; }
};

IN_PROC_BROWSER_TEST_F(SupervisionOnboardingTest,
                       ExitWhenServerDoesNotReturnHeader) {
  supervision_server()->clear_custom_http_header_value();

  ShowScreen();
  WaitForScreenExit();

  EXPECT_EQ(1u, supervision_server()->GetReceivedRequestsCount());
}

IN_PROC_BROWSER_TEST_F(SupervisionOnboardingTest,
                       ExitWhenServerSendsWrongHeader) {
  supervision_server()->set_custom_http_header_value("wrong_header_value");

  ShowScreen();
  WaitForScreenExit();

  EXPECT_EQ(1u, supervision_server()->GetReceivedRequestsCount());
}

IN_PROC_BROWSER_TEST_F(SupervisionOnboardingTest, NextButtonExitsScreen) {
  ShowScreen();
  WaitForScreen();
  EXPECT_EQ(1u, supervision_server()->GetReceivedRequestsCount());

  ClickButton("supervision-onboarding-next-button");
  WaitForScreenExit();
}

IN_PROC_BROWSER_TEST_F(SupervisionOnboardingTest, BackButtonExitsScreen) {
  ShowScreen();
  WaitForScreen();
  EXPECT_EQ(1u, supervision_server()->GetReceivedRequestsCount());

  ClickButton("supervision-onboarding-back-button");
  WaitForScreenExit();
}

IN_PROC_BROWSER_TEST_F(SupervisionOnboardingTest, SkipButtonExitsScreen) {
  ShowScreen();
  WaitForScreen();
  EXPECT_EQ(1u, supervision_server()->GetReceivedRequestsCount());

  ClickButton("supervision-onboarding-skip-button");
  WaitForScreenExit();
}

}  // namespace chromeos
