| // Copyright 2022 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_NATIVE_INPUT_METHOD_ENGINE_OBSERVER_H_ |
| #define CHROME_BROWSER_ASH_INPUT_METHOD_NATIVE_INPUT_METHOD_ENGINE_OBSERVER_H_ |
| |
| #include <optional> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/scoped_observation.h" |
| #include "chrome/browser/ash/input_method/assistive_suggester.h" |
| #include "chrome/browser/ash/input_method/assistive_suggester_switch.h" |
| #include "chrome/browser/ash/input_method/autocorrect_manager.h" |
| #include "chrome/browser/ash/input_method/editor_event_sink.h" |
| #include "chrome/browser/ash/input_method/grammar_manager.h" |
| #include "chrome/browser/ash/input_method/input_method_engine.h" |
| #include "chrome/browser/ash/input_method/pref_change_recorder.h" |
| #include "chrome/browser/ash/input_method/suggestions_collector.h" |
| #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h" |
| #include "chromeos/ash/services/ime/public/cpp/assistive_suggestions.h" |
| #include "chromeos/ash/services/ime/public/mojom/connection_factory.mojom.h" |
| #include "chromeos/ash/services/ime/public/mojom/input_engine.mojom.h" |
| #include "chromeos/ash/services/ime/public/mojom/input_method.mojom.h" |
| #include "chromeos/ash/services/ime/public/mojom/input_method_host.mojom.h" |
| #include "chromeos/ash/services/ime/public/mojom/japanese_settings.mojom.h" |
| #include "components/prefs/pref_change_registrar.h" |
| #include "components/prefs/pref_service.h" |
| #include "mojo/public/cpp/bindings/associated_receiver.h" |
| #include "mojo/public/cpp/bindings/associated_remote.h" |
| #include "mojo/public/cpp/bindings/remote.h" |
| #include "ui/base/ime/ash/text_input_method.h" |
| #include "ui/base/ime/character_composer.h" |
| |
| namespace ash { |
| namespace input_method { |
| |
| bool CanRouteToNativeMojoEngine(const std::string& engine_id); |
| |
| class NativeInputMethodEngineObserver : public InputMethodEngineObserver, |
| public ime::mojom::InputMethodHost { |
| public: |
| // |ime_base_observer| is to forward events to extension during this |
| // migration. It will be removed when the official extension is completely |
| // migrated. |
| // |use_ime_service| should always be |true| in prod code, and may only be |
| // |false| in browser tests that need to avoid connecting to the Mojo IME |
| // service which can involve loading libimedecoder.so unsupported in tests. |
| // TODO(crbug/1197005): Migrate native_input_method_engine_browsertest suite |
| // to e2e Tast tests and unit tests, then dismantle this for-test-only flag. |
| NativeInputMethodEngineObserver( |
| PrefService* prefs, |
| EditorEventSink* editor_event_sink, |
| std::unique_ptr<InputMethodEngineObserver> ime_base_observer, |
| std::unique_ptr<AssistiveSuggester> assistive_suggester, |
| std::unique_ptr<AutocorrectManager> autocorrect_manager, |
| std::unique_ptr<SuggestionsCollector> suggestions_collector, |
| std::unique_ptr<GrammarManager> grammar_manager, |
| bool use_ime_service); |
| ~NativeInputMethodEngineObserver() override; |
| |
| // InputMethodEngineObserver: |
| void OnActivate(const std::string& engine_id) override; |
| void OnFocus(const std::string& engine_id, |
| int context_id, |
| const TextInputMethod::InputContext& context) override; |
| void OnBlur(const std::string& engine_id, int context_id) override; |
| void OnKeyEvent(const std::string& engine_id, |
| const ui::KeyEvent& event, |
| TextInputMethod::KeyEventDoneCallback callback) override; |
| void OnReset(const std::string& engine_id) override; |
| void OnDeactivated(const std::string& engine_id) override; |
| void OnCaretBoundsChanged(const gfx::Rect& caret_bounds) override; |
| void OnSurroundingTextChanged(const std::string& engine_id, |
| const std::u16string& text, |
| gfx::Range selection_range, |
| int offset_pos) override; |
| void OnCandidateClicked(const std::string& component_id, |
| int candidate_id, |
| MouseButtonEvent button) override; |
| void OnAssistiveWindowButtonClicked( |
| const ui::ime::AssistiveWindowButton& button) override; |
| void OnAssistiveWindowChanged( |
| const ash::ime::AssistiveWindow& window) override; |
| void OnMenuItemActivated(const std::string& component_id, |
| const std::string& menu_id) override; |
| void OnScreenProjectionChanged(bool is_projected) override; |
| void OnSuggestionsChanged( |
| const std::vector<std::string>& suggestions) override; |
| void OnInputMethodOptionsChanged(const std::string& engine_id) override; |
| |
| // ime::mojom::InputMethodHost: |
| void CommitText( |
| const std::u16string& text, |
| ime::mojom::CommitTextCursorBehavior cursor_behavior) override; |
| void DEPRECATED_SetComposition( |
| const std::u16string& text, |
| std::vector<ime::mojom::CompositionSpanPtr> spans) override; |
| void SetComposition(const std::u16string& text, |
| std::vector<ime::mojom::CompositionSpanPtr> spans, |
| uint32_t new_cursor_position) override; |
| void SetCompositionRange(uint32_t start_index, uint32_t end_index) override; |
| void FinishComposition() override; |
| void DeleteSurroundingText(uint32_t num_before_cursor, |
| uint32_t num_after_cursor) override; |
| void ReplaceSurroundingText(uint32_t num_before_cursor, |
| uint32_t num_after_cursor, |
| const std::u16string& text) override; |
| void HandleAutocorrect( |
| ime::mojom::AutocorrectSpanPtr autocorrect_span) override; |
| void RequestSuggestions(ime::mojom::SuggestionsRequestPtr request, |
| RequestSuggestionsCallback callback) override; |
| void DisplaySuggestions( |
| const std::vector<ime::AssistiveSuggestion>& suggestions, |
| const std::optional<ime::SuggestionsTextContext>& context) override; |
| void UpdateCandidatesWindow(ime::mojom::CandidatesWindowPtr window) override; |
| void RecordUkm(ime::mojom::UkmEntryPtr entry) override; |
| void DEPRECATED_ReportKoreanAction(ime::mojom::KoreanAction action) override; |
| void DEPRECATED_ReportKoreanSettings( |
| ime::mojom::KoreanSettingsPtr settings) override; |
| void DEPRECATED_ReportSuggestionOpportunity( |
| ime::AssistiveSuggestionMode mode) override; |
| void ReportHistogramSample(base::Histogram* histogram, |
| uint16_t value) override; |
| void UpdateQuickSettings( |
| ime::mojom::InputMethodQuickSettingsPtr quick_settings) override; |
| |
| // Called when suggestions are collected from the system via |
| // suggestions_collector_. |
| void OnSuggestionsGathered(RequestSuggestionsCallback request_callback, |
| ime::mojom::SuggestionsResponsePtr response); |
| |
| bool IsReadyForTesting(); |
| |
| // Flush all relevant Mojo pipes. |
| void FlushForTesting(); |
| |
| // Returns whether this is connected to the input engine. |
| bool IsConnectedForTesting() { return IsInputMethodBound(); } |
| |
| void OnProfileWillBeDestroyed(); |
| |
| private: |
| struct SurroundingText { |
| std::u16string text; |
| gfx::Range selection_range; |
| int offset_pos = 0; |
| }; |
| |
| enum TextClientState { |
| kPending = 0, |
| kActive = 1, |
| }; |
| |
| struct TextClient { |
| int context_id; |
| TextClientState state; |
| }; |
| |
| void SendSurroundingTextToNativeMojoEngine( |
| const SurroundingText& surrounding_text); |
| |
| bool ShouldRouteToRuleBasedEngine(const std::string& engine_id) const; |
| bool ShouldRouteToNativeMojoEngine(const std::string& engine_id) const; |
| |
| void OnConnectionFactoryBound(bool bound); |
| |
| void OnJapaneseSettingsReceived(ime::mojom::JapaneseConfigPtr config); |
| void OnJapaneseDecoderConnected(bool bound); |
| void ConnectToImeService(const std::string& engine_id); |
| |
| void HandleOnFocusAsyncForNativeMojoEngine( |
| const std::string& engine_id, |
| int context_id, |
| const TextInputMethod::InputContext& context, |
| const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions); |
| |
| bool IsInputMethodBound(); |
| bool IsInputMethodConnected(); |
| bool IsTextClientActive(); |
| void OnFocusAck(int context_id, |
| bool on_focus_success, |
| ime::mojom::InputMethodMetadataPtr metadata); |
| |
| // Not owned by this class. |
| raw_ptr<PrefService> prefs_ = nullptr; |
| raw_ptr<EditorEventSink> editor_event_sink_; |
| |
| std::unique_ptr<InputMethodEngineObserver> ime_base_observer_; |
| mojo::Remote<ime::mojom::InputEngineManager> remote_manager_; |
| mojo::Remote<ime::mojom::ConnectionFactory> connection_factory_; |
| mojo::AssociatedRemote<ime::mojom::InputMethod> input_method_; |
| // TODO(b/232341104): Delete this connection once Japanese settings have been |
| // migrated completely |
| mojo::AssociatedRemote<ime::mojom::JapaneseDecoder> japanese_decoder_; |
| mojo::AssociatedReceiver<ime::mojom::InputMethodHost> host_receiver_{this}; |
| |
| std::unique_ptr<AssistiveSuggester> assistive_suggester_; |
| std::unique_ptr<AutocorrectManager> autocorrect_manager_; |
| std::unique_ptr<SuggestionsCollector> suggestions_collector_; |
| std::unique_ptr<GrammarManager> grammar_manager_; |
| |
| std::optional<PrefChangeRecorder> pref_change_recorder_; |
| |
| ui::CharacterComposer character_composer_; |
| |
| SurroundingText last_surrounding_text_; |
| |
| std::optional<TextClient> text_client_; |
| |
| // |use_ime_service| should always be |true| in prod code, and may only be |
| // |false| in browser tests that need to avoid connecting to the Mojo IME |
| // service which can involve loading libimedecoder.so unsupported in tests. |
| // TODO(crbug/1197005): Migrate native_input_method_engine_browsertest suite |
| // to e2e Tast tests and unit tests, then dismantle this for-test-only flag. |
| bool use_ime_service_ = true; |
| |
| // Timer used to show candidates with a delay. As rendering candidates is |
| // slow, it is better to do it asynchronously. |
| base::OneShotTimer update_candidates_timer_; |
| |
| base::WeakPtrFactory<NativeInputMethodEngineObserver> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace input_method |
| } // namespace ash |
| |
| #endif // CHROME_BROWSER_ASH_INPUT_METHOD_NATIVE_INPUT_METHOD_ENGINE_OBSERVER_H_ |