1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/bluetooth/bluez/BluetoothUtils.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,199 @@ 1.4 +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.8 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "base/basictypes.h" 1.11 + 1.12 +#include "BluetoothReplyRunnable.h" 1.13 +#include "BluetoothService.h" 1.14 +#include "BluetoothUtils.h" 1.15 +#include "jsapi.h" 1.16 +#include "mozilla/Scoped.h" 1.17 +#include "mozilla/dom/bluetooth/BluetoothTypes.h" 1.18 +#include "nsContentUtils.h" 1.19 +#include "nsCxPusher.h" 1.20 +#include "nsIScriptContext.h" 1.21 +#include "nsISystemMessagesInternal.h" 1.22 +#include "nsString.h" 1.23 +#include "nsTArray.h" 1.24 +#include "nsServiceManagerUtils.h" 1.25 + 1.26 +BEGIN_BLUETOOTH_NAMESPACE 1.27 + 1.28 +bool 1.29 +SetJsObject(JSContext* aContext, 1.30 + const BluetoothValue& aValue, 1.31 + JS::Handle<JSObject*> aObj) 1.32 +{ 1.33 + MOZ_ASSERT(aContext && aObj); 1.34 + 1.35 + if (aValue.type() != BluetoothValue::TArrayOfBluetoothNamedValue) { 1.36 + BT_WARNING("SetJsObject: Invalid parameter type"); 1.37 + return false; 1.38 + } 1.39 + 1.40 + const nsTArray<BluetoothNamedValue>& arr = 1.41 + aValue.get_ArrayOfBluetoothNamedValue(); 1.42 + 1.43 + for (uint32_t i = 0; i < arr.Length(); i++) { 1.44 + JS::Rooted<JS::Value> val(aContext); 1.45 + const BluetoothValue& v = arr[i].value(); 1.46 + 1.47 + switch(v.type()) { 1.48 + case BluetoothValue::TnsString: { 1.49 + JSString* jsData = JS_NewUCStringCopyN(aContext, 1.50 + v.get_nsString().BeginReading(), 1.51 + v.get_nsString().Length()); 1.52 + NS_ENSURE_TRUE(jsData, false); 1.53 + val = STRING_TO_JSVAL(jsData); 1.54 + break; 1.55 + } 1.56 + case BluetoothValue::Tuint32_t: 1.57 + val = INT_TO_JSVAL(v.get_uint32_t()); 1.58 + break; 1.59 + case BluetoothValue::Tbool: 1.60 + val = BOOLEAN_TO_JSVAL(v.get_bool()); 1.61 + break; 1.62 + default: 1.63 + BT_WARNING("SetJsObject: Parameter is not handled"); 1.64 + break; 1.65 + } 1.66 + 1.67 + if (!JS_SetProperty(aContext, aObj, 1.68 + NS_ConvertUTF16toUTF8(arr[i].name()).get(), 1.69 + val)) { 1.70 + BT_WARNING("Failed to set property"); 1.71 + return false; 1.72 + } 1.73 + } 1.74 + 1.75 + return true; 1.76 +} 1.77 + 1.78 +nsString 1.79 +GetObjectPathFromAddress(const nsAString& aAdapterPath, 1.80 + const nsAString& aDeviceAddress) 1.81 +{ 1.82 + // The object path would be like /org/bluez/2906/hci0/dev_00_23_7F_CB_B4_F1, 1.83 + // and the adapter path would be the first part of the object path, according 1.84 + // to the example above, it's /org/bluez/2906/hci0. 1.85 + nsString devicePath(aAdapterPath); 1.86 + devicePath.AppendLiteral("/dev_"); 1.87 + devicePath.Append(aDeviceAddress); 1.88 + devicePath.ReplaceChar(':', '_'); 1.89 + return devicePath; 1.90 +} 1.91 + 1.92 +nsString 1.93 +GetAddressFromObjectPath(const nsAString& aObjectPath) 1.94 +{ 1.95 + // The object path would be like /org/bluez/2906/hci0/dev_00_23_7F_CB_B4_F1, 1.96 + // and the adapter path would be the first part of the object path, according 1.97 + // to the example above, it's /org/bluez/2906/hci0. 1.98 + nsString address(aObjectPath); 1.99 + int addressHead = address.RFind("/") + 5; 1.100 + 1.101 + MOZ_ASSERT(addressHead + BLUETOOTH_ADDRESS_LENGTH == (int)address.Length()); 1.102 + 1.103 + address.Cut(0, addressHead); 1.104 + address.ReplaceChar('_', ':'); 1.105 + 1.106 + return address; 1.107 +} 1.108 + 1.109 +bool 1.110 +BroadcastSystemMessage(const nsAString& aType, 1.111 + const InfallibleTArray<BluetoothNamedValue>& aData) 1.112 +{ 1.113 + mozilla::AutoSafeJSContext cx; 1.114 + NS_ASSERTION(!::JS_IsExceptionPending(cx), 1.115 + "Shouldn't get here when an exception is pending!"); 1.116 + 1.117 + JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), 1.118 + JS::NullPtr())); 1.119 + if (!obj) { 1.120 + BT_WARNING("Failed to new JSObject for system message!"); 1.121 + return false; 1.122 + } 1.123 + 1.124 + if (!SetJsObject(cx, aData, obj)) { 1.125 + BT_WARNING("Failed to set properties of system message!"); 1.126 + return false; 1.127 + } 1.128 + 1.129 + nsCOMPtr<nsISystemMessagesInternal> systemMessenger = 1.130 + do_GetService("@mozilla.org/system-message-internal;1"); 1.131 + NS_ENSURE_TRUE(systemMessenger, false); 1.132 + 1.133 + JS::Rooted<JS::Value> value(cx, JS::ObjectValue(*obj)); 1.134 + systemMessenger->BroadcastMessage(aType, value, 1.135 + JS::UndefinedHandleValue); 1.136 + 1.137 + return true; 1.138 +} 1.139 + 1.140 +void 1.141 +DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable, 1.142 + const BluetoothValue& aValue, 1.143 + const nsAString& aErrorStr) 1.144 +{ 1.145 + // Reply will be deleted by the runnable after running on main thread 1.146 + BluetoothReply* reply; 1.147 + if (!aErrorStr.IsEmpty()) { 1.148 + nsString err(aErrorStr); 1.149 + reply = new BluetoothReply(BluetoothReplyError(err)); 1.150 + } else { 1.151 + MOZ_ASSERT(aValue.type() != BluetoothValue::T__None); 1.152 + reply = new BluetoothReply(BluetoothReplySuccess(aValue)); 1.153 + } 1.154 + 1.155 + aRunnable->SetReply(reply); 1.156 + if (NS_FAILED(NS_DispatchToMainThread(aRunnable))) { 1.157 + BT_WARNING("Failed to dispatch to main thread!"); 1.158 + } 1.159 +} 1.160 + 1.161 +void 1.162 +ParseAtCommand(const nsACString& aAtCommand, const int aStart, 1.163 + nsTArray<nsCString>& aRetValues) 1.164 +{ 1.165 + int length = aAtCommand.Length(); 1.166 + int begin = aStart; 1.167 + 1.168 + for (int i = aStart; i < length; ++i) { 1.169 + // Use ',' as separator 1.170 + if (aAtCommand[i] == ',') { 1.171 + nsCString tmp(nsDependentCSubstring(aAtCommand, begin, i - begin)); 1.172 + aRetValues.AppendElement(tmp); 1.173 + 1.174 + begin = i + 1; 1.175 + } 1.176 + } 1.177 + 1.178 + nsCString tmp(nsDependentCSubstring(aAtCommand, begin)); 1.179 + aRetValues.AppendElement(tmp); 1.180 +} 1.181 + 1.182 +void 1.183 +DispatchStatusChangedEvent(const nsAString& aType, 1.184 + const nsAString& aAddress, 1.185 + bool aStatus) 1.186 +{ 1.187 + MOZ_ASSERT(NS_IsMainThread()); 1.188 + 1.189 + InfallibleTArray<BluetoothNamedValue> data; 1.190 + data.AppendElement( 1.191 + BluetoothNamedValue(NS_LITERAL_STRING("address"), nsString(aAddress))); 1.192 + data.AppendElement( 1.193 + BluetoothNamedValue(NS_LITERAL_STRING("status"), aStatus)); 1.194 + 1.195 + BluetoothSignal signal(nsString(aType), NS_LITERAL_STRING(KEY_ADAPTER), data); 1.196 + 1.197 + BluetoothService* bs = BluetoothService::Get(); 1.198 + NS_ENSURE_TRUE_VOID(bs); 1.199 + bs->DistributeSignal(signal); 1.200 +} 1.201 + 1.202 +END_BLUETOOTH_NAMESPACE