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_engine_factory_service.h" 6 7 #include <map> 8 #include <string> 9 10 #include "base/strings/string_number_conversions.h" 11 #include "chromeos/dbus/ibus/ibus_constants.h" 12 #include "chromeos/ime/ibus_bridge.h" 13 #include "dbus/bus.h" 14 #include "dbus/exported_object.h" 15 #include "dbus/message.h" 16 17 namespace chromeos { 18 19 namespace { 20 const char* kObjectPathPrefix = "/org/freedesktop/IBus/Engine/"; 21 } // namespace 22 23 class IBusEngineFactoryServiceImpl : public IBusEngineFactoryService { 24 public: 25 explicit IBusEngineFactoryServiceImpl(dbus::Bus* bus) 26 : bus_(bus), 27 object_path_id_(0), 28 weak_ptr_factory_(this) { 29 exported_object_ = bus_->GetExportedObject( 30 dbus::ObjectPath(ibus::engine_factory::kServicePath)); 31 32 exported_object_->ExportMethod( 33 ibus::engine_factory::kServiceInterface, 34 ibus::engine_factory::kCreateEngineMethod, 35 base::Bind(&IBusEngineFactoryServiceImpl::CreateEngine, 36 weak_ptr_factory_.GetWeakPtr()), 37 base::Bind(&IBusEngineFactoryServiceImpl::CreateEngineExported, 38 weak_ptr_factory_.GetWeakPtr())); 39 } 40 41 virtual ~IBusEngineFactoryServiceImpl() { 42 bus_->UnregisterExportedObject(dbus::ObjectPath( 43 ibus::engine_factory::kServicePath)); 44 } 45 46 // IBusEngineFactoryService override. 47 virtual void SetCreateEngineHandler( 48 const std::string& engine_id, 49 const CreateEngineHandler& create_engine_handler) OVERRIDE { 50 DCHECK(create_engine_callback_map_[engine_id].is_null()); 51 create_engine_callback_map_[engine_id] = create_engine_handler; 52 } 53 54 // IBusEngineFactoryService override. 55 virtual void UnsetCreateEngineHandler( 56 const std::string& engine_id) OVERRIDE { 57 create_engine_callback_map_[engine_id].Reset(); 58 } 59 60 // IBusEngineFactoryService override. 61 virtual dbus::ObjectPath GenerateUniqueObjectPath() OVERRIDE { 62 return dbus::ObjectPath(kObjectPathPrefix + 63 base::IntToString(object_path_id_++)); 64 } 65 66 private: 67 // Called when the ibus-daemon requires new engine instance. 68 void CreateEngine(dbus::MethodCall* method_call, 69 dbus::ExportedObject::ResponseSender response_sender) { 70 if (!method_call) { 71 LOG(ERROR) << "method call does not have any arguments."; 72 return; 73 } 74 dbus::MessageReader reader(method_call); 75 std::string engine_name; 76 77 if (!reader.PopString(&engine_name)) { 78 LOG(ERROR) << "Expected argument is string."; 79 return; 80 } 81 if (create_engine_callback_map_[engine_name].is_null()) { 82 LOG(WARNING) << "The CreateEngine handler for " << engine_name 83 << " is NULL."; 84 } else { 85 create_engine_callback_map_[engine_name].Run( 86 base::Bind(&IBusEngineFactoryServiceImpl::CreateEngineSendReply, 87 weak_ptr_factory_.GetWeakPtr(), 88 base::Passed(dbus::Response::FromMethodCall(method_call)), 89 response_sender)); 90 } 91 } 92 93 // Sends reply message for CreateEngine method call. 94 void CreateEngineSendReply( 95 scoped_ptr<dbus::Response> response, 96 const dbus::ExportedObject::ResponseSender response_sender, 97 const dbus::ObjectPath& path) { 98 dbus::MessageWriter writer(response.get()); 99 writer.AppendObjectPath(path); 100 response_sender.Run(response.Pass()); 101 } 102 103 // Called when the CreateEngine method is exported. 104 void CreateEngineExported(const std::string& interface_name, 105 const std::string& method_name, 106 bool success) { 107 DCHECK(success) << "Failed to export: " 108 << interface_name << "." << method_name; 109 } 110 111 // CreateEngine method call handler. 112 std::map<std::string, CreateEngineHandler> create_engine_callback_map_; 113 114 dbus::Bus* bus_; 115 scoped_refptr<dbus::ExportedObject> exported_object_; 116 uint32 object_path_id_; 117 base::WeakPtrFactory<IBusEngineFactoryServiceImpl> weak_ptr_factory_; 118 119 DISALLOW_COPY_AND_ASSIGN(IBusEngineFactoryServiceImpl); 120 }; 121 122 // An implementation of IBusEngineFactoryService without ibus-daemon 123 // interaction. Currently this class is used only on linux desktop. 124 // TODO(nona): Use this on ChromeOS device once crbug.com/171351 is fixed. 125 class IBusEngineFactoryServiceDaemonlessImpl : public IBusEngineFactoryService { 126 public: 127 IBusEngineFactoryServiceDaemonlessImpl() 128 : object_path_id_(0) {} 129 virtual ~IBusEngineFactoryServiceDaemonlessImpl() {} 130 131 // IBusEngineFactoryService override. 132 virtual void SetCreateEngineHandler( 133 const std::string& engine_id, 134 const CreateEngineHandler& create_engine_handler) OVERRIDE { 135 IBusBridge::Get()->SetCreateEngineHandler(engine_id, create_engine_handler); 136 } 137 138 // IBusEngineFactoryService override. 139 virtual void UnsetCreateEngineHandler( 140 const std::string& engine_id) OVERRIDE { 141 IBusBridge::Get()->UnsetCreateEngineHandler(engine_id); 142 } 143 144 // IBusEngineFactoryService override. 145 virtual dbus::ObjectPath GenerateUniqueObjectPath() OVERRIDE { 146 // ObjectPath is not used in non-ibus-daemon implementation. Passing dummy 147 // valid and unique dummy object path. 148 return dbus::ObjectPath("/dummy/object/path" + 149 base::IntToString(object_path_id_++)); 150 } 151 152 private: 153 uint32 object_path_id_; 154 DISALLOW_COPY_AND_ASSIGN(IBusEngineFactoryServiceDaemonlessImpl); 155 }; 156 157 IBusEngineFactoryService::IBusEngineFactoryService() { 158 } 159 160 IBusEngineFactoryService::~IBusEngineFactoryService() { 161 } 162 163 // static 164 IBusEngineFactoryService* IBusEngineFactoryService::Create( 165 dbus::Bus* bus, 166 DBusClientImplementationType type) { 167 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) 168 return new IBusEngineFactoryServiceImpl(bus); 169 else 170 return new IBusEngineFactoryServiceDaemonlessImpl(); 171 } 172 173 } // namespace chromeos 174