Merge inbound to m-c on a CLOSED TREE.
[gecko.git] / dom / bluetooth / BluetoothUtils.cpp
blobfb03577d766c49879bd585671d26217be4c0aace
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 "BluetoothUtils.h"
12 #include "jsapi.h"
13 #include "mozilla/Scoped.h"
14 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
15 #include "nsContentUtils.h"
16 #include "nsCxPusher.h"
17 #include "nsIScriptContext.h"
18 #include "nsISystemMessagesInternal.h"
19 #include "nsString.h"
20 #include "nsTArray.h"
21 #include "nsServiceManagerUtils.h"
23 BEGIN_BLUETOOTH_NAMESPACE
25 bool
26 SetJsObject(JSContext* aContext,
27 const BluetoothValue& aValue,
28 JS::Handle<JSObject*> aObj)
30 MOZ_ASSERT(aContext && aObj);
32 if (aValue.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
33 BT_WARNING("SetJsObject: Invalid parameter type");
34 return false;
37 const nsTArray<BluetoothNamedValue>& arr =
38 aValue.get_ArrayOfBluetoothNamedValue();
40 for (uint32_t i = 0; i < arr.Length(); i++) {
41 JS::Rooted<JS::Value> val(aContext);
42 const BluetoothValue& v = arr[i].value();
44 switch(v.type()) {
45 case BluetoothValue::TnsString: {
46 JSString* jsData = JS_NewUCStringCopyN(aContext,
47 v.get_nsString().BeginReading(),
48 v.get_nsString().Length());
49 NS_ENSURE_TRUE(jsData, false);
50 val = STRING_TO_JSVAL(jsData);
51 break;
53 case BluetoothValue::Tuint32_t:
54 val = INT_TO_JSVAL(v.get_uint32_t());
55 break;
56 case BluetoothValue::Tbool:
57 val = BOOLEAN_TO_JSVAL(v.get_bool());
58 break;
59 default:
60 BT_WARNING("SetJsObject: Parameter is not handled");
61 break;
64 if (!JS_SetProperty(aContext, aObj,
65 NS_ConvertUTF16toUTF8(arr[i].name()).get(),
66 val)) {
67 BT_WARNING("Failed to set property");
68 return false;
72 return true;
75 nsString
76 GetObjectPathFromAddress(const nsAString& aAdapterPath,
77 const nsAString& aDeviceAddress)
79 // The object path would be like /org/bluez/2906/hci0/dev_00_23_7F_CB_B4_F1,
80 // and the adapter path would be the first part of the object path, according
81 // to the example above, it's /org/bluez/2906/hci0.
82 nsString devicePath(aAdapterPath);
83 devicePath.AppendLiteral("/dev_");
84 devicePath.Append(aDeviceAddress);
85 devicePath.ReplaceChar(':', '_');
86 return devicePath;
89 nsString
90 GetAddressFromObjectPath(const nsAString& aObjectPath)
92 // The object path would be like /org/bluez/2906/hci0/dev_00_23_7F_CB_B4_F1,
93 // and the adapter path would be the first part of the object path, according
94 // to the example above, it's /org/bluez/2906/hci0.
95 nsString address(aObjectPath);
96 int addressHead = address.RFind("/") + 5;
98 MOZ_ASSERT(addressHead + BLUETOOTH_ADDRESS_LENGTH == address.Length());
100 address.Cut(0, addressHead);
101 address.ReplaceChar('_', ':');
103 return address;
106 bool
107 BroadcastSystemMessage(const nsAString& aType,
108 const InfallibleTArray<BluetoothNamedValue>& aData)
110 mozilla::AutoSafeJSContext cx;
111 NS_ASSERTION(!::JS_IsExceptionPending(cx),
112 "Shouldn't get here when an exception is pending!");
114 JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, nullptr, nullptr, nullptr));
115 if (!obj) {
116 BT_WARNING("Failed to new JSObject for system message!");
117 return false;
120 if (!SetJsObject(cx, aData, obj)) {
121 BT_WARNING("Failed to set properties of system message!");
122 return false;
125 nsCOMPtr<nsISystemMessagesInternal> systemMessenger =
126 do_GetService("@mozilla.org/system-message-internal;1");
127 NS_ENSURE_TRUE(systemMessenger, false);
129 systemMessenger->BroadcastMessage(aType,
130 OBJECT_TO_JSVAL(obj),
131 JS::UndefinedValue());
133 return true;
136 void
137 DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
138 const BluetoothValue& aValue,
139 const nsAString& aErrorStr)
141 // Reply will be deleted by the runnable after running on main thread
142 BluetoothReply* reply;
143 if (!aErrorStr.IsEmpty()) {
144 nsString err(aErrorStr);
145 reply = new BluetoothReply(BluetoothReplyError(err));
146 } else {
147 MOZ_ASSERT(aValue.type() != BluetoothValue::T__None);
148 reply = new BluetoothReply(BluetoothReplySuccess(aValue));
151 aRunnable->SetReply(reply);
152 if (NS_FAILED(NS_DispatchToMainThread(aRunnable))) {
153 BT_WARNING("Failed to dispatch to main thread!");
157 void
158 ParseAtCommand(const nsACString& aAtCommand, const int aStart,
159 nsTArray<nsCString>& aRetValues)
161 int length = aAtCommand.Length();
162 int begin = aStart;
164 for (int i = aStart; i < length; ++i) {
165 // Use ',' as separator
166 if (aAtCommand[i] == ',') {
167 nsCString tmp(nsDependentCSubstring(aAtCommand, begin, i - begin));
168 aRetValues.AppendElement(tmp);
170 begin = i + 1;
174 nsCString tmp(nsDependentCSubstring(aAtCommand, begin));
175 aRetValues.AppendElement(tmp);
178 void
179 DispatchStatusChangedEvent(const nsAString& aType,
180 const nsAString& aAddress,
181 bool aStatus)
183 MOZ_ASSERT(NS_IsMainThread());
185 InfallibleTArray<BluetoothNamedValue> data;
186 data.AppendElement(
187 BluetoothNamedValue(NS_LITERAL_STRING("address"), nsString(aAddress)));
188 data.AppendElement(
189 BluetoothNamedValue(NS_LITERAL_STRING("status"), aStatus));
191 BluetoothSignal signal(nsString(aType), NS_LITERAL_STRING(KEY_ADAPTER), data);
193 BluetoothService* bs = BluetoothService::Get();
194 NS_ENSURE_TRUE_VOID(bs);
195 bs->DistributeSignal(signal);
198 END_BLUETOOTH_NAMESPACE