chromium/chromeos/ash/services/ime/public/mojom/input_method_host.mojom

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

// Updates to this file must be backwards-compatible, as it is used outside of
// the Chromium repo. This file should be updated first, before syncing in the
// other repos.

// Next MinVersion: 12

module ash.ime.mojom;

import "chromeos/ash/services/ime/public/mojom/input_method.mojom";
import "mojo/public/mojom/base/string16.mojom";

// Do not modify this enum. If new values are needed, deprecate the entire enum.
[Stable, Extensible, RenamedFrom="chromeos.ime.mojom.CommitTextCursorBehavior"]
enum CommitTextCursorBehavior {
  [Default] kMoveCursorAfterText = 0,
  kMoveCursorBeforeText = 1,
};

// Next ordinal: 3
[Stable, Extensible, RenamedFrom="chromeos.ime.mojom.CompositionSpanStyle"]
enum CompositionSpanStyle {
  // Default composition style. Usually, this adds an underline to the span.
  [Default] kDefault = 0,
  // No styling.
  kNone = 1,
  // A stronger style that emphasizes the span, distinguishing it from kDefault.
  // Usually, this uses a thicker underline than kDefault.
  [MinVersion=9] kHighlight = 2,
};

// A span with the composition text, used for styling parts of the composition.
// The indices are relative to the composition text.
//
// Next ordinal: 3
[Stable, RenamedFrom="chromeos.ime.mojom.CompositionSpan"]
struct CompositionSpan {
  uint32 start@0;
  uint32 end@1;
  CompositionSpanStyle style@2;
};

// A range of text. `start` can be equal to or greater than `end`.
// Next ordinal: 2
[Stable, RenamedFrom="chromeos.ime.mojom.TextRange"]
struct TextRange {
  uint32 start;
  uint32 end;
};

// Next ordinal: 3
[Stable, RenamedFrom="chromeos.ime.mojom.AutocorrectSpan"]
struct AutocorrectSpan {
  // The range to set the autocorrect span to, currently having `current_text`.
  TextRange autocorrect_range@0;

  // The original text that was replaced by autocorrect.
  mojo_base.mojom.String16 original_text@1;

  // The current text that replaced `original_text` and is now located at
  // `autocorrect_range` in the text field.
  // NOTE: Technically redundant to require client to supply `current_text` as
  // it can be retrieved from current text editing state known to IMF. However,
  // due to async situation between browser-process IMF and render-process
  // TextInputClient, it may just be a stale value if obtained that way.
  // TODO(crbug/1194424): Remove technically redundant `current_text` param to
  // avoid situation with multiple conflicting sources of truth.
  mojo_base.mojom.String16 current_text@2;
};

// Proposed candidate for completing some text.
//
// Next ordinal: 2
[Stable, RenamedFrom="chromeos.ime.mojom.CompletionCandidate"]
struct CompletionCandidate {
  // The candidate text
  string text@0;

  // Normalized confidence scoring for the candidate
  float normalized_score@1;
};

// Single request to generate suggestion candidates from the given context.
//
// Next ordinal: 3
[Stable, RenamedFrom="chromeos.ime.mojom.SuggestionsRequest"]
struct SuggestionsRequest {
  // The mode of suggestions that should be generated.
  SuggestionMode mode@0;

  // The preceding text used to produced the suggestions.
  string text@1;

  // Optional: any candidates generated to complete the current text.
  array<CompletionCandidate> completion_candidates@2;
};

// Encapsulates the results of a suggestions request.
//
// Next ordinal: 1
[Stable, RenamedFrom="chromeos.ime.mojom.SuggestionsResponse"]
struct SuggestionsResponse {
  // A list of suggestion candidates generated.
  array<SuggestionCandidate> candidates@0;
};

// Next ordinal: 1
[Stable]
struct SuggestionsTextContext {
  // The last N chars from the text used to produce the suggestions.
  string last_n_chars;

  // The total length of the surrounding text used to produce suggestions.
  uint32 surrounding_text_length;
};

// A URL-Keyed Metric (UKM) entry.
[Stable]
union UkmEntry {
  NonCompliantApiMetric non_compliant_api;
};

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
//
// Next ordinal: 5
[Stable, Extensible, RenamedFrom="chromeos.ime.mojom.InputMethodApiOperation"]
enum InputMethodApiOperation {
  [Default] kUnknown = 0,
  kCommitText = 1,
  kSetCompositionText = 2,
  kDeleteSurroundingText = 3,
  [MinVersion = 11] kReplaceSurroundingText = 4
};

// Next ordinal: 1
[Stable, RenamedFrom="chromeos.ime.mojom.NonCompliantApiMetric"]
struct NonCompliantApiMetric {
  InputMethodApiOperation non_compliant_operation@0;
};

// A candidate shown in the candidates window.
//
// Next ordinal: 2
[Stable, RenamedFrom="chromeos.ime.mojom.Candidate"]
struct Candidate {
  string text@0;

  // Some optional text that is displayed to the left of the candidate text.
  // It usually indicates a shortcut that the user can use to select that
  // candidate (e.g. a number).
  string? label@1;

  // Some optional text that is displayed to the right of the candidate text.
  // It typically gives information about how the candidate is used
  // linguistically.
  string? annotation@2;
};

// The highlighted candidate in a candidates window.
// Need to be wrapped in a struct so that its nullable.
[Stable, RenamedFrom="chromeos.ime.mojom.HighlightedCandidate"]
struct HighlightedCandidate {
  uint32 index@0;
};

// The candidates window shows a list of potential candidates for the user's
// current input. It is usually shown as a window below the current composition.
//
// Next ordinal: 3
[Stable, RenamedFrom="chromeos.ime.mojom.CandidatesWindow"]
struct CandidatesWindow {
  // List of candidates to be displayed. Must not be empty.
  array<Candidate> candidates@0;

  // The index of the candidate that should be highlighted visually.
  // DEPRECATED: Use highlighted_candidate instead.
  uint32 DEPRECATED_highlighted_candidate@1;

  // The text to show at the footer of the candidates window.
  // If empty, no footer is shown.
  [MinVersion=4] string? auxiliary_text@2;

  // If this is null, then no candidate is highlighted.
  [MinVersion=6] HighlightedCandidate? highlighted_candidate@3;
};

// Metrics enum for various actions that can be performed on the Korean IME.
//
// Next ordinal: 4
[Extensible, Stable, RenamedFrom="chromeos.ime.mojom.KoreanAction"]
enum KoreanAction {
  [Default] kUnknown = 0,
  // The user pressed the Hanja key.
  kHanjaKey = 1,
  // The user pressed the Hangeul key.
  kHangeulKey = 2,
  // The user composed a Korean syllable out-of-order.
  kComposeOutOfOrder = 3,
};

// Specifies how the buckets of an UMA histogram are determined.
//
// Next ordinal: 2
[Extensible, Stable]
enum HistogramBucketType {
  // Buckets are exponential. For example, buckets might contain (sequentially)
  // the count of values in the following intervals:
  // [0,1), [1,2), [2,4), [4,8), [8,16), [16,32), [32,64), [64,infinity)
  // The algorithm to determine the buckets is from base::Histogram.
  // This is the default for most metrics.
  [Default] kExponential = 0,

  // Buckets are evenly spaced. For example, buckets might contain
  // (sequentially) the count of values in the following intervals:
  // [0,5), [5,10), [10,infinity)
  // The algorithm to determine the buckets is from base::LinearHistogram.
  kLinear = 1,
};

// An UMA histogram with each sample allocated to a bucket.
// The buckets are determined by `bucket_type`, `minimum`, `maximum` and
// `bucket_count`.
//
// Next ordinal: 5
[Stable]
struct BucketedHistogram {
  string name@0;
  HistogramBucketType bucket_type@1;

  // The minimum value for a sample.
  // This must be > 0.
  uint16 minimum@2;

  // The maximum value for a sample.
  // This must be > minimum.
  uint16 maximum@3;

  // The number of buckets between `minimum` and `maximum`.
  // This must be > 2.
  // This must also be <= (maximum - minimum + 2).
  uint16 bucket_count@4;
};

// Interface for InputMethod to interact with Chrome.
// Provides a way for the InputMethod, which lives in a Chrome utility process,
// to communicate back to the browser process.
//
// Next ordinal: 17
[Stable]
interface InputMethodHost {
  // ========================================================
  // The following methods operate on the focused text field.
  // If there's no focus, then they don't do anything.
  // ========================================================

  // Asks the focused input field to commit `text`. If there is a
  // composition, then that composition is removed and `text` is inserted.
  // Otherwise, `text` is inserted at the current cursor position, deleting any
  // text in the current selection if any. In both cases, the cursor moves to
  // the end of `text`.
  CommitText@0(mojo_base.mojom.String16 text,
               CommitTextCursorBehavior cursor_behavior);

  // Asks the focused input field to set composition with `text`.
  // Replaces the current composition if there is one. Otherwise, start a
  // new composition at the current cursor position, deleting any text in the
  // current selection if any. The cursor is moved to the end of `text`.
  // `spans` is used to style `text`.
  DEPRECATED_SetComposition@1(mojo_base.mojom.String16 text, array<CompositionSpan> spans);

  // Asks the focused input field to set composition with `text`.
  // Replaces the current composition if there is one. Otherwise, start a
  // new composition at the current cursor position, deleting any text in the
  // current selection if any.
  //
  // `spans` is used to style `text`.
  //
  // The cursor then moves based on `new_cursor_position`, which is the relative
  // UTF-16 offset of the new cursor position from the front of `text`.
  // For example, if `new_cursor_position` is 3, then the cursor is placed
  // between `text[3]` and `text[4]`. A `new_cursor_position` of 0 places the
  // cursor immediately before `text`, and a value of `text.length()` places the
  // cursor immediately after `text`.
  // If `new_cursor_position > text.length()`, then this is a no-op.
  [MinVersion=5]
  SetComposition@12(mojo_base.mojom.String16 text,
                    array<CompositionSpan> spans,
                    uint32 new_cursor_position);

  // Asks the focused input field to mark the range of text spanned by
  // `start_index` and `end_index` as the current composition, where index 0
  // indicates the beginning of the input field contents. Both indices are in
  // UTF-16 code units.
  // If there was already a composition, then that composition is committed
  // first, as if FinishComposition was called.
  // The order of `start_index` and `end_index` does not matter.
  // If both `start_index` and `end_index` are the same, then this is equivalent
  // to calling `FinishComposition`.
  // The composition range does not have to overlap with the cursor selection.
  // The cursor position remains unchanged.
  SetCompositionRange@2(uint32 start_index, uint32 end_index);

  // Asks the focused input field to commit the current composition text. If
  // there is composition, this is equivalent to calling `CommitText` with the
  // composition text. If there is no current composition then this is a no-op.
  // The cursor position remains unchanged.
  FinishComposition@3();

  // Asks the input field to delete text around the cursor. Specifically,
  // delete `num_before_cursor` and `num_after_cursor` UTF-16 code units before
  // and after the cursor, respectively.
  // This operation fails if there is currently a composition.
  // TODO(b/161490915): Determine the right behaviour when there is a selection.
  DeleteSurroundingText@4(uint32 num_before_cursor,
                          uint32 num_after_cursor);

  // Asks the input field to replace the text around the cursor with `text`.
  // Specifically, delete `num_before_cursor` and `num_after_cursor` UTF-16 code
  // units before and after the cursor, respectively and insert `text` at the
  // cursor position.
  [MinVersion = 11] ReplaceSurroundingText@16(uint32 num_before_cursor,
                                              uint32 num_after_cursor,
                                              mojo_base.mojom.String16 text);

  // Asks the input field to mark the region represented by `autocorrect_span`
  // as having been autocorrected. This usually involves showing some UI
  // (e.g. flashing the text or showing an underline).
  // There can only be at most one active autocorrect span. If this method is
  // called when there is already an active autocorrect span, any UI related to
  // the old span is removed first.
  // This method does not modify the input field text.
  HandleAutocorrect@5(AutocorrectSpan autocorrect_span);

  // Asks the system to display the given suggestions to the user. The
  // surrounding text given with the call was the text used to generate the
  // suggestions. Listeners to this call can use this text to decide what they
  // want to do with the suggestions given.
  DisplaySuggestions@6(
    array<SuggestionCandidate> suggestions,
    [MinVersion=10] SuggestionsTextContext? context);

  // Asks the system to update the current candidates window state.
  // If `window` is null, then the candidates window is hidden.
  [MinVersion=2] UpdateCandidatesWindow@9(CandidatesWindow? window);

  // ===========================================
  // The following methods do not require focus.
  // ===========================================

  // Asks the system to generate and return suggestions for the given
  // prediction context.
  RequestSuggestions@7(SuggestionsRequest request)
    => (SuggestionsResponse response);

  // Asks the system to update the quick settings menu.
  [MinVersion=7] UpdateQuickSettings@13(InputMethodQuickSettings settings);

  // ============================================================
  // The following methods are for metrics and not require focus.
  // ============================================================

  // Record a Url-Keyed Metric (UKM).
  RecordUkm@8(UkmEntry entry);

  // Reports an action performed on the Korean IME.
  // Recorded in UMA as InputMethod.PhysicalKeyboard.Korean.Action.
  // DEPRECATED: Use ReportHistogramSample instead.
  [MinVersion=3] DEPRECATED_ReportKoreanAction@10(KoreanAction action);

  // Reports the usage of certain settings on the Korean IME:
  // - The input multiple syllables setting is recorded in UMA as
  //   InputMethod.PhysicalKeyboard.Korean.MultipleSyllables.
  // - The layout setting is recorded in UMA as
  //   InputMethod.PhysicalKeyboard.Korean.Layout.
  // DEPRECATED: Use ReportHistogramSample instead.
  [MinVersion=3] DEPRECATED_ReportKoreanSettings@11(KoreanSettings settings);

  // Reports an opportunity identified in the current text to show a predictive
  // text suggestions.
  // DEPRECATED: Use ReportHistogramSample instead.
  [MinVersion=8] DEPRECATED_ReportSuggestionOpportunity@14(SuggestionMode mode);

  // Reports a histogram sample to UMA.
  // The name of the histogram must start with 'Untrusted.'. (e.g.
  // 'Untrusted.InputMethod.CharacterCount'), or else this sample is dropped.
  [MinVersion=10] ReportHistogramSample@15(BucketedHistogram histogram,
                                           uint16 value);
};