1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/widget/IconLoader.h"
7 #include "gfxPlatform.h"
8 #include "imgIContainer.h"
10 #include "imgRequestProxy.h"
11 #include "mozilla/dom/Document.h"
12 #include "mozilla/dom/FetchPriority.h"
13 #include "nsContentUtils.h"
14 #include "nsIContent.h"
15 #include "nsIContentPolicy.h"
17 using namespace mozilla
;
19 namespace mozilla::widget
{
21 NS_IMPL_ISUPPORTS(IconLoader
, imgINotificationObserver
)
23 IconLoader::IconLoader(Listener
* aListener
) : mListener(aListener
) {}
25 IconLoader::~IconLoader() { Destroy(); }
27 void IconLoader::Destroy() {
29 mIconRequest
->CancelAndForgetObserver(NS_BINDING_ABORTED
);
30 mIconRequest
= nullptr;
35 nsresult
IconLoader::LoadIcon(nsIURI
* aIconURI
, nsINode
* aNode
,
36 bool aIsInternalIcon
) {
38 // Another icon request is already in flight. Kill it.
39 mIconRequest
->CancelWithReason(
40 NS_BINDING_ABORTED
, "Another icon request is already in flight"_ns
);
41 mIconRequest
= nullptr;
45 return NS_ERROR_FAILURE
;
48 RefPtr
<mozilla::dom::Document
> document
= aNode
->OwnerDoc();
50 nsCOMPtr
<nsILoadGroup
> loadGroup
= document
->GetDocumentLoadGroup();
52 return NS_ERROR_FAILURE
;
55 RefPtr
<imgLoader
> loader
= nsContentUtils::GetImgLoaderForDocument(document
);
57 return NS_ERROR_FAILURE
;
61 if (aIsInternalIcon
) {
62 rv
= loader
->LoadImage(
63 aIconURI
, nullptr, nullptr, nullptr, 0, loadGroup
, this, nullptr,
64 nullptr, nsIRequest::LOAD_NORMAL
, nullptr,
65 nsIContentPolicy::TYPE_INTERNAL_IMAGE
, u
""_ns
,
66 /* aUseUrgentStartForChannel */ false, /* aLinkPreload */ false, 0,
67 dom::FetchPriority::Auto
, getter_AddRefs(mIconRequest
));
69 // TODO: nsIContentPolicy::TYPE_INTERNAL_IMAGE may not be the correct
70 // policy. See bug 1691868 for more details.
71 rv
= loader
->LoadImage(
72 aIconURI
, nullptr, nullptr, aNode
->NodePrincipal(), 0, loadGroup
, this,
73 aNode
, document
, nsIRequest::LOAD_NORMAL
, nullptr,
74 nsIContentPolicy::TYPE_INTERNAL_IMAGE
, u
""_ns
,
75 /* aUseUrgentStartForChannel */ false,
76 /* aLinkPreload */ false, 0, dom::FetchPriority::Auto
,
77 getter_AddRefs(mIconRequest
));
87 // imgINotificationObserver
90 void IconLoader::Notify(imgIRequest
* aRequest
, int32_t aType
,
91 const nsIntRect
* aData
) {
92 if (aType
== imgINotificationObserver::LOAD_COMPLETE
) {
93 // Make sure the image loaded successfully.
94 uint32_t status
= imgIRequest::STATUS_ERROR
;
95 if (NS_FAILED(aRequest
->GetImageStatus(&status
)) ||
96 (status
& imgIRequest::STATUS_ERROR
)) {
97 mIconRequest
->CancelWithReason(NS_BINDING_ABORTED
,
98 "GetImageStatus failed"_ns
);
99 mIconRequest
= nullptr;
103 nsCOMPtr
<imgIContainer
> image
;
104 aRequest
->GetImage(getter_AddRefs(image
));
107 // Ask the image to decode at its intrinsic size.
108 int32_t width
= 0, height
= 0;
109 image
->GetWidth(&width
);
110 image
->GetHeight(&height
);
111 image
->RequestDecodeForSize(nsIntSize(width
, height
),
112 imgIContainer::FLAG_HIGH_QUALITY_SCALING
);
115 if (aType
== imgINotificationObserver::FRAME_COMPLETE
) {
116 nsCOMPtr
<imgIContainer
> image
;
117 aRequest
->GetImage(getter_AddRefs(image
));
121 mListener
->OnComplete(image
);
126 if (aType
== imgINotificationObserver::DECODE_COMPLETE
) {
127 if (mIconRequest
&& mIconRequest
== aRequest
) {
128 mIconRequest
->CancelWithReason(NS_BINDING_ABORTED
, "DECODE_COMPLETE"_ns
);
129 mIconRequest
= nullptr;
134 } // namespace mozilla::widget