/* -*- 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 "net.h" #include "mktrace.h" #include "structs.h" #include "ctxtfunc.h" #include "xp_list.h" #include "nsString.h" #include "nsIStreamListener.h" #include "nsNetStream.h" /****************************************************************************/ /* Beginning of MWContext Evil!!! */ /* ------------------------------- */ /* */ /* Define a dummy MWContext where all of the upcalls are stubbed out. */ /* */ /****************************************************************************/ PRIVATE int stub_noop(int x, ...) { #ifdef XP_MAC #pragma unused (x) #endif /* DebugBreak(); */ return 0; } PRIVATE void stub_GraphProgressInit(MWContext *context, URL_Struct *URL_s, int32 content_length) { nsConnectionInfo *pConn; if (NULL != URL_s->fe_data) { if (URL_s->load_background) return; /* * Retrieve the nsConnectionInfo object from the fe_data field * of the URL_Struct... */ pConn = (nsConnectionInfo *)URL_s->fe_data; if ((NULL != pConn) && (NULL != pConn->pConsumer)) { nsAutoString status; pConn->pConsumer->OnProgress(0, content_length, status); } } } PRIVATE void stub_GraphProgress(MWContext *context, URL_Struct *URL_s, int32 bytes_received, int32 bytes_since_last_time, int32 content_length) { nsConnectionInfo *pConn; if (NULL != URL_s->fe_data) { if (URL_s->load_background) return; /* * Retrieve the nsConnectionInfo object from the fe_data field * of the URL_Struct... */ pConn = (nsConnectionInfo *)URL_s->fe_data; if ((NULL != pConn) && (NULL != pConn->pConsumer)) { nsAutoString status; pConn->pConsumer->OnProgress(bytes_received, content_length, status); } } } PRIVATE void stub_GraphProgressDestroy(MWContext *context, URL_Struct *URL_s, int32 content_length, int32 total_bytes_read) { nsConnectionInfo *pConn; /* * XXX: Currently this function never calls OnProgress(...) because * netlib calls FE_GraphProgressDestroy(...) after closing the * stream... So, OnStopBinding(...) has already been called and * the nsConnectionInfo->pConsumer has been released and NULLed... */ if (NULL != URL_s->fe_data) { if (URL_s->load_background) return; /* * Retrieve the nsConnectionInfo object from the fe_data field * of the URL_Struct... */ pConn = (nsConnectionInfo *)URL_s->fe_data; if ((NULL != pConn) && (NULL != pConn->pConsumer)) { nsAutoString status; pConn->pConsumer->OnProgress(total_bytes_read, content_length, status); } } } #define MAKE_FE_TYPES_PREFIX(func) func##_t #define MAKE_FE_FUNCS_TYPES #include "mk_cx_fn.h" #undef MAKE_FE_FUNCS_TYPES #define stub_CreateNewDocWindow (CreateNewDocWindow_t)stub_noop #define stub_LayoutNewDocument (LayoutNewDocument_t)stub_noop #define stub_SetDocTitle (SetDocTitle_t)stub_noop #define stub_FinishedLayout (FinishedLayout_t)stub_noop #define stub_TranslateISOText (TranslateISOText_t)stub_noop #define stub_GetTextInfo (GetTextInfo_t)stub_noop #define stub_MeasureText (MeasureText_t)stub_noop #define stub_GetEmbedSize (GetEmbedSize_t)stub_noop #define stub_GetJavaAppSize (GetJavaAppSize_t)stub_noop #define stub_GetFormElementInfo (GetFormElementInfo_t)stub_noop #define stub_GetFormElementValue (GetFormElementValue_t)stub_noop #define stub_ResetFormElement (ResetFormElement_t)stub_noop #define stub_SetFormElementToggle (SetFormElementToggle_t)stub_noop #define stub_FreeFormElement (FreeFormElement_t)stub_noop #define stub_FreeImageElement (FreeImageElement_t)stub_noop #define stub_FreeEmbedElement (FreeEmbedElement_t)stub_noop #define stub_FreeJavaAppElement (FreeJavaAppElement_t)stub_noop #define stub_CreateEmbedWindow (CreateEmbedWindow_t)stub_noop #define stub_SaveEmbedWindow (SaveEmbedWindow_t)stub_noop #define stub_RestoreEmbedWindow (RestoreEmbedWindow_t)stub_noop #define stub_DestroyEmbedWindow (DestroyEmbedWindow_t)stub_noop #define stub_HideJavaAppElement (HideJavaAppElement_t)stub_noop #define stub_FreeEdgeElement (FreeEdgeElement_t)stub_noop #define stub_FormTextIsSubmit (FormTextIsSubmit_t)stub_noop #define stub_DisplaySubtext (DisplaySubtext_t)stub_noop #define stub_DisplayText (DisplayText_t)stub_noop #define stub_DisplayImage (DisplayImage_t)stub_noop #define stub_DisplayEmbed (DisplayEmbed_t)stub_noop #define stub_DisplayJavaApp (DisplayJavaApp_t)stub_noop #define stub_DisplaySubImage (DisplaySubImage_t)stub_noop #define stub_DisplayEdge (DisplayEdge_t)stub_noop #define stub_DisplayTable (DisplayTable_t)stub_noop #define stub_DisplayCell (DisplayCell_t)stub_noop #define stub_InvalidateEntireTableOrCell (InvalidateEntireTableOrCell_t)stub_noop #define stub_DisplayAddRowOrColBorder (DisplayAddRowOrColBorder_t)stub_noop #define stub_DisplaySubDoc (DisplaySubDoc_t)stub_noop #define stub_DisplayLineFeed (DisplayLineFeed_t)stub_noop #define stub_DisplayHR (DisplayHR_t)stub_noop #define stub_DisplayBullet (DisplayBullet_t)stub_noop #define stub_DisplayFormElement (DisplayFormElement_t)stub_noop #define stub_DisplayBorder (DisplayBorder_t)stub_noop #define stub_UpdateEnableStates (UpdateEnableStates_t)stub_noop #define stub_DisplayFeedback (DisplayFeedback_t)stub_noop #define stub_ClearView (ClearView_t)stub_noop #define stub_SetDocDimension (SetDocDimension_t)stub_noop #define stub_SetDocPosition (SetDocPosition_t)stub_noop #define stub_GetDocPosition (GetDocPosition_t)stub_noop #define stub_BeginPreSection (BeginPreSection_t)stub_noop #define stub_EndPreSection (EndPreSection_t)stub_noop #define stub_SetProgressBarPercent (SetProgressBarPercent_t)stub_noop #define stub_SetBackgroundColor (SetBackgroundColor_t)stub_noop #define stub_Progress (Progress_t)stub_noop #define stub_Alert (Alert_t)stub_noop #define stub_SetCallNetlibAllTheTime (SetCallNetlibAllTheTime_t)stub_noop #define stub_ClearCallNetlibAllTheTime (ClearCallNetlibAllTheTime_t)stub_noop #define stub_GraphProgressInit (GraphProgressInit_t)stub_GraphProgressInit #define stub_GraphProgressDestroy (GraphProgressDestroy_t)stub_GraphProgressDestroy #define stub_GraphProgress (GraphProgress_t)stub_GraphProgress #define stub_UseFancyFTP (UseFancyFTP_t)stub_noop #define stub_UseFancyNewsgroupListing (UseFancyNewsgroupListing_t)stub_noop #define stub_FileSortMethod (FileSortMethod_t)stub_noop #define stub_ShowAllNewsArticles (ShowAllNewsArticles_t)stub_noop #define stub_Confirm (Confirm_t)stub_noop #define stub_Prompt (Prompt_t)stub_noop #define stub_PromptWithCaption (PromptWithCaption_t)stub_noop #define stub_PromptUsernameAndPassword (PromptUsernameAndPassword_t)stub_noop #define stub_PromptPassword (PromptPassword_t)stub_noop #define stub_EnableClicking (EnableClicking_t)stub_noop #define stub_AllConnectionsComplete (AllConnectionsComplete_t)stub_noop #define stub_ImageSize (ImageSize_t)stub_noop #define stub_ImageData (ImageData_t)stub_noop #define stub_ImageIcon (ImageIcon_t)stub_noop #define stub_ImageOnScreen (ImageOnScreen_t)stub_noop #define stub_SetColormap (SetColormap_t)stub_noop #ifdef LAYERS #define stub_EraseBackground (EraseBackground_t)stub_noop #define stub_SetDrawable (SetDrawable_t)stub_noop #define stub_GetTextFrame (GetTextFrame_t)stub_noop #define stub_SetClipRegion (SetClipRegion_t)stub_noop #define stub_SetOrigin (SetOrigin_t)stub_noop #define stub_GetOrigin (GetOrigin_t)stub_noop #define stub_GetTextFrame (GetTextFrame_t)stub_noop #endif #define stub_GetDefaultBackgroundColor (GetDefaultBackgroundColor_t)stub_noop #define stub_LoadFontResource (LoadFontResource_t)stub_noop #define stub_DrawJavaApp (DrawJavaApp_t)stub_noop #define stub_HandleClippingView (HandleClippingView_t)stub_noop /* Just reuse the same set of context functions: */ ContextFuncs stub_context_funcs; XP_List *stub_context_list = NULL; MWContext *new_stub_context() { static int funcsInitialized = 0; MWContext *context; if (!funcsInitialized) { #define MAKE_FE_FUNCS_PREFIX(f) stub_##f #define MAKE_FE_FUNCS_ASSIGN stub_context_funcs. #include "mk_cx_fn.h" funcsInitialized = 1; stub_context_list = XP_ListNew(); } context = (MWContext *)calloc(sizeof(struct MWContext_), 1); if (nsnull != context) { context->funcs = &stub_context_funcs; context->type = MWContextBrowser; if (nsnull != stub_context_list) { XP_ListAddObjectToEnd(stub_context_list, context); } } return context; } void free_stub_context(MWContext *window_id) { TRACEMSG(("Freeing stub context...\n")); if (stub_context_list) { PRBool result; result = XP_ListRemoveObject(stub_context_list, window_id); PR_ASSERT(PR_TRUE == result); } free(window_id); } extern "C" MWContext * XP_FindContextOfType (MWContext * context, MWContextType type) { MWContext *window_id; /* * Return the context that was passed in if it is the correct type */ if (nsnull != context) { if (context->type == type) { window_id = context; } } /* * Otherwise, the type MUST be a MWBrowserContext, since that is the * only type of context that is created... * * Return the first stub context, since it is as good as any... :-) */ else if (MWContextBrowser == type) { window_id = (MWContext *)XP_ListTopObject(stub_context_list); } return window_id; } /****************************************************************************/ /* End of MWContext Evil!!! */ /****************************************************************************/ nsConnectionInfo *GetConnectionInfoFromStream(NET_StreamClass *stream) { URL_Struct *URL_s = (URL_Struct *)stream->data_object; return (URL_s) ? (nsConnectionInfo *)URL_s->fe_data : NULL; } /* * Define a NET_StreamClass which pushes its data into an nsIStream * and fires off notifications through the nsIStreamListener interface */ void stub_complete(NET_StreamClass *stream) { URL_Struct *URL_s = (URL_Struct *)stream->data_object; nsConnectionInfo *pConn = GetConnectionInfoFromStream(stream); TRACEMSG(("+++ stream complete.\n")); /* Close the stream and remove it from the ConnectionInfo... */ pConn->pNetStream->Close(); pConn->pNetStream->Release(); pConn->pNetStream = NULL; /* Notify the Data Consumer that the Binding has completed... */ if (pConn->pConsumer) { nsAutoString status; pConn->pConsumer->OnStopBinding(NS_BINDING_SUCCEEDED, status); pConn->pConsumer->Release(); pConn->pConsumer = NULL; } /* Release the URL_Struct hanging off of the data_object */ stream->data_object = NULL; NET_DropURLStruct(URL_s); } void stub_abort(NET_StreamClass *stream, int status) { URL_Struct *URL_s = (URL_Struct *)stream->data_object; nsConnectionInfo *pConn = GetConnectionInfoFromStream(stream); TRACEMSG(("+++ stream abort. Status = %d\n", status)); /* Close the stream and remove it from the ConnectionInfo... */ pConn->pNetStream->Close(); pConn->pNetStream->Release(); pConn->pNetStream = NULL; /* Notify the Data Consumer that the Binding has completed... */ /* * XXX: Currently, there is no difference between complete and * abort... */ if (pConn->pConsumer) { nsAutoString status; pConn->pConsumer->OnStopBinding(NS_BINDING_ABORTED, status); pConn->pConsumer->Release(); pConn->pConsumer = NULL; } /* Release the URL_Struct hanging off of the data_object */ stream->data_object = NULL; NET_DropURLStruct(URL_s); } int stub_put_block(NET_StreamClass *stream, const char *buffer, int32 length) { PRInt32 bytesWritten, errorCode; nsConnectionInfo *pConn = GetConnectionInfoFromStream(stream); TRACEMSG(("+++ stream put_block. Length = %d\n", length)); /* * XXX: Sometimes put_block(...) will be called without having * called is_write_ready(...) first. One case is when a stream * is interrupted... In this case, Netlib will call put_block(...) * with the string "Transfer Interrupted!" */ bytesWritten = pConn->pNetStream->Write(&errorCode, buffer, 0, length); /* Abort the connection... */ if (NS_INPUTSTREAM_EOF == errorCode) { return -1; } /* XXX: check return value to abort connection if necessary */ if (pConn->pConsumer && (0 < bytesWritten)) { pConn->pConsumer->OnDataAvailable(pConn->pNetStream, bytesWritten); } return (bytesWritten == length); } unsigned int stub_is_write_ready(NET_StreamClass *stream) { PRInt32 errorCode; unsigned int free_space = 0; URL_Struct *URL_s = (URL_Struct *)stream->data_object; nsConnectionInfo *pConn = GetConnectionInfoFromStream(stream); free_space = (unsigned int)pConn->pNetStream->GetAvailableSpace(&errorCode); /* * If the InputStream has been closed... Return 1 byte available so * Netlib will call put_block(...) one more time... */ if (NS_INPUTSTREAM_EOF == errorCode) { free_space = 1; } TRACEMSG(("+++ stream is_write_ready. Returning %d\n", free_space)); return free_space; } extern "C" { /* *Find a converter routine to create a stream and return the stream struct */ PUBLIC NET_StreamClass * NET_NGLayoutConverter(FO_Present_Types format_out, void *converter_obj, URL_Struct *URL_s, MWContext *context) { NET_StreamClass *stream = NULL; PRBool bSuccess = PR_TRUE; /* * Only create a stream if an nsConnectionInfo object is * available from the fe_data... */ if (NULL != URL_s->fe_data) { stream = (NET_StreamClass *)calloc(sizeof(NET_StreamClass), 1); if (NULL != stream) { nsConnectionInfo *pConn; /* * Initialize the NET_StreamClass instance... */ stream->name = "Stub Stream"; stream->window_id = context; stream->complete = stub_complete; stream->abort = stub_abort; stream->put_block = stub_put_block; stream->is_write_ready = stub_is_write_ready; /* * Retrieve the nsConnectionInfo object from the fe_data field * of the URL_Struct... */ pConn = (nsConnectionInfo *)URL_s->fe_data; /* * If the URL address has been rewritten by netlib then update * the cached info in the URL object... */ if ((URL_s->address_modified) && (NULL != pConn->pURL)) { pConn->pURL->Set(NET_URLStruct_Address(URL_s)); } /* * Create an Async stream unless a blocking stream is already * available in the ConnectionInfo... */ if (NULL == pConn->pNetStream) { pConn->pNetStream = new nsAsyncStream(8192); if (NULL == pConn->pNetStream) { free(stream); return NULL; } pConn->pNetStream->AddRef(); } /* Hang the URL_Struct off of the NET_StreamClass */ NET_HoldURLStruct(URL_s); stream->data_object = URL_s; /* Notify the data consumer that Binding is beginning...*/ /* XXX: check result to terminate connection if necessary */ #ifdef NOISY printf("+++ Created a stream for %s\n", URL_s->address); #endif if (pConn->pConsumer) { nsresult rv; rv = pConn->pConsumer->OnStartBinding(URL_s->content_type); /* * If OnStartBinding fails, then tear down the NET_StreamClass * and release all references... */ if (NS_OK != rv) { NET_DropURLStruct(URL_s); free(stream); stream = NULL; /* * The NET_GetURL(...) exit_routine will clean up the * nsConnectionInfo and associated objects. */ } } } } return stream; } }; /* extern "C" */