Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "base/basictypes.h"
9 #include "BluetoothReplyRunnable.h"
10 #include "BluetoothService.h"
11 #include "BluetoothServiceBluedroid.h"
12 #include "BluetoothUtils.h"
13 #include "jsapi.h"
14 #include "mozilla/Scoped.h"
15 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
16 #include "nsContentUtils.h"
17 #include "nsCxPusher.h"
18 #include "nsIScriptContext.h"
19 #include "nsISystemMessagesInternal.h"
20 #include "nsString.h"
21 #include "nsTArray.h"
22 #include "nsServiceManagerUtils.h"
24 BEGIN_BLUETOOTH_NAMESPACE
26 const bt_interface_t*
27 GetBluetoothInterface()
28 {
29 return BluetoothServiceBluedroid::GetBluetoothInterface();
30 }
32 void
33 StringToBdAddressType(const nsAString& aBdAddress,
34 bt_bdaddr_t *aRetBdAddressType)
35 {
36 NS_ConvertUTF16toUTF8 bdAddressUTF8(aBdAddress);
37 const char* str = bdAddressUTF8.get();
39 for (int i = 0; i < 6; i++) {
40 aRetBdAddressType->address[i] = (uint8_t) strtoul(str, (char **)&str, 16);
41 str++;
42 }
43 }
45 void
46 BdAddressTypeToString(bt_bdaddr_t* aBdAddressType, nsAString& aRetBdAddress)
47 {
48 uint8_t* addr = aBdAddressType->address;
49 char bdstr[18];
51 sprintf(bdstr, "%02x:%02x:%02x:%02x:%02x:%02x",
52 (int)addr[0],(int)addr[1],(int)addr[2],
53 (int)addr[3],(int)addr[4],(int)addr[5]);
55 aRetBdAddress = NS_ConvertUTF8toUTF16(bdstr);
56 }
58 bool
59 SetJsObject(JSContext* aContext,
60 const BluetoothValue& aValue,
61 JS::Handle<JSObject*> aObj)
62 {
63 MOZ_ASSERT(aContext && aObj);
65 if (aValue.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
66 BT_WARNING("SetJsObject: Invalid parameter type");
67 return false;
68 }
70 const nsTArray<BluetoothNamedValue>& arr =
71 aValue.get_ArrayOfBluetoothNamedValue();
73 for (uint32_t i = 0; i < arr.Length(); i++) {
74 JS::Rooted<JS::Value> val(aContext);
75 const BluetoothValue& v = arr[i].value();
77 switch(v.type()) {
78 case BluetoothValue::TnsString: {
79 JSString* jsData = JS_NewUCStringCopyN(aContext,
80 v.get_nsString().BeginReading(),
81 v.get_nsString().Length());
82 NS_ENSURE_TRUE(jsData, false);
83 val = STRING_TO_JSVAL(jsData);
84 break;
85 }
86 case BluetoothValue::Tuint32_t:
87 val = INT_TO_JSVAL(v.get_uint32_t());
88 break;
89 case BluetoothValue::Tbool:
90 val = BOOLEAN_TO_JSVAL(v.get_bool());
91 break;
92 default:
93 BT_WARNING("SetJsObject: Parameter is not handled");
94 break;
95 }
97 if (!JS_SetProperty(aContext, aObj,
98 NS_ConvertUTF16toUTF8(arr[i].name()).get(),
99 val)) {
100 BT_WARNING("Failed to set property");
101 return false;
102 }
103 }
105 return true;
106 }
108 bool
109 BroadcastSystemMessage(const nsAString& aType,
110 const BluetoothValue& aData)
111 {
112 mozilla::AutoSafeJSContext cx;
113 NS_ASSERTION(!::JS_IsExceptionPending(cx),
114 "Shouldn't get here when an exception is pending!");
116 nsCOMPtr<nsISystemMessagesInternal> systemMessenger =
117 do_GetService("@mozilla.org/system-message-internal;1");
118 NS_ENSURE_TRUE(systemMessenger, false);
120 JS::Rooted<JS::Value> value(cx);
121 if (aData.type() == BluetoothValue::TnsString) {
122 JSString* jsData = JS_NewUCStringCopyN(cx,
123 aData.get_nsString().BeginReading(),
124 aData.get_nsString().Length());
125 value = STRING_TO_JSVAL(jsData);
126 } else if (aData.type() == BluetoothValue::TArrayOfBluetoothNamedValue) {
127 JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(),
128 JS::NullPtr()));
129 if (!obj) {
130 BT_WARNING("Failed to new JSObject for system message!");
131 return false;
132 }
134 if (!SetJsObject(cx, aData, obj)) {
135 BT_WARNING("Failed to set properties of system message!");
136 return false;
137 }
138 value = JS::ObjectValue(*obj);
139 } else {
140 BT_WARNING("Not support the unknown BluetoothValue type");
141 return false;
142 }
144 systemMessenger->BroadcastMessage(aType, value,
145 JS::UndefinedHandleValue);
147 return true;
148 }
150 void
151 DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
152 const BluetoothValue& aValue,
153 const nsAString& aErrorStr)
154 {
155 // Reply will be deleted by the runnable after running on main thread
156 BluetoothReply* reply;
157 if (!aErrorStr.IsEmpty()) {
158 nsString err(aErrorStr);
159 reply = new BluetoothReply(BluetoothReplyError(err));
160 } else {
161 MOZ_ASSERT(aValue.type() != BluetoothValue::T__None);
162 reply = new BluetoothReply(BluetoothReplySuccess(aValue));
163 }
165 aRunnable->SetReply(reply);
166 if (NS_FAILED(NS_DispatchToMainThread(aRunnable))) {
167 BT_WARNING("Failed to dispatch to main thread!");
168 }
169 }
171 void
172 DispatchStatusChangedEvent(const nsAString& aType,
173 const nsAString& aAddress,
174 bool aStatus)
175 {
176 MOZ_ASSERT(NS_IsMainThread());
178 InfallibleTArray<BluetoothNamedValue> data;
179 BT_APPEND_NAMED_VALUE(data, "address", nsString(aAddress));
180 BT_APPEND_NAMED_VALUE(data, "status", aStatus);
182 BluetoothSignal signal(nsString(aType), NS_LITERAL_STRING(KEY_ADAPTER), data);
184 BluetoothService* bs = BluetoothService::Get();
185 NS_ENSURE_TRUE_VOID(bs);
186 bs->DistributeSignal(signal);
187 }
189 END_BLUETOOTH_NAMESPACE