1 // Copyright (c) 2012 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 "chromeos/dbus/ibus/ibus_panel_service.h" 6 7 #include <string> 8 #include "base/bind.h" 9 #include "base/callback.h" 10 #include "chromeos/dbus/ibus/ibus_constants.h" 11 #include "chromeos/dbus/ibus/ibus_engine_service.h" 12 #include "chromeos/dbus/ibus/ibus_input_context_client.h" 13 #include "chromeos/dbus/ibus/ibus_lookup_table.h" 14 #include "chromeos/dbus/ibus/ibus_property.h" 15 #include "chromeos/dbus/ibus/ibus_text.h" 16 #include "chromeos/ime/ibus_bridge.h" 17 #include "dbus/bus.h" 18 #include "dbus/exported_object.h" 19 #include "dbus/message.h" 20 #include "dbus/object_path.h" 21 #include "dbus/object_proxy.h" 22 23 namespace chromeos { 24 25 class IBusPanelServiceImpl : public IBusPanelService { 26 public: 27 explicit IBusPanelServiceImpl(dbus::Bus* bus, 28 IBusInputContextClient* input_context) 29 : bus_(bus), 30 candidate_window_handler_(NULL), 31 property_handler_(NULL), 32 weak_ptr_factory_(this) { 33 exported_object_ = bus->GetExportedObject( 34 dbus::ObjectPath(ibus::panel::kServicePath)); 35 36 exported_object_->ExportMethod( 37 ibus::panel::kServiceInterface, 38 ibus::panel::kUpdateLookupTableMethod, 39 base::Bind(&IBusPanelServiceImpl::UpdateLookupTable, 40 weak_ptr_factory_.GetWeakPtr()), 41 base::Bind(&IBusPanelServiceImpl::OnMethodExported, 42 weak_ptr_factory_.GetWeakPtr())); 43 44 exported_object_->ExportMethod( 45 ibus::panel::kServiceInterface, 46 ibus::panel::kHideLookupTableMethod, 47 base::Bind(&IBusPanelServiceImpl::HideLookupTable, 48 weak_ptr_factory_.GetWeakPtr()), 49 base::Bind(&IBusPanelServiceImpl::OnMethodExported, 50 weak_ptr_factory_.GetWeakPtr())); 51 52 exported_object_->ExportMethod( 53 ibus::panel::kServiceInterface, 54 ibus::panel::kUpdateAuxiliaryTextMethod, 55 base::Bind(&IBusPanelServiceImpl::UpdateAuxiliaryText, 56 weak_ptr_factory_.GetWeakPtr()), 57 base::Bind(&IBusPanelServiceImpl::OnMethodExported, 58 weak_ptr_factory_.GetWeakPtr())); 59 60 exported_object_->ExportMethod( 61 ibus::panel::kServiceInterface, 62 ibus::panel::kHideAuxiliaryTextMethod, 63 base::Bind(&IBusPanelServiceImpl::HideAuxiliaryText, 64 weak_ptr_factory_.GetWeakPtr()), 65 base::Bind(&IBusPanelServiceImpl::OnMethodExported, 66 weak_ptr_factory_.GetWeakPtr())); 67 68 exported_object_->ExportMethod( 69 ibus::panel::kServiceInterface, 70 ibus::panel::kUpdatePreeditTextMethod, 71 base::Bind(&IBusPanelServiceImpl::UpdatePreeditText, 72 weak_ptr_factory_.GetWeakPtr()), 73 base::Bind(&IBusPanelServiceImpl::OnMethodExported, 74 weak_ptr_factory_.GetWeakPtr())); 75 76 exported_object_->ExportMethod( 77 ibus::panel::kServiceInterface, 78 ibus::panel::kHidePreeditTextMethod, 79 base::Bind(&IBusPanelServiceImpl::HidePreeditText, 80 weak_ptr_factory_.GetWeakPtr()), 81 base::Bind(&IBusPanelServiceImpl::OnMethodExported, 82 weak_ptr_factory_.GetWeakPtr())); 83 84 exported_object_->ExportMethod( 85 ibus::panel::kServiceInterface, 86 ibus::panel::kRegisterPropertiesMethod, 87 base::Bind(&IBusPanelServiceImpl::RegisterProperties, 88 weak_ptr_factory_.GetWeakPtr()), 89 base::Bind(&IBusPanelServiceImpl::OnMethodExported, 90 weak_ptr_factory_.GetWeakPtr())); 91 92 exported_object_->ExportMethod( 93 ibus::panel::kServiceInterface, 94 ibus::panel::kUpdatePropertyMethod, 95 base::Bind(&IBusPanelServiceImpl::UpdateProperty, 96 weak_ptr_factory_.GetWeakPtr()), 97 base::Bind(&IBusPanelServiceImpl::OnMethodExported, 98 weak_ptr_factory_.GetWeakPtr())); 99 100 exported_object_->ExportMethod( 101 ibus::panel::kServiceInterface, 102 ibus::panel::kFocusInMethod, 103 base::Bind(&IBusPanelServiceImpl::NoOperation, 104 weak_ptr_factory_.GetWeakPtr()), 105 base::Bind(&IBusPanelServiceImpl::OnMethodExported, 106 weak_ptr_factory_.GetWeakPtr())); 107 108 exported_object_->ExportMethod( 109 ibus::panel::kServiceInterface, 110 ibus::panel::kFocusOutMethod, 111 base::Bind(&IBusPanelServiceImpl::NoOperation, 112 weak_ptr_factory_.GetWeakPtr()), 113 base::Bind(&IBusPanelServiceImpl::OnMethodExported, 114 weak_ptr_factory_.GetWeakPtr())); 115 116 exported_object_->ExportMethod( 117 ibus::panel::kServiceInterface, 118 ibus::panel::kStateChangedMethod, 119 base::Bind(&IBusPanelServiceImpl::NoOperation, 120 weak_ptr_factory_.GetWeakPtr()), 121 base::Bind(&IBusPanelServiceImpl::OnMethodExported, 122 weak_ptr_factory_.GetWeakPtr())); 123 124 // Request well known name to ibus-daemon. 125 bus->RequestOwnership( 126 ibus::panel::kServiceName, 127 dbus::Bus::REQUIRE_PRIMARY, 128 base::Bind(&IBusPanelServiceImpl::OnRequestOwnership, 129 weak_ptr_factory_.GetWeakPtr())); 130 131 input_context->SetSetCursorLocationHandler( 132 base::Bind(&IBusPanelServiceImpl::SetCursorLocation, 133 weak_ptr_factory_.GetWeakPtr())); 134 } 135 136 virtual ~IBusPanelServiceImpl() { 137 bus_->UnregisterExportedObject( 138 dbus::ObjectPath(ibus::panel::kServicePath)); 139 } 140 141 // IBusPanelService override. 142 virtual void SetUpCandidateWindowHandler( 143 IBusPanelCandidateWindowHandlerInterface* handler) OVERRIDE { 144 DCHECK(handler); 145 candidate_window_handler_ = handler; 146 } 147 148 // IBusPanelService override. 149 virtual void SetUpPropertyHandler( 150 IBusPanelPropertyHandlerInterface* handler) OVERRIDE { 151 DCHECK(handler); 152 property_handler_ = handler; 153 } 154 155 // IBusPanelService override. 156 virtual void CandidateClicked(uint32 index, 157 ibus::IBusMouseButton button, 158 uint32 state) OVERRIDE { 159 dbus::Signal signal(ibus::panel::kServiceInterface, 160 ibus::panel::kCandidateClickedSignal); 161 dbus::MessageWriter writer(&signal); 162 writer.AppendUint32(index); 163 writer.AppendUint32(static_cast<uint32>(button)); 164 writer.AppendUint32(state); 165 exported_object_->SendSignal(&signal); 166 } 167 168 // IBusPanelService override. 169 virtual void CursorUp() OVERRIDE { 170 dbus::Signal signal(ibus::panel::kServiceInterface, 171 ibus::panel::kCursorUpSignal); 172 exported_object_->SendSignal(&signal); 173 } 174 175 // IBusPanelService override. 176 virtual void CursorDown() OVERRIDE { 177 dbus::Signal signal(ibus::panel::kServiceInterface, 178 ibus::panel::kCursorDownSignal); 179 exported_object_->SendSignal(&signal); 180 } 181 182 // IBusPanelService override. 183 virtual void PageUp() OVERRIDE { 184 dbus::Signal signal(ibus::panel::kServiceInterface, 185 ibus::panel::kPageUpSignal); 186 exported_object_->SendSignal(&signal); 187 } 188 189 // IBusPanelService override. 190 virtual void PageDown() OVERRIDE { 191 dbus::Signal signal(ibus::panel::kServiceInterface, 192 ibus::panel::kPageDownSignal); 193 exported_object_->SendSignal(&signal); 194 } 195 196 private: 197 // Handles UpdateLookupTable method call from ibus-daemon. 198 void UpdateLookupTable(dbus::MethodCall* method_call, 199 dbus::ExportedObject::ResponseSender response_sender) { 200 if (!candidate_window_handler_) 201 return; 202 203 dbus::MessageReader reader(method_call); 204 IBusLookupTable table; 205 if (!PopIBusLookupTable(&reader, &table)) { 206 LOG(WARNING) << "UpdateLookupTable called with incorrect parameters: " 207 << method_call->ToString(); 208 return; 209 } 210 bool visible = false; 211 if (!reader.PopBool(&visible)) { 212 LOG(WARNING) << "UpdateLookupTable called with incorrect parameters: " 213 << method_call->ToString(); 214 return; 215 } 216 candidate_window_handler_->UpdateLookupTable(table, visible); 217 response_sender.Run(dbus::Response::FromMethodCall(method_call)); 218 } 219 220 // Handles HideLookupTable method call from ibus-daemon. 221 void HideLookupTable(dbus::MethodCall* method_call, 222 dbus::ExportedObject::ResponseSender response_sender) { 223 if (!candidate_window_handler_) 224 return; 225 226 candidate_window_handler_->HideLookupTable(); 227 response_sender.Run(dbus::Response::FromMethodCall(method_call)); 228 } 229 230 // Handles UpdateAuxiliaryText method call from ibus-daemon. 231 void UpdateAuxiliaryText( 232 dbus::MethodCall* method_call, 233 dbus::ExportedObject::ResponseSender response_sender) { 234 if (!candidate_window_handler_) 235 return; 236 237 dbus::MessageReader reader(method_call); 238 std::string text; 239 if (!PopStringFromIBusText(&reader, &text)) { 240 LOG(WARNING) << "UpdateAuxiliaryText called with incorrect parameters: " 241 << method_call->ToString(); 242 return; 243 } 244 bool visible = false; 245 if (!reader.PopBool(&visible)) { 246 LOG(WARNING) << "UpdateAuxiliaryText called with incorrect parameters: " 247 << method_call->ToString(); 248 return; 249 } 250 candidate_window_handler_->UpdateAuxiliaryText(text, visible); 251 response_sender.Run(dbus::Response::FromMethodCall(method_call)); 252 } 253 254 // Handles HideAuxiliaryText method call from ibus-daemon. 255 void HideAuxiliaryText(dbus::MethodCall* method_call, 256 dbus::ExportedObject::ResponseSender response_sender) { 257 if (!candidate_window_handler_) 258 return; 259 260 candidate_window_handler_->HideAuxiliaryText(); 261 response_sender.Run(dbus::Response::FromMethodCall(method_call)); 262 } 263 264 // Handles UpdatePreeditText method call from ibus-daemon. 265 void UpdatePreeditText(dbus::MethodCall* method_call, 266 dbus::ExportedObject::ResponseSender response_sender) { 267 if (!candidate_window_handler_) 268 return; 269 270 dbus::MessageReader reader(method_call); 271 std::string text; 272 if (!PopStringFromIBusText(&reader, &text)) { 273 LOG(WARNING) << "UpdatePreeditText called with incorrect parameters: " 274 << method_call->ToString(); 275 return; 276 } 277 uint32 cursor_pos = 0; 278 if (!reader.PopUint32(&cursor_pos)) { 279 LOG(WARNING) << "UpdatePreeditText called with incorrect parameters: " 280 << method_call->ToString(); 281 return; 282 } 283 bool visible = false; 284 if (!reader.PopBool(&visible)) { 285 LOG(WARNING) << "UpdatePreeditText called with incorrect parameters: " 286 << method_call->ToString(); 287 return; 288 } 289 candidate_window_handler_->UpdatePreeditText(text, cursor_pos, visible); 290 response_sender.Run(dbus::Response::FromMethodCall(method_call)); 291 } 292 293 // Handles HidePreeditText method call from ibus-daemon. 294 void HidePreeditText(dbus::MethodCall* method_call, 295 dbus::ExportedObject::ResponseSender response_sender) { 296 if (!candidate_window_handler_) 297 return; 298 299 candidate_window_handler_->HidePreeditText(); 300 response_sender.Run(dbus::Response::FromMethodCall(method_call)); 301 } 302 303 // Handles RegisterProperties method call from ibus-daemon. 304 void RegisterProperties( 305 dbus::MethodCall* method_call, 306 dbus::ExportedObject::ResponseSender response_sender) { 307 if (!property_handler_) 308 return; 309 310 dbus::MessageReader reader(method_call); 311 IBusPropertyList properties; 312 if (!PopIBusPropertyList(&reader, &properties)) { 313 DLOG(WARNING) << "RegisterProperties called with incorrect parameters:" 314 << method_call->ToString(); 315 return; 316 } 317 property_handler_->RegisterProperties(properties); 318 319 response_sender.Run(dbus::Response::FromMethodCall(method_call)); 320 } 321 322 // Handles UpdateProperty method call from ibus-daemon. 323 void UpdateProperty(dbus::MethodCall* method_call, 324 dbus::ExportedObject::ResponseSender response_sender) { 325 if (!property_handler_) 326 return; 327 328 dbus::MessageReader reader(method_call); 329 IBusProperty property; 330 if (!PopIBusProperty(&reader, &property)) { 331 DLOG(WARNING) << "RegisterProperties called with incorrect parameters:" 332 << method_call->ToString(); 333 return; 334 } 335 property_handler_->UpdateProperty(property); 336 337 response_sender.Run(dbus::Response::FromMethodCall(method_call)); 338 } 339 340 void SetCursorLocation(const ibus::Rect& cursor_location, 341 const ibus::Rect& composition_head) { 342 if (candidate_window_handler_) 343 candidate_window_handler_->SetCursorLocation(cursor_location, 344 composition_head); 345 } 346 347 // Handles FocusIn, FocusOut, StateChanged method calls from IBus, and ignores 348 // them. 349 void NoOperation(dbus::MethodCall* method_call, 350 dbus::ExportedObject::ResponseSender response_sender) { 351 if (!property_handler_) 352 return; 353 354 response_sender.Run(dbus::Response::FromMethodCall(method_call)); 355 } 356 357 // Called when the method call is exported. 358 void OnMethodExported(const std::string& interface_name, 359 const std::string& method_name, 360 bool success) { 361 LOG_IF(WARNING, !success) << "Failed to export " 362 << interface_name << "." << method_name; 363 } 364 365 // Called when the well knwon name is acquired. 366 void OnRequestOwnership(const std::string& name, bool obtained) { 367 LOG_IF(ERROR, !obtained) << "Failed to acquire well known name:" 368 << name; 369 } 370 371 // D-Bus bus object used for unregistering exported methods in dtor. 372 dbus::Bus* bus_; 373 374 // All incoming method calls are passed on to the |candidate_window_handler_| 375 // or |property_handler|. This class does not take ownership of following 376 // handlers. 377 IBusPanelCandidateWindowHandlerInterface* candidate_window_handler_; 378 IBusPanelPropertyHandlerInterface* property_handler_; 379 380 scoped_refptr<dbus::ExportedObject> exported_object_; 381 base::WeakPtrFactory<IBusPanelServiceImpl> weak_ptr_factory_; 382 383 DISALLOW_COPY_AND_ASSIGN(IBusPanelServiceImpl); 384 }; 385 386 // An implementation of IBusPanelService without ibus-daemon interaction. 387 // Currently this class is used only on linux desktop. 388 // TODO(nona): Use this on ChromeOS device once crbug.com/171351 is fixed. 389 class IBusPanelServiceDaemonlessImpl : public IBusPanelService { 390 public: 391 IBusPanelServiceDaemonlessImpl() {} 392 virtual ~IBusPanelServiceDaemonlessImpl() {} 393 394 // IBusPanelService override. 395 virtual void SetUpCandidateWindowHandler( 396 IBusPanelCandidateWindowHandlerInterface* handler) OVERRIDE { 397 IBusBridge::Get()->SetCandidateWindowHandler(handler); 398 } 399 400 // IBusPanelService override. 401 virtual void SetUpPropertyHandler( 402 IBusPanelPropertyHandlerInterface* handler) OVERRIDE { 403 IBusBridge::Get()->SetPropertyHandler(handler); 404 } 405 406 // IBusPanelService override. 407 virtual void CandidateClicked(uint32 index, 408 ibus::IBusMouseButton button, 409 uint32 state) OVERRIDE { 410 IBusEngineHandlerInterface* engine = IBusBridge::Get()->GetEngineHandler(); 411 if (engine) 412 engine->CandidateClicked(index, button, state); 413 } 414 415 // IBusPanelService override. 416 virtual void CursorUp() OVERRIDE { 417 // Cursor Up is not supported on Chrome OS. 418 } 419 420 // IBusPanelService override. 421 virtual void CursorDown() OVERRIDE { 422 // Cursor Down is not supported on Chrome OS. 423 } 424 425 // IBusPanelService override. 426 virtual void PageUp() OVERRIDE { 427 // Page Up is not supported on Chrome OS. 428 } 429 430 // IBusPanelService override. 431 virtual void PageDown() OVERRIDE { 432 // Page Down is not supported on Chrome OS. 433 } 434 435 private: 436 DISALLOW_COPY_AND_ASSIGN(IBusPanelServiceDaemonlessImpl); 437 }; 438 439 IBusPanelService::IBusPanelService() { 440 } 441 442 IBusPanelService::~IBusPanelService() { 443 } 444 445 // static 446 IBusPanelService* IBusPanelService::Create( 447 DBusClientImplementationType type, 448 dbus::Bus* bus, 449 IBusInputContextClient* input_context) { 450 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) { 451 return new IBusPanelServiceImpl(bus, input_context); 452 } else { 453 return new IBusPanelServiceDaemonlessImpl(); 454 } 455 } 456 457 } // namespace chromeos 458