Merge inbound to m-c a=merge

This commit is contained in:
Wes Kocher 2015-07-13 15:55:25 -07:00
commit 00bfc9f9d8
1828 changed files with 5689 additions and 4161 deletions

View File

@ -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);
}
}

View File

@ -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.
*/

View File

@ -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);

View File

@ -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.

View File

@ -52,6 +52,7 @@ Accessible::AsOuterDoc()
{
return IsOuterDoc() ? static_cast<OuterDocAccessible*>(this) : nullptr;
}
} // namespace a11y
} // namespace mozilla

View File

@ -223,6 +223,7 @@ WrapperFor(ProxyAccessible* aProxy)
{
return reinterpret_cast<AccessibleWrap*>(aProxy->GetWrapper());
}
} // namespace a11y
} // namespace mozilla

View File

@ -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;
}
}
},

View File

@ -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"/>

View File

@ -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();

View File

@ -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

View File

@ -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;
}
}
}
};

View File

@ -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.

View 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

View File

@ -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;

View File

@ -0,0 +1,12 @@
<html id="outer">
<frameset rows="30%, 70%">
<frame src="data:text/html,&lt;html id='htmlframe1' &gt;&lt;body id='framebody1'&gt;&lt;input id='i1'&gt;&lt;body&gt;&lt;/html&gt;">
<frameset cols="30%, 33%, 34%">
<frame src="data:text/html,&lt;html id='htmlframe2'&gt;&lt;body id='framebody2'&gt;&lt;input id='i2'&gt;&lt;body&gt;&lt;/html&gt;">
<frame src="data:text/html,&lt;html id='htmlframe3'&gt;&lt;body id='framebody3'&gt;&lt;input id='i3'&gt;&lt;body&gt;&lt;/html&gt;">
<frame src="data:text/html,&lt;html id='htmlframe4'&gt;&lt;body id='framebody4'&gt;&lt;input id='i4'&gt;&lt;body&gt;&lt;/html&gt;">
</frameset>
</frameset>
</html>

View File

@ -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();
},

View File

@ -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

View File

@ -37,7 +37,7 @@ namespace {
return PR_ImplodeTime(&prt);
}
} // Anonymous namespace.
} // namespace
////////////////////////////////////////////////////////////////////////////////
//// nsIEHistoryEnumerator

View File

@ -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]

View File

@ -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;
}
};
/**

View 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();
}

View File

@ -10,6 +10,7 @@ SOURCES += [
'TestExplicitOperatorBool.cpp',
'TestGlobalClass.cpp',
'TestMustOverride.cpp',
'TestMustUse.cpp',
'TestNANTestingExpr.cpp',
'TestNANTestingExprC.c',
'TestNoAddRefReleaseOnReturn.cpp',

View File

@ -108,7 +108,7 @@ private:
OriginAttributes* mOriginAttributes;
};
} // anonymous namespace
} // namespace
bool
OriginAttributes::PopulateFromSuffix(const nsACString& aStr)

View File

@ -15,7 +15,7 @@ namespace mozilla {
namespace ipc {
class URIParams;
};
} // namespace ipc
enum DomainSetChangeType{
ACTIVATE_POLICY,

View File

@ -24,7 +24,7 @@ class nsSystemPrincipal;
namespace mozilla {
class OriginAttributes;
}
} // namespace mozilla
/////////////////////////////
// nsScriptSecurityManager //

View File

@ -197,6 +197,6 @@ struct ParamTraits<OverrideMapping>
}
};
}
} // namespace IPC
#endif // RegistryMessageUtils_h

View File

@ -15,8 +15,8 @@
namespace mozilla {
namespace dom {
class PContentParent;
}
}
} // namespace dom
} // namespace mozilla
class nsIPrefBranch;
struct ChromePackage;

View File

@ -15,7 +15,7 @@ namespace mozilla {
namespace dom {
class Link;
}
} // namespace dom
// 0057c9d3-b98e-4933-bdc5-0275d06705e1
#define IHISTORY_IID \

View File

@ -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,

View File

@ -60,8 +60,8 @@
namespace mozilla {
namespace dom {
class EventTarget;
}
}
} // namespace dom
} // namespace mozilla
class nsDocShell;
class nsDOMNavigationTiming;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -116,6 +116,6 @@ AlarmHalService::Notify(const int64_t& aClockDeltaMS)
mSystemClockChangedCb->OnSystemClockChanged(aClockDeltaMS);
}
} // alarm
} // dom
} // mozilla
} // namespace alarm
} // namespace dom
} // namespace mozilla

View File

@ -28,7 +28,7 @@ namespace {
AnimationTimeline* mTimeline;
#endif
};
}
} // namespace
static PLDHashOperator
AppendAnimationToSequence(nsRefPtrHashKey<dom::Animation>* aKey,

View File

@ -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);
}

View File

@ -1618,7 +1618,7 @@ OpenFile(nsIPrincipal* aPrincipal,
return JS::AsmJSCache_Success;
}
} // anonymous namespace
} // namespace
typedef uint32_t AsmJSCookieType;
static const uint32_t sAsmJSCookie = 0x600d600d;

View File

@ -19,7 +19,7 @@ namespace dom {
namespace quota {
class Client;
}
} // namespace quota
namespace asmjscache {

View File

@ -65,4 +65,5 @@ private:
} // namespace dom
} // namespace mozilla
#endif

View File

@ -138,5 +138,5 @@ AnonymousContent::WrapObject(JSContext* aCx,
return AnonymousContentBinding::Wrap(aCx, this, aGivenProto, aReflector);
}
} // dom namespace
} // mozilla namespace
} // namespace dom
} // namespace mozilla

View File

@ -58,7 +58,7 @@ private:
nsCOMPtr<Element> mContentNode;
};
} // dom namespace
} // mozilla namespace
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_AnonymousContent_h

View File

@ -83,7 +83,7 @@ protected:
uint64_t mDataBufferLen;
};
} // dom namespace
} // mozilla namespace
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_BlobSet_h

View File

@ -345,5 +345,6 @@ AllChildrenIterator::GetNextChild()
return nullptr;
}
} // namespace dom
} // namespace mozilla

View File

@ -28,5 +28,6 @@ ChromeUtils::OriginAttributesToSuffix(dom::GlobalObject& aGlobal,
OriginAttributes attrs(aAttrs);
attrs.CreateSuffix(aSuffix);
}
} // namespace dom
} // namespace mozilla

View File

@ -16,7 +16,7 @@ namespace mozilla {
namespace devtools {
class HeapSnapshot;
}
} // namespace devtools
namespace dom {

View File

@ -1469,7 +1469,7 @@ FlushOutput(JSContext* aCx, Sequence<JS::Value>& aSequence, nsString &aOutput)
return true;
}
} // anonymous namespace
} // namespace
bool
Console::ProcessArguments(JSContext* aCx,

View File

@ -221,7 +221,7 @@ private:
friend class ConsoleProfileRunnable;
};
} // dom namespace
} // mozilla namespace
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_Console_h */

View File

@ -248,7 +248,7 @@ private:
void Ensure3DMatrix();
};
}
}
} // namespace dom
} // namespace mozilla
#endif /*MOZILLA_DOM_DOMMATRIX_H_*/

View File

@ -73,7 +73,7 @@ public:
void SetW(double aW) { mW = aW; }
};
}
}
} // namespace dom
} // namespace mozilla
#endif /*MOZILLA_DOMPOINT_H_*/

View File

@ -65,7 +65,7 @@ protected:
mutable nsRefPtr<QuadBounds> mBounds; // allocated lazily
};
}
}
} // namespace dom
} // namespace mozilla
#endif /*MOZILLA_DOMRECT_H_*/

View File

@ -210,8 +210,7 @@ protected:
nsCOMPtr<nsISupports> mParent;
};
}
}
} // namespace dom
} // namespace mozilla
#endif /*MOZILLA_DOMRECT_H_*/

View File

@ -25,7 +25,7 @@ Element::UnregisterActivityObserver()
OwnerDoc()->UnregisterActivityObserver(this);
}
}
}
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ElementInlines_h

View File

@ -1333,5 +1333,5 @@ BlobSet::AppendBlobImpls(const nsTArray<nsRefPtr<BlobImpl>>& aBlobImpls)
return NS_OK;
}
} // dom namespace
} // mozilla namespace
} // namespace dom
} // namespace mozilla

View File

@ -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

View File

@ -2335,7 +2335,7 @@ private:
uint32_t mLength;
};
} // anonymous namespace
} // namespace
static void
AppendEncodedCharacters(const nsTextFragment* aText, StringBuilder& aBuilder)

View File

@ -35,8 +35,8 @@ class nsIURI;
namespace mozilla {
namespace dom {
class Element;
}
}
} // namespace dom
} // namespace mozilla
/**
* A class that implements nsIWeakReference

View File

@ -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;
}

View File

@ -20,7 +20,7 @@ namespace mozilla {
namespace layers {
class Image;
}
} // namespace layers
namespace dom {

View File

@ -778,7 +778,7 @@ VibrateWindowListener::RemoveListener()
true /* use capture */);
}
} // anonymous namespace
} // namespace
void
Navigator::AddIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv)

View File

@ -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 {

View File

@ -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

View File

@ -104,7 +104,7 @@ private:
nsTArray<MessagePortIdentifier> mPortIdentifiers;
};
} // dom namespace
} // mozilla namespace
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_PostMessageEvent_h

View File

@ -540,5 +540,5 @@ URL::CreateSearchParamsIfNeeded()
}
}
}
}
} // namespace dom
} // namespace mozilla

View File

@ -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___ */

View File

@ -272,7 +272,7 @@ void SerializeString(const nsCString& aInput, nsAString& aValue)
}
}
} // anonymous namespace
} // namespace
void
URLParams::Serialize(nsAString& aValue) const

View File

@ -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

View File

@ -41,5 +41,6 @@ struct ChangesToFlush {
bool mFlushAnimations;
};
}
} // namespace mozilla
#endif /* mozFlushType_h___ */

View File

@ -35,8 +35,8 @@ namespace css {
class StyleRule;
struct URLValue;
struct ImageValue;
}
}
} // namespace css
} // namespace mozilla
#define NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM 12

View File

@ -45,7 +45,7 @@ private:
namespace mozilla {
namespace dom {
void TraceBlackJS(JSTracer* aTrc, uint32_t aGCNumber, bool aIsShutdownGC);
}
}
} // namespace dom
} // namespace mozilla
#endif

View File

@ -23,8 +23,8 @@ class nsIFile;
namespace mozilla {
namespace dom {
class DataTransfer;
}
}
} // namespace dom
} // namespace mozilla
//
// class nsContentAreaDragDrop, used to generate the dragdata

View File

@ -33,8 +33,8 @@
namespace mozilla {
namespace dom {
class Element;
}
}
} // namespace dom
} // namespace mozilla
class nsBaseContentList : public nsINodeList

View File

@ -30,7 +30,7 @@ class nsContentPermissionRequestProxy;
// That will mess up windows build.
namespace IPC {
class Principal;
}
} // namespace IPC
class VisibilityChangeListener final : public nsIDOMEventListener
{

View File

@ -42,8 +42,8 @@ class nsIApplicationCache;
namespace mozilla {
namespace css {
class Loader;
}
}
} // namespace css
} // namespace mozilla
#ifdef DEBUG

View File

@ -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()

View File

@ -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

View File

@ -28,8 +28,8 @@
namespace mozilla {
namespace dom {
class Blob;
}
}
} // namespace dom
} // namespace mozilla
class nsDOMFileReader final : public mozilla::dom::FileIOObject,
public nsIDOMFileReader,

View File

@ -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
{

View File

@ -24,8 +24,8 @@ struct nsPoint;
namespace mozilla {
namespace layers {
class LayerTransactionChild;
}
}
} // namespace layers
} // namespace mozilla
class nsTranslationNodeList final : public nsITranslationNodeList
{

View File

@ -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,

View File

@ -122,6 +122,7 @@ public:
// need to send some notification itself with the real origin.
bool mShouldNotifyNewOrigin = true;
};
} // namespace dom
} // namespace mozilla

View File

@ -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

View File

@ -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.

View File

@ -50,7 +50,7 @@ CreateNewFileInstance(Blob& aBlob, const Optional<nsAString>& aFilename)
return aBlob.ToFile(filename);
}
} // anonymous namespace
} // namespace
// -------------------------------------------------------------------------
// nsISupports

View File

@ -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;

View File

@ -1444,7 +1444,7 @@ struct MessageManagerReferentCount
nsDataHashtable<nsStringHashKey, uint32_t> mMessageCounter;
};
} // anonymous namespace
} // namespace
namespace mozilla {
namespace dom {

View File

@ -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")

View File

@ -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.

View File

@ -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,

View File

@ -309,7 +309,7 @@ class BlobURLsReporter final : public nsIMemoryReporter
NS_IMPL_ISUPPORTS(BlobURLsReporter, nsIMemoryReporter)
}
} // namespace mozilla
void
nsHostObjectProtocolHandler::Init(void)

View File

@ -26,8 +26,8 @@ class DOMMediaStream;
namespace dom {
class BlobImpl;
class MediaSource;
}
}
} // namespace dom
} // namespace mozilla
class nsHostObjectProtocolHandler : public nsIProtocolHandler
{

View File

@ -11,8 +11,8 @@
namespace mozilla {
namespace dom {
class Animation;
}
}
} // namespace dom
} // namespace mozilla
#define NS_IANIMATION_OBSERVER_IID \
{ 0xed025fc7, 0xdeda, 0x48b9, \

View File

@ -64,7 +64,7 @@ private:
nsTArray<nsCString> mURIs;
};
} // anonymous namespace
} // namespace
void
nsIGlobalObject::UnlinkHostObjectURIs()

View File

@ -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

View File

@ -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()

View File

@ -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.

View File

@ -28,8 +28,8 @@ namespace mozilla {
namespace dom {
class AutoJSAPI;
class Element;
}
}
} // namespace dom
} // namespace mozilla
class nsJSUtils
{

View File

@ -30,8 +30,8 @@ template<class T> struct already_AddRefed;
namespace mozilla {
namespace dom {
class NodeInfo;
}
}
} // namespace dom
} // namespace mozilla
class nsNodeInfoManager final
{

View File

@ -18,8 +18,8 @@ class nsCycleCollectionTraversalCallback;
namespace mozilla {
namespace dom {
class Animation;
}
}
} // namespace dom
} // namespace mozilla
class nsNodeUtils
{

View File

@ -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

View File

@ -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