diff options
Diffstat (limited to 'dom/html')
34 files changed, 341 insertions, 201 deletions
diff --git a/dom/html/HTMLAnchorElement.cpp b/dom/html/HTMLAnchorElement.cpp index fffe8d9545..8c1689fe7d 100644 --- a/dom/html/HTMLAnchorElement.cpp +++ b/dom/html/HTMLAnchorElement.cpp @@ -14,7 +14,7 @@ #include "nsCOMPtr.h" #include "nsContentUtils.h" #include "nsGkAtoms.h" -#include "nsAttrValueOrString.h" +#include "mozilla/FocusModel.h" #include "mozilla/dom/Document.h" #include "nsPresContext.h" #include "nsIURI.h" @@ -68,10 +68,7 @@ nsresult HTMLAnchorElement::BindToTree(BindContext& aContext, Link::BindToTree(aContext); // Prefetch links - if (IsInComposedDoc()) { - TryDNSPrefetch(*this); - } - + MaybeTryDNSPrefetch(); return rv; } @@ -89,10 +86,10 @@ void HTMLAnchorElement::UnbindFromTree(UnbindContext& aContext) { Link::UnbindFromTree(); } -bool HTMLAnchorElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, +bool HTMLAnchorElement::IsHTMLFocusable(IsFocusableFlags aFlags, + bool* aIsFocusable, int32_t* aTabIndex) { - if (nsGenericHTMLElement::IsHTMLFocusable(aWithMouse, aIsFocusable, - aTabIndex)) { + if (nsGenericHTMLElement::IsHTMLFocusable(aFlags, aIsFocusable, aTabIndex)) { return true; } @@ -122,7 +119,7 @@ bool HTMLAnchorElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, } } - if ((sTabFocusModel & eTabFocus_linksMask) == 0) { + if (!FocusModel::IsTabFocusable(TabFocusableType::Links)) { *aTabIndex = -1; } *aIsFocusable = true; @@ -194,8 +191,8 @@ void HTMLAnchorElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, if (aNamespaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::href) { Link::ResetLinkState(aNotify, !!aValue); - if (aValue && IsInComposedDoc()) { - TryDNSPrefetch(*this); + if (aValue) { + MaybeTryDNSPrefetch(); } } } @@ -210,4 +207,22 @@ void HTMLAnchorElement::AddSizeOfExcludingThis(nsWindowSizes& aSizes, *aNodeSize += Link::SizeOfExcludingThis(aSizes.mState); } +void HTMLAnchorElement::MaybeTryDNSPrefetch() { + if (IsInComposedDoc()) { + nsIURI* docURI = OwnerDoc()->GetDocumentURI(); + if (!docURI) { + return; + } + + bool docIsHttps = docURI->SchemeIs("https"); + if ((docIsHttps && + StaticPrefs::dom_prefetch_dns_for_anchor_https_document()) || + (!docIsHttps && + StaticPrefs::dom_prefetch_dns_for_anchor_http_document())) { + TryDNSPrefetch( + *this, HTMLDNSPrefetch::PrefetchSource::AnchorSpeculativePrefetch); + } + } +} + } // namespace mozilla::dom diff --git a/dom/html/HTMLAnchorElement.h b/dom/html/HTMLAnchorElement.h index 88669549e3..f7f808de05 100644 --- a/dom/html/HTMLAnchorElement.h +++ b/dom/html/HTMLAnchorElement.h @@ -48,7 +48,7 @@ class HTMLAnchorElement final : public nsGenericHTMLElement, nsresult BindToTree(BindContext&, nsINode& aParent) override; void UnbindFromTree(UnbindContext&) override; - bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable, int32_t* aTabIndex) override; void GetEventTargetParent(EventChainPreVisitor& aVisitor) override; @@ -189,6 +189,8 @@ class HTMLAnchorElement final : public nsGenericHTMLElement, protected: virtual ~HTMLAnchorElement(); + void MaybeTryDNSPrefetch(); + JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override; RefPtr<nsDOMTokenList> mRelList; }; diff --git a/dom/html/HTMLButtonElement.cpp b/dom/html/HTMLButtonElement.cpp index 0d9cc921ad..7d7fa7f548 100644 --- a/dom/html/HTMLButtonElement.cpp +++ b/dom/html/HTMLButtonElement.cpp @@ -12,13 +12,13 @@ #include "nsAttrValueInlines.h" #include "nsIContentInlines.h" #include "nsGkAtoms.h" -#include "nsStyleConsts.h" #include "nsPresContext.h" #include "nsIFormControl.h" #include "nsIFrame.h" #include "nsIFormControlFrame.h" #include "mozilla/dom/Document.h" #include "mozilla/ContentEvents.h" +#include "mozilla/FocusModel.h" #include "mozilla/EventDispatcher.h" #include "mozilla/EventStateManager.h" #include "mozilla/MouseEvents.h" @@ -113,15 +113,14 @@ void HTMLButtonElement::GetType(nsAString& aType) { int32_t HTMLButtonElement::TabIndexDefault() { return 0; } -bool HTMLButtonElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, +bool HTMLButtonElement::IsHTMLFocusable(IsFocusableFlags aFlags, + bool* aIsFocusable, int32_t* aTabIndex) { if (nsGenericHTMLFormControlElementWithState::IsHTMLFocusable( - aWithMouse, aIsFocusable, aTabIndex)) { + aFlags, aIsFocusable, aTabIndex)) { return true; } - - *aIsFocusable = IsFormControlDefaultFocusable(aWithMouse) && !IsDisabled(); - + *aIsFocusable = IsFormControlDefaultFocusable(aFlags) && !IsDisabled(); return false; } diff --git a/dom/html/HTMLButtonElement.h b/dom/html/HTMLButtonElement.h index b1a5c53f64..d4bfc3649d 100644 --- a/dom/html/HTMLButtonElement.h +++ b/dom/html/HTMLButtonElement.h @@ -87,7 +87,7 @@ class HTMLButtonElement final : public nsGenericHTMLFormControlElementWithState, nsAttrValue& aResult) override; // nsGenericHTMLElement - bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable, int32_t* aTabIndex) override; bool IsDisabledForEvents(WidgetEvent* aEvent) override; diff --git a/dom/html/HTMLCanvasElement.cpp b/dom/html/HTMLCanvasElement.cpp index 93a7bb3787..a138f2f30a 100644 --- a/dom/html/HTMLCanvasElement.cpp +++ b/dom/html/HTMLCanvasElement.cpp @@ -857,6 +857,20 @@ already_AddRefed<CanvasCaptureMediaStream> HTMLCanvasElement::CaptureStream( return nullptr; } + // Check if we transferred the OffscreenCanvas to a DOM worker. This is not + // defined by the spec yet, so it is better to fail now than implement + // something not compliant: + // https://github.com/w3c/mediacapture-fromelement/issues/65 + // https://github.com/w3c/mediacapture-extensions/pull/26 + // https://github.com/web-platform-tests/wpt/issues/21102 + if (mOffscreenDisplay && + NS_WARN_IF(!mOffscreenDisplay->CanElementCaptureStream())) { + aRv.ThrowNotSupportedError( + "Capture stream not supported when OffscreenCanvas transferred to " + "worker"); + return nullptr; + } + auto stream = MakeRefPtr<CanvasCaptureMediaStream>(window, this); nsCOMPtr<nsIPrincipal> principal = NodePrincipal(); diff --git a/dom/html/HTMLCanvasElement.h b/dom/html/HTMLCanvasElement.h index 586a43fedc..d5a4e019ff 100644 --- a/dom/html/HTMLCanvasElement.h +++ b/dom/html/HTMLCanvasElement.h @@ -356,6 +356,8 @@ class HTMLCanvasElement final : public nsGenericHTMLElement, layers::ImageContainer* GetImageContainer() const { return mImageContainer; } + bool UsingCaptureStream() const { return !!mRequestedFrameRefreshObserver; } + protected: bool mResetLayer; bool mMaybeModified; // we fetched the context, so we may have written to the diff --git a/dom/html/HTMLDNSPrefetch.cpp b/dom/html/HTMLDNSPrefetch.cpp index a4043195fe..779ed23a15 100644 --- a/dom/html/HTMLDNSPrefetch.cpp +++ b/dom/html/HTMLDNSPrefetch.cpp @@ -105,7 +105,7 @@ class DeferredDNSPrefetches final : public nsIWebProgressListener, void Flush(); void SubmitQueue(); - void SubmitQueueEntry(Element&, nsIDNSService::DNSFlags aFlags); + void SubmitQueueEntry(Element& aElement, nsIDNSService::DNSFlags aFlags); uint16_t mHead; uint16_t mTail; @@ -206,8 +206,8 @@ nsIDNSService::DNSFlags HTMLDNSPrefetch::PriorityToDNSServiceFlags( return nsIDNSService::RESOLVE_DEFAULT_FLAGS; } -nsresult HTMLDNSPrefetch::Prefetch(SupportsDNSPrefetch& aSupports, - Element& aElement, Priority aPriority) { +nsresult HTMLDNSPrefetch::DeferPrefetch(SupportsDNSPrefetch& aSupports, + Element& aElement, Priority aPriority) { MOZ_ASSERT(&ToSupportsDNSPrefetch(aElement) == &aSupports); if (!(sInitialized && sPrefetches && sDNSListener) || !EnsureDNSService()) { return NS_ERROR_NOT_AVAILABLE; @@ -362,10 +362,84 @@ void HTMLDNSPrefetch::ElementDestroyed(Element& aElement, } } -void SupportsDNSPrefetch::TryDNSPrefetch(Element& aOwner) { +void HTMLDNSPrefetch::SendRequest(Element& aElement, + nsIDNSService::DNSFlags aFlags) { + auto& supports = ToSupportsDNSPrefetch(aElement); + + nsIURI* uri = supports.GetURIForDNSPrefetch(aElement); + if (!uri) { + return; + } + + nsAutoCString hostName; + uri->GetAsciiHost(hostName); + if (hostName.IsEmpty()) { + return; + } + + bool isLocalResource = false; + nsresult rv = NS_URIChainHasFlags( + uri, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE, &isLocalResource); + if (NS_FAILED(rv) || isLocalResource) { + return; + } + + OriginAttributes oa; + StoragePrincipalHelper::GetOriginAttributesForNetworkState( + aElement.OwnerDoc(), oa); + + bool isHttps = uri->SchemeIs("https"); + + if (IsNeckoChild()) { + // during shutdown gNeckoChild might be null + if (gNeckoChild) { + gNeckoChild->SendHTMLDNSPrefetch(NS_ConvertUTF8toUTF16(hostName), isHttps, + oa, aFlags); + } + } else { + nsCOMPtr<nsICancelable> tmpOutstanding; + + rv = sDNSService->AsyncResolveNative( + hostName, nsIDNSService::RESOLVE_TYPE_DEFAULT, + aFlags | nsIDNSService::RESOLVE_SPECULATE, nullptr, sDNSListener, + nullptr, oa, getter_AddRefs(tmpOutstanding)); + if (NS_FAILED(rv)) { + return; + } + + // Fetch HTTPS RR if needed. + if (StaticPrefs::network_dns_upgrade_with_https_rr() || + StaticPrefs::network_dns_use_https_rr_as_altsvc()) { + sDNSService->AsyncResolveNative( + hostName, nsIDNSService::RESOLVE_TYPE_HTTPSSVC, + aFlags | nsIDNSService::RESOLVE_SPECULATE, nullptr, sDNSListener, + nullptr, oa, getter_AddRefs(tmpOutstanding)); + } + } + + // Tell element that deferred prefetch was requested. + supports.DNSPrefetchRequestStarted(); +} + +void SupportsDNSPrefetch::TryDNSPrefetch( + Element& aOwner, HTMLDNSPrefetch::PrefetchSource aSource) { MOZ_ASSERT(aOwner.IsInComposedDoc()); if (HTMLDNSPrefetch::IsAllowed(aOwner.OwnerDoc())) { - HTMLDNSPrefetch::Prefetch(*this, aOwner, HTMLDNSPrefetch::Priority::Low); + if (!(sInitialized && sDNSListener) || !EnsureDNSService()) { + return; + } + + if (aSource == HTMLDNSPrefetch::PrefetchSource::AnchorSpeculativePrefetch) { + HTMLDNSPrefetch::DeferPrefetch(*this, aOwner, + HTMLDNSPrefetch::Priority::Low); + } else if (aSource == HTMLDNSPrefetch::PrefetchSource::LinkDnsPrefetch) { + HTMLDNSPrefetch::SendRequest( + aOwner, GetDNSFlagsFromElement(aOwner) | + HTMLDNSPrefetch::PriorityToDNSServiceFlags( + HTMLDNSPrefetch::Priority::High)); + } else { + MOZ_ASSERT_UNREACHABLE("Unknown DNS prefetch type"); + } } } @@ -470,59 +544,7 @@ void DeferredDNSPrefetches::SubmitQueueEntry(Element& aElement, return; } - nsIURI* uri = supports.GetURIForDNSPrefetch(aElement); - if (!uri) { - return; - } - - nsAutoCString hostName; - uri->GetAsciiHost(hostName); - if (hostName.IsEmpty()) { - return; - } - - bool isLocalResource = false; - nsresult rv = NS_URIChainHasFlags( - uri, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE, &isLocalResource); - if (NS_FAILED(rv) || isLocalResource) { - return; - } - - OriginAttributes oa; - StoragePrincipalHelper::GetOriginAttributesForNetworkState( - aElement.OwnerDoc(), oa); - - bool isHttps = uri->SchemeIs("https"); - - if (IsNeckoChild()) { - // during shutdown gNeckoChild might be null - if (gNeckoChild) { - gNeckoChild->SendHTMLDNSPrefetch(NS_ConvertUTF8toUTF16(hostName), isHttps, - oa, mEntries[mTail].mFlags); - } - } else { - nsCOMPtr<nsICancelable> tmpOutstanding; - - rv = sDNSService->AsyncResolveNative( - hostName, nsIDNSService::RESOLVE_TYPE_DEFAULT, - mEntries[mTail].mFlags | nsIDNSService::RESOLVE_SPECULATE, nullptr, - sDNSListener, nullptr, oa, getter_AddRefs(tmpOutstanding)); - if (NS_FAILED(rv)) { - return; - } - - // Fetch HTTPS RR if needed. - if (StaticPrefs::network_dns_upgrade_with_https_rr() || - StaticPrefs::network_dns_use_https_rr_as_altsvc()) { - sDNSService->AsyncResolveNative( - hostName, nsIDNSService::RESOLVE_TYPE_HTTPSSVC, - mEntries[mTail].mFlags | nsIDNSService::RESOLVE_SPECULATE, nullptr, - sDNSListener, nullptr, oa, getter_AddRefs(tmpOutstanding)); - } - } - - // Tell element that deferred prefetch was requested. - supports.DNSPrefetchRequestStarted(); + HTMLDNSPrefetch::SendRequest(aElement, aFlags); } void DeferredDNSPrefetches::Activate() { diff --git a/dom/html/HTMLDNSPrefetch.h b/dom/html/HTMLDNSPrefetch.h index 5820a6ecb2..5fd263d3f5 100644 --- a/dom/html/HTMLDNSPrefetch.h +++ b/dom/html/HTMLDNSPrefetch.h @@ -55,7 +55,13 @@ class HTMLDNSPrefetch { Medium, High, }; - static nsresult Prefetch(SupportsDNSPrefetch&, Element&, Priority); + enum class PrefetchSource { + LinkDnsPrefetch, + AnchorSpeculativePrefetch, + }; + static nsresult DeferPrefetch(SupportsDNSPrefetch& aSupports, + Element& aElement, Priority aPriority); + static void SendRequest(Element& aElement, nsIDNSService::DNSFlags aFlags); static nsresult Prefetch( const nsAString& host, bool isHttps, const OriginAttributes& aPartitionedPrincipalOriginAttributes, @@ -68,9 +74,9 @@ class HTMLDNSPrefetch { nsresult aReason); static void ElementDestroyed(Element&, SupportsDNSPrefetch&); - private: static nsIDNSService::DNSFlags PriorityToDNSServiceFlags(Priority); + private: static nsresult Prefetch( const nsAString& host, bool isHttps, const OriginAttributes& aPartitionedPrincipalOriginAttributes, @@ -114,8 +120,8 @@ class SupportsDNSPrefetch { mDNSPrefetchDeferred(false), mDestroyedCalled(false) {} - void CancelDNSPrefetch(Element&); - void TryDNSPrefetch(Element&); + void CancelDNSPrefetch(Element& aOwner); + void TryDNSPrefetch(Element& aOwner, HTMLDNSPrefetch::PrefetchSource aSource); // This MUST be called on the destructor of the Element subclass. // Our own destructor ensures that. diff --git a/dom/html/HTMLDetailsElement.h b/dom/html/HTMLDetailsElement.h index 2c7ed56d98..03df1f07a1 100644 --- a/dom/html/HTMLDetailsElement.h +++ b/dom/html/HTMLDetailsElement.h @@ -48,7 +48,7 @@ class HTMLDetailsElement final : public nsGenericHTMLElement { void ToggleOpen() { SetOpen(!Open(), IgnoreErrors()); } - virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) override; + void AsyncEventRunning(AsyncEventDispatcher* aEvent) override; void HandleInvokeInternal(nsAtom* aAction, ErrorResult& aRv) override; diff --git a/dom/html/HTMLDialogElement.cpp b/dom/html/HTMLDialogElement.cpp index cd36201182..3e717534d2 100644 --- a/dom/html/HTMLDialogElement.cpp +++ b/dom/html/HTMLDialogElement.cpp @@ -157,7 +157,7 @@ void HTMLDialogElement::FocusDialog() { RefPtr<Element> control = HasAttr(nsGkAtoms::autofocus) ? this - : GetFocusDelegate(false /* aWithMouse */); + : GetFocusDelegate(IsFocusableFlags(0)); // If there isn't one of those either, then let control be subject. if (!control) { diff --git a/dom/html/HTMLEmbedElement.cpp b/dom/html/HTMLEmbedElement.cpp index 39582063a7..7cd9fd916c 100644 --- a/dom/html/HTMLEmbedElement.cpp +++ b/dom/html/HTMLEmbedElement.cpp @@ -133,8 +133,8 @@ int32_t HTMLEmbedElement::TabIndexDefault() { return Type() == ObjectType::Document ? 0 : -1; } -bool HTMLEmbedElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, - int32_t* aTabIndex) { +bool HTMLEmbedElement::IsHTMLFocusable(IsFocusableFlags aFlags, + bool* aIsFocusable, int32_t* aTabIndex) { // Has non-plugin content: let the plugin decide what to do in terms of // internal focus from mouse clicks if (aTabIndex) { diff --git a/dom/html/HTMLEmbedElement.h b/dom/html/HTMLEmbedElement.h index 8e7bcd4166..4d7f1496e8 100644 --- a/dom/html/HTMLEmbedElement.h +++ b/dom/html/HTMLEmbedElement.h @@ -38,7 +38,7 @@ class HTMLEmbedElement final : public nsGenericHTMLElement, nsresult BindToTree(BindContext&, nsINode& aParent) override; void UnbindFromTree(UnbindContext&) override; - bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable, int32_t* aTabIndex) override; int32_t TabIndexDefault() override; diff --git a/dom/html/HTMLImageElement.cpp b/dom/html/HTMLImageElement.cpp index 691216d152..597d7f4b22 100644 --- a/dom/html/HTMLImageElement.cpp +++ b/dom/html/HTMLImageElement.cpp @@ -6,6 +6,7 @@ #include "mozilla/dom/HTMLImageElement.h" #include "mozilla/PresShell.h" +#include "mozilla/FocusModel.h" #include "mozilla/dom/BindContext.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/HTMLImageElementBinding.h" @@ -488,13 +489,13 @@ nsINode* HTMLImageElement::GetScopeChainParent() const { return nsGenericHTMLElement::GetScopeChainParent(); } -bool HTMLImageElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, - int32_t* aTabIndex) { +bool HTMLImageElement::IsHTMLFocusable(IsFocusableFlags aFlags, + bool* aIsFocusable, int32_t* aTabIndex) { int32_t tabIndex = TabIndex(); if (IsInComposedDoc() && FindImageMap()) { // Use tab index on individual map areas. - *aTabIndex = (sTabFocusModel & eTabFocus_linksMask) ? 0 : -1; + *aTabIndex = FocusModel::IsTabFocusable(TabFocusableType::Links) ? 0 : -1; // Image map is not focusable itself, but flag as tabbable // so that image map areas get walked into. *aIsFocusable = false; @@ -502,8 +503,10 @@ bool HTMLImageElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, } // Can be in tab order if tabindex >=0 and form controls are tabbable. - *aTabIndex = (sTabFocusModel & eTabFocus_formElementsMask) ? tabIndex : -1; - *aIsFocusable = IsFormControlDefaultFocusable(aWithMouse) && + *aTabIndex = FocusModel::IsTabFocusable(TabFocusableType::FormElements) + ? tabIndex + : -1; + *aIsFocusable = IsFormControlDefaultFocusable(aFlags) && (tabIndex >= 0 || GetTabIndexAttrValue().isSome()); return false; diff --git a/dom/html/HTMLImageElement.h b/dom/html/HTMLImageElement.h index bf41c68d40..1097d1fb04 100644 --- a/dom/html/HTMLImageElement.h +++ b/dom/html/HTMLImageElement.h @@ -70,7 +70,7 @@ class HTMLImageElement final : public nsGenericHTMLElement, void GetEventTargetParent(EventChainPreVisitor& aVisitor) override; nsINode* GetScopeChainParent() const override; - bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable, int32_t* aTabIndex) override; nsresult BindToTree(BindContext&, nsINode& aParent) override; diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index 958601616b..9a7f7e02bd 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -1986,18 +1986,21 @@ Decimal HTMLInputElement::GetStepBase() const { return kDefaultStepBase; } -nsresult HTMLInputElement::GetValueIfStepped(int32_t aStep, - StepCallerType aCallerType, - Decimal* aNextStep) { +Decimal HTMLInputElement::GetValueIfStepped(int32_t aStep, + StepCallerType aCallerType, + ErrorResult& aRv) { + constexpr auto kNaN = Decimal::nan(); if (!DoStepDownStepUpApply()) { - return NS_ERROR_DOM_INVALID_STATE_ERR; + aRv.ThrowInvalidStateError("Step doesn't apply to this input type"); + return kNaN; } Decimal stepBase = GetStepBase(); Decimal step = GetStep(); if (step == kStepAny) { - if (aCallerType != CALLED_FOR_USER_EVENT) { - return NS_ERROR_DOM_INVALID_STATE_ERR; + if (aCallerType != StepCallerType::ForUserEvent) { + aRv.ThrowInvalidStateError("Can't step an input with step=\"any\""); + return kNaN; } // Allow the spin buttons and up/down arrow keys to do something sensible: step = GetDefaultStep(); @@ -2015,7 +2018,7 @@ nsresult HTMLInputElement::GetValueIfStepped(int32_t aStep, // adjustment to align maximum on a step, or else (if we adjusted // maximum) there is no valid step between minimum and the unadjusted // maximum. - return NS_OK; + return kNaN; } } } @@ -2062,25 +2065,20 @@ nsresult HTMLInputElement::GetValueIfStepped(int32_t aStep, (aStep < 0 && value > valueBeforeStepping))) { // We don't want step-up to effectively step down, or step-down to // effectively step up, so return; - return NS_OK; + return kNaN; } - *aNextStep = value; - return NS_OK; + return value; } -nsresult HTMLInputElement::ApplyStep(int32_t aStep) { - Decimal nextStep = Decimal::nan(); // unchanged if value will not change - - nsresult rv = GetValueIfStepped(aStep, CALLED_FOR_SCRIPT, &nextStep); - - if (NS_SUCCEEDED(rv) && nextStep.isFinite()) { - // We know we're not a file input, so the caller type does not matter; just - // pass "not system" to be safe. - SetValue(nextStep, CallerType::NonSystem); +void HTMLInputElement::ApplyStep(int32_t aStep, ErrorResult& aRv) { + Decimal nextStep = GetValueIfStepped(aStep, StepCallerType::ForScript, aRv); + if (aRv.Failed() || !nextStep.isFinite()) { + return; } - - return rv; + // We know we're not a file input, so the caller type does not matter; just + // pass "not system" to be safe. + SetValue(nextStep, CallerType::NonSystem); } bool HTMLInputElement::IsDateTimeInputType(FormControlType aType) { @@ -3520,11 +3518,9 @@ void HTMLInputElement::StepNumberControlForUserEvent(int32_t aDirection) { } } - Decimal newValue = Decimal::nan(); // unchanged if value will not change - - nsresult rv = GetValueIfStepped(aDirection, CALLED_FOR_USER_EVENT, &newValue); - - if (NS_FAILED(rv) || !newValue.isFinite()) { + Decimal newValue = GetValueIfStepped(aDirection, StepCallerType::ForUserEvent, + IgnoreErrors()); + if (!newValue.isFinite()) { return; // value should not or will not change } @@ -3794,6 +3790,12 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { if (mType == FormControlType::InputRadio && keyEvent->IsTrusted() && !keyEvent->IsAlt() && !keyEvent->IsControl() && !keyEvent->IsMeta()) { + // Radio button navigation needs to check visibility, so flush + // to ensure visibility is up to date. + if (Document* doc = GetComposedDoc()) { + doc->FlushPendingNotifications( + FlushType::EnsurePresShellInitAndFrames); + } rv = MaybeHandleRadioButtonNavigation(aVisitor, keyEvent->mKeyCode); } @@ -6427,10 +6429,10 @@ void HTMLInputElement::RemoveFromRadioGroup() { mRadioGroupContainer = nullptr; } -bool HTMLInputElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, - int32_t* aTabIndex) { +bool HTMLInputElement::IsHTMLFocusable(IsFocusableFlags aFlags, + bool* aIsFocusable, int32_t* aTabIndex) { if (nsGenericHTMLFormControlElementWithState::IsHTMLFocusable( - aWithMouse, aIsFocusable, aTabIndex)) { + aFlags, aIsFocusable, aTabIndex)) { return true; } @@ -6444,7 +6446,7 @@ bool HTMLInputElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, return false; } - const bool defaultFocusable = IsFormControlDefaultFocusable(aWithMouse); + const bool defaultFocusable = IsFormControlDefaultFocusable(aFlags); if (CreatesDateTimeWidget()) { if (aTabIndex) { // We only want our native anonymous child to be tabable to, not ourself. diff --git a/dom/html/HTMLInputElement.h b/dom/html/HTMLInputElement.h index 2c90aa83fe..aa8bff8864 100644 --- a/dom/html/HTMLInputElement.h +++ b/dom/html/HTMLInputElement.h @@ -162,7 +162,7 @@ class HTMLInputElement final : public TextControlElement, void FieldSetDisabledChanged(bool aNotify) override; // nsIContent - bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable, int32_t* aTabIndex) override; bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, @@ -663,9 +663,8 @@ class HTMLInputElement final : public TextControlElement, SetUnsignedIntAttr(nsGkAtoms::width, aValue, 0, aRv); } - void StepUp(int32_t aN, ErrorResult& aRv) { aRv = ApplyStep(aN); } - - void StepDown(int32_t aN, ErrorResult& aRv) { aRv = ApplyStep(-aN); } + void StepUp(int32_t aN, ErrorResult& aRv) { ApplyStep(aN, aRv); } + void StepDown(int32_t aN, ErrorResult& aRv) { ApplyStep(-aN, aRv); } /** * Returns the current step value. @@ -1311,22 +1310,17 @@ class HTMLInputElement final : public TextControlElement, */ Decimal GetDefaultStep() const; - enum StepCallerType { CALLED_FOR_USER_EVENT, CALLED_FOR_SCRIPT }; + enum class StepCallerType { ForUserEvent, ForScript }; /** - * Sets the aValue outparam to the value that this input would take if - * someone tries to step aStep steps and this input's value would change as - * a result. Leaves aValue untouched if this inputs value would not change - * (e.g. already at max, and asking for the next step up). + * Returns the value that this input would take if someone tries to step + * aStepCount steps and this input's value would change as a result, or + * Decimal::nan() otherwise (e.g., if this inputs value would not change due + * to it being already at max, and asking for the next step up). * * Negative aStep means step down, positive means step up. - * - * Returns NS_OK or else the error values that should be thrown if this call - * was initiated by a stepUp()/stepDown() call from script under conditions - * that such a call should throw. */ - nsresult GetValueIfStepped(int32_t aStepCount, StepCallerType aCallerType, - Decimal* aNextStep); + Decimal GetValueIfStepped(int32_t aStepCount, StepCallerType, ErrorResult&); /** * Apply a step change from stepUp or stepDown by multiplying aStep by the @@ -1334,7 +1328,7 @@ class HTMLInputElement final : public TextControlElement, * * @param aStep The value used to be multiplied against the step value. */ - nsresult ApplyStep(int32_t aStep); + void ApplyStep(int32_t aStep, ErrorResult&); /** * Returns if the current type is an experimental mobile type. diff --git a/dom/html/HTMLLinkElement.cpp b/dom/html/HTMLLinkElement.cpp index cb316a6f7b..30994cf964 100644 --- a/dom/html/HTMLLinkElement.cpp +++ b/dom/html/HTMLLinkElement.cpp @@ -555,7 +555,7 @@ void HTMLLinkElement:: } if (linkTypes & eDNS_PREFETCH) { - TryDNSPrefetch(*this); + TryDNSPrefetch(*this, HTMLDNSPrefetch::PrefetchSource::LinkDnsPrefetch); } } diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 877f3ec3ba..2db729fa2f 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -318,7 +318,7 @@ class HTMLMediaElement::MediaControlKeyListener final MOZ_INIT_OUTSIDE_CTOR explicit MediaControlKeyListener( HTMLMediaElement* aElement) - : mElement(aElement) { + : mElement(aElement), mElementId(nsID::GenerateUUID()) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aElement); } @@ -411,6 +411,33 @@ class HTMLMediaElement::MediaControlKeyListener final } } + void NotifyMediaPositionState() { + if (!IsStarted()) { + return; + } + + MOZ_ASSERT(mControlAgent); + auto* owner = Owner(); + PositionState state(owner->Duration(), owner->PlaybackRate(), + owner->CurrentTime(), TimeStamp::Now()); + MEDIACONTROL_LOG( + "Notify media position state (duration=%f, playbackRate=%f, " + "position=%f)", + state.mDuration, state.mPlaybackRate, + state.mLastReportedPlaybackPosition); + mControlAgent->UpdateGuessedPositionState(mOwnerBrowsingContextId, + mElementId, Some(state)); + } + + void Shutdown() { + StopIfNeeded(); + if (!mControlAgent) { + return; + } + mControlAgent->UpdateGuessedPositionState(mOwnerBrowsingContextId, + mElementId, Nothing()); + } + // This method can be called before the listener starts, which would cache // the audible state and update after the listener starts. void UpdateMediaAudibleState(bool aIsOwnerAudible) { @@ -543,6 +570,10 @@ class HTMLMediaElement::MediaControlKeyListener final MOZ_ASSERT(mState != aState, "Should not notify same state again!"); mState = aState; mControlAgent->NotifyMediaPlaybackChanged(mOwnerBrowsingContextId, mState); + + if (aState == MediaPlaybackState::ePlayed) { + NotifyMediaPositionState(); + } } void NotifyAudibleStateChanged(MediaAudibleState aState) { @@ -557,6 +588,7 @@ class HTMLMediaElement::MediaControlKeyListener final bool mIsPictureInPictureEnabled = false; bool mIsOwnerAudible = false; MOZ_INIT_OUTSIDE_CTOR uint64_t mOwnerBrowsingContextId; + const nsID mElementId; }; class HTMLMediaElement::MediaStreamTrackListener @@ -994,7 +1026,7 @@ class HTMLMediaElement::MediaStreamRenderer { graph->CreateSourceTrack(MediaSegment::AUDIO)); } - void ResolveAudioDevicePromiseIfExists(const char* aMethodName) { + void ResolveAudioDevicePromiseIfExists(StaticString aMethodName) { if (mSetAudioDevicePromise.IsEmpty()) { return; } @@ -2065,7 +2097,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, NS_IMPL_CYCLE_COLLECTION_UNLINK(mSeekDOMPromise) NS_IMPL_CYCLE_COLLECTION_UNLINK(mSetMediaKeysDOMPromise) if (tmp->mMediaControlKeyListener) { - tmp->mMediaControlKeyListener->StopIfNeeded(); + tmp->mMediaControlKeyListener->Shutdown(); } if (tmp->mEventBlocker) { tmp->mEventBlocker->Shutdown(); @@ -3384,6 +3416,8 @@ void HTMLMediaElement::Seek(double aTime, SeekTarget::Type aSeekType, // We changed whether we're seeking so we need to AddRemoveSelfReference. AddRemoveSelfReference(); + + mMediaControlKeyListener->NotifyMediaPositionState(); } double HTMLMediaElement::Duration() const { @@ -4804,10 +4838,9 @@ void HTMLMediaElement::DoneCreatingElement() { } } -bool HTMLMediaElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, - int32_t* aTabIndex) { - if (nsGenericHTMLElement::IsHTMLFocusable(aWithMouse, aIsFocusable, - aTabIndex)) { +bool HTMLMediaElement::IsHTMLFocusable(IsFocusableFlags aFlags, + bool* aIsFocusable, int32_t* aTabIndex) { + if (nsGenericHTMLElement::IsHTMLFocusable(aFlags, aIsFocusable, aTabIndex)) { return true; } @@ -6871,6 +6904,7 @@ void HTMLMediaElement::SetPlaybackRate(double aPlaybackRate, ErrorResult& aRv) { mDecoder->SetPlaybackRate(ClampPlaybackRate(mPlaybackRate)); } DispatchAsyncEvent(u"ratechange"_ns); + mMediaControlKeyListener->NotifyMediaPositionState(); } void HTMLMediaElement::SetPreservesPitch(bool aPreservesPitch) { diff --git a/dom/html/HTMLMediaElement.h b/dom/html/HTMLMediaElement.h index 6c159a7971..2065796b08 100644 --- a/dom/html/HTMLMediaElement.h +++ b/dom/html/HTMLMediaElement.h @@ -196,24 +196,24 @@ class HTMLMediaElement : public nsGenericHTMLElement, void NodeInfoChanged(Document* aOldDoc) override; - virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, - const nsAString& aValue, - nsIPrincipal* aMaybeScriptedPrincipal, - nsAttrValue& aResult) override; + bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, + const nsAString& aValue, + nsIPrincipal* aMaybeScriptedPrincipal, + nsAttrValue& aResult) override; - virtual nsresult BindToTree(BindContext&, nsINode& aParent) override; - virtual void UnbindFromTree(UnbindContext&) override; - virtual void DoneCreatingElement() override; + nsresult BindToTree(BindContext&, nsINode& aParent) override; + void UnbindFromTree(UnbindContext&) override; + void DoneCreatingElement() override; - virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, - int32_t* aTabIndex) override; - virtual int32_t TabIndexDefault() override; + bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable, + int32_t* aTabIndex) override; + int32_t TabIndexDefault() override; // Called by the video decoder object, on the main thread, // when it has read the metadata containing video dimensions, // etc. - virtual void MetadataLoaded(const MediaInfo* aInfo, - UniquePtr<const MetadataTags> aTags) final; + void MetadataLoaded(const MediaInfo* aInfo, + UniquePtr<const MetadataTags> aTags) final; // Called by the decoder object, on the main thread, // when it has read the first frame of the video or audio. diff --git a/dom/html/HTMLObjectElement.cpp b/dom/html/HTMLObjectElement.cpp index f77a1f3ba2..d449e48407 100644 --- a/dom/html/HTMLObjectElement.cpp +++ b/dom/html/HTMLObjectElement.cpp @@ -135,7 +135,8 @@ void HTMLObjectElement::AfterMaybeChangeAttr(int32_t aNamespaceID, })); } -bool HTMLObjectElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, +bool HTMLObjectElement::IsHTMLFocusable(IsFocusableFlags aFlags, + bool* aIsFocusable, int32_t* aTabIndex) { // TODO: this should probably be managed directly by IsHTMLFocusable. // See bug 597242. diff --git a/dom/html/HTMLObjectElement.h b/dom/html/HTMLObjectElement.h index 00bcbc70d5..4e4eaf181e 100644 --- a/dom/html/HTMLObjectElement.h +++ b/dom/html/HTMLObjectElement.h @@ -42,7 +42,7 @@ class HTMLObjectElement final : public nsGenericHTMLFormControlElement, nsresult BindToTree(BindContext&, nsINode& aParent) override; void UnbindFromTree(UnbindContext&) override; - bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable, int32_t* aTabIndex) override; // Overriden nsIFormControl methods diff --git a/dom/html/HTMLSelectElement.cpp b/dom/html/HTMLSelectElement.cpp index 6ca4209cd9..7a1b5ccf0d 100644 --- a/dom/html/HTMLSelectElement.cpp +++ b/dom/html/HTMLSelectElement.cpp @@ -1026,10 +1026,11 @@ void HTMLSelectElement::SetValue(const nsAString& aValue) { int32_t HTMLSelectElement::TabIndexDefault() { return 0; } -bool HTMLSelectElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, +bool HTMLSelectElement::IsHTMLFocusable(IsFocusableFlags aFlags, + bool* aIsFocusable, int32_t* aTabIndex) { if (nsGenericHTMLFormControlElementWithState::IsHTMLFocusable( - aWithMouse, aIsFocusable, aTabIndex)) { + aFlags, aIsFocusable, aTabIndex)) { return true; } diff --git a/dom/html/HTMLSelectElement.h b/dom/html/HTMLSelectElement.h index 1ba5dc29f6..401748b9d1 100644 --- a/dom/html/HTMLSelectElement.h +++ b/dom/html/HTMLSelectElement.h @@ -198,7 +198,7 @@ class HTMLSelectElement final : public nsGenericHTMLFormControlElementWithState, // nsIContent void GetEventTargetParent(EventChainPreVisitor& aVisitor) override; - bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable, int32_t* aTabIndex) override; void InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis, bool aNotify, ErrorResult& aRv) override; diff --git a/dom/html/HTMLSharedElement.cpp b/dom/html/HTMLSharedElement.cpp index 85849f9f79..0dd151f473 100644 --- a/dom/html/HTMLSharedElement.cpp +++ b/dom/html/HTMLSharedElement.cpp @@ -85,15 +85,22 @@ static void SetBaseURIUsingFirstBaseWithHref(Document* aDocument, getter_AddRefs(newBaseURI), href, aDocument, aDocument->GetFallbackBaseURI()); + // Vaguely based on + // <https://html.spec.whatwg.org/multipage/semantics.html#set-the-frozen-base-url> + + if (newBaseURI && (newBaseURI->SchemeIs("data") || + newBaseURI->SchemeIs("javascript"))) { + newBaseURI = nullptr; + } + // Check if CSP allows this base-uri - nsresult rv = NS_OK; nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp(); if (csp && newBaseURI) { // base-uri is only enforced if explicitly defined in the // policy - do *not* consult default-src, see: // http://www.w3.org/TR/CSP2/#directive-default-src bool cspPermitsBaseURI = true; - rv = csp->Permits( + nsresult rv = csp->Permits( child->AsElement(), nullptr /* nsICSPEventListener */, newBaseURI, nsIContentSecurityPolicy::BASE_URI_DIRECTIVE, true /* aSpecific */, true /* aSendViolationReports */, &cspPermitsBaseURI); @@ -101,6 +108,7 @@ static void SetBaseURIUsingFirstBaseWithHref(Document* aDocument, newBaseURI = nullptr; } } + aDocument->SetBaseURI(newBaseURI); aDocument->SetChromeXHRDocBaseURI(nullptr); return; diff --git a/dom/html/HTMLSummaryElement.cpp b/dom/html/HTMLSummaryElement.cpp index d1fcf22598..1422bb97be 100644 --- a/dom/html/HTMLSummaryElement.cpp +++ b/dom/html/HTMLSummaryElement.cpp @@ -68,10 +68,11 @@ nsresult HTMLSummaryElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { return rv; } -bool HTMLSummaryElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, +bool HTMLSummaryElement::IsHTMLFocusable(IsFocusableFlags aFlags, + bool* aIsFocusable, int32_t* aTabIndex) { - bool disallowOverridingFocusability = nsGenericHTMLElement::IsHTMLFocusable( - aWithMouse, aIsFocusable, aTabIndex); + bool disallowOverridingFocusability = + nsGenericHTMLElement::IsHTMLFocusable(aFlags, aIsFocusable, aTabIndex); if (disallowOverridingFocusability || !IsMainSummary()) { return disallowOverridingFocusability; diff --git a/dom/html/HTMLSummaryElement.h b/dom/html/HTMLSummaryElement.h index b70e8eebbb..d61f3813aa 100644 --- a/dom/html/HTMLSummaryElement.h +++ b/dom/html/HTMLSummaryElement.h @@ -30,7 +30,7 @@ class HTMLSummaryElement final : public nsGenericHTMLElement { nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override; - bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable, int32_t* aTabIndex) override; int32_t TabIndexDefault() override; diff --git a/dom/html/HTMLTextAreaElement.cpp b/dom/html/HTMLTextAreaElement.cpp index be4ba5a891..7624d53b85 100644 --- a/dom/html/HTMLTextAreaElement.cpp +++ b/dom/html/HTMLTextAreaElement.cpp @@ -133,10 +133,11 @@ HTMLTextAreaElement::SelectAll(nsPresContext* aPresContext) { return NS_OK; } -bool HTMLTextAreaElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, +bool HTMLTextAreaElement::IsHTMLFocusable(IsFocusableFlags aFlags, + bool* aIsFocusable, int32_t* aTabIndex) { if (nsGenericHTMLFormControlElementWithState::IsHTMLFocusable( - aWithMouse, aIsFocusable, aTabIndex)) { + aFlags, aIsFocusable, aTabIndex)) { return true; } diff --git a/dom/html/HTMLTextAreaElement.h b/dom/html/HTMLTextAreaElement.h index 0adaa48b21..d14523ae1c 100644 --- a/dom/html/HTMLTextAreaElement.h +++ b/dom/html/HTMLTextAreaElement.h @@ -122,7 +122,7 @@ class HTMLTextAreaElement final : public TextControlElement, nsresult PreHandleEvent(EventChainVisitor& aVisitor) override; nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override; - bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable, int32_t* aTabIndex) override; void DoneAddingChildren(bool aHaveNotified) override; diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp index 1deaf719d3..11383863fd 100644 --- a/dom/html/nsGenericHTMLElement.cpp +++ b/dom/html/nsGenericHTMLElement.cpp @@ -9,6 +9,7 @@ #include "mozilla/EventListenerManager.h" #include "mozilla/EventStateManager.h" #include "mozilla/HTMLEditor.h" +#include "mozilla/FocusModel.h" #include "mozilla/IMEContentObserver.h" #include "mozilla/IMEStateManager.h" #include "mozilla/MappedDeclarationsBuilder.h" @@ -286,7 +287,7 @@ static bool IsOffsetParent(nsIFrame* aFrame) { struct OffsetResult { Element* mParent = nullptr; - CSSIntRect mRect; + nsRect mRect; }; static OffsetResult GetUnretargetedOffsetsFor(const Element& aElement) { @@ -303,6 +304,7 @@ static OffsetResult GetUnretargetedOffsetsFor(const Element& aElement) { nsIContent* offsetParent = nullptr; Element* docElement = aElement.GetComposedDoc()->GetRootElement(); nsIContent* content = frame->GetContent(); + const auto effectiveZoom = frame->Style()->EffectiveZoom(); if (content && (content->IsHTMLElement(nsGkAtoms::body) || content == docElement)) { @@ -321,6 +323,13 @@ static OffsetResult GetUnretargetedOffsetsFor(const Element& aElement) { break; } + // WebKit-ism: offsetParent stops at zoom changes. + // See https://github.com/w3c/csswg-drafts/issues/10252 + if (effectiveZoom != parent->Style()->EffectiveZoom()) { + offsetParent = content; + break; + } + // Add the parent's origin to our own to get to the // right coordinate system. const bool isOffsetParent = !isPositioned && IsOffsetParent(parent); @@ -370,8 +379,7 @@ static OffsetResult GetUnretargetedOffsetsFor(const Element& aElement) { // we only care about the size. We just have to use something non-null. nsRect rcFrame = nsLayoutUtils::GetAllInFlowRectsUnion(frame, frame); rcFrame.MoveTo(origin); - return {Element::FromNodeOrNull(offsetParent), - CSSIntRect::FromAppUnitsRounded(rcFrame)}; + return {Element::FromNodeOrNull(offsetParent), rcFrame}; } static bool ShouldBeRetargeted(const Element& aReferenceElement, @@ -393,20 +401,22 @@ static bool ShouldBeRetargeted(const Element& aReferenceElement, Element* nsGenericHTMLElement::GetOffsetRect(CSSIntRect& aRect) { aRect = CSSIntRect(); - if (!GetPrimaryFrame(FlushType::Layout)) { + nsIFrame* frame = GetPrimaryFrame(FlushType::Layout); + if (!frame) { return nullptr; } OffsetResult thisResult = GetUnretargetedOffsetsFor(*this); - aRect = thisResult.mRect; - + nsRect rect = thisResult.mRect; Element* parent = thisResult.mParent; while (parent && ShouldBeRetargeted(*this, *parent)) { OffsetResult result = GetUnretargetedOffsetsFor(*parent); - aRect += result.mRect.TopLeft(); + rect += result.mRect.TopLeft(); parent = result.mParent; } + aRect = CSSIntRect::FromAppUnitsRounded( + frame->Style()->EffectiveZoom().Unzoom(rect)); return parent; } @@ -1757,8 +1767,8 @@ bool nsGenericHTMLElement::LegacyTouchAPIEnabled(JSContext* aCx, } bool nsGenericHTMLElement::IsFormControlDefaultFocusable( - bool aWithMouse) const { - if (!aWithMouse) { + IsFocusableFlags aFlags) const { + if (!(aFlags & IsFocusableFlags::WithMouse)) { return true; } switch (StaticPrefs::accessibility_mouse_focuses_formcontrol()) { @@ -2303,7 +2313,8 @@ void nsGenericHTMLElement::Click(CallerType aCallerType) { ClearHandlingClick(); } -bool nsGenericHTMLElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, +bool nsGenericHTMLElement::IsHTMLFocusable(IsFocusableFlags aFlags, + bool* aIsFocusable, int32_t* aTabIndex) { MOZ_ASSERT(aIsFocusable); MOZ_ASSERT(aTabIndex); @@ -2589,15 +2600,15 @@ void nsGenericHTMLFormControlElement::GetAutocapitalize( } } -bool nsGenericHTMLFormControlElement::IsHTMLFocusable(bool aWithMouse, +bool nsGenericHTMLFormControlElement::IsHTMLFocusable(IsFocusableFlags aFlags, bool* aIsFocusable, int32_t* aTabIndex) { - if (nsGenericHTMLFormElement::IsHTMLFocusable(aWithMouse, aIsFocusable, + if (nsGenericHTMLFormElement::IsHTMLFocusable(aFlags, aIsFocusable, aTabIndex)) { return true; } - *aIsFocusable = *aIsFocusable && IsFormControlDefaultFocusable(aWithMouse); + *aIsFocusable = *aIsFocusable && IsFormControlDefaultFocusable(aFlags); return false; } @@ -3552,8 +3563,7 @@ void nsGenericHTMLElement::FocusPopover() { RefPtr<Element> control = GetBoolAttr(nsGkAtoms::autofocus) ? this - : GetAutofocusDelegate(false /* aWithMouse */); - + : GetAutofocusDelegate(IsFocusableFlags(0)); if (!control) { return; } diff --git a/dom/html/nsGenericHTMLElement.h b/dom/html/nsGenericHTMLElement.h index 86f87e8795..f63f070207 100644 --- a/dom/html/nsGenericHTMLElement.h +++ b/dom/html/nsGenericHTMLElement.h @@ -198,7 +198,7 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase { } /** Returns whether a form control should be default-focusable. */ - bool IsFormControlDefaultFocusable(bool aWithMouse) const; + bool IsFormControlDefaultFocusable(mozilla::IsFocusableFlags) const; /** * Returns the count of descendants (inclusive of this node) in @@ -333,16 +333,17 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase { nsresult BindToTree(BindContext&, nsINode& aParent) override; void UnbindFromTree(UnbindContext&) override; - Focusable IsFocusableWithoutStyle(bool aWithMouse) override { + Focusable IsFocusableWithoutStyle(mozilla::IsFocusableFlags aFlags = + mozilla::IsFocusableFlags(0)) override { Focusable result; - IsHTMLFocusable(aWithMouse, &result.mFocusable, &result.mTabIndex); + IsHTMLFocusable(aFlags, &result.mFocusable, &result.mTabIndex); return result; } /** * Returns true if a subclass is not allowed to override the value returned * in aIsFocusable. */ - virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + virtual bool IsHTMLFocusable(mozilla::IsFocusableFlags, bool* aIsFocusable, int32_t* aTabIndex); MOZ_CAN_RUN_SCRIPT mozilla::Result<bool, nsresult> PerformAccesskey( @@ -1176,7 +1177,7 @@ class nsGenericHTMLFormControlElement : public nsGenericHTMLFormElement, // nsGenericHTMLElement // autocapitalize attribute support void GetAutocapitalize(nsAString& aValue) const override; - bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + bool IsHTMLFocusable(mozilla::IsFocusableFlags, bool* aIsFocusable, int32_t* aTabIndex) override; // EventTarget diff --git a/dom/html/nsGenericHTMLFrameElement.cpp b/dom/html/nsGenericHTMLFrameElement.cpp index 92591d7b72..c854012f4b 100644 --- a/dom/html/nsGenericHTMLFrameElement.cpp +++ b/dom/html/nsGenericHTMLFrameElement.cpp @@ -311,11 +311,10 @@ nsresult nsGenericHTMLFrameElement::CopyInnerTo(Element* aDest) { return rv; } -bool nsGenericHTMLFrameElement::IsHTMLFocusable(bool aWithMouse, +bool nsGenericHTMLFrameElement::IsHTMLFocusable(IsFocusableFlags aFlags, bool* aIsFocusable, int32_t* aTabIndex) { - if (nsGenericHTMLElement::IsHTMLFocusable(aWithMouse, aIsFocusable, - aTabIndex)) { + if (nsGenericHTMLElement::IsHTMLFocusable(aFlags, aIsFocusable, aTabIndex)) { return true; } diff --git a/dom/html/nsGenericHTMLFrameElement.h b/dom/html/nsGenericHTMLFrameElement.h index 587e861b88..c61fea2c02 100644 --- a/dom/html/nsGenericHTMLFrameElement.h +++ b/dom/html/nsGenericHTMLFrameElement.h @@ -50,15 +50,15 @@ class nsGenericHTMLFrameElement : public nsGenericHTMLElement, NS_DECLARE_STATIC_IID_ACCESSOR(NS_GENERICHTMLFRAMEELEMENT_IID) // nsIContent - virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, - int32_t* aTabIndex) override; - virtual nsresult BindToTree(BindContext&, nsINode& aParent) override; - virtual void UnbindFromTree(UnbindContext&) override; - virtual void DestroyContent() override; + bool IsHTMLFocusable(mozilla::IsFocusableFlags, bool* aIsFocusable, + int32_t* aTabIndex) override; + nsresult BindToTree(BindContext&, nsINode& aParent) override; + void UnbindFromTree(UnbindContext&) override; + void DestroyContent() override; nsresult CopyInnerTo(mozilla::dom::Element* aDest); - virtual int32_t TabIndexDefault() override; + int32_t TabIndexDefault() override; NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsGenericHTMLFrameElement, nsGenericHTMLElement) diff --git a/dom/html/test/forms/mochitest.toml b/dom/html/test/forms/mochitest.toml index 80d6d3530f..82a8639659 100644 --- a/dom/html/test/forms/mochitest.toml +++ b/dom/html/test/forms/mochitest.toml @@ -73,6 +73,8 @@ support-files = ["file_double_submit.html"] ["test_input_datetime_input_change_events.html"] +["test_input_datetime_preventDefault.html"] + ["test_input_datetime_readonly.html"] ["test_input_datetime_reset_default_value_input_change_event.html"] diff --git a/dom/html/test/forms/test_input_datetime_preventDefault.html b/dom/html/test/forms/test_input_datetime_preventDefault.html new file mode 100644 index 0000000000..76e5928c18 --- /dev/null +++ b/dom/html/test/forms/test_input_datetime_preventDefault.html @@ -0,0 +1,23 @@ +<!doctype html> +<title>Test for bug 1848158</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +<input id="input" type="date" value="1998-01-22"> +<script> +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + let value = input.value; + + input.addEventListener("keydown", function(e) { + e.preventDefault(); + }); + + isnot(value, "", "should have a value"); + + input.focus(); + synthesizeKey("KEY_Backspace"); + is(input.value, value, "Value shouldn't change"); + SimpleTest.finish(); +}); +</script> |