Commit cae5f871 authored by James Cook's avatar James Cook Committed by Commit Bot

chromeos: Fix dictation into keyboard shortcut viewer app

Chrome creates a second InputMethodChromeOS when a remote mojo app
opens. This sets a new IMEInputContextHandler on IMEBridge, but does
not trigger an "engine switch".

Make sure the dictation code looks up the current IMEInputContextHandler
each time it tries to inject text.

Bug: 876448
Test: added to interactive_ui_tests
Change-Id: I100a62920ffb397ec823a4bcddb1adf94ec5f6a3
Reviewed-on: https://chromium-review.googlesource.com/1187135
Commit-Queue: James Cook <jamescook@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#585632}
parent 50ca13ac
...@@ -32,14 +32,19 @@ std::string GetUserLocale(Profile* profile) { ...@@ -32,14 +32,19 @@ std::string GetUserLocale(Profile* profile) {
return user_locale.empty() ? kDefaultProfileLocale : user_locale; return user_locale.empty() ? kDefaultProfileLocale : user_locale;
} }
// Returns the current input context. This may change during the session, even
// if the IME engine does not change, because remote mojo applications have
// their own instance of InputMethodChromeOS. See comment on InputMethodBridge.
ui::IMEInputContextHandlerInterface* GetInputContext() {
return ui::IMEBridge::Get()->GetInputContextHandler();
}
} // namespace } // namespace
DictationChromeos::DictationChromeos(Profile* profile) DictationChromeos::DictationChromeos(Profile* profile)
: profile_(profile), weak_ptr_factory_(this) { : composition_(std::make_unique<ui::CompositionText>()),
composition_ = std::make_unique<ui::CompositionText>(); profile_(profile),
input_context_ = ui::IMEBridge::Get()->GetInputContextHandler(); weak_ptr_factory_(this) {}
ui::IMEBridge::Get()->SetObserver(this);
}
DictationChromeos::~DictationChromeos() = default; DictationChromeos::~DictationChromeos() = default;
...@@ -68,8 +73,9 @@ void DictationChromeos::OnSpeechResult(const base::string16& query, ...@@ -68,8 +73,9 @@ void DictationChromeos::OnSpeechResult(const base::string16& query,
if (AccessibilityManager::Get()->IsSpokenFeedbackEnabled()) if (AccessibilityManager::Get()->IsSpokenFeedbackEnabled())
return; return;
if (input_context_) ui::IMEInputContextHandlerInterface* input_context = GetInputContext();
input_context_->UpdateCompositionText(*composition_, 0, true); if (input_context)
input_context->UpdateCompositionText(*composition_, 0, true);
return; return;
} }
DictationOff(); DictationOff();
...@@ -90,10 +96,6 @@ void DictationChromeos::OnSpeechRecognitionStateChanged( ...@@ -90,10 +96,6 @@ void DictationChromeos::OnSpeechRecognitionStateChanged(
void DictationChromeos::GetSpeechAuthParameters(std::string* auth_scope, void DictationChromeos::GetSpeechAuthParameters(std::string* auth_scope,
std::string* auth_token) {} std::string* auth_token) {}
void DictationChromeos::OnRequestSwitchEngine() {
input_context_ = ui::IMEBridge::Get()->GetInputContextHandler();
}
void DictationChromeos::DictationOff() { void DictationChromeos::DictationOff() {
if (!speech_recognizer_) if (!speech_recognizer_)
return; return;
...@@ -101,8 +103,9 @@ void DictationChromeos::DictationOff() { ...@@ -101,8 +103,9 @@ void DictationChromeos::DictationOff() {
if (!composition_->text.empty()) { if (!composition_->text.empty()) {
media::SoundsManager::Get()->Play(chromeos::SOUND_DICTATION_END); media::SoundsManager::Get()->Play(chromeos::SOUND_DICTATION_END);
if (input_context_) ui::IMEInputContextHandlerInterface* input_context = GetInputContext();
input_context_->CommitText(base::UTF16ToASCII(composition_->text)); if (input_context)
input_context->CommitText(base::UTF16ToUTF8(composition_->text));
composition_->text = base::string16(); composition_->text = base::string16();
} else { } else {
......
...@@ -11,11 +11,9 @@ ...@@ -11,11 +11,9 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "chrome/browser/speech/speech_recognizer_delegate.h" #include "chrome/browser/speech/speech_recognizer_delegate.h"
#include "content/public/browser/speech_recognition_session_preamble.h" #include "content/public/browser/speech_recognition_session_preamble.h"
#include "ui/base/ime/ime_bridge_observer.h"
namespace ui { namespace ui {
struct CompositionText; struct CompositionText;
class IMEInputContextHandlerInterface;
} // namespace ui } // namespace ui
class Profile; class Profile;
...@@ -24,8 +22,7 @@ class SpeechRecognizer; ...@@ -24,8 +22,7 @@ class SpeechRecognizer;
namespace chromeos { namespace chromeos {
// Provides global dictation (type what you speak) on Chrome OS. // Provides global dictation (type what you speak) on Chrome OS.
class DictationChromeos : public SpeechRecognizerDelegate, class DictationChromeos : public SpeechRecognizerDelegate {
ui::IMEBridgeObserver {
public: public:
explicit DictationChromeos(Profile* profile); explicit DictationChromeos(Profile* profile);
~DictationChromeos() override; ~DictationChromeos() override;
...@@ -34,6 +31,8 @@ class DictationChromeos : public SpeechRecognizerDelegate, ...@@ -34,6 +31,8 @@ class DictationChromeos : public SpeechRecognizerDelegate,
bool OnToggleDictation(); bool OnToggleDictation();
private: private:
friend class DictationTest;
// SpeechRecognizerDelegate: // SpeechRecognizerDelegate:
void OnSpeechResult(const base::string16& query, bool is_final) override; void OnSpeechResult(const base::string16& query, bool is_final) override;
void OnSpeechSoundLevelChanged(int16_t level) override; void OnSpeechSoundLevelChanged(int16_t level) override;
...@@ -42,21 +41,16 @@ class DictationChromeos : public SpeechRecognizerDelegate, ...@@ -42,21 +41,16 @@ class DictationChromeos : public SpeechRecognizerDelegate,
void GetSpeechAuthParameters(std::string* auth_scope, void GetSpeechAuthParameters(std::string* auth_scope,
std::string* auth_token) override; std::string* auth_token) override;
// IMEBridgeObserver
void OnRequestSwitchEngine() override;
// Saves current dictation result and stops listening. // Saves current dictation result and stops listening.
void DictationOff(); void DictationOff();
std::unique_ptr<SpeechRecognizer> speech_recognizer_; std::unique_ptr<SpeechRecognizer> speech_recognizer_;
std::unique_ptr<ui::CompositionText> composition_; std::unique_ptr<ui::CompositionText> composition_;
ui::IMEInputContextHandlerInterface* input_context_;
Profile* profile_; Profile* profile_;
base::WeakPtrFactory<DictationChromeos> weak_ptr_factory_; base::WeakPtrFactory<DictationChromeos> weak_ptr_factory_;
friend class DictationTest;
DISALLOW_COPY_AND_ASSIGN(DictationChromeos); DISALLOW_COPY_AND_ASSIGN(DictationChromeos);
}; };
......
...@@ -122,4 +122,27 @@ IN_PROC_BROWSER_TEST_F(DictationTest, UserEndsDictationWhenChromeVoxEnabled) { ...@@ -122,4 +122,27 @@ IN_PROC_BROWSER_TEST_F(DictationTest, UserEndsDictationWhenChromeVoxEnabled) {
EXPECT_EQ(kFinalSpeechResult, input_context_handler_->last_commit_text()); EXPECT_EQ(kFinalSpeechResult, input_context_handler_->last_commit_text());
} }
IN_PROC_BROWSER_TEST_F(DictationTest, SwitchInputContext) {
// Turn on dictation and say something.
AccessibilityManager::Get()->ToggleDictation();
SendSpeechResult(kFirstSpeechResult, true /* is_final */);
// Speech goes to the default IMEInputContextHandler.
EXPECT_EQ(kFirstSpeechResult, input_context_handler_->last_commit_text());
// Simulate a remote app instantiating a new IMEInputContextHandler, like the
// keyboard shortcut viewer app creating a second InputMethodChromeOS.
ui::MockIMEInputContextHandler input_context_handler2;
ui::IMEBridge::Get()->SetInputContextHandler(&input_context_handler2);
// Turn on dictation and say something else.
AccessibilityManager::Get()->ToggleDictation();
SendSpeechResult(kSecondSpeechResult, true /* is_final */);
// Speech goes to the new IMEInputContextHandler.
EXPECT_EQ(kSecondSpeechResult, input_context_handler2.last_commit_text());
ui::IMEBridge::Get()->SetInputContextHandler(nullptr);
}
} // namespace chromeos } // namespace chromeos
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment