OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "extensions/browser/api/usb/usb_event_router.h" | 5 #include "extensions/browser/api/usb/usb_event_router.h" |
6 | 6 |
7 #include "device/core/device_client.h" | 7 #include "device/core/device_client.h" |
8 #include "device/usb/usb_device.h" | 8 #include "device/usb/usb_device.h" |
9 #include "device/usb/usb_service.h" | |
10 #include "extensions/browser/api/device_permissions_manager.h" | 9 #include "extensions/browser/api/device_permissions_manager.h" |
11 #include "extensions/common/api/usb.h" | 10 #include "extensions/common/api/usb.h" |
12 #include "extensions/common/permissions/permissions_data.h" | 11 #include "extensions/common/permissions/permissions_data.h" |
13 #include "extensions/common/permissions/usb_device_permission.h" | 12 #include "extensions/common/permissions/usb_device_permission.h" |
14 | 13 |
15 namespace usb = extensions::core_api::usb; | 14 namespace usb = extensions::core_api::usb; |
16 | 15 |
17 using content::BrowserThread; | 16 using content::BrowserThread; |
18 using device::UsbDevice; | 17 using device::UsbDevice; |
19 using device::UsbService; | 18 using device::UsbService; |
20 | 19 |
21 namespace extensions { | 20 namespace extensions { |
22 | 21 |
23 namespace { | 22 namespace { |
24 | 23 |
25 // Returns true iff the given extension has permission to receive events | 24 // Returns true iff the given extension has permission to receive events |
26 // regarding this device. | 25 // regarding this device. |
27 bool WillDispatchDeviceEvent(scoped_refptr<UsbDevice> device, | 26 bool WillDispatchDeviceEvent(scoped_refptr<UsbDevice> device, |
28 const base::string16& serial_number, | |
29 content::BrowserContext* browser_context, | 27 content::BrowserContext* browser_context, |
30 const Extension* extension, | 28 const Extension* extension, |
31 base::ListValue* event_args) { | 29 base::ListValue* event_args) { |
32 // Check install-time and optional permissions. | 30 // Check install-time and optional permissions. |
33 UsbDevicePermission::CheckParam param( | 31 UsbDevicePermission::CheckParam param( |
34 device->vendor_id(), device->product_id(), | 32 device->vendor_id(), device->product_id(), |
35 UsbDevicePermissionData::UNSPECIFIED_INTERFACE); | 33 UsbDevicePermissionData::UNSPECIFIED_INTERFACE); |
36 if (extension->permissions_data()->CheckAPIPermissionWithParam( | 34 if (extension->permissions_data()->CheckAPIPermissionWithParam( |
37 APIPermission::kUsbDevice, ¶m)) { | 35 APIPermission::kUsbDevice, ¶m)) { |
38 return true; | 36 return true; |
39 } | 37 } |
40 | 38 |
41 // Check permissions granted through chrome.usb.getUserSelectedDevices. | 39 // Check permissions granted through chrome.usb.getUserSelectedDevices. |
42 scoped_ptr<DevicePermissions> device_permissions = | 40 DevicePermissions* device_permissions = |
43 DevicePermissionsManager::Get(browser_context) | 41 DevicePermissionsManager::Get(browser_context) |
44 ->GetForExtension(extension->id()); | 42 ->GetForExtension(extension->id()); |
45 if (device_permissions->FindEntry(device, serial_number).get()) { | 43 if (device_permissions->FindEntry(device).get()) { |
46 return true; | 44 return true; |
47 } | 45 } |
48 | 46 |
49 return false; | 47 return false; |
50 } | 48 } |
51 | 49 |
52 base::LazyInstance<BrowserContextKeyedAPIFactory<UsbEventRouter>>::Leaky | 50 base::LazyInstance<BrowserContextKeyedAPIFactory<UsbEventRouter>>::Leaky |
53 g_event_router_factory = LAZY_INSTANCE_INITIALIZER; | 51 g_event_router_factory = LAZY_INSTANCE_INITIALIZER; |
54 | 52 |
55 } // namespace | 53 } // namespace |
56 | 54 |
57 class UsbEventRouter::FileThreadHelper : public UsbService::Observer { | |
58 public: | |
59 FileThreadHelper(base::WeakPtr<UsbEventRouter> usb_event_router) | |
60 : usb_event_router_(usb_event_router), observer_(this) {} | |
61 virtual ~FileThreadHelper() {} | |
62 | |
63 void Start() { | |
64 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | |
65 UsbService* service = device::DeviceClient::Get()->GetUsbService(); | |
66 if (service) { | |
67 observer_.Add(service); | |
68 } | |
69 } | |
70 | |
71 private: | |
72 // UsbService::Observer implementation. | |
73 void OnDeviceAdded(scoped_refptr<device::UsbDevice> device) override { | |
74 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | |
75 | |
76 base::string16 serial_number; | |
77 device->GetSerialNumber(&serial_number); | |
78 | |
79 BrowserThread::PostTask( | |
80 BrowserThread::UI, FROM_HERE, | |
81 base::Bind(&UsbEventRouter::DispatchEvent, usb_event_router_, | |
82 usb::OnDeviceAdded::kEventName, device, serial_number)); | |
83 } | |
84 | |
85 void OnDeviceRemoved(scoped_refptr<device::UsbDevice> device) override { | |
86 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | |
87 | |
88 base::string16 serial_number; | |
89 device->GetSerialNumber(&serial_number); | |
90 | |
91 BrowserThread::PostTask( | |
92 BrowserThread::UI, FROM_HERE, | |
93 base::Bind(&UsbEventRouter::DispatchEvent, usb_event_router_, | |
94 usb::OnDeviceRemoved::kEventName, device, serial_number)); | |
95 } | |
96 | |
97 base::WeakPtr<UsbEventRouter> usb_event_router_; | |
98 ScopedObserver<device::UsbService, device::UsbService::Observer> observer_; | |
99 }; | |
100 | |
101 // static | 55 // static |
102 BrowserContextKeyedAPIFactory<UsbEventRouter>* | 56 BrowserContextKeyedAPIFactory<UsbEventRouter>* |
103 UsbEventRouter::GetFactoryInstance() { | 57 UsbEventRouter::GetFactoryInstance() { |
104 return g_event_router_factory.Pointer(); | 58 return g_event_router_factory.Pointer(); |
105 } | 59 } |
106 | 60 |
107 UsbEventRouter::UsbEventRouter(content::BrowserContext* browser_context) | 61 UsbEventRouter::UsbEventRouter(content::BrowserContext* browser_context) |
108 : browser_context_(browser_context), weak_factory_(this) { | 62 : browser_context_(browser_context), observer_(this) { |
109 EventRouter* event_router = EventRouter::Get(browser_context_); | 63 EventRouter* event_router = EventRouter::Get(browser_context_); |
110 if (event_router) { | 64 if (event_router) { |
111 event_router->RegisterObserver(this, usb::OnDeviceAdded::kEventName); | 65 event_router->RegisterObserver(this, usb::OnDeviceAdded::kEventName); |
112 event_router->RegisterObserver(this, usb::OnDeviceRemoved::kEventName); | 66 event_router->RegisterObserver(this, usb::OnDeviceRemoved::kEventName); |
113 } | 67 } |
114 } | 68 } |
115 | 69 |
116 UsbEventRouter::~UsbEventRouter() { | 70 UsbEventRouter::~UsbEventRouter() { |
117 } | 71 } |
118 | 72 |
119 void UsbEventRouter::Shutdown() { | 73 void UsbEventRouter::Shutdown() { |
120 EventRouter* event_router = EventRouter::Get(browser_context_); | 74 EventRouter* event_router = EventRouter::Get(browser_context_); |
121 if (event_router) { | 75 if (event_router) { |
122 event_router->UnregisterObserver(this); | 76 event_router->UnregisterObserver(this); |
123 } | 77 } |
124 helper_.reset(nullptr); | |
125 } | 78 } |
126 | 79 |
127 void UsbEventRouter::OnListenerAdded(const EventListenerInfo& details) { | 80 void UsbEventRouter::OnListenerAdded(const EventListenerInfo& details) { |
128 if (!helper_) { | 81 UsbService* service = device::DeviceClient::Get()->GetUsbService(); |
129 helper_.reset(new FileThreadHelper(weak_factory_.GetWeakPtr())); | 82 if (!observer_.IsObserving(service)) { |
130 BrowserThread::PostTask( | 83 observer_.Add(service); |
131 BrowserThread::FILE, FROM_HERE, | |
132 base::Bind(&FileThreadHelper::Start, base::Unretained(helper_.get()))); | |
133 } | 84 } |
134 } | 85 } |
135 | 86 |
| 87 void UsbEventRouter::OnDeviceAdded(scoped_refptr<device::UsbDevice> device) { |
| 88 DispatchEvent(usb::OnDeviceAdded::kEventName, device); |
| 89 } |
| 90 |
| 91 void UsbEventRouter::OnDeviceRemoved(scoped_refptr<device::UsbDevice> device) { |
| 92 DispatchEvent(usb::OnDeviceRemoved::kEventName, device); |
| 93 } |
| 94 |
136 void UsbEventRouter::DispatchEvent(const std::string& event_name, | 95 void UsbEventRouter::DispatchEvent(const std::string& event_name, |
137 scoped_refptr<UsbDevice> device, | 96 scoped_refptr<UsbDevice> device) { |
138 const base::string16& serial_number) { | 97 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
139 EventRouter* event_router = EventRouter::Get(browser_context_); | 98 EventRouter* event_router = EventRouter::Get(browser_context_); |
140 if (event_router) { | 99 if (event_router) { |
141 usb::Device device_obj; | 100 usb::Device device_obj; |
142 device_obj.device = device->unique_id(); | 101 device_obj.device = device->unique_id(); |
143 device_obj.vendor_id = device->vendor_id(); | 102 device_obj.vendor_id = device->vendor_id(); |
144 device_obj.product_id = device->product_id(); | 103 device_obj.product_id = device->product_id(); |
145 | 104 |
146 scoped_ptr<Event> event; | 105 scoped_ptr<Event> event; |
147 if (event_name == usb::OnDeviceAdded::kEventName) { | 106 if (event_name == usb::OnDeviceAdded::kEventName) { |
148 event.reset(new Event(usb::OnDeviceAdded::kEventName, | 107 event.reset(new Event(usb::OnDeviceAdded::kEventName, |
149 usb::OnDeviceAdded::Create(device_obj))); | 108 usb::OnDeviceAdded::Create(device_obj))); |
150 } else { | 109 } else { |
151 DCHECK(event_name == usb::OnDeviceRemoved::kEventName); | 110 DCHECK(event_name == usb::OnDeviceRemoved::kEventName); |
152 event.reset(new Event(usb::OnDeviceRemoved::kEventName, | 111 event.reset(new Event(usb::OnDeviceRemoved::kEventName, |
153 usb::OnDeviceRemoved::Create(device_obj))); | 112 usb::OnDeviceRemoved::Create(device_obj))); |
154 } | 113 } |
155 | 114 |
156 event->will_dispatch_callback = | 115 event->will_dispatch_callback = |
157 base::Bind(&WillDispatchDeviceEvent, device, serial_number); | 116 base::Bind(&WillDispatchDeviceEvent, device); |
158 event_router->BroadcastEvent(event.Pass()); | 117 event_router->BroadcastEvent(event.Pass()); |
159 } | 118 } |
160 } | 119 } |
161 | 120 |
162 } // extensions | 121 } // extensions |
OLD | NEW |