Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / chromeos / system / input_device_settings.cc
blobe92b31adb18df975a0bddb98301537e173da4e85
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/chromeos/system/input_device_settings.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/process/kill.h"
14 #include "base/process/launch.h"
15 #include "base/process/process_handle.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/sys_info.h"
19 #include "base/task_runner.h"
20 #include "base/threading/sequenced_worker_pool.h"
21 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
23 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
24 #include "chrome/common/pref_names.h"
25 #include "chromeos/system/statistics_provider.h"
26 #include "content/public/browser/browser_thread.h"
28 namespace chromeos {
29 namespace system {
31 namespace {
33 InputDeviceSettings* g_instance_;
34 InputDeviceSettings* g_test_instance_;
36 const char kDeviceTypeTouchpad[] = "touchpad";
37 const char kDeviceTypeMouse[] = "mouse";
38 const char kInputControl[] = "/opt/google/input/inputcontrol";
40 const char kRemoraRequisition[] = "remora";
42 typedef base::RefCountedData<bool> RefCountedBool;
44 bool ScriptExists(const std::string& script) {
45 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
46 return base::PathExists(base::FilePath(script));
49 // Executes the input control script asynchronously, if it exists.
50 void ExecuteScriptOnFileThread(const std::vector<std::string>& argv) {
51 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
52 DCHECK(!argv.empty());
53 const std::string& script(argv[0]);
55 // Script must exist on device.
56 DCHECK(!base::SysInfo::IsRunningOnChromeOS() || ScriptExists(script));
58 if (!ScriptExists(script))
59 return;
61 base::ProcessHandle handle;
62 base::LaunchProcess(CommandLine(argv), base::LaunchOptions(), &handle);
63 base::EnsureProcessGetsReaped(handle);
66 void ExecuteScript(const std::vector<std::string>& argv) {
67 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
69 if (argv.size() == 1)
70 return;
72 VLOG(1) << "About to launch: \""
73 << CommandLine(argv).GetCommandLineString() << "\"";
75 // Control scripts can take long enough to cause SIGART during shutdown
76 // (http://crbug.com/261426). Run the blocking pool task with
77 // CONTINUE_ON_SHUTDOWN so it won't be joined when Chrome shuts down.
78 base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
79 scoped_refptr<base::TaskRunner> runner =
80 pool->GetTaskRunnerWithShutdownBehavior(
81 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
82 runner->PostTask(FROM_HERE, base::Bind(&ExecuteScriptOnFileThread, argv));
85 void AddSensitivityArguments(const char* device_type, int value,
86 std::vector<std::string>* argv) {
87 DCHECK(value >= kMinPointerSensitivity && value <= kMaxPointerSensitivity);
88 argv->push_back(base::StringPrintf("--%s_sensitivity=%d",
89 device_type, value));
92 void AddTPControlArguments(const char* control,
93 bool enabled,
94 std::vector<std::string>* argv) {
95 argv->push_back(base::StringPrintf("--%s=%d", control, enabled ? 1 : 0));
98 void DeviceExistsBlockingPool(const char* device_type,
99 scoped_refptr<RefCountedBool> exists) {
100 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
101 exists->data = false;
102 if (!ScriptExists(kInputControl))
103 return;
105 std::vector<std::string> argv;
106 argv.push_back(kInputControl);
107 argv.push_back(base::StringPrintf("--type=%s", device_type));
108 argv.push_back("--list");
109 std::string output;
110 // Output is empty if the device is not found.
111 exists->data = base::GetAppOutput(CommandLine(argv), &output) &&
112 !output.empty();
113 DVLOG(1) << "DeviceExistsBlockingPool:" << device_type << "=" << exists->data;
116 void RunCallbackUIThread(
117 scoped_refptr<RefCountedBool> exists,
118 const InputDeviceSettings::DeviceExistsCallback& callback) {
119 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
120 DVLOG(1) << "RunCallbackUIThread " << exists->data;
121 callback.Run(exists->data);
124 void DeviceExists(const char* script,
125 const InputDeviceSettings::DeviceExistsCallback& callback) {
126 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
128 // One or both of the control scripts can apparently hang during shutdown
129 // (http://crbug.com/255546). Run the blocking pool task with
130 // CONTINUE_ON_SHUTDOWN so it won't be joined when Chrome shuts down.
131 scoped_refptr<RefCountedBool> exists(new RefCountedBool(false));
132 base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
133 scoped_refptr<base::TaskRunner> runner =
134 pool->GetTaskRunnerWithShutdownBehavior(
135 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
136 runner->PostTaskAndReply(FROM_HERE,
137 base::Bind(&DeviceExistsBlockingPool, script, exists),
138 base::Bind(&RunCallbackUIThread, exists, callback));
141 class InputDeviceSettingsImpl : public InputDeviceSettings {
142 public:
143 InputDeviceSettingsImpl();
145 private:
146 // Overridden from InputDeviceSettings.
147 virtual void TouchpadExists(const DeviceExistsCallback& callback) OVERRIDE;
148 virtual void UpdateTouchpadSettings(const TouchpadSettings& settings)
149 OVERRIDE;
150 virtual void SetTouchpadSensitivity(int value) OVERRIDE;
151 virtual void SetTapToClick(bool enabled) OVERRIDE;
152 virtual void SetThreeFingerClick(bool enabled) OVERRIDE;
153 virtual void SetTapDragging(bool enabled) OVERRIDE;
154 virtual void SetNaturalScroll(bool enabled) OVERRIDE;
155 virtual void MouseExists(const DeviceExistsCallback& callback) OVERRIDE;
156 virtual void UpdateMouseSettings(const MouseSettings& update) OVERRIDE;
157 virtual void SetMouseSensitivity(int value) OVERRIDE;
158 virtual void SetPrimaryButtonRight(bool right) OVERRIDE;
159 virtual bool ForceKeyboardDrivenUINavigation() OVERRIDE;
160 virtual void ReapplyTouchpadSettings() OVERRIDE;
161 virtual void ReapplyMouseSettings() OVERRIDE;
163 private:
164 TouchpadSettings current_touchpad_settings_;
165 MouseSettings current_mouse_settings_;
167 DISALLOW_COPY_AND_ASSIGN(InputDeviceSettingsImpl);
170 InputDeviceSettingsImpl::InputDeviceSettingsImpl() {}
172 void InputDeviceSettingsImpl::TouchpadExists(
173 const DeviceExistsCallback& callback) {
174 DeviceExists(kDeviceTypeTouchpad, callback);
177 void InputDeviceSettingsImpl::UpdateTouchpadSettings(
178 const TouchpadSettings& settings) {
179 std::vector<std::string> argv;
180 if (current_touchpad_settings_.Update(settings, &argv))
181 ExecuteScript(argv);
184 void InputDeviceSettingsImpl::SetTouchpadSensitivity(int value) {
185 TouchpadSettings settings;
186 settings.SetSensitivity(value);
187 UpdateTouchpadSettings(settings);
190 void InputDeviceSettingsImpl::SetNaturalScroll(bool enabled) {
191 TouchpadSettings settings;
192 settings.SetNaturalScroll(enabled);
193 UpdateTouchpadSettings(settings);
196 void InputDeviceSettingsImpl::SetTapToClick(bool enabled) {
197 TouchpadSettings settings;
198 settings.SetTapToClick(enabled);
199 UpdateTouchpadSettings(settings);
202 void InputDeviceSettingsImpl::SetThreeFingerClick(bool enabled) {
203 // For Alex/ZGB.
204 TouchpadSettings settings;
205 settings.SetThreeFingerClick(enabled);
206 UpdateTouchpadSettings(settings);
209 void InputDeviceSettingsImpl::SetTapDragging(bool enabled) {
210 TouchpadSettings settings;
211 settings.SetTapDragging(enabled);
212 UpdateTouchpadSettings(settings);
215 void InputDeviceSettingsImpl::MouseExists(
216 const DeviceExistsCallback& callback) {
217 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
218 DeviceExists(kDeviceTypeMouse, callback);
221 void InputDeviceSettingsImpl::UpdateMouseSettings(const MouseSettings& update) {
222 std::vector<std::string> argv;
223 if (current_mouse_settings_.Update(update, &argv))
224 ExecuteScript(argv);
227 void InputDeviceSettingsImpl::SetMouseSensitivity(int value) {
228 MouseSettings settings;
229 settings.SetSensitivity(value);
230 UpdateMouseSettings(settings);
233 void InputDeviceSettingsImpl::SetPrimaryButtonRight(bool right) {
234 MouseSettings settings;
235 settings.SetPrimaryButtonRight(right);
236 UpdateMouseSettings(settings);
239 bool InputDeviceSettingsImpl::ForceKeyboardDrivenUINavigation() {
240 policy::BrowserPolicyConnectorChromeOS* connector =
241 g_browser_process->platform_part()->browser_policy_connector_chromeos();
242 if (!connector)
243 return false;
245 policy::DeviceCloudPolicyManagerChromeOS* policy_manager =
246 connector->GetDeviceCloudPolicyManager();
247 if (!policy_manager)
248 return false;
250 if (base::strcasecmp(policy_manager->GetDeviceRequisition().c_str(),
251 kRemoraRequisition) == 0) {
252 return true;
255 bool keyboard_driven = false;
256 if (chromeos::system::StatisticsProvider::GetInstance()->GetMachineFlag(
257 kOemKeyboardDrivenOobeKey, &keyboard_driven)) {
258 return keyboard_driven;
261 return false;
264 void InputDeviceSettingsImpl::ReapplyTouchpadSettings() {
265 TouchpadSettings settings = current_touchpad_settings_;
266 current_touchpad_settings_ = TouchpadSettings();
267 UpdateTouchpadSettings(settings);
270 void InputDeviceSettingsImpl::ReapplyMouseSettings() {
271 MouseSettings settings = current_mouse_settings_;
272 current_mouse_settings_ = MouseSettings();
273 UpdateMouseSettings(settings);
276 } // namespace
278 TouchpadSettings::TouchpadSettings() {}
280 TouchpadSettings& TouchpadSettings::operator=(const TouchpadSettings& other) {
281 if (&other != this) {
282 sensitivity_ = other.sensitivity_;
283 tap_to_click_ = other.tap_to_click_;
284 three_finger_click_ = other.three_finger_click_;
285 tap_dragging_ = other.tap_dragging_;
286 natural_scroll_ = other.natural_scroll_;
288 return *this;
291 void TouchpadSettings::SetSensitivity(int value) {
292 sensitivity_.Set(value);
295 int TouchpadSettings::GetSensitivity() const {
296 return sensitivity_.value();
299 void TouchpadSettings::SetTapToClick(bool enabled) {
300 tap_to_click_.Set(enabled);
303 bool TouchpadSettings::GetTapToClick() const {
304 return tap_to_click_.value();
307 void TouchpadSettings::SetNaturalScroll(bool enabled) {
308 natural_scroll_.Set(enabled);
311 bool TouchpadSettings::GetNaturalScroll() const {
312 return natural_scroll_.value();
315 void TouchpadSettings::SetThreeFingerClick(bool enabled) {
316 three_finger_click_.Set(enabled);
319 bool TouchpadSettings::GetThreeFingerClick() const {
320 return three_finger_click_.value();
323 void TouchpadSettings::SetTapDragging(bool enabled) {
324 tap_dragging_.Set(enabled);
327 bool TouchpadSettings::GetTapDragging() const {
328 return tap_dragging_.value();
331 bool TouchpadSettings::Update(const TouchpadSettings& settings,
332 std::vector<std::string>* argv) {
333 if (argv)
334 argv->push_back(kInputControl);
335 bool updated = false;
336 if (sensitivity_.Update(settings.sensitivity_)) {
337 updated = true;
338 if (argv)
339 AddSensitivityArguments(kDeviceTypeTouchpad, sensitivity_.value(), argv);
341 if (tap_to_click_.Update(settings.tap_to_click_)) {
342 updated = true;
343 if (argv)
344 AddTPControlArguments("tapclick", tap_to_click_.value(), argv);
346 if (three_finger_click_.Update(settings.three_finger_click_)) {
347 updated = true;
348 if (argv)
349 AddTPControlArguments("t5r2_three_finger_click",
350 three_finger_click_.value(),
351 argv);
353 if (tap_dragging_.Update(settings.tap_dragging_)) {
354 updated = true;
355 if (argv)
356 AddTPControlArguments("tapdrag", tap_dragging_.value(), argv);
358 if (natural_scroll_.Update(settings.natural_scroll_)) {
359 updated = true;
360 if (argv)
361 AddTPControlArguments("australian_scrolling", natural_scroll_.value(),
362 argv);
364 return updated;
367 MouseSettings::MouseSettings() {}
369 MouseSettings& MouseSettings::operator=(const MouseSettings& other) {
370 if (&other != this) {
371 sensitivity_ = other.sensitivity_;
372 primary_button_right_ = other.primary_button_right_;
374 return *this;
377 void MouseSettings::SetSensitivity(int value) {
378 sensitivity_.Set(value);
381 int MouseSettings::GetSensitivity() const {
382 return sensitivity_.value();
385 void MouseSettings::SetPrimaryButtonRight(bool right) {
386 primary_button_right_.Set(right);
389 bool MouseSettings::GetPrimaryButtonRight() const {
390 return primary_button_right_.value();
393 bool MouseSettings::Update(const MouseSettings& settings,
394 std::vector<std::string>* argv) {
395 if (argv)
396 argv->push_back(kInputControl);
397 bool updated = false;
398 if (sensitivity_.Update(settings.sensitivity_)) {
399 updated = true;
400 if (argv)
401 AddSensitivityArguments(kDeviceTypeMouse, sensitivity_.value(), argv);
403 if (primary_button_right_.Update(settings.primary_button_right_)) {
404 updated = true;
405 if (argv) {
406 AddTPControlArguments("mouse_swap_lr", primary_button_right_.value(),
407 argv);
410 return updated;
413 // static
414 InputDeviceSettings* InputDeviceSettings::Get() {
415 if (g_test_instance_)
416 return g_test_instance_;
417 if (!g_instance_)
418 g_instance_ = new InputDeviceSettingsImpl;
419 return g_instance_;
422 // static
423 void InputDeviceSettings::SetSettingsForTesting(
424 InputDeviceSettings* test_settings) {
425 if (g_test_instance_ == test_settings)
426 return;
427 delete g_test_instance_;
428 g_test_instance_ = test_settings;
431 } // namespace system
432 } // namespace chromeos