dom/time/TimeChangeObserver.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/time/TimeChangeObserver.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,179 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.7 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "TimeChangeObserver.h"
    1.10 +#include "mozilla/Hal.h"
    1.11 +#include "mozilla/Observer.h"
    1.12 +#include "mozilla/HalTypes.h"
    1.13 +#include "nsWeakPtr.h"
    1.14 +#include "nsTObserverArray.h"
    1.15 +#include "mozilla/ClearOnShutdown.h"
    1.16 +#include "mozilla/Services.h"
    1.17 +#include "mozilla/StaticPtr.h"
    1.18 +#include "nsPIDOMWindow.h"
    1.19 +#include "nsContentUtils.h"
    1.20 +#include "nsIObserverService.h"
    1.21 +#include "nsIDocument.h"
    1.22 +
    1.23 +using namespace mozilla;
    1.24 +using namespace mozilla::hal;
    1.25 +using namespace mozilla::services;
    1.26 +
    1.27 +class nsSystemTimeChangeObserver : public SystemClockChangeObserver,
    1.28 +                                   public SystemTimezoneChangeObserver
    1.29 +{
    1.30 +  typedef nsTObserverArray<nsWeakPtr> ListenerArray;
    1.31 +public:
    1.32 +  static nsSystemTimeChangeObserver* GetInstance();
    1.33 +  virtual ~nsSystemTimeChangeObserver();
    1.34 +
    1.35 +  // Implementing hal::SystemClockChangeObserver::Notify()
    1.36 +  void Notify(const int64_t& aClockDeltaMS);
    1.37 +
    1.38 +  // Implementing hal::SystemTimezoneChangeObserver::Notify()
    1.39 +  void Notify(
    1.40 +    const mozilla::hal::SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo);
    1.41 +
    1.42 +  nsresult AddWindowListenerImpl(nsPIDOMWindow* aWindow);
    1.43 +  nsresult RemoveWindowListenerImpl(nsPIDOMWindow* aWindow);
    1.44 +
    1.45 +private:
    1.46 +  nsSystemTimeChangeObserver() { };
    1.47 +  ListenerArray mWindowListeners;
    1.48 +  void FireMozTimeChangeEvent();
    1.49 +};
    1.50 +
    1.51 +StaticAutoPtr<nsSystemTimeChangeObserver> sObserver;
    1.52 +
    1.53 +nsSystemTimeChangeObserver* nsSystemTimeChangeObserver::GetInstance()
    1.54 +{
    1.55 +  if (!sObserver) {
    1.56 +    sObserver = new nsSystemTimeChangeObserver();
    1.57 +    ClearOnShutdown(&sObserver);
    1.58 +  }
    1.59 +  return sObserver;
    1.60 +}
    1.61 +
    1.62 +nsSystemTimeChangeObserver::~nsSystemTimeChangeObserver()
    1.63 +{
    1.64 +  UnregisterSystemClockChangeObserver(this);
    1.65 +  UnregisterSystemTimezoneChangeObserver(this);
    1.66 +}
    1.67 +
    1.68 +void
    1.69 +nsSystemTimeChangeObserver::FireMozTimeChangeEvent()
    1.70 +{
    1.71 +  ListenerArray::ForwardIterator iter(mWindowListeners);
    1.72 +  while (iter.HasMore()) {
    1.73 +    nsWeakPtr weakWindow = iter.GetNext();
    1.74 +    nsCOMPtr<nsPIDOMWindow> innerWindow = do_QueryReferent(weakWindow);
    1.75 +    nsCOMPtr<nsPIDOMWindow> outerWindow;
    1.76 +    nsCOMPtr<nsIDocument> document;
    1.77 +    if (!innerWindow ||
    1.78 +        !(document = innerWindow->GetExtantDoc()) ||
    1.79 +        !(outerWindow = innerWindow->GetOuterWindow())) {
    1.80 +      mWindowListeners.RemoveElement(weakWindow);
    1.81 +      continue;
    1.82 +    }
    1.83 +
    1.84 +    nsContentUtils::DispatchTrustedEvent(document, outerWindow,
    1.85 +      NS_LITERAL_STRING("moztimechange"), /* bubbles = */ true,
    1.86 +      /* canceable = */ false);
    1.87 +  }
    1.88 +}
    1.89 +
    1.90 +void
    1.91 +nsSystemTimeChangeObserver::Notify(const int64_t& aClockDeltaMS)
    1.92 +{
    1.93 +  // Notify observers that the system clock has been adjusted.
    1.94 +  nsCOMPtr<nsIObserverService> observerService = GetObserverService();
    1.95 +  if (observerService) {
    1.96 +    nsString dataStr;
    1.97 +    dataStr.AppendFloat(static_cast<double>(aClockDeltaMS));
    1.98 +    observerService->NotifyObservers(
    1.99 +      nullptr, "system-clock-change", dataStr.get());
   1.100 +  }
   1.101 +
   1.102 +  FireMozTimeChangeEvent();
   1.103 +}
   1.104 +
   1.105 +void
   1.106 +nsSystemTimeChangeObserver::Notify(
   1.107 +  const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo)
   1.108 +{
   1.109 +  FireMozTimeChangeEvent();
   1.110 +}
   1.111 +
   1.112 +nsresult
   1.113 +mozilla::time::AddWindowListener(nsPIDOMWindow* aWindow)
   1.114 +{
   1.115 +  return nsSystemTimeChangeObserver::GetInstance()->AddWindowListenerImpl(aWindow);
   1.116 +}
   1.117 +
   1.118 +nsresult
   1.119 +nsSystemTimeChangeObserver::AddWindowListenerImpl(nsPIDOMWindow* aWindow)
   1.120 +{
   1.121 +  if (!aWindow) {
   1.122 +    return NS_ERROR_ILLEGAL_VALUE;
   1.123 +  }
   1.124 +
   1.125 +  if (aWindow->IsOuterWindow()) {
   1.126 +    aWindow = aWindow->GetCurrentInnerWindow();
   1.127 +    if (!aWindow) {
   1.128 +      return NS_ERROR_FAILURE;
   1.129 +    }
   1.130 +  }
   1.131 +
   1.132 +  nsWeakPtr windowWeakRef = do_GetWeakReference(aWindow);
   1.133 +  NS_ASSERTION(windowWeakRef, "nsIDOMWindow implementations shuld support weak ref");
   1.134 +
   1.135 +  if (mWindowListeners.IndexOf(windowWeakRef) !=
   1.136 +      ListenerArray::array_type::NoIndex) {
   1.137 +    return NS_OK;
   1.138 +  }
   1.139 +
   1.140 +  if (mWindowListeners.IsEmpty()) {
   1.141 +    RegisterSystemClockChangeObserver(sObserver);
   1.142 +    RegisterSystemTimezoneChangeObserver(sObserver);
   1.143 +  }
   1.144 +
   1.145 +  mWindowListeners.AppendElement(windowWeakRef);
   1.146 +  return NS_OK;
   1.147 +}
   1.148 +
   1.149 +nsresult
   1.150 +mozilla::time::RemoveWindowListener(nsPIDOMWindow* aWindow)
   1.151 +{
   1.152 +  if (!sObserver) {
   1.153 +    return NS_OK;
   1.154 +  }
   1.155 +
   1.156 +  return nsSystemTimeChangeObserver::GetInstance()->RemoveWindowListenerImpl(aWindow);
   1.157 +}
   1.158 +
   1.159 +nsresult
   1.160 +nsSystemTimeChangeObserver::RemoveWindowListenerImpl(nsPIDOMWindow* aWindow)
   1.161 +{
   1.162 +  if (!aWindow) {
   1.163 +    return NS_OK;
   1.164 +  }
   1.165 +
   1.166 +  if (aWindow->IsOuterWindow()) {
   1.167 +    aWindow = aWindow->GetCurrentInnerWindow();
   1.168 +    if (!aWindow) {
   1.169 +      return NS_ERROR_FAILURE;
   1.170 +    }
   1.171 +  }
   1.172 +
   1.173 +  nsWeakPtr windowWeakRef = do_GetWeakReference(aWindow);
   1.174 +  mWindowListeners.RemoveElement(windowWeakRef);
   1.175 +
   1.176 +  if (mWindowListeners.IsEmpty()) {
   1.177 +    UnregisterSystemClockChangeObserver(sObserver);
   1.178 +    UnregisterSystemTimezoneChangeObserver(sObserver);
   1.179 +  }
   1.180 +
   1.181 +  return NS_OK;
   1.182 +}

mercurial