gecko-dev/network/cnvts/cvplugin.cpp

264 lines
6.2 KiB
C++

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "xp.h"
#include "np.h"
#include "prmem.h"
#include "plstr.h"
#include "nsINetPlugin.h"
#include "nsINetPluginInstance.h"
#include "nsIComponentManager.h"
#include "nsNetConverterStream.h"
#include "nsCOMPtr.h"
#include "nscore.h"
static NS_DEFINE_CID(kINetPluginCID, NS_INET_PLUGIN_CID);
static NS_DEFINE_IID(kINetPluginInstanceIID, NS_INETPLUGININSTANCE_IID);
static NS_DEFINE_IID(kINetOStreamIID, NS_INETOSTREAM_IID);
PRIVATE void
plugin_stream_complete(NET_StreamClass *stream)
{
nsINetOStream *instance_stream = (nsINetOStream *)stream->data_object;
instance_stream->Complete();
// mscott -- release instance_stream because we are done with it..
// the owner of the NET_Stream object just frees the struct..
NS_RELEASE(instance_stream);
}
PRIVATE void
plugin_stream_abort(NET_StreamClass *stream, int status)
{
nsINetOStream *instance_stream = (nsINetOStream *)stream->data_object;
instance_stream->Abort(status);
// mscott -- release instance_stream because we are done with it..
// the owner of the NET_Stream object just frees the struct..
NS_RELEASE(instance_stream);
}
PRIVATE int
plugin_stream_write(NET_StreamClass *stream, const char* str, int32 len)
{
nsINetOStream *instance_stream = (nsINetOStream *)stream->data_object;
nsresult res;
int32 written;
res = instance_stream->Write(str, (unsigned int)len, (unsigned int *)&written);
if (res == NS_OK)
{
return written;
}
return -1;
}
PRIVATE unsigned int
plugin_stream_write_ready(NET_StreamClass *stream)
{
nsINetOStream *instance_stream = (nsINetOStream *)stream->data_object;
nsresult res;
unsigned int ready;
res = instance_stream->WriteReady(&ready);
if (res == NS_OK)
{
return ready;
}
return 0;
}
typedef struct UsedConverter {
void *data_id;
char *mime_type;
struct UsedConverter *next;
} UsedConverter;
UsedConverter *RegisteredConverters = NULL;
PRIVATE PRBool
register_converter(char *mime_type, void *data_id)
{
UsedConverter *converter = RegisteredConverters;
if ((mime_type == NULL)||(data_id == NULL))
{
return PR_FALSE;
}
while (converter != NULL)
{
if ((converter->data_id == data_id)&&
(PL_strcmp(converter->mime_type, mime_type) == 0))
{
return PR_FALSE;
}
converter = converter->next;
}
converter = PR_NEWZAP(UsedConverter);
converter->mime_type = PL_strdup(mime_type);
converter->data_id = data_id;
converter->next = RegisteredConverters;
RegisteredConverters = converter;
return PR_TRUE;
}
PRIVATE void
unregister_converter(char *mime_type, void *data_id)
{
UsedConverter *converter = RegisteredConverters;
UsedConverter *last_converter = NULL;
if ((mime_type == NULL)||(data_id == NULL))
{
return;
}
while (converter != NULL)
{
if ((converter->data_id == data_id)&&
(PL_strcmp(converter->mime_type, mime_type) == 0))
{
if (last_converter == NULL)
{
RegisteredConverters = converter->next;
}
else
{
last_converter->next = converter->next;
}
PR_FREEIF(converter->mime_type);
PR_FREEIF(converter);
return;
}
last_converter = converter;
converter = converter->next;
}
}
extern "C" NET_StreamClass * NET_PluginStream(int fmt, void* data_obj, URL_Struct* URL_s, MWContext* w);
extern "C" NET_StreamClass *
NET_PluginStream(int fmt, void* data_obj, URL_Struct* URL_s, MWContext* w)
{
PRBool can_use, error = PR_FALSE;
char *mime_type;
const char *mime_type_out;
NET_StreamClass *new_stream = NULL;
NET_StreamClass *next_stream = NULL;
nsCOMPtr <nsINetPluginInstance> plugin_inst;
nsINetOStream *instance_stream;
nsINetOStream *out_stream;
nsNetConverterStream *converter_stream;
nsCID classID = {0};
nsresult rv = NS_OK;
if (URL_s->transfer_encoding != NULL)
{
mime_type = XP_STRDUP(URL_s->transfer_encoding);
PR_FREEIF(URL_s->transfer_encoding);
}
else if (URL_s->content_encoding != NULL)
{
mime_type = XP_STRDUP(URL_s->content_encoding);
PR_FREEIF(URL_s->content_encoding);
}
else
{
mime_type = XP_STRDUP(URL_s->content_type);
}
can_use = register_converter(mime_type, (void *)URL_s);
if (can_use == PR_FALSE)
{
PR_FREEIF(mime_type);
return NULL;
}
do {
if (nsComponentManager::ProgIDToCLSID(mime_type, &classID) != NS_OK)
{
error = PR_TRUE;
break;
}
nsComponentManager::CreateInstance(classID, (nsISupports *)nsnull, kINetPluginInstanceIID, (void **) getter_AddRefs(plugin_inst));
if (!plugin_inst)
{
error = PR_TRUE;
break;
}
plugin_inst->GetMIMEOutput(&mime_type_out, URL_s->address);
if (mime_type_out != NULL)
{
PR_FREEIF(URL_s->content_type);
URL_s->content_type = XP_STRDUP(mime_type_out);
}
next_stream = NET_StreamBuilder(fmt, URL_s, w);
converter_stream = new nsNetConverterStream();
if (converter_stream == NULL)
{
error = PR_TRUE;
break;
}
converter_stream->Initialize((void *)next_stream);
rv = converter_stream->QueryInterface(kINetOStreamIID, (void **)&out_stream);
if (NS_FAILED(rv))
{
delete converter_stream;
error = PR_TRUE;
break;
}
plugin_inst->Initialize(out_stream, URL_s->address);
rv = plugin_inst->QueryInterface(kINetOStreamIID, (void **)&instance_stream);
if (NS_FAILED(rv))
{
delete converter_stream;
error = PR_TRUE;
break;
}
} while (0);
if (error)
{
unregister_converter(mime_type, (void *)URL_s);
PR_FREEIF(mime_type);
return NULL;
}
new_stream = NET_NewStream("PluginStream", plugin_stream_write, plugin_stream_complete, plugin_stream_abort, plugin_stream_write_ready, (void *)instance_stream, w);
unregister_converter(mime_type, (void *)URL_s);
PR_FREEIF(mime_type);
return new_stream;
}