|
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/. */ |
|
6 |
|
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" |
|
13 |
|
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" |
|
21 |
|
22 using namespace mozilla; |
|
23 |
|
24 USING_BLUETOOTH_NAMESPACE |
|
25 |
|
26 // QueryInterface implementation for BluetoothManager |
|
27 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothManager) |
|
28 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) |
|
29 |
|
30 NS_IMPL_ADDREF_INHERITED(BluetoothManager, DOMEventTargetHelper) |
|
31 NS_IMPL_RELEASE_INHERITED(BluetoothManager, DOMEventTargetHelper) |
|
32 |
|
33 class GetAdapterTask : public BluetoothReplyRunnable |
|
34 { |
|
35 public: |
|
36 GetAdapterTask(BluetoothManager* aManager, |
|
37 nsIDOMDOMRequest* aReq) : |
|
38 BluetoothReplyRunnable(aReq), |
|
39 mManagerPtr(aManager) |
|
40 { |
|
41 } |
|
42 |
|
43 bool |
|
44 ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue) |
|
45 { |
|
46 aValue.setUndefined(); |
|
47 |
|
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 } |
|
54 |
|
55 if (!mManagerPtr->GetOwner()) { |
|
56 BT_WARNING("Bluetooth manager was disconnected from owner window."); |
|
57 |
|
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 } |
|
63 |
|
64 const InfallibleTArray<BluetoothNamedValue>& values = |
|
65 v.get_ArrayOfBluetoothNamedValue(); |
|
66 nsRefPtr<BluetoothAdapter> adapter = |
|
67 BluetoothAdapter::Create(mManagerPtr->GetOwner(), values); |
|
68 |
|
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 } |
|
76 |
|
77 AutoPushJSContext cx(sc->GetNativeContext()); |
|
78 |
|
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 } |
|
87 |
|
88 return true; |
|
89 } |
|
90 |
|
91 void |
|
92 ReleaseMembers() |
|
93 { |
|
94 BluetoothReplyRunnable::ReleaseMembers(); |
|
95 mManagerPtr = nullptr; |
|
96 } |
|
97 |
|
98 private: |
|
99 nsRefPtr<BluetoothManager> mManagerPtr; |
|
100 }; |
|
101 |
|
102 BluetoothManager::BluetoothManager(nsPIDOMWindow *aWindow) |
|
103 : DOMEventTargetHelper(aWindow) |
|
104 , BluetoothPropertyContainer(BluetoothObjectType::TYPE_MANAGER) |
|
105 { |
|
106 MOZ_ASSERT(aWindow); |
|
107 MOZ_ASSERT(IsDOMBinding()); |
|
108 |
|
109 mPath.AssignLiteral("/"); |
|
110 |
|
111 BluetoothService* bs = BluetoothService::Get(); |
|
112 NS_ENSURE_TRUE_VOID(bs); |
|
113 bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this); |
|
114 } |
|
115 |
|
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 } |
|
122 |
|
123 void |
|
124 BluetoothManager::DisconnectFromOwner() |
|
125 { |
|
126 DOMEventTargetHelper::DisconnectFromOwner(); |
|
127 |
|
128 BluetoothService* bs = BluetoothService::Get(); |
|
129 NS_ENSURE_TRUE_VOID(bs); |
|
130 bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this); |
|
131 } |
|
132 |
|
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 } |
|
144 |
|
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 } |
|
153 |
|
154 return bs->IsEnabled(); |
|
155 } |
|
156 |
|
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 } |
|
165 |
|
166 nsRefPtr<DOMRequest> request = new DOMRequest(win); |
|
167 nsRefPtr<BluetoothReplyRunnable> results = |
|
168 new GetAdapterTask(this, request); |
|
169 |
|
170 BluetoothService* bs = BluetoothService::Get(); |
|
171 if (!bs) { |
|
172 aRv.Throw(NS_ERROR_FAILURE); |
|
173 return nullptr; |
|
174 } |
|
175 |
|
176 nsresult rv = bs->GetDefaultAdapterPathInternal(results); |
|
177 if (NS_FAILED(rv)) { |
|
178 aRv.Throw(rv); |
|
179 return nullptr; |
|
180 } |
|
181 |
|
182 return request.forget(); |
|
183 } |
|
184 |
|
185 // static |
|
186 already_AddRefed<BluetoothManager> |
|
187 BluetoothManager::Create(nsPIDOMWindow* aWindow) |
|
188 { |
|
189 MOZ_ASSERT(NS_IsMainThread()); |
|
190 MOZ_ASSERT(aWindow); |
|
191 |
|
192 nsRefPtr<BluetoothManager> manager = new BluetoothManager(aWindow); |
|
193 return manager.forget(); |
|
194 } |
|
195 |
|
196 // static |
|
197 bool |
|
198 BluetoothManager::CheckPermission(nsPIDOMWindow* aWindow) |
|
199 { |
|
200 NS_ASSERTION(aWindow, "Null pointer!"); |
|
201 |
|
202 nsCOMPtr<nsIPermissionManager> permMgr = |
|
203 do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); |
|
204 NS_ENSURE_TRUE(permMgr, false); |
|
205 |
|
206 uint32_t permission; |
|
207 nsresult rv = |
|
208 permMgr->TestPermissionFromWindow(aWindow, "bluetooth", |
|
209 &permission); |
|
210 NS_ENSURE_SUCCESS(rv, false); |
|
211 |
|
212 return permission == nsIPermissionManager::ALLOW_ACTION; |
|
213 } |
|
214 |
|
215 void |
|
216 BluetoothManager::Notify(const BluetoothSignal& aData) |
|
217 { |
|
218 BT_LOGD("[M] %s: %s", __FUNCTION__, NS_ConvertUTF16toUTF8(aData.name()).get()); |
|
219 |
|
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 } |
|
235 |
|
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 } |
|
244 |
|
245 return bs->IsConnected(aProfileId); |
|
246 } |
|
247 |
|
248 JSObject* |
|
249 BluetoothManager::WrapObject(JSContext* aCx) |
|
250 { |
|
251 return BluetoothManagerBinding::Wrap(aCx, this); |
|
252 } |