Unregister from GCM when the only GCM app is removed
[chromium-blink-merge.git] / extensions / browser / api / usb / usb_event_router.cc
blob93fff3fab3f25700a5f0d275c233d611a6bbefab
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
3 // found in the LICENSE file.
5 #include "extensions/browser/api/usb/usb_event_router.h"
7 #include "device/core/device_client.h"
8 #include "device/usb/usb_device.h"
9 #include "device/usb/usb_service.h"
10 #include "extensions/browser/api/device_permissions_manager.h"
11 #include "extensions/common/api/usb.h"
12 #include "extensions/common/permissions/permissions_data.h"
13 #include "extensions/common/permissions/usb_device_permission.h"
15 namespace usb = extensions::core_api::usb;
17 using content::BrowserThread;
18 using device::UsbDevice;
19 using device::UsbService;
21 namespace extensions {
23 namespace {
25 // Returns true iff the given extension has permission to receive events
26 // regarding this device.
27 bool WillDispatchDeviceEvent(scoped_refptr<UsbDevice> device,
28 const base::string16& serial_number,
29 content::BrowserContext* browser_context,
30 const Extension* extension,
31 base::ListValue* event_args) {
32 // Check install-time and optional permissions.
33 UsbDevicePermission::CheckParam param(
34 device->vendor_id(), device->product_id(),
35 UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
36 if (extension->permissions_data()->CheckAPIPermissionWithParam(
37 APIPermission::kUsbDevice, &param)) {
38 return true;
41 // Check permissions granted through chrome.usb.getUserSelectedDevices.
42 scoped_ptr<DevicePermissions> device_permissions =
43 DevicePermissionsManager::Get(browser_context)
44 ->GetForExtension(extension->id());
45 if (device_permissions->FindEntry(device, serial_number).get()) {
46 return true;
49 return false;
52 base::LazyInstance<BrowserContextKeyedAPIFactory<UsbEventRouter>>::Leaky
53 g_event_router_factory = LAZY_INSTANCE_INITIALIZER;
55 } // namespace
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() {}
63 void Start() {
64 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
65 UsbService* service = device::DeviceClient::Get()->GetUsbService();
66 if (service) {
67 observer_.Add(service);
71 private:
72 // UsbService::Observer implementation.
73 void OnDeviceAdded(scoped_refptr<device::UsbDevice> device) override {
74 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
76 base::string16 serial_number;
77 device->GetSerialNumber(&serial_number);
79 BrowserThread::PostTask(
80 BrowserThread::UI, FROM_HERE,
81 base::Bind(&UsbEventRouter::DispatchEvent, usb_event_router_,
82 usb::OnDeviceAdded::kEventName, device, serial_number));
85 void OnDeviceRemoved(scoped_refptr<device::UsbDevice> device) override {
86 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
88 base::string16 serial_number;
89 device->GetSerialNumber(&serial_number);
91 BrowserThread::PostTask(
92 BrowserThread::UI, FROM_HERE,
93 base::Bind(&UsbEventRouter::DispatchEvent, usb_event_router_,
94 usb::OnDeviceRemoved::kEventName, device, serial_number));
97 base::WeakPtr<UsbEventRouter> usb_event_router_;
98 ScopedObserver<device::UsbService, device::UsbService::Observer> observer_;
101 // static
102 BrowserContextKeyedAPIFactory<UsbEventRouter>*
103 UsbEventRouter::GetFactoryInstance() {
104 return g_event_router_factory.Pointer();
107 UsbEventRouter::UsbEventRouter(content::BrowserContext* browser_context)
108 : browser_context_(browser_context), weak_factory_(this) {
109 EventRouter* event_router = EventRouter::Get(browser_context_);
110 if (event_router) {
111 event_router->RegisterObserver(this, usb::OnDeviceAdded::kEventName);
112 event_router->RegisterObserver(this, usb::OnDeviceRemoved::kEventName);
116 UsbEventRouter::~UsbEventRouter() {
119 void UsbEventRouter::Shutdown() {
120 EventRouter* event_router = EventRouter::Get(browser_context_);
121 if (event_router) {
122 event_router->UnregisterObserver(this);
124 helper_.reset(nullptr);
127 void UsbEventRouter::OnListenerAdded(const EventListenerInfo& details) {
128 if (!helper_) {
129 helper_.reset(new FileThreadHelper(weak_factory_.GetWeakPtr()));
130 BrowserThread::PostTask(
131 BrowserThread::FILE, FROM_HERE,
132 base::Bind(&FileThreadHelper::Start, base::Unretained(helper_.get())));
136 void UsbEventRouter::DispatchEvent(const std::string& event_name,
137 scoped_refptr<UsbDevice> device,
138 const base::string16& serial_number) {
139 EventRouter* event_router = EventRouter::Get(browser_context_);
140 if (event_router) {
141 usb::Device device_obj;
142 device_obj.device = device->unique_id();
143 device_obj.vendor_id = device->vendor_id();
144 device_obj.product_id = device->product_id();
146 scoped_ptr<Event> event;
147 if (event_name == usb::OnDeviceAdded::kEventName) {
148 event.reset(new Event(usb::OnDeviceAdded::kEventName,
149 usb::OnDeviceAdded::Create(device_obj)));
150 } else {
151 DCHECK(event_name == usb::OnDeviceRemoved::kEventName);
152 event.reset(new Event(usb::OnDeviceRemoved::kEventName,
153 usb::OnDeviceRemoved::Create(device_obj)));
156 event->will_dispatch_callback =
157 base::Bind(&WillDispatchDeviceEvent, device, serial_number);
158 event_router->BroadcastEvent(event.Pass());
162 } // extensions