summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorortuno <ortuno@chromium.org>2015-07-08 14:35:20 -0700
committerCommit bot <commit-bot@chromium.org>2015-07-08 21:35:50 +0000
commitaf85f60db9f8a89b2b4446e47c73f7cc44dcf4c6 (patch)
treeaeca3b55398142b642b1772e2eb17a736e24b2f2
parentb0caed2bedfc19825ba34024c4678adf351d561c (diff)
downloadchromium_src-af85f60db9f8a89b2b4446e47c73f7cc44dcf4c6.zip
chromium_src-af85f60db9f8a89b2b4446e47c73f7cc44dcf4c6.tar.gz
chromium_src-af85f60db9f8a89b2b4446e47c73f7cc44dcf4c6.tar.bz2
bluetooth: browser-side implementation of writeValue.
Chrome spec repo update: https://github.com/WebBluetoothChrome/web-bluetooth/pull/12 This is the second of three patches to implement writeValue(): [1] http://crrev.com/1212943006 (Blink-side interface) [2] This patch. [3] http://crrev.com/1218803008 (Blink-side implementation) BUG=507415 Review URL: https://codereview.chromium.org/1217983004 Cr-Commit-Position: refs/heads/master@{#337912}
-rw-r--r--content/browser/bad_message.h1
-rw-r--r--content/browser/bluetooth/bluetooth_dispatcher_host.cc82
-rw-r--r--content/browser/bluetooth/bluetooth_dispatcher_host.h10
-rw-r--r--content/child/bluetooth/bluetooth_dispatcher.cc36
-rw-r--r--content/child/bluetooth/bluetooth_dispatcher.h10
-rw-r--r--content/child/bluetooth/web_bluetooth_impl.cc7
-rw-r--r--content/child/bluetooth/web_bluetooth_impl.h3
-rw-r--r--content/common/bluetooth/bluetooth_messages.h21
-rw-r--r--content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc7
-rw-r--r--content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h5
-rw-r--r--tools/metrics/histograms/histograms.xml1
11 files changed, 181 insertions, 2 deletions
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
index 30d33d4..796f66a 100644
--- a/content/browser/bad_message.h
+++ b/content/browser/bad_message.h
@@ -113,6 +113,7 @@ enum BadMessageReason {
SWDH_UPDATE_BAD_REGISTRATION_ID = 87,
SWDH_UPDATE_CANNOT = 88,
SWDH_UNREGISTER_BAD_REGISTRATION_ID = 89,
+ BDH_INVALID_WRITE_VALUE_LENGTH = 90,
// Please add new elements here. The naming convention is abbreviated class
// name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/content/browser/bluetooth/bluetooth_dispatcher_host.cc b/content/browser/bluetooth/bluetooth_dispatcher_host.cc
index 6ccc37b..987a067 100644
--- a/content/browser/bluetooth/bluetooth_dispatcher_host.cc
+++ b/content/browser/bluetooth/bluetooth_dispatcher_host.cc
@@ -189,6 +189,7 @@ bool BluetoothDispatcherHost::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(BluetoothHostMsg_GetPrimaryService, OnGetPrimaryService)
IPC_MESSAGE_HANDLER(BluetoothHostMsg_GetCharacteristic, OnGetCharacteristic)
IPC_MESSAGE_HANDLER(BluetoothHostMsg_ReadValue, OnReadValue)
+ IPC_MESSAGE_HANDLER(BluetoothHostMsg_WriteValue, OnWriteValue)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -432,6 +433,72 @@ void BluetoothDispatcherHost::OnReadValue(
weak_ptr_factory_.GetWeakPtr(), thread_id, request_id));
}
+void BluetoothDispatcherHost::OnWriteValue(
+ int thread_id,
+ int request_id,
+ const std::string& characteristic_instance_id,
+ const std::vector<uint8_t>& value) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // Length check per step 3 of writeValue algorithm:
+ // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattcharacteristic-writevalue
+ // We perform the length check on the renderer side. So if we
+ // get a value with length > 512, we can assume it's a hostile
+ // renderer and kill it.
+ if (value.size() > 512) {
+ bad_message::ReceivedBadMessage(
+ this, bad_message::BDH_INVALID_WRITE_VALUE_LENGTH);
+ return;
+ }
+
+ auto characteristic_iter =
+ characteristic_to_service_.find(characteristic_instance_id);
+ // A characteristic_instance_id not in the map implies a hostile renderer
+ // because a renderer obtains the characteristic id from this class and
+ // it will be added to the map at that time.
+ if (characteristic_iter == characteristic_to_service_.end()) {
+ bad_message::ReceivedBadMessage(this,
+ bad_message::BDH_INVALID_CHARACTERISTIC_ID);
+ return;
+ }
+ const std::string& service_instance_id = characteristic_iter->second;
+
+ auto device_iter = service_to_device_.find(service_instance_id);
+
+ CHECK(device_iter != service_to_device_.end());
+
+ device::BluetoothDevice* device =
+ adapter_->GetDevice(device_iter->second /* device_instance_id */);
+ if (device == nullptr) { // See "NETWORK_ERROR Note" above.
+ Send(new BluetoothMsg_WriteCharacteristicValueError(
+ thread_id, request_id, BluetoothError::NETWORK,
+ kDeviceNoLongerInRange));
+ return;
+ }
+
+ BluetoothGattService* service = device->GetGattService(service_instance_id);
+ if (service == nullptr) {
+ Send(new BluetoothMsg_WriteCharacteristicValueError(
+ thread_id, request_id, BluetoothError::INVALID_STATE,
+ kServiceNoLongerExists));
+ return;
+ }
+
+ BluetoothGattCharacteristic* characteristic =
+ service->GetCharacteristic(characteristic_instance_id);
+ if (characteristic == nullptr) {
+ Send(new BluetoothMsg_WriteCharacteristicValueError(
+ thread_id, request_id, BluetoothError::INVALID_STATE,
+ kCharacteristicNoLongerExits));
+ return;
+ }
+ characteristic->WriteRemoteCharacteristic(
+ value, base::Bind(&BluetoothDispatcherHost::OnWriteValueSuccess,
+ weak_ptr_factory_.GetWeakPtr(), thread_id, request_id),
+ base::Bind(&BluetoothDispatcherHost::OnWriteValueFailed,
+ weak_ptr_factory_.GetWeakPtr(), thread_id, request_id));
+}
+
void BluetoothDispatcherHost::OnDiscoverySessionStarted(
int thread_id,
int request_id,
@@ -582,4 +649,19 @@ void BluetoothDispatcherHost::OnCharacteristicReadValueError(
thread_id, request_id, error.first, error.second));
}
+void BluetoothDispatcherHost::OnWriteValueSuccess(int thread_id,
+ int request_id) {
+ Send(new BluetoothMsg_WriteCharacteristicValueSuccess(thread_id, request_id));
+}
+
+void BluetoothDispatcherHost::OnWriteValueFailed(
+ int thread_id,
+ int request_id,
+ device::BluetoothGattService::GattErrorCode error_code) {
+ std::pair<BluetoothError, std::string> error = TranslateGATTError(error_code);
+
+ Send(new BluetoothMsg_WriteCharacteristicValueError(
+ thread_id, request_id, error.first, error.second));
+}
+
} // namespace content
diff --git a/content/browser/bluetooth/bluetooth_dispatcher_host.h b/content/browser/bluetooth/bluetooth_dispatcher_host.h
index 0e02382..f448468 100644
--- a/content/browser/bluetooth/bluetooth_dispatcher_host.h
+++ b/content/browser/bluetooth/bluetooth_dispatcher_host.h
@@ -77,6 +77,10 @@ class CONTENT_EXPORT BluetoothDispatcherHost final
void OnReadValue(int thread_id,
int request_id,
const std::string& characteristic_instance_id);
+ void OnWriteValue(int thread_id,
+ int request_id,
+ const std::string& characteristic_instance_id,
+ const std::vector<uint8_t>& value);
// Callbacks for BluetoothAdapter::StartDiscoverySession.
void OnDiscoverySessionStarted(
@@ -128,6 +132,12 @@ class CONTENT_EXPORT BluetoothDispatcherHost final
int request_id,
device::BluetoothGattService::GattErrorCode);
+ // Callbacks for BluetoothGattCharacteristic::WriteRemoteCharacteristic.
+ void OnWriteValueSuccess(int thread_id, int request_id);
+ void OnWriteValueFailed(int thread_id,
+ int request_id,
+ device::BluetoothGattService::GattErrorCode);
+
// Maps to get the object's parent based on it's instanceID
// Map of service_instance_id to device_instance_id.
std::map<std::string, std::string> service_to_device_;
diff --git a/content/child/bluetooth/bluetooth_dispatcher.cc b/content/child/bluetooth/bluetooth_dispatcher.cc
index 2643752..82530d9 100644
--- a/content/child/bluetooth/bluetooth_dispatcher.cc
+++ b/content/child/bluetooth/bluetooth_dispatcher.cc
@@ -163,6 +163,10 @@ void BluetoothDispatcher::OnMessageReceived(const IPC::Message& msg) {
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();
@@ -233,6 +237,16 @@ void BluetoothDispatcher::readValue(
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;
}
@@ -404,4 +418,26 @@ void BluetoothDispatcher::OnReadValueError(int thread_id,
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,
+ BluetoothError error_type,
+ const std::string& error_message) {
+ DCHECK(pending_write_value_requests_.Lookup(request_id)) << request_id;
+
+ pending_write_value_requests_.Lookup(request_id)
+ ->onError(
+ new WebBluetoothError(WebBluetoothErrorFromBluetoothError(error_type),
+ WebString::fromUTF8(error_message)));
+
+ pending_write_value_requests_.Remove(request_id);
+}
+
} // namespace content
diff --git a/content/child/bluetooth/bluetooth_dispatcher.h b/content/child/bluetooth/bluetooth_dispatcher.h
index 254c732a..2b2a1357 100644
--- a/content/child/bluetooth/bluetooth_dispatcher.h
+++ b/content/child/bluetooth/bluetooth_dispatcher.h
@@ -65,6 +65,9 @@ class BluetoothDispatcher : public WorkerTaskRunner::Observer {
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;
@@ -109,6 +112,11 @@ class BluetoothDispatcher : public WorkerTaskRunner::Observer {
int request_id,
BluetoothError error_type,
const std::string& error_message);
+ void OnWriteValueSuccess(int thread_id, int request_id);
+ void OnWriteValueError(int thread_id,
+ int request_id,
+ BluetoothError error_type,
+ const std::string& error_message);
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
@@ -130,6 +138,8 @@ class BluetoothDispatcher : public WorkerTaskRunner::Observer {
// 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);
};
diff --git a/content/child/bluetooth/web_bluetooth_impl.cc b/content/child/bluetooth/web_bluetooth_impl.cc
index fd85a7d..c307461 100644
--- a/content/child/bluetooth/web_bluetooth_impl.cc
+++ b/content/child/bluetooth/web_bluetooth_impl.cc
@@ -49,6 +49,13 @@ void WebBluetoothImpl::readValue(
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());
diff --git a/content/child/bluetooth/web_bluetooth_impl.h b/content/child/bluetooth/web_bluetooth_impl.h
index 0a78df2..5eede0e 100644
--- a/content/child/bluetooth/web_bluetooth_impl.h
+++ b/content/child/bluetooth/web_bluetooth_impl.h
@@ -41,6 +41,9 @@ class CONTENT_EXPORT WebBluetoothImpl
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();
diff --git a/content/common/bluetooth/bluetooth_messages.h b/content/common/bluetooth/bluetooth_messages.h
index 4686131..378925e 100644
--- a/content/common/bluetooth/bluetooth_messages.h
+++ b/content/common/bluetooth/bluetooth_messages.h
@@ -175,6 +175,20 @@ IPC_MESSAGE_CONTROL4(BluetoothMsg_ReadCharacteristicValueError,
content::BluetoothError /* result */,
std::string /* error_message */)
+// Informs the renderer that the value has been successfully written to
+// the characteristic.
+IPC_MESSAGE_CONTROL2(BluetoothMsg_WriteCharacteristicValueSuccess,
+ int /* thread_id */,
+ int /* request_id */)
+
+// Informs the renderer that an error occurred while writing a value to a
+// characteristic.
+IPC_MESSAGE_CONTROL4(BluetoothMsg_WriteCharacteristicValueError,
+ int /* thread_id */,
+ int /* request_id */,
+ content::BluetoothError /* result */,
+ std::string /* error_message */)
+
// Messages sent from the renderer to the browser.
// Requests a bluetooth device from the browser.
@@ -215,3 +229,10 @@ IPC_MESSAGE_CONTROL3(BluetoothHostMsg_ReadValue,
int /* thread_id */,
int /* request_id */,
std::string /* characteristic_instance_id */)
+
+// Writes a value to a bluetooth device's characteristic.
+IPC_MESSAGE_CONTROL4(BluetoothHostMsg_WriteValue,
+ int /* thread_id */,
+ int /* request_id */,
+ std::string /* characteristic_instance_id */,
+ std::vector<uint8_t> /* value */)
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
index 4c0635a..aad6fe5 100644
--- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
+++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
@@ -272,6 +272,10 @@ LayoutTestBluetoothAdapterProvider::GetEmptyDevice(
ON_CALL(*device_name_characteristic, ReadRemoteCharacteristic(_, _))
.WillByDefault(RunCallback<0>(device_name_value));
+ ON_CALL(*device_name_characteristic, WriteRemoteCharacteristic(_, _, _))
+ .WillByDefault(RunCallback<2 /* error callback */>(
+ BluetoothGattService::GATT_ERROR_NOT_PERMITTED));
+
generic_access->AddMockCharacteristic(device_name_characteristic.Pass());
scoped_ptr<NiceMock<MockBluetoothGattCharacteristic>> reconnection_address(
@@ -282,6 +286,9 @@ LayoutTestBluetoothAdapterProvider::GetEmptyDevice(
.WillByDefault(
RunCallback<1>(BluetoothGattService::GATT_ERROR_NOT_PERMITTED));
+ ON_CALL(*reconnection_address, WriteRemoteCharacteristic(_, _, _))
+ .WillByDefault(RunCallback<1 /* success callback */>());
+
generic_access->AddMockCharacteristic(reconnection_address.Pass());
empty_device->AddMockService(generic_access.Pass());
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
index da91254..40aa323 100644
--- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
+++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
@@ -101,8 +101,9 @@ class LayoutTestBluetoothAdapterProvider {
// - |GetUUIDs| returns a list with two UUIDs: "1800" and "1801".
// - |GetGattServices| returns a list with one service "Generic Access".
// "Generic Access" has a "Device Name" characteristic, with a value of
- // "Empty Mock Device Name", and a "Reconnection Address" characteristic
- // which can't be read.
+ // "Empty Mock Device Name" that can be read but not written, and a
+ // "Reconnection Address" characteristic which can't be read, but can be
+ // written.
static scoped_ptr<testing::NiceMock<device::MockBluetoothDevice>>
GetEmptyDevice(device::MockBluetoothAdapter* adapter,
const std::string& device_name = "Empty Mock Device");
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 31c9f25..038ec9c 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -50648,6 +50648,7 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
<int value="87" label="SWDH_UPDATE_BAD_REGISTRATION_ID"/>
<int value="88" label="SWDH_UPDATE_CANNOT"/>
<int value="89" label="SWDH_UNREGISTER_BAD_REGISTRATION_ID"/>
+ <int value="90" label="BDH_INVALID_WRITE_VALUE_LENGTH"/>
</enum>
<enum name="BadMessageReasonExtensions" type="int">