Backed out 7 changesets (bug 1942424) for causing frequent crashes. a=backout
[gecko.git] / dom / media / mediacontrol / FetchImageHelper.cpp
blob8ba8d544851374df1422eb09e6b95bdf63fb3b59
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "FetchImageHelper.h"
7 #include "mozilla/gfx/2D.h"
8 #include "mozilla/Logging.h"
9 #include "mozilla/NullPrincipal.h"
10 #include "nsIChannel.h"
11 #include "nsNetUtil.h"
13 mozilla::LazyLogModule gFetchImageLog("FetchImageHelper");
15 #undef LOG
16 #define LOG(msg, ...) \
17 MOZ_LOG(gFetchImageLog, LogLevel::Debug, \
18 ("FetchImageHelper=%p, " msg, this, ##__VA_ARGS__))
20 using namespace mozilla::gfx;
22 namespace mozilla::dom {
24 FetchImageHelper::FetchImageHelper(const MediaImage& aImage)
25 : mSrc(aImage.mSrc) {}
27 FetchImageHelper::~FetchImageHelper() { AbortFetchingImage(); }
29 RefPtr<ImagePromise> FetchImageHelper::FetchImage() {
30 MOZ_ASSERT(NS_IsMainThread());
31 if (IsFetchingImage()) {
32 return mPromise.Ensure(__func__);
35 LOG("Start fetching image from %s", NS_ConvertUTF16toUTF8(mSrc).get());
36 nsCOMPtr<nsIURI> uri;
37 if (NS_FAILED(NS_NewURI(getter_AddRefs(uri), mSrc))) {
38 LOG("Failed to create URI");
39 return ImagePromise::CreateAndReject(false, __func__);
42 MOZ_ASSERT(!mListener);
43 mListener = new ImageFetchListener();
44 if (NS_FAILED(mListener->FetchDecodedImageFromURI(uri, this))) {
45 LOG("Failed to decode image from async channel");
46 return ImagePromise::CreateAndReject(false, __func__);
48 return mPromise.Ensure(__func__);
51 void FetchImageHelper::AbortFetchingImage() {
52 MOZ_ASSERT(NS_IsMainThread());
53 LOG("AbortFetchingImage");
54 mPromise.RejectIfExists(false, __func__);
55 ClearListenerIfNeeded();
58 void FetchImageHelper::ClearListenerIfNeeded() {
59 if (mListener) {
60 mListener->Clear();
61 mListener = nullptr;
65 bool FetchImageHelper::IsFetchingImage() const {
66 MOZ_ASSERT(NS_IsMainThread());
67 return !mPromise.IsEmpty() && mListener;
70 void FetchImageHelper::HandleFetchSuccess(imgIContainer* aImage) {
71 MOZ_ASSERT(aImage);
72 MOZ_ASSERT(NS_IsMainThread());
73 MOZ_ASSERT(IsFetchingImage());
74 LOG("Finished fetching image");
75 mPromise.Resolve(aImage, __func__);
76 ClearListenerIfNeeded();
79 void FetchImageHelper::HandleFetchFail() {
80 MOZ_ASSERT(NS_IsMainThread());
81 MOZ_ASSERT(IsFetchingImage());
82 LOG("Reject the promise because of fetching failed");
83 mPromise.RejectIfExists(false, __func__);
84 ClearListenerIfNeeded();
87 /**
88 * Implementation for FetchImageHelper::ImageFetchListener
90 NS_IMPL_ISUPPORTS(FetchImageHelper::ImageFetchListener, imgIContainerCallback)
92 FetchImageHelper::ImageFetchListener::~ImageFetchListener() {
93 MOZ_ASSERT(NS_IsMainThread());
94 MOZ_ASSERT(!mHelper, "Cancel() should be called before desturction!");
97 nsresult FetchImageHelper::ImageFetchListener::FetchDecodedImageFromURI(
98 nsIURI* aURI, FetchImageHelper* aHelper) {
99 MOZ_ASSERT(!mHelper && !mChannel,
100 "Should call Clear() berfore running another fetching process!");
101 RefPtr<nsIPrincipal> nullPrincipal =
102 NullPrincipal::CreateWithoutOriginAttributes();
103 nsCOMPtr<nsIChannel> channel;
104 nsresult rv =
105 NS_NewChannel(getter_AddRefs(channel), aURI, nullPrincipal,
106 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
107 nsIContentPolicy::TYPE_INTERNAL_IMAGE, nullptr, nullptr,
108 nullptr, nullptr, nsIRequest::LOAD_ANONYMOUS);
109 if (NS_FAILED(rv)) {
110 return rv;
113 nsCOMPtr<imgITools> imgTools = do_GetService("@mozilla.org/image/tools;1");
114 if (!imgTools) {
115 return NS_ERROR_FAILURE;
118 rv = imgTools->DecodeImageFromChannelAsync(aURI, channel, this, nullptr);
119 if (NS_FAILED(rv)) {
120 return NS_ERROR_FAILURE;
122 MOZ_ASSERT(aHelper);
123 mHelper = aHelper;
124 mChannel = channel;
125 return NS_OK;
128 void FetchImageHelper::ImageFetchListener::Clear() {
129 MOZ_ASSERT(NS_IsMainThread());
130 if (mChannel) {
131 mChannel->CancelWithReason(
132 NS_BINDING_ABORTED, "FetchImageHelper::ImageFetchListener::Clear"_ns);
133 mChannel = nullptr;
135 mHelper = nullptr;
138 bool FetchImageHelper::ImageFetchListener::IsFetchingImage() const {
139 MOZ_ASSERT(NS_IsMainThread());
140 return mHelper ? mHelper->IsFetchingImage() : false;
143 NS_IMETHODIMP FetchImageHelper::ImageFetchListener::OnImageReady(
144 imgIContainer* aImage, nsresult aStatus) {
145 MOZ_ASSERT(NS_IsMainThread());
146 if (!IsFetchingImage()) {
147 return NS_OK;
149 // We have received image, so we don't need the channel anymore.
150 mChannel = nullptr;
152 MOZ_ASSERT(mHelper);
153 if (NS_FAILED(aStatus) || !aImage) {
154 mHelper->HandleFetchFail();
155 Clear();
156 return aStatus;
159 mHelper->HandleFetchSuccess(aImage);
161 return NS_OK;
164 } // namespace mozilla::dom