2012-08-02 10:02:29 +04:00
|
|
|
/* 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/. */
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "BlobChild.h"
|
|
|
|
#include "BlobParent.h"
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "BackgroundParent.h"
|
2014-04-24 08:43:57 +04:00
|
|
|
#include "ContentChild.h"
|
|
|
|
#include "ContentParent.h"
|
|
|
|
#include "FileDescriptorSetChild.h"
|
|
|
|
#include "jsapi.h"
|
|
|
|
#include "mozilla/Assertions.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "mozilla/ClearOnShutdown.h"
|
2014-04-24 08:43:57 +04:00
|
|
|
#include "mozilla/DebugOnly.h"
|
|
|
|
#include "mozilla/Monitor.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "mozilla/Mutex.h"
|
2014-04-24 08:43:57 +04:00
|
|
|
#include "mozilla/unused.h"
|
2014-10-08 20:15:23 +04:00
|
|
|
#include "mozilla/dom/File.h"
|
2014-06-11 09:44:03 +04:00
|
|
|
#include "mozilla/dom/nsIContentParent.h"
|
2014-06-11 09:44:06 +04:00
|
|
|
#include "mozilla/dom/nsIContentChild.h"
|
2014-04-24 08:43:57 +04:00
|
|
|
#include "mozilla/dom/PBlobStreamChild.h"
|
|
|
|
#include "mozilla/dom/PBlobStreamParent.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
|
2014-04-24 08:43:57 +04:00
|
|
|
#include "mozilla/ipc/InputStreamUtils.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "mozilla/ipc/PBackgroundChild.h"
|
|
|
|
#include "mozilla/ipc/PBackgroundParent.h"
|
|
|
|
#include "mozilla/ipc/PFileDescriptorSetParent.h"
|
|
|
|
#include "nsDataHashtable.h"
|
|
|
|
#include "nsHashKeys.h"
|
|
|
|
#include "nsID.h"
|
2012-08-02 10:02:29 +04:00
|
|
|
#include "nsIInputStream.h"
|
2012-08-16 08:02:32 +04:00
|
|
|
#include "nsIIPCSerializableInputStream.h"
|
2013-08-04 21:51:18 +04:00
|
|
|
#include "nsIMultiplexInputStream.h"
|
2012-08-02 10:02:29 +04:00
|
|
|
#include "nsIRemoteBlob.h"
|
|
|
|
#include "nsISeekableStream.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "nsIUUIDGenerator.h"
|
2014-04-24 08:43:57 +04:00
|
|
|
#include "nsNetCID.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "nsServiceManagerUtils.h"
|
2012-08-02 10:02:29 +04:00
|
|
|
#include "nsThreadUtils.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "nsXULAppAPI.h"
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
#include "BackgroundChild.h" // BackgroundChild::GetForCurrentThread().
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define DISABLE_ASSERTS_FOR_FUZZING 0
|
|
|
|
|
|
|
|
#if DISABLE_ASSERTS_FOR_FUZZING
|
|
|
|
#define ASSERT_UNLESS_FUZZING(...) do { } while (0)
|
|
|
|
#else
|
|
|
|
#define ASSERT_UNLESS_FUZZING(...) MOZ_ASSERT(false, __VA_ARGS__)
|
|
|
|
#endif
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2012-10-25 22:45:15 +04:00
|
|
|
#define PRIVATE_REMOTE_INPUT_STREAM_IID \
|
|
|
|
{0x30c7699f, 0x51d2, 0x48c8, {0xad, 0x56, 0xc0, 0x16, 0xd7, 0x6f, 0x71, 0x27}}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
|
|
|
|
2012-08-16 08:02:32 +04:00
|
|
|
using namespace mozilla::ipc;
|
2012-08-02 10:02:29 +04:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
const char kUUIDGeneratorContractId[] = "@mozilla.org/uuid-generator;1";
|
|
|
|
|
|
|
|
StaticRefPtr<nsIUUIDGenerator> gUUIDGenerator;
|
|
|
|
|
|
|
|
GeckoProcessType gProcessType = GeckoProcessType_Invalid;
|
|
|
|
|
|
|
|
void
|
|
|
|
CommonStartup()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
gProcessType = XRE_GetProcessType();
|
|
|
|
MOZ_ASSERT(gProcessType != GeckoProcessType_Invalid);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIUUIDGenerator> uuidGen = do_GetService(kUUIDGeneratorContractId);
|
|
|
|
MOZ_RELEASE_ASSERT(uuidGen);
|
|
|
|
|
|
|
|
gUUIDGenerator = uuidGen;
|
|
|
|
ClearOnShutdown(&gUUIDGenerator);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class ManagerType>
|
|
|
|
struct ConcreteManagerTypeTraits;
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct ConcreteManagerTypeTraits<nsIContentChild>
|
|
|
|
{
|
|
|
|
typedef ContentChild Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct ConcreteManagerTypeTraits<PBackgroundChild>
|
|
|
|
{
|
|
|
|
typedef PBackgroundChild Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct ConcreteManagerTypeTraits<nsIContentParent>
|
|
|
|
{
|
|
|
|
typedef ContentParent Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct ConcreteManagerTypeTraits<PBackgroundParent>
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
typedef PBackgroundParent Type;
|
2014-04-24 08:43:57 +04:00
|
|
|
};
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void
|
|
|
|
AssertCorrectThreadForManager(nsIContentChild* aManager)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
AssertCorrectThreadForManager(nsIContentParent* aManager)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
AssertCorrectThreadForManager(PBackgroundChild* aManager)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (aManager) {
|
|
|
|
PBackgroundChild* backgroundChild = BackgroundChild::GetForCurrentThread();
|
|
|
|
MOZ_ASSERT(backgroundChild);
|
|
|
|
MOZ_ASSERT(backgroundChild == aManager);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
AssertCorrectThreadForManager(PBackgroundParent* aManager)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
|
|
|
AssertIsOnBackgroundThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t
|
|
|
|
ActorManagerProcessID(nsIContentParent* aManager)
|
|
|
|
{
|
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
|
|
|
|
return reinterpret_cast<intptr_t>(aManager);
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t
|
|
|
|
ActorManagerProcessID(PBackgroundParent* aManager)
|
|
|
|
{
|
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
|
|
|
|
return BackgroundParent::GetRawContentParentForComparison(aManager);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
EventTargetIsOnCurrentThread(nsIEventTarget* aEventTarget)
|
|
|
|
{
|
|
|
|
if (!aEventTarget) {
|
|
|
|
return NS_IsMainThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool current;
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aEventTarget->IsOnCurrentThread(¤t)));
|
|
|
|
|
|
|
|
return current;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that a nsCOMPtr/nsRefPtr is released on the target thread.
|
2013-08-04 21:51:18 +04:00
|
|
|
template <template <class> class SmartPtr, class T>
|
|
|
|
void
|
2014-09-27 03:21:57 +04:00
|
|
|
ReleaseOnTarget(SmartPtr<T>& aDoomed, nsIEventTarget* aTarget)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aDoomed);
|
|
|
|
MOZ_ASSERT(!EventTargetIsOnCurrentThread(aTarget));
|
|
|
|
|
|
|
|
T* doomedRaw;
|
|
|
|
aDoomed.forget(&doomedRaw);
|
|
|
|
|
|
|
|
auto* doomedSupports = static_cast<nsISupports*>(doomedRaw);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIRunnable> releaseRunnable =
|
|
|
|
NS_NewNonOwningRunnableMethod(doomedSupports, &nsISupports::Release);
|
|
|
|
MOZ_ASSERT(releaseRunnable);
|
|
|
|
|
|
|
|
if (aTarget) {
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aTarget->Dispatch(releaseRunnable,
|
|
|
|
NS_DISPATCH_NORMAL)));
|
|
|
|
} else {
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(releaseRunnable)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class ManagerType>
|
|
|
|
PFileDescriptorSetParent*
|
|
|
|
ConstructFileDescriptorSet(ManagerType* aManager,
|
|
|
|
const nsTArray<FileDescriptor>& aFDs)
|
2013-08-04 21:51:18 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
typedef typename ConcreteManagerTypeTraits<ManagerType>::Type
|
|
|
|
ConcreteManagerType;
|
|
|
|
|
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
|
|
|
|
if (aFDs.IsEmpty()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2013-08-04 21:51:18 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
auto* concreteManager = static_cast<ConcreteManagerType*>(aManager);
|
2013-08-04 21:51:18 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
PFileDescriptorSetParent* fdSet =
|
|
|
|
concreteManager->SendPFileDescriptorSetConstructor(aFDs[0]);
|
|
|
|
if (!fdSet) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (uint32_t index = 1; index < aFDs.Length(); index++) {
|
|
|
|
if (!fdSet->SendAddFileDescriptor(aFDs[index])) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2013-08-04 21:51:18 +04:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
return fdSet;
|
2013-08-04 21:51:18 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
class NS_NO_VTABLE IPrivateRemoteInputStream
|
|
|
|
: public nsISupports
|
2012-10-25 22:45:15 +04:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
NS_DECLARE_STATIC_IID_ACCESSOR(PRIVATE_REMOTE_INPUT_STREAM_IID)
|
|
|
|
|
|
|
|
// This will return the underlying stream.
|
|
|
|
virtual nsIInputStream*
|
|
|
|
BlockAndGetInternalStream() = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_DEFINE_STATIC_IID_ACCESSOR(IPrivateRemoteInputStream,
|
|
|
|
PRIVATE_REMOTE_INPUT_STREAM_IID)
|
|
|
|
|
2013-08-04 21:51:18 +04:00
|
|
|
// This class exists to keep a blob alive at least as long as its internal
|
|
|
|
// stream.
|
2014-09-27 03:21:57 +04:00
|
|
|
class BlobInputStreamTether MOZ_FINAL
|
|
|
|
: public nsIMultiplexInputStream
|
|
|
|
, public nsISeekableStream
|
|
|
|
, public nsIIPCSerializableInputStream
|
2013-08-04 21:51:18 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIInputStream> mStream;
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> mBlobImpl;
|
2013-08-04 21:51:18 +04:00
|
|
|
|
|
|
|
nsIMultiplexInputStream* mWeakMultiplexStream;
|
|
|
|
nsISeekableStream* mWeakSeekableStream;
|
|
|
|
nsIIPCSerializableInputStream* mWeakSerializableStream;
|
|
|
|
|
|
|
|
public:
|
|
|
|
NS_DECL_THREADSAFE_ISUPPORTS
|
|
|
|
NS_FORWARD_NSIINPUTSTREAM(mStream->)
|
|
|
|
NS_FORWARD_SAFE_NSIMULTIPLEXINPUTSTREAM(mWeakMultiplexStream)
|
|
|
|
NS_FORWARD_SAFE_NSISEEKABLESTREAM(mWeakSeekableStream)
|
|
|
|
NS_FORWARD_SAFE_NSIIPCSERIALIZABLEINPUTSTREAM(mWeakSerializableStream)
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
BlobInputStreamTether(nsIInputStream* aStream, FileImpl* aBlobImpl)
|
2014-09-27 03:21:57 +04:00
|
|
|
: mStream(aStream)
|
|
|
|
, mBlobImpl(aBlobImpl)
|
|
|
|
, mWeakMultiplexStream(nullptr)
|
|
|
|
, mWeakSeekableStream(nullptr)
|
|
|
|
, mWeakSerializableStream(nullptr)
|
2013-08-04 21:51:18 +04:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(aStream);
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(aBlobImpl);
|
2013-08-04 21:51:18 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIMultiplexInputStream> multiplexStream =
|
|
|
|
do_QueryInterface(aStream);
|
|
|
|
if (multiplexStream) {
|
|
|
|
MOZ_ASSERT(SameCOMIdentity(aStream, multiplexStream));
|
|
|
|
mWeakMultiplexStream = multiplexStream;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(aStream);
|
|
|
|
if (seekableStream) {
|
|
|
|
MOZ_ASSERT(SameCOMIdentity(aStream, seekableStream));
|
|
|
|
mWeakSeekableStream = seekableStream;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIIPCSerializableInputStream> serializableStream =
|
|
|
|
do_QueryInterface(aStream);
|
|
|
|
if (serializableStream) {
|
|
|
|
MOZ_ASSERT(SameCOMIdentity(aStream, serializableStream));
|
|
|
|
mWeakSerializableStream = serializableStream;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
private:
|
|
|
|
~BlobInputStreamTether()
|
|
|
|
{ }
|
2013-08-04 21:51:18 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMPL_ADDREF(BlobInputStreamTether)
|
|
|
|
NS_IMPL_RELEASE(BlobInputStreamTether)
|
|
|
|
|
|
|
|
NS_INTERFACE_MAP_BEGIN(BlobInputStreamTether)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
|
|
|
|
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIMultiplexInputStream,
|
|
|
|
mWeakMultiplexStream)
|
|
|
|
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, mWeakSeekableStream)
|
|
|
|
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
|
|
|
|
mWeakSerializableStream)
|
|
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
|
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
class RemoteInputStream MOZ_FINAL
|
|
|
|
: public nsIInputStream
|
|
|
|
, public nsISeekableStream
|
|
|
|
, public nsIIPCSerializableInputStream
|
|
|
|
, public IPrivateRemoteInputStream
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
Monitor mMonitor;
|
2012-08-02 10:02:29 +04:00
|
|
|
nsCOMPtr<nsIInputStream> mStream;
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> mBlobImpl;
|
2014-09-27 03:21:57 +04:00
|
|
|
nsCOMPtr<nsIEventTarget> mEventTarget;
|
2013-08-04 21:51:18 +04:00
|
|
|
nsISeekableStream* mWeakSeekableStream;
|
2012-08-02 10:02:29 +04:00
|
|
|
|
|
|
|
public:
|
2013-07-19 06:21:20 +04:00
|
|
|
NS_DECL_THREADSAFE_ISUPPORTS
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
explicit RemoteInputStream(FileImpl* aBlobImpl)
|
2014-09-27 03:21:57 +04:00
|
|
|
: mMonitor("RemoteInputStream.mMonitor")
|
|
|
|
, mBlobImpl(aBlobImpl)
|
|
|
|
, mWeakSeekableStream(nullptr)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(IsOnOwningThread());
|
|
|
|
MOZ_ASSERT(aBlobImpl);
|
|
|
|
|
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
mEventTarget = do_GetCurrentThread();
|
|
|
|
MOZ_ASSERT(mEventTarget);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
IsOnOwningThread() const
|
|
|
|
{
|
|
|
|
return EventTargetIsOnCurrentThread(mEventTarget);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
AssertIsOnOwningThread() const
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(IsOnOwningThread());
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
2012-09-21 21:26:13 +04:00
|
|
|
void
|
2014-03-25 22:37:13 +04:00
|
|
|
Serialize(InputStreamParams& aParams,
|
|
|
|
FileDescriptorArray& /* aFileDescriptors */)
|
2012-09-21 21:26:13 +04:00
|
|
|
{
|
2014-10-07 23:26:59 +04:00
|
|
|
MOZ_RELEASE_ASSERT(mBlobImpl);
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsCOMPtr<nsIRemoteBlob> remote = do_QueryInterface(mBlobImpl);
|
2012-09-21 21:26:13 +04:00
|
|
|
MOZ_ASSERT(remote);
|
|
|
|
|
2014-10-07 23:26:59 +04:00
|
|
|
BlobChild* actor = remote->GetBlobChild();
|
|
|
|
MOZ_ASSERT(actor);
|
|
|
|
|
|
|
|
aParams = RemoteInputStreamParams(actor->ParentID());
|
2012-09-21 21:26:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2014-10-07 23:26:59 +04:00
|
|
|
Deserialize(const InputStreamParams& /* aParams */,
|
2014-03-25 22:37:13 +04:00
|
|
|
const FileDescriptorArray& /* aFileDescriptors */)
|
2012-09-21 21:26:13 +04:00
|
|
|
{
|
|
|
|
// See InputStreamUtils.cpp to see how deserialization of a
|
|
|
|
// RemoteInputStream is special-cased.
|
2013-06-29 05:38:30 +04:00
|
|
|
MOZ_CRASH("RemoteInputStream should never be deserialized");
|
2012-09-21 21:26:13 +04:00
|
|
|
}
|
|
|
|
|
2012-08-02 10:02:29 +04:00
|
|
|
void
|
|
|
|
SetStream(nsIInputStream* aStream)
|
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
2012-08-02 10:02:29 +04:00
|
|
|
MOZ_ASSERT(aStream);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIInputStream> stream = aStream;
|
|
|
|
nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(aStream);
|
|
|
|
|
2013-08-04 21:51:18 +04:00
|
|
|
MOZ_ASSERT_IF(seekableStream, SameCOMIdentity(aStream, seekableStream));
|
|
|
|
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MonitorAutoLock lock(mMonitor);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
|
|
|
MOZ_ASSERT(!mStream);
|
2013-08-04 21:51:18 +04:00
|
|
|
MOZ_ASSERT(!mWeakSeekableStream);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
|
|
|
mStream.swap(stream);
|
2013-08-04 21:51:18 +04:00
|
|
|
mWeakSeekableStream = seekableStream;
|
2012-08-02 10:02:29 +04:00
|
|
|
|
|
|
|
mMonitor.Notify();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD
|
|
|
|
Close() MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
nsresult rv = BlockAndWaitForStream();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> blobImpl;
|
2014-09-27 03:21:57 +04:00
|
|
|
mBlobImpl.swap(blobImpl);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
|
|
|
rv = mStream->Close();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD
|
2012-08-22 19:56:38 +04:00
|
|
|
Available(uint64_t* aAvailable) MOZ_OVERRIDE
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
2014-10-07 23:26:59 +04:00
|
|
|
if (!IsOnOwningThread()) {
|
|
|
|
nsresult rv = BlockAndWaitForStream();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
rv = mStream->Available(aAvailable);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (NS_IsMainThread()) {
|
|
|
|
NS_WARNING("Someone is trying to do main-thread I/O...");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
// See if we already have our real stream.
|
|
|
|
nsCOMPtr<nsIInputStream> inputStream;
|
|
|
|
{
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
|
|
|
|
inputStream = mStream;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we do then just call through.
|
|
|
|
if (inputStream) {
|
|
|
|
rv = inputStream->Available(aAvailable);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the stream is already closed then we can't do anything.
|
|
|
|
if (!mBlobImpl) {
|
2012-08-02 10:02:29 +04:00
|
|
|
return NS_BASE_STREAM_CLOSED;
|
|
|
|
}
|
|
|
|
|
2014-10-07 23:26:59 +04:00
|
|
|
// Otherwise fake it...
|
|
|
|
NS_WARNING("Available() called before real stream has been delivered, "
|
|
|
|
"guessing the amount of data available!");
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
ErrorResult error;
|
|
|
|
*aAvailable = mBlobImpl->GetSize(error);
|
|
|
|
if (NS_WARN_IF(error.Failed())) {
|
|
|
|
return error.ErrorCode();
|
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD
|
2012-08-22 19:56:38 +04:00
|
|
|
Read(char* aBuffer, uint32_t aCount, uint32_t* aResult) MOZ_OVERRIDE
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
|
|
|
nsresult rv = BlockAndWaitForStream();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
rv = mStream->Read(aBuffer, aCount, aResult);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD
|
2012-08-22 19:56:38 +04:00
|
|
|
ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount,
|
|
|
|
uint32_t* aResult) MOZ_OVERRIDE
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
|
|
|
nsresult rv = BlockAndWaitForStream();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
rv = mStream->ReadSegments(aWriter, aClosure, aCount, aResult);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD
|
|
|
|
IsNonBlocking(bool* aNonBlocking) MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aNonBlocking);
|
|
|
|
|
|
|
|
*aNonBlocking = false;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD
|
2012-08-22 19:56:38 +04:00
|
|
|
Seek(int32_t aWhence, int64_t aOffset) MOZ_OVERRIDE
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
|
|
|
nsresult rv = BlockAndWaitForStream();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2013-08-04 21:51:18 +04:00
|
|
|
if (!mWeakSeekableStream) {
|
2012-08-02 10:02:29 +04:00
|
|
|
NS_WARNING("Underlying blob stream is not seekable!");
|
|
|
|
return NS_ERROR_NO_INTERFACE;
|
|
|
|
}
|
|
|
|
|
2013-08-04 21:51:18 +04:00
|
|
|
rv = mWeakSeekableStream->Seek(aWhence, aOffset);
|
2012-08-02 10:02:29 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD
|
2014-09-27 03:21:57 +04:00
|
|
|
Tell(int64_t* aResult) MOZ_OVERRIDE
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
2012-10-25 22:45:15 +04:00
|
|
|
// We can cheat here and assume that we're going to start at 0 if we don't
|
|
|
|
// yet have our stream. Though, really, this should abort since most input
|
|
|
|
// streams could block here.
|
2014-09-27 03:21:57 +04:00
|
|
|
if (IsOnOwningThread() && !mStream) {
|
2012-10-25 22:45:15 +04:00
|
|
|
*aResult = 0;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-08-02 10:02:29 +04:00
|
|
|
nsresult rv = BlockAndWaitForStream();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2013-08-04 21:51:18 +04:00
|
|
|
if (!mWeakSeekableStream) {
|
2012-08-02 10:02:29 +04:00
|
|
|
NS_WARNING("Underlying blob stream is not seekable!");
|
|
|
|
return NS_ERROR_NO_INTERFACE;
|
|
|
|
}
|
|
|
|
|
2013-08-04 21:51:18 +04:00
|
|
|
rv = mWeakSeekableStream->Tell(aResult);
|
2012-08-02 10:02:29 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD
|
2014-09-27 03:21:57 +04:00
|
|
|
SetEOF() MOZ_OVERRIDE
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
|
|
|
nsresult rv = BlockAndWaitForStream();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2013-08-04 21:51:18 +04:00
|
|
|
if (!mWeakSeekableStream) {
|
2012-08-02 10:02:29 +04:00
|
|
|
NS_WARNING("Underlying blob stream is not seekable!");
|
|
|
|
return NS_ERROR_NO_INTERFACE;
|
|
|
|
}
|
|
|
|
|
2013-08-04 21:51:18 +04:00
|
|
|
rv = mWeakSeekableStream->SetEOF();
|
2012-08-02 10:02:29 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-25 22:45:15 +04:00
|
|
|
virtual nsIInputStream*
|
2014-09-27 03:21:57 +04:00
|
|
|
BlockAndGetInternalStream() MOZ_OVERRIDE
|
2012-10-25 22:45:15 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(!IsOnOwningThread());
|
2012-10-25 22:45:15 +04:00
|
|
|
|
|
|
|
nsresult rv = BlockAndWaitForStream();
|
|
|
|
NS_ENSURE_SUCCESS(rv, nullptr);
|
|
|
|
|
|
|
|
return mStream;
|
|
|
|
}
|
|
|
|
|
2012-08-02 10:02:29 +04:00
|
|
|
private:
|
2014-09-27 03:21:57 +04:00
|
|
|
~RemoteInputStream()
|
2013-08-04 21:51:18 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
if (!IsOnOwningThread()) {
|
2013-08-04 21:51:18 +04:00
|
|
|
mStream = nullptr;
|
|
|
|
mWeakSeekableStream = nullptr;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
if (mBlobImpl) {
|
|
|
|
ReleaseOnTarget(mBlobImpl, mEventTarget);
|
|
|
|
}
|
2013-08-04 21:51:18 +04:00
|
|
|
}
|
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
|
|
|
void
|
|
|
|
ReallyBlockAndWaitForStream()
|
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(!IsOnOwningThread());
|
|
|
|
|
|
|
|
DebugOnly<bool> waited;
|
2012-10-25 22:45:15 +04:00
|
|
|
|
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MonitorAutoLock lock(mMonitor);
|
2012-10-25 22:45:15 +04:00
|
|
|
|
|
|
|
waited = !mStream;
|
|
|
|
|
|
|
|
while (!mStream) {
|
|
|
|
mMonitor.Wait();
|
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
2012-10-25 22:45:15 +04:00
|
|
|
|
|
|
|
MOZ_ASSERT(mStream);
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2013-08-04 21:51:18 +04:00
|
|
|
if (waited && mWeakSeekableStream) {
|
2012-10-25 22:45:15 +04:00
|
|
|
int64_t position;
|
2013-08-04 21:51:18 +04:00
|
|
|
MOZ_ASSERT(NS_SUCCEEDED(mWeakSeekableStream->Tell(&position)),
|
2012-10-25 22:45:15 +04:00
|
|
|
"Failed to determine initial stream position!");
|
|
|
|
MOZ_ASSERT(!position, "Stream not starting at 0!");
|
|
|
|
}
|
|
|
|
#endif
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
BlockAndWaitForStream()
|
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
if (IsOnOwningThread()) {
|
|
|
|
NS_WARNING("Blocking the owning thread is not supported!");
|
2012-08-02 10:02:29 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ReallyBlockAndWaitForStream();
|
2012-10-25 22:45:15 +04:00
|
|
|
|
2012-08-02 10:02:29 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
IsSeekableStream()
|
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
if (IsOnOwningThread()) {
|
2012-08-02 10:02:29 +04:00
|
|
|
if (!mStream) {
|
|
|
|
NS_WARNING("Don't know if this stream is seekable yet!");
|
|
|
|
return true;
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
} else {
|
2012-08-02 10:02:29 +04:00
|
|
|
ReallyBlockAndWaitForStream();
|
|
|
|
}
|
|
|
|
|
2013-08-04 21:51:18 +04:00
|
|
|
return !!mWeakSeekableStream;
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-07-19 06:21:20 +04:00
|
|
|
NS_IMPL_ADDREF(RemoteInputStream)
|
|
|
|
NS_IMPL_RELEASE(RemoteInputStream)
|
2012-08-16 08:02:32 +04:00
|
|
|
|
|
|
|
NS_INTERFACE_MAP_BEGIN(RemoteInputStream)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
|
2012-09-21 21:26:13 +04:00
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableInputStream)
|
2012-08-16 08:02:32 +04:00
|
|
|
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, IsSeekableStream())
|
|
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
|
2012-10-25 22:45:15 +04:00
|
|
|
NS_INTERFACE_MAP_ENTRY(IPrivateRemoteInputStream)
|
2012-08-16 08:02:32 +04:00
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
class InputStreamChild MOZ_FINAL
|
|
|
|
: public PBlobStreamChild
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
|
|
|
nsRefPtr<RemoteInputStream> mRemoteStream;
|
|
|
|
|
|
|
|
public:
|
2014-09-27 03:21:57 +04:00
|
|
|
explicit
|
|
|
|
InputStreamChild(RemoteInputStream* aRemoteStream)
|
|
|
|
: mRemoteStream(aRemoteStream)
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(aRemoteStream);
|
2014-09-27 03:21:57 +04:00
|
|
|
aRemoteStream->AssertIsOnOwningThread();
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
InputStreamChild()
|
2014-09-27 03:21:57 +04:00
|
|
|
{ }
|
|
|
|
|
|
|
|
~InputStreamChild()
|
|
|
|
{ }
|
2012-08-02 10:02:29 +04:00
|
|
|
|
|
|
|
private:
|
|
|
|
// This method is only called by the IPDL message machinery.
|
|
|
|
virtual bool
|
2014-03-25 22:37:13 +04:00
|
|
|
Recv__delete__(const InputStreamParams& aParams,
|
|
|
|
const OptionalFileDescriptorSet& aFDs) MOZ_OVERRIDE;
|
|
|
|
};
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
class InputStreamParent MOZ_FINAL
|
|
|
|
: public PBlobStreamParent
|
2014-03-25 22:37:13 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
public:
|
|
|
|
InputStreamParent()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
~InputStreamParent()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
private:
|
|
|
|
// This method is only called by the IPDL message machinery.
|
|
|
|
virtual void
|
|
|
|
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
// Nothing needs to be done here.
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
|
|
StaticAutoPtr<BlobParent::IDTable> BlobParent::sIDTable;
|
|
|
|
StaticAutoPtr<Mutex> BlobParent::sIDTableMutex;
|
|
|
|
|
|
|
|
class BlobParent::IDTableEntry MOZ_FINAL
|
|
|
|
{
|
|
|
|
const nsID mID;
|
|
|
|
const intptr_t mProcessID;
|
2014-10-08 20:15:23 +04:00
|
|
|
const nsRefPtr<FileImpl> mBlobImpl;
|
2014-03-25 22:37:13 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
public:
|
2014-09-27 03:21:57 +04:00
|
|
|
static already_AddRefed<IDTableEntry>
|
2014-10-08 20:15:23 +04:00
|
|
|
Create(const nsID& aID, intptr_t aProcessID, FileImpl* aBlobImpl)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(aBlobImpl);
|
|
|
|
|
|
|
|
DebugOnly<bool> isMutable;
|
|
|
|
MOZ_ASSERT(NS_SUCCEEDED(aBlobImpl->GetMutable(&isMutable)));
|
|
|
|
MOZ_ASSERT(!isMutable);
|
|
|
|
|
|
|
|
return GetOrCreateInternal(aID,
|
|
|
|
aProcessID,
|
|
|
|
aBlobImpl,
|
|
|
|
/* aMayCreate */ true,
|
2014-10-07 23:26:59 +04:00
|
|
|
/* aMayGet */ false,
|
|
|
|
/* aIgnoreProcessID */ false);
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
2014-03-25 22:37:13 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
static already_AddRefed<IDTableEntry>
|
|
|
|
Get(const nsID& aID, intptr_t aProcessID)
|
2014-09-18 03:36:01 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
return GetOrCreateInternal(aID,
|
|
|
|
aProcessID,
|
|
|
|
nullptr,
|
|
|
|
/* aMayCreate */ false,
|
2014-10-07 23:26:59 +04:00
|
|
|
/* aMayGet */ true,
|
|
|
|
/* aIgnoreProcessID */ false);
|
|
|
|
}
|
|
|
|
|
|
|
|
static already_AddRefed<IDTableEntry>
|
|
|
|
Get(const nsID& aID)
|
|
|
|
{
|
|
|
|
return GetOrCreateInternal(aID,
|
|
|
|
0,
|
|
|
|
nullptr,
|
|
|
|
/* aMayCreate */ false,
|
|
|
|
/* aMayGet */ true,
|
|
|
|
/* aIgnoreProcessID */ true);
|
2014-09-18 03:36:01 +04:00
|
|
|
}
|
2014-03-25 22:37:13 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
static already_AddRefed<IDTableEntry>
|
2014-10-08 20:15:23 +04:00
|
|
|
GetOrCreate(const nsID& aID, intptr_t aProcessID, FileImpl* aBlobImpl)
|
2014-09-27 03:21:57 +04:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(aBlobImpl);
|
2014-05-02 22:44:13 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
DebugOnly<bool> isMutable;
|
|
|
|
MOZ_ASSERT(NS_SUCCEEDED(aBlobImpl->GetMutable(&isMutable)));
|
|
|
|
MOZ_ASSERT(!isMutable);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return GetOrCreateInternal(aID,
|
|
|
|
aProcessID,
|
|
|
|
aBlobImpl,
|
|
|
|
/* aMayCreate */ true,
|
2014-10-07 23:26:59 +04:00
|
|
|
/* aMayGet */ true,
|
|
|
|
/* aIgnoreProcessID */ false);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
const nsID&
|
|
|
|
ID() const
|
|
|
|
{
|
|
|
|
return mID;
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t
|
|
|
|
ProcessID() const
|
|
|
|
{
|
|
|
|
return mProcessID;
|
|
|
|
}
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
FileImpl*
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobImpl() const
|
|
|
|
{
|
|
|
|
return mBlobImpl;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(IDTableEntry)
|
|
|
|
|
|
|
|
private:
|
2014-10-08 20:15:23 +04:00
|
|
|
IDTableEntry(const nsID& aID, intptr_t aProcessID, FileImpl* aBlobImpl);
|
2014-09-27 03:21:57 +04:00
|
|
|
~IDTableEntry();
|
|
|
|
|
|
|
|
static already_AddRefed<IDTableEntry>
|
|
|
|
GetOrCreateInternal(const nsID& aID,
|
|
|
|
intptr_t aProcessID,
|
2014-10-08 20:15:23 +04:00
|
|
|
FileImpl* aBlobImpl,
|
2014-09-27 03:21:57 +04:00
|
|
|
bool aMayCreate,
|
2014-10-07 23:26:59 +04:00
|
|
|
bool aMayGet,
|
|
|
|
bool aIgnoreProcessID);
|
2014-09-27 03:21:57 +04:00
|
|
|
};
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2012-10-25 22:45:15 +04:00
|
|
|
// 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
|
2014-09-27 03:21:57 +04:00
|
|
|
// then dispatch itself back to the owning thread to send the child process its
|
2012-10-25 22:45:15 +04:00
|
|
|
// 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.
|
2014-04-24 08:43:57 +04:00
|
|
|
class BlobParent::OpenStreamRunnable MOZ_FINAL
|
|
|
|
: public nsRunnable
|
2012-10-25 22:45:15 +04:00
|
|
|
{
|
|
|
|
friend class nsRevocableEventPtr<OpenStreamRunnable>;
|
|
|
|
|
|
|
|
// Only safe to access these pointers if mRevoked is false!
|
2014-04-24 08:43:57 +04:00
|
|
|
BlobParent* mBlobActor;
|
|
|
|
PBlobStreamParent* mStreamActor;
|
2012-10-25 22:45:15 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIInputStream> mStream;
|
|
|
|
nsCOMPtr<nsIIPCSerializableInputStream> mSerializable;
|
2014-09-27 03:21:57 +04:00
|
|
|
nsCOMPtr<nsIEventTarget> mActorTarget;
|
|
|
|
nsCOMPtr<nsIThread> mIOTarget;
|
2012-10-25 22:45:15 +04:00
|
|
|
|
|
|
|
bool mRevoked;
|
|
|
|
bool mClosing;
|
|
|
|
|
|
|
|
public:
|
2014-04-24 08:43:57 +04:00
|
|
|
OpenStreamRunnable(BlobParent* aBlobActor,
|
|
|
|
PBlobStreamParent* aStreamActor,
|
2012-10-25 22:45:15 +04:00
|
|
|
nsIInputStream* aStream,
|
|
|
|
nsIIPCSerializableInputStream* aSerializable,
|
2014-09-27 03:21:57 +04:00
|
|
|
nsIThread* aIOTarget)
|
|
|
|
: mBlobActor(aBlobActor)
|
|
|
|
, mStreamActor(aStreamActor)
|
|
|
|
, mStream(aStream)
|
|
|
|
, mSerializable(aSerializable)
|
|
|
|
, mIOTarget(aIOTarget)
|
|
|
|
, mRevoked(false)
|
|
|
|
, mClosing(false)
|
2012-10-25 22:45:15 +04:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(aBlobActor);
|
2014-09-27 03:21:57 +04:00
|
|
|
aBlobActor->AssertIsOnOwningThread();
|
2012-10-25 22:45:15 +04:00
|
|
|
MOZ_ASSERT(aStreamActor);
|
|
|
|
MOZ_ASSERT(aStream);
|
|
|
|
// aSerializable may be null.
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(aIOTarget);
|
2012-10-25 22:45:15 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
AssertIsOnBackgroundThread();
|
2012-10-25 22:45:15 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mActorTarget = do_GetCurrentThread();
|
|
|
|
MOZ_ASSERT(mActorTarget);
|
2012-10-25 22:45:15 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
2012-10-25 22:45:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
Dispatch()
|
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mIOTarget);
|
2012-10-25 22:45:15 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsresult rv = mIOTarget->Dispatch(this, NS_DISPATCH_NORMAL);
|
2012-10-25 22:45:15 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
NS_DECL_ISUPPORTS_INHERITED
|
|
|
|
|
2012-10-25 22:45:15 +04:00
|
|
|
private:
|
2014-09-27 03:21:57 +04:00
|
|
|
~OpenStreamRunnable()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
bool
|
|
|
|
IsOnOwningThread() const
|
|
|
|
{
|
|
|
|
return EventTargetIsOnCurrentThread(mActorTarget);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
AssertIsOnOwningThread() const
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(IsOnOwningThread());
|
|
|
|
}
|
|
|
|
|
2012-10-25 22:45:15 +04:00
|
|
|
void
|
|
|
|
Revoke()
|
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
2012-10-25 22:45:15 +04:00
|
|
|
#ifdef DEBUG
|
|
|
|
mBlobActor = nullptr;
|
|
|
|
mStreamActor = nullptr;
|
|
|
|
#endif
|
|
|
|
mRevoked = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
OpenStream()
|
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(!IsOnOwningThread());
|
2012-10-25 22:45:15 +04:00
|
|
|
MOZ_ASSERT(mStream);
|
|
|
|
|
|
|
|
if (!mSerializable) {
|
|
|
|
nsCOMPtr<IPrivateRemoteInputStream> remoteStream =
|
|
|
|
do_QueryInterface(mStream);
|
|
|
|
MOZ_ASSERT(remoteStream, "Must QI to IPrivateRemoteInputStream here!");
|
|
|
|
|
|
|
|
nsCOMPtr<nsIInputStream> realStream =
|
|
|
|
remoteStream->BlockAndGetInternalStream();
|
|
|
|
NS_ENSURE_TRUE(realStream, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
mSerializable = do_QueryInterface(realStream);
|
|
|
|
if (!mSerializable) {
|
|
|
|
MOZ_ASSERT(false, "Must be serializable!");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
mStream.swap(realStream);
|
|
|
|
}
|
|
|
|
|
|
|
|
// To force the stream open we call Available(). We don't actually care
|
|
|
|
// how much data is available.
|
|
|
|
uint64_t available;
|
|
|
|
if (NS_FAILED(mStream->Available(&available))) {
|
|
|
|
NS_WARNING("Available failed on this stream!");
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (mActorTarget) {
|
|
|
|
nsresult rv = mActorTarget->Dispatch(this, NS_DISPATCH_NORMAL);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
} else {
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(this)));
|
|
|
|
}
|
2012-10-25 22:45:15 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
CloseStream()
|
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(!IsOnOwningThread());
|
2012-10-25 22:45:15 +04:00
|
|
|
MOZ_ASSERT(mStream);
|
|
|
|
|
|
|
|
// Going to always release here.
|
|
|
|
nsCOMPtr<nsIInputStream> stream;
|
|
|
|
mStream.swap(stream);
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsCOMPtr<nsIThread> ioTarget;
|
|
|
|
mIOTarget.swap(ioTarget);
|
|
|
|
|
|
|
|
NS_WARN_IF_FALSE(NS_SUCCEEDED(stream->Close()), "Failed to close stream!");
|
|
|
|
|
|
|
|
nsCOMPtr<nsIRunnable> shutdownRunnable =
|
|
|
|
NS_NewRunnableMethod(ioTarget, &nsIThread::Shutdown);
|
|
|
|
MOZ_ASSERT(shutdownRunnable);
|
|
|
|
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(shutdownRunnable)));
|
2012-10-25 22:45:15 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
SendResponse()
|
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
2012-10-25 22:45:15 +04:00
|
|
|
MOZ_ASSERT(mStream);
|
|
|
|
MOZ_ASSERT(mSerializable);
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(mIOTarget);
|
2012-10-25 22:45:15 +04:00
|
|
|
MOZ_ASSERT(!mClosing);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIIPCSerializableInputStream> serializable;
|
|
|
|
mSerializable.swap(serializable);
|
|
|
|
|
|
|
|
if (mRevoked) {
|
|
|
|
MOZ_ASSERT(!mBlobActor);
|
|
|
|
MOZ_ASSERT(!mStreamActor);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
MOZ_ASSERT(mBlobActor);
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(mBlobActor->HasManager());
|
2012-10-25 22:45:15 +04:00
|
|
|
MOZ_ASSERT(mStreamActor);
|
|
|
|
|
|
|
|
InputStreamParams params;
|
2014-03-25 22:37:13 +04:00
|
|
|
nsAutoTArray<FileDescriptor, 10> fds;
|
|
|
|
serializable->Serialize(params, fds);
|
2012-10-25 22:45:15 +04:00
|
|
|
|
|
|
|
MOZ_ASSERT(params.type() != InputStreamParams::T__None);
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
PFileDescriptorSetParent* fdSet;
|
|
|
|
if (nsIContentParent* contentManager = mBlobActor->GetContentManager()) {
|
|
|
|
fdSet = ConstructFileDescriptorSet(contentManager, fds);
|
|
|
|
} else {
|
|
|
|
fdSet = ConstructFileDescriptorSet(mBlobActor->GetBackgroundManager(),
|
|
|
|
fds);
|
2014-03-25 22:37:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
OptionalFileDescriptorSet optionalFDs;
|
|
|
|
if (fdSet) {
|
|
|
|
optionalFDs = fdSet;
|
|
|
|
} else {
|
2014-09-27 03:21:57 +04:00
|
|
|
optionalFDs = void_t();
|
2014-03-25 22:37:13 +04:00
|
|
|
}
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
unused <<
|
|
|
|
PBlobStreamParent::Send__delete__(mStreamActor, params, optionalFDs);
|
2012-10-25 22:45:15 +04:00
|
|
|
|
|
|
|
mBlobActor->NoteRunnableCompleted(this);
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
mBlobActor = nullptr;
|
|
|
|
mStreamActor = nullptr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// If our luck is *really* bad then it is possible for the CloseStream() and
|
|
|
|
// nsIThread::Shutdown() functions to run before the Dispatch() call here
|
|
|
|
// finishes... Keep the thread alive until this method returns.
|
|
|
|
nsCOMPtr<nsIThread> kungFuDeathGrip = mIOTarget;
|
2012-10-25 22:45:15 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mClosing = true;
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsresult rv = mIOTarget->Dispatch(this, NS_DISPATCH_NORMAL);
|
2012-10-25 22:45:15 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
NS_IMETHOD
|
|
|
|
Run() MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mIOTarget);
|
|
|
|
|
|
|
|
if (IsOnOwningThread()) {
|
|
|
|
return SendResponse();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mClosing) {
|
|
|
|
return OpenStream();
|
|
|
|
}
|
|
|
|
|
|
|
|
return CloseStream();
|
|
|
|
}
|
2012-10-25 22:45:15 +04:00
|
|
|
};
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
NS_IMPL_ISUPPORTS_INHERITED0(BlobParent::OpenStreamRunnable, nsRunnable)
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
/*******************************************************************************
|
2014-09-27 03:21:57 +04:00
|
|
|
* BlobChild::RemoteBlobImpl Declaration
|
2014-04-24 08:43:57 +04:00
|
|
|
******************************************************************************/
|
2012-10-25 22:45:15 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
class BlobChild::RemoteBlobImpl MOZ_FINAL
|
2014-10-08 20:15:23 +04:00
|
|
|
: public FileImplBase
|
2014-09-27 03:21:57 +04:00
|
|
|
, public nsIRemoteBlob
|
2012-10-25 22:45:15 +04:00
|
|
|
{
|
2014-04-24 08:43:57 +04:00
|
|
|
class StreamHelper;
|
|
|
|
class SliceHelper;
|
2012-10-25 22:45:15 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
BlobChild* mActor;
|
2014-09-27 03:21:57 +04:00
|
|
|
nsCOMPtr<nsIEventTarget> mActorTarget;
|
2012-10-25 22:45:15 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
public:
|
2014-09-27 03:21:57 +04:00
|
|
|
RemoteBlobImpl(BlobChild* aActor,
|
|
|
|
const nsAString& aName,
|
|
|
|
const nsAString& aContentType,
|
|
|
|
uint64_t aLength,
|
|
|
|
uint64_t aModDate)
|
2014-10-08 20:15:23 +04:00
|
|
|
: FileImplBase(aName, aContentType, aLength, aModDate)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
CommonInit(aActor);
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2012-10-25 22:45:15 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
RemoteBlobImpl(BlobChild* aActor,
|
|
|
|
const nsAString& aContentType,
|
|
|
|
uint64_t aLength)
|
2014-10-08 20:15:23 +04:00
|
|
|
: FileImplBase(aContentType, aLength)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
CommonInit(aActor);
|
2012-10-25 22:45:15 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
explicit
|
|
|
|
RemoteBlobImpl(BlobChild* aActor)
|
2014-10-08 20:15:23 +04:00
|
|
|
: FileImplBase(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
CommonInit(aActor);
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2012-10-25 22:45:15 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
void
|
2014-09-27 03:21:57 +04:00
|
|
|
NoteDyingActor()
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(mActor);
|
|
|
|
mActor->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
mActor = nullptr;
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2013-01-18 00:17:33 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
NS_DECL_ISUPPORTS_INHERITED
|
2013-01-18 00:17:33 +04:00
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
virtual void
|
|
|
|
GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) MOZ_OVERRIDE;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
virtual already_AddRefed<FileImpl>
|
2014-10-08 20:15:22 +04:00
|
|
|
CreateSlice(uint64_t aStart, uint64_t aLength,
|
|
|
|
const nsAString& aContentType, ErrorResult& aRv) MOZ_OVERRIDE;
|
2013-01-18 00:17:33 +04:00
|
|
|
|
2014-06-26 20:47:44 +04:00
|
|
|
virtual nsresult
|
2014-04-24 08:43:57 +04:00
|
|
|
GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE;
|
2013-01-10 17:47:32 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
virtual int64_t
|
|
|
|
GetFileId() MOZ_OVERRIDE;
|
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
virtual int64_t GetLastModified(ErrorResult& aRv) MOZ_OVERRIDE;
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
virtual BlobChild*
|
|
|
|
GetBlobChild() MOZ_OVERRIDE;
|
|
|
|
|
|
|
|
virtual BlobParent*
|
|
|
|
GetBlobParent() MOZ_OVERRIDE;
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
private:
|
2014-09-27 03:21:57 +04:00
|
|
|
~RemoteBlobImpl()
|
2013-08-04 21:51:18 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT_IF(mActorTarget,
|
|
|
|
EventTargetIsOnCurrentThread(mActorTarget));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CommonInit(BlobChild* aActor)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
aActor->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
mActor = aActor;
|
|
|
|
mActorTarget = aActor->EventTarget();
|
|
|
|
|
|
|
|
mImmutable = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Destroy()
|
|
|
|
{
|
|
|
|
if (EventTargetIsOnCurrentThread(mActorTarget)) {
|
|
|
|
if (mActor) {
|
|
|
|
mActor->AssertIsOnOwningThread();
|
|
|
|
mActor->NoteDyingRemoteBlobImpl();
|
|
|
|
}
|
|
|
|
|
|
|
|
delete this;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIRunnable> destroyRunnable =
|
|
|
|
NS_NewNonOwningRunnableMethod(this, &RemoteBlobImpl::Destroy);
|
|
|
|
|
|
|
|
if (mActorTarget) {
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(mActorTarget->Dispatch(destroyRunnable,
|
|
|
|
NS_DISPATCH_NORMAL)));
|
|
|
|
} else {
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(destroyRunnable)));
|
2013-08-04 21:51:18 +04:00
|
|
|
}
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
};
|
2013-08-04 21:51:18 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
class BlobChild::RemoteBlobImpl::StreamHelper MOZ_FINAL
|
2014-04-24 08:43:57 +04:00
|
|
|
: public nsRunnable
|
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
Monitor mMonitor;
|
2014-04-24 08:43:57 +04:00
|
|
|
BlobChild* mActor;
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> mBlobImpl;
|
2014-04-24 08:43:57 +04:00
|
|
|
nsRefPtr<RemoteInputStream> mInputStream;
|
|
|
|
bool mDone;
|
2013-08-04 21:51:18 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
public:
|
2014-10-08 20:15:23 +04:00
|
|
|
StreamHelper(BlobChild* aActor, FileImpl* aBlobImpl)
|
2014-09-27 03:21:57 +04:00
|
|
|
: mMonitor("BlobChild::RemoteBlobImpl::StreamHelper::mMonitor")
|
2014-04-24 08:43:57 +04:00
|
|
|
, mActor(aActor)
|
2014-09-27 03:21:57 +04:00
|
|
|
, mBlobImpl(aBlobImpl)
|
2014-04-24 08:43:57 +04:00
|
|
|
, mDone(false)
|
|
|
|
{
|
|
|
|
// This may be created on any thread.
|
|
|
|
MOZ_ASSERT(aActor);
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(aBlobImpl);
|
2013-08-04 21:51:18 +04:00
|
|
|
}
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
nsresult
|
|
|
|
GetStream(nsIInputStream** aInputStream)
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
2014-04-24 08:43:57 +04:00
|
|
|
// This may be called on any thread.
|
|
|
|
MOZ_ASSERT(aInputStream);
|
|
|
|
MOZ_ASSERT(mActor);
|
|
|
|
MOZ_ASSERT(!mInputStream);
|
|
|
|
MOZ_ASSERT(!mDone);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (mActor->IsOnOwningThread()) {
|
2014-04-24 08:43:57 +04:00
|
|
|
RunInternal(false);
|
2014-09-27 03:21:57 +04:00
|
|
|
} else {
|
|
|
|
nsCOMPtr<nsIEventTarget> target = mActor->EventTarget();
|
|
|
|
if (!target) {
|
|
|
|
target = do_GetMainThread();
|
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(target);
|
|
|
|
|
|
|
|
nsresult rv = target->Dispatch(this, NS_DISPATCH_NORMAL);
|
2014-04-24 08:43:57 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
while (!mDone) {
|
|
|
|
lock.Wait();
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
MOZ_ASSERT(!mActor);
|
|
|
|
MOZ_ASSERT(mDone);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
if (!mInputStream) {
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
mInputStream.forget(aInputStream);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
NS_IMETHOD
|
2014-09-27 03:21:57 +04:00
|
|
|
Run() MOZ_OVERRIDE
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(mActor);
|
|
|
|
mActor->AssertIsOnOwningThread();
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
RunInternal(true);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void
|
|
|
|
RunInternal(bool aNotify)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mActor);
|
2014-09-27 03:21:57 +04:00
|
|
|
mActor->AssertIsOnOwningThread();
|
2014-04-24 08:43:57 +04:00
|
|
|
MOZ_ASSERT(!mInputStream);
|
|
|
|
MOZ_ASSERT(!mDone);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsRefPtr<RemoteInputStream> stream = new RemoteInputStream(mBlobImpl);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
InputStreamChild* streamActor = new InputStreamChild(stream);
|
|
|
|
if (mActor->SendPBlobStreamConstructor(streamActor)) {
|
|
|
|
stream.swap(mInputStream);
|
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
mActor = nullptr;
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
if (aNotify) {
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
mDone = true;
|
|
|
|
lock.Notify();
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
else {
|
|
|
|
mDone = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
class BlobChild::RemoteBlobImpl::SliceHelper MOZ_FINAL
|
2014-04-24 08:43:57 +04:00
|
|
|
: public nsRunnable
|
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
Monitor mMonitor;
|
2014-04-24 08:43:57 +04:00
|
|
|
BlobChild* mActor;
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> mSlice;
|
2014-04-24 08:43:57 +04:00
|
|
|
uint64_t mStart;
|
|
|
|
uint64_t mLength;
|
|
|
|
nsString mContentType;
|
|
|
|
bool mDone;
|
|
|
|
|
|
|
|
public:
|
2014-09-27 03:21:57 +04:00
|
|
|
explicit
|
|
|
|
SliceHelper(BlobChild* aActor)
|
|
|
|
: mMonitor("BlobChild::RemoteBlobImpl::SliceHelper::mMonitor")
|
2014-04-24 08:43:57 +04:00
|
|
|
, mActor(aActor)
|
|
|
|
, mStart(0)
|
|
|
|
, mLength(0)
|
|
|
|
, mDone(false)
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
2014-04-24 08:43:57 +04:00
|
|
|
// This may be created on any thread.
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
FileImpl*
|
2014-04-24 08:43:57 +04:00
|
|
|
GetSlice(uint64_t aStart,
|
|
|
|
uint64_t aLength,
|
2014-09-27 03:21:57 +04:00
|
|
|
const nsAString& aContentType)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
|
|
|
// This may be called on any thread.
|
|
|
|
MOZ_ASSERT(mActor);
|
|
|
|
MOZ_ASSERT(!mSlice);
|
|
|
|
MOZ_ASSERT(!mDone);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
mStart = aStart;
|
|
|
|
mLength = aLength;
|
|
|
|
mContentType = aContentType;
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (mActor->IsOnOwningThread()) {
|
2014-04-24 08:43:57 +04:00
|
|
|
RunInternal(false);
|
2014-09-27 03:21:57 +04:00
|
|
|
} else {
|
|
|
|
nsCOMPtr<nsIEventTarget> target = mActor->EventTarget();
|
|
|
|
if (!target) {
|
|
|
|
target = do_GetMainThread();
|
2014-06-27 07:46:34 +04:00
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(target);
|
|
|
|
|
|
|
|
nsresult rv = target->Dispatch(this, NS_DISPATCH_NORMAL);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
2014-06-27 07:46:34 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
while (!mDone) {
|
|
|
|
lock.Wait();
|
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
MOZ_ASSERT(!mActor);
|
|
|
|
MOZ_ASSERT(mDone);
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (NS_WARN_IF(!mSlice)) {
|
2014-06-27 07:46:34 +04:00
|
|
|
return nullptr;
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
2014-06-27 07:46:34 +04:00
|
|
|
return mSlice;
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
NS_IMETHOD
|
2014-09-27 03:21:57 +04:00
|
|
|
Run() MOZ_OVERRIDE
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(mActor);
|
|
|
|
mActor->AssertIsOnOwningThread();
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
RunInternal(true);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2014-02-08 04:14:59 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
private:
|
|
|
|
void
|
|
|
|
RunInternal(bool aNotify)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mActor);
|
2014-09-27 03:21:57 +04:00
|
|
|
mActor->AssertIsOnOwningThread();
|
2014-04-24 08:43:57 +04:00
|
|
|
MOZ_ASSERT(!mSlice);
|
|
|
|
MOZ_ASSERT(!mDone);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
NS_ENSURE_TRUE_VOID(mActor->HasManager());
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsID id;
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(gUUIDGenerator->GenerateUUIDInPlace(&id)));
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
ChildBlobConstructorParams params(
|
|
|
|
id,
|
|
|
|
NormalBlobConstructorParams(mContentType /* contentType */,
|
|
|
|
mLength /* length */));
|
2013-01-18 00:17:33 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
ParentBlobConstructorParams otherSideParams(
|
|
|
|
SlicedBlobConstructorParams(nullptr /* sourceParent */,
|
|
|
|
mActor /* sourceChild */,
|
|
|
|
id /* optionalID */,
|
|
|
|
mStart /* begin */,
|
|
|
|
mStart + mLength /* end */,
|
|
|
|
mContentType /* contentType */),
|
|
|
|
void_t() /* optionalInputStream */);
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobChild* newActor;
|
|
|
|
if (nsIContentChild* contentManager = mActor->GetContentManager()) {
|
|
|
|
newActor = SendSliceConstructor(contentManager, params, otherSideParams);
|
|
|
|
} else {
|
|
|
|
newActor = SendSliceConstructor(mActor->GetBackgroundManager(),
|
|
|
|
params,
|
|
|
|
otherSideParams);
|
|
|
|
}
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (newActor) {
|
|
|
|
mSlice = newActor->GetBlobImpl();
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
mActor = nullptr;
|
|
|
|
|
|
|
|
if (aNotify) {
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
mDone = true;
|
|
|
|
lock.Notify();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mDone = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/*******************************************************************************
|
2014-09-27 03:21:57 +04:00
|
|
|
* BlobChild::RemoteBlobImpl Implementation
|
2014-04-24 08:43:57 +04:00
|
|
|
******************************************************************************/
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
NS_IMPL_ADDREF(BlobChild::RemoteBlobImpl)
|
|
|
|
NS_IMPL_RELEASE_WITH_DESTROY(BlobChild::RemoteBlobImpl, Destroy())
|
|
|
|
NS_IMPL_QUERY_INTERFACE_INHERITED(BlobChild::RemoteBlobImpl,
|
2014-10-08 20:15:23 +04:00
|
|
|
FileImpl,
|
2014-09-27 03:21:57 +04:00
|
|
|
nsIRemoteBlob)
|
2014-09-13 20:12:19 +04:00
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
void
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobChild::
|
2014-10-08 20:15:22 +04:00
|
|
|
RemoteBlobImpl::GetMozFullPathInternal(nsAString& aFilePath,
|
|
|
|
ErrorResult& aRv)
|
2014-09-27 03:21:57 +04:00
|
|
|
{
|
|
|
|
if (!mActor) {
|
2014-10-08 20:15:22 +04:00
|
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
|
|
return;
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsString filePath;
|
|
|
|
if (!mActor->SendGetFilePath(&filePath)) {
|
2014-10-08 20:15:22 +04:00
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return;
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
aFilePath = filePath;
|
|
|
|
}
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
already_AddRefed<FileImpl>
|
2014-04-24 08:43:57 +04:00
|
|
|
BlobChild::
|
2014-10-08 20:15:22 +04:00
|
|
|
RemoteBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
|
|
|
|
const nsAString& aContentType, ErrorResult& aRv)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
|
|
|
if (!mActor) {
|
2014-10-08 20:15:22 +04:00
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
2014-04-24 08:43:57 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRefPtr<SliceHelper> helper = new SliceHelper(mActor);
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> impl = helper->GetSlice(aStart, aLength, aContentType);
|
2014-09-27 03:21:57 +04:00
|
|
|
if (NS_WARN_IF(!impl)) {
|
2014-10-08 20:15:22 +04:00
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
2014-06-27 07:46:34 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return impl.forget();
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-06-26 20:47:44 +04:00
|
|
|
nsresult
|
2014-04-24 08:43:57 +04:00
|
|
|
BlobChild::
|
2014-09-27 03:21:57 +04:00
|
|
|
RemoteBlobImpl::GetInternalStream(nsIInputStream** aStream)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
|
|
|
if (!mActor) {
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRefPtr<StreamHelper> helper = new StreamHelper(mActor, this);
|
|
|
|
return helper->GetStream(aStream);
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
int64_t
|
|
|
|
BlobChild::
|
|
|
|
RemoteBlobImpl::GetFileId()
|
|
|
|
{
|
|
|
|
int64_t fileId;
|
|
|
|
if (mActor && mActor->SendGetFileId(&fileId)) {
|
|
|
|
return fileId;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
int64_t
|
2014-04-24 08:43:57 +04:00
|
|
|
BlobChild::
|
2014-10-08 20:15:22 +04:00
|
|
|
RemoteBlobImpl::GetLastModified(ErrorResult& aRv)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
|
|
|
if (IsDateUnknown()) {
|
2014-10-08 20:15:22 +04:00
|
|
|
return 0;
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2014-10-08 20:15:22 +04:00
|
|
|
|
|
|
|
return mLastModificationDate;
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobChild*
|
|
|
|
BlobChild::
|
|
|
|
RemoteBlobImpl::GetBlobChild()
|
|
|
|
{
|
|
|
|
return mActor;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlobParent*
|
2014-04-24 08:43:57 +04:00
|
|
|
BlobChild::
|
2014-09-27 03:21:57 +04:00
|
|
|
RemoteBlobImpl::GetBlobParent()
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
return nullptr;
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* BlobChild
|
|
|
|
******************************************************************************/
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
BlobChild::BlobChild(nsIContentChild* aManager, FileImpl* aBlobImpl)
|
2014-09-27 03:21:57 +04:00
|
|
|
: mBackgroundManager(nullptr)
|
|
|
|
, mContentManager(aManager)
|
2014-09-13 20:12:19 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertCorrectThreadForManager(aManager);
|
2014-09-13 20:12:19 +04:00
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
CommonInit(aBlobImpl);
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
BlobChild::BlobChild(PBackgroundChild* aManager, FileImpl* aBlobImpl)
|
2014-09-27 03:21:57 +04:00
|
|
|
: mBackgroundManager(aManager)
|
|
|
|
, mContentManager(nullptr)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertCorrectThreadForManager(aManager);
|
2014-04-24 08:43:57 +04:00
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
CommonInit(aBlobImpl);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
mEventTarget = do_GetCurrentThread();
|
|
|
|
MOZ_ASSERT(mEventTarget);
|
|
|
|
}
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobChild::BlobChild(nsIContentChild* aManager, BlobChild* aOther)
|
|
|
|
: mBackgroundManager(nullptr)
|
|
|
|
, mContentManager(aManager)
|
|
|
|
{
|
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
|
|
|
|
CommonInit(aOther);
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobChild::BlobChild(PBackgroundChild* aManager, BlobChild* aOther)
|
|
|
|
: mBackgroundManager(aManager)
|
|
|
|
, mContentManager(nullptr)
|
|
|
|
{
|
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
CommonInit(aOther);
|
2014-06-26 20:47:44 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
mEventTarget = do_GetCurrentThread();
|
|
|
|
MOZ_ASSERT(mEventTarget);
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobChild::BlobChild(nsIContentChild* aManager,
|
|
|
|
const ChildBlobConstructorParams& aParams)
|
|
|
|
: mBackgroundManager(nullptr)
|
|
|
|
, mContentManager(aManager)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
|
|
|
|
CommonInit(aParams);
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobChild::BlobChild(PBackgroundChild* aManager,
|
|
|
|
const ChildBlobConstructorParams& aParams)
|
|
|
|
: mBackgroundManager(aManager)
|
|
|
|
, mContentManager(nullptr)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertCorrectThreadForManager(aManager);
|
2014-04-24 08:43:57 +04:00
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
CommonInit(aParams);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
mEventTarget = do_GetCurrentThread();
|
|
|
|
MOZ_ASSERT(mEventTarget);
|
|
|
|
}
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobChild::~BlobChild()
|
|
|
|
{
|
|
|
|
AssertIsOnOwningThread();
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_COUNT_DTOR(BlobChild);
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void
|
2014-10-08 20:15:23 +04:00
|
|
|
BlobChild::CommonInit(FileImpl* aBlobImpl)
|
2014-09-27 03:21:57 +04:00
|
|
|
{
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aBlobImpl);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_COUNT_CTOR(BlobChild);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mBlobImpl = aBlobImpl;
|
|
|
|
mRemoteBlobImpl = nullptr;
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mBlobImpl->AddRef();
|
|
|
|
mOwnsBlobImpl = true;
|
|
|
|
|
|
|
|
memset(&mParentID, 0, sizeof(mParentID));
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void
|
|
|
|
BlobChild::CommonInit(BlobChild* aOther)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aOther);
|
|
|
|
MOZ_ASSERT_IF(mContentManager, aOther->GetBackgroundManager());
|
|
|
|
MOZ_ASSERT_IF(mBackgroundManager, aOther->GetContentManager());
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_COUNT_CTOR(BlobChild);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> otherImpl = aOther->GetBlobImpl();
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(otherImpl);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsString contentType;
|
2014-10-08 20:15:22 +04:00
|
|
|
otherImpl->GetType(contentType);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
ErrorResult rv;
|
|
|
|
uint64_t length = otherImpl->GetSize(rv);
|
|
|
|
MOZ_ASSERT(!rv.Failed());
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsRefPtr<RemoteBlobImpl> remoteBlob;
|
|
|
|
if (otherImpl->IsFile()) {
|
|
|
|
nsString name;
|
2014-10-08 20:15:22 +04:00
|
|
|
otherImpl->GetName(name);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
uint64_t modDate = otherImpl->GetLastModified(rv);
|
|
|
|
MOZ_ASSERT(!rv.Failed());
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
remoteBlob = new RemoteBlobImpl(this, name, contentType, length, modDate);
|
|
|
|
} else {
|
|
|
|
remoteBlob = new RemoteBlobImpl(this, contentType, length);
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(remoteBlob);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
DebugOnly<bool> isMutable;
|
|
|
|
MOZ_ASSERT(NS_SUCCEEDED(remoteBlob->GetMutable(&isMutable)));
|
|
|
|
MOZ_ASSERT(!isMutable);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mRemoteBlobImpl = remoteBlob;
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
remoteBlob.forget(&mBlobImpl);
|
|
|
|
mOwnsBlobImpl = true;
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mParentID = aOther->ParentID();
|
2014-09-18 03:36:01 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void
|
|
|
|
BlobChild::CommonInit(const ChildBlobConstructorParams& aParams)
|
2014-09-18 03:36:01 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_COUNT_CTOR(BlobChild);
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
const AnyBlobConstructorParams& blobParams = aParams.blobParams();
|
|
|
|
|
|
|
|
AnyBlobConstructorParams::Type paramsType = blobParams.type();
|
|
|
|
MOZ_ASSERT(paramsType != AnyBlobConstructorParams::T__None &&
|
|
|
|
paramsType !=
|
|
|
|
AnyBlobConstructorParams::TKnownBlobConstructorParams);
|
|
|
|
|
|
|
|
nsRefPtr<RemoteBlobImpl> remoteBlob;
|
|
|
|
|
|
|
|
switch (paramsType) {
|
|
|
|
case AnyBlobConstructorParams::TNormalBlobConstructorParams: {
|
2014-09-18 03:36:01 +04:00
|
|
|
const NormalBlobConstructorParams& params =
|
2014-09-27 03:21:57 +04:00
|
|
|
blobParams.get_NormalBlobConstructorParams();
|
|
|
|
remoteBlob =
|
|
|
|
new RemoteBlobImpl(this, params.contentType(), params.length());
|
2014-09-18 03:36:01 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
case AnyBlobConstructorParams::TFileBlobConstructorParams: {
|
2014-09-18 03:36:01 +04:00
|
|
|
const FileBlobConstructorParams& params =
|
2014-09-27 03:21:57 +04:00
|
|
|
blobParams.get_FileBlobConstructorParams();
|
|
|
|
remoteBlob = new RemoteBlobImpl(this,
|
|
|
|
params.name(),
|
|
|
|
params.contentType(),
|
|
|
|
params.length(),
|
|
|
|
params.modDate());
|
2014-09-18 03:36:01 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
case AnyBlobConstructorParams::TMysteryBlobConstructorParams: {
|
|
|
|
remoteBlob = new RemoteBlobImpl(this);
|
2014-09-18 03:36:01 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
MOZ_CRASH("Unknown params!");
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(remoteBlob);
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
DebugOnly<bool> isMutable;
|
|
|
|
MOZ_ASSERT(NS_SUCCEEDED(remoteBlob->GetMutable(&isMutable)));
|
|
|
|
MOZ_ASSERT(!isMutable);
|
|
|
|
|
|
|
|
mRemoteBlobImpl = remoteBlob;
|
|
|
|
|
|
|
|
remoteBlob.forget(&mBlobImpl);
|
|
|
|
mOwnsBlobImpl = true;
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mParentID = aParams.id();
|
2014-09-18 03:36:01 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
void
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobChild::AssertIsOnOwningThread() const
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(IsOnOwningThread());
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
#endif // DEBUG
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
void
|
|
|
|
BlobChild::Startup(const FriendKey& /* aKey */)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(XRE_GetProcessType() != GeckoProcessType_Default);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
CommonStartup();
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
BlobChild*
|
2014-10-08 20:15:23 +04:00
|
|
|
BlobChild::GetOrCreate(nsIContentChild* aManager, FileImpl* aBlobImpl)
|
2014-09-27 03:21:57 +04:00
|
|
|
{
|
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
|
|
|
|
return GetOrCreateFromImpl(aManager, aBlobImpl);
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
BlobChild*
|
2014-10-08 20:15:23 +04:00
|
|
|
BlobChild::GetOrCreate(PBackgroundChild* aManager, FileImpl* aBlobImpl)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return GetOrCreateFromImpl(aManager, aBlobImpl);
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
BlobChild*
|
|
|
|
BlobChild::Create(nsIContentChild* aManager,
|
|
|
|
const ChildBlobConstructorParams& aParams)
|
|
|
|
{
|
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return CreateFromParams(aManager, aParams);
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
BlobChild*
|
|
|
|
BlobChild::Create(PBackgroundChild* aManager,
|
|
|
|
const ChildBlobConstructorParams& aParams)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return CreateFromParams(aManager, aParams);
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
template <class ChildManagerType>
|
|
|
|
BlobChild*
|
|
|
|
BlobChild::GetOrCreateFromImpl(ChildManagerType* aManager,
|
2014-10-08 20:15:23 +04:00
|
|
|
FileImpl* aBlobImpl)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
MOZ_ASSERT(aBlobImpl);
|
|
|
|
|
|
|
|
// If the blob represents a remote blob then we can simply pass its actor back
|
|
|
|
// here.
|
|
|
|
if (nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(aBlobImpl)) {
|
|
|
|
BlobChild* actor = MaybeGetActorFromRemoteBlob(remoteBlob, aManager);
|
|
|
|
if (actor) {
|
|
|
|
return actor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// All blobs shared between processes must be immutable.
|
|
|
|
if (NS_WARN_IF(NS_FAILED(aBlobImpl->SetMutable(false)))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(!aBlobImpl->IsSizeUnknown());
|
|
|
|
MOZ_ASSERT(!aBlobImpl->IsDateUnknown());
|
|
|
|
|
|
|
|
AnyBlobConstructorParams blobParams;
|
|
|
|
|
|
|
|
nsString contentType;
|
2014-10-08 20:15:22 +04:00
|
|
|
aBlobImpl->GetType(contentType);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
ErrorResult rv;
|
|
|
|
uint64_t length = aBlobImpl->GetSize(rv);
|
|
|
|
MOZ_ASSERT(!rv.Failed());
|
2014-04-24 08:43:57 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIInputStream> stream;
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
|
|
|
aBlobImpl->GetInternalStream(getter_AddRefs(stream))));
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (aBlobImpl->IsFile()) {
|
|
|
|
nsString name;
|
2014-10-08 20:15:22 +04:00
|
|
|
aBlobImpl->GetName(name);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
uint64_t modDate = aBlobImpl->GetLastModified(rv);
|
|
|
|
MOZ_ASSERT(!rv.Failed());
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
blobParams = FileBlobConstructorParams(name, contentType, length, modDate);
|
|
|
|
} else {
|
|
|
|
blobParams = NormalBlobConstructorParams(contentType, length);
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
InputStreamParams inputStreamParams;
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
nsTArray<FileDescriptor> fds;
|
2014-09-27 03:21:57 +04:00
|
|
|
SerializeInputStream(stream, inputStreamParams, fds);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(inputStreamParams.type() != InputStreamParams::T__None);
|
2014-04-24 08:43:57 +04:00
|
|
|
MOZ_ASSERT(fds.IsEmpty());
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobChild* actor = new BlobChild(aManager, aBlobImpl);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
ParentBlobConstructorParams params(blobParams, inputStreamParams);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (NS_WARN_IF(!aManager->SendPBlobConstructor(actor, params))) {
|
|
|
|
BlobChild::Destroy(actor);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return actor;
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
template <class ChildManagerType>
|
|
|
|
BlobChild*
|
|
|
|
BlobChild::CreateFromParams(ChildManagerType* aManager,
|
|
|
|
const ChildBlobConstructorParams& aParams)
|
2014-09-18 03:36:01 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
const AnyBlobConstructorParams& blobParams = aParams.blobParams();
|
|
|
|
|
|
|
|
switch (blobParams.type()) {
|
|
|
|
case AnyBlobConstructorParams::TNormalBlobConstructorParams:
|
|
|
|
case AnyBlobConstructorParams::TFileBlobConstructorParams:
|
|
|
|
case AnyBlobConstructorParams::TMysteryBlobConstructorParams: {
|
|
|
|
return new BlobChild(aManager, aParams);
|
|
|
|
}
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
case AnyBlobConstructorParams::TSlicedBlobConstructorParams: {
|
|
|
|
const SlicedBlobConstructorParams& params =
|
|
|
|
blobParams.get_SlicedBlobConstructorParams();
|
|
|
|
MOZ_ASSERT(params.optionalID().type() == OptionalID::Tvoid_t);
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
auto* actor =
|
|
|
|
const_cast<BlobChild*>(
|
|
|
|
static_cast<const BlobChild*>(params.sourceChild()));
|
|
|
|
MOZ_ASSERT(actor);
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> source = actor->GetBlobImpl();
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(source);
|
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
Optional<int64_t> start;
|
|
|
|
start.Construct(params.begin());
|
|
|
|
|
|
|
|
Optional<int64_t> end;
|
|
|
|
start.Construct(params.end());
|
|
|
|
|
|
|
|
ErrorResult rv;
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> slice =
|
2014-10-08 20:15:22 +04:00
|
|
|
source->Slice(start, end, params.contentType(), rv);
|
|
|
|
if (NS_WARN_IF(rv.Failed())) {
|
2014-09-27 03:21:57 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(slice->SetMutable(false)));
|
|
|
|
|
|
|
|
actor = new BlobChild(aManager, slice);
|
|
|
|
|
|
|
|
actor->mParentID = aParams.id();
|
|
|
|
|
|
|
|
return actor;
|
2014-09-18 03:36:01 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
case AnyBlobConstructorParams::TKnownBlobConstructorParams: {
|
|
|
|
MOZ_CRASH("Parent should never send this type!");
|
2014-09-18 03:36:01 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
MOZ_CRASH("Unknown params!");
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_CRASH("Should never get here!");
|
2014-09-18 03:36:01 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
template <class ChildManagerType>
|
|
|
|
BlobChild*
|
|
|
|
BlobChild::SendSliceConstructor(
|
|
|
|
ChildManagerType* aManager,
|
|
|
|
const ChildBlobConstructorParams& aParams,
|
|
|
|
const ParentBlobConstructorParams& aOtherSideParams)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobChild* newActor = BlobChild::Create(aManager, aParams);
|
|
|
|
MOZ_ASSERT(newActor);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (aManager->SendPBlobConstructor(newActor, aOtherSideParams)) {
|
|
|
|
if (gProcessType != GeckoProcessType_Default || !NS_IsMainThread()) {
|
|
|
|
newActor->SendWaitForSliceCreation();
|
|
|
|
}
|
|
|
|
return newActor;
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobChild::Destroy(newActor);
|
|
|
|
return nullptr;
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
BlobChild*
|
|
|
|
BlobChild::MaybeGetActorFromRemoteBlob(nsIRemoteBlob* aRemoteBlob,
|
|
|
|
nsIContentChild* aManager)
|
|
|
|
{
|
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aRemoteBlob);
|
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
|
|
|
|
if (BlobChild* actor = aRemoteBlob->GetBlobChild()) {
|
|
|
|
if (actor->GetContentManager() == aManager) {
|
|
|
|
return actor;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(actor->GetBackgroundManager());
|
|
|
|
|
|
|
|
actor = new BlobChild(aManager, actor);
|
|
|
|
|
|
|
|
ParentBlobConstructorParams params(
|
|
|
|
KnownBlobConstructorParams(actor->ParentID()) /* blobParams */,
|
|
|
|
void_t() /* optionalInputStream */);
|
|
|
|
|
|
|
|
aManager->SendPBlobConstructor(actor, params);
|
|
|
|
|
|
|
|
return actor;
|
2014-09-18 03:36:01 +04:00
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
BlobChild*
|
|
|
|
BlobChild::MaybeGetActorFromRemoteBlob(nsIRemoteBlob* aRemoteBlob,
|
|
|
|
PBackgroundChild* aManager)
|
|
|
|
{
|
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aRemoteBlob);
|
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
|
|
|
|
if (BlobChild* actor = aRemoteBlob->GetBlobChild()) {
|
|
|
|
if (actor->GetBackgroundManager() == aManager) {
|
|
|
|
return actor;
|
2014-09-18 03:36:01 +04:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
MOZ_ASSERT(actor->GetContentManager());
|
|
|
|
|
|
|
|
actor = new BlobChild(aManager, actor);
|
|
|
|
|
|
|
|
ParentBlobConstructorParams params(
|
|
|
|
KnownBlobConstructorParams(actor->ParentID()) /* blobParams */,
|
|
|
|
void_t() /* optionalInputStream */);
|
|
|
|
|
|
|
|
aManager->SendPBlobConstructor(actor, params);
|
|
|
|
|
|
|
|
return actor;
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
const nsID&
|
|
|
|
BlobChild::ParentID() const
|
|
|
|
{
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mRemoteBlobImpl);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return mParentID;
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
already_AddRefed<FileImpl>
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobChild::GetBlobImpl()
|
|
|
|
{
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mBlobImpl);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> blobImpl;
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// Remote blobs are held alive until the first call to GetBlobImpl. Thereafter
|
|
|
|
// we only hold a weak reference. Normal blobs are held alive until the actor
|
|
|
|
// is destroyed.
|
|
|
|
if (mRemoteBlobImpl && mOwnsBlobImpl) {
|
|
|
|
blobImpl = dont_AddRef(mBlobImpl);
|
|
|
|
mOwnsBlobImpl = false;
|
|
|
|
} else {
|
|
|
|
blobImpl = mBlobImpl;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(blobImpl);
|
|
|
|
|
|
|
|
return blobImpl.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
BlobChild::SetMysteryBlobInfo(const nsString& aName,
|
|
|
|
const nsString& aContentType,
|
|
|
|
uint64_t aLength,
|
|
|
|
uint64_t aLastModifiedDate)
|
|
|
|
{
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mBlobImpl);
|
|
|
|
MOZ_ASSERT(mRemoteBlobImpl);
|
|
|
|
MOZ_ASSERT(aLastModifiedDate != UINT64_MAX);
|
|
|
|
|
|
|
|
mBlobImpl->SetLazyData(aName, aContentType, aLength, aLastModifiedDate);
|
|
|
|
|
|
|
|
FileBlobConstructorParams params(aName, aContentType, aLength,
|
|
|
|
aLastModifiedDate);
|
|
|
|
return SendResolveMystery(params);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
BlobChild::SetMysteryBlobInfo(const nsString& aContentType, uint64_t aLength)
|
|
|
|
{
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mBlobImpl);
|
|
|
|
MOZ_ASSERT(mRemoteBlobImpl);
|
|
|
|
|
|
|
|
nsString voidString;
|
|
|
|
voidString.SetIsVoid(true);
|
|
|
|
|
|
|
|
mBlobImpl->SetLazyData(voidString, aContentType, aLength, UINT64_MAX);
|
|
|
|
|
|
|
|
NormalBlobConstructorParams params(aContentType, aLength);
|
|
|
|
return SendResolveMystery(params);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BlobChild::NoteDyingRemoteBlobImpl()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mBlobImpl);
|
|
|
|
MOZ_ASSERT(mRemoteBlobImpl);
|
|
|
|
MOZ_ASSERT(!mOwnsBlobImpl);
|
|
|
|
|
|
|
|
// This may be called on any thread due to the fact that RemoteBlobImpl is
|
|
|
|
// designed to be passed between threads. We must start the shutdown process
|
|
|
|
// on the owning thread, so we proxy here if necessary.
|
|
|
|
if (!IsOnOwningThread()) {
|
|
|
|
nsCOMPtr<nsIRunnable> runnable =
|
|
|
|
NS_NewNonOwningRunnableMethod(this, &BlobChild::NoteDyingRemoteBlobImpl);
|
|
|
|
|
|
|
|
if (mEventTarget) {
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(mEventTarget->Dispatch(runnable,
|
|
|
|
NS_DISPATCH_NORMAL)));
|
|
|
|
} else {
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable)));
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
return;
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// Must do this before calling Send__delete__ or we'll crash there trying to
|
|
|
|
// access a dangling pointer.
|
|
|
|
mBlobImpl = nullptr;
|
|
|
|
mRemoteBlobImpl = nullptr;
|
|
|
|
|
|
|
|
PBlobChild::Send__delete__(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
BlobChild::IsOnOwningThread() const
|
|
|
|
{
|
|
|
|
return EventTargetIsOnCurrentThread(mEventTarget);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BlobChild::ActorDestroy(ActorDestroyReason aWhy)
|
|
|
|
{
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
if (mRemoteBlobImpl) {
|
|
|
|
mRemoteBlobImpl->NoteDyingActor();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mBlobImpl && mOwnsBlobImpl) {
|
|
|
|
mBlobImpl->Release();
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
mBlobImpl = nullptr;
|
|
|
|
mRemoteBlobImpl = nullptr;
|
|
|
|
mBackgroundManager = nullptr;
|
|
|
|
mContentManager = nullptr;
|
|
|
|
mOwnsBlobImpl = false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
PBlobStreamChild*
|
|
|
|
BlobChild::AllocPBlobStreamChild()
|
|
|
|
{
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
return new InputStreamChild();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
BlobChild::DeallocPBlobStreamChild(PBlobStreamChild* aActor)
|
|
|
|
{
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
delete static_cast<InputStreamChild*>(aActor);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* BlobParent::RemoteBlob Declaration
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
class BlobParent::RemoteBlobImplBase
|
|
|
|
: public nsISupports
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
friend class BlobParent;
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
BlobParent* mActor;
|
2014-09-27 03:21:57 +04:00
|
|
|
nsCOMPtr<nsIEventTarget> mActorTarget;
|
|
|
|
bool mForwards;
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
protected:
|
|
|
|
RemoteBlobImplBase(BlobParent* aActor, bool aForwards)
|
|
|
|
: mActor(aActor)
|
|
|
|
, mActorTarget(aActor->EventTarget())
|
|
|
|
, mForwards(aForwards)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(aActor);
|
2014-09-27 03:21:57 +04:00
|
|
|
aActor->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MOZ_COUNT_CTOR(BlobParent::RemoteBlobImplBase);
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
virtual
|
|
|
|
~RemoteBlobImplBase()
|
2012-08-03 10:25:30 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT_IF(mActorTarget,
|
|
|
|
EventTargetIsOnCurrentThread(mActorTarget));
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_COUNT_DTOR(BlobParent::RemoteBlobImplBase);
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void
|
|
|
|
Destroy()
|
|
|
|
{
|
|
|
|
if (EventTargetIsOnCurrentThread(mActorTarget)) {
|
|
|
|
if (mActor) {
|
|
|
|
mActor->AssertIsOnOwningThread();
|
|
|
|
mActor->NoteDyingRemoteBlobImpl();
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
delete this;
|
|
|
|
return;
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsCOMPtr<nsIRunnable> destroyRunnable =
|
|
|
|
NS_NewNonOwningRunnableMethod(this, &RemoteBlobImplBase::Destroy);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (mActorTarget) {
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(mActorTarget->Dispatch(destroyRunnable,
|
|
|
|
NS_DISPATCH_NORMAL)));
|
|
|
|
} else {
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(destroyRunnable)));
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2012-08-03 10:25:30 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
private:
|
|
|
|
void
|
|
|
|
NoteDyingActor()
|
2012-08-03 10:25:30 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(mActor);
|
|
|
|
mActor->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
mActor = nullptr;
|
2012-08-03 10:25:30 +04:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
class BlobParent::RemoteBlobImpl MOZ_FINAL
|
|
|
|
: public RemoteBlobImplBase
|
2014-10-08 20:15:23 +04:00
|
|
|
, public FileImplBase
|
2014-09-27 03:21:57 +04:00
|
|
|
, public nsIRemoteBlob
|
|
|
|
{
|
|
|
|
friend class mozilla::dom::BlobParent;
|
|
|
|
|
|
|
|
class SliceHelper;
|
|
|
|
|
|
|
|
InputStreamParams mInputStreamParams;
|
|
|
|
|
|
|
|
public:
|
|
|
|
NS_DECL_ISUPPORTS_INHERITED
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
virtual already_AddRefed<FileImpl>
|
2014-10-08 20:15:22 +04:00
|
|
|
CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
|
|
|
|
ErrorResult& aRv) MOZ_OVERRIDE;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
virtual nsresult
|
|
|
|
GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE;
|
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
virtual int64_t
|
|
|
|
GetLastModified(ErrorResult& aRv) MOZ_OVERRIDE;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
virtual BlobChild*
|
|
|
|
GetBlobChild() MOZ_OVERRIDE;
|
|
|
|
|
|
|
|
virtual BlobParent*
|
|
|
|
GetBlobParent() MOZ_OVERRIDE;
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
private:
|
2014-09-27 03:21:57 +04:00
|
|
|
RemoteBlobImpl(BlobParent* aActor,
|
|
|
|
const InputStreamParams& aInputStreamParams,
|
|
|
|
const nsAString& aName,
|
|
|
|
const nsAString& aContentType,
|
|
|
|
uint64_t aLength,
|
|
|
|
uint64_t aModDate)
|
|
|
|
: RemoteBlobImplBase(aActor, /* aForwards */ false)
|
2014-10-08 20:15:23 +04:00
|
|
|
, FileImplBase(aName, aContentType, aLength, aModDate)
|
2013-01-18 00:17:33 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
CommonInit(aInputStreamParams);
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
RemoteBlobImpl(BlobParent* aActor,
|
|
|
|
const InputStreamParams& aInputStreamParams,
|
|
|
|
const nsAString& aContentType,
|
|
|
|
uint64_t aLength)
|
|
|
|
: RemoteBlobImplBase(aActor, /* aForwards */ false)
|
2014-10-08 20:15:23 +04:00
|
|
|
, FileImplBase(aContentType, aLength)
|
2014-09-27 03:21:57 +04:00
|
|
|
{
|
|
|
|
CommonInit(aInputStreamParams);
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
~RemoteBlobImpl()
|
|
|
|
{ }
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void
|
|
|
|
CommonInit(const InputStreamParams& aInputStreamParams)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aInputStreamParams.type() != InputStreamParams::T__None);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mInputStreamParams = aInputStreamParams;
|
|
|
|
|
|
|
|
mImmutable = true;
|
2013-01-18 00:17:33 +04:00
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
};
|
2013-01-18 00:17:33 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
class BlobParent::RemoteBlobImpl::SliceHelper MOZ_FINAL
|
2014-04-24 08:43:57 +04:00
|
|
|
: public nsRunnable
|
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
Monitor mMonitor;
|
2014-04-24 08:43:57 +04:00
|
|
|
BlobParent* mActor;
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> mSlice;
|
2014-04-24 08:43:57 +04:00
|
|
|
uint64_t mStart;
|
|
|
|
uint64_t mLength;
|
|
|
|
nsString mContentType;
|
|
|
|
bool mDone;
|
2013-01-18 00:17:33 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
public:
|
2014-09-27 03:21:57 +04:00
|
|
|
explicit
|
|
|
|
SliceHelper(BlobParent* aActor)
|
|
|
|
: mMonitor("BlobParent::RemoteBlobImpl::SliceHelper::mMonitor")
|
2014-04-24 08:43:57 +04:00
|
|
|
, mActor(aActor)
|
|
|
|
, mStart(0)
|
|
|
|
, mLength(0)
|
|
|
|
, mDone(false)
|
|
|
|
{
|
|
|
|
// This may be created on any thread.
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
}
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
FileImpl*
|
2014-04-24 08:43:57 +04:00
|
|
|
GetSlice(uint64_t aStart,
|
|
|
|
uint64_t aLength,
|
2014-09-27 03:21:57 +04:00
|
|
|
const nsAString& aContentType)
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
2014-04-24 08:43:57 +04:00
|
|
|
// This may be called on any thread.
|
|
|
|
MOZ_ASSERT(mActor);
|
|
|
|
MOZ_ASSERT(!mSlice);
|
|
|
|
MOZ_ASSERT(!mDone);
|
|
|
|
|
|
|
|
mStart = aStart;
|
|
|
|
mLength = aLength;
|
|
|
|
mContentType = aContentType;
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (mActor->IsOnOwningThread()) {
|
2014-04-24 08:43:57 +04:00
|
|
|
RunInternal(false);
|
2014-09-27 03:21:57 +04:00
|
|
|
} else {
|
|
|
|
nsCOMPtr<nsIEventTarget> target = mActor->EventTarget();
|
|
|
|
if (!target) {
|
|
|
|
target = do_GetMainThread();
|
2014-06-27 07:46:34 +04:00
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(target);
|
|
|
|
|
|
|
|
nsresult rv = target->Dispatch(this, NS_DISPATCH_NORMAL);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
2014-06-27 07:46:34 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
while (!mDone) {
|
|
|
|
lock.Wait();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(!mActor);
|
|
|
|
MOZ_ASSERT(mDone);
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (NS_WARN_IF(!mSlice)) {
|
2014-06-27 07:46:34 +04:00
|
|
|
return nullptr;
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-06-27 07:46:34 +04:00
|
|
|
return mSlice;
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD
|
2014-09-27 03:21:57 +04:00
|
|
|
Run() MOZ_OVERRIDE
|
2013-01-18 00:17:33 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(mActor);
|
|
|
|
mActor->AssertIsOnOwningThread();
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
RunInternal(true);
|
|
|
|
return NS_OK;
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
private:
|
|
|
|
void
|
|
|
|
RunInternal(bool aNotify)
|
2013-01-10 17:47:32 +04:00
|
|
|
{
|
2014-04-24 08:43:57 +04:00
|
|
|
MOZ_ASSERT(mActor);
|
2014-09-27 03:21:57 +04:00
|
|
|
mActor->AssertIsOnOwningThread();
|
2014-04-24 08:43:57 +04:00
|
|
|
MOZ_ASSERT(!mSlice);
|
|
|
|
MOZ_ASSERT(!mDone);
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
NS_ENSURE_TRUE_VOID(mActor->HasManager());
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsID id;
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(gUUIDGenerator->GenerateUUIDInPlace(&id)));
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
ParentBlobConstructorParams params(
|
|
|
|
NormalBlobConstructorParams(mContentType /* contentType */,
|
|
|
|
mLength /* length */),
|
|
|
|
void_t() /* optionalInputStreamParams */);
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
ChildBlobConstructorParams otherSideParams(
|
|
|
|
id,
|
|
|
|
SlicedBlobConstructorParams(mActor /* sourceParent*/,
|
|
|
|
nullptr /* sourceChild */,
|
|
|
|
void_t() /* optionalID */,
|
|
|
|
mStart /* begin */,
|
|
|
|
mStart + mLength /* end */,
|
|
|
|
mContentType /* contentType */));
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobParent* newActor;
|
|
|
|
if (nsIContentParent* contentManager = mActor->GetContentManager()) {
|
|
|
|
newActor = SendSliceConstructor(contentManager, params, otherSideParams);
|
|
|
|
} else {
|
|
|
|
newActor = SendSliceConstructor(mActor->GetBackgroundManager(),
|
|
|
|
params,
|
|
|
|
otherSideParams);
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (newActor) {
|
|
|
|
mSlice = newActor->GetBlobImpl();
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
mActor = nullptr;
|
|
|
|
|
|
|
|
if (aNotify) {
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
mDone = true;
|
|
|
|
lock.Notify();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mDone = true;
|
2013-01-10 17:47:32 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
class BlobParent::ForwardingRemoteBlobImpl MOZ_FINAL
|
|
|
|
: public RemoteBlobImplBase
|
2014-10-08 20:15:23 +04:00
|
|
|
, public FileImpl
|
2014-09-27 03:21:57 +04:00
|
|
|
, public nsIRemoteBlob
|
|
|
|
{
|
|
|
|
friend class mozilla::dom::BlobParent;
|
|
|
|
|
|
|
|
typedef mozilla::dom::indexedDB::FileInfo FileInfo;
|
|
|
|
typedef mozilla::dom::indexedDB::FileManager FileManager;
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> mBlobImpl;
|
2014-09-27 03:21:57 +04:00
|
|
|
nsCOMPtr<nsIRemoteBlob> mRemoteBlob;
|
|
|
|
|
|
|
|
public:
|
|
|
|
NS_DECL_ISUPPORTS_INHERITED
|
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
virtual void
|
2014-09-27 03:21:57 +04:00
|
|
|
GetName(nsAString& aName) MOZ_OVERRIDE
|
|
|
|
{
|
2014-10-08 20:15:22 +04:00
|
|
|
mBlobImpl->GetName(aName);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual nsresult
|
|
|
|
GetPath(nsAString& aPath) MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
return mBlobImpl->GetPath(aPath);
|
|
|
|
}
|
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
virtual int64_t
|
|
|
|
GetLastModified(ErrorResult& aRv) MOZ_OVERRIDE
|
2014-09-27 03:21:57 +04:00
|
|
|
{
|
2014-10-08 20:15:22 +04:00
|
|
|
return mBlobImpl->GetLastModified(aRv);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
virtual void
|
|
|
|
GetMozFullPath(nsAString& aName, ErrorResult& aRv) MOZ_OVERRIDE
|
2014-09-27 03:21:57 +04:00
|
|
|
{
|
2014-10-08 20:15:22 +04:00
|
|
|
mBlobImpl->GetMozFullPath(aName, aRv);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
virtual void
|
|
|
|
GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) MOZ_OVERRIDE
|
2014-09-27 03:21:57 +04:00
|
|
|
{
|
2014-10-08 20:15:22 +04:00
|
|
|
mBlobImpl->GetMozFullPathInternal(aFileName, aRv);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
virtual uint64_t
|
|
|
|
GetSize(ErrorResult& aRv) MOZ_OVERRIDE
|
2014-09-27 03:21:57 +04:00
|
|
|
{
|
2014-10-08 20:15:22 +04:00
|
|
|
return mBlobImpl->GetSize(aRv);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
virtual void
|
2014-09-27 03:21:57 +04:00
|
|
|
GetType(nsAString& aType) MOZ_OVERRIDE
|
|
|
|
{
|
2014-10-08 20:15:22 +04:00
|
|
|
mBlobImpl->GetType(aType);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
virtual already_AddRefed<FileImpl>
|
2014-09-27 03:21:57 +04:00
|
|
|
CreateSlice(uint64_t aStart,
|
|
|
|
uint64_t aLength,
|
2014-10-08 20:15:22 +04:00
|
|
|
const nsAString& aContentType,
|
|
|
|
ErrorResult& aRv) MOZ_OVERRIDE
|
2014-09-27 03:21:57 +04:00
|
|
|
{
|
2014-10-08 20:15:22 +04:00
|
|
|
return mBlobImpl->CreateSlice(aStart, aLength, aContentType, aRv);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
virtual const nsTArray<nsRefPtr<FileImpl>>*
|
2014-09-27 03:21:57 +04:00
|
|
|
GetSubBlobImpls() const MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
return mBlobImpl->GetSubBlobImpls();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual nsresult
|
|
|
|
GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
return mBlobImpl->GetInternalStream(aStream);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual int64_t
|
|
|
|
GetFileId() MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
return mBlobImpl->GetFileId();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
AddFileInfo(FileInfo* aFileInfo) MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
return mBlobImpl->AddFileInfo(aFileInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual FileInfo*
|
|
|
|
GetFileInfo(FileManager* aFileManager) MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
return mBlobImpl->GetFileInfo(aFileManager);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual nsresult
|
|
|
|
GetSendInfo(nsIInputStream** aBody,
|
|
|
|
uint64_t* aContentLength,
|
|
|
|
nsACString& aContentType,
|
|
|
|
nsACString& aCharset) MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
return mBlobImpl->GetSendInfo(aBody,
|
|
|
|
aContentLength,
|
|
|
|
aContentType,
|
|
|
|
aCharset);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual nsresult
|
|
|
|
GetMutable(bool* aMutable) const MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
return mBlobImpl->GetMutable(aMutable);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual nsresult
|
|
|
|
SetMutable(bool aMutable) MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
return mBlobImpl->SetMutable(aMutable);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
SetLazyData(const nsAString& aName,
|
|
|
|
const nsAString& aContentType,
|
|
|
|
uint64_t aLength,
|
|
|
|
uint64_t aLastModifiedDate) MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
MOZ_CRASH("This should never be called!");
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool
|
|
|
|
IsMemoryFile() const MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
return mBlobImpl->IsMemoryFile();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool
|
|
|
|
IsSizeUnknown() const MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
return mBlobImpl->IsSizeUnknown();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool
|
|
|
|
IsDateUnknown() const MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
return mBlobImpl->IsDateUnknown();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool
|
|
|
|
IsFile() const MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
return mBlobImpl->IsFile();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
Unlink() MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
return mBlobImpl->Unlink();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
Traverse(nsCycleCollectionTraversalCallback& aCallback) MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
return mBlobImpl->Traverse(aCallback);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual BlobChild*
|
|
|
|
GetBlobChild() MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mRemoteBlob);
|
|
|
|
|
|
|
|
return mRemoteBlob->GetBlobChild();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual BlobParent*
|
|
|
|
GetBlobParent() MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mRemoteBlob);
|
|
|
|
|
|
|
|
return mRemoteBlob->GetBlobParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
ForwardingRemoteBlobImpl(BlobParent* aActor,
|
2014-10-08 20:15:23 +04:00
|
|
|
FileImpl* aBlobImpl)
|
2014-09-27 03:21:57 +04:00
|
|
|
: RemoteBlobImplBase(aActor, /* aForwards */ true)
|
|
|
|
, mBlobImpl(aBlobImpl)
|
|
|
|
, mRemoteBlob(do_QueryObject(aBlobImpl))
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aBlobImpl);
|
|
|
|
|
|
|
|
DebugOnly<bool> isMutable;
|
|
|
|
MOZ_ASSERT(NS_SUCCEEDED(aBlobImpl->GetMutable(&isMutable)));
|
|
|
|
MOZ_ASSERT(!isMutable);
|
|
|
|
}
|
|
|
|
|
|
|
|
~ForwardingRemoteBlobImpl()
|
|
|
|
{ }
|
|
|
|
};
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
/*******************************************************************************
|
2014-09-27 03:21:57 +04:00
|
|
|
* BlobParent::RemoteBlobImpl Implementation
|
2014-04-24 08:43:57 +04:00
|
|
|
******************************************************************************/
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
NS_IMPL_ADDREF(BlobParent::RemoteBlobImpl)
|
|
|
|
NS_IMPL_RELEASE_WITH_DESTROY(BlobParent::RemoteBlobImpl, Destroy())
|
|
|
|
NS_IMPL_QUERY_INTERFACE_INHERITED(BlobParent::RemoteBlobImpl,
|
2014-10-08 20:15:23 +04:00
|
|
|
FileImplBase,
|
2014-09-27 03:21:57 +04:00
|
|
|
nsIRemoteBlob)
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
already_AddRefed<FileImpl>
|
2014-04-24 08:43:57 +04:00
|
|
|
BlobParent::
|
2014-09-27 03:21:57 +04:00
|
|
|
RemoteBlobImpl::CreateSlice(uint64_t aStart,
|
|
|
|
uint64_t aLength,
|
2014-10-08 20:15:22 +04:00
|
|
|
const nsAString& aContentType,
|
|
|
|
ErrorResult& aRv)
|
2013-01-10 17:47:32 +04:00
|
|
|
{
|
2014-04-24 08:43:57 +04:00
|
|
|
if (!mActor) {
|
2014-10-08 20:15:22 +04:00
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
2014-04-24 08:43:57 +04:00
|
|
|
return nullptr;
|
2013-01-10 17:47:32 +04:00
|
|
|
}
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
nsRefPtr<SliceHelper> helper = new SliceHelper(mActor);
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> impl = helper->GetSlice(aStart, aLength, aContentType);
|
2014-09-27 03:21:57 +04:00
|
|
|
if (NS_WARN_IF(!impl)) {
|
2014-10-08 20:15:22 +04:00
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
2014-06-27 07:46:34 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return impl.forget();
|
2013-01-18 00:17:33 +04:00
|
|
|
}
|
2013-01-10 17:47:32 +04:00
|
|
|
|
2014-06-26 20:47:44 +04:00
|
|
|
nsresult
|
2014-04-24 08:43:57 +04:00
|
|
|
BlobParent::
|
2014-09-27 03:21:57 +04:00
|
|
|
RemoteBlobImpl::GetInternalStream(nsIInputStream** aStream)
|
2013-01-18 00:17:33 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(mInputStreamParams.type() != InputStreamParams::T__None);
|
2013-01-18 00:17:33 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsTArray<FileDescriptor> fds;
|
|
|
|
nsCOMPtr<nsIInputStream> realStream =
|
|
|
|
DeserializeInputStream(mInputStreamParams, fds);
|
|
|
|
if (!realStream) {
|
|
|
|
NS_WARNING("Failed to deserialize stream!");
|
2014-04-24 08:43:57 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsCOMPtr<nsIInputStream> stream =
|
|
|
|
new BlobInputStreamTether(realStream, this);
|
|
|
|
stream.forget(aStream);
|
|
|
|
return NS_OK;
|
2013-01-18 00:17:33 +04:00
|
|
|
}
|
2012-10-18 22:29:32 +04:00
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
int64_t
|
2014-04-24 08:43:57 +04:00
|
|
|
BlobParent::
|
2014-10-08 20:15:22 +04:00
|
|
|
RemoteBlobImpl::GetLastModified(ErrorResult& aRv)
|
2014-04-24 08:43:57 +04:00
|
|
|
{
|
|
|
|
if (IsDateUnknown()) {
|
2014-10-08 20:15:22 +04:00
|
|
|
return 0;
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2014-10-08 20:15:22 +04:00
|
|
|
|
|
|
|
return mLastModificationDate;
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobChild*
|
|
|
|
BlobParent::
|
|
|
|
RemoteBlobImpl::GetBlobChild()
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlobParent*
|
|
|
|
BlobParent::
|
|
|
|
RemoteBlobImpl::GetBlobParent()
|
|
|
|
{
|
|
|
|
return mActor;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMPL_ADDREF(BlobParent::ForwardingRemoteBlobImpl)
|
|
|
|
NS_IMPL_RELEASE_WITH_DESTROY(BlobParent::ForwardingRemoteBlobImpl, Destroy())
|
|
|
|
NS_INTERFACE_MAP_BEGIN(BlobParent::ForwardingRemoteBlobImpl)
|
|
|
|
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIRemoteBlob, mRemoteBlob)
|
2014-10-08 20:15:23 +04:00
|
|
|
NS_INTERFACE_MAP_END_INHERITING(FileImpl)
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* BlobParent
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
BlobParent::BlobParent(nsIContentParent* aManager, IDTableEntry* aIDTableEntry)
|
|
|
|
: mBackgroundManager(nullptr)
|
|
|
|
, mContentManager(aManager)
|
|
|
|
{
|
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
|
|
|
|
CommonInit(aIDTableEntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
BlobParent::BlobParent(PBackgroundParent* aManager, IDTableEntry* aIDTableEntry)
|
|
|
|
: mBackgroundManager(aManager)
|
|
|
|
, mContentManager(nullptr)
|
|
|
|
, mEventTarget(do_GetCurrentThread())
|
|
|
|
{
|
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
MOZ_ASSERT(mEventTarget);
|
|
|
|
|
|
|
|
CommonInit(aIDTableEntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
BlobParent::BlobParent(nsIContentParent* aManager,
|
|
|
|
const ParentBlobConstructorParams& aParams,
|
|
|
|
IDTableEntry* aIDTableEntry)
|
|
|
|
: mBackgroundManager(nullptr)
|
|
|
|
, mContentManager(aManager)
|
|
|
|
{
|
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
|
|
|
|
CommonInit(aParams, aIDTableEntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
BlobParent::BlobParent(PBackgroundParent* aManager,
|
|
|
|
const ParentBlobConstructorParams& aParams,
|
|
|
|
IDTableEntry* aIDTableEntry)
|
|
|
|
: mBackgroundManager(aManager)
|
|
|
|
, mContentManager(nullptr)
|
|
|
|
, mEventTarget(do_GetCurrentThread())
|
|
|
|
{
|
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
MOZ_ASSERT(mEventTarget);
|
|
|
|
|
|
|
|
CommonInit(aParams, aIDTableEntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
BlobParent::~BlobParent()
|
|
|
|
{
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MOZ_COUNT_DTOR(BlobParent);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BlobParent::CommonInit(IDTableEntry* aIDTableEntry)
|
|
|
|
{
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aIDTableEntry);
|
|
|
|
MOZ_ASSERT(aIDTableEntry->BlobImpl());
|
|
|
|
|
|
|
|
MOZ_COUNT_CTOR(BlobParent);
|
|
|
|
|
|
|
|
mBlobImpl = aIDTableEntry->BlobImpl();
|
|
|
|
mRemoteBlobImpl = nullptr;
|
|
|
|
|
|
|
|
mBlobImpl->AddRef();
|
|
|
|
mOwnsBlobImpl = true;
|
|
|
|
|
|
|
|
mIDTableEntry = aIDTableEntry;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BlobParent::CommonInit(const ParentBlobConstructorParams& aParams,
|
|
|
|
IDTableEntry* aIDTableEntry)
|
|
|
|
{
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MOZ_COUNT_CTOR(BlobParent);
|
|
|
|
|
|
|
|
const AnyBlobConstructorParams& blobParams = aParams.blobParams();
|
|
|
|
|
|
|
|
const AnyBlobConstructorParams::Type paramsType = blobParams.type();
|
|
|
|
MOZ_ASSERT(paramsType ==
|
|
|
|
AnyBlobConstructorParams::TNormalBlobConstructorParams ||
|
|
|
|
paramsType ==
|
|
|
|
AnyBlobConstructorParams::TFileBlobConstructorParams ||
|
|
|
|
paramsType ==
|
|
|
|
AnyBlobConstructorParams::TKnownBlobConstructorParams);
|
|
|
|
MOZ_ASSERT_IF(paramsType ==
|
|
|
|
AnyBlobConstructorParams::TKnownBlobConstructorParams,
|
|
|
|
aIDTableEntry);
|
|
|
|
MOZ_ASSERT_IF(paramsType !=
|
|
|
|
AnyBlobConstructorParams::TKnownBlobConstructorParams,
|
|
|
|
!aIDTableEntry);
|
|
|
|
MOZ_ASSERT_IF(paramsType ==
|
|
|
|
AnyBlobConstructorParams::TKnownBlobConstructorParams,
|
|
|
|
aParams.optionalInputStreamParams().type() ==
|
|
|
|
OptionalInputStreamParams::Tvoid_t);
|
|
|
|
MOZ_ASSERT_IF(paramsType !=
|
|
|
|
AnyBlobConstructorParams::TKnownBlobConstructorParams,
|
|
|
|
aParams.optionalInputStreamParams().type() ==
|
|
|
|
OptionalInputStreamParams::TInputStreamParams);
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> remoteBlobImpl;
|
2014-09-27 03:21:57 +04:00
|
|
|
RemoteBlobImplBase* remoteBlobBase = nullptr;
|
|
|
|
|
|
|
|
switch (paramsType) {
|
|
|
|
case AnyBlobConstructorParams::TNormalBlobConstructorParams: {
|
|
|
|
const InputStreamParams& inputStreamParams =
|
|
|
|
aParams.optionalInputStreamParams().get_InputStreamParams();
|
|
|
|
|
|
|
|
const NormalBlobConstructorParams& params =
|
|
|
|
blobParams.get_NormalBlobConstructorParams();
|
|
|
|
|
|
|
|
nsRefPtr<RemoteBlobImpl> impl =
|
|
|
|
new RemoteBlobImpl(this,
|
|
|
|
inputStreamParams,
|
|
|
|
params.contentType(),
|
|
|
|
params.length());
|
|
|
|
|
|
|
|
remoteBlobBase = impl;
|
|
|
|
remoteBlobImpl = impl.forget();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case AnyBlobConstructorParams::TFileBlobConstructorParams: {
|
|
|
|
const InputStreamParams& inputStreamParams =
|
|
|
|
aParams.optionalInputStreamParams().get_InputStreamParams();
|
|
|
|
|
|
|
|
const FileBlobConstructorParams& params =
|
|
|
|
blobParams.get_FileBlobConstructorParams();
|
|
|
|
|
|
|
|
nsRefPtr<RemoteBlobImpl> impl =
|
|
|
|
new RemoteBlobImpl(this,
|
|
|
|
inputStreamParams,
|
|
|
|
params.name(),
|
|
|
|
params.contentType(),
|
|
|
|
params.length(),
|
|
|
|
params.modDate());
|
|
|
|
|
|
|
|
remoteBlobBase = impl;
|
|
|
|
remoteBlobImpl = impl.forget();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case AnyBlobConstructorParams::TKnownBlobConstructorParams: {
|
|
|
|
nsRefPtr<ForwardingRemoteBlobImpl> impl =
|
|
|
|
new ForwardingRemoteBlobImpl(this, aIDTableEntry->BlobImpl());
|
|
|
|
|
|
|
|
remoteBlobBase = impl;
|
|
|
|
remoteBlobImpl = impl.forget();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
MOZ_CRASH("Unknown params!");
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(remoteBlobImpl);
|
|
|
|
MOZ_ASSERT(remoteBlobBase);
|
|
|
|
|
|
|
|
DebugOnly<bool> isMutable;
|
|
|
|
MOZ_ASSERT(NS_SUCCEEDED(remoteBlobImpl->GetMutable(&isMutable)));
|
|
|
|
MOZ_ASSERT(!isMutable);
|
|
|
|
|
|
|
|
mRemoteBlobImpl = remoteBlobBase;
|
|
|
|
|
|
|
|
remoteBlobImpl.forget(&mBlobImpl);
|
|
|
|
mOwnsBlobImpl = true;
|
|
|
|
|
|
|
|
mIDTableEntry = aIDTableEntry;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
void
|
|
|
|
BlobParent::AssertIsOnOwningThread() const
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(IsOnOwningThread());
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // DEBUG
|
|
|
|
|
|
|
|
// static
|
|
|
|
void
|
|
|
|
BlobParent::Startup(const FriendKey& /* aKey */)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
|
|
|
|
|
|
|
CommonStartup();
|
|
|
|
|
|
|
|
ClearOnShutdown(&sIDTable);
|
|
|
|
|
|
|
|
sIDTableMutex = new Mutex("BlobParent::sIDTableMutex");
|
|
|
|
ClearOnShutdown(&sIDTableMutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
BlobParent*
|
2014-10-08 20:15:23 +04:00
|
|
|
BlobParent::GetOrCreate(nsIContentParent* aManager, FileImpl* aBlobImpl)
|
2014-09-27 03:21:57 +04:00
|
|
|
{
|
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
|
|
|
|
return GetOrCreateFromImpl(aManager, aBlobImpl);
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
BlobParent*
|
2014-10-08 20:15:23 +04:00
|
|
|
BlobParent::GetOrCreate(PBackgroundParent* aManager, FileImpl* aBlobImpl)
|
2013-01-18 00:17:33 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return GetOrCreateFromImpl(aManager, aBlobImpl);
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
BlobParent*
|
|
|
|
BlobParent::Create(nsIContentParent* aManager,
|
|
|
|
const ParentBlobConstructorParams& aParams)
|
2013-01-10 17:47:32 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertCorrectThreadForManager(aManager);
|
2013-07-17 00:07:09 +04:00
|
|
|
MOZ_ASSERT(aManager);
|
2014-06-26 20:47:44 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return CreateFromParams(aManager, aParams);
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
BlobParent*
|
|
|
|
BlobParent::Create(PBackgroundParent* aManager,
|
|
|
|
const ParentBlobConstructorParams& aParams)
|
|
|
|
{
|
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
2014-09-13 20:12:19 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return CreateFromParams(aManager, aParams);
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
|
|
|
|
2014-10-07 23:26:59 +04:00
|
|
|
// static
|
2014-10-08 20:15:23 +04:00
|
|
|
already_AddRefed<FileImpl>
|
2014-10-07 23:26:59 +04:00
|
|
|
BlobParent::GetBlobImplForID(const nsID& aID)
|
|
|
|
{
|
|
|
|
if (NS_WARN_IF(gProcessType != GeckoProcessType_Default)) {
|
|
|
|
ASSERT_UNLESS_FUZZING();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRefPtr<IDTableEntry> idTableEntry = IDTableEntry::Get(aID);
|
|
|
|
if (NS_WARN_IF(!idTableEntry)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> blobImpl = idTableEntry->BlobImpl();
|
2014-10-07 23:26:59 +04:00
|
|
|
MOZ_ASSERT(blobImpl);
|
|
|
|
|
|
|
|
return blobImpl.forget();
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
template <class ParentManagerType>
|
|
|
|
BlobParent*
|
|
|
|
BlobParent::GetOrCreateFromImpl(ParentManagerType* aManager,
|
2014-10-08 20:15:23 +04:00
|
|
|
FileImpl* aBlobImpl)
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertCorrectThreadForManager(aManager);
|
2014-09-13 20:12:19 +04:00
|
|
|
MOZ_ASSERT(aManager);
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(aBlobImpl);
|
2014-09-13 20:12:19 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// If the blob represents a remote blob for this manager then we can simply
|
|
|
|
// pass its actor back here.
|
|
|
|
if (nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(aBlobImpl)) {
|
|
|
|
BlobParent* actor = MaybeGetActorFromRemoteBlob(remoteBlob, aManager);
|
|
|
|
if (actor) {
|
|
|
|
return actor;
|
|
|
|
}
|
|
|
|
}
|
2014-09-13 20:12:19 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// All blobs shared between processes must be immutable.
|
|
|
|
if (NS_WARN_IF(NS_FAILED(aBlobImpl->SetMutable(false)))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2014-09-13 20:12:19 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
AnyBlobConstructorParams blobParams;
|
2014-09-13 20:12:19 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (aBlobImpl->IsSizeUnknown() || aBlobImpl->IsDateUnknown()) {
|
|
|
|
// We don't want to call GetSize or GetLastModifiedDate yet since that may
|
|
|
|
// stat a file on the this thread. Instead we'll learn the size lazily from
|
|
|
|
// the other side.
|
|
|
|
blobParams = MysteryBlobConstructorParams();
|
|
|
|
} else {
|
|
|
|
nsString contentType;
|
2014-10-08 20:15:22 +04:00
|
|
|
aBlobImpl->GetType(contentType);
|
2014-09-13 20:12:19 +04:00
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
ErrorResult rv;
|
|
|
|
uint64_t length = aBlobImpl->GetSize(rv);
|
|
|
|
MOZ_ASSERT(!rv.Failed());
|
2014-09-13 20:12:19 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (aBlobImpl->IsFile()) {
|
|
|
|
nsString name;
|
2014-10-08 20:15:22 +04:00
|
|
|
aBlobImpl->GetName(name);
|
2014-09-13 20:12:19 +04:00
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
uint64_t modDate = aBlobImpl->GetLastModified(rv);
|
|
|
|
MOZ_ASSERT(!rv.Failed());
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
blobParams =
|
|
|
|
FileBlobConstructorParams(name, contentType, length, modDate);
|
|
|
|
} else {
|
|
|
|
blobParams = NormalBlobConstructorParams(contentType, length);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsID id;
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(gUUIDGenerator->GenerateUUIDInPlace(&id)));
|
|
|
|
|
|
|
|
nsRefPtr<IDTableEntry> idTableEntry =
|
|
|
|
IDTableEntry::GetOrCreate(id, ActorManagerProcessID(aManager), aBlobImpl);
|
|
|
|
MOZ_ASSERT(idTableEntry);
|
|
|
|
|
|
|
|
BlobParent* actor = new BlobParent(aManager, idTableEntry);
|
|
|
|
|
|
|
|
ChildBlobConstructorParams params(id, blobParams);
|
|
|
|
if (NS_WARN_IF(!aManager->SendPBlobConstructor(actor, params))) {
|
|
|
|
BlobParent::Destroy(actor);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return actor;
|
2014-09-13 20:12:19 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
template <class ParentManagerType>
|
2014-09-13 20:12:19 +04:00
|
|
|
BlobParent*
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobParent::CreateFromParams(ParentManagerType* aManager,
|
|
|
|
const ParentBlobConstructorParams& aParams)
|
2014-09-13 20:12:19 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertCorrectThreadForManager(aManager);
|
2014-04-24 08:43:57 +04:00
|
|
|
MOZ_ASSERT(aManager);
|
2012-08-03 10:25:30 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
const AnyBlobConstructorParams& blobParams = aParams.blobParams();
|
2014-04-30 00:02:41 +04:00
|
|
|
|
2013-01-18 00:17:33 +04:00
|
|
|
switch (blobParams.type()) {
|
2014-09-27 03:21:57 +04:00
|
|
|
case AnyBlobConstructorParams::TMysteryBlobConstructorParams: {
|
|
|
|
ASSERT_UNLESS_FUZZING();
|
2014-04-30 00:02:41 +04:00
|
|
|
return nullptr;
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
2014-04-30 00:02:41 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
case AnyBlobConstructorParams::TNormalBlobConstructorParams:
|
|
|
|
case AnyBlobConstructorParams::TFileBlobConstructorParams: {
|
|
|
|
if (aParams.optionalInputStreamParams().type() !=
|
|
|
|
OptionalInputStreamParams::TInputStreamParams) {
|
|
|
|
ASSERT_UNLESS_FUZZING();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return new BlobParent(aManager, aParams, /* aIDTableEntry */ nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
case AnyBlobConstructorParams::TSlicedBlobConstructorParams: {
|
|
|
|
if (aParams.optionalInputStreamParams().type() !=
|
|
|
|
OptionalInputStreamParams::Tvoid_t) {
|
|
|
|
ASSERT_UNLESS_FUZZING();
|
|
|
|
return nullptr;
|
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2013-01-18 00:17:33 +04:00
|
|
|
const SlicedBlobConstructorParams& params =
|
|
|
|
blobParams.get_SlicedBlobConstructorParams();
|
2014-09-27 03:21:57 +04:00
|
|
|
if (NS_WARN_IF(params.optionalID().type() != OptionalID::TnsID)) {
|
|
|
|
ASSERT_UNLESS_FUZZING();
|
|
|
|
return nullptr;
|
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
auto* actor =
|
|
|
|
const_cast<BlobParent*>(
|
|
|
|
static_cast<const BlobParent*>(params.sourceParent()));
|
|
|
|
MOZ_ASSERT(actor);
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> source = actor->GetBlobImpl();
|
2013-01-18 00:17:33 +04:00
|
|
|
MOZ_ASSERT(source);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-10-08 20:15:22 +04:00
|
|
|
Optional<int64_t> start;
|
|
|
|
start.Construct(params.begin());
|
|
|
|
|
|
|
|
Optional<int64_t> end;
|
|
|
|
end.Construct(params.end());
|
|
|
|
|
|
|
|
ErrorResult rv;
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> slice =
|
2014-10-08 20:15:22 +04:00
|
|
|
source->Slice(start, end, params.contentType(), rv);
|
|
|
|
if (NS_WARN_IF(rv.Failed())) {
|
2014-09-27 03:21:57 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(slice->SetMutable(false)));
|
|
|
|
|
|
|
|
nsRefPtr<IDTableEntry> idTableEntry =
|
|
|
|
IDTableEntry::Create(params.optionalID(),
|
|
|
|
ActorManagerProcessID(aManager),
|
|
|
|
slice);
|
|
|
|
if (NS_WARN_IF(!idTableEntry)) {
|
|
|
|
ASSERT_UNLESS_FUZZING();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return new BlobParent(aManager, idTableEntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
case AnyBlobConstructorParams::TKnownBlobConstructorParams: {
|
|
|
|
if (aParams.optionalInputStreamParams().type() !=
|
|
|
|
OptionalInputStreamParams::Tvoid_t) {
|
|
|
|
ASSERT_UNLESS_FUZZING();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
const KnownBlobConstructorParams& params =
|
|
|
|
blobParams.get_KnownBlobConstructorParams();
|
|
|
|
|
|
|
|
nsRefPtr<IDTableEntry> idTableEntry =
|
|
|
|
IDTableEntry::Get(params.id(), ActorManagerProcessID(aManager));
|
|
|
|
if (NS_WARN_IF(!idTableEntry)) {
|
|
|
|
ASSERT_UNLESS_FUZZING();
|
|
|
|
return nullptr;
|
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return new BlobParent(aManager, aParams, idTableEntry);
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
2013-06-29 05:38:30 +04:00
|
|
|
MOZ_CRASH("Unknown params!");
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_CRASH("Should never get here!");
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
template <class ParentManagerType>
|
|
|
|
BlobParent*
|
|
|
|
BlobParent::SendSliceConstructor(
|
|
|
|
ParentManagerType* aManager,
|
|
|
|
const ParentBlobConstructorParams& aParams,
|
|
|
|
const ChildBlobConstructorParams& aOtherSideParams)
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aManager);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobParent* newActor = BlobParent::Create(aManager, aParams);
|
|
|
|
MOZ_ASSERT(newActor);
|
2012-08-03 10:25:30 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (aManager->SendPBlobConstructor(newActor, aOtherSideParams)) {
|
|
|
|
return newActor;
|
2014-09-18 03:36:01 +04:00
|
|
|
}
|
2012-08-03 10:25:30 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobParent::Destroy(newActor);
|
|
|
|
return nullptr;
|
2014-09-18 03:36:01 +04:00
|
|
|
}
|
2012-08-03 10:25:30 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
BlobParent*
|
|
|
|
BlobParent::MaybeGetActorFromRemoteBlob(nsIRemoteBlob* aRemoteBlob,
|
|
|
|
nsIContentParent* aManager)
|
2014-09-18 03:36:01 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aRemoteBlob);
|
|
|
|
MOZ_ASSERT(aManager);
|
2012-08-03 10:25:30 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobParent* actor = aRemoteBlob->GetBlobParent();
|
|
|
|
if (actor && actor->GetContentManager() == aManager) {
|
|
|
|
return actor;
|
|
|
|
}
|
2012-08-03 10:25:30 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return nullptr;
|
2012-08-03 10:25:30 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
BlobParent*
|
|
|
|
BlobParent::MaybeGetActorFromRemoteBlob(nsIRemoteBlob* aRemoteBlob,
|
|
|
|
PBackgroundParent* aManager)
|
2014-06-11 09:44:03 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertCorrectThreadForManager(aManager);
|
|
|
|
MOZ_ASSERT(aRemoteBlob);
|
|
|
|
MOZ_ASSERT(aManager);
|
2014-09-13 20:12:19 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobParent* actor = aRemoteBlob->GetBlobParent();
|
|
|
|
if (actor && actor->GetBackgroundManager() == aManager) {
|
|
|
|
return actor;
|
|
|
|
}
|
2014-06-11 09:44:03 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return nullptr;
|
2014-09-18 03:36:01 +04:00
|
|
|
}
|
2012-08-03 10:25:30 +04:00
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
already_AddRefed<FileImpl>
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobParent::GetBlobImpl()
|
2014-09-18 03:36:01 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mBlobImpl);
|
2013-01-10 17:47:32 +04:00
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
nsRefPtr<FileImpl> blobImpl;
|
2013-01-10 17:47:32 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// Remote blobs are held alive until the first call to GetBlobImpl. Thereafter
|
|
|
|
// we only hold a weak reference. Normal blobs are held alive until the actor
|
|
|
|
// is destroyed.
|
|
|
|
if (mRemoteBlobImpl && mOwnsBlobImpl) {
|
|
|
|
blobImpl = dont_AddRef(mBlobImpl);
|
|
|
|
mOwnsBlobImpl = false;
|
|
|
|
} else {
|
|
|
|
blobImpl = mBlobImpl;
|
|
|
|
}
|
2013-01-10 17:47:32 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(blobImpl);
|
2013-01-10 17:47:32 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return blobImpl.forget();
|
|
|
|
}
|
2013-01-10 17:47:32 +04:00
|
|
|
|
2012-08-02 10:02:29 +04:00
|
|
|
void
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobParent::NoteDyingRemoteBlobImpl()
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(mRemoteBlobImpl);
|
|
|
|
MOZ_ASSERT(!mOwnsBlobImpl);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// This may be called on any thread due to the fact that RemoteBlobImpl is
|
2012-08-03 10:25:30 +04:00
|
|
|
// designed to be passed between threads. We must start the shutdown process
|
|
|
|
// on the main thread, so we proxy here if necessary.
|
2014-09-27 03:21:57 +04:00
|
|
|
if (!IsOnOwningThread()) {
|
2012-08-02 10:02:29 +04:00
|
|
|
nsCOMPtr<nsIRunnable> runnable =
|
2014-09-27 03:21:57 +04:00
|
|
|
NS_NewNonOwningRunnableMethod(this, &BlobParent::NoteDyingRemoteBlobImpl);
|
|
|
|
|
|
|
|
if (mEventTarget) {
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(mEventTarget->Dispatch(runnable,
|
|
|
|
NS_DISPATCH_NORMAL)));
|
|
|
|
} else {
|
|
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable)));
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Must do this before calling Send__delete__ or we'll crash there trying to
|
|
|
|
// access a dangling pointer.
|
2014-09-27 03:21:57 +04:00
|
|
|
mBlobImpl = nullptr;
|
|
|
|
mRemoteBlobImpl = nullptr;
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
unused << PBlobParent::Send__delete__(this);
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-04-24 08:43:57 +04:00
|
|
|
BlobParent::NoteRunnableCompleted(OpenStreamRunnable* aRunnable)
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aRunnable);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
for (uint32_t count = mOpenStreamRunnables.Length(), index = 0;
|
|
|
|
index < count;
|
|
|
|
index++) {
|
2014-04-24 08:43:57 +04:00
|
|
|
nsRevocableEventPtr<OpenStreamRunnable>& runnable =
|
|
|
|
mOpenStreamRunnables[index];
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
if (runnable.get() == aRunnable) {
|
|
|
|
runnable.Forget();
|
|
|
|
mOpenStreamRunnables.RemoveElementAt(index);
|
|
|
|
return;
|
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
2014-02-08 04:14:59 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
MOZ_CRASH("Runnable not in our array!");
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
bool
|
|
|
|
BlobParent::IsOnOwningThread() const
|
|
|
|
{
|
|
|
|
return EventTargetIsOnCurrentThread(mEventTarget);
|
|
|
|
}
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
void
|
|
|
|
BlobParent::ActorDestroy(ActorDestroyReason aWhy)
|
2012-08-03 10:25:30 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
2012-08-03 10:25:30 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (mRemoteBlobImpl) {
|
|
|
|
mRemoteBlobImpl->NoteDyingActor();
|
2012-08-03 10:25:30 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (mBlobImpl && mOwnsBlobImpl) {
|
|
|
|
mBlobImpl->Release();
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2012-08-03 10:25:30 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
#ifdef DEBUG
|
|
|
|
mBlobImpl = nullptr;
|
|
|
|
mRemoteBlobImpl = nullptr;
|
|
|
|
mBackgroundManager = nullptr;
|
|
|
|
mContentManager = nullptr;
|
|
|
|
mOwnsBlobImpl = false;
|
|
|
|
#endif
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2012-08-03 10:25:30 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
PBlobStreamParent*
|
|
|
|
BlobParent::AllocPBlobStreamParent()
|
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
if (NS_WARN_IF(mRemoteBlobImpl && !mRemoteBlobImpl->mForwards)) {
|
|
|
|
ASSERT_UNLESS_FUZZING();
|
|
|
|
return nullptr;
|
|
|
|
}
|
2012-08-03 10:25:30 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
return new InputStreamParent();
|
2012-08-03 10:25:30 +04:00
|
|
|
}
|
|
|
|
|
2012-08-02 10:02:29 +04:00
|
|
|
bool
|
2014-04-24 08:43:57 +04:00
|
|
|
BlobParent::RecvPBlobStreamConstructor(PBlobStreamParent* aActor)
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
2014-04-24 08:43:57 +04:00
|
|
|
MOZ_ASSERT(aActor);
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(mBlobImpl);
|
|
|
|
MOZ_ASSERT_IF(mRemoteBlobImpl, mRemoteBlobImpl->mForwards);
|
|
|
|
MOZ_ASSERT(mOwnsBlobImpl);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIInputStream> stream;
|
2014-09-27 03:21:57 +04:00
|
|
|
nsresult rv = mBlobImpl->GetInternalStream(getter_AddRefs(stream));
|
2012-08-02 10:02:29 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, false);
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// If the stream is entirely backed by memory then we can serialize and send
|
|
|
|
// it immediately.
|
|
|
|
if (mBlobImpl->IsMemoryFile()) {
|
|
|
|
InputStreamParams params;
|
|
|
|
nsTArray<FileDescriptor> fds;
|
|
|
|
SerializeInputStream(stream, params, fds);
|
|
|
|
|
|
|
|
MOZ_ASSERT(params.type() != InputStreamParams::T__None);
|
|
|
|
MOZ_ASSERT(fds.IsEmpty());
|
|
|
|
|
|
|
|
return PBlobStreamParent::Send__delete__(aActor, params, void_t());
|
|
|
|
}
|
2014-09-13 20:12:19 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(mBlobImpl);
|
2013-02-16 01:39:43 +04:00
|
|
|
nsCOMPtr<IPrivateRemoteInputStream> remoteStream;
|
2012-10-25 22:45:15 +04:00
|
|
|
if (remoteBlob) {
|
2013-02-16 01:39:43 +04:00
|
|
|
remoteStream = do_QueryInterface(stream);
|
2012-10-25 22:45:15 +04:00
|
|
|
}
|
|
|
|
|
2013-02-16 01:39:43 +04:00
|
|
|
// There are three cases in which we can use the stream obtained from the blob
|
|
|
|
// directly as our serialized stream:
|
|
|
|
//
|
|
|
|
// 1. The blob is not a remote blob.
|
|
|
|
// 2. The blob is a remote blob that represents this actor.
|
|
|
|
// 3. The blob is a remote blob representing a different actor but we
|
|
|
|
// already have a non-remote, i.e. serialized, serialized stream.
|
|
|
|
//
|
|
|
|
// In all other cases we need to be on a background thread before we can get
|
|
|
|
// to the real stream.
|
|
|
|
nsCOMPtr<nsIIPCSerializableInputStream> serializableStream;
|
2012-10-25 22:45:15 +04:00
|
|
|
if (!remoteBlob ||
|
2014-09-27 03:21:57 +04:00
|
|
|
remoteBlob->GetBlobParent() == this ||
|
2013-02-16 01:39:43 +04:00
|
|
|
!remoteStream) {
|
2012-10-25 22:45:15 +04:00
|
|
|
serializableStream = do_QueryInterface(stream);
|
|
|
|
if (!serializableStream) {
|
|
|
|
MOZ_ASSERT(false, "Must be serializable!");
|
|
|
|
return false;
|
|
|
|
}
|
2012-08-16 08:02:32 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsCOMPtr<nsIThread> target;
|
|
|
|
rv = NS_NewNamedThread("Blob Opener", getter_AddRefs(target));
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return false;
|
|
|
|
}
|
2012-08-16 08:02:32 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
nsRefPtr<OpenStreamRunnable> runnable =
|
|
|
|
new OpenStreamRunnable(this, aActor, stream, serializableStream, target);
|
2012-08-16 08:02:32 +04:00
|
|
|
|
2012-10-25 22:45:15 +04:00
|
|
|
rv = runnable->Dispatch();
|
2012-08-16 08:02:32 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, false);
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
// nsRevocableEventPtr lacks some of the operators needed for anything nicer.
|
|
|
|
*mOpenStreamRunnables.AppendElement() = runnable;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
BlobParent::DeallocPBlobStreamParent(PBlobStreamParent* aActor)
|
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
2014-04-24 08:43:57 +04:00
|
|
|
|
|
|
|
delete static_cast<InputStreamParent*>(aActor);
|
2012-08-16 08:02:32 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2014-04-24 08:43:57 +04:00
|
|
|
BlobParent::RecvResolveMystery(const ResolveMysteryParams& aParams)
|
2012-08-16 08:02:32 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aParams.type() != ResolveMysteryParams::T__None);
|
|
|
|
MOZ_ASSERT(mBlobImpl);
|
|
|
|
MOZ_ASSERT(!mRemoteBlobImpl);
|
|
|
|
MOZ_ASSERT(mOwnsBlobImpl);
|
2012-08-16 08:02:32 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
switch (aParams.type()) {
|
|
|
|
case ResolveMysteryParams::TNormalBlobConstructorParams: {
|
|
|
|
const NormalBlobConstructorParams& params =
|
|
|
|
aParams.get_NormalBlobConstructorParams();
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
if (NS_WARN_IF(params.length() == UINT64_MAX)) {
|
|
|
|
ASSERT_UNLESS_FUZZING();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
nsString voidString;
|
|
|
|
voidString.SetIsVoid(true);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
mBlobImpl->SetLazyData(voidString,
|
|
|
|
params.contentType(),
|
|
|
|
params.length(),
|
|
|
|
UINT64_MAX);
|
|
|
|
return true;
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2012-08-16 08:02:32 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
case ResolveMysteryParams::TFileBlobConstructorParams: {
|
|
|
|
const FileBlobConstructorParams& params =
|
|
|
|
aParams.get_FileBlobConstructorParams();
|
2014-09-27 03:21:57 +04:00
|
|
|
if (NS_WARN_IF(params.name().IsVoid())) {
|
|
|
|
ASSERT_UNLESS_FUZZING();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_WARN_IF(params.length() == UINT64_MAX)) {
|
|
|
|
ASSERT_UNLESS_FUZZING();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_WARN_IF(params.modDate() == UINT64_MAX)) {
|
|
|
|
ASSERT_UNLESS_FUZZING();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
mBlobImpl->SetLazyData(params.name(),
|
|
|
|
params.contentType(),
|
|
|
|
params.length(),
|
|
|
|
params.modDate());
|
|
|
|
return true;
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-04-24 08:43:57 +04:00
|
|
|
default:
|
|
|
|
MOZ_CRASH("Unknown params!");
|
|
|
|
}
|
2013-07-08 19:48:40 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_CRASH("Should never get here!");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
BlobParent::RecvWaitForSliceCreation()
|
|
|
|
{
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mBlobImpl);
|
|
|
|
MOZ_ASSERT(!mRemoteBlobImpl);
|
|
|
|
MOZ_ASSERT(mOwnsBlobImpl);
|
|
|
|
|
|
|
|
// The whole point of this message is to ensure that the sliced blob created
|
|
|
|
// by the child has been inserted into our IDTable.
|
|
|
|
MOZ_ASSERT(mIDTableEntry);
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(sIDTableMutex);
|
|
|
|
MutexAutoLock lock(*sIDTableMutex);
|
|
|
|
|
|
|
|
MOZ_ASSERT(sIDTable);
|
|
|
|
MOZ_ASSERT(sIDTable->Contains(mIDTableEntry->ID()));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
BlobParent::RecvGetFileId(int64_t* aFileId)
|
|
|
|
{
|
|
|
|
using namespace mozilla::dom::indexedDB;
|
|
|
|
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mBlobImpl);
|
|
|
|
MOZ_ASSERT(!mRemoteBlobImpl);
|
|
|
|
MOZ_ASSERT(mOwnsBlobImpl);
|
|
|
|
|
|
|
|
if (NS_WARN_IF(!IndexedDatabaseManager::InTestingMode())) {
|
|
|
|
ASSERT_UNLESS_FUZZING();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*aFileId = mBlobImpl->GetFileId();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
BlobParent::RecvGetFilePath(nsString* aFilePath)
|
|
|
|
{
|
|
|
|
using namespace mozilla::dom::indexedDB;
|
|
|
|
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mBlobImpl);
|
|
|
|
MOZ_ASSERT(!mRemoteBlobImpl);
|
|
|
|
MOZ_ASSERT(mOwnsBlobImpl);
|
|
|
|
|
|
|
|
// In desktop e10s the file picker code sends this message.
|
|
|
|
#ifdef MOZ_CHILD_PERMISSIONS
|
|
|
|
if (NS_WARN_IF(!IndexedDatabaseManager::InTestingMode())) {
|
|
|
|
ASSERT_UNLESS_FUZZING();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
nsString filePath;
|
2014-10-08 20:15:22 +04:00
|
|
|
ErrorResult rv;
|
|
|
|
mBlobImpl->GetMozFullPathInternal(filePath, rv);
|
|
|
|
if (NS_WARN_IF(rv.Failed())) {
|
2014-09-27 03:21:57 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*aFilePath = filePath;
|
2014-04-24 08:43:57 +04:00
|
|
|
return true;
|
2013-07-08 19:48:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2014-04-24 08:43:57 +04:00
|
|
|
InputStreamChild::Recv__delete__(const InputStreamParams& aParams,
|
|
|
|
const OptionalFileDescriptorSet& aFDs)
|
2013-07-08 19:48:40 +04:00
|
|
|
{
|
2014-04-24 08:43:57 +04:00
|
|
|
MOZ_ASSERT(mRemoteStream);
|
2014-09-27 03:21:57 +04:00
|
|
|
mRemoteStream->AssertIsOnOwningThread();
|
2014-04-24 08:43:57 +04:00
|
|
|
|
|
|
|
nsTArray<FileDescriptor> fds;
|
|
|
|
if (aFDs.type() == OptionalFileDescriptorSet::TPFileDescriptorSetChild) {
|
|
|
|
FileDescriptorSetChild* fdSetActor =
|
|
|
|
static_cast<FileDescriptorSetChild*>(aFDs.get_PFileDescriptorSetChild());
|
|
|
|
MOZ_ASSERT(fdSetActor);
|
|
|
|
|
|
|
|
fdSetActor->ForgetFileDescriptors(fds);
|
|
|
|
MOZ_ASSERT(!fds.IsEmpty());
|
|
|
|
|
|
|
|
fdSetActor->Send__delete__(fdSetActor);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIInputStream> stream = DeserializeInputStream(aParams, fds);
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(stream);
|
2014-04-24 08:43:57 +04:00
|
|
|
|
|
|
|
mRemoteStream->SetStream(stream);
|
2013-07-08 19:48:40 +04:00
|
|
|
return true;
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobParent::
|
|
|
|
IDTableEntry::IDTableEntry(const nsID& aID,
|
|
|
|
intptr_t aProcessID,
|
2014-10-08 20:15:23 +04:00
|
|
|
FileImpl* aBlobImpl)
|
2014-09-27 03:21:57 +04:00
|
|
|
: mID(aID)
|
|
|
|
, mProcessID(aProcessID)
|
|
|
|
, mBlobImpl(aBlobImpl)
|
2014-05-02 22:44:13 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(aBlobImpl);
|
2014-05-02 22:44:13 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobParent::
|
|
|
|
IDTableEntry::~IDTableEntry()
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(sIDTableMutex);
|
|
|
|
sIDTableMutex->AssertNotCurrentThreadOwns();
|
|
|
|
MOZ_ASSERT(sIDTable);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
{
|
|
|
|
MutexAutoLock lock(*sIDTableMutex);
|
|
|
|
MOZ_ASSERT(sIDTable->Get(mID) == this);
|
|
|
|
|
|
|
|
sIDTable->Remove(mID);
|
|
|
|
|
|
|
|
if (!sIDTable->Count()) {
|
|
|
|
sIDTable = nullptr;
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
already_AddRefed<BlobParent::IDTableEntry>
|
|
|
|
BlobParent::
|
|
|
|
IDTableEntry::GetOrCreateInternal(const nsID& aID,
|
|
|
|
intptr_t aProcessID,
|
2014-10-08 20:15:23 +04:00
|
|
|
FileImpl* aBlobImpl,
|
2014-09-27 03:21:57 +04:00
|
|
|
bool aMayCreate,
|
2014-10-07 23:26:59 +04:00
|
|
|
bool aMayGet,
|
|
|
|
bool aIgnoreProcessID)
|
2014-09-27 03:21:57 +04:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
|
|
|
MOZ_ASSERT(sIDTableMutex);
|
|
|
|
sIDTableMutex->AssertNotCurrentThreadOwns();
|
|
|
|
|
|
|
|
nsRefPtr<IDTableEntry> entry;
|
|
|
|
|
|
|
|
{
|
|
|
|
MutexAutoLock lock(*sIDTableMutex);
|
|
|
|
|
|
|
|
if (!sIDTable) {
|
|
|
|
if (NS_WARN_IF(!aMayCreate)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
sIDTable = new IDTable();
|
|
|
|
}
|
|
|
|
|
|
|
|
entry = sIDTable->Get(aID);
|
|
|
|
|
|
|
|
if (entry) {
|
|
|
|
MOZ_ASSERT_IF(aBlobImpl, entry->BlobImpl() == aBlobImpl);
|
|
|
|
|
|
|
|
if (NS_WARN_IF(!aMayGet)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2014-10-07 23:26:59 +04:00
|
|
|
if (!aIgnoreProcessID && NS_WARN_IF(entry->mProcessID != aProcessID)) {
|
2014-09-27 03:21:57 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (NS_WARN_IF(!aMayCreate)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(aBlobImpl);
|
|
|
|
|
|
|
|
entry = new IDTableEntry(aID, aProcessID, aBlobImpl);
|
|
|
|
|
|
|
|
sIDTable->Put(aID, entry);
|
|
|
|
}
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(entry);
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return entry.forget();
|
2014-04-24 08:43:57 +04:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|