Index: third_party/WebKit/Source/core/dom/ScriptLoader.cpp |
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp |
index d6606fab495121cb50c5c20e263bd6a2ce322ed4..e114b02eb24d497f611d106cb46b6ecef9718251 100644 |
--- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp |
+++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp |
@@ -37,6 +37,7 @@ |
#include "core/events/Event.h" |
#include "core/fetch/AccessControlStatus.h" |
#include "core/fetch/FetchRequest.h" |
+#include "core/fetch/MemoryCache.h" |
#include "core/fetch/ResourceFetcher.h" |
#include "core/fetch/ScriptResource.h" |
#include "core/frame/LocalFrame.h" |
@@ -51,6 +52,7 @@ |
#include "core/svg/SVGScriptElement.h" |
#include "platform/MIMETypeRegistry.h" |
#include "platform/weborigin/SecurityOrigin.h" |
+#include "public/platform/WebCachePolicy.h" |
#include "public/platform/WebFrameScheduler.h" |
#include "wtf/StdLibExtras.h" |
#include "wtf/text/StringBuilder.h" |
@@ -71,6 +73,7 @@ ScriptLoader::ScriptLoader(Element* element, bool parserInserted, bool alreadySt |
, m_forceAsync(!parserInserted) |
, m_createdDuringDocumentWrite(createdDuringDocumentWrite) |
, m_asyncExecType(ScriptRunner::None) |
+ , m_documentWriteIntervention(DocumentWriteIntervention::DocumentWriteInterventionNone) |
{ |
DCHECK(m_element); |
if (parserInserted && element->document().scriptableDocumentParser() && !element->document().isInDocumentWrite()) |
@@ -89,6 +92,12 @@ DEFINE_TRACE(ScriptLoader) |
ScriptResourceClient::trace(visitor); |
} |
+void ScriptLoader::setFetchDocWrittenScriptDeferIdle() |
+{ |
+ DCHECK(!m_createdDuringDocumentWrite); |
+ m_documentWriteIntervention = DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle; |
+} |
+ |
void ScriptLoader::didNotifySubtreeInsertionsToDocument() |
{ |
if (!m_parserInserted) |
@@ -238,10 +247,21 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, Legacy |
FetchRequest::DeferOption defer = FetchRequest::NoDefer; |
if (!m_parserInserted || client->asyncAttributeValue() || client->deferAttributeValue()) |
defer = FetchRequest::LazyLoad; |
+ if (m_documentWriteIntervention == DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) |
+ defer = FetchRequest::IdleLoad; |
if (!fetchScript(client->sourceAttributeValue(), defer)) |
return false; |
} |
+ // Since the asynchronous, low priority fetch for doc.written blocked |
+ // script is not for execution, return early from here. Watch for its |
+ // completion to be able to remove it from the memory cache. |
+ if (m_documentWriteIntervention == DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) { |
+ m_pendingScript = PendingScript::create(m_element, m_resource.get()); |
+ m_pendingScript->watchForLoad(this); |
+ return true; |
+ } |
+ |
if (client->hasSourceAttribute() && client->deferAttributeValue() && m_parserInserted && !client->asyncAttributeValue()) { |
m_willExecuteWhenDocumentFinishedParsing = true; |
m_willBeParserExecuted = true; |
@@ -317,16 +337,25 @@ bool ScriptLoader::fetchScript(const String& sourceUrl, FetchRequest::DeferOptio |
request.setIntegrityMetadata(metadataSet); |
} |
+ if (m_documentWriteIntervention == DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) { |
+ request.mutableResourceRequest().setHTTPHeaderField("Intervention", "<https://www.chromestatus.com/feature/5718547946799104>"); |
+ } |
+ |
m_resource = ScriptResource::fetch(request, elementDocument->fetcher()); |
m_isExternalScript = true; |
} |
- if (m_resource) |
- return true; |
+ if (!m_resource) { |
+ dispatchErrorEvent(); |
+ return false; |
+ } |
- dispatchErrorEvent(); |
- return false; |
+ if (m_createdDuringDocumentWrite && m_resource->resourceRequest().getCachePolicy() == WebCachePolicy::ReturnCacheDataDontLoad) { |
+ m_documentWriteIntervention = DocumentWriteIntervention::DoNotFetchDocWrittenScript; |
+ } |
+ |
+ return true; |
} |
bool isHTMLScriptLoader(Element* element) |
@@ -482,6 +511,17 @@ void ScriptLoader::execute() |
void ScriptLoader::notifyFinished(Resource* resource) |
{ |
DCHECK(!m_willBeParserExecuted); |
+ |
+ // We do not need this script in the memory cache. The primary goals of |
+ // sending this fetch request are to let the third party server know |
+ // about the document.write scripts intervention and populate the http |
+ // cache for subsequent uses. |
+ if (m_documentWriteIntervention == DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) { |
+ memoryCache()->remove(resource); |
+ m_pendingScript->stopWatchingForLoad(); |
+ return; |
+ } |
+ |
DCHECK(m_asyncExecType != ScriptRunner::None); |
Document* contextDocument = m_element->document().contextDocument(); |