mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Merge inbound to m-c a=merge
This commit is contained in:
commit
00bfc9f9d8
@ -480,44 +480,6 @@ EventQueue::CreateTextChangeEventFor(AccMutationEvent* aEvent)
|
||||
aEvent->mIsFromUserInput ? eFromUserInput : eNoUserInput);
|
||||
}
|
||||
|
||||
void
|
||||
EventQueue::SendIPCEvent(AccEvent* aEvent) const
|
||||
{
|
||||
DocAccessibleChild* ipcDoc = mDocument->IPCDoc();
|
||||
uint64_t id = aEvent->GetAccessible()->IsDoc() ? 0 :
|
||||
reinterpret_cast<uintptr_t>(aEvent->GetAccessible());
|
||||
|
||||
switch(aEvent->GetEventType()) {
|
||||
case nsIAccessibleEvent::EVENT_SHOW:
|
||||
ipcDoc->ShowEvent(downcast_accEvent(aEvent));
|
||||
break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_HIDE:
|
||||
ipcDoc->SendHideEvent(id);
|
||||
break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_REORDER:
|
||||
// reorder events on the application acc aren't necessary to tell the parent
|
||||
// about new top level documents.
|
||||
if (!aEvent->GetAccessible()->IsApplication())
|
||||
ipcDoc->SendEvent(id, aEvent->GetEventType());
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_STATE_CHANGE: {
|
||||
AccStateChangeEvent* event = downcast_accEvent(aEvent);
|
||||
ipcDoc->SendStateChangeEvent(id, event->GetState(),
|
||||
event->IsStateEnabled());
|
||||
break;
|
||||
}
|
||||
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED: {
|
||||
AccCaretMoveEvent* event = downcast_accEvent(aEvent);
|
||||
ipcDoc->SendEvent(id, event->GetCaretOffset());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ipcDoc->SendEvent(id, aEvent->GetEventType());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EventQueue: event queue
|
||||
|
||||
@ -594,8 +556,5 @@ EventQueue::ProcessEventQueue()
|
||||
|
||||
if (!mDocument)
|
||||
return;
|
||||
|
||||
if (IPCAccessibilityActive())
|
||||
SendIPCEvent(event);
|
||||
}
|
||||
}
|
||||
|
@ -53,11 +53,6 @@ private:
|
||||
AccSelChangeEvent* aThisEvent,
|
||||
uint32_t aThisIndex);
|
||||
|
||||
/**
|
||||
* Notify the parent process of events being fired by this event queue.
|
||||
*/
|
||||
void SendIPCEvent(AccEvent* aEvent) const;
|
||||
|
||||
/**
|
||||
* Coalesce text change events caused by sibling hide events.
|
||||
*/
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "ApplicationAccessible.h"
|
||||
#include "nsEventShell.h"
|
||||
#include "nsTextEquivUtils.h"
|
||||
#include "DocAccessibleChild.h"
|
||||
#include "Relation.h"
|
||||
#include "Role.h"
|
||||
#include "RootAccessible.h"
|
||||
@ -832,6 +833,42 @@ Accessible::HandleAccEvent(AccEvent* aEvent)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aEvent);
|
||||
|
||||
if (IPCAccessibilityActive() && Document()) {
|
||||
DocAccessibleChild* ipcDoc = mDoc->IPCDoc();
|
||||
uint64_t id = aEvent->GetAccessible()->IsDoc() ? 0 :
|
||||
reinterpret_cast<uintptr_t>(aEvent->GetAccessible());
|
||||
|
||||
switch(aEvent->GetEventType()) {
|
||||
case nsIAccessibleEvent::EVENT_SHOW:
|
||||
ipcDoc->ShowEvent(downcast_accEvent(aEvent));
|
||||
break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_HIDE:
|
||||
ipcDoc->SendHideEvent(id);
|
||||
break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_REORDER:
|
||||
// reorder events on the application acc aren't necessary to tell the parent
|
||||
// about new top level documents.
|
||||
if (!aEvent->GetAccessible()->IsApplication())
|
||||
ipcDoc->SendEvent(id, aEvent->GetEventType());
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_STATE_CHANGE: {
|
||||
AccStateChangeEvent* event = downcast_accEvent(aEvent);
|
||||
ipcDoc->SendStateChangeEvent(id, event->GetState(),
|
||||
event->IsStateEnabled());
|
||||
break;
|
||||
}
|
||||
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED: {
|
||||
AccCaretMoveEvent* event = downcast_accEvent(aEvent);
|
||||
ipcDoc->SendEvent(id, event->GetCaretOffset());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ipcDoc->SendEvent(id, aEvent->GetEventType());
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
|
||||
NS_ENSURE_TRUE(obsService, NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -336,6 +336,12 @@ public:
|
||||
*/
|
||||
void RecreateAccessible(nsIContent* aContent);
|
||||
|
||||
/**
|
||||
* If this document is in a content process return the object responsible for
|
||||
* communicating with the main process for it.
|
||||
*/
|
||||
DocAccessibleChild* IPCDoc() const { return mIPCDoc; }
|
||||
|
||||
protected:
|
||||
virtual ~DocAccessible();
|
||||
|
||||
@ -519,12 +525,6 @@ protected:
|
||||
*/
|
||||
bool IsLoadEventTarget() const;
|
||||
|
||||
/**
|
||||
* If this document is in a content process return the object responsible for
|
||||
* communicating with the main process for it.
|
||||
*/
|
||||
DocAccessibleChild* IPCDoc() const { return mIPCDoc; }
|
||||
|
||||
/*
|
||||
* Set the object responsible for communicating with the main process on
|
||||
* behalf of this document.
|
||||
|
@ -52,6 +52,7 @@ Accessible::AsOuterDoc()
|
||||
{
|
||||
return IsOuterDoc() ? static_cast<OuterDocAccessible*>(this) : nullptr;
|
||||
}
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -223,6 +223,7 @@ WrapperFor(ProxyAccessible* aProxy)
|
||||
{
|
||||
return reinterpret_cast<AccessibleWrap*>(aProxy->GetWrapper());
|
||||
}
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -8,6 +8,7 @@ var FullScreen = {
|
||||
"DOMFullscreen:Request",
|
||||
"DOMFullscreen:NewOrigin",
|
||||
"DOMFullscreen:Exit",
|
||||
"DOMFullscreen:Painted",
|
||||
],
|
||||
|
||||
init: function() {
|
||||
@ -166,6 +167,10 @@ var FullScreen = {
|
||||
this._windowUtils.remoteFrameFullscreenReverted();
|
||||
break;
|
||||
}
|
||||
case "DOMFullscreen:Painted": {
|
||||
Services.obs.notifyObservers(window, "fullscreen-painted", "");
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -82,7 +82,6 @@
|
||||
<command id="Browser:PrevTab" oncommand="gBrowser.tabContainer.advanceSelectedTab(-1, true);" reserved="true"/>
|
||||
<command id="Browser:ShowAllTabs" oncommand="allTabs.open();"/>
|
||||
<command id="Browser:ToggleTabView" oncommand="TabView.toggle();"/>
|
||||
<command id="Browser:FocusNextFrame" oncommand="focusNextFrame(event);"/>
|
||||
<command id="cmd_fullZoomReduce" oncommand="FullZoom.reduce()"/>
|
||||
<command id="cmd_fullZoomEnlarge" oncommand="FullZoom.enlarge()"/>
|
||||
<command id="cmd_fullZoomReset" oncommand="FullZoom.reset()"/>
|
||||
@ -357,8 +356,6 @@
|
||||
#endif
|
||||
<key id="goHome" keycode="VK_HOME" command="Browser:Home" modifiers="alt"/>
|
||||
<key keycode="VK_F5" command="Browser:Reload"/>
|
||||
<key keycode="VK_F6" command="Browser:FocusNextFrame"/>
|
||||
<key keycode="VK_F6" command="Browser:FocusNextFrame" modifiers="shift"/>
|
||||
#ifndef XP_MACOSX
|
||||
<key id="showAllHistoryKb" key="&showAllHistoryCmd.commandkey;" command="Browser:ShowAllHistory" modifiers="accel,shift"/>
|
||||
<key keycode="VK_F5" command="Browser:ReloadSkipCache" modifiers="accel"/>
|
||||
|
@ -7648,16 +7648,6 @@ var MousePosTracker = {
|
||||
}
|
||||
};
|
||||
|
||||
function focusNextFrame(event) {
|
||||
let fm = Services.focus;
|
||||
let dir = event.shiftKey ? fm.MOVEFOCUS_BACKWARDDOC : fm.MOVEFOCUS_FORWARDDOC;
|
||||
let element = fm.moveFocus(window, null, dir, fm.FLAG_BYKEY);
|
||||
let panelOrNotificationSelector = "popupnotification " + element.localName + ", " +
|
||||
"panel " + element.localName;
|
||||
if (element.ownerDocument == document && !element.matches(panelOrNotificationSelector))
|
||||
focusAndSelectUrlBar();
|
||||
}
|
||||
|
||||
function BrowserOpenNewTabOrWindow(event) {
|
||||
if (event.shiftKey) {
|
||||
OpenBrowserWindow();
|
||||
|
@ -58,6 +58,7 @@
|
||||
screenX="4" screenY="4"
|
||||
fullscreenbutton="true"
|
||||
sizemode="normal"
|
||||
retargetdocumentfocus="urlbar"
|
||||
persist="screenX screenY width height sizemode">
|
||||
|
||||
# All JS files which are not content (only) dependent that browser.xul
|
||||
|
@ -624,8 +624,10 @@ let DOMFullscreenHandler = {
|
||||
addMessageListener("DOMFullscreen:Approved", this);
|
||||
addMessageListener("DOMFullscreen:CleanUp", this);
|
||||
addEventListener("MozDOMFullscreen:Request", this);
|
||||
addEventListener("MozDOMFullscreen:Entered", this);
|
||||
addEventListener("MozDOMFullscreen:NewOrigin", this);
|
||||
addEventListener("MozDOMFullscreen:Exit", this);
|
||||
addEventListener("MozDOMFullscreen:Exited", this);
|
||||
},
|
||||
|
||||
get _windowUtils() {
|
||||
@ -678,6 +680,16 @@ let DOMFullscreenHandler = {
|
||||
sendAsyncMessage("DOMFullscreen:Exit");
|
||||
break;
|
||||
}
|
||||
case "MozDOMFullscreen:Entered":
|
||||
case "MozDOMFullscreen:Exited": {
|
||||
addEventListener("MozAfterPaint", this);
|
||||
break;
|
||||
}
|
||||
case "MozAfterPaint": {
|
||||
removeEventListener("MozAfterPaint", this);
|
||||
sendAsyncMessage("DOMFullscreen:Painted");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -57,6 +57,7 @@ support-files =
|
||||
file_bug970276_popup2.html
|
||||
file_bug970276_favicon1.ico
|
||||
file_bug970276_favicon2.ico
|
||||
file_documentnavigation_frameset.html
|
||||
file_dom_notifications.html
|
||||
file_double_close_tab.html
|
||||
file_favicon_change.html
|
||||
@ -287,6 +288,7 @@ skip-if = e10s # Bug 1071623
|
||||
[browser_discovery.js]
|
||||
[browser_double_close_tab.js]
|
||||
skip-if = e10s
|
||||
[browser_documentnavigation.js]
|
||||
[browser_duplicateIDs.js]
|
||||
[browser_drag.js]
|
||||
skip-if = true # browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
|
||||
|
266
browser/base/content/test/general/browser_documentnavigation.js
Normal file
266
browser/base/content/test/general/browser_documentnavigation.js
Normal file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
* This test checks that focus is adjusted properly in a browser when pressing F6 and Shift+F6.
|
||||
* There are additional tests in dom/tests/mochitest/chrome/test_focus_docnav.xul which test
|
||||
* non-browser cases.
|
||||
*/
|
||||
|
||||
let testPage1 = "data:text/html,<html id='html1'><body id='body1'><button id='button1'>Tab 1</button></body></html>";
|
||||
let testPage2 = "data:text/html,<html id='html2'><body id='body2'><button id='button2'>Tab 2</button></body></html>";
|
||||
let testPage3 = "data:text/html,<html id='html3'><body id='body3' contenteditable='true'><button id='button3'>Tab 3</button></body></html>";
|
||||
|
||||
let fm = Services.focus;
|
||||
|
||||
function* expectFocusOnF6(backward, expectedDocument, expectedElement, onContent, desc)
|
||||
{
|
||||
let focusChangedInChildResolver = null;
|
||||
let focusPromise = onContent ? new Promise(resolve => focusChangedInChildResolver = resolve) :
|
||||
BrowserTestUtils.waitForEvent(window, "focus", true);
|
||||
|
||||
function focusChangedListener(msg) {
|
||||
let expected = expectedDocument;
|
||||
if (!expectedElement.startsWith("html")) {
|
||||
expected += "," + expectedElement;
|
||||
}
|
||||
|
||||
is(msg.data.details, expected, desc + " child focus matches");
|
||||
focusChangedInChildResolver();
|
||||
}
|
||||
|
||||
if (onContent) {
|
||||
messageManager.addMessageListener("BrowserTest:FocusChanged", focusChangedListener);
|
||||
|
||||
yield ContentTask.spawn(gBrowser.selectedBrowser, { expectedElementId: expectedElement }, function* (arg) {
|
||||
let expectedElement = content.document.getElementById(arg.expectedElementId);
|
||||
if (!expectedElement) {
|
||||
// Element not found, so look in the child frames.
|
||||
for (let f = 0; f < content.frames.length; f++) {
|
||||
if (content.frames[f].document.getElementById(arg.expectedElementId)) {
|
||||
expectedElement = content.frames[f].document;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (expectedElement.localName == "html") {
|
||||
expectedElement = expectedElement.ownerDocument;
|
||||
}
|
||||
|
||||
if (!expectedElement) {
|
||||
sendSyncMessage("BrowserTest:FocusChanged",
|
||||
{ details : "expected element " + arg.expectedElementId + " not found" });
|
||||
return;
|
||||
}
|
||||
|
||||
expectedElement.addEventListener("focus", function focusReceived() {
|
||||
expectedElement.removeEventListener("focus", focusReceived, true);
|
||||
|
||||
const fm = Components.classes["@mozilla.org/focus-manager;1"].
|
||||
getService(Components.interfaces.nsIFocusManager);
|
||||
let details = fm.focusedWindow.document.documentElement.id;
|
||||
if (fm.focusedElement) {
|
||||
details += "," + fm.focusedElement.id;
|
||||
}
|
||||
|
||||
sendSyncMessage("BrowserTest:FocusChanged", { details : details });
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
|
||||
EventUtils.synthesizeKey("VK_F6", { shiftKey: backward });
|
||||
yield focusPromise;
|
||||
|
||||
if (typeof expectedElement == "string") {
|
||||
expectedElement = fm.focusedWindow.document.getElementById(expectedElement);
|
||||
}
|
||||
|
||||
if (gMultiProcessBrowser && onContent) {
|
||||
expectedDocument = "main-window";
|
||||
expectedElement = gBrowser.selectedBrowser;
|
||||
}
|
||||
|
||||
is(fm.focusedWindow.document.documentElement.id, expectedDocument, desc + " document matches");
|
||||
is(fm.focusedElement, expectedElement, desc + " element matches");
|
||||
|
||||
if (onContent) {
|
||||
messageManager.removeMessageListener("BrowserTest:FocusChanged", focusChangedListener);
|
||||
}
|
||||
}
|
||||
|
||||
// Load a page and navigate between it and the chrome window.
|
||||
add_task(function* ()
|
||||
{
|
||||
let page1Promise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||
gBrowser.selectedBrowser.loadURI(testPage1);
|
||||
yield page1Promise;
|
||||
|
||||
// When the urlbar is focused, pressing F6 should focus the root of the content page.
|
||||
gURLBar.focus();
|
||||
yield* expectFocusOnF6(false, "html1", "html1",
|
||||
true, "basic focus content page");
|
||||
|
||||
// When the content is focused, pressing F6 should focus the urlbar.
|
||||
yield* expectFocusOnF6(false, "main-window", gURLBar.inputField,
|
||||
false, "basic focus content page urlbar");
|
||||
|
||||
// When a button in content is focused, pressing F6 should focus the urlbar.
|
||||
yield* expectFocusOnF6(false, "html1", "html1",
|
||||
true, "basic focus content page with button focused");
|
||||
|
||||
return ContentTask.spawn(gBrowser.selectedBrowser, { }, function* () {
|
||||
return content.document.getElementById("button1").focus();
|
||||
});
|
||||
|
||||
yield* expectFocusOnF6(false, "main-window", gURLBar.inputField,
|
||||
false, "basic focus content page with button focused urlbar");
|
||||
|
||||
// The document root should be focused, not the button
|
||||
yield* expectFocusOnF6(false, "html1", "html1",
|
||||
true, "basic focus again content page with button focused");
|
||||
|
||||
// Check to ensure that the root element is focused
|
||||
let match = yield ContentTask.spawn(gBrowser.selectedBrowser, { }, function* () {
|
||||
return content.document.activeElement == content.document.documentElement;
|
||||
});
|
||||
ok(match, "basic focus again content page with button focused child root is focused");
|
||||
});
|
||||
|
||||
// Open a second tab. Document focus should skip the background tab.
|
||||
add_task(function* ()
|
||||
{
|
||||
yield BrowserTestUtils.openNewForegroundTab(gBrowser, testPage2);
|
||||
|
||||
yield* expectFocusOnF6(false, "main-window", gURLBar.inputField,
|
||||
false, "basic focus content page and second tab urlbar");
|
||||
yield* expectFocusOnF6(false, "html2", "html2",
|
||||
true, "basic focus content page with second tab");
|
||||
|
||||
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
|
||||
// Shift+F6 should navigate backwards. There's only one document here so the effect
|
||||
// is the same.
|
||||
add_task(function* ()
|
||||
{
|
||||
gURLBar.focus();
|
||||
yield* expectFocusOnF6(true, "html1", "html1",
|
||||
true, "back focus content page");
|
||||
yield* expectFocusOnF6(true, "main-window", gURLBar.inputField,
|
||||
false, "back focus content page urlbar");
|
||||
});
|
||||
|
||||
// Open the sidebar and navigate between the sidebar, content and top-level window
|
||||
add_task(function* ()
|
||||
{
|
||||
let sidebar = document.getElementById("sidebar");
|
||||
|
||||
let loadPromise = BrowserTestUtils.waitForEvent(sidebar, "load", true);
|
||||
SidebarUI.toggle('viewBookmarksSidebar');
|
||||
yield loadPromise;
|
||||
|
||||
|
||||
gURLBar.focus();
|
||||
yield* expectFocusOnF6(false, "bookmarksPanel",
|
||||
sidebar.contentDocument.getElementById("search-box").inputField,
|
||||
false, "focus with sidebar open sidebar");
|
||||
yield* expectFocusOnF6(false, "html1", "html1",
|
||||
true, "focus with sidebar open content");
|
||||
yield* expectFocusOnF6(false, "main-window", gURLBar.inputField,
|
||||
false, "focus with sidebar urlbar");
|
||||
|
||||
// Now go backwards
|
||||
yield* expectFocusOnF6(true, "html1", "html1",
|
||||
true, "back focus with sidebar open content");
|
||||
yield* expectFocusOnF6(true, "bookmarksPanel",
|
||||
sidebar.contentDocument.getElementById("search-box").inputField,
|
||||
false, "back focus with sidebar open sidebar");
|
||||
yield* expectFocusOnF6(true, "main-window", gURLBar.inputField,
|
||||
false, "back focus with sidebar urlbar");
|
||||
|
||||
SidebarUI.toggle('viewBookmarksSidebar');
|
||||
});
|
||||
|
||||
// Navigate when the downloads panel is open
|
||||
add_task(function* ()
|
||||
{
|
||||
yield pushPrefs(["accessibility.tabfocus", 7]);
|
||||
|
||||
let popupShownPromise = BrowserTestUtils.waitForEvent(document, "popupshown", true);
|
||||
EventUtils.synthesizeMouseAtCenter(document.getElementById("downloads-button"), { });
|
||||
yield popupShownPromise;
|
||||
|
||||
gURLBar.focus();
|
||||
yield* expectFocusOnF6(false, "main-window", document.getElementById("downloadsHistory"),
|
||||
false, "focus with downloads panel open panel");
|
||||
yield* expectFocusOnF6(false, "html1", "html1",
|
||||
true, "focus with downloads panel open");
|
||||
yield* expectFocusOnF6(false, "main-window", gURLBar.inputField,
|
||||
false, "focus downloads panel open urlbar");
|
||||
|
||||
// Now go backwards
|
||||
yield* expectFocusOnF6(true, "html1", "html1",
|
||||
true, "back focus with downloads panel open");
|
||||
yield* expectFocusOnF6(true, "main-window", document.getElementById("downloadsHistory"),
|
||||
false, "back focus with downloads panel open");
|
||||
yield* expectFocusOnF6(true, "main-window", gURLBar.inputField,
|
||||
false, "back focus downloads panel open urlbar");
|
||||
|
||||
let downloadsPopup = document.getElementById("downloadsPanel");
|
||||
let popupHiddenPromise = BrowserTestUtils.waitForEvent(downloadsPopup, "popuphidden", true);
|
||||
downloadsPopup.hidePopup();
|
||||
yield popupHiddenPromise;
|
||||
});
|
||||
|
||||
// Navigation with a contenteditable body
|
||||
add_task(function* ()
|
||||
{
|
||||
yield BrowserTestUtils.openNewForegroundTab(gBrowser, testPage3);
|
||||
|
||||
// The body should be focused when it is editable, not the root.
|
||||
gURLBar.focus();
|
||||
yield* expectFocusOnF6(false, "html3", "body3",
|
||||
true, "focus with contenteditable body");
|
||||
yield* expectFocusOnF6(false, "main-window", gURLBar.inputField,
|
||||
false, "focus with contenteditable body urlbar");
|
||||
|
||||
// Now go backwards
|
||||
|
||||
yield* expectFocusOnF6(false, "html3", "body3",
|
||||
true, "back focus with contenteditable body");
|
||||
yield* expectFocusOnF6(false, "main-window", gURLBar.inputField,
|
||||
false, "back focus with contenteditable body urlbar");
|
||||
|
||||
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
|
||||
// Navigation with a frameset loaded
|
||||
add_task(function* ()
|
||||
{
|
||||
yield BrowserTestUtils.openNewForegroundTab(gBrowser,
|
||||
"http://mochi.test:8888/browser/browser/base/content/test/general/file_documentnavigation_frameset.html");
|
||||
|
||||
gURLBar.focus();
|
||||
yield* expectFocusOnF6(false, "htmlframe1", "htmlframe1",
|
||||
true, "focus on frameset frame 0");
|
||||
yield* expectFocusOnF6(false, "htmlframe2", "htmlframe2",
|
||||
true, "focus on frameset frame 1");
|
||||
yield* expectFocusOnF6(false, "htmlframe3", "htmlframe3",
|
||||
true, "focus on frameset frame 2");
|
||||
yield* expectFocusOnF6(false, "htmlframe4", "htmlframe4",
|
||||
true, "focus on frameset frame 3");
|
||||
yield* expectFocusOnF6(false, "main-window", gURLBar.inputField,
|
||||
false, "focus on frameset frame urlbar");
|
||||
|
||||
yield* expectFocusOnF6(true, "htmlframe4", "htmlframe4",
|
||||
true, "back focus on frameset frame 3");
|
||||
yield* expectFocusOnF6(true, "htmlframe3", "htmlframe3",
|
||||
true, "back focus on frameset frame 2");
|
||||
yield* expectFocusOnF6(true, "htmlframe2", "htmlframe2",
|
||||
true, "back focus on frameset frame 1");
|
||||
yield* expectFocusOnF6(true, "htmlframe1", "htmlframe1",
|
||||
true, "back focus on frameset frame 0");
|
||||
yield* expectFocusOnF6(true, "main-window", gURLBar.inputField,
|
||||
false, "back focus on frameset frame urlbar");
|
||||
|
||||
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
|
||||
// XXXndeakin add tests for browsers inside of panels
|
@ -121,6 +121,10 @@ let gTests = [
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
yield pushPrefs(
|
||||
["full-screen-api.transition-duration.enter", "0 0"],
|
||||
["full-screen-api.transition-duration.leave", "0 0"]);
|
||||
|
||||
let tab = gBrowser.addTab("about:robots");
|
||||
let browser = tab.linkedBrowser;
|
||||
gBrowser.selectedTab = tab;
|
||||
|
@ -0,0 +1,12 @@
|
||||
<html id="outer">
|
||||
|
||||
<frameset rows="30%, 70%">
|
||||
<frame src="data:text/html,<html id='htmlframe1' ><body id='framebody1'><input id='i1'><body></html>">
|
||||
<frameset cols="30%, 33%, 34%">
|
||||
<frame src="data:text/html,<html id='htmlframe2'><body id='framebody2'><input id='i2'><body></html>">
|
||||
<frame src="data:text/html,<html id='htmlframe3'><body id='framebody3'><input id='i3'><body></html>">
|
||||
<frame src="data:text/html,<html id='htmlframe4'><body id='framebody4'><input id='i4'><body></html>">
|
||||
</frameset>
|
||||
</frameset>
|
||||
|
||||
</html>
|
@ -507,6 +507,8 @@ function runTest(testNum) {
|
||||
subwindow.addEventListener("mozfullscreenchange", openDomFullScreen, false);
|
||||
SpecialPowers.setBoolPref("full-screen-api.approval-required", false);
|
||||
SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", false);
|
||||
SpecialPowers.setCharPref("full-screen-api.transition-duration.enter", "0 0");
|
||||
SpecialPowers.setCharPref("full-screen-api.transition-duration.leave", "0 0");
|
||||
full_screen_element.mozRequestFullScreen();
|
||||
},
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
oncommand="goDoCommand('downloadsCmd_clearList')"/>
|
||||
</commandset>
|
||||
|
||||
<popupset>
|
||||
<popupset id="mainPopupSet">
|
||||
<!-- The panel has level="top" to ensure that it is never hidden by the
|
||||
taskbar on Windows. See bug 672365. For accessibility to screen
|
||||
readers, we use a label on the panel instead of the anchor because the
|
||||
|
@ -37,7 +37,7 @@ namespace {
|
||||
return PR_ImplodeTime(&prt);
|
||||
}
|
||||
|
||||
} // Anonymous namespace.
|
||||
} // namespace
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// nsIEHistoryEnumerator
|
||||
|
@ -353,7 +353,7 @@ skip-if = e10s && debug
|
||||
[browser_dbg_promises-allocation-stack.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_promises-chrome-allocation-stack.js]
|
||||
skip-if = (e10s || os == "linux") && debug
|
||||
skip-if = (e10s && debug) || os == "linux" # Bug 1177730
|
||||
[browser_dbg_reload-preferred-script-01.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_reload-preferred-script-02.js]
|
||||
|
@ -235,6 +235,25 @@ public:
|
||||
return attr->getAnnotation() == spelling;
|
||||
}
|
||||
|
||||
void HandleUnusedExprResult(const Stmt *stmt) {
|
||||
const Expr* E = dyn_cast_or_null<Expr>(stmt);
|
||||
if (E) {
|
||||
// XXX It would be nice if we could use getAsTagDecl,
|
||||
// but our version of clang is too old.
|
||||
// (getAsTagDecl would also cover enums etc.)
|
||||
QualType T = E->getType();
|
||||
CXXRecordDecl *decl = T->getAsCXXRecordDecl();
|
||||
if (decl) {
|
||||
decl = decl->getDefinition();
|
||||
if (decl && hasCustomAnnotation(decl, "moz_must_use")) {
|
||||
unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
|
||||
DiagnosticIDs::Error, "Unused MOZ_MUST_USE value of type %0");
|
||||
Diag.Report(E->getLocStart(), errorID) << T;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool VisitCXXRecordDecl(CXXRecordDecl *d) {
|
||||
// We need definitions, not declarations
|
||||
if (!d->isThisDeclarationADefinition()) return true;
|
||||
@ -317,6 +336,41 @@ public:
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitSwitchCase(SwitchCase* stmt) {
|
||||
HandleUnusedExprResult(stmt->getSubStmt());
|
||||
return true;
|
||||
}
|
||||
bool VisitCompoundStmt(CompoundStmt* stmt) {
|
||||
for (CompoundStmt::body_iterator it = stmt->body_begin(), e = stmt->body_end();
|
||||
it != e; ++it) {
|
||||
HandleUnusedExprResult(*it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool VisitIfStmt(IfStmt* Stmt) {
|
||||
HandleUnusedExprResult(Stmt->getThen());
|
||||
HandleUnusedExprResult(Stmt->getElse());
|
||||
return true;
|
||||
}
|
||||
bool VisitWhileStmt(WhileStmt* Stmt) {
|
||||
HandleUnusedExprResult(Stmt->getBody());
|
||||
return true;
|
||||
}
|
||||
bool VisitDoStmt(DoStmt* Stmt) {
|
||||
HandleUnusedExprResult(Stmt->getBody());
|
||||
return true;
|
||||
}
|
||||
bool VisitForStmt(ForStmt* Stmt) {
|
||||
HandleUnusedExprResult(Stmt->getBody());
|
||||
HandleUnusedExprResult(Stmt->getInit());
|
||||
HandleUnusedExprResult(Stmt->getInc());
|
||||
return true;
|
||||
}
|
||||
bool VisitBinComma(BinaryOperator* Op) {
|
||||
HandleUnusedExprResult(Op->getLHS());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
156
build/clang-plugin/tests/TestMustUse.cpp
Normal file
156
build/clang-plugin/tests/TestMustUse.cpp
Normal file
@ -0,0 +1,156 @@
|
||||
#define MOZ_MUST_USE __attribute__((annotate("moz_must_use")))
|
||||
|
||||
class MOZ_MUST_USE MustUse {};
|
||||
class MayUse {};
|
||||
|
||||
MustUse producesMustUse();
|
||||
MustUse *producesMustUsePointer();
|
||||
MustUse &producesMustUseRef();
|
||||
|
||||
MayUse producesMayUse();
|
||||
MayUse *producesMayUsePointer();
|
||||
MayUse &producesMayUseRef();
|
||||
|
||||
void use(MustUse*);
|
||||
void use(MustUse&);
|
||||
void use(MustUse&&);
|
||||
void use(MayUse*);
|
||||
void use(MayUse&);
|
||||
void use(MayUse&&);
|
||||
void use(bool);
|
||||
|
||||
void foo() {
|
||||
producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
producesMustUsePointer();
|
||||
producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
producesMayUse();
|
||||
producesMayUsePointer();
|
||||
producesMayUseRef();
|
||||
{
|
||||
producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
producesMustUsePointer();
|
||||
producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
producesMayUse();
|
||||
producesMayUsePointer();
|
||||
producesMayUseRef();
|
||||
}
|
||||
if (true) {
|
||||
producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
producesMustUsePointer();
|
||||
producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
producesMayUse();
|
||||
producesMayUsePointer();
|
||||
producesMayUseRef();
|
||||
} else {
|
||||
producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
producesMustUsePointer();
|
||||
producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
producesMayUse();
|
||||
producesMayUsePointer();
|
||||
producesMayUseRef();
|
||||
}
|
||||
|
||||
if(true) producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
else producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
if(true) producesMustUsePointer();
|
||||
else producesMustUsePointer();
|
||||
if(true) producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
else producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
if(true) producesMayUse();
|
||||
else producesMayUse();
|
||||
if(true) producesMayUsePointer();
|
||||
else producesMayUsePointer();
|
||||
if(true) producesMayUseRef();
|
||||
else producesMayUseRef();
|
||||
|
||||
while (true) producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
while (true) producesMustUsePointer();
|
||||
while (true) producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
while (true) producesMayUse();
|
||||
while (true) producesMayUsePointer();
|
||||
while (true) producesMayUseRef();
|
||||
|
||||
do producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
while (true);
|
||||
do producesMustUsePointer();
|
||||
while (true);
|
||||
do producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
while (true);
|
||||
do producesMayUse();
|
||||
while (true);
|
||||
do producesMayUsePointer();
|
||||
while (true);
|
||||
do producesMayUseRef();
|
||||
while (true);
|
||||
|
||||
for (;;) producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
for (;;) producesMustUsePointer();
|
||||
for (;;) producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
for (;;) producesMayUse();
|
||||
for (;;) producesMayUsePointer();
|
||||
for (;;) producesMayUseRef();
|
||||
|
||||
for (producesMustUse();;); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
for (producesMustUsePointer();;);
|
||||
for (producesMustUseRef();;); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
for (producesMayUse();;);
|
||||
for (producesMayUsePointer();;);
|
||||
for (producesMayUseRef();;);
|
||||
|
||||
for (;;producesMustUse()); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
for (;;producesMustUsePointer());
|
||||
for (;;producesMustUseRef()); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
for (;;producesMayUse());
|
||||
for (;;producesMayUsePointer());
|
||||
for (;;producesMayUseRef());
|
||||
|
||||
use((producesMustUse(), false)); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
use((producesMustUsePointer(), false));
|
||||
use((producesMustUseRef(), false)); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
use((producesMayUse(), false));
|
||||
use((producesMayUsePointer(), false));
|
||||
use((producesMayUseRef(), false));
|
||||
|
||||
switch (1) {
|
||||
case 1:
|
||||
producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
producesMustUsePointer();
|
||||
producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
producesMayUse();
|
||||
producesMayUsePointer();
|
||||
producesMayUseRef();
|
||||
case 2:
|
||||
producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
case 3:
|
||||
producesMustUsePointer();
|
||||
case 4:
|
||||
producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
case 5:
|
||||
producesMayUse();
|
||||
case 6:
|
||||
producesMayUsePointer();
|
||||
case 7:
|
||||
producesMayUseRef();
|
||||
default:
|
||||
producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
producesMustUsePointer();
|
||||
producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
|
||||
producesMayUse();
|
||||
producesMayUsePointer();
|
||||
producesMayUseRef();
|
||||
}
|
||||
|
||||
use(producesMustUse());
|
||||
use(producesMustUsePointer());
|
||||
use(producesMustUseRef());
|
||||
use(producesMayUse());
|
||||
use(producesMayUsePointer());
|
||||
use(producesMayUseRef());
|
||||
|
||||
MustUse a = producesMustUse();
|
||||
MustUse *b = producesMustUsePointer();
|
||||
MustUse &c = producesMustUseRef();
|
||||
MayUse d = producesMayUse();
|
||||
MayUse *e = producesMayUsePointer();
|
||||
MayUse &f = producesMayUseRef();
|
||||
}
|
@ -10,6 +10,7 @@ SOURCES += [
|
||||
'TestExplicitOperatorBool.cpp',
|
||||
'TestGlobalClass.cpp',
|
||||
'TestMustOverride.cpp',
|
||||
'TestMustUse.cpp',
|
||||
'TestNANTestingExpr.cpp',
|
||||
'TestNANTestingExprC.c',
|
||||
'TestNoAddRefReleaseOnReturn.cpp',
|
||||
|
@ -108,7 +108,7 @@ private:
|
||||
OriginAttributes* mOriginAttributes;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
bool
|
||||
OriginAttributes::PopulateFromSuffix(const nsACString& aStr)
|
||||
|
@ -15,7 +15,7 @@ namespace mozilla {
|
||||
|
||||
namespace ipc {
|
||||
class URIParams;
|
||||
};
|
||||
} // namespace ipc
|
||||
|
||||
enum DomainSetChangeType{
|
||||
ACTIVATE_POLICY,
|
||||
|
@ -24,7 +24,7 @@ class nsSystemPrincipal;
|
||||
|
||||
namespace mozilla {
|
||||
class OriginAttributes;
|
||||
}
|
||||
} // namespace mozilla
|
||||
|
||||
/////////////////////////////
|
||||
// nsScriptSecurityManager //
|
||||
|
@ -197,6 +197,6 @@ struct ParamTraits<OverrideMapping>
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace IPC
|
||||
|
||||
#endif // RegistryMessageUtils_h
|
||||
|
@ -15,8 +15,8 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class PContentParent;
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsIPrefBranch;
|
||||
struct ChromePackage;
|
||||
|
@ -15,7 +15,7 @@ namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
class Link;
|
||||
}
|
||||
} // namespace dom
|
||||
|
||||
// 0057c9d3-b98e-4933-bdc5-0275d06705e1
|
||||
#define IHISTORY_IID \
|
||||
|
@ -2804,16 +2804,16 @@ nsDocShell::GetBusyFlags(uint32_t* aBusyFlags)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::TabToTreeOwner(bool aForward, bool* aTookFocus)
|
||||
nsDocShell::TabToTreeOwner(bool aForward, bool aForDocumentNavigation, bool* aTookFocus)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aTookFocus);
|
||||
|
||||
nsCOMPtr<nsIWebBrowserChromeFocus> chromeFocus = do_GetInterface(mTreeOwner);
|
||||
if (chromeFocus) {
|
||||
if (aForward) {
|
||||
*aTookFocus = NS_SUCCEEDED(chromeFocus->FocusNextElement());
|
||||
*aTookFocus = NS_SUCCEEDED(chromeFocus->FocusNextElement(aForDocumentNavigation));
|
||||
} else {
|
||||
*aTookFocus = NS_SUCCEEDED(chromeFocus->FocusPrevElement());
|
||||
*aTookFocus = NS_SUCCEEDED(chromeFocus->FocusPrevElement(aForDocumentNavigation));
|
||||
}
|
||||
} else {
|
||||
*aTookFocus = false;
|
||||
@ -8420,7 +8420,8 @@ private:
|
||||
mRestorePresentationEvent;
|
||||
nsRefPtr<nsDocShell::RestorePresentationEvent> mEvent;
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
nsresult
|
||||
nsDocShell::RestoreFromHistory()
|
||||
@ -9448,7 +9449,7 @@ private:
|
||||
NS_IMPL_ISUPPORTS(nsCopyFaviconCallback, nsIFaviconDataCallback)
|
||||
#endif
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
void
|
||||
nsDocShell::CopyFavicon(nsIURI* aOldURI,
|
||||
|
@ -60,8 +60,8 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class EventTarget;
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsDocShell;
|
||||
class nsDOMNavigationTiming;
|
||||
|
@ -46,7 +46,7 @@ interface nsITabParent;
|
||||
|
||||
typedef unsigned long nsLoadFlags;
|
||||
|
||||
[scriptable, builtinclass, uuid(b3137b7c-d589-48aa-b89b-e02aa451d42c)]
|
||||
[scriptable, builtinclass, uuid(97471054-0BC8-4A57-BBFE-6C255BCBBB67)]
|
||||
interface nsIDocShell : nsIDocShellTreeItem
|
||||
{
|
||||
/**
|
||||
@ -347,9 +347,12 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||
/*
|
||||
* Tells the docshell to offer focus to its tree owner.
|
||||
* This is currently only necessary for embedding chrome.
|
||||
* If forDocumentNavigation is true, then document navigation should be
|
||||
* performed, where only the root of documents are selected. Otherwise, the
|
||||
* next element in the parent should be returned. Returns true if focus was
|
||||
* successfully taken by the tree owner.
|
||||
*/
|
||||
void tabToTreeOwner(in boolean forward,
|
||||
out boolean tookFocus);
|
||||
bool tabToTreeOwner(in boolean forward, in boolean forDocumentNavigation);
|
||||
|
||||
/**
|
||||
* Current busy state for DocShell
|
||||
|
@ -27,7 +27,7 @@ namespace {
|
||||
|
||||
uint64_t gSHEntrySharedID = 0;
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
#define CONTENT_VIEWER_TIMEOUT_SECONDS "browser.sessionhistory.contentViewerTimeout"
|
||||
// Default this to time out unused content viewers after 30 minutes
|
||||
|
@ -227,7 +227,7 @@ EvictContentViewerForTransaction(nsISHTransaction* aTrans)
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
nsSHistory::nsSHistory()
|
||||
: mIndex(-1)
|
||||
@ -1046,7 +1046,7 @@ public:
|
||||
int32_t mDistance;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
void
|
||||
|
@ -116,6 +116,6 @@ AlarmHalService::Notify(const int64_t& aClockDeltaMS)
|
||||
mSystemClockChangedCb->OnSystemClockChanged(aClockDeltaMS);
|
||||
}
|
||||
|
||||
} // alarm
|
||||
} // dom
|
||||
} // mozilla
|
||||
} // namespace alarm
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -28,7 +28,7 @@ namespace {
|
||||
AnimationTimeline* mTimeline;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
static PLDHashOperator
|
||||
AppendAnimationToSequence(nsRefPtrHashKey<dom::Animation>* aKey,
|
||||
|
@ -81,7 +81,8 @@ for (var funcName of ["async_test", "assert_not_equals", "assert_equals",
|
||||
"assert_approx_equals", "assert_less_than",
|
||||
"assert_less_than_equal", "assert_between_inclusive",
|
||||
"assert_true", "assert_false",
|
||||
"assert_class_string", "assert_throws", "test"]) {
|
||||
"assert_class_string", "assert_throws",
|
||||
"assert_unreached", "test"]) {
|
||||
window[funcName] = opener[funcName].bind(opener);
|
||||
}
|
||||
|
||||
|
@ -1618,7 +1618,7 @@ OpenFile(nsIPrincipal* aPrincipal,
|
||||
return JS::AsmJSCache_Success;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
typedef uint32_t AsmJSCookieType;
|
||||
static const uint32_t sAsmJSCookie = 0x600d600d;
|
||||
|
@ -19,7 +19,7 @@ namespace dom {
|
||||
|
||||
namespace quota {
|
||||
class Client;
|
||||
}
|
||||
} // namespace quota
|
||||
|
||||
namespace asmjscache {
|
||||
|
||||
|
@ -65,4 +65,5 @@ private:
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -138,5 +138,5 @@ AnonymousContent::WrapObject(JSContext* aCx,
|
||||
return AnonymousContentBinding::Wrap(aCx, this, aGivenProto, aReflector);
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -58,7 +58,7 @@ private:
|
||||
nsCOMPtr<Element> mContentNode;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_AnonymousContent_h
|
||||
|
@ -83,7 +83,7 @@ protected:
|
||||
uint64_t mDataBufferLen;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_BlobSet_h
|
||||
|
@ -345,5 +345,6 @@ AllChildrenIterator::GetNextChild()
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -28,5 +28,6 @@ ChromeUtils::OriginAttributesToSuffix(dom::GlobalObject& aGlobal,
|
||||
OriginAttributes attrs(aAttrs);
|
||||
attrs.CreateSuffix(aSuffix);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -16,7 +16,7 @@ namespace mozilla {
|
||||
|
||||
namespace devtools {
|
||||
class HeapSnapshot;
|
||||
}
|
||||
} // namespace devtools
|
||||
|
||||
namespace dom {
|
||||
|
||||
|
@ -1469,7 +1469,7 @@ FlushOutput(JSContext* aCx, Sequence<JS::Value>& aSequence, nsString &aOutput)
|
||||
return true;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
bool
|
||||
Console::ProcessArguments(JSContext* aCx,
|
||||
|
@ -221,7 +221,7 @@ private:
|
||||
friend class ConsoleProfileRunnable;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_dom_Console_h */
|
||||
|
@ -248,7 +248,7 @@ private:
|
||||
void Ensure3DMatrix();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /*MOZILLA_DOM_DOMMATRIX_H_*/
|
||||
|
@ -73,7 +73,7 @@ public:
|
||||
void SetW(double aW) { mW = aW; }
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /*MOZILLA_DOMPOINT_H_*/
|
||||
|
@ -65,7 +65,7 @@ protected:
|
||||
mutable nsRefPtr<QuadBounds> mBounds; // allocated lazily
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /*MOZILLA_DOMRECT_H_*/
|
||||
|
@ -210,8 +210,7 @@ protected:
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /*MOZILLA_DOMRECT_H_*/
|
||||
|
@ -25,7 +25,7 @@ Element::UnregisterActivityObserver()
|
||||
OwnerDoc()->UnregisterActivityObserver(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_ElementInlines_h
|
||||
|
@ -1333,5 +1333,5 @@ BlobSet::AppendBlobImpls(const nsTArray<nsRefPtr<BlobImpl>>& aBlobImpls)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -42,7 +42,7 @@ namespace dom {
|
||||
|
||||
namespace indexedDB {
|
||||
class FileInfo;
|
||||
};
|
||||
} // namespace indexedDB
|
||||
|
||||
struct BlobPropertyBag;
|
||||
struct ChromeFilePropertyBag;
|
||||
@ -1038,7 +1038,7 @@ private:
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
} // file namespace
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_File_h
|
||||
|
@ -2335,7 +2335,7 @@ private:
|
||||
uint32_t mLength;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
static void
|
||||
AppendEncodedCharacters(const nsTextFragment* aText, StringBuilder& aBuilder)
|
||||
|
@ -35,8 +35,8 @@ class nsIURI;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Element;
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
* A class that implements nsIWeakReference
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "mozilla/gfx/DataSurfaceHelpers.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/SyncRunnable.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
@ -206,7 +207,7 @@ public:
|
||||
rv = NS_DispatchToMainThread(mEncodingCompleteEvent);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Better to leak than to crash.
|
||||
mEncodingCompleteEvent.forget();
|
||||
unused << mEncodingCompleteEvent.forget();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ namespace mozilla {
|
||||
|
||||
namespace layers {
|
||||
class Image;
|
||||
}
|
||||
} // namespace layers
|
||||
|
||||
namespace dom {
|
||||
|
||||
|
@ -778,7 +778,7 @@ VibrateWindowListener::RemoveListener()
|
||||
true /* use capture */);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
void
|
||||
Navigator::AddIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv)
|
||||
|
@ -41,8 +41,8 @@ class WakeLock;
|
||||
class ArrayBufferViewOrBlobOrStringOrFormData;
|
||||
struct MobileIdOptions;
|
||||
class ServiceWorkerContainer;
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
//*****************************************************************************
|
||||
// Navigator: Script "navigator" object
|
||||
@ -75,7 +75,7 @@ class MozGetUserMediaDevicesSuccessCallback;
|
||||
|
||||
namespace network {
|
||||
class Connection;
|
||||
} // namespace Connection;
|
||||
} // namespace network
|
||||
|
||||
#ifdef MOZ_B2G_BT
|
||||
namespace bluetooth {
|
||||
|
@ -36,7 +36,7 @@ struct StructuredCloneInfo
|
||||
nsTArray<nsRefPtr<MessagePortBase>> clonedPorts;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
const JSStructuredCloneCallbacks PostMessageEvent::sPostMessageCallbacks = {
|
||||
PostMessageEvent::ReadStructuredClone,
|
||||
@ -393,5 +393,5 @@ PostMessageEvent::Write(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
&scInfo);
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -104,7 +104,7 @@ private:
|
||||
nsTArray<MessagePortIdentifier> mPortIdentifiers;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_PostMessageEvent_h
|
||||
|
@ -540,5 +540,5 @@ URL::CreateSearchParamsIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -30,7 +30,7 @@ struct objectURLOptions;
|
||||
|
||||
namespace workers {
|
||||
class URLProxy;
|
||||
}
|
||||
} // namespace workers
|
||||
|
||||
class URL final : public URLSearchParamsObserver
|
||||
, public nsWrapperCache
|
||||
@ -168,7 +168,7 @@ private:
|
||||
|
||||
bool IsChromeURI(nsIURI* aURI);
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* URL_h___ */
|
||||
|
@ -272,7 +272,7 @@ void SerializeString(const nsCString& aInput, nsAString& aValue)
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
void
|
||||
URLParams::Serialize(nsAString& aValue) const
|
||||
|
@ -319,7 +319,7 @@ private:
|
||||
nsresult mRv;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
nsresult
|
||||
WebSocketImpl::PrintErrorOnConsole(const char *aBundleURI,
|
||||
@ -461,7 +461,7 @@ private:
|
||||
const nsCString mReasonString;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
nsresult
|
||||
WebSocketImpl::CloseConnection(uint16_t aReasonCode,
|
||||
@ -592,7 +592,7 @@ private:
|
||||
WebSocketImpl* mImpl;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
nsresult
|
||||
WebSocketImpl::Disconnect()
|
||||
@ -1149,7 +1149,7 @@ private:
|
||||
ErrorResult& mRv;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
already_AddRefed<WebSocket>
|
||||
WebSocket::Constructor(const GlobalObject& aGlobal,
|
||||
@ -2063,7 +2063,7 @@ private:
|
||||
WebSocketImpl* mWebSocketImpl;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
void
|
||||
WebSocketImpl::AddRefObject()
|
||||
@ -2484,7 +2484,7 @@ private:
|
||||
nsRefPtr<WebSocketImpl> mImpl;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
// Window closed, stop/reload button pressed, user navigated away from page, etc.
|
||||
NS_IMETHODIMP
|
||||
@ -2657,7 +2657,7 @@ private:
|
||||
nsCOMPtr<nsIRunnable> mEvent;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketImpl::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags)
|
||||
@ -2717,5 +2717,5 @@ WebSocket::AssertIsOnTargetThread() const
|
||||
MOZ_ASSERT(NS_IsMainThread() == mIsMainThread);
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -41,5 +41,6 @@ struct ChangesToFlush {
|
||||
bool mFlushAnimations;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozFlushType_h___ */
|
||||
|
@ -35,8 +35,8 @@ namespace css {
|
||||
class StyleRule;
|
||||
struct URLValue;
|
||||
struct ImageValue;
|
||||
}
|
||||
}
|
||||
} // namespace css
|
||||
} // namespace mozilla
|
||||
|
||||
#define NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM 12
|
||||
|
||||
|
@ -45,7 +45,7 @@ private:
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
void TraceBlackJS(JSTracer* aTrc, uint32_t aGCNumber, bool aIsShutdownGC);
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
@ -23,8 +23,8 @@ class nsIFile;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class DataTransfer;
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
//
|
||||
// class nsContentAreaDragDrop, used to generate the dragdata
|
||||
|
@ -33,8 +33,8 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Element;
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
class nsBaseContentList : public nsINodeList
|
||||
|
@ -30,7 +30,7 @@ class nsContentPermissionRequestProxy;
|
||||
// That will mess up windows build.
|
||||
namespace IPC {
|
||||
class Principal;
|
||||
}
|
||||
} // namespace IPC
|
||||
|
||||
class VisibilityChangeListener final : public nsIDOMEventListener
|
||||
{
|
||||
|
@ -42,8 +42,8 @@ class nsIApplicationCache;
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
class Loader;
|
||||
}
|
||||
}
|
||||
} // namespace css
|
||||
} // namespace mozilla
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "MediaDecoder.h"
|
||||
// nsNPAPIPluginInstance must be included before nsIDocument.h, which is included in mozAutoDocUpdate.h.
|
||||
#include "nsNPAPIPluginInstance.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "mozAutoDocUpdate.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
@ -442,7 +443,7 @@ private:
|
||||
nsCString mCharset;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
/* static */
|
||||
TimeDuration
|
||||
@ -2026,9 +2027,9 @@ namespace dom {
|
||||
namespace workers {
|
||||
extern bool IsCurrentThreadRunningChromeWorker();
|
||||
extern JSContext* GetCurrentThreadJSContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace workers
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
bool
|
||||
nsContentUtils::ThreadsafeIsCallerChrome()
|
||||
|
@ -15,8 +15,8 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class DOMRect;
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
* Implementation of a DOM Caret Position, which is a node and offset within
|
||||
|
@ -28,8 +28,8 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Blob;
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsDOMFileReader final : public mozilla::dom::FileIOObject,
|
||||
public nsIDOMFileReader,
|
||||
|
@ -24,9 +24,9 @@ static const nsDOMPerformanceNavigationType TYPE_NAVIGATE = 0;
|
||||
static const nsDOMPerformanceNavigationType TYPE_RELOAD = 1;
|
||||
static const nsDOMPerformanceNavigationType TYPE_BACK_FORWARD = 2;
|
||||
static const nsDOMPerformanceNavigationType TYPE_RESERVED = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace PerformanceNavigation
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsDOMNavigationTiming final
|
||||
{
|
||||
|
@ -24,8 +24,8 @@ struct nsPoint;
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
class LayerTransactionChild;
|
||||
}
|
||||
}
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
class nsTranslationNodeList final : public nsITranslationNodeList
|
||||
{
|
||||
|
@ -591,6 +591,7 @@ struct PositionComparator
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
bool
|
||||
@ -5933,7 +5934,7 @@ public:
|
||||
|
||||
NS_IMPL_ISUPPORTS(ProcessStackRunner, nsIRunnable);
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
void
|
||||
nsDocument::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
|
||||
@ -9635,7 +9636,7 @@ struct SuppressArgs
|
||||
uint32_t mIncrease;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
static bool
|
||||
SuppressEventHandlingInDocument(nsIDocument* aDocument, void* aData)
|
||||
@ -9912,7 +9913,7 @@ public:
|
||||
};
|
||||
NS_IMPL_ISUPPORTS(StubCSSLoaderObserver, nsICSSLoaderObserver)
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void
|
||||
nsDocument::PreloadStyle(nsIURI* uri, const nsAString& charset,
|
||||
@ -9969,7 +9970,7 @@ struct UnsuppressArgs
|
||||
nsTArray<nsCOMPtr<nsIDocument>> mDocs;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
static bool
|
||||
GetAndUnsuppressSubDocuments(nsIDocument* aDocument,
|
||||
|
@ -122,6 +122,7 @@ public:
|
||||
// need to send some notification itself with the real origin.
|
||||
bool mShouldNotifyNewOrigin = true;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIDOMChromeWindow.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMRange.h"
|
||||
@ -33,6 +34,7 @@
|
||||
#include "nsFrameSelection.h"
|
||||
#include "mozilla/dom/Selection.h"
|
||||
#include "nsXULPopupManager.h"
|
||||
#include "nsMenuPopupFrame.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIObserverService.h"
|
||||
@ -41,6 +43,7 @@
|
||||
#include "nsStyleCoord.h"
|
||||
#include "SelectionCarets.h"
|
||||
#include "TabChild.h"
|
||||
#include "nsFrameLoader.h"
|
||||
|
||||
#include "mozilla/ContentEvents.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
@ -521,6 +524,10 @@ nsFocusManager::MoveFocus(nsIDOMWindow* aWindow, nsIDOMElement* aStartElement,
|
||||
nsCOMPtr<nsIContent> newFocus;
|
||||
nsresult rv = DetermineElementToMoveFocus(window, startContent, aType, noParentTraversal,
|
||||
getter_AddRefs(newFocus));
|
||||
if (rv == NS_SUCCESS_DOM_NO_OPERATION) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
LOGCONTENTNAVIGATION("Element to be focused: %s", newFocus.get());
|
||||
@ -2361,7 +2368,8 @@ nsFocusManager::GetSelectionLocation(nsIDocument* aDocument,
|
||||
eLeaf,
|
||||
false, // aVisual
|
||||
false, // aLockInScrollView
|
||||
true // aFollowOOFs
|
||||
true, // aFollowOOFs
|
||||
false // aSkipPopupChecks
|
||||
);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -2421,9 +2429,19 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
|
||||
{
|
||||
*aNextContent = nullptr;
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
|
||||
if (!docShell)
|
||||
return NS_OK;
|
||||
// True if we are navigating by document (F6/Shift+F6) or false if we are
|
||||
// navigating by element (Tab/Shift+Tab).
|
||||
bool forDocumentNavigation = false;
|
||||
|
||||
// This is used for document navigation only. It will be set to true if we
|
||||
// start navigating from a starting point. If this starting point is near the
|
||||
// end of the document (for example, an element on a statusbar), and there
|
||||
// are no child documents or panels before the end of the document, then we
|
||||
// will need to ensure that we don't consider the root chrome window when we
|
||||
// loop around and instead find the next child document/panel, as focus is
|
||||
// already in that window. This flag will be cleared once we navigate into
|
||||
// another document.
|
||||
bool mayFocusRoot = (aStartContent != nullptr);
|
||||
|
||||
nsCOMPtr<nsIContent> startContent = aStartContent;
|
||||
if (!startContent && aType != MOVEFOCUS_CARET) {
|
||||
@ -2449,19 +2467,24 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
|
||||
LookAndFeel::GetInt(LookAndFeel::eIntID_TabFocusModel,
|
||||
&nsIContent::sTabFocusModel);
|
||||
|
||||
if (aType == MOVEFOCUS_ROOT) {
|
||||
// These types are for document navigation using F6.
|
||||
if (aType == MOVEFOCUS_FORWARDDOC || aType == MOVEFOCUS_BACKWARDDOC ||
|
||||
aType == MOVEFOCUS_FIRSTDOC || aType == MOVEFOCUS_LASTDOC) {
|
||||
forDocumentNavigation = true;
|
||||
}
|
||||
|
||||
// If moving to the root or first document, find the root element and return.
|
||||
if (aType == MOVEFOCUS_ROOT || aType == MOVEFOCUS_FIRSTDOC) {
|
||||
NS_IF_ADDREF(*aNextContent = GetRootForFocus(aWindow, doc, false, false));
|
||||
return NS_OK;
|
||||
if (!*aNextContent && aType == MOVEFOCUS_FIRSTDOC) {
|
||||
// When looking for the first document, if the root wasn't focusable,
|
||||
// find the next focusable document.
|
||||
aType = MOVEFOCUS_FORWARDDOC;
|
||||
} else {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
if (aType == MOVEFOCUS_FORWARDDOC) {
|
||||
NS_IF_ADDREF(*aNextContent = GetNextTabbableDocument(startContent, true));
|
||||
return NS_OK;
|
||||
}
|
||||
if (aType == MOVEFOCUS_BACKWARDDOC) {
|
||||
NS_IF_ADDREF(*aNextContent = GetNextTabbableDocument(startContent, false));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsIContent* rootContent = doc->GetRootElement();
|
||||
NS_ENSURE_TRUE(rootContent, NS_OK);
|
||||
|
||||
@ -2473,17 +2496,19 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
|
||||
startContent = rootContent;
|
||||
return GetNextTabbableContent(presShell, startContent,
|
||||
nullptr, startContent,
|
||||
true, 1, false, aNextContent);
|
||||
true, 1, false, false, aNextContent);
|
||||
}
|
||||
if (aType == MOVEFOCUS_LAST) {
|
||||
if (!aStartContent)
|
||||
startContent = rootContent;
|
||||
return GetNextTabbableContent(presShell, startContent,
|
||||
nullptr, startContent,
|
||||
false, 0, false, aNextContent);
|
||||
false, 0, false, false, aNextContent);
|
||||
}
|
||||
|
||||
bool forward = (aType == MOVEFOCUS_FORWARD || aType == MOVEFOCUS_CARET);
|
||||
bool forward = (aType == MOVEFOCUS_FORWARD ||
|
||||
aType == MOVEFOCUS_FORWARDDOC ||
|
||||
aType == MOVEFOCUS_CARET);
|
||||
bool doNavigation = true;
|
||||
bool ignoreTabIndex = false;
|
||||
// when a popup is open, we want to ensure that tab navigation occurs only
|
||||
@ -2518,7 +2543,7 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
|
||||
nsGkAtoms::menuPopupFrame);
|
||||
}
|
||||
|
||||
if (popupFrame) {
|
||||
if (popupFrame && !forDocumentNavigation) {
|
||||
// Don't navigate outside of a popup, so pretend that the
|
||||
// root content is the popup itself
|
||||
rootContent = popupFrame->GetContent();
|
||||
@ -2550,13 +2575,24 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
|
||||
}
|
||||
#endif
|
||||
if (popupFrame) {
|
||||
rootContent = popupFrame->GetContent();
|
||||
NS_ASSERTION(rootContent, "Popup frame doesn't have a content node");
|
||||
startContent = rootContent;
|
||||
// When there is a popup open, and no starting content, start the search
|
||||
// at the topmost popup.
|
||||
startContent = popupFrame->GetContent();
|
||||
NS_ASSERTION(startContent, "Popup frame doesn't have a content node");
|
||||
// Unless we are searching for documents, set the root content to the
|
||||
// popup as well, so that we don't tab-navigate outside the popup.
|
||||
// When navigating by documents, we start at the popup but can navigate
|
||||
// outside of it to look for other panels and documents.
|
||||
if (!forDocumentNavigation) {
|
||||
rootContent = startContent;
|
||||
}
|
||||
|
||||
doc = startContent ? startContent->GetComposedDoc() : nullptr;
|
||||
}
|
||||
else {
|
||||
// Otherwise, for content shells, start from the location of the caret.
|
||||
if (docShell->ItemType() != nsIDocShellTreeItem::typeChrome) {
|
||||
nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
|
||||
if (docShell && docShell->ItemType() != nsIDocShellTreeItem::typeChrome) {
|
||||
nsCOMPtr<nsIContent> endSelectionContent;
|
||||
GetSelectionLocation(doc, presShell,
|
||||
getter_AddRefs(startContent),
|
||||
@ -2593,6 +2629,29 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the starting content is the same as the content assigned to the
|
||||
// retargetdocumentfocus attribute. Is so, we don't want to start searching
|
||||
// from there but instead from the beginning of the document. Otherwise, the
|
||||
// content that appears before the retargetdocumentfocus element will never
|
||||
// get checked as it will be skipped when the focus is retargetted to it.
|
||||
if (forDocumentNavigation && doc->IsXULDocument()) {
|
||||
nsAutoString retarget;
|
||||
|
||||
if (rootContent->GetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::retargetdocumentfocus, retarget)) {
|
||||
nsIContent* retargetElement = doc->GetElementById(retarget);
|
||||
// The common case here is the urlbar where focus is on the anonymous
|
||||
// input inside the textbox, but the retargetdocumentfocus attribute
|
||||
// refers to the textbox. The Contains check will return false and the
|
||||
// ContentIsDescendantOf check will return true in this case.
|
||||
if (retargetElement && (retargetElement == startContent ||
|
||||
(!retargetElement->Contains(startContent) &&
|
||||
nsContentUtils::ContentIsDescendantOf(startContent, retargetElement)))) {
|
||||
startContent = rootContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(startContent, "starting content not set");
|
||||
|
||||
// keep a reference to the starting content. If we find that again, it means
|
||||
@ -2610,7 +2669,8 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
|
||||
nsIContent* originalStartContent = startContent;
|
||||
|
||||
LOGCONTENTNAVIGATION("Focus Navigation Start Content %s", startContent.get());
|
||||
LOGFOCUSNAVIGATION((" Tabindex: %d Ignore: %d", tabIndex, ignoreTabIndex));
|
||||
LOGFOCUSNAVIGATION((" Forward: %d Tabindex: %d Ignore: %d DocNav: %d",
|
||||
forward, tabIndex, ignoreTabIndex, forDocumentNavigation));
|
||||
|
||||
while (doc) {
|
||||
if (doNavigation) {
|
||||
@ -2619,22 +2679,29 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
|
||||
skipOriginalContentCheck ? nullptr : originalStartContent,
|
||||
startContent, forward,
|
||||
tabIndex, ignoreTabIndex,
|
||||
forDocumentNavigation,
|
||||
getter_AddRefs(nextFocus));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (rv == NS_SUCCESS_DOM_NO_OPERATION) {
|
||||
// Navigation was redirected to a child process, so just return.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// found a content node to focus.
|
||||
if (nextFocus) {
|
||||
LOGCONTENTNAVIGATION("Next Content: %s", nextFocus.get());
|
||||
|
||||
// as long as the found node was not the same as the starting node,
|
||||
// set it as the return value.
|
||||
if (nextFocus != originalStartContent) {
|
||||
// set it as the return value. For document navigation, we can return
|
||||
// the same element in case there is only one content node that could
|
||||
// be returned, for example, in a child process document.
|
||||
if (nextFocus != originalStartContent || forDocumentNavigation) {
|
||||
nextFocus.forget(aNextContent);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (popupFrame) {
|
||||
if (popupFrame && !forDocumentNavigation) {
|
||||
// in a popup, so start again from the beginning of the popup. However,
|
||||
// if we already started at the beginning, then there isn't anything to
|
||||
// focus, so just return
|
||||
@ -2648,7 +2715,7 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
|
||||
}
|
||||
|
||||
doNavigation = true;
|
||||
skipOriginalContentCheck = false;
|
||||
skipOriginalContentCheck = forDocumentNavigation;
|
||||
ignoreTabIndex = false;
|
||||
|
||||
if (aNoParentTraversal) {
|
||||
@ -2660,46 +2727,45 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
|
||||
continue;
|
||||
}
|
||||
|
||||
// reached the beginning or end of the document. Traverse up to the parent
|
||||
// document and try again.
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShellParent;
|
||||
docShell->GetParent(getter_AddRefs(docShellParent));
|
||||
if (docShellParent) {
|
||||
// move up to the parent shell and try again from there.
|
||||
// Reached the beginning or end of the document. Next, navigate up to the
|
||||
// parent document and try again.
|
||||
nsCOMPtr<nsPIDOMWindow> piWindow = doc->GetWindow();
|
||||
NS_ENSURE_TRUE(piWindow, NS_ERROR_FAILURE);
|
||||
|
||||
// first, get the frame element this window is inside.
|
||||
nsCOMPtr<nsPIDOMWindow> piWindow = docShell->GetWindow();
|
||||
NS_ENSURE_TRUE(piWindow, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIDocShell> docShell = piWindow->GetDocShell();
|
||||
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
|
||||
|
||||
// Next, retrieve the parent docshell, document and presshell.
|
||||
docShell = do_QueryInterface(docShellParent);
|
||||
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> piParentWindow = docShellParent->GetWindow();
|
||||
NS_ENSURE_TRUE(piParentWindow, NS_ERROR_FAILURE);
|
||||
doc = piParentWindow->GetExtantDoc();
|
||||
// Get the frame element this window is inside and, from that, get the
|
||||
// parent document and presshell. If there is no enclosing frame element,
|
||||
// then this is a top-level, embedded or remote window.
|
||||
startContent = piWindow->GetFrameElementInternal();
|
||||
if (startContent) {
|
||||
doc = startContent->GetComposedDoc();
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
||||
|
||||
rootContent = doc->GetRootElement();
|
||||
presShell = doc->GetShell();
|
||||
|
||||
rootContent = doc->GetRootElement();
|
||||
startContent = piWindow->GetFrameElementInternal();
|
||||
if (startContent) {
|
||||
nsIFrame* frame = startContent->GetPrimaryFrame();
|
||||
if (!frame)
|
||||
return NS_OK;
|
||||
// We can focus the root element now that we have moved to another document.
|
||||
mayFocusRoot = true;
|
||||
|
||||
frame->IsFocusable(&tabIndex, 0);
|
||||
if (tabIndex < 0) {
|
||||
tabIndex = 1;
|
||||
ignoreTabIndex = true;
|
||||
}
|
||||
nsIFrame* frame = startContent->GetPrimaryFrame();
|
||||
if (!frame) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// if the frame is inside a popup, make sure to scan only within the
|
||||
// popup. This handles the situation of tabbing amongst elements
|
||||
// inside an iframe which is itself inside a popup. Otherwise,
|
||||
// navigation would move outside the popup when tabbing outside the
|
||||
// iframe.
|
||||
frame->IsFocusable(&tabIndex, 0);
|
||||
if (tabIndex < 0) {
|
||||
tabIndex = 1;
|
||||
ignoreTabIndex = true;
|
||||
}
|
||||
|
||||
// if the frame is inside a popup, make sure to scan only within the
|
||||
// popup. This handles the situation of tabbing amongst elements
|
||||
// inside an iframe which is itself inside a popup. Otherwise,
|
||||
// navigation would move outside the popup when tabbing outside the
|
||||
// iframe.
|
||||
if (!forDocumentNavigation) {
|
||||
popupFrame = nsLayoutUtils::GetClosestFrameOfType(frame,
|
||||
nsGkAtoms::menuPopupFrame);
|
||||
if (popupFrame) {
|
||||
@ -2707,17 +2773,13 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
|
||||
NS_ASSERTION(rootContent, "Popup frame doesn't have a content node");
|
||||
}
|
||||
}
|
||||
else {
|
||||
startContent = rootContent;
|
||||
tabIndex = forward ? 1 : 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no parent, so call the tree owner. This will tell the embedder that
|
||||
// it should take the focus.
|
||||
// There is no parent, so call the tree owner. This will tell the
|
||||
// embedder or parent process that it should take the focus.
|
||||
bool tookFocus;
|
||||
docShell->TabToTreeOwner(forward, &tookFocus);
|
||||
// if the tree owner, took the focus, blur the current content
|
||||
docShell->TabToTreeOwner(forward, forDocumentNavigation, &tookFocus);
|
||||
// If the tree owner took the focus, blur the current content.
|
||||
if (tookFocus) {
|
||||
nsCOMPtr<nsPIDOMWindow> window = docShell->GetWindow();
|
||||
if (window->GetFocusedNode() == mFocusedContent)
|
||||
@ -2727,6 +2789,23 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we have reached the end of the top-level document, focus the
|
||||
// first element in the top-level document. This should always happen
|
||||
// when navigating by document forwards but when navigating backwards,
|
||||
// only do this if we started in another document or within a popup frame.
|
||||
// If the focus started in this window outside a popup however, we should
|
||||
// continue by looping around to the end again.
|
||||
if (forDocumentNavigation && (forward || mayFocusRoot || popupFrame)) {
|
||||
// HTML content documents can have their root element focused (a focus
|
||||
// ring appears around the entire content area frame). This root
|
||||
// appears in the tab order before all of the elements in the document.
|
||||
// Chrome documents however cannot be focused directly, so instead we
|
||||
// focus the first focusable element within the window.
|
||||
// For example, the urlbar.
|
||||
nsIContent* root = GetRootForFocus(piWindow, doc, true, true);
|
||||
return FocusFirst(root, aNextContent);
|
||||
}
|
||||
|
||||
// reset the tab index and start again from the beginning or end
|
||||
startContent = rootContent;
|
||||
tabIndex = forward ? 1 : 0;
|
||||
@ -2749,6 +2828,7 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
|
||||
bool aForward,
|
||||
int32_t aCurrentTabIndex,
|
||||
bool aIgnoreTabIndex,
|
||||
bool aForDocumentNavigation,
|
||||
nsIContent** aResultContent)
|
||||
{
|
||||
*aResultContent = nullptr;
|
||||
@ -2785,13 +2865,17 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
|
||||
continue;
|
||||
}
|
||||
|
||||
// For tab navigation, pass false for aSkipPopupChecks so that we don't
|
||||
// iterate into or out of a popup. For document naviation pass true to
|
||||
// ignore these boundaries.
|
||||
nsCOMPtr<nsIFrameEnumerator> frameTraversal;
|
||||
nsresult rv = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
|
||||
presContext, startFrame,
|
||||
ePreOrder,
|
||||
false, // aVisual
|
||||
false, // aLockInScrollView
|
||||
true // aFollowOOFs
|
||||
true, // aFollowOOFs
|
||||
aForDocumentNavigation // aSkipPopupChecks
|
||||
);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -2816,6 +2900,51 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
|
||||
// Walk frames to find something tabbable matching mCurrentTabIndex
|
||||
nsIFrame* frame = static_cast<nsIFrame*>(frameTraversal->CurrentItem());
|
||||
while (frame) {
|
||||
nsIContent* currentContent = frame->GetContent();
|
||||
|
||||
// For document navigation, check if this element is an open panel. Since
|
||||
// panels aren't focusable (tabIndex would be -1), we'll just assume that
|
||||
// for document navigation, the tabIndex is 0.
|
||||
if (aForDocumentNavigation && currentContent && (aCurrentTabIndex == 0) &&
|
||||
currentContent->IsXULElement(nsGkAtoms::panel)) {
|
||||
nsMenuPopupFrame* popupFrame = do_QueryFrame(frame);
|
||||
// Check if the panel is open. Closed panels are ignored since you can't
|
||||
// focus anything in them.
|
||||
if (popupFrame && popupFrame->IsOpen()) {
|
||||
// When moving backward, skip the popup we started in otherwise it
|
||||
// will be selected again.
|
||||
bool validPopup = true;
|
||||
if (!aForward) {
|
||||
nsIContent* content = aStartContent;
|
||||
while (content) {
|
||||
if (content == currentContent) {
|
||||
validPopup = false;
|
||||
break;
|
||||
}
|
||||
|
||||
content = content->GetParent();
|
||||
}
|
||||
}
|
||||
|
||||
if (validPopup) {
|
||||
// Since a panel isn't focusable itself, find the first focusable
|
||||
// content within the popup. If there isn't any focusable content
|
||||
// in the popup, skip this popup and continue iterating through the
|
||||
// frames. We pass the panel itself (currentContent) as the starting
|
||||
// and root content, so that we only find content within the panel.
|
||||
// Note also that we pass false for aForDocumentNavigation since we
|
||||
// want to locate the first content, not the first document.
|
||||
rv = GetNextTabbableContent(aPresShell, currentContent,
|
||||
nullptr, currentContent,
|
||||
true, 1, false, false,
|
||||
aResultContent);
|
||||
if (NS_SUCCEEDED(rv) && *aResultContent) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TabIndex not set defaults to 0 for form elements, anchors and other
|
||||
// elements that are normally focusable. Tabindex defaults to -1
|
||||
// for elements that are not normally focusable.
|
||||
@ -2823,17 +2952,16 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
|
||||
// < 0 not tabbable at all
|
||||
// == 0 in normal tab order (last after positive tabindexed items)
|
||||
// > 0 can be tabbed to in the order specified by this value
|
||||
|
||||
int32_t tabIndex;
|
||||
frame->IsFocusable(&tabIndex, 0);
|
||||
|
||||
LOGCONTENTNAVIGATION("Next Tabbable %s:", frame->GetContent());
|
||||
LOGFOCUSNAVIGATION((" with tabindex: %d expected: %d", tabIndex, aCurrentTabIndex));
|
||||
|
||||
nsIContent* currentContent = frame->GetContent();
|
||||
if (tabIndex >= 0) {
|
||||
NS_ASSERTION(currentContent, "IsFocusable set a tabindex for a frame with no content");
|
||||
if (currentContent->IsHTMLElement(nsGkAtoms::img) &&
|
||||
if (!aForDocumentNavigation &&
|
||||
currentContent->IsHTMLElement(nsGkAtoms::img) &&
|
||||
currentContent->HasAttr(kNameSpaceID_None, nsGkAtoms::usemap)) {
|
||||
// This is an image with a map. Image map areas are not traversed by
|
||||
// nsIFrameTraversal so look for the next or previous area element.
|
||||
@ -2852,29 +2980,50 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// found a node with a matching tab index. Check if it is a child
|
||||
// frame. If so, navigate into the child frame instead.
|
||||
nsIDocument* doc = currentContent->GetComposedDoc();
|
||||
NS_ASSERTION(doc, "content not in document");
|
||||
nsIDocument* subdoc = doc->GetSubDocumentFor(currentContent);
|
||||
if (subdoc) {
|
||||
if (!subdoc->EventHandlingSuppressed()) {
|
||||
bool checkSubDocument = true;
|
||||
if (aForDocumentNavigation) {
|
||||
// If this is a remote child browser, call NavigateDocument to have
|
||||
// the child process continue the navigation. Return a special error
|
||||
// code to have the caller return early. If the child ends up not
|
||||
// being focusable in some way, the child process will call back
|
||||
// into document navigation again by calling MoveFocus.
|
||||
TabParent* remote = TabParent::GetFrom(currentContent);
|
||||
if (remote) {
|
||||
remote->NavigateDocument(aForward);
|
||||
return NS_SUCCESS_DOM_NO_OPERATION;
|
||||
}
|
||||
|
||||
// Next, check if this a non-remote child document.
|
||||
nsIContent* docRoot = GetRootForChildDocument(currentContent);
|
||||
if (docRoot) {
|
||||
// If GetRootForChildDocument returned something then call
|
||||
// FocusFirst to find the root or first element to focus within
|
||||
// the child document. If this is a frameset though, skip this and
|
||||
// fall through to the checkSubDocument block below to iterate into
|
||||
// the frameset's frames and locate the first focusable frame.
|
||||
if (!docRoot->IsHTMLElement(nsGkAtoms::frameset)) {
|
||||
return FocusFirst(docRoot, aResultContent);
|
||||
}
|
||||
} else {
|
||||
// Set checkSubDocument to false, as this was neither a frame
|
||||
// type element or a child document that was focusable.
|
||||
checkSubDocument = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkSubDocument) {
|
||||
// found a node with a matching tab index. Check if it is a child
|
||||
// frame. If so, navigate into the child frame instead.
|
||||
nsIDocument* doc = currentContent->GetComposedDoc();
|
||||
NS_ASSERTION(doc, "content not in document");
|
||||
nsIDocument* subdoc = doc->GetSubDocumentFor(currentContent);
|
||||
if (subdoc && !subdoc->EventHandlingSuppressed()) {
|
||||
if (aForward) {
|
||||
// when tabbing forward into a frame, return the root
|
||||
// frame so that the canvas becomes focused.
|
||||
nsCOMPtr<nsPIDOMWindow> subframe = subdoc->GetWindow();
|
||||
if (subframe) {
|
||||
// If the subframe body is editable by contenteditable,
|
||||
// we should set the editor's root element rather than the
|
||||
// actual root element. Otherwise, we should set the focus
|
||||
// to the root content.
|
||||
*aResultContent =
|
||||
nsLayoutUtils::GetEditableRootContentByContentEditable(subdoc);
|
||||
if (!*aResultContent ||
|
||||
!((*aResultContent)->GetPrimaryFrame())) {
|
||||
*aResultContent =
|
||||
GetRootForFocus(subframe, subdoc, false, true);
|
||||
}
|
||||
*aResultContent = GetRootForFocus(subframe, subdoc, false, true);
|
||||
if (*aResultContent) {
|
||||
NS_ADDREF(*aResultContent);
|
||||
return NS_OK;
|
||||
@ -2887,29 +3036,29 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
|
||||
rv = GetNextTabbableContent(subShell, rootElement,
|
||||
aOriginalStartContent, rootElement,
|
||||
aForward, (aForward ? 1 : 0),
|
||||
false, aResultContent);
|
||||
false, aForDocumentNavigation, aResultContent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (*aResultContent)
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
// otherwise, use this as the next content node to tab to, unless
|
||||
// this was the element we started on. This would happen for
|
||||
// instance on an element with child frames, where frame navigation
|
||||
// could return the original element again. In that case, just skip
|
||||
// it. Also, if the next content node is the root content, then
|
||||
// return it. This latter case would happen only if someone made a
|
||||
// popup focusable.
|
||||
// Also, when going backwards, check to ensure that the focus
|
||||
// wouldn't be redirected. Otherwise, for example, when an input in
|
||||
// a textbox is focused, the enclosing textbox would be found and
|
||||
// the same inner input would be returned again.
|
||||
else if (currentContent == aRootContent ||
|
||||
(currentContent != startContent &&
|
||||
(aForward || !GetRedirectedFocus(currentContent)))) {
|
||||
NS_ADDREF(*aResultContent = currentContent);
|
||||
return NS_OK;
|
||||
// otherwise, use this as the next content node to tab to, unless
|
||||
// this was the element we started on. This would happen for
|
||||
// instance on an element with child frames, where frame navigation
|
||||
// could return the original element again. In that case, just skip
|
||||
// it. Also, if the next content node is the root content, then
|
||||
// return it. This latter case would happen only if someone made a
|
||||
// popup focusable.
|
||||
// Also, when going backwards, check to ensure that the focus
|
||||
// wouldn't be redirected. Otherwise, for example, when an input in
|
||||
// a textbox is focused, the enclosing textbox would be found and
|
||||
// the same inner input would be returned again.
|
||||
else if (currentContent == aRootContent ||
|
||||
(currentContent != startContent &&
|
||||
(aForward || !GetRedirectedFocus(currentContent)))) {
|
||||
NS_ADDREF(*aResultContent = currentContent);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2942,13 +3091,14 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
|
||||
// A bit counterintuitive but true, tabindex order goes 1, 2, ... 32767, 0
|
||||
if (aCurrentTabIndex == (aForward ? 0 : 1)) {
|
||||
// if going backwards, the canvas should be focused once the beginning
|
||||
// has been reached.
|
||||
// has been reached, so get the root element.
|
||||
if (!aForward) {
|
||||
nsCOMPtr<nsPIDOMWindow> window = GetCurrentWindow(aRootContent);
|
||||
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
||||
NS_IF_ADDREF(*aResultContent =
|
||||
GetRootForFocus(window, aRootContent->GetComposedDoc(),
|
||||
false, true));
|
||||
|
||||
nsCOMPtr<nsIContent> docRoot =
|
||||
GetRootForFocus(window, aRootContent->GetComposedDoc(), false, true);
|
||||
FocusFirst(docRoot, aResultContent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -3054,26 +3204,58 @@ nsFocusManager::GetNextTabIndex(nsIContent* aParent,
|
||||
return tabIndex;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFocusManager::FocusFirst(nsIContent* aRootContent, nsIContent** aNextContent)
|
||||
{
|
||||
if (!aRootContent) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDocument* doc = aRootContent->GetComposedDoc();
|
||||
if (doc) {
|
||||
if (doc->IsXULDocument()) {
|
||||
// If the redirectdocumentfocus attribute is set, redirect the focus to a
|
||||
// specific element. This is primarily used to retarget the focus to the
|
||||
// urlbar during document navigation.
|
||||
nsAutoString retarget;
|
||||
|
||||
if (aRootContent->GetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::retargetdocumentfocus, retarget)) {
|
||||
nsCOMPtr<nsIContent> retargetElement =
|
||||
CheckIfFocusable(doc->GetElementById(retarget), 0);
|
||||
if (retargetElement) {
|
||||
retargetElement.forget(aNextContent);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell = doc->GetDocShell();
|
||||
if (docShell->ItemType() == nsIDocShellTreeItem::typeChrome) {
|
||||
// If the found content is in a chrome shell, navigate forward one
|
||||
// tabbable item so that the first item is focused. Note that we
|
||||
// always go forward and not back here.
|
||||
nsIPresShell* presShell = doc->GetShell();
|
||||
if (presShell) {
|
||||
return GetNextTabbableContent(presShell, aRootContent,
|
||||
nullptr, aRootContent,
|
||||
true, 1, false, false,
|
||||
aNextContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_ADDREF(*aNextContent = aRootContent);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
nsFocusManager::GetRootForFocus(nsPIDOMWindow* aWindow,
|
||||
nsIDocument* aDocument,
|
||||
bool aIsForDocNavigation,
|
||||
bool aForDocumentNavigation,
|
||||
bool aCheckVisibility)
|
||||
{
|
||||
// the root element's canvas may be focused as long as the document is in a
|
||||
// a non-chrome shell and does not contain a frameset.
|
||||
if (aIsForDocNavigation) {
|
||||
nsCOMPtr<Element> docElement = aWindow->GetFrameElementInternal();
|
||||
// document navigation skips iframes and frames that are specifically non-focusable
|
||||
if (docElement) {
|
||||
if (docElement->NodeInfo()->NameAtom() == nsGkAtoms::iframe)
|
||||
return nullptr;
|
||||
|
||||
nsIFrame* frame = docElement->GetPrimaryFrame();
|
||||
if (!frame || !frame->IsFocusable(nullptr, 0))
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
if (!aForDocumentNavigation) {
|
||||
nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
|
||||
if (docShell->ItemType() == nsIDocShellTreeItem::typeChrome) {
|
||||
return nullptr;
|
||||
@ -3083,9 +3265,15 @@ nsFocusManager::GetRootForFocus(nsPIDOMWindow* aWindow,
|
||||
if (aCheckVisibility && !IsWindowVisible(aWindow))
|
||||
return nullptr;
|
||||
|
||||
Element *rootElement = aDocument->GetRootElement();
|
||||
if (!rootElement) {
|
||||
return nullptr;
|
||||
// If the body is contenteditable, use the editor's root element rather than
|
||||
// the actual root element.
|
||||
nsCOMPtr<nsIContent> rootElement =
|
||||
nsLayoutUtils::GetEditableRootContentByContentEditable(aDocument);
|
||||
if (!rootElement || !rootElement->GetPrimaryFrame()) {
|
||||
rootElement = aDocument->GetRootElement();
|
||||
if (!rootElement) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (aCheckVisibility && !rootElement->GetPrimaryFrame()) {
|
||||
@ -3094,291 +3282,43 @@ nsFocusManager::GetRootForFocus(nsPIDOMWindow* aWindow,
|
||||
|
||||
// Finally, check if this is a frameset
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(aDocument);
|
||||
if (htmlDoc && aDocument->GetHtmlChildElement(nsGkAtoms::frameset)) {
|
||||
return nullptr;
|
||||
if (htmlDoc) {
|
||||
nsIContent* htmlChild = aDocument->GetHtmlChildElement(nsGkAtoms::frameset);
|
||||
if (htmlChild) {
|
||||
// In document navigation mode, return the frameset so that navigation
|
||||
// descends into the child frames.
|
||||
return aForDocumentNavigation ? htmlChild : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return rootElement;
|
||||
}
|
||||
|
||||
void
|
||||
nsFocusManager::GetLastDocShell(nsIDocShellTreeItem* aItem,
|
||||
nsIDocShellTreeItem** aResult)
|
||||
{
|
||||
*aResult = nullptr;
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> curItem = aItem;
|
||||
while (curItem) {
|
||||
int32_t childCount = 0;
|
||||
curItem->GetChildCount(&childCount);
|
||||
if (!childCount) {
|
||||
curItem.forget(aResult);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
curItem->GetChildAt(childCount - 1, getter_AddRefs(curItem));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsFocusManager::GetNextDocShell(nsIDocShellTreeItem* aItem,
|
||||
nsIDocShellTreeItem** aResult)
|
||||
{
|
||||
*aResult = nullptr;
|
||||
|
||||
int32_t childCount = 0;
|
||||
aItem->GetChildCount(&childCount);
|
||||
if (childCount) {
|
||||
aItem->GetChildAt(0, aResult);
|
||||
if (*aResult)
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> curItem = aItem;
|
||||
while (curItem) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentItem;
|
||||
curItem->GetParent(getter_AddRefs(parentItem));
|
||||
if (!parentItem)
|
||||
return;
|
||||
|
||||
// Note that we avoid using GetChildOffset() here because docshell
|
||||
// child offsets can't be trusted to be correct. bug 162283.
|
||||
nsCOMPtr<nsIDocShellTreeItem> iterItem;
|
||||
childCount = 0;
|
||||
parentItem->GetChildCount(&childCount);
|
||||
for (int32_t index = 0; index < childCount; ++index) {
|
||||
parentItem->GetChildAt(index, getter_AddRefs(iterItem));
|
||||
if (iterItem == curItem) {
|
||||
++index;
|
||||
if (index < childCount) {
|
||||
parentItem->GetChildAt(index, aResult);
|
||||
if (*aResult)
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
curItem = parentItem;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsFocusManager::GetPreviousDocShell(nsIDocShellTreeItem* aItem,
|
||||
nsIDocShellTreeItem** aResult)
|
||||
{
|
||||
*aResult = nullptr;
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentItem;
|
||||
aItem->GetParent(getter_AddRefs(parentItem));
|
||||
if (!parentItem)
|
||||
return;
|
||||
|
||||
// Note that we avoid using GetChildOffset() here because docshell
|
||||
// child offsets can't be trusted to be correct. bug 162283.
|
||||
int32_t childCount = 0;
|
||||
parentItem->GetChildCount(&childCount);
|
||||
nsCOMPtr<nsIDocShellTreeItem> prevItem, iterItem;
|
||||
for (int32_t index = 0; index < childCount; ++index) {
|
||||
parentItem->GetChildAt(index, getter_AddRefs(iterItem));
|
||||
if (iterItem == aItem)
|
||||
break;
|
||||
prevItem = iterItem;
|
||||
}
|
||||
|
||||
if (prevItem)
|
||||
GetLastDocShell(prevItem, aResult);
|
||||
else
|
||||
parentItem.forget(aResult);
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
nsFocusManager::GetNextTabbablePanel(nsIDocument* aDocument, nsIFrame* aCurrentPopup, bool aForward)
|
||||
nsFocusManager::GetRootForChildDocument(nsIContent* aContent)
|
||||
{
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (!pm)
|
||||
// Check for elements that represent child documents, that is, browsers,
|
||||
// editors or frames from a frameset. We don't include iframes since we
|
||||
// consider them to be an integral part of the same window or page.
|
||||
if (!aContent ||
|
||||
!(aContent->IsXULElement(nsGkAtoms::browser) ||
|
||||
aContent->IsXULElement(nsGkAtoms::editor) ||
|
||||
aContent->IsHTMLElement(nsGkAtoms::frame))) {
|
||||
return nullptr;
|
||||
|
||||
// Iterate through the array backwards if aForward is false.
|
||||
nsTArray<nsIFrame *> popups;
|
||||
pm->GetVisiblePopups(popups);
|
||||
int32_t i = aForward ? 0 : popups.Length() - 1;
|
||||
int32_t end = aForward ? popups.Length() : -1;
|
||||
|
||||
for (; i != end; aForward ? i++ : i--) {
|
||||
nsIFrame* popupFrame = popups[i];
|
||||
if (aCurrentPopup) {
|
||||
// If the current popup is set, then we need to skip over this popup and
|
||||
// wait until the currently focused popup is found. Once found, the
|
||||
// current popup will be cleared so that the next popup is used.
|
||||
if (aCurrentPopup == popupFrame)
|
||||
aCurrentPopup = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip over non-panels
|
||||
if (!popupFrame->GetContent()->IsXULElement(nsGkAtoms::panel) ||
|
||||
(aDocument && popupFrame->GetContent()->GetComposedDoc() != aDocument)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find the first focusable content within the popup. If there isn't any
|
||||
// focusable content in the popup, skip to the next popup.
|
||||
nsIPresShell* presShell = popupFrame->PresContext()->GetPresShell();
|
||||
if (presShell) {
|
||||
nsCOMPtr<nsIContent> nextFocus;
|
||||
nsIContent* popup = popupFrame->GetContent();
|
||||
nsresult rv = GetNextTabbableContent(presShell, popup,
|
||||
nullptr, popup,
|
||||
true, 1, false,
|
||||
getter_AddRefs(nextFocus));
|
||||
if (NS_SUCCEEDED(rv) && nextFocus) {
|
||||
return nextFocus.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
nsFocusManager::GetNextTabbableDocument(nsIContent* aStartContent, bool aForward)
|
||||
{
|
||||
// If currentPopup is set, then the starting content is in a panel.
|
||||
nsIFrame* currentPopup = nullptr;
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
nsCOMPtr<nsIDocShell> startDocShell;
|
||||
|
||||
if (aStartContent) {
|
||||
doc = aStartContent->GetComposedDoc();
|
||||
if (doc) {
|
||||
startDocShell = doc->GetWindow()->GetDocShell();
|
||||
}
|
||||
|
||||
// Check if the starting content is inside a panel. Document navigation
|
||||
// must start from this panel instead of the document root.
|
||||
nsIContent* content = aStartContent;
|
||||
while (content) {
|
||||
if (content->NodeInfo()->Equals(nsGkAtoms::panel, kNameSpaceID_XUL)) {
|
||||
currentPopup = content->GetPrimaryFrame();
|
||||
break;
|
||||
}
|
||||
content = content->GetParent();
|
||||
}
|
||||
}
|
||||
else if (mFocusedWindow) {
|
||||
startDocShell = mFocusedWindow->GetDocShell();
|
||||
doc = mFocusedWindow->GetExtantDoc();
|
||||
} else if (mActiveWindow) {
|
||||
startDocShell = mActiveWindow->GetDocShell();
|
||||
doc = mActiveWindow->GetExtantDoc();
|
||||
}
|
||||
|
||||
if (!startDocShell)
|
||||
nsIDocument* doc = aContent->GetComposedDoc();
|
||||
if (!doc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// perform a depth first search (preorder) of the docshell tree
|
||||
// looking for an HTML Frame or a chrome document
|
||||
nsIContent* content = aStartContent;
|
||||
nsCOMPtr<nsIDocShellTreeItem> curItem = startDocShell.get();
|
||||
nsCOMPtr<nsIDocShellTreeItem> nextItem;
|
||||
do {
|
||||
// If moving forward, check for a panel in the starting document. If one
|
||||
// exists with focusable content, return that content instead of the next
|
||||
// document. If currentPopup is set, then, another panel may exist. If no
|
||||
// such panel exists, then continue on to check the next document.
|
||||
// When moving backwards, and the starting content is in a panel, then
|
||||
// check for additional panels in the starting document. If the starting
|
||||
// content is not in a panel, move back to the previous document and check
|
||||
// for panels there.
|
||||
nsIDocument* subdoc = doc->GetSubDocumentFor(aContent);
|
||||
if (!subdoc || subdoc->EventHandlingSuppressed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool checkPopups = false;
|
||||
nsCOMPtr<nsPIDOMWindow> nextFrame = nullptr;
|
||||
|
||||
if (doc && (aForward || currentPopup)) {
|
||||
nsIContent* popupContent = GetNextTabbablePanel(doc, currentPopup, aForward);
|
||||
if (popupContent)
|
||||
return popupContent;
|
||||
|
||||
if (!aForward && currentPopup) {
|
||||
// The starting content was in a popup, yet no other popups were
|
||||
// found. Move onto the starting content's document.
|
||||
nextFrame = doc->GetWindow();
|
||||
}
|
||||
}
|
||||
|
||||
// Look for the next or previous document.
|
||||
if (!nextFrame) {
|
||||
if (aForward) {
|
||||
GetNextDocShell(curItem, getter_AddRefs(nextItem));
|
||||
if (!nextItem) {
|
||||
// wrap around to the beginning, which is the top of the tree
|
||||
startDocShell->GetRootTreeItem(getter_AddRefs(nextItem));
|
||||
}
|
||||
}
|
||||
else {
|
||||
GetPreviousDocShell(curItem, getter_AddRefs(nextItem));
|
||||
if (!nextItem) {
|
||||
// wrap around to the end, which is the last item in the tree
|
||||
nsCOMPtr<nsIDocShellTreeItem> rootItem;
|
||||
startDocShell->GetRootTreeItem(getter_AddRefs(rootItem));
|
||||
GetLastDocShell(rootItem, getter_AddRefs(nextItem));
|
||||
}
|
||||
|
||||
// When going back to the previous document, check for any focusable
|
||||
// popups in that previous document first.
|
||||
checkPopups = true;
|
||||
}
|
||||
|
||||
curItem = nextItem;
|
||||
nextFrame = nextItem ? nextItem->GetWindow() : nullptr;
|
||||
}
|
||||
|
||||
if (!nextFrame)
|
||||
return nullptr;
|
||||
|
||||
// Clear currentPopup for the next iteration
|
||||
currentPopup = nullptr;
|
||||
|
||||
// If event handling is suppressed, move on to the next document. Set
|
||||
// content to null so that the popup check will be skipped on the next
|
||||
// loop iteration.
|
||||
doc = nextFrame->GetExtantDoc();
|
||||
if (!doc || doc->EventHandlingSuppressed()) {
|
||||
content = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (checkPopups) {
|
||||
// When iterating backwards, check the panels of the previous document
|
||||
// first. If a panel exists that has focusable content, focus that.
|
||||
// Otherwise, continue on to focus the document.
|
||||
nsIContent* popupContent = GetNextTabbablePanel(doc, nullptr, false);
|
||||
if (popupContent)
|
||||
return popupContent;
|
||||
}
|
||||
|
||||
content = GetRootForFocus(nextFrame, doc, true, true);
|
||||
if (content && !GetRootForFocus(nextFrame, doc, false, false)) {
|
||||
// if the found content is in a chrome shell or a frameset, navigate
|
||||
// forward one tabbable item so that the first item is focused. Note
|
||||
// that we always go forward and not back here.
|
||||
nsCOMPtr<nsIContent> nextFocus;
|
||||
Element* rootElement = doc->GetRootElement();
|
||||
nsIPresShell* presShell = doc->GetShell();
|
||||
if (presShell) {
|
||||
nsresult rv = GetNextTabbableContent(presShell, rootElement,
|
||||
nullptr, rootElement,
|
||||
true, 1, false,
|
||||
getter_AddRefs(nextFocus));
|
||||
return NS_SUCCEEDED(rv) ? nextFocus.get() : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} while (!content);
|
||||
|
||||
return content;
|
||||
nsCOMPtr<nsPIDOMWindow> window = subdoc->GetWindow();
|
||||
return GetRootForFocus(window, subdoc, true, true);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -25,6 +25,12 @@ class nsIDocShellTreeItem;
|
||||
class nsPIDOMWindow;
|
||||
class nsIMessageBroadcaster;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class TabParent;
|
||||
}
|
||||
}
|
||||
|
||||
struct nsDelayedBlurOrFocusEvent;
|
||||
|
||||
/**
|
||||
@ -387,6 +393,7 @@ protected:
|
||||
bool aForward,
|
||||
int32_t aCurrentTabIndex,
|
||||
bool aIgnoreTabIndex,
|
||||
bool aForDocumentNavigation,
|
||||
nsIContent** aResultContent);
|
||||
|
||||
/**
|
||||
@ -415,65 +422,32 @@ protected:
|
||||
int32_t aCurrentTabIndex,
|
||||
bool aForward);
|
||||
|
||||
/**
|
||||
* Focus the first focusable content within the document with a root node of
|
||||
* aRootContent. For content documents, this will be aRootContent itself, but
|
||||
* for chrome documents, this will locate the next focusable content.
|
||||
*/
|
||||
nsresult FocusFirst(nsIContent* aRootContent, nsIContent** aNextContent);
|
||||
|
||||
/**
|
||||
* Retrieves and returns the root node from aDocument to be focused. Will
|
||||
* return null if the root node cannot be focused. There are several reasons
|
||||
* for this:
|
||||
*
|
||||
* - if aIsForDocNavigation is true, and aWindow is in an <iframe>.
|
||||
* - if aIsForDocNavigation is false, and aWindow is a chrome shell.
|
||||
* - if aForDocumentNavigation is false and aWindow is a chrome shell.
|
||||
* - if aCheckVisibility is true and the aWindow is not visible.
|
||||
* - if aDocument is a frameset document.
|
||||
*/
|
||||
nsIContent* GetRootForFocus(nsPIDOMWindow* aWindow,
|
||||
nsIDocument* aDocument,
|
||||
bool aIsForDocNavigation,
|
||||
bool aForDocumentNavigation,
|
||||
bool aCheckVisibility);
|
||||
|
||||
/**
|
||||
* Get the last docshell child of aItem and return it in aResult.
|
||||
* Retrieves and returns the root node as with GetRootForFocus but only if
|
||||
* aContent is a frame with a valid child document.
|
||||
*/
|
||||
void GetLastDocShell(nsIDocShellTreeItem* aItem,
|
||||
nsIDocShellTreeItem** aResult);
|
||||
|
||||
/**
|
||||
* Get the next docshell child of aItem and return it in aResult.
|
||||
*/
|
||||
void GetNextDocShell(nsIDocShellTreeItem* aItem,
|
||||
nsIDocShellTreeItem** aResult);
|
||||
|
||||
/**
|
||||
* Get the previous docshell child of aItem and return it in aResult.
|
||||
*/
|
||||
void GetPreviousDocShell(nsIDocShellTreeItem* aItem,
|
||||
nsIDocShellTreeItem** aResult);
|
||||
|
||||
/**
|
||||
* Determine the first panel with focusable content in document tab order
|
||||
* from the given document. aForward indicates the direction to scan. If
|
||||
* aCurrentPopup is set to a panel, the next or previous popup after
|
||||
* aCurrentPopup after it is used. If aCurrentPopup is null, then the first
|
||||
* or last popup is used. If a panel has no focusable content, it is skipped.
|
||||
* Null is returned if no panel is open or no open panel contains a focusable
|
||||
* element.
|
||||
*/
|
||||
nsIContent* GetNextTabbablePanel(nsIDocument* aDocument, nsIFrame* aCurrentPopup, bool aForward);
|
||||
|
||||
/**
|
||||
* Get the tabbable next document from aStartContent or, if null, the
|
||||
* currently focused frame if aForward is true, or the previously tabbable
|
||||
* document if aForward is false. If this document is a chrome or frameset
|
||||
* document, returns the first focusable element within this document,
|
||||
* otherwise, returns the root node of the document.
|
||||
*
|
||||
*
|
||||
* Panels with focusable content are also placed in the cycling order, just
|
||||
* after the document containing that panel.
|
||||
*
|
||||
* This method would be used for document navigation, which is typically
|
||||
* invoked by pressing F6.
|
||||
*/
|
||||
nsIContent* GetNextTabbableDocument(nsIContent* aStartContent, bool aForward);
|
||||
nsIContent* GetRootForChildDocument(nsIContent* aContent);
|
||||
|
||||
/**
|
||||
* Retreives a focusable element within the current selection of aWindow.
|
||||
|
@ -50,7 +50,7 @@ CreateNewFileInstance(Blob& aBlob, const Optional<nsAString>& aFilename)
|
||||
return aBlob.ToFile(filename);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// nsISupports
|
||||
|
@ -41,12 +41,12 @@ class ContentParent;
|
||||
class PBrowserParent;
|
||||
class TabParent;
|
||||
struct StructuredCloneData;
|
||||
}
|
||||
} // namespace dom
|
||||
|
||||
namespace layout {
|
||||
class RenderFrameParent;
|
||||
}
|
||||
}
|
||||
} // namespace layout
|
||||
} // namespace mozilla
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK)
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
|
@ -1444,7 +1444,7 @@ struct MessageManagerReferentCount
|
||||
nsDataHashtable<nsStringHashKey, uint32_t> mMessageCounter;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -1013,6 +1013,7 @@ GK_ATOM(resource, "resource")
|
||||
GK_ATOM(resources, "resources")
|
||||
GK_ATOM(result, "result")
|
||||
GK_ATOM(resultPrefix, "result-prefix")
|
||||
GK_ATOM(retargetdocumentfocus, "retargetdocumentfocus")
|
||||
GK_ATOM(rev, "rev")
|
||||
GK_ATOM(reverse, "reverse")
|
||||
GK_ATOM(reversed, "reversed")
|
||||
|
@ -566,8 +566,8 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
extern uint64_t
|
||||
NextWindowID();
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow)
|
||||
: mFrameElement(nullptr), mDocShell(nullptr), mModalStateDepth(0),
|
||||
@ -6030,6 +6030,211 @@ FinishDOMFullscreenChange(nsIDocument* aDoc, bool aInDOMFullscreen)
|
||||
}
|
||||
}
|
||||
|
||||
struct FullscreenTransitionDuration
|
||||
{
|
||||
// The unit of the durations is millisecond
|
||||
uint16_t mFadeIn = 0;
|
||||
uint16_t mFadeOut = 0;
|
||||
bool IsSuppressed() const
|
||||
{
|
||||
return mFadeIn == 0 && mFadeOut == 0;
|
||||
}
|
||||
};
|
||||
|
||||
static void
|
||||
GetFullscreenTransitionDuration(bool aEnterFullscreen,
|
||||
FullscreenTransitionDuration* aDuration)
|
||||
{
|
||||
const char* pref = aEnterFullscreen ?
|
||||
"full-screen-api.transition-duration.enter" :
|
||||
"full-screen-api.transition-duration.leave";
|
||||
nsAdoptingCString prefValue = Preferences::GetCString(pref);
|
||||
if (!prefValue.IsEmpty()) {
|
||||
sscanf(prefValue.get(), "%hu%hu",
|
||||
&aDuration->mFadeIn, &aDuration->mFadeOut);
|
||||
}
|
||||
}
|
||||
|
||||
class FullscreenTransitionTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
FullscreenTransitionTask(const FullscreenTransitionDuration& aDuration,
|
||||
nsGlobalWindow* aWindow, bool aFullscreen,
|
||||
nsIWidget* aWidget, nsIScreen* aScreen,
|
||||
nsISupports* aTransitionData)
|
||||
: mWindow(aWindow)
|
||||
, mWidget(aWidget)
|
||||
, mScreen(aScreen)
|
||||
, mTransitionData(aTransitionData)
|
||||
, mDuration(aDuration)
|
||||
, mStage(eBeforeToggle)
|
||||
, mFullscreen(aFullscreen)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run() override;
|
||||
|
||||
private:
|
||||
enum Stage {
|
||||
// BeforeToggle stage happens before we enter or leave fullscreen
|
||||
// state. In this stage, the task triggers the pre-toggle fullscreen
|
||||
// transition on the widget.
|
||||
eBeforeToggle,
|
||||
// ToggleFullscreen stage actually executes the fullscreen toggle,
|
||||
// and wait for the next paint on the content to continue.
|
||||
eToggleFullscreen,
|
||||
// AfterToggle stage happens after we toggle the fullscreen state.
|
||||
// In this stage, the task triggers the post-toggle fullscreen
|
||||
// transition on the widget.
|
||||
eAfterToggle
|
||||
};
|
||||
|
||||
class Observer final : public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
explicit Observer(FullscreenTransitionTask* aTask)
|
||||
: mTask(aTask) { }
|
||||
|
||||
private:
|
||||
~Observer() {}
|
||||
|
||||
nsRefPtr<FullscreenTransitionTask> mTask;
|
||||
};
|
||||
|
||||
static const uint32_t kNextPaintTimeout = 1000; // ms
|
||||
static const char* const kPaintedTopic;
|
||||
|
||||
nsRefPtr<nsGlobalWindow> mWindow;
|
||||
nsCOMPtr<nsIWidget> mWidget;
|
||||
nsCOMPtr<nsIScreen> mScreen;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
nsCOMPtr<nsISupports> mTransitionData;
|
||||
|
||||
FullscreenTransitionDuration mDuration;
|
||||
Stage mStage;
|
||||
bool mFullscreen;
|
||||
};
|
||||
|
||||
const char* const
|
||||
FullscreenTransitionTask::kPaintedTopic = "fullscreen-painted";
|
||||
|
||||
NS_IMETHODIMP
|
||||
FullscreenTransitionTask::Run()
|
||||
{
|
||||
Stage stage = mStage;
|
||||
mStage = Stage(mStage + 1);
|
||||
if (stage == eBeforeToggle) {
|
||||
mWidget->PerformFullscreenTransition(nsIWidget::eBeforeFullscreenToggle,
|
||||
mDuration.mFadeIn, mTransitionData,
|
||||
this);
|
||||
} else if (stage == eToggleFullscreen) {
|
||||
if (MOZ_UNLIKELY(mWindow->mFullScreen != mFullscreen)) {
|
||||
// This could happen in theory if several fullscreen requests in
|
||||
// different direction happen continuously in a short time. We
|
||||
// need to ensure the fullscreen state matches our target here,
|
||||
// otherwise the widget would change the window state as if we
|
||||
// toggle for Fullscreen Mode instead of Fullscreen API.
|
||||
NS_WARNING("The fullscreen state of the window does not match");
|
||||
mWindow->mFullScreen = mFullscreen;
|
||||
}
|
||||
// Toggle the fullscreen state on the widget
|
||||
mWidget->MakeFullScreen(mFullscreen, mScreen);
|
||||
// Set observer for the next content paint.
|
||||
nsCOMPtr<nsIObserver> observer = new Observer(this);
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->AddObserver(observer, kPaintedTopic, false);
|
||||
// There are several edge cases where we may never get the paint
|
||||
// notification, including:
|
||||
// 1. the window/tab is closed before the next paint;
|
||||
// 2. the user has switched to another tab before we get here.
|
||||
// Completely fixing those cases seems to be tricky, and since they
|
||||
// should rarely happen, it probably isn't worth to fix. Hence we
|
||||
// simply add a timeout here to ensure we never hang forever.
|
||||
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
mTimer->Init(observer, kNextPaintTimeout, nsITimer::TYPE_ONE_SHOT);
|
||||
} else if (stage == eAfterToggle) {
|
||||
mWidget->PerformFullscreenTransition(nsIWidget::eAfterFullscreenToggle,
|
||||
mDuration.mFadeOut, mTransitionData,
|
||||
this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(FullscreenTransitionTask::Observer, nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
FullscreenTransitionTask::Observer::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const char16_t* aData)
|
||||
{
|
||||
bool shouldContinue = false;
|
||||
if (strcmp(aTopic, FullscreenTransitionTask::kPaintedTopic) == 0) {
|
||||
nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(aSubject));
|
||||
nsCOMPtr<nsIWidget> widget = win ?
|
||||
static_cast<nsGlobalWindow*>(win.get())->GetMainWidget() : nullptr;
|
||||
if (widget == mTask->mWidget) {
|
||||
// The paint notification arrives first. Cancel the timer.
|
||||
mTask->mTimer->Cancel();
|
||||
shouldContinue = true;
|
||||
}
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(strcmp(aTopic, NS_TIMER_CALLBACK_TOPIC) == 0,
|
||||
"Should only get fullscreen-painted or timer-callback");
|
||||
nsCOMPtr<nsITimer> timer(do_QueryInterface(aSubject));
|
||||
MOZ_ASSERT(timer && timer == mTask->mTimer,
|
||||
"Should only trigger this with the timer the task created");
|
||||
#endif
|
||||
shouldContinue = true;
|
||||
}
|
||||
if (shouldContinue) {
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->RemoveObserver(this, kPaintedTopic);
|
||||
mTask->mTimer = nullptr;
|
||||
mTask->Run();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool
|
||||
MakeWidgetFullscreen(nsGlobalWindow* aWindow, gfx::VRHMDInfo* aHMD,
|
||||
nsPIDOMWindow::FullscreenReason aReason, bool aFullscreen)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = aWindow->GetMainWidget();
|
||||
if (!widget) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FullscreenTransitionDuration duration;
|
||||
bool performTransition = false;
|
||||
nsCOMPtr<nsISupports> transitionData;
|
||||
if (aReason == nsPIDOMWindow::eForFullscreenAPI) {
|
||||
GetFullscreenTransitionDuration(aFullscreen, &duration);
|
||||
if (!duration.IsSuppressed()) {
|
||||
performTransition = widget->
|
||||
PrepareForFullscreenTransition(getter_AddRefs(transitionData));
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIScreen> screen = aHMD ? aHMD->GetScreen() : nullptr;
|
||||
if (!performTransition) {
|
||||
if (aReason == nsPIDOMWindow::eForFullscreenMode) {
|
||||
// If we enter fullscreen for fullscreen mode, we want
|
||||
// the native system behavior.
|
||||
widget->MakeFullScreenWithNativeTransition(aFullscreen, screen);
|
||||
} else {
|
||||
widget->MakeFullScreen(aFullscreen, screen);
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsIRunnable> task =
|
||||
new FullscreenTransitionTask(duration, aWindow, aFullscreen,
|
||||
widget, screen, transitionData);
|
||||
task->Run();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindow::SetFullscreenInternal(FullscreenReason aReason,
|
||||
bool aFullScreen,
|
||||
@ -6041,8 +6246,7 @@ nsGlobalWindow::SetFullscreenInternal(FullscreenReason aReason,
|
||||
|
||||
// Only chrome can change our fullscreen mode. Otherwise, the state
|
||||
// can only be changed for DOM fullscreen.
|
||||
if (aFullScreen == FullScreen() ||
|
||||
(aReason == eForFullscreenMode && !nsContentUtils::IsCallerChrome())) {
|
||||
if (aReason == eForFullscreenMode && !nsContentUtils::IsCallerChrome()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -6098,16 +6302,7 @@ nsGlobalWindow::SetFullscreenInternal(FullscreenReason aReason,
|
||||
// dimensions to appear to increase when entering fullscreen mode; we just
|
||||
// want the content to fill the entire client area of the emulator window.
|
||||
if (!Preferences::GetBool("full-screen-api.ignore-widgets", false)) {
|
||||
nsCOMPtr<nsIWidget> widget = GetMainWidget();
|
||||
if (widget) {
|
||||
nsCOMPtr<nsIScreen> screen;
|
||||
if (aHMD) {
|
||||
screen = aHMD->GetScreen();
|
||||
}
|
||||
if (aReason == eForFullscreenAPI) {
|
||||
widget->PrepareForDOMFullscreenTransition();
|
||||
}
|
||||
widget->MakeFullScreen(aFullScreen, screen);
|
||||
if (MakeWidgetFullscreen(this, aHMD, aReason, aFullScreen)) {
|
||||
// The rest of code for switching fullscreen is in nsGlobalWindow::
|
||||
// FinishFullscreenChange() which will be called after sizemodechange
|
||||
// event is dispatched.
|
||||
|
@ -484,6 +484,9 @@ public:
|
||||
// Inner windows only.
|
||||
virtual void RefreshCompartmentPrincipal() override;
|
||||
|
||||
// For accessing protected field mFullScreen
|
||||
friend class FullscreenTransitionTask;
|
||||
|
||||
// Outer windows only.
|
||||
virtual nsresult SetFullscreenInternal(
|
||||
FullscreenReason aReason, bool aIsFullscreen,
|
||||
|
@ -309,7 +309,7 @@ class BlobURLsReporter final : public nsIMemoryReporter
|
||||
|
||||
NS_IMPL_ISUPPORTS(BlobURLsReporter, nsIMemoryReporter)
|
||||
|
||||
}
|
||||
} // namespace mozilla
|
||||
|
||||
void
|
||||
nsHostObjectProtocolHandler::Init(void)
|
||||
|
@ -26,8 +26,8 @@ class DOMMediaStream;
|
||||
namespace dom {
|
||||
class BlobImpl;
|
||||
class MediaSource;
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsHostObjectProtocolHandler : public nsIProtocolHandler
|
||||
{
|
||||
|
@ -11,8 +11,8 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Animation;
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#define NS_IANIMATION_OBSERVER_IID \
|
||||
{ 0xed025fc7, 0xdeda, 0x48b9, \
|
||||
|
@ -64,7 +64,7 @@ private:
|
||||
nsTArray<nsCString> mURIs;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
void
|
||||
nsIGlobalObject::UnlinkHostObjectURIs()
|
||||
|
@ -2501,7 +2501,7 @@ struct SelectorMatchInfo {
|
||||
nsCSSSelectorList* const mSelectorList;
|
||||
TreeMatchContext& mMatchContext;
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Given an id, find elements with that id under aRoot that match aMatchInfo if
|
||||
// any is provided. If no SelectorMatchInfo is provided, just find the ones
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsSVGEffects.h"
|
||||
|
||||
#include "gfxPrefs.h"
|
||||
|
||||
#include "mozAutoDocUpdate.h"
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/EventStates.h"
|
||||
@ -1359,7 +1361,7 @@ private:
|
||||
nsCOMPtr<imgIRequest> mRequest;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace
|
||||
|
||||
void
|
||||
nsImageLoadingContent::MakePendingRequestCurrent()
|
||||
|
@ -26,12 +26,12 @@ namespace JS {
|
||||
template <typename T>
|
||||
class AutoVectorRooter;
|
||||
typedef AutoVectorRooter<Value> AutoValueVector;
|
||||
}
|
||||
} // namespace JS
|
||||
|
||||
namespace mozilla {
|
||||
template <class> class Maybe;
|
||||
struct CycleCollectorResults;
|
||||
}
|
||||
} // namespace mozilla
|
||||
|
||||
// The amount of time we wait between a request to GC (due to leaving
|
||||
// a page) and doing the actual GC.
|
||||
|
@ -28,8 +28,8 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
class AutoJSAPI;
|
||||
class Element;
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsJSUtils
|
||||
{
|
||||
|
@ -30,8 +30,8 @@ template<class T> struct already_AddRefed;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class NodeInfo;
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsNodeInfoManager final
|
||||
{
|
||||
|
@ -18,8 +18,8 @@ class nsCycleCollectionTraversalCallback;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Animation;
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsNodeUtils
|
||||
{
|
||||
|
@ -35,8 +35,8 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
template<typename T> class Sequence;
|
||||
struct MozPluginParameter;
|
||||
}
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
, public nsIStreamListener
|
||||
|
@ -36,11 +36,11 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
class AudioContext;
|
||||
class Element;
|
||||
}
|
||||
} // namespace dom
|
||||
namespace gfx {
|
||||
class VRHMDInfo;
|
||||
}
|
||||
}
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
||||
// Popup control state enum. The values in this enum must go from most
|
||||
// permissive to least permissive so that it's safe to push state in
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user