Chromium Code Reviews

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: Address Elliott's review comments Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | 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 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
OLDNEW

Powered by Google App Engine