michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "InputStreamUtils.h" michael@0: michael@0: #include "nsIIPCSerializableInputStream.h" michael@0: michael@0: #include "mozilla/Assertions.h" michael@0: #include "mozilla/dom/ipc/Blob.h" michael@0: #include "nsComponentManagerUtils.h" michael@0: #include "nsDebug.h" michael@0: #include "nsID.h" michael@0: #include "nsIDOMFile.h" michael@0: #include "nsIXULRuntime.h" michael@0: #include "nsMIMEInputStream.h" michael@0: #include "nsMultiplexInputStream.h" michael@0: #include "nsNetCID.h" michael@0: #include "nsStringStream.h" michael@0: #include "nsThreadUtils.h" michael@0: #include "nsXULAppAPI.h" michael@0: michael@0: using mozilla::dom::BlobChild; michael@0: using mozilla::dom::BlobParent; michael@0: michael@0: namespace { michael@0: michael@0: NS_DEFINE_CID(kStringInputStreamCID, NS_STRINGINPUTSTREAM_CID); michael@0: NS_DEFINE_CID(kFileInputStreamCID, NS_LOCALFILEINPUTSTREAM_CID); michael@0: NS_DEFINE_CID(kPartialFileInputStreamCID, NS_PARTIALLOCALFILEINPUTSTREAM_CID); michael@0: NS_DEFINE_CID(kBufferedInputStreamCID, NS_BUFFEREDINPUTSTREAM_CID); michael@0: NS_DEFINE_CID(kMIMEInputStreamCID, NS_MIMEINPUTSTREAM_CID); michael@0: NS_DEFINE_CID(kMultiplexInputStreamCID, NS_MULTIPLEXINPUTSTREAM_CID); michael@0: michael@0: } // anonymous namespace michael@0: michael@0: namespace mozilla { michael@0: namespace ipc { michael@0: michael@0: void michael@0: SerializeInputStream(nsIInputStream* aInputStream, michael@0: InputStreamParams& aParams, michael@0: nsTArray& aFileDescriptors) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: MOZ_ASSERT(aInputStream); michael@0: michael@0: nsCOMPtr serializable = michael@0: do_QueryInterface(aInputStream); michael@0: if (!serializable) { michael@0: MOZ_CRASH("Input stream is not serializable!"); michael@0: } michael@0: michael@0: serializable->Serialize(aParams, aFileDescriptors); michael@0: michael@0: if (aParams.type() == InputStreamParams::T__None) { michael@0: MOZ_CRASH("Serialize failed!"); michael@0: } michael@0: } michael@0: michael@0: void michael@0: SerializeInputStream(nsIInputStream* aInputStream, michael@0: OptionalInputStreamParams& aParams, michael@0: nsTArray& aFileDescriptors) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: michael@0: if (aInputStream) { michael@0: InputStreamParams params; michael@0: SerializeInputStream(aInputStream, params, aFileDescriptors); michael@0: aParams = params; michael@0: } michael@0: else { michael@0: aParams = mozilla::void_t(); michael@0: } michael@0: } michael@0: michael@0: already_AddRefed michael@0: DeserializeInputStream(const InputStreamParams& aParams, michael@0: const nsTArray& aFileDescriptors) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: michael@0: nsCOMPtr serializable; michael@0: michael@0: switch (aParams.type()) { michael@0: case InputStreamParams::TStringInputStreamParams: michael@0: serializable = do_CreateInstance(kStringInputStreamCID); michael@0: break; michael@0: michael@0: case InputStreamParams::TFileInputStreamParams: michael@0: serializable = do_CreateInstance(kFileInputStreamCID); michael@0: break; michael@0: michael@0: case InputStreamParams::TPartialFileInputStreamParams: michael@0: serializable = do_CreateInstance(kPartialFileInputStreamCID); michael@0: break; michael@0: michael@0: case InputStreamParams::TBufferedInputStreamParams: michael@0: serializable = do_CreateInstance(kBufferedInputStreamCID); michael@0: break; michael@0: michael@0: case InputStreamParams::TMIMEInputStreamParams: michael@0: serializable = do_CreateInstance(kMIMEInputStreamCID); michael@0: break; michael@0: michael@0: case InputStreamParams::TMultiplexInputStreamParams: michael@0: serializable = do_CreateInstance(kMultiplexInputStreamCID); michael@0: break; michael@0: michael@0: // When the input stream already exists in this process, all we need to do michael@0: // is retrieve the original instead of sending any data over the wire. michael@0: case InputStreamParams::TRemoteInputStreamParams: { michael@0: nsCOMPtr domBlob; michael@0: const RemoteInputStreamParams& params = michael@0: aParams.get_RemoteInputStreamParams(); michael@0: michael@0: domBlob = params.remoteBlobParent() ? michael@0: static_cast(params.remoteBlobParent())->GetBlob() : michael@0: static_cast(params.remoteBlobChild())->GetBlob(); michael@0: michael@0: MOZ_ASSERT(domBlob, "Invalid blob contents"); michael@0: michael@0: // If fetching the internal stream fails, we ignore it and return a michael@0: // null stream. michael@0: nsCOMPtr stream; michael@0: nsresult rv = domBlob->GetInternalStream(getter_AddRefs(stream)); michael@0: if (NS_FAILED(rv) || !stream) { michael@0: NS_WARNING("Couldn't obtain a valid stream from the blob"); michael@0: } michael@0: return stream.forget(); michael@0: } michael@0: michael@0: default: michael@0: MOZ_ASSERT(false, "Unknown params!"); michael@0: return nullptr; michael@0: } michael@0: michael@0: MOZ_ASSERT(serializable); michael@0: michael@0: if (!serializable->Deserialize(aParams, aFileDescriptors)) { michael@0: MOZ_ASSERT(false, "Deserialize failed!"); michael@0: return nullptr; michael@0: } michael@0: michael@0: nsCOMPtr stream = do_QueryInterface(serializable); michael@0: MOZ_ASSERT(stream); michael@0: michael@0: return stream.forget(); michael@0: } michael@0: michael@0: already_AddRefed michael@0: DeserializeInputStream(const OptionalInputStreamParams& aParams, michael@0: const nsTArray& aFileDescriptors) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: michael@0: nsCOMPtr stream; michael@0: michael@0: switch (aParams.type()) { michael@0: case OptionalInputStreamParams::Tvoid_t: michael@0: // Leave stream null. michael@0: break; michael@0: michael@0: case OptionalInputStreamParams::TInputStreamParams: michael@0: stream = DeserializeInputStream(aParams.get_InputStreamParams(), michael@0: aFileDescriptors); michael@0: break; michael@0: michael@0: default: michael@0: MOZ_ASSERT(false, "Unknown params!"); michael@0: } michael@0: michael@0: return stream.forget(); michael@0: } michael@0: michael@0: } // namespace ipc michael@0: } // namespace mozilla