Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / mojo / public / cpp / bindings / lib / connector.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/public/cpp/bindings/lib/connector.h"
6
7 #include <assert.h>
8 #include <stdlib.h>
9
10 #include "mojo/public/cpp/bindings/error_handler.h"
11
12 namespace mojo {
13 namespace internal {
14
15 // ----------------------------------------------------------------------------
16
17 Connector::Connector(ScopedMessagePipeHandle message_pipe,
18                      MojoAsyncWaiter* waiter)
19     : error_handler_(NULL),
20       waiter_(waiter),
21       message_pipe_(message_pipe.Pass()),
22       incoming_receiver_(NULL),
23       async_wait_id_(0),
24       error_(false),
25       drop_writes_(false),
26       enforce_errors_from_incoming_receiver_(true) {
27   // Even though we don't have an incoming receiver, we still want to monitor
28   // the message pipe to know if is closed or encounters an error.
29   WaitToReadMore();
30 }
31
32 Connector::~Connector() {
33   if (async_wait_id_)
34     waiter_->CancelWait(waiter_, async_wait_id_);
35 }
36
37 void Connector::CloseMessagePipe() {
38   Close(message_pipe_.Pass());
39 }
40
41 ScopedMessagePipeHandle Connector::ReleaseMessagePipe() {
42   if (async_wait_id_) {
43     waiter_->CancelWait(waiter_, async_wait_id_);
44     async_wait_id_ = 0;
45   }
46   return message_pipe_.Pass();
47 }
48
49 bool Connector::Accept(Message* message) {
50   assert(message_pipe_.is_valid());
51
52   if (error_)
53     return false;
54
55   if (drop_writes_)
56     return true;
57
58   MojoResult rv = WriteMessageRaw(
59       message_pipe_.get(),
60       message->data(),
61       message->data_num_bytes(),
62       message->mutable_handles()->empty() ? NULL :
63           reinterpret_cast<const MojoHandle*>(
64               &message->mutable_handles()->front()),
65       static_cast<uint32_t>(message->mutable_handles()->size()),
66       MOJO_WRITE_MESSAGE_FLAG_NONE);
67
68   switch (rv) {
69     case MOJO_RESULT_OK:
70       // The handles were successfully transferred, so we don't need the message
71       // to track their lifetime any longer.
72       message->mutable_handles()->clear();
73       break;
74     case MOJO_RESULT_FAILED_PRECONDITION:
75       // There's no point in continuing to write to this pipe since the other
76       // end is gone. Avoid writing any future messages. Hide write failures
77       // from the caller since we'd like them to continue consuming any backlog
78       // of incoming messages before regarding the message pipe as closed.
79       drop_writes_ = true;
80       break;
81     default:
82       // This particular write was rejected, presumably because of bad input.
83       // The pipe is not necessarily in a bad state.
84       return false;
85   }
86   return true;
87 }
88
89 bool Connector::AcceptWithResponder(Message* message,
90                                     MessageReceiver* responder) {
91   // TODO(darin): Implement this!
92   assert(false);
93   return false;
94 }
95
96 // static
97 void Connector::CallOnHandleReady(void* closure, MojoResult result) {
98   Connector* self = static_cast<Connector*>(closure);
99   self->OnHandleReady(result);
100 }
101
102 void Connector::OnHandleReady(MojoResult result) {
103   async_wait_id_ = 0;
104
105   if (result == MOJO_RESULT_OK) {
106     ReadMore();
107   } else {
108     error_ = true;
109   }
110
111   if (error_ && error_handler_)
112     error_handler_->OnConnectionError();
113 }
114
115 void Connector::WaitToReadMore() {
116   async_wait_id_ = waiter_->AsyncWait(waiter_,
117                                       message_pipe_.get().value(),
118                                       MOJO_WAIT_FLAG_READABLE,
119                                       MOJO_DEADLINE_INDEFINITE,
120                                       &Connector::CallOnHandleReady,
121                                       this);
122 }
123
124 void Connector::ReadMore() {
125   while (true) {
126     bool receiver_result = false;
127     MojoResult rv =  ReadAndDispatchMessage(
128         message_pipe_.get(), incoming_receiver_, &receiver_result);
129     if (rv == MOJO_RESULT_SHOULD_WAIT) {
130       WaitToReadMore();
131       break;
132     }
133     if (rv != MOJO_RESULT_OK ||
134         (enforce_errors_from_incoming_receiver_ && !receiver_result)) {
135       error_ = true;
136       break;
137     }
138   }
139 }
140
141 }  // namespace internal
142 }  // namespace mojo