| 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 |