Bug 697132 - Implement wakelock interfaces. r=jlebar

This commit is contained in:
Kan-Ru Chen 2012-03-07 12:03:25 +01:00
parent 4cd89227bb
commit 255811e424
27 changed files with 1343 additions and 28 deletions

View File

@ -70,6 +70,8 @@
#include "mozilla/Telemetry.h"
#include "BatteryManager.h"
#include "PowerManager.h"
#include "nsIDOMWakeLock.h"
#include "nsIPowerManagerService.h"
#include "SmsManager.h"
#include "nsISmsService.h"
#include "mozilla/Hal.h"
@ -172,7 +174,10 @@ Navigator::Invalidate()
mBatteryManager = nsnull;
}
mPowerManager = nsnull;
if (mPowerManager) {
mPowerManager->Shutdown();
mPowerManager = nsnull;
}
if (mSmsManager) {
mSmsManager->Shutdown();
@ -958,15 +963,38 @@ Navigator::GetMozBattery(nsIDOMMozBatteryManager** aBattery)
NS_IMETHODIMP
Navigator::GetMozPower(nsIDOMMozPowerManager** aPower)
{
*aPower = nsnull;
if (!mPowerManager) {
nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(win, NS_OK);
mPowerManager = new power::PowerManager();
mPowerManager->Init(win);
}
NS_ADDREF(*aPower = mPowerManager);
nsCOMPtr<nsIDOMMozPowerManager> power =
do_QueryInterface(NS_ISUPPORTS_CAST(nsIDOMMozPowerManager*, mPowerManager));
power.forget(aPower);
return NS_OK;
}
NS_IMETHODIMP
Navigator::RequestWakeLock(const nsAString &aTopic, nsIDOMMozWakeLock **aWakeLock)
{
*aWakeLock = nsnull;
nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(win, NS_OK);
nsCOMPtr<nsIPowerManagerService> pmService =
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
NS_ENSURE_TRUE(pmService, NS_OK);
return pmService->NewWakeLock(aTopic, win, aWakeLock);
}
//*****************************************************************************
// Navigator::nsIDOMNavigatorSms
//*****************************************************************************

View File

@ -507,6 +507,7 @@ using mozilla::dom::indexedDB::IDBWrapperCache;
#include "nsIDOMBatteryManager.h"
#include "BatteryManager.h"
#include "nsIDOMPowerManager.h"
#include "nsIDOMWakeLock.h"
#include "nsIDOMSmsManager.h"
#include "nsIDOMSmsMessage.h"
#include "nsIDOMSmsEvent.h"
@ -1436,6 +1437,9 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(MozPowerManager, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MozWakeLock, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MozSmsManager, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -4031,6 +4035,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozPowerManager)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(MozWakeLock, nsIDOMMozWakeLock)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozWakeLock)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(MozSmsManager, nsIDOMMozSmsManager)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsManager)
DOM_CLASSINFO_MAP_END

View File

@ -429,6 +429,7 @@ DOMCI_CLASS(GeoPositionError)
DOMCI_CLASS(MozBatteryManager)
DOMCI_CLASS(MozPowerManager)
DOMCI_CLASS(MozWakeLock)
DOMCI_CLASS(MozSmsManager)
DOMCI_CLASS(MozSmsMessage)

View File

@ -131,3 +131,4 @@ interface nsIDOMFontFaceList;
// Power
interface nsIDOMMozPowerManager;
interface nsIDOMMozWakeLock;

View File

@ -39,7 +39,7 @@
#include "domstubs.idl"
[scriptable, uuid(b1f4b1fa-49c2-4375-9ce8-bf97ecf6b428)]
[scriptable, uuid(e610c037-db58-4cd7-8ed3-0d7f1422b4d3)]
interface nsIDOMNavigator : nsISupports
{
readonly attribute DOMString appCodeName;
@ -110,4 +110,34 @@ interface nsIDOMNavigator : nsISupports
*/
[implicit_jscontext]
void mozVibrate(in jsval aPattern);
/**
* Request a wake lock for a resource.
*
* A page holds a wake lock to request that a resource not be turned
* off (or otherwise made unavailable).
*
* The topic is the name of a resource that might be made unavailable for
* various reasons. For example, on a mobile device the power manager might
* decide to turn off the screen after a period of idle time to save power.
*
* The resource manager checks the lock state of a topic before turning off
* the associated resource. For example, a page could hold a lock on the
* "screen" topic to prevent the screensaver from appearing or the screen
* from turning off.
*
* The resource manager defines what each topic means and sets policy. For
* example, the resource manager might decide to ignore 'screen' wake locks
* held by pages which are not visible.
*
* One topic can be locked multiple times; it is considered released only when
* all locks on the topic have been released.
*
* The returned nsIDOMMozWakeLock object is a token of the lock. You can
* unlock the lock via the object's |unlock| method. The lock is released
* automatically when its associated window is unloaded.
*
* @param aTopic resource name
*/
nsIDOMMozWakeLock requestWakeLock(in DOMString aTopic);
};

View File

@ -52,15 +52,19 @@ EXPORTS_NAMESPACES = mozilla/dom/power
EXPORTS_mozilla/dom/power = \
PowerManagerService.h \
Types.h \
$(NULL)
CPPSRCS = \
PowerManager.cpp \
PowerManagerService.cpp \
WakeLock.cpp \
$(NULL)
XPIDLSRCS = \
nsIDOMPowerManager.idl \
nsIDOMWakeLock.idl \
nsIDOMWakeLockListener.idl \
nsIPowerManagerService.idl \
$(NULL)

View File

@ -36,9 +36,13 @@
* ***** END LICENSE BLOCK ***** */
#include "PowerManager.h"
#include "WakeLock.h"
#include "nsContentUtils.h"
#include "nsDOMClassInfoID.h"
#include "nsIDOMWakeLockListener.h"
#include "nsIPowerManagerService.h"
#include "nsIPrincipal.h"
#include "nsPIDOMWindow.h"
#include "nsServiceManagerUtils.h"
DOMCI_DATA(MozPowerManager, mozilla::dom::power::PowerManager)
@ -50,20 +54,66 @@ namespace power {
NS_INTERFACE_MAP_BEGIN(PowerManager)
NS_INTERFACE_MAP_ENTRY(nsIDOMMozPowerManager)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozPowerManager)
NS_INTERFACE_MAP_ENTRY(nsIDOMMozWakeLockListener)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozPowerManager)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(PowerManager)
NS_IMPL_RELEASE(PowerManager)
NS_IMETHODIMP
PowerManager::Reboot()
nsresult
PowerManager::Init(nsIDOMWindow *aWindow)
{
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR);
mWindow = do_GetWeakReference(aWindow);
nsCOMPtr<nsIPowerManagerService> pmService =
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
NS_ENSURE_TRUE(pmService, NS_OK);
NS_ENSURE_STATE(pmService);
// Add ourself to the global notification list.
pmService->AddWakeLockListener(this);
return NS_OK;
}
nsresult
PowerManager::Shutdown()
{
nsCOMPtr<nsIPowerManagerService> pmService =
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
NS_ENSURE_STATE(pmService);
// Remove ourself from the global notification list.
pmService->RemoveWakeLockListener(this);
return NS_OK;
}
nsresult
PowerManager::CheckPermission()
{
nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mWindow);
NS_ENSURE_STATE(win);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(win->GetExtantDocument());
NS_ENSURE_STATE(doc);
nsCOMPtr<nsIURI> uri;
doc->NodePrincipal()->GetURI(getter_AddRefs(uri));
if (!nsContentUtils::URIIsChromeOrInPref(uri, "dom.power.whitelist")) {
return NS_ERROR_DOM_SECURITY_ERR;
}
return NS_OK;
}
NS_IMETHODIMP
PowerManager::Reboot()
{
nsresult rv = CheckPermission();
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPowerManagerService> pmService =
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
NS_ENSURE_STATE(pmService);
pmService->Reboot();
@ -73,17 +123,74 @@ PowerManager::Reboot()
NS_IMETHODIMP
PowerManager::PowerOff()
{
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR);
nsresult rv = CheckPermission();
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPowerManagerService> pmService =
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
NS_ENSURE_TRUE(pmService, NS_OK);
NS_ENSURE_STATE(pmService);
pmService->PowerOff();
return NS_OK;
}
NS_IMETHODIMP
PowerManager::AddWakeLockListener(nsIDOMMozWakeLockListener *aListener)
{
nsresult rv = CheckPermission();
NS_ENSURE_SUCCESS(rv, rv);
// already added? bail out.
if (mListeners.Contains(aListener))
return NS_OK;
mListeners.AppendElement(aListener);
return NS_OK;
}
NS_IMETHODIMP
PowerManager::RemoveWakeLockListener(nsIDOMMozWakeLockListener *aListener)
{
nsresult rv = CheckPermission();
NS_ENSURE_SUCCESS(rv, rv);
mListeners.RemoveElement(aListener);
return NS_OK;
}
NS_IMETHODIMP
PowerManager::GetWakeLockState(const nsAString &aTopic, nsAString &aState)
{
nsresult rv = CheckPermission();
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPowerManagerService> pmService =
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
NS_ENSURE_STATE(pmService);
return pmService->GetWakeLockState(aTopic, aState);
}
NS_IMETHODIMP
PowerManager::Callback(const nsAString &aTopic, const nsAString &aState)
{
/**
* We maintain a local listener list instead of using the global
* list so that when the window is destroyed we don't have to
* cleanup the mess.
* Copy the listeners list before we walk through the callbacks
* because the callbacks may install new listeners. We expect no
* more than one listener per window, so it shouldn't be too long.
*/
nsAutoTArray<nsCOMPtr<nsIDOMMozWakeLockListener>, 2> listeners(mListeners);
for (PRUint32 i = 0; i < listeners.Length(); ++i) {
listeners[i]->Callback(aTopic, aState);
}
return NS_OK;
}
} // power
} // dom
} // mozilla

View File

@ -37,7 +37,12 @@
#ifndef mozilla_dom_power_PowerManager_h
#define mozilla_dom_power_PowerManager_h
#include "nsCOMPtr.h"
#include "nsTArray.h"
#include "nsIDOMPowerManager.h"
#include "nsIDOMWakeLockListener.h"
#include "nsIDOMWindow.h"
#include "nsWeakReference.h"
namespace mozilla {
namespace dom {
@ -45,13 +50,24 @@ namespace power {
class PowerManager
: public nsIDOMMozPowerManager
, public nsIDOMMozWakeLockListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMMOZPOWERMANAGER
NS_DECL_NSIDOMMOZWAKELOCKLISTENER
PowerManager() {};
virtual ~PowerManager() {};
nsresult Init(nsIDOMWindow *aWindow);
nsresult Shutdown();
private:
nsresult CheckPermission();
nsWeakPtr mWindow;
nsTArray<nsCOMPtr<nsIDOMMozWakeLockListener> > mListeners;
};
} // namespace power

View File

@ -36,7 +36,12 @@
* ***** END LICENSE BLOCK ***** */
#include "mozilla/Hal.h"
#include "mozilla/HalWakeLock.h"
#include "mozilla/ClearOnShutdown.h"
#include "nsIDOMWakeLockListener.h"
#include "nsIDOMWindow.h"
#include "PowerManagerService.h"
#include "WakeLock.h"
namespace mozilla {
namespace dom {
@ -44,14 +49,67 @@ namespace power {
NS_IMPL_ISUPPORTS1(PowerManagerService, nsIPowerManagerService)
/* static */ nsRefPtr<PowerManagerService> PowerManagerService::sSingleton;
/* static */ already_AddRefed<nsIPowerManagerService>
PowerManagerService::GetInstance()
{
nsCOMPtr<nsIPowerManagerService> pmService;
if (!sSingleton) {
sSingleton = new PowerManagerService();
sSingleton->Init();
ClearOnShutdown(&sSingleton);
}
pmService = new PowerManagerService();
nsCOMPtr<nsIPowerManagerService> service(do_QueryInterface(sSingleton));
return service.forget();
}
return pmService.forget();
void
PowerManagerService::Init()
{
hal::RegisterWakeLockObserver(this);
}
PowerManagerService::~PowerManagerService()
{
hal::UnregisterWakeLockObserver(this);
}
void
PowerManagerService::ComputeWakeLockState(const hal::WakeLockInformation& aWakeLockInfo,
nsAString &aState)
{
hal::WakeLockState state = hal::ComputeWakeLockState(aWakeLockInfo.numLocks(),
aWakeLockInfo.numHidden());
switch (state) {
case hal::WAKE_LOCK_STATE_UNLOCKED:
aState.AssignLiteral("unlocked");
break;
case hal::WAKE_LOCK_STATE_HIDDEN:
aState.AssignLiteral("locked-background");
break;
case hal::WAKE_LOCK_STATE_VISIBLE:
aState.AssignLiteral("locked-foreground");
break;
}
}
void
PowerManagerService::Notify(const hal::WakeLockInformation& aWakeLockInfo)
{
nsAutoString state;
ComputeWakeLockState(aWakeLockInfo, state);
/**
* Copy the listeners list before we walk through the callbacks
* because the callbacks may install new listeners. We expect no
* more than one listener per window, so it shouldn't be too long.
*/
nsAutoTArray<nsCOMPtr<nsIDOMMozWakeLockListener>, 2> listeners(mWakeLockListeners);
for (PRUint32 i = 0; i < listeners.Length(); ++i) {
listeners[i]->Callback(aWakeLockInfo.topic(), state);
}
}
NS_IMETHODIMP
@ -68,6 +126,50 @@ PowerManagerService::PowerOff()
return NS_OK;
}
NS_IMETHODIMP
PowerManagerService::AddWakeLockListener(nsIDOMMozWakeLockListener *aListener)
{
if (mWakeLockListeners.Contains(aListener))
return NS_OK;
mWakeLockListeners.AppendElement(aListener);
return NS_OK;
}
NS_IMETHODIMP
PowerManagerService::RemoveWakeLockListener(nsIDOMMozWakeLockListener *aListener)
{
mWakeLockListeners.RemoveElement(aListener);
return NS_OK;
}
NS_IMETHODIMP
PowerManagerService::GetWakeLockState(const nsAString &aTopic, nsAString &aState)
{
hal::WakeLockInformation info;
hal::GetWakeLockInfo(aTopic, &info);
ComputeWakeLockState(info, aState);
return NS_OK;
}
NS_IMETHODIMP
PowerManagerService::NewWakeLock(const nsAString &aTopic,
nsIDOMWindow *aWindow,
nsIDOMMozWakeLock **aWakeLock)
{
nsRefPtr<WakeLock> wakelock = new WakeLock();
nsresult rv = wakelock->Init(aTopic, aWindow);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMMozWakeLock> wl =
do_QueryInterface(NS_ISUPPORTS_CAST(nsIDOMMozWakeLock*, wakelock));
wl.forget(aWakeLock);
return NS_OK;
}
} // power
} // dom
} // mozilla

View File

@ -37,8 +37,13 @@
#ifndef mozilla_dom_power_PowerManagerService_h
#define mozilla_dom_power_PowerManagerService_h
#include "nsCOMPtr.h"
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
#include "nsTArray.h"
#include "nsIPowerManagerService.h"
#include "nsCOMPtr.h" // for already_AddRefed
#include "mozilla/Observer.h"
#include "Types.h"
namespace mozilla {
namespace dom {
@ -46,12 +51,29 @@ namespace power {
class PowerManagerService
: public nsIPowerManagerService
, public WakeLockObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPOWERMANAGERSERVICE
static already_AddRefed<nsIPowerManagerService> GetInstance();
void Init();
// Implement WakeLockObserver
void Notify(const hal::WakeLockInformation& aWakeLockInfo);
private:
~PowerManagerService();
void ComputeWakeLockState(const hal::WakeLockInformation& aWakeLockInfo,
nsAString &aState);
static nsRefPtr<PowerManagerService> sSingleton;
nsTArray<nsCOMPtr<nsIDOMMozWakeLockListener> > mWakeLockListeners;
};
} // namespace power

21
dom/power/Types.h Normal file
View File

@ -0,0 +1,21 @@
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef mozilla_dom_power_Types_h
#define mozilla_dom_power_Types_h
namespace mozilla {
namespace hal {
class WakeLockInformation;
} // namespace hal
template <class T>
class Observer;
typedef Observer<hal::WakeLockInformation> WakeLockObserver;
} // namespace mozilla
#endif // mozilla_dom_power_Types_h

204
dom/power/WakeLock.cpp Normal file
View File

@ -0,0 +1,204 @@
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "mozilla/Hal.h"
#include "mozilla/HalWakeLock.h"
#include "nsDOMClassInfoID.h"
#include "nsDOMError.h"
#include "nsIDOMWindow.h"
#include "nsIDOMEvent.h"
#include "nsIDOMDocument.h"
#include "nsIDOMEventTarget.h"
#include "nsPIDOMWindow.h"
#include "PowerManager.h"
#include "WakeLock.h"
DOMCI_DATA(MozWakeLock, mozilla::dom::power::WakeLock)
namespace mozilla {
namespace dom {
namespace power {
NS_INTERFACE_MAP_BEGIN(WakeLock)
NS_INTERFACE_MAP_ENTRY(nsIDOMMozWakeLock)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozWakeLock)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozWakeLock)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(WakeLock)
NS_IMPL_RELEASE(WakeLock)
WakeLock::WakeLock()
: mLocked(false)
, mHidden(true)
{
}
WakeLock::~WakeLock()
{
DoUnlock();
DetachEventListener();
}
nsresult
WakeLock::Init(const nsAString &aTopic, nsIDOMWindow *aWindow)
{
mTopic.Assign(aTopic);
mWindow = do_GetWeakReference(aWindow);
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
/**
* Null windows are allowed. A wake lock without associated window
* is always considered invisible.
*/
if (window) {
nsCOMPtr<nsIDOMDocument> domDoc = window->GetExtantDocument();
NS_ENSURE_STATE(domDoc);
domDoc->GetMozHidden(&mHidden);
}
AttachEventListener();
DoLock();
return NS_OK;
}
void
WakeLock::DoLock()
{
if (!mLocked) {
// Change the flag immediately to prevent recursive reentering
mLocked = true;
hal::ModifyWakeLock(mTopic,
hal::WAKE_LOCK_ADD_ONE,
mHidden ? hal::WAKE_LOCK_ADD_ONE : hal::WAKE_LOCK_NO_CHANGE);
}
}
void
WakeLock::DoUnlock()
{
if (mLocked) {
// Change the flag immediately to prevent recursive reentering
mLocked = false;
hal::ModifyWakeLock(mTopic,
hal::WAKE_LOCK_REMOVE_ONE,
mHidden ? hal::WAKE_LOCK_REMOVE_ONE : hal::WAKE_LOCK_NO_CHANGE);
}
}
void
WakeLock::AttachEventListener()
{
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
if (window) {
nsCOMPtr<nsIDOMDocument> domDoc = window->GetExtantDocument();
if (domDoc) {
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(domDoc);
target->AddSystemEventListener(NS_LITERAL_STRING("mozvisibilitychange"),
this,
/* useCapture = */ true,
/* wantsUntrusted = */ false);
target = do_QueryInterface(window);
target->AddSystemEventListener(NS_LITERAL_STRING("pagehide"),
this,
/* useCapture = */ true,
/* wantsUntrusted = */ false);
target->AddSystemEventListener(NS_LITERAL_STRING("pageshow"),
this,
/* useCapture = */ true,
/* wantsUntrusted = */ false);
}
}
}
void
WakeLock::DetachEventListener()
{
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
if (window) {
nsCOMPtr<nsIDOMDocument> domDoc = window->GetExtantDocument();
if (domDoc) {
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(domDoc);
target->RemoveSystemEventListener(NS_LITERAL_STRING("mozvisibilitychange"),
this,
/* useCapture = */ true);
target = do_QueryInterface(window);
target->RemoveSystemEventListener(NS_LITERAL_STRING("pagehide"),
this,
/* useCapture = */ true);
target->RemoveSystemEventListener(NS_LITERAL_STRING("pageshow"),
this,
/* useCapture = */ true);
}
}
}
NS_IMETHODIMP
WakeLock::Unlock()
{
/*
* We throw NS_ERROR_DOM_INVALID_STATE_ERR on double unlock.
*/
if (!mLocked) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
DoUnlock();
DetachEventListener();
return NS_OK;
}
NS_IMETHODIMP
WakeLock::GetTopic(nsAString &aTopic)
{
aTopic.Assign(mTopic);
return NS_OK;
}
NS_IMETHODIMP
WakeLock::HandleEvent(nsIDOMEvent *aEvent)
{
nsAutoString type;
aEvent->GetType(type);
if (type.EqualsLiteral("mozvisibilitychange")) {
nsCOMPtr<nsIDOMEventTarget> target;
aEvent->GetTarget(getter_AddRefs(target));
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(target);
NS_ENSURE_STATE(domDoc);
domDoc->GetMozHidden(&mHidden);
if (mLocked) {
hal::ModifyWakeLock(mTopic,
hal::WAKE_LOCK_NO_CHANGE,
mHidden ? hal::WAKE_LOCK_ADD_ONE : hal::WAKE_LOCK_REMOVE_ONE);
}
return NS_OK;
}
if (type.EqualsLiteral("pagehide")) {
DoUnlock();
return NS_OK;
}
if (type.EqualsLiteral("pageshow")) {
DoLock();
return NS_OK;
}
return NS_OK;
}
} // power
} // dom
} // mozilla

53
dom/power/WakeLock.h Normal file
View File

@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef mozilla_dom_power_WakeLock_h
#define mozilla_dom_power_WakeLock_h
#include "nsCOMPtr.h"
#include "nsIDOMWakeLock.h"
#include "nsIDOMEventListener.h"
#include "nsString.h"
#include "nsWeakReference.h"
class nsIDOMWindow;
namespace mozilla {
namespace dom {
namespace power {
class WakeLock
: public nsIDOMMozWakeLock
, public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMMOZWAKELOCK
NS_DECL_NSIDOMEVENTLISTENER
WakeLock();
virtual ~WakeLock();
nsresult Init(const nsAString &aTopic, nsIDOMWindow *aWindow);
private:
void DoUnlock();
void DoLock();
void AttachEventListener();
void DetachEventListener();
bool mLocked;
bool mHidden;
nsString mTopic;
// window that this was created for. Weak reference.
nsWeakPtr mWindow;
};
} // namespace power
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_power_WakeLock_h

View File

@ -37,9 +37,40 @@
#include "nsISupports.idl"
[scriptable, uuid(6ec16abc-2fe8-4ab3-99b0-0f08405be81b)]
interface nsIDOMMozWakeLockListener;
/**
* This interface implements navigator.mozPower
*/
[scriptable, uuid(abf4b2b1-139d-4eff-998d-8f24616910ae)]
interface nsIDOMMozPowerManager : nsISupports
{
void powerOff();
void reboot();
void powerOff();
void reboot();
/**
* The listeners are notified when a resource changes its lock state to:
* - unlocked
* - locked but not visible
* - locked and visible
*/
void addWakeLockListener(in nsIDOMMozWakeLockListener aListener);
void removeWakeLockListener(in nsIDOMMozWakeLockListener aListener);
/**
* Query the wake lock state of the topic.
*
* Possible states are:
*
* - "unlocked" - nobody holds the wake lock.
*
* - "locked-foreground" - at least one window holds the wake lock,
* and it is visible.
*
* - "locked-background" - at least one window holds the wake lock,
* but all of them are hidden.
*
* @param aTopic The resource name related to the wake lock.
*/
DOMString getWakeLockState(in DOMString aTopic);
};

View File

@ -0,0 +1,19 @@
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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(2e61eed1-5983-4562-8f26-fd361ab4a00d)]
interface nsIDOMMozWakeLock : nsISupports
{
readonly attribute DOMString topic;
/**
* Release the wake lock.
*
* @throw NS_ERROR_DOM_INVALID_STATE_ERR if already unlocked.
*/
void unlock();
};

View File

@ -0,0 +1,29 @@
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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, function, uuid(4e258af8-cffb-47bc-b16d-e8241243426e)]
interface nsIDOMMozWakeLockListener : nsISupports
{
/**
* The callback will be called when a lock topic changes its lock
* state.
*
* Possible states are:
*
* - "unlocked" - nobody holds the wake lock.
*
* - "locked-foreground" - at least one window holds the wake lock,
* and it is visible.
*
* - "locked-background" - at least one window holds the wake lock,
* but all of them are hidden.
*
* @param aTopic The resource name related to the wake lock.
* @param aState The wake lock state
*/
void callback(in DOMString aTopic, in DOMString aState);
};

View File

@ -42,9 +42,26 @@
#define POWERMANAGERSERVICE_CONTRACTID "@mozilla.org/power/powermanagerservice;1"
%}
[scriptable, builtinclass, uuid(38919539-4641-4f0b-9f11-6b6294a9386f)]
interface nsIDOMMozWakeLock;
interface nsIDOMMozWakeLockListener;
interface nsIDOMWindow;
/**
* For use with non-content code.
*/
[scriptable, builtinclass, uuid(235ca1a1-d0c8-41f3-9b4a-dbaa4437d69c)]
interface nsIPowerManagerService : nsISupports
{
void powerOff();
void reboot();
void powerOff();
void reboot();
void addWakeLockListener(in nsIDOMMozWakeLockListener aListener);
void removeWakeLockListener(in nsIDOMMozWakeLockListener aListener);
DOMString getWakeLockState(in DOMString aTopic);
/**
* Return a wake lock object of aTopic associated with aWindow.
* A wake lock without associated window, e.g. used in chrome, is
* always considered invisible.
*/
nsIDOMMozWakeLock newWakeLock(in DOMString aTopic, [optional] in nsIDOMWindow aWindow);
};

View File

@ -52,8 +52,15 @@ _TEST_FILES = \
test_power_basics.html \
$(NULL)
_BROWSER_TEST_FILES = \
browser_bug697132.js \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
libs:: $(_BROWSER_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
#libs:: $(_CHROME_TEST_FILES)
# $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)

View File

@ -0,0 +1,235 @@
"use strict";
waitForExplicitFinish();
let kPrefNode = "dom.power.whitelist";
let kPageSource1 = "data:text/html,1";
let kPageSource2 = "data:text/html,2";
let gOldPref;
let gWin, gWin1, gWin2;
let gTab, gTab1, gTab2;
let gLock, gLock1, gLock2;
let gCurStepIndex = -1;
let gSteps = [
function basicWakeLock() {
gTab = gBrowser.addTab(kPageSource1);
gWin = gBrowser.getBrowserForTab(gTab).contentWindow;
let browser = gBrowser.getBrowserForTab(gTab);
browser.addEventListener("load", function onLoad(e) {
browser.removeEventListener("load", onLoad, true);
let nav = gWin.navigator;
let power = nav.mozPower;
gLock = nav.requestWakeLock("test");
ok(gLock != null,
"navigator.requestWakeLock should return a wake lock");
is(gLock.topic, "test",
"wake lock should remember the locked topic");
isnot(power.getWakeLockState("test"), "unlocked",
"topic is locked");
gLock.unlock();
is(gLock.topic, "test",
"wake lock should remember the locked topic even after unlock");
is(power.getWakeLockState("test"), "unlocked",
"topic is unlocked");
try {
gLock.unlock();
ok(false, "Should have thrown an error.");
} catch (e) {
is(e.code, DOMException.INVALID_STATE_ERR, "double unlock should throw InvalidStateError");
}
gBrowser.removeTab(gTab);
executeSoon(runNextStep);
}, true);
},
function multiWakeLock() {
gTab = gBrowser.addTab(kPageSource1);
gWin = gBrowser.getBrowserForTab(gTab).contentWindow;
let browser = gBrowser.getBrowserForTab(gTab);
browser.addEventListener("load", function onLoad(e) {
browser.removeEventListener("load", onLoad, true);
let nav = gWin.navigator;
let power = nav.mozPower;
let count = 0;
power.addWakeLockListener(function onWakeLockEvent(topic, state) {
is(topic, "test", "gLock topic is test");
ok(state == "unlocked" ||
state == "locked-foreground" ||
state == "locked-background",
"wake lock should be either locked or unlocked");
count++;
if (state == "locked-foreground" ||
state == "locked-background") {
is(count, 1,
"wake lock should be locked and the listener should only fire once");
}
if (state == "unlocked") {
is(count, 2,
"wake lock should be unlocked and the listener should only fire once");
ok(power.getWakeLockState("test") == "unlocked",
"topic is unlocked");
power.removeWakeLockListener(onWakeLockEvent);
gBrowser.removeTab(gTab);
executeSoon(runNextStep);
}
});
gLock1 = nav.requestWakeLock("test");
isnot(power.getWakeLockState("test"), "unlocked",
"topic is locked");
gLock2 = nav.requestWakeLock("test");
isnot(power.getWakeLockState("test"), "unlocked",
"topic is locked");
gLock1.unlock();
isnot(power.getWakeLockState("test"), "unlocked",
"topic is locked");
gLock2.unlock();
}, true);
},
function crossTabWakeLock1() {
gTab1 = gBrowser.addTab(kPageSource1);
gWin1 = gBrowser.getBrowserForTab(gTab1).contentWindow;
gTab2 = gBrowser.addTab(kPageSource1);
gWin2 = gBrowser.getBrowserForTab(gTab2).contentWindow;
gBrowser.selectedTab = gTab1;
let browser = gBrowser.getBrowserForTab(gTab2);
browser.addEventListener("load", function onLoad(e) {
browser.removeEventListener("load", onLoad, true);
gLock2 = gWin2.navigator.requestWakeLock("test");
is(gWin2.document.mozHidden, true,
"window is background")
is(gWin2.navigator.mozPower.getWakeLockState("test"), "locked-background",
"wake lock is background");
let doc2 = gWin2.document;
doc2.addEventListener("mozvisibilitychange", function onVisibilityChange(e) {
if (!doc2.mozHidden) {
doc2.removeEventListener("mozvisibilitychange", onVisibilityChange);
executeSoon(runNextStep);
}
});
gBrowser.selectedTab = gTab2;
}, true);
},
function crossTabWakeLock2() {
is(gWin2.document.mozHidden, false,
"window is foreground")
is(gWin2.navigator.mozPower.getWakeLockState("test"), "locked-foreground",
"wake lock is foreground");
gWin2.addEventListener("pagehide", function onPageHide(e) {
gWin2.removeEventListener("pagehide", onPageHide, true);
executeSoon(runNextStep);
}, true);
gWin2.addEventListener("pageshow", function onPageShow(e) {
gWin2.removeEventListener("pageshow", onPageShow, true);
executeSoon(runNextStep);
}, true);
gWin2.location = kPageSource2;
},
function crossTabWakeLock3() {
is(gWin1.navigator.mozPower.getWakeLockState("test"), "unlocked",
"wake lock should auto-unlock when page is unloaded");
gWin2.back();
// runNextStep called in onPageShow
},
function crossTabWakeLock4() {
is(gWin1.navigator.mozPower.getWakeLockState("test"), "locked-foreground",
"wake lock should auto-reacquire when page is available again");
gBrowser.selectedTab = gTab1;
executeSoon(runNextStep);
},
function crossTabWakeLock5() {
// Test again in background tab
is(gWin2.document.mozHidden, true,
"window is background")
is(gWin2.navigator.mozPower.getWakeLockState("test"), "locked-background",
"wake lock is background");
gWin2.addEventListener("pagehide", function onPageHide(e) {
gWin2.removeEventListener("pagehide", onPageHide, true);
executeSoon(runNextStep);
}, true);
gWin2.addEventListener("pageshow", function onPageShow(e) {
gWin2.removeEventListener("pageshow", onPageShow, true);
executeSoon(runNextStep);
}, true);
gWin2.location = kPageSource2;
},
function crossTabWakeLock6() {
is(gWin1.navigator.mozPower.getWakeLockState("test"), "unlocked",
"wake lock should auto-unlock when page is unloaded");
gWin2.back();
// runNextStep called in onPageShow
},
function crossTabWakeLock7() {
is(gWin1.navigator.mozPower.getWakeLockState("test"), "locked-background",
"wake lock should auto-reacquire when page is available again");
gLock2.unlock();
gBrowser.selectedTab = gTab2;
executeSoon(runNextStep);
},
function crossTabWakeLock8() {
is(gWin1.document.mozHidden, true,
"gWin1 is background");
is(gWin2.document.mozHidden, false,
"gWin2 is foreground");
gLock1 = gWin1.navigator.requestWakeLock("test");
gLock2 = gWin2.navigator.requestWakeLock("test");
is(gWin1.navigator.mozPower.getWakeLockState("test"), "locked-foreground",
"topic is locked-foreground when one page is foreground and one is background");
gLock2.unlock();
is(gWin1.navigator.mozPower.getWakeLockState("test"), "locked-background",
"topic is locked-background when all locks are background");
gLock2 = gWin2.navigator.requestWakeLock("test");
is(gWin1.navigator.mozPower.getWakeLockState("test"), "locked-foreground",
"topic is locked-foreground when one page is foreground and one is background");
gLock1.unlock();
is(gWin1.navigator.mozPower.getWakeLockState("test"), "locked-foreground",
"topic is locked-foreground");
gBrowser.removeTab(gTab1);
gBrowser.removeTab(gTab2);
executeSoon(runNextStep);
},
];
function runNextStep() {
gCurStepIndex++;
if (gCurStepIndex < gSteps.length) {
gSteps[gCurStepIndex]();
} else {
Services.prefs.setCharPref(kPrefNode, gOldPref);
finish();
}
}
function test() {
try {
gOldPref = Services.prefs.getCharPref(kPrefNode);
} catch (e) {
gOldPref = "";
}
// data url inherits its parent's principal, which is |about:| here.
Services.prefs.setCharPref(kPrefNode, "about:");
runNextStep();
}

View File

@ -184,13 +184,31 @@ public:
if (mObservers->Length() == 0) {
DisableNotifications();
OnNotificationsDisabled();
delete mObservers;
mObservers = 0;
mHasValidCache = false;
}
}
void BroadcastInformation(const InfoType& aInfo) {
MOZ_ASSERT(mObservers);
mObservers->Broadcast(aInfo);
}
protected:
virtual void EnableNotifications() = 0;
virtual void DisableNotifications() = 0;
virtual void OnNotificationsDisabled() {}
private:
mozilla::ObserverList<InfoType>* mObservers;
};
template <class InfoType>
class CachingObserversManager : public ObserversManager<InfoType>
{
public:
InfoType GetCurrentInformation() {
if (mHasValidCache) {
return mInfo;
@ -207,22 +225,22 @@ public:
}
void BroadcastCachedInformation() {
MOZ_ASSERT(mObservers);
mObservers->Broadcast(mInfo);
BroadcastInformation(mInfo);
}
protected:
virtual void EnableNotifications() = 0;
virtual void DisableNotifications() = 0;
virtual void GetCurrentInformationInternal(InfoType*) = 0;
virtual void OnNotificationsDisabled() {
mHasValidCache = false;
}
private:
mozilla::ObserverList<InfoType>* mObservers;
InfoType mInfo;
bool mHasValidCache;
};
class BatteryObserversManager : public ObserversManager<BatteryInformation>
class BatteryObserversManager : public CachingObserversManager<BatteryInformation>
{
protected:
void EnableNotifications() {
@ -240,7 +258,7 @@ protected:
static BatteryObserversManager sBatteryObservers;
class NetworkObserversManager : public ObserversManager<NetworkInformation>
class NetworkObserversManager : public CachingObserversManager<NetworkInformation>
{
protected:
void EnableNotifications() {
@ -258,6 +276,20 @@ protected:
static NetworkObserversManager sNetworkObservers;
class WakeLockObserversManager : public ObserversManager<WakeLockInformation>
{
protected:
void EnableNotifications() {
PROXY_IF_SANDBOXED(EnableWakeLockNotifications());
}
void DisableNotifications() {
PROXY_IF_SANDBOXED(DisableWakeLockNotifications());
}
};
static WakeLockObserversManager sWakeLockObservers;
void
RegisterBatteryObserver(BatteryObserver* aObserver)
{
@ -435,5 +467,42 @@ void PowerOff()
PROXY_IF_SANDBOXED(PowerOff());
}
void
RegisterWakeLockObserver(WakeLockObserver* aObserver)
{
AssertMainThread();
sWakeLockObservers.AddObserver(aObserver);
}
void
UnregisterWakeLockObserver(WakeLockObserver* aObserver)
{
AssertMainThread();
sWakeLockObservers.RemoveObserver(aObserver);
}
void
ModifyWakeLock(const nsAString &aTopic,
hal::WakeLockControl aLockAdjust,
hal::WakeLockControl aHiddenAdjust)
{
AssertMainThread();
PROXY_IF_SANDBOXED(ModifyWakeLock(aTopic, aLockAdjust, aHiddenAdjust));
}
void
GetWakeLockInfo(const nsAString &aTopic, WakeLockInformation *aWakeLockInfo)
{
AssertMainThread();
PROXY_IF_SANDBOXED(GetWakeLockInfo(aTopic, aWakeLockInfo));
}
void
NotifyWakeLockChange(const WakeLockInformation& aInfo)
{
AssertMainThread();
sWakeLockObservers.BroadcastInformation(aInfo);
}
} // namespace hal
} // namespace mozilla

View File

@ -14,6 +14,7 @@
#include "prlog.h"
#include "mozilla/dom/battery/Types.h"
#include "mozilla/dom/network/Types.h"
#include "mozilla/dom/power/Types.h"
#include "mozilla/hal_sandbox/PHal.h"
/*
@ -240,6 +241,55 @@ void Reboot();
*/
void PowerOff();
/**
* Enable wake lock notifications from the backend.
*
* This method is only used by WakeLockObserversManager.
*/
void EnableWakeLockNotifications();
/**
* Disable wake lock notifications from the backend.
*
* This method is only used by WakeLockObserversManager.
*/
void DisableWakeLockNotifications();
/**
* Inform the wake lock backend there is a new wake lock observer.
* @param aWakeLockObserver The observer that should be added.
*/
void RegisterWakeLockObserver(WakeLockObserver* aObserver);
/**
* Inform the wake lock backend a wake lock observer unregistered.
* @param aWakeLockObserver The observer that should be removed.
*/
void UnregisterWakeLockObserver(WakeLockObserver* aObserver);
/**
* Adjust the internal wake lock counts.
* @param aTopic lock topic
* @param aLockAdjust to increase or decrease active locks
* @param aHiddenAdjust to increase or decrease hidden locks
*/
void ModifyWakeLock(const nsAString &aTopic,
hal::WakeLockControl aLockAdjust,
hal::WakeLockControl aHiddenAdjust);
/**
* Query the wake lock numbers of aTopic.
* @param aTopic lock topic
* @param aWakeLockInfo wake lock numbers
*/
void GetWakeLockInfo(const nsAString &aTopic, hal::WakeLockInformation *aWakeLockInfo);
/**
* Notify of a change in the wake lock state.
* @param aWakeLockInfo The new wake lock information.
*/
void NotifyWakeLockChange(const hal::WakeLockInformation& aWakeLockInfo);
} // namespace MOZ_HAL_NAMESPACE
} // namespace mozilla

View File

@ -36,9 +36,25 @@ enum FlashMode {
eHalLightFlash_Timed = 1, // timed flashing. Use flashOnMS and flashOffMS for timing
eHalLightFlash_Hardware = 2 // hardware assisted flashing
};
} // namespace hal
} // namespace mozilla
namespace mozilla {
namespace hal {
/**
* Used by ModifyWakeLock
*/
enum WakeLockControl {
WAKE_LOCK_REMOVE_ONE = -1,
WAKE_LOCK_NO_CHANGE = 0,
WAKE_LOCK_ADD_ONE = 1,
};
}
}
namespace IPC {
/**
@ -71,6 +87,16 @@ struct ParamTraits<mozilla::hal::FlashMode>
mozilla::hal::eHalLightFlash_Hardware>
{};
/**
* WakeLockControl serializer.
*/
template <>
struct ParamTraits<mozilla::hal::WakeLockControl>
: public EnumSerializer<mozilla::hal::WakeLockControl,
mozilla::hal::WAKE_LOCK_REMOVE_ONE,
mozilla::hal::WAKE_LOCK_ADD_ONE>
{};
} // namespace IPC
#endif // mozilla_hal_Types_h

125
hal/HalWakeLock.cpp Normal file
View File

@ -0,0 +1,125 @@
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "mozilla/Hal.h"
#include "mozilla/HalWakeLock.h"
#include "mozilla/ClearOnShutdown.h"
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
using namespace mozilla::hal;
namespace mozilla {
namespace hal {
WakeLockState
ComputeWakeLockState(int aNumLocks, int aNumHidden)
{
if (aNumLocks == 0) {
return WAKE_LOCK_STATE_UNLOCKED;
} else if (aNumLocks == aNumHidden) {
return WAKE_LOCK_STATE_HIDDEN;
} else {
return WAKE_LOCK_STATE_VISIBLE;
}
}
} // hal
} // mozilla
namespace mozilla {
namespace hal_impl {
namespace {
struct LockCount {
PRUint32 numLocks;
PRUint32 numHidden;
};
}
static int sActiveChildren = 0;
static nsAutoPtr<nsDataHashtable<nsStringHashKey, LockCount> > sLockTable;
static bool sInitialized = false;
static void
Init()
{
sLockTable = new nsDataHashtable<nsStringHashKey, LockCount>();
sLockTable->Init();
ClearOnShutdown(&sLockTable);
sInitialized = true;
}
void
EnableWakeLockNotifications()
{
sActiveChildren++;
}
void
DisableWakeLockNotifications()
{
sActiveChildren--;
}
void
ModifyWakeLock(const nsAString &aTopic,
hal::WakeLockControl aLockAdjust,
hal::WakeLockControl aHiddenAdjust)
{
if (!sInitialized) {
Init();
}
LockCount count;
count.numLocks = 0;
count.numHidden = 0;
sLockTable->Get(aTopic, &count);
MOZ_ASSERT(count.numLocks >= count.numHidden);
MOZ_ASSERT(aLockAdjust >= 0 || count.numLocks > 0);
MOZ_ASSERT(aHiddenAdjust >= 0 || count.numHidden > 0);
WakeLockState oldState = ComputeWakeLockState(count.numLocks, count.numHidden);
count.numLocks += aLockAdjust;
count.numHidden += aHiddenAdjust;
MOZ_ASSERT(count.numLocks >= count.numHidden);
if (count.numLocks) {
sLockTable->Put(aTopic, count);
} else {
sLockTable->Remove(aTopic);
}
WakeLockState newState = ComputeWakeLockState(count.numLocks, count.numHidden);
if (sActiveChildren && oldState != newState) {
WakeLockInformation info;
info.numLocks() = count.numLocks;
info.numHidden() = count.numHidden;
info.topic() = aTopic;
NotifyWakeLockChange(info);
}
}
void
GetWakeLockInfo(const nsAString &aTopic, WakeLockInformation *aWakeLockInfo)
{
if (!sInitialized) {
Init();
}
LockCount count;
count.numLocks = 0;
count.numHidden = 0;
sLockTable->Get(aTopic, &count);
aWakeLockInfo->numLocks() = count.numLocks;
aWakeLockInfo->numHidden() = count.numHidden;
aWakeLockInfo->topic() = aTopic;
}
} // hal_impl
} // mozilla

26
hal/HalWakeLock.h Normal file
View File

@ -0,0 +1,26 @@
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef __HAL_WAKELOCK_H_
#define __HAL_WAKELOCK_H_
namespace mozilla {
namespace hal {
enum WakeLockState {
WAKE_LOCK_STATE_UNLOCKED,
WAKE_LOCK_STATE_HIDDEN,
WAKE_LOCK_STATE_VISIBLE
};
/**
* Return the wake lock state according to the numbers.
*/
WakeLockState ComputeWakeLockState(int aNumLocks, int aNumHidden);
} // hal
} // mozilla
#endif /* __HAL_WAKELOCK_H_ */

View File

@ -63,12 +63,14 @@ EXPORTS_mozilla = \
HalSandbox.h \
HalSensor.h \
HalTypes.h \
HalWakeLock.h \
$(NULL)
CPPSRCS = \
Hal.cpp \
SandboxHal.cpp \
WindowIdentifier.cpp \
HalWakeLock.cpp \
$(NULL)
ifeq (android,$(MOZ_WIDGET_TOOLKIT))

View File

@ -48,6 +48,7 @@ using mozilla::hal::FlashMode;
using mozilla::hal::LightType;
using mozilla::hal::LightMode;
using mozilla::hal::SensorType;
using mozilla::hal::WakeLockControl;
namespace mozilla {
@ -81,6 +82,14 @@ namespace hal {
};
}
namespace hal {
struct WakeLockInformation {
uint32_t numLocks;
uint32_t numHidden;
nsString topic;
};
}
namespace hal_sandbox {
sync protocol PHal {
@ -89,6 +98,7 @@ sync protocol PHal {
child:
NotifyBatteryChange(BatteryInformation aBatteryInfo);
NotifyNetworkChange(NetworkInformation aNetworkInfo);
NotifyWakeLockChange(WakeLockInformation aWakeLockInfo);
parent:
Vibrate(uint32[] pattern, uint64[] id, PBrowser browser);
@ -121,6 +131,12 @@ parent:
Reboot();
PowerOff();
ModifyWakeLock(nsString aTopic, WakeLockControl aLockAdjust, WakeLockControl aHiddenAdjust);
EnableWakeLockNotifications();
DisableWakeLockNotifications();
sync GetWakeLockInfo(nsString aTopic)
returns (WakeLockInformation aWakeLockInfo);
child:
NotifySensorChange(SensorData aSensorData);

View File

@ -169,10 +169,35 @@ DisableSensorNotifications(SensorType aSensor) {
Hal()->SendDisableSensorNotifications(aSensor);
}
void
EnableWakeLockNotifications()
{
Hal()->SendEnableWakeLockNotifications();
}
void
DisableWakeLockNotifications()
{
Hal()->SendDisableWakeLockNotifications();
}
void
ModifyWakeLock(const nsAString &aTopic, WakeLockControl aLockAdjust, WakeLockControl aHiddenAdjust)
{
Hal()->SendModifyWakeLock(nsString(aTopic), aLockAdjust, aHiddenAdjust);
}
void
GetWakeLockInfo(const nsAString &aTopic, WakeLockInformation *aWakeLockInfo)
{
Hal()->SendGetWakeLockInfo(nsString(aTopic), aWakeLockInfo);
}
class HalParent : public PHalParent
, public BatteryObserver
, public NetworkObserver
, public ISensorObserver
, public WakeLockObserver
{
public:
NS_OVERRIDE virtual bool
@ -343,6 +368,41 @@ public:
void Notify(const SensorData& aSensorData) {
unused << SendNotifySensorChange(aSensorData);
}
NS_OVERRIDE virtual bool
RecvModifyWakeLock(const nsString &aTopic,
const WakeLockControl &aLockAdjust,
const WakeLockControl &aHiddenAdjust)
{
hal::ModifyWakeLock(aTopic, aLockAdjust, aHiddenAdjust);
return true;
}
NS_OVERRIDE virtual bool
RecvEnableWakeLockNotifications()
{
hal::RegisterWakeLockObserver(this);
return true;
}
NS_OVERRIDE virtual bool
RecvDisableWakeLockNotifications()
{
hal::UnregisterWakeLockObserver(this);
return true;
}
NS_OVERRIDE virtual bool
RecvGetWakeLockInfo(const nsString &aTopic, WakeLockInformation *aWakeLockInfo)
{
hal::GetWakeLockInfo(aTopic, aWakeLockInfo);
return true;
}
void Notify(const WakeLockInformation& aWakeLockInfo)
{
unused << SendNotifyWakeLockChange(aWakeLockInfo);
}
};
class HalChild : public PHalChild {
@ -361,6 +421,12 @@ public:
hal::NotifyNetworkChange(aNetworkInfo);
return true;
}
NS_OVERRIDE virtual bool
RecvNotifyWakeLockChange(const WakeLockInformation& aWakeLockInfo) {
hal::NotifyWakeLockChange(aWakeLockInfo);
return true;
}
};
bool