1 #include "gtest/gtest.h"
3 #include "mozilla/CORSMode.h"
4 #include "mozilla/dom/XMLDocument.h"
5 #include "mozilla/dom/ReferrerPolicyBinding.h"
6 #include "mozilla/FetchPreloader.h"
7 #include "mozilla/gtest/MozAssertions.h"
8 #include "mozilla/Maybe.h"
9 #include "mozilla/PreloadHashKey.h"
10 #include "mozilla/SpinEventLoopUntil.h"
11 #include "nsNetUtil.h"
12 #include "nsIChannel.h"
13 #include "nsIStreamListener.h"
14 #include "nsISupportsPriority.h"
15 #include "nsThreadUtils.h"
16 #include "nsStringStream.h"
20 auto const ERROR_CANCEL
= NS_ERROR_ABORT
;
21 auto const ERROR_ONSTOP
= NS_ERROR_NET_INTERRUPT
;
22 auto const ERROR_THROW
= NS_ERROR_FAILURE
;
24 class FakeChannel
: public nsIChannel
{
30 nsresult
Start() { return mListener
->OnStartRequest(this); }
31 nsresult
Data(const nsACString
& aData
) {
32 if (NS_FAILED(mStatus
)) {
35 nsCOMPtr
<nsIInputStream
> is
;
36 NS_NewCStringInputStream(getter_AddRefs(is
), aData
);
37 return mListener
->OnDataAvailable(this, is
, 0, aData
.Length());
39 nsresult
Stop(nsresult status
) {
40 if (NS_SUCCEEDED(mStatus
)) {
43 mListener
->OnStopRequest(this, mStatus
);
49 virtual ~FakeChannel() = default;
50 bool mIsPending
= false;
51 bool mCanceled
= false;
52 nsresult mStatus
= NS_OK
;
53 nsCOMPtr
<nsIStreamListener
> mListener
;
56 NS_IMPL_ISUPPORTS(FakeChannel
, nsIChannel
, nsIRequest
)
58 NS_IMETHODIMP
FakeChannel::GetName(nsACString
& result
) { return NS_OK
; }
59 NS_IMETHODIMP
FakeChannel::IsPending(bool* result
) {
63 NS_IMETHODIMP
FakeChannel::GetStatus(nsresult
* status
) {
67 NS_IMETHODIMP
FakeChannel::SetCanceledReason(const nsACString
& aReason
) {
68 return SetCanceledReasonImpl(aReason
);
70 NS_IMETHODIMP
FakeChannel::GetCanceledReason(nsACString
& aReason
) {
71 return GetCanceledReasonImpl(aReason
);
73 NS_IMETHODIMP
FakeChannel::CancelWithReason(nsresult aStatus
,
74 const nsACString
& aReason
) {
75 return CancelWithReasonImpl(aStatus
, aReason
);
77 NS_IMETHODIMP
FakeChannel::Cancel(nsresult status
) {
84 NS_IMETHODIMP
FakeChannel::Suspend() { return NS_OK
; }
85 NS_IMETHODIMP
FakeChannel::Resume() { return NS_OK
; }
86 NS_IMETHODIMP
FakeChannel::GetLoadFlags(nsLoadFlags
* aLoadFlags
) {
90 NS_IMETHODIMP
FakeChannel::SetLoadFlags(nsLoadFlags aLoadFlags
) {
93 NS_IMETHODIMP
FakeChannel::GetTRRMode(nsIRequest::TRRMode
* aTRRMode
) {
94 return NS_ERROR_NOT_IMPLEMENTED
;
96 NS_IMETHODIMP
FakeChannel::SetTRRMode(nsIRequest::TRRMode aTRRMode
) {
97 return NS_ERROR_NOT_IMPLEMENTED
;
99 NS_IMETHODIMP
FakeChannel::GetLoadGroup(nsILoadGroup
** aLoadGroup
) {
102 NS_IMETHODIMP
FakeChannel::SetLoadGroup(nsILoadGroup
* aLoadGroup
) {
105 NS_IMETHODIMP
FakeChannel::GetOriginalURI(nsIURI
** aURI
) { return NS_OK
; }
106 NS_IMETHODIMP
FakeChannel::SetOriginalURI(nsIURI
* aURI
) { return NS_OK
; }
107 NS_IMETHODIMP
FakeChannel::GetURI(nsIURI
** aURI
) { return NS_OK
; }
108 NS_IMETHODIMP
FakeChannel::GetOwner(nsISupports
** aOwner
) { return NS_OK
; }
109 NS_IMETHODIMP
FakeChannel::SetOwner(nsISupports
* aOwner
) { return NS_OK
; }
110 NS_IMETHODIMP
FakeChannel::SetLoadInfo(nsILoadInfo
* aLoadInfo
) { return NS_OK
; }
111 NS_IMETHODIMP
FakeChannel::GetLoadInfo(nsILoadInfo
** aLoadInfo
) {
114 NS_IMETHODIMP
FakeChannel::GetIsDocument(bool* aIsDocument
) {
115 *aIsDocument
= false;
118 NS_IMETHODIMP
FakeChannel::GetNotificationCallbacks(
119 nsIInterfaceRequestor
** aCallbacks
) {
122 NS_IMETHODIMP
FakeChannel::SetNotificationCallbacks(
123 nsIInterfaceRequestor
* aCallbacks
) {
126 NS_IMETHODIMP
FakeChannel::GetSecurityInfo(
127 nsITransportSecurityInfo
** aSecurityInfo
) {
130 NS_IMETHODIMP
FakeChannel::GetContentType(nsACString
& aContentType
) {
133 NS_IMETHODIMP
FakeChannel::SetContentType(const nsACString
& aContentType
) {
136 NS_IMETHODIMP
FakeChannel::GetContentCharset(nsACString
& aContentCharset
) {
139 NS_IMETHODIMP
FakeChannel::SetContentCharset(
140 const nsACString
& aContentCharset
) {
143 NS_IMETHODIMP
FakeChannel::GetContentDisposition(
144 uint32_t* aContentDisposition
) {
147 NS_IMETHODIMP
FakeChannel::SetContentDisposition(uint32_t aContentDisposition
) {
150 NS_IMETHODIMP
FakeChannel::GetContentDispositionFilename(
151 nsAString
& aContentDispositionFilename
) {
154 NS_IMETHODIMP
FakeChannel::SetContentDispositionFilename(
155 const nsAString
& aContentDispositionFilename
) {
158 NS_IMETHODIMP
FakeChannel::GetContentDispositionHeader(
159 nsACString
& aContentDispositionHeader
) {
160 return NS_ERROR_NOT_AVAILABLE
;
162 NS_IMETHODIMP
FakeChannel::GetContentLength(int64_t* aContentLength
) {
165 NS_IMETHODIMP
FakeChannel::SetContentLength(int64_t aContentLength
) {
168 NS_IMETHODIMP
FakeChannel::GetCanceled(bool* aCanceled
) {
169 *aCanceled
= mCanceled
;
172 NS_IMETHODIMP
FakeChannel::Open(nsIInputStream
** aStream
) {
173 return NS_ERROR_NOT_IMPLEMENTED
;
176 FakeChannel::AsyncOpen(nsIStreamListener
* aListener
) {
178 mListener
= aListener
;
182 class FakePreloader
: public mozilla::FetchPreloader
{
184 explicit FakePreloader(FakeChannel
* aChannel
) : mDrivingChannel(aChannel
) {}
187 RefPtr
<FakeChannel
> mDrivingChannel
;
189 virtual nsresult
CreateChannel(
190 nsIChannel
** aChannel
, nsIURI
* aURI
, const mozilla::CORSMode aCORSMode
,
191 const mozilla::dom::ReferrerPolicy
& aReferrerPolicy
,
192 mozilla::dom::Document
* aDocument
, nsILoadGroup
* aLoadGroup
,
193 nsIInterfaceRequestor
* aCallbacks
, uint64_t aHttpChannelId
,
194 int32_t aSupportsPriorityValue
) override
{
195 mDrivingChannel
.forget(aChannel
);
200 class FakeListener
: public nsIStreamListener
{
202 NS_DECL_NSIREQUESTOBSERVER
203 NS_DECL_NSISTREAMLISTENER
205 enum { Never
, OnStart
, OnData
, OnStop
} mCancelIn
= Never
;
207 nsresult mOnStartResult
= NS_OK
;
208 nsresult mOnDataResult
= NS_OK
;
209 nsresult mOnStopResult
= NS_OK
;
211 bool mOnStart
= false;
213 mozilla::Maybe
<nsresult
> mOnStop
;
216 virtual ~FakeListener() = default;
219 NS_IMPL_ISUPPORTS(FakeListener
, nsIStreamListener
, nsIRequestObserver
)
221 NS_IMETHODIMP
FakeListener::OnStartRequest(nsIRequest
* request
) {
222 EXPECT_FALSE(mOnStart
);
225 if (mCancelIn
== OnStart
) {
226 request
->Cancel(ERROR_CANCEL
);
229 return mOnStartResult
;
231 NS_IMETHODIMP
FakeListener::OnDataAvailable(nsIRequest
* request
,
232 nsIInputStream
* input
,
233 uint64_t offset
, uint32_t count
) {
235 data
.SetLength(count
);
238 input
->Read(data
.BeginWriting(), count
, &read
);
241 if (mCancelIn
== OnData
) {
242 request
->Cancel(ERROR_CANCEL
);
245 return mOnDataResult
;
247 NS_IMETHODIMP
FakeListener::OnStopRequest(nsIRequest
* request
,
249 EXPECT_FALSE(mOnStop
);
250 mOnStop
.emplace(status
);
252 if (mCancelIn
== OnStop
) {
253 request
->Cancel(ERROR_CANCEL
);
256 return mOnStopResult
;
259 bool eventInProgress
= true;
262 MOZ_ALWAYS_TRUE(mozilla::SpinEventLoopUntil(
263 "uriloader:TestFetchPreloader:Await"_ns
, [&]() {
264 bool yield
= !eventInProgress
;
265 eventInProgress
= true; // Just for convenience
270 // WinBase.h defines this.
272 void Yield() { eventInProgress
= false; }
276 // ****************************************************************************
278 // ****************************************************************************
280 // Caching with all good results (data + NS_OK)
281 TEST(TestFetchPreloader
, CacheNoneBeforeConsume
)
283 nsCOMPtr
<nsIURI
> uri
;
284 NS_NewURI(getter_AddRefs(uri
), "https://example.com"_ns
);
285 auto key
= mozilla::PreloadHashKey::CreateAsFetch(uri
, mozilla::CORS_NONE
);
287 RefPtr
<FakeChannel
> channel
= new FakeChannel();
288 RefPtr
<FakePreloader
> preloader
= new FakePreloader(channel
);
289 RefPtr
<mozilla::dom::Document
> doc
;
290 NS_NewXMLDocument(getter_AddRefs(doc
), nullptr, nullptr);
292 EXPECT_TRUE(NS_SUCCEEDED(preloader
->OpenChannel(
293 key
, uri
, mozilla::CORS_NONE
, mozilla::dom::ReferrerPolicy::_empty
, doc
,
294 0, nsISupportsPriority::PRIORITY_NORMAL
)));
296 RefPtr
<FakeListener
> listener
= new FakeListener();
297 EXPECT_NS_SUCCEEDED(preloader
->AsyncConsume(listener
));
298 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
300 EXPECT_NS_SUCCEEDED(channel
->Start());
301 EXPECT_NS_SUCCEEDED(channel
->Data("one"_ns
));
302 EXPECT_NS_SUCCEEDED(channel
->Data("two"_ns
));
303 EXPECT_NS_SUCCEEDED(channel
->Data("three"_ns
));
304 EXPECT_NS_SUCCEEDED(channel
->Stop(NS_OK
));
306 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
307 EXPECT_TRUE(listener
->mOnStart
);
308 EXPECT_TRUE(listener
->mOnData
.EqualsLiteral("onetwothree"));
309 EXPECT_TRUE(listener
->mOnStop
&& *listener
->mOnStop
== NS_OK
);
316 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
319 TEST(TestFetchPreloader
, CacheStartBeforeConsume
)
321 nsCOMPtr
<nsIURI
> uri
;
322 NS_NewURI(getter_AddRefs(uri
), "https://example.com"_ns
);
323 auto key
= mozilla::PreloadHashKey::CreateAsFetch(uri
, mozilla::CORS_NONE
);
325 RefPtr
<FakeChannel
> channel
= new FakeChannel();
326 RefPtr
<FakePreloader
> preloader
= new FakePreloader(channel
);
327 RefPtr
<mozilla::dom::Document
> doc
;
328 NS_NewXMLDocument(getter_AddRefs(doc
), nullptr, nullptr);
330 EXPECT_TRUE(NS_SUCCEEDED(preloader
->OpenChannel(
331 key
, uri
, mozilla::CORS_NONE
, mozilla::dom::ReferrerPolicy::_empty
, doc
,
332 0, nsISupportsPriority::PRIORITY_NORMAL
)));
334 EXPECT_NS_SUCCEEDED(channel
->Start());
336 RefPtr
<FakeListener
> listener
= new FakeListener();
337 EXPECT_NS_SUCCEEDED(preloader
->AsyncConsume(listener
));
338 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
340 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
341 EXPECT_TRUE(listener
->mOnStart
);
343 EXPECT_NS_SUCCEEDED(channel
->Data("one"_ns
));
344 EXPECT_NS_SUCCEEDED(channel
->Data("two"_ns
));
345 EXPECT_NS_SUCCEEDED(channel
->Data("three"_ns
));
346 EXPECT_TRUE(listener
->mOnData
.EqualsLiteral("onetwothree"));
348 EXPECT_NS_SUCCEEDED(channel
->Stop(NS_OK
));
349 EXPECT_TRUE(listener
->mOnStop
&& *listener
->mOnStop
== NS_OK
);
356 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
359 TEST(TestFetchPreloader
, CachePartOfDataBeforeConsume
)
361 nsCOMPtr
<nsIURI
> uri
;
362 NS_NewURI(getter_AddRefs(uri
), "https://example.com"_ns
);
363 auto key
= mozilla::PreloadHashKey::CreateAsFetch(uri
, mozilla::CORS_NONE
);
365 RefPtr
<FakeChannel
> channel
= new FakeChannel();
366 RefPtr
<FakePreloader
> preloader
= new FakePreloader(channel
);
367 RefPtr
<mozilla::dom::Document
> doc
;
368 NS_NewXMLDocument(getter_AddRefs(doc
), nullptr, nullptr);
370 EXPECT_TRUE(NS_SUCCEEDED(preloader
->OpenChannel(
371 key
, uri
, mozilla::CORS_NONE
, mozilla::dom::ReferrerPolicy::_empty
, doc
,
372 0, nsISupportsPriority::PRIORITY_NORMAL
)));
374 EXPECT_NS_SUCCEEDED(channel
->Start());
375 EXPECT_NS_SUCCEEDED(channel
->Data("one"_ns
));
376 EXPECT_NS_SUCCEEDED(channel
->Data("two"_ns
));
378 RefPtr
<FakeListener
> listener
= new FakeListener();
379 EXPECT_NS_SUCCEEDED(preloader
->AsyncConsume(listener
));
380 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
382 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
383 EXPECT_TRUE(listener
->mOnStart
);
385 EXPECT_NS_SUCCEEDED(channel
->Data("three"_ns
));
386 EXPECT_TRUE(listener
->mOnData
.EqualsLiteral("onetwothree"));
388 EXPECT_NS_SUCCEEDED(channel
->Stop(NS_OK
));
389 EXPECT_TRUE(listener
->mOnStop
&& *listener
->mOnStop
== NS_OK
);
396 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
399 TEST(TestFetchPreloader
, CacheAllDataBeforeConsume
)
401 nsCOMPtr
<nsIURI
> uri
;
402 NS_NewURI(getter_AddRefs(uri
), "https://example.com"_ns
);
403 auto key
= mozilla::PreloadHashKey::CreateAsFetch(uri
, mozilla::CORS_NONE
);
405 RefPtr
<FakeChannel
> channel
= new FakeChannel();
406 RefPtr
<FakePreloader
> preloader
= new FakePreloader(channel
);
407 RefPtr
<mozilla::dom::Document
> doc
;
408 NS_NewXMLDocument(getter_AddRefs(doc
), nullptr, nullptr);
410 EXPECT_TRUE(NS_SUCCEEDED(preloader
->OpenChannel(
411 key
, uri
, mozilla::CORS_NONE
, mozilla::dom::ReferrerPolicy::_empty
, doc
,
412 0, nsISupportsPriority::PRIORITY_NORMAL
)));
414 EXPECT_NS_SUCCEEDED(channel
->Start());
415 EXPECT_NS_SUCCEEDED(channel
->Data("one"_ns
));
416 EXPECT_NS_SUCCEEDED(channel
->Data("two"_ns
));
417 EXPECT_NS_SUCCEEDED(channel
->Data("three"_ns
));
419 // Request consumation of the preload...
420 RefPtr
<FakeListener
> listener
= new FakeListener();
421 EXPECT_NS_SUCCEEDED(preloader
->AsyncConsume(listener
));
422 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
424 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
425 EXPECT_TRUE(listener
->mOnStart
);
426 EXPECT_TRUE(listener
->mOnData
.EqualsLiteral("onetwothree"));
428 EXPECT_NS_SUCCEEDED(channel
->Stop(NS_OK
));
429 EXPECT_TRUE(listener
->mOnStop
&& *listener
->mOnStop
== NS_OK
);
436 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
439 TEST(TestFetchPreloader
, CacheAllBeforeConsume
)
441 nsCOMPtr
<nsIURI
> uri
;
442 NS_NewURI(getter_AddRefs(uri
), "https://example.com"_ns
);
443 auto key
= mozilla::PreloadHashKey::CreateAsFetch(uri
, mozilla::CORS_NONE
);
445 RefPtr
<FakeChannel
> channel
= new FakeChannel();
446 RefPtr
<FakePreloader
> preloader
= new FakePreloader(channel
);
447 RefPtr
<mozilla::dom::Document
> doc
;
448 NS_NewXMLDocument(getter_AddRefs(doc
), nullptr, nullptr);
450 EXPECT_TRUE(NS_SUCCEEDED(preloader
->OpenChannel(
451 key
, uri
, mozilla::CORS_NONE
, mozilla::dom::ReferrerPolicy::_empty
, doc
,
452 0, nsISupportsPriority::PRIORITY_NORMAL
)));
454 EXPECT_NS_SUCCEEDED(channel
->Start());
455 EXPECT_NS_SUCCEEDED(channel
->Data("one"_ns
));
456 EXPECT_NS_SUCCEEDED(channel
->Data("two"_ns
));
457 EXPECT_NS_SUCCEEDED(channel
->Data("three"_ns
));
458 EXPECT_NS_SUCCEEDED(channel
->Stop(NS_OK
));
460 RefPtr
<FakeListener
> listener
= new FakeListener();
461 EXPECT_NS_SUCCEEDED(preloader
->AsyncConsume(listener
));
462 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
464 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
465 EXPECT_TRUE(listener
->mOnStart
);
466 EXPECT_TRUE(listener
->mOnData
.EqualsLiteral("onetwothree"));
467 EXPECT_TRUE(listener
->mOnStop
&& *listener
->mOnStop
== NS_OK
);
474 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
477 // Get data before the channel fails
478 TEST(TestFetchPreloader
, CacheAllBeforeConsumeWithChannelError
)
480 nsCOMPtr
<nsIURI
> uri
;
481 NS_NewURI(getter_AddRefs(uri
), "https://example.com"_ns
);
482 auto key
= mozilla::PreloadHashKey::CreateAsFetch(uri
, mozilla::CORS_NONE
);
484 RefPtr
<FakeChannel
> channel
= new FakeChannel();
485 RefPtr
<FakePreloader
> preloader
= new FakePreloader(channel
);
486 RefPtr
<mozilla::dom::Document
> doc
;
487 NS_NewXMLDocument(getter_AddRefs(doc
), nullptr, nullptr);
489 EXPECT_TRUE(NS_SUCCEEDED(preloader
->OpenChannel(
490 key
, uri
, mozilla::CORS_NONE
, mozilla::dom::ReferrerPolicy::_empty
, doc
,
491 0, nsISupportsPriority::PRIORITY_NORMAL
)));
493 EXPECT_NS_SUCCEEDED(channel
->Start());
494 EXPECT_NS_SUCCEEDED(channel
->Data("one"_ns
));
495 EXPECT_NS_SUCCEEDED(channel
->Data("two"_ns
));
496 EXPECT_NS_SUCCEEDED(channel
->Data("three"_ns
));
497 EXPECT_NS_FAILED(channel
->Stop(ERROR_ONSTOP
));
499 RefPtr
<FakeListener
> listener
= new FakeListener();
500 EXPECT_NS_SUCCEEDED(preloader
->AsyncConsume(listener
));
501 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
503 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
504 EXPECT_TRUE(listener
->mOnStart
);
505 EXPECT_TRUE(listener
->mOnData
.EqualsLiteral("onetwothree"));
506 EXPECT_TRUE(listener
->mOnStop
&& *listener
->mOnStop
== ERROR_ONSTOP
);
513 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
516 // Cancel the channel between caching and consuming
517 TEST(TestFetchPreloader
, CacheAllBeforeConsumeWithChannelCancel
)
519 nsCOMPtr
<nsIURI
> uri
;
520 NS_NewURI(getter_AddRefs(uri
), "https://example.com"_ns
);
521 auto key
= mozilla::PreloadHashKey::CreateAsFetch(uri
, mozilla::CORS_NONE
);
523 RefPtr
<FakeChannel
> channel
= new FakeChannel();
524 RefPtr
<FakePreloader
> preloader
= new FakePreloader(channel
);
525 RefPtr
<mozilla::dom::Document
> doc
;
526 NS_NewXMLDocument(getter_AddRefs(doc
), nullptr, nullptr);
528 EXPECT_TRUE(NS_SUCCEEDED(preloader
->OpenChannel(
529 key
, uri
, mozilla::CORS_NONE
, mozilla::dom::ReferrerPolicy::_empty
, doc
,
530 0, nsISupportsPriority::PRIORITY_NORMAL
)));
532 EXPECT_NS_SUCCEEDED(channel
->Start());
533 EXPECT_NS_SUCCEEDED(channel
->Data("one"_ns
));
534 EXPECT_NS_SUCCEEDED(channel
->Data("two"_ns
));
535 channel
->Cancel(ERROR_CANCEL
);
536 EXPECT_NS_FAILED(channel
->Stop(ERROR_CANCEL
));
538 RefPtr
<FakeListener
> listener
= new FakeListener();
539 EXPECT_NS_SUCCEEDED(preloader
->AsyncConsume(listener
));
540 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
542 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
543 EXPECT_TRUE(listener
->mOnStart
);
544 // XXX - This is hard to solve; the data is there but we won't deliver it.
545 // This is a bit different case than e.g. a network error. We want to
546 // deliver some data in that case. Cancellation probably happens because of
547 // navigation or a demand to not consume the channel anyway.
548 EXPECT_TRUE(listener
->mOnData
.IsEmpty());
549 EXPECT_TRUE(listener
->mOnStop
&& *listener
->mOnStop
== ERROR_CANCEL
);
556 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
559 // Let the listener throw while data is already cached
560 TEST(TestFetchPreloader
, CacheAllBeforeConsumeThrowFromOnStartRequest
)
562 nsCOMPtr
<nsIURI
> uri
;
563 NS_NewURI(getter_AddRefs(uri
), "https://example.com"_ns
);
564 auto key
= mozilla::PreloadHashKey::CreateAsFetch(uri
, mozilla::CORS_NONE
);
566 RefPtr
<FakeChannel
> channel
= new FakeChannel();
567 RefPtr
<FakePreloader
> preloader
= new FakePreloader(channel
);
568 RefPtr
<mozilla::dom::Document
> doc
;
569 NS_NewXMLDocument(getter_AddRefs(doc
), nullptr, nullptr);
571 EXPECT_TRUE(NS_SUCCEEDED(preloader
->OpenChannel(
572 key
, uri
, mozilla::CORS_NONE
, mozilla::dom::ReferrerPolicy::_empty
, doc
,
573 0, nsISupportsPriority::PRIORITY_NORMAL
)));
575 EXPECT_NS_SUCCEEDED(channel
->Start());
576 EXPECT_NS_SUCCEEDED(channel
->Data("one"_ns
));
577 EXPECT_NS_SUCCEEDED(channel
->Data("two"_ns
));
578 EXPECT_NS_SUCCEEDED(channel
->Data("three"_ns
));
579 EXPECT_NS_SUCCEEDED(channel
->Stop(NS_OK
));
581 RefPtr
<FakeListener
> listener
= new FakeListener();
582 listener
->mOnStartResult
= ERROR_THROW
;
584 EXPECT_NS_SUCCEEDED(preloader
->AsyncConsume(listener
));
585 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
587 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
588 EXPECT_TRUE(listener
->mOnStart
);
589 EXPECT_TRUE(listener
->mOnData
.IsEmpty());
590 EXPECT_TRUE(listener
->mOnStop
&& *listener
->mOnStop
== ERROR_THROW
);
597 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
600 TEST(TestFetchPreloader
, CacheAllBeforeConsumeThrowFromOnDataAvailable
)
602 nsCOMPtr
<nsIURI
> uri
;
603 NS_NewURI(getter_AddRefs(uri
), "https://example.com"_ns
);
604 auto key
= mozilla::PreloadHashKey::CreateAsFetch(uri
, mozilla::CORS_NONE
);
606 RefPtr
<FakeChannel
> channel
= new FakeChannel();
607 RefPtr
<FakePreloader
> preloader
= new FakePreloader(channel
);
608 RefPtr
<mozilla::dom::Document
> doc
;
609 NS_NewXMLDocument(getter_AddRefs(doc
), nullptr, nullptr);
611 EXPECT_TRUE(NS_SUCCEEDED(preloader
->OpenChannel(
612 key
, uri
, mozilla::CORS_NONE
, mozilla::dom::ReferrerPolicy::_empty
, doc
,
613 0, nsISupportsPriority::PRIORITY_NORMAL
)));
615 EXPECT_NS_SUCCEEDED(channel
->Start());
616 EXPECT_NS_SUCCEEDED(channel
->Data("one"_ns
));
617 EXPECT_NS_SUCCEEDED(channel
->Data("two"_ns
));
618 EXPECT_NS_SUCCEEDED(channel
->Data("three"_ns
));
619 EXPECT_NS_SUCCEEDED(channel
->Stop(NS_OK
));
621 RefPtr
<FakeListener
> listener
= new FakeListener();
622 listener
->mOnDataResult
= ERROR_THROW
;
624 EXPECT_NS_SUCCEEDED(preloader
->AsyncConsume(listener
));
625 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
627 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
628 EXPECT_TRUE(listener
->mOnStart
);
629 EXPECT_TRUE(listener
->mOnData
.EqualsLiteral("one"));
630 EXPECT_TRUE(listener
->mOnStop
&& *listener
->mOnStop
== ERROR_THROW
);
637 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
640 TEST(TestFetchPreloader
, CacheAllBeforeConsumeThrowFromOnStopRequest
)
642 nsCOMPtr
<nsIURI
> uri
;
643 NS_NewURI(getter_AddRefs(uri
), "https://example.com"_ns
);
644 auto key
= mozilla::PreloadHashKey::CreateAsFetch(uri
, mozilla::CORS_NONE
);
646 RefPtr
<FakeChannel
> channel
= new FakeChannel();
647 RefPtr
<FakePreloader
> preloader
= new FakePreloader(channel
);
648 RefPtr
<mozilla::dom::Document
> doc
;
649 NS_NewXMLDocument(getter_AddRefs(doc
), nullptr, nullptr);
651 EXPECT_TRUE(NS_SUCCEEDED(preloader
->OpenChannel(
652 key
, uri
, mozilla::CORS_NONE
, mozilla::dom::ReferrerPolicy::_empty
, doc
,
653 0, nsISupportsPriority::PRIORITY_NORMAL
)));
655 EXPECT_NS_SUCCEEDED(channel
->Start());
656 EXPECT_NS_SUCCEEDED(channel
->Data("one"_ns
));
657 EXPECT_NS_SUCCEEDED(channel
->Data("two"_ns
));
658 EXPECT_NS_SUCCEEDED(channel
->Data("three"_ns
));
659 EXPECT_NS_SUCCEEDED(channel
->Stop(NS_OK
));
661 RefPtr
<FakeListener
> listener
= new FakeListener();
662 listener
->mOnStopResult
= ERROR_THROW
;
664 EXPECT_NS_SUCCEEDED(preloader
->AsyncConsume(listener
));
665 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
667 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
668 EXPECT_TRUE(listener
->mOnStart
);
669 EXPECT_TRUE(listener
->mOnData
.EqualsLiteral("onetwothree"));
670 // Throwing from OnStopRequest is generally ignored.
671 EXPECT_TRUE(listener
->mOnStop
&& *listener
->mOnStop
== NS_OK
);
678 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
681 // Cancel the channel in various callbacks
682 TEST(TestFetchPreloader
, CacheAllBeforeConsumeCancelInOnStartRequest
)
684 nsCOMPtr
<nsIURI
> uri
;
685 NS_NewURI(getter_AddRefs(uri
), "https://example.com"_ns
);
686 auto key
= mozilla::PreloadHashKey::CreateAsFetch(uri
, mozilla::CORS_NONE
);
688 RefPtr
<FakeChannel
> channel
= new FakeChannel();
689 RefPtr
<FakePreloader
> preloader
= new FakePreloader(channel
);
690 RefPtr
<mozilla::dom::Document
> doc
;
691 NS_NewXMLDocument(getter_AddRefs(doc
), nullptr, nullptr);
693 EXPECT_TRUE(NS_SUCCEEDED(preloader
->OpenChannel(
694 key
, uri
, mozilla::CORS_NONE
, mozilla::dom::ReferrerPolicy::_empty
, doc
,
695 0, nsISupportsPriority::PRIORITY_NORMAL
)));
697 EXPECT_NS_SUCCEEDED(channel
->Start());
698 EXPECT_NS_SUCCEEDED(channel
->Data("one"_ns
));
699 EXPECT_NS_SUCCEEDED(channel
->Data("two"_ns
));
700 EXPECT_NS_SUCCEEDED(channel
->Data("three"_ns
));
701 EXPECT_NS_SUCCEEDED(channel
->Stop(NS_OK
));
703 RefPtr
<FakeListener
> listener
= new FakeListener();
704 listener
->mCancelIn
= FakeListener::OnStart
;
705 // check that throwing from OnStartRequest doesn't affect the cancellation
707 listener
->mOnStartResult
= ERROR_THROW
;
709 EXPECT_NS_SUCCEEDED(preloader
->AsyncConsume(listener
));
710 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
712 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
713 EXPECT_TRUE(listener
->mOnStart
);
714 EXPECT_TRUE(listener
->mOnData
.IsEmpty());
715 EXPECT_TRUE(listener
->mOnStop
&& *listener
->mOnStop
== ERROR_CANCEL
);
722 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
725 TEST(TestFetchPreloader
, CacheAllBeforeConsumeCancelInOnDataAvailable
)
727 nsCOMPtr
<nsIURI
> uri
;
728 NS_NewURI(getter_AddRefs(uri
), "https://example.com"_ns
);
729 auto key
= mozilla::PreloadHashKey::CreateAsFetch(uri
, mozilla::CORS_NONE
);
731 RefPtr
<FakeChannel
> channel
= new FakeChannel();
732 RefPtr
<FakePreloader
> preloader
= new FakePreloader(channel
);
733 RefPtr
<mozilla::dom::Document
> doc
;
734 NS_NewXMLDocument(getter_AddRefs(doc
), nullptr, nullptr);
736 EXPECT_TRUE(NS_SUCCEEDED(preloader
->OpenChannel(
737 key
, uri
, mozilla::CORS_NONE
, mozilla::dom::ReferrerPolicy::_empty
, doc
,
738 0, nsISupportsPriority::PRIORITY_NORMAL
)));
740 EXPECT_NS_SUCCEEDED(channel
->Start());
741 EXPECT_NS_SUCCEEDED(channel
->Data("one"_ns
));
742 EXPECT_NS_SUCCEEDED(channel
->Data("two"_ns
));
743 EXPECT_NS_SUCCEEDED(channel
->Data("three"_ns
));
744 EXPECT_NS_SUCCEEDED(channel
->Stop(NS_OK
));
746 RefPtr
<FakeListener
> listener
= new FakeListener();
747 listener
->mCancelIn
= FakeListener::OnData
;
748 // check that throwing from OnStartRequest doesn't affect the cancellation
750 listener
->mOnDataResult
= ERROR_THROW
;
752 EXPECT_NS_SUCCEEDED(preloader
->AsyncConsume(listener
));
753 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
755 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
756 EXPECT_TRUE(listener
->mOnStart
);
757 EXPECT_TRUE(listener
->mOnData
.EqualsLiteral("one"));
758 EXPECT_TRUE(listener
->mOnStop
&& *listener
->mOnStop
== ERROR_CANCEL
);
765 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
769 TEST(TestFetchPreloader
, CachePartlyBeforeConsumeCancelInOnDataAvailable
)
771 nsCOMPtr
<nsIURI
> uri
;
772 NS_NewURI(getter_AddRefs(uri
), "https://example.com"_ns
);
773 auto key
= mozilla::PreloadHashKey::CreateAsFetch(uri
, mozilla::CORS_NONE
);
775 RefPtr
<FakeChannel
> channel
= new FakeChannel();
776 RefPtr
<FakePreloader
> preloader
= new FakePreloader(channel
);
777 RefPtr
<mozilla::dom::Document
> doc
;
778 NS_NewXMLDocument(getter_AddRefs(doc
), nullptr, nullptr);
780 EXPECT_TRUE(NS_SUCCEEDED(preloader
->OpenChannel(
781 key
, uri
, mozilla::CORS_NONE
, mozilla::dom::ReferrerPolicy::_empty
, doc
,
782 0, nsISupportsPriority::PRIORITY_NORMAL
)));
784 EXPECT_NS_SUCCEEDED(channel
->Start());
785 EXPECT_NS_SUCCEEDED(channel
->Data("one"_ns
));
786 EXPECT_NS_SUCCEEDED(channel
->Data("two"_ns
));
788 RefPtr
<FakeListener
> listener
= new FakeListener();
789 listener
->mCancelIn
= FakeListener::OnData
;
791 EXPECT_NS_SUCCEEDED(preloader
->AsyncConsume(listener
));
792 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
794 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
795 EXPECT_NS_FAILED(channel
->Data("three"_ns
));
796 EXPECT_NS_FAILED(channel
->Stop(NS_OK
));
798 EXPECT_TRUE(listener
->mOnStart
);
799 EXPECT_TRUE(listener
->mOnData
.EqualsLiteral("one"));
800 EXPECT_TRUE(listener
->mOnStop
&& *listener
->mOnStop
== ERROR_CANCEL
);
807 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
810 TEST(TestFetchPreloader
, CachePartlyBeforeConsumeCancelInOnStartRequestAndRace
)
812 nsCOMPtr
<nsIURI
> uri
;
813 NS_NewURI(getter_AddRefs(uri
), "https://example.com"_ns
);
814 auto key
= mozilla::PreloadHashKey::CreateAsFetch(uri
, mozilla::CORS_NONE
);
816 RefPtr
<FakeChannel
> channel
= new FakeChannel();
817 RefPtr
<FakePreloader
> preloader
= new FakePreloader(channel
);
818 RefPtr
<mozilla::dom::Document
> doc
;
819 NS_NewXMLDocument(getter_AddRefs(doc
), nullptr, nullptr);
821 EXPECT_TRUE(NS_SUCCEEDED(preloader
->OpenChannel(
822 key
, uri
, mozilla::CORS_NONE
, mozilla::dom::ReferrerPolicy::_empty
, doc
,
823 0, nsISupportsPriority::PRIORITY_NORMAL
)));
825 EXPECT_NS_SUCCEEDED(channel
->Start());
826 EXPECT_NS_SUCCEEDED(channel
->Data("one"_ns
));
827 EXPECT_NS_SUCCEEDED(channel
->Data("two"_ns
));
829 // This has to simulate a possibiilty when stream listener notifications from
830 // the channel are already pending in the queue while AsyncConsume is called.
831 // At this moment the listener has not been notified yet.
832 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
833 EXPECT_NS_SUCCEEDED(channel
->Data("three"_ns
));
834 EXPECT_NS_SUCCEEDED(channel
->Stop(NS_OK
));
837 RefPtr
<FakeListener
> listener
= new FakeListener();
838 listener
->mCancelIn
= FakeListener::OnStart
;
840 EXPECT_NS_SUCCEEDED(preloader
->AsyncConsume(listener
));
841 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
843 // Check listener's been fed properly. Expected is to NOT get any data and
844 // propagate the cancellation code and not being called duplicated
846 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
847 EXPECT_TRUE(listener
->mOnStart
);
848 EXPECT_TRUE(listener
->mOnData
.IsEmpty());
849 EXPECT_TRUE(listener
->mOnStop
&& *listener
->mOnStop
== ERROR_CANCEL
);
856 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
859 TEST(TestFetchPreloader
, CachePartlyBeforeConsumeCancelInOnDataAvailableAndRace
)
861 nsCOMPtr
<nsIURI
> uri
;
862 NS_NewURI(getter_AddRefs(uri
), "https://example.com"_ns
);
863 auto key
= mozilla::PreloadHashKey::CreateAsFetch(uri
, mozilla::CORS_NONE
);
865 RefPtr
<FakeChannel
> channel
= new FakeChannel();
866 RefPtr
<FakePreloader
> preloader
= new FakePreloader(channel
);
867 RefPtr
<mozilla::dom::Document
> doc
;
868 NS_NewXMLDocument(getter_AddRefs(doc
), nullptr, nullptr);
870 EXPECT_TRUE(NS_SUCCEEDED(preloader
->OpenChannel(
871 key
, uri
, mozilla::CORS_NONE
, mozilla::dom::ReferrerPolicy::_empty
, doc
,
872 0, nsISupportsPriority::PRIORITY_NORMAL
)));
874 EXPECT_NS_SUCCEEDED(channel
->Start());
875 EXPECT_NS_SUCCEEDED(channel
->Data("one"_ns
));
876 EXPECT_NS_SUCCEEDED(channel
->Data("two"_ns
));
878 // This has to simulate a possibiilty when stream listener notifications from
879 // the channel are already pending in the queue while AsyncConsume is called.
880 // At this moment the listener has not been notified yet.
881 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
882 EXPECT_NS_SUCCEEDED(channel
->Data("three"_ns
));
883 EXPECT_NS_SUCCEEDED(channel
->Stop(NS_OK
));
886 RefPtr
<FakeListener
> listener
= new FakeListener();
887 listener
->mCancelIn
= FakeListener::OnData
;
889 EXPECT_NS_SUCCEEDED(preloader
->AsyncConsume(listener
));
890 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
892 // Check listener's been fed properly. Expected is to NOT get anything after
893 // the first OnData and propagate the cancellation code and not being called
894 // duplicated OnStopRequest.
895 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
896 EXPECT_TRUE(listener
->mOnStart
);
897 EXPECT_TRUE(listener
->mOnData
.EqualsLiteral("one"));
898 EXPECT_TRUE(listener
->mOnStop
&& *listener
->mOnStop
== ERROR_CANCEL
);
905 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
908 TEST(TestFetchPreloader
, CachePartlyBeforeConsumeThrowFromOnStartRequestAndRace
)
910 nsCOMPtr
<nsIURI
> uri
;
911 NS_NewURI(getter_AddRefs(uri
), "https://example.com"_ns
);
912 auto key
= mozilla::PreloadHashKey::CreateAsFetch(uri
, mozilla::CORS_NONE
);
914 RefPtr
<FakeChannel
> channel
= new FakeChannel();
915 RefPtr
<FakePreloader
> preloader
= new FakePreloader(channel
);
916 RefPtr
<mozilla::dom::Document
> doc
;
917 NS_NewXMLDocument(getter_AddRefs(doc
), nullptr, nullptr);
919 EXPECT_TRUE(NS_SUCCEEDED(preloader
->OpenChannel(
920 key
, uri
, mozilla::CORS_NONE
, mozilla::dom::ReferrerPolicy::_empty
, doc
,
921 0, nsISupportsPriority::PRIORITY_NORMAL
)));
923 EXPECT_NS_SUCCEEDED(channel
->Start());
924 EXPECT_NS_SUCCEEDED(channel
->Data("one"_ns
));
925 EXPECT_NS_SUCCEEDED(channel
->Data("two"_ns
));
927 // This has to simulate a possibiilty when stream listener notifications from
928 // the channel are already pending in the queue while AsyncConsume is called.
929 // At this moment the listener has not been notified yet.
930 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
931 EXPECT_NS_SUCCEEDED(channel
->Data("three"_ns
));
932 EXPECT_NS_SUCCEEDED(channel
->Stop(NS_OK
));
935 RefPtr
<FakeListener
> listener
= new FakeListener();
936 listener
->mOnStartResult
= ERROR_THROW
;
938 EXPECT_NS_SUCCEEDED(preloader
->AsyncConsume(listener
));
939 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));
941 // Check listener's been fed properly. Expected is to NOT get any data and
942 // propagate the throwing code and not being called duplicated OnStopRequest.
943 NS_DispatchToMainThread(NS_NewRunnableFunction("test", [&]() {
944 EXPECT_TRUE(listener
->mOnStart
);
945 EXPECT_TRUE(listener
->mOnData
.IsEmpty());
946 EXPECT_TRUE(listener
->mOnStop
&& *listener
->mOnStop
== ERROR_THROW
);
953 EXPECT_FALSE(NS_SUCCEEDED(preloader
->AsyncConsume(listener
)));