void NodeRemovedFromDocument(Node* node) { NodeList* childNodes = node->get_childNodes(); unsigned int length = childNodes->get_length(); for (unsigned int i = 0; i < length; ++i) { Node* child = childNodes->item(i); NodeRemovedFromDocument(child); } Document* ownerDocument = node->get_ownerDocument(); DocumentEvent* ownerDocumentEvent = dynamic_cast<DocumentEvent*>(ownerDocument); ASSERT(ownerDocumentEvent != nullptr); MutationEvent* event = dynamic_cast<MutationEvent*>(ownerDocumentEvent->createEvent(S("MutationEvent"))); event->initMutationEvent(S("DOMNodeRemovedFromDocument"), false, false, NULL/*relatedNode*/, nullptr, nullptr, nullptr, CHANGE_UNKNOWN); EventTarget* target = dynamic_cast<EventTarget*>(node); target->dispatchEvent(event); }
bool ScriptExecutionContext::dispatchErrorEvent(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, CachedScript* cachedScript) { EventTarget* target = errorEventTarget(); if (!target) return false; #if PLATFORM(IOS) if (target == target->toDOMWindow() && isDocument()) { Settings* settings = static_cast<Document*>(this)->settings(); if (settings && !settings->shouldDispatchJavaScriptWindowOnErrorEvents()) return false; } #endif String message = errorMessage; int line = lineNumber; int column = columnNumber; String sourceName = sourceURL; sanitizeScriptError(message, line, column, sourceName, cachedScript); ASSERT(!m_inDispatchErrorEvent); m_inDispatchErrorEvent = true; RefPtr<ErrorEvent> errorEvent = ErrorEvent::create(message, sourceName, line, column); target->dispatchEvent(errorEvent); m_inDispatchErrorEvent = false; return errorEvent->defaultPrevented(); }
ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, HTMLVideoElement* video, int sx, int sy, int sw, int sh, ExceptionState& exceptionState) { // This variant does not work in worker threads. ASSERT(eventTarget.toDOMWindow()); if (video->networkState() == HTMLMediaElement::NETWORK_EMPTY) { exceptionState.throwDOMException(InvalidStateError, "The provided element has not retrieved data."); return ScriptPromise(); } if (video->readyState() <= HTMLMediaElement::HAVE_METADATA) { exceptionState.throwDOMException(InvalidStateError, "The provided element's player has no current data."); return ScriptPromise(); } if (!sw || !sh) { exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width")); return ScriptPromise(); } if (!video->hasSingleSecurityOrigin()) { exceptionState.throwSecurityError("The source video contains image data from multiple origins."); return ScriptPromise(); } if (!video->webMediaPlayer()->didPassCORSAccessCheck() && eventTarget.toDOMWindow()->document()->securityOrigin()->taintsCanvas(video->currentSrc())) { exceptionState.throwSecurityError("Cross-origin access to the source video is denied."); return ScriptPromise(); } // FIXME: make ImageBitmap creation asynchronous crbug.com/258082 return fulfillImageBitmap(scriptState, ImageBitmap::create(video, IntRect(sx, sy, sw, sh))); }
void revoke() { ExecutionContext* executionContext = m_scriptState->getExecutionContext(); if (!executionContext) return; ScriptState::Scope scope(m_scriptState); v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate()); v8::Local<v8::Value> reason = m_exception.newLocal(m_scriptState->isolate()); // Either collected or https://crbug.com/450330 if (value.IsEmpty() || !value->IsPromise()) return; EventTarget* target = executionContext->errorEventTarget(); if (target && !executionContext->shouldSanitizeScriptError(m_resourceName, m_corsStatus)) { PromiseRejectionEventInit init; init.setPromise(ScriptPromise(m_scriptState, value)); init.setReason(ScriptValue(m_scriptState, reason)); PromiseRejectionEvent* event = PromiseRejectionEvent::create( m_scriptState, EventTypeNames::rejectionhandled, init); target->dispatchEvent(event); } if (m_shouldLogToConsole && m_promiseRejectionId) { V8PerIsolateData* data = V8PerIsolateData::from(m_scriptState->isolate()); if (data->threadDebugger()) data->threadDebugger()->promiseRejectionRevoked( m_scriptState->context(), m_promiseRejectionId); } }
void nsFormFillController::RemoveWindowListeners(nsPIDOMWindow *aWindow) { if (!aWindow) return; StopControllingInput(); nsCOMPtr<nsIDocument> doc = aWindow->GetDoc(); RemoveForDocument(doc); EventTarget* target = aWindow->GetChromeEventHandler(); if (!target) return; target->RemoveEventListener(NS_LITERAL_STRING("focus"), this, true); target->RemoveEventListener(NS_LITERAL_STRING("blur"), this, true); target->RemoveEventListener(NS_LITERAL_STRING("pagehide"), this, true); target->RemoveEventListener(NS_LITERAL_STRING("mousedown"), this, true); target->RemoveEventListener(NS_LITERAL_STRING("input"), this, true); target->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, true); target->RemoveEventListener(NS_LITERAL_STRING("compositionstart"), this, true); target->RemoveEventListener(NS_LITERAL_STRING("compositionend"), this, true); target->RemoveEventListener(NS_LITERAL_STRING("contextmenu"), this, true); }
void nsFormFillController::AddWindowListeners(nsPIDOMWindow *aWindow) { if (!aWindow) return; EventTarget* target = aWindow->GetChromeEventHandler(); if (!target) return; target->AddEventListener(NS_LITERAL_STRING("focus"), this, true, false); target->AddEventListener(NS_LITERAL_STRING("blur"), this, true, false); target->AddEventListener(NS_LITERAL_STRING("pagehide"), this, true, false); target->AddEventListener(NS_LITERAL_STRING("mousedown"), this, true, false); target->AddEventListener(NS_LITERAL_STRING("input"), this, true, false); target->AddEventListener(NS_LITERAL_STRING("keypress"), this, true, false); target->AddEventListener(NS_LITERAL_STRING("compositionstart"), this, true, false); target->AddEventListener(NS_LITERAL_STRING("compositionend"), this, true, false); target->AddEventListener(NS_LITERAL_STRING("contextmenu"), this, true, false); // Note that any additional listeners added should ensure that they ignore // untrusted events, which might be sent by content that's up to no good. }
void ScriptedAnimationController::dispatchEvents(const AtomicString& eventInterfaceFilter) { WillBeHeapVector<RefPtrWillBeMember<Event> > events; if (eventInterfaceFilter.isEmpty()) { events.swap(m_eventQueue); m_perFrameEvents.clear(); } else { WillBeHeapVector<RefPtrWillBeMember<Event> > remaining; for (auto& event : m_eventQueue) { if (event && event->interfaceName() == eventInterfaceFilter) { m_perFrameEvents.remove(eventTargetKey(event.get())); events.append(event.release()); } else { remaining.append(event.release()); } } remaining.swap(m_eventQueue); } for (size_t i = 0; i < events.size(); ++i) { EventTarget* eventTarget = events[i]->target(); // FIXME: we should figure out how to make dispatchEvent properly virtual to avoid // special casting window. // FIXME: We should not fire events for nodes that are no longer in the tree. if (LocalDOMWindow* window = eventTarget->toDOMWindow()) window->dispatchEvent(events[i], nullptr); else eventTarget->dispatchEvent(events[i]); InspectorInstrumentation::didRemoveEvent(eventTarget, events[i].get()); } }
void revoke() { ExecutionContext* executionContext = m_scriptState->executionContext(); if (!executionContext) return; ScriptState::Scope scope(m_scriptState); v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate()); v8::Local<v8::Value> reason = m_exception.newLocal(m_scriptState->isolate()); // Either collected or https://crbug.com/450330 if (value.IsEmpty() || !value->IsPromise()) return; EventTarget* target = executionContext->errorEventTarget(); if (RuntimeEnabledFeatures::promiseRejectionEventEnabled() && target && !executionContext->shouldSanitizeScriptError(m_resourceName, m_corsStatus)) { PromiseRejectionEventInit init; init.setPromise(ScriptPromise(m_scriptState, value)); init.setReason(ScriptValue(m_scriptState, reason)); RefPtrWillBeRawPtr<PromiseRejectionEvent> event = PromiseRejectionEvent::create(m_scriptState, EventTypeNames::rejectionhandled, init); target->dispatchEvent(event); } if (m_shouldLogToConsole) { RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(JSMessageSource, RevokedErrorMessageLevel, "Handler added to rejected promise"); consoleMessage->setRelatedMessageId(m_consoleMessageId); executionContext->addConsoleMessage(consoleMessage.release()); } }
bool ScriptExecutionContext::dispatchErrorEvent(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, JSC::Exception* exception, CachedScript* cachedScript) { EventTarget* target = errorEventTarget(); if (!target) return false; #if PLATFORM(IOS) if (target->toDOMWindow() && is<Document>(*this)) { Settings* settings = downcast<Document>(*this).settings(); if (settings && !settings->shouldDispatchJavaScriptWindowOnErrorEvents()) return false; } #endif String message = errorMessage; int line = lineNumber; int column = columnNumber; String sourceName = sourceURL; Deprecated::ScriptValue error = exception && exception->value() ? Deprecated::ScriptValue(vm(), exception->value()) : Deprecated::ScriptValue(); sanitizeScriptError(message, line, column, sourceName, error, cachedScript); ASSERT(!m_inDispatchErrorEvent); m_inDispatchErrorEvent = true; Ref<ErrorEvent> errorEvent = ErrorEvent::create(message, sourceName, line, column, error); target->dispatchEvent(errorEvent); m_inDispatchErrorEvent = false; return errorEvent->defaultPrevented(); }
void EventListenerInfo::getEventListeners(EventTarget* target, WillBeHeapVector<EventListenerInfo>& eventInformation, bool includeAncestors) { // The Node's Ancestors including self. WillBeHeapVector<RawPtrWillBeMember<EventTarget>> ancestors; ancestors.append(target); if (includeAncestors) { Node* node = target->toNode(); for (ContainerNode* ancestor = node ? node->parentOrShadowHostNode() : nullptr; ancestor; ancestor = ancestor->parentOrShadowHostNode()) ancestors.append(ancestor); } // Nodes and their Listeners for the concerned event types (order is top to bottom) for (size_t i = ancestors.size(); i; --i) { EventTarget* ancestor = ancestors[i - 1]; Vector<AtomicString> eventTypes = ancestor->eventTypes(); for (size_t j = 0; j < eventTypes.size(); ++j) { AtomicString& type = eventTypes[j]; EventListenerVector* listeners = ancestor->getEventListeners(type); if (!listeners) continue; EventListenerVector filteredListeners; filteredListeners.reserveCapacity(listeners->size()); for (size_t k = 0; k < listeners->size(); ++k) { if (listeners->at(k).listener->type() == EventListener::JSEventListenerType) filteredListeners.append(listeners->at(k)); } if (!filteredListeners.isEmpty()) eventInformation.append(EventListenerInfo(ancestor, type, filteredListeners)); } } }
void ReplayController::willDispatchEvent(const Event& event, Frame* frame) { EventTarget* target = event.target(); if (!target && !frame) return; Document* document = frame ? frame->document() : nullptr; // Fetch the document from the event target, because the target could be detached. if (Node* node = target->toNode()) document = node->inDocument() ? &node->document() : node->ownerDocument(); else if (DOMWindow* window = target->toDOMWindow()) document = window->document(); ASSERT(document); InputCursor& cursor = document->inputCursor(); #if !LOG_DISABLED bool eventIsUnrelated = !cursor.isCapturing() && !cursor.isReplaying(); logDispatchedDOMEvent(event, eventIsUnrelated); #else UNUSED_PARAM(cursor); #endif #if ENABLE_AGGRESSIVE_DETERMINISM_CHECKS // To ensure deterministic JS execution, all DOM events must be dispatched deterministically. // If these assertions fail, then this DOM event is being dispatched by a nondeterministic EventLoop // cycle, and may cause program execution to diverge if any JS code runs because of the DOM event. if (cursor.isCapturing() || cursor.isReplaying()) ASSERT(cursor.withinEventLoopInputExtent()); else if (cursor.isReplaying()) ASSERT(dispatcher().isDispatching()); #endif }
void nsFormFillController::RemoveWindowListeners(nsIDOMWindow *aWindow) { if (!aWindow) return; StopControllingInput(); nsCOMPtr<nsIDOMDocument> domDoc; aWindow->GetDocument(getter_AddRefs(domDoc)); nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc); PwmgrInputsEnumData ed(this, doc); mPwmgrInputs.Enumerate(RemoveForDocumentEnumerator, &ed); nsCOMPtr<nsPIDOMWindow> privateDOMWindow(do_QueryInterface(aWindow)); EventTarget* target = nullptr; if (privateDOMWindow) target = privateDOMWindow->GetChromeEventHandler(); if (!target) return; target->RemoveEventListener(NS_LITERAL_STRING("focus"), this, true); target->RemoveEventListener(NS_LITERAL_STRING("blur"), this, true); target->RemoveEventListener(NS_LITERAL_STRING("pagehide"), this, true); target->RemoveEventListener(NS_LITERAL_STRING("mousedown"), this, true); target->RemoveEventListener(NS_LITERAL_STRING("input"), this, true); target->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, true); target->RemoveEventListener(NS_LITERAL_STRING("compositionstart"), this, true); target->RemoveEventListener(NS_LITERAL_STRING("compositionend"), this, true); target->RemoveEventListener(NS_LITERAL_STRING("contextmenu"), this, true); }
nsresult HTMLEditor::EndMoving() { if (mPositioningShadow) { nsCOMPtr<nsIPresShell> ps = GetPresShell(); NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED); DeleteRefToAnonymousNode(std::move(mPositioningShadow), ps); mPositioningShadow = nullptr; } EventTarget* eventTarget = GetDOMEventTarget(); if (eventTarget && mMouseMotionListenerP) { EventListenerManager* eventListenerManager = eventTarget->GetOrCreateListenerManager(); eventListenerManager->RemoveEventListenerByType( mMouseMotionListenerP, NS_LITERAL_STRING("mousemove"), TrustedEventsAtSystemGroupBubble()); } mMouseMotionListenerP = nullptr; mGrabberClicked = false; mIsMoving = false; RefPtr<Selection> selection = GetSelection(); if (!selection) { return NS_ERROR_NOT_INITIALIZED; } nsresult rv = RefereshEditingUI(*selection); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } return NS_OK; }
ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, HTMLImageElement* image, int sx, int sy, int sw, int sh, ExceptionState& exceptionState) { // This variant does not work in worker threads. ASSERT(eventTarget.toDOMWindow()); if (!image->cachedImage()) { exceptionState.throwDOMException(InvalidStateError, "No image can be retrieved from the provided element."); return ScriptPromise(); } if (image->cachedImage()->image()->isSVGImage()) { exceptionState.throwDOMException(InvalidStateError, "The image element contains an SVG image, which is unsupported."); return ScriptPromise(); } if (!sw || !sh) { exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width")); return ScriptPromise(); } if (!image->cachedImage()->image()->currentFrameHasSingleSecurityOrigin()) { exceptionState.throwSecurityError("The source image contains image data from multiple origins."); return ScriptPromise(); } Document* document = eventTarget.toDOMWindow()->document(); if (!image->cachedImage()->passesAccessControlCheck(document->securityOrigin()) && document->securityOrigin()->taintsCanvas(image->src())) { exceptionState.throwSecurityError("Cross-origin access to the source image is denied."); return ScriptPromise(); } // FIXME: make ImageBitmap creation asynchronous crbug.com/258082 return fulfillImageBitmap(scriptState, ImageBitmap::create(image, IntRect(sx, sy, sw, sh))); }
bool ScriptExecutionContext::dispatchErrorEvent(const String& errorMessage, int lineNumber, const String& sourceURL) { EventTarget* target = errorEventTarget(); if (!target) return false; String message; int line; String sourceName; KURL targetUrl = completeURL(sourceURL); if (securityOrigin()->canRequest(targetUrl)) { message = errorMessage; line = lineNumber; sourceName = sourceURL; } else { message = "Script error."; sourceName = String(); line = 0; } ASSERT(!m_inDispatchErrorEvent); m_inDispatchErrorEvent = true; RefPtr<ErrorEvent> errorEvent = ErrorEvent::create(message, sourceName, line); target->dispatchEvent(errorEvent); m_inDispatchErrorEvent = false; return errorEvent->defaultPrevented(); }
void EventQueue::dispatchEvent(PassRefPtr<Event> event) { EventTarget* eventTarget = event->target(); if (eventTarget->toDOMWindow()) eventTarget->toDOMWindow()->dispatchEvent(event, 0); else eventTarget->dispatchEvent(event); }
bool MediaControls::containsRelatedTarget(Event* event) { if (!event->isMouseEvent()) return false; EventTarget* relatedTarget = toMouseEvent(event)->relatedTarget(); if (!relatedTarget) return false; return contains(relatedTarget->toNode()); }
void DOMWindowEventQueue::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event) { EventTarget* eventTarget = event->target(); if (eventTarget->toDOMWindow()) eventTarget->toDOMWindow()->dispatchEvent(event, nullptr); else eventTarget->dispatchEvent(event); }
static inline bool shouldStopAtShadowRoot(Event& event, ShadowRoot& shadowRoot, EventTarget& target) { // WebKit never allowed selectstart event to cross the the shadow DOM boundary. // Changing this breaks existing sites. // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details. const AtomicString eventType = event.type(); return target.toNode() && target.toNode()->shadowHost() == shadowRoot.host() && event.scoped(); }
void DOMWindowEventQueue::dispatchEvent(Event* event) { EventTarget* eventTarget = event->target(); InspectorInstrumentation::AsyncTask asyncTask( eventTarget->getExecutionContext(), event); if (LocalDOMWindow* window = eventTarget->toLocalDOMWindow()) window->dispatchEvent(event, nullptr); else eventTarget->dispatchEvent(event); }
bool MediaControlRootElement::containsRelatedTarget(Event* event) { if (!event->isMouseEvent()) return false; EventTarget* relatedTarget = static_cast<MouseEvent*>(event)->relatedTarget(); if (!relatedTarget) return false; return contains(relatedTarget->toNode()); }
void EventDispatcher::_RemoveTemporaryListeners() { for (int32 i = fTargets.CountItems(); i-- > 0;) { EventTarget* target = fTargets.ItemAt(i); target->RemoveTemporaryListeners(); } }
void EventDispatcher::RemoveTemporaryListener(EventTarget& target, int32 token) { BAutolock _(this); ETRACE(("events: remove temporary listener token %ld\n", token)); if (target.RemoveTemporaryListener(token) && target.IsEmpty()) fTargets.RemoveItem(&target); }
bool MediaControls::containsRelatedTarget(Event* event) { if (!is<MouseEvent>(*event)) return false; EventTarget* relatedTarget = downcast<MouseEvent>(*event).relatedTarget(); if (!relatedTarget) return false; return contains(relatedTarget->toNode()); }
Node* MouseEvent::fromElement() const { // MSIE extension - "object from which activation or the mouse pointer is exiting during the event" (huh?) if (type() != eventNames().mouseoutEvent && type() != eventNames().mouseleaveEvent) { EventTarget* relatedTarget = this->relatedTarget(); return relatedTarget ? relatedTarget->toNode() : nullptr; } return target() ? target()->toNode() : nullptr; }
Node* MouseEvent::toElement() const { // MSIE extension - "the object toward which the user is moving the mouse pointer" if (type() == eventNames().mouseoutEvent || type() == eventNames().mouseleaveEvent) { EventTarget* relatedTarget = this->relatedTarget(); return relatedTarget ? relatedTarget->toNode() : nullptr; } return target() ? target()->toNode() : nullptr; }
JSValue* jsEventTargetDispatchEvent(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) { Node* eventNode = 0; EventTarget* eventTarget = 0; if (!retrieveEventTargetAndCorrespondingNode(exec, thisValue, eventNode, eventTarget)) return throwError(exec, TypeError); DOMExceptionTranslator exception(exec); return jsBoolean(eventTarget->dispatchEvent(toEvent(args.at(exec, 0)), exception)); }
void GObjectEventListener::gobjectDestroyed() { ASSERT(m_coreTarget); // We must set m_coreTarget to null, because removeEventListener // may call the destructor as a side effect and we must be in the // proper state to prevent g_object_weak_unref. EventTarget* target = m_coreTarget; m_coreTarget = 0; target->removeEventListener(m_domEventName.data(), this, m_capture); }
void report() { if (!m_scriptState->contextIsValid()) return; // If execution termination has been triggered, quietly bail out. if (v8::V8::IsExecutionTerminating(m_scriptState->isolate())) return; ExecutionContext* executionContext = m_scriptState->executionContext(); if (!executionContext) return; ScriptState::Scope scope(m_scriptState); v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate()); v8::Local<v8::Value> reason = m_exception.newLocal(m_scriptState->isolate()); // Either collected or https://crbug.com/450330 if (value.IsEmpty() || !value->IsPromise()) return; ASSERT(!hasHandler()); EventTarget* target = executionContext->errorEventTarget(); if (RuntimeEnabledFeatures::promiseRejectionEventEnabled() && target && !executionContext->shouldSanitizeScriptError(m_resourceName, m_corsStatus)) { PromiseRejectionEventInit init; init.setPromise(ScriptPromise(m_scriptState, value)); init.setReason(ScriptValue(m_scriptState, reason)); init.setCancelable(true); RefPtrWillBeRawPtr<PromiseRejectionEvent> event = PromiseRejectionEvent::create(m_scriptState, EventTypeNames::unhandledrejection, init); // Log to console if event was not preventDefault()'ed. m_shouldLogToConsole = target->dispatchEvent(event); } if (m_shouldLogToConsole) { const String errorMessage = "Uncaught (in promise)"; Vector<ScriptValue> args; args.append(ScriptValue(m_scriptState, v8String(m_scriptState->isolate(), errorMessage))); args.append(ScriptValue(m_scriptState, reason)); RefPtrWillBeRawPtr<ScriptArguments> arguments = ScriptArguments::create(m_scriptState, args); String embedderErrorMessage = m_errorMessage; if (embedderErrorMessage.isEmpty()) embedderErrorMessage = errorMessage; else if (embedderErrorMessage.startsWith("Uncaught ")) embedderErrorMessage.insert(" (in promise)", 8); RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, embedderErrorMessage, m_resourceName, m_lineNumber, m_columnNumber); consoleMessage->setScriptArguments(arguments); consoleMessage->setCallStack(m_callStack); consoleMessage->setScriptId(m_scriptId); m_consoleMessageId = consoleMessage->assignMessageId(); executionContext->addConsoleMessage(consoleMessage.release()); } m_callStack.clear(); }
void GenericEventQueue::cancelAllEvents() { m_timer.stop(); for (const auto& pendingEvent : m_pendingEvents) { Event* event = pendingEvent.get(); TRACE_EVENT_ASYNC_END2("event", "GenericEventQueue:enqueueEvent", event, "type", event->type().ascii(), "status", "cancelled"); EventTarget* target = event->target() ? event->target() : m_owner.get(); InspectorInstrumentation::asyncTaskCanceled(target->getExecutionContext(), event); } m_pendingEvents.clear(); }