Bug 714358: Time manager implementation. r=jlebar

This commit is contained in:
Steven Lee 2012-08-07 19:11:00 -04:00
parent ab3e1cc85d
commit dd1279bf1b
22 changed files with 352 additions and 20 deletions

View File

@ -201,6 +201,7 @@
@BINPATH@/components/dom_xpath.xpt
@BINPATH@/components/dom_xul.xpt
@BINPATH@/components/dom_loadsave.xpt
@BINPATH@/components/dom_time.xpt
@BINPATH@/components/downloads.xpt
@BINPATH@/components/editor.xpt
@BINPATH@/components/embed_base.xpt

View File

@ -683,6 +683,7 @@ GK_ATOM(onmozfullscreenchange, "onmozfullscreenchange")
GK_ATOM(onmozfullscreenerror, "onmozfullscreenerror")
GK_ATOM(onmozpointerlockchange, "onmozpointerlockchange")
GK_ATOM(onmozpointerlockerror, "onmozpointerlockerror")
GK_ATOM(onmoztimechange, "onmoztimechange")
GK_ATOM(onMozMousePixelScroll, "onMozMousePixelScroll")
GK_ATOM(onMozScrolledAreaChanged, "onMozScrolledAreaChanged")
GK_ATOM(ononline, "ononline")

View File

@ -435,6 +435,10 @@ WINDOW_ONLY_EVENT(devicelight,
NS_DEVICE_LIGHT,
EventNameType_None,
NS_EVENT)
WINDOW_ONLY_EVENT(moztimechange,
NS_MOZ_TIME_CHANGE_EVENT,
EventNameType_None,
NS_EVENT)
TOUCH_EVENT(touchstart,
NS_TOUCH_START,

View File

@ -97,7 +97,8 @@ static const char* const sEventNames[] = {
"deviceorientation",
"deviceproximity",
"userproximity",
"devicelight"
"devicelight",
"moztimechange"
};
static char *sPopupAllowedEvents;

View File

@ -177,7 +177,8 @@ public:
eDOMEvents_deviceorientation,
eDOMEvents_deviceproximity,
eDOMEvents_userproximity,
eDOMEvents_devicelight
eDOMEvents_devicelight,
eDOMEvents_moztimechange
};
nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent);

View File

@ -53,6 +53,7 @@
#include "nsIContentSecurityPolicy.h"
#include "nsJSEnvironment.h"
#include "xpcpublic.h"
#include "TimeChangeObserver.h"
using namespace mozilla::dom;
using namespace mozilla::hal;
@ -271,6 +272,8 @@ nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener,
EnableDevice(NS_DEVICE_LIGHT);
} else if (aTypeAtom == nsGkAtoms::ondevicemotion) {
EnableDevice(NS_DEVICE_MOTION);
} else if (aTypeAtom == nsGkAtoms::onmoztimechange) {
EnableTimeChangeNotifications();
} else if ((aType >= NS_MOZTOUCH_DOWN && aType <= NS_MOZTOUCH_UP) ||
(aTypeAtom == nsGkAtoms::ontouchstart ||
aTypeAtom == nsGkAtoms::ontouchend ||
@ -396,6 +399,7 @@ nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener,
PRUint32 count = mListeners.Length();
PRUint32 typeCount = 0;
bool deviceType = IsDeviceType(aType);
bool timeChangeEvent = (aType == NS_MOZ_TIME_CHANGE_EVENT);
for (PRUint32 i = 0; i < count; ++i) {
ls = &mListeners.ElementAt(i);
@ -409,7 +413,7 @@ nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener,
mNoListenerForEvent = NS_EVENT_TYPE_NULL;
mNoListenerForEventAtom = nullptr;
if (!deviceType) {
if (!deviceType && !timeChangeEvent) {
return;
}
--typeCount;
@ -419,6 +423,8 @@ nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener,
if (deviceType && typeCount == 0) {
DisableDevice(aType);
} else if (timeChangeEvent && typeCount == 0) {
DisableTimeChangeNotifications();
}
}
@ -1109,3 +1115,27 @@ nsEventListenerManager::UnmarkGrayJSListeners()
}
}
}
void
nsEventListenerManager::EnableTimeChangeNotifications()
{
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mTarget);
if (!window) {
return;
}
NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window");
window->EnableTimeChangeNotifications();
}
void
nsEventListenerManager::DisableTimeChangeNotifications()
{
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mTarget);
if (!window) {
return;
}
NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window");
window->DisableTimeChangeNotifications();
}

View File

@ -261,6 +261,9 @@ protected:
void EnableDevice(PRUint32 aType);
void DisableDevice(PRUint32 aType);
void EnableTimeChangeNotifications();
void DisableTimeChangeNotifications();
public:
/**
* Set the "inline" event listener for aEventName to |v|. This

View File

@ -38,6 +38,7 @@
#include "Connection.h"
#include "MobileConnection.h"
#include "nsIIdleObserver.h"
#include "TimeManager.h"
#ifdef MOZ_MEDIA_NAVIGATOR
#include "MediaManager.h"
@ -115,6 +116,7 @@ NS_INTERFACE_MAP_BEGIN(Navigator)
#endif
NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorCamera)
NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorSystemMessages)
NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorTime)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Navigator)
NS_INTERFACE_MAP_END
@ -197,6 +199,9 @@ Navigator::Invalidate()
}
mDeviceStorageStores.Clear();
if (mTimeManager) {
mTimeManager = nsnull;
}
}
nsPIDOMWindow *
@ -1241,21 +1246,9 @@ Navigator::GetMozMobileConnection(nsIDOMMozMobileConnection** aMobileConnection)
if (!mMobileConnection) {
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(window && window->GetDocShell(), NS_OK);
// Chrome is always allowed access, so do the permission check only
// for non-chrome pages.
if (!nsContentUtils::IsCallerChrome()) {
nsCOMPtr<nsIDocument> doc = do_QueryInterface(window->GetExtantDocument());
NS_ENSURE_TRUE(doc, NS_OK);
nsCOMPtr<nsIURI> uri;
doc->NodePrincipal()->GetURI(getter_AddRefs(uri));
if (!nsContentUtils::URIIsChromeOrInPref(uri, "dom.mobileconnection.whitelist")) {
return NS_OK;
}
}
if (!CheckPermission("dom.mobileconnection.whitelist")) {
return NS_OK;
}
mMobileConnection = new network::MobileConnection();
mMobileConnection->Init(window);
@ -1351,6 +1344,25 @@ Navigator::MozSetMessageHandler(const nsAString& aType,
#endif
}
//*****************************************************************************
// Navigator::nsIDOMNavigatorTime
//*****************************************************************************
NS_IMETHODIMP
Navigator::GetMozTime(nsIDOMMozTimeManager** aTime)
{
if (!CheckPermission("dom.time.whitelist")) {
return NS_ERROR_DOM_SECURITY_ERR;
}
if (!mTimeManager) {
*aTime = nsnull;
mTimeManager = new time::TimeManager();
}
NS_ADDREF(*aTime = mTimeManager);
return NS_OK;
}
//*****************************************************************************
// nsNavigator::nsIDOMNavigatorCamera
//*****************************************************************************
@ -1414,6 +1426,21 @@ Navigator::OnNavigation()
}
}
bool
Navigator::CheckPermission(const char* aPref)
{
if (!nsContentUtils::IsCallerChrome()) {
nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(win, false);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(win->GetExtantDocument());
NS_ENSURE_TRUE(doc, false);
nsCOMPtr<nsIURI> uri;
doc->NodePrincipal()->GetURI(getter_AddRefs(uri));
return nsContentUtils::URIIsChromeOrInPref(uri, aPref);
}
return true;
}
} // namespace dom
} // namespace mozilla

View File

@ -15,6 +15,7 @@
#include "nsINavigatorBattery.h"
#include "nsIDOMNavigatorSms.h"
#include "nsIDOMNavigatorNetwork.h"
#include "nsIDOMNavigatorTime.h"
#include "nsAutoPtr.h"
#include "nsWeakReference.h"
#include "DeviceStorage.h"
@ -69,6 +70,10 @@ namespace power {
class PowerManager;
} // namespace power
namespace time {
class TimeManager;
} // namespace time
class Navigator : public nsIDOMNavigator
, public nsIDOMClientInformation
, public nsIDOMNavigatorDeviceStorage
@ -88,6 +93,7 @@ class Navigator : public nsIDOMNavigator
#endif
, public nsIDOMNavigatorCamera
, public nsIDOMNavigatorSystemMessages
, public nsIDOMMozNavigatorTime
{
public:
Navigator(nsPIDOMWindow *aInnerWindow);
@ -113,6 +119,7 @@ public:
NS_DECL_NSIDOMNAVIGATORBLUETOOTH
#endif
NS_DECL_NSIDOMNAVIGATORSYSTEMMESSAGES
NS_DECL_NSIDOMMOZNAVIGATORTIME
static void Init();
@ -144,6 +151,7 @@ public:
private:
bool IsSmsAllowed() const;
bool IsSmsSupported() const;
bool CheckPermission(const char* aPref);
nsRefPtr<nsMimeTypeArray> mMimeTypes;
nsRefPtr<nsPluginArray> mPlugins;
@ -164,6 +172,7 @@ private:
nsRefPtr<nsDOMCameraManager> mCameraManager;
nsCOMPtr<nsIDOMNavigatorSystemMessages> mMessagesManager;
nsTArray<nsRefPtr<nsDOMDeviceStorage> > mDeviceStorageStores;
nsRefPtr<time::TimeManager> mTimeManager;
nsWeakPtr mWindow;
};

View File

@ -523,6 +523,7 @@ using mozilla::dom::indexedDB::IDBWrapperCache;
#include "nsIDOMNavigatorSystemMessages.h"
#include "mozilla/dom/Activity.h"
#include "TimeManager.h"
#include "DOMCameraManager.h"
#include "CameraControl.h"
@ -1698,6 +1699,9 @@ static nsDOMClassInfoData sClassInfoData[] = {
EVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MozActivity, nsEventTargetSH,
EVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MozTimeManager, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
};
// Objects that should be constructable through |new Name();|
@ -2471,6 +2475,7 @@ nsDOMClassInfo::Init()
#endif
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorCamera)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorSystemMessages)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozNavigatorTime)
DOM_CLASSINFO_MAP_END
@ -4506,6 +4511,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(MozTimeManager, nsIDOMMozTimeManager)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozTimeManager)
DOM_CLASSINFO_MAP_END
#ifdef DEBUG
{
PRUint32 i = ArrayLength(sClassInfoData);

View File

@ -538,3 +538,5 @@ DOMCI_CLASS(FileRequest)
DOMCI_CLASS(LockedFile)
DOMCI_CLASS(MozActivity)
DOMCI_CLASS(MozTimeManager)

View File

@ -222,6 +222,7 @@
#include "nsDOMEventTargetHelper.h"
#include "nsIAppsService.h"
#include "prrng.h"
#include "TimeChangeObserver.h"
#ifdef ANDROID
#include <android/log.h>
@ -1055,6 +1056,7 @@ nsGlobalWindow::CleanUp(bool aIgnoreModalDialog)
mIdleTimer = nullptr;
}
DisableTimeChangeNotifications();
#ifdef DEBUG
nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject*>(this));
#endif
@ -10620,6 +10622,18 @@ nsGlobalWindow::GetURL(nsIDOMMozURLProperty** aURL)
return NS_OK;
}
void
nsGlobalWindow::EnableTimeChangeNotifications()
{
nsSystemTimeChangeObserver::GetInstance()->AddWindowListener(this);
}
void
nsGlobalWindow::DisableTimeChangeNotifications()
{
nsSystemTimeChangeObserver::GetInstance()->RemoveWindowListener(this);
}
// static
bool
nsGlobalWindow::HasIndexedDBSupport()

View File

@ -537,6 +537,9 @@ public:
virtual void EnableDeviceSensor(PRUint32 aType);
virtual void DisableDeviceSensor(PRUint32 aType);
virtual void EnableTimeChangeNotifications();
virtual void DisableTimeChangeNotifications();
virtual nsresult SetArguments(nsIArray *aArguments, nsIPrincipal *aOrigin);
static bool DOMWindowDumpEnabled();

View File

@ -576,6 +576,9 @@ public:
*/
virtual void DisableDeviceSensor(PRUint32 aType) = 0;
virtual void EnableTimeChangeNotifications() = 0;
virtual void DisableTimeChangeNotifications() = 0;
/**
* Set a arguments for this window. This will be set on the window
* right away (if there's an existing document) and it will also be

View File

@ -16,7 +16,14 @@ FORCE_STATIC_LIB = 1
include $(topsrcdir)/dom/dom-config.mk
CPPSRCS = $(NULL)
CPPSRCS = \
TimeManager.cpp \
TimeChangeObserver.cpp \
$(NULL)
EXPORTS = \
TimeChangeObserver.h \
$(NULL)
XPIDLSRCS = \
nsIDOMNavigatorTime.idl \
@ -24,4 +31,5 @@ XPIDLSRCS = \
$(NULL)
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,87 @@
/* -*- Mode: C++; tab-width: 2; 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 "TimeChangeObserver.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/StaticPtr.h"
#include "nsPIDOMWindow.h"
#include "nsDOMEvent.h"
#include "nsContentUtils.h"
using namespace mozilla::hal;
using namespace mozilla;
StaticAutoPtr<nsSystemTimeChangeObserver> sObserver;
nsSystemTimeChangeObserver* nsSystemTimeChangeObserver::GetInstance()
{
if (!sObserver) {
sObserver = new nsSystemTimeChangeObserver();
ClearOnShutdown(&sObserver);
}
return sObserver;
}
void
nsSystemTimeChangeObserver::Notify(const SystemTimeChange& aReason)
{
//Copy mWindowListeners and iterate over windowListeners instead because
//mWindowListeners may be modified while we loop.
nsTArray<nsWeakPtr> windowListeners;
for (PRUint32 i = 0; i < mWindowListeners.Length(); i++) {
windowListeners.AppendElement(mWindowListeners.SafeElementAt(i));
}
for (PRInt32 i = windowListeners.Length() - 1; i >= 0; i--) {
nsCOMPtr<nsIDOMWindow> window = do_QueryReferent(windowListeners[i]);
if (!window) {
mWindowListeners.RemoveElement(windowListeners[i]);
return;
}
nsCOMPtr<nsIDOMDocument> domdoc;
window->GetDocument(getter_AddRefs(domdoc));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domdoc));
if (!domdoc) {
return;
}
nsContentUtils::DispatchTrustedEvent(doc, window,
NS_LITERAL_STRING("moztimechange"), /* bubbles = */ true,
/* canceable = */ false);
}
}
nsresult
nsSystemTimeChangeObserver::AddWindowListener(nsIDOMWindow* aWindow)
{
if (!aWindow) {
return NS_ERROR_ILLEGAL_VALUE;
}
if (mWindowListeners.IndexOf(NS_GetWeakReference(aWindow)) !=
nsTArray<nsIDOMWindow*>::NoIndex) {
return NS_OK;
}
if (mWindowListeners.Length() == 0) {
RegisterSystemTimeChangeObserver(this);
}
mWindowListeners.AppendElement(NS_GetWeakReference(aWindow));
return NS_OK;
}
nsresult
nsSystemTimeChangeObserver::RemoveWindowListener(nsIDOMWindow *aWindow)
{
mWindowListeners.RemoveElement(NS_GetWeakReference(aWindow));
if (mWindowListeners.Length() == 0) {
UnregisterSystemTimeChangeObserver(this);
}
return NS_OK;
}

View File

@ -0,0 +1,29 @@
/* -*- Mode: C++; tab-width: 2; 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_time_change_observer_h_
#define _mozilla_time_change_observer_h_
#include "mozilla/Hal.h"
#include "mozilla/Observer.h"
#include "mozilla/HalTypes.h"
#include "nsPIDOMWindow.h"
#include "nsWeakPtr.h"
typedef mozilla::Observer<mozilla::hal::SystemTimeChange> SystemTimeChangeObserver;
class nsSystemTimeChangeObserver : public SystemTimeChangeObserver
{
public:
static nsSystemTimeChangeObserver* GetInstance();
void Notify(const mozilla::hal::SystemTimeChange& aReason);
nsresult AddWindowListener(nsIDOMWindow *aWindow);
nsresult RemoveWindowListener(nsIDOMWindow *aWindow);
private:
nsSystemTimeChangeObserver() {};
nsTArray<nsWeakPtr> mWindowListeners;
};
#endif //_mozilla_time_change_observer_h_

57
dom/time/TimeManager.cpp Normal file
View File

@ -0,0 +1,57 @@
/* 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 "jsapi.h"
#include "mozilla/Hal.h"
#include "nsDOMEvent.h"
#include "nsDOMEventTargetHelper.h"
#include "nsIDOMClassInfo.h"
#include "prtime.h"
#include "TimeManager.h"
using namespace mozilla::hal;
DOMCI_DATA(MozTimeManager, mozilla::dom::time::TimeManager)
namespace mozilla {
namespace dom {
namespace time {
NS_INTERFACE_MAP_BEGIN(TimeManager)
NS_INTERFACE_MAP_ENTRY(nsIDOMMozTimeManager)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozTimeManager)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(TimeManager)
NS_IMPL_RELEASE(TimeManager)
nsresult
TimeManager::Set(const JS::Value& date, JSContext* ctx) {
double nowMSec = JS_Now() / 1000;
double dateMSec;
if (date.isObject()) {
JSObject* dateObj = JSVAL_TO_OBJECT(date);
if (JS_ObjectIsDate(ctx, dateObj) && js_DateIsValid(ctx, dateObj)) {
dateMSec = js_DateGetMsecSinceEpoch(ctx, dateObj);
}
else {
NS_WARN_IF_FALSE(JS_ObjectIsDate(ctx, dateObj), "This is not a Date object");
NS_WARN_IF_FALSE(js_DateIsValid(ctx, dateObj), "Date is not valid");
return NS_ERROR_INVALID_ARG;
}
} else if (date.isNumber()) {
dateMSec = date.toNumber();
} else {
return NS_ERROR_INVALID_ARG;
}
hal::AdjustSystemClock(JS_DoubleToInt32(dateMSec - nowMSec));
return NS_OK;
}
} // namespace time
} // namespace dom
} // namespace mozilla

31
dom/time/TimeManager.h Normal file
View File

@ -0,0 +1,31 @@
/* 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_time_TimeManager_h
#define mozilla_dom_time_TimeManager_h
#include "mozilla/HalTypes.h"
#include "nsIDOMTimeManager.h"
#include "mozilla/Observer.h"
class nsPIDOMWindow;
namespace mozilla {
typedef Observer<hal::SystemTimeChange> SystemTimeObserver;
namespace dom {
namespace time {
class TimeManager : public nsIDOMMozTimeManager
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMMOZTIMEMANAGER
};
} // namespace time
} // namespace dom
} // namespace mozilla
#endif //mozilla_dom_time_TimeManager_h

View File

@ -7,6 +7,14 @@
[scriptable, builtinclass, uuid(d29beaaa-bd54-4fd5-9f18-e0eedb1dc96d)]
interface nsIDOMMozTimeManager : nsISupports
{
// jsval could be Date object or UTC seconds
/* Set the system time.
*
* The |time| argument can be either a Date object or a number.
*
* - If |time| is a number, it's interpreted as seconds since the epoch
* (midnight UTC on January 1, 1970)
* - If |time| is a Date object, |set(time)| is equivalent to
* |set(time.getTime())|.
*/
[implicit_jscontext] void set(in jsval time);
};

View File

@ -83,6 +83,7 @@ SHARED_LIBRARY_LIBS = \
$(DEPTH)/dom/indexedDB/$(LIB_PREFIX)dom_indexeddb_s.$(LIB_SUFFIX) \
$(DEPTH)/dom/indexedDB/ipc/$(LIB_PREFIX)dom_indexeddb_ipc_s.$(LIB_SUFFIX) \
$(DEPTH)/dom/browser-element/$(LIB_PREFIX)dom_browserelement_s.$(LIB_SUFFIX) \
$(DEPTH)/dom/time/$(LIB_PREFIX)dom_time_s.$(LIB_SUFFIX) \
$(DEPTH)/editor/libeditor/text/$(LIB_PREFIX)texteditor_s.$(LIB_SUFFIX) \
$(DEPTH)/editor/libeditor/base/$(LIB_PREFIX)editorbase_s.$(LIB_SUFFIX) \
$(DEPTH)/parser/html/$(LIB_PREFIX)html5p_s.$(LIB_SUFFIX) \

View File

@ -537,6 +537,9 @@ class nsHashKey;
#define NS_POINTERLOCKCHANGE (NS_POINTERLOCK_START)
#define NS_POINTERLOCKERROR (NS_POINTERLOCK_START + 1)
//System time is changed
#define NS_MOZ_TIME_CHANGE_EVENT 5400
/**
* Return status for event processors, nsEventStatus, is defined in
* nsEvent.h.