Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / extensions / api / terminal / terminal_private_api.cc
blob49326bc97a20ce597dc9d42d78b9c6e4dc69ee3f
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/terminal/terminal_private_api.h"
7 #include "base/bind.h"
8 #include "base/json/json_writer.h"
9 #include "base/sys_info.h"
10 #include "base/values.h"
11 #include "chrome/browser/extensions/api/terminal/terminal_extension_helper.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/common/extensions/api/terminal_private.h"
15 #include "chromeos/process_proxy/process_proxy_registry.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "extensions/browser/event_router.h"
19 namespace terminal_private = extensions::api::terminal_private;
20 namespace OnTerminalResize =
21 extensions::api::terminal_private::OnTerminalResize;
22 namespace OpenTerminalProcess =
23 extensions::api::terminal_private::OpenTerminalProcess;
24 namespace SendInput = extensions::api::terminal_private::SendInput;
26 namespace {
28 const char kCroshName[] = "crosh";
29 const char kCroshCommand[] = "/usr/bin/crosh";
30 // We make stubbed crosh just echo back input.
31 const char kStubbedCroshCommand[] = "cat";
33 const char* GetCroshPath() {
34 if (base::SysInfo::IsRunningOnChromeOS())
35 return kCroshCommand;
36 else
37 return kStubbedCroshCommand;
40 const char* GetProcessCommandForName(const std::string& name) {
41 if (name == kCroshName)
42 return GetCroshPath();
43 else
44 return NULL;
47 void NotifyProcessOutput(Profile* profile,
48 const std::string& extension_id,
49 pid_t pid,
50 const std::string& output_type,
51 const std::string& output) {
52 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
53 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
54 base::Bind(&NotifyProcessOutput, profile, extension_id,
55 pid, output_type, output));
56 return;
59 scoped_ptr<base::ListValue> args(new base::ListValue());
60 args->Append(new base::FundamentalValue(pid));
61 args->Append(new base::StringValue(output_type));
62 args->Append(new base::StringValue(output));
64 extensions::EventRouter* event_router = extensions::EventRouter::Get(profile);
65 if (profile && event_router) {
66 scoped_ptr<extensions::Event> event(new extensions::Event(
67 extensions::events::TERMINAL_PRIVATE_ON_PROCESS_OUTPUT,
68 terminal_private::OnProcessOutput::kEventName, args.Pass()));
69 event_router->DispatchEventToExtension(extension_id, event.Pass());
73 } // namespace
75 namespace extensions {
77 TerminalPrivateFunction::TerminalPrivateFunction() {}
79 TerminalPrivateFunction::~TerminalPrivateFunction() {}
81 bool TerminalPrivateFunction::RunAsync() {
82 return RunTerminalFunction();
85 TerminalPrivateOpenTerminalProcessFunction::
86 TerminalPrivateOpenTerminalProcessFunction() : command_(NULL) {}
88 TerminalPrivateOpenTerminalProcessFunction::
89 ~TerminalPrivateOpenTerminalProcessFunction() {}
91 bool TerminalPrivateOpenTerminalProcessFunction::RunTerminalFunction() {
92 scoped_ptr<OpenTerminalProcess::Params> params(
93 OpenTerminalProcess::Params::Create(*args_));
94 EXTENSION_FUNCTION_VALIDATE(params.get());
96 command_ = GetProcessCommandForName(params->process_name);
97 if (!command_) {
98 error_ = "Invalid process name.";
99 return false;
102 // Registry lives on FILE thread.
103 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
104 base::Bind(&TerminalPrivateOpenTerminalProcessFunction::OpenOnFileThread,
105 this));
106 return true;
109 void TerminalPrivateOpenTerminalProcessFunction::OpenOnFileThread() {
110 DCHECK(command_);
112 chromeos::ProcessProxyRegistry* registry =
113 chromeos::ProcessProxyRegistry::Get();
114 pid_t pid;
115 if (!registry->OpenProcess(
116 command_,
117 &pid,
118 base::Bind(&NotifyProcessOutput, GetProfile(), extension_id()))) {
119 // If new process could not be opened, we return -1.
120 pid = -1;
123 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
124 base::Bind(&TerminalPrivateOpenTerminalProcessFunction::RespondOnUIThread,
125 this, pid));
128 TerminalPrivateSendInputFunction::~TerminalPrivateSendInputFunction() {}
130 void TerminalPrivateOpenTerminalProcessFunction::RespondOnUIThread(pid_t pid) {
131 SetResult(new base::FundamentalValue(pid));
132 SendResponse(true);
135 bool TerminalPrivateSendInputFunction::RunTerminalFunction() {
136 scoped_ptr<SendInput::Params> params(SendInput::Params::Create(*args_));
137 EXTENSION_FUNCTION_VALIDATE(params.get());
139 // Registry lives on the FILE thread.
140 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
141 base::Bind(&TerminalPrivateSendInputFunction::SendInputOnFileThread,
142 this, params->pid, params->input));
143 return true;
146 void TerminalPrivateSendInputFunction::SendInputOnFileThread(pid_t pid,
147 const std::string& text) {
148 bool success = chromeos::ProcessProxyRegistry::Get()->SendInput(pid, text);
150 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
151 base::Bind(&TerminalPrivateSendInputFunction::RespondOnUIThread, this,
152 success));
155 void TerminalPrivateSendInputFunction::RespondOnUIThread(bool success) {
156 SetResult(new base::FundamentalValue(success));
157 SendResponse(true);
160 TerminalPrivateCloseTerminalProcessFunction::
161 ~TerminalPrivateCloseTerminalProcessFunction() {}
163 bool TerminalPrivateCloseTerminalProcessFunction::RunTerminalFunction() {
164 if (args_->GetSize() != 1)
165 return false;
166 pid_t pid;
167 if (!args_->GetInteger(0, &pid))
168 return false;
170 // Registry lives on the FILE thread.
171 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
172 base::Bind(&TerminalPrivateCloseTerminalProcessFunction::
173 CloseOnFileThread, this, pid));
175 return true;
178 void TerminalPrivateCloseTerminalProcessFunction::CloseOnFileThread(pid_t pid) {
179 bool success = chromeos::ProcessProxyRegistry::Get()->CloseProcess(pid);
181 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
182 base::Bind(&TerminalPrivateCloseTerminalProcessFunction::
183 RespondOnUIThread, this, success));
186 void TerminalPrivateCloseTerminalProcessFunction::RespondOnUIThread(
187 bool success) {
188 SetResult(new base::FundamentalValue(success));
189 SendResponse(true);
192 TerminalPrivateOnTerminalResizeFunction::
193 ~TerminalPrivateOnTerminalResizeFunction() {}
195 bool TerminalPrivateOnTerminalResizeFunction::RunTerminalFunction() {
196 scoped_ptr<OnTerminalResize::Params> params(
197 OnTerminalResize::Params::Create(*args_));
198 EXTENSION_FUNCTION_VALIDATE(params.get());
200 // Registry lives on the FILE thread.
201 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
202 base::Bind(&TerminalPrivateOnTerminalResizeFunction::OnResizeOnFileThread,
203 this, params->pid, params->width, params->height));
205 return true;
208 void TerminalPrivateOnTerminalResizeFunction::OnResizeOnFileThread(pid_t pid,
209 int width, int height) {
210 bool success = chromeos::ProcessProxyRegistry::Get()->OnTerminalResize(
211 pid, width, height);
213 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
214 base::Bind(&TerminalPrivateOnTerminalResizeFunction::RespondOnUIThread,
215 this, success));
218 void TerminalPrivateOnTerminalResizeFunction::RespondOnUIThread(bool success) {
219 SetResult(new base::FundamentalValue(success));
220 SendResponse(true);
223 } // namespace extensions