Commit 27273fd1 authored by Jing Wang's avatar Jing Wang Committed by Commit Bot

Handle Engine failure better.

1. Add an extra error param to GetEngineIfActive, so that we can tell if
it fails because the engine is unavailable or inactive.
2. Add LOGs for engine errors.
3. Add error handling to more functions.
4. Add some helper functions to reduce code duplication.
5. Minor change on constants name for readability.
6. Disable some browser tests, they were actually testing nothing before (because there was no active engine, they actually skipped everything...). Eventually we should rewrite those tests in the new fashion as https://cs.chromium.org/chromium/src/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc

R=keithlee, shend, shuchen

Bug: 1024606
Change-Id: I9902e42a472122c5c1a02c36e70f71b52cdd80d1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1933855Reviewed-by: default avatarKeith Lee <keithlee@chromium.org>
Reviewed-by: default avatarShu Chen <shuchen@chromium.org>
Reviewed-by: default avatarDarren Shen <shend@chromium.org>
Commit-Queue: Keith Lee <keithlee@chromium.org>
Commit-Queue: Jing Wang <jiwan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#719454}
parent d16e059d
......@@ -80,7 +80,20 @@ namespace {
const char kXkbPrefix[] = "xkb:";
const char kErrorFailToShowInputView[] =
"Unable to show the input view window.";
const char kInputImeApiEngineNotAvaliable[] = "Engine is not available";
const char kErrorRouterNotAvailable[] = "The router is not available.";
InputMethodEngineBase* GetEngineIfActive(
content::BrowserContext* browser_context,
const std::string& extension_id,
std::string* error) {
Profile* profile = Profile::FromBrowserContext(browser_context);
extensions::InputImeEventRouter* event_router =
extensions::GetInputImeEventRouter(profile);
CHECK(event_router) << kErrorRouterNotAvailable;
InputMethodEngineBase* engine =
event_router->GetEngineIfActive(extension_id, error);
return engine;
}
} // namespace
......@@ -344,77 +357,69 @@ ExtensionFunction::ResponseAction InputMethodPrivateSetSettingFunction::Run() {
ExtensionFunction::ResponseAction
InputMethodPrivateSetCompositionRangeFunction::Run() {
InputImeEventRouter* event_router =
GetInputImeEventRouter(Profile::FromBrowserContext(browser_context()));
std::string error;
InputMethodEngineBase* engine =
event_router ? event_router->GetEngineIfActive(extension_id()) : nullptr;
if (engine) {
const auto parent_params = SetCompositionRange::Params::Create(*args_);
const auto& params = parent_params->parameters;
std::vector<InputMethodEngineBase::SegmentInfo> segments;
if (params.segments) {
for (const auto& segments_arg : *params.segments) {
InputMethodEngineBase::SegmentInfo segment_info;
segment_info.start = segments_arg.start;
segment_info.end = segments_arg.end;
switch (segments_arg.style) {
case input_method_private::UNDERLINE_STYLE_UNDERLINE:
segment_info.style = InputMethodEngineBase::SEGMENT_STYLE_UNDERLINE;
break;
case input_method_private::UNDERLINE_STYLE_DOUBLEUNDERLINE:
segment_info.style =
InputMethodEngineBase::SEGMENT_STYLE_DOUBLE_UNDERLINE;
break;
case input_method_private::UNDERLINE_STYLE_NOUNDERLINE:
segment_info.style =
InputMethodEngineBase::SEGMENT_STYLE_NO_UNDERLINE;
break;
case input_method_private::UNDERLINE_STYLE_NONE:
EXTENSION_FUNCTION_VALIDATE(false);
break;
}
segments.push_back(segment_info);
}
} else {
// Default to a single segment that spans the entire range.
GetEngineIfActive(browser_context(), extension_id(), &error);
if (!engine)
return RespondNow(Error(error));
const auto parent_params = SetCompositionRange::Params::Create(*args_);
const auto& params = parent_params->parameters;
std::vector<InputMethodEngineBase::SegmentInfo> segments;
if (params.segments) {
for (const auto& segments_arg : *params.segments) {
InputMethodEngineBase::SegmentInfo segment_info;
segment_info.start = 0;
segment_info.end = params.selection_before + params.selection_after;
segment_info.style = InputMethodEngineBase::SEGMENT_STYLE_UNDERLINE;
segment_info.start = segments_arg.start;
segment_info.end = segments_arg.end;
switch (segments_arg.style) {
case input_method_private::UNDERLINE_STYLE_UNDERLINE:
segment_info.style = InputMethodEngineBase::SEGMENT_STYLE_UNDERLINE;
break;
case input_method_private::UNDERLINE_STYLE_DOUBLEUNDERLINE:
segment_info.style =
InputMethodEngineBase::SEGMENT_STYLE_DOUBLE_UNDERLINE;
break;
case input_method_private::UNDERLINE_STYLE_NOUNDERLINE:
segment_info.style =
InputMethodEngineBase::SEGMENT_STYLE_NO_UNDERLINE;
break;
case input_method_private::UNDERLINE_STYLE_NONE:
EXTENSION_FUNCTION_VALIDATE(false);
break;
}
segments.push_back(segment_info);
}
std::string error;
if (!engine->SetCompositionRange(params.context_id, params.selection_before,
params.selection_after, segments,
&error)) {
auto results = std::make_unique<base::ListValue>();
results->Append(std::make_unique<base::Value>(false));
return RespondNow(ErrorWithArguments(std::move(results), error));
}
} else {
// Default to a single segment that spans the entire range.
InputMethodEngineBase::SegmentInfo segment_info;
segment_info.start = 0;
segment_info.end = params.selection_before + params.selection_after;
segment_info.style = InputMethodEngineBase::SEGMENT_STYLE_UNDERLINE;
segments.push_back(segment_info);
}
if (!engine->SetCompositionRange(params.context_id, params.selection_before,
params.selection_after, segments, &error)) {
auto results = std::make_unique<base::ListValue>();
results->Append(std::make_unique<base::Value>(false));
return RespondNow(ErrorWithArguments(std::move(results), error));
}
return RespondNow(OneArgument(std::make_unique<base::Value>(true)));
}
ExtensionFunction::ResponseAction
InputMethodPrivateSetSelectionRangeFunction::Run() {
InputImeEventRouter* event_router =
GetInputImeEventRouter(Profile::FromBrowserContext(browser_context()));
std::string error;
InputMethodEngineBase* engine =
event_router ? event_router->GetEngineIfActive(extension_id()) : nullptr;
if (!engine) {
auto results = std::make_unique<base::ListValue>();
results->Append(std::make_unique<base::Value>(false));
return RespondNow(
ErrorWithArguments(std::move(results), kInputImeApiEngineNotAvaliable));
}
GetEngineIfActive(browser_context(), extension_id(), &error);
if (!engine)
return RespondNow(Error(error));
std::unique_ptr<SetSelectionRange::Params> parent_params(
SetSelectionRange::Params::Create(*args_));
const SetSelectionRange::Params::Parameters& params =
parent_params->parameters;
std::string error;
if (!engine->SetSelectionRange(params.context_id, *params.selection_start,
*params.selection_end, &error)) {
auto results = std::make_unique<base::ListValue>();
......
......@@ -19,9 +19,22 @@ namespace SendKeyEvents = extensions::api::input_ime::SendKeyEvents;
using input_method::InputMethodEngineBase;
namespace {
const char kInputImeApiErrorEngineNotAvailable[] = "Engine is not available";
const char kInputImeApiErrorSetKeyEventsFail[] = "Could not send key events";
const char kErrorRouterNotAvailable[] = "The router is not available.";
const char kErrorSetKeyEventsFail[] = "Could not send key events";
InputMethodEngineBase* GetEngineIfActive(Profile* profile,
const std::string& extension_id,
std::string* error) {
extensions::InputImeEventRouter* event_router =
extensions::GetInputImeEventRouter(profile);
CHECK(event_router) << kErrorRouterNotAvailable;
InputMethodEngineBase* engine =
event_router->GetEngineIfActive(extension_id, error);
return engine;
}
} // namespace
namespace ui {
ImeObserver::ImeObserver(const std::string& extension_id, Profile* profile)
......@@ -89,13 +102,13 @@ void ImeObserver::OnKeyEvent(
return;
}
extensions::InputImeEventRouter* event_router =
extensions::GetInputImeEventRouter(profile_);
if (!event_router || !event_router->GetEngineIfActive(extension_id_))
std::string error;
InputMethodEngineBase* engine =
GetEngineIfActive(profile_, extension_id_, &error);
if (!engine)
return;
const std::string request_id =
event_router->GetEngineIfActive(extension_id_)
->AddPendingKeyEvent(component_id, std::move(callback));
engine->AddPendingKeyEvent(component_id, std::move(callback));
input_ime::KeyboardEvent key_data_value;
key_data_value.type = input_ime::ParseKeyboardEventType(event.type);
......@@ -303,92 +316,86 @@ void InputImeEventRouterFactory::RemoveProfile(Profile* profile) {
ExtensionFunction::ResponseAction InputImeKeyEventHandledFunction::Run() {
std::unique_ptr<KeyEventHandled::Params> params(
KeyEventHandled::Params::Create(*args_));
InputImeEventRouter* event_router =
GetInputImeEventRouter(Profile::FromBrowserContext(browser_context()));
InputMethodEngineBase* engine =
event_router ? event_router->GetEngineIfActive(extension_id()) : nullptr;
if (engine) {
engine->KeyEventHandled(extension_id(), params->request_id,
params->response);
}
std::string error;
InputMethodEngineBase* engine = GetEngineIfActive(
Profile::FromBrowserContext(browser_context()), extension_id(), &error);
if (!engine)
return RespondNow(Error(error));
engine->KeyEventHandled(extension_id(), params->request_id, params->response);
return RespondNow(NoArguments());
}
ExtensionFunction::ResponseAction InputImeSetCompositionFunction::Run() {
InputImeEventRouter* event_router =
GetInputImeEventRouter(Profile::FromBrowserContext(browser_context()));
InputMethodEngineBase* engine =
event_router ? event_router->GetEngineIfActive(extension_id()) : nullptr;
if (engine) {
std::unique_ptr<SetComposition::Params> parent_params(
SetComposition::Params::Create(*args_));
const SetComposition::Params::Parameters& params =
parent_params->parameters;
std::vector<InputMethodEngineBase::SegmentInfo> segments;
if (params.segments) {
for (const auto& segments_arg : *params.segments) {
EXTENSION_FUNCTION_VALIDATE(segments_arg.style !=
input_ime::UNDERLINE_STYLE_NONE);
InputMethodEngineBase::SegmentInfo segment_info;
segment_info.start = segments_arg.start;
segment_info.end = segments_arg.end;
if (segments_arg.style == input_ime::UNDERLINE_STYLE_UNDERLINE) {
segment_info.style = InputMethodEngineBase::SEGMENT_STYLE_UNDERLINE;
} else if (segments_arg.style ==
input_ime::UNDERLINE_STYLE_DOUBLEUNDERLINE) {
segment_info.style =
InputMethodEngineBase::SEGMENT_STYLE_DOUBLE_UNDERLINE;
} else {
segment_info.style =
InputMethodEngineBase::SEGMENT_STYLE_NO_UNDERLINE;
}
segments.push_back(segment_info);
std::string error;
InputMethodEngineBase* engine = GetEngineIfActive(
Profile::FromBrowserContext(browser_context()), extension_id(), &error);
if (!engine)
return RespondNow(Error(error));
std::unique_ptr<SetComposition::Params> parent_params(
SetComposition::Params::Create(*args_));
const SetComposition::Params::Parameters& params = parent_params->parameters;
std::vector<InputMethodEngineBase::SegmentInfo> segments;
if (params.segments) {
for (const auto& segments_arg : *params.segments) {
EXTENSION_FUNCTION_VALIDATE(segments_arg.style !=
input_ime::UNDERLINE_STYLE_NONE);
InputMethodEngineBase::SegmentInfo segment_info;
segment_info.start = segments_arg.start;
segment_info.end = segments_arg.end;
if (segments_arg.style == input_ime::UNDERLINE_STYLE_UNDERLINE) {
segment_info.style = InputMethodEngineBase::SEGMENT_STYLE_UNDERLINE;
} else if (segments_arg.style ==
input_ime::UNDERLINE_STYLE_DOUBLEUNDERLINE) {
segment_info.style =
InputMethodEngineBase::SEGMENT_STYLE_DOUBLE_UNDERLINE;
} else {
segment_info.style = InputMethodEngineBase::SEGMENT_STYLE_NO_UNDERLINE;
}
}
int selection_start =
params.selection_start ? *params.selection_start : params.cursor;
int selection_end =
params.selection_end ? *params.selection_end : params.cursor;
std::string error;
if (!engine->SetComposition(params.context_id, params.text.c_str(),
selection_start, selection_end, params.cursor,
segments, &error)) {
std::unique_ptr<base::ListValue> results =
std::make_unique<base::ListValue>();
results->Append(std::make_unique<base::Value>(false));
return RespondNow(ErrorWithArguments(std::move(results), error));
segments.push_back(segment_info);
}
}
int selection_start =
params.selection_start ? *params.selection_start : params.cursor;
int selection_end =
params.selection_end ? *params.selection_end : params.cursor;
if (!engine->SetComposition(params.context_id, params.text.c_str(),
selection_start, selection_end, params.cursor,
segments, &error)) {
std::unique_ptr<base::ListValue> results =
std::make_unique<base::ListValue>();
results->Append(std::make_unique<base::Value>(false));
return RespondNow(ErrorWithArguments(std::move(results), error));
}
return RespondNow(OneArgument(std::make_unique<base::Value>(true)));
}
ExtensionFunction::ResponseAction InputImeCommitTextFunction::Run() {
InputImeEventRouter* event_router =
GetInputImeEventRouter(Profile::FromBrowserContext(browser_context()));
InputMethodEngineBase* engine =
event_router ? event_router->GetEngineIfActive(extension_id()) : nullptr;
if (engine) {
std::unique_ptr<CommitText::Params> parent_params(
CommitText::Params::Create(*args_));
const CommitText::Params::Parameters& params = parent_params->parameters;
std::string error;
if (!engine->CommitText(params.context_id, params.text.c_str(), &error)) {
std::unique_ptr<base::ListValue> results =
std::make_unique<base::ListValue>();
results->Append(std::make_unique<base::Value>(false));
return RespondNow(ErrorWithArguments(std::move(results), error));
}
std::string error;
InputMethodEngineBase* engine = GetEngineIfActive(
Profile::FromBrowserContext(browser_context()), extension_id(), &error);
if (!engine)
return RespondNow(Error(error));
std::unique_ptr<CommitText::Params> parent_params(
CommitText::Params::Create(*args_));
const CommitText::Params::Parameters& params = parent_params->parameters;
if (!engine->CommitText(params.context_id, params.text.c_str(), &error)) {
std::unique_ptr<base::ListValue> results =
std::make_unique<base::ListValue>();
results->Append(std::make_unique<base::Value>(false));
return RespondNow(ErrorWithArguments(std::move(results), error));
}
return RespondNow(OneArgument(std::make_unique<base::Value>(true)));
}
ExtensionFunction::ResponseAction InputImeSendKeyEventsFunction::Run() {
InputImeEventRouter* event_router =
GetInputImeEventRouter(Profile::FromBrowserContext(browser_context()));
InputMethodEngineBase* engine =
event_router ? event_router->GetEngineIfActive(extension_id()) : nullptr;
std::string error;
InputMethodEngineBase* engine = GetEngineIfActive(
Profile::FromBrowserContext(browser_context()), extension_id(), &error);
if (!engine)
return RespondNow(Error(kInputImeApiErrorEngineNotAvailable));
return RespondNow(Error(error));
std::unique_ptr<SendKeyEvents::Params> parent_params(
SendKeyEvents::Params::Create(*args_));
......@@ -411,7 +418,7 @@ ExtensionFunction::ResponseAction InputImeSendKeyEventsFunction::Run() {
event.caps_lock = key_event.caps_lock ? *(key_event.caps_lock) : false;
}
if (!engine->SendKeyEvents(params.context_id, key_data_out))
return RespondNow(Error(kInputImeApiErrorSetKeyEventsFail));
return RespondNow(Error(kErrorSetKeyEventsFail));
return RespondNow(NoArguments());
}
......
......@@ -177,7 +177,8 @@ class InputImeEventRouter : public InputImeEventRouterBase {
chromeos::InputMethodEngine* GetEngine(const std::string& extension_id);
input_method::InputMethodEngineBase* GetEngineIfActive(
const std::string& extension_id) override;
const std::string& extension_id,
std::string* error) override;
std::string GetUnloadedExtensionId() const {
return unloaded_component_extension_id_;
......
......@@ -35,7 +35,8 @@ namespace input_ime = extensions::api::input_ime;
namespace {
const char kErrorNoActiveEngine[] = "The extension has not been activated.";
const char kErrorEngineNotActive[] = "The engine is not active.";
const char kErrorRouterNotAvailable[] = "The router is not available.";
const char kErrorPermissionDenied[] = "User denied permission.";
const char kErrorCouldNotFindActiveBrowser[] =
"Cannot find the active browser.";
......@@ -123,13 +124,13 @@ class ImeObserverNonChromeOS : public ui::ImeObserver {
namespace extensions {
InputMethodEngine* GetEngineIfActive(content::BrowserContext* browser_context,
const std::string& extension_id) {
const std::string& extension_id,
std::string* error) {
Profile* profile = Profile::FromBrowserContext(browser_context);
InputImeEventRouter* event_router = GetInputImeEventRouter(profile);
InputMethodEngine* engine =
event_router ? static_cast<InputMethodEngine*>(
event_router->GetEngineIfActive(extension_id))
: nullptr;
CHECK(event_router) << kErrorRouterNotAvailable;
InputMethodEngine* engine = static_cast<InputMethodEngine*>(
event_router->GetEngineIfActive(extension_id, error));
return engine;
}
......@@ -175,12 +176,16 @@ InputImeEventRouter::~InputImeEventRouter() {
}
InputMethodEngineBase* InputImeEventRouter::GetEngineIfActive(
const std::string& extension_id) {
return (ui::IMEBridge::Get()->GetCurrentEngineHandler() &&
active_engine_ &&
active_engine_->GetExtensionId() == extension_id)
? active_engine_
: nullptr;
const std::string& extension_id,
std::string* error) {
if (ui::IMEBridge::Get()->GetCurrentEngineHandler() && active_engine_ &&
active_engine_->GetExtensionId() == extension_id) {
return active_engine_;
} else {
LOG(WARNING) << kErrorEngineNotActive << " extension id: " << extension_id;
*error = kErrorEngineNotActive;
return nullptr;
}
}
void InputImeEventRouter::SetActiveEngine(const std::string& extension_id) {
......@@ -229,7 +234,7 @@ ExtensionFunction::ResponseAction InputImeActivateFunction::Run() {
Profile* profile = Profile::FromBrowserContext(browser_context());
InputImeEventRouter* event_router = GetInputImeEventRouter(profile);
if (!event_router)
return RespondNow(Error(kErrorNoActiveEngine));
return RespondNow(Error(kErrorEngineNotActive));
ExtensionPrefs* prefs = ExtensionPrefs::Get(profile);
......@@ -306,7 +311,7 @@ void InputImeActivateFunction::OnPermissionBubbleFinished(
Profile* profile = Profile::FromBrowserContext(browser_context());
InputImeEventRouter* event_router = GetInputImeEventRouter(profile);
if (!event_router) {
Respond(Error(kErrorNoActiveEngine));
Respond(Error(kErrorEngineNotActive));
return;
}
event_router->SetActiveEngine(extension_id());
......@@ -323,8 +328,12 @@ void InputImeActivateFunction::OnPermissionBubbleFinished(
}
ExtensionFunction::ResponseAction InputImeDeactivateFunction::Run() {
std::string error;
InputMethodEngine* engine =
GetEngineIfActive(browser_context(), extension_id());
GetEngineIfActive(browser_context(), extension_id(), &error);
if (!engine) {
return RespondNow(Error(error));
}
ui::IMEBridge::Get()->SetCurrentEngineHandler(nullptr);
if (engine)
engine->CloseImeWindows();
......@@ -351,12 +360,12 @@ ExtensionFunction::ResponseAction InputImeCreateWindowFunction::Run() {
bounds.set_height(options.bounds->height);
}
std::string error;
InputMethodEngine* engine =
GetEngineIfActive(browser_context(), extension_id());
GetEngineIfActive(browser_context(), extension_id(), &error);
if (!engine)
return RespondNow(Error(kErrorNoActiveEngine));
return RespondNow(Error(error));
std::string error;
int frame_id = engine->CreateImeWindow(
extension(), render_frame_host(),
options.url.get() ? *options.url : url::kAboutBlankURL,
......@@ -374,10 +383,11 @@ ExtensionFunction::ResponseAction InputImeCreateWindowFunction::Run() {
}
ExtensionFunction::ResponseAction InputImeShowWindowFunction::Run() {
std::string error;
InputMethodEngine* engine =
GetEngineIfActive(browser_context(), extension_id());
GetEngineIfActive(browser_context(), extension_id(), &error);
if (!engine)
return RespondNow(Error(kErrorNoActiveEngine));
return RespondNow(Error(error));
std::unique_ptr<api::input_ime::ShowWindow::Params> params(
api::input_ime::ShowWindow::Params::Create(*args_));
......@@ -387,10 +397,11 @@ ExtensionFunction::ResponseAction InputImeShowWindowFunction::Run() {
}
ExtensionFunction::ResponseAction InputImeHideWindowFunction::Run() {
std::string error;
InputMethodEngine* engine =
GetEngineIfActive(browser_context(), extension_id());
GetEngineIfActive(browser_context(), extension_id(), &error);
if (!engine)
return RespondNow(Error(kErrorNoActiveEngine));
return RespondNow(Error(error));
std::unique_ptr<api::input_ime::HideWindow::Params> params(
api::input_ime::HideWindow::Params::Create(*args_));
......
......@@ -35,7 +35,8 @@ class InputImeEventRouter : public InputImeEventRouterBase {
// Gets the input method engine if the extension is active.
input_method::InputMethodEngineBase* GetEngineIfActive(
const std::string& extension_id) override;
const std::string& extension_id,
std::string* error) override;
// Actives the extension with new input method engine, and deletes the
// previous engine if another extension was active.
......
......@@ -23,7 +23,8 @@ class InputImeEventRouterBase {
// Gets the input method engine if the extension is active.
virtual input_method::InputMethodEngineBase* GetEngineIfActive(
const std::string& extension_id) = 0;
const std::string& extension_id,
std::string* error) = 0;
Profile* GetProfile() const { return profile_; }
......
......@@ -2,36 +2,36 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function setCompositionTest() {
chrome.input.ime.setComposition({
"contextID": 1,
"text": "Pie",
"selectionStart": 1,
"selectionEnd": 2,
"cursor": 3,
"segments": [{
"start": 0,
"end": 1,
"style": "underline"
}]
}, chrome.test.callbackPass());
}
function clearCompositionTest() {
chrome.input.ime.clearComposition({
"contextID": 1
}, chrome.test.callbackPass());
}
// Disabled: crbug.com/641425.
// function setCompositionTest() {
// chrome.input.ime.setComposition({
// "contextID": 1,
// "text": "Pie",
// "selectionStart": 1,
// "selectionEnd": 2,
// "cursor": 3,
// "segments": [{
// "start": 0,
// "end": 1,
// "style": "underline"
// }]
// }, chrome.test.callbackPass());
// }
function commitTextTest() {
chrome.input.ime.commitText({
"contextID": 2,
"text": "Seaguls"
}, chrome.test.callbackPass());
}
// Disabled: crbug.com/641425.
// function clearCompositionTest() {
// chrome.input.ime.clearComposition({
// "contextID": 1
// }, chrome.test.callbackPass());
// }
// Disabled: crbug.com/641425.
// function commitTextTest() {
// chrome.input.ime.commitText({
// "contextID": 2,
// "text": "Seaguls"
// }, chrome.test.callbackPass());
// }
// Disabled: crbug.com/641425.
// function setCandidateWindowPropertiesTest() {
......@@ -48,37 +48,36 @@ function commitTextTest() {
// }, chrome.test.callbackPass());
// }
// Disabled: crbug.com/641425.
// function setCandidatesTest() {
// chrome.input.ime.setCandidates({
// "contextID": 8,
// "candidates": [{
// "candidate": "one",
// "id": 1,
// "label": "first",
// "annotation": "The first one"
// }, {
// "candidate": "two",
// "id": 2,
// "label": "second",
// "annotation": "The second one"
// }, {
// "candidate": "three",
// "id": 3,
// "label": "third",
// "annotation": "The third one"
// }]
// }, chrome.test.callbackPass());
// }
function setCandidatesTest() {
chrome.input.ime.setCandidates({
"contextID": 8,
"candidates": [{
"candidate": "one",
"id": 1,
"label": "first",
"annotation": "The first one"
}, {
"candidate": "two",
"id": 2,
"label": "second",
"annotation": "The second one"
}, {
"candidate": "three",
"id": 3,
"label": "third",
"annotation": "The third one"
}]
}, chrome.test.callbackPass());
}
function setCursorPositionTest() {
chrome.input.ime.setCursorPosition({
"contextID": 9,
"candidateID": 1
}, chrome.test.callbackPass());
}
// Disabled: crbug.com/641425.
// function setCursorPositionTest() {
// chrome.input.ime.setCursorPosition({
// "contextID": 9,
// "candidateID": 1
// }, chrome.test.callbackPass());
// }
// Disabled: crbug.com/641425.
// function setMenuItemsTest() {
......@@ -125,12 +124,12 @@ function setCursorPositionTest() {
// }
chrome.test.runTests([
setCompositionTest,
clearCompositionTest,
commitTextTest,
// setCompositionTest,
// clearCompositionTest,
// commitTextTest,
// setCandidateWindowPropertiesTest,
setCandidatesTest,
setCursorPositionTest,
// setCandidatesTest,
// setCursorPositionTest,
// setMenuItemsTest,
// updateMenuItemsTest,
// deleteSurroundingText,
......
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