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"
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;
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())
37 return kStubbedCroshCommand;
40 const char* GetProcessCommandForName(const std::string& name) {
41 if (name == kCroshName)
42 return GetCroshPath();
47 void NotifyProcessOutput(Profile* profile,
48 const std::string& extension_id,
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));
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 terminal_private::OnProcessOutput::kEventName, args.Pass()));
68 event_router->DispatchEventToExtension(extension_id, event.Pass());
74 namespace extensions {
76 TerminalPrivateFunction::TerminalPrivateFunction() {}
78 TerminalPrivateFunction::~TerminalPrivateFunction() {}
80 bool TerminalPrivateFunction::RunAsync() {
81 return RunTerminalFunction();
84 TerminalPrivateOpenTerminalProcessFunction::
85 TerminalPrivateOpenTerminalProcessFunction() : command_(NULL) {}
87 TerminalPrivateOpenTerminalProcessFunction::
88 ~TerminalPrivateOpenTerminalProcessFunction() {}
90 bool TerminalPrivateOpenTerminalProcessFunction::RunTerminalFunction() {
91 scoped_ptr<OpenTerminalProcess::Params> params(
92 OpenTerminalProcess::Params::Create(*args_));
93 EXTENSION_FUNCTION_VALIDATE(params.get());
95 command_ = GetProcessCommandForName(params->process_name);
97 error_ = "Invalid process name.";
101 // Registry lives on FILE thread.
102 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
103 base::Bind(&TerminalPrivateOpenTerminalProcessFunction::OpenOnFileThread,
108 void TerminalPrivateOpenTerminalProcessFunction::OpenOnFileThread() {
111 chromeos::ProcessProxyRegistry* registry =
112 chromeos::ProcessProxyRegistry::Get();
114 if (!registry->OpenProcess(
117 base::Bind(&NotifyProcessOutput, GetProfile(), extension_id()))) {
118 // If new process could not be opened, we return -1.
122 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
123 base::Bind(&TerminalPrivateOpenTerminalProcessFunction::RespondOnUIThread,
127 TerminalPrivateSendInputFunction::~TerminalPrivateSendInputFunction() {}
129 void TerminalPrivateOpenTerminalProcessFunction::RespondOnUIThread(pid_t pid) {
130 SetResult(new base::FundamentalValue(pid));
134 bool TerminalPrivateSendInputFunction::RunTerminalFunction() {
135 scoped_ptr<SendInput::Params> params(SendInput::Params::Create(*args_));
136 EXTENSION_FUNCTION_VALIDATE(params.get());
138 // Registry lives on the FILE thread.
139 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
140 base::Bind(&TerminalPrivateSendInputFunction::SendInputOnFileThread,
141 this, params->pid, params->input));
145 void TerminalPrivateSendInputFunction::SendInputOnFileThread(pid_t pid,
146 const std::string& text) {
147 bool success = chromeos::ProcessProxyRegistry::Get()->SendInput(pid, text);
149 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
150 base::Bind(&TerminalPrivateSendInputFunction::RespondOnUIThread, this,
154 void TerminalPrivateSendInputFunction::RespondOnUIThread(bool success) {
155 SetResult(new base::FundamentalValue(success));
159 TerminalPrivateCloseTerminalProcessFunction::
160 ~TerminalPrivateCloseTerminalProcessFunction() {}
162 bool TerminalPrivateCloseTerminalProcessFunction::RunTerminalFunction() {
163 if (args_->GetSize() != 1)
166 if (!args_->GetInteger(0, &pid))
169 // Registry lives on the FILE thread.
170 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
171 base::Bind(&TerminalPrivateCloseTerminalProcessFunction::
172 CloseOnFileThread, this, pid));
177 void TerminalPrivateCloseTerminalProcessFunction::CloseOnFileThread(pid_t pid) {
178 bool success = chromeos::ProcessProxyRegistry::Get()->CloseProcess(pid);
180 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
181 base::Bind(&TerminalPrivateCloseTerminalProcessFunction::
182 RespondOnUIThread, this, success));
185 void TerminalPrivateCloseTerminalProcessFunction::RespondOnUIThread(
187 SetResult(new base::FundamentalValue(success));
191 TerminalPrivateOnTerminalResizeFunction::
192 ~TerminalPrivateOnTerminalResizeFunction() {}
194 bool TerminalPrivateOnTerminalResizeFunction::RunTerminalFunction() {
195 scoped_ptr<OnTerminalResize::Params> params(
196 OnTerminalResize::Params::Create(*args_));
197 EXTENSION_FUNCTION_VALIDATE(params.get());
199 // Registry lives on the FILE thread.
200 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
201 base::Bind(&TerminalPrivateOnTerminalResizeFunction::OnResizeOnFileThread,
202 this, params->pid, params->width, params->height));
207 void TerminalPrivateOnTerminalResizeFunction::OnResizeOnFileThread(pid_t pid,
208 int width, int height) {
209 bool success = chromeos::ProcessProxyRegistry::Get()->OnTerminalResize(
212 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
213 base::Bind(&TerminalPrivateOnTerminalResizeFunction::RespondOnUIThread,
217 void TerminalPrivateOnTerminalResizeFunction::RespondOnUIThread(bool success) {
218 SetResult(new base::FundamentalValue(success));
222 } // namespace extensions