// 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.

#ifndef CONTENT_BROWSER_PRELOADING_PRERENDER_PRERENDER_ATTRIBUTES_H_
#define CONTENT_BROWSER_PRELOADING_PRERENDER_PRERENDER_ATTRIBUTES_H_

#include <optional>
#include <string>

#include "content/browser/preloading/preload_pipeline_info_impl.h"
#include "content/browser/preloading/speculation_rules/speculation_rules_params.h"
#include "content/common/content_export.h"
#include "content/public/browser/frame_tree_node_id.h"
#include "content/public/browser/preload_pipeline_info.h"
#include "content/public/browser/preloading.h"
#include "content/public/browser/preloading_trigger_type.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/referrer.h"
#include "net/http/http_no_vary_search_data.h"
#include "net/http/http_request_headers.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"
#include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom.h"
#include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h"
#include "ui/base/page_transition_types.h"

namespace content {

// Records the basic attributes of a prerender request.
struct CONTENT_EXPORT PrerenderAttributes {
  // - `prerendering_url` indicates the initial URL of the prerender request.
  //    The real url might be changed during the prerendering navigation, e.g.,
  //    redirection.
  // - `initiator_render_frame_host`: the render frame host that initiates this
  //    prerender request. It could be null if the prerender is initiated by
  //    browser.
  // - `initiator_web_contents`: the web contents that the initiator render
  //    frame host belongs to. Note that `initiator_web_contents` is non-null
  //    even if `initiator_render_frame_host` is null, because the attempted
  //    prerender could be triggered by other components of a WebContents.
  PrerenderAttributes(
      const GURL& prerendering_url,
      PreloadingTriggerType trigger_type,
      const std::string& embedder_histogram_suffix,
      std::optional<SpeculationRulesParams> speculation_rules_params,
      Referrer referrer,
      std::optional<net::HttpNoVarySearchData> no_vary_search_hint,
      RenderFrameHost* initiator_render_frame_host,
      base::WeakPtr<WebContents> initiator_web_contents,
      ui::PageTransition transition_type,
      bool should_warm_up_compositor,
      bool should_prepare_paint_tree,
      blink::mojom::SpeculationAction prerender_action_type,
      base::RepeatingCallback<bool(const GURL&,
                                   const std::optional<UrlMatchType>&)>
          url_match_predicate,
      base::RepeatingCallback<void(NavigationHandle&)>
          prerender_navigation_handle_callback,
      scoped_refptr<PreloadPipelineInfoImpl> preload_pipeline_info,
      bool allow_reuse,
      bool form_submission);

  ~PrerenderAttributes();

  // Copyable and movable.
  PrerenderAttributes(const PrerenderAttributes&);
  PrerenderAttributes& operator=(const PrerenderAttributes&);
  PrerenderAttributes(PrerenderAttributes&&) noexcept;
  PrerenderAttributes& operator=(PrerenderAttributes&&) noexcept;

  bool IsBrowserInitiated() const { return !initiator_origin.has_value(); }

  std::optional<blink::mojom::SpeculationTargetHint> GetTargetHint() const;
  std::optional<blink::mojom::SpeculationEagerness> GetEagerness() const;
  std::optional<SpeculationRulesTags> GetTags() const;

  GURL prerendering_url;

  PreloadingTriggerType trigger_type;

  // Used for kEmbedder trigger type to avoid exposing information of embedders
  // to content/. Only used for metrics.
  std::string embedder_histogram_suffix;

  // This is std::nullopt when prerendering is initiated by browser.
  std::optional<SpeculationRulesParams> speculation_rules_params;

  Referrer referrer;

#if BUILDFLAG(IS_ANDROID)
  // Additional headers to be attached to prerendering navigation. Currently
  // this is used only for Android WebView.
  net::HttpRequestHeaders additional_headers;
#endif  // BUILDFLAG(IS_ANDROID)

  // Records the No-Vary-Search hint of the corresponding speculation rule.
  // This is std::nullopt when No-Vary-Search hint is not specified.
  std::optional<net::HttpNoVarySearchData> no_vary_search_hint;

  // This is std::nullopt when prerendering is initiated by the browser
  // (not by a renderer using Speculation Rules API).
  std::optional<url::Origin> initiator_origin;

  // This is ChildProcessHost::kInvalidUniqueID when prerendering is initiated
  // by the browser.
  int initiator_process_id = ChildProcessHost::kInvalidUniqueID;

  // This hosts a primary page that is initiating this prerender attempt.
  base::WeakPtr<WebContents> initiator_web_contents;

  // This is std::nullopt when prerendering is initiated by the browser.
  std::optional<blink::LocalFrameToken> initiator_frame_token;

  // This is invalid when prerendering is initiated by the browser.
  FrameTreeNodeId initiator_frame_tree_node_id;

  // This is ukm::kInvalidSourceId when prerendering is initiated by the
  // browser.
  ukm::SourceId initiator_ukm_id = ukm::kInvalidSourceId;

  ui::PageTransition transition_type;

  // If true, warms up compositor on a certain loading event of prerender
  // initial navigation. Please see crbug.com/41496019 and comments on
  // Page::should_warm_up_compositor_on_prerender_ for more details.
  bool should_warm_up_compositor = false;

  // Whether to dry run paint phase to pre-build a paint tree for the page, so
  // then the intermediate result can be reused after activation.
  bool should_prepare_paint_tree = false;

  // The action type of the speculation rule that triggered this prerender.
  blink::mojom::SpeculationAction prerender_action_type;

  // If the caller wants to override the default holdback processing, they can
  // set this. Otherwise, it will be computed as part of
  // PrerenderHostRegistry::CreateAndStartHost.
  PreloadingHoldbackStatus holdback_status_override =
      PreloadingHoldbackStatus::kUnspecified;

  // Triggers can specify their own predicate judging whether two URLs are
  // considered as pointing to the same destination. The URLs must be in
  // same-origin.
  base::RepeatingCallback<bool(const GURL&, const std::optional<UrlMatchType>&)>
      url_match_predicate;

  base::RepeatingCallback<void(NavigationHandle&)>
      prerender_navigation_handle_callback;

  // Information of preload pipeline that this prerender belongs to.
  scoped_refptr<PreloadPipelineInfoImpl> preload_pipeline_info;

  // Whether the created prerender host can be reused for future navigations.
  bool allow_reuse = false;

  // Whether the created prerender is a GET form submission navigation.
  bool form_submission = false;

  // Enabled the feature for the speculation rules sent from the
  // renderer process.
  // TODO(https://crbug.com/440387014): Remove this field once OT is finished.
  bool enable_cross_origin_prerender_iframes = false;

  // This is std::nullopt when prerendering is initiated by the browser.
  std::optional<base::UnguessableToken> initiator_devtools_navigation_token;

  // Serialises this struct into a trace.
  void WriteIntoTrace(perfetto::TracedValue trace_context) const;

#if BUILDFLAG(ARKWEB_NETWORK_LOAD)
  std::string extra_headers;
#endif
};

}  // namespace content

#endif  // CONTENT_BROWSER_PRELOADING_PRERENDER_PRERENDER_ATTRIBUTES_H_