From 36b2354fd4c113ea61126cac30cd49a1973eabda Mon Sep 17 00:00:00 2001 From: roytam1 Date: Fri, 18 Mar 2022 12:44:46 +0800 Subject: [PATCH] import changes from `dev' branch of rmottola/Arctic-Fox: - Bug 1186307 - StructuredCloneHelper in workers.postMessage(), r=smaug (0d3c817afa) - Bug 1183824 - Remove NS_ENSURE_TRUE(mCallback, NS_ERROR_NOT_INITIALIZED) warning from nsFrameMessageManager::DispatchAsyncMessageInternal. r=smaug (64dfd50f7f) - Bug 1167189: Use a size annotation on the OOM abort. r=bholley (5e7fb331a0) - missing crash reporter (47f183fab4) - Bug 1137151: Marked destructor of |nsClipboard| as protected, r=mwu (5655bf8862) - Bug 1194497 - Convert a few remaining PRUnichar to char16_t. r=roc (1554ffcec2) - Bug 952456 - Part 1: Implement gonk/nsClipboard for rich text and raw image. r=fabrice (419381f7af) - Bug 1198795 - ipc/StructuredCloneUtils should be merged with StructuredCloneHelper, r=smaug (02183262bd) - Bug 1201806 - part 1 - Remove OwningSerializedStructuredCloneBuffer and use StructuredCloneIPCHelper everywhere in IPC code, r=smaug (6dc69151b4) - Bug 1201806 - part 2 - nsStructuredCloneContainer should use StructuredCloneIPCHelper, r=smaug (b6ebaa8e95) - Bug 1202028 - Implement range based for loops for SavedFrame stacks. r=terrence (57c198910c) - missing bit of Bug 1106264 (fa67f8ab56) - Bug 1168806: Configurable I/O thread for socket IPC classes, r=kmachulis (213a8fb2b9) - Bug 1159209: Remove template parameters from |DataSocketIO|, r=kmachulis (0d658c5cf8) - Bug 1168806: Configurable consumer thread for socket IPC classes, r=kmachulis (ee054dd6b0) - Bug 1167207: Add |BluetoothDaemonConnectionConsumer|, r=shuang (b8b89290df) - Bug 1154281: Remove |UnixSocketConsumer| and its helpers, r=kmachulis (d40430b10f) - Bug 1166638: Add |StreamSocketConsumer|, r=kmachulis (59b5c1abf3) - Bug 1166638: Add |ListenSocketConsumer|, r=kmachulis (d119bcaa2a) - Bug 1168806: Use 'consumer thread' in socket interface, r=kmachulis (65d232d21c) - Bug 1170466: Inherit |ConnectionOrientedSocketIO| from |UnixSocketWatcher|, r=kmachulis (b91d0c624a) - Bug 1170466: Share socket I/O methods in |ConnectionOrientedSocketIO|, r=kmachulis (108fb6696e) - Bug 1170466: Implement accept and connect in |ConnectionOrientedSocketIO|, r=kmachulis (590b3b4617) - Bug 1172479: Replace |nsIThread| by |MessageLoop| in socket I/O code, r=kmachulis (618073dcef) - Bug 1203426 - Rename StructuredCloneIPCHelper to StructuredCloneData, r=smaug (dc31124113) - Bug 1167392 - Change nsFrameMessageManager::mParentManager to a smart pointer. r=ehsan (98d60c0398) - Bug 1186843 - Always cache delayed scripts in message manager (b0ab501959) - Bug 1189550 - In parent process, cpmm.initialProcessData should be same as ppmm.initialProcessData (r=smaug) (7a8ab62432) - Bug 1196057 - Use channel->Open2() in dom/base/nsFrameMessageManager.cpp (r=sicking) (a032d483d6) - missing parts of Bug 1132072 - Tab switch refactoring (r=mconley) (e6fbbb722a) - Bug 1175736 - Implement the iframe referrer attribute. r=ckerschb, r=bz (a5fc4e683b) - Bug 1171017: Rename |BluetoothDaemonConnectionConsumer| to |DaemonSocketConsumer|, r=shuang (0af5957609) - Bug 1170993: Manage socket buffers in sub-classes of |UnixSocketBuffer|, r=kmachulis (960de8be45) - Bug 1171017: Rename |BluetoothDaemonPDUConsumer| to |DaemonSocketIOConsumer|, r=shuang (eea1681ab8) - Bug 1171100 - Fix incorrect logic of handling Bluetooth Gatt Responses in daemon backend. r=tzimmermann (c385364d1e) - Bug 1171866 - Remove ReversedUuidToString; f=tzimmermann, r=jocelyn (9b58176c39) - Bug 1171017: Rename |BluetoothSocketPDU| to |DaemonSocketPDU|, r=shuang (ce1bbd9d4a) - Bug 1171017: Rename |BluetoothDaemonConnectionIO| to |DaemonSocketIO|, r=shuang (00f2a38220) - Bug 1171017: Rename |BluetoothDaemonConnection| to |DaemonSocket|, r=shuang (b3c3522719) - Bug 1171017: Move classes from ipc/bluetooth to ipc/hal, r=shuang (047714aee4) - Bug 1171994: Add |RilSocket| and |RilSocketConsumer|, r=htsai (276211bbb7) - Bug 1171994: Forward received RIL socket I/O via |WorkerCrossThreadDispatcher|, r=htsai (7825d1c837) - Bug 1185478: Add leak checks to socket I/O classes (40e2c01ce4) - Bug 1185478: Remove strong references from socket I/O class to socket classes (6fa94f34ff) - Bug 1163912: Set |Type| property of BluetoothDevice a initial value during LeScan; f=elin, r=jocelyn (bda66689ed) - Bug 1166215 - Cast 'BluetoothTypeOfDevice' to uint32_t before the BT signal is distributed to BluetoothAdapter. r=joliu (d38ad4e55f) - Bug 1170086 - Fix the parameter type of DispatchReplyError() in StartLeScan result handler. r=joliu (a24e23e02f) - Bug 1161956 - Fix crashes while using GATT client functions. r=jocelyn (cebfb8c700) - Bug 1171868 - Remove GeneratePathFromGattId(aId, aPath, aUuidStr); r=jocelyn (0eac291b3c) - Bug 1161945 - Fix empty characteristics and descriptors after searching services. f=elin, r=jocelyn (a0d816fee4) - Bug 1164387 - Use |btgatt_client_interface_t.get_device_type| to get the device type. r=jocelyn (c7b5c97a00) - Bug 1173139 - Reorder global creation on workers, r=khuey. (acb79ae54e) - Bug 1170071 - Part 1: Revise BluetoothGattInterface, result handler, and interface helper for daemon support of gatt server. r=shuang (0ad0c9244e) - Bug 1170071 - Part 2: Add helpers for Bluetooth daemon GATT server support. r=shuang (46a4062579) - Bug 1170071 - Part 3: Add gatt server support to GATT module for Bluetooth daemon. r=shuang (71d80aabea) - Bug 1170071 - Part 4: Add Gatt server interfaces for Bluetooth daemon. r=shuang (a556aaf048) - Bug 1187230: Convert Bluetooth to use daemon runnables, r=shuang (9be6501225) - Bug 1204382: Add #include for nsIInputStream.h to MediaParent.cpp, to fix a build error in --disable-webrtc builds. r=jib (8b20e934) --- docshell/test/browser/head.js | 13 +- dom/base/PostMessageEvent.cpp | 8 +- dom/base/StructuredCloneHelper.cpp | 494 +++++- dom/base/StructuredCloneHelper.h | 87 +- dom/base/StructuredCloneTags.h | 2 + dom/base/nsFrameLoader.cpp | 28 +- dom/base/nsFrameLoader.h | 7 +- dom/base/nsFrameMessageManager.cpp | 204 ++- dom/base/nsFrameMessageManager.h | 49 +- dom/base/nsInProcessTabChildGlobal.cpp | 13 +- dom/base/nsInProcessTabChildGlobal.h | 8 +- dom/base/nsStructuredCloneContainer.cpp | 89 +- dom/base/nsStructuredCloneContainer.h | 14 +- dom/base/test/mochitest.ini | 1 + dom/base/test/test_postMessages.html | 143 +- dom/base/test/worker_postMessages.js | 33 + dom/bluetooth/BluetoothInterface.cpp | 6 + dom/bluetooth/BluetoothInterface.h | 13 +- dom/bluetooth/BluetoothInterfaceHelpers.h | 179 ++ dom/bluetooth/BluetoothUtils.cpp | 29 +- dom/bluetooth/BluetoothUtils.h | 25 - .../BluetoothDaemonA2dpInterface.cpp | 52 +- .../bluedroid/BluetoothDaemonA2dpInterface.h | 70 +- .../BluetoothDaemonAvrcpInterface.cpp | 154 +- .../bluedroid/BluetoothDaemonAvrcpInterface.h | 172 +- .../bluedroid/BluetoothDaemonConnector.cpp | 9 +- .../BluetoothDaemonGattInterface.cpp | 1543 +++++++++++++++-- .../bluedroid/BluetoothDaemonGattInterface.h | 592 +++++-- .../BluetoothDaemonHandsfreeInterface.cpp | 198 +-- .../BluetoothDaemonHandsfreeInterface.h | 240 ++- .../bluedroid/BluetoothDaemonHelpers.cpp | 165 +- .../bluedroid/BluetoothDaemonHelpers.h | 365 ++-- .../bluedroid/BluetoothDaemonInterface.cpp | 425 +++-- .../bluedroid/BluetoothDaemonInterface.h | 12 +- .../BluetoothDaemonSocketInterface.cpp | 34 +- .../BluetoothDaemonSocketInterface.h | 38 +- .../bluedroid/BluetoothGattHALInterface.cpp | 59 +- .../bluedroid/BluetoothGattManager.cpp | 182 +- .../bluedroid/BluetoothGattManager.h | 1 + .../bluedroid/BluetoothHALHelpers.cpp | 24 +- dom/bluetooth/bluedroid/BluetoothHALHelpers.h | 49 +- dom/bluetooth/bluedroid/BluetoothSocket.cpp | 211 ++- dom/bluetooth/bluedroid/BluetoothSocket.h | 21 +- dom/bluetooth/bluetooth2/BluetoothGatt.cpp | 77 + dom/bluetooth/bluetooth2/BluetoothGatt.h | 44 + .../BluetoothGattCharacteristic.cpp | 24 +- .../bluetooth2/BluetoothGattCharacteristic.h | 7 +- .../bluetooth2/BluetoothGattDescriptor.cpp | 7 +- .../bluetooth2/BluetoothGattService.cpp | 87 +- .../bluetooth2/BluetoothGattService.h | 35 +- dom/bluetooth/bluez/BluetoothSocket.cpp | 191 +- dom/bluetooth/bluez/BluetoothSocket.h | 32 +- .../bluez/BluetoothUnixSocketConnector.cpp | 9 +- dom/broadcastchannel/BroadcastChannel.cpp | 11 +- .../BroadcastChannelChild.cpp | 15 +- dom/canvas/ImageBitmap.cpp | 2 +- dom/fetch/ChannelInfo.cpp | 4 +- dom/html/HTMLIFrameElement.h | 9 + dom/ipc/ContentBridgeChild.cpp | 1 - dom/ipc/ContentBridgeParent.cpp | 2 +- dom/ipc/ContentBridgeParent.h | 3 +- dom/ipc/ContentChild.cpp | 15 +- dom/ipc/ContentParent.cpp | 21 +- dom/ipc/ContentParent.h | 9 +- dom/ipc/PBrowser.ipdl | 6 +- dom/ipc/PContent.ipdl | 8 +- dom/ipc/PContentBridge.ipdl | 4 +- dom/ipc/StructuredCloneData.cpp | 146 ++ dom/ipc/StructuredCloneData.h | 101 ++ dom/ipc/StructuredCloneUtils.cpp | 140 -- dom/ipc/StructuredCloneUtils.h | 55 - dom/ipc/TabChild.cpp | 26 +- dom/ipc/TabChild.h | 12 +- dom/ipc/TabParent.cpp | 30 +- dom/ipc/TabParent.h | 14 +- dom/ipc/moz.build | 4 +- dom/ipc/nsIContentChild.cpp | 8 +- dom/ipc/nsIContentParent.cpp | 24 +- dom/ipc/nsIContentParent.h | 6 +- dom/media/systemservices/MediaParent.cpp | 3 +- dom/messagechannel/MessagePort.cpp | 5 +- .../SharedMessagePortMessage.cpp | 8 - dom/messagechannel/SharedMessagePortMessage.h | 3 +- dom/promise/Promise.cpp | 1 + dom/push/PushManager.cpp | 1 + dom/system/gonk/SystemWorkerManager.h | 2 +- dom/webidl/HTMLIFrameElement.webidl | 2 + dom/workers/DataStore.cpp | 6 +- dom/workers/ScriptLoader.cpp | 33 +- dom/workers/ServiceWorkerClient.cpp | 92 +- dom/workers/ServiceWorkerManager.cpp | 1 + dom/workers/WorkerPrivate.cpp | 690 +------- dom/workers/WorkerPrivate.h | 18 +- dom/workers/WorkerScope.cpp | 14 + dom/workers/WorkerStructuredClone.h | 63 - dom/workers/XMLHttpRequest.cpp | 367 ++-- dom/workers/XMLHttpRequest.h | 7 +- gfx/thebes/gfxTextRun.cpp | 2 +- ipc/bluetooth/BluetoothDaemonConnection.cpp | 533 ------ ipc/bluetooth/BluetoothDaemonConnection.h | 151 -- ipc/glue/IPCMessageUtils.h | 89 +- ipc/hal/DaemonSocket.cpp | 262 +++ ipc/hal/DaemonSocket.h | 63 + ipc/hal/DaemonSocketConsumer.cpp | 33 + ipc/hal/DaemonSocketConsumer.h | 68 + ipc/hal/DaemonSocketPDU.cpp | 195 +++ ipc/hal/DaemonSocketPDU.h | 91 + ipc/{bluetooth => hal}/moz.build | 10 +- ipc/ipdl/ipdl/lower.py | 2 +- ipc/keystore/KeyStoreConnector.cpp | 9 +- ipc/moz.build | 5 +- ipc/nfc/NfcConnector.cpp | 9 +- ipc/ril/RilConnector.cpp | 9 +- ipc/ril/RilSocket.cpp | 442 +++++ ipc/ril/RilSocket.h | 110 ++ ipc/ril/RilSocketConsumer.cpp | 20 + ipc/ril/RilSocketConsumer.h | 64 + ipc/ril/moz.build | 6 +- ipc/unixsocket/ConnectionOrientedSocket.cpp | 187 +- ipc/unixsocket/ConnectionOrientedSocket.h | 84 +- ipc/unixsocket/DataSocket.cpp | 98 +- ipc/unixsocket/DataSocket.h | 73 +- ipc/unixsocket/ListenSocket.cpp | 117 +- ipc/unixsocket/ListenSocket.h | 40 +- ipc/unixsocket/ListenSocketConsumer.cpp | 20 + ipc/unixsocket/ListenSocketConsumer.h | 46 + ipc/unixsocket/SocketBase.cpp | 226 ++- ipc/unixsocket/SocketBase.h | 149 +- ipc/unixsocket/StreamSocket.cpp | 386 ++--- ipc/unixsocket/StreamSocket.h | 27 +- ipc/unixsocket/StreamSocketConsumer.cpp | 20 + ipc/unixsocket/StreamSocketConsumer.h | 60 + ipc/unixsocket/UnixSocket.cpp | 667 ------- ipc/unixsocket/UnixSocket.h | 95 - ipc/unixsocket/UnixSocketConnector.cpp | 9 +- ipc/unixsocket/moz.build | 6 +- js/src/jsapi-tests/testSavedStacks.cpp | 50 +- js/src/vm/SavedFrame.h | 104 +- js/src/vm/SavedStacks.cpp | 2 +- layout/mathml/nsMathMLChar.h | 2 +- .../streamconv/converters/nsIndexedToHTML.cpp | 2 +- testing/mochitest/browser-test.js | 1 + widget/gonk/GonkClipboardData.cpp | 75 + widget/gonk/GonkClipboardData.h | 49 + widget/gonk/moz.build | 2 + widget/gonk/nsClipboard.cpp | 254 ++- widget/gonk/nsClipboard.h | 12 +- widget/windows/nsWindow.cpp | 2 +- 148 files changed, 8207 insertions(+), 5397 deletions(-) create mode 100644 dom/base/test/worker_postMessages.js create mode 100644 dom/ipc/StructuredCloneData.cpp create mode 100644 dom/ipc/StructuredCloneData.h delete mode 100644 dom/ipc/StructuredCloneUtils.cpp delete mode 100644 dom/ipc/StructuredCloneUtils.h delete mode 100644 dom/workers/WorkerStructuredClone.h delete mode 100644 ipc/bluetooth/BluetoothDaemonConnection.cpp delete mode 100644 ipc/bluetooth/BluetoothDaemonConnection.h create mode 100644 ipc/hal/DaemonSocket.cpp create mode 100644 ipc/hal/DaemonSocket.h create mode 100644 ipc/hal/DaemonSocketConsumer.cpp create mode 100644 ipc/hal/DaemonSocketConsumer.h create mode 100644 ipc/hal/DaemonSocketPDU.cpp create mode 100644 ipc/hal/DaemonSocketPDU.h rename ipc/{bluetooth => hal}/moz.build (70%) create mode 100644 ipc/ril/RilSocket.cpp create mode 100644 ipc/ril/RilSocket.h create mode 100644 ipc/ril/RilSocketConsumer.cpp create mode 100644 ipc/ril/RilSocketConsumer.h create mode 100644 ipc/unixsocket/ListenSocketConsumer.cpp create mode 100644 ipc/unixsocket/ListenSocketConsumer.h create mode 100644 ipc/unixsocket/StreamSocketConsumer.cpp create mode 100644 ipc/unixsocket/StreamSocketConsumer.h delete mode 100644 ipc/unixsocket/UnixSocket.cpp delete mode 100644 ipc/unixsocket/UnixSocket.h create mode 100644 widget/gonk/GonkClipboardData.cpp create mode 100644 widget/gonk/GonkClipboardData.h diff --git a/docshell/test/browser/head.js b/docshell/test/browser/head.js index 7a22f229ed..29df446d6c 100644 --- a/docshell/test/browser/head.js +++ b/docshell/test/browser/head.js @@ -39,9 +39,16 @@ function makeTimelineTest(frameScriptName, url) { /* Open a URL for a timeline test. */ function timelineTestOpenUrl(url) { - return new Promise(function(resolve, reject) { - window.focus(); + window.focus(); + let tabSwitchPromise = new Promise((resolve, reject) => { + window.gBrowser.addEventListener("TabSwitchDone", function listener() { + window.gBrowser.removeEventListener("TabSwitchDone", listener); + resolve(); + }); + }); + + let loadPromise = new Promise(function(resolve, reject) { let tab = window.gBrowser.selectedTab = window.gBrowser.addTab(url); let linkedBrowser = tab.linkedBrowser; @@ -50,4 +57,6 @@ function timelineTestOpenUrl(url) { resolve(tab); }, true); }); + + return Promise.all([tabSwitchPromise, loadPromise]).then(([_, tab]) => tab); } diff --git a/dom/base/PostMessageEvent.cpp b/dom/base/PostMessageEvent.cpp index 90f5452574..029516a9da 100644 --- a/dom/base/PostMessageEvent.cpp +++ b/dom/base/PostMessageEvent.cpp @@ -28,7 +28,8 @@ PostMessageEvent::PostMessageEvent(nsGlobalWindow* aSource, nsGlobalWindow* aTargetWindow, nsIPrincipal* aProvidedPrincipal, bool aTrustedCaller) -: StructuredCloneHelper(CloningSupported, TransferringSupported), +: StructuredCloneHelper(CloningSupported, TransferringSupported, + SameProcessSameThread), mSource(aSource), mCallerOrigin(aCallerOrigin), mTargetWindow(aTargetWindow), @@ -113,8 +114,11 @@ PostMessageEvent::Run() false /*cancelable */, messageData, mCallerOrigin, EmptyString(), mSource); + nsTArray> ports; + TakeTransferredPorts(ports); + event->SetPorts(new MessagePortList(static_cast(event.get()), - GetTransferredPorts())); + ports)); // We can't simply call dispatchEvent on the window because doing so ends // up flipping the trusted bit on the event, and we don't want that to diff --git a/dom/base/StructuredCloneHelper.cpp b/dom/base/StructuredCloneHelper.cpp index 1ba82f186d..00fc35fb89 100644 --- a/dom/base/StructuredCloneHelper.cpp +++ b/dom/base/StructuredCloneHelper.cpp @@ -14,11 +14,24 @@ #include "mozilla/dom/FileListBinding.h" #include "mozilla/dom/ImageBitmap.h" #include "mozilla/dom/ImageBitmapBinding.h" +#include "mozilla/dom/ImageData.h" +#include "mozilla/dom/ImageDataBinding.h" +#include "mozilla/dom/ipc/BlobChild.h" +#include "mozilla/dom/StructuredClone.h" #include "mozilla/dom/MessagePort.h" #include "mozilla/dom/MessagePortBinding.h" #include "mozilla/dom/PMessagePort.h" #include "mozilla/dom/StructuredCloneTags.h" #include "mozilla/dom/ToJSValue.h" +#include "mozilla/dom/WebCryptoCommon.h" +#include "mozilla/ipc/BackgroundChild.h" +#include "mozilla/ipc/BackgroundUtils.h" +#include "MultipartBlobImpl.h" +#include "nsFormData.h" +#include "nsIRemoteBlob.h" +#include "nsQueryObject.h" + +using namespace mozilla::ipc; namespace mozilla { namespace dom { @@ -142,11 +155,7 @@ bool StructuredCloneHelperInternal::Write(JSContext* aCx, JS::Handle aValue) { - MOZ_ASSERT(!mBuffer, "Double Write is not allowed"); - MOZ_ASSERT(!mShutdownCalled, "This method cannot be called after Shutdown."); - - mBuffer = new JSAutoStructuredCloneBuffer(&gCallbacks, this); - return mBuffer->write(aCx, aValue, &gCallbacks, this); + return Write(aCx, aValue, JS::UndefinedHandleValue); } bool @@ -158,7 +167,13 @@ StructuredCloneHelperInternal::Write(JSContext* aCx, MOZ_ASSERT(!mShutdownCalled, "This method cannot be called after Shutdown."); mBuffer = new JSAutoStructuredCloneBuffer(&gCallbacks, this); - return mBuffer->write(aCx, aValue, aTransfer, &gCallbacks, this); + + if (!mBuffer->write(aCx, aValue, aTransfer, &gCallbacks, this)) { + mBuffer = nullptr; + return false; + } + + return true; } bool @@ -208,15 +223,21 @@ StructuredCloneHelperInternal::FreeTransferCallback(uint32_t aTag, // StructuredCloneHelper class StructuredCloneHelper::StructuredCloneHelper(CloningSupport aSupportsCloning, - TransferringSupport aSupportsTransferring) + TransferringSupport aSupportsTransferring, + ContextSupport aContext) : mSupportsCloning(aSupportsCloning == CloningSupported) , mSupportsTransferring(aSupportsTransferring == TransferringSupported) + , mContext(aContext) , mParent(nullptr) +#ifdef DEBUG + , mCreationThread(NS_GetCurrentThread()) +#endif {} StructuredCloneHelper::~StructuredCloneHelper() { Shutdown(); + MOZ_ASSERT(mTransferredPorts.IsEmpty()); } void @@ -233,8 +254,21 @@ StructuredCloneHelper::Write(JSContext* aCx, JS::Handle aTransfer, ErrorResult& aRv) { + MOZ_ASSERT_IF(mContext == SameProcessSameThread, + mCreationThread == NS_GetCurrentThread()); + if (!StructuredCloneHelperInternal::Write(aCx, aValue, aTransfer)) { aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); + return; + } + + if (mContext != SameProcessSameThread) { + for (uint32_t i = 0, len = mBlobImplArray.Length(); i < len; ++i) { + if (!mBlobImplArray[i]->MayBeClonedToOtherThreads()) { + aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); + return; + } + } } } @@ -244,6 +278,9 @@ StructuredCloneHelper::Read(nsISupports* aParent, JS::MutableHandle aValue, ErrorResult& aRv) { + MOZ_ASSERT_IF(mContext == SameProcessSameThread, + mCreationThread == NS_GetCurrentThread()); + mozilla::AutoRestore guard(mParent); mParent = aParent; @@ -280,6 +317,9 @@ StructuredCloneHelper::ReadFromBuffer(nsISupports* aParent, JS::MutableHandle aValue, ErrorResult& aRv) { + MOZ_ASSERT_IF(mContext == SameProcessSameThread, + mCreationThread == NS_GetCurrentThread()); + MOZ_ASSERT(!mBuffer, "ReadFromBuffer() must be called without a Write()."); MOZ_ASSERT(aBuffer); @@ -297,6 +337,9 @@ void StructuredCloneHelper::MoveBufferDataToArray(FallibleTArray& aArray, ErrorResult& aRv) { + MOZ_ASSERT_IF(mContext == SameProcessSameThread, + mCreationThread == NS_GetCurrentThread()); + MOZ_ASSERT(mBuffer, "MoveBuffer() cannot be called without a Write()."); if (NS_WARN_IF(!aArray.SetLength(BufferSize(), mozilla::fallible))) { @@ -324,6 +367,346 @@ StructuredCloneHelper::FreeBuffer(uint64_t* aBuffer, JS_ClearStructuredClone(aBuffer, aBufferLength, &gCallbacks, this, false); } +namespace { + +// Recursive! +already_AddRefed +EnsureBlobForBackgroundManager(BlobImpl* aBlobImpl, + PBackgroundChild* aManager = nullptr) +{ + MOZ_ASSERT(aBlobImpl); + + if (!aManager) { + aManager = BackgroundChild::GetForCurrentThread(); + MOZ_ASSERT(aManager); + } + + nsRefPtr blobImpl = aBlobImpl; + + const nsTArray>* subBlobImpls = + aBlobImpl->GetSubBlobImpls(); + + if (!subBlobImpls || !subBlobImpls->Length()) { + if (nsCOMPtr remoteBlob = do_QueryObject(blobImpl)) { + // Always make sure we have a blob from an actor we can use on this + // thread. + BlobChild* blobChild = BlobChild::GetOrCreate(aManager, blobImpl); + MOZ_ASSERT(blobChild); + + blobImpl = blobChild->GetBlobImpl(); + MOZ_ASSERT(blobImpl); + + DebugOnly isMutable; + MOZ_ASSERT(NS_SUCCEEDED(blobImpl->GetMutable(&isMutable))); + MOZ_ASSERT(!isMutable); + } else { + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(blobImpl->SetMutable(false))); + } + + return blobImpl.forget(); + } + + const uint32_t subBlobCount = subBlobImpls->Length(); + MOZ_ASSERT(subBlobCount); + + nsTArray> newSubBlobImpls; + newSubBlobImpls.SetLength(subBlobCount); + + bool newBlobImplNeeded = false; + + for (uint32_t index = 0; index < subBlobCount; index++) { + const nsRefPtr& subBlobImpl = subBlobImpls->ElementAt(index); + MOZ_ASSERT(subBlobImpl); + + nsRefPtr& newSubBlobImpl = newSubBlobImpls[index]; + + newSubBlobImpl = EnsureBlobForBackgroundManager(subBlobImpl, aManager); + MOZ_ASSERT(newSubBlobImpl); + + if (subBlobImpl != newSubBlobImpl) { + newBlobImplNeeded = true; + } + } + + if (newBlobImplNeeded) { + nsString contentType; + blobImpl->GetType(contentType); + + if (blobImpl->IsFile()) { + nsString name; + blobImpl->GetName(name); + + blobImpl = new MultipartBlobImpl(newSubBlobImpls, name, contentType); + } else { + blobImpl = new MultipartBlobImpl(newSubBlobImpls, contentType); + } + + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(blobImpl->SetMutable(false))); + } + + return blobImpl.forget(); +} + +JSObject* +ReadBlob(JSContext* aCx, + uint32_t aIndex, + StructuredCloneHelper* aHelper) +{ + MOZ_ASSERT(aHelper); + MOZ_ASSERT(aIndex < aHelper->BlobImpls().Length()); + nsRefPtr blobImpl = aHelper->BlobImpls()[aIndex]; + + blobImpl = EnsureBlobForBackgroundManager(blobImpl); + MOZ_ASSERT(blobImpl); + + // nsRefPtr needs to go out of scope before toObjectOrNull() is + // called because the static analysis thinks dereferencing XPCOM objects + // can GC (because in some cases it can!), and a return statement with a + // JSObject* type means that JSObject* is on the stack as a raw pointer + // while destructors are running. + JS::Rooted val(aCx); + { + nsRefPtr blob = Blob::Create(aHelper->ParentDuringRead(), blobImpl); + if (!ToJSValue(aCx, blob, &val)) { + return nullptr; + } + } + + return &val.toObject(); +} + +bool +WriteBlob(JSStructuredCloneWriter* aWriter, + Blob* aBlob, + StructuredCloneHelper* aHelper) +{ + MOZ_ASSERT(aWriter); + MOZ_ASSERT(aBlob); + MOZ_ASSERT(aHelper); + + nsRefPtr blobImpl = EnsureBlobForBackgroundManager(aBlob->Impl()); + MOZ_ASSERT(blobImpl); + + // We store the position of the blobImpl in the array as index. + if (JS_WriteUint32Pair(aWriter, SCTAG_DOM_BLOB, + aHelper->BlobImpls().Length())) { + aHelper->BlobImpls().AppendElement(blobImpl); + return true; + } + + return false; +} + +// Read the WriteFileList for the format. +JSObject* +ReadFileList(JSContext* aCx, + JSStructuredCloneReader* aReader, + uint32_t aCount, + StructuredCloneHelper* aHelper) +{ + MOZ_ASSERT(aCx); + MOZ_ASSERT(aReader); + + JS::Rooted val(aCx); + { + nsRefPtr fileList = new FileList(aHelper->ParentDuringRead()); + + uint32_t tag, offset; + // Offset is the index of the blobImpl from which we can find the blobImpl + // for this FileList. + if (!JS_ReadUint32Pair(aReader, &tag, &offset)) { + return nullptr; + } + + MOZ_ASSERT(tag == 0); + + // |aCount| is the number of BlobImpls to use from the |offset|. + for (uint32_t i = 0; i < aCount; ++i) { + uint32_t index = offset + i; + MOZ_ASSERT(index < aHelper->BlobImpls().Length()); + + nsRefPtr blobImpl = aHelper->BlobImpls()[index]; + MOZ_ASSERT(blobImpl->IsFile()); + + nsRefPtr file = File::Create(aHelper->ParentDuringRead(), blobImpl); + if (!fileList->Append(file)) { + return nullptr; + } + } + + if (!ToJSValue(aCx, fileList, &val)) { + return nullptr; + } + } + + return &val.toObject(); +} + +// The format of the FileList serialization is: +// - pair of ints: SCTAG_DOM_FILELIST, Length of the FileList +// - pair of ints: 0, The offset of the BlobImpl array +bool +WriteFileList(JSStructuredCloneWriter* aWriter, + FileList* aFileList, + StructuredCloneHelper* aHelper) +{ + MOZ_ASSERT(aWriter); + MOZ_ASSERT(aFileList); + MOZ_ASSERT(aHelper); + + // A FileList is serialized writing the X number of elements and the offset + // from mBlobImplArray. The Read will take X elements from mBlobImplArray + // starting from the offset. + if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_FILELIST, + aFileList->Length()) || + !JS_WriteUint32Pair(aWriter, 0, + aHelper->BlobImpls().Length())) { + return false; + } + + for (uint32_t i = 0; i < aFileList->Length(); ++i) { + aHelper->BlobImpls().AppendElement(aFileList->Item(i)->Impl()); + } + + return true; +} + +// Read the WriteFormData for the format. +JSObject* +ReadFormData(JSContext* aCx, + JSStructuredCloneReader* aReader, + uint32_t aCount, + StructuredCloneHelper* aHelper) +{ + MOZ_ASSERT(aCx); + MOZ_ASSERT(aReader); + MOZ_ASSERT(aHelper); + + // See the serialization of the FormData for the format. + JS::Rooted val(aCx); + { + nsRefPtr formData = + new nsFormData(aHelper->ParentDuringRead()); + + Optional thirdArg; + for (uint32_t i = 0; i < aCount; ++i) { + nsAutoString name; + if (!ReadString(aReader, name)) { + return nullptr; + } + + uint32_t tag, indexOrLengthOfString; + if (!JS_ReadUint32Pair(aReader, &tag, &indexOrLengthOfString)) { + return nullptr; + } + + if (tag == SCTAG_DOM_BLOB) { + MOZ_ASSERT(indexOrLengthOfString < aHelper->BlobImpls().Length()); + + nsRefPtr blobImpl = + aHelper->BlobImpls()[indexOrLengthOfString]; + MOZ_ASSERT(blobImpl->IsFile()); + + nsRefPtr file = + File::Create(aHelper->ParentDuringRead(), blobImpl); + MOZ_ASSERT(file); + + formData->Append(name, *file, thirdArg); + } else { + MOZ_ASSERT(tag == 0); + + nsAutoString value; + value.SetLength(indexOrLengthOfString); + size_t charSize = sizeof(nsString::char_type); + if (!JS_ReadBytes(aReader, (void*) value.BeginWriting(), + indexOrLengthOfString * charSize)) { + return nullptr; + } + + formData->Append(name, value); + } + } + + if (!ToJSValue(aCx, formData, &val)) { + return nullptr; + } + } + + return &val.toObject(); +} + +// The format of the FormData serialization is: +// - pair of ints: SCTAG_DOM_FORMDATA, Length of the FormData elements +// - for each Element element: +// - name string +// - if it's a blob: +// - pair of ints: SCTAG_DOM_BLOB, index of the BlobImpl in the array +// mBlobImplArray. +// - else: +// - pair of ints: 0, string length +// - value string +bool +WriteFormData(JSStructuredCloneWriter* aWriter, + nsFormData* aFormData, + StructuredCloneHelper* aHelper) +{ + MOZ_ASSERT(aWriter); + MOZ_ASSERT(aFormData); + MOZ_ASSERT(aHelper); + + if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_FORMDATA, + aFormData->Length())) { + return false; + } + + class MOZ_STACK_CLASS Closure final + { + JSStructuredCloneWriter* mWriter; + StructuredCloneHelper* mHelper; + + public: + Closure(JSStructuredCloneWriter* aWriter, + StructuredCloneHelper* aHelper) + : mWriter(aWriter), + mHelper(aHelper) + { } + + static bool + Write(const nsString& aName, bool isFile, const nsString& aValue, + File* aFile, void* aClosure) + { + Closure* closure = static_cast(aClosure); + if (!WriteString(closure->mWriter, aName)) { + return false; + } + + if (isFile) { + BlobImpl* blobImpl = aFile->Impl(); + if (!JS_WriteUint32Pair(closure->mWriter, SCTAG_DOM_BLOB, + closure->mHelper->BlobImpls().Length())) { + return false; + } + + closure->mHelper->BlobImpls().AppendElement(blobImpl); + return true; + } + + size_t charSize = sizeof(nsString::char_type); + if (!JS_WriteUint32Pair(closure->mWriter, 0, aValue.Length()) || + !JS_WriteBytes(closure->mWriter, aValue.get(), + aValue.Length() * charSize)) { + return false; + } + + return true; + } + }; + Closure closure(aWriter, aHelper); + return aFormData->ForEach(Closure::Write, &closure); +} + +} // anonymous namespace + JSObject* StructuredCloneHelper::ReadCallback(JSContext* aCx, JSStructuredCloneReader* aReader, @@ -333,59 +716,25 @@ StructuredCloneHelper::ReadCallback(JSContext* aCx, MOZ_ASSERT(mSupportsCloning); if (aTag == SCTAG_DOM_BLOB) { - MOZ_ASSERT(aIndex < mBlobImplArray.Length()); - nsRefPtr blobImpl = mBlobImplArray[aIndex]; - - // nsRefPtr needs to go out of scope before toObjectOrNull() is - // called because the static analysis thinks dereferencing XPCOM objects - // can GC (because in some cases it can!), and a return statement with a - // JSObject* type means that JSObject* is on the stack as a raw pointer - // while destructors are running. - JS::Rooted val(aCx); - { - nsRefPtr blob = Blob::Create(mParent, blobImpl); - if (!ToJSValue(aCx, blob, &val)) { - return nullptr; - } - } - - return &val.toObject(); + return ReadBlob(aCx, aIndex, this); } if (aTag == SCTAG_DOM_FILELIST) { - JS::Rooted val(aCx); - { - nsRefPtr fileList = new FileList(mParent); + return ReadFileList(aCx, aReader, aIndex, this); + } - // |aIndex| is the number of BlobImpls to use from |offset|. - uint32_t tag, offset; - if (!JS_ReadUint32Pair(aReader, &tag, &offset)) { - return nullptr; - } - MOZ_ASSERT(tag == 0); + if (aTag == SCTAG_DOM_IMAGEDATA) { + return ReadStructuredCloneImageData(aCx, aReader); + } - for (uint32_t i = 0; i < aIndex; ++i) { - uint32_t index = offset + i; - MOZ_ASSERT(index < mBlobImplArray.Length()); - - nsRefPtr blobImpl = mBlobImplArray[index]; - MOZ_ASSERT(blobImpl->IsFile()); - - nsRefPtr file = File::Create(mParent, blobImpl); - if (!fileList->Append(file)) { - return nullptr; - } - } - - if (!ToJSValue(aCx, fileList, &val)) { - return nullptr; - } - } - - return &val.toObject(); + if (aTag == SCTAG_DOM_FORMDATA) { + return ReadFormData(aCx, aReader, aIndex, this); } if (aTag == SCTAG_DOM_IMAGEBITMAP) { + MOZ_ASSERT(mContext == SameProcessSameThread || + mContext == SameProcessDifferentThread); + // Get the current global object. // This can be null. nsCOMPtr parent = do_QueryInterface(mParent); @@ -410,40 +759,37 @@ StructuredCloneHelper::WriteCallback(JSContext* aCx, { Blob* blob = nullptr; if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, aObj, blob))) { - BlobImpl* blobImpl = blob->Impl(); - if (JS_WriteUint32Pair(aWriter, SCTAG_DOM_BLOB, - mBlobImplArray.Length())) { - mBlobImplArray.AppendElement(blobImpl); - return true; - } - - return false; + return WriteBlob(aWriter, blob, this); } } + // See if this is a FileList object. { FileList* fileList = nullptr; if (NS_SUCCEEDED(UNWRAP_OBJECT(FileList, aObj, fileList))) { - // A FileList is serialized writing the X number of elements and the offset - // from mBlobImplArray. The Read will take X elements from mBlobImplArray - // starting from the offset. - if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_FILELIST, - fileList->Length()) || - !JS_WriteUint32Pair(aWriter, 0, - mBlobImplArray.Length())) { - return false; - } + return WriteFileList(aWriter, fileList, this); + } + } - for (uint32_t i = 0; i < fileList->Length(); ++i) { - mBlobImplArray.AppendElement(fileList->Item(i)->Impl()); - } + // See if this is a ImageData object. + { + ImageData* imageData = nullptr; + if (NS_SUCCEEDED(UNWRAP_OBJECT(ImageData, aObj, imageData))) { + return WriteStructuredCloneImageData(aCx, aWriter, imageData); + } + } - return true; + // See if this is a FormData object. + { + nsFormData* formData = nullptr; + if (NS_SUCCEEDED(UNWRAP_OBJECT(FormData, aObj, formData))) { + return WriteFormData(aWriter, formData, this); } } // See if this is an ImageBitmap object. - { + if (mContext == SameProcessSameThread || + mContext == SameProcessDifferentThread) { ImageBitmap* imageBitmap = nullptr; if (NS_SUCCEEDED(UNWRAP_OBJECT(ImageBitmap, aObj, imageBitmap))) { return ImageBitmap::WriteStructuredClone(aWriter, diff --git a/dom/base/StructuredCloneHelper.h b/dom/base/StructuredCloneHelper.h index 0c72104e66..49518f6dfa 100644 --- a/dom/base/StructuredCloneHelper.h +++ b/dom/base/StructuredCloneHelper.h @@ -11,6 +11,10 @@ #include "nsISupports.h" #include "nsTArray.h" +#ifdef DEBUG +#include "nsIThread.h" +#endif + namespace mozilla { class ErrorResult; namespace layers { @@ -81,6 +85,11 @@ public: bool Read(JSContext* aCx, JS::MutableHandle aValue); + bool HasBeenWritten() const + { + return !!mBuffer; + } + uint64_t* BufferData() const { MOZ_ASSERT(mBuffer, "Write() has never been called."); @@ -120,12 +129,24 @@ public: TransferringNotSupported }; + enum ContextSupport + { + SameProcessSameThread, + SameProcessDifferentThread, + DifferentProcess + }; + // If cloning is supported, this object will clone objects such as Blobs, // FileList, ImageData, etc. // If transferring is supported, we will transfer MessagePorts and in the // future other transferrable objects. + // The ContextSupport is useful to know where the cloned/transferred data can + // be read and written. Additional checks about the nature of the objects + // will be done based on this context value because not all the objects can + // be sent between threads or processes. explicit StructuredCloneHelper(CloningSupport aSupportsCloning, - TransferringSupport aSupportsTransferring); + TransferringSupport aSupportsTransferring, + ContextSupport aContextSupport); virtual ~StructuredCloneHelper(); // Normally you should just use Write() and Read(). @@ -150,28 +171,6 @@ public: void MoveBufferDataToArray(FallibleTArray& aArray, ErrorResult& aRv); - // If you receive a buffer from IPC, you can use this method to retrieve a - // JS::Value. It can happen that you want to pre-populate the array of Blobs - // and/or the PortIdentifiers. - void ReadFromBuffer(nsISupports* aParent, - JSContext* aCx, - uint64_t* aBuffer, - size_t aBufferLength, - JS::MutableHandle aValue, - ErrorResult &aRv); - - void ReadFromBuffer(nsISupports* aParent, - JSContext* aCx, - uint64_t* aBuffer, - size_t aBufferLength, - uint32_t aAlgorithmVersion, - JS::MutableHandle aValue, - ErrorResult &aRv); - - // Use this method to free a buffer generated by MoveToBuffer(). - void FreeBuffer(uint64_t* aBuffer, - size_t aBufferLength); - bool HasClonedDOMObjects() const { return !mBlobImplArray.IsEmpty() || @@ -184,10 +183,19 @@ public: return mBlobImplArray; } - const nsTArray>& GetTransferredPorts() const + nsISupports* ParentDuringRead() const + { + return mParent; + } + + // This must be called if the transferring has ports generated by Read(). + // MessagePorts are not thread-safe and they must be retrieved in the thread + // where they are created. + void TakeTransferredPorts(nsTArray>& aPorts) { MOZ_ASSERT(mSupportsTransferring); - return mTransferredPorts; + MOZ_ASSERT(aPorts.IsEmpty()); + aPorts.SwapElements(mTransferredPorts); } nsTArray& PortIdentifiers() @@ -230,9 +238,32 @@ public: JS::TransferableOwnership aOwnership, void* aContent, uint64_t aExtraData) override; -private: +protected: + // If you receive a buffer from IPC, you can use this method to retrieve a + // JS::Value. It can happen that you want to pre-populate the array of Blobs + // and/or the PortIdentifiers. + void ReadFromBuffer(nsISupports* aParent, + JSContext* aCx, + uint64_t* aBuffer, + size_t aBufferLength, + JS::MutableHandle aValue, + ErrorResult &aRv); + + void ReadFromBuffer(nsISupports* aParent, + JSContext* aCx, + uint64_t* aBuffer, + size_t aBufferLength, + uint32_t aAlgorithmVersion, + JS::MutableHandle aValue, + ErrorResult &aRv); + + // Use this method to free a buffer generated by MoveToBuffer(). + void FreeBuffer(uint64_t* aBuffer, + size_t aBufferLength); + bool mSupportsCloning; bool mSupportsTransferring; + ContextSupport mContext; // Useful for the structured clone algorithm: @@ -256,6 +287,10 @@ private: // are able to reconnect the new transferred ports with the other // MessageChannel ports. nsTArray mPortIdentifiers; + +#ifdef DEBUG + nsCOMPtr mCreationThread; +#endif }; } // dom namespace diff --git a/dom/base/StructuredCloneTags.h b/dom/base/StructuredCloneTags.h index 545b9a10d9..fe6ccdf371 100644 --- a/dom/base/StructuredCloneTags.h +++ b/dom/base/StructuredCloneTags.h @@ -46,6 +46,8 @@ enum StructuredCloneTags { SCTAG_DOM_RTC_CERTIFICATE, + SCTAG_DOM_FORMDATA, + SCTAG_DOM_MAX }; diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp index c7145c6772..5623ebfbf0 100644 --- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -92,7 +92,7 @@ #include "nsSandboxFlags.h" #include "mozilla/layers/CompositorChild.h" -#include "mozilla/dom/StructuredCloneUtils.h" +#include "mozilla/dom/ipc/StructuredCloneData.h" #ifdef MOZ_XUL #include "nsXULPopupManager.h" @@ -374,7 +374,19 @@ nsFrameLoader::ReallyStartLoadingInternal() } } - loadInfo->SetReferrerPolicy(mOwnerContent->OwnerDoc()->GetReferrerPolicy()); + // get referrer policy for this iframe: + // first load document wide policy, then + // load iframe referrer attribute if enabled in preferences + // per element referrer overrules document wide referrer if enabled + net::ReferrerPolicy referrerPolicy = mOwnerContent->OwnerDoc()->GetReferrerPolicy(); + HTMLIFrameElement* iframe = HTMLIFrameElement::FromContent(mOwnerContent); + if (iframe) { + net::ReferrerPolicy iframeReferrerPolicy = iframe->GetReferrerPolicy(); + if (iframeReferrerPolicy != net::RP_Unset) { + referrerPolicy = iframeReferrerPolicy; + } + } + loadInfo->SetReferrerPolicy(referrerPolicy); // Default flags: int32_t flags = nsIWebNavigation::LOAD_FLAGS_NONE; @@ -2367,7 +2379,7 @@ public: nsAsyncMessageToChild(JSContext* aCx, nsFrameLoader* aFrameLoader, const nsAString& aMessage, - const StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) : nsSameProcessAsyncMessageBase(aCx, aMessage, aData, aCpows, aPrincipal) @@ -2394,7 +2406,7 @@ public: bool nsFrameLoader::DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, - const StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) { @@ -2744,6 +2756,10 @@ nsFrameLoader::RequestNotifyLayerTreeReady() return mRemoteBrowser->RequestNotifyLayerTreeReady() ? NS_OK : NS_ERROR_NOT_AVAILABLE; } + if (!mOwnerContent) { + return NS_ERROR_NOT_AVAILABLE; + } + nsRefPtr event = new AsyncEventDispatcher(mOwnerContent, NS_LITERAL_STRING("MozLayerTreeReady"), @@ -2760,6 +2776,10 @@ nsFrameLoader::RequestNotifyLayerTreeCleared() return mRemoteBrowser->RequestNotifyLayerTreeCleared() ? NS_OK : NS_ERROR_NOT_AVAILABLE; } + if (!mOwnerContent) { + return NS_ERROR_NOT_AVAILABLE; + } + nsRefPtr event = new AsyncEventDispatcher(mOwnerContent, NS_LITERAL_STRING("MozLayerTreeCleared"), diff --git a/dom/base/nsFrameLoader.h b/dom/base/nsFrameLoader.h index 39c393d68d..a46b3a78c5 100644 --- a/dom/base/nsFrameLoader.h +++ b/dom/base/nsFrameLoader.h @@ -41,9 +41,12 @@ namespace dom { class ContentParent; class PBrowserParent; class TabParent; -struct StructuredCloneData; } // namespace dom +namespace ipc { +class StructuredCloneData; +} // namespace ipc + namespace layout { class RenderFrameParent; } // namespace layout @@ -86,7 +89,7 @@ public: bool aRunInGlobalScope) override; virtual bool DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, - const mozilla::dom::StructuredCloneData& aData, + mozilla::dom::ipc::StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) override; virtual bool CheckPermission(const nsAString& aPermission) override; diff --git a/dom/base/nsFrameMessageManager.cpp b/dom/base/nsFrameMessageManager.cpp index 14c0588872..caebae40a4 100644 --- a/dom/base/nsFrameMessageManager.cpp +++ b/dom/base/nsFrameMessageManager.cpp @@ -37,9 +37,9 @@ #include "mozilla/dom/ProcessGlobal.h" #include "mozilla/dom/SameProcessMessageQueue.h" #include "mozilla/dom/ScriptSettings.h" -#include "mozilla/dom/StructuredCloneUtils.h" #include "mozilla/dom/ipc/BlobChild.h" #include "mozilla/dom/ipc/BlobParent.h" +#include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/dom/DOMStringList.h" #include "mozilla/jsipc/CrossProcessObjectWrappers.h" #include "nsPrintfCString.h" @@ -47,6 +47,10 @@ #include "nsQueryObject.h" #include +#ifdef MOZ_CRASHREPORTER +#include "nsExceptionHandler.h" +#endif + #ifdef ANDROID #include #endif @@ -137,6 +141,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameMessageManager) tmp->mListeners.EnumerateRead(CycleCollectorTraverseListeners, static_cast(&cb)); NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildManagers) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentManager) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END @@ -151,6 +156,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFrameMessageManager) Disconnect(false); } NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildManagers) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentManager) tmp->mInitialProcessData.setNull(); NS_IMPL_CYCLE_COLLECTION_UNLINK_END @@ -270,13 +276,14 @@ struct DataBlobs template static bool BuildClonedMessageData(typename BlobTraits::ConcreteContentManagerType* aManager, - const StructuredCloneData& aData, + StructuredCloneData& aData, ClonedMessageData& aClonedData) { SerializedStructuredCloneBuffer& buffer = aClonedData.data(); - buffer.data = aData.mData; - buffer.dataLength = aData.mDataLength; - const nsTArray>& blobImpls = aData.mClosure.mBlobImpls; + buffer.data = aData.Data(); + buffer.dataLength = aData.DataLength(); + const nsTArray>& blobImpls = aData.BlobImpls(); + if (!blobImpls.IsEmpty()) { typedef typename BlobTraits::ProtocolType ProtocolType; InfallibleTArray& blobList = DataBlobs::Blobs(aClonedData); @@ -296,7 +303,7 @@ BuildClonedMessageData(typename BlobTraits::ConcreteContentManagerType* bool MessageManagerCallback::BuildClonedMessageDataForParent(nsIContentParent* aParent, - const StructuredCloneData& aData, + StructuredCloneData& aData, ClonedMessageData& aClonedData) { return BuildClonedMessageData(aParent, aData, aClonedData); @@ -304,25 +311,26 @@ MessageManagerCallback::BuildClonedMessageDataForParent(nsIContentParent* aParen bool MessageManagerCallback::BuildClonedMessageDataForChild(nsIContentChild* aChild, - const StructuredCloneData& aData, + StructuredCloneData& aData, ClonedMessageData& aClonedData) { return BuildClonedMessageData(aChild, aData, aClonedData); } template -static StructuredCloneData -UnpackClonedMessageData(const ClonedMessageData& aData) +static void +UnpackClonedMessageData(const ClonedMessageData& aClonedData, + StructuredCloneData& aData) { - const SerializedStructuredCloneBuffer& buffer = aData.data(); + const SerializedStructuredCloneBuffer& buffer = aClonedData.data(); typedef typename BlobTraits::ProtocolType ProtocolType; - const InfallibleTArray& blobs = DataBlobs::Blobs(aData); - StructuredCloneData cloneData; - cloneData.mData = buffer.data; - cloneData.mDataLength = buffer.dataLength; + const InfallibleTArray& blobs = DataBlobs::Blobs(aClonedData); + + aData.UseExternalData(buffer.data, buffer.dataLength); + if (!blobs.IsEmpty()) { uint32_t length = blobs.Length(); - cloneData.mClosure.mBlobImpls.SetCapacity(length); + aData.BlobImpls().SetCapacity(length); for (uint32_t i = 0; i < length; ++i) { auto* blob = static_cast::BlobType*>(blobs[i]); @@ -331,22 +339,23 @@ UnpackClonedMessageData(const ClonedMessageData& aData) nsRefPtr blobImpl = blob->GetBlobImpl(); MOZ_ASSERT(blobImpl); - cloneData.mClosure.mBlobImpls.AppendElement(blobImpl); + aData.BlobImpls().AppendElement(blobImpl); } } - return cloneData; } -StructuredCloneData -mozilla::dom::ipc::UnpackClonedMessageDataForParent(const ClonedMessageData& aData) +void +mozilla::dom::ipc::UnpackClonedMessageDataForParent(const ClonedMessageData& aClonedData, + StructuredCloneData& aData) { - return UnpackClonedMessageData(aData); + UnpackClonedMessageData(aClonedData, aData); } -StructuredCloneData -mozilla::dom::ipc::UnpackClonedMessageDataForChild(const ClonedMessageData& aData) +void +mozilla::dom::ipc::UnpackClonedMessageDataForChild(const ClonedMessageData& aClonedData, + StructuredCloneData& aData) { - return UnpackClonedMessageData(aData); + UnpackClonedMessageData(aClonedData, aData); } bool @@ -509,16 +518,9 @@ nsFrameMessageManager::LoadScript(const nsAString& aURL, bool aRunInGlobalScope) { if (aAllowDelayedLoad) { - if (IsGlobal() || IsBroadcaster()) { - // Cache for future windows or frames - mPendingScripts.AppendElement(aURL); - mPendingScriptsGlobalStates.AppendElement(aRunInGlobalScope); - } else if (!mCallback) { - // We're frame message manager, which isn't connected yet. - mPendingScripts.AppendElement(aURL); - mPendingScriptsGlobalStates.AppendElement(aRunInGlobalScope); - return NS_OK; - } + // Cache for future windows or frames + mPendingScripts.AppendElement(aURL); + mPendingScriptsGlobalStates.AppendElement(aRunInGlobalScope); } if (mCallback) { @@ -643,15 +645,18 @@ JSONCreator(const char16_t* aBuf, uint32_t aLen, void* aData) static bool GetParamsForMessage(JSContext* aCx, - const JS::Value& aData, - JSAutoStructuredCloneBuffer& aBuffer, - StructuredCloneClosure& aClosure) + const JS::Value& aValue, + StructuredCloneData& aData) { // First try to use structured clone on the whole thing. - JS::RootedValue v(aCx, aData); - if (WriteStructuredClone(aCx, v, aBuffer, aClosure)) { + JS::RootedValue v(aCx, aValue); + ErrorResult rv; + aData.Write(aCx, v, rv); + if (!rv.Failed()) { return true; } + + rv.SuppressException(); JS_ClearPendingException(aCx); nsCOMPtr console(do_GetService(NS_CONSOLESERVICE_CONTRACTID)); @@ -679,9 +684,14 @@ GetParamsForMessage(JSContext* aCx, NS_ENSURE_TRUE(JS_ParseJSON(aCx, static_cast(json.get()), json.Length(), &val), false); - return WriteStructuredClone(aCx, val, aBuffer, aClosure); -} + aData.Write(aCx, val, rv); + if (NS_WARN_IF(rv.Failed())) { + rv.SuppressException(); + return false; + } + return true; +} // nsISyncMessageSender @@ -736,29 +746,25 @@ nsFrameMessageManager::SendMessage(const nsAString& aMessageName, } StructuredCloneData data; - JSAutoStructuredCloneBuffer buffer; - if (aArgc >= 2 && - !GetParamsForMessage(aCx, aJSON, buffer, data.mClosure)) { + if (aArgc >= 2 && !GetParamsForMessage(aCx, aJSON, data)) { return NS_ERROR_DOM_DATA_CLONE_ERR; } - data.mData = buffer.data(); - data.mDataLength = buffer.nbytes(); JS::Rooted objects(aCx); if (aArgc >= 3 && aObjects.isObject()) { objects = &aObjects.toObject(); } - nsTArray retval; + nsTArray retval; sSendingSyncMessage |= aIsSync; - bool rv = mCallback->DoSendBlockingMessage(aCx, aMessageName, data, objects, + bool ok = mCallback->DoSendBlockingMessage(aCx, aMessageName, data, objects, aPrincipal, &retval, aIsSync); if (aIsSync) { sSendingSyncMessage = false; } - if (!rv) { + if (!ok) { return NS_OK; } @@ -768,8 +774,9 @@ nsFrameMessageManager::SendMessage(const nsAString& aMessageName, for (uint32_t i = 0; i < len; ++i) { JS::Rooted ret(aCx); - if (!JS_ReadStructuredClone(aCx, retval[i].data, retval[i].dataLength, - JS_STRUCTURED_CLONE_VERSION, &ret, nullptr, nullptr)) { + ErrorResult rv; + retval[i].Read(aCx, &ret, rv); + if (rv.Failed()) { MOZ_ASSERT(false, "Unable to read structured clone in SendMessage"); return NS_ERROR_UNEXPECTED; } @@ -785,7 +792,7 @@ nsFrameMessageManager::SendMessage(const nsAString& aMessageName, nsresult nsFrameMessageManager::DispatchAsyncMessageInternal(JSContext* aCx, const nsAString& aMessage, - const StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) { @@ -798,7 +805,10 @@ nsFrameMessageManager::DispatchAsyncMessageInternal(JSContext* aCx, return NS_OK; } - NS_ENSURE_TRUE(mCallback, NS_ERROR_NOT_INITIALIZED); + if (!mCallback) { + return NS_ERROR_NOT_INITIALIZED; + } + if (!mCallback->DoSendAsyncMessage(aCx, aMessage, aData, aCpows, aPrincipal)) { return NS_ERROR_FAILURE; } @@ -814,10 +824,7 @@ nsFrameMessageManager::DispatchAsyncMessage(const nsAString& aMessageName, uint8_t aArgc) { StructuredCloneData data; - JSAutoStructuredCloneBuffer buffer; - - if (aArgc >= 2 && - !GetParamsForMessage(aCx, aJSON, buffer, data.mClosure)) { + if (aArgc >= 2 && !GetParamsForMessage(aCx, aJSON, data)) { return NS_ERROR_DOM_DATA_CLONE_ERR; } @@ -826,9 +833,6 @@ nsFrameMessageManager::DispatchAsyncMessage(const nsAString& aMessageName, objects = &aObjects.toObject(); } - data.mData = buffer.data(); - data.mDataLength = buffer.nbytes(); - return DispatchAsyncMessageInternal(aCx, aMessageName, data, objects, aPrincipal); } @@ -1058,10 +1062,10 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, nsIFrameLoader* aTargetFrameLoader, const nsAString& aMessage, bool aIsSync, - const StructuredCloneData* aCloneData, + StructuredCloneData* aCloneData, mozilla::jsipc::CpowHolder* aCpows, nsIPrincipal* aPrincipal, - nsTArray* aRetVal) + nsTArray* aRetVal) { return ReceiveMessage(aTarget, aTargetFrameLoader, mClosed, aMessage, aIsSync, aCloneData, aCpows, aPrincipal, aRetVal); @@ -1073,10 +1077,10 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, bool aTargetClosed, const nsAString& aMessage, bool aIsSync, - const StructuredCloneData* aCloneData, + StructuredCloneData* aCloneData, mozilla::jsipc::CpowHolder* aCpows, nsIPrincipal* aPrincipal, - nsTArray* aRetVal) + nsTArray* aRetVal) { nsAutoTObserverArray* listeners = mListeners.Get(aMessage); @@ -1157,10 +1161,14 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, JS::Rooted cpowsv(cx, JS::ObjectValue(*cpows)); JS::Rooted json(cx, JS::NullValue()); - if (aCloneData && aCloneData->mDataLength && - !ReadStructuredClone(cx, *aCloneData, &json)) { - JS_ClearPendingException(cx); - return NS_OK; + if (aCloneData && aCloneData->DataLength()) { + ErrorResult rv; + aCloneData->Read(cx, &json, rv); + if (NS_WARN_IF(rv.Failed())) { + rv.SuppressException(); + JS_ClearPendingException(cx); + return NS_OK; + } } JS::Rooted jsMessage(cx, JS_NewUCStringCopyN(cx, @@ -1251,8 +1259,11 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, continue; } if (aRetVal) { - JSAutoStructuredCloneBuffer buffer; - if (!buffer.write(cx, rval)) { + ErrorResult rv; + StructuredCloneData* data = aRetVal->AppendElement(); + data->Write(cx, rval, rv); + if (NS_WARN_IF(rv.Failed())) { + aRetVal->RemoveElementAt(aRetVal->Length() - 1); nsString msg = aMessage + NS_LITERAL_STRING(": message reply cannot be cloned. Are you trying to send an XPCOM object?"); nsCOMPtr console(do_GetService(NS_CONSOLESERVICE_CONTRACTID)); @@ -1266,9 +1277,6 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, JS_ClearPendingException(cx); continue; } - - OwningSerializedStructuredCloneBuffer* data = aRetVal->AppendElement(); - buffer.steal(&data->data, &data->dataLength); } } } @@ -1423,6 +1431,14 @@ nsFrameMessageManager::GetInitialProcessData(JSContext* aCx, JS::MutableHandleVa init.setObject(*obj); } + if (!mChrome && XRE_IsParentProcess()) { + // This is the cpmm in the parent process. We should use the same object as the ppmm. + nsCOMPtr ppmm = + do_GetService("@mozilla.org/parentprocessmessagemanager;1"); + ppmm->GetInitialProcessData(aCx, &init); + mInitialProcessData = init; + } + if (!JS_WrapValue(aCx, &init)) { return NS_ERROR_OUT_OF_MEMORY; } @@ -1736,7 +1752,7 @@ nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript( NS_NewChannel(getter_AddRefs(channel), uri, nsContentUtils::GetSystemPrincipal(), - nsILoadInfo::SEC_NORMAL, + nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, nsIContentPolicy::TYPE_OTHER); if (!channel) { @@ -1744,7 +1760,8 @@ nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript( } nsCOMPtr input; - channel->Open(getter_AddRefs(input)); + rv = channel->Open2(getter_AddRefs(input)); + NS_ENSURE_SUCCESS_VOID(rv); nsString dataString; char16_t* dataStringBuf = nullptr; size_t dataStringLength = 0; @@ -1871,7 +1888,7 @@ class nsAsyncMessageToSameProcessChild : public nsSameProcessAsyncMessageBase, public: nsAsyncMessageToSameProcessChild(JSContext* aCx, const nsAString& aMessage, - const StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) : nsSameProcessAsyncMessageBase(aCx, aMessage, aData, aCpows, aPrincipal) @@ -1913,7 +1930,7 @@ public: virtual bool DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, - const StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) override { @@ -1967,10 +1984,10 @@ public: virtual bool DoSendBlockingMessage(JSContext* aCx, const nsAString& aMessage, - const mozilla::dom::StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal, - nsTArray* aRetVal, + nsTArray* aRetVal, bool aIsSync) override { mozilla::dom::ContentChild* cc = @@ -1996,7 +2013,7 @@ public: virtual bool DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, - const mozilla::dom::StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) override { @@ -2026,7 +2043,7 @@ class nsAsyncMessageToSameProcessParent : public nsSameProcessAsyncMessageBase, public: nsAsyncMessageToSameProcessParent(JSContext* aCx, const nsAString& aMessage, - const StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) : nsSameProcessAsyncMessageBase(aCx, aMessage, aData, aCpows, aPrincipal) @@ -2058,10 +2075,10 @@ public: virtual bool DoSendBlockingMessage(JSContext* aCx, const nsAString& aMessage, - const mozilla::dom::StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal, - nsTArray* aRetVal, + nsTArray* aRetVal, bool aIsSync) override { SameProcessMessageQueue* queue = SameProcessMessageQueue::Get(); @@ -2078,7 +2095,7 @@ public: virtual bool DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, - const mozilla::dom::StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) override { @@ -2155,7 +2172,6 @@ NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult) NS_ENSURE_TRUE(global->Init(), NS_ERROR_UNEXPECTED); global.forget(aResult); return NS_OK; - } static PLDHashOperator @@ -2185,7 +2201,7 @@ nsFrameMessageManager::MarkForCC() nsSameProcessAsyncMessageBase::nsSameProcessAsyncMessageBase(JSContext* aCx, const nsAString& aMessage, - const StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) : mRuntime(js::GetRuntime(aCx)), @@ -2193,10 +2209,13 @@ nsSameProcessAsyncMessageBase::nsSameProcessAsyncMessageBase(JSContext* aCx, mCpows(aCx, aCpows), mPrincipal(aPrincipal) { - if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) { - NS_RUNTIMEABORT("OOM"); + if (!mData.Copy(aData)) { +#ifdef MOZ_CRASHREPORTER + CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AsyncMessageOOM"), + NS_ConvertUTF16toUTF8(aMessage)); +#endif + NS_ABORT_OOM(aData.DataLength()); } - mClosure = aData.mClosure; } void @@ -2205,15 +2224,10 @@ nsSameProcessAsyncMessageBase::ReceiveMessage(nsISupports* aTarget, nsFrameMessageManager* aManager) { if (aManager) { - StructuredCloneData data; - data.mData = mData.data(); - data.mDataLength = mData.nbytes(); - data.mClosure = mClosure; - SameProcessCpowHolder cpows(mRuntime, mCpows); nsRefPtr mm = aManager; - mm->ReceiveMessage(aTarget, aTargetFrameLoader, mMessage, false, &data, &cpows, - mPrincipal, nullptr); + mm->ReceiveMessage(aTarget, aTargetFrameLoader, mMessage, false, &mData, + &cpows, mPrincipal, nullptr); } } diff --git a/dom/base/nsFrameMessageManager.h b/dom/base/nsFrameMessageManager.h index 755f759d69..6cfb8b7738 100644 --- a/dom/base/nsFrameMessageManager.h +++ b/dom/base/nsFrameMessageManager.h @@ -28,15 +28,12 @@ #include "js/RootingAPI.h" #include "nsTObserverArray.h" #include "mozilla/dom/SameProcessMessageQueue.h" -#include "mozilla/dom/StructuredCloneUtils.h" +#include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/jsipc/CpowHolder.h" class nsIFrameLoader; namespace mozilla { - -struct OwningSerializedStructuredCloneBuffer; - namespace dom { class nsIContentParent; @@ -57,9 +54,6 @@ enum MessageManagerFlags { class MessageManagerCallback { -protected: - typedef mozilla::OwningSerializedStructuredCloneBuffer OwningSerializedStructuredCloneBuffer; - public: virtual ~MessageManagerCallback() {} @@ -70,10 +64,10 @@ public: virtual bool DoSendBlockingMessage(JSContext* aCx, const nsAString& aMessage, - const StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal, - nsTArray* aRetVal, + nsTArray* aRetVal, bool aIsSync) { return true; @@ -81,7 +75,7 @@ public: virtual bool DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, - const StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) { @@ -116,15 +110,18 @@ public: protected: bool BuildClonedMessageDataForParent(nsIContentParent* aParent, - const StructuredCloneData& aData, + StructuredCloneData& aData, ClonedMessageData& aClonedData); bool BuildClonedMessageDataForChild(nsIContentChild* aChild, - const StructuredCloneData& aData, + StructuredCloneData& aData, ClonedMessageData& aClonedData); }; -StructuredCloneData UnpackClonedMessageDataForParent(const ClonedMessageData& aData); -StructuredCloneData UnpackClonedMessageDataForChild(const ClonedMessageData& aData); +void UnpackClonedMessageDataForParent(const ClonedMessageData& aClonedData, + StructuredCloneData& aData); + +void UnpackClonedMessageDataForChild(const ClonedMessageData& aClonedData, + StructuredCloneData& aData); } // namespace ipc } // namespace dom @@ -166,8 +163,7 @@ class nsFrameMessageManager final : public nsIContentFrameMessageManager, public nsIProcessChecker { friend class mozilla::dom::MessageManagerReporter; - typedef mozilla::dom::StructuredCloneData StructuredCloneData; - typedef mozilla::OwningSerializedStructuredCloneBuffer OwningSerializedStructuredCloneBuffer; + typedef mozilla::dom::ipc::StructuredCloneData StructuredCloneData; public: nsFrameMessageManager(mozilla::dom::ipc::MessageManagerCallback* aCallback, nsFrameMessageManager* aParentManager, @@ -196,9 +192,9 @@ public: nsresult ReceiveMessage(nsISupports* aTarget, nsIFrameLoader* aTargetFrameLoader, const nsAString& aMessage, - bool aIsSync, const StructuredCloneData* aCloneData, + bool aIsSync, StructuredCloneData* aCloneData, mozilla::jsipc::CpowHolder* aCpows, nsIPrincipal* aPrincipal, - nsTArray* aRetVal); + nsTArray* aRetVal); void AddChildManager(nsFrameMessageManager* aManager); void RemoveChildManager(nsFrameMessageManager* aManager) @@ -223,7 +219,7 @@ public: uint8_t aArgc); nsresult DispatchAsyncMessageInternal(JSContext* aCx, const nsAString& aMessage, - const StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal); void RemoveFromParent(); @@ -264,9 +260,9 @@ private: nsresult ReceiveMessage(nsISupports* aTarget, nsIFrameLoader* aTargetFrameLoader, bool aTargetClosed, const nsAString& aMessage, - bool aIsSync, const StructuredCloneData* aCloneData, + bool aIsSync, StructuredCloneData* aCloneData, mozilla::jsipc::CpowHolder* aCpows, nsIPrincipal* aPrincipal, - nsTArray* aRetVal); + nsTArray* aRetVal); NS_IMETHOD LoadScript(const nsAString& aURL, bool aAllowDelayedLoad, @@ -291,7 +287,7 @@ protected: bool mDisconnected; mozilla::dom::ipc::MessageManagerCallback* mCallback; nsAutoPtr mOwnedCallback; - nsFrameMessageManager* mParentManager; + nsRefPtr mParentManager; nsTArray mPendingScripts; nsTArray mPendingScriptsGlobalStates; JS::Heap mInitialProcessData; @@ -329,14 +325,12 @@ private: */ class nsSameProcessAsyncMessageBase { - typedef mozilla::dom::StructuredCloneClosure StructuredCloneClosure; - public: - typedef mozilla::dom::StructuredCloneData StructuredCloneData; + typedef mozilla::dom::ipc::StructuredCloneData StructuredCloneData; nsSameProcessAsyncMessageBase(JSContext* aCx, const nsAString& aMessage, - const StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal); @@ -348,8 +342,7 @@ private: JSRuntime* mRuntime; nsString mMessage; - JSAutoStructuredCloneBuffer mData; - StructuredCloneClosure mClosure; + StructuredCloneData mData; JS::PersistentRooted mCpows; nsCOMPtr mPrincipal; }; diff --git a/dom/base/nsInProcessTabChildGlobal.cpp b/dom/base/nsInProcessTabChildGlobal.cpp index 1d4bcfd78b..cd004dae27 100644 --- a/dom/base/nsInProcessTabChildGlobal.cpp +++ b/dom/base/nsInProcessTabChildGlobal.cpp @@ -18,21 +18,18 @@ #include "nsDOMClassInfoID.h" #include "mozilla/EventDispatcher.h" #include "mozilla/dom/SameProcessMessageQueue.h" -#include "mozilla/dom/StructuredCloneUtils.h" -#include "js/StructuredClone.h" -using mozilla::dom::StructuredCloneData; -using mozilla::dom::StructuredCloneClosure; using namespace mozilla; using namespace mozilla::dom; +using namespace mozilla::dom::ipc; bool nsInProcessTabChildGlobal::DoSendBlockingMessage(JSContext* aCx, const nsAString& aMessage, - const dom::StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal, - nsTArray* aRetVal, + nsTArray* aRetVal, bool aIsSync) { SameProcessMessageQueue* queue = SameProcessMessageQueue::Get(); @@ -55,7 +52,7 @@ public: nsAsyncMessageToParent(JSContext* aCx, nsInProcessTabChildGlobal* aTabChild, const nsAString& aMessage, - const StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) : nsSameProcessAsyncMessageBase(aCx, aMessage, aData, aCpows, aPrincipal), @@ -75,7 +72,7 @@ public: bool nsInProcessTabChildGlobal::DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, - const StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) { diff --git a/dom/base/nsInProcessTabChildGlobal.h b/dom/base/nsInProcessTabChildGlobal.h index e8c2d83d33..b861329f62 100644 --- a/dom/base/nsInProcessTabChildGlobal.h +++ b/dom/base/nsInProcessTabChildGlobal.h @@ -35,7 +35,7 @@ class nsInProcessTabChildGlobal : public mozilla::DOMEventTargetHelper, public nsSupportsWeakReference, public mozilla::dom::ipc::MessageManagerCallback { - typedef mozilla::OwningSerializedStructuredCloneBuffer OwningSerializedStructuredCloneBuffer; + typedef mozilla::dom::ipc::StructuredCloneData StructuredCloneData; public: nsInProcessTabChildGlobal(nsIDocShell* aShell, nsIContent* aOwner, @@ -83,14 +83,14 @@ public: */ virtual bool DoSendBlockingMessage(JSContext* aCx, const nsAString& aMessage, - const mozilla::dom::StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal, - nsTArray* aRetVal, + nsTArray* aRetVal, bool aIsSync) override; virtual bool DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, - const mozilla::dom::StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) override; diff --git a/dom/base/nsStructuredCloneContainer.cpp b/dom/base/nsStructuredCloneContainer.cpp index 62bc8ecd13..430bfe3b3e 100644 --- a/dom/base/nsStructuredCloneContainer.cpp +++ b/dom/base/nsStructuredCloneContainer.cpp @@ -16,7 +16,6 @@ #include "xpcpublic.h" #include "mozilla/Base64.h" -#include "mozilla/dom/StructuredCloneHelper.h" #include "mozilla/dom/ScriptSettings.h" using namespace mozilla; @@ -31,23 +30,19 @@ NS_INTERFACE_MAP_BEGIN(nsStructuredCloneContainer) NS_INTERFACE_MAP_END nsStructuredCloneContainer::nsStructuredCloneContainer() - : StructuredCloneHelper(CloningSupported, TransferringNotSupported) - , mState(eNotInitialized) , mData(nullptr), mSize(0), mVersion(0) + : mVersion(0) { } nsStructuredCloneContainer::~nsStructuredCloneContainer() { - if (mData) { - free(mData); - } } NS_IMETHODIMP nsStructuredCloneContainer::InitFromJSVal(JS::Handle aData, JSContext* aCx) { - if (mState != eNotInitialized) { + if (DataLength()) { return NS_ERROR_FAILURE; } @@ -57,7 +52,7 @@ nsStructuredCloneContainer::InitFromJSVal(JS::Handle aData, return rv.StealNSResult(); } - mState = eInitializedFromJSVal; + mVersion = JS_STRUCTURED_CLONE_VERSION; return NS_OK; } @@ -66,7 +61,7 @@ nsStructuredCloneContainer::InitFromBase64(const nsAString &aData, uint32_t aFormatVersion, JSContext* aCx) { - if (mState != eNotInitialized) { + if (DataLength()) { return NS_ERROR_FAILURE; } @@ -76,15 +71,11 @@ nsStructuredCloneContainer::InitFromBase64(const nsAString &aData, nsresult rv = Base64Decode(data, binaryData); NS_ENSURE_SUCCESS(rv, rv); - // Copy the string's data into our own buffer. - mData = (uint64_t*) malloc(binaryData.Length()); - NS_ENSURE_STATE(mData); - memcpy(mData, binaryData.get(), binaryData.Length()); + if (!CopyExternalData(binaryData.get(), binaryData.Length())) { + return NS_ERROR_OUT_OF_MEMORY; + } - mSize = binaryData.Length(); mVersion = aFormatVersion; - - mState = eInitializedFromBase64; return NS_OK; } @@ -95,21 +86,10 @@ nsStructuredCloneContainer::DeserializeToJsval(JSContext* aCx, aValue.setNull(); JS::Rooted jsStateObj(aCx); - if (mState == eInitializedFromJSVal) { - ErrorResult rv; - Read(nullptr, aCx, &jsStateObj, rv); - if (NS_WARN_IF(rv.Failed())) { - return rv.StealNSResult(); - } - } else { - MOZ_ASSERT(mState == eInitializedFromBase64); - MOZ_ASSERT(mData); - - ErrorResult rv; - ReadFromBuffer(nullptr, aCx, mData, mSize, mVersion, &jsStateObj, rv); - if (NS_WARN_IF(rv.Failed())) { - return rv.StealNSResult(); - } + ErrorResult rv; + Read(aCx, &jsStateObj, rv); + if (NS_WARN_IF(rv.Failed())) { + return rv.StealNSResult(); } aValue.set(jsStateObj); @@ -123,7 +103,7 @@ nsStructuredCloneContainer::DeserializeToVariant(JSContext* aCx, NS_ENSURE_ARG_POINTER(aData); *aData = nullptr; - if (mState == eNotInitialized) { + if (!DataLength()) { return NS_ERROR_FAILURE; } @@ -150,29 +130,15 @@ nsStructuredCloneContainer::GetDataAsBase64(nsAString &aOut) { aOut.Truncate(); - if (mState == eNotInitialized) { + if (!DataLength()) { return NS_ERROR_FAILURE; } - uint64_t* data; - size_t size; - - if (mState == eInitializedFromJSVal) { - if (HasClonedDOMObjects()) { - return NS_ERROR_FAILURE; - } - - data = BufferData(); - size = BufferSize(); - } else { - MOZ_ASSERT(mState == eInitializedFromBase64); - MOZ_ASSERT(mData); - - data = mData; - size = mSize; + if (HasClonedDOMObjects()) { + return NS_ERROR_FAILURE; } - nsAutoCString binaryData(reinterpret_cast(data), size); + nsAutoCString binaryData(reinterpret_cast(Data()), DataLength()); nsAutoCString base64Data; nsresult rv = Base64Encode(binaryData, base64Data); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -188,22 +154,11 @@ nsStructuredCloneContainer::GetSerializedNBytes(uint64_t* aSize) { NS_ENSURE_ARG_POINTER(aSize); - if (mState == eNotInitialized) { + if (!DataLength()) { return NS_ERROR_FAILURE; } - if (mState == eInitializedFromJSVal) { - *aSize = BufferSize(); - return NS_OK; - } - - MOZ_ASSERT(mState == eInitializedFromBase64); - - // mSize is a size_t, while aSize is a uint64_t. We rely on an implicit cast - // here so that we'll get a compile error if a size_t-to-uint64_t cast is - // narrowing. - *aSize = mSize; - + *aSize = DataLength(); return NS_OK; } @@ -212,16 +167,10 @@ nsStructuredCloneContainer::GetFormatVersion(uint32_t* aFormatVersion) { NS_ENSURE_ARG_POINTER(aFormatVersion); - if (mState == eNotInitialized) { + if (!DataLength()) { return NS_ERROR_FAILURE; } - if (mState == eInitializedFromJSVal) { - *aFormatVersion = JS_STRUCTURED_CLONE_VERSION; - return NS_OK; - } - - MOZ_ASSERT(mState == eInitializedFromBase64); *aFormatVersion = mVersion; return NS_OK; } diff --git a/dom/base/nsStructuredCloneContainer.h b/dom/base/nsStructuredCloneContainer.h index ddad5af9c6..a826c8c075 100644 --- a/dom/base/nsStructuredCloneContainer.h +++ b/dom/base/nsStructuredCloneContainer.h @@ -9,7 +9,7 @@ #include "nsIStructuredCloneContainer.h" #include "mozilla/Attributes.h" -#include "mozilla/dom/StructuredCloneHelper.h" +#include "mozilla/dom/ipc/StructuredCloneData.h" #define NS_STRUCTUREDCLONECONTAINER_CONTRACTID \ "@mozilla.org/docshell/structured-clone-container;1" @@ -23,7 +23,7 @@ class nsStructuredCloneContainer final : public nsIStructuredCloneContainer - , public mozilla::dom::StructuredCloneHelper + , public mozilla::dom::ipc::StructuredCloneData { public: nsStructuredCloneContainer(); @@ -34,16 +34,6 @@ class nsStructuredCloneContainer final private: ~nsStructuredCloneContainer(); - enum { - eNotInitialized = 0, - eInitializedFromJSVal, - eInitializedFromBase64, - } mState; - - uint64_t* mData; - - // This needs to be size_t rather than a PR-type so it matches the JS API. - size_t mSize; uint32_t mVersion; }; diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini index db9beff154..ad374fe0a7 100644 --- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -812,4 +812,5 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' [test_window_element_enumeration.html] [test_referrer_redirect.html] [test_postMessages.html] +support-files = worker_postMessages.js [test_window_proto.html] diff --git a/dom/base/test/test_postMessages.html b/dom/base/test/test_postMessages.html index 1e544c84bb..ed343caba5 100644 --- a/dom/base/test/test_postMessages.html +++ b/dom/base/test/test_postMessages.html @@ -278,6 +278,51 @@ function test_windowToIframeURL(url) { document.body.appendChild(ifr); } +// PostMessage for Workers +function test_workers() { + info("Testing Workers"); + + var resolve; + + var w = new Worker('worker_postMessages.js'); + w.postMessage('workers'); + w.onmessage = function(e) { + is(e.data, 'ok', "Worker ready!"); + + w.onmessage = function(e) { + if (!resolve) { + ok(false, "Unexpected message!"); + return; + } + + let tmp = resolve; + resolve = null; + tmp({ data: e.data, ports: e.ports }); + } + + runTests({ + clonableObjects: true, + transferableObjects: true, + send: function(what, ports) { + return new Promise(function(r, rr) { + resolve = r; + try { + w.postMessage(what, ports); + } catch(e) { + resolve = null; + rr(); + } + }); + }, + + finished: function() { + onmessage = null; + next(); + } + }); + } +} + // PostMessage for BroadcastChannel function test_broadcastChannel() { info("Testing broadcastChannel"); @@ -320,6 +365,52 @@ function test_broadcastChannel() { }); } +// PostMessage for BroadcastChannel in workers +function test_broadcastChannel_inWorkers() { + info("Testing broadcastChannel in Workers"); + + var bc = new BroadcastChannel('postMessagesTest_inWorkers'); + var resolve; + + var w = new Worker('worker_postMessages.js'); + w.postMessage('broadcastChannel'); + w.onmessage = function(e) { + is(e.data, 'ok', "Worker ready!"); + + w.onmessage = function(e) { + if (!resolve) { + ok(false, "Unexpected message!"); + return; + } + + let tmp = resolve; + resolve = null; + tmp({ data: e.data, ports: e.ports }); + } + + runTests({ + clonableObjects: true, + transferableObjects: false, + send: function(what, ports) { + return new Promise(function(r, rr) { + if (ports.length) { + rr(); + return; + } + + resolve = r; + bc.postMessage(what); + }); + }, + + finished: function() { + onmessage = null; + next(); + } + }); + } +} + // PostMessage for MessagePort function test_messagePort() { info("Testing messagePort"); @@ -360,6 +451,52 @@ function test_messagePort() { }); } +// PostMessage for MessagePort in Workers +function test_messagePort_inWorkers() { + info("Testing messagePort in workers"); + + var mc = new MessageChannel(); + var resolve; + + var w = new Worker('worker_postMessages.js'); + w.postMessage('messagePort', [ mc.port2 ]); + w.onmessage = function(e) { + is(e.data, 'ok', "Worker ready!"); + + w.onmessage = function(e) { + if (!resolve) { + ok(false, "Unexpected message!"); + return; + } + + let tmp = resolve; + resolve = null; + tmp({ data: e.data, ports: e.ports }); + } + + runTests({ + clonableObjects: true, + transferableObjects: true, + send: function(what, ports) { + return new Promise(function(r, rr) { + resolve = r; + try { + mc.port1.postMessage(what, ports); + } catch(e) { + resolve = null; + rr(); + } + }); + }, + + finished: function() { + onmessage = null; + next(); + } + }); + } +} + var tests = [ create_fileList, @@ -367,11 +504,13 @@ var tests = [ test_windowToIframe, test_windowToCrossOriginIframe, + test_workers, + test_broadcastChannel, - // TODO BroadcastChannel in worker + test_broadcastChannel_inWorkers, test_messagePort, - // TODO MessagePort in worker + test_messagePort_inWorkers, ]; function next() { diff --git a/dom/base/test/worker_postMessages.js b/dom/base/test/worker_postMessages.js new file mode 100644 index 0000000000..968ec209a2 --- /dev/null +++ b/dom/base/test/worker_postMessages.js @@ -0,0 +1,33 @@ +function test_workers() { + onmessage = function(e) { + postMessage(e.data, e.ports); + } +} + +function test_broadcastChannel() { + var bc = new BroadcastChannel('postMessagesTest_inWorkers'); + bc.onmessage = function(e) { + postMessage(e.data); + } +} + +function test_messagePort(port) { + port.onmessage = function(e) { + postMessage(e.data, e.ports); + } +} + +onmessage = function(e) { + if (e.data == 'workers') { + test_workers(); + postMessage('ok'); + } else if (e.data == 'broadcastChannel') { + test_broadcastChannel(); + postMessage('ok'); + } else if (e.data == 'messagePort') { + test_messagePort(e.ports[0]); + postMessage('ok'); + } else { + postMessage('ko'); + } +} diff --git a/dom/bluetooth/BluetoothInterface.cpp b/dom/bluetooth/BluetoothInterface.cpp index 26f217eb86..0b898514df 100644 --- a/dom/bluetooth/BluetoothInterface.cpp +++ b/dom/bluetooth/BluetoothInterface.cpp @@ -107,6 +107,12 @@ BluetoothGattClientInterface::BluetoothGattClientInterface() BluetoothGattClientInterface::~BluetoothGattClientInterface() { } +BluetoothGattServerInterface::BluetoothGattServerInterface() +{ } + +BluetoothGattServerInterface::~BluetoothGattServerInterface() +{ } + BluetoothGattInterface::BluetoothGattInterface() { } diff --git a/dom/bluetooth/BluetoothInterface.h b/dom/bluetooth/BluetoothInterface.h index 9749cf8a87..58b557978e 100644 --- a/dom/bluetooth/BluetoothInterface.h +++ b/dom/bluetooth/BluetoothInterface.h @@ -687,7 +687,8 @@ public: const nsAString& aBdAddr, int aAttributeHandle, int aOffset, - const nsTArray& aValue, + int aLength, + const uint8_t* aValue, bool aNeedResponse, bool aIsPrepareWrite) { } @@ -788,7 +789,7 @@ public: virtual void DeregisterNotification() { } virtual void ReadRemoteRssi() { } - virtual void GetDeviceType() { } + virtual void GetDeviceType(BluetoothTypeOfDevice type) { } virtual void SetAdvData() { } virtual void TestCommand() { } @@ -796,16 +797,11 @@ protected: virtual ~BluetoothGattClientResultHandler() { } }; -class BluetoothGattServerResultHandler +class BluetoothGattServerResultHandler : public BluetoothGattResultHandler { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothGattServerResultHandler) - virtual void OnError(BluetoothStatus aStatus) - { - BT_WARNING("Received error code %d", (int)aStatus); - } - virtual void RegisterServer() { } virtual void UnregisterServer() { } @@ -1048,6 +1044,7 @@ public: virtual void Cleanup(BluetoothGattResultHandler* aRes) = 0; virtual BluetoothGattClientInterface* GetBluetoothGattClientInterface() = 0; + virtual BluetoothGattServerInterface* GetBluetoothGattServerInterface() = 0; protected: BluetoothGattInterface(); diff --git a/dom/bluetooth/BluetoothInterfaceHelpers.h b/dom/bluetooth/BluetoothInterfaceHelpers.h index 259a5f7e81..37bdc9eb06 100644 --- a/dom/bluetooth/BluetoothInterfaceHelpers.h +++ b/dom/bluetooth/BluetoothInterfaceHelpers.h @@ -687,6 +687,185 @@ private: Tin5 mArg5; }; +template +class BluetoothNotificationRunnable6 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationRunnable6 + SelfType; + + template + static already_AddRefed Create( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6), + const InitOp& aInitOp) + { + nsRefPtr runnable(new SelfType(aMethod)); + if (NS_FAILED(runnable->Init(aInitOp))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6), + const InitOp& aInitOp) + { + nsRefPtr runnable = Create(aMethod, aInitOp); + if (!runnable) { + BT_WARNING("BluetoothNotificationRunnable6::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() override + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + if (!obj) { + BT_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4, mArg5, mArg6); + } + return NS_OK; + } + +private: + BluetoothNotificationRunnable6( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult + Init(const InitOp& aInitOp) + { + nsresult rv = aInitOp(mArg1, mArg2, mArg3, mArg4, mArg5, mArg6); + if (NS_FAILED(rv)) { + return rv; + } + return NS_OK; + } + + Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); + Tin1 mArg1; + Tin2 mArg2; + Tin3 mArg3; + Tin4 mArg4; + Tin5 mArg5; + Tin6 mArg6; +}; + +template +class BluetoothNotificationRunnable9 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationRunnable9 SelfType; + + template + static already_AddRefed Create( + Res (ObjectType::*aMethod)( + Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9), + const InitOp& aInitOp) + { + nsRefPtr runnable(new SelfType(aMethod)); + if (NS_FAILED(runnable->Init(aInitOp))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch( + Res (ObjectType::*aMethod)( + Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9), + const InitOp& aInitOp) + { + nsRefPtr runnable = Create(aMethod, aInitOp); + if (!runnable) { + BT_WARNING("BluetoothNotificationRunnable8::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() override + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + if (!obj) { + BT_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4, + mArg5, mArg6, mArg7, mArg8, mArg9); + } + return NS_OK; + } + +private: + BluetoothNotificationRunnable9( + Res (ObjectType::*aMethod)( + Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9)) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult + Init(const InitOp& aInitOp) + { + nsresult rv = aInitOp(mArg1, mArg2, mArg3, mArg4, + mArg5, mArg6, mArg7, mArg8, mArg9); + if (NS_FAILED(rv)) { + return rv; + } + return NS_OK; + } + + Res (ObjectType::*mMethod)( + Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9); + Tin1 mArg1; + Tin2 mArg2; + Tin3 mArg3; + Tin4 mArg4; + Tin5 mArg5; + Tin6 mArg6; + Tin7 mArg7; + Tin8 mArg8; + Tin9 mArg9; +}; + + // // Init operators // diff --git a/dom/bluetooth/BluetoothUtils.cpp b/dom/bluetooth/BluetoothUtils.cpp index 4e17724e91..f1cff7631b 100644 --- a/dom/bluetooth/BluetoothUtils.cpp +++ b/dom/bluetooth/BluetoothUtils.cpp @@ -42,17 +42,6 @@ UuidToString(const BluetoothUuid& aUuid, nsAString& aString) aString.AssignLiteral(uuidStr); } -void -ReversedUuidToString(const BluetoothUuid& aUuid, nsAString& aString) -{ - BluetoothUuid uuid; - for (uint8_t i = 0; i < 16; i++) { - uuid.mUuid[i] = aUuid.mUuid[15 - i]; - } - - UuidToString(uuid, aString); -} - void StringToUuid(const char* aString, BluetoothUuid& aUuid) { @@ -98,24 +87,16 @@ GenerateUuid(nsAString &aUuidString) aUuidString.Assign(Substring(uuidString, 1, NSID_LENGTH - 3)); } -void -GeneratePathFromGattId(const BluetoothGattId& aId, - nsAString& aPath, - nsAString& aUuidStr) -{ - ReversedUuidToString(aId.mUuid, aUuidStr); - - aPath.Assign(aUuidStr); - aPath.AppendLiteral("_"); - aPath.AppendInt(aId.mInstanceId); -} - void GeneratePathFromGattId(const BluetoothGattId& aId, nsAString& aPath) { nsString uuidStr; - GeneratePathFromGattId(aId, aPath, uuidStr); + UuidToString(aId.mUuid, uuidStr); + + aPath.Assign(uuidStr); + aPath.AppendLiteral("_"); + aPath.AppendInt(aId.mInstanceId); } void diff --git a/dom/bluetooth/BluetoothUtils.h b/dom/bluetooth/BluetoothUtils.h index 14beabe11e..e3595294ef 100644 --- a/dom/bluetooth/BluetoothUtils.h +++ b/dom/bluetooth/BluetoothUtils.h @@ -29,19 +29,6 @@ class BluetoothValue; void UuidToString(const BluetoothUuid& aUuid, nsAString& aString); -/** - * Convert BluetoothUuid object in a reversed byte order to - * xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx uuid string. - * Bluedroid stack reports the BluetoothUuid in a reversed byte order for - * GATT service, characteristic, descriptor uuids. - * - * Note: This utility function is used by gecko internal only to convert - * BluetoothUuid in a reversed byte order created by bluetooth stack to uuid - * string representation. - */ -void -ReversedUuidToString(const BluetoothUuid& aUuid, nsAString& aString); - /** * Convert xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx uuid string to BluetoothUuid object. * @@ -63,18 +50,6 @@ GenerateUuid(nsAString &aUuidString); // Generate bluetooth signal path from GattId // -/** - * Generate bluetooth signal path and UUID string from a GattId. - * - * @param aId [in] GattId value to convert. - * @param aPath [out] Bluetooth signal path generated from aId. - * @param aUuidStr [out] UUID string generated from aId. - */ -void -GeneratePathFromGattId(const BluetoothGattId& aId, - nsAString& aPath, - nsAString& aUuidStr); - /** * Generate bluetooth signal path from a GattId. * diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonA2dpInterface.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonA2dpInterface.cpp index ef408174fb..9fc11525ec 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonA2dpInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothDaemonA2dpInterface.cpp @@ -27,7 +27,7 @@ BluetoothDaemonA2dpModule::SetNotificationHandler( } nsresult -BluetoothDaemonA2dpModule::Send(BluetoothDaemonPDU* aPDU, +BluetoothDaemonA2dpModule::Send(DaemonSocketPDU* aPDU, BluetoothA2dpResultHandler* aRes) { aRes->AddRef(); // Keep reference for response @@ -35,11 +35,11 @@ BluetoothDaemonA2dpModule::Send(BluetoothDaemonPDU* aPDU, } void -BluetoothDaemonA2dpModule::HandleSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData) +BluetoothDaemonA2dpModule::HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonA2dpModule::* const HandleOp[])( - const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&, void*) = { + const DaemonSocketPDUHeader&, DaemonSocketPDU&, void*) = { INIT_ARRAY_AT(0, &BluetoothDaemonA2dpModule::HandleRsp), INIT_ARRAY_AT(1, &BluetoothDaemonA2dpModule::HandleNtf), }; @@ -61,7 +61,7 @@ BluetoothDaemonA2dpModule::ConnectCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(SERVICE_ID, + nsAutoPtr pdu(new DaemonSocketPDU(SERVICE_ID, OPCODE_CONNECT, 6)); // Address nsresult rv = PackPDU( @@ -83,7 +83,7 @@ BluetoothDaemonA2dpModule::DisconnectCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(SERVICE_ID, + nsAutoPtr pdu(new DaemonSocketPDU(SERVICE_ID, OPCODE_DISCONNECT, 6)); // Address nsresult rv = PackPDU( @@ -104,8 +104,8 @@ BluetoothDaemonA2dpModule::DisconnectCmd( void BluetoothDaemonA2dpModule::ErrorRsp( - const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, BluetoothA2dpResultHandler* aRes) + const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothA2dpResultHandler* aRes) { ErrorRunnable::Dispatch( aRes, &BluetoothA2dpResultHandler::OnError, UnpackPDUInitOp(aPDU)); @@ -113,7 +113,7 @@ BluetoothDaemonA2dpModule::ErrorRsp( void BluetoothDaemonA2dpModule::ConnectRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothA2dpResultHandler* aRes) { ResultRunnable::Dispatch( @@ -122,7 +122,7 @@ BluetoothDaemonA2dpModule::ConnectRsp( void BluetoothDaemonA2dpModule::DisconnectRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothA2dpResultHandler* aRes) { ResultRunnable::Dispatch( @@ -131,12 +131,12 @@ BluetoothDaemonA2dpModule::DisconnectRsp( void BluetoothDaemonA2dpModule::HandleRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonA2dpModule::* const HandleRsp[])( - const BluetoothDaemonPDUHeader&, - BluetoothDaemonPDU&, + const DaemonSocketPDUHeader&, + DaemonSocketPDU&, BluetoothA2dpResultHandler*) = { INIT_ARRAY_AT(OPCODE_ERROR, &BluetoothDaemonA2dpModule::ErrorRsp), @@ -186,14 +186,14 @@ class BluetoothDaemonA2dpModule::ConnectionStateInitOp final : private PDUInitOp { public: - ConnectionStateInitOp(BluetoothDaemonPDU& aPDU) + ConnectionStateInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } nsresult operator () (BluetoothA2dpConnectionState& aArg1, nsString& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read state */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -214,7 +214,7 @@ public: void BluetoothDaemonA2dpModule::ConnectionStateNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ConnectionStateNotification::Dispatch( &BluetoothA2dpNotificationHandler::ConnectionStateNotification, @@ -226,7 +226,7 @@ class BluetoothDaemonA2dpModule::AudioStateInitOp final : private PDUInitOp { public: - AudioStateInitOp(BluetoothDaemonPDU& aPDU) + AudioStateInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -234,7 +234,7 @@ public: operator () (BluetoothA2dpAudioState& aArg1, nsString& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read state */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -255,7 +255,7 @@ public: void BluetoothDaemonA2dpModule::AudioStateNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { AudioStateNotification::Dispatch( &BluetoothA2dpNotificationHandler::AudioStateNotification, @@ -267,14 +267,14 @@ class BluetoothDaemonA2dpModule::AudioConfigInitOp final : private PDUInitOp { public: - AudioConfigInitOp(BluetoothDaemonPDU& aPDU) + AudioConfigInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } nsresult operator () (nsString& aArg1, uint32_t aArg2, uint8_t aArg3) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read address */ nsresult rv = UnpackPDU( @@ -301,7 +301,7 @@ public: void BluetoothDaemonA2dpModule::AudioConfigNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { AudioConfigNotification::Dispatch( &BluetoothA2dpNotificationHandler::AudioConfigNotification, @@ -310,11 +310,11 @@ BluetoothDaemonA2dpModule::AudioConfigNtf( void BluetoothDaemonA2dpModule::HandleNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonA2dpModule::* const HandleNtf[])( - const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&) = { + const DaemonSocketPDUHeader&, DaemonSocketPDU&) = { INIT_ARRAY_AT(0, &BluetoothDaemonA2dpModule::ConnectionStateNtf), INIT_ARRAY_AT(1, &BluetoothDaemonA2dpModule::AudioStateNtf), #if ANDROID_VERSION >= 21 @@ -481,8 +481,8 @@ void BluetoothDaemonA2dpInterface::DispatchError( BluetoothA2dpResultHandler* aRes, BluetoothStatus aStatus) { - BluetoothResultRunnable1::Dispatch( + DaemonResultRunnable1::Dispatch( aRes, &BluetoothA2dpResultHandler::OnError, ConstantInitOp1(aStatus)); } diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonA2dpInterface.h b/dom/bluetooth/bluedroid/BluetoothDaemonA2dpInterface.h index 408a59f801..2edf6319db 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonA2dpInterface.h +++ b/dom/bluetooth/bluedroid/BluetoothDaemonA2dpInterface.h @@ -10,6 +10,7 @@ #include "BluetoothDaemonHelpers.h" #include "BluetoothInterface.h" #include "BluetoothInterfaceHelpers.h" +#include "mozilla/ipc/DaemonRunnables.h" BEGIN_BLUETOOTH_NAMESPACE @@ -30,7 +31,7 @@ public: static const int MAX_NUM_CLIENTS; - virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0; + virtual nsresult Send(DaemonSocketPDU* aPDU, void* aUserData) = 0; virtual nsresult RegisterModule(uint8_t aId, uint8_t aMode, uint32_t aMaxNumClients, @@ -52,37 +53,38 @@ public: BluetoothA2dpResultHandler* aRes); protected: - nsresult Send(BluetoothDaemonPDU* aPDU, + nsresult Send(DaemonSocketPDU* aPDU, BluetoothA2dpResultHandler* aRes); - void HandleSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData); + void HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); // // Responses // - typedef BluetoothResultRunnable0 + typedef mozilla::ipc::DaemonResultRunnable0< + BluetoothA2dpResultHandler, void> ResultRunnable; - typedef BluetoothResultRunnable1 + typedef mozilla::ipc::DaemonResultRunnable1< + BluetoothA2dpResultHandler, void, BluetoothStatus, BluetoothStatus> ErrorRunnable; - void ErrorRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ErrorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothA2dpResultHandler* aRes); - void ConnectRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ConnectRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothA2dpResultHandler* aRes); - void DisconnectRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void DisconnectRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothA2dpResultHandler* aRes); - void HandleRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void HandleRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); // @@ -91,40 +93,36 @@ protected: class NotificationHandlerWrapper; - typedef BluetoothNotificationRunnable2 + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, BluetoothA2dpConnectionState, nsString, + BluetoothA2dpConnectionState, const nsAString&> ConnectionStateNotification; - typedef BluetoothNotificationRunnable2 + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, BluetoothA2dpAudioState, nsString, + BluetoothA2dpAudioState, const nsAString&> AudioStateNotification; - typedef BluetoothNotificationRunnable3 + typedef mozilla::ipc::DaemonNotificationRunnable3< + NotificationHandlerWrapper, void, nsString, uint32_t, uint8_t, + const nsAString&, uint32_t, uint8_t> AudioConfigNotification; class ConnectionStateInitOp; class AudioStateInitOp; class AudioConfigInitOp; - void ConnectionStateNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ConnectionStateNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void AudioStateNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void AudioStateNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void AudioConfigNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void AudioConfigNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void HandleNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void HandleNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); static BluetoothA2dpNotificationHandler* sNotificationHandler; diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.cpp index 479e792d2c..8335f993f8 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.cpp @@ -27,7 +27,7 @@ BluetoothDaemonAvrcpModule::SetNotificationHandler( } nsresult -BluetoothDaemonAvrcpModule::Send(BluetoothDaemonPDU* aPDU, +BluetoothDaemonAvrcpModule::Send(DaemonSocketPDU* aPDU, BluetoothAvrcpResultHandler* aRes) { if (aRes) { @@ -37,11 +37,11 @@ BluetoothDaemonAvrcpModule::Send(BluetoothDaemonPDU* aPDU, } void -BluetoothDaemonAvrcpModule::HandleSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData) +BluetoothDaemonAvrcpModule::HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonAvrcpModule::* const HandleOp[])( - const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&, void*) = { + const DaemonSocketPDUHeader&, DaemonSocketPDU&, void*) = { INIT_ARRAY_AT(0, &BluetoothDaemonAvrcpModule::HandleRsp), INIT_ARRAY_AT(1, &BluetoothDaemonAvrcpModule::HandleNtf), }; @@ -63,8 +63,8 @@ BluetoothDaemonAvrcpModule::GetPlayStatusRspCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_PLAY_STATUS_RSP, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_PLAY_STATUS_RSP, 1 + // Play status 4 + // Duration 4)); // Position @@ -88,8 +88,8 @@ BluetoothDaemonAvrcpModule::ListPlayerAppAttrRspCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_LIST_PLAYER_APP_ATTR_RSP, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_LIST_PLAYER_APP_ATTR_RSP, 1 + // # Attributes aNumAttr)); // Player attributes @@ -113,8 +113,8 @@ BluetoothDaemonAvrcpModule::ListPlayerAppValueRspCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_LIST_PLAYER_APP_VALUE_RSP, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_LIST_PLAYER_APP_VALUE_RSP, 1 + // # Values aNumVal)); // Player values @@ -138,8 +138,8 @@ BluetoothDaemonAvrcpModule::GetPlayerAppValueRspCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_PLAYER_APP_VALUE_RSP, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_PLAYER_APP_VALUE_RSP, 1 + // # Pairs 2 * aNumAttrs)); // Attribute-value pairs nsresult rv = PackPDU( @@ -163,8 +163,8 @@ BluetoothDaemonAvrcpModule::GetPlayerAppAttrTextRspCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_PLAYER_APP_ATTR_TEXT_RSP, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_PLAYER_APP_ATTR_TEXT_RSP, 0)); // Dynamically allocated nsresult rv = PackPDU( PackConversion(aNumAttr), @@ -187,8 +187,8 @@ BluetoothDaemonAvrcpModule::GetPlayerAppValueTextRspCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_PLAYER_APP_VALUE_TEXT_RSP, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_PLAYER_APP_VALUE_TEXT_RSP, 0)); // Dynamically allocated nsresult rv = PackPDU( PackConversion(aNumVal), @@ -211,8 +211,8 @@ BluetoothDaemonAvrcpModule::GetElementAttrRspCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_ELEMENT_ATTR_RSP, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_ELEMENT_ATTR_RSP, 0)); // Dynamically allocated nsresult rv = PackPDU( aNumAttr, @@ -234,8 +234,8 @@ BluetoothDaemonAvrcpModule::SetPlayerAppValueRspCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_SET_PLAYER_APP_VALUE_RSP, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_PLAYER_APP_VALUE_RSP, 1)); // Status code nsresult rv = PackPDU(aRspStatus, *pdu); @@ -258,8 +258,8 @@ BluetoothDaemonAvrcpModule::RegisterNotificationRspCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_REGISTER_NOTIFICATION_RSP, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_REGISTER_NOTIFICATION_RSP, 1 + // Event 1 + // Type 1 + // Data length @@ -284,8 +284,8 @@ BluetoothDaemonAvrcpModule::SetVolumeCmd(uint8_t aVolume, { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_SET_VOLUME, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_VOLUME, 1)); // Volume nsresult rv = PackPDU(aVolume, *pdu); @@ -305,8 +305,8 @@ BluetoothDaemonAvrcpModule::SetVolumeCmd(uint8_t aVolume, void BluetoothDaemonAvrcpModule::ErrorRsp( - const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) + const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes) { ErrorRunnable::Dispatch( aRes, &BluetoothAvrcpResultHandler::OnError, UnpackPDUInitOp(aPDU)); @@ -314,8 +314,8 @@ BluetoothDaemonAvrcpModule::ErrorRsp( void BluetoothDaemonAvrcpModule::GetPlayStatusRspRsp( - const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) + const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes) { ResultRunnable::Dispatch( aRes, &BluetoothAvrcpResultHandler::GetPlayStatusRsp, @@ -324,8 +324,8 @@ BluetoothDaemonAvrcpModule::GetPlayStatusRspRsp( void BluetoothDaemonAvrcpModule::ListPlayerAppAttrRspRsp( - const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) + const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes) { ResultRunnable::Dispatch( aRes, &BluetoothAvrcpResultHandler::ListPlayerAppAttrRsp, @@ -334,8 +334,8 @@ BluetoothDaemonAvrcpModule::ListPlayerAppAttrRspRsp( void BluetoothDaemonAvrcpModule::ListPlayerAppValueRspRsp( - const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) + const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes) { ResultRunnable::Dispatch( aRes, &BluetoothAvrcpResultHandler::ListPlayerAppValueRsp, @@ -344,8 +344,8 @@ BluetoothDaemonAvrcpModule::ListPlayerAppValueRspRsp( void BluetoothDaemonAvrcpModule::GetPlayerAppValueRspRsp( - const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) + const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes) { ResultRunnable::Dispatch( aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueRsp, @@ -354,8 +354,8 @@ BluetoothDaemonAvrcpModule::GetPlayerAppValueRspRsp( void BluetoothDaemonAvrcpModule::GetPlayerAppAttrTextRspRsp( - const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) + const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes) { ResultRunnable::Dispatch( aRes, &BluetoothAvrcpResultHandler::GetPlayerAppAttrTextRsp, @@ -364,8 +364,8 @@ BluetoothDaemonAvrcpModule::GetPlayerAppAttrTextRspRsp( void BluetoothDaemonAvrcpModule::GetPlayerAppValueTextRspRsp( - const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) + const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes) { ResultRunnable::Dispatch( aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueTextRsp, @@ -374,8 +374,8 @@ BluetoothDaemonAvrcpModule::GetPlayerAppValueTextRspRsp( void BluetoothDaemonAvrcpModule::GetElementAttrRspRsp( - const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) + const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes) { ResultRunnable::Dispatch( aRes, &BluetoothAvrcpResultHandler::GetElementAttrRsp, @@ -384,8 +384,8 @@ BluetoothDaemonAvrcpModule::GetElementAttrRspRsp( void BluetoothDaemonAvrcpModule::SetPlayerAppValueRspRsp( - const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) + const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes) { ResultRunnable::Dispatch( aRes, &BluetoothAvrcpResultHandler::SetPlayerAppValueRsp, @@ -394,8 +394,8 @@ BluetoothDaemonAvrcpModule::SetPlayerAppValueRspRsp( void BluetoothDaemonAvrcpModule::RegisterNotificationRspRsp( - const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) + const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes) { ResultRunnable::Dispatch( aRes, &BluetoothAvrcpResultHandler::RegisterNotificationRsp, @@ -404,8 +404,8 @@ BluetoothDaemonAvrcpModule::RegisterNotificationRspRsp( void BluetoothDaemonAvrcpModule::SetVolumeRsp( - const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) + const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes) { ResultRunnable::Dispatch( aRes, &BluetoothAvrcpResultHandler::SetVolume, @@ -414,12 +414,12 @@ BluetoothDaemonAvrcpModule::SetVolumeRsp( void BluetoothDaemonAvrcpModule::HandleRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonAvrcpModule::* const HandleRsp[])( - const BluetoothDaemonPDUHeader&, - BluetoothDaemonPDU&, + const DaemonSocketPDUHeader&, + DaemonSocketPDU&, BluetoothAvrcpResultHandler*) = { INIT_ARRAY_AT(OPCODE_ERROR, &BluetoothDaemonAvrcpModule::ErrorRsp), @@ -485,14 +485,14 @@ class BluetoothDaemonAvrcpModule::RemoteFeatureInitOp final : private PDUInitOp { public: - RemoteFeatureInitOp(BluetoothDaemonPDU& aPDU) + RemoteFeatureInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } nsresult operator () (nsString& aArg1, unsigned long& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read address */ nsresult rv = UnpackPDU( @@ -515,7 +515,7 @@ public: void BluetoothDaemonAvrcpModule::RemoteFeatureNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { RemoteFeatureNotification::Dispatch( &BluetoothAvrcpNotificationHandler::RemoteFeatureNotification, @@ -524,7 +524,7 @@ BluetoothDaemonAvrcpModule::RemoteFeatureNtf( void BluetoothDaemonAvrcpModule::GetPlayStatusNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { GetPlayStatusNotification::Dispatch( &BluetoothAvrcpNotificationHandler::GetPlayStatusNotification, @@ -533,7 +533,7 @@ BluetoothDaemonAvrcpModule::GetPlayStatusNtf( void BluetoothDaemonAvrcpModule::ListPlayerAppAttrNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ListPlayerAppAttrNotification::Dispatch( &BluetoothAvrcpNotificationHandler::ListPlayerAppAttrNotification, @@ -542,7 +542,7 @@ BluetoothDaemonAvrcpModule::ListPlayerAppAttrNtf( void BluetoothDaemonAvrcpModule::ListPlayerAppValuesNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ListPlayerAppValuesNotification::Dispatch( &BluetoothAvrcpNotificationHandler::ListPlayerAppValuesNotification, @@ -554,7 +554,7 @@ class BluetoothDaemonAvrcpModule::GetPlayerAppValueInitOp final : private PDUInitOp { public: - GetPlayerAppValueInitOp(BluetoothDaemonPDU& aPDU) + GetPlayerAppValueInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -562,7 +562,7 @@ public: operator () (uint8_t& aArg1, nsAutoArrayPtr& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read number of attributes */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -583,7 +583,7 @@ public: void BluetoothDaemonAvrcpModule::GetPlayerAppValueNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { GetPlayerAppValueNotification::Dispatch( &BluetoothAvrcpNotificationHandler::GetPlayerAppValueNotification, @@ -595,7 +595,7 @@ class BluetoothDaemonAvrcpModule::GetPlayerAppAttrsTextInitOp final : private PDUInitOp { public: - GetPlayerAppAttrsTextInitOp(BluetoothDaemonPDU& aPDU) + GetPlayerAppAttrsTextInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -603,7 +603,7 @@ public: operator () (uint8_t& aArg1, nsAutoArrayPtr& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read number of attributes */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -624,7 +624,7 @@ public: void BluetoothDaemonAvrcpModule::GetPlayerAppAttrsTextNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { GetPlayerAppAttrsTextNotification::Dispatch( &BluetoothAvrcpNotificationHandler::GetPlayerAppAttrsTextNotification, @@ -636,7 +636,7 @@ class BluetoothDaemonAvrcpModule::GetPlayerAppValuesTextInitOp final : private PDUInitOp { public: - GetPlayerAppValuesTextInitOp(BluetoothDaemonPDU& aPDU) + GetPlayerAppValuesTextInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -644,7 +644,7 @@ public: operator () (uint8_t& aArg1, uint8_t& aArg2, nsAutoArrayPtr& aArg3) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read attribute */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -670,7 +670,7 @@ public: void BluetoothDaemonAvrcpModule::GetPlayerAppValuesTextNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { GetPlayerAppValuesTextNotification::Dispatch( &BluetoothAvrcpNotificationHandler::GetPlayerAppValuesTextNotification, @@ -679,7 +679,7 @@ BluetoothDaemonAvrcpModule::GetPlayerAppValuesTextNtf( void BluetoothDaemonAvrcpModule::SetPlayerAppValueNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { SetPlayerAppValueNotification::Dispatch( &BluetoothAvrcpNotificationHandler::SetPlayerAppValueNotification, @@ -691,7 +691,7 @@ class BluetoothDaemonAvrcpModule::GetElementAttrInitOp final : private PDUInitOp { public: - GetElementAttrInitOp(BluetoothDaemonPDU& aPDU) + GetElementAttrInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -699,7 +699,7 @@ public: operator () (uint8_t& aArg1, nsAutoArrayPtr& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read number of attributes */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -720,7 +720,7 @@ public: void BluetoothDaemonAvrcpModule::GetElementAttrNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { GetElementAttrNotification::Dispatch( &BluetoothAvrcpNotificationHandler::GetElementAttrNotification, @@ -729,7 +729,7 @@ BluetoothDaemonAvrcpModule::GetElementAttrNtf( void BluetoothDaemonAvrcpModule::RegisterNotificationNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { RegisterNotificationNotification::Dispatch( &BluetoothAvrcpNotificationHandler::RegisterNotificationNotification, @@ -739,7 +739,7 @@ BluetoothDaemonAvrcpModule::RegisterNotificationNtf( #if ANDROID_VERSION >= 19 void BluetoothDaemonAvrcpModule::VolumeChangeNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { VolumeChangeNotification::Dispatch( &BluetoothAvrcpNotificationHandler::VolumeChangeNotification, @@ -751,14 +751,14 @@ class BluetoothDaemonAvrcpModule::PassthroughCmdInitOp final : private PDUInitOp { public: - PassthroughCmdInitOp(BluetoothDaemonPDU& aPDU) + PassthroughCmdInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } nsresult operator () (int& aArg1, int& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); nsresult rv = UnpackPDU(pdu, UnpackConversion(aArg1)); if (NS_FAILED(rv)) { @@ -775,7 +775,7 @@ public: void BluetoothDaemonAvrcpModule::PassthroughCmdNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { PassthroughCmdNotification::Dispatch( &BluetoothAvrcpNotificationHandler::PassthroughCmdNotification, @@ -785,11 +785,11 @@ BluetoothDaemonAvrcpModule::PassthroughCmdNtf( void BluetoothDaemonAvrcpModule::HandleNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonAvrcpModule::* const HandleNtf[])( - const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&) = { + const DaemonSocketPDUHeader&, DaemonSocketPDU&) = { #if ANDROID_VERSION >= 19 INIT_ARRAY_AT(0, &BluetoothDaemonAvrcpModule::RemoteFeatureNtf), INIT_ARRAY_AT(1, &BluetoothDaemonAvrcpModule::GetPlayStatusNtf), @@ -1089,8 +1089,8 @@ void BluetoothDaemonAvrcpInterface::DispatchError( BluetoothAvrcpResultHandler* aRes, BluetoothStatus aStatus) { - BluetoothResultRunnable1::Dispatch( + DaemonResultRunnable1::Dispatch( aRes, &BluetoothAvrcpResultHandler::OnError, ConstantInitOp1(aStatus)); } diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.h b/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.h index 5f41bc4509..4916196e78 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.h +++ b/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.h @@ -10,6 +10,7 @@ #include "BluetoothDaemonHelpers.h" #include "BluetoothInterface.h" #include "BluetoothInterfaceHelpers.h" +#include "mozilla/ipc/DaemonRunnables.h" BEGIN_BLUETOOTH_NAMESPACE @@ -62,7 +63,7 @@ public: static const int MAX_NUM_CLIENTS; - virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0; + virtual nsresult Send(DaemonSocketPDU* aPDU, void* aUserData) = 0; virtual nsresult RegisterModule(uint8_t aId, uint8_t aMode, uint32_t aMaxNumClients, @@ -116,69 +117,70 @@ public: nsresult SetVolumeCmd(uint8_t aVolume, BluetoothAvrcpResultHandler* aRes); protected: - nsresult Send(BluetoothDaemonPDU* aPDU, + nsresult Send(DaemonSocketPDU* aPDU, BluetoothAvrcpResultHandler* aRes); - void HandleSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData); + void HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); // // Responses // - typedef BluetoothResultRunnable0 + typedef mozilla::ipc::DaemonResultRunnable0< + BluetoothAvrcpResultHandler, void> ResultRunnable; - typedef BluetoothResultRunnable1 + typedef mozilla::ipc::DaemonResultRunnable1< + BluetoothAvrcpResultHandler, void, BluetoothStatus, BluetoothStatus> ErrorRunnable; - void ErrorRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ErrorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes); - void GetPlayStatusRspRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void GetPlayStatusRspRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes); - void ListPlayerAppAttrRspRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ListPlayerAppAttrRspRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes); - void ListPlayerAppValueRspRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ListPlayerAppValueRspRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes); - void GetPlayerAppValueRspRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void GetPlayerAppValueRspRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes); - void GetPlayerAppAttrTextRspRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void GetPlayerAppAttrTextRspRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes); - void GetPlayerAppValueTextRspRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void GetPlayerAppValueTextRspRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes); - void GetElementAttrRspRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void GetElementAttrRspRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes); - void SetPlayerAppValueRspRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void SetPlayerAppValueRspRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes); - void RegisterNotificationRspRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void RegisterNotificationRspRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes); - void SetVolumeRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void SetVolumeRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothAvrcpResultHandler* aRes); - void HandleRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void HandleRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); // @@ -187,57 +189,61 @@ protected: class NotificationHandlerWrapper; - typedef BluetoothNotificationRunnable2 + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, nsString, unsigned long, + const nsAString&> RemoteFeatureNotification; - typedef BluetoothNotificationRunnable0 + typedef mozilla::ipc::DaemonNotificationRunnable0< + NotificationHandlerWrapper, void> GetPlayStatusNotification; - typedef BluetoothNotificationRunnable0 + typedef mozilla::ipc::DaemonNotificationRunnable0< + NotificationHandlerWrapper, void> ListPlayerAppAttrNotification; - typedef BluetoothNotificationRunnable1 + typedef mozilla::ipc::DaemonNotificationRunnable1< + NotificationHandlerWrapper, void, BluetoothAvrcpPlayerAttribute> ListPlayerAppValuesNotification; - typedef BluetoothNotificationRunnable2, + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, uint8_t, + nsAutoArrayPtr, uint8_t, const BluetoothAvrcpPlayerAttribute*> GetPlayerAppValueNotification; - typedef BluetoothNotificationRunnable2, + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, uint8_t, + nsAutoArrayPtr, uint8_t, const BluetoothAvrcpPlayerAttribute*> GetPlayerAppAttrsTextNotification; - typedef BluetoothNotificationRunnable3, uint8_t, - uint8_t, const uint8_t*> + typedef mozilla::ipc::DaemonNotificationRunnable3< + NotificationHandlerWrapper, void, uint8_t, uint8_t, + nsAutoArrayPtr, uint8_t, uint8_t, const uint8_t*> GetPlayerAppValuesTextNotification; - typedef BluetoothNotificationRunnable1 + typedef mozilla::ipc::DaemonNotificationRunnable1< + NotificationHandlerWrapper, void, BluetoothAvrcpPlayerSettings, + const BluetoothAvrcpPlayerSettings&> SetPlayerAppValueNotification; - typedef BluetoothNotificationRunnable2, + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, uint8_t, + nsAutoArrayPtr, uint8_t, const BluetoothAvrcpMediaAttribute*> GetElementAttrNotification; - typedef BluetoothNotificationRunnable2 + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, BluetoothAvrcpEvent, uint32_t> RegisterNotificationNotification; - typedef BluetoothNotificationRunnable2 + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, uint8_t, uint8_t> VolumeChangeNotification; - typedef BluetoothNotificationRunnable2 + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, int, int> PassthroughCmdNotification; class GetElementAttrInitOp; @@ -247,44 +253,44 @@ protected: class PassthroughCmdInitOp; class RemoteFeatureInitOp; - void RemoteFeatureNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void RemoteFeatureNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void GetPlayStatusNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void GetPlayStatusNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ListPlayerAppAttrNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ListPlayerAppAttrNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ListPlayerAppValuesNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ListPlayerAppValuesNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void GetPlayerAppValueNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void GetPlayerAppValueNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void GetPlayerAppAttrsTextNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void GetPlayerAppAttrsTextNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void GetPlayerAppValuesTextNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void GetPlayerAppValuesTextNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void SetPlayerAppValueNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void SetPlayerAppValueNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void GetElementAttrNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void GetElementAttrNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void RegisterNotificationNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void RegisterNotificationNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void VolumeChangeNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void VolumeChangeNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void PassthroughCmdNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void PassthroughCmdNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void HandleNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void HandleNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); static BluetoothAvrcpNotificationHandler* sNotificationHandler; diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonConnector.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonConnector.cpp index ca3a18646c..ecf382a929 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonConnector.cpp +++ b/dom/bluetooth/bluedroid/BluetoothDaemonConnector.cpp @@ -8,6 +8,7 @@ #include "BluetoothDaemonConnector.h" #include #include +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR #include "nsThreadUtils.h" BEGIN_BLUETOOTH_NAMESPACE @@ -15,10 +16,14 @@ BEGIN_BLUETOOTH_NAMESPACE BluetoothDaemonConnector::BluetoothDaemonConnector( const nsACString& aSocketName) : mSocketName(aSocketName) -{ } +{ + MOZ_COUNT_CTOR_INHERITED(BluetoothDaemonConnector, UnixSocketConnector); +} BluetoothDaemonConnector::~BluetoothDaemonConnector() -{ } +{ + MOZ_COUNT_CTOR_INHERITED(BluetoothDaemonConnector, UnixSocketConnector); +} nsresult BluetoothDaemonConnector::CreateSocket(int& aFd) const diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonGattInterface.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonGattInterface.cpp index 78d78bffce..629796afae 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonGattInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothDaemonGattInterface.cpp @@ -27,7 +27,7 @@ BluetoothDaemonGattModule::SetNotificationHandler( } nsresult -BluetoothDaemonGattModule::Send(BluetoothDaemonPDU* aPDU, +BluetoothDaemonGattModule::Send(DaemonSocketPDU* aPDU, BluetoothGattResultHandler* aRes) { if (aRes) { @@ -37,7 +37,7 @@ BluetoothDaemonGattModule::Send(BluetoothDaemonPDU* aPDU, } nsresult -BluetoothDaemonGattModule::Send(BluetoothDaemonPDU* aPDU, +BluetoothDaemonGattModule::Send(DaemonSocketPDU* aPDU, BluetoothGattClientResultHandler* aRes) { if (aRes) { @@ -46,12 +46,20 @@ BluetoothDaemonGattModule::Send(BluetoothDaemonPDU* aPDU, return Send(aPDU, static_cast(aRes)); } +nsresult +BluetoothDaemonGattModule::Send(DaemonSocketPDU* aPDU, + BluetoothGattServerResultHandler* aRes) +{ + aRes->AddRef(); // Keep reference for response + return Send(aPDU, static_cast(aRes)); +} + void -BluetoothDaemonGattModule::HandleSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData) +BluetoothDaemonGattModule::HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonGattModule::* const HandleOp[])( - const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&, void*) = { + const DaemonSocketPDUHeader&, DaemonSocketPDU&, void*) = { INIT_ARRAY_AT(0, &BluetoothDaemonGattModule::HandleRsp), INIT_ARRAY_AT(1, &BluetoothDaemonGattModule::HandleNtf), }; @@ -73,9 +81,9 @@ BluetoothDaemonGattModule::ClientRegisterCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_REGISTER, - 16)); // Service UUID + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_REGISTER, + 16)); // Service UUID nsresult rv = PackPDU(aUuid, *pdu); @@ -96,9 +104,9 @@ BluetoothDaemonGattModule::ClientUnregisterCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_UNREGISTER, - 4)); // Client Interface + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_UNREGISTER, + 4)); // Client Interface nsresult rv = PackPDU(aClientIf, *pdu); if (NS_FAILED(rv)) { @@ -118,10 +126,10 @@ BluetoothDaemonGattModule::ClientScanCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_SCAN, - 4 + // Client Interface - 1)); // Start + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_SCAN, + 4 + // Client Interface + 1)); // Start nsresult rv = PackPDU(PackConversion(aClientIf), PackConversion(aStart), *pdu); @@ -143,12 +151,12 @@ BluetoothDaemonGattModule::ClientConnectCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_CONNECT, - 4 + // Client Interface - 6 + // Remote Address - 1 + // Is Direct - 4)); // Transport + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_CONNECT, + 4 + // Client Interface + 6 + // Remote Address + 1 + // Is Direct + 4)); // Transport nsresult rv = PackPDU( PackConversion(aClientIf), @@ -173,11 +181,11 @@ BluetoothDaemonGattModule::ClientDisconnectCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_DISCONNECT, - 4 + // Client Interface - 6 + // Remote Address - 4)); // Connection ID + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_DISCONNECT, + 4 + // Client Interface + 6 + // Remote Address + 4)); // Connection ID nsresult rv; rv = PackPDU(PackConversion(aClientIf), @@ -200,10 +208,10 @@ BluetoothDaemonGattModule::ClientListenCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_LISTEN, - 4 + // Client Interface - 1)); // Start + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_LISTEN, + 4 + // Client Interface + 1)); // Start nsresult rv; rv = PackPDU(PackConversion(aClientIf), @@ -226,10 +234,10 @@ BluetoothDaemonGattModule::ClientRefreshCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_REFRESH, - 4 + // Client Interface - 6)); // Remote Address + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_REFRESH, + 4 + // Client Interface + 6)); // Remote Address nsresult rv = PackPDU(PackConversion(aClientIf), PackConversion(aBdAddr), @@ -252,14 +260,16 @@ BluetoothDaemonGattModule::ClientSearchServiceCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_SEARCH_SERVICE, - 4 + // Connection ID - 1 + // Filtered - 16)); // UUID + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_SEARCH_SERVICE, + 4 + // Connection ID + 1 + // Filtered + 16)); // UUID nsresult rv = PackPDU(PackConversion(aConnId), - PackConversion(aFiltered), aUuid, *pdu); + PackConversion(aFiltered), + PackReversed(aUuid), + *pdu); if (NS_FAILED(rv)) { return rv; } @@ -279,12 +289,12 @@ BluetoothDaemonGattModule::ClientGetIncludedServiceCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_GET_INCLUDED_SERVICE, - 4 + // Connection ID - 18 + // Service ID - 1 + // Continuation - 18)); // Start Service ID + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_GET_INCLUDED_SERVICE, + 4 + // Connection ID + 18 + // Service ID + 1 + // Continuation + 18)); // Start Service ID nsresult rv = PackPDU(PackConversion(aConnId), aServiceId, PackConversion(aContinuation), @@ -308,12 +318,12 @@ BluetoothDaemonGattModule::ClientGetCharacteristicCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_GET_CHARACTERISTIC, - 4 + // Connection ID - 18 + // Service ID - 1 + // Continuation - 17)); // Start Characteristic ID + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_GET_CHARACTERISTIC, + 4 + // Connection ID + 18 + // Service ID + 1 + // Continuation + 17)); // Start Characteristic ID nsresult rv = PackPDU(PackConversion(aConnId), aServiceId, PackConversion(aContinuation), @@ -339,13 +349,13 @@ BluetoothDaemonGattModule::ClientGetDescriptorCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_GET_DESCRIPTOR, - 4 + // Connection ID - 18 + // Service ID - 17 + // Characteristic ID - 1 + // Continuation - 17)); // Start Descriptor ID + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_GET_DESCRIPTOR, + 4 + // Connection ID + 18 + // Service ID + 17 + // Characteristic ID + 1 + // Continuation + 17)); // Start Descriptor ID nsresult rv = PackPDU(PackConversion(aConnId), aServiceId, aCharId, @@ -370,12 +380,12 @@ BluetoothDaemonGattModule::ClientReadCharacteristicCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_READ_CHARACTERISTIC, - 4 + // Connection ID - 18 + // Service ID - 17 + // Characteristic ID - 4)); // Authorization + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_READ_CHARACTERISTIC, + 4 + // Connection ID + 18 + // Service ID + 17 + // Characteristic ID + 4)); // Authorization nsresult rv = PackPDU(PackConversion(aConnId), aServiceId, aCharId, aAuthReq, *pdu); @@ -399,8 +409,8 @@ BluetoothDaemonGattModule::ClientWriteCharacteristicCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_WRITE_CHARACTERISTIC, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_WRITE_CHARACTERISTIC, 0)); nsresult rv = PackPDU(PackConversion(aConnId), aServiceId, aCharId, aWriteType, @@ -425,13 +435,13 @@ BluetoothDaemonGattModule::ClientReadDescriptorCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_READ_DESCRIPTOR, - 4 + // Connection ID - 18 + // Service ID - 17 + // Characteristic ID - 17 + // Descriptor ID - 4)); // Authorization + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_READ_DESCRIPTOR, + 4 + // Connection ID + 18 + // Service ID + 17 + // Characteristic ID + 17 + // Descriptor ID + 4)); // Authorization nsresult rv = PackPDU(PackConversion(aConnId), aServiceId, aCharId, aDescriptorId, aAuthReq, *pdu); @@ -456,8 +466,8 @@ BluetoothDaemonGattModule::ClientWriteDescriptorCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_WRITE_DESCRIPTOR, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_WRITE_DESCRIPTOR, 0)); nsresult rv = PackPDU(PackConversion(aConnId), aServiceId, aCharId, aDescriptorId, aWriteType, @@ -480,10 +490,10 @@ BluetoothDaemonGattModule::ClientExecuteWriteCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_EXECUTE_WRITE, - 4 + // Connection ID - 4)); // Execute + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_EXECUTE_WRITE, + 4 + // Connection ID + 4)); // Execute nsresult rv = PackPDU(PackConversion(aConnId), PackConversion(aIsExecute), *pdu); @@ -506,12 +516,12 @@ BluetoothDaemonGattModule::ClientRegisterNotificationCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_REGISTER_NOTIFICATION, - 4 + // Client Interface - 6 + // Remote Address - 18 + // Service ID - 17)); // Characteristic ID + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_REGISTER_NOTIFICATION, + 4 + // Client Interface + 6 + // Remote Address + 18 + // Service ID + 17)); // Characteristic ID nsresult rv = PackPDU(PackConversion(aClientIf), PackConversion(aBdAddr), @@ -535,12 +545,12 @@ BluetoothDaemonGattModule::ClientDeregisterNotificationCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_DEREGISTER_NOTIFICATION, - 4 + // Client Interface - 6 + // Remote Address - 18 + // Service ID - 17)); // Characteristic ID + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_DEREGISTER_NOTIFICATION, + 4 + // Client Interface + 6 + // Remote Address + 18 + // Service ID + 17)); // Characteristic ID nsresult rv = PackPDU(PackConversion(aClientIf), PackConversion(aBdAddr), @@ -563,10 +573,10 @@ BluetoothDaemonGattModule::ClientReadRemoteRssiCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_READ_REMOTE_RSSI, - 4 + // Client Interface - 6)); // Remote Address + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_READ_REMOTE_RSSI, + 4 + // Client Interface + 6)); // Remote Address nsresult rv = PackPDU(PackConversion(aClientIf), PackConversion(aBdAddr), @@ -588,9 +598,9 @@ BluetoothDaemonGattModule::ClientGetDeviceTypeCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_GET_DEVICE_TYPE, - 6)); // Remote Address + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_GET_DEVICE_TYPE, + 6)); // Remote Address nsresult rv = PackPDU( PackConversion(aBdAddr), *pdu); @@ -616,8 +626,8 @@ BluetoothDaemonGattModule::ClientSetAdvDataCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_SET_ADV_DATA, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_SET_ADV_DATA, 0)); nsresult rv = PackPDU( PackConversion(aServerIf), @@ -648,16 +658,16 @@ BluetoothDaemonGattModule::ClientTestCommandCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLIENT_TEST_COMMAND, - 4 + // Command - 6 + // Address - 16 + // UUID - 2 + // U1 - 2 + // U2 - 2 + // U3 - 2 + // U4 - 2)); // U5 + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_TEST_COMMAND, + 4 + // Command + 6 + // Address + 16 + // UUID + 2 + // U1 + 2 + // U2 + 2 + // U3 + 2 + // U4 + 2)); // U5 nsresult rv = PackPDU( PackConversion(aCommand), @@ -675,13 +685,363 @@ BluetoothDaemonGattModule::ClientTestCommandCmd( return NS_OK; } +nsresult +BluetoothDaemonGattModule::ServerRegisterCmd( + const BluetoothUuid& aUuid, BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_REGISTER, + 16)); // Uuid + + nsresult rv = PackPDU(aUuid, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonGattModule::ServerUnregisterCmd( + int aServerIf, BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_UNREGISTER, + 4)); // Server Interface + + nsresult rv = PackPDU(PackConversion(aServerIf), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonGattModule::ServerConnectPeripheralCmd( + int aServerIf, const nsAString& aBdAddr, bool aIsDirect, + BluetoothTransport aTransport, BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_CONNECT_PERIPHERAL, + 4 + // Server Interface + 6 + // Remote Address + 1 + // Is Direct + 4)); // Transport + + nsresult rv = PackPDU( + PackConversion(aServerIf), + PackConversion(aBdAddr), + PackConversion(aIsDirect), + PackConversion(aTransport), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonGattModule::ServerDisconnectPeripheralCmd( + int aServerIf, const nsAString& aBdAddr, int aConnId, + BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_DISCONNECT_PERIPHERAL, + 4 + // Server Interface + 6 + // Remote Address + 4)); // Connection Id + + nsresult rv = PackPDU(PackConversion(aServerIf), + PackConversion(aBdAddr), + PackConversion(aConnId), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonGattModule::ServerAddServiceCmd( + int aServerIf, const BluetoothGattServiceId& aServiceId, int aNumHandles, + BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_ADD_SERVICE, + 4 + // Server Interface + 18 + // Service ID + 4)); // Number of Handles + + nsresult rv = PackPDU(PackConversion(aServerIf), aServiceId, + PackConversion(aNumHandles), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonGattModule::ServerAddIncludedServiceCmd( + int aServerIf, int aServiceHandle, int aIncludedServiceHandle, + BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_ADD_INCLUDED_SERVICE, + 4 + // Server Interface + 4 + // Service Handle + 4)); // Included Service Handle + + nsresult rv = PackPDU(PackConversion(aServerIf), + PackConversion(aServiceHandle), + PackConversion(aIncludedServiceHandle), + *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonGattModule::ServerAddCharacteristicCmd( + int aServerIf, int aServiceHandle, const BluetoothUuid& aUuid, + BluetoothGattCharProp aProperties, BluetoothGattAttrPerm aPermissions, + BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_ADD_CHARACTERISTIC, + 4 + // Server Interface + 4 + // Service Handle + 16 + // UUID + 4 + // Properties + 4)); // Permissions + + nsresult rv = PackPDU(PackConversion(aServerIf), + PackConversion(aServiceHandle), + aUuid, aProperties, aPermissions, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonGattModule::ServerAddDescriptorCmd( + int aServerIf, int aServiceHandle, const BluetoothUuid& aUuid, + BluetoothGattAttrPerm aPermissions, BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_ADD_DESCRIPTOR, + 4 + // Server Interface + 4 + // Service Handle + 16 + // UUID + 4)); // Permissions + + nsresult rv = PackPDU(PackConversion(aServerIf), + PackConversion(aServiceHandle), + aUuid, aPermissions, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonGattModule::ServerStartServiceCmd( + int aServerIf, int aServiceHandle, BluetoothTransport aTransport, + BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_START_SERVICE, + 4 + // Server Interface + 4 + // Service Handle + 4)); // Transport + + nsresult rv = PackPDU( + PackConversion(aServerIf), + PackConversion(aServiceHandle), + PackConversion(aTransport), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonGattModule::ServerStopServiceCmd( + int aServerIf, int aServiceHandle, BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_STOP_SERVICE, + 4 + // Server Interface + 4)); // Service Handle + + nsresult rv = PackPDU(PackConversion(aServerIf), + PackConversion(aServiceHandle), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonGattModule::ServerDeleteServiceCmd( + int aServerIf, int aServiceHandle, BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_DELETE_SERVICE, + 4 + // Server Interface + 4)); // Service Handle + + nsresult rv = PackPDU(PackConversion(aServerIf), + PackConversion(aServiceHandle), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonGattModule::ServerSendIndicationCmd( + int aServerIf, int aAttributeHandle, int aConnId, int aLength, bool aConfirm, + uint8_t* aValue, BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_SEND_INDICATION, + 0)); + + nsresult rv = PackPDU(PackConversion(aServerIf), + PackConversion(aAttributeHandle), + PackConversion(aConnId), + PackConversion(aLength), + PackConversion(aConfirm), + PackArray(aValue, aLength), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonGattModule::ServerSendResponseCmd( + int aConnId, int aTransId, BluetoothGattStatus aStatus, + const BluetoothGattResponse& aResponse, + BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_SEND_RESPONSE, + 0)); + + nsresult rv = PackPDU( + PackConversion(aConnId), + PackConversion(aTransId), + aResponse.mHandle, + aResponse.mOffset, + PackConversion(aResponse.mAuthReq), + PackConversion(aStatus), + aResponse.mLength, + PackArray(aResponse.mValue, aResponse.mLength), *pdu); + + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + // Responses // void BluetoothDaemonGattModule::ErrorRsp( - const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, BluetoothGattResultHandler* aRes) + const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattResultHandler* aRes) { ErrorRunnable::Dispatch( aRes, &BluetoothGattResultHandler::OnError, UnpackPDUInitOp(aPDU)); @@ -689,7 +1049,7 @@ BluetoothDaemonGattModule::ErrorRsp( void BluetoothDaemonGattModule::ClientRegisterRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -699,7 +1059,7 @@ BluetoothDaemonGattModule::ClientRegisterRsp( void BluetoothDaemonGattModule::ClientUnregisterRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -709,7 +1069,7 @@ BluetoothDaemonGattModule::ClientUnregisterRsp( void BluetoothDaemonGattModule::ClientScanRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -718,7 +1078,7 @@ BluetoothDaemonGattModule::ClientScanRsp( void BluetoothDaemonGattModule::ClientConnectRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -727,7 +1087,7 @@ BluetoothDaemonGattModule::ClientConnectRsp( void BluetoothDaemonGattModule::ClientDisconnectRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -737,7 +1097,7 @@ BluetoothDaemonGattModule::ClientDisconnectRsp( void BluetoothDaemonGattModule::ClientListenRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -746,7 +1106,7 @@ BluetoothDaemonGattModule::ClientListenRsp( void BluetoothDaemonGattModule::ClientRefreshRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -755,7 +1115,7 @@ BluetoothDaemonGattModule::ClientRefreshRsp( void BluetoothDaemonGattModule::ClientSearchServiceRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -765,7 +1125,7 @@ BluetoothDaemonGattModule::ClientSearchServiceRsp( void BluetoothDaemonGattModule::ClientGetIncludedServiceRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -775,7 +1135,7 @@ BluetoothDaemonGattModule::ClientGetIncludedServiceRsp( void BluetoothDaemonGattModule::ClientGetCharacteristicRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -785,7 +1145,7 @@ BluetoothDaemonGattModule::ClientGetCharacteristicRsp( void BluetoothDaemonGattModule::ClientGetDescriptorRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -795,7 +1155,7 @@ BluetoothDaemonGattModule::ClientGetDescriptorRsp( void BluetoothDaemonGattModule::ClientReadCharacteristicRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -805,7 +1165,7 @@ BluetoothDaemonGattModule::ClientReadCharacteristicRsp( void BluetoothDaemonGattModule::ClientWriteCharacteristicRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -815,7 +1175,7 @@ BluetoothDaemonGattModule::ClientWriteCharacteristicRsp( void BluetoothDaemonGattModule::ClientReadDescriptorRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -825,7 +1185,7 @@ BluetoothDaemonGattModule::ClientReadDescriptorRsp( void BluetoothDaemonGattModule::ClientWriteDescriptorRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -835,7 +1195,7 @@ BluetoothDaemonGattModule::ClientWriteDescriptorRsp( void BluetoothDaemonGattModule::ClientExecuteWriteRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -845,7 +1205,7 @@ BluetoothDaemonGattModule::ClientExecuteWriteRsp( void BluetoothDaemonGattModule::ClientRegisterNotificationRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -855,7 +1215,7 @@ BluetoothDaemonGattModule::ClientRegisterNotificationRsp( void BluetoothDaemonGattModule::ClientDeregisterNotificationRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -865,7 +1225,7 @@ BluetoothDaemonGattModule::ClientDeregisterNotificationRsp( void BluetoothDaemonGattModule::ClientReadRemoteRssiRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -873,19 +1233,42 @@ BluetoothDaemonGattModule::ClientReadRemoteRssiRsp( UnpackPDUInitOp(aPDU)); } +// Init operator class for ClientGetDeviceTypeRsp +class BluetoothDaemonGattModule::ClientGetDeviceTypeInitOp final + : private PDUInitOp +{ +public: + ClientGetDeviceTypeInitOp(DaemonSocketPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (BluetoothTypeOfDevice& aArg1) const + { + /* Read device type */ + nsresult rv = UnpackPDU( + GetPDU(), UnpackConversion(aArg1)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + void BluetoothDaemonGattModule::ClientGetDeviceTypeRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { - ClientResultRunnable::Dispatch( + ClientGetDeviceTypeResultRunnable::Dispatch( aRes, &BluetoothGattClientResultHandler::GetDeviceType, - UnpackPDUInitOp(aPDU)); + ClientGetDeviceTypeInitOp(aPDU)); } void BluetoothDaemonGattModule::ClientSetAdvDataRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -895,7 +1278,7 @@ BluetoothDaemonGattModule::ClientSetAdvDataRsp( void BluetoothDaemonGattModule::ClientTestCommandRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes) { ClientResultRunnable::Dispatch( @@ -903,22 +1286,152 @@ BluetoothDaemonGattModule::ClientTestCommandRsp( UnpackPDUInitOp(aPDU)); } +void +BluetoothDaemonGattModule::ServerRegisterRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes) +{ + ServerResultRunnable::Dispatch( + aRes, &BluetoothGattServerResultHandler::RegisterServer, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerUnregisterRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes) +{ + ServerResultRunnable::Dispatch( + aRes, &BluetoothGattServerResultHandler::UnregisterServer, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerConnectPeripheralRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes) +{ + ServerResultRunnable::Dispatch( + aRes, &BluetoothGattServerResultHandler::ConnectPeripheral, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerDisconnectPeripheralRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes) +{ + ServerResultRunnable::Dispatch( + aRes, &BluetoothGattServerResultHandler::DisconnectPeripheral, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerAddServiceRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes) +{ + ServerResultRunnable::Dispatch( + aRes, &BluetoothGattServerResultHandler::AddService, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerAddIncludedServiceRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes) +{ + ServerResultRunnable::Dispatch( + aRes, &BluetoothGattServerResultHandler::AddIncludedService, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerAddCharacteristicRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes) +{ + ServerResultRunnable::Dispatch( + aRes, &BluetoothGattServerResultHandler::AddCharacteristic, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerAddDescriptorRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes) +{ + ServerResultRunnable::Dispatch( + aRes, &BluetoothGattServerResultHandler::AddDescriptor, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerStartServiceRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes) +{ + ServerResultRunnable::Dispatch( + aRes, &BluetoothGattServerResultHandler::StartService, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerStopServiceRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes) +{ + ServerResultRunnable::Dispatch( + aRes, &BluetoothGattServerResultHandler::StopService, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerDeleteServiceRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes) +{ + ServerResultRunnable::Dispatch( + aRes, &BluetoothGattServerResultHandler::DeleteService, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerSendIndicationRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes) +{ + ServerResultRunnable::Dispatch( + aRes, &BluetoothGattServerResultHandler::SendIndication, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerSendResponseRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes) +{ + ServerResultRunnable::Dispatch( + aRes, &BluetoothGattServerResultHandler::SendResponse, + UnpackPDUInitOp(aPDU)); +} + void BluetoothDaemonGattModule::HandleRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonGattModule::* const HandleRsp[])( - const BluetoothDaemonPDUHeader&, - BluetoothDaemonPDU&, + const DaemonSocketPDUHeader&, + DaemonSocketPDU&, BluetoothGattResultHandler*) = { INIT_ARRAY_AT(OPCODE_ERROR, &BluetoothDaemonGattModule::ErrorRsp) }; static void (BluetoothDaemonGattModule::* const HandleClientRsp[])( - const BluetoothDaemonPDUHeader&, - BluetoothDaemonPDU&, + const DaemonSocketPDUHeader&, + DaemonSocketPDU&, BluetoothGattClientResultHandler*) = { INIT_ARRAY_AT(0, nullptr), INIT_ARRAY_AT(OPCODE_CLIENT_REGISTER, @@ -967,15 +1480,81 @@ BluetoothDaemonGattModule::HandleRsp( &BluetoothDaemonGattModule::ClientTestCommandRsp) }; + /** + * These client opcodes are added since non-trivial designated initializers + * are not supported. + * We could use a single array for GattRsp, GattClientRsp, and GattServerRsp + * after combining result handlers in Bug 1181512. + **/ + static void (BluetoothDaemonGattModule::* const HandleServerRsp[])( + const DaemonSocketPDUHeader&, + DaemonSocketPDU&, + BluetoothGattServerResultHandler*) = { + INIT_ARRAY_AT(0, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_REGISTER, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_UNREGISTER, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_SCAN, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_CONNECT, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_DISCONNECT, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_LISTEN, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_REFRESH, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_SEARCH_SERVICE, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_GET_INCLUDED_SERVICE, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_GET_CHARACTERISTIC, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_GET_DESCRIPTOR, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_READ_CHARACTERISTIC, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_WRITE_CHARACTERISTIC, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_READ_DESCRIPTOR, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_WRITE_DESCRIPTOR, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_EXECUTE_WRITE, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_REGISTER_NOTIFICATION, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_DEREGISTER_NOTIFICATION, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_READ_REMOTE_RSSI, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_GET_DEVICE_TYPE, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_SET_ADV_DATA, nullptr), + INIT_ARRAY_AT(OPCODE_CLIENT_TEST_COMMAND, nullptr), + INIT_ARRAY_AT(OPCODE_SERVER_REGISTER, + &BluetoothDaemonGattModule::ServerRegisterRsp), + INIT_ARRAY_AT(OPCODE_SERVER_UNREGISTER, + &BluetoothDaemonGattModule::ServerUnregisterRsp), + INIT_ARRAY_AT(OPCODE_SERVER_CONNECT_PERIPHERAL, + &BluetoothDaemonGattModule::ServerConnectPeripheralRsp), + INIT_ARRAY_AT(OPCODE_SERVER_DISCONNECT_PERIPHERAL, + &BluetoothDaemonGattModule::ServerDisconnectPeripheralRsp), + INIT_ARRAY_AT(OPCODE_SERVER_ADD_SERVICE, + &BluetoothDaemonGattModule::ServerAddServiceRsp), + INIT_ARRAY_AT(OPCODE_SERVER_ADD_INCLUDED_SERVICE, + &BluetoothDaemonGattModule::ServerAddIncludedServiceRsp), + INIT_ARRAY_AT(OPCODE_SERVER_ADD_CHARACTERISTIC, + &BluetoothDaemonGattModule::ServerAddCharacteristicRsp), + INIT_ARRAY_AT(OPCODE_SERVER_ADD_DESCRIPTOR, + &BluetoothDaemonGattModule::ServerAddDescriptorRsp), + INIT_ARRAY_AT(OPCODE_SERVER_START_SERVICE, + &BluetoothDaemonGattModule::ServerStartServiceRsp), + INIT_ARRAY_AT(OPCODE_SERVER_STOP_SERVICE, + &BluetoothDaemonGattModule::ServerStopServiceRsp), + INIT_ARRAY_AT(OPCODE_SERVER_DELETE_SERVICE, + &BluetoothDaemonGattModule::ServerDeleteServiceRsp), + INIT_ARRAY_AT(OPCODE_SERVER_SEND_INDICATION, + &BluetoothDaemonGattModule::ServerSendIndicationRsp), + INIT_ARRAY_AT(OPCODE_SERVER_SEND_RESPONSE, + &BluetoothDaemonGattModule::ServerSendResponseRsp) + }; + MOZ_ASSERT(!NS_IsMainThread()); // I/O thread - size_t length = MOZ_ARRAY_LENGTH(HandleRsp) + - MOZ_ARRAY_LENGTH(HandleClientRsp); - bool isInGattArray = HandleRsp[aHeader.mOpcode]; - bool isInGattClientArray = HandleClientRsp[aHeader.mOpcode]; + bool isInGattArray = aHeader.mOpcode < MOZ_ARRAY_LENGTH(HandleRsp) && + HandleRsp[aHeader.mOpcode]; + bool isInGattClientArray = + aHeader.mOpcode < MOZ_ARRAY_LENGTH(HandleClientRsp) && + HandleClientRsp[aHeader.mOpcode]; - if (NS_WARN_IF(!(aHeader.mOpcode < length)) || - NS_WARN_IF(!(isInGattArray || isInGattClientArray))) { + bool isInGattServerArray = + aHeader.mOpcode < MOZ_ARRAY_LENGTH(HandleServerRsp) && + HandleServerRsp[aHeader.mOpcode]; + + if (NS_WARN_IF(!isInGattArray && !isInGattClientArray && + !isInGattServerArray)) { return; } @@ -988,13 +1567,17 @@ BluetoothDaemonGattModule::HandleRsp( already_AddRefed( static_cast(aUserData)); (this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); - } else { + } else if (isInGattClientArray) { nsRefPtr res = already_AddRefed( static_cast(aUserData)); (this->*(HandleClientRsp[aHeader.mOpcode]))(aHeader, aPDU, res); + } else { // isInGattServerArray + nsRefPtr res = + already_AddRefed( + static_cast(aUserData)); + (this->*(HandleServerRsp[aHeader.mOpcode]))(aHeader, aPDU, res); } - } // Notifications @@ -1028,9 +1611,23 @@ public: } }; +// Returns the current notification handler to a notification runnable +class BluetoothDaemonGattModule::ServerNotificationHandlerWrapper final +{ +public: + typedef BluetoothGattServerNotificationHandler ObjectType; + + static ObjectType* GetInstance() + { + MOZ_ASSERT(NS_IsMainThread()); + + return sNotificationHandler; + } +}; + void BluetoothDaemonGattModule::ClientRegisterNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientRegisterNotification::Dispatch( &BluetoothGattClientNotificationHandler::RegisterClientNotification, @@ -1042,7 +1639,7 @@ class BluetoothDaemonGattModule::ClientScanResultInitOp final : private PDUInitOp { public: - ClientScanResultInitOp(BluetoothDaemonPDU& aPDU) + ClientScanResultInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -1051,7 +1648,7 @@ public: int& aArg2, BluetoothGattAdvData& aArg3) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read address */ nsresult rv = UnpackPDU( @@ -1083,7 +1680,7 @@ public: void BluetoothDaemonGattModule::ClientScanResultNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientScanResultNotification::Dispatch( &BluetoothGattClientNotificationHandler::ScanResultNotification, @@ -1095,7 +1692,7 @@ class BluetoothDaemonGattModule::ClientConnectDisconnectInitOp final : private PDUInitOp { public: - ClientConnectDisconnectInitOp(BluetoothDaemonPDU& aPDU) + ClientConnectDisconnectInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -1105,7 +1702,7 @@ public: int& aArg3, nsString& aArg4) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read connection ID */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -1136,7 +1733,7 @@ public: void BluetoothDaemonGattModule::ClientConnectNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientConnectNotification::Dispatch( &BluetoothGattClientNotificationHandler::ConnectNotification, @@ -1145,7 +1742,7 @@ BluetoothDaemonGattModule::ClientConnectNtf( void BluetoothDaemonGattModule::ClientDisconnectNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientDisconnectNotification::Dispatch( &BluetoothGattClientNotificationHandler::DisconnectNotification, @@ -1154,7 +1751,7 @@ BluetoothDaemonGattModule::ClientDisconnectNtf( void BluetoothDaemonGattModule::ClientSearchCompleteNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientSearchCompleteNotification::Dispatch( &BluetoothGattClientNotificationHandler::SearchCompleteNotification, @@ -1163,7 +1760,7 @@ BluetoothDaemonGattModule::ClientSearchCompleteNtf( void BluetoothDaemonGattModule::ClientSearchResultNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientSearchResultNotification::Dispatch( &BluetoothGattClientNotificationHandler::SearchResultNotification, @@ -1172,7 +1769,7 @@ BluetoothDaemonGattModule::ClientSearchResultNtf( void BluetoothDaemonGattModule::ClientGetCharacteristicNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientGetCharacteristicNotification::Dispatch( &BluetoothGattClientNotificationHandler::GetCharacteristicNotification, @@ -1181,7 +1778,7 @@ BluetoothDaemonGattModule::ClientGetCharacteristicNtf( void BluetoothDaemonGattModule::ClientGetDescriptorNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientGetDescriptorNotification::Dispatch( &BluetoothGattClientNotificationHandler::GetDescriptorNotification, @@ -1190,7 +1787,7 @@ BluetoothDaemonGattModule::ClientGetDescriptorNtf( void BluetoothDaemonGattModule::ClientGetIncludedServiceNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientGetIncludedServiceNotification::Dispatch( &BluetoothGattClientNotificationHandler::GetIncludedServiceNotification, @@ -1199,7 +1796,7 @@ BluetoothDaemonGattModule::ClientGetIncludedServiceNtf( void BluetoothDaemonGattModule::ClientRegisterNotificationNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientRegisterNotificationNotification::Dispatch( &BluetoothGattClientNotificationHandler::RegisterNotificationNotification, @@ -1208,7 +1805,7 @@ BluetoothDaemonGattModule::ClientRegisterNotificationNtf( void BluetoothDaemonGattModule::ClientNotifyNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientNotifyNotification::Dispatch( &BluetoothGattClientNotificationHandler::NotifyNotification, @@ -1217,7 +1814,7 @@ BluetoothDaemonGattModule::ClientNotifyNtf( void BluetoothDaemonGattModule::ClientReadCharacteristicNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientReadCharacteristicNotification::Dispatch( &BluetoothGattClientNotificationHandler::ReadCharacteristicNotification, @@ -1226,7 +1823,7 @@ BluetoothDaemonGattModule::ClientReadCharacteristicNtf( void BluetoothDaemonGattModule::ClientWriteCharacteristicNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientWriteCharacteristicNotification::Dispatch( &BluetoothGattClientNotificationHandler::WriteCharacteristicNotification, @@ -1235,7 +1832,7 @@ BluetoothDaemonGattModule::ClientWriteCharacteristicNtf( void BluetoothDaemonGattModule::ClientReadDescriptorNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientReadDescriptorNotification::Dispatch( &BluetoothGattClientNotificationHandler::ReadDescriptorNotification, @@ -1244,7 +1841,7 @@ BluetoothDaemonGattModule::ClientReadDescriptorNtf( void BluetoothDaemonGattModule::ClientWriteDescriptorNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientWriteDescriptorNotification::Dispatch( &BluetoothGattClientNotificationHandler::WriteDescriptorNotification, @@ -1253,7 +1850,7 @@ BluetoothDaemonGattModule::ClientWriteDescriptorNtf( void BluetoothDaemonGattModule::ClientExecuteWriteNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientExecuteWriteNotification::Dispatch( &BluetoothGattClientNotificationHandler::ExecuteWriteNotification, @@ -1265,7 +1862,7 @@ class BluetoothDaemonGattModule::ClientReadRemoteRssiInitOp final : private PDUInitOp { public: - ClientReadRemoteRssiInitOp(BluetoothDaemonPDU& aPDU) + ClientReadRemoteRssiInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -1275,7 +1872,7 @@ public: int& aArg3, BluetoothGattStatus& aArg4) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read client interface */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -1305,7 +1902,7 @@ public: void BluetoothDaemonGattModule::ClientReadRemoteRssiNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientReadRemoteRssiNotification::Dispatch( &BluetoothGattClientNotificationHandler::ReadRemoteRssiNotification, @@ -1314,20 +1911,356 @@ BluetoothDaemonGattModule::ClientReadRemoteRssiNtf( void BluetoothDaemonGattModule::ClientListenNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClientListenNotification::Dispatch( &BluetoothGattClientNotificationHandler::ListenNotification, UnpackPDUInitOp(aPDU)); } +void +BluetoothDaemonGattModule::ServerRegisterNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + ServerRegisterNotification::Dispatch( + &BluetoothGattServerNotificationHandler::RegisterServerNotification, + UnpackPDUInitOp(aPDU)); +} + +// Init operator class for ServerConnectionNotification +class BluetoothDaemonGattModule::ServerConnectionInitOp final + : private PDUInitOp +{ +public: + ServerConnectionInitOp(DaemonSocketPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (int& aArg1, + int& aArg2, + bool& aArg3, + nsString& aArg4) const + { + DaemonSocketPDU& pdu = GetPDU(); + + /* Read connection ID */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + /* Read server interface */ + rv = UnpackPDU(pdu, aArg2); + if (NS_FAILED(rv)) { + return rv; + } + /* Read connected */ + rv = UnpackPDU(pdu, aArg3); + if (NS_FAILED(rv)) { + return rv; + } + /* Read address */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg4)); + if (NS_FAILED(rv)) { + return rv; + } + + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonGattModule::ServerConnectionNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + ServerConnectionNotification::Dispatch( + &BluetoothGattServerNotificationHandler::ConnectionNotification, + ServerConnectionInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerServiceAddedNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + ServerServiceAddedNotification::Dispatch( + &BluetoothGattServerNotificationHandler::ServiceAddedNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerIncludedServiceAddedNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + ServerIncludedServiceAddedNotification::Dispatch( + &BluetoothGattServerNotificationHandler::IncludedServiceAddedNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerCharacteristicAddedNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + ServerCharacteristicAddedNotification::Dispatch( + &BluetoothGattServerNotificationHandler::CharacteristicAddedNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerDescriptorAddedNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + ServerDescriptorAddedNotification::Dispatch( + &BluetoothGattServerNotificationHandler::DescriptorAddedNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerServiceStartedNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + ServerServiceStartedNotification::Dispatch( + &BluetoothGattServerNotificationHandler::ServiceStartedNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerServiceStoppedNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + ServerServiceStoppedNotification::Dispatch( + &BluetoothGattServerNotificationHandler::ServiceStoppedNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerServiceDeletedNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + ServerServiceDeletedNotification::Dispatch( + &BluetoothGattServerNotificationHandler::ServiceDeletedNotification, + UnpackPDUInitOp(aPDU)); +} + +// Init operator class for ServerRequestReadNotification +class BluetoothDaemonGattModule::ServerRequestReadInitOp final + : private PDUInitOp +{ +public: + ServerRequestReadInitOp(DaemonSocketPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (int& aArg1, + int& aArg2, + nsString& aArg3, + int& aArg4, + int& aArg5, + bool& aArg6) const + { + DaemonSocketPDU& pdu = GetPDU(); + + /* Read connection ID */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + /* Read trans ID */ + rv = UnpackPDU(pdu, aArg2); + if (NS_FAILED(rv)) { + return rv; + } + /* Read address */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg3)); + if (NS_FAILED(rv)) { + return rv; + } + /* Read attribute handle */ + rv = UnpackPDU(pdu, aArg4); + if (NS_FAILED(rv)) { + return rv; + } + /* Read offset */ + rv = UnpackPDU(pdu, aArg5); + if (NS_FAILED(rv)) { + return rv; + } + /* Read isLong */ + rv = UnpackPDU(pdu, aArg6); + if (NS_FAILED(rv)) { + return rv; + } + + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonGattModule::ServerRequestReadNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + ServerRequestReadNotification::Dispatch( + &BluetoothGattServerNotificationHandler::RequestReadNotification, + ServerRequestReadInitOp(aPDU)); +} + +// Init operator class for ServerRequestWriteNotification +class BluetoothDaemonGattModule::ServerRequestWriteInitOp final + : private PDUInitOp +{ +public: + ServerRequestWriteInitOp(DaemonSocketPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (int& aArg1, + int& aArg2, + nsString& aArg3, + int& aArg4, + int& aArg5, + int& aArg6, + nsAutoArrayPtr& aArg7, + bool& aArg8, + bool& aArg9) const + { + DaemonSocketPDU& pdu = GetPDU(); + + /* Read connection ID */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + /* Read trans ID */ + rv = UnpackPDU(pdu, aArg2); + if (NS_FAILED(rv)) { + return rv; + } + /* Read address */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg3)); + if (NS_FAILED(rv)) { + return rv; + } + /* Read attribute handle */ + rv = UnpackPDU(pdu, aArg4); + if (NS_FAILED(rv)) { + return rv; + } + /* Read offset */ + rv = UnpackPDU(pdu, aArg5); + if (NS_FAILED(rv)) { + return rv; + } + /* Read Length */ + rv = UnpackPDU(pdu, aArg6); + if (NS_FAILED(rv)) { + return rv; + } + /* Read value */ + rv = UnpackPDU(pdu, + UnpackArray(aArg7, static_cast(aArg6))); + if (NS_FAILED(rv)) { + return rv; + } + /* Read need response */ + rv = UnpackPDU(pdu, aArg8); + if (NS_FAILED(rv)) { + return rv; + } + /* Read isPrepare */ + rv = UnpackPDU(pdu, aArg9); + if (NS_FAILED(rv)) { + return rv; + } + + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonGattModule::ServerRequestWriteNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + ServerRequestWriteNotification::Dispatch( + &BluetoothGattServerNotificationHandler::RequestWriteNotification, + ServerRequestWriteInitOp(aPDU)); +} + +// Init operator class for ServerRequestExecuteWriteNotification +class BluetoothDaemonGattModule::ServerRequestExecuteWriteInitOp final + : private PDUInitOp +{ +public: + ServerRequestExecuteWriteInitOp(DaemonSocketPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (int& aArg1, + int& aArg2, + nsString& aArg3, + bool& aArg4) const + { + DaemonSocketPDU& pdu = GetPDU(); + + /* Read connection ID */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + /* Read trans ID */ + rv = UnpackPDU(pdu, aArg2); + if (NS_FAILED(rv)) { + return rv; + } + /* Read address */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg3)); + if (NS_FAILED(rv)) { + return rv; + } + /* Read execute write */ + rv = UnpackPDU(pdu, aArg4); + if (NS_FAILED(rv)) { + return rv; + } + + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonGattModule::ServerRequestExecuteWriteNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + ServerRequestExecuteWriteNotification::Dispatch( + &BluetoothGattServerNotificationHandler::RequestExecuteWriteNotification, + ServerRequestExecuteWriteInitOp(aPDU)); +} + +void +BluetoothDaemonGattModule::ServerResponseConfirmationNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + ServerResponseConfirmationNotification::Dispatch( + &BluetoothGattServerNotificationHandler::ResponseConfirmationNotification, + UnpackPDUInitOp(aPDU)); +} + void BluetoothDaemonGattModule::HandleNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonGattModule::* const HandleNtf[])( - const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&) = { + const DaemonSocketPDUHeader&, DaemonSocketPDU&) = { INIT_ARRAY_AT(0, &BluetoothDaemonGattModule::ClientRegisterNtf), INIT_ARRAY_AT(1, &BluetoothDaemonGattModule::ClientScanResultNtf), INIT_ARRAY_AT(2, &BluetoothDaemonGattModule::ClientConnectNtf), @@ -1345,7 +2278,20 @@ BluetoothDaemonGattModule::HandleNtf( INIT_ARRAY_AT(14, &BluetoothDaemonGattModule::ClientWriteDescriptorNtf), INIT_ARRAY_AT(15, &BluetoothDaemonGattModule::ClientExecuteWriteNtf), INIT_ARRAY_AT(16, &BluetoothDaemonGattModule::ClientReadRemoteRssiNtf), - INIT_ARRAY_AT(17, &BluetoothDaemonGattModule::ClientListenNtf) + INIT_ARRAY_AT(17, &BluetoothDaemonGattModule::ClientListenNtf), + INIT_ARRAY_AT(18, &BluetoothDaemonGattModule::ServerRegisterNtf), + INIT_ARRAY_AT(19, &BluetoothDaemonGattModule::ServerConnectionNtf), + INIT_ARRAY_AT(20, &BluetoothDaemonGattModule::ServerServiceAddedNtf), + INIT_ARRAY_AT(21, &BluetoothDaemonGattModule::ServerIncludedServiceAddedNtf), + INIT_ARRAY_AT(22, &BluetoothDaemonGattModule::ServerCharacteristicAddedNtf), + INIT_ARRAY_AT(23, &BluetoothDaemonGattModule::ServerDescriptorAddedNtf), + INIT_ARRAY_AT(24, &BluetoothDaemonGattModule::ServerServiceStartedNtf), + INIT_ARRAY_AT(25, &BluetoothDaemonGattModule::ServerServiceStoppedNtf), + INIT_ARRAY_AT(26, &BluetoothDaemonGattModule::ServerServiceDeletedNtf), + INIT_ARRAY_AT(27, &BluetoothDaemonGattModule::ServerRequestReadNtf), + INIT_ARRAY_AT(28, &BluetoothDaemonGattModule::ServerRequestWriteNtf), + INIT_ARRAY_AT(29, &BluetoothDaemonGattModule::ServerRequestExecuteWriteNtf), + INIT_ARRAY_AT(30, &BluetoothDaemonGattModule::ServerResponseConfirmationNtf) }; MOZ_ASSERT(!NS_IsMainThread()); @@ -1369,6 +2315,11 @@ BluetoothDaemonGattClientInterface::BluetoothDaemonGattClientInterface( : mModule(aModule) { } +BluetoothDaemonGattServerInterface::BluetoothDaemonGattServerInterface( + BluetoothDaemonGattModule* aModule) + : mModule(aModule) +{ } + BluetoothDaemonGattInterface::BluetoothDaemonGattInterface( BluetoothDaemonGattModule* aModule) : mModule(aModule) @@ -1812,12 +2763,209 @@ BluetoothDaemonGattClientInterface::TestCommand( } } +/* Register / Unregister */ +void +BluetoothDaemonGattServerInterface::RegisterServer( + const BluetoothUuid& aUuid, BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->ServerRegisterCmd(aUuid, aRes); + + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +void +BluetoothDaemonGattServerInterface::UnregisterServer( + int aServerIf, BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->ServerUnregisterCmd(aServerIf, aRes); + + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +/* Connect / Disconnect */ +void +BluetoothDaemonGattServerInterface::ConnectPeripheral( + int aServerIf, const nsAString& aBdAddr, bool aIsDirect, /* auto connect */ + BluetoothTransport aTransport, BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->ServerConnectPeripheralCmd( + aServerIf, aBdAddr, aIsDirect, aTransport, aRes); + + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +void +BluetoothDaemonGattServerInterface::DisconnectPeripheral( + int aServerIf, const nsAString& aBdAddr, int aConnId, + BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->ServerDisconnectPeripheralCmd( + aServerIf, aBdAddr, aConnId, aRes); + + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +/* Add a services / a characteristic / a descriptor */ +void +BluetoothDaemonGattServerInterface::AddService( + int aServerIf, const BluetoothGattServiceId& aServiceId, int aNumHandles, + BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->ServerAddServiceCmd( + aServerIf, aServiceId, aNumHandles, aRes); + + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +void +BluetoothDaemonGattServerInterface::AddIncludedService( + int aServerIf, int aServiceHandle, int aIncludedServiceHandle, + BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->ServerAddIncludedServiceCmd( + aServerIf, aServiceHandle, aIncludedServiceHandle, aRes); + + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +void +BluetoothDaemonGattServerInterface::AddCharacteristic( + int aServerIf, int aServiceHandle, const BluetoothUuid& aUuid, + BluetoothGattCharProp aProperties, BluetoothGattAttrPerm aPermissions, + BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->ServerAddCharacteristicCmd( + aServerIf, aServiceHandle, aUuid, aProperties, aPermissions, aRes); + + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +void +BluetoothDaemonGattServerInterface::AddDescriptor( + int aServerIf, int aServiceHandle, const BluetoothUuid& aUuid, + BluetoothGattAttrPerm aPermissions, BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->ServerAddDescriptorCmd( + aServerIf, aServiceHandle, aUuid, aPermissions, aRes); + + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +/* Start / Stop / Delete a service */ +void +BluetoothDaemonGattServerInterface::StartService( + int aServerIf, int aServiceHandle, BluetoothTransport aTransport, + BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->ServerStartServiceCmd( + aServerIf, aServiceHandle, aTransport, aRes); + + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +void +BluetoothDaemonGattServerInterface::StopService( + int aServerIf, int aServiceHandle, BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->ServerStopServiceCmd(aServerIf, aServiceHandle, aRes); + + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +void +BluetoothDaemonGattServerInterface::DeleteService( + int aServerIf, int aServiceHandle, BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->ServerDeleteServiceCmd( + aServerIf, aServiceHandle, aRes); + + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +void +BluetoothDaemonGattServerInterface::SendIndication( + int aServerIf, int aAttributeHandle, int aConnId, + const nsTArray& aValue, bool aConfirm, + BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->ServerSendIndicationCmd( + aServerIf, aAttributeHandle, aConnId, + aValue.Length() * sizeof(uint8_t), aConfirm, + const_cast(aValue.Elements()), aRes); + + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +void +BluetoothDaemonGattServerInterface::SendResponse( + int aConnId, int aTransId, BluetoothGattStatus aStatus, + const BluetoothGattResponse& aResponse, + BluetoothGattServerResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->ServerSendResponseCmd( + aConnId, aTransId, aStatus, aResponse, aRes); + + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + void BluetoothDaemonGattClientInterface::DispatchError( BluetoothGattClientResultHandler* aRes, BluetoothStatus aStatus) { - BluetoothResultRunnable1::Dispatch( + DaemonResultRunnable1::Dispatch( aRes, &BluetoothGattResultHandler::OnError, ConstantInitOp1(aStatus)); } @@ -1834,12 +2982,34 @@ BluetoothDaemonGattClientInterface::DispatchError( DispatchError(aRes, status); } +void +BluetoothDaemonGattServerInterface::DispatchError( + BluetoothGattServerResultHandler* aRes, BluetoothStatus aStatus) +{ + DaemonResultRunnable1::Dispatch( + aRes, &BluetoothGattResultHandler::OnError, + ConstantInitOp1(aStatus)); +} + +void +BluetoothDaemonGattServerInterface::DispatchError( + BluetoothGattServerResultHandler* aRes, nsresult aRv) +{ + BluetoothStatus status; + + if (NS_WARN_IF(NS_FAILED(Convert(aRv, status)))) { + status = STATUS_FAIL; + } + DispatchError(aRes, status); +} + void BluetoothDaemonGattInterface::DispatchError( BluetoothGattResultHandler* aRes, BluetoothStatus aStatus) { - BluetoothResultRunnable1::Dispatch( + DaemonResultRunnable1::Dispatch( aRes, &BluetoothGattResultHandler::OnError, ConstantInitOp1(aStatus)); } @@ -1867,4 +3037,15 @@ BluetoothDaemonGattInterface::GetBluetoothGattClientInterface() return gattClientInterface; } +BluetoothGattServerInterface* +BluetoothDaemonGattInterface::GetBluetoothGattServerInterface() +{ + MOZ_ASSERT(mModule); + + BluetoothDaemonGattServerInterface* gattServerInterface = + new BluetoothDaemonGattServerInterface(mModule); + + return gattServerInterface; +} + END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonGattInterface.h b/dom/bluetooth/bluedroid/BluetoothDaemonGattInterface.h index f1d9da514b..7ae43c4503 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonGattInterface.h +++ b/dom/bluetooth/bluedroid/BluetoothDaemonGattInterface.h @@ -10,6 +10,7 @@ #include "BluetoothDaemonHelpers.h" #include "BluetoothInterface.h" #include "BluetoothInterfaceHelpers.h" +#include "mozilla/ipc/DaemonRunnables.h" BEGIN_BLUETOOTH_NAMESPACE @@ -45,13 +46,26 @@ public: OPCODE_CLIENT_READ_REMOTE_RSSI = 0x13, OPCODE_CLIENT_GET_DEVICE_TYPE = 0x14, OPCODE_CLIENT_SET_ADV_DATA = 0x15, - OPCODE_CLIENT_TEST_COMMAND = 0x16 - // TODO: Add server opcodes + OPCODE_CLIENT_TEST_COMMAND = 0x16, + OPCODE_SERVER_REGISTER = 0x17, + OPCODE_SERVER_UNREGISTER = 0x18, + OPCODE_SERVER_CONNECT_PERIPHERAL = 0x19, + OPCODE_SERVER_DISCONNECT_PERIPHERAL = 0x1a, + OPCODE_SERVER_ADD_SERVICE = 0x1b, + OPCODE_SERVER_ADD_INCLUDED_SERVICE = 0x1c, + OPCODE_SERVER_ADD_CHARACTERISTIC = 0x1d, + OPCODE_SERVER_ADD_DESCRIPTOR = 0x1e, + OPCODE_SERVER_START_SERVICE = 0x1f, + OPCODE_SERVER_STOP_SERVICE = 0x20, + OPCODE_SERVER_DELETE_SERVICE = 0x21, + OPCODE_SERVER_SEND_INDICATION = 0x22, + OPCODE_SERVER_SEND_RESPONSE = 0x23 + // TODO: Add L support }; static const int MAX_NUM_CLIENTS; - virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0; + virtual nsresult Send(DaemonSocketPDU* aPDU, void* aUserData) = 0; virtual nsresult RegisterModule(uint8_t aId, uint8_t aMode, uint32_t aMaxNumClients, @@ -208,129 +222,268 @@ public: const BluetoothGattTestParam& aTestParam, BluetoothGattClientResultHandler* aRes); - // TODO: Add server commands + /* Register / Unregister */ + nsresult ServerRegisterCmd(const BluetoothUuid& aUuid, + BluetoothGattServerResultHandler* aRes); + + nsresult ServerUnregisterCmd(int aServerIf, + BluetoothGattServerResultHandler* aRes); + + /* Connect / Disconnect */ + nsresult ServerConnectPeripheralCmd(int aServerIf, + const nsAString& aBdAddr, + bool aIsDirect, + BluetoothTransport aTransport, + BluetoothGattServerResultHandler* aRes); + + nsresult ServerDisconnectPeripheralCmd( + int aServerIf, + const nsAString& aBdAddr, + int aConnId, + BluetoothGattServerResultHandler* aRes); + + /* Add a services / a characteristic / a descriptor */ + nsresult ServerAddServiceCmd(int aServerIf, + const BluetoothGattServiceId& aServiceId, + int aNumHandles, + BluetoothGattServerResultHandler* aRes); + + nsresult ServerAddIncludedServiceCmd(int aServerIf, + int aServiceHandle, + int aIncludedServiceHandle, + BluetoothGattServerResultHandler* aRes); + + nsresult ServerAddCharacteristicCmd(int aServerIf, + int aServiceHandle, + const BluetoothUuid& aUuid, + BluetoothGattCharProp aProperties, + BluetoothGattAttrPerm aPermissions, + BluetoothGattServerResultHandler* aRes); + + nsresult ServerAddDescriptorCmd(int aServerIf, + int aServiceHandle, + const BluetoothUuid& aUuid, + BluetoothGattAttrPerm aPermissions, + BluetoothGattServerResultHandler* aRes); + + /* Start / Stop / Delete a service */ + nsresult ServerStartServiceCmd(int aServerIf, + int aServiceHandle, + BluetoothTransport aTransport, + BluetoothGattServerResultHandler* aRes); + + nsresult ServerStopServiceCmd(int aServerIf, + int aServiceHandle, + BluetoothGattServerResultHandler* aRes); + + nsresult ServerDeleteServiceCmd(int aServerIf, + int aServiceHandle, + BluetoothGattServerResultHandler* aRes); + + /* Send an indication or a notification */ + nsresult ServerSendIndicationCmd(int aServerIf, + int aAttributeHandle, + int aConnId, + int aLength, + bool aConfirm, + uint8_t* aValue, + BluetoothGattServerResultHandler* aRes); + + /* Send a response for an incoming indication */ + nsresult ServerSendResponseCmd(int aConnId, + int aTransId, + BluetoothGattStatus aStatus, + const BluetoothGattResponse& aResponse, + BluetoothGattServerResultHandler* aRes); + // TODO: Add L support protected: - nsresult Send(BluetoothDaemonPDU* aPDU, + nsresult Send(DaemonSocketPDU* aPDU, BluetoothGattResultHandler* aRes); - nsresult Send(BluetoothDaemonPDU* aPDU, + nsresult Send(DaemonSocketPDU* aPDU, BluetoothGattClientResultHandler* aRes); - void HandleSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData); + nsresult Send(DaemonSocketPDU* aPDU, + BluetoothGattServerResultHandler* aRes); + + void HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); // // Responses // - typedef BluetoothResultRunnable0 + typedef mozilla::ipc::DaemonResultRunnable0< + BluetoothGattClientResultHandler, void> ClientResultRunnable; - typedef BluetoothResultRunnable0 + typedef mozilla::ipc::DaemonResultRunnable1< + BluetoothGattClientResultHandler, void, + BluetoothTypeOfDevice, BluetoothTypeOfDevice> + ClientGetDeviceTypeResultRunnable; + + typedef mozilla::ipc::DaemonResultRunnable0< + BluetoothGattServerResultHandler, void> + ServerResultRunnable; + + typedef mozilla::ipc::DaemonResultRunnable0< + BluetoothGattResultHandler, void> ResultRunnable; - typedef BluetoothResultRunnable1 + typedef mozilla::ipc::DaemonResultRunnable1< + BluetoothGattResultHandler, void, BluetoothStatus, BluetoothStatus> ErrorRunnable; - void ErrorRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ErrorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattResultHandler* aRes); - void ClientRegisterRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientRegisterRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientUnregisterRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientUnregisterRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientScanRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientScanRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientConnectRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientConnectRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientDisconnectRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientDisconnectRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientListenRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientListenRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientRefreshRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientRefreshRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientSearchServiceRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientSearchServiceRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientGetIncludedServiceRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientGetIncludedServiceRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientGetCharacteristicRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientGetCharacteristicRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientGetDescriptorRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientGetDescriptorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientReadCharacteristicRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientReadCharacteristicRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientWriteCharacteristicRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientWriteCharacteristicRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientReadDescriptorRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientReadDescriptorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientWriteDescriptorRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientWriteDescriptorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientExecuteWriteRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientExecuteWriteRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientRegisterNotificationRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientRegisterNotificationRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientDeregisterNotificationRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientDeregisterNotificationRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientReadRemoteRssiRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientReadRemoteRssiRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientGetDeviceTypeRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientGetDeviceTypeRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientSetAdvDataRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientSetAdvDataRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void ClientTestCommandRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClientTestCommandRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothGattClientResultHandler* aRes); - void HandleRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, - void* aUserData); + void ServerRegisterRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes); - // TODO: Add Server responses + void ServerUnregisterRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes); + + void ServerConnectPeripheralRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes); + + void ServerDisconnectPeripheralRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes); + + void ServerAddServiceRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes); + + void ServerAddIncludedServiceRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes); + + void ServerAddCharacteristicRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes); + + void ServerAddDescriptorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes); + + void ServerStartServiceRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes); + + void ServerStopServiceRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes); + + void ServerDeleteServiceRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes); + + void ServerSendIndicationRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes); + + void ServerSendResponseRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothGattServerResultHandler* aRes); + + // TODO: Add L support + + void HandleRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + void* aUserData); // // Notifications @@ -338,44 +491,44 @@ protected: class NotificationHandlerWrapper; class ClientNotificationHandlerWrapper; + class ServerNotificationHandlerWrapper; - // GATT Client Notification - typedef BluetoothNotificationRunnable3< + typedef mozilla::ipc::DaemonNotificationRunnable3< ClientNotificationHandlerWrapper, void, BluetoothGattStatus, int, BluetoothUuid, BluetoothGattStatus, int, const BluetoothUuid&> ClientRegisterNotification; - typedef BluetoothNotificationRunnable3< + typedef mozilla::ipc::DaemonNotificationRunnable3< ClientNotificationHandlerWrapper, void, nsString, int, BluetoothGattAdvData, const nsAString&, int, const BluetoothGattAdvData&> ClientScanResultNotification; - typedef BluetoothNotificationRunnable4< + typedef mozilla::ipc::DaemonNotificationRunnable4< ClientNotificationHandlerWrapper, void, int, BluetoothGattStatus, int, nsString, int, BluetoothGattStatus, int, const nsAString&> ClientConnectNotification; - typedef BluetoothNotificationRunnable4< + typedef mozilla::ipc::DaemonNotificationRunnable4< ClientNotificationHandlerWrapper, void, int, BluetoothGattStatus, int, nsString, int, BluetoothGattStatus, int, const nsAString&> ClientDisconnectNotification; - typedef BluetoothNotificationRunnable2< + typedef mozilla::ipc::DaemonNotificationRunnable2< ClientNotificationHandlerWrapper, void, int, BluetoothGattStatus> ClientSearchCompleteNotification; - typedef BluetoothNotificationRunnable2< + typedef mozilla::ipc::DaemonNotificationRunnable2< ClientNotificationHandlerWrapper, void, int, BluetoothGattServiceId, int, const BluetoothGattServiceId&> ClientSearchResultNotification; - typedef BluetoothNotificationRunnable5< + typedef mozilla::ipc::DaemonNotificationRunnable5< ClientNotificationHandlerWrapper, void, int, BluetoothGattStatus, BluetoothGattServiceId, BluetoothGattId, BluetoothGattCharProp, @@ -383,7 +536,7 @@ protected: const BluetoothGattId&, const BluetoothGattCharProp&> ClientGetCharacteristicNotification; - typedef BluetoothNotificationRunnable5< + typedef mozilla::ipc::DaemonNotificationRunnable5< ClientNotificationHandlerWrapper, void, int, BluetoothGattStatus, BluetoothGattServiceId, BluetoothGattId, BluetoothGattId, @@ -391,14 +544,14 @@ protected: const BluetoothGattId&, const BluetoothGattId&> ClientGetDescriptorNotification; - typedef BluetoothNotificationRunnable4< + typedef mozilla::ipc::DaemonNotificationRunnable4< ClientNotificationHandlerWrapper, void, int, BluetoothGattStatus, BluetoothGattServiceId, BluetoothGattServiceId, int, BluetoothGattStatus, const BluetoothGattServiceId&, const BluetoothGattServiceId&> ClientGetIncludedServiceNotification; - typedef BluetoothNotificationRunnable5< + typedef mozilla::ipc::DaemonNotificationRunnable5< ClientNotificationHandlerWrapper, void, int, int, BluetoothGattStatus, BluetoothGattServiceId, BluetoothGattId, @@ -406,112 +559,231 @@ protected: const BluetoothGattServiceId&, const BluetoothGattId&> ClientRegisterNotificationNotification; - typedef BluetoothNotificationRunnable2< + typedef mozilla::ipc::DaemonNotificationRunnable2< ClientNotificationHandlerWrapper, void, int, BluetoothGattNotifyParam, int, const BluetoothGattNotifyParam&> ClientNotifyNotification; - typedef BluetoothNotificationRunnable3< + typedef mozilla::ipc::DaemonNotificationRunnable3< ClientNotificationHandlerWrapper, void, int, BluetoothGattStatus, BluetoothGattReadParam, int, BluetoothGattStatus, const BluetoothGattReadParam&> ClientReadCharacteristicNotification; - typedef BluetoothNotificationRunnable3< + typedef mozilla::ipc::DaemonNotificationRunnable3< ClientNotificationHandlerWrapper, void, int, BluetoothGattStatus, BluetoothGattWriteParam, int, BluetoothGattStatus, const BluetoothGattWriteParam&> ClientWriteCharacteristicNotification; - typedef BluetoothNotificationRunnable3< + typedef mozilla::ipc::DaemonNotificationRunnable3< ClientNotificationHandlerWrapper, void, int, BluetoothGattStatus, BluetoothGattReadParam, int, BluetoothGattStatus, const BluetoothGattReadParam&> ClientReadDescriptorNotification; - typedef BluetoothNotificationRunnable3< + typedef mozilla::ipc::DaemonNotificationRunnable3< ClientNotificationHandlerWrapper, void, int, BluetoothGattStatus, BluetoothGattWriteParam, int, BluetoothGattStatus, const BluetoothGattWriteParam&> ClientWriteDescriptorNotification; - typedef BluetoothNotificationRunnable2< + typedef mozilla::ipc::DaemonNotificationRunnable2< ClientNotificationHandlerWrapper, void, int, BluetoothGattStatus> ClientExecuteWriteNotification; - typedef BluetoothNotificationRunnable4< + typedef mozilla::ipc::DaemonNotificationRunnable4< ClientNotificationHandlerWrapper, void, int, nsString, int, BluetoothGattStatus, int, const nsAString&, int, BluetoothGattStatus> ClientReadRemoteRssiNotification; - typedef BluetoothNotificationRunnable2< + typedef mozilla::ipc::DaemonNotificationRunnable2< ClientNotificationHandlerWrapper, void, BluetoothGattStatus, int> ClientListenNotification; + typedef mozilla::ipc::DaemonNotificationRunnable3< + ServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int, BluetoothUuid, + BluetoothGattStatus, int, const BluetoothUuid&> + ServerRegisterNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable4< + ServerNotificationHandlerWrapper, void, + int, int, bool, nsString, + int, int, bool, const nsAString&> + ServerConnectionNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable4< + ServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int, BluetoothGattServiceId, int, + BluetoothGattStatus, int, const BluetoothGattServiceId&, int> + ServerServiceAddedNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable4< + ServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int, int, int> + ServerIncludedServiceAddedNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable5< + ServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int, BluetoothUuid, int, int, + BluetoothGattStatus, int, const BluetoothUuid&, int, int> + ServerCharacteristicAddedNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable5< + ServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int, BluetoothUuid, int, int, + BluetoothGattStatus, int, const BluetoothUuid&, int, int> + ServerDescriptorAddedNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable3< + ServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int, int> + ServerServiceStartedNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable3< + ServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int, int> + ServerServiceStoppedNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable3< + ServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int, int> + ServerServiceDeletedNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable6< + ServerNotificationHandlerWrapper, void, + int, int, nsString, int, int, bool, + int, int, const nsAString&, int, int, bool> + ServerRequestReadNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable9< + ServerNotificationHandlerWrapper, void, + int, int, nsString, int, int, int, nsAutoArrayPtr, bool, bool, + int, int, const nsAString&, int, int, int, const uint8_t*, bool, bool> + ServerRequestWriteNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable4< + ServerNotificationHandlerWrapper, void, + int, int, nsString, bool, + int, int, const nsAString&, bool> + ServerRequestExecuteWriteNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable2< + ServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int> + ServerResponseConfirmationNotification; + class ClientScanResultInitOp; class ClientConnectDisconnectInitOp; class ClientReadRemoteRssiInitOp; + class ClientGetDeviceTypeInitOp; + class ServerConnectionInitOp; + class ServerRequestReadInitOp; + class ServerRequestWriteInitOp; + class ServerRequestExecuteWriteInitOp; - void ClientRegisterNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientRegisterNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientScanResultNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientScanResultNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientConnectNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientConnectNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientDisconnectNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientDisconnectNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientSearchCompleteNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientSearchCompleteNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientSearchResultNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientSearchResultNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientGetCharacteristicNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientGetCharacteristicNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientGetDescriptorNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientGetDescriptorNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientGetIncludedServiceNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientGetIncludedServiceNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientRegisterNotificationNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientRegisterNotificationNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientNotifyNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientNotifyNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientReadCharacteristicNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientReadCharacteristicNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientWriteCharacteristicNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientWriteCharacteristicNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientReadDescriptorNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientReadDescriptorNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientWriteDescriptorNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientWriteDescriptorNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientExecuteWriteNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientExecuteWriteNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientReadRemoteRssiNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientReadRemoteRssiNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClientListenNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClientListenNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void HandleNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ServerRegisterNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void ServerConnectionNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void ServerServiceAddedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void ServerIncludedServiceAddedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void ServerCharacteristicAddedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void ServerDescriptorAddedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void ServerServiceStartedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void ServerServiceStoppedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void ServerServiceDeletedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void ServerRequestReadNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void ServerRequestWriteNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void ServerRequestExecuteWriteNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void ServerResponseConfirmationNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + // TODO: Add L support + + void HandleNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); static BluetoothGattNotificationHandler* sNotificationHandler; @@ -533,6 +805,7 @@ public: void Cleanup(BluetoothGattResultHandler* aRes); BluetoothGattClientInterface* GetBluetoothGattClientInterface(); + BluetoothGattServerInterface* GetBluetoothGattServerInterface(); private: void DispatchError(BluetoothGattResultHandler* aRes, @@ -678,7 +951,86 @@ private: BluetoothDaemonGattModule* mModule; }; -// TODO: Add GattServerInterface +class BluetoothDaemonGattServerInterface final + : public BluetoothGattServerInterface +{ +public: + BluetoothDaemonGattServerInterface(BluetoothDaemonGattModule* aModule); + + /* Register / Unregister */ + void RegisterServer(const BluetoothUuid& aUuid, + BluetoothGattServerResultHandler* aRes); + void UnregisterServer(int aServerIf, + BluetoothGattServerResultHandler* aRes); + + /* Connect / Disconnect */ + void ConnectPeripheral(int aServerIf, + const nsAString& aBdAddr, + bool aIsDirect, /* auto connect */ + BluetoothTransport aTransport, + BluetoothGattServerResultHandler* aRes); + void DisconnectPeripheral(int aServerIf, + const nsAString& aBdAddr, + int aConnId, + BluetoothGattServerResultHandler* aRes); + + /* Add a services / a characteristic / a descriptor */ + void AddService(int aServerIf, + const BluetoothGattServiceId& aServiceId, + int aNumHandles, + BluetoothGattServerResultHandler* aRes); + void AddIncludedService(int aServerIf, + int aServiceHandle, + int aIncludedServiceHandle, + BluetoothGattServerResultHandler* aRes); + void AddCharacteristic(int aServerIf, + int aServiceHandle, + const BluetoothUuid& aUuid, + BluetoothGattCharProp aProperties, + BluetoothGattAttrPerm aPermissions, + BluetoothGattServerResultHandler* aRes); + void AddDescriptor(int aServerIf, + int aServiceHandle, + const BluetoothUuid& aUuid, + BluetoothGattAttrPerm aPermissions, + BluetoothGattServerResultHandler* aRes); + + /* Start / Stop / Delete a service */ + void StartService(int aServerIf, + int aServiceHandle, + BluetoothTransport aTransport, + BluetoothGattServerResultHandler* aRes); + void StopService(int aServerIf, + int aServiceHandle, + BluetoothGattServerResultHandler* aRes); + void DeleteService(int aServerIf, + int aServiceHandle, + BluetoothGattServerResultHandler* aRes); + + /* Send an indication or a notification */ + void SendIndication( + int aServerIf, + int aAttributeHandle, + int aConnId, + const nsTArray& aValue, + bool aConfirm, /* true: indication, false: notification */ + BluetoothGattServerResultHandler* aRes); + + /* Send a response for an incoming indication */ + void SendResponse(int aConnId, + int aTransId, + BluetoothGattStatus aStatus, + const BluetoothGattResponse& aResponse, + BluetoothGattServerResultHandler* aRes); + + +private: + void DispatchError(BluetoothGattServerResultHandler* aRes, + BluetoothStatus aStatus); + void DispatchError(BluetoothGattServerResultHandler* aRes, nsresult aRv); + BluetoothDaemonGattModule* mModule; +}; + END_BLUETOOTH_NAMESPACE #endif diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.cpp index c571c3e0d4..63186fb833 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.cpp @@ -30,7 +30,7 @@ BluetoothDaemonHandsfreeModule::SetNotificationHandler( } nsresult -BluetoothDaemonHandsfreeModule::Send(BluetoothDaemonPDU* aPDU, +BluetoothDaemonHandsfreeModule::Send(DaemonSocketPDU* aPDU, BluetoothHandsfreeResultHandler* aRes) { aRes->AddRef(); // Keep reference for response @@ -38,11 +38,11 @@ BluetoothDaemonHandsfreeModule::Send(BluetoothDaemonPDU* aPDU, } void -BluetoothDaemonHandsfreeModule::HandleSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData) +BluetoothDaemonHandsfreeModule::HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonHandsfreeModule::* const HandleOp[])( - const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&, void*) = { + const DaemonSocketPDUHeader&, DaemonSocketPDU&, void*) = { INIT_ARRAY_AT(0, &BluetoothDaemonHandsfreeModule::HandleRsp), INIT_ARRAY_AT(1, &BluetoothDaemonHandsfreeModule::HandleNtf), }; @@ -64,8 +64,8 @@ BluetoothDaemonHandsfreeModule::ConnectCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CONNECT, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CONNECT, 6)); // Address nsresult rv = PackPDU( @@ -87,8 +87,8 @@ BluetoothDaemonHandsfreeModule::DisconnectCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_DISCONNECT, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_DISCONNECT, 6)); // Address nsresult rv = PackPDU( @@ -110,8 +110,8 @@ BluetoothDaemonHandsfreeModule::ConnectAudioCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CONNECT_AUDIO, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CONNECT_AUDIO, 6)); // Address nsresult rv = PackPDU( @@ -133,8 +133,8 @@ BluetoothDaemonHandsfreeModule::DisconnectAudioCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_DISCONNECT_AUDIO, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_DISCONNECT_AUDIO, 6)); // Address nsresult rv = PackPDU( @@ -156,8 +156,8 @@ BluetoothDaemonHandsfreeModule::StartVoiceRecognitionCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_START_VOICE_RECOGNITION, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_START_VOICE_RECOGNITION, 6)); // Address (BlueZ 5.25) nsresult rv; @@ -182,8 +182,8 @@ BluetoothDaemonHandsfreeModule::StopVoiceRecognitionCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_STOP_VOICE_RECOGNITION, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_STOP_VOICE_RECOGNITION, 6)); // Address (BlueZ 5.25) nsresult rv; @@ -209,8 +209,8 @@ BluetoothDaemonHandsfreeModule::VolumeControlCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_VOLUME_CONTROL, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_VOLUME_CONTROL, 1 + // Volume type 1 + // Volume 6)); // Address (BlueZ 5.25) @@ -241,8 +241,8 @@ BluetoothDaemonHandsfreeModule::DeviceStatusNotificationCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_DEVICE_STATUS_NOTIFICATION, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_DEVICE_STATUS_NOTIFICATION, 1 + // Network state 1 + // Service type 1 + // Signal strength @@ -269,8 +269,8 @@ BluetoothDaemonHandsfreeModule::CopsResponseCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_COPS_RESPONSE, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_COPS_RESPONSE, 0 + // Dynamically allocated 6)); // Address (BlueZ 5.25) @@ -302,8 +302,8 @@ BluetoothDaemonHandsfreeModule::CindResponseCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CIND_RESPONSE, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CIND_RESPONSE, 1 + // Service 1 + // # Active 1 + // # Held @@ -350,8 +350,8 @@ BluetoothDaemonHandsfreeModule::FormattedAtResponseCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_FORMATTED_AT_RESPONSE, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_FORMATTED_AT_RESPONSE, 0 + // Dynamically allocated 6)); // Address (BlueZ 5.25) @@ -380,8 +380,8 @@ BluetoothDaemonHandsfreeModule::AtResponseCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_AT_RESPONSE, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_AT_RESPONSE, 1 + // AT Response code 1 + // Error code 6)); // Address (BlueZ 5.25) @@ -417,8 +417,8 @@ BluetoothDaemonHandsfreeModule::ClccResponseCmd( NS_ConvertUTF16toUTF8 number(aNumber); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLCC_RESPONSE, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CLCC_RESPONSE, 1 + // Call index 1 + // Call direction 1 + // Call state @@ -460,8 +460,8 @@ BluetoothDaemonHandsfreeModule::PhoneStateChangeCmd( NS_ConvertUTF16toUTF8 number(aNumber); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_PHONE_STATE_CHANGE, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_PHONE_STATE_CHANGE, 1 + // # Active 1 + // # Held 1 + // Call state @@ -491,8 +491,8 @@ BluetoothDaemonHandsfreeModule::ConfigureWbsCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu( - new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CONFIGURE_WBS, + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CONFIGURE_WBS, 6 + // Address 1)); // Config @@ -514,8 +514,8 @@ BluetoothDaemonHandsfreeModule::ConfigureWbsCmd( void BluetoothDaemonHandsfreeModule::ErrorRsp( - const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) + const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) { ErrorRunnable::Dispatch( aRes, &BluetoothHandsfreeResultHandler::OnError, UnpackPDUInitOp(aPDU)); @@ -523,7 +523,7 @@ BluetoothDaemonHandsfreeModule::ErrorRsp( void BluetoothDaemonHandsfreeModule::ConnectRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) { ResultRunnable::Dispatch( @@ -532,7 +532,7 @@ BluetoothDaemonHandsfreeModule::ConnectRsp( void BluetoothDaemonHandsfreeModule::DisconnectRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) { ResultRunnable::Dispatch( @@ -541,7 +541,7 @@ BluetoothDaemonHandsfreeModule::DisconnectRsp( void BluetoothDaemonHandsfreeModule::ConnectAudioRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) { ResultRunnable::Dispatch( @@ -551,7 +551,7 @@ BluetoothDaemonHandsfreeModule::ConnectAudioRsp( void BluetoothDaemonHandsfreeModule::DisconnectAudioRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) { ResultRunnable::Dispatch( @@ -561,7 +561,7 @@ BluetoothDaemonHandsfreeModule::DisconnectAudioRsp( void BluetoothDaemonHandsfreeModule::StartVoiceRecognitionRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) { ResultRunnable::Dispatch( @@ -571,7 +571,7 @@ BluetoothDaemonHandsfreeModule::StartVoiceRecognitionRsp( void BluetoothDaemonHandsfreeModule::StopVoiceRecognitionRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) { ResultRunnable::Dispatch( @@ -581,7 +581,7 @@ BluetoothDaemonHandsfreeModule::StopVoiceRecognitionRsp( void BluetoothDaemonHandsfreeModule::VolumeControlRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) { ResultRunnable::Dispatch( @@ -591,7 +591,7 @@ BluetoothDaemonHandsfreeModule::VolumeControlRsp( void BluetoothDaemonHandsfreeModule::DeviceStatusNotificationRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) { ResultRunnable::Dispatch( @@ -601,7 +601,7 @@ BluetoothDaemonHandsfreeModule::DeviceStatusNotificationRsp( void BluetoothDaemonHandsfreeModule::CopsResponseRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) { ResultRunnable::Dispatch( @@ -611,7 +611,7 @@ BluetoothDaemonHandsfreeModule::CopsResponseRsp( void BluetoothDaemonHandsfreeModule::CindResponseRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) { ResultRunnable::Dispatch( @@ -621,7 +621,7 @@ BluetoothDaemonHandsfreeModule::CindResponseRsp( void BluetoothDaemonHandsfreeModule::FormattedAtResponseRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) { ResultRunnable::Dispatch( @@ -631,7 +631,7 @@ BluetoothDaemonHandsfreeModule::FormattedAtResponseRsp( void BluetoothDaemonHandsfreeModule::AtResponseRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) { ResultRunnable::Dispatch( @@ -641,7 +641,7 @@ BluetoothDaemonHandsfreeModule::AtResponseRsp( void BluetoothDaemonHandsfreeModule::ClccResponseRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) { ResultRunnable::Dispatch( @@ -651,7 +651,7 @@ BluetoothDaemonHandsfreeModule::ClccResponseRsp( void BluetoothDaemonHandsfreeModule::PhoneStateChangeRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) { ResultRunnable::Dispatch( @@ -661,7 +661,7 @@ BluetoothDaemonHandsfreeModule::PhoneStateChangeRsp( void BluetoothDaemonHandsfreeModule::ConfigureWbsRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) { ResultRunnable::Dispatch( @@ -671,12 +671,12 @@ BluetoothDaemonHandsfreeModule::ConfigureWbsRsp( void BluetoothDaemonHandsfreeModule::HandleRsp( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonHandsfreeModule::* const HandleRsp[])( - const BluetoothDaemonPDUHeader&, - BluetoothDaemonPDU&, + const DaemonSocketPDUHeader&, + DaemonSocketPDU&, BluetoothHandsfreeResultHandler*) = { INIT_ARRAY_AT(OPCODE_ERROR, &BluetoothDaemonHandsfreeModule::ErrorRsp), @@ -752,7 +752,7 @@ class BluetoothDaemonHandsfreeModule::ConnectionStateInitOp final : private PDUInitOp { public: - ConnectionStateInitOp(BluetoothDaemonPDU& aPDU) + ConnectionStateInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -760,7 +760,7 @@ public: operator () (BluetoothHandsfreeConnectionState& aArg1, nsString& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read state */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -789,7 +789,7 @@ public: void BluetoothDaemonHandsfreeModule::ConnectionStateNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ConnectionStateNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::ConnectionStateNotification, @@ -801,14 +801,14 @@ class BluetoothDaemonHandsfreeModule::AudioStateInitOp final : private PDUInitOp { public: - AudioStateInitOp(BluetoothDaemonPDU& aPDU) + AudioStateInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } nsresult operator () (BluetoothHandsfreeAudioState& aArg1, nsString& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read state */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -829,7 +829,7 @@ public: void BluetoothDaemonHandsfreeModule::AudioStateNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { AudioStateNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::AudioStateNotification, @@ -841,7 +841,7 @@ class BluetoothDaemonHandsfreeModule::VoiceRecognitionInitOp final : private PDUInitOp { public: - VoiceRecognitionInitOp(BluetoothDaemonPDU& aPDU) + VoiceRecognitionInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -849,7 +849,7 @@ public: operator () (BluetoothHandsfreeVoiceRecognitionState& aArg1, nsString& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read state */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -874,7 +874,7 @@ public: void BluetoothDaemonHandsfreeModule::VoiceRecognitionNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { VoiceRecognitionNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::VoiceRecognitionNotification, @@ -886,7 +886,7 @@ class BluetoothDaemonHandsfreeModule::AnswerCallInitOp final : private PDUInitOp { public: - AnswerCallInitOp(BluetoothDaemonPDU& aPDU) + AnswerCallInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -910,7 +910,7 @@ public: void BluetoothDaemonHandsfreeModule::AnswerCallNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { AnswerCallNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::AnswerCallNotification, @@ -922,7 +922,7 @@ class BluetoothDaemonHandsfreeModule::HangupCallInitOp final : private PDUInitOp { public: - HangupCallInitOp(BluetoothDaemonPDU& aPDU) + HangupCallInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -946,7 +946,7 @@ public: void BluetoothDaemonHandsfreeModule::HangupCallNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { HangupCallNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::HangupCallNotification, @@ -958,7 +958,7 @@ class BluetoothDaemonHandsfreeModule::VolumeInitOp final : private PDUInitOp { public: - VolumeInitOp(BluetoothDaemonPDU& aPDU) + VolumeInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -966,7 +966,7 @@ public: operator () (BluetoothHandsfreeVolumeType& aArg1, int& aArg2, nsString& aArg3) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read volume type */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -997,7 +997,7 @@ public: void BluetoothDaemonHandsfreeModule::VolumeNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { VolumeNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::VolumeNotification, @@ -1009,14 +1009,14 @@ class BluetoothDaemonHandsfreeModule::DialCallInitOp final : private PDUInitOp { public: - DialCallInitOp(BluetoothDaemonPDU& aPDU) + DialCallInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } nsresult operator () (nsString& aArg1, nsString& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); nsresult rv; /* Read address @@ -1045,7 +1045,7 @@ public: void BluetoothDaemonHandsfreeModule::DialCallNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { DialCallNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::DialCallNotification, @@ -1057,14 +1057,14 @@ class BluetoothDaemonHandsfreeModule::DtmfInitOp final : private PDUInitOp { public: - DtmfInitOp(BluetoothDaemonPDU& aPDU) + DtmfInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } nsresult operator () (char& aArg1, nsString& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read tone */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -1089,7 +1089,7 @@ public: void BluetoothDaemonHandsfreeModule::DtmfNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { DtmfNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::DtmfNotification, @@ -1101,14 +1101,14 @@ class BluetoothDaemonHandsfreeModule::NRECInitOp final : private PDUInitOp { public: - NRECInitOp(BluetoothDaemonPDU& aPDU) + NRECInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } nsresult operator () (BluetoothHandsfreeNRECState& aArg1, nsString& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read state */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -1133,7 +1133,7 @@ public: void BluetoothDaemonHandsfreeModule::NRECNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { NRECNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::NRECNotification, @@ -1145,14 +1145,14 @@ class BluetoothDaemonHandsfreeModule::CallHoldInitOp final : private PDUInitOp { public: - CallHoldInitOp(BluetoothDaemonPDU& aPDU) + CallHoldInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } nsresult operator () (BluetoothHandsfreeCallHoldType& aArg1, nsString& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read type */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -1177,7 +1177,7 @@ public: void BluetoothDaemonHandsfreeModule::CallHoldNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { CallHoldNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::CallHoldNotification, @@ -1189,7 +1189,7 @@ class BluetoothDaemonHandsfreeModule::CnumInitOp final : private PDUInitOp { public: - CnumInitOp(BluetoothDaemonPDU& aPDU) + CnumInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -1213,7 +1213,7 @@ public: void BluetoothDaemonHandsfreeModule::CnumNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { CnumNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::CnumNotification, @@ -1225,7 +1225,7 @@ class BluetoothDaemonHandsfreeModule::CindInitOp final : private PDUInitOp { public: - CindInitOp(BluetoothDaemonPDU& aPDU) + CindInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -1249,7 +1249,7 @@ public: void BluetoothDaemonHandsfreeModule::CindNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { CindNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::CindNotification, @@ -1261,7 +1261,7 @@ class BluetoothDaemonHandsfreeModule::CopsInitOp final : private PDUInitOp { public: - CopsInitOp(BluetoothDaemonPDU& aPDU) + CopsInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -1285,7 +1285,7 @@ public: void BluetoothDaemonHandsfreeModule::CopsNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { CopsNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::CopsNotification, @@ -1297,7 +1297,7 @@ class BluetoothDaemonHandsfreeModule::ClccInitOp final : private PDUInitOp { public: - ClccInitOp(BluetoothDaemonPDU& aPDU) + ClccInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -1321,7 +1321,7 @@ public: void BluetoothDaemonHandsfreeModule::ClccNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { ClccNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::ClccNotification, @@ -1333,14 +1333,14 @@ class BluetoothDaemonHandsfreeModule::UnknownAtInitOp final : private PDUInitOp { public: - UnknownAtInitOp(BluetoothDaemonPDU& aPDU) + UnknownAtInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } nsresult operator () (nsCString& aArg1, nsString& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); nsresult rv; /* Read address @@ -1369,7 +1369,7 @@ public: void BluetoothDaemonHandsfreeModule::UnknownAtNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { UnknownAtNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::UnknownAtNotification, @@ -1381,7 +1381,7 @@ class BluetoothDaemonHandsfreeModule::KeyPressedInitOp final : private PDUInitOp { public: - KeyPressedInitOp(BluetoothDaemonPDU& aPDU) + KeyPressedInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -1405,7 +1405,7 @@ public: void BluetoothDaemonHandsfreeModule::KeyPressedNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) { KeyPressedNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::KeyPressedNotification, @@ -1414,11 +1414,11 @@ BluetoothDaemonHandsfreeModule::KeyPressedNtf( void BluetoothDaemonHandsfreeModule::HandleNtf( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonHandsfreeModule::* const HandleNtf[])( - const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&) = { + const DaemonSocketPDUHeader&, DaemonSocketPDU&) = { INIT_ARRAY_AT(0, &BluetoothDaemonHandsfreeModule::ConnectionStateNtf), INIT_ARRAY_AT(1, &BluetoothDaemonHandsfreeModule::AudioStateNtf), INIT_ARRAY_AT(2, &BluetoothDaemonHandsfreeModule::VoiceRecognitionNtf), @@ -1799,8 +1799,8 @@ void BluetoothDaemonHandsfreeInterface::DispatchError( BluetoothHandsfreeResultHandler* aRes, BluetoothStatus aStatus) { - BluetoothResultRunnable1::Dispatch( + DaemonResultRunnable1::Dispatch( aRes, &BluetoothHandsfreeResultHandler::OnError, ConstantInitOp1(aStatus)); } diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.h b/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.h index 0818675598..d4538d0cfe 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.h +++ b/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.h @@ -10,6 +10,7 @@ #include "BluetoothDaemonHelpers.h" #include "BluetoothInterface.h" #include "BluetoothInterfaceHelpers.h" +#include "mozilla/ipc/DaemonRunnables.h" BEGIN_BLUETOOTH_NAMESPACE @@ -41,7 +42,7 @@ public: OPCODE_CONFIGURE_WBS = 0x0f }; - virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0; + virtual nsresult Send(DaemonSocketPDU* aPDU, void* aUserData) = 0; virtual nsresult RegisterModule(uint8_t aId, uint8_t aMode, uint32_t aMaxNumClients, @@ -125,89 +126,90 @@ public: BluetoothHandsfreeResultHandler* aRes); protected: - nsresult Send(BluetoothDaemonPDU* aPDU, + nsresult Send(DaemonSocketPDU* aPDU, BluetoothHandsfreeResultHandler* aRes); - void HandleSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData); + void HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); // // Responses // - typedef BluetoothResultRunnable0 + typedef mozilla::ipc::DaemonResultRunnable0< + BluetoothHandsfreeResultHandler, void> ResultRunnable; - typedef BluetoothResultRunnable1 + typedef mozilla::ipc::DaemonResultRunnable1< + BluetoothHandsfreeResultHandler, void, BluetoothStatus, BluetoothStatus> ErrorRunnable; - void ErrorRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ErrorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes); - void ConnectRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ConnectRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes); - void DisconnectRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void DisconnectRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes); - void ConnectAudioRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ConnectAudioRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes); - void DisconnectAudioRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void DisconnectAudioRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes); - void StartVoiceRecognitionRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void StartVoiceRecognitionRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes); - void StopVoiceRecognitionRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void StopVoiceRecognitionRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes); - void VolumeControlRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void VolumeControlRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes); - void DeviceStatusNotificationRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void DeviceStatusNotificationRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes); - void CopsResponseRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void CopsResponseRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes); - void CindResponseRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void CindResponseRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes); - void FormattedAtResponseRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void FormattedAtResponseRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes); - void AtResponseRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void AtResponseRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes); - void ClccResponseRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ClccResponseRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes); - void PhoneStateChangeRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void PhoneStateChangeRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes); - void ConfigureWbsRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ConfigureWbsRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothHandsfreeResultHandler* aRes); - void HandleRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void HandleRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); // @@ -216,88 +218,76 @@ protected: class NotificationHandlerWrapper; - typedef BluetoothNotificationRunnable2 + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, BluetoothHandsfreeConnectionState, + nsString, BluetoothHandsfreeConnectionState, const nsAString&> ConnectionStateNotification; - typedef BluetoothNotificationRunnable2 + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, BluetoothHandsfreeAudioState, + nsString, BluetoothHandsfreeAudioState, const nsAString&> AudioStateNotification; - typedef BluetoothNotificationRunnable2 + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, BluetoothHandsfreeVoiceRecognitionState, + nsString, BluetoothHandsfreeVoiceRecognitionState, const nsAString&> VoiceRecognitionNotification; - typedef BluetoothNotificationRunnable1 + typedef mozilla::ipc::DaemonNotificationRunnable1< + NotificationHandlerWrapper, void, nsString, const nsAString&> AnswerCallNotification; - typedef BluetoothNotificationRunnable1 + typedef mozilla::ipc::DaemonNotificationRunnable1< + NotificationHandlerWrapper, void, nsString, const nsAString&> HangupCallNotification; - typedef BluetoothNotificationRunnable3 + typedef mozilla::ipc::DaemonNotificationRunnable3< + NotificationHandlerWrapper, void, BluetoothHandsfreeVolumeType, + int, nsString, BluetoothHandsfreeVolumeType, int, const nsAString&> VolumeNotification; - typedef BluetoothNotificationRunnable2 + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, nsString, nsString, const nsAString&, + const nsAString&> DialCallNotification; - typedef BluetoothNotificationRunnable2 + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, char, nsString, char, const nsAString&> DtmfNotification; - typedef BluetoothNotificationRunnable2 NRECNotification; - typedef BluetoothNotificationRunnable2 + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, BluetoothHandsfreeCallHoldType, + nsString, BluetoothHandsfreeCallHoldType, const nsAString&> CallHoldNotification; - typedef BluetoothNotificationRunnable1 + typedef mozilla::ipc::DaemonNotificationRunnable1< + NotificationHandlerWrapper, void, nsString, const nsAString&> CnumNotification; - typedef BluetoothNotificationRunnable1 + typedef mozilla::ipc::DaemonNotificationRunnable1< + NotificationHandlerWrapper, void, nsString, const nsAString&> CindNotification; - typedef BluetoothNotificationRunnable1 + typedef mozilla::ipc::DaemonNotificationRunnable1< + NotificationHandlerWrapper, void, nsString, const nsAString&> CopsNotification; - typedef BluetoothNotificationRunnable1 + typedef mozilla::ipc::DaemonNotificationRunnable1< + NotificationHandlerWrapper, void, nsString, const nsAString&> ClccNotification; - typedef BluetoothNotificationRunnable2 UnknownAtNotification; - typedef BluetoothNotificationRunnable1 + typedef mozilla::ipc::DaemonNotificationRunnable1< + NotificationHandlerWrapper, void, nsString, const nsAString&> KeyPressedNotification; class ConnectionStateInitOp; @@ -318,56 +308,56 @@ protected: class UnknownAtInitOp; class KeyPressedInitOp; - void ConnectionStateNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ConnectionStateNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void AudioStateNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void AudioStateNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void VoiceRecognitionNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void VoiceRecognitionNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void AnswerCallNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void AnswerCallNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void HangupCallNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void HangupCallNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void VolumeNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void VolumeNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void DialCallNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void DialCallNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void DtmfNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void DtmfNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void NRECNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void NRECNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void CallHoldNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void CallHoldNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void CnumNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void CnumNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void CindNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void CindNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void CopsNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void CopsNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void ClccNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void ClccNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void UnknownAtNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void UnknownAtNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void KeyPressedNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU); + void KeyPressedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); - void HandleNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void HandleNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); static BluetoothHandsfreeNotificationHandler* sNotificationHandler; diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp index b9da3f38b2..5c25bebbb4 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp +++ b/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp @@ -30,6 +30,21 @@ Convert(bool aIn, uint8_t& aOut) return NS_OK; } +nsresult +Convert(bool aIn, int32_t& aOut) +{ + static const bool sValue[] = { + CONVERT(false, 0x00), + CONVERT(true, 0x01) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sValue))) { + aOut = 0; + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sValue[aIn]; + return NS_OK; +} + nsresult Convert(bool aIn, BluetoothScanMode& aOut) { @@ -402,6 +417,12 @@ Convert(uint8_t aIn, BluetoothHandsfreeWbsConfig& aOut) return NS_OK; } +nsresult +Convert(uint8_t aIn, BluetoothTypeOfDevice& aOut) +{ + return Convert((int32_t)aIn, aOut); +} + nsresult Convert(uint8_t aIn, BluetoothPropertyType& aOut) { @@ -1070,20 +1091,20 @@ Convert(const ConvertArray& aIn, Tout& aOut) // nsresult -PackPDU(bool aIn, BluetoothDaemonPDU& aPDU) +PackPDU(bool aIn, DaemonSocketPDU& aPDU) { return PackPDU(PackConversion(aIn), aPDU); } nsresult -PackPDU(const BluetoothAddress& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothAddress& aIn, DaemonSocketPDU& aPDU) { return PackPDU(PackArray(aIn.mAddr, sizeof(aIn.mAddr)), aPDU); } nsresult PackPDU(const BluetoothAvrcpAttributeTextPairs& aIn, - BluetoothDaemonPDU& aPDU) + DaemonSocketPDU& aPDU) { size_t i; @@ -1119,7 +1140,7 @@ PackPDU(const BluetoothAvrcpAttributeTextPairs& aIn, nsresult PackPDU(const BluetoothAvrcpAttributeValuePairs& aIn, - BluetoothDaemonPDU& aPDU) + DaemonSocketPDU& aPDU) { size_t i; @@ -1137,7 +1158,7 @@ PackPDU(const BluetoothAvrcpAttributeValuePairs& aIn, } nsresult -PackPDU(const BluetoothAvrcpElementAttribute& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothAvrcpElementAttribute& aIn, DaemonSocketPDU& aPDU) { nsresult rv = PackPDU(PackConversion(aIn.mId), aPDU); if (NS_FAILED(rv)) { @@ -1163,13 +1184,13 @@ PackPDU(const BluetoothAvrcpElementAttribute& aIn, BluetoothDaemonPDU& aPDU) } nsresult -PackPDU(BluetoothAvrcpEvent aIn, BluetoothDaemonPDU& aPDU) +PackPDU(BluetoothAvrcpEvent aIn, DaemonSocketPDU& aPDU) { return PackPDU(PackConversion(aIn), aPDU); } nsresult -PackPDU(const BluetoothAvrcpEventParamPair& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothAvrcpEventParamPair& aIn, DaemonSocketPDU& aPDU) { nsresult rv; @@ -1211,110 +1232,110 @@ PackPDU(const BluetoothAvrcpEventParamPair& aIn, BluetoothDaemonPDU& aPDU) } nsresult -PackPDU(BluetoothAvrcpNotification aIn, BluetoothDaemonPDU& aPDU) +PackPDU(BluetoothAvrcpNotification aIn, DaemonSocketPDU& aPDU) { return PackPDU( PackConversion(aIn), aPDU); } nsresult -PackPDU(BluetoothAvrcpPlayerAttribute aIn, BluetoothDaemonPDU& aPDU) +PackPDU(BluetoothAvrcpPlayerAttribute aIn, DaemonSocketPDU& aPDU) { return PackPDU( PackConversion(aIn), aPDU); } nsresult -PackPDU(BluetoothAvrcpStatus aIn, BluetoothDaemonPDU& aPDU) +PackPDU(BluetoothAvrcpStatus aIn, DaemonSocketPDU& aPDU) { return PackPDU(PackConversion(aIn), aPDU); } nsresult -PackPDU(const BluetoothConfigurationParameter& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothConfigurationParameter& aIn, DaemonSocketPDU& aPDU) { return PackPDU(aIn.mType, aIn.mLength, PackArray(aIn.mValue.get(), aIn.mLength), aPDU); } nsresult -PackPDU(const BluetoothDaemonPDUHeader& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const DaemonSocketPDUHeader& aIn, DaemonSocketPDU& aPDU) { return PackPDU(aIn.mService, aIn.mOpcode, aIn.mLength, aPDU); } nsresult -PackPDU(const BluetoothHandsfreeAtResponse& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothHandsfreeAtResponse& aIn, DaemonSocketPDU& aPDU) { return PackPDU( PackConversion(aIn), aPDU); } nsresult -PackPDU(const BluetoothHandsfreeCallAddressType& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothHandsfreeCallAddressType& aIn, DaemonSocketPDU& aPDU) { return PackPDU( PackConversion(aIn), aPDU); } nsresult -PackPDU(const BluetoothHandsfreeCallDirection& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothHandsfreeCallDirection& aIn, DaemonSocketPDU& aPDU) { return PackPDU( PackConversion(aIn), aPDU); } nsresult -PackPDU(const BluetoothHandsfreeCallMode& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothHandsfreeCallMode& aIn, DaemonSocketPDU& aPDU) { return PackPDU( PackConversion(aIn), aPDU); } nsresult -PackPDU(const BluetoothHandsfreeCallMptyType& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothHandsfreeCallMptyType& aIn, DaemonSocketPDU& aPDU) { return PackPDU( PackConversion(aIn), aPDU); } nsresult -PackPDU(const BluetoothHandsfreeCallState& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothHandsfreeCallState& aIn, DaemonSocketPDU& aPDU) { return PackPDU( PackConversion(aIn), aPDU); } nsresult -PackPDU(const BluetoothHandsfreeNetworkState& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothHandsfreeNetworkState& aIn, DaemonSocketPDU& aPDU) { return PackPDU( PackConversion(aIn), aPDU); } nsresult -PackPDU(const BluetoothHandsfreeServiceType& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothHandsfreeServiceType& aIn, DaemonSocketPDU& aPDU) { return PackPDU( PackConversion(aIn), aPDU); } nsresult -PackPDU(const BluetoothHandsfreeVolumeType& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothHandsfreeVolumeType& aIn, DaemonSocketPDU& aPDU) { return PackPDU( PackConversion(aIn), aPDU); } nsresult -PackPDU(const BluetoothHandsfreeWbsConfig& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothHandsfreeWbsConfig& aIn, DaemonSocketPDU& aPDU) { return PackPDU( PackConversion(aIn), aPDU); } nsresult -PackPDU(const BluetoothNamedValue& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothNamedValue& aIn, DaemonSocketPDU& aPDU) { nsresult rv = PackPDU( PackConversion(aIn.name()), aPDU); @@ -1350,7 +1371,7 @@ PackPDU(const BluetoothNamedValue& aIn, BluetoothDaemonPDU& aPDU) } nsresult -PackPDU(const BluetoothPinCode& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothPinCode& aIn, DaemonSocketPDU& aPDU) { return PackPDU(aIn.mLength, PackArray(aIn.mPinCode, sizeof(aIn.mPinCode)), @@ -1358,58 +1379,58 @@ PackPDU(const BluetoothPinCode& aIn, BluetoothDaemonPDU& aPDU) } nsresult -PackPDU(BluetoothPropertyType aIn, BluetoothDaemonPDU& aPDU) +PackPDU(BluetoothPropertyType aIn, DaemonSocketPDU& aPDU) { return PackPDU(PackConversion(aIn), aPDU); } nsresult -PackPDU(BluetoothSspVariant aIn, BluetoothDaemonPDU& aPDU) +PackPDU(BluetoothSspVariant aIn, DaemonSocketPDU& aPDU) { return PackPDU(PackConversion(aIn), aPDU); } nsresult -PackPDU(BluetoothScanMode aIn, BluetoothDaemonPDU& aPDU) +PackPDU(BluetoothScanMode aIn, DaemonSocketPDU& aPDU) { return PackPDU(PackConversion(aIn), aPDU); } nsresult -PackPDU(const BluetoothServiceName& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothServiceName& aIn, DaemonSocketPDU& aPDU) { return PackPDU(PackArray(aIn.mName, sizeof(aIn.mName)), aPDU); } nsresult -PackPDU(BluetoothSocketType aIn, BluetoothDaemonPDU& aPDU) +PackPDU(BluetoothSocketType aIn, DaemonSocketPDU& aPDU) { return PackPDU(PackConversion(aIn), aPDU); } nsresult -PackPDU(ControlPlayStatus aIn, BluetoothDaemonPDU& aPDU) +PackPDU(ControlPlayStatus aIn, DaemonSocketPDU& aPDU) { return PackPDU(PackConversion(aIn), aPDU); } nsresult -PackPDU(BluetoothTransport aIn, BluetoothDaemonPDU& aPDU) +PackPDU(BluetoothTransport aIn, DaemonSocketPDU& aPDU) { return PackPDU(PackConversion(aIn), aPDU); } nsresult -PackPDU(const BluetoothUuid& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothUuid& aIn, DaemonSocketPDU& aPDU) { return PackPDU( PackArray(aIn.mUuid, sizeof(aIn.mUuid)), aPDU); } nsresult -PackPDU(const BluetoothGattId& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothGattId& aIn, DaemonSocketPDU& aPDU) { - nsresult rv = PackPDU(aIn.mUuid, aPDU); + nsresult rv = PackPDU(PackReversed(aIn.mUuid), aPDU); if (NS_FAILED(rv)) { return rv; } @@ -1417,7 +1438,7 @@ PackPDU(const BluetoothGattId& aIn, BluetoothDaemonPDU& aPDU) } nsresult -PackPDU(const BluetoothGattServiceId& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const BluetoothGattServiceId& aIn, DaemonSocketPDU& aPDU) { nsresult rv = PackPDU(aIn.mId, aPDU); if (NS_FAILED(rv)) { @@ -1427,13 +1448,13 @@ PackPDU(const BluetoothGattServiceId& aIn, BluetoothDaemonPDU& aPDU) } nsresult -PackPDU(BluetoothGattAuthReq aIn, BluetoothDaemonPDU& aPDU) +PackPDU(BluetoothGattAuthReq aIn, DaemonSocketPDU& aPDU) { return PackPDU(PackConversion(aIn), aPDU); } nsresult -PackPDU(BluetoothGattWriteType aIn, BluetoothDaemonPDU& aPDU) +PackPDU(BluetoothGattWriteType aIn, DaemonSocketPDU& aPDU) { return PackPDU(PackConversion(aIn), aPDU); } @@ -1443,60 +1464,60 @@ PackPDU(BluetoothGattWriteType aIn, BluetoothDaemonPDU& aPDU) // nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, bool& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, bool& aOut) { return UnpackPDU(aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, char& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, char& aOut) { return UnpackPDU(aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothA2dpAudioState& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothA2dpAudioState& aOut) { return UnpackPDU( aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothA2dpConnectionState& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothA2dpConnectionState& aOut) { return UnpackPDU( aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAclState& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothAclState& aOut) { return UnpackPDU(aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpEvent& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothAvrcpEvent& aOut) { return UnpackPDU( aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpMediaAttribute& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothAvrcpMediaAttribute& aOut) { return UnpackPDU( aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpPlayerAttribute& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothAvrcpPlayerAttribute& aOut) { return UnpackPDU( aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpPlayerSettings& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothAvrcpPlayerSettings& aOut) { /* Read number of attribute-value pairs */ nsresult rv = UnpackPDU(aPDU, aOut.mNumAttr); @@ -1518,55 +1539,55 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpPlayerSettings& aOut) } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpRemoteFeature& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothAvrcpRemoteFeature& aOut) { return UnpackPDU( aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothBondState& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothBondState& aOut) { return UnpackPDU(aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothTypeOfDevice& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothTypeOfDevice& aOut) { return UnpackPDU( aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeAudioState& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHandsfreeAudioState& aOut) { return UnpackPDU( aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeCallHoldType& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHandsfreeCallHoldType& aOut) { return UnpackPDU( aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeConnectionState& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHandsfreeConnectionState& aOut) { return UnpackPDU( aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeNRECState& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHandsfreeNRECState& aOut) { return UnpackPDU( aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHandsfreeVoiceRecognitionState& aOut) { return UnpackPDU( @@ -1575,14 +1596,14 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeVolumeType& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHandsfreeVolumeType& aOut) { return UnpackPDU( aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothProperty& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothProperty& aOut) { nsresult rv = UnpackPDU(aPDU, aOut.mType); if (NS_FAILED(rv)) { @@ -1667,14 +1688,14 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothProperty& aOut) } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothPropertyType& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothPropertyType& aOut) { return UnpackPDU( aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothRemoteInfo& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothRemoteInfo& aOut) { nsresult rv = UnpackPDU(aPDU, UnpackConversion(aOut.mVerMajor)); @@ -1689,13 +1710,13 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothRemoteInfo& aOut) } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothScanMode& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothScanMode& aOut) { return UnpackPDU(aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothServiceRecord& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothServiceRecord& aOut) { /* unpack UUID */ nsresult rv = UnpackPDU(aPDU, aOut.mUuid); @@ -1712,29 +1733,29 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothServiceRecord& aOut) } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothSspVariant& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothSspVariant& aOut) { return UnpackPDU( aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothStatus& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothStatus& aOut) { return UnpackPDU(aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattStatus& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattStatus& aOut) { return UnpackPDU(aPDU, UnpackConversion(aOut)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattId& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattId& aOut) { /* unpack UUID */ - nsresult rv = UnpackPDU(aPDU, aOut.mUuid); + nsresult rv = UnpackPDU(aPDU, UnpackReversed(aOut.mUuid)); if (NS_FAILED(rv)) { return rv; } @@ -1743,7 +1764,7 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattId& aOut) } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattServiceId& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattServiceId& aOut) { /* unpack id */ nsresult rv = UnpackPDU(aPDU, aOut.mId); @@ -1755,7 +1776,7 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattServiceId& aOut) } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattReadParam& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattReadParam& aOut) { /* unpack service id */ nsresult rv = UnpackPDU(aPDU, aOut.mServiceId); @@ -1792,7 +1813,7 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattReadParam& aOut) } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattWriteParam& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattWriteParam& aOut) { /* unpack service id */ nsresult rv = UnpackPDU(aPDU, aOut.mServiceId); @@ -1814,7 +1835,7 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattWriteParam& aOut) } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattNotifyParam& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattNotifyParam& aOut) { /* unpack address and convert to nsString */ @@ -1851,7 +1872,7 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattNotifyParam& aOut) return aPDU.Read(aOut.mValue, aOut.mLength); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, nsDependentCString& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, nsDependentCString& aOut) { // We get a pointer to the first character in the PDU, a length // of 1 ensures we consume the \0 byte. With 'str' pointing to @@ -1881,7 +1902,7 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, nsDependentCString& aOut) } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackCString0& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, const UnpackCString0& aOut) { nsDependentCString cstring; @@ -1896,7 +1917,7 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackCString0& aOut) } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackString0& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, const UnpackString0& aOut) { nsDependentCString cstring; diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h b/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h index b8cb7a0ace..3699764a63 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h +++ b/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h @@ -10,7 +10,7 @@ #include "BluetoothCommon.h" #include "mozilla/ArrayUtils.h" #include "mozilla/dom/bluetooth/BluetoothTypes.h" -#include "mozilla/ipc/BluetoothDaemonConnection.h" +#include "mozilla/ipc/DaemonSocketPDU.h" #include "nsThreadUtils.h" using namespace mozilla::ipc; @@ -75,14 +75,14 @@ struct BluetoothConfigurationParameter { nsAutoArrayPtr mValue; }; -struct BluetoothDaemonPDUHeader { - BluetoothDaemonPDUHeader() +struct DaemonSocketPDUHeader { + DaemonSocketPDUHeader() : mService(0x00) , mOpcode(0x00) , mLength(0x00) { } - BluetoothDaemonPDUHeader(uint8_t aService, uint8_t aOpcode, uint8_t aLength) + DaemonSocketPDUHeader(uint8_t aService, uint8_t aOpcode, uint8_t aLength) : mService(aService) , mOpcode(aOpcode) , mLength(aLength) @@ -119,6 +119,9 @@ struct BluetoothServiceName { nsresult Convert(bool aIn, uint8_t& aOut); +nsresult +Convert(bool aIn, int32_t& aOut); + nsresult Convert(bool aIn, BluetoothScanMode& aOut); @@ -315,141 +318,141 @@ Convert(BluetoothGattWriteType aIn, int32_t& aOut); // introduce link errors on non-handled data types template nsresult -PackPDU(T aIn, BluetoothDaemonPDU& aPDU); +PackPDU(T aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(bool aIn, BluetoothDaemonPDU& aPDU); +PackPDU(bool aIn, DaemonSocketPDU& aPDU); inline nsresult -PackPDU(uint8_t aIn, BluetoothDaemonPDU& aPDU) +PackPDU(uint8_t aIn, DaemonSocketPDU& aPDU) { return aPDU.Write(aIn); } inline nsresult -PackPDU(uint16_t aIn, BluetoothDaemonPDU& aPDU) +PackPDU(uint16_t aIn, DaemonSocketPDU& aPDU) { return aPDU.Write(aIn); } inline nsresult -PackPDU(int32_t aIn, BluetoothDaemonPDU& aPDU) +PackPDU(int32_t aIn, DaemonSocketPDU& aPDU) { return aPDU.Write(aIn); } inline nsresult -PackPDU(uint32_t aIn, BluetoothDaemonPDU& aPDU) +PackPDU(uint32_t aIn, DaemonSocketPDU& aPDU) { return aPDU.Write(aIn); } nsresult -PackPDU(const BluetoothAddress& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothAddress& aIn, DaemonSocketPDU& aPDU); nsresult PackPDU(const BluetoothAvrcpAttributeTextPairs& aIn, - BluetoothDaemonPDU& aPDU); + DaemonSocketPDU& aPDU); nsresult PackPDU(const BluetoothAvrcpAttributeValuePairs& aIn, - BluetoothDaemonPDU& aPDU); + DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothAvrcpElementAttribute& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothAvrcpElementAttribute& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(BluetoothAvrcpEvent aIn, BluetoothDaemonPDU& aPDU); +PackPDU(BluetoothAvrcpEvent aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothAvrcpEventParamPair& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothAvrcpEventParamPair& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(BluetoothAvrcpNotification aIn, BluetoothDaemonPDU& aPDU); +PackPDU(BluetoothAvrcpNotification aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(BluetoothAvrcpPlayerAttribute aIn, BluetoothDaemonPDU& aPDU); +PackPDU(BluetoothAvrcpPlayerAttribute aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(BluetoothAvrcpStatus aIn, BluetoothDaemonPDU& aPDU); +PackPDU(BluetoothAvrcpStatus aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothConfigurationParameter& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothConfigurationParameter& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothDaemonPDUHeader& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const DaemonSocketPDUHeader& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothHandsfreeAtResponse& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothHandsfreeAtResponse& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothHandsfreeCallAddressType& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothHandsfreeCallAddressType& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothHandsfreeCallDirection& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothHandsfreeCallDirection& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothHandsfreeCallMode& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothHandsfreeCallMode& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothHandsfreeCallMptyType& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothHandsfreeCallMptyType& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothHandsfreeCallState& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothHandsfreeCallState& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothHandsfreeNetworkState& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothHandsfreeNetworkState& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothHandsfreeServiceType& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothHandsfreeServiceType& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothHandsfreeVolumeType& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothHandsfreeVolumeType& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothHandsfreeWbsConfig& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothHandsfreeWbsConfig& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothNamedValue& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothNamedValue& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothPinCode& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothPinCode& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(BluetoothPropertyType aIn, BluetoothDaemonPDU& aPDU); +PackPDU(BluetoothPropertyType aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothServiceName& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothServiceName& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(BluetoothSocketType aIn, BluetoothDaemonPDU& aPDU); +PackPDU(BluetoothSocketType aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(BluetoothSspVariant aIn, BluetoothDaemonPDU& aPDU); +PackPDU(BluetoothSspVariant aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(BluetoothScanMode aIn, BluetoothDaemonPDU& aPDU); +PackPDU(BluetoothScanMode aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(ControlPlayStatus aIn, BluetoothDaemonPDU& aPDU); +PackPDU(ControlPlayStatus aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothUuid& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothUuid& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothGattId& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothGattId& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(const BluetoothGattServiceId& aIn, BluetoothDaemonPDU& aPDU); +PackPDU(const BluetoothGattServiceId& aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(BluetoothGattAuthReq aIn, BluetoothDaemonPDU& aPDU); +PackPDU(BluetoothGattAuthReq aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(BluetoothGattWriteType aIn, BluetoothDaemonPDU& aPDU); +PackPDU(BluetoothGattWriteType aIn, DaemonSocketPDU& aPDU); nsresult -PackPDU(BluetoothTransport aIn, BluetoothDaemonPDU& aPDU); +PackPDU(BluetoothTransport aIn, DaemonSocketPDU& aPDU); /* |PackConversion| is a helper for packing converted values. Pass * an instance of this structure to |PackPDU| to convert a value from @@ -466,7 +469,7 @@ struct PackConversion { template inline nsresult -PackPDU(const PackConversion& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const PackConversion& aIn, DaemonSocketPDU& aPDU) { Tout out; @@ -498,7 +501,7 @@ struct PackArray */ template inline nsresult -PackPDU(const PackArray& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const PackArray& aIn, DaemonSocketPDU& aPDU) { for (size_t i = 0; i < aIn.mLength; ++i) { nsresult rv = PackPDU(aIn.mData[i], aPDU); @@ -511,7 +514,7 @@ PackPDU(const PackArray& aIn, BluetoothDaemonPDU& aPDU) template<> inline nsresult -PackPDU(const PackArray& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const PackArray& aIn, DaemonSocketPDU& aPDU) { /* Write raw bytes in one pass */ return aPDU.Write(aIn.mData, aIn.mLength); @@ -519,7 +522,7 @@ PackPDU(const PackArray& aIn, BluetoothDaemonPDU& aPDU) template<> inline nsresult -PackPDU(const PackArray& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const PackArray& aIn, DaemonSocketPDU& aPDU) { /* Write raw bytes in one pass */ return aPDU.Write(aIn.mData, aIn.mLength); @@ -541,16 +544,67 @@ struct PackCString0 /* This implementation of |PackPDU| packs a 0-terminated C string. */ inline nsresult -PackPDU(const PackCString0& aIn, BluetoothDaemonPDU& aPDU) +PackPDU(const PackCString0& aIn, DaemonSocketPDU& aPDU) { return PackPDU( PackArray(reinterpret_cast(aIn.mString.get()), aIn.mString.Length() + 1), aPDU); } +/* |PackReversed| is a helper for packing data in reversed order. Pass an + * instance of this structure as the first argument to |PackPDU| to pack data + * in reversed order. + */ +template +struct PackReversed +{ + PackReversed(const T& aValue) + : mValue(aValue) + { } + + const T& mValue; +}; + +/* No general rules to pack data in reversed order. Signal a link error if the + * type |T| of |PackReversed| is not defined explicitly. + */ +template +nsresult +PackPDU(const PackReversed& aIn, DaemonSocketPDU& aPDU); + +/* This implementation of |PackPDU| packs elements in |PackArray| in reversed + * order. (ex. reversed GATT UUID, see bug 1171866) + */ +template +inline nsresult +PackPDU(const PackReversed>& aIn, DaemonSocketPDU& aPDU) +{ + for (size_t i = 0; i < aIn.mValue.mLength; ++i) { + nsresult rv = PackPDU(aIn.mValue.mData[aIn.mValue.mLength - i - 1], aPDU); + if (NS_FAILED(rv)) { + return rv; + } + } + return NS_OK; +} + +/* This implementation of |PackPDU| packs |BluetoothUuid| in reversed order. + * (ex. reversed GATT UUID, see bug 1171866) + */ +template <> +inline nsresult +PackPDU(const PackReversed& aIn, + DaemonSocketPDU& aPDU) +{ + return PackPDU( + PackReversed>( + PackArray(aIn.mValue.mUuid, sizeof(aIn.mValue.mUuid))), + aPDU); +} + template inline nsresult -PackPDU(const T1& aIn1, const T2& aIn2, BluetoothDaemonPDU& aPDU) +PackPDU(const T1& aIn1, const T2& aIn2, DaemonSocketPDU& aPDU) { nsresult rv = PackPDU(aIn1, aPDU); if (NS_FAILED(rv)) { @@ -562,7 +616,7 @@ PackPDU(const T1& aIn1, const T2& aIn2, BluetoothDaemonPDU& aPDU) template inline nsresult PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3, - BluetoothDaemonPDU& aPDU) + DaemonSocketPDU& aPDU) { nsresult rv = PackPDU(aIn1, aPDU); if (NS_FAILED(rv)) { @@ -578,7 +632,7 @@ PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3, template inline nsresult PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4, - BluetoothDaemonPDU& aPDU) + DaemonSocketPDU& aPDU) { nsresult rv = PackPDU(aIn1, aPDU); if (NS_FAILED(rv)) { @@ -600,7 +654,7 @@ template +inline nsresult +PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3, + const T4& aIn4, const T5& aIn5, const T6& aIn6, + DaemonSocketPDU& aPDU) +{ + nsresult rv = PackPDU(aIn1, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn2, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn3, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn4, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn5, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + return PackPDU(aIn6, aPDU); +} + template inline nsresult PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4, const T5& aIn5, const T6& aIn6, - const T7& aIn7, BluetoothDaemonPDU& aPDU) + const T7& aIn7, DaemonSocketPDU& aPDU) { nsresult rv = PackPDU(aIn1, aPDU); if (NS_FAILED(rv)) { @@ -662,7 +746,7 @@ template nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, T& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, T& aOut); inline nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, int8_t& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, int8_t& aOut) { return aPDU.Read(aOut); } inline nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, uint8_t& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, uint8_t& aOut) { return aPDU.Read(aOut); } inline nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, uint16_t& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, uint16_t& aOut) { return aPDU.Read(aOut); } inline nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, int32_t& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, int32_t& aOut) { return aPDU.Read(aOut); } inline nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, uint32_t& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, uint32_t& aOut) { return aPDU.Read(aOut); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, bool& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, bool& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, char& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, char& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothA2dpAudioState& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothA2dpAudioState& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothA2dpConnectionState& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothA2dpConnectionState& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAclState& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothAclState& aOut); inline nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAddress& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothAddress& aOut) { return aPDU.Read(aOut.mAddr, sizeof(aOut.mAddr)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpEvent& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothAvrcpEvent& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpMediaAttribute& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothAvrcpMediaAttribute& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpPlayerAttribute& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothAvrcpPlayerAttribute& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpPlayerSettings& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothAvrcpPlayerSettings& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpRemoteFeature& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothAvrcpRemoteFeature& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothBondState& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothBondState& aOut); inline nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothDaemonPDUHeader& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, DaemonSocketPDUHeader& aOut) { nsresult rv = UnpackPDU(aPDU, aOut.mService); if (NS_FAILED(rv)) { @@ -851,80 +935,80 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothDaemonPDUHeader& aOut) } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothTypeOfDevice& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothTypeOfDevice& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeAudioState& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHandsfreeAudioState& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeCallHoldType& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHandsfreeCallHoldType& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeConnectionState& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHandsfreeConnectionState& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeNRECState& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHandsfreeNRECState& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHandsfreeVoiceRecognitionState& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeVolumeType& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHandsfreeVolumeType& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothRemoteInfo& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothRemoteInfo& aOut); inline nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothRemoteName& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothRemoteName& aOut) { return aPDU.Read(aOut.mName, sizeof(aOut.mName)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothProperty& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothProperty& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothPropertyType& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothPropertyType& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothScanMode& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothScanMode& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothServiceRecord& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothServiceRecord& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothSspVariant& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothSspVariant& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothStatus& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothStatus& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattStatus& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattStatus& aOut); inline nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothUuid& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothUuid& aOut) { return aPDU.Read(aOut.mUuid, sizeof(aOut.mUuid)); } nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattId& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattId& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattServiceId& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattServiceId& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattReadParam& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattReadParam& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattWriteParam& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattWriteParam& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattNotifyParam& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattNotifyParam& aOut); nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, nsDependentCString& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, nsDependentCString& aOut); /* |UnpackConversion| is a helper for convering unpacked values. Pass * an instance of this structure to |UnpackPDU| to read a value from @@ -941,7 +1025,7 @@ struct UnpackConversion { template inline nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackConversion& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, const UnpackConversion& aOut) { Tin in; nsresult rv = UnpackPDU(aPDU, in); @@ -985,7 +1069,7 @@ struct UnpackArray template inline nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackArray& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, const UnpackArray& aOut) { for (size_t i = 0; i < aOut.mLength; ++i) { nsresult rv = UnpackPDU(aPDU, aOut.mData[i]); @@ -998,7 +1082,7 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackArray& aOut) template inline nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, UnpackArray& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, UnpackArray& aOut) { for (size_t i = 0; i < aOut.mLength; ++i) { nsresult rv = UnpackPDU(aPDU, aOut.mData[i]); @@ -1011,7 +1095,7 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, UnpackArray& aOut) template<> inline nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackArray& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, const UnpackArray& aOut) { /* Read raw bytes in one pass */ return aPDU.Read(aOut.mData, aOut.mLength); @@ -1019,7 +1103,7 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackArray& aOut) template inline nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, nsTArray& aOut) +UnpackPDU(DaemonSocketPDU& aPDU, nsTArray& aOut) { for (typename nsTArray::size_type i = 0; i < aOut.Length(); ++i) { nsresult rv = UnpackPDU(aPDU, aOut[i]); @@ -1046,7 +1130,7 @@ struct UnpackCString0 /* This implementation of |UnpackPDU| unpacks a 0-terminated C string. */ nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackCString0& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, const UnpackCString0& aOut); /* |UnpackString0| is a helper for unpacking 0-terminated C string, * including the \0 character. Pass an instance of this structure @@ -1066,7 +1150,60 @@ struct UnpackString0 * and converts it to wide-character encoding. */ nsresult -UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackString0& aOut); +UnpackPDU(DaemonSocketPDU& aPDU, const UnpackString0& aOut); + +/* |UnpackReversed| is a helper for unpacking data in reversed order. Pass an + * instance of this structure as the second argument to |UnpackPDU| to unpack + * data in reversed order. + */ +template +struct UnpackReversed +{ + UnpackReversed(T& aValue) + : mValue(&aValue) + { } + + UnpackReversed(T&& aValue) + : mValue(&aValue) + { } + + T* mValue; +}; + +/* No general rules to unpack data in reversed order. Signal a link error if + * the type |T| of |UnpackReversed| is not defined explicitly. + */ +template +nsresult +UnpackPDU(DaemonSocketPDU& aPDU, const UnpackReversed& aOut); + +template +inline nsresult +UnpackPDU(DaemonSocketPDU& aPDU, const UnpackReversed>& aOut) +{ + for (size_t i = 0; i < aOut.mValue->mLength; ++i) { + nsresult rv = UnpackPDU(aPDU, + aOut.mValue->mData[aOut.mValue->mLength - i - 1]); + if (NS_FAILED(rv)) { + return rv; + } + } + return NS_OK; +} + +/* This implementation of |UnpackPDU| unpacks |BluetoothUuid| in reversed + * order. (ex. reversed GATT UUID, see bug 1171866) + */ +template<> +inline nsresult +UnpackPDU(DaemonSocketPDU& aPDU, + const UnpackReversed& aOut) +{ + return UnpackPDU( + aPDU, + UnpackReversed>( + UnpackArray(aOut.mValue->mUuid, sizeof(aOut.mValue->mUuid)))); +} // // Init operators @@ -1076,11 +1213,11 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackString0& aOut); class PDUInitOp { protected: - PDUInitOp(BluetoothDaemonPDU& aPDU) + PDUInitOp(DaemonSocketPDU& aPDU) : mPDU(&aPDU) { } - BluetoothDaemonPDU& GetPDU() const + DaemonSocketPDU& GetPDU() const { return *mPDU; // cannot be nullptr } @@ -1102,7 +1239,7 @@ protected: } private: - BluetoothDaemonPDU* mPDU; // Hold pointer to allow for constant instances + DaemonSocketPDU* mPDU; // Hold pointer to allow for constant instances }; // |UnpackPDUInitOp| is a general-purpose init operator for all variants @@ -1112,7 +1249,7 @@ private: class UnpackPDUInitOp final : private PDUInitOp { public: - UnpackPDUInitOp(BluetoothDaemonPDU& aPDU) + UnpackPDUInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -1136,7 +1273,7 @@ public: template nsresult operator () (T1& aArg1, T2& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); nsresult rv = UnpackPDU(pdu, aArg1); if (NS_FAILED(rv)) { @@ -1153,7 +1290,7 @@ public: template nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); nsresult rv = UnpackPDU(pdu, aArg1); if (NS_FAILED(rv)) { @@ -1174,7 +1311,7 @@ public: template nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); nsresult rv = UnpackPDU(pdu, aArg1); if (NS_FAILED(rv)) { @@ -1200,7 +1337,7 @@ public: nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4, T5& aArg5) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); nsresult rv = UnpackPDU(pdu, aArg1); if (NS_FAILED(rv)) { diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp index d1de652ad4..d9caea833c 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp @@ -17,6 +17,8 @@ #include "BluetoothDaemonSetupInterface.h" #include "BluetoothDaemonSocketInterface.h" #include "BluetoothInterfaceHelpers.h" +#include "mozilla/ipc/DaemonRunnables.h" +#include "mozilla/ipc/DaemonSocket.h" #include "mozilla/ipc/ListenSocket.h" #include "mozilla/unused.h" #include "prrng.h" @@ -34,7 +36,7 @@ static const int sRetryInterval = 100; // ms class BluetoothDaemonSetupModule { public: - virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0; + virtual nsresult Send(DaemonSocketPDU* aPDU, void* aUserData) = 0; // Commands // @@ -45,7 +47,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x00, 0x01, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x00, 0x01, 0)); #if ANDROID_VERSION >= 21 nsresult rv = PackPDU(aId, aMode, aMaxNumClients, *pdu); @@ -68,7 +70,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x00, 0x02, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x00, 0x02, 0)); nsresult rv = PackPDU(aId, *pdu); if (NS_FAILED(rv)) { @@ -87,7 +89,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x00, 0x03, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x00, 0x03, 0)); nsresult rv = PackPDU( aLen, PackArray(aParam, aLen), *pdu); @@ -106,12 +108,12 @@ protected: // Called to handle PDUs with Service field equal to 0x00, which // contains internal operations for setup and configuration. - void HandleSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData) + void HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonSetupModule::* const HandleRsp[])( - const BluetoothDaemonPDUHeader&, - BluetoothDaemonPDU&, + const DaemonSocketPDUHeader&, + DaemonSocketPDU&, BluetoothSetupResultHandler*) = { INIT_ARRAY_AT(0x00, &BluetoothDaemonSetupModule::ErrorRsp), INIT_ARRAY_AT(0x01, &BluetoothDaemonSetupModule::RegisterModuleRsp), @@ -135,7 +137,7 @@ protected: (this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); } - nsresult Send(BluetoothDaemonPDU* aPDU, BluetoothSetupResultHandler* aRes) + nsresult Send(DaemonSocketPDU* aPDU, BluetoothSetupResultHandler* aRes) { aRes->AddRef(); // Keep reference for response return Send(aPDU, static_cast(aRes)); @@ -146,16 +148,17 @@ private: // Responses // - typedef BluetoothResultRunnable0 + typedef mozilla::ipc::DaemonResultRunnable0< + BluetoothSetupResultHandler, void> ResultRunnable; - typedef BluetoothResultRunnable1 + typedef mozilla::ipc::DaemonResultRunnable1< + BluetoothSetupResultHandler, void, BluetoothStatus, BluetoothStatus> ErrorRunnable; void - ErrorRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + ErrorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothSetupResultHandler* aRes) { ErrorRunnable::Dispatch( @@ -163,8 +166,8 @@ private: } void - RegisterModuleRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + RegisterModuleRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothSetupResultHandler* aRes) { ResultRunnable::Dispatch( @@ -173,8 +176,8 @@ private: } void - UnregisterModuleRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + UnregisterModuleRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothSetupResultHandler* aRes) { ResultRunnable::Dispatch( @@ -183,8 +186,8 @@ private: } void - ConfigurationRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + ConfigurationRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothSetupResultHandler* aRes) { ResultRunnable::Dispatch( @@ -205,13 +208,13 @@ public: static const int MAX_NUM_CLIENTS; - virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0; + virtual nsresult Send(DaemonSocketPDU* aPDU, void* aUserData) = 0; nsresult EnableCmd(BluetoothResultHandler* aRes) { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x01, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x01, 0)); nsresult rv = Send(pdu, aRes); if (NS_FAILED(rv)) { @@ -225,7 +228,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x02, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x02, 0)); nsresult rv = Send(pdu, aRes); if (NS_FAILED(rv)) { @@ -239,7 +242,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x03, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x03, 0)); nsresult rv = Send(pdu, aRes); if (NS_FAILED(rv)) { @@ -254,7 +257,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x04, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x04, 0)); nsresult rv = PackPDU( PackConversion(aName), *pdu); @@ -274,7 +277,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x05, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x05, 0)); nsresult rv = PackPDU(aProperty, *pdu); if (NS_FAILED(rv)) { @@ -293,7 +296,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x06, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x06, 0)); nsresult rv = PackPDU( PackConversion(aRemoteAddr), *pdu); @@ -314,7 +317,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x07, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x07, 0)); nsresult rv = PackPDU( PackConversion(aRemoteAddr), @@ -336,7 +339,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x08, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x08, 0)); nsresult rv = PackPDU( PackConversion(aRemoteAddr), @@ -358,7 +361,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x09, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x09, 0)); nsresult rv = PackPDU( PackConversion(aRemoteAddr), @@ -379,7 +382,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x0a, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0a, 0)); nsresult rv = PackPDU( PackConversion(aRemoteAddr), *pdu); @@ -398,7 +401,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x0b, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0b, 0)); nsresult rv = Send(pdu, aRes); if (NS_FAILED(rv)) { @@ -412,7 +415,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x0c, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0c, 0)); nsresult rv = Send(pdu, aRes); if (NS_FAILED(rv)) { @@ -428,7 +431,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x0d, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0d, 0)); #if ANDROID_VERSION >= 21 nsresult rv = PackPDU( @@ -453,7 +456,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x0e, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0e, 0)); nsresult rv = PackPDU( PackConversion(aBdAddr), *pdu); @@ -473,7 +476,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x0f, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0f, 0)); nsresult rv = PackPDU( PackConversion(aBdAddr), *pdu); @@ -494,7 +497,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x10, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x10, 0)); nsresult rv = PackPDU( PackConversion(aBdAddr), @@ -517,7 +520,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x11, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x11, 0)); nsresult rv = PackPDU( PackConversion(aBdAddr), @@ -537,7 +540,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x12, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x12, 0)); nsresult rv = PackPDU(aEnable, *pdu); if (NS_FAILED(rv)) { @@ -556,7 +559,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x13, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x13, 0)); nsresult rv = PackPDU(aOpcode, aLen, PackArray(aBuf, aLen), *pdu); @@ -576,7 +579,7 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x01, 0x14, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x14, 0)); nsresult rv = PackPDU(aOpcode, aLen, PackArray(aBuf, aLen), *pdu); @@ -593,11 +596,11 @@ public: protected: - void HandleSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData) + void HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonCoreModule::* const HandleOp[])( - const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&, void*) = { + const DaemonSocketPDUHeader&, DaemonSocketPDU&, void*) = { INIT_ARRAY_AT(0, &BluetoothDaemonCoreModule::HandleRsp), INIT_ARRAY_AT(1, &BluetoothDaemonCoreModule::HandleNtf), }; @@ -607,7 +610,7 @@ protected: (this->*(HandleOp[!!(aHeader.mOpcode & 0x80)]))(aHeader, aPDU, aUserData); } - nsresult Send(BluetoothDaemonPDU* aPDU, BluetoothResultHandler* aRes) + nsresult Send(DaemonSocketPDU* aPDU, BluetoothResultHandler* aRes) { aRes->AddRef(); // Keep reference for response return Send(aPDU, static_cast(aRes)); @@ -618,39 +621,40 @@ private: // Responses // - typedef BluetoothResultRunnable0 + typedef mozilla::ipc::DaemonResultRunnable0< + BluetoothResultHandler, void> ResultRunnable; - typedef BluetoothResultRunnable1 + typedef mozilla::ipc::DaemonResultRunnable1< + BluetoothResultHandler, void, BluetoothStatus, BluetoothStatus> ErrorRunnable; - void ErrorRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ErrorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ErrorRunnable::Dispatch( aRes, &BluetoothResultHandler::OnError, UnpackPDUInitOp(aPDU)); } - void EnableRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void EnableRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( aRes, &BluetoothResultHandler::Enable, UnpackPDUInitOp(aPDU)); } - void DisableRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void DisableRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( aRes, &BluetoothResultHandler::Disable, UnpackPDUInitOp(aPDU)); } - void GetAdapterPropertiesRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void GetAdapterPropertiesRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -658,8 +662,8 @@ private: UnpackPDUInitOp(aPDU)); } - void GetAdapterPropertyRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void GetAdapterPropertyRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -667,8 +671,8 @@ private: UnpackPDUInitOp(aPDU)); } - void SetAdapterPropertyRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void SetAdapterPropertyRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -676,8 +680,8 @@ private: UnpackPDUInitOp(aPDU)); } - void GetRemoteDevicePropertiesRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void GetRemoteDevicePropertiesRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -686,8 +690,8 @@ private: } void - GetRemoteDevicePropertyRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + GetRemoteDevicePropertyRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -695,8 +699,8 @@ private: UnpackPDUInitOp(aPDU)); } - void SetRemoteDevicePropertyRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void SetRemoteDevicePropertyRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -704,8 +708,8 @@ private: UnpackPDUInitOp(aPDU)); } - void GetRemoteServiceRecordRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void GetRemoteServiceRecordRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -713,8 +717,8 @@ private: UnpackPDUInitOp(aPDU)); } - void GetRemoteServicesRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void GetRemoteServicesRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -722,8 +726,8 @@ private: UnpackPDUInitOp(aPDU)); } - void StartDiscoveryRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void StartDiscoveryRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -731,8 +735,8 @@ private: UnpackPDUInitOp(aPDU)); } - void CancelDiscoveryRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void CancelDiscoveryRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -740,8 +744,8 @@ private: UnpackPDUInitOp(aPDU)); } - void CreateBondRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void CreateBondRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -749,8 +753,8 @@ private: UnpackPDUInitOp(aPDU)); } - void RemoveBondRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void RemoveBondRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -758,8 +762,8 @@ private: UnpackPDUInitOp(aPDU)); } - void CancelBondRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void CancelBondRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -767,8 +771,8 @@ private: UnpackPDUInitOp(aPDU)); } - void PinReplyRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void PinReplyRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -776,8 +780,8 @@ private: UnpackPDUInitOp(aPDU)); } - void SspReplyRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void SspReplyRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -785,8 +789,8 @@ private: UnpackPDUInitOp(aPDU)); } - void DutModeConfigureRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void DutModeConfigureRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -794,8 +798,8 @@ private: UnpackPDUInitOp(aPDU)); } - void DutModeSendRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void DutModeSendRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -803,8 +807,8 @@ private: UnpackPDUInitOp(aPDU)); } - void LeTestModeRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void LeTestModeRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothResultHandler* aRes) { ResultRunnable::Dispatch( @@ -812,12 +816,12 @@ private: UnpackPDUInitOp(aPDU)); } - void HandleRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData) + void HandleRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonCoreModule::* const HandleRsp[])( - const BluetoothDaemonPDUHeader&, - BluetoothDaemonPDU&, + const DaemonSocketPDUHeader&, + DaemonSocketPDU&, BluetoothResultHandler*) = { INIT_ARRAY_AT(0x00, &BluetoothDaemonCoreModule::ErrorRsp), INIT_ARRAY_AT(0x01, &BluetoothDaemonCoreModule::EnableRsp), @@ -880,67 +884,62 @@ private: } }; - typedef BluetoothNotificationRunnable1 + typedef mozilla::ipc::DaemonNotificationRunnable1< + NotificationHandlerWrapper, void, bool> AdapterStateChangedNotification; - typedef BluetoothNotificationRunnable3, - BluetoothStatus, int, - const BluetoothProperty*> + typedef mozilla::ipc::DaemonNotificationRunnable3< + NotificationHandlerWrapper, void, BluetoothStatus, int, + nsAutoArrayPtr, BluetoothStatus, int, + const BluetoothProperty*> AdapterPropertiesNotification; - typedef BluetoothNotificationRunnable4, - BluetoothStatus, const nsAString&, - int, const BluetoothProperty*> + typedef mozilla::ipc::DaemonNotificationRunnable4< + NotificationHandlerWrapper, void, BluetoothStatus, nsString, int, + nsAutoArrayPtr, BluetoothStatus, const nsAString&, + int, const BluetoothProperty*> RemoteDevicePropertiesNotification; - typedef BluetoothNotificationRunnable2, - int, const BluetoothProperty*> + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, int, nsAutoArrayPtr, + int, const BluetoothProperty*> DeviceFoundNotification; - typedef BluetoothNotificationRunnable1 + typedef mozilla::ipc::DaemonNotificationRunnable1< + NotificationHandlerWrapper, void, bool> DiscoveryStateChangedNotification; - typedef BluetoothNotificationRunnable3 + typedef mozilla::ipc::DaemonNotificationRunnable3< + NotificationHandlerWrapper, void, nsString, nsString, uint32_t, + const nsAString&, const nsAString&> PinRequestNotification; - typedef BluetoothNotificationRunnable5 + typedef mozilla::ipc::DaemonNotificationRunnable5< + NotificationHandlerWrapper, void, nsString, nsString, uint32_t, + BluetoothSspVariant, uint32_t, const nsAString&, const nsAString&> SspRequestNotification; - typedef BluetoothNotificationRunnable3 + typedef mozilla::ipc::DaemonNotificationRunnable3< + NotificationHandlerWrapper, void, BluetoothStatus, nsString, + BluetoothBondState, BluetoothStatus, const nsAString&> BondStateChangedNotification; - typedef BluetoothNotificationRunnable3 + typedef mozilla::ipc::DaemonNotificationRunnable3< + NotificationHandlerWrapper, void, BluetoothStatus, nsString, bool, + BluetoothStatus, const nsAString&> AclStateChangedNotification; - typedef BluetoothNotificationRunnable3, - uint8_t, uint16_t, const uint8_t*> + typedef mozilla::ipc::DaemonNotificationRunnable3< + NotificationHandlerWrapper, void, uint16_t, nsAutoArrayPtr, + uint8_t, uint16_t, const uint8_t*> DutModeRecvNotification; - typedef BluetoothNotificationRunnable2 + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, BluetoothStatus, uint16_t> LeTestModeNotification; - void AdapterStateChangedNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU) + void AdapterStateChangedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU) { AdapterStateChangedNotification::Dispatch( &BluetoothNotificationHandler::AdapterStateChangedNotification, @@ -951,7 +950,7 @@ private: class AdapterPropertiesInitOp final : private PDUInitOp { public: - AdapterPropertiesInitOp(BluetoothDaemonPDU& aPDU) + AdapterPropertiesInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -959,7 +958,7 @@ private: operator () (BluetoothStatus& aArg1, int& aArg2, nsAutoArrayPtr& aArg3) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read status */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -986,8 +985,8 @@ private: } }; - void AdapterPropertiesNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU) + void AdapterPropertiesNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU) { AdapterPropertiesNotification::Dispatch( &BluetoothNotificationHandler::AdapterPropertiesNotification, @@ -998,7 +997,7 @@ private: class RemoteDevicePropertiesInitOp final : private PDUInitOp { public: - RemoteDevicePropertiesInitOp(BluetoothDaemonPDU& aPDU) + RemoteDevicePropertiesInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -1006,7 +1005,7 @@ private: operator () (BluetoothStatus& aArg1, nsString& aArg2, int& aArg3, nsAutoArrayPtr& aArg4) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read status */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -1040,8 +1039,8 @@ private: } }; - void RemoteDevicePropertiesNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU) + void RemoteDevicePropertiesNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU) { RemoteDevicePropertiesNotification::Dispatch( &BluetoothNotificationHandler::RemoteDevicePropertiesNotification, @@ -1052,14 +1051,14 @@ private: class DeviceFoundInitOp final : private PDUInitOp { public: - DeviceFoundInitOp(BluetoothDaemonPDU& aPDU) + DeviceFoundInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } nsresult operator () (int& aArg1, nsAutoArrayPtr& aArg2) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read number of properties */ uint8_t numProperties; @@ -1080,16 +1079,16 @@ private: } }; - void DeviceFoundNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU) + void DeviceFoundNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU) { DeviceFoundNotification::Dispatch( &BluetoothNotificationHandler::DeviceFoundNotification, DeviceFoundInitOp(aPDU)); } - void DiscoveryStateChangedNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU) + void DiscoveryStateChangedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU) { DiscoveryStateChangedNotification::Dispatch( &BluetoothNotificationHandler::DiscoveryStateChangedNotification, @@ -1100,14 +1099,14 @@ private: class PinRequestInitOp final : private PDUInitOp { public: - PinRequestInitOp(BluetoothDaemonPDU& aPDU) + PinRequestInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } nsresult operator () (nsString& aArg1, nsString& aArg2, uint32_t& aArg3) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read remote address */ nsresult rv = UnpackPDU( @@ -1133,8 +1132,8 @@ private: } }; - void PinRequestNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU) + void PinRequestNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU) { PinRequestNotification::Dispatch( &BluetoothNotificationHandler::PinRequestNotification, @@ -1145,7 +1144,7 @@ private: class SspRequestInitOp final : private PDUInitOp { public: - SspRequestInitOp(BluetoothDaemonPDU& aPDU) + SspRequestInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -1153,7 +1152,7 @@ private: operator () (nsString& aArg1, nsString& aArg2, uint32_t& aArg3, BluetoothSspVariant& aArg4, uint32_t& aArg5) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read remote address */ nsresult rv = UnpackPDU( @@ -1191,8 +1190,8 @@ private: } }; - void SspRequestNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU) + void SspRequestNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU) { SspRequestNotification::Dispatch( &BluetoothNotificationHandler::SspRequestNotification, @@ -1203,7 +1202,7 @@ private: class BondStateChangedInitOp final : private PDUInitOp { public: - BondStateChangedInitOp(BluetoothDaemonPDU& aPDU) + BondStateChangedInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -1211,7 +1210,7 @@ private: operator () (BluetoothStatus& aArg1, nsString& aArg2, BluetoothBondState& aArg3) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read status */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -1236,8 +1235,8 @@ private: } }; - void BondStateChangedNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU) + void BondStateChangedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU) { BondStateChangedNotification::Dispatch( &BluetoothNotificationHandler::BondStateChangedNotification, @@ -1248,14 +1247,14 @@ private: class AclStateChangedInitOp final : private PDUInitOp { public: - AclStateChangedInitOp(BluetoothDaemonPDU& aPDU) + AclStateChangedInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } nsresult operator () (BluetoothStatus& aArg1, nsString& aArg2, bool& aArg3) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read status */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -1281,8 +1280,8 @@ private: } }; - void AclStateChangedNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU) + void AclStateChangedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU) { AclStateChangedNotification::Dispatch( &BluetoothNotificationHandler::AclStateChangedNotification, @@ -1293,7 +1292,7 @@ private: class DutModeRecvInitOp final : private PDUInitOp { public: - DutModeRecvInitOp(BluetoothDaemonPDU& aPDU) + DutModeRecvInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } @@ -1301,7 +1300,7 @@ private: operator () (uint16_t& aArg1, nsAutoArrayPtr& aArg2, uint8_t& aArg3) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); /* Read opcode */ nsresult rv = UnpackPDU(pdu, aArg1); @@ -1325,27 +1324,27 @@ private: } }; - void DutModeRecvNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU) + void DutModeRecvNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU) { DutModeRecvNotification::Dispatch( &BluetoothNotificationHandler::DutModeRecvNotification, DutModeRecvInitOp(aPDU)); } - void LeTestModeNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU) + void LeTestModeNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU) { LeTestModeNotification::Dispatch( &BluetoothNotificationHandler::LeTestModeNotification, UnpackPDUInitOp(aPDU)); } - void HandleNtf(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData) + void HandleNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonCoreModule::* const HandleNtf[])( - const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&) = { + const DaemonSocketPDUHeader&, DaemonSocketPDU&) = { INIT_ARRAY_AT(0, &BluetoothDaemonCoreModule::AdapterStateChangedNtf), INIT_ARRAY_AT(1, &BluetoothDaemonCoreModule::AdapterPropertiesNtf), INIT_ARRAY_AT(2, &BluetoothDaemonCoreModule::RemoteDevicePropertiesNtf), @@ -1404,8 +1403,8 @@ const int BluetoothDaemonCoreModule::MAX_NUM_CLIENTS = 1; // |UnregisterModule| works like |RegisterModule|, but for cleanups. // // |BluetoothDaemonProtocol| also handles PDU receiving. It implements -// the method |Handle| from |BluetoothDaemonPDUConsumer|. The socket -// connections of type |BluetoothDaemonConnection| invoke this method +// the method |Handle| from |DaemonSocketIOConsumer|. The socket +// connections of type |DaemonSocket| invoke this method // to forward received PDUs for processing by higher layers. The // implementation of |Handle| checks the service id of the PDU and // forwards it to the correct module class using the module's method @@ -1427,7 +1426,7 @@ const int BluetoothDaemonCoreModule::MAX_NUM_CLIENTS = 1; // PDUs into a module. // class BluetoothDaemonProtocol final - : public BluetoothDaemonPDUConsumer + : public DaemonSocketIOConsumer , public BluetoothDaemonSetupModule , public BluetoothDaemonCoreModule , public BluetoothDaemonSocketModule @@ -1439,7 +1438,7 @@ class BluetoothDaemonProtocol final public: BluetoothDaemonProtocol(); - void SetConnection(BluetoothDaemonConnection* aConnection); + void SetConnection(DaemonSocket* aConnection); nsresult RegisterModule(uint8_t aId, uint8_t aMode, uint32_t aMaxNumClients, BluetoothSetupResultHandler* aRes) override; @@ -1450,34 +1449,34 @@ public: // Outgoing PDUs // - nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) override; + nsresult Send(DaemonSocketPDU* aPDU, void* aUserData) override; - void StoreUserData(const BluetoothDaemonPDU& aPDU) override; + void StoreUserData(const DaemonSocketPDU& aPDU) override; // Incoming PUDs // - void Handle(BluetoothDaemonPDU& aPDU) override; + void Handle(DaemonSocketPDU& aPDU) override; - void* FetchUserData(const BluetoothDaemonPDUHeader& aHeader); + void* FetchUserData(const DaemonSocketPDUHeader& aHeader); private: - void HandleSetupSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData); - void HandleCoreSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData); - void HandleSocketSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData); - void HandleHandsfreeSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData); - void HandleA2dpSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData); - void HandleAvrcpSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData); - void HandleGattSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData); + void HandleSetupSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); + void HandleCoreSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); + void HandleSocketSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); + void HandleHandsfreeSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); + void HandleA2dpSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); + void HandleAvrcpSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); + void HandleGattSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); - BluetoothDaemonConnection* mConnection; + DaemonSocket* mConnection; nsTArray mUserDataQ; }; @@ -1485,7 +1484,7 @@ BluetoothDaemonProtocol::BluetoothDaemonProtocol() { } void -BluetoothDaemonProtocol::SetConnection(BluetoothDaemonConnection* aConnection) +BluetoothDaemonProtocol::SetConnection(DaemonSocket* aConnection) { mConnection = aConnection; } @@ -1507,7 +1506,7 @@ BluetoothDaemonProtocol::UnregisterModule(uint8_t aId, } nsresult -BluetoothDaemonProtocol::Send(BluetoothDaemonPDU* aPDU, void* aUserData) +BluetoothDaemonProtocol::Send(DaemonSocketPDU* aPDU, void* aUserData) { MOZ_ASSERT(mConnection); MOZ_ASSERT(aPDU); @@ -1528,7 +1527,7 @@ BluetoothDaemonProtocol::Send(BluetoothDaemonPDU* aPDU, void* aUserData) void BluetoothDaemonProtocol::HandleSetupSvc( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, void* aUserData) { BluetoothDaemonSetupModule::HandleSvc(aHeader, aPDU, aUserData); @@ -1536,7 +1535,7 @@ BluetoothDaemonProtocol::HandleSetupSvc( void BluetoothDaemonProtocol::HandleCoreSvc( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, void* aUserData) { BluetoothDaemonCoreModule::HandleSvc(aHeader, aPDU, aUserData); @@ -1544,7 +1543,7 @@ BluetoothDaemonProtocol::HandleCoreSvc( void BluetoothDaemonProtocol::HandleSocketSvc( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, void* aUserData) { BluetoothDaemonSocketModule::HandleSvc(aHeader, aPDU, aUserData); @@ -1552,7 +1551,7 @@ BluetoothDaemonProtocol::HandleSocketSvc( void BluetoothDaemonProtocol::HandleHandsfreeSvc( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, void* aUserData) { BluetoothDaemonHandsfreeModule::HandleSvc(aHeader, aPDU, aUserData); @@ -1560,7 +1559,7 @@ BluetoothDaemonProtocol::HandleHandsfreeSvc( void BluetoothDaemonProtocol::HandleA2dpSvc( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, void* aUserData) { BluetoothDaemonA2dpModule::HandleSvc(aHeader, aPDU, aUserData); @@ -1568,7 +1567,7 @@ BluetoothDaemonProtocol::HandleA2dpSvc( void BluetoothDaemonProtocol::HandleAvrcpSvc( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, void* aUserData) { BluetoothDaemonAvrcpModule::HandleSvc(aHeader, aPDU, aUserData); @@ -1576,17 +1575,17 @@ BluetoothDaemonProtocol::HandleAvrcpSvc( void BluetoothDaemonProtocol::HandleGattSvc( - const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, void* aUserData) { BluetoothDaemonGattModule::HandleSvc(aHeader, aPDU, aUserData); } void -BluetoothDaemonProtocol::Handle(BluetoothDaemonPDU& aPDU) +BluetoothDaemonProtocol::Handle(DaemonSocketPDU& aPDU) { static void (BluetoothDaemonProtocol::* const HandleSvc[])( - const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&, void*) = { + const DaemonSocketPDUHeader&, DaemonSocketPDU&, void*) = { INIT_ARRAY_AT(0x00, &BluetoothDaemonProtocol::HandleSetupSvc), INIT_ARRAY_AT(0x01, &BluetoothDaemonProtocol::HandleCoreSvc), INIT_ARRAY_AT(0x02, &BluetoothDaemonProtocol::HandleSocketSvc), @@ -1603,7 +1602,7 @@ BluetoothDaemonProtocol::Handle(BluetoothDaemonPDU& aPDU) &BluetoothDaemonProtocol::HandleGattSvc) }; - BluetoothDaemonPDUHeader header; + DaemonSocketPDUHeader header; if (NS_FAILED(UnpackPDU(aPDU, header)) || NS_WARN_IF(!(header.mService < MOZ_ARRAY_LENGTH(HandleSvc))) || @@ -1615,7 +1614,7 @@ BluetoothDaemonProtocol::Handle(BluetoothDaemonPDU& aPDU) } void -BluetoothDaemonProtocol::StoreUserData(const BluetoothDaemonPDU& aPDU) +BluetoothDaemonProtocol::StoreUserData(const DaemonSocketPDU& aPDU) { MOZ_ASSERT(!NS_IsMainThread()); @@ -1623,7 +1622,7 @@ BluetoothDaemonProtocol::StoreUserData(const BluetoothDaemonPDU& aPDU) } void* -BluetoothDaemonProtocol::FetchUserData(const BluetoothDaemonPDUHeader& aHeader) +BluetoothDaemonProtocol::FetchUserData(const DaemonSocketPDUHeader& aHeader) { MOZ_ASSERT(!NS_IsMainThread()); @@ -1863,7 +1862,7 @@ BluetoothDaemonInterface::Init( // Init, step 1: Listen for command channel... */ if (!mCmdChannel) { - mCmdChannel = new BluetoothDaemonConnection(mProtocol, this, CMD_CHANNEL); + mCmdChannel = new DaemonSocket(mProtocol, this, CMD_CHANNEL); } else if ( NS_WARN_IF(mCmdChannel->GetConnectionStatus() == SOCKET_CONNECTED)) { // Command channel should not be open; let's close it. @@ -2240,7 +2239,7 @@ void BluetoothDaemonInterface::DispatchError(BluetoothResultHandler* aRes, BluetoothStatus aStatus) { - BluetoothResultRunnable1< + DaemonResultRunnable1< BluetoothResultHandler, void, BluetoothStatus, BluetoothStatus>::Dispatch( aRes, &BluetoothResultHandler::OnError, ConstantInitOp1(aStatus)); @@ -2321,7 +2320,7 @@ BluetoothDaemonInterface::GetBluetoothGattInterface() return mGattInterface; } -// |BluetoothDaemonConnectionConsumer|, |ListenSocketConsumer| +// |DaemonSocketConsumer|, |ListenSocketConsumer| void BluetoothDaemonInterface::OnConnectSuccess(int aIndex) @@ -2355,7 +2354,7 @@ BluetoothDaemonInterface::OnConnectSuccess(int aIndex) case CMD_CHANNEL: // Init, step 3: Listen for notification channel... if (!mNtfChannel) { - mNtfChannel = new BluetoothDaemonConnection(mProtocol, this, NTF_CHANNEL); + mNtfChannel = new DaemonSocket(mProtocol, this, NTF_CHANNEL); } else if ( NS_WARN_IF(mNtfChannel->GetConnectionStatus() == SOCKET_CONNECTED)) { /* Notification channel should not be open; let's close it. */ diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.h b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.h index 681dcddb4b..1d2b336100 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.h +++ b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.h @@ -8,13 +8,13 @@ #define mozilla_dom_bluetooth_bluedroid_bluetoothdaemoninterface_h__ #include "BluetoothInterface.h" -#include "mozilla/ipc/BluetoothDaemonConnectionConsumer.h" +#include "mozilla/ipc/DaemonSocketConsumer.h" #include "mozilla/ipc/ListenSocketConsumer.h" namespace mozilla { namespace ipc { -class BluetoothDaemonConnection; +class DaemonSocket; class ListenSocket; } @@ -31,7 +31,7 @@ class BluetoothDaemonSocketInterface; class BluetoothDaemonInterface final : public BluetoothInterface - , public mozilla::ipc::BluetoothDaemonConnectionConsumer + , public mozilla::ipc::DaemonSocketConsumer , public mozilla::ipc::ListenSocketConsumer { public: @@ -143,7 +143,7 @@ protected: unsigned long aPostfixLength, nsACString& aAddress); - // Methods for |BluetoothDaemonConnectionConsumer| and |ListenSocketConsumer| + // Methods for |DaemonSocketConsumer| and |ListenSocketConsumer| // void OnConnectSuccess(int aIndex) override; @@ -156,8 +156,8 @@ private: nsCString mListenSocketName; nsRefPtr mListenSocket; - nsRefPtr mCmdChannel; - nsRefPtr mNtfChannel; + nsRefPtr mCmdChannel; + nsRefPtr mNtfChannel; nsAutoPtr mProtocol; nsTArray > mResultHandlerQ; diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.cpp index 71572fe4b3..98315fefc8 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.cpp @@ -30,7 +30,7 @@ BluetoothDaemonSocketModule::ListenCmd(BluetoothSocketType aType, { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x02, 0x01, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x02, 0x01, 0)); nsresult rv = PackPDU( aType, @@ -59,7 +59,7 @@ BluetoothDaemonSocketModule::ConnectCmd(const nsAString& aBdAddr, { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new BluetoothDaemonPDU(0x02, 0x02, 0)); + nsAutoPtr pdu(new DaemonSocketPDU(0x02, 0x02, 0)); nsresult rv = PackPDU( PackConversion(aBdAddr), @@ -156,13 +156,13 @@ BluetoothDaemonSocketModule::CloseCmd(BluetoothSocketResultHandler* aRes) } void -BluetoothDaemonSocketModule::HandleSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, +BluetoothDaemonSocketModule::HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData) { static void (BluetoothDaemonSocketModule::* const HandleRsp[])( - const BluetoothDaemonPDUHeader&, - BluetoothDaemonPDU&, + const DaemonSocketPDUHeader&, + DaemonSocketPDU&, BluetoothSocketResultHandler*) = { INIT_ARRAY_AT(0x00, &BluetoothDaemonSocketModule::ErrorRsp), INIT_ARRAY_AT(0x01, &BluetoothDaemonSocketModule::ListenRsp), @@ -186,7 +186,7 @@ BluetoothDaemonSocketModule::HandleSvc(const BluetoothDaemonPDUHeader& aHeader, } nsresult -BluetoothDaemonSocketModule::Send(BluetoothDaemonPDU* aPDU, +BluetoothDaemonSocketModule::Send(DaemonSocketPDU* aPDU, BluetoothSocketResultHandler* aRes) { aRes->AddRef(); // Keep reference for response @@ -203,8 +203,8 @@ BluetoothDaemonSocketModule::SocketFlags(bool aEncrypt, bool aAuth) // void -BluetoothDaemonSocketModule::ErrorRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, +BluetoothDaemonSocketModule::ErrorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothSocketResultHandler* aRes) { ErrorRunnable::Dispatch( @@ -214,14 +214,14 @@ BluetoothDaemonSocketModule::ErrorRsp(const BluetoothDaemonPDUHeader& aHeader, class BluetoothDaemonSocketModule::ListenInitOp final : private PDUInitOp { public: - ListenInitOp(BluetoothDaemonPDU& aPDU) + ListenInitOp(DaemonSocketPDU& aPDU) : PDUInitOp(aPDU) { } nsresult operator () (int& aArg1) const { - BluetoothDaemonPDU& pdu = GetPDU(); + DaemonSocketPDU& pdu = GetPDU(); aArg1 = pdu.AcquireFd(); @@ -234,8 +234,8 @@ public: }; void -BluetoothDaemonSocketModule::ListenRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, +BluetoothDaemonSocketModule::ListenRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothSocketResultHandler* aRes) { IntResultRunnable::Dispatch( @@ -274,8 +274,8 @@ public: }; void -BluetoothDaemonSocketModule::ConnectRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, +BluetoothDaemonSocketModule::ConnectRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothSocketResultHandler* aRes) { /* the file descriptor is attached in the PDU's ancillary data */ @@ -366,8 +366,8 @@ void BluetoothDaemonSocketInterface::DispatchError( BluetoothSocketResultHandler* aRes, BluetoothStatus aStatus) { - BluetoothResultRunnable1::Dispatch( + DaemonResultRunnable1::Dispatch( aRes, &BluetoothSocketResultHandler::OnError, ConstantInitOp1(aStatus)); } diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.h b/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.h index 3632afeac1..da40f09427 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.h +++ b/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.h @@ -10,6 +10,7 @@ #include "BluetoothDaemonHelpers.h" #include "BluetoothInterface.h" #include "BluetoothInterfaceHelpers.h" +#include "mozilla/ipc/DaemonRunnables.h" BEGIN_BLUETOOTH_NAMESPACE @@ -20,7 +21,7 @@ class BluetoothDaemonSocketModule public: static const int MAX_NUM_CLIENTS; - virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0; + virtual nsresult Send(DaemonSocketPDU* aPDU, void* aUserData) = 0; // Commands // @@ -43,10 +44,10 @@ public: protected: - void HandleSvc(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, void* aUserData); + void HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, void* aUserData); - nsresult Send(BluetoothDaemonPDU* aPDU, BluetoothSocketResultHandler* aRes); + nsresult Send(DaemonSocketPDU* aPDU, BluetoothSocketResultHandler* aRes); private: class AcceptWatcher; @@ -58,32 +59,33 @@ private: // Responses // - typedef BluetoothResultRunnable0 + typedef mozilla::ipc::DaemonResultRunnable0< + BluetoothSocketResultHandler, void> ResultRunnable; - typedef BluetoothResultRunnable1 + typedef mozilla::ipc::DaemonResultRunnable1< + BluetoothSocketResultHandler, void, int, int> IntResultRunnable; - typedef BluetoothResultRunnable1 + typedef mozilla::ipc::DaemonResultRunnable1< + BluetoothSocketResultHandler, void, BluetoothStatus, BluetoothStatus> ErrorRunnable; - typedef BluetoothResultRunnable3 + typedef mozilla::ipc::DaemonResultRunnable3< + BluetoothSocketResultHandler, void, int, nsString, int, int, + const nsAString_internal&, int> IntStringIntResultRunnable; - void ErrorRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ErrorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothSocketResultHandler* aRes); - void ListenRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ListenRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothSocketResultHandler* aRes); - void ConnectRsp(const BluetoothDaemonPDUHeader& aHeader, - BluetoothDaemonPDU& aPDU, + void ConnectRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, BluetoothSocketResultHandler* aRes); }; diff --git a/dom/bluetooth/bluedroid/BluetoothGattHALInterface.cpp b/dom/bluetooth/bluedroid/BluetoothGattHALInterface.cpp index f2090367e9..445049f241 100644 --- a/dom/bluetooth/bluedroid/BluetoothGattHALInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothGattHALInterface.cpp @@ -13,6 +13,11 @@ typedef BluetoothHALInterfaceRunnable0 BluetoothGattClientHALResultRunnable; +typedef + BluetoothHALInterfaceRunnable1 + BluetoothGattClientGetDeviceTypeHALResultRunnable; + typedef BluetoothHALInterfaceRunnable1 @@ -82,6 +87,35 @@ DispatchBluetoothGattServerHALResult( return rv; } +template +static nsresult +DispatchBluetoothGattClientHALResult( + BluetoothGattClientResultHandler* aRes, + void (BluetoothGattClientResultHandler::*aMethod)(Arg1), + Tin1 aArg1, + BluetoothStatus aStatus) +{ + MOZ_ASSERT(aRes); + + nsRunnable* runnable; + Arg1 arg1; + + if (aStatus != STATUS_SUCCESS) { + runnable = new BluetoothGattClientHALErrorRunnable(aRes, + &BluetoothGattClientResultHandler::OnError, aStatus); + } else if (NS_FAILED(Convert(aArg1, arg1))) { + runnable = new BluetoothGattClientHALErrorRunnable(aRes, + &BluetoothGattClientResultHandler::OnError, STATUS_PARM_INVALID); + } else { + runnable = new ResultRunnable(aRes, aMethod, arg1); + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + return rv; +} + static nsresult DispatchBluetoothGattHALResult( BluetoothGattResultHandler* aRes, @@ -470,10 +504,10 @@ struct BluetoothGattServerCallback int, int, const nsAString&, int, int, bool> RequestReadNotification; - typedef BluetoothNotificationHALRunnable8< + typedef BluetoothNotificationHALRunnable9< GattServerNotificationHandlerWrapper, void, - int, int, nsString, int, int, nsTArray, bool, bool, - int, int, const nsAString&, int, int, const nsTArray&, bool, bool> + int, int, nsString, int, int, int, nsAutoArrayPtr, bool, bool, + int, int, const nsAString&, int, int, int, const uint8_t*, bool, bool> RequestWriteNotification; typedef BluetoothNotificationHALRunnable4< @@ -599,12 +633,10 @@ struct BluetoothGattServerCallback int aAttrHandle, int aOffset, int aLength, bool aNeedRsp, bool aIsPrep, uint8_t* aValue) { - nsTArray value; - value.AppendElements(aValue, aLength); RequestWriteNotification::Dispatch( &BluetoothGattServerNotificationHandler::RequestWriteNotification, - aConnId, aTransId, *aBdAddr, aAttrHandle, aOffset, value, aNeedRsp, - aIsPrep); + aConnId, aTransId, *aBdAddr, aAttrHandle, aOffset, aLength, + ConvertArray(aValue, aLength), aNeedRsp, aIsPrep); } static void @@ -1210,22 +1242,23 @@ void BluetoothGattClientHALInterface::GetDeviceType( const nsAString& aBdAddr, BluetoothGattClientResultHandler* aRes) { - int status; + int status = BT_STATUS_FAIL; + bt_device_type_t type = BT_DEVICE_DEVTYPE_BLE; #if ANDROID_VERSION >= 19 bt_bdaddr_t bdAddr; if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { - status = mInterface->get_device_type(&bdAddr); - } else { - status = BT_STATUS_PARM_INVALID; + status = BT_STATUS_SUCCESS; + type = static_cast(mInterface->get_device_type(&bdAddr)); } #else status = BT_STATUS_UNSUPPORTED; #endif if (aRes) { - DispatchBluetoothGattClientHALResult( - aRes, &BluetoothGattClientResultHandler::GetDeviceType, + DispatchBluetoothGattClientHALResult< + BluetoothGattClientGetDeviceTypeHALResultRunnable>( + aRes, &BluetoothGattClientResultHandler::GetDeviceType, type, ConvertDefault(status, STATUS_FAIL)); } } diff --git a/dom/bluetooth/bluedroid/BluetoothGattManager.cpp b/dom/bluetooth/bluedroid/BluetoothGattManager.cpp index 2baef78f3e..0b84892ee7 100644 --- a/dom/bluetooth/bluedroid/BluetoothGattManager.cpp +++ b/dom/bluetooth/bluedroid/BluetoothGattManager.cpp @@ -33,6 +33,7 @@ namespace { StaticRefPtr sBluetoothGattManager; static BluetoothGattInterface* sBluetoothGattInterface; static BluetoothGattClientInterface* sBluetoothGattClientInterface; + static BluetoothGattServerInterface* sBluetoothGattServerInterface; } // anonymous namespace bool BluetoothGattManager::mInShutdown = false; @@ -306,6 +307,10 @@ BluetoothGattManager::InitGattInterface(BluetoothProfileResultHandler* aRes) sBluetoothGattInterface->GetBluetoothGattClientInterface(); NS_ENSURE_TRUE_VOID(sBluetoothGattClientInterface); + sBluetoothGattServerInterface = + sBluetoothGattInterface->GetBluetoothGattServerInterface(); + NS_ENSURE_TRUE_VOID(sBluetoothGattServerInterface); + if (!sClients) { sClients = new nsTArray >; } @@ -335,6 +340,7 @@ public: void Cleanup() override { sBluetoothGattClientInterface = nullptr; + sBluetoothGattServerInterface = nullptr; sBluetoothGattInterface = nullptr; sClients = nullptr; @@ -479,7 +485,10 @@ BluetoothGattManager::UnregisterClient(int aClientIf, size_t index = sClients->IndexOf(aClientIf, 0 /* Start */, ClientIfComparator()); - MOZ_ASSERT(index != sClients->NoIndex); + if (NS_WARN_IF(index == sClients->NoIndex)) { + DispatchReplyError(aRunnable, STATUS_PARM_INVALID); + return; + } nsRefPtr client = sClients->ElementAt(index); client->mUnregisterClientRunnable = aRunnable; @@ -522,8 +531,7 @@ public: gattManager->UnregisterClient(mClient->mClientIf, result); } - DispatchReplyError(mClient->mStartLeScanRunnable, - BluetoothValue(mClient->mAppUuid)); + DispatchReplyError(mClient->mStartLeScanRunnable, aStatus); mClient->mStartLeScanRunnable = nullptr; } @@ -581,7 +589,7 @@ BluetoothGattManager::StartLeScan(const nsTArray& aServiceUuids, size_t index = sClients->IndexOf(appUuidStr, 0 /* Start */, UuidComparator()); // Reject the startLeScan request if the clientIf is being used. - if (index != sClients->NoIndex) { + if (NS_WARN_IF(index != sClients->NoIndex)) { DispatchReplyError(aRunnable, NS_LITERAL_STRING("start LE scan failed")); return; @@ -739,7 +747,10 @@ BluetoothGattManager::Disconnect(const nsAString& aAppUuid, ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable); size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator()); - MOZ_ASSERT(index != sClients->NoIndex); + if (NS_WARN_IF(index == sClients->NoIndex)) { + DispatchReplyError(aRunnable, STATUS_PARM_INVALID); + return; + } nsRefPtr client = sClients->ElementAt(index); client->mDisconnectRunnable = aRunnable; @@ -783,7 +794,10 @@ BluetoothGattManager::Discover(const nsAString& aAppUuid, ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable); size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator()); - MOZ_ASSERT(index != sClients->NoIndex); + if (NS_WARN_IF(index == sClients->NoIndex)) { + DispatchReplyError(aRunnable, STATUS_PARM_INVALID); + return; + } nsRefPtr client = sClients->ElementAt(index); MOZ_ASSERT(client->mConnId > 0); @@ -852,7 +866,10 @@ BluetoothGattManager::ReadRemoteRssi(int aClientIf, size_t index = sClients->IndexOf(aClientIf, 0 /* Start */, ClientIfComparator()); - MOZ_ASSERT(index != sClients->NoIndex); + if (NS_WARN_IF(index == sClients->NoIndex)) { + DispatchReplyError(aRunnable, STATUS_PARM_INVALID); + return; + } nsRefPtr client = sClients->ElementAt(index); client->mReadRemoteRssiRunnable = aRunnable; @@ -916,7 +933,10 @@ BluetoothGattManager::RegisterNotifications( ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable); size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator()); - MOZ_ASSERT(index != sClients->NoIndex); + if (NS_WARN_IF(index == sClients->NoIndex)) { + DispatchReplyError(aRunnable, STATUS_PARM_INVALID); + return; + } nsRefPtr client = sClients->ElementAt(index); @@ -989,7 +1009,10 @@ BluetoothGattManager::DeregisterNotifications( ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable); size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator()); - MOZ_ASSERT(index != sClients->NoIndex); + if (NS_WARN_IF(index == sClients->NoIndex)) { + DispatchReplyError(aRunnable, STATUS_PARM_INVALID); + return; + } nsRefPtr client = sClients->ElementAt(index); @@ -1050,9 +1073,7 @@ BluetoothGattManager::ReadCharacteristicValue( size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator()); if (NS_WARN_IF(index == sClients->NoIndex)) { - // Reject the read characteristic value request - DispatchReplyError(aRunnable, - NS_LITERAL_STRING("ReadCharacteristicValue failed")); + DispatchReplyError(aRunnable, STATUS_PARM_INVALID); return; } @@ -1132,9 +1153,7 @@ BluetoothGattManager::WriteCharacteristicValue( size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator()); if (NS_WARN_IF(index == sClients->NoIndex)) { - // Reject the write characteristic value request - DispatchReplyError(aRunnable, - NS_LITERAL_STRING("WriteCharacteristicValue failed")); + DispatchReplyError(aRunnable, STATUS_PARM_INVALID); return; } @@ -1215,9 +1234,7 @@ BluetoothGattManager::ReadDescriptorValue( size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator()); if (NS_WARN_IF(index == sClients->NoIndex)) { - // Reject the read descriptor value request - DispatchReplyError(aRunnable, - NS_LITERAL_STRING("ReadDescriptorValue failed")); + DispatchReplyError(aRunnable, STATUS_PARM_INVALID); return; } @@ -1298,9 +1315,7 @@ BluetoothGattManager::WriteDescriptorValue( size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator()); if (NS_WARN_IF(index == sClients->NoIndex)) { - // Reject the write descriptor value request - DispatchReplyError(aRunnable, - NS_LITERAL_STRING("WriteDescriptorValue failed")); + DispatchReplyError(aRunnable, STATUS_PARM_INVALID); return; } @@ -1352,7 +1367,8 @@ BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus, UuidToString(aAppUuid, uuid); size_t index = sClients->IndexOf(uuid, 0 /* Start */, UuidComparator()); - MOZ_ASSERT(index != sClients->NoIndex); + NS_ENSURE_TRUE_VOID(index != sClients->NoIndex); + nsRefPtr client = sClients->ElementAt(index); BluetoothService* bs = BluetoothService::Get(); @@ -1406,6 +1422,53 @@ BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus, } } +class BluetoothGattManager::ScanDeviceTypeResultHandler final + : public BluetoothGattClientResultHandler +{ +public: + ScanDeviceTypeResultHandler(const nsAString& aBdAddr, int aRssi, + const BluetoothGattAdvData& aAdvData) + : mBdAddr(aBdAddr) + , mRssi(static_cast(aRssi)) + { + mAdvData.AppendElements(aAdvData.mAdvData, sizeof(aAdvData.mAdvData)); + } + + void GetDeviceType(BluetoothTypeOfDevice type) + { + DistributeSignalDeviceFound(type); + } + + void OnError(BluetoothStatus aStatus) override + { + DistributeSignalDeviceFound(TYPE_OF_DEVICE_BLE); + } + +private: + void DistributeSignalDeviceFound(BluetoothTypeOfDevice type) + { + MOZ_ASSERT(NS_IsMainThread()); + + InfallibleTArray properties; + + BT_APPEND_NAMED_VALUE(properties, "Address", mBdAddr); + BT_APPEND_NAMED_VALUE(properties, "Rssi", mRssi); + BT_APPEND_NAMED_VALUE(properties, "GattAdv", mAdvData); + BT_APPEND_NAMED_VALUE(properties, "Type", static_cast(type)); + + BluetoothService* bs = BluetoothService::Get(); + NS_ENSURE_TRUE_VOID(bs); + + bs->DistributeSignal(NS_LITERAL_STRING("LeDeviceFound"), + NS_LITERAL_STRING(KEY_ADAPTER), + BluetoothValue(properties)); + } + + nsString mBdAddr; + int32_t mRssi; + nsTArray mAdvData; +}; + void BluetoothGattManager::ScanResultNotification( const nsAString& aBdAddr, int aRssi, @@ -1413,21 +1476,13 @@ BluetoothGattManager::ScanResultNotification( { MOZ_ASSERT(NS_IsMainThread()); - InfallibleTArray properties; + NS_ENSURE_TRUE_VOID(sBluetoothGattClientInterface); - nsTArray advData; - advData.AppendElements(aAdvData.mAdvData, sizeof(aAdvData.mAdvData)); - - BT_APPEND_NAMED_VALUE(properties, "Address", nsString(aBdAddr)); - BT_APPEND_NAMED_VALUE(properties, "Rssi", static_cast(aRssi)); - BT_APPEND_NAMED_VALUE(properties, "GattAdv", advData); - - BluetoothService* bs = BluetoothService::Get(); - NS_ENSURE_TRUE_VOID(bs); - - bs->DistributeSignal(NS_LITERAL_STRING("LeDeviceFound"), - NS_LITERAL_STRING(KEY_ADAPTER), - BluetoothValue(properties)); + // Distribute "LeDeviceFound" signal after we know the corresponding + // BluetoothTypeOfDevice of the device + sBluetoothGattClientInterface->GetDeviceType( + aBdAddr, + new ScanDeviceTypeResultHandler(aBdAddr, aRssi, aAdvData)); } void @@ -1443,7 +1498,8 @@ BluetoothGattManager::ConnectNotification(int aConnId, size_t index = sClients->IndexOf(aClientIf, 0 /* Start */, ClientIfComparator()); - MOZ_ASSERT(index != sClients->NoIndex); + NS_ENSURE_TRUE_VOID(index != sClients->NoIndex); + nsRefPtr client = sClients->ElementAt(index); if (aStatus != GATT_STATUS_SUCCESS) { @@ -1494,7 +1550,8 @@ BluetoothGattManager::DisconnectNotification(int aConnId, size_t index = sClients->IndexOf(aClientIf, 0 /* Start */, ClientIfComparator()); - MOZ_ASSERT(index != sClients->NoIndex); + NS_ENSURE_TRUE_VOID(index != sClients->NoIndex); + nsRefPtr client = sClients->ElementAt(index); if (aStatus != GATT_STATUS_SUCCESS) { @@ -1540,7 +1597,7 @@ BluetoothGattManager::SearchCompleteNotification(int aConnId, size_t index = sClients->IndexOf(aConnId, 0 /* Start */, ConnIdComparator()); - MOZ_ASSERT(index != sClients->NoIndex); + NS_ENSURE_TRUE_VOID(index != sClients->NoIndex); nsRefPtr client = sClients->ElementAt(index); MOZ_ASSERT(client->mDiscoverRunnable); @@ -1577,7 +1634,7 @@ BluetoothGattManager::SearchResultNotification( size_t index = sClients->IndexOf(aConnId, 0 /* Start */, ConnIdComparator()); - MOZ_ASSERT(index != sClients->NoIndex); + NS_ENSURE_TRUE_VOID(index != sClients->NoIndex); // Save to mServices for distributing to application and discovering // included services, characteristics of this service later @@ -1598,7 +1655,7 @@ BluetoothGattManager::GetCharacteristicNotification( size_t index = sClients->IndexOf(aConnId, 0 /* Start */, ConnIdComparator()); - MOZ_ASSERT(index != sClients->NoIndex); + NS_ENSURE_TRUE_VOID(index != sClients->NoIndex); nsRefPtr client = sClients->ElementAt(index); MOZ_ASSERT(client->mDiscoverRunnable); @@ -1624,13 +1681,15 @@ BluetoothGattManager::GetCharacteristicNotification( aCharId, new DiscoverResultHandler(client)); } else { // all characteristics of this service are discovered - // Notify BluetoothGattService to create characteristics then proceed - nsString path; - GeneratePathFromGattId(aServiceId.mId, path); + // Notify BluetoothGatt to make BluetoothGattService create characteristics + // then proceed + nsTArray values; + BT_APPEND_NAMED_VALUE(values, "serviceId", aServiceId); + BT_APPEND_NAMED_VALUE(values, "characteristics", client->mCharacteristics); bs->DistributeSignal(NS_LITERAL_STRING("CharacteristicsDiscovered"), - path, - BluetoothValue(client->mCharacteristics)); + client->mAppUuid, + BluetoothValue(values)); ProceedDiscoverProcess(client, aServiceId); } @@ -1650,7 +1709,7 @@ BluetoothGattManager::GetDescriptorNotification( size_t index = sClients->IndexOf(aConnId, 0 /* Start */, ConnIdComparator()); - MOZ_ASSERT(index != sClients->NoIndex); + NS_ENSURE_TRUE_VOID(index != sClients->NoIndex); nsRefPtr client = sClients->ElementAt(index); MOZ_ASSERT(client->mDiscoverRunnable); @@ -1668,13 +1727,16 @@ BluetoothGattManager::GetDescriptorNotification( aDescriptorId, new DiscoverResultHandler(client)); } else { // all descriptors of this characteristic are discovered - // Notify BluetoothGattCharacteristic to create descriptors then proceed - nsString path; - GeneratePathFromGattId(aCharId, path); + // Notify BluetoothGatt to make BluetoothGattCharacteristic create + // descriptors then proceed + nsTArray values; + BT_APPEND_NAMED_VALUE(values, "serviceId", aServiceId); + BT_APPEND_NAMED_VALUE(values, "characteristicId", aCharId); + BT_APPEND_NAMED_VALUE(values, "descriptors", client->mDescriptors); bs->DistributeSignal(NS_LITERAL_STRING("DescriptorsDiscovered"), - path, - BluetoothValue(client->mDescriptors)); + client->mAppUuid, + BluetoothValue(values)); client->mDescriptors.Clear(); ProceedDiscoverProcess(client, aServiceId); @@ -1694,7 +1756,7 @@ BluetoothGattManager::GetIncludedServiceNotification( size_t index = sClients->IndexOf(aConnId, 0 /* Start */, ConnIdComparator()); - MOZ_ASSERT(index != sClients->NoIndex); + NS_ENSURE_TRUE_VOID(index != sClients->NoIndex); nsRefPtr client = sClients->ElementAt(index); MOZ_ASSERT(client->mDiscoverRunnable); @@ -1711,13 +1773,16 @@ BluetoothGattManager::GetIncludedServiceNotification( aIncludedServId, new DiscoverResultHandler(client)); } else { // all included services of this service are discovered - // Notify BluetoothGattService to create included services - nsString path; - GeneratePathFromGattId(aServiceId.mId, path); + // Notify BluetoothGatt to make BluetoothGattService create included + // services + nsTArray values; + BT_APPEND_NAMED_VALUE(values, "serviceId", aServiceId); + BT_APPEND_NAMED_VALUE(values, "includedServices", + client->mIncludedServices); bs->DistributeSignal(NS_LITERAL_STRING("IncludedServicesDiscovered"), - path, - BluetoothValue(client->mIncludedServices)); + client->mAppUuid, + BluetoothValue(values)); client->mIncludedServices.Clear(); // Start to discover characteristics of this service @@ -2012,6 +2077,7 @@ BluetoothGattManager::ReadRemoteRssiNotification(int aClientIf, size_t index = sClients->IndexOf(aClientIf, 0 /* Start */, ClientIfComparator()); NS_ENSURE_TRUE_VOID(index != sClients->NoIndex); + nsRefPtr client = sClients->ElementAt(index); if (aStatus != GATT_STATUS_SUCCESS) { // operation failed diff --git a/dom/bluetooth/bluedroid/BluetoothGattManager.h b/dom/bluetooth/bluedroid/BluetoothGattManager.h index 5fc8e9c731..6fb51187ef 100644 --- a/dom/bluetooth/bluedroid/BluetoothGattManager.h +++ b/dom/bluetooth/bluedroid/BluetoothGattManager.h @@ -110,6 +110,7 @@ private: class WriteCharacteristicValueResultHandler; class ReadDescriptorValueResultHandler; class WriteDescriptorValueResultHandler; + class ScanDeviceTypeResultHandler; BluetoothGattManager(); diff --git a/dom/bluetooth/bluedroid/BluetoothHALHelpers.cpp b/dom/bluetooth/bluedroid/BluetoothHALHelpers.cpp index 4a3b7180fa..6e89ec9227 100644 --- a/dom/bluetooth/bluedroid/BluetoothHALHelpers.cpp +++ b/dom/bluetooth/bluedroid/BluetoothHALHelpers.cpp @@ -233,15 +233,35 @@ Convert(const btrc_player_settings_t& aIn, BluetoothAvrcpPlayerSettings& aOut) nsresult Convert(const BluetoothGattId& aIn, btgatt_gatt_id_t& aOut) { + nsresult rv = Convert(aIn.mUuid, aOut.uuid); + if (NS_FAILED(rv)) { + return rv; + } + // HAL uses reversed UUID for GATT + for (uint8_t i = 0; i < sizeof(aOut.uuid.uu) / 2; i++) { + auto temp = aOut.uuid.uu[i]; + aOut.uuid.uu[i] = aOut.uuid.uu[sizeof(aOut.uuid.uu) - i - 1]; + aOut.uuid.uu[sizeof(aOut.uuid.uu) - i - 1] = temp; + } aOut.inst_id = aIn.mInstanceId; - return Convert(aIn.mUuid, aOut.uuid); + return NS_OK; } nsresult Convert(const btgatt_gatt_id_t& aIn, BluetoothGattId& aOut) { + nsresult rv = Convert(aIn.uuid, aOut.mUuid); + if (NS_FAILED(rv)) { + return rv; + } + // HAL uses reversed UUID for GATT + for (uint8_t i = 0; i < sizeof(aOut.mUuid.mUuid) / 2; i++) { + auto temp = aOut.mUuid.mUuid[i]; + aOut.mUuid.mUuid[i] = aOut.mUuid.mUuid[sizeof(aOut.mUuid.mUuid) - i - 1]; + aOut.mUuid.mUuid[sizeof(aOut.mUuid.mUuid) - i - 1] = temp; + } aOut.mInstanceId = aIn.inst_id; - return Convert(aIn.uuid, aOut.mUuid); + return NS_OK; } nsresult diff --git a/dom/bluetooth/bluedroid/BluetoothHALHelpers.h b/dom/bluetooth/bluedroid/BluetoothHALHelpers.h index 980bee22f7..6f804091fa 100644 --- a/dom/bluetooth/bluedroid/BluetoothHALHelpers.h +++ b/dom/bluetooth/bluedroid/BluetoothHALHelpers.h @@ -1945,47 +1945,48 @@ private: template -class BluetoothNotificationHALRunnable8 : public nsRunnable + typename Arg7=Tin7, typename Arg8=Tin8, typename Arg9=Tin9> +class BluetoothNotificationHALRunnable9 : public nsRunnable { public: typedef typename ObjectWrapper::ObjectType ObjectType; - typedef BluetoothNotificationHALRunnable8 SelfType; + typedef BluetoothNotificationHALRunnable9 SelfType; template + typename T6, typename T7, typename T8, typename T9> static already_AddRefed Create( - Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8), + Res (ObjectType::*aMethod)( + Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9), const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4, const T5& aIn5, const T6& aIn6, - const T7& aIn7, const T8& aIn8) + const T7& aIn7, const T8& aIn8, const T9& aIn9) { nsRefPtr runnable(new SelfType(aMethod)); if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3, aIn4, aIn5, - aIn6, aIn7, aIn8))) { + aIn6, aIn7, aIn8, aIn9))) { return nullptr; } return runnable.forget(); } template + typename T6, typename T7, typename T8, typename T9> static void Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, - Arg8), + Arg8, Arg9), const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4, const T5& aIn5, const T6& aIn6, - const T7& aIn7, const T8& aIn8) + const T7& aIn7, const T8& aIn8, const T9& aIn9) { nsRefPtr runnable = Create(aMethod, aIn1, aIn2, aIn3, aIn4, aIn5, aIn6, - aIn7, aIn8); + aIn7, aIn8, aIn9); if (!runnable) { BT_WARNING("BluetoothNotificationHALRunnable8::Create failed"); return; @@ -2006,25 +2007,27 @@ public: if (!obj) { BT_WARNING("Notification handler not initialized"); } else { - ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4, mArg5, mArg6, mArg7, mArg8); + ((*obj).*mMethod)( + mArg1, mArg2, mArg3, mArg4, mArg5, mArg6, mArg7, mArg8, mArg9); } return NS_OK; } private: - BluetoothNotificationHALRunnable8( - Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)) + BluetoothNotificationHALRunnable9( + Res (ObjectType::*aMethod)( + Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9)) : mMethod(aMethod) { MOZ_ASSERT(mMethod); } template + typename T6, typename T7, typename T8, typename T9> nsresult ConvertAndSet(const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4, const T5& aIn5, const T6& aIn6, - const T7& aIn7, const T8& aIn8) + const T7& aIn7, const T8& aIn8, const T9& aIn9) { nsresult rv = Convert(aIn1, mArg1); if (NS_FAILED(rv)) { @@ -2058,10 +2061,15 @@ private: if (NS_FAILED(rv)) { return rv; } + rv = Convert(aIn9, mArg9); + if (NS_FAILED(rv)) { + return rv; + } return NS_OK; } - Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8); + Res (ObjectType::*mMethod)( + Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9); Tin1 mArg1; Tin2 mArg2; Tin3 mArg3; @@ -2070,6 +2078,7 @@ private: Tin6 mArg6; Tin7 mArg7; Tin8 mArg8; + Tin9 mArg9; }; END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth/bluedroid/BluetoothSocket.cpp b/dom/bluetooth/bluedroid/BluetoothSocket.cpp index e3249194c0..fef6e52ecd 100644 --- a/dom/bluetooth/bluedroid/BluetoothSocket.cpp +++ b/dom/bluetooth/bluedroid/BluetoothSocket.cpp @@ -5,18 +5,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "BluetoothSocket.h" - #include #include - -#include "base/message_loop.h" #include "BluetoothSocketObserver.h" #include "BluetoothInterface.h" #include "BluetoothUtils.h" #include "mozilla/ipc/UnixSocketWatcher.h" #include "mozilla/FileUtils.h" #include "mozilla/RefPtr.h" -#include "nsThreadUtils.h" +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR #include "nsXULAppAPI.h" using namespace mozilla::ipc; @@ -43,7 +40,7 @@ EnsureBluetoothSocketHalLoad() } class mozilla::dom::bluetooth::DroidSocketImpl - : public ipc::UnixFdWatcher + : public mozilla::ipc::UnixFdWatcher , public DataSocketIO { public: @@ -74,16 +71,23 @@ public: SOCKET_IS_CONNECTED }; - DroidSocketImpl(MessageLoop* aIOLoop, BluetoothSocket* aConsumer) - : ipc::UnixFdWatcher(aIOLoop) + DroidSocketImpl(MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, + BluetoothSocket* aConsumer) + : mozilla::ipc::UnixFdWatcher(aIOLoop) + , DataSocketIO(aConsumerLoop) , mConsumer(aConsumer) , mShuttingDownOnIOThread(false) , mConnectionStatus(SOCKET_IS_DISCONNECTED) - { } + { + MOZ_COUNT_CTOR_INHERITED(DroidSocketImpl, DataSocketIO); + } ~DroidSocketImpl() { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(IsConsumerThread()); + + MOZ_COUNT_DTOR_INHERITED(DroidSocketImpl, DataSocketIO); } void Send(UnixSocketIOBuffer* aBuffer) @@ -110,7 +114,7 @@ public: BluetoothSocket* GetBluetoothSocket() { - return mConsumer.get(); + return mConsumer; } DataSocket* GetDataSocket() @@ -119,11 +123,11 @@ public: } /** - * Consumer pointer. Non-thread safe RefPtr, so should only be manipulated - * directly from main thread. All non-main-thread accesses should happen with - * mImpl as container. + * Consumer pointer. Non-thread-safe pointer, so should only be manipulated + * directly from consumer thread. All non-consumer-thread accesses should + * happen with mImpl as container. */ - RefPtr mConsumer; + BluetoothSocket* mConsumer; // Methods for |DataSocket| // @@ -140,9 +144,10 @@ public: return GetDataSocket(); } - bool IsShutdownOnMainThread() const override + bool IsShutdownOnConsumerThread() const override { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(IsConsumerThread()); + return mConsumer == nullptr; } @@ -151,16 +156,17 @@ public: return mShuttingDownOnIOThread; } - void ShutdownOnMainThread() override + void ShutdownOnConsumerThread() override { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!IsShutdownOnMainThread()); + MOZ_ASSERT(IsConsumerThread()); + MOZ_ASSERT(!IsShutdownOnConsumerThread()); + mConsumer = nullptr; } void ShutdownOnIOThread() override { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!IsConsumerThread()); MOZ_ASSERT(!mShuttingDownOnIOThread); Close(); // will also remove fd from I/O loop @@ -168,7 +174,7 @@ public: } private: - class ReceiveRunnable; + class ReceiveTask; /** * libevent triggered functions that reads data from socket when available and @@ -214,7 +220,7 @@ public: void Run() override { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!GetIO()->IsConsumerThread()); MOZ_ASSERT(!IsCanceled()); GetIO()->Connect(mFd); @@ -234,7 +240,7 @@ public: void Run() override { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!GetIO()->IsConsumerThread()); if (!IsCanceled()) { GetIO()->Listen(mFd); @@ -254,7 +260,7 @@ class SocketConnectClientFdTask final void Run() override { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!GetIO()->IsConsumerThread()); GetIO()->ConnectClientFd(); } @@ -314,8 +320,8 @@ DroidSocketImpl::Accept(int aFd) SetFd(aFd); mConnectionStatus = SOCKET_IS_CONNECTED; - NS_DispatchToMainThread( - new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS)); + GetConsumerThread()->PostTask( + FROM_HERE, new SocketEventTask(this, SocketEventTask::CONNECT_SUCCESS)); AddWatchers(READ_WATCHER, true); if (HasPendingData()) { @@ -338,10 +344,10 @@ DroidSocketImpl::OnFileCanReadWithoutBlocking(int aFd) void DroidSocketImpl::OnSocketCanReceiveWithoutBlocking(int aFd) { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!IsConsumerThread()); MOZ_ASSERT(!mShuttingDownOnIOThread); - ssize_t res = ReceiveData(aFd, this); + ssize_t res = ReceiveData(aFd); if (res < 0) { /* I/O error */ RemoveWatchers(READ_WATCHER|WRITE_WATCHER); @@ -361,7 +367,7 @@ public: void Run() override { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!GetIO()->IsConsumerThread()); MOZ_ASSERT(!IsCanceled()); GetIO()->Accept(mFd); @@ -383,11 +389,11 @@ public: void Accept(int aFd, const nsAString& aBdAddress, int aConnectionStatus) override { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mImpl->IsConsumerThread()); mozilla::ScopedClose fd(aFd); // Close received socket fd on error - if (mImpl->IsShutdownOnMainThread()) { + if (mImpl->IsShutdownOnConsumerThread()) { BT_LOGD("mConsumer is null, aborting receive!"); return; } @@ -398,16 +404,16 @@ public: } mImpl->mConsumer->SetAddress(aBdAddress); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new AcceptTask(mImpl, fd.forget())); + mImpl->GetIOLoop()->PostTask(FROM_HERE, + new AcceptTask(mImpl, fd.forget())); } void OnError(BluetoothStatus aStatus) override { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mImpl->IsConsumerThread()); BT_LOGR("BluetoothSocketInterface::Accept failed: %d", (int)aStatus); - if (!mImpl->IsShutdownOnMainThread()) { + if (!mImpl->IsShutdownOnConsumerThread()) { // Instead of NotifyError(), call NotifyDisconnect() to trigger // BluetoothOppManager::OnSocketDisconnect() as // DroidSocketImpl::OnFileCanReadWithoutBlocking() in Firefox OS 2.0 in @@ -420,25 +426,23 @@ private: DroidSocketImpl* mImpl; }; -class AcceptRunnable final : public SocketIORunnable +class InvokeAcceptTask final : public SocketTask { public: - AcceptRunnable(DroidSocketImpl* aImpl, int aFd) - : SocketIORunnable(aImpl) - , mFd(aFd) + InvokeAcceptTask(DroidSocketImpl* aImpl, int aFd) + : SocketTask(aImpl) + , mFd(aFd) { } - NS_IMETHOD Run() override + void Run() override { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(GetIO()->IsConsumerThread()); MOZ_ASSERT(sBluetoothSocketInterface); BluetoothSocketResultHandler* res = new AcceptResultHandler(GetIO()); GetIO()->mConsumer->SetCurrentResultHandler(res); sBluetoothSocketInterface->Accept(mFd, res); - - return NS_OK; } private: @@ -448,7 +452,7 @@ private: void DroidSocketImpl::OnSocketCanAcceptWithoutBlocking(int aFd) { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!IsConsumerThread()); MOZ_ASSERT(!mShuttingDownOnIOThread); /* When a listening socket is ready for receiving data, @@ -456,8 +460,7 @@ DroidSocketImpl::OnSocketCanAcceptWithoutBlocking(int aFd) */ RemoveWatchers(READ_WATCHER); - nsRefPtr t = new AcceptRunnable(this, aFd); - NS_DispatchToMainThread(t); + GetConsumerThread()->PostTask(FROM_HERE, new InvokeAcceptTask(this, aFd)); } void @@ -475,11 +478,11 @@ DroidSocketImpl::OnFileCanWriteWithoutBlocking(int aFd) void DroidSocketImpl::OnSocketCanSendWithoutBlocking(int aFd) { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!IsConsumerThread()); MOZ_ASSERT(!mShuttingDownOnIOThread); MOZ_ASSERT(aFd >= 0); - nsresult rv = SendPendingData(aFd, this); + nsresult rv = SendPendingData(aFd); if (NS_FAILED(rv)) { return; } @@ -492,7 +495,7 @@ DroidSocketImpl::OnSocketCanSendWithoutBlocking(int aFd) void DroidSocketImpl::OnSocketCanConnectWithoutBlocking(int aFd) { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!IsConsumerThread()); MOZ_ASSERT(!mShuttingDownOnIOThread); /* We follow Posix behaviour here: Connect operations are @@ -501,8 +504,8 @@ DroidSocketImpl::OnSocketCanConnectWithoutBlocking(int aFd) mConnectionStatus = SOCKET_IS_CONNECTED; - NS_DispatchToMainThread( - new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS)); + GetConsumerThread()->PostTask( + FROM_HERE, new SocketEventTask(this, SocketEventTask::CONNECT_SUCCESS)); AddWatchers(READ_WATCHER, true); if (HasPendingData()) { @@ -528,35 +531,32 @@ DroidSocketImpl::QueryReceiveBuffer( /** * |ReceiveRunnable| transfers data received on the I/O thread - * to an instance of |BluetoothSocket| on the main thread. + * to an instance of |BluetoothSocket| on the consumer thread. */ -class DroidSocketImpl::ReceiveRunnable final - : public SocketIORunnable +class DroidSocketImpl::ReceiveTask final : public SocketTask { public: - ReceiveRunnable(DroidSocketImpl* aIO, UnixSocketBuffer* aBuffer) - : SocketIORunnable(aIO) + ReceiveTask(DroidSocketImpl* aIO, UnixSocketBuffer* aBuffer) + : SocketTask(aIO) , mBuffer(aBuffer) { } - NS_IMETHOD Run() override + void Run() override { - MOZ_ASSERT(NS_IsMainThread()); + DroidSocketImpl* io = SocketTask::GetIO(); - DroidSocketImpl* io = SocketIORunnable::GetIO(); + MOZ_ASSERT(io->IsConsumerThread()); - if (NS_WARN_IF(io->IsShutdownOnMainThread())) { + if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) { // Since we've already explicitly closed and the close // happened before this, this isn't really an error. - return NS_OK; + return; } BluetoothSocket* bluetoothSocket = io->GetBluetoothSocket(); MOZ_ASSERT(bluetoothSocket); bluetoothSocket->ReceiveSocketData(mBuffer); - - return NS_OK; } private: @@ -566,7 +566,8 @@ private: void DroidSocketImpl::ConsumeBuffer() { - NS_DispatchToMainThread(new ReceiveRunnable(this, mBuffer.forget())); + GetConsumerThread()->PostTask(FROM_HERE, + new ReceiveTask(this, mBuffer.forget())); } void @@ -586,10 +587,17 @@ BluetoothSocket::BluetoothSocket(BluetoothSocketObserver* aObserver) { MOZ_ASSERT(aObserver); + MOZ_COUNT_CTOR_INHERITED(BluetoothSocket, DataSocket); + EnsureBluetoothSocketHalLoad(); mDeviceAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE); } +BluetoothSocket::~BluetoothSocket() +{ + MOZ_COUNT_DTOR_INHERITED(BluetoothSocket, DataSocket); +} + class ConnectSocketResultHandler final : public BluetoothSocketResultHandler { public: @@ -602,9 +610,9 @@ public: void Connect(int aFd, const nsAString& aBdAddress, int aConnectionStatus) override { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mImpl->IsConsumerThread()); - if (mImpl->IsShutdownOnMainThread()) { + if (mImpl->IsShutdownOnConsumerThread()) { BT_LOGD("mConsumer is null, aborting send!"); return; } @@ -615,16 +623,16 @@ public: } mImpl->mConsumer->SetAddress(aBdAddress); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new SocketConnectTask(mImpl, aFd)); + mImpl->GetIOLoop()->PostTask(FROM_HERE, + new SocketConnectTask(mImpl, aFd)); } void OnError(BluetoothStatus aStatus) override { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mImpl->IsConsumerThread()); BT_WARNING("Connect failed: %d", (int)aStatus); - if (!mImpl->IsShutdownOnMainThread()) { + if (!mImpl->IsShutdownOnConsumerThread()) { // Instead of NotifyError(), call NotifyDisconnect() to trigger // BluetoothOppManager::OnSocketDisconnect() as // DroidSocketImpl::OnFileCanReadWithoutBlocking() in Firefox OS 2.0 in @@ -642,14 +650,15 @@ BluetoothSocket::Connect(const nsAString& aDeviceAddress, const BluetoothUuid& aServiceUuid, BluetoothSocketType aType, int aChannel, - bool aAuth, bool aEncrypt) + bool aAuth, bool aEncrypt, + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!mImpl); SetConnectionStatus(SOCKET_CONNECTING); - mImpl = new DroidSocketImpl(XRE_GetIOMessageLoop(), this); + mImpl = new DroidSocketImpl(aConsumerLoop, aIOLoop, this); BluetoothSocketResultHandler* res = new ConnectSocketResultHandler(mImpl); SetCurrentResultHandler(res); @@ -662,6 +671,17 @@ BluetoothSocket::Connect(const nsAString& aDeviceAddress, return NS_OK; } +nsresult +BluetoothSocket::Connect(const nsAString& aDeviceAddress, + const BluetoothUuid& aServiceUuid, + BluetoothSocketType aType, + int aChannel, + bool aAuth, bool aEncrypt) +{ + return Connect(aDeviceAddress, aServiceUuid, aType, aChannel, aAuth, + aEncrypt, MessageLoop::current(), XRE_GetIOMessageLoop()); +} + class ListenResultHandler final : public BluetoothSocketResultHandler { public: @@ -673,15 +693,14 @@ public: void Listen(int aFd) override { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mImpl->IsConsumerThread()); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new SocketListenTask(mImpl, aFd)); + mImpl->GetIOLoop()->PostTask(FROM_HERE, new SocketListenTask(mImpl, aFd)); } void OnError(BluetoothStatus aStatus) override { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mImpl->IsConsumerThread()); BT_WARNING("Listen failed: %d", (int)aStatus); } @@ -695,14 +714,15 @@ BluetoothSocket::Listen(const nsAString& aServiceName, const BluetoothUuid& aServiceUuid, BluetoothSocketType aType, int aChannel, - bool aAuth, bool aEncrypt) + bool aAuth, bool aEncrypt, + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!mImpl); SetConnectionStatus(SOCKET_LISTENING); - mImpl = new DroidSocketImpl(XRE_GetIOMessageLoop(), this); + mImpl = new DroidSocketImpl(aConsumerLoop, aIOLoop, this); BluetoothSocketResultHandler* res = new ListenResultHandler(mImpl); SetCurrentResultHandler(res); @@ -715,10 +735,20 @@ BluetoothSocket::Listen(const nsAString& aServiceName, return NS_OK; } +nsresult +BluetoothSocket::Listen(const nsAString& aServiceName, + const BluetoothUuid& aServiceUuid, + BluetoothSocketType aType, + int aChannel, + bool aAuth, bool aEncrypt) +{ + return Listen(aServiceName, aServiceUuid, aType, aChannel, aAuth, aEncrypt, + MessageLoop::current(), XRE_GetIOMessageLoop()); +} + void BluetoothSocket::ReceiveSocketData(nsAutoPtr& aBuffer) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mObserver); mObserver->ReceiveSocketData(this, aBuffer); @@ -729,11 +759,11 @@ BluetoothSocket::ReceiveSocketData(nsAutoPtr& aBuffer) void BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mImpl); - MOZ_ASSERT(!mImpl->IsShutdownOnMainThread()); + MOZ_ASSERT(mImpl->IsConsumerThread()); + MOZ_ASSERT(!mImpl->IsShutdownOnConsumerThread()); - XRE_GetIOMessageLoop()->PostTask( + mImpl->GetIOLoop()->PostTask( FROM_HERE, new SocketIOSendTask(mImpl, aBuffer)); } @@ -743,12 +773,14 @@ BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer) void BluetoothSocket::Close() { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(sBluetoothSocketInterface); + if (!mImpl) { return; } + MOZ_ASSERT(mImpl->IsConsumerThread()); + // Stop any watching |SocketMessageWatcher| if (mCurrentRes) { sBluetoothSocketInterface->Close(mCurrentRes); @@ -757,10 +789,8 @@ BluetoothSocket::Close() // From this point on, we consider mImpl as being deleted. // We sever the relationship here so any future calls to listen or connect // will create a new implementation. - mImpl->ShutdownOnMainThread(); - - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mImpl)); - + mImpl->ShutdownOnConsumerThread(); + mImpl->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mImpl)); mImpl = nullptr; NotifyDisconnect(); @@ -769,7 +799,6 @@ BluetoothSocket::Close() void BluetoothSocket::OnConnectSuccess() { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mObserver); SetCurrentResultHandler(nullptr); @@ -779,7 +808,6 @@ BluetoothSocket::OnConnectSuccess() void BluetoothSocket::OnConnectError() { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mObserver); SetCurrentResultHandler(nullptr); @@ -789,7 +817,6 @@ BluetoothSocket::OnConnectError() void BluetoothSocket::OnDisconnect() { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mObserver); mObserver->OnSocketDisconnect(this); } diff --git a/dom/bluetooth/bluedroid/BluetoothSocket.h b/dom/bluetooth/bluedroid/BluetoothSocket.h index 74f6915f1d..8afa3d0f0a 100644 --- a/dom/bluetooth/bluedroid/BluetoothSocket.h +++ b/dom/bluetooth/bluedroid/BluetoothSocket.h @@ -10,6 +10,8 @@ #include "BluetoothCommon.h" #include "mozilla/ipc/DataSocket.h" +class MessageLoop; + BEGIN_BLUETOOTH_NAMESPACE class BluetoothSocketObserver; @@ -20,6 +22,15 @@ class BluetoothSocket final : public mozilla::ipc::DataSocket { public: BluetoothSocket(BluetoothSocketObserver* aObserver); + ~BluetoothSocket(); + + nsresult Connect(const nsAString& aDeviceAddress, + const BluetoothUuid& aServiceUuid, + BluetoothSocketType aType, + int aChannel, + bool aAuth, bool aEncrypt, + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop); nsresult Connect(const nsAString& aDeviceAddress, const BluetoothUuid& aServiceUuid, @@ -27,6 +38,14 @@ public: int aChannel, bool aAuth, bool aEncrypt); + nsresult Listen(const nsAString& aServiceName, + const BluetoothUuid& aServiceUuid, + BluetoothSocketType aType, + int aChannel, + bool aAuth, bool aEncrypt, + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop); + nsresult Listen(const nsAString& aServiceName, const BluetoothUuid& aServiceUuid, BluetoothSocketType aType, @@ -35,7 +54,7 @@ public: /** * Method to be called whenever data is received. This is only called on the - * main thread. + * consumer thread. * * @param aBuffer Data received from the socket. */ diff --git a/dom/bluetooth/bluetooth2/BluetoothGatt.cpp b/dom/bluetooth/bluetooth2/BluetoothGatt.cpp index 212d765c0a..9f15f8c845 100644 --- a/dom/bluetooth/bluetooth2/BluetoothGatt.cpp +++ b/dom/bluetooth/bluetooth2/BluetoothGatt.cpp @@ -269,6 +269,77 @@ BluetoothGatt::HandleServicesDiscovered(const BluetoothValue& aValue) BluetoothGattBinding::ClearCachedServicesValue(this); } +void +BluetoothGatt::HandleIncludedServicesDiscovered(const BluetoothValue& aValue) +{ + MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue); + + const InfallibleTArray& values = + aValue.get_ArrayOfBluetoothNamedValue(); + MOZ_ASSERT(values.Length() == 2); // ServiceId, IncludedServices + MOZ_ASSERT(values[0].name().EqualsLiteral("serviceId")); + MOZ_ASSERT(values[0].value().type() == + BluetoothValue::TBluetoothGattServiceId); + MOZ_ASSERT(values[1].name().EqualsLiteral("includedServices")); + MOZ_ASSERT(values[1].value().type() == + BluetoothValue::TArrayOfBluetoothGattServiceId); + + size_t index = mServices.IndexOf( + values[0].value().get_BluetoothGattServiceId()); + NS_ENSURE_TRUE_VOID(index != mServices.NoIndex); + + nsRefPtr service = mServices.ElementAt(index); + service->AssignIncludedServices( + values[1].value().get_ArrayOfBluetoothGattServiceId()); +} + +void +BluetoothGatt::HandleCharacteristicsDiscovered(const BluetoothValue& aValue) +{ + MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue); + + const InfallibleTArray& values = + aValue.get_ArrayOfBluetoothNamedValue(); + MOZ_ASSERT(values.Length() == 2); // ServiceId, Characteristics + MOZ_ASSERT(values[0].name().EqualsLiteral("serviceId")); + MOZ_ASSERT(values[0].value().type() == BluetoothValue::TBluetoothGattServiceId); + MOZ_ASSERT(values[1].name().EqualsLiteral("characteristics")); + MOZ_ASSERT(values[1].value().type() == + BluetoothValue::TArrayOfBluetoothGattCharAttribute); + + size_t index = mServices.IndexOf( + values[0].value().get_BluetoothGattServiceId()); + NS_ENSURE_TRUE_VOID(index != mServices.NoIndex); + + nsRefPtr service = mServices.ElementAt(index); + service->AssignCharacteristics( + values[1].value().get_ArrayOfBluetoothGattCharAttribute()); +} + +void +BluetoothGatt::HandleDescriptorsDiscovered(const BluetoothValue& aValue) +{ + MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue); + + const InfallibleTArray& values = + aValue.get_ArrayOfBluetoothNamedValue(); + MOZ_ASSERT(values.Length() == 3); // ServiceId, CharacteristicId, Descriptors + MOZ_ASSERT(values[0].name().EqualsLiteral("serviceId")); + MOZ_ASSERT(values[0].value().type() == BluetoothValue::TBluetoothGattServiceId); + MOZ_ASSERT(values[1].name().EqualsLiteral("characteristicId")); + MOZ_ASSERT(values[1].value().type() == BluetoothValue::TBluetoothGattId); + MOZ_ASSERT(values[2].name().EqualsLiteral("descriptors")); + MOZ_ASSERT(values[2].value().type() == BluetoothValue::TArrayOfBluetoothGattId); + + size_t index = mServices.IndexOf( + values[0].value().get_BluetoothGattServiceId()); + NS_ENSURE_TRUE_VOID(index != mServices.NoIndex); + + nsRefPtr service = mServices.ElementAt(index); + service->AssignDescriptors(values[1].value().get_BluetoothGattId(), + values[2].value().get_ArrayOfBluetoothGattId()); +} + void BluetoothGatt::HandleCharacteristicChanged(const BluetoothValue& aValue) { @@ -336,6 +407,12 @@ BluetoothGatt::Notify(const BluetoothSignal& aData) } mDiscoveringServices = false; + } else if (aData.name().EqualsLiteral("IncludedServicesDiscovered")) { + HandleIncludedServicesDiscovered(v); + } else if (aData.name().EqualsLiteral("CharacteristicsDiscovered")) { + HandleCharacteristicsDiscovered(v); + } else if (aData.name().EqualsLiteral("DescriptorsDiscovered")) { + HandleDescriptorsDiscovered(v); } else if (aData.name().EqualsLiteral(GATT_CHARACTERISTIC_CHANGED_ID)) { HandleCharacteristicChanged(v); } else { diff --git a/dom/bluetooth/bluetooth2/BluetoothGatt.h b/dom/bluetooth/bluetooth2/BluetoothGatt.h index c897c604ad..2f494f2a3a 100644 --- a/dom/bluetooth/bluetooth2/BluetoothGatt.h +++ b/dom/bluetooth/bluetooth2/BluetoothGatt.h @@ -96,6 +96,50 @@ private: */ void HandleServicesDiscovered(const BluetoothValue& aValue); + /** + * Add newly discovered GATT included services into mIncludedServices of + * BluetoothGattService and update the cache value of mIncludedServices. + * + * @param aValue [in] BluetoothValue which contains an array of + * BluetoothNamedValue. There are exact two elements in + * the array. The first element uses 'serviceId' as the + * name and uses BluetoothGattServiceId as the value. The + * second element uses 'includedServices' as the name and + * uses an array of BluetoothGattServiceId of all + * discovered included services as the value. + */ + void HandleIncludedServicesDiscovered(const BluetoothValue& aValue); + + /** + * Add newly discovered GATT characteristics into mCharacteristics of + * BluetoothGattService and update the cache value of mCharacteristics. + * + * @param aValue [in] BluetoothValue which contains an array of + * BluetoothNamedValue. There are exact two elements in + * the array. The first element uses 'serviceId' as the + * name and uses BluetoothGattServiceId as the value. The + * second element uses 'characteristics' as the name and + * uses an array of BluetoothGattCharAttribute of all + * discovered characteristics as the value. + */ + void HandleCharacteristicsDiscovered(const BluetoothValue& aValue); + + /** + * Add newly discovered GATT descriptors into mDescriptors of + * BluetoothGattCharacteristic and update the cache value of mDescriptors. + * + * @param aValue [in] BluetoothValue which contains an array of + * BluetoothNamedValue. There are exact three elements in + * the array. The first element uses 'serviceId' as the + * name and uses BluetoothGattServiceId as the value. The + * second element uses 'characteristicId' as the name and + * uses BluetoothGattId as the value. The third element + * uses 'descriptors' as the name and uses an array of + * BluetoothGattId of all discovered descriptors as the + * value. + */ + void HandleDescriptorsDiscovered(const BluetoothValue& aValue); + /** * The value of a GATT characteristic has changed. In the mean time, the * cached value of this GATT characteristic has already been updated. An diff --git a/dom/bluetooth/bluetooth2/BluetoothGattCharacteristic.cpp b/dom/bluetooth/bluetooth2/BluetoothGattCharacteristic.cpp index 96e229ca56..27ec6c013c 100644 --- a/dom/bluetooth/bluetooth2/BluetoothGattCharacteristic.cpp +++ b/dom/bluetooth/bluetooth2/BluetoothGattCharacteristic.cpp @@ -68,10 +68,11 @@ BluetoothGattCharacteristic::BluetoothGattCharacteristic( MOZ_ASSERT(aOwner); MOZ_ASSERT(mService); - // Generate bluetooth signal path and a string representation to provide uuid - // of this characteristic to applications + UuidToString(mCharId.mUuid, mUuidStr); + + // Generate bluetooth signal path of this characteristic to applications nsString path; - GeneratePathFromGattId(mCharId, path, mUuidStr); + GeneratePathFromGattId(mCharId, path); RegisterBluetoothSignalHandler(path, this); } @@ -129,18 +130,13 @@ BluetoothGattCharacteristic::StopNotifications(ErrorResult& aRv) } void -BluetoothGattCharacteristic::HandleDescriptorsDiscovered( - const BluetoothValue& aValue) +BluetoothGattCharacteristic::AssignDescriptors( + const nsTArray& aDescriptorIds) { - MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothGattId); - - const InfallibleTArray& descriptorIds = - aValue.get_ArrayOfBluetoothGattId(); - mDescriptors.Clear(); - for (uint32_t i = 0; i < descriptorIds.Length(); i++) { + for (uint32_t i = 0; i < aDescriptorIds.Length(); i++) { mDescriptors.AppendElement(new BluetoothGattDescriptor( - GetParentObject(), this, descriptorIds[i])); + GetParentObject(), this, aDescriptorIds[i])); } BluetoothGattCharacteristicBinding::ClearCachedDescriptorsValue(this); @@ -162,9 +158,7 @@ BluetoothGattCharacteristic::Notify(const BluetoothSignal& aData) NS_ENSURE_TRUE_VOID(mSignalRegistered); BluetoothValue v = aData.value(); - if (aData.name().EqualsLiteral("DescriptorsDiscovered")) { - HandleDescriptorsDiscovered(v); - } else if (aData.name().EqualsLiteral("CharacteristicValueUpdated")) { + if (aData.name().EqualsLiteral("CharacteristicValueUpdated")) { HandleCharacteristicValueUpdated(v); } else { BT_WARNING("Not handling GATT Characteristic signal: %s", diff --git a/dom/bluetooth/bluetooth2/BluetoothGattCharacteristic.h b/dom/bluetooth/bluetooth2/BluetoothGattCharacteristic.h index b5d197c436..61682aea10 100644 --- a/dom/bluetooth/bluetooth2/BluetoothGattCharacteristic.h +++ b/dom/bluetooth/bluetooth2/BluetoothGattCharacteristic.h @@ -32,6 +32,7 @@ class BluetoothGattCharacteristic final : public nsISupports , public nsWrapperCache , public BluetoothSignalObserver { + friend class BluetoothGattService; public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BluetoothGattCharacteristic) @@ -106,10 +107,10 @@ private: * Add newly discovered GATT descriptors into mDescriptors and update the * cache value of mDescriptors. * - * @param aValue [in] BluetoothValue which contains an array of - * BluetoothGattId of all discovered descriptors. + * @param aDescriptorIds [in] An array of BluetoothGattId for each descriptor + * that belongs to this characteristic. */ - void HandleDescriptorsDiscovered(const BluetoothValue& aValue); + void AssignDescriptors(const nsTArray& aDescriptorIds); /** * Update the value of this characteristic. diff --git a/dom/bluetooth/bluetooth2/BluetoothGattDescriptor.cpp b/dom/bluetooth/bluetooth2/BluetoothGattDescriptor.cpp index 3eb7a87bd6..ebe8f6c10b 100644 --- a/dom/bluetooth/bluetooth2/BluetoothGattDescriptor.cpp +++ b/dom/bluetooth/bluetooth2/BluetoothGattDescriptor.cpp @@ -63,10 +63,11 @@ BluetoothGattDescriptor::BluetoothGattDescriptor( MOZ_ASSERT(aOwner); MOZ_ASSERT(aCharacteristic); - // Generate bluetooth signal path and a string representation to provide uuid - // of this descriptor to applications + UuidToString(mDescriptorId.mUuid, mUuidStr); + + // Generate bluetooth signal path of this descriptor to applications nsString path; - GeneratePathFromGattId(mDescriptorId, path, mUuidStr); + GeneratePathFromGattId(mDescriptorId, path); RegisterBluetoothSignalHandler(path, this); } diff --git a/dom/bluetooth/bluetooth2/BluetoothGattService.cpp b/dom/bluetooth/bluetooth2/BluetoothGattService.cpp index 8a5a945f38..91fd66a4f8 100644 --- a/dom/bluetooth/bluetooth2/BluetoothGattService.cpp +++ b/dom/bluetooth/bluetooth2/BluetoothGattService.cpp @@ -17,33 +17,10 @@ using namespace mozilla::dom; USING_BLUETOOTH_NAMESPACE -NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothGattService) - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BluetoothGattService) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mIncludedServices) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mCharacteristics) - NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER - - /** - * Unregister the bluetooth signal handler after unlinked. - * - * This is needed to avoid ending up with exposing a deleted object to JS or - * accessing deleted objects while receiving signals from parent process - * after unlinked. Please see Bug 1138267 for detail informations. - */ - nsString path; - GeneratePathFromGattId(tmp->mServiceId.mId, path); - UnregisterBluetoothSignalHandler(path, tmp); -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BluetoothGattService) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIncludedServices) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCharacteristics) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END -NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(BluetoothGattService) +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(BluetoothGattService, + mOwner, + mIncludedServices, + mCharacteristics) NS_IMPL_CYCLE_COLLECTING_ADDREF(BluetoothGattService) NS_IMPL_CYCLE_COLLECTING_RELEASE(BluetoothGattService) @@ -62,72 +39,50 @@ BluetoothGattService::BluetoothGattService( MOZ_ASSERT(aOwner); MOZ_ASSERT(!mAppUuid.IsEmpty()); - // Generate bluetooth signal path and a string representation to provide - // uuid of this service to applications - nsString path; - GeneratePathFromGattId(mServiceId.mId, path, mUuidStr); - RegisterBluetoothSignalHandler(path, this); + UuidToString(mServiceId.mId.mUuid, mUuidStr); } BluetoothGattService::~BluetoothGattService() { - nsString path; - GeneratePathFromGattId(mServiceId.mId, path); - UnregisterBluetoothSignalHandler(path, this); } void -BluetoothGattService::HandleIncludedServicesDiscovered( - const BluetoothValue& aValue) +BluetoothGattService::AssignIncludedServices( + const nsTArray& aServiceIds) { - MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothGattServiceId); - - const InfallibleTArray& includedServIds = - aValue.get_ArrayOfBluetoothGattServiceId(); - mIncludedServices.Clear(); - for (uint32_t i = 0; i < includedServIds.Length(); i++) { + for (uint32_t i = 0; i < aServiceIds.Length(); i++) { mIncludedServices.AppendElement(new BluetoothGattService( - GetParentObject(), mAppUuid, includedServIds[i])); + GetParentObject(), mAppUuid, aServiceIds[i])); } BluetoothGattServiceBinding::ClearCachedIncludedServicesValue(this); } void -BluetoothGattService::HandleCharacteristicsDiscovered( - const BluetoothValue& aValue) +BluetoothGattService::AssignCharacteristics( + const nsTArray& aCharacteristics) { - MOZ_ASSERT(aValue.type() == - BluetoothValue::TArrayOfBluetoothGattCharAttribute); - - const InfallibleTArray& characteristics = - aValue.get_ArrayOfBluetoothGattCharAttribute(); - mCharacteristics.Clear(); - for (uint32_t i = 0; i < characteristics.Length(); i++) { + for (uint32_t i = 0; i < aCharacteristics.Length(); i++) { mCharacteristics.AppendElement(new BluetoothGattCharacteristic( - GetParentObject(), this, characteristics[i])); + GetParentObject(), this, aCharacteristics[i])); } BluetoothGattServiceBinding::ClearCachedCharacteristicsValue(this); } void -BluetoothGattService::Notify(const BluetoothSignal& aData) +BluetoothGattService::AssignDescriptors( + const BluetoothGattId& aCharacteristicId, + const nsTArray& aDescriptorIds) { - BT_LOGD("[D] %s", NS_ConvertUTF16toUTF8(aData.name()).get()); - NS_ENSURE_TRUE_VOID(mSignalRegistered); + size_t index = mCharacteristics.IndexOf(aCharacteristicId); + NS_ENSURE_TRUE_VOID(index != mCharacteristics.NoIndex); - BluetoothValue v = aData.value(); - if (aData.name().EqualsLiteral("IncludedServicesDiscovered")) { - HandleIncludedServicesDiscovered(v); - } else if (aData.name().EqualsLiteral("CharacteristicsDiscovered")) { - HandleCharacteristicsDiscovered(v); - } else { - BT_WARNING("Not handling GATT Service signal: %s", - NS_ConvertUTF16toUTF8(aData.name()).get()); - } + nsRefPtr characteristic = + mCharacteristics.ElementAt(index); + characteristic->AssignDescriptors(aDescriptorIds); } JSObject* diff --git a/dom/bluetooth/bluetooth2/BluetoothGattService.h b/dom/bluetooth/bluetooth2/BluetoothGattService.h index 16eebef4c4..2199ff63b3 100644 --- a/dom/bluetooth/bluetooth2/BluetoothGattService.h +++ b/dom/bluetooth/bluetooth2/BluetoothGattService.h @@ -17,13 +17,14 @@ BEGIN_BLUETOOTH_NAMESPACE +class BluetoothGatt; class BluetoothSignal; class BluetoothValue; class BluetoothGattService final : public nsISupports , public nsWrapperCache - , public BluetoothSignalObserver { + friend class BluetoothGatt; public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BluetoothGattService) @@ -71,8 +72,6 @@ public: return mServiceId; } - void Notify(const BluetoothSignal& aData); // BluetoothSignalObserver - nsPIDOMWindow* GetParentObject() const { return mOwner; @@ -92,20 +91,36 @@ private: * Add newly discovered GATT included services into mIncludedServices and * update the cache value of mIncludedServices. * - * @param aValue [in] BluetoothValue which contains an array of - * BluetoothGattServiceId of all discovered included - * services. + * @param aServiceIds [in] An array of BluetoothGattServiceId for each + * included service that belongs to this service. */ - void HandleIncludedServicesDiscovered(const BluetoothValue& aValue); + void AssignIncludedServices( + const nsTArray& aServiceIds); /** * Add newly discovered GATT characteristics into mCharacteristics and * update the cache value of mCharacteristics. * - * @param aValue [in] BluetoothValue which contains an array of - * BluetoothGattId of all discovered characteristics. + * @param aCharacteristics [in] An array of BluetoothGattCharAttribute for + * each characteristic that belongs to this + * service. */ - void HandleCharacteristicsDiscovered(const BluetoothValue& aValue); + void AssignCharacteristics( + const nsTArray& aCharacteristics); + + /** + * Add newly discovered GATT descriptors into mDescriptors of + * BluetoothGattCharacteristic and update the cache value of mDescriptors. + * + * @param aCharacteristicId [in] BluetoothGattId of a characteristic that + * belongs to this service. + * @param aDescriptorIds [in] An array of BluetoothGattId for each descriptor + * that belongs to the characteristic referred by + * aCharacteristicId. + */ + void AssignDescriptors( + const BluetoothGattId& aCharacteristicId, + const nsTArray& aDescriptorIds); /**************************************************************************** * Variables diff --git a/dom/bluetooth/bluez/BluetoothSocket.cpp b/dom/bluetooth/bluez/BluetoothSocket.cpp index adbc9082db..57e5a40dd3 100644 --- a/dom/bluetooth/bluez/BluetoothSocket.cpp +++ b/dom/bluetooth/bluez/BluetoothSocket.cpp @@ -8,9 +8,8 @@ #include #include "BluetoothSocketObserver.h" #include "BluetoothUnixSocketConnector.h" -#include "mozilla/unused.h" -#include "nsTArray.h" -#include "nsThreadUtils.h" +#include "mozilla/RefPtr.h" +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR #include "nsXULAppAPI.h" using namespace mozilla::ipc; @@ -28,7 +27,8 @@ class BluetoothSocket::BluetoothSocketIO final , public DataSocketIO { public: - BluetoothSocketIO(MessageLoop* mIOLoop, + BluetoothSocketIO(MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, BluetoothSocket* aConsumer, UnixSocketConnector* aConnector); ~BluetoothSocketIO(); @@ -82,23 +82,23 @@ public: SocketBase* GetSocketBase() override; - bool IsShutdownOnMainThread() const override; + bool IsShutdownOnConsumerThread() const override; bool IsShutdownOnIOThread() const override; - void ShutdownOnMainThread() override; + void ShutdownOnConsumerThread() override; void ShutdownOnIOThread() override; private: - class ReceiveRunnable; + class ReceiveTask; void FireSocketError(); /** - * Consumer pointer. Non-thread safe RefPtr, so should only be manipulated - * directly from main thread. All non-main-thread accesses should happen with - * mIO as container. + * Consumer pointer. Non-thread-safe pointer, so should only be manipulated + * directly from consumer thread. All non-consumer-thread accesses should + * happen with mIO as container. */ - RefPtr mConsumer; + BluetoothSocket* mConsumer; /** * Connector object used to create the connection we are currently using. @@ -121,7 +121,8 @@ private: struct sockaddr_storage mAddress; /** - * Task member for delayed connect task. Should only be access on main thread. + * Task member for delayed connect task. Should only be access on consumer + * thread. */ CancelableTask* mDelayedConnectTask; @@ -132,10 +133,12 @@ private: }; BluetoothSocket::BluetoothSocketIO::BluetoothSocketIO( - MessageLoop* mIOLoop, + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, BluetoothSocket* aConsumer, UnixSocketConnector* aConnector) - : UnixSocketWatcher(mIOLoop) + : UnixSocketWatcher(aIOLoop) + , DataSocketIO(aConsumerLoop) , mConsumer(aConsumer) , mConnector(aConnector) , mShuttingDownOnIOThread(false) @@ -144,12 +147,16 @@ BluetoothSocket::BluetoothSocketIO::BluetoothSocketIO( { MOZ_ASSERT(mConsumer); MOZ_ASSERT(mConnector); + + MOZ_COUNT_CTOR_INHERITED(BluetoothSocketIO, DataSocketIO); } BluetoothSocket::BluetoothSocketIO::~BluetoothSocketIO() { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(IsShutdownOnMainThread()); + MOZ_ASSERT(IsConsumerThread()); + MOZ_ASSERT(IsShutdownOnConsumerThread()); + + MOZ_COUNT_DTOR_INHERITED(BluetoothSocketIO, DataSocketIO); } void @@ -176,7 +183,7 @@ BluetoothSocket::BluetoothSocketIO::GetSocketAddr(nsAString& aAddrStr) const BluetoothSocket* BluetoothSocket::BluetoothSocketIO::GetBluetoothSocket() { - return mConsumer.get(); + return mConsumer; } DataSocket* @@ -188,7 +195,7 @@ BluetoothSocket::BluetoothSocketIO::GetDataSocket() void BluetoothSocket::BluetoothSocketIO::SetDelayedConnectTask(CancelableTask* aTask) { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(IsConsumerThread()); mDelayedConnectTask = aTask; } @@ -196,7 +203,7 @@ BluetoothSocket::BluetoothSocketIO::SetDelayedConnectTask(CancelableTask* aTask) void BluetoothSocket::BluetoothSocketIO::ClearDelayedConnectTask() { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(IsConsumerThread()); mDelayedConnectTask = nullptr; } @@ -204,7 +211,7 @@ BluetoothSocket::BluetoothSocketIO::ClearDelayedConnectTask() void BluetoothSocket::BluetoothSocketIO::CancelDelayedConnectTask() { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(IsConsumerThread()); if (!mDelayedConnectTask) { return; @@ -277,8 +284,8 @@ BluetoothSocket::BluetoothSocketIO::OnConnected() MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); - NS_DispatchToMainThread( - new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS)); + GetConsumerThread()->PostTask( + FROM_HERE, new SocketEventTask(this, SocketEventTask::CONNECT_SUCCESS)); AddWatchers(READ_WATCHER, true); if (HasPendingData()) { @@ -326,8 +333,8 @@ BluetoothSocket::BluetoothSocketIO::OnSocketCanAcceptWithoutBlocking() Close(); SetSocket(fd, SOCKET_IS_CONNECTED); - NS_DispatchToMainThread( - new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS)); + GetConsumerThread()->PostTask( + FROM_HERE, new SocketEventTask(this, SocketEventTask::CONNECT_SUCCESS)); AddWatchers(READ_WATCHER, true); if (HasPendingData()) { @@ -341,7 +348,7 @@ BluetoothSocket::BluetoothSocketIO::OnSocketCanReceiveWithoutBlocking() MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); // see bug 990984 - ssize_t res = ReceiveData(GetFd(), this); + ssize_t res = ReceiveData(GetFd()); if (res < 0) { /* I/O error */ RemoveWatchers(READ_WATCHER|WRITE_WATCHER); @@ -357,7 +364,7 @@ BluetoothSocket::BluetoothSocketIO::OnSocketCanSendWithoutBlocking() MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); // see bug 990984 - nsresult rv = SendPendingData(GetFd(), this); + nsresult rv = SendPendingData(GetFd()); if (NS_FAILED(rv)) { return; } @@ -375,10 +382,9 @@ BluetoothSocket::BluetoothSocketIO::FireSocketError() // Clean up watchers, statuses, fds Close(); - // Tell the main thread we've errored - NS_DispatchToMainThread( - new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR)); - + // Tell the consumer thread we've errored + GetConsumerThread()->PostTask( + FROM_HERE, new SocketEventTask(this, SocketEventTask::CONNECT_ERROR)); } // |DataSocketIO| @@ -398,36 +404,34 @@ BluetoothSocket::BluetoothSocketIO::QueryReceiveBuffer( } /** - * |ReceiveRunnable| transfers data received on the I/O thread - * to an instance of |BluetoothSocket| on the main thread. + * |ReceiveTask| transfers data received on the I/O thread + * to an instance of |BluetoothSocket| on the consumer thread. */ -class BluetoothSocket::BluetoothSocketIO::ReceiveRunnable final - : public SocketIORunnable +class BluetoothSocket::BluetoothSocketIO::ReceiveTask final + : public SocketTask { public: - ReceiveRunnable(BluetoothSocketIO* aIO, UnixSocketBuffer* aBuffer) - : SocketIORunnable(aIO) + ReceiveTask(BluetoothSocketIO* aIO, UnixSocketBuffer* aBuffer) + : SocketTask(aIO) , mBuffer(aBuffer) { } - NS_IMETHOD Run() override + void Run() override { - MOZ_ASSERT(NS_IsMainThread()); + BluetoothSocketIO* io = SocketTask::GetIO(); - BluetoothSocketIO* io = SocketIORunnable::GetIO(); + MOZ_ASSERT(io->IsConsumerThread()); - if (NS_WARN_IF(io->IsShutdownOnMainThread())) { + if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) { // Since we've already explicitly closed and the close // happened before this, this isn't really an error. - return NS_OK; + return; } BluetoothSocket* bluetoothSocket = io->GetBluetoothSocket(); MOZ_ASSERT(bluetoothSocket); bluetoothSocket->ReceiveSocketData(mBuffer); - - return NS_OK; } private: @@ -437,7 +441,8 @@ private: void BluetoothSocket::BluetoothSocketIO::ConsumeBuffer() { - NS_DispatchToMainThread(new ReceiveRunnable(this, mBuffer.forget())); + GetConsumerThread()->PostTask(FROM_HERE, + new ReceiveTask(this, mBuffer.forget())); } void @@ -455,18 +460,18 @@ BluetoothSocket::BluetoothSocketIO::GetSocketBase() } bool -BluetoothSocket::BluetoothSocketIO::IsShutdownOnMainThread() const +BluetoothSocket::BluetoothSocketIO::IsShutdownOnConsumerThread() const { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(IsConsumerThread()); return mConsumer == nullptr; } void -BluetoothSocket::BluetoothSocketIO::ShutdownOnMainThread() +BluetoothSocket::BluetoothSocketIO::ShutdownOnConsumerThread() { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!IsShutdownOnMainThread()); + MOZ_ASSERT(IsConsumerThread()); + MOZ_ASSERT(!IsShutdownOnConsumerThread()); mConsumer = nullptr; } @@ -480,7 +485,7 @@ BluetoothSocket::BluetoothSocketIO::IsShutdownOnIOThread() const void BluetoothSocket::BluetoothSocketIO::ShutdownOnIOThread() { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!IsConsumerThread()); MOZ_ASSERT(!mShuttingDownOnIOThread); Close(); // will also remove fd from I/O loop @@ -502,7 +507,7 @@ public: void Run() override { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!GetIO()->IsConsumerThread()); if (!IsCanceled()) { GetIO()->Listen(); @@ -520,7 +525,7 @@ public: void Run() override { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!GetIO()->IsConsumerThread()); MOZ_ASSERT(!IsCanceled()); GetIO()->Connect(); @@ -537,19 +542,19 @@ public: void Run() override { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(GetIO()->IsConsumerThread()); if (IsCanceled()) { return; } BluetoothSocketIO* io = GetIO(); - if (io->IsShutdownOnMainThread()) { + if (io->IsShutdownOnConsumerThread()) { return; } io->ClearDelayedConnectTask(); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new ConnectTask(io)); + io->GetIOLoop()->PostTask(FROM_HERE, new ConnectTask(io)); } }; @@ -562,11 +567,15 @@ BluetoothSocket::BluetoothSocket(BluetoothSocketObserver* aObserver) , mIO(nullptr) { MOZ_ASSERT(aObserver); + + MOZ_COUNT_CTOR_INHERITED(BluetoothSocket, DataSocket); } BluetoothSocket::~BluetoothSocket() { MOZ_ASSERT(!mIO); + + MOZ_COUNT_DTOR_INHERITED(BluetoothSocket, DataSocket); } nsresult @@ -576,7 +585,6 @@ BluetoothSocket::Connect(const nsAString& aDeviceAddress, int aChannel, bool aAuth, bool aEncrypt) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!aDeviceAddress.IsEmpty()); nsAutoPtr connector( @@ -603,8 +611,6 @@ BluetoothSocket::Listen(const nsAString& aServiceName, int aChannel, bool aAuth, bool aEncrypt) { - MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr connector( new BluetoothUnixSocketConnector(NS_LITERAL_CSTRING(BLUETOOTH_ADDRESS_NONE), aType, aChannel, aAuth, aEncrypt)); @@ -625,7 +631,6 @@ BluetoothSocket::Listen(const nsAString& aServiceName, void BluetoothSocket::ReceiveSocketData(nsAutoPtr& aBuffer) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mObserver); mObserver->ReceiveSocketData(this, aBuffer); @@ -645,39 +650,57 @@ BluetoothSocket::SendSocketData(const nsACString& aStr) nsresult BluetoothSocket::Connect(BluetoothUnixSocketConnector* aConnector, - int aDelayMs) + int aDelayMs, + MessageLoop* aConsumerLoop, MessageLoop* aIOLoop) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aConnector); + MOZ_ASSERT(aConsumerLoop); + MOZ_ASSERT(aIOLoop); MOZ_ASSERT(!mIO); - MessageLoop* ioLoop = XRE_GetIOMessageLoop(); - mIO = new BluetoothSocketIO(ioLoop, this, aConnector); + mIO = new BluetoothSocketIO(aConsumerLoop, aIOLoop, this, aConnector); SetConnectionStatus(SOCKET_CONNECTING); + if (aDelayMs > 0) { DelayedConnectTask* connectTask = new DelayedConnectTask(mIO); mIO->SetDelayedConnectTask(connectTask); MessageLoop::current()->PostDelayedTask(FROM_HERE, connectTask, aDelayMs); } else { - ioLoop->PostTask(FROM_HERE, new ConnectTask(mIO)); + aIOLoop->PostTask(FROM_HERE, new ConnectTask(mIO)); } + + return NS_OK; +} + +nsresult +BluetoothSocket::Connect(BluetoothUnixSocketConnector* aConnector, + int aDelayMs) +{ + return Connect(aConnector, aDelayMs, MessageLoop::current(), + XRE_GetIOMessageLoop()); +} + +nsresult +BluetoothSocket::Listen(BluetoothUnixSocketConnector* aConnector, + MessageLoop* aConsumerLoop, MessageLoop* aIOLoop) +{ + MOZ_ASSERT(aConnector); + MOZ_ASSERT(aConsumerLoop); + MOZ_ASSERT(aIOLoop); + MOZ_ASSERT(!mIO); + + mIO = new BluetoothSocketIO(aConsumerLoop, aIOLoop, this, aConnector); + SetConnectionStatus(SOCKET_LISTENING); + + aIOLoop->PostTask(FROM_HERE, new ListenTask(mIO)); + return NS_OK; } nsresult BluetoothSocket::Listen(BluetoothUnixSocketConnector* aConnector) { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(aConnector); - MOZ_ASSERT(!mIO); - - MessageLoop* ioLoop = XRE_GetIOMessageLoop(); - - mIO = new BluetoothSocketIO(ioLoop, this, aConnector); - SetConnectionStatus(SOCKET_LISTENING); - ioLoop->PostTask(FROM_HERE, new ListenTask(mIO)); - - return NS_OK; + return Listen(aConnector, MessageLoop::current(), XRE_GetIOMessageLoop()); } void @@ -696,11 +719,11 @@ BluetoothSocket::GetAddress(nsAString& aAddrStr) void BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mIO); - MOZ_ASSERT(!mIO->IsShutdownOnMainThread()); + MOZ_ASSERT(mIO->IsConsumerThread()); + MOZ_ASSERT(!mIO->IsShutdownOnConsumerThread()); - XRE_GetIOMessageLoop()->PostTask( + mIO->GetIOLoop()->PostTask( FROM_HERE, new SocketIOSendTask(mIO, aBuffer)); } @@ -710,20 +733,19 @@ BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer) void BluetoothSocket::Close() { - MOZ_ASSERT(NS_IsMainThread()); if (!mIO) { return; } + MOZ_ASSERT(mIO->IsConsumerThread()); + mIO->CancelDelayedConnectTask(); // From this point on, we consider mIO as being deleted. // We sever the relationship here so any future calls to listen or connect // will create a new implementation. - mIO->ShutdownOnMainThread(); - - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO)); - + mIO->ShutdownOnConsumerThread(); + mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO)); mIO = nullptr; NotifyDisconnect(); @@ -732,7 +754,6 @@ BluetoothSocket::Close() void BluetoothSocket::OnConnectSuccess() { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mObserver); mObserver->OnSocketConnectSuccess(this); } @@ -740,7 +761,6 @@ BluetoothSocket::OnConnectSuccess() void BluetoothSocket::OnConnectError() { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mObserver); mObserver->OnSocketConnectError(this); } @@ -748,7 +768,6 @@ BluetoothSocket::OnConnectError() void BluetoothSocket::OnDisconnect() { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mObserver); mObserver->OnSocketDisconnect(this); } diff --git a/dom/bluetooth/bluez/BluetoothSocket.h b/dom/bluetooth/bluez/BluetoothSocket.h index 0ea997a12c..0ab6c9e4c7 100644 --- a/dom/bluetooth/bluez/BluetoothSocket.h +++ b/dom/bluetooth/bluez/BluetoothSocket.h @@ -8,13 +8,12 @@ #define mozilla_dom_bluetooth_BluetoothSocket_h #include "BluetoothCommon.h" -#include #include "mozilla/ipc/DataSocket.h" #include "mozilla/ipc/UnixSocketWatcher.h" -#include "mozilla/RefPtr.h" #include "nsAutoPtr.h" #include "nsString.h" -#include "nsThreadUtils.h" + +class MessageLoop; BEGIN_BLUETOOTH_NAMESPACE @@ -41,7 +40,7 @@ public: /** * Method to be called whenever data is received. This is only called on the - * main thread. + * consumer thread. * * @param aBuffer Data received from the socket. */ @@ -58,6 +57,19 @@ public: */ bool SendSocketData(const nsACString& aMessage); + /** + * Starts a task on the socket that will try to connect to a socket in a + * non-blocking manner. + * + * @param aConnector Connector object for socket type specific functions + * @param aDelayMs Time delay in milli-seconds. + * @param aConsumerLoop The socket's consumer thread. + * @param aIOLoop The socket's I/O thread. + * @return NS_OK on success, or an XPCOM error code otherwise. + */ + nsresult Connect(BluetoothUnixSocketConnector* aConnector, int aDelayMs, + MessageLoop* aConsumerLoop, MessageLoop* aIOLoop); + /** * Starts a task on the socket that will try to connect to a socket in a * non-blocking manner. @@ -69,6 +81,18 @@ public: nsresult Connect(BluetoothUnixSocketConnector* aConnector, int aDelayMs = 0); + /** + * Starts a task on the socket that will try to accept a new connection in a + * non-blocking manner. + * + * @param aConnector Connector object for socket type specific functions + * @param aConsumerLoop The socket's consumer thread. + * @param aIOLoop The socket's I/O thread. + * @return NS_OK on success, or an XPCOM error code otherwise. + */ + nsresult Listen(BluetoothUnixSocketConnector* aConnector, + MessageLoop* aConsumerLoop, MessageLoop* aIOLoop); + /** * Starts a task on the socket that will try to accept a new connection in a * non-blocking manner. diff --git a/dom/bluetooth/bluez/BluetoothUnixSocketConnector.cpp b/dom/bluetooth/bluez/BluetoothUnixSocketConnector.cpp index 0578b4b81a..4429fd4238 100644 --- a/dom/bluetooth/bluez/BluetoothUnixSocketConnector.cpp +++ b/dom/bluetooth/bluez/BluetoothUnixSocketConnector.cpp @@ -30,6 +30,7 @@ #include #include #include +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR #include "nsThreadUtils.h" // For NS_IsMainThread. using namespace mozilla::ipc; @@ -52,10 +53,14 @@ BluetoothUnixSocketConnector::BluetoothUnixSocketConnector( , mChannel(aChannel) , mAuth(aAuth) , mEncrypt(aEncrypt) -{ } +{ + MOZ_COUNT_CTOR_INHERITED(BluetoothUnixSocketConnector, UnixSocketConnector); +} BluetoothUnixSocketConnector::~BluetoothUnixSocketConnector() -{ } +{ + MOZ_COUNT_DTOR_INHERITED(BluetoothUnixSocketConnector, UnixSocketConnector); +} nsresult BluetoothUnixSocketConnector::CreateSocket(int& aFd) const diff --git a/dom/broadcastchannel/BroadcastChannel.cpp b/dom/broadcastchannel/BroadcastChannel.cpp index bd0367249c..db8a39c614 100644 --- a/dom/broadcastchannel/BroadcastChannel.cpp +++ b/dom/broadcastchannel/BroadcastChannel.cpp @@ -38,7 +38,8 @@ public: NS_INLINE_DECL_REFCOUNTING(BroadcastChannelMessage) BroadcastChannelMessage() - : StructuredCloneHelper(CloningSupported, TransferringNotSupported) + : StructuredCloneHelper(CloningSupported, TransferringNotSupported, + DifferentProcess) {} private: @@ -502,14 +503,6 @@ BroadcastChannel::PostMessageInternal(JSContext* aCx, return; } - const nsTArray>& blobImpls = data->BlobImpls(); - for (uint32_t i = 0, len = blobImpls.Length(); i < len; ++i) { - if (!blobImpls[i]->MayBeClonedToOtherThreads()) { - aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); - return; - } - } - PostMessageData(data); } diff --git a/dom/broadcastchannel/BroadcastChannelChild.cpp b/dom/broadcastchannel/BroadcastChannelChild.cpp index 892b4c8e30..f19c01ff18 100644 --- a/dom/broadcastchannel/BroadcastChannelChild.cpp +++ b/dom/broadcastchannel/BroadcastChannelChild.cpp @@ -11,11 +11,11 @@ #include "mozilla/dom/File.h" #include "mozilla/dom/MessageEvent.h" #include "mozilla/dom/MessageEventBinding.h" -#include "mozilla/dom/StructuredCloneHelper.h" #include "mozilla/dom/WorkerPrivate.h" #include "mozilla/dom/WorkerScope.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/ipc/PBackgroundChild.h" +#include "mozilla/dom/ipc/StructuredCloneData.h" #include "WorkerPrivate.h" namespace mozilla { @@ -85,18 +85,17 @@ BroadcastChannelChild::RecvNotify(const ClonedMessageData& aData) return true; } - JSContext* cx = jsapi.cx(); + ipc::StructuredCloneData cloneData; + cloneData.BlobImpls().AppendElements(blobs); + const SerializedStructuredCloneBuffer& buffer = aData.data(); - StructuredCloneHelper cloneHelper(StructuredCloneHelper::CloningSupported, - StructuredCloneHelper::TransferringNotSupported); - - cloneHelper.BlobImpls().AppendElements(blobs); + cloneData.UseExternalData(buffer.data, buffer.dataLength); + JSContext* cx = jsapi.cx(); JS::Rooted value(cx, JS::NullValue()); if (buffer.dataLength) { ErrorResult rv; - cloneHelper.ReadFromBuffer(mBC->GetParentObject(), cx, - buffer.data, buffer.dataLength, &value, rv); + cloneData.Read(cx, &value, rv); if (NS_WARN_IF(rv.Failed())) { return true; } diff --git a/dom/canvas/ImageBitmap.cpp b/dom/canvas/ImageBitmap.cpp index 13fc4a4628..139c745334 100644 --- a/dom/canvas/ImageBitmap.cpp +++ b/dom/canvas/ImageBitmap.cpp @@ -7,11 +7,11 @@ #include "mozilla/dom/ImageBitmap.h" #include "mozilla/dom/ImageBitmapBinding.h" #include "mozilla/dom/Promise.h" +#include "mozilla/dom/StructuredCloneTags.h" #include "mozilla/dom/WorkerPrivate.h" #include "mozilla/dom/WorkerRunnable.h" #include "mozilla/gfx/2D.h" #include "imgTools.h" -#include "js/StructuredClone.h" #include "libyuv.h" #include "nsLayoutUtils.h" diff --git a/dom/fetch/ChannelInfo.cpp b/dom/fetch/ChannelInfo.cpp index bf49e530ce..4c1ef0d660 100644 --- a/dom/fetch/ChannelInfo.cpp +++ b/dom/fetch/ChannelInfo.cpp @@ -48,7 +48,7 @@ ChannelInfo::InitFromChannel(nsIChannel* aChannel) } void -ChannelInfo::InitFromIPCChannelInfo(const ipc::IPCChannelInfo& aChannelInfo) +ChannelInfo::InitFromIPCChannelInfo(const mozilla::ipc::IPCChannelInfo& aChannelInfo) { MOZ_ASSERT(!mInited, "Cannot initialize the object twice"); @@ -136,7 +136,7 @@ ChannelInfo::ResurrectInfoOnChannel(nsIChannel* aChannel) return NS_OK; } -ipc::IPCChannelInfo +mozilla::ipc::IPCChannelInfo ChannelInfo::AsIPCChannelInfo() const { // This may be called when mInited is false, for example if we try to store diff --git a/dom/html/HTMLIFrameElement.h b/dom/html/HTMLIFrameElement.h index 5aa32e43b4..e96e7508d8 100644 --- a/dom/html/HTMLIFrameElement.h +++ b/dom/html/HTMLIFrameElement.h @@ -159,6 +159,15 @@ public: { SetHTMLAttr(nsGkAtoms::marginheight, aMarginHeight, aError); } + void SetReferrer(const nsAString& aReferrer, ErrorResult& aError) + { + SetHTMLAttr(nsGkAtoms::referrer, aReferrer, aError); + } + void GetReferrer(nsAString& aReferrer) + { + GetHTMLAttr(nsGkAtoms::referrer, aReferrer); + } + nsIDocument* GetSVGDocument() { return GetContentDocument(); diff --git a/dom/ipc/ContentBridgeChild.cpp b/dom/ipc/ContentBridgeChild.cpp index fc72ea5097..f84c53db8b 100644 --- a/dom/ipc/ContentBridgeChild.cpp +++ b/dom/ipc/ContentBridgeChild.cpp @@ -7,7 +7,6 @@ #include "mozilla/dom/ContentBridgeChild.h" #include "mozilla/dom/ContentChild.h" #include "mozilla/dom/File.h" -#include "mozilla/dom/StructuredCloneUtils.h" #include "mozilla/dom/TabChild.h" #include "mozilla/dom/ipc/BlobChild.h" #include "mozilla/jsipc/CrossProcessObjectWrappers.h" diff --git a/dom/ipc/ContentBridgeParent.cpp b/dom/ipc/ContentBridgeParent.cpp index b269928b60..612882c39b 100644 --- a/dom/ipc/ContentBridgeParent.cpp +++ b/dom/ipc/ContentBridgeParent.cpp @@ -76,7 +76,7 @@ ContentBridgeParent::RecvSyncMessage(const nsString& aMsg, const ClonedMessageData& aData, InfallibleTArray&& aCpows, const IPC::Principal& aPrincipal, - nsTArray* aRetvals) + nsTArray* aRetvals) { return nsIContentParent::RecvSyncMessage(aMsg, aData, Move(aCpows), aPrincipal, aRetvals); diff --git a/dom/ipc/ContentBridgeParent.h b/dom/ipc/ContentBridgeParent.h index 3b2c0e3807..a82059b9d0 100644 --- a/dom/ipc/ContentBridgeParent.h +++ b/dom/ipc/ContentBridgeParent.h @@ -19,7 +19,6 @@ class ContentBridgeParent : public PContentBridgeParent , public nsIContentParent , public nsIObserver { - typedef mozilla::OwningSerializedStructuredCloneBuffer OwningSerializedStructuredCloneBuffer; public: explicit ContentBridgeParent(Transport* aTransport); @@ -83,7 +82,7 @@ protected: const ClonedMessageData& aData, InfallibleTArray&& aCpows, const IPC::Principal& aPrincipal, - nsTArray* aRetvals) override; + nsTArray* aRetvals) override; virtual bool RecvAsyncMessage(const nsString& aMsg, const ClonedMessageData& aData, InfallibleTArray&& aCpows, diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index dcc1e0c27a..323a6e5365 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -174,13 +174,13 @@ #endif #include "ProcessUtils.h" -#include "StructuredCloneUtils.h" #include "URIUtils.h" #include "nsContentUtils.h" #include "nsIPrincipal.h" #include "nsDeviceStorage.h" #include "DomainPolicy.h" #include "mozilla/dom/DataStoreService.h" +#include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/dom/telephony/PTelephonyChild.h" #include "mozilla/dom/time/DateCacheCleaner.h" #include "mozilla/dom/voicemail/VoicemailIPCService.h" @@ -789,7 +789,7 @@ ContentChild::InitXPCOM() bool isConnected; ClipboardCapabilities clipboardCaps; DomainPolicyClone domainPolicy; - OwningSerializedStructuredCloneBuffer initialData; + StructuredCloneData initialData; SendGetXPCOMProcessAttributes(&isOffline, &isConnected, &isLangRTL, &mAvailableDictionaries, @@ -821,9 +821,10 @@ ContentChild::InitXPCOM() if (NS_WARN_IF(!jsapi.Init(xpc::PrivilegedJunkScope()))) { MOZ_CRASH(); } + ErrorResult rv; JS::RootedValue data(jsapi.cx()); - if (!JS_ReadStructuredClone(jsapi.cx(), initialData.data, initialData.dataLength, - JS_STRUCTURED_CLONE_VERSION, &data, nullptr, nullptr)) { + initialData.Read(jsapi.cx(), &data, rv); + if (NS_WARN_IF(rv.Failed())) { MOZ_CRASH(); } ProcessGlobal* global = ProcessGlobal::Get(); @@ -2042,10 +2043,11 @@ ContentChild::RecvAsyncMessage(const nsString& aMsg, { nsRefPtr cpm = nsFrameMessageManager::GetChildProcessManager(); if (cpm) { - StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForChild(aData); + StructuredCloneData data; + ipc::UnpackClonedMessageDataForChild(aData, data); CrossProcessCpowHolder cpows(this, aCpows); cpm->ReceiveMessage(static_cast(cpm.get()), nullptr, - aMsg, false, &cloneData, &cpows, aPrincipal, nullptr); + aMsg, false, &data, &cpows, aPrincipal, nullptr); } return true; } @@ -2834,4 +2836,3 @@ ContentChild::RecvTestGraphicsDeviceReset(const uint32_t& aResetReason) } // namespace dom } // namespace mozilla - diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 82118e9fb6..103849001b 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -148,7 +148,6 @@ #include "SandboxHal.h" #include "ScreenManagerParent.h" #include "SourceSurfaceRawData.h" -#include "StructuredCloneUtils.h" #include "TabParent.h" #include "URIUtils.h" #include "nsIWebBrowserChrome.h" @@ -159,6 +158,7 @@ #include "prio.h" #include "private/pprio.h" #include "ContentProcessManager.h" +#include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/psm/PSMContentListener.h" #include "nsPluginHost.h" #include "nsPluginTags.h" @@ -2904,7 +2904,7 @@ ContentParent::OnNewProcessCreated(uint32_t aPid, InfallibleTArray unusedDictionaries; ClipboardCapabilities clipboardCaps; DomainPolicyClone domainPolicy; - OwningSerializedStructuredCloneBuffer initialData; + StructuredCloneData initialData; RecvGetXPCOMProcessAttributes(&isOffline, &isConnected, &isLangRTL, &unusedDictionaries, @@ -3224,7 +3224,7 @@ ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline, InfallibleTArray* dictionaries, ClipboardCapabilities* clipboardCaps, DomainPolicyClone* domainPolicy, - OwningSerializedStructuredCloneBuffer* initialData) + StructuredCloneData* aInitialData) { nsCOMPtr io(do_GetIOService()); MOZ_ASSERT(io, "No IO service?"); @@ -3271,12 +3271,11 @@ ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline, return false; } - JSAutoStructuredCloneBuffer buffer; - if (!buffer.write(jsapi.cx(), init)) { + ErrorResult rv; + aInitialData->Write(jsapi.cx(), init, rv); + if (NS_WARN_IF(rv.Failed())) { return false; } - - buffer.steal(&initialData->data, &initialData->dataLength); } return true; @@ -4091,7 +4090,7 @@ ContentParent::RecvSyncMessage(const nsString& aMsg, const ClonedMessageData& aData, InfallibleTArray&& aCpows, const IPC::Principal& aPrincipal, - nsTArray* aRetvals) + nsTArray* aRetvals) { return nsIContentParent::RecvSyncMessage(aMsg, aData, Move(aCpows), aPrincipal, aRetvals); @@ -4102,7 +4101,7 @@ ContentParent::RecvRpcMessage(const nsString& aMsg, const ClonedMessageData& aData, InfallibleTArray&& aCpows, const IPC::Principal& aPrincipal, - nsTArray* aRetvals) + nsTArray* aRetvals) { return nsIContentParent::RecvRpcMessage(aMsg, aData, Move(aCpows), aPrincipal, aRetvals); @@ -4335,12 +4334,12 @@ ContentParent::DoLoadMessageManagerScript(const nsAString& aURL, bool ContentParent::DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, - const mozilla::dom::StructuredCloneData& aData, + StructuredCloneData& aHelper, JS::Handle aCpows, nsIPrincipal* aPrincipal) { ClonedMessageData data; - if (!BuildClonedMessageDataForParent(this, aData, data)) { + if (!BuildClonedMessageDataForParent(this, aHelper, data)) { return false; } InfallibleTArray cpows; diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 8a92af31c5..0b7512bd03 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -82,7 +82,6 @@ class ContentParent final : public PContentParent typedef mozilla::ipc::TestShellParent TestShellParent; typedef mozilla::ipc::URIParams URIParams; typedef mozilla::dom::ClonedMessageData ClonedMessageData; - typedef mozilla::OwningSerializedStructuredCloneBuffer OwningSerializedStructuredCloneBuffer; public: #ifdef MOZ_NUWA_PROCESS @@ -198,7 +197,7 @@ public: bool aRunInGlobalScope) override; virtual bool DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, - const mozilla::dom::StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) override; virtual bool CheckPermission(const nsAString& aPermission) override; @@ -568,7 +567,7 @@ private: InfallibleTArray* dictionaries, ClipboardCapabilities* clipboardCaps, DomainPolicyClone* domainPolicy, - OwningSerializedStructuredCloneBuffer* initialData) override; + StructuredCloneData* initialData) override; virtual bool DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*) override; @@ -724,12 +723,12 @@ private: const ClonedMessageData& aData, InfallibleTArray&& aCpows, const IPC::Principal& aPrincipal, - nsTArray* aRetvals) override; + nsTArray* aRetvals) override; virtual bool RecvRpcMessage(const nsString& aMsg, const ClonedMessageData& aData, InfallibleTArray&& aCpows, const IPC::Principal& aPrincipal, - nsTArray* aRetvals) override; + nsTArray* aRetvals) override; virtual bool RecvAsyncMessage(const nsString& aMsg, const ClonedMessageData& aData, InfallibleTArray&& aCpows, diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 9173b585c4..71133d098a 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -63,7 +63,7 @@ using mozilla::WritingMode from "mozilla/WritingModes.h"; using mozilla::layers::TouchBehaviorFlags from "mozilla/layers/APZUtils.h"; using nsIWidget::TouchPointerState from "nsIWidget.h"; using struct LookAndFeelInt from "mozilla/widget/WidgetMessageUtils.h"; -using struct mozilla::OwningSerializedStructuredCloneBuffer from "ipc/IPCMessageUtils.h"; +using class mozilla::dom::ipc::StructuredCloneData from "ipc/IPCMessageUtils.h"; using mozilla::EventMessage from "mozilla/EventForwards.h"; using nsEventStatus from "mozilla/EventForwards.h"; using nsSizeMode from "nsIWidgetListener.h"; @@ -180,11 +180,11 @@ parent: sync SyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows, Principal aPrincipal) - returns (OwningSerializedStructuredCloneBuffer[] retval); + returns (StructuredCloneData[] retval); prio(high) sync RpcMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows, Principal aPrincipal) - returns (OwningSerializedStructuredCloneBuffer[] retval); + returns (StructuredCloneData[] retval); /** * Notifies chrome that there is a focus change involving an editable diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 1424513d3e..41f6fc827d 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -85,7 +85,7 @@ using gfxIntSize from "nsSize.h"; using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h"; using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h"; using struct LookAndFeelInt from "mozilla/widget/WidgetMessageUtils.h"; -using struct mozilla::OwningSerializedStructuredCloneBuffer from "ipc/IPCMessageUtils.h"; +using class mozilla::dom::ipc::StructuredCloneData from "ipc/IPCMessageUtils.h"; union ChromeRegistryItem { @@ -676,7 +676,7 @@ parent: returns (bool isOffline, bool isConnected, bool isLangRTL, nsString[] dictionaries, ClipboardCapabilities clipboardCaps, DomainPolicyClone domainPolicy, - OwningSerializedStructuredCloneBuffer initialData); + StructuredCloneData initialData); sync CreateChildProcess(IPCTabContext context, ProcessPriority priority, @@ -791,11 +791,11 @@ parent: sync SyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows, Principal aPrincipal) - returns (OwningSerializedStructuredCloneBuffer[] retval); + returns (StructuredCloneData[] retval); prio(high) sync RpcMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows, Principal aPrincipal) - returns (OwningSerializedStructuredCloneBuffer[] retval); + returns (StructuredCloneData[] retval); ShowAlertNotification(nsString imageUrl, nsString title, diff --git a/dom/ipc/PContentBridge.ipdl b/dom/ipc/PContentBridge.ipdl index 0003a6f095..502f1fa066 100644 --- a/dom/ipc/PContentBridge.ipdl +++ b/dom/ipc/PContentBridge.ipdl @@ -16,7 +16,7 @@ include PTabContext; using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h"; using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h"; using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h"; -using struct mozilla::OwningSerializedStructuredCloneBuffer from "ipc/IPCMessageUtils.h"; +using class mozilla::dom::ipc::StructuredCloneData from "ipc/IPCMessageUtils.h"; namespace mozilla { namespace dom { @@ -40,7 +40,7 @@ prio(normal upto urgent) sync protocol PContentBridge parent: sync SyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows, Principal aPrincipal) - returns (OwningSerializedStructuredCloneBuffer[] retval); + returns (StructuredCloneData[] retval); both: // Both the parent and the child can construct the PBrowser. // See the comment in PContent::PBrowser(). diff --git a/dom/ipc/StructuredCloneData.cpp b/dom/ipc/StructuredCloneData.cpp new file mode 100644 index 0000000000..3ea6b33831 --- /dev/null +++ b/dom/ipc/StructuredCloneData.cpp @@ -0,0 +1,146 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=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 "StructuredCloneData.h" + +#include "nsIDOMDOMException.h" +#include "nsIMutable.h" +#include "nsIXPConnect.h" + +#include "mozilla/dom/BindingUtils.h" +#include "mozilla/dom/BlobBinding.h" +#include "mozilla/dom/File.h" +#include "mozilla/dom/ToJSValue.h" +#include "nsContentUtils.h" +#include "nsJSEnvironment.h" +#include "MainThreadUtils.h" +#include "StructuredCloneTags.h" +#include "jsapi.h" + +namespace mozilla { +namespace dom { +namespace ipc { + +bool +StructuredCloneData::Copy(const StructuredCloneData& aData) +{ + if (!aData.mData) { + return true; + } + + uint64_t* data = static_cast(js_malloc(aData.mDataLength)); + if (!data) { + return false; + } + + memcpy(data, aData.mData, aData.mDataLength); + + mData = data; + mDataLength = aData.mDataLength; + mDataOwned = eJSAllocated; + + MOZ_ASSERT(BlobImpls().IsEmpty()); + BlobImpls().AppendElements(aData.BlobImpls()); + + MOZ_ASSERT(GetImages().IsEmpty()); + + return true; +} + +void +StructuredCloneData::Read(JSContext* aCx, + JS::MutableHandle aValue, + ErrorResult &aRv) +{ + MOZ_ASSERT(mData); + + nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx)); + MOZ_ASSERT(global); + + ReadFromBuffer(global, aCx, mData, mDataLength, aValue, aRv); +} + +void +StructuredCloneData::Write(JSContext* aCx, + JS::Handle aValue, + ErrorResult &aRv) +{ + MOZ_ASSERT(!mData); + + StructuredCloneHelper::Write(aCx, aValue, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return; + } + + mBuffer->steal(&mData, &mDataLength); + mBuffer = nullptr; + mDataOwned = eJSAllocated; +} + +void +StructuredCloneData::WriteIPCParams(Message* aMsg) const +{ + WriteParam(aMsg, mDataLength); + + if (mDataLength) { + // Structured clone data must be 64-bit aligned. + aMsg->WriteBytes(mData, mDataLength, sizeof(uint64_t)); + } +} + +bool +StructuredCloneData::ReadIPCParams(const IPC::Message* aMsg, + void** aIter) +{ + MOZ_ASSERT(!mData); + + if (!ReadParam(aMsg, aIter, &mDataLength)) { + return false; + } + + if (!mDataLength) { + return true; + } + + const char** buffer = + const_cast(reinterpret_cast(&mData)); + // Structured clone data must be 64-bit aligned. + if (!aMsg->ReadBytes(aIter, buffer, mDataLength, sizeof(uint64_t))) { + return false; + } + + uint64_t* data = static_cast(js_malloc(mDataLength)); + if (!data) { + return false; + } + + memcpy(data, mData, mDataLength); + mData = data; + mDataOwned = eJSAllocated; + return true; +} + +bool +StructuredCloneData::CopyExternalData(const void* aData, + size_t aDataLength) +{ + MOZ_ASSERT(!mData); + uint64_t* data = static_cast(js_malloc(aDataLength)); + if (!data) { + return false; + } + + memcpy(data, aData, aDataLength); + mData = data; + mDataLength = aDataLength; + mDataOwned = eJSAllocated; + + return true; +} + +} // namespace ipc +} // namespace dom +} // namespace mozilla diff --git a/dom/ipc/StructuredCloneData.h b/dom/ipc/StructuredCloneData.h new file mode 100644 index 0000000000..73125e041d --- /dev/null +++ b/dom/ipc/StructuredCloneData.h @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=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/. */ + +#ifndef mozilla_dom_ipc_StructuredCloneData_h +#define mozilla_dom_ipc_StructuredCloneData_h + +#include "mozilla/dom/StructuredCloneHelper.h" + +namespace IPC { +class Message; +} + +namespace mozilla { +namespace dom { +namespace ipc { + +class StructuredCloneData : public StructuredCloneHelper +{ +public: + StructuredCloneData() + : StructuredCloneHelper(StructuredCloneHelper::CloningSupported, + StructuredCloneHelper::TransferringNotSupported, + StructuredCloneHelper::DifferentProcess) + , mData(nullptr) + , mDataLength(0) + , mDataOwned(eNone) + {} + + StructuredCloneData(const StructuredCloneData&) = delete; + + ~StructuredCloneData() + { + if (mDataOwned == eJSAllocated) { + js_free(mData); + } + } + + StructuredCloneData& + operator=(const StructuredCloneData& aOther) = delete; + + const nsTArray>& BlobImpls() const + { + return mBlobImplArray; + } + + nsTArray>& BlobImpls() + { + return mBlobImplArray; + } + + bool Copy(const StructuredCloneData& aData); + + void Read(JSContext* aCx, + JS::MutableHandle aValue, + ErrorResult &aRv); + + void Write(JSContext* aCx, + JS::Handle aValue, + ErrorResult &aRv); + + void UseExternalData(uint64_t* aData, size_t aDataLength) + { + MOZ_ASSERT(!mData); + mData = aData; + mDataLength = aDataLength; + MOZ_ASSERT(mDataOwned == eNone); + } + + bool CopyExternalData(const void* aData, size_t aDataLength); + + uint64_t* Data() const + { + return mData; + } + + size_t DataLength() const + { + return mDataLength; + } + + // For IPC serialization + void WriteIPCParams(IPC::Message* aMessage) const; + bool ReadIPCParams(const IPC::Message* aMessage, void** aIter); + +private: + uint64_t* mData; + size_t mDataLength; + enum { + eNone, + eJSAllocated, + } mDataOwned; +}; + +} // namespace ipc +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_ipc_StructuredCloneData_h diff --git a/dom/ipc/StructuredCloneUtils.cpp b/dom/ipc/StructuredCloneUtils.cpp deleted file mode 100644 index de2fb029a9..0000000000 --- a/dom/ipc/StructuredCloneUtils.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=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 "StructuredCloneUtils.h" - -#include "nsIDOMDOMException.h" -#include "nsIMutable.h" -#include "nsIXPConnect.h" - -#include "mozilla/dom/BindingUtils.h" -#include "mozilla/dom/BlobBinding.h" -#include "mozilla/dom/File.h" -#include "mozilla/dom/ToJSValue.h" -#include "nsContentUtils.h" -#include "nsJSEnvironment.h" -#include "MainThreadUtils.h" -#include "StructuredCloneTags.h" -#include "jsapi.h" - -using namespace mozilla::dom; - -namespace { - -void -Error(JSContext* aCx, uint32_t aErrorId) -{ - if (NS_IsMainThread()) { - NS_DOMStructuredCloneError(aCx, aErrorId); - } else { - Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR); - } -} - -JSObject* -Read(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag, - uint32_t aData, void* aClosure) -{ - MOZ_ASSERT(aClosure); - - StructuredCloneClosure* closure = - static_cast(aClosure); - - if (aTag == SCTAG_DOM_BLOB) { - // nsRefPtr needs to go out of scope before toObjectOrNull() is - // called because the static analysis thinks dereferencing XPCOM objects - // can GC (because in some cases it can!), and a return statement with a - // JSObject* type means that JSObject* is on the stack as a raw pointer - // while destructors are running. - JS::Rooted val(aCx); - { - MOZ_ASSERT(aData < closure->mBlobImpls.Length()); - nsRefPtr blobImpl = closure->mBlobImpls[aData]; - -#ifdef DEBUG - { - // Blob should not be mutable. - bool isMutable; - MOZ_ASSERT(NS_SUCCEEDED(blobImpl->GetMutable(&isMutable))); - MOZ_ASSERT(!isMutable); - } -#endif - - // Let's create a new blob with the correct parent. - nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx)); - MOZ_ASSERT(global); - - nsRefPtr newBlob = Blob::Create(global, blobImpl); - if (!ToJSValue(aCx, newBlob, &val)) { - return nullptr; - } - } - - return &val.toObject(); - } - - return NS_DOMReadStructuredClone(aCx, aReader, aTag, aData, nullptr); -} - -bool -Write(JSContext* aCx, JSStructuredCloneWriter* aWriter, - JS::Handle aObj, void* aClosure) -{ - MOZ_ASSERT(aClosure); - - StructuredCloneClosure* closure = - static_cast(aClosure); - - // See if the wrapped native is a File/Blob. - { - Blob* blob = nullptr; - if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, aObj, blob)) && - NS_SUCCEEDED(blob->SetMutable(false)) && - JS_WriteUint32Pair(aWriter, SCTAG_DOM_BLOB, - closure->mBlobImpls.Length())) { - closure->mBlobImpls.AppendElement(blob->Impl()); - return true; - } - } - - return NS_DOMWriteStructuredClone(aCx, aWriter, aObj, nullptr); -} - -const JSStructuredCloneCallbacks gCallbacks = { - Read, - Write, - Error, - nullptr, - nullptr, - nullptr -}; - -} // namespace - -namespace mozilla { -namespace dom { - -bool -ReadStructuredClone(JSContext* aCx, uint64_t* aData, size_t aDataLength, - const StructuredCloneClosure& aClosure, - JS::MutableHandle aClone) -{ - void* closure = &const_cast(aClosure); - return !!JS_ReadStructuredClone(aCx, aData, aDataLength, - JS_STRUCTURED_CLONE_VERSION, aClone, - &gCallbacks, closure); -} - -bool -WriteStructuredClone(JSContext* aCx, JS::Handle aSource, - JSAutoStructuredCloneBuffer& aBuffer, - StructuredCloneClosure& aClosure) -{ - return aBuffer.write(aCx, aSource, &gCallbacks, &aClosure); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/ipc/StructuredCloneUtils.h b/dom/ipc/StructuredCloneUtils.h deleted file mode 100644 index f8d1c37d7d..0000000000 --- a/dom/ipc/StructuredCloneUtils.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=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/. */ - -#ifndef mozilla_dom_StructuredCloneUtils_h -#define mozilla_dom_StructuredCloneUtils_h - -#include "nsCOMPtr.h" -#include "nsTArray.h" -#include "mozilla/dom/File.h" - -#include "js/StructuredClone.h" - -namespace mozilla { -namespace dom { - -struct -StructuredCloneClosure -{ - nsTArray> mBlobImpls; -}; - -struct -StructuredCloneData -{ - StructuredCloneData() : mData(nullptr), mDataLength(0) {} - uint64_t* mData; - size_t mDataLength; - StructuredCloneClosure mClosure; -}; - -bool -ReadStructuredClone(JSContext* aCx, uint64_t* aData, size_t aDataLength, - const StructuredCloneClosure& aClosure, - JS::MutableHandle aClone); - -inline bool -ReadStructuredClone(JSContext* aCx, const StructuredCloneData& aData, - JS::MutableHandle aClone) -{ - return ReadStructuredClone(aCx, aData.mData, aData.mDataLength, - aData.mClosure, aClone); -} - -bool -WriteStructuredClone(JSContext* aCx, JS::Handle aSource, - JSAutoStructuredCloneBuffer& aBuffer, - StructuredCloneClosure& aClosure); - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_StructuredCloneUtils_h diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 95874e1461..245e2f143c 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -75,7 +75,7 @@ #include "nsWindowWatcher.h" #include "PermissionMessageUtils.h" #include "PuppetWidget.h" -#include "StructuredCloneUtils.h" +#include "StructuredCloneData.h" #include "nsViewportInfo.h" #include "nsILoadContext.h" #include "ipc/nsGUIEventIPC.h" @@ -229,15 +229,16 @@ TabChildBase::DispatchMessageManagerMessage(const nsAString& aMessageName, { AutoSafeJSContext cx; JS::Rooted json(cx, JS::NullValue()); - StructuredCloneData cloneData; - JSAutoStructuredCloneBuffer buffer; + StructuredCloneData data; if (JS_ParseJSON(cx, static_cast(aJSONData.BeginReading()), aJSONData.Length(), &json)) { - WriteStructuredClone(cx, json, buffer, cloneData.mClosure); - cloneData.mData = buffer.data(); - cloneData.mDataLength = buffer.nbytes(); + ErrorResult rv; + data.Write(cx, json, rv); + if (NS_WARN_IF(rv.Failed())) { + return; + } } nsCOMPtr kungFuDeathGrip(GetGlobal()); @@ -246,7 +247,7 @@ TabChildBase::DispatchMessageManagerMessage(const nsAString& aMessageName, nsRefPtr mm = static_cast(mTabChildGlobal->mMessageManager.get()); mm->ReceiveMessage(static_cast(mTabChildGlobal), nullptr, - aMessageName, false, &cloneData, nullptr, nullptr, nullptr); + aMessageName, false, &data, nullptr, nullptr, nullptr); } bool @@ -2396,12 +2397,13 @@ TabChild::RecvAsyncMessage(const nsString& aMessage, { if (mTabChildGlobal) { nsCOMPtr kungFuDeathGrip(GetGlobal()); - StructuredCloneData cloneData = UnpackClonedMessageDataForChild(aData); + StructuredCloneData data; + UnpackClonedMessageDataForChild(aData, data); nsRefPtr mm = static_cast(mTabChildGlobal->mMessageManager.get()); CrossProcessCpowHolder cpows(Manager(), aCpows); mm->ReceiveMessage(static_cast(mTabChildGlobal), nullptr, - aMessage, false, &cloneData, &cpows, aPrincipal, nullptr); + aMessage, false, &data, &cpows, aPrincipal, nullptr); } return true; } @@ -2823,10 +2825,10 @@ TabChild::SetTabId(const TabId& aTabId) bool TabChild::DoSendBlockingMessage(JSContext* aCx, const nsAString& aMessage, - const StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal, - nsTArray* aRetVal, + nsTArray* aRetVal, bool aIsSync) { ClonedMessageData data; @@ -2849,7 +2851,7 @@ TabChild::DoSendBlockingMessage(JSContext* aCx, bool TabChild::DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, - const StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) { diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 38ff2d39de..4299994f61 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -228,7 +228,6 @@ class TabChild final : public TabChildBase, public nsITooltipListener { typedef mozilla::dom::ClonedMessageData ClonedMessageData; - typedef mozilla::OwningSerializedStructuredCloneBuffer OwningSerializedStructuredCloneBuffer; typedef mozilla::layout::RenderFrameChild RenderFrameChild; typedef mozilla::layers::APZEventState APZEventState; typedef mozilla::layers::SetTargetAPZCCallback SetTargetAPZCCallback; @@ -277,14 +276,14 @@ public: */ virtual bool DoSendBlockingMessage(JSContext* aCx, const nsAString& aMessage, - const mozilla::dom::StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal, - nsTArray* aRetVal, + nsTArray* aRetVal, bool aIsSync) override; virtual bool DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage, - const mozilla::dom::StructuredCloneData& aData, + StructuredCloneData& aData, JS::Handle aCpows, nsIPrincipal* aPrincipal) override; virtual bool DoUpdateZoomConstraints(const uint32_t& aPresShellId, @@ -522,11 +521,6 @@ protected: private: /** * Create a new TabChild object. - * - * |aOwnOrContainingAppId| is the app-id of our frame or of the closest app - * frame in the hierarchy which contains us. - * - * |aIsBrowserElement| indicates whether we're a browser (but not an app). */ TabChild(nsIContentChild* aManager, const TabId& aTabId, diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index d1d3325287..b304973fa2 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -78,7 +78,7 @@ #include "nsWindowWatcher.h" #include "private/pprio.h" #include "PermissionMessageUtils.h" -#include "StructuredCloneUtils.h" +#include "StructuredCloneData.h" #include "ColorPickerParent.h" #include "FilePickerParent.h" #include "TabChild.h" @@ -1806,7 +1806,7 @@ TabParent::RecvSyncMessage(const nsString& aMessage, const ClonedMessageData& aData, InfallibleTArray&& aCpows, const IPC::Principal& aPrincipal, - nsTArray* aRetVal) + nsTArray* aRetVal) { // FIXME Permission check for TabParent in Content process nsIPrincipal* principal = aPrincipal; @@ -1818,9 +1818,11 @@ TabParent::RecvSyncMessage(const nsString& aMessage, } } - StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); + StructuredCloneData data; + ipc::UnpackClonedMessageDataForParent(aData, data); + CrossProcessCpowHolder cpows(Manager(), aCpows); - return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aRetVal); + return ReceiveMessage(aMessage, true, &data, &cpows, aPrincipal, aRetVal); } bool @@ -1828,7 +1830,7 @@ TabParent::RecvRpcMessage(const nsString& aMessage, const ClonedMessageData& aData, InfallibleTArray&& aCpows, const IPC::Principal& aPrincipal, - nsTArray* aRetVal) + nsTArray* aRetVal) { // FIXME Permission check for TabParent in Content process nsIPrincipal* principal = aPrincipal; @@ -1840,9 +1842,11 @@ TabParent::RecvRpcMessage(const nsString& aMessage, } } - StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); + StructuredCloneData data; + ipc::UnpackClonedMessageDataForParent(aData, data); + CrossProcessCpowHolder cpows(Manager(), aCpows); - return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aRetVal); + return ReceiveMessage(aMessage, true, &data, &cpows, aPrincipal, aRetVal); } bool @@ -1861,9 +1865,11 @@ TabParent::RecvAsyncMessage(const nsString& aMessage, } } - StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); + StructuredCloneData data; + ipc::UnpackClonedMessageDataForParent(aData, data); + CrossProcessCpowHolder cpows(Manager(), aCpows); - return ReceiveMessage(aMessage, false, &cloneData, &cpows, aPrincipal, nullptr); + return ReceiveMessage(aMessage, false, &data, &cpows, aPrincipal, nullptr); } bool @@ -2590,10 +2596,10 @@ TabParent::RecvDispatchFocusToTopLevelWindow() bool TabParent::ReceiveMessage(const nsString& aMessage, bool aSync, - const StructuredCloneData* aCloneData, + StructuredCloneData* aData, CpowHolder* aCpows, nsIPrincipal* aPrincipal, - nsTArray* aRetVal) + nsTArray* aRetVal) { nsRefPtr frameLoader = GetFrameLoader(true); if (frameLoader && frameLoader->GetFrameMessageManager()) { @@ -2604,7 +2610,7 @@ TabParent::ReceiveMessage(const nsString& aMessage, frameLoader, aMessage, aSync, - aCloneData, + aData, aCpows, aPrincipal, aRetVal); diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index 19e6c99314..b44d996dee 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -66,7 +66,10 @@ class ClonedMessageData; class nsIContentParent; class Element; class DataTransfer; -struct StructuredCloneData; + +namespace ipc { +class StructuredCloneData; +} // ipc namespace class TabParent final : public PBrowserParent , public nsIDOMEventListener @@ -78,7 +81,6 @@ class TabParent final : public PBrowserParent , public nsAPostRefreshObserver { typedef mozilla::dom::ClonedMessageData ClonedMessageData; - typedef mozilla::OwningSerializedStructuredCloneBuffer OwningSerializedStructuredCloneBuffer; virtual ~TabParent(); @@ -152,12 +154,12 @@ public: const ClonedMessageData& aData, InfallibleTArray&& aCpows, const IPC::Principal& aPrincipal, - nsTArray* aRetVal) override; + nsTArray* aRetVal) override; virtual bool RecvRpcMessage(const nsString& aMessage, const ClonedMessageData& aData, InfallibleTArray&& aCpows, const IPC::Principal& aPrincipal, - nsTArray* aRetVal) override; + nsTArray* aRetVal) override; virtual bool RecvAsyncMessage(const nsString& aMessage, const ClonedMessageData& aData, InfallibleTArray&& aCpows, @@ -433,10 +435,10 @@ public: protected: bool ReceiveMessage(const nsString& aMessage, bool aSync, - const StructuredCloneData* aCloneData, + ipc::StructuredCloneData* aData, mozilla::jsipc::CpowHolder* aCpows, nsIPrincipal* aPrincipal, - nsTArray* aJSONRetVal = nullptr); + nsTArray* aJSONRetVal = nullptr); virtual bool RecvAsyncAuthPrompt(const nsCString& aUri, const nsString& aRealm, diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build index 3603352aad..7a3b2b61c9 100644 --- a/dom/ipc/moz.build +++ b/dom/ipc/moz.build @@ -19,6 +19,7 @@ EXPORTS.mozilla.dom.ipc += [ 'BlobParent.h', 'IdType.h', 'nsIRemoteBlob.h', + 'StructuredCloneData.h', ] EXPORTS.mozilla.dom += [ @@ -35,7 +36,6 @@ EXPORTS.mozilla.dom += [ 'NuwaChild.h', 'NuwaParent.h', 'PermissionMessageUtils.h', - 'StructuredCloneUtils.h', 'TabChild.h', 'TabContext.h', 'TabMessageUtils.h', @@ -67,7 +67,7 @@ UNIFIED_SOURCES += [ 'PreallocatedProcessManager.cpp', 'ProcessPriorityManager.cpp', 'ScreenManagerParent.cpp', - 'StructuredCloneUtils.cpp', + 'StructuredCloneData.cpp', 'TabChild.cpp', 'TabContext.cpp', 'TabMessageUtils.cpp', diff --git a/dom/ipc/nsIContentChild.cpp b/dom/ipc/nsIContentChild.cpp index 814d3d73bc..a3b3edf706 100644 --- a/dom/ipc/nsIContentChild.cpp +++ b/dom/ipc/nsIContentChild.cpp @@ -10,9 +10,9 @@ #include "mozilla/dom/DOMTypes.h" #include "mozilla/dom/File.h" #include "mozilla/dom/PermissionMessageUtils.h" -#include "mozilla/dom/StructuredCloneUtils.h" #include "mozilla/dom/TabChild.h" #include "mozilla/dom/ipc/BlobChild.h" +#include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/ipc/InputStreamUtils.h" #include "nsPrintfCString.h" @@ -117,10 +117,12 @@ nsIContentChild::RecvAsyncMessage(const nsString& aMsg, { nsRefPtr cpm = nsFrameMessageManager::GetChildProcessManager(); if (cpm) { - StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForChild(aData); + ipc::StructuredCloneData data; + ipc::UnpackClonedMessageDataForChild(aData, data); + CrossProcessCpowHolder cpows(this, aCpows); cpm->ReceiveMessage(static_cast(cpm.get()), nullptr, - aMsg, false, &cloneData, &cpows, aPrincipal, nullptr); + aMsg, false, &data, &cpows, aPrincipal, nullptr); } return true; } diff --git a/dom/ipc/nsIContentParent.cpp b/dom/ipc/nsIContentParent.cpp index 71b4cdc747..6d78aa4393 100644 --- a/dom/ipc/nsIContentParent.cpp +++ b/dom/ipc/nsIContentParent.cpp @@ -13,9 +13,9 @@ #include "mozilla/dom/ContentBridgeParent.h" #include "mozilla/dom/PTabContext.h" #include "mozilla/dom/PermissionMessageUtils.h" -#include "mozilla/dom/StructuredCloneUtils.h" #include "mozilla/dom/TabParent.h" #include "mozilla/dom/ipc/BlobParent.h" +#include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/jsipc/CrossProcessObjectWrappers.h" #include "mozilla/unused.h" @@ -187,7 +187,7 @@ nsIContentParent::RecvSyncMessage(const nsString& aMsg, const ClonedMessageData& aData, InfallibleTArray&& aCpows, const IPC::Principal& aPrincipal, - nsTArray* aRetvals) + nsTArray* aRetvals) { // FIXME Permission check in Content process nsIPrincipal* principal = aPrincipal; @@ -201,10 +201,12 @@ nsIContentParent::RecvSyncMessage(const nsString& aMsg, nsRefPtr ppm = mMessageManager; if (ppm) { - StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); + ipc::StructuredCloneData data; + ipc::UnpackClonedMessageDataForParent(aData, data); + CrossProcessCpowHolder cpows(this, aCpows); ppm->ReceiveMessage(static_cast(ppm.get()), nullptr, - aMsg, true, &cloneData, &cpows, aPrincipal, aRetvals); + aMsg, true, &data, &cpows, aPrincipal, aRetvals); } return true; } @@ -214,7 +216,7 @@ nsIContentParent::RecvRpcMessage(const nsString& aMsg, const ClonedMessageData& aData, InfallibleTArray&& aCpows, const IPC::Principal& aPrincipal, - nsTArray* aRetvals) + nsTArray* aRetvals) { // FIXME Permission check in Content process nsIPrincipal* principal = aPrincipal; @@ -228,10 +230,12 @@ nsIContentParent::RecvRpcMessage(const nsString& aMsg, nsRefPtr ppm = mMessageManager; if (ppm) { - StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); + ipc::StructuredCloneData data; + ipc::UnpackClonedMessageDataForParent(aData, data); + CrossProcessCpowHolder cpows(this, aCpows); ppm->ReceiveMessage(static_cast(ppm.get()), nullptr, - aMsg, true, &cloneData, &cpows, aPrincipal, aRetvals); + aMsg, true, &data, &cpows, aPrincipal, aRetvals); } return true; } @@ -254,10 +258,12 @@ nsIContentParent::RecvAsyncMessage(const nsString& aMsg, nsRefPtr ppm = mMessageManager; if (ppm) { - StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); + ipc::StructuredCloneData data; + ipc::UnpackClonedMessageDataForParent(aData, data); + CrossProcessCpowHolder cpows(this, aCpows); ppm->ReceiveMessage(static_cast(ppm.get()), nullptr, - aMsg, false, &cloneData, &cpows, aPrincipal, nullptr); + aMsg, false, &data, &cpows, aPrincipal, nullptr); } return true; } diff --git a/dom/ipc/nsIContentParent.h b/dom/ipc/nsIContentParent.h index 29a50f25d1..b1aaba59b4 100644 --- a/dom/ipc/nsIContentParent.h +++ b/dom/ipc/nsIContentParent.h @@ -47,8 +47,6 @@ class nsIContentParent : public nsISupports , public mozilla::dom::ipc::MessageManagerCallback , public CPOWManagerGetter { - typedef mozilla::OwningSerializedStructuredCloneBuffer OwningSerializedStructuredCloneBuffer; - public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICONTENTPARENT_IID) @@ -104,12 +102,12 @@ protected: // IPDL methods const ClonedMessageData& aData, InfallibleTArray&& aCpows, const IPC::Principal& aPrincipal, - nsTArray* aRetvals); + nsTArray* aRetvals); virtual bool RecvRpcMessage(const nsString& aMsg, const ClonedMessageData& aData, InfallibleTArray&& aCpows, const IPC::Principal& aPrincipal, - nsTArray* aRetvals); + nsTArray* aRetvals); virtual bool RecvAsyncMessage(const nsString& aMsg, const ClonedMessageData& aData, InfallibleTArray&& aCpows, diff --git a/dom/media/systemservices/MediaParent.cpp b/dom/media/systemservices/MediaParent.cpp index 06c2a90c05..64fae22963 100644 --- a/dom/media/systemservices/MediaParent.cpp +++ b/dom/media/systemservices/MediaParent.cpp @@ -15,8 +15,9 @@ #include "nsThreadUtils.h" #include "nsNetCID.h" #include "nsNetUtil.h" -#include "nsIOutputStream.h" +#include "nsIInputStream.h" #include "nsILineInputStream.h" +#include "nsIOutputStream.h" #include "nsISafeOutputStream.h" #include "nsAppDirectoryServiceDefs.h" #include "nsISupportsImpl.h" diff --git a/dom/messagechannel/MessagePort.cpp b/dom/messagechannel/MessagePort.cpp index c969b2ee1f..9aa49c053f 100644 --- a/dom/messagechannel/MessagePort.cpp +++ b/dom/messagechannel/MessagePort.cpp @@ -140,9 +140,12 @@ public: event->SetTrusted(true); event->SetSource(mPort); + nsTArray> ports; + mData->TakeTransferredPorts(ports); + nsRefPtr portList = new MessagePortList(static_cast(event.get()), - mData->GetTransferredPorts()); + ports); event->SetPorts(portList); bool dummy; diff --git a/dom/messagechannel/SharedMessagePortMessage.cpp b/dom/messagechannel/SharedMessagePortMessage.cpp index 55ce97e6dc..1528f2ee62 100644 --- a/dom/messagechannel/SharedMessagePortMessage.cpp +++ b/dom/messagechannel/SharedMessagePortMessage.cpp @@ -51,14 +51,6 @@ SharedMessagePortMessage::Write(JSContext* aCx, return; } - const nsTArray>& blobImpls = BlobImpls(); - for (uint32_t i = 0, len = blobImpls.Length(); i < len; ++i) { - if (!blobImpls[i]->MayBeClonedToOtherThreads()) { - aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); - return; - } - } - FallibleTArray cloneData; MoveBufferDataToArray(cloneData, aRv); diff --git a/dom/messagechannel/SharedMessagePortMessage.h b/dom/messagechannel/SharedMessagePortMessage.h index d2dbb800fd..1a7e777e10 100644 --- a/dom/messagechannel/SharedMessagePortMessage.h +++ b/dom/messagechannel/SharedMessagePortMessage.h @@ -23,7 +23,8 @@ public: nsTArray mData; SharedMessagePortMessage() - : StructuredCloneHelper(CloningSupported, TransferringSupported) + : StructuredCloneHelper(CloningSupported, TransferringSupported, + DifferentProcess) {} void Read(nsISupports* aParent, diff --git a/dom/promise/Promise.cpp b/dom/promise/Promise.cpp index 31657ae90c..49b6596ea2 100644 --- a/dom/promise/Promise.cpp +++ b/dom/promise/Promise.cpp @@ -21,6 +21,7 @@ #include "mozilla/dom/ScriptSettings.h" #include "jsfriendapi.h" +#include "js/StructuredClone.h" #include "nsContentUtils.h" #include "nsGlobalWindow.h" #include "nsIScriptObjectPrincipal.h" diff --git a/dom/push/PushManager.cpp b/dom/push/PushManager.cpp index 1e4e22fbf5..5e8e0977c8 100644 --- a/dom/push/PushManager.cpp +++ b/dom/push/PushManager.cpp @@ -20,6 +20,7 @@ #include "nsIPrincipal.h" #include "nsIPushClient.h" +#include "nsComponentManagerUtils.h" #include "nsFrameMessageManager.h" #include "nsContentCID.h" diff --git a/dom/system/gonk/SystemWorkerManager.h b/dom/system/gonk/SystemWorkerManager.h index d5b4a33a81..bdb977f2d4 100644 --- a/dom/system/gonk/SystemWorkerManager.h +++ b/dom/system/gonk/SystemWorkerManager.h @@ -64,7 +64,7 @@ private: nsCOMPtr mWifiWorker; - nsRefPtr mKeyStore; + nsRefPtr mKeyStore; bool mShutdown; }; diff --git a/dom/webidl/HTMLIFrameElement.webidl b/dom/webidl/HTMLIFrameElement.webidl index ec8e7676f0..53f06424bd 100644 --- a/dom/webidl/HTMLIFrameElement.webidl +++ b/dom/webidl/HTMLIFrameElement.webidl @@ -26,6 +26,8 @@ interface HTMLIFrameElement : HTMLElement { attribute DOMString width; [SetterThrows, Pure] attribute DOMString height; + [SetterThrows, Pure, Pref="network.http.enablePerElementReferrer"] + attribute DOMString referrer; readonly attribute Document? contentDocument; readonly attribute WindowProxy? contentWindow; }; diff --git a/dom/workers/DataStore.cpp b/dom/workers/DataStore.cpp index a033497220..1558314ea8 100644 --- a/dom/workers/DataStore.cpp +++ b/dom/workers/DataStore.cpp @@ -224,7 +224,8 @@ public: const nsAString& aRevisionId, ErrorResult& aRv) : DataStoreProxyRunnable(aWorkerPrivate, aBackingStore, aWorkerPromise) - , StructuredCloneHelper(CloningNotSupported, TransferringNotSupported) + , StructuredCloneHelper(CloningNotSupported, TransferringNotSupported, + SameProcessDifferentThread) , mId(aId) , mRevisionId(aRevisionId) , mRv(aRv) @@ -285,7 +286,8 @@ public: const nsAString& aRevisionId, ErrorResult& aRv) : DataStoreProxyRunnable(aWorkerPrivate, aBackingStore, aWorkerPromise) - , StructuredCloneHelper(CloningNotSupported, TransferringNotSupported) + , StructuredCloneHelper(CloningNotSupported, TransferringNotSupported, + SameProcessDifferentThread) , mId(aId) , mRevisionId(aRevisionId) , mRv(aRv) diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp index 0beca9e53f..21beedfe7d 100644 --- a/dom/workers/ScriptLoader.cpp +++ b/dom/workers/ScriptLoader.cpp @@ -1683,27 +1683,24 @@ ScriptExecutorRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) } } - JS::Rooted global(aCx, JS::CurrentGlobalOrNull(aCx)); - NS_ASSERTION(global, "Must have a global by now!"); + JS::Rooted global(aCx); - // Determine whether we want to be discarding source on this global to save - // memory. It would make more sense to do this when we create the global, but - // the information behind UsesSystemPrincipal() et al isn't finalized until - // the call to SetPrincipal during the first script load. After that, however, - // it never changes. So we can just idempotently set the bits here. - // - // Note that we read a pref that is cached on the main thread. This is benignly - // racey. - if (xpc::ShouldDiscardSystemSource()) { - bool discard = aWorkerPrivate->UsesSystemPrincipal() || - aWorkerPrivate->IsInPrivilegedApp(); - JS::CompartmentOptionsRef(global).setDiscardSource(discard); + if (mIsWorkerScript) { + WorkerGlobalScope* globalScope = + aWorkerPrivate->GetOrCreateGlobalScope(aCx); + if (NS_WARN_IF(!globalScope)) { + NS_WARNING("Failed to make global!"); + return false; + } + + global.set(globalScope->GetWrapper()); + } else { + global.set(JS::CurrentGlobalOrNull(aCx)); } - // Similar to the above. - if (xpc::ExtraWarningsForSystemJS() && aWorkerPrivate->UsesSystemPrincipal()) { - JS::CompartmentOptionsRef(global).extraWarningsOverride().set(true); - } + MOZ_ASSERT(global); + + JSAutoCompartment ac(aCx, global); for (uint32_t index = mFirstIndex; index <= mLastIndex; index++) { ScriptLoadInfo& loadInfo = loadInfos.ElementAt(index); diff --git a/dom/workers/ServiceWorkerClient.cpp b/dom/workers/ServiceWorkerClient.cpp index e52d26629e..0a304ee533 100644 --- a/dom/workers/ServiceWorkerClient.cpp +++ b/dom/workers/ServiceWorkerClient.cpp @@ -13,7 +13,6 @@ #include "nsGlobalWindow.h" #include "nsIDocument.h" #include "WorkerPrivate.h" -#include "WorkerStructuredClone.h" using namespace mozilla; using namespace mozilla::dom; @@ -73,24 +72,18 @@ ServiceWorkerClient::WrapObject(JSContext* aCx, JS::Handle aGivenProt namespace { -class ServiceWorkerClientPostMessageRunnable final : public nsRunnable +class ServiceWorkerClientPostMessageRunnable final + : public nsRunnable + , public StructuredCloneHelper { uint64_t mWindowId; - JSAutoStructuredCloneBuffer mBuffer; - WorkerStructuredCloneClosure mClosure; public: - ServiceWorkerClientPostMessageRunnable(uint64_t aWindowId, - JSAutoStructuredCloneBuffer&& aData, - WorkerStructuredCloneClosure& aClosure) - : mWindowId(aWindowId), - mBuffer(Move(aData)) - { - mClosure.mClonedObjects.SwapElements(aClosure.mClonedObjects); - mClosure.mClonedImages.SwapElements(aClosure.mClonedImages); - MOZ_ASSERT(aClosure.mMessagePorts.IsEmpty()); - mClosure.mMessagePortIdentifiers.SwapElements(aClosure.mMessagePortIdentifiers); - } + explicit ServiceWorkerClientPostMessageRunnable(uint64_t aWindowId) + : StructuredCloneHelper(CloningSupported, TransferringSupported, + SameProcessDifferentThread) + , mWindowId(aWindowId) + {} NS_IMETHOD Run() @@ -123,40 +116,40 @@ private: { AssertIsOnMainThread(); - // Release reference to objects that were AddRef'd for - // cloning into worker when array goes out of scope. - WorkerStructuredCloneClosure closure; - closure.mClonedObjects.SwapElements(mClosure.mClonedObjects); - closure.mClonedImages.SwapElements(mClosure.mClonedImages); - MOZ_ASSERT(mClosure.mMessagePorts.IsEmpty()); - closure.mMessagePortIdentifiers.SwapElements(mClosure.mMessagePortIdentifiers); - closure.mParentWindow = do_QueryInterface(aTargetContainer->GetParentObject()); - JS::Rooted messageData(aCx); - if (!mBuffer.read(aCx, &messageData, - WorkerStructuredCloneCallbacks(), &closure)) { - xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR); + ErrorResult rv; + Read(aTargetContainer->GetParentObject(), aCx, &messageData, rv); + if (NS_WARN_IF(rv.Failed())) { + xpc::Throw(aCx, rv.StealNSResult()); return NS_ERROR_FAILURE; } - nsCOMPtr event = new MessageEvent(aTargetContainer, - nullptr, nullptr); - nsresult rv = - event->InitMessageEvent(NS_LITERAL_STRING("message"), - false /* non-bubbling */, - false /* not cancelable */, - messageData, - EmptyString(), - EmptyString(), - nullptr); - if (NS_FAILED(rv)) { - xpc::Throw(aCx, rv); + nsRefPtr event = new MessageEvent(aTargetContainer, + nullptr, nullptr); + rv = event->InitMessageEvent(NS_LITERAL_STRING("message"), + false /* non-bubbling */, + false /* not cancelable */, + messageData, + EmptyString(), + EmptyString(), + nullptr); + if (NS_WARN_IF(rv.Failed())) { + xpc::Throw(aCx, rv.StealNSResult()); return NS_ERROR_FAILURE; } + nsTArray> ports; + TakeTransferredPorts(ports); + + nsRefPtr portList = + new MessagePortList(static_cast(event.get()), + ports); + event->SetPorts(portList); + event->SetTrusted(true); bool status = false; - aTargetContainer->DispatchEvent(event, &status); + aTargetContainer->DispatchEvent(static_cast(event.get()), + &status); if (!status) { return NS_ERROR_FAILURE; @@ -194,22 +187,17 @@ ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle aMessage, transferable.setObject(*array); } - const JSStructuredCloneCallbacks* callbacks = WorkerStructuredCloneCallbacks(); + nsRefPtr runnable = + new ServiceWorkerClientPostMessageRunnable(mWindowId); - WorkerStructuredCloneClosure closure; - - JSAutoStructuredCloneBuffer buffer; - if (!buffer.write(aCx, aMessage, transferable, callbacks, &closure)) { - aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); + runnable->Write(aCx, aMessage, transferable, aRv); + if (NS_WARN_IF(aRv.Failed())) { return; } - nsRefPtr runnable = - new ServiceWorkerClientPostMessageRunnable(mWindowId, Move(buffer), - closure); - nsresult rv = NS_DispatchToMainThread(runnable); - if (NS_FAILED(rv)) { - aRv.Throw(NS_ERROR_FAILURE); + aRv = NS_DispatchToMainThread(runnable); + if (NS_WARN_IF(aRv.Failed())) { + return; } } diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp index 8e83bf6cd9..f4fd105976 100644 --- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -36,6 +36,7 @@ #include "mozilla/dom/DOMError.h" #include "mozilla/dom/ErrorEvent.h" #include "mozilla/dom/Headers.h" +#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h" #include "mozilla/dom/indexedDB/IDBFactory.h" #include "mozilla/dom/InternalHeaders.h" #include "mozilla/dom/Navigator.h" diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 571e348ef1..e35b1642d4 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -45,15 +45,10 @@ #include "mozilla/Likely.h" #include "mozilla/LoadContext.h" #include "mozilla/dom/BindingUtils.h" -#include "mozilla/dom/BlobBinding.h" #include "mozilla/dom/ErrorEvent.h" #include "mozilla/dom/ErrorEventBinding.h" #include "mozilla/dom/Exceptions.h" #include "mozilla/dom/FunctionBinding.h" -#include "mozilla/dom/ImageBitmap.h" -#include "mozilla/dom/ImageBitmapBinding.h" -#include "mozilla/dom/ImageData.h" -#include "mozilla/dom/ImageDataBinding.h" #include "mozilla/dom/MessageEvent.h" #include "mozilla/dom/MessageEventBinding.h" #include "mozilla/dom/MessagePort.h" @@ -62,26 +57,18 @@ #include "mozilla/dom/Promise.h" #include "mozilla/dom/PromiseDebugging.h" #include "mozilla/dom/ScriptSettings.h" -#include "mozilla/dom/StructuredClone.h" +#include "mozilla/dom/StructuredCloneHelper.h" #include "mozilla/dom/TabChild.h" -#include "mozilla/dom/WebCryptoCommon.h" #include "mozilla/dom/WorkerBinding.h" #include "mozilla/dom/WorkerDebuggerGlobalScopeBinding.h" #include "mozilla/dom/WorkerGlobalScopeBinding.h" #include "mozilla/dom/indexedDB/IDBFactory.h" -#include "mozilla/dom/ipc/BlobChild.h" -#include "mozilla/dom/ipc/nsIRemoteBlob.h" -#include "mozilla/ipc/BackgroundChild.h" -#include "mozilla/ipc/BackgroundUtils.h" -#include "mozilla/ipc/PBackgroundSharedTypes.h" #include "mozilla/Preferences.h" -#include "MultipartBlobImpl.h" #include "nsAlgorithm.h" #include "nsContentUtils.h" #include "nsCycleCollector.h" #include "nsError.h" #include "nsDOMJSUtils.h" -#include "nsFormData.h" #include "nsHostObjectProtocolHandler.h" #include "nsJSEnvironment.h" #include "nsJSUtils.h" @@ -113,7 +100,6 @@ #include "WorkerFeature.h" #include "WorkerRunnable.h" #include "WorkerScope.h" -#include "WorkerStructuredClone.h" #include "WorkerThread.h" #ifdef XP_WIN @@ -327,484 +313,6 @@ LogErrorToConsole(const nsAString& aMessage, fflush(stderr); } -// Recursive! -already_AddRefed -EnsureBlobForBackgroundManager(BlobImpl* aBlobImpl, - PBackgroundChild* aManager = nullptr) -{ - MOZ_ASSERT(aBlobImpl); - - if (!aManager) { - aManager = BackgroundChild::GetForCurrentThread(); - MOZ_ASSERT(aManager); - } - - nsRefPtr blobImpl = aBlobImpl; - - const nsTArray>* subBlobImpls = - aBlobImpl->GetSubBlobImpls(); - - if (!subBlobImpls) { - if (nsCOMPtr remoteBlob = do_QueryObject(blobImpl)) { - // Always make sure we have a blob from an actor we can use on this - // thread. - BlobChild* blobChild = BlobChild::GetOrCreate(aManager, blobImpl); - MOZ_ASSERT(blobChild); - - blobImpl = blobChild->GetBlobImpl(); - MOZ_ASSERT(blobImpl); - - DebugOnly isMutable; - MOZ_ASSERT(NS_SUCCEEDED(blobImpl->GetMutable(&isMutable))); - MOZ_ASSERT(!isMutable); - } else { - MOZ_ALWAYS_TRUE(NS_SUCCEEDED(blobImpl->SetMutable(false))); - } - - return blobImpl.forget(); - } - - const uint32_t subBlobCount = subBlobImpls->Length(); - MOZ_ASSERT(subBlobCount); - - nsTArray> newSubBlobImpls; - newSubBlobImpls.SetLength(subBlobCount); - - bool newBlobImplNeeded = false; - - for (uint32_t index = 0; index < subBlobCount; index++) { - const nsRefPtr& subBlobImpl = subBlobImpls->ElementAt(index); - MOZ_ASSERT(subBlobImpl); - - nsRefPtr& newSubBlobImpl = newSubBlobImpls[index]; - - newSubBlobImpl = EnsureBlobForBackgroundManager(subBlobImpl, aManager); - MOZ_ASSERT(newSubBlobImpl); - - if (subBlobImpl != newSubBlobImpl) { - newBlobImplNeeded = true; - } - } - - if (newBlobImplNeeded) { - nsString contentType; - blobImpl->GetType(contentType); - - if (blobImpl->IsFile()) { - nsString name; - blobImpl->GetName(name); - - blobImpl = new MultipartBlobImpl(newSubBlobImpls, name, contentType); - } else { - blobImpl = new MultipartBlobImpl(newSubBlobImpls, contentType); - } - - MOZ_ALWAYS_TRUE(NS_SUCCEEDED(blobImpl->SetMutable(false))); - } - - return blobImpl.forget(); -} - -already_AddRefed -ReadBlobOrFileNoWrap(JSContext* aCx, - JSStructuredCloneReader* aReader) -{ - MOZ_ASSERT(aCx); - MOZ_ASSERT(aReader); - - nsRefPtr blobImpl; - { - BlobImpl* rawBlobImpl; - MOZ_ALWAYS_TRUE(JS_ReadBytes(aReader, &rawBlobImpl, sizeof(rawBlobImpl))); - - MOZ_ASSERT(rawBlobImpl); - - blobImpl = rawBlobImpl; - } - - blobImpl = EnsureBlobForBackgroundManager(blobImpl); - MOZ_ASSERT(blobImpl); - - nsCOMPtr parent; - if (NS_IsMainThread()) { - nsCOMPtr scriptGlobal = - nsJSUtils::GetStaticScriptGlobal(JS::CurrentGlobalOrNull(aCx)); - parent = do_QueryInterface(scriptGlobal); - } else { - WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); - MOZ_ASSERT(workerPrivate); - - WorkerGlobalScope* globalScope = workerPrivate->GlobalScope(); - MOZ_ASSERT(globalScope); - - parent = do_QueryObject(globalScope); - } - - nsRefPtr blob = Blob::Create(parent, blobImpl); - return blob.forget(); -} - -void -ReadBlobOrFile(JSContext* aCx, - JSStructuredCloneReader* aReader, - JS::MutableHandle aBlobOrFile) -{ - nsRefPtr blob = ReadBlobOrFileNoWrap(aCx, aReader); - aBlobOrFile.set(blob->WrapObject(aCx, nullptr)); -} - -// See WriteFormData for serialization format. -void -ReadFormData(JSContext* aCx, - JSStructuredCloneReader* aReader, - uint32_t aCount, - JS::MutableHandle aFormData) -{ - MOZ_ASSERT(aCx); - MOZ_ASSERT(aReader); - MOZ_ASSERT(!aFormData); - - nsCOMPtr parent; - if (NS_IsMainThread()) { - nsCOMPtr scriptGlobal = - nsJSUtils::GetStaticScriptGlobal(JS::CurrentGlobalOrNull(aCx)); - parent = do_QueryInterface(scriptGlobal); - } else { - WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); - MOZ_ASSERT(workerPrivate); - workerPrivate->AssertIsOnWorkerThread(); - - WorkerGlobalScope* globalScope = workerPrivate->GlobalScope(); - MOZ_ASSERT(globalScope); - - parent = do_QueryObject(globalScope); - } - - nsRefPtr formData = new nsFormData(parent); - MOZ_ASSERT(formData); - - Optional thirdArg; - - uint32_t isFile; - uint32_t dummy; - for (uint32_t i = 0; i < aCount; ++i) { - MOZ_ALWAYS_TRUE(JS_ReadUint32Pair(aReader, &isFile, &dummy)); - - nsAutoString name; - MOZ_ALWAYS_TRUE(ReadString(aReader, name)); - - if (isFile) { - // Read out the tag since the blob reader isn't expecting it. - MOZ_ALWAYS_TRUE(JS_ReadUint32Pair(aReader, &dummy, &dummy)); - nsRefPtr blob = ReadBlobOrFileNoWrap(aCx, aReader); - MOZ_ASSERT(blob); - formData->Append(name, *blob, thirdArg); - } else { - nsAutoString value; - MOZ_ALWAYS_TRUE(ReadString(aReader, value)); - formData->Append(name, value); - } - } - - aFormData.set(formData->WrapObject(aCx, nullptr)); -} - -bool -WriteBlobOrFile(JSStructuredCloneWriter* aWriter, - BlobImpl* aBlobImpl, - WorkerStructuredCloneClosure& aClosure) -{ - MOZ_ASSERT(aWriter); - MOZ_ASSERT(aBlobImpl); - - if (!aBlobImpl->MayBeClonedToOtherThreads()) { - NS_WARNING("Not all the blob implementations can be sent between threads."); - return false; - } - - nsRefPtr blobImpl = EnsureBlobForBackgroundManager(aBlobImpl); - MOZ_ASSERT(blobImpl); - - aBlobImpl = blobImpl; - - if (NS_WARN_IF(!JS_WriteUint32Pair(aWriter, DOMWORKER_SCTAG_BLOB, 0)) || - NS_WARN_IF(!JS_WriteBytes(aWriter, &aBlobImpl, sizeof(aBlobImpl)))) { - return false; - } - - aClosure.mClonedObjects.AppendElement(aBlobImpl); - return true; -} - -// A FormData is serialized as: -// - A pair of ints (tag identifying it as a FormData, number of elements in -// the FormData) -// - for each (key, value) pair: -// - pair of ints (is value a file?, 0). If not a file, value is a string. -// - string name -// - if value is a file: -// - write the file/blob -// - else: -// - string value -bool -WriteFormData(JSContext* aCx, - JSStructuredCloneWriter* aWriter, - nsFormData* aFormData, - WorkerStructuredCloneClosure& aClosure) -{ - MOZ_ASSERT(aCx); - MOZ_ASSERT(aWriter); - MOZ_ASSERT(aFormData); - - if (NS_WARN_IF(!JS_WriteUint32Pair(aWriter, DOMWORKER_SCTAG_FORMDATA, aFormData->Length()))) { - return false; - } - - class MOZ_STACK_CLASS Closure final - { - JSContext* mCx; - JSStructuredCloneWriter* mWriter; - WorkerStructuredCloneClosure& mClones; - - public: - Closure(JSContext* aCx, JSStructuredCloneWriter* aWriter, - WorkerStructuredCloneClosure& aClones) - : mCx(aCx), mWriter(aWriter), mClones(aClones) - { } - - static bool - Write(const nsString& aName, bool isFile, const nsString& aValue, - File* aFile, void* aClosure) - { - Closure* closure = static_cast(aClosure); - if (!JS_WriteUint32Pair(closure->mWriter, /* a file? */ (uint32_t) isFile, 0)) { - return false; - } - - if (!WriteString(closure->mWriter, aName)) { - return false; - } - - if (isFile) { - if (!WriteBlobOrFile(closure->mWriter, aFile->Impl(), - closure->mClones)) { - return false; - } - } else { - if (!WriteString(closure->mWriter, aValue)) { - return false; - } - } - - return true; - } - }; - - Closure closure(aCx, aWriter, aClosure); - return aFormData->ForEach(Closure::Write, &closure); -} - -struct WorkerStructuredCloneCallbacks -{ - static JSObject* - Read(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag, - uint32_t aData, void* aClosure) - { - // See if object is a nsIDOMBlob pointer. - if (aTag == DOMWORKER_SCTAG_BLOB) { - MOZ_ASSERT(!aData); - - JS::Rooted blobOrFile(aCx); - ReadBlobOrFile(aCx, aReader, &blobOrFile); - - return blobOrFile; - } - - // See if the object is an ImageData. - if (aTag == SCTAG_DOM_IMAGEDATA) { - MOZ_ASSERT(!aData); - return ReadStructuredCloneImageData(aCx, aReader); - } - - // See if the object is a FormData. - if (aTag == DOMWORKER_SCTAG_FORMDATA) { - JS::Rooted formData(aCx); - // aData is the entry count. - ReadFormData(aCx, aReader, aData, &formData); - return formData; - } - - // See if the object is an ImageBitmap. - if (aTag == SCTAG_DOM_IMAGEBITMAP) { - NS_ASSERTION(aClosure, "Null pointer!"); - - // Get the current global object. - auto* closure = static_cast(aClosure); - nsCOMPtr parent = do_QueryInterface(closure->mParentWindow); - // aData is the index of the cloned image. - return ImageBitmap::ReadStructuredClone(aCx, aReader, parent, - closure->mClonedImages, aData); - } - - return NS_DOMReadStructuredClone(aCx, aReader, aTag, aData, nullptr); - } - - static bool - Write(JSContext* aCx, JSStructuredCloneWriter* aWriter, - JS::Handle aObj, void* aClosure) - { - NS_ASSERTION(aClosure, "Null pointer!"); - - auto* closure = static_cast(aClosure); - - // See if this is a Blob/File object. - { - nsRefPtr blob; - if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, aObj, blob))) { - BlobImpl* blobImpl = blob->Impl(); - MOZ_ASSERT(blobImpl); - - if (WriteBlobOrFile(aWriter, blobImpl, *closure)) { - return true; - } - } - } - - // See if this is an ImageData object. - { - ImageData* imageData = nullptr; - if (NS_SUCCEEDED(UNWRAP_OBJECT(ImageData, aObj, imageData))) { - return WriteStructuredCloneImageData(aCx, aWriter, imageData); - } - } - - // See if this is a FormData object. - { - nsFormData* formData = nullptr; - if (NS_SUCCEEDED(UNWRAP_OBJECT(FormData, aObj, formData))) { - if (WriteFormData(aCx, aWriter, formData, *closure)) { - return true; - } - } - } - - // See if this is an ImageBitmap object. - { - ImageBitmap* imageBitmap = nullptr; - if (NS_SUCCEEDED(UNWRAP_OBJECT(ImageBitmap, aObj, imageBitmap))) { - return ImageBitmap::WriteStructuredClone(aWriter, - closure->mClonedImages, - imageBitmap); - } - } - - return NS_DOMWriteStructuredClone(aCx, aWriter, aObj, nullptr); - } - - static void - Error(JSContext* aCx, uint32_t /* aErrorId */) - { - Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR); - } - - static bool - ReadTransfer(JSContext* aCx, JSStructuredCloneReader* aReader, - uint32_t aTag, void* aContent, uint64_t aExtraData, - void* aClosure, JS::MutableHandle aReturnObject) - { - MOZ_ASSERT(aClosure); - - auto* closure = static_cast(aClosure); - - if (aTag == SCTAG_DOM_MAP_MESSAGEPORT) { - MOZ_ASSERT(!aContent); - MOZ_ASSERT(aExtraData < closure->mMessagePortIdentifiers.Length()); - - ErrorResult rv; - nsRefPtr port = - dom::MessagePort::Create(closure->mParentWindow, - closure->mMessagePortIdentifiers[aExtraData], - rv); - - if (NS_WARN_IF(rv.Failed())) { - return false; - } - - closure->mMessagePorts.AppendElement(port); - - JS::Rooted value(aCx); - if (!GetOrCreateDOMReflector(aCx, port, &value)) { - JS_ClearPendingException(aCx); - return false; - } - - aReturnObject.set(&value.toObject()); - return true; - } - - return false; - } - - static bool - Transfer(JSContext* aCx, JS::Handle aObj, void* aClosure, - uint32_t* aTag, JS::TransferableOwnership* aOwnership, - void** aContent, uint64_t *aExtraData) - { - MOZ_ASSERT(aClosure); - - auto* closure = static_cast(aClosure); - - MessagePortBase* port; - nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port); - if (NS_SUCCEEDED(rv)) { - if (NS_WARN_IF(closure->mTransferredPorts.Contains(port))) { - // No duplicates. - return false; - } - - MessagePortIdentifier identifier; - if (!port->CloneAndDisentangle(identifier)) { - return false; - } - - closure->mMessagePortIdentifiers.AppendElement(identifier); - closure->mTransferredPorts.AppendElement(port); - - *aTag = SCTAG_DOM_MAP_MESSAGEPORT; - *aOwnership = JS::SCTAG_TMO_CUSTOM; - *aContent = nullptr; - *aExtraData = closure->mMessagePortIdentifiers.Length() - 1; - - return true; - } - - return false; - } - - static void - FreeTransfer(uint32_t aTag, JS::TransferableOwnership aOwnership, - void *aContent, uint64_t aExtraData, void* aClosure) - { - if (aTag == SCTAG_DOM_MAP_MESSAGEPORT) { - MOZ_ASSERT(aClosure); - MOZ_ASSERT(!aContent); - auto* closure = static_cast(aClosure); - - MOZ_ASSERT(aExtraData < closure->mMessagePortIdentifiers.Length()); - dom::MessagePort::ForceClose(closure->mMessagePortIdentifiers[aExtraData]); - } - } -}; - -const JSStructuredCloneCallbacks gWorkerStructuredCloneCallbacks = { - WorkerStructuredCloneCallbacks::Read, - WorkerStructuredCloneCallbacks::Write, - WorkerStructuredCloneCallbacks::Error, - WorkerStructuredCloneCallbacks::ReadTransfer, - WorkerStructuredCloneCallbacks::Transfer, - WorkerStructuredCloneCallbacks::FreeTransfer -}; - class MainThreadReleaseRunnable final : public nsRunnable { nsTArray> mDoomed; @@ -983,21 +491,12 @@ private: virtual bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { - WorkerGlobalScope* globalScope = - aWorkerPrivate->GetOrCreateGlobalScope(aCx); - if (!globalScope) { - NS_WARNING("Failed to make global!"); + if (!scriptloader::LoadMainScript(aCx, mScriptURL, WorkerScript)) { return false; } - JS::Rooted global(aCx, globalScope->GetWrapper()); - - JSAutoCompartment ac(aCx, global); - bool result = scriptloader::LoadMainScript(aCx, mScriptURL, WorkerScript); - if (result) { - aWorkerPrivate->SetWorkerScriptExecutedSuccessfully(); - } - return result; + aWorkerPrivate->SetWorkerScriptExecutedSuccessfully(); + return true; } }; @@ -1093,9 +592,8 @@ private: }; class MessageEventRunnable final : public WorkerRunnable + , public StructuredCloneHelper { - JSAutoStructuredCloneBuffer mBuffer; - WorkerStructuredCloneClosure mClosure; uint64_t mMessagePortSerial; bool mToMessagePort; @@ -1107,24 +605,13 @@ public: TargetAndBusyBehavior aBehavior, bool aToMessagePort, uint64_t aMessagePortSerial) : WorkerRunnable(aWorkerPrivate, aBehavior) + , StructuredCloneHelper(CloningSupported, TransferringSupported, + SameProcessDifferentThread) , mMessagePortSerial(aMessagePortSerial) , mToMessagePort(aToMessagePort) { } - bool - Write(JSContext* aCx, JS::Handle aValue, - JS::Handle aTransferredValue, - const JSStructuredCloneCallbacks *aCallbacks) - { - bool ok = mBuffer.write(aCx, aValue, aTransferredValue, aCallbacks, - &mClosure); - // This hashtable has to be empty because it could contain MessagePort - // objects that cannot be freed on a different thread. - mClosure.mTransferredPorts.Clear(); - return ok; - } - void SetMessageSource(ServiceWorkerClientInfo* aSource) { @@ -1135,49 +622,44 @@ public: DispatchDOMEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate, DOMEventTargetHelper* aTarget, bool aIsMainThread) { - // Release reference to objects that were AddRef'd for - // cloning into worker when array goes out of scope. - WorkerStructuredCloneClosure closure; - closure.mClonedObjects.SwapElements(mClosure.mClonedObjects); - closure.mClonedImages.SwapElements(mClosure.mClonedImages); - MOZ_ASSERT(mClosure.mMessagePorts.IsEmpty()); - closure.mMessagePortIdentifiers.SwapElements(mClosure.mMessagePortIdentifiers); - + nsCOMPtr parent; if (aIsMainThread) { - closure.mParentWindow = do_QueryInterface(aTarget->GetParentObject()); + parent = do_QueryInterface(aTarget->GetParentObject()); } JS::Rooted messageData(aCx); - if (!mBuffer.read(aCx, &messageData, - workers::WorkerStructuredCloneCallbacks(), - &closure)) { - xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR); + ErrorResult rv; + Read(parent, aCx, &messageData, rv); + if (NS_WARN_IF(rv.Failed())) { + xpc::Throw(aCx, rv.StealNSResult()); return false; } nsRefPtr event = new MessageEvent(aTarget, nullptr, nullptr); - nsresult rv = - event->InitMessageEvent(NS_LITERAL_STRING("message"), - false /* non-bubbling */, - false /* non-cancelable */, - messageData, - EmptyString(), - EmptyString(), - nullptr); + rv = event->InitMessageEvent(NS_LITERAL_STRING("message"), + false /* non-bubbling */, + false /* cancelable */, + messageData, + EmptyString(), + EmptyString(), + nullptr); if (mEventSource) { nsRefPtr client = new ServiceWorkerWindowClient(aTarget, *mEventSource); event->SetSource(client); } - if (NS_FAILED(rv)) { - xpc::Throw(aCx, rv); + if (NS_WARN_IF(rv.Failed())) { + xpc::Throw(aCx, rv.StealNSResult()); return false; } + nsTArray> ports; + TakeTransferredPorts(ports); + event->SetTrusted(true); event->SetPorts(new MessagePortList(static_cast(event.get()), - closure.mMessagePorts)); + ports)); nsCOMPtr domEvent = do_QueryObject(event); nsEventStatus dummy = nsEventStatus_eIgnore; @@ -1202,8 +684,7 @@ private: return aWorkerPrivate->DispatchMessageEventToMessagePort(aCx, mMessagePortSerial, - Move(mBuffer), - mClosure); + *this); } if (aWorkerPrivate->IsFrozen()) { @@ -3311,9 +2792,8 @@ WorkerPrivateParent::PostMessageInternal( WorkerRunnable::WorkerThreadModifyBusyCount, aToMessagePort, aMessagePortSerial); - if (!runnable->Write(aCx, aMessage, transferable, - &gWorkerStructuredCloneCallbacks)) { - aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); + runnable->Write(aCx, aMessage, transferable, aRv); + if (NS_WARN_IF(aRv.Failed())) { return; } @@ -3356,45 +2836,10 @@ template bool WorkerPrivateParent::DispatchMessageEventToMessagePort( JSContext* aCx, uint64_t aMessagePortSerial, - JSAutoStructuredCloneBuffer&& aBuffer, - WorkerStructuredCloneClosure& aClosure) + StructuredCloneHelper& aHelper) { AssertIsOnMainThread(); - JSAutoStructuredCloneBuffer buffer(Move(aBuffer)); - - class MOZ_STACK_CLASS AutoCloneBufferCleaner final - { - public: - AutoCloneBufferCleaner(JSAutoStructuredCloneBuffer& aBuffer, - const JSStructuredCloneCallbacks* aCallbacks, - WorkerStructuredCloneClosure& aClosure) - : mBuffer(aBuffer) - , mCallbacks(aCallbacks) - , mClosure(aClosure) - {} - - ~AutoCloneBufferCleaner() - { - mBuffer.clear(mCallbacks, &mClosure); - } - - private: - JSAutoStructuredCloneBuffer& mBuffer; - const JSStructuredCloneCallbacks* mCallbacks; - WorkerStructuredCloneClosure& mClosure; - }; - - WorkerStructuredCloneClosure closure; - closure.mClonedObjects.SwapElements(aClosure.mClonedObjects); - closure.mClonedImages.SwapElements(aClosure.mClonedImages); - MOZ_ASSERT(aClosure.mMessagePorts.IsEmpty()); - closure.mMessagePortIdentifiers.SwapElements(aClosure.mMessagePortIdentifiers); - - AutoCloneBufferCleaner bufferCleaner(buffer, - &gWorkerStructuredCloneCallbacks, - closure); - SharedWorker* sharedWorker; if (!mSharedWorkers.Get(aMessagePortSerial, &sharedWorker)) { // SharedWorker has already been unregistered? @@ -3408,7 +2853,7 @@ WorkerPrivateParent::DispatchMessageEventToMessagePort( return true; } - closure.mParentWindow = do_QueryInterface(port->GetParentObject()); + nsCOMPtr parent = do_QueryInterface(port->GetParentObject()); AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(port->GetParentObject()))) { @@ -3416,24 +2861,27 @@ WorkerPrivateParent::DispatchMessageEventToMessagePort( } JSContext* cx = jsapi.cx(); + ErrorResult rv; JS::Rooted data(cx); - if (!buffer.read(cx, &data, &gWorkerStructuredCloneCallbacks, - &closure)) { + aHelper.Read(parent, cx, &data, rv); + if (NS_WARN_IF(rv.Failed())) { + xpc::Throw(cx, rv.StealNSResult()); return false; } nsRefPtr event = new MessageEvent(port, nullptr, nullptr); - nsresult rv = - event->InitMessageEvent(NS_LITERAL_STRING("message"), false, false, data, - EmptyString(), EmptyString(), nullptr); - if (NS_FAILED(rv)) { - xpc::Throw(cx, rv); + rv = event->InitMessageEvent(NS_LITERAL_STRING("message"), false, false, data, + EmptyString(), EmptyString(), nullptr); + if (NS_WARN_IF(rv.Failed())) { + xpc::Throw(cx, rv.StealNSResult()); return false; } - event->SetTrusted(true); + nsTArray> ports; + aHelper.TakeTransferredPorts(ports); - event->SetPorts(new MessagePortList(port, closure.mMessagePorts)); + event->SetTrusted(true); + event->SetPorts(new MessagePortList(port, ports)); nsCOMPtr domEvent; CallQueryInterface(event.get(), getter_AddRefs(domEvent)); @@ -3441,8 +2889,8 @@ WorkerPrivateParent::DispatchMessageEventToMessagePort( bool ignored; rv = port->DispatchEvent(domEvent, &ignored); - if (NS_FAILED(rv)) { - xpc::Throw(cx, rv); + if (NS_WARN_IF(rv.Failed())) { + xpc::Throw(cx, rv.StealNSResult()); return false; } @@ -5936,7 +5384,9 @@ WorkerPrivate::RunCurrentSyncLoop() MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(mThread, false)); // Now *might* be a good time to GC. Let the JS engine make the decision. - JS_MaybeGC(cx); + if (JS::CurrentGlobalOrNull(cx)) { + JS_MaybeGC(cx); + } } } @@ -6082,9 +5532,8 @@ WorkerPrivate::PostMessageToParentInternal( WorkerRunnable::ParentThreadUnchangedBusyCount, aToMessagePort, aMessagePortSerial); - if (!runnable->Write(aCx, aMessage, transferable, - &gWorkerStructuredCloneCallbacks)) { - aRv = NS_ERROR_DOM_DATA_CLONE_ERR; + runnable->Write(aCx, aMessage, transferable, aRv); + if (NS_WARN_IF(aRv.Failed())) { return; } @@ -6166,7 +5615,9 @@ WorkerPrivate::EnterDebuggerEventLoop() runnable->Release(); // Now *might* be a good time to GC. Let the JS engine make the decision. - JS_MaybeGC(cx); + if (JS::CurrentGlobalOrNull(cx)) { + JS_MaybeGC(cx); + } } } } @@ -6414,7 +5865,8 @@ WorkerPrivate::ReportError(JSContext* aCx, const char* aMessage, // if there was an error in the close handler or if we ran out of memory. bool fireAtScope = mErrorHandlerRecursionCount == 1 && !mCloseHandlerStarted && - errorNumber != JSMSG_OUT_OF_MEMORY; + errorNumber != JSMSG_OUT_OF_MEMORY && + JS::CurrentGlobalOrNull(aCx); if (!ReportErrorRunnable::ReportError(aCx, this, fireAtScope, nullptr, message, filename, line, lineNumber, @@ -6803,7 +6255,7 @@ WorkerPrivate::GarbageCollectInternal(JSContext* aCx, bool aShrinking, { AssertIsOnWorkerThread(); - if (!JS::CurrentGlobalOrNull(aCx)) { + if (!GlobalScope()) { // We haven't compiled anything yet. Just bail out. return; } @@ -7052,13 +6504,16 @@ WorkerPrivate::GetOrCreateGlobalScope(JSContext* aCx) JSAutoCompartment ac(aCx, global); + // RegisterBindings() can spin a nested event loop so we have to set mScope + // before calling it, and we have to make sure to unset mScope if it fails. + mScope = Move(globalScope); + if (!RegisterBindings(aCx, global)) { + mScope = nullptr; return nullptr; } JS_FireOnNewGlobalObject(aCx, global); - - mScope = globalScope.forget(); } return mScope; @@ -7225,30 +6680,7 @@ GetWorkerCrossThreadDispatcher(JSContext* aCx, JS::Value aWorker) return w->GetCrossThreadDispatcher(); } -const JSStructuredCloneCallbacks* -WorkerStructuredCloneCallbacks() -{ - return &gWorkerStructuredCloneCallbacks; -} - // Force instantiation. template class WorkerPrivateParent; -WorkerStructuredCloneClosure::WorkerStructuredCloneClosure() -{} - -WorkerStructuredCloneClosure::~WorkerStructuredCloneClosure() -{} - -void -WorkerStructuredCloneClosure::Clear() -{ - mParentWindow = nullptr; - mClonedObjects.Clear(); - mClonedImages.Clear(); - mMessagePorts.Clear(); - mMessagePortIdentifiers.Clear(); - mTransferredPorts.Clear(); -} - END_WORKERS_NAMESPACE diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index 0f95e58a12..8b03e1b5cd 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -28,12 +28,10 @@ #include "nsTArray.h" #include "nsThreadUtils.h" #include "nsTObserverArray.h" -#include "mozilla/dom/StructuredCloneTags.h" #include "Queue.h" #include "WorkerFeature.h" -class JSAutoStructuredCloneBuffer; class nsIChannel; class nsIDocument; class nsIEventTarget; @@ -52,6 +50,7 @@ struct RuntimeStats; namespace mozilla { namespace dom { class Function; +class StructuredCloneHelper; } // namespace dom namespace ipc { class PrincipalInfo; @@ -74,7 +73,6 @@ class WorkerDebuggerGlobalScope; class WorkerGlobalScope; class WorkerPrivate; class WorkerRunnable; -class WorkerStructuredCloneClosure; class WorkerThread; // SharedMutex is a small wrapper around an (internal) reference-counted Mutex @@ -350,8 +348,7 @@ public: DispatchMessageEventToMessagePort( JSContext* aCx, uint64_t aMessagePortSerial, - JSAutoStructuredCloneBuffer&& aBuffer, - WorkerStructuredCloneClosure& aClosure); + StructuredCloneHelper& aHelper); void UpdateRuntimeOptions(JSContext* aCx, @@ -1511,17 +1508,6 @@ IsCurrentThreadRunningChromeWorker(); JSContext* GetCurrentThreadJSContext(); -enum WorkerStructuredDataType -{ - DOMWORKER_SCTAG_BLOB = SCTAG_DOM_MAX, - DOMWORKER_SCTAG_FORMDATA = SCTAG_DOM_MAX + 1, - - DOMWORKER_SCTAG_END -}; - -const JSStructuredCloneCallbacks* -WorkerStructuredCloneCallbacks(); - class AutoSyncLoopHolder { WorkerPrivate* mWorkerPrivate; diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index 1aa0e5e573..460829ab11 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -418,6 +418,20 @@ DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx, JS::CompartmentOptions options; mWorkerPrivate->CopyJSCompartmentOptions(options); + const bool usesSystemPrincipal = mWorkerPrivate->UsesSystemPrincipal(); + + // Note that xpc::ShouldDiscardSystemSource() and + // xpc::ExtraWarningsForSystemJS() read prefs that are cached on the main + // thread. This is benignly racey. + const bool discardSource = (usesSystemPrincipal || + mWorkerPrivate->IsInPrivilegedApp()) && + xpc::ShouldDiscardSystemSource(); + const bool extraWarnings = usesSystemPrincipal && + xpc::ExtraWarningsForSystemJS(); + + options.setDiscardSource(discardSource) + .extraWarningsOverride().set(extraWarnings); + return DedicatedWorkerGlobalScopeBinding_workers::Wrap(aCx, this, this, options, GetWorkerPrincipal(), diff --git a/dom/workers/WorkerStructuredClone.h b/dom/workers/WorkerStructuredClone.h deleted file mode 100644 index 3e824aeb92..0000000000 --- a/dom/workers/WorkerStructuredClone.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* 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/. */ - -#ifndef mozilla_dom_workers_WorkerStructuredClone_h -#define mozilla_dom_workers_WorkerStructuredClone_h - -#include "Workers.h" -#include "mozilla/dom/PMessagePort.h" - -class nsPIDOMWindow; - -namespace mozilla { -namespace layers { -class Image; -} - -namespace dom { - -class MessagePortBase; - -namespace workers { - -// This class is implemented in WorkerPrivate.cpp -class WorkerStructuredCloneClosure final -{ -private: - WorkerStructuredCloneClosure(const WorkerStructuredCloneClosure&) = delete; - WorkerStructuredCloneClosure & operator=(const WorkerStructuredCloneClosure&) = delete; - -public: - WorkerStructuredCloneClosure(); - ~WorkerStructuredCloneClosure(); - - void Clear(); - - // This can be null if the MessagePort is created in a worker. - nsCOMPtr mParentWindow; - - nsTArray> mClonedObjects; - - // This is used for sharing the backend of ImageBitmaps. - // The layers::Image object must be thread-safely reference-counted. - // The layers::Image object will not be written ever via any ImageBitmap - // instance, so no race condition will occur. - nsTArray> mClonedImages; - - // The transferred ports. - nsTArray> mMessagePorts; - - // Information for the transferring. - nsTArray mMessagePortIdentifiers; - - // To avoid duplicates in the transferred ports. - nsTArray> mTransferredPorts; -}; - -} // workers namespace -} // dom namespace -} // mozilla namespace - -#endif // mozilla_dom_workers_WorkerStructuredClone_h diff --git a/dom/workers/XMLHttpRequest.cpp b/dom/workers/XMLHttpRequest.cpp index 8ce46effff..3e1b8875ee 100644 --- a/dom/workers/XMLHttpRequest.cpp +++ b/dom/workers/XMLHttpRequest.cpp @@ -18,6 +18,7 @@ #include "mozilla/dom/Exceptions.h" #include "mozilla/dom/File.h" #include "mozilla/dom/ProgressEvent.h" +#include "mozilla/dom/StructuredCloneHelper.h" #include "nsComponentManagerUtils.h" #include "nsContentUtils.h" #include "nsFormData.h" @@ -27,7 +28,6 @@ #include "RuntimeService.h" #include "WorkerPrivate.h" #include "WorkerRunnable.h" -#include "WorkerStructuredClone.h" #include "XMLHttpRequestUpload.h" using namespace mozilla; @@ -175,6 +175,117 @@ private: } }; +class WorkerThreadProxySyncRunnable : public nsRunnable +{ +protected: + WorkerPrivate* mWorkerPrivate; + nsRefPtr mProxy; + nsCOMPtr mSyncLoopTarget; + +private: + class ResponseRunnable final: public MainThreadStopSyncLoopRunnable + { + nsRefPtr mProxy; + nsresult mErrorCode; + + public: + ResponseRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy, + nsresult aErrorCode) + : MainThreadStopSyncLoopRunnable(aWorkerPrivate, aProxy->GetEventTarget(), + NS_SUCCEEDED(aErrorCode)), + mProxy(aProxy), mErrorCode(aErrorCode) + { + MOZ_ASSERT(aProxy); + } + + private: + ~ResponseRunnable() + { } + + virtual void + MaybeSetException(JSContext* aCx) override + { + MOZ_ASSERT(NS_FAILED(mErrorCode)); + + Throw(aCx, mErrorCode); + } + }; + +public: + WorkerThreadProxySyncRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy) + : mWorkerPrivate(aWorkerPrivate), mProxy(aProxy) + { + MOZ_ASSERT(aWorkerPrivate); + MOZ_ASSERT(aProxy); + aWorkerPrivate->AssertIsOnWorkerThread(); + } + + NS_DECL_ISUPPORTS_INHERITED + + bool + Dispatch(JSContext* aCx) + { + mWorkerPrivate->AssertIsOnWorkerThread(); + + AutoSyncLoopHolder syncLoop(mWorkerPrivate); + mSyncLoopTarget = syncLoop.EventTarget(); + + if (NS_FAILED(NS_DispatchToMainThread(this))) { + JS_ReportError(aCx, "Failed to dispatch to main thread!"); + return false; + } + + return syncLoop.Run(); + } + +protected: + virtual ~WorkerThreadProxySyncRunnable() + { } + + virtual nsresult + MainThreadRun() = 0; + +private: + NS_DECL_NSIRUNNABLE +}; + +class SendRunnable final + : public WorkerThreadProxySyncRunnable + , public StructuredCloneHelper +{ + nsString mStringBody; + nsCOMPtr mSyncLoopTarget; + bool mHasUploadListeners; + +public: + SendRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy, + const nsAString& aStringBody) + : WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy) + , StructuredCloneHelper(CloningSupported, TransferringNotSupported, + SameProcessDifferentThread) + , mStringBody(aStringBody) + , mHasUploadListeners(false) + { + } + + void SetHaveUploadListeners(bool aHasUploadListeners) + { + mHasUploadListeners = aHasUploadListeners; + } + + void SetSyncLoopTarget(nsIEventTarget* aSyncLoopTarget) + { + mSyncLoopTarget = aSyncLoopTarget; + } + +private: + ~SendRunnable() + { } + + virtual nsresult + MainThreadRun() override; +}; + END_WORKERS_NAMESPACE namespace { @@ -410,11 +521,10 @@ private: }; class EventRunnable final : public MainThreadProxyRunnable + , public StructuredCloneHelper { nsString mType; nsString mResponseType; - JSAutoStructuredCloneBuffer mResponseBuffer; - WorkerStructuredCloneClosure mResponseClosure; JS::Heap mResponse; nsString mResponseText; nsString mResponseURL; @@ -456,17 +566,21 @@ public: EventRunnable(Proxy* aProxy, bool aUploadEvent, const nsString& aType, bool aLengthComputable, uint64_t aLoaded, uint64_t aTotal) - : MainThreadProxyRunnable(aProxy->mWorkerPrivate, aProxy), mType(aType), - mResponse(JS::UndefinedValue()), mLoaded(aLoaded), mTotal(aTotal), - mEventStreamId(aProxy->mInnerEventStreamId), mStatus(0), mReadyState(0), - mUploadEvent(aUploadEvent), mProgressEvent(true), + : MainThreadProxyRunnable(aProxy->mWorkerPrivate, aProxy), + StructuredCloneHelper(CloningSupported, TransferringNotSupported, + SameProcessDifferentThread), + mType(aType), mResponse(JS::UndefinedValue()), mLoaded(aLoaded), + mTotal(aTotal), mEventStreamId(aProxy->mInnerEventStreamId), mStatus(0), + mReadyState(0), mUploadEvent(aUploadEvent), mProgressEvent(true), mLengthComputable(aLengthComputable), mUseCachedArrayBufferResponse(false), mResponseTextResult(NS_OK), mStatusResult(NS_OK), mResponseResult(NS_OK) { } EventRunnable(Proxy* aProxy, bool aUploadEvent, const nsString& aType) - : MainThreadProxyRunnable(aProxy->mWorkerPrivate, aProxy), mType(aType), - mResponse(JS::UndefinedValue()), mLoaded(0), mTotal(0), + : MainThreadProxyRunnable(aProxy->mWorkerPrivate, aProxy), + StructuredCloneHelper(CloningSupported, TransferringNotSupported, + SameProcessDifferentThread), + mType(aType), mResponse(JS::UndefinedValue()), mLoaded(0), mTotal(0), mEventStreamId(aProxy->mInnerEventStreamId), mStatus(0), mReadyState(0), mUploadEvent(aUploadEvent), mProgressEvent(false), mLengthComputable(0), mUseCachedArrayBufferResponse(false), mResponseTextResult(NS_OK), @@ -484,80 +598,6 @@ private: WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override; }; -class WorkerThreadProxySyncRunnable : public nsRunnable -{ -protected: - WorkerPrivate* mWorkerPrivate; - nsRefPtr mProxy; - nsCOMPtr mSyncLoopTarget; - -private: - class ResponseRunnable final: public MainThreadStopSyncLoopRunnable - { - nsRefPtr mProxy; - nsresult mErrorCode; - - public: - ResponseRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy, - nsresult aErrorCode) - : MainThreadStopSyncLoopRunnable(aWorkerPrivate, aProxy->GetEventTarget(), - NS_SUCCEEDED(aErrorCode)), - mProxy(aProxy), mErrorCode(aErrorCode) - { - MOZ_ASSERT(aProxy); - } - - private: - ~ResponseRunnable() - { } - - virtual void - MaybeSetException(JSContext* aCx) override - { - MOZ_ASSERT(NS_FAILED(mErrorCode)); - - Throw(aCx, mErrorCode); - } - }; - -public: - WorkerThreadProxySyncRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy) - : mWorkerPrivate(aWorkerPrivate), mProxy(aProxy) - { - MOZ_ASSERT(aWorkerPrivate); - MOZ_ASSERT(aProxy); - aWorkerPrivate->AssertIsOnWorkerThread(); - } - - NS_DECL_ISUPPORTS_INHERITED - - bool - Dispatch(JSContext* aCx) - { - mWorkerPrivate->AssertIsOnWorkerThread(); - - AutoSyncLoopHolder syncLoop(mWorkerPrivate); - mSyncLoopTarget = syncLoop.EventTarget(); - - if (NS_FAILED(NS_DispatchToMainThread(this))) { - JS_ReportError(aCx, "Failed to dispatch to main thread!"); - return false; - } - - return syncLoop.Run(); - } - -protected: - virtual ~WorkerThreadProxySyncRunnable() - { } - - virtual nsresult - MainThreadRun() = 0; - -private: - NS_DECL_NSIRUNNABLE -}; - class SyncTeardownRunnable final : public WorkerThreadProxySyncRunnable { public: @@ -791,39 +831,6 @@ private: MainThreadRunInternal(); }; -class SendRunnable final : public WorkerThreadProxySyncRunnable -{ - nsString mStringBody; - JSAutoStructuredCloneBuffer mBody; - WorkerStructuredCloneClosure mClosure; - nsCOMPtr mSyncLoopTarget; - bool mHasUploadListeners; - -public: - SendRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy, - const nsAString& aStringBody, JSAutoStructuredCloneBuffer&& aBody, - WorkerStructuredCloneClosure& aClosure, - nsIEventTarget* aSyncLoopTarget, bool aHasUploadListeners) - : WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy) - , mStringBody(aStringBody) - , mBody(Move(aBody)) - , mSyncLoopTarget(aSyncLoopTarget) - , mHasUploadListeners(aHasUploadListeners) - { - mClosure.mClonedObjects.SwapElements(aClosure.mClonedObjects); - mClosure.mClonedImages.SwapElements(aClosure.mClonedImages); - MOZ_ASSERT(aClosure.mMessagePorts.IsEmpty()); - MOZ_ASSERT(aClosure.mMessagePortIdentifiers.IsEmpty()); - } - -private: - ~SendRunnable() - { } - - virtual nsresult - MainThreadRun() override; -}; - class SetRequestHeaderRunnable final : public WorkerThreadProxySyncRunnable { nsCString mHeader; @@ -1227,21 +1234,11 @@ EventRunnable::PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate) } if (doClone) { - // Anything subject to GC must be cloned. - const JSStructuredCloneCallbacks* callbacks = - workers::WorkerStructuredCloneCallbacks(); - - WorkerStructuredCloneClosure closure; - - if (mResponseBuffer.write(aCx, response, transferable, callbacks, - &closure)) { - mResponseClosure.mClonedObjects.SwapElements(closure.mClonedObjects); - mResponseClosure.mClonedImages.SwapElements(closure.mClonedImages); - MOZ_ASSERT(mResponseClosure.mMessagePorts.IsEmpty()); - MOZ_ASSERT(mResponseClosure.mMessagePortIdentifiers.IsEmpty()); - } else { + ErrorResult rv; + Write(aCx, response, transferable, rv); + if (NS_WARN_IF(rv.Failed())) { NS_WARNING("Failed to clone response!"); - mResponseResult = NS_ERROR_DOM_DATA_CLONE_ERR; + mResponseResult = rv.StealNSResult(); mProxy->mArrayBufferResponseWasTransferred = false; } } @@ -1336,22 +1333,14 @@ EventRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) state->mResponseResult = mResponseResult; if (NS_SUCCEEDED(mResponseResult)) { - if (mResponseBuffer.data()) { + if (HasBeenWritten()) { MOZ_ASSERT(mResponse.isUndefined()); - JSAutoStructuredCloneBuffer responseBuffer(Move(mResponseBuffer)); - - const JSStructuredCloneCallbacks* callbacks = - workers::WorkerStructuredCloneCallbacks(); - - WorkerStructuredCloneClosure closure; - closure.mClonedObjects.SwapElements(mResponseClosure.mClonedObjects); - closure.mClonedImages.SwapElements(mResponseClosure.mClonedImages); - MOZ_ASSERT(mResponseClosure.mMessagePorts.IsEmpty()); - MOZ_ASSERT(mResponseClosure.mMessagePortIdentifiers.IsEmpty()); - + ErrorResult rv; JS::Rooted response(aCx); - if (!responseBuffer.read(aCx, &response, callbacks, &closure)) { + Read(nullptr, aCx, &response, rv); + if (NS_WARN_IF(rv.Failed())) { + rv.SuppressException(); return false; } @@ -1517,32 +1506,25 @@ SendRunnable::MainThreadRun() { nsCOMPtr variant; - if (mBody.data()) { + if (HasBeenWritten()) { AutoSafeJSContext cx; JSAutoRequest ar(cx); nsIXPConnect* xpc = nsContentUtils::XPConnect(); MOZ_ASSERT(xpc); - nsresult rv = NS_OK; - - const JSStructuredCloneCallbacks* callbacks = - workers::WorkerStructuredCloneCallbacks(); + ErrorResult rv; JS::Rooted body(cx); - if (mBody.read(cx, &body, callbacks, &mClosure)) { - if (NS_FAILED(xpc->JSValToVariant(cx, body, getter_AddRefs(variant)))) { - rv = NS_ERROR_DOM_INVALID_STATE_ERR; - } - } - else { - rv = NS_ERROR_DOM_DATA_CLONE_ERR; + Read(nullptr, cx, &body, rv); + if (NS_WARN_IF(rv.Failed())) { + return rv.StealNSResult(); } - mBody.clear(); - mClosure.Clear(); - - NS_ENSURE_SUCCESS(rv, rv); + rv = xpc->JSValToVariant(cx, body, getter_AddRefs(variant)); + if (NS_WARN_IF(rv.Failed())) { + return rv.StealNSResult(); + } } else { nsCOMPtr wvariant = @@ -1845,11 +1827,10 @@ XMLHttpRequest::Unpin() } void -XMLHttpRequest::SendInternal(const nsAString& aStringBody, - JSAutoStructuredCloneBuffer&& aBody, - WorkerStructuredCloneClosure& aClosure, +XMLHttpRequest::SendInternal(SendRunnable* aRunnable, ErrorResult& aRv) { + MOZ_ASSERT(aRunnable); mWorkerPrivate->AssertIsOnWorkerThread(); // No send() calls when open is running. @@ -1879,10 +1860,10 @@ XMLHttpRequest::SendInternal(const nsAString& aStringBody, JSContext* cx = mWorkerPrivate->GetJSContext(); - nsRefPtr runnable = - new SendRunnable(mWorkerPrivate, mProxy, aStringBody, Move(aBody), - aClosure, syncLoopTarget, hasUploadListeners); - if (!runnable->Dispatch(cx)) { + aRunnable->SetSyncLoopTarget(syncLoopTarget); + aRunnable->SetHaveUploadListeners(hasUploadListeners); + + if (!aRunnable->Dispatch(cx)) { // Dispatch() may have spun the event loop and we may have already unrooted. // If so we don't want autoUnpin to try again. if (!mRooted) { @@ -2109,11 +2090,11 @@ XMLHttpRequest::Send(ErrorResult& aRv) return; } - // Nothing to clone. - JSAutoStructuredCloneBuffer buffer; - WorkerStructuredCloneClosure closure; + nsRefPtr sendRunnable = + new SendRunnable(mWorkerPrivate, mProxy, NullString()); - SendInternal(NullString(), Move(buffer), closure, aRv); + // Nothing to clone. + SendInternal(sendRunnable, aRv); } void @@ -2131,11 +2112,11 @@ XMLHttpRequest::Send(const nsAString& aBody, ErrorResult& aRv) return; } - // Nothing to clone. - JSAutoStructuredCloneBuffer buffer; - WorkerStructuredCloneClosure closure; + nsRefPtr sendRunnable = + new SendRunnable(mWorkerPrivate, mProxy, aBody); - SendInternal(aBody, Move(buffer), closure, aRv); + // Nothing to clone. + SendInternal(sendRunnable, aRv); } void @@ -2171,18 +2152,15 @@ XMLHttpRequest::Send(JS::Handle aBody, ErrorResult& aRv) valToClone.setString(bodyStr); } - const JSStructuredCloneCallbacks* callbacks = - WorkerStructuredCloneCallbacks(); + nsRefPtr sendRunnable = + new SendRunnable(mWorkerPrivate, mProxy, EmptyString()); - WorkerStructuredCloneClosure closure; - - JSAutoStructuredCloneBuffer buffer; - if (!buffer.write(cx, valToClone, callbacks, &closure)) { - aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); + sendRunnable->Write(cx, valToClone, aRv); + if (NS_WARN_IF(aRv.Failed())) { return; } - SendInternal(EmptyString(), Move(buffer), closure, aRv); + SendInternal(sendRunnable, aRv); } void @@ -2215,18 +2193,15 @@ XMLHttpRequest::Send(Blob& aBody, ErrorResult& aRv) return; } - const JSStructuredCloneCallbacks* callbacks = - WorkerStructuredCloneCallbacks(); + nsRefPtr sendRunnable = + new SendRunnable(mWorkerPrivate, mProxy, EmptyString()); - WorkerStructuredCloneClosure closure; - - JSAutoStructuredCloneBuffer buffer; - if (!buffer.write(cx, value, callbacks, &closure)) { - aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); + sendRunnable->Write(cx, value, aRv); + if (NS_WARN_IF(aRv.Failed())) { return; } - SendInternal(EmptyString(), Move(buffer), closure, aRv); + SendInternal(sendRunnable, aRv); } void @@ -2251,17 +2226,15 @@ XMLHttpRequest::Send(nsFormData& aBody, ErrorResult& aRv) return; } - const JSStructuredCloneCallbacks* callbacks = - WorkerStructuredCloneCallbacks(); + nsRefPtr sendRunnable = + new SendRunnable(mWorkerPrivate, mProxy, EmptyString()); - JSAutoStructuredCloneBuffer buffer; - WorkerStructuredCloneClosure closure; - if (!buffer.write(cx, value, callbacks, &closure)) { - aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); + sendRunnable->Write(cx, value, aRv); + if (NS_WARN_IF(aRv.Failed())) { return; } - SendInternal(EmptyString(), Move(buffer), closure, aRv); + SendInternal(sendRunnable, aRv); } void diff --git a/dom/workers/XMLHttpRequest.h b/dom/workers/XMLHttpRequest.h index 330cb5f89b..cb9aec2b58 100644 --- a/dom/workers/XMLHttpRequest.h +++ b/dom/workers/XMLHttpRequest.h @@ -14,7 +14,6 @@ #include "mozilla/dom/TypedArray.h" -#include "js/StructuredClone.h" #include "nsXMLHttpRequest.h" namespace mozilla { @@ -26,9 +25,9 @@ class Blob; BEGIN_WORKERS_NAMESPACE class Proxy; +class SendRunnable; class XMLHttpRequestUpload; class WorkerPrivate; -class WorkerStructuredCloneClosure; class XMLHttpRequest final: public nsXHREventTarget, public WorkerFeature @@ -291,9 +290,7 @@ private: ErrorResult& aRv); void - SendInternal(const nsAString& aStringBody, - JSAutoStructuredCloneBuffer&& aBody, - WorkerStructuredCloneClosure& aClosure, + SendInternal(SendRunnable* aRunnable, ErrorResult& aRv); }; diff --git a/gfx/thebes/gfxTextRun.cpp b/gfx/thebes/gfxTextRun.cpp index 78167643c9..8782e8bdde 100644 --- a/gfx/thebes/gfxTextRun.cpp +++ b/gfx/thebes/gfxTextRun.cpp @@ -3220,7 +3220,7 @@ gfxMissingFontRecorder::Flush() } mNotifiedFonts[i] |= (1 << j); if (!fontNeeded.IsEmpty()) { - fontNeeded.Append(PRUnichar(',')); + fontNeeded.Append(char16_t(',')); } uint32_t tag = GetScriptTagForCode(i * 32 + j); fontNeeded.Append(char16_t(tag >> 24)); diff --git a/ipc/bluetooth/BluetoothDaemonConnection.cpp b/ipc/bluetooth/BluetoothDaemonConnection.cpp deleted file mode 100644 index a1f0dc7970..0000000000 --- a/ipc/bluetooth/BluetoothDaemonConnection.cpp +++ /dev/null @@ -1,533 +0,0 @@ -/* -*- 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 "BluetoothDaemonConnection.h" -#include -#include -#include -#include -#include -#include "mozilla/ipc/BluetoothDaemonConnectionConsumer.h" -#include "mozilla/ipc/DataSocket.h" -#include "mozilla/ipc/UnixSocketConnector.h" -#include "mozilla/ipc/UnixSocketWatcher.h" -#include "nsTArray.h" -#include "nsXULAppAPI.h" - -#ifdef CHROMIUM_LOG -#undef CHROMIUM_LOG -#endif - -#if defined(MOZ_WIDGET_GONK) -#include -#define CHROMIUM_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "I/O", args); -#else -#include -#define IODEBUG true -#define CHROMIUM_LOG(args...) if (IODEBUG) printf(args); -#endif - -namespace mozilla { -namespace ipc { - -// The connection to the Bluetooth daemon is established -// using an abstract socket name. The \0 prefix will be added -// by the |Connect| method. -static const char sBluetoothdSocketName[] = "bluez_hal_socket"; - -// -// BluetoothDaemonPDU -// - -BluetoothDaemonPDU::BluetoothDaemonPDU(uint8_t aService, uint8_t aOpcode, - uint16_t aPayloadSize) - : UnixSocketIOBuffer(HEADER_SIZE + aPayloadSize) - , mConsumer(nullptr) - , mUserData(nullptr) -{ - uint8_t* data = Append(HEADER_SIZE); - MOZ_ASSERT(data); - - // Setup PDU header - data[OFF_SERVICE] = aService; - data[OFF_OPCODE] = aOpcode; - memcpy(data + OFF_LENGTH, &aPayloadSize, sizeof(aPayloadSize)); -} - -BluetoothDaemonPDU::BluetoothDaemonPDU(size_t aPayloadSize) - : UnixSocketIOBuffer(HEADER_SIZE + aPayloadSize) - , mConsumer(nullptr) - , mUserData(nullptr) -{ } - -void -BluetoothDaemonPDU::GetHeader(uint8_t& aService, uint8_t& aOpcode, - uint16_t& aPayloadSize) -{ - memcpy(&aService, GetData(OFF_SERVICE), sizeof(aService)); - memcpy(&aOpcode, GetData(OFF_OPCODE), sizeof(aOpcode)); - memcpy(&aPayloadSize, GetData(OFF_LENGTH), sizeof(aPayloadSize)); -} - -ssize_t -BluetoothDaemonPDU::Send(int aFd) -{ - struct iovec iv; - memset(&iv, 0, sizeof(iv)); - iv.iov_base = GetData(GetLeadingSpace()); - iv.iov_len = GetSize(); - - struct msghdr msg; - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = &iv; - msg.msg_iovlen = 1; - msg.msg_control = nullptr; - msg.msg_controllen = 0; - - ssize_t res = TEMP_FAILURE_RETRY(sendmsg(aFd, &msg, 0)); - if (res < 0) { - MOZ_ASSERT(errno != EBADF); /* internal error */ - OnError("sendmsg", errno); - return -1; - } - - Consume(res); - - if (mConsumer) { - // We successfully sent a PDU, now store the - // result runnable in the consumer. - mConsumer->StoreUserData(*this); - } - - return res; -} - -#define CMSGHDR_CONTAINS_FD(_cmsghdr) \ - ( ((_cmsghdr)->cmsg_level == SOL_SOCKET) && \ - ((_cmsghdr)->cmsg_type == SCM_RIGHTS) ) - -ssize_t -BluetoothDaemonPDU::Receive(int aFd) -{ - struct iovec iv; - memset(&iv, 0, sizeof(iv)); - iv.iov_base = GetData(0); - iv.iov_len = GetAvailableSpace(); - - uint8_t cmsgbuf[CMSG_SPACE(sizeof(int))]; - - struct msghdr msg; - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = &iv; - msg.msg_iovlen = 1; - msg.msg_control = cmsgbuf; - msg.msg_controllen = sizeof(cmsgbuf); - - ssize_t res = TEMP_FAILURE_RETRY(recvmsg(aFd, &msg, MSG_NOSIGNAL)); - if (res < 0) { - MOZ_ASSERT(errno != EBADF); /* internal error */ - OnError("recvmsg", errno); - return -1; - } - if (msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) { - return -1; - } - - SetRange(0, res); - - struct cmsghdr *chdr = CMSG_FIRSTHDR(&msg); - - for (; chdr; chdr = CMSG_NXTHDR(&msg, chdr)) { - if (NS_WARN_IF(!CMSGHDR_CONTAINS_FD(chdr))) { - continue; - } - // Retrieve sent file descriptor. If multiple file descriptors - // have been sent, we close all but the final one. - mReceivedFd = *(static_cast(CMSG_DATA(chdr))); - } - - return res; -} - -int -BluetoothDaemonPDU::AcquireFd() -{ - return mReceivedFd.forget(); -} - -nsresult -BluetoothDaemonPDU::UpdateHeader() -{ - size_t len = GetPayloadSize(); - if (len >= MAX_PAYLOAD_LENGTH) { - return NS_ERROR_ILLEGAL_VALUE; - } - uint16_t len16 = static_cast(len); - - memcpy(GetData(OFF_LENGTH), &len16, sizeof(len16)); - - return NS_OK; -} - -size_t -BluetoothDaemonPDU::GetPayloadSize() const -{ - MOZ_ASSERT(GetSize() >= HEADER_SIZE); - - return GetSize() - HEADER_SIZE; -} - -void -BluetoothDaemonPDU::OnError(const char* aFunction, int aErrno) -{ - CHROMIUM_LOG("%s failed with error %d (%s)", - aFunction, aErrno, strerror(aErrno)); -} - -// -// BluetoothDaemonPDUConsumer -// - -BluetoothDaemonPDUConsumer::BluetoothDaemonPDUConsumer() -{ } - -BluetoothDaemonPDUConsumer::~BluetoothDaemonPDUConsumer() -{ } - -// -// BluetoothDaemonConnectionIO -// - -class BluetoothDaemonConnectionIO final - : public UnixSocketWatcher - , public ConnectionOrientedSocketIO -{ -public: - BluetoothDaemonConnectionIO(MessageLoop* aIOLoop, int aFd, - ConnectionStatus aConnectionStatus, - BluetoothDaemonConnection* aConnection, - BluetoothDaemonPDUConsumer* aConsumer); - - // Task callback methods - // - - void Send(UnixSocketIOBuffer* aBuffer); - - void OnSocketCanReceiveWithoutBlocking() override; - void OnSocketCanSendWithoutBlocking() override; - - void OnConnected() override; - void OnError(const char* aFunction, int aErrno) override; - - // Methods for |ConnectionOrientedSocketIO| - // - - nsresult Accept(int aFd, - const struct sockaddr* aAddress, - socklen_t aAddressLength) override; - - // Methods for |DataSocketIO| - // - - nsresult QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) override; - void ConsumeBuffer() override; - void DiscardBuffer() override; - - // Methods for |SocketIOBase| - // - - SocketBase* GetSocketBase() override; - - bool IsShutdownOnMainThread() const override; - bool IsShutdownOnIOThread() const override; - - void ShutdownOnMainThread() override; - void ShutdownOnIOThread() override; - -private: - BluetoothDaemonConnection* mConnection; - BluetoothDaemonPDUConsumer* mConsumer; - nsAutoPtr mPDU; - bool mShuttingDownOnIOThread; -}; - -BluetoothDaemonConnectionIO::BluetoothDaemonConnectionIO( - MessageLoop* aIOLoop, int aFd, - ConnectionStatus aConnectionStatus, - BluetoothDaemonConnection* aConnection, - BluetoothDaemonPDUConsumer* aConsumer) -: UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus) -, mConnection(aConnection) -, mConsumer(aConsumer) -, mShuttingDownOnIOThread(false) -{ - MOZ_ASSERT(mConnection); - MOZ_ASSERT(mConsumer); -} - -void -BluetoothDaemonConnectionIO::Send(UnixSocketIOBuffer* aBuffer) -{ - MOZ_ASSERT(aBuffer); - - EnqueueData(aBuffer); - AddWatchers(WRITE_WATCHER, false); -} - -void -BluetoothDaemonConnectionIO::OnSocketCanReceiveWithoutBlocking() -{ - ssize_t res = ReceiveData(GetFd()); - if (res < 0) { - /* I/O error */ - RemoveWatchers(READ_WATCHER|WRITE_WATCHER); - } else if (!res) { - /* EOF or peer shutdown */ - RemoveWatchers(READ_WATCHER); - } -} - -void -BluetoothDaemonConnectionIO::OnSocketCanSendWithoutBlocking() -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); - MOZ_ASSERT(!IsShutdownOnIOThread()); - - if (NS_WARN_IF(NS_FAILED(SendPendingData(GetFd())))) { - RemoveWatchers(WRITE_WATCHER); - } -} - -void -BluetoothDaemonConnectionIO::OnConnected() -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); - - NS_DispatchToMainThread( - new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS)); - - AddWatchers(READ_WATCHER, true); - if (HasPendingData()) { - AddWatchers(WRITE_WATCHER, false); - } -} - -void -BluetoothDaemonConnectionIO::OnError(const char* aFunction, int aErrno) -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - - UnixFdWatcher::OnError(aFunction, aErrno); - - // Clean up watchers, status, fd - Close(); - - // Tell the main thread we've errored - NS_DispatchToMainThread( - new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR)); -} - -// |ConnectionOrientedSocketIO| - -nsresult -BluetoothDaemonConnectionIO::Accept(int aFd, - const struct sockaddr* aAddress, - socklen_t aAddressLength) -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING); - - // File-descriptor setup - - if (TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, O_NONBLOCK)) < 0) { - OnError("fcntl", errno); - ScopedClose cleanupFd(aFd); - return NS_ERROR_FAILURE; - } - - SetSocket(aFd, SOCKET_IS_CONNECTED); - - // Signal success - OnConnected(); - - return NS_OK; -} - -// |DataSocketIO| - -nsresult -BluetoothDaemonConnectionIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) -{ - MOZ_ASSERT(aBuffer); - - if (!mPDU) { - /* There's only one PDU for receiving. We reuse it every time. */ - mPDU = new BluetoothDaemonPDU(BluetoothDaemonPDU::MAX_PAYLOAD_LENGTH); - } - *aBuffer = mPDU.get(); - - return NS_OK; -} - -void -BluetoothDaemonConnectionIO::ConsumeBuffer() -{ - MOZ_ASSERT(mConsumer); - - mConsumer->Handle(*mPDU); -} - -void -BluetoothDaemonConnectionIO::DiscardBuffer() -{ - // Nothing to do. -} - -// |SocketIOBase| - -SocketBase* -BluetoothDaemonConnectionIO::GetSocketBase() -{ - return mConnection; -} - -bool -BluetoothDaemonConnectionIO::IsShutdownOnMainThread() const -{ - MOZ_ASSERT(NS_IsMainThread()); - - return mConnection == nullptr; -} - -bool -BluetoothDaemonConnectionIO::IsShutdownOnIOThread() const -{ - return mShuttingDownOnIOThread; -} - -void -BluetoothDaemonConnectionIO::ShutdownOnMainThread() -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!IsShutdownOnMainThread()); - - mConnection = nullptr; -} - -void -BluetoothDaemonConnectionIO::ShutdownOnIOThread() -{ - MOZ_ASSERT(!NS_IsMainThread()); - MOZ_ASSERT(!mShuttingDownOnIOThread); - - Close(); // will also remove fd from I/O loop - mShuttingDownOnIOThread = true; -} - -// -// BluetoothDaemonConnection -// - -BluetoothDaemonConnection::BluetoothDaemonConnection( - BluetoothDaemonPDUConsumer* aPDUConsumer, - BluetoothDaemonConnectionConsumer* aConsumer, - int aIndex) - : mPDUConsumer(aPDUConsumer) - , mConsumer(aConsumer) - , mIndex(aIndex) - , mIO(nullptr) -{ - MOZ_ASSERT(mConsumer); -} - -BluetoothDaemonConnection::~BluetoothDaemonConnection() -{ } - -// |ConnectionOrientedSocket| - -nsresult -BluetoothDaemonConnection::PrepareAccept(UnixSocketConnector* aConnector, - ConnectionOrientedSocketIO*& aIO) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!mIO); - - // |BluetoothDaemonConnection| now owns the connector, but doesn't - // actually use it. So the connector is stored in an auto pointer - // to be deleted at the end of the method. - nsAutoPtr connector(aConnector); - - SetConnectionStatus(SOCKET_CONNECTING); - - mIO = new BluetoothDaemonConnectionIO( - XRE_GetIOMessageLoop(), -1, UnixSocketWatcher::SOCKET_IS_CONNECTING, - this, mPDUConsumer); - aIO = mIO; - - return NS_OK; -} - -// |DataSocket| - -void -BluetoothDaemonConnection::SendSocketData(UnixSocketIOBuffer* aBuffer) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mIO); - - XRE_GetIOMessageLoop()->PostTask( - FROM_HERE, - new SocketIOSendTask(mIO, aBuffer)); -} - -// |SocketBase| - -void -BluetoothDaemonConnection::Close() -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (!mIO) { - CHROMIUM_LOG("Bluetooth daemon already disconnected!"); - return; - } - - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO)); - - mIO = nullptr; - - NotifyDisconnect(); -} - -void -BluetoothDaemonConnection::OnConnectSuccess() -{ - MOZ_ASSERT(NS_IsMainThread()); - - mConsumer->OnConnectSuccess(mIndex); -} - -void -BluetoothDaemonConnection::OnConnectError() -{ - MOZ_ASSERT(NS_IsMainThread()); - - mConsumer->OnConnectError(mIndex); -} - -void -BluetoothDaemonConnection::OnDisconnect() -{ - MOZ_ASSERT(NS_IsMainThread()); - - mConsumer->OnDisconnect(mIndex); -} - -} -} diff --git a/ipc/bluetooth/BluetoothDaemonConnection.h b/ipc/bluetooth/BluetoothDaemonConnection.h deleted file mode 100644 index afc935c3da..0000000000 --- a/ipc/bluetooth/BluetoothDaemonConnection.h +++ /dev/null @@ -1,151 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_ipc_bluetooth_BluetoothDaemonConnection_h -#define mozilla_ipc_bluetooth_BluetoothDaemonConnection_h - -#include "mozilla/Attributes.h" -#include "mozilla/FileUtils.h" -#include "mozilla/ipc/ConnectionOrientedSocket.h" -#include "nsAutoPtr.h" - -namespace mozilla { -namespace ipc { - -class BluetoothDaemonConnectionConsumer; -class BluetoothDaemonConnectionIO; -class BluetoothDaemonPDUConsumer; - -/* - * |BlutoothDaemonPDU| represents a single PDU that is transfered from or to - * the Bluetooth daemon. Each PDU contains exactly one command. - * - * A PDU as the following format - * - * | 1 | 1 | 2 | n | - * | service | opcode | payload length | payload | - * - * Service and Opcode each require 1 byte, the payload length requires 2 - * bytes, and the payload requires the number of bytes as stored in the - * payload-length field. - * - * Each service and opcode can have a different payload with individual - * length. For the exact details of the Bluetooth protocol, please refer - * to - * - * https://git.kernel.org/cgit/bluetooth/bluez.git/tree/android/hal-ipc-api.txt?id=5.24 - * - */ -class BluetoothDaemonPDU final : public UnixSocketIOBuffer -{ -public: - enum { - OFF_SERVICE = 0, - OFF_OPCODE = 1, - OFF_LENGTH = 2, - OFF_PAYLOAD = 4, - HEADER_SIZE = OFF_PAYLOAD, - MAX_PAYLOAD_LENGTH = 1 << 16 - }; - - BluetoothDaemonPDU(uint8_t aService, uint8_t aOpcode, - uint16_t aPayloadSize); - BluetoothDaemonPDU(size_t aPayloadSize); - - void SetConsumer(BluetoothDaemonPDUConsumer* aConsumer) - { - mConsumer = aConsumer; - } - - void SetUserData(void* aUserData) - { - mUserData = aUserData; - } - - void* GetUserData() const - { - return mUserData; - } - - void GetHeader(uint8_t& aService, uint8_t& aOpcode, - uint16_t& aPayloadSize); - - ssize_t Send(int aFd) override; - ssize_t Receive(int aFd) override; - - int AcquireFd(); - - nsresult UpdateHeader(); - -private: - size_t GetPayloadSize() const; - void OnError(const char* aFunction, int aErrno); - - BluetoothDaemonPDUConsumer* mConsumer; - void* mUserData; - ScopedClose mReceivedFd; -}; - -/* - * |BluetoothDaemonPDUConsumer| processes incoming PDUs from the Bluetooth - * daemon. Please note that its method |Handle| runs on a different than the - * main thread. - */ -class BluetoothDaemonPDUConsumer -{ -public: - virtual ~BluetoothDaemonPDUConsumer(); - - virtual void Handle(BluetoothDaemonPDU& aPDU) = 0; - virtual void StoreUserData(const BluetoothDaemonPDU& aPDU) = 0; - -protected: - BluetoothDaemonPDUConsumer(); -}; - -/* - * |BluetoothDaemonConnection| represents the socket to connect to the - * Bluetooth daemon. It offers connection establishment and sending - * PDUs. PDU receiving is performed by |BluetoothDaemonPDUConsumer|. - */ -class BluetoothDaemonConnection : public ConnectionOrientedSocket -{ -public: - BluetoothDaemonConnection(BluetoothDaemonPDUConsumer* aPDUConsumer, - BluetoothDaemonConnectionConsumer* aConsumer, - int aIndex); - virtual ~BluetoothDaemonConnection(); - - // Methods for |ConnectionOrientedSocket| - // - - nsresult PrepareAccept(UnixSocketConnector* aConnector, - ConnectionOrientedSocketIO*& aIO) override; - - // Methods for |DataSocket| - // - - void SendSocketData(UnixSocketIOBuffer* aBuffer) override; - - // Methods for |SocketBase| - // - - void Close() override; - void OnConnectSuccess() override; - void OnConnectError() override; - void OnDisconnect() override; - -private: - BluetoothDaemonPDUConsumer* mPDUConsumer; - BluetoothDaemonConnectionConsumer* mConsumer; - int mIndex; - BluetoothDaemonConnectionIO* mIO; -}; - -} -} - -#endif diff --git a/ipc/glue/IPCMessageUtils.h b/ipc/glue/IPCMessageUtils.h index cf4858b384..b550c8d2eb 100644 --- a/ipc/glue/IPCMessageUtils.h +++ b/ipc/glue/IPCMessageUtils.h @@ -12,6 +12,7 @@ #include "mozilla/ArrayUtils.h" #include "mozilla/DebugOnly.h" +#include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/Maybe.h" #include "mozilla/TimeStamp.h" #ifdef XP_WIN @@ -64,11 +65,6 @@ struct SerializedStructuredCloneBuffer : data(nullptr), dataLength(0) { } - explicit SerializedStructuredCloneBuffer(const JSAutoStructuredCloneBuffer& aOther) - { - *this = aOther; - } - bool operator==(const SerializedStructuredCloneBuffer& aOther) const { @@ -76,47 +72,10 @@ struct SerializedStructuredCloneBuffer this->dataLength == aOther.dataLength; } - SerializedStructuredCloneBuffer& - operator=(const JSAutoStructuredCloneBuffer& aOther) - { - data = aOther.data(); - dataLength = aOther.nbytes(); - return *this; - } - uint64_t* data; size_t dataLength; }; -struct OwningSerializedStructuredCloneBuffer : public SerializedStructuredCloneBuffer -{ - OwningSerializedStructuredCloneBuffer() - {} - - OwningSerializedStructuredCloneBuffer(const OwningSerializedStructuredCloneBuffer&) = delete; - - explicit OwningSerializedStructuredCloneBuffer(const JSAutoStructuredCloneBuffer& aOther) - : SerializedStructuredCloneBuffer(aOther) - {} - - ~OwningSerializedStructuredCloneBuffer() - { - if (data) { - js_free(data); - } - } - - OwningSerializedStructuredCloneBuffer& - operator=(const JSAutoStructuredCloneBuffer& aOther) - { - SerializedStructuredCloneBuffer::operator=(aOther); - return *this; - } - - OwningSerializedStructuredCloneBuffer& - operator=(const OwningSerializedStructuredCloneBuffer& aOther) = delete; -}; - } // namespace mozilla namespace IPC { @@ -733,6 +692,27 @@ struct ParamTraits #endif +template <> +struct ParamTraits +{ + typedef mozilla::dom::ipc::StructuredCloneData paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + aParam.WriteIPCParams(aMsg); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + return aResult->ReadIPCParams(aMsg, aIter); + } + + static void Log(const paramType& aParam, std::wstring* aLog) + { + LogParam(aParam.DataLength(), aLog); + } +}; + template <> struct ParamTraits { @@ -774,31 +754,6 @@ struct ParamTraits } }; -template <> -struct ParamTraits - : public ParamTraits -{ - typedef mozilla::OwningSerializedStructuredCloneBuffer paramType; - - static bool Read(const Message* aMsg, void** aIter, paramType* aResult) - { - if (!ParamTraits::Read(aMsg, aIter, aResult)) { - return false; - } - - if (aResult->data) { - uint64_t* data = static_cast(js_malloc(aResult->dataLength)); - if (!data) { - return false; - } - memcpy(data, aResult->data, aResult->dataLength); - aResult->data = data; - } - - return true; - } -}; - template <> struct ParamTraits : public BitFlagsEnumSerializer +#define CHROMIUM_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "I/O", args); +#else +#include +#define IODEBUG true +#define CHROMIUM_LOG(args...) if (IODEBUG) printf(args); +#endif + +namespace mozilla { +namespace ipc { + +// +// DaemonSocketIO +// + +class DaemonSocketIO final : public ConnectionOrientedSocketIO +{ +public: + DaemonSocketIO(MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, + int aFd, ConnectionStatus aConnectionStatus, + UnixSocketConnector* aConnector, + DaemonSocket* aConnection, + DaemonSocketIOConsumer* aConsumer); + + ~DaemonSocketIO(); + + // Methods for |DataSocketIO| + // + + nsresult QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) override; + void ConsumeBuffer() override; + void DiscardBuffer() override; + + // Methods for |SocketIOBase| + // + + SocketBase* GetSocketBase() override; + + bool IsShutdownOnConsumerThread() const override; + bool IsShutdownOnIOThread() const override; + + void ShutdownOnConsumerThread() override; + void ShutdownOnIOThread() override; + +private: + DaemonSocket* mConnection; + DaemonSocketIOConsumer* mConsumer; + nsAutoPtr mPDU; + bool mShuttingDownOnIOThread; +}; + +DaemonSocketIO::DaemonSocketIO( + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, + int aFd, + ConnectionStatus aConnectionStatus, + UnixSocketConnector* aConnector, + DaemonSocket* aConnection, + DaemonSocketIOConsumer* aConsumer) + : ConnectionOrientedSocketIO(aConsumerLoop, + aIOLoop, + aFd, + aConnectionStatus, + aConnector) + , mConnection(aConnection) + , mConsumer(aConsumer) + , mShuttingDownOnIOThread(false) +{ + MOZ_ASSERT(mConnection); + MOZ_ASSERT(mConsumer); + + MOZ_COUNT_CTOR_INHERITED(DaemonSocketIO, ConnectionOrientedSocketIO); +} + +DaemonSocketIO::~DaemonSocketIO() +{ + MOZ_COUNT_DTOR_INHERITED(DaemonSocketIO, ConnectionOrientedSocketIO); +} + +// |DataSocketIO| + +nsresult +DaemonSocketIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) +{ + MOZ_ASSERT(aBuffer); + + if (!mPDU) { + /* There's only one PDU for receiving. We reuse it every time. */ + mPDU = new DaemonSocketPDU(DaemonSocketPDU::MAX_PAYLOAD_LENGTH); + } + *aBuffer = mPDU.get(); + + return NS_OK; +} + +void +DaemonSocketIO::ConsumeBuffer() +{ + MOZ_ASSERT(mConsumer); + + mConsumer->Handle(*mPDU); +} + +void +DaemonSocketIO::DiscardBuffer() +{ + // Nothing to do. +} + +// |SocketIOBase| + +SocketBase* +DaemonSocketIO::GetSocketBase() +{ + return mConnection; +} + +bool +DaemonSocketIO::IsShutdownOnConsumerThread() const +{ + MOZ_ASSERT(IsConsumerThread()); + + return mConnection == nullptr; +} + +bool +DaemonSocketIO::IsShutdownOnIOThread() const +{ + return mShuttingDownOnIOThread; +} + +void +DaemonSocketIO::ShutdownOnConsumerThread() +{ + MOZ_ASSERT(IsConsumerThread()); + MOZ_ASSERT(!IsShutdownOnConsumerThread()); + + mConnection = nullptr; +} + +void +DaemonSocketIO::ShutdownOnIOThread() +{ + MOZ_ASSERT(!IsConsumerThread()); + MOZ_ASSERT(!mShuttingDownOnIOThread); + + Close(); // will also remove fd from I/O loop + mShuttingDownOnIOThread = true; +} + +// +// DaemonSocket +// + +DaemonSocket::DaemonSocket( + DaemonSocketIOConsumer* aIOConsumer, + DaemonSocketConsumer* aConsumer, + int aIndex) + : mIO(nullptr) + , mIOConsumer(aIOConsumer) + , mConsumer(aConsumer) + , mIndex(aIndex) +{ + MOZ_ASSERT(mConsumer); + + MOZ_COUNT_CTOR_INHERITED(DaemonSocket, ConnectionOrientedSocket); +} + +DaemonSocket::~DaemonSocket() +{ + MOZ_COUNT_DTOR_INHERITED(DaemonSocket, ConnectionOrientedSocket); +} + +// |ConnectionOrientedSocket| + +nsresult +DaemonSocket::PrepareAccept(UnixSocketConnector* aConnector, + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, + ConnectionOrientedSocketIO*& aIO) +{ + MOZ_ASSERT(!mIO); + + SetConnectionStatus(SOCKET_CONNECTING); + + mIO = new DaemonSocketIO( + aConsumerLoop, aIOLoop, -1, UnixSocketWatcher::SOCKET_IS_CONNECTING, + aConnector, this, mIOConsumer); + aIO = mIO; + + return NS_OK; +} + +// |DataSocket| + +void +DaemonSocket::SendSocketData(UnixSocketIOBuffer* aBuffer) +{ + MOZ_ASSERT(mIO); + MOZ_ASSERT(mIO->IsConsumerThread()); + + mIO->GetIOLoop()->PostTask( + FROM_HERE, + new SocketIOSendTask(mIO, aBuffer)); +} + +// |SocketBase| + +void +DaemonSocket::Close() +{ + if (!mIO) { + CHROMIUM_LOG("HAL daemon already disconnected!"); + return; + } + + MOZ_ASSERT(mIO->IsConsumerThread()); + + mIO->ShutdownOnConsumerThread(); + mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO)); + mIO = nullptr; + + NotifyDisconnect(); +} + +void +DaemonSocket::OnConnectSuccess() +{ + mConsumer->OnConnectSuccess(mIndex); +} + +void +DaemonSocket::OnConnectError() +{ + mConsumer->OnConnectError(mIndex); +} + +void +DaemonSocket::OnDisconnect() +{ + mConsumer->OnDisconnect(mIndex); +} + +} +} diff --git a/ipc/hal/DaemonSocket.h b/ipc/hal/DaemonSocket.h new file mode 100644 index 0000000000..63d3a2e5cc --- /dev/null +++ b/ipc/hal/DaemonSocket.h @@ -0,0 +1,63 @@ +/* -*- 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/. */ + +#ifndef mozilla_ipc_DaemonSocket_h +#define mozilla_ipc_DaemonSocket_h + +#include "mozilla/ipc/ConnectionOrientedSocket.h" + +namespace mozilla { +namespace ipc { + +class DaemonSocketConsumer; +class DaemonSocketIO; +class DaemonSocketIOConsumer; + +/** + * |DaemonSocket| represents the socket to connect to the HAL daemon. It + * offers connection establishment and sending PDUs. PDU receiving is + * performed by |DaemonSocketIOConsumer|. + */ +class DaemonSocket : public ConnectionOrientedSocket +{ +public: + DaemonSocket(DaemonSocketIOConsumer* aIOConsumer, + DaemonSocketConsumer* aConsumer, + int aIndex); + virtual ~DaemonSocket(); + + // Methods for |ConnectionOrientedSocket| + // + + nsresult PrepareAccept(UnixSocketConnector* aConnector, + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, + ConnectionOrientedSocketIO*& aIO) override; + + // Methods for |DataSocket| + // + + void SendSocketData(UnixSocketIOBuffer* aBuffer) override; + + // Methods for |SocketBase| + // + + void Close() override; + void OnConnectSuccess() override; + void OnConnectError() override; + void OnDisconnect() override; + +private: + DaemonSocketIO* mIO; + DaemonSocketIOConsumer* mIOConsumer; + DaemonSocketConsumer* mConsumer; + int mIndex; +}; + +} +} + +#endif diff --git a/ipc/hal/DaemonSocketConsumer.cpp b/ipc/hal/DaemonSocketConsumer.cpp new file mode 100644 index 0000000000..ad57d5f575 --- /dev/null +++ b/ipc/hal/DaemonSocketConsumer.cpp @@ -0,0 +1,33 @@ +/* -*- 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 "DaemonSocketConsumer.h" + +namespace mozilla { +namespace ipc { + +// +// DaemonSocketIOConsumer +// + +DaemonSocketIOConsumer::DaemonSocketIOConsumer() +{ } + +DaemonSocketIOConsumer::~DaemonSocketIOConsumer() +{ } + +// +// DaemonSocketConsumer +// + +DaemonSocketConsumer::DaemonSocketConsumer() +{ } + +DaemonSocketConsumer::~DaemonSocketConsumer() +{ } + +} +} diff --git a/ipc/hal/DaemonSocketConsumer.h b/ipc/hal/DaemonSocketConsumer.h new file mode 100644 index 0000000000..4dda45046f --- /dev/null +++ b/ipc/hal/DaemonSocketConsumer.h @@ -0,0 +1,68 @@ +/* -*- 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/. */ + +#ifndef mozilla_ipc_DaemonSocketConsumer_h +#define mozilla_ipc_DaemonSocketConsumer_h + +namespace mozilla { +namespace ipc { + +class DaemonSocketPDU; + +/** + * |DaemonSocketIOConsumer| processes incoming PDUs from the + * HAL daemon. Please note that its method |Handle| runs on a + * different than the consumer thread. + */ +class DaemonSocketIOConsumer +{ +public: + virtual ~DaemonSocketIOConsumer(); + + virtual void Handle(DaemonSocketPDU& aPDU) = 0; + virtual void StoreUserData(const DaemonSocketPDU& aPDU) = 0; + +protected: + DaemonSocketIOConsumer(); +}; + +/** + * |DaemonSocketConsumer| handles socket events. + */ +class DaemonSocketConsumer +{ +public: + /** + * Callback for socket success. Consumer-thread only. + * + * @param aIndex The index that has been given to the stream socket. + */ + virtual void OnConnectSuccess(int aIndex) = 0; + + /** + * Callback for socket errors. Consumer-thread only. + * + * @param aIndex The index that has been given to the stream socket. + */ + virtual void OnConnectError(int aIndex) = 0; + + /** + * Callback for socket disconnect. Consumer-thread only. + * + * @param aIndex The index that has been given to the stream socket. + */ + virtual void OnDisconnect(int aIndex) = 0; + +protected: + DaemonSocketConsumer(); + virtual ~DaemonSocketConsumer(); +}; + +} +} + +#endif + diff --git a/ipc/hal/DaemonSocketPDU.cpp b/ipc/hal/DaemonSocketPDU.cpp new file mode 100644 index 0000000000..380c0eef9f --- /dev/null +++ b/ipc/hal/DaemonSocketPDU.cpp @@ -0,0 +1,195 @@ +/* -*- 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 "DaemonSocketPDU.h" +#include "mozilla/ipc/DaemonSocketConsumer.h" +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR + +#ifdef CHROMIUM_LOG +#undef CHROMIUM_LOG +#endif + +#if defined(MOZ_WIDGET_GONK) +#include +#define CHROMIUM_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "I/O", args); +#else +#include +#define IODEBUG true +#define CHROMIUM_LOG(args...) if (IODEBUG) printf(args); +#endif + +namespace mozilla { +namespace ipc { + +// +// DaemonSocketPDU +// + +DaemonSocketPDU::DaemonSocketPDU(uint8_t aService, uint8_t aOpcode, + uint16_t aPayloadSize) + : mConsumer(nullptr) + , mUserData(nullptr) +{ + MOZ_COUNT_CTOR_INHERITED(DaemonSocketPDU, UnixSocketIOBuffer); + + // Allocate memory + size_t availableSpace = HEADER_SIZE + aPayloadSize; + ResetBuffer(new uint8_t[availableSpace], 0, 0, availableSpace); + + // Reserve PDU header + uint8_t* data = Append(HEADER_SIZE); + MOZ_ASSERT(data); + + // Setup PDU header + data[OFF_SERVICE] = aService; + data[OFF_OPCODE] = aOpcode; + memcpy(data + OFF_LENGTH, &aPayloadSize, sizeof(aPayloadSize)); +} + +DaemonSocketPDU::DaemonSocketPDU(size_t aPayloadSize) + : mConsumer(nullptr) + , mUserData(nullptr) +{ + MOZ_COUNT_CTOR_INHERITED(DaemonSocketPDU, UnixSocketIOBuffer); + + size_t availableSpace = HEADER_SIZE + aPayloadSize; + ResetBuffer(new uint8_t[availableSpace], 0, 0, availableSpace); +} + +DaemonSocketPDU::~DaemonSocketPDU() +{ + MOZ_COUNT_DTOR_INHERITED(DaemonSocketPDU, UnixSocketIOBuffer); + + nsAutoArrayPtr data(GetBuffer()); + ResetBuffer(nullptr, 0, 0, 0); +} + +void +DaemonSocketPDU::GetHeader(uint8_t& aService, uint8_t& aOpcode, + uint16_t& aPayloadSize) +{ + memcpy(&aService, GetData(OFF_SERVICE), sizeof(aService)); + memcpy(&aOpcode, GetData(OFF_OPCODE), sizeof(aOpcode)); + memcpy(&aPayloadSize, GetData(OFF_LENGTH), sizeof(aPayloadSize)); +} + +ssize_t +DaemonSocketPDU::Send(int aFd) +{ + struct iovec iv; + memset(&iv, 0, sizeof(iv)); + iv.iov_base = GetData(GetLeadingSpace()); + iv.iov_len = GetSize(); + + struct msghdr msg; + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = &iv; + msg.msg_iovlen = 1; + msg.msg_control = nullptr; + msg.msg_controllen = 0; + + ssize_t res = TEMP_FAILURE_RETRY(sendmsg(aFd, &msg, 0)); + if (res < 0) { + MOZ_ASSERT(errno != EBADF); /* internal error */ + OnError("sendmsg", errno); + return -1; + } + + Consume(res); + + if (mConsumer) { + // We successfully sent a PDU, now store the + // result runnable in the consumer. + mConsumer->StoreUserData(*this); + } + + return res; +} + +#define CMSGHDR_CONTAINS_FD(_cmsghdr) \ + ( ((_cmsghdr)->cmsg_level == SOL_SOCKET) && \ + ((_cmsghdr)->cmsg_type == SCM_RIGHTS) ) + +ssize_t +DaemonSocketPDU::Receive(int aFd) +{ + struct iovec iv; + memset(&iv, 0, sizeof(iv)); + iv.iov_base = GetData(0); + iv.iov_len = GetAvailableSpace(); + + uint8_t cmsgbuf[CMSG_SPACE(sizeof(int))]; + + struct msghdr msg; + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = &iv; + msg.msg_iovlen = 1; + msg.msg_control = cmsgbuf; + msg.msg_controllen = sizeof(cmsgbuf); + + ssize_t res = TEMP_FAILURE_RETRY(recvmsg(aFd, &msg, MSG_NOSIGNAL)); + if (res < 0) { + MOZ_ASSERT(errno != EBADF); /* internal error */ + OnError("recvmsg", errno); + return -1; + } + if (msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) { + return -1; + } + + SetRange(0, res); + + struct cmsghdr *chdr = CMSG_FIRSTHDR(&msg); + + for (; chdr; chdr = CMSG_NXTHDR(&msg, chdr)) { + if (NS_WARN_IF(!CMSGHDR_CONTAINS_FD(chdr))) { + continue; + } + // Retrieve sent file descriptor. If multiple file descriptors + // have been sent, we close all but the final one. + mReceivedFd = *(static_cast(CMSG_DATA(chdr))); + } + + return res; +} + +int +DaemonSocketPDU::AcquireFd() +{ + return mReceivedFd.forget(); +} + +nsresult +DaemonSocketPDU::UpdateHeader() +{ + size_t len = GetPayloadSize(); + if (len >= MAX_PAYLOAD_LENGTH) { + return NS_ERROR_ILLEGAL_VALUE; + } + uint16_t len16 = static_cast(len); + + memcpy(GetData(OFF_LENGTH), &len16, sizeof(len16)); + + return NS_OK; +} + +size_t +DaemonSocketPDU::GetPayloadSize() const +{ + MOZ_ASSERT(GetSize() >= HEADER_SIZE); + + return GetSize() - HEADER_SIZE; +} + +void +DaemonSocketPDU::OnError(const char* aFunction, int aErrno) +{ + CHROMIUM_LOG("%s failed with error %d (%s)", + aFunction, aErrno, strerror(aErrno)); +} + +} +} diff --git a/ipc/hal/DaemonSocketPDU.h b/ipc/hal/DaemonSocketPDU.h new file mode 100644 index 0000000000..95275f03c5 --- /dev/null +++ b/ipc/hal/DaemonSocketPDU.h @@ -0,0 +1,91 @@ +/* -*- 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/. */ + +#ifndef mozilla_ipc_DaemonSocketPDU_h +#define mozilla_ipc_DaemonSocketPDU_h + +#include "mozilla/FileUtils.h" +#include "mozilla/ipc/SocketBase.h" + +namespace mozilla { +namespace ipc { + +class DaemonSocketIOConsumer; + +/** + * |DaemonSocketPDU| represents a single PDU that is transfered from or to + * the HAL daemon. Each PDU contains exactly one command. + * + * A PDU as the following format + * + * | 1 | 1 | 2 | n | + * | service | opcode | payload length | payload | + * + * Service and Opcode each require 1 byte, the payload length requires 2 + * bytes, and the payload requires the number of bytes as stored in the + * payload-length field. + * + * Each service and opcode can have a different payload with individual + * length. For the exact details of the HAL protocol, please refer to + * + * https://git.kernel.org/cgit/bluetooth/bluez.git/tree/android/hal-ipc-api.txt?id=5.24 + * + */ +class DaemonSocketPDU final : public UnixSocketIOBuffer +{ +public: + enum { + OFF_SERVICE = 0, + OFF_OPCODE = 1, + OFF_LENGTH = 2, + OFF_PAYLOAD = 4, + HEADER_SIZE = OFF_PAYLOAD, + MAX_PAYLOAD_LENGTH = 1 << 16 + }; + + DaemonSocketPDU(uint8_t aService, uint8_t aOpcode, uint16_t aPayloadSize); + DaemonSocketPDU(size_t aPayloadSize); + ~DaemonSocketPDU(); + + void SetConsumer(DaemonSocketIOConsumer* aConsumer) + { + mConsumer = aConsumer; + } + + void SetUserData(void* aUserData) + { + mUserData = aUserData; + } + + void* GetUserData() const + { + return mUserData; + } + + void GetHeader(uint8_t& aService, uint8_t& aOpcode, + uint16_t& aPayloadSize); + + ssize_t Send(int aFd) override; + ssize_t Receive(int aFd) override; + + int AcquireFd(); + + nsresult UpdateHeader(); + +private: + size_t GetPayloadSize() const; + void OnError(const char* aFunction, int aErrno); + + DaemonSocketIOConsumer* mConsumer; + void* mUserData; + ScopedClose mReceivedFd; +}; + +} +} + +#endif + diff --git a/ipc/bluetooth/moz.build b/ipc/hal/moz.build similarity index 70% rename from ipc/bluetooth/moz.build rename to ipc/hal/moz.build index 03c7e8a9fa..382856dec0 100644 --- a/ipc/bluetooth/moz.build +++ b/ipc/hal/moz.build @@ -5,11 +5,15 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. EXPORTS.mozilla.ipc += [ - 'BluetoothDaemonConnection.h' + 'DaemonSocket.h', + 'DaemonSocketConsumer.h', + 'DaemonSocketPDU.h' ] -SOURCES += [ - 'BluetoothDaemonConnection.cpp' +UNIFIED_SOURCES += [ + 'DaemonSocket.cpp', + 'DaemonSocketConsumer.cpp', + 'DaemonSocketPDU.cpp' ] include('/ipc/chromium/chromium-config.mozbuild') diff --git a/ipc/ipdl/ipdl/lower.py b/ipc/ipdl/ipdl/lower.py index 249b4b165f..b7fb045247 100644 --- a/ipc/ipdl/ipdl/lower.py +++ b/ipc/ipdl/ipdl/lower.py @@ -2933,7 +2933,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor): ExprMemberInit(p.lastActorIdVar(), [ p.actorIdInit(self.side) ]), ExprMemberInit(p.otherPidVar(), - [ ExprVar('ipc::kInvalidProcessId') ]), + [ ExprVar('mozilla::ipc::kInvalidProcessId') ]), ExprMemberInit(p.lastShmemIdVar(), [ p.shmemIdInit(self.side) ]), ExprMemberInit(p.stateVar(), diff --git a/ipc/keystore/KeyStoreConnector.cpp b/ipc/keystore/KeyStoreConnector.cpp index 6f019aebaf..0e11fcec65 100644 --- a/ipc/keystore/KeyStoreConnector.cpp +++ b/ipc/keystore/KeyStoreConnector.cpp @@ -10,6 +10,7 @@ #include #include #include +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR #include "nsThreadUtils.h" // For NS_IsMainThread. #ifdef MOZ_WIDGET_GONK @@ -26,10 +27,14 @@ static const char KEYSTORE_SOCKET_PATH[] = "/dev/socket/keystore"; KeyStoreConnector::KeyStoreConnector(const char** const aAllowedUsers) : mAllowedUsers(aAllowedUsers) -{ } +{ + MOZ_COUNT_CTOR_INHERITED(KeyStoreConnector, UnixSocketConnector); +} KeyStoreConnector::~KeyStoreConnector() -{ } +{ + MOZ_COUNT_DTOR_INHERITED(KeyStoreConnector, UnixSocketConnector); +} nsresult KeyStoreConnector::CreateSocket(int& aFd) const diff --git a/ipc/moz.build b/ipc/moz.build index 568ca5d2b3..ab07dc6945 100644 --- a/ipc/moz.build +++ b/ipc/moz.build @@ -14,9 +14,6 @@ DIRS += [ if CONFIG['MOZ_B2G_RIL']: DIRS += ['ril'] -if CONFIG['MOZ_B2G_BT_BLUEDROID']: - DIRS += ['bluetooth'] - if CONFIG['MOZ_B2G_BT_BLUEZ']: DIRS += ['dbus'] @@ -27,7 +24,7 @@ if CONFIG['MOZ_B2G_RIL'] or CONFIG['MOZ_B2G_BT'] or CONFIG['MOZ_NFC'] or CONFIG[ DIRS += ['unixfd', 'unixsocket'] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': - DIRS += ['keystore', 'netd'] + DIRS += ['hal', 'keystore', 'netd'] if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android': DIRS += ['contentproc'] diff --git a/ipc/nfc/NfcConnector.cpp b/ipc/nfc/NfcConnector.cpp index c86a4c9589..01e08fc45f 100644 --- a/ipc/nfc/NfcConnector.cpp +++ b/ipc/nfc/NfcConnector.cpp @@ -8,6 +8,7 @@ #include "NfcConnector.h" #include #include +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR #include "nsThreadUtils.h" // For NS_IsMainThread. namespace mozilla { @@ -15,10 +16,14 @@ namespace ipc { NfcConnector::NfcConnector(const nsACString& aAddressString) : mAddressString(aAddressString) -{ } +{ + MOZ_COUNT_CTOR_INHERITED(NfcConnector, UnixSocketConnector); +} NfcConnector::~NfcConnector() -{ } +{ + MOZ_COUNT_DTOR_INHERITED(NfcConnector, UnixSocketConnector); +} nsresult NfcConnector::CreateSocket(int& aFd) const diff --git a/ipc/ril/RilConnector.cpp b/ipc/ril/RilConnector.cpp index c3ab7f5afe..6e10beed77 100644 --- a/ipc/ril/RilConnector.cpp +++ b/ipc/ril/RilConnector.cpp @@ -8,6 +8,7 @@ #include "RilConnector.h" #include #include +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR #include "nsThreadUtils.h" // For NS_IsMainThread. #ifdef AF_INET @@ -27,10 +28,14 @@ RilConnector::RilConnector(const nsACString& aAddressString, unsigned long aClientId) : mAddressString(aAddressString) , mClientId(aClientId) -{ } +{ + MOZ_COUNT_CTOR_INHERITED(RilConnector, UnixSocketConnector); +} RilConnector::~RilConnector() -{ } +{ + MOZ_COUNT_DTOR_INHERITED(RilConnector, UnixSocketConnector); +} nsresult RilConnector::CreateSocket(int aDomain, int& aFd) const diff --git a/ipc/ril/RilSocket.cpp b/ipc/ril/RilSocket.cpp new file mode 100644 index 0000000000..017a0905e8 --- /dev/null +++ b/ipc/ril/RilSocket.cpp @@ -0,0 +1,442 @@ +/* -*- 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 "RilSocket.h" +#include +#include "mozilla/dom/workers/Workers.h" +#include "mozilla/ipc/UnixSocketConnector.h" +#include "mozilla/RefPtr.h" +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR +#include "nsXULAppAPI.h" +#include "RilSocketConsumer.h" + +static const size_t MAX_READ_SIZE = 1 << 16; + +namespace mozilla { +namespace ipc { + +USING_WORKERS_NAMESPACE + +// +// RilSocketIO +// + +class RilSocketIO final : public ConnectionOrientedSocketIO +{ +public: + class ConnectTask; + class DelayedConnectTask; + class ReceiveTask; + + RilSocketIO(WorkerCrossThreadDispatcher* aDispatcher, + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, + RilSocket* aRilSocket, + UnixSocketConnector* aConnector); + ~RilSocketIO(); + + RilSocket* GetRilSocket(); + DataSocket* GetDataSocket(); + + // Delayed-task handling + // + + void SetDelayedConnectTask(CancelableTask* aTask); + void ClearDelayedConnectTask(); + void CancelDelayedConnectTask(); + + // Methods for |DataSocket| + // + + nsresult QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) override; + void ConsumeBuffer() override; + void DiscardBuffer() override; + + // Methods for |SocketIOBase| + // + + SocketBase* GetSocketBase() override; + + bool IsShutdownOnConsumerThread() const override; + bool IsShutdownOnIOThread() const override; + + void ShutdownOnConsumerThread() override; + void ShutdownOnIOThread() override; + +private: + /** + * Cross-thread dispatcher for the RIL worker + */ + nsRefPtr mDispatcher; + + /** + * Consumer pointer. Non-thread safe RefPtr, so should only be manipulated + * directly from consumer thread. All non-consumer-thread accesses should + * happen with mIO as container. + */ + RefPtr mRilSocket; + + /** + * If true, do not requeue whatever task we're running + */ + bool mShuttingDownOnIOThread; + + /** + * Task member for delayed connect task. Should only be access on consumer + * thread. + */ + CancelableTask* mDelayedConnectTask; + + /** + * I/O buffer for received data + */ + nsAutoPtr mBuffer; +}; + +RilSocketIO::RilSocketIO(WorkerCrossThreadDispatcher* aDispatcher, + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, + RilSocket* aRilSocket, + UnixSocketConnector* aConnector) + : ConnectionOrientedSocketIO(aConsumerLoop, aIOLoop, aConnector) + , mDispatcher(aDispatcher) + , mRilSocket(aRilSocket) + , mShuttingDownOnIOThread(false) + , mDelayedConnectTask(nullptr) +{ + MOZ_ASSERT(mDispatcher); + MOZ_ASSERT(mRilSocket); + + MOZ_COUNT_CTOR_INHERITED(RilSocketIO, ConnectionOrientedSocketIO); +} + +RilSocketIO::~RilSocketIO() +{ + MOZ_ASSERT(IsConsumerThread()); + MOZ_ASSERT(IsShutdownOnConsumerThread()); + + MOZ_COUNT_DTOR_INHERITED(RilSocketIO, ConnectionOrientedSocketIO); +} + +RilSocket* +RilSocketIO::GetRilSocket() +{ + return mRilSocket.get(); +} + +DataSocket* +RilSocketIO::GetDataSocket() +{ + return mRilSocket.get(); +} + +void +RilSocketIO::SetDelayedConnectTask(CancelableTask* aTask) +{ + MOZ_ASSERT(IsConsumerThread()); + + mDelayedConnectTask = aTask; +} + +void +RilSocketIO::ClearDelayedConnectTask() +{ + MOZ_ASSERT(IsConsumerThread()); + + mDelayedConnectTask = nullptr; +} + +void +RilSocketIO::CancelDelayedConnectTask() +{ + MOZ_ASSERT(IsConsumerThread()); + + if (!mDelayedConnectTask) { + return; + } + + mDelayedConnectTask->Cancel(); + ClearDelayedConnectTask(); +} + +// |DataSocketIO| + +nsresult +RilSocketIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) +{ + MOZ_ASSERT(aBuffer); + + if (!mBuffer) { + mBuffer = new UnixSocketRawData(MAX_READ_SIZE); + } + *aBuffer = mBuffer.get(); + + return NS_OK; +} + +/** + * |ReceiveTask| transfers data received on the I/O thread + * to an instance of |RilSocket| on the consumer thread. + */ +class RilSocketIO::ReceiveTask final : public WorkerTask +{ +public: + ReceiveTask(RilSocketIO* aIO, UnixSocketBuffer* aBuffer) + : mIO(aIO) + , mBuffer(aBuffer) + { + MOZ_ASSERT(mIO); + } + + bool RunTask(JSContext* aCx) override + { + // Dispatched via WCTD, but still needs to run on the consumer thread + MOZ_ASSERT(mIO->IsConsumerThread()); + + if (NS_WARN_IF(mIO->IsShutdownOnConsumerThread())) { + // Since we've already explicitly closed and the close + // happened before this, this isn't really an error. + return true; + } + + RilSocket* rilSocket = mIO->GetRilSocket(); + MOZ_ASSERT(rilSocket); + + rilSocket->ReceiveSocketData(aCx, mBuffer); + + return true; + } + +private: + RilSocketIO* mIO; + nsAutoPtr mBuffer; +}; + +void +RilSocketIO::ConsumeBuffer() +{ + nsRefPtr task = new ReceiveTask(this, mBuffer.forget()); + NS_WARN_IF(!mDispatcher->PostTask(task)); +} + +void +RilSocketIO::DiscardBuffer() +{ + // Nothing to do. +} + +// |SocketIOBase| + +SocketBase* +RilSocketIO::GetSocketBase() +{ + return GetDataSocket(); +} + +bool +RilSocketIO::IsShutdownOnConsumerThread() const +{ + MOZ_ASSERT(IsConsumerThread()); + + return mRilSocket == nullptr; +} + +bool +RilSocketIO::IsShutdownOnIOThread() const +{ + return mShuttingDownOnIOThread; +} + +void +RilSocketIO::ShutdownOnConsumerThread() +{ + MOZ_ASSERT(IsConsumerThread()); + MOZ_ASSERT(!IsShutdownOnConsumerThread()); + + mRilSocket = nullptr; +} + +void +RilSocketIO::ShutdownOnIOThread() +{ + MOZ_ASSERT(!IsConsumerThread()); + MOZ_ASSERT(!mShuttingDownOnIOThread); + + Close(); // will also remove fd from I/O loop + mShuttingDownOnIOThread = true; +} + +// +// Socket tasks +// + +class RilSocketIO::ConnectTask final + : public SocketIOTask +{ +public: + ConnectTask(RilSocketIO* aIO) + : SocketIOTask(aIO) + { } + + void Run() override + { + MOZ_ASSERT(!GetIO()->IsConsumerThread()); + MOZ_ASSERT(!IsCanceled()); + + GetIO()->Connect(); + } +}; + +class RilSocketIO::DelayedConnectTask final + : public SocketIOTask +{ +public: + DelayedConnectTask(RilSocketIO* aIO) + : SocketIOTask(aIO) + { } + + void Run() override + { + MOZ_ASSERT(GetIO()->IsConsumerThread()); + + if (IsCanceled()) { + return; + } + + RilSocketIO* io = GetIO(); + if (io->IsShutdownOnConsumerThread()) { + return; + } + + io->ClearDelayedConnectTask(); + io->GetIOLoop()->PostTask(FROM_HERE, new ConnectTask(io)); + } +}; + +// +// RilSocket +// + +RilSocket::RilSocket(WorkerCrossThreadDispatcher* aDispatcher, + RilSocketConsumer* aConsumer, int aIndex) + : mIO(nullptr) + , mDispatcher(aDispatcher) + , mConsumer(aConsumer) + , mIndex(aIndex) +{ + MOZ_ASSERT(mDispatcher); + MOZ_ASSERT(mConsumer); + + MOZ_COUNT_CTOR_INHERITED(RilSocket, ConnectionOrientedSocket); +} + +RilSocket::~RilSocket() +{ + MOZ_ASSERT(!mIO); + + MOZ_COUNT_DTOR_INHERITED(RilSocket, ConnectionOrientedSocket); +} + +void +RilSocket::ReceiveSocketData(JSContext* aCx, + nsAutoPtr& aBuffer) +{ + mConsumer->ReceiveSocketData(aCx, mIndex, aBuffer); +} + +nsresult +RilSocket::Connect(UnixSocketConnector* aConnector, int aDelayMs, + MessageLoop* aConsumerLoop, MessageLoop* aIOLoop) +{ + MOZ_ASSERT(!mIO); + + mIO = new RilSocketIO(mDispatcher, aConsumerLoop, aIOLoop, this, aConnector); + SetConnectionStatus(SOCKET_CONNECTING); + + if (aDelayMs > 0) { + RilSocketIO::DelayedConnectTask* connectTask = + new RilSocketIO::DelayedConnectTask(mIO); + mIO->SetDelayedConnectTask(connectTask); + MessageLoop::current()->PostDelayedTask(FROM_HERE, connectTask, aDelayMs); + } else { + aIOLoop->PostTask(FROM_HERE, new RilSocketIO::ConnectTask(mIO)); + } + + return NS_OK; +} + +nsresult +RilSocket::Connect(UnixSocketConnector* aConnector, int aDelayMs) +{ + return Connect(aConnector, aDelayMs, + MessageLoop::current(), XRE_GetIOMessageLoop()); +} + +// |ConnectionOrientedSocket| + +nsresult +RilSocket::PrepareAccept(UnixSocketConnector* aConnector, + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, + ConnectionOrientedSocketIO*& aIO) +{ + MOZ_CRASH("|RilSocket| does not support accepting connections."); +} + +// |DataSocket| + +void +RilSocket::SendSocketData(UnixSocketIOBuffer* aBuffer) +{ + MOZ_ASSERT(mIO); + MOZ_ASSERT(mIO->IsConsumerThread()); + MOZ_ASSERT(!mIO->IsShutdownOnConsumerThread()); + + mIO->GetIOLoop()->PostTask( + FROM_HERE, + new SocketIOSendTask(mIO, aBuffer)); +} + +// |SocketBase| + +void +RilSocket::Close() +{ + MOZ_ASSERT(mIO); + MOZ_ASSERT(mIO->IsConsumerThread()); + + mIO->CancelDelayedConnectTask(); + + // From this point on, we consider |mIO| as being deleted. We sever + // the relationship here so any future calls to |Connect| will create + // a new I/O object. + mIO->ShutdownOnConsumerThread(); + mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO)); + mIO = nullptr; + + NotifyDisconnect(); +} + +void +RilSocket::OnConnectSuccess() +{ + mConsumer->OnConnectSuccess(mIndex); +} + +void +RilSocket::OnConnectError() +{ + mConsumer->OnConnectError(mIndex); +} + +void +RilSocket::OnDisconnect() +{ + mConsumer->OnDisconnect(mIndex); +} + +} // namespace ipc +} // namespace mozilla diff --git a/ipc/ril/RilSocket.h b/ipc/ril/RilSocket.h new file mode 100644 index 0000000000..e1ca8f75cd --- /dev/null +++ b/ipc/ril/RilSocket.h @@ -0,0 +1,110 @@ +/* -*- 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/. */ + +#ifndef mozilla_ipc_RilSocket_h +#define mozilla_ipc_RilSocket_h + +#include "mozilla/ipc/ConnectionOrientedSocket.h" + +class JSContext; +class MessageLoop; + +namespace mozilla { +namespace dom { +namespace workers { + +class WorkerCrossThreadDispatcher; + +} // namespace workers +} // namespace dom +} // namespace mozilla + +namespace mozilla { +namespace ipc { + +class RilSocketConsumer; +class RilSocketIO; +class UnixSocketConnector; + +class RilSocket final : public ConnectionOrientedSocket +{ +public: + /** + * Constructs an instance of |RilSocket|. + * + * @param aDispatcher The dispatcher class for the received messages. + * @param aConsumer The consumer for the socket. + * @param aIndex An arbitrary index. + */ + RilSocket(mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher, + RilSocketConsumer* aConsumer, int aIndex); + + /** + * Method to be called whenever data is received. RIL-worker only. + * + * @param aCx The RIL worker's JS context. + * @param aBuffer Data received from the socket. + */ + void ReceiveSocketData(JSContext* aCx, nsAutoPtr& aBuffer); + + /** + * Starts a task on the socket that will try to connect to a socket in a + * non-blocking manner. + * + * @param aConnector Connector object for socket type specific functions + * @param aDelayMs Time delay in milliseconds. + * @param aConsumerLoop The socket's consumer thread. + * @param aIOLoop The socket's I/O thread. + * @return NS_OK on success, or an XPCOM error code otherwise. + */ + nsresult Connect(UnixSocketConnector* aConnector, int aDelayMs, + MessageLoop* aConsumerLoop, MessageLoop* aIOLoop); + + /** + * Starts a task on the socket that will try to connect to a socket in a + * non-blocking manner. + * + * @param aConnector Connector object for socket type specific functions + * @param aDelayMs Time delay in milliseconds. + * @return NS_OK on success, or an XPCOM error code otherwise. + */ + nsresult Connect(UnixSocketConnector* aConnector, int aDelayMs = 0); + + // Methods for |ConnectionOrientedSocket| + // + + nsresult PrepareAccept(UnixSocketConnector* aConnector, + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, + ConnectionOrientedSocketIO*& aIO) override; + + // Methods for |DataSocket| + // + + void SendSocketData(UnixSocketIOBuffer* aBuffer) override; + + // Methods for |SocketBase| + // + + void Close() override; + void OnConnectSuccess() override; + void OnConnectError() override; + void OnDisconnect() override; + +protected: + virtual ~RilSocket(); + +private: + RilSocketIO* mIO; + nsRefPtr mDispatcher; + RilSocketConsumer* mConsumer; + int mIndex; +}; + +} // namespace ipc +} // namepsace mozilla + +#endif // mozilla_ipc_RilSocket_h diff --git a/ipc/ril/RilSocketConsumer.cpp b/ipc/ril/RilSocketConsumer.cpp new file mode 100644 index 0000000000..a8a7418872 --- /dev/null +++ b/ipc/ril/RilSocketConsumer.cpp @@ -0,0 +1,20 @@ +/* -*- 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 "RilSocketConsumer.h" + +namespace mozilla { +namespace ipc { + +// +// RilSocketConsumer +// + +RilSocketConsumer::~RilSocketConsumer() +{ } + +} +} diff --git a/ipc/ril/RilSocketConsumer.h b/ipc/ril/RilSocketConsumer.h new file mode 100644 index 0000000000..510517b4ad --- /dev/null +++ b/ipc/ril/RilSocketConsumer.h @@ -0,0 +1,64 @@ +/* -*- 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/. */ + +#ifndef mozilla_ipc_RilSocketConsumer_h +#define mozilla_ipc_RilSocketConsumer_h + +#include "nsAutoPtr.h" + +class JSContext; + +namespace mozilla { +namespace ipc { + +class UnixSocketBuffer; + +/** + * |RilSocketConsumer| handles socket events and received data. + */ +class RilSocketConsumer +{ +public: + /** + * Method to be called whenever data is received. RIL-worker only. + * + * @param aCx The RIL worker's JS context. + * @param aIndex The index that has been given to the stream socket. + * @param aBuffer Data received from the socket. + */ + virtual void ReceiveSocketData(JSContext* aCx, + int aIndex, + nsAutoPtr& aBuffer) = 0; + + /** + * Callback for socket success. Consumer-thread only. + * + * @param aIndex The index that has been given to the stream socket. + */ + virtual void OnConnectSuccess(int aIndex) = 0; + + /** + * Callback for socket errors. Consumer-thread only. + * + * @param aIndex The index that has been given to the stream socket. + */ + virtual void OnConnectError(int aIndex) = 0; + + /** + * Callback for socket disconnect. Consumer-thread only. + * + * @param aIndex The index that has been given to the stream socket. + */ + virtual void OnDisconnect(int aIndex) = 0; + +protected: + virtual ~RilSocketConsumer(); +}; + +} +} + +#endif diff --git a/ipc/ril/moz.build b/ipc/ril/moz.build index 4088d65b69..be20a4acee 100644 --- a/ipc/ril/moz.build +++ b/ipc/ril/moz.build @@ -6,11 +6,15 @@ EXPORTS.mozilla.ipc += [ 'Ril.h', + 'RilSocket.h', + 'RilSocketConsumer.h' ] SOURCES += [ 'Ril.cpp', - 'RilConnector.cpp' + 'RilConnector.cpp', + 'RilSocket.cpp', + 'RilSocketConsumer.cpp' ] include('/ipc/chromium/chromium-config.mozbuild') diff --git a/ipc/unixsocket/ConnectionOrientedSocket.cpp b/ipc/unixsocket/ConnectionOrientedSocket.cpp index 915a1f1f38..983a33767f 100644 --- a/ipc/unixsocket/ConnectionOrientedSocket.cpp +++ b/ipc/unixsocket/ConnectionOrientedSocket.cpp @@ -5,15 +5,198 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ConnectionOrientedSocket.h" +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR +#include "UnixSocketConnector.h" namespace mozilla { namespace ipc { +// +// ConnectionOrientedSocketIO +// + +ConnectionOrientedSocketIO::ConnectionOrientedSocketIO( + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, + int aFd, ConnectionStatus aConnectionStatus, + UnixSocketConnector* aConnector) + : DataSocketIO(aConsumerLoop) + , UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus) + , mConnector(aConnector) + , mPeerAddressLength(0) +{ + MOZ_ASSERT(mConnector); + + MOZ_COUNT_CTOR_INHERITED(ConnectionOrientedSocketIO, DataSocketIO); +} + +ConnectionOrientedSocketIO::ConnectionOrientedSocketIO( + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, + UnixSocketConnector* aConnector) + : DataSocketIO(aConsumerLoop) + , UnixSocketWatcher(aIOLoop) + , mConnector(aConnector) + , mPeerAddressLength(0) +{ + MOZ_ASSERT(mConnector); + + MOZ_COUNT_CTOR_INHERITED(ConnectionOrientedSocketIO, DataSocketIO); +} + ConnectionOrientedSocketIO::~ConnectionOrientedSocketIO() -{ } +{ + MOZ_COUNT_DTOR_INHERITED(ConnectionOrientedSocketIO, DataSocketIO); +} + +nsresult +ConnectionOrientedSocketIO::Accept(int aFd, + const struct sockaddr* aPeerAddress, + socklen_t aPeerAddressLength) +{ + MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); + MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING); + + SetSocket(aFd, SOCKET_IS_CONNECTED); + + // Address setup + mPeerAddressLength = aPeerAddressLength; + memcpy(&mPeerAddress, aPeerAddress, mPeerAddressLength); + + // Signal success and start data transfer + OnConnected(); + + return NS_OK; +} + +nsresult +ConnectionOrientedSocketIO::Connect() +{ + MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); + MOZ_ASSERT(!IsOpen()); + + struct sockaddr* peerAddress = + reinterpret_cast(&mPeerAddress); + mPeerAddressLength = sizeof(mPeerAddress); + + int fd; + nsresult rv = mConnector->CreateStreamSocket(peerAddress, + &mPeerAddressLength, + fd); + if (NS_FAILED(rv)) { + // Tell the consumer thread we've errored + GetConsumerThread()->PostTask( + FROM_HERE, new SocketEventTask(this, SocketEventTask::CONNECT_ERROR)); + return NS_ERROR_FAILURE; + } + + SetFd(fd); + + // calls OnConnected() on success, or OnError() otherwise + rv = UnixSocketWatcher::Connect(peerAddress, mPeerAddressLength); + + if (NS_FAILED(rv)) { + return rv; + } + + return NS_OK; +} + +void +ConnectionOrientedSocketIO::Send(UnixSocketIOBuffer* aBuffer) +{ + MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); + + EnqueueData(aBuffer); + AddWatchers(WRITE_WATCHER, false); +} + +// |UnixSocketWatcher| + +void +ConnectionOrientedSocketIO::OnSocketCanReceiveWithoutBlocking() +{ + MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); + MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); // see bug 990984 + + ssize_t res = ReceiveData(GetFd()); + if (res < 0) { + /* I/O error */ + RemoveWatchers(READ_WATCHER|WRITE_WATCHER); + } else if (!res) { + /* EOF or peer shutdown */ + RemoveWatchers(READ_WATCHER); + } +} + +void +ConnectionOrientedSocketIO::OnSocketCanSendWithoutBlocking() +{ + MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); + MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); // see bug 990984 + MOZ_ASSERT(!IsShutdownOnIOThread()); + + nsresult rv = SendPendingData(GetFd()); + if (NS_FAILED(rv)) { + return; + } + + if (HasPendingData()) { + AddWatchers(WRITE_WATCHER, false); + } +} + +void +ConnectionOrientedSocketIO::OnConnected() +{ + MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); + MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); + + GetConsumerThread()->PostTask( + FROM_HERE, new SocketEventTask(this, SocketEventTask::CONNECT_SUCCESS)); + + AddWatchers(READ_WATCHER, true); + if (HasPendingData()) { + AddWatchers(WRITE_WATCHER, false); + } +} + +void +ConnectionOrientedSocketIO::OnListening() +{ + MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); + + NS_NOTREACHED("Invalid call to |ConnectionOrientedSocketIO::OnListening|"); +} + +void +ConnectionOrientedSocketIO::OnError(const char* aFunction, int aErrno) +{ + MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); + + UnixFdWatcher::OnError(aFunction, aErrno); + + // Clean up watchers, status, fd + Close(); + + // Tell the consumer thread we've errored + GetConsumerThread()->PostTask( + FROM_HERE, new SocketEventTask(this, SocketEventTask::CONNECT_ERROR)); +} + +// +// ConnectionOrientedSocket +// + +ConnectionOrientedSocket::ConnectionOrientedSocket() +{ + MOZ_COUNT_CTOR_INHERITED(ConnectionOrientedSocket, DataSocket); +} ConnectionOrientedSocket::~ConnectionOrientedSocket() -{ } +{ + MOZ_COUNT_DTOR_INHERITED(ConnectionOrientedSocket, DataSocket); +} } } diff --git a/ipc/unixsocket/ConnectionOrientedSocket.h b/ipc/unixsocket/ConnectionOrientedSocket.h index 291ecd8049..8493a2aa9a 100644 --- a/ipc/unixsocket/ConnectionOrientedSocket.h +++ b/ipc/unixsocket/ConnectionOrientedSocket.h @@ -4,11 +4,14 @@ * 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/. */ -#ifndef mozilla_ipc_connectionorientedsocket_h -#define mozilla_ipc_connectionorientedsocket_h +#ifndef mozilla_ipc_ConnectionOrientedSocket_h +#define mozilla_ipc_ConnectionOrientedSocket_h #include #include "DataSocket.h" +#include "mozilla/ipc/UnixSocketWatcher.h" + +class MessageLoop; namespace mozilla { namespace ipc { @@ -17,18 +20,76 @@ class UnixSocketConnector; /* * |ConnectionOrientedSocketIO| and |ConnectionOrientedSocket| define - * interfaces for implementing stream sockets on I/O and main thread. + * interfaces for implementing stream sockets on I/O and consumer thread. * |ListenSocket| uses these classes to handle accepted sockets. */ -class ConnectionOrientedSocketIO : public DataSocketIO +class ConnectionOrientedSocketIO + : public DataSocketIO + , public UnixSocketWatcher { public: virtual ~ConnectionOrientedSocketIO(); - virtual nsresult Accept(int aFd, - const struct sockaddr* aAddress, - socklen_t aAddressLength) = 0; + nsresult Accept(int aFd, + const struct sockaddr* aAddress, + socklen_t aAddressLength); + + nsresult Connect(); + + void Send(UnixSocketIOBuffer* aBuffer); + + // Methods for |UnixSocketWatcher| + // + + void OnSocketCanReceiveWithoutBlocking() final; + void OnSocketCanSendWithoutBlocking() final; + + void OnListening() final; + void OnConnected() final; + void OnError(const char* aFunction, int aErrno) final; + +protected: + /** + * Constructs an instance of |ConnectionOrientedSocketIO| + * + * @param aConsumerLoop The socket's consumer thread. + * @param aIOLoop The socket's I/O loop. + * @param aFd The socket file descriptor. + * @param aConnectionStatus The connection status for |aFd|. + * @param aConnector Connector object for socket-type-specific methods. + */ + ConnectionOrientedSocketIO(MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, + int aFd, ConnectionStatus aConnectionStatus, + UnixSocketConnector* aConnector); + + /** + * Constructs an instance of |ConnectionOrientedSocketIO| + * + * @param aConsumerLoop The socket's consumer thread. + * @param aIOLoop The socket's I/O loop. + * @param aConnector Connector object for socket-type-specific methods. + */ + ConnectionOrientedSocketIO(MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, + UnixSocketConnector* aConnector); + +private: + /** + * Connector object used to create the connection we are currently using. + */ + nsAutoPtr mConnector; + + /** + * Number of valid bytes in |mPeerAddress|. + */ + socklen_t mPeerAddressLength; + + /** + * Address of the socket's current peer. + */ + struct sockaddr_storage mPeerAddress; }; class ConnectionOrientedSocket : public DataSocket @@ -36,21 +97,26 @@ class ConnectionOrientedSocket : public DataSocket public: /** * Prepares an instance of |ConnectionOrientedSocket| in DISCONNECTED - * state for accepting a connection. Main-thread only. + * state for accepting a connection. Consumer-thread only. * * @param aConnector The new connector object, owned by the * connection-oriented socket. + * @param aConsumerLoop The socket's consumer thread. + * @param aIOLoop The socket's I/O thread. * @param[out] aIO, Returns an instance of |ConnectionOrientedSocketIO|. * @return NS_OK on success, or an XPCOM error code otherwise. */ virtual nsresult PrepareAccept(UnixSocketConnector* aConnector, + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, ConnectionOrientedSocketIO*& aIO) = 0; protected: + ConnectionOrientedSocket(); virtual ~ConnectionOrientedSocket(); }; } } -#endif +#endif // mozilla_ipc_ConnectionOrientedSocket diff --git a/ipc/unixsocket/DataSocket.cpp b/ipc/unixsocket/DataSocket.cpp index f153f8419c..f093d42bf6 100644 --- a/ipc/unixsocket/DataSocket.cpp +++ b/ipc/unixsocket/DataSocket.cpp @@ -6,7 +6,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "mozilla/ipc/DataSocket.h" +#include "DataSocket.h" +#ifdef MOZ_TASK_TRACER +#include "GeckoTaskTracer.h" +#endif +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR + +#ifdef MOZ_TASK_TRACER +using namespace mozilla::tasktracer; +#endif namespace mozilla { namespace ipc { @@ -16,7 +24,9 @@ namespace ipc { // DataSocketIO::~DataSocketIO() -{ } +{ + MOZ_COUNT_DTOR_INHERITED(DataSocketIO, SocketIOBase); +} void DataSocketIO::EnqueueData(UnixSocketIOBuffer* aBuffer) @@ -34,15 +44,93 @@ DataSocketIO::HasPendingData() const return !mOutgoingQ.IsEmpty(); } -DataSocketIO::DataSocketIO() -{ } +ssize_t +DataSocketIO::ReceiveData(int aFd) +{ + MOZ_ASSERT(aFd >= 0); + + UnixSocketIOBuffer* incoming; + nsresult rv = QueryReceiveBuffer(&incoming); + if (NS_FAILED(rv)) { + /* an error occured */ + GetConsumerThread()->PostTask(FROM_HERE, + new SocketRequestClosingTask(this)); + return -1; + } + + ssize_t res = incoming->Receive(aFd); + if (res < 0) { + /* an I/O error occured */ + DiscardBuffer(); + GetConsumerThread()->PostTask(FROM_HERE, + new SocketRequestClosingTask(this)); + return -1; + } else if (!res) { + /* EOF or peer shut down sending */ + DiscardBuffer(); + GetConsumerThread()->PostTask(FROM_HERE, + new SocketRequestClosingTask(this)); + return 0; + } + +#ifdef MOZ_TASK_TRACER + /* Make unix socket creation events to be the source events of TaskTracer, + * and originate the rest correlation tasks from here. + */ + AutoSourceEvent taskTracerEvent(SourceEventType::Unixsocket); +#endif + + ConsumeBuffer(); + + return res; +} + +nsresult +DataSocketIO::SendPendingData(int aFd) +{ + MOZ_ASSERT(aFd >= 0); + + while (HasPendingData()) { + UnixSocketIOBuffer* outgoing = mOutgoingQ.ElementAt(0); + + ssize_t res = outgoing->Send(aFd); + if (res < 0) { + /* an I/O error occured */ + GetConsumerThread()->PostTask(FROM_HERE, + new SocketRequestClosingTask(this)); + return NS_ERROR_FAILURE; + } else if (!res && outgoing->GetSize()) { + /* I/O is currently blocked; try again later */ + return NS_OK; + } + if (!outgoing->GetSize()) { + mOutgoingQ.RemoveElementAt(0); + delete outgoing; + } + } + + return NS_OK; +} + +DataSocketIO::DataSocketIO(MessageLoop* aConsumerLoop) + : SocketIOBase(aConsumerLoop) +{ + MOZ_COUNT_CTOR_INHERITED(DataSocketIO, SocketIOBase); +} // // DataSocket // +DataSocket::DataSocket() +{ + MOZ_COUNT_CTOR_INHERITED(DataSocket, SocketBase); +} + DataSocket::~DataSocket() -{ } +{ + MOZ_COUNT_DTOR_INHERITED(DataSocket, SocketBase); +} } } diff --git a/ipc/unixsocket/DataSocket.h b/ipc/unixsocket/DataSocket.h index 47fd34f889..7e17412421 100644 --- a/ipc/unixsocket/DataSocket.h +++ b/ipc/unixsocket/DataSocket.h @@ -10,6 +10,7 @@ #define mozilla_ipc_datasocket_h #include "mozilla/ipc/SocketBase.h" +#include "nsTArray.h" namespace mozilla { namespace ipc { @@ -35,6 +36,9 @@ public: * @param aBuffer Data to be sent to socket */ virtual void SendSocketData(UnixSocketIOBuffer* aBuffer) = 0; + +protected: + DataSocket(); }; // @@ -85,73 +89,12 @@ public: void EnqueueData(UnixSocketIOBuffer* aBuffer); bool HasPendingData() const; - template - ssize_t ReceiveData(int aFd, T* aIO) - { - MOZ_ASSERT(aFd >= 0); - MOZ_ASSERT(aIO); + ssize_t ReceiveData(int aFd); - UnixSocketIOBuffer* incoming; - nsresult rv = QueryReceiveBuffer(&incoming); - if (NS_FAILED(rv)) { - /* an error occured */ - NS_DispatchToMainThread(new SocketIORequestClosingRunnable(aIO)); - return -1; - } - - ssize_t res = incoming->Receive(aFd); - if (res < 0) { - /* an I/O error occured */ - DiscardBuffer(); - NS_DispatchToMainThread(new SocketIORequestClosingRunnable(aIO)); - return -1; - } else if (!res) { - /* EOF or peer shut down sending */ - DiscardBuffer(); - NS_DispatchToMainThread(new SocketIORequestClosingRunnable(aIO)); - return 0; - } - -#ifdef MOZ_TASK_TRACER - // Make unix socket creation events to be the source events of TaskTracer, - // and originate the rest correlation tasks from here. - AutoSourceEvent taskTracerEvent(SourceEventType::Unixsocket); -#endif - - ConsumeBuffer(); - - return res; - } - - template - nsresult SendPendingData(int aFd, T* aIO) - { - MOZ_ASSERT(aFd >= 0); - MOZ_ASSERT(aIO); - - while (HasPendingData()) { - UnixSocketIOBuffer* outgoing = mOutgoingQ.ElementAt(0); - - ssize_t res = outgoing->Send(aFd); - if (res < 0) { - /* an I/O error occured */ - NS_DispatchToMainThread(new SocketIORequestClosingRunnable(aIO)); - return NS_ERROR_FAILURE; - } else if (!res && outgoing->GetSize()) { - /* I/O is currently blocked; try again later */ - return NS_OK; - } - if (!outgoing->GetSize()) { - mOutgoingQ.RemoveElementAt(0); - delete outgoing; - } - } - - return NS_OK; - } + nsresult SendPendingData(int aFd); protected: - DataSocketIO(); + DataSocketIO(MessageLoop* aConsumerLoop); private: /** @@ -181,10 +124,10 @@ public: void Run() override { - MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!SocketIOTask::IsCanceled()); Tio* io = SocketIOTask::GetIO(); + MOZ_ASSERT(!io->IsConsumerThread()); MOZ_ASSERT(!io->IsShutdownOnIOThread()); io->Send(mData); diff --git a/ipc/unixsocket/ListenSocket.cpp b/ipc/unixsocket/ListenSocket.cpp index 13e223fcec..79b23848fe 100644 --- a/ipc/unixsocket/ListenSocket.cpp +++ b/ipc/unixsocket/ListenSocket.cpp @@ -10,6 +10,7 @@ #include "DataSocket.h" #include "ListenSocketConsumer.h" #include "mozilla/RefPtr.h" +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR #include "nsXULAppAPI.h" #include "UnixSocketConnector.h" @@ -27,7 +28,8 @@ class ListenSocketIO final public: class ListenTask; - ListenSocketIO(MessageLoop* mIOLoop, + ListenSocketIO(MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, ListenSocket* aListenSocket, UnixSocketConnector* aConnector); ~ListenSocketIO(); @@ -55,21 +57,21 @@ public: SocketBase* GetSocketBase() override; - bool IsShutdownOnMainThread() const override; + bool IsShutdownOnConsumerThread() const override; bool IsShutdownOnIOThread() const override; - void ShutdownOnMainThread() override; + void ShutdownOnConsumerThread() override; void ShutdownOnIOThread() override; private: void FireSocketError(); /** - * Consumer pointer. Non-thread safe RefPtr, so should only be manipulated - * directly from main thread. All non-main-thread accesses should happen with - * mIO as container. + * Consumer pointer. Non-thread-safe pointer, so should only be manipulated + * directly from consumer thread. All non-consumer-thread accesses should + * happen with mIO as container. */ - RefPtr mListenSocket; + ListenSocket* mListenSocket; /** * Connector object used to create the connection we are currently using. @@ -94,11 +96,12 @@ private: ConnectionOrientedSocketIO* mCOSocketIO; }; -ListenSocketIO::ListenSocketIO(MessageLoop* mIOLoop, +ListenSocketIO::ListenSocketIO(MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, ListenSocket* aListenSocket, UnixSocketConnector* aConnector) - : UnixSocketWatcher(mIOLoop) - , SocketIOBase() + : UnixSocketWatcher(aIOLoop) + , SocketIOBase(aConsumerLoop) , mListenSocket(aListenSocket) , mConnector(aConnector) , mShuttingDownOnIOThread(false) @@ -107,12 +110,16 @@ ListenSocketIO::ListenSocketIO(MessageLoop* mIOLoop, { MOZ_ASSERT(mListenSocket); MOZ_ASSERT(mConnector); + + MOZ_COUNT_CTOR_INHERITED(ListenSocketIO, SocketIOBase); } ListenSocketIO::~ListenSocketIO() { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(IsShutdownOnMainThread()); + MOZ_ASSERT(IsConsumerThread()); + MOZ_ASSERT(IsShutdownOnConsumerThread()); + + MOZ_COUNT_DTOR_INHERITED(ListenSocketIO, SocketIOBase); } UnixSocketConnector* @@ -166,8 +173,8 @@ ListenSocketIO::OnListening() AddWatchers(READ_WATCHER, true); /* We signal a successful 'connection' to a local address for listening. */ - NS_DispatchToMainThread( - new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS)); + GetConsumerThread()->PostTask( + FROM_HERE, new SocketEventTask(this, SocketEventTask::CONNECT_SUCCESS)); } void @@ -187,9 +194,9 @@ ListenSocketIO::FireSocketError() // Clean up watchers, statuses, fds Close(); - // Tell the main thread we've errored - NS_DispatchToMainThread( - new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR)); + // Tell the consumer thread we've errored + GetConsumerThread()->PostTask( + FROM_HERE, new SocketEventTask(this, SocketEventTask::CONNECT_ERROR)); } void @@ -224,13 +231,13 @@ ListenSocketIO::OnSocketCanAcceptWithoutBlocking() SocketBase* ListenSocketIO::GetSocketBase() { - return mListenSocket.get(); + return mListenSocket; } bool -ListenSocketIO::IsShutdownOnMainThread() const +ListenSocketIO::IsShutdownOnConsumerThread() const { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(IsConsumerThread()); return mListenSocket == nullptr; } @@ -242,10 +249,10 @@ ListenSocketIO::IsShutdownOnIOThread() const } void -ListenSocketIO::ShutdownOnMainThread() +ListenSocketIO::ShutdownOnConsumerThread() { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!IsShutdownOnMainThread()); + MOZ_ASSERT(IsConsumerThread()); + MOZ_ASSERT(!IsShutdownOnConsumerThread()); mListenSocket = nullptr; } @@ -253,7 +260,7 @@ ListenSocketIO::ShutdownOnMainThread() void ListenSocketIO::ShutdownOnIOThread() { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!IsConsumerThread()); MOZ_ASSERT(!mShuttingDownOnIOThread); Close(); // will also remove fd from I/O loop @@ -264,20 +271,26 @@ ListenSocketIO::ShutdownOnIOThread() // Socket tasks // -class ListenSocketIO::ListenTask final - : public SocketIOTask +class ListenSocketIO::ListenTask final : public SocketIOTask { public: ListenTask(ListenSocketIO* aIO, ConnectionOrientedSocketIO* aCOSocketIO) - : SocketIOTask(aIO) - , mCOSocketIO(aCOSocketIO) + : SocketIOTask(aIO) + , mCOSocketIO(aCOSocketIO) { MOZ_ASSERT(mCOSocketIO); + + MOZ_COUNT_CTOR(ListenTask); + } + + ~ListenTask() + { + MOZ_COUNT_DTOR(ListenTask); } void Run() override { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!GetIO()->IsConsumerThread()); if (!IsCanceled()) { GetIO()->Listen(mCOSocketIO); @@ -289,30 +302,35 @@ private: }; // -// UnixSocketConsumer +// ListenSocket // ListenSocket::ListenSocket(ListenSocketConsumer* aConsumer, int aIndex) - : mConsumer(aConsumer) + : mIO(nullptr) + , mConsumer(aConsumer) , mIndex(aIndex) - , mIO(nullptr) { MOZ_ASSERT(mConsumer); + + MOZ_COUNT_CTOR_INHERITED(ListenSocket, SocketBase); } ListenSocket::~ListenSocket() { MOZ_ASSERT(!mIO); + + MOZ_COUNT_DTOR_INHERITED(ListenSocket, SocketBase); } nsresult ListenSocket::Listen(UnixSocketConnector* aConnector, + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, ConnectionOrientedSocket* aCOSocket) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!mIO); - mIO = new ListenSocketIO(XRE_GetIOMessageLoop(), this, aConnector); + mIO = new ListenSocketIO(aConsumerLoop, aIOLoop, this, aConnector); // Prepared I/O object, now start listening. nsresult rv = Listen(aCOSocket); @@ -325,10 +343,17 @@ ListenSocket::Listen(UnixSocketConnector* aConnector, return NS_OK; } +nsresult +ListenSocket::Listen(UnixSocketConnector* aConnector, + ConnectionOrientedSocket* aCOSocket) +{ + return Listen(aConnector, MessageLoop::current(), XRE_GetIOMessageLoop(), + aCOSocket); +} + nsresult ListenSocket::Listen(ConnectionOrientedSocket* aCOSocket) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aCOSocket); MOZ_ASSERT(mIO); @@ -342,7 +367,9 @@ ListenSocket::Listen(ConnectionOrientedSocket* aCOSocket) } nsAutoPtr io; - rv = aCOSocket->PrepareAccept(connector, *io.StartAssignment()); + rv = aCOSocket->PrepareAccept(connector, + mIO->GetConsumerThread(), mIO->GetIOLoop(), + *io.StartAssignment()); if (NS_FAILED(rv)) { return rv; } @@ -352,7 +379,7 @@ ListenSocket::Listen(ConnectionOrientedSocket* aCOSocket) SetConnectionStatus(SOCKET_LISTENING); - XRE_GetIOMessageLoop()->PostTask( + mIO->GetIOLoop()->PostTask( FROM_HERE, new ListenSocketIO::ListenTask(mIO, io.forget())); return NS_OK; @@ -363,19 +390,17 @@ ListenSocket::Listen(ConnectionOrientedSocket* aCOSocket) void ListenSocket::Close() { - MOZ_ASSERT(NS_IsMainThread()); - if (!mIO) { return; } + MOZ_ASSERT(mIO->IsConsumerThread()); + // From this point on, we consider mIO as being deleted. We sever // the relationship here so any future calls to listen or connect // will create a new implementation. - mIO->ShutdownOnMainThread(); - - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO)); - + mIO->ShutdownOnConsumerThread(); + mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO)); mIO = nullptr; NotifyDisconnect(); @@ -384,24 +409,18 @@ ListenSocket::Close() void ListenSocket::OnConnectSuccess() { - MOZ_ASSERT(NS_IsMainThread()); - mConsumer->OnConnectSuccess(mIndex); } void ListenSocket::OnConnectError() { - MOZ_ASSERT(NS_IsMainThread()); - mConsumer->OnConnectError(mIndex); } void ListenSocket::OnDisconnect() { - MOZ_ASSERT(NS_IsMainThread()); - mConsumer->OnDisconnect(mIndex); } diff --git a/ipc/unixsocket/ListenSocket.h b/ipc/unixsocket/ListenSocket.h index b4b5cd2a9d..9bde4602d2 100644 --- a/ipc/unixsocket/ListenSocket.h +++ b/ipc/unixsocket/ListenSocket.h @@ -4,11 +4,13 @@ * 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/. */ -#ifndef mozilla_ipc_listensocket_h -#define mozilla_ipc_listensocket_h +#ifndef mozilla_ipc_ListenSocket_h +#define mozilla_ipc_ListenSocket_h -#include "nsString.h" #include "mozilla/ipc/SocketBase.h" +#include "nsString.h" + +class MessageLoop; namespace mozilla { namespace ipc { @@ -20,12 +22,31 @@ class UnixSocketConnector; class ListenSocket final : public SocketBase { -protected: - virtual ~ListenSocket(); - public: + /** + * Constructs an instance of |ListenSocket|. + * + * @param aConsumer The consumer for the socket. + * @param aIndex An arbitrary index. + */ ListenSocket(ListenSocketConsumer* aConsumer, int aIndex); + /** + * Starts a task on the socket that will try to accept a new connection + * in a non-blocking manner. + * + * @param aConnector Connector object for socket-type-specific functions + * @param aConsumerLoop The socket's consumer thread. + * @param aIOLoop The socket's I/O thread. + * @param aCOSocket The connection-oriented socket for handling the + * accepted connection. + * @return NS_OK on success, or an XPCOM error code otherwise. + */ + nsresult Listen(UnixSocketConnector* aConnector, + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, + ConnectionOrientedSocket* aCOSocket); + /** * Starts a task on the socket that will try to accept a new connection * in a non-blocking manner. @@ -57,13 +78,16 @@ public: void OnConnectError() override; void OnDisconnect() override; +protected: + virtual ~ListenSocket(); + private: + ListenSocketIO* mIO; ListenSocketConsumer* mConsumer; int mIndex; - ListenSocketIO* mIO; }; } // namespace ipc } // namepsace mozilla -#endif // mozilla_ipc_listensocket_h +#endif // mozilla_ipc_ListenSocket_h diff --git a/ipc/unixsocket/ListenSocketConsumer.cpp b/ipc/unixsocket/ListenSocketConsumer.cpp new file mode 100644 index 0000000000..f4de0c42e3 --- /dev/null +++ b/ipc/unixsocket/ListenSocketConsumer.cpp @@ -0,0 +1,20 @@ +/* -*- 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 "ListenSocketConsumer.h" + +namespace mozilla { +namespace ipc { + +// +// ListenSocketConsumer +// + +ListenSocketConsumer::~ListenSocketConsumer() +{ } + +} +} diff --git a/ipc/unixsocket/ListenSocketConsumer.h b/ipc/unixsocket/ListenSocketConsumer.h new file mode 100644 index 0000000000..8c9af3019b --- /dev/null +++ b/ipc/unixsocket/ListenSocketConsumer.h @@ -0,0 +1,46 @@ +/* -*- 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/. */ + +#ifndef mozilla_ipc_listensocketconsumer_h +#define mozilla_ipc_listensocketconsumer_h + +namespace mozilla { +namespace ipc { + +/** + * |ListenSocketConsumer| handles socket events. + */ +class ListenSocketConsumer +{ +public: + virtual ~ListenSocketConsumer(); + + /** + * Callback for socket success. Consumer-thread only. + * + * @param aIndex The index that has been given to the listening socket. + */ + virtual void OnConnectSuccess(int aIndex) = 0; + + /** + * Callback for socket errors. Consumer-thread only. + * + * @param aIndex The index that has been given to the listening socket. + */ + virtual void OnConnectError(int aIndex) = 0; + + /** + * Callback for socket disconnect. Consumer-thread only. + * + * @param aIndex The index that has been given to the listeing socket. + */ + virtual void OnDisconnect(int aIndex) = 0; +}; + +} +} + +#endif diff --git a/ipc/unixsocket/SocketBase.cpp b/ipc/unixsocket/SocketBase.cpp index 491c463850..d06539f446 100644 --- a/ipc/unixsocket/SocketBase.cpp +++ b/ipc/unixsocket/SocketBase.cpp @@ -10,6 +10,7 @@ #include #include #include +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR namespace mozilla { namespace ipc { @@ -18,27 +19,22 @@ namespace ipc { // UnixSocketIOBuffer // -UnixSocketBuffer::UnixSocketBuffer(const void* aData, size_t aSize) - : mSize(aSize) - , mOffset(0) - , mAvailableSpace(aSize) -{ - MOZ_ASSERT(aData || !mSize); - - mData = new uint8_t[mAvailableSpace]; - memcpy(mData, aData, mSize); -} - -UnixSocketBuffer::UnixSocketBuffer(size_t aAvailableSpace) +UnixSocketBuffer::UnixSocketBuffer() : mSize(0) , mOffset(0) - , mAvailableSpace(aAvailableSpace) + , mAvailableSpace(0) + , mData(nullptr) { - mData = new uint8_t[mAvailableSpace]; + MOZ_COUNT_CTOR(UnixSocketBuffer); } UnixSocketBuffer::~UnixSocketBuffer() -{ } +{ + MOZ_COUNT_DTOR(UnixSocketBuffer); + + // Make sure that the caller released the buffer's memory. + MOZ_ASSERT(!GetBuffer()); +} const uint8_t* UnixSocketBuffer::Consume(size_t aLen) @@ -105,28 +101,44 @@ UnixSocketBuffer::CleanupLeadingSpace() // UnixSocketIOBuffer // -UnixSocketIOBuffer::UnixSocketIOBuffer(const void* aData, size_t aSize) - : UnixSocketBuffer(aData, aSize) -{ } - -UnixSocketIOBuffer::UnixSocketIOBuffer(size_t aAvailableSpace) - : UnixSocketBuffer(aAvailableSpace) -{ } +UnixSocketIOBuffer::UnixSocketIOBuffer() +{ + MOZ_COUNT_CTOR_INHERITED(UnixSocketIOBuffer, UnixSocketBuffer); +} UnixSocketIOBuffer::~UnixSocketIOBuffer() -{ } +{ + MOZ_COUNT_DTOR_INHERITED(UnixSocketIOBuffer, UnixSocketBuffer); +} // // UnixSocketRawData // UnixSocketRawData::UnixSocketRawData(const void* aData, size_t aSize) -: UnixSocketIOBuffer(aData, aSize) -{ } +{ + MOZ_ASSERT(aData || !aSize); + + MOZ_COUNT_CTOR_INHERITED(UnixSocketRawData, UnixSocketIOBuffer); + + ResetBuffer(static_cast(memcpy(new uint8_t[aSize], aData, aSize)), + 0, aSize, aSize); +} UnixSocketRawData::UnixSocketRawData(size_t aSize) -: UnixSocketIOBuffer(aSize) -{ } +{ + MOZ_COUNT_CTOR_INHERITED(UnixSocketRawData, UnixSocketIOBuffer); + + ResetBuffer(new uint8_t[aSize], 0, 0, aSize); +} + +UnixSocketRawData::~UnixSocketRawData() +{ + MOZ_COUNT_DTOR_INHERITED(UnixSocketRawData, UnixSocketIOBuffer); + + nsAutoArrayPtr data(GetBuffer()); + ResetBuffer(nullptr, 0, 0, 0); +} ssize_t UnixSocketRawData::Receive(int aFd) @@ -186,24 +198,18 @@ UnixSocketRawData::Send(int aFd) SocketConnectionStatus SocketBase::GetConnectionStatus() const { - MOZ_ASSERT(NS_IsMainThread()); - return mConnectionStatus; } int SocketBase::GetSuggestedConnectDelayMs() const { - MOZ_ASSERT(NS_IsMainThread()); - return mConnectDelayMs; } void SocketBase::NotifySuccess() { - MOZ_ASSERT(NS_IsMainThread()); - mConnectionStatus = SOCKET_CONNECTED; mConnectTimestamp = PR_IntervalNow(); OnConnectSuccess(); @@ -212,8 +218,6 @@ SocketBase::NotifySuccess() void SocketBase::NotifyError() { - MOZ_ASSERT(NS_IsMainThread()); - mConnectionStatus = SOCKET_DISCONNECTED; mConnectDelayMs = CalculateConnectDelayMs(); mConnectTimestamp = 0; @@ -223,8 +227,6 @@ SocketBase::NotifyError() void SocketBase::NotifyDisconnect() { - MOZ_ASSERT(NS_IsMainThread()); - mConnectionStatus = SOCKET_DISCONNECTED; mConnectDelayMs = CalculateConnectDelayMs(); mConnectTimestamp = 0; @@ -234,8 +236,6 @@ SocketBase::NotifyDisconnect() uint32_t SocketBase::CalculateConnectDelayMs() const { - MOZ_ASSERT(NS_IsMainThread()); - uint32_t connectDelayMs = mConnectDelayMs; if (mConnectTimestamp && (PR_IntervalNow()-mConnectTimestamp) > connectDelayMs) { @@ -255,11 +255,15 @@ SocketBase::SocketBase() : mConnectionStatus(SOCKET_DISCONNECTED) , mConnectTimestamp(0) , mConnectDelayMs(0) -{ } +{ + MOZ_COUNT_CTOR(SocketBase); +} SocketBase::~SocketBase() { MOZ_ASSERT(mConnectionStatus == SOCKET_DISCONNECTED); + + MOZ_COUNT_DTOR(SocketBase); } void @@ -272,33 +276,58 @@ SocketBase::SetConnectionStatus(SocketConnectionStatus aConnectionStatus) // SocketIOBase // -SocketIOBase::SocketIOBase() -{ } +SocketIOBase::SocketIOBase(MessageLoop* aConsumerLoop) + : mConsumerLoop(aConsumerLoop) +{ + MOZ_ASSERT(mConsumerLoop); + + MOZ_COUNT_CTOR(SocketIOBase); +} SocketIOBase::~SocketIOBase() -{ } - -// -// SocketIOEventRunnable -// - -SocketIOEventRunnable::SocketIOEventRunnable(SocketIOBase* aIO, - SocketEvent aEvent) - : SocketIORunnable(aIO) - , mEvent(aEvent) -{ } - -NS_METHOD -SocketIOEventRunnable::Run() { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_COUNT_DTOR(SocketIOBase); +} - SocketIOBase* io = SocketIORunnable::GetIO(); +MessageLoop* +SocketIOBase::GetConsumerThread() const +{ + return mConsumerLoop; +} - if (NS_WARN_IF(io->IsShutdownOnMainThread())) { +bool +SocketIOBase::IsConsumerThread() const +{ + return GetConsumerThread() == MessageLoop::current(); +} + +// +// SocketEventTask +// + +SocketEventTask::SocketEventTask(SocketIOBase* aIO, SocketEvent aEvent) + : SocketTask(aIO) + , mEvent(aEvent) +{ + MOZ_COUNT_CTOR(SocketEventTask); +} + +SocketEventTask::~SocketEventTask() +{ + MOZ_COUNT_DTOR(SocketEventTask); +} + +void +SocketEventTask::Run() +{ + SocketIOBase* io = SocketTask::GetIO(); + + MOZ_ASSERT(io->IsConsumerThread()); + + if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) { // Since we've already explicitly closed and the close // happened before this, this isn't really an error. - return NS_OK; + return; } SocketBase* socketBase = io->GetSocketBase(); @@ -311,55 +340,61 @@ SocketIOEventRunnable::Run() } else if (mEvent == DISCONNECT) { socketBase->NotifyDisconnect(); } - - return NS_OK; } // -// SocketIORequestClosingRunnable +// SocketRequestClosingTask // -SocketIORequestClosingRunnable::SocketIORequestClosingRunnable( - SocketIOBase* aIO) - : SocketIORunnable(aIO) -{ } - -NS_METHOD -SocketIORequestClosingRunnable::Run() +SocketRequestClosingTask::SocketRequestClosingTask(SocketIOBase* aIO) + : SocketTask(aIO) { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_COUNT_CTOR(SocketRequestClosingTask); +} - SocketIOBase* io = SocketIORunnable::GetIO(); +SocketRequestClosingTask::~SocketRequestClosingTask() +{ + MOZ_COUNT_DTOR(SocketRequestClosingTask); +} - if (NS_WARN_IF(io->IsShutdownOnMainThread())) { +void +SocketRequestClosingTask::Run() +{ + SocketIOBase* io = SocketTask::GetIO(); + + MOZ_ASSERT(io->IsConsumerThread()); + + if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) { // Since we've already explicitly closed and the close // happened before this, this isn't really an error. - return NS_OK; + return; } SocketBase* socketBase = io->GetSocketBase(); MOZ_ASSERT(socketBase); socketBase->Close(); - - return NS_OK; } // -// SocketIODeleteInstanceRunnable +// SocketDeleteInstanceTask // -SocketIODeleteInstanceRunnable::SocketIODeleteInstanceRunnable( - SocketIOBase* aIO) +SocketDeleteInstanceTask::SocketDeleteInstanceTask(SocketIOBase* aIO) : mIO(aIO) -{ } +{ + MOZ_COUNT_CTOR(SocketDeleteInstanceTask); +} -NS_METHOD -SocketIODeleteInstanceRunnable::Run() +SocketDeleteInstanceTask::~SocketDeleteInstanceTask() +{ + MOZ_COUNT_DTOR(SocketDeleteInstanceTask); +} + +void +SocketDeleteInstanceTask::Run() { mIO = nullptr; // delete instance - - return NS_OK; } // @@ -368,24 +403,31 @@ SocketIODeleteInstanceRunnable::Run() SocketIOShutdownTask::SocketIOShutdownTask(SocketIOBase* aIO) : SocketIOTask(aIO) -{ } +{ + MOZ_COUNT_CTOR(SocketIOShutdownTask); +} + +SocketIOShutdownTask::~SocketIOShutdownTask() +{ + MOZ_COUNT_DTOR(SocketIOShutdownTask); +} void SocketIOShutdownTask::Run() { - MOZ_ASSERT(!NS_IsMainThread()); - SocketIOBase* io = SocketIOTask::GetIO(); + MOZ_ASSERT(!io->IsConsumerThread()); + MOZ_ASSERT(!io->IsShutdownOnIOThread()); + // At this point, there should be no new events on the I/O thread // after this one with the possible exception of an accept task, // which ShutdownOnIOThread will cancel for us. We are now fully - // shut down, so we can send a message to the main thread to delete - // |io| safely knowing that it's not reference any longer. - MOZ_ASSERT(!io->IsShutdownOnIOThread()); + // shut down, so we can send a message to the consumer thread to + // delete |io| safely knowing that it's not reference any longer. io->ShutdownOnIOThread(); - - NS_DispatchToMainThread(new SocketIODeleteInstanceRunnable(io)); + io->GetConsumerThread()->PostTask(FROM_HERE, + new SocketDeleteInstanceTask(io)); } } diff --git a/ipc/unixsocket/SocketBase.h b/ipc/unixsocket/SocketBase.h index 8b917b3514..ba3c909792 100644 --- a/ipc/unixsocket/SocketBase.h +++ b/ipc/unixsocket/SocketBase.h @@ -11,13 +11,6 @@ #include "base/message_loop.h" #include "nsAutoPtr.h" -#include "nsTArray.h" -#include "nsThreadUtils.h" - -#ifdef MOZ_TASK_TRACER -#include "GeckoTaskTracer.h" -using namespace mozilla::tasktracer; -#endif namespace mozilla { namespace ipc { @@ -114,15 +107,38 @@ public: } protected: + UnixSocketBuffer(); - /* This constructor copies aData of aSize bytes length into the - * new instance of |UnixSocketBuffer|. + /** + * Sets the raw memory. The caller is responsible for freeing + * this memory. + * + * @param aData A pointer to the buffer's raw memory. + * @param aOffset The start of valid bytes in |aData|. + * @param aSize The number of valid bytes in |aData|. + * @param aAvailableSpace The number of bytes in |aData|. */ - UnixSocketBuffer(const void* aData, size_t aSize); + void ResetBuffer(uint8_t* aData, + size_t aOffset, size_t aSize, size_t aAvailableSpace) + { + MOZ_ASSERT(aData || !aAvailableSpace); + MOZ_ASSERT((aOffset + aSize) <= aAvailableSpace); - /* This constructor reserves aAvailableSpace bytes of space. + mOffset = aOffset; + mSize = aSize; + mAvailableSpace = aAvailableSpace; + mData = aData; + } + + /** + * Retrieves the memory buffer. + * + * @return A pointer to the buffer's raw memory. */ - UnixSocketBuffer(size_t aAvailableSpace); + uint8_t* GetBuffer() + { + return mData; + } size_t GetLeadingSpace() const { @@ -165,7 +181,7 @@ private: size_t mSize; size_t mOffset; size_t mAvailableSpace; - nsAutoArrayPtr mData; + uint8_t* mData; }; // @@ -181,6 +197,7 @@ private: class UnixSocketIOBuffer : public UnixSocketBuffer { public: + UnixSocketIOBuffer(); virtual ~UnixSocketIOBuffer(); /** @@ -195,17 +212,6 @@ public: * is the number of bytes written, or a negative value on error. */ virtual ssize_t Send(int aFd) = 0; - -protected: - - /* This constructor copies aData of aSize bytes length into the - * new instance of |UnixSocketIOBuffer|. - */ - UnixSocketIOBuffer(const void* aData, size_t aSize); - - /* This constructor reserves aAvailableSpace bytes of space. - */ - UnixSocketIOBuffer(size_t aAvailableSpace); }; // @@ -215,16 +221,28 @@ protected: class UnixSocketRawData final : public UnixSocketIOBuffer { public: - /* This constructor copies aData of aSize bytes length into the + /** + * This constructor copies aData of aSize bytes length into the * new instance of |UnixSocketRawData|. + * + * @param aData The buffer to copy. + * @param aSize The number of bytes in |aData|. */ UnixSocketRawData(const void* aData, size_t aSize); - /* This constructor reserves aSize bytes of space. Currently + /** + * This constructor reserves aSize bytes of space. Currently * it's only possible to fill this buffer by calling |Receive|. + * + * @param aSize The number of bytes to allocate. */ UnixSocketRawData(size_t aSize); + /** + * The destructor releases the buffer's raw memory. + */ + ~UnixSocketRawData(); + /** * Receives data from aFd at the end of the buffer. The returned value * is the number of newly received bytes, or 0 if the peer shut down @@ -261,23 +279,23 @@ public: /** * Queues the internal representation of socket for deletion. Can be called - * from main thread. + * from consumer thread. */ virtual void Close() = 0; /** * Callback for socket connect/accept success. Called after connect/accept has - * finished. Will be run on main thread, before any reads take place. + * finished. Will be run on consumer thread before any reads take place. */ virtual void OnConnectSuccess() = 0; /** - * Callback for socket connect/accept error. Will be run on main thread. + * Callback for socket connect/accept error. Will be run on consumer thread. */ virtual void OnConnectError() = 0; /** - * Callback for socket disconnect. Will be run on main thread. + * Callback for socket disconnect. Will be run on consumer thread. */ virtual void OnDisconnect() = 0; @@ -345,7 +363,7 @@ public: * * @return True if the socket class has been shut down, false otherwise. */ - virtual bool IsShutdownOnMainThread() const = 0; + virtual bool IsShutdownOnConsumerThread() const = 0; /** * Signals to the socket I/O classes that it has been shut down. @@ -356,24 +374,40 @@ public: * Signals to the socket I/O classes that the socket class has been * shut down. */ - virtual void ShutdownOnMainThread() = 0; + virtual void ShutdownOnConsumerThread() = 0; + + /** + * Returns the consumer thread. + * + * @return A pointer to the consumer thread. + */ + MessageLoop* GetConsumerThread() const; + + /** + * @return True if the current thread is the consumer thread, or false + * otherwise. + */ + bool IsConsumerThread() const; protected: - SocketIOBase(); + SocketIOBase(MessageLoop* aConsumerLoop); + +private: + MessageLoop* mConsumerLoop; }; // -// Socket I/O runnables +// Socket tasks // -/* |SocketIORunnable| is a runnable for sending a message from - * the I/O thread to the main thread. +/* |SocketTask| is a task for sending a message from + * the I/O thread to the consumer thread. */ template -class SocketIORunnable : public nsRunnable +class SocketTask : public Task { public: - virtual ~SocketIORunnable() + virtual ~SocketTask() { } T* GetIO() const @@ -382,8 +416,8 @@ public: } protected: - SocketIORunnable(T* aIO) - : mIO(aIO) + SocketTask(T* aIO) + : mIO(aIO) { MOZ_ASSERT(aIO); } @@ -393,10 +427,10 @@ private: }; /** - * |SocketIOEventRunnable| reports the connection state on the - * I/O thread back to the main thread. + * |SocketEventTask| reports the connection state on the + * I/O thread back to the consumer thread. */ -class SocketIOEventRunnable final : public SocketIORunnable +class SocketEventTask final : public SocketTask { public: enum SocketEvent { @@ -405,36 +439,38 @@ public: DISCONNECT }; - SocketIOEventRunnable(SocketIOBase* aIO, SocketEvent aEvent); + SocketEventTask(SocketIOBase* aIO, SocketEvent aEvent); + ~SocketEventTask(); - NS_IMETHOD Run() override; + void Run() override; private: SocketEvent mEvent; }; /** - * |SocketIORequestClosingRunnable| closes an instance of |SocketBase| - * to the main thread. + * |SocketRequestClosingTask| closes an instance of |SocketBase| + * on the consumer thread. */ -class SocketIORequestClosingRunnable final - : public SocketIORunnable +class SocketRequestClosingTask final : public SocketTask { public: - SocketIORequestClosingRunnable(SocketIOBase* aIO); + SocketRequestClosingTask(SocketIOBase* aIO); + ~SocketRequestClosingTask(); - NS_IMETHOD Run() override; + void Run() override; }; /** - * |SocketIODeleteInstanceRunnable| deletes an object on the main thread. + * |SocketDeleteInstanceTask| deletes an object on the consumer thread. */ -class SocketIODeleteInstanceRunnable final : public nsRunnable +class SocketDeleteInstanceTask final : public Task { public: - SocketIODeleteInstanceRunnable(SocketIOBase* aIO); + SocketDeleteInstanceTask(SocketIOBase* aIO); + ~SocketDeleteInstanceTask(); - NS_IMETHOD Run() override; + void Run() override; private: nsAutoPtr mIO; @@ -482,12 +518,13 @@ private: /** * |SocketIOShutdownTask| signals shutdown to the socket I/O class on - * the I/O thread and sends it to the main thread for destruction. + * the I/O thread and sends it to the consumer thread for destruction. */ class SocketIOShutdownTask final : public SocketIOTask { public: SocketIOShutdownTask(SocketIOBase* aIO); + ~SocketIOShutdownTask(); void Run() override; }; diff --git a/ipc/unixsocket/StreamSocket.cpp b/ipc/unixsocket/StreamSocket.cpp index c0b02e128c..be274a2ac4 100644 --- a/ipc/unixsocket/StreamSocket.cpp +++ b/ipc/unixsocket/StreamSocket.cpp @@ -7,6 +7,7 @@ #include "StreamSocket.h" #include #include "mozilla/RefPtr.h" +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR #include "nsXULAppAPI.h" #include "StreamSocketConsumer.h" #include "UnixSocketConnector.h" @@ -20,20 +21,20 @@ namespace ipc { // StreamSocketIO // -class StreamSocketIO final - : public UnixSocketWatcher - , public ConnectionOrientedSocketIO +class StreamSocketIO final : public ConnectionOrientedSocketIO { public: class ConnectTask; class DelayedConnectTask; - class ReceiveRunnable; + class ReceiveTask; - StreamSocketIO(MessageLoop* mIOLoop, + StreamSocketIO(MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, StreamSocket* aStreamSocket, UnixSocketConnector* aConnector); - StreamSocketIO(MessageLoop* mIOLoop, int aFd, - ConnectionStatus aConnectionStatus, + StreamSocketIO(MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, + int aFd, ConnectionStatus aConnectionStatus, StreamSocket* aStreamSocket, UnixSocketConnector* aConnector); ~StreamSocketIO(); @@ -48,32 +49,6 @@ public: void ClearDelayedConnectTask(); void CancelDelayedConnectTask(); - // Task callback methods - // - - /** - * Connect to a socket - */ - void Connect(); - - void Send(UnixSocketIOBuffer* aBuffer); - - // I/O callback methods - // - - void OnConnected() override; - void OnError(const char* aFunction, int aErrno) override; - void OnListening() override; - void OnSocketCanReceiveWithoutBlocking() override; - void OnSocketCanSendWithoutBlocking() override; - - // Methods for |ConnectionOrientedSocketIO| - // - - nsresult Accept(int aFd, - const struct sockaddr* aAddress, - socklen_t aAddressLength) override; - // Methods for |DataSocket| // @@ -86,26 +61,19 @@ public: SocketBase* GetSocketBase() override; - bool IsShutdownOnMainThread() const override; + bool IsShutdownOnConsumerThread() const override; bool IsShutdownOnIOThread() const override; - void ShutdownOnMainThread() override; + void ShutdownOnConsumerThread() override; void ShutdownOnIOThread() override; private: - void FireSocketError(); - /** - * Consumer pointer. Non-thread safe RefPtr, so should only be manipulated - * directly from main thread. All non-main-thread accesses should happen with - * mIO as container. + * Consumer pointer. Non-thread-safe pointer, so should only be manipulated + * directly from consumer thread. All non-consumer-thread accesses should + * happen with mIO as container. */ - RefPtr mStreamSocket; - - /** - * Connector object used to create the connection we are currently using. - */ - nsAutoPtr mConnector; + StreamSocket* mStreamSocket; /** * If true, do not requeue whatever task we're running @@ -113,17 +81,8 @@ private: bool mShuttingDownOnIOThread; /** - * Number of valid bytes in |mAddress| - */ - socklen_t mAddressLength; - - /** - * Address structure of the socket currently in use - */ - struct sockaddr_storage mAddress; - - /** - * Task member for delayed connect task. Should only be access on main thread. + * Task member for delayed connect task. Should only be access on consumer + * thread. */ CancelableTask* mDelayedConnectTask; @@ -133,57 +92,63 @@ private: nsAutoPtr mBuffer; }; -StreamSocketIO::StreamSocketIO(MessageLoop* mIOLoop, +StreamSocketIO::StreamSocketIO(MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, StreamSocket* aStreamSocket, UnixSocketConnector* aConnector) - : UnixSocketWatcher(mIOLoop) + : ConnectionOrientedSocketIO(aConsumerLoop, aIOLoop, aConnector) , mStreamSocket(aStreamSocket) - , mConnector(aConnector) , mShuttingDownOnIOThread(false) - , mAddressLength(0) , mDelayedConnectTask(nullptr) { MOZ_ASSERT(mStreamSocket); - MOZ_ASSERT(mConnector); + + MOZ_COUNT_CTOR_INHERITED(StreamSocketIO, ConnectionOrientedSocketIO); } -StreamSocketIO::StreamSocketIO(MessageLoop* mIOLoop, int aFd, - ConnectionStatus aConnectionStatus, +StreamSocketIO::StreamSocketIO(MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, + int aFd, ConnectionStatus aConnectionStatus, StreamSocket* aStreamSocket, UnixSocketConnector* aConnector) - : UnixSocketWatcher(mIOLoop, aFd, aConnectionStatus) + : ConnectionOrientedSocketIO(aConsumerLoop, + aIOLoop, + aFd, + aConnectionStatus, + aConnector) , mStreamSocket(aStreamSocket) - , mConnector(aConnector) , mShuttingDownOnIOThread(false) - , mAddressLength(0) , mDelayedConnectTask(nullptr) { MOZ_ASSERT(mStreamSocket); - MOZ_ASSERT(mConnector); + + MOZ_COUNT_CTOR_INHERITED(StreamSocketIO, ConnectionOrientedSocketIO); } StreamSocketIO::~StreamSocketIO() { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(IsShutdownOnMainThread()); + MOZ_ASSERT(IsConsumerThread()); + MOZ_ASSERT(IsShutdownOnConsumerThread()); + + MOZ_COUNT_DTOR_INHERITED(StreamSocketIO, ConnectionOrientedSocketIO); } StreamSocket* StreamSocketIO::GetStreamSocket() { - return mStreamSocket.get(); + return mStreamSocket; } DataSocket* StreamSocketIO::GetDataSocket() { - return mStreamSocket.get(); + return GetStreamSocket(); } void StreamSocketIO::SetDelayedConnectTask(CancelableTask* aTask) { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(IsConsumerThread()); mDelayedConnectTask = aTask; } @@ -191,7 +156,7 @@ StreamSocketIO::SetDelayedConnectTask(CancelableTask* aTask) void StreamSocketIO::ClearDelayedConnectTask() { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(IsConsumerThread()); mDelayedConnectTask = nullptr; } @@ -199,7 +164,7 @@ StreamSocketIO::ClearDelayedConnectTask() void StreamSocketIO::CancelDelayedConnectTask() { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(IsConsumerThread()); if (!mDelayedConnectTask) { return; @@ -209,142 +174,6 @@ StreamSocketIO::CancelDelayedConnectTask() ClearDelayedConnectTask(); } -void -StreamSocketIO::Connect() -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(mConnector); - - MOZ_ASSERT(!IsOpen()); - - struct sockaddr* address = reinterpret_cast(&mAddress); - mAddressLength = sizeof(mAddress); - - int fd; - nsresult rv = mConnector->CreateStreamSocket(address, &mAddressLength, fd); - if (NS_FAILED(rv)) { - FireSocketError(); - return; - } - SetFd(fd); - - // calls OnConnected() on success, or OnError() otherwise - rv = UnixSocketWatcher::Connect(address, mAddressLength); - NS_WARN_IF(NS_FAILED(rv)); -} - -void -StreamSocketIO::Send(UnixSocketIOBuffer* aData) -{ - EnqueueData(aData); - AddWatchers(WRITE_WATCHER, false); -} - -void -StreamSocketIO::OnConnected() -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); - - NS_DispatchToMainThread( - new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS)); - - AddWatchers(READ_WATCHER, true); - if (HasPendingData()) { - AddWatchers(WRITE_WATCHER, false); - } -} - -void -StreamSocketIO::OnListening() -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - - NS_NOTREACHED("Invalid call to |StreamSocketIO::OnListening|"); -} - -void -StreamSocketIO::OnError(const char* aFunction, int aErrno) -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - - UnixFdWatcher::OnError(aFunction, aErrno); - FireSocketError(); -} - -void -StreamSocketIO::OnSocketCanReceiveWithoutBlocking() -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); // see bug 990984 - - ssize_t res = ReceiveData(GetFd(), this); - if (res < 0) { - /* I/O error */ - RemoveWatchers(READ_WATCHER|WRITE_WATCHER); - } else if (!res) { - /* EOF or peer shutdown */ - RemoveWatchers(READ_WATCHER); - } -} - -void -StreamSocketIO::OnSocketCanSendWithoutBlocking() -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); // see bug 990984 - - nsresult rv = SendPendingData(GetFd(), this); - if (NS_FAILED(rv)) { - return; - } - - if (HasPendingData()) { - AddWatchers(WRITE_WATCHER, false); - } -} - -void -StreamSocketIO::FireSocketError() -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - - // Clean up watchers, statuses, fds - Close(); - - // Tell the main thread we've errored - NS_DispatchToMainThread( - new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR)); -} - -// |ConnectionOrientedSocketIO| - -nsresult -StreamSocketIO::Accept(int aFd, - const struct sockaddr* aAddress, - socklen_t aAddressLength) -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING); - - SetSocket(aFd, SOCKET_IS_CONNECTED); - - // Address setup - mAddressLength = aAddressLength; - memcpy(&mAddress, aAddress, mAddressLength); - - // Signal success - NS_DispatchToMainThread( - new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS)); - - AddWatchers(READ_WATCHER, true); - if (HasPendingData()) { - AddWatchers(WRITE_WATCHER, false); - } - - return NS_OK; -} - // |DataSocketIO| nsresult @@ -361,36 +190,40 @@ StreamSocketIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) } /** - * |ReceiveRunnable| transfers data received on the I/O thread - * to an instance of |StreamSocket| on the main thread. + * |ReceiveTask| transfers data received on the I/O thread + * to an instance of |StreamSocket| on the consumer thread. */ -class StreamSocketIO::ReceiveRunnable final - : public SocketIORunnable +class StreamSocketIO::ReceiveTask final : public SocketTask { public: - ReceiveRunnable(StreamSocketIO* aIO, UnixSocketBuffer* aBuffer) - : SocketIORunnable(aIO) + ReceiveTask(StreamSocketIO* aIO, UnixSocketBuffer* aBuffer) + : SocketTask(aIO) , mBuffer(aBuffer) - { } - - NS_IMETHOD Run() override { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_COUNT_CTOR(ReceiveTask); + } - StreamSocketIO* io = SocketIORunnable::GetIO(); + ~ReceiveTask() + { + MOZ_COUNT_DTOR(ReceiveTask); + } - if (NS_WARN_IF(io->IsShutdownOnMainThread())) { + void Run() override + { + StreamSocketIO* io = SocketTask::GetIO(); + + MOZ_ASSERT(io->IsConsumerThread()); + + if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) { // Since we've already explicitly closed and the close // happened before this, this isn't really an error. - return NS_OK; + return; } StreamSocket* streamSocket = io->GetStreamSocket(); MOZ_ASSERT(streamSocket); streamSocket->ReceiveSocketData(mBuffer); - - return NS_OK; } private: @@ -400,7 +233,8 @@ private: void StreamSocketIO::ConsumeBuffer() { - NS_DispatchToMainThread(new ReceiveRunnable(this, mBuffer.forget())); + GetConsumerThread()->PostTask(FROM_HERE, + new ReceiveTask(this, mBuffer.forget())); } void @@ -418,9 +252,9 @@ StreamSocketIO::GetSocketBase() } bool -StreamSocketIO::IsShutdownOnMainThread() const +StreamSocketIO::IsShutdownOnConsumerThread() const { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(IsConsumerThread()); return mStreamSocket == nullptr; } @@ -432,10 +266,10 @@ StreamSocketIO::IsShutdownOnIOThread() const } void -StreamSocketIO::ShutdownOnMainThread() +StreamSocketIO::ShutdownOnConsumerThread() { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!IsShutdownOnMainThread()); + MOZ_ASSERT(IsConsumerThread()); + MOZ_ASSERT(!IsShutdownOnConsumerThread()); mStreamSocket = nullptr; } @@ -443,7 +277,7 @@ StreamSocketIO::ShutdownOnMainThread() void StreamSocketIO::ShutdownOnIOThread() { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!IsConsumerThread()); MOZ_ASSERT(!mShuttingDownOnIOThread); Close(); // will also remove fd from I/O loop @@ -454,17 +288,23 @@ StreamSocketIO::ShutdownOnIOThread() // Socket tasks // -class StreamSocketIO::ConnectTask final - : public SocketIOTask +class StreamSocketIO::ConnectTask final : public SocketIOTask { public: ConnectTask(StreamSocketIO* aIO) - : SocketIOTask(aIO) - { } + : SocketIOTask(aIO) + { + MOZ_COUNT_CTOR(ReceiveTask); + } + + ~ConnectTask() + { + MOZ_COUNT_DTOR(ReceiveTask); + } void Run() override { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!GetIO()->IsConsumerThread()); MOZ_ASSERT(!IsCanceled()); GetIO()->Connect(); @@ -476,24 +316,31 @@ class StreamSocketIO::DelayedConnectTask final { public: DelayedConnectTask(StreamSocketIO* aIO) - : SocketIOTask(aIO) - { } + : SocketIOTask(aIO) + { + MOZ_COUNT_CTOR(DelayedConnectTask); + } + + ~DelayedConnectTask() + { + MOZ_COUNT_DTOR(DelayedConnectTask); + } void Run() override { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(GetIO()->IsConsumerThread()); if (IsCanceled()) { return; } StreamSocketIO* io = GetIO(); - if (io->IsShutdownOnMainThread()) { + if (io->IsShutdownOnConsumerThread()) { return; } io->ClearDelayedConnectTask(); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new ConnectTask(io)); + io->GetIOLoop()->PostTask(FROM_HERE, new ConnectTask(io)); } }; @@ -502,35 +349,35 @@ public: // StreamSocket::StreamSocket(StreamSocketConsumer* aConsumer, int aIndex) - : mConsumer(aConsumer) + : mIO(nullptr) + , mConsumer(aConsumer) , mIndex(aIndex) - , mIO(nullptr) { MOZ_ASSERT(mConsumer); + + MOZ_COUNT_CTOR_INHERITED(StreamSocket, ConnectionOrientedSocket); } StreamSocket::~StreamSocket() { MOZ_ASSERT(!mIO); + + MOZ_COUNT_DTOR_INHERITED(StreamSocket, ConnectionOrientedSocket); } void StreamSocket::ReceiveSocketData(nsAutoPtr& aBuffer) { - MOZ_ASSERT(NS_IsMainThread()); - mConsumer->ReceiveSocketData(mIndex, aBuffer); } nsresult -StreamSocket::Connect(UnixSocketConnector* aConnector, - int aDelayMs) +StreamSocket::Connect(UnixSocketConnector* aConnector, int aDelayMs, + MessageLoop* aConsumerLoop, MessageLoop* aIOLoop) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!mIO); - MessageLoop* ioLoop = XRE_GetIOMessageLoop(); - mIO = new StreamSocketIO(ioLoop, this, aConnector); + mIO = new StreamSocketIO(aConsumerLoop, aIOLoop, this, aConnector); SetConnectionStatus(SOCKET_CONNECTING); if (aDelayMs > 0) { @@ -539,24 +386,33 @@ StreamSocket::Connect(UnixSocketConnector* aConnector, mIO->SetDelayedConnectTask(connectTask); MessageLoop::current()->PostDelayedTask(FROM_HERE, connectTask, aDelayMs); } else { - ioLoop->PostTask(FROM_HERE, new StreamSocketIO::ConnectTask(mIO)); + aIOLoop->PostTask(FROM_HERE, new StreamSocketIO::ConnectTask(mIO)); } + return NS_OK; } +nsresult +StreamSocket::Connect(UnixSocketConnector* aConnector, int aDelayMs) +{ + return Connect(aConnector, aDelayMs, + MessageLoop::current(), XRE_GetIOMessageLoop()); +} + // |ConnectionOrientedSocket| nsresult StreamSocket::PrepareAccept(UnixSocketConnector* aConnector, + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, ConnectionOrientedSocketIO*& aIO) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!mIO); MOZ_ASSERT(aConnector); SetConnectionStatus(SOCKET_CONNECTING); - mIO = new StreamSocketIO(XRE_GetIOMessageLoop(), + mIO = new StreamSocketIO(aConsumerLoop, aIOLoop, -1, UnixSocketWatcher::SOCKET_IS_CONNECTING, this, aConnector); aIO = mIO; @@ -569,11 +425,11 @@ StreamSocket::PrepareAccept(UnixSocketConnector* aConnector, void StreamSocket::SendSocketData(UnixSocketIOBuffer* aBuffer) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mIO); + MOZ_ASSERT(mIO->IsConsumerThread()); + MOZ_ASSERT(!mIO->IsShutdownOnConsumerThread()); - MOZ_ASSERT(!mIO->IsShutdownOnMainThread()); - XRE_GetIOMessageLoop()->PostTask( + mIO->GetIOLoop()->PostTask( FROM_HERE, new SocketIOSendTask(mIO, aBuffer)); } @@ -583,18 +439,16 @@ StreamSocket::SendSocketData(UnixSocketIOBuffer* aBuffer) void StreamSocket::Close() { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mIO); + MOZ_ASSERT(mIO->IsConsumerThread()); mIO->CancelDelayedConnectTask(); // From this point on, we consider |mIO| as being deleted. We sever // the relationship here so any future calls to |Connect| will create // a new I/O object. - mIO->ShutdownOnMainThread(); - - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO)); - + mIO->ShutdownOnConsumerThread(); + mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO)); mIO = nullptr; NotifyDisconnect(); @@ -603,24 +457,18 @@ StreamSocket::Close() void StreamSocket::OnConnectSuccess() { - MOZ_ASSERT(NS_IsMainThread()); - mConsumer->OnConnectSuccess(mIndex); } void StreamSocket::OnConnectError() { - MOZ_ASSERT(NS_IsMainThread()); - mConsumer->OnConnectError(mIndex); } void StreamSocket::OnDisconnect() { - MOZ_ASSERT(NS_IsMainThread()); - mConsumer->OnDisconnect(mIndex); } diff --git a/ipc/unixsocket/StreamSocket.h b/ipc/unixsocket/StreamSocket.h index 720c6441ce..178e13c857 100644 --- a/ipc/unixsocket/StreamSocket.h +++ b/ipc/unixsocket/StreamSocket.h @@ -9,6 +9,8 @@ #include "ConnectionOrientedSocket.h" +class MessageLoop; + namespace mozilla { namespace ipc { @@ -19,15 +21,34 @@ class UnixSocketConnector; class StreamSocket final : public ConnectionOrientedSocket { public: + /** + * Constructs an instance of |StreamSocket|. + * + * @param aConsumer The consumer for the socket. + * @param aIndex An arbitrary index. + */ StreamSocket(StreamSocketConsumer* aConsumer, int aIndex); /** - * Method to be called whenever data is received. Main-thread only. + * Method to be called whenever data is received. Consumer-thread only. * * @param aBuffer Data received from the socket. */ void ReceiveSocketData(nsAutoPtr& aBuffer); + /** + * Starts a task on the socket that will try to connect to a socket in a + * non-blocking manner. + * + * @param aConnector Connector object for socket type specific functions + * @param aDelayMs Time delay in milliseconds. + * @param aConsumerLoop The socket's consumer thread. + * @param aIOLoop The socket's I/O thread. + * @return NS_OK on success, or an XPCOM error code otherwise. + */ + nsresult Connect(UnixSocketConnector* aConnector, int aDelayMs, + MessageLoop* aConsumerLoop, MessageLoop* aIOLoop); + /** * Starts a task on the socket that will try to connect to a socket in a * non-blocking manner. @@ -42,6 +63,8 @@ public: // nsresult PrepareAccept(UnixSocketConnector* aConnector, + MessageLoop* aConsumerLoop, + MessageLoop* aIOLoop, ConnectionOrientedSocketIO*& aIO) override; // Methods for |DataSocket| @@ -61,9 +84,9 @@ protected: virtual ~StreamSocket(); private: + StreamSocketIO* mIO; StreamSocketConsumer* mConsumer; int mIndex; - StreamSocketIO* mIO; }; } // namespace ipc diff --git a/ipc/unixsocket/StreamSocketConsumer.cpp b/ipc/unixsocket/StreamSocketConsumer.cpp new file mode 100644 index 0000000000..bac9c1fe70 --- /dev/null +++ b/ipc/unixsocket/StreamSocketConsumer.cpp @@ -0,0 +1,20 @@ +/* -*- 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 "StreamSocketConsumer.h" + +namespace mozilla { +namespace ipc { + +// +// StreamSocketConsumer +// + +StreamSocketConsumer::~StreamSocketConsumer() +{ } + +} +} diff --git a/ipc/unixsocket/StreamSocketConsumer.h b/ipc/unixsocket/StreamSocketConsumer.h new file mode 100644 index 0000000000..59d4f6748f --- /dev/null +++ b/ipc/unixsocket/StreamSocketConsumer.h @@ -0,0 +1,60 @@ +/* -*- 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/. */ + +#ifndef mozilla_ipc_streamsocketconsumer_h +#define mozilla_ipc_streamsocketconsumer_h + +#include "nsAutoPtr.h" + +namespace mozilla { +namespace ipc { + +class UnixSocketBuffer; + +/** + * |StreamSocketConsumer| handles socket events and received data. + */ +class StreamSocketConsumer +{ +public: + /** + * Method to be called whenever data is received. Consumer-thread only. + * + * @param aIndex The index that has been given to the stream socket. + * @param aBuffer Data received from the socket. + */ + virtual void ReceiveSocketData(int aIndex, + nsAutoPtr& aBuffer) = 0; + + /** + * Callback for socket success. Consumer-thread only. + * + * @param aIndex The index that has been given to the stream socket. + */ + virtual void OnConnectSuccess(int aIndex) = 0; + + /** + * Callback for socket errors. Consumer-thread only. + * + * @param aIndex The index that has been given to the stream socket. + */ + virtual void OnConnectError(int aIndex) = 0; + + /** + * Callback for socket disconnect. Consumer-thread only. + * + * @param aIndex The index that has been given to the stream socket. + */ + virtual void OnDisconnect(int aIndex) = 0; + +protected: + virtual ~StreamSocketConsumer(); +}; + +} +} + +#endif diff --git a/ipc/unixsocket/UnixSocket.cpp b/ipc/unixsocket/UnixSocket.cpp deleted file mode 100644 index 1e0df9284d..0000000000 --- a/ipc/unixsocket/UnixSocket.cpp +++ /dev/null @@ -1,667 +0,0 @@ -/* -*- 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 "UnixSocket.h" -#include "nsTArray.h" -#include "nsXULAppAPI.h" -#include -#include "mozilla/unused.h" - -static const size_t MAX_READ_SIZE = 1 << 16; - -namespace mozilla { -namespace ipc { - -// -// UnixSocketConsumerIO -// - -class UnixSocketConsumerIO final : public UnixSocketWatcher - , protected SocketIOBase -{ -public: - UnixSocketConsumerIO(MessageLoop* mIOLoop, - UnixSocketConsumer* aConsumer, - UnixSocketConnector* aConnector, - const nsACString& aAddress); - ~UnixSocketConsumerIO(); - - void GetSocketAddr(nsAString& aAddrStr) const; - SocketConsumerBase* GetConsumer(); - SocketBase* GetSocketBase(); - - // Shutdown state - // - - bool IsShutdownOnMainThread() const; - void ShutdownOnMainThread(); - - bool IsShutdownOnIOThread() const; - void ShutdownOnIOThread(); - - // Delayed-task handling - // - - void SetDelayedConnectTask(CancelableTask* aTask); - void ClearDelayedConnectTask(); - void CancelDelayedConnectTask(); - - // Task callback methods - // - - /** - * Run bind/listen to prepare for further runs of accept() - */ - void Listen(); - - /** - * Connect to a socket - */ - void Connect(); - - void Send(UnixSocketRawData* aData); - - // I/O callback methods - // - - void OnAccepted(int aFd, const sockaddr_any* aAddr, - socklen_t aAddrLen) override; - void OnConnected() override; - void OnError(const char* aFunction, int aErrno) override; - void OnListening() override; - void OnSocketCanReceiveWithoutBlocking() override; - void OnSocketCanSendWithoutBlocking() override; - -private: - void FireSocketError(); - - // Set up flags on file descriptor. - static bool SetSocketFlags(int aFd); - - /** - * Consumer pointer. Non-thread safe RefPtr, so should only be manipulated - * directly from main thread. All non-main-thread accesses should happen with - * mIO as container. - */ - RefPtr mConsumer; - - /** - * Connector object used to create the connection we are currently using. - */ - nsAutoPtr mConnector; - - /** - * If true, do not requeue whatever task we're running - */ - bool mShuttingDownOnIOThread; - - /** - * Address we are connecting to, assuming we are creating a client connection. - */ - nsCString mAddress; - - /** - * Size of the socket address struct - */ - socklen_t mAddrSize; - - /** - * Address struct of the socket currently in use - */ - sockaddr_any mAddr; - - /** - * Task member for delayed connect task. Should only be access on main thread. - */ - CancelableTask* mDelayedConnectTask; -}; - -UnixSocketConsumerIO::UnixSocketConsumerIO(MessageLoop* mIOLoop, - UnixSocketConsumer* aConsumer, - UnixSocketConnector* aConnector, - const nsACString& aAddress) - : UnixSocketWatcher(mIOLoop) - , SocketIOBase(MAX_READ_SIZE) - , mConsumer(aConsumer) - , mConnector(aConnector) - , mShuttingDownOnIOThread(false) - , mAddress(aAddress) - , mDelayedConnectTask(nullptr) -{ - MOZ_ASSERT(mConsumer); - MOZ_ASSERT(mConnector); -} - -UnixSocketConsumerIO::~UnixSocketConsumerIO() -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(IsShutdownOnMainThread()); -} - -void -UnixSocketConsumerIO::GetSocketAddr(nsAString& aAddrStr) const -{ - if (!mConnector) { - NS_WARNING("No connector to get socket address from!"); - aAddrStr.Truncate(); - return; - } - mConnector->GetSocketAddr(mAddr, aAddrStr); -} - -SocketConsumerBase* -UnixSocketConsumerIO::GetConsumer() -{ - return mConsumer.get(); -} - -SocketBase* -UnixSocketConsumerIO::GetSocketBase() -{ - return GetConsumer(); -} - -bool -UnixSocketConsumerIO::IsShutdownOnMainThread() const -{ - MOZ_ASSERT(NS_IsMainThread()); - - return mConsumer == nullptr; -} - -void -UnixSocketConsumerIO::ShutdownOnMainThread() -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!IsShutdownOnMainThread()); - - mConsumer = nullptr; -} - -bool -UnixSocketConsumerIO::IsShutdownOnIOThread() const -{ - return mShuttingDownOnIOThread; -} - -void -UnixSocketConsumerIO::ShutdownOnIOThread() -{ - MOZ_ASSERT(!NS_IsMainThread()); - MOZ_ASSERT(!mShuttingDownOnIOThread); - - Close(); // will also remove fd from I/O loop - mShuttingDownOnIOThread = true; -} - -void -UnixSocketConsumerIO::SetDelayedConnectTask(CancelableTask* aTask) -{ - MOZ_ASSERT(NS_IsMainThread()); - - mDelayedConnectTask = aTask; -} - -void -UnixSocketConsumerIO::ClearDelayedConnectTask() -{ - MOZ_ASSERT(NS_IsMainThread()); - - mDelayedConnectTask = nullptr; -} - -void -UnixSocketConsumerIO::CancelDelayedConnectTask() -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (!mDelayedConnectTask) { - return; - } - - mDelayedConnectTask->Cancel(); - ClearDelayedConnectTask(); -} - -void -UnixSocketConsumerIO::Listen() -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(mConnector); - - // This will set things we don't particularly care about, but it will hand - // back the correct structure size which is what we do care about. - if (!mConnector->CreateAddr(true, mAddrSize, mAddr, nullptr)) { - NS_WARNING("Cannot create socket address!"); - FireSocketError(); - return; - } - - if (!IsOpen()) { - int fd = mConnector->Create(); - if (fd < 0) { - NS_WARNING("Cannot create socket fd!"); - FireSocketError(); - return; - } - if (!SetSocketFlags(fd)) { - NS_WARNING("Cannot set socket flags!"); - FireSocketError(); - return; - } - SetFd(fd); - - // calls OnListening on success, or OnError otherwise - nsresult rv = UnixSocketWatcher::Listen( - reinterpret_cast(&mAddr), mAddrSize); - NS_WARN_IF(NS_FAILED(rv)); - } -} - -void -UnixSocketConsumerIO::Connect() -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(mConnector); - - if (!IsOpen()) { - int fd = mConnector->Create(); - if (fd < 0) { - NS_WARNING("Cannot create socket fd!"); - FireSocketError(); - return; - } - if (!SetSocketFlags(fd)) { - NS_WARNING("Cannot set socket flags!"); - FireSocketError(); - return; - } - SetFd(fd); - } - - if (!mConnector->CreateAddr(false, mAddrSize, mAddr, mAddress.get())) { - NS_WARNING("Cannot create socket address!"); - FireSocketError(); - return; - } - - // calls OnConnected() on success, or OnError() otherwise - nsresult rv = UnixSocketWatcher::Connect( - reinterpret_cast(&mAddr), mAddrSize); - NS_WARN_IF(NS_FAILED(rv)); -} - -void -UnixSocketConsumerIO::Send(UnixSocketRawData* aData) -{ - EnqueueData(aData); - AddWatchers(WRITE_WATCHER, false); -} - -void -UnixSocketConsumerIO::OnAccepted(int aFd, - const sockaddr_any* aAddr, - socklen_t aAddrLen) -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_LISTENING); - MOZ_ASSERT(aAddr); - MOZ_ASSERT(aAddrLen > 0 && (size_t)aAddrLen <= sizeof(mAddr)); - - memcpy (&mAddr, aAddr, aAddrLen); - mAddrSize = aAddrLen; - - if (!mConnector->SetUp(aFd)) { - NS_WARNING("Could not set up socket!"); - return; - } - - RemoveWatchers(READ_WATCHER|WRITE_WATCHER); - Close(); - if (!SetSocketFlags(aFd)) { - return; - } - SetSocket(aFd, SOCKET_IS_CONNECTED); - - nsRefPtr r = - new SocketIOEventRunnable( - this, SocketIOEventRunnable::CONNECT_SUCCESS); - NS_DispatchToMainThread(r); - - AddWatchers(READ_WATCHER, true); - if (HasPendingData()) { - AddWatchers(WRITE_WATCHER, false); - } -} - -void -UnixSocketConsumerIO::OnConnected() -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); - - if (!SetSocketFlags(GetFd())) { - NS_WARNING("Cannot set socket flags!"); - FireSocketError(); - return; - } - - if (!mConnector->SetUp(GetFd())) { - NS_WARNING("Could not set up socket!"); - FireSocketError(); - return; - } - - nsRefPtr r = - new SocketIOEventRunnable( - this, SocketIOEventRunnable::CONNECT_SUCCESS); - NS_DispatchToMainThread(r); - - AddWatchers(READ_WATCHER, true); - if (HasPendingData()) { - AddWatchers(WRITE_WATCHER, false); - } -} - -void -UnixSocketConsumerIO::OnListening() -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_LISTENING); - - if (!mConnector->SetUpListenSocket(GetFd())) { - NS_WARNING("Could not set up listen socket!"); - FireSocketError(); - return; - } - - AddWatchers(READ_WATCHER, true); -} - -void -UnixSocketConsumerIO::OnError(const char* aFunction, int aErrno) -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - - UnixFdWatcher::OnError(aFunction, aErrno); - FireSocketError(); -} - -void -UnixSocketConsumerIO::OnSocketCanReceiveWithoutBlocking() -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); // see bug 990984 - - ssize_t res = ReceiveData(GetFd(), this); - if (res < 0) { - /* I/O error */ - RemoveWatchers(READ_WATCHER|WRITE_WATCHER); - } else if (!res) { - /* EOF or peer shutdown */ - RemoveWatchers(READ_WATCHER); - } -} - -void -UnixSocketConsumerIO::OnSocketCanSendWithoutBlocking() -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); // see bug 990984 - - nsresult rv = SendPendingData(GetFd(), this); - if (NS_FAILED(rv)) { - return; - } - - if (HasPendingData()) { - AddWatchers(WRITE_WATCHER, false); - } -} - -void -UnixSocketConsumerIO::FireSocketError() -{ - MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop()); - - // Clean up watchers, statuses, fds - Close(); - - // Tell the main thread we've errored - nsRefPtr r = - new SocketIOEventRunnable( - this, SocketIOEventRunnable::CONNECT_ERROR); - - NS_DispatchToMainThread(r); -} - -bool -UnixSocketConsumerIO::SetSocketFlags(int aFd) -{ - // Set socket addr to be reused even if kernel is still waiting to close - int n = 1; - if (setsockopt(aFd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) < 0) { - return false; - } - - // Set close-on-exec bit. - int flags = TEMP_FAILURE_RETRY(fcntl(aFd, F_GETFD)); - if (-1 == flags) { - return false; - } - flags |= FD_CLOEXEC; - if (-1 == TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFD, flags))) { - return false; - } - - // Set non-blocking status flag. - flags = TEMP_FAILURE_RETRY(fcntl(aFd, F_GETFL)); - if (-1 == flags) { - return false; - } - flags |= O_NONBLOCK; - if (-1 == TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, flags))) { - return false; - } - - return true; -} - -// -// Socket tasks -// - -class ListenTask final : public SocketIOTask -{ -public: - ListenTask(UnixSocketConsumerIO* aIO) - : SocketIOTask(aIO) - { } - - void Run() override - { - MOZ_ASSERT(!NS_IsMainThread()); - - if (!IsCanceled()) { - GetIO()->Listen(); - } - } -}; - -class ConnectTask final : public SocketIOTask -{ -public: - ConnectTask(UnixSocketConsumerIO* aIO) - : SocketIOTask(aIO) - { } - - void Run() override - { - MOZ_ASSERT(!NS_IsMainThread()); - MOZ_ASSERT(!IsCanceled()); - - GetIO()->Connect(); - } -}; - -class DelayedConnectTask final : public SocketIOTask -{ -public: - DelayedConnectTask(UnixSocketConsumerIO* aIO) - : SocketIOTask(aIO) - { } - - void Run() override - { - MOZ_ASSERT(NS_IsMainThread()); - - if (IsCanceled()) { - return; - } - - UnixSocketConsumerIO* io = GetIO(); - if (io->IsShutdownOnMainThread()) { - return; - } - - io->ClearDelayedConnectTask(); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new ConnectTask(io)); - } -}; - -// -// UnixSocketConsumer -// - -UnixSocketConsumer::UnixSocketConsumer() -: mIO(nullptr) -{ } - -UnixSocketConsumer::~UnixSocketConsumer() -{ - MOZ_ASSERT(!mIO); -} - -bool -UnixSocketConsumer::SendSocketData(UnixSocketRawData* aData) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (!mIO) { - return false; - } - - MOZ_ASSERT(!mIO->IsShutdownOnMainThread()); - XRE_GetIOMessageLoop()->PostTask( - FROM_HERE, - new SocketIOSendTask(mIO, aData)); - - return true; -} - -bool -UnixSocketConsumer::SendSocketData(const nsACString& aStr) -{ - if (aStr.Length() > MAX_READ_SIZE) { - return false; - } - - nsAutoPtr data( - new UnixSocketRawData(aStr.BeginReading(), aStr.Length())); - - if (!SendSocketData(data)) { - return false; - } - - unused << data.forget(); - - return true; -} - -void -UnixSocketConsumer::CloseSocket() -{ - MOZ_ASSERT(NS_IsMainThread()); - if (!mIO) { - return; - } - - mIO->CancelDelayedConnectTask(); - - // From this point on, we consider mIO as being deleted. - // We sever the relationship here so any future calls to listen or connect - // will create a new implementation. - mIO->ShutdownOnMainThread(); - - XRE_GetIOMessageLoop()->PostTask( - FROM_HERE, new SocketIOShutdownTask(mIO)); - - mIO = nullptr; - - NotifyDisconnect(); -} - -void -UnixSocketConsumer::GetSocketAddr(nsAString& aAddrStr) -{ - aAddrStr.Truncate(); - if (!mIO || GetConnectionStatus() != SOCKET_CONNECTED) { - NS_WARNING("No socket currently open!"); - return; - } - mIO->GetSocketAddr(aAddrStr); -} - -bool -UnixSocketConsumer::ConnectSocket(UnixSocketConnector* aConnector, - const char* aAddress, - int aDelayMs) -{ - MOZ_ASSERT(aConnector); - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr connector(aConnector); - - if (mIO) { - NS_WARNING("Socket already connecting/connected!"); - return false; - } - - nsCString addr(aAddress); - MessageLoop* ioLoop = XRE_GetIOMessageLoop(); - mIO = new UnixSocketConsumerIO(ioLoop, this, connector.forget(), addr); - SetConnectionStatus(SOCKET_CONNECTING); - if (aDelayMs > 0) { - DelayedConnectTask* connectTask = new DelayedConnectTask(mIO); - mIO->SetDelayedConnectTask(connectTask); - MessageLoop::current()->PostDelayedTask(FROM_HERE, connectTask, aDelayMs); - } else { - ioLoop->PostTask(FROM_HERE, new ConnectTask(mIO)); - } - return true; -} - -bool -UnixSocketConsumer::ListenSocket(UnixSocketConnector* aConnector) -{ - MOZ_ASSERT(aConnector); - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr connector(aConnector); - - if (mIO) { - NS_WARNING("Socket already connecting/connected!"); - return false; - } - - mIO = new UnixSocketConsumerIO( - XRE_GetIOMessageLoop(), this, connector.forget(), EmptyCString()); - SetConnectionStatus(SOCKET_LISTENING); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new ListenTask(mIO)); - return true; -} - -} // namespace ipc -} // namespace mozilla diff --git a/ipc/unixsocket/UnixSocket.h b/ipc/unixsocket/UnixSocket.h deleted file mode 100644 index 9867c796f8..0000000000 --- a/ipc/unixsocket/UnixSocket.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- 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/. */ - -#ifndef mozilla_ipc_unixsocket_h -#define mozilla_ipc_unixsocket_h - -#include -#include "nsAutoPtr.h" -#include "nsString.h" -#include "nsThreadUtils.h" -#include "mozilla/ipc/SocketBase.h" -#include "mozilla/ipc/UnixSocketWatcher.h" -#include "mozilla/RefPtr.h" -#include "UnixSocketConnector.h" - -namespace mozilla { -namespace ipc { - -class UnixSocketConsumerIO; - -class UnixSocketConsumer : public SocketConsumerBase -{ -protected: - virtual ~UnixSocketConsumer(); - -public: - UnixSocketConsumer(); - - /** - * Queue data to be sent to the socket on the IO thread. Can only be called on - * originating thread. - * - * @param aMessage Data to be sent to socket - * - * @return true if data is queued, false otherwise (i.e. not connected) - */ - bool SendSocketData(UnixSocketRawData* aMessage); - - /** - * Convenience function for sending strings to the socket (common in bluetooth - * profile usage). Converts to a UnixSocketRawData struct. Can only be called - * on originating thread. - * - * @param aMessage String to be sent to socket - * - * @return true if data is queued, false otherwise (i.e. not connected) - */ - bool SendSocketData(const nsACString& aMessage); - - /** - * Starts a task on the socket that will try to connect to a socket in a - * non-blocking manner. - * - * @param aConnector Connector object for socket type specific functions - * @param aAddress Address to connect to. - * @param aDelayMs Time delay in milli-seconds. - * - * @return true on connect task started, false otherwise. - */ - bool ConnectSocket(UnixSocketConnector* aConnector, - const char* aAddress, - int aDelayMs = 0); - - /** - * Starts a task on the socket that will try to accept a new connection in a - * non-blocking manner. - * - * @param aConnector Connector object for socket type specific functions - * - * @return true on listen started, false otherwise - */ - bool ListenSocket(UnixSocketConnector* aConnector); - - /** - * Queues the internal representation of socket for deletion. Can be called - * from main thread. - */ - void CloseSocket(); - - /** - * Get the current sockaddr for the socket - */ - void GetSocketAddr(nsAString& aAddrStr); - -private: - UnixSocketConsumerIO* mIO; -}; - -} // namespace ipc -} // namepsace mozilla - -#endif // mozilla_ipc_unixsocket_h diff --git a/ipc/unixsocket/UnixSocketConnector.cpp b/ipc/unixsocket/UnixSocketConnector.cpp index 37ddd0fb1b..680437c124 100644 --- a/ipc/unixsocket/UnixSocketConnector.cpp +++ b/ipc/unixsocket/UnixSocketConnector.cpp @@ -5,15 +5,20 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "UnixSocketConnector.h" +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR namespace mozilla { namespace ipc { UnixSocketConnector::UnixSocketConnector() -{ } +{ + MOZ_COUNT_CTOR(UnixSocketConnector); +} UnixSocketConnector::~UnixSocketConnector() -{ } +{ + MOZ_COUNT_DTOR(UnixSocketConnector); +} } } diff --git a/ipc/unixsocket/moz.build b/ipc/unixsocket/moz.build index b15dc63d5e..85d7bc36a1 100644 --- a/ipc/unixsocket/moz.build +++ b/ipc/unixsocket/moz.build @@ -8,9 +8,10 @@ EXPORTS.mozilla.ipc += [ 'ConnectionOrientedSocket.h', 'DataSocket.h', 'ListenSocket.h', + 'ListenSocketConsumer.h', 'SocketBase.h', 'StreamSocket.h', - 'UnixSocket.h', + 'StreamSocketConsumer.h', 'UnixSocketConnector.h' ] @@ -18,9 +19,10 @@ SOURCES += [ 'ConnectionOrientedSocket.cpp', 'DataSocket.cpp', 'ListenSocket.cpp', + 'ListenSocketConsumer.cpp', 'SocketBase.cpp', 'StreamSocket.cpp', - 'UnixSocket.cpp', + 'StreamSocketConsumer.cpp', 'UnixSocketConnector.cpp' ] diff --git a/js/src/jsapi-tests/testSavedStacks.cpp b/js/src/jsapi-tests/testSavedStacks.cpp index d3bfd75cfa..b1caa66485 100644 --- a/js/src/jsapi-tests/testSavedStacks.cpp +++ b/js/src/jsapi-tests/testSavedStacks.cpp @@ -8,8 +8,8 @@ #include "jsfriendapi.h" #include "jsstr.h" +#include "builtin/TestingFunctions.h" #include "jsapi-tests/tests.h" - #include "vm/ArrayObject.h" #include "vm/SavedStacks.h" @@ -63,3 +63,51 @@ BEGIN_TEST(testSavedStacks_ApiDefaultValues) return true; } END_TEST(testSavedStacks_ApiDefaultValues) + +BEGIN_TEST(testSavedStacks_RangeBasedForLoops) +{ + CHECK(js::DefineTestingFunctions(cx, global, false)); + + JS::RootedValue val(cx); + CHECK(evaluate("(function one() { \n" // 1 + " return (function two() { \n" // 2 + " return (function three() { \n" // 3 + " return saveStack(); \n" // 4 + " }()); \n" // 5 + " }()); \n" // 6 + "}()); \n", // 7 + "filename.js", + 1, + &val)); + + CHECK(val.isObject()); + JS::RootedObject obj(cx, &val.toObject()); + + CHECK(obj->is()); + JS::Rooted savedFrame(cx, &obj->as()); + + js::SavedFrame* f = savedFrame.get(); + for (auto& frame : *savedFrame.get()) { + CHECK(&frame == f); + f = f->getParent(); + } + CHECK(f == nullptr); + + const js::SavedFrame* cf = savedFrame.get(); + for (const auto& frame : *savedFrame.get()) { + CHECK(&frame == cf); + cf = cf->getParent(); + } + CHECK(cf == nullptr); + + JS::Rooted rf(cx, savedFrame); + for (JS::Handle frame : js::SavedFrame::RootedRange(cx, rf)) { + JS_GC(cx->runtime()); + CHECK(frame == rf); + rf = rf->getParent(); + } + CHECK(rf == nullptr); + + return true; +} +END_TEST(testSavedStacks_RangeBasedForLoops) diff --git a/js/src/vm/SavedFrame.h b/js/src/vm/SavedFrame.h index df878d2888..afb1fe11fc 100644 --- a/js/src/vm/SavedFrame.h +++ b/js/src/vm/SavedFrame.h @@ -32,15 +32,86 @@ class SavedFrame : public NativeObject { static void finalize(FreeOp* fop, JSObject* obj); // Convenient getters for SavedFrame's reserved slots for use from C++. - JSAtom* getSource(); - uint32_t getLine(); - uint32_t getColumn(); - JSAtom* getFunctionDisplayName(); - JSAtom* getAsyncCause(); - SavedFrame* getParent(); + JSAtom* getSource(); + uint32_t getLine(); + uint32_t getColumn(); + JSAtom* getFunctionDisplayName(); + JSAtom* getAsyncCause(); + SavedFrame* getParent() const; JSPrincipals* getPrincipals(); + bool isSelfHosted(); - bool isSelfHosted(); + // Iterators for use with C++11 range based for loops, eg: + // + // SavedFrame* stack = getSomeSavedFrameStack(); + // for (const SavedFrame* frame : *stack) { + // ... + // } + // + // If you need to keep each frame rooted during iteration, you can use + // `SavedFrame::RootedRange`. Each frame yielded by + // `SavedFrame::RootedRange` is only a valid handle to a rooted `SavedFrame` + // within the loop's block for a single loop iteration. When the next + // iteration begins, the value is invalidated. + // + // RootedSavedFrame stack(cx, getSomeSavedFrameStack()); + // for (HandleSavedFrame frame : SavedFrame::RootedRange(cx, stack)) { + // ... + // } + + class Iterator { + SavedFrame* frame_; + public: + explicit Iterator(SavedFrame* frame) : frame_(frame) { } + SavedFrame& operator*() const { MOZ_ASSERT(frame_); return *frame_; } + bool operator!=(const Iterator& rhs) const { return rhs.frame_ != frame_; } + inline void operator++(); + }; + + Iterator begin() { return Iterator(this); } + Iterator end() { return Iterator(nullptr); } + + class ConstIterator { + const SavedFrame* frame_; + public: + explicit ConstIterator(const SavedFrame* frame) : frame_(frame) { } + const SavedFrame& operator*() const { MOZ_ASSERT(frame_); return *frame_; } + bool operator!=(const ConstIterator& rhs) const { return rhs.frame_ != frame_; } + inline void operator++(); + }; + + ConstIterator begin() const { return ConstIterator(this); } + ConstIterator end() const { return ConstIterator(nullptr); } + + class RootedRange; + + class MOZ_STACK_CLASS RootedIterator { + friend class RootedRange; + RootedRange* range_; + // For use by RootedRange::end() only. + explicit RootedIterator() : range_(nullptr) { } + + public: + explicit RootedIterator(RootedRange& range) : range_(&range) { } + HandleSavedFrame operator*() { MOZ_ASSERT(range_); return range_->frame_; } + bool operator!=(const RootedIterator& rhs) const { + // We should only ever compare to the null range, aka we are just + // testing if this range is done. + MOZ_ASSERT(rhs.range_ == nullptr); + return range_->frame_ != nullptr; + } + inline void operator++(); + }; + + class MOZ_STACK_CLASS RootedRange { + friend class RootedIterator; + RootedSavedFrame frame_; + + public: + RootedRange(JSContext* cx, HandleSavedFrame frame) : frame_(cx, frame) { } + RootedIterator begin() { return RootedIterator(*this); } + RootedIterator end() { return RootedIterator(); } + }; static bool isSavedFrameAndNotProto(JSObject& obj) { return obj.is() && @@ -107,6 +178,25 @@ struct SavedFrame::HashPolicy // SavedFrame object or wrapper (Xray or CCW) around a SavedFrame object. inline void AssertObjectIsSavedFrameOrWrapper(JSContext* cx, HandleObject stack); +inline void +SavedFrame::Iterator::operator++() +{ + frame_ = frame_->getParent(); +} + +inline void +SavedFrame::ConstIterator::operator++() +{ + frame_ = frame_->getParent(); +} + +inline void +SavedFrame::RootedIterator::operator++() +{ + MOZ_ASSERT(range_); + range_->frame_ = range_->frame_->getParent(); +} + } // namespace js #endif // vm_SavedFrame_h diff --git a/js/src/vm/SavedStacks.cpp b/js/src/vm/SavedStacks.cpp index 960ef336c1..d6d1bc5b5c 100644 --- a/js/src/vm/SavedStacks.cpp +++ b/js/src/vm/SavedStacks.cpp @@ -387,7 +387,7 @@ SavedFrame::getAsyncCause() } SavedFrame* -SavedFrame::getParent() +SavedFrame::getParent() const { const Value& v = getReservedSlot(JSSLOT_PARENT); return v.isObject() ? &v.toObject().as() : nullptr; diff --git a/layout/mathml/nsMathMLChar.h b/layout/mathml/nsMathMLChar.h index 29c9e0efae..f1216c3c9f 100644 --- a/layout/mathml/nsMathMLChar.h +++ b/layout/mathml/nsMathMLChar.h @@ -61,7 +61,7 @@ struct nsGlyphCode { bool IsGlyphID() const { return font == -1; } int32_t Length() const { - return (IsGlyphID() || code[1] == PRUnichar('\0') ? 1 : 2); + return (IsGlyphID() || code[1] == char16_t('\0') ? 1 : 2); } bool Exists() const { diff --git a/netwerk/streamconv/converters/nsIndexedToHTML.cpp b/netwerk/streamconv/converters/nsIndexedToHTML.cpp index e18b929297..299cce7d1e 100644 --- a/netwerk/streamconv/converters/nsIndexedToHTML.cpp +++ b/netwerk/streamconv/converters/nsIndexedToHTML.cpp @@ -679,7 +679,7 @@ nsIndexedToHTML::OnIndexAvailable(nsIRequest *aRequest, if (loc.IsEmpty()) { return NS_ERROR_ILLEGAL_VALUE; } - if (loc.First() == PRUnichar('.')) + if (loc.First() == char16_t('.')) pushBuffer.AppendLiteral(" class=\"hidden-object\""); pushBuffer.AppendLiteral(">\n (mImage); +} + +already_AddRefed +GonkClipboardData::GetImage() const +{ + // Return cloned DataSourceSurface. + RefPtr cloned = gfx::CreateDataSourceSurfaceByCloning(mImage); + return cloned.forget(); +} + +void +GonkClipboardData::Clear() +{ + mPlain.Truncate(0); + mHTML.Truncate(0); + mImage = nullptr; +} + +} // namespace mozilla diff --git a/widget/gonk/GonkClipboardData.h b/widget/gonk/GonkClipboardData.h new file mode 100644 index 0000000000..8bc1f1c9c4 --- /dev/null +++ b/widget/gonk/GonkClipboardData.h @@ -0,0 +1,49 @@ +/* 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/. */ + +#ifndef mozilla_GonkClipboardData +#define mozilla_GonkClipboardData + +#include "mozilla/RefPtr.h" +#include "nsString.h" + +namespace mozilla { + +namespace gfx { +class DataSourceSurface; +} + +class GonkClipboardData final +{ +public: + explicit GonkClipboardData() = default; + ~GonkClipboardData() = default; + + // For text/plain + void SetText(const nsAString &aText); + bool HasText() const; + const nsAString& GetText() const; + + // For text/html + void SetHTML(const nsAString &aHTML); + bool HasHTML() const; + const nsAString& GetHTML() const; + + // For images + void SetImage(gfx::DataSourceSurface* aDataSource); + bool HasImage() const; + already_AddRefed GetImage() const; + + // For other APIs + void Clear(); + +private: + nsAutoString mPlain; + nsAutoString mHTML; + RefPtr mImage; +}; + +} // namespace mozilla + +#endif // mozilla_GonkClipboardData diff --git a/widget/gonk/moz.build b/widget/gonk/moz.build index ced3b0d836..52d260e808 100644 --- a/widget/gonk/moz.build +++ b/widget/gonk/moz.build @@ -58,6 +58,7 @@ elif CONFIG['ANDROID_VERSION'] == '15': SOURCES += [ 'GeckoTouchDispatcher.cpp', 'GfxInfo.cpp', + 'GonkClipboardData.cpp', 'GonkMemoryPressureMonitoring.cpp', 'GonkPermission.cpp', 'HwcComposer2D.cpp', @@ -85,6 +86,7 @@ LOCAL_INCLUDES += [ '/dom/system/android', '/gfx/skia/skia/include/config', '/gfx/skia/skia/include/core', + '/image', '/widget', ] diff --git a/widget/gonk/nsClipboard.cpp b/widget/gonk/nsClipboard.cpp index 6b8f820fbe..0134b9b22d 100644 --- a/widget/gonk/nsClipboard.cpp +++ b/widget/gonk/nsClipboard.cpp @@ -2,12 +2,20 @@ * 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 "mozilla/dom/ContentChild.h" #include "nsClipboard.h" + +#include "gfxDrawable.h" +#include "gfxUtils.h" +#include "ImageOps.h" +#include "imgIContainer.h" +#include "imgTools.h" +#include "mozilla/dom/ContentChild.h" #include "nsClipboardProxy.h" #include "nsISupportsPrimitives.h" -#include "nsCOMPtr.h" #include "nsComponentManagerUtils.h" +#include "nsCOMPtr.h" +#include "nsServiceManagerUtils.h" +#include "nsStringStream.h" #include "nsXULAppAPI.h" using namespace mozilla; @@ -17,15 +25,18 @@ using mozilla::dom::ContentChild; #define LOGI(args...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, ## args) #define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, ## args) + NS_IMPL_ISUPPORTS(nsClipboard, nsIClipboard) nsClipboard::nsClipboard() + : mClipboard(mozilla::MakeUnique()) { } NS_IMETHODIMP nsClipboard::SetData(nsITransferable *aTransferable, - nsIClipboardOwner *anOwner, int32_t aWhichClipboard) + nsIClipboardOwner *anOwner, + int32_t aWhichClipboard) { if (aWhichClipboard != kGlobalClipboard) { return NS_ERROR_NOT_IMPLEMENTED; @@ -37,28 +48,108 @@ nsClipboard::SetData(nsITransferable *aTransferable, return clipboardProxy->SetData(aTransferable, anOwner, aWhichClipboard); } - nsCOMPtr tmp; - uint32_t len; - nsresult rv = aTransferable->GetTransferData(kUnicodeMime, getter_AddRefs(tmp), - &len); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - nsCOMPtr supportsString = do_QueryInterface(tmp); - // No support for non-text data - if (NS_WARN_IF(!supportsString)) { - LOGE("No support for non-text data. See bug 952456."); - return NS_ERROR_NOT_IMPLEMENTED; - } - nsAutoString buffer; - supportsString->GetData(buffer); + // Clear out the clipboard in order to set the new data + EmptyClipboard(aWhichClipboard); + + // Get the types of supported flavors. + nsCOMPtr flavorList; + nsresult rv = aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList)); + if (!flavorList || NS_FAILED(rv)) { + return NS_ERROR_FAILURE; + } + + uint32_t flavorCount = 0; + flavorList->Count(&flavorCount); + bool imageAdded = false; + for (uint32_t i = 0; i < flavorCount; ++i) { + nsCOMPtr currentFlavor = do_QueryElementAt(flavorList, i); + + if (currentFlavor) { + // MIME type + nsXPIDLCString flavorStr; + currentFlavor->ToString(getter_Copies(flavorStr)); + + // Clip is the data which will be sent to the clipboard. + nsCOMPtr clip; + uint32_t len; + + if (flavorStr.EqualsLiteral(kUnicodeMime)) { + // text/plain + rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(clip), &len); + nsCOMPtr wideString = do_QueryInterface(clip); + if (!wideString || NS_FAILED(rv)) { + continue; + } + + nsAutoString utf16string; + wideString->GetData(utf16string); + mClipboard->SetText(utf16string); + } else if (flavorStr.EqualsLiteral(kHTMLMime)) { + // text/html + rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(clip), &len); + nsCOMPtr wideString = do_QueryInterface(clip); + if (!wideString || NS_FAILED(rv)) { + continue; + } + + nsAutoString utf16string; + wideString->GetData(utf16string); + mClipboard->SetHTML(utf16string); + } else if (!imageAdded && // image is added only once to the clipboard. + (flavorStr.EqualsLiteral(kNativeImageMime) || + flavorStr.EqualsLiteral(kPNGImageMime) || + flavorStr.EqualsLiteral(kJPEGImageMime) || + flavorStr.EqualsLiteral(kJPGImageMime) || + flavorStr.EqualsLiteral(kGIFImageMime))) { + // image/[png|jpeg|jpg|gif] or application/x-moz-nativeimage + + // Look through our transfer data for the image. + static const char* const imageMimeTypes[] = { + kNativeImageMime, kPNGImageMime, kJPEGImageMime, kJPGImageMime, kGIFImageMime }; + + nsCOMPtr imgPtr; + for (uint32_t i = 0; !imgPtr && i < ArrayLength(imageMimeTypes); ++i) { + aTransferable->GetTransferData(imageMimeTypes[i], getter_AddRefs(clip), &len); + imgPtr = do_QueryInterface(clip); + } + if (!imgPtr) { + continue; + } + + nsCOMPtr imageData; + imgPtr->GetData(getter_AddRefs(imageData)); + nsCOMPtr image(do_QueryInterface(imageData)); + if (!image) { + continue; + } + + RefPtr surface = + image->GetFrame(imgIContainer::FRAME_CURRENT, + imgIContainer::FLAG_SYNC_DECODE); + if (!surface) { + continue; + } + + RefPtr dataSurface; + if (surface->GetFormat() == gfx::SurfaceFormat::B8G8R8A8) { + dataSurface = surface->GetDataSurface(); + } else { + // Convert format to SurfaceFormat::B8G8R8A8. + dataSurface = gfxUtils::CopySurfaceToDataSourceSurfaceWithFormat(surface, gfx::SurfaceFormat::B8G8R8A8); + } + + mClipboard->SetImage(dataSurface); + imageAdded = true; + } + } + } - mClipboard = buffer; return NS_OK; } NS_IMETHODIMP -nsClipboard::GetData(nsITransferable *aTransferable, int32_t aWhichClipboard) +nsClipboard::GetData(nsITransferable *aTransferable, + int32_t aWhichClipboard) { if (aWhichClipboard != kGlobalClipboard) { return NS_ERROR_NOT_IMPLEMENTED; @@ -70,29 +161,92 @@ nsClipboard::GetData(nsITransferable *aTransferable, int32_t aWhichClipboard) return clipboardProxy->GetData(aTransferable, aWhichClipboard); } - nsAutoString buffer(mClipboard); + // Get flavor list that includes all acceptable flavors (including + // ones obtained through conversion). + // Note: We don't need to call nsITransferable::AddDataFlavor here + // because ContentParent already did. + nsCOMPtr flavorList; + nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList)); - nsresult rv; - nsCOMPtr dataWrapper = - do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; + if (!flavorList || NS_FAILED(rv)) { + return NS_ERROR_FAILURE; } - rv = dataWrapper->SetData(buffer); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } + // Walk through flavors and see which flavor matches the one being pasted. + uint32_t flavorCount; + flavorList->Count(&flavorCount); - // If our data flavor has already been added, this will fail. But we don't care - aTransferable->AddDataFlavor(kUnicodeMime); + for (uint32_t i = 0; i < flavorCount; ++i) { + nsCOMPtr currentFlavor = do_QueryElementAt(flavorList, i); - nsCOMPtr nsisupportsDataWrapper = - do_QueryInterface(dataWrapper); - rv = aTransferable->SetTransferData(kUnicodeMime, nsisupportsDataWrapper, - buffer.Length() * sizeof(PRUnichar)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; + if (currentFlavor) { + // flavorStr is the mime type. + nsXPIDLCString flavorStr; + currentFlavor->ToString(getter_Copies(flavorStr)); + + // text/plain, text/Unicode + if (flavorStr.EqualsLiteral(kUnicodeMime) && mClipboard->HasText()) { + nsresult rv; + nsCOMPtr dataWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv); + rv = dataWrapper->SetData(mClipboard->GetText()); + if (NS_WARN_IF(NS_FAILED(rv))) { + continue; + } + + nsCOMPtr genericDataWrapper = do_QueryInterface(dataWrapper); + uint32_t len = mClipboard->GetText().Length() * sizeof(char16_t); + rv = aTransferable->SetTransferData(flavorStr, genericDataWrapper, len); + if (NS_WARN_IF(NS_FAILED(rv))) { + continue; + } + break; + } + + // text/html + if (flavorStr.EqualsLiteral(kHTMLMime) && mClipboard->HasHTML()) { + nsresult rv; + nsCOMPtr dataWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv); + rv = dataWrapper->SetData(mClipboard->GetHTML()); + if (NS_WARN_IF(NS_FAILED(rv))) { + continue; + } + + nsCOMPtr genericDataWrapper = do_QueryInterface(dataWrapper); + uint32_t len = mClipboard->GetHTML().Length() * sizeof(char16_t); + rv = aTransferable->SetTransferData(flavorStr, genericDataWrapper, len); + if (NS_WARN_IF(NS_FAILED(rv))) { + continue; + } + break; + } + + // image/[png|jpeg|jpg|gif] + if ((flavorStr.EqualsLiteral(kPNGImageMime) || + flavorStr.EqualsLiteral(kJPEGImageMime) || + flavorStr.EqualsLiteral(kJPGImageMime) || + flavorStr.EqualsLiteral(kGIFImageMime)) && + mClipboard->HasImage() ) { + // Get image buffer from clipboard. + RefPtr image = mClipboard->GetImage(); + + // Encode according to MIME type. + nsRefPtr drawable = new gfxSurfaceDrawable(image, image->GetSize()); + nsCOMPtr imageContainer(image::ImageOps::CreateFromDrawable(drawable)); + nsCOMPtr imgTool = do_GetService(NS_IMGTOOLS_CID); + + nsCOMPtr byteStream; + imgTool->EncodeImage(imageContainer, flavorStr, EmptyString(), getter_AddRefs(byteStream)); + + // Set transferable. + nsresult rv = aTransferable->SetTransferData(flavorStr, + byteStream, + sizeof(nsIInputStream*)); + if (NS_WARN_IF(NS_FAILED(rv))) { + continue; + } + break; + } + } } return NS_OK; @@ -105,7 +259,7 @@ nsClipboard::EmptyClipboard(int32_t aWhichClipboard) return NS_ERROR_NOT_IMPLEMENTED; } if (XRE_IsParentProcess()) { - mClipboard.Truncate(0); + mClipboard->Clear(); } else { ContentChild::GetSingleton()->SendEmptyClipboard(aWhichClipboard); } @@ -123,7 +277,27 @@ nsClipboard::HasDataMatchingFlavors(const char **aFlavorList, return NS_ERROR_NOT_IMPLEMENTED; } if (XRE_IsParentProcess()) { - *aHasType = !mClipboard.IsEmpty(); + // Retrieve the union of all aHasType in aFlavorList + for (uint32_t i = 0; i < aLength; ++i) { + const char *flavor = aFlavorList[i]; + if (!flavor) { + continue; + } + if (!strcmp(flavor, kUnicodeMime) && mClipboard->HasText()) { + *aHasType = true; + } else if (!strcmp(flavor, kHTMLMime) && mClipboard->HasHTML()) { + *aHasType = true; + } else if (!strcmp(flavor, kJPEGImageMime) || + !strcmp(flavor, kJPGImageMime) || + !strcmp(flavor, kPNGImageMime) || + !strcmp(flavor, kGIFImageMime)) { + // We will encode the image into any format you want, so we don't + // need to check each specific format + if (mClipboard->HasImage()) { + *aHasType = true; + } + } + } } else { nsRefPtr clipboardProxy = new nsClipboardProxy(); return clipboardProxy->HasDataMatchingFlavors(aFlavorList, aLength, aWhichClipboard, aHasType); diff --git a/widget/gonk/nsClipboard.h b/widget/gonk/nsClipboard.h index 6adcd4ee5f..cd2e0dbd54 100644 --- a/widget/gonk/nsClipboard.h +++ b/widget/gonk/nsClipboard.h @@ -1,21 +1,27 @@ -/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public +/* 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/. */ #ifndef nsClipbard_h__ #define nsClipbard_h__ +#include "GonkClipboardData.h" +#include "mozilla/UniquePtr.h" #include "nsIClipboard.h" class nsClipboard final : public nsIClipboard { - nsAutoString mClipboard; public: NS_DECL_ISUPPORTS NS_DECL_NSICLIPBOARD nsClipboard(); + +protected: + ~nsClipboard() {} + +private: + mozilla::UniquePtr mClipboard; }; #endif diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index a6dbfc368b..ccc0bc8aad 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -4311,7 +4311,7 @@ inline static mozilla::HangMonitor::ActivityType ActivityTypeForMessage(UINT msg // and http://msdn.microsoft.com/en-us/library/ms633573%28VS.85%29.aspx LRESULT CALLBACK nsWindow::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - ipc::CancelCPOWs(); + mozilla::ipc::CancelCPOWs(); HangMonitor::NotifyActivity(ActivityTypeForMessage(msg));