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"
8 #include "BluetoothManager.h"
9 #include "BluetoothCommon.h"
10 #include "BluetoothAdapter.h"
11 #include "BluetoothService.h"
12 #include "BluetoothReplyRunnable.h"
14 #include "DOMRequest.h"
15 #include "nsContentUtils.h"
16 #include "nsDOMClassInfo.h"
17 #include "nsIPermissionManager.h"
18 #include "nsThreadUtils.h"
19 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
20 #include "mozilla/dom/BluetoothManagerBinding.h"
22 using namespace mozilla;
24 USING_BLUETOOTH_NAMESPACE
26 // QueryInterface implementation for BluetoothManager
27 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothManager)
28 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
30 NS_IMPL_ADDREF_INHERITED(BluetoothManager, DOMEventTargetHelper)
31 NS_IMPL_RELEASE_INHERITED(BluetoothManager, DOMEventTargetHelper)
33 class GetAdapterTask : public BluetoothReplyRunnable
34 {
35 public:
36 GetAdapterTask(BluetoothManager* aManager,
37 nsIDOMDOMRequest* aReq) :
38 BluetoothReplyRunnable(aReq),
39 mManagerPtr(aManager)
40 {
41 }
43 bool
44 ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
45 {
46 aValue.setUndefined();
48 const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
49 if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
50 BT_WARNING("Not a BluetoothNamedValue array!");
51 SetError(NS_LITERAL_STRING("BluetoothReplyTypeError"));
52 return false;
53 }
55 if (!mManagerPtr->GetOwner()) {
56 BT_WARNING("Bluetooth manager was disconnected from owner window.");
58 // Stop to create adapter since owner window of Bluetooth manager was
59 // gone. These is no need to create a DOMEvent target which has no owner
60 // to reply to.
61 return false;
62 }
64 const InfallibleTArray<BluetoothNamedValue>& values =
65 v.get_ArrayOfBluetoothNamedValue();
66 nsRefPtr<BluetoothAdapter> adapter =
67 BluetoothAdapter::Create(mManagerPtr->GetOwner(), values);
69 nsresult rv;
70 nsIScriptContext* sc = mManagerPtr->GetContextForEventHandlers(&rv);
71 if (!sc) {
72 BT_WARNING("Cannot create script context!");
73 SetError(NS_LITERAL_STRING("BluetoothScriptContextError"));
74 return false;
75 }
77 AutoPushJSContext cx(sc->GetNativeContext());
79 JS::Rooted<JSObject*> scope(cx, sc->GetWindowProxy());
80 JSAutoCompartment ac(cx, scope);
81 rv = nsContentUtils::WrapNative(cx, adapter, aValue);
82 if (NS_FAILED(rv)) {
83 BT_WARNING("Cannot create native object!");
84 SetError(NS_LITERAL_STRING("BluetoothNativeObjectError"));
85 return false;
86 }
88 return true;
89 }
91 void
92 ReleaseMembers()
93 {
94 BluetoothReplyRunnable::ReleaseMembers();
95 mManagerPtr = nullptr;
96 }
98 private:
99 nsRefPtr<BluetoothManager> mManagerPtr;
100 };
102 BluetoothManager::BluetoothManager(nsPIDOMWindow *aWindow)
103 : DOMEventTargetHelper(aWindow)
104 , BluetoothPropertyContainer(BluetoothObjectType::TYPE_MANAGER)
105 {
106 MOZ_ASSERT(aWindow);
107 MOZ_ASSERT(IsDOMBinding());
109 mPath.AssignLiteral("/");
111 BluetoothService* bs = BluetoothService::Get();
112 NS_ENSURE_TRUE_VOID(bs);
113 bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
114 }
116 BluetoothManager::~BluetoothManager()
117 {
118 BluetoothService* bs = BluetoothService::Get();
119 NS_ENSURE_TRUE_VOID(bs);
120 bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
121 }
123 void
124 BluetoothManager::DisconnectFromOwner()
125 {
126 DOMEventTargetHelper::DisconnectFromOwner();
128 BluetoothService* bs = BluetoothService::Get();
129 NS_ENSURE_TRUE_VOID(bs);
130 bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
131 }
133 void
134 BluetoothManager::SetPropertyByValue(const BluetoothNamedValue& aValue)
135 {
136 #ifdef DEBUG
137 const nsString& name = aValue.name();
138 nsCString warningMsg;
139 warningMsg.AssignLiteral("Not handling manager property: ");
140 warningMsg.Append(NS_ConvertUTF16toUTF8(name));
141 BT_WARNING(warningMsg.get());
142 #endif
143 }
145 bool
146 BluetoothManager::GetEnabled(ErrorResult& aRv)
147 {
148 BluetoothService* bs = BluetoothService::Get();
149 if (!bs) {
150 aRv.Throw(NS_ERROR_FAILURE);
151 return false;
152 }
154 return bs->IsEnabled();
155 }
157 already_AddRefed<dom::DOMRequest>
158 BluetoothManager::GetDefaultAdapter(ErrorResult& aRv)
159 {
160 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
161 if (!win) {
162 aRv.Throw(NS_ERROR_FAILURE);
163 return nullptr;
164 }
166 nsRefPtr<DOMRequest> request = new DOMRequest(win);
167 nsRefPtr<BluetoothReplyRunnable> results =
168 new GetAdapterTask(this, request);
170 BluetoothService* bs = BluetoothService::Get();
171 if (!bs) {
172 aRv.Throw(NS_ERROR_FAILURE);
173 return nullptr;
174 }
176 nsresult rv = bs->GetDefaultAdapterPathInternal(results);
177 if (NS_FAILED(rv)) {
178 aRv.Throw(rv);
179 return nullptr;
180 }
182 return request.forget();
183 }
185 // static
186 already_AddRefed<BluetoothManager>
187 BluetoothManager::Create(nsPIDOMWindow* aWindow)
188 {
189 MOZ_ASSERT(NS_IsMainThread());
190 MOZ_ASSERT(aWindow);
192 nsRefPtr<BluetoothManager> manager = new BluetoothManager(aWindow);
193 return manager.forget();
194 }
196 // static
197 bool
198 BluetoothManager::CheckPermission(nsPIDOMWindow* aWindow)
199 {
200 NS_ASSERTION(aWindow, "Null pointer!");
202 nsCOMPtr<nsIPermissionManager> permMgr =
203 do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
204 NS_ENSURE_TRUE(permMgr, false);
206 uint32_t permission;
207 nsresult rv =
208 permMgr->TestPermissionFromWindow(aWindow, "bluetooth",
209 &permission);
210 NS_ENSURE_SUCCESS(rv, false);
212 return permission == nsIPermissionManager::ALLOW_ACTION;
213 }
215 void
216 BluetoothManager::Notify(const BluetoothSignal& aData)
217 {
218 BT_LOGD("[M] %s: %s", __FUNCTION__, NS_ConvertUTF16toUTF8(aData.name()).get());
220 if (aData.name().EqualsLiteral("AdapterAdded")) {
221 DispatchTrustedEvent(NS_LITERAL_STRING("adapteradded"));
222 } else if (aData.name().EqualsLiteral("Enabled")) {
223 DispatchTrustedEvent(NS_LITERAL_STRING("enabled"));
224 } else if (aData.name().EqualsLiteral("Disabled")) {
225 DispatchTrustedEvent(NS_LITERAL_STRING("disabled"));
226 } else {
227 #ifdef DEBUG
228 nsCString warningMsg;
229 warningMsg.AssignLiteral("Not handling manager signal: ");
230 warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
231 BT_WARNING(warningMsg.get());
232 #endif
233 }
234 }
236 bool
237 BluetoothManager::IsConnected(uint16_t aProfileId, ErrorResult& aRv)
238 {
239 BluetoothService* bs = BluetoothService::Get();
240 if (!bs) {
241 aRv.Throw(NS_ERROR_FAILURE);
242 return false;
243 }
245 return bs->IsConnected(aProfileId);
246 }
248 JSObject*
249 BluetoothManager::WrapObject(JSContext* aCx)
250 {
251 return BluetoothManagerBinding::Wrap(aCx, this);
252 }