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

#include "chrome/browser/renderer_host/chrome_navigation_ui_data.h"

#include "build/build_config.h"
#include "chrome/browser/actor/actor_keyed_service.h"
#include "chrome/browser/actor/actor_task.h"
#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
#include "chrome/browser/profiles/profile.h"
#include "components/actor/core/task_id.h"
#include "components/no_state_prefetch/browser/no_state_prefetch_contents.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
#include "extensions/buildflags/buildflags.h"

#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/common/constants.h"
#endif

namespace {
actor::TaskId GetActorTaskId(content::WebContents& web_contents) {
  if (auto* actor_keyed_service =
          actor::ActorKeyedService::Get(web_contents.GetBrowserContext())) {
    if (auto* task = actor_keyed_service->GetActingActorTaskForWebContents(
            &web_contents)) {
      return task->id();
    }
  }
  return actor::TaskId();
}
}  // namespace

ChromeNavigationUIData::ChromeNavigationUIData() = default;

ChromeNavigationUIData::ChromeNavigationUIData(
    content::NavigationHandle* navigation_handle) {
  auto* web_contents = navigation_handle->GetWebContents();
#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
  int tab_id = extension_misc::kUnknownTabId;
  int window_id = extension_misc::kUnknownWindowId;
  // The browser client can be null in unittests.
  if (extensions::ExtensionsBrowserClient::Get()) {
    extensions::ExtensionsBrowserClient::Get()->GetTabAndWindowIdForWebContents(
        web_contents, &tab_id, &window_id);
  }
  extension_data_ = std::make_unique<extensions::ExtensionNavigationUIData>(
      navigation_handle, tab_id, window_id);
#endif

  auto* no_state_prefetch_contents =
      prerender::ChromeNoStatePrefetchContentsDelegate::FromWebContents(
          web_contents);
  if (no_state_prefetch_contents) {
    is_no_state_prefetching_ = true;
  }

  actor_task_id_ = GetActorTaskId(*web_contents);
}

ChromeNavigationUIData::~ChromeNavigationUIData() = default;

// static
std::unique_ptr<ChromeNavigationUIData>
ChromeNavigationUIData::CreateForMainFrameNavigation(
    content::WebContents* web_contents,
    bool is_using_https_as_default_scheme,
    bool force_no_https_upgrade) {
  auto navigation_ui_data = std::make_unique<ChromeNavigationUIData>();
  navigation_ui_data->is_using_https_as_default_scheme_ =
      is_using_https_as_default_scheme;
  navigation_ui_data->force_no_https_upgrade_ = force_no_https_upgrade;

#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
  int tab_id = extension_misc::kUnknownTabId;
  int window_id = extension_misc::kUnknownWindowId;
  // The browser client can be null in unittests.
  if (extensions::ExtensionsBrowserClient::Get()) {
    extensions::ExtensionsBrowserClient::Get()->GetTabAndWindowIdForWebContents(
        web_contents, &tab_id, &window_id);
  }

  navigation_ui_data->extension_data_ =
      extensions::ExtensionNavigationUIData::CreateForMainFrameNavigation(
          web_contents, tab_id, window_id);
#endif

  navigation_ui_data->actor_task_id_ = GetActorTaskId(*web_contents);

  return navigation_ui_data;
}

std::unique_ptr<content::NavigationUIData> ChromeNavigationUIData::Clone() {
  auto copy = std::make_unique<ChromeNavigationUIData>();

  copy->is_using_https_as_default_scheme_ = is_using_https_as_default_scheme_;
  copy->force_no_https_upgrade_ = force_no_https_upgrade_;

#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
  if (extension_data_) {
    copy->SetExtensionNavigationUIData(extension_data_->DeepCopy());
  }
#endif

#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
  if (offline_page_data_) {
    copy->SetOfflinePageNavigationUIData(offline_page_data_->DeepCopy());
  }
#endif

  copy->is_no_state_prefetching_ = is_no_state_prefetching_;
  copy->bookmark_id_ = bookmark_id_;
#if BUILDFLAG(IS_ANDROID)
  copy->twa_launch_token_ = twa_launch_token_;
#endif
  copy->actor_task_id_ = actor_task_id_;
  copy->navigation_initiated_from_sync_ = navigation_initiated_from_sync_;

  return std::move(copy);
}

#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
void ChromeNavigationUIData::SetExtensionNavigationUIData(
    std::unique_ptr<extensions::ExtensionNavigationUIData> extension_data) {
  extension_data_ = std::move(extension_data);
}
#endif

#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
void ChromeNavigationUIData::SetOfflinePageNavigationUIData(
    std::unique_ptr<offline_pages::OfflinePageNavigationUIData>
        offline_page_data) {
  offline_page_data_ = std::move(offline_page_data);
}
#endif
