chromium/third_party/blink/public/mojom/loader/navigation_predictor.mojom

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

module blink.mojom;

import "mojo/public/mojom/base/time.mojom";
import "url/mojom/url.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
import "third_party/blink/public/mojom/preloading/anchor_element_interaction_host.mojom";

// This mojom file is for user navigation prediction experiment, using anchor
// element metrics gathered from the renderer process. See crbug.com/850624.

// Struct holding metrics of an anchor element extracted in the renderer
// process.
struct AnchorElementMetrics {
  // An ID assigned to this Anchor. This is the hash of the anchor's pointer
  // value. This means module hash collisions, anchor IDs should be unique for
  // a given page load and given renderer, but are not stable across page loads
  // (loading the same page twice will give two different IDs for the same
  // anchor element). If anchor IDs from different renderers are combined on the
  // browser site (for the same page load), then the browser has to be careful
  // about collisions. Since we currently do not report anchor elements from
  // OOPIFs, this is not a concern at this point.
  uint32 anchor_id;

  // The ratio between the absolute clickable region area of an anchor
  // element, and the viewport area. The value is capped at 1.
  float ratio_area;

  // The distance between the top of the clickable region of an anchor
  // element and the top edge of the visible region, divided by the viewport
  // height.
  float ratio_distance_top_to_visible_top;

  // The distance between the top of the clickable region of an anchor element
  // and the top edge of the root frame, divided by the viewport height.
  float ratio_distance_root_top;

  // Whether the anchor element is within an iframe.
  bool is_in_iframe;

  // Whether the anchor element contains an image element.
  bool contains_image;

  // Whether the link target has the same host as the root document.
  bool is_same_host;

  // Whether the target URL and the host URL only differ by one number,
  // and the number in target URL equals the one in host URL plus one.
  bool is_url_incremented_by_one;

  // Whether the anchor element has an immediate sibling that is a text node.
  bool has_text_sibling;

  // The font size in pixels of the anchor element according to its computed
  // style.
  uint32 font_size_px;

  // The font weight of the anchor element according to its computed style.
  uint32 font_weight;

  // The target URL (href) specified by the anchor element. URLs sent from a
  // renderer process are not trusted, however it is intended here since it
  // is only used for metrics calculation.
  url.mojom.Url target_url;

  // The size of the viewport at the time the anchor element was created.
  gfx.mojom.Size viewport_size;
};

struct AnchorElementClick {
  // The ID of the anchor that was clicked.
  uint32 anchor_id;

  // The URL of the anchor when it was clicked.
  url.mojom.Url target_url;

  // The time between navigation start of the anchor element's root document and
  // the time the user clicked on the link.
  mojo_base.mojom.TimeDelta navigation_start_to_click;
};

struct AnchorElementPointerDataOnHoverTimerFired {
  // The ID of the anchor that was clicked.
  uint32 anchor_id;

  // The pointer data including mouse velocity and acceleration.
  blink.mojom.AnchorElementPointerData pointer_data;
};

struct AnchorElementEnteredViewport {
  // The ID of the anchor that entered the viewport.
  uint32 anchor_id;

  // The time between navigation start of the anchor element's root document and
  // the time the anchor element entered the viewport.
  mojo_base.mojom.TimeDelta navigation_start_to_entered_viewport;
};

struct AnchorElementLeftViewport {
  // The ID of the anchor that exited the viewport.
  uint32 anchor_id;

  // The time between the moment the anchor element entered the viewport and the
  // moment it left the viewport.
  mojo_base.mojom.TimeDelta time_in_viewport;
};

struct AnchorElementPointerOver {
  // The ID of the anchor that pointer started hovering over it.
  uint32 anchor_id;

  // The time between navigation start of the anchor element's root document and
  // the time the pointer started hovering over the anchor element event.
  mojo_base.mojom.TimeDelta navigation_start_to_pointer_over;
};

struct AnchorElementPointerOut {
  // The ID of the anchor that pointer hovered over it.
  uint32 anchor_id;

  // The time interval pointer was hovering over the anchor element.
  mojo_base.mojom.TimeDelta hover_dwell_time;
};

// Represents different user interaction types used for computing preloading ML
// model inputs..
enum AnchorElementUserInteractionEventForMLModelType {
  kPointerOver,
  kPointerOut,
  kEnteredViewport,
  kLeftViewport,
  kUnknown,
};

struct AnchorElementPointerEventForMLModel {
  // The ID of the anchor that pointer hovered over it.
  uint32 anchor_id;

  // Whether the point event triggered by mouse or not.
  bool is_mouse;

  // User interaction event type.
  AnchorElementUserInteractionEventForMLModelType user_interaction_event_type;
};

struct AnchorElementPointerDown {
  // The ID of the anchor that pointer down event happened over it.
  uint32 anchor_id;

  // The time between navigation start of the anchor element's root document and
  // the time the pointer down event happened over the anchor element event.
  mojo_base.mojom.TimeDelta navigation_start_to_pointer_down;
};

struct AnchorElementPositionUpdate {
  // The ID of the anchor.
  uint32 anchor_id;

  // The vertical position of the anchor's center in the viewport (expressed as
  // a ratio of the viewport height).
  float vertical_position_ratio;

  // The vertical distance between the anchor's center and the last recorded
  // pointer down (expressed as a ratio of the screen height).
  float? distance_from_pointer_down_ratio;
};

// TODO(isaboori): It's better to move the methods that are called for all
// anchor elements and not just the down-sampled ones to a new
// `AnchorElementInteractionHost` interface.

// An interface to pass descriptive information about anchor elements from
// the renderer process to the implementation of this interface living in the
// browser process.
interface AnchorElementMetricsHost {
  // This is called when an anchor element is clicked. The renderer extracts and
  // sends |metrics| of the clicked anchor element.
  // This is called for all anchor elements.
  ReportAnchorElementClick(AnchorElementClick clicked);

  // At each layout, HTMLAnchorElements that have been newly created (since the
  // last layout) may be reported. Only elements with an HTTPS href attribute
  // that are 'visible' (they have non-empty bounding box, though they may not
  // be in the viewport) are reported. This reports various metrics about each
  // element. New HTMLAnchorElements that are not visible after the first layout
  // since their creation will never be reported. This is not ideal, but allows
  // us to avoid keeping references to elements that may never become visible.
  // `removed_elements` contains the anchor ids of anchor elements that have
  // been removed from the document since the last call to this method.
  // This is called for all anchor elements.
  ReportNewAnchorElements(array<AnchorElementMetrics> metrics,
                          array<uint32> removed_elements);

  // This is called regularly to report anchors that entered the viewport. This
  // just reports the ID of each element entering the viewport. These records
  // can be joined with the metrics reported by ReportNewAnchorElements.
  // However, it is possible that some elements reported by this RPC have not
  // previously been reported by ReportNewAnchorElements (e.g. because they were
  // not visible following the first layout after the HTMLAnchorElement was
  // created).
  // This is called only for randomly selected anchor elements that we track.
  ReportAnchorElementsEnteredViewport(
    array<AnchorElementEnteredViewport> elements);

  // This is called regularly to report anchors that left the viewport. This
  // just reports the ID of each element leaving the viewport. These records
  // can be joined with the metrics reported by
  // |ReportAnchorElementsEnteredViewport|.
  // This is called only for randomly selected anchor elements that we track.
  ReportAnchorElementsLeftViewport(array<AnchorElementLeftViewport> elements);

  // This is called after the end of a scroll to report metrics related to the
  // position of anchors in the viewport. The update will only include metrics
  // for anchors that have already been reported to be inside the viewport.
  // This is called only for randomly selected anchor elements that we track.
  ReportAnchorElementsPositionUpdate(
    array<AnchorElementPositionUpdate> elements);

  // This is called whenever the pointer starts hovering over anchor element.
  // This is called only for randomly selected anchor elements that we track.
  ReportAnchorElementPointerOver(AnchorElementPointerOver pointer_over_event);

  // This is called whenever pointer stops hovering over the anchor element.
  // This is called only for randomly selected anchor elements that we track.
  ReportAnchorElementPointerOut(AnchorElementPointerOut hover_event);

  // This is called whenever pointer down event happens over the anchor element.
  // This is called only for randomly selected anchor elements that we track.
  ReportAnchorElementPointerDown(AnchorElementPointerDown pointer_down_event);

  // This is called whenever the on-hover timer for the anchor element is fired.
  // This is called for all anchor elements.
  ReportAnchorElementPointerDataOnHoverTimerFired(
    AnchorElementPointerDataOnHoverTimerFired pointer_data);

  // This is called whenever a pointer event is triggered and intended to be
  // used by the preloading heuristics ML model.
  // This is called for all anchor elements.
  ProcessPointerEventUsingMLModel(
    AnchorElementPointerEventForMLModel pointer_event);

  // Asks the browser whether to send subsequent updates immediately
  // instead of rate limiting.
  // Skipping the delays is only expected to be done for testing.
  ShouldSkipUpdateDelays() => (bool should_skip_for_testing);
};