Bug 545812 - DOM/content changes required for DOM full-screen API. r=jst

This commit is contained in:
Chris Pearce 2011-09-05 08:39:05 +12:00
parent 6a38c7561a
commit 7c1b965126
11 changed files with 305 additions and 7 deletions

View File

@ -1700,6 +1700,11 @@ public:
*/
static PRBool IsFocusedContent(const nsIContent *aContent);
/**
* Returns PR_TRUE if the DOM full-screen API is enabled.
*/
static PRBool IsFullScreenApiEnabled();
static void GetShiftText(nsAString& text);
static void GetControlText(nsAString& text);
static void GetMetaText(nsAString& text);
@ -1864,6 +1869,7 @@ private:
static PRBool sIsHandlingKeyBoardEvent;
static PRBool sAllowXULXBL_for_file;
static PRBool sIsFullScreenApiEnabled;
static nsHtml5Parser* sHTMLFragmentParser;
static nsIParser* sXMLFragmentParser;

View File

@ -127,8 +127,8 @@ class Element;
#define NS_IDOCUMENT_IID \
{ 0x455e4d79, 0x756b, 0x4f73, \
{ 0x95, 0xea, 0x3f, 0xf6, 0x0c, 0x6a, 0x8c, 0xa6 } }
{ 0x15d92ce2, 0x472a, 0x4ea7, \
{ 0xaf, 0x29, 0x47, 0x7b, 0xac, 0x98, 0xa0, 0x43 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -742,6 +742,37 @@ public:
virtual void AddToNameTable(Element* aElement, nsIAtom* aName) = 0;
virtual void RemoveFromNameTable(Element* aElement, nsIAtom* aName) = 0;
/**
* Resets the current full-screen element to nsnull.
*/
virtual void ResetFullScreenElement() = 0;
/**
* Returns the element which either is the full-screen element, or
* contains the full-screen element if a child of this document contains
* the fullscreen element.
*/
virtual Element* GetFullScreenElement() = 0;
/**
* Requests that the document make aElement the full-screen element,
* and move into full-screen mode.
*/
virtual void RequestFullScreen(Element* aElement) = 0;
/**
* Updates the full-screen status on this document, setting the full-screen
* mode to aIsFullScreen. This doesn't affect the window's full-screen mode,
* this updates the document's internal state which determines whether the
* document reports as being in full-screen mode.
*/
virtual void UpdateFullScreenStatus(PRBool aIsFullScreen) = 0;
/**
* Returns PR_TRUE if this document is in full-screen mode.
*/
virtual PRBool IsFullScreenDoc() = 0;
//----------------------------------------------------------------------
// Document notification API's

View File

@ -261,6 +261,7 @@ nsString* nsContentUtils::sAltText = nsnull;
nsString* nsContentUtils::sModifierSeparator = nsnull;
PRBool nsContentUtils::sInitialized = PR_FALSE;
PRBool nsContentUtils::sIsFullScreenApiEnabled = PR_FALSE;
nsHtml5Parser* nsContentUtils::sHTMLFragmentParser = nsnull;
nsIParser* nsContentUtils::sXMLFragmentParser = nsnull;
@ -384,6 +385,9 @@ nsContentUtils::Init()
Preferences::AddBoolVarCache(&sAllowXULXBL_for_file,
"dom.allow_XUL_XBL_for_file");
Preferences::AddBoolVarCache(&sIsFullScreenApiEnabled,
"full-screen-api.enabled");
sInitialized = PR_TRUE;
return NS_OK;
@ -5696,3 +5700,9 @@ nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
return res == JS_FALSE || rval != JSVAL_NULL;
}
PRBool
nsContentUtils::IsFullScreenApiEnabled()
{
return sIsFullScreenApiEnabled;
}

View File

@ -1544,6 +1544,7 @@ nsDOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
nsDocument::nsDocument(const char* aContentType)
: nsIDocument()
, mAnimatingImages(PR_TRUE)
, mIsFullScreen(PR_FALSE)
{
SetContentTypeInternal(nsDependentCString(aContentType));
@ -1871,6 +1872,7 @@ 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,6 +1929,7 @@ 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;
@ -8459,6 +8462,173 @@ nsIDocument::SizeOf() const
return size;
}
// Returns the root document in a document hierarchy.
static nsIDocument*
GetRootDocument(nsIDocument* aDoc)
{
if (!aDoc) {
return nsnull;
}
nsCOMPtr<nsIPresShell> shell = aDoc->GetShell();
if (!shell) {
return nsnull;
}
nsPresContext* ctx = shell->GetPresContext();
if (!ctx) {
return nsnull;
}
nsRootPresContext* rpc = ctx->GetRootPresContext();
if (!rpc) {
return nsnull;
}
return rpc->Document();
}
void
nsDocument::UpdateFullScreenStatus(PRBool aIsFullScreen)
{
mIsFullScreen = aIsFullScreen;
if (!mIsFullScreen) {
// Full-screen is being turned off. Reset the full-screen element, to
// save us from having to traverse the document hierarchy again in
// MozCancelFullScreen().
ResetFullScreenElement();
}
}
static PRBool
UpdateFullScreenStatus(nsIDocument* aDocument, void* aData)
{
aDocument->UpdateFullScreenStatus(*static_cast<PRBool*>(aData));
aDocument->EnumerateSubDocuments(UpdateFullScreenStatus, aData);
return PR_TRUE;
}
static void
UpdateFullScreenStatusInDocTree(nsIDocument* aDoc, PRBool aIsFullScreen)
{
nsIDocument* root = GetRootDocument(aDoc);
if (root) {
UpdateFullScreenStatus(root, static_cast<void*>(&aIsFullScreen));
}
}
void
nsDocument::ResetFullScreenElement()
{
mFullScreenElement = nsnull;
}
static PRBool
ResetFullScreenElement(nsIDocument* aDocument, void* aData)
{
aDocument->ResetFullScreenElement();
aDocument->EnumerateSubDocuments(ResetFullScreenElement, aData);
return PR_TRUE;
}
static void
ResetFullScreenElementInDocTree(nsIDocument* aDoc)
{
nsIDocument* root = GetRootDocument(aDoc);
if (root) {
ResetFullScreenElement(root, nsnull);
}
}
NS_IMETHODIMP
nsDocument::MozCancelFullScreen()
{
if (!nsContentUtils::IsFullScreenApiEnabled() ||
!IsFullScreenDoc() ||
!GetWindow()) {
return NS_OK;
}
// Disable full-screen mode in all documents in this hierarchy.
UpdateFullScreenStatusInDocTree(this, PR_FALSE);
// Move the window out of full-screen mode.
GetWindow()->SetFullScreen(PR_FALSE);
return NS_OK;
}
PRBool
nsDocument::IsFullScreenDoc()
{
return nsContentUtils::IsFullScreenApiEnabled() && mIsFullScreen;
}
void
nsDocument::RequestFullScreen(Element* aElement)
{
if (!aElement || !nsContentUtils::IsFullScreenApiEnabled() || !GetWindow()) {
return;
}
// Reset the full-screen elements of every document in this document
// hierarchy.
ResetFullScreenElementInDocTree(this);
if (aElement->IsInDoc()) {
// Propagate up the document hierarchy, setting the full-screen element as
// the element's container in ancestor documents. Note we don't propagate
// down the document hierarchy, the full-screen element (or its container)
// is not visible there.
mFullScreenElement = aElement;
nsIDocument* child = this;
nsIDocument* parent;
while (parent = child->GetParentDocument()) {
nsIContent* content = parent->FindContentForSubDocument(child);
nsCOMPtr<Element> element(do_QueryInterface(content));
static_cast<nsDocument*>(parent)->mFullScreenElement = element;
child = parent;
}
}
// Set all documents in hierarchy to full-screen mode.
UpdateFullScreenStatusInDocTree(this, PR_TRUE);
// 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 browser.js to distinguish between browser and dom full-screen
// modes.
GetWindow()->SetFullScreen(PR_TRUE);
}
NS_IMETHODIMP
nsDocument::GetMozFullScreenElement(nsIDOMHTMLElement **aFullScreenElement)
{
NS_ENSURE_ARG_POINTER(aFullScreenElement);
if (!nsContentUtils::IsFullScreenApiEnabled() || !IsFullScreenDoc()) {
*aFullScreenElement = nsnull;
return NS_OK;
}
nsCOMPtr<nsIDOMHTMLElement> e(do_QueryInterface(GetFullScreenElement()));
NS_IF_ADDREF(*aFullScreenElement = e);
return NS_OK;
}
Element*
nsDocument::GetFullScreenElement()
{
if (!nsContentUtils::IsFullScreenApiEnabled() ||
(mFullScreenElement && !mFullScreenElement->IsInDoc())) {
return nsnull;
}
return mFullScreenElement;
}
NS_IMETHODIMP
nsDocument::GetMozFullScreen(PRBool *aFullScreen)
{
NS_ENSURE_ARG_POINTER(aFullScreen);
*aFullScreen = nsContentUtils::IsFullScreenApiEnabled() && IsFullScreenDoc();
return NS_OK;
}
PRInt64
nsDocument::SizeOf() const
{

View File

@ -941,6 +941,12 @@ public:
virtual Element* FindImageMap(const nsAString& aNormalizedMapName);
virtual void ResetFullScreenElement();
virtual Element* GetFullScreenElement();
virtual void RequestFullScreen(Element* aElement);
virtual void UpdateFullScreenStatus(PRBool aIsFullScreen);
virtual PRBool IsFullScreenDoc();
protected:
friend class nsNodeUtils;
@ -1078,6 +1084,9 @@ 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.
PRPackedBool mIsGoingAway:1;
// True if the document is being destroyed.
@ -1110,6 +1119,9 @@ protected:
// Whether we currently require our images to animate
PRPackedBool mAnimatingImages:1;
// Whether we are currently in full-screen mode, as per the DOM API.
PRPackedBool mIsFullScreen:1;
PRUint8 mXMLDeclarationBits;
PRUint8 mDefaultElementType;

View File

@ -3379,6 +3379,29 @@ nsGenericHTMLElement::Focus()
return fm ? fm->SetFocus(elem, 0) : NS_OK;
}
nsresult nsGenericHTMLElement::MozRequestFullScreen()
{
if (!nsContentUtils::IsFullScreenApiEnabled()) {
return NS_OK;
}
nsIDocument* doc = GetOwnerDoc();
NS_ENSURE_STATE(doc);
doc->RequestFullScreen(this);
#ifdef DEBUG
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(doc->GetWindow());
NS_ENSURE_STATE(window);
PRBool fullscreen;
window->GetFullScreen(&fullscreen);
NS_ASSERTION(fullscreen, "Windows should report fullscreen");
nsCOMPtr<nsIDOMDocument> domDocument(do_QueryInterface(doc));
domDocument->GetMozFullScreen(&fullscreen);
NS_ASSERTION(fullscreen, "Document should report fullscreen");
NS_ASSERTION(doc->IsFullScreenDoc(), "Should be in full screen state!");
#endif
return NS_OK;
}
nsresult nsGenericHTMLElement::Click()
{
if (HasFlag(NODE_HANDLING_CLICK))

View File

@ -139,6 +139,7 @@ public:
virtual nsresult InsertAdjacentHTML(const nsAString& aPosition,
const nsAString& aText);
nsresult ScrollIntoView(PRBool aTop, PRUint8 optional_argc);
nsresult MozRequestFullScreen();
// Declare Focus(), Blur(), GetTabIndex(), SetTabIndex(), GetHidden(),
// SetHidden(), GetSpellcheck(), SetSpellcheck(), and GetDraggable() such that
// classes that inherit interfaces with those methods properly override them.

View File

@ -4406,9 +4406,11 @@ nsGlobalWindow::SetFullScreen(PRBool aFullScreen)
PRBool rootWinFullScreen;
GetFullScreen(&rootWinFullScreen);
// Only chrome can change our fullScreen mode.
if (aFullScreen == rootWinFullScreen ||
!nsContentUtils::IsCallerTrustedForWrite()) {
// Only chrome can change our fullScreen mode, unless the DOM full-screen
// API is enabled.
if ((aFullScreen == rootWinFullScreen ||
!nsContentUtils::IsCallerTrustedForWrite()) &&
!nsContentUtils::IsFullScreenApiEnabled()) {
return NS_OK;
}
@ -4458,6 +4460,14 @@ nsGlobalWindow::SetFullScreen(PRBool 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();
}
return NS_OK;
}

View File

@ -63,7 +63,7 @@ interface nsIDOMCaretPosition;
* http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
*/
[scriptable, uuid(d19897dc-948a-42e7-8ac6-d8a0bd141b85)]
[scriptable, uuid(903493d3-72b6-4416-b930-fbfc17ef1d87)]
interface nsIDOMDocument : nsIDOMNode
{
readonly attribute nsIDOMDocumentType doctype;
@ -371,4 +371,28 @@ interface nsIDOMDocument : nsIDOMNode
in nsIDOMElement aImageElement);
nsIDOMCaretPosition caretPositionFromPoint(in float x, in float y);
/**
* Element which is currently the full-screen element as per the DOM
* full-screen api.
*
* @see <https://wiki.mozilla.org/index.php?title=Gecko:FullScreenAPI>
*/
readonly attribute nsIDOMHTMLElement mozFullScreenElement;
/**
* Causes the document to leave DOM full-screen mode, if it's in
* full-screen mode, as per the DOM full-screen api.
*
* @see <https://wiki.mozilla.org/index.php?title=Gecko:FullScreenAPI>
*/
void mozCancelFullScreen();
/**
* Denotes whether this document is in DOM full-screen mode, as per the DOM
* full-screen api.
*
* @see <https://wiki.mozilla.org/index.php?title=Gecko:FullScreenAPI>
*/
readonly attribute boolean mozFullScreen;
};

View File

@ -41,7 +41,7 @@
interface nsIDOMDOMStringMap;
interface nsIDOMHTMLMenuElement;
[scriptable, uuid(0c3b4b63-30b2-4c93-906d-f983ee9af584)]
[scriptable, uuid(38305156-007a-4b68-8592-b1c3625c6f6c)]
interface nsIDOMNSHTMLElement : nsISupports
{
readonly attribute long offsetTop;
@ -76,4 +76,12 @@ interface nsIDOMNSHTMLElement : nsISupports
attribute boolean spellcheck;
readonly attribute nsIDOMDOMStringMap dataset;
/**
* Requests that this element be made the full-screen element, as per the DOM
* full-screen api.
*
* @see <https://wiki.mozilla.org/index.php?title=Gecko:FullScreenAPI>
*/
void mozRequestFullScreen();
};

View File

@ -3346,6 +3346,9 @@ pref("alerts.slideIncrement", 1);
pref("alerts.slideIncrementTime", 10);
pref("alerts.totalOpenTime", 4000);
pref("alerts.disableSlidingEffect", false);
// DOM full-screen API.
pref("full-screen-api.enabled", false);
//3D Transforms
pref("layout.3d-transforms.enabled", false);