const TypedEventHandler* EventListenerManager::GetTypedEventHandler(nsIAtom* aEventName, const nsAString& aTypeString) { uint32_t eventType = nsContentUtils::GetEventId(aEventName); Listener* listener = FindEventHandler(eventType, aEventName, aTypeString); if (!listener) { return nullptr; } JSEventHandler* jsEventHandler = listener->GetJSEventHandler(); if (listener->mHandlerIsString) { CompileEventHandlerInternal(listener, nullptr, nullptr); } const TypedEventHandler& typedHandler = jsEventHandler->GetTypedEventHandler(); return typedHandler.HasEventHandler() ? &typedHandler : nullptr; }
nsresult EventListenerManager::HandleEventSubType(Listener* aListener, nsIDOMEvent* aDOMEvent, EventTarget* aCurrentTarget) { nsresult result = NS_OK; EventListenerHolder listenerHolder(aListener->mListener); // strong ref // If this is a script handler and we haven't yet // compiled the event handler itself if ((aListener->mListenerType == Listener::eJSEventListener) && aListener->mHandlerIsString) { result = CompileEventHandlerInternal(aListener, nullptr, nullptr); aListener = nullptr; } if (NS_SUCCEEDED(result)) { if (mIsMainThreadELM) { nsContentUtils::EnterMicroTask(); } // nsIDOMEvent::currentTarget is set in EventDispatcher. if (listenerHolder.HasWebIDLCallback()) { ErrorResult rv; listenerHolder.GetWebIDLCallback()-> HandleEvent(aCurrentTarget, *(aDOMEvent->InternalDOMEvent()), rv); result = rv.ErrorCode(); } else { result = listenerHolder.GetXPCOMCallback()->HandleEvent(aDOMEvent); } if (mIsMainThreadELM) { nsContentUtils::LeaveMicroTask(); } } return result; }
nsresult EventListenerManager::SetEventHandler(nsIAtom* aName, const nsAString& aBody, uint32_t aLanguage, bool aDeferCompilation, bool aPermitUntrustedEvents, Element* aElement) { NS_PRECONDITION(aLanguage != nsIProgrammingLanguage::UNKNOWN, "Must know the language for the script event listener"); // |aPermitUntrustedEvents| is set to False for chrome - events // *generated* from an unknown source are not allowed. // However, for script languages with no 'sandbox', we want to reject // such scripts based on the source of their code, not just the source // of the event. if (aPermitUntrustedEvents && aLanguage != nsIProgrammingLanguage::JAVASCRIPT) { NS_WARNING("Discarding non-JS event listener from untrusted source"); return NS_ERROR_FAILURE; } nsCOMPtr<nsIDocument> doc; nsCOMPtr<nsIScriptGlobalObject> global = GetScriptGlobalAndDocument(getter_AddRefs(doc)); if (!global) { // This can happen; for example this document might have been // loaded as data. return NS_OK; } #ifdef DEBUG nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(global); if (win) { MOZ_ASSERT(win->IsInnerWindow(), "We should not have an outer window here!"); } #endif nsresult rv = NS_OK; // return early preventing the event listener from being added // 'doc' is fetched above if (doc) { // Don't allow adding an event listener if the document is sandboxed // without 'allow-scripts'. if (doc->GetSandboxFlags() & SANDBOXED_SCRIPTS) { return NS_ERROR_DOM_SECURITY_ERR; } nsCOMPtr<nsIContentSecurityPolicy> csp; rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp)); NS_ENSURE_SUCCESS(rv, rv); if (csp) { bool inlineOK = true; bool reportViolations = false; rv = csp->GetAllowsInlineScript(&reportViolations, &inlineOK); NS_ENSURE_SUCCESS(rv, rv); if (reportViolations) { // gather information to log with violation report nsIURI* uri = doc->GetDocumentURI(); nsAutoCString asciiSpec; if (uri) uri->GetAsciiSpec(asciiSpec); nsAutoString scriptSample, attr, tagName(NS_LITERAL_STRING("UNKNOWN")); aName->ToString(attr); nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mTarget)); if (domNode) domNode->GetNodeName(tagName); // build a "script sample" based on what we know about this element scriptSample.Assign(attr); scriptSample.AppendLiteral(" attribute on "); scriptSample.Append(tagName); scriptSample.AppendLiteral(" element"); csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_INLINE_SCRIPT, NS_ConvertUTF8toUTF16(asciiSpec), scriptSample, 0, EmptyString(), EmptyString()); } // return early if CSP wants us to block inline scripts if (!inlineOK) { return NS_OK; } } } // This might be the first reference to this language in the global // We must init the language before we attempt to fetch its context. if (NS_FAILED(global->EnsureScriptEnvironment())) { NS_WARNING("Failed to setup script environment for this language"); // but fall through and let the inevitable failure below handle it. } nsIScriptContext* context = global->GetScriptContext(); NS_ENSURE_TRUE(context, NS_ERROR_FAILURE); NS_ENSURE_STATE(global->GetGlobalJSObject()); JSAutoRequest ar(context->GetNativeContext()); JS::Rooted<JSObject*> scope(context->GetNativeContext(), global->GetGlobalJSObject()); Listener* listener = SetEventHandlerInternal(scope, aName, EmptyString(), nsEventHandler(), aPermitUntrustedEvents); if (!aDeferCompilation) { return CompileEventHandlerInternal(listener, &aBody, aElement); } return NS_OK; }