chromium/ui/base/ime/ash/mock_ime_input_context_handler.cc

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

#include "ui/base/ime/ash/mock_ime_input_context_handler.h"

#include <string_view>

#include "base/logging.h"
#include "base/notreached.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/input_method.h"
#include "ui/gfx/range/range.h"

namespace ash {

MockIMEInputContextHandler::MockIMEInputContextHandler()
    : commit_text_call_count_(0),
      update_preedit_text_call_count_(0),
      delete_surrounding_text_call_count_(0) {}

MockIMEInputContextHandler::~MockIMEInputContextHandler() = default;

void MockIMEInputContextHandler::CommitText(
    const std::u16string& text,
    ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) {
  ++commit_text_call_count_;
  last_commit_text_ = text;
  for (Observer& observer : observers_) {
    observer.OnCommitText(text);
  }
}

void MockIMEInputContextHandler::UpdateCompositionText(
    const ui::CompositionText& text,
    uint32_t cursor_pos,
    bool visible) {
  ++update_preedit_text_call_count_;
  last_update_composition_arg_.composition_text = text;
  last_update_composition_arg_.selection = gfx::Range(cursor_pos);
  last_update_composition_arg_.is_visible = visible;
}

bool MockIMEInputContextHandler::SetCompositionRange(
    uint32_t before,
    uint32_t after,
    const std::vector<ui::ImeTextSpan>& text_spans) {
  // TODO(shend): Make this work with before, after and different text contents.
  last_update_composition_arg_.composition_text.text = last_commit_text_;
  return true;
}

bool MockIMEInputContextHandler::SetComposingRange(
    uint32_t start,
    uint32_t end,
    const std::vector<ui::ImeTextSpan>& text_spans) {
  // TODO(shend): Make this work with start, end and different text contents.
  last_update_composition_arg_.composition_text.text = last_commit_text_;
  return true;
}

gfx::Range MockIMEInputContextHandler::GetAutocorrectRange() {
  return autocorrect_range_;
}

void MockIMEInputContextHandler::SetAutocorrectRange(
    const gfx::Range& range,
    SetAutocorrectRangeDoneCallback callback) {
  if (autocorrect_enabled_) {
    autocorrect_range_ = range;
  }

  std::move(callback).Run(autocorrect_enabled_);
}

std::optional<ui::GrammarFragment>
MockIMEInputContextHandler::GetGrammarFragmentAtCursor() {
  for (const auto& fragment : grammar_fragments_) {
    if (fragment.range.Contains(cursor_range_)) {
      return fragment;
    }
  }
  return std::nullopt;
}

bool MockIMEInputContextHandler::ClearGrammarFragments(
    const gfx::Range& range) {
  std::vector<ui::GrammarFragment> updated_fragments;
  for (const ui::GrammarFragment& fragment : grammar_fragments_) {
    if (!range.Contains(fragment.range)) {
      updated_fragments.push_back(fragment);
    }
  }
  grammar_fragments_ = updated_fragments;
  return true;
}

bool MockIMEInputContextHandler::AddGrammarFragments(
    const std::vector<ui::GrammarFragment>& fragments) {
  grammar_fragments_.insert(grammar_fragments_.end(), fragments.begin(),
                            fragments.end());
  return true;
}

void MockIMEInputContextHandler::DeleteSurroundingText(
    uint32_t num_char16s_before_cursor,
    uint32_t num_char16s_after_cursor) {
  ++delete_surrounding_text_call_count_;
  last_delete_surrounding_text_arg_.num_char16s_before_cursor =
      num_char16s_before_cursor;
  last_delete_surrounding_text_arg_.num_char16s_after_cursor =
      num_char16s_after_cursor;
}

void MockIMEInputContextHandler::ReplaceSurroundingText(
    uint32_t length_before_selection,
    uint32_t length_after_selection,
    const std::u16string_view replacement_text) {
  last_replace_surrounding_text_arg_.length_before_selection =
      length_before_selection;
  last_replace_surrounding_text_arg_.length_after_selection =
      length_after_selection;
  last_replace_surrounding_text_arg_.replacement_text =
      std::u16string(replacement_text);
}

SurroundingTextInfo MockIMEInputContextHandler::GetSurroundingTextInfo() {
  SurroundingTextInfo info;
  info.selection_range = cursor_range_;
  info.offset = 0;
  return info;
}

void MockIMEInputContextHandler::Reset() {
  commit_text_call_count_ = 0;
  update_preedit_text_call_count_ = 0;
  delete_surrounding_text_call_count_ = 0;
  autocorrect_enabled_ = true;
  last_commit_text_.clear();
  sent_key_events_.clear();
}

void MockIMEInputContextHandler::SendKeyEvent(ui::KeyEvent* event) {
  sent_key_events_.emplace_back(*event);
}

ui::InputMethod* MockIMEInputContextHandler::GetInputMethod() {
  return nullptr;
}

void MockIMEInputContextHandler::ConfirmComposition(bool reset_engine) {
  // TODO(b/134473433) Modify this function so that the selection is unchanged.
  NOTIMPLEMENTED_LOG_ONCE();

  if (!HasCompositionText()) {
    return;
  }

  CommitText(
      last_update_composition_arg_.composition_text.text,
      ui::TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText);
  last_update_composition_arg_.composition_text.text = std::u16string();
}

bool MockIMEInputContextHandler::HasCompositionText() {
  return !last_update_composition_arg_.composition_text.text.empty();
}

ukm::SourceId MockIMEInputContextHandler::GetClientSourceForMetrics() {
  return ukm::kInvalidSourceId;
}

void MockIMEInputContextHandler::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void MockIMEInputContextHandler::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

}  // namespace ash