380 lines
9.9 KiB
C++
380 lines
9.9 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Chak Nanga <chak@netscape.com>
|
|
*/
|
|
|
|
#include "nsViewSourceChannel.h"
|
|
#include "nsIIOService.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsIInterfaceRequestor.h"
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
#include "nsXPIDLString.h"
|
|
#include "nsMimeTypes.h"
|
|
#include "nsNetUtil.h"
|
|
|
|
// nsViewSourceChannel methods
|
|
nsViewSourceChannel::nsViewSourceChannel()
|
|
{
|
|
NS_INIT_REFCNT();
|
|
}
|
|
|
|
nsViewSourceChannel::~nsViewSourceChannel()
|
|
{
|
|
}
|
|
|
|
NS_IMPL_THREADSAFE_ISUPPORTS5(nsViewSourceChannel,
|
|
nsIRequest,
|
|
nsIChannel,
|
|
nsIViewSourceChannel,
|
|
nsIStreamListener,
|
|
nsIRequestObserver)
|
|
|
|
nsresult
|
|
nsViewSourceChannel::Init(nsIURI* uri)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsXPIDLCString path;
|
|
rv = uri->GetPath(getter_Copies(path));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsIIOService> pService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = pService->NewChannel(path, nsnull, getter_AddRefs(mChannel));
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_METHOD
|
|
nsViewSourceChannel::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult)
|
|
{
|
|
nsViewSourceChannel* fc = new nsViewSourceChannel();
|
|
if (fc == nsnull)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
NS_ADDREF(fc);
|
|
nsresult rv = fc->QueryInterface(aIID, aResult);
|
|
NS_RELEASE(fc);
|
|
return rv;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// nsIRequest methods:
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::GetName(PRUnichar* *result)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::IsPending(PRBool *result)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->IsPending(result);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::GetStatus(nsresult *status)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->GetStatus(status);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::Cancel(nsresult status)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->Cancel(status);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::Suspend(void)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->Suspend();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::Resume(void)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->Resume();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// nsIChannel methods:
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::GetOriginalURI(nsIURI* *aURI)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->GetOriginalURI(aURI);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::SetOriginalURI(nsIURI* aURI)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->SetOriginalURI(aURI);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::GetURI(nsIURI* *aURI)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->GetURI(aURI);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::Open(nsIInputStream **_retval)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->Open(_retval);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
mListener = aListener;
|
|
|
|
return mChannel->AsyncOpen(this, ctxt);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::GetLoadFlags(PRUint32 *aLoadFlags)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->GetLoadFlags(aLoadFlags);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::SetLoadFlags(PRUint32 aLoadFlags)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
// "View source" always wants the currently cached content.
|
|
|
|
return mChannel->SetLoadFlags(aLoadFlags | nsIRequest::LOAD_FROM_CACHE);
|
|
}
|
|
|
|
#define X_VIEW_SOURCE_PARAM "; x-view-type=view-source"
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::GetContentType(char* *aContentType)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aContentType);
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
if(mContentType.IsEmpty())
|
|
{
|
|
// Get the current content type
|
|
nsresult rv;
|
|
nsXPIDLCString contentType;
|
|
rv = mChannel->GetContentType(getter_Copies(contentType));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// Tack on the view-source param to the content type
|
|
// Doing this so as to preserve the original content
|
|
// type as received from the webserver. But, by adding
|
|
// the x-view-type param we're indicating a custom preference
|
|
// of how this should be displayed - viewsource or regular view
|
|
|
|
nsCAutoString viewSrcContentType;
|
|
viewSrcContentType.Append(contentType);
|
|
viewSrcContentType.Append(X_VIEW_SOURCE_PARAM);
|
|
|
|
// At this stage the content-type string will be
|
|
// of the form "text/html; x-view-type=view-source"
|
|
|
|
*aContentType = nsCRT::strdup(viewSrcContentType.get());
|
|
|
|
if (!*aContentType) return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
mContentType = *aContentType;
|
|
|
|
return NS_OK;
|
|
}
|
|
else
|
|
{
|
|
*aContentType = mContentType.ToNewCString();
|
|
|
|
if (!*aContentType) return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::SetContentType(const char *aContentType)
|
|
{
|
|
NS_ENSURE_ARG(aContentType);
|
|
|
|
// Our GetContentType() currently returns strings of the
|
|
// form "text/html; x-view-type=view-source"(see above)
|
|
//
|
|
// However, during the parsing phase the parser calls our channels'
|
|
// GetContentType(). Returing a string of the form given above
|
|
// trips up the parser. In order to avoid messy changes and not to have
|
|
// the parser depend on nsIViewSourceChannel Vidur proposed the
|
|
// following solution:
|
|
//
|
|
// The ViewSourceChannel initially returns a content type of the
|
|
// form "text/html; x-view-type=view-source". Based on this type
|
|
// decisions to create a viewer for doing a view source are made.
|
|
// After the viewer is created, nsLayoutDLF::CreateInstance()
|
|
// calls this SetContentType() with the original content type.
|
|
// When it's time for the parser to find out the content type it
|
|
// will call our channels' GetContentType() and it will get the
|
|
// original content type, such as, text/html and everything
|
|
// is kosher from then on
|
|
|
|
mContentType = aContentType;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::GetContentLength(PRInt32 *aContentLength)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->GetContentLength(aContentLength);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::SetContentLength(PRInt32 aContentLength)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->SetContentLength(aContentLength);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->GetLoadGroup(aLoadGroup);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->SetLoadGroup(aLoadGroup);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::GetOwner(nsISupports* *aOwner)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->GetOwner(aOwner);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::SetOwner(nsISupports* aOwner)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->SetOwner(aOwner);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->GetNotificationCallbacks(aNotificationCallbacks);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->SetNotificationCallbacks(aNotificationCallbacks);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
|
|
{
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->GetSecurityInfo(aSecurityInfo);
|
|
}
|
|
|
|
// nsIViewSourceChannel methods
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::GetOriginalContentType(char* *aContentType)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aContentType);
|
|
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
|
|
|
|
return mChannel->GetContentType(aContentType);
|
|
}
|
|
|
|
// nsIRequestObserver methods
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
|
|
{
|
|
NS_ENSURE_TRUE(mListener, NS_ERROR_FAILURE);
|
|
|
|
return mListener->OnStartRequest(this, aContext);
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::OnStopRequest(nsIRequest *aRequest, nsISupports* aContext,
|
|
nsresult aStatus)
|
|
{
|
|
NS_ENSURE_TRUE(mListener, NS_ERROR_FAILURE);
|
|
|
|
return mListener->OnStopRequest(this, aContext, aStatus);
|
|
}
|
|
|
|
|
|
// nsIStreamListener methods
|
|
NS_IMETHODIMP
|
|
nsViewSourceChannel::OnDataAvailable(nsIRequest *aRequest, nsISupports* aContext,
|
|
nsIInputStream *aInputStream, PRUint32 aSourceOffset,
|
|
PRUint32 aLength)
|
|
{
|
|
NS_ENSURE_TRUE(mListener, NS_ERROR_FAILURE);
|
|
|
|
return mListener->OnDataAvailable(this, aContext, aInputStream,
|
|
aSourceOffset, aLength);
|
|
}
|