OLD | NEW |
| (Empty) |
1 // Copyright 2014 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/edk/embedder/embedder.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/location.h" | |
9 #include "base/logging.h" | |
10 #include "base/memory/scoped_ptr.h" | |
11 #include "base/message_loop/message_loop_proxy.h" | |
12 #include "mojo/edk/embedder/embedder_internal.h" | |
13 #include "mojo/edk/embedder/platform_support.h" | |
14 #include "mojo/edk/system/channel.h" | |
15 #include "mojo/edk/system/channel_endpoint.h" | |
16 #include "mojo/edk/system/channel_manager.h" | |
17 #include "mojo/edk/system/configuration.h" | |
18 #include "mojo/edk/system/core.h" | |
19 #include "mojo/edk/system/message_pipe_dispatcher.h" | |
20 #include "mojo/edk/system/platform_handle_dispatcher.h" | |
21 #include "mojo/edk/system/raw_channel.h" | |
22 | |
23 namespace mojo { | |
24 namespace embedder { | |
25 | |
26 namespace { | |
27 | |
28 // Helper for |CreateChannel...()|. Returns 0 on failure. Called on the channel | |
29 // creation thread. | |
30 system::ChannelId MakeChannel( | |
31 ScopedPlatformHandle platform_handle, | |
32 scoped_refptr<system::ChannelEndpoint> channel_endpoint) { | |
33 DCHECK(platform_handle.is_valid()); | |
34 | |
35 // Create and initialize a |system::Channel|. | |
36 DCHECK(internal::g_core); | |
37 scoped_refptr<system::Channel> channel = | |
38 new system::Channel(internal::g_core->platform_support()); | |
39 channel->Init(system::RawChannel::Create(platform_handle.Pass())); | |
40 channel->SetBootstrapEndpoint(channel_endpoint); | |
41 | |
42 DCHECK(internal::g_channel_manager); | |
43 return internal::g_channel_manager->AddChannel( | |
44 channel, base::MessageLoopProxy::current()); | |
45 } | |
46 | |
47 // Helper for |CreateChannel()|. Called on the channel creation thread. | |
48 void CreateChannelHelper( | |
49 ScopedPlatformHandle platform_handle, | |
50 scoped_ptr<ChannelInfo> channel_info, | |
51 scoped_refptr<system::ChannelEndpoint> channel_endpoint, | |
52 DidCreateChannelCallback callback, | |
53 scoped_refptr<base::TaskRunner> callback_thread_task_runner) { | |
54 channel_info->channel_id = | |
55 MakeChannel(platform_handle.Pass(), channel_endpoint); | |
56 | |
57 // Hand the channel back to the embedder. | |
58 if (callback_thread_task_runner) { | |
59 callback_thread_task_runner->PostTask( | |
60 FROM_HERE, base::Bind(callback, channel_info.release())); | |
61 } else { | |
62 callback.Run(channel_info.release()); | |
63 } | |
64 } | |
65 | |
66 } // namespace | |
67 | |
68 namespace internal { | |
69 | |
70 // Declared in embedder_internal.h. | |
71 system::Core* g_core = nullptr; | |
72 system::ChannelManager* g_channel_manager = nullptr; | |
73 | |
74 } // namespace internal | |
75 | |
76 void Init(scoped_ptr<PlatformSupport> platform_support) { | |
77 DCHECK(!internal::g_core); | |
78 internal::g_core = new system::Core(platform_support.Pass()); | |
79 DCHECK(!internal::g_channel_manager); | |
80 internal::g_channel_manager = new system::ChannelManager(); | |
81 } | |
82 | |
83 Configuration* GetConfiguration() { | |
84 return system::GetMutableConfiguration(); | |
85 } | |
86 | |
87 // TODO(vtl): Write tests for this. | |
88 ScopedMessagePipeHandle CreateChannelOnIOThread( | |
89 ScopedPlatformHandle platform_handle, | |
90 ChannelInfo** channel_info) { | |
91 DCHECK(platform_handle.is_valid()); | |
92 DCHECK(channel_info); | |
93 | |
94 scoped_refptr<system::ChannelEndpoint> channel_endpoint; | |
95 scoped_refptr<system::MessagePipeDispatcher> dispatcher = | |
96 system::MessagePipeDispatcher::CreateRemoteMessagePipe(&channel_endpoint); | |
97 | |
98 DCHECK(internal::g_core); | |
99 ScopedMessagePipeHandle rv( | |
100 MessagePipeHandle(internal::g_core->AddDispatcher(dispatcher))); | |
101 | |
102 *channel_info = | |
103 new ChannelInfo(MakeChannel(platform_handle.Pass(), channel_endpoint)); | |
104 | |
105 return rv.Pass(); | |
106 } | |
107 | |
108 ScopedMessagePipeHandle CreateChannel( | |
109 ScopedPlatformHandle platform_handle, | |
110 scoped_refptr<base::TaskRunner> io_thread_task_runner, | |
111 DidCreateChannelCallback callback, | |
112 scoped_refptr<base::TaskRunner> callback_thread_task_runner) { | |
113 DCHECK(platform_handle.is_valid()); | |
114 DCHECK(io_thread_task_runner); | |
115 DCHECK(!callback.is_null()); | |
116 | |
117 scoped_refptr<system::ChannelEndpoint> channel_endpoint; | |
118 scoped_refptr<system::MessagePipeDispatcher> dispatcher = | |
119 system::MessagePipeDispatcher::CreateRemoteMessagePipe(&channel_endpoint); | |
120 | |
121 DCHECK(internal::g_core); | |
122 ScopedMessagePipeHandle rv( | |
123 MessagePipeHandle(internal::g_core->AddDispatcher(dispatcher))); | |
124 | |
125 // We'll have to set |channel_info->channel_id| on the I/O thread. | |
126 scoped_ptr<ChannelInfo> channel_info(new ChannelInfo()); | |
127 | |
128 if (rv.is_valid()) { | |
129 io_thread_task_runner->PostTask( | |
130 FROM_HERE, | |
131 base::Bind(&CreateChannelHelper, base::Passed(&platform_handle), | |
132 base::Passed(&channel_info), channel_endpoint, callback, | |
133 callback_thread_task_runner)); | |
134 } else { | |
135 (callback_thread_task_runner.get() ? callback_thread_task_runner | |
136 : io_thread_task_runner) | |
137 ->PostTask(FROM_HERE, base::Bind(callback, channel_info.release())); | |
138 } | |
139 | |
140 return rv.Pass(); | |
141 } | |
142 | |
143 // TODO(vtl): Write tests for this. | |
144 void DestroyChannel(ChannelInfo* channel_info) { | |
145 DCHECK(channel_info); | |
146 DCHECK(channel_info->channel_id); | |
147 DCHECK(internal::g_channel_manager); | |
148 // This will destroy the channel synchronously if called from the channel | |
149 // thread. | |
150 internal::g_channel_manager->ShutdownChannel(channel_info->channel_id); | |
151 delete channel_info; | |
152 } | |
153 | |
154 void WillDestroyChannelSoon(ChannelInfo* channel_info) { | |
155 DCHECK(channel_info); | |
156 DCHECK(internal::g_channel_manager); | |
157 internal::g_channel_manager->WillShutdownChannel(channel_info->channel_id); | |
158 } | |
159 | |
160 MojoResult CreatePlatformHandleWrapper( | |
161 ScopedPlatformHandle platform_handle, | |
162 MojoHandle* platform_handle_wrapper_handle) { | |
163 DCHECK(platform_handle_wrapper_handle); | |
164 | |
165 scoped_refptr<system::Dispatcher> dispatcher( | |
166 new system::PlatformHandleDispatcher(platform_handle.Pass())); | |
167 | |
168 DCHECK(internal::g_core); | |
169 MojoHandle h = internal::g_core->AddDispatcher(dispatcher); | |
170 if (h == MOJO_HANDLE_INVALID) { | |
171 LOG(ERROR) << "Handle table full"; | |
172 dispatcher->Close(); | |
173 return MOJO_RESULT_RESOURCE_EXHAUSTED; | |
174 } | |
175 | |
176 *platform_handle_wrapper_handle = h; | |
177 return MOJO_RESULT_OK; | |
178 } | |
179 | |
180 MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle, | |
181 ScopedPlatformHandle* platform_handle) { | |
182 DCHECK(platform_handle); | |
183 | |
184 DCHECK(internal::g_core); | |
185 scoped_refptr<system::Dispatcher> dispatcher( | |
186 internal::g_core->GetDispatcher(platform_handle_wrapper_handle)); | |
187 if (!dispatcher) | |
188 return MOJO_RESULT_INVALID_ARGUMENT; | |
189 | |
190 if (dispatcher->GetType() != system::Dispatcher::kTypePlatformHandle) | |
191 return MOJO_RESULT_INVALID_ARGUMENT; | |
192 | |
193 *platform_handle = | |
194 static_cast<system::PlatformHandleDispatcher*>(dispatcher.get()) | |
195 ->PassPlatformHandle() | |
196 .Pass(); | |
197 return MOJO_RESULT_OK; | |
198 } | |
199 | |
200 MojoResult AsyncWait(MojoHandle handle, | |
201 MojoHandleSignals signals, | |
202 base::Callback<void(MojoResult)> callback) { | |
203 return internal::g_core->AsyncWait(handle, signals, callback); | |
204 } | |
205 | |
206 } // namespace embedder | |
207 } // namespace mojo | |
OLD | NEW |