Bug 1556627 - Make nsFocusManager::SetFocus work in Fission. r=NeilDeakin,farre,masayuki

Differential Revision: https://phabricator.services.mozilla.com/D55651

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Henri Sivonen 2020-02-18 13:30:04 +00:00
Родитель 759c48f75e
Коммит ac7d3f7b2a
26 изменённых файлов: 1276 добавлений и 257 удалений

Просмотреть файл

@ -87,6 +87,7 @@ support-files = file_anchor_elements.html
skip-if = (verify && (os == 'win' || os == 'mac'))
[browser_preloadedBrowser_zoom.js]
[browser_progress_keyword_search_handling.js]
skip-if = fission #Bug 1613589
[browser_reload_deleted_file.js]
skip-if = (debug && os == 'mac') || (debug && os == 'linux' && bits == 64) #Bug 1421183, disabled on Linux/OSX for leaked windows
[browser_tabCloseSpacer.js]

Просмотреть файл

@ -186,6 +186,7 @@ skip-if = !e10s || !crashreporter # the tab's process is killed during the test.
[browser_ext_runtime_openOptionsPage.js]
[browser_ext_runtime_openOptionsPage_uninstall.js]
[browser_ext_search.js]
skip-if = fission #Bug 1613590
[browser_ext_search_favicon.js]
[browser_ext_runtime_setUninstallURL.js]
[browser_ext_sessions_forgetClosedTab.js]

Просмотреть файл

@ -459,6 +459,13 @@ void BrowsingContext::Detach(bool aFromIPC) {
mGroup->Unregister(this);
mIsDiscarded = true;
if (XRE_IsParentProcess()) {
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
fm->BrowsingContextDetached(this);
}
}
if (nsCOMPtr<nsIObserverService> obs = services::GetObserverService()) {
obs->NotifyObservers(ToSupports(this), "browsing-context-discarded",
nullptr);
@ -577,6 +584,9 @@ void BrowsingContext::UnregisterWindowContext(WindowContext* aWindow) {
// double-check.
if (aWindow == mCurrentWindowContext) {
mCurrentWindowContext = nullptr;
if (XRE_IsParentProcess()) {
BrowserParent::UpdateFocusFromBrowsingContext();
}
}
}
@ -1421,6 +1431,9 @@ bool BrowsingContext::CanSet(FieldIndex<IDX_CurrentInnerWindowId>,
void BrowsingContext::DidSet(FieldIndex<IDX_CurrentInnerWindowId>) {
mCurrentWindowContext = WindowContext::GetById(GetCurrentInnerWindowId());
if (XRE_IsParentProcess()) {
BrowserParent::UpdateFocusFromBrowsingContext();
}
}
bool BrowsingContext::CanSet(FieldIndex<IDX_IsPopupSpam>, const bool& aValue,

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/dom/ContentParent.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/ThrottledEventQueue.h"
#include "nsFocusManager.h"
namespace mozilla {
namespace dom {
@ -66,11 +67,27 @@ void BrowsingContextGroup::EnsureSubscribed(ContentParent* aProcess) {
Subscribe(aProcess);
bool sendFocused = false;
bool sendActive = false;
BrowsingContext* focused = nullptr;
BrowsingContext* active = nullptr;
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
focused = fm->GetFocusedBrowsingContextInChrome();
active = fm->GetActiveBrowsingContextInChrome();
}
nsTArray<BrowsingContext::IPCInitializer> inits(mContexts.Count());
nsTArray<WindowContext::IPCInitializer> windowInits(mContexts.Count());
auto addInits = [&](BrowsingContext* aContext) {
inits.AppendElement(aContext->GetIPCInitializer());
if (focused == aContext) {
sendFocused = true;
}
if (active == aContext) {
sendActive = true;
}
for (auto& window : aContext->GetWindowContexts()) {
windowInits.AppendElement(window->GetIPCInitializer());
}
@ -96,6 +113,11 @@ void BrowsingContextGroup::EnsureSubscribed(ContentParent* aProcess) {
// Send all of our contexts to the target content process.
Unused << aProcess->SendRegisterBrowsingContextGroup(inits, windowInits);
if (sendActive || sendFocused) {
Unused << aProcess->SendSetupFocusedAndActive(
sendFocused ? focused : nullptr, sendActive ? active : nullptr);
}
}
bool BrowsingContextGroup::IsContextCached(BrowsingContext* aContext) const {

Просмотреть файл

@ -6,6 +6,7 @@
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/dom/BrowsingContextGroup.h"
#include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/dom/ContentProcessManager.h"

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -31,6 +31,8 @@ namespace dom {
class Element;
struct FocusOptions;
class BrowserParent;
class ContentChild;
class ContentParent;
} // namespace dom
} // namespace mozilla
@ -46,6 +48,8 @@ class nsFocusManager final : public nsIFocusManager,
public nsSupportsWeakReference {
typedef mozilla::widget::InputContextAction InputContextAction;
typedef mozilla::dom::Document Document;
friend class mozilla::dom::ContentChild;
friend class mozilla::dom::ContentParent;
public:
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFocusManager, nsIFocusManager)
@ -93,11 +97,42 @@ class nsFocusManager final : public nsIFocusManager,
*/
nsPIDOMWindowOuter* GetFocusedWindow() const { return mFocusedWindow; }
/**
* In the chrome process, retrieves the BrowsingContext corresponding
* to GetFocusedWindow(). In a content process, retrieves the
* focused BrowsingContext, which may not belong to this process.
*/
mozilla::dom::BrowsingContext* GetFocusedBrowsingContext() const {
if (XRE_IsParentProcess()) {
if (mFocusedWindow) {
return mFocusedWindow->GetBrowsingContext();
}
return nullptr;
}
return mFocusedBrowsingContextInContent;
}
/**
* Return an active window. Version of nsIFocusManager::GetActiveWindow.
*/
nsPIDOMWindowOuter* GetActiveWindow() const { return mActiveWindow; }
/**
* In the chrome process, retrieves the BrowsingContext corresponding
* to GetActiveWindow(). In a content process, retrieves the
* BrowsingContext of the top-level Web content in the active tab if
* in the same process as the caller or nullptr otherwise.
*/
mozilla::dom::BrowsingContext* GetActiveBrowsingContext() const {
if (XRE_IsParentProcess()) {
if (mActiveWindow) {
return mActiveWindow->GetBrowsingContext();
}
return nullptr;
}
return mActiveBrowsingContextInContent;
}
/**
* Called when content has been removed.
*/
@ -231,13 +266,19 @@ class nsFocusManager final : public nsIFocusManager,
*/
bool IsSameOrAncestor(nsPIDOMWindowOuter* aPossibleAncestor,
nsPIDOMWindowOuter* aWindow);
bool IsSameOrAncestor(nsPIDOMWindowOuter* aPossibleAncestor,
mozilla::dom::BrowsingContext* aContext);
bool IsSameOrAncestor(mozilla::dom::BrowsingContext* aPossibleAncestor,
nsPIDOMWindowOuter* aWindow);
bool IsSameOrAncestor(mozilla::dom::BrowsingContext* aPossibleAncestor,
mozilla::dom::BrowsingContext* aContext);
/**
* Returns the window that is the lowest common ancestor of both aWindow1
* and aWindow2, or null if they share no common ancestor.
* Returns the window that is the lowest common ancestor of both aWindow
* and aContext, or null if they share no common ancestor.
*/
already_AddRefed<nsPIDOMWindowOuter> GetCommonAncestor(
nsPIDOMWindowOuter* aWindow1, nsPIDOMWindowOuter* aWindow2);
mozilla::dom::BrowsingContext* GetCommonAncestor(
nsPIDOMWindowOuter* aWindow, mozilla::dom::BrowsingContext* aContext);
/**
* When aNewWindow is focused, adjust the ancestors of aNewWindow so that they
@ -283,14 +324,14 @@ class nsFocusManager final : public nsIFocusManager,
* focused as a result. This would mean that the caller should not proceed
* with a pending call to Focus. Normally, true would be returned.
*
* The currently focused element within aWindowToClear will be cleared.
* aWindowToClear may be null, which means that no window is cleared. This
* will be the case, for example, when lowering a window, as we want to fire
* a blur, but not actually change what element would be focused, so that
* the same element will be focused again when the window is raised.
* The currently focused element within aBrowsingContextToClear will be
* cleared. aBrowsingContextToClear may be null, which means that no window is
* cleared. This will be the case, for example, when lowering a window, as we
* want to fire a blur, but not actually change what element would be focused,
* so that the same element will be focused again when the window is raised.
*
* aAncestorWindowToFocus should be set to the common ancestor of the window
* that is being blurred and the window that is going to focused, when
* aAncestorBrowsingContextToFocus should be set to the common ancestor of the
* window that is being blurred and the window that is going to focused, when
* switching focus to a sibling window.
*
* aIsLeavingDocument should be set to true if the document/window is being
@ -301,9 +342,21 @@ class nsFocusManager final : public nsIFocusManager,
*/
// MOZ_CAN_RUN_SCRIPT_BOUNDARY for now, until we annotate callers.
MOZ_CAN_RUN_SCRIPT_BOUNDARY
bool Blur(nsPIDOMWindowOuter* aWindowToClear,
nsPIDOMWindowOuter* aAncestorWindowToFocus, bool aIsLeavingDocument,
bool aAdjustWidget, nsIContent* aContentToFocus = nullptr);
bool Blur(mozilla::dom::BrowsingContext* aBrowsingContextToClear,
mozilla::dom::BrowsingContext* aAncestorBrowsingContextToFocus,
bool aIsLeavingDocument, bool aAdjustWidget,
nsIContent* aContentToFocus = nullptr);
MOZ_CAN_RUN_SCRIPT_BOUNDARY
void BlurFromOtherProcess(
mozilla::dom::BrowsingContext* aFocusedBrowsingContext,
mozilla::dom::BrowsingContext* aBrowsingContextToClear,
mozilla::dom::BrowsingContext* aAncestorBrowsingContextToFocus,
bool aIsLeavingDocument, bool aAdjustWidget);
MOZ_CAN_RUN_SCRIPT_BOUNDARY
bool BlurImpl(mozilla::dom::BrowsingContext* aBrowsingContextToClear,
mozilla::dom::BrowsingContext* aAncestorBrowsingContextToFocus,
bool aIsLeavingDocument, bool aAdjustWidget,
nsIContent* aContentToFocus);
/**
* Focus an element in the active window and child frame.
@ -631,17 +684,109 @@ class nsFocusManager final : public nsIFocusManager,
bool aForward, bool aForDocumentNavigation,
nsIContent** aResultContent);
// the currently active and front-most top-most window
// Sets the focused BrowsingContext and, if appropriate, syncs it to
// other processes.
void SetFocusedBrowsingContext(mozilla::dom::BrowsingContext* aContext);
// Content-only
// Called when receiving an IPC message about another process setting
// the focused BrowsingContext.
void SetFocusedBrowsingContextFromOtherProcess(
mozilla::dom::BrowsingContext* aContext);
// Chrome-only
// Sets the chrome process notion of what BrowsingContext is focused
// in content.
void SetFocusedBrowsingContextInChrome(
mozilla::dom::BrowsingContext* aContext);
public:
// Chrome-only
// Gets the chrome process notion of what BrowsingContext is focused
// in content.
mozilla::dom::BrowsingContext* GetFocusedBrowsingContextInChrome();
// Chrome-only
// Notifies the focus manager that BrowsingContext::Detach was called
// on a BrowsingContext so that pointers to it can be forgotten.
void BrowsingContextDetached(mozilla::dom::BrowsingContext* aContext);
private:
// Content-only
// Sets the BrowsingContext corresponding to top-level Web content
// in the frontmost tab if focus is in Web content.
void SetActiveBrowsingContextInContent(
mozilla::dom::BrowsingContext* aContext);
// Content-only
// Receives notification of another process setting the top-level Web
// content as being in the frontmost tab with focus in Web content.
void SetActiveBrowsingContextFromOtherProcess(
mozilla::dom::BrowsingContext* aContext);
// Content-only
// Receives notification that another process determined that focus
// moved to chrome so a particular BrowsingContext is no longer the
// "active" one.
void UnsetActiveBrowsingContextFromOtherProcess(
mozilla::dom::BrowsingContext* aContext);
// Chrome-only
// Sets the chrome process notion of what content believes to be
// the top-level BrowsingContext in the frontmost tab when focus
// is in Web content.
void SetActiveBrowsingContextInChrome(
mozilla::dom::BrowsingContext* aContext);
public:
// Chrome-only
// Gets the chrome process notion of what content believes to be
// the top-level BrowsingContext in the frontmost tab when focus
// is in Web content.
mozilla::dom::BrowsingContext* GetActiveBrowsingContextInChrome();
private:
// In the chrome process, the currently active and front-most top-most
// window. Not supposed to be used in a meaningful way in content
// processes.
nsCOMPtr<nsPIDOMWindowOuter> mActiveWindow;
// the child or top-level window that is currently focused. This window will
// In a content process, the BrowsingContext corresponding to top-level
// Web content in the active tab or nullptr if focus is not in a
// BrowsingContextGroup that this process participates in. Synced
// across processes in a BrowsingContextGroup.
// Not supposed to be used in a meaningful way in the chrome process.
RefPtr<mozilla::dom::BrowsingContext> mActiveBrowsingContextInContent;
// This is the chrome process notion of content's
// mActiveBrowsingContextInContent. Avoiding field reuse for different
// semantics in different process types to make it easier to catch bugs.
RefPtr<mozilla::dom::BrowsingContext> mActiveBrowsingContextInChrome;
// the child or top-level window that is currently focused. In the chrome
// process, when a window isn't being raised or lowered, this window will
// either be the same window as mActiveWindow or a descendant of it.
// Except during shutdown use SetFocusedWindowInternal to set mFocusedWindow!
nsCOMPtr<nsPIDOMWindowOuter> mFocusedWindow;
// the currently focused content, which is always inside mFocusedWindow. This
// is a cached copy of the mFocusedWindow's current content. This may be null
// if no content is focused.
// The focused BrowsingContext if this is a chrome process and focus is
// in chrome or if this is a content process and focus is in Web content
// in this BrowsingContextGroup. nullptr otherwise.
// Except during shutdown, must be set via SetFocusedWindowInternal which
// calls SetFocusedBrowsingContext or if the value is coming in via IPC
// via SetFocusedBrowsingContextFromOtherProcess.
RefPtr<mozilla::dom::BrowsingContext> mFocusedBrowsingContextInContent;
// This is the chrome process notion of content's
// mFocusedBrowsingContextInContent. Avoiding field reuse for different
// semantics in different process types to make it easier to catch bugs.
RefPtr<mozilla::dom::BrowsingContext> mFocusedBrowsingContextInChrome;
// the currently focused content if in-process or the XUL browser in which
// Web content focus resides. Always inside mFocusedWindow. When a window
// isn't being raised or lowered, this is a cached copy of the
// mFocusedWindow's current content. This may be null if no content is
// focused.
RefPtr<mozilla::dom::Element> mFocusedElement;
// these fields store a content node temporarily while it is being focused

Просмотреть файл

@ -575,7 +575,7 @@ skip-if = (verify && !debug && (os == 'linux')) #bug 687032
[test_bug927196.html]
[test_bug962251.html]
[test_bug976673.html]
fail-if = fission # Setting focus from mousedown handler: <input> in the iframe should get focus - got "input-value: ", expected "input-value: focus"
skip-if = fission #Bug 1613899
[test_bug982153.html]
[test_bug999456.html]
[test_bug1022229.html]

Просмотреть файл

@ -5,3 +5,4 @@ scheme = https
skip-if = !e10s
[test_credman_iframes.html]
skip-if = fission #Bug 1612839

Просмотреть файл

@ -132,7 +132,10 @@ void IMEStateManager::OnFocusMovedBetweenBrowsers(BrowserParent* aBlur,
}
}
if (aBlur) {
// The manager check is to avoid telling the content process to stop
// IME state management after focus has already moved there between
// two same-process-hosted out-of-process iframes.
if (aBlur && (!aFocus || (aBlur->Manager() != aFocus->Manager()))) {
MOZ_LOG(sISMLog, LogLevel::Debug,
(" OnFocusMovedBetweenBrowsers(), notifying previous "
"focused child process of parent process or another child process "
@ -441,7 +444,7 @@ nsresult IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
}
if (sActiveIMEContentObserver) {
MOZ_ASSERT(!remoteHasFocus,
MOZ_ASSERT(!remoteHasFocus || XRE_IsContentProcess(),
"IMEContentObserver should have been destroyed by "
"OnFocusMovedBetweenBrowsers.");
if (!aPresContext) {

Просмотреть файл

@ -520,6 +520,7 @@ skip-if = (toolkit == 'android') || ((os == 'win' || os == 'linux') && debug) #
[test_ul_attributes_reflection.html]
[test_input_files_not_nsIFile.html]
[test_ignoreuserfocus.html]
skip-if = true # Firefox OS test disabled to enable Fission focus changes
[test_fragment_form_pointer.html]
[test_bug1682.html]
[test_bug1823.html]

Просмотреть файл

@ -149,7 +149,9 @@ LazyLogModule gBrowserFocusLog("BrowserFocus");
MOZ_LOG(gBrowserFocusLog, mozilla::LogLevel::Debug, args)
/* static */
StaticAutoPtr<nsTArray<BrowserParent*>> BrowserParent::sFocusStack;
BrowserParent* BrowserParent::sFocus = nullptr;
/* static */
BrowserParent* BrowserParent::sTopLevelWebFocus = nullptr;
// The flags passed by the webProgress notifications are 16 bits shifted
// from the ones registered by webProgressListeners.
@ -230,22 +232,10 @@ BrowserParent::BrowserParent(ContentParent* aManager, const TabId& aTabId,
BrowserParent::~BrowserParent() {}
/* static */
void BrowserParent::InitializeStatics() {
MOZ_ASSERT(XRE_IsParentProcess());
sFocusStack = new nsTArray<BrowserParent*>();
ClearOnShutdown(&sFocusStack);
}
void BrowserParent::InitializeStatics() { MOZ_ASSERT(XRE_IsParentProcess()); }
/* static */
BrowserParent* BrowserParent::GetFocused() {
if (!sFocusStack) {
return nullptr;
}
if (sFocusStack->IsEmpty()) {
return nullptr;
}
return sFocusStack->LastElement();
}
BrowserParent* BrowserParent::GetFocused() { return sFocus; }
/*static*/
BrowserParent* BrowserParent::GetFrom(nsFrameLoader* aFrameLoader) {
@ -628,7 +618,7 @@ void BrowserParent::RemoveWindowListeners() {
}
void BrowserParent::DestroyInternal() {
PopFocus(this);
UnsetTopLevelWebFocus(this);
RemoveWindowListeners();
@ -703,7 +693,7 @@ void BrowserParent::ActorDestroy(ActorDestroyReason why) {
// Even though BrowserParent::Destroy calls this, we need to do it here too in
// case of a crash.
BrowserParent::PopFocus(this);
BrowserParent::UnsetTopLevelWebFocus(this);
// Prevent executing ContentParent::NotifyTabDestroying in
// BrowserParent::Destroy() called by frameLoader->DestroyComplete() below
@ -1147,7 +1137,7 @@ void BrowserParent::HandleAccessKey(const WidgetKeyboardEvent& aEvent,
void BrowserParent::Activate() {
LOGBROWSERFOCUS(("Activate %p", this));
if (!mIsDestroyed) {
PushFocus(this); // Intentionally inside "if"
SetTopLevelWebFocus(this); // Intentionally inside "if"
Unused << Manager()->SendActivate(this);
}
}
@ -1155,7 +1145,7 @@ void BrowserParent::Activate() {
void BrowserParent::Deactivate(bool aWindowLowering) {
LOGBROWSERFOCUS(("Deactivate %p", this));
if (!aWindowLowering) {
PopFocus(this); // Intentionally outside the next "if"
UnsetTopLevelWebFocus(this); // Intentionally outside the next "if"
}
if (!mIsDestroyed) {
Unused << Manager()->SendDeactivate(this);
@ -2923,88 +2913,95 @@ bool BrowserParent::SendPasteTransferable(const IPCDataTransfer& aDataTransfer,
}
/* static */
void BrowserParent::PushFocus(BrowserParent* aBrowserParent) {
if (!sFocusStack) {
MOZ_ASSERT_UNREACHABLE("PushFocus when not initialized");
return;
}
if (!aBrowserParent->GetBrowserBridgeParent()) {
// top-level Web content
// When a new native window is created, we spin a nested event loop.
// As a result, unlike when raising an existing window, we get
// PushFocus for content in the new window before we get the PopFocus
// for content in the old one. Hence, if the stack isn't empty when
// pushing top-level Web content, first pop everything off the stack.
PopFocusAll();
MOZ_ASSERT(sFocusStack->IsEmpty());
} else {
// out-of-process iframe
// Considering that we can get top-level pushes out of order, let's
// ignore trailing out-of-process iframe pushes for the previous top-level
// Web content.
if (sFocusStack->IsEmpty()) {
LOGBROWSERFOCUS(
("PushFocus for out-of-process iframe ignored with empty stack %p",
aBrowserParent));
return;
}
nsCOMPtr<nsIWidget> webRootWidget = sFocusStack->ElementAt(0)->GetWidget();
nsCOMPtr<nsIWidget> iframeWigdet = aBrowserParent->GetWidget();
if (webRootWidget != iframeWigdet) {
LOGBROWSERFOCUS(
("PushFocus for out-of-process iframe ignored with mismatching "
"top-level content %p",
aBrowserParent));
return;
}
}
if (sFocusStack->Contains(aBrowserParent)) {
MOZ_ASSERT_UNREACHABLE(
"Trying to push a BrowserParent that is already on the stack");
return;
}
void BrowserParent::SetTopLevelWebFocus(BrowserParent* aBrowserParent) {
BrowserParent* old = GetFocused();
sFocusStack->AppendElement(aBrowserParent);
MOZ_ASSERT(GetFocused() == aBrowserParent);
LOGBROWSERFOCUS(("PushFocus changed focus to %p", aBrowserParent));
IMEStateManager::OnFocusMovedBetweenBrowsers(old, aBrowserParent);
}
/* static */
void BrowserParent::PopFocus(BrowserParent* aBrowserParent) {
if (!sFocusStack) {
MOZ_ASSERT_UNREACHABLE("PopFocus when not initialized");
return;
}
// When focus is in an out-of-process iframe and the whole window
// or tab loses focus, we first receive a pop for the top-level Web
// content process and only then for its out-of-process iframes.
// Hence, we do all the popping up front and then ignore the
// pop requests for the out-of-process iframes that we already
// popped.
auto pos = sFocusStack->LastIndexOf(aBrowserParent);
if (pos == nsTArray<BrowserParent*>::NoIndex) {
LOGBROWSERFOCUS(("PopFocus not on stack %p", aBrowserParent));
return;
}
auto len = sFocusStack->Length();
auto itemsToPop = len - pos;
LOGBROWSERFOCUS(("PopFocus pops %zu items %p", itemsToPop, aBrowserParent));
while (pos < sFocusStack->Length()) {
BrowserParent* popped = sFocusStack->PopLastElement();
BrowserParent* focused = GetFocused();
LOGBROWSERFOCUS(("PopFocus changed focus to %p", focused));
IMEStateManager::OnFocusMovedBetweenBrowsers(popped, focused);
if (aBrowserParent && !aBrowserParent->GetBrowserBridgeParent()) {
// top-level Web content
sTopLevelWebFocus = aBrowserParent;
BrowserParent* bp = UpdateFocus();
if (old != bp) {
LOGBROWSERFOCUS(
("SetTopLevelWebFocus updated focus; old: %p, new: %p", old, bp));
IMEStateManager::OnFocusMovedBetweenBrowsers(old, bp);
}
}
}
/* static */
void BrowserParent::PopFocusAll() {
if (!sFocusStack->IsEmpty()) {
LOGBROWSERFOCUS(("PopFocusAll pops items"));
PopFocus(sFocusStack->ElementAt(0));
} else {
LOGBROWSERFOCUS(("PopFocusAll does nothing"));
void BrowserParent::UnsetTopLevelWebFocus(BrowserParent* aBrowserParent) {
BrowserParent* old = GetFocused();
if (sTopLevelWebFocus == aBrowserParent) {
// top-level Web content
sTopLevelWebFocus = nullptr;
sFocus = nullptr;
if (old) {
LOGBROWSERFOCUS(
("UnsetTopLevelWebFocus moved focus to chrome; old: %p", old));
IMEStateManager::OnFocusMovedBetweenBrowsers(old, nullptr);
}
}
}
/* static */
void BrowserParent::UpdateFocusFromBrowsingContext() {
BrowserParent* old = GetFocused();
BrowserParent* bp = UpdateFocus();
if (old != bp) {
LOGBROWSERFOCUS(
("UpdateFocusFromBrowsingContext updated focus; old: %p, new: %p", old,
bp));
IMEStateManager::OnFocusMovedBetweenBrowsers(old, bp);
}
}
/* static */
BrowserParent* BrowserParent::UpdateFocus() {
if (!sTopLevelWebFocus) {
sFocus = nullptr;
return nullptr;
}
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
BrowsingContext* bc = fm->GetFocusedBrowsingContextInChrome();
if (bc) {
BrowsingContext* top = bc->Top();
MOZ_ASSERT(top, "Should always have a top BrowsingContext.");
CanonicalBrowsingContext* canonicalTop = top->Canonical();
MOZ_ASSERT(canonicalTop,
"Casting to canonical should always be possible in the parent "
"process (top case).");
WindowGlobalParent* globalTop = canonicalTop->GetCurrentWindowGlobal();
if (globalTop) {
RefPtr<BrowserParent> globalTopParent = globalTop->GetBrowserParent();
if (sTopLevelWebFocus == globalTopParent) {
CanonicalBrowsingContext* canonical = bc->Canonical();
MOZ_ASSERT(
canonical,
"Casting to canonical should always be possible in the parent "
"process.");
WindowGlobalParent* global = canonical->GetCurrentWindowGlobal();
if (global) {
RefPtr<BrowserParent> parent = global->GetBrowserParent();
sFocus = parent;
return sFocus;
}
LOGBROWSERFOCUS(
("Focused BrowsingContext did not have WindowGlobalParent."));
}
} else {
LOGBROWSERFOCUS(
("Top-level BrowsingContext did not have WindowGlobalParent."));
}
}
}
sFocus = sTopLevelWebFocus;
return sFocus;
}
/* static */
void BrowserParent::UnsetTopLevelWebFocusAll() {
if (sTopLevelWebFocus) {
UnsetTopLevelWebFocus(sTopLevelWebFocus);
}
}

Просмотреть файл

@ -834,17 +834,36 @@ class BrowserParent final : public PBrowserParent,
static void RemoveBrowserParentFromTable(layers::LayersId aLayersId);
// Keeps track of which BrowserParent has keyboard focus
static StaticAutoPtr<nsTArray<BrowserParent*>> sFocusStack;
// Keeps track of which BrowserParent has keyboard focus.
// If nullptr, the parent process has focus.
// Use UpdateFocus() to manage.
static BrowserParent* sFocus;
static void PushFocus(BrowserParent* aBrowserParent);
// Keeps track of which top-level BrowserParent the keyboard focus is under.
// If nullptr, the parent process has focus.
// Use SetTopLevelWebFocus and UnsetTopLevelWebFocus to manage.
static BrowserParent* sTopLevelWebFocus;
static void PopFocus(BrowserParent* aBrowserParent);
// Setter for sTopLevelWebFocus
static void SetTopLevelWebFocus(BrowserParent* aBrowserParent);
// Unsetter for sTopLevelWebFocus; only unsets if argument matches
// current sTopLevelWebFocus. Use UnsetTopLevelWebFocusAll() to
// unset regardless of current value.
static void UnsetTopLevelWebFocus(BrowserParent* aBrowserParent);
// Recomputes sFocus and returns it.
static BrowserParent* UpdateFocus();
void OnSubFrameCrashed();
public:
static void PopFocusAll();
// Unsets sTopLevelWebFocus regardless of its current value.
static void UnsetTopLevelWebFocusAll();
// Recomputes focus when the BrowsingContext tree changes in a
// way that potentially invalidates the sFocus.
static void UpdateFocusFromBrowsingContext();
private:
TabId mTabId;

Просмотреть файл

@ -116,6 +116,7 @@
#include "audio_thread_priority.h"
#include "nsIURIMutator.h"
#include "nsIInputStreamChannel.h"
#include "nsFocusManager.h"
#if !defined(XP_WIN)
# include "mozilla/Omnijar.h"
@ -4045,6 +4046,152 @@ mozilla::ipc::IPCResult ContentChild::RecvWindowBlur(
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvRaiseWindow(BrowsingContext* aContext,
CallerType aCallerType) {
if (!aContext) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
nsCOMPtr<nsPIDOMWindowOuter> window = aContext->GetDOMWindow();
if (!window) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to send a message to a context without a window"));
return IPC_OK();
}
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
fm->RaiseWindow(window, aCallerType);
}
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvClearFocus(
BrowsingContext* aContext) {
if (!aContext) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
nsCOMPtr<nsPIDOMWindowOuter> window = aContext->GetDOMWindow();
if (!window) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to send a message to a context without a window"));
return IPC_OK();
}
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
fm->ClearFocus(window);
}
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvSetFocusedBrowsingContext(
BrowsingContext* aContext) {
if (!aContext) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
fm->SetFocusedBrowsingContextFromOtherProcess(aContext);
}
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvSetActiveBrowsingContext(
BrowsingContext* aContext) {
if (!aContext) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
fm->SetActiveBrowsingContextFromOtherProcess(aContext);
}
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvUnsetActiveBrowsingContext(
BrowsingContext* aContext) {
if (!aContext) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
fm->UnsetActiveBrowsingContextFromOtherProcess(aContext);
}
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvSetFocusedElement(
BrowsingContext* aContext, bool aNeedsFocus) {
if (!aContext) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
nsCOMPtr<nsPIDOMWindowOuter> window = aContext->GetDOMWindow();
if (!window) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to send a message to a context without a window"));
return IPC_OK();
}
window->SetFocusedElement(nullptr, 0, aNeedsFocus);
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvBlurToChild(
BrowsingContext* aFocusedBrowsingContext,
BrowsingContext* aBrowsingContextToClear,
BrowsingContext* aAncestorBrowsingContextToFocus, bool aIsLeavingDocument,
bool aAdjustWidget) {
if (!aFocusedBrowsingContext) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
fm->BlurFromOtherProcess(aFocusedBrowsingContext, aBrowsingContextToClear,
aAncestorBrowsingContextToFocus,
aIsLeavingDocument, aAdjustWidget);
}
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvSetupFocusedAndActive(
BrowsingContext* aFocusedBrowsingContext,
BrowsingContext* aActiveBrowsingContext) {
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
if (aActiveBrowsingContext) {
fm->SetActiveBrowsingContextFromOtherProcess(aActiveBrowsingContext);
}
if (aFocusedBrowsingContext) {
fm->SetFocusedBrowsingContextFromOtherProcess(aFocusedBrowsingContext);
}
}
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvWindowPostMessage(
BrowsingContext* aContext, const ClonedMessageData& aMessage,
const PostMessageData& aData) {

Просмотреть файл

@ -751,6 +751,25 @@ class ContentChild final
mozilla::ipc::IPCResult RecvWindowFocus(BrowsingContext* aContext,
CallerType aCallerType);
mozilla::ipc::IPCResult RecvWindowBlur(BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvRaiseWindow(BrowsingContext* aContext,
CallerType aCallerType);
mozilla::ipc::IPCResult RecvClearFocus(BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvSetFocusedBrowsingContext(
BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvSetActiveBrowsingContext(
BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvUnsetActiveBrowsingContext(
BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvSetFocusedElement(BrowsingContext* aContext,
bool aNeedsFocus);
mozilla::ipc::IPCResult RecvBlurToChild(
BrowsingContext* aFocusedBrowsingContext,
BrowsingContext* aBrowsingContextToClear,
BrowsingContext* aAncestorBrowsingContextToFocus, bool aIsLeavingDocument,
bool aAdjustWidget);
mozilla::ipc::IPCResult RecvSetupFocusedAndActive(
BrowsingContext* aFocusedBrowsingContext,
BrowsingContext* aActiveBrowsingContext);
mozilla::ipc::IPCResult RecvWindowPostMessage(
BrowsingContext* aContext, const ClonedMessageData& aMessage,
const PostMessageData& aData);

Просмотреть файл

@ -6316,6 +6316,172 @@ mozilla::ipc::IPCResult ContentParent::RecvWindowBlur(
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvRaiseWindow(
BrowsingContext* aContext, CallerType aCallerType) {
if (!aContext || aContext->IsDiscarded()) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
ContentParent* cp = cpm->GetContentProcessById(
ContentParentId(aContext->Canonical()->OwnerProcessId()));
Unused << cp->SendRaiseWindow(aContext, aCallerType);
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvClearFocus(
BrowsingContext* aContext) {
if (!aContext || aContext->IsDiscarded()) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
ContentParent* cp = cpm->GetContentProcessById(
ContentParentId(aContext->Canonical()->OwnerProcessId()));
Unused << cp->SendClearFocus(aContext);
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvSetFocusedBrowsingContext(
BrowsingContext* aContext) {
if (!aContext || aContext->IsDiscarded()) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
fm->SetFocusedBrowsingContextInChrome(aContext);
BrowserParent::UpdateFocusFromBrowsingContext();
}
aContext->Group()->EachOtherParent(this, [&](ContentParent* aParent) {
Unused << aParent->SendSetFocusedBrowsingContext(aContext);
});
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvSetActiveBrowsingContext(
BrowsingContext* aContext) {
if (!aContext || aContext->IsDiscarded()) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
fm->SetActiveBrowsingContextInChrome(aContext);
}
aContext->Group()->EachOtherParent(this, [&](ContentParent* aParent) {
Unused << aParent->SendSetActiveBrowsingContext(aContext);
});
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvUnsetActiveBrowsingContext(
BrowsingContext* aContext) {
if (!aContext || aContext->IsDiscarded()) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
if (aContext == fm->GetActiveBrowsingContextInChrome()) {
fm->SetActiveBrowsingContextInChrome(nullptr);
}
}
aContext->Group()->EachOtherParent(this, [&](ContentParent* aParent) {
Unused << aParent->SendUnsetActiveBrowsingContext(aContext);
});
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvSetFocusedElement(
BrowsingContext* aContext, bool aNeedsFocus) {
if (!aContext || aContext->IsDiscarded()) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
ContentParent* cp = cpm->GetContentProcessById(
ContentParentId(aContext->Canonical()->OwnerProcessId()));
Unused << cp->SendSetFocusedElement(aContext, aNeedsFocus);
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvBlurToParent(
BrowsingContext* aFocusedBrowsingContext,
BrowsingContext* aBrowsingContextToClear,
BrowsingContext* aAncestorBrowsingContextToFocus, bool aIsLeavingDocument,
bool aAdjustWidget, bool aBrowsingContextToClearHandled,
bool aAncestorBrowsingContextToFocusHandled) {
if (!aFocusedBrowsingContext || aFocusedBrowsingContext->IsDiscarded()) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
// If aBrowsingContextToClear and aAncestorBrowsingContextToFocusHandled
// didn't get handled in the process that sent this IPC message and they
// aren't in the same process as aFocusedBrowsingContext, we need to split
// off their handling here and use SendSetFocusedElement to send them
// elsewhere than the blurring itself.
bool ancestorDifferent =
(!aAncestorBrowsingContextToFocusHandled &&
aAncestorBrowsingContextToFocus &&
!aAncestorBrowsingContextToFocus->IsDiscarded() &&
(aFocusedBrowsingContext->Canonical()->OwnerProcessId() !=
aAncestorBrowsingContextToFocus->Canonical()->OwnerProcessId()));
if (!aBrowsingContextToClearHandled && aBrowsingContextToClear &&
!aBrowsingContextToClear->IsDiscarded() &&
(aFocusedBrowsingContext->Canonical()->OwnerProcessId() !=
aBrowsingContextToClear->Canonical()->OwnerProcessId())) {
MOZ_RELEASE_ASSERT(!ancestorDifferent,
"This combination is not supposed to happen.");
ContentParent* cp = cpm->GetContentProcessById(ContentParentId(
aBrowsingContextToClear->Canonical()->OwnerProcessId()));
Unused << cp->SendSetFocusedElement(aBrowsingContextToClear, false);
} else if (ancestorDifferent) {
ContentParent* cp = cpm->GetContentProcessById(ContentParentId(
aAncestorBrowsingContextToFocus->Canonical()->OwnerProcessId()));
Unused << cp->SendSetFocusedElement(aAncestorBrowsingContextToFocus, true);
}
ContentParent* cp = cpm->GetContentProcessById(
ContentParentId(aFocusedBrowsingContext->Canonical()->OwnerProcessId()));
Unused << cp->SendBlurToChild(
aFocusedBrowsingContext, aBrowsingContextToClear,
aAncestorBrowsingContextToFocus, aIsLeavingDocument, aAdjustWidget);
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvWindowPostMessage(
BrowsingContext* aContext, const ClonedMessageData& aMessage,
const PostMessageData& aData) {

Просмотреть файл

@ -659,6 +659,23 @@ class ContentParent final
mozilla::ipc::IPCResult RecvWindowFocus(BrowsingContext* aContext,
CallerType aCallerType);
mozilla::ipc::IPCResult RecvWindowBlur(BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvRaiseWindow(BrowsingContext* aContext,
CallerType aCallerType);
mozilla::ipc::IPCResult RecvClearFocus(BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvSetFocusedBrowsingContext(
BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvSetActiveBrowsingContext(
BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvUnsetActiveBrowsingContext(
BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvSetFocusedElement(BrowsingContext* aContext,
bool aNeedsFocus);
mozilla::ipc::IPCResult RecvBlurToParent(
BrowsingContext* aFocusedBrowsingContext,
BrowsingContext* aBrowsingContextToClear,
BrowsingContext* aAncestorBrowsingContextToFocus, bool aIsLeavingDocument,
bool aAdjustWidget, bool aBrowsingContextToClearHandled,
bool aAncestorBrowsingContextToFocusHandled);
mozilla::ipc::IPCResult RecvWindowPostMessage(
BrowsingContext* aContext, const ClonedMessageData& aMessage,
const PostMessageData& aData);

Просмотреть файл

@ -1609,6 +1609,27 @@ both:
async WindowClose(BrowsingContext aContext, bool aTrustedCaller);
async WindowFocus(BrowsingContext aContext, CallerType aCallerType);
async WindowBlur(BrowsingContext aContext);
async RaiseWindow(BrowsingContext aContext, CallerType aCallerType);
async ClearFocus(BrowsingContext aContext);
async SetFocusedBrowsingContext(BrowsingContext aContext);
async SetActiveBrowsingContext(BrowsingContext aContext);
async UnsetActiveBrowsingContext(BrowsingContext aContext);
async SetFocusedElement(BrowsingContext aContext, bool aNeedsFocus);
parent:
async BlurToParent(BrowsingContext aFocusedBrowsingContext,
BrowsingContext aBrowsingContextToClear,
BrowsingContext aAncestorBrowsingContextToFocus,
bool aIsLeavingDocument, bool aAdjustWidget,
bool aBrowsingContextToClearHandled,
bool aAncestorBrowsingContextToFocusHandled);
child:
async BlurToChild(BrowsingContext aFocusedBrowsingContext,
BrowsingContext aBrowsingContextToClear,
BrowsingContext aAncestorBrowsingContextToFocus,
bool aIsLeavingDocument, bool aAdjustWidget);
async SetupFocusedAndActive(BrowsingContext aFocusedBrowsingContext,
BrowsingContext aActiveBrowsingContext);
both:
async WindowPostMessage(BrowsingContext aContext, ClonedMessageData aMessage,
PostMessageData aData);

Просмотреть файл

@ -69,7 +69,7 @@ skip-if = os == 'mac' || os == 'win' || toolkit == 'android' # Bug 1404995, no l
[test_getUserMedia_basicVideo.html]
[test_getUserMedia_basicVideo_playAfterLoadedmetadata.html]
[test_getUserMedia_basicScreenshare.html]
skip-if = toolkit == 'android' || (os == 'win' && webrender) # no screenshare on android, see bug 1504162 for webrender on windows
skip-if = toolkit == 'android' || (os == 'win' && webrender) || fission # no screenshare on android, see bug 1504162 for webrender on windows, see bug 1613717 for Fission
[test_getUserMedia_basicTabshare.html]
skip-if = toolkit == 'android' # no windowshare on android
[test_getUserMedia_basicWindowshare.html]

Просмотреть файл

@ -8,13 +8,18 @@ skip-if = !e10s
scheme = https
[test_webauthn_abort_signal.html]
skip-if = fission #Bug 1612844
[test_webauthn_attestation_conveyance.html]
skip-if = fission #Bug 1612844
[test_webauthn_authenticator_selection.html]
skip-if = fission #Bug 1612844
[test_webauthn_authenticator_transports.html]
skip-if = fission #Bug 1612844
[test_webauthn_loopback.html]
[test_webauthn_no_token.html]
[test_webauthn_make_credential.html]
[test_webauthn_get_assertion.html]
skip-if = fission #Bug 1612844
[test_webauthn_get_assertion_dead_object.html]
[test_webauthn_override_request.html]
[test_webauthn_store_credential.html]

Просмотреть файл

@ -1,6 +1,6 @@
[DEFAULT]
[test_bug486990.xhtml]
skip-if = toolkit == 'android' #TIMED_OUT
skip-if = toolkit == 'android' || fission #TIMED_OUT #Bug 1612842
[test_disable_scroll_frame_plain.html]

Просмотреть файл

@ -5,6 +5,5 @@
[When the policy is disabled, 'autofocus' and scripted focus do not focus the document.]
expected:
if fission: PASS
FAIL

Просмотреть файл

@ -1,5 +0,0 @@
[same-origin-autofocus.html]
[Autofocus should work in the same origin grand child iframe]
expected:
if fission: FAIL

Просмотреть файл

@ -33,7 +33,6 @@ skip-if = toolkit == 'android' # autocomplete
scheme = https
skip-if = toolkit == 'android' # autocomplete
[test_autocomplete_https_downgrade.html]
fail-if = fission # Bug 1588091
scheme = http # Tests downgrading
skip-if = toolkit == 'android' || (os == 'linux' && debug) # autocomplete && Bug 1554959 for linux debug disable
[test_autocomplete_https_upgrade.html]

Просмотреть файл

@ -9,4 +9,4 @@ support-files =
file_mousecapture3.html
file_mousecapture4.html
file_mousecapture5.html
skip-if = toolkit == "android"
skip-if = (toolkit == "android") || fission #Bug 1613031

Просмотреть файл

@ -29,7 +29,7 @@ skip-if = (verify && debug)
[test_ua_widget_unbind.html]
[test_videocontrols.html]
tags = fullscreen
skip-if = toolkit == 'android' || (verify && debug && (os == 'linux')) || (webrender && (os == 'linux')) #TIMED_OUT #Bug 1484210
skip-if = toolkit == 'android' || (verify && debug && (os == 'linux')) || (webrender && (os == 'linux')) || fission #TIMED_OUT #Bug 1484210 #Bug 1511256 #Bug 1615544
[test_videocontrols_keyhandler.html]
skip-if = (toolkit == 'android') || (os == 'linux') #Bug 1366957
[test_videocontrols_vtt.html]