michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsWyciwyg.h" michael@0: michael@0: #include "base/compiler_specific.h" michael@0: michael@0: #include "mozilla/net/ChannelEventQueue.h" michael@0: #include "WyciwygChannelChild.h" michael@0: #include "mozilla/dom/TabChild.h" michael@0: michael@0: #include "nsCharsetSource.h" michael@0: #include "nsStringStream.h" michael@0: #include "nsNetUtil.h" michael@0: #include "nsISerializable.h" michael@0: #include "nsSerializationHelper.h" michael@0: #include "nsIProgressEventSink.h" michael@0: #include "mozilla/ipc/URIUtils.h" michael@0: #include "SerializedLoadContext.h" michael@0: michael@0: using namespace mozilla::ipc; michael@0: michael@0: namespace mozilla { michael@0: namespace net { michael@0: michael@0: NS_IMPL_ISUPPORTS(WyciwygChannelChild, michael@0: nsIRequest, michael@0: nsIChannel, michael@0: nsIWyciwygChannel, michael@0: nsIPrivateBrowsingChannel) michael@0: michael@0: michael@0: WyciwygChannelChild::WyciwygChannelChild() michael@0: : mStatus(NS_OK) michael@0: , mIsPending(false) michael@0: , mCanceled(false) michael@0: , mLoadFlags(LOAD_NORMAL) michael@0: , mContentLength(-1) michael@0: , mCharsetSource(kCharsetUninitialized) michael@0: , mState(WCC_NEW) michael@0: , mIPCOpen(false) michael@0: , mSentAppData(false) michael@0: { michael@0: LOG(("Creating WyciwygChannelChild @%x\n", this)); michael@0: mEventQ = new ChannelEventQueue(NS_ISUPPORTS_CAST(nsIWyciwygChannel*, this)); michael@0: } michael@0: michael@0: WyciwygChannelChild::~WyciwygChannelChild() michael@0: { michael@0: LOG(("Destroying WyciwygChannelChild @%x\n", this)); michael@0: } michael@0: michael@0: void michael@0: WyciwygChannelChild::AddIPDLReference() michael@0: { michael@0: NS_ABORT_IF_FALSE(!mIPCOpen, "Attempt to retain more than one IPDL reference"); michael@0: mIPCOpen = true; michael@0: AddRef(); michael@0: } michael@0: michael@0: void michael@0: WyciwygChannelChild::ReleaseIPDLReference() michael@0: { michael@0: NS_ABORT_IF_FALSE(mIPCOpen, "Attempt to release nonexistent IPDL reference"); michael@0: mIPCOpen = false; michael@0: Release(); michael@0: } michael@0: michael@0: nsresult michael@0: WyciwygChannelChild::Init(nsIURI* uri) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(uri); michael@0: michael@0: mState = WCC_INIT; michael@0: michael@0: mURI = uri; michael@0: mOriginalURI = uri; michael@0: michael@0: URIParams serializedUri; michael@0: SerializeURI(uri, serializedUri); michael@0: michael@0: SendInit(serializedUri); michael@0: return NS_OK; michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // WyciwygChannelChild::PWyciwygChannelChild michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: class WyciwygStartRequestEvent : public ChannelEvent michael@0: { michael@0: public: michael@0: WyciwygStartRequestEvent(WyciwygChannelChild* child, michael@0: const nsresult& statusCode, michael@0: const int64_t& contentLength, michael@0: const int32_t& source, michael@0: const nsCString& charset, michael@0: const nsCString& securityInfo) michael@0: : mChild(child), mStatusCode(statusCode), mContentLength(contentLength), michael@0: mSource(source), mCharset(charset), mSecurityInfo(securityInfo) {} michael@0: void Run() { mChild->OnStartRequest(mStatusCode, mContentLength, mSource, michael@0: mCharset, mSecurityInfo); } michael@0: private: michael@0: WyciwygChannelChild* mChild; michael@0: nsresult mStatusCode; michael@0: int64_t mContentLength; michael@0: int32_t mSource; michael@0: nsCString mCharset; michael@0: nsCString mSecurityInfo; michael@0: }; michael@0: michael@0: bool michael@0: WyciwygChannelChild::RecvOnStartRequest(const nsresult& statusCode, michael@0: const int64_t& contentLength, michael@0: const int32_t& source, michael@0: const nsCString& charset, michael@0: const nsCString& securityInfo) michael@0: { michael@0: if (mEventQ->ShouldEnqueue()) { michael@0: mEventQ->Enqueue(new WyciwygStartRequestEvent(this, statusCode, michael@0: contentLength, source, michael@0: charset, securityInfo)); michael@0: } else { michael@0: OnStartRequest(statusCode, contentLength, source, charset, securityInfo); michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: void michael@0: WyciwygChannelChild::OnStartRequest(const nsresult& statusCode, michael@0: const int64_t& contentLength, michael@0: const int32_t& source, michael@0: const nsCString& charset, michael@0: const nsCString& securityInfo) michael@0: { michael@0: LOG(("WyciwygChannelChild::RecvOnStartRequest [this=%p]\n", this)); michael@0: michael@0: mState = WCC_ONSTART; michael@0: michael@0: mStatus = statusCode; michael@0: mContentLength = contentLength; michael@0: mCharsetSource = source; michael@0: mCharset = charset; michael@0: michael@0: if (!securityInfo.IsEmpty()) { michael@0: NS_DeserializeObject(securityInfo, getter_AddRefs(mSecurityInfo)); michael@0: } michael@0: michael@0: AutoEventEnqueuer ensureSerialDispatch(mEventQ); michael@0: michael@0: nsresult rv = mListener->OnStartRequest(this, mListenerContext); michael@0: if (NS_FAILED(rv)) michael@0: Cancel(rv); michael@0: } michael@0: michael@0: class WyciwygDataAvailableEvent : public ChannelEvent michael@0: { michael@0: public: michael@0: WyciwygDataAvailableEvent(WyciwygChannelChild* child, michael@0: const nsCString& data, michael@0: const uint64_t& offset) michael@0: : mChild(child), mData(data), mOffset(offset) {} michael@0: void Run() { mChild->OnDataAvailable(mData, mOffset); } michael@0: private: michael@0: WyciwygChannelChild* mChild; michael@0: nsCString mData; michael@0: uint64_t mOffset; michael@0: }; michael@0: michael@0: bool michael@0: WyciwygChannelChild::RecvOnDataAvailable(const nsCString& data, michael@0: const uint64_t& offset) michael@0: { michael@0: if (mEventQ->ShouldEnqueue()) { michael@0: mEventQ->Enqueue(new WyciwygDataAvailableEvent(this, data, offset)); michael@0: } else { michael@0: OnDataAvailable(data, offset); michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: void michael@0: WyciwygChannelChild::OnDataAvailable(const nsCString& data, michael@0: const uint64_t& offset) michael@0: { michael@0: LOG(("WyciwygChannelChild::RecvOnDataAvailable [this=%p]\n", this)); michael@0: michael@0: if (mCanceled) michael@0: return; michael@0: michael@0: mState = WCC_ONDATA; michael@0: michael@0: // NOTE: the OnDataAvailable contract requires the client to read all the data michael@0: // in the inputstream. This code relies on that ('data' will go away after michael@0: // this function). Apparently the previous, non-e10s behavior was to actually michael@0: // support only reading part of the data, allowing later calls to read the michael@0: // rest. michael@0: nsCOMPtr stringStream; michael@0: nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream), michael@0: data.get(), michael@0: data.Length(), michael@0: NS_ASSIGNMENT_DEPEND); michael@0: if (NS_FAILED(rv)) { michael@0: Cancel(rv); michael@0: return; michael@0: } michael@0: michael@0: AutoEventEnqueuer ensureSerialDispatch(mEventQ); michael@0: michael@0: rv = mListener->OnDataAvailable(this, mListenerContext, michael@0: stringStream, offset, data.Length()); michael@0: if (NS_FAILED(rv)) michael@0: Cancel(rv); michael@0: michael@0: if (mProgressSink && NS_SUCCEEDED(rv) && !(mLoadFlags & LOAD_BACKGROUND)) michael@0: mProgressSink->OnProgress(this, nullptr, offset + data.Length(), michael@0: uint64_t(mContentLength)); michael@0: } michael@0: michael@0: class WyciwygStopRequestEvent : public ChannelEvent michael@0: { michael@0: public: michael@0: WyciwygStopRequestEvent(WyciwygChannelChild* child, michael@0: const nsresult& statusCode) michael@0: : mChild(child), mStatusCode(statusCode) {} michael@0: void Run() { mChild->OnStopRequest(mStatusCode); } michael@0: private: michael@0: WyciwygChannelChild* mChild; michael@0: nsresult mStatusCode; michael@0: }; michael@0: michael@0: bool michael@0: WyciwygChannelChild::RecvOnStopRequest(const nsresult& statusCode) michael@0: { michael@0: if (mEventQ->ShouldEnqueue()) { michael@0: mEventQ->Enqueue(new WyciwygStopRequestEvent(this, statusCode)); michael@0: } else { michael@0: OnStopRequest(statusCode); michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: void michael@0: WyciwygChannelChild::OnStopRequest(const nsresult& statusCode) michael@0: { michael@0: LOG(("WyciwygChannelChild::RecvOnStopRequest [this=%p status=%u]\n", michael@0: this, statusCode)); michael@0: michael@0: { // We need to ensure that all IPDL message dispatching occurs michael@0: // before we delete the protocol below michael@0: AutoEventEnqueuer ensureSerialDispatch(mEventQ); michael@0: michael@0: mState = WCC_ONSTOP; michael@0: michael@0: mIsPending = false; michael@0: michael@0: if (!mCanceled) michael@0: mStatus = statusCode; michael@0: michael@0: mListener->OnStopRequest(this, mListenerContext, statusCode); michael@0: michael@0: mListener = 0; michael@0: mListenerContext = 0; michael@0: michael@0: if (mLoadGroup) michael@0: mLoadGroup->RemoveRequest(this, nullptr, mStatus); michael@0: michael@0: mCallbacks = 0; michael@0: mProgressSink = 0; michael@0: } michael@0: michael@0: if (mIPCOpen) michael@0: PWyciwygChannelChild::Send__delete__(this); michael@0: } michael@0: michael@0: class WyciwygCancelEvent : public ChannelEvent michael@0: { michael@0: public: michael@0: WyciwygCancelEvent(WyciwygChannelChild* child, const nsresult& status) michael@0: : mChild(child) michael@0: , mStatus(status) {} michael@0: michael@0: void Run() { mChild->CancelEarly(mStatus); } michael@0: private: michael@0: WyciwygChannelChild* mChild; michael@0: nsresult mStatus; michael@0: }; michael@0: michael@0: bool michael@0: WyciwygChannelChild::RecvCancelEarly(const nsresult& statusCode) michael@0: { michael@0: if (mEventQ->ShouldEnqueue()) { michael@0: mEventQ->Enqueue(new WyciwygCancelEvent(this, statusCode)); michael@0: } else { michael@0: CancelEarly(statusCode); michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: void WyciwygChannelChild::CancelEarly(const nsresult& statusCode) michael@0: { michael@0: LOG(("WyciwygChannelChild::CancelEarly [this=%p]\n", this)); michael@0: michael@0: if (mCanceled) michael@0: return; michael@0: michael@0: mCanceled = true; michael@0: mStatus = statusCode; michael@0: michael@0: mIsPending = false; michael@0: if (mLoadGroup) michael@0: mLoadGroup->RemoveRequest(this, nullptr, mStatus); michael@0: michael@0: if (mListener) { michael@0: mListener->OnStartRequest(this, mListenerContext); michael@0: mListener->OnStopRequest(this, mListenerContext, mStatus); michael@0: } michael@0: mListener = nullptr; michael@0: mListenerContext = nullptr; michael@0: michael@0: if (mIPCOpen) michael@0: PWyciwygChannelChild::Send__delete__(this); michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsIRequest michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: /* readonly attribute AUTF8String name; */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::GetName(nsACString & aName) michael@0: { michael@0: return mURI->GetSpec(aName); michael@0: } michael@0: michael@0: /* boolean isPending (); */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::IsPending(bool *aIsPending) michael@0: { michael@0: *aIsPending = mIsPending; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute nsresult status; */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::GetStatus(nsresult *aStatus) michael@0: { michael@0: *aStatus = mStatus; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void cancel (in nsresult aStatus); */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::Cancel(nsresult aStatus) michael@0: { michael@0: if (mCanceled) michael@0: return NS_OK; michael@0: michael@0: mCanceled = true; michael@0: mStatus = aStatus; michael@0: if (mIPCOpen) michael@0: SendCancel(aStatus); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void suspend (); */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::Suspend() michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: /* void resume (); */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::Resume() michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: /* attribute nsILoadGroup loadGroup; */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::GetLoadGroup(nsILoadGroup * *aLoadGroup) michael@0: { michael@0: *aLoadGroup = mLoadGroup; michael@0: NS_IF_ADDREF(*aLoadGroup); michael@0: return NS_OK; michael@0: } michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::SetLoadGroup(nsILoadGroup * aLoadGroup) michael@0: { michael@0: if (!CanSetLoadGroup(aLoadGroup)) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: mLoadGroup = aLoadGroup; michael@0: NS_QueryNotificationCallbacks(mCallbacks, michael@0: mLoadGroup, michael@0: NS_GET_IID(nsIProgressEventSink), michael@0: getter_AddRefs(mProgressSink)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* attribute nsLoadFlags loadFlags; */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::GetLoadFlags(nsLoadFlags *aLoadFlags) michael@0: { michael@0: *aLoadFlags = mLoadFlags; michael@0: return NS_OK; michael@0: } michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::SetLoadFlags(nsLoadFlags aLoadFlags) michael@0: { michael@0: mLoadFlags = aLoadFlags; michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsIChannel michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: /* attribute nsIURI originalURI; */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::GetOriginalURI(nsIURI * *aOriginalURI) michael@0: { michael@0: *aOriginalURI = mOriginalURI; michael@0: NS_ADDREF(*aOriginalURI); michael@0: return NS_OK; michael@0: } michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::SetOriginalURI(nsIURI * aOriginalURI) michael@0: { michael@0: NS_ENSURE_TRUE(mState == WCC_INIT, NS_ERROR_UNEXPECTED); michael@0: michael@0: NS_ENSURE_ARG_POINTER(aOriginalURI); michael@0: mOriginalURI = aOriginalURI; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute nsIURI URI; */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::GetURI(nsIURI * *aURI) michael@0: { michael@0: *aURI = mURI; michael@0: NS_IF_ADDREF(*aURI); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* attribute nsISupports owner; */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::GetOwner(nsISupports * *aOwner) michael@0: { michael@0: NS_PRECONDITION(mOwner, "Must have a principal!"); michael@0: NS_ENSURE_STATE(mOwner); michael@0: michael@0: NS_ADDREF(*aOwner = mOwner); michael@0: return NS_OK; michael@0: } michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::SetOwner(nsISupports * aOwner) michael@0: { michael@0: mOwner = aOwner; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* attribute nsIInterfaceRequestor notificationCallbacks; */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::GetNotificationCallbacks(nsIInterfaceRequestor * *aCallbacks) michael@0: { michael@0: *aCallbacks = mCallbacks; michael@0: NS_IF_ADDREF(*aCallbacks); michael@0: return NS_OK; michael@0: } michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::SetNotificationCallbacks(nsIInterfaceRequestor * aCallbacks) michael@0: { michael@0: if (!CanSetCallbacks(aCallbacks)) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: mCallbacks = aCallbacks; michael@0: NS_QueryNotificationCallbacks(mCallbacks, michael@0: mLoadGroup, michael@0: NS_GET_IID(nsIProgressEventSink), michael@0: getter_AddRefs(mProgressSink)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute nsISupports securityInfo; */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::GetSecurityInfo(nsISupports * *aSecurityInfo) michael@0: { michael@0: NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* attribute ACString contentType; */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::GetContentType(nsACString & aContentType) michael@0: { michael@0: aContentType.AssignLiteral(WYCIWYG_TYPE); michael@0: return NS_OK; michael@0: } michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::SetContentType(const nsACString & aContentType) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: /* attribute ACString contentCharset; */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::GetContentCharset(nsACString & aContentCharset) michael@0: { michael@0: aContentCharset.Assign("UTF-16"); michael@0: return NS_OK; michael@0: } michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::SetContentCharset(const nsACString & aContentCharset) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::GetContentDisposition(uint32_t *aContentDisposition) michael@0: { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::SetContentDisposition(uint32_t aContentDisposition) michael@0: { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::GetContentDispositionFilename(nsAString &aContentDispositionFilename) michael@0: { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::SetContentDispositionFilename(const nsAString &aContentDispositionFilename) michael@0: { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::GetContentDispositionHeader(nsACString &aContentDispositionHeader) michael@0: { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: /* attribute int64_t contentLength; */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::GetContentLength(int64_t *aContentLength) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::SetContentLength(int64_t aContentLength) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: /* nsIInputStream open (); */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::Open(nsIInputStream **_retval) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: static mozilla::dom::TabChild* michael@0: GetTabChild(nsIChannel* aChannel) michael@0: { michael@0: nsCOMPtr iTabChild; michael@0: NS_QueryNotificationCallbacks(aChannel, iTabChild); michael@0: return iTabChild ? static_cast(iTabChild.get()) : nullptr; michael@0: } michael@0: michael@0: /* void asyncOpen (in nsIStreamListener aListener, in nsISupports aContext); */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext) michael@0: { michael@0: LOG(("WyciwygChannelChild::AsyncOpen [this=%p]\n", this)); michael@0: michael@0: // The only places creating wyciwyg: channels should be michael@0: // HTMLDocument::OpenCommon and session history. Both should be setting an michael@0: // owner. michael@0: NS_PRECONDITION(mOwner, "Must have a principal"); michael@0: NS_ENSURE_STATE(mOwner); michael@0: michael@0: NS_ENSURE_ARG_POINTER(aListener); michael@0: NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); michael@0: michael@0: mListener = aListener; michael@0: mListenerContext = aContext; michael@0: mIsPending = true; michael@0: michael@0: if (mLoadGroup) michael@0: mLoadGroup->AddRequest(this, nullptr); michael@0: michael@0: URIParams originalURI; michael@0: SerializeURI(mOriginalURI, originalURI); michael@0: michael@0: mozilla::dom::TabChild* tabChild = GetTabChild(this); michael@0: if (MissingRequiredTabChild(tabChild, "wyciwyg")) { michael@0: return NS_ERROR_ILLEGAL_VALUE; michael@0: } michael@0: michael@0: SendAsyncOpen(originalURI, mLoadFlags, IPC::SerializedLoadContext(this), tabChild); michael@0: michael@0: mSentAppData = true; michael@0: mState = WCC_OPENED; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsIWyciwygChannel michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: /* void writeToCacheEntry (in AString aData); */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::WriteToCacheEntry(const nsAString & aData) michael@0: { michael@0: NS_ENSURE_TRUE((mState == WCC_INIT) || michael@0: (mState == WCC_ONWRITE), NS_ERROR_UNEXPECTED); michael@0: michael@0: if (!mSentAppData) { michael@0: mozilla::dom::TabChild* tabChild = GetTabChild(this); michael@0: SendAppData(IPC::SerializedLoadContext(this), tabChild); michael@0: mSentAppData = true; michael@0: } michael@0: michael@0: SendWriteToCacheEntry(PromiseFlatString(aData)); michael@0: mState = WCC_ONWRITE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void closeCacheEntry (in nsresult reason); */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::CloseCacheEntry(nsresult reason) michael@0: { michael@0: NS_ENSURE_TRUE(mState == WCC_ONWRITE, NS_ERROR_UNEXPECTED); michael@0: michael@0: SendCloseCacheEntry(reason); michael@0: mState = WCC_ONCLOSED; michael@0: michael@0: if (mIPCOpen) michael@0: PWyciwygChannelChild::Send__delete__(this); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void setSecurityInfo (in nsISupports aSecurityInfo); */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::SetSecurityInfo(nsISupports *aSecurityInfo) michael@0: { michael@0: mSecurityInfo = aSecurityInfo; michael@0: michael@0: if (mSecurityInfo) { michael@0: nsCOMPtr serializable = do_QueryInterface(mSecurityInfo); michael@0: if (serializable) { michael@0: nsCString secInfoStr; michael@0: NS_SerializeToString(serializable, secInfoStr); michael@0: SendSetSecurityInfo(secInfoStr); michael@0: } michael@0: else { michael@0: NS_WARNING("Can't serialize security info"); michael@0: } michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void setCharsetAndSource (in long aSource, in ACString aCharset); */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::SetCharsetAndSource(int32_t aSource, const nsACString & aCharset) michael@0: { michael@0: // mState == WCC_ONSTART when reading from the channel michael@0: // mState == WCC_INIT when writing to the cache michael@0: NS_ENSURE_TRUE((mState == WCC_ONSTART) || michael@0: (mState == WCC_INIT), NS_ERROR_UNEXPECTED); michael@0: michael@0: mCharsetSource = aSource; michael@0: mCharset = aCharset; michael@0: michael@0: // TODO ensure that nsWyciwygChannel in the parent has still the cache entry michael@0: SendSetCharsetAndSource(mCharsetSource, mCharset); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* ACString getCharsetAndSource (out long aSource); */ michael@0: NS_IMETHODIMP michael@0: WyciwygChannelChild::GetCharsetAndSource(int32_t *aSource, nsACString & _retval) michael@0: { michael@0: NS_ENSURE_TRUE((mState == WCC_ONSTART) || michael@0: (mState == WCC_ONDATA) || michael@0: (mState == WCC_ONSTOP), NS_ERROR_NOT_AVAILABLE); michael@0: michael@0: if (mCharsetSource == kCharsetUninitialized) michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: michael@0: *aSource = mCharsetSource; michael@0: _retval = mCharset; michael@0: return NS_OK; michael@0: } michael@0: michael@0: //------------------------------------------------------------------------------ michael@0: }} // mozilla::net