This commit is contained in:
Robert Sayre 2008-12-18 15:17:19 -05:00
Родитель 3886ed2912 c5ae2a1961
Коммит 9e73b4eefc
760 изменённых файлов: 5762 добавлений и 100570 удалений

Просмотреть файл

@ -103,7 +103,14 @@ interface nsIAccessible : nsISupports
readonly attribute long indexInParent; readonly attribute long indexInParent;
/** /**
* Accessible name -- the main text equivalent for this node * Accessible name -- the main text equivalent for this node. The name is
* specified by ARIA or by native markup. Example of ARIA markup is
* aria-labelledby attribute placed on element of this accessible. Example
* of native markup is HTML label linked with HTML element of this accessible.
*
* Value can be string or null. A null value indicates that AT may attempt to
* compute the name. Any string value, including the empty string, should be
* considered author-intentional, and respected.
*/ */
attribute AString name; attribute AString name;

Просмотреть файл

@ -448,29 +448,16 @@ nsAccUtils::GetTextAccessibleFromSelection(nsISelection *aSelection,
// Get accessible from selection's focus DOM point (the DOM point where // Get accessible from selection's focus DOM point (the DOM point where
// selection is ended). // selection is ended).
nsCOMPtr<nsIDOMNode> resultNode; nsCOMPtr<nsIDOMNode> focusNode;
aSelection->GetFocusNode(getter_AddRefs(resultNode)); aSelection->GetFocusNode(getter_AddRefs(focusNode));
if (!resultNode) if (!focusNode)
return nsnull; return nsnull;
// Get DOM node that focus DOM point points to. PRInt32 focusOffset = 0;
nsCOMPtr<nsIContent> content(do_QueryInterface(resultNode)); aSelection->GetFocusOffset(&focusOffset);
if (content && content->IsNodeOfType(nsINode::eELEMENT)) {
PRInt32 offset = 0;
aSelection->GetFocusOffset(&offset);
PRInt32 childCount = static_cast<PRInt32>(content->GetChildCount()); nsCOMPtr<nsIDOMNode> resultNode =
NS_ASSERTION(offset >= 0 && offset <= childCount, nsCoreUtils::GetDOMNodeFromDOMPoint(focusNode, focusOffset);
"Wrong focus offset in selection!");
// The offset can be after last child of container node that means DOM point
// is placed immediately after the last child. In this case use focusNode
// as result node.
if (offset != childCount) {
nsCOMPtr<nsIContent> child = content->GetChildAt(offset);
resultNode = do_QueryInterface(child);
}
}
nsIAccessibilityService *accService = nsAccessNode::GetAccService(); nsIAccessibilityService *accService = nsAccessNode::GetAccService();

Просмотреть файл

@ -308,7 +308,7 @@ nsAccessible::GetName(nsAString& aName)
if (content->GetAttr(kNameSpaceID_None, tooltipAttr, name)) { if (content->GetAttr(kNameSpaceID_None, tooltipAttr, name)) {
name.CompressWhitespace(); name.CompressWhitespace();
aName = name; aName = name;
} else { } else if (rv != NS_OK_EMPTY_NAME) {
aName.SetIsVoid(PR_TRUE); aName.SetIsVoid(PR_TRUE);
} }

Просмотреть файл

@ -66,9 +66,14 @@ class nsIDOMNode;
class nsIAtom; class nsIAtom;
class nsIView; class nsIView;
// see nsAccessible::GetAttrValue
#define NS_OK_NO_ARIA_VALUE \ #define NS_OK_NO_ARIA_VALUE \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x21) NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x21)
// see nsAccessible::GetNameInternal
#define NS_OK_EMPTY_NAME \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x23)
// Saves a data member -- if child count equals this value we haven't // Saves a data member -- if child count equals this value we haven't
// cached children or child count yet // cached children or child count yet
enum { eChildCountUninitialized = -1 }; enum { eChildCountUninitialized = -1 };
@ -135,7 +140,13 @@ public:
/** /**
* Returns the accessible name provided by native markup. It doesn't take * Returns the accessible name provided by native markup. It doesn't take
* into account ARIA stuffs used to specify the name. * into account ARIA markup used to specify the name.
*
* @param aName [out] the accessible name
*
* @return NS_OK_EMPTY_NAME points empty name was specified by native markup
* explicitly (see nsIAccessible::name attribute for
* details)
*/ */
virtual nsresult GetNameInternal(nsAString& aName); virtual nsresult GetNameInternal(nsAString& aName);

Просмотреть файл

@ -192,6 +192,31 @@ nsCoreUtils::GetDOMElementFor(nsIDOMNode *aNode)
return element; return element;
} }
already_AddRefed<nsIDOMNode>
nsCoreUtils::GetDOMNodeFromDOMPoint(nsIDOMNode *aNode, PRUint32 aOffset)
{
nsIDOMNode *resultNode = nsnull;
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
if (content && content->IsNodeOfType(nsINode::eELEMENT)) {
PRInt32 childCount = static_cast<PRInt32>(content->GetChildCount());
NS_ASSERTION(aOffset >= 0 && aOffset <= childCount,
"Wrong offset of the DOM point!");
// The offset can be after last child of container node that means DOM point
// is placed immediately after the last child. In this case use the DOM node
// from the given DOM point is used as result node.
if (aOffset != childCount) {
CallQueryInterface(content->GetChildAt(aOffset), &resultNode);
return resultNode;
}
}
NS_IF_ADDREF(resultNode = aNode);
return resultNode;
}
nsIContent* nsIContent*
nsCoreUtils::GetRoleContent(nsIDOMNode *aDOMNode) nsCoreUtils::GetRoleContent(nsIDOMNode *aDOMNode)
{ {

Просмотреть файл

@ -86,6 +86,11 @@ public:
*/ */
static already_AddRefed<nsIDOMElement> GetDOMElementFor(nsIDOMNode *aNode); static already_AddRefed<nsIDOMElement> GetDOMElementFor(nsIDOMNode *aNode);
/**
* Return DOM node for the given DOM point.
*/
static already_AddRefed<nsIDOMNode> GetDOMNodeFromDOMPoint(nsIDOMNode *aNode,
PRUint32 aOffset);
/** /**
* Return the nsIContent* to check for ARIA attributes on -- this may not * Return the nsIContent* to check for ARIA attributes on -- this may not
* always be the DOM node for the accessible. Specifically, for doc * always be the DOM node for the accessible. Specifically, for doc

Просмотреть файл

@ -127,10 +127,6 @@ nsHTMLImageAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
nsresult nsresult
nsHTMLImageAccessible::GetNameInternal(nsAString& aName) nsHTMLImageAccessible::GetNameInternal(nsAString& aName)
{ {
// No alt attribute means AT can repair if there is no accessible name
// alt="" with no title or aria-labelledby means image is presentational and
// AT should leave accessible name empty
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode)); nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
PRBool hasAltAttrib = PRBool hasAltAttrib =
content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::alt, aName); content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::alt, aName);
@ -140,10 +136,12 @@ nsHTMLImageAccessible::GetNameInternal(nsAString& aName)
nsresult rv = nsAccessible::GetNameInternal(aName); nsresult rv = nsAccessible::GetNameInternal(aName);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (aName.IsVoid() && hasAltAttrib) { if (aName.IsEmpty() && hasAltAttrib) {
// No accessible name but empty alt attribute is present. This means a name // No accessible name but empty 'alt' attribute is present. If further name
// was provided by author and AT repair of the name isn't allowed. // computation algorithm doesn't provide non empty name then it means
aName.Truncate(); // an empty 'alt' attribute was used to indicate a decorative image (see
// nsIAccessible::name attribute for details).
return NS_OK_EMPTY_NAME;
} }
return NS_OK; return NS_OK;

Просмотреть файл

@ -1632,23 +1632,46 @@ NS_IMETHODIMP nsHyperTextAccessible::SetCaretOffset(PRInt32 aCaretOffset)
/* /*
* Gets the offset position of the caret (cursor). * Gets the offset position of the caret (cursor).
*/ */
NS_IMETHODIMP nsHyperTextAccessible::GetCaretOffset(PRInt32 *aCaretOffset) NS_IMETHODIMP
nsHyperTextAccessible::GetCaretOffset(PRInt32 *aCaretOffset)
{ {
*aCaretOffset = 0; *aCaretOffset = -1;
// No caret if the focused node is not inside this DOM node and this DOM node
// is not inside of focused node.
PRBool isInsideOfFocusedNode =
nsCoreUtils::IsAncestorOf(gLastFocusedNode, mDOMNode);
if (!isInsideOfFocusedNode && mDOMNode != gLastFocusedNode &&
!nsCoreUtils::IsAncestorOf(mDOMNode, gLastFocusedNode))
return NS_OK;
// Turn the focus node and offset of the selection into caret hypretext
// offset.
nsCOMPtr<nsISelection> domSel; nsCOMPtr<nsISelection> domSel;
nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL, nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
nsnull, getter_AddRefs(domSel)); nsnull, getter_AddRefs(domSel));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> caretNode; nsCOMPtr<nsIDOMNode> focusNode;
rv = domSel->GetFocusNode(getter_AddRefs(caretNode)); rv = domSel->GetFocusNode(getter_AddRefs(focusNode));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
PRInt32 caretOffset; PRInt32 focusOffset;
domSel->GetFocusOffset(&caretOffset); rv = domSel->GetFocusOffset(&focusOffset);
NS_ENSURE_SUCCESS(rv, rv);
return DOMPointToHypertextOffset(caretNode, caretOffset, aCaretOffset); // No caret if this DOM node is inside of focused node but the selection's
// focus point is not inside of this DOM node.
if (isInsideOfFocusedNode) {
nsCOMPtr<nsIDOMNode> resultNode =
nsCoreUtils::GetDOMNodeFromDOMPoint(focusNode, focusOffset);
if (resultNode != mDOMNode &&
!nsCoreUtils::IsAncestorOf(mDOMNode, resultNode))
return NS_OK;
}
return DOMPointToHypertextOffset(focusNode, focusOffset, aCaretOffset);
} }
PRInt32 nsHyperTextAccessible::GetCaretLineNumber() PRInt32 nsHyperTextAccessible::GetCaretLineNumber()

Просмотреть файл

@ -145,7 +145,7 @@ __try {
return GetHRESULT(rv); return GetHRESULT(rv);
*aOffset = offset; *aOffset = offset;
return S_OK; return offset != -1 ? S_OK : S_FALSE;
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { } } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return E_FAIL; return E_FAIL;

Просмотреть файл

@ -6,6 +6,8 @@ const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
const nsIAccessibleEvent = Components.interfaces.nsIAccessibleEvent; const nsIAccessibleEvent = Components.interfaces.nsIAccessibleEvent;
const nsIAccessibleStateChangeEvent = const nsIAccessibleStateChangeEvent =
Components.interfaces.nsIAccessibleStateChangeEvent; Components.interfaces.nsIAccessibleStateChangeEvent;
const nsIAccessibleCaretMoveEvent =
Components.interfaces.nsIAccessibleCaretMoveEvent;
const nsIAccessibleStates = Components.interfaces.nsIAccessibleStates; const nsIAccessibleStates = Components.interfaces.nsIAccessibleStates;
const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole; const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole;
@ -73,7 +75,61 @@ const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE;
var gAccRetrieval = null; var gAccRetrieval = null;
/** /**
* Return accessible for the given ID attribute or DOM element. * Invokes the given function when document is loaded. Preferable to mochitests
* 'addLoadEvent' function -- additionally ensures state of the document
* accessible is not busy.
*
* @param aFunc the function to invoke
*/
function addA11yLoadEvent(aFunc)
{
function waitForDocLoad()
{
window.setTimeout(
function()
{
var accDoc = getAccessible(document);
var state = {};
accDoc.getState(state, {});
if (state.value & nsIAccessibleStates.STATE_BUSY)
return waitForDocLoad();
aFunc.call();
},
0
);
}
addLoadEvent(waitForDocLoad);
}
////////////////////////////////////////////////////////////////////////////////
// Get DOM node/accesible helpers
/**
* Return the DOM node.
*/
function getNode(aNodeOrID)
{
if (!aNodeOrID)
return null;
var node = aNodeOrID;
if (!(aNodeOrID instanceof nsIDOMNode)) {
node = document.getElementById(aNodeOrID);
if (!node) {
ok(false, "Can't get DOM element for " + aNodeOrID);
return null;
}
}
return node;
}
/**
* Return accessible for the given ID attribute or DOM element or accessible.
* *
* @param aAccOrElmOrID [in] DOM element or ID attribute to get an accessible * @param aAccOrElmOrID [in] DOM element or ID attribute to get an accessible
* for or an accessible to query additional interfaces. * for or an accessible to query additional interfaces.
@ -210,6 +266,7 @@ function unregisterA11yEventListener(aEventType, aEventHandler)
* invoke: function(){}, // generates event for the DOM node * invoke: function(){}, // generates event for the DOM node
* check: function(aEvent){}, // checks event for correctness * check: function(aEvent){}, // checks event for correctness
* DOMNode getter() {} // DOM node event is generated for * DOMNode getter() {} // DOM node event is generated for
* getID: function(){} // returns invoker ID
* }; * };
* *
* @param aEventType the given event type * @param aEventType the given event type
@ -235,8 +292,11 @@ function eventQueue(aEventType)
if (aQueue.mIndex == aQueue.mInvokers.length - 1) { if (aQueue.mIndex == aQueue.mInvokers.length - 1) {
unregisterA11yEventListener(aQueue.mEventType, aQueue.mEventHandler); unregisterA11yEventListener(aQueue.mEventType, aQueue.mEventHandler);
for (var idx = 0; idx < aQueue.mInvokers.length; idx++) for (var idx = 0; idx < aQueue.mInvokers.length; idx++) {
ok(aQueue.mInvokers[idx].wasCaught, "test " + idx + " failed."); var invoker = aQueue.mInvokers[idx];
ok(invoker.wasCaught,
"test with ID = '" + invoker.getID() + "' failed.");
}
SimpleTest.finish(); SimpleTest.finish();
return; return;
@ -246,7 +306,7 @@ function eventQueue(aEventType)
aQueue.invoke(); aQueue.invoke();
}, },
100, this 200, this
); );
} }
@ -309,6 +369,12 @@ function eventHandlerForEventQueue(aQueue)
this.handleEvent = function eventHandlerForEventQueue_handleEvent(aEvent) this.handleEvent = function eventHandlerForEventQueue_handleEvent(aEvent)
{ {
var invoker = this.mQueue.getInvoker(); var invoker = this.mQueue.getInvoker();
if (!invoker) // skip events before test was started
return;
if ("debugCheck" in invoker)
invoker.debugCheck(aEvent);
if (aEvent.DOMNode == invoker.DOMNode) { if (aEvent.DOMNode == invoker.DOMNode) {
invoker.check(aEvent); invoker.check(aEvent);
invoker.wasCaught = true; invoker.wasCaught = true;

Просмотреть файл

@ -17,114 +17,183 @@
src="chrome://mochikit/content/a11y/accessible/common.js"></script> src="chrome://mochikit/content/a11y/accessible/common.js"></script>
<script type="application/javascript"> <script type="application/javascript">
function synthMouseTest(aNode) /**
* Invoker base class.
*/
function synthAction(aNodeOrID, aCaretOffset)
{ {
this.node = aNode; this.DOMNode = getNode(aNodeOrID);
this.testFunc = function testFunc()
this.check = function synthAction_check(aEvent)
{ {
synthesizeMouse(this.node, 1, 1, {}); is(aEvent.QueryInterface(nsIAccessibleCaretMoveEvent).caretOffset,
this.caretOffset,
"Wrong caret offset for " + aNodeOrID);
}
this.getID = function synthAction_getID() { return aNodeOrID + " action"; }
this.caretOffset = aCaretOffset;
}
/**
* Click invoker.
*/
function synthClick(aNodeOrID, aCaretOffset,
aExtraNodeOrID, aExtraCaretOffset)
{
this.__proto__ = new synthAction(aNodeOrID, aCaretOffset);
this.extraNode = getNode(aExtraNodeOrID);
this.extraCaretOffset = aExtraCaretOffset;
this.invoke = function synthClick_invoke()
{
// Scroll the node into view, otherwise synth click may fail.
this.DOMNode.scrollIntoView(true);
synthesizeMouse(this.DOMNode, 1, 1, {});
}
this.check = function synthFocus_check(aEvent)
{
this.__proto__.check(aEvent);
if (this.extraNode) {
var acc = getAccessible(this.extraNode, [nsIAccessibleText]);
is(acc.caretOffset, this.extraCaretOffset,
"Wrong caret offset for " + aExtraNodeOrID);
} }
} }
function synthKeyTest(aNode, aKey) this.getID = function synthFocus_getID() { return aNodeOrID + " click"; }
}
/**
* Key press invokers.
*/
function synthKey(aNodeOrID, aCaretOffset, aKey, aArgs)
{ {
this.node = aNode; this.__proto__ = new synthAction(aNodeOrID, aCaretOffset);
this.testFunc = function testFunc()
this.invoke = function synthKey_invoke()
{ {
synthesizeKey(aKey, {}); synthesizeKey(this.mKey, this.mArgs);
}
this.mKey = aKey;
this.mArgs = aArgs ? aArgs : {};
}
function synthTabTest(aNodeOrID, aCaretOffset, aBackTab)
{
this.__proto__ = new synthKey(aNodeOrID, aCaretOffset,
"VK_TAB", {shiftKey: aBackTab});
this.getID = function synthTabTest_getID() { return aNodeOrID + " tab"; }
}
function synthDownKey(aNodeOrID, aCaretOffset)
{
this.__proto__ = new synthKey(aNodeOrID, aCaretOffset, "VK_DOWN");
this.getID = function synthDownKey_getID()
{
return aNodeOrID + " key down";
} }
} }
function synthTabTest(aNode, aBackTab) function synthRightKey(aNodeOrID, aCaretOffset)
{ {
this.node = aNode; this.__proto__ = new synthKey(aNodeOrID, aCaretOffset, "VK_RIGHT");
this.testFunc = function testFunc()
this.getID = function synthRightKey_getID()
{ {
synthesizeKey("VK_TAB", {shiftKey: aBackTab}); return aNodeOrID + " key right";
} }
} }
function synthFocusTest(aNode) /**
* Focus invoker.
*/
function synthFocus(aNodeOrID, aCaretOffset)
{ {
// bug 460417 this.__proto__ = new synthAction(aNodeOrID, aCaretOffset);
this.node = aNode;
this.testFunc = function testFunc() this.invoke = function synthFocus_invoke()
{ {
this.node.focus(); this.DOMNode.focus();
}
this.getID = function synthFocus_getID() { return aNodeOrID + " focus"; }
}
/**
* Select all invoker.
*/
function synthSelectAll(aNodeOrID, aCaretOffset)
{
this.__proto__ = new synthAction(aNodeOrID, aCaretOffset);
this.invoke = function synthSelectAll_invoke()
{
if (this.DOMNode instanceof Components.interfaces.nsIDOMHTMLInputElement)
this.DOMNode.select();
else
window.getSelection().selectAllChildren(this.DOMNode);
}
this.getID = function synthSelectAll_getID()
{
return aNodeOrID + " selectall";
} }
} }
function synthSelectAllTest(aNode) /**
* Do tests.
*/
var gQueue = null;
function testCaretOffset(aAccOrElmOrID, aCaretOffset)
{ {
// bug 460417 var acc = getAccessible(aAccOrElmOrID, [nsIAccessibleText]);
this.node = aNode; is(acc.caretOffset, aCaretOffset,
this.testFunc = function testFunc() "Wrong caret offset for " + aAccOrElmOrID);
{
this.node.select();
}
}
var gTestsArray = [];
var gTestIdx = -1;
var gCaretMoveHandler =
{
handleEvent: function handleEvent(aEvent)
{
if (aEvent.DOMNode == gTestsArray[gTestIdx].node)
gTestsArray[gTestIdx].wasCaught = true;
}
};
function doTest()
{
window.setTimeout(
function()
{
if (gTestIdx == gTestsArray.length - 1) {
unregisterA11yEventListener(nsIAccessibleEvent.EVENT_TEXT_CARET_MOVED,
gCaretMoveHandler);
for (var idx = 0; idx < gTestsArray.length; idx++)
ok(gTestsArray[idx].wasCaught, "test " + idx + " failed");
SimpleTest.finish();
return;
}
gTestsArray[++gTestIdx].testFunc();
doTest();
},
100
);
} }
function doTests() function doTests()
{ {
var textbox = document.getElementById("textbox"); // test no focused accessibles
gTestsArray.push(new synthFocusTest(textbox)); testCaretOffset("textbox", -1);
gTestsArray.push(new synthSelectAllTest(textbox)); testCaretOffset("textarea", -1);
gTestsArray.push(new synthMouseTest(textbox)); testCaretOffset("p", -1);
gTestsArray.push(new synthKeyTest(textbox, "VK_RIGHT"));
var textarea = document.getElementById("textarea"); // test caret move events and caret offsets
gTestsArray.push(new synthMouseTest(textarea)); gQueue = new eventQueue(nsIAccessibleEvent.EVENT_TEXT_CARET_MOVED);
gTestsArray.push(new synthKeyTest(textarea, "VK_RIGHT"));
gTestsArray.push(new synthKeyTest(textarea, "VK_DOWN"));
var p = document.getElementById("p"); var id = "textbox";
gTestsArray.push(new synthMouseTest(p)); gQueue.push(new synthFocus(id, 5));
gTestsArray.push(new synthKeyTest(p, "VK_RIGHT")); gQueue.push(new synthSelectAll(id, 5));
gTestsArray.push(new synthKeyTest(p, "VK_DOWN")); gQueue.push(new synthClick(id, 0));
gQueue.push(new synthRightKey(id, 1));
gTestsArray.push(new synthTabTest(textarea, true)); id = "textarea";
gTestsArray.push(new synthTabTest(p)); gQueue.push(new synthClick(id, 0));
gQueue.push(new synthRightKey(id, 1));
gQueue.push(new synthDownKey(id, 12));
registerA11yEventListener(nsIAccessibleEvent.EVENT_TEXT_CARET_MOVED, id = "p";
gCaretMoveHandler); gQueue.push(new synthClick(id, 0));
gQueue.push(new synthRightKey(id, 1));
gQueue.push(new synthDownKey(id, 6));
doTest(); gQueue.push(new synthClick("p1_in_div", 0, "p2_in_div", -1));
gQueue.push(new synthTabTest("p", 0, true));
gQueue.push(new synthTabTest("textarea", 12, true));
gQueue.push(new synthTabTest("p", 0, false));
gQueue.invoke(); // Will call SimpleTest.finish();
} }
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
@ -147,6 +216,7 @@
<input id="textbox" value="hello"/> <input id="textbox" value="hello"/>
<textarea id="textarea">text<br>text</textarea> <textarea id="textarea">text<br>text</textarea>
<p id="p" contentEditable="true"><span>text</span><br/>text</p> <p id="p" contentEditable="true"><span>text</span><br/>text</p>
<div id="div" contentEditable="true"><p id="p1_in_div">text</p><p id="p2_in_div">text</p></div>
</body> </body>
</html> </html>

Просмотреть файл

@ -147,10 +147,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429659
testThis("linkedImageWithTitle", "Link to MoFo", "moz.png", 93, 42); testThis("linkedImageWithTitle", "Link to MoFo", "moz.png", 93, 42);
// Test simple image with empty alt attribute // Test simple image with empty alt attribute
// testThis("nonLinkedImageEmptyAlt", "", "moz.png", 89, 38); testThis("nonLinkedImageEmptyAlt", "", "moz.png", 89, 38);
// Test linked image with empty alt attribute // Test linked image with empty alt attribute
// testThis("linkedImageEmptyAlt", "", "moz.png", 93, 42); testThis("linkedImageEmptyAlt", "", "moz.png", 93, 42);
// Test simple image with empty alt attribute and title // Test simple image with empty alt attribute and title
testThis("nonLinkedImageEmptyAltAndTitle", "MozillaFoundation", "moz.png", 89, 38); testThis("nonLinkedImageEmptyAltAndTitle", "MozillaFoundation", "moz.png", 89, 38);

Просмотреть файл

@ -20,7 +20,7 @@
<script type="application/javascript"> <script type="application/javascript">
<![CDATA[ <![CDATA[
function openHideCombobox(aComboboxNode, aIsOpen) function openHideCombobox(aComboboxNodeOrID, aIsOpen)
{ {
this.invoke = function invoke() this.invoke = function invoke()
{ {
@ -30,13 +30,21 @@
{ {
aEvent.QueryInterface(nsIAccessibleStateChangeEvent); aEvent.QueryInterface(nsIAccessibleStateChangeEvent);
var id = this.getID();
is(aEvent.state, nsIAccessibleStates.STATE_EXPANDED, is(aEvent.state, nsIAccessibleStates.STATE_EXPANDED,
"Wrong state change event is handled."); "Wrong state change event is handled in test '" + id + "'.");
is(aEvent.isEnabled(), this.mIsOpen, is(aEvent.isEnabled(), this.mIsOpen,
"Wrong value of state expanded."); "Wrong value of state expanded in test '" + id + "'.");
}
this.getID = function getID()
{
if (this.mIsOpen)
return this.DOMNodeOrID + " open combobox";
return this.DOMNodeOrID + " close combobox";
} }
this.DOMNode = aComboboxNode; this.DOMNodeOrID = aComboboxNodeOrID;
this.DOMNode = getNode(aComboboxNodeOrID);
this.mIsOpen = aIsOpen; this.mIsOpen = aIsOpen;
} }
@ -45,9 +53,9 @@
{ {
gQueue = new eventQueue(nsIAccessibleEvent.EVENT_STATE_CHANGE); gQueue = new eventQueue(nsIAccessibleEvent.EVENT_STATE_CHANGE);
var menulist = document.getElementById("menulist"); var ID = "menulist";
gQueue.push(new openHideCombobox(menulist, true)); gQueue.push(new openHideCombobox(ID, true));
gQueue.push(new openHideCombobox(menulist, false)); gQueue.push(new openHideCombobox(ID, false));
// XXX: searchbar doesn't fire state change events because accessible // XXX: searchbar doesn't fire state change events because accessible
// parent of combobox_list accessible is pushbutton accessible. // parent of combobox_list accessible is pushbutton accessible.

Просмотреть файл

@ -21,37 +21,24 @@
var gComputedStyle = null; var gComputedStyle = null;
var gObserverService = null; var gTextAttrChangedEventHandler = {
var gA11yEventObserver = null; handleEvent: function gTextAttrChangedEventHandler_handleEvent(aEvent)
{
this.eventNumber++;
},
eventNumber: 0
};
function testSpellTextAttrs() function testSpellTextAttrs()
{ {
gA11yEventObserver = { registerA11yEventListener(nsIAccessibleEvent.EVENT_TEXT_ATTRIBUTE_CHANGED,
observe: function observe(aSubject, aTopic, aData) gTextAttrChangedEventHandler);
{
if (aTopic != "accessible-event")
return;
var event = aSubject.QueryInterface(nsIAccessibleEvent);
if (event.eventType == nsIAccessibleEvent.EVENT_TEXT_ATTRIBUTE_CHANGED)
this.mTextAttrChangedEventCounter++;
},
mTextAttrChangedEventCounter: 0
};
// Add accessibility event listeners
var gObserverService = Components.classes["@mozilla.org/observer-service;1"].
getService(nsIObserverService);
gObserverService.addObserver(gA11yEventObserver, "accessible-event",
false);
ID = "area8"; ID = "area8";
var node = document.getElementById(ID); var node = document.getElementById(ID);
node.setAttribute("value", "valid text inalid tixt");
node.focus(); node.focus();
var editor = node.QueryInterface(nsIDOMNSEditableElement).editor; var editor = node.QueryInterface(nsIDOMNSEditableElement).editor;
@ -82,16 +69,11 @@
testTextAttrs(ID, 17, attrs, 17, 18); testTextAttrs(ID, 17, attrs, 17, 18);
testTextAttrs(ID, 18, misspelledAttrs, 18, 22); testTextAttrs(ID, 18, misspelledAttrs, 18, 22);
if (navigator.platform == "Win32") is(gTextAttrChangedEventHandler.eventNumber, 2,
is(gA11yEventObserver.mTextAttrChangedEventCounter, 2,
"Wrong count of 'text attribute changed' events for " + ID);
else
todo(gA11yEventObserver.mTextAttrChangedEventCounter, 2,
"Wrong count of 'text attribute changed' events for " + ID); "Wrong count of 'text attribute changed' events for " + ID);
// Remove a11y events listener unregisterA11yEventListener(nsIAccessibleEvent.EVENT_TEXT_ATTRIBUTE_CHANGED,
gObserverService.removeObserver(gA11yEventObserver, gTextAttrChangedEventHandler);
"accessible-event");
SimpleTest.finish(); SimpleTest.finish();
}, 0); }, 0);
@ -383,7 +365,7 @@
} }
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
addLoadEvent(doTest); addA11yLoadEvent(doTest);
</script> </script>
</head> </head>
<body> <body>
@ -439,7 +421,7 @@
</span> </span>
</p> </p>
<input id="area8" value="valid text inalid tixt"/> <input id="area8"/>
<p id="output"/> <p id="output"/>
</body> </body>

Просмотреть файл

@ -22,6 +22,7 @@
# Annie Sullivan <annie.sullivan@gmail.com> # Annie Sullivan <annie.sullivan@gmail.com>
# Joe Hughes <joe@retrovirus.com> # Joe Hughes <joe@retrovirus.com>
# Asaf Romano <mano@mozilla.com> # Asaf Romano <mano@mozilla.com>
# Ehsan Akhgari <ehsan.akhgari@gmail.com>
# #
# Alternatively, the contents of this file may be used under the terms of # Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or # either the GNU General Public License Version 2 or later (the "GPL"), or
@ -166,6 +167,9 @@ var StarUI = {
_doShowEditBookmarkPanel: _doShowEditBookmarkPanel:
function SU__doShowEditBookmarkPanel(aItemId, aAnchorElement, aPosition) { function SU__doShowEditBookmarkPanel(aItemId, aAnchorElement, aPosition) {
if (this.panel.state != "closed")
return;
this._blockCommands(); // un-done in the popuphiding handler this._blockCommands(); // un-done in the popuphiding handler
var bundle = this._element("bundle_browser"); var bundle = this._element("bundle_browser");
@ -216,17 +220,10 @@ var StarUI = {
isTransient: false, isTransient: false,
merge: function() { return false; } }); merge: function() { return false; } });
if (this.panel.state == "closed") {
// Consume dismiss clicks, see bug 400924 // Consume dismiss clicks, see bug 400924
this.panel.popupBoxObject this.panel.popupBoxObject
.setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_CONSUME); .setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_CONSUME);
this.panel.openPopup(aAnchorElement, aPosition, -1, -1); this.panel.openPopup(aAnchorElement, aPosition, -1, -1);
}
else {
var namePicker = this._element("editBMPanel_namePicker");
namePicker.focus();
namePicker.editor.selectAll();
}
gEditItemOverlay.initPanel(this._itemId, gEditItemOverlay.initPanel(this._itemId,
{ hiddenRows: ["description", "location", { hiddenRows: ["description", "location",

Просмотреть файл

@ -31,6 +31,11 @@ toolbar[printpreview="true"] {
display: none; display: none;
} }
#feed-button > .button-box > .box-inherit > .button-text,
#feed-button > .button-box > .button-menu-dropmarker {
display: none;
}
#urlbar[pageproxystate="invalid"] > #urlbar-icons > :not(#go-button) , #urlbar[pageproxystate="invalid"] > #urlbar-icons > :not(#go-button) ,
#urlbar[pageproxystate="valid"] > #urlbar-icons > #go-button , #urlbar[pageproxystate="valid"] > #urlbar-icons > #go-button ,
#urlbar[empty="true"] > #urlbar-icons > #go-button { #urlbar[empty="true"] > #urlbar-icons > #go-button {

Просмотреть файл

@ -333,12 +333,12 @@ const gPopupBlockerObserver = {
if (!gBrowser.pageReport) { if (!gBrowser.pageReport) {
// Hide the popup blocker statusbar button // Hide the popup blocker statusbar button
this._reportButton.removeAttribute("blocked"); this._reportButton.hidden = true;
return; return;
} }
this._reportButton.setAttribute("blocked", true); this._reportButton.hidden = false;
// Only show the notification again if we've not already shown it. Since // Only show the notification again if we've not already shown it. Since
// notifications are per-browser, we don't need to worry about re-adding // notifications are per-browser, we don't need to worry about re-adding
@ -6103,20 +6103,15 @@ var FeedHandler = {
var feeds = gBrowser.mCurrentBrowser.feeds; var feeds = gBrowser.mCurrentBrowser.feeds;
if (!feeds || feeds.length == 0) { if (!feeds || feeds.length == 0) {
if (feedButton) { if (feedButton) {
feedButton.removeAttribute("feeds"); feedButton.collapsed = true;
feedButton.removeAttribute("feed"); feedButton.removeAttribute("feed");
feedButton.setAttribute("tooltiptext",
gNavigatorBundle.getString("feedNoFeeds"));
} }
this._feedMenuitem.setAttribute("disabled", "true"); this._feedMenuitem.setAttribute("disabled", "true");
this._feedMenupopup.setAttribute("hidden", "true"); this._feedMenupopup.setAttribute("hidden", "true");
this._feedMenuitem.removeAttribute("hidden"); this._feedMenuitem.removeAttribute("hidden");
} else { } else {
if (feedButton) { if (feedButton)
feedButton.setAttribute("feeds", "true"); feedButton.collapsed = false;
feedButton.setAttribute("tooltiptext",
gNavigatorBundle.getString("feedHasFeedsNew"));
}
if (feeds.length > 1) { if (feeds.length > 1) {
this._feedMenuitem.setAttribute("hidden", "true"); this._feedMenuitem.setAttribute("hidden", "true");
@ -6152,11 +6147,8 @@ var FeedHandler = {
browserForLink.feeds = feeds; browserForLink.feeds = feeds;
if (browserForLink == gBrowser || browserForLink == gBrowser.mCurrentBrowser) { if (browserForLink == gBrowser || browserForLink == gBrowser.mCurrentBrowser) {
var feedButton = document.getElementById("feed-button"); var feedButton = document.getElementById("feed-button");
if (feedButton) { if (feedButton)
feedButton.setAttribute("feeds", "true"); feedButton.collapsed = false;
feedButton.setAttribute("tooltiptext",
gNavigatorBundle.getString("feedHasFeedsNew"));
}
} }
} }
} }

Просмотреть файл

@ -397,6 +397,8 @@
class="plain urlbar-icon" class="plain urlbar-icon"
id="feed-button" id="feed-button"
chromedir="&locale.dir;" chromedir="&locale.dir;"
collapsed="true"
tooltiptext="&feedButton.tooltip;"
onclick="return FeedHandler.onFeedButtonClick(event);"> onclick="return FeedHandler.onFeedButtonClick(event);">
<menupopup position="after_end" <menupopup position="after_end"
onpopupshowing="return FeedHandler.buildFeedList(this);" onpopupshowing="return FeedHandler.buildFeedList(this);"
@ -573,6 +575,7 @@
ondblclick="if (event.button == 0) displaySecurityInfo();"/> ondblclick="if (event.button == 0) displaySecurityInfo();"/>
<statusbarpanel id="page-report-button" type="menu" <statusbarpanel id="page-report-button" type="menu"
class="statusbarpanel-menu-iconic" class="statusbarpanel-menu-iconic"
hidden="true"
tooltiptext="&pageReportIcon.tooltip;"> tooltiptext="&pageReportIcon.tooltip;">
<menupopup onpopupshowing="gPopupBlockerObserver.fillPopupList(event);"> <menupopup onpopupshowing="gPopupBlockerObserver.fillPopupList(event);">
<menuitem observes="blockedPopupAllowSite"/> <menuitem observes="blockedPopupAllowSite"/>

Просмотреть файл

@ -64,7 +64,7 @@
<hbox pack="center"> <hbox pack="center">
<statusbar style="width:20em"> <statusbar style="width:20em">
<statusbarpanel flex="1" pack="left"><description>&done.label;</description></statusbarpanel> <statusbarpanel flex="1" pack="left"><description>&done.label;</description></statusbarpanel>
<statusbarpanel class="statusbarpanel-iconic" style="min-height:18px" id="page-report-button" blocked="true"/> <statusbarpanel class="statusbarpanel-iconic" style="min-height:18px" id="page-report-button"/>
</statusbar> </statusbar>
</hbox> </hbox>

Просмотреть файл

@ -60,6 +60,7 @@ _BROWSER_FILES = browser_bug321000.js \
browser_bug409481.js \ browser_bug409481.js \
browser_bug413915.js \ browser_bug413915.js \
browser_bug420160.js \ browser_bug420160.js \
browser_bug432599.js \
browser_bug427559.js \ browser_bug427559.js \
browser_bug441778.js \ browser_bug441778.js \
browser_discovery.js \ browser_discovery.js \

Просмотреть файл

@ -0,0 +1,109 @@
function invokeUsingCtrlD(phase) {
switch (phase) {
case 1:
EventUtils.synthesizeKey("d", { accelKey: true });
break;
case 2:
case 4:
EventUtils.synthesizeKey("VK_ESCAPE", {});
break;
case 3:
EventUtils.synthesizeKey("d", { accelKey: true });
EventUtils.synthesizeKey("d", { accelKey: true });
break;
}
}
function invokeUsingStarButton(phase) {
switch (phase) {
case 1:
EventUtils.sendMouseEvent({ type: "click" }, "star-button");
break;
case 2:
case 4:
EventUtils.synthesizeKey("VK_ESCAPE", {});
break;
case 3:
EventUtils.synthesizeMouse(document.getElementById("star-button"),
1, 1, { clickCount: 2 });
break;
}
}
// test bug 432599
function test() {
waitForExplicitFinish();
let testTab = gBrowser.addTab();
gBrowser.selectedTab = testTab;
let testBrowser = gBrowser.getBrowserForTab(testTab);
testBrowser.addEventListener("load", initTest, true);
testBrowser.contentWindow.location = "data:text/plain,Content";
}
let invokers = [invokeUsingStarButton, invokeUsingCtrlD];
let currentInvoker = 0;
function initTest() {
// first, bookmark the page
let app = Components.classes["@mozilla.org/fuel/application;1"]
.getService(Components.interfaces.fuelIApplication);
let ios = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
app.bookmarks.toolbar.addBookmark("Bug 432599 Test",
ios.newURI("data:text/plain,Content", null, null));
checkBookmarksPanel(invokers[currentInvoker], 1);
}
let initialValue;
let initialRemoveHidden;
let popupElement = document.getElementById("editBookmarkPanel");
let titleElement = document.getElementById("editBookmarkPanelTitle");
let removeElement = document.getElementById("editBookmarkPanelRemoveButton");
function checkBookmarksPanel(invoker, phase)
{
let onPopupShown = function(aEvent) {
if (aEvent.originalTarget == popupElement) {
checkBookmarksPanel(invoker, phase + 1);
popupElement.removeEventListener("popupshown", onPopupShown, false);
}
};
let onPopupHidden = function(aEvent) {
if (aEvent.originalTarget == popupElement) {
if (phase < 4) {
checkBookmarksPanel(invoker, phase + 1);
} else {
++ currentInvoker;
if (currentInvoker < invokers.length) {
checkBookmarksPanel(invokers[currentInvoker], 1);
} else {
gBrowser.removeCurrentTab();
finish();
}
}
popupElement.removeEventListener("popuphidden", onPopupHidden, false);
}
};
switch (phase) {
case 1:
case 3:
popupElement.addEventListener("popupshown", onPopupShown, false);
break;
case 2:
popupElement.addEventListener("popuphidden", onPopupHidden, false);
initialValue = titleElement.value;
initialRemoveHidden = removeElement.hidden;
break;
case 4:
popupElement.addEventListener("popuphidden", onPopupHidden, false);
is(titleElement.value, initialValue, "The bookmark panel's title should be the same");
is(removeElement.hidden, initialRemoveHidden, "The bookmark panel's visibility should not change");
break;
}
invoker(phase);
}

Просмотреть файл

@ -353,7 +353,7 @@ function getShellService()
function isBidiEnabled() { function isBidiEnabled() {
// first check the pref. // first check the pref.
if (getBoolPref("browser.bidi.ui", false)) if (getBoolPref("bidi.browser.ui", false))
return true; return true;
// if the pref isn't set, check for an RTL locale and force the pref to true // if the pref isn't set, check for an RTL locale and force the pref to true

Просмотреть файл

@ -85,14 +85,17 @@ var gEditItemOverlay = {
this._element("nameRow").collapsed = this._hiddenRows.indexOf("name") != -1; this._element("nameRow").collapsed = this._hiddenRows.indexOf("name") != -1;
this._element("folderRow").collapsed = this._element("folderRow").collapsed =
this._hiddenRows.indexOf("folderPicker") != -1 || this._readOnly; this._hiddenRows.indexOf("folderPicker") != -1 || this._readOnly;
this._element("tagsRow").collapsed = !this._uri || this._element("tagsRow").collapsed = !this._uri ||
this._hiddenRows.indexOf("tags") != -1 || isQuery; this._hiddenRows.indexOf("tags") != -1 || isQuery;
// Collapse the tag selector if the item does not accept tags.
if (!this._element("tagsSelector").collapsed &&
this._element("tagsRow").collapsed)
this.toggleTagsSelector();
this._element("descriptionRow").collapsed = this._element("descriptionRow").collapsed =
this._hiddenRows.indexOf("description") != -1 || this._readOnly; this._hiddenRows.indexOf("description") != -1 || this._readOnly;
this._element("keywordRow").collapsed = !isBookmark || this._readOnly || this._element("keywordRow").collapsed = !isBookmark || this._readOnly ||
this._hiddenRows.indexOf("keyword") != -1 || isQuery; this._hiddenRows.indexOf("keyword") != -1 || isQuery;
this._element("locationRow").collapsed = !isBookmark || isQuery || this._element("locationRow").collapsed = !(this._uri && !isQuery) ||
this._hiddenRows.indexOf("location") != -1; this._hiddenRows.indexOf("location") != -1;
this._element("loadInSidebarCheckbox").collapsed = !isBookmark || isQuery || this._element("loadInSidebarCheckbox").collapsed = !isBookmark || isQuery ||
this._readOnly || this._hiddenRows.indexOf("loadInSidebar") != -1; this._readOnly || this._hiddenRows.indexOf("loadInSidebar") != -1;

Просмотреть файл

@ -77,6 +77,7 @@
class="chevron" class="chevron"
mousethrough="never" mousethrough="never"
collapsed="true" collapsed="true"
tooltiptext="&bookmarksToolbarChevron.tooltip;"
onpopupshowing="chevronPopupShowing(event);"> onpopupshowing="chevronPopupShowing(event);">
<xul:menupopup anonid="chevronPopup" <xul:menupopup anonid="chevronPopup"
xbl:inherits="tooltip" xbl:inherits="tooltip"

Просмотреть файл

@ -294,10 +294,14 @@ PlacesTreeView.prototype = {
var min = { }, max = { }; var min = { }, max = { };
selection.getRangeAt(rangeIndex, min, max); selection.getRangeAt(rangeIndex, min, max);
var lastIndex = Math.min(max.value, startReplacement + replaceCount -1); var lastIndex = Math.min(max.value, startReplacement + replaceCount -1);
if (min.value < startReplacement || min.value > lastIndex) // if this range does not overlap the replaced chunk we don't need to
// persist the selection.
if (max.value < startReplacement || min.value > lastIndex)
continue; continue;
// if this range starts before the replaced chunk we should persist from
for (var nodeIndex = min.value; nodeIndex <= lastIndex; nodeIndex++) // startReplacement to lastIndex
var firstIndex = Math.max(min.value, startReplacement);
for (var nodeIndex = firstIndex; nodeIndex <= lastIndex; nodeIndex++)
previouslySelectedNodes.push( previouslySelectedNodes.push(
{ node: this._visibleElements[nodeIndex].node, oldIndex: nodeIndex }); { node: this._visibleElements[nodeIndex].node, oldIndex: nodeIndex });
} }
@ -309,7 +313,8 @@ PlacesTreeView.prototype = {
// Building the new list will set the new elements' visible indices. // Building the new list will set the new elements' visible indices.
var newElements = []; var newElements = [];
var toOpenElements = []; var toOpenElements = [];
this._buildVisibleSection(aContainer, newElements, toOpenElements, startReplacement); this._buildVisibleSection(aContainer,
newElements, toOpenElements, startReplacement);
// actually update the visible list // actually update the visible list
this._visibleElements = this._visibleElements =
@ -320,7 +325,7 @@ PlacesTreeView.prototype = {
// If the new area has a different size, we'll have to renumber the // If the new area has a different size, we'll have to renumber the
// elements following the area. // elements following the area.
if (replaceCount != newElements.length) { if (replaceCount != newElements.length) {
for (i = startReplacement + newElements.length; for (var i = startReplacement + newElements.length;
i < this._visibleElements.length; i ++) { i < this._visibleElements.length; i ++) {
this._visibleElements[i].node.viewIndex = i; this._visibleElements[i].node.viewIndex = i;
} }

Просмотреть файл

@ -63,6 +63,11 @@
name="pref.privacy.disable_button.view_cookies" name="pref.privacy.disable_button.view_cookies"
type="bool"/> type="bool"/>
<!-- Location Bar -->
<preference id="browser.urlbar.search.sources"
name="browser.urlbar.search.sources"
type="int"/>
<!-- History --> <!-- History -->
<preference id="browser.history_expire_days" <preference id="browser.history_expire_days"
name="browser.history_expire_days" name="browser.history_expire_days"
@ -104,6 +109,22 @@
<groupbox id="historyGroup"> <groupbox id="historyGroup">
<caption label="&history.label;"/> <caption label="&history.label;"/>
<hbox align="center">
<label id="locationBarSuggestionLabel"
control="locationBarSuggestion"
accesskey="&locbar.pre.accessKey;">&locbar.pre.label;</label>
<menulist id="locationBarSuggestion"
preference="browser.urlbar.search.sources">
<menupopup>
<menuitem label="&locbar.both.label;" value="3"/>
<menuitem label="&locbar.history.label;" value="1"/>
<menuitem label="&locbar.bookmarks.label;" value="2"/>
<menuitem label="&locbar.nothing.label;" value="0"/>
</menupopup>
</menulist>
<label>&locbar.post.label;</label>
</hbox>
<hbox align="center"> <hbox align="center">
<checkbox id="rememberHistoryDays" <checkbox id="rememberHistoryDays"
label="&rememberDaysBefore.label;" label="&rememberDaysBefore.label;"

Просмотреть файл

@ -98,6 +98,7 @@ function cleanUp()
"places.sqlite", "places.sqlite",
"cookies.sqlite", "cookies.sqlite",
"signons.sqlite", "signons.sqlite",
"permissions.sqlite"
]; ];
for (let i = 0; i < files.length; i++) { for (let i = 0; i < files.length; i++) {

Просмотреть файл

@ -1341,8 +1341,12 @@ SessionStoreService.prototype = {
let data = {}; let data = {};
do { do {
let id = node.id ? "#" + node.id : XPathHelper.generate(node); let id = node.id ? "#" + node.id : XPathHelper.generate(node);
if (node instanceof Ci.nsIDOMHTMLInputElement) if (node instanceof Ci.nsIDOMHTMLInputElement) {
if (node.type != "file")
data[id] = node.type == "checkbox" || node.type == "radio" ? node.checked : node.value; data[id] = node.type == "checkbox" || node.type == "radio" ? node.checked : node.value;
else
data[id] = { type: "file", value: node.value };
}
else if (node instanceof Ci.nsIDOMHTMLTextAreaElement) else if (node instanceof Ci.nsIDOMHTMLTextAreaElement)
data[id] = node.value; data[id] = node.value;
else if (!node.multiple) else if (!node.multiple)
@ -1633,8 +1637,8 @@ SessionStoreService.prototype = {
this.restoreCookies(winData.cookies); this.restoreCookies(winData.cookies);
} }
if (winData.extData) { if (winData.extData) {
if (!this._windows[aWindow.__SSi].extData) { if (aOverwriteTabs || !this._windows[aWindow.__SSi].extData) {
this._windows[aWindow.__SSi].extData = {} this._windows[aWindow.__SSi].extData = {};
} }
for (var key in winData.extData) { for (var key in winData.extData) {
this._windows[aWindow.__SSi].extData[key] = winData.extData[key]; this._windows[aWindow.__SSi].extData[key] = winData.extData[key];
@ -1969,7 +1973,7 @@ SessionStoreService.prototype = {
RegExp.$1 == aPrefix && hasExpectedURL(aContent.document, aURL)) { RegExp.$1 == aPrefix && hasExpectedURL(aContent.document, aURL)) {
var document = aContent.document; var document = aContent.document;
var node = RegExp.$2 ? document.getElementById(RegExp.$3) : document.getElementsByName(RegExp.$3)[0] || null; var node = RegExp.$2 ? document.getElementById(RegExp.$3) : document.getElementsByName(RegExp.$3)[0] || null;
if (node && "value" in node) { if (node && "value" in node && node.type != "file") {
node.value = decodeURI(RegExp.$4); node.value = decodeURI(RegExp.$4);
var event = document.createEvent("UIEvents"); var event = document.createEvent("UIEvents");
@ -1991,7 +1995,7 @@ SessionStoreService.prototype = {
continue; continue;
let value = aData[key]; let value = aData[key];
if (typeof value == "string") { if (typeof value == "string" && node.type != "file") {
node.value = value; node.value = value;
let event = aDocument.createEvent("UIEvents"); let event = aDocument.createEvent("UIEvents");
@ -2004,6 +2008,8 @@ SessionStoreService.prototype = {
try { try {
node.selectedIndex = value; node.selectedIndex = value;
} catch (ex) { /* throws for invalid indices */ } } catch (ex) { /* throws for invalid indices */ }
else if (value && value.type && value.type == node.type)
node.value = value.value;
else if (value && typeof value.indexOf == "function" && node.options) { else if (value && typeof value.indexOf == "function" && node.options) {
Array.forEach(node.options, function(aOpt, aIx) { Array.forEach(node.options, function(aOpt, aIx) {
aOpt.selected = value.indexOf(aIx) > -1; aOpt.selected = value.indexOf(aIx) > -1;
@ -2122,11 +2128,20 @@ SessionStoreService.prototype = {
if (!isNaN(aLeft) && !isNaN(aTop) && (aLeft != win_("screenX") || aTop != win_("screenY"))) { if (!isNaN(aLeft) && !isNaN(aTop) && (aLeft != win_("screenX") || aTop != win_("screenY"))) {
aWindow.moveTo(aLeft, aTop); aWindow.moveTo(aLeft, aTop);
} }
if (aSizeMode == "maximized" && win_("sizemode") != "maximized") { switch (aSizeMode)
{
case "maximized":
if (win_("sizemode") != "maximized")
aWindow.maximize(); aWindow.maximize();
} break
else if (aSizeMode && aSizeMode != "maximized" && win_("sizemode") != "normal") { case "minimized":
if (win_("sizemode") != "minimized")
aWindow.minimize();
break
default:
if (win_("sizemode") != "normal")
aWindow.restore(); aWindow.restore();
break
} }
var sidebar = aWindow.document.getElementById("sidebar-box"); var sidebar = aWindow.document.getElementById("sidebar-box");
if (sidebar.getAttribute("sidebarcommand") != aSidebar) { if (sidebar.getAttribute("sidebarcommand") != aSidebar) {

Просмотреть файл

@ -66,6 +66,9 @@ _BROWSER_TEST_FILES = \
browser_463206.js \ browser_463206.js \
browser_463206_sample.html \ browser_463206_sample.html \
browser_465215.js \ browser_465215.js \
browser_465223.js \
browser_466937.js \
browser_466937_sample.html \
$(NULL) $(NULL)
libs:: $(_BROWSER_TEST_FILES) libs:: $(_BROWSER_TEST_FILES)

Просмотреть файл

@ -0,0 +1,79 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is sessionstore test code.
*
* The Initial Developer of the Original Code is
* Simon Bünzli <zeniko@gmail.com>.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
function test() {
/** Test for Bug 465223 **/
// test setup
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
waitForExplicitFinish();
let uniqueKey1 = "bug 465223.1";
let uniqueKey2 = "bug 465223.2";
let uniqueValue1 = "unik" + Date.now();
let uniqueValue2 = "pi != " + Math.random();
// open a window and set a value on it
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
newWin.addEventListener("load", function(aEvent) {
ss.setWindowValue(newWin, uniqueKey1, uniqueValue1);
let newState = { windows: [{ tabs:[{ entries: [] }], extData: {} }] };
newState.windows[0].extData[uniqueKey2] = uniqueValue2;
ss.setWindowState(newWin, JSON.stringify(newState), false);
is(newWin.gBrowser.tabContainer.childNodes.length, 2,
"original tab wasn't overwritten");
is(ss.getWindowValue(newWin, uniqueKey1), uniqueValue1,
"window value wasn't overwritten when the tabs weren't");
is(ss.getWindowValue(newWin, uniqueKey2), uniqueValue2,
"new window value was correctly added");
newState.windows[0].extData[uniqueKey2] = uniqueValue1;
ss.setWindowState(newWin, JSON.stringify(newState), true);
is(newWin.gBrowser.tabContainer.childNodes.length, 1,
"original tabs were overwritten");
is(ss.getWindowValue(newWin, uniqueKey1), "",
"window value was cleared");
is(ss.getWindowValue(newWin, uniqueKey2), uniqueValue1,
"window value was correctly overwritten");
// clean up
newWin.close();
finish();
}, false);
}

Просмотреть файл

@ -0,0 +1,69 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is sessionstore test code.
*
* The Initial Developer of the Original Code is
* Simon Bünzli <zeniko@gmail.com>.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
function test() {
/** Test for Bug 466937 **/
waitForExplicitFinish();
let testURL = "http://localhost:8888/browser/" +
"browser/components/sessionstore/test/browser/browser_466937_sample.html";
let testPath = "/home/user/regular.file";
let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) {
let doc = tab.linkedBrowser.contentDocument;
doc.getElementById("reverse_thief").value = "/home/user/secret2";
doc.getElementById("bystander").value = testPath;
let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("load", function(aEvent) {
doc = tab2.linkedBrowser.contentDocument;
is(doc.getElementById("thief").value, "",
"file path wasn't set to text field value");
is(doc.getElementById("reverse_thief").value, "",
"text field value wasn't set to full file path");
is(doc.getElementById("bystander").value, testPath,
"normal case: file path was correctly preserved");
// clean up
gBrowser.removeTab(tab2);
gBrowser.removeTab(tab);
finish();
}, true);
}, true);
}

Просмотреть файл

@ -0,0 +1,20 @@
<!-- Testcase originally by <moz_bug_r_a4@yahoo.com> -->
<!DOCTYPE html>
<title>Test for bug 466937</title>
<input id="thief" value="/home/user/secret">
<input type="file" id="reverse_thief">
<input type="file" id="bystander">
<script>
window.addEventListener("DOMContentLoaded", function() {
if (!document.location.hash) {
document.location.hash = "#ready";
}
else {
document.getElementById("thief").type = "file";
document.getElementById("reverse_thief").type = "text";
}
}, false);
</script>

Просмотреть файл

@ -71,6 +71,7 @@
<!ENTITY addCurPagesCmd.label "Bookmark All Tabs…"> <!ENTITY addCurPagesCmd.label "Bookmark All Tabs…">
<!ENTITY organizeBookmarks.label "Organize Bookmarks…"> <!ENTITY organizeBookmarks.label "Organize Bookmarks…">
<!ENTITY bookmarkAllCmd.label "Bookmark All Tabs…"> <!ENTITY bookmarkAllCmd.label "Bookmark All Tabs…">
<!ENTITY bookmarksToolbarChevron.tooltip "Show more bookmarks">
<!ENTITY backCmd.label "Back"> <!ENTITY backCmd.label "Back">
<!ENTITY backCmd.accesskey "B"> <!ENTITY backCmd.accesskey "B">
@ -87,6 +88,7 @@
<!ENTITY stopCmd.macCommandKey "."> <!ENTITY stopCmd.macCommandKey ".">
<!ENTITY stopButton.tooltip "Stop loading this page"> <!ENTITY stopButton.tooltip "Stop loading this page">
<!ENTITY goEndCap.tooltip "Go to the address in the Location Bar"> <!ENTITY goEndCap.tooltip "Go to the address in the Location Bar">
<!ENTITY feedButton.tooltip "Subscribe to this page…">
<!ENTITY printButton.label "Print"> <!ENTITY printButton.label "Print">
<!ENTITY printButton.tooltip "Print this page"> <!ENTITY printButton.tooltip "Print this page">

Просмотреть файл

@ -73,9 +73,7 @@ updatesItem_pending=Apply Downloaded Update Now…
updatesItem_pendingFallback=Apply Downloaded Update Now… updatesItem_pendingFallback=Apply Downloaded Update Now…
# RSS Pretty Print # RSS Pretty Print
feedNoFeeds=Page has no feeds
feedShowFeedNew=Subscribe to '%S'… feedShowFeedNew=Subscribe to '%S'…
feedHasFeedsNew=Subscribe to this page…
# History menu # History menu
menuOpenAllInTabs.label=Open All in Tabs menuOpenAllInTabs.label=Open All in Tabs

Просмотреть файл

@ -1,5 +1,13 @@
<!ENTITY history.label "History"> <!ENTITY history.label "History">
<!ENTITY locbar.pre.label "When using the location bar, suggest:">
<!ENTITY locbar.pre.accessKey "l">
<!ENTITY locbar.post.label "">
<!ENTITY locbar.both.label "History and Bookmarks">
<!ENTITY locbar.history.label "History">
<!ENTITY locbar.bookmarks.label "Bookmarks">
<!ENTITY locbar.nothing.label "Nothing">
<!-- LOCALIZATION NOTE: <!-- LOCALIZATION NOTE:
The entities rememberDaysBefore.label and rememberDaysAfter2.label appear on a single The entities rememberDaysBefore.label and rememberDaysAfter2.label appear on a single
line in preferences as follows: line in preferences as follows:

Просмотреть файл

@ -986,19 +986,10 @@ toolbar[iconsize="small"] #paste-button[disabled="true"] {
background-color: transparent; background-color: transparent;
} }
#feed-button > hbox > .button-menu-dropmarker,
#feed-button > hbox > .button-text {
display: none;
}
#feed-button { #feed-button {
-moz-binding: url("chrome://global/content/bindings/button.xml#menu");
-moz-appearance: none; -moz-appearance: none;
min-width: 0px; min-width: 0px;
margin-right: 1px !important; margin-right: 1px !important;
}
#feed-button[feeds] {
list-style-image: url("chrome://browser/skin/page-livemarks.png"); list-style-image: url("chrome://browser/skin/page-livemarks.png");
} }
@ -1130,14 +1121,8 @@ statusbarpanel#statusbar-display {
} }
#page-report-button { #page-report-button {
list-style-image: none;
width: 20px;
display: none;
}
#page-report-button[blocked] {
list-style-image: url("chrome://browser/skin/Info.png"); list-style-image: url("chrome://browser/skin/Info.png");
display: -moz-box; width: 20px;
} }
/* Throbber */ /* Throbber */

Просмотреть файл

@ -983,6 +983,7 @@ richlistitem[selected="true"][current="true"] > hbox > .ac-result-type-bookmark,
/* STAR BUTTON */ /* STAR BUTTON */
#star-button { #star-button {
padding: 1px; padding: 1px;
-moz-padding-start: 4px;
list-style-image: url("chrome://browser/skin/places/star-icons.png"); list-style-image: url("chrome://browser/skin/places/star-icons.png");
-moz-image-region: rect(0px, 16px, 16px, 0px); -moz-image-region: rect(0px, 16px, 16px, 0px);
} }
@ -1433,46 +1434,25 @@ sidebarheader > .tabs-closebutton > .toolbarbutton-text {
/* ----- PAGE REPORT DISPLAY ----- */ /* ----- PAGE REPORT DISPLAY ----- */
#page-report-button { #page-report-button {
display: none;
}
#page-report-button[blocked] {
display: -moz-box;
list-style-image: url("chrome://browser/skin/Popup-blocked.png"); list-style-image: url("chrome://browser/skin/Popup-blocked.png");
padding: 0px 3px 0px 3px; padding: 0px 3px 0px 3px;
} }
/* ----- FEED CONTENT DISPLAY ---- */ /* ----- FEED CONTENT DISPLAY ---- */
#feed-button, #feed-button > .button-box,
#feed-button:hover:active > .button-box {
padding: 0px;
margin: -1px;
border: 0px;
background-color: transparent;
}
#feed-button .button-menu-dropmarker,
#feed-button .button-text {
display: none;
}
#feed-button { #feed-button {
-moz-binding: url("chrome://global/content/bindings/button.xml#menu");
-moz-appearance: none; -moz-appearance: none;
min-width: 0; min-width: 0;
min-height: 0; min-height: 0;
margin-right: 1px !important; -moz-padding-start: 4px !important;
}
#feed-button[feeds] {
list-style-image: url("chrome://browser/skin/feed-icons.png"); list-style-image: url("chrome://browser/skin/feed-icons.png");
-moz-image-region: rect(0px, 16px, 16px, 0px); -moz-image-region: rect(0px, 16px, 16px, 0px);
} }
#feed-button[feeds]:hover { #feed-button:hover {
-moz-image-region: rect(0px, 32px, 16px, 16px); -moz-image-region: rect(0px, 32px, 16px, 16px);
} }
#feed-button[feeds]:active { #feed-button[open="true"],
#feed-button:hover:active {
-moz-image-region: rect(0px, 48px, 16px, 32px); -moz-image-region: rect(0px, 48px, 16px, 32px);
} }

Просмотреть файл

@ -1261,14 +1261,8 @@ statusbarpanel#statusbar-display {
} }
#page-report-button { #page-report-button {
list-style-image: none;
width: 20px; width: 20px;
display: none;
}
#page-report-button[blocked] {
list-style-image: url("chrome://browser/skin/Info.png"); list-style-image: url("chrome://browser/skin/Info.png");
display: -moz-box;
} }
/* ::::: throbber ::::: */ /* ::::: throbber ::::: */
@ -1654,7 +1648,8 @@ toolbar[mode="text"] > #window-controls > toolbarbutton > .toolbarbutton-text {
} }
/* Feed icon */ /* Feed icon */
#feed-button, #feed-button > .button-box, #feed-button,
#feed-button > .button-box,
#feed-button:hover:active > .button-box { #feed-button:hover:active > .button-box {
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
@ -1662,36 +1657,23 @@ toolbar[mode="text"] > #window-controls > toolbarbutton > .toolbarbutton-text {
background-color: transparent; background-color: transparent;
} }
#feed-button > hbox > .button-menu-dropmarker,
#feed-button > hbox > .button-text {
display: none;
}
#feed-button { #feed-button {
-moz-binding: url("chrome://global/content/bindings/button.xml#menu");
-moz-appearance: none; -moz-appearance: none;
min-width: 0px; min-width: 0px;
padding: 0 2px !important; padding: 0 2px !important;
}
#feed-button[feeds] {
list-style-image: url("chrome://browser/skin/feeds/feed-icons-16.png"); list-style-image: url("chrome://browser/skin/feeds/feed-icons-16.png");
-moz-image-region: rect(0px 16px 16px 0px); -moz-image-region: rect(0px 16px 16px 0px);
} }
#feed-button[feeds]:hover { #feed-button:hover {
-moz-image-region: rect(0px 32px 16px 16px); -moz-image-region: rect(0px 32px 16px 16px);
} }
#feed-button[feeds][open="true"], #feed-button[open="true"],
#feed-button[feeds]:hover:active { #feed-button:hover:active {
-moz-image-region: rect(0px 48px 16px 32px); -moz-image-region: rect(0px 48px 16px 32px);
} }
#feed-button:not([feeds]) {
visibility: collapse;
}
/* ::::: About Popup Blocking dialog ::::: */ /* ::::: About Popup Blocking dialog ::::: */
#pageReportFirstTime statusbarpanel.statusbar-resizerpanel { #pageReportFirstTime statusbarpanel.statusbar-resizerpanel {
visibility: collapse; visibility: collapse;

Просмотреть файл

@ -71,6 +71,10 @@ MOZCE_SHUNT_API int putenv(const char *a);
MOZCE_SHUNT_API char SetEnvironmentVariableW(const unsigned short * name, const unsigned short * value ); MOZCE_SHUNT_API char SetEnvironmentVariableW(const unsigned short * name, const unsigned short * value );
MOZCE_SHUNT_API char GetEnvironmentVariableW(const unsigned short * lpName, unsigned short* lpBuffer, unsigned long nSize); MOZCE_SHUNT_API char GetEnvironmentVariableW(const unsigned short * lpName, unsigned short* lpBuffer, unsigned long nSize);
MOZCE_SHUNT_API unsigned int ExpandEnvironmentStringsW(const unsigned short* lpSrc,
unsigned short* lpDst,
unsigned int nSize);
/* File system stuff */ /* File system stuff */
MOZCE_SHUNT_API unsigned short * _wgetcwd(unsigned short* dir, unsigned long size); MOZCE_SHUNT_API unsigned short * _wgetcwd(unsigned short* dir, unsigned long size);
MOZCE_SHUNT_API unsigned short *_wfullpath( unsigned short *absPath, const unsigned short *relPath, unsigned long maxLength ); MOZCE_SHUNT_API unsigned short *_wfullpath( unsigned short *absPath, const unsigned short *relPath, unsigned long maxLength );

Просмотреть файл

@ -193,6 +193,121 @@ MOZCE_SHUNT_API char SetEnvironmentVariableW( const unsigned short * name, const
return map_put(key,val); return map_put(key,val);
} }
typedef struct MOZCE_SHUNT_SPECIAL_FOLDER_INFO
{
int nFolder;
char *folderEnvName;
} MozceShuntSpecialFolderInfo;
// TAKEN DIRECTLY FROM MICROSOFT SHELLAPI.H HEADER FILE
// supported SHGetSpecialFolderPath nFolder ids
#define CSIDL_DESKTOP 0x0000
#define CSIDL_PROGRAMS 0x0002 // \Windows\Start Menu\Programs
#define CSIDL_PERSONAL 0x0005
#define CSIDL_WINDOWS 0x0024 // \Windows
#define CSIDL_PROGRAM_FILES 0x0026 // \Program Files
#define CSIDL_APPDATA 0x001A // NOT IN SHELLAPI.H header file
#define CSIDL_PROFILE 0x0028 // NOT IN SHELLAPI.H header file
MozceShuntSpecialFolderInfo mozceSpecialFoldersToEnvVars[] = {
{ CSIDL_APPDATA, "APPDATA" },
{ CSIDL_PROGRAM_FILES, "ProgramFiles" },
{ CSIDL_WINDOWS, "windir" },
// { CSIDL_PROFILE, "HOMEPATH" }, // No return on WinMobile 6 Pro
// { CSIDL_PROFILE, "USERPROFILE" }, // No return on WinMobile 6 Pro
// { int, "ALLUSERSPROFILE" }, // Only one profile on WinCE
// { int, "CommonProgramFiles" },
// { int, "COMPUTERNAME" },
// { int, "HOMEDRIVE" },
// { int, "SystemDrive" },
// { int, "SystemRoot" },
// { int, "TEMP" },
{ NULL, NULL }
};
static void InitializeSpecialFolderEnvVars()
{
MozceShuntSpecialFolderInfo *p = mozceSpecialFoldersToEnvVars;
while ( p && p->nFolder && p->folderEnvName ) {
WCHAR wPath[MAX_PATH];
char cPath[MAX_PATH];
if ( SHGetSpecialFolderPath(NULL, wPath, p->nFolder, FALSE) )
if ( 0 != WideCharToMultiByte(CP_ACP, 0, wPath, -1, cPath, MAX_PATH, 0, 0) )
map_put(p->folderEnvName, cPath);
p++;
}
}
MOZCE_SHUNT_API unsigned int ExpandEnvironmentStringsW(const unsigned short* lpSrc,
unsigned short* lpDst,
unsigned int nSize)
{
if ( NULL == lpDst )
return 0;
unsigned int size = 0;
unsigned int index = 0;
unsigned int origLen = wcslen(lpSrc);
const unsigned short *pIn = lpSrc;
unsigned short *pOut = lpDst;
while ( index < origLen ) {
if (*pIn != L'%') { // Regular char, copy over
if ( size < nSize ) *pOut = *pIn, pOut++;
index++, size++, pIn++;
continue;
}
// Have a starting '%' - look for matching '%'
int envlen = 0;
const unsigned short *pTmp = ++pIn; // Move past original '%'
while ( L'%' != *pTmp ) {
envlen++, pTmp++;
if ( origLen < index + envlen ) { // Ran past end of original
SetLastError(ERROR_INVALID_PARAMETER); // buffer without matching '%'
return -1;
}
}
if ( 0 == envlen ) { // Encountered a "%%" - mapping to "%"
size++;
if ( size < nSize ) *pOut = *pIn, pOut++;
pIn++;
index += 2;
} else {
// Encountered a "%something%" - mapping "something"
char key[250];
WideCharToMultiByte( CP_ACP, 0, pIn, envlen, key, 250, NULL, NULL );
key[envlen] = 0;
char *pC = map_get(key);
if ( NULL != pC ) {
int n = MultiByteToWideChar( CP_ACP, 0, pC, -1, pOut, nSize - size );
if ( n > 0 ) {
size += n - 1; // Account for trailing zero
pOut += n - 1;
}
}
index += envlen + 2;
pIn = ++pTmp;
}
}
if ( size < nSize ) lpDst[size] = 0;
return size;
}
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
// errno // errno
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
@ -223,14 +338,23 @@ MOZCE_SHUNT_API unsigned short *_wfullpath( unsigned short *absPath, const unsig
if(absPath == NULL){ if(absPath == NULL){
absPath = (unsigned short *)malloc(maxLength*sizeof(unsigned short)); absPath = (unsigned short *)malloc(maxLength*sizeof(unsigned short));
} }
_wgetcwd( absPath, maxLength); unsigned short cwd[MAX_PATH];
unsigned long len = wcslen(absPath); if (NULL == _wgetcwd( cwd, MAX_PATH))
if(!(absPath[len-1] == TCHAR('/') || absPath[len-1] == TCHAR('\\'))&& len< maxLength){ return NULL;
absPath[len] = TCHAR('\\');
absPath[++len] = TCHAR('\0'); unsigned long len = wcslen(cwd);
if(!(cwd[len-1] == TCHAR('/') || cwd[len-1] == TCHAR('\\'))&& len< maxLength){
cwd[len] = TCHAR('\\');
cwd[++len] = TCHAR('\0');
} }
if(len+wcslen(relPath) < maxLength){ if(len+wcslen(relPath) < maxLength){
return wcscat(absPath,relPath); #if (_WIN32_WCE > 300)
if ( 0 < CeGetCanonicalPathName(wcscat(cwd,relPath), absPath, maxLength, 0) )
return absPath;
#else
#error Need CeGetCanonicalPathName to build.
// NO ACTUAL CeGetCanonicalPathName function in earlier versions of WinCE
#endif
} }
return NULL; return NULL;
} }
@ -459,6 +583,35 @@ MOZCE_SHUNT_API struct lconv * localeconv(void)
return &s_locale_conv; return &s_locale_conv;
} }
BOOL WINAPI DllMain(HANDLE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
InitializeSpecialFolderEnvVars();
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
#if 0 #if 0
{ {
#endif #endif

Просмотреть файл

@ -2175,6 +2175,9 @@ echo-variable-%:
echo-tiers: echo-tiers:
@echo $(TIERS) @echo $(TIERS)
echo-tier-dirs:
@$(foreach tier,$(TIERS),echo '$(tier):'; echo ' dirs: $(tier_$(tier)_dirs)'; echo ' staticdirs: $(tier_$(tier)_staticdirs)'; )
echo-dirs: echo-dirs:
@echo $(DIRS) @echo $(DIRS)

Просмотреть файл

@ -59,6 +59,7 @@
#include "nsIDOMEvent.h" #include "nsIDOMEvent.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "nsTextFragment.h" #include "nsTextFragment.h"
#include "nsReadableUtils.h"
struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will force strange compilation error! struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will force strange compilation error!
@ -112,6 +113,7 @@ class nsIXTFService;
#ifdef IBMBIDI #ifdef IBMBIDI
class nsIBidiKeyboard; class nsIBidiKeyboard;
#endif #endif
class nsIMIMEHeaderParam;
extern const char kLoadAsData[]; extern const char kLoadAsData[];
@ -1683,4 +1685,33 @@ inline NS_HIDDEN_(PRBool) NS_FloatIsFinite(jsdouble f) {
return (rv); \ return (rv); \
} }
// Deletes a linked list iteratively to avoid blowing up the stack (bug 460444).
#define NS_CONTENT_DELETE_LIST_MEMBER(type_, ptr_, member_) \
{ \
type_ *cur = (ptr_)->member_; \
(ptr_)->member_ = nsnull; \
while (cur) { \
type_ *next = cur->member_; \
cur->member_ = nsnull; \
delete cur; \
cur = next; \
} \
}
class nsContentTypeParser {
public:
nsContentTypeParser(const nsAString& aString);
~nsContentTypeParser();
nsresult GetParameter(const char* aParameterName, nsAString& aResult);
nsresult GetType(nsAString& aResult)
{
return GetParameter(nsnull, aResult);
}
private:
NS_ConvertUTF16toUTF8 mString;
nsIMIMEHeaderParam* mService;
};
#endif /* nsContentUtils_h___ */ #endif /* nsContentUtils_h___ */

Просмотреть файл

@ -558,18 +558,23 @@ public:
* IME_STATUS_PASSWORD should be returned only from password editor, * IME_STATUS_PASSWORD should be returned only from password editor,
* this value has a special meaning. It is used as alternative of * this value has a special meaning. It is used as alternative of
* IME_STATUS_DISABLED. * IME_STATUS_DISABLED.
* IME_STATUS_PLUGIN should be returned only when plug-in has focus.
* When a plug-in is focused content, we should send native events
* directly. Because we don't process some native events, but they may
* be needed by the plug-in.
*/ */
enum { enum {
IME_STATUS_NONE = 0x0000, IME_STATUS_NONE = 0x0000,
IME_STATUS_ENABLE = 0x0001, IME_STATUS_ENABLE = 0x0001,
IME_STATUS_DISABLE = 0x0002, IME_STATUS_DISABLE = 0x0002,
IME_STATUS_PASSWORD = 0x0004, IME_STATUS_PASSWORD = 0x0004,
IME_STATUS_OPEN = 0x0008, IME_STATUS_PLUGIN = 0x0008,
IME_STATUS_CLOSE = 0x0010 IME_STATUS_OPEN = 0x0010,
IME_STATUS_CLOSE = 0x0020
}; };
enum { enum {
IME_STATUS_MASK_ENABLED = IME_STATUS_ENABLE | IME_STATUS_DISABLE | IME_STATUS_MASK_ENABLED = IME_STATUS_ENABLE | IME_STATUS_DISABLE |
IME_STATUS_PASSWORD, IME_STATUS_PASSWORD | IME_STATUS_PLUGIN,
IME_STATUS_MASK_OPENED = IME_STATUS_OPEN | IME_STATUS_CLOSE IME_STATUS_MASK_OPENED = IME_STATUS_OPEN | IME_STATUS_CLOSE
}; };
virtual PRUint32 GetDesiredIMEState() virtual PRUint32 GetDesiredIMEState()

Просмотреть файл

@ -161,6 +161,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "nsIOfflineCacheUpdate.h" #include "nsIOfflineCacheUpdate.h"
#include "nsCPrefetchService.h" #include "nsCPrefetchService.h"
#include "nsIChromeRegistry.h" #include "nsIChromeRegistry.h"
#include "nsIMIMEHeaderParam.h"
#ifdef IBMBIDI #ifdef IBMBIDI
#include "nsIBidiKeyboard.h" #include "nsIBidiKeyboard.h"
@ -462,7 +463,7 @@ nsContentUtils::InitializeEventTable() {
{ &nsGkAtoms::onloadstart, { NS_LOADSTART, EventNameType_HTML }}, { &nsGkAtoms::onloadstart, { NS_LOADSTART, EventNameType_HTML }},
{ &nsGkAtoms::onprogress, { NS_PROGRESS, EventNameType_HTML }}, { &nsGkAtoms::onprogress, { NS_PROGRESS, EventNameType_HTML }},
{ &nsGkAtoms::onloadedmetadata, { NS_LOADEDMETADATA, EventNameType_HTML }}, { &nsGkAtoms::onloadedmetadata, { NS_LOADEDMETADATA, EventNameType_HTML }},
{ &nsGkAtoms::onloadedfirstframe, { NS_LOADEDFIRSTFRAME, EventNameType_HTML }}, { &nsGkAtoms::onloadeddata, { NS_LOADEDDATA, EventNameType_HTML }},
{ &nsGkAtoms::onemptied, { NS_EMPTIED, EventNameType_HTML }}, { &nsGkAtoms::onemptied, { NS_EMPTIED, EventNameType_HTML }},
{ &nsGkAtoms::onstalled, { NS_STALLED, EventNameType_HTML }}, { &nsGkAtoms::onstalled, { NS_STALLED, EventNameType_HTML }},
{ &nsGkAtoms::onplay, { NS_PLAY, EventNameType_HTML }}, { &nsGkAtoms::onplay, { NS_PLAY, EventNameType_HTML }},
@ -472,8 +473,6 @@ nsContentUtils::InitializeEventTable() {
{ &nsGkAtoms::onseeked, { NS_SEEKED, EventNameType_HTML }}, { &nsGkAtoms::onseeked, { NS_SEEKED, EventNameType_HTML }},
{ &nsGkAtoms::ontimeupdate, { NS_TIMEUPDATE, EventNameType_HTML }}, { &nsGkAtoms::ontimeupdate, { NS_TIMEUPDATE, EventNameType_HTML }},
{ &nsGkAtoms::onended, { NS_ENDED, EventNameType_HTML }}, { &nsGkAtoms::onended, { NS_ENDED, EventNameType_HTML }},
{ &nsGkAtoms::ondataunavailable, { NS_DATAUNAVAILABLE, EventNameType_HTML }},
{ &nsGkAtoms::oncanshowcurrentframe, { NS_CANSHOWCURRENTFRAME, EventNameType_HTML }},
{ &nsGkAtoms::oncanplay, { NS_CANPLAY, EventNameType_HTML }}, { &nsGkAtoms::oncanplay, { NS_CANPLAY, EventNameType_HTML }},
{ &nsGkAtoms::oncanplaythrough, { NS_CANPLAYTHROUGH, EventNameType_HTML }}, { &nsGkAtoms::oncanplaythrough, { NS_CANPLAYTHROUGH, EventNameType_HTML }},
{ &nsGkAtoms::onratechange, { NS_RATECHANGE, EventNameType_HTML }}, { &nsGkAtoms::onratechange, { NS_RATECHANGE, EventNameType_HTML }},
@ -3862,6 +3861,8 @@ nsContentUtils::GetWidgetStatusFromIMEStatus(PRUint32 aState)
return nsIWidget::IME_STATUS_ENABLED; return nsIWidget::IME_STATUS_ENABLED;
case nsIContent::IME_STATUS_PASSWORD: case nsIContent::IME_STATUS_PASSWORD:
return nsIWidget::IME_STATUS_PASSWORD; return nsIWidget::IME_STATUS_PASSWORD;
case nsIContent::IME_STATUS_PLUGIN:
return nsIWidget::IME_STATUS_PLUGIN;
default: default:
NS_ERROR("The given state doesn't have valid enable state"); NS_ERROR("The given state doesn't have valid enable state");
return nsIWidget::IME_STATUS_ENABLED; return nsIWidget::IME_STATUS_ENABLED;
@ -4522,3 +4523,22 @@ nsSameOriginChecker::GetInterface(const nsIID & aIID, void **aResult)
return QueryInterface(aIID, aResult); return QueryInterface(aIID, aResult);
} }
nsContentTypeParser::nsContentTypeParser(const nsAString& aString)
: mString(aString), mService(nsnull)
{
CallGetService("@mozilla.org/network/mime-hdrparam;1", &mService);
}
nsContentTypeParser::~nsContentTypeParser()
{
NS_IF_RELEASE(mService);
}
nsresult
nsContentTypeParser::GetParameter(const char* aParameterName, nsAString& aResult)
{
NS_ENSURE_TRUE(mService, NS_ERROR_FAILURE);
return mService->GetParameter(mString, aParameterName,
EmptyCString(), PR_FALSE, nsnull,
aResult);
}

Просмотреть файл

@ -1566,7 +1566,7 @@ GK_ATOM(HTMLVideoFrame, "VideoFrame")
GK_ATOM(onloadstart, "onloadstart") GK_ATOM(onloadstart, "onloadstart")
GK_ATOM(onprogress, "onprogress") GK_ATOM(onprogress, "onprogress")
GK_ATOM(onloadedmetadata, "onloadedmetadata") GK_ATOM(onloadedmetadata, "onloadedmetadata")
GK_ATOM(onloadedfirstframe, "onloadedfirstframe") GK_ATOM(onloadeddata, "onloadeddata")
GK_ATOM(onemptied, "onemptied") GK_ATOM(onemptied, "onemptied")
GK_ATOM(onstalled, "onstalled") GK_ATOM(onstalled, "onstalled")
GK_ATOM(onplay, "onplay") GK_ATOM(onplay, "onplay")
@ -1576,8 +1576,6 @@ GK_ATOM(onseeking, "onseeking")
GK_ATOM(onseeked, "onseeked") GK_ATOM(onseeked, "onseeked")
GK_ATOM(ontimeupdate, "ontimeupdate") GK_ATOM(ontimeupdate, "ontimeupdate")
GK_ATOM(onended, "onended") GK_ATOM(onended, "onended")
GK_ATOM(ondataunavailable, "ondataunavailable")
GK_ATOM(oncanshowcurrentframe, "oncanshowcurrentframe")
GK_ATOM(oncanplay, "oncanplay") GK_ATOM(oncanplay, "oncanplay")
GK_ATOM(oncanplaythrough, "oncanplaythrough") GK_ATOM(oncanplaythrough, "oncanplaythrough")
GK_ATOM(onratechange, "onratechange") GK_ATOM(onratechange, "onratechange")
@ -1586,7 +1584,7 @@ GK_ATOM(onvolumechange, "onvolumechange")
GK_ATOM(loadstart, "loadstart") GK_ATOM(loadstart, "loadstart")
GK_ATOM(progress, "progress") GK_ATOM(progress, "progress")
GK_ATOM(loadedmetadata, "loadedmetadata") GK_ATOM(loadedmetadata, "loadedmetadata")
GK_ATOM(loadedfirstframe, "loadedfirstframe") GK_ATOM(loadeddata, "loadeddata")
GK_ATOM(emptied, "emptied") GK_ATOM(emptied, "emptied")
GK_ATOM(stalled, "stalled") GK_ATOM(stalled, "stalled")
GK_ATOM(play, "play") GK_ATOM(play, "play")
@ -1596,8 +1594,6 @@ GK_ATOM(seeking, "seeking")
GK_ATOM(seeked, "seeked") GK_ATOM(seeked, "seeked")
GK_ATOM(timeupdate, "timeupdate") GK_ATOM(timeupdate, "timeupdate")
GK_ATOM(ended, "ended") GK_ATOM(ended, "ended")
GK_ATOM(dataunavailable, "dataunavailable")
GK_ATOM(canshowcurrentframe, "canshowcurrentframe")
GK_ATOM(canplay, "canplay") GK_ATOM(canplay, "canplay")
GK_ATOM(canplaythrough, "canplaythrough") GK_ATOM(canplaythrough, "canplaythrough")
GK_ATOM(ratechange, "ratechange") GK_ATOM(ratechange, "ratechange")

Просмотреть файл

@ -46,9 +46,11 @@
#define nsImageLoadingContent_h__ #define nsImageLoadingContent_h__
#include "nsIImageLoadingContent.h" #include "nsIImageLoadingContent.h"
#include "nsINode.h"
#include "imgIRequest.h" #include "imgIRequest.h"
#include "prtypes.h" #include "prtypes.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsContentUtils.h"
#include "nsString.h" #include "nsString.h"
class nsIURI; class nsIURI;
@ -163,7 +165,7 @@ private:
~ImageObserver() ~ImageObserver()
{ {
MOZ_COUNT_DTOR(ImageObserver); MOZ_COUNT_DTOR(ImageObserver);
delete mNext; NS_CONTENT_DELETE_LIST_MEMBER(ImageObserver, this, mNext);
} }
nsCOMPtr<imgIDecoderObserver> mObserver; nsCOMPtr<imgIDecoderObserver> mObserver;

Просмотреть файл

@ -44,7 +44,6 @@
#include "nsScriptLoader.h" #include "nsScriptLoader.h"
#include "nsIDOMCharacterData.h" #include "nsIDOMCharacterData.h"
#include "nsParserUtils.h" #include "nsParserUtils.h"
#include "nsIMIMEHeaderParam.h"
#include "nsICharsetConverterManager.h" #include "nsICharsetConverterManager.h"
#include "nsIUnicodeDecoder.h" #include "nsIUnicodeDecoder.h"
#include "nsIContent.h" #include "nsIContent.h"
@ -331,16 +330,10 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// If type exists, it trumps the deprecated 'language=' // If type exists, it trumps the deprecated 'language='
aElement->GetScriptType(type); aElement->GetScriptType(type);
if (!type.IsEmpty()) { if (!type.IsEmpty()) {
nsCOMPtr<nsIMIMEHeaderParam> mimeHdrParser = nsContentTypeParser parser(type);
do_GetService("@mozilla.org/network/mime-hdrparam;1");
NS_ENSURE_TRUE(mimeHdrParser, NS_ERROR_FAILURE);
NS_ConvertUTF16toUTF8 typeAndParams(type);
nsAutoString mimeType; nsAutoString mimeType;
rv = mimeHdrParser->GetParameter(typeAndParams, nsnull, rv = parser.GetType(mimeType);
EmptyCString(), PR_FALSE, nsnull,
mimeType);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Javascript keeps the fast path, optimized for most-likely type // Javascript keeps the fast path, optimized for most-likely type
@ -379,9 +372,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
if (typeID != nsIProgrammingLanguage::UNKNOWN) { if (typeID != nsIProgrammingLanguage::UNKNOWN) {
// Get the version string, and ensure the language supports it. // Get the version string, and ensure the language supports it.
nsAutoString versionName; nsAutoString versionName;
rv = mimeHdrParser->GetParameter(typeAndParams, "version", rv = parser.GetParameter("version", versionName);
EmptyCString(), PR_FALSE, nsnull,
versionName);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
// no version attribute - version remains 0. // no version attribute - version remains 0.
if (rv != NS_ERROR_INVALID_ARG) if (rv != NS_ERROR_INVALID_ARG)
@ -404,10 +395,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// Some js specifics yet to be abstracted. // Some js specifics yet to be abstracted.
if (typeID == nsIProgrammingLanguage::JAVASCRIPT) { if (typeID == nsIProgrammingLanguage::JAVASCRIPT) {
nsAutoString value; nsAutoString value;
rv = parser.GetParameter("e4x", value);
rv = mimeHdrParser->GetParameter(typeAndParams, "e4x",
EmptyCString(), PR_FALSE, nsnull,
value);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
if (rv != NS_ERROR_INVALID_ARG) if (rv != NS_ERROR_INVALID_ARG)
return rv; return rv;

Просмотреть файл

@ -458,8 +458,15 @@ nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
nsresult rv; nsresult rv;
nsCOMPtr<nsIInputStream> bufferedStream; nsCOMPtr<nsIInputStream> bufferedStream;
if (!NS_InputStreamIsBuffered(aIn)) { if (!NS_InputStreamIsBuffered(aIn)) {
PRInt32 chunkSize;
rv = aChannel->GetContentLength(&chunkSize);
if (NS_FAILED(rv)) {
chunkSize = 4096;
}
chunkSize = PR_MIN(PR_UINT16_MAX, chunkSize);
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), aIn, rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), aIn,
4096); chunkSize);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
aIn = bufferedStream; aIn = bufferedStream;

Просмотреть файл

@ -1967,13 +1967,17 @@ nsCanvasRenderingContext2D::SetFont(const nsAString& font)
// un-zoom the font size to avoid being affected by text-only zoom // un-zoom the font size to avoid being affected by text-only zoom
const nscoord fontSize = nsStyleFont::UnZoomText(parentContext->PresContext(), fontStyle->mFont.size); const nscoord fontSize = nsStyleFont::UnZoomText(parentContext->PresContext(), fontStyle->mFont.size);
PRBool printerFont = (presShell->GetPresContext()->Type() == nsPresContext::eContext_PrintPreview ||
presShell->GetPresContext()->Type() == nsPresContext::eContext_Print);
gfxFontStyle style(fontStyle->mFont.style, gfxFontStyle style(fontStyle->mFont.style,
fontStyle->mFont.weight, fontStyle->mFont.weight,
NSAppUnitsToFloatPixels(fontSize, aupcp), NSAppUnitsToFloatPixels(fontSize, aupcp),
langGroup, langGroup,
fontStyle->mFont.sizeAdjust, fontStyle->mFont.sizeAdjust,
fontStyle->mFont.systemFont, fontStyle->mFont.systemFont,
fontStyle->mFont.familyNameQuirks); fontStyle->mFont.familyNameQuirks,
printerFont);
CurrentState().fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(fontStyle->mFont.name, &style, presShell->GetPresContext()->GetUserFontSet()); CurrentState().fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(fontStyle->mFont.name, &style, presShell->GetPresContext()->GetUserFontSet());
NS_ASSERTION(CurrentState().fontGroup, "Could not get font group"); NS_ASSERTION(CurrentState().fontGroup, "Could not get font group");

Просмотреть файл

@ -49,6 +49,9 @@
class nsIPrivateTextRange : public nsISupports { class nsIPrivateTextRange : public nsISupports {
public: public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IPRIVATETEXTRANGE_IID) NS_DECLARE_STATIC_IID_ACCESSOR(NS_IPRIVATETEXTRANGE_IID)
// Note that the range array may not specify a caret position; in that
// case there will be no range of type TEXTRANGE_CARETPOSITION in the array.
enum { enum {
TEXTRANGE_CARETPOSITION = 1, TEXTRANGE_CARETPOSITION = 1,
TEXTRANGE_RAWINPUT = 2, TEXTRANGE_RAWINPUT = 2,

Просмотреть файл

@ -77,11 +77,10 @@ static const char* const sEventNames[] = {
"SVGZoom", "SVGZoom",
#endif // MOZ_SVG #endif // MOZ_SVG
#ifdef MOZ_MEDIA #ifdef MOZ_MEDIA
"loadstart", "progress", "loadedmetadata", "loadedfirstframe", "loadstart", "progress", "loadedmetadata", "loadeddata",
"emptied", "stalled", "play", "pause", "emptied", "stalled", "play", "pause",
"waiting", "seeking", "seeked", "timeupdate", "ended", "dataunavailable", "waiting", "seeking", "seeked", "timeupdate", "ended",
"canshowcurrentframe", "canplay", "canplaythrough", "ratechange", "canplay", "canplaythrough", "ratechange", "durationchange", "volumechange",
"durationchange", "volumechange",
#endif // MOZ_MEDIA #endif // MOZ_MEDIA
"MozAfterPaint", "MozAfterPaint",
"MozSwipeGesture", "MozSwipeGesture",
@ -616,8 +615,8 @@ nsDOMEvent::SetEventType(const nsAString& aEventTypeArg)
mEvent->message = NS_PROGRESS; mEvent->message = NS_PROGRESS;
else if (atom == nsGkAtoms::onloadedmetadata) else if (atom == nsGkAtoms::onloadedmetadata)
mEvent->message = NS_LOADEDMETADATA; mEvent->message = NS_LOADEDMETADATA;
else if (atom == nsGkAtoms::onloadedfirstframe) else if (atom == nsGkAtoms::onloadeddata)
mEvent->message = NS_LOADEDFIRSTFRAME; mEvent->message = NS_LOADEDDATA;
else if (atom == nsGkAtoms::onemptied) else if (atom == nsGkAtoms::onemptied)
mEvent->message = NS_EMPTIED; mEvent->message = NS_EMPTIED;
else if (atom == nsGkAtoms::onstalled) else if (atom == nsGkAtoms::onstalled)
@ -636,10 +635,6 @@ nsDOMEvent::SetEventType(const nsAString& aEventTypeArg)
mEvent->message = NS_TIMEUPDATE; mEvent->message = NS_TIMEUPDATE;
else if (atom == nsGkAtoms::onended) else if (atom == nsGkAtoms::onended)
mEvent->message = NS_ENDED; mEvent->message = NS_ENDED;
else if (atom == nsGkAtoms::ondataunavailable)
mEvent->message = NS_DATAUNAVAILABLE;
else if (atom == nsGkAtoms::oncanshowcurrentframe)
mEvent->message = NS_CANSHOWCURRENTFRAME;
else if (atom == nsGkAtoms::oncanplay) else if (atom == nsGkAtoms::oncanplay)
mEvent->message = NS_CANPLAY; mEvent->message = NS_CANPLAY;
else if (atom == nsGkAtoms::oncanplaythrough) else if (atom == nsGkAtoms::oncanplaythrough)
@ -1479,8 +1474,8 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
return sEventNames[eDOMEvents_progress]; return sEventNames[eDOMEvents_progress];
case NS_LOADEDMETADATA: case NS_LOADEDMETADATA:
return sEventNames[eDOMEvents_loadedmetadata]; return sEventNames[eDOMEvents_loadedmetadata];
case NS_LOADEDFIRSTFRAME: case NS_LOADEDDATA:
return sEventNames[eDOMEvents_loadedfirstframe]; return sEventNames[eDOMEvents_loadeddata];
case NS_EMPTIED: case NS_EMPTIED:
return sEventNames[eDOMEvents_emptied]; return sEventNames[eDOMEvents_emptied];
case NS_STALLED: case NS_STALLED:
@ -1499,10 +1494,6 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
return sEventNames[eDOMEvents_timeupdate]; return sEventNames[eDOMEvents_timeupdate];
case NS_ENDED: case NS_ENDED:
return sEventNames[eDOMEvents_ended]; return sEventNames[eDOMEvents_ended];
case NS_DATAUNAVAILABLE:
return sEventNames[eDOMEvents_dataunavailable];
case NS_CANSHOWCURRENTFRAME:
return sEventNames[eDOMEvents_canshowcurrentframe];
case NS_CANPLAY: case NS_CANPLAY:
return sEventNames[eDOMEvents_canplay]; return sEventNames[eDOMEvents_canplay];
case NS_CANPLAYTHROUGH: case NS_CANPLAYTHROUGH:

Просмотреть файл

@ -143,7 +143,7 @@ public:
eDOMEvents_loadstart, eDOMEvents_loadstart,
eDOMEvents_progress, eDOMEvents_progress,
eDOMEvents_loadedmetadata, eDOMEvents_loadedmetadata,
eDOMEvents_loadedfirstframe, eDOMEvents_loadeddata,
eDOMEvents_emptied, eDOMEvents_emptied,
eDOMEvents_stalled, eDOMEvents_stalled,
eDOMEvents_play, eDOMEvents_play,
@ -153,8 +153,6 @@ public:
eDOMEvents_seeked, eDOMEvents_seeked,
eDOMEvents_timeupdate, eDOMEvents_timeupdate,
eDOMEvents_ended, eDOMEvents_ended,
eDOMEvents_dataunavailable,
eDOMEvents_canshowcurrentframe,
eDOMEvents_canplay, eDOMEvents_canplay,
eDOMEvents_canplaythrough, eDOMEvents_canplaythrough,
eDOMEvents_ratechange, eDOMEvents_ratechange,

Просмотреть файл

@ -57,8 +57,6 @@ private:
nsEventTargetChainItem(nsPIDOMEventTarget* aTarget, nsEventTargetChainItem(nsPIDOMEventTarget* aTarget,
nsEventTargetChainItem* aChild = nsnull); nsEventTargetChainItem* aChild = nsnull);
void Destroy(nsFixedSizeAllocator* aAllocator);
public: public:
static nsEventTargetChainItem* Create(nsFixedSizeAllocator* aAllocator, static nsEventTargetChainItem* Create(nsFixedSizeAllocator* aAllocator,
nsPIDOMEventTarget* aTarget, nsPIDOMEventTarget* aTarget,
@ -73,9 +71,18 @@ public:
static void Destroy(nsFixedSizeAllocator* aAllocator, static void Destroy(nsFixedSizeAllocator* aAllocator,
nsEventTargetChainItem* aItem) nsEventTargetChainItem* aItem)
{ {
aItem->Destroy(aAllocator); // ::Destroy deletes ancestor chain.
aItem->~nsEventTargetChainItem(); nsEventTargetChainItem* item = aItem;
aAllocator->Free(aItem, sizeof(nsEventTargetChainItem)); if (item->mChild) {
item->mChild->mParent = nsnull;
item->mChild = nsnull;
}
while (item) {
nsEventTargetChainItem* parent = item->mParent;
item->~nsEventTargetChainItem();
aAllocator->Free(item, sizeof(nsEventTargetChainItem));
item = parent;
}
} }
PRBool IsValid() PRBool IsValid()
@ -181,22 +188,6 @@ nsEventTargetChainItem::nsEventTargetChainItem(nsPIDOMEventTarget* aTarget,
} }
} }
void
nsEventTargetChainItem::Destroy(nsFixedSizeAllocator* aAllocator)
{
if (mChild) {
mChild->mParent = nsnull;
mChild = nsnull;
}
if (mParent) {
Destroy(aAllocator, mParent);
mParent = nsnull;
}
mTarget = nsnull;
}
nsresult nsresult
nsEventTargetChainItem::PreHandleEvent(nsEventChainPreVisitor& aVisitor) nsEventTargetChainItem::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{ {

Просмотреть файл

@ -4497,6 +4497,8 @@ nsEventStateManager::GetNextTabbableMapArea(PRBool aForward,
nsCOMPtr<nsIDocument> doc = aImageContent->GetDocument(); nsCOMPtr<nsIDocument> doc = aImageContent->GetDocument();
if (doc) { if (doc) {
nsCOMPtr<nsIDOMHTMLMapElement> imageMap = nsImageMapUtils::FindImageMap(doc, useMap); nsCOMPtr<nsIDOMHTMLMapElement> imageMap = nsImageMapUtils::FindImageMap(doc, useMap);
if (!imageMap)
return nsnull;
nsCOMPtr<nsIContent> mapContent = do_QueryInterface(imageMap); nsCOMPtr<nsIContent> mapContent = do_QueryInterface(imageMap);
PRUint32 count = mapContent->GetChildCount(); PRUint32 count = mapContent->GetChildCount();
// First see if mCurrentFocus is in this map // First see if mCurrentFocus is in this map

Просмотреть файл

@ -62,6 +62,7 @@ _TEST_FILES = \
test_bug412567.html \ test_bug412567.html \
test_bug443985.html \ test_bug443985.html \
test_bug447736.html \ test_bug447736.html \
test_bug450876.html \
test_bug456273.html \ test_bug456273.html \
test_bug457672.html \ test_bug457672.html \
test_bug428988.html \ test_bug428988.html \

Просмотреть файл

@ -117,23 +117,23 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
utils.sendKeyEvent("keyup", key, 0, modifier); utils.sendKeyEvent("keyup", key, 0, modifier);
if (shouldStop) { if (shouldStop) {
// Did focus handling succeed // Did focus handling succeed
ok(forwardFocusArray.length == 0, is(forwardFocusArray.length, 0,
"Not all forward tabbing focus tests were run, " + "Not all forward tabbing focus tests were run, " +
forwardFocusArray.toString()); forwardFocusArray.toString());
ok(backwardFocusArray.length == 0, is(backwardFocusArray.length, 0,
"Not all backward tabbing focus tests were run, " + "Not all backward tabbing focus tests were run, " +
backwardFocusArray.toString()); backwardFocusArray.toString());
ok(expectedWindowFocusCount == 0, is(expectedWindowFocusCount, 0,
"|window| didn't get the right amount of focus events"); "|window| didn't get the right amount of focus events");
// and blur. // and blur.
ok(forwardBlurArray.length == 0, is(forwardBlurArray.length, 0,
"Not all forward tabbing blur tests were run, " + "Not all forward tabbing blur tests were run, " +
forwardBlurArray.toString()); forwardBlurArray.toString());
ok(backwardBlurArray.length == 0, is(backwardBlurArray.length, 0,
"Not all backward tabbing blur tests were run, " + "Not all backward tabbing blur tests were run, " +
backwardBlurArray.toString()); backwardBlurArray.toString());
ok(expectedWindowBlurCount == 0, is(expectedWindowBlurCount, 0,
"|window| didn't get the right amount of blur events"); "|window| didn't get the right amount of blur events");
setOrRestoreTabFocus(0); setOrRestoreTabFocus(0);
SimpleTest.finish(); SimpleTest.finish();
@ -154,6 +154,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
elements[i].addEventListener("focus", handleFocus, false); elements[i].addEventListener("focus", handleFocus, false);
elements[i].addEventListener("blur", handleBlur, false); elements[i].addEventListener("blur", handleBlur, false);
} }
if (elements[i].getAttribute("tabindex") == "1") {
elements[i].setAttribute("tabindex", "-1");
}
} }
tab(); tab();
} }
@ -206,6 +209,73 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
<tr> <tr>
<td>tabindex="0"</td><td><span tabindex="0" id="i12">span</span></td> <td>tabindex="0"</td><td><span tabindex="0" id="i12">span</span></td>
</tr> </tr>
<tr>
<td><h3>Form elements with tabindex="-1"</h3></td>
</tr>
<tr>
<td>type="text"</td><td><input type="text" tabindex="-1" value=""></td>
</tr>
<tr>
<td>type="button"</td><td><input type="button" tabindex="-1" value="type='button'"></td>
</tr>
<tr>
<td>type="checkbox"</td><td><input type="checkbox" tabindex="-1"></td>
</tr>
<tr>
<td>type="radio" checked</td><td><input type="radio" tabindex="-1" name="radio3" checked>
<input type="radio" tabindex="-1" name="radio3"></td>
</tr>
<tr>
<td>type="radio"</td><td><input type="radio" tabindex="-1" name="radio4">
<input type="radio" tabindex="-1" name="radio4"></td>
</tr>
<tr>
<td>type="password"</td><td><input type="password" tabindex="-1"></td>
</tr>
<tr>
<td>type="file"</td><td><input type="file" tabindex="-1"></td>
</tr>
<tr>
<td>button</td><td><button tabindex="-1">button</button></td>
</tr>
<tr>
<td>select</td><td><select tabindex="-1"><option>select</option></select></td>
</tr>
<tr>
<td><h3>Form elements with .setAttribute("tabindex", "-1")</h3></td>
</tr>
<tr>
<td>type="text"</td><td><input type="text" tabindex="1" value=""></td>
</tr>
<tr>
<td>type="button"</td><td><input type="button" tabindex="1" value="type='button'"></td>
</tr>
<tr>
<td>type="checkbox"</td><td><input type="checkbox" tabindex="1"></td>
</tr>
<tr>
<td>type="radio" checked</td><td><input type="radio" tabindex="1" name="radio5" checked>
<input type="radio" tabindex="1" name="radio5"></td>
</tr>
<tr>
<td>type="radio"</td><td><input type="radio" tabindex="1" name="radio6">
<input type="radio" tabindex="1" name="radio6"></td>
</tr>
<tr>
<td>type="password"</td><td><input type="password" tabindex="1"></td>
</tr>
<tr>
<td>type="file"</td><td><input type="file" tabindex="1"></td>
</tr>
<tr>
<td>button</td><td><button tabindex="1">button</button></td>
</tr>
<tr>
<td>select</td><td><select tabindex="1"><option>select</option></select></td>
</tr>
</tbody> </tbody>
</table> </table>
<h4 tabindex="0" id="end">done.</h4> <h4 tabindex="0" id="end">done.</h4>

Просмотреть файл

@ -0,0 +1,43 @@
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=450876
-->
<head>
<title>Test for Bug 450876 - Crash [@ nsEventStateManager::GetNextTabbableMapArea] with img usemap and tabindex</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=450876">Mozilla Bug 450876</a>
<p id="display"><a href="#" id="a">link to focus from</a><img usemap="#a" tabindex="1"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 450876 **/
function doTest() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
is(document.activeElement, document.body, "body element should be focused");
document.getElementById('a').focus();
is(document.activeElement, document.getElementById('a'), "link should have focus");
var wu = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
wu.sendKeyEvent('keypress', 9, 0, 0);
is(document.activeElement, document.body, "body element should be focused");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doTest);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -138,9 +138,9 @@ public:
// events can be fired. // events can be fired.
void ChangeReadyState(nsMediaReadyState aState); void ChangeReadyState(nsMediaReadyState aState);
// Is the media element actively playing as defined by the HTML 5 specification. // Is the media element potentially playing as defined by the HTML 5 specification.
// http://www.whatwg.org/specs/web-apps/current-work/#actively // http://www.whatwg.org/specs/web-apps/current-work/#potentially-playing
PRBool IsActivelyPlaying() const; PRBool IsPotentiallyPlaying() const;
// Has playback ended as defined by the HTML 5 specification. // Has playback ended as defined by the HTML 5 specification.
// http://www.whatwg.org/specs/web-apps/current-work/#ended // http://www.whatwg.org/specs/web-apps/current-work/#ended
@ -159,8 +159,14 @@ public:
void Thaw(); void Thaw();
// Returns true if we can handle this MIME type in a <video> or <audio> // Returns true if we can handle this MIME type in a <video> or <audio>
// element // element.
static PRBool CanHandleMediaType(const char* aMIMEType); // If it returns true, then it also returns a null-terminated list
// of supported codecs in *aSupportedCodecs, and a null-terminated list
// of codecs that *may* be supported in *aMaybeSupportedCodecs. These
// lists should not be freed, they area static data.
static PRBool CanHandleMediaType(const char* aMIMEType,
const char*** aSupportedCodecs,
const char*** aMaybeSupportedCodecs);
/** /**
* Initialize data for available media types * Initialize data for available media types
@ -172,29 +178,39 @@ public:
static void ShutdownMediaTypes(); static void ShutdownMediaTypes();
protected: protected:
class nsMediaLoadListener;
/** /**
* Figure out which resource to load (either the 'src' attribute or * Figure out which resource to load (either the 'src' attribute or a
* a <source> child) and create the decoder for it. * <source> child) and return the associated URI.
*/ */
nsresult PickMediaElement(); nsresult PickMediaElement(nsIURI** aURI);
/** /**
* Create a decoder for the given aMIMEType. Returns false if we * Create a decoder for the given aMIMEType. Returns false if we
* were unable to create the decoder. * were unable to create the decoder.
*/ */
PRBool CreateDecoder(const nsACString& aMIMEType); PRBool CreateDecoder(const nsACString& aMIMEType);
/**
* Initialize a decoder to load the given URI.
*/
nsresult InitializeDecoder(const nsAString& aURISpec);
/** /**
* Initialize a decoder to load the given channel. The decoder's stream * Initialize a decoder to load the given channel. The decoder's stream
* listener is returned via aListener. * listener is returned via aListener.
*/ */
nsresult InitializeDecoderForChannel(nsIChannel *aChannel, nsresult InitializeDecoderForChannel(nsIChannel *aChannel,
nsIStreamListener **aListener); nsIStreamListener **aListener);
/**
* Execute the initial steps of the load algorithm that ensure existing
* loads are aborted and the element is emptied. Returns true if aborted,
* false if emptied.
*/
PRBool AbortExistingLoads();
/**
* Create a URI for the given aURISpec string.
*/
nsresult NewURIFromString(const nsAutoString& aURISpec, nsIURI** aURI);
nsRefPtr<nsMediaDecoder> mDecoder; nsRefPtr<nsMediaDecoder> mDecoder;
nsCOMPtr<nsIChannel> mChannel;
// Error attribute // Error attribute
nsCOMPtr<nsIDOMHTMLMediaError> mError; nsCOMPtr<nsIDOMHTMLMediaError> mError;
@ -250,4 +266,8 @@ protected:
// to ensure that the playstate doesn't change when the user goes Forward/Back // to ensure that the playstate doesn't change when the user goes Forward/Back
// from the bfcache. // from the bfcache.
PRPackedBool mPausedBeforeFreeze; PRPackedBool mPausedBeforeFreeze;
// True if playback was requested before a decoder was available to begin
// playback with.
PRPackedBool mPlayRequested;
}; };

Просмотреть файл

@ -55,6 +55,7 @@
#include "nsXPCOMStrings.h" #include "nsXPCOMStrings.h"
#include "prlock.h" #include "prlock.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsContentUtils.h"
#include "nsIScriptSecurityManager.h" #include "nsIScriptSecurityManager.h"
#include "nsIXPConnect.h" #include "nsIXPConnect.h"
@ -68,6 +69,7 @@
#include "nsIDOMProgressEvent.h" #include "nsIDOMProgressEvent.h"
#include "nsHTMLMediaError.h" #include "nsHTMLMediaError.h"
#include "nsICategoryManager.h" #include "nsICategoryManager.h"
#include "nsCommaSeparatedTokenizer.h"
#ifdef MOZ_OGG #ifdef MOZ_OGG
#include "nsOggDecoder.h" #include "nsOggDecoder.h"
@ -96,6 +98,67 @@ public:
} }
}; };
class nsHTMLMediaElement::nsMediaLoadListener : public nsIStreamListener
{
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
public:
nsMediaLoadListener(nsHTMLMediaElement* aElement)
: mElement(aElement)
{
NS_ABORT_IF_FALSE(mElement, "Must pass an element to call back");
}
private:
nsRefPtr<nsHTMLMediaElement> mElement;
nsCOMPtr<nsIStreamListener> mNextListener;
};
NS_IMPL_ISUPPORTS2(nsHTMLMediaElement::nsMediaLoadListener, nsIRequestObserver, nsIStreamListener)
NS_IMETHODIMP nsHTMLMediaElement::nsMediaLoadListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
{
nsresult rv;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
if (channel &&
mElement &&
NS_SUCCEEDED(mElement->InitializeDecoderForChannel(channel, getter_AddRefs(mNextListener))) &&
mNextListener) {
rv = mNextListener->OnStartRequest(aRequest, aContext);
} else {
// If InitializeDecoderForChannel did not return a listener, we abort
// the connection since we aren't interested in keeping the channel
// alive ourselves.
rv = NS_BINDING_ABORTED;
}
// The element is only needed until we've had a chance to call
// InitializeDecoderForChannel.
mElement = nsnull;
return rv;
}
NS_IMETHODIMP nsHTMLMediaElement::nsMediaLoadListener::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
nsresult aStatus)
{
if (mNextListener) {
return mNextListener->OnStopRequest(aRequest, aContext, aStatus);
}
return NS_OK;
}
NS_IMETHODIMP nsHTMLMediaElement::nsMediaLoadListener::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
nsIInputStream* aStream, PRUint32 aOffset,
PRUint32 aCount)
{
NS_ABORT_IF_FALSE(mNextListener, "Must have a listener");
return mNextListener->OnDataAvailable(aRequest, aContext, aStream, aOffset, aCount);
}
// nsIDOMHTMLMediaElement // nsIDOMHTMLMediaElement
NS_IMPL_URI_ATTR(nsHTMLMediaElement, Src, src) NS_IMPL_URI_ATTR(nsHTMLMediaElement, Src, src)
NS_IMPL_BOOL_ATTR(nsHTMLMediaElement, Controls, controls) NS_IMPL_BOOL_ATTR(nsHTMLMediaElement, Controls, controls)
@ -143,28 +206,19 @@ NS_IMETHODIMP nsHTMLMediaElement::GetNetworkState(PRUint16 *aNetworkState)
return NS_OK; return NS_OK;
} }
/* void load (); */ PRBool nsHTMLMediaElement::AbortExistingLoads()
NS_IMETHODIMP nsHTMLMediaElement::Load()
{ {
return LoadWithChannel(nsnull, nsnull); if (mDecoder) {
} mDecoder->ElementUnavailable();
mDecoder->Shutdown();
nsresult nsHTMLMediaElement::LoadWithChannel(nsIChannel *aChannel, mDecoder = nsnull;
nsIStreamListener **aListener)
{
NS_ASSERTION((aChannel == nsnull) == (aListener == nsnull),
"channel and listener should both be null or both non-null");
if (aListener) {
*aListener = nsnull;
} }
if (mBegun) { if (mBegun) {
mBegun = PR_FALSE; mBegun = PR_FALSE;
mError = new nsHTMLMediaError(nsHTMLMediaError::MEDIA_ERR_ABORTED); mError = new nsHTMLMediaError(nsHTMLMediaError::MEDIA_ERR_ABORTED);
DispatchProgressEvent(NS_LITERAL_STRING("abort")); DispatchProgressEvent(NS_LITERAL_STRING("abort"));
return NS_OK; return PR_TRUE;
} }
mError = nsnull; mError = nsnull;
@ -173,23 +227,95 @@ nsresult nsHTMLMediaElement::LoadWithChannel(nsIChannel *aChannel,
// TODO: The playback rate must be set to the default playback rate. // TODO: The playback rate must be set to the default playback rate.
if (mNetworkState != nsIDOMHTMLMediaElement::EMPTY) { if (mNetworkState != nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
mNetworkState = nsIDOMHTMLMediaElement::EMPTY; mNetworkState = nsIDOMHTMLMediaElement::NETWORK_EMPTY;
ChangeReadyState(nsIDOMHTMLMediaElement::DATA_UNAVAILABLE); ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING);
mPaused = PR_TRUE; mPaused = PR_TRUE;
// TODO: The current playback position must be set to 0. // TODO: The current playback position must be set to 0.
// TODO: The currentLoop DOM attribute must be set to 0. // TODO: The currentLoop DOM attribute must be set to 0.
DispatchSimpleEvent(NS_LITERAL_STRING("emptied")); DispatchSimpleEvent(NS_LITERAL_STRING("emptied"));
} }
nsresult rv; return PR_FALSE;
if (aChannel) { }
rv = InitializeDecoderForChannel(aChannel, aListener);
} else { /* void load (); */
rv = PickMediaElement(); NS_IMETHODIMP nsHTMLMediaElement::Load()
{
if (AbortExistingLoads())
return NS_OK;
nsCOMPtr<nsIURI> uri;
nsresult rv = PickMediaElement(getter_AddRefs(uri));
if (NS_FAILED(rv))
return rv;
if (mChannel) {
mChannel->Cancel(NS_BINDING_ABORTED);
mChannel = nsnull;
} }
rv = NS_NewChannel(getter_AddRefs(mChannel),
uri,
nsnull,
nsnull,
nsnull,
nsIRequest::LOAD_NORMAL);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// The listener holds a strong reference to us. This creates a reference
// cycle which is manually broken in the listener's OnStartRequest method
// after it is finished with the element.
nsCOMPtr<nsIStreamListener> listener = new nsMediaLoadListener(this);
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIHttpChannel> hc = do_QueryInterface(mChannel);
if (hc) {
// Use a byte range request from the start of the resource.
// This enables us to detect if the stream supports byte range
// requests, and therefore seeking, early.
hc->SetRequestHeader(NS_LITERAL_CSTRING("Range"),
NS_LITERAL_CSTRING("bytes=0-"),
PR_FALSE);
}
rv = mChannel->AsyncOpen(listener, nsnull);
if (NS_FAILED(rv)) {
// OnStartRequest is guaranteed to be called if the open succeeds. If
// the open failed, the listener's OnStartRequest will never be called,
// so we need to break the element->channel->listener->element reference
// cycle here. The channel holds the only reference to the listener,
// and is useless now anyway, so drop our reference to it to allow it to
// be destroyed.
mChannel = nsnull;
return rv;
}
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
mBegun = PR_TRUE;
DispatchAsyncProgressEvent(NS_LITERAL_STRING("loadstart"));
return NS_OK;
}
nsresult nsHTMLMediaElement::LoadWithChannel(nsIChannel *aChannel,
nsIStreamListener **aListener)
{
NS_ENSURE_ARG_POINTER(aChannel);
NS_ENSURE_ARG_POINTER(aListener);
*aListener = nsnull;
if (AbortExistingLoads())
return NS_OK;
nsresult rv = InitializeDecoderForChannel(aChannel, aListener);
if (NS_FAILED(rv)) {
return rv;
}
mBegun = PR_TRUE; mBegun = PR_TRUE;
DispatchAsyncProgressEvent(NS_LITERAL_STRING("loadstart")); DispatchAsyncProgressEvent(NS_LITERAL_STRING("loadstart"));
@ -229,10 +355,10 @@ NS_IMETHODIMP nsHTMLMediaElement::SetCurrentTime(float aCurrentTime)
if (!(aCurrentTime >= 0.0)) if (!(aCurrentTime >= 0.0))
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
if (mNetworkState < nsIDOMHTMLMediaElement::LOADED_METADATA) if (mReadyState == nsIDOMHTMLMediaElement::HAVE_NOTHING)
return NS_ERROR_DOM_INVALID_STATE_ERR; return NS_ERROR_DOM_INVALID_STATE_ERR;
mPlayingBeforeSeek = IsActivelyPlaying(); mPlayingBeforeSeek = IsPotentiallyPlaying();
// The media backend is responsible for dispatching the timeupdate // The media backend is responsible for dispatching the timeupdate
// event if it changes the playback position as a result of the seek. // event if it changes the playback position as a result of the seek.
nsresult rv = mDecoder->Seek(aCurrentTime); nsresult rv = mDecoder->Seek(aCurrentTime);
@ -262,7 +388,7 @@ NS_IMETHODIMP nsHTMLMediaElement::Pause()
nsresult rv; nsresult rv;
if (mNetworkState == nsIDOMHTMLMediaElement::EMPTY) { if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
rv = Load(); rv = Load();
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
@ -337,8 +463,8 @@ NS_IMETHODIMP nsHTMLMediaElement::SetMuted(PRBool aMuted)
nsHTMLMediaElement::nsHTMLMediaElement(nsINodeInfo *aNodeInfo, PRBool aFromParser) nsHTMLMediaElement::nsHTMLMediaElement(nsINodeInfo *aNodeInfo, PRBool aFromParser)
: nsGenericHTMLElement(aNodeInfo), : nsGenericHTMLElement(aNodeInfo),
mNetworkState(nsIDOMHTMLMediaElement::EMPTY), mNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY),
mReadyState(nsIDOMHTMLMediaElement::DATA_UNAVAILABLE), mReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING),
mMutedVolume(0.0), mMutedVolume(0.0),
mMediaSize(-1,-1), mMediaSize(-1,-1),
mBegun(PR_FALSE), mBegun(PR_FALSE),
@ -347,7 +473,8 @@ nsHTMLMediaElement::nsHTMLMediaElement(nsINodeInfo *aNodeInfo, PRBool aFromParse
mPaused(PR_TRUE), mPaused(PR_TRUE),
mMuted(PR_FALSE), mMuted(PR_FALSE),
mIsDoneAddingChildren(!aFromParser), mIsDoneAddingChildren(!aFromParser),
mPlayingBeforeSeek(PR_FALSE) mPlayingBeforeSeek(PR_FALSE),
mPlayRequested(PR_FALSE)
{ {
} }
@ -357,19 +484,24 @@ nsHTMLMediaElement::~nsHTMLMediaElement()
mDecoder->Shutdown(); mDecoder->Shutdown();
mDecoder = nsnull; mDecoder = nsnull;
} }
if (mChannel) {
mChannel->Cancel(NS_BINDING_ABORTED);
mChannel = nsnull;
}
} }
NS_IMETHODIMP NS_IMETHODIMP nsHTMLMediaElement::Play()
nsHTMLMediaElement::Play(void)
{ {
if (!mDecoder) if (!mDecoder) {
mPlayRequested = PR_TRUE;
return NS_OK; return NS_OK;
}
nsresult rv; nsresult rv;
if (mNetworkState == nsIDOMHTMLMediaElement::EMPTY) { if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
rv = Load(); mPlayRequested = PR_TRUE;
NS_ENSURE_SUCCESS(rv, rv); return Load();
} }
if (mDecoder->IsEnded()) { if (mDecoder->IsEnded()) {
@ -392,8 +524,7 @@ nsHTMLMediaElement::Play(void)
return NS_OK; return NS_OK;
} }
PRBool PRBool nsHTMLMediaElement::ParseAttribute(PRInt32 aNamespaceID,
nsHTMLMediaElement::ParseAttribute(PRInt32 aNamespaceID,
nsIAtom* aAttribute, nsIAtom* aAttribute,
const nsAString& aValue, const nsAString& aValue,
nsAttrValue& aResult) nsAttrValue& aResult)
@ -419,8 +550,7 @@ nsHTMLMediaElement::ParseAttribute(PRInt32 aNamespaceID,
aResult); aResult);
} }
nsresult nsresult nsHTMLMediaElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsHTMLMediaElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue, nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify) PRBool aNotify)
{ {
@ -447,7 +577,7 @@ nsresult nsHTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aPar
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (mIsDoneAddingChildren && if (mIsDoneAddingChildren &&
mNetworkState == nsIDOMHTMLMediaElement::EMPTY) { mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
Load(); Load();
} }
@ -457,19 +587,31 @@ nsresult nsHTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aPar
void nsHTMLMediaElement::UnbindFromTree(PRBool aDeep, void nsHTMLMediaElement::UnbindFromTree(PRBool aDeep,
PRBool aNullParent) PRBool aNullParent)
{ {
if (!mPaused && mNetworkState != nsIDOMHTMLMediaElement::EMPTY) if (!mPaused && mNetworkState != nsIDOMHTMLMediaElement::NETWORK_EMPTY)
Pause(); Pause();
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
} }
#ifdef MOZ_OGG #ifdef MOZ_OGG
// See http://www.rfc-editor.org/rfc/rfc5334.txt for the definitions
// of Ogg media types and codec types
static const char gOggTypes[][16] = { static const char gOggTypes[][16] = {
"video/ogg", "video/ogg",
"audio/ogg", "audio/ogg",
"application/ogg" "application/ogg"
}; };
static const char* gOggCodecs[] = {
"vorbis",
"theora",
nsnull
};
static const char* gOggMaybeCodecs[] = {
nsnull
};
static PRBool IsOggEnabled() static PRBool IsOggEnabled()
{ {
return nsContentUtils::GetBoolPref("media.ogg.enabled"); return nsContentUtils::GetBoolPref("media.ogg.enabled");
@ -488,6 +630,9 @@ static PRBool IsOggType(const nsACString& aType)
#endif #endif
#ifdef MOZ_WAVE #ifdef MOZ_WAVE
// See http://www.rfc-editor.org/rfc/rfc2361.txt for the definitions
// of WAVE media types and codec types. However, the audio/vnd.wave
// MIME type described there is not used.
static const char gWaveTypes[][16] = { static const char gWaveTypes[][16] = {
"audio/x-wav", "audio/x-wav",
"audio/wav", "audio/wav",
@ -495,6 +640,16 @@ static const char gWaveTypes[][16] = {
"audio/x-pn-wav" "audio/x-pn-wav"
}; };
static const char* gWaveCodecs[] = {
"1", // Microsoft PCM Format
nsnull
};
static const char* gWaveMaybeCodecs[] = {
"0", // Microsoft Unknown Wave Format
nsnull
};
static PRBool IsWaveEnabled() static PRBool IsWaveEnabled()
{ {
return nsContentUtils::GetBoolPref("media.wave.enabled"); return nsContentUtils::GetBoolPref("media.wave.enabled");
@ -513,19 +668,99 @@ static PRBool IsWaveType(const nsACString& aType)
#endif #endif
/* static */ /* static */
PRBool nsHTMLMediaElement::CanHandleMediaType(const char* aMIMEType) PRBool nsHTMLMediaElement::CanHandleMediaType(const char* aMIMEType,
const char*** aCodecList,
const char*** aMaybeCodecList)
{ {
#ifdef MOZ_OGG #ifdef MOZ_OGG
if (IsOggType(nsDependentCString(aMIMEType))) if (IsOggType(nsDependentCString(aMIMEType))) {
*aCodecList = gOggCodecs;
*aMaybeCodecList = gOggMaybeCodecs;
return PR_TRUE; return PR_TRUE;
}
#endif #endif
#ifdef MOZ_WAVE #ifdef MOZ_WAVE
if (IsWaveType(nsDependentCString(aMIMEType))) if (IsWaveType(nsDependentCString(aMIMEType))) {
*aCodecList = gWaveCodecs;
*aMaybeCodecList = gWaveMaybeCodecs;
return PR_TRUE; return PR_TRUE;
}
#endif #endif
return PR_FALSE; return PR_FALSE;
} }
static PRBool
CodecListContains(const char** aCodecs, const nsAString& aCodec)
{
for (PRInt32 i = 0; aCodecs[i]; ++i) {
if (aCodec.EqualsASCII(aCodecs[i]))
return PR_TRUE;
}
return PR_FALSE;
}
enum CanPlayStatus {
CANPLAY_NO,
CANPLAY_MAYBE,
CANPLAY_YES
};
static CanPlayStatus GetCanPlay(const nsAString& aType)
{
nsContentTypeParser parser(aType);
nsAutoString mimeType;
nsresult rv = parser.GetType(mimeType);
if (NS_FAILED(rv))
return CANPLAY_NO;
NS_ConvertUTF16toUTF8 mimeTypeUTF8(mimeType);
const char** supportedCodecs;
const char** maybeSupportedCodecs;
if (!nsHTMLMediaElement::CanHandleMediaType(mimeTypeUTF8.get(),
&supportedCodecs, &maybeSupportedCodecs))
return CANPLAY_NO;
nsAutoString codecs;
rv = parser.GetParameter("codecs", codecs);
if (NS_FAILED(rv))
// Parameter not found or whatever
return CANPLAY_MAYBE;
CanPlayStatus result = CANPLAY_YES;
// See http://www.rfc-editor.org/rfc/rfc4281.txt for the description
// of the 'codecs' parameter
nsCommaSeparatedTokenizer tokenizer(codecs);
PRBool expectMoreTokens = PR_FALSE;
while (tokenizer.hasMoreTokens()) {
const nsSubstring& token = tokenizer.nextToken();
if (CodecListContains(maybeSupportedCodecs, token)) {
result = CANPLAY_MAYBE;
} else if (!CodecListContains(supportedCodecs, token)) {
// Totally unsupported codec
return CANPLAY_NO;
}
expectMoreTokens = tokenizer.lastTokenEndedWithComma();
}
if (expectMoreTokens) {
// Last codec name was empty
return CANPLAY_NO;
}
return result;
}
NS_IMETHODIMP
nsHTMLMediaElement::CanPlayType(const nsAString& aType, nsAString& aResult)
{
switch (GetCanPlay(aType)) {
case CANPLAY_NO: aResult.AssignLiteral("no"); break;
case CANPLAY_YES: aResult.AssignLiteral("probably"); break;
default:
case CANPLAY_MAYBE: aResult.AssignLiteral("maybe"); break;
}
return NS_OK;
}
/* static */ /* static */
void nsHTMLMediaElement::InitMediaTypes() void nsHTMLMediaElement::InitMediaTypes()
{ {
@ -602,109 +837,114 @@ nsresult nsHTMLMediaElement::InitializeDecoderForChannel(nsIChannel *aChannel,
if (!CreateDecoder(mimeType)) if (!CreateDecoder(mimeType))
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
mNetworkState = nsIDOMHTMLMediaElement::LOADING; mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
mDecoder->ElementAvailable(this); mDecoder->ElementAvailable(this);
return mDecoder->Load(nsnull, aChannel, aListener); return mDecoder->Load(nsnull, aChannel, aListener);
} }
nsresult nsHTMLMediaElement::PickMediaElement() nsresult nsHTMLMediaElement::NewURIFromString(const nsAutoString& aURISpec, nsIURI** aURI)
{ {
// Implements: NS_ENSURE_ARG_POINTER(aURI);
// http://www.whatwg.org/specs/web-apps/current-work/#pick-a
nsAutoString src;
if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
#ifdef MOZ_OGG
// Currently assuming an Ogg file
// TODO: Instantiate decoder based on type
if (mDecoder) {
mDecoder->ElementUnavailable();
mDecoder->Shutdown();
mDecoder = nsnull;
}
if (IsOggEnabled()) { *aURI = nsnull;
mDecoder = new nsOggDecoder();
if (mDecoder && !mDecoder->Init()) {
mDecoder = nsnull;
}
}
#endif
return InitializeDecoder(src);
}
// Checking of 'source' elements as per:
// http://www.whatwg.org/specs/web-apps/current-work/#pick-a
PRUint32 count = GetChildCount();
for (PRUint32 i = 0; i < count; ++i) {
nsIContent* child = GetChildAt(i);
NS_ASSERTION(child, "GetChildCount lied!");
nsCOMPtr<nsIContent> source = do_QueryInterface(child);
if (source) {
nsAutoString type;
nsAutoString src;
if (source->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src) &&
source->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type) &&
CreateDecoder(NS_ConvertUTF16toUTF8(type)))
return InitializeDecoder(src);
}
}
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
nsresult nsHTMLMediaElement::InitializeDecoder(const nsAString& aURISpec)
{
mNetworkState = nsIDOMHTMLMediaElement::LOADING;
nsCOMPtr<nsIDocument> doc = GetOwnerDoc(); nsCOMPtr<nsIDocument> doc = GetOwnerDoc();
if (!doc) { if (!doc) {
return NS_ERROR_DOM_INVALID_STATE_ERR; return NS_ERROR_DOM_INVALID_STATE_ERR;
} }
nsresult rv; nsCOMPtr<nsIURI> baseURI = GetBaseURI();
nsCOMPtr<nsIURI> uri; nsresult rv = nsContentUtils::NewURIWithDocumentCharset(aURI,
nsCOMPtr<nsIURI> baseURL = GetBaseURI();
rv = nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri),
aURISpec, aURISpec,
doc, doc,
baseURL); baseURI);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (mDecoder) { PRBool equal;
mDecoder->ElementAvailable(this); if (aURISpec.IsEmpty() &&
rv = mDecoder->Load(uri, nsnull, nsnull); doc->GetDocumentURI() &&
if (NS_FAILED(rv)) { NS_SUCCEEDED(doc->GetDocumentURI()->Equals(*aURI, &equal)) &&
mDecoder->Shutdown(); equal) {
mDecoder = nsnull; // It's not possible for a media resource to be embedded in the current
// document we extracted aURISpec from, so there's no point returning
// the current document URI just to let the caller attempt and fail to
// decode it.
NS_RELEASE(*aURI);
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
return NS_OK;
}
nsresult nsHTMLMediaElement::PickMediaElement(nsIURI** aURI)
{
NS_ENSURE_ARG_POINTER(aURI);
// Implements:
// http://www.whatwg.org/specs/web-apps/current-work/#pick-a-media-resource
nsAutoString src;
if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
return NewURIFromString(src, aURI);
}
// Checking of 'source' elements as per:
// http://www.whatwg.org/specs/web-apps/current-work/#pick-a-media-resource
PRUint32 count = GetChildCount();
for (PRUint32 i = 0; i < count; ++i) {
nsIContent* child = GetChildAt(i);
NS_ASSERTION(child, "GetChildCount lied!");
nsCOMPtr<nsIContent> source = do_QueryInterface(child);
if (source &&
source->Tag() == nsGkAtoms::source &&
source->IsNodeOfType(nsINode::eHTML)) {
nsAutoString type;
nsAutoString src;
if (source->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
if (source->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type)) {
if (GetCanPlay(type) != CANPLAY_NO)
return NewURIFromString(src, aURI);
} else if (i + 1 == count) {
// The last source element is permitted to omit the type
// attribute, in which case we need to open the URI and examine
// the channel's MIME type.
return NewURIFromString(src, aURI);
} }
} }
return rv; }
}
return NS_ERROR_DOM_INVALID_STATE_ERR;
} }
void nsHTMLMediaElement::MetadataLoaded() void nsHTMLMediaElement::MetadataLoaded()
{ {
mNetworkState = nsIDOMHTMLMediaElement::LOADED_METADATA; ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("durationchange")); DispatchAsyncSimpleEvent(NS_LITERAL_STRING("durationchange"));
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("loadedmetadata")); DispatchAsyncSimpleEvent(NS_LITERAL_STRING("loadedmetadata"));
if (mPlayRequested) {
mPlayRequested = PR_FALSE;
mPaused = PR_FALSE;
if (mDecoder) {
mDecoder->Play();
}
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("play"));
}
} }
void nsHTMLMediaElement::FirstFrameLoaded() void nsHTMLMediaElement::FirstFrameLoaded()
{ {
mNetworkState = nsIDOMHTMLMediaElement::LOADED_FIRST_FRAME; ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA);
ChangeReadyState(nsIDOMHTMLMediaElement::CAN_SHOW_CURRENT_FRAME);
mLoadedFirstFrame = PR_TRUE; mLoadedFirstFrame = PR_TRUE;
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("loadedfirstframe")); DispatchAsyncSimpleEvent(NS_LITERAL_STRING("loadeddata"));
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("canshowcurrentframe"));
} }
void nsHTMLMediaElement::ResourceLoaded() void nsHTMLMediaElement::ResourceLoaded()
{ {
mBegun = PR_FALSE; mBegun = PR_FALSE;
mNetworkState = nsIDOMHTMLMediaElement::LOADED; mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADED;
ChangeReadyState(nsIDOMHTMLMediaElement::CAN_PLAY_THROUGH); ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA);
DispatchProgressEvent(NS_LITERAL_STRING("load")); DispatchProgressEvent(NS_LITERAL_STRING("load"));
} }
@ -713,8 +953,8 @@ void nsHTMLMediaElement::NetworkError()
mError = new nsHTMLMediaError(nsHTMLMediaError::MEDIA_ERR_NETWORK); mError = new nsHTMLMediaError(nsHTMLMediaError::MEDIA_ERR_NETWORK);
mBegun = PR_FALSE; mBegun = PR_FALSE;
DispatchProgressEvent(NS_LITERAL_STRING("error")); DispatchProgressEvent(NS_LITERAL_STRING("error"));
mNetworkState = nsIDOMHTMLMediaElement::EMPTY; mNetworkState = nsIDOMHTMLMediaElement::NETWORK_EMPTY;
DispatchSimpleEvent(NS_LITERAL_STRING("empty")); DispatchSimpleEvent(NS_LITERAL_STRING("emptied"));
} }
void nsHTMLMediaElement::PlaybackEnded() void nsHTMLMediaElement::PlaybackEnded()
@ -727,7 +967,7 @@ void nsHTMLMediaElement::PlaybackEnded()
void nsHTMLMediaElement::CanPlayThrough() void nsHTMLMediaElement::CanPlayThrough()
{ {
ChangeReadyState(nsIDOMHTMLMediaElement::CAN_PLAY_THROUGH); ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA);
} }
void nsHTMLMediaElement::SeekStarted() void nsHTMLMediaElement::SeekStarted()
@ -743,31 +983,27 @@ void nsHTMLMediaElement::SeekCompleted()
void nsHTMLMediaElement::ChangeReadyState(nsMediaReadyState aState) void nsHTMLMediaElement::ChangeReadyState(nsMediaReadyState aState)
{ {
// Handle raising of "waiting" event during seek (see 4.7.10.8) // Handle raising of "waiting" event during seek (see 4.8.10.9)
if (mPlayingBeforeSeek && aState <= nsIDOMHTMLMediaElement::CAN_PLAY) if (mPlayingBeforeSeek && aState < nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA)
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("waiting")); DispatchAsyncSimpleEvent(NS_LITERAL_STRING("waiting"));
mReadyState = aState; mReadyState = aState;
if (mNetworkState != nsIDOMHTMLMediaElement::EMPTY) { if (mNetworkState != nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
switch(mReadyState) { switch(mReadyState) {
case nsIDOMHTMLMediaElement::DATA_UNAVAILABLE: case nsIDOMHTMLMediaElement::HAVE_NOTHING:
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("dataunavailable")); LOG(PR_LOG_DEBUG, ("Ready state changed to HAVE_NOTHING"));
LOG(PR_LOG_DEBUG, ("Ready state changed to DATA_UNAVAILABLE"));
break; break;
case nsIDOMHTMLMediaElement::CAN_SHOW_CURRENT_FRAME: case nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA:
if (mLoadedFirstFrame) { LOG(PR_LOG_DEBUG, ("Ready state changed to HAVE_CURRENT_DATA"));
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("canshowcurrentframe"));
LOG(PR_LOG_DEBUG, ("Ready state changed to CAN_SHOW_CURRENT_FRAME"));
}
break; break;
case nsIDOMHTMLMediaElement::CAN_PLAY: case nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA:
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("canplay")); DispatchAsyncSimpleEvent(NS_LITERAL_STRING("canplay"));
LOG(PR_LOG_DEBUG, ("Ready state changed to CAN_PLAY")); LOG(PR_LOG_DEBUG, ("Ready state changed to HAVE_FUTURE_DATA"));
break; break;
case nsIDOMHTMLMediaElement::CAN_PLAY_THROUGH: case nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA:
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("canplaythrough")); DispatchAsyncSimpleEvent(NS_LITERAL_STRING("canplaythrough"));
if (mAutoplaying && if (mAutoplaying &&
mPaused && mPaused &&
@ -776,9 +1012,9 @@ void nsHTMLMediaElement::ChangeReadyState(nsMediaReadyState aState)
if (mDecoder) { if (mDecoder) {
mDecoder->Play(); mDecoder->Play();
} }
LOG(PR_LOG_DEBUG, ("Ready state changed to CAN_PLAY_THROUGH"));
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("play")); DispatchAsyncSimpleEvent(NS_LITERAL_STRING("play"));
} }
LOG(PR_LOG_DEBUG, ("Ready state changed to HAVE_ENOUGH_DATA"));
break; break;
} }
} }
@ -841,7 +1077,7 @@ nsresult nsHTMLMediaElement::DoneAddingChildren(PRBool aHaveNotified)
if (!mIsDoneAddingChildren) { if (!mIsDoneAddingChildren) {
mIsDoneAddingChildren = PR_TRUE; mIsDoneAddingChildren = PR_TRUE;
if (mNetworkState == nsIDOMHTMLMediaElement::EMPTY) { if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
Load(); Load();
} }
} }
@ -854,15 +1090,15 @@ PRBool nsHTMLMediaElement::IsDoneAddingChildren()
return mIsDoneAddingChildren; return mIsDoneAddingChildren;
} }
PRBool nsHTMLMediaElement::IsActivelyPlaying() const PRBool nsHTMLMediaElement::IsPotentiallyPlaying() const
{ {
// TODO: // TODO:
// playback has not stopped due to errors, // playback has not stopped due to errors,
// and the element has not paused for user interaction // and the element has not paused for user interaction
return return
!mPaused && !mPaused &&
(mReadyState == nsIDOMHTMLMediaElement::CAN_PLAY || (mReadyState == nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA ||
mReadyState == nsIDOMHTMLMediaElement::CAN_PLAY_THROUGH) && mReadyState == nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA) &&
!IsPlaybackEnded(); !IsPlaybackEnded();
} }
@ -872,12 +1108,11 @@ PRBool nsHTMLMediaElement::IsPlaybackEnded() const
// the current playback position is equal to the effective end of the media resource, // the current playback position is equal to the effective end of the media resource,
// and the currentLoop attribute is equal to playCount-1. // and the currentLoop attribute is equal to playCount-1.
// See bug 449157. // See bug 449157.
return mNetworkState >= nsIDOMHTMLMediaElement::LOADED_METADATA && return mNetworkState >= nsIDOMHTMLMediaElement::HAVE_METADATA &&
mDecoder ? mDecoder->IsEnded() : PR_FALSE; mDecoder ? mDecoder->IsEnded() : PR_FALSE;
} }
nsIPrincipal* nsIPrincipal* nsHTMLMediaElement::GetCurrentPrincipal()
nsHTMLMediaElement::GetCurrentPrincipal()
{ {
if (!mDecoder) if (!mDecoder)
return nsnull; return nsnull;
@ -896,6 +1131,10 @@ void nsHTMLMediaElement::DestroyContent()
mDecoder->Shutdown(); mDecoder->Shutdown();
mDecoder = nsnull; mDecoder = nsnull;
} }
if (mChannel) {
mChannel->Cancel(NS_BINDING_ABORTED);
mChannel = nsnull;
}
nsGenericHTMLElement::DestroyContent(); nsGenericHTMLElement::DestroyContent();
} }

Просмотреть файл

@ -298,7 +298,7 @@ PRUint32
nsHTMLObjectElement::GetDesiredIMEState() nsHTMLObjectElement::GetDesiredIMEState()
{ {
if (Type() == eType_Plugin) { if (Type() == eType_Plugin) {
return nsIContent::IME_STATUS_ENABLE; return nsIContent::IME_STATUS_PLUGIN;
} }
return nsGenericHTMLFormElement::GetDesiredIMEState(); return nsGenericHTMLFormElement::GetDesiredIMEState();

Просмотреть файл

@ -317,7 +317,7 @@ PRUint32
nsHTMLSharedObjectElement::GetDesiredIMEState() nsHTMLSharedObjectElement::GetDesiredIMEState()
{ {
if (Type() == eType_Plugin) { if (Type() == eType_Plugin) {
return nsIContent::IME_STATUS_ENABLE; return nsIContent::IME_STATUS_PLUGIN;
} }
return nsGenericHTMLElement::GetDesiredIMEState(); return nsGenericHTMLElement::GetDesiredIMEState();

Просмотреть файл

@ -1,4 +1,4 @@
load 353713-1.html #load 353713-1.html # Bug 469626
load 388183-1.html load 388183-1.html
load 395340-1.html load 395340-1.html
load 407053.html load 407053.html

Просмотреть файл

@ -40,6 +40,7 @@
#include "nscore.h" #include "nscore.h"
#include "prlog.h" #include "prlog.h"
#include "nsTArray.h"
extern PRLogModuleInfo* gAudioStreamLog; extern PRLogModuleInfo* gAudioStreamLog;
@ -117,6 +118,12 @@ class nsAudioStream
SampleFormat mFormat; SampleFormat mFormat;
// When a Write() request is made, and the number of samples
// requested to be written exceeds the buffer size of the audio
// backend, the remaining samples are stored in this variable. They
// will be written on the next Write() request.
nsTArray<short> mBufferOverflow;
PRPackedBool mPaused; PRPackedBool mPaused;
}; };
#endif #endif

Просмотреть файл

@ -122,19 +122,26 @@ void nsAudioStream::Write(const void* aBuf, PRUint32 aCount)
"Buffer size must be divisible by channel count"); "Buffer size must be divisible by channel count");
mSamplesBuffered += aCount; mSamplesBuffered += aCount;
PRUint32 offset = mBufferOverflow.Length();
PRInt32 count = aCount + offset;
if (!mAudioHandle) if (!mAudioHandle)
return; return;
nsAutoArrayPtr<short> s_data(new short[aCount]); nsAutoArrayPtr<short> s_data(new short[count]);
if (s_data) { if (s_data) {
for (PRUint32 i=0; i < offset; ++i) {
s_data[i] = mBufferOverflow.ElementAt(i);
}
mBufferOverflow.Clear();
switch (mFormat) { switch (mFormat) {
case FORMAT_U8: { case FORMAT_U8: {
const PRUint8* buf = static_cast<const PRUint8*>(aBuf); const PRUint8* buf = static_cast<const PRUint8*>(aBuf);
PRInt32 volume = PRInt32((1 << 16) * mVolume); PRInt32 volume = PRInt32((1 << 16) * mVolume);
for (PRUint32 i = 0; i < aCount; ++i) { for (PRUint32 i = 0; i < aCount; ++i) {
s_data[i] = short(((PRInt32(buf[i]) - 128) * volume) >> 8); s_data[i + offset] = short(((PRInt32(buf[i]) - 128) * volume) >> 8);
} }
break; break;
} }
@ -142,20 +149,20 @@ void nsAudioStream::Write(const void* aBuf, PRUint32 aCount)
const short* buf = static_cast<const short*>(aBuf); const short* buf = static_cast<const short*>(aBuf);
PRInt32 volume = PRInt32((1 << 16) * mVolume); PRInt32 volume = PRInt32((1 << 16) * mVolume);
for (PRUint32 i = 0; i < aCount; ++i) { for (PRUint32 i = 0; i < aCount; ++i) {
s_data[i] = short((PRInt32(buf[i]) * volume) >> 16); s_data[i + offset] = short((PRInt32(buf[i]) * volume) >> 16);
} }
break; break;
} }
case FORMAT_FLOAT32_LE: { case FORMAT_FLOAT32_LE: {
const float* buf = static_cast<const float*>(aBuf); const float* buf = static_cast<const float*>(aBuf);
for (PRUint32 i= 0; i < aCount; ++i) { for (PRUint32 i = 0; i < aCount; ++i) {
float scaled_value = floorf(0.5 + 32768 * buf[i] * mVolume); float scaled_value = floorf(0.5 + 32768 * buf[i] * mVolume);
if (buf[i] < 0.0) { if (buf[i] < 0.0) {
s_data[i] = (scaled_value < -32768.0) ? s_data[i + offset] = (scaled_value < -32768.0) ?
-32768 : -32768 :
short(scaled_value); short(scaled_value);
} else { } else {
s_data[i] = (scaled_value > 32767.0) ? s_data[i+offset] = (scaled_value > 32767.0) ?
32767 : 32767 :
short(scaled_value); short(scaled_value);
} }
@ -164,7 +171,14 @@ void nsAudioStream::Write(const void* aBuf, PRUint32 aCount)
} }
} }
if (sa_stream_write(static_cast<sa_stream_t*>(mAudioHandle), s_data.get(), aCount * sizeof(short)) != SA_SUCCESS) { PRInt32 available = Available();
if (available < count) {
mBufferOverflow.AppendElements(s_data.get() + available, (count - available));
count = available;
}
if (sa_stream_write(static_cast<sa_stream_t*>(mAudioHandle),
s_data.get(), count * sizeof(short)) != SA_SUCCESS) {
PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_write error")); PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_write error"));
Shutdown(); Shutdown();
} }
@ -197,11 +211,21 @@ void nsAudioStream::SetVolume(float aVolume)
void nsAudioStream::Drain() void nsAudioStream::Drain()
{ {
if (!mAudioHandle) { if (!mAudioHandle) {
// mSamplesBuffered already accounts for the data in the
// mBufferOverflow array.
PRUint32 drainTime = (float(mSamplesBuffered) / mRate / mChannels - GetTime()) * 1000.0; PRUint32 drainTime = (float(mSamplesBuffered) / mRate / mChannels - GetTime()) * 1000.0;
PR_Sleep(PR_MillisecondsToInterval(drainTime)); PR_Sleep(PR_MillisecondsToInterval(drainTime));
return; return;
} }
// Write any remaining unwritten sound data in the overflow buffer
if (!mBufferOverflow.IsEmpty()) {
if (sa_stream_write(static_cast<sa_stream_t*>(mAudioHandle),
mBufferOverflow.Elements(),
mBufferOverflow.Length() * sizeof(short)) != SA_SUCCESS)
return;
}
if (sa_stream_drain(static_cast<sa_stream_t*>(mAudioHandle)) != SA_SUCCESS) { if (sa_stream_drain(static_cast<sa_stream_t*>(mAudioHandle)) != SA_SUCCESS) {
PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_drain error")); PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_drain error"));
Shutdown(); Shutdown();

Просмотреть файл

@ -141,6 +141,15 @@ public:
MOZ_COUNT_DTOR(FrameData); MOZ_COUNT_DTOR(FrameData);
} }
// Write the audio data from the frame to the Audio stream.
void Write(nsAudioStream* aStream)
{
PRUint32 length = mAudioData.Length();
if (length == 0)
return;
aStream->Write(mAudioData.Elements(), length);
}
nsAutoArrayPtr<unsigned char> mVideoData; nsAutoArrayPtr<unsigned char> mVideoData;
nsTArray<float> mAudioData; nsTArray<float> mAudioData;
@ -260,9 +269,8 @@ public:
void PlayVideo(FrameData* aFrame); void PlayVideo(FrameData* aFrame);
// Play the audio data from the given frame. The decode monitor must // Play the audio data from the given frame. The decode monitor must
// be locked when calling this method. Returns PR_FALSE if unable to // be locked when calling this method.
// write to the audio device without blocking. void PlayAudio(FrameData* aFrame);
PRBool PlayAudio(FrameData* aFrame);
// Called from the main thread to get the current frame time. The decoder // Called from the main thread to get the current frame time. The decoder
// monitor must be obtained before calling this. // monitor must be obtained before calling this.
@ -629,13 +637,13 @@ void nsOggDecodeStateMachine::PlayFrame() {
double time = (PR_IntervalToMilliseconds(PR_IntervalNow()-mPlayStartTime-mPauseDuration)/1000.0); double time = (PR_IntervalToMilliseconds(PR_IntervalNow()-mPlayStartTime-mPauseDuration)/1000.0);
if (time >= frame->mTime) { if (time >= frame->mTime) {
mDecodedFrames.Pop();
// Audio for the current frame is played, but video for the next frame // Audio for the current frame is played, but video for the next frame
// is displayed, to account for lag from the time the audio is written // is displayed, to account for lag from the time the audio is written
// to when it is played. This will go away when we move to a/v sync // to when it is played. This will go away when we move to a/v sync
// using the audio hardware clock. // using the audio hardware clock.
PlayVideo(mDecodedFrames.IsEmpty() ? frame : mDecodedFrames.Peek());
PlayAudio(frame); PlayAudio(frame);
mDecodedFrames.Pop();
PlayVideo(mDecodedFrames.IsEmpty() ? frame : mDecodedFrames.Peek());
UpdatePlaybackPosition(frame->mDecodedFrameTime); UpdatePlaybackPosition(frame->mDecodedFrameTime);
delete frame; delete frame;
} }
@ -677,17 +685,13 @@ void nsOggDecodeStateMachine::PlayVideo(FrameData* aFrame)
} }
} }
PRBool nsOggDecodeStateMachine::PlayAudio(FrameData* aFrame) void nsOggDecodeStateMachine::PlayAudio(FrameData* aFrame)
{ {
// NS_ASSERTION(PR_InMonitor(mDecoder->GetMonitor()), "PlayAudio() called without acquiring decoder monitor"); // NS_ASSERTION(PR_InMonitor(mDecoder->GetMonitor()), "PlayAudio() called without acquiring decoder monitor");
if (mAudioStream && aFrame && !aFrame->mAudioData.IsEmpty()) { if (!mAudioStream)
if (PRUint32(mAudioStream->Available()) < aFrame->mAudioData.Length()) return;
return PR_FALSE;
mAudioStream->Write(aFrame->mAudioData.Elements(), aFrame->mAudioData.Length()); aFrame->Write(mAudioStream);
}
return PR_TRUE;
} }
void nsOggDecodeStateMachine::OpenAudioStream() void nsOggDecodeStateMachine::OpenAudioStream()
@ -1054,6 +1058,14 @@ nsresult nsOggDecodeStateMachine::Run()
if (mState != DECODER_STATE_COMPLETED) if (mState != DECODER_STATE_COMPLETED)
continue; continue;
if (mAudioStream) {
mon.Exit();
mAudioStream->Drain();
mon.Enter();
if (mState != DECODER_STATE_COMPLETED)
continue;
}
nsCOMPtr<nsIRunnable> event = nsCOMPtr<nsIRunnable> event =
NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, PlaybackEnded); NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, PlaybackEnded);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
@ -1546,7 +1558,7 @@ void nsOggDecoder::BufferingStopped()
return; return;
if (mElement) { if (mElement) {
mElement->ChangeReadyState(nsIDOMHTMLMediaElement::CAN_SHOW_CURRENT_FRAME); mElement->ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA);
} }
} }
@ -1556,7 +1568,7 @@ void nsOggDecoder::BufferingStarted()
return; return;
if (mElement) { if (mElement) {
mElement->ChangeReadyState(nsIDOMHTMLMediaElement::DATA_UNAVAILABLE); mElement->ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA);
} }
} }

Просмотреть файл

@ -537,8 +537,9 @@ nsWaveStateMachine::Run()
// completely fill the audio backend's buffers with data. This // completely fill the audio backend's buffers with data. This
// allows us plenty of time to wake up and refill the buffers // allows us plenty of time to wake up and refill the buffers
// without an underrun occurring. // without an underrun occurring.
PRUint32 sampleSize = mSampleFormat == nsAudioStream::FORMAT_U8 ? 1 : 2;
PRUint32 len = RoundDownToSample(NS_MIN(mStream->Available(), PRUint32 len = RoundDownToSample(NS_MIN(mStream->Available(),
PRUint32(mAudioStream->Available() * sizeof(short)))); PRUint32(mAudioStream->Available() * sampleSize)));
if (len) { if (len) {
nsAutoArrayPtr<char> buf(new char[len]); nsAutoArrayPtr<char> buf(new char[len]);
PRUint32 got = 0; PRUint32 got = 0;
@ -1315,7 +1316,7 @@ nsWaveDecoder::BufferingStarted()
} }
if (mElement) { if (mElement) {
mElement->ChangeReadyState(nsIDOMHTMLMediaElement::DATA_UNAVAILABLE); mElement->ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA);
} }
} }
@ -1327,7 +1328,7 @@ nsWaveDecoder::BufferingStopped()
} }
if (mElement) { if (mElement) {
mElement->ChangeReadyState(nsIDOMHTMLMediaElement::CAN_SHOW_CURRENT_FRAME); mElement->ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA);
} }
} }

Просмотреть файл

@ -43,21 +43,31 @@ relativesrcdir = content/media/video/test
include $(DEPTH)/config/autoconf.mk include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk
_TEST_FILES = test_autoplay.html \ _TEST_FILES = \
test_bug461281.html \ can_play_type_ogg.js \
can_play_type_wave.js \
test_autoplay.html \
test_can_play_type.html \
test_constants.html \ test_constants.html \
test_controls.html \ test_controls.html \
test_currentTime.html \ test_currentTime.html \
test_decoder_disable.html \ test_networkState.html \
test_paused.html \
test_readyState.html \
test_seek2.html \
test_volume.html \
$(NULL)
ifdef MOZ_OGG
_TEST_FILES += \
test_bug448534.html \
test_bug461281.html \
test_can_play_type_ogg.html \
test_duration1.html \ test_duration1.html \
test_ended1.html \ test_ended1.html \
test_ended2.html \ test_ended2.html \
test_networkState.html \
test_onloadedmetadata.html \ test_onloadedmetadata.html \
test_paused.html \
test_readyState.html \
test_seek1.html \ test_seek1.html \
test_seek2.html \
test_seek3.html \ test_seek3.html \
test_seek4.html \ test_seek4.html \
test_seek5.html \ test_seek5.html \
@ -68,7 +78,20 @@ _TEST_FILES = test_autoplay.html \
test_timeupdate1.html \ test_timeupdate1.html \
test_timeupdate2.html \ test_timeupdate2.html \
test_timeupdate3.html \ test_timeupdate3.html \
test_volume.html \ 320x240.ogg \
bug461281.ogg \
seek.ogg \
$(NULL)
else
_TEST_FILES += \
test_can_play_type_no_ogg.html \
$(NULL)
endif
ifdef MOZ_WAVE
_TEST_FILES += \
test_bug463162.xhtml \
test_can_play_type_wave.html \
test_wav_8bit.html \ test_wav_8bit.html \
test_wav_ended1.html \ test_wav_ended1.html \
test_wav_seek3.html \ test_wav_seek3.html \
@ -82,15 +105,25 @@ _TEST_FILES = test_autoplay.html \
test_wav_trailing.html \ test_wav_trailing.html \
test_wav_trunc.html \ test_wav_trunc.html \
test_wav_trunc_seek.html \ test_wav_trunc_seek.html \
320x240.ogg \
bug461281.ogg \
seek.ogg \
r11025_s16_c1.wav \ r11025_s16_c1.wav \
r11025_s16_c1_trailing.wav \ r11025_s16_c1_trailing.wav \
r11025_s16_c1_trunc.wav \
r11025_u8_c1.wav \ r11025_u8_c1.wav \
# test_bug448534.html \ r11025_u8_c1_trunc.wav \
$(NULL) $(NULL)
else
_TEST_FILES += \
test_can_play_type_no_wave.html \
$(NULL)
endif
ifdef MOZ_OGG
ifdef MOZ_WAVE
_TEST_FILES += \
test_decoder_disable.html \
test_media_selection.html \
$(NULL)
endif
endif
libs:: $(_TEST_FILES) libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)

Просмотреть файл

@ -0,0 +1,22 @@
function check_ogg(v, enabled) {
function check(type, expected) {
is(v.canPlayType(type), enabled ? expected : "no", type);
}
// Ogg types
check("video/ogg", "maybe");
check("audio/ogg", "maybe");
check("application/ogg", "maybe");
// Supported Ogg codecs
check("audio/ogg; codecs=vorbis", "probably");
check("video/ogg; codecs=vorbis", "probably");
check("video/ogg; codecs=vorbis,theora", "probably");
check("video/ogg; codecs=\"vorbis, theora\"", "probably");
check("video/ogg; codecs=theora", "probably");
// Unsupported Ogg codecs
check("video/ogg; codecs=xyz", "no");
check("video/ogg; codecs=xyz,vorbis", "no");
check("video/ogg; codecs=vorbis,xyz", "no");
}

Просмотреть файл

@ -0,0 +1,30 @@
function check_wave(v, enabled) {
function check(type, expected) {
is(v.canPlayType(type), enabled ? expected : "no", type);
}
// Wave types
check("audio/wave", "maybe");
check("audio/wav", "maybe");
check("audio/x-wav", "maybe");
check("audio/x-pn-wav", "maybe");
// Supported Wave codecs
check("audio/wave; codecs=1", "probably");
// "no codecs" should be supported, I guess
check("audio/wave; codecs=", "probably");
check("audio/wave; codecs=\"\"", "probably");
// Maybe-supported Wave codecs
check("audio/wave; codecs=0", "maybe");
check("audio/wave; codecs=\"0, 1\"", "maybe");
// Unsupported Wave codecs
check("audio/wave; codecs=2", "no");
check("audio/wave; codecs=xyz,0", "no");
check("audio/wave; codecs=0,xyz", "no");
check("audio/wave; codecs=\"xyz, 1\"", "no");
// empty codec names
check("audio/wave; codecs=,", "no");
check("audio/wave; codecs=\"0, 1,\"", "no");
}

Двоичные данные
content/media/video/test/r11025_s16_c1_trunc.wav

Двоичный файл не отображается.

Двоичные данные
content/media/video/test/r11025_u8_c1_trunc.wav Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,31 @@
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:svg="http://www.w3.org/2000/svg">
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=463162
-->
<head>
<title>Test for Bug 463162</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"/>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=463162">Mozilla Bug 463162</a>
<audio id='a1'><sauce type="audio/x-wav" src="r11025_s16_c1.wav"/></audio>
<audio id='a2'><source type="audio/x-wav" src="r11025_s16_c1.wav"/></audio>
<audio id='a3'><html:source type="audio/x-wav" src="r11025_s16_c1.wav"/></audio>
<audio id='a4'><svg:source type="audio/x-wav" src="r11025_s16_c1.wav"/></audio>
<pre id="test">
<script class="testbody" type="text/javascript">
<![CDATA[
ok($("a1").networkState == HTMLMediaElement.NETWORK_EMPTY, "audio a1 with bogus child should not be loading");
ok($("a2").networkState >= HTMLMediaElement.NETWORK_LOADING, "audio a2 with valid child should be loading");
ok($("a3").networkState >= HTMLMediaElement.NETWORK_LOADING, "audio a3 with valid child should be loading");
ok($("a4").networkState == HTMLMediaElement.NETWORK_EMPTY, "audio a4 with bogus child should not be loading");
]]>
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,38 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=469247
-->
<head>
<title>Test for Bug 469247</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=469247">Mozill
a Bug 469247</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<video id="v"></video>
<pre id="test">
<script type="application/javascript">
var v = document.getElementById('v');
function check(type, expected) {
is(v.canPlayType(type), expected, type);
}
// Invalid types
check("foo/bar", "no");
check("", "no");
check("!!!", "no");
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,29 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=469247
-->
<head>
<title>Test for Bug 469247: Ogg backend disabled</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=469247">Mozill
a Bug 469247</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<video id="v"></video>
<pre id="test">
<script src="can_play_type_ogg.js"></script>
check_ogg(document.getElementById('v'), false);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,29 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=469247
-->
<head>
<title>Test for Bug 469247: WAVE backend disabled</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=469247">Mozill
a Bug 469247</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<video id="v"></video>
<pre id="test">
<script src="can_play_type_wave.js"></script>
check_wave(document.getElementById('v'), false);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,28 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=469247
-->
<head>
<title>Test for Bug 469247: Ogg backend</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=469247">Mozill
a Bug 469247</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<video id="v"></video>
<pre id="test">
<script src="can_play_type_ogg.js"></script>
<script>
check_ogg(document.getElementById('v'), true);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,28 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=469247
-->
<head>
<title>Test for Bug 469247: WAVE backend</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=469247">Mozill
a Bug 469247</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<video id="v"></video>
<pre id="test">
<script src="can_play_type_wave.js"></script>
<script>
check_wave(document.getElementById('v'), true);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -2,7 +2,7 @@
<html> <html>
<!-- <!--
Adapted from: Adapted from:
http://simon.html5.org/test/html/dom/interfaces/HTMLElement/HTMLMediaElement/const-unsigned-short/001.htm http://simon.html5.org/test/html/dom/interfaces/htmlelement/htmlmediaelement/const-unsigned-short/001.htm
--> -->
<head> <head>
<title>Media test: constants</title> <title>Media test: constants</title>
@ -14,132 +14,133 @@
<video><source></video><audio><source></audio> <video><source></video><audio><source></audio>
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
is(HTMLElement.EMPTY, undefined); is(HTMLElement.NETWORK_EMPTY, undefined);
is(HTMLElement.LOADING, undefined); is(HTMLElement.NETWORK_IDLE, undefined);
is(HTMLElement.LOADED_METADATA, undefined); is(HTMLElement.NETWORK_LOADING, undefined);
is(HTMLElement.LOADED_FIRST_FRAME, undefined); is(HTMLElement.NETWORK_LOADED, undefined);
is(HTMLElement.LOADED, undefined); is(HTMLElement.HAVE_NOTHING, undefined);
is(HTMLElement.DATA_UNAVAILABLE, undefined); is(HTMLElement.HAVE_METADATA, undefined);
is(HTMLElement.CAN_SHOW_CURRENT_FRAME, undefined); is(HTMLElement.HAVE_CURRENT_DATA, undefined);
is(HTMLElement.CAN_PLAY, undefined); is(HTMLElement.HAVE_FUTURE_DATA, undefined);
is(HTMLElement.CAN_PLAY_THROUGH, undefined); is(HTMLElement.HAVE_ENOUGH_DATA, undefined);
is(HTMLMediaElement.EMPTY, 0); is(HTMLMediaElement.NETWORK_EMPTY, 0);
is(HTMLMediaElement.LOADING, 1); is(HTMLMediaElement.NETWORK_IDLE, 1);
is(HTMLMediaElement.LOADED_METADATA, 2); is(HTMLMediaElement.NETWORK_LOADING, 2);
is(HTMLMediaElement.LOADED_FIRST_FRAME, 3); is(HTMLMediaElement.NETWORK_LOADED, 3);
is(HTMLMediaElement.LOADED, 4); is(HTMLMediaElement.HAVE_NOTHING, 0);
is(HTMLMediaElement.DATA_UNAVAILABLE, 0); is(HTMLMediaElement.HAVE_METADATA, 1);
is(HTMLMediaElement.CAN_SHOW_CURRENT_FRAME, 1); is(HTMLMediaElement.HAVE_CURRENT_DATA, 2);
is(HTMLMediaElement.CAN_PLAY, 2); is(HTMLMediaElement.HAVE_FUTURE_DATA, 3);
is(HTMLMediaElement.CAN_PLAY_THROUGH, 3); is(HTMLMediaElement.HAVE_ENOUGH_DATA, 4);
is(HTMLVideoElement.EMPTY, undefined); is(HTMLVideoElement.NETWORK_EMPTY, undefined);
is(HTMLVideoElement.LOADING, undefined); is(HTMLVideoElement.NETWORK_IDLE, undefined);
is(HTMLVideoElement.LOADED_METADATA, undefined); is(HTMLVideoElement.NETWORK_LOADING, undefined);
is(HTMLVideoElement.LOADED_FIRST_FRAME, undefined); is(HTMLVideoElement.NETWORK_LOADED, undefined);
is(HTMLVideoElement.LOADED, undefined); is(HTMLVideoElement.HAVE_NOTHING, undefined);
is(HTMLVideoElement.DATA_UNAVAILABLE, undefined); is(HTMLVideoElement.HAVE_METADATA, undefined);
is(HTMLVideoElement.CAN_SHOW_CURRENT_FRAME, undefined); is(HTMLVideoElement.HAVE_CURRENT_DATA, undefined);
is(HTMLVideoElement.CAN_PLAY, undefined); is(HTMLVideoElement.HAVE_FUTURE_DATA, undefined);
is(HTMLVideoElement.CAN_PLAY_THROUGH, undefined); is(HTMLVideoElement.HAVE_ENOUGH_DATA, undefined);
is(HTMLAudioElement.EMPTY, undefined); is(HTMLAudioElement.NETWORK_EMPTY, undefined);
is(HTMLAudioElement.LOADING, undefined); is(HTMLAudioElement.NETWORK_IDLE, undefined);
is(HTMLAudioElement.LOADED_METADATA, undefined); is(HTMLAudioElement.NETWORK_LOADING, undefined);
is(HTMLAudioElement.LOADED_FIRST_FRAME, undefined); is(HTMLAudioElement.NETWORK_LOADED, undefined);
is(HTMLAudioElement.LOADED, undefined); is(HTMLAudioElement.HAVE_NOTHING, undefined);
is(HTMLAudioElement.DATA_UNAVAILABLE, undefined); is(HTMLAudioElement.HAVE_METADATA, undefined);
is(HTMLAudioElement.CAN_SHOW_CURRENT_FRAME, undefined); is(HTMLAudioElement.HAVE_CURRENT_DATA, undefined);
is(HTMLAudioElement.CAN_PLAY, undefined); is(HTMLAudioElement.HAVE_FUTURE_DATA, undefined);
is(HTMLAudioElement.CAN_PLAY_THROUGH, undefined); is(HTMLAudioElement.HAVE_ENOUGH_DATA, undefined);
is(HTMLSourceElement.EMPTY, undefined); is(HTMLSourceElement.NETWORK_EMPTY, undefined);
is(HTMLSourceElement.LOADING, undefined); is(HTMLSourceElement.NETWORK_IDLE, undefined);
is(HTMLSourceElement.LOADED_METADATA, undefined); is(HTMLSourceElement.NETWORK_LOADING, undefined);
is(HTMLSourceElement.LOADED_FIRST_FRAME, undefined); is(HTMLSourceElement.NETWORK_LOADED, undefined);
is(HTMLSourceElement.LOADED, undefined); is(HTMLSourceElement.HAVE_NOTHING, undefined);
is(HTMLSourceElement.DATA_UNAVAILABLE, undefined); is(HTMLSourceElement.HAVE_METADATA, undefined);
is(HTMLSourceElement.CAN_SHOW_CURRENT_FRAME, undefined); is(HTMLSourceElement.HAVE_CURRENT_DATA, undefined);
is(HTMLSourceElement.CAN_PLAY, undefined); is(HTMLSourceElement.HAVE_FUTURE_DATA, undefined);
is(HTMLSourceElement.CAN_PLAY_THROUGH, undefined); is(HTMLSourceElement.HAVE_ENOUGH_DATA, undefined);
is(document.body.EMPTY, undefined); is(document.body.NETWORK_EMPTY, undefined);
is(document.body.LOADING, undefined); is(document.body.NETWORK_IDLE, undefined);
is(document.body.LOADED_METADATA, undefined); is(document.body.NETWORK_LOADING, undefined);
is(document.body.LOADED_FIRST_FRAME, undefined); is(document.body.NETWORK_LOADED, undefined);
is(document.body.LOADED, undefined); is(document.body.HAVE_NOTHING, undefined);
is(document.body.DATA_UNAVAILABLE, undefined); is(document.body.HAVE_METADATA, undefined);
is(document.body.CAN_SHOW_CURRENT_FRAME, undefined); is(document.body.HAVE_CURRENT_DATA, undefined);
is(document.body.CAN_PLAY, undefined); is(document.body.HAVE_FUTURE_DATA, undefined);
is(document.body.CAN_PLAY_THROUGH, undefined); is(document.body.HAVE_ENOUGH_DATA, undefined);
is(document.getElementsByTagName("video")[0].EMPTY, 0); is(document.getElementsByTagName("video")[0].NETWORK_EMPTY, 0);
is(document.getElementsByTagName("video")[0].LOADING, 1); is(document.getElementsByTagName("video")[0].NETWORK_IDLE, 1);
is(document.getElementsByTagName("video")[0].LOADED_METADATA, 2); is(document.getElementsByTagName("video")[0].NETWORK_LOADING, 2);
is(document.getElementsByTagName("video")[0].LOADED_FIRST_FRAME, 3); is(document.getElementsByTagName("video")[0].NETWORK_LOADED, 3);
is(document.getElementsByTagName("video")[0].LOADED, 4); is(document.getElementsByTagName("video")[0].HAVE_NOTHING, 0);
is(document.getElementsByTagName("video")[0].DATA_UNAVAILABLE, 0); is(document.getElementsByTagName("video")[0].HAVE_METADATA, 1);
is(document.getElementsByTagName("video")[0].CAN_SHOW_CURRENT_FRAME, 1); is(document.getElementsByTagName("video")[0].HAVE_CURRENT_DATA, 2);
is(document.getElementsByTagName("video")[0].CAN_PLAY, 2); is(document.getElementsByTagName("video")[0].HAVE_FUTURE_DATA, 3);
is(document.getElementsByTagName("video")[0].CAN_PLAY_THROUGH, 3); is(document.getElementsByTagName("video")[0].HAVE_ENOUGH_DATA, 4);
is(document.getElementsByTagName("audio")[0].EMPTY, 0); is(document.getElementsByTagName("audio")[0].NETWORK_EMPTY, 0);
is(document.getElementsByTagName("audio")[0].LOADING, 1); is(document.getElementsByTagName("audio")[0].NETWORK_IDLE, 1);
is(document.getElementsByTagName("audio")[0].LOADED_METADATA, 2); is(document.getElementsByTagName("audio")[0].NETWORK_LOADING, 2);
is(document.getElementsByTagName("audio")[0].LOADED_FIRST_FRAME, 3); is(document.getElementsByTagName("audio")[0].NETWORK_LOADED, 3);
is(document.getElementsByTagName("audio")[0].LOADED, 4); is(document.getElementsByTagName("audio")[0].HAVE_NOTHING, 0);
is(document.getElementsByTagName("audio")[0].DATA_UNAVAILABLE, 0); is(document.getElementsByTagName("audio")[0].HAVE_METADATA, 1);
is(document.getElementsByTagName("audio")[0].CAN_SHOW_CURRENT_FRAME, 1); is(document.getElementsByTagName("audio")[0].HAVE_CURRENT_DATA, 2);
is(document.getElementsByTagName("audio")[0].CAN_PLAY, 2); is(document.getElementsByTagName("audio")[0].HAVE_FUTURE_DATA, 3);
is(document.getElementsByTagName("audio")[0].CAN_PLAY_THROUGH, 3); is(document.getElementsByTagName("audio")[0].HAVE_ENOUGH_DATA, 4);
is(document.getElementsByTagName("source")[0].EMPTY, undefined); is(document.getElementsByTagName("source")[0].NETWORK_EMPTY, undefined);
is(document.getElementsByTagName("source")[0].LOADING, undefined); is(document.getElementsByTagName("source")[0].NETWORK_IDLE, undefined);
is(document.getElementsByTagName("source")[0].LOADED_METADATA, undefined); is(document.getElementsByTagName("source")[0].NETWORK_LOADING, undefined);
is(document.getElementsByTagName("source")[0].LOADED_FIRST_FRAME, undefined); is(document.getElementsByTagName("source")[0].NETWORK_LOADED, undefined);
is(document.getElementsByTagName("source")[0].LOADED, undefined); is(document.getElementsByTagName("source")[0].HAVE_NOTHING, undefined);
is(document.getElementsByTagName("source")[0].DATA_UNAVAILABLE, undefined); is(document.getElementsByTagName("source")[0].HAVE_METADATA, undefined);
is(document.getElementsByTagName("source")[0].CAN_SHOW_CURRENT_FRAME, undefined); is(document.getElementsByTagName("source")[0].HAVE_CURRENT_DATA, undefined);
is(document.getElementsByTagName("source")[0].CAN_PLAY, undefined); is(document.getElementsByTagName("source")[0].HAVE_FUTURE_DATA, undefined);
is(document.getElementsByTagName("source")[0].CAN_PLAY_THROUGH, undefined); is(document.getElementsByTagName("source")[0].HAVE_ENOUGH_DATA, undefined);
is(document.getElementsByTagName("source")[1].EMPTY, undefined); is(HTMLElement.prototype.NETWORK_EMPTY, undefined);
is(document.getElementsByTagName("source")[1].LOADING, undefined); is(HTMLElement.prototype.NETWORK_IDLE, undefined);
is(document.getElementsByTagName("source")[1].LOADED_METADATA, undefined); is(HTMLElement.prototype.NETWORK_LOADING, undefined);
is(document.getElementsByTagName("source")[1].LOADED_FIRST_FRAME, undefined); is(HTMLElement.prototype.NETWORK_LOADED, undefined);
is(document.getElementsByTagName("source")[1].LOADED, undefined); is(HTMLElement.prototype.HAVE_NOTHING, undefined);
is(document.getElementsByTagName("source")[1].DATA_UNAVAILABLE, undefined); is(HTMLElement.prototype.HAVE_METADATA, undefined);
is(document.getElementsByTagName("source")[1].CAN_SHOW_CURRENT_FRAME, undefined); is(HTMLElement.prototype.HAVE_CURRENT_DATA, undefined);
is(document.getElementsByTagName("source")[1].CAN_PLAY, undefined); is(HTMLElement.prototype.HAVE_FUTURE_DATA, undefined);
is(document.getElementsByTagName("source")[1].CAN_PLAY_THROUGH, undefined); is(HTMLElement.prototype.HAVE_ENOUGH_DATA, undefined);
is(HTMLElement.prototype.EMPTY, undefined); todo_is(HTMLMediaElement.prototype.NETWORK_EMPTY, 0, "HTMLMediaElement.prototype.NETWORK_EMPTY");
is(HTMLElement.prototype.LOADING, undefined); todo_is(HTMLMediaElement.prototype.NETWORK_IDLE, 1, "HTMLMediaElement.prototype.NETWORK_IDLE");
is(HTMLElement.prototype.LOADED_METADATA, undefined); todo_is(HTMLMediaElement.prototype.NETWORK_LOADING, 2, "HTMLMediaElement.prototype.NETWORK_LOADING");
is(HTMLElement.prototype.LOADED_FIRST_FRAME, undefined); todo_is(HTMLMediaElement.prototype.NETWORK_LOADED, 3, "HTMLMediaElement.prototype.NETWORK_LOADED");
is(HTMLElement.prototype.LOADED, undefined); todo_is(HTMLMediaElement.prototype.HAVE_NOTHING, 0, "HTMLMediaElement.prototype.HAVE_NOTHING");
is(HTMLElement.prototype.DATA_UNAVAILABLE, undefined); todo_is(HTMLMediaElement.prototype.HAVE_METADATA, 1, "HTMLMediaElement.prototype.HAVE_METADATA");
is(HTMLElement.prototype.CAN_SHOW_CURRENT_FRAME, undefined); todo_is(HTMLMediaElement.prototype.HAVE_CURRENT_DATA, 2, "HTMLMediaElement.prototype.HAVE_CURRENT_DATA");
is(HTMLElement.prototype.CAN_PLAY, undefined); todo_is(HTMLMediaElement.prototype.HAVE_FUTURE_DATA, 3, "HTMLMediaElement.prototype.HAVE_FUTURE_DATA");
is(HTMLElement.prototype.CAN_PLAY_THROUGH, undefined); todo_is(HTMLMediaElement.prototype.HAVE_ENOUGH_DATA, 4, "HTMLMediaElement.prototype.HAVE_ENOUGH_DATA");
is(HTMLVideoElement.prototype.EMPTY, 0); is(HTMLVideoElement.prototype.NETWORK_EMPTY, 0);
is(HTMLVideoElement.prototype.LOADING, 1); is(HTMLVideoElement.prototype.NETWORK_IDLE, 1);
is(HTMLVideoElement.prototype.LOADED_METADATA, 2); is(HTMLVideoElement.prototype.NETWORK_LOADING, 2);
is(HTMLVideoElement.prototype.LOADED_FIRST_FRAME, 3); is(HTMLVideoElement.prototype.NETWORK_LOADED, 3);
is(HTMLVideoElement.prototype.LOADED, 4); is(HTMLVideoElement.prototype.HAVE_NOTHING, 0);
is(HTMLVideoElement.prototype.DATA_UNAVAILABLE, 0); is(HTMLVideoElement.prototype.HAVE_METADATA, 1);
is(HTMLVideoElement.prototype.CAN_SHOW_CURRENT_FRAME, 1); is(HTMLVideoElement.prototype.HAVE_CURRENT_DATA, 2);
is(HTMLVideoElement.prototype.CAN_PLAY, 2); is(HTMLVideoElement.prototype.HAVE_FUTURE_DATA, 3);
is(HTMLVideoElement.prototype.CAN_PLAY_THROUGH, 3); is(HTMLVideoElement.prototype.HAVE_ENOUGH_DATA, 4);
is(HTMLAudioElement.prototype.EMPTY, 0); is(HTMLAudioElement.prototype.NETWORK_EMPTY, 0);
is(HTMLAudioElement.prototype.LOADING, 1); is(HTMLAudioElement.prototype.NETWORK_IDLE, 1);
is(HTMLAudioElement.prototype.LOADED_METADATA, 2); is(HTMLAudioElement.prototype.NETWORK_LOADING, 2);
is(HTMLAudioElement.prototype.LOADED_FIRST_FRAME, 3); is(HTMLAudioElement.prototype.NETWORK_LOADED, 3);
is(HTMLAudioElement.prototype.LOADED, 4); is(HTMLAudioElement.prototype.HAVE_NOTHING, 0);
is(HTMLAudioElement.prototype.DATA_UNAVAILABLE, 0); is(HTMLAudioElement.prototype.HAVE_METADATA, 1);
is(HTMLAudioElement.prototype.CAN_SHOW_CURRENT_FRAME, 1); is(HTMLAudioElement.prototype.HAVE_CURRENT_DATA, 2);
is(HTMLAudioElement.prototype.CAN_PLAY, 2); is(HTMLAudioElement.prototype.HAVE_FUTURE_DATA, 3);
is(HTMLAudioElement.prototype.CAN_PLAY_THROUGH, 3); is(HTMLAudioElement.prototype.HAVE_ENOUGH_DATA, 4);
is(HTMLSourceElement.prototype.EMPTY, undefined); is(HTMLSourceElement.prototype.NETWORK_EMPTY, undefined);
is(HTMLSourceElement.prototype.LOADING, undefined); is(HTMLSourceElement.prototype.NETWORK_IDLE, undefined);
is(HTMLSourceElement.prototype.LOADED_METADATA, undefined); is(HTMLSourceElement.prototype.NETWORK_LOADING, undefined);
is(HTMLSourceElement.prototype.LOADED_FIRST_FRAME, undefined); is(HTMLSourceElement.prototype.NETWORK_LOADED, undefined);
is(HTMLSourceElement.prototype.LOADED, undefined); is(HTMLSourceElement.prototype.HAVE_NOTHING, undefined);
is(HTMLSourceElement.prototype.DATA_UNAVAILABLE, undefined); is(HTMLSourceElement.prototype.HAVE_METADATA, undefined);
is(HTMLSourceElement.prototype.CAN_SHOW_CURRENT_FRAME, undefined); is(HTMLSourceElement.prototype.HAVE_CURRENT_DATA, undefined);
is(HTMLSourceElement.prototype.CAN_PLAY, undefined); is(HTMLSourceElement.prototype.HAVE_FUTURE_DATA, undefined);
is(HTMLSourceElement.prototype.CAN_PLAY_THROUGH, undefined); is(HTMLSourceElement.prototype.HAVE_ENOUGH_DATA, undefined);
</script> </script>
</pre> </pre>
</body> </body>

Просмотреть файл

@ -0,0 +1,143 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Media test: media selection</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
function maketest(expect_load, attach_media, name, type, check_metadata) {
return function (testNum) {
var e = document.createElement('video');
if (expect_load) {
// this could be loadedmetadata, but needs bug 466410 fixed
e.addEventListener('loadeddata', function () {
ok(e.readyState >= HTMLMediaElement.HAVE_METADATA,
'test ' + testNum + ' networkState ' + e.networkState + ' expected >= ' + e.LOADED_METADATA);
is(e.currentSrc.substring(e.currentSrc.length - name.length), name, 'test ' + testNum);
check_metadata(e);
e.parentNode.removeChild(e);
runNextTest();
}, false);
}
attach_media(e, name, type);
if (expect_load) {
ok(e.networkState >= HTMLMediaElement.NETWORK_LOADING,
'test ' + testNum + ' networkState ' + e.networkState + ' expected >= ' + e.LOADING);
} else {
ok(e.networkState == HTMLMediaElement.NETWORK_EMPTY,
'test ' + testNum + ' networkState ' + e.networkState + ' expected ' + e.EMPTY);
is(e.currentSrc, '', 'test ' + testNum);
e.parentNode.removeChild(e);
runNextTest();
}
}
}
function set_src(element, name, type) {
element.src = name;
document.body.appendChild(element);
}
function add_source(element, name, type) {
do_add_source(element, name, type);
document.body.appendChild(element);
}
function do_add_source(element, name, type) {
var source = document.createElement('source');
if (type) {
source.type = type;
}
source.src = name;
element.appendChild(source);
}
function add_sources_last(element, name, type) {
do_add_source(element, name, 'unsupported/type');
do_add_source(element, name, type);
document.body.appendChild(element);
}
function add_sources_first(element, name, type) {
do_add_source(element, name, type);
do_add_source(element, name, 'unsupported/type');
document.body.appendChild(element);
}
function late_add_sources_last(element, name, type) {
document.body.appendChild(element);
do_add_source(element, name, 'unsupported/type');
do_add_source(element, name, type);
}
function late_add_sources_first(element, name, type) {
document.body.appendChild(element);
do_add_source(element, name, type);
do_add_source(element, name, 'unsupported/type');
}
function check_ogg(e) {
ok(e.videoWidth == 320 && e.videoHeight == 240, "video should be 320x240");
}
function check_wav(e) {
ok(e.duration > 0.9 && e.duration < 1.1, "duration should be around 1.0");
}
var nextTest = 0;
var subTests = [
maketest(true, set_src, '320x240.ogg', null, check_ogg),
maketest(true, add_source, '320x240.ogg', null, check_ogg),
maketest(true, add_source, '320x240.ogg', 'application/ogg', check_ogg),
maketest(true, add_sources_last, '320x240.ogg', null, check_ogg),
maketest(true, add_sources_first, '320x240.ogg', 'application/ogg', check_ogg),
maketest(true, set_src, 'r11025_u8_c1.wav', null, check_wav),
maketest(true, add_source, 'r11025_u8_c1.wav', null, check_wav),
maketest(true, add_source, 'r11025_u8_c1.wav', 'audio/x-wav', check_wav),
maketest(true, add_sources_last, 'r11025_u8_c1.wav', null, check_wav),
maketest(true, add_sources_first, 'r11025_u8_c1.wav', 'audio/x-wav', check_wav),
// type hint matches a decoder, actual type matches different decoder
maketest(true, add_source, '320x240.ogg', 'audio/x-wav', check_ogg),
maketest(true, add_source, 'r11025_u8_c1.wav', 'application/ogg', check_wav),
// should not start loading, type excludes it from media candiate list
maketest(false, add_source, '320x240.ogg', 'bogus/type', null),
maketest(false, add_source, 'r11025_u8_c1.wav', 'bogus/type', null),
maketest(false, add_source, 'unknown.raw', 'bogus/type', null),
// should start loading, then fire error, needs bug 462455 fixed
// maketest(true, add_source, 'unknown.raw', 'application/ogg', null),
// maketest(true, add_source, 'unknown.raw', 'audio/x-wav', null),
// element doesn't notice source children attached later, needs bug 462455 fixed
// maketest(true, late_add_sources_last, '320x240.ogg', null, 0.2, 0.4),
// maketest(true, late_add_sources_first, '320x240.ogg', 'application/ogg', 0.2, 0.4),
// maketest(true, late_add_sources_last, 'r11025_u8_c1.wav', null, 0.2, 0.4),
// maketest(true, late_add_sources_first, 'r11025_u8_c1.wav', 'audio/x-wav', 0.2, 0.4),
SimpleTest.finish
];
function runNextTest() {
setTimeout(function () {
dump('subtest ' + nextTest + '\n');
subTests[nextTest](nextTest);
nextTest += 1;
}, 0);
}
addLoadEvent(runNextTest);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -16,7 +16,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=467972
src="320x240.ogg" src="320x240.ogg"
onloadedmetadata="return loadedMetaData();" onloadedmetadata="return loadedMetaData();"
onended="playbackEnded();" onended="playbackEnded();"
onloadedfirstframe="return loadedFirstFrame();" onloadeddata="return loadedData();"
onseeking="seekStarted();" onseeking="seekStarted();"
onseeked="seekEnded();" onseeked="seekEnded();"
controls></video> controls></video>
@ -34,7 +34,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=467972
var gEnded = false; var gEnded = false;
var gSeekStarted = false; var gSeekStarted = false;
var gSeekEnded = false; var gSeekEnded = false;
var gLoadedFirstFrameCount = 0; var gLoadedDataCount = 0;
var gLoadedMetaDataCount = 0; var gLoadedMetaDataCount = 0;
function get(id) { function get(id) {
@ -54,9 +54,9 @@ function seekEnded() {
video().play(); video().play();
} }
function loadedFirstFrame() { function loadedData() {
gLoadedFirstFrameCount++; gLoadedDataCount++;
ok(gLoadedFirstFrameCount <= 1, "No more than 1 onloadedfirstframe events"); ok(gLoadedDataCount <= 1, "No more than 1 onloaddata events");
} }
function loadedMetaData() { function loadedMetaData() {
@ -73,8 +73,8 @@ function playbackEnded() {
} else { } else {
ok(gSeekEnded, "Should have received seekended"); ok(gSeekEnded, "Should have received seekended");
ok(gSeekStarted, "Should have received seekstarted"); ok(gSeekStarted, "Should have received seekstarted");
ok(gLoadedFirstFrameCount == 1, "Should have 1 onloadedfirstframe event"); is(gLoadedDataCount, 1, "Should have 1 onloadeddata event");
ok(gLoadedMetaDataCount == 1, "Should have 1 onloadedmetadata event"); is(gLoadedMetaDataCount, 1, "Should have 1 onloadedmetadata event");
SimpleTest.finish(); SimpleTest.finish();
} }
return false; return false;

Просмотреть файл

@ -47,6 +47,7 @@ function seekStarted() {
return false; return false;
var v = document.getElementById('v'); var v = document.getElementById('v');
v.pause();
startPassed = true; startPassed = true;
seekFlagStart = v.seeking; seekFlagStart = v.seeking;
return false; return false;
@ -59,6 +60,7 @@ function seekEnded() {
var v = document.getElementById('v'); var v = document.getElementById('v');
var t = v.currentTime; var t = v.currentTime;
ok(t >= 2 && t <= 3, "Video currentTime should be around 2: " + t); ok(t >= 2 && t <= 3, "Video currentTime should be around 2: " + t);
v.play();
endPassed = true; endPassed = true;
seekFlagEnd = v.seeking; seekFlagEnd = v.seeking;
return false; return false;

Просмотреть файл

@ -10,14 +10,14 @@
<video id='v'></video> <video id='v'></video>
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
// http://www.whatwg.org/specs/web-apps/current-work/#seek // http://www.whatwg.org/specs/web-apps/current-work/#dom-media-seek
// If the media element's networkState is less than LOADED_METADATA, // If the media element's readyState is HAVE_NOTHING, then the user agent
// then the user agent must raise an INVALID_STATE_ERR exception // must raise an INVALID_STATE_ERR exception.
var v = document.getElementById('v'); var v = document.getElementById('v');
var passed = false; var passed = false;
ok(v.networkState < HTMLMediaElement.LOADED_METADATA, ok(v.readyState == HTMLMediaElement.HAVE_NOTHING,
"Invalid network state in media element"); "Invalid ready state in media element");
try { try {
v.seek(1); v.seek(1);

Просмотреть файл

@ -43,8 +43,6 @@ function seekEnded() {
if (completed) if (completed)
return false; return false;
var t = document.getElementById('v').currentTime;
ok(t >= 2 && t <= 3, "Video currentTime should be around 2: " + t);
endPassed = true; endPassed = true;
return false; return false;
} }

Просмотреть файл

@ -17,6 +17,7 @@
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
// Test for a seek, followed by a play before the seek completes, ensure we play at the end of the seek. // Test for a seek, followed by a play before the seek completes, ensure we play at the end of the seek.
var startPassed = false; var startPassed = false;
var endPassed = false;
var completed = false; var completed = false;
var seekCount = 0; var seekCount = 0;
@ -41,15 +42,15 @@ function seekStarted() {
function seekEnded() { function seekEnded() {
if (completed) if (completed)
return false; return false;
var v = document.getElementById('v'); endPassed = true;
ok(v.currentTime>=2 && v.currentTime<=2.2, "First seek");
return false; return false;
} }
function playbackEnded() { function playbackEnded() {
if (completed) if (completed)
return false; return false;
ok(true, "Playback ended"); ok(startPassed, "Got seeking event");
ok(endPassed, "Got seeked event");
completed = true; completed = true;
SimpleTest.finish(); SimpleTest.finish();
return false; return false;

Просмотреть файл

@ -44,8 +44,6 @@ function seekEnded() {
if (completed) if (completed)
return false; return false;
var t = document.getElementById('v').currentTime;
ok(t >= 0.4 && t <= 0.6, "Video currentTime should be around 0.5: " + t);
endPassed = true; endPassed = true;
return false; return false;
} }

Просмотреть файл

@ -18,6 +18,7 @@
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
// Test for a seek, followed by a play before the seek completes, ensure we play at the end of the seek. // Test for a seek, followed by a play before the seek completes, ensure we play at the end of the seek.
var startPassed = false; var startPassed = false;
var endPassed = false;
var completed = false; var completed = false;
var seekCount = 0; var seekCount = 0;
@ -42,15 +43,15 @@ function seekStarted() {
function seekEnded() { function seekEnded() {
if (completed) if (completed)
return false; return false;
var v = document.getElementById('v'); endPassed = true;
ok(v.currentTime>=0.4 && v.currentTime<=0.6, "First seek");
return false; return false;
} }
function playbackEnded() { function playbackEnded() {
if (completed) if (completed)
return false; return false;
ok(true, "Playback ended"); ok(startPassed, "Got seeking event");
ok(endPassed, "Got seeked event");
completed = true; completed = true;
SimpleTest.finish(); SimpleTest.finish();
return false; return false;

Просмотреть файл

@ -10,7 +10,7 @@
<audio id='v' <audio id='v'
onloadedmetadata='return startTest();' onloadedmetadata='return startTest();'
onended='return playbackEnded();'> onended='return playbackEnded();'>
<source type='audio/x-wav' src='r11025_s16_c1_trunc.wav'> <source type='audio/x-wav' src='r11025_u8_c1_trunc.wav'>
</audio> </audio>
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
@ -23,7 +23,7 @@ function startTest() {
if (completed) if (completed)
return false; return false;
ok(v.duration > 0.3 && v.duration < 0.5, "Duration should be around 0.4: " + v.duration); ok(v.duration > 1.7 && v.duration < 1.9, "Duration should be around 1.8: " + v.duration);
v.play(); v.play();
return false; return false;
@ -34,7 +34,7 @@ function playbackEnded() {
return false return false
completed = true; completed = true;
ok(v.currentTime >= 0.3 && v.currentTime <= 0.5, ok(v.currentTime >= 1.7 && v.currentTime <= 1.9,
"Checking currentTime at end: " + v.currentTime); "Checking currentTime at end: " + v.currentTime);
ok(v.ended, "Checking playback has ended"); ok(v.ended, "Checking playback has ended");
SimpleTest.finish(); SimpleTest.finish();

Просмотреть файл

@ -11,7 +11,7 @@
onloadedmetadata='return startTest();' onloadedmetadata='return startTest();'
onseeked='return endSeek();' onseeked='return endSeek();'
onended='return endTest();'> onended='return endTest();'>
<source type='audio/x-wav' src='r11025_s16_c1_trunc.wav'> <source type='audio/x-wav' src='r11025_u8_c1_trunc.wav'>
</audio> </audio>
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
@ -24,9 +24,9 @@ function startTest() {
if (completed) if (completed)
return false; return false;
ok(v.duration > 0.3 && v.duration < 0.5, "Duration should be around 0.4: " + v.duration); ok(v.duration > 1.7 && v.duration < 1.9, "Duration should be around 1.8: " + v.duration);
v.currentTime = 1.0; v.currentTime = 3.0;
return false; return false;
} }
@ -41,7 +41,7 @@ function endSeek() {
return false return false
completed = true; completed = true;
ok(v.currentTime >= 0.3 && v.currentTime <= 0.5, ok(v.currentTime >= 1.7 && v.currentTime <= 1.9,
"Checking currentTime at end: " + v.currentTime); "Checking currentTime at end: " + v.currentTime);
v.play(); v.play();
return false; return false;

Просмотреть файл

@ -71,7 +71,7 @@ nsXBLProtoImplField::~nsXBLProtoImplField()
if (mFieldText) if (mFieldText)
nsMemory::Free(mFieldText); nsMemory::Free(mFieldText);
NS_Free(mName); NS_Free(mName);
delete mNext; NS_CONTENT_DELETE_LIST_MEMBER(nsXBLProtoImplField, this, mNext);
} }
void void

Просмотреть файл

@ -47,6 +47,7 @@
#include "nsIJSRuntimeService.h" #include "nsIJSRuntimeService.h"
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
#include "nsReadableUtils.h" #include "nsReadableUtils.h"
#include "nsContentUtils.h"
#include "nsCycleCollectionParticipant.h" #include "nsCycleCollectionParticipant.h"
class nsIScriptContext; class nsIScriptContext;
@ -99,7 +100,10 @@ class nsXBLProtoImplMember
{ {
public: public:
nsXBLProtoImplMember(const PRUnichar* aName) :mNext(nsnull) { mName = ToNewUnicode(nsDependentString(aName)); } nsXBLProtoImplMember(const PRUnichar* aName) :mNext(nsnull) { mName = ToNewUnicode(nsDependentString(aName)); }
virtual ~nsXBLProtoImplMember() { nsMemory::Free(mName); delete mNext; } virtual ~nsXBLProtoImplMember() {
nsMemory::Free(mName);
NS_CONTENT_DELETE_LIST_MEMBER(nsXBLProtoImplMember, this, mNext);
}
nsXBLProtoImplMember* GetNext() { return mNext; } nsXBLProtoImplMember* GetNext() { return mNext; }
void SetNext(nsXBLProtoImplMember* aNext) { mNext = aNext; } void SetNext(nsXBLProtoImplMember* aNext) { mNext = aNext; }

Просмотреть файл

@ -59,7 +59,7 @@ struct nsXBLParameter {
~nsXBLParameter() { ~nsXBLParameter() {
MOZ_COUNT_DTOR(nsXBLParameter); MOZ_COUNT_DTOR(nsXBLParameter);
nsMemory::Free(mName); nsMemory::Free(mName);
delete mNext; NS_CONTENT_DELETE_LIST_MEMBER(nsXBLParameter, this, mNext);
} }
}; };

Просмотреть файл

@ -123,7 +123,9 @@ protected:
mDstNameSpace(aDstNameSpace), mDstNameSpace(aDstNameSpace),
mNext(nsnull) { } mNext(nsnull) { }
~nsXBLAttributeEntry() { delete mNext; } ~nsXBLAttributeEntry() {
NS_CONTENT_DELETE_LIST_MEMBER(nsXBLAttributeEntry, this, mNext);
}
private: private:
// Hide so that only Create() and Destroy() can be used to // Hide so that only Create() and Destroy() can be used to

Просмотреть файл

@ -67,7 +67,6 @@
#include "nsPIWindowRoot.h" #include "nsPIWindowRoot.h"
#include "nsIDOMWindowInternal.h" #include "nsIDOMWindowInternal.h"
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
#include "nsContentUtils.h"
#include "nsIScriptError.h" #include "nsIScriptError.h"
#include "nsXPIDLString.h" #include "nsXPIDLString.h"
#include "nsReadableUtils.h" #include "nsReadableUtils.h"
@ -156,7 +155,7 @@ nsXBLPrototypeHandler::~nsXBLPrototypeHandler()
} }
// We own the next handler in the chain, so delete it now. // We own the next handler in the chain, so delete it now.
delete mNextHandler; NS_CONTENT_DELETE_LIST_MEMBER(nsXBLPrototypeHandler, this, mNextHandler);
} }
already_AddRefed<nsIContent> already_AddRefed<nsIContent>

Просмотреть файл

@ -39,6 +39,7 @@
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsICSSLoaderObserver.h" #include "nsICSSLoaderObserver.h"
#include "nsCOMArray.h" #include "nsCOMArray.h"
#include "nsContentUtils.h"
#include "nsCycleCollectionParticipant.h" #include "nsCycleCollectionParticipant.h"
class nsIContent; class nsIContent;
@ -66,7 +67,7 @@ struct nsXBLResource {
~nsXBLResource() { ~nsXBLResource() {
MOZ_COUNT_DTOR(nsXBLResource); MOZ_COUNT_DTOR(nsXBLResource);
delete mNext; NS_CONTENT_DELETE_LIST_MEMBER(nsXBLResource, this, mNext);
} }
}; };

Просмотреть файл

@ -74,7 +74,6 @@
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsRDFCID.h" #include "nsRDFCID.h"
#include "nsParserUtils.h" #include "nsParserUtils.h"
#include "nsIMIMEHeaderParam.h"
#include "nsXPIDLString.h" #include "nsXPIDLString.h"
#include "nsReadableUtils.h" #include "nsReadableUtils.h"
#include "nsXULElement.h" #include "nsXULElement.h"
@ -983,16 +982,10 @@ XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes,
src.Assign(aAttributes[1]); src.Assign(aAttributes[1]);
} }
else if (key.EqualsLiteral("type")) { else if (key.EqualsLiteral("type")) {
nsCOMPtr<nsIMIMEHeaderParam> mimeHdrParser = nsDependentString str(aAttributes[1]);
do_GetService("@mozilla.org/network/mime-hdrparam;1"); nsContentTypeParser parser(str);
NS_ENSURE_TRUE(mimeHdrParser, NS_ERROR_FAILURE);
NS_ConvertUTF16toUTF8 typeAndParams(aAttributes[1]);
nsAutoString mimeType; nsAutoString mimeType;
rv = mimeHdrParser->GetParameter(typeAndParams, nsnull, rv = parser.GetType(mimeType);
EmptyCString(), PR_FALSE, nsnull,
mimeType);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
if (rv == NS_ERROR_INVALID_ARG) { if (rv == NS_ERROR_INVALID_ARG) {
// Might as well bail out now instead of setting langID to // Might as well bail out now instead of setting langID to
@ -1043,9 +1036,7 @@ XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes,
if (langID != nsIProgrammingLanguage::UNKNOWN) { if (langID != nsIProgrammingLanguage::UNKNOWN) {
// Get the version string, and ensure the language supports it. // Get the version string, and ensure the language supports it.
nsAutoString versionName; nsAutoString versionName;
rv = mimeHdrParser->GetParameter(typeAndParams, "version", rv = parser.GetParameter("version", versionName);
EmptyCString(), PR_FALSE, nsnull,
versionName);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
if (rv != NS_ERROR_INVALID_ARG) if (rv != NS_ERROR_INVALID_ARG)
return rv; return rv;
@ -1071,9 +1062,7 @@ XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes,
version |= JSVERSION_HAS_XML; version |= JSVERSION_HAS_XML;
nsAutoString value; nsAutoString value;
rv = mimeHdrParser->GetParameter(typeAndParams, "e4x", rv = parser.GetParameter("e4x", value);
EmptyCString(), PR_FALSE, nsnull,
value);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
if (rv != NS_ERROR_INVALID_ARG) if (rv != NS_ERROR_INVALID_ARG)
return rv; return rv;

Просмотреть файл

@ -2006,8 +2006,6 @@ nsXULDocument::StartLayout(void)
if (! docShell) if (! docShell)
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
nsRect r = cx->GetVisibleArea();
// Trigger a refresh before the call to InitialReflow(), // Trigger a refresh before the call to InitialReflow(),
// because the view manager's UpdateView() function is // because the view manager's UpdateView() function is
// dropping dirty rects if refresh is disabled rather than // dropping dirty rects if refresh is disabled rather than
@ -2030,6 +2028,10 @@ nsXULDocument::StartLayout(void)
mMayStartLayout = PR_TRUE; mMayStartLayout = PR_TRUE;
// Don't try to call GetVisibleArea earlier than this --- the EnableRefresh call
// above can flush reflows, which can cause a parent document to be flushed,
// calling ResizeReflow on our document which does SetVisibleArea.
nsRect r = cx->GetVisibleArea();
// Make sure we're holding a strong ref to |shell| before we call // Make sure we're holding a strong ref to |shell| before we call
// InitialReflow() // InitialReflow()
nsCOMPtr<nsIPresShell> shellGrip = shell; nsCOMPtr<nsIPresShell> shellGrip = shell;

Просмотреть файл

@ -56,7 +56,7 @@
#endif #endif
%} %}
[scriptable, uuid(e3e2a8c1-4b56-4154-8ef2-fc4b2bb42e97)] [scriptable, uuid(c19f04dc-f09a-4b1f-b354-af65a12aa8bc)]
interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement
{ {
// error state // error state
@ -65,19 +65,20 @@ interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement
// network state // network state
attribute DOMString src; attribute DOMString src;
readonly attribute DOMString currentSrc; readonly attribute DOMString currentSrc;
const unsigned short EMPTY = 0; const unsigned short NETWORK_EMPTY = 0;
const unsigned short LOADING = 1; const unsigned short NETWORK_IDLE = 1;
const unsigned short LOADED_METADATA = 2; const unsigned short NETWORK_LOADING = 2;
const unsigned short LOADED_FIRST_FRAME = 3; const unsigned short NETWORK_LOADED = 3;
const unsigned short LOADED = 4;
readonly attribute unsigned short networkState; readonly attribute unsigned short networkState;
void load(); void load();
DOMString canPlayType(in DOMString type);
// ready state // ready state
const unsigned short DATA_UNAVAILABLE = 0; const unsigned short HAVE_NOTHING = 0;
const unsigned short CAN_SHOW_CURRENT_FRAME = 1; const unsigned short HAVE_METADATA = 1;
const unsigned short CAN_PLAY = 2; const unsigned short HAVE_CURRENT_DATA = 2;
const unsigned short CAN_PLAY_THROUGH = 3; const unsigned short HAVE_FUTURE_DATA = 3;
const unsigned short HAVE_ENOUGH_DATA = 4;
readonly attribute unsigned short readyState; readonly attribute unsigned short readyState;
readonly attribute boolean seeking; readonly attribute boolean seeking;

Просмотреть файл

@ -1635,12 +1635,12 @@ nsDOMClassInfo::DefineStaticJSVals(JSContext *cx)
// static // static
nsresult nsresult
nsDOMClassInfo::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native, nsDOMClassInfo::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
const nsIID& aIID, jsval *vp, const nsIID* aIID, jsval *vp,
nsIXPConnectJSObjectHolder **aHolder) nsIXPConnectJSObjectHolder **aHolder)
{ {
*aHolder = nsnull;
if (!native) { if (!native) {
NS_ASSERTION(!aHolder || !*aHolder, "*aHolder should be null!");
*vp = JSVAL_NULL; *vp = JSVAL_NULL;
return NS_OK; return NS_OK;
@ -1648,19 +1648,8 @@ nsDOMClassInfo::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
NS_ENSURE_TRUE(sXPConnect, NS_ERROR_UNEXPECTED); NS_ENSURE_TRUE(sXPConnect, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; return sXPConnect->WrapNativeToJSVal(cx, ::JS_GetGlobalForObject(cx, scope),
nsresult rv = sXPConnect->WrapNative(cx, ::JS_GetGlobalForObject(cx, scope), native, aIID, vp, aHolder);
native, aIID, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
JSObject* obj = nsnull;
rv = holder->GetJSObject(&obj);
NS_ENSURE_SUCCESS(rv, rv);
*vp = OBJECT_TO_JSVAL(obj);
holder.swap(*aHolder);
return rv;
} }
// static // static
@ -1691,7 +1680,7 @@ nsDOMClassInfo::ThrowJSException(JSContext *cx, nsresult aResult)
jsval jv; jsval jv;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, ::JS_GetGlobalObject(cx), exception, rv = WrapNative(cx, ::JS_GetGlobalObject(cx), exception,
NS_GET_IID(nsIException), &jv, getter_AddRefs(holder)); &NS_GET_IID(nsIException), &jv, getter_AddRefs(holder));
if (NS_FAILED(rv) || JSVAL_IS_NULL(jv)) { if (NS_FAILED(rv) || JSVAL_IS_NULL(jv)) {
break; break;
} }
@ -4495,8 +4484,7 @@ nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj,
if (result) { if (result) {
jsval v; jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, obj, result, NS_GET_IID(nsISupports), &v, nsresult rv = WrapNative(cx, obj, result, &v, getter_AddRefs(holder));
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, JS_FALSE); NS_ENSURE_SUCCESS(rv, JS_FALSE);
if (!::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(jsstr), if (!::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(jsstr),
@ -4690,7 +4678,7 @@ nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, frameWin->GetGlobalJSObject(), frame, rv = WrapNative(cx, frameWin->GetGlobalJSObject(), frame,
NS_GET_IID(nsIDOMWindow), vp, &NS_GET_IID(nsIDOMWindow), vp,
getter_AddRefs(holder)); getter_AddRefs(holder));
} }
@ -4807,7 +4795,7 @@ nsWindowSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && location, rv); NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && location, rv);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, location, NS_GET_IID(nsIDOMLocation), vp, rv = WrapNative(cx, obj, location, &NS_GET_IID(nsIDOMLocation), vp,
getter_AddRefs(holder)); getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -5062,8 +5050,8 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner,
} }
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = nsDOMGenericSH::WrapNative(cx, obj, native, NS_GET_IID(nsISupports), rv = nsDOMGenericSH::WrapNative(cx, obj, native, rval,
rval, getter_AddRefs(holder)); getter_AddRefs(holder));
return rv; return rv;
} }
@ -5529,7 +5517,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
jsval v; jsval v;
rv = WrapNative(cx, obj, constructor, NS_GET_IID(nsIDOMDOMConstructor), &v, rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor), &v,
getter_AddRefs(holder)); getter_AddRefs(holder));
sDoSecurityCheckInAddProperty = doSecurityCheckInAddProperty; sDoSecurityCheckInAddProperty = doSecurityCheckInAddProperty;
@ -5591,7 +5579,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
jsval v; jsval v;
rv = WrapNative(cx, obj, constructor, NS_GET_IID(nsIDOMDOMConstructor), &v, rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor), &v,
getter_AddRefs(holder)); getter_AddRefs(holder));
sDoSecurityCheckInAddProperty = doSecurityCheckInAddProperty; sDoSecurityCheckInAddProperty = doSecurityCheckInAddProperty;
@ -5806,7 +5794,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
jsval val; jsval val;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, constructor, NS_GET_IID(nsIDOMDOMConstructor), rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor),
&val, getter_AddRefs(holder)); &val, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -5854,8 +5842,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
scope = aWin->GetGlobalJSObject(); scope = aWin->GetGlobalJSObject();
} }
rv = WrapNative(cx, scope, native, NS_GET_IID(nsISupports), &prop_val, rv = WrapNative(cx, scope, native, &prop_val, getter_AddRefs(holder));
getter_AddRefs(holder));
} }
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -6146,7 +6133,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
jsval v; jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, wrapperObj, child_win, rv = WrapNative(cx, wrapperObj, child_win,
NS_GET_IID(nsIDOMWindowInternal), &v, &NS_GET_IID(nsIDOMWindowInternal), &v,
getter_AddRefs(holder)); getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -6267,7 +6254,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
jsval v; jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, scope, location, NS_GET_IID(nsIDOMLocation), &v, rv = WrapNative(cx, scope, location, &NS_GET_IID(nsIDOMLocation), &v,
getter_AddRefs(holder)); getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -6324,7 +6311,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
jsval v; jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, navigator, NS_GET_IID(nsIDOMNavigator), &v, rv = WrapNative(cx, obj, navigator, &NS_GET_IID(nsIDOMNavigator), &v,
getter_AddRefs(holder)); getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -6348,7 +6335,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
jsval v; jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, document, NS_GET_IID(nsIDOMDocument), &v, rv = WrapNative(cx, obj, document, &NS_GET_IID(nsIDOMDocument), &v,
getter_AddRefs(holder)); getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -6953,8 +6940,7 @@ nsNodeSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj,
jsval v; jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, globalObj, native_parent, nsresult rv = WrapNative(cx, globalObj, native_parent, &v,
NS_GET_IID(nsISupports), &v,
getter_AddRefs(holder)); getter_AddRefs(holder));
*parentObj = JSVAL_TO_OBJECT(v); *parentObj = JSVAL_TO_OBJECT(v);
@ -7021,7 +7007,7 @@ nsNodeSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
} }
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, obj, uri, NS_GET_IID(nsIURI), vp, nsresult rv = WrapNative(cx, obj, uri, &NS_GET_IID(nsIURI), vp,
getter_AddRefs(holder)); getter_AddRefs(holder));
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
} }
@ -7032,7 +7018,7 @@ nsNodeSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, obj, node->NodePrincipal(), nsresult rv = WrapNative(cx, obj, node->NodePrincipal(),
NS_GET_IID(nsIPrincipal), vp, &NS_GET_IID(nsIPrincipal), vp,
getter_AddRefs(holder)); getter_AddRefs(holder));
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
} }
@ -7730,9 +7716,7 @@ nsArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (array_item) { if (array_item) {
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; rv = WrapNative(cx, obj, array_item, vp);
rv = WrapNative(cx, obj, array_item, NS_GET_IID(nsISupports), vp,
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = NS_SUCCESS_I_DID_SOMETHING; rv = NS_SUCCESS_I_DID_SOMETHING;
@ -7766,8 +7750,7 @@ nsNodeListSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
jsval v; jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, globalObj, native_parent, nsresult rv = WrapNative(cx, globalObj, native_parent, &v,
NS_GET_IID(nsISupports), &v,
getter_AddRefs(holder)); getter_AddRefs(holder));
*parentObj = JSVAL_TO_OBJECT(v); *parentObj = JSVAL_TO_OBJECT(v);
@ -7867,9 +7850,7 @@ nsNamedArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (item) { if (item) {
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; rv = WrapNative(cx, obj, item, vp);
rv = WrapNative(cx, obj, item, NS_GET_IID(nsISupports), vp,
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = NS_SUCCESS_I_DID_SOMETHING; rv = NS_SUCCESS_I_DID_SOMETHING;
@ -7981,8 +7962,7 @@ nsContentListSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
jsval v; jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, globalObj, native_parent, nsresult rv = WrapNative(cx, globalObj, native_parent, &v,
NS_GET_IID(nsISupports), &v,
getter_AddRefs(holder)); getter_AddRefs(holder));
*parentObj = JSVAL_TO_OBJECT(v); *parentObj = JSVAL_TO_OBJECT(v);
@ -8098,7 +8078,7 @@ nsDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
jsval v; jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, location, NS_GET_IID(nsIDOMLocation), &v, rv = WrapNative(cx, obj, location, &NS_GET_IID(nsIDOMLocation), &v,
getter_AddRefs(holder)); getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -8142,7 +8122,7 @@ nsDocumentSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE); NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, obj, uri, NS_GET_IID(nsIURI), vp, nsresult rv = WrapNative(cx, obj, uri, &NS_GET_IID(nsIURI), vp,
getter_AddRefs(holder)); getter_AddRefs(holder));
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
@ -8174,7 +8154,7 @@ nsDocumentSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, location, NS_GET_IID(nsIDOMLocation), vp, rv = WrapNative(cx, obj, location, &NS_GET_IID(nsIDOMLocation), vp,
getter_AddRefs(holder)); getter_AddRefs(holder));
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
} }
@ -8232,7 +8212,7 @@ nsDocumentSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
jsval winVal; jsval winVal;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, win, NS_GET_IID(nsIDOMWindow), &winVal, rv = WrapNative(cx, obj, win, &NS_GET_IID(nsIDOMWindow), &winVal,
getter_AddRefs(holder)); getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -8351,7 +8331,7 @@ nsHTMLDocumentSH::DocumentOpen(JSContext *cx, JSObject *obj, uintN argc,
} }
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, retval, NS_GET_IID(nsIDOMDocument), rval, rv = WrapNative(cx, obj, retval, &NS_GET_IID(nsIDOMDocument), rval,
getter_AddRefs(holder)); getter_AddRefs(holder));
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to wrap native!"); NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to wrap native!");
@ -8426,8 +8406,7 @@ nsHTMLDocumentSH::GetDocumentAllNodeList(JSContext *cx, JSObject *obj,
rv |= domdoc->GetElementsByTagName(NS_LITERAL_STRING("*"), nodeList); rv |= domdoc->GetElementsByTagName(NS_LITERAL_STRING("*"), nodeList);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv |= nsDOMClassInfo::WrapNative(cx, obj, *nodeList, rv |= nsDOMClassInfo::WrapNative(cx, obj, *nodeList, &collection,
NS_GET_IID(nsISupports), &collection,
getter_AddRefs(holder)); getter_AddRefs(holder));
// ... and store it in our reserved slot. // ... and store it in our reserved slot.
@ -8514,9 +8493,7 @@ nsHTMLDocumentSH::DocumentAllGetProperty(JSContext *cx, JSObject *obj,
} }
if (result) { if (result) {
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; rv = WrapNative(cx, obj, result, vp);
rv = nsDOMClassInfo::WrapNative(cx, obj, result, NS_GET_IID(nsISupports),
vp, getter_AddRefs(holder));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
nsDOMClassInfo::ThrowJSException(cx, rv); nsDOMClassInfo::ThrowJSException(cx, rv);
@ -8788,8 +8765,7 @@ nsHTMLDocumentSH::DocumentAllTagsNewResolve(JSContext *cx, JSObject *obj,
if (tags) { if (tags) {
jsval v; jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = nsDOMClassInfo::WrapNative(cx, obj, tags, nsresult rv = nsDOMClassInfo::WrapNative(cx, obj, tags, &v,
NS_GET_IID(nsISupports), &v,
getter_AddRefs(holder)); getter_AddRefs(holder));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
nsDOMClassInfo::ThrowJSException(cx, rv); nsDOMClassInfo::ThrowJSException(cx, rv);
@ -8948,9 +8924,7 @@ nsHTMLDocumentSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (result) { if (result) {
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; rv = WrapNative(cx, obj, result, vp);
rv = WrapNative(cx, obj, result, NS_GET_IID(nsISupports), vp,
getter_AddRefs(holder));
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
rv = NS_SUCCESS_I_DID_SOMETHING; rv = NS_SUCCESS_I_DID_SOMETHING;
} }
@ -9090,9 +9064,7 @@ nsHTMLFormElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
if (result) { if (result) {
// Wrap result, result can be either an element or a list of // Wrap result, result can be either an element or a list of
// elements // elements
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsresult rv = WrapNative(cx, obj, result, vp);
nsresult rv = WrapNative(cx, obj, result, NS_GET_IID(nsISupports), vp,
getter_AddRefs(holder));
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
} }
} }
@ -9104,9 +9076,7 @@ nsHTMLFormElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
form->GetElementAt(n, getter_AddRefs(control)); form->GetElementAt(n, getter_AddRefs(control));
if (control) { if (control) {
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsresult rv = WrapNative(cx, obj, control, vp);
nsresult rv = WrapNative(cx, obj, control, NS_GET_IID(nsISupports), vp,
getter_AddRefs(holder));
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
} }
} }
@ -9213,9 +9183,7 @@ nsHTMLSelectElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
options->Item(n, getter_AddRefs(node)); options->Item(n, getter_AddRefs(node));
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; rv = WrapNative(cx, obj, node, &NS_GET_IID(nsIDOMNode), vp);
rv = WrapNative(cx, obj, node, NS_GET_IID(nsIDOMNode), vp,
getter_AddRefs(holder));
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
rv = NS_SUCCESS_I_DID_SOMETHING; rv = NS_SUCCESS_I_DID_SOMETHING;
} }

Просмотреть файл

@ -130,11 +130,22 @@ public:
} }
static nsresult WrapNative(JSContext *cx, JSObject *scope, static nsresult WrapNative(JSContext *cx, JSObject *scope,
nsISupports *native, const nsIID& aIID, nsISupports *native, const nsIID* aIID,
jsval *vp, jsval *vp,
// aHolder keeps the jsval alive while // If non-null aHolder will keep the jsval alive
// there's a ref to it // while there's a ref to it
nsIXPConnectJSObjectHolder** aHolder); nsIXPConnectJSObjectHolder** aHolder = nsnull);
// Same as the WrapNative above, but use this one if aIID is nsISupports' IID.
static nsresult WrapNative(JSContext *cx, JSObject *scope,
nsISupports *native, jsval *vp,
// If non-null aHolder will keep the jsval alive
// while there's a ref to it
nsIXPConnectJSObjectHolder** aHolder = nsnull)
{
return WrapNative(cx, scope, native, nsnull, vp, aHolder);
}
static nsresult ThrowJSException(JSContext *cx, nsresult aResult); static nsresult ThrowJSException(JSContext *cx, nsresult aResult);
static nsresult InitDOMJSClass(JSContext *cx, JSObject *obj); static nsresult InitDOMJSClass(JSContext *cx, JSObject *obj);

Просмотреть файл

@ -3874,6 +3874,9 @@ nsGlobalWindow::EnsureReflowFlushAndPaint()
NS_ASSERTION(mDocShell, "EnsureReflowFlushAndPaint() called with no " NS_ASSERTION(mDocShell, "EnsureReflowFlushAndPaint() called with no "
"docshell!"); "docshell!");
if (!mDocShell)
return;
nsCOMPtr<nsIPresShell> presShell; nsCOMPtr<nsIPresShell> presShell;
mDocShell->GetPresShell(getter_AddRefs(presShell)); mDocShell->GetPresShell(getter_AddRefs(presShell));
@ -5930,6 +5933,8 @@ nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs,
{ {
*aRetVal = nsnull; *aRetVal = nsnull;
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMWindow> dlgWin; nsCOMPtr<nsIDOMWindow> dlgWin;
nsAutoString options(NS_LITERAL_STRING("-moz-internal-modal=1,status=1")); nsAutoString options(NS_LITERAL_STRING("-moz-internal-modal=1,status=1"));
@ -6037,6 +6042,7 @@ nsGlobalWindow::Find(const nsAString& aStr, PRBool aCaseSensitive,
*aDidFind = PR_FALSE; *aDidFind = PR_FALSE;
nsCOMPtr<nsIWebBrowserFind> finder(do_GetInterface(mDocShell)); nsCOMPtr<nsIWebBrowserFind> finder(do_GetInterface(mDocShell));
NS_ENSURE_TRUE(finder, NS_ERROR_FAILURE);
// Set the options of the search // Set the options of the search
rv = finder->SetSearchString(PromiseFlatString(aStr).get()); rv = finder->SetSearchString(PromiseFlatString(aStr).get());

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше