Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: mojo/services/dbus_echo/dbus_echo_service.cc

Issue 242763003: Implement a trivial Mojo EchoService that can be connected to over DBus (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Automatically exclude DBusServiceLoader on non-Linux Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
viettrungluu 2014/04/23 20:07:24 Nit: There's no "(c)" in the current copyright not
Chris Masone 2014/04/23 22:31:00 Done.
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 "base/at_exit.h"
6 #include "base/bind.h"
7 #include "base/callback.h"
8 #include "base/command_line.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/message_loop/message_loop_proxy.h"
13 #include "base/run_loop.h"
14 #include "dbus/bus.h"
15 #include "dbus/exported_object.h"
16 #include "dbus/file_descriptor.h"
17 #include "dbus/message.h"
18 #include "dbus/object_path.h"
19 #include "mojo/common/mojo_channel_init.h"
20 #include "mojo/embedder/embedder.h"
21 #include "mojo/public/cpp/bindings/interface.h"
22 #include "mojo/public/cpp/bindings/remote_ptr.h"
23 #include "mojo/public/cpp/environment/environment.h"
24 #include "mojo/public/cpp/shell/application.h"
25 #include "mojo/public/interfaces/shell/shell.mojom.h"
26 #include "mojo/services/dbus_echo/echo.mojom.h"
27 #include "mojo/shell/external_service.mojom.h"
28
29 class EchoServiceImpl : public mojo::ServiceConnection<mojo::EchoService,
30 EchoServiceImpl> {
31 public:
32 EchoServiceImpl() {}
33 virtual ~EchoServiceImpl() {}
34
35 protected:
36 virtual void Echo(
37 const mojo::String& in_to_echo,
38 const mojo::Callback<void(mojo::String)>& callback) OVERRIDE {
39 DVLOG(1) << "Asked to echo " << in_to_echo.To<std::string>();
40 callback.Run(in_to_echo);
41 }
42 };
43
44
45 class DBusEchoService : public mojo::ExternalService {
46 public:
47 static const char kMojoImplPath[];
48 static const char kMojoInterface[];
49 static const char kServiceName[];
50
51 DBusEchoService() : exported_object_(NULL) {
52 }
53 ~DBusEchoService() {}
54
55 void Start() {
56 InitializeDBus();
57 ExportMethods();
58 TakeDBusServiceOwnership();
59 DVLOG(1) << "Echo service started";
60 }
61
62 private:
63 // TODO(cmasone): Use a Delegate pattern to allow the ConnectChannel
64 // code to be shared among all Mojo services that wish to be
65 // connected to over DBus.
66 virtual void Activate(mojo::ScopedMessagePipeHandle client_handle) OVERRIDE {
67 mojo::ScopedShellHandle shell_handle(
68 mojo::ShellHandle(client_handle.release().value()));
69 app_.reset(new mojo::Application(shell_handle.Pass()));
70 app_->AddServiceConnector(new mojo::ServiceConnector<EchoServiceImpl>());
71 }
72
73 // Implementation of org.chromium.Mojo.ConnectChannel, exported over DBus.
74 // Takes a file descriptor and uses it to create a MessagePipe that is then
75 // hooked to a RemotePtr<mojo::ExternalServiceHost>.
76 void ConnectChannel(dbus::MethodCall* method_call,
77 dbus::ExportedObject::ResponseSender sender) {
78 dbus::MessageReader reader(method_call);
79 dbus::FileDescriptor wrapped_fd;
80 if (!reader.PopFileDescriptor(&wrapped_fd)) {
81 sender.Run(
82 dbus::ErrorResponse::FromMethodCall(
83 method_call,
84 "org.chromium.Mojo.BadHandle",
85 "Invalid FD.").PassAs<dbus::Response>());
86 return;
87 }
88 wrapped_fd.CheckValidity();
89 channel_init_.reset(new mojo::common::MojoChannelInit);
90 channel_init_->Init(wrapped_fd.TakeValue(),
91 base::MessageLoopProxy::current());
92 CHECK(channel_init_->is_handle_valid());
93
94 // TODO(cmasone): Figure out how to correctly clean up the channel when
95 // the peer disappears. Passing an ErrorHandler when constructing the
96 // RemotePtr<> below didn't seem to work. OnError wasn't called.
97 mojo::ScopedExternalServiceHostHandle client_handle(
98 mojo::ExternalServiceHostHandle(
99 channel_init_->bootstrap_message_pipe().release().value()));
100 external_service_host_.reset(client_handle.Pass(), this);
101
102 sender.Run(dbus::Response::FromMethodCall(method_call));
103 }
104
105 void ExportMethods() {
106 CHECK(exported_object_);
107 CHECK(exported_object_->ExportMethodAndBlock(
108 kMojoInterface, "ConnectChannel",
109 base::Bind(&DBusEchoService::ConnectChannel,
110 base::Unretained(this))));
111 }
112
113 void InitializeDBus() {
114 CHECK(!bus_);
115 dbus::Bus::Options options;
116 options.bus_type = dbus::Bus::SESSION;
117 bus_ = new dbus::Bus(options);
118 CHECK(bus_->Connect());
119 CHECK(bus_->SetUpAsyncOperations());
120
121 exported_object_ = bus_->GetExportedObject(dbus::ObjectPath(kMojoImplPath));
122 }
123
124 void TakeDBusServiceOwnership() {
125 CHECK(bus_->RequestOwnershipAndBlock(
126 kServiceName,
127 dbus::Bus::REQUIRE_PRIMARY_ALLOW_REPLACEMENT))
128 << "Unable to take ownership of " << kServiceName;
129 }
130
131 scoped_refptr<dbus::Bus> bus_;
132 dbus::ExportedObject* exported_object_; // Owned by bus_;
133 scoped_ptr<mojo::common::MojoChannelInit> channel_init_;
134 mojo::RemotePtr<mojo::ExternalServiceHost> external_service_host_;
135 scoped_ptr<mojo::Application> app_;
136 };
137
138 // TODO(cmasone): Figure out where these "well-known" names should be defined
139 // so they can be shared with DBusServiceLoader and such.
140 const char DBusEchoService::kMojoImplPath[] = "/org/chromium/MojoImpl";
141 const char DBusEchoService::kMojoInterface[] = "org.chromium.Mojo";
142 const char DBusEchoService::kServiceName[] = "org.chromium.EchoService";
143
144 int main(int argc, char** argv) {
145 base::AtExitManager exit_manager;
146 CommandLine::Init(argc, argv);
147
148 logging::LoggingSettings settings;
149 settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
150 logging::InitLogging(settings);
151 logging::SetLogItems(false, // Process ID
152 false, // Thread ID
153 false, // Timestamp
154 false); // Tick count
155
156 mojo::Environment env;
157 mojo::embedder::Init();
158
159 base::MessageLoopForIO message_loop;
160 base::RunLoop run_loop;
161
162 DBusEchoService echo_service;
163 echo_service.Start();
164
165 run_loop.Run();
166 }
viettrungluu 2014/04/23 20:07:24 nit: Presumably, this never actually quits, and th
Chris Masone 2014/04/23 22:31:00 Done.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698