Add an extension override bubble and warning box for proxy extensions. (2nd attempt...
[chromium-blink-merge.git] / mojo / system / dispatcher.cc
blob98cb8fb8b24677d507a624e6487f6502e518f844
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.
5 #include "mojo/system/dispatcher.h"
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"
13 namespace mojo {
14 namespace system {
16 namespace test {
18 // TODO(vtl): Maybe this should be defined in a test-only file instead.
19 DispatcherTransport DispatcherTryStartTransport(
20 Dispatcher* dispatcher) {
21 return Dispatcher::HandleTableAccess::TryStartTransport(dispatcher);
24 } // namespace test
26 // Dispatcher ------------------------------------------------------------------
28 // static
29 DispatcherTransport Dispatcher::HandleTableAccess::TryStartTransport(
30 Dispatcher* dispatcher) {
31 DCHECK(dispatcher);
33 if (!dispatcher->lock_.Try())
34 return DispatcherTransport();
36 // We shouldn't race with things that close dispatchers, since closing can
37 // only take place either under |handle_table_lock_| or when the handle is
38 // marked as busy.
39 DCHECK(!dispatcher->is_closed_);
41 return DispatcherTransport(dispatcher);
44 // static
45 void Dispatcher::TransportDataAccess::StartSerialize(
46 Dispatcher* dispatcher,
47 Channel* channel,
48 size_t* max_size,
49 size_t* max_platform_handles) {
50 DCHECK(dispatcher);
51 dispatcher->StartSerialize(channel, max_size, max_platform_handles);
54 // static
55 bool Dispatcher::TransportDataAccess::EndSerializeAndClose(
56 Dispatcher* dispatcher,
57 Channel* channel,
58 void* destination,
59 size_t* actual_size,
60 embedder::PlatformHandleVector* platform_handles) {
61 DCHECK(dispatcher);
62 return dispatcher->EndSerializeAndClose(channel, destination, actual_size,
63 platform_handles);
66 // static
67 scoped_refptr<Dispatcher> Dispatcher::TransportDataAccess::Deserialize(
68 Channel* channel,
69 int32_t type,
70 const void* source,
71 size_t size,
72 embedder::PlatformHandleVector* platform_handles) {
73 switch (static_cast<int32_t>(type)) {
74 case kTypeUnknown:
75 DVLOG(2) << "Deserializing invalid handle";
76 return scoped_refptr<Dispatcher>();
77 case kTypeMessagePipe:
78 return scoped_refptr<Dispatcher>(
79 MessagePipeDispatcher::Deserialize(channel, source, size));
80 case kTypeDataPipeProducer:
81 case kTypeDataPipeConsumer:
82 // TODO(vtl): Implement.
83 LOG(WARNING) << "Deserialization of dispatcher type " << type
84 << " not supported";
85 return scoped_refptr<Dispatcher>();
86 case kTypeSharedBuffer:
87 return scoped_refptr<Dispatcher>(
88 SharedBufferDispatcher::Deserialize(channel, source, size,
89 platform_handles));
90 case kTypePlatformHandle:
91 return scoped_refptr<Dispatcher>(
92 PlatformHandleDispatcher::Deserialize(channel, source, size,
93 platform_handles));
95 LOG(WARNING) << "Unknown dispatcher type " << type;
96 return scoped_refptr<Dispatcher>();
99 MojoResult Dispatcher::Close() {
100 base::AutoLock locker(lock_);
101 if (is_closed_)
102 return MOJO_RESULT_INVALID_ARGUMENT;
104 CloseNoLock();
105 return MOJO_RESULT_OK;
108 MojoResult Dispatcher::WriteMessage(
109 const void* bytes,
110 uint32_t num_bytes,
111 std::vector<DispatcherTransport>* transports,
112 MojoWriteMessageFlags flags) {
113 DCHECK(!transports || (transports->size() > 0 &&
114 transports->size() < kMaxMessageNumHandles));
116 base::AutoLock locker(lock_);
117 if (is_closed_)
118 return MOJO_RESULT_INVALID_ARGUMENT;
120 return WriteMessageImplNoLock(bytes, num_bytes, transports, flags);
123 MojoResult Dispatcher::ReadMessage(void* bytes,
124 uint32_t* num_bytes,
125 DispatcherVector* dispatchers,
126 uint32_t* num_dispatchers,
127 MojoReadMessageFlags flags) {
128 DCHECK(!num_dispatchers || *num_dispatchers == 0 ||
129 (dispatchers && dispatchers->empty()));
131 base::AutoLock locker(lock_);
132 if (is_closed_)
133 return MOJO_RESULT_INVALID_ARGUMENT;
135 return ReadMessageImplNoLock(bytes, num_bytes, dispatchers, num_dispatchers,
136 flags);
139 MojoResult Dispatcher::WriteData(const void* elements,
140 uint32_t* num_bytes,
141 MojoWriteDataFlags flags) {
142 base::AutoLock locker(lock_);
143 if (is_closed_)
144 return MOJO_RESULT_INVALID_ARGUMENT;
146 return WriteDataImplNoLock(elements, num_bytes, flags);
149 MojoResult Dispatcher::BeginWriteData(void** buffer,
150 uint32_t* buffer_num_bytes,
151 MojoWriteDataFlags flags) {
152 base::AutoLock locker(lock_);
153 if (is_closed_)
154 return MOJO_RESULT_INVALID_ARGUMENT;
156 return BeginWriteDataImplNoLock(buffer, buffer_num_bytes, flags);
159 MojoResult Dispatcher::EndWriteData(uint32_t num_bytes_written) {
160 base::AutoLock locker(lock_);
161 if (is_closed_)
162 return MOJO_RESULT_INVALID_ARGUMENT;
164 return EndWriteDataImplNoLock(num_bytes_written);
167 MojoResult Dispatcher::ReadData(void* elements,
168 uint32_t* num_bytes,
169 MojoReadDataFlags flags) {
170 base::AutoLock locker(lock_);
171 if (is_closed_)
172 return MOJO_RESULT_INVALID_ARGUMENT;
174 return ReadDataImplNoLock(elements, num_bytes, flags);
177 MojoResult Dispatcher::BeginReadData(const void** buffer,
178 uint32_t* buffer_num_bytes,
179 MojoReadDataFlags flags) {
180 base::AutoLock locker(lock_);
181 if (is_closed_)
182 return MOJO_RESULT_INVALID_ARGUMENT;
184 return BeginReadDataImplNoLock(buffer, buffer_num_bytes, flags);
187 MojoResult Dispatcher::EndReadData(uint32_t num_bytes_read) {
188 base::AutoLock locker(lock_);
189 if (is_closed_)
190 return MOJO_RESULT_INVALID_ARGUMENT;
192 return EndReadDataImplNoLock(num_bytes_read);
195 MojoResult Dispatcher::DuplicateBufferHandle(
196 const MojoDuplicateBufferHandleOptions* options,
197 scoped_refptr<Dispatcher>* new_dispatcher) {
198 base::AutoLock locker(lock_);
199 if (is_closed_)
200 return MOJO_RESULT_INVALID_ARGUMENT;
202 return DuplicateBufferHandleImplNoLock(options, new_dispatcher);
205 MojoResult Dispatcher::MapBuffer(
206 uint64_t offset,
207 uint64_t num_bytes,
208 MojoMapBufferFlags flags,
209 scoped_ptr<RawSharedBufferMapping>* mapping) {
210 base::AutoLock locker(lock_);
211 if (is_closed_)
212 return MOJO_RESULT_INVALID_ARGUMENT;
214 return MapBufferImplNoLock(offset, num_bytes, flags, mapping);
217 MojoResult Dispatcher::AddWaiter(Waiter* waiter,
218 MojoWaitFlags flags,
219 MojoResult wake_result) {
220 DCHECK_GE(wake_result, 0);
222 base::AutoLock locker(lock_);
223 if (is_closed_)
224 return MOJO_RESULT_INVALID_ARGUMENT;
226 return AddWaiterImplNoLock(waiter, flags, wake_result);
229 void Dispatcher::RemoveWaiter(Waiter* waiter) {
230 base::AutoLock locker(lock_);
231 if (is_closed_)
232 return;
233 RemoveWaiterImplNoLock(waiter);
236 Dispatcher::Dispatcher()
237 : is_closed_(false) {
240 Dispatcher::~Dispatcher() {
241 // Make sure that |Close()| was called.
242 DCHECK(is_closed_);
245 void Dispatcher::CancelAllWaitersNoLock() {
246 lock_.AssertAcquired();
247 DCHECK(is_closed_);
248 // By default, waiting isn't supported. Only dispatchers that can be waited on
249 // will do something nontrivial.
252 void Dispatcher::CloseImplNoLock() {
253 lock_.AssertAcquired();
254 DCHECK(is_closed_);
255 // This may not need to do anything. Dispatchers should override this to do
256 // any actual close-time cleanup necessary.
259 MojoResult Dispatcher::WriteMessageImplNoLock(
260 const void* /*bytes*/,
261 uint32_t /*num_bytes*/,
262 std::vector<DispatcherTransport>* /*transports*/,
263 MojoWriteMessageFlags /*flags*/) {
264 lock_.AssertAcquired();
265 DCHECK(!is_closed_);
266 // By default, not supported. Only needed for message pipe dispatchers.
267 return MOJO_RESULT_INVALID_ARGUMENT;
270 MojoResult Dispatcher::ReadMessageImplNoLock(void* /*bytes*/,
271 uint32_t* /*num_bytes*/,
272 DispatcherVector* /*dispatchers*/,
273 uint32_t* /*num_dispatchers*/,
274 MojoReadMessageFlags /*flags*/) {
275 lock_.AssertAcquired();
276 DCHECK(!is_closed_);
277 // By default, not supported. Only needed for message pipe dispatchers.
278 return MOJO_RESULT_INVALID_ARGUMENT;
281 MojoResult Dispatcher::WriteDataImplNoLock(const void* /*elements*/,
282 uint32_t* /*num_bytes*/,
283 MojoWriteDataFlags /*flags*/) {
284 lock_.AssertAcquired();
285 DCHECK(!is_closed_);
286 // By default, not supported. Only needed for data pipe dispatchers.
287 return MOJO_RESULT_INVALID_ARGUMENT;
290 MojoResult Dispatcher::BeginWriteDataImplNoLock(void** /*buffer*/,
291 uint32_t* /*buffer_num_bytes*/,
292 MojoWriteDataFlags /*flags*/) {
293 lock_.AssertAcquired();
294 DCHECK(!is_closed_);
295 // By default, not supported. Only needed for data pipe dispatchers.
296 return MOJO_RESULT_INVALID_ARGUMENT;
299 MojoResult Dispatcher::EndWriteDataImplNoLock(uint32_t /*num_bytes_written*/) {
300 lock_.AssertAcquired();
301 DCHECK(!is_closed_);
302 // By default, not supported. Only needed for data pipe dispatchers.
303 return MOJO_RESULT_INVALID_ARGUMENT;
306 MojoResult Dispatcher::ReadDataImplNoLock(void* /*elements*/,
307 uint32_t* /*num_bytes*/,
308 MojoReadDataFlags /*flags*/) {
309 lock_.AssertAcquired();
310 DCHECK(!is_closed_);
311 // By default, not supported. Only needed for data pipe dispatchers.
312 return MOJO_RESULT_INVALID_ARGUMENT;
315 MojoResult Dispatcher::BeginReadDataImplNoLock(const void** /*buffer*/,
316 uint32_t* /*buffer_num_bytes*/,
317 MojoReadDataFlags /*flags*/) {
318 lock_.AssertAcquired();
319 DCHECK(!is_closed_);
320 // By default, not supported. Only needed for data pipe dispatchers.
321 return MOJO_RESULT_INVALID_ARGUMENT;
324 MojoResult Dispatcher::EndReadDataImplNoLock(uint32_t /*num_bytes_read*/) {
325 lock_.AssertAcquired();
326 DCHECK(!is_closed_);
327 // By default, not supported. Only needed for data pipe dispatchers.
328 return MOJO_RESULT_INVALID_ARGUMENT;
331 MojoResult Dispatcher::DuplicateBufferHandleImplNoLock(
332 const MojoDuplicateBufferHandleOptions* /*options*/,
333 scoped_refptr<Dispatcher>* /*new_dispatcher*/) {
334 lock_.AssertAcquired();
335 DCHECK(!is_closed_);
336 // By default, not supported. Only needed for buffer dispatchers.
337 return MOJO_RESULT_INVALID_ARGUMENT;
340 MojoResult Dispatcher::MapBufferImplNoLock(
341 uint64_t /*offset*/,
342 uint64_t /*num_bytes*/,
343 MojoMapBufferFlags /*flags*/,
344 scoped_ptr<RawSharedBufferMapping>* /*mapping*/) {
345 lock_.AssertAcquired();
346 DCHECK(!is_closed_);
347 // By default, not supported. Only needed for buffer dispatchers.
348 return MOJO_RESULT_INVALID_ARGUMENT;
351 MojoResult Dispatcher::AddWaiterImplNoLock(Waiter* /*waiter*/,
352 MojoWaitFlags /*flags*/,
353 MojoResult /*wake_result*/) {
354 lock_.AssertAcquired();
355 DCHECK(!is_closed_);
356 // By default, waiting isn't supported. Only dispatchers that can be waited on
357 // will do something nontrivial.
358 return MOJO_RESULT_FAILED_PRECONDITION;
361 void Dispatcher::RemoveWaiterImplNoLock(Waiter* /*waiter*/) {
362 lock_.AssertAcquired();
363 DCHECK(!is_closed_);
364 // By default, waiting isn't supported. Only dispatchers that can be waited on
365 // will do something nontrivial.
368 void Dispatcher::StartSerializeImplNoLock(Channel* /*channel*/,
369 size_t* max_size,
370 size_t* max_platform_handles) {
371 DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
372 DCHECK(!is_closed_);
373 *max_size = 0;
374 *max_platform_handles = 0;
377 bool Dispatcher::EndSerializeAndCloseImplNoLock(
378 Channel* /*channel*/,
379 void* /*destination*/,
380 size_t* /*actual_size*/,
381 embedder::PlatformHandleVector* /*platform_handles*/) {
382 DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
383 DCHECK(is_closed_);
384 // By default, serializing isn't supported, so just close.
385 CloseImplNoLock();
386 return false;
389 bool Dispatcher::IsBusyNoLock() const {
390 lock_.AssertAcquired();
391 DCHECK(!is_closed_);
392 // Most dispatchers support only "atomic" operations, so they are never busy
393 // (in this sense).
394 return false;
397 void Dispatcher::CloseNoLock() {
398 lock_.AssertAcquired();
399 DCHECK(!is_closed_);
401 is_closed_ = true;
402 CancelAllWaitersNoLock();
403 CloseImplNoLock();
406 scoped_refptr<Dispatcher>
407 Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() {
408 lock_.AssertAcquired();
409 DCHECK(!is_closed_);
411 is_closed_ = true;
412 CancelAllWaitersNoLock();
413 return CreateEquivalentDispatcherAndCloseImplNoLock();
416 void Dispatcher::StartSerialize(Channel* channel,
417 size_t* max_size,
418 size_t* max_platform_handles) {
419 DCHECK(channel);
420 DCHECK(max_size);
421 DCHECK(max_platform_handles);
422 DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
423 DCHECK(!is_closed_);
424 StartSerializeImplNoLock(channel, max_size, max_platform_handles);
427 bool Dispatcher::EndSerializeAndClose(
428 Channel* channel,
429 void* destination,
430 size_t* actual_size,
431 embedder::PlatformHandleVector* platform_handles) {
432 DCHECK(channel);
433 DCHECK(actual_size);
434 DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
435 DCHECK(!is_closed_);
437 // Like other |...Close()| methods, we mark ourselves as closed before calling
438 // the impl.
439 is_closed_ = true;
440 // No need to cancel waiters: we shouldn't have any (and shouldn't be in
441 // |Core|'s handle table.
443 #if !defined(NDEBUG)
444 // See the comment above |EndSerializeAndCloseImplNoLock()|. In brief: Locking
445 // isn't actually needed, but we need to satisfy assertions (which we don't
446 // want to remove or weaken).
447 base::AutoLock locker(lock_);
448 #endif
450 return EndSerializeAndCloseImplNoLock(channel, destination, actual_size,
451 platform_handles);
454 // DispatcherTransport ---------------------------------------------------------
456 void DispatcherTransport::End() {
457 DCHECK(dispatcher_);
458 dispatcher_->lock_.Release();
459 dispatcher_ = NULL;
462 } // namespace system
463 } // namespace mojo