/* * Copyright (C) 2000-2004 Marco Pesenti Gritti * Copyright (C) 2003, 2004 Christian Persch * Copyright (C) 2004 Crispin Flowerday * * 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$ */ #include "mozilla-config.h" #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef ALLOW_PRIVATE_API #include #include #include #include #include #include #endif #include "ephy-debug.h" #include "EphyBrowser.h" #include "EphyUtils.h" #include "EventContext.h" #define KEY_CODE 256 EventContext::EventContext () { LOG ("EventContext ctor [%p]", this); } EventContext::~EventContext () { LOG ("EventContext dtor [%p]", this); } nsresult EventContext::Init (EphyBrowser *browser) { mBrowser = browser; mDOMDocument = nsnull; return NS_OK; } nsresult EventContext::GatherTextUnder (nsIDOMNode* aNode, nsAString& aResult) { nsString text; nsCOMPtr node; aNode->GetFirstChild(getter_AddRefs(node)); PRUint32 depth = 1; while (node && depth) { nsCOMPtr charData(do_QueryInterface(node)); PRUint16 nodeType; node->GetNodeType(&nodeType); if (charData && nodeType == nsIDOMNode::TEXT_NODE) { /* Add this text to our collection. */ text += ' '; nsString data; charData->GetData(data); text += data; } else { nsCOMPtr img(do_QueryInterface(node)); if (img) { nsString altText; img->GetAlt(altText); if (altText.Length()) { text = altText; break; } } } /* Find the next node to test. */ PRBool hasChildNodes; node->HasChildNodes(&hasChildNodes); if (hasChildNodes) { nsCOMPtr temp = node; temp->GetFirstChild(getter_AddRefs(node)); depth++; } else { nsCOMPtr nextSibling; node->GetNextSibling(getter_AddRefs(nextSibling)); if (nextSibling) { node = nextSibling; } else { nsCOMPtr 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; } /* FIXME: we should resolve against the element's base, not the document's base */ nsresult EventContext::ResolveBaseURL (const nsAString &relurl, nsACString &url) { nsCString cRelURL; NS_UTF16ToCString (relurl, NS_CSTRING_ENCODING_UTF8, cRelURL); return mBaseURI->Resolve (cRelURL, url); } nsresult EventContext::Unescape (const nsACString &aEscaped, nsACString &aUnescaped) { if (!aEscaped.Length()) return NS_ERROR_FAILURE; nsCOMPtr escaper (do_CreateInstance ("@mozilla.org/intl/texttosuburi;1")); NS_ENSURE_TRUE (escaper, NS_ERROR_FAILURE); nsresult rv; nsCString encoding; rv = mBrowser->GetEncoding (encoding); NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE); nsString unescaped; rv = escaper->UnEscapeURIForUI (encoding, aEscaped, unescaped); NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && unescaped.Length(), NS_ERROR_FAILURE); NS_UTF16ToCString (unescaped, NS_CSTRING_ENCODING_UTF8, aUnescaped); return NS_OK; } nsresult EventContext::GetEventContext (nsIDOMEventTarget *EventTarget, MozillaEmbedEvent *info) { nsresult rv; const PRUnichar hrefLiteral[] = {'h', 'r', 'e', 'f', '\0'}; const PRUnichar imgLiteral[] = {'i', 'm', 'g', '\0'}; const PRUnichar typeLiteral[] = {'t', 'y', 'p', 'e', '\0'}; const PRUnichar xlinknsLiteral[] = {'h', 't', 't', 'p', ':', '/', '/','w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/', '1', '9', '9', '9', '/', 'x', 'l', 'i', 'n', 'k', '\0'}; const PRUnichar bodyLiteral[] = { 'b', 'o', 'd', 'y', '\0' }; mEmbedEvent = info; info->context = EPHY_EMBED_CONTEXT_DOCUMENT; nsCOMPtr 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 domDoc; rv = node->GetOwnerDocument(getter_AddRefs(domDoc)); if (NS_FAILED(rv) || !domDoc) return NS_ERROR_FAILURE; nsCOMPtr xul_document = do_QueryInterface(domDoc); if (xul_document) { info->context = EPHY_EMBED_CONTEXT_NONE; return NS_ERROR_FAILURE; } mDOMDocument = domDoc; rv = mBrowser->GetEncoding (mCharset); NS_ENSURE_SUCCESS (rv, rv); /* Get base URI and CSS view */ nsCOMPtr docView (do_QueryInterface (domDoc)); NS_ENSURE_TRUE (docView, NS_ERROR_FAILURE); nsCOMPtr abstractView; docView->GetDefaultView (getter_AddRefs (abstractView)); NS_ENSURE_TRUE (abstractView, NS_ERROR_FAILURE); /* the abstract view is really the DOM window */ mViewCSS = do_QueryInterface (abstractView); NS_ENSURE_TRUE (mViewCSS, NS_ERROR_FAILURE); nsCOMPtr webNav (do_GetInterface (abstractView, &rv)); NS_ENSURE_SUCCESS (rv, rv); rv = webNav->GetCurrentURI (getter_AddRefs (mBaseURI)); NS_ENSURE_SUCCESS (rv, rv); // 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; PRBool has_image = PR_FALSE; nsCOMPtr element = do_QueryInterface(node); if ((nsIDOMNode::ELEMENT_NODE == type) && element) { nsString uTag; rv = element->GetLocalName(uTag); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; nsCString tag; NS_UTF16ToCString (uTag, NS_CSTRING_ENCODING_UTF8, tag); if (g_ascii_strcasecmp (tag.get(), "img") == 0) { nsString img; nsCOMPtr 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); info->context |= EPHY_EMBED_CONTEXT_IMAGE; has_image = PR_TRUE; } else if (g_ascii_strcasecmp (tag.get(), "area") == 0) { nsCOMPtr area = do_QueryInterface(node, &rv); if (NS_FAILED(rv) || !area) return NS_ERROR_FAILURE; // Parent node is the map itself nsCOMPtr parentNode; node->GetParentNode (getter_AddRefs(parentNode)); nsCOMPtr map = do_QueryInterface(parentNode, &rv); if (NS_FAILED(rv) || !area) return NS_ERROR_FAILURE; nsString mapName; rv = map->GetName (mapName); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; // Now we are searching for all the images with a usemap attribute nsCOMPtr imgs; rv = mDOMDocument->GetElementsByTagName (nsString(imgLiteral), getter_AddRefs (imgs)); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; PRUint32 imgs_count; rv = imgs->GetLength (&imgs_count); if (NS_FAILED (rv)) return NS_ERROR_FAILURE; for (PRUint32 i = 0; i < imgs_count; i++) { nsCOMPtr aNode; rv = imgs->Item (i, getter_AddRefs (aNode)); if (NS_FAILED (rv)) continue; nsCOMPtr img = do_QueryInterface(aNode, &rv); if (NS_FAILED(rv) || !img) continue; nsString imgMapName; rv = img->GetUseMap (imgMapName); if (NS_FAILED (rv)) continue; // usemap always starts with # imgMapName.Cut (0,1); // Check if the current image is attached to the map we are looking for if (EphyUtils::StringEquals(imgMapName, mapName)) { nsString imgSrc; rv = img->GetSrc (imgSrc); if (NS_FAILED(rv)) continue; SetStringProperty ("image", imgSrc); info->context |= EPHY_EMBED_CONTEXT_IMAGE; has_image = PR_TRUE; break; } } } else if (g_ascii_strcasecmp (tag.get(), "input") == 0) { CheckInput (node); } else if (g_ascii_strcasecmp (tag.get(), "textarea") == 0) { info->context |= EPHY_EMBED_CONTEXT_INPUT; } else if (g_ascii_strcasecmp (tag.get(), "object") == 0) { nsCOMPtr object; object = do_QueryInterface (node); if (!element) return NS_ERROR_FAILURE; nsString value; object->GetType(value); nsCString cValue; NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cValue); // MIME types are always lower case if (g_str_has_prefix (cValue.get(), "image/")) { nsString img; rv = object->GetData (img); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; nsCString cImg; rv = ResolveBaseURL (img, cImg); if (NS_FAILED (rv)) return NS_ERROR_FAILURE; SetStringProperty ("image", cImg.get()); info->context |= EPHY_EMBED_CONTEXT_IMAGE; has_image = PR_TRUE; } else { info->context = EPHY_EMBED_CONTEXT_NONE; return NS_OK; } } else if (g_ascii_strcasecmp (tag.get(), "html") == 0) { /* Clicked on part of the page without a , so * look for a background image in the body tag */ nsCOMPtr nodeList; rv = mDOMDocument->GetElementsByTagName (nsString(bodyLiteral), getter_AddRefs (nodeList)); if (NS_SUCCEEDED (rv) && nodeList) { nsCOMPtr bodyNode; nodeList->Item (0, getter_AddRefs (bodyNode)); nsString cssurl; rv = GetCSSBackground (bodyNode, cssurl); if (NS_SUCCEEDED (rv)) { nsCString bgimg; rv = ResolveBaseURL (cssurl, bgimg); if (NS_FAILED (rv)) return NS_ERROR_FAILURE; SetStringProperty ("image", bgimg.get()); info->context |= EPHY_EMBED_CONTEXT_IMAGE; has_image = PR_TRUE; } } } } /* Is page framed ? */ PRBool framed; IsPageFramed (node, &framed); SetIntProperty ("framed_page", framed); /* Bubble out, looking for items of interest */ while (node) { nsCOMPtr dom_elem = do_QueryInterface(node); if (dom_elem) { nsString value; dom_elem->GetAttributeNS (nsString(xlinknsLiteral), nsString(typeLiteral), value); nsCString cValue; NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cValue); if (g_ascii_strcasecmp (cValue.get(), "simple") == 0) { info->context |= EPHY_EMBED_CONTEXT_LINK; dom_elem->GetAttributeNS (nsString(xlinknsLiteral), nsString(hrefLiteral), value); SetURIProperty (node, "link", value); CheckLinkScheme (value); } } rv = node->GetNodeType(&type); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; element = do_QueryInterface(node); if ((nsIDOMNode::ELEMENT_NODE == type) && element) { nsString uTag; rv = element->GetLocalName(uTag); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; nsCString tag; NS_UTF16ToCString (uTag, NS_CSTRING_ENCODING_UTF8, tag); /* Link */ if (g_ascii_strcasecmp (tag.get(), "a") == 0) { nsString tmp; rv = GatherTextUnder (node, tmp); if (NS_SUCCEEDED(rv)) SetStringProperty ("linktext", tmp); nsCOMPtr anchor = do_QueryInterface(node); nsCString href; anchor->GetHref (tmp); NS_UTF16ToCString (tmp, NS_CSTRING_ENCODING_UTF8, href); if (g_str_has_prefix (href.get(), "mailto:")) { /* cut "mailto:" */ href.Cut (0, 7); char *str = g_strdup (href.get()); g_strdelimit (str, "?", '\0'); nsCString unescapedHref; rv = Unescape (nsCString(str), unescapedHref); if (NS_SUCCEEDED (rv) && unescapedHref.Length()) { SetStringProperty ("email", unescapedHref.get()); info->context |= EPHY_EMBED_CONTEXT_EMAIL_LINK; } g_free (str); } if (anchor && tmp.Length()) { info->context |= EPHY_EMBED_CONTEXT_LINK; SetURIProperty (node, "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); nsCString linkType; NS_UTF16ToCString (tmp, NS_CSTRING_ENCODING_UTF8, linkType); if (g_ascii_strcasecmp (linkType.get(), "text/smartbookmark") == 0) { SetIntProperty ("link_is_smart", TRUE); nsCOMPtr childNode; node->GetFirstChild (getter_AddRefs(childNode)); if (childNode) { nsCOMPtr image = do_QueryInterface(childNode, &rv); if (image) { nsString img; rv = image->GetSrc (img); if (!NS_FAILED(rv)) { SetStringProperty ("image", img); } } } } else { SetIntProperty ("link_is_smart", FALSE); } } } else if (g_ascii_strcasecmp (tag.get(), "option") == 0) { info->context = EPHY_EMBED_CONTEXT_NONE; return NS_OK; } else if (g_ascii_strcasecmp (tag.get(), "area") == 0) { info->context |= EPHY_EMBED_CONTEXT_LINK; nsCOMPtr area = do_QueryInterface(node, &rv); if (NS_SUCCEEDED(rv) && area) { nsString href; rv = area->GetHref (href); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; SetURIProperty (node, "link", href); CheckLinkScheme (href); } } else if (g_ascii_strcasecmp (tag.get(), "input") == 0) { CheckInput (node); } else if (g_ascii_strcasecmp (tag.get(), "textarea") == 0) { info->context |= EPHY_EMBED_CONTEXT_INPUT; } if (!has_image) { nsString cssurl; rv = GetCSSBackground (node, cssurl); if (NS_SUCCEEDED (rv)) { nsCString bgimg; rv = ResolveBaseURL (cssurl, bgimg); if (NS_FAILED (rv)) return NS_ERROR_FAILURE; SetStringProperty ("image", bgimg.get()); info->context |= EPHY_EMBED_CONTEXT_IMAGE; has_image = PR_TRUE; } } } nsCOMPtr parentNode; node->GetParentNode (getter_AddRefs(parentNode)); node = parentNode; } return NS_OK; } nsresult EventContext::GetCSSBackground (nsIDOMNode *node, nsAString& url) { if (!mViewCSS) return NS_ERROR_NOT_INITIALIZED; nsresult rv; const PRUnichar bgimage[] = {'b', 'a', 'c', 'k', 'g', 'r', 'o', 'u', 'n', 'd', '-', 'i', 'm', 'a', 'g', 'e', '\0'}; nsCOMPtr element = do_QueryInterface (node); NS_ENSURE_TRUE (element, NS_ERROR_FAILURE); nsCOMPtr decl; mViewCSS->GetComputedStyle (element, nsString(), getter_AddRefs (decl)); NS_ENSURE_TRUE (decl, NS_ERROR_FAILURE); nsCOMPtr CSSValue; decl->GetPropertyCSSValue (nsString(bgimage), getter_AddRefs (CSSValue)); nsCOMPtr primitiveValue = do_QueryInterface (CSSValue); if (!primitiveValue) return NS_ERROR_FAILURE; PRUint16 type; rv = primitiveValue->GetPrimitiveType (&type); NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE); if (type != nsIDOMCSSPrimitiveValue::CSS_URI) return NS_ERROR_FAILURE; rv = primitiveValue->GetStringValue (url); NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE); return NS_OK; } nsresult EventContext::GetTargetCoords (nsIDOMEventTarget *aTarget, PRInt32 *aX, PRInt32 *aY) { /* Calculate the node coordinates relative to the widget origin */ nsCOMPtr 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 parent; elem->GetOffsetParent (getter_AddRefs (parent)); elem = do_QueryInterface(parent); } *aX = x; *aY = y; return NS_OK; } nsresult EventContext::GetMouseEventInfo (nsIDOMMouseEvent *aMouseEvent, MozillaEmbedEvent *info) { /* FIXME: casting 32-bit guint* to PRUint16* below will break on big-endian */ PRUint16 btn = 1729; aMouseEvent->GetButton (&btn); switch (btn) { /* mozilla's button counting is one-off from gtk+'s */ case 0: info->button = 1; break; case 1: info->button = 2; break; case 2: info->button = 3; break; case (PRUint16) -1: /* when the user submits a form with Return, mozilla synthesises * a _mouse_ click event with btn=65535 (-1). */ default: info->button = 0; break; } if (info->button != 0) { /* OTOH, casting only between (un)signedness is safe */ aMouseEvent->GetScreenX ((PRInt32*)&info->x); aMouseEvent->GetScreenY ((PRInt32*)&info->y); } else /* this is really a keyboard event */ { nsCOMPtr eventTarget; aMouseEvent->GetTarget (getter_AddRefs (eventTarget)); GetTargetCoords (eventTarget, (PRInt32*)&info->x, (PRInt32*)&info->y); } /* be sure we are not clicking on the scroolbars */ nsCOMPtr nsEvent = do_QueryInterface(aMouseEvent); if (!nsEvent) return NS_ERROR_FAILURE; #ifdef MOZ_NSIDOMNSEVENT_GETISTRUSTED /* make sure the event is trusted */ PRBool isTrusted = PR_FALSE; nsEvent->GetIsTrusted (&isTrusted); if (!isTrusted) return NS_ERROR_UNEXPECTED; #endif /* MOZ_NSIDOMNSEVENT_GETISTRUSTED */ nsresult rv; nsCOMPtr OriginalTarget; rv = nsEvent->GetOriginalTarget(getter_AddRefs(OriginalTarget)); if (NS_FAILED (rv) || !OriginalTarget) return NS_ERROR_FAILURE; nsCOMPtr OriginalNode = do_QueryInterface(OriginalTarget); if (!OriginalNode) return NS_ERROR_FAILURE; nsString nodename; OriginalNode->GetNodeName(nodename); nsCString cNodeName; NS_UTF16ToCString (nodename, NS_CSTRING_ENCODING_UTF8, cNodeName); if (g_ascii_strcasecmp (cNodeName.get(), "xul:scrollbarbutton") == 0 || g_ascii_strcasecmp (cNodeName.get(), "xul:thumb") == 0 || g_ascii_strcasecmp (cNodeName.get(), "xul:vbox") == 0 || g_ascii_strcasecmp (cNodeName.get(), "xul:spacer") == 0 || g_ascii_strcasecmp (cNodeName.get(), "xul:slider") == 0) return NS_ERROR_FAILURE; nsCOMPtr EventTarget; rv = aMouseEvent->GetTarget(getter_AddRefs(EventTarget)); if (NS_FAILED (rv) || !EventTarget) return NS_ERROR_FAILURE; rv = GetEventContext (EventTarget, info); if (NS_FAILED (rv)) return rv; /* 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; /* no need to check GetMetaKey, it's always PR_FALSE, * see widget/src/gtk2/nsWindow.cpp:InitMouseEvent */ aMouseEvent->GetCtrlKey(&mod_key); if (mod_key) info->modifier |= GDK_CONTROL_MASK; return NS_OK; } nsresult EventContext::GetKeyEventInfo (nsIDOMKeyEvent *aKeyEvent, MozillaEmbedEvent *info) { #ifdef MOZ_NSIDOMNSEVENT_GETISTRUSTED /* make sure the event is trusted */ nsCOMPtr nsEvent (do_QueryInterface (aKeyEvent)); NS_ENSURE_TRUE (nsEvent, NS_ERROR_FAILURE); PRBool isTrusted = PR_FALSE; nsEvent->GetIsTrusted (&isTrusted); if (!isTrusted) return NS_ERROR_UNEXPECTED; #endif /* MOZ_NSIDOMNSEVENT_GETISTRUSTED */ info->button = 0; nsresult rv; PRUint32 keyCode; rv = aKeyEvent->GetKeyCode(&keyCode); if (NS_FAILED(rv)) return rv; info->keycode = keyCode; nsCOMPtr target; rv = aKeyEvent->GetTarget(getter_AddRefs(target)); if (NS_FAILED(rv) || !target) return NS_ERROR_FAILURE; GetTargetCoords (target, (PRInt32*)&info->x, (PRInt32*)&info->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 rv; nsCOMPtr mainDocument; rv = mBrowser->GetDocument (getter_AddRefs(mainDocument)); if (NS_FAILED (rv) || !mainDocument) return NS_ERROR_FAILURE; nsCOMPtr nodeDocument; rv = node->GetOwnerDocument (getter_AddRefs(nodeDocument)); if (NS_FAILED (rv) || !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 element; element = do_QueryInterface (aNode); if (!element) return NS_ERROR_FAILURE; nsString uValue; element->GetAttribute (nsString(typeLiteral), uValue); nsCString value; NS_UTF16ToCString (uValue, NS_CSTRING_ENCODING_UTF8, value); if (g_ascii_strcasecmp (value.get(), "image") == 0) { mEmbedEvent->context |= EPHY_EMBED_CONTEXT_IMAGE; nsCOMPtr input; input = do_QueryInterface (aNode); if (!input) return NS_ERROR_FAILURE; nsresult rv; nsString img; rv = input->GetSrc (img); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; nsCString cImg; rv = ResolveBaseURL (img, cImg); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; SetStringProperty ("image", cImg.get()); } else if (g_ascii_strcasecmp (value.get(), "radio") != 0 && g_ascii_strcasecmp (value.get(), "submit") != 0 && g_ascii_strcasecmp (value.get(), "reset") != 0 && g_ascii_strcasecmp (value.get(), "hidden") != 0 && g_ascii_strcasecmp (value.get(), "button") != 0 && g_ascii_strcasecmp (value.get(), "checkbox") != 0) { mEmbedEvent->context |= EPHY_EMBED_CONTEXT_INPUT; if (g_ascii_strcasecmp (value.get(), "password") == 0) { mEmbedEvent->context |= EPHY_EMBED_CONTEXT_INPUT_PASSWORD; } } return NS_OK; } nsresult EventContext::CheckLinkScheme (const nsAString &link) { nsCOMPtr uri; EphyUtils::NewURI (getter_AddRefs (uri), link); if (!uri) return NS_ERROR_FAILURE; nsresult rv; nsCString scheme; rv = uri->GetScheme (scheme); if (NS_FAILED (rv)) return NS_ERROR_FAILURE; if (g_ascii_strcasecmp (scheme.get(), "http") == 0 || g_ascii_strcasecmp (scheme.get(), "https") == 0 || g_ascii_strcasecmp (scheme.get(), "ftp") == 0 || g_ascii_strcasecmp (scheme.get(), "file") == 0 || g_ascii_strcasecmp (scheme.get(), "data") == 0 || g_ascii_strcasecmp (scheme.get(), "resource") == 0 || g_ascii_strcasecmp (scheme.get(), "about") == 0 || g_ascii_strcasecmp (scheme.get(), "gopher") == 0) { 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) { nsCString cValue; NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cValue); return SetStringProperty (name, cValue.get()); } nsresult EventContext::SetURIProperty (nsIDOMNode *node, const char *name, const nsACString &value) { nsresult rv; nsCOMPtr uri; rv = EphyUtils::NewURI (getter_AddRefs (uri), value, mCharset.Length () ? mCharset.get() : nsnull, mBaseURI); if (NS_SUCCEEDED (rv) && uri) { /* Hide password part */ nsCString user; uri->GetUsername (user); uri->SetUserPass (user); nsCString spec; uri->GetSpec (spec); rv = SetStringProperty (name, spec.get()); } else { rv = SetStringProperty (name, nsCString(value).get()); } return rv; } nsresult EventContext::SetURIProperty (nsIDOMNode *node, const char *name, const nsAString &value) { nsCString cValue; NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cValue); return SetURIProperty (node, name, cValue); } /* static */ PRBool EventContext::CheckKeyPress (nsIDOMKeyEvent *aEvent) { PRBool retval = PR_FALSE; /* make sure the event is trusted */ nsCOMPtr nsEvent (do_QueryInterface (aEvent)); NS_ENSURE_TRUE (nsEvent, retval); PRBool isTrusted = PR_FALSE; nsEvent->GetIsTrusted (&isTrusted); if (!isTrusted) return retval; /* check for alt/ctrl */ PRBool isCtrl = PR_FALSE, isAlt = PR_FALSE; aEvent->GetCtrlKey (&isCtrl); aEvent->GetAltKey (&isAlt); if (isCtrl || isAlt) return retval; nsCOMPtr uiEvent (do_QueryInterface (aEvent)); NS_ENSURE_TRUE (uiEvent, retval); /* check for already handled event */ PRBool isPrevented = PR_FALSE; uiEvent->GetPreventDefault (&isPrevented); if (isPrevented) return retval; /* check for form controls */ nsresult rv; nsCOMPtr target; rv = aEvent->GetTarget (getter_AddRefs (target)); NS_ENSURE_SUCCESS (rv, retval); nsCOMPtr inputElement (do_QueryInterface (target)); if (inputElement) { nsString type; inputElement->GetType (type); nsCString (cType); NS_UTF16ToCString (type, NS_CSTRING_ENCODING_UTF8, cType); if (g_ascii_strcasecmp (cType.get(), "text") == 0 || g_ascii_strcasecmp (cType.get(), "password") == 0 || g_ascii_strcasecmp (cType.get(), "file") == 0) return retval; } nsCOMPtr textArea; nsCOMPtr selectElement; nsCOMPtr indexElement; if ((textArea = do_QueryInterface (target)) || (selectElement = do_QueryInterface (target)) || (indexElement = do_QueryInterface (target))) return retval; /* check for design mode */ nsCOMPtr node (do_QueryInterface (target, &rv)); NS_ENSURE_SUCCESS (rv, PR_FALSE); nsCOMPtr doc; rv = node->GetOwnerDocument (getter_AddRefs (doc)); NS_ENSURE_SUCCESS (rv, retval); nsCOMPtr xul_document (do_QueryInterface(doc, &rv)); if (xul_document) return retval; nsCOMPtr htmlDoc (do_QueryInterface (doc)); if (htmlDoc) { nsString uDesign; rv = htmlDoc->GetDesignMode (uDesign); NS_ENSURE_SUCCESS (rv, retval); nsCString design; NS_UTF16ToCString (uDesign, NS_CSTRING_ENCODING_UTF8, design); retval = g_ascii_strcasecmp (design.get(), "on") != 0; } else { retval = PR_TRUE; } return retval; }