My understanding of the problem is as follows. We create the main content document, first it is about:blank in a content process. When the bug happens the about:blank document has WindowRaised called on it and this makes it the active window, and then it tells the parent process that it is the active browsing context (via SendSetActiveBrowsingContext). When the bug doesn't happen this doesn't happen, perhaps because we navigate away from about:blank before it can happen.
So the browsing context navigates to the new document and it gets moved to a different content process. BrowsingContextGroup::EnsureSubscribed is called, if the parent process got told of the active document above then we call SendSetupFocusedAndActive (if it didn't then the active browsing context remains null and so it doesn't call SendSetupFocusedAndActive). When the child gets RecvSetupFocusedAndActive it calls SetActiveBrowsingContextFromOtherProcess on the focus manager.
nsFocusManager::WindowRaised is called for the new document, we bail early because of this line
https://searchfox.org/mozilla-central/rev/d5b34cc8872177d3ee071e06f787c2a14268595b/dom/base/nsFocusManager.cpp#661
because we are the browsing context that was set from another process. And so we fail to make the Focus call at the end of that function. So mFocusedWindow remains null in the child process.
The nsFocusManager::WindowShown call that happens for every new document load thus does not do anything because this line
https://searchfox.org/mozilla-central/rev/d5b34cc8872177d3ee071e06f787c2a14268595b/dom/base/nsFocusManager.cpp#906
always fails because mFocusedWindow is null and it never changes.
Differential Revision: https://phabricator.services.mozilla.com/D65302
The heuristic is that we show focus outlines for unknown or key focus, and not
for mouse / touch.
This is probably not the final heuristic we take, but this allows people to play
with it and file bugs.
Once this is mature enough we should remove :-moz-focusring in favor of
:focus-visible.
Differential Revision: https://phabricator.services.mozilla.com/D63861
This covers most cycle collected objects which support weak references, but
not the ones which inherit from a cycle collected class and don't do any cycle
collection on their own.
Differential Revision: https://phabricator.services.mozilla.com/D63962
The heuristic is that we show focus outlines for unknown or key focus, and not
for mouse / touch.
This is probably not the final heuristic we take, but this allows people to play
with it and file bugs.
Once this is mature enough we should remove :-moz-focusring in favor of
:focus-visible.
Differential Revision: https://phabricator.services.mozilla.com/D63861
The original check, `currentContent != startContent`, is to skip the element we started on in frame traversal.
This would happen for instance on a scrollable element, where frame traversal could return the element again.
However, in shadow dom case, the frame traversal may start on a redirected shadow host, where `startContent` is still the original start element.
Differential Revision: https://phabricator.services.mozilla.com/D61566
The checks for `*TopLevelScopeOwner` are to skip the scope that we have already checked.
But when the shadow host is scrollable, we will traverse anonymous children for the scroll frame first in frame traversal and `oldTopLevelScopeOwner` will be reset.
Then we don't realize that we have already checked the host's scope.
Differential Revision: https://phabricator.services.mozilla.com/D60923
The original check, `currentContent != startContent`, is to skip the element we started on in frame traversal.
This would happen for instance on a scrollable element, where frame traversal could return the element again.
However, in shadow dom case, the frame traversal may start on a redirected shadow host, where `startContent` is still the original start element.
Differential Revision: https://phabricator.services.mozilla.com/D61566
The checks for `*TopLevelScopeOwner` are to skip the scope that we have already checked.
But when the shadow host is scrollable, we will traverse anonymous children for the scroll frame first in frame traversal and `oldTopLevelScopeOwner` will be reset.
Then we don't realize that we have already checked the host's scope.
Differential Revision: https://phabricator.services.mozilla.com/D60923
This was missing a check and as a result we were hanging. The simplified setup
is as follows:
<dialog>
#shadow-root
<panel>
<!-- nothing focusable here -->
And chrome code calling advanceFocusIntoSubtree with <panel> as the start
content.
We first try starting at <panel>, then from the root. It's in this second try
where we fail to find anything into the <panel> subtree, but we don't realize we
wrapped around and should stop.
I think we should really look into unifying the shadow dom and non-shadow dom
focus code, these bugs are somewhat nasty :/
I don't think this is observable from the web because this second iteration
happens from here:
* https://searchfox.org/mozilla-central/rev/220a3bd6063fcbe5ca50e88dcabdc7dee0aca448/dom/base/nsFocusManager.cpp#2916
And in the web case we'd hit the TabToTreeOwner call above...
Differential Revision: https://phabricator.services.mozilla.com/D61075
Instead, subclass nsTextControlFrame. This simplifies the code and avoids
correctness issues.
I kept the localization functionality though it is not spec compliant. But I
filed a bug to remove it in a followup.
Differential Revision: https://phabricator.services.mozilla.com/D57193
Instead, subclass nsTextControlFrame. This simplifies the code and avoids
correctness issues.
I kept the localization functionality though it is not spec compliant. But I
filed a bug to remove it in a followup.
Differential Revision: https://phabricator.services.mozilla.com/D57193
This patch contains three changes, but we just simpliy the logic, the result is the same,
1). s/oldTopLevelScopeOwner/currentTopLevelScopeOwner/
We can use either `oldTopLevelScopeOwner` or `currentTopLevelScopeOwner` in if-check, they point to the same element at that point.
Using `currentTopLevelScopeOwner` is clearer given that it is updated in the if-block.
2). remove else-block
We run into this else-block when `aForward && oldTopLevelScopeOwner == currentContent`,
so `oldTopLevelScopeOwner`, `currentTopLevelScopeOwner` and `currentContent` all point to the same element.
It is not necessary to set `currentTopLevelScopeOwner` to `currentContent` again.
3). s/IsHostOrSlot(currentTopLevelScopeOwner)/currentTopLevelScopeOwner/
After above two changes, `currentTopLevelScopeOwner` is always set to result of `GetTopLevelScopeOwner(currentContent)`,
so we don't need `IsHostOrSlot()` checks. And there is an asserion in `HostOrSlotTabIndexValue()` to ensure it is either a host or slot.
Differential Revision: https://phabricator.services.mozilla.com/D58810
Currently if we call `GetTopLevelScopeOwner` with a <slot> which is in top-level-scope, e.g. `<body><slot></slot></body>`.
It returns <slot> itself, but it should returns `nullptr` per design.
Differential Revision: https://phabricator.services.mozilla.com/D58805
After bug 1544826, `FindOwner` returns only shadow host or slot, update the
comment and rename it to `FindScopeOwner` to reflect the current behavior.
Differential Revision: https://phabricator.services.mozilla.com/D58578
This matches other browsers.
Keep the restriction just to chrome nodes, and in that case, avoid getting into
the broken state, which is what causes the issue. I'm not sure if this even
matters anymore given e10s but...
Differential Revision: https://phabricator.services.mozilla.com/D57475
We are going to introduce a new function in Document in this commit series,
which enumerates all child documents regardless of whether it's in the same
process, in content processes or in out-of-process iframes. The function takes
std::functions, but I don't have any good ideas to convert lambda functions with
capturing variables to function pointer.
Differential Revision: https://phabricator.services.mozilla.com/D57434
We are going to introduce a new function in Document in this commit series,
which enumerates all child documents regardless of whether it's in the same
process, in content processes or in out-of-process iframes. The function takes
std::functions, but I don't have any good ideas to convert lambda functions with
capturing variables to function pointer.
Differential Revision: https://phabricator.services.mozilla.com/D57434
The inclusions were removed with the following very crude script and the
resulting breakage was fixed up by hand. The manual fixups did either
revert the changes done by the script, replace a generic header with a more
specific one or replace a header with a forward declaration.
find . -name "*.idl" | grep -v web-platform | grep -v third_party | while read path; do
interfaces=$(grep "^\(class\|interface\).*:.*" "$path" | cut -d' ' -f2)
if [ -n "$interfaces" ]; then
if [[ "$interfaces" == *$'\n'* ]]; then
regexp="\("
for i in $interfaces; do regexp="$regexp$i\|"; done
regexp="${regexp%%\\\|}\)"
else
regexp="$interfaces"
fi
interface=$(basename "$path")
rg -l "#include.*${interface%%.idl}.h" . | while read path2; do
hits=$(grep -v "#include.*${interface%%.idl}.h" "$path2" | grep -c "$regexp" )
if [ $hits -eq 0 ]; then
echo "Removing ${interface} from ${path2}"
grep -v "#include.*${interface%%.idl}.h" "$path2" > "$path2".tmp
mv -f "$path2".tmp "$path2"
fi
done
fi
done
Differential Revision: https://phabricator.services.mozilla.com/D55442