123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- /* -*- Mode: C++; tab-width: 8; 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/Hal.h"
- #include "mozilla/Observer.h"
- #include "mozilla/HalTypes.h"
- #include "nsWeakPtr.h"
- #include "nsTObserverArray.h"
- #include "mozilla/ClearOnShutdown.h"
- #include "mozilla/Services.h"
- #include "mozilla/StaticPtr.h"
- #include "nsPIDOMWindow.h"
- #include "nsContentUtils.h"
- #include "nsIObserverService.h"
- #include "nsIDocument.h"
- using namespace mozilla;
- using namespace mozilla::hal;
- using namespace mozilla::services;
- class nsSystemTimeChangeObserver : public SystemClockChangeObserver,
- public SystemTimezoneChangeObserver
- {
- typedef nsTObserverArray<nsWeakPtr> ListenerArray;
- public:
- static nsSystemTimeChangeObserver* GetInstance();
- virtual ~nsSystemTimeChangeObserver();
- // Implementing hal::SystemClockChangeObserver::Notify()
- void Notify(const int64_t& aClockDeltaMS);
- // Implementing hal::SystemTimezoneChangeObserver::Notify()
- void Notify(
- const mozilla::hal::SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo);
- nsresult AddWindowListenerImpl(nsPIDOMWindowInner* aWindow);
- nsresult RemoveWindowListenerImpl(nsPIDOMWindowInner* aWindow);
- private:
- nsSystemTimeChangeObserver() { };
- ListenerArray mWindowListeners;
- void FireMozTimeChangeEvent();
- };
- StaticAutoPtr<nsSystemTimeChangeObserver> sObserver;
- nsSystemTimeChangeObserver* nsSystemTimeChangeObserver::GetInstance()
- {
- if (!sObserver) {
- sObserver = new nsSystemTimeChangeObserver();
- ClearOnShutdown(&sObserver);
- }
- return sObserver;
- }
- nsSystemTimeChangeObserver::~nsSystemTimeChangeObserver()
- {
- UnregisterSystemClockChangeObserver(this);
- UnregisterSystemTimezoneChangeObserver(this);
- }
- void
- nsSystemTimeChangeObserver::FireMozTimeChangeEvent()
- {
- ListenerArray::ForwardIterator iter(mWindowListeners);
- while (iter.HasMore()) {
- nsWeakPtr weakWindow = iter.GetNext();
- nsCOMPtr<nsPIDOMWindowInner> innerWindow = do_QueryReferent(weakWindow);
- nsCOMPtr<nsPIDOMWindowOuter> outerWindow;
- nsCOMPtr<nsIDocument> document;
- if (!innerWindow ||
- !(document = innerWindow->GetExtantDoc()) ||
- !(outerWindow = innerWindow->GetOuterWindow())) {
- mWindowListeners.RemoveElement(weakWindow);
- continue;
- }
- nsContentUtils::DispatchTrustedEvent(document, outerWindow,
- NS_LITERAL_STRING("moztimechange"), /* bubbles = */ true,
- /* canceable = */ false);
- }
- }
- void
- nsSystemTimeChangeObserver::Notify(const int64_t& aClockDeltaMS)
- {
- // Notify observers that the system clock has been adjusted.
- nsCOMPtr<nsIObserverService> observerService = GetObserverService();
- if (observerService) {
- nsString dataStr;
- dataStr.AppendFloat(static_cast<double>(aClockDeltaMS));
- observerService->NotifyObservers(
- nullptr, "system-clock-change", dataStr.get());
- }
- FireMozTimeChangeEvent();
- }
- void
- nsSystemTimeChangeObserver::Notify(
- const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo)
- {
- FireMozTimeChangeEvent();
- }
- nsresult
- mozilla::time::AddWindowListener(nsPIDOMWindowInner* aWindow)
- {
- return nsSystemTimeChangeObserver::GetInstance()->AddWindowListenerImpl(aWindow);
- }
- nsresult
- nsSystemTimeChangeObserver::AddWindowListenerImpl(nsPIDOMWindowInner* aWindow)
- {
- if (!aWindow) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- nsWeakPtr windowWeakRef = do_GetWeakReference(aWindow);
- NS_ASSERTION(windowWeakRef, "nsIDOMWindow implementations shuld support weak ref");
- if (mWindowListeners.IndexOf(windowWeakRef) !=
- ListenerArray::array_type::NoIndex) {
- return NS_OK;
- }
- if (mWindowListeners.IsEmpty()) {
- RegisterSystemClockChangeObserver(sObserver);
- RegisterSystemTimezoneChangeObserver(sObserver);
- }
- mWindowListeners.AppendElement(windowWeakRef);
- return NS_OK;
- }
- nsresult
- mozilla::time::RemoveWindowListener(nsPIDOMWindowInner* aWindow)
- {
- if (!sObserver) {
- return NS_OK;
- }
- return nsSystemTimeChangeObserver::GetInstance()->RemoveWindowListenerImpl(aWindow);
- }
- nsresult
- nsSystemTimeChangeObserver::RemoveWindowListenerImpl(nsPIDOMWindowInner* aWindow)
- {
- if (!aWindow) {
- return NS_OK;
- }
- nsWeakPtr windowWeakRef = do_GetWeakReference(aWindow);
- mWindowListeners.RemoveElement(windowWeakRef);
- if (mWindowListeners.IsEmpty()) {
- UnregisterSystemClockChangeObserver(sObserver);
- UnregisterSystemTimezoneChangeObserver(sObserver);
- }
- return NS_OK;
- }
|