summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp')
-rw-r--r--netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp808
1 files changed, 808 insertions, 0 deletions
diff --git a/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp b/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp
new file mode 100644
index 000000000..52949b799
--- /dev/null
+++ b/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp
@@ -0,0 +1,808 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsWyciwyg.h"
+#include "nsWyciwygChannel.h"
+#include "nsILoadGroup.h"
+#include "nsNetUtil.h"
+#include "nsNetCID.h"
+#include "LoadContextInfo.h"
+#include "nsICacheService.h" // only to initialize
+#include "nsICacheStorageService.h"
+#include "nsICacheStorage.h"
+#include "nsICacheEntry.h"
+#include "nsCharsetSource.h"
+#include "nsProxyRelease.h"
+#include "nsThreadUtils.h"
+#include "nsIInputStream.h"
+#include "nsIInputStreamPump.h"
+#include "nsIOutputStream.h"
+#include "nsIProgressEventSink.h"
+#include "nsIURI.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/Unused.h"
+#include "mozilla/BasePrincipal.h"
+#include "nsProxyRelease.h"
+#include "nsContentSecurityManager.h"
+#include "nsContentUtils.h"
+
+typedef mozilla::net::LoadContextInfo LoadContextInfo;
+
+// nsWyciwygChannel methods
+nsWyciwygChannel::nsWyciwygChannel()
+ : mMode(NONE),
+ mStatus(NS_OK),
+ mIsPending(false),
+ mNeedToWriteCharset(false),
+ mCharsetSource(kCharsetUninitialized),
+ mContentLength(-1),
+ mLoadFlags(LOAD_NORMAL),
+ mNeedToSetSecurityInfo(false)
+{
+}
+
+nsWyciwygChannel::~nsWyciwygChannel()
+{
+ if (mLoadInfo) {
+ NS_ReleaseOnMainThread(mLoadInfo.forget(), false);
+ }
+}
+
+NS_IMPL_ISUPPORTS(nsWyciwygChannel,
+ nsIChannel,
+ nsIRequest,
+ nsIStreamListener,
+ nsIRequestObserver,
+ nsICacheEntryOpenCallback,
+ nsIWyciwygChannel,
+ nsIPrivateBrowsingChannel)
+
+nsresult
+nsWyciwygChannel::Init(nsIURI* uri)
+{
+ NS_ENSURE_ARG_POINTER(uri);
+
+ mURI = uri;
+ mOriginalURI = uri;
+
+ return NS_OK;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// nsIRequest methods:
+///////////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetName(nsACString &aName)
+{
+ return mURI->GetSpec(aName);
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::IsPending(bool *aIsPending)
+{
+ *aIsPending = mIsPending;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetStatus(nsresult *aStatus)
+{
+ if (NS_SUCCEEDED(mStatus) && mPump)
+ mPump->GetStatus(aStatus);
+ else
+ *aStatus = mStatus;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::Cancel(nsresult status)
+{
+ mStatus = status;
+ if (mPump)
+ mPump->Cancel(status);
+ // else we're waiting for OnCacheEntryAvailable
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::Suspend()
+{
+ if (mPump)
+ mPump->Suspend();
+ // XXX else, we'll ignore this ... and that's probably bad!
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::Resume()
+{
+ if (mPump)
+ mPump->Resume();
+ // XXX else, we'll ignore this ... and that's probably bad!
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
+{
+ *aLoadGroup = mLoadGroup;
+ NS_IF_ADDREF(*aLoadGroup);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
+{
+ if (!CanSetLoadGroup(aLoadGroup)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ mLoadGroup = aLoadGroup;
+ NS_QueryNotificationCallbacks(mCallbacks,
+ mLoadGroup,
+ NS_GET_IID(nsIProgressEventSink),
+ getter_AddRefs(mProgressSink));
+ UpdatePrivateBrowsing();
+ NS_GetOriginAttributes(this, mOriginAttributes);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::SetLoadFlags(uint32_t aLoadFlags)
+{
+ mLoadFlags = aLoadFlags;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetLoadFlags(uint32_t * aLoadFlags)
+{
+ *aLoadFlags = mLoadFlags;
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIChannel methods:
+///////////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetOriginalURI(nsIURI* *aURI)
+{
+ *aURI = mOriginalURI;
+ NS_ADDREF(*aURI);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::SetOriginalURI(nsIURI* aURI)
+{
+ NS_ENSURE_ARG_POINTER(aURI);
+ mOriginalURI = aURI;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetURI(nsIURI* *aURI)
+{
+ *aURI = mURI;
+ NS_IF_ADDREF(*aURI);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetOwner(nsISupports **aOwner)
+{
+ NS_IF_ADDREF(*aOwner = mOwner);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::SetOwner(nsISupports* aOwner)
+{
+ mOwner = aOwner;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetLoadInfo(nsILoadInfo **aLoadInfo)
+{
+ NS_IF_ADDREF(*aLoadInfo = mLoadInfo);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::SetLoadInfo(nsILoadInfo* aLoadInfo)
+{
+ mLoadInfo = aLoadInfo;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aCallbacks)
+{
+ *aCallbacks = mCallbacks.get();
+ NS_IF_ADDREF(*aCallbacks);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
+{
+ if (!CanSetCallbacks(aNotificationCallbacks)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ mCallbacks = aNotificationCallbacks;
+ NS_QueryNotificationCallbacks(mCallbacks,
+ mLoadGroup,
+ NS_GET_IID(nsIProgressEventSink),
+ getter_AddRefs(mProgressSink));
+
+ UpdatePrivateBrowsing();
+ NS_GetOriginAttributes(this, mOriginAttributes);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
+{
+ NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetContentType(nsACString &aContentType)
+{
+ aContentType.AssignLiteral(WYCIWYG_TYPE);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::SetContentType(const nsACString &aContentType)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetContentCharset(nsACString &aContentCharset)
+{
+ aContentCharset.AssignLiteral("UTF-16");
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::SetContentCharset(const nsACString &aContentCharset)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetContentDisposition(uint32_t *aContentDisposition)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::SetContentDisposition(uint32_t aContentDisposition)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetContentLength(int64_t *aContentLength)
+{
+ *aContentLength = mContentLength;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::SetContentLength(int64_t aContentLength)
+{
+ mContentLength = aContentLength;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::Open(nsIInputStream ** aReturn)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::Open2(nsIInputStream** aStream)
+{
+ nsCOMPtr<nsIStreamListener> listener;
+ nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+ NS_ENSURE_SUCCESS(rv, rv);
+ return Open(aStream);
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx)
+{
+ MOZ_ASSERT(!mLoadInfo ||
+ mLoadInfo->GetSecurityMode() == 0 ||
+ mLoadInfo->GetInitialSecurityCheckDone() ||
+ (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL &&
+ nsContentUtils::IsSystemPrincipal(mLoadInfo->LoadingPrincipal())),
+ "security flags in loadInfo but asyncOpen2() not called");
+
+ LOG(("nsWyciwygChannel::AsyncOpen [this=%p]\n", this));
+ MOZ_ASSERT(mMode == NONE, "nsWyciwygChannel already open");
+
+ NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
+ NS_ENSURE_TRUE(mMode == NONE, NS_ERROR_IN_PROGRESS);
+ NS_ENSURE_ARG_POINTER(listener);
+
+ mMode = READING;
+
+ // open a cache entry for this channel...
+ // mIsPending set to true since OnCacheEntryAvailable may be called
+ // synchronously and fails when mIsPending found false.
+ mIsPending = true;
+ nsresult rv = OpenCacheEntryForReading(mURI);
+ if (NS_FAILED(rv)) {
+ LOG(("nsWyciwygChannel::OpenCacheEntryForReading failed [rv=%x]\n", rv));
+ mIsPending = false;
+ return rv;
+ }
+
+ // There is no code path that would invoke the listener sooner than
+ // we get to this line in case OnCacheEntryAvailable is invoked
+ // synchronously.
+ mListener = listener;
+ mListenerContext = ctx;
+
+ if (mLoadGroup)
+ mLoadGroup->AddRequest(this, nullptr);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::AsyncOpen2(nsIStreamListener *aListener)
+{
+ nsCOMPtr<nsIStreamListener> listener = aListener;
+ nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+ NS_ENSURE_SUCCESS(rv, rv);
+ return AsyncOpen(listener, nullptr);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// nsIWyciwygChannel
+//////////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP
+nsWyciwygChannel::WriteToCacheEntry(const nsAString &aData)
+{
+ LOG(("nsWyciwygChannel::WriteToCacheEntry [this=%p]", this));
+
+ nsresult rv;
+
+ if (mMode == READING) {
+ LOG(("nsWyciwygChannel::WriteToCacheEntry already open for reading"));
+ MOZ_ASSERT(false);
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ mMode = WRITING;
+
+ if (!mCacheEntry) {
+ nsresult rv = OpenCacheEntryForWriting(mURI);
+ if (NS_FAILED(rv) || !mCacheEntry) {
+ LOG((" could not synchronously open cache entry for write!"));
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ if (mLoadFlags & INHIBIT_PERSISTENT_CACHING) {
+ rv = mCacheEntry->SetMetaDataElement("inhibit-persistent-caching", "1");
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ if (mNeedToSetSecurityInfo) {
+ mCacheEntry->SetSecurityInfo(mSecurityInfo);
+ mNeedToSetSecurityInfo = false;
+ }
+
+ if (mNeedToWriteCharset) {
+ WriteCharsetAndSourceToCache(mCharsetSource, mCharset);
+ mNeedToWriteCharset = false;
+ }
+
+ uint32_t out;
+ if (!mCacheOutputStream) {
+ // Get the outputstream from the cache entry.
+ rv = mCacheEntry->OpenOutputStream(0, getter_AddRefs(mCacheOutputStream));
+ if (NS_FAILED(rv)) return rv;
+
+ // Write out a Byte Order Mark, so that we'll know if the data is
+ // BE or LE when we go to read it.
+ char16_t bom = 0xFEFF;
+ rv = mCacheOutputStream->Write((char *)&bom, sizeof(bom), &out);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ return mCacheOutputStream->Write((const char *)PromiseFlatString(aData).get(),
+ aData.Length() * sizeof(char16_t), &out);
+}
+
+
+NS_IMETHODIMP
+nsWyciwygChannel::CloseCacheEntry(nsresult reason)
+{
+ if (mCacheEntry) {
+ LOG(("nsWyciwygChannel::CloseCacheEntry [this=%p ]", this));
+ mCacheOutputStream = nullptr;
+ mCacheInputStream = nullptr;
+
+ if (NS_FAILED(reason)) {
+ mCacheEntry->AsyncDoom(nullptr);
+ }
+
+ mCacheEntry = nullptr;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::SetSecurityInfo(nsISupports *aSecurityInfo)
+{
+ if (mMode == READING) {
+ MOZ_ASSERT(false);
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ mSecurityInfo = aSecurityInfo;
+
+ if (mCacheEntry) {
+ return mCacheEntry->SetSecurityInfo(mSecurityInfo);
+ }
+
+ mNeedToSetSecurityInfo = true;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::SetCharsetAndSource(int32_t aSource,
+ const nsACString& aCharset)
+{
+ NS_ENSURE_ARG(!aCharset.IsEmpty());
+
+ if (mCacheEntry) {
+ WriteCharsetAndSourceToCache(mCharsetSource, mCharset);
+ } else {
+ MOZ_ASSERT(mMode != WRITING, "We must have an entry!");
+ if (mMode == READING) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ mNeedToWriteCharset = true;
+ mCharsetSource = aSource;
+ mCharset = aCharset;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::GetCharsetAndSource(int32_t* aSource, nsACString& aCharset)
+{
+ MOZ_ASSERT(mMode == READING);
+
+ if (!mCacheEntry) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ nsXPIDLCString data;
+ mCacheEntry->GetMetaDataElement("charset", getter_Copies(data));
+
+ if (data.IsEmpty()) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ nsXPIDLCString sourceStr;
+ mCacheEntry->GetMetaDataElement("charset-source", getter_Copies(sourceStr));
+
+ int32_t source;
+ nsresult err;
+ source = sourceStr.ToInteger(&err);
+ if (NS_FAILED(err) || source == 0) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ *aSource = source;
+ aCharset = data;
+ return NS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// nsICacheEntryOpenCallback
+//////////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP
+nsWyciwygChannel::OnCacheEntryCheck(nsICacheEntry* entry, nsIApplicationCache* appCache,
+ uint32_t* aResult)
+{
+ *aResult = ENTRY_WANTED;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWyciwygChannel::OnCacheEntryAvailable(nsICacheEntry *aCacheEntry,
+ bool aNew,
+ nsIApplicationCache* aAppCache,
+ nsresult aStatus)
+{
+ LOG(("nsWyciwygChannel::OnCacheEntryAvailable [this=%p entry=%p "
+ "new=%d status=%x]\n", this, aCacheEntry, aNew, aStatus));
+
+ MOZ_RELEASE_ASSERT(!aNew, "New entry must not be returned when flag "
+ "OPEN_READONLY is used!");
+
+ // if the channel's already fired onStopRequest,
+ // then we should ignore this event.
+ if (!mIsPending)
+ return NS_OK;
+
+ if (NS_SUCCEEDED(mStatus)) {
+ if (NS_SUCCEEDED(aStatus)) {
+ MOZ_ASSERT(aCacheEntry);
+ mCacheEntry = aCacheEntry;
+ nsresult rv = ReadFromCache();
+ if (NS_FAILED(rv)) {
+ mStatus = rv;
+ }
+ } else {
+ mStatus = aStatus;
+ }
+ }
+
+ if (NS_FAILED(mStatus)) {
+ LOG(("channel was canceled [this=%p status=%x]\n", this, mStatus));
+ // Since OnCacheEntryAvailable can be called directly from AsyncOpen
+ // we must dispatch.
+ NS_DispatchToCurrentThread(mozilla::NewRunnableMethod(
+ this, &nsWyciwygChannel::NotifyListener));
+ }
+
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+// nsWyciwygChannel::nsIStreamListener
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+nsWyciwygChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctx,
+ nsIInputStream *input,
+ uint64_t offset, uint32_t count)
+{
+ LOG(("nsWyciwygChannel::OnDataAvailable [this=%p request=%x offset=%llu count=%u]\n",
+ this, request, offset, count));
+
+ nsresult rv;
+
+ nsCOMPtr<nsIStreamListener> listener = mListener;
+ nsCOMPtr<nsISupports> listenerContext = mListenerContext;
+
+ if (listener) {
+ rv = listener->OnDataAvailable(this, listenerContext, input, offset, count);
+ } else {
+ MOZ_ASSERT(false, "We must have a listener!");
+ rv = NS_ERROR_UNEXPECTED;
+ }
+
+ // XXX handle 64-bit stuff for real
+ if (mProgressSink && NS_SUCCEEDED(rv)) {
+ mProgressSink->OnProgress(this, nullptr, offset + count, mContentLength);
+ }
+
+ return rv; // let the pump cancel on failure
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// nsIRequestObserver
+//////////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP
+nsWyciwygChannel::OnStartRequest(nsIRequest *request, nsISupports *ctx)
+{
+ LOG(("nsWyciwygChannel::OnStartRequest [this=%p request=%x\n",
+ this, request));
+
+ nsCOMPtr<nsIStreamListener> listener = mListener;
+ nsCOMPtr<nsISupports> listenerContext = mListenerContext;
+
+ if (listener) {
+ return listener->OnStartRequest(this, listenerContext);
+ }
+
+ MOZ_ASSERT(false, "We must have a listener!");
+ return NS_ERROR_UNEXPECTED;
+}
+
+
+NS_IMETHODIMP
+nsWyciwygChannel::OnStopRequest(nsIRequest *request, nsISupports *ctx, nsresult status)
+{
+ LOG(("nsWyciwygChannel::OnStopRequest [this=%p request=%x status=%d\n",
+ this, request, status));
+
+ if (NS_SUCCEEDED(mStatus))
+ mStatus = status;
+
+ mIsPending = false;
+
+ nsCOMPtr<nsIStreamListener> listener;
+ nsCOMPtr<nsISupports> listenerContext;
+ listener.swap(mListener);
+ listenerContext.swap(mListenerContext);
+
+ if (listener) {
+ listener->OnStopRequest(this, listenerContext, mStatus);
+ } else {
+ MOZ_ASSERT(false, "We must have a listener!");
+ }
+
+ if (mLoadGroup)
+ mLoadGroup->RemoveRequest(this, nullptr, mStatus);
+
+ CloseCacheEntry(mStatus);
+ mPump = nullptr;
+
+ // Drop notification callbacks to prevent cycles.
+ mCallbacks = nullptr;
+ mProgressSink = nullptr;
+
+ return NS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Helper functions
+//////////////////////////////////////////////////////////////////////////////
+
+nsresult
+nsWyciwygChannel::GetCacheStorage(nsICacheStorage **_retval)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsICacheStorageService> cacheService =
+ do_GetService("@mozilla.org/netwerk/cache-storage-service;1", &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool anonymous = mLoadFlags & LOAD_ANONYMOUS;
+ mOriginAttributes.SyncAttributesWithPrivateBrowsing(mPrivateBrowsing);
+ RefPtr<LoadContextInfo> loadInfo = mozilla::net::GetLoadContextInfo(anonymous, mOriginAttributes);
+
+ if (mLoadFlags & INHIBIT_PERSISTENT_CACHING) {
+ return cacheService->MemoryCacheStorage(loadInfo, _retval);
+ }
+
+ return cacheService->DiskCacheStorage(loadInfo, false, _retval);
+}
+
+nsresult
+nsWyciwygChannel::OpenCacheEntryForReading(nsIURI *aURI)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsICacheStorage> cacheStorage;
+ rv = GetCacheStorage(getter_AddRefs(cacheStorage));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return cacheStorage->AsyncOpenURI(aURI, EmptyCString(),
+ nsICacheStorage::OPEN_READONLY |
+ nsICacheStorage::CHECK_MULTITHREADED,
+ this);
+}
+
+nsresult
+nsWyciwygChannel::OpenCacheEntryForWriting(nsIURI *aURI)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsICacheStorage> cacheStorage;
+ rv = GetCacheStorage(getter_AddRefs(cacheStorage));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return cacheStorage->OpenTruncate(aURI, EmptyCString(),
+ getter_AddRefs(mCacheEntry));
+}
+
+nsresult
+nsWyciwygChannel::ReadFromCache()
+{
+ LOG(("nsWyciwygChannel::ReadFromCache [this=%p] ", this));
+
+ NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_FAILURE);
+ nsresult rv;
+
+ // Get the stored security info
+ mCacheEntry->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
+
+ nsAutoCString tmpStr;
+ rv = mCacheEntry->GetMetaDataElement("inhibit-persistent-caching",
+ getter_Copies(tmpStr));
+ if (NS_SUCCEEDED(rv) && tmpStr.EqualsLiteral("1"))
+ mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
+
+ // Get a transport to the cached data...
+ rv = mCacheEntry->OpenInputStream(0, getter_AddRefs(mCacheInputStream));
+ if (NS_FAILED(rv))
+ return rv;
+ NS_ENSURE_TRUE(mCacheInputStream, NS_ERROR_UNEXPECTED);
+
+ rv = NS_NewInputStreamPump(getter_AddRefs(mPump), mCacheInputStream);
+ if (NS_FAILED(rv)) return rv;
+
+ // Pump the cache data downstream
+ return mPump->AsyncRead(this, nullptr);
+}
+
+void
+nsWyciwygChannel::WriteCharsetAndSourceToCache(int32_t aSource,
+ const nsCString& aCharset)
+{
+ NS_PRECONDITION(mCacheEntry, "Better have cache entry!");
+
+ mCacheEntry->SetMetaDataElement("charset", aCharset.get());
+
+ nsAutoCString source;
+ source.AppendInt(aSource);
+ mCacheEntry->SetMetaDataElement("charset-source", source.get());
+}
+
+void
+nsWyciwygChannel::NotifyListener()
+{
+ nsCOMPtr<nsIStreamListener> listener;
+ nsCOMPtr<nsISupports> listenerContext;
+
+ listener.swap(mListener);
+ listenerContext.swap(mListenerContext);
+
+ if (listener) {
+ listener->OnStartRequest(this, listenerContext);
+ mIsPending = false;
+ listener->OnStopRequest(this, listenerContext, mStatus);
+ } else {
+ MOZ_ASSERT(false, "We must have the listener!");
+ mIsPending = false;
+ }
+
+ CloseCacheEntry(mStatus);
+
+ // Remove ourselves from the load group.
+ if (mLoadGroup) {
+ mLoadGroup->RemoveRequest(this, nullptr, mStatus);
+ }
+}
+
+// vim: ts=2 sw=2