OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. | 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 24 matching lines...) Expand all Loading... |
35 #include "public/platform/WebThread.h" | 35 #include "public/platform/WebThread.h" |
36 | 36 |
37 namespace blink { | 37 namespace blink { |
38 | 38 |
39 ScriptRunner::ScriptRunner(Document* document) | 39 ScriptRunner::ScriptRunner(Document* document) |
40 : m_document(document) | 40 : m_document(document) |
41 , m_taskRunner(Platform::current()->currentThread()->scheduler()->loadingTas
kRunner()) | 41 , m_taskRunner(Platform::current()->currentThread()->scheduler()->loadingTas
kRunner()) |
42 , m_numberOfInOrderScriptsWithPendingNotification(0) | 42 , m_numberOfInOrderScriptsWithPendingNotification(0) |
43 , m_isSuspended(false) | 43 , m_isSuspended(false) |
44 #if !ENABLE(OILPAN) | 44 #if !ENABLE(OILPAN) |
45 , m_isDisposed(false) | |
46 , m_weakPointerFactoryForTasks(this) | 45 , m_weakPointerFactoryForTasks(this) |
47 #endif | 46 #endif |
48 { | 47 { |
49 ASSERT(document); | 48 ASSERT(document); |
50 #ifndef NDEBUG | 49 #ifndef NDEBUG |
51 m_hasEverBeenSuspended = false; | 50 m_hasEverBeenSuspended = false; |
52 #endif | 51 #endif |
53 } | 52 } |
54 | 53 |
55 ScriptRunner::~ScriptRunner() | 54 ScriptRunner::~ScriptRunner() |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 scriptLoader->detach(); | 90 scriptLoader->detach(); |
92 for (ScriptLoader* scriptLoader : m_inOrderScriptsToExecuteSoon) | 91 for (ScriptLoader* scriptLoader : m_inOrderScriptsToExecuteSoon) |
93 scriptLoader->detach(); | 92 scriptLoader->detach(); |
94 for (ScriptLoader* scriptLoader : m_asyncScriptsToExecuteSoon) | 93 for (ScriptLoader* scriptLoader : m_asyncScriptsToExecuteSoon) |
95 scriptLoader->detach(); | 94 scriptLoader->detach(); |
96 | 95 |
97 m_pendingInOrderScripts.clear(); | 96 m_pendingInOrderScripts.clear(); |
98 m_pendingAsyncScripts.clear(); | 97 m_pendingAsyncScripts.clear(); |
99 m_inOrderScriptsToExecuteSoon.clear(); | 98 m_inOrderScriptsToExecuteSoon.clear(); |
100 m_asyncScriptsToExecuteSoon.clear(); | 99 m_asyncScriptsToExecuteSoon.clear(); |
101 m_isDisposed = true; | 100 m_numberOfInOrderScriptsWithPendingNotification = 0; |
102 } | 101 } |
103 #endif | 102 #endif |
104 | 103 |
105 void ScriptRunner::addPendingAsyncScript(ScriptLoader* scriptLoader) | |
106 { | |
107 m_document->incrementLoadEventDelayCount(); | |
108 m_pendingAsyncScripts.add(scriptLoader); | |
109 } | |
110 | |
111 void ScriptRunner::queueScriptForExecution(ScriptLoader* scriptLoader, Execution
Type executionType) | 104 void ScriptRunner::queueScriptForExecution(ScriptLoader* scriptLoader, Execution
Type executionType) |
112 { | 105 { |
113 ASSERT(scriptLoader); | 106 ASSERT(scriptLoader); |
114 | 107 m_document->incrementLoadEventDelayCount(); |
115 switch (executionType) { | 108 switch (executionType) { |
116 case ASYNC_EXECUTION: | 109 case ASYNC_EXECUTION: |
117 addPendingAsyncScript(scriptLoader); | 110 m_pendingAsyncScripts.add(scriptLoader); |
118 break; | 111 break; |
119 | 112 |
120 case IN_ORDER_EXECUTION: | 113 case IN_ORDER_EXECUTION: |
121 m_document->incrementLoadEventDelayCount(); | |
122 m_pendingInOrderScripts.append(scriptLoader); | 114 m_pendingInOrderScripts.append(scriptLoader); |
123 m_numberOfInOrderScriptsWithPendingNotification++; | 115 m_numberOfInOrderScriptsWithPendingNotification++; |
124 break; | 116 break; |
125 } | 117 } |
126 } | 118 } |
127 | 119 |
128 void ScriptRunner::postTask(const WebTraceLocation& webTraceLocation) | 120 void ScriptRunner::postTask(const WebTraceLocation& webTraceLocation) |
129 { | 121 { |
130 // TODO(altimin): Replace all this with `new Task(this)` when Oilpan is here
. | 122 // TODO(altimin): Replace all this with `new Task(this)` when Oilpan is here
. |
131 WeakPtrWillBeRawPtr<ScriptRunner> scriptRunnerForTask; | 123 WeakPtrWillBeRawPtr<ScriptRunner> scriptRunnerForTask; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 | 176 |
185 while (!m_pendingInOrderScripts.isEmpty() && m_pendingInOrderScripts.fir
st()->isReady()) { | 177 while (!m_pendingInOrderScripts.isEmpty() && m_pendingInOrderScripts.fir
st()->isReady()) { |
186 m_inOrderScriptsToExecuteSoon.append(m_pendingInOrderScripts.takeFir
st()); | 178 m_inOrderScriptsToExecuteSoon.append(m_pendingInOrderScripts.takeFir
st()); |
187 postTask(BLINK_FROM_HERE); | 179 postTask(BLINK_FROM_HERE); |
188 } | 180 } |
189 | 181 |
190 break; | 182 break; |
191 } | 183 } |
192 } | 184 } |
193 | 185 |
| 186 bool ScriptRunner::removePendingInOrderScript(ScriptLoader* scriptLoader) |
| 187 { |
| 188 for (auto it = m_pendingInOrderScripts.begin(); it != m_pendingInOrderScript
s.end(); ++it) { |
| 189 if (*it == scriptLoader) { |
| 190 m_pendingInOrderScripts.remove(it); |
| 191 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_numberOfInOrderScriptsWit
hPendingNotification > 0); |
| 192 m_numberOfInOrderScriptsWithPendingNotification--; |
| 193 return true; |
| 194 } |
| 195 } |
| 196 return false; |
| 197 } |
| 198 |
194 void ScriptRunner::notifyScriptLoadError(ScriptLoader* scriptLoader, ExecutionTy
pe executionType) | 199 void ScriptRunner::notifyScriptLoadError(ScriptLoader* scriptLoader, ExecutionTy
pe executionType) |
195 { | 200 { |
196 switch (executionType) { | 201 switch (executionType) { |
197 case ASYNC_EXECUTION: { | 202 case ASYNC_EXECUTION: { |
198 bool foundLoader = m_pendingAsyncScripts.contains(scriptLoader); | |
199 #if !ENABLE(OILPAN) | |
200 // If the document and ScriptRunner has been disposed of, there's | |
201 // no bookkeeping to be done here. | |
202 foundLoader = foundLoader || m_isDisposed; | |
203 #endif | |
204 // RELEASE_ASSERT makes us crash in a controlled way in error cases | 203 // RELEASE_ASSERT makes us crash in a controlled way in error cases |
205 // where the ScriptLoader is associated with the wrong ScriptRunner | 204 // where the ScriptLoader is associated with the wrong ScriptRunner |
206 // (otherwise we'd cause a use-after-free in ~ScriptRunner when it tries | 205 // (otherwise we'd cause a use-after-free in ~ScriptRunner when it tries |
207 // to detach). | 206 // to detach). |
208 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(foundLoader); | 207 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_pendingAsyncScripts.contains(
scriptLoader)); |
209 m_pendingAsyncScripts.remove(scriptLoader); | 208 m_pendingAsyncScripts.remove(scriptLoader); |
210 break; | 209 break; |
211 } | 210 } |
212 case IN_ORDER_EXECUTION: | 211 case IN_ORDER_EXECUTION: |
213 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_numberOfInOrderScriptsWithPen
dingNotification > 0); | 212 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(removePendingInOrderScript(scri
ptLoader)); |
214 m_numberOfInOrderScriptsWithPendingNotification--; | |
215 | |
216 bool foundPendingScript = false; | |
217 for (auto it = m_pendingInOrderScripts.begin(); it != m_pendingInOrderSc
ripts.end(); ++it) { | |
218 if (*it == scriptLoader) { | |
219 m_pendingInOrderScripts.remove(it); | |
220 foundPendingScript = true; | |
221 break; | |
222 } | |
223 } | |
224 #if !ENABLE(OILPAN) | |
225 foundPendingScript = foundPendingScript || m_isDisposed; | |
226 #endif | |
227 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(foundPendingScript); | |
228 break; | 213 break; |
229 } | 214 } |
230 scriptLoader->detach(); | 215 scriptLoader->detach(); |
231 m_document->decrementLoadEventDelayCount(); | 216 m_document->decrementLoadEventDelayCount(); |
232 } | 217 } |
233 | 218 |
234 void ScriptRunner::movePendingAsyncScript(Document& oldDocument, Document& newDo
cument, ScriptLoader* scriptLoader) | 219 void ScriptRunner::movePendingScript(Document& oldDocument, Document& newDocumen
t, ScriptLoader* scriptLoader) |
235 { | 220 { |
236 RefPtrWillBeRawPtr<Document> newContextDocument = newDocument.contextDocumen
t().get(); | 221 RefPtrWillBeRawPtr<Document> newContextDocument = newDocument.contextDocumen
t().get(); |
237 if (!newContextDocument) { | 222 if (!newContextDocument) { |
238 // Document's contextDocument() method will return no Document if the | 223 // Document's contextDocument() method will return no Document if the |
239 // following conditions both hold: | 224 // following conditions both hold: |
240 // | 225 // |
241 // - The Document wasn't created with an explicit context document | 226 // - The Document wasn't created with an explicit context document |
242 // and that document is otherwise kept alive. | 227 // and that document is otherwise kept alive. |
243 // - The Document itself is detached from its frame. | 228 // - The Document itself is detached from its frame. |
244 // | 229 // |
245 // The script element's loader is in that case moved to document() and | 230 // The script element's loader is in that case moved to document() and |
246 // its script runner, which is the non-null Document that contextDocumen
t() | 231 // its script runner, which is the non-null Document that contextDocumen
t() |
247 // would return if not detached. | 232 // would return if not detached. |
248 ASSERT(!newDocument.frame()); | 233 ASSERT(!newDocument.frame()); |
249 newContextDocument = &newDocument; | 234 newContextDocument = &newDocument; |
250 } | 235 } |
251 RefPtrWillBeRawPtr<Document> oldContextDocument = oldDocument.contextDocumen
t().get(); | 236 RefPtrWillBeRawPtr<Document> oldContextDocument = oldDocument.contextDocumen
t().get(); |
252 if (!oldContextDocument) { | 237 if (!oldContextDocument) { |
253 ASSERT(!oldDocument.frame()); | 238 ASSERT(!oldDocument.frame()); |
254 oldContextDocument = &oldDocument; | 239 oldContextDocument = &oldDocument; |
255 } | 240 } |
256 if (oldContextDocument != newContextDocument) | 241 if (oldContextDocument != newContextDocument) |
257 oldContextDocument->scriptRunner()->movePendingAsyncScript(newContextDoc
ument->scriptRunner(), scriptLoader); | 242 oldContextDocument->scriptRunner()->movePendingScript(newContextDocument
->scriptRunner(), scriptLoader); |
258 } | 243 } |
259 | 244 |
260 void ScriptRunner::movePendingAsyncScript(ScriptRunner* newRunner, ScriptLoader*
scriptLoader) | 245 void ScriptRunner::movePendingScript(ScriptRunner* newRunner, ScriptLoader* scri
ptLoader) |
261 { | 246 { |
262 if (m_pendingAsyncScripts.contains(scriptLoader)) { | 247 if (m_pendingAsyncScripts.contains(scriptLoader)) { |
263 newRunner->addPendingAsyncScript(scriptLoader); | 248 newRunner->queueScriptForExecution(scriptLoader, ASYNC_EXECUTION); |
264 m_pendingAsyncScripts.remove(scriptLoader); | 249 m_pendingAsyncScripts.remove(scriptLoader); |
265 m_document->decrementLoadEventDelayCount(); | 250 m_document->decrementLoadEventDelayCount(); |
| 251 return; |
| 252 } |
| 253 if (removePendingInOrderScript(scriptLoader)) { |
| 254 newRunner->queueScriptForExecution(scriptLoader, IN_ORDER_EXECUTION); |
| 255 m_document->decrementLoadEventDelayCount(); |
266 } | 256 } |
267 } | 257 } |
268 | 258 |
269 // Returns true if task was run, and false otherwise. | 259 // Returns true if task was run, and false otherwise. |
270 bool ScriptRunner::executeTaskFromQueue(WillBeHeapDeque<RawPtrWillBeMember<Scrip
tLoader>>* taskQueue) | 260 bool ScriptRunner::executeTaskFromQueue(WillBeHeapDeque<RawPtrWillBeMember<Scrip
tLoader>>* taskQueue) |
271 { | 261 { |
272 if (taskQueue->isEmpty()) | 262 if (taskQueue->isEmpty()) |
273 return false; | 263 return false; |
274 taskQueue->takeFirst()->execute(); | 264 taskQueue->takeFirst()->execute(); |
275 | 265 |
(...skipping 23 matching lines...) Expand all Loading... |
299 #if ENABLE(OILPAN) | 289 #if ENABLE(OILPAN) |
300 visitor->trace(m_document); | 290 visitor->trace(m_document); |
301 visitor->trace(m_pendingInOrderScripts); | 291 visitor->trace(m_pendingInOrderScripts); |
302 visitor->trace(m_pendingAsyncScripts); | 292 visitor->trace(m_pendingAsyncScripts); |
303 visitor->trace(m_asyncScriptsToExecuteSoon); | 293 visitor->trace(m_asyncScriptsToExecuteSoon); |
304 visitor->trace(m_inOrderScriptsToExecuteSoon); | 294 visitor->trace(m_inOrderScriptsToExecuteSoon); |
305 #endif | 295 #endif |
306 } | 296 } |
307 | 297 |
308 } // namespace blink | 298 } // namespace blink |
OLD | NEW |