dom/bluetooth/BluetoothDevice.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/bluetooth/BluetoothDevice.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,243 @@
     1.4 +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
     1.5 +/* vim: set ts=2 et sw=2 tw=80: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.8 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include "base/basictypes.h"
    1.11 +#include "BluetoothDevice.h"
    1.12 +#include "BluetoothReplyRunnable.h"
    1.13 +#include "BluetoothService.h"
    1.14 +#include "BluetoothUtils.h"
    1.15 +
    1.16 +#include "nsDOMClassInfo.h"
    1.17 +#include "nsTArrayHelpers.h"
    1.18 +
    1.19 +#include "mozilla/dom/bluetooth/BluetoothTypes.h"
    1.20 +#include "mozilla/dom/BluetoothDeviceBinding.h"
    1.21 +
    1.22 +USING_BLUETOOTH_NAMESPACE
    1.23 +
    1.24 +DOMCI_DATA(BluetoothDevice, BluetoothDevice)
    1.25 +
    1.26 +NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothDevice)
    1.27 +
    1.28 +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(BluetoothDevice,
    1.29 +                                               DOMEventTargetHelper)
    1.30 +  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsUuids)
    1.31 +  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsServices)
    1.32 +NS_IMPL_CYCLE_COLLECTION_TRACE_END
    1.33 +
    1.34 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothDevice,
    1.35 +                                                  DOMEventTargetHelper)
    1.36 +  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
    1.37 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    1.38 +
    1.39 +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothDevice,
    1.40 +                                                DOMEventTargetHelper)
    1.41 +  tmp->Unroot();
    1.42 +NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    1.43 +
    1.44 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothDevice)
    1.45 +NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
    1.46 +
    1.47 +NS_IMPL_ADDREF_INHERITED(BluetoothDevice, DOMEventTargetHelper)
    1.48 +NS_IMPL_RELEASE_INHERITED(BluetoothDevice, DOMEventTargetHelper)
    1.49 +
    1.50 +BluetoothDevice::BluetoothDevice(nsPIDOMWindow* aWindow,
    1.51 +                                 const nsAString& aAdapterPath,
    1.52 +                                 const BluetoothValue& aValue)
    1.53 +  : DOMEventTargetHelper(aWindow)
    1.54 +  , BluetoothPropertyContainer(BluetoothObjectType::TYPE_DEVICE)
    1.55 +  , mJsUuids(nullptr)
    1.56 +  , mJsServices(nullptr)
    1.57 +  , mAdapterPath(aAdapterPath)
    1.58 +  , mIsRooted(false)
    1.59 +{
    1.60 +  MOZ_ASSERT(aWindow);
    1.61 +  MOZ_ASSERT(IsDOMBinding());
    1.62 +
    1.63 +  const InfallibleTArray<BluetoothNamedValue>& values =
    1.64 +    aValue.get_ArrayOfBluetoothNamedValue();
    1.65 +  for (uint32_t i = 0; i < values.Length(); ++i) {
    1.66 +    SetPropertyByValue(values[i]);
    1.67 +  }
    1.68 +
    1.69 +  BluetoothService* bs = BluetoothService::Get();
    1.70 +  NS_ENSURE_TRUE_VOID(bs);
    1.71 +  bs->RegisterBluetoothSignalHandler(mAddress, this);
    1.72 +}
    1.73 +
    1.74 +BluetoothDevice::~BluetoothDevice()
    1.75 +{
    1.76 +  BluetoothService* bs = BluetoothService::Get();
    1.77 +  // bs can be null on shutdown, where destruction might happen.
    1.78 +  NS_ENSURE_TRUE_VOID(bs);
    1.79 +  bs->UnregisterBluetoothSignalHandler(mAddress, this);
    1.80 +  Unroot();
    1.81 +}
    1.82 +
    1.83 +void
    1.84 +BluetoothDevice::DisconnectFromOwner()
    1.85 +{
    1.86 +  DOMEventTargetHelper::DisconnectFromOwner();
    1.87 +
    1.88 +  BluetoothService* bs = BluetoothService::Get();
    1.89 +  NS_ENSURE_TRUE_VOID(bs);
    1.90 +  bs->UnregisterBluetoothSignalHandler(mAddress, this);
    1.91 +}
    1.92 +
    1.93 +void
    1.94 +BluetoothDevice::Root()
    1.95 +{
    1.96 +  if (!mIsRooted) {
    1.97 +    mozilla::HoldJSObjects(this);
    1.98 +    mIsRooted = true;
    1.99 +  }
   1.100 +}
   1.101 +
   1.102 +void
   1.103 +BluetoothDevice::Unroot()
   1.104 +{
   1.105 +  if (mIsRooted) {
   1.106 +    mJsUuids = nullptr;
   1.107 +    mJsServices = nullptr;
   1.108 +    mozilla::DropJSObjects(this);
   1.109 +    mIsRooted = false;
   1.110 +  }
   1.111 +}
   1.112 +
   1.113 +void
   1.114 +BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue& aValue)
   1.115 +{
   1.116 +  const nsString& name = aValue.name();
   1.117 +  const BluetoothValue& value = aValue.value();
   1.118 +  if (name.EqualsLiteral("Name")) {
   1.119 +    mName = value.get_nsString();
   1.120 +  } else if (name.EqualsLiteral("Path")) {
   1.121 +    MOZ_ASSERT(value.get_nsString().Length() > 0);
   1.122 +    mPath = value.get_nsString();
   1.123 +  } else if (name.EqualsLiteral("Address")) {
   1.124 +    mAddress = value.get_nsString();
   1.125 +  } else if (name.EqualsLiteral("Class")) {
   1.126 +    mClass = value.get_uint32_t();
   1.127 +  } else if (name.EqualsLiteral("Icon")) {
   1.128 +    mIcon = value.get_nsString();
   1.129 +  } else if (name.EqualsLiteral("Connected")) {
   1.130 +    mConnected = value.get_bool();
   1.131 +  } else if (name.EqualsLiteral("Paired")) {
   1.132 +    mPaired = value.get_bool();
   1.133 +  } else if (name.EqualsLiteral("UUIDs")) {
   1.134 +    mUuids = value.get_ArrayOfnsString();
   1.135 +    nsresult rv;
   1.136 +    nsIScriptContext* sc = GetContextForEventHandlers(&rv);
   1.137 +    NS_ENSURE_SUCCESS_VOID(rv);
   1.138 +    NS_ENSURE_TRUE_VOID(sc);
   1.139 +
   1.140 +    AutoPushJSContext cx(sc->GetNativeContext());
   1.141 +
   1.142 +    JS::Rooted<JSObject*> uuids(cx);
   1.143 +    if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, uuids.address()))) {
   1.144 +      BT_WARNING("Cannot set JS UUIDs object!");
   1.145 +      return;
   1.146 +    }
   1.147 +    mJsUuids = uuids;
   1.148 +    Root();
   1.149 +  } else if (name.EqualsLiteral("Services")) {
   1.150 +    mServices = value.get_ArrayOfnsString();
   1.151 +    nsresult rv;
   1.152 +    nsIScriptContext* sc = GetContextForEventHandlers(&rv);
   1.153 +    NS_ENSURE_SUCCESS_VOID(rv);
   1.154 +    NS_ENSURE_TRUE_VOID(sc);
   1.155 +
   1.156 +    AutoPushJSContext cx(sc->GetNativeContext());
   1.157 +
   1.158 +    JS::Rooted<JSObject*> services(cx);
   1.159 +    if (NS_FAILED(nsTArrayToJSArray(cx, mServices, services.address()))) {
   1.160 +      BT_WARNING("Cannot set JS Services object!");
   1.161 +      return;
   1.162 +    }
   1.163 +    mJsServices = services;
   1.164 +    Root();
   1.165 +  } else {
   1.166 +    nsCString warningMsg;
   1.167 +    warningMsg.AssignLiteral("Not handling device property: ");
   1.168 +    warningMsg.Append(NS_ConvertUTF16toUTF8(name));
   1.169 +    BT_WARNING(warningMsg.get());
   1.170 +  }
   1.171 +}
   1.172 +
   1.173 +// static
   1.174 +already_AddRefed<BluetoothDevice>
   1.175 +BluetoothDevice::Create(nsPIDOMWindow* aWindow,
   1.176 +                        const nsAString& aAdapterPath,
   1.177 +                        const BluetoothValue& aValue)
   1.178 +{
   1.179 +  MOZ_ASSERT(NS_IsMainThread());
   1.180 +  MOZ_ASSERT(aWindow);
   1.181 +
   1.182 +  nsRefPtr<BluetoothDevice> device =
   1.183 +    new BluetoothDevice(aWindow, aAdapterPath, aValue);
   1.184 +  return device.forget();
   1.185 +}
   1.186 +
   1.187 +void
   1.188 +BluetoothDevice::Notify(const BluetoothSignal& aData)
   1.189 +{
   1.190 +  BT_LOGD("[D] %s: %s", __FUNCTION__, NS_ConvertUTF16toUTF8(aData.name()).get());
   1.191 +
   1.192 +  BluetoothValue v = aData.value();
   1.193 +  if (aData.name().EqualsLiteral("PropertyChanged")) {
   1.194 +    MOZ_ASSERT(v.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
   1.195 +
   1.196 +    const InfallibleTArray<BluetoothNamedValue>& arr =
   1.197 +      v.get_ArrayOfBluetoothNamedValue();
   1.198 +
   1.199 +    for (uint32_t i = 0, propCount = arr.Length(); i < propCount; ++i) {
   1.200 +      SetPropertyByValue(arr[i]);
   1.201 +    }
   1.202 +  } else {
   1.203 +#ifdef DEBUG
   1.204 +    nsCString warningMsg;
   1.205 +    warningMsg.AssignLiteral("Not handling device signal: ");
   1.206 +    warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
   1.207 +    BT_WARNING(warningMsg.get());
   1.208 +#endif
   1.209 +  }
   1.210 +}
   1.211 +
   1.212 +void
   1.213 +BluetoothDevice::GetUuids(JSContext* aContext,
   1.214 +                           JS::MutableHandle<JS::Value> aUuids,
   1.215 +                           ErrorResult& aRv)
   1.216 +{
   1.217 +  if (!mJsUuids) {
   1.218 +    BT_WARNING("UUIDs not yet set!");
   1.219 +    aRv.Throw(NS_ERROR_FAILURE);
   1.220 +    return;
   1.221 +  }
   1.222 +
   1.223 +  JS::ExposeObjectToActiveJS(mJsUuids);
   1.224 +  aUuids.setObject(*mJsUuids);
   1.225 +}
   1.226 +
   1.227 +void
   1.228 +BluetoothDevice::GetServices(JSContext* aCx,
   1.229 +                             JS::MutableHandle<JS::Value> aServices,
   1.230 +                             ErrorResult& aRv)
   1.231 +{
   1.232 +  if (!mJsServices) {
   1.233 +    BT_WARNING("Services not yet set!");
   1.234 +    aRv.Throw(NS_ERROR_FAILURE);
   1.235 +    return;
   1.236 +  }
   1.237 +
   1.238 +  JS::ExposeObjectToActiveJS(mJsServices);
   1.239 +  aServices.setObject(*mJsServices);
   1.240 +}
   1.241 +
   1.242 +JSObject*
   1.243 +BluetoothDevice::WrapObject(JSContext* aContext)
   1.244 +{
   1.245 +  return BluetoothDeviceBinding::Wrap(aContext, this);
   1.246 +}

mercurial