summaryrefslogtreecommitdiffstats
path: root/extensions/browser/api/usb/usb_event_router.cc
blob: 41ae77775b8f512f83195c326d4fe09c4610b912 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "extensions/browser/api/usb/usb_event_router.h"

#include "device/core/device_client.h"
#include "device/usb/usb_device.h"
#include "extensions/browser/api/device_permissions_manager.h"
#include "extensions/common/api/usb.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/permissions/usb_device_permission.h"

namespace usb = extensions::core_api::usb;

using content::BrowserThread;
using device::UsbDevice;
using device::UsbService;

namespace extensions {

namespace {

// Returns true iff the given extension has permission to receive events
// regarding this device.
bool WillDispatchDeviceEvent(scoped_refptr<UsbDevice> device,
                             content::BrowserContext* browser_context,
                             const Extension* extension,
                             base::ListValue* event_args) {
  // Check install-time and optional permissions.
  UsbDevicePermission::CheckParam param(
      device->vendor_id(), device->product_id(),
      UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
  if (extension->permissions_data()->CheckAPIPermissionWithParam(
          APIPermission::kUsbDevice, &param)) {
    return true;
  }

  // Check permissions granted through chrome.usb.getUserSelectedDevices.
  DevicePermissions* device_permissions =
      DevicePermissionsManager::Get(browser_context)
          ->GetForExtension(extension->id());
  if (device_permissions->FindEntry(device).get()) {
    return true;
  }

  return false;
}

base::LazyInstance<BrowserContextKeyedAPIFactory<UsbEventRouter>>::Leaky
    g_event_router_factory = LAZY_INSTANCE_INITIALIZER;

}  // namespace

// static
BrowserContextKeyedAPIFactory<UsbEventRouter>*
UsbEventRouter::GetFactoryInstance() {
  return g_event_router_factory.Pointer();
}

UsbEventRouter::UsbEventRouter(content::BrowserContext* browser_context)
    : browser_context_(browser_context), observer_(this) {
  EventRouter* event_router = EventRouter::Get(browser_context_);
  if (event_router) {
    event_router->RegisterObserver(this, usb::OnDeviceAdded::kEventName);
    event_router->RegisterObserver(this, usb::OnDeviceRemoved::kEventName);
  }
}

UsbEventRouter::~UsbEventRouter() {
}

void UsbEventRouter::Shutdown() {
  EventRouter* event_router = EventRouter::Get(browser_context_);
  if (event_router) {
    event_router->UnregisterObserver(this);
  }
}

void UsbEventRouter::OnListenerAdded(const EventListenerInfo& details) {
  UsbService* service = device::DeviceClient::Get()->GetUsbService();
  if (!observer_.IsObserving(service)) {
    observer_.Add(service);
  }
}

void UsbEventRouter::OnDeviceAdded(scoped_refptr<device::UsbDevice> device) {
  DispatchEvent(usb::OnDeviceAdded::kEventName, device);
}

void UsbEventRouter::OnDeviceRemoved(scoped_refptr<device::UsbDevice> device) {
  DispatchEvent(usb::OnDeviceRemoved::kEventName, device);
}

void UsbEventRouter::DispatchEvent(const std::string& event_name,
                                   scoped_refptr<UsbDevice> device) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  EventRouter* event_router = EventRouter::Get(browser_context_);
  if (event_router) {
    usb::Device device_obj;
    device_obj.device = device->unique_id();
    device_obj.vendor_id = device->vendor_id();
    device_obj.product_id = device->product_id();

    scoped_ptr<Event> event;
    if (event_name == usb::OnDeviceAdded::kEventName) {
      event.reset(new Event(usb::OnDeviceAdded::kEventName,
                            usb::OnDeviceAdded::Create(device_obj)));
    } else {
      DCHECK(event_name == usb::OnDeviceRemoved::kEventName);
      event.reset(new Event(usb::OnDeviceRemoved::kEventName,
                            usb::OnDeviceRemoved::Create(device_obj)));
    }

    event->will_dispatch_callback =
        base::Bind(&WillDispatchDeviceEvent, device);
    event_router->BroadcastEvent(event.Pass());
  }
}

}  // extensions