From 50b5ccd2c241f3fab0b9ba261d83e4920a2bae55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kan-Ru=20Chen=20=28=E9=99=B3=E4=BE=83=E5=A6=82=29?= Date: Wed, 11 Feb 2015 11:18:32 +0100 Subject: [PATCH] Bug 1126119 - Create SystemMessageCache and cache hasPendingMessage in content process. r=fabrice --- b2g/installer/package-manifest.in | 1 + browser/installer/package-manifest.in | 1 + dom/ipc/ContentChild.cpp | 5 ++ dom/ipc/ContentParent.cpp | 13 ++- dom/messages/SystemMessageCache.js | 84 +++++++++++++++++++ dom/messages/SystemMessageInternal.js | 48 ++++++----- dom/messages/SystemMessageManager.js | 14 +++- dom/messages/SystemMessageManager.manifest | 3 + dom/messages/interfaces/moz.build | 1 + .../interfaces/nsISystemMessageCache.idl | 13 +++ .../interfaces/nsISystemMessagesInternal.idl | 7 ++ dom/messages/moz.build | 1 + 12 files changed, 167 insertions(+), 24 deletions(-) create mode 100644 dom/messages/SystemMessageCache.js create mode 100644 dom/messages/interfaces/nsISystemMessageCache.idl diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index 292124bc9772..a9c609fb3eb6 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -594,6 +594,7 @@ @BINPATH@/components/SystemMessageInternal.js @BINPATH@/components/SystemMessageManager.js +@BINPATH@/components/SystemMessageCache.js @BINPATH@/components/SystemMessageManager.manifest @BINPATH@/components/HCIEventTransactionSystemMessage.manifest @BINPATH@/components/HCIEventTransactionSystemMessageConfigurator.js diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index 500eb80f929e..c976bb96d5fa 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -579,6 +579,7 @@ @RESPATH@/components/TCPSocket.manifest #ifdef MOZ_ACTIVITIES +@RESPATH@/components/SystemMessageCache.js @RESPATH@/components/SystemMessageInternal.js @RESPATH@/components/SystemMessageManager.js @RESPATH@/components/SystemMessageManager.manifest diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 456b35268112..df00b5ca32bd 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -91,6 +91,7 @@ #include "nsAnonymousTemporaryFile.h" #include "nsISpellChecker.h" #include "nsClipboardProxy.h" +#include "nsISystemMessageCache.h" #include "IHistory.h" #include "nsNetUtil.h" @@ -530,6 +531,10 @@ InitOnContentProcessCreated() PostForkPreload(); #endif + nsCOMPtr smc = + do_GetService("@mozilla.org/system-message-cache;1"); + NS_WARN_IF(!smc); + // This will register cross-process observer. mozilla::dom::time::InitializeDateCacheCleaner(); } diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 52e6a69f959d..b799bfc3e224 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -119,6 +119,7 @@ #include "nsISpellChecker.h" #include "nsIStyleSheet.h" #include "nsISupportsPrimitives.h" +#include "nsISystemMessagesInternal.h" #include "nsITimer.h" #include "nsIURIFixup.h" #include "nsIWindowWatcher.h" @@ -1324,11 +1325,21 @@ ContentParent::ForwardKnownInfo() #ifdef MOZ_WIDGET_GONK InfallibleTArray volumeInfo; nsRefPtr vs = nsVolumeService::GetSingleton(); - if (vs) { + if (vs && !mIsForBrowser) { vs->GetVolumesForIPC(&volumeInfo); unused << SendVolumes(volumeInfo); } #endif /* MOZ_WIDGET_GONK */ + + nsCOMPtr systemMessenger = + do_GetService("@mozilla.org/system-message-internal;1"); + if (systemMessenger && !mIsForBrowser) { + nsCOMPtr manifestURI; + nsresult rv = NS_NewURI(getter_AddRefs(manifestURI), mAppManifestURL); + if (NS_SUCCEEDED(rv)) { + systemMessenger->RefreshCache(mMessageManager, manifestURI); + } + } } namespace { diff --git a/dom/messages/SystemMessageCache.js b/dom/messages/SystemMessageCache.js new file mode 100644 index 000000000000..fcf1fffa6a82 --- /dev/null +++ b/dom/messages/SystemMessageCache.js @@ -0,0 +1,84 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const Ci = Components.interfaces; +const Cu = Components.utils; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +XPCOMUtils.defineLazyServiceGetter(this, "cpmm", + "@mozilla.org/childprocessmessagemanager;1", + "nsISyncMessageSender"); + +function debug(aMsg) { + // dump("-- SystemMessageCache " + Date.now() + " : " + aMsg + "\n"); +} + +const kMessages = ["SystemMessageCache:RefreshCache"]; + +function SystemMessageCache() { + debug("init"); + + this._pagesCache = []; + + dump("SystemMessageCache: init"); + Services.obs.addObserver(this, "xpcom-shutdown", false); + kMessages.forEach(function(aMessage) { + cpmm.addMessageListener(aMessage, this); + }, this); +} + +SystemMessageCache.prototype = { + + observe: function(aSubject, aTopic, aData) { + switch (aTopic) { + case "xpcom-shutdown": + debug("received xpcom-shutdown"); + kMessages.forEach(function(aMessage) { + cpmm.removeMessageListener(aMessage, this); + }, this); + Services.obs.removeObserver(this, "xpcom-shutdown"); + cpmm = null; + break; + default: + break; + } + }, + + receiveMessage: function(aMessage) { + switch (aMessage.name) { + case "SystemMessageCache:RefreshCache": + this._pagesCache = aMessage.data; + debug("received RefreshCache"); + break; + default: + debug("received unknown message " + aMessage.name); + break; + } + }, + + hasPendingMessage: function(aType, aPageURL, aManifestURL) { + let hasMessage = this._pagesCache.some(function(aPage) { + if (aPage.type === aType && + aPage.pageURL === aPageURL && + aPage.manifestURL === aManifestURL) { + return true; + } + return false; + }, this); + debug("hasPendingMessage " + aType + " " + aPageURL + " " + + aManifestURL + ": " + hasMessage); + return hasMessage; + }, + + classID: Components.ID("{5a19d86a-21e5-4ac8-9634-8c364c73f87f}"), + QueryInterface: XPCOMUtils.generateQI([Ci.nsISystemMessageCache, + Ci.nsIMessageListener, + Ci.nsIObserver]) +}; + +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SystemMessageCache]); diff --git a/dom/messages/SystemMessageInternal.js b/dom/messages/SystemMessageInternal.js index c6305701cb5e..7cb25228c217 100644 --- a/dom/messages/SystemMessageInternal.js +++ b/dom/messages/SystemMessageInternal.js @@ -40,14 +40,13 @@ try { } const kMessages =["SystemMessageManager:GetPendingMessages", - "SystemMessageManager:HasPendingMessages", "SystemMessageManager:Register", "SystemMessageManager:Unregister", "SystemMessageManager:Message:Return:OK", "SystemMessageManager:AskReadyToRegister", "SystemMessageManager:HandleMessagesDone", "SystemMessageManager:HandleMessageDone", - "child-process-shutdown"] + "child-process-shutdown"]; function debug(aMsg) { // dump("-- SystemMessageInternal " + Date.now() + " : " + aMsg + "\n"); @@ -178,6 +177,19 @@ SystemMessageInternal.prototype = { return page; }, + _findCacheForApp: function(aManifestURL) { + let cache = []; + this._pages.forEach(function(aPage) { + if (aPage.manifestURL === aManifestURL && + aPage.pendingMessages.length != 0) { + cache.push({ type: aPage.type, + pageURL: aPage.pageURL, + manifestURL: aPage.manifestURL }); + } + }); + return cache; + }, + sendMessage: function(aType, aMessage, aPageURI, aManifestURI, aExtra) { return new Promise((aResolve, aReject) => { this.sendMessageInternal(aType, aMessage, aPageURI, aManifestURI, aExtra, @@ -349,6 +361,18 @@ SystemMessageInternal.prototype = { pendingMessages: [] }); }, + refreshCache: function(aChildMM, aManifestURI) { + if (!aManifestURI) { + throw Cr.NS_ERROR_INVALID_ARG; + } + this._refreshCacheInternal(aChildMM, aManifestURI.spec); + }, + + _refreshCacheInternal: function(aChildMM, aManifestURL) { + let cache = this._findCacheForApp(aManifestURL); + aChildMM.sendAsyncMessage("SystemMessageCache:RefreshCache", cache); + }, + _findTargetIndex: function(aTargets, aTarget) { if (!aTargets || !aTarget) { return -1; @@ -417,7 +441,6 @@ SystemMessageInternal.prototype = { // TODO: fix bug 988142 to re-enable. // "SystemMessageManager:Unregister", "SystemMessageManager:GetPendingMessages", - "SystemMessageManager:HasPendingMessages", "SystemMessageManager:Message:Return:OK", "SystemMessageManager:HandleMessagesDone", "SystemMessageManager:HandleMessageDone"].indexOf(aMessage.name) != -1) { @@ -456,6 +479,7 @@ SystemMessageInternal.prototype = { } } + this._refreshCacheInternal(aMessage.target, msg.manifestURL); debug("listeners for " + msg.manifestURL + " innerWinID " + msg.innerWindowID); break; @@ -514,21 +538,7 @@ SystemMessageInternal.prototype = { manifestURL: msg.manifestURL, pageURL: msg.pageURL, msgQueue: pendingMessages }); - break; - } - case "SystemMessageManager:HasPendingMessages": - { - debug("received SystemMessageManager:HasPendingMessages " + msg.type + - " for " + msg.pageURL + " @ " + msg.manifestURL); - - // This is a sync call used to return if a page has pending messages. - // Find the right page to get its corresponding pending messages. - let page = this._findPage(msg.type, msg.pageURL, msg.manifestURL); - if (!page) { - return false; - } - - return page.pendingMessages.length != 0; + this._refreshCacheInternal(aMessage.target, msg.manifestURL); break; } case "SystemMessageManager:Message:Return:OK": @@ -697,7 +707,7 @@ SystemMessageInternal.prototype = { _isPageMatched: function(aPage, aType, aPageURL, aManifestURL) { return (aPage.type === aType && aPage.manifestURL === aManifestURL && - aPage.pageURL === aPageURL) + aPage.pageURL === aPageURL); }, _createKeyForPage: function _createKeyForPage(aPage) { diff --git a/dom/messages/SystemMessageManager.js b/dom/messages/SystemMessageManager.js index 31925e15c12d..d326c2d1b602 100644 --- a/dom/messages/SystemMessageManager.js +++ b/dom/messages/SystemMessageManager.js @@ -193,10 +193,16 @@ SystemMessageManager.prototype = { return false; } - return cpmm.sendSyncMessage("SystemMessageManager:HasPendingMessages", - { type: aType, - pageURL: this._pageURL, - manifestURL: this._manifestURL })[0]; + + /* + * NB: If the system message is fired after we received the cache + * and before we registered the pageURL we will get false + * negative however this is unlikely and will do no harm. + */ + let cache = Cc["@mozilla.org/system-message-cache;1"] + .getService(Ci.nsISystemMessageCache); + + return cache.hasPendingMessage(aType, this._pageURL, this._manifestURL); }, mozIsHandlingMessage: function() { diff --git a/dom/messages/SystemMessageManager.manifest b/dom/messages/SystemMessageManager.manifest index 307bd40d8979..33b95f2f7a32 100644 --- a/dom/messages/SystemMessageManager.manifest +++ b/dom/messages/SystemMessageManager.manifest @@ -3,3 +3,6 @@ contract @mozilla.org/system-message-manager;1 {bc076ea0-609b-4d8f-83d7-5af7cbdc component {70589ca5-91ac-4b9e-b839-d6a88167d714} SystemMessageInternal.js contract @mozilla.org/system-message-internal;1 {70589ca5-91ac-4b9e-b839-d6a88167d714} + +component {5a19d86a-21e5-4ac8-9634-8c364c73f87f} SystemMessageCache.js +contract @mozilla.org/system-message-cache;1 {5a19d86a-21e5-4ac8-9634-8c364c73f87f} diff --git a/dom/messages/interfaces/moz.build b/dom/messages/interfaces/moz.build index 3089f53b16d0..269f88cd30b9 100644 --- a/dom/messages/interfaces/moz.build +++ b/dom/messages/interfaces/moz.build @@ -6,6 +6,7 @@ XPIDL_SOURCES += [ 'nsIDOMNavigatorSystemMessages.idl', + 'nsISystemMessageCache.idl', 'nsISystemMessageGlue.idl', 'nsISystemMessagesInternal.idl', ] diff --git a/dom/messages/interfaces/nsISystemMessageCache.idl b/dom/messages/interfaces/nsISystemMessageCache.idl new file mode 100644 index 000000000000..4cfc8440b0ac --- /dev/null +++ b/dom/messages/interfaces/nsISystemMessageCache.idl @@ -0,0 +1,13 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +[scriptable, uuid(e888447c-6d4d-4045-92bd-1a5985404375)] +interface nsISystemMessageCache : nsISupports +{ + boolean hasPendingMessage(in DOMString type, + in DOMString pageURL, + in DOMString manifestURL); +}; diff --git a/dom/messages/interfaces/nsISystemMessagesInternal.idl b/dom/messages/interfaces/nsISystemMessagesInternal.idl index dbd48dfb9284..ad6f95121d1a 100644 --- a/dom/messages/interfaces/nsISystemMessagesInternal.idl +++ b/dom/messages/interfaces/nsISystemMessagesInternal.idl @@ -6,6 +6,7 @@ interface nsIURI; interface nsIDOMWindow; +interface nsIMessageSender; // Implemented by the contract id @mozilla.org/system-message-internal;1 @@ -45,6 +46,12 @@ interface nsISystemMessagesInternal : nsISupports * @param manifestURI The webapp's manifest URI. */ void registerPage(in DOMString type, in nsIURI pageURI, in nsIURI manifestURI); + + /* + * Refresh the system message cache in a content process. + * @param manifestURI The webapp's manifest URI. + */ + void refreshCache(in nsIMessageSender childMM, in nsIURI manifestURI); }; [scriptable, uuid(002f0e82-91f0-41de-ad43-569a2b9d12df)] diff --git a/dom/messages/moz.build b/dom/messages/moz.build index 19d8125a58a9..c8d978705944 100644 --- a/dom/messages/moz.build +++ b/dom/messages/moz.build @@ -7,6 +7,7 @@ DIRS += ['interfaces'] EXTRA_COMPONENTS += [ + 'SystemMessageCache.js', 'SystemMessageInternal.js', 'SystemMessageManager.js', 'SystemMessageManager.manifest',