OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "chrome/browser/service/service_process_control.h" | 5 #include "chrome/browser/service/service_process_control.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/file_path.h" | 8 #include "base/file_path.h" |
9 #include "base/process_util.h" | 9 #include "base/process_util.h" |
10 #include "base/thread.h" | 10 #include "base/thread.h" |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 connect_done_task_.reset(task); | 103 connect_done_task_.reset(task); |
104 ConnectInternal(); | 104 ConnectInternal(); |
105 } | 105 } |
106 | 106 |
107 void ServiceProcessControl::ConnectInternal() { | 107 void ServiceProcessControl::ConnectInternal() { |
108 LOG(INFO) << "Connecting to Service Process IPC Server"; | 108 LOG(INFO) << "Connecting to Service Process IPC Server"; |
109 // Run the IPC channel on the shared IO thread. | 109 // Run the IPC channel on the shared IO thread. |
110 base::Thread* io_thread = g_browser_process->io_thread(); | 110 base::Thread* io_thread = g_browser_process->io_thread(); |
111 | 111 |
112 // TODO(hclam): Determine the the channel id from profile and type. | 112 // TODO(hclam): Determine the the channel id from profile and type. |
| 113 // TODO(hclam): Handle error connecting to channel. |
113 const std::string channel_id = GetServiceProcessChannelName(type_); | 114 const std::string channel_id = GetServiceProcessChannelName(type_); |
114 channel_.reset( | 115 channel_.reset( |
115 new IPC::SyncChannel(channel_id, IPC::Channel::MODE_CLIENT, this, NULL, | 116 new IPC::SyncChannel(channel_id, IPC::Channel::MODE_CLIENT, this, NULL, |
116 io_thread->message_loop(), true, | 117 io_thread->message_loop(), true, |
117 g_browser_process->shutdown_event())); | 118 g_browser_process->shutdown_event())); |
118 channel_->set_sync_messages_with_no_timeout_allowed(false); | 119 channel_->set_sync_messages_with_no_timeout_allowed(false); |
119 } | 120 } |
120 | 121 |
121 void ServiceProcessControl::Launch(Task* task) { | 122 void ServiceProcessControl::Launch(Task* task) { |
122 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 123 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
123 if (channel_.get()) { | 124 if (channel_.get()) { |
124 task->Run(); | 125 if (task) { |
125 delete task; | 126 task->Run(); |
| 127 delete task; |
| 128 } |
126 return; | 129 return; |
127 } | 130 } |
128 | 131 |
129 // A service process should have a different mechanism for starting, but now | 132 // A service process should have a different mechanism for starting, but now |
130 // we start it as if it is a child process. | 133 // we start it as if it is a child process. |
131 FilePath exe_path = ChildProcessHost::GetChildPath(true); | 134 FilePath exe_path = ChildProcessHost::GetChildPath(true); |
132 if (exe_path.empty()) { | 135 if (exe_path.empty()) { |
133 NOTREACHED() << "Unable to get service process binary name."; | 136 NOTREACHED() << "Unable to get service process binary name."; |
134 } | 137 } |
135 | 138 |
136 CommandLine* cmd_line = new CommandLine(exe_path); | 139 CommandLine* cmd_line = new CommandLine(exe_path); |
137 cmd_line->AppendSwitchASCII(switches::kProcessType, | 140 cmd_line->AppendSwitchASCII(switches::kProcessType, |
138 switches::kServiceProcess); | 141 switches::kServiceProcess); |
139 | 142 |
140 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); | 143 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); |
141 FilePath user_data_dir = | 144 FilePath user_data_dir = |
142 browser_command_line.GetSwitchValuePath(switches::kUserDataDir); | 145 browser_command_line.GetSwitchValuePath(switches::kUserDataDir); |
143 if (!user_data_dir.empty()) | 146 if (!user_data_dir.empty()) |
144 cmd_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir); | 147 cmd_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir); |
145 | 148 |
146 std::string logging_level = browser_command_line.GetSwitchValueASCII( | 149 std::string logging_level = browser_command_line.GetSwitchValueASCII( |
147 switches::kLoggingLevel); | 150 switches::kLoggingLevel); |
148 if (!logging_level.empty()) | 151 if (!logging_level.empty()) |
149 cmd_line->AppendSwitchASCII(switches::kLoggingLevel, logging_level); | 152 cmd_line->AppendSwitchASCII(switches::kLoggingLevel, logging_level); |
150 | 153 |
| 154 if (browser_command_line.HasSwitch(switches::kWaitForDebuggerChildren)) { |
| 155 cmd_line->AppendSwitch(switches::kWaitForDebugger); |
| 156 } |
| 157 |
151 // And then start the process asynchronously. | 158 // And then start the process asynchronously. |
152 launcher_ = new Launcher(this, cmd_line); | 159 launcher_ = new Launcher(this, cmd_line); |
153 launcher_->Run( | 160 launcher_->Run( |
154 NewRunnableMethod(this, &ServiceProcessControl::OnProcessLaunched, task)); | 161 NewRunnableMethod(this, &ServiceProcessControl::OnProcessLaunched, task)); |
155 } | 162 } |
156 | 163 |
157 void ServiceProcessControl::OnProcessLaunched(Task* task) { | 164 void ServiceProcessControl::OnProcessLaunched(Task* task) { |
158 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 165 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
159 if (launcher_->launched()) { | 166 if (launcher_->launched()) { |
160 // Now use the launch task as the connect task. | 167 // Now use the launch task as the connect task. |
161 connect_done_task_.reset(task); | 168 connect_done_task_.reset(task); |
162 | 169 |
163 // After we have successfully created the service process we try to connect | 170 // After we have successfully created the service process we try to connect |
164 // to it. The launch task is transfered to a connect task. | 171 // to it. The launch task is transfered to a connect task. |
165 ConnectInternal(); | 172 ConnectInternal(); |
166 } else { | 173 } else if (task) { |
167 // If we don't have process handle that means launching the service process | 174 // If we don't have process handle that means launching the service process |
168 // has failed. | 175 // has failed. |
169 task->Run(); | 176 task->Run(); |
170 delete task; | 177 delete task; |
171 } | 178 } |
172 | 179 |
173 // We don't need the launcher anymore. | 180 // We don't need the launcher anymore. |
174 launcher_ = NULL; | 181 launcher_ = NULL; |
175 } | 182 } |
176 | 183 |
177 void ServiceProcessControl::OnMessageReceived(const IPC::Message& message) { | 184 void ServiceProcessControl::OnMessageReceived(const IPC::Message& message) { |
178 if (!message_handler_) | 185 if (!message_handler_) |
179 return; | 186 return; |
180 | 187 |
181 if (message.type() == ServiceHostMsg_GoodDay::ID) | 188 if (message.type() == ServiceHostMsg_GoodDay::ID) |
182 message_handler_->OnGoodDay(); | 189 message_handler_->OnGoodDay(); |
183 } | 190 } |
184 | 191 |
185 void ServiceProcessControl::OnChannelConnected(int32 peer_pid) { | 192 void ServiceProcessControl::OnChannelConnected(int32 peer_pid) { |
186 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 193 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 194 if (!connect_done_task_.get()) |
| 195 return; |
187 connect_done_task_->Run(); | 196 connect_done_task_->Run(); |
188 connect_done_task_.reset(); | 197 connect_done_task_.reset(); |
189 } | 198 } |
190 | 199 |
191 void ServiceProcessControl::OnChannelError() { | 200 void ServiceProcessControl::OnChannelError() { |
192 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 201 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
193 channel_.reset(); | 202 channel_.reset(); |
| 203 if (!connect_done_task_.get()) |
| 204 return; |
194 connect_done_task_->Run(); | 205 connect_done_task_->Run(); |
195 connect_done_task_.reset(); | 206 connect_done_task_.reset(); |
196 } | 207 } |
197 | 208 |
198 bool ServiceProcessControl::Send(IPC::Message* message) { | 209 bool ServiceProcessControl::Send(IPC::Message* message) { |
199 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 210 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 211 if (!channel_.get()) |
| 212 return false; |
200 return channel_->Send(message); | 213 return channel_->Send(message); |
201 } | 214 } |
202 | 215 |
203 bool ServiceProcessControl::SendHello() { | 216 bool ServiceProcessControl::SendHello() { |
204 return Send(new ServiceMsg_Hello()); | 217 return Send(new ServiceMsg_Hello()); |
205 } | 218 } |
206 | 219 |
207 bool ServiceProcessControl::Shutdown() { | 220 bool ServiceProcessControl::Shutdown() { |
208 bool ret = Send(new ServiceMsg_Shutdown()); | 221 bool ret = Send(new ServiceMsg_Shutdown()); |
209 channel_.reset(); | 222 channel_.reset(); |
210 return ret; | 223 return ret; |
211 } | 224 } |
212 | 225 |
213 bool ServiceProcessControl::EnableRemotingWithTokens( | 226 bool ServiceProcessControl::EnableRemotingWithTokens( |
214 const std::string& user, | 227 const std::string& user, |
215 const std::string& remoting_token, | 228 const std::string& remoting_token, |
216 const std::string& talk_token) { | 229 const std::string& talk_token) { |
217 return Send( | 230 return Send( |
218 new ServiceMsg_EnableRemotingWithTokens(user, remoting_token, | 231 new ServiceMsg_EnableRemotingWithTokens(user, remoting_token, |
219 talk_token)); | 232 talk_token)); |
220 } | 233 } |
221 | 234 |
222 DISABLE_RUNNABLE_METHOD_REFCOUNT(ServiceProcessControl); | 235 DISABLE_RUNNABLE_METHOD_REFCOUNT(ServiceProcessControl); |
OLD | NEW |