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 extensions::events::TERMINAL_PRIVATE_ON_PROCESS_OUTPUT
,
68 terminal_private::OnProcessOutput::kEventName
, args
.Pass()));
69 event_router
->DispatchEventToExtension(extension_id
, event
.Pass());
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
);
98 error_
= "Invalid process name.";
102 // Registry lives on FILE thread.
103 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE
,
104 base::Bind(&TerminalPrivateOpenTerminalProcessFunction::OpenOnFileThread
,
109 void TerminalPrivateOpenTerminalProcessFunction::OpenOnFileThread() {
112 chromeos::ProcessProxyRegistry
* registry
=
113 chromeos::ProcessProxyRegistry::Get();
115 if (!registry
->OpenProcess(
118 base::Bind(&NotifyProcessOutput
, GetProfile(), extension_id()))) {
119 // If new process could not be opened, we return -1.
123 content::BrowserThread::PostTask(content::BrowserThread::UI
, FROM_HERE
,
124 base::Bind(&TerminalPrivateOpenTerminalProcessFunction::RespondOnUIThread
,
128 TerminalPrivateSendInputFunction::~TerminalPrivateSendInputFunction() {}
130 void TerminalPrivateOpenTerminalProcessFunction::RespondOnUIThread(pid_t pid
) {
131 SetResult(new base::FundamentalValue(pid
));
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
));
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,
155 void TerminalPrivateSendInputFunction::RespondOnUIThread(bool success
) {
156 SetResult(new base::FundamentalValue(success
));
160 TerminalPrivateCloseTerminalProcessFunction::
161 ~TerminalPrivateCloseTerminalProcessFunction() {}
163 bool TerminalPrivateCloseTerminalProcessFunction::RunTerminalFunction() {
164 if (args_
->GetSize() != 1)
167 if (!args_
->GetInteger(0, &pid
))
170 // Registry lives on the FILE thread.
171 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE
,
172 base::Bind(&TerminalPrivateCloseTerminalProcessFunction::
173 CloseOnFileThread
, this, pid
));
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(
188 SetResult(new base::FundamentalValue(success
));
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
));
208 void TerminalPrivateOnTerminalResizeFunction::OnResizeOnFileThread(pid_t pid
,
209 int width
, int height
) {
210 bool success
= chromeos::ProcessProxyRegistry::Get()->OnTerminalResize(
213 content::BrowserThread::PostTask(content::BrowserThread::UI
, FROM_HERE
,
214 base::Bind(&TerminalPrivateOnTerminalResizeFunction::RespondOnUIThread
,
218 void TerminalPrivateOnTerminalResizeFunction::RespondOnUIThread(bool success
) {
219 SetResult(new base::FundamentalValue(success
));
223 } // namespace extensions