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

Side by Side Diff: dbus/bus.cc

Issue 7491029: Implement Bus and ObjectProxy classes for our D-Bus library. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: work-in-progress Created 9 years, 4 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
« dbus/bus.h ('K') | « dbus/bus.h ('k') | dbus/dbus.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 "dbus/bus.h"
6
7 #include "base/logging.h"
8 #include "base/message_loop.h"
9 #include "base/threading/thread.h"
10 #include "base/threading/thread_restrictions.h"
11 #include "dbus/object_proxy.h"
12
13 namespace dbus {
14
15 namespace {
16
17 // The class is used for watching the file descriptor used for D-Bus
18 // communication.
19 class Watch : public base::MessagePumpLibevent::Watcher {
20 public:
21 Watch(DBusWatch* watch)
22 : raw_watch_(watch) {
23 dbus_watch_set_data(raw_watch_, this, NULL);
24 }
25
26 ~Watch() {
27 dbus_watch_set_data(raw_watch_, NULL, NULL);
28 }
29
30 // Returns true if the underlying file descriptor is ready to be watched.
31 bool IsReadyToBeWatched() {
32 return dbus_watch_get_enabled(raw_watch_);
33 }
34
35 // Starts watching the underlying file descriptor.
36 void StartWatching() {
37 const int fd = dbus_watch_get_unix_fd(raw_watch_);
38 const int flags = dbus_watch_get_flags(raw_watch_);
39
40 MessageLoopForIO::Mode mode;
41 if ((flags & DBUS_WATCH_READABLE) && (flags & DBUS_WATCH_WRITABLE))
42 mode = MessageLoopForIO::WATCH_READ_WRITE;
43 if (flags & DBUS_WATCH_READABLE)
stevenjb 2011/07/29 21:54:17 else if
satorux1 2011/08/01 19:56:41 Done.
44 mode = MessageLoopForIO::WATCH_READ;
45 if (flags & DBUS_WATCH_WRITABLE)
stevenjb 2011/07/29 21:54:17 else if
satorux1 2011/08/01 19:56:41 Done.
46 mode = MessageLoopForIO::WATCH_WRITE;
stevenjb 2011/07/29 21:54:17 else NOTREACHED()
satorux1 2011/08/01 19:56:41 Done.
47
48 const bool persistent = true; // Watch persistently.
49 const bool success = MessageLoopForIO::current()->WatchFileDescriptor(
50 fd,
51 persistent,
52 mode,
53 &file_descriptor_watcher_,
54 this);
55 DCHECK(success) << "Unable to allocate memory";
56 }
57
58 // Stops watching the underlying file descriptor.
59 void StopWatching() {
60 file_descriptor_watcher_->StopWatchingFileDescriptor();
61 }
62
63 private:
64 // Implement MessagePumpLibevent::Watcher.
65 virtual void OnFileCanReadWithoutBlocking(int fd) {
66 const bool success = dbus_watch_handle(raw_watch_, DBUS_WATCH_READABLE);
67 DCHECK(success) << "Unable to allocate memory";
68 }
69
70 // Implement MessagePumpLibevent::Watcher.
71 virtual void OnFileCanWriteWithoutBlocking(int fd) {
72 const bool success = dbus_watch_handle(raw_watch_, DBUS_WATCH_WRITABLE);
73 DCHECK(success) << "Unable to allocate memory";
74 }
75
76 DBusWatch* raw_watch_;
77 base::MessagePumpLibevent::FileDescriptorWatcher file_descriptor_watcher_;
78 };
79
80 } // namespace
81
82 Bus::Options::Options()
83 : bus_type(SESSION),
84 connection_type(PRIVATE),
85 io_thread(NULL) {
86 }
87
88 Bus::Bus(const Options& options)
89 : bus_type_(options.bus_type),
90 connection_type_(options.connection_type),
91 io_thread_(options.io_thread),
92 connection_(NULL) {
93 if (io_thread_) {
94 DCHECK(io_thread_->IsRunning())
95 << "The IO thread should be running";
96 DCHECK_EQ(MessageLoop::TYPE_IO,
97 io_thread_->message_loop()->type())
98 << "The IO thread should have an MessageLoopForIO attached";
99 }
100 }
101
102 Bus::~Bus() {
103 // Private connection should be closed.
104 if (connection_ && connection_type_ == PRIVATE) {
105 dbus_connection_close(connection_);
106 }
107 }
108
109 ObjectProxy* Bus::GetObjectProxy(const std::string& service_name,
110 const std::string& object_path) {
111 return new ObjectProxy(this, service_name, object_path);
112 }
113
114 bool Bus::Init() {
115 // dbus_bus_get_private() and dbus_bus_get() are blocking calls.
116 base::ThreadRestrictions::AssertIOAllowed();
117
118 // Check if it's already initialized.
119 if (connection_)
120 return true;
121
122 DBusError error = {};
stevenjb 2011/07/29 21:54:17 nit: don't need to initialize error (and better no
satorux1 2011/08/01 19:56:41 Done.
123 dbus_error_init(&error);
124 const DBusBusType dbus_bus_type = static_cast<DBusBusType>(bus_type_);
125 if (connection_type_ == PRIVATE) {
126 connection_ = dbus_bus_get_private(dbus_bus_type, &error);
127 } else {
128 connection_ = dbus_bus_get(dbus_bus_type, &error);
129 }
130 if (!connection_) {
131 if (dbus_error_is_set(&error)) {
132 LOG(ERROR) << error.message;
133 }
134 return false;
135 }
136
137 // This is unnecessary if client only uses synchronous APIs, but it
138 // won't hurt.
139 SetUpAsyncOperations();
140
141 return true;
142 }
143
144 void Bus::SetUpAsyncOperations() {
145 // Process all the incoming data if any, so that OnDispatchStatus() will
146 // be called when the incoming data is ready.
147 ProcessAllIncomingDataIfAny(connection_);
148
149 dbus_connection_set_watch_functions(connection_,
150 &Bus::OnAddWatchStub,
151 &Bus::OnRemoveWatchStub,
152 &Bus::OnToggleWatchStub,
153 this,
154 NULL);
155 // TODO(satorux): Timeout is not yet implemented.
156 dbus_connection_set_timeout_functions(connection_,
157 NULL,
158 NULL,
159 NULL,
160 NULL,
161 NULL);
162 dbus_connection_set_dispatch_status_function(
163 connection_,
164 &Bus::OnDispatchStatusChangedStub,
165 connection_,
166 NULL);
167 }
168
169 void Bus::ProcessAllIncomingDataIfAny(DBusConnection* connection) {
170 if (dbus_connection_get_dispatch_status(connection) ==
171 DBUS_DISPATCH_DATA_REMAINS) {
172 while (dbus_connection_dispatch(connection) ==
173 DBUS_DISPATCH_DATA_REMAINS);
174 }
175 }
176
177 void Bus::PostTaskToIoThread(const tracked_objects::Location& from_here,
178 const base::Closure& task) {
179 DCHECK(io_thread_);
180 io_thread_->message_loop()->PostTask(from_here, task);
181 }
182
183 dbus_bool_t Bus::OnAddWatch(DBusWatch* raw_watch) {
184 Watch* watch = new Watch(raw_watch);
stevenjb 2011/07/29 21:54:17 This confused me for a while re: when Watch gets d
satorux1 2011/08/01 19:56:41 Good point. I think adding a comment is sufficient
185 if (watch->IsReadyToBeWatched()) {
186 watch->StartWatching();
187 }
188 return true;
189 }
190
191 void Bus::OnRemoveWatch(DBusWatch* raw_watch) {
192 Watch* watch = reinterpret_cast<Watch*>(dbus_watch_get_data(raw_watch));
stevenjb 2011/07/29 21:54:17 dbus_watch_get_data should return a void*, so stat
satorux1 2011/08/01 19:56:41 You are right. Done.
193 delete watch;
194 }
195
196 void Bus::OnToggleWatch(DBusWatch* raw_watch) {
197 Watch* watch = reinterpret_cast<Watch*>(dbus_watch_get_data(raw_watch));
198 if (watch->IsReadyToBeWatched()) {
199 watch->StartWatching();
200 } else {
201 watch->StopWatching();
stevenjb 2011/07/29 21:54:17 Is it safe to call this if StartWatching() was nev
satorux1 2011/08/01 19:56:41 Good point. Yes it's safe. Added a comment about i
202 }
203 }
204
205 void Bus::OnDispatchStatusChanged(DBusConnection* connection,
206 DBusDispatchStatus status) {
207 if (!dbus_connection_get_is_connected(connection))
208 return;
209 ProcessAllIncomingDataIfAny(connection);
210 }
211
212 dbus_bool_t Bus::OnAddWatchStub(DBusWatch* raw_watch, void* data) {
stevenjb 2011/07/29 21:54:17 These could be local functions instead of class st
satorux1 2011/08/01 19:56:41 Here, we need to call self->OnAddWatch(), which is
213 Bus* self = reinterpret_cast<Bus*>(data);
214 return self->OnAddWatch(raw_watch);
215 }
216
217 void Bus::OnRemoveWatchStub(DBusWatch* raw_watch, void* data) {
218 Bus* self = reinterpret_cast<Bus*>(data);
219 return self->OnRemoveWatch(raw_watch);
220 }
221
222 void Bus::OnToggleWatchStub(DBusWatch* raw_watch, void* data) {
223 Bus* self = reinterpret_cast<Bus*>(data);
224 return self->OnToggleWatch(raw_watch);
225 }
226
227 void Bus::OnDispatchStatusChangedStub(DBusConnection* connection,
228 DBusDispatchStatus status,
229 void* data) {
230 Bus* self = reinterpret_cast<Bus*>(data);
231 return self->OnDispatchStatusChanged(connection, status);
232 }
233
234 } // namespace dbus
OLDNEW
« dbus/bus.h ('K') | « dbus/bus.h ('k') | dbus/dbus.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698