// Copyright 2023 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/browser/btm/btm_test_utils.h"

#include <string_view>

#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/content_settings/core/common/content_settings_utils.h"
#include "content/browser/btm/btm_service_impl.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/btm_service.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/hit_test_region_observer.h"
#include "content/public/test/test_frame_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "net/base/schemeful_site.h"
#include "net/cookies/cookie_setting_override.h"
#include "net/cookies/site_for_cookies.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/public/mojom/frame/frame.mojom-shared.h"

namespace content {

void CloseTab(WebContents* web_contents) {
  WebContentsDestroyedWatcher destruction_watcher(web_contents);
  web_contents->Close();
  destruction_watcher.Wait();
}

base::expected<WebContents*, std::string> OpenInNewTab(
    WebContents* original_tab,
    const GURL& url) {
  OpenedWindowObserver tab_observer(original_tab,
                                    WindowOpenDisposition::NEW_FOREGROUND_TAB);
  if (!ExecJs(original_tab, JsReplace("window.open($1, '_blank');", url))) {
    return base::unexpected("window.open failed");
  }
  tab_observer.Wait();

  // Wait for the new tab to finish navigating.
  WaitForLoadStop(tab_observer.window());

  return tab_observer.window();
}

[[nodiscard]] testing::AssertionResult AccessStorage(
    RenderFrameHost* frame,
    blink::mojom::StorageTypeAccessed type) {
  // We drop the first character of ToString(type) because it's just the
  // constant-indicating 'k'.
  return ExecJs(frame,
                base::StringPrintf(kStorageAccessScript,
                                   base::ToString(type).substr(1).c_str()),
                EXECUTE_SCRIPT_NO_USER_GESTURE,
                /*world_id=*/1);
}

void AccessCookieViaJSIn(WebContents* web_contents, RenderFrameHost* frame) {
  FrameCookieAccessObserver observer(web_contents, frame,
                                     CookieOperation::kChange);
  ASSERT_TRUE(ExecJs(frame, "document.cookie = 'foo=bar';",
                     EXECUTE_SCRIPT_NO_USER_GESTURE));
  observer.Wait();
}

[[nodiscard]] testing::AssertionResult ClientSideRedirectViaMetaTag(
    WebContents* web_contents,
    RenderFrameHost* frame,
    const GURL& target_url,
    const std::optional<const GURL>& expected_commit_url) {
  TestFrameNavigationObserver nav_observer(frame);
  bool js_succeeded = ExecJs(frame,
                             JsReplace(
                                 R"(
      function redirectViaMetaTag() {
        var element = document.createElement('meta');
        element.setAttribute('http-equiv', 'refresh');
        element.setAttribute('content', '0; url=$1');
        document.getElementsByTagName('head')[0].appendChild(element);
      }
      if (document.readyState === "loading") {
        document.addEventListener("DOMContentLoaded", redirectViaMetaTag);
      } else {
        redirectViaMetaTag();
      }
      )",
                                 target_url),
                             EXECUTE_SCRIPT_NO_USER_GESTURE);
  if (!js_succeeded) {
    return testing::AssertionFailure()
           << "Failed to execute script to client-side redirect to URL "
           << target_url;
  }
  nav_observer.Wait();
  if (nav_observer.last_committed_url() ==
      expected_commit_url.value_or(target_url)) {
    return testing::AssertionSuccess();
  } else {
    return testing::AssertionFailure()
           << "Expected to arrive at "
           << expected_commit_url.value_or(target_url)
           << " but URL was actually " << nav_observer.last_committed_url();
  }
}

[[nodiscard]] testing::AssertionResult ClientSideRedirectViaJS(
    WebContents* web_contents,
    RenderFrameHost* frame,
    const GURL& target_url,
    const std::optional<const GURL>& expected_commit_url) {
  TestFrameNavigationObserver nav_observer(frame);
  bool js_succeeded =
      ExecJs(frame, JsReplace(R"(window.location.replace($1);)", target_url),
             EXECUTE_SCRIPT_NO_USER_GESTURE);
  if (!js_succeeded) {
    return testing::AssertionFailure()
           << "Failed to execute script to client-side redirect to URL "
           << target_url;
  }
  nav_observer.Wait();
  if (nav_observer.last_committed_url() ==
      expected_commit_url.value_or(target_url)) {
    return testing::AssertionSuccess();
  } else {
    return testing::AssertionFailure()
           << "Expected to arrive at "
           << expected_commit_url.value_or(target_url)
           << " but URL was actually " << nav_observer.last_committed_url();
  }
}

std::string StringifyBtmClientRedirectMethod(
    BtmClientRedirectMethod client_redirect_method) {
  switch (client_redirect_method) {
    case BtmClientRedirectMethod::kMetaTag:
      return "MetaTag";
    case BtmClientRedirectMethod::kJsWindowLocationReplace:
      return "JsWindowLocationReplace";
    case BtmClientRedirectMethod::kRedirectLikeNavigation:
      return "RedirectLikeNavigation";
  }
}

[[nodiscard]] testing::AssertionResult PerformClientRedirect(
    BtmClientRedirectMethod redirect_method,
    WebContents* web_contents,
    const GURL& redirect_url,
    const std::optional<const GURL>& expected_commit_url) {
  const GURL& commit_url = expected_commit_url.value_or(redirect_url);
  switch (redirect_method) {
    case BtmClientRedirectMethod::kMetaTag:
      return ClientSideRedirectViaMetaTag(web_contents,
                                          web_contents->GetPrimaryMainFrame(),
                                          redirect_url, commit_url);
    case BtmClientRedirectMethod::kJsWindowLocationReplace:
      return ClientSideRedirectViaJS(web_contents,
                                     web_contents->GetPrimaryMainFrame(),
                                     redirect_url, commit_url);
    case BtmClientRedirectMethod::kRedirectLikeNavigation:
      return testing::AssertionResult(
          NavigateToURLFromRendererWithoutUserGesture(
              web_contents, redirect_url, commit_url));
  }
}

bool NavigateToSetCookie(WebContents* web_contents,
                         const net::EmbeddedTestServer* server,
                         std::string_view host,
                         bool is_secure_cookie_set,
                         bool is_ad_tagged) {
  std::string relative_url = "/set-cookie?name=value";
  if (is_secure_cookie_set) {
    relative_url += ";Secure;SameSite=None";
  }
  if (is_ad_tagged) {
    relative_url += "&isad=1";
  }
  const auto url = server->GetURL(host, relative_url);

  URLCookieAccessObserver observer(web_contents, url, CookieOperation::kChange);
  bool success = NavigateToURL(web_contents, url);
  if (success) {
    observer.Wait();
  }
  return success;
}

void CreateImageAndWaitForCookieAccess(WebContents* web_contents,
                                       const GURL& image_url) {
  URLCookieAccessObserver observer(web_contents, image_url,
                                   CookieOperation::kRead);
  ASSERT_TRUE(ExecJs(web_contents,
                     JsReplace(
                         R"(
    let img = document.createElement('img');
    img.src = $1;
    document.body.appendChild(img);)",
                         image_url),
                     EXECUTE_SCRIPT_NO_USER_GESTURE));
  // The image must cause a cookie access, or else this will hang.
  observer.Wait();
}

std::optional<StateValue> GetBtmState(BtmServiceImpl* btm_service,
                                      const GURL& url) {
  std::optional<StateValue> state;

  auto* storage = btm_service->storage();
  DCHECK(storage);
  storage->AsyncCall(&BtmStorage::Read)
      .WithArgs(url)
      .Then(base::BindLambdaForTesting([&](const BtmState& loaded_state) {
        if (loaded_state.was_loaded()) {
          state = loaded_state.ToStateValue();
        }
      }));
  WaitOnStorage(btm_service);

  return state;
}

URLCookieAccessObserver::URLCookieAccessObserver(WebContents* web_contents,
                                                 const GURL& url,
                                                 CookieOperation access_type)
    : WebContentsObserver(web_contents), url_(url), access_type_(access_type) {}

void URLCookieAccessObserver::Wait() {
  run_loop_.Run();
}

void URLCookieAccessObserver::OnCookiesAccessed(
    RenderFrameHost* render_frame_host,
    const CookieAccessDetails& details) {
  cookie_accessed_in_primary_page_ = IsInPrimaryPage(*render_frame_host);

  if (details.type == access_type_ && details.url == url_) {
    run_loop_.Quit();
  }
}

void URLCookieAccessObserver::OnCookiesAccessed(
    NavigationHandle* navigation_handle,
    const CookieAccessDetails& details) {
  cookie_accessed_in_primary_page_ = IsInPrimaryPage(*navigation_handle);

  if (details.type == access_type_ && details.url == url_) {
    run_loop_.Quit();
  }
}

bool URLCookieAccessObserver::CookieAccessedInPrimaryPage() const {
  return cookie_accessed_in_primary_page_;
}

FrameCookieAccessObserver::FrameCookieAccessObserver(
    WebContents* web_contents,
    RenderFrameHost* render_frame_host,
    CookieOperation access_type)
    : WebContentsObserver(web_contents),
      render_frame_host_(render_frame_host),
      access_type_(access_type) {}

void FrameCookieAccessObserver::Wait() {
  run_loop_.Run();
}

void FrameCookieAccessObserver::OnCookiesAccessed(
    RenderFrameHost* render_frame_host,
    const CookieAccessDetails& details) {
  if (details.type == access_type_ && render_frame_host_ == render_frame_host) {
    run_loop_.Quit();
  }
}

UserActivationObserver::UserActivationObserver(
    WebContents* web_contents,
    RenderFrameHost* render_frame_host)
    : WebContentsObserver(web_contents),
      render_frame_host_(render_frame_host) {}

void UserActivationObserver::Wait() {
  run_loop_.Run();
}

void UserActivationObserver::FrameReceivedUserActivation(
    RenderFrameHost* render_frame_host) {
  if (render_frame_host_ == render_frame_host) {
    run_loop_.Quit();
  }
}

EntryUrlsAre::EntryUrlsAre(std::string entry_name,
                           std::vector<std::string> urls)
    : entry_name_(std::move(entry_name)), expected_urls_(std::move(urls)) {
  // Sort the URLs before comparing, so order doesn't matter. (BtmDatabase
  // currently sorts its results, but that could change and these tests
  // shouldn't care.)
  std::sort(expected_urls_.begin(), expected_urls_.end());
}

EntryUrlsAre::EntryUrlsAre(const EntryUrlsAre&) = default;
EntryUrlsAre::EntryUrlsAre(EntryUrlsAre&&) = default;
EntryUrlsAre::~EntryUrlsAre() = default;

bool EntryUrlsAre::MatchAndExplain(
    const ukm::TestUkmRecorder& ukm_recorder,
    testing::MatchResultListener* result_listener) const {
  std::vector<std::string> actual_urls;
  for (const ukm::mojom::UkmEntry* entry :
       ukm_recorder.GetEntriesByName(entry_name_)) {
    GURL url = ukm_recorder.GetSourceForSourceId(entry->source_id)->url();
    actual_urls.push_back(url.spec());
  }
  std::sort(actual_urls.begin(), actual_urls.end());

  // ExplainMatchResult() won't print out the full contents of `actual_urls`,
  // so for more helpful error messages, we do it ourselves.
  *result_listener << "whose entries for '" << entry_name_
                   << "' contain the URLs "
                   << testing::PrintToString(actual_urls) << ", ";

  // Use ContainerEq() instead of e.g. ElementsAreArray() because the error
  // messages are much more useful.
  return ExplainMatchResult(testing::ContainerEq(expected_urls_), actual_urls,
                            result_listener);
}

void EntryUrlsAre::DescribeTo(std::ostream* os) const {
  *os << "has entries for '" << entry_name_ << "' whose URLs are "
      << testing::PrintToString(expected_urls_);
}

void EntryUrlsAre::DescribeNegationTo(std::ostream* os) const {
  *os << "does not have entries for '" << entry_name_ << "' whose URLs are "
      << testing::PrintToString(expected_urls_);
}

ScopedInitFeature::ScopedInitFeature(const base::Feature& feature,
                                     bool enable,
                                     const base::FieldTrialParams& params) {
  if (enable) {
    feature_list_.InitAndEnableFeatureWithParameters(feature, params);
  } else {
    feature_list_.InitAndDisableFeature(feature);
  }
}

ScopedInitBtmFeature::ScopedInitBtmFeature(bool enable,
                                           const base::FieldTrialParams& params)
    : init_feature_(features::kBtm, enable, params) {}

OpenedWindowObserver::OpenedWindowObserver(
    WebContents* web_contents,
    WindowOpenDisposition open_disposition)
    : WebContentsObserver(web_contents), open_disposition_(open_disposition) {}

void OpenedWindowObserver::DidOpenRequestedURL(
    WebContents* new_contents,
    RenderFrameHost* source_render_frame_host,
    const GURL& url,
    const Referrer& referrer,
    WindowOpenDisposition disposition,
    ui::PageTransition transition,
    bool started_from_context_menu,
    bool renderer_initiated) {
  if (!window_ && disposition == open_disposition_) {
    window_ = new_contents;
    run_loop_.Quit();
  }
}

// TODO - crbug.com/40247129: Remove this method in favor of directly using
// SimulateMouseClickAndWait() once mouse clicks / taps reliably trigger user
// activation on Android
void SimulateUserActivation(WebContents* web_contents) {
#if BUILDFLAG(IS_ANDROID)
  ASSERT_TRUE(ExecJs(web_contents, ""));
#else
  SimulateMouseClickAndWait(web_contents);
#endif
}

void SimulateMouseClickAndWait(WebContents* web_contents) {
  WaitForHitTestData(web_contents->GetPrimaryMainFrame());
  UserActivationObserver observer(web_contents,
                                  web_contents->GetPrimaryMainFrame());
  SimulateMouseClick(web_contents, 0, blink::WebMouseEvent::Button::kLeft);
  observer.Wait();
}

TpcBlockingBrowserClient::TpcBlockingBrowserClient() = default;
TpcBlockingBrowserClient::~TpcBlockingBrowserClient() = default;

bool TpcBlockingBrowserClient::IsFullCookieAccessAllowed(
    BrowserContext* browser_context,
    WebContents* web_contents,
    const GURL& url,
    const blink::StorageKey& storage_key,
    net::CookieSettingOverrides overrides) {
  return IsFullCookieAccessAllowed(url, storage_key.ToNetSiteForCookies(),
                                   storage_key.origin(), overrides,
                                   storage_key.ToCookiePartitionKey());
}

void TpcBlockingBrowserClient::GrantCookieAccessDueToHeuristic(
    BrowserContext* browser_context,
    const net::SchemefulSite& top_frame_site,
    const net::SchemefulSite& accessing_site,
    base::TimeDelta ttl,
    bool ignore_schemes) {
  ContentSettingsPattern primary_pattern =
      ContentSettingsPattern::FromURLToSchemefulSitePattern(
          accessing_site.GetURL());
  ContentSettingsPattern secondary_pattern =
      ContentSettingsPattern::FromURLToSchemefulSitePattern(
          top_frame_site.GetURL());
  if (ignore_schemes) {
    primary_pattern =
        ContentSettingsPattern::ToHostOnlyPattern(primary_pattern);
    secondary_pattern =
        ContentSettingsPattern::ToHostOnlyPattern(secondary_pattern);
  }
  tpc_content_settings_.SetValue(primary_pattern, secondary_pattern,
                                 base::Value(CONTENT_SETTING_ALLOW),
                                 /*metadata=*/{});
}

bool TpcBlockingBrowserClient::AreThirdPartyCookiesGenerallyAllowed(
    BrowserContext* browser_context,
    WebContents* web_contents) {
  return !block_3pcs_;
}

bool TpcBlockingBrowserClient::ShouldBtmDeleteInteractionRecords(
    uint64_t remove_mask) {
  return remove_mask & TpcBlockingBrowserClient::DATA_TYPE_HISTORY;
}

void TpcBlockingBrowserClient::AllowThirdPartyCookiesOnSite(const GURL& url) {
  tpc_content_settings_.SetValue(
      ContentSettingsPattern::Wildcard(),
      ContentSettingsPattern::FromURLToSchemefulSitePattern(url),
      base::Value(CONTENT_SETTING_ALLOW), /*metadata=*/{});
}

void TpcBlockingBrowserClient::GrantCookieAccessTo3pSite(const GURL& url) {
  tpc_content_settings_.SetValue(
      ContentSettingsPattern::FromURLToSchemefulSitePattern(url),
      ContentSettingsPattern::Wildcard(), base::Value(CONTENT_SETTING_ALLOW),
      /*metadata=*/{});
}

void TpcBlockingBrowserClient::BlockThirdPartyCookiesOnSite(const GURL& url) {
  tpc_content_settings_.SetValue(
      ContentSettingsPattern::Wildcard(),
      ContentSettingsPattern::FromURLToSchemefulSitePattern(url),
      base::Value(CONTENT_SETTING_BLOCK), /*metadata=*/{});
}

void TpcBlockingBrowserClient::BlockThirdPartyCookies(
    const GURL& url,
    const GURL& first_party_url) {
  tpc_content_settings_.SetValue(
      ContentSettingsPattern::FromURLToSchemefulSitePattern(url),
      ContentSettingsPattern::FromURLToSchemefulSitePattern(first_party_url),
      base::Value(CONTENT_SETTING_BLOCK), /*metadata=*/{});
}

// Overrides for content_settings::CookieSettingsBase

bool TpcBlockingBrowserClient::ShouldIgnoreSameSiteRestrictions(
    const GURL& url,
    const net::SiteForCookies& site_for_cookies) const {
  return false;
}

ContentSetting TpcBlockingBrowserClient::GetContentSetting(
    const GURL& primary_url,
    const GURL& secondary_url,
    ContentSettingsType content_type,
    content_settings::SettingInfo* info) const {
  if (content_type != ContentSettingsType::COOKIES) {
    return CONTENT_SETTING_DEFAULT;
  }

  const content_settings::RuleEntry* rule_entry =
      tpc_content_settings_.Find(primary_url, secondary_url);
  if (rule_entry == nullptr) {
    if (info) {
      info->primary_pattern = ContentSettingsPattern::Wildcard();
      info->secondary_pattern = ContentSettingsPattern::Wildcard();
    }
    // By default we'll allow cookies. Blocking by default will override any 3PC
    // exemption settings.
    return CONTENT_SETTING_ALLOW;
  }
  if (info) {
    info->primary_pattern = rule_entry->first.primary_pattern;
    info->secondary_pattern = rule_entry->first.secondary_pattern;
  }
  return content_settings::ValueToContentSetting(rule_entry->second.value);
}

bool TpcBlockingBrowserClient::ShouldAlwaysAllowCookies(
    const GURL& url,
    const GURL& first_party_url) const {
  return false;
}

bool TpcBlockingBrowserClient::ShouldBlockThirdPartyCookies(
    base::optional_ref<const url::Origin> top_frame_origin,
    net::CookieSettingOverrides overrides) const {
  return block_3pcs_;
}

bool TpcBlockingBrowserClient::MitigationsEnabledFor3pcd() const {
  return false;
}

bool TpcBlockingBrowserClient::IsThirdPartyCookiesAllowedScheme(
    std::string_view scheme) const {
  return false;
}

PausedCookieAccessObservers::PausedCookieAccessObservers(
    NotifyCookiesAccessedCallback callback,
    PendingObserversWithContext observers)
    : CookieAccessObservers(std::move(callback)),
      pending_receivers_(std::move(observers)) {}

PausedCookieAccessObservers::~PausedCookieAccessObservers() = default;

void PausedCookieAccessObservers::Add(
    mojo::PendingReceiver<network::mojom::CookieAccessObserver> receiver,
    CookieAccessDetails::Source source) {
  pending_receivers_.emplace_back(std::move(receiver), source);
}

PausedCookieAccessObservers::PendingObserversWithContext
PausedCookieAccessObservers::TakeReceiversWithContext() {
  return std::exchange(pending_receivers_, {});
}

CookieAccessInterceptor::CookieAccessInterceptor(WebContents& web_contents)
    : WebContentsObserver(&web_contents) {}

CookieAccessInterceptor::~CookieAccessInterceptor() = default;

void CookieAccessInterceptor::DidStartNavigation(
    NavigationHandle* navigation_handle) {
  auto& request = *NavigationRequest::From(navigation_handle);

  auto observers = std::make_unique<PausedCookieAccessObservers>(
      base::BindRepeating(&NavigationRequest::NotifyCookiesAccessed,
                          // Unretained is safe here because ownership of the
                          // observers is passed to the request below.
                          base::Unretained(&request)),
      request.TakeCookieObservers());
  request.SetCookieAccessObserversForTesting(std::move(observers));
}

}  // namespace content
