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
;
29 static nsSystemTimeChangeObserver
* GetInstance();
30 virtual ~nsSystemTimeChangeObserver();
32 // Implementing hal::SystemClockChangeObserver::Notify()
33 void Notify(const int64_t& aClockDeltaMS
);
35 // Implementing hal::SystemTimezoneChangeObserver::Notify()
37 const mozilla::hal::SystemTimezoneChangeInformation
& aSystemTimezoneChangeInfo
);
39 nsresult
AddWindowListenerImpl(nsPIDOMWindow
* aWindow
);
40 nsresult
RemoveWindowListenerImpl(nsPIDOMWindow
* aWindow
);
43 nsSystemTimeChangeObserver() { };
44 ListenerArray mWindowListeners
;
45 void FireMozTimeChangeEvent();
48 StaticAutoPtr
<nsSystemTimeChangeObserver
> sObserver
;
50 nsSystemTimeChangeObserver
* nsSystemTimeChangeObserver::GetInstance()
53 sObserver
= new nsSystemTimeChangeObserver();
54 ClearOnShutdown(&sObserver
);
59 nsSystemTimeChangeObserver::~nsSystemTimeChangeObserver()
61 UnregisterSystemClockChangeObserver(this);
62 UnregisterSystemTimezoneChangeObserver(this);
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
;
75 !(document
= innerWindow
->GetExtantDoc()) ||
76 !(outerWindow
= innerWindow
->GetOuterWindow())) {
77 mWindowListeners
.RemoveElement(weakWindow
);
81 nsContentUtils::DispatchTrustedEvent(document
, outerWindow
,
82 NS_LITERAL_STRING("moztimechange"), /* bubbles = */ true,
83 /* canceable = */ false);
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
) {
94 dataStr
.AppendFloat(static_cast<double>(aClockDeltaMS
));
95 observerService
->NotifyObservers(
96 nullptr, "system-clock-change", dataStr
.get());
99 FireMozTimeChangeEvent();
103 nsSystemTimeChangeObserver::Notify(
104 const SystemTimezoneChangeInformation
& aSystemTimezoneChangeInfo
)
106 FireMozTimeChangeEvent();
110 mozilla::time::AddWindowListener(nsPIDOMWindow
* aWindow
)
112 return nsSystemTimeChangeObserver::GetInstance()->AddWindowListenerImpl(aWindow
);
116 nsSystemTimeChangeObserver::AddWindowListenerImpl(nsPIDOMWindow
* aWindow
)
119 return NS_ERROR_ILLEGAL_VALUE
;
122 if (aWindow
->IsOuterWindow()) {
123 aWindow
= aWindow
->GetCurrentInnerWindow();
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
) {
137 if (mWindowListeners
.IsEmpty()) {
138 RegisterSystemClockChangeObserver(sObserver
);
139 RegisterSystemTimezoneChangeObserver(sObserver
);
142 mWindowListeners
.AppendElement(windowWeakRef
);
147 mozilla::time::RemoveWindowListener(nsPIDOMWindow
* aWindow
)
153 return nsSystemTimeChangeObserver::GetInstance()->RemoveWindowListenerImpl(aWindow
);
157 nsSystemTimeChangeObserver::RemoveWindowListenerImpl(nsPIDOMWindow
* aWindow
)
163 if (aWindow
->IsOuterWindow()) {
164 aWindow
= aWindow
->GetCurrentInnerWindow();
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
);