// 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 printing.mojom;

import "mojo/public/mojom/base/shared_memory.mojom";
import "mojo/public/mojom/base/string16.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
import "mojo/public/mojom/base/values.mojom";
import "printing/mojom/print.mojom";
import "ui/accessibility/mojom/ax_tree_update.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";

// Preview Ids, the id of the preview request and the print preview ui
// associated with this request.
[EnableIf=enable_print_preview]
struct PreviewIds {
  int32 request_id = -1;
  int32 ui_id = -1;
};

// Parameters required to do print preview.
[EnableIf=enable_print_preview]
struct RequestPrintPreviewParams {
  [EnableIf=is_chromeos]
  bool is_from_arc = false;

  bool webnode_only = false;
  bool has_selection = false;
  bool selection_only = false;
};

// Parameters required to print the content of an out-of-process subframe.
struct PrintFrameContentParams {
  // Physical printable area of the page in pixels according to dpi.
  gfx.mojom.Rect printable_area;

  // Cookie that is unique for each print request. It is used to associate the
  // printed frame with its original print request.
  int32 document_cookie;
};

// Parameters required to set options from a document.
struct OptionsFromDocumentParams {
  // Specifies whether print scaling is enabled or not.
  bool is_scaling_disabled;
  // Specifies number of copies to be printed.
  int32 copies;
  // Specifies paper handling option.
  DuplexMode duplex;
};

// Holds the printed content information.
// The printed content is in shared memory, and passed as a region.
// A map on out-of-process subframe contents is also included so the printed
// content can be composited as needed.
struct DidPrintContentParams {
  // A shared memory region for the metafile data.
  mojo_base.mojom.ReadOnlySharedMemoryRegion? metafile_data_region;
  // Content id to render frame proxy token mapping for out-of-process
  // subframes.
  map<uint32, mojo_base.mojom.UnguessableToken> subframe_content_info;
};

// Parameters to describe the to-be-rendered preview document.
struct DidStartPreviewParams {
  // Total page count for the rendered preview. (Not the number of pages the
  // user selected to print.)
  uint32 page_count;
  // The list of 0-based page numbers that will be rendered.
  array<uint32> pages_to_render;
  // number of pages per sheet and should be greater or equal to 1.
  int32 pages_per_sheet;
  // Physical size of the page, including non-printable margins.
  gfx.mojom.SizeF page_size;
  // Scaling % to fit to page
  int32 fit_to_page_scaling;
};

// Parameters to describe a rendered preview page.
struct DidPreviewPageParams {
  // Page's content including metafile data and subframe info.
  DidPrintContentParams content;
  // `page_index` is zero-based.
  uint32 page_index;
  // Cookie for the document to ensure correctness.
  int32 document_cookie;
};

// Parameters to describe the final rendered preview document.
struct DidPreviewDocumentParams {
  // Document's content including metafile data and subframe info.
  DidPrintContentParams content;
  // Cookie for the document to ensure correctness.
  int32 document_cookie;
  // Store the expected pages count.
  uint32 expected_pages_count;
};

// Parameters for a render request.
struct PrintParams {
  // Physical size of the page, including non-printable margins,
  // in device pixels.
  gfx.mojom.SizeF page_size;
  // In device pixels.
  gfx.mojom.SizeF content_size;
  // Physical printable area of the page in device pixels.
  gfx.mojom.RectF printable_area;
  // The y-offset of the printable area, in device pixels.
  float margin_top = 0;
  // The x-offset of the printable area, in device pixels.
  float margin_left = 0;
  // Specifies the page orientation.
  PageOrientation page_orientation = kUpright;
  // Specifies dots per inch in the x and y direction.
  gfx.mojom.Size dpi;
  // Specifies the scale factor in percent
  double scale_factor = 1.0;
  // Cookie for the document to ensure correctness.
  int32 document_cookie = 0;
  // Should only print currently selected text.
  bool selection_only = false;

  // *** Parameters in this section are used only for Print Preview. ***
  // The id of the preview request.
  int32 preview_request_id = 0;
  // True if this is the first preview request.
  bool is_first_request = false;
  // Specifies the page scaling option for preview printing.
  PrintScalingOption print_scaling_option = kSourceSize;

  // *** Parameters in this section are used for Print Preview and Headless. ***
  // True if print to pdf is requested.
  bool print_to_pdf = false;
  // Specifies if the header and footer should be rendered.
  bool display_header_footer = false;
  // Title string to be printed as header if requested by the user.
  mojo_base.mojom.String16 title;
  // URL string to be printed as footer if requested by the user.
  mojo_base.mojom.String16 url;
  // HTML template to use as a print header.
  mojo_base.mojom.String16 header_template;
  // HTML template to use as a print footer.
  mojo_base.mojom.String16 footer_template;
  // Whether to rasterize a PDF for printing
  bool rasterize_pdf = false;
  // Override of the DPI to use if `rasterize_pdf` is true.  A non-positive
  // value would be an invalid choice of a DPI, and indicates no override
  // should be applied.
  int32 rasterize_pdf_dpi = 0;
  // True if print backgrounds is requested by the user.
  bool should_print_backgrounds = false;
  // The document type of printed page(s) from render.
  SkiaDocumentType printed_doc_type = kPDF;
  // True if page size defined by css should be preferred.
  bool prefer_css_page_size = false;
  // Number of pages per sheet.  This parameter is for N-up mode.
  // Defaults to 1 if the feature is disabled, and some number greater
  // than 1 otherwise.  See printing::NupParameters for supported values.
  uint32 pages_per_sheet = 1;
  // Whether tagged (accessible) PDF should be generated. No value assumes
  // embedder choice provided by PrintRenderFrameHelper delegate.
  bool? generate_tagged_pdf;
  // Whether the document outline should be embedded in the PDF.
  GenerateDocumentOutline generate_document_outline = kNone;
};

// Parameters for a print setting that has parameters for a print request and an
// array of pages to print.
struct PrintPagesParams {
  // Parameters to render the page as a printed page. It must always be the same
  // value for all the document.
  PrintParams params;
  // If empty, this means a request to render all the printed pages.
  array<PageRange> pages;
};

// Parameters to describe a rendered page.
struct DidPrintDocumentParams {
  // Document's content including metafile data and subframe info.
  DidPrintContentParams content;
  // Cookie for the document to ensure correctness.
  int32 document_cookie;
  // The size of the page the page author specified.
  gfx.mojom.Size page_size;
  // The printable area the page author specified.
  gfx.mojom.Rect content_area;
  // The physical offsets of the printer in DPI. Used for PS printing.
  gfx.mojom.Point physical_offsets;
};

// TODO(dgn): Rename *ScriptedPrint messages because they are not called only
//           from scripts.
// Parameters to get a print setting from a user before printing.
struct ScriptedPrintParams {
  int32 cookie;
  uint32 expected_pages_count;
  bool has_selection;
  bool is_scripted;
  MarginType margin_type;
};

// Interface implemented by a class that desires to render print documents for
// Chrome print preview.
[EnableIf=is_chromeos]
interface PrintRenderer {
  // Creates a preview document for print preview using the provided
  // `job_settings`.
  // The returned `preview_document_region` contains the preview document data
  // as a flattened PDF. It will be invalid if errors occurred while rendering
  // the preview document.
  CreatePreviewDocument(mojo_base.mojom.DictionaryValue job_settings)
      => (mojo_base.mojom.ReadOnlySharedMemoryRegion? preview_document_region);
};

// Browser process interface exposed to the renderer to handle the print
// preview UI.
interface PrintPreviewUI {
  // Notifies the WebUI to set print preset options from source PDF.
  // `request_id` comes from the chrome://print WebUI when it requests to update
  // the print preview.
  [EnableIf=enable_print_preview]
  SetOptionsFromDocument(OptionsFromDocumentParams params, int32 request_id);

  // Notifies the browser of preparing to print the document, for cases where
  // the document will be collected from the individual pages instead of being
  // provided by an extra metafile at end containing all pages.
  [EnableIf=enable_print_preview]
  DidPrepareDocumentForPreview(int32 document_cookie, int32 request_id);

  // Notifies the browser a print preview page has been rendered.
  [EnableIf=enable_print_preview]
  DidPreviewPage(DidPreviewPageParams params, int32 request_id);

  // Sends back to the browser the complete rendered document that was requested
  // by PrintPreview.
  [EnableIf=enable_print_preview]
  MetafileReadyForPrinting(
      DidPreviewDocumentParams params, int32 request_id);

  // Tells the browser print preview failed.
  // `document_cookie`, if valid, identifies the print job that needs to be
  // cleaned up on failure.
  // `request_id` identifies the preview request.
  [EnableIf=enable_print_preview]
  PrintPreviewFailed(int32 document_cookie, int32 request_id);

  // Tell the browser print preview was cancelled.
  // `document_cookie` and `request_id` have the same semantics as the
  // PrintPreviewFailed() parameters with the same names.
  [EnableIf=enable_print_preview]
  PrintPreviewCancelled(int32 document_cookie, int32 request_id);

  // Tell the browser print preview found the selected printer has invalid
  // settings (which typically caused by disconnected network printer or
  // printer driver is bogus).
  // `document_cookie` and `request_id` have the same semantics as the
  // PrintPreviewFailed() parameters with the same names.
  [EnableIf=enable_print_preview]
  PrinterSettingsInvalid(int32 document_cookie, int32 request_id);

  // Notifies the browser of the default page layout according to the currently
  // selected printer and page size.
  // `printable_area_in_points` Specifies the printable area in points.
  // `all_pages_have_custom_size` is true when the printing frame has a custom
  // page size in CSS on ALL pages, otherwise false.
  // `all_pages_have_custom_orientation` is true when the printing frame
  // additionally has a custom orientation on ALL pages, otherwise false.
  [EnableIf=enable_print_preview]
  DidGetDefaultPageLayout(PageSizeMargins page_layout_in_points,
                          gfx.mojom.RectF printable_area_in_points,
                          bool all_pages_have_custom_size,
                          bool all_pages_have_custom_orientation,
                          int32 request_id);

  // Notifies the browser about the to-be-rendered print preview document.
  [EnableIf=enable_print_preview]
  DidStartPreview(DidStartPreviewParams params, int32 request_id);
};

struct PrintWithParamsResultData {
  DidPrintDocumentParams params;
  ax.mojom.AXTreeUpdate accessibility_tree;
  GenerateDocumentOutline generate_document_outline = kNone;
};

enum PrintFailureReason {
  kGeneralFailure,
  kInvalidPageRange,
  kPrintingInProgress,
};

// Render process interface exposed to the browser to handle most of the
// printing grunt work for RenderView.
interface PrintRenderFrame {
  // Tells the RenderFrame to switch the CSS to print media type, render every
  // requested page, and then switch back the CSS to display media type.
  PrintRequestedPages();

  // Requests the frame to be printed with specified parameters. This is used
  // to programmatically produce PDF by request from the browser (e.g. over
  // DevTools protocol) and, unlike other printing code paths, is not designed
  // around the legacy protocol between renderer and the browser to support
  // interactive print preview -- the final print settings are supplied by
  // the caller and printing is completed without further round-trips to the
  // browser.
  PrintWithParams(PrintPagesParams params)
      => result<PrintWithParamsResultData, PrintFailureReason>;

  // Tells the RenderFrame to switch the CSS to print media type, render every
  // requested page using the print preview document's frame/node, and then
  // switch the CSS back to display media type.
  [EnableIf=enable_print_preview]
  PrintForSystemDialog();

  // Tells the RenderFrame to initiate print preview for the entire document.
  // Optionally provides a `print_renderer` to render print documents.
  [EnableIf=enable_print_preview]
  InitiatePrintPreview(
      [EnableIf=is_chromeos] pending_associated_remote<PrintRenderer>?
          print_renderer,
      bool has_selection);

  // Sets PrintPreviewUI interface to notify the browser of preview actions.
  [EnableIf=enable_print_preview]
  SetPrintPreviewUI(pending_associated_remote<PrintPreviewUI> preview);

  // Tells the RenderFrame to switch the CSS to print media type and render
  // every requested page for print preview using the given `settings`. This
  // gets called multiple times as the user updates settings.
  [EnableIf=enable_print_preview]
  PrintPreview(mojo_base.mojom.DictionaryValue settings);

  // Tells the RenderFrame that the print preview dialog was closed.
  [EnableIf=enable_print_preview]
  OnPrintPreviewDialogClosed();

  // Prints the content of an out-of-process subframe. Replies back to the
  // browser the rendered subframe content that was requested.
  PrintFrameContent(PrintFrameContentParams params)
      => (int32 document_cookie, DidPrintContentParams params);

  // Message with no arguments and no reply that is used to simply ensure the
  // communication channel between the browser and renderer exists. Without the
  // connection, PrintViewManager cannot correctly keep track of associated PDF
  // renderers. See crbug.com/1251431 for context.
  ConnectToPdfRenderer();

  // Tells the RenderFrame that printing is done so it can clean up.
  PrintingDone(bool success);

  // Tells the RenderFrame to initiate printing or print preview for a
  // particular node, depending on which mode the RenderFrame is in.
  PrintNodeUnderContextMenu();
};

// Browser process interface exposed to the renderer to handle the general
// print management.
interface PrintManagerHost {
  // Tells the browser that the renderer is done calculating the number of
  // rendered pages according to the specified settings.
  DidGetPrintedPagesCount(int32 cookie, uint32 number_pages);

  // Requests the default print settings.
  [Sync]
  GetDefaultPrintSettings() => (PrintParams? default_settings);

  // Tells the browser that the print dialog has been shown.
  DidShowPrintDialog();

  // Sends back to the browser the rendered document that was requested by a
  // PrintRequestedPages() or from scripted printing. Waits until the document
  // is ready before replying.
  [Sync]
  DidPrintDocument(DidPrintDocumentParams params) => (bool completed);

  // Asks the browser whether printing is enabled or not.
  [Sync]
  IsPrintingEnabled() => (bool printing_enabled);

  // Requests the print settings from the user. This step is about showing
  // UI to the user to select the final print settings. If the user cancels or
  // an error occurs, return null.
  [Sync]
  ScriptedPrint(ScriptedPrintParams params) => (PrintPagesParams? settings);

  // Tells the browser printing failed.
  PrintingFailed(int32 cookie, PrintFailureReason reason);

  // Gets the print settings as a `PrintPagesParams` from the browser. If an
  // error occurs, the browser returns null.
  [EnableIf=enable_print_preview, Sync]
  GetPrintPreviewParams() => (PrintPagesParams? current_settings);

  // Tells the browser to set up the print preview requested by the script. It
  // runs a nested run loop in the renderer until print preview for
  // window.print() finishes.
  [EnableIf=enable_print_preview]
  SetupScriptedPrintPreview() => ();

  // Tells the browser to show the print preview when the document is loaded.
  [EnableIf=enable_print_preview]
  ShowScriptedPrintPreview();

  // Asks the browser to do print preview.
  [EnableIf=enable_print_preview]
  RequestPrintPreview(RequestPrintPreviewParams params);

  // Asks the browser whether the print preview has been cancelled. It
  // gets true if the preview corresponding to `preview_ui_id` and `request_id`
  // has been cancelled.
  [EnableIf=enable_print_preview, Sync]
  CheckForCancel(
      mojo_base.mojom.UnguessableToken preview_ui_id, int32 request_id)
      => (bool cancel);

  // Sends the accessibility tree corresponding to a document being
  // printed, needed for a tagged (accessible) PDF.
  [EnableIf=enable_print_preview]
  SetAccessibilityTree(
      int32 cookie, ax.mojom.AXTreeUpdate accessibility_tree);

  // Tells the browser to set up the print dialog requested by the script on
  // Android. This is the Android-equivalent of SetupScriptedPrintPreview().
  // It runs a nested run loop in the renderer until the print dialog
  // for window.print() finishes.
  // The run loop continues until the done callback is invoked, which allows
  // the browser process to finish any UI work it needs to do to set up the
  // print.
  [EnableIf=is_android]
  SetupScriptedPrintAndroid() => ();
};
