PerformanceObserver.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "PerformanceObserver.h"
  6. #include "mozilla/dom/Performance.h"
  7. #include "mozilla/dom/PerformanceBinding.h"
  8. #include "mozilla/dom/PerformanceEntryBinding.h"
  9. #include "mozilla/dom/PerformanceObserverBinding.h"
  10. #include "nsPIDOMWindow.h"
  11. #include "nsQueryObject.h"
  12. #include "nsString.h"
  13. #include "PerformanceEntry.h"
  14. #include "PerformanceObserverEntryList.h"
  15. #include "WorkerPrivate.h"
  16. #include "WorkerScope.h"
  17. using namespace mozilla;
  18. using namespace mozilla::dom;
  19. using namespace mozilla::dom::workers;
  20. NS_IMPL_CYCLE_COLLECTION_CLASS(PerformanceObserver)
  21. NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PerformanceObserver)
  22. tmp->Disconnect();
  23. NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
  24. NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
  25. NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
  26. NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
  27. NS_IMPL_CYCLE_COLLECTION_UNLINK_END
  28. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PerformanceObserver)
  29. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
  30. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
  31. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
  32. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  33. NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(PerformanceObserver)
  34. NS_IMPL_CYCLE_COLLECTING_ADDREF(PerformanceObserver)
  35. NS_IMPL_CYCLE_COLLECTING_RELEASE(PerformanceObserver)
  36. NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceObserver)
  37. NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
  38. NS_INTERFACE_MAP_ENTRY(nsISupports)
  39. NS_INTERFACE_MAP_END
  40. PerformanceObserver::PerformanceObserver(nsPIDOMWindowInner* aOwner,
  41. PerformanceObserverCallback& aCb)
  42. : mOwner(aOwner)
  43. , mCallback(&aCb)
  44. , mConnected(false)
  45. {
  46. MOZ_ASSERT(mOwner);
  47. mPerformance = aOwner->GetPerformance();
  48. }
  49. PerformanceObserver::PerformanceObserver(WorkerPrivate* aWorkerPrivate,
  50. PerformanceObserverCallback& aCb)
  51. : mCallback(&aCb)
  52. , mConnected(false)
  53. {
  54. MOZ_ASSERT(aWorkerPrivate);
  55. mPerformance = aWorkerPrivate->GlobalScope()->GetPerformance();
  56. }
  57. PerformanceObserver::~PerformanceObserver()
  58. {
  59. Disconnect();
  60. MOZ_ASSERT(!mConnected);
  61. }
  62. // static
  63. already_AddRefed<PerformanceObserver>
  64. PerformanceObserver::Constructor(const GlobalObject& aGlobal,
  65. PerformanceObserverCallback& aCb,
  66. ErrorResult& aRv)
  67. {
  68. if (NS_IsMainThread()) {
  69. nsCOMPtr<nsPIDOMWindowInner> ownerWindow =
  70. do_QueryInterface(aGlobal.GetAsSupports());
  71. if (!ownerWindow) {
  72. aRv.Throw(NS_ERROR_FAILURE);
  73. return nullptr;
  74. }
  75. MOZ_ASSERT(ownerWindow->IsInnerWindow());
  76. RefPtr<PerformanceObserver> observer =
  77. new PerformanceObserver(ownerWindow, aCb);
  78. return observer.forget();
  79. }
  80. JSContext* cx = aGlobal.Context();
  81. WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
  82. MOZ_ASSERT(workerPrivate);
  83. RefPtr<PerformanceObserver> observer =
  84. new PerformanceObserver(workerPrivate, aCb);
  85. return observer.forget();
  86. }
  87. JSObject*
  88. PerformanceObserver::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
  89. {
  90. return PerformanceObserverBinding::Wrap(aCx, this, aGivenProto);
  91. }
  92. void
  93. PerformanceObserver::Notify()
  94. {
  95. if (mQueuedEntries.IsEmpty()) {
  96. return;
  97. }
  98. RefPtr<PerformanceObserverEntryList> list =
  99. new PerformanceObserverEntryList(this, mQueuedEntries);
  100. mQueuedEntries.Clear();
  101. ErrorResult rv;
  102. mCallback->Call(this, *list, *this, rv);
  103. if (NS_WARN_IF(rv.Failed())) {
  104. rv.SuppressException();
  105. }
  106. }
  107. void
  108. PerformanceObserver::QueueEntry(PerformanceEntry* aEntry)
  109. {
  110. MOZ_ASSERT(aEntry);
  111. nsAutoString entryType;
  112. aEntry->GetEntryType(entryType);
  113. if (!mEntryTypes.Contains<nsString>(entryType)) {
  114. return;
  115. }
  116. mQueuedEntries.AppendElement(aEntry);
  117. }
  118. static const char16_t *const sValidTypeNames[4] = {
  119. u"mark",
  120. u"measure",
  121. u"resource",
  122. u"server"
  123. };
  124. void
  125. PerformanceObserver::Observe(const PerformanceObserverInit& aOptions,
  126. ErrorResult& aRv)
  127. {
  128. if (aOptions.mEntryTypes.IsEmpty()) {
  129. aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
  130. return;
  131. }
  132. nsTArray<nsString> validEntryTypes;
  133. for (const char16_t* name : sValidTypeNames) {
  134. nsDependentString validTypeName(name);
  135. if (aOptions.mEntryTypes.Contains<nsString>(validTypeName) &&
  136. !validEntryTypes.Contains<nsString>(validTypeName)) {
  137. validEntryTypes.AppendElement(validTypeName);
  138. }
  139. }
  140. if (validEntryTypes.IsEmpty()) {
  141. aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
  142. return;
  143. }
  144. mEntryTypes.SwapElements(validEntryTypes);
  145. mPerformance->AddObserver(this);
  146. if (aOptions.mBuffered) {
  147. for (auto entryType : mEntryTypes) {
  148. nsTArray<RefPtr<PerformanceEntry>> existingEntries;
  149. mPerformance->GetEntriesByType(entryType, existingEntries);
  150. if (!existingEntries.IsEmpty()) {
  151. mQueuedEntries.AppendElements(existingEntries);
  152. }
  153. }
  154. }
  155. mConnected = true;
  156. }
  157. void
  158. PerformanceObserver::Disconnect()
  159. {
  160. if (mConnected) {
  161. MOZ_ASSERT(mPerformance);
  162. mPerformance->RemoveObserver(this);
  163. mConnected = false;
  164. }
  165. }