From 3ddeef804136e9f47f66c38c80d126a4285d525d Mon Sep 17 00:00:00 2001 From: Christian Persch Date: Fri, 8 Apr 2005 12:58:18 +0000 Subject: Emit signal when encountering alternate links. Fixes bug #171657. 2005-04-08 Christian Persch * embed/ephy-embed.c: (ephy_embed_base_init): * embed/ephy-embed.h: * embed/mozilla/EphyBrowser.cpp: * embed/mozilla/EphyBrowser.h: * lib/ephy-marshal.list: Emit signal when encountering alternate links. Fixes bug #171657. --- embed/ephy-embed.c | 23 +++++- embed/ephy-embed.h | 4 ++ embed/mozilla/EphyBrowser.cpp | 161 +++++++++++++++++++++++++----------------- embed/mozilla/EphyBrowser.h | 10 ++- 4 files changed, 128 insertions(+), 70 deletions(-) (limited to 'embed') diff --git a/embed/ephy-embed.c b/embed/ephy-embed.c index a331c2ab4..c77dfb657 100644 --- a/embed/ephy-embed.c +++ b/embed/ephy-embed.c @@ -128,7 +128,28 @@ ephy_embed_base_init (gpointer g_class) g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, - G_TYPE_STRING); + G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE); +/** + * EphyEmbed::ge-feed-link: + * @embed: + * @type: the mime-type of the news feed + * @title: the title of the news feed + * @address: the URL to @embed's web site's news feed + * + * The ::ge_rss signal is emitted when @embed discovers that a news feed + * is available for the site it is visiting. + **/ + g_signal_new ("ge_feed_link", + EPHY_TYPE_EMBED, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EphyEmbedIface, feed_link), + NULL, NULL, + ephy_marshal_VOID__STRING_STRING_STRING, + G_TYPE_NONE, + 3, + G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE, + G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE, + G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE); /** * EphyEmbed::ge-location: * @embed: diff --git a/embed/ephy-embed.h b/embed/ephy-embed.h index a25e74d78..014aa6cd8 100644 --- a/embed/ephy-embed.h +++ b/embed/ephy-embed.h @@ -116,6 +116,10 @@ struct _EphyEmbedIface EphyEmbedEvent *event); void (* favicon) (EphyEmbed *embed, const char *location); + void (* feed_link) (EphyEmbed *embed, + const char *type, + const char *title, + const char *address); void (* location) (EphyEmbed *embed, const char *location); void (* net_state) (EphyEmbed *embed, diff --git a/embed/mozilla/EphyBrowser.cpp b/embed/mozilla/EphyBrowser.cpp index ac7771c89..aa2d639bc 100644 --- a/embed/mozilla/EphyBrowser.cpp +++ b/embed/mozilla/EphyBrowser.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2000-2004 Marco Pesenti Gritti + * Copyright (C) 2003, 2004, 2005 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 @@ -99,20 +100,15 @@ #endif #endif -static PRUnichar DOMLinkAdded[] = { 'D', 'O', 'M', 'L', 'i', 'n', 'k', - 'A', 'd', 'd', 'e', 'd', '\0' }; -static PRUnichar ContextMenu[] = { 'c', 'o', 'n', 't', 'e', 'x', 't', 'm', - 'e', 'n', 'u', '\0' }; -static PRUnichar DOMPopupBlocked[] = { 'D', 'O', 'M', 'P', 'o', 'p', - 'u', 'p', 'B', 'l', 'o', 'c', - 'k', 'e', 'd', '\0' }; -static PRUnichar DOMWillOpenModalDialog[] = { 'D', 'O', 'M', 'W', 'i', 'l', 'l', - 'O', 'p', 'e', 'n', 'M', 'o', 'd', - 'a', 'l', 'D', 'i', 'a', 'l', 'o', - 'g', '\0' }; -static PRUnichar DOMModalDialogClosed[] = { 'D', 'O', 'M', 'M', 'o', 'd', 'a', - 'l', 'D', 'i', 'a', 'l', 'o', 'g', - 'C', 'l', 'o', 's', 'e', 'd', '\0' }; +const static PRUnichar kDOMLinkAdded[] = { 'D', 'O', 'M', 'L', 'i', 'n', 'k', 'A', 'd', 'd', 'e', 'd', '\0' }; +const static PRUnichar kContextMenu[] = { 'c', 'o', 'n', 't', 'e', 'x', 't', 'm', 'e', 'n', 'u', '\0' }; +const static PRUnichar kDOMPopupBlocked[] = { 'D', 'O', 'M', 'P', 'o', 'p', 'u', 'p', 'B', 'l', 'o', 'c', 'k', 'e', 'd', '\0' }; +const static PRUnichar kDOMWillOpenModalDialog[] = { 'D', 'O', 'M', 'W', 'i', 'l', 'l', 'O', 'p', 'e', 'n', 'M', 'o', 'd', 'a', 'l', 'D', 'i', 'a', 'l', 'o', 'g', '\0' }; +const static PRUnichar kDOMModalDialogClosed[] = { 'D', 'O', 'M', 'M', 'o', 'd', 'a', 'l', 'D', 'i', 'a', 'l', 'o', 'g', 'C', 'l', 'o', 's', 'e', 'd', '\0' }; +const static PRUnichar kHrefAttr[] = { 'h', 'r', 'e', 'f', '\0' }; +const static PRUnichar kTypeAttr[] = { 't', 'y', 'p', 'e', '\0' }; +const static PRUnichar kTitleAttr[] = { 't', 'i', 't', 'l', 'e', '\0' }; +const static PRUnichar kRelAttr[] = { 'r', 'e', 'l', '\0' }; EphyEventListener::EphyEventListener() : mOwner(nsnull) @@ -135,22 +131,17 @@ EphyEventListener::Init (EphyBrowser *aOwner) } NS_IMETHODIMP -EphyFaviconEventListener::HandleEvent(nsIDOMEvent* aDOMEvent) +EphyDOMLinkEventListener::HandleEvent (nsIDOMEvent* aDOMEvent) { nsCOMPtr eventTarget; aDOMEvent->GetTarget(getter_AddRefs(eventTarget)); - nsCOMPtr node = do_QueryInterface(eventTarget); - NS_ENSURE_TRUE (node, NS_ERROR_FAILURE); - - nsCOMPtr linkElement; - linkElement = do_QueryInterface (node); + nsCOMPtr linkElement (do_QueryInterface (eventTarget)); if (!linkElement) return NS_ERROR_FAILURE; - PRUnichar relAttr[] = { 'r', 'e', 'l', '\0' }; nsresult rv; nsEmbedString value; - rv = linkElement->GetAttribute (nsEmbedString(relAttr), value); + rv = linkElement->GetAttribute (nsEmbedString(kRelAttr), value); if (NS_FAILED (rv)) return NS_ERROR_FAILURE; nsEmbedCString rel; @@ -159,16 +150,8 @@ EphyFaviconEventListener::HandleEvent(nsIDOMEvent* aDOMEvent) if (g_ascii_strcasecmp (rel.get(), "SHORTCUT ICON") == 0 || g_ascii_strcasecmp (rel.get(), "ICON") == 0) { - PRUnichar hrefAttr[] = { 'h', 'r', 'e', 'f', '\0' }; - nsEmbedString hrefValue; - rv = linkElement->GetAttribute (nsEmbedString (hrefAttr), hrefValue); - if (NS_FAILED (rv) || !hrefValue.Length()) return NS_ERROR_FAILURE; - - nsEmbedCString link; - NS_UTF16ToCString (hrefValue, NS_CSTRING_ENCODING_UTF8, link); - nsCOMPtr domDoc; - node->GetOwnerDocument(getter_AddRefs(domDoc)); + linkElement->GetOwnerDocument(getter_AddRefs(domDoc)); NS_ENSURE_TRUE (domDoc, NS_ERROR_FAILURE); nsCOMPtr docView (do_QueryInterface (domDoc)); @@ -188,22 +171,18 @@ EphyFaviconEventListener::HandleEvent(nsIDOMEvent* aDOMEvent) /* disallow subframes to set favicon */ if (domWinAsISupports != topDomWinAsISupports) return NS_OK; - nsCOMPtr doc (do_QueryInterface (domDoc)); - NS_ENSURE_TRUE (doc, NS_ERROR_FAILURE); - - nsEmbedString spec; - rv = doc->GetDocumentURI (spec); - NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE); + nsCOMPtr docUri; + rv = GetDocURI (linkElement, getter_AddRefs (docUri)); + NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && docUri, NS_ERROR_FAILURE); - nsEmbedCString encoding; - mOwner->GetEncoding (encoding); + rv = linkElement->GetAttribute (nsEmbedString (kHrefAttr), value); + if (NS_FAILED (rv) || !value.Length()) return NS_ERROR_FAILURE; - nsCOMPtr docUri; - EphyUtils::NewURI (getter_AddRefs(docUri), spec, encoding.get()); - NS_ENSURE_TRUE (docUri, NS_ERROR_FAILURE); + nsEmbedCString cLink; + NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cLink); nsEmbedCString faviconUrl; - rv = docUri->Resolve (link, faviconUrl); + rv = docUri->Resolve (cLink, faviconUrl); NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE); nsCOMPtr favUri; @@ -228,15 +207,10 @@ EphyFaviconEventListener::HandleEvent(nsIDOMEvent* aDOMEvent) NS_ENSURE_TRUE (policy, NS_OK); #if MOZ_NSICONTENTPOLICY_VARIANT == 2 - /* FIXME: mozilla tabbrowser.xml passes - * safeGetProperty(event.target, "type") as mimetype guess: - */ - PRUnichar typeAttr[] = { 't', 'y', 'p', 'e', '\0' }; - nsEmbedString typeVal; - linkElement->GetAttribute (nsEmbedString (typeAttr), typeVal); + linkElement->GetAttribute (nsEmbedString (kTypeAttr), value); nsEmbedCString cTypeVal; - NS_UTF16ToCString (typeVal, NS_CSTRING_ENCODING_UTF8, cTypeVal); + NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cTypeVal); PRInt16 decision = 0; rv = policy->ShouldLoad (nsIContentPolicy::TYPE_IMAGE, @@ -258,10 +232,65 @@ EphyFaviconEventListener::HandleEvent(nsIDOMEvent* aDOMEvent) /* ok, we accept this as a valid favicon for this site */ g_signal_emit_by_name (mOwner->mEmbed, "ge_favicon", faviconUrl.get()); } + else if (g_ascii_strcasecmp (rel.get (), "alternate") == 0) + { + linkElement->GetAttribute (nsEmbedString (kTypeAttr), value); + + nsEmbedCString cTypeVal; + NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cTypeVal); + + if (g_ascii_strcasecmp (cTypeVal.get (), "application/rss+xml") == 0 || + g_ascii_strcasecmp (cTypeVal.get (), "application/atom+xml") == 0) + { + rv = linkElement->GetAttribute (nsEmbedString (kHrefAttr), value); + if (NS_FAILED (rv) || !value.Length()) return NS_ERROR_FAILURE; + + nsEmbedCString cLink; + NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cLink); + + nsCOMPtr docUri; + rv = GetDocURI (linkElement, getter_AddRefs (docUri)); + NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && docUri, NS_ERROR_FAILURE); + + nsEmbedCString resolvedLink; + rv = docUri->Resolve (cLink, resolvedLink); + NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE); + + linkElement->GetAttribute (nsEmbedString (kTitleAttr), value); + + nsEmbedCString cTitle; + NS_UTF16ToCString (value, NS_CSTRING_ENCODING_UTF8, cTitle); + + g_signal_emit_by_name (mOwner->mEmbed, "ge_feed_link", + cTypeVal.get(), cTitle.get(), resolvedLink.get()); + } + } return NS_OK; } +nsresult +EphyDOMLinkEventListener::GetDocURI (nsIDOMElement *aElement, + nsIURI **aDocURI) +{ + nsCOMPtr domDoc; + aElement->GetOwnerDocument (getter_AddRefs(domDoc)); + + nsCOMPtr doc (do_QueryInterface (domDoc)); + NS_ENSURE_TRUE (doc, NS_ERROR_FAILURE); + + nsresult rv; + nsEmbedString spec; + rv = doc->GetDocumentURI (spec); + NS_ENSURE_SUCCESS (rv, rv); + + nsEmbedCString encoding; + rv = mOwner->GetEncoding (encoding); + NS_ENSURE_SUCCESS (rv, rv); + + return EphyUtils::NewURI (aDocURI, spec, encoding.get()); +} + NS_IMETHODIMP EphyPopupBlockEventListener::HandleEvent (nsIDOMEvent * aDOMEvent) { @@ -432,7 +461,7 @@ EphyContextMenuListener::HandleEvent (nsIDOMEvent* aDOMEvent) } EphyBrowser::EphyBrowser () -: mFaviconEventListener(nsnull) +: mDOMLinkEventListener(nsnull) , mPopupBlockEventListener(nsnull) , mModalAlertListener(nsnull) , mContextMenuListener(nsnull) @@ -465,10 +494,10 @@ nsresult EphyBrowser::Init (GtkMozEmbed *mozembed) rv = mDOMWindow->GetDocument (getter_AddRefs (domDocument)); NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE); - mFaviconEventListener = new EphyFaviconEventListener(); - if (!mFaviconEventListener) return NS_ERROR_OUT_OF_MEMORY; + mDOMLinkEventListener = new EphyDOMLinkEventListener(); + if (!mDOMLinkEventListener) return NS_ERROR_OUT_OF_MEMORY; - rv = mFaviconEventListener->Init (this); + rv = mDOMLinkEventListener->Init (this); NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE); mPopupBlockEventListener = new EphyPopupBlockEventListener(); @@ -566,15 +595,15 @@ EphyBrowser::AttachListeners(void) NS_ENSURE_TRUE (mEventTarget, NS_ERROR_FAILURE); nsresult rv; - rv = mEventTarget->AddEventListener(nsEmbedString(DOMLinkAdded), - mFaviconEventListener, PR_FALSE); - rv |= mEventTarget->AddEventListener(nsEmbedString(DOMPopupBlocked), + rv = mEventTarget->AddEventListener(nsEmbedString(kDOMLinkAdded), + mDOMLinkEventListener, PR_FALSE); + rv |= mEventTarget->AddEventListener(nsEmbedString(kDOMPopupBlocked), mPopupBlockEventListener, PR_FALSE); - rv |= mEventTarget->AddEventListener(nsEmbedString(DOMWillOpenModalDialog), + rv |= mEventTarget->AddEventListener(nsEmbedString(kDOMWillOpenModalDialog), mModalAlertListener, PR_TRUE); - rv |= mEventTarget->AddEventListener(nsEmbedString(DOMModalDialogClosed), + rv |= mEventTarget->AddEventListener(nsEmbedString(kDOMModalDialogClosed), mModalAlertListener, PR_TRUE); - rv |= mEventTarget->AddEventListener(nsEmbedString(ContextMenu), + rv |= mEventTarget->AddEventListener(nsEmbedString(kContextMenu), mContextMenuListener, PR_TRUE /* capture */); NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE); @@ -587,15 +616,15 @@ EphyBrowser::DetachListeners(void) if (!mEventTarget) return NS_OK; nsresult rv; - rv = mEventTarget->RemoveEventListener(nsEmbedString(DOMLinkAdded), - mFaviconEventListener, PR_FALSE); - rv |= mEventTarget->RemoveEventListener(nsEmbedString(DOMPopupBlocked), + rv = mEventTarget->RemoveEventListener(nsEmbedString(kDOMLinkAdded), + mDOMLinkEventListener, PR_FALSE); + rv |= mEventTarget->RemoveEventListener(nsEmbedString(kDOMPopupBlocked), mPopupBlockEventListener, PR_FALSE); - rv |= mEventTarget->RemoveEventListener(nsEmbedString(DOMWillOpenModalDialog), + rv |= mEventTarget->RemoveEventListener(nsEmbedString(kDOMWillOpenModalDialog), mModalAlertListener, PR_TRUE); - rv |= mEventTarget->RemoveEventListener(nsEmbedString(DOMModalDialogClosed), + rv |= mEventTarget->RemoveEventListener(nsEmbedString(kDOMModalDialogClosed), mModalAlertListener, PR_TRUE); - rv |= mEventTarget->RemoveEventListener(nsEmbedString(ContextMenu), + rv |= mEventTarget->RemoveEventListener(nsEmbedString(kContextMenu), mContextMenuListener, PR_TRUE /* capture */); NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE); diff --git a/embed/mozilla/EphyBrowser.h b/embed/mozilla/EphyBrowser.h index 4878dc412..c594e7f7c 100644 --- a/embed/mozilla/EphyBrowser.h +++ b/embed/mozilla/EphyBrowser.h @@ -67,10 +67,14 @@ protected: EphyBrowser *mOwner; }; -class EphyFaviconEventListener : public EphyEventListener +class EphyDOMLinkEventListener : public EphyEventListener { public: NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent); +private: + nsresult GetDocURI (nsIDOMElement *aElement, + nsIURI **aDocURI); + }; class EphyPopupBlockEventListener : public EphyEventListener @@ -107,7 +111,7 @@ protected: class EphyBrowser { friend class EphyEventListener; -friend class EphyFaviconEventListener; +friend class EphyDOMLinkEventListener; friend class EphyPopupBlockEventListener; friend class EphyModalAlertEventListener; friend class EphyContextMenuListener; @@ -177,7 +181,7 @@ private: nsCOMPtr mTargetDocument; nsCOMPtr mEventTarget; nsCOMPtr mDOMWindow; - EphyFaviconEventListener *mFaviconEventListener; + EphyDOMLinkEventListener *mDOMLinkEventListener; EphyPopupBlockEventListener *mPopupBlockEventListener; EphyModalAlertEventListener *mModalAlertListener; EphyContextMenuListener *mContextMenuListener; -- cgit v1.2.3