summaryrefslogtreecommitdiffstats
path: root/dom/file/TemporaryFileBlobImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/file/TemporaryFileBlobImpl.cpp126
1 files changed, 126 insertions, 0 deletions
diff --git a/dom/file/TemporaryFileBlobImpl.cpp b/dom/file/TemporaryFileBlobImpl.cpp
new file mode 100644
index 0000000000..505d4a96d4
--- /dev/null
+++ b/dom/file/TemporaryFileBlobImpl.cpp
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "TemporaryFileBlobImpl.h"
+
+#include "RemoteLazyInputStreamThread.h"
+#include "mozilla/ErrorResult.h"
+#include "nsFileStreams.h"
+#include "nsIFile.h"
+#include "nsIFileStreams.h"
+#include "nsNetUtil.h"
+#include "nsThreadUtils.h"
+#include "nsXULAppAPI.h"
+
+using namespace mozilla::ipc;
+
+namespace mozilla::dom {
+
+namespace {
+
+// Here the flags needed in order to keep the temporary file opened.
+// 1. REOPEN_ON_REWIND -> otherwise the stream is not serializable more than
+// once.
+// 2. no DEFER_OPEN -> the file must be kept open on windows in order to be
+// deleted when used.
+// 3. no CLOSE_ON_EOF -> the file will be closed by the DTOR. No needs. Also
+// because the inputStream will not be read directly.
+// 4. no SHARE_DELETE -> We don't want to allow this file to be deleted.
+const uint32_t sTemporaryFileStreamFlags = nsIFileInputStream::REOPEN_ON_REWIND;
+
+class TemporaryFileInputStream final : public nsFileInputStream {
+ public:
+ static nsresult Create(nsIFile* aFile, nsIInputStream** aInputStream) {
+ MOZ_ASSERT(aFile);
+ MOZ_ASSERT(aInputStream);
+ MOZ_ASSERT(XRE_IsParentProcess());
+
+ RefPtr<TemporaryFileInputStream> stream =
+ new TemporaryFileInputStream(aFile);
+
+ nsresult rv = stream->Init(aFile, -1, -1, sTemporaryFileStreamFlags);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ stream.forget(aInputStream);
+ return NS_OK;
+ }
+
+ void Serialize(InputStreamParams& aParams, uint32_t aMaxSize,
+ uint32_t* aSizeUsed) override {
+ MOZ_CRASH("This inputStream cannot be serialized.");
+ }
+
+ bool Deserialize(const InputStreamParams& aParams) override {
+ MOZ_CRASH("This inputStream cannot be deserialized.");
+ return false;
+ }
+
+ private:
+ explicit TemporaryFileInputStream(nsIFile* aFile) : mFile(aFile) {
+ MOZ_ASSERT(XRE_IsParentProcess());
+ }
+
+ ~TemporaryFileInputStream() override {
+ // Let's delete the file on the RemoteLazyInputStream Thread.
+ RefPtr<RemoteLazyInputStreamThread> thread =
+ RemoteLazyInputStreamThread::GetOrCreate();
+ if (NS_WARN_IF(!thread)) {
+ return;
+ }
+
+ nsCOMPtr<nsIFile> file = std::move(mFile);
+ thread->Dispatch(
+ NS_NewRunnableFunction("TemporaryFileInputStream::Runnable",
+ [file]() { file->Remove(false); }));
+ }
+
+ nsCOMPtr<nsIFile> mFile;
+};
+
+} // namespace
+
+TemporaryFileBlobImpl::TemporaryFileBlobImpl(nsIFile* aFile,
+ const nsAString& aContentType)
+ : FileBlobImpl(aFile, u""_ns, aContentType)
+#ifdef DEBUG
+ ,
+ mInputStreamCreated(false)
+#endif
+{
+ MOZ_ASSERT(XRE_IsParentProcess());
+
+ // This must be considered a blob.
+ mIsFile = false;
+}
+
+TemporaryFileBlobImpl::~TemporaryFileBlobImpl() {
+ MOZ_ASSERT(mInputStreamCreated);
+}
+
+already_AddRefed<BlobImpl> TemporaryFileBlobImpl::CreateSlice(
+ uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
+ ErrorResult& aRv) const {
+ MOZ_CRASH("This BlobImpl is not meant to be sliced!");
+ return nullptr;
+}
+
+void TemporaryFileBlobImpl::CreateInputStream(nsIInputStream** aStream,
+ ErrorResult& aRv) const {
+#ifdef DEBUG
+ MOZ_ASSERT(!mInputStreamCreated);
+ // CreateInputStream can be called only once.
+ mInputStreamCreated = true;
+#endif
+
+ aRv = TemporaryFileInputStream::Create(mFile, aStream);
+ if (NS_WARN_IF(aRv.Failed())) {
+ return;
+ }
+}
+
+} // namespace mozilla::dom