Bumping manifests a=b2g-bump
[gecko.git] / dom / time / TimeChangeObserver.cpp
blob96c76e7f3489d6ad2ded3096de265b36fdbf0957
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "TimeChangeObserver.h"
7 #include "mozilla/Hal.h"
8 #include "mozilla/Observer.h"
9 #include "mozilla/HalTypes.h"
10 #include "nsWeakPtr.h"
11 #include "nsTObserverArray.h"
12 #include "mozilla/ClearOnShutdown.h"
13 #include "mozilla/Services.h"
14 #include "mozilla/StaticPtr.h"
15 #include "nsPIDOMWindow.h"
16 #include "nsContentUtils.h"
17 #include "nsIObserverService.h"
18 #include "nsIDocument.h"
20 using namespace mozilla;
21 using namespace mozilla::hal;
22 using namespace mozilla::services;
24 class nsSystemTimeChangeObserver : public SystemClockChangeObserver,
25 public SystemTimezoneChangeObserver
27 typedef nsTObserverArray<nsWeakPtr> ListenerArray;
28 public:
29 static nsSystemTimeChangeObserver* GetInstance();
30 virtual ~nsSystemTimeChangeObserver();
32 // Implementing hal::SystemClockChangeObserver::Notify()
33 void Notify(const int64_t& aClockDeltaMS);
35 // Implementing hal::SystemTimezoneChangeObserver::Notify()
36 void Notify(
37 const mozilla::hal::SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo);
39 nsresult AddWindowListenerImpl(nsPIDOMWindow* aWindow);
40 nsresult RemoveWindowListenerImpl(nsPIDOMWindow* aWindow);
42 private:
43 nsSystemTimeChangeObserver() { };
44 ListenerArray mWindowListeners;
45 void FireMozTimeChangeEvent();
48 StaticAutoPtr<nsSystemTimeChangeObserver> sObserver;
50 nsSystemTimeChangeObserver* nsSystemTimeChangeObserver::GetInstance()
52 if (!sObserver) {
53 sObserver = new nsSystemTimeChangeObserver();
54 ClearOnShutdown(&sObserver);
56 return sObserver;
59 nsSystemTimeChangeObserver::~nsSystemTimeChangeObserver()
61 UnregisterSystemClockChangeObserver(this);
62 UnregisterSystemTimezoneChangeObserver(this);
65 void
66 nsSystemTimeChangeObserver::FireMozTimeChangeEvent()
68 ListenerArray::ForwardIterator iter(mWindowListeners);
69 while (iter.HasMore()) {
70 nsWeakPtr weakWindow = iter.GetNext();
71 nsCOMPtr<nsPIDOMWindow> innerWindow = do_QueryReferent(weakWindow);
72 nsCOMPtr<nsPIDOMWindow> outerWindow;
73 nsCOMPtr<nsIDocument> document;
74 if (!innerWindow ||
75 !(document = innerWindow->GetExtantDoc()) ||
76 !(outerWindow = innerWindow->GetOuterWindow())) {
77 mWindowListeners.RemoveElement(weakWindow);
78 continue;
81 nsContentUtils::DispatchTrustedEvent(document, outerWindow,
82 NS_LITERAL_STRING("moztimechange"), /* bubbles = */ true,
83 /* canceable = */ false);
87 void
88 nsSystemTimeChangeObserver::Notify(const int64_t& aClockDeltaMS)
90 // Notify observers that the system clock has been adjusted.
91 nsCOMPtr<nsIObserverService> observerService = GetObserverService();
92 if (observerService) {
93 nsString dataStr;
94 dataStr.AppendFloat(static_cast<double>(aClockDeltaMS));
95 observerService->NotifyObservers(
96 nullptr, "system-clock-change", dataStr.get());
99 FireMozTimeChangeEvent();
102 void
103 nsSystemTimeChangeObserver::Notify(
104 const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo)
106 FireMozTimeChangeEvent();
109 nsresult
110 mozilla::time::AddWindowListener(nsPIDOMWindow* aWindow)
112 return nsSystemTimeChangeObserver::GetInstance()->AddWindowListenerImpl(aWindow);
115 nsresult
116 nsSystemTimeChangeObserver::AddWindowListenerImpl(nsPIDOMWindow* aWindow)
118 if (!aWindow) {
119 return NS_ERROR_ILLEGAL_VALUE;
122 if (aWindow->IsOuterWindow()) {
123 aWindow = aWindow->GetCurrentInnerWindow();
124 if (!aWindow) {
125 return NS_ERROR_FAILURE;
129 nsWeakPtr windowWeakRef = do_GetWeakReference(aWindow);
130 NS_ASSERTION(windowWeakRef, "nsIDOMWindow implementations shuld support weak ref");
132 if (mWindowListeners.IndexOf(windowWeakRef) !=
133 ListenerArray::array_type::NoIndex) {
134 return NS_OK;
137 if (mWindowListeners.IsEmpty()) {
138 RegisterSystemClockChangeObserver(sObserver);
139 RegisterSystemTimezoneChangeObserver(sObserver);
142 mWindowListeners.AppendElement(windowWeakRef);
143 return NS_OK;
146 nsresult
147 mozilla::time::RemoveWindowListener(nsPIDOMWindow* aWindow)
149 if (!sObserver) {
150 return NS_OK;
153 return nsSystemTimeChangeObserver::GetInstance()->RemoveWindowListenerImpl(aWindow);
156 nsresult
157 nsSystemTimeChangeObserver::RemoveWindowListenerImpl(nsPIDOMWindow* aWindow)
159 if (!aWindow) {
160 return NS_OK;
163 if (aWindow->IsOuterWindow()) {
164 aWindow = aWindow->GetCurrentInnerWindow();
165 if (!aWindow) {
166 return NS_ERROR_FAILURE;
170 nsWeakPtr windowWeakRef = do_GetWeakReference(aWindow);
171 mWindowListeners.RemoveElement(windowWeakRef);
173 if (mWindowListeners.IsEmpty()) {
174 UnregisterSystemClockChangeObserver(sObserver);
175 UnregisterSystemTimezoneChangeObserver(sObserver);
178 return NS_OK;