chromium/components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom

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

module paint_preview.mojom;

import "components/discardable_memory/public/mojom/discardable_shared_memory_manager.mojom";
import "components/paint_preview/common/mojom/paint_preview_types.mojom";
import "mojo/public/mojom/base/memory_pressure_level.mojom";
import "mojo/public/mojom/base/proto_wrapper.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
import "sandbox/policy/mojom/sandbox.mojom";
import "skia/public/mojom/bitmap.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
import "url/mojom/url.mojom";

// A request sent to the PaintPreviewCompositor to request deserialization.
struct PaintPreviewBeginCompositeRequest {
  // A serialized PaintPreviewProto.
  mojo_base.mojom.ProtoWrapper preview;

  // A mapping between frame GUIDs and serialized recordings.
  map<mojo_base.mojom.UnguessableToken, SerializedRecording> recording_map;
};

// A struct representing the clip rect of a subframe within its parent.
struct SubframeClipRect {
  mojo_base.mojom.UnguessableToken frame_guid;
  gfx.mojom.RectF clip_rect;
};

// A struct representing the scroll extents and subframes of a parent frame.
struct FrameData {
  // The dimensions of the frame.
  gfx.mojom.Size scroll_extents;

  // The initial scroll offsets of the frame.
  gfx.mojom.Size scroll_offsets;

  // This is not a map because a parent can, in theory, embed the same subframe
  // multiple times.
  array<SubframeClipRect> subframes;
};

// A response sent as a result of a begin composite request. It provides the
// ID of the root frame (used for the primary UI) and the map can be used for
// looking up the data associated with each frame.
struct PaintPreviewBeginCompositeResponse {
  mojo_base.mojom.UnguessableToken root_frame_guid;
  map<mojo_base.mojom.UnguessableToken, FrameData> frames;
};

// A compositor that converts paint preview captures into bitmaps.
//
// |Begin*FrameComposite| must be called to prepare the compositor for returning
// bitmaps from a paint preview capture. It can be called again later to prepare
// another capture.
// After |Begin*FrameComposite| is called, the corresponding |BitmapFor*Frame|
// can be called any number of times concurrently.
//
// This interface should run in a sandboxed utility process called by the
// browser process.
interface PaintPreviewCompositor {
  // The status code for |BeginSeparatedFrameComposite| and
  // |BeginMainFrameComposite|.
  enum BeginCompositeStatus {
    // The request succeeded.
    kSuccess = 0,

    // The request succeeded, but some frames are missing from output.
    kPartialSuccess = 1,

    // Indicates there was an issue deserializing the proto or root frame.
    // Problematic subframes are omitted since compositing can occur without
    // them.
    kDeserializingFailure = -1,

    // Indicates there was a failure to composite a bitmap for the requested
    // frame. Either; 1. it failed to deserialize or 2. there was an issue with
    // the parameters provided.
    kCompositingFailure = -2,
  };

  // The status code for |BitmapForSeparatedFrame| and |BitmapForMainFrame|.
  enum BitmapStatus {
    // The request succeeded.
    kSuccess = 0,

    // Indicates there was a failure to find the frame required for the given
    // request. This may be because the requested |frame_guid| is not valid or
    // that the associated |BeginSeparatedFrameComposite| or
    // |BeginMainFrameComposite| method has not been called yet.
    kMissingFrame = 1,

    // Indicates that memory allocation for the bitmap failed.
    kAllocFailed = 2,
  };

  // Starts the compositing process for |BitmapForSeparatedFrame| calls using
  // frame data |request|. On success returns |response| containing metadata
  // required for UI. |status| will be negative on failure. If the root frame is
  // successfully loaded but subframes fail, |status| will indicate partial
  // success.
  BeginSeparatedFrameComposite(PaintPreviewBeginCompositeRequest request) =>
    (BeginCompositeStatus status, PaintPreviewBeginCompositeResponse? response);

  // Requests a bitmap associated with |frame_guid| the dimensions and
  // location of the bitmap will match |clip_rect| at scale |scale_factor|.
  // Bitmap will not include embedded sub-frame content.
  // Returns |bitmap| on success and will indicate failure via a negative
  // |status|.
  // |BeginSeparatedFrameComposite| must be called before this method.
  BitmapForSeparatedFrame(mojo_base.mojom.UnguessableToken frame_guid,
                          gfx.mojom.Rect clip_rect,
                          float scale_factor) =>
    (BitmapStatus status, skia.mojom.BitmapN32? bitmap);

  // Starts the compositing process for |BitmapForMainFrame| calls using frame
  // data |request|. On success returns |response| containing metadata
  // required for UI. |status| will be negative on failure.
  BeginMainFrameComposite(PaintPreviewBeginCompositeRequest request) =>
    (BeginCompositeStatus status, PaintPreviewBeginCompositeResponse? response);

  // Requests a bitmap of the main frame with sub-frame content included. The
  // dimensions and location of the bitmap will match |clip_rect| at scale
  // |scale_factor|.
  // Returns |bitmap| on success and will indicate failure via a negative
  // |status|.
  // |BeginMainFrameComposite| must be called before this method.
  BitmapForMainFrame(gfx.mojom.Rect clip_rect, float scale_factor) =>
    (BitmapStatus status, skia.mojom.BitmapN32? bitmap);

  // Sets the root frame of the compositor. Used for tracing and diagnostics.
  SetRootFrameUrl(url.mojom.Url url);
};

// Holds a collection of PaintPreviewCompositor instances running in the same
// process.
// TODO(crbug.com/40686792): Investigate using a different Sandbox.
[ServiceSandbox=sandbox.mojom.Sandbox.kPrintCompositor]
interface PaintPreviewCompositorCollection {
  // Provides an interface for managing discardable shared memory regions. Must
  // be called before calling any methods on managed PaintPreviewCompositors.
  SetDiscardableSharedMemoryManager(
      pending_remote<discardable_memory.mojom.DiscardableSharedMemoryManager>
          manager);

  // Adds a PaintPreviewCompositor to the utility process. Returns an ID for
  // the compositor.
  CreateCompositor(pending_receiver<PaintPreviewCompositor> compositor)
    => (mojo_base.mojom.UnguessableToken compositor_id);

  // Called when the system is low on memory.
  OnMemoryPressure(mojo_base.mojom.MemoryPressureLevel memory_pressure_level);

  // Returns a list of active compositor IDs.
  ListCompositors() => (array<mojo_base.mojom.UnguessableToken> compositor_ids);
};