TimeChangeObserver.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /* -*- Mode: C++; tab-width: 8; 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/. */
  5. #include "TimeChangeObserver.h"
  6. #include "mozilla/Hal.h"
  7. #include "mozilla/Observer.h"
  8. #include "mozilla/HalTypes.h"
  9. #include "nsWeakPtr.h"
  10. #include "nsTObserverArray.h"
  11. #include "mozilla/ClearOnShutdown.h"
  12. #include "mozilla/Services.h"
  13. #include "mozilla/StaticPtr.h"
  14. #include "nsPIDOMWindow.h"
  15. #include "nsContentUtils.h"
  16. #include "nsIObserverService.h"
  17. #include "nsIDocument.h"
  18. using namespace mozilla;
  19. using namespace mozilla::hal;
  20. using namespace mozilla::services;
  21. class nsSystemTimeChangeObserver : public SystemClockChangeObserver,
  22. public SystemTimezoneChangeObserver
  23. {
  24. typedef nsTObserverArray<nsWeakPtr> ListenerArray;
  25. public:
  26. static nsSystemTimeChangeObserver* GetInstance();
  27. virtual ~nsSystemTimeChangeObserver();
  28. // Implementing hal::SystemClockChangeObserver::Notify()
  29. void Notify(const int64_t& aClockDeltaMS);
  30. // Implementing hal::SystemTimezoneChangeObserver::Notify()
  31. void Notify(
  32. const mozilla::hal::SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo);
  33. nsresult AddWindowListenerImpl(nsPIDOMWindowInner* aWindow);
  34. nsresult RemoveWindowListenerImpl(nsPIDOMWindowInner* aWindow);
  35. private:
  36. nsSystemTimeChangeObserver() { };
  37. ListenerArray mWindowListeners;
  38. void FireMozTimeChangeEvent();
  39. };
  40. StaticAutoPtr<nsSystemTimeChangeObserver> sObserver;
  41. nsSystemTimeChangeObserver* nsSystemTimeChangeObserver::GetInstance()
  42. {
  43. if (!sObserver) {
  44. sObserver = new nsSystemTimeChangeObserver();
  45. ClearOnShutdown(&sObserver);
  46. }
  47. return sObserver;
  48. }
  49. nsSystemTimeChangeObserver::~nsSystemTimeChangeObserver()
  50. {
  51. UnregisterSystemClockChangeObserver(this);
  52. UnregisterSystemTimezoneChangeObserver(this);
  53. }
  54. void
  55. nsSystemTimeChangeObserver::FireMozTimeChangeEvent()
  56. {
  57. ListenerArray::ForwardIterator iter(mWindowListeners);
  58. while (iter.HasMore()) {
  59. nsWeakPtr weakWindow = iter.GetNext();
  60. nsCOMPtr<nsPIDOMWindowInner> innerWindow = do_QueryReferent(weakWindow);
  61. nsCOMPtr<nsPIDOMWindowOuter> outerWindow;
  62. nsCOMPtr<nsIDocument> document;
  63. if (!innerWindow ||
  64. !(document = innerWindow->GetExtantDoc()) ||
  65. !(outerWindow = innerWindow->GetOuterWindow())) {
  66. mWindowListeners.RemoveElement(weakWindow);
  67. continue;
  68. }
  69. nsContentUtils::DispatchTrustedEvent(document, outerWindow,
  70. NS_LITERAL_STRING("moztimechange"), /* bubbles = */ true,
  71. /* canceable = */ false);
  72. }
  73. }
  74. void
  75. nsSystemTimeChangeObserver::Notify(const int64_t& aClockDeltaMS)
  76. {
  77. // Notify observers that the system clock has been adjusted.
  78. nsCOMPtr<nsIObserverService> observerService = GetObserverService();
  79. if (observerService) {
  80. nsString dataStr;
  81. dataStr.AppendFloat(static_cast<double>(aClockDeltaMS));
  82. observerService->NotifyObservers(
  83. nullptr, "system-clock-change", dataStr.get());
  84. }
  85. FireMozTimeChangeEvent();
  86. }
  87. void
  88. nsSystemTimeChangeObserver::Notify(
  89. const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo)
  90. {
  91. FireMozTimeChangeEvent();
  92. }
  93. nsresult
  94. mozilla::time::AddWindowListener(nsPIDOMWindowInner* aWindow)
  95. {
  96. return nsSystemTimeChangeObserver::GetInstance()->AddWindowListenerImpl(aWindow);
  97. }
  98. nsresult
  99. nsSystemTimeChangeObserver::AddWindowListenerImpl(nsPIDOMWindowInner* aWindow)
  100. {
  101. if (!aWindow) {
  102. return NS_ERROR_ILLEGAL_VALUE;
  103. }
  104. nsWeakPtr windowWeakRef = do_GetWeakReference(aWindow);
  105. NS_ASSERTION(windowWeakRef, "nsIDOMWindow implementations shuld support weak ref");
  106. if (mWindowListeners.IndexOf(windowWeakRef) !=
  107. ListenerArray::array_type::NoIndex) {
  108. return NS_OK;
  109. }
  110. if (mWindowListeners.IsEmpty()) {
  111. RegisterSystemClockChangeObserver(sObserver);
  112. RegisterSystemTimezoneChangeObserver(sObserver);
  113. }
  114. mWindowListeners.AppendElement(windowWeakRef);
  115. return NS_OK;
  116. }
  117. nsresult
  118. mozilla::time::RemoveWindowListener(nsPIDOMWindowInner* aWindow)
  119. {
  120. if (!sObserver) {
  121. return NS_OK;
  122. }
  123. return nsSystemTimeChangeObserver::GetInstance()->RemoveWindowListenerImpl(aWindow);
  124. }
  125. nsresult
  126. nsSystemTimeChangeObserver::RemoveWindowListenerImpl(nsPIDOMWindowInner* aWindow)
  127. {
  128. if (!aWindow) {
  129. return NS_OK;
  130. }
  131. nsWeakPtr windowWeakRef = do_GetWeakReference(aWindow);
  132. mWindowListeners.RemoveElement(windowWeakRef);
  133. if (mWindowListeners.IsEmpty()) {
  134. UnregisterSystemClockChangeObserver(sObserver);
  135. UnregisterSystemTimezoneChangeObserver(sObserver);
  136. }
  137. return NS_OK;
  138. }