OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "config.h" | |
6 #include "core/dom/ScriptedIdleTaskController.h" | |
7 | |
8 #include "core/dom/ExecutionContext.h" | |
9 #include "core/dom/IdleRequestCallback.h" | |
10 #include "core/loader/DocumentLoadTiming.h" | |
11 #include "platform/Logging.h" | |
12 #include "platform/TraceEvent.h" | |
13 #include "public/platform/Platform.h" | |
14 #include "public/platform/WebScheduler.h" | |
15 #include "public/platform/WebTraceLocation.h" | |
16 #include "wtf/CurrentTime.h" | |
17 #include "wtf/Functional.h" | |
18 | |
19 namespace blink { | |
20 | |
21 namespace internal { | |
22 | |
23 class IdleRequestCallbackWrapper : public RefCounted<IdleRequestCallbackWrapper> { | |
24 public: | |
25 static PassRefPtr<IdleRequestCallbackWrapper> create(ScriptedIdleTaskControl ler::CallbackId id, PassRefPtrWillBeRawPtr<ScriptedIdleTaskController> controlle r) | |
26 { | |
27 return adoptRef(new IdleRequestCallbackWrapper(id, controller)); | |
28 } | |
29 virtual ~IdleRequestCallbackWrapper() | |
30 { | |
31 } | |
32 | |
33 static void idleTaskFired(PassRefPtr<IdleRequestCallbackWrapper> callbackWra pper, double deadlineSeconds) | |
34 { | |
35 callbackWrapper->controller()->callbackFired(callbackWrapper->id(), dead lineSeconds, IdleCallbackDeadline::CallbackType::CalledWhenIdle); | |
esprehn
2015/08/21 08:22:21
This doesn't have the clamping behavior where shor
rmcilroy
2015/08/21 11:21:52
I know that there is discussion on clamping to avo
| |
36 } | |
37 | |
38 static void timeoutFired(PassRefPtr<IdleRequestCallbackWrapper> callbackWrap per) | |
39 { | |
40 callbackWrapper->controller()->callbackFired(callbackWrapper->id(), mono tonicallyIncreasingTime(), IdleCallbackDeadline::CallbackType::CalledByTimeout); | |
41 } | |
42 | |
43 ScriptedIdleTaskController::CallbackId id() { return m_id; } | |
esprehn
2015/08/21 08:22:21
const
rmcilroy
2015/08/21 11:21:52
Done.
| |
44 PassRefPtrWillBeRawPtr<ScriptedIdleTaskController> controller() { return m_c ontroller; } | |
45 | |
46 private: | |
47 explicit IdleRequestCallbackWrapper(ScriptedIdleTaskController::CallbackId i d, PassRefPtrWillBeRawPtr<ScriptedIdleTaskController> controller) | |
48 : m_id(id) | |
49 , m_controller(controller) | |
50 { | |
51 } | |
52 | |
53 ScriptedIdleTaskController::CallbackId m_id; | |
54 RefPtrWillBePersistent<ScriptedIdleTaskController> m_controller; | |
55 }; | |
56 | |
57 } // namespace internal | |
58 | |
59 ScriptedIdleTaskController::ScriptedIdleTaskController(ExecutionContext* context , const DocumentLoadTiming& timing) | |
60 : ActiveDOMObject(context) | |
61 , m_timing(timing) | |
62 , m_scheduler(Platform::current()->currentThread()->scheduler()) | |
63 , m_nextCallbackId(0) | |
64 , m_suspended(false) | |
65 { | |
66 suspendIfNeeded(); | |
67 } | |
68 | |
69 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(ScriptedIdleTaskController); | |
70 | |
71 DEFINE_TRACE(ScriptedIdleTaskController) | |
72 { | |
73 ActiveDOMObject::trace(visitor); | |
74 visitor->trace(m_callbacks); | |
75 } | |
76 | |
77 ScriptedIdleTaskController::CallbackId ScriptedIdleTaskController::registerCallb ack(IdleRequestCallback* callback, double timeoutMillis) | |
78 { | |
79 CallbackId id = ++m_nextCallbackId; | |
80 m_callbacks.set(id, callback); | |
81 | |
82 RefPtr<internal::IdleRequestCallbackWrapper> callbackWrapper = internal::Idl eRequestCallbackWrapper::create(id, this); | |
83 m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&internal::IdleReques tCallbackWrapper::idleTaskFired, callbackWrapper)); | |
84 if (timeoutMillis > 0) | |
85 m_scheduler->postTimerTask(FROM_HERE, WTF::bind(&internal::IdleRequestCa llbackWrapper::timeoutFired, callbackWrapper), static_cast<long long>(timeoutMil lis)); | |
86 | |
87 // TODO(rmcilroy): Add devtools tracing. | |
88 return id; | |
89 } | |
90 | |
91 void ScriptedIdleTaskController::cancelCallback(CallbackId id) | |
92 { | |
93 // TODO(rmcilroy): Add devtools tracing. | |
94 m_callbacks.remove(id); | |
95 } | |
96 | |
97 void ScriptedIdleTaskController::callbackFired(CallbackId id, double deadlineSec onds, IdleCallbackDeadline::CallbackType callbackType) | |
98 { | |
99 if (!m_callbacks.contains(id)) | |
100 return; | |
101 | |
102 if (m_suspended) { | |
103 if (callbackType == IdleCallbackDeadline::CallbackType::CalledByTimeout) { | |
104 // Queue for execution when we are resumed. | |
105 m_pendingTimeouts.append(id); | |
106 } | |
107 // Just drop callbacks called while suspended, these will be reposted on the idle task queue when we are resumed. | |
108 return; | |
109 } | |
110 | |
111 double deadlineMillis = 1000.0 * m_timing.monotonicTimeToZeroBasedDocumentTi me(deadlineSeconds); | |
112 runCallback(id, deadlineMillis, callbackType); | |
113 } | |
114 | |
115 void ScriptedIdleTaskController::runCallback(CallbackId id, double deadlineMilli s, IdleCallbackDeadline::CallbackType callbackType) | |
116 { | |
117 ASSERT(!m_suspended); | |
118 auto callback = m_callbacks.take(id); | |
119 if (!callback) | |
120 return; | |
121 | |
122 // TODO(rmcilroy): Add devtools tracing. | |
123 callback->handleEvent(IdleCallbackDeadline::create(deadlineMillis, callbackT ype, m_timing)); | |
124 } | |
125 | |
126 void ScriptedIdleTaskController::stop() | |
127 { | |
128 m_callbacks.clear(); | |
129 } | |
130 | |
131 void ScriptedIdleTaskController::suspend() | |
132 { | |
133 m_suspended = true; | |
134 } | |
135 | |
136 void ScriptedIdleTaskController::resume() | |
137 { | |
138 ASSERT(m_suspended); | |
139 m_suspended = false; | |
140 | |
141 // Run any pending timeouts. | |
142 Vector<CallbackId> pendingTimeouts; | |
143 m_pendingTimeouts.swap(pendingTimeouts); | |
144 for (auto& id : pendingTimeouts) | |
145 runCallback(id, monotonicallyIncreasingTime(), IdleCallbackDeadline::Cal lbackType::CalledByTimeout); | |
146 | |
147 // Repost idle tasks for any remaining callbacks. | |
148 for (auto& callback : m_callbacks) { | |
149 RefPtr<internal::IdleRequestCallbackWrapper> callbackWrapper = internal: :IdleRequestCallbackWrapper::create(callback.key, this); | |
150 m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&internal::IdleRe questCallbackWrapper::idleTaskFired, callbackWrapper)); | |
151 } | |
152 } | |
153 | |
154 bool ScriptedIdleTaskController::hasPendingActivity() const | |
155 { | |
156 return !m_callbacks.isEmpty(); | |
157 } | |
158 | |
159 | |
160 | |
161 } // namespace blink | |
OLD | NEW |