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