OLD | NEW |
---|---|
(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.
| |
OLD | NEW |