Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: content/browser/bluetooth/bluetooth_dispatcher_host.cc

Issue 1286063002: Add a path for content/ to open and control a Bluetooth chooser dialog. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkcr
Patch Set: Remove an unnecessary include and forward decl Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 // NETWORK_ERROR Note: 5 // NETWORK_ERROR Note:
6 // When a device can't be found in the BluetoothAdapter, that generally 6 // When a device can't be found in the BluetoothAdapter, that generally
7 // indicates that it's gone out of range. We reject with a NetworkError in that 7 // indicates that it's gone out of range. We reject with a NetworkError in that
8 // case. 8 // case.
9 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothdevice-conne ctgatt 9 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothdevice-conne ctgatt
10 10
11 #include "content/browser/bluetooth/bluetooth_dispatcher_host.h" 11 #include "content/browser/bluetooth/bluetooth_dispatcher_host.h"
12 12
13 #include "base/bind.h"
14 #include "base/single_thread_task_runner.h"
13 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
16 #include "base/thread_task_runner_handle.h"
14 #include "content/browser/bad_message.h" 17 #include "content/browser/bad_message.h"
15 #include "content/browser/bluetooth/bluetooth_metrics.h" 18 #include "content/browser/bluetooth/bluetooth_metrics.h"
16 #include "content/browser/frame_host/render_frame_host_impl.h" 19 #include "content/browser/frame_host/render_frame_host_impl.h"
17 #include "content/common/bluetooth/bluetooth_messages.h" 20 #include "content/common/bluetooth/bluetooth_messages.h"
18 #include "device/bluetooth/bluetooth_adapter.h" 21 #include "device/bluetooth/bluetooth_adapter.h"
19 #include "device/bluetooth/bluetooth_adapter_factory.h" 22 #include "device/bluetooth/bluetooth_adapter_factory.h"
20 #include "device/bluetooth/bluetooth_device.h" 23 #include "device/bluetooth/bluetooth_device.h"
21 #include "device/bluetooth/bluetooth_discovery_session.h" 24 #include "device/bluetooth/bluetooth_discovery_session.h"
22 #include "device/bluetooth/bluetooth_gatt_characteristic.h" 25 #include "device/bluetooth/bluetooth_gatt_characteristic.h"
23 #include "device/bluetooth/bluetooth_gatt_service.h" 26 #include "device/bluetooth/bluetooth_gatt_service.h"
24 27
25 using blink::WebBluetoothError; 28 using blink::WebBluetoothError;
26 using device::BluetoothAdapter; 29 using device::BluetoothAdapter;
27 using device::BluetoothAdapterFactory; 30 using device::BluetoothAdapterFactory;
28 using device::BluetoothGattCharacteristic; 31 using device::BluetoothGattCharacteristic;
29 using device::BluetoothGattService; 32 using device::BluetoothGattService;
30 using device::BluetoothUUID; 33 using device::BluetoothUUID;
31 34
32 namespace content { 35 namespace content {
33 36
34 namespace { 37 namespace {
35 38
36 // TODO(ortuno): Once we have a chooser for scanning and the right 39 // TODO(ortuno): Once we have a chooser for scanning, a way to control that
37 // callback for discovered services we should delete these constants. 40 // chooser from tests, and the right callback for discovered services we should
41 // delete these constants.
38 // https://crbug.com/436280 and https://crbug.com/484504 42 // https://crbug.com/436280 and https://crbug.com/484504
39 const int kDelayTime = 5; // 5 seconds for scanning and discovering 43 const int kDelayTime = 5; // 5 seconds for scanning and discovering
40 const int kTestingDelayTime = 0; // No need to wait during tests 44 const int kTestingDelayTime = 0; // No need to wait during tests
41 45
42 // Defined at 46 // Defined at
43 // https://webbluetoothchrome.github.io/web-bluetooth/#dfn-matches-a-filter 47 // https://webbluetoothchrome.github.io/web-bluetooth/#dfn-matches-a-filter
44 bool MatchesFilter(const std::set<BluetoothUUID>& device_uuids, 48 bool MatchesFilter(const std::set<BluetoothUUID>& device_uuids,
45 const content::BluetoothScanFilter& filter) { 49 const content::BluetoothScanFilter& filter) {
46 if (filter.services.empty()) 50 if (filter.services.empty())
47 return false; 51 return false;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 return blink::WebBluetoothError::GATTNotPaired; 134 return blink::WebBluetoothError::GATTNotPaired;
131 case BluetoothGattService::GATT_ERROR_NOT_SUPPORTED: 135 case BluetoothGattService::GATT_ERROR_NOT_SUPPORTED:
132 RecordGATTOperationOutcome(operation, 136 RecordGATTOperationOutcome(operation,
133 UMAGATTOperationOutcome::NOT_SUPPORTED); 137 UMAGATTOperationOutcome::NOT_SUPPORTED);
134 return blink::WebBluetoothError::GATTNotSupported; 138 return blink::WebBluetoothError::GATTNotSupported;
135 } 139 }
136 NOTREACHED(); 140 NOTREACHED();
137 return blink::WebBluetoothError::GATTUntranslatedErrorCode; 141 return blink::WebBluetoothError::GATTUntranslatedErrorCode;
138 } 142 }
139 143
144 void StopDiscoverySession(
145 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) {
146 // Nothing goes wrong if the discovery session fails to stop, and we don't
147 // need to wait for it before letting the user's script proceed, so we ignore
148 // the results here.
149 discovery_session->Stop(base::Bind(&base::DoNothing),
150 base::Bind(&base::DoNothing));
151 }
152
140 } // namespace 153 } // namespace
141 154
142 BluetoothDispatcherHost::BluetoothDispatcherHost(int render_process_id) 155 BluetoothDispatcherHost::BluetoothDispatcherHost(int render_process_id)
143 : BrowserMessageFilter(BluetoothMsgStart), 156 : BrowserMessageFilter(BluetoothMsgStart),
144 render_process_id_(render_process_id), 157 render_process_id_(render_process_id),
158 current_delay_time_(kDelayTime),
159 discovery_session_timer_(
160 FROM_HERE,
161 // TODO(jyasskin): Add a way for tests to control the dialog
162 // directly, and change this to a reasonable discovery timeout.
163 base::TimeDelta::FromSecondsD(current_delay_time_),
164 base::Bind(&BluetoothDispatcherHost::StopDeviceDiscovery,
165 // base::Timer guarantees it won't call back after its
166 // destructor starts.
167 base::Unretained(this)),
168 /*is_repeating=*/false),
145 weak_ptr_factory_(this) { 169 weak_ptr_factory_(this) {
146 DCHECK_CURRENTLY_ON(BrowserThread::UI); 170 DCHECK_CURRENTLY_ON(BrowserThread::UI);
147 current_delay_time_ = kDelayTime;
148 if (BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) 171 if (BluetoothAdapterFactory::IsBluetoothAdapterAvailable())
149 BluetoothAdapterFactory::GetAdapter( 172 BluetoothAdapterFactory::GetAdapter(
150 base::Bind(&BluetoothDispatcherHost::set_adapter, 173 base::Bind(&BluetoothDispatcherHost::set_adapter,
151 weak_ptr_factory_.GetWeakPtr())); 174 weak_ptr_factory_.GetWeakPtr()));
152 } 175 }
153 176
154 void BluetoothDispatcherHost::OnDestruct() const { 177 void BluetoothDispatcherHost::OnDestruct() const {
155 // See class comment: UI Thread Note. 178 // See class comment: UI Thread Note.
156 BrowserThread::DeleteOnUIThread::Destruct(this); 179 BrowserThread::DeleteOnUIThread::Destruct(this);
157 } 180 }
(...skipping 17 matching lines...) Expand all
175 IPC_MESSAGE_HANDLER(BluetoothHostMsg_WriteValue, OnWriteValue) 198 IPC_MESSAGE_HANDLER(BluetoothHostMsg_WriteValue, OnWriteValue)
176 IPC_MESSAGE_UNHANDLED(handled = false) 199 IPC_MESSAGE_UNHANDLED(handled = false)
177 IPC_END_MESSAGE_MAP() 200 IPC_END_MESSAGE_MAP()
178 return handled; 201 return handled;
179 } 202 }
180 203
181 void BluetoothDispatcherHost::SetBluetoothAdapterForTesting( 204 void BluetoothDispatcherHost::SetBluetoothAdapterForTesting(
182 scoped_refptr<device::BluetoothAdapter> mock_adapter) { 205 scoped_refptr<device::BluetoothAdapter> mock_adapter) {
183 DCHECK_CURRENTLY_ON(BrowserThread::UI); 206 DCHECK_CURRENTLY_ON(BrowserThread::UI);
184 current_delay_time_ = kTestingDelayTime; 207 current_delay_time_ = kTestingDelayTime;
208 // Reset the discovery session timer to use the new delay time.
209 discovery_session_timer_.Start(
210 FROM_HERE, base::TimeDelta::FromSecondsD(current_delay_time_),
211 base::Bind(&BluetoothDispatcherHost::StopDeviceDiscovery,
212 // base::Timer guarantees it won't call back after its
213 // destructor starts.
214 base::Unretained(this)));
185 set_adapter(mock_adapter.Pass()); 215 set_adapter(mock_adapter.Pass());
186 } 216 }
187 217
188 BluetoothDispatcherHost::~BluetoothDispatcherHost() { 218 BluetoothDispatcherHost::~BluetoothDispatcherHost() {
189 DCHECK_CURRENTLY_ON(BrowserThread::UI); 219 DCHECK_CURRENTLY_ON(BrowserThread::UI);
190 // Clear adapter, releasing observer references. 220 // Clear adapter, releasing observer references.
191 set_adapter(scoped_refptr<device::BluetoothAdapter>()); 221 set_adapter(scoped_refptr<device::BluetoothAdapter>());
192 } 222 }
193 223
194 // Stores information associated with an in-progress requestDevice call. This 224 // Stores information associated with an in-progress requestDevice call. This
195 // will include the state of the active chooser dialog in a future patch. 225 // will include the state of the active chooser dialog in a future patch.
196 struct BluetoothDispatcherHost::RequestDeviceSession { 226 struct BluetoothDispatcherHost::RequestDeviceSession {
197 RequestDeviceSession(const std::vector<BluetoothScanFilter>& filters, 227 public:
228 RequestDeviceSession(int thread_id,
229 int request_id,
230 const std::vector<BluetoothScanFilter>& filters,
198 const std::vector<BluetoothUUID>& optional_services) 231 const std::vector<BluetoothUUID>& optional_services)
199 : filters(filters), optional_services(optional_services) {} 232 : thread_id(thread_id),
233 request_id(request_id),
234 filters(filters),
235 optional_services(optional_services) {}
200 236
201 std::vector<BluetoothScanFilter> filters; 237 void AddFilteredDevice(const device::BluetoothDevice& device) {
202 std::vector<BluetoothUUID> optional_services; 238 if (chooser && MatchesFilters(device, filters)) {
239 chooser->AddDevice(device.GetIdentifier(), device.GetName());
240 }
241 }
242
243 const int thread_id;
244 const int request_id;
245 const std::vector<BluetoothScanFilter> filters;
246 const std::vector<BluetoothUUID> optional_services;
247 scoped_ptr<BluetoothChooser> chooser;
248 scoped_ptr<device::BluetoothDiscoverySession> discovery_session;
203 }; 249 };
204 250
205 void BluetoothDispatcherHost::set_adapter( 251 void BluetoothDispatcherHost::set_adapter(
206 scoped_refptr<device::BluetoothAdapter> adapter) { 252 scoped_refptr<device::BluetoothAdapter> adapter) {
207 DCHECK_CURRENTLY_ON(BrowserThread::UI); 253 DCHECK_CURRENTLY_ON(BrowserThread::UI);
208 if (adapter_.get()) 254 if (adapter_.get())
209 adapter_->RemoveObserver(this); 255 adapter_->RemoveObserver(this);
210 adapter_ = adapter; 256 adapter_ = adapter;
211 if (adapter_.get()) 257 if (adapter_.get())
212 adapter_->AddObserver(this); 258 adapter_->AddObserver(this);
213 } 259 }
214 260
261 void BluetoothDispatcherHost::StopDeviceDiscovery() {
262 for (IDMap<RequestDeviceSession, IDMapOwnPointer>::iterator iter(
263 &request_device_sessions_);
264 !iter.IsAtEnd(); iter.Advance()) {
265 RequestDeviceSession* session = iter.GetCurrentValue();
266 if (session->discovery_session) {
267 StopDiscoverySession(session->discovery_session.Pass());
268 }
269 if (session->chooser) {
270 session->chooser->ShowDiscoveryState(
271 BluetoothChooser::DiscoveryState::IDLE);
272 }
273 }
274 }
275
276 void BluetoothDispatcherHost::AdapterPoweredChanged(
277 device::BluetoothAdapter* adapter,
278 bool powered) {
279 const BluetoothChooser::AdapterPresence presence =
280 powered ? BluetoothChooser::AdapterPresence::POWERED_ON
281 : BluetoothChooser::AdapterPresence::POWERED_OFF;
282 for (IDMap<RequestDeviceSession, IDMapOwnPointer>::iterator iter(
283 &request_device_sessions_);
284 !iter.IsAtEnd(); iter.Advance()) {
285 RequestDeviceSession* session = iter.GetCurrentValue();
286 if (session->chooser)
287 session->chooser->SetAdapterPresence(presence);
288 }
289 }
290
291 void BluetoothDispatcherHost::DeviceAdded(device::BluetoothAdapter* adapter,
292 device::BluetoothDevice* device) {
293 VLOG(1) << "Adding device to all choosers: " << device->GetIdentifier();
294 for (IDMap<RequestDeviceSession, IDMapOwnPointer>::iterator iter(
295 &request_device_sessions_);
296 !iter.IsAtEnd(); iter.Advance()) {
297 RequestDeviceSession* session = iter.GetCurrentValue();
298 session->AddFilteredDevice(*device);
299 }
300 }
301
215 static scoped_ptr<device::BluetoothDiscoveryFilter> ComputeScanFilter( 302 static scoped_ptr<device::BluetoothDiscoveryFilter> ComputeScanFilter(
216 const std::vector<BluetoothScanFilter>& filters) { 303 const std::vector<BluetoothScanFilter>& filters) {
217 std::set<BluetoothUUID> services; 304 std::set<BluetoothUUID> services;
218 for (const BluetoothScanFilter& filter : filters) { 305 for (const BluetoothScanFilter& filter : filters) {
219 services.insert(filter.services.begin(), filter.services.end()); 306 services.insert(filter.services.begin(), filter.services.end());
220 } 307 }
221 scoped_ptr<device::BluetoothDiscoveryFilter> discovery_filter( 308 scoped_ptr<device::BluetoothDiscoveryFilter> discovery_filter(
222 new device::BluetoothDiscoveryFilter( 309 new device::BluetoothDiscoveryFilter(
223 device::BluetoothDiscoveryFilter::TRANSPORT_DUAL)); 310 device::BluetoothDiscoveryFilter::TRANSPORT_DUAL));
224 for (const BluetoothUUID& service : services) { 311 for (const BluetoothUUID& service : services) {
(...skipping 30 matching lines...) Expand all
255 if (!render_frame_host) { 342 if (!render_frame_host) {
256 DLOG(WARNING) 343 DLOG(WARNING)
257 << "Got a requestDevice IPC without a matching RenderFrameHost: " 344 << "Got a requestDevice IPC without a matching RenderFrameHost: "
258 << render_process_id_ << ", " << frame_routing_id; 345 << render_process_id_ << ", " << frame_routing_id;
259 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_RENDER_FRAME); 346 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_RENDER_FRAME);
260 Send(new BluetoothMsg_RequestDeviceError( 347 Send(new BluetoothMsg_RequestDeviceError(
261 thread_id, request_id, WebBluetoothError::RequestDeviceWithoutFrame)); 348 thread_id, request_id, WebBluetoothError::RequestDeviceWithoutFrame));
262 return; 349 return;
263 } 350 }
264 351
265 // TODO(scheib): Device selection UI: crbug.com/436280 352 if (!adapter_) {
266 // TODO(scheib): Utilize BluetoothAdapter::Observer::DeviceAdded/Removed.
267 if (adapter_.get()) {
268 if (!request_device_sessions_
269 .insert(std::make_pair(
270 std::make_pair(thread_id, request_id),
271 RequestDeviceSession(filters, optional_services)))
272 .second) {
273 LOG(ERROR) << "2 requestDevice() calls with the same thread_id ("
274 << thread_id << ") and request_id (" << request_id
275 << ") shouldn't arrive at the same BluetoothDispatcherHost.";
276 bad_message::ReceivedBadMessage(
277 this, bad_message::BDH_DUPLICATE_REQUEST_DEVICE_ID);
278 }
279 if (!adapter_->IsPresent()) {
280 VLOG(1) << "Bluetooth Adapter not present. Can't serve requestDevice.";
281 RecordRequestDeviceOutcome(
282 UMARequestDeviceOutcome::BLUETOOTH_ADAPTER_NOT_PRESENT);
283 Send(new BluetoothMsg_RequestDeviceError(
284 thread_id, request_id, WebBluetoothError::NoBluetoothAdapter));
285 request_device_sessions_.erase(std::make_pair(thread_id, request_id));
286 return;
287 }
288 // TODO(jyasskin): Once the dialog is available, the dialog should check for
289 // the status of the adapter, i.e. check IsPowered() and
290 // BluetoothAdapter::Observer::PoweredChanged, and inform the user. But
291 // until the dialog is available we log/histogram the status and return
292 // with a message.
293 // https://crbug.com/517237
294 if (!adapter_->IsPowered()) {
295 RecordRequestDeviceOutcome(
296 UMARequestDeviceOutcome::BLUETOOTH_ADAPTER_OFF);
297 Send(new BluetoothMsg_RequestDeviceError(
298 thread_id, request_id, WebBluetoothError::BluetoothAdapterOff));
299 request_device_sessions_.erase(std::make_pair(thread_id, request_id));
300 return;
301 }
302 adapter_->StartDiscoverySessionWithFilter(
303 ComputeScanFilter(filters),
304 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted,
305 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id),
306 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError,
307 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id));
308 } else {
309 VLOG(1) << "No BluetoothAdapter. Can't serve requestDevice."; 353 VLOG(1) << "No BluetoothAdapter. Can't serve requestDevice.";
310 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_BLUETOOTH_ADAPTER); 354 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_BLUETOOTH_ADAPTER);
311 Send(new BluetoothMsg_RequestDeviceError( 355 Send(new BluetoothMsg_RequestDeviceError(
312 thread_id, request_id, WebBluetoothError::NoBluetoothAdapter)); 356 thread_id, request_id, WebBluetoothError::NoBluetoothAdapter));
357 return;
313 } 358 }
314 return; 359
360 if (!adapter_->IsPresent()) {
361 VLOG(1) << "Bluetooth Adapter not present. Can't serve requestDevice.";
362 RecordRequestDeviceOutcome(
363 UMARequestDeviceOutcome::BLUETOOTH_ADAPTER_NOT_PRESENT);
364 Send(new BluetoothMsg_RequestDeviceError(
365 thread_id, request_id, WebBluetoothError::NoBluetoothAdapter));
366 return;
367 }
368
369 // Create storage for the information that backs the chooser, and show the
370 // chooser.
371 RequestDeviceSession* const session = new RequestDeviceSession(
372 thread_id, request_id, filters, optional_services);
373 int chooser_id = request_device_sessions_.Add(session);
374
375 session->chooser = render_frame_host->RunBluetoothChooser(
jam 2015/08/25 15:49:21 instead of going through RenderFrameHost->RenderFr
Jeffrey Yasskin 2015/08/25 17:13:13 Thanks; I didn't realize that route existed.
376 this, chooser_id, render_frame_host->GetLastCommittedURL().GetOrigin());
377 if (!session->chooser) {
378 LOG(ERROR) << "No Bluetooth chooser implementation.";
379 RecordRequestDeviceOutcome(
380 UMARequestDeviceOutcome::NO_BLUETOOTH_CHOOSER_IMPLEMENTATION);
381 Send(new BluetoothMsg_RequestDeviceError(
382 thread_id, request_id, WebBluetoothError::NoBluetoothChooser));
383 request_device_sessions_.Remove(chooser_id);
384 return;
385 }
386
387 // Populate the initial list of devices.
388 VLOG(1) << "Populating devices in chooser " << chooser_id;
389 for (const device::BluetoothDevice* device : adapter_->GetDevices()) {
390 VLOG(1) << "\t" << device->GetIdentifier();
391 session->AddFilteredDevice(*device);
392 }
393
394 if (!session->chooser) {
395 // If the dialog's closing, no need to do any of the rest of this.
396 return;
397 }
398
399 if (!adapter_->IsPowered()) {
400 session->chooser->SetAdapterPresence(
401 BluetoothChooser::AdapterPresence::POWERED_OFF);
402 return;
403 }
404
405 // Redundant with the chooser's default; just to be clear:
406 session->chooser->ShowDiscoveryState(
407 BluetoothChooser::DiscoveryState::DISCOVERING);
408 adapter_->StartDiscoverySessionWithFilter(
409 ComputeScanFilter(filters),
410 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted,
411 weak_ptr_factory_.GetWeakPtr(), chooser_id),
412 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError,
413 weak_ptr_factory_.GetWeakPtr(), chooser_id));
315 } 414 }
316 415
317 void BluetoothDispatcherHost::OnConnectGATT( 416 void BluetoothDispatcherHost::OnConnectGATT(
318 int thread_id, 417 int thread_id,
319 int request_id, 418 int request_id,
320 const std::string& device_instance_id) { 419 const std::string& device_instance_id) {
321 DCHECK_CURRENTLY_ON(BrowserThread::UI); 420 DCHECK_CURRENTLY_ON(BrowserThread::UI);
322 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::CONNECT_GATT); 421 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::CONNECT_GATT);
323 const base::TimeTicks start_time = base::TimeTicks::Now(); 422 const base::TimeTicks start_time = base::TimeTicks::Now();
324 423
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 return; 656 return;
558 } 657 }
559 characteristic->WriteRemoteCharacteristic( 658 characteristic->WriteRemoteCharacteristic(
560 value, base::Bind(&BluetoothDispatcherHost::OnWriteValueSuccess, 659 value, base::Bind(&BluetoothDispatcherHost::OnWriteValueSuccess,
561 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), 660 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id),
562 base::Bind(&BluetoothDispatcherHost::OnWriteValueFailed, 661 base::Bind(&BluetoothDispatcherHost::OnWriteValueFailed,
563 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); 662 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id));
564 } 663 }
565 664
566 void BluetoothDispatcherHost::OnDiscoverySessionStarted( 665 void BluetoothDispatcherHost::OnDiscoverySessionStarted(
567 int thread_id, 666 int chooser_id,
568 int request_id,
569 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { 667 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) {
570 DCHECK_CURRENTLY_ON(BrowserThread::UI); 668 DCHECK_CURRENTLY_ON(BrowserThread::UI);
571 BrowserThread::PostDelayedTask( 669 VLOG(1) << "Started discovery session for " << chooser_id;
572 BrowserThread::UI, FROM_HERE, 670 if (RequestDeviceSession* session =
573 base::Bind(&BluetoothDispatcherHost::StopDiscoverySession, 671 request_device_sessions_.Lookup(chooser_id)) {
574 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, 672 session->discovery_session = discovery_session.Pass();
575 base::Passed(&discovery_session)), 673
576 base::TimeDelta::FromSeconds(current_delay_time_)); 674 // Arrange to stop discovery later.
675 discovery_session_timer_.Reset();
676 } else {
677 VLOG(1) << "Chooser " << chooser_id
678 << " was closed before the session finished starting. Stopping.";
679 StopDiscoverySession(discovery_session.Pass());
680 }
577 } 681 }
578 682
579 void BluetoothDispatcherHost::OnDiscoverySessionStartedError(int thread_id, 683 void BluetoothDispatcherHost::OnDiscoverySessionStartedError(int chooser_id) {
580 int request_id) {
581 DCHECK_CURRENTLY_ON(BrowserThread::UI); 684 DCHECK_CURRENTLY_ON(BrowserThread::UI);
582 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStartedError"; 685 VLOG(1) << "Failed to start discovery session for " << chooser_id;
583 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::DISCOVERY_START_FAILED); 686 if (RequestDeviceSession* session =
584 Send(new BluetoothMsg_RequestDeviceError( 687 request_device_sessions_.Lookup(chooser_id)) {
585 thread_id, request_id, WebBluetoothError::DiscoverySessionStartFailed)); 688 if (session->chooser && !session->discovery_session) {
586 request_device_sessions_.erase(std::make_pair(thread_id, request_id)); 689 session->chooser->ShowDiscoveryState(
690 BluetoothChooser::DiscoveryState::FAILED_TO_START);
691 }
692 }
693 // Ignore discovery session start errors when the dialog was already closed by
694 // the time they happen.
587 } 695 }
588 696
589 void BluetoothDispatcherHost::StopDiscoverySession( 697 void BluetoothDispatcherHost::CloseDialog(int chooser_id,
590 int thread_id, 698 const base::Closure& callback) {
591 int request_id, 699 RequestDeviceSession* session = request_device_sessions_.Lookup(chooser_id);
592 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { 700 DCHECK(session) << "Shouldn't close the dialog twice.";
593 DCHECK_CURRENTLY_ON(BrowserThread::UI); 701 CHECK(session->chooser) << "Shouldn't close the dialog twice.";
594 discovery_session->Stop( 702
595 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStopped, 703 // Synchronously ensure nothing else calls into the chooser after it has asked
596 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), 704 // to be closed.
597 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStoppedError, 705 session->chooser.reset();
598 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); 706
707 // Yield to the event loop to make sure |callback| isn't called within a
708 // BluetoothDispatcherHost stack frame.
709 if (!base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback)) {
710 LOG(WARNING) << "No TaskRunner; not closing requestDevice dialog.";
711 }
599 } 712 }
600 713
601 void BluetoothDispatcherHost::OnDiscoverySessionStopped(int thread_id, 714 void BluetoothDispatcherHost::DialogCancelled(int chooser_id) {
602 int request_id) { 715 CloseDialog(chooser_id,
603 DCHECK_CURRENTLY_ON(BrowserThread::UI); 716 base::Bind(&BluetoothDispatcherHost::OnRequestDeviceCancelled,
604 auto session = 717 weak_ptr_factory_.GetWeakPtr(), chooser_id));
605 request_device_sessions_.find(std::make_pair(thread_id, request_id));
606 CHECK(session != request_device_sessions_.end());
607 BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
608 for (device::BluetoothDevice* device : devices) {
609 VLOG(1) << "Device: " << device->GetName();
610 VLOG(1) << "UUIDs: ";
611 for (BluetoothUUID uuid : device->GetUUIDs())
612 VLOG(1) << "\t" << uuid.canonical_value();
613 if (MatchesFilters(*device, session->second.filters)) {
614 content::BluetoothDevice device_ipc(
615 device->GetAddress(), // instance_id
616 device->GetName(), // name
617 device->GetBluetoothClass(), // device_class
618 device->GetVendorIDSource(), // vendor_id_source
619 device->GetVendorID(), // vendor_id
620 device->GetProductID(), // product_id
621 device->GetDeviceID(), // product_version
622 device->IsPaired(), // paired
623 content::BluetoothDevice::UUIDsFromBluetoothUUIDs(
624 device->GetUUIDs())); // uuids
625 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::SUCCESS);
626 Send(new BluetoothMsg_RequestDeviceSuccess(thread_id, request_id,
627 device_ipc));
628 request_device_sessions_.erase(session);
629 return;
630 }
631 }
632 RecordRequestDeviceOutcome(
633 UMARequestDeviceOutcome::NO_MATCHING_DEVICES_FOUND);
634 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id,
635 WebBluetoothError::NoDevicesFound));
636 request_device_sessions_.erase(session);
637 } 718 }
638 719
639 void BluetoothDispatcherHost::OnDiscoverySessionStoppedError(int thread_id, 720 void BluetoothDispatcherHost::DeviceSelected(int chooser_id,
640 int request_id) { 721 const std::string& device_id) {
641 DCHECK_CURRENTLY_ON(BrowserThread::UI); 722 CloseDialog(
642 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStoppedError"; 723 chooser_id,
643 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::DISCOVERY_STOP_FAILED); 724 base::Bind(&BluetoothDispatcherHost::OnRequestDeviceSelected,
725 weak_ptr_factory_.GetWeakPtr(), chooser_id, device_id));
726 }
727
728 void BluetoothDispatcherHost::OnRequestDeviceCancelled(int chooser_id) {
729 RequestDeviceSession* session = request_device_sessions_.Lookup(chooser_id);
730 DCHECK(session) << "Session removed unexpectedly.";
731 RecordRequestDeviceOutcome(
732 UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_CANCELLED);
733 VLOG(1) << "Bluetooth chooser cancelled";
644 Send(new BluetoothMsg_RequestDeviceError( 734 Send(new BluetoothMsg_RequestDeviceError(
645 thread_id, request_id, WebBluetoothError::DiscoverySessionStopFailed)); 735 session->thread_id, session->request_id,
646 request_device_sessions_.erase(std::make_pair(thread_id, request_id)); 736 WebBluetoothError::ChooserCancelled));
737 request_device_sessions_.Remove(chooser_id);
738 }
739
740 void BluetoothDispatcherHost::OnRequestDeviceSelected(
741 int chooser_id,
742 const std::string& device_id) {
743 RequestDeviceSession* session = request_device_sessions_.Lookup(chooser_id);
744 DCHECK(session) << "Session removed unexpectedly.";
745
746 const device::BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
747 const device::BluetoothDevice* const device = adapter_->GetDevice(device_id);
748 if (device == nullptr) {
749 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::CHOSEN_DEVICE_VANISHED);
750 Send(new BluetoothMsg_RequestDeviceError(
751 session->thread_id, session->request_id,
752 WebBluetoothError::ChosenDeviceVanished));
753 request_device_sessions_.Remove(chooser_id);
754 return;
755 }
756
757 VLOG(1) << "Device: " << device->GetName();
758 VLOG(1) << "UUIDs: ";
759 for (BluetoothUUID uuid : device->GetUUIDs())
760 VLOG(1) << "\t" << uuid.canonical_value();
761
762 content::BluetoothDevice device_ipc(
763 device->GetAddress(), // instance_id
764 device->GetName(), // name
765 device->GetBluetoothClass(), // device_class
766 device->GetVendorIDSource(), // vendor_id_source
767 device->GetVendorID(), // vendor_id
768 device->GetProductID(), // product_id
769 device->GetDeviceID(), // product_version
770 device->IsPaired(), // paired
771 content::BluetoothDevice::UUIDsFromBluetoothUUIDs(
772 device->GetUUIDs())); // uuids
773 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::SUCCESS);
774 Send(new BluetoothMsg_RequestDeviceSuccess(session->thread_id,
775 session->request_id, device_ipc));
776 request_device_sessions_.Remove(chooser_id);
647 } 777 }
648 778
649 void BluetoothDispatcherHost::OnGATTConnectionCreated( 779 void BluetoothDispatcherHost::OnGATTConnectionCreated(
650 int thread_id, 780 int thread_id,
651 int request_id, 781 int request_id,
652 const std::string& device_instance_id, 782 const std::string& device_instance_id,
653 base::TimeTicks start_time, 783 base::TimeTicks start_time,
654 scoped_ptr<device::BluetoothGattConnection> connection) { 784 scoped_ptr<device::BluetoothGattConnection> connection) {
655 // TODO(ortuno): Save the BluetoothGattConnection so we can disconnect 785 // TODO(ortuno): Save the BluetoothGattConnection so we can disconnect
656 // from it. 786 // from it.
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 int thread_id, 871 int thread_id,
742 int request_id, 872 int request_id,
743 device::BluetoothGattService::GattErrorCode error_code) { 873 device::BluetoothGattService::GattErrorCode error_code) {
744 // TranslateGATTError calls RecordGATTOperationOutcome. 874 // TranslateGATTError calls RecordGATTOperationOutcome.
745 Send(new BluetoothMsg_WriteCharacteristicValueError( 875 Send(new BluetoothMsg_WriteCharacteristicValueError(
746 thread_id, request_id, 876 thread_id, request_id,
747 TranslateGATTError(error_code, UMAGATTOperation::CHARACTERISTIC_WRITE))); 877 TranslateGATTError(error_code, UMAGATTOperation::CHARACTERISTIC_WRITE)));
748 } 878 }
749 879
750 } // namespace content 880 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698