webengine/wmlengine/src/hed/src/HEDCompositeContentHandler.cpp
changeset 74 91031d3aab7d
parent 68 92a765b5b3e7
child 85 e358f2276d3f
equal deleted inserted replaced
68:92a765b5b3e7 74:91031d3aab7d
     1 /*
       
     2 * Copyright (c) 2000 - 2001 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "nw_hed_compositecontenthandleri.h"
       
    20 #include "nw_hed_documentroot.h"
       
    21 #include "nw_system_optionlist.h"
       
    22 #include "nw_image_epoc32simpleimage.h"
       
    23 #include "nw_imagech_epoc32contenthandler.h"
       
    24 #include "nwx_multipart_generator.h"
       
    25 #include "nw_image_epoc32cannedimage.h"
       
    26 #include "nw_image_cannedimages.h"
       
    27 #include "HEDDocumentListener.h"
       
    28 #include "nw_lmgr_rootbox.h"
       
    29 #include "nw_image_virtualimage.h"
       
    30 #include "BrsrStatusCodes.h"
       
    31 #include "nwx_settings.h"
       
    32 #include <nwx_http_defs.h>
       
    33 #include "StringUtils.h"
       
    34 #include "TEncodingMapping.h"
       
    35 #include "bodypart.h"
       
    36 #include "MemoryManager.h"
       
    37 
       
    38 
       
    39 /* ------------------------------------------------------------------------- *
       
    40    static data
       
    41  * ------------------------------------------------------------------------- */
       
    42 
       
    43 /* ------------------------------------------------------------------------- */
       
    44 const NW_HED_CompositeContentHandler_Class_t NW_HED_CompositeContentHandler_Class = {
       
    45   { /* NW_Object_Core                 */
       
    46     /* super                          */ &NW_HED_ContentHandler_Class,
       
    47     /* queryInterface                 */ _NW_Object_Base_QueryInterface
       
    48   },
       
    49   { /* NW_Object_Base                 */
       
    50     /* interfaceList                  */ NW_HED_CompositeContentHandler_SecondaryList
       
    51   },
       
    52   { /* NW_Object_Dynamic              */
       
    53     /* instanceSize                   */ sizeof (NW_HED_CompositeContentHandler_t),
       
    54     /* construct                      */ _NW_HED_CompositeContentHandler_Construct,
       
    55     /* destruct                       */ _NW_HED_CompositeContentHandler_Destruct
       
    56   },
       
    57   { /* NW_HED_DocumentNode            */
       
    58     /* cancel                         */ _NW_HED_CompositeContentHandler_Cancel,
       
    59     /* partialLoadCallback	          */ NULL,
       
    60     /* initialize                     */ _NW_HED_ContentHandler_Initialize,
       
    61     /* nodeChanged                    */ _NW_HED_DocumentNode_NodeChanged,
       
    62     /* getBoxTree                     */ _NW_HED_ContentHandler_GetBoxTree,
       
    63     /* processEvent                   */ _NW_HED_DocumentNode_ProcessEvent,
       
    64     /* handleError                    */ _NW_HED_DocumentNode_HandleError,
       
    65     /* suspend                        */ _NW_HED_CompositeContentHandler_Suspend,
       
    66     /* resume                         */ _NW_HED_CompositeContentHandler_Resume,
       
    67     /* allLoadsCompleted              */ _NW_HED_CompositeContentHandler_AllLoadsCompleted,
       
    68     /* intraPageNavigationCompleted   */ _NW_HED_DocumentNode_IntraPageNavigationCompleted,
       
    69     /* loseFocus                      */ _NW_HED_CompositeContentHandler_LoseFocus,
       
    70     /* gainFocus                      */ _NW_HED_CompositeContentHandler_GainFocus,
       
    71     /* handleLoadComplete           */ _NW_HED_DocumentNode_HandleLoadComplete,
       
    72   },
       
    73   { /* NW_HED_ContentHandler          */  
       
    74     /* partialNextChunk               */ _NW_HED_ContentHandler_PartialNextChunk,
       
    75     /* getTitle                       */ NULL,
       
    76     /* getUrl                         */ _NW_HED_ContentHandler_GetURL,
       
    77     /* resolveUrl                     */ _NW_HED_ContentHandler_ResolveURL,
       
    78     /* createHistoryEntry             */ _NW_HED_ContentHandler_CreateHistoryEntry,
       
    79     /* createIntraHistoryEntry        */ _NW_HED_ContentHandler_CreateIntraDocumentHistoryEntry,
       
    80     /* newUrlResponse                 */ _NW_HED_ContentHandler_NewUrlResponse,
       
    81     /* createBoxTree                  */ NULL,
       
    82     /* handleRequest                  */ _NW_HED_ContentHandler_HandleRequest,
       
    83     /* featureQuery                   */ _NW_HED_ContentHandler_FeatureQuery,
       
    84     /* responseComplete               */ _NW_HED_ContentHandler_ResponseComplete
       
    85   },
       
    86   { /* NW_HED_CompositeContentHandler */
       
    87     /* documentDisplayed              */ _NW_HED_CompositeContentHandler_DocumentDisplayed
       
    88   }
       
    89 };
       
    90 
       
    91 /* ------------------------------------------------------------------------- */
       
    92 const NW_Object_Class_t* const NW_HED_CompositeContentHandler_SecondaryList[] = {
       
    93   &NW_HED_CompositeContentHandler_CompositeNode_Class,
       
    94   NULL,
       
    95 };
       
    96 
       
    97 /* ------------------------------------------------------------------------- */
       
    98 const NW_HED_CompositeNode_Class_t NW_HED_CompositeContentHandler_CompositeNode_Class = {
       
    99   { /* NW_Object_Core       */
       
   100     /* super                */ &NW_HED_CompositeNode_Class,
       
   101     /* querySecondary       */ _NW_Object_Core_QuerySecondary
       
   102   },
       
   103   { /* NW_Object_Secondary  */
       
   104     /* offset               */ offsetof (NW_HED_CompositeContentHandler_t,
       
   105                                          NW_HED_CompositeNode)
       
   106   },
       
   107   { /* NW_Object_Aggregate  */
       
   108     /* secondaryList        */ NULL,
       
   109     /* construct            */ NULL,
       
   110     /* destruct             */ NULL
       
   111   },
       
   112   { /* NW_HED_CompositeNode */
       
   113     /* addChild             */ _NW_HED_CompositeContentHandler_CompositeNode_AddChild
       
   114   }
       
   115 };
       
   116 
       
   117 /* ------------------------------------------------------------------------- */
       
   118 static NW_Int32 NW_HED_CompositeContentHandler_FindCharset(NW_Uint8* charset, NW_Uint32 charsetLength)
       
   119 {
       
   120   NW_Uint32 i = 0;
       
   121   NW_Ucs2* supportedCharStr = NULL;
       
   122 
       
   123   for (; supportedCharset[i].charset != NULL; i++)
       
   124   {
       
   125     supportedCharStr = NW_Asc_toUcs2((char*)supportedCharset[i].charset);
       
   126     if (charsetLength == NW_Str_Strlen(supportedCharStr)*sizeof(NW_Ucs2) &&
       
   127       NW_Byte_Strnicmp((const NW_Byte*)supportedCharStr, (const NW_Byte*)charset, charsetLength) == 0)
       
   128     {
       
   129       NW_Str_Delete(supportedCharStr);
       
   130       return i;
       
   131     }
       
   132     NW_Str_Delete(supportedCharStr);
       
   133   }
       
   134   return -1;
       
   135 }
       
   136 
       
   137 NW_Int16 NW_HED_CompositeContentHandler_Encoding(NW_Uint8* charset, NW_Uint32 charsetLength)
       
   138     {
       
   139     NW_Int16 encoding = 0;
       
   140     NW_Ucs2* supportedCharStr = NULL;
       
   141     StringUtils::ConvertPtrAsciiToUcs2(TPtrC8(charset, charsetLength), &supportedCharStr);
       
   142     NW_Int32 index = NW_HED_CompositeContentHandler_FindCharset((NW_Byte*)supportedCharStr, charsetLength * sizeof(NW_Ucs2));
       
   143     if (index != -1 )
       
   144         {
       
   145         encoding = supportedCharset[index].ianaEncoding ;
       
   146         }
       
   147     delete supportedCharStr;
       
   148     return encoding;
       
   149     }
       
   150 
       
   151 NW_Int32 NW_HED_CompositeContentHandler_GetCharsetString(NW_Uint16 aCharset,
       
   152                                                      const NW_Uint8** aCharsetString)
       
   153     {
       
   154     TUint i = 0;
       
   155     
       
   156     for (; supportedCharset[i].charset != NULL; i++)
       
   157         {
       
   158         if (supportedCharset[i].ianaEncoding == aCharset)
       
   159             {
       
   160             *aCharsetString = supportedCharset[i].charset;
       
   161             return KErrNone;
       
   162             }
       
   163         }
       
   164     return KErrArgument;
       
   165     }
       
   166 
       
   167 static NW_Int32 NW_HED_CompositeContentHandler_FindCharsetFromInternalEncoding(NW_Uint16 internalEncoding)
       
   168 {
       
   169   NW_Uint32 i = 0;
       
   170 
       
   171   // First check if "automatic" encoding mode set on phone, if so return -1.  This is
       
   172   // needed to allow the follow on code to determine the encoding from the response.
       
   173   if (internalEncoding == EAutomatic)
       
   174   {
       
   175     return -1;
       
   176   }
       
   177 	
       
   178   // If not "automatic" encoding, get the charset encoding that is set on phone
       
   179   for (; supportedCharset[i].charset != NULL; i++)
       
   180   {
       
   181     if (supportedCharset[i].internalEncoding == internalEncoding)
       
   182     {
       
   183       return i;
       
   184     }
       
   185   }
       
   186   return -1;
       
   187 }
       
   188 
       
   189 static NW_Int32 NW_HED_CompositeContentHandler_FindCharsetFromIanaEncoding(NW_Uint16 ianaEncoding)
       
   190 {
       
   191   NW_Uint32 i = 0;
       
   192   for (; supportedCharset[i].charset != NULL; i++)
       
   193   {
       
   194     if (supportedCharset[i].ianaEncoding == ianaEncoding)
       
   195     {
       
   196       return i;
       
   197     }
       
   198   }
       
   199   return -1;
       
   200 }
       
   201 
       
   202 
       
   203 /* ------------------------------------------------------------------------- *
       
   204    NW_HED_DocumentNode methods
       
   205  * ------------------------------------------------------------------------- */
       
   206 
       
   207 TBrowserStatusCode
       
   208 _NW_HED_CompositeContentHandler_Construct (NW_Object_Dynamic_t* dynamicObject,
       
   209                                              va_list* argp)
       
   210     {
       
   211     NW_HED_CompositeContentHandler_t* thisObj;
       
   212     TBrowserStatusCode status;
       
   213 
       
   214     /* for convenience */
       
   215     thisObj = NW_HED_CompositeContentHandlerOf (dynamicObject);
       
   216 
       
   217     /* invoke our superclass constructor */
       
   218     status = _NW_HED_ContentHandler_Construct (dynamicObject, argp);
       
   219     if (status != KBrsrSuccess)
       
   220         {
       
   221         return status;
       
   222         }
       
   223 
       
   224     thisObj->iMultipart = EFalse;
       
   225 
       
   226     return KBrsrSuccess;
       
   227     }
       
   228 
       
   229 // -----------------------------------------------------------------------------
       
   230 void
       
   231 _NW_HED_CompositeContentHandler_Destruct (NW_Object_Dynamic_t* dynamicObject)
       
   232     {
       
   233     NW_HED_CompositeContentHandler_t* thisObj;
       
   234 
       
   235     /* cast the 'object' for convenience */
       
   236     thisObj = NW_HED_CompositeContentHandlerOf (dynamicObject);
       
   237 
       
   238 
       
   239     // multipart related cleanup
       
   240     if( thisObj->iMultipart )
       
   241         {
       
   242         // Free original body
       
   243         NW_Buffer_Free( thisObj->iOldResponseBody );
       
   244 
       
   245         // clean up body part array and its content
       
   246         TInt size = thisObj->iBodyPartArray.Count();
       
   247         TInt i;
       
   248         for (i = 0; i < size; i++)
       
   249             {
       
   250             delete thisObj->iBodyPartArray[i];
       
   251             }
       
   252         thisObj->iBodyPartArray.Reset();
       
   253         }
       
   254   }
       
   255 
       
   256 /* ------------------------------------------------------------------------- */
       
   257 TBrowserStatusCode
       
   258 _NW_HED_CompositeContentHandler_Cancel (NW_HED_DocumentNode_t* documentNode, 
       
   259 					NW_HED_CancelType_t cancelType)
       
   260 {
       
   261   NW_HED_CompositeContentHandler_t* thisObj;
       
   262   NW_HED_CompositeNode_t* compositeNode;
       
   263   NW_ADT_Iterator_t* iterator = NULL;
       
   264   
       
   265   /* parameter assertion block */
       
   266   NW_ASSERT (NW_Object_IsInstanceOf (documentNode,
       
   267                                      &NW_HED_CompositeContentHandler_Class));
       
   268   
       
   269   /* for convenience */
       
   270   thisObj = NW_HED_CompositeContentHandlerOf (documentNode);
       
   271   compositeNode = (NW_HED_CompositeNode_t *)
       
   272     NW_Object_QuerySecondary (thisObj, &NW_HED_CompositeNode_Class);
       
   273   NW_ASSERT (NW_Object_IsInstanceOf (compositeNode,
       
   274                                      &NW_HED_CompositeContentHandler_CompositeNode_Class));
       
   275 
       
   276   NW_TRY (status) {
       
   277     NW_HED_DocumentNode_t* childNode;
       
   278 
       
   279     /* create the child iterator */
       
   280     status = NW_HED_CompositeNode_GetChildren (compositeNode, &iterator);
       
   281     if (status != KBrsrSuccess) {
       
   282       if (status != KBrsrNotFound) {
       
   283         NW_THROW (status);
       
   284       }
       
   285     } else {
       
   286       /* iterate through the children */
       
   287       while (NW_ADT_Iterator_HasMoreElements (iterator)) {
       
   288         status = NW_ADT_Iterator_GetNextElement (iterator, &childNode);
       
   289         NW_ASSERT (status == KBrsrSuccess);
       
   290 
       
   291         /* invoke the child method */
       
   292         (void) NW_HED_DocumentNode_Cancel (childNode, cancelType);
       
   293       }
       
   294     }
       
   295 
       
   296     /* invoke our superclass */
       
   297    status = NW_HED_ContentHandler_Class.NW_HED_DocumentNode.
       
   298       cancel (documentNode, cancelType);
       
   299   }
       
   300   
       
   301   NW_CATCH (status) { /* empty */ }
       
   302 
       
   303   NW_FINALLY {
       
   304     NW_Object_Delete (iterator);
       
   305 	return status;
       
   306   } NW_END_TRY
       
   307 }
       
   308 
       
   309 /* ------------------------------------------------------------------------- */
       
   310 void
       
   311 _NW_HED_CompositeContentHandler_Suspend (NW_HED_DocumentNode_t* documentNode,
       
   312                                          NW_Bool aDestroyBoxTree)
       
   313 {
       
   314   NW_HED_CompositeContentHandler_t* thisObj;
       
   315   NW_HED_CompositeNode_t* compositeNode;
       
   316   NW_ADT_Iterator_t* iterator = NULL;
       
   317   
       
   318   /* parameter assertion block */
       
   319   NW_ASSERT (NW_Object_IsInstanceOf (documentNode,
       
   320                                      &NW_HED_CompositeContentHandler_Class));
       
   321   
       
   322   /* for convenience */
       
   323   thisObj = NW_HED_CompositeContentHandlerOf (documentNode);
       
   324   compositeNode = (NW_HED_CompositeNode_t *)
       
   325     NW_Object_QuerySecondary (thisObj, &NW_HED_CompositeNode_Class);
       
   326   NW_ASSERT (NW_Object_IsInstanceOf (compositeNode,
       
   327                                      &NW_HED_CompositeContentHandler_CompositeNode_Class));
       
   328 
       
   329   NW_TRY (status) {
       
   330     NW_HED_DocumentNode_t* childNode;
       
   331 
       
   332     /* create the child iterator */
       
   333     status = NW_HED_CompositeNode_GetChildren (compositeNode, &iterator);
       
   334     if (status != KBrsrSuccess) {
       
   335       if (status != KBrsrNotFound) {
       
   336         NW_THROW (status);
       
   337       }
       
   338     } else {
       
   339       /* iterate through the children */
       
   340       while (NW_ADT_Iterator_HasMoreElements (iterator)) {
       
   341         status = NW_ADT_Iterator_GetNextElement (iterator, &childNode);
       
   342         NW_ASSERT (status == KBrsrSuccess);
       
   343 
       
   344         /* invoke the child method */
       
   345         NW_HED_DocumentNode_Suspend (childNode, aDestroyBoxTree);
       
   346       }
       
   347     }
       
   348 
       
   349     /* invoke our superclass */
       
   350     NW_HED_ContentHandler_Class.NW_HED_DocumentNode.
       
   351       suspend (documentNode, aDestroyBoxTree);
       
   352   }
       
   353   
       
   354   NW_CATCH (status) { /* empty */ }
       
   355 
       
   356   NW_FINALLY {
       
   357     NW_Object_Delete (iterator);
       
   358   } NW_END_TRY
       
   359 }
       
   360 
       
   361 /* ------------------------------------------------------------------------- */
       
   362 void
       
   363 _NW_HED_CompositeContentHandler_Resume (NW_HED_DocumentNode_t* documentNode)
       
   364 {
       
   365   NW_HED_CompositeContentHandler_t* thisObj;
       
   366   NW_HED_CompositeNode_t* compositeNode;
       
   367   NW_ADT_Iterator_t* iterator = NULL;
       
   368   
       
   369   /* parameter assertion block */
       
   370   NW_ASSERT (NW_Object_IsInstanceOf (documentNode,
       
   371                                      &NW_HED_CompositeContentHandler_Class));
       
   372   
       
   373   /* for convenience */
       
   374   thisObj = NW_HED_CompositeContentHandlerOf (documentNode);
       
   375   compositeNode = (NW_HED_CompositeNode_t *)
       
   376     NW_Object_QuerySecondary (thisObj, &NW_HED_CompositeNode_Class);
       
   377   NW_ASSERT (NW_Object_IsInstanceOf (compositeNode,
       
   378                                      &NW_HED_CompositeContentHandler_CompositeNode_Class));
       
   379 
       
   380   NW_TRY (status) {
       
   381     NW_HED_DocumentNode_t* childNode;
       
   382 
       
   383     /* create the child iterator */
       
   384     status = NW_HED_CompositeNode_GetChildren (compositeNode, &iterator);
       
   385     if (status != KBrsrSuccess) {
       
   386       if (status != KBrsrNotFound) {
       
   387         NW_THROW (status);
       
   388       }
       
   389     } else {
       
   390       /* iterate through the children */
       
   391       while (NW_ADT_Iterator_HasMoreElements (iterator)) {
       
   392         status = NW_ADT_Iterator_GetNextElement (iterator, &childNode);
       
   393         NW_ASSERT (status == KBrsrSuccess);
       
   394 
       
   395         /* invoke the child method */
       
   396         NW_HED_DocumentNode_Resume (childNode);
       
   397       }
       
   398     }
       
   399 
       
   400     /* invoke our superclass */
       
   401     NW_HED_ContentHandler_Class.NW_HED_DocumentNode.
       
   402       resume (documentNode);
       
   403   }
       
   404   
       
   405   NW_CATCH (status) { /* empty */ }
       
   406 
       
   407   NW_FINALLY {
       
   408     NW_Object_Delete (iterator);
       
   409   } NW_END_TRY
       
   410 }
       
   411 
       
   412 /* ------------------------------------------------------------------------- */
       
   413 void
       
   414 _NW_HED_CompositeContentHandler_AllLoadsCompleted (NW_HED_DocumentNode_t* documentNode)
       
   415 {
       
   416   NW_HED_CompositeContentHandler_t* thisObj;
       
   417   NW_HED_CompositeNode_t* compositeNode;
       
   418   NW_ADT_Iterator_t* iterator = NULL;
       
   419   
       
   420   /* parameter assertion block */
       
   421   NW_ASSERT (NW_Object_IsInstanceOf (documentNode,
       
   422                                      &NW_HED_CompositeContentHandler_Class));
       
   423   
       
   424   /* for convenience */
       
   425   thisObj = NW_HED_CompositeContentHandlerOf (documentNode);
       
   426   compositeNode = (NW_HED_CompositeNode_t *)
       
   427     NW_Object_QuerySecondary (thisObj, &NW_HED_CompositeNode_Class);
       
   428   NW_ASSERT (NW_Object_IsInstanceOf (compositeNode,
       
   429                                      &NW_HED_CompositeContentHandler_CompositeNode_Class));
       
   430 
       
   431   NW_TRY (status) {
       
   432     NW_HED_DocumentNode_t* childNode;
       
   433 
       
   434     /* create the child iterator */
       
   435     status = NW_HED_CompositeNode_GetChildren (compositeNode, &iterator);
       
   436     if (status != KBrsrSuccess) {
       
   437       if (status != KBrsrNotFound) {
       
   438         NW_THROW (status);
       
   439       }
       
   440     } else {
       
   441       /* iterate through the children */
       
   442       while (NW_ADT_Iterator_HasMoreElements (iterator)) {
       
   443         status = NW_ADT_Iterator_GetNextElement (iterator, &childNode);
       
   444         NW_ASSERT (status == KBrsrSuccess);
       
   445 
       
   446         /* invoke the child method */
       
   447         NW_HED_DocumentNode_AllLoadsCompleted (childNode);
       
   448       }
       
   449     }
       
   450 
       
   451     /* invoke our superclass */
       
   452     NW_HED_ContentHandler_Class.NW_HED_DocumentNode.
       
   453       allLoadsCompleted (documentNode);
       
   454   }
       
   455   
       
   456   NW_CATCH (status) { /* empty */ }
       
   457 
       
   458   NW_FINALLY {
       
   459     NW_Object_Delete (iterator);
       
   460   } NW_END_TRY
       
   461 }
       
   462 
       
   463 /* ------------------------------------------------------------------------- */
       
   464 void
       
   465 _NW_HED_CompositeContentHandler_LoseFocus (NW_HED_DocumentNode_t* documentNode)
       
   466 {
       
   467   NW_HED_CompositeContentHandler_t* thisObj;
       
   468   NW_HED_CompositeNode_t* compositeNode;
       
   469   NW_ADT_Iterator_t* iterator = NULL;
       
   470   
       
   471   /* parameter assertion block */
       
   472   NW_ASSERT (NW_Object_IsInstanceOf (documentNode,
       
   473                                      &NW_HED_CompositeContentHandler_Class));
       
   474   
       
   475   /* for convenience */
       
   476   thisObj = NW_HED_CompositeContentHandlerOf (documentNode);
       
   477   compositeNode = (NW_HED_CompositeNode_t *)
       
   478     NW_Object_QuerySecondary (thisObj, &NW_HED_CompositeNode_Class);
       
   479   NW_ASSERT (NW_Object_IsInstanceOf (compositeNode,
       
   480                                      &NW_HED_CompositeContentHandler_CompositeNode_Class));
       
   481 
       
   482   NW_TRY (status) {
       
   483     NW_HED_DocumentNode_t* childNode;
       
   484 
       
   485     /* create the child iterator */
       
   486     status = NW_HED_CompositeNode_GetChildren (compositeNode, &iterator);
       
   487     if (status != KBrsrSuccess) {
       
   488       if (status != KBrsrNotFound) {
       
   489         NW_THROW (status);
       
   490       }
       
   491     } else {
       
   492       /* iterate through the children */
       
   493       while (NW_ADT_Iterator_HasMoreElements (iterator)) {
       
   494         status = NW_ADT_Iterator_GetNextElement (iterator, &childNode);
       
   495         NW_ASSERT (status == KBrsrSuccess);
       
   496 
       
   497         /* invoke the child method */
       
   498         NW_HED_DocumentNode_LoseFocus (childNode);
       
   499       }
       
   500     }
       
   501 
       
   502     /* invoke our superclass */
       
   503     NW_HED_ContentHandler_Class.NW_HED_DocumentNode.
       
   504       loseFocus (documentNode);
       
   505   }
       
   506   
       
   507   NW_CATCH (status) { /* empty */ }
       
   508 
       
   509   NW_FINALLY {
       
   510     NW_Object_Delete (iterator);
       
   511   } NW_END_TRY
       
   512 }
       
   513 
       
   514 /* ------------------------------------------------------------------------- */
       
   515 void
       
   516 _NW_HED_CompositeContentHandler_GainFocus (NW_HED_DocumentNode_t* documentNode)
       
   517 {
       
   518   NW_HED_CompositeContentHandler_t* thisObj;
       
   519   NW_HED_CompositeNode_t* compositeNode;
       
   520   NW_ADT_Iterator_t* iterator = NULL;
       
   521   
       
   522   /* parameter assertion block */
       
   523   NW_ASSERT (NW_Object_IsInstanceOf (documentNode,
       
   524                                      &NW_HED_CompositeContentHandler_Class));
       
   525   
       
   526   /* for convenience */
       
   527   thisObj = NW_HED_CompositeContentHandlerOf (documentNode);
       
   528   compositeNode = (NW_HED_CompositeNode_t *)
       
   529     NW_Object_QuerySecondary (thisObj, &NW_HED_CompositeNode_Class);
       
   530   NW_ASSERT (NW_Object_IsInstanceOf (compositeNode,
       
   531                                      &NW_HED_CompositeContentHandler_CompositeNode_Class));
       
   532 
       
   533   NW_TRY (status) {
       
   534     NW_HED_DocumentNode_t* childNode;
       
   535 
       
   536     /* create the child iterator */
       
   537     status = NW_HED_CompositeNode_GetChildren (compositeNode, &iterator);
       
   538     if (status != KBrsrSuccess) {
       
   539       if (status != KBrsrNotFound) {
       
   540         NW_THROW (status);
       
   541       }
       
   542     } else {
       
   543       /* iterate through the children */
       
   544       while (NW_ADT_Iterator_HasMoreElements (iterator)) {
       
   545         status = NW_ADT_Iterator_GetNextElement (iterator, &childNode);
       
   546         NW_ASSERT (status == KBrsrSuccess);
       
   547 
       
   548         /* invoke the child method */
       
   549         NW_HED_DocumentNode_GainFocus (childNode);
       
   550       }
       
   551     }
       
   552 
       
   553     /* invoke our superclass */
       
   554     NW_HED_ContentHandler_Class.NW_HED_DocumentNode.
       
   555       gainFocus (documentNode);
       
   556   }
       
   557   
       
   558   NW_CATCH (status) { /* empty */ }
       
   559 
       
   560   NW_FINALLY {
       
   561     NW_Object_Delete (iterator);
       
   562   } NW_END_TRY
       
   563 }
       
   564 
       
   565 /* ------------------------------------------------------------------------- */
       
   566 TBrowserStatusCode
       
   567 _NW_HED_CompositeContentHandler_DetachChildren (NW_HED_CompositeContentHandler_t* thisObj)
       
   568 {
       
   569   NW_HED_CompositeNode_t* compositeNode;
       
   570   NW_ADT_Iterator_t* iterator = NULL;
       
   571   
       
   572   /* parameter assertion block */
       
   573   NW_ASSERT (NW_Object_IsInstanceOf (thisObj,
       
   574                                      &NW_HED_CompositeContentHandler_Class));
       
   575   
       
   576   /* for convenience */
       
   577   compositeNode = (NW_HED_CompositeNode_t *)
       
   578     NW_Object_QuerySecondary (thisObj, &NW_HED_CompositeNode_Class);
       
   579   NW_ASSERT (NW_Object_IsInstanceOf (compositeNode,
       
   580                                      &NW_HED_CompositeContentHandler_CompositeNode_Class));
       
   581 
       
   582   NW_TRY (status) {
       
   583     NW_HED_DocumentNode_t* childNode;
       
   584 
       
   585     /* create the child iterator */
       
   586     status = NW_HED_CompositeNode_GetChildren (compositeNode, &iterator);
       
   587     if (status == KBrsrNotFound) {
       
   588       NW_THROW_SUCCESS (status);
       
   589     }
       
   590     NW_THROW_ON_ERROR (status);
       
   591 
       
   592     /* iterate through the children */
       
   593     while (NW_ADT_Iterator_HasMoreElements (iterator)) {
       
   594       status = NW_ADT_Iterator_GetNextElement (iterator, &childNode);
       
   595       NW_ASSERT (status == KBrsrSuccess);
       
   596 
       
   597       /* detach the child */
       
   598       if (NW_HED_ContentHandlerOf (childNode)->boxTree != NULL) {
       
   599         (void) NW_LMgr_Box_Detach (NW_HED_ContentHandlerOf (childNode)->boxTree);
       
   600       }
       
   601     }
       
   602   }
       
   603   
       
   604   NW_CATCH (status) { /* empty */ }
       
   605 
       
   606   NW_FINALLY {
       
   607     NW_Object_Delete (iterator);
       
   608     return status;
       
   609   } NW_END_TRY
       
   610 }
       
   611 
       
   612 /* ------------------------------------------------------------------------- */
       
   613 TBrowserStatusCode
       
   614 _NW_HED_CompositeContentHandler_DocumentDisplayed (NW_HED_ContentHandler_t* thisObj)
       
   615 {
       
   616   NW_REQUIRED_PARAM(thisObj);
       
   617 
       
   618   /* Default implementation does nothing. */
       
   619   return KBrsrSuccess;
       
   620 }
       
   621 
       
   622 /* ------------------------------------------------------------------------- */
       
   623 
       
   624 static
       
   625 NW_Bool
       
   626 _NW_HED_CompositeContentHandler_DetectEncoding(NW_Buffer_t* pInBuf,
       
   627                                                NW_Uint16* encoding,
       
   628                                                NW_Uint8* byteOrder)
       
   629 {
       
   630   /*
       
   631     The goal here is to permit the content author to do something
       
   632     which is within current specifications and can be depended on to
       
   633     work.
       
   634  
       
   635     Despite of the charset in response header, we apply the following 
       
   636     constraint to determine the charset:
       
   637  
       
   638     Content authors must place a byte order mark (BOM) at the
       
   639     beginning of the document only if the encoding is UCS-2 or UTF-8.
       
   640 
       
   641     If the first bytes are:
       
   642     0xFE 0xFF ## ## (big endian) or 0xFF 0xFE ## ## (little endian), where the
       
   643     two ## bytes are not both zero then the encoding is UCS-2.
       
   644     (UCS-2 is roughly a subset of UTF-16 in our use, aka Unicode)
       
   645  
       
   646     0xEF 0xBB 0xBF then the encoding is UTF-8
       
   647  
       
   648     otherwise the encoding is left as Latin-1.
       
   649  
       
   650     Differentiating ASCII from Latin-1 is never an issue because it is
       
   651     a subset of Latin-1 which is the default.
       
   652  
       
   653     You can find a discussion of this type of encoding detection at
       
   654     http://www.w3.org/TR/2000/REC-xml-20001006#sec-guessing
       
   655   */
       
   656 
       
   657   *byteOrder = NW_BYTEORDER_SINGLE_BYTE;
       
   658 
       
   659   if ((pInBuf == NULL) || (pInBuf->data == NULL))
       
   660   {
       
   661     return NW_FALSE;
       
   662   }
       
   663 
       
   664   if (pInBuf->length >= 3)
       
   665   {
       
   666     if (((pInBuf->data)[0] == 0xef)
       
   667         && ((pInBuf->data)[1] == 0xbb)
       
   668         && ((pInBuf->data)[2] == 0xbf))
       
   669     {
       
   670       *encoding = HTTP_utf_8;
       
   671       *byteOrder = NW_BYTEORDER_SINGLE_BYTE;
       
   672       return NW_TRUE;
       
   673     }
       
   674   }
       
   675 
       
   676   if (pInBuf->length >= 4)
       
   677   {
       
   678     if (((pInBuf->data)[0] == 0xfe) && ((pInBuf->data)[1] == 0xff))
       
   679     {
       
   680       *encoding = HTTP_iso_10646_ucs_2;
       
   681       *byteOrder = NW_BYTEORDER_BIG_ENDIAN;
       
   682       // The order is suppose to be big-endian but check to see if it looks
       
   683       // like little-endian.
       
   684       if (((pInBuf->data)[2] != 0) && ((pInBuf->data)[3] == 0))
       
   685       {
       
   686         *byteOrder = NW_BYTEORDER_LITTLE_ENDIAN;
       
   687       }
       
   688       return NW_TRUE;
       
   689     }        
       
   690     if (((pInBuf->data)[0] == 0xff) && ((pInBuf->data)[1] == 0xfe))
       
   691     {
       
   692       *encoding = HTTP_iso_10646_ucs_2;
       
   693       *byteOrder = NW_BYTEORDER_LITTLE_ENDIAN;
       
   694       // The order is suppose to be little-endian but check to see if it looks
       
   695       // like big-endian.
       
   696       if (((pInBuf->data)[2] == 0) && ((pInBuf->data)[3] != 0))
       
   697       {
       
   698         *byteOrder = NW_BYTEORDER_BIG_ENDIAN;
       
   699       }
       
   700       return NW_TRUE;
       
   701     }
       
   702   }
       
   703 
       
   704   // Special case: content authors write a ucs-2 document but do not place BOM
       
   705   // at beginning of document. If first two chars (4 bytes) look like ucs-2
       
   706   // then set encoding to ucs-2 and check the byte-order. Note, this is not
       
   707   // exact. It looks for zero bytes followed by non-zero bytes or vice-versa.
       
   708   // It is highly probably that if these conditions are met then the contents
       
   709   // are in fact ucs-2. However, it is theoretically possible for both of the
       
   710   // first two chars to not have a zero-byte but still be ucs-2. If that were
       
   711   // to occur this logic would not be able to determine that it is ucs-2 and
       
   712   // would end up returning FALSE, indicating encoding not found.
       
   713   if (pInBuf->length >= 4)
       
   714   {
       
   715     // Check to see if it looks like big-endian ucs-2.
       
   716     if ((((pInBuf->data)[0] == 0) && ((pInBuf->data)[1] != 0)) &&
       
   717          (((pInBuf->data)[2] == 0) && ((pInBuf->data)[3] != 0)))
       
   718     {
       
   719       *encoding = HTTP_iso_10646_ucs_2;
       
   720       *byteOrder = NW_BYTEORDER_BIG_ENDIAN;
       
   721       return NW_TRUE;
       
   722     }
       
   723     // Check to see if it looks like little-endian ucs-2.
       
   724     if ((((pInBuf->data)[0] != 0) && ((pInBuf->data)[1] == 0)) &&
       
   725          (((pInBuf->data)[2] != 0) && ((pInBuf->data)[3] == 0)))
       
   726     {
       
   727       *encoding = HTTP_iso_10646_ucs_2;
       
   728       *byteOrder = NW_BYTEORDER_LITTLE_ENDIAN;
       
   729       return NW_TRUE;
       
   730     }
       
   731   }
       
   732 
       
   733   return NW_FALSE;
       
   734 }
       
   735 
       
   736 
       
   737 /* ------------------------------------------------------------------------- */
       
   738 TBrowserStatusCode
       
   739 _NW_HED_CompositeContentHandler_ConvertEncoding(NW_HED_CompositeContentHandler_t* thisObj,
       
   740                                                 NW_Uint32 foreignEncoding, 
       
   741                                                 NW_Buffer_t* inBuf, 
       
   742                                                 NW_Int32* numUnconvertible, 
       
   743                                                 NW_Int32* indexFirstUnconvertible, 
       
   744                                                 NW_Buffer_t** outBuf)                       
       
   745 {
       
   746   TBrowserStatusCode status = KBrsrSuccess;
       
   747   NW_HED_DocumentRoot_t* docRoot;
       
   748   NW_HED_AppServices_t* appServices;
       
   749 
       
   750   docRoot = (NW_HED_DocumentRoot_t*)NW_HED_DocumentNode_GetRootNode(thisObj);
       
   751   appServices = (NW_HED_AppServices_t *) NW_HED_DocumentRoot_GetAppServices(docRoot);
       
   752   status = appServices->characterConversionAPI.convertFromForeignChunk(NW_HED_DocumentRoot_GetBrowserAppCtx(docRoot), 
       
   753               foreignEncoding, inBuf, (TInt *)numUnconvertible, (TInt*)indexFirstUnconvertible, (void**)outBuf);
       
   754   if (status == KBrsrSuccess && *outBuf == NULL)
       
   755     *outBuf = inBuf;
       
   756   return status;
       
   757 }
       
   758 
       
   759 
       
   760 /* ------------------------------------------------------------------------- */
       
   761 TBrowserStatusCode
       
   762 _NW_HED_CompositeContentHandler_ComputeEncoding(NW_HED_CompositeContentHandler_t* thisObj,
       
   763                                                 NW_Url_Resp_t* response,
       
   764                                                 NW_Bool* encodingFound)
       
   765 {  
       
   766   TBrowserStatusCode status = KBrsrSuccess;
       
   767   NW_Uint16 settingEncoding = NW_Settings_GetEncoding();
       
   768   NW_Int32 index = NW_HED_CompositeContentHandler_FindCharsetFromInternalEncoding(settingEncoding);
       
   769   NW_ASSERT(encodingFound != NULL);
       
   770   NW_REQUIRED_PARAM(thisObj);
       
   771   // If the setting is not automatic, use the charset from the settings
       
   772   if (index >= 0)
       
   773   {
       
   774     response->charset = supportedCharset[index].ianaEncoding;
       
   775     *encodingFound = NW_TRUE;
       
   776   }
       
   777   else
       
   778   {
       
   779     *encodingFound = _NW_HED_CompositeContentHandler_DetectEncoding(
       
   780 	  response->body, &response->charset, &response->byteOrder);
       
   781     if (*encodingFound)
       
   782 	{
       
   783 	  NW_Settings_SetOriginalEncoding(response->charset);
       
   784 	}
       
   785   }
       
   786   
       
   787   return status;
       
   788 }
       
   789 
       
   790 // take a url repsonse, and try to find to find its charset in http header,
       
   791 // if not found, use default locale charset, if that's not supported,
       
   792 // use latin-1 as default. 
       
   793 // also set the response charset to whatever is determined
       
   794 // finally returns the index of the charset.
       
   795 static NW_Int32 findDefaultCharsetIndex(NW_Url_Resp_t * response)
       
   796 {
       
   797   NW_Int32 index = -1;
       
   798   if (response->charsetString != NULL)
       
   799   {
       
   800     index = NW_HED_CompositeContentHandler_FindCharsetFromIanaEncoding(response->charset);
       
   801   }
       
   802   if (index < 0)
       
   803   {
       
   804     // No valid http header was found, use the locale specific default
       
   805     index = NW_HED_CompositeContentHandler_FindCharsetFromInternalEncoding(NW_Settings_GetDefaultCharset());
       
   806   }
       
   807   if (index < 0)
       
   808   {
       
   809     index = NW_HED_CompositeContentHandler_FindCharsetFromInternalEncoding(HTTP_iso_8859_1);
       
   810   }
       
   811   response->charset = supportedCharset[index].ianaEncoding;
       
   812   NW_Settings_SetOriginalEncoding(response->charset);
       
   813   return index;
       
   814 }
       
   815 
       
   816 // this function serves 3 purposes: 
       
   817 // 1. when charset is found in META or XML, 
       
   818 //             charsetLength and charsetOffset not zero,
       
   819 //             (Mainly called from handle_Meta or handle_xml_charset in parser).
       
   820 // 2. when encoding is set auto, and charset not found in META or XML, 
       
   821 //             charsetLength and charsetOffset would be zero, selectedCharset should be 0;
       
   822 //             (Mainly called from BodyStart in parser).
       
   823 // 3. when encoding is set auto, and parser needs to perform the char conv based on previous found charset.
       
   824 //             charsetLength and charsetOffset would be zero, selectedCharset is not 0;
       
   825 //             also, in this case, we should expect the response->charset has been set to
       
   826 //             the correct value.
       
   827 //             (Mainly called from htmlp_to_wbxml function to perform transcoding).
       
   828 TBrowserStatusCode NW_HED_CompositeContentHandler_CharConvCB(void* context,
       
   829                                                              NW_Uint32 charsetLength,
       
   830                                                              NW_Uint32 charsetOffset,
       
   831                                                              NW_Buffer_t* body, 
       
   832                                                              NW_Int32* numUnconvertible, 
       
   833                                                              NW_Int32* indexFirstUnconvertible, 
       
   834                                                              NW_Buffer_t** outBuf,
       
   835                                                              NW_Uint32* selectedCharset)
       
   836 {
       
   837   NW_HED_CharsetConvContext* ctx = NULL;
       
   838   NW_Int32 index = -1;
       
   839   TBrowserStatusCode status = KBrsrSuccess;
       
   840   
       
   841   ctx = (NW_HED_CharsetConvContext*) context;
       
   842   NW_ASSERT(ctx != NULL);
       
   843   NW_ASSERT(ctx->contentHandler != NULL);
       
   844   NW_ASSERT(ctx->response != NULL);
       
   845   NW_ASSERT(body != NULL);
       
   846   
       
   847   if (charsetLength == 0 && charsetOffset == 0)
       
   848   {
       
   849     if (*selectedCharset == NULL)
       
   850     {
       
   851       // case 2:
       
   852       // We are here because the Encoding setting is automatic and there was no Meta tag or XML declaration
       
   853       // Look for Http header, but only if it was set by the server and we can support it,
       
   854       // if not, we'll use default encoding
       
   855       index = findDefaultCharsetIndex(ctx->response);
       
   856     }
       
   857     else
       
   858     {
       
   859       // case 3: use selectedCharset to set response->charset
       
   860       ctx->response->charset = (NW_Uint16)*selectedCharset; 
       
   861       status = _NW_HED_CompositeContentHandler_ConvertEncoding(ctx->contentHandler, ctx->response->charset, 
       
   862         body, numUnconvertible, indexFirstUnconvertible, 
       
   863         outBuf);
       
   864     }
       
   865   }
       
   866   else // case 1: find the charset from the META or XML 
       
   867   {
       
   868     index = NW_HED_CompositeContentHandler_FindCharset(body->data + charsetOffset, charsetLength);
       
   869     if (index < 0)
       
   870     {
       
   871       index = findDefaultCharsetIndex(ctx->response);
       
   872     }
       
   873     else{
       
   874       ctx->response->charset = supportedCharset[index].ianaEncoding;
       
   875     }
       
   876   }
       
   877   *selectedCharset = ctx->response->charset;
       
   878   NW_Settings_SetOriginalEncoding(ctx->response->charset);
       
   879   return status;
       
   880 }
       
   881 
       
   882 /************************************************************************
       
   883  
       
   884   Function: NW_HED_CompositeContentHandler_SaveImagesToFile
       
   885 
       
   886   Description:  Write images to a file in the form of multipart segments.
       
   887                 Each segment consists of:
       
   888                       header length (including content type length)
       
   889                       image data length
       
   890                       content type (including character encoding)
       
   891                       headers
       
   892                       image
       
   893  
       
   894   Parameters:   thisObj  - in: content handler
       
   895                 file     - in: file name
       
   896     
       
   897   Return Value: KBrsrSuccess
       
   898                 KBrsrFailure
       
   899                 KBrsrOutOfMemory
       
   900                 KBrsrSavedPageFailed
       
   901                   
       
   902 **************************************************************************/
       
   903 TBrowserStatusCode
       
   904 _NW_HED_CompositeContentHandler_SaveImagesToFile(NW_HED_CompositeContentHandler_t* thisObj,
       
   905                                                  NW_Osu_File_t fh)
       
   906 {
       
   907   TBrowserStatusCode status = KBrsrFailure;
       
   908   NW_HED_CompositeNode_t* compositeNode;
       
   909   NW_HED_ContentHandler_t* childNode;
       
   910   NW_ADT_Iterator_t* iter = NULL;
       
   911   NW_Image_Epoc32Simple_t* image = NULL;
       
   912   const NW_Byte* rawData = NULL;
       
   913   NW_Uint32 rawDataLen = 0;
       
   914   NW_Byte* segment;
       
   915   NW_Uint32 segmentLen;
       
   916   char* urlAscii = NULL;
       
   917   NW_Image_CannedImages_t     *cannedImages;
       
   918   NW_LMgr_RootBox_t           *rootBox;
       
   919   MHEDDocumentListener    *documentListener;
       
   920   NW_HED_DocumentRoot_t         *documentRoot;
       
   921         
       
   922 
       
   923   /* parameter assertion block */
       
   924   NW_ASSERT (NW_Object_IsInstanceOf (thisObj,
       
   925                                      &NW_HED_CompositeContentHandler_Class));
       
   926 
       
   927   compositeNode = (NW_HED_CompositeNode_t *)
       
   928     NW_Object_QuerySecondary (thisObj, &NW_HED_CompositeNode_Class);
       
   929   NW_ASSERT (NW_Object_IsInstanceOf (compositeNode,
       
   930                                      &NW_HED_CompositeContentHandler_CompositeNode_Class));
       
   931 
       
   932   TUint originalEncoding = NW_Settings_GetOriginalEncoding();
       
   933   
       
   934   /* Create a child iterator */
       
   935   if (thisObj != NULL)
       
   936     status = NW_HED_CompositeNode_GetChildren (compositeNode, &iter);
       
   937 
       
   938   /* If there are no children, return success status */
       
   939   if (status == KBrsrNotFound)
       
   940     return KBrsrSuccess;
       
   941   
       
   942   if (status == KBrsrSuccess)
       
   943   {
       
   944     /* Loop through the child content handlers; each contatins an image. */
       
   945     while (NW_ADT_Iterator_HasMoreElements (iter))
       
   946     {
       
   947       NW_ImageCH_Epoc32ContentHandler_t* imageCH;
       
   948 
       
   949       status = NW_ADT_Iterator_GetNextElement (iter, &childNode);
       
   950 
       
   951       if (status != KBrsrSuccess)
       
   952       {
       
   953         status = KBrsrFailure;
       
   954         break;
       
   955       }
       
   956 
       
   957       if (!NW_Object_IsClass(childNode, &NW_ImageCH_Epoc32ContentHandler_Class))
       
   958         continue;
       
   959 
       
   960       imageCH = NW_ImageCH_Epoc32ContentHandlerOf(childNode);
       
   961 
       
   962       if (imageCH->image != NULL)
       
   963       {
       
   964         if (NW_Object_IsInstanceOf(imageCH->image, &NW_Image_Virtual_Class))
       
   965           continue;
       
   966 
       
   967         image = NW_Image_Epoc32SimpleOf(imageCH->image);
       
   968         rawData = (const NW_Byte *)image->rawData;
       
   969         rawDataLen = image->rawDataLength;
       
   970       }
       
   971       else
       
   972       {        
       
   973         documentRoot =
       
   974           (NW_HED_DocumentRoot_t*) NW_HED_DocumentNode_GetRootNode (thisObj);
       
   975         NW_ASSERT(documentRoot != NULL);
       
   976         
       
   977         documentListener = documentRoot->documentListener;
       
   978         NW_ASSERT(documentListener != NULL);
       
   979         
       
   980         rootBox = documentListener->GetRootBox();
       
   981         if (rootBox==NULL) {
       
   982           return KBrsrOutOfMemory;
       
   983         }
       
   984         
       
   985         cannedImages = rootBox->cannedImages;
       
   986         NW_ASSERT(cannedImages!=NULL);
       
   987         image = NULL;
       
   988         image = (NW_Image_Epoc32Simple_t *)
       
   989           NW_Image_CannedImages_GetImage(cannedImages, NW_Image_Missing);
       
   990         NW_ASSERT(image != NULL);
       
   991 
       
   992         rawData = (const NW_Byte *)image->rawData;
       
   993         rawDataLen = image->rawDataLength;
       
   994       }
       
   995 
       
   996       /* Get response URL. If it is NULL, use it anyway. */
       
   997       if (imageCH->requestUrl)
       
   998         urlAscii = NW_Str_CvtToAscii(imageCH->requestUrl);
       
   999 
       
  1000       status = NW_CreateMultipartSegment
       
  1001                   (
       
  1002                     HTTP_iso_8859_1, // encoding - does it matter for images?
       
  1003 					originalEncoding, // used by saved foreign content loading
       
  1004                     childNode->response->contentTypeString,
       
  1005                     urlAscii,
       
  1006                     rawData,
       
  1007                     rawDataLen,
       
  1008                     &segment,
       
  1009                     &segmentLen
       
  1010                   );
       
  1011       NW_Mem_Free(urlAscii);
       
  1012       if (status != KBrsrSuccess)
       
  1013         break;
       
  1014 
       
  1015       /* write segment to file */
       
  1016       status = NW_Osu_WriteFile(fh, segment, segmentLen);
       
  1017       NW_Mem_Free(segment);
       
  1018       if (status != KBrsrSuccess)
       
  1019         break;
       
  1020     }
       
  1021     
       
  1022     NW_Object_Delete (iter);
       
  1023   }
       
  1024   return status;
       
  1025 }
       
  1026 
       
  1027 
       
  1028 /************************************************************************
       
  1029  
       
  1030   Function: NW_HED_CompositeContentHandler_GetImageCount
       
  1031 
       
  1032   Description:  Gets the number of images embedded in the document.
       
  1033   This does not include the images loaded via CSS
       
  1034  
       
  1035   Parameters:   thisObj  - in: content handler
       
  1036     
       
  1037   Return Value: Number of images
       
  1038                   
       
  1039 **************************************************************************/
       
  1040 NW_Uint32
       
  1041 NW_HED_CompositeContentHandler_GetImageCount(NW_HED_CompositeContentHandler_t* thisObj)
       
  1042 {
       
  1043   TBrowserStatusCode status = KBrsrFailure;
       
  1044   NW_HED_CompositeNode_t* compositeNode;
       
  1045   NW_HED_ContentHandler_t* childNode;
       
  1046   NW_ADT_Iterator_t* iter = NULL;
       
  1047   NW_Uint32 numImages = 0;
       
  1048 
       
  1049   /* parameter assertion block */
       
  1050   NW_ASSERT (NW_Object_IsInstanceOf (thisObj,
       
  1051                                      &NW_HED_CompositeContentHandler_Class));
       
  1052 
       
  1053   compositeNode = (NW_HED_CompositeNode_t *)
       
  1054     NW_Object_QuerySecondary (thisObj, &NW_HED_CompositeNode_Class);
       
  1055   NW_ASSERT (NW_Object_IsInstanceOf (compositeNode,
       
  1056                                      &NW_HED_CompositeContentHandler_CompositeNode_Class));
       
  1057 
       
  1058   /* Create a child iterator */
       
  1059   if (thisObj != NULL)
       
  1060     status = NW_HED_CompositeNode_GetChildren (compositeNode, &iter);
       
  1061 
       
  1062   /* If there are no children, return success status */
       
  1063   if (status == KBrsrNotFound)
       
  1064     return 0;
       
  1065   
       
  1066   if (status == KBrsrSuccess)
       
  1067   {
       
  1068     /* Loop through the child content handlers; each contatins an image. */
       
  1069     while (NW_ADT_Iterator_HasMoreElements (iter))
       
  1070     {
       
  1071       NW_ImageCH_Epoc32ContentHandler_t* imageCH;
       
  1072 
       
  1073       status = NW_ADT_Iterator_GetNextElement (iter, &childNode);
       
  1074 
       
  1075       if (status != KBrsrSuccess)
       
  1076         break;
       
  1077 
       
  1078       if (!NW_Object_IsClass(childNode, &NW_ImageCH_Epoc32ContentHandler_Class))
       
  1079         continue;
       
  1080 
       
  1081       imageCH = NW_ImageCH_Epoc32ContentHandlerOf(childNode);
       
  1082 
       
  1083       if (imageCH->image != NULL)
       
  1084       {
       
  1085         if (!NW_Object_IsInstanceOf(imageCH->image, &NW_Image_Virtual_Class))     
       
  1086           numImages++;
       
  1087       }
       
  1088     }
       
  1089   }
       
  1090   return numImages;
       
  1091 }
       
  1092 
       
  1093                                            
       
  1094 /************************************************************************
       
  1095  
       
  1096   Function: NW_HED_CompositeContentHandler_AddChild
       
  1097 
       
  1098   Description:  Add a child to the list
       
  1099  
       
  1100   Parameters:   thisObj - in: composite content handler
       
  1101                 childNode - in: child to be added
       
  1102     
       
  1103   Return Value: 
       
  1104                   
       
  1105 **************************************************************************/
       
  1106 TBrowserStatusCode
       
  1107 NW_HED_CompositeContentHandler_AddChild( NW_HED_CompositeContentHandler_t* thisObj,
       
  1108                                          NW_HED_DocumentNode_t* childNode, 
       
  1109                                          void* context )
       
  1110   {
       
  1111   NW_HED_CompositeNode_t* compositeNode;
       
  1112   
       
  1113   // parameter assertion block 
       
  1114   NW_ASSERT( NW_Object_IsInstanceOf( thisObj, &NW_HED_CompositeContentHandler_Class ) );
       
  1115   NW_ASSERT( NW_Object_IsInstanceOf( childNode, &NW_HED_ContentHandler_Class ) );
       
  1116   
       
  1117   // for convenience 
       
  1118   compositeNode = (NW_HED_CompositeNode_t *)
       
  1119     NW_Object_QuerySecondary( thisObj, &NW_HED_CompositeNode_Class );
       
  1120   
       
  1121   NW_ASSERT( NW_Object_IsInstanceOf( compositeNode,
       
  1122     &NW_HED_CompositeContentHandler_CompositeNode_Class ) );
       
  1123 
       
  1124   NW_TRY( status ) 
       
  1125     {
       
  1126     // insert the childNode into our children list
       
  1127     status = NW_HED_CompositeNode_AddChild( compositeNode, childNode, context );
       
  1128     _NW_THROW_ON_ERROR( status );
       
  1129     }
       
  1130   NW_CATCH( status ) 
       
  1131     { 
       
  1132     }
       
  1133   NW_FINALLY 
       
  1134     {
       
  1135     return status;
       
  1136     } 
       
  1137   NW_END_TRY
       
  1138   }
       
  1139 
       
  1140 /* ------------------------------------------------------------------------- *
       
  1141    protected methods
       
  1142  * ------------------------------------------------------------------------- */
       
  1143 
       
  1144 
       
  1145 /* ------------------------------------------------------------------------- *
       
  1146    NW_HED_CompositeNode methods
       
  1147  * ------------------------------------------------------------------------- */
       
  1148 
       
  1149 /* ------------------------------------------------------------------------- */
       
  1150 TBrowserStatusCode
       
  1151 _NW_HED_CompositeContentHandler_CompositeNode_AddChild (NW_HED_CompositeNode_t* compositeNode,
       
  1152                                                         NW_HED_DocumentNode_t* childNode,
       
  1153                                                         void* key)
       
  1154 {
       
  1155   /* parameter assertion block */
       
  1156   NW_ASSERT (NW_Object_IsInstanceOf (compositeNode,
       
  1157                                      &NW_HED_CompositeContentHandler_CompositeNode_Class));
       
  1158   NW_ASSERT (NW_Object_IsInstanceOf (childNode, &NW_HED_DocumentNode_Class));
       
  1159 
       
  1160   /* if the content handler is not embeddable do not add it.There is this
       
  1161      prevents nested <html> tags created inadvertently */
       
  1162   if (NW_HED_ContentHandlerOf (childNode)->isEmbeddable == NW_FALSE) {
       
  1163     return KBrsrBadInputParam;
       
  1164   }
       
  1165 
       
  1166   return _NW_HED_CompositeNode_AddChild (compositeNode, childNode, key);
       
  1167 }
       
  1168 
       
  1169 
       
  1170 /*****************************************************************
       
  1171 
       
  1172   Name:         NW_HED_CompositeContentHandler_HandleImageLoad
       
  1173 
       
  1174   Description:  If the image corresponsing to the newContentHandler
       
  1175                 (which is an ImageCH) exists more than once in the document,
       
  1176                 this function creates new ImageCH for all those other
       
  1177                 transactions and sets Virtual Image in them
       
  1178 
       
  1179   Parameters:   See below
       
  1180 
       
  1181   Return Value:
       
  1182 
       
  1183 *****************************************************************/
       
  1184 TBrowserStatusCode
       
  1185 NW_HED_CompositeContentHandler_HandleImageLoad(
       
  1186            NW_HED_CompositeContentHandler_t* thisObj,
       
  1187            NW_Int32 chunkIndex,
       
  1188 					 NW_HED_ContentHandler_t* newContentHandler,
       
  1189            NW_HED_UrlRequest_t* urlRequest )
       
  1190   {
       
  1191   // note that this function should be in a utility class instead
       
  1192   NW_TRY( status )
       
  1193     {
       
  1194     NW_ADT_Vector_Metric_t index;
       
  1195     NW_ADT_Vector_Metric_t numItems;
       
  1196     // get document root load list
       
  1197     NW_HED_DocumentRoot_t* docRoot = (NW_HED_DocumentRoot_t*)
       
  1198       _NW_HED_DocumentNode_GetRootNode( NW_HED_DocumentNodeOf( thisObj ) );
       
  1199 
       
  1200     // handle unlikely error cases
       
  1201     NW_THROW_ON_NULL( newContentHandler, status, KBrsrUnexpectedError );
       
  1202     NW_THROW_ON_NULL( newContentHandler->response, status, KBrsrUnexpectedError );
       
  1203 
       
  1204     numItems = NW_ADT_Vector_GetSize( docRoot->loadList );
       
  1205     index = numItems;
       
  1206 
       
  1207     while (index > 0)
       
  1208       {
       
  1209       NW_HED_DocumentRoot_LoadContext_t *entry = NULL;
       
  1210 
       
  1211       index--;
       
  1212       entry = *(NW_HED_DocumentRoot_LoadContext_t**)
       
  1213         NW_ADT_Vector_ElementAt( docRoot->loadList, index );
       
  1214 
       
  1215       NW_ASSERT( entry );
       
  1216       // find all the corresponding virtual entries.
       
  1217       if( ( entry ) && ( entry->virtualRequest == NW_TRUE ) &&
       
  1218           ( entry->transactionId == newContentHandler->response->transId ) )
       
  1219         {
       
  1220         NW_ImageCH_Epoc32ContentHandler_t* virtualHandler = NULL;
       
  1221 
       
  1222         // first chunk. let's create the virtual image content handler
       
  1223         if( chunkIndex == 0 )
       
  1224           {
       
  1225           // clone image handler
       
  1226           status = NW_ImageCH_Epoc32ContentHandler_GetVirtualHandler(
       
  1227             NW_HED_DocumentNodeOf( thisObj ), urlRequest,
       
  1228             NW_ImageCH_Epoc32ContentHandlerOf( newContentHandler ), &virtualHandler );
       
  1229           // check only OOM
       
  1230           NW_THROW_ON( KBrsrOutOfMemory, status );
       
  1231 
       
  1232           if( virtualHandler &&
       
  1233               NW_HED_CompositeContentHandler_AddChild( NW_HED_CompositeContentHandlerOf( thisObj ),
       
  1234                    NW_HED_DocumentNodeOf( virtualHandler ), entry->clientData ) == KBrsrSuccess )
       
  1235             {
       
  1236             // set the context
       
  1237             virtualHandler->context = entry->clientData;
       
  1238             }
       
  1239           else
       
  1240             {
       
  1241             // if the virtual content handler is either NULL or could not be added to the child list
       
  1242             // then erase and set it to NULL.
       
  1243             NW_Object_Delete( virtualHandler );
       
  1244             virtualHandler = NULL;
       
  1245             // release entry
       
  1246             NW_Mem_Free( entry );
       
  1247             // remove it from the list
       
  1248             NW_ADT_DynamicVector_RemoveAt( docRoot->loadList, index );
       
  1249             // catch OOM only
       
  1250             NW_THROW_ON( KBrsrOutOfMemory, status );
       
  1251             }
       
  1252           // jump to the next candidate
       
  1253           }
       
  1254         // last chunk, load complete
       
  1255         else if( chunkIndex == -1 )
       
  1256           {
       
  1257           NW_HED_CompositeNode_t* compositeNode;
       
  1258 
       
  1259           // look up the child list to get the virtual content handler
       
  1260           compositeNode = (NW_HED_CompositeNode_t*)
       
  1261             (NW_Object_QueryAggregate( thisObj, &NW_HED_CompositeNode_Class));
       
  1262           NW_ASSERT( compositeNode != NULL );
       
  1263 
       
  1264           virtualHandler = (NW_ImageCH_Epoc32ContentHandler_t*)
       
  1265             NW_HED_CompositeNode_LookupChild( compositeNode, entry->clientData );
       
  1266 
       
  1267           if( virtualHandler )
       
  1268             {
       
  1269             status = NW_HED_DocumentNode_Initialize( NW_HED_DocumentNodeOf( virtualHandler ), KBrsrSuccess );
       
  1270             // catch OOM only
       
  1271             NW_THROW_ON( KBrsrOutOfMemory, status );
       
  1272             }
       
  1273           NW_Mem_Free( entry );
       
  1274           // load complet. remove virtual item from the loadList
       
  1275           status = NW_ADT_DynamicVector_RemoveAt( docRoot->loadList, index );
       
  1276           // catch OOM only
       
  1277           NW_THROW_ON( KBrsrOutOfMemory, status );
       
  1278           }
       
  1279         else
       
  1280           {
       
  1281           // only the first chunk and the load complete should
       
  1282           // be passed to the function
       
  1283           NW_ASSERT( NW_TRUE );
       
  1284           }
       
  1285         }
       
  1286       }
       
  1287     }
       
  1288   NW_CATCH( status )
       
  1289     {
       
  1290     }
       
  1291   NW_FINALLY
       
  1292     {
       
  1293     return status;
       
  1294     }
       
  1295   NW_END_TRY
       
  1296   }
       
  1297 
       
  1298 /* ------------------------------------------------------------------------- */
       
  1299 /* NW_HED_CompositeContentHandler_CreateContentHandler
       
  1300  *
       
  1301  * Creates non top level content handler for a given context
       
  1302  * Parameters:
       
  1303  *  image:     this object
       
  1304  */
       
  1305 NW_HED_ContentHandler_t*
       
  1306 NW_HED_CompositeContentHandler_CreateContentHandler( NW_HED_ContentHandler_t* thisObj,
       
  1307                                             NW_Uint8* contentTypeString, NW_HED_UrlRequest_t* urlRequest, 
       
  1308                                             NW_Url_Resp_t* response, void* clientData )
       
  1309            
       
  1310   {
       
  1311   NW_HED_ContentHandler_t* newContentHandler;
       
  1312   NW_HED_DocumentRoot_t* docRoot;
       
  1313 
       
  1314   // parameter assertion block 
       
  1315   NW_ASSERT( thisObj != NULL );
       
  1316   NW_ASSERT( urlRequest != NULL );
       
  1317   NW_ASSERT( contentTypeString != NULL );
       
  1318 
       
  1319   // it musn't be top level request
       
  1320   NW_ASSERT( NW_HED_UrlRequest_IsTopLevelRequest( urlRequest ) != NW_TRUE );
       
  1321 
       
  1322   docRoot = (NW_HED_DocumentRoot_t*)
       
  1323     _NW_HED_DocumentNode_GetRootNode( NW_HED_DocumentNodeOf( thisObj ) );
       
  1324 
       
  1325     newContentHandler = NW_HED_MimeTable_CreateContentHandler( docRoot->mimeTable, NW_HED_DocumentNodeOf( thisObj ), 
       
  1326       contentTypeString, urlRequest, response, NW_FALSE );
       
  1327   
       
  1328   // if this is null we don't support the content-type of the response 
       
  1329   if( newContentHandler != NULL )
       
  1330     {
       
  1331     TBrowserStatusCode status;
       
  1332     // add content handler to the children list
       
  1333     status = NW_HED_CompositeContentHandler_AddChild( NW_HED_CompositeContentHandlerOf( thisObj ), 
       
  1334       NW_HED_DocumentNodeOf( newContentHandler ), clientData );   
       
  1335 
       
  1336     // the content handler initalized successfully set "contentHandler" 
       
  1337     if( status != KBrsrSuccess )
       
  1338       {
       
  1339       // delete the bogus content handler
       
  1340       NW_Object_Delete( newContentHandler );      
       
  1341       newContentHandler = NULL;
       
  1342       }
       
  1343     }
       
  1344   return newContentHandler;
       
  1345   }
       
  1346 
       
  1347 
       
  1348 // check if any body part has the same url as the one passed in
       
  1349 // if it does, return true, set aBodyPart to the body part 
       
  1350 // else, return false
       
  1351 TBool
       
  1352 _NW_HED_CompositeContentHandler_IsUrlInMultipart( NW_HED_CompositeContentHandler_t* thisObj,
       
  1353                                                   const NW_Ucs2* aUrl,
       
  1354                                                   CBodyPart** aBodyPart )
       
  1355     {
       
  1356     TInt32 bodyPartLen;
       
  1357 
       
  1358     if( thisObj->iMultipart )
       
  1359         {
       
  1360         TInt size = thisObj->iBodyPartArray.Count();
       
  1361         TInt i;
       
  1362         TInt32 len = NW_Str_Strlen( aUrl );
       
  1363         for (i = 0; i < size; i++)
       
  1364             {
       
  1365             CBodyPart* bodyPart = thisObj->iBodyPartArray[i];
       
  1366             NW_Ucs2* bodyPartUrl = (NW_Ucs2*)( bodyPart->Url().Ptr() );
       
  1367 
       
  1368             if( bodyPartUrl )
       
  1369                 {
       
  1370                 bodyPartLen = NW_Str_Strlen( bodyPartUrl );
       
  1371 
       
  1372                 if( bodyPartLen == len )
       
  1373                     {
       
  1374                     if( NW_Str_Strcmp( bodyPartUrl, aUrl ) == 0 )
       
  1375                         {
       
  1376                         //aBodyPart = &bodyPart;
       
  1377                         *aBodyPart = bodyPart;
       
  1378                         return ETrue;
       
  1379                         }
       
  1380                     // else: continue loop
       
  1381                     }
       
  1382                 // else: continue loop
       
  1383                 }
       
  1384             // else: continue loop
       
  1385             }
       
  1386         }
       
  1387     // else: return false
       
  1388 
       
  1389     return EFalse;
       
  1390     }
       
  1391