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
  132
  133
  134

content / browser / bluetooth / bluetooth_blocklist.h [blame]

// Copyright 2016 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_BLUETOOTH_BLUETOOTH_BLOCKLIST_H_
#define CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_BLOCKLIST_H_

#include <map>
#include <string_view>
#include <vector>

#include "base/lazy_instance.h"
#include "content/common/content_export.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/public/cpp/bluetooth_uuid.h"
#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"

namespace content {

// Implements the Web Bluetooth Blocklist policy as defined in the Web Bluetooth
// specification:
// https://webbluetoothcg.github.io/web-bluetooth/#the-gatt-blocklist
//
// Client code may query UUIDs to determine if they are excluded from use by the
// blocklist.
//
// Singleton access via Get() enforces only one copy of blocklist.
class CONTENT_EXPORT BluetoothBlocklist final {
 public:
  // Blocklist value terminology from Web Bluetooth specification:
  // https://webbluetoothcg.github.io/web-bluetooth/#the-gatt-blocklist
  enum class Value {
    EXCLUDE,        // Implies EXCLUDE_READS and EXCLUDE_WRITES.
    EXCLUDE_READS,  // Excluded from read operations.
    EXCLUDE_WRITES  // Excluded from write operations.
  };

  using DataPrefix = std::vector<blink::mojom::WebBluetoothDataFilterPtr>;
  using BlocklistedManufacturerDataMap =
      std::map<device::BluetoothDevice::ManufacturerId,
               std::vector<DataPrefix>>;

  BluetoothBlocklist(const BluetoothBlocklist&) = delete;
  BluetoothBlocklist& operator=(const BluetoothBlocklist&) = delete;

  ~BluetoothBlocklist();

  // Returns a singleton instance of the blocklist.
  static BluetoothBlocklist& Get();

  // Adds a UUID to the blocklist to be excluded from operations, merging with
  // any previous value and resulting in the strictest exclusion rule from the
  // combination of the two, E.G.:
  //   Add(uuid, EXCLUDE_READS);
  //   Add(uuid, EXCLUDE_WRITES);
  //   IsExcluded(uuid);  // true.
  // Requires UUID to be valid.
  void Add(const device::BluetoothUUID&, Value);

  // Adds UUIDs to the blocklist by parsing a blocklist string and calling
  // Add(uuid, value).
  //
  // The blocklist string format is defined at
  // ContentBrowserClient::GetWebBluetoothBlocklist().
  //
  // Malformed pairs in the string are ignored, including invalid UUID or
  // exclusion values. Duplicate UUIDs follow Add()'s merging rule.
  void Add(std::string_view blocklist_string);

  // Adds a manufacturer data prefix to |blocklisted_manufacturer_data_prefix_|
  // so that any manufacturer data in the device's advertisement matched
  // |prefix| will be excluded from device's advertisements.
  void Add(const device::BluetoothDevice::ManufacturerId& company_identifier,
           const std::vector<blink::mojom::WebBluetoothDataFilter>& prefix);

  // Returns if a UUID is excluded from all operations. UUID must be valid.
  bool IsExcluded(const device::BluetoothUUID&) const;

  // Returns if the filter of |company_identifier| and |data_filter| pair
  // is a strict subset of any blocked records in
  // |blocklisted_manufacturer_data_prefix_| hence should be excluded.
  bool IsExcluded(
      const blink::mojom::WebBluetoothCompanyPtr& company_identifier,
      const std::vector<blink::mojom::WebBluetoothDataFilterPtr>& data_filter)
      const;

  // Return if the |company_identifier| and |manufacturer_data| should be
  // excluded according to |blocklisted_manufacturer_data_prefix_|
  bool IsExcluded(
      const device::BluetoothDevice::ManufacturerId& company_identifier,
      const device::BluetoothDevice::ManufacturerData& manufacturer_data) const;

  // Returns if any UUID in a set of filters is excluded from all operations.
  // UUID must be valid.
  bool IsExcluded(
      const std::vector<blink::mojom::WebBluetoothLeScanFilterPtr>& filters);

  // Returns if a UUID is excluded from read operations. UUID must be valid.
  bool IsExcludedFromReads(const device::BluetoothUUID&) const;

  // Returns if a UUID is excluded from write operations. UUID must be valid.
  bool IsExcludedFromWrites(const device::BluetoothUUID&) const;

  // Modifies |options->optional_services|, removing any UUIDs with
  // Value::EXCLUDE.
  void RemoveExcludedUUIDs(
      blink::mojom::WebBluetoothRequestDeviceOptions* options);

  // Size of blocklist.
  size_t size() { return blocklisted_uuids_.size(); }

  void ResetToDefaultValuesForTest();

 private:
  // friend LazyInstance to permit access to private constructor.
  friend base::LazyInstanceTraitsBase<BluetoothBlocklist>;

  BluetoothBlocklist();

  void PopulateWithDefaultValues();

  // Populates blocklist with values obtained dynamically from a server, able
  // to be updated without shipping new executable versions.
  void PopulateWithServerProvidedValues();

  // Map of UUID to blocklisted value.
  std::map<device::BluetoothUUID, Value> blocklisted_uuids_;

  BlocklistedManufacturerDataMap blocklisted_manufacturer_data_prefix_;
};

}  // namespace content

#endif  // CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_BLOCKLIST_H_