Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/extensions/extension_input_ui_api.h" | |
| 6 | |
| 7 #include <string> | |
| 8 | |
| 9 #include "base/json/json_writer.h" | |
| 10 #include "base/logging.h" | |
| 11 #include "base/string_util.h" | |
| 12 #include "base/values.h" | |
| 13 #include "chrome/browser/extensions/extension_event_router.h" | |
| 14 #include "chrome/browser/profiles/profile.h" | |
| 15 #include "third_party/cros/chromeos_cros_api.h" | |
| 16 #include "third_party/cros/chromeos_input_method_ui.h" | |
| 17 | |
| 18 namespace events { | |
| 19 | |
| 20 const char kOnUpdateAuxiliaryText[] = | |
| 21 "experimental.input.ui.onUpdateAuxiliaryText"; | |
| 22 const char kOnUpdateLookupTable[] = "experimental.input.ui.onUpdateLookupTable"; | |
| 23 const char kOnSetCursorLocation[] = "experimental.input.ui.onSetCursorLocation"; | |
| 24 | |
| 25 } // namespace events | |
| 26 | |
| 27 class InputUiController { | |
| 28 public: | |
| 29 explicit InputUiController(ExtensionInputUiEventRouter* router); | |
| 30 ~InputUiController(); | |
| 31 | |
| 32 void CandidateClicked(int index, int button, int flags); | |
| 33 void CursorUp(); | |
| 34 void CursorDown(); | |
| 35 void PageUp(); | |
| 36 void PageDown(); | |
| 37 private: | |
|
Yusuke Sato
2011/05/02 07:33:31
nit: one vertical space between line 36 and 37, pl
Peng
2011/05/02 17:17:23
Done.
| |
| 38 // The function is called when |HideAuxiliaryText| signal is received in | |
| 39 // libcros. |ui_controller| is a void pointer to this object. | |
| 40 static void OnHideAuxiliaryText(void* ui_controller); | |
| 41 | |
| 42 // The function is called when |HideLookupTable| signal is received in | |
| 43 // libcros. |ui_controller| is a void pointer to this object. | |
| 44 static void OnHideLookupTable(void* ui_controller); | |
| 45 | |
| 46 // The function is called when |SetCursorLocation| signal is received | |
| 47 // in libcros. |ui_controller| is a void pointer to this object. | |
| 48 static void OnSetCursorLocation(void* ui_controller, | |
| 49 int x, | |
| 50 int y, | |
| 51 int width, | |
| 52 int height); | |
| 53 | |
| 54 // The function is called when |UpdateAuxiliaryText| signal is received | |
| 55 // in libcros. |ui_controller| is a void pointer to this object. | |
| 56 static void OnUpdateAuxiliaryText(void* ui_controller, | |
| 57 const std::string& utf8_text, | |
| 58 bool visible); | |
| 59 | |
| 60 // The function is called when |UpdateLookupTable| signal is received | |
| 61 // in libcros. |ui_controller| is a void pointer to this object. | |
| 62 static void OnUpdateLookupTable(void* ui_controller, | |
| 63 const chromeos::InputMethodLookupTable& lookup_table); | |
| 64 | |
| 65 // This function is called by libcros when ibus connects or disconnects. | |
| 66 // |ui_controller| is a void pointer to this object. | |
| 67 static void OnConnectionChange(void* ui_controller, bool connected); | |
| 68 | |
| 69 ExtensionInputUiEventRouter* router_; | |
| 70 chromeos::InputMethodUiStatusConnection* ui_status_connection_; | |
| 71 | |
| 72 DISALLOW_COPY_AND_ASSIGN(InputUiController); | |
| 73 }; | |
| 74 | |
| 75 InputUiController::InputUiController( | |
| 76 ExtensionInputUiEventRouter* router) : | |
| 77 router_(router), | |
| 78 ui_status_connection_(NULL) { | |
| 79 std::string error; | |
| 80 chromeos::LoadLibcros(NULL, error); | |
| 81 | |
| 82 chromeos::InputMethodUiStatusMonitorFunctions functions; | |
| 83 functions.hide_auxiliary_text = | |
| 84 &InputUiController::OnHideAuxiliaryText; | |
| 85 functions.hide_lookup_table = | |
| 86 &InputUiController::OnHideLookupTable; | |
| 87 functions.set_cursor_location = | |
| 88 &InputUiController::OnSetCursorLocation; | |
| 89 functions.update_auxiliary_text = | |
| 90 &InputUiController::OnUpdateAuxiliaryText; | |
| 91 functions.update_lookup_table = | |
| 92 &InputUiController::OnUpdateLookupTable; | |
| 93 ui_status_connection_ = chromeos::MonitorInputMethodUiStatus(functions, this); | |
| 94 | |
| 95 if (!ui_status_connection_) | |
| 96 LOG(ERROR) << "chromeos::MonitorInputMethodUiStatus() failed!"; | |
| 97 } | |
| 98 | |
| 99 InputUiController::~InputUiController() { | |
| 100 chromeos::DisconnectInputMethodUiStatus(ui_status_connection_); | |
| 101 } | |
| 102 | |
| 103 void InputUiController::CandidateClicked( | |
| 104 int index, int button, int flags) { | |
| 105 chromeos::NotifyCandidateClicked(ui_status_connection_, index, button, flags); | |
| 106 } | |
| 107 | |
| 108 void InputUiController::CursorUp() { | |
| 109 chromeos::NotifyCursorUp(ui_status_connection_); | |
| 110 } | |
| 111 | |
| 112 void InputUiController::CursorDown() { | |
| 113 chromeos::NotifyCursorDown(ui_status_connection_); | |
| 114 } | |
| 115 | |
| 116 void InputUiController::PageUp() { | |
| 117 chromeos::NotifyPageUp(ui_status_connection_); | |
| 118 } | |
| 119 | |
| 120 void InputUiController::PageDown() { | |
| 121 chromeos::NotifyPageDown(ui_status_connection_); | |
| 122 } | |
| 123 | |
| 124 void InputUiController::OnHideAuxiliaryText( | |
| 125 void* ui_controller) { | |
| 126 InputUiController *self = static_cast<InputUiController*>(ui_controller); | |
| 127 self->router_->OnHideAuxiliaryText(); | |
| 128 } | |
| 129 | |
| 130 void InputUiController::OnHideLookupTable( | |
| 131 void* ui_controller) { | |
| 132 InputUiController *self = static_cast<InputUiController*>(ui_controller); | |
| 133 self->router_->OnHideLookupTable(); | |
| 134 } | |
| 135 | |
| 136 void InputUiController::OnSetCursorLocation( | |
| 137 void* ui_controller, | |
| 138 int x, int y, int width, int height) { | |
| 139 InputUiController *self = static_cast<InputUiController*>(ui_controller); | |
| 140 self->router_->OnSetCursorLocation(x, y, width, height); | |
| 141 } | |
| 142 | |
| 143 void InputUiController::OnUpdateAuxiliaryText( | |
| 144 void* ui_controller, | |
| 145 const std::string& utf8_text, | |
| 146 bool visible) { | |
| 147 InputUiController *self = static_cast<InputUiController*>(ui_controller); | |
| 148 if (!visible) { | |
| 149 self->router_->OnHideAuxiliaryText(); | |
| 150 } else { | |
| 151 self->router_->OnUpdateAuxiliaryText(utf8_text); | |
| 152 } | |
| 153 } | |
| 154 | |
| 155 void InputUiController::OnUpdateLookupTable( | |
| 156 void* ui_controller, | |
| 157 const chromeos::InputMethodLookupTable& lookup_table) { | |
| 158 InputUiController *self = static_cast<InputUiController*>(ui_controller); | |
| 159 self->router_->OnUpdateLookupTable(lookup_table); | |
| 160 } | |
| 161 | |
| 162 ExtensionInputUiEventRouter* | |
| 163 ExtensionInputUiEventRouter::GetInstance() { | |
| 164 return Singleton<ExtensionInputUiEventRouter>::get(); | |
| 165 } | |
| 166 | |
| 167 ExtensionInputUiEventRouter::ExtensionInputUiEventRouter() | |
| 168 : profile_(NULL), | |
| 169 ui_controller_(NULL) { | |
| 170 } | |
| 171 | |
| 172 ExtensionInputUiEventRouter::~ExtensionInputUiEventRouter() { | |
| 173 delete ui_controller_; | |
| 174 } | |
| 175 | |
| 176 void ExtensionInputUiEventRouter::Init() { | |
| 177 if (ui_controller_ == NULL) { | |
| 178 ui_controller_ = new InputUiController(this); | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 void ExtensionInputUiEventRouter::Register( | |
| 183 Profile* profile, const std::string& extension_id) { | |
| 184 profile_ = profile; | |
| 185 extension_id_ = extension_id; | |
| 186 } | |
| 187 | |
| 188 void ExtensionInputUiEventRouter::CandidateClicked(Profile* profile, | |
| 189 const std::string& extension_id, int index, int button) { | |
| 190 if (profile_ != profile || extension_id_ != extension_id) { | |
| 191 DLOG(WARNING) << "called from unregistered extension"; | |
| 192 } | |
| 193 ui_controller_->CandidateClicked(index, button, 0); | |
| 194 } | |
| 195 | |
| 196 void ExtensionInputUiEventRouter::CursorUp(Profile* profile, | |
| 197 const std::string& extension_id) { | |
| 198 if (profile_ != profile || extension_id_ != extension_id) { | |
| 199 DLOG(WARNING) << "called from unregistered extension"; | |
| 200 } | |
| 201 ui_controller_->CursorUp(); | |
| 202 } | |
| 203 | |
| 204 void ExtensionInputUiEventRouter::CursorDown(Profile* profile, | |
| 205 const std::string& extension_id) { | |
| 206 if (profile_ != profile || extension_id_ != extension_id) { | |
| 207 DLOG(WARNING) << "called from unregistered extension"; | |
| 208 } | |
| 209 ui_controller_->CursorDown(); | |
| 210 } | |
| 211 | |
| 212 void ExtensionInputUiEventRouter::PageUp(Profile* profile, | |
| 213 const std::string& extension_id) { | |
| 214 if (profile_ != profile || extension_id_ != extension_id) { | |
| 215 DLOG(WARNING) << "called from unregistered extension"; | |
| 216 } | |
| 217 ui_controller_->PageUp(); | |
| 218 } | |
| 219 | |
| 220 void ExtensionInputUiEventRouter::PageDown(Profile* profile, | |
| 221 const std::string& extension_id) { | |
| 222 if (profile_ != profile || extension_id_ != extension_id) { | |
| 223 DLOG(WARNING) << "called from unregistered extension"; | |
| 224 } | |
| 225 ui_controller_->PageDown(); | |
| 226 } | |
| 227 | |
| 228 void ExtensionInputUiEventRouter::OnHideAuxiliaryText() { | |
| 229 OnUpdateAuxiliaryText(""); | |
| 230 } | |
| 231 | |
| 232 void ExtensionInputUiEventRouter::OnHideLookupTable() { | |
| 233 if (profile_ == NULL || extension_id_.empty()) | |
| 234 return; | |
| 235 | |
| 236 DictionaryValue* dict = new DictionaryValue(); | |
| 237 dict->SetBoolean("visible", false); | |
| 238 | |
| 239 ListValue *candidates = new ListValue(); | |
| 240 dict->Set("candidates", candidates); | |
| 241 | |
| 242 ListValue args; | |
| 243 args.Append(dict); | |
| 244 | |
| 245 std::string json_args; | |
| 246 base::JSONWriter::Write(&args, false, &json_args); | |
| 247 profile_->GetExtensionEventRouter()->DispatchEventToExtension( | |
| 248 extension_id_, events::kOnUpdateLookupTable, json_args, profile_, GURL()); | |
| 249 } | |
| 250 | |
| 251 void ExtensionInputUiEventRouter::OnSetCursorLocation( | |
| 252 int x, int y, int width, int height) { | |
| 253 | |
| 254 if (profile_ == NULL || extension_id_.empty()) | |
| 255 return; | |
| 256 | |
| 257 ListValue args; | |
| 258 args.Append(Value::CreateIntegerValue(x)); | |
| 259 args.Append(Value::CreateIntegerValue(y)); | |
| 260 args.Append(Value::CreateIntegerValue(width)); | |
| 261 args.Append(Value::CreateIntegerValue(height)); | |
| 262 | |
| 263 std::string json_args; | |
| 264 base::JSONWriter::Write(&args, false, &json_args); | |
| 265 profile_->GetExtensionEventRouter()->DispatchEventToExtension( | |
| 266 extension_id_, events::kOnSetCursorLocation, json_args, profile_, GURL()); | |
| 267 } | |
| 268 | |
| 269 void ExtensionInputUiEventRouter::OnUpdateAuxiliaryText( | |
| 270 const std::string& utf8_text) { | |
| 271 if (profile_ == NULL || extension_id_.empty()) | |
| 272 return; | |
| 273 | |
| 274 ListValue args; | |
| 275 args.Append(Value::CreateStringValue(utf8_text)); | |
| 276 | |
| 277 std::string json_args; | |
| 278 base::JSONWriter::Write(&args, false, &json_args); | |
| 279 profile_->GetExtensionEventRouter()->DispatchEventToExtension( | |
| 280 extension_id_, events::kOnUpdateAuxiliaryText, json_args, profile_, GURL()); | |
| 281 } | |
| 282 | |
| 283 void ExtensionInputUiEventRouter::OnUpdateLookupTable( | |
| 284 const chromeos::InputMethodLookupTable& lookup_table) { | |
| 285 if (profile_ == NULL || extension_id_.empty()) | |
| 286 return; | |
| 287 | |
| 288 DictionaryValue* dict = new DictionaryValue(); | |
| 289 dict->SetBoolean("visible", lookup_table.visible); | |
| 290 | |
| 291 if (lookup_table.visible) { | |
| 292 } | |
| 293 | |
| 294 ListValue *candidates = new ListValue(); | |
| 295 for (size_t i = 0; i < lookup_table.candidates.size(); i++) { | |
| 296 candidates->Append(Value::CreateStringValue(lookup_table.candidates[i])); | |
| 297 } | |
| 298 | |
| 299 dict->Set("candidates", candidates); | |
| 300 | |
| 301 ListValue args; | |
| 302 args.Append(dict); | |
| 303 | |
| 304 std::string json_args; | |
| 305 base::JSONWriter::Write(&args, false, &json_args); | |
| 306 profile_->GetExtensionEventRouter()->DispatchEventToExtension( | |
| 307 extension_id_, events::kOnUpdateLookupTable, json_args, profile_, GURL()); | |
| 308 } | |
| 309 | |
| 310 bool RegisterInputUiFunction::RunImpl() { | |
| 311 ExtensionInputUiEventRouter::GetInstance()->Register( | |
| 312 profile(), extension_id()); | |
| 313 return true; | |
| 314 } | |
| 315 | |
| 316 bool CandidateClickedInputUiFunction::RunImpl() { | |
| 317 int index = 0; | |
| 318 int button = 0; | |
| 319 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &index)); | |
| 320 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(1, &button)); | |
| 321 | |
| 322 ExtensionInputUiEventRouter::GetInstance()->CandidateClicked( | |
| 323 profile(), extension_id(), index, button); | |
| 324 | |
| 325 return true; | |
| 326 } | |
| 327 | |
| 328 bool CursorUpInputUiFunction::RunImpl() { | |
| 329 ExtensionInputUiEventRouter::GetInstance()->CursorUp( | |
| 330 profile(), extension_id()); | |
| 331 return true; | |
| 332 } | |
| 333 | |
| 334 bool CursorDownInputUiFunction::RunImpl() { | |
| 335 ExtensionInputUiEventRouter::GetInstance()->CursorDown( | |
| 336 profile(), extension_id()); | |
| 337 return true; | |
| 338 } | |
| 339 | |
| 340 bool PageUpInputUiFunction::RunImpl() { | |
| 341 ExtensionInputUiEventRouter::GetInstance()->PageUp( | |
| 342 profile(), extension_id()); | |
| 343 return true; | |
| 344 } | |
| 345 | |
| 346 bool PageDownInputUiFunction::RunImpl() { | |
| 347 ExtensionInputUiEventRouter::GetInstance()->PageDown( | |
| 348 profile(), extension_id()); | |
| 349 return true; | |
| 350 } | |
| 351 | |
| OLD | NEW |