| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "device/hid/hid_service_linux.h" | 5 #include "device/hid/hid_service_linux.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 |
| 9 #include <limits> | 10 #include <limits> |
| 11 #include <memory> |
| 10 #include <string> | 12 #include <string> |
| 11 #include <utility> | 13 #include <utility> |
| 12 | 14 |
| 13 #include "base/bind.h" | 15 #include "base/bind.h" |
| 14 #include "base/files/file.h" | 16 #include "base/files/file.h" |
| 15 #include "base/files/file_path.h" | 17 #include "base/files/file_path.h" |
| 16 #include "base/files/file_util.h" | 18 #include "base/files/file_util.h" |
| 17 #include "base/location.h" | 19 #include "base/location.h" |
| 18 #include "base/macros.h" | 20 #include "base/macros.h" |
| 19 #include "base/scoped_observer.h" | 21 #include "base/scoped_observer.h" |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 public: | 72 public: |
| 71 FileThreadHelper(base::WeakPtr<HidServiceLinux> service, | 73 FileThreadHelper(base::WeakPtr<HidServiceLinux> service, |
| 72 scoped_refptr<base::SingleThreadTaskRunner> task_runner) | 74 scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
| 73 : observer_(this), service_(service), task_runner_(task_runner) {} | 75 : observer_(this), service_(service), task_runner_(task_runner) {} |
| 74 | 76 |
| 75 ~FileThreadHelper() override { | 77 ~FileThreadHelper() override { |
| 76 DCHECK(thread_checker_.CalledOnValidThread()); | 78 DCHECK(thread_checker_.CalledOnValidThread()); |
| 77 base::MessageLoop::current()->RemoveDestructionObserver(this); | 79 base::MessageLoop::current()->RemoveDestructionObserver(this); |
| 78 } | 80 } |
| 79 | 81 |
| 80 static void Start(scoped_ptr<FileThreadHelper> self) { | 82 static void Start(std::unique_ptr<FileThreadHelper> self) { |
| 81 base::ThreadRestrictions::AssertIOAllowed(); | 83 base::ThreadRestrictions::AssertIOAllowed(); |
| 82 self->thread_checker_.DetachFromThread(); | 84 self->thread_checker_.DetachFromThread(); |
| 83 // |self| must be added as a destruction observer first so that it will be | 85 // |self| must be added as a destruction observer first so that it will be |
| 84 // notified before DeviceMonitorLinux. | 86 // notified before DeviceMonitorLinux. |
| 85 base::MessageLoop::current()->AddDestructionObserver(self.get()); | 87 base::MessageLoop::current()->AddDestructionObserver(self.get()); |
| 86 | 88 |
| 87 DeviceMonitorLinux* monitor = DeviceMonitorLinux::GetInstance(); | 89 DeviceMonitorLinux* monitor = DeviceMonitorLinux::GetInstance(); |
| 88 self->observer_.Add(monitor); | 90 self->observer_.Add(monitor); |
| 89 monitor->Enumerate(base::Bind(&FileThreadHelper::OnDeviceAdded, | 91 monitor->Enumerate(base::Bind(&FileThreadHelper::OnDeviceAdded, |
| 90 base::Unretained(self.get()))); | 92 base::Unretained(self.get()))); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 base::WeakPtr<HidServiceLinux> service_; | 206 base::WeakPtr<HidServiceLinux> service_; |
| 205 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 207 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| 206 | 208 |
| 207 DISALLOW_COPY_AND_ASSIGN(FileThreadHelper); | 209 DISALLOW_COPY_AND_ASSIGN(FileThreadHelper); |
| 208 }; | 210 }; |
| 209 | 211 |
| 210 HidServiceLinux::HidServiceLinux( | 212 HidServiceLinux::HidServiceLinux( |
| 211 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) | 213 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) |
| 212 : file_task_runner_(file_task_runner), weak_factory_(this) { | 214 : file_task_runner_(file_task_runner), weak_factory_(this) { |
| 213 task_runner_ = base::ThreadTaskRunnerHandle::Get(); | 215 task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| 214 scoped_ptr<FileThreadHelper> helper( | 216 std::unique_ptr<FileThreadHelper> helper( |
| 215 new FileThreadHelper(weak_factory_.GetWeakPtr(), task_runner_)); | 217 new FileThreadHelper(weak_factory_.GetWeakPtr(), task_runner_)); |
| 216 helper_ = helper.get(); | 218 helper_ = helper.get(); |
| 217 file_task_runner_->PostTask( | 219 file_task_runner_->PostTask( |
| 218 FROM_HERE, base::Bind(&FileThreadHelper::Start, base::Passed(&helper))); | 220 FROM_HERE, base::Bind(&FileThreadHelper::Start, base::Passed(&helper))); |
| 219 } | 221 } |
| 220 | 222 |
| 221 HidServiceLinux::~HidServiceLinux() { | 223 HidServiceLinux::~HidServiceLinux() { |
| 222 file_task_runner_->DeleteSoon(FROM_HERE, helper_); | 224 file_task_runner_->DeleteSoon(FROM_HERE, helper_); |
| 223 } | 225 } |
| 224 | 226 |
| 225 void HidServiceLinux::Connect(const HidDeviceId& device_id, | 227 void HidServiceLinux::Connect(const HidDeviceId& device_id, |
| 226 const ConnectCallback& callback) { | 228 const ConnectCallback& callback) { |
| 227 DCHECK(thread_checker_.CalledOnValidThread()); | 229 DCHECK(thread_checker_.CalledOnValidThread()); |
| 228 | 230 |
| 229 const auto& map_entry = devices().find(device_id); | 231 const auto& map_entry = devices().find(device_id); |
| 230 if (map_entry == devices().end()) { | 232 if (map_entry == devices().end()) { |
| 231 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); | 233 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); |
| 232 return; | 234 return; |
| 233 } | 235 } |
| 234 scoped_refptr<HidDeviceInfoLinux> device_info = | 236 scoped_refptr<HidDeviceInfoLinux> device_info = |
| 235 static_cast<HidDeviceInfoLinux*>(map_entry->second.get()); | 237 static_cast<HidDeviceInfoLinux*>(map_entry->second.get()); |
| 236 | 238 |
| 237 scoped_ptr<ConnectParams> params(new ConnectParams( | 239 std::unique_ptr<ConnectParams> params(new ConnectParams( |
| 238 device_info, callback, task_runner_, file_task_runner_)); | 240 device_info, callback, task_runner_, file_task_runner_)); |
| 239 | 241 |
| 240 #if defined(OS_CHROMEOS) | 242 #if defined(OS_CHROMEOS) |
| 241 chromeos::PermissionBrokerClient* client = | 243 chromeos::PermissionBrokerClient* client = |
| 242 chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient(); | 244 chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient(); |
| 243 DCHECK(client) << "Could not get permission broker client."; | 245 DCHECK(client) << "Could not get permission broker client."; |
| 244 chromeos::PermissionBrokerClient::ErrorCallback error_callback = | 246 chromeos::PermissionBrokerClient::ErrorCallback error_callback = |
| 245 base::Bind(&HidServiceLinux::OnPathOpenError, | 247 base::Bind(&HidServiceLinux::OnPathOpenError, |
| 246 params->device_info->device_node(), params->callback); | 248 params->device_info->device_node(), params->callback); |
| 247 client->OpenPath( | 249 client->OpenPath( |
| 248 device_info->device_node(), | 250 device_info->device_node(), |
| 249 base::Bind(&HidServiceLinux::OnPathOpenComplete, base::Passed(¶ms)), | 251 base::Bind(&HidServiceLinux::OnPathOpenComplete, base::Passed(¶ms)), |
| 250 error_callback); | 252 error_callback); |
| 251 #else | 253 #else |
| 252 file_task_runner_->PostTask(FROM_HERE, | 254 file_task_runner_->PostTask(FROM_HERE, |
| 253 base::Bind(&HidServiceLinux::OpenOnBlockingThread, | 255 base::Bind(&HidServiceLinux::OpenOnBlockingThread, |
| 254 base::Passed(¶ms))); | 256 base::Passed(¶ms))); |
| 255 #endif // defined(OS_CHROMEOS) | 257 #endif // defined(OS_CHROMEOS) |
| 256 } | 258 } |
| 257 | 259 |
| 258 #if defined(OS_CHROMEOS) | 260 #if defined(OS_CHROMEOS) |
| 259 | 261 |
| 260 // static | 262 // static |
| 261 void HidServiceLinux::OnPathOpenComplete(scoped_ptr<ConnectParams> params, | 263 void HidServiceLinux::OnPathOpenComplete(std::unique_ptr<ConnectParams> params, |
| 262 dbus::FileDescriptor fd) { | 264 dbus::FileDescriptor fd) { |
| 263 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner = | 265 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner = |
| 264 params->file_task_runner; | 266 params->file_task_runner; |
| 265 file_task_runner->PostTask( | 267 file_task_runner->PostTask( |
| 266 FROM_HERE, base::Bind(&HidServiceLinux::ValidateFdOnBlockingThread, | 268 FROM_HERE, base::Bind(&HidServiceLinux::ValidateFdOnBlockingThread, |
| 267 base::Passed(¶ms), base::Passed(&fd))); | 269 base::Passed(¶ms), base::Passed(&fd))); |
| 268 } | 270 } |
| 269 | 271 |
| 270 // static | 272 // static |
| 271 void HidServiceLinux::OnPathOpenError(const std::string& device_path, | 273 void HidServiceLinux::OnPathOpenError(const std::string& device_path, |
| 272 const ConnectCallback& callback, | 274 const ConnectCallback& callback, |
| 273 const std::string& error_name, | 275 const std::string& error_name, |
| 274 const std::string& error_message) { | 276 const std::string& error_message) { |
| 275 HID_LOG(EVENT) << "Permission broker failed to open '" << device_path | 277 HID_LOG(EVENT) << "Permission broker failed to open '" << device_path |
| 276 << "': " << error_name << ": " << error_message; | 278 << "': " << error_name << ": " << error_message; |
| 277 callback.Run(nullptr); | 279 callback.Run(nullptr); |
| 278 } | 280 } |
| 279 | 281 |
| 280 // static | 282 // static |
| 281 void HidServiceLinux::ValidateFdOnBlockingThread( | 283 void HidServiceLinux::ValidateFdOnBlockingThread( |
| 282 scoped_ptr<ConnectParams> params, | 284 std::unique_ptr<ConnectParams> params, |
| 283 dbus::FileDescriptor fd) { | 285 dbus::FileDescriptor fd) { |
| 284 base::ThreadRestrictions::AssertIOAllowed(); | 286 base::ThreadRestrictions::AssertIOAllowed(); |
| 285 fd.CheckValidity(); | 287 fd.CheckValidity(); |
| 286 DCHECK(fd.is_valid()); | 288 DCHECK(fd.is_valid()); |
| 287 params->device_file = base::File(fd.TakeValue()); | 289 params->device_file = base::File(fd.TakeValue()); |
| 288 FinishOpen(std::move(params)); | 290 FinishOpen(std::move(params)); |
| 289 } | 291 } |
| 290 | 292 |
| 291 #else | 293 #else |
| 292 | 294 |
| 293 // static | 295 // static |
| 294 void HidServiceLinux::OpenOnBlockingThread(scoped_ptr<ConnectParams> params) { | 296 void HidServiceLinux::OpenOnBlockingThread( |
| 297 std::unique_ptr<ConnectParams> params) { |
| 295 base::ThreadRestrictions::AssertIOAllowed(); | 298 base::ThreadRestrictions::AssertIOAllowed(); |
| 296 scoped_refptr<base::SingleThreadTaskRunner> task_runner = params->task_runner; | 299 scoped_refptr<base::SingleThreadTaskRunner> task_runner = params->task_runner; |
| 297 | 300 |
| 298 base::FilePath device_path(params->device_info->device_node()); | 301 base::FilePath device_path(params->device_info->device_node()); |
| 299 base::File& device_file = params->device_file; | 302 base::File& device_file = params->device_file; |
| 300 int flags = | 303 int flags = |
| 301 base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE; | 304 base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE; |
| 302 device_file.Initialize(device_path, flags); | 305 device_file.Initialize(device_path, flags); |
| 303 if (!device_file.IsValid()) { | 306 if (!device_file.IsValid()) { |
| 304 base::File::Error file_error = device_file.error_details(); | 307 base::File::Error file_error = device_file.error_details(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 317 task_runner->PostTask(FROM_HERE, base::Bind(params->callback, nullptr)); | 320 task_runner->PostTask(FROM_HERE, base::Bind(params->callback, nullptr)); |
| 318 return; | 321 return; |
| 319 } | 322 } |
| 320 | 323 |
| 321 FinishOpen(std::move(params)); | 324 FinishOpen(std::move(params)); |
| 322 } | 325 } |
| 323 | 326 |
| 324 #endif // defined(OS_CHROMEOS) | 327 #endif // defined(OS_CHROMEOS) |
| 325 | 328 |
| 326 // static | 329 // static |
| 327 void HidServiceLinux::FinishOpen(scoped_ptr<ConnectParams> params) { | 330 void HidServiceLinux::FinishOpen(std::unique_ptr<ConnectParams> params) { |
| 328 base::ThreadRestrictions::AssertIOAllowed(); | 331 base::ThreadRestrictions::AssertIOAllowed(); |
| 329 scoped_refptr<base::SingleThreadTaskRunner> task_runner = params->task_runner; | 332 scoped_refptr<base::SingleThreadTaskRunner> task_runner = params->task_runner; |
| 330 | 333 |
| 331 if (!base::SetNonBlocking(params->device_file.GetPlatformFile())) { | 334 if (!base::SetNonBlocking(params->device_file.GetPlatformFile())) { |
| 332 HID_PLOG(ERROR) << "Failed to set the non-blocking flag on the device fd"; | 335 HID_PLOG(ERROR) << "Failed to set the non-blocking flag on the device fd"; |
| 333 task_runner->PostTask(FROM_HERE, base::Bind(params->callback, nullptr)); | 336 task_runner->PostTask(FROM_HERE, base::Bind(params->callback, nullptr)); |
| 334 return; | 337 return; |
| 335 } | 338 } |
| 336 | 339 |
| 337 task_runner->PostTask( | 340 task_runner->PostTask( |
| 338 FROM_HERE, | 341 FROM_HERE, |
| 339 base::Bind(&HidServiceLinux::CreateConnection, base::Passed(¶ms))); | 342 base::Bind(&HidServiceLinux::CreateConnection, base::Passed(¶ms))); |
| 340 } | 343 } |
| 341 | 344 |
| 342 // static | 345 // static |
| 343 void HidServiceLinux::CreateConnection(scoped_ptr<ConnectParams> params) { | 346 void HidServiceLinux::CreateConnection(std::unique_ptr<ConnectParams> params) { |
| 344 DCHECK(params->device_file.IsValid()); | 347 DCHECK(params->device_file.IsValid()); |
| 345 params->callback.Run(make_scoped_refptr(new HidConnectionLinux( | 348 params->callback.Run(make_scoped_refptr(new HidConnectionLinux( |
| 346 params->device_info, std::move(params->device_file), | 349 params->device_info, std::move(params->device_file), |
| 347 params->file_task_runner))); | 350 params->file_task_runner))); |
| 348 } | 351 } |
| 349 | 352 |
| 350 } // namespace device | 353 } // namespace device |
| OLD | NEW |