/*
* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: Content handler for XHTML content type
*
*/
// INCLUDE FILES
#include <e32def.h> // To avoid NULL redefine warning (no #ifndef NULL)
#include "nw_lmgr_box.h"
#include "nw_lmgr_rootbox.h"
#include "nw_lmgr_marqueebox.h"
#include "nw_lmgr_verticaltablebox.h"
#include "nw_lmgr_verticaltablerowbox.h"
#include "nw_lmgr_verticaltablecellbox.h"
#include "nw_lmgr_bidiflowbox.h"
#include "nw_lmgr_textbox.h"
#include <f32file.h>
#include <flogger.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "nwx_string.h"
#include "nw_xhtml_xhtmlcontenthandleri.h"
#include "nw_basicforms_xhtmlformliaison.h"
#include "XhtmlTableElementHandlerOOC.h"
#include "nw_basictables_trelementhandler.h"
#include "nw_basictables_cellelementhandler.h"
#include "nw_xhtml_textelementhandler.h"
#include "nw_text_coretextelementhandler.h"
#include "nw_xhtml_pielementhandler.h"
#include "nw_image_imgelementhandler.h"
#include "nw_hed_documentroot.h"
#include "nw_hed_inumbercollectori.h"
#include "nw_lmgr_bidiflowbox.h"
#include "nw_dom_domvisitor.h"
#include "nw_tinydom.h"
#include "nw_dom_element.h"
#include "nw_dom_document.h"
#include "nw_adt_segmentedvector.h"
#include "nw_adt_resizableobjectvector.h"
#include "nw_adt_mapiterator.h"
#include "nw_xmlp_xmlp2wbxml.h"
#include "nw_htmlp_to_wbxml.h"
#include "nwx_url_utils.h"
#include "nwx_string.h"
#include "nwx_logger.h"
#include "nw_hed_context.h"
#include "NW_Text_Abstract.h"
#include "nw_text_ucs2.h"
#include "nw_xhtml_xhtmlentityset.h"
#include "nwx_ctx.h"
#include "nw_hed_documentroot.h"
#include "HEDDocumentListener.h"
#include "nw_xhtml_xhtml_1_0_tokens.h"
#include "nw_hed_domhelper.h"
#include "nw_msg_messagedispatcher.h"
#include "nw_markup_numbercollector.h"
//R->ul #include "urlloader_urlloaderint.h"
#include "nwx_osu_file.h"
#include "nw_hed_hedeventhandler.h"
#include "nw_lmgr_activecontainerbox.h"
#include "nwx_http_defs.h"
#include "nwx_settings.h"
//#include "nw_ecma_contenthandler.h"
#include "MapElementList.h"
#include "nw_lmgr_simplepropertylist.h"
#include "BrsrStatusCodes.h"
#include "nwx_statuscodeconvert.h"
#include <flogger.h>
#include "nw_markup_wbxmlmodule.h"
#include "nw_structure_scriptelementhandler.h"
#include "XhtmlObjectElementHandlerOOCi.h"
#include "XHTMLMessageListener.h"
#include "bodypart.h"
#include "MVCShell.h"
#include "BrCtl.h"
#include <stddef.h>
#include "CReferrerHelper.h"
#include "CSSVariableStyleSheet.h"
// MODULE DATA STRUCTURES
/* ------------------------------------------------------------------------- *
class definition
* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- *
forward method declarations
* ------------------------------------------------------------------------- */
static
TBrowserStatusCode
NW_XHTML_ContentHandler_MetaRefreshTimerCallback (void* timerData);
// ============================= LOCAL FUNCTIONS ===============================
static
NW_LMgr_ContainerBox_t*
NW_XHTML_ContentHandler_GetContainerSpecialCase ( NW_DOM_Node_t* node,
NW_DOM_Node_t* parentNode,
NW_LMgr_ContainerBox_t* containerBox)
{
NW_ASSERT (parentNode);
NW_ASSERT (node);
NW_ASSERT (containerBox);
// special handling for form inside table
NW_Uint16 token = NW_HED_DomHelper_GetElementToken (parentNode);
if (token == NW_XHTML_ElementToken_form)
{
// if chunk cuts after form
token = NW_HED_DomHelper_GetElementToken (node);
if (token == NW_XHTML_ElementToken_tr ||
token == NW_XHTML_ElementToken_td ||
token == NW_XHTML_ElementToken_th)
{
containerBox = NW_LMgr_Box_GetParent(containerBox);
}
else
{
NW_Uint32 type = NW_DOM_Node_getNodeType(node);
// special handling for text node is under form and form is under table, th, tr
if (type == NW_DOM_TEXT_NODE)
{
NW_DOM_Node_t* tempNode = NW_DOM_Node_getParentNode(parentNode);
token = NW_HED_DomHelper_GetElementToken (tempNode);
if (token == NW_XHTML_ElementToken_tr ||
token == NW_XHTML_ElementToken_th ||
token == NW_XHTML_ElementToken_table)
{
containerBox = NW_LMgr_Box_GetParent(containerBox);
}
}
}
}
else if (token == NW_XHTML_ElementToken_table)
{
// if chunk cuts above form
token = NW_HED_DomHelper_GetElementToken (node);
if (token == NW_XHTML_ElementToken_form)
{
containerBox = NW_LMgr_Box_GetParent(containerBox);
}
} // end of if (token == NW_XHTML_ElementToken_form)
return containerBox;
}
static
NW_DOM_Node_t*
NW_XHTML_ContentHandler_GetParentNodeSpecialCase ( NW_DOM_Node_t* node,
NW_DOM_Node_t* parentNode,
NW_Bool* formInTable)
{
NW_ASSERT (parentNode);
NW_ASSERT (node);
NW_Uint16 token = NW_HED_DomHelper_GetElementToken (parentNode);
if (token == NW_XHTML_ElementToken_form)
{
// special handling for form inside table
token = NW_HED_DomHelper_GetElementToken (node);
if (token == NW_XHTML_ElementToken_tr ||
token == NW_XHTML_ElementToken_td ||
token == NW_XHTML_ElementToken_th)
{
parentNode = NW_DOM_Node_getParentNode(parentNode);
}
else
{
NW_Uint32 type = NW_DOM_Node_getNodeType(node);
// special handling for text node is under form and form is under table, th, tr
if (type == NW_DOM_TEXT_NODE)
{
NW_DOM_Node_t* tempNode = NW_DOM_Node_getParentNode(parentNode);
token = NW_HED_DomHelper_GetElementToken (tempNode);
if (token == NW_XHTML_ElementToken_tr ||
token == NW_XHTML_ElementToken_th ||
token == NW_XHTML_ElementToken_table)
{
parentNode = tempNode;
}
}
}
}
else if (token == NW_XHTML_ElementToken_table)
{
// if chunk cuts above form
token = NW_HED_DomHelper_GetElementToken (node);
if (token == NW_XHTML_ElementToken_form)
{
*formInTable = NW_TRUE;
}
} // end of if (token == NW_XHTML_ElementToken_form)
return parentNode;
}
static
TBrowserStatusCode
NW_XHTML_ContentHandler_GetContainerBox ( NW_DOM_Node_t* lastDomNode,
NW_DOM_Node_t* currentDomNode,
NW_LMgr_ContainerBox_t** containerBox,
NW_LMgr_ContainerBox_t* parentBox )
{
NW_ASSERT (lastDomNode);
NW_ASSERT (currentDomNode);
NW_ASSERT (parentBox);
// used to track the levels up in the box tree to find the right container box
NW_LMgr_Box_t* lastBox;
// check the levels of the current parent node and the last dom node
NW_DOM_Node_t* currentParentNode = NW_DOM_Node_getParentNode(currentDomNode);
lastBox = (NW_LMgr_Box_t *)parentBox ;
// if the currentDomNode's ancestor is the last node, then return the lastContainerBox
// this can happen when last dom node's children arrives in the next chunk
if (currentParentNode == lastDomNode)
{
// get the last box from the box tree
do
{
NW_ADT_Vector_Metric_t numChildren = NW_LMgr_ContainerBox_GetChildCount(NW_LMgr_ContainerBoxOf(lastBox ));
// if the box has no children , then break , it could be a box or a last container box
if (numChildren == 0 )
{
break;
}
// get the last box in the level
numChildren --;
lastBox = NW_LMgr_ContainerBox_GetChild(NW_LMgr_ContainerBoxOf(lastBox), numChildren );
}
while (NW_Object_IsInstanceOf (lastBox, &NW_LMgr_ContainerBox_Class));
// if the last box is not an instance of container box , find the parent box
// of the last box
NW_LMgr_ContainerBox_t* lastContainerBox;
if (!NW_Object_IsInstanceOf (lastBox, &NW_LMgr_ContainerBox_Class))
{
lastContainerBox = NW_LMgr_Box_GetParent(lastBox );
}
else
{
lastContainerBox = NW_LMgr_ContainerBoxOf(lastBox );
}
// special handling for form inside table
*containerBox = NW_XHTML_ContentHandler_GetContainerSpecialCase( currentDomNode,
currentParentNode,
lastContainerBox);
}
else
{
// if the container box is not in the parent hirerchy
NW_Bool formInsideTable = NW_FALSE;
currentParentNode = NW_XHTML_ContentHandler_GetParentNodeSpecialCase (currentDomNode,
currentParentNode,
&formInsideTable);
// traverse the last branch of the box tree
NW_Bool found = NW_FALSE;
do
{
NW_LMgr_PropertyValue_t value;
value.object = NULL;
(void)NW_LMgr_Box_GetPropertyValue(lastBox, NW_CSS_Prop_elementId, NW_CSS_ValueType_Object, &value);
if (value.object)
{
NW_DOM_ElementNode_t* elementNode = (NW_DOM_ElementNode_t*)value.object;
if (elementNode == currentParentNode)
{
found = NW_TRUE;
break;
}
}
NW_ADT_Vector_Metric_t numChildren = NW_LMgr_ContainerBox_GetChildCount(NW_LMgr_ContainerBoxOf(lastBox ));
if (numChildren == 0 )
{
break;
}
numChildren --;
lastBox = NW_LMgr_ContainerBox_GetChild(NW_LMgr_ContainerBoxOf(lastBox), numChildren );
}
while (NW_Object_IsInstanceOf (lastBox, &NW_LMgr_ContainerBox_Class));
// could be the case when header occupies first chunk
if (!found)
{
NW_LMgr_Box_t* rootBox = NW_LMgr_BoxOf(NW_LMgr_Box_GetParent(parentBox));
NW_ASSERT(NW_Object_IsInstanceOf (rootBox, &NW_LMgr_RootBox_Class));
NW_LMgr_Box_t* bodyBox = NW_LMgr_RootBox_GetBody(NW_LMgr_RootBoxOf(rootBox));
if (!bodyBox)
{
*containerBox = NW_LMgr_ContainerBoxOf(NW_LMgr_ContainerBox_GetChild(NW_LMgr_ContainerBoxOf(rootBox), 0));
}
else
{
*containerBox = NW_LMgr_ContainerBoxOf(bodyBox);
}
}
else
{
if (formInsideTable)
{
// if form is under table, attach form to the parent box of table box
*containerBox = NW_LMgr_Box_GetParent(lastBox);
}
else
{
*containerBox = NW_LMgr_ContainerBoxOf(lastBox);
}
}
} // end of if (currentParentNode == lastDomNode)
return KBrsrSuccess;
}
static
TBrowserStatusCode
NW_XHTML_ContentHandler_CreatePartialBoxTree (NW_XHTML_ContentHandler_t* thisObj,
NW_LMgr_Box_t** boxTree)
{
NW_DOM_Node_t* domNode = NULL;
NW_DOM_Node_t* lastDomNode;
const NW_XHTML_ElementHandler_t* elementHandler;
NW_cXML_DOM_DOMVisitor_t * domDOMVisitor = NULL;
NW_LOG0( NW_LOG_LEVEL2, "NW_XHTML_ContentHandler_CreatePartialBoxTree START" );
NW_TRY (status)
{
if (thisObj->prevInitializedDomNode == 0)
NW_THROW_SUCCESS(status);
// if there are new nodes to create the box tree
domDOMVisitor =
NW_cXML_DOM_DOMVisitor_New( NW_HED_DomTree_GetRootNode( thisObj->domTree));
NW_THROW_ON_NULL( domDOMVisitor, status, KBrsrOutOfMemory );
// skip DOM nodes for which boxes were created (of the previous chunks)
domDOMVisitor->currentNode = thisObj->prevInitializedDomNode;
lastDomNode = thisObj->prevInitializedDomNode;
#ifdef _DEBUG1
NW_LMgr_Box_DumpBoxTree1((NW_LMgr_Box_t*)*boxTree);
#endif
// get the next dom node - this will be the first node of the new chunk
domNode = NW_cXML_DOM_DOMVisitor_Next( domDOMVisitor, NW_DOM_ELEMENT_NODE |
NW_DOM_TEXT_NODE | NW_DOM_PROCESSING_INSTRUCTION_NODE );
if (domNode == 0) // no new domNode to create a tree
NW_THROW_SUCCESS(status);
do
{
NW_LMgr_ContainerBox_t* containerBox = NULL;
// find the correspoding container box for the dom node
(void)NW_XHTML_ContentHandler_GetContainerBox(lastDomNode, domNode, &containerBox, NW_LMgr_ContainerBoxOf(*boxTree));
NW_ASSERT(containerBox != NULL);
NW_ASSERT(NW_Object_IsInstanceOf (containerBox, &NW_LMgr_ContainerBox_Class));
NW_ASSERT(!NW_Object_IsInstanceOf (containerBox, &NW_LMgr_RootBox_Class));
// create the box tree for the subtree
// all the siblings can use the container box to create the box tree
// traverse the sibling nodes and create the box tree for the sibling nodes.
// skip the siblings and all its child nodes
NW_DOM_Node_t* prevDomNode = domNode;
for (;domNode != NULL ;domNode = NW_DOM_Node_getNextSibling (domNode))
{
NW_Uint32 type = NW_DOM_Node_getNodeType(domNode);
thisObj->prevInitializedDomNode = domNode ;
if (type == NW_DOM_TEXT_NODE)
{
NW_DOM_Node_t* parentNode = NW_DOM_Node_getParentNode(domNode);
NW_Uint16 token = NW_HED_DomHelper_GetElementToken (parentNode);
if (token == NW_XHTML_ElementToken_table ||
token == NW_XHTML_ElementToken_tr ||
token == NW_XHTML_ElementToken_th)
{
// special handling for text node under table, th, tr
lastDomNode = domNode;
continue;
}
else if (token == NW_XHTML_ElementToken_form &&
(NW_Object_IsInstanceOf (containerBox, &NW_LMgr_VerticalTableBox_Class) ||
NW_Object_IsInstanceOf (containerBox, &NW_LMgr_VerticalTableRowBox_Class)))
{
// special handling for text node under form in dom tree
// text node is under table, th, tr in box tree
lastDomNode = domNode;
continue;
}
}
elementHandler = NW_XHTML_ContentHandler_GetElementHandler (thisObj,
(NW_DOM_ElementNode_t*) domNode);
NW_ASSERT(elementHandler != NULL);
status = NW_XHTML_ElementHandler_CreateBoxTree (elementHandler,
thisObj,
domNode,
containerBox);
_NW_THROW_ON_ERROR(status);
lastDomNode = domNode;
} // end of for (;domNode != NULL
// go up the hirarchy and process all the dom nodes and all its children
do
{
prevDomNode = NW_DOM_Node_getParentNode(prevDomNode);
if (prevDomNode && NW_DOM_Node_getNextSibling (prevDomNode))
{
domNode = NW_DOM_Node_getNextSibling (prevDomNode);
break;
}
}
while (prevDomNode);
#ifdef _DEBUG1
NW_LMgr_Box_DumpBoxTree((NW_LMgr_Box_t*)*boxTree);
#endif
}
while (domNode);
} // end NW_TRY
NW_CATCH (status)
{}
NW_FINALLY
{
if (domDOMVisitor)
{
NW_Object_Delete (domDOMVisitor);
}
NW_LOG0( NW_LOG_LEVEL2, "NW_XHTML_ContentHandler_CreatePartialBoxTree END" );
return status;
}
NW_END_TRY
}
/* ------------------------------------------------------------------------- *
private methods
* ------------------------------------------------------------------------- */
// -----------------------------------------------------------------------------
TBrowserStatusCode
NW_XHTML_ContentHandler_CreatePartialDocument( NW_XHTML_ContentHandler_t* contentHandler,
NW_Url_Resp_t* response, NW_Bool isFirst )
{
NW_Buffer_t* domBuffer;
NW_Uint32 line = 0;
TBrowserStatusCode status;
NW_Uint32 codePageSwitchCount = 0;
NW_Int32 lastValid = -1;
NW_Bool encodingFound;
void* WBXMLEncStrTbl = NULL;
NW_LOG0(NW_LOG_LEVEL2, "NW_XHTML_ContentHandler_CreatePartialDocument");
status = _NW_HED_CompositeContentHandler_ComputeEncoding(NW_HED_CompositeContentHandlerOf(contentHandler),
response, &encodingFound);
if (status != KBrsrSuccess)
{
return status;
}
if(response->contentLocationString != NULL)
{
contentHandler->contentLocation = NW_Str_CvtFromAscii((char *)response->contentLocationString);
if(contentHandler->contentLocation == NULL)
{
return KBrsrOutOfMemory;
}
}
/* Change done to support saved deck */
if ((0 == NW_Asc_stricmp((char*)HTTP_text_vnd_wap_wml_string,
(char*)response->contentTypeString)) ||
(0 == NW_Asc_stricmp((char*)HTTP_application_xhtml_xml_string,
(char*)response->contentTypeString)) ||
(0 == NW_Asc_stricmp((char*)HTTP_application_vnd_wap_xhtml_xml_string,
(char*)response->contentTypeString)) ||
(0 == NW_Asc_stricmp((char*)HTTP_text_html_string,
(char*)response->contentTypeString)) ||
(0 == NW_Asc_stricmp((char*)HTTP_application_vnd_wap_wml_plus_xml_string,
(char*)response->contentTypeString)))
{
NW_HED_CharsetConvContext ctx;
ctx.contentHandler = NW_HED_CompositeContentHandlerOf( contentHandler );
ctx.response = response;
NW_LOG0(NW_LOG_LEVEL2, "CreateDocument: before NW_HTMLP_SegToWbxml ");
NW_Bool detectEncoding = (encodingFound) ? NW_FALSE : NW_TRUE;
status = NW_HTMLP_SegToWbxml( response->body, response->charset,
response->byteOrder,
&domBuffer, &line, NW_xhtml_1_0_PublicId,
NW_HTMLP_Get_ElementTableCount(),
NW_HTMLP_Get_ElementDescriptionTable(),
NW_FALSE, /* consume spaces */
detectEncoding, /* need to detect charset */
isFirst, /* is this the first segment of a document? */
NW_FALSE, /* is this the last segment of a document? */
&lastValid,
&(contentHandler->htmlpParser) ,
&codePageSwitchCount,
&ctx,
NW_HED_CompositeContentHandler_CharConvCB,
&WBXMLEncStrTbl,
NW_FALSE);
if ( status == KBrsrBufferTooSmall )
{
NW_LOG0(NW_LOG_LEVEL2, "CreatePartialDocument: NW_HTMLP_SegToWbxml returns KBrsrBufferTooSmall.");
return status;
}
if (BRSR_STAT_IS_FAILURE(status))
{
NW_LOG1(NW_LOG_LEVEL1, "!!!CreatePartialDocument: NW_HTMLP_SegToWbxml: BadContent: SegToWbxml failure. status: %d", status);
NW_Buffer_Free(domBuffer);
return KBrsrXhtmlBadContent;
}
if (domBuffer)
{
NW_LOG1(NW_LOG_LEVEL2, "CreatePartialDocument: NW_HTMLP_SegToWbxml succeeds, domBuffer length: %d", domBuffer->length);
}
}
else
{
/* init our domBuffer */
domBuffer = NW_Buffer_New(0);
if (domBuffer != NULL)
{
domBuffer->allocatedLength = response->body->allocatedLength;
domBuffer->length = response->body->length;
domBuffer->data = response->body->data;
/* This block is only used to switch the byte order of domBuffer. Each time the
function NW_HED_DomTree_New is called, the byte order of domBuffer is changed.
For a saved page, the domBuffer saved in the byte order after the change when
this page was loaded from web. So this order is wrong when call function
NW_HED_DomTree_New below. Thus we call NW_HED_DomTree_New here to change the
byte order back for saved page loading */
contentHandler->domTree = NW_HED_DomTree_New (domBuffer, response->charset,
NW_xhtml_1_0_PublicId,WBXMLEncStrTbl);
if (contentHandler->domTree != NULL)
{
/* Orphan the Buffer so it isn't deleted then delete the temp DomTree */
domBuffer = NW_HED_DomTree_OrphanDomBuffer (contentHandler->domTree);
NW_HED_DomTree_Delete (contentHandler->domTree);
contentHandler->domTree = NULL;
}
/* end of the byte order switch */
delete response->body;
response->body = NULL;
}
else
{
return KBrsrOutOfMemory;
}
}
/* build the DOM tree */
if (lastValid == -1)
{
contentHandler->domTree = NW_HED_DomTree_New (domBuffer,
response->charset,
NW_xhtml_1_0_PublicId,WBXMLEncStrTbl
);
NW_LOG0(NW_LOG_LEVEL2, "CreatePartialDocument: after NW_HED_DomTree_New ");
}
else
{
if (isFirst)
{
NW_HED_DomTree_Delete (contentHandler->domTree);
contentHandler->domTree = NULL;
}
status = NW_HED_DomTree_Append (&(contentHandler->domTree),
domBuffer,
HTTP_iso_10646_ucs_2,
NW_xhtml_1_0_PublicId,
codePageSwitchCount,
lastValid,
WBXMLEncStrTbl
);
NW_LOG1(NW_LOG_LEVEL2, "CreatePartialDocument: after NW_HED_DomTree_Append, status: %x", status);
}
// set override the status if NW_HED_DomTree_New was called and failed
if (contentHandler->domTree == NULL && status == KBrsrSuccess)
{
NW_LOG0(NW_LOG_LEVEL1, "!!!NW_XHTML_ContentHandler_CreatePartialDocument: BadContent: NULL domTree with success status after NW_HED_DomTree_Append ");
status = KBrsrXhtmlBadContent;
}
/* init the domHelper */
contentHandler->domHelper.entitySet =
NW_HED_EntitySetOf (&NW_XHTML_EntitySet);
contentHandler->domHelper.context = NULL;
contentHandler->domHelper.resolvePlainTextVariablesAndEntities = NW_TRUE;
/* find the body element, if it exists */
if (contentHandler->domTree != NULL && status == KBrsrSuccess)
{
contentHandler->baseElement =
NW_HED_DomHelper_FindElement (&(contentHandler->domHelper),
NW_HED_DomTree_GetRootNode(contentHandler->domTree),
3, NW_XHTML_ElementToken_base, 0, NULL);
}
else
{
NW_LOG1(NW_LOG_LEVEL2, "!!CreatePartialDocument: DOM Tree creation/appending failed, status: %x", status);
}
/* print the domTree */
#ifdef _DEBUG1
if (status == KBrsrSuccess)
{
NW_HED_DomHelper_PrintTree
(&contentHandler->domHelper,
NW_HED_DomTree_GetRootNode (contentHandler->domTree));
}
#endif
return status;
}
static
TBrowserStatusCode
NW_XHTML_ContentHandler_AppendPartialDocument( NW_XHTML_ContentHandler_t* contentHandler,
NW_Url_Resp_t* response)
{
return NW_XHTML_ContentHandler_CreatePartialDocument( contentHandler, response, NW_FALSE );
}
/* ------------------------------------------------------------------------- */
static
TBrowserStatusCode
NW_XHTML_ContentHandler_InitializeElementHandlers( NW_XHTML_ContentHandler_t* thisObj )
{
NW_cXML_DOM_DOMVisitor_t* domDOMVisitor = NULL;
NW_DOM_Node_t* domNode = NULL;
NW_DOM_Node_t* prevToLast = NULL;
NW_ASSERT( thisObj != NULL );
NW_TRY (status)
{
// should not crash browser even if domTree is not valid for some reason.
if (!thisObj->domTree)
NW_LOG0(NW_LOG_LEVEL1, "!!!NW_XHTML_ContentHandler_InitializeElementHandlers: BadContent: domTree NULL");
NW_THROW_ON_NULL( thisObj->domTree, status, KBrsrXhtmlBadContent );
// create the DOMVisitor object on the document and use it to traverse the
// tree
domDOMVisitor = NW_cXML_DOM_DOMVisitor_New( NW_HED_DomTree_GetRootNode( thisObj->domTree ) );
NW_THROW_ON_NULL( domDOMVisitor, status, KBrsrOutOfMemory );
NW_LOG0(NW_LOG_LEVEL2, "====== ! NW_XHTML_ContentHandler_Initialize: before while loop ");
// initialize DOMVisitor to last node of the previous chunk as we do not
// want to initialize already visited DOM nodes
domDOMVisitor->currentNode = thisObj->lastInitializedDomNode;
while ( ( domNode = NW_cXML_DOM_DOMVisitor_Next( domDOMVisitor,
NW_DOM_ELEMENT_NODE |
NW_DOM_TEXT_NODE |
NW_DOM_PROCESSING_INSTRUCTION_NODE ) )
!= NULL )
{
const NW_XHTML_ElementHandler_t * elementHandler;
// skip the elements up to the skipToNode, if found set skipToNode to NULL
if (thisObj->skipToNode != NULL )
{
NW_DOM_Node_t* parentNode;
parentNode = NW_DOM_Node_getParentNode((NW_DOM_Node_t*) domNode) ;
if (thisObj->skipToNode == parentNode )
{
continue;
}
else
{
thisObj->skipToNode = NULL;
}
}
// set iBodyIsPresent to true if we hit the <body> tag
if( !thisObj->iBodyIsPresent && NW_DOM_Node_getNodeType ((NW_DOM_Node_t*) domNode ) == NW_DOM_ELEMENT_NODE )
{
if( NW_HED_DomHelper_GetElementToken (domNode) == NW_XHTML_ElementToken_body )
{
//
thisObj->iBodyIsPresent = NW_TRUE;
}
}
prevToLast = thisObj->lastInitializedDomNode;
thisObj->lastInitializedDomNode = domNode;
// get the ElementHandler for the element - if there is no ElementHandler,
// we must ignore the element and continue our traversal
elementHandler = NW_XHTML_ContentHandler_GetElementHandler(
thisObj, (NW_DOM_ElementNode_t*) domNode );
if ( elementHandler == NULL )
{
continue;
}
// initialize the element
status = NW_XHTML_ElementHandler_Initialize(
elementHandler, thisObj, (NW_DOM_ElementNode_t*)domNode );
NW_THROW_ON( status, KBrsrOutOfMemory );
// stopInitEH is a special flag used to stop initializing element
// handlers. It is set by NW_XHTML_ElementHandler_NextSiblingExists(),
// which is called by several of the ElementHandler_Initialize() methods.
if (thisObj->stopInitEH)
{
break;
}
} // end while...
if (thisObj->stopInitEH)
{
// in case select is cut between chunks, leave it processed in the next chunk
thisObj->stopInitEH = NW_FALSE;
if(!thisObj->lastChunk)
{
// Special handling for certain elements; leave their processing to the
// next chunk. Set lastInitializedDomNode to be the node right before,
// either sibling or parent. Note, this is used in conjunction with
// stopInitEH flag set by NW_XHTML_ElementHandler_NextSiblingExists(),
// which is called by several of the ElementHandler_Initialize() methods.
NW_Uint16 token = NW_HED_DomHelper_GetElementToken (thisObj->lastInitializedDomNode);
if (token == NW_XHTML_ElementToken_style ||
token == NW_XHTML_ElementToken_title ||
token == NW_XHTML_ElementToken_script ||
token == NW_XHTML_ElementToken_select ||
token == NW_XHTML_ElementToken_object ||
token == NW_XHTML_ElementToken_map ||
token == NW_XHTML_ElementToken_textarea ||
token == NW_XHTML_ElementToken_table ||
token == NW_XHTML_ElementToken_a)
{
thisObj->lastInitializedDomNode = prevToLast;
}
}
}
NW_LOG0(NW_LOG_LEVEL2, "===== ! NW_XHTML_ContentHandler_Initialize: after while loop ");
}
NW_CATCH (status )
{}
NW_FINALLY
{
NW_Object_Delete (domDOMVisitor);
return status;
}
NW_END_TRY
}
/* ------------------------------------------------------------------------- */
static
NW_Text_t*
NW_XHTML_ContentHandler_UnEscapeText (const NW_Text_t* text)
{
NW_Ucs2* origText = NULL;
NW_Bool freeOrigText = NW_FALSE;
NW_Ucs2* escapedText = NULL;
NW_ASSERT (text != NULL);
/* get the ucs2 string from text */
NW_THROWIF_NULL (origText = NW_Text_GetUCS2Buffer (text, NW_Text_Flags_NullTerminated |
NW_Text_Flags_Aligned, NULL, &freeOrigText));
/* unescape the text */
NW_THROWIF_NULL (escapedText = NW_Str_New(NW_Url_UnEscapeStringLen(origText)));
NW_Url_UnEscapeString(origText, escapedText);
if (freeOrigText == NW_TRUE)
{
NW_Str_Delete (origText);
}
/* create a new text item */
return (NW_Text_t*) NW_Text_UCS2_New ((void*) escapedText, 0, NW_Text_Flags_TakeOwnership);
NW_CATCH_ERROR
if (freeOrigText == NW_TRUE)
{
NW_Str_Delete (origText);
}
NW_Str_Delete (escapedText);
return NULL;
}
// -----------------------------------------------------------------------------
TBrowserStatusCode
NW_XHTML_ContentHandler_ShowFragment (NW_XHTML_ContentHandler_t* thisObj,
const NW_Text_t* fragment)
{
NW_HED_DocumentRoot_t* docRoot = NULL;
NW_Bool mustCallCompleted = NW_FALSE;
TBrowserStatusCode status = KBrsrFailure;
docRoot = (NW_HED_DocumentRoot_t*) NW_HED_DocumentNode_GetRootNode (thisObj);
NW_THROWIF_NULL (docRoot);
/* notify the docRoot that we are performing an intra-document navigation */
NW_THROWIF_ERROR (status = NW_HED_DocumentRoot_HandleIntraPageNavigationStarted (docRoot));
mustCallCompleted = NW_TRUE;
/* navigate to the fragment */
if (fragment != NULL)
{
NW_LMgr_Box_t* boxTree;
NW_Text_t* frag = NULL;
/* unescape the fragment */
frag = NW_XHTML_ContentHandler_UnEscapeText (fragment);
/* show the box */
status = NW_HED_DocumentNode_GetBoxTree (thisObj, &boxTree);
status = docRoot->documentListener->ShowNamedBox (boxTree, frag);
NW_Object_Delete (frag);
if (status != KBrsrSuccess && status != KBrsrNotFound)
{
NW_HED_DocumentNode_HandleError (thisObj, NULL,
BRSR_STAT_CLASS_GENERAL, (NW_WaeError_t) status);
}
NW_THROWIF_ERROR(status);
}
/* "navigate" to the top */
/* TODO see if there is a better way to "scroll" to the top */
else
{
(void) NW_HED_DocumentNode_NodeChanged (thisObj, NULL);
}
/* notify the docRoot that we are done navigating */
NW_HED_DocumentRoot_HandleIntraPageNavigationCompleted (docRoot);
return KBrsrSuccess;
NW_CATCH_ERROR
if (mustCallCompleted == NW_TRUE)
{
NW_HED_DocumentRoot_HandleIntraPageNavigationCompleted (docRoot);
}
return status;
}
// -----------------------------------------------------------------------------
static
TBrowserStatusCode
NW_XHTML_ContentHandler_GetFragment (NW_XHTML_ContentHandler_t* thisObj,
const NW_Text_t* url,
const NW_Text_t** fragment)
{
TBrowserStatusCode status = KBrsrFailure;
const NW_Ucs2* urlStorage = NULL;
NW_Text_Length_t urlLength;
NW_Uint8 urlFreeNeeded = NW_FALSE;
NW_Ucs2* fragmentStorage = NULL;
const NW_Ucs2* currentUrlStorage = NULL;
NW_Ucs2* urlBase = NULL;
NW_Ucs2* currentUrlBase = NULL;
NW_Int32 match;
/* pram check */
NW_THROWIF_NULL (url);
NW_THROWIF_NULL (fragment);
*fragment = NULL;
/* get the base urls */
NW_THROWIF_NULL (urlStorage = NW_Text_GetUCS2Buffer (url, NW_Text_Flags_Aligned,
&urlLength, &urlFreeNeeded));
if (NW_XHTML_ContentHandler_IsSaveddeck(thisObj))
{
NW_THROWIF_NULL (currentUrlStorage = NW_HED_UrlResponse_GetRawUrl (
NW_HED_ContentHandler_GetUrlResponse (thisObj)));
}
else
{
NW_THROWIF_NULL (currentUrlStorage = NW_HED_UrlRequest_GetRawUrl (
NW_HED_ContentHandler_GetUrlRequest (thisObj)));
}
NW_THROWIF_ERROR (status = NW_Url_GetBase(urlStorage, &urlBase));
NW_THROWIF_ERROR (status = NW_Url_GetBase(currentUrlStorage, ¤tUrlBase));
/* compare the current url with the specified */
match = (NW_Str_Strlen (currentUrlBase) != NW_Str_Strlen (urlBase)) || NW_Str_Strncmp (currentUrlBase, urlBase, NW_Str_Strlen (currentUrlStorage));
/* create the fragment Text object */
if (match == 0)
{
if (NW_Url_GetFragId (urlStorage, &fragmentStorage, 0) == KBrsrSuccess)
{
*fragment = (NW_Text_t*)
NW_Text_UCS2_New (fragmentStorage, 0, NW_Text_Flags_TakeOwnership);
}
/*
** else the frag is missing. In this case we want to show the page's default
** fragment (the top of the page). This is done by returning a null fragment
** with a return value of KBrsrSuccess.
*/
}
/* the url bases do not match so return failure */
else
{
NW_Mem_Free (fragmentStorage);
status = KBrsrFailure;
NW_THROW_ERROR();
}
/* clean up after us */
if (urlFreeNeeded)
{
NW_Mem_Free ((NW_Ucs2*) urlStorage);
urlFreeNeeded = NW_FALSE;
}
NW_Mem_Free ((NW_Ucs2*) urlBase);
NW_Mem_Free ((NW_Ucs2*) currentUrlBase);
return KBrsrSuccess;
NW_CATCH_ERROR
if (urlFreeNeeded)
{
NW_Mem_Free ((NW_Ucs2*) urlStorage);
}
NW_Mem_Free (fragmentStorage);
NW_Mem_Free ((NW_Ucs2*) urlBase);
NW_Mem_Free ((NW_Ucs2*) currentUrlBase);
return status;
}
// -----------------------------------------------------------------------------
static
TBrowserStatusCode
NW_XHTML_ContentHandler_LoadFragment (NW_XHTML_ContentHandler_t* thisObj,
NW_HED_UrlRequest_t* urlRequest)
{
NW_HED_DocumentRoot_t* docRoot = NULL;
NW_HED_HistoryStack_t* history = NULL;
NW_HED_HistoryEntry_t* entry = NULL;
NW_HED_HistoryEntry_t* currentEntry = NULL;
const NW_Text_t* url = NULL;
const NW_Text_t* fragment = NULL;
TBrowserStatusCode status = KBrsrFailure;
docRoot = (NW_HED_DocumentRoot_t*) NW_HED_DocumentNode_GetRootNode (thisObj);
NW_THROWIF_NULL (docRoot);
NW_THROWIF_NULL (history = NW_HED_DocumentRoot_GetHistoryStack (docRoot));
/*
** get the fragment, an error will be thrown if the url's base doesn't match the
** base of the url used to load this content handler.
*/
NW_THROWIF_NULL (url = NW_HED_UrlRequest_GetUrl (urlRequest));
NW_THROWIF_ERROR (status = NW_XHTML_ContentHandler_GetFragment (thisObj, url,
(const NW_Text_t**) & fragment));
/* urls that don't contain a fragment shouldn't be handled internally. */
if (fragment == NULL)
{
status = KBrsrFailure;
NW_THROW_ERROR ();
}
/* show the frag */
status = NW_XHTML_ContentHandler_ShowFragment (thisObj, fragment);
if (status != KBrsrNotFound)
{
NW_THROWIF_ERROR(status);
/* add history entry */
if (NW_HED_UrlRequest_IsHistoricRequest (urlRequest) == NW_FALSE)
{
NW_THROWIF_NULL (entry = NW_HED_ContentHandler_CreateIntraDocumentHistoryEntry (thisObj,
url, url));
NW_THROWIF_ERROR (status = NW_HED_HistoryStack_PushEntry (history, entry));
entry = NULL;
NW_Object_Delete (urlRequest);
urlRequest = NULL;
}
/* update the content handler to point to the associated history entry */
NW_THROWIF_NULL (currentEntry = NW_HED_HistoryStack_GetEntry (history,
NW_HED_HistoryStack_Direction_Current));
NW_THROWIF_ERROR (status = NW_HED_ContentHandler_SetAssociatedHistoryEntry (
thisObj, currentEntry));
}
NW_Object_Delete ((NW_Text_t*) fragment);
return KBrsrSuccess;
NW_CATCH_ERROR
NW_Object_Delete ((NW_Text_t*) fragment);
NW_Object_Delete (entry);
return status;
}
// -----------------------------------------------------------------------------
static
TBrowserStatusCode
NW_XHTML_ContentHandler_DeleteFormLiaison (NW_XHTML_ContentHandler_t* thisObj)
{
NW_ADT_Vector_Metric_t nodeCtxSize = NW_ADT_Vector_GetSize(thisObj->nodeContexts);
for (NW_ADT_Vector_Metric_t i = 0 ; i < nodeCtxSize; i++)
{
NW_XHTML_Form_Node_Context_t* formCtx =
*(NW_XHTML_Form_Node_Context_t**)NW_ADT_Vector_ElementAt
(thisObj->nodeContexts, i);
NW_XHTML_FormLiaison_t* formLiaison = (NW_XHTML_FormLiaison_t*)formCtx->formLiaison;
NW_Object_Delete(formLiaison);
formCtx->formLiaison = NULL;
delete formCtx ;
}
return KBrsrSuccess;
}
// -----------------------------------------------------------------------------
static
TBrowserStatusCode
NW_XHTML_ContentHandler_RestoreControlSet (NW_XHTML_ContentHandler_t* thisObj)
{
NW_HED_DocumentRoot_t* documentRoot;
NW_HED_HistoryEntry_t* entry;
NW_Object_Dynamic_t* controlValueSet;
const NW_HED_UrlRequest_t *urlReq;
documentRoot =
(NW_HED_DocumentRoot_t*) NW_HED_DocumentNode_GetRootNode (thisObj);
NW_THROWIF_NULL (documentRoot);
NW_THROWIF_NULL (entry = NW_HED_HistoryStack_GetEntry (documentRoot->historyStack,
NW_HED_HistoryStack_Direction_Current));
NW_THROWIF_NULL (urlReq = NW_HED_HistoryEntry_GetUrlRequest (entry));
NW_THROWIF_NULL (thisObj->historyContentData =
NW_HED_HistoryEntry_GetContentDataHolder (entry));
NW_THROWIF_ERROR(NW_Object_Shared_OrphanObject(thisObj->historyContentData,
&controlValueSet));
/*
** clear the cached form values if we are reloading the document,
** otherwise restore them.
*/
if (NW_HED_UrlRequest_GetReason (urlReq) == NW_HED_UrlRequest_Reason_ShellReload)
{
NW_Object_Delete (controlValueSet);
}
else
{
thisObj->controlValueSet = NW_ADT_DynamicVectorOf(controlValueSet);
}
return KBrsrSuccess;
NW_CATCH_ERROR
return KBrsrFailure;
}
// -----------------------------------------------------------------------------
static
NW_HED_Context_t*
NW_XHTML_GetGlobalContext (NW_XHTML_ContentHandler_t* thisObj)
{
#if 1 /* use this one if we want to support wml-variables in xhtml */
NW_HED_DocumentRoot_t* docRoot = NULL;
docRoot = (NW_HED_DocumentRoot_t*) NW_HED_DocumentNode_GetRootNode (thisObj);
return NW_HED_DocumentRoot_GetContext (docRoot, NW_HED_DocumentRoot_ContextGlobalId);
#else /* otherwise use this one */
NW_REQUIRED_PARAM (thisObj);
return NULL;
#endif
}
// -----------------------------------------------------------------------------
static
TBrowserStatusCode
NW_XHTML_ContentHandler_MetaRefreshCreateTimer(NW_XHTML_ContentHandler_t* thisObj)
{
NW_ASSERT(thisObj);
NW_TRY (status)
{
if (thisObj->metaRefreshTimer == NULL)
{
thisObj->metaRefreshTimer =
NW_System_Timer_New(NW_XHTML_ContentHandler_MetaRefreshTimerCallback,
thisObj, (thisObj->metaRefreshSeconds * 1000), NW_FALSE);
NW_THROW_OOM_ON_NULL(thisObj->metaRefreshTimer, status);
}
}
NW_CATCH (status)
{}
NW_FINALLY {
return status;
} NW_END_TRY
}
// -----------------------------------------------------------------------------
static
void
NW_XHTML_ContentHandler_MetaRefreshDestroyTimer(NW_XHTML_ContentHandler_t* thisObj)
{
NW_ASSERT(thisObj);
if (thisObj->metaRefreshTimer != NULL)
{
NW_Object_Delete (thisObj->metaRefreshTimer);
thisObj->metaRefreshTimer = NULL;
}
}
// -----------------------------------------------------------------------------
static
void
NW_XHTML_ContentHandler_MetaRefreshSuspendTimer(NW_XHTML_ContentHandler_t* thisObj)
{
NW_ASSERT(thisObj);
if (thisObj->metaRefreshTimer != NULL)
{
/* return status is ignored */
(void) NW_System_Timer_Stop(thisObj->metaRefreshTimer);
}
}
// -----------------------------------------------------------------------------
static
void
NW_XHTML_ContentHandler_MetaRefreshResumeTimer(NW_XHTML_ContentHandler_t* thisObj)
{
NW_ASSERT(thisObj);
if (thisObj->metaRefreshTimer != NULL)
{
/* return status is ignored */
(void) NW_System_Timer_Resume(thisObj->metaRefreshTimer);
}
}
// -----------------------------------------------------------------------------
static
TBrowserStatusCode
NW_XHTML_ContentHandler_MetaRefreshStartLoad(NW_XHTML_ContentHandler_t* thisObj)
{
NW_HED_DocumentRoot_t* docRoot;
NW_ASSERT(thisObj);
NW_ASSERT(thisObj->metaRefreshResolvedUrl);
NW_TRY (status)
{
docRoot = (NW_HED_DocumentRoot_t*) NW_HED_DocumentNode_GetRootNode(thisObj);
NW_THROWIF_NULL(docRoot);
status = NW_HED_DocumentRoot_StartLoad(docRoot,
NW_HED_DocumentNodeOf(docRoot),
thisObj->metaRefreshResolvedUrl,
thisObj->metaRefreshLoadReason,
NULL,
NW_UrlRequest_Type_Any, NW_CACHE_NOCACHE);
_NW_THROW_ON_ERROR(status);
}
NW_CATCH (status)
{
NW_CATCH_ERROR
if (status != KBrsrSuccess)
{
NW_HED_DocumentNode_HandleError(thisObj,
NW_HED_ContentHandler_GetUrlRequest(thisObj),
BRSR_STAT_CLASS_GENERAL,
(NW_WaeError_t) status);
}
}
NW_FINALLY {
/* metaRefreshResolvedUrl will never be used again. */
if (thisObj->metaRefreshResolvedUrl != NULL)
{
NW_Object_Delete (thisObj->metaRefreshResolvedUrl);
thisObj->metaRefreshResolvedUrl = NULL;
}
return status;
} NW_END_TRY
}
// -----------------------------------------------------------------------------
static
TBrowserStatusCode
NW_XHTML_ContentHandler_MetaRefreshTimerCallback(void* timerData)
{
TBrowserStatusCode status;
NW_XHTML_ContentHandler_t* thisObj;
NW_ASSERT(timerData);
/* cast timerData to aggregate */
thisObj = NW_XHTML_ContentHandlerOf(timerData);
NW_XHTML_ContentHandler_MetaRefreshDestroyTimer(thisObj);
status = NW_XHTML_ContentHandler_MetaRefreshStartLoad(thisObj);
return status;
}
// -----------------------------------------------------------------------------
static
void
NW_XHTML_ContentHandler_ActivateImageMapBox( NW_XHTML_ContentHandler_t* thisObj )
{
NW_ASSERT( thisObj );
// loop through the image map boxes and create area list for each of them
if ( thisObj->imageMapLookupTable )
{
// imageElement list
CMapElementList* mapElementList = (CMapElementList*)thisObj->imageMapLookupTable;
TInt mapElementCount = mapElementList->MapElementCount();
for ( TInt i = 0; i < mapElementCount; i++ )
{
CMapElementEntry* entry = mapElementList->MapElementEntry( i );
// get image map boxes. note that one useMap can hold multiple
// image map boxes.
CImageMapBoxList* imageMapBoxList = entry->ImageMapBoxList();
NW_DOM_ElementNode_t* domNode = entry->DomNode();
// initailaze image map unless either the <img usemap= or
// <map name= is missing.
if ( imageMapBoxList && domNode )
{
TInt imageListCount = imageMapBoxList->Count();
for ( TInt j = 0; j < imageListCount; j++ )
{
// get image element handler
const NW_XHTML_ElementHandler_t* imageElementHandler =
NW_XHTML_ElementHandlerOf( &NW_XHTML_imgElementHandler );
NW_LMgr_ImageMapBox_t* imageMapBox = imageMapBoxList->At( j );
// call create area list on every image boxes unless the image box
// has already been initialized with the area boxes -do not create
// areaboxes twice
if ( !NW_LMgr_ImageMapBox_GetAreaBoxList( imageMapBox ) )
{
// ignore return value
(void)NW_XHTML_imgElementHandler_CreateAreaList(
imageElementHandler, thisObj, domNode, NW_LMgr_BoxOf( imageMapBox ) );
}
}
}
}
}
}
// -----------------------------------------------------------------------------
static
TBrowserStatusCode
NW_XHTML_ContentHandler_DeleteAllElementHandlerInstances(NW_XHTML_ContentHandler_t *thisObj)
{
NW_ADT_MapIterator_t iterator;
NW_Object_Invalidate (&iterator);
NW_TRY (status) {
/* create an iterator */
status = NW_ADT_MapIterator_Initialize (&iterator, thisObj->iElementHandlerMap);
NW_THROW_ON_ERROR (status);
while (NW_ADT_Iterator_HasMoreElements (&iterator)) {
void* key;
CBase* elementHandler;
status = NW_ADT_Iterator_GetNextElement (&iterator, &key);
NW_ASSERT (status == KBrsrSuccess);
status = NW_ADT_Map_Get (thisObj->iElementHandlerMap, &key, &elementHandler);
NW_THROW_ON_ERROR (status);
if (elementHandler) {
delete elementHandler;
}
}
NW_ADT_Map_Clear (thisObj->iElementHandlerMap);
}
NW_CATCH (status) {
}
NW_FINALLY {
NW_Object_Terminate (&iterator);
return status;
} NW_END_TRY
}
// -----------------------------------------------------------------------------
const
NW_XHTML_ContentHandler_Class_t NW_XHTML_ContentHandler_Class =
{
{ /* NW_Object_Core */
/* super */ &NW_HED_CompositeContentHandler_Class,
/* querySecondary */ _NW_Object_Base_QueryInterface
},
{ /* NW_Object_Base */
/* interfaceList */ NW_XHTML_InterfaceList
},
{ /* NW_Object_Dynamic */
/* instanceSize */ sizeof (NW_XHTML_ContentHandler_t),
/* construct */ _NW_XHTML_ContentHandler_Construct,
/* destruct */ _NW_XHTML_ContentHandler_Destruct
},
{ /* NW_HED_DocumentNode */
/* cancel */ _NW_XHTML_ContentHandler_Cancel,
/* partialLoadCallback */ NULL,
/* initialize */ _NW_XHTML_ContentHandler_Initialize,
/* nodeChanged */ _NW_HED_DocumentNode_NodeChanged,
/* getBoxTree */ _NW_HED_ContentHandler_GetBoxTree,
/* processEvent */ _NW_XHTML_ContentHandler_ProcessEvent,
/* handleError */ _NW_HED_DocumentNode_HandleError,
/* suspend */ _NW_XHTML_ContentHandler_Suspend,
/* resume */ _NW_XHTML_CompositeContentHandler_Resume,
/* allLoadsCompleted */ _NW_XHTML_ContentHandler_AllLoadsCompleted,
/* intraPageNavigationCompleted */ _NW_HED_DocumentNode_IntraPageNavigationCompleted,
/* loseFocus */ _NW_XHTML_ContentHandler_LoseFocus,
/* gainFocus */ _NW_XHTML_ContentHandler_GainFocus,
/* handleLoadComplete */ _NW_XHTML_DocumentNode_HandleLoadComplete,
},
{ /* NW_HED_ContentHandler */
/* partialNextChunk */ _NW_XHTML_ContentHandler_PartialNextChunk,
/* getTitle */ _NW_XHTML_ContentHandler_GetTitle,
/* getUrl */ _NW_HED_ContentHandler_GetURL,
/* resolveUrl */ _NW_XHTML_ContentHandler_ResolveURL,
/* createHistoryEntry */ _NW_HED_ContentHandler_CreateHistoryEntry,
/* createIntraHistoryEntry */ _NW_HED_ContentHandler_CreateIntraDocumentHistoryEntry,
/* newUrlResponse */ _NW_HED_ContentHandler_NewUrlResponse,
/* createBoxTree */ _NW_XHTML_ContentHandler_CreateBoxTree,
/* handleRequest */ _NW_XHTML_ContentHandler_HandleRequest,
/* featureQuery */ _NW_HED_ContentHandler_FeatureQuery,
/* responseComplete */ _NW_HED_ContentHandler_ResponseComplete
},
{ /* NW_HED_CompositeContentHandler */
/* documentDisplayed */ _NW_XHTML_ContentHandler_DocumentDisplayed,
},
/* (Kimono has this in Epoc32XhtmlContentHandler) */
{ /* NW_XHTML_ContentHandler */
/* numModules */ 0,
/* modules */ NULL
}
};
// -----------------------------------------------------------------------------
const
NW_Object_Class_t* const NW_XHTML_InterfaceList[] =
{
&NW_XHTML_ContentHandler_NumberCollector_Class,
NULL
};
// -----------------------------------------------------------------------------
const
NW_Markup_NumberCollector_Class_t NW_XHTML_ContentHandler_NumberCollector_Class =
{
{ /* NW_Object_Core */
/* super */ &NW_Markup_NumberCollector_Class,
/* querySecondary */ _NW_Object_Core_QuerySecondary
},
{ /* NW_Object_Secondary */
/* offset */ offsetof (NW_XHTML_ContentHandler_t,
NW_Markup_NumberCollector)
},
{ /* NW_Object_Aggregate */
/* secondaryList */ _NW_Markup_NumberCollector_SecondaryList,
/* construct */ NULL,
/* destruct */ NULL
},
{ /* NW_Markup_NumberCollector */
/* getBoxTree */ _NW_XHTML_ContentHandler_NumberCollector_GetBoxTree,
/* boxIsValid */ _NW_Markup_NumberCollector_BoxIsValid,
/* getHrefAttr */ _NW_XHTML_ContentHandler_NumberCollector_GetHrefAttr,
/* getAltAttr */ _NW_XHTML_ContentHandler_NumberCollector_GetAltAttr
}
};
/* ------------------------------------------------------------------------- *
virtual methods
* ------------------------------------------------------------------------- */
// -----------------------------------------------------------------------------
TBrowserStatusCode
_NW_XHTML_ContentHandler_Construct (NW_Object_Dynamic_t* dynamicObject,
va_list* argp)
{
NW_XHTML_ContentHandler_t* thisObj;
TBrowserStatusCode status;
const NW_HED_UrlRequest_t* urlRequest;
NW_LOG0(NW_LOG_LEVEL2, "NW_XHTML_ContentHandler_Construct START");
/* for convenience */
thisObj = NW_XHTML_ContentHandlerOf (dynamicObject);
/* invoke our superclass constructor */
status = _NW_HED_CompositeContentHandler_Construct (dynamicObject, argp);
if (status != KBrsrSuccess)
{
return status;
}
thisObj->domTree = NULL;
thisObj->title = NULL;
thisObj->baseElement = NULL;
thisObj->contentLocation = NULL;
thisObj->iBodyNode = NULL;
thisObj->nodeContexts = (NW_ADT_DynamicVector_t*)
NW_ADT_ResizableVector_New (sizeof (NW_XHTML_Form_Node_Context_t*),
0, 5);
if (thisObj->nodeContexts == NULL)
{
return KBrsrOutOfMemory;
}
thisObj->iElementHandlerMap = (NW_ADT_Map_t*) NW_ADT_ResizableMap_New (
sizeof(NW_DOM_ElementNode_t*), sizeof(CBase*), 1, 1);
if (thisObj->iElementHandlerMap == NULL)
{
NW_Object_Delete(thisObj->nodeContexts);
thisObj->nodeContexts = NULL;
return KBrsrOutOfMemory;
}
thisObj->processor = NULL;
thisObj->historyContentData = NULL;
thisObj->controlValueSet = NULL;
thisObj->controlSet = NULL;
thisObj->saveddeck = NW_FALSE;
thisObj->histload = NW_FALSE;
thisObj->reload = NW_FALSE;
thisObj->htmlSubset = NW_XHTML_CONTENTHANDLER_IMODEHTMLEXT;
thisObj->metaRefreshSet = NW_FALSE;
thisObj->metaRefreshResolvedUrl = NULL;
thisObj->metaRefreshTimer = NULL;
thisObj->ignoreFramesetElement = NW_FALSE;
thisObj->ignoreBodyElement = NW_FALSE;
thisObj->ignoreNoScriptElement = NW_TRUE;
thisObj->imageMapLookupTable = NULL;
// ZAL: find a better init value
thisObj->lastInitializedDomNode = 0;
thisObj->stopInitEH = NW_FALSE;
thisObj->lastChunk = NW_FALSE;
thisObj->iScriptIsExecuted = NW_FALSE;
thisObj->iScriptIsResumed = NW_FALSE;
//
thisObj->switchBackToNormalLayout = NW_FALSE;
thisObj->formattingComplete = NW_FALSE;
thisObj->scriptLoadComplete = NW_FALSE;
thisObj->iBodyIsPresent = NW_FALSE;
thisObj->metaNoCache = NW_FALSE;
thisObj->metaCacheExpires = NW_FALSE;
thisObj->metaExpiresDate = NULL;
thisObj->iScriptCancelled = NW_FALSE;
thisObj->scriptLoadTransactionIds = (void*)(new RArray<TExternalScriptNode>);
if (!thisObj->scriptLoadTransactionIds)
{
return KBrsrOutOfMemory;
}
thisObj->scriptNodes = (void*)(new RPointerArray<NW_XHTML_Script_Node_Context_t>(1));
if (!thisObj->scriptNodes)
{
return KBrsrOutOfMemory;
}
thisObj->formNodes = (void*)(new RPointerArray<NW_DOM_ElementNode_t>(1));
if (!thisObj->formNodes)
{
return KBrsrOutOfMemory;
}
TRAPD(ret, thisObj->iMessageListener = new (ELeave) TMessageListener (thisObj));
if (ret == KErrNoMemory)
{
return KBrsrOutOfMemory;
}
/*
** reset the global context if the request that created the content-handler
** was started from a shell request, like the goto dialog or
** hotlist dialog. See WML June2000 Specification section 10.4.
*/
urlRequest = va_arg (*argp, NW_HED_UrlRequest_t*);
NW_ASSERT (urlRequest);
NW_ASSERT (NW_Object_IsInstanceOf (urlRequest, &NW_HED_UrlRequest_Class));
if (NW_HED_UrlRequest_GetReason (urlRequest) == NW_HED_UrlRequest_Reason_ShellLoad)
{
NW_HED_Context_t* context;
context = NW_XHTML_GetGlobalContext (thisObj);
NW_HED_Context_Reset (context);
}
/*
* Initialize a local copy of the CCSSVariableStyleSheet. Note that
* if it already exists this will efficiently get a copy of the
* reference. If not then it will be created on the spot.
*/
thisObj->variableStyleSheet = CCSSVariableStyleSheet::CreateSingleton();
NW_LOG0(NW_LOG_LEVEL2, "NW_XHTML_ContentHandler_Construct END");
/* successful completion */
return KBrsrSuccess;
}
// -----------------------------------------------------------------------------
void
_NW_XHTML_ContentHandler_Destruct (NW_Object_Dynamic_t* dynamicObject)
{
NW_XHTML_ContentHandler_t* thisObj;
/* cast the 'object' for convenience */
thisObj = NW_XHTML_ContentHandlerOf (dynamicObject);
if (thisObj->iBodyNode && NW_Settings_GetEcmaScriptEnabled())
{
NW_HED_DocumentRoot_t* documentRoot = (NW_HED_DocumentRoot_t*) NW_HED_DocumentNode_GetRootNode (thisObj);
if (!documentRoot->documentListener->Exiting())
{
#if !defined(__SERIES60_28__) && !defined(__SERIES60_27__)
// Don't execute scripts if the browser is exiting. It will crash
//R->ecma
//NW_Ecma_HandleEvent(documentRoot , thisObj->iBodyNode, thisObj->iBodyNode, NW_Ecma_Evt_OnUnload);
#endif
}
}
NW_XHTML_ContentHandler_DeleteFormLiaison (thisObj);
NW_HED_DomTree_Delete (thisObj->domTree);
thisObj->domTree = NULL;
thisObj->baseElement = NULL;
NW_Str_Delete(thisObj->contentLocation);
NW_Object_Delete (thisObj->title);
thisObj->title = NULL;
thisObj->iScriptIsResumed = NW_FALSE;
// if the document root reference the referrer url from this document
// set it to NULL
NW_HED_DocumentRoot_t* docRoot = (NW_HED_DocumentRoot_t*)
NW_HED_DocumentNode_GetRootNode (thisObj);
const NW_Text_t* referrerUrl = NW_HED_DocumentRoot_GetDocumentReferrer(docRoot);
const NW_HED_UrlResponse_t* urlResponse = NW_HED_ContentHandler_GetUrlResponse( thisObj );
if ( urlResponse && referrerUrl && referrerUrl == NW_HED_UrlResponse_GetUrl( urlResponse ) )
{
NW_HED_DocumentRoot_SetDocumentReferrer(docRoot , NULL);
}
RArray<TExternalScriptNode>* scriptIds = STATIC_CAST(RArray<TExternalScriptNode>*, thisObj->scriptLoadTransactionIds);
if (scriptIds)
{
scriptIds->Close();
delete scriptIds;
}
RPointerArray<NW_XHTML_Script_Node_Context_t>* scriptNodeList = STATIC_CAST(RPointerArray<NW_XHTML_Script_Node_Context_t>*,
thisObj->scriptNodes);
if (scriptNodeList)
{
scriptNodeList->ResetAndDestroy();
scriptNodeList->Close();
delete scriptNodeList;
}
RPointerArray<NW_DOM_ElementNode_t>* formNodes = (RPointerArray<NW_DOM_ElementNode_t>*)thisObj->formNodes;
{
formNodes->Reset();
delete formNodes;
}
NW_Object_Delete (thisObj->nodeContexts);
thisObj->nodeContexts = NULL;
NW_XHTML_ContentHandler_DeleteAllElementHandlerInstances(thisObj);
NW_Object_Delete(thisObj->iElementHandlerMap);
thisObj->iElementHandlerMap = NULL;
NW_Object_Delete (thisObj->processor);
if (thisObj->metaRefreshResolvedUrl != NULL)
{
NW_Object_Delete (thisObj->metaRefreshResolvedUrl);
thisObj->metaRefreshResolvedUrl = NULL;
}
if (thisObj->metaRefreshTimer != NULL)
{
NW_XHTML_ContentHandler_MetaRefreshDestroyTimer(thisObj);
}
/* save any possible form control values to history */
if (thisObj->controlSet != NULL)
{
if (thisObj->historyContentData != NULL)
{
NW_Object_Dynamic_t* controlValueSet;
controlValueSet = (NW_Object_Dynamic_t*)
NW_XHTML_ControlSet_GetValueVector (thisObj->controlSet);
(void) NW_Object_Shared_AdoptObject (thisObj->historyContentData, controlValueSet);
}
NW_Object_Delete (thisObj->controlSet);
}
if (thisObj->controlValueSet != NULL)
{
NW_Object_Delete (thisObj->controlValueSet);
}
if (thisObj->imageMapLookupTable != NULL)
{
delete static_cast<CMapElementList*>(thisObj->imageMapLookupTable);
thisObj->imageMapLookupTable = NULL;
}
NW_Str_Delete(thisObj->metaExpiresDate);
delete thisObj->iMessageListener;
}
// -----------------------------------------------------------------------------
TBrowserStatusCode
_NW_XHTML_ContentHandler_Cancel(NW_HED_DocumentNode_t* documentNode,
NW_HED_CancelType_t cancelType)
{
TBrowserStatusCode status;
NW_XHTML_ContentHandler_t* thisObj;
// parameter assertion block
NW_ASSERT (NW_Object_IsInstanceOf (documentNode,
&NW_XHTML_ContentHandler_Class));
// cast into the 'thisObj' pointer for convenience
thisObj = NW_XHTML_ContentHandlerOf (documentNode);
// stop the META-Refresh timer if it is running
NW_XHTML_ContentHandler_MetaRefreshDestroyTimer(thisObj);
thisObj->iScriptCancelled = NW_TRUE;
// cancel any executing event script
NW_HED_DocumentRoot_t *documentRoot =
(NW_HED_DocumentRoot_t*) NW_HED_DocumentNode_GetRootNode (thisObj);
RArray<TExternalScriptNode>* scriptIds = STATIC_CAST(RArray<TExternalScriptNode>*, thisObj->scriptLoadTransactionIds);
scriptIds->Reset();
if (thisObj->scriptNodes)
{
RPointerArray<NW_XHTML_Script_Node_Context_t>* scriptNodeList = STATIC_CAST(RPointerArray<NW_XHTML_Script_Node_Context_t>*,
thisObj->scriptNodes);
scriptNodeList->ResetAndDestroy();
}
// invoke super class cancel
status = NW_HED_CompositeContentHandler_Class.NW_HED_DocumentNode.
cancel(documentNode, cancelType);
return status;
}
static TBrowserStatusCode NW_HTMLP_NotifyDocCompleteCallBack(void* context,
const NW_Buffer_t* residueWbxml, NW_Uint32 encoding,
NW_Uint32 codePageSwitchCount, NW_Int32 lastValid, void* WBXMLEncStrTbl)
{
TBrowserStatusCode status = KBrsrSuccess;
NW_XHTML_ContentHandler_t* thisObj = (NW_XHTML_ContentHandler_t*) context;
NW_Buffer_t* buffer = (NW_Buffer_t*) residueWbxml;
if (buffer != NULL)
{
if (!thisObj->domTree)
{
thisObj->domTree = NW_HED_DomTree_New(buffer,
(NW_Http_CharSet_t) encoding,
NW_xhtml_1_0_PublicId,
WBXMLEncStrTbl);
/* init the domHelper */
thisObj->domHelper.entitySet = NW_HED_EntitySetOf(&NW_XHTML_EntitySet);
thisObj->domHelper.context = NULL;
thisObj->domHelper.resolvePlainTextVariablesAndEntities = NW_TRUE;
/* find the body element, if it exists */
if (thisObj->domTree != NULL)
{
thisObj->baseElement = NW_HED_DomHelper_FindElement(&(thisObj->domHelper),
NW_HED_DomTree_GetRootNode(thisObj->domTree),
3, NW_XHTML_ElementToken_base, 0, NULL);
}
else
{
status = KBrsrUnexpectedError;
}
}
else
{
status = NW_HED_DomTree_Append(&thisObj->domTree, buffer,
(NW_Http_CharSet_t) encoding, NW_xhtml_1_0_PublicId, codePageSwitchCount,
lastValid, WBXMLEncStrTbl);
}
}
return status;
}
// -----------------------------------------------------------------------------
TBrowserStatusCode
_NW_XHTML_ContentHandler_Initialize(NW_HED_DocumentNode_t* documentNode,
TBrowserStatusCode aInitStatus)
{
NW_XHTML_ContentHandler_t* thisObj;
NW_HED_ContentHandler_t* contentHandler;
const NW_HED_UrlRequest_t* urlRequest;
NW_Uint32 encoding;
void* WBXMLEncStrTbl = NULL;
NW_REQUIRED_PARAM(aInitStatus);
NW_TRY(status)
{
NW_LOG0(NW_LOG_LEVEL2, "_NW_XHTML_ContentHandler_Initialize START");
// cast into the 'thisObj' pointer for convenience
thisObj = NW_XHTML_ContentHandlerOf(documentNode);
NW_LOG0(NW_LOG_LEVEL2,
"in _NW_XHTML_ContentHandler_Initialize documentLoadComplete");
contentHandler = NW_HED_ContentHandlerOf(thisObj);
if ( NW_Asc_stricmp((char*)HTTP_application_xhtml_xml_saved_string,
(char*)contentHandler->response->contentTypeString) == 0 ||
NW_Asc_stricmp((char*)HTTP_application_saved_string,
(char*)contentHandler->response->contentTypeString) == 0 )
{
NW_XHTML_ContentHandler_SetSaveddeck(thisObj, NW_TRUE);
}
urlRequest = NW_HED_ContentHandler_GetUrlRequest(contentHandler);
if(urlRequest != NULL && (NW_HED_UrlRequest_GetReason(urlRequest) == NW_HED_UrlRequest_Reason_ShellPrev))
{
NW_XHTML_ContentHandler_SetHistoryLoad(thisObj, NW_TRUE);
}
if(urlRequest != NULL && (NW_HED_UrlRequest_GetReason(urlRequest) == NW_HED_UrlRequest_Reason_ShellReload))
{
NW_XHTML_ContentHandler_SetReLoad(thisObj, NW_TRUE);
}
// do not call node initialize on the handler if there are external
// script loads pending. If load count > 0 then super class is
// initialized in the function _NW_XHTML_DocumentNode_HandleLoadComplete
// when document loading is complete, let the parser know about it
// as it might have some leftovers to process
if (thisObj->htmlpParser)
{
NW_HTMLP_NotifyDocComplete(thisObj->htmlpParser, &encoding,
&WBXMLEncStrTbl, NW_HTMLP_NotifyDocCompleteCallBack, thisObj);
thisObj->htmlpParser = NULL;
}
// in case select is the last part of page, we always leave it processed in the next chunk
// if there's no more chunk, we still want to process select
thisObj->lastChunk = NW_TRUE;
// make sure we've got the dom tree
if (!thisObj->domTree)
{
NW_LOG0(NW_LOG_LEVEL1, "_NW_XHTML_ContentHandler_Initialize: BadContent error: domTree null");
}
NW_THROW_ON_NULL(thisObj->domTree, status, KBrsrXhtmlBadContent);
status = NW_XHTML_ContentHandler_InitializeElementHandlers( thisObj );
// Do we really wanna jump to the end and leaving out
// initialization if something fails on initelemhandlers?
_NW_THROW_ON_ERROR(status);
NW_Uint16 token = NW_HED_DomHelper_GetElementToken( thisObj->lastInitializedDomNode );
if(token == NW_XHTML_ElementToken_style ||
token == NW_XHTML_ElementToken_title ||
token == NW_XHTML_ElementToken_script ||
token == NW_XHTML_ElementToken_select ||
token == NW_XHTML_ElementToken_object ||
token == NW_XHTML_ElementToken_map ||
token == NW_XHTML_ElementToken_textarea ||
token == NW_XHTML_ElementToken_table ||
token == NW_XHTML_ElementToken_a)
{
NW_HED_DocumentRoot_t* docRoot = NULL;
// set the default priority on this chunk
CActive :: TPriority priorirty = (( CActive::TPriority )( CActive::EPriorityStandard ));
docRoot = ( NW_HED_DocumentRoot_t* ) NW_HED_DocumentNode_GetRootNode( thisObj );
( void ) docRoot->documentListener->DocumentChangedPartial( docRoot, priorirty );
}
// create area list on each image map box
NW_XHTML_ContentHandler_ActivateImageMapBox(thisObj);
// no more partial content comes.
// invalidate prev ecma script context
// invoke our superclass method
status = NW_HED_CompositeContentHandler_Class.NW_HED_DocumentNode.
initialize(documentNode, KBrsrSuccess);
NW_LOG0(NW_LOG_LEVEL2, "_NW_XHTML_ContentHandler_Initialize END");
#ifdef _DEBUG1
if (thisObj->domTree != NULL)
{
NW_HED_DomHelper_PrintTree (&thisObj->domHelper, NW_HED_DomTree_GetRootNode (thisObj->domTree) );
}
#endif
}
NW_CATCH( status )
{
}
NW_FINALLY
{
return status;
}
NW_END_TRY
}
/* ------------------------------------------------------------------------- */
TBrowserStatusCode
_NW_XHTML_ContentHandler_PartialNextChunk( NW_HED_ContentHandler_t* contentHandler,
NW_Int32 chunkIndex, NW_Url_Resp_t* response,
void* context)
{
NW_XHTML_ContentHandler_t* thisObj;
NW_ASSERT( contentHandler != NULL );
NW_LOG1( NW_LOG_LEVEL2, "_NW_XHTML_ContentHandler_PartialNextChunk starts: chunkIndex: %d", chunkIndex);
#ifdef __WINS__
if ( response != NULL && response->body != NULL )
{
char* buffer;
buffer = (char*)malloc( response->body->length + 1 );
if (buffer != NULL)
{
memcpy( (void*)buffer, (const void*)response->body->data, response->body->length );
buffer[ response->body->length ] = 0;
FILE* stream = fopen( "chunks.txt", "a+" ); /* open for reading and appending */
if (stream != NULL)
{
fprintf((FILE*)stream, "\n\n========== Chunk %d ==============\n", chunkIndex );
fprintf((FILE*)stream, "%s", buffer );
fflush((FILE*)stream);
fclose((FILE*)stream);
}
}
free( (void*)buffer);
}
#endif // _WINS_
NW_TRY( status )
{
// set the default priority on this chunk
CActive::TPriority priorirty = ((CActive::TPriority)( CActive::EPriorityLow + 2 ));
NW_HED_DocumentRoot_t* docRoot;
const NW_HED_UrlRequest_t* urlRequest;
// cast into the 'thisObj' pointer for convenience
thisObj = NW_XHTML_ContentHandlerOf( contentHandler );
docRoot = (NW_HED_DocumentRoot_t*) NW_HED_DocumentNode_GetRootNode( thisObj );
NW_Bool oldBodyIsPresent = thisObj->iBodyIsPresent;
// make sure we have a valid response
NW_THROW_ON_NULL( response, status, KBrsrUnexpectedError );
// first chunk.
if ( chunkIndex == 0 )
{
// set body to false
thisObj->iBodyIsPresent = NW_FALSE;
//
NW_Bool disableSmallScreen;
// invoke superclass
status = NW_HED_ContentHandler_Class.NW_HED_ContentHandler.partialNextChunk(
contentHandler, chunkIndex, response, context );
// response has been released by the base class call.
response = NULL;
_NW_THROW_ON_ERROR( status );
// disable ss on xhtml pages.
disableSmallScreen = (NW_Bool)( NW_Asc_stricmp(
(char*)HTTP_application_vnd_wap_xhtml_xml_string,
(char*)contentHandler->response->contentTypeString ) == 0 );
NW_Settings_SetDisableSmallScreenLayout( disableSmallScreen );
// if the current layout is Normal layout or ss is enabled, switch to vertical layout.
if ( !NW_Settings_GetVerticalLayoutEnabled() && !disableSmallScreen )
{
NW_Settings_SetInternalVerticalLayoutEnabled( NW_TRUE );
thisObj->switchBackToNormalLayout = NW_TRUE;
}
// get rid of the old title (if any)
(void) NW_XHTML_ContentHandler_SetTitle( thisObj, NULL );
// get the controlSet from the history
status = NW_XHTML_ContentHandler_RestoreControlSet( thisObj );
_NW_THROW_ON_ERROR( status );
// build the dom tree out of the first chunk
status = NW_XHTML_ContentHandler_CreatePartialDocument( thisObj,
contentHandler->response, NW_TRUE );
_NW_THROW_ON_ERROR( status );
// Must mark as a saved deck before we initialize the element
// handlers and make requests
if( NW_Asc_stricmp((char*)HTTP_application_xhtml_xml_saved_string,
(char*)contentHandler->response->contentTypeString) == 0 ||
NW_Asc_stricmp((char*)HTTP_application_saved_string,
(char*)contentHandler->response->contentTypeString) == 0 )
{
NW_XHTML_ContentHandler_SetSaveddeck(thisObj, NW_TRUE);
}
urlRequest = NW_HED_ContentHandler_GetUrlRequest(contentHandler);
if(urlRequest != NULL && (NW_HED_UrlRequest_GetReason(urlRequest) == NW_HED_UrlRequest_Reason_ShellPrev))
{
NW_XHTML_ContentHandler_SetHistoryLoad(thisObj, NW_TRUE);
}
if(urlRequest != NULL && (NW_HED_UrlRequest_GetReason(urlRequest) == NW_HED_UrlRequest_Reason_ShellReload))
{
NW_XHTML_ContentHandler_SetReLoad(thisObj, NW_TRUE);
}
// initialize partial element handlers
status = NW_XHTML_ContentHandler_InitializeElementHandlers( thisObj );
_NW_THROW_ON_ERROR( status );
}
else if ( chunkIndex != -1 )
{
// build the dom tree out of the chunk
status = NW_XHTML_ContentHandler_AppendPartialDocument( thisObj, response );
_NW_THROW_ON_ERROR( status );
status = NW_XHTML_ContentHandler_InitializeElementHandlers( thisObj );
_NW_THROW_ON_ERROR( status );
}
else
{
// this function musn't be called with the last partial response that has no body.
// Initialize must be called instead
NW_ASSERT( NW_TRUE );
}
// if this is the first chunk where the body is present, then set
// the formatting priority higher
if( !oldBodyIsPresent && thisObj->iBodyIsPresent )
{
// higher priority
priorirty = CActive::EPriorityStandard;
}
// let the shell know about the new partial document so that it can initiate
// update display message.
// if small screen layout is not disabled do not update.
// mobile profile pages do not format correctly when tables span
// chunks.
if( thisObj->iBodyIsPresent && !NW_Settings_GetDisableSmallScreenLayout() )
{
(void)docRoot->documentListener->DocumentChangedPartial( docRoot, priorirty );
}
}
NW_CATCH( status )
{
// special handling for the "need more data" case which means
// that the parser needs more chunks to process the buffer.
// it is not an error case so the status has to be
// modified to success
if ( status == KBrsrBufferTooSmall )
{
status = KBrsrSuccess;
}
}
NW_FINALLY
{
// body ownership is taken by the parser
// free the response
UrlLoader_UrlResponseDelete( response );
NW_LOG1( NW_LOG_LEVEL2, "_NW_XHTML_ContentHandler_PartialNextChunk ends: status: %d", status);
return status;
}
NW_END_TRY
}
// -----------------------------------------------------------------------------
NW_Uint8
_NW_XHTML_ContentHandler_ProcessEvent (NW_HED_DocumentNode_t* documentNode,
NW_LMgr_Box_t* box,
NW_Evt_Event_t* event,
void* context)
{
NW_XHTML_ContentHandler_t* thisObj;
const NW_XHTML_ElementHandler_t* elementHandler;
/* cast the 'object' for convenience */
thisObj = NW_XHTML_ContentHandlerOf (documentNode);
/* the context that was passed in is in reality a 'NW_DOM_Node_t*' - use that
to find the appropriate ElementHandler and invoke its processEvent
method */
elementHandler =
NW_XHTML_ContentHandler_GetElementHandler (NW_XHTML_ContentHandlerOf (documentNode),
(NW_DOM_ElementNode_t*) context);
NW_ASSERT (elementHandler != NULL);
return NW_XHTML_ElementHandler_ProcessEvent (elementHandler, thisObj,
(NW_DOM_ElementNode_t*) context,
box, event);
}
// -----------------------------------------------------------------------------
void
_NW_XHTML_ContentHandler_Suspend (NW_HED_DocumentNode_t* documentNode, NW_Bool aDestroyBoxTree)
{
NW_XHTML_ContentHandler_t* thisObj;
/* parameter assertion block */
NW_ASSERT (NW_Object_IsInstanceOf (documentNode,
&NW_XHTML_ContentHandler_Class));
/* for convenience */
thisObj = NW_XHTML_ContentHandlerOf (documentNode);
/* stop the META-Refresh timer if it is running */
NW_XHTML_ContentHandler_MetaRefreshDestroyTimer(thisObj);
if (thisObj->processor)
{
NW_CSS_Processor_Suspend(thisObj->processor);
}
//reset the script nodes as the boxes in the scriptNode contexts are deleted
if (thisObj->scriptNodes)
{
RPointerArray<NW_XHTML_Script_Node_Context_t>* scriptNodeList = STATIC_CAST(RPointerArray<NW_XHTML_Script_Node_Context_t>*,
thisObj->scriptNodes);
scriptNodeList->ResetAndDestroy();
}
//R->ecma
//NW_HED_DocumentRoot_t* documentRoot = (NW_HED_DocumentRoot_t*) NW_HED_DocumentNode_GetRootNode (thisObj);
//(void) NW_Ecma_InvalidateFormsElements(documentRoot);
/* invoke our superclass */
NW_HED_CompositeContentHandler_Class.NW_HED_DocumentNode.suspend(documentNode, aDestroyBoxTree);
}
//------------------------------------------------------------------------------
void
_NW_XHTML_CompositeContentHandler_Resume (NW_HED_DocumentNode_t* documentNode)
{
NW_XHTML_ContentHandler_t* thisObj;
/* parameter assertion block */
NW_ASSERT (NW_Object_IsInstanceOf (documentNode,
&NW_XHTML_ContentHandler_Class));
/* for convenience */
thisObj = NW_XHTML_ContentHandlerOf (documentNode);
/* invoke our superclass */
NW_HED_CompositeContentHandler_Class.NW_HED_DocumentNode.resume(documentNode);
thisObj->iScriptIsResumed = NW_TRUE;
}
// -----------------------------------------------------------------------------
void
_NW_XHTML_ContentHandler_AllLoadsCompleted (NW_HED_DocumentNode_t* documentNode)
{
NW_XHTML_ContentHandler_t* thisObj;
NW_Msg_Message_t* message = NULL;
NW_Text_t* fragment = NULL;
const NW_Text_t* url = NULL;
/* parameter assertion block */
NW_ASSERT (NW_Object_IsInstanceOf (documentNode,
&NW_XHTML_ContentHandler_Class));
/* call our super class to notify the children */
NW_HED_CompositeContentHandler_Class.NW_HED_DocumentNode.
allLoadsCompleted (documentNode);
/* for convenience */
thisObj = NW_XHTML_ContentHandlerOf (documentNode);
NW_TRY (status)
{
/* get the fragment */
url = NW_HED_UrlRequest_GetUrl (NW_HED_ContentHandler_GetUrlRequest
(thisObj));
status = NW_XHTML_ContentHandler_GetFragment (thisObj, url,
(const NW_Text_t**) & fragment);
/* show the frag */
if ((status == KBrsrSuccess) && (fragment != NULL))
{
/*
** we need to use a message to display the fragment because we need
** to wait until the box-tree is laid out -- which is also done via
** a message.
*/
/* create the message */
message = NW_Msg_Message_New (NW_XHTML_ContentHandler_Msg_ShowFragment,
fragment, NW_TRUE);
NW_THROW_OOM_ON_NULL (message, status);
fragment = NULL;
/* dispatch it */
status = NW_Msg_MessageDispatcher_DispatchMessage (&NW_Msg_MessageDispatcher, message, thisObj->iMessageListener);
NW_THROW_ON_ERROR (status);
message = NULL;
}
}
NW_CATCH (status)
{
NW_Object_Delete (fragment);
NW_Object_Delete (message);
}
NW_FINALLY {
} NW_END_TRY
}
// -----------------------------------------------------------------------------
void
_NW_XHTML_ContentHandler_LoseFocus (NW_HED_DocumentNode_t* documentNode)
{
NW_XHTML_ContentHandler_t* thisObj;
/* parameter assertion block */
NW_ASSERT (NW_Object_IsInstanceOf (documentNode,
&NW_XHTML_ContentHandler_Class));
/* for convenience */
thisObj = NW_XHTML_ContentHandlerOf (documentNode);
/* suspend the META-Refresh timer if it is running */
NW_XHTML_ContentHandler_MetaRefreshSuspendTimer(thisObj);
/* invoke our superclass */
NW_HED_CompositeContentHandler_Class.NW_HED_DocumentNode.loseFocus(documentNode);
}
// -----------------------------------------------------------------------------
void
_NW_XHTML_ContentHandler_GainFocus (NW_HED_DocumentNode_t* documentNode)
{
NW_XHTML_ContentHandler_t* thisObj;
/* parameter assertion block */
NW_ASSERT (NW_Object_IsInstanceOf (documentNode,
&NW_XHTML_ContentHandler_Class));
/* for convenience */
thisObj = NW_XHTML_ContentHandlerOf (documentNode);
/* invoke our superclass */
NW_HED_CompositeContentHandler_Class.NW_HED_DocumentNode.gainFocus(documentNode);
/* resume the META-Refresh timer if it was running */
NW_XHTML_ContentHandler_MetaRefreshResumeTimer(thisObj);
}
// -----------------------------------------------------------------------------
// after loading last chunk of embedded content the function is called
// by documentroot.
// If the transactionId exits in scriptIds list , it is removed from the pendginglist
void
_NW_XHTML_DocumentNode_HandleLoadComplete(NW_HED_DocumentNode_t* documentNode,
const NW_HED_UrlRequest_t *urlRequest,
NW_Int16 errorClass,
TBrowserStatusCode error,
NW_Uint16 /*aTransactionId*/,
void* context )
{
//check if the transaction is a script load request and decrement the counter
NW_REQUIRED_PARAM(urlRequest);
NW_REQUIRED_PARAM(errorClass);
NW_REQUIRED_PARAM(error);
NW_REQUIRED_PARAM(context);
NW_REQUIRED_PARAM(documentNode);
/* parameter assertion block */
NW_ASSERT (NW_Object_IsInstanceOf (documentNode,
&NW_XHTML_ContentHandler_Class));
/* for convenience */
NW_LOG0( NW_LOG_LEVEL2, "NW_XHTML_DocumentNode_HandleLoadComplete Start" );
NW_LOG0( NW_LOG_LEVEL2, "NW_XHTML_DocumentNode_HandleLoadComplete End" );
}
// -----------------------------------------------------------------------------
const NW_Text_t*
_NW_XHTML_ContentHandler_GetTitle (NW_HED_ContentHandler_t* contentHandler)
{
NW_XHTML_ContentHandler_t* thisObj;
/* for convenience */
thisObj = NW_XHTML_ContentHandlerOf (contentHandler);
/* return the title */
return thisObj->title;
}
// -----------------------------------------------------------------------------
TBrowserStatusCode
_NW_XHTML_ContentHandler_ResolveURL (NW_HED_ContentHandler_t* thisObj,
NW_Text_t* url, NW_Text_t** retUrl)
{
NW_Uint8 freeLoadUrl = NW_FALSE;
NW_String_t baseUrl;
NW_String_t href;
NW_String_t contentLoc;
NW_Ucs2* compositeBase = NULL;
NW_DOM_Node_t* baseElement;
NW_Ucs2 *contentLocation = NULL;
void* docUrl = NULL;
const NW_Ucs2* loadUrl = NULL;
NW_Text_UCS2_t* absUrlText = NULL;
NW_Ucs2* absUrl = NULL;
NW_Bool isRelative;
baseUrl.length = 0;
baseUrl.storage = NULL;
href.length = 0;
href.storage = NULL;
contentLoc.length = 0;
contentLoc.storage = NULL;
NW_TRY(status)
{
/* get the url as a ucs2 char string */
loadUrl = NW_Text_GetUCS2Buffer (url, NW_Text_Flags_Aligned, NULL, &freeLoadUrl);
NW_THROW_OOM_ON_NULL((void*)loadUrl, status);
if(!NW_Text_GetCharCount(url))
{
isRelative = NW_TRUE;
}
else
{
/* if the supplied URL is absolute we simply return that */
status = NW_Url_IsRelative (loadUrl, &isRelative);
_NW_THROW_ON_ERROR (status);
}
if ( isRelative == NW_FALSE)
{
if (freeLoadUrl)
{
NW_Mem_Free ((NW_Ucs2*) loadUrl);
}
/*make a deep copy of the text */
*retUrl = NW_Text_Copy(url, NW_TRUE);
NW_THROW_OOM_ON_NULL(*retUrl, status);
NW_Object_Delete (url);
return KBrsrSuccess;
}
/* Get the the document's url. The result is not owned by us. */
docUrl =
NW_HED_UrlResponse_GetUrl( NW_HED_ContentHandler_GetUrlResponse( thisObj ) )->storage;
NW_THROW_OOM_ON_NULL(docUrl, status);
/*
* If the URL was the result of a file operation, then we want the
* response URL rather than
* the request URL. This is to support save-to-file operations. If it wasn't the result of
* a file operation, then the response URL should be the same as the request.
*/
if (NW_Str_Strncmp((const NW_Ucs2*)docUrl, (const NW_Ucs2*)NW_STR("file://"), 7) == 0)
{
docUrl = NW_HED_UrlResponse_GetUrl
(NW_HED_ContentHandler_GetUrlResponse (thisObj))->storage;
NW_THROW_OOM_ON_NULL(docUrl, status);
}
/* get the base url as found in the "base" element */
baseElement = NW_XHTML_ContentHandler_GetBaseElement(thisObj);
/*get the content location id present*/
contentLocation = NW_XHTML_ContentHandler_GetContentLocation(thisObj);
if(contentLocation != NULL && baseElement == NULL)
{
status = StatusCodeConvert(NW_String_ucs2CharToString (&contentLoc, contentLocation, HTTP_iso_10646_ucs_2));
NW_THROW_ON_ERROR (status);
status = NW_Url_IsRelative (contentLocation, &isRelative);
NW_THROW_ON_ERROR (status);
if (isRelative == NW_TRUE)
{
status = NW_Url_RelToAbs ((const NW_Ucs2*)docUrl, (const NW_Ucs2 *) contentLoc.storage,
&compositeBase);
NW_THROW_ON_ERROR (status);
status = NW_HED_DomHelper_CatUcs2String (&baseUrl, compositeBase);
NW_THROW_ON_ERROR (status);
NW_Mem_Free (compositeBase);
compositeBase = NULL;
}
/* otherwise use the base */
else
{
status = NW_HED_DomHelper_CatString (&baseUrl, &contentLoc, HTTP_iso_10646_ucs_2);
NW_THROW_ON_ERROR (status);
}
}
if (baseElement != NULL)
{
status =
NW_HED_DomHelper_GetHTMLAttributeValue
(&((NW_XHTML_ContentHandler_t *) thisObj)->domHelper, baseElement,
NW_XHTML_AttributeToken_href, &href);
if (status == KBrsrSuccess)
{
/*
* if the base element is a relative url the base-url is formed by cat'ing the
* document's url with the base.
*/
status = NW_Url_IsRelative ((const NW_Ucs2*) href.storage, &isRelative);
NW_THROW_ON_ERROR (status);
if (isRelative == NW_TRUE)
{
status = NW_Url_RelToAbs ((const NW_Ucs2*)docUrl, (const NW_Ucs2 *) href.storage,
&compositeBase);
NW_THROW_ON_ERROR (status);
status = NW_HED_DomHelper_CatUcs2String (&baseUrl, compositeBase);
NW_THROW_ON_ERROR (status);
NW_Mem_Free (compositeBase);
compositeBase = NULL;
}
/* otherwise use the base */
else
{
status = NW_HED_DomHelper_CatString (&baseUrl, &href, HTTP_iso_10646_ucs_2);
NW_THROW_ON_ERROR (status);
}
NW_String_deleteStorage (&href);
}
}
/*
* if the base-url is still null just use the document's url as the
* base-url */
if (baseUrl.storage == NULL)
{
status = NW_HED_DomHelper_CatUcs2String (&baseUrl, (const NW_Ucs2*)docUrl);
NW_THROW_ON_ERROR (status);
}
if(!NW_Str_Strlen(loadUrl))
{
absUrl = NW_Str_Newcpy((const NW_Ucs2*) baseUrl.storage);
NW_THROW_OOM_ON_NULL(absUrl, status);
}
else
{
/* construct the absolute URL */
status = NW_Url_RelToAbs ((const NW_Ucs2*) baseUrl.storage, loadUrl, &absUrl);
NW_THROW_ON_ERROR (status);
}
absUrlText = NW_Text_UCS2_New (absUrl, 0, NW_Text_Flags_TakeOwnership);
NW_THROW_OOM_ON_NULL(absUrlText, status);
absUrl = NULL;
/* fall through */
}
NW_CATCH (status)
{ /* empty */
}
NW_FINALLY {
if (freeLoadUrl == NW_TRUE)
{
NW_Mem_Free ((NW_Ucs2*) loadUrl);
}
NW_String_deleteStorage (&baseUrl);
NW_String_deleteStorage (&href);
NW_String_deleteStorage (&contentLoc);
NW_Mem_Free (absUrl);
NW_Mem_Free (compositeBase);
if (status == KBrsrSuccess)
{
NW_Object_Delete (url);
}
*retUrl = (NW_Text_t*) absUrlText;
return status;
}
NW_END_TRY
}
// -----------------------------------------------------------------------------
TBrowserStatusCode
_NW_XHTML_ContentHandler_CreateBoxTree (NW_HED_ContentHandler_t* contentHandler,
NW_LMgr_Box_t** boxTree)
{
NW_XHTML_ContentHandler_t* thisObj;
NW_DOM_Node_t* domNode;
const NW_XHTML_ElementHandler_t* elementHandler;
NW_LMgr_BidiFlowBox_t* bidiFlowBox = NULL;
NW_LMgr_Property_t prop;
/* parameter assertion block */
NW_ASSERT (NW_Object_IsInstanceOf (contentHandler,
&NW_XHTML_ContentHandler_Class));
/* for convenience */
thisObj = NW_XHTML_ContentHandlerOf (contentHandler);
thisObj->ignoreFramesetElement = NW_FALSE;
thisObj->ignoreBodyElement = NW_FALSE;
NW_TRY (status)
{
#ifdef _DEBUG1
NW_HED_DomHelper_PrintTree(&thisObj->domHelper, NW_HED_DomTree_GetRootNode(thisObj->domTree));
#endif
// if the box tree is Not null then update the box tree with the new content
if (*boxTree)
{
status = NW_XHTML_ContentHandler_CreatePartialBoxTree(thisObj, boxTree);
// Set the prevInitializedDom. This denotes the last node for which the
// box tree was created and will be used as a starting point when the
// next chunk comes
_NW_THROW_ON_ERROR(status);
}
else
{
/* create a BidiFlowBox in which to build the box tree */
bidiFlowBox = NW_LMgr_BidiFlowBox_New (1);
NW_THROW_OOM_ON_NULL (bidiFlowBox, status);
/* Set the display property on the container */
prop.type = NW_CSS_ValueType_Token;
prop.value.token = NW_CSS_PropValue_display_block;
NW_LMgr_Box_SetProperty (NW_LMgr_BoxOf (bidiFlowBox),
NW_CSS_Prop_display, &prop);
/* The root node is the so-called document node and is basically
a holder for some general document info such as encoding. */
domNode = NW_HED_DomTree_GetRootNode (thisObj->domTree);
NW_THROW_ON_NULL (domNode, status, KBrsrUnexpectedError);
/* The actual content of the document starts with the root's children. */
for (domNode = NW_DOM_Node_getFirstChild (domNode);
domNode != NULL ;
domNode = NW_DOM_Node_getNextSibling (domNode))
{
thisObj->prevInitializedDomNode = domNode;
elementHandler = NW_XHTML_ContentHandler_GetElementHandler (thisObj,
(NW_DOM_ElementNode_t*) domNode);
NW_ASSERT(elementHandler != NULL);
if (elementHandler != NULL)
{
status = NW_XHTML_ElementHandler_CreateBoxTree (elementHandler,
thisObj,
domNode,
NW_LMgr_ContainerBoxOf(bidiFlowBox));
_NW_THROW_ON_ERROR(status);
}
}
/* next is a little optimization to eliminate excess top-level nesting */
if (NW_LMgr_ContainerBox_GetChildCount(NW_LMgr_ContainerBoxOf(bidiFlowBox))
== 1)
{
NW_LMgr_BidiFlowBox_t* tempFlowBox =
((NW_LMgr_BidiFlowBox_t*)
NW_LMgr_ContainerBox_GetChild(NW_LMgr_ContainerBoxOf(bidiFlowBox), 0));
if (NW_Object_IsClass(tempFlowBox, &NW_LMgr_BidiFlowBox_Class))
{
NW_LMgr_Box_Detach(NW_LMgr_BoxOf(tempFlowBox));
NW_Object_Delete(bidiFlowBox);
bidiFlowBox = tempFlowBox;
}
}
} // else
}
NW_CATCH (status)
{
if (bidiFlowBox)
{
NW_Object_Delete(bidiFlowBox);
bidiFlowBox = NULL;
}
if (status != KBrsrOutOfMemory)
{
// ZAL: changed temporarily to distinguish create box
// tree error from parser errors.
status = KBrsrSavedPageFailed;
}
NW_HED_DocumentNode_HandleError( contentHandler,
NW_HED_ContentHandler_GetUrlRequest(contentHandler),
BRSR_STAT_CLASS_GENERAL, status);
}
NW_FINALLY
{
#ifdef _DEBUG1
NW_HED_DomHelper_PrintTree(&thisObj->domHelper, NW_HED_DomTree_GetRootNode(thisObj->domTree));
#endif
if (bidiFlowBox)
{
*boxTree = NW_LMgr_BoxOf(bidiFlowBox);
}
// if the boxtree creation is exited , then thisObj->prevInitializedDomNode is
// set by the function call NW_XHTML_ContentHandler_BreakBoxTreeCreation(...)
thisObj->prevInitializedDomNode = thisObj->lastInitializedDomNode;
return status;
}
NW_END_TRY
}
// -----------------------------------------------------------------------------
TBrowserStatusCode
_NW_XHTML_ContentHandler_HandleRequest (NW_HED_ContentHandler_t* thisObj,
NW_HED_UrlRequest_t* urlRequest)
{
TBrowserStatusCode status;
NW_ASSERT (NW_HED_UrlRequestOf (urlRequest));
/* don't handle reload requests here */
if (NW_HED_UrlRequest_GetReason (urlRequest) == NW_HED_UrlRequest_Reason_ShellReload)
{
return KBrsrFailure;
}
/* don't handle post requests here */
if (NW_HED_UrlRequest_GetMethod (urlRequest) == NW_URL_METHOD_POST)
{
return KBrsrFailure;
}
/* jump to the fragment if one is provided */
status = NW_XHTML_ContentHandler_LoadFragment (NW_XHTML_ContentHandlerOf (
thisObj), urlRequest);
return status;
}
// -----------------------------------------------------------------------------
TBrowserStatusCode
_NW_XHTML_ContentHandler_DocumentDisplayed (NW_HED_ContentHandler_t* contentHandler)
{
NW_XHTML_ContentHandler_t* thisObj;
/* for convenience */
thisObj = NW_XHTML_ContentHandlerOf (contentHandler);
NW_TRY (status)
{
if (thisObj->metaRefreshSet)
{
// Clear RefreshSet to only allow refresh once, in case URL is
// invalid or some other type of error occurs.
thisObj->metaRefreshSet = FALSE;
if (thisObj->metaRefreshSeconds <= 0)
{
status = NW_XHTML_ContentHandler_MetaRefreshStartLoad(thisObj);
_NW_THROW_ON_ERROR(status);
}
else
{
/* start a timer for the refresh delay */
status = NW_XHTML_ContentHandler_MetaRefreshCreateTimer(thisObj);
_NW_THROW_ON_ERROR(status);
}
}
const NW_Ucs2* rawUrl = NW_HED_UrlRequest_GetRawUrl (NW_HED_ContentHandler_GetUrlRequest(NW_HED_ContentHandlerOf(contentHandler)));
if(thisObj->metaNoCache)
{
//R->ul UrlLoader_ClearItemInCache( rawUrl );
}
if(thisObj->metaCacheExpires == NW_TRUE)
{
//R->ul UrlLoader_SetHeaderInCache(rawUrl, (unsigned char*) expires, thisObj->metaExpiresDate);
}
NW_HED_DocumentRoot_t* docRoot = (NW_HED_DocumentRoot_t*) NW_HED_DocumentNode_GetRootNode (thisObj);
// check the content type of the response
if ( thisObj->switchBackToNormalLayout )
{
// switch back to normal
// but first make sure we have to switch at all as imagine the following case
// 1. original status is normal
// 2. first chunk cames in, we switch to ss mode ( content type is text/html )
// 3. pi element handler disables ss mode ( mobile profile )
// 4. formatting is carried on in normal mode
// 5. execution comes here and we trying to switch to normal mode
// 6. MHEDDocumentListener::SwitchLayout replaces boxes ( tables )
// so all the static table box will be transformed to vertical box eventhough
// we are in normal mode
// so change only if we are really really in ss mode.
NW_Bool smallScreenMode = NW_Settings_GetVerticalLayoutEnabled();
NW_Settings_SetInternalVerticalLayoutEnabled( NW_FALSE );
if ( smallScreenMode )
{
(void) docRoot->documentListener->SwitchLayout (NW_FALSE, NW_TRUE /*reformatBoxTree*/);
NW_CSS_Processor_t* processor = NW_XHTML_ContentHandler_GetCSSProcessor( thisObj );
if ( processor != NULL )
{
NW_CSS_Processor_ProcessPendingLoads( processor );
}
}
thisObj->switchBackToNormalLayout = NW_FALSE;
}
}
NW_CATCH (status)
{}
NW_FINALLY
{
return status;
}
NW_END_TRY
}
/* ------------------------------------------------------------------------- *
final methods
* ------------------------------------------------------------------------- */
// -----------------------------------------------------------------------------
const NW_XHTML_ElementHandler_t*
NW_XHTML_ContentHandler_GetElementHandler (NW_XHTML_ContentHandler_t* contentHandler,
NW_DOM_ElementNode_t* domElement)
{
int i;
int numModules;
// NW_LOG1(NW_LOG_LEVEL2, "contetnHandler: %x", contentHandler );
/* text nodes handled at content handler level */
if (NW_DOM_Node_getNodeType (domElement) == NW_DOM_TEXT_NODE)
{
// NW_LOG1(NW_LOG_LEVEL2, "NW_XHTML_TextElementHandler: %x", &NW_XHTML_TextElementHandler );
return NW_XHTML_ElementHandlerOf (&NW_XHTML_TextElementHandler);
}
/* PI nodes handled at content handler level */
if (NW_DOM_Node_getNodeType (domElement)
== NW_DOM_PROCESSING_INSTRUCTION_NODE)
{
// NW_LOG1(NW_LOG_LEVEL2, "NW_XHTML_PiElementHandler: %x", &NW_XHTML_PiElementHandler );
return NW_XHTML_ElementHandlerOf (&NW_XHTML_PiElementHandler);
}
/* iterate through the module table */
NW_Uint16 tagToken = NW_HED_DomHelper_GetElementToken (domElement);
numModules = NW_XHTML_ContentHandler_GetClassPart (contentHandler).numModules;
for (i = 0; i < numModules; i++)
{
NW_XHTML_ElementHandler_t* elementHandler;
/* query the module for an appropriate ElementHandler */
const NW_Markup_Module_t* module =
NW_XHTML_ContentHandler_GetClassPart (contentHandler).modules[i];
elementHandler = (NW_XHTML_ElementHandler_t*)
NW_Markup_WBXMLModule_GetHandler (module, tagToken);
/* we found one, return it */
if (elementHandler != NULL)
{
// NW_LOG1(NW_LOG_LEVEL2, "ElementHandler: %x", elementHandler );
return elementHandler;
}
}
/* no ElementHandler was found, so we return the generic
ElementHandler - this will at least allow us to traverse the
children of this unknown node */
// NW_LOG1(NW_LOG_LEVEL2, "NW_XHTML_ElementHandler: %x", &NW_XHTML_ElementHandler );
return &NW_XHTML_ElementHandler;
}
// -----------------------------------------------------------------------------
TBrowserStatusCode
NW_XHTML_GetDOMAttribute (NW_XHTML_ContentHandler_t* thisObj,
NW_DOM_ElementNode_t* elementNode,
const NW_Uint16 token, NW_Text_t** text_t)
{
TBrowserStatusCode status;
NW_String_t value;
NW_Text_t *attributeValue = NULL;
/* get the attribute */
status = NW_HED_DomHelper_GetHTMLAttributeValue
(&thisObj->domHelper, elementNode, token, &value);
/* convert it to a NW_Text */
if (status == KBrsrSuccess)
{
attributeValue = NW_Text_New (HTTP_iso_10646_ucs_2, (void*) NW_String_getStorage (&value),
NW_String_getCharCount (&value, HTTP_iso_10646_ucs_2),
(NW_Uint8) (NW_String_getUserOwnsStorage (&value) ? NW_Text_Flags_TakeOwnership : 0));
}
*text_t = attributeValue;
/* return the result */
return status;
}
// -----------------------------------------------------------------------------
NW_Text_t*
NW_XHTML_GetDOMTextNodeData(NW_XHTML_ContentHandler_t* thisObj,
NW_DOM_TextNode_t* textNode)
{
TBrowserStatusCode status;
NW_String_t value;
NW_Text_t *text = NULL;
NW_Uint32 encoding;
NW_REQUIRED_PARAM (thisObj);
NW_ASSERT(textNode != NULL);
/* extract the text from the element */
status = NW_HED_DomHelper_GetText (&thisObj->domHelper, textNode,
NW_TRUE, &value, &encoding);
/* convert it to a NW_Text */
if (status == KBrsrSuccess)
{
NW_Uint8 flag = 0;
if (NW_String_getUserOwnsStorage (&value) == NW_TRUE)
{
flag = NW_Text_Flags_TakeOwnership;
}
text = NW_Text_New (encoding, value.storage, NW_String_getCharCount (&value,
encoding), flag);
}
return text;
}
// -----------------------------------------------------------------------------
TBrowserStatusCode
NW_XHTML_ContentHandler_StartRequest(NW_XHTML_ContentHandler_t* thisObj,
NW_HED_UrlRequest_t* urlRequest,
void* clientData )
{
return NW_XHTML_ContentHandler_StartRequest_tId(thisObj, urlRequest, clientData , NULL);
}
// -----------------------------------------------------------------------------
TBrowserStatusCode
NW_XHTML_ContentHandler_StartRequest_tId(NW_XHTML_ContentHandler_t* thisObj,
NW_HED_UrlRequest_t* urlRequest,
void* clientData , NW_Uint16* aTransationId)
{
TBrowserStatusCode status;
const NW_Ucs2* origUrl = NULL;
NW_Ucs2* escapedUrl = NULL;
NW_Text_t* resolvedUrl = NULL;
NW_Text_t* retUrl = NULL;
NW_HED_DocumentRoot_t* docRoot;
NW_HED_DocumentNode_t* owner = NULL;
NW_Url_Schema_t schema = NW_SCHEMA_INVALID;
NW_Ucs2* resolvedUrlUcs2 = NULL;
CBodyPart* bodyPart = NULL;
TBool isUrlInMultipart = EFalse;
NW_ASSERT (thisObj != NULL);
NW_ASSERT (urlRequest != NULL);
/* get the orig url as a ucs2 string */
status = KBrsrOutOfMemory;
NW_THROWIF_NULL (origUrl = NW_HED_UrlRequest_GetRawUrl (urlRequest));
/* ensure that the url is escaped correctly */
status = KBrsrOutOfMemory;
NW_THROWIF_NULL (escapedUrl = NW_Str_New(NW_Url_EscapeUnwiseLen(origUrl)));
NW_Url_EscapeUnwise(origUrl, escapedUrl);
NW_Url_GetSchemeNoValidation(escapedUrl, &schema);
/* resolve the url */
status = KBrsrOutOfMemory;
resolvedUrl = NW_Text_New (HTTP_iso_10646_ucs_2, escapedUrl, 0, NW_Text_Flags_TakeOwnership);
NW_THROWIF_NULL (resolvedUrl);
escapedUrl = NULL;
if (schema != NW_SCHEMA_WTAI) {
status = NW_HED_ContentHandler_ResolveURL (thisObj, resolvedUrl, &retUrl );
_NW_THROW_ON_ERROR(status);
/* give ownership back to resolvedUrl */
resolvedUrl = retUrl;
retUrl = NULL;
}
/* update the UrlRequest with the resolved url */
NW_THROWIF_ERROR (status = NW_HED_UrlRequest_UpdateUrl (urlRequest, resolvedUrl));
/* issue the request */
docRoot = (NW_HED_DocumentRoot_t*) NW_HED_DocumentNode_GetRootNode (thisObj);
// load owner is the docroot unless this is a non top level request
owner = NW_HED_DocumentNodeOf( docRoot );
if ( NW_HED_UrlRequest_IsTopLevelRequest( urlRequest ) != NW_TRUE )
{
owner = NW_HED_DocumentNodeOf( thisObj );
}
// compare url with body part
NW_Uint8 freeNeeded;
resolvedUrlUcs2 = NW_Text_GetUCS2Buffer( resolvedUrl, NULL, NULL, &freeNeeded);
isUrlInMultipart = _NW_HED_CompositeContentHandler_IsUrlInMultipart(
NW_HED_CompositeContentHandlerOf(thisObj),
resolvedUrlUcs2, &bodyPart );
if( freeNeeded )
{
NW_Mem_Free( resolvedUrlUcs2 );
}
if( isUrlInMultipart )
{
TDataType dataType( bodyPart->ContentType() );
TUint8* charset = (TUint8*) bodyPart->Charset().Ptr();
TInt lenCh = bodyPart->Charset().Length();
CShell* shell = REINTERPRET_CAST(CShell*, NW_Ctx_Get(NW_CTX_BROWSER_APP, 0));
NW_ASSERT(shell);
TInt32 uidInt = shell->GetUidFromCharset( charset, lenCh );
TUid uid = TUid::Uid( uidInt );
//R
/*
CBrCtl* brCtl = shell->BrCtl();
brCtl->LoadDataL( bodyPart->Url(), bodyPart->Body(), dataType, uid,
owner, clientData, NULL, aTransationId,
urlRequest->loadType, urlRequest->method );*/
}
else
{
// Check if SendReferrerHeader is enabled
if ( NW_Settings_GetSendReferrerHeader() && docRoot->referrerUrl != NULL)
{ // Set Referrer Header
NW_Text_Length_t urlLength;
NW_Uint8 urlFreeNeeded = NW_FALSE;
// convert the url to Unicode and get the storage
NW_Ucs2* referrerUrl = (NW_Ucs2*) NW_Text_GetUCS2Buffer (docRoot->referrerUrl,
NW_Text_Flags_NullTerminated | NW_Text_Flags_Aligned,
&urlLength, &urlFreeNeeded);
SetReferrerHeader(urlRequest, referrerUrl);
if (urlFreeNeeded)
{
NW_Mem_Free(referrerUrl);
}
}
status = NW_HED_DocumentRoot_StartRequest_tId (docRoot, owner, urlRequest, clientData , aTransationId);
}
NW_Object_Delete (resolvedUrl);
resolvedUrl = NULL;
return status;
_NW_CATCH:
NW_CATCH_ERROR
NW_Str_Delete (escapedUrl);
NW_Object_Delete (resolvedUrl);
return status;
}
// -----------------------------------------------------------------------------
TBrowserStatusCode
NW_XHTML_ContentHandler_StartLoad(NW_XHTML_ContentHandler_t* thisObj,
const NW_Text_t* url,
NW_Uint8 reason,
void* clientData,
NW_Uint8 loadType)
{
return NW_XHTML_ContentHandler_StartLoad_tId (thisObj, url, reason,
clientData, loadType, NULL);
}
// -----------------------------------------------------------------------------
TBrowserStatusCode
NW_XHTML_ContentHandler_StartLoad_tId (NW_XHTML_ContentHandler_t* thisObj,
const NW_Text_t* url,
NW_Uint8 reason,
void* clientData,
NW_Uint8 loadType, NW_Uint16* aTransationId)
{
NW_HED_UrlRequest_t* request;
NW_ASSERT (thisObj != NULL);
NW_ASSERT (url != NULL);
NW_TRY (status)
{
/* make a UrlRequest */
if (NW_HED_UrlRequest_Reason_DocLoadHead != reason)
{
request = NW_HED_UrlRequest_New (NW_TextOf (url), NW_URL_METHOD_GET, NULL,
NULL, reason, NW_HED_UrlRequest_LoadNormal, loadType);
}
else
{
request = NW_HED_UrlRequest_New(NW_TextOf (url), NW_URL_METHOD_HEAD, NULL,
NULL, reason, NW_HED_UrlRequest_LoadNormal, loadType);
}
NW_THROW_OOM_ON_NULL (request, status);
if (NW_XHTML_ContentHandler_IsSaveddeck(thisObj) &&
NW_HED_UrlRequest_Reason_DocLoadChild == reason &&
// Allow to load a plugin from a saved page, because the user explicitly requested it
loadType != NW_UrlRequest_Type_Plugin)
{
NW_HED_UrlRequest_SetCacheMode(request, NW_CACHE_ONLYCACHE);
}
if(NW_XHTML_ContentHandler_IsHistoryLoad(thisObj) &&
NW_HED_UrlRequest_Reason_DocLoadChild == reason)
{
NW_HED_UrlRequest_SetCacheMode(request, NW_CACHE_HISTPREV);
}
if(NW_XHTML_ContentHandler_IsReLoad(thisObj) &&
NW_HED_UrlRequest_Reason_DocLoadChild == reason)
{
NW_HED_UrlRequest_SetCacheMode(request, NW_CACHE_NOCACHE);
}
/* pass it to StartRequest to be satisfied */
status = NW_XHTML_ContentHandler_StartRequest_tId (thisObj, request, clientData , aTransationId);
_NW_THROW_ON_ERROR (status);
}
NW_CATCH (status)
{
if (request)
{
NW_Object_Delete(request);
}
}
NW_FINALLY {
return status;
} NW_END_TRY
}
// -----------------------------------------------------------------------------
TBrowserStatusCode
NW_XHTML_ContentHandler_SetLoadObserver(NW_XHTML_ContentHandler_t* thisObj,
NW_Uint16 aTransationId,
MHEDLoadObserver* aLoadObserver)
{
NW_HED_DocumentRoot_t* docRoot = (NW_HED_DocumentRoot_t*)
NW_HED_DocumentNode_GetRootNode (thisObj);
return NW_HED_DocumentRoot_SetLoadObserver(docRoot, aTransationId, aLoadObserver);
}
// -----------------------------------------------------------------------------
NW_CSS_Processor_t*
NW_XHTML_ContentHandler_CreateCSSProcessor(NW_XHTML_ContentHandler_t* thisObj)
{
if (thisObj->processor == NULL)
{
thisObj->processor = NW_CSS_Processor_New();
if (thisObj->processor != NULL)
{
NW_CSS_Processor_SetOwner(thisObj->processor, NW_HED_DocumentNodeOf(thisObj));
NW_CSS_Processor_SetDictionary(thisObj->processor,
(NW_WBXML_Dictionary_t *) & NW_XHTML_WBXMLDictionary);
NW_CSS_Processor_SetApplyCSSCallback(thisObj->processor,
NW_XHTML_ElementHandler_ApplyCSSCallback);
thisObj->processor->isSavedDeck = NW_XHTML_ContentHandler_IsSaveddeck(thisObj);
thisObj->processor->isHistLoad = NW_XHTML_ContentHandler_IsHistoryLoad(thisObj);
thisObj->processor->isReLoad = NW_XHTML_ContentHandler_IsReLoad(thisObj);
}
}
return thisObj->processor;
}
// -----------------------------------------------------------------------------
NW_WBXML_Dictionary_t*
NW_XHTML_ContentHandler_GetDictionary(NW_XHTML_ContentHandler_t* contentHandler)
{
NW_REQUIRED_PARAM(contentHandler);
return (NW_WBXML_Dictionary_t *) & NW_XHTML_WBXMLDictionary;
}
// -----------------------------------------------------------------------------
TBrowserStatusCode
NW_XHTML_ContentHandler_AddFormLiaison(
NW_XHTML_ContentHandler_t* contentHandler,
NW_DOM_ElementNode_t* formNode)
{
TBrowserStatusCode status = KBrsrSuccess;
NW_XHTML_FormLiaison_t* formLiaison;
NW_XHTML_ContentHandler_t* thisObj = NW_XHTML_ContentHandlerOf (contentHandler);
/* make sure we have a control set */
if (contentHandler->controlSet == NULL)
{
/* no control set; make sure we have a value set */
if (contentHandler->controlValueSet == NULL)
{
/* no value set; make an empty one */
contentHandler->controlValueSet =
(NW_ADT_DynamicVector_t*) NW_ADT_ResizableObjectVector_New(0, 5);
if (contentHandler->controlValueSet == NULL)
{
return KBrsrOutOfMemory;
}
}
contentHandler->controlSet =
NW_XHTML_ControlSet_New(contentHandler->controlValueSet);
if (contentHandler->controlSet == NULL)
{
return KBrsrOutOfMemory;
}
contentHandler->controlValueSet = NULL; /* controlSet now has ownership */
}
formLiaison = NW_XHTML_FormLiaison_New(formNode,
contentHandler,
contentHandler->controlSet);
if (formLiaison == NULL)
{
return KBrsrOutOfMemory;
}
NW_XHTML_Form_Node_Context_t* formContext = new NW_XHTML_Form_Node_Context_t;
//lint -e{774} Boolean within 'if' always evaluates to False
if (formContext != NULL)
{
formContext->formNode = formNode;
formContext->formLiaison = (NW_FBox_FormLiaison_t*)formLiaison;
// append formContext to nodeContext vector
if (NW_ADT_DynamicVector_InsertAt
(thisObj->nodeContexts, &formContext, NW_ADT_Vector_AtEnd ) == NULL)
{
status = KBrsrOutOfMemory;
}
}
else
{
status = KBrsrOutOfMemory;
}
if (status != KBrsrSuccess)
{
NW_Object_Delete(formLiaison);
}
return status;
}
// -----------------------------------------------------------------------------
NW_FBox_FormLiaison_t*
NW_XHTML_ContentHandler_GetFormLiaison(NW_XHTML_ContentHandler_t* contentHandler,
NW_DOM_ElementNode_t* elementNode)
{
NW_XHTML_FormLiaison_t* formLiaison = NULL;
NW_DOM_ElementNode_t* node = NULL;
NW_XHTML_ContentHandler_t* thisObj = NW_XHTML_ContentHandlerOf (contentHandler);
if (elementNode != NULL)
{
node = NW_XHTML_ContentHandler_GetFormNode(contentHandler,elementNode);
if (node != NULL)
{
//if we found the form, get the associated form liaison */
NW_ADT_Vector_Metric_t nodeCtxSize = NW_ADT_Vector_GetSize(thisObj->nodeContexts);
for (NW_ADT_Vector_Metric_t i = 0 ; i < nodeCtxSize; i++)
{
NW_XHTML_Form_Node_Context_t* formCtx =
*(NW_XHTML_Form_Node_Context_t**)NW_ADT_Vector_ElementAt (thisObj->nodeContexts, i);
if (formCtx->formNode == node )
{
formLiaison = (NW_XHTML_FormLiaison_t*)formCtx->formLiaison;
break;
}
}
}
}
return NW_FBox_FormLiaisonOf(formLiaison);
}
/* ------------------------------------------------------------------------- *
NW_Markup_NumberCollector methods
* ------------------------------------------------------------------------- */
// -----------------------------------------------------------------------------
NW_LMgr_Box_t*
_NW_XHTML_ContentHandler_NumberCollector_GetBoxTree (NW_Markup_NumberCollector_t*
numberCollector)
{
NW_XHTML_ContentHandler_t* thisObj;
NW_LMgr_Box_t* boxTree;
/* parameter assertion block */
NW_ASSERT (NW_Object_IsInstanceOf (numberCollector,
&NW_XHTML_ContentHandler_NumberCollector_Class));
/* for convenience */
thisObj = static_cast<NW_XHTML_ContentHandler_t*>
(NW_Object_Aggregate_GetAggregator (numberCollector));
NW_ASSERT (NW_Object_IsInstanceOf (thisObj, &NW_XHTML_ContentHandler_Class));
/* return the box tree */
(void) NW_HED_DocumentNode_GetBoxTree (thisObj, &boxTree);
return boxTree;
}
/* ------------------------------------------------------------------------- *
NW_Markup_NumberCollector methods
* ------------------------------------------------------------------------- */
// -----------------------------------------------------------------------------
NW_Text_t*
_NW_XHTML_ContentHandler_NumberCollector_GetHrefAttr (NW_Markup_NumberCollector_t*
numberCollector,
NW_LMgr_Box_t* box)
{
NW_XHTML_ContentHandler_t* thisObj;
NW_HED_EventHandler_t* eventHandler = NULL;
NW_DOM_ElementNode_t* elementNode;
NW_Text_t* text = NULL;
NW_Text_t* retUrl = NULL;
/* parameter assertion block */
NW_ASSERT (NW_Object_IsInstanceOf (numberCollector,
&NW_XHTML_ContentHandler_NumberCollector_Class));
NW_ASSERT(NW_Object_IsInstanceOf(box, &NW_LMgr_ActiveContainerBox_Class));
/* for convenience */
thisObj = static_cast<NW_XHTML_ContentHandler_t*>
(NW_Object_Aggregate_GetAggregator (numberCollector));
NW_ASSERT (NW_Object_IsInstanceOf (thisObj, &NW_XHTML_ContentHandler_Class));
eventHandler = (NW_HED_EventHandler_t *)((NW_LMgr_ActiveContainerBoxOf(box))->eventHandler);
elementNode = (NW_DOM_ElementNode_t *)(eventHandler->context);
if(NW_LMgr_ActiveContainerBoxOf(box)->hrefAttr != NULL)
{
text = NW_Text_Copy(NW_LMgr_ActiveContainerBoxOf(box)->hrefAttr, NW_TRUE);
}
else
{
NW_XHTML_GetDOMAttribute (thisObj, elementNode, NW_XHTML_AttributeToken_href, &text);
}
if (text)
{
(void)NW_HED_ContentHandler_ResolveURL ((NW_HED_ContentHandler_t *)thisObj, text, &retUrl);
text = retUrl;
}
return text;
}
// -----------------------------------------------------------------------------
NW_Text_t*
_NW_XHTML_ContentHandler_NumberCollector_GetAltAttr (NW_Markup_NumberCollector_t*
numberCollector,
NW_LMgr_Box_t* box)
{
NW_LMgr_PropertyValue_t value;
NW_XHTML_ContentHandler_t* thisObj;
NW_Text_t* text = NULL;
NW_DOM_ElementNode_t* elementNode;
/* parameter assertion block */
NW_ASSERT (NW_Object_IsInstanceOf (numberCollector,
&NW_XHTML_ContentHandler_NumberCollector_Class));
/* for convenience */
thisObj = static_cast<NW_XHTML_ContentHandler_t*>
(NW_Object_Aggregate_GetAggregator (numberCollector));
NW_ASSERT (NW_Object_IsInstanceOf (thisObj, &NW_XHTML_ContentHandler_Class));
value.object = NULL;
(void)NW_LMgr_Box_GetPropertyValue(box, NW_CSS_Prop_elementId, NW_CSS_ValueType_Object,
&value);
if (value.object)
{
elementNode = (NW_DOM_ElementNode_t *)(value.object);
NW_XHTML_GetDOMAttribute (thisObj, elementNode, NW_XHTML_AttributeToken_alt, &text);
}
return text;
}
// -----------------------------------------------------------------------------
// NW_XHTML_ContentHandler_IsSaveddeck
// Description: Used for cache-only loading for embeded elements in saved file
// (other items were commented in a header).
// Returns: NW_Bool: true if the xhtml content is retrieved from saved deck
// false, otherwise
// -----------------------------------------------------------------------------
//
NW_Bool
NW_XHTML_ContentHandler_IsSaveddeck(const NW_XHTML_ContentHandler_t* thisObj)
{
NW_ASSERT (thisObj);
return thisObj->saveddeck;
}
// -----------------------------------------------------------------------------
// NW_XHTML_ContentHandler_IsHistoryLoad
// Description: Used for setting cache mode for embeded elements
// (other items were commented in a header).
// Returns: NW_Bool: true if the xhtml content is result of history load
// false, otherwise
// -----------------------------------------------------------------------------
//
NW_Bool
NW_XHTML_ContentHandler_IsHistoryLoad(const NW_XHTML_ContentHandler_t* thisObj)
{
NW_ASSERT (thisObj);
return thisObj->histload;
}
// -----------------------------------------------------------------------------
// NW_XHTML_ContentHandler_IsReLoad
// Description: Used for setting cache mode for embeded elements
// (other items were commented in a header).
// Returns: NW_Bool: true if the xhtml content is result of reload
// false, otherwise
// -----------------------------------------------------------------------------
//
NW_Bool
NW_XHTML_ContentHandler_IsReLoad(const NW_XHTML_ContentHandler_t* thisObj)
{
NW_ASSERT (thisObj);
return thisObj->reload;
}
// -----------------------------------------------------------------------------
// NW_XHTML_ContentHandler_SetSaveddeck
// Description: set the saveddeck boolean member
// Returns: TBrowserStatusCode
// -----------------------------------------------------------------------------
//
TBrowserStatusCode
NW_XHTML_ContentHandler_SetSaveddeck(NW_XHTML_ContentHandler_t *thisObj, NW_Bool isSaveddeck)
{
NW_ASSERT (thisObj);
thisObj->saveddeck = isSaveddeck;
return KBrsrSuccess;
}
// -----------------------------------------------------------------------------
// NW_XHTML_ContentHandler_SetHistoryLoad
// Description: set the histload boolean member
// Returns: TBrowserStatusCode
// -----------------------------------------------------------------------------
//
TBrowserStatusCode
NW_XHTML_ContentHandler_SetHistoryLoad(NW_XHTML_ContentHandler_t *thisObj, NW_Bool isHistLoad)
{
NW_ASSERT (thisObj);
thisObj->histload = isHistLoad;
return KBrsrSuccess;
}
// -----------------------------------------------------------------------------
// NW_XHTML_ContentHandler_SetReLoad
// Description: set the reload boolean member
// Returns: TBrowserStatusCode
// -----------------------------------------------------------------------------
//
TBrowserStatusCode
NW_XHTML_ContentHandler_SetReLoad(NW_XHTML_ContentHandler_t *thisObj, NW_Bool isReLoad)
{
NW_ASSERT (thisObj);
thisObj->reload = isReLoad;
return KBrsrSuccess;
}
// -----------------------------------------------------------------------------
// NW_XHTML_ContentHandler_MetaRefreshInitialize
// Description: Initialize the META refresh. If and only if returns success, the
// content handler object will take ownership of and assume responsibility for
// destructing the resolvedUrl object. Once initialized, the content handler
// object performs the META refresh when needed.
// Returns: TBrowserStatusCode
// -----------------------------------------------------------------------------
//
TBrowserStatusCode
NW_XHTML_ContentHandler_MetaRefreshInitialize(NW_XHTML_ContentHandler_t* thisObj,
NW_Int32 seconds,
NW_Text_t* resolvedUrl,
NW_Uint8 loadReason)
{
NW_ASSERT (thisObj);
NW_ASSERT (resolvedUrl);
/* Cannot be set more than once. */
if (thisObj->metaRefreshSet)
{
return KBrsrUnexpectedError;
}
/* Save the variables for later. */
thisObj->metaRefreshSet = NW_TRUE;
thisObj->metaRefreshSeconds = seconds;
thisObj->metaRefreshLoadReason = loadReason;
thisObj->metaRefreshResolvedUrl = resolvedUrl; // We own the object now.
return KBrsrSuccess;
}
// -----------------------------------------------------------------------------
void
NW_XHTML_ContentHandler_SetImageMapLookupTable(NW_XHTML_ContentHandler_t *thisObj,
void* imageMapLookupTable)
{
thisObj->imageMapLookupTable = imageMapLookupTable;
}
// -----------------------------------------------------------------------------
void
NW_XHTML_ContentHandler_SetReferrerUrl(NW_XHTML_ContentHandler_t *thisObj)
{
const NW_Text_t* url =
NW_HED_UrlResponse_GetUrl( NW_HED_ContentHandler_GetUrlResponse(thisObj));
NW_HED_DocumentRoot_t* docRoot = (NW_HED_DocumentRoot_t*)
NW_HED_DocumentNode_GetRootNode (thisObj);
// The HTTP referrer header is being SET only if it is request from http or https.
//If it is any other request then don't set this. For example, link from the static
//file.
if( (NW_Str_Strnicmp((const NW_Ucs2*) url->storage, (const NW_Ucs2*) NW_STR("http:"), 5) == 0) ||
(NW_Str_Strnicmp((const NW_Ucs2*) url->storage, (const NW_Ucs2*) NW_STR("https:"), 6) == 0) )
{
NW_HED_DocumentRoot_SetDocumentReferrer(docRoot , url);
}
else
{
NW_HED_DocumentRoot_SetDocumentReferrer(docRoot , NULL);
}
}
// -----------------------------------------------------------------------------
void*
NW_XHTML_ContentHandler_GetImageMapLookupTable(NW_XHTML_ContentHandler_t *thisObj)
{
return thisObj->imageMapLookupTable;
}
// the function appends the transactionId to a list of pending script load
// requests. The function is called from scriptelementhandler after issuing
// a load request from external scripts
TBrowserStatusCode
NW_XHTML_ContentHandler_AddToPendingScriptTids(NW_XHTML_ContentHandler_t *thisObj, const TExternalScriptNode& aScriptNodeId )
{
TBrowserStatusCode status = KBrsrSuccess;
TBool foundScriptIndex = EFalse;
RArray<TExternalScriptNode>* scriptIds = STATIC_CAST(RArray<TExternalScriptNode>*, thisObj->scriptLoadTransactionIds);
TInt length = scriptIds->Count();
for (TInt index = 0 ; index < length ; index++)
{
TExternalScriptNode& scriptNode = (*scriptIds)[index];
if (scriptNode.iTransactionId == aScriptNodeId.iTransactionId )
{
foundScriptIndex = ETrue;
break;
}
}
// append to the scriptTid list
if (!foundScriptIndex)
{
TInt err = scriptIds->Append(aScriptNodeId);
if ( err != KErrNone)
{
status = (err == KErrNoMemory) ? KBrsrOutOfMemory : KBrsrFailure;
}
}
return status;
}
// the function returns the count of outstanding pending requests for external scripts
NW_Uint8
NW_XHTML_ContentHandler_PendingScriptLoadCount(NW_XHTML_ContentHandler_t *thisObj)
{
RArray<TExternalScriptNode>* scriptIds = STATIC_CAST(RArray<TExternalScriptNode>*, thisObj->scriptLoadTransactionIds);
return (NW_Uint8)scriptIds->Count();
}
// the function checks if the element node depends on the external scripts ,
// To check for dependency , check if there are any external script nodes that were before aElementNode
NW_Bool
NW_XHTML_ContentHandler_IsScriptLoadPending(NW_XHTML_ContentHandler_t *thisObj, NW_DOM_ElementNode_t* aElementNode)
{
NW_Bool depends = NW_FALSE;
RArray<TExternalScriptNode>* scriptIds = STATIC_CAST(RArray<TExternalScriptNode>*, thisObj->scriptLoadTransactionIds);
// if the pending script count is 0 then return NW_FALSE
// check if the first script node in the pending list > aElementNode then return NW_FALSE, else NW_TRUE
if(scriptIds->Count())
{
NW_DOM_ElementNode_t* scriptNode = (*scriptIds)[0].iScriptNode;
if (scriptNode->source_offset > aElementNode->source_offset)
{
depends = NW_FALSE;
}
else
{
depends = NW_TRUE;
}
}
else
{
depends = NW_FALSE;
}
return depends ;
}
// add the form node to the document form nodes list
TBrowserStatusCode
NW_XHTML_ContentHandler_AddFormNodes(NW_XHTML_ContentHandler_t *aThisObj, NW_DOM_ElementNode_t* aElementNode)
{
TBrowserStatusCode status = KBrsrSuccess;
RPointerArray<NW_DOM_ElementNode_t>* formNodes = (RPointerArray<NW_DOM_ElementNode_t>*)aThisObj->formNodes;
TInt err = formNodes->Append(aElementNode);
if ( err != KErrNone)
{
status = (err == KErrNoMemory) ? KBrsrOutOfMemory : KBrsrFailure;
}
return status;
}
// Returns the form node for a given input element node. The mechanism used
// here to find the form node is to search through the array of form nodes in
// reverse, comparing the element's source offset with that of the form node
// until the form node's source offset is <= to the element's source offset.
//
// WARNING:
//
// This approach has a flaw in it. It assumes that the source offset is
// accurate; that all the items are inserted sequentially. However, this is not
// the case for script-generated forms. Script forms get parsed separately as
// though they are separate streams/files. The source offset then ends up being
// relative to the start of the script and not the top-level HTML. Hence, for
// these cases, the source offset is not reliable.
//
// One example use case as of this writing is the delete button of the inbox
// email for www.excite.com wasn't working because it has several forms on the
// page along with a script-generated form.
//
NW_DOM_ElementNode_t*
NW_XHTML_ContentHandler_GetFormNodeFromSourceOffset(
NW_XHTML_ContentHandler_t *aThisObj, NW_DOM_ElementNode_t* aElementNode)
{
NW_DOM_ElementNode_t* node = NULL;
// get all the form nodes in the document
RPointerArray<NW_DOM_ElementNode_t>* formNodes = (RPointerArray<NW_DOM_ElementNode_t>*)aThisObj->formNodes;
// check the under what umberall does the input element fall under
for (TInt nodeIndex = formNodes->Count()-1; nodeIndex >=0; nodeIndex--)
{
// the first formNode to have the offset <= elementNode offset , it is the candidate
NW_DOM_ElementNode_t* formNode = (*formNodes)[nodeIndex];
if(formNode->source_offset <= aElementNode->source_offset)
{
node = formNode;
break;
}
}
return node;
}
// Returns the form node for a given input element node. The mechanism used
// here to find the form nodes is to walk up the DOM tree until the parent
// form node is found.
//
// WARNING:
//
// This approach assumes the DOM tree is accurate with the form node always
// being the parent node of its form elements - as it should be. However,
// under certain circumstances of poorly structured HTML, the current DOM tree
// processing does not place the form node as a parent of the form elements.
//
// One example use case of an incorrect DOM tree as of this writing is from the
// Nokia test suite:
// testsuite.nokia-boston.com/s60accept/cannedSites/fedexCopy/fedex.html
//
NW_DOM_ElementNode_t*
NW_XHTML_ContentHandler_GetFormNodeFromDomTree(
NW_XHTML_ContentHandler_t *aThisObj, NW_DOM_ElementNode_t* aElementNode)
{
NW_REQUIRED_PARAM(aThisObj);
NW_DOM_ElementNode_t* node = aElementNode;
// Walk up the DOM tree until parent form node is found or top is reached.
while (node && (NW_DOM_Node_getNodeToken(node) != NW_XHTML_ElementToken_form))
{
node = NW_DOM_Node_getParentNode(node);
}
return node;
}
// Returns the form node for a given input element node or NULL if none.
// An attempt is made to first get the form node by walking up the DOM tree.
// The DOM tree isn't always accurate (described above); hence, as a backup if
// the form node isn't found by walking up the DOM tree, then a second approach
// is used - search the form node array using source offset. This 2nd approach
// is also not always accruate (described above) and is even less reliable.
//
// Given that both mechanisms of finding the form node do not always work,
// there is the possibility that the wrong form node (or none) will be returned
// for some theoretical poorly structured HTML. If this should arise, the more
// rebust solution is to fix the DOM parsing such that form element nodes are
// always descendants of their form node.
//
NW_DOM_ElementNode_t*
NW_XHTML_ContentHandler_GetFormNode(NW_XHTML_ContentHandler_t *aThisObj, NW_DOM_ElementNode_t* aElementNode)
{
NW_DOM_ElementNode_t* node = NULL;
node = NW_XHTML_ContentHandler_GetFormNodeFromDomTree(aThisObj, aElementNode);
if (!node)
{
node = NW_XHTML_ContentHandler_GetFormNodeFromSourceOffset(aThisObj, aElementNode);
}
return node;
}
// -----------------------------------------------------------------------------
CBase*
NW_XHTML_ContentHandler_GetElementHandlerInstance(NW_XHTML_ContentHandler_t *thisObj,
NW_DOM_ElementNode_t* elementNode)
{
TBrowserStatusCode status;
CBase* value;
NW_ASSERT(thisObj != NULL);
NW_ASSERT(elementNode != NULL);
status = NW_ADT_Map_Get(thisObj->iElementHandlerMap, &elementNode, &value);
if ((status == KBrsrSuccess) && (value != NULL)) {
return value;
}
else {
return NULL;
}
}
// -----------------------------------------------------------------------------
TBrowserStatusCode
NW_XHTML_ContentHandler_SetElementHandlerInstance(NW_XHTML_ContentHandler_t *thisObj,
NW_DOM_ElementNode_t* elementNode, CBase* elementHandler)
{
CBase* oldInstance;
NW_ASSERT(thisObj != NULL);
NW_ASSERT(elementNode != NULL);
// Delete the previous value
oldInstance = NW_XHTML_ContentHandler_GetElementHandlerInstance(thisObj, elementNode);
// Disallow adding an existing context
if (oldInstance == elementHandler) {
return KBrsrSuccess;
}
// Remove the previous context
if (oldInstance) {
(void) NW_ADT_Map_Remove(thisObj->iElementHandlerMap, &elementNode);
delete oldInstance;
}
// Add the context
return NW_ADT_Map_Set(thisObj->iElementHandlerMap, &elementNode, &elementHandler);
}
// -----------------------------------------------------------------------------
// Returns true if the media string passed to it contains one of the supported
// media types, all, handheld, or NULL. The syntax is defined in section 6.13
// of the HTML 4.01 specification.
NW_Bool
NW_XHTML_ContentHandler_AllowableStylesheet(const NW_Ucs2* media, NW_Bool* isHandheld)
{
NW_Bool allowable = NW_FALSE;
NW_ASSERT(isHandheld != NULL);
*isHandheld = NW_FALSE;
// A NULL value is acceptable.
if (media == NULL)
{
return NW_TRUE;
}
do
{
const NW_Ucs2* valueEnd;
NW_Uint32 len;
// Skip leading white space.
while (NW_Str_Isspace(*media))
{
media++;
}
// Scan forward until hit something other than alpha, digit, hyphen.
valueEnd = media;
while (NW_Str_Isalnum(*valueEnd) || (*valueEnd == (NW_Ucs2)'-'))
{
valueEnd++;
}
// Try to match (case insensitive) with one of accepted media type strings.
len = valueEnd - media;
if ((len == 3) && (NW_Str_StrnicmpConst(media, "all", 3) == 0))
{
allowable = NW_TRUE;
}
if ((len == 8) && (NW_Str_StrnicmpConst(media, "handheld", 8) == 0))
{
*isHandheld = NW_TRUE;
allowable = NW_TRUE;
}
// If doesn't match, scan forward for comma and if found repeat.
while (*valueEnd)
{
if (*valueEnd == ',')
{
valueEnd++;
break;
}
valueEnd++;
}
media = valueEnd;
} while (*media);
return allowable;
}
// -----------------------------------------------------------------------------
// Enables mobile profile mode by disabling small screen layout and loading any
// pending external stylesheets.
void NW_XHTML_ContentHandler_EnableMobileProfileMode(NW_XHTML_ContentHandler_t* thisObj)
{
NW_CSS_Processor_t* processor = NULL;
NW_ASSERT(thisObj != NULL);
NW_Settings_SetDisableSmallScreenLayout(NW_TRUE);
processor = NW_XHTML_ContentHandler_GetCSSProcessor(thisObj);
if(processor != NULL)
{
NW_CSS_Processor_ProcessPendingLoads(processor);
}
}
// -----------------------------------------------------------------------------
// Load or queue a request for an external stylesheet.
TBrowserStatusCode
NW_XHTML_ContentHandler_LoadStylesheet(NW_XHTML_ContentHandler_t* thisObj,
const NW_Ucs2* type, const NW_Ucs2* relation, const NW_Ucs2* media,
const NW_Ucs2* url, const NW_Ucs2* charset, const NW_Ucs2* alternate)
{
NW_Bool isHandheld;
NW_Bool allowable;
NW_CSS_Processor_t* processor = NULL;
NW_Text_t* urlText = NULL;
NW_Text_t* resolvedUrl = NULL;
NW_Text_t* charsetText = NULL;
NW_ASSERT(thisObj != NULL);
NW_TRY (status)
{
// Verify that the url isn't NULL.
if (url == NULL)
{
NW_THROW_STATUS(status, KBrsrFailure);
}
// Verify that the type is text/css.
if ((type != NULL) && (NW_Str_StricmpConst(type, "text/css") != 0))
{
NW_THROW_STATUS(status, KBrsrFailure);
}
// Verify that the rel is stylesheet.
if ((relation != NULL) && (NW_Str_StricmpConst(relation, "stylesheet") != 0))
{
NW_THROW_STATUS(status, KBrsrFailure);
}
// Verify that the alternate is no.
if ((alternate != NULL) && (NW_Str_StricmpConst(alternate, "no") != 0))
{
NW_THROW_STATUS(status, KBrsrFailure);
}
// Verify that the media is allowable.
if (media != NULL)
{
allowable = NW_XHTML_ContentHandler_AllowableStylesheet(media, &isHandheld);
if (!allowable)
{
NW_THROW_STATUS(status, KBrsrFailure);
}
// If a "handheld" stylesheet is found switch to mobile profile mode.
if (isHandheld)
{
NW_XHTML_ContentHandler_EnableMobileProfileMode(thisObj);
}
}
// Resolve the url.
urlText = (NW_Text_t*) NW_Text_UCS2_New((void *) url, 0, 0);
NW_THROW_OOM_ON_NULL (urlText, status);
status = NW_HED_ContentHandler_ResolveURL(thisObj, urlText, &resolvedUrl);
NW_THROW_ON_ERROR(status);
urlText = NULL;
// Wrap the charset
if (charset != NULL)
{
charsetText = (NW_Text_t*) NW_Text_UCS2_New((void *) charset, 0, 0);
NW_THROW_OOM_ON_NULL(charsetText, status);
}
// Get the CSS processor
processor = NW_XHTML_ContentHandler_CreateCSSProcessor(thisObj);
NW_THROW_ON_NULL(processor, status, KBrsrUnexpectedError);
// Load or queue the stylesheet request.
status = NW_CSS_Processor_Load(processor, resolvedUrl, charsetText,
NW_XHTML_ContentHandler_IsSaveddeck(thisObj), NW_XHTML_ContentHandler_IsHistoryLoad(thisObj),
NW_XHTML_ContentHandler_IsReLoad(thisObj));
NW_THROW_ON_ERROR(status);
if (resolvedUrl)
{
NW_Object_Delete(resolvedUrl);
}
resolvedUrl = NULL;
charsetText = NULL;
}
NW_CATCH (status)
{
NW_Object_Delete(urlText);
NW_Object_Delete(resolvedUrl);
NW_Object_Delete(charsetText);
}
NW_FINALLY
{
return status;
} NW_END_TRY
}
TBrowserStatusCode
NW_XHTML_ContentHandler_WindowOpen(NW_XHTML_ContentHandler_t* thisObj,
NW_Text_t* url, NW_Text_t* target)
{
NW_HED_DocumentRoot_t* docRoot = NULL;
TBrowserStatusCode status = KBrsrSuccess;
docRoot = (NW_HED_DocumentRoot_t*) NW_HED_DocumentNode_GetRootNode (thisObj);
NW_ASSERT(docRoot != NULL);
NW_Uint32 length;
NW_Bool urlFreeNeeded = NW_FALSE;
NW_Bool targetFreeNeeded = NW_FALSE;
NW_Ucs2* urlStorage = NW_Text_GetUCS2Buffer (url, NW_Text_Flags_Aligned,
&length, &urlFreeNeeded);
NW_Ucs2* targetStorage = NW_Text_GetUCS2Buffer (target, NW_Text_Flags_Aligned,
&length, &targetFreeNeeded);
if (urlStorage == NULL || targetStorage == NULL)
{
status = KBrsrOutOfMemory;
}
else
{
TRAP(status, docRoot->documentListener->WindowOpenL(urlStorage, targetStorage, NW_Ecma_Evt_OnClick));
if (status != KBrsrSuccess)
status = KBrsrOutOfMemory;
}
if (urlFreeNeeded)
{
NW_Mem_Free(urlStorage);
}
if (targetFreeNeeded)
{
NW_Mem_Free(targetStorage);
}
return status;
}
TBrowserStatusCode
NW_XHTML_ContentHandler_WindowOpenAndPost(NW_XHTML_ContentHandler_t* thisObj,
NW_Text_t* url, NW_Text_t* target, NW_Uint8* contentType,
NW_Uint32 contentTypeLength, NW_Uint8* postData, NW_Uint32 postDataLength,
NW_Uint8* boundary)
{
NW_HED_DocumentRoot_t* docRoot = NULL;
TBrowserStatusCode status = KBrsrSuccess;
docRoot = (NW_HED_DocumentRoot_t*) NW_HED_DocumentNode_GetRootNode (thisObj);
NW_ASSERT(docRoot != NULL);
NW_Uint32 length;
NW_Bool urlFreeNeeded = NW_FALSE;
NW_Bool targetFreeNeeded = NW_FALSE;
NW_Ucs2* urlStorage = NW_Text_GetUCS2Buffer (url, NW_Text_Flags_Aligned,
&length, &urlFreeNeeded);
NW_Ucs2* targetStorage = NW_Text_GetUCS2Buffer (target, NW_Text_Flags_Aligned,
&length, &targetFreeNeeded);
if (urlStorage == NULL || targetStorage == NULL)
{
status = KBrsrOutOfMemory;
}
else
{
NW_ASSERT(postData != NULL);
TPtrC8 contentTypePtr (contentType, contentTypeLength);
TPtrC8 postDataPtr (postData, postDataLength);
TPtrC8 boundaryPtr(NULL, 0);
TDesC8* ptrForBoundary = NULL;
if (boundary != NULL)
{
boundaryPtr.Set(boundary, User::StringLength(boundary));
ptrForBoundary = &boundaryPtr;
}
TRAP(status, docRoot->documentListener->WindowOpenAndPostL(urlStorage, targetStorage, NW_Ecma_Evt_OnClick,
TBrCtlDefs::EMethodPost, &contentTypePtr, &postDataPtr, ptrForBoundary, NULL));
if (status != KBrsrSuccess)
status = KBrsrOutOfMemory;
}
if (urlFreeNeeded)
{
NW_Mem_Free(urlStorage);
}
if (targetFreeNeeded)
{
NW_Mem_Free(targetStorage);
}
return status;
}
/*
Get the target in base tag defined in header, this value can be used to decide if to
open a link in a new window or not
*/
void
NW_XHTML_ContentHandler_GetBaseTagTarget (NW_XHTML_ContentHandler_t* contentHandler,
NW_Text_t** targetVal)
{
NW_DOM_Node_t* baseElement;
NW_Text_t* target = NULL;
NW_ASSERT (targetVal);
/* get the base url as found in the "base" element */
baseElement = NW_HED_DomHelper_FindElement (&contentHandler->domHelper, NW_HED_DomTree_GetRootNode (
contentHandler->domTree), 3, NW_XHTML_ElementToken_base, 0, NULL);
if (baseElement != NULL)
{
NW_XHTML_GetDOMAttribute (contentHandler, baseElement, NW_XHTML_AttributeToken_target, &target);
if (target != NULL && target->characterCount == 0)
{
NW_Object_Delete(target);
target = NULL;
}
if (target != NULL)
{
*targetVal = (NW_Text_t*) NW_Text_UCS2_New (target->storage, NW_Text_GetCharCount(target), NW_Text_Flags_TakeOwnership);
}
}
}