/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* vim: set sw=4 ts=8 et 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_Blob_h #define mozilla_dom_ipc_Blob_h #include "mozilla/Attributes.h" #include "mozilla/dom/PBlobChild.h" #include "mozilla/dom/PBlobParent.h" #include "mozilla/dom/PBlobStreamChild.h" #include "mozilla/dom/PBlobStreamParent.h" #include "mozilla/dom/PContent.h" #include "nsAutoPtr.h" #include "nsCOMPtr.h" #include "nsTArray.h" #include "nsThreadUtils.h" class nsIDOMBlob; class nsIIPCSerializableInputStream; class nsIInputStream; namespace mozilla { namespace dom { namespace ipc { enum ActorFlavorEnum { Parent = 0, Child }; template struct BlobTraits { }; template <> struct BlobTraits { typedef mozilla::dom::PBlobParent ProtocolType; typedef mozilla::dom::PBlobStreamParent StreamType; // BaseType on the parent side is a bit more complicated than for the child // side. In the case of nsIInputStreams backed by files we need to ensure that // the files are actually opened and closed on a background thread before we // can send their file handles across to the child. The child process could // crash during this process so we need to make sure we cancel the intended // response in such a case. We do that by holding an array of // nsRevocableEventPtr. If the child crashes then this actor will be destroyed // and the nsRevocableEventPtr destructor will cancel any stream events that // are currently in flight. class BaseType : public ProtocolType { protected: BaseType() { } virtual ~BaseType() { } // Each instance of this class will be dispatched to the network stream // thread pool to run the first time where it will open the file input // stream. It will then dispatch itself back to the main thread to send the // child process its response (assuming that the child has not crashed). The // runnable will then dispatch itself to the thread pool again in order to // close the file input stream. class OpenStreamRunnable : public nsRunnable { friend class nsRevocableEventPtr; public: NS_DECL_NSIRUNNABLE OpenStreamRunnable(BaseType* aOwner, StreamType* aActor, nsIInputStream* aStream, nsIIPCSerializableInputStream* aSerializable, nsIEventTarget* aTarget); private: #ifdef DEBUG void Revoke(); #else void Revoke() { mRevoked = true; } #endif // Only safe to access these two pointers if mRevoked is false! BaseType* mOwner; StreamType* mActor; nsCOMPtr mStream; nsCOMPtr mSerializable; nsCOMPtr mTarget; bool mRevoked; bool mClosing; }; friend class OpenStreamRunnable; void NoteRunnableCompleted(OpenStreamRunnable* aRunnable); nsTArray > mOpenStreamRunnables; }; }; template <> struct BlobTraits { typedef mozilla::dom::PBlobChild ProtocolType; typedef mozilla::dom::PBlobStreamChild StreamType; class BaseType : public ProtocolType { protected: BaseType() { } virtual ~BaseType() { } }; }; template class RemoteBlob; template class Blob : public BlobTraits::BaseType { friend class RemoteBlob; public: typedef typename BlobTraits::ProtocolType ProtocolType; typedef typename BlobTraits::StreamType StreamType; typedef typename BlobTraits::BaseType BaseType; typedef RemoteBlob RemoteBlobType; typedef mozilla::ipc::IProtocolManager< mozilla::ipc::RPCChannel::RPCListener>::ActorDestroyReason ActorDestroyReason; typedef mozilla::dom::BlobConstructorParams BlobConstructorParams; protected: nsIDOMBlob* mBlob; RemoteBlobType* mRemoteBlob; bool mOwnsBlob; bool mBlobIsFile; public: // This create function is called on the sending side. static Blob* Create(nsIDOMBlob* aBlob) { return new Blob(aBlob); } // This create function is called on the receiving side. static Blob* Create(const BlobConstructorParams& aParams); // Get the blob associated with this actor. This may always be called on the // sending side. It may also be called on the receiving side unless this is a // "mystery" blob that has not yet received a SetMysteryBlobInfo() call. already_AddRefed GetBlob(); // Use this for files. bool SetMysteryBlobInfo(const nsString& aName, const nsString& aContentType, PRUint64 aLength); // Use this for non-file blobs. bool SetMysteryBlobInfo(const nsString& aContentType, PRUint64 aLength); private: // This constructor is called on the sending side. Blob(nsIDOMBlob* aBlob); // This constructor is called on the receiving side. Blob(const BlobConstructorParams& aParams); void SetRemoteBlob(nsRefPtr& aRemoteBlob); void NoteDyingRemoteBlob(); // These methods are only called by the IPDL message machinery. virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; virtual bool RecvResolveMystery(const ResolveMysteryParams& aParams) MOZ_OVERRIDE; virtual bool RecvPBlobStreamConstructor(StreamType* aActor) MOZ_OVERRIDE; virtual StreamType* AllocPBlobStream() MOZ_OVERRIDE; virtual bool DeallocPBlobStream(StreamType* aActor) MOZ_OVERRIDE; }; } // namespace ipc typedef mozilla::dom::ipc::Blob BlobChild; typedef mozilla::dom::ipc::Blob BlobParent; } // namespace dom } // namespace mozilla #endif // mozilla_dom_ipc_Blob_h