Back to index

lightning-sunbird  0.9+nobinonly
Public Types | Public Member Functions | Protected Member Functions | Private Member Functions | Private Attributes
nsMetaCharsetObserver Class Reference

#include <nsMetaCharsetObserver.h>

Inheritance diagram for nsMetaCharsetObserver:
Inheritance graph
[legend]
Collaboration diagram for nsMetaCharsetObserver:
Collaboration graph
[legend]

List of all members.

Public Types

enum  { IS_DOCUMENT_WRITE = 1U }

Public Member Functions

 nsMetaCharsetObserver ()
virtual ~nsMetaCharsetObserver ()
NS_IMETHOD Notify (PRUint32 aDocumentID, eHTMLTags aTag, PRUint32 numOfAttributes, const PRUnichar *nameArray[], const PRUnichar *valueArray[])
NS_IMETHOD Notify (PRUint32 aDocumentID, const PRUnichar *aTag, PRUint32 numOfAttributes, const PRUnichar *nameArray[], const PRUnichar *valueArray[])
NS_IMETHOD Notify (nsISupports *aWebShell, nsISupports *aChannel, const PRUnichar *aTag, const nsStringArray *keys, const nsStringArray *values, const PRUint32 aFlags)
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER NS_IMETHOD 
Start ()
NS_IMETHOD End ()
void observe (in nsISupports aSubject, in string aTopic, in wstring aData)
 Observe will be called when there is a notification for the topic |aTopic|.

Protected Member Functions

NS_IMETHOD NotifyWebShell (nsISupports *aWebShell, nsISupports *aChannel, const char *charset, PRInt32 source)

Private Member Functions

NS_IMETHOD Notify (PRUint32 aDocumentID, PRUint32 numOfAttributes, const PRUnichar *nameArray[], const PRUnichar *valueArray[])
NS_IMETHOD Notify (nsISupports *aWebShell, nsISupports *aChannel, const nsStringArray *keys, const nsStringArray *values)
NS_IMETHOD GetCharsetFromCompatibilityTag (const nsStringArray *keys, const nsStringArray *values, nsAString &aCharset)

Private Attributes

nsCOMPtr< nsICharsetAliasmAlias
PRBool bMetaCharsetObserverStarted

Detailed Description

Definition at line 52 of file nsMetaCharsetObserver.h.


Member Enumeration Documentation

anonymous enum [inherited]
Enumerator:
IS_DOCUMENT_WRITE 

Definition at line 63 of file nsIElementObserver.h.


Constructor & Destructor Documentation

Definition at line 66 of file nsMetaCharsetObserver.cpp.

{
  bMetaCharsetObserverStarted = PR_FALSE;
  nsresult res;
  mAlias = nsnull;
  nsCOMPtr<nsICharsetAlias> calias(do_GetService(kCharsetAliasCID, &res));
  if(NS_SUCCEEDED(res)) {
     mAlias = calias;
  }
}

Here is the call graph for this function:

Definition at line 77 of file nsMetaCharsetObserver.cpp.

{
}

Member Function Documentation

Implements nsIMetaCharsetService.

Definition at line 421 of file nsMetaCharsetObserver.cpp.

{
  nsresult rv = NS_OK;
  if (bMetaCharsetObserverStarted == PR_TRUE)  {
    bMetaCharsetObserverStarted = PR_FALSE;

    nsCOMPtr<nsIParserService> parserService(do_GetService(NS_PARSERSERVICE_CONTRACTID, &rv));

    if (NS_FAILED(rv))
      return rv;
    
    rv = parserService->UnregisterObserver(this, NS_LITERAL_STRING("text/html"));
  }
  return rv;
}

Here is the call graph for this function:

NS_IMETHODIMP nsMetaCharsetObserver::GetCharsetFromCompatibilityTag ( const nsStringArray *  keys,
const nsStringArray *  values,
nsAString &  aCharset 
) [private]

Definition at line 334 of file nsMetaCharsetObserver.cpp.

{
    if (!mAlias)
        return NS_ERROR_ABORT;

    aCharset.Truncate(0);
    nsresult res = NS_OK;


    // support for non standard case for compatibility
    // e.g. <META charset="ISO-8859-1">
    PRInt32 numOfAttributes = keys->Count();
    if ((numOfAttributes >= 3) &&
        (keys->StringAt(0)->LowerCaseEqualsLiteral("charset")))
    {
      nsAutoString srcStr((values->StringAt(numOfAttributes-2))->get());
      PRInt32 err;
      PRInt32  src = srcStr.ToInteger(&err);
      // if we cannot convert the string into PRInt32, return error
      if (NS_FAILED(err))
          return NS_ERROR_ILLEGAL_VALUE;
      
      // current charset have a lower priority
      if (kCharsetFromMetaTag > src)
      {
          nsCAutoString newCharset;
          newCharset.AssignWithConversion(values->StringAt(0)->get());
          
          nsCAutoString preferred;
          res = mAlias->GetPreferred(newCharset,
                                     preferred);
          if (NS_SUCCEEDED(res))
          {
              // compare against the current charset, 
              // also some charsets which should have been found in
              // the BOM detection.
              nsString* currentCharset = values->StringAt(numOfAttributes-3);
              if (!preferred.Equals(NS_LossyConvertUCS2toASCII(*currentCharset)) &&
                  !preferred.EqualsLiteral("UTF-16") &&
                  !preferred.EqualsLiteral("UTF-16BE") &&
                  !preferred.EqualsLiteral("UTF-16LE") &&
                  !preferred.EqualsLiteral("UTF-32BE") &&
                  !preferred.EqualsLiteral("UTF-32LE"))
                  AppendASCIItoUTF16(preferred, aCharset);
          }
      }
    }

  return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP nsMetaCharsetObserver::Notify ( PRUint32  aDocumentID,
eHTMLTags  aTag,
PRUint32  numOfAttributes,
const PRUnichar nameArray[],
const PRUnichar valueArray[] 
) [virtual]

Implements nsIElementObserver.

Definition at line 107 of file nsMetaCharsetObserver.cpp.

{
    if(eHTMLTag_meta != aTag) 
        return NS_ERROR_ILLEGAL_VALUE;
    else 
        return Notify(aDocumentID, numOfAttributes, nameArray, valueArray);
}

Here is the caller graph for this function:

NS_IMETHOD nsMetaCharsetObserver::Notify ( PRUint32  aDocumentID,
const PRUnichar aTag,
PRUint32  numOfAttributes,
const PRUnichar nameArray[],
const PRUnichar valueArray[] 
) [virtual]

Implements nsIElementObserver.

NS_IMETHODIMP nsMetaCharsetObserver::Notify ( nsISupports *  aWebShell,
nsISupports *  aChannel,
const PRUnichar aTag,
const nsStringArray *  keys,
const nsStringArray *  values,
const PRUint32  aFlags 
) [virtual]

Implements nsIElementObserver.

Definition at line 136 of file nsMetaCharsetObserver.cpp.

{
  nsresult result = NS_OK;
  // bug 125317 - document.write content is already an unicode content.
  if (!(aFlags & nsIElementObserver::IS_DOCUMENT_WRITE)) {
    if(!nsDependentString(aTag).LowerCaseEqualsLiteral("meta")) {
        result = NS_ERROR_ILLEGAL_VALUE;
    }
    else {
        result = Notify(aWebShell, aChannel, keys, values);
    }
  }
  return result;
}

Here is the call graph for this function:

NS_IMETHODIMP nsMetaCharsetObserver::Notify ( PRUint32  aDocumentID,
PRUint32  numOfAttributes,
const PRUnichar nameArray[],
const PRUnichar valueArray[] 
) [private]

Definition at line 120 of file nsMetaCharsetObserver.cpp.

{
   nsDeque keys(0);
   nsDeque values(0);
   PRUint32 i;
   for(i=0;i<numOfAttributes;i++)
   {
       keys.Push((void*)nameArray[i]);
       values.Push((void*)valueArray[i]);
   }
   return NS_OK;//Notify((nsISupports*)aDocumentID, &keys, &values);
}
NS_IMETHODIMP nsMetaCharsetObserver::Notify ( nsISupports *  aWebShell,
nsISupports *  aChannel,
const nsStringArray *  keys,
const nsStringArray *  values 
) [private]

Definition at line 159 of file nsMetaCharsetObserver.cpp.

{
    NS_PRECONDITION(keys!=nsnull && values!=nsnull,"Need key-value pair");

    PRInt32 numOfAttributes = keys->Count();
    NS_ASSERTION( numOfAttributes == values->Count(), "size mismatch");
    nsresult res=NS_OK;
#ifdef DEBUG

    PRUnichar Uxcommand[]={'X','_','C','O','M','M','A','N','D','\0'};
    PRUnichar UcharsetSource[]={'c','h','a','r','s','e','t','S','o','u','r','c','e','\0'};
    PRUnichar Ucharset[]={'c','h','a','r','s','e','t','\0'};
    
    NS_ASSERTION(numOfAttributes >= 3, "should have at least 3 private attribute");
    NS_ASSERTION(0==nsCRT::strcmp(Uxcommand,(keys->StringAt(numOfAttributes-1))->get()),"last name should be 'X_COMMAND'" );
    NS_ASSERTION(0==nsCRT::strcmp(UcharsetSource,(keys->StringAt(numOfAttributes-2))->get()),"2nd last name should be 'charsetSource'" );
    NS_ASSERTION(0==nsCRT::strcmp(Ucharset,(keys->StringAt(numOfAttributes-3))->get()),"3rd last name should be 'charset'" );

#endif
    NS_ASSERTION(mAlias, "Didn't get nsICharsetAlias in constructor");

    if(nsnull == mAlias)
      return NS_ERROR_ABORT;

    // we need at least 5 - HTTP-EQUIV, CONTENT and 3 private
    if(numOfAttributes >= 5 ) 
    {
      const PRUnichar *charset = (values->StringAt(numOfAttributes-3))->get();
      const PRUnichar *source =  (values->StringAt(numOfAttributes-2))->get();
      PRInt32 err;
      nsAutoString srcStr(source);
      PRInt32  src = srcStr.ToInteger(&err);
      // if we cannot convert the string into PRInt32, return error
      NS_ASSERTION(NS_SUCCEEDED(err), "cannot get charset source");
      if(NS_FAILED(err))
          return NS_ERROR_ILLEGAL_VALUE;

      if(kCharsetFromMetaTag <= src)
          return NS_OK; // current charset has higher priority. don't bother to do the following

      PRInt32 i;
      const PRUnichar *httpEquivValue=nsnull;
      const PRUnichar *contentValue=nsnull;
      const PRUnichar *charsetValue=nsnull;

      for(i=0;i<(numOfAttributes-3);i++)
      {
        const PRUnichar *keyStr;
        keyStr = (keys->StringAt(i))->get();

        //Change 3.190 in nsHTMLTokens.cpp allow  ws/tab/cr/lf exist before 
        // and after text value, this need to be skipped before comparison
        while(IS_SPACE_CHARS(*keyStr)) 
          keyStr++;

        if(Substring(keyStr, keyStr+10).LowerCaseEqualsLiteral("http-equiv"))
              httpEquivValue = values->StringAt(i)->get();
        else if(Substring(keyStr, keyStr+7).LowerCaseEqualsLiteral("content"))
              contentValue = values->StringAt(i)->get();
        else if (Substring(keyStr, keyStr+7).LowerCaseEqualsLiteral("charset"))
              charsetValue = values->StringAt(i)->get();
      }
      NS_NAMED_LITERAL_STRING(contenttype, "Content-Type");
      NS_NAMED_LITERAL_STRING(texthtml, "text/html");

      if(nsnull == httpEquivValue || nsnull == contentValue)
        return NS_OK;

      while(IS_SPACE_CHARS(*httpEquivValue))
        ++httpEquivValue;
      // skip opening quote
      if (*httpEquivValue == '\'' || *httpEquivValue == '\"')
        ++httpEquivValue;

      while(IS_SPACE_CHARS(*contentValue))
        ++contentValue;
      // skip opening quote
      if (*contentValue == '\'' || *contentValue == '\"')
        ++contentValue;

      if(
         Substring(httpEquivValue,
                   httpEquivValue+contenttype.Length()).Equals(contenttype,
                                                               nsCaseInsensitiveStringComparator())
         &&
         Substring(contentValue,
                   contentValue+texthtml.Length()).Equals(texthtml,
                                                          nsCaseInsensitiveStringComparator())
        )
      {

         nsCAutoString newCharset;

         if (nsnull == charsetValue) 
         {
           nsAutoString contentPart1(contentValue+9); // after "text/html"
           PRInt32 start = contentPart1.RFind("charset=", PR_TRUE ) ;
           PRInt32 end = contentPart1.Length();
           if(kNotFound != start)
           {
             start += 8; // 8 = "charset=".length 
             while (start < end && contentPart1.CharAt(start) == PRUnichar(' '))
               ++start;
             if (start < end) {
               end = contentPart1.FindCharInSet("\'\"; ", start);
               if(kNotFound == end ) 
                 end = contentPart1.Length();
               NS_ASSERTION(end>=start, "wrong index");
               LossyCopyUTF16toASCII(Substring(contentPart1, start, end-start),
                                     newCharset);
             }
           } 
         }
         else   
         {
             LossyCopyUTF16toASCII(nsDependentString(charsetValue), newCharset);
         } 

         nsCAutoString charsetString; charsetString.AssignWithConversion(charset);
         
         if (!newCharset.IsEmpty())
         {    
             if(! newCharset.Equals(charsetString, nsCaseInsensitiveCStringComparator()))
             {
                 PRBool same = PR_FALSE;
                 nsresult res2 = mAlias->Equals( newCharset, charsetString , &same);
                 if(NS_SUCCEEDED(res2) && (! same))
                 {
                     nsCAutoString preferred;
                     res2 = mAlias->GetPreferred(newCharset, preferred);
                     if(NS_SUCCEEDED(res2))
                     {
                        // following charset should have been detected by parser
                        if (!preferred.EqualsLiteral("UTF-16") &&
                            !preferred.EqualsLiteral("UTF-16BE") &&
                            !preferred.EqualsLiteral("UTF-16LE") &&
                            !preferred.EqualsLiteral("UTF-32BE") &&
                            !preferred.EqualsLiteral("UTF-32LE")) {
                          // Propagate the error message so that the parser can
                          // shutdown correctly. - Ref. Bug 96440
                          res = NotifyWebShell(aWebShell,
                                               aChannel,
                                               preferred.get(),
                                               kCharsetFromMetaTag);
                        }
                     } // if(NS_SUCCEEDED(res)
                 }
             }
             else {
               res = NS_HTMLPARSER_VALID_META_CHARSET;
             } // if EqualIgnoreCase 
         } // if !newCharset.IsEmpty()
      } // if
    }
    else
    {
      nsAutoString compatCharset;
      if (NS_SUCCEEDED(GetCharsetFromCompatibilityTag(keys, values, compatCharset)))
      {
        if (!compatCharset.IsEmpty()) {
          res = NotifyWebShell(aWebShell,
                               aChannel,
                               NS_ConvertUCS2toUTF8(compatCharset).get(), 
                               kCharsetFromMetaTag);
        }
      }
    }
    return res;
}

Here is the call graph for this function:

NS_IMETHODIMP nsObserverBase::NotifyWebShell ( nsISupports *  aWebShell,
nsISupports *  aChannel,
const char *  charset,
PRInt32  source 
) [protected, inherited]

Definition at line 49 of file nsObserverBase.cpp.

{

   nsresult rv  = NS_OK;
   nsresult res = NS_OK;

   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel,&res));
   if (NS_SUCCEEDED(res)) {
     nsCAutoString method;
     httpChannel->GetRequestMethod(method);
     if (method.EqualsLiteral("POST")) { // XXX What about PUT, etc?
       return NS_OK;
     }
   }

   nsCOMPtr<nsIWebShellServices> wss;
   wss = do_QueryInterface(aWebShell,&res);
   if (NS_SUCCEEDED(res)) {

#ifndef DONT_INFORM_WEBSHELL
     // ask the webshellservice to load the URL
     if (NS_FAILED( res = wss->SetRendering(PR_FALSE) ))
       rv = res;

     // XXX nisheeth, uncomment the following two line to see the reent problem

     else if (NS_FAILED(res = wss->StopDocumentLoad())){
             rv = wss->SetRendering(PR_TRUE); // turn on the rendering so at least we will see something.
     }
     else if (NS_FAILED(res = wss->ReloadDocument(charset, source))) {
             rv = wss->SetRendering(PR_TRUE); // turn on the rendering so at least we will see something.
     }
     else {
       rv = NS_ERROR_HTMLPARSER_STOPPARSING; // We're reloading a new document...stop loading the current.
     }
#endif
   }

   //if our reload request is not accepted, we should tell parser to go on
  if (rv != NS_ERROR_HTMLPARSER_STOPPARSING) 
    rv = NS_ERROR_HTMLPARSER_CONTINUE;

  return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsIObserver::observe ( in nsISupports  aSubject,
in string  aTopic,
in wstring  aData 
) [inherited]

Observe will be called when there is a notification for the topic |aTopic|.

This assumes that the object implementing this interface has been registered with an observer service such as the nsIObserverService.

If you expect multiple topics/subjects, the impl is responsible for filtering.

You should not modify, add, remove, or enumerate notifications in the implemention of observe.

Parameters:
aSubject: Notification specific interface pointer.
aTopic: The notification topic or subject.
aData: Notification specific wide string. subject event.

Implements nsIMetaCharsetService.

Definition at line 401 of file nsMetaCharsetObserver.cpp.

{
  nsresult rv = NS_OK;

  if (bMetaCharsetObserverStarted == PR_FALSE)  {
    bMetaCharsetObserverStarted = PR_TRUE;

    nsCOMPtr<nsIParserService> parserService(do_GetService(NS_PARSERSERVICE_CONTRACTID, &rv));

    if (NS_FAILED(rv))
      return rv;

    rv = parserService->RegisterObserver(this,
                                         NS_LITERAL_STRING("text/html"),
                                         gWatchTags);
  }

  return rv;
}

Here is the call graph for this function:


Member Data Documentation

Definition at line 108 of file nsMetaCharsetObserver.h.

Definition at line 106 of file nsMetaCharsetObserver.h.


The documentation for this class was generated from the following files: