// Copyright 2021 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/renderer_host/page_impl.h"

#include "base/barrier_closure.h"
#include "base/feature_list.h"
#include "base/i18n/character_encoding.h"
#include "base/trace_event/optional_trace_event.h"
#include "cc/base/features.h"
#include "cc/input/browser_controls_offset_tag_modifications.h"
#include "content/browser/manifest/manifest_manager_host.h"
#include "content/browser/preloading/prerender/prerender_features.h"
#include "content/browser/preloading/prerender/prerender_host.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/page_delegate.h"
#include "content/browser/renderer_host/render_frame_host_delegate.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_frame_proxy_host.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/shared_storage/shared_storage_features.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/peak_gpu_memory_tracker_factory.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/common/content_client.h"
#include "services/viz/public/mojom/compositing/offset_tag.mojom.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/loader/loader_constants.h"
#include "third_party/blink/public/common/shared_storage/shared_storage_utils.h"
#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
#include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom.h"
#include "third_party/perfetto/include/perfetto/tracing/traced_value.h"

namespace content {

PageImpl::PageImpl(RenderFrameHostImpl& rfh, PageDelegate& delegate)
    : main_document_(rfh),
      delegate_(delegate),
      text_autosizer_page_info_({0, 0, 1.f}) {
  if (base::FeatureList::IsEnabled(features::kSharedStorageSelectURLLimit)) {
    select_url_overall_budget_ =
        features::kSharedStorageSelectURLBitBudgetPerPageLoad.Get();
    select_url_max_bits_per_site_ =
        features::kSharedStorageSelectURLBitBudgetPerSitePerPageLoad.Get();
  }

#if BUILDFLAG(IS_ANDROID)
  page_proxy_ = std::make_unique<PageProxy>(this);
#endif
}

PageImpl::~PageImpl() {
#if BUILDFLAG(IS_ANDROID)
  page_proxy_->WillDeletePage(GetMainDocument().IsInLifecycleState(
      RenderFrameHost::LifecycleState::kPrerendering));
#endif

  // As SupportsUserData is a base class of PageImpl, Page members will be
  // destroyed before running ~SupportsUserData, which would delete the
  // associated PageUserData objects. Avoid this by calling ClearAllUserData
  // explicitly here to ensure that the PageUserData destructors can access
  // associated Page object.
  ClearAllUserData();

  // If we still have a PeakGpuMemoryTracker, then the loading it was observing
  // never completed. Cancel its callback so that we don't report partial
  // loads to UMA.
  CancelLoadingMemoryTracker();
}

const std::optional<GURL>& PageImpl::GetManifestUrl() const {
  return manifest_url_;
}

void PageImpl::GetManifest(GetManifestCallback callback) {
  ManifestManagerHost* manifest_manager_host =
      ManifestManagerHost::GetOrCreateForPage(*this);
  manifest_manager_host->GetManifest(std::move(callback));
}

bool PageImpl::IsPrimary() const {
  return main_document_->IsInPrimaryMainFrame();
}

void PageImpl::UpdateManifestUrl(const GURL& manifest_url) {
  manifest_url_ = manifest_url;

  // If |main_document_| is not active, the notification is sent on the page
  // activation.
  if (!main_document_->IsActive()) {
    return;
  }

  main_document_->delegate()->OnManifestUrlChanged(*this);
}

void PageImpl::WriteIntoTrace(perfetto::TracedValue context) {
  auto dict = std::move(context).WriteDictionary();
  dict.Add("main_document", *main_document_);
}

base::WeakPtr<Page> PageImpl::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

base::WeakPtr<PageImpl> PageImpl::GetWeakPtrImpl() {
  return weak_factory_.GetWeakPtr();
}

bool PageImpl::IsPageScaleFactorOne() {
  return GetPageScaleFactor() == 1.f;
}

const std::string& PageImpl::GetContentsMimeType() const {
  return contents_mime_type_;
}

void PageImpl::SetResizableForTesting(std::optional<bool> resizable) {
  SetResizable(resizable);
}

void PageImpl::SetResizable(std::optional<bool> resizable) {
  resizable_ = resizable;
  delegate_->OnWebApiWindowResizableChanged();
}

std::optional<bool> PageImpl::GetResizable() {
  return resizable_;
}

#if BUILDFLAG(IS_ANDROID)
const base::android::JavaRef<jobject>& PageImpl::GetJavaPage() {
  return page_proxy_->java_page();
}
#endif

void PageImpl::OnFirstVisuallyNonEmptyPaint() {
  did_first_visually_non_empty_paint_ = true;
  delegate_->OnFirstVisuallyNonEmptyPaint(*this);
}

void PageImpl::OnThemeColorChanged(const std::optional<SkColor>& theme_color) {
  main_document_theme_color_ = theme_color;
  delegate_->OnThemeColorChanged(*this);
}

void PageImpl::DidChangeBackgroundColor(SkColor4f background_color,
                                        bool color_adjust) {
  // TODO(aaronhk): This should remain an SkColor4f
  main_document_background_color_ = background_color.toSkColor();
  delegate_->OnBackgroundColorChanged(*this);
  if (color_adjust) {
    // <meta name="color-scheme" content="dark"> may pass the dark canvas
    // background before the first paint in order to avoid flashing the white
    // background in between loading documents. If we perform a navigation
    // within the same renderer process, we keep the content background from the
    // previous page while rendering is blocked in the new page, but for cross
    // process navigations we would paint the default background (typically
    // white) while the rendering is blocked.
    main_document_->GetRenderWidgetHost()->GetView()->SetContentBackgroundColor(
        background_color.toSkColor());
  }
}

void PageImpl::DidInferColorScheme(
    blink::mojom::PreferredColorScheme color_scheme) {
  main_document_inferred_color_scheme_ = color_scheme;
  delegate_->DidInferColorScheme(*this);
}

void PageImpl::NotifyPageBecameCurrent() {
  if (!IsPrimary()) {
    return;
  }
  delegate_->NotifyPageBecamePrimary(*this);
}

void PageImpl::SetContentsMimeType(std::string mime_type) {
  contents_mime_type_ = std::move(mime_type);
}

void PageImpl::OnTextAutosizerPageInfoChanged(
    blink::mojom::TextAutosizerPageInfoPtr page_info) {
  OPTIONAL_TRACE_EVENT0("content", "PageImpl::OnTextAutosizerPageInfoChanged");

  // Keep a copy of `page_info` in case we create a new `blink::WebView` before
  // the next update, so that the PageImpl can tell the newly created
  // `blink::WebView` about the autosizer info.
  text_autosizer_page_info_.main_frame_width = page_info->main_frame_width;
  text_autosizer_page_info_.main_frame_layout_width =
      page_info->main_frame_layout_width;
  text_autosizer_page_info_.device_scale_adjustment =
      page_info->device_scale_adjustment;

  auto remote_frames_broadcast_callback =
      [this](RenderFrameProxyHost* proxy_host) {
        DCHECK(proxy_host);
        proxy_host->GetAssociatedRemoteMainFrame()->UpdateTextAutosizerPageInfo(
            text_autosizer_page_info_.Clone());
      };

  {
    TRACE_EVENT("navigation",
                "PageImpl::OnTextAutosizerPageInfoChanged broadcast");
    main_document_->frame_tree()
        ->root()
        ->render_manager()
        ->ExecuteRemoteFramesBroadcastMethod(
            std::move(remote_frames_broadcast_callback),
            main_document_->GetSiteInstance()->group());
  }
}

void PageImpl::SetActivationStartTime(base::TimeTicks activation_start) {
  CHECK(!activation_start_time_);
  activation_start_time_ = activation_start;
}

void PageImpl::NotifyCrossOriginSubframePrerenderIsAllowed() {
  is_cross_origin_subframe_prerender_allowed_ = true;
}

void PageImpl::Activate(
    ActivationType type,
    StoredPage::RenderViewHostImplSafeRefSet& render_view_hosts,
    std::optional<blink::ViewTransitionState> view_transition_state,
    base::OnceCallback<void(base::TimeTicks)> completion_callback) {
  TRACE_EVENT1("navigation", "PageImpl::Activate", "activation_type", type);

  // SetActivationStartTime() should be called first as the value is used in
  // the callback below.
  CHECK(activation_start_time_.has_value());

  base::OnceClosure did_activate_render_views = base::BindOnce(
      &PageImpl::DidActivateAllRenderViewsForPrerenderingOrPreview,
      weak_factory_.GetWeakPtr(), std::move(completion_callback));

  base::RepeatingClosure barrier = base::BarrierClosure(
      render_view_hosts.size(), std::move(did_activate_render_views));
  bool view_transition_state_consumed = false;
  for (const auto& rvh : render_view_hosts) {
    auto params = blink::mojom::PrerenderPageActivationParams::New();

    const bool is_main_document = main_document_->GetRenderViewHost() == &*rvh;
    if (is_main_document) {
      // These RenderViews still need to know about activation so their
      // documents are created in the non-prerendered state once their
      // navigation is committed.
      // Note that there cannot be a use-after-move since the if condition
      // should be true at most once.
      CHECK(!view_transition_state_consumed);
      params->view_transition_state = std::move(view_transition_state);
      view_transition_state_consumed = true;
    }

    const bool should_send_activation_start = [&]() {
      // For prerendering activation, send activation_start only to the
      // RenderViewHost for the main frame to avoid sending the info
      // cross-origin. Only this RenderViewHost needs the info, as we expect
      // the other RenderViewHosts are made for cross-origin iframes which
      // have not yet loaded their document. To the renderer, it just looks
      // like an ongoing navigation is happening in the frame and has not yet
      // committed.
      if (is_main_document) {
        return true;
      }

      // Even cross-origin, we allow if the main document has the special
      // header. See PrerenderHost::AllowCrossOriginSubframeNavigation() for
      // detail.
      if (base::FeatureList::IsEnabled(
              ::features::kPrerender2CrossOriginIframes) &&
          type == ActivationType::kPrerendering &&
          is_cross_origin_subframe_prerender_allowed_) {
        return true;
      }

      // For preview activation, send activation_start to all RenderViewHosts
      // as preview loads cross-origin subframes under the capability control,
      // and activation_start time is meaningful there.
      if (type == ActivationType::kPreview) {
        return true;
      }
      return false;
    }();
    if (should_send_activation_start) {
      params->activation_start = *activation_start_time_;
    }

    // For preview activation, there is no way to activate the previewed page
    // other than with a user action, or testing only methods.
    params->was_user_activated =
        (main_document_->frame_tree_node()
             ->has_received_user_gesture_before_nav() ||
         type == ActivationType::kPreview)
            ? blink::mojom::WasActivatedOption::kYes
            : blink::mojom::WasActivatedOption::kNo;
    rvh->ActivatePrerenderedPage(std::move(params), barrier);
  }

  // Prepare each RenderFrameHostImpl in this Page for activation.
  main_document_->ForEachRenderFrameHostImplIncludingSpeculative(
      [](RenderFrameHostImpl* rfh) {
        rfh->RendererWillActivateForPrerenderingOrPreview();
      });
}

void PageImpl::MaybeDispatchLoadEventsOnPrerenderActivation() {
  DCHECK(IsPrimary());

  // Dispatch LoadProgressChanged notification on activation with the
  // prerender last load progress value if the value is not equal to
  // blink::kFinalLoadProgress, whose notification is dispatched during call
  // to DidStopLoading.
  if (load_progress() != blink::kFinalLoadProgress) {
    main_document_->DidChangeLoadProgress(load_progress());
  }

  // Dispatch PrimaryMainDocumentElementAvailable before dispatching following
  // load complete events.
  if (is_main_document_element_available()) {
    main_document_->MainDocumentElementAvailable(uses_temporary_zoom_level());
  }

  main_document_->ForEachRenderFrameHostImpl(
      &RenderFrameHostImpl::MaybeDispatchDOMContentLoadedOnPrerenderActivation);

  if (is_on_load_completed_in_main_document()) {
    main_document_->DocumentOnLoadCompleted();
  }

  if (first_contentful_paint_in_main_document_load_time_) {
    main_document_->NotifyFirstContentfulPaint();
  }

  main_document_->ForEachRenderFrameHostImpl(
      &RenderFrameHostImpl::MaybeDispatchDidFinishLoadOnPrerenderActivation);
}

void PageImpl::DidActivateAllRenderViewsForPrerenderingOrPreview(
    base::OnceCallback<void(base::TimeTicks)> completion_callback) {
  TRACE_EVENT0("navigation",
               "PageImpl::DidActivateAllRenderViewsForPrerendering");

  // Tell each RenderFrameHostImpl in this Page that activation finished.
  main_document_->ForEachRenderFrameHostImplIncludingSpeculative(
      [this](RenderFrameHostImpl* rfh) {
        if (&rfh->GetPage() != this) {
          return;
        }
        rfh->RendererDidActivateForPrerendering();
      });
  CHECK(activation_start_time_.has_value());
  std::move(completion_callback).Run(*activation_start_time_);
}

RenderFrameHost& PageImpl::GetMainDocumentHelper() {
  return *main_document_;
}

RenderFrameHostImpl& PageImpl::GetMainDocument() const {
  return *main_document_;
}

void PageImpl::UpdateBrowserControlsState(
    cc::BrowserControlsState constraints,
    cc::BrowserControlsState current,
    bool animate,
    const std::optional<cc::BrowserControlsOffsetTagModifications>&
        offset_tag_modifications) {
  // TODO(crbug.com/40159655): Asking for the LocalMainFrame interface
  // before the RenderFrame is created is racy.
  if (!GetMainDocument().IsRenderFrameLive()) {
    return;
  }

  GetMainDocument().GetRenderWidgetHost()->UpdateBrowserControlsState(
      constraints, current, animate, offset_tag_modifications);
}

float PageImpl::GetPageScaleFactor() const {
  return GetMainDocument().GetPageScaleFactor();
}

void PageImpl::UpdateEncoding(const std::string& encoding_name) {
  if (encoding_name == last_reported_encoding_) {
    return;
  }
  last_reported_encoding_ = encoding_name;

  canonical_encoding_ =
      base::GetCanonicalEncodingNameByAliasName(encoding_name);
}

void PageImpl::NotifyVirtualKeyboardOverlayRect(
    const gfx::Rect& keyboard_rect) {
  // TODO(crbug.com/40222405): send notification to outer frames if
  // needed.
  DCHECK_EQ(virtual_keyboard_mode(),
            ui::mojom::VirtualKeyboardMode::kOverlaysContent);
  GetMainDocument().GetAssociatedLocalFrame()->NotifyVirtualKeyboardOverlayRect(
      keyboard_rect);
}

void PageImpl::ShowInterestInElement(int nodeID) {
  GetMainDocument().GetAssociatedLocalFrame()->ShowInterestInElement(nodeID);
}

void PageImpl::SetVirtualKeyboardMode(ui::mojom::VirtualKeyboardMode mode) {
  if (virtual_keyboard_mode_ == mode) {
    return;
  }

  virtual_keyboard_mode_ = mode;

  delegate_->OnVirtualKeyboardModeChanged(*this);
}

base::flat_map<std::string, std::string> PageImpl::GetKeyboardLayoutMap() {
  return GetMainDocument().GetRenderWidgetHost()->GetKeyboardLayoutMap();
}

int32_t PageImpl::GetSavedQueryResultIndexOrStoreCallback(
    const url::Origin& origin,
    const GURL& script_url,
    const std::string& operation_name,
    const std::u16string& query_name,
    base::OnceCallback<void(uint32_t)> callback) {
  auto key = std::make_tuple(origin, script_url, operation_name, query_name);
  auto it = select_url_saved_query_index_results_.find(key);
  if (it == select_url_saved_query_index_results_.end()) {
    select_url_saved_query_index_results_[key] = SharedStorageSavedQueryData();
    // The result index will be determined by running the registered worklet
    // operation upon return to the SHaredStorageWorkletHost.
    return -2;
  }
  if (it->second.index == -1) {
    // The result index will be determined when a previously initiated worklet
    // operation finishes running. We save a callback that will notify us of the
    // result.
    it->second.callbacks.push(std::move(callback));
    return -1;
  }
  // The result index has been stored from a previously resolved worklet
  // operation.
  return it->second.index;
}

void PageImpl::SetSavedQueryResultIndexAndRunCallbacks(
    const url::Origin& origin,
    const GURL& script_url,
    const std::string& operation_name,
    const std::u16string& query_name,
    uint32_t index) {
  auto key = std::make_tuple(origin, script_url, operation_name, query_name);
  auto it = select_url_saved_query_index_results_.find(key);
  CHECK(it != select_url_saved_query_index_results_.end());
  CHECK_EQ(it->second.index, -1L);
  it->second.index = index;
  while (!it->second.callbacks.empty()) {
    std::move(it->second.callbacks.front()).Run(index);
    it->second.callbacks.pop();
  }
}

blink::SharedStorageSelectUrlBudgetStatus
PageImpl::CheckAndMaybeDebitSelectURLBudgets(const net::SchemefulSite& site,
                                             double bits_to_charge) {
  if (!select_url_overall_budget_) {
    // The limits are not enabled.
    return blink::SharedStorageSelectUrlBudgetStatus::kSufficientBudget;
  }

  // Return insufficient if there is insufficient overall budget.
  if (bits_to_charge > select_url_overall_budget_.value()) {
    GetContentClient()->browser()->LogWebFeatureForCurrentPage(
        &GetMainDocument(),
        blink::mojom::WebFeature::
            kSharedStorageAPI_SelectURLOverallPageloadBudgetInsufficient);
    return blink::SharedStorageSelectUrlBudgetStatus::
        kInsufficientOverallPageloadBudget;
  }

  DCHECK(select_url_max_bits_per_site_);

  // Return false if the max bits per site is set to a value smaller than the
  // current bits to charge.
  if (bits_to_charge > select_url_max_bits_per_site_.value()) {
    return blink::SharedStorageSelectUrlBudgetStatus::
        kInsufficientSitePageloadBudget;
  }

  // Charge the per-site budget or return insufficient if there is not enough.
  auto it = select_url_per_site_budget_.find(site);
  if (it == select_url_per_site_budget_.end()) {
    select_url_per_site_budget_[site] =
        select_url_max_bits_per_site_.value() - bits_to_charge;
  } else if (bits_to_charge > it->second) {
    // There is insufficient per-site budget remaining.
    return blink::SharedStorageSelectUrlBudgetStatus::
        kInsufficientSitePageloadBudget;
  } else {
    it->second -= bits_to_charge;
  }

  // Charge the overall budget.
  select_url_overall_budget_.value() -= bits_to_charge;
  return blink::SharedStorageSelectUrlBudgetStatus::kSufficientBudget;
}

void PageImpl::TakeLoadingMemoryTracker(NavigationRequest* request) {
  CHECK(IsPrimary());
  loading_memory_tracker_ = request->TakePeakGpuMemoryTracker();
}

void PageImpl::ResetLoadingMemoryTracker() {
  CHECK(IsPrimary());
  if (loading_memory_tracker_) {
    loading_memory_tracker_.reset();
  }
}

void PageImpl::CancelLoadingMemoryTracker() {
  if (loading_memory_tracker_) {
    loading_memory_tracker_->Cancel();
    loading_memory_tracker_.reset();
  }
}

void PageImpl::SetLastCommitParams(
    mojom::DidCommitProvisionalLoadParamsPtr commit_params) {
  CHECK(GetMainDocument().IsOutermostMainFrame());
  last_commit_params_ = std::move(commit_params);
}

mojom::DidCommitProvisionalLoadParamsPtr PageImpl::TakeLastCommitParams() {
  CHECK(GetMainDocument().IsOutermostMainFrame());
  return std::move(last_commit_params_);
}

}  // namespace content
