summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp')
-rw-r--r--netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp764
1 files changed, 764 insertions, 0 deletions
diff --git a/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp b/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
new file mode 100644
index 000000000..2a794df3b
--- /dev/null
+++ b/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
@@ -0,0 +1,764 @@
+/* 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 "base/compiler_specific.h"
+
+#include "mozilla/net/ChannelEventQueue.h"
+#include "WyciwygChannelChild.h"
+#include "mozilla/dom/TabChild.h"
+#include "mozilla/dom/ContentChild.h"
+
+#include "nsCharsetSource.h"
+#include "nsContentUtils.h"
+#include "nsStringStream.h"
+#include "nsNetUtil.h"
+#include "nsISerializable.h"
+#include "nsSerializationHelper.h"
+#include "nsIProgressEventSink.h"
+#include "mozilla/ipc/URIUtils.h"
+#include "SerializedLoadContext.h"
+#include "mozilla/ipc/BackgroundUtils.h"
+#include "nsProxyRelease.h"
+#include "nsContentSecurityManager.h"
+
+using namespace mozilla::ipc;
+using namespace mozilla::dom;
+
+namespace mozilla {
+namespace net {
+
+NS_IMPL_ISUPPORTS(WyciwygChannelChild,
+ nsIRequest,
+ nsIChannel,
+ nsIWyciwygChannel,
+ nsIPrivateBrowsingChannel)
+
+
+WyciwygChannelChild::WyciwygChannelChild()
+ : mStatus(NS_OK)
+ , mIsPending(false)
+ , mCanceled(false)
+ , mLoadFlags(LOAD_NORMAL)
+ , mContentLength(-1)
+ , mCharsetSource(kCharsetUninitialized)
+ , mState(WCC_NEW)
+ , mIPCOpen(false)
+ , mSentAppData(false)
+{
+ LOG(("Creating WyciwygChannelChild @%x\n", this));
+ mEventQ = new ChannelEventQueue(NS_ISUPPORTS_CAST(nsIWyciwygChannel*, this));
+}
+
+WyciwygChannelChild::~WyciwygChannelChild()
+{
+ LOG(("Destroying WyciwygChannelChild @%x\n", this));
+ if (mLoadInfo) {
+ NS_ReleaseOnMainThread(mLoadInfo.forget());
+ }
+}
+
+void
+WyciwygChannelChild::AddIPDLReference()
+{
+ MOZ_ASSERT(!mIPCOpen, "Attempt to retain more than one IPDL reference");
+ mIPCOpen = true;
+ AddRef();
+}
+
+void
+WyciwygChannelChild::ReleaseIPDLReference()
+{
+ MOZ_ASSERT(mIPCOpen, "Attempt to release nonexistent IPDL reference");
+ mIPCOpen = false;
+ Release();
+}
+
+nsresult
+WyciwygChannelChild::Init(nsIURI* uri)
+{
+ NS_ENSURE_ARG_POINTER(uri);
+
+ mState = WCC_INIT;
+
+ mURI = uri;
+ mOriginalURI = uri;
+
+ URIParams serializedUri;
+ SerializeURI(uri, serializedUri);
+
+ // propagate loadInfo
+ mozilla::ipc::PrincipalInfo requestingPrincipalInfo;
+ mozilla::ipc::PrincipalInfo triggeringPrincipalInfo;
+ mozilla::ipc::PrincipalInfo principalToInheritInfo;
+ uint32_t securityFlags;
+ uint32_t policyType;
+ if (mLoadInfo) {
+ mozilla::ipc::PrincipalToPrincipalInfo(mLoadInfo->LoadingPrincipal(),
+ &requestingPrincipalInfo);
+ mozilla::ipc::PrincipalToPrincipalInfo(mLoadInfo->TriggeringPrincipal(),
+ &triggeringPrincipalInfo);
+ mozilla::ipc::PrincipalToPrincipalInfo(mLoadInfo->PrincipalToInherit(),
+ &principalToInheritInfo);
+ securityFlags = mLoadInfo->GetSecurityFlags();
+ policyType = mLoadInfo->InternalContentPolicyType();
+ }
+ else {
+ // use default values if no loadInfo is provided
+ mozilla::ipc::PrincipalToPrincipalInfo(nsContentUtils::GetSystemPrincipal(),
+ &requestingPrincipalInfo);
+ mozilla::ipc::PrincipalToPrincipalInfo(nsContentUtils::GetSystemPrincipal(),
+ &triggeringPrincipalInfo);
+ mozilla::ipc::PrincipalToPrincipalInfo(nsContentUtils::GetSystemPrincipal(),
+ &principalToInheritInfo);
+ securityFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
+ policyType = nsIContentPolicy::TYPE_OTHER;
+ }
+
+ SendInit(serializedUri,
+ requestingPrincipalInfo,
+ triggeringPrincipalInfo,
+ principalToInheritInfo,
+ securityFlags,
+ policyType);
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+// WyciwygChannelChild::PWyciwygChannelChild
+//-----------------------------------------------------------------------------
+
+class WyciwygStartRequestEvent : public ChannelEvent
+{
+public:
+ WyciwygStartRequestEvent(WyciwygChannelChild* child,
+ const nsresult& statusCode,
+ const int64_t& contentLength,
+ const int32_t& source,
+ const nsCString& charset,
+ const nsCString& securityInfo)
+ : mChild(child), mStatusCode(statusCode), mContentLength(contentLength),
+ mSource(source), mCharset(charset), mSecurityInfo(securityInfo) {}
+ void Run() { mChild->OnStartRequest(mStatusCode, mContentLength, mSource,
+ mCharset, mSecurityInfo); }
+private:
+ WyciwygChannelChild* mChild;
+ nsresult mStatusCode;
+ int64_t mContentLength;
+ int32_t mSource;
+ nsCString mCharset;
+ nsCString mSecurityInfo;
+};
+
+bool
+WyciwygChannelChild::RecvOnStartRequest(const nsresult& statusCode,
+ const int64_t& contentLength,
+ const int32_t& source,
+ const nsCString& charset,
+ const nsCString& securityInfo)
+{
+ mEventQ->RunOrEnqueue(new WyciwygStartRequestEvent(this, statusCode,
+ contentLength, source,
+ charset, securityInfo));
+ return true;
+}
+
+void
+WyciwygChannelChild::OnStartRequest(const nsresult& statusCode,
+ const int64_t& contentLength,
+ const int32_t& source,
+ const nsCString& charset,
+ const nsCString& securityInfo)
+{
+ LOG(("WyciwygChannelChild::RecvOnStartRequest [this=%p]\n", this));
+
+ mState = WCC_ONSTART;
+
+ mStatus = statusCode;
+ mContentLength = contentLength;
+ mCharsetSource = source;
+ mCharset = charset;
+
+ if (!securityInfo.IsEmpty()) {
+ NS_DeserializeObject(securityInfo, getter_AddRefs(mSecurityInfo));
+ }
+
+ AutoEventEnqueuer ensureSerialDispatch(mEventQ);
+
+ nsresult rv = mListener->OnStartRequest(this, mListenerContext);
+ if (NS_FAILED(rv))
+ Cancel(rv);
+}
+
+class WyciwygDataAvailableEvent : public ChannelEvent
+{
+public:
+ WyciwygDataAvailableEvent(WyciwygChannelChild* child,
+ const nsCString& data,
+ const uint64_t& offset)
+ : mChild(child), mData(data), mOffset(offset) {}
+ void Run() { mChild->OnDataAvailable(mData, mOffset); }
+private:
+ WyciwygChannelChild* mChild;
+ nsCString mData;
+ uint64_t mOffset;
+};
+
+bool
+WyciwygChannelChild::RecvOnDataAvailable(const nsCString& data,
+ const uint64_t& offset)
+{
+ mEventQ->RunOrEnqueue(new WyciwygDataAvailableEvent(this, data, offset));
+ return true;
+}
+
+void
+WyciwygChannelChild::OnDataAvailable(const nsCString& data,
+ const uint64_t& offset)
+{
+ LOG(("WyciwygChannelChild::RecvOnDataAvailable [this=%p]\n", this));
+
+ if (mCanceled)
+ return;
+
+ mState = WCC_ONDATA;
+
+ // NOTE: the OnDataAvailable contract requires the client to read all the data
+ // in the inputstream. This code relies on that ('data' will go away after
+ // this function). Apparently the previous, non-e10s behavior was to actually
+ // support only reading part of the data, allowing later calls to read the
+ // rest.
+ nsCOMPtr<nsIInputStream> stringStream;
+ nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream),
+ data.get(),
+ data.Length(),
+ NS_ASSIGNMENT_DEPEND);
+ if (NS_FAILED(rv)) {
+ Cancel(rv);
+ return;
+ }
+
+ AutoEventEnqueuer ensureSerialDispatch(mEventQ);
+
+ rv = mListener->OnDataAvailable(this, mListenerContext,
+ stringStream, offset, data.Length());
+ if (NS_FAILED(rv))
+ Cancel(rv);
+
+ if (mProgressSink && NS_SUCCEEDED(rv)) {
+ mProgressSink->OnProgress(this, nullptr, offset + data.Length(),
+ mContentLength);
+ }
+}
+
+class WyciwygStopRequestEvent : public ChannelEvent
+{
+public:
+ WyciwygStopRequestEvent(WyciwygChannelChild* child,
+ const nsresult& statusCode)
+ : mChild(child), mStatusCode(statusCode) {}
+ void Run() { mChild->OnStopRequest(mStatusCode); }
+private:
+ WyciwygChannelChild* mChild;
+ nsresult mStatusCode;
+};
+
+bool
+WyciwygChannelChild::RecvOnStopRequest(const nsresult& statusCode)
+{
+ mEventQ->RunOrEnqueue(new WyciwygStopRequestEvent(this, statusCode));
+ return true;
+}
+
+void
+WyciwygChannelChild::OnStopRequest(const nsresult& statusCode)
+{
+ LOG(("WyciwygChannelChild::RecvOnStopRequest [this=%p status=%u]\n",
+ this, statusCode));
+
+ { // We need to ensure that all IPDL message dispatching occurs
+ // before we delete the protocol below
+ AutoEventEnqueuer ensureSerialDispatch(mEventQ);
+
+ mState = WCC_ONSTOP;
+
+ mIsPending = false;
+
+ if (!mCanceled)
+ mStatus = statusCode;
+
+ mListener->OnStopRequest(this, mListenerContext, statusCode);
+
+ mListener = nullptr;
+ mListenerContext = nullptr;
+
+ if (mLoadGroup)
+ mLoadGroup->RemoveRequest(this, nullptr, mStatus);
+
+ mCallbacks = nullptr;
+ mProgressSink = nullptr;
+ }
+
+ if (mIPCOpen)
+ PWyciwygChannelChild::Send__delete__(this);
+}
+
+class WyciwygCancelEvent : public ChannelEvent
+{
+ public:
+ WyciwygCancelEvent(WyciwygChannelChild* child, const nsresult& status)
+ : mChild(child)
+ , mStatus(status) {}
+
+ void Run() { mChild->CancelEarly(mStatus); }
+ private:
+ WyciwygChannelChild* mChild;
+ nsresult mStatus;
+};
+
+bool
+WyciwygChannelChild::RecvCancelEarly(const nsresult& statusCode)
+{
+ mEventQ->RunOrEnqueue(new WyciwygCancelEvent(this, statusCode));
+ return true;
+}
+
+void WyciwygChannelChild::CancelEarly(const nsresult& statusCode)
+{
+ LOG(("WyciwygChannelChild::CancelEarly [this=%p]\n", this));
+
+ if (mCanceled)
+ return;
+
+ mCanceled = true;
+ mStatus = statusCode;
+
+ mIsPending = false;
+ if (mLoadGroup)
+ mLoadGroup->RemoveRequest(this, nullptr, mStatus);
+
+ if (mListener) {
+ mListener->OnStartRequest(this, mListenerContext);
+ mListener->OnStopRequest(this, mListenerContext, mStatus);
+ }
+ mListener = nullptr;
+ mListenerContext = nullptr;
+
+ if (mIPCOpen)
+ PWyciwygChannelChild::Send__delete__(this);
+}
+
+//-----------------------------------------------------------------------------
+// nsIRequest
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetName(nsACString & aName)
+{
+ return mURI->GetSpec(aName);
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::IsPending(bool *aIsPending)
+{
+ *aIsPending = mIsPending;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetStatus(nsresult *aStatus)
+{
+ *aStatus = mStatus;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::Cancel(nsresult aStatus)
+{
+ if (mCanceled)
+ return NS_OK;
+
+ mCanceled = true;
+ mStatus = aStatus;
+ if (mIPCOpen)
+ SendCancel(aStatus);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::Suspend()
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::Resume()
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetLoadGroup(nsILoadGroup * *aLoadGroup)
+{
+ *aLoadGroup = mLoadGroup;
+ NS_IF_ADDREF(*aLoadGroup);
+ return NS_OK;
+}
+NS_IMETHODIMP
+WyciwygChannelChild::SetLoadGroup(nsILoadGroup * aLoadGroup)
+{
+ if (!CanSetLoadGroup(aLoadGroup)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ mLoadGroup = aLoadGroup;
+ NS_QueryNotificationCallbacks(mCallbacks,
+ mLoadGroup,
+ NS_GET_IID(nsIProgressEventSink),
+ getter_AddRefs(mProgressSink));
+
+ UpdatePrivateBrowsing();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetLoadFlags(nsLoadFlags *aLoadFlags)
+{
+ *aLoadFlags = mLoadFlags;
+ return NS_OK;
+}
+NS_IMETHODIMP
+WyciwygChannelChild::SetLoadFlags(nsLoadFlags aLoadFlags)
+{
+ mLoadFlags = aLoadFlags;
+ return NS_OK;
+}
+
+
+//-----------------------------------------------------------------------------
+// nsIChannel
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetOriginalURI(nsIURI * *aOriginalURI)
+{
+ *aOriginalURI = mOriginalURI;
+ NS_ADDREF(*aOriginalURI);
+ return NS_OK;
+}
+NS_IMETHODIMP
+WyciwygChannelChild::SetOriginalURI(nsIURI * aOriginalURI)
+{
+ NS_ENSURE_TRUE(mState == WCC_INIT, NS_ERROR_UNEXPECTED);
+
+ NS_ENSURE_ARG_POINTER(aOriginalURI);
+ mOriginalURI = aOriginalURI;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetURI(nsIURI * *aURI)
+{
+ *aURI = mURI;
+ NS_IF_ADDREF(*aURI);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetOwner(nsISupports * *aOwner)
+{
+ NS_IF_ADDREF(*aOwner = mOwner);
+ return NS_OK;
+}
+NS_IMETHODIMP
+WyciwygChannelChild::SetOwner(nsISupports * aOwner)
+{
+ mOwner = aOwner;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetLoadInfo(nsILoadInfo **aLoadInfo)
+{
+ NS_IF_ADDREF(*aLoadInfo = mLoadInfo);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::SetLoadInfo(nsILoadInfo* aLoadInfo)
+{
+ mLoadInfo = aLoadInfo;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetNotificationCallbacks(nsIInterfaceRequestor * *aCallbacks)
+{
+ *aCallbacks = mCallbacks;
+ NS_IF_ADDREF(*aCallbacks);
+ return NS_OK;
+}
+NS_IMETHODIMP
+WyciwygChannelChild::SetNotificationCallbacks(nsIInterfaceRequestor * aCallbacks)
+{
+ if (!CanSetCallbacks(aCallbacks)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ mCallbacks = aCallbacks;
+ NS_QueryNotificationCallbacks(mCallbacks,
+ mLoadGroup,
+ NS_GET_IID(nsIProgressEventSink),
+ getter_AddRefs(mProgressSink));
+ UpdatePrivateBrowsing();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetSecurityInfo(nsISupports * *aSecurityInfo)
+{
+ NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetContentType(nsACString & aContentType)
+{
+ aContentType.AssignLiteral(WYCIWYG_TYPE);
+ return NS_OK;
+}
+NS_IMETHODIMP
+WyciwygChannelChild::SetContentType(const nsACString & aContentType)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetContentCharset(nsACString & aContentCharset)
+{
+ aContentCharset.AssignLiteral("UTF-16");
+ return NS_OK;
+}
+NS_IMETHODIMP
+WyciwygChannelChild::SetContentCharset(const nsACString & aContentCharset)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetContentDisposition(uint32_t *aContentDisposition)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::SetContentDisposition(uint32_t aContentDisposition)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetContentDispositionFilename(nsAString &aContentDispositionFilename)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::SetContentDispositionFilename(const nsAString &aContentDispositionFilename)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetContentDispositionHeader(nsACString &aContentDispositionHeader)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetContentLength(int64_t *aContentLength)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP
+WyciwygChannelChild::SetContentLength(int64_t aContentLength)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::Open(nsIInputStream **_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::Open2(nsIInputStream** aStream)
+{
+ nsCOMPtr<nsIStreamListener> listener;
+ nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+ NS_ENSURE_SUCCESS(rv, rv);
+ return Open(aStream);
+}
+
+static mozilla::dom::TabChild*
+GetTabChild(nsIChannel* aChannel)
+{
+ nsCOMPtr<nsITabChild> iTabChild;
+ NS_QueryNotificationCallbacks(aChannel, iTabChild);
+ return iTabChild ? static_cast<mozilla::dom::TabChild*>(iTabChild.get()) : nullptr;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
+{
+ 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(("WyciwygChannelChild::AsyncOpen [this=%p]\n", this));
+
+ // The only places creating wyciwyg: channels should be
+ // HTMLDocument::OpenCommon and session history. Both should be setting an
+ // owner or loadinfo.
+ NS_PRECONDITION(mOwner || mLoadInfo, "Must have a principal");
+ NS_ENSURE_STATE(mOwner || mLoadInfo);
+
+ NS_ENSURE_ARG_POINTER(aListener);
+ NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
+
+ mListener = aListener;
+ mListenerContext = aContext;
+ mIsPending = true;
+
+ if (mLoadGroup) {
+ mLoadGroup->AddRequest(this, nullptr);
+ }
+
+ URIParams originalURI;
+ SerializeURI(mOriginalURI, originalURI);
+
+ mozilla::dom::TabChild* tabChild = GetTabChild(this);
+ if (MissingRequiredTabChild(tabChild, "wyciwyg")) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+
+ PBrowserOrId browser = static_cast<ContentChild*>(Manager()->Manager())
+ ->GetBrowserOrId(tabChild);
+
+ SendAsyncOpen(originalURI, mLoadFlags, IPC::SerializedLoadContext(this), browser);
+
+ mSentAppData = true;
+ mState = WCC_OPENED;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::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
+WyciwygChannelChild::WriteToCacheEntry(const nsAString & aData)
+{
+ NS_ENSURE_TRUE((mState == WCC_INIT) ||
+ (mState == WCC_ONWRITE), NS_ERROR_UNEXPECTED);
+
+ if (!mSentAppData) {
+ mozilla::dom::TabChild* tabChild = GetTabChild(this);
+
+ PBrowserOrId browser = static_cast<ContentChild*>(Manager()->Manager())
+ ->GetBrowserOrId(tabChild);
+
+ SendAppData(IPC::SerializedLoadContext(this), browser);
+ mSentAppData = true;
+ }
+
+ SendWriteToCacheEntry(PromiseFlatString(aData));
+ mState = WCC_ONWRITE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::CloseCacheEntry(nsresult reason)
+{
+ NS_ENSURE_TRUE(mState == WCC_ONWRITE, NS_ERROR_UNEXPECTED);
+
+ SendCloseCacheEntry(reason);
+ mState = WCC_ONCLOSED;
+
+ if (mIPCOpen)
+ PWyciwygChannelChild::Send__delete__(this);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::SetSecurityInfo(nsISupports *aSecurityInfo)
+{
+ mSecurityInfo = aSecurityInfo;
+
+ if (mSecurityInfo) {
+ nsCOMPtr<nsISerializable> serializable = do_QueryInterface(mSecurityInfo);
+ if (serializable) {
+ nsCString secInfoStr;
+ NS_SerializeToString(serializable, secInfoStr);
+ SendSetSecurityInfo(secInfoStr);
+ }
+ else {
+ NS_WARNING("Can't serialize security info");
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::SetCharsetAndSource(int32_t aSource, const nsACString & aCharset)
+{
+ // mState == WCC_ONSTART when reading from the channel
+ // mState == WCC_INIT when writing to the cache
+ NS_ENSURE_TRUE((mState == WCC_ONSTART) ||
+ (mState == WCC_INIT), NS_ERROR_UNEXPECTED);
+
+ mCharsetSource = aSource;
+ mCharset = aCharset;
+
+ // TODO ensure that nsWyciwygChannel in the parent has still the cache entry
+ SendSetCharsetAndSource(mCharsetSource, mCharset);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WyciwygChannelChild::GetCharsetAndSource(int32_t *aSource, nsACString & _retval)
+{
+ NS_ENSURE_TRUE((mState == WCC_ONSTART) ||
+ (mState == WCC_ONDATA) ||
+ (mState == WCC_ONSTOP), NS_ERROR_NOT_AVAILABLE);
+
+ if (mCharsetSource == kCharsetUninitialized)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ *aSource = mCharsetSource;
+ _retval = mCharset;
+ return NS_OK;
+}
+
+//------------------------------------------------------------------------------
+} // namespace net
+} // namespace mozilla