summaryrefslogtreecommitdiffstats
path: root/content/renderer/bluetooth
diff options
context:
space:
mode:
authorjyasskin <jyasskin@chromium.org>2015-07-20 17:27:48 -0700
committerCommit bot <commit-bot@chromium.org>2015-07-21 00:28:23 +0000
commitf89a11b5f43fe6c3a0f31466fdf83f65c5d08f10 (patch)
tree0dca9d816f2549c72e3dc557a80d4a706c9d076d /content/renderer/bluetooth
parent7b425ad85c9afdd4195794cc51ee0316bbcc0464 (diff)
downloadchromium_src-f89a11b5f43fe6c3a0f31466fdf83f65c5d08f10.zip
chromium_src-f89a11b5f43fe6c3a0f31466fdf83f65c5d08f10.tar.gz
chromium_src-f89a11b5f43fe6c3a0f31466fdf83f65c5d08f10.tar.bz2
Move the Web Bluetooth implementation from child/ to renderer/.
Since requestDevice() uses the Frame, and we don't support workers yet, jochen@ wants us to implement in renderer/ for now. This is the second of a 3-patch sequence: 1. Attach a frame-specific WebBluetooth in Blink. (https://codereview.chromium.org/1228283003) 2. Move Web Bluetooth from content/child/ to content/renderer/ (This patch) 3. Put the RenderFrame's ID in that WebBluetooth and plumb it back to the browser. (https://codereview.chromium.org/1228113004/) BUG=500989 Review URL: https://codereview.chromium.org/1234413006 Cr-Commit-Position: refs/heads/master@{#339573}
Diffstat (limited to 'content/renderer/bluetooth')
-rw-r--r--content/renderer/bluetooth/DEPS4
-rw-r--r--content/renderer/bluetooth/OWNERS1
-rw-r--r--content/renderer/bluetooth/PRESUBMIT.py14
-rw-r--r--content/renderer/bluetooth/bluetooth_dispatcher.cc387
-rw-r--r--content/renderer/bluetooth/bluetooth_dispatcher.h143
-rw-r--r--content/renderer/bluetooth/bluetooth_message_filter.cc37
-rw-r--r--content/renderer/bluetooth/bluetooth_message_filter.h30
-rw-r--r--content/renderer/bluetooth/web_bluetooth_impl.cc64
-rw-r--r--content/renderer/bluetooth/web_bluetooth_impl.h58
9 files changed, 738 insertions, 0 deletions
diff --git a/content/renderer/bluetooth/DEPS b/content/renderer/bluetooth/DEPS
new file mode 100644
index 0000000..2c5a329
--- /dev/null
+++ b/content/renderer/bluetooth/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+device/bluetooth",
+]
+
diff --git a/content/renderer/bluetooth/OWNERS b/content/renderer/bluetooth/OWNERS
new file mode 100644
index 0000000..673aeda
--- /dev/null
+++ b/content/renderer/bluetooth/OWNERS
@@ -0,0 +1 @@
+scheib@chromium.org
diff --git a/content/renderer/bluetooth/PRESUBMIT.py b/content/renderer/bluetooth/PRESUBMIT.py
new file mode 100644
index 0000000..3f9babe
--- /dev/null
+++ b/content/renderer/bluetooth/PRESUBMIT.py
@@ -0,0 +1,14 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Presubmit script.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into depot_tools.
+"""
+
+def CheckChangeOnUpload(input_api, output_api):
+ results = []
+ results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
+ return results
diff --git a/content/renderer/bluetooth/bluetooth_dispatcher.cc b/content/renderer/bluetooth/bluetooth_dispatcher.cc
new file mode 100644
index 0000000..d80430b
--- /dev/null
+++ b/content/renderer/bluetooth/bluetooth_dispatcher.cc
@@ -0,0 +1,387 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/bluetooth/bluetooth_dispatcher.h"
+
+#include "base/lazy_instance.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/thread_task_runner_handle.h"
+#include "content/child/thread_safe_sender.h"
+#include "content/common/bluetooth/bluetooth_messages.h"
+#include "device/bluetooth/bluetooth_uuid.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothDevice.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothError.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTCharacteristic.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTRemoteServer.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTService.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebRequestDeviceOptions.h"
+
+using blink::WebBluetoothConnectGATTCallbacks;
+using blink::WebBluetoothDevice;
+using blink::WebBluetoothError;
+using blink::WebBluetoothGATTCharacteristic;
+using blink::WebBluetoothGATTRemoteServer;
+using blink::WebBluetoothGATTService;
+using blink::WebBluetoothReadValueCallbacks;
+using blink::WebBluetoothRequestDeviceCallbacks;
+using blink::WebBluetoothScanFilter;
+using blink::WebRequestDeviceOptions;
+using blink::WebString;
+using blink::WebVector;
+
+struct BluetoothPrimaryServiceRequest {
+ BluetoothPrimaryServiceRequest(
+ blink::WebString device_instance_id,
+ blink::WebString service_uuid,
+ blink::WebBluetoothGetPrimaryServiceCallbacks* callbacks)
+ : device_instance_id(device_instance_id),
+ service_uuid(service_uuid),
+ callbacks(callbacks) {}
+ ~BluetoothPrimaryServiceRequest() {}
+
+ blink::WebString device_instance_id;
+ blink::WebString service_uuid;
+ scoped_ptr<blink::WebBluetoothGetPrimaryServiceCallbacks> callbacks;
+};
+
+struct BluetoothCharacteristicRequest {
+ BluetoothCharacteristicRequest(
+ blink::WebString service_instance_id,
+ blink::WebString characteristic_uuid,
+ blink::WebBluetoothGetCharacteristicCallbacks* callbacks)
+ : service_instance_id(service_instance_id),
+ characteristic_uuid(characteristic_uuid),
+ callbacks(callbacks) {}
+ ~BluetoothCharacteristicRequest() {}
+
+ blink::WebString service_instance_id;
+ blink::WebString characteristic_uuid;
+ scoped_ptr<blink::WebBluetoothGetCharacteristicCallbacks> callbacks;
+};
+
+namespace content {
+
+namespace {
+
+base::LazyInstance<base::ThreadLocalPointer<BluetoothDispatcher>>::Leaky
+ g_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
+
+BluetoothDispatcher* const kHasBeenDeleted =
+ reinterpret_cast<BluetoothDispatcher*>(0x1);
+
+int CurrentWorkerId() {
+ return WorkerTaskRunner::Instance()->CurrentWorkerId();
+}
+
+WebBluetoothDevice::VendorIDSource GetWebVendorIdSource(
+ device::BluetoothDevice::VendorIDSource vendor_id_source) {
+ switch (vendor_id_source) {
+ case device::BluetoothDevice::VENDOR_ID_UNKNOWN:
+ return WebBluetoothDevice::VendorIDSource::Unknown;
+ case device::BluetoothDevice::VENDOR_ID_BLUETOOTH:
+ return WebBluetoothDevice::VendorIDSource::Bluetooth;
+ case device::BluetoothDevice::VENDOR_ID_USB:
+ return WebBluetoothDevice::VendorIDSource::USB;
+ }
+ NOTREACHED();
+ return WebBluetoothDevice::VendorIDSource::Unknown;
+}
+
+} // namespace
+
+BluetoothDispatcher::BluetoothDispatcher(ThreadSafeSender* sender)
+ : thread_safe_sender_(sender) {
+ g_dispatcher_tls.Pointer()->Set(this);
+}
+
+BluetoothDispatcher::~BluetoothDispatcher() {
+ g_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
+}
+
+BluetoothDispatcher* BluetoothDispatcher::GetOrCreateThreadSpecificInstance(
+ ThreadSafeSender* thread_safe_sender) {
+ if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
+ NOTREACHED() << "Re-instantiating TLS BluetoothDispatcher.";
+ g_dispatcher_tls.Pointer()->Set(NULL);
+ }
+ if (g_dispatcher_tls.Pointer()->Get())
+ return g_dispatcher_tls.Pointer()->Get();
+
+ BluetoothDispatcher* dispatcher = new BluetoothDispatcher(thread_safe_sender);
+ if (CurrentWorkerId())
+ WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
+ return dispatcher;
+}
+
+bool BluetoothDispatcher::Send(IPC::Message* msg) {
+ return thread_safe_sender_->Send(msg);
+}
+
+void BluetoothDispatcher::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(BluetoothDispatcher, msg)
+ IPC_MESSAGE_HANDLER(BluetoothMsg_RequestDeviceSuccess,
+ OnRequestDeviceSuccess);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_RequestDeviceError, OnRequestDeviceError);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_ConnectGATTSuccess, OnConnectGATTSuccess);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_ConnectGATTError, OnConnectGATTError);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_GetPrimaryServiceSuccess,
+ OnGetPrimaryServiceSuccess);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_GetPrimaryServiceError,
+ OnGetPrimaryServiceError);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_GetCharacteristicSuccess,
+ OnGetCharacteristicSuccess);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_GetCharacteristicError,
+ OnGetCharacteristicError);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_ReadCharacteristicValueSuccess,
+ OnReadValueSuccess);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_ReadCharacteristicValueError,
+ OnReadValueError);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueSuccess,
+ OnWriteValueSuccess);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueError,
+ OnWriteValueError);
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ DCHECK(handled) << "Unhandled message:" << msg.type();
+}
+
+void BluetoothDispatcher::requestDevice(
+ const WebRequestDeviceOptions& options,
+ blink::WebBluetoothRequestDeviceCallbacks* callbacks) {
+ int request_id = pending_requests_.Add(callbacks);
+
+ // Convert |options| to its IPC form.
+ std::vector<content::BluetoothScanFilter> filters(options.filters.size());
+ for (size_t i = 0; i < options.filters.size(); ++i) {
+ const WebBluetoothScanFilter& web_filter = options.filters[i];
+ BluetoothScanFilter& filter = filters[i];
+ filter.services.reserve(web_filter.services.size());
+ for (const WebString& service : web_filter.services) {
+ filter.services.push_back(device::BluetoothUUID(service.utf8()));
+ }
+ }
+ std::vector<device::BluetoothUUID> optional_services;
+ optional_services.reserve(options.optionalServices.size());
+ for (const WebString& optional_service : options.optionalServices) {
+ optional_services.push_back(device::BluetoothUUID(optional_service.utf8()));
+ }
+
+ Send(new BluetoothHostMsg_RequestDevice(CurrentWorkerId(), request_id,
+ filters, optional_services));
+}
+
+void BluetoothDispatcher::connectGATT(
+ const blink::WebString& device_instance_id,
+ blink::WebBluetoothConnectGATTCallbacks* callbacks) {
+ int request_id = pending_connect_requests_.Add(callbacks);
+ Send(new BluetoothHostMsg_ConnectGATT(CurrentWorkerId(), request_id,
+ device_instance_id.utf8()));
+}
+
+void BluetoothDispatcher::getPrimaryService(
+ const blink::WebString& device_instance_id,
+ const blink::WebString& service_uuid,
+ blink::WebBluetoothGetPrimaryServiceCallbacks* callbacks) {
+ int request_id =
+ pending_primary_service_requests_.Add(new BluetoothPrimaryServiceRequest(
+ device_instance_id, service_uuid, callbacks));
+ Send(new BluetoothHostMsg_GetPrimaryService(CurrentWorkerId(), request_id,
+ device_instance_id.utf8(),
+ service_uuid.utf8()));
+}
+
+void BluetoothDispatcher::getCharacteristic(
+ const blink::WebString& service_instance_id,
+ const blink::WebString& characteristic_uuid,
+ blink::WebBluetoothGetCharacteristicCallbacks* callbacks) {
+ int request_id =
+ pending_characteristic_requests_.Add(new BluetoothCharacteristicRequest(
+ service_instance_id, characteristic_uuid, callbacks));
+ Send(new BluetoothHostMsg_GetCharacteristic(CurrentWorkerId(), request_id,
+ service_instance_id.utf8(),
+ characteristic_uuid.utf8()));
+}
+
+void BluetoothDispatcher::readValue(
+ const blink::WebString& characteristic_instance_id,
+ blink::WebBluetoothReadValueCallbacks* callbacks) {
+ int request_id = pending_read_value_requests_.Add(callbacks);
+ Send(new BluetoothHostMsg_ReadValue(CurrentWorkerId(), request_id,
+ characteristic_instance_id.utf8()));
+}
+
+void BluetoothDispatcher::writeValue(
+ const blink::WebString& characteristic_instance_id,
+ const std::vector<uint8_t>& value,
+ blink::WebBluetoothWriteValueCallbacks* callbacks) {
+ int request_id = pending_write_value_requests_.Add(callbacks);
+
+ Send(new BluetoothHostMsg_WriteValue(
+ CurrentWorkerId(), request_id, characteristic_instance_id.utf8(), value));
+}
+
+void BluetoothDispatcher::OnWorkerRunLoopStopped() {
+ delete this;
+}
+
+void BluetoothDispatcher::OnRequestDeviceSuccess(
+ int thread_id,
+ int request_id,
+ const BluetoothDevice& device) {
+ DCHECK(pending_requests_.Lookup(request_id)) << request_id;
+
+ WebVector<WebString> uuids(device.uuids.size());
+ for (size_t i = 0; i < device.uuids.size(); ++i)
+ uuids[i] = WebString::fromUTF8(device.uuids[i].c_str());
+
+ pending_requests_.Lookup(request_id)
+ ->onSuccess(new WebBluetoothDevice(
+ WebString::fromUTF8(device.instance_id), WebString(device.name),
+ device.device_class, GetWebVendorIdSource(device.vendor_id_source),
+ device.vendor_id, device.product_id, device.product_version,
+ device.paired, uuids));
+ pending_requests_.Remove(request_id);
+}
+
+void BluetoothDispatcher::OnRequestDeviceError(int thread_id,
+ int request_id,
+ WebBluetoothError error) {
+ DCHECK(pending_requests_.Lookup(request_id)) << request_id;
+ pending_requests_.Lookup(request_id)->onError(new WebBluetoothError(error));
+ pending_requests_.Remove(request_id);
+}
+
+void BluetoothDispatcher::OnConnectGATTSuccess(
+ int thread_id,
+ int request_id,
+ const std::string& device_instance_id) {
+ DCHECK(pending_connect_requests_.Lookup(request_id)) << request_id;
+ pending_connect_requests_.Lookup(request_id)
+ ->onSuccess(new WebBluetoothGATTRemoteServer(
+ WebString::fromUTF8(device_instance_id), true /* connected */));
+ pending_connect_requests_.Remove(request_id);
+}
+
+void BluetoothDispatcher::OnConnectGATTError(int thread_id,
+ int request_id,
+ WebBluetoothError error) {
+ DCHECK(pending_connect_requests_.Lookup(request_id)) << request_id;
+ pending_connect_requests_.Lookup(request_id)
+ ->onError(new WebBluetoothError(error));
+ pending_connect_requests_.Remove(request_id);
+}
+
+void BluetoothDispatcher::OnGetPrimaryServiceSuccess(
+ int thread_id,
+ int request_id,
+ const std::string& service_instance_id) {
+ DCHECK(pending_primary_service_requests_.Lookup(request_id)) << request_id;
+ BluetoothPrimaryServiceRequest* request =
+ pending_primary_service_requests_.Lookup(request_id);
+ request->callbacks->onSuccess(new WebBluetoothGATTService(
+ WebString::fromUTF8(service_instance_id), request->service_uuid,
+ true /* isPrimary */, request->device_instance_id));
+ pending_primary_service_requests_.Remove(request_id);
+}
+
+void BluetoothDispatcher::OnGetPrimaryServiceError(int thread_id,
+ int request_id,
+ WebBluetoothError error) {
+ DCHECK(pending_primary_service_requests_.Lookup(request_id)) << request_id;
+
+ // Since we couldn't find the service return null. See Step 3 of
+ // getPrimaryService algorithm:
+ // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattremoteserver-getprimaryservice
+ if (error == WebBluetoothError::ServiceNotFound) {
+ pending_primary_service_requests_.Lookup(request_id)
+ ->callbacks->onSuccess(nullptr);
+ pending_primary_service_requests_.Remove(request_id);
+ return;
+ }
+
+ pending_primary_service_requests_.Lookup(request_id)
+ ->callbacks->onError(new WebBluetoothError(error));
+ pending_primary_service_requests_.Remove(request_id);
+}
+
+void BluetoothDispatcher::OnGetCharacteristicSuccess(
+ int thread_id,
+ int request_id,
+ const std::string& characteristic_instance_id) {
+ DCHECK(pending_characteristic_requests_.Lookup(request_id)) << request_id;
+
+ BluetoothCharacteristicRequest* request =
+ pending_characteristic_requests_.Lookup(request_id);
+ request->callbacks->onSuccess(new WebBluetoothGATTCharacteristic(
+ WebString::fromUTF8(characteristic_instance_id),
+ request->service_instance_id, request->characteristic_uuid));
+
+ pending_characteristic_requests_.Remove(request_id);
+}
+
+void BluetoothDispatcher::OnGetCharacteristicError(int thread_id,
+ int request_id,
+ WebBluetoothError error) {
+ DCHECK(pending_characteristic_requests_.Lookup(request_id)) << request_id;
+
+ // Since we couldn't find the characteristic return null. See Step 3 of
+ // getCharacteristic algorithm:
+ // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattservice-getcharacteristic
+ if (error == WebBluetoothError::CharacteristicNotFound) {
+ pending_characteristic_requests_.Lookup(request_id)
+ ->callbacks->onSuccess(nullptr);
+ } else {
+ pending_characteristic_requests_.Lookup(request_id)
+ ->callbacks->onError(new WebBluetoothError(error));
+ }
+ pending_characteristic_requests_.Remove(request_id);
+}
+
+void BluetoothDispatcher::OnReadValueSuccess(
+ int thread_id,
+ int request_id,
+ const std::vector<uint8_t>& value) {
+ DCHECK(pending_read_value_requests_.Lookup(request_id)) << request_id;
+
+ // WebArrayBuffer is not accessible from Source/modules so we pass a
+ // WebVector instead.
+ pending_read_value_requests_.Lookup(request_id)
+ ->onSuccess(new WebVector<uint8_t>(value));
+
+ pending_read_value_requests_.Remove(request_id);
+}
+
+void BluetoothDispatcher::OnReadValueError(int thread_id,
+ int request_id,
+ WebBluetoothError error) {
+ DCHECK(pending_read_value_requests_.Lookup(request_id)) << request_id;
+
+ pending_read_value_requests_.Lookup(request_id)
+ ->onError(new WebBluetoothError(error));
+
+ pending_read_value_requests_.Remove(request_id);
+}
+
+void BluetoothDispatcher::OnWriteValueSuccess(int thread_id, int request_id) {
+ DCHECK(pending_write_value_requests_.Lookup(request_id)) << request_id;
+
+ pending_write_value_requests_.Lookup(request_id)->onSuccess();
+
+ pending_write_value_requests_.Remove(request_id);
+}
+
+void BluetoothDispatcher::OnWriteValueError(int thread_id,
+ int request_id,
+ WebBluetoothError error) {
+ DCHECK(pending_write_value_requests_.Lookup(request_id)) << request_id;
+
+ pending_write_value_requests_.Lookup(request_id)
+ ->onError(new WebBluetoothError(error));
+
+ pending_write_value_requests_.Remove(request_id);
+}
+
+} // namespace content
diff --git a/content/renderer/bluetooth/bluetooth_dispatcher.h b/content/renderer/bluetooth/bluetooth_dispatcher.h
new file mode 100644
index 0000000..97e43cd
--- /dev/null
+++ b/content/renderer/bluetooth/bluetooth_dispatcher.h
@@ -0,0 +1,143 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_CHILD_BLUETOOTH_BLUETOOTH_DISPATCHER_H_
+#define CONTENT_CHILD_BLUETOOTH_BLUETOOTH_DISPATCHER_H_
+
+#include "base/id_map.h"
+#include "base/memory/ref_counted.h"
+#include "content/child/worker_task_runner.h"
+#include "content/common/bluetooth/bluetooth_device.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetooth.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothError.h"
+
+namespace base {
+class MessageLoop;
+class TaskRunner;
+}
+
+namespace IPC {
+class Message;
+}
+
+struct BluetoothCharacteristicRequest;
+struct BluetoothPrimaryServiceRequest;
+
+namespace content {
+class ThreadSafeSender;
+
+// Dispatcher for child process threads which communicates to the browser's
+// BluetoothDispatcherHost.
+//
+// Instances are created for each thread as necessary by WebBluetoothImpl.
+//
+// Incoming IPC messages are received by the BluetoothMessageFilter and
+// directed to the thread specific instance of this class.
+// Outgoing messages come from WebBluetoothImpl.
+class BluetoothDispatcher : public WorkerTaskRunner::Observer {
+ public:
+ explicit BluetoothDispatcher(ThreadSafeSender* sender);
+ ~BluetoothDispatcher() override;
+
+ // Gets or Creates a BluetoothDispatcher for the current thread.
+ // |thread_safe_sender| is required when constructing a BluetoothDispatcher.
+ static BluetoothDispatcher* GetOrCreateThreadSpecificInstance(
+ ThreadSafeSender* thread_safe_sender);
+
+ // IPC Send and Receiving interface, see IPC::Sender and IPC::Listener.
+ bool Send(IPC::Message* msg);
+ void OnMessageReceived(const IPC::Message& msg);
+
+ // Corresponding to WebBluetoothImpl methods.
+ void requestDevice(const blink::WebRequestDeviceOptions& options,
+ blink::WebBluetoothRequestDeviceCallbacks* callbacks);
+ void connectGATT(const blink::WebString& device_instance_id,
+ blink::WebBluetoothConnectGATTCallbacks* callbacks);
+ void getPrimaryService(
+ const blink::WebString& device_instance_id,
+ const blink::WebString& service_uuid,
+ blink::WebBluetoothGetPrimaryServiceCallbacks* callbacks);
+
+ void getCharacteristic(
+ const blink::WebString& service_instance_id,
+ const blink::WebString& characteristic_uuid,
+ blink::WebBluetoothGetCharacteristicCallbacks* callbacks);
+ void readValue(const blink::WebString& characteristic_instance_id,
+ blink::WebBluetoothReadValueCallbacks* callbacks);
+ void writeValue(const blink::WebString& characteristic_instance_id,
+ const std::vector<uint8_t>& value,
+ blink::WebBluetoothWriteValueCallbacks*);
+
+ // WorkerTaskRunner::Observer implementation.
+ void OnWorkerRunLoopStopped() override;
+
+ private:
+ // IPC Handlers, see definitions in bluetooth_messages.h.
+ void OnRequestDeviceSuccess(int thread_id,
+ int request_id,
+ const BluetoothDevice& device);
+ void OnRequestDeviceError(int thread_id,
+ int request_id,
+ blink::WebBluetoothError error);
+
+ void OnConnectGATTSuccess(int thread_id,
+ int request_id,
+ const std::string& message);
+
+ void OnConnectGATTError(int thread_id,
+ int request_id,
+ blink::WebBluetoothError error);
+ void OnGetPrimaryServiceSuccess(int thread_id,
+ int request_id,
+ const std::string& service_instance_id);
+ void OnGetPrimaryServiceError(int thread_id,
+ int request_id,
+ blink::WebBluetoothError error);
+ void OnGetCharacteristicSuccess(
+ int thread_id,
+ int request_id,
+ const std::string& characteristic_instance_id);
+ void OnGetCharacteristicError(int thread_id,
+ int request_id,
+ blink::WebBluetoothError error);
+ void OnReadValueSuccess(int thread_id,
+ int request_id,
+ const std::vector<uint8_t>& value);
+ void OnReadValueError(int thread_id,
+ int request_id,
+ blink::WebBluetoothError error);
+ void OnWriteValueSuccess(int thread_id, int request_id);
+ void OnWriteValueError(int thread_id,
+ int request_id,
+ blink::WebBluetoothError error);
+
+ scoped_refptr<ThreadSafeSender> thread_safe_sender_;
+
+ // Tracks device requests sent to browser to match replies with callbacks.
+ // Owns callback objects.
+ IDMap<blink::WebBluetoothRequestDeviceCallbacks, IDMapOwnPointer>
+ pending_requests_;
+ // Tracks requests to connect to a device.
+ // Owns callback objects.
+ IDMap<blink::WebBluetoothConnectGATTCallbacks, IDMapOwnPointer>
+ pending_connect_requests_;
+ // Tracks requests to get a primary service from a device.
+ // Owns request objects.
+ IDMap<BluetoothPrimaryServiceRequest, IDMapOwnPointer>
+ pending_primary_service_requests_;
+ // Tracks requests to get a characteristic from a service.
+ IDMap<BluetoothCharacteristicRequest, IDMapOwnPointer>
+ pending_characteristic_requests_;
+ // Tracks requests to read from a characteristics.
+ IDMap<blink::WebBluetoothReadValueCallbacks, IDMapOwnPointer>
+ pending_read_value_requests_;
+ IDMap<blink::WebBluetoothWriteValueCallbacks, IDMapOwnPointer>
+ pending_write_value_requests_;
+
+ DISALLOW_COPY_AND_ASSIGN(BluetoothDispatcher);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_BLUETOOTH_BLUETOOTH_DISPATCHER_H_
diff --git a/content/renderer/bluetooth/bluetooth_message_filter.cc b/content/renderer/bluetooth/bluetooth_message_filter.cc
new file mode 100644
index 0000000..bd688da
--- /dev/null
+++ b/content/renderer/bluetooth/bluetooth_message_filter.cc
@@ -0,0 +1,37 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/bluetooth/bluetooth_message_filter.h"
+
+#include "content/child/thread_safe_sender.h"
+#include "content/renderer/bluetooth/bluetooth_dispatcher.h"
+#include "ipc/ipc_message_macros.h"
+
+namespace content {
+
+BluetoothMessageFilter::BluetoothMessageFilter(ThreadSafeSender* sender)
+ : WorkerThreadMessageFilter(sender) {
+}
+
+BluetoothMessageFilter::~BluetoothMessageFilter() {
+}
+
+bool BluetoothMessageFilter::ShouldHandleMessage(
+ const IPC::Message& msg) const {
+ return IPC_MESSAGE_CLASS(msg) == BluetoothMsgStart;
+}
+
+void BluetoothMessageFilter::OnFilteredMessageReceived(
+ const IPC::Message& msg) {
+ BluetoothDispatcher::GetOrCreateThreadSpecificInstance(thread_safe_sender())
+ ->OnMessageReceived(msg);
+}
+
+bool BluetoothMessageFilter::GetWorkerThreadIdForMessage(
+ const IPC::Message& msg,
+ int* ipc_thread_id) {
+ return base::PickleIterator(msg).ReadInt(ipc_thread_id);
+}
+
+} // namespace content
diff --git a/content/renderer/bluetooth/bluetooth_message_filter.h b/content/renderer/bluetooth/bluetooth_message_filter.h
new file mode 100644
index 0000000..5692dcc
--- /dev/null
+++ b/content/renderer/bluetooth/bluetooth_message_filter.h
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_CHILD_BLUETOOTH_BLUETOOTH_MESSAGE_FILTER_H_
+#define CONTENT_CHILD_BLUETOOTH_BLUETOOTH_MESSAGE_FILTER_H_
+
+#include "content/child/worker_thread_message_filter.h"
+
+namespace content {
+
+class BluetoothMessageFilter : public WorkerThreadMessageFilter {
+ public:
+ explicit BluetoothMessageFilter(ThreadSafeSender* thread_safe_sender);
+
+ private:
+ ~BluetoothMessageFilter() override;
+
+ // WorkerThreadMessageFilter:
+ bool ShouldHandleMessage(const IPC::Message& msg) const override;
+ void OnFilteredMessageReceived(const IPC::Message& msg) override;
+ bool GetWorkerThreadIdForMessage(const IPC::Message& msg,
+ int* ipc_thread_id) override;
+
+ DISALLOW_COPY_AND_ASSIGN(BluetoothMessageFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_BLUETOOTH_BLUETOOTH_MESSAGE_FILTER_H_
diff --git a/content/renderer/bluetooth/web_bluetooth_impl.cc b/content/renderer/bluetooth/web_bluetooth_impl.cc
new file mode 100644
index 0000000..1c62c04
--- /dev/null
+++ b/content/renderer/bluetooth/web_bluetooth_impl.cc
@@ -0,0 +1,64 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/bluetooth/web_bluetooth_impl.h"
+
+#include "content/child/thread_safe_sender.h"
+#include "content/renderer/bluetooth/bluetooth_dispatcher.h"
+
+namespace content {
+
+WebBluetoothImpl::WebBluetoothImpl(ThreadSafeSender* thread_safe_sender)
+ : thread_safe_sender_(thread_safe_sender) {
+}
+
+WebBluetoothImpl::~WebBluetoothImpl() {
+}
+
+void WebBluetoothImpl::requestDevice(
+ const blink::WebRequestDeviceOptions& options,
+ blink::WebBluetoothRequestDeviceCallbacks* callbacks) {
+ GetDispatcher()->requestDevice(options, callbacks);
+}
+
+void WebBluetoothImpl::connectGATT(const blink::WebString& device_instance_id,
+ blink::WebBluetoothConnectGATTCallbacks* callbacks) {
+ GetDispatcher()->connectGATT(device_instance_id, callbacks);
+}
+
+void WebBluetoothImpl::getPrimaryService(
+ const blink::WebString& device_instance_id,
+ const blink::WebString& service_uuid,
+ blink::WebBluetoothGetPrimaryServiceCallbacks* callbacks) {
+ GetDispatcher()->getPrimaryService(device_instance_id, service_uuid,
+ callbacks);
+}
+
+void WebBluetoothImpl::getCharacteristic(
+ const blink::WebString& service_instance_id,
+ const blink::WebString& characteristic_uuid,
+ blink::WebBluetoothGetCharacteristicCallbacks* callbacks) {
+ GetDispatcher()->getCharacteristic(service_instance_id, characteristic_uuid,
+ callbacks);
+}
+
+void WebBluetoothImpl::readValue(
+ const blink::WebString& characteristic_instance_id,
+ blink::WebBluetoothReadValueCallbacks* callbacks) {
+ GetDispatcher()->readValue(characteristic_instance_id, callbacks);
+}
+
+void WebBluetoothImpl::writeValue(
+ const blink::WebString& characteristic_instance_id,
+ const std::vector<uint8_t>& value,
+ blink::WebBluetoothWriteValueCallbacks* callbacks) {
+ GetDispatcher()->writeValue(characteristic_instance_id, value, callbacks);
+}
+
+BluetoothDispatcher* WebBluetoothImpl::GetDispatcher() {
+ return BluetoothDispatcher::GetOrCreateThreadSpecificInstance(
+ thread_safe_sender_.get());
+}
+
+} // namespace content
diff --git a/content/renderer/bluetooth/web_bluetooth_impl.h b/content/renderer/bluetooth/web_bluetooth_impl.h
new file mode 100644
index 0000000..5eede0e
--- /dev/null
+++ b/content/renderer/bluetooth/web_bluetooth_impl.h
@@ -0,0 +1,58 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_CHILD_BLUETOOTH_WEB_BLUETOOTH_IMPL_H_
+#define CONTENT_CHILD_BLUETOOTH_WEB_BLUETOOTH_IMPL_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetooth.h"
+
+namespace content {
+
+class BluetoothDispatcher;
+class ThreadSafeSender;
+
+// Implementation of blink::WebBluetooth. Passes calls through to the thread
+// specific BluetoothDispatcher.
+class CONTENT_EXPORT WebBluetoothImpl
+ : NON_EXPORTED_BASE(public blink::WebBluetooth) {
+ public:
+ explicit WebBluetoothImpl(ThreadSafeSender* thread_safe_sender);
+ ~WebBluetoothImpl();
+
+ // blink::WebBluetooth interface:
+ void requestDevice(
+ const blink::WebRequestDeviceOptions& options,
+ blink::WebBluetoothRequestDeviceCallbacks* callbacks) override;
+ void connectGATT(const blink::WebString& device_instance_id,
+ blink::WebBluetoothConnectGATTCallbacks* callbacks) override;
+ void getPrimaryService(
+ const blink::WebString& device_instance_id,
+ const blink::WebString& service_uuid,
+ blink::WebBluetoothGetPrimaryServiceCallbacks* callbacks) override;
+ void getCharacteristic(
+ const blink::WebString& service_instance_id,
+ const blink::WebString& characteristic_uuid,
+ blink::WebBluetoothGetCharacteristicCallbacks* callbacks) override;
+ void readValue(const blink::WebString& characteristic_instance_id,
+ blink::WebBluetoothReadValueCallbacks* callbacks) override;
+ void writeValue(const blink::WebString& characteristic_instance_id,
+ const std::vector<uint8_t>& value,
+ blink::WebBluetoothWriteValueCallbacks*) override;
+
+ private:
+ BluetoothDispatcher* GetDispatcher();
+
+ scoped_refptr<ThreadSafeSender> thread_safe_sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebBluetoothImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_BLUETOOTH_WEB_BLUETOOTH_IMPL_H_