Backed out 7 changesets (bug 1444491, bug 1801761) for causing failures on autofocus-attribute.svg. CLOSED TREE
Backed out changeset 1cee414009cb (bug 1444491) Backed out changeset 30f786b79191 (bug 1444491) Backed out changeset ce06375518a7 (bug 1801761) Backed out changeset 64c8bb293e5c (bug 1444491) Backed out changeset 94aa0ce630f2 (bug 1444491) Backed out changeset 80010eabc0c1 (bug 1444491) Backed out changeset 7d8da1f44177 (bug 1444491)
This commit is contained in:
@@ -381,7 +381,6 @@
|
||||
#include "nsIX509Cert.h"
|
||||
#include "nsIX509CertValidity.h"
|
||||
#include "nsIXMLContentSink.h"
|
||||
#include "nsIHTMLContentSink.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "nsImageLoadingContent.h"
|
||||
#include "nsImportModule.h"
|
||||
@@ -6843,9 +6842,6 @@ already_AddRefed<PresShell> Document::CreatePresShell(
|
||||
mDocumentL10n->OnCreatePresShell();
|
||||
}
|
||||
|
||||
if (HasAutoFocusCandidates()) {
|
||||
ScheduleFlushAutoFocusCandidates();
|
||||
}
|
||||
// Now that we have a shell, we might have @font-face rules (the presence of a
|
||||
// shell may change which rules apply to us). We don't need to do anything
|
||||
// like EnsureStyleFlush or such, there's nothing to update yet and when stuff
|
||||
@@ -6952,7 +6948,6 @@ void Document::DeletePresShell() {
|
||||
mExternalResourceMap.HideViewers();
|
||||
if (nsPresContext* presContext = mPresShell->GetPresContext()) {
|
||||
presContext->RefreshDriver()->CancelPendingFullscreenEvents(this);
|
||||
presContext->RefreshDriver()->CancelFlushAutoFocus(this);
|
||||
}
|
||||
|
||||
// When our shell goes away, request that all our images be immediately
|
||||
@@ -12630,254 +12625,121 @@ Document* Document::GetTemplateContentsOwner() {
|
||||
return mTemplateContentsOwner;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#the-autofocus-attribute
|
||||
void Document::ElementWithAutoFocusInserted(Element* aAutoFocusCandidate) {
|
||||
BrowsingContext* bc = GetBrowsingContext();
|
||||
if (!bc) {
|
||||
static already_AddRefed<nsPIDOMWindowOuter> FindTopWindowForElement(
|
||||
Element* element) {
|
||||
Document* document = element->OwnerDoc();
|
||||
if (!document) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> window = document->GetWindow();
|
||||
if (!window) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Trying to find the top window (equivalent to window.top).
|
||||
if (nsCOMPtr<nsPIDOMWindowOuter> top = window->GetInProcessTop()) {
|
||||
window = std::move(top);
|
||||
}
|
||||
return window.forget();
|
||||
}
|
||||
|
||||
/**
|
||||
* nsAutoFocusEvent is used to dispatch a focus event for an
|
||||
* nsGenericHTMLFormElement with the autofocus attribute enabled.
|
||||
*/
|
||||
class nsAutoFocusEvent : public Runnable {
|
||||
public:
|
||||
explicit nsAutoFocusEvent(nsCOMPtr<Element>&& aElement,
|
||||
nsCOMPtr<nsPIDOMWindowOuter>&& aTopWindow)
|
||||
: mozilla::Runnable("nsAutoFocusEvent"),
|
||||
mElement(std::move(aElement)),
|
||||
mTopWindow(std::move(aTopWindow)) {}
|
||||
|
||||
NS_IMETHOD Run() override {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> currentTopWindow =
|
||||
FindTopWindowForElement(mElement);
|
||||
if (currentTopWindow != mTopWindow) {
|
||||
// The element's top window changed from when the event was queued.
|
||||
// Don't take away focus from an unrelated window.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (Document* doc = mTopWindow->GetExtantDoc()) {
|
||||
if (doc->IsAutoFocusFired()) {
|
||||
return NS_OK;
|
||||
}
|
||||
doc->SetAutoFocusFired();
|
||||
}
|
||||
|
||||
// Don't steal focus from the user.
|
||||
if (mTopWindow->GetFocusedElement()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
FocusOptions options;
|
||||
ErrorResult rv;
|
||||
mElement->Focus(options, CallerType::System, rv);
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<Element> mElement;
|
||||
nsCOMPtr<nsPIDOMWindowOuter> mTopWindow;
|
||||
};
|
||||
|
||||
void Document::SetAutoFocusElement(Element* aAutoFocusElement) {
|
||||
if (mAutoFocusFired) {
|
||||
// Too late.
|
||||
return;
|
||||
}
|
||||
|
||||
// If target is not fully active, then return.
|
||||
if (!IsCurrentActiveDocument()) {
|
||||
if (mAutoFocusElement) {
|
||||
// The spec disallows multiple autofocus elements, so we consider only the
|
||||
// first one to preserve the old behavior.
|
||||
return;
|
||||
}
|
||||
|
||||
// If target's active sandboxing flag set has the sandboxed automatic features
|
||||
// browsing context flag, then return.
|
||||
if (GetSandboxFlags() & SANDBOXED_AUTOMATIC_FEATURES) {
|
||||
return;
|
||||
mAutoFocusElement = do_GetWeakReference(aAutoFocusElement);
|
||||
TriggerAutoFocus();
|
||||
}
|
||||
|
||||
// For each ancestorBC of target's browsing context's ancestor browsing
|
||||
// contexts: if ancestorBC's active document's origin is not same origin with
|
||||
// target's origin, then return.
|
||||
while (bc) {
|
||||
BrowsingContext* parent = bc->GetParent();
|
||||
if (!parent) {
|
||||
break;
|
||||
}
|
||||
// AncestorBC is not the same site
|
||||
if (!parent->IsInProcess()) {
|
||||
return;
|
||||
}
|
||||
void Document::SetAutoFocusFired() { mAutoFocusFired = true; }
|
||||
|
||||
Document* currentDocument = bc->GetDocument();
|
||||
if (!currentDocument) {
|
||||
return;
|
||||
}
|
||||
bool Document::IsAutoFocusFired() { return mAutoFocusFired; }
|
||||
|
||||
Document* parentDocument = parent->GetDocument();
|
||||
if (!parentDocument) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Not same origin
|
||||
if (!currentDocument->NodePrincipal()->Equals(
|
||||
parentDocument->NodePrincipal())) {
|
||||
return;
|
||||
}
|
||||
|
||||
bc = parent;
|
||||
}
|
||||
MOZ_ASSERT(bc->IsTop());
|
||||
|
||||
Document* topDocument = bc->GetDocument();
|
||||
MOZ_ASSERT(topDocument);
|
||||
topDocument->AppendAutoFocusCandidateToTopDocument(aAutoFocusCandidate);
|
||||
}
|
||||
|
||||
void Document::ScheduleFlushAutoFocusCandidates() {
|
||||
MOZ_ASSERT(mPresShell && mPresShell->DidInitialize());
|
||||
MOZ_ASSERT(GetBrowsingContext()->IsTop());
|
||||
if (nsRefreshDriver* rd = mPresShell->GetRefreshDriver()) {
|
||||
rd->ScheduleAutoFocusFlush(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Document::AppendAutoFocusCandidateToTopDocument(
|
||||
Element* aAutoFocusCandidate) {
|
||||
MOZ_ASSERT(GetBrowsingContext()->IsTop());
|
||||
void Document::TriggerAutoFocus() {
|
||||
if (mAutoFocusFired) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HasAutoFocusCandidates()) {
|
||||
// PresShell may be initialized later
|
||||
if (mPresShell && mPresShell->DidInitialize()) {
|
||||
ScheduleFlushAutoFocusCandidates();
|
||||
}
|
||||
}
|
||||
|
||||
nsWeakPtr element = do_GetWeakReference(aAutoFocusCandidate);
|
||||
mAutoFocusCandidates.RemoveElement(element);
|
||||
mAutoFocusCandidates.AppendElement(element);
|
||||
}
|
||||
|
||||
void Document::SetAutoFocusFired() {
|
||||
mAutoFocusCandidates.Clear();
|
||||
mAutoFocusFired = true;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#flush-autofocus-candidates
|
||||
void Document::FlushAutoFocusCandidates() {
|
||||
MOZ_ASSERT(GetBrowsingContext()->IsTop());
|
||||
if (mAutoFocusFired) {
|
||||
if (!mPresShell || !mPresShell->DidInitialize()) {
|
||||
// Delay autofocus until frames are constructed so that we don't thrash
|
||||
// style and layout calculations.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mPresShell) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(HasAutoFocusCandidates());
|
||||
MOZ_ASSERT(mPresShell->DidInitialize());
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> topWindow = GetWindow();
|
||||
// We should be the top document
|
||||
nsCOMPtr<Element> autoFocusElement = do_QueryReferent(mAutoFocusElement);
|
||||
if (autoFocusElement && autoFocusElement->OwnerDoc() == this) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> topWindow =
|
||||
FindTopWindowForElement(autoFocusElement);
|
||||
if (!topWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
// Trying to find the top window (equivalent to window.top).
|
||||
nsCOMPtr<nsPIDOMWindowOuter> top = topWindow->GetInProcessTop();
|
||||
MOZ_ASSERT(topWindow == top);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Don't steal the focus from the user
|
||||
if (topWindow->GetFocusedElement()) {
|
||||
SetAutoFocusFired();
|
||||
// NOTE: This may be removed in the future since the spec technically
|
||||
// allows autofocus after load.
|
||||
nsCOMPtr<Document> topDoc = topWindow->GetExtantDoc();
|
||||
if (topDoc &&
|
||||
topDoc->GetReadyStateEnum() == Document::READYSTATE_COMPLETE) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mDocumentURI);
|
||||
nsAutoCString ref;
|
||||
// GetRef never fails
|
||||
nsresult rv = mDocumentURI->GetRef(ref);
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
nsContentUtils::GetTargetElement(this, NS_ConvertUTF8toUTF16(ref))) {
|
||||
SetAutoFocusFired();
|
||||
return;
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
new nsAutoFocusEvent(std::move(autoFocusElement), topWindow.forget());
|
||||
nsresult rv = NS_DispatchToCurrentThread(event.forget());
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
}
|
||||
|
||||
nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mAutoFocusCandidates);
|
||||
while (iter.HasMore()) {
|
||||
nsCOMPtr<Element> autoFocusElement = do_QueryReferent(iter.GetNext());
|
||||
if (!autoFocusElement) {
|
||||
continue;
|
||||
}
|
||||
RefPtr<Document> autoFocusElementDoc = autoFocusElement->OwnerDoc();
|
||||
// Get the latest info about the frame and allow scripts
|
||||
// to run which might affect the focusability of this element.
|
||||
autoFocusElementDoc->FlushPendingNotifications(FlushType::Frames);
|
||||
|
||||
// Above layout flush may cause the PresShell to disappear.
|
||||
if (!mPresShell) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Re-get the element because the ownerDoc() might have changed
|
||||
autoFocusElementDoc = autoFocusElement->OwnerDoc();
|
||||
BrowsingContext* bc = autoFocusElementDoc->GetBrowsingContext();
|
||||
if (!bc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If doc is not fully active, then remove element from candidates, and
|
||||
// continue.
|
||||
if (!autoFocusElementDoc->IsCurrentActiveDocument()) {
|
||||
iter.Remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentSink> sink =
|
||||
do_QueryInterface(autoFocusElementDoc->GetCurrentContentSink());
|
||||
if (sink) {
|
||||
nsHtml5TreeOpExecutor* executor =
|
||||
static_cast<nsHtml5TreeOpExecutor*>(sink->AsExecutor());
|
||||
if (executor) {
|
||||
// This is a HTML5 document
|
||||
MOZ_ASSERT(autoFocusElementDoc->IsHTMLDocument());
|
||||
// If doc's script-blocking style sheet counter is greater than 0, th
|
||||
// return.
|
||||
if (executor->WaitForPendingSheets()) {
|
||||
// In this case, element is the currently-best candidate, but doc is
|
||||
// not ready for autofocusing. We'll try again next time flush
|
||||
// autofocus candidates is called.
|
||||
ScheduleFlushAutoFocusCandidates();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The autofocus element could be moved to a different
|
||||
// top level BC.
|
||||
if (bc->Top()->GetDocument() != this) {
|
||||
continue;
|
||||
}
|
||||
|
||||
iter.Remove();
|
||||
|
||||
// Let inclusiveAncestorDocuments be a list consisting of doc, plus the
|
||||
// active documents of each of doc's browsing context's ancestor browsing
|
||||
// contexts.
|
||||
// If any Document in inclusiveAncestorDocuments has non-null target
|
||||
// element, then continue.
|
||||
bool shouldFocus = true;
|
||||
while (bc) {
|
||||
Document* doc = bc->GetDocument();
|
||||
if (!doc) {
|
||||
shouldFocus = false;
|
||||
break;
|
||||
}
|
||||
|
||||
nsIURI* uri = doc->GetDocumentURI();
|
||||
if (!uri) {
|
||||
shouldFocus = false;
|
||||
break;
|
||||
}
|
||||
|
||||
nsAutoCString ref;
|
||||
nsresult rv = uri->GetRef(ref);
|
||||
// If there is an element in the document tree that has an ID equal to
|
||||
// fragment
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
nsContentUtils::GetTargetElement(doc, NS_ConvertUTF8toUTF16(ref))) {
|
||||
shouldFocus = false;
|
||||
break;
|
||||
}
|
||||
bc = bc->GetParent();
|
||||
}
|
||||
|
||||
if (!shouldFocus) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(topWindow);
|
||||
if (TryAutoFocusCandidate(*autoFocusElement)) {
|
||||
// We've successfully autofocused an element, don't
|
||||
// need to try to focus the rest.
|
||||
SetAutoFocusFired();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (HasAutoFocusCandidates()) {
|
||||
ScheduleFlushAutoFocusCandidates();
|
||||
}
|
||||
}
|
||||
|
||||
bool Document::TryAutoFocusCandidate(Element& aElement) {
|
||||
const FocusOptions options;
|
||||
if (RefPtr<Element> target = nsFocusManager::GetTheFocusableArea(
|
||||
&aElement, nsFocusManager::ProgrammaticFocusFlags(options))) {
|
||||
target->Focus(options, CallerType::NonSystem, IgnoreErrors());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Document::SetScrollToRef(nsIURI* aDocumentURI) {
|
||||
|
||||
@@ -1927,8 +1927,6 @@ class Document : public nsINode,
|
||||
// layer. The removed element, if any, is returned.
|
||||
Element* TopLayerPop(FunctionRef<bool(Element*)> aPredicate);
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT bool TryAutoFocusCandidate(Element& aElement);
|
||||
|
||||
public:
|
||||
// Removes all the elements with fullscreen flag set from the top layer, and
|
||||
// clears their fullscreen flag.
|
||||
@@ -3105,14 +3103,10 @@ class Document : public nsINode,
|
||||
|
||||
nsISupports* GetCurrentContentSink();
|
||||
|
||||
void ElementWithAutoFocusInserted(Element* aAutoFocusCandidate);
|
||||
MOZ_CAN_RUN_SCRIPT void FlushAutoFocusCandidates();
|
||||
void ScheduleFlushAutoFocusCandidates();
|
||||
bool HasAutoFocusCandidates() const {
|
||||
return !mAutoFocusCandidates.IsEmpty();
|
||||
}
|
||||
|
||||
void SetAutoFocusElement(Element* aAutoFocusElement);
|
||||
void TriggerAutoFocus();
|
||||
void SetAutoFocusFired();
|
||||
bool IsAutoFocusFired();
|
||||
|
||||
void SetScrollToRef(nsIURI* aDocumentURI);
|
||||
MOZ_CAN_RUN_SCRIPT void ScrollToRef();
|
||||
@@ -3956,8 +3950,6 @@ class Document : public nsINode,
|
||||
void RecomputeLanguageFromCharset();
|
||||
bool GetSHEntryHasUserInteraction();
|
||||
|
||||
void AppendAutoFocusCandidateToTopDocument(Element* aAutoFocusCandidate);
|
||||
|
||||
public:
|
||||
void SetMayNeedFontPrefsUpdate() { mMayNeedFontPrefsUpdate = true; }
|
||||
|
||||
@@ -5147,11 +5139,7 @@ class Document : public nsINode,
|
||||
// Recorded time of change to 'loading' state.
|
||||
TimeStamp mLoadingTimeStamp;
|
||||
|
||||
// Decided to use nsTObserverArray because it allows us to
|
||||
// remove candidates while iterating them and this is what
|
||||
// the spec defines. We could implement the spec without
|
||||
// using nsTObserverArray, however using nsTObserverArray is more clear.
|
||||
nsTObserverArray<nsWeakPtr> mAutoFocusCandidates;
|
||||
nsWeakPtr mAutoFocusElement;
|
||||
|
||||
nsCString mScrollToRef;
|
||||
|
||||
|
||||
@@ -169,10 +169,6 @@ class nsContentSink : public nsICSSLoaderObserver,
|
||||
|
||||
Document* GetDocument() { return mDocument; }
|
||||
|
||||
// Later on we might want to make this more involved somehow
|
||||
// (e.g. stop waiting after some timeout or whatnot).
|
||||
bool WaitForPendingSheets() { return mPendingSheetCount > 0; }
|
||||
|
||||
protected:
|
||||
inline int32_t GetNotificationInterval() {
|
||||
if (mDynamicLowerValue) {
|
||||
@@ -184,6 +180,10 @@ class nsContentSink : public nsICSSLoaderObserver,
|
||||
|
||||
virtual nsresult FlushTags() = 0;
|
||||
|
||||
// Later on we might want to make this more involved somehow
|
||||
// (e.g. stop waiting after some timeout or whatnot).
|
||||
bool WaitForPendingSheets() { return mPendingSheetCount > 0; }
|
||||
|
||||
void DoProcessLinkHeader();
|
||||
|
||||
void StopDeflecting() {
|
||||
|
||||
@@ -2982,59 +2982,6 @@ BrowserParent* nsContentUtils::GetCommonBrowserParentAncestor(
|
||||
});
|
||||
}
|
||||
|
||||
/* static */
|
||||
Element* nsContentUtils::GetTargetElement(Document* aDocument,
|
||||
const nsAString& aAnchorName) {
|
||||
MOZ_ASSERT(aDocument);
|
||||
|
||||
if (aAnchorName.IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
// 1. If there is an element in the document tree that has an ID equal to
|
||||
// fragment, then return the first such element in tree order.
|
||||
if (Element* el = aDocument->GetElementById(aAnchorName)) {
|
||||
return el;
|
||||
}
|
||||
|
||||
// 2. If there is an a element in the document tree that has a name
|
||||
// attribute whose value is equal to fragment, then return the first such
|
||||
// element in tree order.
|
||||
//
|
||||
// FIXME(emilio): Why the different code-paths for HTML and non-HTML docs?
|
||||
if (aDocument->IsHTMLDocument()) {
|
||||
nsCOMPtr<nsINodeList> list = aDocument->GetElementsByName(aAnchorName);
|
||||
// Loop through the named nodes looking for the first anchor
|
||||
uint32_t length = list->Length();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
nsIContent* node = list->Item(i);
|
||||
if (node->IsHTMLElement(nsGkAtoms::a)) {
|
||||
return node->AsElement();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
constexpr auto nameSpace = u"http://www.w3.org/1999/xhtml"_ns;
|
||||
// Get the list of anchor elements
|
||||
nsCOMPtr<nsINodeList> list =
|
||||
aDocument->GetElementsByTagNameNS(nameSpace, u"a"_ns);
|
||||
// Loop through the anchors looking for the first one with the given name.
|
||||
for (uint32_t i = 0; true; i++) {
|
||||
nsIContent* node = list->Item(i);
|
||||
if (!node) { // End of list
|
||||
break;
|
||||
}
|
||||
|
||||
// Compare the name attribute
|
||||
if (node->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
|
||||
aAnchorName, eCaseMatters)) {
|
||||
return node->AsElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Return null.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* static */
|
||||
template <typename FPT, typename FRT, typename SPT, typename SRT>
|
||||
Maybe<int32_t> nsContentUtils::ComparePoints(
|
||||
|
||||
@@ -526,10 +526,6 @@ class nsContentUtils {
|
||||
mozilla::dom::BrowserParent* aBrowserParent1,
|
||||
mozilla::dom::BrowserParent* aBrowserParent2);
|
||||
|
||||
// https://html.spec.whatwg.org/#target-element
|
||||
// https://html.spec.whatwg.org/#find-a-potential-indicated-element
|
||||
static Element* GetTargetElement(Document* aDocument,
|
||||
const nsAString& aAnchorName);
|
||||
/**
|
||||
* Returns true if aNode1 is before aNode2 in the same connected
|
||||
* tree.
|
||||
|
||||
@@ -380,7 +380,8 @@ nsFocusManager::GetActiveBrowsingContext(BrowsingContext** aBrowsingContext) {
|
||||
void nsFocusManager::FocusWindow(nsPIDOMWindowOuter* aWindow,
|
||||
CallerType aCallerType) {
|
||||
if (RefPtr<nsFocusManager> fm = sInstance) {
|
||||
fm->SetFocusedWindowWithCallerType(aWindow, aCallerType);
|
||||
fm->SetFocusedWindowWithCallerType(aWindow, aCallerType,
|
||||
sInstance->GenerateFocusActionId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,19 +402,19 @@ nsFocusManager::GetFocusedContentBrowsingContext(
|
||||
}
|
||||
|
||||
nsresult nsFocusManager::SetFocusedWindowWithCallerType(
|
||||
mozIDOMWindowProxy* aWindowToFocus, CallerType aCallerType) {
|
||||
LOGFOCUS(("<<SetFocusedWindow begin>>"));
|
||||
mozIDOMWindowProxy* aWindowToFocus, CallerType aCallerType,
|
||||
uint64_t aActionId) {
|
||||
LOGFOCUS(("<<SetFocusedWindow begin actionid: %" PRIu64 ">>", aActionId));
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> windowToFocus =
|
||||
nsPIDOMWindowOuter::From(aWindowToFocus);
|
||||
NS_ENSURE_TRUE(windowToFocus, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<Element> frameElement = windowToFocus->GetFrameElementInternal();
|
||||
Maybe<uint64_t> actionIdFromSetFocusInner;
|
||||
if (frameElement) {
|
||||
// pass false for aFocusChanged so that the caret does not get updated
|
||||
// and scrolling does not occur.
|
||||
actionIdFromSetFocusInner = SetFocusInner(frameElement, 0, false, true);
|
||||
SetFocusInner(frameElement, 0, false, true, aActionId);
|
||||
} else {
|
||||
// this is a top-level window. If the window has a child frame focused,
|
||||
// clear the focus. Otherwise, focus should already be in this frame, or
|
||||
@@ -427,21 +428,19 @@ nsresult nsFocusManager::SetFocusedWindowWithCallerType(
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> rootWindow = windowToFocus->GetPrivateRoot();
|
||||
const uint64_t actionId = actionIdFromSetFocusInner.isSome()
|
||||
? actionIdFromSetFocusInner.value()
|
||||
: sInstance->GenerateFocusActionId();
|
||||
if (rootWindow) {
|
||||
RaiseWindow(rootWindow, aCallerType, actionId);
|
||||
RaiseWindow(rootWindow, aCallerType, aActionId);
|
||||
}
|
||||
|
||||
LOGFOCUS(("<<SetFocusedWindow end actionid: %" PRIu64 ">>", actionId));
|
||||
LOGFOCUS(("<<SetFocusedWindow end actionid: %" PRIu64 ">>", aActionId));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFocusManager::SetFocusedWindow(
|
||||
mozIDOMWindowProxy* aWindowToFocus) {
|
||||
return SetFocusedWindowWithCallerType(aWindowToFocus, CallerType::System);
|
||||
return SetFocusedWindowWithCallerType(aWindowToFocus, CallerType::System,
|
||||
GenerateFocusActionId());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@@ -471,7 +470,7 @@ nsFocusManager::SetFocus(Element* aElement, uint32_t aFlags) {
|
||||
|
||||
NS_ENSURE_ARG(aElement);
|
||||
|
||||
SetFocusInner(aElement, aFlags, true, true);
|
||||
SetFocusInner(aElement, aFlags, true, true, GenerateFocusActionId());
|
||||
|
||||
LOGFOCUS(("<<SetFocus end>>"));
|
||||
|
||||
@@ -544,7 +543,7 @@ nsFocusManager::MoveFocus(mozIDOMWindowProxy* aWindow, Element* aStartElement,
|
||||
// would be a problem because the caret would move to the beginning of the
|
||||
// focused link making it impossible to navigate the caret over a link.
|
||||
SetFocusInner(MOZ_KnownLive(newFocus->AsElement()), aFlags,
|
||||
aType != MOVEFOCUS_CARET, true);
|
||||
aType != MOVEFOCUS_CARET, true, GenerateFocusActionId());
|
||||
*aElement = do_AddRef(newFocus->AsElement()).take();
|
||||
} else if (aType == MOVEFOCUS_ROOT || aType == MOVEFOCUS_CARET) {
|
||||
// no content was found, so clear the focus for these two types.
|
||||
@@ -1473,15 +1472,14 @@ static bool IsEmeddededInNoautofocusPopup(BrowsingContext& aBc) {
|
||||
.GetXULBoolAttr(nsGkAtoms::noautofocus);
|
||||
}
|
||||
|
||||
Maybe<uint64_t> nsFocusManager::SetFocusInner(Element* aNewContent,
|
||||
int32_t aFlags,
|
||||
bool aFocusChanged,
|
||||
bool aAdjustWidget) {
|
||||
void nsFocusManager::SetFocusInner(Element* aNewContent, int32_t aFlags,
|
||||
bool aFocusChanged, bool aAdjustWidget,
|
||||
uint64_t aActionId) {
|
||||
// if the element is not focusable, just return and leave the focus as is
|
||||
RefPtr<Element> elementToFocus =
|
||||
FlushAndCheckIfFocusable(aNewContent, aFlags);
|
||||
if (!elementToFocus) {
|
||||
return Nothing();
|
||||
return;
|
||||
}
|
||||
|
||||
const RefPtr<BrowsingContext> focusedBrowsingContext =
|
||||
@@ -1517,7 +1515,7 @@ Maybe<uint64_t> nsFocusManager::SetFocusInner(Element* aNewContent,
|
||||
// focused rather than the frame it is in.
|
||||
if (!newWindow || (newBrowsingContext == GetFocusedBrowsingContext() &&
|
||||
elementToFocus == mFocusedElement)) {
|
||||
return Nothing();
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(newBrowsingContext);
|
||||
@@ -1534,7 +1532,7 @@ Maybe<uint64_t> nsFocusManager::SetFocusInner(Element* aNewContent,
|
||||
BrowsingContext* walk = focusedBrowsingContext;
|
||||
while (walk) {
|
||||
if (walk == bc) {
|
||||
return Nothing();
|
||||
return;
|
||||
}
|
||||
walk = walk->GetParent();
|
||||
}
|
||||
@@ -1551,13 +1549,13 @@ Maybe<uint64_t> nsFocusManager::SetFocusInner(Element* aNewContent,
|
||||
bool inUnload;
|
||||
docShell->GetIsInUnload(&inUnload);
|
||||
if (inUnload) {
|
||||
return Nothing();
|
||||
return;
|
||||
}
|
||||
|
||||
bool beingDestroyed;
|
||||
docShell->IsBeingDestroyed(&beingDestroyed);
|
||||
if (beingDestroyed) {
|
||||
return Nothing();
|
||||
return;
|
||||
}
|
||||
|
||||
BrowsingContext* bc = docShell->GetBrowsingContext();
|
||||
@@ -1572,7 +1570,7 @@ Maybe<uint64_t> nsFocusManager::SetFocusInner(Element* aNewContent,
|
||||
do {
|
||||
bc = bc->GetParent();
|
||||
if (bc && bc->IsDiscarded()) {
|
||||
return Nothing();
|
||||
return;
|
||||
}
|
||||
} while (bc && !bc->IsInProcess());
|
||||
if (bc) {
|
||||
@@ -1618,12 +1616,12 @@ Maybe<uint64_t> nsFocusManager::SetFocusInner(Element* aNewContent,
|
||||
}
|
||||
|
||||
if (!focusedPrincipal || !newPrincipal) {
|
||||
return Nothing();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!focusedPrincipal->Subsumes(newPrincipal)) {
|
||||
NS_WARNING("Not allowed to focus the new window!");
|
||||
return Nothing();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1730,12 +1728,11 @@ Maybe<uint64_t> nsFocusManager::SetFocusInner(Element* aNewContent,
|
||||
LOGFOCUS((" Flags: %x Current Window: %p New Window: %p Current Element: %p",
|
||||
aFlags, mFocusedWindow.get(), newWindow.get(),
|
||||
mFocusedElement.get()));
|
||||
const uint64_t actionId = GenerateFocusActionId();
|
||||
LOGFOCUS(
|
||||
(" In Active Window: %d Moves to different BrowsingContext: %d "
|
||||
"SendFocus: %d actionid: %" PRIu64,
|
||||
isElementInActiveWindow, focusMovesToDifferentBC, sendFocusEvent,
|
||||
actionId));
|
||||
aActionId));
|
||||
|
||||
if (sendFocusEvent) {
|
||||
Maybe<BlurredElementInfo> blurredInfo;
|
||||
@@ -1788,19 +1785,19 @@ Maybe<uint64_t> nsFocusManager::SetFocusInner(Element* aNewContent,
|
||||
? focusedBrowsingContext.get()
|
||||
: nullptr),
|
||||
commonAncestor, focusMovesToDifferentBC, aAdjustWidget,
|
||||
remainActive, actionId, elementToFocus)) {
|
||||
return Some(actionId);
|
||||
remainActive, aActionId, elementToFocus)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Focus(newWindow, elementToFocus, aFlags, focusMovesToDifferentBC,
|
||||
aFocusChanged, false, aAdjustWidget, actionId, blurredInfo);
|
||||
aFocusChanged, false, aAdjustWidget, aActionId, blurredInfo);
|
||||
} else {
|
||||
// otherwise, for inactive windows and when the caller cannot steal the
|
||||
// focus, update the node in the window, and raise the window if desired.
|
||||
if (allowFrameSwitch) {
|
||||
AdjustWindowFocus(newBrowsingContext, true, IsWindowVisible(newWindow),
|
||||
actionId);
|
||||
aActionId);
|
||||
}
|
||||
|
||||
// set the focus node and method as needed
|
||||
@@ -1832,7 +1829,7 @@ Maybe<uint64_t> nsFocusManager::SetFocusInner(Element* aNewContent,
|
||||
RaiseWindow(outerWindow,
|
||||
aFlags & FLAG_NONSYSTEMCALLER ? CallerType::NonSystem
|
||||
: CallerType::System,
|
||||
actionId);
|
||||
aActionId);
|
||||
} else {
|
||||
mozilla::dom::ContentChild* contentChild =
|
||||
mozilla::dom::ContentChild::GetSingleton();
|
||||
@@ -1841,12 +1838,11 @@ Maybe<uint64_t> nsFocusManager::SetFocusInner(Element* aNewContent,
|
||||
aFlags & FLAG_NONSYSTEMCALLER
|
||||
? CallerType::NonSystem
|
||||
: CallerType::System,
|
||||
actionId);
|
||||
aActionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Some(actionId);
|
||||
}
|
||||
|
||||
static already_AddRefed<BrowsingContext> GetParentIgnoreChromeBoundary(
|
||||
|
||||
@@ -214,7 +214,8 @@ class nsFocusManager final : public nsIFocusManager,
|
||||
* Setter for focusedWindow with CallerType
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT nsresult SetFocusedWindowWithCallerType(
|
||||
mozIDOMWindowProxy* aWindowToFocus, mozilla::dom::CallerType aCallerType);
|
||||
mozIDOMWindowProxy* aWindowToFocus, mozilla::dom::CallerType aCallerType,
|
||||
uint64_t aActionId);
|
||||
|
||||
/**
|
||||
* Given an element, which must be the focused element, activate the remote
|
||||
@@ -313,13 +314,10 @@ class nsFocusManager final : public nsIFocusManager,
|
||||
*
|
||||
* All actual focus changes must use this method to do so. (as opposed
|
||||
* to those that update the focus in an inactive window for instance).
|
||||
*
|
||||
* Returns Nothing() if we end up not trying to focus the element,
|
||||
* otherwise returns the generated action id.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT Maybe<uint64_t> SetFocusInner(
|
||||
mozilla::dom::Element* aNewContent, int32_t aFlags, bool aFocusChanged,
|
||||
bool aAdjustWidget);
|
||||
MOZ_CAN_RUN_SCRIPT void SetFocusInner(mozilla::dom::Element* aNewContent,
|
||||
int32_t aFlags, bool aFocusChanged,
|
||||
bool aAdjustWidget, uint64_t aActionId);
|
||||
|
||||
/**
|
||||
* Returns true if aPossibleAncestor is the same as aWindow or an
|
||||
|
||||
@@ -216,7 +216,7 @@ nsresult nsStyledElement::BindToTree(BindContext& aContext, nsINode& aParent) {
|
||||
|
||||
if (HasAttr(nsGkAtoms::autofocus) && aContext.AllowsAutoFocus() &&
|
||||
(!IsSVGElement() || IsFocusable())) {
|
||||
aContext.OwnerDoc().ElementWithAutoFocusInserted(this);
|
||||
aContext.OwnerDoc().SetAutoFocusElement(this);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
@@ -114,7 +114,6 @@ class HTMLContentSink : public nsContentSink, public nsIHTMLContentSink {
|
||||
virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding) override;
|
||||
virtual nsISupports* GetTarget() override;
|
||||
virtual bool IsScriptExecuting() override;
|
||||
virtual bool WaitForPendingSheets() override;
|
||||
virtual void ContinueInterruptedParsingAsync() override;
|
||||
|
||||
// nsIHTMLContentSink
|
||||
@@ -925,10 +924,6 @@ void HTMLContentSink::ContinueInterruptedParsingIfEnabled() {
|
||||
}
|
||||
}
|
||||
|
||||
bool HTMLContentSink::WaitForPendingSheets() {
|
||||
return nsContentSink::WaitForPendingSheets();
|
||||
}
|
||||
|
||||
void HTMLContentSink::ContinueInterruptedParsingAsync() {
|
||||
nsCOMPtr<nsIRunnable> ev = NewRunnableMethod(
|
||||
"HTMLContentSink::ContinueInterruptedParsingIfEnabled", this,
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
<html>
|
||||
<link rel='stylesheet' type='text/css' href='style.css'>
|
||||
<body>
|
||||
<input autofocus><textarea></textarea><select></select><button></button>
|
||||
<input><textarea></textarea><select></select><button></button>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -25,13 +25,6 @@ add_task(async function() {
|
||||
backgroundTab.linkedBrowser,
|
||||
[],
|
||||
async function() {
|
||||
// Spec asks us to flush autofocus candidates in the
|
||||
// `update-the-rendering` step, so we need to wait
|
||||
// for a rAF to ensure autofocus candidates are
|
||||
// flushed.
|
||||
await new Promise(r => {
|
||||
content.requestAnimationFrame(r);
|
||||
});
|
||||
return content.document.activeElement.tagName;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1850,9 +1850,7 @@ nsresult PresShell::Initialize() {
|
||||
NS_ENSURE_STATE(!mHaveShutDown);
|
||||
}
|
||||
|
||||
if (mDocument->HasAutoFocusCandidates()) {
|
||||
mDocument->ScheduleFlushAutoFocusCandidates();
|
||||
}
|
||||
mDocument->TriggerAutoFocus();
|
||||
|
||||
NS_ASSERTION(rootFrame, "How did that happen?");
|
||||
|
||||
@@ -3138,8 +3136,52 @@ nsresult PresShell::GoToAnchor(const nsAString& aAnchorName, bool aScroll,
|
||||
//
|
||||
// https://html.spec.whatwg.org/#target-element
|
||||
// https://html.spec.whatwg.org/#find-a-potential-indicated-element
|
||||
RefPtr<Element> target =
|
||||
nsContentUtils::GetTargetElement(mDocument, aAnchorName);
|
||||
RefPtr<Element> target = [&]() -> Element* {
|
||||
// 1. If there is an element in the document tree that has an ID equal to
|
||||
// fragment, then return the first such element in tree order.
|
||||
if (Element* el = mDocument->GetElementById(aAnchorName)) {
|
||||
return el;
|
||||
}
|
||||
|
||||
// 2. If there is an a element in the document tree that has a name
|
||||
// attribute whose value is equal to fragment, then return the first such
|
||||
// element in tree order.
|
||||
//
|
||||
// FIXME(emilio): Why the different code-paths for HTML and non-HTML docs?
|
||||
if (mDocument->IsHTMLDocument()) {
|
||||
nsCOMPtr<nsINodeList> list = mDocument->GetElementsByName(aAnchorName);
|
||||
// Loop through the named nodes looking for the first anchor
|
||||
uint32_t length = list->Length();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
nsIContent* node = list->Item(i);
|
||||
if (node->IsHTMLElement(nsGkAtoms::a)) {
|
||||
return node->AsElement();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
constexpr auto nameSpace = u"http://www.w3.org/1999/xhtml"_ns;
|
||||
// Get the list of anchor elements
|
||||
nsCOMPtr<nsINodeList> list =
|
||||
mDocument->GetElementsByTagNameNS(nameSpace, u"a"_ns);
|
||||
// Loop through the anchors looking for the first one with the given name.
|
||||
for (uint32_t i = 0; true; i++) {
|
||||
nsIContent* node = list->Item(i);
|
||||
if (!node) { // End of list
|
||||
break;
|
||||
}
|
||||
|
||||
// Compare the name attribute
|
||||
if (node->IsElement() &&
|
||||
node->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
|
||||
aAnchorName, eCaseMatters)) {
|
||||
return node->AsElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Return null.
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
// 1. If there is no indicated part of the document, set the Document's
|
||||
// target element to null.
|
||||
|
||||
@@ -1843,7 +1843,6 @@ uint32_t nsRefreshDriver::ObserverCount() const {
|
||||
sum += mViewManagerFlushIsPending;
|
||||
sum += mEarlyRunners.Length();
|
||||
sum += mTimerAdjustmentObservers.Length();
|
||||
sum += mAutoFocusFlushDocuments.Length();
|
||||
return sum;
|
||||
}
|
||||
|
||||
@@ -1864,7 +1863,7 @@ bool nsRefreshDriver::HasObservers() const {
|
||||
!mPendingFullscreenEvents.IsEmpty() ||
|
||||
!mFrameRequestCallbackDocs.IsEmpty() ||
|
||||
!mThrottledFrameRequestCallbackDocs.IsEmpty() ||
|
||||
!mAutoFocusFlushDocuments.IsEmpty() || !mEarlyRunners.IsEmpty();
|
||||
!mEarlyRunners.IsEmpty();
|
||||
}
|
||||
|
||||
void nsRefreshDriver::AppendObserverDescriptionsToString(
|
||||
@@ -1906,10 +1905,6 @@ void nsRefreshDriver::AppendObserverDescriptionsToString(
|
||||
aStr.AppendPrintf("%zux Throttled frame request callback doc, ",
|
||||
mThrottledFrameRequestCallbackDocs.Length());
|
||||
}
|
||||
if (!mAutoFocusFlushDocuments.IsEmpty()) {
|
||||
aStr.AppendPrintf("%zux AutoFocus flush doc, ",
|
||||
mAutoFocusFlushDocuments.Length());
|
||||
}
|
||||
if (!mEarlyRunners.IsEmpty()) {
|
||||
aStr.AppendPrintf("%zux Early runner, ", mEarlyRunners.Length());
|
||||
}
|
||||
@@ -2139,24 +2134,6 @@ static void TakeFrameRequestCallbacksFrom(
|
||||
aDocument->TakeFrameRequestCallbacks(aTarget.LastElement().mCallbacks);
|
||||
}
|
||||
|
||||
void nsRefreshDriver::ScheduleAutoFocusFlush(Document* aDocument) {
|
||||
MOZ_ASSERT(!mAutoFocusFlushDocuments.Contains(aDocument));
|
||||
mAutoFocusFlushDocuments.AppendElement(aDocument);
|
||||
EnsureTimerStarted();
|
||||
}
|
||||
|
||||
void nsRefreshDriver::FlushAutoFocusDocuments() {
|
||||
nsTArray<RefPtr<Document>> docs(std::move(mAutoFocusFlushDocuments));
|
||||
|
||||
for (const auto& doc : docs) {
|
||||
MOZ_KnownLive(doc)->FlushAutoFocusCandidates();
|
||||
}
|
||||
}
|
||||
|
||||
void nsRefreshDriver::CancelFlushAutoFocus(Document* aDocument) {
|
||||
mAutoFocusFlushDocuments.RemoveElement(aDocument);
|
||||
}
|
||||
|
||||
// https://fullscreen.spec.whatwg.org/#run-the-fullscreen-steps
|
||||
void nsRefreshDriver::RunFullscreenSteps() {
|
||||
// Swap out the current pending events
|
||||
@@ -2597,7 +2574,6 @@ void nsRefreshDriver::Tick(VsyncId aId, TimeStamp aNowTime,
|
||||
if (i == 1) {
|
||||
// This is the FlushType::Style case.
|
||||
|
||||
FlushAutoFocusDocuments();
|
||||
DispatchScrollEvents();
|
||||
DispatchVisualViewportScrollEvents();
|
||||
DispatchAnimationEvents();
|
||||
|
||||
@@ -346,8 +346,6 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
|
||||
|
||||
bool IsWaitingForPaint(mozilla::TimeStamp aTime);
|
||||
|
||||
void ScheduleAutoFocusFlush(Document* aDocument);
|
||||
|
||||
// nsARefreshObserver
|
||||
NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override {
|
||||
return TransactionIdAllocator::AddRef();
|
||||
@@ -449,8 +447,6 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
|
||||
// paints to one per vsync (see CanDoExtraTick).
|
||||
void FinishedVsyncTick() { mAttemptedExtraTickSinceLastVsync = false; }
|
||||
|
||||
void CancelFlushAutoFocus(Document* aDocument);
|
||||
|
||||
private:
|
||||
typedef nsTArray<RefPtr<VVPResizeEvent>> VisualViewportResizeEventArray;
|
||||
typedef nsTArray<RefPtr<mozilla::Runnable>> ScrollEventArray;
|
||||
@@ -478,8 +474,6 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
|
||||
operator RefPtr<nsARefreshObserver>() { return mObserver; }
|
||||
};
|
||||
typedef nsTObserverArray<ObserverData> ObserverArray;
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void FlushAutoFocusDocuments();
|
||||
void RunFullscreenSteps();
|
||||
void DispatchAnimationEvents();
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
@@ -675,7 +669,6 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
|
||||
// nsTArray on purpose, because we want to be able to swap.
|
||||
nsTArray<Document*> mFrameRequestCallbackDocs;
|
||||
nsTArray<Document*> mThrottledFrameRequestCallbackDocs;
|
||||
nsTArray<RefPtr<Document>> mAutoFocusFlushDocuments;
|
||||
nsTObserverArray<nsAPostRefreshObserver*> mPostRefreshObservers;
|
||||
nsTArray<mozilla::UniquePtr<mozilla::PendingFullscreenEvent>>
|
||||
mPendingFullscreenEvents;
|
||||
|
||||
@@ -131,8 +131,6 @@ class nsHtml5TreeOpExecutor final
|
||||
*/
|
||||
void WillResume() override;
|
||||
|
||||
virtual nsIContentSink* AsExecutor() override { return this; }
|
||||
|
||||
virtual void InitialTranslationCompleted() override;
|
||||
|
||||
/**
|
||||
|
||||
@@ -89,12 +89,6 @@ class nsIContentSink : public nsISupports {
|
||||
*/
|
||||
virtual void WillResume() = 0;
|
||||
|
||||
/**
|
||||
* This method returns nullptr unless `this` can
|
||||
* be cast as nsHtml5TreeOpExecutor.
|
||||
*/
|
||||
virtual nsIContentSink* AsExecutor() { return nullptr; }
|
||||
|
||||
/**
|
||||
* This method gets called by the parser so that the content
|
||||
* sink can retain a reference to the parser. The expectation
|
||||
|
||||
@@ -83,12 +83,6 @@ class nsIHTMLContentSink : public nsIContentSink {
|
||||
* @param aTag - The tag to be closed.
|
||||
*/
|
||||
NS_IMETHOD CloseContainer(ElementType aTag) = 0;
|
||||
|
||||
/**
|
||||
* This method returns true if there are more than one
|
||||
* pending style sheets, false otherwise.
|
||||
*/
|
||||
virtual bool WaitForPendingSheets() = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIHTMLContentSink, NS_IHTML_CONTENT_SINK_IID)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[autofocus-dialog.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[<dialog> can contain autofocus, without stopping page autofocus content from working]
|
||||
expected: FAIL
|
||||
@@ -0,0 +1,3 @@
|
||||
[autofocus-in-not-fully-active-document.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
@@ -0,0 +1,5 @@
|
||||
[autofocus-on-stable-document.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Autofocus should work if an element with autofocus is inserted into a document which was loaded some time ago.]
|
||||
expected: FAIL
|
||||
@@ -0,0 +1,8 @@
|
||||
[document-with-fragment-empty.html]
|
||||
[Autofocus elements in iframed documents with empty fragments should work.]
|
||||
expected:
|
||||
if not debug and (os == "win") and (processor == "x86"): [FAIL, PASS]
|
||||
if debug and (os == "android"): PASS
|
||||
if debug and (os == "mac"): PASS
|
||||
if debug and (os == "linux"): PASS
|
||||
[PASS, FAIL]
|
||||
@@ -0,0 +1,6 @@
|
||||
[document-with-fragment-nonexistent.html]
|
||||
[Autofocus elements in iframed documents with non-existent fragments should work.]
|
||||
expected:
|
||||
if debug and (os == "linux"): PASS
|
||||
if debug and (os == "android"): PASS
|
||||
[PASS, FAIL]
|
||||
@@ -0,0 +1,7 @@
|
||||
[document-with-fragment-top.html]
|
||||
[Autofocus elements in iframed documents with "top" fragments should work.]
|
||||
expected:
|
||||
if debug and (os == "android"): PASS
|
||||
if debug and (os == "linux"): PASS
|
||||
if debug and (os == "mac"): PASS
|
||||
[PASS, FAIL]
|
||||
@@ -0,0 +1,5 @@
|
||||
[first-reconnected.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[The second autofocus element wins if the first autofocus element was disconnected and reconnected before flushing the autofocus candidates.]
|
||||
expected: FAIL
|
||||
@@ -0,0 +1,3 @@
|
||||
[first-when-later-but-before.html]
|
||||
[The temporally first autofocus in the document wins, even if an element is inserted later that is previous in the document tree.]
|
||||
expected: [PASS, FAIL]
|
||||
@@ -0,0 +1,3 @@
|
||||
[first-when-later.html]
|
||||
[The first autofocus in the document wins, even if elements are inserted later.]
|
||||
expected: [PASS, FAIL]
|
||||
@@ -0,0 +1,3 @@
|
||||
[first.html]
|
||||
[The first autofocus element in the document should win.]
|
||||
expected: [PASS, FAIL]
|
||||
@@ -0,0 +1,5 @@
|
||||
[focusable-area-in-top-document.html]
|
||||
[If topDocument's focused area is not topDocument, autofocus is not processed.]
|
||||
expected:
|
||||
if (processor == "x86") and (os == "linux"): [FAIL, PASS]
|
||||
[PASS, FAIL]
|
||||
@@ -0,0 +1,3 @@
|
||||
[no-autofocus-on-changing-input-type.html]
|
||||
[Changing input type should not refocus on the element.]
|
||||
expected: [PASS, FAIL]
|
||||
@@ -0,0 +1,3 @@
|
||||
[no-cross-origin-autofocus.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
@@ -0,0 +1,3 @@
|
||||
[no-sandboxed-automatic-features.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
@@ -0,0 +1,3 @@
|
||||
[not-on-first-task.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
@@ -0,0 +1,8 @@
|
||||
[queue-non-focusable.html]
|
||||
[If the first autofocus element is not focusable, but becomes focusable before a frame, it should be focused.]
|
||||
expected:
|
||||
if debug and (os == "win") and swgl: PASS
|
||||
if debug and (os == "android"): PASS
|
||||
if debug and (os == "linux"): PASS
|
||||
if debug and (os == "mac"): PASS
|
||||
[PASS, FAIL]
|
||||
@@ -0,0 +1,5 @@
|
||||
[same-origin-autofocus.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Autofocus should not work in the same origin grand child iframe]
|
||||
expected: FAIL
|
||||
@@ -0,0 +1,3 @@
|
||||
[skip-another-top-level-browsing-context.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
@@ -0,0 +1,5 @@
|
||||
[skip-non-focusable.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Non-focusable autofocus element is skipped.]
|
||||
expected: FAIL
|
||||
@@ -0,0 +1,3 @@
|
||||
[skip-not-fully-active.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
@@ -0,0 +1,5 @@
|
||||
[spin-by-blocking-style-sheet.html]
|
||||
expected: TIMEOUT
|
||||
[Script-blocking style sheet should pause flushing autofocus candidates.]
|
||||
expected: TIMEOUT
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
[supported-elements.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Contenteditable element should support autofocus]
|
||||
expected: FAIL
|
||||
|
||||
[Element with tabindex should support autofocus]
|
||||
expected: FAIL
|
||||
|
||||
[Host element with delegatesFocus including no focusable descendants should be skipped]
|
||||
expected: FAIL
|
||||
|
||||
[Area element should support autofocus]
|
||||
expected: FAIL
|
||||
|
||||
[Host element with delegatesFocus should support autofocus]
|
||||
expected: FAIL
|
||||
@@ -2,4 +2,4 @@
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
["Flush autofocus candidates" should be happen before a scroll event and animation frame callbacks]
|
||||
expected: [PASS, FAIL]
|
||||
expected: FAIL
|
||||
|
||||
@@ -10,12 +10,9 @@
|
||||
|
||||
promise_test(async () => {
|
||||
await waitForLoad(window);
|
||||
const iframe = document.querySelector('iframe');
|
||||
await waitUntilStableAutofocusState();
|
||||
assert_equals(document.activeElement, iframe,
|
||||
assert_equals(document.activeElement, document.querySelector('iframe'),
|
||||
'Autofocus elements in iframes should be focused.');
|
||||
const doc = iframe.contentDocument;
|
||||
assert_true(!doc.querySelector(':target'));
|
||||
|
||||
let input = document.createElement('input');
|
||||
input.autofocus = true;
|
||||
|
||||
@@ -21,23 +21,7 @@ promise_test(async () => {
|
||||
doc.body.appendChild(input);
|
||||
await waitUntilStableAutofocusState();
|
||||
assert_not_equals(doc.activeElement, input);
|
||||
iframe.remove();
|
||||
}, 'Autofocus elements in iframed documents with URL fragments should be skipped. (id matches)');
|
||||
|
||||
promise_test(async () => {
|
||||
let iframe = await waitForIframeLoad("resources/frame-with-a.html");
|
||||
iframe.contentWindow.location.hash = 'anchor1';
|
||||
await waitForEvent(iframe.contentWindow, 'hashchange');
|
||||
const doc = iframe.contentDocument;
|
||||
assert_true(!!doc.querySelector(':target'));
|
||||
|
||||
let input = doc.createElement('input');
|
||||
input.autofocus = true;
|
||||
doc.body.appendChild(input);
|
||||
await waitUntilStableAutofocusState();
|
||||
assert_not_equals(doc.activeElement, input);
|
||||
iframe.remove();
|
||||
}, 'Autofocus elements in iframed documents with URL fragments should be skipped.(a element)');
|
||||
}, 'Autofocus elements in iframed documents with URL fragments should be skipped.');
|
||||
|
||||
promise_test(async () => {
|
||||
let w = window.open('resources/frame-with-anchor.html');
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<body>
|
||||
<a name="anchor1"></a>
|
||||
</body>
|
||||
@@ -39,13 +39,3 @@ async function waitUntilStableAutofocusState(w) {
|
||||
// Awaiting one animation frame is an easy way to determine autofocus state.
|
||||
await waitForAnimationFrame(targetWindow);
|
||||
}
|
||||
|
||||
async function waitForIframeLoad(src, w = window) {
|
||||
const iframe = w.document.createElement("iframe");
|
||||
let loadPromise = new Promise(resolve => {
|
||||
iframe.addEventListener("load", () => resolve(iframe));
|
||||
});
|
||||
iframe.src = src;
|
||||
w.document.body.appendChild(iframe);
|
||||
return loadPromise;
|
||||
}
|
||||
|
||||
@@ -2,18 +2,16 @@
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/utils.js"></script>
|
||||
<link rel="stylesheet" href="resources/erase-first.css?pipe=trickle(d1)">
|
||||
|
||||
<input id="first" autofocus>
|
||||
<input id="second" autofocus>
|
||||
|
||||
<link rel="stylesheet" href="resources/erase-first.css?pipe=trickle(d1)">
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
promise_test(async () => {
|
||||
await waitForLoad(window);
|
||||
await waitForAnimationFrame();
|
||||
await waitForEvent(document.body, 'focus', {capture:true});
|
||||
assert_equals(document.activeElement.id, 'second');
|
||||
}, 'Script-blocking style sheet should pause flushing autofocus candidates.');
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user