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

Unified Diff: Source/core/dom/ScriptLoader.cpp

Issue 271533002: Make ScriptLoader into a ResourceOwner (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: Source/core/dom/ScriptLoader.cpp
diff --git a/Source/core/dom/ScriptLoader.cpp b/Source/core/dom/ScriptLoader.cpp
index 6585f8d7680a82e49a5bc6bc81ef217d9b6a41b1..07a18092e922017b7c8386f736ccf790206146f9 100644
--- a/Source/core/dom/ScriptLoader.cpp
+++ b/Source/core/dom/ScriptLoader.cpp
@@ -54,7 +54,6 @@ namespace WebCore {
ScriptLoader::ScriptLoader(Element* element, bool parserInserted, bool alreadyStarted)
: m_element(element)
- , m_resource(0)
, m_startLineNumber(WTF::OrdinalNumber::beforeFirst())
, m_parserInserted(parserInserted)
, m_isExternalScript(false)
@@ -73,7 +72,6 @@ ScriptLoader::ScriptLoader(Element* element, bool parserInserted, bool alreadySt
ScriptLoader::~ScriptLoader()
{
- stopLoadRequest();
}
void ScriptLoader::didNotifySubtreeInsertionsToDocument()
@@ -165,7 +163,7 @@ bool ScriptLoader::isScriptTypeSupported(LegacyTypeSupport supportLegacyTypes) c
}
// http://dev.w3.org/html5/spec/Overview.html#prepare-a-script
-bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, LegacyTypeSupport supportLegacyTypes)
+bool ScriptLoader::prepareScript(ResourcePtr<ScriptResource>* fetchedResource, const TextPosition& scriptStartPosition, LegacyTypeSupport supportLegacyTypes)
{
if (m_alreadyStarted)
return false;
@@ -215,9 +213,13 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, Legacy
else
m_characterEncoding = elementDocument.charset();
+ ResourcePtr<ScriptResource> resource;
if (client->hasSourceAttribute()) {
- if (!fetchScript(client->sourceAttributeValue()))
+ resource = fetchScript(client->sourceAttributeValue());
+ if (!resource) {
+ dispatchErrorEvent();
return false;
+ }
}
if (client->hasSourceAttribute() && client->deferAttributeValue() && m_parserInserted && !client->asyncAttributeValue()) {
@@ -230,11 +232,9 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, Legacy
m_readyToBeParserExecuted = true;
} else if (client->hasSourceAttribute() && !client->asyncAttributeValue() && !m_forceAsync) {
m_willExecuteInOrder = true;
- contextDocument->scriptRunner()->queueScriptForExecution(this, m_resource, ScriptRunner::IN_ORDER_EXECUTION);
- m_resource->addClient(this);
+ contextDocument->scriptRunner()->queueScriptForExecution(this, resource, ScriptRunner::IN_ORDER_EXECUTION);
} else if (client->hasSourceAttribute()) {
- contextDocument->scriptRunner()->queueScriptForExecution(this, m_resource, ScriptRunner::ASYNC_EXECUTION);
- m_resource->addClient(this);
+ contextDocument->scriptRunner()->queueScriptForExecution(this, resource, ScriptRunner::ASYNC_EXECUTION);
} else {
// Reset line numbering for nested writes.
TextPosition position = elementDocument.isInDocumentWrite() ? TextPosition() : scriptStartPosition;
@@ -242,18 +242,27 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, Legacy
executeScript(ScriptSourceCode(scriptContent(), scriptURL, position));
}
+ if (resource) {
+ // We have to return fetchedResource instead of let callers ask ScriptLoader::resource()
+ // because resource() can be null when it is accessed: Following setResource() can trigger clearResource().
+ if (fetchedResource)
+ *fetchedResource = resource;
+ setResource(resource);
+ }
+
return true;
}
-bool ScriptLoader::fetchScript(const String& sourceUrl)
+ResourcePtr<ScriptResource> ScriptLoader::fetchScript(const String& sourceUrl)
{
ASSERT(m_element);
RefPtr<Document> elementDocument(m_element->document());
if (!m_element->inDocument() || m_element->document() != elementDocument)
- return false;
+ return ResourcePtr<ScriptResource>();
- ASSERT(!m_resource);
+ ASSERT(!resource());
+ ResourcePtr<ScriptResource> resource;
if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) {
FetchRequest request(ResourceRequest(elementDocument->completeURL(sourceUrl)), m_element->localName());
@@ -266,15 +275,11 @@ bool ScriptLoader::fetchScript(const String& sourceUrl)
if (isValidScriptNonce)
request.setContentSecurityCheck(DoNotCheckContentSecurityPolicy);
- m_resource = elementDocument->fetcher()->fetchScript(request);
+ resource = elementDocument->fetcher()->fetchScript(request);
m_isExternalScript = true;
}
- if (m_resource)
- return true;
-
- dispatchErrorEvent();
- return false;
+ return resource;
}
bool isHTMLScriptLoader(Element* element)
@@ -309,7 +314,7 @@ void ScriptLoader::executeScript(const ScriptSourceCode& sourceCode)
return;
if (m_isExternalScript) {
- ScriptResource* resource = m_resource ? m_resource.get() : sourceCode.resource();
+ ScriptResource* resource = this->resource() ? this->resource() : sourceCode.resource();
if (resource && !resource->mimeTypeAllowedByNosniff()) {
contextDocument->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Refused to execute script from '" + resource->url().elidedString() + "' because its MIME type ('" + resource->mimeType() + "') is not executable, and strict MIME type checking is enabled.");
return;
@@ -341,15 +346,6 @@ void ScriptLoader::executeScript(const ScriptSourceCode& sourceCode)
}
}
-void ScriptLoader::stopLoadRequest()
-{
- if (m_resource) {
- if (!m_willBeParserExecuted)
- m_resource->removeClient(this);
- m_resource = 0;
- }
-}
-
void ScriptLoader::execute(ScriptResource* resource)
{
ASSERT(!m_willBeParserExecuted);
@@ -360,12 +356,13 @@ void ScriptLoader::execute(ScriptResource* resource)
executeScript(ScriptSourceCode(resource));
dispatchLoadEvent();
}
- resource->removeClient(this);
+
+ clearResource();
}
void ScriptLoader::cancel(Document* contextDocument)
{
- if (!m_resource)
+ if (!resource())
return;
finishLoading(contextDocument, FinishWithCancel);
}
@@ -375,11 +372,12 @@ void ScriptLoader::notifyFinished(Resource* resource)
// Resource possibly invokes this notifyFinished() more than
// once because ScriptLoader doesn't unsubscribe itself from
// Resource here and does it in execute() instead.
- // We use m_resource to check if this function is already called.
- ASSERT_UNUSED(resource, resource == m_resource);
- if (!m_resource)
+ // We use resource() to check if this function is already called.
+ ASSERT_UNUSED(resource, resource == this->resource());
+ if (!this->resource())
return;
+ RefPtr<Element> protect(m_element);
RefPtr<Document> elementDocument(m_element->document());
RefPtr<Document> contextDocument = elementDocument->contextDocument().get();
finishLoading(contextDocument.get(), resource->errorOccurred() ? FinishWithError : FinishSuccessfully);
@@ -387,29 +385,28 @@ void ScriptLoader::notifyFinished(Resource* resource)
void ScriptLoader::finishLoading(Document* contextDocument, ScriptLoader::FinishType type)
{
- if (!contextDocument)
- return;
+ if (!m_willBeParserExecuted && contextDocument)
+ notifyRunnerFinishLoading(contextDocument->scriptRunner(), type);
+ clearResource();
+}
+void ScriptLoader::notifyRunnerFinishLoading(ScriptRunner* runner, ScriptLoader::FinishType type)
+{
switch (type) {
case FinishWithCancel:
- if (!m_willBeParserExecuted)
- contextDocument->scriptRunner()->notifyScriptLoadError(this, m_willExecuteInOrder ? ScriptRunner::IN_ORDER_EXECUTION : ScriptRunner::ASYNC_EXECUTION);
- stopLoadRequest();
+ runner->notifyScriptLoadError(this, m_willExecuteInOrder ? ScriptRunner::IN_ORDER_EXECUTION : ScriptRunner::ASYNC_EXECUTION);
break;
case FinishWithError:
- ASSERT(!m_willBeParserExecuted);
dispatchErrorEvent();
- contextDocument->scriptRunner()->notifyScriptLoadError(this, m_willExecuteInOrder ? ScriptRunner::IN_ORDER_EXECUTION : ScriptRunner::ASYNC_EXECUTION);
- m_resource = 0;
+ runner->notifyScriptLoadError(this, m_willExecuteInOrder ? ScriptRunner::IN_ORDER_EXECUTION : ScriptRunner::ASYNC_EXECUTION);
break;
case FinishSuccessfully:
- ASSERT(!m_willBeParserExecuted);
- contextDocument->scriptRunner()->notifyScriptReady(this, m_willExecuteInOrder ? ScriptRunner::IN_ORDER_EXECUTION : ScriptRunner::ASYNC_EXECUTION);
- m_resource = 0;
+ runner->notifyScriptReady(this, m_willExecuteInOrder ? ScriptRunner::IN_ORDER_EXECUTION : ScriptRunner::ASYNC_EXECUTION);
break;
}
}
+
Nate Chapin 2014/05/07 18:13:10 Nit: Remove this line.
bool ScriptLoader::ignoresLoadRequest() const
{
return m_alreadyStarted || m_isExternalScript || m_parserInserted || !element() || !element()->inDocument();

Powered by Google App Engine
This is Rietveld 408576698