| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // ID Not In Map Note: | 5 // ID Not In Map Note: |
| 6 // A service, characteristic, or descriptor ID not in the corresponding | 6 // A service, characteristic, or descriptor ID not in the corresponding |
| 7 // BluetoothDispatcherHost map [service_to_device_, characteristic_to_service_, | 7 // BluetoothDispatcherHost map [service_to_device_, characteristic_to_service_, |
| 8 // descriptor_to_characteristic_] implies a hostile renderer because a renderer | 8 // descriptor_to_characteristic_] implies a hostile renderer because a renderer |
| 9 // obtains the corresponding ID from this class and it will be added to the map | 9 // obtains the corresponding ID from this class and it will be added to the map |
| 10 // at that time. | 10 // at that time. |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 for (BluetoothGattService* service : device->GetGattServices()) { | 226 for (BluetoothGattService* service : device->GetGattServices()) { |
| 227 VLOG(1) << "Service in cache: " << service->GetUUID().canonical_value(); | 227 VLOG(1) << "Service in cache: " << service->GetUUID().canonical_value(); |
| 228 if (service->GetUUID().canonical_value() == service_uuid && | 228 if (service->GetUUID().canonical_value() == service_uuid && |
| 229 service->IsPrimary()) { | 229 service->IsPrimary()) { |
| 230 services.push_back(service); | 230 services.push_back(service); |
| 231 } | 231 } |
| 232 } | 232 } |
| 233 return services; | 233 return services; |
| 234 } | 234 } |
| 235 | 235 |
| 236 UMARequestDeviceOutcome OutcomeFromChooserEvent(BluetoothChooser::Event event) { |
| 237 switch (event) { |
| 238 case BluetoothChooser::Event::DENIED_PERMISSION: |
| 239 return UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_DENIED_PERMISSION; |
| 240 case BluetoothChooser::Event::CANCELLED: |
| 241 return UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_CANCELLED; |
| 242 case BluetoothChooser::Event::SHOW_OVERVIEW_HELP: |
| 243 return UMARequestDeviceOutcome::BLUETOOTH_OVERVIEW_HELP_LINK_PRESSED; |
| 244 case BluetoothChooser::Event::SHOW_ADAPTER_OFF_HELP: |
| 245 return UMARequestDeviceOutcome::ADAPTER_OFF_HELP_LINK_PRESSED; |
| 246 case BluetoothChooser::Event::SHOW_NEED_LOCATION_HELP: |
| 247 return UMARequestDeviceOutcome::NEED_LOCATION_HELP_LINK_PRESSED; |
| 248 case BluetoothChooser::Event::SELECTED: |
| 249 // We can't know if we are going to send a success message yet because |
| 250 // the device could have vanished. This event should be histogramed |
| 251 // manually after checking if the device is still around. |
| 252 NOTREACHED(); |
| 253 return UMARequestDeviceOutcome::SUCCESS; |
| 254 case BluetoothChooser::Event::RESCAN: |
| 255 // Rescanning doesn't result in a IPC message for the request being sent |
| 256 // so no need to histogram it. |
| 257 NOTREACHED(); |
| 258 return UMARequestDeviceOutcome::SUCCESS; |
| 259 } |
| 260 NOTREACHED(); |
| 261 return UMARequestDeviceOutcome::SUCCESS; |
| 262 } |
| 263 |
| 236 } // namespace | 264 } // namespace |
| 237 | 265 |
| 238 BluetoothDispatcherHost::BluetoothDispatcherHost(int render_process_id) | 266 BluetoothDispatcherHost::BluetoothDispatcherHost(int render_process_id) |
| 239 : BrowserMessageFilter(BluetoothMsgStart), | 267 : BrowserMessageFilter(BluetoothMsgStart), |
| 240 render_process_id_(render_process_id), | 268 render_process_id_(render_process_id), |
| 241 current_delay_time_(kDelayTime), | 269 current_delay_time_(kDelayTime), |
| 242 discovery_session_timer_( | 270 discovery_session_timer_( |
| 243 FROM_HERE, | 271 FROM_HERE, |
| 244 // TODO(jyasskin): Add a way for tests to control the dialog | 272 // TODO(jyasskin): Add a way for tests to control the dialog |
| 245 // directly, and change this to a reasonable discovery timeout. | 273 // directly, and change this to a reasonable discovery timeout. |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 // Clear adapter, releasing observer references. | 359 // Clear adapter, releasing observer references. |
| 332 set_adapter(scoped_refptr<device::BluetoothAdapter>()); | 360 set_adapter(scoped_refptr<device::BluetoothAdapter>()); |
| 333 } | 361 } |
| 334 | 362 |
| 335 // Stores information associated with an in-progress requestDevice call. This | 363 // Stores information associated with an in-progress requestDevice call. This |
| 336 // will include the state of the active chooser dialog in a future patch. | 364 // will include the state of the active chooser dialog in a future patch. |
| 337 struct BluetoothDispatcherHost::RequestDeviceSession { | 365 struct BluetoothDispatcherHost::RequestDeviceSession { |
| 338 public: | 366 public: |
| 339 RequestDeviceSession(int thread_id, | 367 RequestDeviceSession(int thread_id, |
| 340 int request_id, | 368 int request_id, |
| 369 int frame_routing_id, |
| 341 url::Origin origin, | 370 url::Origin origin, |
| 342 const std::vector<BluetoothScanFilter>& filters, | 371 const std::vector<BluetoothScanFilter>& filters, |
| 343 const std::vector<BluetoothUUID>& optional_services) | 372 const std::vector<BluetoothUUID>& optional_services) |
| 344 : thread_id(thread_id), | 373 : thread_id(thread_id), |
| 345 request_id(request_id), | 374 request_id(request_id), |
| 375 frame_routing_id(frame_routing_id), |
| 346 origin(origin), | 376 origin(origin), |
| 347 filters(filters), | 377 filters(filters), |
| 348 optional_services(optional_services) {} | 378 optional_services(optional_services) {} |
| 349 | 379 |
| 350 void AddFilteredDevice(const device::BluetoothDevice& device) { | 380 void AddFilteredDevice(const device::BluetoothDevice& device) { |
| 351 if (chooser && MatchesFilters(device, filters)) { | 381 if (chooser && MatchesFilters(device, filters)) { |
| 352 chooser->AddDevice(device.GetAddress(), device.GetName()); | 382 chooser->AddDevice(device.GetAddress(), device.GetName()); |
| 353 } | 383 } |
| 354 } | 384 } |
| 355 | 385 |
| 356 scoped_ptr<device::BluetoothDiscoveryFilter> ComputeScanFilter() const { | 386 scoped_ptr<device::BluetoothDiscoveryFilter> ComputeScanFilter() const { |
| 357 std::set<BluetoothUUID> services; | 387 std::set<BluetoothUUID> services; |
| 358 for (const BluetoothScanFilter& filter : filters) { | 388 for (const BluetoothScanFilter& filter : filters) { |
| 359 services.insert(filter.services.begin(), filter.services.end()); | 389 services.insert(filter.services.begin(), filter.services.end()); |
| 360 } | 390 } |
| 361 scoped_ptr<device::BluetoothDiscoveryFilter> discovery_filter( | 391 scoped_ptr<device::BluetoothDiscoveryFilter> discovery_filter( |
| 362 new device::BluetoothDiscoveryFilter( | 392 new device::BluetoothDiscoveryFilter( |
| 363 device::BluetoothDiscoveryFilter::TRANSPORT_DUAL)); | 393 device::BluetoothDiscoveryFilter::TRANSPORT_DUAL)); |
| 364 for (const BluetoothUUID& service : services) { | 394 for (const BluetoothUUID& service : services) { |
| 365 discovery_filter->AddUUID(service); | 395 discovery_filter->AddUUID(service); |
| 366 } | 396 } |
| 367 return discovery_filter; | 397 return discovery_filter; |
| 368 } | 398 } |
| 369 | 399 |
| 370 const int thread_id; | 400 const int thread_id; |
| 371 const int request_id; | 401 const int request_id; |
| 402 const int frame_routing_id; |
| 372 const url::Origin origin; | 403 const url::Origin origin; |
| 373 const std::vector<BluetoothScanFilter> filters; | 404 const std::vector<BluetoothScanFilter> filters; |
| 374 const std::vector<BluetoothUUID> optional_services; | 405 const std::vector<BluetoothUUID> optional_services; |
| 375 scoped_ptr<BluetoothChooser> chooser; | 406 scoped_ptr<BluetoothChooser> chooser; |
| 376 scoped_ptr<device::BluetoothDiscoverySession> discovery_session; | 407 scoped_ptr<device::BluetoothDiscoverySession> discovery_session; |
| 377 }; | 408 }; |
| 378 | 409 |
| 379 struct BluetoothDispatcherHost::CacheQueryResult { | 410 struct BluetoothDispatcherHost::CacheQueryResult { |
| 380 CacheQueryResult() | 411 CacheQueryResult() |
| 381 : device(nullptr), | 412 : device(nullptr), |
| (...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1056 | 1087 |
| 1057 // The renderer should never send empty filters. | 1088 // The renderer should never send empty filters. |
| 1058 if (HasEmptyOrInvalidFilter(filters)) { | 1089 if (HasEmptyOrInvalidFilter(filters)) { |
| 1059 bad_message::ReceivedBadMessage(this, | 1090 bad_message::ReceivedBadMessage(this, |
| 1060 bad_message::BDH_EMPTY_OR_INVALID_FILTERS); | 1091 bad_message::BDH_EMPTY_OR_INVALID_FILTERS); |
| 1061 return; | 1092 return; |
| 1062 } | 1093 } |
| 1063 | 1094 |
| 1064 // Create storage for the information that backs the chooser, and show the | 1095 // Create storage for the information that backs the chooser, and show the |
| 1065 // chooser. | 1096 // chooser. |
| 1066 RequestDeviceSession* const session = new RequestDeviceSession( | 1097 RequestDeviceSession* const session = |
| 1067 thread_id, request_id, render_frame_host->GetLastCommittedOrigin(), | 1098 new RequestDeviceSession(thread_id, request_id, frame_routing_id, |
| 1068 filters, optional_services_blacklist_filtered); | 1099 render_frame_host->GetLastCommittedOrigin(), |
| 1100 filters, optional_services_blacklist_filtered); |
| 1069 int chooser_id = request_device_sessions_.Add(session); | 1101 int chooser_id = request_device_sessions_.Add(session); |
| 1070 | 1102 |
| 1071 BluetoothChooser::EventHandler chooser_event_handler = | 1103 BluetoothChooser::EventHandler chooser_event_handler = |
| 1072 base::Bind(&BluetoothDispatcherHost::OnBluetoothChooserEvent, | 1104 base::Bind(&BluetoothDispatcherHost::OnBluetoothChooserEvent, |
| 1073 weak_ptr_on_ui_thread_, chooser_id); | 1105 weak_ptr_on_ui_thread_, chooser_id); |
| 1074 if (WebContents* web_contents = | 1106 if (WebContents* web_contents = |
| 1075 WebContents::FromRenderFrameHost(render_frame_host)) { | 1107 WebContents::FromRenderFrameHost(render_frame_host)) { |
| 1076 if (WebContentsDelegate* delegate = web_contents->GetDelegate()) { | 1108 if (WebContentsDelegate* delegate = web_contents->GetDelegate()) { |
| 1077 session->chooser = delegate->RunBluetoothChooser(render_frame_host, | 1109 session->chooser = delegate->RunBluetoothChooser(render_frame_host, |
| 1078 chooser_event_handler); | 1110 chooser_event_handler); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1153 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1185 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1154 RequestDeviceSession* session = request_device_sessions_.Lookup(chooser_id); | 1186 RequestDeviceSession* session = request_device_sessions_.Lookup(chooser_id); |
| 1155 DCHECK(session) << "Shouldn't receive an event (" << static_cast<int>(event) | 1187 DCHECK(session) << "Shouldn't receive an event (" << static_cast<int>(event) |
| 1156 << ") from a closed chooser."; | 1188 << ") from a closed chooser."; |
| 1157 CHECK(session->chooser) << "Shouldn't receive an event (" | 1189 CHECK(session->chooser) << "Shouldn't receive an event (" |
| 1158 << static_cast<int>(event) | 1190 << static_cast<int>(event) |
| 1159 << ") from a closed chooser."; | 1191 << ") from a closed chooser."; |
| 1160 switch (event) { | 1192 switch (event) { |
| 1161 case BluetoothChooser::Event::RESCAN: | 1193 case BluetoothChooser::Event::RESCAN: |
| 1162 StartDeviceDiscovery(session, chooser_id); | 1194 StartDeviceDiscovery(session, chooser_id); |
| 1163 break; | 1195 // No need to close the chooser so we return. |
| 1196 return; |
| 1164 case BluetoothChooser::Event::DENIED_PERMISSION: | 1197 case BluetoothChooser::Event::DENIED_PERMISSION: |
| 1165 case BluetoothChooser::Event::CANCELLED: | 1198 case BluetoothChooser::Event::CANCELLED: |
| 1166 case BluetoothChooser::Event::SELECTED: { | 1199 case BluetoothChooser::Event::SELECTED: |
| 1167 // Synchronously ensure nothing else calls into the chooser after it has | |
| 1168 // asked to be closed. | |
| 1169 session->chooser.reset(); | |
| 1170 | |
| 1171 // Yield to the event loop to make sure we don't destroy the session | |
| 1172 // within a BluetoothDispatcherHost stack frame. | |
| 1173 if (!base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 1174 FROM_HERE, | |
| 1175 base::Bind(&BluetoothDispatcherHost::FinishClosingChooser, | |
| 1176 weak_ptr_on_ui_thread_, chooser_id, event, | |
| 1177 device_id))) { | |
| 1178 LOG(WARNING) << "No TaskRunner; not closing requestDevice dialog."; | |
| 1179 } | |
| 1180 break; | 1200 break; |
| 1181 } | |
| 1182 case BluetoothChooser::Event::SHOW_OVERVIEW_HELP: | 1201 case BluetoothChooser::Event::SHOW_OVERVIEW_HELP: |
| 1183 ShowBluetoothOverviewLink(); | 1202 VLOG(1) << "Overview Help link pressed."; |
| 1184 break; | |
| 1185 case BluetoothChooser::Event::SHOW_PAIRING_HELP: | |
| 1186 ShowBluetoothPairingLink(); | |
| 1187 break; | 1203 break; |
| 1188 case BluetoothChooser::Event::SHOW_ADAPTER_OFF_HELP: | 1204 case BluetoothChooser::Event::SHOW_ADAPTER_OFF_HELP: |
| 1189 ShowBluetoothAdapterOffLink(); | 1205 VLOG(1) << "Adapter Off Help link pressed."; |
| 1190 break; | 1206 break; |
| 1191 case BluetoothChooser::Event::SHOW_NEED_LOCATION_HELP: | 1207 case BluetoothChooser::Event::SHOW_NEED_LOCATION_HELP: |
| 1192 ShowNeedLocationLink(); | 1208 VLOG(1) << "Need Location Help link pressed."; |
| 1193 break; | 1209 break; |
| 1194 } | 1210 } |
| 1211 |
| 1212 // Synchronously ensure nothing else calls into the chooser after it has |
| 1213 // asked to be closed. |
| 1214 session->chooser.reset(); |
| 1215 |
| 1216 // Yield to the event loop to make sure we don't destroy the session |
| 1217 // within a BluetoothDispatcherHost stack frame. |
| 1218 if (!base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 1219 FROM_HERE, |
| 1220 base::Bind(&BluetoothDispatcherHost::FinishClosingChooser, |
| 1221 weak_ptr_on_ui_thread_, chooser_id, event, device_id))) { |
| 1222 LOG(WARNING) << "No TaskRunner; not closing requestDevice dialog."; |
| 1223 } |
| 1195 } | 1224 } |
| 1196 | 1225 |
| 1197 void BluetoothDispatcherHost::FinishClosingChooser( | 1226 void BluetoothDispatcherHost::FinishClosingChooser( |
| 1198 int chooser_id, | 1227 int chooser_id, |
| 1199 BluetoothChooser::Event event, | 1228 BluetoothChooser::Event event, |
| 1200 const std::string& device_id) { | 1229 const std::string& device_id) { |
| 1201 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1230 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1202 RequestDeviceSession* session = request_device_sessions_.Lookup(chooser_id); | 1231 RequestDeviceSession* session = request_device_sessions_.Lookup(chooser_id); |
| 1203 DCHECK(session) << "Session removed unexpectedly."; | 1232 DCHECK(session) << "Session removed unexpectedly."; |
| 1204 | 1233 |
| 1205 if (event == BluetoothChooser::Event::CANCELLED) { | 1234 if ((event != BluetoothChooser::Event::DENIED_PERMISSION) && |
| 1206 RecordRequestDeviceOutcome( | 1235 (event != BluetoothChooser::Event::SELECTED)) { |
| 1207 UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_CANCELLED); | 1236 RecordRequestDeviceOutcome(OutcomeFromChooserEvent(event)); |
| 1208 VLOG(1) << "Bluetooth chooser cancelled"; | |
| 1209 Send(new BluetoothMsg_RequestDeviceError( | 1237 Send(new BluetoothMsg_RequestDeviceError( |
| 1210 session->thread_id, session->request_id, | 1238 session->thread_id, session->request_id, |
| 1211 WebBluetoothError::ChooserCancelled)); | 1239 WebBluetoothError::ChooserCancelled)); |
| 1212 request_device_sessions_.Remove(chooser_id); | 1240 request_device_sessions_.Remove(chooser_id); |
| 1213 return; | 1241 return; |
| 1214 } | 1242 } |
| 1215 if (event == BluetoothChooser::Event::DENIED_PERMISSION) { | 1243 if (event == BluetoothChooser::Event::DENIED_PERMISSION) { |
| 1216 RecordRequestDeviceOutcome( | 1244 RecordRequestDeviceOutcome( |
| 1217 UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_DENIED_PERMISSION); | 1245 UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_DENIED_PERMISSION); |
| 1218 VLOG(1) << "Bluetooth chooser denied permission"; | 1246 VLOG(1) << "Bluetooth chooser denied permission"; |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1493 } | 1521 } |
| 1494 | 1522 |
| 1495 bool BluetoothDispatcherHost::CanFrameAccessCharacteristicInstance( | 1523 bool BluetoothDispatcherHost::CanFrameAccessCharacteristicInstance( |
| 1496 int frame_routing_id, | 1524 int frame_routing_id, |
| 1497 const std::string& characteristic_instance_id) { | 1525 const std::string& characteristic_instance_id) { |
| 1498 return QueryCacheForCharacteristic(GetOrigin(frame_routing_id), | 1526 return QueryCacheForCharacteristic(GetOrigin(frame_routing_id), |
| 1499 characteristic_instance_id) | 1527 characteristic_instance_id) |
| 1500 .outcome != CacheQueryOutcome::BAD_RENDERER; | 1528 .outcome != CacheQueryOutcome::BAD_RENDERER; |
| 1501 } | 1529 } |
| 1502 | 1530 |
| 1503 void BluetoothDispatcherHost::ShowBluetoothOverviewLink() { | |
| 1504 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 1505 NOTIMPLEMENTED(); | |
| 1506 } | |
| 1507 | |
| 1508 void BluetoothDispatcherHost::ShowBluetoothPairingLink() { | |
| 1509 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 1510 NOTIMPLEMENTED(); | |
| 1511 } | |
| 1512 | |
| 1513 void BluetoothDispatcherHost::ShowBluetoothAdapterOffLink() { | |
| 1514 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 1515 NOTIMPLEMENTED(); | |
| 1516 } | |
| 1517 | |
| 1518 void BluetoothDispatcherHost::ShowNeedLocationLink() { | |
| 1519 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 1520 NOTIMPLEMENTED(); | |
| 1521 } | |
| 1522 | |
| 1523 } // namespace content | 1531 } // namespace content |
| OLD | NEW |