diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 011566f6af4a..82d5d77948e7 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -176,6 +176,41 @@ private: PrefObserver& operator=(const PrefObserver&); }; +class AlertObserver +{ +public: + + AlertObserver(nsIObserver *aObserver, const nsString& aData) + : mData(aData) + , mObserver(aObserver) + { + } + + ~AlertObserver() {} + + bool ShouldRemoveFrom(nsIObserver* aObserver, + const nsString& aData) const + { + return (mObserver == aObserver && + mData == aData); + } + + bool Observes(const nsString& aData) const + { + return mData.Equals(aData); + } + + bool Notify(const nsCString& aType) const + { + mObserver->Observe(nsnull, aType.get(), mData.get()); + return true; + } + +private: + nsCOMPtr mObserver; + nsString mData; +}; + ContentChild* ContentChild::sSingleton; @@ -286,7 +321,7 @@ ContentChild::ActorDestroy(ActorDestroyReason why) // |if (mDead)| special case below and we're safe. mDead = true; mPrefObservers.Clear(); - + mAlertObservers.Clear(); XRE_ShutdownChildProcess(); } @@ -331,6 +366,15 @@ ContentChild::RemoveRemotePrefObserver(const nsCString& aDomain, return NS_ERROR_UNEXPECTED; } +nsresult +ContentChild::AddRemoteAlertObserver(const nsString& aData, + nsIObserver* aObserver) +{ + NS_ASSERTION(aObserver, "Adding a null observer?"); + mAlertObservers.AppendElement(new AlertObserver(aObserver, aData)); + return NS_OK; +} + bool ContentChild::RecvNotifyRemotePrefObserver(const nsCString& aPref) { @@ -349,6 +393,27 @@ ContentChild::RecvNotifyRemotePrefObserver(const nsCString& aPref) return true; } +bool +ContentChild::RecvNotifyAlertsObserver(const nsCString& aType, const nsString& aData) +{ + printf("ContentChild::RecvNotifyAlertsObserver %s\n", aType.get() ); + + for (PRUint32 i = 0; i < mAlertObservers.Length(); + /*we mutate the array during the loop; ++i iff no mutation*/) { + AlertObserver* observer = mAlertObservers[i]; + if (observer->Observes(aData) && observer->Notify(aType)) { + // if aType == alertfinished, this alert is done. we can + // remove the observer. + if (aType.Equals(nsDependentCString("alertfinished"))) { + mAlertObservers.RemoveElementAt(i); + continue; + } + } + ++i; + } + return true; +} + bool ContentChild::RecvNotifyVisited(const IPC::URI& aURI) { diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 08e37055e7a2..4059b671240f 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -52,6 +52,7 @@ struct OverrideMapping; namespace mozilla { namespace dom { +class AlertObserver; class PrefObserver; class ContentChild : public PContentChild @@ -101,14 +102,20 @@ public: const nsCString& aPrefRoot, nsIObserver* aObserver); + // auto remove when alertfinished is received. + nsresult AddRemoteAlertObserver(const nsString& aData, nsIObserver* aObserver); + virtual bool RecvNotifyRemotePrefObserver(const nsCString& aDomain); + virtual bool RecvNotifyAlertsObserver(const nsCString& aType, const nsString& aData); + virtual bool RecvAsyncMessage(const nsString& aMsg, const nsString& aJSON); private: NS_OVERRIDE virtual void ActorDestroy(ActorDestroyReason why); + nsTArray > mAlertObservers; nsTArray > mPrefObservers; bool mDead; diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 2ce5f1fdba15..5e9b23c0e595 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -56,6 +56,8 @@ #include "nsExternalHelperAppService.h" #include "nsCExternalHandlerService.h" #include "nsFrameMessageManager.h" +#include "nsIAlertsService.h" +#include "nsToolkitCompsCID.h" #ifdef ANDROID #include "AndroidBridge.h" @@ -367,6 +369,13 @@ ContentParent::Observe(nsISupports* aSubject, if (!SendSetOffline(!strcmp(offline, "true") ? true : false)) return NS_ERROR_NOT_AVAILABLE; } + // listening for alert notifications + else if (!strcmp(aTopic, "alertfinished") || + !strcmp(aTopic, "alertclickcallback") ) { + if (!SendNotifyAlertsObserver(nsDependentCString(aTopic), + nsDependentString(aData))) + return NS_ERROR_NOT_AVAILABLE; + } return NS_OK; } @@ -558,6 +567,19 @@ ContentParent::RecvNotifyIME(const int& aType, const int& aStatus) #endif } +bool +ContentParent::RecvShowAlertNotification(const nsString& aImageUrl, const nsString& aTitle, + const nsString& aText, const PRBool& aTextClickable, + const nsString& aCookie, const nsString& aName) +{ + nsCOMPtr sysAlerts(do_GetService(NS_ALERTSERVICE_CONTRACTID)); + if (sysAlerts) { + sysAlerts->ShowAlertNotification(aImageUrl, aTitle, aText, aTextClickable, + aCookie, this, aName); + } + + return true; +} bool ContentParent::RecvSyncMessage(const nsString& aMsg, const nsString& aJSON, diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 0a36c1e2cd53..b475261257c5 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -158,9 +158,11 @@ private: virtual bool RecvNotifyIME(const int&, const int&); virtual bool RecvNotifyIMEChange(const nsString&, const PRUint32&, const int&, - const int&, const int&) -; + const int&, const int&); + virtual bool RecvShowAlertNotification(const nsString& aImageUrl, const nsString& aTitle, + const nsString& aText, const PRBool& aTextClickable, + const nsString& aCookie, const nsString& aName); virtual bool RecvLoadURIExternal(const IPC::URI& uri); diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index fef4cd5c4db7..5305c10be402 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -72,6 +72,8 @@ child: NotifyRemotePrefObserver(nsCString aDomain); + NotifyAlertsObserver(nsCString topic, nsString data); + parent: PNecko(); @@ -102,6 +104,13 @@ parent: sync SyncMessage(nsString aMessage, nsString aJSON) returns (nsString[] retval); + ShowAlertNotification(nsString imageUrl, + nsString title, + nsString text, + PRBool textClickable, + nsString cookie, + nsString name); + both: AsyncMessage(nsString aMessage, nsString aJSON); diff --git a/toolkit/components/alerts/src/Makefile.in b/toolkit/components/alerts/src/Makefile.in index 1f61b9001da1..304b2ac9ec29 100644 --- a/toolkit/components/alerts/src/Makefile.in +++ b/toolkit/components/alerts/src/Makefile.in @@ -55,6 +55,8 @@ CPPSRCS = \ LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/components/build/ +include $(topsrcdir)/config/config.mk +include $(topsrcdir)/ipc/chromium/chromium-config.mk include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS) diff --git a/toolkit/components/alerts/src/nsAlertsService.cpp b/toolkit/components/alerts/src/nsAlertsService.cpp index 620192ff4ebd..c4dd5a152ef3 100644 --- a/toolkit/components/alerts/src/nsAlertsService.cpp +++ b/toolkit/components/alerts/src/nsAlertsService.cpp @@ -38,6 +38,12 @@ * * ***** END LICENSE BLOCK ***** */ +#ifdef MOZ_IPC +#include "mozilla/dom/ContentChild.h" +#include "nsXULAppAPI.h" +using mozilla::dom::ContentChild; +#endif + #include "nsAlertsService.h" #ifdef ANDROID @@ -82,6 +88,23 @@ NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const nsAString & aImageUrl nsIObserver * aAlertListener, const nsAString & aAlertName) { +#ifdef MOZ_IPC + if (XRE_GetProcessType() == GeckoProcessType_Content) { + ContentChild* cpc = ContentChild::GetSingleton(); + + if (aAlertListener) + cpc->AddRemoteAlertObserver(nsDependentString(aAlertCookie), aAlertListener); + + cpc->SendShowAlertNotification(nsAutoString(aImageUrl), + nsAutoString(aAlertTitle), + nsAutoString(aAlertText), + aAlertTextClickable, + nsAutoString(aAlertCookie), + nsAutoString(aAlertName)); + return NS_OK; + } +#endif + #ifdef ANDROID mozilla::AndroidBridge::Bridge()->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertCookie, aAlertListener, aAlertName);