File: assistive_suggester.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (229 lines) | stat: -rw-r--r-- 8,694 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
// 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.

#ifndef CHROME_BROWSER_ASH_INPUT_METHOD_ASSISTIVE_SUGGESTER_H_
#define CHROME_BROWSER_ASH_INPUT_METHOD_ASSISTIVE_SUGGESTER_H_

#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/timer/timer.h"
#include "chrome/browser/ash/input_method/assistive_suggester_switch.h"
#include "chrome/browser/ash/input_method/emoji_suggester.h"
#include "chrome/browser/ash/input_method/longpress_control_v_suggester.h"
#include "chrome/browser/ash/input_method/longpress_diacritics_suggester.h"
#include "chrome/browser/ash/input_method/multi_word_suggester.h"
#include "chrome/browser/ash/input_method/suggester.h"
#include "chrome/browser/ash/input_method/suggestion_enums.h"
#include "chrome/browser/ash/input_method/suggestion_handler_interface.h"
#include "chrome/browser/ash/input_method/suggestions_source.h"
#include "chromeos/ash/services/ime/public/cpp/assistive_suggestions.h"

namespace ash::input_method {

enum class AssistiveSuggesterKeyResult {
  // The key event was not handled by the assistive suggester.
  // The key event should be handled via normal key event flow.
  kNotHandled,
  // The key event was handled by the assistive suggester.
  // The key event should not be propagated as-is. Instead, it should be
  // dispatched as a PROCESS key to prevent the client from triggering the
  // default behaviour for the key.
  kHandled,
  // Same as not kNotHandled, except the key event should not trigger
  // autorepeat.
  kNotHandledSuppressAutoRepeat,
};

// An agent to suggest assistive information when the user types, and adopt or
// dismiss the suggestion according to the user action.
class AssistiveSuggester : public SuggestionsSource {
 public:
  // Features handled by assistive suggester.
  enum class AssistiveFeature {
    kUnknown,  // Includes features not handled by assistive suggester.
    kEmojiSuggestion,
    kMultiWordSuggestion,
  };

  AssistiveSuggester(
      SuggestionHandlerInterface* suggestion_handler,
      Profile* profile,
      std::unique_ptr<AssistiveSuggesterSwitch> suggester_switch);

  ~AssistiveSuggester() override;

  bool IsAssistiveFeatureEnabled();

  // Fetches enabled suggestions in the current browser context then run
  // callback.
  void FetchEnabledSuggestionsFromBrowserContextThen(
      AssistiveSuggesterSwitch::FetchEnabledSuggestionsCallback callback);

  // SuggestionsSource overrides
  std::vector<ime::AssistiveSuggestion> GetSuggestions() override;

  // Called when a new input engine is activated by the system.
  void OnActivate(const std::string& engine_id);

  // Called when a text field gains focus, and suggester starts working.
  void OnFocus(int context_id, const TextInputMethod::InputContext& context);

  // Called when a text field loses focus, and suggester stops working.
  void OnBlur();

  // Called when a surrounding text is changed.
  // Returns true if it changes the surrounding text, e.g. a suggestion is
  // generated or dismissed.
  void OnSurroundingTextChanged(const std::u16string& text,
                                gfx::Range selection_range);

  // Called when the user pressed a key.
  AssistiveSuggesterKeyResult OnKeyEvent(const ui::KeyEvent& event);

  // Called when suggestions are generated outside of the assistive framework.
  void OnExternalSuggestionsUpdated(
      const std::vector<ime::AssistiveSuggestion>& suggestions,
      const std::optional<ime::SuggestionsTextContext>& context);

  // Accepts the suggestion at a given index if a suggester is currently
  // active.
  void AcceptSuggestion(size_t index);

  // Check if suggestion is being shown.
  bool IsSuggestionShown();

  EmojiSuggester* get_emoji_suggester_for_testing() {
    return &emoji_suggester_;
  }

  std::optional<AssistiveSuggesterSwitch::EnabledSuggestions>
  get_enabled_suggestion_from_last_onfocus_for_testing() {
    return enabled_suggestions_from_last_onfocus_;
  }

 private:
  // Callback that is run after enabled_suggestions is received.
  void ProcessOnSurroundingTextChanged(
      const std::u16string& text,
      gfx::Range selection_range,
      const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions);

  // Returns if any suggestion text should be displayed according to the
  // surrounding text information.
  bool TrySuggestWithSurroundingText(
      const std::u16string& text,
      gfx::Range selection_range,
      const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions);

  void DismissSuggestion();

  bool IsEmojiSuggestAdditionEnabled();

  bool IsMultiWordSuggestEnabled();

  bool IsDiacriticsOnPhysicalKeyboardLongpressEnabled();

  // Checks the text before cursor, emits metric if any assistive prefix is
  // matched.
  void RecordAssistiveMatchMetrics(
      const std::u16string& text,
      gfx::Range selection_range,
      const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions);

  void RecordAssistiveMatchMetricsForAssistiveType(
      AssistiveType type,
      const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions);

  // Only the first applicable reason in DisabledReason enum is returned.
  DisabledReason GetDisabledReasonForEmoji(
      const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions);

  // Only the first applicable reason in DisabledReason enum is returned.
  DisabledReason GetDisabledReasonForMultiWord(
      const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions);

  AssistiveFeature GetAssistiveFeatureForType(AssistiveType type);

  bool IsAssistiveTypeEnabled(AssistiveType type);

  bool IsAssistiveTypeAllowedInBrowserContext(
      AssistiveType type,
      const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions);

  bool WithinGrammarFragment();

  void ProcessExternalSuggestions(
      const std::vector<ime::AssistiveSuggestion>& suggestions,
      const std::optional<ime::SuggestionsTextContext>& context,
      const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions);

  // This records any text input state metrics for each relevant assistive
  // feature. It is called once when a text field gains focus.
  void RecordTextInputStateMetrics(
      const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions);

  // Does longpress related processing (if enabled).
  // Returns true if we block the keyevent from passing to IME, and stop
  // dispatch.
  // Returns false, if we want IME to process the event and dispatch it.
  AssistiveSuggesterKeyResult HandleLongpressEnabledKeyEvent(
      const ui::KeyEvent& key_character);

  void HandleEnabledSuggestionsOnFocus(
      const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions);

  void OnLongpressDetected();

  // Accepts or dismisses a Ctrl+V long-press suggestion based on the exit
  // status of the clipboard history menu, as indicated by `will_paste_item`.
  void OnClipboardHistoryMenuClosing(bool will_paste_item);

  raw_ptr<Profile> profile_;
  EmojiSuggester emoji_suggester_;
  MultiWordSuggester multi_word_suggester_;
  LongpressDiacriticsSuggester longpress_diacritics_suggester_;
  LongpressControlVSuggester longpress_control_v_suggester_;
  std::unique_ptr<AssistiveSuggesterSwitch> suggester_switch_;

  // The id of the currently active input engine.
  std::string active_engine_id_;

  // ID of the focused text field, nullopt if none focused.
  std::optional<int> focused_context_id_;

  // KeyEvent of the held down key at key down. nullopt if no longpress in
  // progress.
  std::optional<ui::KeyEvent> current_longpress_keydown_;

  // Timer for longpress. Starts when key is held down. Fires when successfully
  // held down for a specified longpress duration.
  base::OneShotTimer longpress_timer_;

  // The current suggester in use, nullptr means no suggestion is shown.
  raw_ptr<Suggester> current_suggester_ = nullptr;

  std::optional<AssistiveSuggesterSwitch::EnabledSuggestions>
      enabled_suggestions_from_last_onfocus_;

  std::u16string last_surrounding_text_ = u"";

  // Keeps track if there is a key being held down currently which was already
  // recorded for the auto repeat suppressed metric.
  bool auto_repeat_suppress_metric_emitted_ = false;

  int last_cursor_pos_ = 0;

  TextInputMethod::InputContext context_;

  base::WeakPtrFactory<AssistiveSuggester> weak_ptr_factory_{this};
};

}  // namespace ash::input_method

#endif  // CHROME_BROWSER_ASH_INPUT_METHOD_ASSISTIVE_SUGGESTER_H_