| Index: content/browser/bluetooth/bluetooth_dispatcher_host.cc
 | 
| diff --git a/content/browser/bluetooth/bluetooth_dispatcher_host.cc b/content/browser/bluetooth/bluetooth_dispatcher_host.cc
 | 
| index 61d35955a2169cb768de875934ad772f2c66132c..3cdba38b7c19de094608f923920a73790b97a3bd 100644
 | 
| --- a/content/browser/bluetooth/bluetooth_dispatcher_host.cc
 | 
| +++ b/content/browser/bluetooth/bluetooth_dispatcher_host.cc
 | 
| @@ -52,18 +52,161 @@ enum class UMARequestDeviceOutcome {
 | 
|    DISCOVERY_START_FAILED = 3,
 | 
|    DISCOVERY_STOP_FAILED = 4,
 | 
|    NO_MATCHING_DEVICES_FOUND = 5,
 | 
| +  BLUETOOTH_ADAPTER_OFF = 6,
 | 
|    // NOTE: Add new requestDevice() outcomes immediately above this line. Make
 | 
|    // sure to update the enum list in
 | 
|    // tools/metrics/histogram/histograms.xml accordingly.
 | 
|    COUNT
 | 
|  };
 | 
|  
 | 
| +enum class UMAGATTServices {
 | 
| +  UNKNOWN,
 | 
| +  ALERT_NOTIFICATION,
 | 
| +  AUTOMATION_IO,
 | 
| +  BATTERY_SERVICE,
 | 
| +  BLOOD_PRESSURE,
 | 
| +  BODY_COMPOSITION,
 | 
| +  BOND_MANAGEMENT,
 | 
| +  CONTINUOUS_GLUCOSE_MONITORING,
 | 
| +  CURRENT_TIME,
 | 
| +  CYCLING_POWER,
 | 
| +  CYCLING_SPEED_AND_CADENCE,
 | 
| +  DEVICE_INFORMATION,
 | 
| +  ENVIRONMENTAL_SENSING,
 | 
| +  GENERIC_ACCESS,
 | 
| +  GENERIC_ATTRIBUTE,
 | 
| +  GLUCOSE,
 | 
| +  HEALTH_THERMOMETER,
 | 
| +  HEART_RATE,
 | 
| +  HUMAN_INTERFACE_DEVICE,
 | 
| +  IMMEDIATE_ALERT,
 | 
| +  INDOOR_POSITIONING,
 | 
| +  INTERNET_PROTOCOL_SUPPORT,
 | 
| +  LINK_LOSS,
 | 
| +  LOCATION_AND_NAVIGATION,
 | 
| +  NEXT_DST_CHANGE,
 | 
| +  PHONE_ALERT_STATUS,
 | 
| +  PULSE_OXIMETER,
 | 
| +  REFERENCE_TIME_UPDATE,
 | 
| +  RUNNING_SPEED_AND_CADENCE,
 | 
| +  SCAN_PARAMETERS,
 | 
| +  TX_POWER,
 | 
| +  USER_DATA,
 | 
| +  WEIGHT_SCALE,
 | 
| +  // NOTE: Add new services immediately above this line. Make sure to update the
 | 
| +  // enum list in tools/metrics/histogram/histograms.xml accordingly.
 | 
| +  COUNT
 | 
| +};
 | 
| +
 | 
| +typedef std::map<BluetoothUUID, UMAGATTServices> BluetoothUUIDToServicesMap;
 | 
| +
 | 
| +std::map<BluetoothUUID, UMAGATTServices>* getServiceToEnumMap() {
 | 
| +  CR_DEFINE_STATIC_LOCAL(BluetoothUUIDToServicesMap, services, ());
 | 
| +  if (services.empty()) {
 | 
| +    services.insert(std::make_pair(BluetoothUUID("1811"),
 | 
| +                                   UMAGATTServices::ALERT_NOTIFICATION));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("180F"),
 | 
| +                                   UMAGATTServices::BATTERY_SERVICE));
 | 
| +    services.insert(
 | 
| +        std::make_pair(BluetoothUUID("1810"), UMAGATTServices::BLOOD_PRESSURE));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("181B"),
 | 
| +                                   UMAGATTServices::BODY_COMPOSITION));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("181E"),
 | 
| +                                   UMAGATTServices::BOND_MANAGEMENT));
 | 
| +    services.insert(std::make_pair(
 | 
| +        BluetoothUUID("181F"), UMAGATTServices::CONTINUOUS_GLUCOSE_MONITORING));
 | 
| +    services.insert(
 | 
| +        std::make_pair(BluetoothUUID("1805"), UMAGATTServices::CURRENT_TIME));
 | 
| +    services.insert(
 | 
| +        std::make_pair(BluetoothUUID("1818"), UMAGATTServices::CYCLING_POWER));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("1816"),
 | 
| +                                   UMAGATTServices::CYCLING_SPEED_AND_CADENCE));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("180A"),
 | 
| +                                   UMAGATTServices::DEVICE_INFORMATION));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("181A"),
 | 
| +                                   UMAGATTServices::ENVIRONMENTAL_SENSING));
 | 
| +    services.insert(
 | 
| +        std::make_pair(BluetoothUUID("1800"), UMAGATTServices::GENERIC_ACCESS));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("1801"),
 | 
| +                                   UMAGATTServices::GENERIC_ATTRIBUTE));
 | 
| +    services.insert(
 | 
| +        std::make_pair(BluetoothUUID("1808"), UMAGATTServices::GLUCOSE));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("1809"),
 | 
| +                                   UMAGATTServices::HEALTH_THERMOMETER));
 | 
| +    services.insert(
 | 
| +        std::make_pair(BluetoothUUID("180D"), UMAGATTServices::HEART_RATE));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("1812"),
 | 
| +                                   UMAGATTServices::HUMAN_INTERFACE_DEVICE));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("1802"),
 | 
| +                                   UMAGATTServices::IMMEDIATE_ALERT));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("1821"),
 | 
| +                                   UMAGATTServices::INDOOR_POSITIONING));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("1820"),
 | 
| +                                   UMAGATTServices::INTERNET_PROTOCOL_SUPPORT));
 | 
| +    services.insert(
 | 
| +        std::make_pair(BluetoothUUID("1803"), UMAGATTServices::LINK_LOSS));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("1819"),
 | 
| +                                   UMAGATTServices::LOCATION_AND_NAVIGATION));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("1807"),
 | 
| +                                   UMAGATTServices::NEXT_DST_CHANGE));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("180E"),
 | 
| +                                   UMAGATTServices::PHONE_ALERT_STATUS));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("1806"),
 | 
| +                                   UMAGATTServices::REFERENCE_TIME_UPDATE));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("1814"),
 | 
| +                                   UMAGATTServices::RUNNING_SPEED_AND_CADENCE));
 | 
| +    services.insert(std::make_pair(BluetoothUUID("1813"),
 | 
| +                                   UMAGATTServices::SCAN_PARAMETERS));
 | 
| +    services.insert(
 | 
| +        std::make_pair(BluetoothUUID("1804"), UMAGATTServices::TX_POWER));
 | 
| +    services.insert(
 | 
| +        std::make_pair(BluetoothUUID("181C"), UMAGATTServices::USER_DATA));
 | 
| +    services.insert(
 | 
| +        std::make_pair(BluetoothUUID("181D"), UMAGATTServices::WEIGHT_SCALE));
 | 
| +  }
 | 
| +  return &services;
 | 
| +}
 | 
| +
 | 
| +int GetServiceBucket(const BluetoothUUID& service) {
 | 
| +  std::map<BluetoothUUID, UMAGATTServices>* services = getServiceToEnumMap();
 | 
| +
 | 
| +  auto it = services->find(service);
 | 
| +  if (it == services->end())
 | 
| +    return static_cast<int>(UMAGATTServices::UNKNOWN);
 | 
| +  return static_cast<int>(it->second);
 | 
| +}
 | 
| +
 | 
|  void RecordRequestDeviceOutcome(UMARequestDeviceOutcome outcome) {
 | 
| -  UMA_HISTOGRAM_ENUMERATION("Bluetooth.RequestDevice.Outcome",
 | 
| +  UMA_HISTOGRAM_ENUMERATION("WebBluetooth.RequestDevice.Outcome",
 | 
|                              static_cast<int>(outcome),
 | 
|                              static_cast<int>(UMARequestDeviceOutcome::COUNT));
 | 
|  }
 | 
|  
 | 
| +void RecordRequestDeviceFilters(
 | 
| +    const std::vector<content::BluetoothScanFilter>& filters) {
 | 
| +  UMA_HISTOGRAM_COUNTS("WebBluetooth.RequestDevice.Filters.Count",
 | 
| +                       filters.size());
 | 
| +  for (const content::BluetoothScanFilter& filter : filters) {
 | 
| +    for (const BluetoothUUID& service : filter.services) {
 | 
| +      UMA_HISTOGRAM_ENUMERATION("WebBluetooth.RequestDevice.Filters.Services",
 | 
| +                                GetServiceBucket(service),
 | 
| +                                static_cast<int>(UMAGATTServices::COUNT));
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void RecordRequestDeviceOptionalServices(
 | 
| +    const std::vector<BluetoothUUID>& optional_services) {
 | 
| +  UMA_HISTOGRAM_COUNTS("WebBluetooth.RequestDevice.OptionalServices.Count",
 | 
| +                       optional_services.size());
 | 
| +  for (const BluetoothUUID& service : optional_services) {
 | 
| +    UMA_HISTOGRAM_ENUMERATION(
 | 
| +        "WebBluetooth.RequestDevice.OptionalServices.Services",
 | 
| +        static_cast<int>(GetServiceBucket(service)),
 | 
| +        static_cast<int>(UMAGATTServices::COUNT));
 | 
| +  }
 | 
| +}
 | 
| +
 | 
|  // TODO(ortuno): Once we have a chooser for scanning and the right
 | 
|  // callback for discovered services we should delete these constants.
 | 
|  // https://crbug.com/436280 and https://crbug.com/484504
 | 
| @@ -254,14 +397,27 @@ void BluetoothDispatcherHost::OnRequestDevice(
 | 
|      const std::vector<BluetoothUUID>& optional_services) {
 | 
|    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 | 
|    RecordAction(UserMetricsAction("WebBluetooth_RequestDevice"));
 | 
| +  RecordRequestDeviceFilters(filters);
 | 
| +  RecordRequestDeviceOptionalServices(optional_services);
 | 
| +
 | 
| +  VLOG(1) << "requestDevice called with the following filters: ";
 | 
| +  for (const BluetoothScanFilter& filter : filters) {
 | 
| +    VLOG(1) << "[";
 | 
| +    for (const BluetoothUUID& service : filter.services)
 | 
| +      VLOG(1) << service.value();
 | 
| +    VLOG(1) << "]";
 | 
| +  }
 | 
| +
 | 
| +  VLOG(1) << "requestDevice called with the following optional services: ";
 | 
| +  for (const BluetoothUUID& service : optional_services)
 | 
| +    VLOG(1) << service.value();
 | 
|  
 | 
|    RenderFrameHostImpl* render_frame_host =
 | 
|        RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id);
 | 
|  
 | 
|    if (!render_frame_host) {
 | 
| -    DLOG(WARNING)
 | 
| -        << "Got a requestDevice IPC without a matching RenderFrameHost: "
 | 
| -        << render_process_id_ << ", " << frame_routing_id;
 | 
| +    VLOG(1) << "Got a requestDevice IPC without a matching RenderFrameHost: "
 | 
| +            << render_process_id_ << ", " << frame_routing_id;
 | 
|      RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_RENDER_FRAME);
 | 
|      Send(new BluetoothMsg_RequestDeviceError(
 | 
|          thread_id, request_id, WebBluetoothError::RequestDeviceWithoutFrame));
 | 
| @@ -281,6 +437,22 @@ void BluetoothDispatcherHost::OnRequestDevice(
 | 
|        bad_message::ReceivedBadMessage(
 | 
|            this, bad_message::BDH_DUPLICATE_REQUEST_DEVICE_ID);
 | 
|      }
 | 
| +
 | 
| +    if (!adapter_->IsPresent()) {
 | 
| +      VLOG(1) << "BluetoothAdapter not present. Can't serve requestDevice.";
 | 
| +      RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_BLUETOOTH_ADAPTER);
 | 
| +      Send(new BluetoothMsg_RequestDeviceError(
 | 
| +          thread_id, request_id, WebBluetoothError::NoBluetoothAdapter));
 | 
| +      return;
 | 
| +    }
 | 
| +    if (!adapter_->IsPowered()) {
 | 
| +      VLOG(1) << "BluetoothAdapter is not powered. Can't serve requestDevice.";
 | 
| +      RecordRequestDeviceOutcome(
 | 
| +          UMARequestDeviceOutcome::BLUETOOTH_ADAPTER_OFF);
 | 
| +      Send(new BluetoothMsg_RequestDeviceError(
 | 
| +          thread_id, request_id, WebBluetoothError::BluetoothAdapterOff));
 | 
| +      return;
 | 
| +    }
 | 
|      adapter_->StartDiscoverySessionWithFilter(
 | 
|          ComputeScanFilter(filters),
 | 
|          base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted,
 | 
| @@ -288,7 +460,7 @@ void BluetoothDispatcherHost::OnRequestDevice(
 | 
|          base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError,
 | 
|                     weak_ptr_factory_.GetWeakPtr(), thread_id, request_id));
 | 
|    } else {
 | 
| -    DLOG(WARNING) << "No BluetoothAdapter. Can't serve requestDevice.";
 | 
| +    VLOG(1) << "No BluetoothAdapter. Can't serve requestDevice.";
 | 
|      RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_BLUETOOTH_ADAPTER);
 | 
|      Send(new BluetoothMsg_RequestDeviceError(
 | 
|          thread_id, request_id, WebBluetoothError::NoBluetoothAdapter));
 | 
| @@ -589,6 +761,7 @@ void BluetoothDispatcherHost::OnDiscoverySessionStopped(int thread_id,
 | 
|        return;
 | 
|      }
 | 
|    }
 | 
| +  VLOG(1) << "No matching Bluetooth Devices found";
 | 
|    RecordRequestDeviceOutcome(
 | 
|        UMARequestDeviceOutcome::NO_MATCHING_DEVICES_FOUND);
 | 
|    Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id,
 | 
| 
 |