dom/bluetooth/BluetoothAdapter.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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 "nsCxPusher.h"
     9 #include "nsDOMClassInfo.h"
    10 #include "nsTArrayHelpers.h"
    11 #include "DOMRequest.h"
    12 #include "nsThreadUtils.h"
    14 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
    15 #include "mozilla/dom/BluetoothAdapterBinding.h"
    16 #include "mozilla/dom/BluetoothDeviceEvent.h"
    17 #include "mozilla/dom/BluetoothStatusChangedEvent.h"
    18 #include "mozilla/dom/ContentChild.h"
    19 #include "mozilla/LazyIdleThread.h"
    21 #include "BluetoothAdapter.h"
    22 #include "BluetoothDevice.h"
    23 #include "BluetoothReplyRunnable.h"
    24 #include "BluetoothService.h"
    25 #include "BluetoothUtils.h"
    27 using namespace mozilla;
    28 using namespace mozilla::dom;
    30 USING_BLUETOOTH_NAMESPACE
    32 NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothAdapter)
    34 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(BluetoothAdapter,
    35                                                DOMEventTargetHelper)
    36   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsUuids)
    37   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsDeviceAddresses)
    38 NS_IMPL_CYCLE_COLLECTION_TRACE_END
    40 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter,
    41                                                   DOMEventTargetHelper)
    42   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
    43 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    45 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter,
    46                                                 DOMEventTargetHelper)
    47   tmp->Unroot();
    48 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    50 // QueryInterface implementation for BluetoothAdapter
    51 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothAdapter)
    52 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
    54 NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, DOMEventTargetHelper)
    55 NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, DOMEventTargetHelper)
    57 class GetDevicesTask : public BluetoothReplyRunnable
    58 {
    59 public:
    60   GetDevicesTask(BluetoothAdapter* aAdapterPtr,
    61                        nsIDOMDOMRequest* aReq) :
    62     BluetoothReplyRunnable(aReq),
    63     mAdapterPtr(aAdapterPtr)
    64   {
    65     MOZ_ASSERT(aReq && aAdapterPtr);
    66   }
    68   virtual bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
    69   {
    70     aValue.setUndefined();
    72     const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
    73     if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
    74       BT_WARNING("Not a BluetoothNamedValue array!");
    75       SetError(NS_LITERAL_STRING("BluetoothReplyTypeError"));
    76       return false;
    77     }
    79     const InfallibleTArray<BluetoothNamedValue>& values =
    80       v.get_ArrayOfBluetoothNamedValue();
    82     nsTArray<nsRefPtr<BluetoothDevice> > devices;
    83     for (uint32_t i = 0; i < values.Length(); i++) {
    84       const BluetoothValue properties = values[i].value();
    85       if (properties.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
    86         BT_WARNING("Not a BluetoothNamedValue array!");
    87         SetError(NS_LITERAL_STRING("BluetoothReplyTypeError"));
    88         return false;
    89       }
    90       nsRefPtr<BluetoothDevice> d =
    91         BluetoothDevice::Create(mAdapterPtr->GetOwner(),
    92                                 mAdapterPtr->GetPath(),
    93                                 properties);
    94       devices.AppendElement(d);
    95     }
    97     nsresult rv;
    98     nsIScriptContext* sc = mAdapterPtr->GetContextForEventHandlers(&rv);
    99     if (!sc) {
   100       BT_WARNING("Cannot create script context!");
   101       SetError(NS_LITERAL_STRING("BluetoothScriptContextError"));
   102       return false;
   103     }
   105     AutoPushJSContext cx(sc->GetNativeContext());
   106     JSObject* JsDevices = nullptr;
   107     rv = nsTArrayToJSArray(cx, devices, &JsDevices);
   108     if (!JsDevices) {
   109       BT_WARNING("Cannot create JS array!");
   110       SetError(NS_LITERAL_STRING("BluetoothError"));
   111       return false;
   112     }
   114     aValue.setObject(*JsDevices);
   115     return true;
   116   }
   118   void
   119   ReleaseMembers()
   120   {
   121     BluetoothReplyRunnable::ReleaseMembers();
   122     mAdapterPtr = nullptr;
   123   }
   124 private:
   125   nsRefPtr<BluetoothAdapter> mAdapterPtr;
   126 };
   128 class GetScoConnectionStatusTask : public BluetoothReplyRunnable
   129 {
   130 public:
   131   GetScoConnectionStatusTask(nsIDOMDOMRequest* aReq) :
   132     BluetoothReplyRunnable(aReq)
   133   {
   134     MOZ_ASSERT(aReq);
   135   }
   137   virtual bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
   138   {
   139     aValue.setUndefined();
   141     const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
   142     if (v.type() != BluetoothValue::Tbool) {
   143       BT_WARNING("Not a boolean!");
   144       SetError(NS_LITERAL_STRING("BluetoothReplyTypeError"));
   145       return false;
   146     }
   148     aValue.setBoolean(v.get_bool());
   149     return true;
   150   }
   152   void
   153   ReleaseMembers()
   154   {
   155     BluetoothReplyRunnable::ReleaseMembers();
   156   }
   157 };
   159 static int kCreatePairedDeviceTimeout = 50000; // unit: msec
   161 BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow* aWindow,
   162                                    const BluetoothValue& aValue)
   163   : DOMEventTargetHelper(aWindow)
   164   , BluetoothPropertyContainer(BluetoothObjectType::TYPE_ADAPTER)
   165   , mJsUuids(nullptr)
   166   , mJsDeviceAddresses(nullptr)
   167   , mDiscoverable(false)
   168   , mDiscovering(false)
   169   , mPairable(false)
   170   , mPowered(false)
   171   , mIsRooted(false)
   172 {
   173   MOZ_ASSERT(aWindow);
   174   MOZ_ASSERT(IsDOMBinding());
   176   const InfallibleTArray<BluetoothNamedValue>& values =
   177     aValue.get_ArrayOfBluetoothNamedValue();
   178   for (uint32_t i = 0; i < values.Length(); ++i) {
   179     SetPropertyByValue(values[i]);
   180   }
   182   BluetoothService* bs = BluetoothService::Get();
   183   NS_ENSURE_TRUE_VOID(bs);
   184   bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_ADAPTER), this);
   185 }
   187 BluetoothAdapter::~BluetoothAdapter()
   188 {
   189   Unroot();
   190   BluetoothService* bs = BluetoothService::Get();
   191   // We can be null on shutdown, where this might happen
   192   NS_ENSURE_TRUE_VOID(bs);
   193   bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_ADAPTER), this);
   194 }
   196 void
   197 BluetoothAdapter::DisconnectFromOwner()
   198 {
   199   DOMEventTargetHelper::DisconnectFromOwner();
   201   BluetoothService* bs = BluetoothService::Get();
   202   NS_ENSURE_TRUE_VOID(bs);
   203   bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_ADAPTER), this);
   204 }
   206 void
   207 BluetoothAdapter::Unroot()
   208 {
   209   if (!mIsRooted) {
   210     return;
   211   }
   212   mJsUuids = nullptr;
   213   mJsDeviceAddresses = nullptr;
   214   mozilla::DropJSObjects(this);
   215   mIsRooted = false;
   216 }
   218 void
   219 BluetoothAdapter::Root()
   220 {
   221   if (mIsRooted) {
   222     return;
   223   }
   224   mozilla::HoldJSObjects(this);
   225   mIsRooted = true;
   226 }
   228 void
   229 BluetoothAdapter::SetPropertyByValue(const BluetoothNamedValue& aValue)
   230 {
   231   const nsString& name = aValue.name();
   232   const BluetoothValue& value = aValue.value();
   233   if (name.EqualsLiteral("Name")) {
   234     mName = value.get_nsString();
   235   } else if (name.EqualsLiteral("Address")) {
   236     mAddress = value.get_nsString();
   237   } else if (name.EqualsLiteral("Path")) {
   238     mPath = value.get_nsString();
   239   } else if (name.EqualsLiteral("Discoverable")) {
   240     mDiscoverable = value.get_bool();
   241   } else if (name.EqualsLiteral("Discovering")) {
   242     mDiscovering = value.get_bool();
   243   } else if (name.EqualsLiteral("Pairable")) {
   244     mPairable = value.get_bool();
   245   } else if (name.EqualsLiteral("Powered")) {
   246     mPowered = value.get_bool();
   247   } else if (name.EqualsLiteral("PairableTimeout")) {
   248     mPairableTimeout = value.get_uint32_t();
   249   } else if (name.EqualsLiteral("DiscoverableTimeout")) {
   250     mDiscoverableTimeout = value.get_uint32_t();
   251   } else if (name.EqualsLiteral("Class")) {
   252     mClass = value.get_uint32_t();
   253   } else if (name.EqualsLiteral("UUIDs")) {
   254     mUuids = value.get_ArrayOfnsString();
   255     nsresult rv;
   256     nsIScriptContext* sc = GetContextForEventHandlers(&rv);
   257     NS_ENSURE_SUCCESS_VOID(rv);
   258     NS_ENSURE_TRUE_VOID(sc);
   260     AutoPushJSContext cx(sc->GetNativeContext());
   261     JS::Rooted<JSObject*> uuids(cx);
   262     if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, uuids.address()))) {
   263       BT_WARNING("Cannot set JS UUIDs object!");
   264       return;
   265     }
   266     mJsUuids = uuids;
   267     Root();
   268   } else if (name.EqualsLiteral("Devices")) {
   269     mDeviceAddresses = value.get_ArrayOfnsString();
   271     nsresult rv;
   272     nsIScriptContext* sc = GetContextForEventHandlers(&rv);
   273     NS_ENSURE_SUCCESS_VOID(rv);
   274     NS_ENSURE_TRUE_VOID(sc);
   276     AutoPushJSContext cx(sc->GetNativeContext());
   277     JS::Rooted<JSObject*> deviceAddresses(cx);
   278     if (NS_FAILED(nsTArrayToJSArray(cx, mDeviceAddresses,
   279                                     deviceAddresses.address()))) {
   280       BT_WARNING("Cannot set JS Devices object!");
   281       return;
   282     }
   283     mJsDeviceAddresses = deviceAddresses;
   284     Root();
   285   } else {
   286 #ifdef DEBUG
   287     nsCString warningMsg;
   288     warningMsg.AssignLiteral("Not handling adapter property: ");
   289     warningMsg.Append(NS_ConvertUTF16toUTF8(name));
   290     BT_WARNING(warningMsg.get());
   291 #endif
   292   }
   293 }
   295 // static
   296 already_AddRefed<BluetoothAdapter>
   297 BluetoothAdapter::Create(nsPIDOMWindow* aWindow, const BluetoothValue& aValue)
   298 {
   299   MOZ_ASSERT(NS_IsMainThread());
   300   MOZ_ASSERT(aWindow);
   302   nsRefPtr<BluetoothAdapter> adapter = new BluetoothAdapter(aWindow, aValue);
   303   return adapter.forget();
   304 }
   306 void
   307 BluetoothAdapter::Notify(const BluetoothSignal& aData)
   308 {
   309   InfallibleTArray<BluetoothNamedValue> arr;
   311   BT_LOGD("[A] %s: %s", __FUNCTION__, NS_ConvertUTF16toUTF8(aData.name()).get());
   313   BluetoothValue v = aData.value();
   314   if (aData.name().EqualsLiteral("DeviceFound")) {
   315     nsRefPtr<BluetoothDevice> device = BluetoothDevice::Create(GetOwner(), mPath, aData.value());
   317     BluetoothDeviceEventInit init;
   318     init.mBubbles = false;
   319     init.mCancelable = false;
   320     init.mDevice = device;
   321     nsRefPtr<BluetoothDeviceEvent> event =
   322       BluetoothDeviceEvent::Constructor(this, NS_LITERAL_STRING("devicefound"), init);
   323     DispatchTrustedEvent(event);
   324   } else if (aData.name().EqualsLiteral("PropertyChanged")) {
   325     MOZ_ASSERT(v.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
   327     const InfallibleTArray<BluetoothNamedValue>& arr =
   328       v.get_ArrayOfBluetoothNamedValue();
   330     for (uint32_t i = 0, propCount = arr.Length(); i < propCount; ++i) {
   331       SetPropertyByValue(arr[i]);
   332     }
   333   } else if (aData.name().EqualsLiteral(PAIRED_STATUS_CHANGED_ID) ||
   334              aData.name().EqualsLiteral(HFP_STATUS_CHANGED_ID) ||
   335              aData.name().EqualsLiteral(SCO_STATUS_CHANGED_ID) ||
   336              aData.name().EqualsLiteral(A2DP_STATUS_CHANGED_ID)) {
   337     MOZ_ASSERT(v.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
   338     const InfallibleTArray<BluetoothNamedValue>& arr =
   339       v.get_ArrayOfBluetoothNamedValue();
   341     MOZ_ASSERT(arr.Length() == 2 &&
   342                arr[0].value().type() == BluetoothValue::TnsString &&
   343                arr[1].value().type() == BluetoothValue::Tbool);
   344     nsString address = arr[0].value().get_nsString();
   345     bool status = arr[1].value().get_bool();
   347     BluetoothStatusChangedEventInit init;
   348     init.mBubbles = false;
   349     init.mCancelable = false;
   350     init.mAddress = address;
   351     init.mStatus = status;
   352     nsRefPtr<BluetoothStatusChangedEvent> event =
   353       BluetoothStatusChangedEvent::Constructor(this, aData.name(), init);
   354     DispatchTrustedEvent(event);
   355   } else if (aData.name().EqualsLiteral(REQUEST_MEDIA_PLAYSTATUS_ID)) {
   356     nsCOMPtr<nsIDOMEvent> event;
   357     nsresult rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr);
   358     NS_ENSURE_SUCCESS_VOID(rv);
   360     rv = event->InitEvent(aData.name(), false, false);
   361     NS_ENSURE_SUCCESS_VOID(rv);
   363     DispatchTrustedEvent(event);
   364   } else {
   365 #ifdef DEBUG
   366     nsCString warningMsg;
   367     warningMsg.AssignLiteral("Not handling adapter signal: ");
   368     warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
   369     BT_WARNING(warningMsg.get());
   370 #endif
   371   }
   372 }
   374 already_AddRefed<DOMRequest>
   375 BluetoothAdapter::StartStopDiscovery(bool aStart, ErrorResult& aRv)
   376 {
   377   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   378   if (!win) {
   379     aRv.Throw(NS_ERROR_FAILURE);
   380     return nullptr;
   381   }
   383   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   384   nsRefPtr<BluetoothVoidReplyRunnable> results =
   385     new BluetoothVoidReplyRunnable(request);
   387   BluetoothService* bs = BluetoothService::Get();
   388   if (!bs) {
   389     aRv.Throw(NS_ERROR_FAILURE);
   390     return nullptr;
   391   }
   392   nsresult rv;
   393   if (aStart) {
   394     rv = bs->StartDiscoveryInternal(results);
   395   } else {
   396     rv = bs->StopDiscoveryInternal(results);
   397   }
   398   if (NS_FAILED(rv)) {
   399     BT_WARNING("Start/Stop Discovery failed!");
   400     aRv.Throw(rv);
   401     return nullptr;
   402   }
   404   // mDiscovering is not set here, we'll get a Property update from our external
   405   // protocol to tell us that it's been set.
   407   return request.forget();
   408 }
   410 already_AddRefed<DOMRequest>
   411 BluetoothAdapter::StartDiscovery(ErrorResult& aRv)
   412 {
   413   return StartStopDiscovery(true, aRv);
   414 }
   416 already_AddRefed<DOMRequest>
   417 BluetoothAdapter::StopDiscovery(ErrorResult& aRv)
   418 {
   419   return StartStopDiscovery(false, aRv);
   420 }
   422 void
   423 BluetoothAdapter::GetDevices(JSContext* aContext,
   424                              JS::MutableHandle<JS::Value> aDevices,
   425                              ErrorResult& aRv)
   426 {
   427   if (!mJsDeviceAddresses) {
   428     BT_WARNING("Devices not yet set!\n");
   429     aRv.Throw(NS_ERROR_FAILURE);
   430     return;
   431   }
   433   JS::ExposeObjectToActiveJS(mJsDeviceAddresses);
   434   aDevices.setObject(*mJsDeviceAddresses);
   435 }
   437 void
   438 BluetoothAdapter::GetUuids(JSContext* aContext,
   439                            JS::MutableHandle<JS::Value> aUuids,
   440                            ErrorResult& aRv)
   441 {
   442   if (!mJsUuids) {
   443     BT_WARNING("UUIDs not yet set!\n");
   444     aRv.Throw(NS_ERROR_FAILURE);
   445     return;
   446   }
   448   JS::ExposeObjectToActiveJS(mJsUuids);
   449   aUuids.setObject(*mJsUuids);
   450 }
   452 already_AddRefed<DOMRequest>
   453 BluetoothAdapter::SetName(const nsAString& aName, ErrorResult& aRv)
   454 {
   455   if (mName.Equals(aName)) {
   456     return FirePropertyAlreadySet(GetOwner(), aRv);
   457   }
   458   nsString name(aName);
   459   BluetoothValue value(name);
   460   BluetoothNamedValue property(NS_LITERAL_STRING("Name"), value);
   461   return SetProperty(GetOwner(), property, aRv);
   462 }
   464 already_AddRefed<DOMRequest>
   465 BluetoothAdapter::SetDiscoverable(bool aDiscoverable, ErrorResult& aRv)
   466 {
   467   if (aDiscoverable == mDiscoverable) {
   468     return FirePropertyAlreadySet(GetOwner(), aRv);
   469   }
   470   BluetoothValue value(aDiscoverable);
   471   BluetoothNamedValue property(NS_LITERAL_STRING("Discoverable"), value);
   472   return SetProperty(GetOwner(), property, aRv);
   473 }
   475 already_AddRefed<DOMRequest>
   476 BluetoothAdapter::SetDiscoverableTimeout(uint32_t aDiscoverableTimeout, ErrorResult& aRv)
   477 {
   478   if (aDiscoverableTimeout == mDiscoverableTimeout) {
   479     return FirePropertyAlreadySet(GetOwner(), aRv);
   480   }
   481   BluetoothValue value(aDiscoverableTimeout);
   482   BluetoothNamedValue property(NS_LITERAL_STRING("DiscoverableTimeout"), value);
   483   return SetProperty(GetOwner(), property, aRv);
   484 }
   486 already_AddRefed<DOMRequest>
   487 BluetoothAdapter::GetConnectedDevices(uint16_t aServiceUuid, ErrorResult& aRv)
   488 {
   489   MOZ_ASSERT(NS_IsMainThread());
   491   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   492   if (!win) {
   493     aRv.Throw(NS_ERROR_FAILURE);
   494     return nullptr;
   495   }
   497   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   498   nsRefPtr<BluetoothReplyRunnable> results =
   499     new GetDevicesTask(this, request);
   501   BluetoothService* bs = BluetoothService::Get();
   502   if (!bs) {
   503     aRv.Throw(NS_ERROR_FAILURE);
   504     return nullptr;
   505   }
   506   nsresult rv = bs->GetConnectedDevicePropertiesInternal(aServiceUuid, results);
   507   if (NS_FAILED(rv)) {
   508     aRv.Throw(rv);
   509     return nullptr;
   510   }
   512   return request.forget();
   513 }
   515 already_AddRefed<DOMRequest>
   516 BluetoothAdapter::GetPairedDevices(ErrorResult& aRv)
   517 {
   518   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   519   if (!win) {
   520     aRv.Throw(NS_ERROR_FAILURE);
   521     return nullptr;
   522   }
   524   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   525   nsRefPtr<BluetoothReplyRunnable> results =
   526     new GetDevicesTask(this, request);
   528   BluetoothService* bs = BluetoothService::Get();
   529   if (!bs) {
   530     aRv.Throw(NS_ERROR_FAILURE);
   531     return nullptr;
   532   }
   533   nsresult rv = bs->GetPairedDevicePropertiesInternal(mDeviceAddresses, results);
   534   if (NS_FAILED(rv)) {
   535     aRv.Throw(rv);
   536     return nullptr;
   537   }
   539   return request.forget();
   540 }
   542 already_AddRefed<DOMRequest>
   543 BluetoothAdapter::PairUnpair(bool aPair, const nsAString& aDeviceAddress,
   544                              ErrorResult& aRv)
   545 {
   546   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   547   if (!win) {
   548     aRv.Throw(NS_ERROR_FAILURE);
   549     return nullptr;
   550   }
   552   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   553   nsRefPtr<BluetoothVoidReplyRunnable> results =
   554     new BluetoothVoidReplyRunnable(request);
   556   BluetoothService* bs = BluetoothService::Get();
   557   if (!bs) {
   558     aRv.Throw(NS_ERROR_FAILURE);
   559     return nullptr;
   560   }
   561   nsresult rv;
   562   if (aPair) {
   563     rv = bs->CreatePairedDeviceInternal(aDeviceAddress,
   564                                         kCreatePairedDeviceTimeout,
   565                                         results);
   566   } else {
   567     rv = bs->RemoveDeviceInternal(aDeviceAddress, results);
   568   }
   569   if (NS_FAILED(rv)) {
   570     BT_WARNING("Pair/Unpair failed!");
   571     aRv.Throw(rv);
   572     return nullptr;
   573   }
   575   return request.forget();
   576 }
   578 already_AddRefed<DOMRequest>
   579 BluetoothAdapter::Pair(const nsAString& aDeviceAddress, ErrorResult& aRv)
   580 {
   581   return PairUnpair(true, aDeviceAddress, aRv);
   582 }
   584 already_AddRefed<DOMRequest>
   585 BluetoothAdapter::Unpair(const nsAString& aDeviceAddress, ErrorResult& aRv)
   586 {
   587   return PairUnpair(false, aDeviceAddress, aRv);
   588 }
   590 already_AddRefed<DOMRequest>
   591 BluetoothAdapter::SetPinCode(const nsAString& aDeviceAddress,
   592                              const nsAString& aPinCode, ErrorResult& aRv)
   593 {
   594   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   595   if (!win) {
   596     aRv.Throw(NS_ERROR_FAILURE);
   597     return nullptr;
   598   }
   600   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   601   nsRefPtr<BluetoothVoidReplyRunnable> results =
   602     new BluetoothVoidReplyRunnable(request);
   604   BluetoothService* bs = BluetoothService::Get();
   605   if (!bs) {
   606     aRv.Throw(NS_ERROR_FAILURE);
   607     return nullptr;
   608   }
   609   if (!bs->SetPinCodeInternal(aDeviceAddress, aPinCode, results)) {
   610     BT_WARNING("SetPinCode failed!");
   611     aRv.Throw(NS_ERROR_FAILURE);
   612     return nullptr;
   613   }
   615   return request.forget();
   616 }
   618 already_AddRefed<DOMRequest>
   619 BluetoothAdapter::SetPasskey(const nsAString& aDeviceAddress, uint32_t aPasskey,
   620                              ErrorResult& aRv)
   621 {
   622   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   623   if (!win) {
   624     aRv.Throw(NS_ERROR_FAILURE);
   625     return nullptr;
   626   }
   628   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   629   nsRefPtr<BluetoothVoidReplyRunnable> results =
   630     new BluetoothVoidReplyRunnable(request);
   632   BluetoothService* bs = BluetoothService::Get();
   633   if (!bs) {
   634     aRv.Throw(NS_ERROR_FAILURE);
   635     return nullptr;
   636   }
   637   if (bs->SetPasskeyInternal(aDeviceAddress, aPasskey, results)) {
   638     BT_WARNING("SetPasskeyInternal failed!");
   639     aRv.Throw(NS_ERROR_FAILURE);
   640     return nullptr;
   641   }
   643   return request.forget();
   644 }
   646 already_AddRefed<DOMRequest>
   647 BluetoothAdapter::SetPairingConfirmation(const nsAString& aDeviceAddress,
   648                                          bool aConfirmation, ErrorResult& aRv)
   649 {
   650   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   651   if (!win) {
   652     aRv.Throw(NS_ERROR_FAILURE);
   653     return nullptr;
   654   }
   656   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   657   nsRefPtr<BluetoothVoidReplyRunnable> results =
   658     new BluetoothVoidReplyRunnable(request);
   660   BluetoothService* bs = BluetoothService::Get();
   661   if (!bs) {
   662     aRv.Throw(NS_ERROR_FAILURE);
   663     return nullptr;
   664   }
   665   if (!bs->SetPairingConfirmationInternal(aDeviceAddress,
   666                                           aConfirmation,
   667                                           results)) {
   668     BT_WARNING("SetPairingConfirmation failed!");
   669     aRv.Throw(NS_ERROR_FAILURE);
   670     return nullptr;
   671   }
   673   return request.forget();
   674 }
   676 already_AddRefed<DOMRequest>
   677 BluetoothAdapter::Connect(BluetoothDevice& aDevice,
   678                           const Optional<short unsigned int>& aServiceUuid,
   679                           ErrorResult& aRv)
   680 {
   681   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   682   if (!win) {
   683     aRv.Throw(NS_ERROR_FAILURE);
   684     return nullptr;
   685   }
   687   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   688   nsRefPtr<BluetoothVoidReplyRunnable> results =
   689     new BluetoothVoidReplyRunnable(request);
   691   nsAutoString address;
   692   aDevice.GetAddress(address);
   693   uint32_t deviceClass = aDevice.Class();
   694   uint16_t serviceUuid = 0;
   695   if (aServiceUuid.WasPassed()) {
   696     serviceUuid = aServiceUuid.Value();
   697   }
   699   BluetoothService* bs = BluetoothService::Get();
   700   if (!bs) {
   701     aRv.Throw(NS_ERROR_FAILURE);
   702     return nullptr;
   703   }
   704   bs->Connect(address, deviceClass, serviceUuid, results);
   706   return request.forget();
   707 }
   709 already_AddRefed<DOMRequest>
   710 BluetoothAdapter::Disconnect(BluetoothDevice& aDevice,
   711                              const Optional<short unsigned int>& aServiceUuid,
   712                              ErrorResult& aRv)
   713 {
   714   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   715   if (!win) {
   716     aRv.Throw(NS_ERROR_FAILURE);
   717     return nullptr;
   718   }
   720   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   721   nsRefPtr<BluetoothVoidReplyRunnable> results =
   722     new BluetoothVoidReplyRunnable(request);
   724   nsAutoString address;
   725   aDevice.GetAddress(address);
   726   uint16_t serviceUuid = 0;
   727   if (aServiceUuid.WasPassed()) {
   728     serviceUuid = aServiceUuid.Value();
   729   }
   731   BluetoothService* bs = BluetoothService::Get();
   732   if (!bs) {
   733     aRv.Throw(NS_ERROR_FAILURE);
   734     return nullptr;
   735   }
   736   bs->Disconnect(address, serviceUuid, results);
   738   return request.forget();
   739 }
   741 already_AddRefed<DOMRequest>
   742 BluetoothAdapter::SendFile(const nsAString& aDeviceAddress,
   743                            nsIDOMBlob* aBlob, ErrorResult& aRv)
   744 {
   745   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   746   if (!win) {
   747     aRv.Throw(NS_ERROR_FAILURE);
   748     return nullptr;
   749   }
   751   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   752   nsRefPtr<BluetoothVoidReplyRunnable> results =
   753     new BluetoothVoidReplyRunnable(request);
   755   BluetoothService* bs = BluetoothService::Get();
   756   if (!bs) {
   757     aRv.Throw(NS_ERROR_FAILURE);
   758     return nullptr;
   759   }
   761   if (XRE_GetProcessType() == GeckoProcessType_Default) {
   762     // In-process transfer
   763     bs->SendFile(aDeviceAddress, aBlob, results);
   764   } else {
   765     ContentChild *cc = ContentChild::GetSingleton();
   766     if (!cc) {
   767       aRv.Throw(NS_ERROR_FAILURE);
   768       return nullptr;
   769     }
   771     BlobChild* actor = cc->GetOrCreateActorForBlob(aBlob);
   772     if (!actor) {
   773       aRv.Throw(NS_ERROR_FAILURE);
   774       return nullptr;
   775     }
   777     bs->SendFile(aDeviceAddress, nullptr, actor, results);
   778   }
   780   return request.forget();
   781 }
   783 already_AddRefed<DOMRequest>
   784 BluetoothAdapter::StopSendingFile(const nsAString& aDeviceAddress, ErrorResult& aRv)
   785 {
   786   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   787   if (!win) {
   788     aRv.Throw(NS_ERROR_FAILURE);
   789     return nullptr;
   790   }
   792   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   793   nsRefPtr<BluetoothVoidReplyRunnable> results =
   794     new BluetoothVoidReplyRunnable(request);
   796   BluetoothService* bs = BluetoothService::Get();
   797   if (!bs) {
   798     aRv.Throw(NS_ERROR_FAILURE);
   799     return nullptr;
   800   }
   801   bs->StopSendingFile(aDeviceAddress, results);
   803   return request.forget();
   804 }
   806 already_AddRefed<DOMRequest>
   807 BluetoothAdapter::ConfirmReceivingFile(const nsAString& aDeviceAddress,
   808                                        bool aConfirmation, ErrorResult& aRv)
   809 {
   810   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   811   if (!win) {
   812     aRv.Throw(NS_ERROR_FAILURE);
   813     return nullptr;
   814   }
   816   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   817   nsRefPtr<BluetoothVoidReplyRunnable> results =
   818     new BluetoothVoidReplyRunnable(request);
   820   BluetoothService* bs = BluetoothService::Get();
   821   if (!bs) {
   822     aRv.Throw(NS_ERROR_FAILURE);
   823     return nullptr;
   824   }
   825   bs->ConfirmReceivingFile(aDeviceAddress, aConfirmation, results);
   827   return request.forget();
   828 }
   830 already_AddRefed<DOMRequest>
   831 BluetoothAdapter::ConnectSco(ErrorResult& aRv)
   832 {
   833   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   834   if (!win) {
   835     aRv.Throw(NS_ERROR_FAILURE);
   836     return nullptr;
   837   }
   839   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   840   nsRefPtr<BluetoothVoidReplyRunnable> results =
   841     new BluetoothVoidReplyRunnable(request);
   843   BluetoothService* bs = BluetoothService::Get();
   844   if (!bs) {
   845     aRv.Throw(NS_ERROR_FAILURE);
   846     return nullptr;
   847   }
   848   bs->ConnectSco(results);
   850   return request.forget();
   851 }
   853 already_AddRefed<DOMRequest>
   854 BluetoothAdapter::DisconnectSco(ErrorResult& aRv)
   855 {
   856   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   857   if (!win) {
   858     aRv.Throw(NS_ERROR_FAILURE);
   859     return nullptr;
   860   }
   862   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   863   nsRefPtr<BluetoothVoidReplyRunnable> results =
   864     new BluetoothVoidReplyRunnable(request);
   866   BluetoothService* bs = BluetoothService::Get();
   867   if (!bs) {
   868     aRv.Throw(NS_ERROR_FAILURE);
   869     return nullptr;
   870   }
   871   bs->DisconnectSco(results);
   873   return request.forget();
   874 }
   876 already_AddRefed<DOMRequest>
   877 BluetoothAdapter::IsScoConnected(ErrorResult& aRv)
   878 {
   879   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   880   if (!win) {
   881     aRv.Throw(NS_ERROR_FAILURE);
   882     return nullptr;
   883   }
   885   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   886   nsRefPtr<BluetoothReplyRunnable> results =
   887     new GetScoConnectionStatusTask(request);
   889   BluetoothService* bs = BluetoothService::Get();
   890   if (!bs) {
   891     aRv.Throw(NS_ERROR_FAILURE);
   892     return nullptr;
   893   }
   894   bs->IsScoConnected(results);
   896   return request.forget();
   897 }
   899 already_AddRefed<DOMRequest>
   900 BluetoothAdapter::AnswerWaitingCall(ErrorResult& aRv)
   901 {
   902 #ifdef MOZ_B2G_RIL
   903   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   904   if (!win) {
   905     aRv.Throw(NS_ERROR_FAILURE);
   906     return nullptr;
   907   }
   909   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   910   nsRefPtr<BluetoothVoidReplyRunnable> results =
   911     new BluetoothVoidReplyRunnable(request);
   913   BluetoothService* bs = BluetoothService::Get();
   914   if (!bs) {
   915     aRv.Throw(NS_ERROR_FAILURE);
   916     return nullptr;
   917   }
   918   bs->AnswerWaitingCall(results);
   920   return request.forget();
   921 #else
   922   aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
   923   return nullptr;
   924 #endif // MOZ_B2G_RIL
   925 }
   927 already_AddRefed<DOMRequest>
   928 BluetoothAdapter::IgnoreWaitingCall(ErrorResult& aRv)
   929 {
   930 #ifdef MOZ_B2G_RIL
   931   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   932   if (!win) {
   933     aRv.Throw(NS_ERROR_FAILURE);
   934     return nullptr;
   935   }
   937   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   938   nsRefPtr<BluetoothVoidReplyRunnable> results =
   939     new BluetoothVoidReplyRunnable(request);
   941   BluetoothService* bs = BluetoothService::Get();
   942   if (!bs) {
   943     aRv.Throw(NS_ERROR_FAILURE);
   944     return nullptr;
   945   }
   946   bs->IgnoreWaitingCall(results);
   948   return request.forget();
   949 #else
   950   aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
   951   return nullptr;
   952 #endif // MOZ_B2G_RIL
   953 }
   955 already_AddRefed<DOMRequest>
   956 BluetoothAdapter::ToggleCalls(ErrorResult& aRv)
   957 {
   958 #ifdef MOZ_B2G_RIL
   959   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   960   if (!win) {
   961     aRv.Throw(NS_ERROR_FAILURE);
   962     return nullptr;
   963   }
   965   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   966   nsRefPtr<BluetoothVoidReplyRunnable> results =
   967     new BluetoothVoidReplyRunnable(request);
   969   BluetoothService* bs = BluetoothService::Get();
   970   if (!bs) {
   971     aRv.Throw(NS_ERROR_FAILURE);
   972     return nullptr;
   973   }
   974   bs->ToggleCalls(results);
   976   return request.forget();
   977 #else
   978   aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
   979   return nullptr;
   980 #endif // MOZ_B2G_RIL
   981 }
   983 already_AddRefed<DOMRequest>
   984 BluetoothAdapter::SendMediaMetaData(const MediaMetaData& aMediaMetaData, ErrorResult& aRv)
   985 {
   986   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   987   if (!win) {
   988     aRv.Throw(NS_ERROR_FAILURE);
   989     return nullptr;
   990   }
   992   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   993   nsRefPtr<BluetoothReplyRunnable> results =
   994     new BluetoothVoidReplyRunnable(request);
   996   BluetoothService* bs = BluetoothService::Get();
   997   if (!bs) {
   998     aRv.Throw(NS_ERROR_FAILURE);
   999     return nullptr;
  1001   bs->SendMetaData(aMediaMetaData.mTitle,
  1002                    aMediaMetaData.mArtist,
  1003                    aMediaMetaData.mAlbum,
  1004                    aMediaMetaData.mMediaNumber,
  1005                    aMediaMetaData.mTotalMediaCount,
  1006                    aMediaMetaData.mDuration,
  1007                    results);
  1009   return request.forget();
  1012 already_AddRefed<DOMRequest>
  1013 BluetoothAdapter::SendMediaPlayStatus(const MediaPlayStatus& aMediaPlayStatus, ErrorResult& aRv)
  1015   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
  1016   if (!win) {
  1017     aRv.Throw(NS_ERROR_FAILURE);
  1018     return nullptr;
  1021   nsRefPtr<DOMRequest> request = new DOMRequest(win);
  1022   nsRefPtr<BluetoothReplyRunnable> results =
  1023     new BluetoothVoidReplyRunnable(request);
  1025   BluetoothService* bs = BluetoothService::Get();
  1026   if (!bs) {
  1027     aRv.Throw(NS_ERROR_FAILURE);
  1028     return nullptr;
  1030   bs->SendPlayStatus(aMediaPlayStatus.mDuration,
  1031                      aMediaPlayStatus.mPosition,
  1032                      aMediaPlayStatus.mPlayStatus,
  1033                      results);
  1035   return request.forget();
  1038 JSObject*
  1039 BluetoothAdapter::WrapObject(JSContext* aCx)
  1041   return BluetoothAdapterBinding::Wrap(aCx, this);

mercurial