| 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 |