1/*
2 * Copyright (C) 2017 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "PerformanceObserver.h"
28
29#include "DOMWindow.h"
30#include "Document.h"
31#include "InspectorInstrumentation.h"
32#include "Performance.h"
33#include "PerformanceObserverEntryList.h"
34#include "WorkerGlobalScope.h"
35
36namespace WebCore {
37
38PerformanceObserver::PerformanceObserver(ScriptExecutionContext& scriptExecutionContext, Ref<PerformanceObserverCallback>&& callback)
39 : m_callback(WTFMove(callback))
40{
41 if (is<Document>(scriptExecutionContext)) {
42 auto& document = downcast<Document>(scriptExecutionContext);
43 if (DOMWindow* window = document.domWindow())
44 m_performance = &window->performance();
45 } else if (is<WorkerGlobalScope>(scriptExecutionContext)) {
46 auto& workerGlobalScope = downcast<WorkerGlobalScope>(scriptExecutionContext);
47 m_performance = &workerGlobalScope.performance();
48 } else
49 ASSERT_NOT_REACHED();
50}
51
52void PerformanceObserver::disassociate()
53{
54 m_performance = nullptr;
55 m_registered = false;
56}
57
58ExceptionOr<void> PerformanceObserver::observe(Init&& init)
59{
60 if (!m_performance)
61 return Exception { TypeError };
62
63 if (init.entryTypes.isEmpty())
64 return Exception { TypeError, "entryTypes cannot be an empty list"_s };
65
66 OptionSet<PerformanceEntry::Type> filter;
67 for (const String& entryType : init.entryTypes) {
68 if (auto type = PerformanceEntry::parseEntryTypeString(entryType))
69 filter.add(*type);
70 }
71
72 if (filter.isEmpty())
73 return Exception { TypeError, "entryTypes contained only unsupported types"_s };
74
75 m_typeFilter = filter;
76
77 if (!m_registered) {
78 m_performance->registerPerformanceObserver(*this);
79 m_registered = true;
80 }
81
82 return { };
83}
84
85void PerformanceObserver::disconnect()
86{
87 if (m_performance)
88 m_performance->unregisterPerformanceObserver(*this);
89
90 m_registered = false;
91 m_entriesToDeliver.clear();
92}
93
94void PerformanceObserver::queueEntry(PerformanceEntry& entry)
95{
96 m_entriesToDeliver.append(&entry);
97}
98
99void PerformanceObserver::deliver()
100{
101 if (m_entriesToDeliver.isEmpty())
102 return;
103
104 auto* context = m_callback->scriptExecutionContext();
105 if (!context)
106 return;
107
108 Vector<RefPtr<PerformanceEntry>> entries = WTFMove(m_entriesToDeliver);
109 auto list = PerformanceObserverEntryList::create(WTFMove(entries));
110
111 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireObserverCallback(*context, "PerformanceObserver"_s);
112 m_callback->handleEvent(list, *this);
113 InspectorInstrumentation::didFireObserverCallback(cookie);
114}
115
116Vector<String> PerformanceObserver::supportedEntryTypes()
117{
118 return {
119 // FIXME: <https://webkit.org/b/184363> Add support for Navigation Timing Level 2
120 // "navigation"_s,
121 "mark"_s,
122 "measure"_s,
123 "resource"_s
124 };
125}
126
127} // namespace WebCore
128