Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(527)

Side by Side Diff: Source/core/dom/ScriptedIdleTaskController.cpp

Issue 1119683003: Implement requestIdleCallback API (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebased Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 ScriptedIdleTaskController::ScriptedIdleTaskController(ExecutionContext* context , const DocumentLoadTiming& timing)
22 : ActiveDOMObject(context)
23 , m_timing(timing)
24 , m_scheduler(Platform::current()->currentThread()->scheduler())
25 , m_nextCallbackId(0)
26 , m_suspended(false)
27 {
28 suspendIfNeeded();
29 }
30
31 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(ScriptedIdleTaskController);
32
33 DEFINE_TRACE(ScriptedIdleTaskController)
34 {
35 ActiveDOMObject::trace(visitor);
36 visitor->trace(m_callbacks);
37 }
38
39 ScriptedIdleTaskController::CallbackId ScriptedIdleTaskController::registerCallb ack(IdleRequestCallback* callback, double timeoutMillis)
40 {
41 CallbackId id = ++m_nextCallbackId;
42 m_callbacks.set(id, callback);
43
44 RefPtr<IdleRequestCallbackWrapper> callbackWrapper = IdleRequestCallbackWrap per::create(id, this);
45 if (timeoutMillis > 0)
46 callbackWrapper->setTimeout(timeoutMillis);
47
48 m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&ScriptedIdleTaskCont roller::IdleRequestCallbackWrapper::idleTaskFired, callbackWrapper));
49 // TODO(rmcilroy): Add devtools tracing.
50 return id;
51 }
52
53 void ScriptedIdleTaskController::cancelCallback(CallbackId id)
54 {
55 // TODO(rmcilroy): Add devtools tracing.
56 m_callbacks.remove(id);
57 }
58
59 void ScriptedIdleTaskController::callbackFired(IdleRequestCallbackWrapper* callb ackWrapper, double deadlineSeconds, IdleCallbackDeadline::CallbackType callbackT ype)
60 {
61 CallbackId id = callbackWrapper->id();
62 if (!m_callbacks.contains(id))
63 return;
64
65 if (m_suspended) {
66 if (callbackType == IdleCallbackDeadline::CallbackType::CalledByTimeout) {
67 callbackWrapper->cancelTimeout();
68 // Queue for execution when we are resumed.
69 m_pendingTimeouts.push(id);
70 }
71 // Just drop callbacks called while suspended, these will be reposted on the idle task queue when we are resumed.
72 return;
73 }
74 callbackWrapper->cancelTimeout();
75
76 double deadlineMillis = 1000.0 * m_timing.monotonicTimeToZeroBasedDocumentTi me(deadlineSeconds);
77 runCallback(id, deadlineMillis, callbackType);
78 }
79
80 void ScriptedIdleTaskController::runCallback(CallbackId id, double deadlineMilli s, IdleCallbackDeadline::CallbackType callbackType)
81 {
82 ASSERT(!m_suspended);
83 auto callback = m_callbacks.take(id);
84 if (!callback)
85 return;
86
87 // TODO(rmcilroy): Add devtools tracing.
88 callback->handleEvent(IdleCallbackDeadline::create(deadlineMillis, callbackT ype, m_timing));
89 }
90
91 void ScriptedIdleTaskController::stop()
92 {
93 m_callbacks.clear();
94 }
95
96 void ScriptedIdleTaskController::suspend()
97 {
98 m_suspended = true;
99 }
100
101 void ScriptedIdleTaskController::resume()
102 {
103 ASSERT(m_suspended);
104 m_suspended = false;
105
106 // Run any pending timeouts.
107 while (!m_pendingTimeouts.empty()) {
esprehn 2015/08/20 20:45:55 Vector<...> pendingTimeouts; m_pendingTimeouts.swa
rmcilroy 2015/08/21 00:03:45 Done.
108 runCallback(m_pendingTimeouts.front(), -1, IdleCallbackDeadline::Callbac kType::CalledByTimeout);
esprehn 2015/08/20 20:45:55 Why is the deadline -1?
rmcilroy 2015/08/21 00:03:45 Good catch, this was a leftover from the spec befo
109 m_pendingTimeouts.pop();
110 }
111
112 // Repost idle tasks for any remaining callbacks.
113 for (auto callback = m_callbacks.begin(); callback != m_callbacks.end();
esprehn 2015/08/20 20:45:55 for(auto& callback : m_callbacks)
rmcilroy 2015/08/21 00:03:45 Done.
114 ++callback) {
115 RefPtr<IdleRequestCallbackWrapper> callbackWrapper = IdleRequestCallback Wrapper::create(callback->key, this);
116 m_scheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&ScriptedIdleTask Controller::IdleRequestCallbackWrapper::idleTaskFired, callbackWrapper));
117 }
118 }
119
120 bool ScriptedIdleTaskController::hasPendingActivity() const
121 {
122 return !m_callbacks.isEmpty();
123 }
124
125 ScriptedIdleTaskController::IdleRequestCallbackWrapper::IdleRequestCallbackWrapp er(CallbackId id, PassRefPtrWillBeRawPtr<ScriptedIdleTaskController> controller)
126 : m_id(id)
127 , m_timeoutTimer(nullptr)
128 , m_controller(controller)
129 {
130 }
131
132 ScriptedIdleTaskController::IdleRequestCallbackWrapper::~IdleRequestCallbackWrap per()
esprehn 2015/08/20 20:45:55 Can we un nested the classes and put them in separ
rmcilroy 2015/08/21 00:03:45 I've removed the IdleRequestTimeoutTimer class ent
133 {
134 }
135
136 // static
137 void ScriptedIdleTaskController::IdleRequestCallbackWrapper::idleTaskFired(PassR efPtr<IdleRequestCallbackWrapper> callbackWrapper, double deadlineSeconds)
138 {
139 callbackWrapper->m_controller->callbackFired(callbackWrapper.get(), deadline Seconds, IdleCallbackDeadline::CallbackType::CalledWhenIdle);
140 }
141
142 ScriptedIdleTaskController::IdleRequestCallbackWrapper::IdleRequestTimeoutTimer: :IdleRequestTimeoutTimer(PassRefPtr<IdleRequestCallbackWrapper> callbackWrapper)
143 : Timer(this, &IdleRequestTimeoutTimer::timeoutFired)
144 , m_callbackWrapper(callbackWrapper)
145 {
146 }
147
148 void ScriptedIdleTaskController::IdleRequestCallbackWrapper::cancelTimeout()
149 {
150 if (m_timeoutTimer.get()) {
esprehn 2015/08/20 20:45:55 Why is this heap allocated? The destructor should
rmcilroy 2015/08/21 00:03:45 Removed entirely.
151 m_timeoutTimer->stop();
152 m_timeoutTimer.clear();
153 }
154 }
155
156 ScriptedIdleTaskController::IdleRequestCallbackWrapper::IdleRequestTimeoutTimer: :~IdleRequestTimeoutTimer()
157 {
158 }
159
160 void ScriptedIdleTaskController::IdleRequestCallbackWrapper::IdleRequestTimeoutT imer::timeoutFired(Timer<IdleRequestTimeoutTimer>* timer)
161 {
162 m_callbackWrapper->controller()->callbackFired(m_callbackWrapper.get(), mono tonicallyIncreasingTime(), IdleCallbackDeadline::CallbackType::CalledByTimeout);
esprehn 2015/08/20 20:45:55 Can we just do this with methods on the controller
rmcilroy 2015/08/21 00:03:44 As discussed offline, changed this to be a bind()
163 }
164
165 void ScriptedIdleTaskController::IdleRequestCallbackWrapper::setTimeout(double t imeoutMillis)
166 {
167 ASSERT(!m_timeoutTimer.get());
168 m_timeoutTimer = adoptPtr(new IdleRequestTimeoutTimer(this));
169 m_timeoutTimer->startOneShot(0.001 * timeoutMillis, FROM_HERE);
170 }
171
172 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698