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
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131

content / browser / usb / web_usb_service_impl.h [blame]

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_USB_WEB_USB_SERVICE_IMPL_H_
#define CONTENT_BROWSER_USB_WEB_USB_SERVICE_IMPL_H_

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/usb_chooser.h"
#include "content/public/browser/usb_delegate.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote_set.h"
#include "services/device/public/mojom/usb_device.mojom-forward.h"
#include "services/device/public/mojom/usb_enumeration_options.mojom-forward.h"
#include "third_party/blink/public/mojom/usb/web_usb_service.mojom.h"
#include "url/origin.h"

namespace content {

class RenderFrameHostImpl;

// Implements a restricted device::mojom::UsbDeviceManager interface by wrapping
// another UsbDeviceManager instance and enforces the rules of the WebUSB
// permission model as well as permission granted by the user through a device
// chooser UI.
class CONTENT_EXPORT WebUsbServiceImpl : public blink::mojom::WebUsbService,
                                         public UsbDelegate::Observer {
 public:
  WebUsbServiceImpl(RenderFrameHostImpl* render_frame_host,
                    base::WeakPtr<ServiceWorkerVersion> service_worker_version,
                    const url::Origin& origin);
  WebUsbServiceImpl(const WebUsbServiceImpl&) = delete;
  WebUsbServiceImpl& operator=(const WebUsbServiceImpl&) = delete;
  ~WebUsbServiceImpl() override;

  // Use this when creating from a document.
  static void Create(
      RenderFrameHostImpl& render_frame_host,
      mojo::PendingReceiver<blink::mojom::WebUsbService> pending_receiver);

  // Use this when creating from a service worker.
  static void Create(
      base::WeakPtr<ServiceWorkerVersion> service_worker_version,
      const url::Origin& origin,
      mojo::PendingReceiver<blink::mojom::WebUsbService> pending_receiver);

  // blink::mojom::WebUsbService implementation:
  void GetDevices(GetDevicesCallback callback) override;
  void GetDevice(
      const std::string& guid,
      mojo::PendingReceiver<device::mojom::UsbDevice> device_receiver) override;
  void GetPermission(blink::mojom::WebUsbRequestDeviceOptionsPtr options,
                     GetPermissionCallback callback) override;
  void ForgetDevice(const std::string& guid,
                    ForgetDeviceCallback callback) override;
  void SetClient(
      mojo::PendingAssociatedRemote<device::mojom::UsbDeviceManagerClient>
          client) override;

  // UsbDelegate::Observer implementation:
  void OnDeviceAdded(const device::mojom::UsbDeviceInfo& device_info) override;
  void OnDeviceRemoved(
      const device::mojom::UsbDeviceInfo& device_info) override;
  void OnDeviceManagerConnectionError() override;
  void OnPermissionRevoked(const url::Origin& origin) override;

  const mojo::AssociatedRemoteSet<device::mojom::UsbDeviceManagerClient>&
  clients() const {
    return clients_;
  }

  base::WeakPtr<content::ServiceWorkerVersion> service_worker_version() {
    return service_worker_version_;
  }

 private:
  class UsbDeviceClient;

  // Get the `BrowserContext` this `WebUsbServiceImpl` belongs to. Returns
  // `nullptr` if the `BrowserContext` is destroyed.
  BrowserContext* GetBrowserContext() const;

  std::vector<uint8_t> GetProtectedInterfaceClasses() const;

  void OnGetDevices(
      GetDevicesCallback callback,
      std::vector<device::mojom::UsbDeviceInfoPtr> device_info_list);

  void IncrementConnectionCount();
  void DecrementConnectionCount();
  void RemoveDeviceClient(const UsbDeviceClient* client);

  // May be `nullptr` if this `WebUsbServiceImpl` is created in a context
  // without a frame. When `render_frame_host_` is destroyed, this
  // `WebUsbServiceImpl` is destroyed first.
  const raw_ptr<RenderFrameHostImpl> render_frame_host_;

  // The ServiceWorkerVersion of the service worker this WebUsbService belongs
  // to.
  const base::WeakPtr<ServiceWorkerVersion> service_worker_version_;

  // The request uuid for keeping service worker alive.
  std::optional<base::Uuid> service_worker_activity_request_uuid_;

  const url::Origin origin_;

  std::unique_ptr<UsbChooser> usb_chooser_;

  // Used to bind with Blink.
  mojo::AssociatedRemoteSet<device::mojom::UsbDeviceManagerClient> clients_;

  // A UsbDeviceClient tracks a UsbDevice pipe that has been passed to Blink.
  int connection_count_ = 0;
  std::vector<std::unique_ptr<UsbDeviceClient>> device_clients_;

  base::WeakPtrFactory<WebUsbServiceImpl> weak_factory_{this};
};

}  // namespace content

#endif  // CONTENT_BROWSER_USB_WEB_USB_SERVICE_IMPL_H_