Logo Search packages:      
Sourcecode: galeon version File versions

EventContext.cpp

/*
 *  Copyright (C) 2000 Marco Pesenti Gritti
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "EventContext.h"
#include "GaleonWrapper.h"
#include "GaleonUtils.h"
#include "GulString.h"

#include <nsIInterfaceRequestorUtils.h>
#include <nsIDOMEventTarget.h>
#include <nsIInterfaceRequestor.h>
#include <nsIDOMElement.h>
#include <nsIDOMWindow.h>
#include <nsIDOMXULDocument.h>
#include <nsIURI.h>
#include <nsIDOMNSEvent.h>
#include <nsIDOMNSHTMLElement.h>
#include <nsIDOMCharacterData.h>
#include <nsIDOMHTMLButtonElement.h>
#include <nsIDOMHTMLLabelElement.h>
#include <nsIDOMHTMLLegendElement.h>
#include <nsIDOMHTMLTextAreaElement.h>
#include <nsIDOMHTMLImageElement.h>
#include <nsIDOMHTMLInputElement.h>
#include <nsIDOMHTMLObjectElement.h>
#include <nsIDOMHTMLAnchorElement.h>
#include <nsIDOMHTMLAreaElement.h>
#include <nsIDOMViewCSS.h>
#include <nsIDOMDocumentView.h>
#include <nsIDOMAbstractView.h>
#include <nsIDOMNodeList.h>
#include <nsIDOMCSSPrimitiveValue.h>
#include <nsIDOMCSSStyleDeclaration.h>
#include <nsIDOMCSSValue.h>
#include <nsIDOMDocument.h>
#include <nsIDOMEventTarget.h>
#include <nsIDOMMouseEvent.h>
#include <nsIDOMKeyEvent.h>
#include <nsIServiceManager.h>
#include <nsITextToSubURI.h>
#include <nsIWebBrowser.h>
#include <nsISelection.h>
#include <nsIDOM3Node.h>
#include <nsMemory.h>

#include <gdk/gdkkeysyms.h>

EventContext::EventContext ()
{
}

EventContext::~EventContext ()
{
}

nsresult EventContext::Init (GaleonWrapper *wrapper)
{
      mWrapper = wrapper;
      mDOMDocument = nsnull;

      return NS_OK;
}

nsresult EventContext::Unescape (const nsACString &aEscaped, nsAString &aUnescaped)
{
        if (!aEscaped.Length()) return NS_ERROR_FAILURE;

      NS_ENSURE_TRUE (mWrapper, NS_ERROR_FAILURE);

        nsCOMPtr<nsITextToSubURI> escaper
                (do_CreateInstance ("@mozilla.org/intl/texttosuburi;1"));
        NS_ENSURE_TRUE (escaper, NS_ERROR_FAILURE);

      nsresult rv;
      GulCString encoding;
      rv = mWrapper->GetEncoding (encoding);
        NS_ENSURE_SUCCESS (rv, rv);
      
        return escaper->UnEscapeNonAsciiURI (encoding, aEscaped, aUnescaped);
}

nsresult EventContext::GetEventContext (nsIDOMEventTarget *EventTarget,
                              GaleonEmbedEvent *info)
{
      nsresult rv;

      mEmbedEvent = info;

      info->context = EMBED_CONTEXT_DOCUMENT;

      nsCOMPtr<nsIDOMNode> node = do_QueryInterface(EventTarget, &rv);
      if (NS_FAILED(rv) || !node) return NS_ERROR_FAILURE;

        /* Is page xul ? then do not display context menus
       * FIXME I guess there is an easier way ... */
      /* From philipl: This test needs to be here otherwise we
       * arrogantly assume we can QI to a HTMLElement, which is
       * not true for xul content. */ 

      nsCOMPtr<nsIDOMDocument> domDoc;
      rv = node->GetOwnerDocument(getter_AddRefs(domDoc));
      if (NS_FAILED(rv) || !domDoc) return NS_ERROR_FAILURE;

      mDOMDocument = domDoc;

      nsCOMPtr<nsIDOMXULDocument> xul_document = do_QueryInterface(domDoc);
      if (xul_document)
      {
            info->context = EMBED_CONTEXT_NONE;
            return NS_ERROR_FAILURE;
      }

      // Now we know that the page isn't a xul window, we can try and
      // do something useful with it.
      
      // Get the selected text in the document, if any
      nsCOMPtr<nsIDOMWindow> domWindow;
      rv = mWrapper->GetDOMWindow(getter_AddRefs(domWindow));
      if (NS_SUCCEEDED(rv))
      {
            nsCOMPtr<nsISelection> selection;
            rv = domWindow->GetSelection(getter_AddRefs(selection));
            if (NS_SUCCEEDED(rv))
            {
                  PRUnichar * selText;
                  rv = selection->ToString (&selText);
                  if (NS_SUCCEEDED(rv) && selText)
                  {
                        SetStringProperty ("selection", GulString (selText));
                        nsMemory::Free (selText);
                  }
            }
      }

      PRUint16 type;
      rv = node->GetNodeType(&type);
      if (NS_FAILED(rv)) return NS_ERROR_FAILURE;

      PRBool has_background = PR_FALSE;

      nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(node);
      if ((nsIDOMNode::ELEMENT_NODE == type) && element)
      {
            GulString uTag;
            rv = element->GetLocalName(uTag);
            if (NS_FAILED(rv)) return NS_ERROR_FAILURE;

            GulCString tag (uTag);
            if (tag.EqualsAsciiIgnoreCase("img"))
            {
                  info->context |= EMBED_CONTEXT_IMAGE;

                  GulString img;
                  nsCOMPtr <nsIDOMHTMLImageElement> image = 
                                    do_QueryInterface(node, &rv);
                  if (NS_FAILED(rv) || !image) return NS_ERROR_FAILURE;             

                  rv = image->GetSrc (img);
                  if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
                  SetStringProperty ("image", img);

                  rv = image->GetAlt (img);
                  if (NS_SUCCEEDED(rv))
                  {
                        SetStringProperty ("image_alt", img);     
                  }

                  rv = image->GetLongDesc (img);
                  if (NS_SUCCEEDED(rv) && !img.IsEmpty())
                  {
                        GulCString imglongdesc;
                        rv = ResolveBaseURL (img, imglongdesc);
                        if (NS_FAILED (rv)) return NS_ERROR_FAILURE;

                        SetStringProperty ("image_long_desc",
                                       imglongdesc.get());
                  }

                  int imgwidth, imgheight;
                  rv = image->GetWidth (&imgwidth);
                  rv = image->GetHeight (&imgheight);
                  SetIntProperty ("image_width", imgwidth);
                  SetIntProperty ("image_height", imgheight);

                  rv = element->GetTitle (img);
                        if (NS_SUCCEEDED(rv))
                  {
                        SetStringProperty ("image_title",
                                       img);
                  }
            }
            else if (tag.EqualsAsciiIgnoreCase("input"))
            {
                  CheckInput (node);                  
            }
            else if (tag.EqualsAsciiIgnoreCase("textarea"))
            {
                  info->context |= EMBED_CONTEXT_INPUT;
            }
            else if (tag.EqualsAsciiIgnoreCase("object"))
            {
                  nsCOMPtr<nsIDOMHTMLObjectElement> object;
                  object = do_QueryInterface (node);
                  if (!element) return NS_ERROR_FAILURE;

                  GulString value;
                  object->GetType(value);

                  GulCString cValue = value;

                  // MIME types are always lower case
                  if (cValue.StartsWith("image/"))
                  {
                        info->context |= EMBED_CONTEXT_IMAGE;
                        
                        GulString img;
                        
                        rv = object->GetData (img);
                        if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
                        
                        GulCString cImg;
                        rv = ResolveBaseURL (img, cImg);
                        if (NS_FAILED (rv)) return NS_ERROR_FAILURE;

                        SetStringProperty ("image", cImg.get());
                  }
                  else
                  {
                        info->context = EMBED_CONTEXT_NONE;
                        return NS_OK;
                  }
            }
            else if (tag.EqualsAsciiIgnoreCase("html"))
            {
                  /* Clicked on part of the page without a <body>, so
                   * look for a background image in the body tag */
                  nsCOMPtr<nsIDOMNodeList> nodeList;

                  rv = mDOMDocument->GetElementsByTagName (NS_LITERAL_STRING ("body"),
                                                 getter_AddRefs (nodeList));
                  if (NS_SUCCEEDED (rv) && nodeList)
                  {
                        nsCOMPtr<nsIDOMNode> bodyNode;
                        nodeList->Item (0, getter_AddRefs (bodyNode));

                        GulString cssurl;
                        rv = GetCSSBackground (bodyNode, cssurl);
                        if (NS_SUCCEEDED (rv))
                        {
                              GulCString bgimg;
                              rv = ResolveBaseURL (cssurl, bgimg);
                              if (NS_FAILED (rv))
                                    return NS_ERROR_FAILURE;

                              SetStringProperty ("background_image",
                                             bgimg.get());
                              has_background = TRUE;
                        }
                  }
            }
      }

      /* Is page framed ? */
      PRBool framed;
      IsPageFramed (node, &framed);
      SetIntProperty ("framed_page", framed);

      /* Bubble out, looking for items of interest */
      while (node)
      {
            nsCOMPtr <nsIDOMElement> dom_elem = do_QueryInterface(node);
            if (dom_elem)
            {
                  NS_NAMED_LITERAL_STRING(nspace, "http://www.w3.org/1999/xlink");
                  NS_NAMED_LITERAL_STRING(localname_type, "type");

                  GulString value;
                  dom_elem->GetAttributeNS (nspace, localname_type, value);
                  
                  GulCString cValue = value;
                  if (cValue.EqualsAsciiIgnoreCase ("simple"))
                  {
                        info->context |= EMBED_CONTEXT_LINK;
                        NS_NAMED_LITERAL_STRING (localname_href, "href");
                        dom_elem->GetAttributeNS (nspace, localname_href, value);
                        
                        SetStringProperty ("link", value);
                        CheckLinkScheme (value);
                  }
            }

            PRUint16 type;
            rv = node->GetNodeType(&type);
            if (NS_FAILED(rv)) return NS_ERROR_FAILURE;

            element = do_QueryInterface(node);
            if ((nsIDOMNode::ELEMENT_NODE == type) && element)
            {
                  GulString uTag;
                  rv = element->GetLocalName(uTag);
                  if (NS_FAILED(rv)) return NS_ERROR_FAILURE;

                  GulCString tag = uTag;

                  /* Link */
                  if (tag.EqualsAsciiIgnoreCase("a"))
                  {
                        GulString tmp;

                        rv = GatherTextUnder (node, tmp);
                        if (NS_SUCCEEDED(rv))
                                    SetStringProperty ("link_text", tmp);

                        nsCOMPtr <nsIDOMHTMLAnchorElement> anchor =
                              do_QueryInterface(node);
                        anchor->GetHref (tmp);

                        GulCString href = tmp;
                        if (href.StartsWith ("mailto:"))
                        {
                              href.Cut (0, 7);

                              // Chop off any extra parameters
                              char *str = g_strdup (href.get());
                              g_strdelimit (str, "?", '\0');

                              GulString unescapedHref;
                              rv = Unescape (GulDependentCString (str), unescapedHref);
                              if (NS_SUCCEEDED (rv) && unescapedHref.Length())
                              {
                                    SetStringProperty ("email", unescapedHref);
                                    info->context |= EMBED_CONTEXT_EMAIL_LINK;
                              }
                              g_free (str);
                        }
                        
                        if (anchor && !tmp.IsEmpty()) 
                        {
                              info->context |= EMBED_CONTEXT_LINK;

                              SetStringProperty ("link", tmp);
                              CheckLinkScheme (tmp);
                              rv = anchor->GetHreflang (tmp);
                              if (NS_SUCCEEDED(rv))
                                    SetStringProperty ("link_lang", tmp);
                              rv = anchor->GetTarget (tmp);
                              if (NS_SUCCEEDED(rv))
                                    SetStringProperty ("link_target", tmp);
                              rv = anchor->GetRel (tmp);
                              if (NS_SUCCEEDED(rv))
                                    SetStringProperty ("link_rel", tmp);
                              rv = anchor->GetRev (tmp);
                              if (NS_SUCCEEDED(rv))
                                    SetStringProperty ("link_rev", tmp);
                              rv = element->GetTitle (tmp);
                                    if (NS_SUCCEEDED(rv))
                                    SetStringProperty ("link_title", tmp);
                              rv = anchor->GetType (tmp);
                              if (NS_SUCCEEDED(rv))
                                    SetStringProperty ("link_type", tmp);

                              GulCString linkType = tmp;

                              if (linkType.EqualsAsciiIgnoreCase("text/smartbookmark"))
                              {
                                    SetIntProperty ("link_is_smart", TRUE);
                                    
                                    nsCOMPtr<nsIDOMNode> childNode;
                                    node->GetFirstChild (getter_AddRefs(childNode));
                                    if (childNode)
                                    {
                                          nsCOMPtr <nsIDOMHTMLImageElement> image = 
                                                do_QueryInterface(childNode, &rv);

                                          if (image)
                                          {
                                                GulString img;
                                                rv = image->GetSrc (img);
                                                if (!NS_FAILED(rv))
                                                {
                                                      SetStringProperty ("image", img);
                                                }
                                          }
                                    }
                              }
                              else
                              {
                                    SetIntProperty ("link_is_smart", FALSE);
                              }
                        }
                  
                  }
                  else if (tag.EqualsAsciiIgnoreCase("option"))
                  {
                        info->context = EMBED_CONTEXT_NONE;
                        return NS_OK;
                  }
                  else if (tag.EqualsAsciiIgnoreCase("area"))
                  {
                        info->context |= EMBED_CONTEXT_LINK;
                        nsCOMPtr <nsIDOMHTMLAreaElement> area =
                                    do_QueryInterface(node, &rv);
                        if (NS_SUCCEEDED(rv) && area)
                        {
                              GulString href;
                              rv = area->GetHref (href);
                              if (NS_FAILED(rv))
                                    return NS_ERROR_FAILURE;
                              
                              SetStringProperty ("link", href);
                              CheckLinkScheme (href);
                        }
                  }
                  else if (tag.EqualsAsciiIgnoreCase("input"))
                  {
                        CheckInput (node);
                  }
                  else if (tag.EqualsAsciiIgnoreCase("textarea"))
                  {
                        info->context |= EMBED_CONTEXT_INPUT;
                  }

                  if (!has_background)
                  {
                        GulString cssurl;
                        rv = GetCSSBackground (node, cssurl);
                        if (NS_SUCCEEDED (rv))
                        {
                              GulCString bgimg;
                              rv = ResolveBaseURL (cssurl, bgimg);
                              if (NS_FAILED (rv))
                                    return NS_ERROR_FAILURE;

                              SetStringProperty ("background_image",
                                             bgimg.get());
                              has_background = TRUE;
                        }
                  }
            }
            
            nsCOMPtr<nsIDOMNode> parentNode;
            node->GetParentNode (getter_AddRefs(parentNode));
            node = parentNode;
      }
      
      return NS_OK;
}

nsresult EventContext::GetCSSBackground (nsIDOMNode *node, nsAString& url)
{
      nsresult rv;

      nsCOMPtr<nsIDOMDocumentView> docView = do_QueryInterface (mDOMDocument);
      if (!docView) return NS_ERROR_FAILURE;

      nsCOMPtr<nsIDOMAbstractView> abstractView;
      rv = docView->GetDefaultView (getter_AddRefs (abstractView));
      if (NS_FAILED (rv)) return rv;

      nsCOMPtr<nsIDOMViewCSS> viewCSS = do_QueryInterface (abstractView);
      if (!viewCSS) return NS_ERROR_FAILURE;
      
      nsCOMPtr<nsIDOMElement> element = do_QueryInterface (node);
      if (!element) return NS_ERROR_FAILURE;

      nsCOMPtr<nsIDOMCSSStyleDeclaration> decl;
      rv = viewCSS->GetComputedStyle (element, NS_LITERAL_STRING(""),
                                  getter_AddRefs (decl));
      if (NS_FAILED (rv)) return rv;

      nsCOMPtr<nsIDOMCSSValue> CSSValue;
      decl->GetPropertyCSSValue (NS_LITERAL_STRING ("background-image"),
                           getter_AddRefs (CSSValue));
      if (!CSSValue) return NS_ERROR_FAILURE;

      nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue = 
            do_QueryInterface (CSSValue);
      if (!primitiveValue) return NS_ERROR_FAILURE;
      
      PRUint16 type;
      rv = primitiveValue->GetPrimitiveType (&type);
      if (NS_FAILED (rv)) return rv;

      if (type != nsIDOMCSSPrimitiveValue::CSS_URI)
            return NS_ERROR_FAILURE;

      rv = primitiveValue->GetStringValue (url);
      if (NS_FAILED (rv)) return rv;

      return NS_OK;
}

nsresult EventContext::GetTargetCoords (nsIDOMEventTarget *aTarget, PRInt32 *aX, PRInt32 *aY)
{
      /* Calculate the node coordinates relative to the widget origin */
      nsCOMPtr<nsIDOMNSHTMLElement> elem = do_QueryInterface(aTarget);

      PRInt32 x = 0, y = 0;
      while (elem)
      {
            PRInt32 val;
            elem->GetOffsetTop(&val);     y += val;
            elem->GetScrollTop(&val);     y -= val;
            elem->GetOffsetLeft(&val);    x += val;
            elem->GetScrollLeft(&val);    x -= val;

            nsCOMPtr<nsIDOMElement> parent;
            elem->GetOffsetParent(getter_AddRefs(parent));
            elem = do_QueryInterface(parent);
      }
      *aX = x;
      *aY = y;

      return NS_OK;
}


nsresult EventContext::GetMouseEventInfo (nsIDOMMouseEvent *aMouseEvent, GaleonEmbedEvent *info)
{
      nsresult result;

      info->keycode = 0;

      // casting 32-bit guint* to PRUint16* below will break on big-endian
      PRUint16 btn = 500;
      aMouseEvent->GetButton (&btn);

      /* Mozilla's buttons are 0 = left, 1 = middle, 2 = right,
       * gtk is 1 = left, 2 = middle, 3 = right */
      switch (btn)
      {
            case 0:
              case 1:
              case 2:
                  info->mouse_button = btn+1;
            break;

#ifdef HAVE_BROKEN_CTX_MENU_EVENT
            /* This only appears to happen when getting a mouse context menu
             * signal, so map it to button 3 (right mouse button)
             * - http://bugzilla.mozilla.org/show_bug.cgi?id=258193 */
              case 500: 
                  info->mouse_button = 3;
            break;
#endif

            case (PRUint16) -1:
                  /* when the user submits a form with Return, mozilla synthesises
                   * a _mouse_ click event with btn=65535 (-1).
                   */
                  info->mouse_button = 0;
            break;

            default:
                  g_warning ("Unknown mouse button: %d", (int)btn);
                  info->mouse_button = 0;
      }


      nsCOMPtr<nsIDOMEventTarget> EventTarget;
      result = aMouseEvent->GetTarget(getter_AddRefs(EventTarget));
      if (NS_FAILED(result) || !EventTarget) return NS_ERROR_FAILURE;

      if (info->mouse_button)
      {
            // OTOH, casting only between (un)signedness is safe
            aMouseEvent->GetScreenX ((PRInt32*)&info->x);
            aMouseEvent->GetScreenY ((PRInt32*)&info->y);
      } else {
            GetTargetCoords (EventTarget, (PRInt32*)&info->x,
                         (PRInt32*)&info->y);
      }

      /* be sure we are not clicking on the scrollbars */
      nsCOMPtr<nsIDOMNSEvent> nsEvent = do_QueryInterface(aMouseEvent, &result);
      if (NS_FAILED(result) || !nsEvent) return NS_ERROR_FAILURE;

      nsCOMPtr<nsIDOMEventTarget> OriginalTarget;
      result = nsEvent->GetOriginalTarget(getter_AddRefs(OriginalTarget));
      if (NS_FAILED(result) || !OriginalTarget) return NS_ERROR_FAILURE;

      nsCOMPtr<nsIDOMNode> OriginalNode = do_QueryInterface(OriginalTarget);
      if (!OriginalNode) return NS_ERROR_FAILURE;

      GulString nodename;
      OriginalNode->GetNodeName(nodename);

      GulCString cNodeName = nodename;

      if (cNodeName.StartsWith ("xul:") &&
          (cNodeName.EqualsAsciiIgnoreCase ("xul:scrollbarbutton") ||
           cNodeName.EqualsAsciiIgnoreCase ("xul:thumb") ||
           cNodeName.EqualsAsciiIgnoreCase ("xul:vbox")  ||
           cNodeName.EqualsAsciiIgnoreCase ("xul:spacer") ||
           cNodeName.EqualsAsciiIgnoreCase ("xul:slider")))
            return NS_ERROR_FAILURE;

      result = GetEventContext (EventTarget, info);
      if (NS_FAILED(result)) return result;

      /* Get the modifier */

      PRBool mod_key;

      info->modifier = 0;

      aMouseEvent->GetAltKey(&mod_key);
      if (mod_key) info->modifier |= GDK_MOD1_MASK;

      aMouseEvent->GetShiftKey(&mod_key);
      if (mod_key) info->modifier |= GDK_SHIFT_MASK;

      aMouseEvent->GetMetaKey(&mod_key);
      if (mod_key) info->modifier |= GDK_MOD2_MASK;
      
      aMouseEvent->GetCtrlKey(&mod_key);
      if (mod_key) info->modifier |= GDK_CONTROL_MASK;

      return NS_OK;
}

nsresult EventContext::GetKeyEventInfo (nsIDOMKeyEvent *aKeyEvent, GaleonEmbedEvent *info)
{
      nsresult rv;

      info->mouse_button = 0;

      PRUint32 keyCode;
      rv = aKeyEvent->GetKeyCode(&keyCode);
      if (NS_FAILED(rv)) return rv;
      info->keycode = keyCode;

      nsCOMPtr<nsIDOMEventTarget> target;
      rv = aKeyEvent->GetTarget(getter_AddRefs(target));
      if (NS_FAILED(rv) || !target) return NS_ERROR_FAILURE;
      
      rv = GetTargetCoords (target, (PRInt32*)&info->x, (PRInt32*)&info->y);
      NS_ENSURE_SUCCESS (rv, rv);

      /* Context */
      rv = GetEventContext (target, info);
      if (NS_FAILED(rv)) return rv;

      /* Get the modifier */

      PRBool mod_key;

      info->modifier = 0;

      aKeyEvent->GetAltKey(&mod_key);
      if (mod_key) info->modifier |= GDK_MOD1_MASK;

      aKeyEvent->GetShiftKey(&mod_key);
      if (mod_key) info->modifier |= GDK_SHIFT_MASK;

      aKeyEvent->GetMetaKey(&mod_key);
      if (mod_key) info->modifier |= GDK_MOD2_MASK;
      
      aKeyEvent->GetCtrlKey(&mod_key);
      if (mod_key) info->modifier |= GDK_CONTROL_MASK;

      return NS_OK;
}

nsresult EventContext::IsPageFramed (nsIDOMNode *node, PRBool *Framed)
{
      nsresult result;
      
      nsCOMPtr<nsIDOMDocument> mainDocument;
      result = mWrapper->GetMainDOMDocument (getter_AddRefs(mainDocument));
      if (NS_FAILED(result) || !mainDocument) return NS_ERROR_FAILURE;
      
      nsCOMPtr<nsIDOMDocument> nodeDocument;
      result = node->GetOwnerDocument (getter_AddRefs(nodeDocument));
      if (NS_FAILED(result) || !nodeDocument) return NS_ERROR_FAILURE;
 
      *Framed = (mainDocument != nodeDocument);

        return NS_OK;
}

nsresult EventContext::GetTargetDocument (nsIDOMDocument **domDoc)
{
      if (!mDOMDocument) return NS_ERROR_FAILURE;

      *domDoc = mDOMDocument.get();

      NS_IF_ADDREF(*domDoc);

      return NS_OK;
}

nsresult EventContext::CheckInput (nsIDOMNode *aNode)
{
      const PRUnichar typeLiteral[] = { 't', 'y', 'p', 'e', '\0' };

      nsCOMPtr<nsIDOMElement> element;
      element = do_QueryInterface (aNode);
      if (!element) return NS_ERROR_FAILURE;

      GulString uValue;
      element->GetAttribute (GulString(typeLiteral), uValue);

      GulCString value = uValue;

      if (value.EqualsAsciiIgnoreCase ("image"))
      {
            mEmbedEvent->context |= EMBED_CONTEXT_IMAGE;
            nsCOMPtr<nsIDOMHTMLInputElement> input;
            input = do_QueryInterface (aNode);
            if (!input) return NS_ERROR_FAILURE;

            nsresult rv;
            GulString img;
            rv = input->GetSrc (img);
            if (NS_FAILED(rv)) return NS_ERROR_FAILURE;

            GulCString cImg;
            rv = ResolveBaseURL (img, cImg);
            if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
            SetStringProperty ("image", cImg.get());
      }
      else if (!value.EqualsAsciiIgnoreCase ("radio") &&
             !value.EqualsAsciiIgnoreCase ("submit") &&
             !value.EqualsAsciiIgnoreCase ("reset") &&
             !value.EqualsAsciiIgnoreCase ("hidden") &&
             !value.EqualsAsciiIgnoreCase ("button") &&
             !value.EqualsAsciiIgnoreCase ("checkbox"))
      {
            mEmbedEvent->context |= EMBED_CONTEXT_INPUT;
      }

      return NS_OK;
}

nsresult EventContext::CheckLinkScheme (const nsAString &link)
{
      nsCOMPtr<nsIURI> uri;
      GaleonUtils::NewURI (getter_AddRefs (uri), link);
      if (!uri) return NS_ERROR_FAILURE;

      nsresult rv;
      GulCString scheme;
      rv = uri->GetScheme (scheme);
      if (NS_FAILED (rv)) return NS_ERROR_FAILURE;

      if (scheme.EqualsAsciiIgnoreCase ("http")  ||
          scheme.EqualsAsciiIgnoreCase ("https") ||
          scheme.EqualsAsciiIgnoreCase ("ftp")   ||
          scheme.EqualsAsciiIgnoreCase ("file")  ||
          scheme.EqualsAsciiIgnoreCase ("about") ||
          scheme.EqualsAsciiIgnoreCase ("data")  ||
          scheme.EqualsAsciiIgnoreCase ("resource")  ||
          scheme.EqualsAsciiIgnoreCase ("gopher"))
      {
            SetIntProperty ("link-can-open-in-new-tab", TRUE);
      }
      return NS_OK;
}


nsresult EventContext::GatherTextUnder (nsIDOMNode* aNode, nsAString& aResult)
{
      GulString text;
      nsCOMPtr<nsIDOMNode> node;
      aNode->GetFirstChild(getter_AddRefs(node));
      PRUint32 depth = 1;

      while (node && depth)
      {
            nsCOMPtr<nsIDOMCharacterData> charData(do_QueryInterface(node));
            PRUint16 nodeType;

            node->GetNodeType(&nodeType);
            if (charData && nodeType == nsIDOMNode::TEXT_NODE)
            {
                  /* Add this text to our collection. */
                  text += ' ';
                  GulString data;
                  charData->GetData(data);
                  text += data;
            }
            else
            {
                  nsCOMPtr<nsIDOMHTMLImageElement> img(do_QueryInterface(node));
                  if (img)
                  {
                        GulString altText;
                        img->GetAlt(altText);
                        if (altText.Length())
                        {
                              text = altText;
                              break;
                        }
                  }
            }

            /* Find the next node to test. */
            PRBool hasChildNodes;
            node->HasChildNodes(&hasChildNodes);
            if (hasChildNodes)
            {
                  nsCOMPtr<nsIDOMNode> temp = node;
                  temp->GetFirstChild(getter_AddRefs(node));
                  depth++;
            }
            else
            {
                  nsCOMPtr<nsIDOMNode> nextSibling;
                  node->GetNextSibling(getter_AddRefs(nextSibling));
                  if (nextSibling)
                  {
                        node = nextSibling;
                  }
                  else
                  {
                        nsCOMPtr<nsIDOMNode> parentNode;
                        node->GetParentNode(getter_AddRefs(parentNode));
                        if (!parentNode)
                        {
                              node = nsnull;
                        }
                        else
                        {
                              parentNode->GetNextSibling(getter_AddRefs(nextSibling));
                              node = nextSibling;
                              depth--;
                        }
                  }
            }
      }

      /* FIXME we should trim spaces here */

      aResult = text;

      return NS_OK;
}
      
nsresult EventContext::SetIntProperty (const char *name, int value)
{

      GValue *val = g_new0 (GValue, 1);

      g_value_init (val, G_TYPE_INT);
      
      g_value_set_int (val, value);

      galeon_embed_event_set_property (mEmbedEvent, name, val);

      return NS_OK;
}

nsresult EventContext::SetStringProperty (const char *name, const char *value)
{
      GValue *val = g_new0 (GValue, 1);

      g_value_init (val, G_TYPE_STRING);
      
      g_value_set_string (val, value);
                   
      galeon_embed_event_set_property (mEmbedEvent, name, val);

      return NS_OK;
}

nsresult EventContext::SetStringProperty (const char *name, const nsAString &value)
{
      return SetStringProperty (name, GulCString (value).get());
}

nsresult EventContext::ResolveBaseURL (const nsAString &relurl, nsACString &url)
{
      nsresult rv;

      nsCOMPtr<nsIDOM3Node> node(do_QueryInterface (mDOMDocument));
      GulString spec;
      node->GetBaseURI (spec);

      nsCOMPtr<nsIURI> base;
      rv = GaleonUtils::NewURI (getter_AddRefs(base), spec);
      if (!base) return NS_ERROR_FAILURE;

      return base->Resolve (GulCString (relurl), url);
}

Generated by  Doxygen 1.6.0   Back to index