Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / terminal / terminal_private_api.cc
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/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"
18
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;
25
26 namespace {
27
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";
32
33 const char* GetCroshPath() {
34   if (base::SysInfo::IsRunningOnChromeOS())
35     return kCroshCommand;
36   else
37     return kStubbedCroshCommand;
38 }
39
40 const char* GetProcessCommandForName(const std::string& name) {
41   if (name == kCroshName)
42     return GetCroshPath();
43   else
44     return NULL;
45 }
46
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;
57   }
58
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));
63
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());
69   }
70 }
71
72 }  // namespace
73
74 namespace extensions {
75
76 TerminalPrivateFunction::TerminalPrivateFunction() {}
77
78 TerminalPrivateFunction::~TerminalPrivateFunction() {}
79
80 bool TerminalPrivateFunction::RunAsync() {
81   return RunTerminalFunction();
82 }
83
84 TerminalPrivateOpenTerminalProcessFunction::
85     TerminalPrivateOpenTerminalProcessFunction() : command_(NULL) {}
86
87 TerminalPrivateOpenTerminalProcessFunction::
88     ~TerminalPrivateOpenTerminalProcessFunction() {}
89
90 bool TerminalPrivateOpenTerminalProcessFunction::RunTerminalFunction() {
91   scoped_ptr<OpenTerminalProcess::Params> params(
92       OpenTerminalProcess::Params::Create(*args_));
93   EXTENSION_FUNCTION_VALIDATE(params.get());
94
95   command_ = GetProcessCommandForName(params->process_name);
96   if (!command_) {
97     error_ = "Invalid process name.";
98     return false;
99   }
100
101   // Registry lives on FILE thread.
102   content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
103       base::Bind(&TerminalPrivateOpenTerminalProcessFunction::OpenOnFileThread,
104                  this));
105   return true;
106 }
107
108 void TerminalPrivateOpenTerminalProcessFunction::OpenOnFileThread() {
109   DCHECK(command_);
110
111   chromeos::ProcessProxyRegistry* registry =
112       chromeos::ProcessProxyRegistry::Get();
113   pid_t pid;
114   if (!registry->OpenProcess(
115            command_,
116            &pid,
117            base::Bind(&NotifyProcessOutput, GetProfile(), extension_id()))) {
118     // If new process could not be opened, we return -1.
119     pid = -1;
120   }
121
122   content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
123       base::Bind(&TerminalPrivateOpenTerminalProcessFunction::RespondOnUIThread,
124                  this, pid));
125 }
126
127 TerminalPrivateSendInputFunction::~TerminalPrivateSendInputFunction() {}
128
129 void TerminalPrivateOpenTerminalProcessFunction::RespondOnUIThread(pid_t pid) {
130   SetResult(new base::FundamentalValue(pid));
131   SendResponse(true);
132 }
133
134 bool TerminalPrivateSendInputFunction::RunTerminalFunction() {
135   scoped_ptr<SendInput::Params> params(SendInput::Params::Create(*args_));
136   EXTENSION_FUNCTION_VALIDATE(params.get());
137
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));
142   return true;
143 }
144
145 void TerminalPrivateSendInputFunction::SendInputOnFileThread(pid_t pid,
146     const std::string& text) {
147   bool success = chromeos::ProcessProxyRegistry::Get()->SendInput(pid, text);
148
149   content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
150       base::Bind(&TerminalPrivateSendInputFunction::RespondOnUIThread, this,
151       success));
152 }
153
154 void TerminalPrivateSendInputFunction::RespondOnUIThread(bool success) {
155   SetResult(new base::FundamentalValue(success));
156   SendResponse(true);
157 }
158
159 TerminalPrivateCloseTerminalProcessFunction::
160     ~TerminalPrivateCloseTerminalProcessFunction() {}
161
162 bool TerminalPrivateCloseTerminalProcessFunction::RunTerminalFunction() {
163   if (args_->GetSize() != 1)
164     return false;
165   pid_t pid;
166   if (!args_->GetInteger(0, &pid))
167     return false;
168
169   // Registry lives on the FILE thread.
170   content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
171       base::Bind(&TerminalPrivateCloseTerminalProcessFunction::
172                  CloseOnFileThread, this, pid));
173
174   return true;
175 }
176
177 void TerminalPrivateCloseTerminalProcessFunction::CloseOnFileThread(pid_t pid) {
178   bool success = chromeos::ProcessProxyRegistry::Get()->CloseProcess(pid);
179
180   content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
181       base::Bind(&TerminalPrivateCloseTerminalProcessFunction::
182                  RespondOnUIThread, this, success));
183 }
184
185 void TerminalPrivateCloseTerminalProcessFunction::RespondOnUIThread(
186     bool success) {
187   SetResult(new base::FundamentalValue(success));
188   SendResponse(true);
189 }
190
191 TerminalPrivateOnTerminalResizeFunction::
192     ~TerminalPrivateOnTerminalResizeFunction() {}
193
194 bool TerminalPrivateOnTerminalResizeFunction::RunTerminalFunction() {
195   scoped_ptr<OnTerminalResize::Params> params(
196       OnTerminalResize::Params::Create(*args_));
197   EXTENSION_FUNCTION_VALIDATE(params.get());
198
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));
203
204   return true;
205 }
206
207 void TerminalPrivateOnTerminalResizeFunction::OnResizeOnFileThread(pid_t pid,
208                                                     int width, int height) {
209   bool success = chromeos::ProcessProxyRegistry::Get()->OnTerminalResize(
210       pid, width, height);
211
212   content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
213       base::Bind(&TerminalPrivateOnTerminalResizeFunction::RespondOnUIThread,
214                  this, success));
215 }
216
217 void TerminalPrivateOnTerminalResizeFunction::RespondOnUIThread(bool success) {
218   SetResult(new base::FundamentalValue(success));
219   SendResponse(true);
220 }
221
222 }  // namespace extensions