Chromium Code Reviews| Index: chrome/browser/extensions/extension_ime_ui_api.cc |
| diff --git a/chrome/browser/extensions/extension_ime_ui_api.cc b/chrome/browser/extensions/extension_ime_ui_api.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..7698a44e9053edb46ceebc598ffa03c106964752 |
| --- /dev/null |
| +++ b/chrome/browser/extensions/extension_ime_ui_api.cc |
| @@ -0,0 +1,355 @@ |
| +// Copyright (c) 2011 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 "chrome/browser/extensions/extension_ime_ui_api.h" |
| + |
| +#include <string> |
| + |
| +#include "base/json/json_writer.h" |
| +#include "base/logging.h" |
| +#include "base/string_util.h" |
| +#include "base/values.h" |
| +#include "chrome/browser/extensions/extension_event_router.h" |
| +#include "chrome/browser/profiles/profile.h" |
| +#include "third_party/cros/chromeos_cros_api.h" |
| +#include "third_party/cros/chromeos_input_method_ui.h" |
| + |
| +namespace events { |
| + |
| +const char kOnUpdateAuxiliaryText[] = |
| + "experimental.ime.ui.onUpdateAuxiliaryText"; |
| +const char kOnUpdateLookupTable[] = "experimental.ime.ui.onUpdateLookupTable"; |
| +const char kOnSetCursorLocation[] = "experimental.ime.ui.onSetCursorLocation"; |
| + |
| +} // namespace events |
| + |
| +class ImeUiController { |
| + public: |
| + explicit ImeUiController(ExtensionImeUiEventRouter* router); |
| + ~ImeUiController(); |
| + |
| + void CandidateClicked(int index, int button, int flags); |
| + void CursorUp(); |
| + void CursorDown(); |
| + void PageUp(); |
| + void PageDown(); |
| + private: |
| + // The function is called when |HideAuxiliaryText| signal is received in |
| + // libcros. |input_method_library| is a void pointer to this object. |
|
Yusuke Sato
2011/04/18 08:21:29
It might be better to rename input_method_library
Peng
2011/04/18 14:35:38
Done.
|
| + static void OnHideAuxiliaryText(void* input_method_library); |
| + |
| + // The function is called when |HideLookupTable| signal is received in |
| + // libcros. |input_method_library| is a void pointer to this object. |
| + static void OnHideLookupTable(void* input_method_library); |
| + |
| + // The function is called when |SetCursorLocation| signal is received |
| + // in libcros. |input_method_library| is a void pointer to this object. |
| + static void OnSetCursorLocation(void* input_method_library, |
| + int x, |
| + int y, |
| + int width, |
| + int height); |
| + |
| + // The function is called when |UpdateAuxiliaryText| signal is received |
| + // in libcros. |input_method_library| is a void pointer to this object. |
| + static void OnUpdateAuxiliaryText(void* input_method_library, |
| + const std::string& utf8_text, |
| + bool visible); |
| + |
| + // The function is called when |UpdateLookupTable| signal is received |
| + // in libcros. |input_method_library| is a void pointer to this object. |
| + static void OnUpdateLookupTable(void* input_method_library, |
| + const chromeos::InputMethodLookupTable& lookup_table); |
| + |
| + // This function is called by libcros when ibus connects or disconnects. |
| + // |input_method_library| is a void pointer to this object. |
| + static void OnConnectionChange(void* input_method_library, bool connected); |
| + |
| + ExtensionImeUiEventRouter* router_; |
| + chromeos::InputMethodUiStatusConnection* ui_status_connection_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(ImeUiController); |
| +}; |
| + |
| +ImeUiController::ImeUiController( |
| + ExtensionImeUiEventRouter* router) : |
| + router_(router), |
| + ui_status_connection_(NULL) { |
| + std::string error; |
| + chromeos::LoadLibcros(NULL, error); |
| + |
| + chromeos::InputMethodUiStatusMonitorFunctions functions; |
| + functions.hide_auxiliary_text = |
| + &ImeUiController::OnHideAuxiliaryText; |
| + functions.hide_lookup_table = |
| + &ImeUiController::OnHideLookupTable; |
| + functions.set_cursor_location = |
| + &ImeUiController::OnSetCursorLocation; |
| + functions.update_auxiliary_text = |
| + &ImeUiController::OnUpdateAuxiliaryText; |
| + functions.update_lookup_table = |
| + &ImeUiController::OnUpdateLookupTable; |
| + ui_status_connection_ = chromeos::MonitorInputMethodUiStatus(functions, this); |
| + |
| + if (!ui_status_connection_) |
| + LOG(ERROR) << "chromeos::MonitorInputMethodUiStatus() failed!"; |
| +} |
| + |
| +ImeUiController::~ImeUiController() { |
| + chromeos::DisconnectInputMethodUiStatus(ui_status_connection_); |
| +} |
| + |
| +void ImeUiController::CandidateClicked( |
| + int index, int button, int flags) { |
| + chromeos::NotifyCandidateClicked(ui_status_connection_, index, button, flags); |
| +} |
| + |
| +void ImeUiController::CursorUp() { |
| + chromeos::NotifyCursorUp(ui_status_connection_); |
| +} |
| + |
| +void ImeUiController::CursorDown() { |
| + chromeos::NotifyCursorDown(ui_status_connection_); |
| +} |
| + |
| +void ImeUiController::PageUp() { |
| + chromeos::NotifyPageUp(ui_status_connection_); |
|
Zachary Kuznia
2011/04/18 03:52:29
CursorUp, CursorDown, PageUp and PageDown are not
Peng
2011/04/18 14:35:38
I think it is necessary for touch devices. Because
|
| +} |
| + |
| +void ImeUiController::PageDown() { |
| + chromeos::NotifyPageDown(ui_status_connection_); |
| +} |
| + |
| +void ImeUiController::OnHideAuxiliaryText( |
| + void* input_method_library) { |
| + ImeUiController *self = static_cast<ImeUiController*>(input_method_library); |
| + self->router_->OnHideAuxiliaryText(); |
| +} |
| + |
| +void ImeUiController::OnHideLookupTable( |
| + void* input_method_library) { |
| + ImeUiController *self = static_cast<ImeUiController*>(input_method_library); |
| + self->router_->OnHideLookupTable(); |
| +} |
| + |
| +void ImeUiController::OnSetCursorLocation( |
| + void* input_method_library, |
| + int x, int y, int width, int height) { |
| + ImeUiController *self = static_cast<ImeUiController*>(input_method_library); |
| + self->router_->OnSetCursorLocation(x, y, width, height); |
| +} |
| + |
| +void ImeUiController::OnUpdateAuxiliaryText( |
| + void* input_method_library, |
| + const std::string& utf8_text, |
| + bool visible) { |
| + ImeUiController *self = static_cast<ImeUiController*>(input_method_library); |
| + if (!visible) { |
| + self->router_->OnHideAuxiliaryText(); |
| + } else { |
| + self->router_->OnUpdateAuxiliaryText(utf8_text); |
| + } |
| +} |
| + |
| +void ImeUiController::OnUpdateLookupTable( |
| + void* input_method_library, |
| + const chromeos::InputMethodLookupTable& lookup_table) { |
| + ImeUiController *self = static_cast<ImeUiController*>(input_method_library); |
| + self->router_->OnUpdateLookupTable(lookup_table); |
| +} |
| + |
| +ExtensionImeUiEventRouter* |
| +ExtensionImeUiEventRouter::GetInstance() { |
| + return Singleton<ExtensionImeUiEventRouter>::get(); |
| +} |
| + |
| +ExtensionImeUiEventRouter::ExtensionImeUiEventRouter() |
| + : profile_(NULL), |
| + ime_ui_controller_(NULL) { |
| +} |
| + |
| +ExtensionImeUiEventRouter::~ExtensionImeUiEventRouter() { |
| + delete ime_ui_controller_; |
| +} |
| + |
| +void ExtensionImeUiEventRouter::Init() { |
| + if (ime_ui_controller_ == NULL) { |
| + ime_ui_controller_ = new ImeUiController(this); |
| + } |
| +} |
| + |
| +void ExtensionImeUiEventRouter::Register( |
| + Profile* profile, const std::string& extension_id) { |
| + profile_ = profile; |
| + extension_id_ = extension_id; |
| +} |
| + |
| +void ExtensionImeUiEventRouter::CandidateClicked(Profile* profile, |
| + const std::string& extension_id, int index, int button) { |
| + if (profile_ != profile || extension_id_ != extension_id) { |
| + DLOG(WARNING) << "called from unregistered extension"; |
| + } |
| + ime_ui_controller_->CandidateClicked(index, button, 0); |
| +} |
| + |
| +void ExtensionImeUiEventRouter::CursorUp(Profile* profile, |
| + const std::string& extension_id) { |
| + if (profile_ != profile || extension_id_ != extension_id) { |
| + DLOG(WARNING) << "called from unregistered extension"; |
| + } |
| + ime_ui_controller_->CursorUp(); |
| +} |
| + |
| +void ExtensionImeUiEventRouter::CursorDown(Profile* profile, |
| + const std::string& extension_id) { |
| + if (profile_ != profile || extension_id_ != extension_id) { |
| + DLOG(WARNING) << "called from unregistered extension"; |
| + } |
| + ime_ui_controller_->CursorDown(); |
| +} |
| + |
| +void ExtensionImeUiEventRouter::PageUp(Profile* profile, |
| + const std::string& extension_id) { |
| + if (profile_ != profile || extension_id_ != extension_id) { |
| + DLOG(WARNING) << "called from unregistered extension"; |
| + } |
| + ime_ui_controller_->PageUp(); |
| +} |
| + |
| +void ExtensionImeUiEventRouter::PageDown(Profile* profile, |
| + const std::string& extension_id) { |
| + if (profile_ != profile || extension_id_ != extension_id) { |
| + DLOG(WARNING) << "called from unregistered extension"; |
| + } |
| + ime_ui_controller_->PageDown(); |
| +} |
| + |
| +void ExtensionImeUiEventRouter::OnHideAuxiliaryText() { |
| + OnUpdateAuxiliaryText(""); |
| +} |
| + |
| +void ExtensionImeUiEventRouter::OnHideLookupTable() { |
| + if (profile_ == NULL || extension_id_.empty()) |
| + return; |
| + |
| + DictionaryValue* dict = new DictionaryValue(); |
| + dict->SetBoolean("visible", false); |
| + |
| + ListValue *candidates = new ListValue(); |
| + dict->Set("candidates", candidates); |
| + |
| + ListValue args; |
| + args.Append(dict); |
| + |
| + std::string json_args; |
| + base::JSONWriter::Write(&args, false, &json_args); |
| + profile_->GetExtensionEventRouter()->DispatchEventToExtension( |
| + extension_id_, events::kOnUpdateLookupTable, json_args, profile_, GURL()); |
| +} |
| + |
| +void ExtensionImeUiEventRouter::OnSetCursorLocation( |
| + int x, int y, int width, int height) { |
| + |
| + if (profile_ == NULL || extension_id_.empty()) |
| + return; |
| + |
| + ListValue args; |
| + args.Append(Value::CreateIntegerValue(x)); |
| + args.Append(Value::CreateIntegerValue(y)); |
| + args.Append(Value::CreateIntegerValue(width)); |
| + args.Append(Value::CreateIntegerValue(height)); |
| + |
| + std::string json_args; |
| + base::JSONWriter::Write(&args, false, &json_args); |
| + profile_->GetExtensionEventRouter()->DispatchEventToExtension( |
| + extension_id_, events::kOnSetCursorLocation, json_args, profile_, GURL()); |
| +} |
| + |
| +void ExtensionImeUiEventRouter::OnUpdateAuxiliaryText( |
| + const std::string& utf8_text) { |
| + if (profile_ == NULL || extension_id_.empty()) |
| + return; |
| + |
| + ListValue args; |
| + args.Append(Value::CreateStringValue(utf8_text)); |
| + |
| + std::string json_args; |
| + base::JSONWriter::Write(&args, false, &json_args); |
| + profile_->GetExtensionEventRouter()->DispatchEventToExtension( |
| + extension_id_, events::kOnUpdateAuxiliaryText, json_args, profile_, GURL()); |
| +} |
| + |
| +void ExtensionImeUiEventRouter::OnUpdateLookupTable( |
| + const chromeos::InputMethodLookupTable& lookup_table) { |
| + if (profile_ == NULL || extension_id_.empty()) |
| + return; |
| + |
| + DictionaryValue* dict = new DictionaryValue(); |
| + dict->SetBoolean("visible", lookup_table.visible); |
| + |
| + if (lookup_table.visible) { |
| + } |
| + |
| + ListValue *candidates = new ListValue(); |
| + for (size_t i = 0; i < lookup_table.candidates.size(); i++) { |
| + candidates->Append(Value::CreateStringValue(lookup_table.candidates[i])); |
| + } |
| + |
| + dict->Set("candidates", candidates); |
| + |
| + ListValue args; |
| + args.Append(dict); |
| + |
| + std::string json_args; |
| + base::JSONWriter::Write(&args, false, &json_args); |
| + profile_->GetExtensionEventRouter()->DispatchEventToExtension( |
| + extension_id_, events::kOnUpdateLookupTable, json_args, profile_, GURL()); |
| +} |
| + |
| +void ImeUiFunction::Run() { |
| + SendResponse(RunImpl()); |
| +} |
| + |
| +bool RegisterImeUiFunction::RunImpl() { |
| + ExtensionImeUiEventRouter::GetInstance()->Register( |
| + profile(), extension_id()); |
| + return true; |
| +} |
| + |
| +bool CandidateClickedImeUiFunction::RunImpl() { |
| + int index = 0; |
| + int button = 0; |
| + EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &index)); |
| + EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(1, &button)); |
| + |
| + ExtensionImeUiEventRouter::GetInstance()->CandidateClicked( |
| + profile(), extension_id(), index, button); |
| + |
| + return true; |
| +} |
| + |
| +bool CursorUpImeUiFunction::RunImpl() { |
| + ExtensionImeUiEventRouter::GetInstance()->CursorUp( |
| + profile(), extension_id()); |
| + return true; |
| +} |
| + |
| +bool CursorDownImeUiFunction::RunImpl() { |
| + ExtensionImeUiEventRouter::GetInstance()->CursorDown( |
| + profile(), extension_id()); |
| + return true; |
| +} |
| + |
| +bool PageUpImeUiFunction::RunImpl() { |
| + ExtensionImeUiEventRouter::GetInstance()->PageUp( |
| + profile(), extension_id()); |
| + return true; |
| +} |
| + |
| +bool PageDownImeUiFunction::RunImpl() { |
| + ExtensionImeUiEventRouter::GetInstance()->PageDown( |
| + profile(), extension_id()); |
| + return true; |
| +} |
| + |