summaryrefslogtreecommitdiffstats
path: root/mailnews/news/src/nsNntpMockChannel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mailnews/news/src/nsNntpMockChannel.cpp')
-rw-r--r--mailnews/news/src/nsNntpMockChannel.cpp353
1 files changed, 353 insertions, 0 deletions
diff --git a/mailnews/news/src/nsNntpMockChannel.cpp b/mailnews/news/src/nsNntpMockChannel.cpp
new file mode 100644
index 000000000..1dfd462ff
--- /dev/null
+++ b/mailnews/news/src/nsNntpMockChannel.cpp
@@ -0,0 +1,353 @@
+/* -*- 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 "nsNntpMockChannel.h"
+
+#include "msgCore.h"
+#include "nsILoadInfo.h"
+#include "nsNNTPProtocol.h"
+#include "nsNetUtil.h"
+#include "nsIInputStream.h"
+#include "nsContentSecurityManager.h"
+
+NS_IMPL_ISUPPORTS(nsNntpMockChannel, nsIChannel, nsIRequest)
+
+nsNntpMockChannel::nsNntpMockChannel(nsIURI *aUri, nsIMsgWindow *aMsgWindow)
+: m_url(aUri),
+ m_msgWindow(aMsgWindow),
+ m_channelState(CHANNEL_UNOPENED),
+ m_protocol(nullptr),
+ m_cancelStatus(NS_OK),
+ m_loadFlags(0),
+ m_contentLength(-1)
+{
+}
+
+nsNntpMockChannel::nsNntpMockChannel(nsIURI *aUri, nsIMsgWindow *aMsgWindow,
+ nsISupports *aConsumer)
+: m_url(aUri),
+ m_context(aConsumer),
+ m_msgWindow(aMsgWindow),
+ m_channelState(CHANNEL_OPEN_WITH_LOAD),
+ m_protocol(nullptr),
+ m_cancelStatus(NS_OK),
+ m_loadFlags(0),
+ m_contentLength(-1)
+{
+}
+
+nsNntpMockChannel::~nsNntpMockChannel()
+{
+}
+
+#define FORWARD_CALL(function, argument) \
+ if (m_protocol) \
+ return m_protocol->function(argument);
+
+////////////////////////
+// nsIRequest methods //
+////////////////////////
+
+NS_IMETHODIMP nsNntpMockChannel::GetName(nsACString &result)
+{
+ FORWARD_CALL(GetName, result)
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::IsPending(bool *result)
+{
+ FORWARD_CALL(IsPending, result)
+ // We haven't been loaded yet, so we're still pending.
+ *result = true;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::GetStatus(nsresult *status)
+{
+ FORWARD_CALL(GetStatus, status)
+ *status = m_cancelStatus;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::Cancel(nsresult status)
+{
+ m_cancelStatus = status;
+ m_channelState = CHANNEL_CLOSED;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::Suspend()
+{
+ NS_NOTREACHED("nsNntpMockChannel::Suspend");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::Resume()
+{
+ NS_NOTREACHED("nsNntpMockChannel::Resume");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::SetLoadGroup(nsILoadGroup *aLoadGroup)
+{
+ FORWARD_CALL(SetLoadGroup, aLoadGroup)
+ m_loadGroup = aLoadGroup;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::GetLoadGroup(nsILoadGroup **aLoadGroup)
+{
+ FORWARD_CALL(GetLoadGroup, aLoadGroup)
+ NS_IF_ADDREF(*aLoadGroup = m_loadGroup);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
+{
+ FORWARD_CALL(GetLoadFlags, aLoadFlags)
+ *aLoadFlags = m_loadFlags;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
+{
+ FORWARD_CALL(SetLoadFlags, aLoadFlags)
+ m_loadFlags = aLoadFlags;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::GetLoadInfo(nsILoadInfo **aLoadInfo)
+{
+ FORWARD_CALL(GetLoadInfo, aLoadInfo)
+ NS_IF_ADDREF(*aLoadInfo = m_loadInfo);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::SetLoadInfo(nsILoadInfo *aLoadInfo)
+{
+ FORWARD_CALL(SetLoadInfo, aLoadInfo)
+ m_loadInfo = aLoadInfo;
+ return NS_OK;
+}
+
+////////////////////////
+// nsIChannel methods //
+////////////////////////
+
+NS_IMETHODIMP nsNntpMockChannel::GetOriginalURI(nsIURI **aURI)
+{
+ FORWARD_CALL(GetOriginalURI, aURI)
+ NS_IF_ADDREF(*aURI = m_url);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::SetOriginalURI(nsIURI *aURI)
+{
+ FORWARD_CALL(SetOriginalURI, aURI)
+ // News does not seem to have the notion of an original URI.
+ // (See bug 193317 and bug 1312314.)
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::GetURI(nsIURI **aURI)
+{
+ NS_IF_ADDREF(*aURI = m_url);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::GetOwner(nsISupports **owner)
+{
+ FORWARD_CALL(GetOwner, owner)
+ NS_IF_ADDREF(*owner = m_owner);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::SetOwner(nsISupports *aOwner)
+{
+ FORWARD_CALL(SetOwner, aOwner)
+ m_owner = aOwner;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNntpMockChannel::GetNotificationCallbacks(nsIInterfaceRequestor **callbacks)
+{
+ FORWARD_CALL(GetNotificationCallbacks, callbacks)
+ NS_IF_ADDREF(*callbacks = m_notificationCallbacks);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNntpMockChannel::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
+{
+ FORWARD_CALL(SetNotificationCallbacks, aCallbacks)
+ m_notificationCallbacks = aCallbacks;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::GetSecurityInfo(nsISupports **securityInfo)
+{
+ FORWARD_CALL(GetSecurityInfo, securityInfo)
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::GetContentType(nsACString &aContentType)
+{
+ FORWARD_CALL(GetContentType, aContentType)
+ aContentType = m_contentType;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::SetContentType(const nsACString &aContentType)
+{
+ FORWARD_CALL(SetContentType, aContentType)
+ return NS_ParseResponseContentType(aContentType, m_contentType, m_contentCharset);
+}
+
+NS_IMETHODIMP nsNntpMockChannel::GetContentCharset(nsACString &aCharset)
+{
+ FORWARD_CALL(GetContentCharset, aCharset)
+ aCharset = m_contentCharset;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::SetContentCharset(const nsACString &aCharset)
+{
+ FORWARD_CALL(SetContentCharset, aCharset)
+ m_contentCharset = aCharset;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNntpMockChannel::GetContentDisposition(uint32_t *aContentDisposition)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+nsNntpMockChannel::SetContentDisposition(uint32_t aContentDisposition)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+nsNntpMockChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+nsNntpMockChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+nsNntpMockChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::GetContentLength(int64_t *length)
+{
+ FORWARD_CALL(GetContentLength, length)
+ *length = m_contentLength;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNntpMockChannel::SetContentLength(int64_t aLength)
+{
+ FORWARD_CALL(SetContentLength, aLength)
+ m_contentLength = aLength;
+ return NS_OK;
+}
+
+////////////////////////////////////////
+// nsIChannel and nsNNTPProtocol glue //
+////////////////////////////////////////
+
+NS_IMETHODIMP nsNntpMockChannel::Open(nsIInputStream **_retval)
+{
+ return NS_ImplementChannelOpen(this, _retval);
+}
+
+NS_IMETHODIMP nsNntpMockChannel::Open2(nsIInputStream **_retval)
+{
+ nsCOMPtr<nsIStreamListener> listener;
+ nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+ NS_ENSURE_SUCCESS(rv, rv);
+ return Open(_retval);
+}
+
+NS_IMETHODIMP nsNntpMockChannel::AsyncOpen(nsIStreamListener *listener,
+ nsISupports *ctxt)
+{
+ m_channelState = CHANNEL_OPEN_WITH_ASYNC;
+ m_channelListener = listener;
+ m_context = ctxt;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsNntpMockChannel::AsyncOpen2(nsIStreamListener *aListener)
+{
+ nsCOMPtr<nsIStreamListener> listener = aListener;
+ nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+ NS_ENSURE_SUCCESS(rv, rv);
+ return AsyncOpen(listener, nullptr);
+}
+
+nsresult
+nsNntpMockChannel::AttachNNTPConnection(nsNNTPProtocol &protocol)
+{
+ // First things first. Were we canceled? If so, tell the protocol.
+ if (m_channelState == CHANNEL_CLOSED || m_channelState == CHANNEL_UNOPENED)
+ return NS_ERROR_FAILURE;
+
+
+ // We're going to active the protocol now. Note that if the user has
+ // interacted with us through the nsIChannel API, we need to pass it to the
+ // protocol instance. We also need to initialize it. For best results, we're
+ // going to initialize the code and then set the values.
+ nsresult rv = protocol.Initialize(m_url, m_msgWindow);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Variable fun
+ protocol.SetLoadGroup(m_loadGroup);
+ protocol.SetLoadFlags(m_loadFlags);
+ protocol.SetOwner(m_owner);
+ protocol.SetNotificationCallbacks(m_notificationCallbacks);
+ protocol.SetContentType(m_contentType);
+
+ // Now that we've set up the protocol, attach it to ourselves so that we can
+ // forward all future calls to the protocol instance. We do not refcount this
+ // instance, since the server will be owning all of them: once the server
+ // releases its reference, the protocol instance is no longer usable anyways.
+ m_protocol = &protocol;
+
+ switch (m_channelState)
+ {
+ case CHANNEL_OPEN_WITH_LOAD:
+ rv = protocol.LoadNewsUrl(m_url, m_context);
+ break;
+ case CHANNEL_OPEN_WITH_ASYNC:
+ rv = protocol.AsyncOpen(m_channelListener, m_context);
+ break;
+ default:
+ NS_NOTREACHED("Unknown channel state got us here.");
+ return NS_ERROR_FAILURE;
+ }
+
+ // If we fail, that means that loading the NNTP protocol failed. Since we
+ // essentially promised that we would load (by virtue of returning NS_OK to
+ // AsyncOpen), we must now tell our listener the bad news.
+ if (NS_FAILED(rv) && m_channelListener)
+ m_channelListener->OnStopRequest(this, m_context, rv);
+
+ // Returning a failure code is our way of telling the server that this URL
+ // isn't going to run, so it should give the connection the next URL in the
+ // queue.
+ return rv;
+}