| 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 |