/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "BlobChild.h" #include "BlobParent.h" #include "BackgroundParent.h" #include "ContentChild.h" #include "ContentParent.h" #include "FileDescriptorSetChild.h" #include "jsapi.h" #include "mozilla/Assertions.h" #include "mozilla/ClearOnShutdown.h" #include "mozilla/DebugOnly.h" #include "mozilla/Monitor.h" #include "mozilla/Mutex.h" #include "mozilla/Unused.h" #include "mozilla/dom/File.h" #include "mozilla/dom/nsIContentParent.h" #include "mozilla/dom/nsIContentChild.h" #include "mozilla/dom/PBlobStreamChild.h" #include "mozilla/dom/PBlobStreamParent.h" #include "mozilla/dom/indexedDB/FileSnapshot.h" #include "mozilla/dom/IndexedDatabaseManager.h" #include "mozilla/ipc/InputStreamUtils.h" #include "mozilla/ipc/IPCStreamUtils.h" #include "mozilla/ipc/PBackgroundChild.h" #include "mozilla/ipc/PBackgroundParent.h" #include "mozilla/ipc/PFileDescriptorSetParent.h" #include "MultipartBlobImpl.h" #include "nsDataHashtable.h" #include "nsHashKeys.h" #include "nsID.h" #include "nsIFileStreams.h" #include "nsIInputStream.h" #include "nsIIPCSerializableInputStream.h" #include "nsIMultiplexInputStream.h" #include "nsIRemoteBlob.h" #include "nsISeekableStream.h" #include "nsIUUIDGenerator.h" #include "nsNetCID.h" #include "nsServiceManagerUtils.h" #include "nsStringStream.h" #include "nsThreadUtils.h" #include "nsXULAppAPI.h" #include "WorkerPrivate.h" #include "WorkerRunnable.h" #ifdef DEBUG #include "BackgroundChild.h" // BackgroundChild::GetForCurrentThread(). #endif #ifdef OS_POSIX #include "chrome/common/file_descriptor_set_posix.h" #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 #define PRIVATE_REMOTE_INPUT_STREAM_IID \ {0x30c7699f, 0x51d2, 0x48c8, {0xad, 0x56, 0xc0, 0x16, 0xd7, 0x6f, 0x71, 0x27}} namespace mozilla { namespace dom { using namespace mozilla::ipc; using namespace mozilla::dom::indexedDB; using namespace mozilla::dom::workers; namespace { const char kUUIDGeneratorContractId[] = "@mozilla.org/uuid-generator;1"; const uint32_t kMaxFileDescriptorsPerMessage = 250; #ifdef OS_POSIX // Keep this in sync with other platforms. static_assert(FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE == 250, "MAX_DESCRIPTORS_PER_MESSAGE mismatch!"); #endif StaticRefPtr gUUIDGenerator; GeckoProcessType gProcessType = GeckoProcessType_Invalid; void CommonStartup() { MOZ_ASSERT(NS_IsMainThread()); gProcessType = XRE_GetProcessType(); MOZ_ASSERT(gProcessType != GeckoProcessType_Invalid); nsCOMPtr uuidGen = do_GetService(kUUIDGeneratorContractId); MOZ_RELEASE_ASSERT(uuidGen); gUUIDGenerator = uuidGen; ClearOnShutdown(&gUUIDGenerator); } template struct ConcreteManagerTypeTraits; template <> struct ConcreteManagerTypeTraits { typedef ContentChild Type; }; template <> struct ConcreteManagerTypeTraits { typedef PBackgroundChild Type; }; template <> struct ConcreteManagerTypeTraits { typedef ContentParent Type; }; template <> struct ConcreteManagerTypeTraits { typedef PBackgroundParent Type; }; 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(aManager); } intptr_t ActorManagerProcessID(PBackgroundParent* aManager) { AssertCorrectThreadForManager(aManager); MOZ_ASSERT(aManager); return BackgroundParent::GetRawContentParentForComparison(aManager); } bool ActorManagerIsSameProcess(nsIContentParent* aManager) { AssertCorrectThreadForManager(aManager); MOZ_ASSERT(aManager); return false; } bool ActorManagerIsSameProcess(PBackgroundParent* aManager) { AssertCorrectThreadForManager(aManager); MOZ_ASSERT(aManager); return !BackgroundParent::IsOtherProcessActor(aManager); } bool EventTargetIsOnCurrentThread(nsIEventTarget* aEventTarget) { if (!aEventTarget) { return NS_IsMainThread(); } bool current; // If this fails, we are probably shutting down. if (NS_WARN_IF(NS_FAILED(aEventTarget->IsOnCurrentThread(¤t)))) { return true; } return current; } class CancelableRunnableWrapper final : public CancelableRunnable { nsCOMPtr mRunnable; #ifdef DEBUG nsCOMPtr mDEBUGEventTarget; #endif public: CancelableRunnableWrapper(nsIRunnable* aRunnable, nsIEventTarget* aEventTarget) : mRunnable(aRunnable) #ifdef DEBUG , mDEBUGEventTarget(aEventTarget) #endif { MOZ_ASSERT(aRunnable); MOZ_ASSERT(aEventTarget); } NS_DECL_ISUPPORTS_INHERITED private: ~CancelableRunnableWrapper() { } NS_DECL_NSIRUNNABLE nsresult Cancel() override; }; NS_IMPL_ISUPPORTS_INHERITED0(CancelableRunnableWrapper, CancelableRunnable) NS_IMETHODIMP CancelableRunnableWrapper::Run() { DebugOnly onTarget; MOZ_ASSERT(mDEBUGEventTarget); MOZ_ASSERT(NS_SUCCEEDED(mDEBUGEventTarget->IsOnCurrentThread(&onTarget))); MOZ_ASSERT(onTarget); nsCOMPtr runnable; mRunnable.swap(runnable); if (runnable) { return runnable->Run(); } return NS_OK; } nsresult CancelableRunnableWrapper::Cancel() { DebugOnly onTarget; MOZ_ASSERT(mDEBUGEventTarget); MOZ_ASSERT(NS_SUCCEEDED(mDEBUGEventTarget->IsOnCurrentThread(&onTarget))); MOZ_ASSERT(onTarget); if (NS_WARN_IF(!mRunnable)) { return NS_ERROR_UNEXPECTED; } Unused << Run(); MOZ_ASSERT(!mRunnable); return NS_OK; } // Ensure that a nsCOMPtr/nsRefPtr is released on the target thread. template