blob: 043165029a801090a14752956894ce64b9d917c5 (
plain)
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
|
// Copyright (c) 2010 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 "chrome/common/child_process_host.h"
#include "base/command_line.h"
#include "base/path_service.h"
#include "chrome/common/child_process_info.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths_internal.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/plugin_messages.h"
#if defined(OS_LINUX)
#include "base/linux_util.h"
#endif // OS_LINUX
ChildProcessHost::ChildProcessHost()
: ALLOW_THIS_IN_INITIALIZER_LIST(listener_(this)),
opening_channel_(false) {
}
ChildProcessHost::~ChildProcessHost() {
}
// static
FilePath ChildProcessHost::GetChildPath(bool allow_self) {
FilePath child_path;
child_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
switches::kBrowserSubprocessPath);
if (!child_path.empty())
return child_path;
#if defined(OS_MACOSX)
// On the Mac, the child executable lives at a predefined location within
// the app bundle's versioned directory.
return chrome::GetVersionedDirectory().
Append(chrome::kHelperProcessExecutablePath);
#endif
#if defined(OS_LINUX)
// Use /proc/self/exe rather than our known binary path so updates
// can't swap out the binary from underneath us.
if (allow_self)
return FilePath("/proc/self/exe");
#endif
// On most platforms, the child executable is the same as the current
// executable.
PathService::Get(base::FILE_EXE, &child_path);
return child_path;
}
bool ChildProcessHost::CreateChannel() {
channel_id_ = ChildProcessInfo::GenerateRandomChannelID(this);
channel_.reset(new IPC::Channel(
channel_id_, IPC::Channel::MODE_SERVER, &listener_));
if (!channel_->Connect())
return false;
opening_channel_ = true;
return true;
}
void ChildProcessHost::InstanceCreated() {
Notify(NotificationType::CHILD_INSTANCE_CREATED);
}
bool ChildProcessHost::SendOnChannel(IPC::Message* msg) {
if (!channel_.get()) {
delete msg;
return false;
}
return channel_->Send(msg);
}
void ChildProcessHost::OnChildDied() {
delete this;
}
ChildProcessHost::ListenerHook::ListenerHook(ChildProcessHost* host)
: host_(host) {
}
void ChildProcessHost::ListenerHook::OnMessageReceived(
const IPC::Message& msg) {
#ifdef IPC_MESSAGE_LOG_ENABLED
IPC::Logging* logger = IPC::Logging::current();
if (msg.type() == IPC_LOGGING_ID) {
logger->OnReceivedLoggingMessage(msg);
return;
}
if (logger->Enabled())
logger->OnPreDispatchMessage(msg);
#endif
bool handled = host_->InterceptMessageFromChild(msg);
if (!handled) {
if (msg.type() == PluginProcessHostMsg_ShutdownRequest::ID) {
if (host_->CanShutdown())
host_->SendOnChannel(new PluginProcessMsg_Shutdown());
} else {
host_->OnMessageReceived(msg);
}
}
#ifdef IPC_MESSAGE_LOG_ENABLED
if (logger->Enabled())
logger->OnPostDispatchMessage(msg, host_->channel_id_);
#endif
}
void ChildProcessHost::ListenerHook::OnChannelConnected(int32 peer_pid) {
host_->opening_channel_ = false;
host_->OnChannelConnected(peer_pid);
#if defined(IPC_MESSAGE_LOG_ENABLED)
bool enabled = IPC::Logging::current()->Enabled();
host_->SendOnChannel(new PluginProcessMsg_SetIPCLoggingEnabled(enabled));
#endif
host_->SendOnChannel(new PluginProcessMsg_AskBeforeShutdown());
// Notify in the main loop of the connection.
host_->Notify(NotificationType::CHILD_PROCESS_HOST_CONNECTED);
}
void ChildProcessHost::ListenerHook::OnChannelError() {
host_->opening_channel_ = false;
host_->OnChannelError();
// This will delete host_, which will also destroy this!
host_->OnChildDied();
}
void ChildProcessHost::ForceShutdown() {
SendOnChannel(new PluginProcessMsg_Shutdown());
}
|