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 |