Bug 938889 - Remote IdleService and disable idle-daily notifications in content processes. r=roc

This commit is contained in:
Reuben Morais 2013-12-13 14:28:46 -02:00
parent c34e0e7754
commit 7c641f6b3b
6 changed files with 133 additions and 10 deletions

View File

@ -1502,6 +1502,33 @@ ContentChild::RecvNotifyPhoneStateChange(const nsString& aState)
return true;
}
void
ContentChild::AddIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS)
{
MOZ_ASSERT(aObserver, "null idle observer");
// Make sure aObserver isn't released while we wait for the parent
aObserver->AddRef();
SendAddIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
}
void
ContentChild::RemoveIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS)
{
MOZ_ASSERT(aObserver, "null idle observer");
SendRemoveIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
aObserver->Release();
}
bool
ContentChild::RecvNotifyIdleObserver(const uint64_t& aObserver,
const nsCString& aTopic,
const nsString& aTimeStr)
{
nsIObserver* observer = reinterpret_cast<nsIObserver*>(aObserver);
observer->Observe(nullptr, aTopic.get(), aTimeStr.get());
return true;
}
bool
ContentChild::RecvLoadAndRegisterSheet(const URIParams& aURI, const uint32_t& aType)
{

View File

@ -240,6 +240,12 @@ public:
virtual bool RecvUnregisterSheet(const URIParams& aURI, const uint32_t& aType);
virtual bool RecvNotifyPhoneStateChange(const nsString& state);
void AddIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS);
void RemoveIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS);
virtual bool RecvNotifyIdleObserver(const uint64_t& aObserver,
const nsCString& aTopic,
const nsString& aData);
#ifdef ANDROID
gfxIntSize GetScreenSize() { return mScreenSize; }
#endif

View File

@ -68,6 +68,7 @@
#include "nsIDOMWindow.h"
#include "nsIExternalProtocolService.h"
#include "nsIFilePicker.h"
#include "nsIIdleService.h"
#include "nsIMemoryReporter.h"
#include "nsIMozBrowserFrame.h"
#include "nsIMutable.h"
@ -1082,6 +1083,8 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
obs->NotifyObservers((nsIPropertyBag2*) props, "ipc:content-shutdown", nullptr);
}
mIdleListeners.Clear();
// If the child process was terminated due to a SIGKIL, ShutDownProcess
// might not have been called yet. We must call it to ensure that our
// channel is closed, etc.
@ -3155,5 +3158,47 @@ ContentParent::RecvRecordingDeviceEvents(const nsString& aRecordingStatus,
return true;
}
bool
ContentParent::RecvAddIdleObserver(const uint64_t& aObserver, const uint32_t& aIdleTimeInS)
{
nsresult rv;
nsCOMPtr<nsIIdleService> idleService =
do_GetService("@mozilla.org/widget/idleservice;1", &rv);
NS_ENSURE_SUCCESS(rv, false);
nsCOMPtr<ParentIdleListener> listener = new ParentIdleListener(this, aObserver);
mIdleListeners.Put(aObserver, listener);
idleService->AddIdleObserver(listener, aIdleTimeInS);
return true;
}
bool
ContentParent::RecvRemoveIdleObserver(const uint64_t& aObserver, const uint32_t& aIdleTimeInS)
{
nsresult rv;
nsCOMPtr<nsIIdleService> idleService =
do_GetService("@mozilla.org/widget/idleservice;1", &rv);
NS_ENSURE_SUCCESS(rv, false);
nsCOMPtr<ParentIdleListener> listener;
bool found = mIdleListeners.Get(aObserver, &listener);
if (found) {
mIdleListeners.Remove(aObserver);
idleService->RemoveIdleObserver(listener, aIdleTimeInS);
}
return true;
}
} // namespace dom
} // namespace mozilla
NS_IMPL_ISUPPORTS1(ParentIdleListener, nsIObserver)
NS_IMETHODIMP
ParentIdleListener::Observe(nsISupports*, const char* aTopic, const PRUnichar* aData) {
mozilla::unused << mParent->SendNotifyIdleObserver(mObserver,
nsDependentCString(aTopic),
nsDependentString(aData));
return NS_OK;
}

View File

@ -15,7 +15,9 @@
#include "mozilla/LinkedList.h"
#include "mozilla/StaticPtr.h"
#include "nsDataHashtable.h"
#include "nsFrameMessageManager.h"
#include "nsHashKeys.h"
#include "nsIObserver.h"
#include "nsIThreadInternal.h"
#include "nsIDOMGeoPositionCallback.h"
@ -27,7 +29,7 @@ class mozIApplication;
class nsConsoleService;
class nsIDOMBlob;
class nsIMemoryReporter;
template<class KeyClass,class DataType> class nsDataHashtable;
class ParentIdleListener;
namespace mozilla {
@ -510,6 +512,9 @@ private:
virtual void ProcessingError(Result what) MOZ_OVERRIDE;
virtual bool RecvAddIdleObserver(const uint64_t& observerId, const uint32_t& aIdleTimeInS);
virtual bool RecvRemoveIdleObserver(const uint64_t& observerId, const uint32_t& aIdleTimeInS);
// If you add strong pointers to cycle collected objects here, be sure to
// release these objects in ShutDownProcess. See the comment there for more
// details.
@ -559,9 +564,25 @@ private:
nsRefPtr<nsConsoleService> mConsoleService;
nsConsoleService* GetConsoleService();
nsDataHashtable<nsUint64HashKey, nsCOMPtr<ParentIdleListener> > mIdleListeners;
};
} // namespace dom
} // namespace mozilla
class ParentIdleListener : public nsIObserver {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
ParentIdleListener(mozilla::dom::ContentParent* aParent, uint64_t aObserver)
: mParent(aParent), mObserver(aObserver)
{}
virtual ~ParentIdleListener() {}
private:
nsRefPtr<mozilla::dom::ContentParent> mParent;
uint64_t mObserver;
};
#endif

View File

@ -325,6 +325,11 @@ child:
async UnregisterSheet(URIParams uri, uint32_t type);
NotifyPhoneStateChange(nsString newState);
/**
* Notify idle observers in the child
*/
NotifyIdleObserver(uint64_t observerId, nsCString topic, nsString str);
parent:
/**
* Tell the content process some attributes of itself. This is
@ -502,6 +507,8 @@ parent:
bool isAudio,
bool isVideo);
AddIdleObserver(uint64_t observerId, uint32_t idleTimeInS);
RemoveIdleObserver(uint64_t observerId, uint32_t idleTimeInS);
both:
AsyncMessage(nsString aMessage, ClonedMessageData aData,
CpowEntry[] aCpows, Principal aPrincipal);

View File

@ -11,9 +11,11 @@
#include "nsIServiceManager.h"
#include "nsDebug.h"
#include "nsCOMArray.h"
#include "nsXULAppAPI.h"
#include "prinrval.h"
#include "prlog.h"
#include "prtime.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/Services.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
@ -397,8 +399,10 @@ nsIdleService::nsIdleService() : mCurrentlySetToTimeoutAt(TimeStamp()),
#endif
MOZ_ASSERT(!gIdleService);
gIdleService = this;
mDailyIdle = new nsIdleServiceDaily(this);
mDailyIdle->Init();
if (XRE_GetProcessType() == GeckoProcessType_Default) {
mDailyIdle = new nsIdleServiceDaily(this);
mDailyIdle->Init();
}
}
nsIdleService::~nsIdleService()
@ -417,20 +421,26 @@ NS_IMPL_ISUPPORTS2(nsIdleService, nsIIdleService, nsIIdleServiceInternal)
NS_IMETHODIMP
nsIdleService::AddIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS)
{
NS_ENSURE_ARG_POINTER(aObserver);
// We don't accept idle time at 0, and we can't handle idle time that are too
// high either - no more than ~136 years.
NS_ENSURE_ARG_RANGE(aIdleTimeInS, 1, (UINT32_MAX / 10) - 1);
if (XRE_GetProcessType() == GeckoProcessType_Content) {
dom::ContentChild* cpc = dom::ContentChild::GetSingleton();
cpc->AddIdleObserver(aObserver, aIdleTimeInS);
return NS_OK;
}
PR_LOG(sLog, PR_LOG_DEBUG,
("idleService: Register idle observer %x for %d seconds",
aObserver, aIdleTimeInS));
("idleService: Register idle observer %x for %d seconds",
aObserver, aIdleTimeInS));
#ifdef MOZ_WIDGET_ANDROID
__android_log_print(ANDROID_LOG_INFO, "IdleService",
"Register idle observer %x for %d seconds",
aObserver, aIdleTimeInS);
#endif
NS_ENSURE_ARG_POINTER(aObserver);
// We don't accept idle time at 0, and we can't handle idle time that are too
// high either - no more than ~136 years.
NS_ENSURE_ARG_RANGE(aIdleTimeInS, 1, (UINT32_MAX / 10) - 1);
// Put the time + observer in a struct we can keep:
IdleListener listener(aObserver, aIdleTimeInS);
@ -474,6 +484,13 @@ nsIdleService::RemoveIdleObserver(nsIObserver* aObserver, uint32_t aTimeInS)
NS_ENSURE_ARG_POINTER(aObserver);
NS_ENSURE_ARG(aTimeInS);
if (XRE_GetProcessType() == GeckoProcessType_Content) {
dom::ContentChild* cpc = dom::ContentChild::GetSingleton();
cpc->RemoveIdleObserver(aObserver, aTimeInS);
return NS_OK;
}
IdleListener listener(aObserver, aTimeInS);
// Find the entry and remove it, if it was the last entry, we just let the