BlobParent* nsIContentParent::GetOrCreateActorForBlob(nsIDOMBlob* aBlob) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aBlob); // If the blob represents a remote blob for this ContentParent then we can // simply pass its actor back here. const auto* domFile = static_cast<DOMFile*>(aBlob); nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(domFile->Impl()); if (remoteBlob) { BlobParent* actor = remoteBlob->GetBlobParent(); if (actor && actor->GetContentManager() == this) { return actor; } } // All blobs shared between processes must be immutable. nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(aBlob); if (!mutableBlob || NS_FAILED(mutableBlob->SetMutable(false))) { NS_WARNING("Failed to make blob immutable!"); return nullptr; } // XXX This is only safe so long as all blob implementations in our tree // inherit DOMFileImplBase. If that ever changes then this will need to grow // a real interface or something. const auto* blob = static_cast<DOMFileImplBase*>(domFile->Impl()); ChildBlobConstructorParams params; if (blob->IsSizeUnknown() || blob->IsDateUnknown()) { // We don't want to call GetSize or GetLastModifiedDate // yet since that may stat a file on the main thread // here. Instead we'll learn the size lazily from the // other process. params = MysteryBlobConstructorParams(); } else { nsString contentType; nsresult rv = aBlob->GetType(contentType); NS_ENSURE_SUCCESS(rv, nullptr); uint64_t length; rv = aBlob->GetSize(&length); NS_ENSURE_SUCCESS(rv, nullptr); nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob); if (file) { FileBlobConstructorParams fileParams; rv = file->GetMozLastModifiedDate(&fileParams.modDate()); NS_ENSURE_SUCCESS(rv, nullptr); rv = file->GetName(fileParams.name()); NS_ENSURE_SUCCESS(rv, nullptr); fileParams.contentType() = contentType; fileParams.length() = length; params = fileParams; } else { NormalBlobConstructorParams blobParams; blobParams.contentType() = contentType; blobParams.length() = length; params = blobParams; } } BlobParent* actor = BlobParent::Create(this, aBlob); NS_ENSURE_TRUE(actor, nullptr); return SendPBlobConstructor(actor, params) ? actor : nullptr; }
BlobChild* nsIContentChild::GetOrCreateActorForBlob(nsIDOMBlob* aBlob) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aBlob); // If the blob represents a remote blob then we can simply pass its actor back // here. const auto* domFile = static_cast<DOMFile*>(aBlob); nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(domFile->Impl()); if (remoteBlob) { BlobChild* actor = remoteBlob->GetBlobChild(); MOZ_ASSERT(actor); if (actor->GetContentManager() == this) { return actor; } } // All blobs shared between processes must be immutable. nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(aBlob); if (!mutableBlob || NS_FAILED(mutableBlob->SetMutable(false))) { NS_WARNING("Failed to make blob immutable!"); return nullptr; } #ifdef DEBUG { // XXX This is only safe so long as all blob implementations in our tree // inherit DOMFileImplBase. If that ever changes then this will need to // grow a real interface or something. const auto* blob = static_cast<DOMFileImplBase*>(domFile->Impl()); MOZ_ASSERT(!blob->IsSizeUnknown()); MOZ_ASSERT(!blob->IsDateUnknown()); } #endif ParentBlobConstructorParams params; nsString contentType; nsresult rv = aBlob->GetType(contentType); NS_ENSURE_SUCCESS(rv, nullptr); uint64_t length; rv = aBlob->GetSize(&length); NS_ENSURE_SUCCESS(rv, nullptr); nsCOMPtr<nsIInputStream> stream; rv = aBlob->GetInternalStream(getter_AddRefs(stream)); NS_ENSURE_SUCCESS(rv, nullptr); InputStreamParams inputStreamParams; nsTArray<mozilla::ipc::FileDescriptor> fds; SerializeInputStream(stream, inputStreamParams, fds); MOZ_ASSERT(fds.IsEmpty()); params.optionalInputStreamParams() = inputStreamParams; nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob); if (file) { FileBlobConstructorParams fileParams; rv = file->GetName(fileParams.name()); NS_ENSURE_SUCCESS(rv, nullptr); rv = file->GetMozLastModifiedDate(&fileParams.modDate()); NS_ENSURE_SUCCESS(rv, nullptr); fileParams.contentType() = contentType; fileParams.length() = length; params.blobParams() = fileParams; } else { NormalBlobConstructorParams blobParams; blobParams.contentType() = contentType; blobParams.length() = length; params.blobParams() = blobParams; } BlobChild* actor = BlobChild::Create(this, aBlob); NS_ENSURE_TRUE(actor, nullptr); return SendPBlobConstructor(actor, params) ? actor : nullptr; }
BlobParent* ContentParent::GetOrCreateActorForBlob(nsIDOMBlob* aBlob) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(aBlob, "Null pointer!"); nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(aBlob); if (remoteBlob) { BlobParent* actor = static_cast<BlobParent*>( static_cast<PBlobParent*>(remoteBlob->GetPBlob())); NS_ASSERTION(actor, "Null actor?!"); return actor; } // XXX This is only safe so long as all blob implementations in our tree // inherit nsDOMFileBase. If that ever changes then this will need to grow // a real interface or something. const nsDOMFileBase* blob = static_cast<nsDOMFileBase*>(aBlob); BlobConstructorParams params; if (blob->IsSizeUnknown()) { // We don't want to call GetSize yet since that may stat a file on the main // thread here. Instead we'll learn the size lazily from the other process. params = MysteryBlobConstructorParams(); } else { nsString contentType; nsresult rv = aBlob->GetType(contentType); NS_ENSURE_SUCCESS(rv, nullptr); PRUint64 length; rv = aBlob->GetSize(&length); NS_ENSURE_SUCCESS(rv, nullptr); nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob); if (file) { FileBlobConstructorParams fileParams; rv = file->GetName(fileParams.name()); NS_ENSURE_SUCCESS(rv, nullptr); fileParams.contentType() = contentType; fileParams.length() = length; params = fileParams; } else { NormalBlobConstructorParams blobParams; blobParams.contentType() = contentType; blobParams.length() = length; params = blobParams; } } BlobParent* actor = BlobParent::Create(aBlob); NS_ENSURE_TRUE(actor, nullptr); if (!SendPBlobConstructor(actor, params)) { return nullptr; } return actor; }