Bug 1198563 part 1 - Encapsulate iterating fullscreen request list code. r=smaug

This commit is contained in:
Xidorn Quan 2015-08-27 11:21:29 +10:00
parent 7019ee5f82
commit e645a7ee1c
3 changed files with 91 additions and 76 deletions

View File

@ -11631,7 +11631,84 @@ FullscreenRequest::~FullscreenRequest()
// of nsDocument because in the majority of time, there would be at most
// one document requesting fullscreen. We shouldn't waste the space to
// hold for it in every document.
static LinkedList<FullscreenRequest> sPendingFullscreenRequests;
class PendingFullscreenRequestList
{
public:
static void Add(UniquePtr<FullscreenRequest>&& aRequest)
{
sList.insertBack(aRequest.release());
}
static const FullscreenRequest* GetLast()
{
return sList.getLast();
}
class Iterator
{
public:
explicit Iterator(nsIDocument* aDoc)
: mCurrent(PendingFullscreenRequestList::sList.getFirst())
{
if (mCurrent) {
mRootShell = GetRootShell(aDoc);
SkipToNextMatch();
}
}
void DeleteAndNext()
{
DeleteAndNextInternal();
SkipToNextMatch();
}
bool AtEnd() const { return mCurrent == nullptr; }
const FullscreenRequest& Get() const { return *mCurrent; }
private:
already_AddRefed<nsIDocShellTreeItem> GetRootShell(nsIDocument* aDoc)
{
if (nsIDocShellTreeItem* shell = aDoc->GetDocShell()) {
nsCOMPtr<nsIDocShellTreeItem> rootShell;
shell->GetRootTreeItem(getter_AddRefs(rootShell));
return rootShell.forget();
}
return nullptr;
}
void DeleteAndNextInternal()
{
FullscreenRequest* thisRequest = mCurrent;
mCurrent = mCurrent->getNext();
delete thisRequest;
}
void SkipToNextMatch()
{
while (mCurrent) {
nsCOMPtr<nsIDocShellTreeItem>
rootShell = GetRootShell(mCurrent->GetDocument());
if (!rootShell) {
// Always automatically drop documents which has been
// detached from the doc shell.
DeleteAndNextInternal();
} else if (rootShell != mRootShell) {
mCurrent = mCurrent->getNext();
} else {
break;
}
}
}
FullscreenRequest* mCurrent;
nsCOMPtr<nsIDocShellTreeItem> mRootShell;
};
private:
PendingFullscreenRequestList() = delete;
static LinkedList<FullscreenRequest> sList;
};
/* static */ LinkedList<FullscreenRequest> PendingFullscreenRequestList::sList;
static nsCOMPtr<nsPIDOMWindow>
GetRootWindow(nsIDocument* aDoc)
@ -11669,7 +11746,7 @@ nsDocument::RequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
return;
}
sPendingFullscreenRequests.insertBack(aRequest.release());
PendingFullscreenRequestList::Add(Move(aRequest));
if (XRE_GetProcessType() == GeckoProcessType_Content) {
// If we are not the top level process, dispatch an event to make
// our parent process go fullscreen first.
@ -11678,58 +11755,24 @@ nsDocument::RequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
/* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
} else {
// Make the window fullscreen.
FullscreenRequest* lastRequest = sPendingFullscreenRequests.getLast();
const FullscreenRequest*
lastRequest = PendingFullscreenRequestList::GetLast();
rootWin->SetFullscreenInternal(nsPIDOMWindow::eForFullscreenAPI, true,
lastRequest->mVRHMDDevice);
}
}
/* static */ bool
nsIDocument::HandlePendingFullscreenRequest(const FullscreenRequest& aRequest,
nsIDocShellTreeItem* aRootShell,
bool* aHandled)
{
nsDocument* doc = aRequest.GetDocument();
nsIDocShellTreeItem* shell = doc->GetDocShell();
if (!shell) {
return true;
}
nsCOMPtr<nsIDocShellTreeItem> rootShell;
shell->GetRootTreeItem(getter_AddRefs(rootShell));
if (rootShell != aRootShell) {
return false;
}
if (doc->ApplyFullscreen(aRequest)) {
*aHandled = true;
}
return true;
}
/* static */ bool
nsIDocument::HandlePendingFullscreenRequests(nsIDocument* aDoc)
{
if (sPendingFullscreenRequests.isEmpty()) {
return false;
}
bool handled = false;
nsIDocShellTreeItem* shell = aDoc->GetDocShell();
nsCOMPtr<nsIDocShellTreeItem> rootShell;
if (shell) {
shell->GetRootTreeItem(getter_AddRefs(rootShell));
}
FullscreenRequest* request = sPendingFullscreenRequests.getFirst();
while (request) {
if (HandlePendingFullscreenRequest(*request, rootShell, &handled)) {
// Drop requests, which either have been detached from document/
// document shell, or are handled by HandleFullscreenRequest.
FullscreenRequest* thisRequest = request;
request = request->getNext();
delete thisRequest;
} else {
request = request->getNext();
PendingFullscreenRequestList::Iterator iter(aDoc);
while (!iter.AtEnd()) {
const FullscreenRequest& request = iter.Get();
if (request.GetDocument()->ApplyFullscreen(request)) {
handled = true;
}
iter.DeleteAndNext();
}
return handled;
}
@ -11737,29 +11780,9 @@ nsIDocument::HandlePendingFullscreenRequests(nsIDocument* aDoc)
static void
ClearPendingFullscreenRequests(nsIDocument* aDoc)
{
nsIDocShellTreeItem* shell = aDoc->GetDocShell();
if (!shell) {
return;
}
FullscreenRequest* request = sPendingFullscreenRequests.getFirst();
while (request) {
nsIDocument* doc = request->GetDocument();
bool shouldRemove = false;
for (nsCOMPtr<nsIDocShellTreeItem> docShell = doc->GetDocShell();
docShell; docShell->GetParent(getter_AddRefs(docShell))) {
if (docShell == shell) {
shouldRemove = true;
break;
}
}
if (shouldRemove) {
FullscreenRequest* thisRequest = request;
request = request->getNext();
delete thisRequest;
} else {
request = request->getNext();
}
PendingFullscreenRequestList::Iterator iter(aDoc);
while (!iter.AtEnd()) {
iter.DeleteAndNext();
}
}

View File

@ -100,6 +100,7 @@ class CallbackFunction;
struct FullscreenRequest : public LinkedListElement<FullscreenRequest>
{
explicit FullscreenRequest(Element* aElement);
FullscreenRequest(const FullscreenRequest&) = delete;
~FullscreenRequest();
Element* GetElement() const { return mElement; }

View File

@ -1184,15 +1184,6 @@ public:
*/
static void AsyncExitFullscreen(nsIDocument* aDocument);
/**
* Handles one single fullscreen request, updates `aHandled` if the request
* is handled, and returns whether this request should be removed from the
* request queue.
*/
static bool HandlePendingFullscreenRequest(const FullscreenRequest& aRequest,
nsIDocShellTreeItem* aRootShell,
bool* aHandled);
/**
* Handles any pending fullscreen in aDocument or its subdocuments.
*