Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / mojo / system / dispatcher.cc
1 // Copyright 2013 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 "mojo/system/dispatcher.h"
6
7 #include "base/logging.h"
8 #include "mojo/system/constants.h"
9 #include "mojo/system/message_pipe_dispatcher.h"
10 #include "mojo/system/platform_handle_dispatcher.h"
11 #include "mojo/system/shared_buffer_dispatcher.h"
12
13 namespace mojo {
14 namespace system {
15
16 namespace test {
17
18 // TODO(vtl): Maybe this should be defined in a test-only file instead.
19 DispatcherTransport DispatcherTryStartTransport(Dispatcher* dispatcher) {
20   return Dispatcher::HandleTableAccess::TryStartTransport(dispatcher);
21 }
22
23 }  // namespace test
24
25 // Dispatcher ------------------------------------------------------------------
26
27 // static
28 DispatcherTransport Dispatcher::HandleTableAccess::TryStartTransport(
29     Dispatcher* dispatcher) {
30   DCHECK(dispatcher);
31
32   if (!dispatcher->lock_.Try())
33     return DispatcherTransport();
34
35   // We shouldn't race with things that close dispatchers, since closing can
36   // only take place either under |handle_table_lock_| or when the handle is
37   // marked as busy.
38   DCHECK(!dispatcher->is_closed_);
39
40   return DispatcherTransport(dispatcher);
41 }
42
43 // static
44 void Dispatcher::TransportDataAccess::StartSerialize(
45     Dispatcher* dispatcher,
46     Channel* channel,
47     size_t* max_size,
48     size_t* max_platform_handles) {
49   DCHECK(dispatcher);
50   dispatcher->StartSerialize(channel, max_size, max_platform_handles);
51 }
52
53 // static
54 bool Dispatcher::TransportDataAccess::EndSerializeAndClose(
55     Dispatcher* dispatcher,
56     Channel* channel,
57     void* destination,
58     size_t* actual_size,
59     embedder::PlatformHandleVector* platform_handles) {
60   DCHECK(dispatcher);
61   return dispatcher->EndSerializeAndClose(
62       channel, destination, actual_size, platform_handles);
63 }
64
65 // static
66 scoped_refptr<Dispatcher> Dispatcher::TransportDataAccess::Deserialize(
67     Channel* channel,
68     int32_t type,
69     const void* source,
70     size_t size,
71     embedder::PlatformHandleVector* platform_handles) {
72   switch (static_cast<int32_t>(type)) {
73     case kTypeUnknown:
74       DVLOG(2) << "Deserializing invalid handle";
75       return scoped_refptr<Dispatcher>();
76     case kTypeMessagePipe:
77       return scoped_refptr<Dispatcher>(
78           MessagePipeDispatcher::Deserialize(channel, source, size));
79     case kTypeDataPipeProducer:
80     case kTypeDataPipeConsumer:
81       // TODO(vtl): Implement.
82       LOG(WARNING) << "Deserialization of dispatcher type " << type
83                    << " not supported";
84       return scoped_refptr<Dispatcher>();
85     case kTypeSharedBuffer:
86       return scoped_refptr<Dispatcher>(SharedBufferDispatcher::Deserialize(
87           channel, source, size, platform_handles));
88     case kTypePlatformHandle:
89       return scoped_refptr<Dispatcher>(PlatformHandleDispatcher::Deserialize(
90           channel, source, size, platform_handles));
91   }
92   LOG(WARNING) << "Unknown dispatcher type " << type;
93   return scoped_refptr<Dispatcher>();
94 }
95
96 MojoResult Dispatcher::Close() {
97   base::AutoLock locker(lock_);
98   if (is_closed_)
99     return MOJO_RESULT_INVALID_ARGUMENT;
100
101   CloseNoLock();
102   return MOJO_RESULT_OK;
103 }
104
105 MojoResult Dispatcher::WriteMessage(
106     UserPointer<const void> bytes,
107     uint32_t num_bytes,
108     std::vector<DispatcherTransport>* transports,
109     MojoWriteMessageFlags flags) {
110   DCHECK(!transports || (transports->size() > 0 &&
111                          transports->size() < kMaxMessageNumHandles));
112
113   base::AutoLock locker(lock_);
114   if (is_closed_)
115     return MOJO_RESULT_INVALID_ARGUMENT;
116
117   return WriteMessageImplNoLock(bytes, num_bytes, transports, flags);
118 }
119
120 MojoResult Dispatcher::ReadMessage(UserPointer<void> bytes,
121                                    UserPointer<uint32_t> num_bytes,
122                                    DispatcherVector* dispatchers,
123                                    uint32_t* num_dispatchers,
124                                    MojoReadMessageFlags flags) {
125   DCHECK(!num_dispatchers || *num_dispatchers == 0 ||
126          (dispatchers && dispatchers->empty()));
127
128   base::AutoLock locker(lock_);
129   if (is_closed_)
130     return MOJO_RESULT_INVALID_ARGUMENT;
131
132   return ReadMessageImplNoLock(
133       bytes, num_bytes, dispatchers, num_dispatchers, flags);
134 }
135
136 MojoResult Dispatcher::WriteData(UserPointer<const void> elements,
137                                  UserPointer<uint32_t> num_bytes,
138                                  MojoWriteDataFlags flags) {
139   base::AutoLock locker(lock_);
140   if (is_closed_)
141     return MOJO_RESULT_INVALID_ARGUMENT;
142
143   return WriteDataImplNoLock(elements, num_bytes, flags);
144 }
145
146 MojoResult Dispatcher::BeginWriteData(UserPointer<void*> buffer,
147                                       UserPointer<uint32_t> buffer_num_bytes,
148                                       MojoWriteDataFlags flags) {
149   base::AutoLock locker(lock_);
150   if (is_closed_)
151     return MOJO_RESULT_INVALID_ARGUMENT;
152
153   return BeginWriteDataImplNoLock(buffer, buffer_num_bytes, flags);
154 }
155
156 MojoResult Dispatcher::EndWriteData(uint32_t num_bytes_written) {
157   base::AutoLock locker(lock_);
158   if (is_closed_)
159     return MOJO_RESULT_INVALID_ARGUMENT;
160
161   return EndWriteDataImplNoLock(num_bytes_written);
162 }
163
164 MojoResult Dispatcher::ReadData(UserPointer<void> elements,
165                                 UserPointer<uint32_t> num_bytes,
166                                 MojoReadDataFlags flags) {
167   base::AutoLock locker(lock_);
168   if (is_closed_)
169     return MOJO_RESULT_INVALID_ARGUMENT;
170
171   return ReadDataImplNoLock(elements, num_bytes, flags);
172 }
173
174 MojoResult Dispatcher::BeginReadData(UserPointer<const void*> buffer,
175                                      UserPointer<uint32_t> buffer_num_bytes,
176                                      MojoReadDataFlags flags) {
177   base::AutoLock locker(lock_);
178   if (is_closed_)
179     return MOJO_RESULT_INVALID_ARGUMENT;
180
181   return BeginReadDataImplNoLock(buffer, buffer_num_bytes, flags);
182 }
183
184 MojoResult Dispatcher::EndReadData(uint32_t num_bytes_read) {
185   base::AutoLock locker(lock_);
186   if (is_closed_)
187     return MOJO_RESULT_INVALID_ARGUMENT;
188
189   return EndReadDataImplNoLock(num_bytes_read);
190 }
191
192 MojoResult Dispatcher::DuplicateBufferHandle(
193     UserPointer<const MojoDuplicateBufferHandleOptions> options,
194     scoped_refptr<Dispatcher>* new_dispatcher) {
195   base::AutoLock locker(lock_);
196   if (is_closed_)
197     return MOJO_RESULT_INVALID_ARGUMENT;
198
199   return DuplicateBufferHandleImplNoLock(options, new_dispatcher);
200 }
201
202 MojoResult Dispatcher::MapBuffer(
203     uint64_t offset,
204     uint64_t num_bytes,
205     MojoMapBufferFlags flags,
206     scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) {
207   base::AutoLock locker(lock_);
208   if (is_closed_)
209     return MOJO_RESULT_INVALID_ARGUMENT;
210
211   return MapBufferImplNoLock(offset, num_bytes, flags, mapping);
212 }
213
214 HandleSignalsState Dispatcher::GetHandleSignalsState() const {
215   base::AutoLock locker(lock_);
216   if (is_closed_)
217     return HandleSignalsState();
218
219   return GetHandleSignalsStateImplNoLock();
220 }
221
222 MojoResult Dispatcher::AddWaiter(Waiter* waiter,
223                                  MojoHandleSignals signals,
224                                  uint32_t context,
225                                  HandleSignalsState* signals_state) {
226   base::AutoLock locker(lock_);
227   if (is_closed_) {
228     if (signals_state)
229       *signals_state = HandleSignalsState();
230     return MOJO_RESULT_INVALID_ARGUMENT;
231   }
232
233   return AddWaiterImplNoLock(waiter, signals, context, signals_state);
234 }
235
236 void Dispatcher::RemoveWaiter(Waiter* waiter,
237                               HandleSignalsState* handle_signals_state) {
238   base::AutoLock locker(lock_);
239   if (is_closed_) {
240     if (handle_signals_state)
241       *handle_signals_state = HandleSignalsState();
242     return;
243   }
244   RemoveWaiterImplNoLock(waiter, handle_signals_state);
245 }
246
247 Dispatcher::Dispatcher() : is_closed_(false) {
248 }
249
250 Dispatcher::~Dispatcher() {
251   // Make sure that |Close()| was called.
252   DCHECK(is_closed_);
253 }
254
255 void Dispatcher::CancelAllWaitersNoLock() {
256   lock_.AssertAcquired();
257   DCHECK(is_closed_);
258   // By default, waiting isn't supported. Only dispatchers that can be waited on
259   // will do something nontrivial.
260 }
261
262 void Dispatcher::CloseImplNoLock() {
263   lock_.AssertAcquired();
264   DCHECK(is_closed_);
265   // This may not need to do anything. Dispatchers should override this to do
266   // any actual close-time cleanup necessary.
267 }
268
269 MojoResult Dispatcher::WriteMessageImplNoLock(
270     UserPointer<const void> /*bytes*/,
271     uint32_t /*num_bytes*/,
272     std::vector<DispatcherTransport>* /*transports*/,
273     MojoWriteMessageFlags /*flags*/) {
274   lock_.AssertAcquired();
275   DCHECK(!is_closed_);
276   // By default, not supported. Only needed for message pipe dispatchers.
277   return MOJO_RESULT_INVALID_ARGUMENT;
278 }
279
280 MojoResult Dispatcher::ReadMessageImplNoLock(
281     UserPointer<void> /*bytes*/,
282     UserPointer<uint32_t> /*num_bytes*/,
283     DispatcherVector* /*dispatchers*/,
284     uint32_t* /*num_dispatchers*/,
285     MojoReadMessageFlags /*flags*/) {
286   lock_.AssertAcquired();
287   DCHECK(!is_closed_);
288   // By default, not supported. Only needed for message pipe dispatchers.
289   return MOJO_RESULT_INVALID_ARGUMENT;
290 }
291
292 MojoResult Dispatcher::WriteDataImplNoLock(UserPointer<const void> /*elements*/,
293                                            UserPointer<uint32_t> /*num_bytes*/,
294                                            MojoWriteDataFlags /*flags*/) {
295   lock_.AssertAcquired();
296   DCHECK(!is_closed_);
297   // By default, not supported. Only needed for data pipe dispatchers.
298   return MOJO_RESULT_INVALID_ARGUMENT;
299 }
300
301 MojoResult Dispatcher::BeginWriteDataImplNoLock(
302     UserPointer<void*> /*buffer*/,
303     UserPointer<uint32_t> /*buffer_num_bytes*/,
304     MojoWriteDataFlags /*flags*/) {
305   lock_.AssertAcquired();
306   DCHECK(!is_closed_);
307   // By default, not supported. Only needed for data pipe dispatchers.
308   return MOJO_RESULT_INVALID_ARGUMENT;
309 }
310
311 MojoResult Dispatcher::EndWriteDataImplNoLock(uint32_t /*num_bytes_written*/) {
312   lock_.AssertAcquired();
313   DCHECK(!is_closed_);
314   // By default, not supported. Only needed for data pipe dispatchers.
315   return MOJO_RESULT_INVALID_ARGUMENT;
316 }
317
318 MojoResult Dispatcher::ReadDataImplNoLock(UserPointer<void> /*elements*/,
319                                           UserPointer<uint32_t> /*num_bytes*/,
320                                           MojoReadDataFlags /*flags*/) {
321   lock_.AssertAcquired();
322   DCHECK(!is_closed_);
323   // By default, not supported. Only needed for data pipe dispatchers.
324   return MOJO_RESULT_INVALID_ARGUMENT;
325 }
326
327 MojoResult Dispatcher::BeginReadDataImplNoLock(
328     UserPointer<const void*> /*buffer*/,
329     UserPointer<uint32_t> /*buffer_num_bytes*/,
330     MojoReadDataFlags /*flags*/) {
331   lock_.AssertAcquired();
332   DCHECK(!is_closed_);
333   // By default, not supported. Only needed for data pipe dispatchers.
334   return MOJO_RESULT_INVALID_ARGUMENT;
335 }
336
337 MojoResult Dispatcher::EndReadDataImplNoLock(uint32_t /*num_bytes_read*/) {
338   lock_.AssertAcquired();
339   DCHECK(!is_closed_);
340   // By default, not supported. Only needed for data pipe dispatchers.
341   return MOJO_RESULT_INVALID_ARGUMENT;
342 }
343
344 MojoResult Dispatcher::DuplicateBufferHandleImplNoLock(
345     UserPointer<const MojoDuplicateBufferHandleOptions> /*options*/,
346     scoped_refptr<Dispatcher>* /*new_dispatcher*/) {
347   lock_.AssertAcquired();
348   DCHECK(!is_closed_);
349   // By default, not supported. Only needed for buffer dispatchers.
350   return MOJO_RESULT_INVALID_ARGUMENT;
351 }
352
353 MojoResult Dispatcher::MapBufferImplNoLock(
354     uint64_t /*offset*/,
355     uint64_t /*num_bytes*/,
356     MojoMapBufferFlags /*flags*/,
357     scoped_ptr<embedder::PlatformSharedBufferMapping>* /*mapping*/) {
358   lock_.AssertAcquired();
359   DCHECK(!is_closed_);
360   // By default, not supported. Only needed for buffer dispatchers.
361   return MOJO_RESULT_INVALID_ARGUMENT;
362 }
363
364 HandleSignalsState Dispatcher::GetHandleSignalsStateImplNoLock() const {
365   lock_.AssertAcquired();
366   DCHECK(!is_closed_);
367   // By default, waiting isn't supported. Only dispatchers that can be waited on
368   // will do something nontrivial.
369   return HandleSignalsState();
370 }
371
372 MojoResult Dispatcher::AddWaiterImplNoLock(Waiter* /*waiter*/,
373                                            MojoHandleSignals /*signals*/,
374                                            uint32_t /*context*/,
375                                            HandleSignalsState* signals_state) {
376   lock_.AssertAcquired();
377   DCHECK(!is_closed_);
378   // By default, waiting isn't supported. Only dispatchers that can be waited on
379   // will do something nontrivial.
380   if (signals_state)
381     *signals_state = HandleSignalsState();
382   return MOJO_RESULT_FAILED_PRECONDITION;
383 }
384
385 void Dispatcher::RemoveWaiterImplNoLock(Waiter* /*waiter*/,
386                                         HandleSignalsState* signals_state) {
387   lock_.AssertAcquired();
388   DCHECK(!is_closed_);
389   // By default, waiting isn't supported. Only dispatchers that can be waited on
390   // will do something nontrivial.
391   if (signals_state)
392     *signals_state = HandleSignalsState();
393 }
394
395 void Dispatcher::StartSerializeImplNoLock(Channel* /*channel*/,
396                                           size_t* max_size,
397                                           size_t* max_platform_handles) {
398   DCHECK(HasOneRef());  // Only one ref => no need to take the lock.
399   DCHECK(!is_closed_);
400   *max_size = 0;
401   *max_platform_handles = 0;
402 }
403
404 bool Dispatcher::EndSerializeAndCloseImplNoLock(
405     Channel* /*channel*/,
406     void* /*destination*/,
407     size_t* /*actual_size*/,
408     embedder::PlatformHandleVector* /*platform_handles*/) {
409   DCHECK(HasOneRef());  // Only one ref => no need to take the lock.
410   DCHECK(is_closed_);
411   // By default, serializing isn't supported, so just close.
412   CloseImplNoLock();
413   return false;
414 }
415
416 bool Dispatcher::IsBusyNoLock() const {
417   lock_.AssertAcquired();
418   DCHECK(!is_closed_);
419   // Most dispatchers support only "atomic" operations, so they are never busy
420   // (in this sense).
421   return false;
422 }
423
424 void Dispatcher::CloseNoLock() {
425   lock_.AssertAcquired();
426   DCHECK(!is_closed_);
427
428   is_closed_ = true;
429   CancelAllWaitersNoLock();
430   CloseImplNoLock();
431 }
432
433 scoped_refptr<Dispatcher>
434 Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() {
435   lock_.AssertAcquired();
436   DCHECK(!is_closed_);
437
438   is_closed_ = true;
439   CancelAllWaitersNoLock();
440   return CreateEquivalentDispatcherAndCloseImplNoLock();
441 }
442
443 void Dispatcher::StartSerialize(Channel* channel,
444                                 size_t* max_size,
445                                 size_t* max_platform_handles) {
446   DCHECK(channel);
447   DCHECK(max_size);
448   DCHECK(max_platform_handles);
449   DCHECK(HasOneRef());  // Only one ref => no need to take the lock.
450   DCHECK(!is_closed_);
451   StartSerializeImplNoLock(channel, max_size, max_platform_handles);
452 }
453
454 bool Dispatcher::EndSerializeAndClose(
455     Channel* channel,
456     void* destination,
457     size_t* actual_size,
458     embedder::PlatformHandleVector* platform_handles) {
459   DCHECK(channel);
460   DCHECK(actual_size);
461   DCHECK(HasOneRef());  // Only one ref => no need to take the lock.
462   DCHECK(!is_closed_);
463
464   // Like other |...Close()| methods, we mark ourselves as closed before calling
465   // the impl. But there's no need to cancel waiters: we shouldn't have any (and
466   // shouldn't be in |Core|'s handle table.
467   is_closed_ = true;
468
469 #if !defined(NDEBUG)
470   // See the comment above |EndSerializeAndCloseImplNoLock()|. In brief: Locking
471   // isn't actually needed, but we need to satisfy assertions (which we don't
472   // want to remove or weaken).
473   base::AutoLock locker(lock_);
474 #endif
475
476   return EndSerializeAndCloseImplNoLock(
477       channel, destination, actual_size, platform_handles);
478 }
479
480 // DispatcherTransport ---------------------------------------------------------
481
482 void DispatcherTransport::End() {
483   DCHECK(dispatcher_);
484   dispatcher_->lock_.Release();
485   dispatcher_ = NULL;
486 }
487
488 }  // namespace system
489 }  // namespace mojo