/*
* Copyright (C) 2000-2004 Marco Pesenti Gritti
* Copyright (C) 2003, 2004 Christian Persch
*
* 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.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "EventContext.h"
#include "nsIDOMEventTarget.h"
#include "nsIDocument.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsIDOMHTMLObjectElement.h"
#include "nsIInterfaceRequestor.h"
#include "nsIDOMHTMLImageElement.h"
#include "nsIDOMElement.h"
#include "nsIDOMXULDocument.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsIDOMNSDocument.h"
#include "nsReadableUtils.h"
#include "nsGUIEvent.h"
#include "nsIDOMNSEvent.h"
#include "nsIDOMCharacterData.h"
#include "nsIDOMHTMLButtonElement.h"
#include "nsIDOMHTMLLabelElement.h"
#include "nsIDOMHTMLLegendElement.h"
#include "nsIDOMHTMLTextAreaElement.h"
#include <gdk/gdkkeysyms.h>
#include "nsIPrivateDOMEvent.h"
#include "nsIDOMNSUIEvent.h"
#define KEY_CODE 256
EventContext::EventContext ()
{
}
EventContext::~EventContext ()
{
}
nsresult EventContext::Init (EphyBrowser *browser)
{
mBrowser = browser;
mDOMDocument = nsnull;
return NS_OK;
}
nsresult EventContext::GatherTextUnder (nsIDOMNode* aNode, nsString& aResult)
{
nsAutoString 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 += NS_LITERAL_STRING(" ");
nsAutoString data;
charData->GetData(data);
text += data;
}
else
{
nsCOMPtr<nsIDOMHTMLImageElement> img(do_QueryInterface(node));
if (img)
{
nsAutoString altText;
img->GetAlt(altText);
if (!altText.IsEmpty())
{
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
{
nsCOMPtr<nsIDOMNode> nextSibling;
parentNode->GetNextSibling(getter_AddRefs(nextSibling));
node = nextSibling;
depth--;
}
}
}
}
text.CompressWhitespace();
aResult = text;
return NS_OK;
}
nsresult EventContext::ResolveBaseURL (nsIDocument *doc, const nsAString &relurl, nsACString &url)
{
nsresult rv;
#if MOZILLA_SNAPSHOT > 13
nsIURI *base;
base = doc->GetBaseURI ();
if (!base) return NS_ERROR_FAILURE;
#elif MOZILLA_SNAPSHOT > 11
nsIURI *base;
base = doc->GetBaseURL ();
if (!base) return NS_ERROR_FAILURE;
#endif
return base->Resolve (NS_ConvertUTF16toUTF8(relurl), url);
}
nsresult EventContext::ResolveDocumentURL (nsIDocument *doc, const nsAString &relurl, nsACString &url)
{
nsresult rv;
#if MOZILLA_SNAPSHOT > 13
nsIURI *uri;
uri = doc->GetDocumentURI ();
if (!uri) return NS_ERROR_FAILURE;
#elif MOZILLA_SNAPSHOT > 11
nsIURI *uri;
uri = doc->GetDocumentURL ();
if (!uri) return NS_ERROR_FAILURE;
#endif
return uri->Resolve (NS_ConvertUTF16toUTF8(relurl), url);
}
nsresult EventContext::GetEventContext (nsIDOMEventTarget *EventTarget,
MozillaEmbedEvent *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<nsIDocument> doc = do_QueryInterface(domDoc, &rv);
if (NS_FAILED(rv) || !doc) return NS_ERROR_FAILURE;
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.
PRUint16 type;
rv = node->GetNodeType(&type);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(node);
if ((nsIDOMNode::ELEMENT_NODE == type) && element)
{
nsAutoString tag;
rv = element->GetTagName(tag);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
if (tag.EqualsIgnoreCase("img"))
{
info->context |= EMBED_CONTEXT_IMAGE;
nsAutoString 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())
{
nsCAutoString imglongdesc;
rv = ResolveDocumentURL (doc, img, imglongdesc);
SetStringProperty ("image_long_desc",
NS_ConvertUTF8toUTF16(imglongdesc));
}
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.EqualsIgnoreCase("input"))
{
nsCOMPtr<nsIDOMElement> element;
element = do_QueryInterface (node);
if (!element) return NS_ERROR_FAILURE;
NS_NAMED_LITERAL_STRING(attr, "type");
nsAutoString value;
element->GetAttribute (attr, value);
if (value.EqualsIgnoreCase("image"))
{
info->context |= EMBED_CONTEXT_IMAGE;
nsCOMPtr<nsIDOMHTMLInputElement> input;
input = do_QueryInterface (node);
if (!input) return NS_ERROR_FAILURE;
nsAutoString img;
rv = input->GetSrc (img);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsCAutoString cImg;
rv = ResolveDocumentURL (doc, img, cImg);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
SetStringProperty ("image",
NS_ConvertUTF8toUTF16(cImg));
}
else if (!value.EqualsIgnoreCase("radio") &&
!value.EqualsIgnoreCase("submit") &&
!value.EqualsIgnoreCase("reset") &&
!value.EqualsIgnoreCase("hidden") &&
!value.EqualsIgnoreCase("button") &&
!value.EqualsIgnoreCase("checkbox"))
{
info->context |= EMBED_CONTEXT_INPUT;
}
}
else if (tag.EqualsIgnoreCase("textarea"))
{
info->context |= EMBED_CONTEXT_INPUT;
}
else if (tag.EqualsIgnoreCase("object"))
{
nsCOMPtr<nsIDOMHTMLObjectElement> object;
object = do_QueryInterface (node);
if (!element) return NS_ERROR_FAILURE;
nsAutoString value;
object->GetType(value);
// MIME types are always lower case
if (Substring (value, 0, 6).Equals(NS_LITERAL_STRING("image/")))
{
info->context |= EMBED_CONTEXT_IMAGE;
nsAutoString img;
rv = object->GetData (img);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsCAutoString cImg;
rv = ResolveDocumentURL (doc, img, cImg);
if (NS_FAILED (rv)) return NS_ERROR_FAILURE;
SetStringProperty ("image", cImg.get());
}
else
{
info->context = EMBED_CONTEXT_NONE;
return NS_OK;
}
}
}
/* 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");
nsAutoString value;
dom_elem->GetAttributeNS (nspace, localname_type, value);
if (value.EqualsIgnoreCase("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)
{
nsAutoString tag;
rv = element->GetTagName(tag);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
/* Link */
if (tag.EqualsIgnoreCase("a"))
{
nsAutoString tmp;
nsAutoString substr;
rv = GatherTextUnder (node, tmp);
if (NS_SUCCEEDED(rv))
SetStringProperty ("linktext", tmp);
nsCOMPtr <nsIDOMHTMLAnchorElement> anchor =
do_QueryInterface(node);
anchor->GetHref (tmp);
substr.Assign (Substring (tmp, 0, 7));
if (substr.EqualsIgnoreCase("mailto:"))
{
info->context |= EMBED_CONTEXT_EMAIL_LINK;
const nsAString &address = Substring(tmp, 7, tmp.Length()-7);
SetStringProperty ("email", address);
}
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);
if (tmp.EqualsIgnoreCase("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)
{
nsAutoString img;
rv = image->GetSrc (img);
if (!NS_FAILED(rv))
{
SetStringProperty ("image", img);
}
}
}
}
else
{
SetIntProperty ("link_is_smart", FALSE);
}
}
}
else if (tag.EqualsIgnoreCase("option"))
{
info->context = EMBED_CONTEXT_NONE;
return NS_OK;
}
if (tag.EqualsIgnoreCase("area"))
{
info->context |= EMBED_CONTEXT_LINK;
nsCOMPtr <nsIDOMHTMLAreaElement> area =
do_QueryInterface(node, &rv);
if (NS_SUCCEEDED(rv) && area)
{
nsAutoString href;
rv = area->GetHref (href);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
SetStringProperty ("link", href);
CheckLinkScheme (href);
}
}
else if (tag.EqualsIgnoreCase("textarea") ||
tag.EqualsIgnoreCase("input"))
{
info->context |= EMBED_CONTEXT_INPUT;
}
nsCOMPtr<nsIDOMElement> domelement;
domelement = do_QueryInterface (node);
if (!domelement) return NS_ERROR_FAILURE;
PRBool has_background = PR_FALSE;
NS_NAMED_LITERAL_STRING(attr, "background");
nsAutoString value;
domelement->GetAttribute (attr, value);
if (!value.IsEmpty())
{
nsCAutoString bgimg;
rv = ResolveDocumentURL (doc, value, bgimg);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
SetStringProperty ("background_image", bgimg.get());
}
else
{
nsCOMPtr<nsIDOMHTMLBodyElement> bgelement;
bgelement = do_QueryInterface (node);
if (bgelement)
{
nsAutoString value;
bgelement->GetBackground (value);
if (!value.IsEmpty())
{
nsCAutoString bgimg;
rv = ResolveBaseURL (doc, value, bgimg);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
SetStringProperty ("background_image",
bgimg.get());
has_background = PR_TRUE;
}
}
}
if (!has_background)
{
nsAutoString cssurl;
rv = GetCSSBackground (node, cssurl);
if (NS_SUCCEEDED (rv))
{
nsCAutoString bgimg;
rv = ResolveBaseURL (doc, cssurl, bgimg);
if (NS_FAILED (rv))
return NS_ERROR_FAILURE;
SetStringProperty ("background_image",
bgimg.get());
if (NS_FAILED (rv))
return NS_ERROR_FAILURE;
}
}
}
nsCOMPtr<nsIDOMNode> parentNode;
node->GetParentNode (getter_AddRefs(parentNode));
node = parentNode;
}
return NS_OK;
}
nsresult EventContext::GetCSSBackground (nsIDOMNode *node, nsAutoString& url)
{
nsresult result;
nsCOMPtr<nsIDOMElementCSSInlineStyle> style;
style = do_QueryInterface (node);
if (!style) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMCSSStyleDeclaration> decl;
result = style->GetStyle (getter_AddRefs(decl));
if (NS_FAILED(result)) return NS_ERROR_FAILURE;
nsAutoString value;
NS_NAMED_LITERAL_STRING(prop_bgi, "background-image");
decl->GetPropertyValue (prop_bgi, value);
if (value.IsEmpty())
{
NS_NAMED_LITERAL_STRING(prop_bg, "background");
decl->GetPropertyValue (prop_bg, value);
if (value.IsEmpty())
{
NS_NAMED_LITERAL_STRING(prop_bgr, "background-repeat");
decl->GetPropertyValue (prop_bgr, value);
if (value.IsEmpty())
return NS_ERROR_FAILURE;
}
}
PRInt32 start, end;
nsAutoString cssurl;
NS_NAMED_LITERAL_STRING(startsub, "url(");
NS_NAMED_LITERAL_STRING(endsub, ")");
start = value.Find (startsub) + 4;
end = value.Find (endsub);
if (start == -1 || end == -1)
return NS_ERROR_FAILURE;
url.Assign(Substring (value, start, end - start));
return NS_OK;
}
nsresult EventContext::GetMouseEventInfo (nsIDOMMouseEvent *aMouseEvent, MozillaEmbedEvent *info)
{
nsresult result;
/* casting 32-bit guint* to PRUint16* below will break on big-endian */
PRUint16 btn;
aMouseEvent->GetButton (&btn);
switch (btn)
{
case 0:
info->type = EPHY_EMBED_EVENT_MOUSE_BUTTON1;
break;
case 1:
info->type = EPHY_EMBED_EVENT_MOUSE_BUTTON2;
break;
case 2:
info->type = EPHY_EMBED_EVENT_MOUSE_BUTTON3;
break;
default:
g_warning ("Unknown mouse button");
}
/* OTOH, casting only between (un)signedness is safe */
aMouseEvent->GetScreenX ((PRInt32*)&info->x);
aMouseEvent->GetScreenY ((PRInt32*)&info->y);
/* be sure we are not clicking on the scroolbars */
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;
nsAutoString nodename;
OriginalNode->GetNodeName(nodename);
if (nodename.EqualsIgnoreCase("xul:scrollbarbutton") ||
nodename.EqualsIgnoreCase("xul:thumb") ||
nodename.EqualsIgnoreCase("xul:vbox") ||
nodename.EqualsIgnoreCase("xul:spacer") ||
nodename.EqualsIgnoreCase("xul:slider"))
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMEventTarget> EventTarget;
result = aMouseEvent->GetTarget(getter_AddRefs(EventTarget));
if (NS_FAILED(result) || !EventTarget) 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, MozillaEmbedEvent *info)
{
nsresult rv;
info->type = EPHY_EMBED_EVENT_KEY;
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;
/* Calculate the node coordinates relative to the widget origin */
nsCOMPtr<nsIDOMNSHTMLElement> elem = do_QueryInterface(target, &rv);
if (NS_FAILED(rv)) return rv;
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, &rv);
}
info->x = x;
info->y = y;
/* 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 = mBrowser->GetDocument (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::CheckLinkScheme (const nsAString &link)
{
nsCOMPtr<nsIURI> uri;
NS_NewURI (getter_AddRefs (uri), link);
if (!uri) return NS_ERROR_FAILURE;
nsresult rv;
nsCAutoString scheme;
rv = uri->GetScheme (scheme);
if (NS_FAILED (rv)) return NS_ERROR_FAILURE;
if (scheme.EqualsIgnoreCase ("http") ||
scheme.EqualsIgnoreCase ("https") ||
scheme.EqualsIgnoreCase ("ftp") ||
scheme.EqualsIgnoreCase ("file") ||
scheme.EqualsIgnoreCase ("data") ||
scheme.EqualsIgnoreCase ("resource") ||
scheme.EqualsIgnoreCase ("about") ||
scheme.EqualsIgnoreCase ("gopher"))
{
SetIntProperty ("link-has-web-scheme", TRUE);
}
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);
mozilla_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);
mozilla_embed_event_set_property (mEmbedEvent, name, val);
return NS_OK;
}
nsresult EventContext::SetStringProperty (const char *name, const nsAString &value)
{
return SetStringProperty (name, NS_ConvertUTF16toUTF8(value).get());
}