1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "MutableBlobStreamListener.h"
8 #include "MutableBlobStorage.h"
9 #include "nsIInputStream.h"
10 #include "nsThreadUtils.h"
11
12 namespace mozilla {
13 namespace dom {
14
MutableBlobStreamListener(MutableBlobStorage::MutableBlobStorageType aStorageType,const nsACString & aContentType,MutableBlobStorageCallback * aCallback,nsIEventTarget * aEventTarget)15 MutableBlobStreamListener::MutableBlobStreamListener(
16 MutableBlobStorage::MutableBlobStorageType aStorageType,
17 const nsACString& aContentType, MutableBlobStorageCallback* aCallback,
18 nsIEventTarget* aEventTarget)
19 : mCallback(aCallback),
20 mStorageType(aStorageType),
21 mContentType(aContentType),
22 mEventTarget(aEventTarget) {
23 MOZ_ASSERT(NS_IsMainThread());
24 MOZ_ASSERT(aCallback);
25
26 if (!mEventTarget) {
27 mEventTarget = GetMainThreadEventTarget();
28 }
29
30 MOZ_ASSERT(mEventTarget);
31 }
32
~MutableBlobStreamListener()33 MutableBlobStreamListener::~MutableBlobStreamListener() {
34 MOZ_ASSERT(NS_IsMainThread());
35 }
36
NS_IMPL_ISUPPORTS(MutableBlobStreamListener,nsIStreamListener,nsIThreadRetargetableStreamListener,nsIRequestObserver)37 NS_IMPL_ISUPPORTS(MutableBlobStreamListener, nsIStreamListener,
38 nsIThreadRetargetableStreamListener, nsIRequestObserver)
39
40 NS_IMETHODIMP
41 MutableBlobStreamListener::OnStartRequest(nsIRequest* aRequest) {
42 MOZ_ASSERT(NS_IsMainThread());
43 MOZ_ASSERT(!mStorage);
44 MOZ_ASSERT(mEventTarget);
45
46 mStorage = new MutableBlobStorage(mStorageType, mEventTarget);
47 return NS_OK;
48 }
49
50 NS_IMETHODIMP
OnStopRequest(nsIRequest * aRequest,nsresult aStatus)51 MutableBlobStreamListener::OnStopRequest(nsIRequest* aRequest,
52 nsresult aStatus) {
53 MOZ_ASSERT(NS_IsMainThread());
54 MOZ_ASSERT(mStorage);
55
56 // Resetting mStorage to nullptr.
57 RefPtr<MutableBlobStorage> storage;
58 storage.swap(mStorage);
59
60 // Let's propagate the error simulating a failure of the storage.
61 if (NS_FAILED(aStatus)) {
62 mCallback->BlobStoreCompleted(storage, nullptr, aStatus);
63 return NS_OK;
64 }
65
66 storage->GetBlobImplWhenReady(mContentType, mCallback);
67 return NS_OK;
68 }
69
70 NS_IMETHODIMP
OnDataAvailable(nsIRequest * aRequest,nsIInputStream * aStream,uint64_t aSourceOffset,uint32_t aCount)71 MutableBlobStreamListener::OnDataAvailable(nsIRequest* aRequest,
72 nsIInputStream* aStream,
73 uint64_t aSourceOffset,
74 uint32_t aCount) {
75 // This method could be called on any thread.
76 MOZ_ASSERT(mStorage);
77
78 uint32_t countRead;
79 return aStream->ReadSegments(WriteSegmentFun, this, aCount, &countRead);
80 }
81
WriteSegmentFun(nsIInputStream * aWriterStream,void * aClosure,const char * aFromSegment,uint32_t aToOffset,uint32_t aCount,uint32_t * aWriteCount)82 nsresult MutableBlobStreamListener::WriteSegmentFun(
83 nsIInputStream* aWriterStream, void* aClosure, const char* aFromSegment,
84 uint32_t aToOffset, uint32_t aCount, uint32_t* aWriteCount) {
85 // This method could be called on any thread.
86
87 MutableBlobStreamListener* self =
88 static_cast<MutableBlobStreamListener*>(aClosure);
89 MOZ_ASSERT(self->mStorage);
90
91 nsresult rv = self->mStorage->Append(aFromSegment, aCount);
92 if (NS_WARN_IF(NS_FAILED(rv))) {
93 return rv;
94 }
95
96 *aWriteCount = aCount;
97 return NS_OK;
98 }
99
100 NS_IMETHODIMP
CheckListenerChain()101 MutableBlobStreamListener::CheckListenerChain() { return NS_OK; }
102
103 } // namespace dom
104 } // namespace mozilla
105