Home | History | Annotate | Download | only in ibus
      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