• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/extensions/api/terminal/terminal_private_api.h"
6 
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/extensions/extension_system.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/common/extensions/api/terminal_private.h"
16 #include "chromeos/process_proxy/process_proxy_registry.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "extensions/browser/event_router.h"
19 
20 namespace terminal_private = extensions::api::terminal_private;
21 namespace OnTerminalResize =
22     extensions::api::terminal_private::OnTerminalResize;
23 namespace OpenTerminalProcess =
24     extensions::api::terminal_private::OpenTerminalProcess;
25 namespace SendInput = extensions::api::terminal_private::SendInput;
26 
27 namespace {
28 
29 const char kCroshName[] = "crosh";
30 const char kCroshCommand[] = "/usr/bin/crosh";
31 // We make stubbed crosh just echo back input.
32 const char kStubbedCroshCommand[] = "cat";
33 
GetCroshPath()34 const char* GetCroshPath() {
35   if (base::SysInfo::IsRunningOnChromeOS())
36     return kCroshCommand;
37   else
38     return kStubbedCroshCommand;
39 }
40 
GetProcessCommandForName(const std::string & name)41 const char* GetProcessCommandForName(const std::string& name) {
42   if (name == kCroshName)
43     return GetCroshPath();
44   else
45     return NULL;
46 }
47 
NotifyProcessOutput(Profile * profile,const std::string & extension_id,pid_t pid,const std::string & output_type,const std::string & output)48 void NotifyProcessOutput(Profile* profile,
49                          const std::string& extension_id,
50                          pid_t pid,
51                          const std::string& output_type,
52                          const std::string& output) {
53   if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
54     content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
55         base::Bind(&NotifyProcessOutput, profile, extension_id,
56                                          pid, output_type, output));
57     return;
58   }
59 
60   scoped_ptr<base::ListValue> args(new base::ListValue());
61   args->Append(new base::FundamentalValue(pid));
62   args->Append(new base::StringValue(output_type));
63   args->Append(new base::StringValue(output));
64 
65   if (profile &&
66       extensions::ExtensionSystem::Get(profile)->event_router()) {
67     scoped_ptr<extensions::Event> event(new extensions::Event(
68         terminal_private::OnProcessOutput::kEventName, args.Pass()));
69     extensions::ExtensionSystem::Get(profile)->event_router()->
70         DispatchEventToExtension(extension_id, event.Pass());
71   }
72 }
73 
74 }  // namespace
75 
76 namespace extensions {
77 
TerminalPrivateFunction()78 TerminalPrivateFunction::TerminalPrivateFunction() {}
79 
~TerminalPrivateFunction()80 TerminalPrivateFunction::~TerminalPrivateFunction() {}
81 
RunImpl()82 bool TerminalPrivateFunction::RunImpl() {
83   return RunTerminalFunction();
84 }
85 
86 TerminalPrivateOpenTerminalProcessFunction::
TerminalPrivateOpenTerminalProcessFunction()87     TerminalPrivateOpenTerminalProcessFunction() : command_(NULL) {}
88 
89 TerminalPrivateOpenTerminalProcessFunction::
~TerminalPrivateOpenTerminalProcessFunction()90     ~TerminalPrivateOpenTerminalProcessFunction() {}
91 
RunTerminalFunction()92 bool TerminalPrivateOpenTerminalProcessFunction::RunTerminalFunction() {
93   scoped_ptr<OpenTerminalProcess::Params> params(
94       OpenTerminalProcess::Params::Create(*args_));
95   EXTENSION_FUNCTION_VALIDATE(params.get());
96 
97   command_ = GetProcessCommandForName(params->process_name);
98   if (!command_) {
99     error_ = "Invalid process name.";
100     return false;
101   }
102 
103   // Registry lives on FILE thread.
104   content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
105       base::Bind(&TerminalPrivateOpenTerminalProcessFunction::OpenOnFileThread,
106                  this));
107   return true;
108 }
109 
OpenOnFileThread()110 void TerminalPrivateOpenTerminalProcessFunction::OpenOnFileThread() {
111   DCHECK(command_);
112 
113   chromeos::ProcessProxyRegistry* registry =
114       chromeos::ProcessProxyRegistry::Get();
115   pid_t pid;
116   if (!registry->OpenProcess(
117            command_,
118            &pid,
119            base::Bind(&NotifyProcessOutput, GetProfile(), extension_id()))) {
120     // If new process could not be opened, we return -1.
121     pid = -1;
122   }
123 
124   content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
125       base::Bind(&TerminalPrivateOpenTerminalProcessFunction::RespondOnUIThread,
126                  this, pid));
127 }
128 
~TerminalPrivateSendInputFunction()129 TerminalPrivateSendInputFunction::~TerminalPrivateSendInputFunction() {}
130 
RespondOnUIThread(pid_t pid)131 void TerminalPrivateOpenTerminalProcessFunction::RespondOnUIThread(pid_t pid) {
132   SetResult(new base::FundamentalValue(pid));
133   SendResponse(true);
134 }
135 
RunTerminalFunction()136 bool TerminalPrivateSendInputFunction::RunTerminalFunction() {
137   scoped_ptr<SendInput::Params> params(SendInput::Params::Create(*args_));
138   EXTENSION_FUNCTION_VALIDATE(params.get());
139 
140   // Registry lives on the FILE thread.
141   content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
142       base::Bind(&TerminalPrivateSendInputFunction::SendInputOnFileThread,
143                  this, params->pid, params->input));
144   return true;
145 }
146 
SendInputOnFileThread(pid_t pid,const std::string & text)147 void TerminalPrivateSendInputFunction::SendInputOnFileThread(pid_t pid,
148     const std::string& text) {
149   bool success = chromeos::ProcessProxyRegistry::Get()->SendInput(pid, text);
150 
151   content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
152       base::Bind(&TerminalPrivateSendInputFunction::RespondOnUIThread, this,
153       success));
154 }
155 
RespondOnUIThread(bool success)156 void TerminalPrivateSendInputFunction::RespondOnUIThread(bool success) {
157   SetResult(new base::FundamentalValue(success));
158   SendResponse(true);
159 }
160 
161 TerminalPrivateCloseTerminalProcessFunction::
~TerminalPrivateCloseTerminalProcessFunction()162     ~TerminalPrivateCloseTerminalProcessFunction() {}
163 
RunTerminalFunction()164 bool TerminalPrivateCloseTerminalProcessFunction::RunTerminalFunction() {
165   if (args_->GetSize() != 1)
166     return false;
167   pid_t pid;
168   if (!args_->GetInteger(0, &pid))
169     return false;
170 
171   // Registry lives on the FILE thread.
172   content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
173       base::Bind(&TerminalPrivateCloseTerminalProcessFunction::
174                  CloseOnFileThread, this, pid));
175 
176   return true;
177 }
178 
CloseOnFileThread(pid_t pid)179 void TerminalPrivateCloseTerminalProcessFunction::CloseOnFileThread(pid_t pid) {
180   bool success = chromeos::ProcessProxyRegistry::Get()->CloseProcess(pid);
181 
182   content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
183       base::Bind(&TerminalPrivateCloseTerminalProcessFunction::
184                  RespondOnUIThread, this, success));
185 }
186 
RespondOnUIThread(bool success)187 void TerminalPrivateCloseTerminalProcessFunction::RespondOnUIThread(
188     bool success) {
189   SetResult(new base::FundamentalValue(success));
190   SendResponse(true);
191 }
192 
193 TerminalPrivateOnTerminalResizeFunction::
~TerminalPrivateOnTerminalResizeFunction()194     ~TerminalPrivateOnTerminalResizeFunction() {}
195 
RunTerminalFunction()196 bool TerminalPrivateOnTerminalResizeFunction::RunTerminalFunction() {
197   scoped_ptr<OnTerminalResize::Params> params(
198       OnTerminalResize::Params::Create(*args_));
199   EXTENSION_FUNCTION_VALIDATE(params.get());
200 
201   // Registry lives on the FILE thread.
202   content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
203       base::Bind(&TerminalPrivateOnTerminalResizeFunction::OnResizeOnFileThread,
204                  this, params->pid, params->width, params->height));
205 
206   return true;
207 }
208 
OnResizeOnFileThread(pid_t pid,int width,int height)209 void TerminalPrivateOnTerminalResizeFunction::OnResizeOnFileThread(pid_t pid,
210                                                     int width, int height) {
211   bool success = chromeos::ProcessProxyRegistry::Get()->OnTerminalResize(
212       pid, width, height);
213 
214   content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
215       base::Bind(&TerminalPrivateOnTerminalResizeFunction::RespondOnUIThread,
216                  this, success));
217 }
218 
RespondOnUIThread(bool success)219 void TerminalPrivateOnTerminalResizeFunction::RespondOnUIThread(bool success) {
220   SetResult(new base::FundamentalValue(success));
221   SendResponse(true);
222 }
223 
224 }  // namespace extensions
225