bool ScriptElement::requestScript(const String& sourceUrl) { Ref<Document> originalDocument(m_element->document()); if (!m_element->dispatchBeforeLoadEvent(sourceUrl)) return false; if (!m_element->inDocument() || &m_element->document() != &originalDocument.get()) return false; if (!m_element->document().contentSecurityPolicy()->allowScriptNonce(m_element->fastGetAttribute(HTMLNames::nonceAttr), m_element->document().url(), m_startLineNumber, m_element->document().completeURL(sourceUrl))) return false; ASSERT(!m_cachedScript); if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) { CachedResourceRequest request(ResourceRequest(m_element->document().completeURL(sourceUrl))); String crossOriginMode = m_element->fastGetAttribute(HTMLNames::crossoriginAttr); if (!crossOriginMode.isNull()) { m_requestUsesAccessControl = true; StoredCredentials allowCredentials = equalIgnoringCase(crossOriginMode, "use-credentials") ? AllowStoredCredentials : DoNotAllowStoredCredentials; updateRequestForAccessControl(request.mutableResourceRequest(), m_element->document().securityOrigin(), allowCredentials); } request.setCharset(scriptCharset()); request.setInitiator(element()); m_cachedScript = m_element->document().cachedResourceLoader()->requestScript(request); m_isExternalScript = true; } if (m_cachedScript) { return true; } dispatchErrorEvent(); return false; }
void ScriptLoader::notifyFinished(Resource* resource) { ASSERT(!m_willBeParserExecuted); RefPtrWillBeRawPtr<Document> elementDocument(m_element->document()); RefPtrWillBeRawPtr<Document> contextDocument = elementDocument->contextDocument().get(); if (!contextDocument) return; ASSERT_UNUSED(resource, resource == m_resource); ScriptRunner::ExecutionType runOrder = m_willExecuteInOrder ? ScriptRunner::IN_ORDER_EXECUTION : ScriptRunner::ASYNC_EXECUTION; if (m_resource->errorOccurred()) { dispatchErrorEvent(); // The error handler can move the HTMLScriptElement to a new document. // In that case, we must notify the ScriptRunner of the new document, // not the ScriptRunner of the old docuemnt. contextDocument = m_element->document().contextDocument().get(); if (!contextDocument) return; contextDocument->scriptRunner()->notifyScriptLoadError(this, runOrder); return; } contextDocument->scriptRunner()->notifyScriptReady(this, runOrder); m_pendingScript.stopWatchingForLoad(this); }
// https://html.spec.whatwg.org/multipage/scripting.html#upgrades bool ScriptCustomElementDefinition::runConstructor(Element* element) { if (!m_scriptState->contextIsValid()) return false; ScriptState::Scope scope(m_scriptState.get()); v8::Isolate* isolate = m_scriptState->isolate(); // Step 5 says to rethrow the exception; but there is no one to // catch it. The side effect is to report the error. v8::TryCatch tryCatch(isolate); tryCatch.SetVerbose(true); Element* result = runConstructor(); // To report exception thrown from runConstructor() if (tryCatch.HasCaught()) return false; // To report InvalidStateError Exception, when the constructor returns some // different object if (result != element) { const String& message = "custom element constructors must call super() first and must " "not return a different object"; v8::Local<v8::Value> exception = V8ThrowException::createDOMException( m_scriptState->isolate(), InvalidStateError, message); dispatchErrorEvent(isolate, exception, constructor()); return false; } return true; }
void ScriptElement::notifyFinished(CachedResource* resource) { ASSERT(!m_willBeParserExecuted); // CachedResource possibly invokes this notifyFinished() more than // once because ScriptElement doesn't unsubscribe itself from // CachedResource here and does it in execute() instead. // We use m_cachedScript to check if this function is already called. ASSERT_UNUSED(resource, resource == m_cachedScript); if (!m_cachedScript) return; if (m_requestUsesAccessControl && !m_element->document()->securityOrigin()->canRequest(m_cachedScript->response().url()) && !m_cachedScript->passesAccessControlCheck(m_element->document()->securityOrigin())) { dispatchErrorEvent(); DEFINE_STATIC_LOCAL(String, consoleMessage, (ASCIILiteral("Cross-origin script load denied by Cross-Origin Resource Sharing policy."))); m_element->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, consoleMessage); return; } if (m_willExecuteInOrder) m_element->document()->scriptRunner()->notifyScriptReady(this, ScriptRunner::IN_ORDER_EXECUTION); else m_element->document()->scriptRunner()->notifyScriptReady(this, ScriptRunner::ASYNC_EXECUTION); m_cachedScript = 0; }
bool ScriptElement::requestScript(const String& sourceUrl) { RefPtr<Document> originalDocument = m_element->document(); if (!m_element->dispatchBeforeLoadEvent(sourceUrl)) return false; if (!m_element->inDocument() || m_element->document() != originalDocument) return false; ASSERT(!m_cachedScript); if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) { ResourceRequest request(m_element->document()->completeURL(sourceUrl)); m_cachedScript = m_element->document()->cachedResourceLoader()->requestScript(request, scriptCharset()); m_isExternalScript = true; } if (m_cachedScript) { #if PLATFORM(CHROMIUM) ASSERT(m_cachedScriptState == NeverSet); m_cachedScriptState = Set; #endif return true; } dispatchErrorEvent(); return false; }
bool ScriptElement::requestClassicScript(const String& sourceURL) { Ref<Document> originalDocument(m_element.document()); if (!m_element.dispatchBeforeLoadEvent(sourceURL)) return false; bool didEventListenerDisconnectThisElement = !m_element.inDocument() || &m_element.document() != originalDocument.ptr(); if (didEventListenerDisconnectThisElement) return false; ASSERT(!m_loadableScript); if (!stripLeadingAndTrailingHTMLSpaces(sourceURL).isEmpty()) { auto request = requestScriptWithCache(m_element.document().completeURL(sourceURL), m_element.attributeWithoutSynchronization(HTMLNames::nonceAttr)); if (request) { m_loadableScript = LoadableClassicScript::create(WTFMove(request)); m_isExternalScript = true; } } if (m_loadableScript) return true; callOnMainThread([this, element = Ref<Element>(m_element)] { dispatchErrorEvent(); }); return false; }
bool ScriptElement::requestScript(const String& sourceUrl) { RefPtr<Document> originalDocument = m_element->document(); if (!m_element->dispatchBeforeLoadEvent(sourceUrl)) return false; if (!m_element->inDocument() || m_element->document() != originalDocument) return false; ASSERT(!m_cachedScript); if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) { ResourceRequest request = ResourceRequest(m_element->document()->completeURL(sourceUrl)); String crossOriginMode = m_element->fastGetAttribute(HTMLNames::crossoriginAttr); if (!crossOriginMode.isNull()) { m_requestUsesAccessControl = true; StoredCredentials allowCredentials = equalIgnoringCase(crossOriginMode, "use-credentials") ? AllowStoredCredentials : DoNotAllowStoredCredentials; updateRequestForAccessControl(request, m_element->document()->securityOrigin(), allowCredentials); } m_cachedScript = m_element->document()->cachedResourceLoader()->requestScript(request, scriptCharset()); m_isExternalScript = true; } if (m_cachedScript) { return true; } dispatchErrorEvent(); return false; }
void ScriptLoader::notifyFinished(Resource* resource) { ASSERT(!m_willBeParserExecuted); RefPtrWillBeRawPtr<Document> elementDocument(m_element->document()); RefPtrWillBeRawPtr<Document> contextDocument = elementDocument->contextDocument().get(); if (!contextDocument) return; // 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) return; if (m_resource->errorOccurred()) { dispatchErrorEvent(); contextDocument->scriptRunner()->notifyScriptLoadError(this, m_willExecuteInOrder ? ScriptRunner::IN_ORDER_EXECUTION : ScriptRunner::ASYNC_EXECUTION); return; } if (m_willExecuteInOrder) contextDocument->scriptRunner()->notifyScriptReady(this, ScriptRunner::IN_ORDER_EXECUTION); else contextDocument->scriptRunner()->notifyScriptReady(this, ScriptRunner::ASYNC_EXECUTION); m_resource = 0; }
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(); if (!contextDocument) { detach(); return; } DCHECK_EQ(resource, m_resource); if (m_resource->errorOccurred()) { contextDocument->scriptRunner()->notifyScriptLoadError(this, m_asyncExecType); detach(); dispatchErrorEvent(); return; } contextDocument->scriptRunner()->notifyScriptReady(this, m_asyncExecType); m_pendingScript->stopWatchingForLoad(); }
bool ScriptLoader::fetchScript(const String& sourceUrl, FetchRequest::DeferOption defer) { ASSERT(m_element); RefPtrWillBeRawPtr<Document> elementDocument(m_element->document()); if (!m_element->inDocument() || m_element->document() != elementDocument) return false; ASSERT(!m_resource); if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) { FetchRequest request(ResourceRequest(elementDocument->completeURL(sourceUrl)), m_element->localName()); AtomicString crossOriginMode = m_element->fastGetAttribute(HTMLNames::crossoriginAttr); if (!crossOriginMode.isNull()) request.setCrossOriginAccessControl(elementDocument->securityOrigin(), crossOriginMode); request.setCharset(scriptCharset()); bool scriptPassesCSP = elementDocument->contentSecurityPolicy()->allowScriptWithNonce(m_element->fastGetAttribute(HTMLNames::nonceAttr)); if (scriptPassesCSP) request.setContentSecurityCheck(DoNotCheckContentSecurityPolicy); request.setDefer(defer); m_resource = elementDocument->fetcher()->fetchScript(request); m_isExternalScript = true; } if (m_resource) return true; dispatchErrorEvent(); return false; }
void ScriptLoader::execute() { DCHECK(!m_willBeParserExecuted); DCHECK(m_asyncExecType != ScriptRunner::None); DCHECK(m_pendingScript->resource()); bool errorOccurred = false; ScriptSourceCode source = m_pendingScript->getSource(KURL(), errorOccurred); m_pendingScript->dispose(); if (errorOccurred) { dispatchErrorEvent(); } else if (!m_resource->wasCanceled()) { if (executeScript(source)) dispatchLoadEvent(); else dispatchErrorEvent(); } m_resource = nullptr; }
void ScriptLoader::execute() { DCHECK(!m_willBeParserExecuted); DCHECK(m_pendingScript->resource()); bool errorOccurred = false; ScriptSourceCode source = m_pendingScript->getSource(KURL(), errorOccurred); Element* element = m_pendingScript->releaseElementAndClear(); ALLOW_UNUSED_LOCAL(element); if (errorOccurred) { dispatchErrorEvent(); } else if (!m_resource->wasCanceled()) { if (executeScript(source)) dispatchLoadEvent(); else dispatchErrorEvent(); } m_resource = nullptr; }
void ScriptLoader::execute() { ASSERT(!m_willBeParserExecuted); ASSERT(m_pendingScript.resource()); bool errorOccurred = false; ScriptSourceCode source = m_pendingScript.getSource(KURL(), errorOccurred); RefPtrWillBeRawPtr<Element> element = m_pendingScript.releaseElementAndClear(); ALLOW_UNUSED_LOCAL(element); if (errorOccurred) { dispatchErrorEvent(); } else if (!m_resource->wasCanceled()) { if (executeScript(source)) dispatchLoadEvent(); else dispatchErrorEvent(); } m_resource = 0; }
void XMLHttpRequest::networkError() { genericError(); dispatchErrorEvent(); if (!m_uploadComplete) { m_uploadComplete = true; if (m_upload) m_upload->dispatchErrorEvent(); } }
void XMLHttpRequest::networkError() { genericError(); dispatchErrorEvent(); if (!m_uploadComplete) { m_uploadComplete = true; if (m_upload && m_uploadEventsAllowed) m_upload->dispatchErrorEvent(); } internalAbort(); }
void Notification::taskTimerFired(Timer<Notification>* timer) { ASSERT(scriptExecutionContext()->isDocument()); ASSERT(static_cast<Document*>(scriptExecutionContext())->page()); ASSERT_UNUSED(timer, timer == m_taskTimer.get()); if (NotificationController::from(static_cast<Document*>(scriptExecutionContext())->page())->client()->checkPermission(scriptExecutionContext()) != NotificationClient::PermissionAllowed) { dispatchErrorEvent(); return; } show(); }
void ScriptLoader::execute(ScriptResource* resource) { ASSERT(!m_willBeParserExecuted); ASSERT(resource); if (resource->errorOccurred()) { dispatchErrorEvent(); } else if (!resource->wasCanceled()) { executeScript(ScriptSourceCode(resource)); dispatchLoadEvent(); } resource->removeClient(this); }
void ScriptElement::execute(CachedScript* cachedScript) { ASSERT(!m_willBeParserExecuted); ASSERT(cachedScript); if (cachedScript->errorOccurred()) dispatchErrorEvent(); else if (!cachedScript->wasCanceled()) { executeScript(ScriptSourceCode(cachedScript)); dispatchLoadEvent(); } cachedScript->removeClient(this); }
void Notification::prepareShow() { DCHECK_EQ(m_state, State::Loading); if (NotificationManager::from(getExecutionContext())->permissionStatus() != mojom::blink::PermissionStatus::GRANTED) { dispatchErrorEvent(); return; } m_loader = new NotificationResourcesLoader( WTF::bind(&Notification::didLoadResources, wrapWeakPersistent(this))); m_loader->start(getExecutionContext(), m_data); }
void ScriptElement::executeScriptAndDispatchEvent(LoadableScript& loadableScript) { if (Optional<LoadableScript::Error> error = loadableScript.wasErrored()) { if (Optional<LoadableScript::ConsoleMessage> message = error->consoleMessage) m_element.document().addConsoleMessage(message->source, message->level, message->message); dispatchErrorEvent(); } else if (!loadableScript.wasCanceled()) { ASSERT(!loadableScript.wasErrored()); loadableScript.execute(*this); dispatchLoadEvent(); } }
void ImageLoader::imageNotifyFinished(ImageResource* resource) { RESOURCE_LOADING_DVLOG(1) << "ImageLoader::imageNotifyFinished " << this << "; m_hasPendingLoadEvent=" << m_hasPendingLoadEvent; DCHECK(m_failedLoadURL.isEmpty()); DCHECK_EQ(resource, m_image.get()); m_imageComplete = true; // Update ImageAnimationPolicy for m_image. if (m_image) m_image->updateImageAnimationPolicy(); updateLayoutObject(); if (m_image && m_image->getImage() && m_image->getImage()->isSVGImage()) toSVGImage(m_image->getImage())->updateUseCounters(element()->document()); if (!m_hasPendingLoadEvent) return; if (resource->errorOccurred()) { loadEventSender().cancelEvent(this); m_hasPendingLoadEvent = false; if (resource->resourceError().isAccessCheck()) { crossSiteOrCSPViolationOccurred( AtomicString(resource->resourceError().failingURL())); } // The error event should not fire if the image data update is a result of // environment change. // https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element:the-img-element-55 if (!m_suppressErrorEvents) dispatchErrorEvent(); // Only consider updating the protection ref-count of the Element // immediately before returning from this function as doing so might result // in the destruction of this ImageLoader. updatedHasPendingEvent(); return; } if (resource->wasCanceled()) { m_hasPendingLoadEvent = false; // Only consider updating the protection ref-count of the Element // immediately before returning from this function as doing so might result // in the destruction of this ImageLoader. updatedHasPendingEvent(); return; } loadEventSender().dispatchEventSoon(this); }
void Notification::show() { ASSERT(m_state == NotificationStateIdle); if (!toDocument(executionContext())->page()) return; if (m_client->checkPermission(executionContext()) != NotificationClient::PermissionAllowed) { dispatchErrorEvent(); return; } if (m_client->show(this)) m_state = NotificationStateShowing; }
void Notification::show() { ASSERT(m_state == NotificationStateIdle); if (Notification::checkPermission(executionContext()) != WebNotificationPermissionAllowed) { dispatchErrorEvent(); return; } SecurityOrigin* origin = executionContext()->securityOrigin(); ASSERT(origin); notificationManager()->show(WebSecurityOrigin(origin), m_data, this); m_state = NotificationStateShowing; }
void Notification::show() { // prevent double-showing if (m_state == Idle) { if (!toDocument(scriptExecutionContext())->page()) return; if (NotificationController::from(toDocument(scriptExecutionContext())->page())->client()->checkPermission(scriptExecutionContext()) != NotificationClient::PermissionAllowed) { dispatchErrorEvent(); return; } if (m_notificationClient->show(this)) { m_state = Showing; setPendingActivity(this); } } }
void Worker::notifyFinished(CachedResource* resource) { ASSERT(resource == m_cachedScript.get()); if (m_cachedScript->errorOccurred()) dispatchErrorEvent(); else { String userAgent = document()->frame() ? document()->frame()->loader()->userAgent(m_scriptURL) : String(); RefPtr<WorkerThread> thread = WorkerThread::create(m_scriptURL, userAgent, m_cachedScript->script(), m_messagingProxy); m_messagingProxy->workerThreadCreated(thread); thread->start(); } m_cachedScript->removeClient(this); m_cachedScript = 0; unsetPendingActivity(this); }
bool ScriptLoader::fetchScript(const String& sourceUrl, FetchRequest::DeferOption defer) { DCHECK(m_element); Document* elementDocument = &(m_element->document()); if (!m_element->inShadowIncludingDocument() || m_element->document() != elementDocument) return false; DCHECK(!m_resource); if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) { FetchRequest request(ResourceRequest(elementDocument->completeURL(sourceUrl)), m_element->localName()); CrossOriginAttributeValue crossOrigin = crossOriginAttributeValue(m_element->fastGetAttribute(HTMLNames::crossoriginAttr)); if (crossOrigin != CrossOriginAttributeNotSet) request.setCrossOriginAccessControl(elementDocument->getSecurityOrigin(), crossOrigin); request.setCharset(scriptCharset()); // Skip fetch-related CSP checks if dynamically injected script is whitelisted and this script is not parser-inserted. bool scriptPassesCSPDynamic = (!isParserInserted() && elementDocument->contentSecurityPolicy()->allowDynamic()); request.setContentSecurityPolicyNonce(m_element->fastGetAttribute(HTMLNames::nonceAttr)); if (scriptPassesCSPDynamic) { UseCounter::count(elementDocument->frame(), UseCounter::ScriptPassesCSPDynamic); request.setContentSecurityCheck(DoNotCheckContentSecurityPolicy); } request.setDefer(defer); String integrityAttr = m_element->fastGetAttribute(HTMLNames::integrityAttr); if (!integrityAttr.isEmpty()) { IntegrityMetadataSet metadataSet; SubresourceIntegrity::parseIntegrityAttribute(integrityAttr, metadataSet, elementDocument); request.setIntegrityMetadata(metadataSet); } m_resource = ScriptResource::fetch(request, elementDocument->fetcher()); m_isExternalScript = true; } if (m_resource) return true; dispatchErrorEvent(); return false; }
void Notification::show() { // prevent double-showing if (m_state == Idle && m_notificationCenter->client()) { #if ENABLE(NOTIFICATIONS) if (!downcast<Document>(*scriptExecutionContext()).page()) return; if (NotificationController::from(downcast<Document>(*scriptExecutionContext()).page())->client()->checkPermission(scriptExecutionContext()) != NotificationClient::PermissionAllowed) { dispatchErrorEvent(); return; } #endif if (m_notificationCenter->client()->show(this)) { m_state = Showing; setPendingActivity(this); } } }
void ScriptLoader::finishLoading(Document* contextDocument, ScriptLoader::FinishType type) { ASSERT(!m_willBeParserExecuted); if (!contextDocument) return; if (type == FinishWithErrorOrCancel) { dispatchErrorEvent(); contextDocument->scriptRunner()->notifyScriptLoadError(this, m_willExecuteInOrder ? ScriptRunner::IN_ORDER_EXECUTION : ScriptRunner::ASYNC_EXECUTION); return; } if (m_willExecuteInOrder) contextDocument->scriptRunner()->notifyScriptReady(this, ScriptRunner::IN_ORDER_EXECUTION); else contextDocument->scriptRunner()->notifyScriptReady(this, ScriptRunner::ASYNC_EXECUTION); m_resource = 0; }
bool ScriptLoader::fetchScript(const String& sourceUrl, FetchRequest::DeferOption defer) { ASSERT(m_element); RefPtrWillBeRawPtr<Document> elementDocument(m_element->document()); if (!m_element->inDocument() || m_element->document() != elementDocument) return false; ASSERT(!m_resource); if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) { FetchRequest request(ResourceRequest(elementDocument->completeURL(sourceUrl)), m_element->localName()); CrossOriginAttributeValue crossOrigin = crossOriginAttributeValue(m_element->fastGetAttribute(HTMLNames::crossoriginAttr)); if (crossOrigin != CrossOriginAttributeNotSet) request.setCrossOriginAccessControl(elementDocument->securityOrigin(), crossOrigin); request.setCharset(scriptCharset()); bool scriptPassesCSP = elementDocument->contentSecurityPolicy()->allowScriptWithNonce(m_element->fastGetAttribute(HTMLNames::nonceAttr)); if (scriptPassesCSP) request.setContentSecurityCheck(DoNotCheckContentSecurityPolicy); request.setDefer(defer); String integrityAttr = m_element->fastGetAttribute(HTMLNames::integrityAttr); IntegrityMetadataSet metadataSet; if (!integrityAttr.isEmpty()) { SubresourceIntegrity::parseIntegrityAttribute(integrityAttr, metadataSet, elementDocument.get()); request.setIntegrityMetadata(metadataSet); } m_resource = ScriptResource::fetch(request, elementDocument->fetcher()); if (m_resource && !integrityAttr.isEmpty()) m_resource->setIntegrityMetadata(metadataSet); m_isExternalScript = true; } if (m_resource) return true; dispatchErrorEvent(); return false; }
void ScriptExecutionContext::reportException(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, JSC::Exception* exception, RefPtr<ScriptCallStack>&& callStack, CachedScript* cachedScript) { if (m_inDispatchErrorEvent) { if (!m_pendingExceptions) m_pendingExceptions = std::make_unique<Vector<std::unique_ptr<PendingException>>>(); m_pendingExceptions->append(std::make_unique<PendingException>(errorMessage, lineNumber, columnNumber, sourceURL, callStack.copyRef())); return; } // First report the original exception and only then all the nested ones. if (!dispatchErrorEvent(errorMessage, lineNumber, columnNumber, sourceURL, exception, cachedScript)) logExceptionToConsole(errorMessage, sourceURL, lineNumber, columnNumber, callStack.copyRef()); if (!m_pendingExceptions) return; std::unique_ptr<Vector<std::unique_ptr<PendingException>>> pendingExceptions = WTFMove(m_pendingExceptions); for (auto& exception : *pendingExceptions) logExceptionToConsole(exception->m_errorMessage, exception->m_sourceURL, exception->m_lineNumber, exception->m_columnNumber, exception->m_callStack.copyRef()); }