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

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

Issue 288673002: 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
« no previous file with comments | « Source/core/dom/ScriptLoader.h ('k') | Source/core/fetch/ResourceOwner.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/dom/ScriptLoader.cpp
diff --git a/Source/core/dom/ScriptLoader.cpp b/Source/core/dom/ScriptLoader.cpp
index 0b3ab8bf8fcc993c01c8f51619e28583f17470cb..6c8c4a3a72a7f99c8be1df7e48f200647f6d8df1 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,10 +163,10 @@ 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)
+ScriptPrep ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, LegacyTypeSupport supportLegacyTypes)
{
if (m_alreadyStarted)
- return false;
+ return ScriptPrep::failed();
ScriptLoaderClient* client = this->client();
@@ -185,13 +183,13 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, Legacy
// FIXME: HTML5 spec says we should check that all children are either comments or empty text nodes.
if (!client->hasSourceAttribute() && !m_element->firstChild())
- return false;
+ return ScriptPrep::failed();
if (!m_element->inDocument())
- return false;
+ return ScriptPrep::failed();
if (!isScriptTypeSupported(supportLegacyTypes))
- return false;
+ return ScriptPrep::failed();
if (wasParserInserted) {
m_parserInserted = true;
@@ -205,19 +203,24 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, Legacy
Document* contextDocument = elementDocument.contextDocument().get();
if (!contextDocument || !contextDocument->allowExecutingScripts(m_element))
- return false;
+ return ScriptPrep::failed();
if (!isScriptForEventSupported())
- return false;
+ return ScriptPrep::failed();
if (!client->charsetAttributeValue().isEmpty())
m_characterEncoding = client->charsetAttributeValue();
else
m_characterEncoding = elementDocument.charset();
+ ResourcePtr<ScriptResource> resource;
if (client->hasSourceAttribute()) {
- if (!fetchScript(client->sourceAttributeValue()))
- return false;
+ resource = fetchScript(client->sourceAttributeValue());
+ if (!resource) {
+ dispatchErrorEvent();
+ return ScriptPrep::failed();
+ }
+
}
if (client->hasSourceAttribute() && client->deferAttributeValue() && m_parserInserted && !client->asyncAttributeValue()) {
@@ -230,11 +233,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 +243,25 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, Legacy
executeScript(ScriptSourceCode(scriptContent(), scriptURL, position));
}
- return true;
+ // FIXME: This second "subscribing" parameter is a mess. We shouldn't have to need this.
+ if (resource)
+ setResource(resource, !m_willBeParserExecuted);
+
+ // 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().
+ return ScriptPrep(true, resource);
}
-bool ScriptLoader::fetchScript(const String& sourceUrl)
+ResourcePtr<ScriptResource> ScriptLoader::fetchScript(const String& sourceUrl)
{
ASSERT(m_element);
RefPtrWillBeRawPtr<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 +274,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 +313,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 +345,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 +355,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 +371,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 +384,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;
}
}
+
bool ScriptLoader::ignoresLoadRequest() const
{
return m_alreadyStarted || m_isExternalScript || m_parserInserted || !element() || !element()->inDocument();
« no previous file with comments | « Source/core/dom/ScriptLoader.h ('k') | Source/core/fetch/ResourceOwner.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698