mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 704039 part 2 - Implement full-screen mode rollback stack. r=bz
This commit is contained in:
parent
1279d53503
commit
c2405549e1
@ -134,6 +134,15 @@ public:
|
||||
*/
|
||||
void UpdateLinkState(nsEventStates aState);
|
||||
|
||||
/**
|
||||
* Returns true if this element is either a full-screen element or an
|
||||
* ancestor of the full-screen element.
|
||||
*/
|
||||
bool IsFullScreenAncestor() const {
|
||||
return mState.HasAtLeastOneOfStates(NS_EVENT_STATE_FULL_SCREEN_ANCESTOR |
|
||||
NS_EVENT_STATE_FULL_SCREEN);
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Method to get the _intrinsic_ content state of this element. This is the
|
||||
|
@ -124,8 +124,9 @@ class Element;
|
||||
} // namespace mozilla
|
||||
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0x3b78f6, 0x6dc5, 0x44c6, \
|
||||
{ 0xbc, 0x28, 0x60, 0x2a, 0xb2, 0x4f, 0xfb, 0x7b } }
|
||||
{ 0x283ec27d, 0x5b23, 0x49b2, \
|
||||
{ 0x94, 0xd9, 0x9, 0xb5, 0xdb, 0x45, 0x30, 0x73 } }
|
||||
|
||||
|
||||
// Flag for AddStyleSheet().
|
||||
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
|
||||
@ -752,21 +753,31 @@ public:
|
||||
|
||||
/**
|
||||
* Asynchronously requests that the document make aElement the full-screen
|
||||
* element, and move into full-screen mode.
|
||||
* element, and move into full-screen mode. The current full-screen element
|
||||
* (if any) is pushed onto the full-screen element stack, and it can be
|
||||
* returned to full-screen status by calling RestorePreviousFullScreenState().
|
||||
*/
|
||||
virtual void AsyncRequestFullScreen(Element* aElement) = 0;
|
||||
|
||||
/**
|
||||
* Requests that the document, and all documents in its hierarchy exit
|
||||
* from DOM full-screen mode.
|
||||
* Restores the previous full-screen element to full-screen status. If there
|
||||
* is no former full-screen element, this exits full-screen, moving the
|
||||
* top-level browser window out of full-screen mode.
|
||||
*/
|
||||
virtual void CancelFullScreen() = 0;
|
||||
virtual void RestorePreviousFullScreenState() = 0;
|
||||
|
||||
/**
|
||||
* Returns true if this document is in full-screen mode.
|
||||
*/
|
||||
virtual bool IsFullScreenDoc() = 0;
|
||||
|
||||
/**
|
||||
* Exits all documents from DOM full-screen mode, and moves the top-level
|
||||
* browser window out of full-screen mode. If aRunAsync is true, this runs
|
||||
* asynchronously.
|
||||
*/
|
||||
static void ExitFullScreen(bool aRunAsync);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Document notification API's
|
||||
|
@ -1872,7 +1872,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
|
||||
nsIDOMNodeList)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOriginalDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCachedEncoder)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFullScreenElement)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mStateObjectCached)
|
||||
|
||||
// Traverse all our nsCOMArrays.
|
||||
@ -1927,7 +1926,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mImageMaps)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOriginalDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCachedEncoder)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFullScreenElement)
|
||||
|
||||
tmp->mParentDocument = nsnull;
|
||||
|
||||
@ -7303,21 +7301,6 @@ NotifyPageHide(nsIDocument* aDocument, void* aData)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
SetFullScreenElement(nsIDocument* aDoc, Element* aElement);
|
||||
|
||||
static void
|
||||
SetWindowFullScreen(nsIDocument* aDoc, bool aValue);
|
||||
|
||||
static bool
|
||||
ResetFullScreen(nsIDocument* aDocument, void* aData) {
|
||||
if (aDocument->IsFullScreenDoc()) {
|
||||
::SetFullScreenElement(aDocument, nsnull);
|
||||
aDocument->EnumerateSubDocuments(ResetFullScreen, nsnull);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::OnPageHide(bool aPersisted,
|
||||
nsIDOMEventTarget* aDispatchStartTarget)
|
||||
@ -7372,23 +7355,15 @@ nsDocument::OnPageHide(bool aPersisted,
|
||||
// A full-screen doc has been hidden. We need to ensure we exit
|
||||
// full-screen, i.e. remove full-screen state from all full-screen
|
||||
// documents, and exit the top-level window from full-screen mode.
|
||||
// Unfortunately by the time a doc is hidden, it has been removed
|
||||
// from the doc tree, so we can't just call CancelFullScreen()...
|
||||
// By the time a doc is hidden, it has been removed from the doc tree,
|
||||
// so nsIDocument::ExitFullScreen() won't be able to traverse to this
|
||||
// document to reset its state, so reset full-screen state in *this*
|
||||
// document. OnPageHide() is called in every hidden document, so doing
|
||||
// this ensures all hidden documents have their full-screen state reset.
|
||||
ClearFullScreenStack();
|
||||
|
||||
// So firstly reset full-screen state in *this* document. OnPageHide()
|
||||
// is called in every hidden document, so doing this ensures all hidden
|
||||
// documents have their state reset.
|
||||
::SetFullScreenElement(this, nsnull);
|
||||
|
||||
// Next walk the document tree of still visible documents, and reset
|
||||
// their full-screen state. We then move the top-level window out
|
||||
// of full-screen mode.
|
||||
nsCOMPtr<nsIDocument> fullScreenRoot(do_QueryReferent(sFullScreenRootDoc));
|
||||
if (fullScreenRoot) {
|
||||
fullScreenRoot->EnumerateSubDocuments(ResetFullScreen, nsnull);
|
||||
SetWindowFullScreen(fullScreenRoot, false);
|
||||
sFullScreenRootDoc = nsnull;
|
||||
}
|
||||
// Next reset full-screen state in all visible documents in the doctree.
|
||||
nsIDocument::ExitFullScreen(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8444,40 +8419,13 @@ DispatchFullScreenChange(nsIDocument* aTarget)
|
||||
e->PostDOMEvent();
|
||||
}
|
||||
|
||||
bool
|
||||
nsDocument::SetFullScreenElement(Element* aElement)
|
||||
{
|
||||
if (mFullScreenElement == aElement) {
|
||||
return false;
|
||||
}
|
||||
if (mFullScreenElement) {
|
||||
// Reset the ancestor and full-screen styles on the outgoing full-screen
|
||||
// element in the current document.
|
||||
nsEventStateManager::SetFullScreenState(mFullScreenElement, false);
|
||||
}
|
||||
bool stateChange = (mFullScreenElement != nsnull) != (aElement != nsnull);
|
||||
mFullScreenElement = aElement;
|
||||
if (aElement) {
|
||||
nsEventStateManager::SetFullScreenState(aElement, true);
|
||||
}
|
||||
return stateChange;
|
||||
}
|
||||
|
||||
// Wrapper for the nsIDocument -> nsDocument cast required to call
|
||||
// nsDocument::SetFullScreenElement().
|
||||
static bool
|
||||
SetFullScreenElement(nsIDocument* aDoc, Element* aElement)
|
||||
{
|
||||
return static_cast<nsDocument*>(aDoc)->SetFullScreenElement(aElement);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::MozCancelFullScreen()
|
||||
{
|
||||
if (!nsContentUtils::IsRequestFullScreenAllowed()) {
|
||||
return NS_OK;
|
||||
}
|
||||
CancelFullScreen();
|
||||
RestorePreviousFullScreenState();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -8510,8 +8458,80 @@ SetWindowFullScreen(nsIDocument* aDoc, bool aValue)
|
||||
nsContentUtils::AddScriptRunner(new nsSetWindowFullScreen(aDoc, aValue));
|
||||
}
|
||||
|
||||
class nsCallExitFullScreen : public nsRunnable {
|
||||
public:
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsDocument::ExitFullScreen();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsDocument::CancelFullScreen()
|
||||
nsIDocument::ExitFullScreen(bool aRunAsync)
|
||||
{
|
||||
if (aRunAsync) {
|
||||
NS_DispatchToCurrentThread(new nsCallExitFullScreen());
|
||||
return;
|
||||
}
|
||||
nsDocument::ExitFullScreen();
|
||||
}
|
||||
|
||||
static bool
|
||||
ResetFullScreen(nsIDocument* aDocument, void* aData) {
|
||||
if (aDocument->IsFullScreenDoc()) {
|
||||
static_cast<nsDocument*>(aDocument)->ClearFullScreenStack();
|
||||
NS_ASSERTION(!aDocument->IsFullScreenDoc(), "Should reset full-screen");
|
||||
nsTArray<nsIDocument*>* changed = reinterpret_cast<nsTArray<nsIDocument*>*>(aData);
|
||||
changed->AppendElement(aDocument);
|
||||
aDocument->EnumerateSubDocuments(ResetFullScreen, aData);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsDocument::ExitFullScreen()
|
||||
{
|
||||
// Clear full-screen stacks in all descendant documents.
|
||||
nsCOMPtr<nsIDocument> root(do_QueryReferent(sFullScreenRootDoc));
|
||||
if (!root) {
|
||||
// Not in full-screen mode.
|
||||
return;
|
||||
}
|
||||
NS_ASSERTION(root->IsFullScreenDoc(),
|
||||
"Full-screen root should be a full-screen doc...");
|
||||
|
||||
// Stores a list of documents to which we must dispatch "mozfullscreenchange".
|
||||
// We're required by the spec to dispatch the events in leaf-to-root
|
||||
// order when exiting full-screen, but we traverse the doctree in a
|
||||
// root-to-leaf order, so we save references to the documents we must
|
||||
// dispatch to so that we dispatch in the specified order.
|
||||
nsAutoTArray<nsIDocument*, 8> changed;
|
||||
|
||||
// Walk the tree of full-screen documents, and reset their full-screen state.
|
||||
ResetFullScreen(root, static_cast<void*>(&changed));
|
||||
|
||||
// Dispatch "mozfullscreenchange" events. Note this loop is in reverse
|
||||
// order so that the events for the leaf document arrives before the root
|
||||
// document, as required by the spec.
|
||||
for (PRUint32 i = 0; i < changed.Length(); ++i) {
|
||||
DispatchFullScreenChange(changed[changed.Length() - i - 1]);
|
||||
}
|
||||
|
||||
// Reset global state. Do this before we move the window out of full-screen
|
||||
// mode, as that calls nsGlobalWindow::SetFullScreen() which calls back into
|
||||
// nsIDocument::ExitFullScreen().
|
||||
sFullScreenRootDoc = nsnull;
|
||||
sFullScreenDoc = nsnull;
|
||||
|
||||
// Move the top-level window out of full-screen mode.
|
||||
SetWindowFullScreen(root, false);
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::RestorePreviousFullScreenState()
|
||||
{
|
||||
NS_ASSERTION(!IsFullScreenDoc() || sFullScreenDoc != nsnull,
|
||||
"Should have a full-screen doc when full-screen!");
|
||||
@ -8520,32 +8540,57 @@ nsDocument::CancelFullScreen()
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset full-screen state in all full-screen documents.
|
||||
nsCOMPtr<nsIDocument> doc(do_QueryReferent(sFullScreenDoc));
|
||||
while (doc != nsnull) {
|
||||
if (::SetFullScreenElement(doc, nsnull)) {
|
||||
DispatchFullScreenChange(doc);
|
||||
}
|
||||
// Clear full-screen stacks in all descendant documents, bottom up.
|
||||
nsCOMPtr<nsIDocument> fullScreenDoc(do_QueryReferent(sFullScreenDoc));
|
||||
nsIDocument* doc = fullScreenDoc;
|
||||
while (doc != this) {
|
||||
NS_ASSERTION(doc->IsFullScreenDoc(), "Should be full-screen doc");
|
||||
static_cast<nsDocument*>(doc)->ClearFullScreenStack();
|
||||
DispatchFullScreenChange(doc);
|
||||
doc = doc->GetParentDocument();
|
||||
}
|
||||
sFullScreenDoc = nsnull;
|
||||
sFullScreenRootDoc = nsnull;
|
||||
|
||||
// Move the window out of full-screen mode.
|
||||
SetWindowFullScreen(this, false);
|
||||
// Roll-back full-screen state to previous full-screen element.
|
||||
NS_ASSERTION(doc == this, "Must have reached this doc.");
|
||||
while (doc != nsnull) {
|
||||
static_cast<nsDocument*>(doc)->FullScreenStackPop();
|
||||
DispatchFullScreenChange(doc);
|
||||
if (static_cast<nsDocument*>(doc)->mFullScreenStack.IsEmpty()) {
|
||||
// Full-screen stack in document is empty. Go back up to the parent
|
||||
// document. We'll pop the containing element off its stack, and use
|
||||
// its next full-screen element as the full-screen element.
|
||||
doc = doc->GetParentDocument();
|
||||
} else {
|
||||
// Else we popped the top of the stack, and there's still another
|
||||
// element in there, so that will become the full-screen element.
|
||||
sFullScreenDoc = do_GetWeakReference(doc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
if (doc == nsnull) {
|
||||
// We moved all documents out of full-screen mode, reset global full-screen
|
||||
// state and move the top-level window out of full-screen mode.
|
||||
DebugOnly< nsCOMPtr<nsIDocument> > root(do_QueryReferent(sFullScreenRootDoc));
|
||||
NS_ASSERTION(!root->IsFullScreenDoc(), "Should have cleared all docs' stacks");
|
||||
sFullScreenDoc = nsnull;
|
||||
sFullScreenRootDoc = nsnull;
|
||||
SetWindowFullScreen(this, false);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsDocument::IsFullScreenDoc()
|
||||
{
|
||||
return mFullScreenElement != nsnull;
|
||||
return GetFullScreenElement() != nsnull;
|
||||
}
|
||||
|
||||
static nsIDocument*
|
||||
GetCommonAncestor(nsIDocument* aDoc1, nsIDocument* aDoc2)
|
||||
{
|
||||
if (!aDoc1 || !aDoc2) {
|
||||
return nsnull;
|
||||
}
|
||||
nsIDocument* doc1 = aDoc1;
|
||||
nsIDocument* doc2 = aDoc2;
|
||||
|
||||
@ -8629,12 +8674,99 @@ LogFullScreenDenied(bool aLogFailure, const char* aMessage, nsIDocument* aDoc)
|
||||
"DOM", aDoc);
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::ClearFullScreenStack()
|
||||
{
|
||||
if (mFullScreenStack.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
// The top element in the full-screen stack will have full-screen
|
||||
// style bits set on it and its ancestors. Remove the style bits.
|
||||
// Note the non-top elements won't have the style bits set.
|
||||
Element* top = FullScreenStackTop();
|
||||
NS_ASSERTION(top, "Should have a top when full-screen stack isn't empty");
|
||||
if (top) {
|
||||
nsEventStateManager::SetFullScreenState(top, false);
|
||||
}
|
||||
mFullScreenStack.Clear();
|
||||
}
|
||||
|
||||
bool
|
||||
nsDocument::FullScreenStackPush(Element* aElement)
|
||||
{
|
||||
NS_ASSERTION(aElement, "Must pass non-null to FullScreenStackPush()");
|
||||
Element* top = FullScreenStackTop();
|
||||
if (top == aElement || !aElement) {
|
||||
return false;
|
||||
}
|
||||
if (top) {
|
||||
// We're pushing a new element onto the full-screen stack, so we must
|
||||
// remove the ancestor and full-screen styles from the former top of the
|
||||
// stack.
|
||||
nsEventStateManager::SetFullScreenState(top, false);
|
||||
}
|
||||
nsEventStateManager::SetFullScreenState(aElement, true);
|
||||
mFullScreenStack.AppendElement(do_GetWeakReference(aElement));
|
||||
NS_ASSERTION(GetFullScreenElement() == aElement, "Should match");
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::FullScreenStackPop()
|
||||
{
|
||||
if (mFullScreenStack.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove styles from existing top element.
|
||||
Element* top = FullScreenStackTop();
|
||||
nsEventStateManager::SetFullScreenState(top, false);
|
||||
|
||||
// Remove top element. Note the remaining top element in the stack
|
||||
// will not have full-screen style bits set, so we will need to restore
|
||||
// them on the new top element before returning.
|
||||
PRUint32 last = mFullScreenStack.Length() - 1;
|
||||
mFullScreenStack.RemoveElementAt(last);
|
||||
|
||||
// Pop from the stack null elements (references to elements which have
|
||||
// been GC'd since they were added to the stack) and elements which are
|
||||
// no longer in this document.
|
||||
while (!mFullScreenStack.IsEmpty()) {
|
||||
Element* element = FullScreenStackTop();
|
||||
if (!element || !element->IsInDoc() || element->OwnerDoc() != this) {
|
||||
NS_ASSERTION(!element->IsFullScreenAncestor(),
|
||||
"Should have already removed full-screen styles");
|
||||
PRUint32 last = mFullScreenStack.Length() - 1;
|
||||
mFullScreenStack.RemoveElementAt(last);
|
||||
} else {
|
||||
// The top element of the stack is now an in-doc element. Apply the
|
||||
// full-screen styles and return.
|
||||
nsEventStateManager::SetFullScreenState(element, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Element*
|
||||
nsDocument::FullScreenStackTop()
|
||||
{
|
||||
if (mFullScreenStack.IsEmpty()) {
|
||||
return nsnull;
|
||||
}
|
||||
PRUint32 last = mFullScreenStack.Length() - 1;
|
||||
nsCOMPtr<Element> element(do_QueryReferent(mFullScreenStack[last]));
|
||||
NS_ASSERTION(element, "Should have full-screen element!");
|
||||
NS_ASSERTION(element->IsInDoc(), "Full-screen element should be in doc");
|
||||
NS_ASSERTION(element->OwnerDoc() == this, "Full-screen element should be in this doc");
|
||||
return element;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::RequestFullScreen(Element* aElement, bool aWasCallerChrome)
|
||||
{
|
||||
NS_ASSERTION(aElement,
|
||||
"Must pass non-null element to nsDocument::RequestFullScreen");
|
||||
if (!aElement) {
|
||||
if (!aElement || aElement == GetFullScreenElement()) {
|
||||
return;
|
||||
}
|
||||
if (!aElement->IsInDoc()) {
|
||||
@ -8653,28 +8785,29 @@ nsDocument::RequestFullScreen(Element* aElement, bool aWasCallerChrome)
|
||||
// IsFullScreenEnabled calls LogFullScreenDenied, no need to log.
|
||||
return;
|
||||
}
|
||||
if (GetFullScreenElement() &&
|
||||
!nsContentUtils::ContentIsDescendantOf(aElement, GetFullScreenElement())) {
|
||||
// If this document is full-screen, only grant full-screen requests from
|
||||
// a descendent of the current full-screen element.
|
||||
LogFullScreenDenied(true, "FullScreenDeniedNotDescendant", this);
|
||||
return;
|
||||
}
|
||||
|
||||
// Turn off full-screen state in all documents which were previously
|
||||
// full-screen but which shouldn't be after this request is granted.
|
||||
// Note commonAncestor will be null when in a separate browser window
|
||||
// to the requesting document.
|
||||
nsIDocument* commonAncestor = nsnull;
|
||||
// Stores a list of documents which we must dispatch "mozfullscreenchange"
|
||||
// too. We're required by the spec to dispatch the events in root-to-leaf
|
||||
// order, but we traverse the doctree in a leaf-to-root order, so we save
|
||||
// references to the documents we must dispatch to so that we get the order
|
||||
// as specified.
|
||||
nsAutoTArray<nsIDocument*, 8> changed;
|
||||
|
||||
// If another top-level window is full-screen. Exit it from full-screen.
|
||||
nsCOMPtr<nsIDocument> fullScreenDoc(do_QueryReferent(sFullScreenDoc));
|
||||
if (fullScreenDoc) {
|
||||
commonAncestor = GetCommonAncestor(fullScreenDoc, this);
|
||||
}
|
||||
nsIDocument* doc = fullScreenDoc;
|
||||
while (doc != commonAncestor) {
|
||||
if (::SetFullScreenElement(doc, nsnull)) {
|
||||
DispatchFullScreenChange(doc);
|
||||
}
|
||||
doc = doc->GetParentDocument();
|
||||
}
|
||||
if (!commonAncestor && fullScreenDoc) {
|
||||
// Other doc is in another browser window. Move it out of full-screen.
|
||||
// Note that nsGlobalWindow::SetFullScreen() proxies to the root window
|
||||
// in its hierarchy, and does not operate on the a per-nsIDOMWindow basis.
|
||||
SetWindowFullScreen(fullScreenDoc, false);
|
||||
nsIDocument* commonAncestor = GetCommonAncestor(fullScreenDoc, this);
|
||||
if (fullScreenDoc && !commonAncestor) {
|
||||
// A document which doesn't have a common ancestor is full-screen, this
|
||||
// must be in a separate browser window. Fully exit full-screen, to move
|
||||
// the other browser window/doctree out of full-screen.
|
||||
nsIDocument::ExitFullScreen(false);
|
||||
}
|
||||
|
||||
// Remember the root document, so that if a full-screen document is hidden
|
||||
@ -8684,10 +8817,10 @@ nsDocument::RequestFullScreen(Element* aElement, bool aWasCallerChrome)
|
||||
// Set the full-screen element. This sets the full-screen style on the
|
||||
// element, and the full-screen-ancestor styles on ancestors of the element
|
||||
// in this document.
|
||||
if (SetFullScreenElement(aElement)) {
|
||||
DispatchFullScreenChange(aElement->OwnerDoc());
|
||||
}
|
||||
|
||||
DebugOnly<bool> x = FullScreenStackPush(aElement);
|
||||
NS_ASSERTION(x, "Full-screen state of requesting doc should always change!");
|
||||
changed.AppendElement(this);
|
||||
|
||||
// Propagate up the document hierarchy, setting the full-screen element as
|
||||
// the element's container in ancestor documents. This also sets the
|
||||
// appropriate css styles as well. Note we don't propagate down the
|
||||
@ -8697,21 +8830,49 @@ nsDocument::RequestFullScreen(Element* aElement, bool aWasCallerChrome)
|
||||
nsIDocument* parent;
|
||||
while ((parent = child->GetParentDocument())) {
|
||||
Element* element = parent->FindContentForSubDocument(child)->AsElement();
|
||||
if (::SetFullScreenElement(parent, element)) {
|
||||
DispatchFullScreenChange(element->OwnerDoc());
|
||||
if (static_cast<nsDocument*>(parent)->FullScreenStackPush(element)) {
|
||||
changed.AppendElement(parent);
|
||||
child = parent;
|
||||
} else {
|
||||
NS_ASSERTION(!commonAncestor || child == commonAncestor,
|
||||
"Should finish loop at common ancestor (or null)");
|
||||
// We've reached either the root, or a point in the doctree where the
|
||||
// new full-screen element container is the same as the previous
|
||||
// full-screen element's container. No more changes need to be made
|
||||
// to the full-screen stacks of documents further up the tree.
|
||||
break;
|
||||
}
|
||||
child = parent;
|
||||
}
|
||||
|
||||
// Dispatch "mozfullscreenchange" events. Note this loop is in reverse
|
||||
// order so that the events for the root document arrives before the leaf
|
||||
// document, as required by the spec.
|
||||
for (PRUint32 i = 0; i < changed.Length(); ++i) {
|
||||
DispatchFullScreenChange(changed[changed.Length() - i - 1]);
|
||||
}
|
||||
|
||||
// Remember this is the requesting full-screen document.
|
||||
sFullScreenDoc = do_GetWeakReference(static_cast<nsIDocument*>(this));
|
||||
|
||||
// Make the window full-screen. Note we must make the state changes above
|
||||
// before making the window full-screen, as then the document reports as
|
||||
// being in full-screen mode when the chrome "fullscreen" event fires,
|
||||
// enabling chrome to distinguish between browser and dom full-screen
|
||||
// modes.
|
||||
// modes. Also note that nsGlobalWindow::SetFullScreen() (which
|
||||
// SetWindowFullScreen() calls) proxies to the root window in its hierarchy,
|
||||
// and does not operate on the a per-nsIDOMWindow basis.
|
||||
SetWindowFullScreen(this, true);
|
||||
|
||||
// Remember this is the requesting full-screen document.
|
||||
sFullScreenDoc = do_GetWeakReference(static_cast<nsIDocument*>(this));
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(GetFullScreenElement() == aElement,
|
||||
"Full-screen element should be the requested element!");
|
||||
NS_ASSERTION(IsFullScreenDoc(), "Should be full-screen doc");
|
||||
nsCOMPtr<nsIDOMHTMLElement> fse;
|
||||
GetMozFullScreenElement(getter_AddRefs(fse));
|
||||
nsCOMPtr<nsIContent> c(do_QueryInterface(fse));
|
||||
NS_ASSERTION(c->AsElement() == aElement,
|
||||
"GetMozFullScreenElement should match GetFullScreenElement()");
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -8730,7 +8891,10 @@ nsDocument::GetMozFullScreenElement(nsIDOMHTMLElement **aFullScreenElement)
|
||||
Element*
|
||||
nsDocument::GetFullScreenElement()
|
||||
{
|
||||
return mFullScreenElement;
|
||||
Element* element = FullScreenStackTop();
|
||||
NS_ASSERTION(!element || element->IsFullScreenAncestor(),
|
||||
"Should have full-screen styles applied!");
|
||||
return element;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -8749,6 +8913,26 @@ nsDocument::GetMozFullScreenEnabled(bool *aFullScreen)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool
|
||||
HasFullScreenSubDocument(nsIDocument* aDoc, void* aData)
|
||||
{
|
||||
if (aDoc->IsFullScreenDoc()) {
|
||||
// This subdocument is full-screen. Set result and return false to
|
||||
// stop iteration.
|
||||
*static_cast<bool*>(aData) = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
HasFullScreenSubDocument(nsIDocument* aDoc)
|
||||
{
|
||||
bool result = false;
|
||||
aDoc->EnumerateSubDocuments(&HasFullScreenSubDocument, static_cast<void*>(&result));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
nsDocument::IsFullScreenEnabled(bool aCallerIsChrome, bool aLogFailure)
|
||||
{
|
||||
@ -8772,6 +8956,10 @@ nsDocument::IsFullScreenEnabled(bool aCallerIsChrome, bool aLogFailure)
|
||||
LogFullScreenDenied(aLogFailure, "FullScreenDeniedHidden", this);
|
||||
return false;
|
||||
}
|
||||
if (HasFullScreenSubDocument(this)) {
|
||||
LogFullScreenDenied(aLogFailure, "FullScreenDeniedSubDocFullScreen", this);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure that all ancestor <iframe> elements have the mozallowfullscreen
|
||||
// boolean attribute set.
|
||||
|
@ -958,8 +958,9 @@ public:
|
||||
|
||||
virtual Element* GetFullScreenElement();
|
||||
virtual void AsyncRequestFullScreen(Element* aElement);
|
||||
virtual void CancelFullScreen();
|
||||
virtual void RestorePreviousFullScreenState();
|
||||
virtual bool IsFullScreenDoc();
|
||||
static void ExitFullScreen();
|
||||
|
||||
// This is called asynchronously by nsIDocument::AsyncRequestFullScreen()
|
||||
// to move document into full-screen mode if allowed. aWasCallerChrome
|
||||
@ -967,12 +968,23 @@ public:
|
||||
// by chrome code.
|
||||
void RequestFullScreen(Element* aElement, bool aWasCallerChrome);
|
||||
|
||||
// Sets the full-screen element to aElement, applying appropriate styles to
|
||||
// aElement, and removing them from the old full-screen element. Returns true
|
||||
// if making this change results in a change in the full-screen state of this
|
||||
// document.
|
||||
bool SetFullScreenElement(Element* aElement);
|
||||
|
||||
// Removes all elements from the full-screen stack, removing full-scren
|
||||
// styles from the top element in the stack.
|
||||
void ClearFullScreenStack();
|
||||
|
||||
// Pushes aElement onto the full-screen stack, and removes full-screen styles
|
||||
// from the former full-screen stack top, and its ancestors, and applies the
|
||||
// styles to aElement. aElement becomes the new "full-screen element".
|
||||
bool FullScreenStackPush(Element* aElement);
|
||||
|
||||
// Remove the top element from the full-screen stack. Removes the full-screen
|
||||
// styles from the former top element, and applies them to the new top
|
||||
// element, if there is one.
|
||||
void FullScreenStackPop();
|
||||
|
||||
// Returns the top element from the full-screen stack.
|
||||
Element* FullScreenStackTop();
|
||||
|
||||
// This method may fire a DOM event; if it does so it will happen
|
||||
// synchronously.
|
||||
void UpdateVisibilityState();
|
||||
@ -1112,6 +1124,11 @@ protected:
|
||||
// document is hidden/navigation occurs.
|
||||
static nsWeakPtr sFullScreenRootDoc;
|
||||
|
||||
// Stack of full-screen elements. When we request full-screen we push the
|
||||
// full-screen element onto this stack, and when we cancel full-screen we
|
||||
// pop one off this stack, restoring the previous full-screen state
|
||||
nsTArray<nsWeakPtr> mFullScreenStack;
|
||||
|
||||
nsRefPtr<nsEventListenerManager> mListenerManager;
|
||||
nsCOMPtr<nsIDOMStyleSheetList> mDOMStyleSheets;
|
||||
nsRefPtr<nsDOMStyleSheetSetList> mStyleSheetSetList;
|
||||
@ -1131,9 +1148,6 @@ protected:
|
||||
// Recorded time of change to 'loading' state.
|
||||
mozilla::TimeStamp mLoadingTimeStamp;
|
||||
|
||||
// The current full-screen element of this document.
|
||||
nsCOMPtr<Element> mFullScreenElement;
|
||||
|
||||
// True if the document has been detached from its content viewer.
|
||||
bool mIsGoingAway:1;
|
||||
// True if the document is being destroyed.
|
||||
|
@ -3067,14 +3067,6 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsFullScreenAncestor(Element* aElement)
|
||||
{
|
||||
nsEventStates state = aElement->State();
|
||||
return state.HasAtLeastOneOfStates(NS_EVENT_STATE_FULL_SCREEN_ANCESTOR |
|
||||
NS_EVENT_STATE_FULL_SCREEN);
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
{
|
||||
@ -3086,7 +3078,7 @@ nsGenericElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
HasFlag(NODE_FORCE_XBL_BINDINGS) ? OwnerDoc() : GetCurrentDoc();
|
||||
|
||||
if (aNullParent) {
|
||||
if (IsFullScreenAncestor(this)) {
|
||||
if (IsFullScreenAncestor()) {
|
||||
// The element being removed is an ancestor of the full-screen element,
|
||||
// exit full-screen state.
|
||||
nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
|
||||
@ -3094,8 +3086,9 @@ nsGenericElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
nsnull, 0, nsnull,
|
||||
EmptyString(), 0, 0,
|
||||
nsIScriptError::warningFlag,
|
||||
"DOM", OwnerDoc());
|
||||
OwnerDoc()->CancelFullScreen();
|
||||
"DOM", OwnerDoc());
|
||||
// Fully exit full-screen.
|
||||
nsIDocument::ExitFullScreen(false);
|
||||
}
|
||||
if (GetParent()) {
|
||||
NS_RELEASE(mParent);
|
||||
|
@ -297,8 +297,7 @@ nsHTMLSharedObjectElement::BindToTree(nsIDocument *aDocument,
|
||||
// This content contains a windowed plugin for which we don't control
|
||||
// event dispatch, and we're in full-screen mode. Exit full-screen mode
|
||||
// to prevent phishing attacks.
|
||||
NS_DispatchToCurrentThread(
|
||||
NS_NewRunnableMethod(aDocument, &nsIDocument::CancelFullScreen));
|
||||
nsIDocument::ExitFullScreen(true);
|
||||
nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
|
||||
"AddedWindowedPluginWhileFullScreen",
|
||||
nsnull, 0, nsnull,
|
||||
|
@ -292,6 +292,7 @@ _TEST_FILES = \
|
||||
file_fullscreen-navigation.html \
|
||||
file_fullscreen-esc-exit.html \
|
||||
file_fullscreen-esc-exit-inner.html \
|
||||
file_fullscreen-rollback.html \
|
||||
test_li_attributes_reflection.html \
|
||||
test_ol_attributes_reflection.html \
|
||||
test_bug651956.html \
|
||||
|
@ -28,11 +28,11 @@ var keyList = [
|
||||
];
|
||||
|
||||
function ok(condition, msg) {
|
||||
opener.ok(condition, msg);
|
||||
opener.ok(condition, "[keys] " + msg);
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
opener.is(a, b, msg);
|
||||
opener.is(a, b, "[keys] " + msg);
|
||||
}
|
||||
|
||||
var gKeyTestIndex = 0;
|
||||
|
@ -22,11 +22,11 @@ Test DOM full-screen API.
|
||||
/** Test for Bug 545812 **/
|
||||
|
||||
function ok(condition, msg) {
|
||||
opener.ok(condition, msg);
|
||||
opener.ok(condition, "[fullscreen] " + msg);
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
opener.is(a, b, msg);
|
||||
opener.is(a, b, "[fullscreen] " + msg);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -64,27 +64,23 @@ function fullScreenElement() {
|
||||
function fullScreenChange(event) {
|
||||
switch (fullScreenChangeCount) {
|
||||
case 0: {
|
||||
ok(document.mozFullScreen, "Should be in full-screen mode (first time)");
|
||||
is(event.target, document, "Event target should be full-screen document #1");
|
||||
is(document.mozFullScreenElement, fullScreenElement(),
|
||||
"Full-screen element should be div element.");
|
||||
ok(document.mozFullScreenElement.mozMatchesSelector(":-moz-full-screen"),
|
||||
"FSE should match :-moz-full-screen");
|
||||
ok(document.mozFullScreen, "1. Should be in full-screen mode (first time)");
|
||||
is(event.target, document, "2. Event target should be full-screen document #1");
|
||||
is(document.mozFullScreenElement, fullScreenElement(), "3. Full-screen element should be div element.");
|
||||
ok(document.mozFullScreenElement.mozMatchesSelector(":-moz-full-screen"), "4. FSE should match :-moz-full-screen");
|
||||
var fse = fullScreenElement();
|
||||
fse.parentNode.removeChild(fse);
|
||||
is(document.mozFullScreenElement, null,
|
||||
"Full-screen element should be null after removing.");
|
||||
ok(!document.mozFullScreen, "Should have left full-screen mode when we remove full-screen element");
|
||||
is(document.mozFullScreenElement, null, "5. Full-screen element should be null after removing.");
|
||||
ok(!document.mozFullScreen, "6. Should have left full-screen mode when we remove full-screen element");
|
||||
document.body.appendChild(fse);
|
||||
ok(!document.mozFullScreen, "Should not return to full-screen mode when re-adding former FSE");
|
||||
is(document.mozFullScreenElement, null,
|
||||
"Full-screen element should still be null after re-adding former FSE.");
|
||||
ok(!document.mozFullScreen, "7. Should not return to full-screen mode when re-adding former FSE");
|
||||
is(document.mozFullScreenElement, null, "8. Full-screen element should still be null after re-adding former FSE.");
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
ok(!document.mozFullScreen, "Should have left full-screen mode (first time)");
|
||||
is(event.target, document, "Event target should be full-screen document #2");
|
||||
is(document.mozFullScreenElement, null, "Full-screen element should be null.");
|
||||
ok(!document.mozFullScreen, "9. Should have left full-screen mode (first time)");
|
||||
is(event.target, document, "10. Event target should be full-screen document #2");
|
||||
is(document.mozFullScreenElement, null, "11. Full-screen element should be null.");
|
||||
iframe = document.createElement("iframe");
|
||||
iframe.mozAllowFullScreen = true;
|
||||
document.body.appendChild(iframe);
|
||||
@ -92,41 +88,48 @@ function fullScreenChange(event) {
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
ok(document.mozFullScreen, "Should be back in full-screen mode (second time)");
|
||||
is(event.target, document, "Event target should be full-screen document #3");
|
||||
is(document.mozFullScreenElement, iframe,
|
||||
"Full-screen element should be iframe element.");
|
||||
|
||||
SimpleTest.waitForFocus(function() {
|
||||
ok(document.mozFullScreen, "Should still be full-screen mode before focus.");
|
||||
SpecialPowers.focus(window);
|
||||
ok(document.mozFullScreen, "Should still be full-screen mode after focus.");
|
||||
|
||||
var fse = fullScreenElement();
|
||||
fse.mozRequestFullScreen();
|
||||
|
||||
// RequestFullScreen() is async, continue after it completes.
|
||||
setTimeout(function() {
|
||||
ok(document.mozFullScreen, "Should still be full-screen mode after re-requesting.");
|
||||
is(document.mozFullScreenElement, fse, "Full-screen element should have switched to requestee.");
|
||||
var _innerFrame = iframe.contentDocument.getElementById("inner-frame");
|
||||
_innerFrame.contentDocument.body.appendChild(fse);
|
||||
ok(!document.mozFullScreen, "Should exit full-screen after transplanting FSE");
|
||||
is(document.mozFullScreenElement, null, "Full-screen element transplanted, should be null.");
|
||||
is(iframe.contentDocument.mozFullScreenElement, null, "Full-screen element in outer frame should be null.");
|
||||
is(_innerFrame.contentDocument.mozFullScreenElement, null, "Full-screen element in inner frame should be null.");
|
||||
ok(!iframe.contentDocument.mozFullScreen, "Outer frame should not acquire full-screen status.");
|
||||
ok(!_innerFrame.contentDocument.mozFullScreen, "Inner frame should not acquire full-screen status.");
|
||||
|
||||
document.body.appendChild(fse);
|
||||
}, 0);
|
||||
}, 0);
|
||||
ok(document.mozFullScreen, "12. Should be back in full-screen mode (second time)");
|
||||
is(event.target, document, "13. Event target should be full-screen document #3");
|
||||
is(document.mozFullScreenElement, iframe, "14. Full-screen element should be iframe element.");
|
||||
is(iframe.contentDocument.mozFullScreenElement, iframe.contentDocument.body, "15. Full-screen element in subframe should be body");
|
||||
|
||||
// The iframe's body is full-screen. Cancel full-screen in the subdocument to return
|
||||
// the full-screen element to the previous full-screen element. This causes
|
||||
// a fullscreenchange event.
|
||||
document.mozCancelFullScreen();
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
ok(!document.mozFullScreen, "Should be back in non-full-screen mode (second time)");
|
||||
is(event.target, document, "Event target should be full-screen document #4");
|
||||
is(document.mozFullScreenElement, null, "Full-screen element should be null.");
|
||||
ok(!document.mozFullScreen, "16. Should have left full-screen when removing FSE ancestor.");
|
||||
is(document.mozFullScreenElement, null, "17. Full-screen element should have rolled back.");
|
||||
is(iframe.contentDocument.mozFullScreenElement, null, "18. Full-screen element in subframe should be null");
|
||||
|
||||
fullScreenElement().mozRequestFullScreen();
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
ok(document.mozFullScreen, "19. Should be back in full-screen mode (second time)");
|
||||
is(event.target, document, "20. Event target should be full-screen document #3");
|
||||
is(document.mozFullScreenElement, fullScreenElement(), "21. Full-screen element should be div.");
|
||||
|
||||
// Transplant the FSE into subdoc. Should exit full-screen.
|
||||
var _innerFrame = iframe.contentDocument.getElementById("inner-frame");
|
||||
var fse = fullScreenElement();
|
||||
_innerFrame.contentDocument.body.appendChild(fse);
|
||||
ok(!document.mozFullScreen, "22. Should exit full-screen after transplanting FSE");
|
||||
is(document.mozFullScreenElement, null, "23. Full-screen element transplanted, should be null.");
|
||||
is(iframe.contentDocument.mozFullScreenElement, null, "24. Full-screen element in outer frame should be null.");
|
||||
is(_innerFrame.contentDocument.mozFullScreenElement, null, "25. Full-screen element in inner frame should be null.");
|
||||
ok(!iframe.contentDocument.mozFullScreen, "26. Outer frame should not acquire full-screen status.");
|
||||
ok(!_innerFrame.contentDocument.mozFullScreen, "27. Inner frame should not acquire full-screen status.");
|
||||
|
||||
document.body.appendChild(fse);
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
ok(!document.mozFullScreen, "28. Should be back in non-full-screen mode (second time)");
|
||||
is(event.target, document, "29. Event target should be full-screen document #4");
|
||||
is(document.mozFullScreenElement, null, "30. Full-screen element should be null.");
|
||||
document.body.removeChild(iframe);
|
||||
iframe = null;
|
||||
|
||||
@ -136,7 +139,7 @@ function fullScreenChange(event) {
|
||||
var f =
|
||||
function(e) {
|
||||
document.removeEventListener("mozfullscreenerror", f, false);
|
||||
ok(!document.mozFullScreen, "Requests for full-screen from not-in-doc elements should fail.");
|
||||
ok(!document.mozFullScreen, "31. Requests for full-screen from not-in-doc elements should fail.");
|
||||
fullScreenErrorRun = true;
|
||||
|
||||
container = document.createElement("div");
|
||||
@ -151,12 +154,11 @@ function fullScreenChange(event) {
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
ok(document.mozFullScreen, "Should still be in full-screen mode (third time)");
|
||||
is(event.target, document, "Event target should be full-screen document #5");
|
||||
ok(fullScreenErrorRun, "Should have run fullscreenerror handler from previous case.");
|
||||
is(document.mozFullScreenElement, inDocElement,
|
||||
"FSE should be inDocElement.");
|
||||
case 6: {
|
||||
ok(document.mozFullScreen, "32. Should still be in full-screen mode (third time)");
|
||||
is(event.target, document, "33. Event target should be full-screen document #5");
|
||||
ok(fullScreenErrorRun, "34. Should have run fullscreenerror handler from previous case.");
|
||||
is(document.mozFullScreenElement, inDocElement, "35. FSE should be inDocElement.");
|
||||
|
||||
var n = container;
|
||||
do {
|
||||
@ -166,14 +168,12 @@ function fullScreenChange(event) {
|
||||
|
||||
// Remove full-screen ancestor element from document, verify it stops being reported as current FSE.
|
||||
container.parentNode.removeChild(container);
|
||||
ok(!document.mozFullScreen,
|
||||
"Should exit full-screen mode after removing full-screen element ancestor from document");
|
||||
is(document.mozFullScreenElement, null,
|
||||
"Should not have a full-screen element again.");
|
||||
ok(!document.mozFullScreen, "36. Should exit full-screen mode after removing full-screen element ancestor from document");
|
||||
is(document.mozFullScreenElement, null, "37. Should not have a full-screen element again.");
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
ok(!document.mozFullScreen, "Should be back in non-full-screen mode (third time)");
|
||||
case 7: {
|
||||
ok(!document.mozFullScreen, "38. Should be back in non-full-screen mode (third time)");
|
||||
setRequireTrustedContext(true);
|
||||
fullscreendenied = false;
|
||||
fullScreenElement().mozRequestFullScreen();
|
||||
@ -189,7 +189,7 @@ function fullScreenChange(event) {
|
||||
}, 0);
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
case 8: {
|
||||
ok(document.mozFullScreen, "Moved to full-screen after mouse click");
|
||||
document.mozCancelFullScreen();
|
||||
ok(document.mozFullScreen, "Should still be in full-screen mode, because calling context isn't trusted.");
|
||||
@ -198,7 +198,7 @@ function fullScreenChange(event) {
|
||||
ok(!document.mozFullScreen, "Should have left full-screen mode.");
|
||||
break;
|
||||
}
|
||||
case 7: {
|
||||
case 9: {
|
||||
ok(!document.mozFullScreen, "Should have left full-screen mode (last time).");
|
||||
|
||||
SpecialPowers.setBoolPref("full-screen-api.enabled", false);
|
||||
|
@ -22,11 +22,11 @@ Test DOM full-screen API.
|
||||
/** Test for Bug 545812 **/
|
||||
|
||||
function ok(condition, msg) {
|
||||
opener.ok(condition, msg);
|
||||
opener.ok(condition, "[denied] " + msg);
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
opener.is(a, b, msg);
|
||||
opener.is(a, b, "[denied] " + msg);
|
||||
}
|
||||
|
||||
var fullscreendenied = false;
|
||||
|
@ -21,11 +21,11 @@ exit DOM full-screen mode.
|
||||
<script type="application/javascript">
|
||||
|
||||
function ok(condition, msg) {
|
||||
opener.ok(condition, msg);
|
||||
opener.ok(condition, "[esc-exit] " + msg);
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
opener.is(a, b, msg);
|
||||
opener.is(a, b, "[esc-exit] " + msg);
|
||||
}
|
||||
|
||||
function finish() {
|
||||
@ -34,6 +34,7 @@ function finish() {
|
||||
|
||||
function fullscreenchange1(event) {
|
||||
ok(document.mozFullScreen, "Should have entered full-screen mode");
|
||||
is(document.mozFullScreenElement, document.body, "FSE should be doc");
|
||||
document.removeEventListener("mozfullscreenchange", fullscreenchange1, false);
|
||||
document.addEventListener("mozfullscreenchange", fullscreenchange2, false);
|
||||
ok(!document.getElementById("subdoc").contentWindow.escKeySent, "Should not yet have sent ESC key press.");
|
||||
|
@ -34,17 +34,18 @@ function boom()
|
||||
|
||||
function b2()
|
||||
{
|
||||
try { e1.mozRequestFullScreen(); } catch(e) { opener.ok(false, "Should not enter full-screen"); }
|
||||
try { e1.mozRequestFullScreen(); } catch(e) { opener.ok(false, "[hidden] Should not enter full-screen"); }
|
||||
setTimeout(done, 0);
|
||||
}
|
||||
|
||||
function done() {
|
||||
opener.ok(!document.mozFullScreen, "Should not have entered full-screen mode in hidden document.");
|
||||
opener.ok(!e1.ownerDocument.mozFullScreen, "Requesting owner should not have entered full-screen mode.");
|
||||
opener.ok(!document.mozFullScreen, "[hidden] Should not have entered full-screen mode in hidden document.");
|
||||
opener.ok(!e1.ownerDocument.mozFullScreen, "[hidden] Requesting owner should not have entered full-screen mode.");
|
||||
opener.nextTest();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
@ -34,14 +34,14 @@ function boom()
|
||||
e1.mozRequestFullScreen();
|
||||
setTimeout(
|
||||
function() {
|
||||
opener.ok(document.mozFullScreen, "Request should be granted");
|
||||
opener.ok(document.mozFullScreen, "[navigation] Request should be granted");
|
||||
frameWin.location = "data:text/html,<body text=blue onload='parent.b2()'>2";
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function b2()
|
||||
{
|
||||
opener.ok(!document.mozFullScreen, "Should have left full-screen due to navigation.");
|
||||
opener.ok(!document.mozFullScreen, "[navigation] Should have left full-screen due to navigation.");
|
||||
opener.nextTest();
|
||||
}
|
||||
|
||||
|
@ -43,11 +43,11 @@ Test plugins with DOM full-screen API:
|
||||
/** Test for Bug 545812 **/
|
||||
|
||||
function ok(condition, msg) {
|
||||
opener.ok(condition, msg);
|
||||
opener.ok(condition, "[plugins] " + msg);
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
opener.is(a, b, msg);
|
||||
opener.is(a, b, "[plugins] " + msg);
|
||||
}
|
||||
|
||||
const isMacOs = navigator.appVersion.indexOf("Macintosh") != -1;
|
||||
@ -144,6 +144,7 @@ function fullScreenChange(event) {
|
||||
switch (fullScreenChangeCount) {
|
||||
case 0: {
|
||||
ok(document.mozFullScreen, "Request for full-screen with document containing windowless plugin should be granted");
|
||||
is(document.mozFullScreenElement, document.body, "FSE should be body.");
|
||||
// Add windowed plugin to document, should cause full-screen mode to exit.
|
||||
document.body.appendChild(windowedPlugin);
|
||||
break;
|
||||
|
130
content/html/content/test/file_fullscreen-rollback.html
Normal file
130
content/html/content/test/file_fullscreen-rollback.html
Normal file
@ -0,0 +1,130 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=700764
|
||||
|
||||
Verifies that cancelFullScreen() rolls back to have the previous full-screen
|
||||
element full-screen.
|
||||
|
||||
Tests:
|
||||
* Request full-screen in doc.
|
||||
* Request full-screen in doc on element not descended from full-screen element. Request should be denied.
|
||||
* Request full-screen in subdoc.
|
||||
* Cancel full-screen in subdoc, doc should be full-screen.
|
||||
* Request full-screen in subdoc.
|
||||
* Removing FSE should fully-exit full-screen.
|
||||
|
||||
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 700764</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
</head>
|
||||
<body onload="start();">
|
||||
|
||||
<div id="fse">
|
||||
<div id="fse-inner">
|
||||
<iframe id="subdoc" mozallowfullscreen src="data:text/html,<html><body bgcolor='black'></body></html>"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="non-fse"></div>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 700764 **/
|
||||
|
||||
function ok(condition, msg) {
|
||||
opener.ok(condition, "[rollback] " + msg);
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
opener.is(a, b, "[rollback] " + msg);
|
||||
}
|
||||
|
||||
function addListener(type, f) {
|
||||
document.addEventListener("mozfullscreen" + type, f, false);
|
||||
}
|
||||
|
||||
function removeListener(type, f) {
|
||||
document.removeEventListener("mozfullscreen" + type, f, false);
|
||||
}
|
||||
|
||||
function e(id) {
|
||||
return document.getElementById(id);
|
||||
}
|
||||
|
||||
function start() {
|
||||
SimpleTest.waitForFocus(
|
||||
function() {
|
||||
addListener("change", change1);
|
||||
e("fse").mozRequestFullScreen();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function change1() {
|
||||
removeListener("change", change1);
|
||||
addListener("error", error1);
|
||||
is(document.mozFullScreenElement, e("fse"), "Body should be FSE");
|
||||
|
||||
// Request full-screen from element not descendent from current FSE.
|
||||
e("non-fse").mozRequestFullScreen();
|
||||
}
|
||||
|
||||
function error1() {
|
||||
removeListener("error", error1);
|
||||
addListener("change", change2);
|
||||
is(document.mozFullScreenElement, e("fse"), "FSE should not change");
|
||||
var iframe = e("subdoc");
|
||||
iframe.contentDocument.body.mozRequestFullScreen();
|
||||
}
|
||||
|
||||
function change2() {
|
||||
removeListener("change", change2);
|
||||
var iframe = e("subdoc");
|
||||
is(document.mozFullScreenElement, iframe, "Subdoc container should be FSE.");
|
||||
is(iframe.contentDocument.mozFullScreenElement, iframe.contentDocument.body, "Subdoc body should be FSE in subdoc");
|
||||
addListener("change", change3);
|
||||
iframe.contentDocument.mozCancelFullScreen();
|
||||
}
|
||||
|
||||
function change3() {
|
||||
removeListener("change", change3);
|
||||
is(document.mozFullScreenElement, e("fse"), "FSE should rollback to FSE.");
|
||||
addListener("change", change4);
|
||||
document.mozCancelFullScreen();
|
||||
}
|
||||
|
||||
function change4() {
|
||||
removeListener("change", change4);
|
||||
is(document.mozFullScreenElement, null, "Should have left full-screen entirely");
|
||||
addListener("change", change5);
|
||||
e("fse").mozRequestFullScreen();
|
||||
}
|
||||
|
||||
function change5() {
|
||||
removeListener("change", change5);
|
||||
addListener("change", change6);
|
||||
is(document.mozFullScreenElement, e("fse"), "FSE should be e('fse')");
|
||||
e("fse-inner").mozRequestFullScreen();
|
||||
}
|
||||
|
||||
function change6() {
|
||||
removeListener("change", change6);
|
||||
addListener("change", change7);
|
||||
var element = e('fse-inner');
|
||||
is(document.mozFullScreenElement, element, "FSE should be e('fse-inner')");
|
||||
element.parentNode.removeChild(element);
|
||||
}
|
||||
|
||||
function change7() {
|
||||
removeListener("change", change7);
|
||||
is(document.mozFullScreenElement, null, "Should have fully exited full-screen mode when removed FSE from doc");
|
||||
opener.nextTest();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -36,6 +36,7 @@ SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", false);
|
||||
// run in an iframe, which by default will not have the mozallowfullscreen
|
||||
// attribute set, so full-screen won't work.
|
||||
var gTestWindows = [
|
||||
"file_fullscreen-rollback.html",
|
||||
"file_fullscreen-esc-exit.html",
|
||||
"file_fullscreen-denied.html",
|
||||
"file_fullscreen-api.html",
|
||||
|
@ -4424,12 +4424,12 @@ nsGlobalWindow::SetFullScreen(bool aFullScreen)
|
||||
if (widget)
|
||||
widget->MakeFullScreen(aFullScreen);
|
||||
|
||||
if (!mFullScreen && mDocument) {
|
||||
// Notify the document that we've left full-screen mode. This is so that
|
||||
// if we're in full-screen mode and the user exits full-screen mode with
|
||||
// the browser full-screen mode toggle keyboard-shortcut, we detect that
|
||||
// and leave DOM API full-screen mode too.
|
||||
mDocument->MozCancelFullScreen();
|
||||
if (!mFullScreen) {
|
||||
// Force exit from DOM full-screen mode. This is so that if we're in
|
||||
// DOM full-screen mode and the user exits full-screen mode with
|
||||
// the browser full-screen mode toggle keyboard-shortcut, we'll detect
|
||||
// that and leave DOM API full-screen mode too.
|
||||
nsIDocument::ExitFullScreen(false);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -123,6 +123,8 @@ FullScreenDeniedNotInputDriven=Request for full-screen was denied because Elemen
|
||||
FullScreenDeniedNotInDocument=Request for full-screen was denied because requesting element is no longer in its document.
|
||||
FullScreenDeniedMovedDocument=Request for full-screen was denied because requesting element has moved document.
|
||||
FullScreenDeniedLostWindow=Request for full-screen was denied because we no longer have a window.
|
||||
FullScreenDeniedSubDocFullScreen=Request for full-screen was denied because a subdocument of the document requesting full-screen is already full-screen.
|
||||
FullScreenDeniedNotDescendant=Request for full-screen was denied because requesting element is not a descendant of the current full-screen element.
|
||||
RemovedFullScreenElement=Exited full-screen because full-screen element was removed from document.
|
||||
AddedWindowedPluginWhileFullScreen=Exited full-screen because windowed plugin was added to document.
|
||||
HTMLMultipartXHRWarning=HTML parsing in XMLHttpRequest is not supported for multipart responses.
|
||||
|
@ -3313,8 +3313,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
|
||||
nsIDocument *doc = mContent ? mContent->OwnerDoc() : nsnull;
|
||||
#ifndef XP_MACOSX
|
||||
if (!windowless && doc && doc->IsFullScreenDoc()) {
|
||||
NS_DispatchToCurrentThread(
|
||||
NS_NewRunnableMethod(doc, &nsIDocument::CancelFullScreen));
|
||||
nsIDocument::ExitFullScreen(true);
|
||||
}
|
||||
#endif
|
||||
// always create widgets in Twips, not pixels
|
||||
|
@ -6337,9 +6337,7 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsEventStatus* aStatus)
|
||||
if (aEvent->message == NS_KEY_UP) {
|
||||
// ESC key released while in DOM full-screen mode.
|
||||
// Exit full-screen mode.
|
||||
NS_DispatchToCurrentThread(
|
||||
NS_NewRunnableMethod(root,
|
||||
&nsIDocument::CancelFullScreen));
|
||||
nsIDocument::ExitFullScreen(true);
|
||||
}
|
||||
} else if (IsFullScreenAndRestrictedKeyEvent(mCurrentEventContent, aEvent)) {
|
||||
// Restricted key press while in DOM full-screen mode. Dispatch
|
||||
|
Loading…
Reference in New Issue
Block a user