| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "mojo/edk/embedder/embedder.h" | 5 #include "mojo/edk/embedder/embedder.h" |
| 6 | 6 |
| 7 #include <stddef.h> | |
| 8 #include <stdint.h> | 7 #include <stdint.h> |
| 9 | 8 |
| 10 #include <utility> | |
| 11 | |
| 12 #include "base/atomicops.h" | |
| 13 #include "base/bind.h" | 9 #include "base/bind.h" |
| 14 #include "base/bind_helpers.h" | |
| 15 #include "base/command_line.h" | |
| 16 #include "base/location.h" | 10 #include "base/location.h" |
| 17 #include "base/logging.h" | 11 #include "base/logging.h" |
| 18 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/ref_counted.h" |
| 19 #include "base/message_loop/message_loop.h" | 13 #include "base/strings/string_number_conversions.h" |
| 20 #include "base/task_runner.h" | 14 #include "base/task_runner.h" |
| 15 #include "base/thread_task_runner_handle.h" |
| 16 #include "crypto/random.h" |
| 21 #include "mojo/edk/embedder/embedder_internal.h" | 17 #include "mojo/edk/embedder/embedder_internal.h" |
| 22 #include "mojo/edk/embedder/platform_channel_pair.h" | 18 #include "mojo/edk/embedder/platform_channel_pair.h" |
| 23 #include "mojo/edk/embedder/process_delegate.h" | 19 #include "mojo/edk/embedder/process_delegate.h" |
| 24 #include "mojo/edk/embedder/simple_platform_support.h" | 20 #include "mojo/edk/embedder/simple_platform_support.h" |
| 25 #include "mojo/edk/system/broker_state.h" | |
| 26 #include "mojo/edk/system/child_broker.h" | |
| 27 #include "mojo/edk/system/child_broker_host.h" | |
| 28 #include "mojo/edk/system/configuration.h" | |
| 29 #include "mojo/edk/system/core.h" | 21 #include "mojo/edk/system/core.h" |
| 30 #include "mojo/edk/system/message_pipe_dispatcher.h" | |
| 31 #include "mojo/edk/system/platform_handle_dispatcher.h" | |
| 32 | 22 |
| 33 namespace mojo { | 23 namespace mojo { |
| 34 namespace edk { | 24 namespace edk { |
| 35 | 25 |
| 26 class Core; |
| 27 class PlatformSupport; |
| 28 |
| 36 namespace internal { | 29 namespace internal { |
| 37 | 30 |
| 38 // Declared in embedder_internal.h. | 31 Core* g_core; |
| 39 Broker* g_broker = nullptr; | 32 base::TaskRunner* g_io_thread_task_runner; |
| 40 PlatformSupport* g_platform_support = nullptr; | 33 PlatformSupport* g_platform_support; |
| 41 Core* g_core = nullptr; | 34 ProcessDelegate* g_process_delegate; |
| 42 | 35 |
| 43 ProcessDelegate* g_process_delegate; | 36 // This is used to help negotiate message pipe connections over arbitrary |
| 44 base::TaskRunner* g_io_thread_task_runner = nullptr; | 37 // platform channels. The embedder needs to know which end of the pipe it's on |
| 38 // so it can do the right thing. |
| 39 // |
| 40 // TODO: Remove this when people stop using mojo::embedder::CreateChannel() |
| 41 // and thus mojo::edk::CreateMessagePipe(ScopedPlatformHandle). |
| 42 bool g_is_parent_process = true; |
| 45 | 43 |
| 46 Core* GetCore() { | 44 Core* GetCore() { return g_core; } |
| 47 return g_core; | |
| 48 } | |
| 49 | 45 |
| 50 } // namespace internal | 46 } // namespace internal |
| 51 | 47 |
| 52 void SetMaxMessageSize(size_t bytes) { | 48 void SetMaxMessageSize(size_t bytes) { |
| 53 GetMutableConfiguration()->max_message_num_bytes = bytes; | |
| 54 } | 49 } |
| 55 | 50 |
| 56 void PreInitializeParentProcess() { | 51 void PreInitializeParentProcess() { |
| 57 BrokerState::GetInstance(); | |
| 58 } | 52 } |
| 59 | 53 |
| 60 void PreInitializeChildProcess() { | 54 void PreInitializeChildProcess() { |
| 61 ChildBroker::GetInstance(); | 55 internal::g_is_parent_process = false; |
| 62 } | 56 } |
| 63 | 57 |
| 64 ScopedPlatformHandle ChildProcessLaunched(base::ProcessHandle child_process) { | 58 ScopedPlatformHandle ChildProcessLaunched(base::ProcessHandle child_process) { |
| 65 PlatformChannelPair token_channel; | 59 PlatformChannelPair channel; |
| 66 new ChildBrokerHost(child_process, token_channel.PassServerHandle()); | 60 ChildProcessLaunched(child_process, channel.PassServerHandle()); |
| 67 return token_channel.PassClientHandle(); | 61 return channel.PassClientHandle(); |
| 68 } | 62 } |
| 69 | 63 |
| 70 void ChildProcessLaunched(base::ProcessHandle child_process, | 64 void ChildProcessLaunched(base::ProcessHandle child_process, |
| 71 ScopedPlatformHandle server_pipe) { | 65 ScopedPlatformHandle server_pipe) { |
| 72 new ChildBrokerHost(child_process, std::move(server_pipe)); | 66 CHECK(internal::g_core); |
| 67 internal::g_core->AddChild(child_process, std::move(server_pipe)); |
| 73 } | 68 } |
| 74 | 69 |
| 75 void SetParentPipeHandle(ScopedPlatformHandle pipe) { | 70 void SetParentPipeHandle(ScopedPlatformHandle pipe) { |
| 76 ChildBroker::GetInstance()->SetChildBrokerHostHandle(std::move(pipe)); | 71 CHECK(internal::g_core); |
| 72 internal::g_is_parent_process = false; |
| 73 internal::g_core->InitChild(std::move(pipe)); |
| 77 } | 74 } |
| 78 | 75 |
| 79 void Init() { | 76 void Init() { |
| 80 const base::CommandLine& command_line = | 77 internal::g_core = new Core(); |
| 81 *base::CommandLine::ForCurrentProcess(); | |
| 82 if (command_line.HasSwitch("use-new-edk") && !internal::g_broker) | |
| 83 BrokerState::GetInstance(); | |
| 84 | |
| 85 DCHECK(!internal::g_platform_support); | |
| 86 internal::g_platform_support = new SimplePlatformSupport(); | 78 internal::g_platform_support = new SimplePlatformSupport(); |
| 87 | |
| 88 DCHECK(!internal::g_core); | |
| 89 internal::g_core = new Core(internal::g_platform_support); | |
| 90 } | 79 } |
| 91 | 80 |
| 92 MojoResult AsyncWait(MojoHandle handle, | 81 MojoResult AsyncWait(MojoHandle handle, |
| 93 MojoHandleSignals signals, | 82 MojoHandleSignals signals, |
| 94 const base::Callback<void(MojoResult)>& callback) { | 83 const base::Callback<void(MojoResult)>& callback) { |
| 84 CHECK(internal::g_core); |
| 95 return internal::g_core->AsyncWait(handle, signals, callback); | 85 return internal::g_core->AsyncWait(handle, signals, callback); |
| 96 } | 86 } |
| 97 | 87 |
| 98 MojoResult CreatePlatformHandleWrapper( | 88 MojoResult CreatePlatformHandleWrapper( |
| 99 ScopedPlatformHandle platform_handle, | 89 ScopedPlatformHandle platform_handle, |
| 100 MojoHandle* platform_handle_wrapper_handle) { | 90 MojoHandle* platform_handle_wrapper_handle) { |
| 101 DCHECK(platform_handle_wrapper_handle); | 91 return internal::g_core->CreatePlatformHandleWrapper( |
| 102 | 92 std::move(platform_handle), platform_handle_wrapper_handle); |
| 103 scoped_refptr<Dispatcher> dispatcher = | |
| 104 PlatformHandleDispatcher::Create(std::move(platform_handle)); | |
| 105 | |
| 106 DCHECK(internal::g_core); | |
| 107 MojoHandle h = internal::g_core->AddDispatcher(dispatcher); | |
| 108 if (h == MOJO_HANDLE_INVALID) { | |
| 109 LOG(ERROR) << "Handle table full"; | |
| 110 dispatcher->Close(); | |
| 111 return MOJO_RESULT_RESOURCE_EXHAUSTED; | |
| 112 } | |
| 113 | |
| 114 *platform_handle_wrapper_handle = h; | |
| 115 return MOJO_RESULT_OK; | |
| 116 } | 93 } |
| 117 | 94 |
| 118 MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle, | 95 MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle, |
| 119 ScopedPlatformHandle* platform_handle) { | 96 ScopedPlatformHandle* platform_handle) { |
| 120 DCHECK(platform_handle); | 97 return internal::g_core->PassWrappedPlatformHandle( |
| 121 | 98 platform_handle_wrapper_handle, platform_handle); |
| 122 DCHECK(internal::g_core); | |
| 123 scoped_refptr<Dispatcher> dispatcher( | |
| 124 internal::g_core->GetDispatcher(platform_handle_wrapper_handle)); | |
| 125 if (!dispatcher) | |
| 126 return MOJO_RESULT_INVALID_ARGUMENT; | |
| 127 | |
| 128 if (dispatcher->GetType() != Dispatcher::Type::PLATFORM_HANDLE) | |
| 129 return MOJO_RESULT_INVALID_ARGUMENT; | |
| 130 | |
| 131 *platform_handle = static_cast<PlatformHandleDispatcher*>(dispatcher.get()) | |
| 132 ->PassPlatformHandle(); | |
| 133 return MOJO_RESULT_OK; | |
| 134 } | 99 } |
| 135 | 100 |
| 136 void InitIPCSupport(ProcessDelegate* process_delegate, | 101 void InitIPCSupport(ProcessDelegate* process_delegate, |
| 137 scoped_refptr<base::TaskRunner> io_thread_task_runner) { | 102 scoped_refptr<base::TaskRunner> io_thread_task_runner) { |
| 138 // |Init()| must have already been called. | 103 CHECK(internal::g_core); |
| 139 DCHECK(internal::g_core); | 104 CHECK(!internal::g_io_thread_task_runner); |
| 105 internal::g_io_thread_task_runner = io_thread_task_runner.get(); |
| 106 internal::g_io_thread_task_runner->AddRef(); |
| 107 |
| 108 internal::g_core->SetIOTaskRunner(io_thread_task_runner); |
| 140 internal::g_process_delegate = process_delegate; | 109 internal::g_process_delegate = process_delegate; |
| 141 internal::g_io_thread_task_runner = io_thread_task_runner.get(); | |
| 142 } | 110 } |
| 143 | 111 |
| 144 void ShutdownIPCSupportOnIOThread() { | 112 void ShutdownIPCSupportOnIOThread() { |
| 145 } | 113 } |
| 146 | 114 |
| 147 void ShutdownIPCSupport() { | 115 void ShutdownIPCSupport() { |
| 148 // TODO(jam): remove ProcessDelegate from new EDK once the old EDK is gone. | 116 CHECK(internal::g_process_delegate); |
| 149 internal::g_process_delegate->OnShutdownComplete(); | 117 CHECK(internal::g_core); |
| 118 internal::g_core->RequestShutdown( |
| 119 base::Bind(&ProcessDelegate::OnShutdownComplete, |
| 120 base::Unretained(internal::g_process_delegate))); |
| 150 } | 121 } |
| 151 | 122 |
| 152 ScopedMessagePipeHandle CreateMessagePipe( | 123 ScopedMessagePipeHandle CreateMessagePipe( |
| 153 ScopedPlatformHandle platform_handle) { | 124 ScopedPlatformHandle platform_handle) { |
| 154 MojoCreateMessagePipeOptions options = { | 125 NOTREACHED(); |
| 155 static_cast<uint32_t>(sizeof(MojoCreateMessagePipeOptions)), | 126 return ScopedMessagePipeHandle(); |
| 156 MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_TRANSFERABLE}; | 127 } |
| 157 scoped_refptr<MessagePipeDispatcher> dispatcher = | |
| 158 MessagePipeDispatcher::Create(options); | |
| 159 | 128 |
| 160 ScopedMessagePipeHandle rv( | 129 void CreateMessagePipe( |
| 161 MessagePipeHandle(internal::g_core->AddDispatcher(dispatcher))); | 130 ScopedPlatformHandle platform_handle, |
| 162 CHECK(rv.is_valid()); | 131 const base::Callback<void(ScopedMessagePipeHandle)>& callback) { |
| 163 dispatcher->Init(std::move(platform_handle), nullptr, 0, nullptr, 0, nullptr, | 132 DCHECK(internal::g_core); |
| 164 nullptr); | 133 if (internal::g_is_parent_process) { |
| 165 // TODO(vtl): The |.Pass()| below is only needed due to an MSVS bug; remove it | 134 internal::g_core->CreateParentMessagePipe(std::move(platform_handle), |
| 166 // once that's fixed. | 135 callback); |
| 167 return rv; | 136 } else { |
| 137 internal::g_core->CreateChildMessagePipe(std::move(platform_handle), |
| 138 callback); |
| 139 } |
| 140 } |
| 141 |
| 142 void CreateParentMessagePipe( |
| 143 const std::string& token, |
| 144 const base::Callback<void(ScopedMessagePipeHandle)>& callback) { |
| 145 DCHECK(internal::g_core); |
| 146 internal::g_core->CreateParentMessagePipe(token, callback); |
| 147 } |
| 148 |
| 149 void CreateChildMessagePipe( |
| 150 const std::string& token, |
| 151 const base::Callback<void(ScopedMessagePipeHandle)>& callback) { |
| 152 DCHECK(internal::g_core); |
| 153 internal::g_core->CreateChildMessagePipe(token, callback); |
| 154 } |
| 155 |
| 156 std::string GenerateRandomToken() { |
| 157 char random_bytes[16]; |
| 158 crypto::RandBytes(random_bytes, 16); |
| 159 return base::HexEncode(random_bytes, 16); |
| 168 } | 160 } |
| 169 | 161 |
| 170 } // namespace edk | 162 } // namespace edk |
| 171 } // namespace mojo | 163 } // namespace mojo |
| OLD | NEW |