diff -r 000000000000 -r 6474c204b198 dom/bluetooth/BluetoothManager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/bluetooth/BluetoothManager.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,252 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "base/basictypes.h" +#include "BluetoothManager.h" +#include "BluetoothCommon.h" +#include "BluetoothAdapter.h" +#include "BluetoothService.h" +#include "BluetoothReplyRunnable.h" + +#include "DOMRequest.h" +#include "nsContentUtils.h" +#include "nsDOMClassInfo.h" +#include "nsIPermissionManager.h" +#include "nsThreadUtils.h" +#include "mozilla/dom/bluetooth/BluetoothTypes.h" +#include "mozilla/dom/BluetoothManagerBinding.h" + +using namespace mozilla; + +USING_BLUETOOTH_NAMESPACE + +// QueryInterface implementation for BluetoothManager +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothManager) +NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) + +NS_IMPL_ADDREF_INHERITED(BluetoothManager, DOMEventTargetHelper) +NS_IMPL_RELEASE_INHERITED(BluetoothManager, DOMEventTargetHelper) + +class GetAdapterTask : public BluetoothReplyRunnable +{ +public: + GetAdapterTask(BluetoothManager* aManager, + nsIDOMDOMRequest* aReq) : + BluetoothReplyRunnable(aReq), + mManagerPtr(aManager) + { + } + + bool + ParseSuccessfulReply(JS::MutableHandle aValue) + { + aValue.setUndefined(); + + const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value(); + if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue) { + BT_WARNING("Not a BluetoothNamedValue array!"); + SetError(NS_LITERAL_STRING("BluetoothReplyTypeError")); + return false; + } + + if (!mManagerPtr->GetOwner()) { + BT_WARNING("Bluetooth manager was disconnected from owner window."); + + // Stop to create adapter since owner window of Bluetooth manager was + // gone. These is no need to create a DOMEvent target which has no owner + // to reply to. + return false; + } + + const InfallibleTArray& values = + v.get_ArrayOfBluetoothNamedValue(); + nsRefPtr adapter = + BluetoothAdapter::Create(mManagerPtr->GetOwner(), values); + + nsresult rv; + nsIScriptContext* sc = mManagerPtr->GetContextForEventHandlers(&rv); + if (!sc) { + BT_WARNING("Cannot create script context!"); + SetError(NS_LITERAL_STRING("BluetoothScriptContextError")); + return false; + } + + AutoPushJSContext cx(sc->GetNativeContext()); + + JS::Rooted scope(cx, sc->GetWindowProxy()); + JSAutoCompartment ac(cx, scope); + rv = nsContentUtils::WrapNative(cx, adapter, aValue); + if (NS_FAILED(rv)) { + BT_WARNING("Cannot create native object!"); + SetError(NS_LITERAL_STRING("BluetoothNativeObjectError")); + return false; + } + + return true; + } + + void + ReleaseMembers() + { + BluetoothReplyRunnable::ReleaseMembers(); + mManagerPtr = nullptr; + } + +private: + nsRefPtr mManagerPtr; +}; + +BluetoothManager::BluetoothManager(nsPIDOMWindow *aWindow) + : DOMEventTargetHelper(aWindow) + , BluetoothPropertyContainer(BluetoothObjectType::TYPE_MANAGER) +{ + MOZ_ASSERT(aWindow); + MOZ_ASSERT(IsDOMBinding()); + + mPath.AssignLiteral("/"); + + BluetoothService* bs = BluetoothService::Get(); + NS_ENSURE_TRUE_VOID(bs); + bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this); +} + +BluetoothManager::~BluetoothManager() +{ + BluetoothService* bs = BluetoothService::Get(); + NS_ENSURE_TRUE_VOID(bs); + bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this); +} + +void +BluetoothManager::DisconnectFromOwner() +{ + DOMEventTargetHelper::DisconnectFromOwner(); + + BluetoothService* bs = BluetoothService::Get(); + NS_ENSURE_TRUE_VOID(bs); + bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this); +} + +void +BluetoothManager::SetPropertyByValue(const BluetoothNamedValue& aValue) +{ +#ifdef DEBUG + const nsString& name = aValue.name(); + nsCString warningMsg; + warningMsg.AssignLiteral("Not handling manager property: "); + warningMsg.Append(NS_ConvertUTF16toUTF8(name)); + BT_WARNING(warningMsg.get()); +#endif +} + +bool +BluetoothManager::GetEnabled(ErrorResult& aRv) +{ + BluetoothService* bs = BluetoothService::Get(); + if (!bs) { + aRv.Throw(NS_ERROR_FAILURE); + return false; + } + + return bs->IsEnabled(); +} + +already_AddRefed +BluetoothManager::GetDefaultAdapter(ErrorResult& aRv) +{ + nsCOMPtr win = GetOwner(); + if (!win) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + nsRefPtr request = new DOMRequest(win); + nsRefPtr results = + new GetAdapterTask(this, request); + + BluetoothService* bs = BluetoothService::Get(); + if (!bs) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + nsresult rv = bs->GetDefaultAdapterPathInternal(results); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return nullptr; + } + + return request.forget(); +} + +// static +already_AddRefed +BluetoothManager::Create(nsPIDOMWindow* aWindow) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aWindow); + + nsRefPtr manager = new BluetoothManager(aWindow); + return manager.forget(); +} + +// static +bool +BluetoothManager::CheckPermission(nsPIDOMWindow* aWindow) +{ + NS_ASSERTION(aWindow, "Null pointer!"); + + nsCOMPtr permMgr = + do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); + NS_ENSURE_TRUE(permMgr, false); + + uint32_t permission; + nsresult rv = + permMgr->TestPermissionFromWindow(aWindow, "bluetooth", + &permission); + NS_ENSURE_SUCCESS(rv, false); + + return permission == nsIPermissionManager::ALLOW_ACTION; +} + +void +BluetoothManager::Notify(const BluetoothSignal& aData) +{ + BT_LOGD("[M] %s: %s", __FUNCTION__, NS_ConvertUTF16toUTF8(aData.name()).get()); + + if (aData.name().EqualsLiteral("AdapterAdded")) { + DispatchTrustedEvent(NS_LITERAL_STRING("adapteradded")); + } else if (aData.name().EqualsLiteral("Enabled")) { + DispatchTrustedEvent(NS_LITERAL_STRING("enabled")); + } else if (aData.name().EqualsLiteral("Disabled")) { + DispatchTrustedEvent(NS_LITERAL_STRING("disabled")); + } else { +#ifdef DEBUG + nsCString warningMsg; + warningMsg.AssignLiteral("Not handling manager signal: "); + warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name())); + BT_WARNING(warningMsg.get()); +#endif + } +} + +bool +BluetoothManager::IsConnected(uint16_t aProfileId, ErrorResult& aRv) +{ + BluetoothService* bs = BluetoothService::Get(); + if (!bs) { + aRv.Throw(NS_ERROR_FAILURE); + return false; + } + + return bs->IsConnected(aProfileId); +} + +JSObject* +BluetoothManager::WrapObject(JSContext* aCx) +{ + return BluetoothManagerBinding::Wrap(aCx, this); +}