void EventListenerManager::SetEventHandler(OnErrorEventHandlerNonNull* aHandler) { if (mIsMainThreadELM) { if (!aHandler) { RemoveEventHandler(nsGkAtoms::onerror, EmptyString()); return; } // Untrusted events are always permitted for non-chrome script // handlers. SetEventHandlerInternal(nsGkAtoms::onerror, EmptyString(), TypedEventHandler(aHandler), !nsContentUtils::IsCallerChrome()); } else { if (!aHandler) { RemoveEventHandler(nullptr, NS_LITERAL_STRING("error")); return; } // Untrusted events are always permitted. SetEventHandlerInternal(nullptr, NS_LITERAL_STRING("error"), TypedEventHandler(aHandler), true); } }
void EventListenerManager::SetEventHandler( OnBeforeUnloadEventHandlerNonNull* aHandler) { if (!aHandler) { RemoveEventHandler(nsGkAtoms::onbeforeunload, EmptyString()); return; } // Untrusted events are always permitted for non-chrome script // handlers. SetEventHandlerInternal(JS::NullPtr(), nsGkAtoms::onbeforeunload, EmptyString(), nsEventHandler(aHandler), !mIsMainThreadELM || !nsContentUtils::IsCallerChrome()); }
void EventListenerManager::SetEventHandler(nsIAtom* aEventName, const nsAString& aTypeString, EventHandlerNonNull* aHandler) { if (!aHandler) { RemoveEventHandler(aEventName, aTypeString); return; } // Untrusted events are always permitted for non-chrome script // handlers. SetEventHandlerInternal(aEventName, aTypeString, TypedEventHandler(aHandler), !mIsMainThreadELM || !nsContentUtils::IsCallerChrome()); }
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; }