already_AddRefed<Promise>
BluetoothMapRequestHandle::ReplyToFolderListing(long aMasId,
  const nsAString& aFolderlists, ErrorResult& aRv)
{
  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
  if (!global) {
    aRv.Throw(NS_ERROR_FAILURE);
    return nullptr;
  }

  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
  NS_ENSURE_TRUE(!aRv.Failed(), nullptr);

  BluetoothService* bs = BluetoothService::Get();
  if (!bs) {
    aRv.Throw(NS_ERROR_FAILURE);
    return nullptr;
  }

  if (XRE_GetProcessType() == GeckoProcessType_Default) {
    // In-process reply
    bs->ReplyToMapFolderListing(aMasId, aFolderlists,
      new BluetoothVoidReplyRunnable(nullptr, promise));
  } else {
    ContentChild *cc = ContentChild::GetSingleton();
    if (!cc) {
      aRv.Throw(NS_ERROR_FAILURE);
      return nullptr;
    }

    bs->ReplyToMapFolderListing(aMasId, aFolderlists,
      new BluetoothVoidReplyRunnable(nullptr, promise));
  }

  return promise.forget();
}
BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow* aWindow,
                                   const BluetoothValue& aValue)
  : DOMEventTargetHelper(aWindow)
  , BluetoothPropertyContainer(BluetoothObjectType::TYPE_ADAPTER)
  , mJsUuids(nullptr)
  , mJsDeviceAddresses(nullptr)
  , mDiscoverable(false)
  , mDiscovering(false)
  , mPairable(false)
  , mPowered(false)
  , mIsRooted(false)
{
  MOZ_ASSERT(aWindow);

  const InfallibleTArray<BluetoothNamedValue>& values =
    aValue.get_ArrayOfBluetoothNamedValue();
  for (uint32_t i = 0; i < values.Length(); ++i) {
    SetPropertyByValue(values[i]);
  }

  BluetoothService* bs = BluetoothService::Get();
  NS_ENSURE_TRUE_VOID(bs);
  bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_ADAPTER), this);
}
Exemple #3
0
BluetoothDevice::BluetoothDevice(nsPIDOMWindow* aWindow,
                                 const nsAString& aAdapterPath,
                                 const BluetoothValue& aValue)
  : DOMEventTargetHelper(aWindow)
  , BluetoothPropertyContainer(BluetoothObjectType::TYPE_DEVICE)
  , mJsUuids(nullptr)
  , mJsServices(nullptr)
  , mAdapterPath(aAdapterPath)
  , mConnected(false)
  , mPaired(false)
  , mIsRooted(false)
{
  MOZ_ASSERT(aWindow);

  const InfallibleTArray<BluetoothNamedValue>& values =
    aValue.get_ArrayOfBluetoothNamedValue();
  for (uint32_t i = 0; i < values.Length(); ++i) {
    SetPropertyByValue(values[i]);
  }

  BluetoothService* bs = BluetoothService::Get();
  NS_ENSURE_TRUE_VOID(bs);
  bs->RegisterBluetoothSignalHandler(mAddress, this);
}
  bool Execute() override
  {
    BluetoothService* bs = BluetoothService::Get();
    if (NS_WARN_IF(!bs)) {
      return false;
    }

    BluetoothUuid appUuid;
    if (NS_FAILED(StringToUuid(mServer->mAppUuid, appUuid))) {
      return false;
    }

    BluetoothUuid uuid;
    mDescriptor->GetUuid(uuid);
    bs->GattServerAddDescriptorInternal(
      appUuid,
      mService->GetServiceHandle(),
      mCharacteristic->GetCharacteristicHandle(),
      uuid,
      mDescriptor->GetPermissions(),
      GetReply());

    return true;
  }
bool
BluetoothProfileController::IsBtServiceAvailable() const
{
  BluetoothService* bs = BluetoothService::Get();
  return (bs && bs->IsEnabled() && !bs->IsToggling());
}
already_AddRefed<Promise>
BluetoothGattServer::SendResponse(const nsAString& aAddress,
                                  uint16_t aStatus,
                                  int32_t aRequestId,
                                  ErrorResult& aRv)
{
  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
  if (!global) {
    aRv.Throw(NS_ERROR_FAILURE);
    return nullptr;
  }

  RefPtr<Promise> promise = Promise::Create(global, aRv);
  NS_ENSURE_TRUE(!aRv.Failed(), nullptr);

  BluetoothUuid appUuid;
  BT_ENSURE_TRUE_REJECT(NS_SUCCEEDED(StringToUuid(mAppUuid, appUuid)),
                        promise,
                        NS_ERROR_DOM_OPERATION_ERR);

  BluetoothAddress address;
  BT_ENSURE_TRUE_REJECT(
    NS_SUCCEEDED(StringToAddress(aAddress, address)),
    promise,
    NS_ERROR_INVALID_ARG);

  BT_ENSURE_TRUE_REJECT(mValid, promise, NS_ERROR_NOT_AVAILABLE);

  RequestData* requestData;
  mRequestMap.Get(aRequestId, &requestData);
  BT_ENSURE_TRUE_REJECT(requestData, promise, NS_ERROR_UNEXPECTED);

  BluetoothGattResponse response;
  memset(&response, 0, sizeof(response));
  response.mHandle = requestData->mHandle;

  if (requestData->mCharacteristic) {
    const nsTArray<uint8_t>& value = requestData->mCharacteristic->GetValue();
    response.mLength = value.Length();
    memcpy(&response.mValue, value.Elements(), response.mLength);
  } else if (requestData->mDescriptor) {
    const nsTArray<uint8_t>& value = requestData->mDescriptor->GetValue();
    response.mLength = value.Length();
    memcpy(&response.mValue, value.Elements(), response.mLength);
  } else {
    MOZ_ASSERT_UNREACHABLE(
      "There should be at least one characteristic or descriptor in the "
      "request data.");

    promise->MaybeReject(NS_ERROR_INVALID_ARG);
    return promise.forget();
  }

  BluetoothService* bs = BluetoothService::Get();
  BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);

  bs->GattServerSendResponseInternal(
    appUuid,
    address,
    aStatus,
    aRequestId,
    response,
    new BluetoothVoidReplyRunnable(nullptr, promise));

  return promise.forget();
}
BluetoothManager::~BluetoothManager()
{
  BluetoothService* bs = BluetoothService::Get();
  NS_ENSURE_TRUE_VOID(bs);
  bs->UnregisterBluetoothSignalHandler(mPath, this);
}
Exemple #8
0
BluetoothManager::~BluetoothManager()
{
  BluetoothService* bs = BluetoothService::Get();
  NS_ENSURE_TRUE_VOID(bs);
  bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
}
void
BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState)
{
  MOZ_ASSERT(NS_IsMainThread());

  BT_LOGR("BT_STATE: %d", aState);

  sAdapterEnabled = aState;

  if (!sAdapterEnabled) {
    static void (* const sDeinitManager[])(BluetoothProfileResultHandler*) = {
      BluetoothHfpManager::DeinitHfpInterface,
      BluetoothA2dpManager::DeinitA2dpInterface,
      BluetoothGattManager::DeinitGattInterface
    };

    // Return error if BluetoothService is unavailable
    BluetoothService* bs = BluetoothService::Get();
    NS_ENSURE_TRUE_VOID(bs);

    // Cleanup static adapter properties and notify adapter.
    sAdapterBdAddress.Truncate();
    sAdapterBdName.Truncate();

    InfallibleTArray<BluetoothNamedValue> props;
    BT_APPEND_NAMED_VALUE(props, "Name", sAdapterBdName);
    BT_APPEND_NAMED_VALUE(props, "Address", sAdapterBdAddress);
    if (sAdapterDiscoverable) {
      sAdapterDiscoverable = false;
      BT_APPEND_NAMED_VALUE(props, "Discoverable", false);
    }
    if (sAdapterDiscovering) {
      sAdapterDiscovering = false;
      BT_APPEND_NAMED_VALUE(props, "Discovering", false);
    }

    bs->DistributeSignal(NS_LITERAL_STRING("PropertyChanged"),
                         NS_LITERAL_STRING(KEY_ADAPTER),
                         BluetoothValue(props));

    // Cleanup bluetooth interfaces after BT state becomes BT_STATE_OFF.
    nsRefPtr<ProfileDeinitResultHandler> res =
      new ProfileDeinitResultHandler(MOZ_ARRAY_LENGTH(sDeinitManager));

    for (size_t i = 0; i < MOZ_ARRAY_LENGTH(sDeinitManager); ++i) {
      sDeinitManager[i](res);
    }
  }

  BluetoothService::AcknowledgeToggleBt(sAdapterEnabled);

  if (sAdapterEnabled) {
    // Bluetooth just enabled, clear profile controllers and runnable arrays.
    sControllerArray.Clear();
    sChangeDiscoveryRunnableArray.Clear();
    sSetPropertyRunnableArray.Clear();
    sGetDeviceRunnableArray.Clear();
    sFetchUuidsRunnableArray.Clear();
    sBondingRunnableArray.Clear();
    sUnbondingRunnableArray.Clear();
    sPairingNameTable.Clear();

    // Bluetooth scan mode is SCAN_MODE_CONNECTABLE by default, i.e., it should
    // be connectable and non-discoverable.
    NS_ENSURE_TRUE_VOID(sBtInterface);
    sBtInterface->SetAdapterProperty(
      BluetoothNamedValue(NS_ConvertUTF8toUTF16("Discoverable"), false),
      new SetAdapterPropertyDiscoverableResultHandler());

    // Trigger BluetoothOppManager to listen
    BluetoothOppManager* opp = BluetoothOppManager::Get();
    if (!opp || !opp->Listen()) {
      BT_LOGR("Fail to start BluetoothOppManager listening");
    }
  }

  // Resolve promise if existed
  if (!sChangeAdapterStateRunnableArray.IsEmpty()) {
    DispatchReplySuccess(sChangeAdapterStateRunnableArray[0]);
    sChangeAdapterStateRunnableArray.RemoveElementAt(0);
  }
}
nsresult
BluetoothManager::HandleMozsettingChanged(const PRUnichar* aData)
{
  // The string that we're interested in will be a JSON string that looks like:
  //  {"key":"bluetooth.enabled","value":true}
  nsresult rv;

  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
  if (NS_FAILED(rv)) {
    return NS_ERROR_UNEXPECTED;
  }

  JSContext *cx = sc->GetNativeContext();
  if (!cx) {
    return NS_OK;
  }

  // In the following [if] blocks, NS_OK will be returned even if JS_* functions
  // return false. That's because this function gets called whenever mozSettings
  // changes, so that we'll receive signals we're not interested in and it would
  // be one of the reasons for making JS_* functions return false.
  nsDependentString dataStr(aData);
  JS::Value val;
  if (!JS_ParseJSON(cx, dataStr.get(), dataStr.Length(), &val)) {
    return NS_OK;
  }

  if (!val.isObject()) {
    return NS_OK;
  }

  JSObject &obj(val.toObject());
  JS::Value key;
  if (!JS_GetProperty(cx, &obj, "key", &key)) {
    return NS_OK;
  }

  if (!key.isString()) {
    return NS_OK;
  }

  JSBool match;
  if (!JS_StringEqualsAscii(cx, key.toString(), "bluetooth.enabled", &match)) {
    return NS_OK;
  }

  if (!match) {
    return NS_OK;
  }

  JS::Value value;
  if (!JS_GetProperty(cx, &obj, "value", &value)) {
    return NS_OK;
  }

  if (!value.isBoolean()) {
    return NS_OK;
  }

  BluetoothService* bs = BluetoothService::Get();
  if (!bs) {
    NS_WARNING("BluetoothService not available!");
    return NS_ERROR_FAILURE;
  }

  bool enabled = value.toBoolean();
  nsCOMPtr<nsIRunnable> resultTask = new ToggleBtResultTask(this, enabled);

  if (enabled) {
    if (NS_FAILED(bs->Start(resultTask))) {
      return NS_ERROR_FAILURE;
    }
  } else {
    if (NS_FAILED(bs->Stop(resultTask))) {
      return NS_ERROR_FAILURE;
    }
  }

  return NS_OK;
}