Bumping gaia.json for 3 gaia revision(s) a=gaia-bump
[gecko.git] / netwerk / protocol / wyciwyg / nsWyciwygChannel.cpp
blob42c6d00f412e9c4fa6c99a3ca248bbecb923bfb8
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
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/. */
7 #include "nsWyciwyg.h"
8 #include "nsWyciwygChannel.h"
9 #include "nsILoadGroup.h"
10 #include "nsNetUtil.h"
11 #include "LoadContextInfo.h"
12 #include "nsICacheService.h" // only to initialize
13 #include "nsICacheStorageService.h"
14 #include "nsICacheStorage.h"
15 #include "nsICacheEntry.h"
16 #include "CacheObserver.h"
17 #include "nsCharsetSource.h"
18 #include "nsProxyRelease.h"
19 #include "nsThreadUtils.h"
20 #include "nsIEventTarget.h"
21 #include "nsIInputStream.h"
22 #include "nsIInputStreamPump.h"
23 #include "nsIOutputStream.h"
24 #include "nsIProgressEventSink.h"
25 #include "nsIURI.h"
26 #include "mozilla/DebugOnly.h"
27 #include "mozilla/unused.h"
29 typedef mozilla::net::LoadContextInfo LoadContextInfo;
31 // Must release mChannel on the main thread
32 class nsWyciwygAsyncEvent : public nsRunnable {
33 public:
34 explicit nsWyciwygAsyncEvent(nsWyciwygChannel *aChannel) : mChannel(aChannel) {}
36 ~nsWyciwygAsyncEvent()
38 nsCOMPtr<nsIThread> thread = do_GetMainThread();
39 NS_WARN_IF_FALSE(thread, "Couldn't get the main thread!");
40 if (thread) {
41 nsIWyciwygChannel *chan = static_cast<nsIWyciwygChannel *>(mChannel);
42 mozilla::unused << mChannel.forget();
43 NS_ProxyRelease(thread, chan);
46 protected:
47 nsRefPtr<nsWyciwygChannel> mChannel;
50 class nsWyciwygSetCharsetandSourceEvent : public nsWyciwygAsyncEvent {
51 public:
52 explicit nsWyciwygSetCharsetandSourceEvent(nsWyciwygChannel *aChannel)
53 : nsWyciwygAsyncEvent(aChannel) {}
55 NS_IMETHOD Run()
57 mChannel->SetCharsetAndSourceInternal();
58 return NS_OK;
62 class nsWyciwygWriteEvent : public nsWyciwygAsyncEvent {
63 public:
64 nsWyciwygWriteEvent(nsWyciwygChannel *aChannel, const nsAString &aData)
65 : nsWyciwygAsyncEvent(aChannel), mData(aData) {}
67 NS_IMETHOD Run()
69 mChannel->WriteToCacheEntryInternal(mData);
70 return NS_OK;
72 private:
73 nsString mData;
76 class nsWyciwygCloseEvent : public nsWyciwygAsyncEvent {
77 public:
78 nsWyciwygCloseEvent(nsWyciwygChannel *aChannel, nsresult aReason)
79 : nsWyciwygAsyncEvent(aChannel), mReason(aReason) {}
81 NS_IMETHOD Run()
83 mChannel->CloseCacheEntryInternal(mReason);
84 return NS_OK;
86 private:
87 nsresult mReason;
91 // nsWyciwygChannel methods
92 nsWyciwygChannel::nsWyciwygChannel()
93 : mMode(NONE),
94 mStatus(NS_OK),
95 mIsPending(false),
96 mCharsetAndSourceSet(false),
97 mNeedToWriteCharset(false),
98 mCharsetSource(kCharsetUninitialized),
99 mContentLength(-1),
100 mLoadFlags(LOAD_NORMAL),
101 mAppId(NECKO_NO_APP_ID),
102 mInBrowser(false)
106 nsWyciwygChannel::~nsWyciwygChannel()
110 NS_IMPL_ISUPPORTS(nsWyciwygChannel,
111 nsIChannel,
112 nsIRequest,
113 nsIStreamListener,
114 nsIRequestObserver,
115 nsICacheEntryOpenCallback,
116 nsIWyciwygChannel,
117 nsIPrivateBrowsingChannel)
119 nsresult
120 nsWyciwygChannel::Init(nsIURI* uri)
122 NS_ENSURE_ARG_POINTER(uri);
124 nsresult rv;
126 if (!mozilla::net::CacheObserver::UseNewCache()) {
127 // Since nsWyciwygChannel can use the new cache API off the main thread
128 // and that API normally does this initiation, we need to take care
129 // of initiating the old cache service here manually. Will be removed
130 // with bug 913828.
131 MOZ_ASSERT(NS_IsMainThread());
132 nsCOMPtr<nsICacheService> service =
133 do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
136 mURI = uri;
137 mOriginalURI = uri;
139 nsCOMPtr<nsICacheStorageService> serv =
140 do_GetService("@mozilla.org/netwerk/cache-storage-service;1", &rv);
141 NS_ENSURE_SUCCESS(rv, rv);
143 rv = serv->GetIoTarget(getter_AddRefs(mCacheIOTarget));
144 NS_ENSURE_SUCCESS(rv, rv);
146 return NS_OK;
149 ///////////////////////////////////////////////////////////////////////////////
150 // nsIRequest methods:
151 ///////////////////////////////////////////////////////////////////////////////
153 NS_IMETHODIMP
154 nsWyciwygChannel::GetName(nsACString &aName)
156 return mURI->GetSpec(aName);
159 NS_IMETHODIMP
160 nsWyciwygChannel::IsPending(bool *aIsPending)
162 *aIsPending = mIsPending;
163 return NS_OK;
166 NS_IMETHODIMP
167 nsWyciwygChannel::GetStatus(nsresult *aStatus)
169 if (NS_SUCCEEDED(mStatus) && mPump)
170 mPump->GetStatus(aStatus);
171 else
172 *aStatus = mStatus;
173 return NS_OK;
176 NS_IMETHODIMP
177 nsWyciwygChannel::Cancel(nsresult status)
179 mStatus = status;
180 if (mPump)
181 mPump->Cancel(status);
182 // else we're waiting for OnCacheEntryAvailable
183 return NS_OK;
186 NS_IMETHODIMP
187 nsWyciwygChannel::Suspend()
189 if (mPump)
190 mPump->Suspend();
191 // XXX else, we'll ignore this ... and that's probably bad!
192 return NS_OK;
195 NS_IMETHODIMP
196 nsWyciwygChannel::Resume()
198 if (mPump)
199 mPump->Resume();
200 // XXX else, we'll ignore this ... and that's probably bad!
201 return NS_OK;
204 NS_IMETHODIMP
205 nsWyciwygChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
207 *aLoadGroup = mLoadGroup;
208 NS_IF_ADDREF(*aLoadGroup);
209 return NS_OK;
212 NS_IMETHODIMP
213 nsWyciwygChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
215 if (!CanSetLoadGroup(aLoadGroup)) {
216 return NS_ERROR_FAILURE;
219 mLoadGroup = aLoadGroup;
220 NS_QueryNotificationCallbacks(mCallbacks,
221 mLoadGroup,
222 NS_GET_IID(nsIProgressEventSink),
223 getter_AddRefs(mProgressSink));
224 mPrivateBrowsing = NS_UsePrivateBrowsing(this);
225 NS_GetAppInfo(this, &mAppId, &mInBrowser);
226 return NS_OK;
229 NS_IMETHODIMP
230 nsWyciwygChannel::SetLoadFlags(uint32_t aLoadFlags)
232 mLoadFlags = aLoadFlags;
233 return NS_OK;
236 NS_IMETHODIMP
237 nsWyciwygChannel::GetLoadFlags(uint32_t * aLoadFlags)
239 *aLoadFlags = mLoadFlags;
240 return NS_OK;
243 ////////////////////////////////////////////////////////////////////////////////
244 // nsIChannel methods:
245 ///////////////////////////////////////////////////////////////////////////////
247 NS_IMETHODIMP
248 nsWyciwygChannel::GetOriginalURI(nsIURI* *aURI)
250 *aURI = mOriginalURI;
251 NS_ADDREF(*aURI);
252 return NS_OK;
255 NS_IMETHODIMP
256 nsWyciwygChannel::SetOriginalURI(nsIURI* aURI)
258 NS_ENSURE_ARG_POINTER(aURI);
259 mOriginalURI = aURI;
260 return NS_OK;
263 NS_IMETHODIMP
264 nsWyciwygChannel::GetURI(nsIURI* *aURI)
266 *aURI = mURI;
267 NS_IF_ADDREF(*aURI);
268 return NS_OK;
271 NS_IMETHODIMP
272 nsWyciwygChannel::GetOwner(nsISupports **aOwner)
274 NS_IF_ADDREF(*aOwner = mOwner);
275 return NS_OK;
278 NS_IMETHODIMP
279 nsWyciwygChannel::SetOwner(nsISupports* aOwner)
281 mOwner = aOwner;
282 return NS_OK;
285 NS_IMETHODIMP
286 nsWyciwygChannel::GetLoadInfo(nsILoadInfo **aLoadInfo)
288 NS_IF_ADDREF(*aLoadInfo = mLoadInfo);
289 return NS_OK;
292 NS_IMETHODIMP
293 nsWyciwygChannel::SetLoadInfo(nsILoadInfo* aLoadInfo)
295 mLoadInfo = aLoadInfo;
296 return NS_OK;
299 NS_IMETHODIMP
300 nsWyciwygChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aCallbacks)
302 *aCallbacks = mCallbacks.get();
303 NS_IF_ADDREF(*aCallbacks);
304 return NS_OK;
307 NS_IMETHODIMP
308 nsWyciwygChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
310 if (!CanSetCallbacks(aNotificationCallbacks)) {
311 return NS_ERROR_FAILURE;
314 mCallbacks = aNotificationCallbacks;
315 NS_QueryNotificationCallbacks(mCallbacks,
316 mLoadGroup,
317 NS_GET_IID(nsIProgressEventSink),
318 getter_AddRefs(mProgressSink));
320 mPrivateBrowsing = NS_UsePrivateBrowsing(this);
321 NS_GetAppInfo(this, &mAppId, &mInBrowser);
323 return NS_OK;
326 NS_IMETHODIMP
327 nsWyciwygChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
329 NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo);
331 return NS_OK;
334 NS_IMETHODIMP
335 nsWyciwygChannel::GetContentType(nsACString &aContentType)
337 aContentType.AssignLiteral(WYCIWYG_TYPE);
338 return NS_OK;
341 NS_IMETHODIMP
342 nsWyciwygChannel::SetContentType(const nsACString &aContentType)
344 return NS_ERROR_NOT_IMPLEMENTED;
347 NS_IMETHODIMP
348 nsWyciwygChannel::GetContentCharset(nsACString &aContentCharset)
350 aContentCharset.AssignLiteral("UTF-16");
351 return NS_OK;
354 NS_IMETHODIMP
355 nsWyciwygChannel::SetContentCharset(const nsACString &aContentCharset)
357 return NS_ERROR_NOT_IMPLEMENTED;
360 NS_IMETHODIMP
361 nsWyciwygChannel::GetContentDisposition(uint32_t *aContentDisposition)
363 return NS_ERROR_NOT_AVAILABLE;
366 NS_IMETHODIMP
367 nsWyciwygChannel::SetContentDisposition(uint32_t aContentDisposition)
369 return NS_ERROR_NOT_AVAILABLE;
372 NS_IMETHODIMP
373 nsWyciwygChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename)
375 return NS_ERROR_NOT_AVAILABLE;
378 NS_IMETHODIMP
379 nsWyciwygChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename)
381 return NS_ERROR_NOT_AVAILABLE;
384 NS_IMETHODIMP
385 nsWyciwygChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader)
387 return NS_ERROR_NOT_AVAILABLE;
390 NS_IMETHODIMP
391 nsWyciwygChannel::GetContentLength(int64_t *aContentLength)
393 *aContentLength = mContentLength;
394 return NS_OK;
397 NS_IMETHODIMP
398 nsWyciwygChannel::SetContentLength(int64_t aContentLength)
400 mContentLength = aContentLength;
402 return NS_OK;
405 NS_IMETHODIMP
406 nsWyciwygChannel::Open(nsIInputStream ** aReturn)
408 return NS_ERROR_NOT_IMPLEMENTED;
411 NS_IMETHODIMP
412 nsWyciwygChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx)
414 LOG(("nsWyciwygChannel::AsyncOpen [this=%p]\n", this));
415 MOZ_ASSERT(mMode == NONE, "nsWyciwygChannel already open");
417 NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
418 NS_ENSURE_TRUE(mMode == NONE, NS_ERROR_IN_PROGRESS);
419 NS_ENSURE_ARG_POINTER(listener);
421 mMode = READING;
423 // open a cache entry for this channel...
424 // mIsPending set to true since OnCacheEntryAvailable may be called
425 // synchronously and fails when mIsPending found false.
426 mIsPending = true;
427 nsresult rv = OpenCacheEntry(mURI, nsICacheStorage::OPEN_READONLY |
428 nsICacheStorage::CHECK_MULTITHREADED);
429 if (NS_FAILED(rv)) {
430 LOG(("nsWyciwygChannel::OpenCacheEntry failed [rv=%x]\n", rv));
431 mIsPending = false;
432 return rv;
435 // There is no code path that would invoke the listener sooner than
436 // we get to this line in case OnCacheEntryAvailable is invoked
437 // synchronously.
438 mListener = listener;
439 mListenerContext = ctx;
441 if (mLoadGroup)
442 mLoadGroup->AddRequest(this, nullptr);
444 return NS_OK;
447 //////////////////////////////////////////////////////////////////////////////
448 // nsIWyciwygChannel
449 //////////////////////////////////////////////////////////////////////////////
451 nsresult
452 nsWyciwygChannel::EnsureWriteCacheEntry()
454 MOZ_ASSERT(mMode == WRITING, "nsWyciwygChannel not open for writing");
456 if (!mCacheEntry) {
457 // OPEN_TRUNCATE will give us the entry instantly
458 nsresult rv = OpenCacheEntry(mURI, nsICacheStorage::OPEN_TRUNCATE);
459 if (NS_FAILED(rv) || !mCacheEntry) {
460 LOG((" could not synchronously open cache entry for write!"));
461 return NS_ERROR_FAILURE;
465 return NS_OK;
468 NS_IMETHODIMP
469 nsWyciwygChannel::WriteToCacheEntry(const nsAString &aData)
471 if (mMode == READING) {
472 LOG(("nsWyciwygChannel::WriteToCacheEntry already open for reading"));
473 MOZ_ASSERT(false);
474 return NS_ERROR_UNEXPECTED;
477 mMode = WRITING;
479 if (mozilla::net::CacheObserver::UseNewCache()) {
480 nsresult rv = EnsureWriteCacheEntry();
481 if (NS_FAILED(rv)) return rv;
484 return mCacheIOTarget->Dispatch(new nsWyciwygWriteEvent(this, aData),
485 NS_DISPATCH_NORMAL);
488 nsresult
489 nsWyciwygChannel::WriteToCacheEntryInternal(const nsAString &aData)
491 LOG(("nsWyciwygChannel::WriteToCacheEntryInternal [this=%p]", this));
492 NS_ASSERTION(IsOnCacheIOThread(), "wrong thread");
494 nsresult rv;
496 // With the new cache entry this will just pass as a no-op since we
497 // are opening the entry in WriteToCacheEntry.
498 rv = EnsureWriteCacheEntry();
499 if (NS_WARN_IF(NS_FAILED(rv))) {
500 return rv;
503 if (mLoadFlags & INHIBIT_PERSISTENT_CACHING) {
504 rv = mCacheEntry->SetMetaDataElement("inhibit-persistent-caching", "1");
505 if (NS_FAILED(rv)) return rv;
508 if (mSecurityInfo) {
509 mCacheEntry->SetSecurityInfo(mSecurityInfo);
512 if (mNeedToWriteCharset) {
513 WriteCharsetAndSourceToCache(mCharsetSource, mCharset);
514 mNeedToWriteCharset = false;
517 uint32_t out;
518 if (!mCacheOutputStream) {
519 // Get the outputstream from the cache entry.
520 rv = mCacheEntry->OpenOutputStream(0, getter_AddRefs(mCacheOutputStream));
521 if (NS_FAILED(rv)) return rv;
523 // Write out a Byte Order Mark, so that we'll know if the data is
524 // BE or LE when we go to read it.
525 char16_t bom = 0xFEFF;
526 rv = mCacheOutputStream->Write((char *)&bom, sizeof(bom), &out);
527 if (NS_FAILED(rv)) return rv;
530 return mCacheOutputStream->Write((const char *)PromiseFlatString(aData).get(),
531 aData.Length() * sizeof(char16_t), &out);
535 NS_IMETHODIMP
536 nsWyciwygChannel::CloseCacheEntry(nsresult reason)
538 return mCacheIOTarget->Dispatch(new nsWyciwygCloseEvent(this, reason),
539 NS_DISPATCH_NORMAL);
542 nsresult
543 nsWyciwygChannel::CloseCacheEntryInternal(nsresult reason)
545 NS_ASSERTION(IsOnCacheIOThread(), "wrong thread");
547 if (mCacheEntry) {
548 LOG(("nsWyciwygChannel::CloseCacheEntryInternal [this=%p ]", this));
549 mCacheOutputStream = 0;
550 mCacheInputStream = 0;
552 if (NS_FAILED(reason))
553 mCacheEntry->AsyncDoom(nullptr); // here we were calling Doom() ...
555 mCacheEntry = 0;
557 return NS_OK;
560 NS_IMETHODIMP
561 nsWyciwygChannel::SetSecurityInfo(nsISupports *aSecurityInfo)
563 mSecurityInfo = aSecurityInfo;
565 return NS_OK;
568 NS_IMETHODIMP
569 nsWyciwygChannel::SetCharsetAndSource(int32_t aSource,
570 const nsACString& aCharset)
572 NS_ENSURE_ARG(!aCharset.IsEmpty());
574 mCharsetAndSourceSet = true;
575 mCharset = aCharset;
576 mCharsetSource = aSource;
578 return mCacheIOTarget->Dispatch(new nsWyciwygSetCharsetandSourceEvent(this),
579 NS_DISPATCH_NORMAL);
582 void
583 nsWyciwygChannel::SetCharsetAndSourceInternal()
585 NS_ASSERTION(IsOnCacheIOThread(), "wrong thread");
587 if (mCacheEntry) {
588 WriteCharsetAndSourceToCache(mCharsetSource, mCharset);
589 } else {
590 mNeedToWriteCharset = true;
594 NS_IMETHODIMP
595 nsWyciwygChannel::GetCharsetAndSource(int32_t* aSource, nsACString& aCharset)
597 if (mCharsetAndSourceSet) {
598 *aSource = mCharsetSource;
599 aCharset = mCharset;
600 return NS_OK;
603 if (!mCacheEntry) {
604 return NS_ERROR_NOT_AVAILABLE;
607 nsXPIDLCString data;
608 mCacheEntry->GetMetaDataElement("charset", getter_Copies(data));
610 if (data.IsEmpty()) {
611 return NS_ERROR_NOT_AVAILABLE;
614 nsXPIDLCString sourceStr;
615 mCacheEntry->GetMetaDataElement("charset-source", getter_Copies(sourceStr));
617 int32_t source;
618 nsresult err;
619 source = sourceStr.ToInteger(&err);
620 if (NS_FAILED(err) || source == 0) {
621 return NS_ERROR_NOT_AVAILABLE;
624 *aSource = source;
625 aCharset = data;
626 return NS_OK;
629 //////////////////////////////////////////////////////////////////////////////
630 // nsICacheEntryOpenCallback
631 //////////////////////////////////////////////////////////////////////////////
633 NS_IMETHODIMP
634 nsWyciwygChannel::OnCacheEntryCheck(nsICacheEntry* entry, nsIApplicationCache* appCache,
635 uint32_t* aResult)
637 *aResult = ENTRY_WANTED;
638 return NS_OK;
641 NS_IMETHODIMP
642 nsWyciwygChannel::OnCacheEntryAvailable(nsICacheEntry *aCacheEntry,
643 bool aNew,
644 nsIApplicationCache* aAppCache,
645 nsresult aStatus)
647 LOG(("nsWyciwygChannel::OnCacheEntryAvailable [this=%p entry=%p "
648 "new=%d status=%x]\n", this, aCacheEntry, aNew, aStatus));
650 // if the channel's already fired onStopRequest,
651 // then we should ignore this event.
652 if (!mIsPending && !aNew)
653 return NS_OK;
655 // otherwise, we have to handle this event.
656 if (NS_SUCCEEDED(aStatus))
657 mCacheEntry = aCacheEntry;
658 else if (NS_SUCCEEDED(mStatus))
659 mStatus = aStatus;
661 nsresult rv = NS_OK;
662 if (NS_FAILED(mStatus)) {
663 LOG(("channel was canceled [this=%p status=%x]\n", this, mStatus));
664 rv = mStatus;
666 else if (!aNew) { // advance to the next state...
667 rv = ReadFromCache();
670 // a failure from Connect means that we have to abort the channel.
671 if (NS_FAILED(rv)) {
672 CloseCacheEntry(rv);
674 if (!aNew) {
675 // Since OnCacheEntryAvailable can be called directly from AsyncOpen
676 // we must dispatch.
677 NS_DispatchToCurrentThread(NS_NewRunnableMethod(
678 this, &nsWyciwygChannel::NotifyListener));
682 return NS_OK;
685 //-----------------------------------------------------------------------------
686 // nsWyciwygChannel::nsIStreamListener
687 //-----------------------------------------------------------------------------
689 NS_IMETHODIMP
690 nsWyciwygChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctx,
691 nsIInputStream *input,
692 uint64_t offset, uint32_t count)
694 LOG(("nsWyciwygChannel::OnDataAvailable [this=%p request=%x offset=%llu count=%u]\n",
695 this, request, offset, count));
697 nsresult rv;
699 rv = mListener->OnDataAvailable(this, mListenerContext, input, offset, count);
701 // XXX handle 64-bit stuff for real
702 if (mProgressSink && NS_SUCCEEDED(rv)) {
703 mProgressSink->OnProgress(this, nullptr, offset + count,
704 uint64_t(mContentLength));
707 return rv; // let the pump cancel on failure
710 //////////////////////////////////////////////////////////////////////////////
711 // nsIRequestObserver
712 //////////////////////////////////////////////////////////////////////////////
714 NS_IMETHODIMP
715 nsWyciwygChannel::OnStartRequest(nsIRequest *request, nsISupports *ctx)
717 LOG(("nsWyciwygChannel::OnStartRequest [this=%p request=%x\n",
718 this, request));
720 return mListener->OnStartRequest(this, mListenerContext);
724 NS_IMETHODIMP
725 nsWyciwygChannel::OnStopRequest(nsIRequest *request, nsISupports *ctx, nsresult status)
727 LOG(("nsWyciwygChannel::OnStopRequest [this=%p request=%x status=%d\n",
728 this, request, status));
730 if (NS_SUCCEEDED(mStatus))
731 mStatus = status;
733 mListener->OnStopRequest(this, mListenerContext, mStatus);
734 mListener = 0;
735 mListenerContext = 0;
737 if (mLoadGroup)
738 mLoadGroup->RemoveRequest(this, nullptr, mStatus);
740 CloseCacheEntry(mStatus);
741 mPump = 0;
742 mIsPending = false;
744 // Drop notification callbacks to prevent cycles.
745 mCallbacks = 0;
746 mProgressSink = 0;
748 return NS_OK;
751 //////////////////////////////////////////////////////////////////////////////
752 // Helper functions
753 //////////////////////////////////////////////////////////////////////////////
755 nsresult
756 nsWyciwygChannel::OpenCacheEntry(nsIURI *aURI,
757 uint32_t aOpenFlags)
759 nsresult rv;
761 nsCOMPtr<nsICacheStorageService> cacheService =
762 do_GetService("@mozilla.org/netwerk/cache-storage-service;1", &rv);
763 NS_ENSURE_SUCCESS(rv, rv);
765 bool anonymous = mLoadFlags & LOAD_ANONYMOUS;
766 nsRefPtr<LoadContextInfo> loadInfo = mozilla::net::GetLoadContextInfo(
767 mPrivateBrowsing, mAppId, mInBrowser, anonymous);
769 nsCOMPtr<nsICacheStorage> cacheStorage;
770 if (mLoadFlags & INHIBIT_PERSISTENT_CACHING)
771 rv = cacheService->MemoryCacheStorage(loadInfo, getter_AddRefs(cacheStorage));
772 else
773 rv = cacheService->DiskCacheStorage(loadInfo, false, getter_AddRefs(cacheStorage));
774 NS_ENSURE_SUCCESS(rv, rv);
776 rv = cacheStorage->AsyncOpenURI(aURI, EmptyCString(), aOpenFlags, this);
777 NS_ENSURE_SUCCESS(rv, rv);
779 return NS_OK;
782 nsresult
783 nsWyciwygChannel::ReadFromCache()
785 LOG(("nsWyciwygChannel::ReadFromCache [this=%p] ", this));
787 NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_FAILURE);
788 nsresult rv;
790 // Get the stored security info
791 mCacheEntry->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
793 nsAutoCString tmpStr;
794 rv = mCacheEntry->GetMetaDataElement("inhibit-persistent-caching",
795 getter_Copies(tmpStr));
796 if (NS_SUCCEEDED(rv) && tmpStr.EqualsLiteral("1"))
797 mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
799 // Get a transport to the cached data...
800 rv = mCacheEntry->OpenInputStream(0, getter_AddRefs(mCacheInputStream));
801 if (NS_FAILED(rv))
802 return rv;
803 NS_ENSURE_TRUE(mCacheInputStream, NS_ERROR_UNEXPECTED);
805 rv = NS_NewInputStreamPump(getter_AddRefs(mPump), mCacheInputStream);
806 if (NS_FAILED(rv)) return rv;
808 // Pump the cache data downstream
809 return mPump->AsyncRead(this, nullptr);
812 void
813 nsWyciwygChannel::WriteCharsetAndSourceToCache(int32_t aSource,
814 const nsCString& aCharset)
816 NS_ASSERTION(IsOnCacheIOThread(), "wrong thread");
817 NS_PRECONDITION(mCacheEntry, "Better have cache entry!");
819 mCacheEntry->SetMetaDataElement("charset", aCharset.get());
821 nsAutoCString source;
822 source.AppendInt(aSource);
823 mCacheEntry->SetMetaDataElement("charset-source", source.get());
826 void
827 nsWyciwygChannel::NotifyListener()
829 if (mListener) {
830 mListener->OnStartRequest(this, mListenerContext);
831 mListener->OnStopRequest(this, mListenerContext, mStatus);
832 mListener = 0;
833 mListenerContext = 0;
836 mIsPending = false;
838 // Remove ourselves from the load group.
839 if (mLoadGroup) {
840 mLoadGroup->RemoveRequest(this, nullptr, mStatus);
844 bool
845 nsWyciwygChannel::IsOnCacheIOThread()
847 bool correctThread;
848 mCacheIOTarget->IsOnCurrentThread(&correctThread);
849 return correctThread;
852 // vim: ts=2 sw=2