blob: bc8a227767774a59eb82eed89cb04e8363a93c2e [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/auto_reset.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/ui_test_utils.h"
#include "extensions/test/extension_test_message_listener.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/dummy_text_input_client.h"
#include "ui/base/ime/input_method.h"
namespace extensions {
class InputImeApiTest : public ExtensionApiTest {
public:
InputImeApiTest() {}
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
ExtensionApiTest::SetUpCommandLine(command_line);
command_line->AppendSwitch(switches::kEnableInputImeAPI);
}
// Sets the private flag of |track_key_events_for_testing_| in InputMethod.
void SetTrackKeyEvents(ui::InputMethod* input_method, bool track) {
input_method->track_key_events_for_testing_ = track;
}
// Returns true if the key events get from input method equals to the expected
// key events.
bool CompareKeyEvents(
const std::vector<std::unique_ptr<ui::KeyEvent>>& expected_key_events,
ui::InputMethod* input_method) {
if (expected_key_events.size() != GetKeyEvents(input_method).size())
return false;
for (size_t i = 0; i < expected_key_events.size(); i++) {
ui::KeyEvent* event1 = expected_key_events[i].get();
ui::KeyEvent* event2 = GetKeyEvents(input_method)[i].get();
if (event1->type() != event2->type() ||
event1->key_code() != event2->key_code() ||
event1->flags() != event2->flags()) {
return false;
}
}
return true;
}
private:
// Returns the tracked key events of using input.ime.sendKeyEvents API.
const std::vector<std::unique_ptr<ui::KeyEvent>>& GetKeyEvents(
ui::InputMethod* input_method) {
return input_method->GetKeyEventsForTesting();
}
DISALLOW_COPY_AND_ASSIGN(InputImeApiTest);
};
// TODO(crbug.com/882338) This test fails basically once per try run.
// See bug for details.
IN_PROC_BROWSER_TEST_F(InputImeApiTest, DISABLED_BasicApiTest) {
// Manipulates the focused text input client because the follow cursor
// window requires the text input focus.
ui::InputMethod* input_method =
browser()->window()->GetNativeWindow()->GetHost()->GetInputMethod();
std::unique_ptr<ui::DummyTextInputClient> client(
new ui::DummyTextInputClient(ui::TEXT_INPUT_TYPE_TEXT));
input_method->SetFocusedTextInputClient(client.get());
ExtensionFunction::ScopedUserGestureForTests scoped_user_gesture;
base::AutoReset<bool> auto_reset_disable_bubble(
&InputImeActivateFunction::disable_bubble_for_testing_, true);
SetTrackKeyEvents(input_method, true);
// Listens for the input.ime.onBlur event.
ExtensionTestMessageListener blur_listener("get_blur_event", false);
ASSERT_TRUE(RunExtensionTest("input_ime_nonchromeos")) << message_;
// Test the input.ime.commitText API.
const std::vector<base::string16>& insert_text_history =
client->insert_text_history();
ASSERT_EQ(1UL, insert_text_history.size());
EXPECT_EQ(base::UTF8ToUTF16("test_commit_text"), insert_text_history[0]);
// Test the input.ime.setComposition API.
ui::CompositionText composition;
composition.text = base::UTF8ToUTF16("test_set_composition");
composition.ime_text_spans.push_back(ui::ImeTextSpan(
ui::ImeTextSpan::Type::kComposition, 0, composition.text.length(),
ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT));
composition.selection = gfx::Range(2, 2);
const std::vector<ui::CompositionText>& composition_history =
client->composition_history();
ASSERT_EQ(2UL, composition_history.size());
EXPECT_EQ(base::UTF8ToUTF16("test_set_composition"),
composition_history[0].text);
EXPECT_EQ(base::UTF8ToUTF16(""), composition_history[1].text);
// Tests input.ime.onBlur API should get event when focusing to another
// text input client.
std::unique_ptr<ui::DummyTextInputClient> client2(
new ui::DummyTextInputClient(ui::TEXT_INPUT_TYPE_TEXT));
input_method->SetFocusedTextInputClient(client2.get());
ASSERT_TRUE(blur_listener.WaitUntilSatisfied()) << message_;
input_method->DetachTextInputClient(client2.get());
}
IN_PROC_BROWSER_TEST_F(InputImeApiTest, SendKeyEventsOnNormalPage) {
// Navigates to special page that sendKeyEvents API has limition with.
ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
// Manipulates the focused text input client because the follow cursor
// window requires the text input focus.
ui::InputMethod* input_method =
browser()->window()->GetNativeWindow()->GetHost()->GetInputMethod();
std::unique_ptr<ui::DummyTextInputClient> client(
new ui::DummyTextInputClient(ui::TEXT_INPUT_TYPE_TEXT));
input_method->SetFocusedTextInputClient(client.get());
ExtensionFunction::ScopedUserGestureForTests scoped_user_gesture;
base::AutoReset<bool> auto_reset_disable_bubble(
&InputImeActivateFunction::disable_bubble_for_testing_, true);
SetTrackKeyEvents(input_method, true);
ASSERT_TRUE(RunExtensionTest("input_ime_nonchromeos")) << message_;
std::vector<std::unique_ptr<ui::KeyEvent>> key_events;
key_events.push_back(std::unique_ptr<ui::KeyEvent>(
new ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE)));
key_events.push_back(std::unique_ptr<ui::KeyEvent>(
new ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_A, ui::EF_NONE)));
key_events.push_back(std::unique_ptr<ui::KeyEvent>(
new ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_CONTROL_DOWN)));
key_events.push_back(std::unique_ptr<ui::KeyEvent>(
new ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_A, ui::EF_CONTROL_DOWN)));
key_events.push_back(std::unique_ptr<ui::KeyEvent>(
new ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_TAB, ui::EF_NONE)));
EXPECT_TRUE(CompareKeyEvents(key_events, input_method));
input_method->DetachTextInputClient(client.get());
}
// TODO(https://crbug.com/795631): This test is failing on the Linux bot.
#if defined(OS_LINUX)
IN_PROC_BROWSER_TEST_F(InputImeApiTest, DISABLED_SendKeyEventsOnSpecialPage) {
#else
IN_PROC_BROWSER_TEST_F(InputImeApiTest, SendKeyEventsOnSpecialPage) {
#endif
// Navigates to special page that sendKeyEvents API has limition with.
ui_test_utils::NavigateToURL(browser(), GURL("chrome://flags"));
ui::InputMethod* input_method =
browser()->window()->GetNativeWindow()->GetHost()->GetInputMethod();
std::unique_ptr<ui::DummyTextInputClient> client(
new ui::DummyTextInputClient(ui::TEXT_INPUT_TYPE_TEXT));
input_method->SetFocusedTextInputClient(client.get());
ExtensionFunction::ScopedUserGestureForTests scoped_user_gesture;
base::AutoReset<bool> auto_reset_disable_bubble(
&InputImeActivateFunction::disable_bubble_for_testing_, true);
SetTrackKeyEvents(input_method, true);
ASSERT_TRUE(RunExtensionTest("input_ime_nonchromeos")) << message_;
std::vector<std::unique_ptr<ui::KeyEvent>> key_events;
key_events.push_back(std::unique_ptr<ui::KeyEvent>(
new ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE)));
key_events.push_back(std::unique_ptr<ui::KeyEvent>(
new ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_A, ui::EF_NONE)));
EXPECT_TRUE(CompareKeyEvents(key_events, input_method));
input_method->DetachTextInputClient(client.get());
}
} // namespace extensions