1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdint.h>
#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "base/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/browser/mojo/mojo_shell_client_host.h"
#include "content/common/mojo/mojo_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/mojo_shell_connection.h"
#include "ipc/ipc_sender.h"
#include "mojo/application/public/cpp/application_impl.h"
#include "mojo/application/public/interfaces/application_manager.mojom.h"
#include "mojo/converters/network/network_type_converters.h"
#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h"
namespace content {
namespace {
const char kMojoShellInstanceURL[] = "mojo_shell_instance_url";
const char kMojoPlatformFile[] = "mojo_platform_file";
void DidCreateChannel(mojo::embedder::ChannelInfo* info) {}
base::PlatformFile PlatformFileFromScopedPlatformHandle(
mojo::embedder::ScopedPlatformHandle handle) {
#if defined(OS_POSIX)
return handle.release().fd;
#elif defined(OS_WIN)
return handle.release().handle;
#endif
}
class InstanceURL : public base::SupportsUserData::Data {
public:
InstanceURL(const std::string& instance_url) : instance_url_(instance_url) {}
~InstanceURL() override {}
std::string get() const { return instance_url_; }
private:
std::string instance_url_;
DISALLOW_COPY_AND_ASSIGN(InstanceURL);
};
class InstanceShellHandle : public base::SupportsUserData::Data {
public:
InstanceShellHandle(base::PlatformFile shell_handle)
: shell_handle_(shell_handle) {}
~InstanceShellHandle() override {}
base::PlatformFile get() const { return shell_handle_; }
private:
base::PlatformFile shell_handle_;
DISALLOW_COPY_AND_ASSIGN(InstanceShellHandle);
};
void SetMojoApplicationInstanceURL(RenderProcessHost* render_process_host,
const std::string& instance_url) {
render_process_host->SetUserData(kMojoShellInstanceURL,
new InstanceURL(instance_url));
}
void SetMojoPlatformFile(RenderProcessHost* render_process_host,
base::PlatformFile platform_file) {
render_process_host->SetUserData(kMojoPlatformFile,
new InstanceShellHandle(platform_file));
}
void CallRegisterProcessWithBroker(base::ProcessId pid,
MojoHandle client_pipe) {
mojo::shell::mojom::ApplicationManagerPtr application_manager;
MojoShellConnection::Get()->GetApplication()->ConnectToService(
"mojo:shell", &application_manager);
application_manager->RegisterProcessWithBroker(
static_cast<uint32_t>(pid),
mojo::ScopedHandle(mojo::Handle(client_pipe)));
}
} // namespace
void RegisterChildWithExternalShell(int child_process_id,
RenderProcessHost* render_process_host) {
// Some process types get created before the main message loop.
if (!MojoShellConnection::Get())
return;
// Create the channel to be shared with the target process.
mojo::embedder::HandlePassingInformation handle_passing_info;
mojo::embedder::PlatformChannelPair platform_channel_pair;
// Give one end to the shell so that it can create an instance.
mojo::embedder::ScopedPlatformHandle platform_channel =
platform_channel_pair.PassServerHandle();
mojo::ScopedMessagePipeHandle handle(mojo::embedder::CreateChannel(
platform_channel.Pass(), base::Bind(&DidCreateChannel),
base::ThreadTaskRunnerHandle::Get()));
mojo::shell::mojom::ApplicationManagerPtr application_manager;
MojoShellConnection::Get()->GetApplication()->ConnectToService(
"mojo:shell", &application_manager);
// The content of the URL/qualifier we pass is actually meaningless, it's only
// important that they're unique per process.
// TODO(beng): We need to specify a restrictive CapabilityFilter here that
// matches the needs of the target process. Figure out where that
// specification is best determined (not here, this is a common
// chokepoint for all process types) and how to wire it through.
// http://crbug.com/555393
std::string url =
base::StringPrintf("exe:chrome_renderer%d", child_process_id);
application_manager->CreateInstanceForHandle(
mojo::ScopedHandle(mojo::Handle(handle.release().value())),
url,
CreateCapabilityFilterForRenderer());
// Send the other end to the child via Chrome IPC.
base::PlatformFile client_file = PlatformFileFromScopedPlatformHandle(
platform_channel_pair.PassClientHandle());
SetMojoPlatformFile(render_process_host, client_file);
// Store the URL on the RPH so client code can access it later via
// GetMojoApplicationInstanceURL().
SetMojoApplicationInstanceURL(render_process_host, url);
}
std::string GetMojoApplicationInstanceURL(
RenderProcessHost* render_process_host) {
InstanceURL* instance_url = static_cast<InstanceURL*>(
render_process_host->GetUserData(kMojoShellInstanceURL));
return instance_url ? instance_url->get() : std::string();
}
void SendExternalMojoShellHandleToChild(
base::ProcessHandle process_handle,
RenderProcessHost* render_process_host) {
InstanceShellHandle* client_file = static_cast<InstanceShellHandle*>(
render_process_host->GetUserData(kMojoPlatformFile));
if (!client_file)
return;
render_process_host->Send(new MojoMsg_BindExternalMojoShellHandle(
IPC::GetFileHandleForProcess(client_file->get(), process_handle, true)));
}
mojo::embedder::ScopedPlatformHandle RegisterProcessWithBroker(
base::ProcessId pid) {
mojo::embedder::PlatformChannelPair platform_channel_pair;
MojoHandle platform_handle_wrapper;
MojoResult rv = mojo::embedder::CreatePlatformHandleWrapper(
platform_channel_pair.PassServerHandle(), &platform_handle_wrapper);
CHECK_EQ(rv, MOJO_RESULT_OK);
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
CallRegisterProcessWithBroker(pid, platform_handle_wrapper);
} else {
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(CallRegisterProcessWithBroker, pid,
platform_handle_wrapper));
}
return platform_channel_pair.PassClientHandle();
}
} // namespace content
|