Merge mozilla-central to tracemonkey.

This commit is contained in:
Robert Sayre 2009-07-11 23:46:16 -04:00
commit 247b1e3f5d
421 changed files with 13184 additions and 5811 deletions

View File

@ -18,7 +18,7 @@ on http://developer.mozilla.org, you can try asking your question in a
mozilla.* Usenet group, or on IRC at irc.mozilla.org. [The Mozilla news groups
are accessible on Google Groups, or news.mozilla.org with a NNTP reader.]
You can download nightly development builds from the the Mozilla FTP server.
You can download nightly development builds from the Mozilla FTP server.
Keep in mind that nightly builds, which are used by Mozilla developers for
testing, may be buggy. Firefox nightlies, for example, can be found at:

View File

@ -74,7 +74,6 @@ nsHyperTextAccessibleWrap(aDomNode, aShell)
// nsAccessible
/* unsigned long getRole (); */
nsresult
nsHTMLTableCellAccessible::GetRoleInternal(PRUint32 *aResult)
{
@ -82,6 +81,29 @@ nsHTMLTableCellAccessible::GetRoleInternal(PRUint32 *aResult)
return NS_OK;
}
nsresult
nsHTMLTableCellAccessible::GetStateInternal(PRUint32 *aState,
PRUint32 *aExtraState)
{
nsresult rv= nsHyperTextAccessibleWrap::GetStateInternal(aState, aExtraState);
NS_ENSURE_A11Y_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mWeakShell);
nsIFrame *frame = presShell->GetPrimaryFrameFor(content);
NS_ASSERTION(frame, "No frame for valid cell accessible!");
if (frame) {
*aState |= nsIAccessibleStates::STATE_SELECTABLE;
PRBool isSelected = PR_FALSE;
frame->GetSelected(&isSelected);
if (isSelected)
*aState |= nsIAccessibleStates::STATE_SELECTED;
}
return NS_OK;
}
nsresult
nsHTMLTableCellAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
{
@ -1277,46 +1299,44 @@ NS_IMETHODIMP nsHTMLTableAccessible::GetDescription(nsAString& aDescription)
return NS_OK;
}
PRBool nsHTMLTableAccessible::HasDescendant(const char *aTagName, PRBool aAllowEmpty)
PRBool
nsHTMLTableAccessible::HasDescendant(const nsAString& aTagName,
PRBool aAllowEmpty)
{
nsCOMPtr<nsIDOMElement> tableElt(do_QueryInterface(mDOMNode));
NS_ENSURE_TRUE(tableElt, PR_FALSE);
nsCOMPtr<nsIDOMNodeList> nodeList;
nsAutoString tagName;
tagName.AssignWithConversion(aTagName);
tableElt->GetElementsByTagName(tagName, getter_AddRefs(nodeList));
tableElt->GetElementsByTagName(aTagName, getter_AddRefs(nodeList));
NS_ENSURE_TRUE(nodeList, PR_FALSE);
PRUint32 length;
nodeList->GetLength(&length);
if (length == 1) {
// Make sure it's not the table itself
nsCOMPtr<nsIDOMNode> foundItem;
nodeList->Item(0, getter_AddRefs(foundItem));
if (foundItem == mDOMNode) {
return PR_FALSE;
}
if (!aAllowEmpty) {
// Make sure that the item we found has contents
// and either has multiple children or the
// found item is not a whitespace-only text node
nsCOMPtr<nsIContent> foundItemContent = do_QueryInterface(foundItem);
if (!foundItemContent) {
return PR_FALSE;
}
if (foundItemContent->GetChildCount() > 1) {
return PR_TRUE; // Treat multiple child nodes as non-empty
}
nsIContent *innerItemContent = foundItemContent->GetChildAt(0);
if (!innerItemContent || innerItemContent->TextIsOnlyWhitespace()) {
return PR_FALSE;
}
}
return PR_TRUE;
}
return length > 0;
nsCOMPtr<nsIDOMNode> foundItem;
nodeList->Item(0, getter_AddRefs(foundItem));
if (!foundItem)
return PR_FALSE;
if (aAllowEmpty)
return PR_TRUE;
// Make sure that the item we found has contents and either has multiple
// children or the found item is not a whitespace-only text node.
nsCOMPtr<nsIContent> foundItemContent = do_QueryInterface(foundItem);
if (foundItemContent->GetChildCount() > 1)
return PR_TRUE; // Treat multiple child nodes as non-empty
nsIContent *innerItemContent = foundItemContent->GetChildAt(0);
if (innerItemContent && !innerItemContent->TextIsOnlyWhitespace())
return PR_TRUE;
// If we found more than one node then return true not depending on
// aAllowEmpty flag.
// XXX it might be dummy but bug 501375 where we changed this addresses
// performance problems only. Note, currently 'aAllowEmpty' flag is used for
// caption element only. On another hand we create accessible object for
// the first entry of caption element (see
// nsHTMLTableAccessible::CacheChildren).
nodeList->Item(1, getter_AddRefs(foundItem));
return !!foundItem;
}
NS_IMETHODIMP
@ -1373,11 +1393,14 @@ nsHTMLTableAccessible::IsProbablyForLayout(PRBool *aIsProbablyForLayout)
// Check for legitimate data table elements or attributes
nsAutoString summary;
if ((content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::summary, summary) && !summary.IsEmpty()) ||
HasDescendant("caption", PR_FALSE) || HasDescendant("th") || HasDescendant("thead") ||
HasDescendant("tfoot") || HasDescendant("colgroup")) {
HasDescendant(NS_LITERAL_STRING("caption"), PR_FALSE) ||
HasDescendant(NS_LITERAL_STRING("th")) ||
HasDescendant(NS_LITERAL_STRING("thead")) ||
HasDescendant(NS_LITERAL_STRING("tfoot")) ||
HasDescendant(NS_LITERAL_STRING("colgroup"))) {
RETURN_LAYOUT_ANSWER(PR_FALSE, "Has caption, summary, th, thead, tfoot or colgroup -- legitimate table structures");
}
if (HasDescendant("table")) {
if (HasDescendant(NS_LITERAL_STRING("table"))) {
RETURN_LAYOUT_ANSWER(PR_TRUE, "Has a nested table within it");
}
@ -1487,7 +1510,10 @@ nsHTMLTableAccessible::IsProbablyForLayout(PRBool *aIsProbablyForLayout)
RETURN_LAYOUT_ANSWER(PR_TRUE, "2-4 columns, 10 cells or less, non-bordered");
}
if (HasDescendant("embed") || HasDescendant("object") || HasDescendant("applet") || HasDescendant("iframe")) {
if (HasDescendant(NS_LITERAL_STRING("embed")) ||
HasDescendant(NS_LITERAL_STRING("object")) ||
HasDescendant(NS_LITERAL_STRING("applet")) ||
HasDescendant(NS_LITERAL_STRING("iframe"))) {
RETURN_LAYOUT_ANSWER(PR_TRUE, "Has no borders, and has iframe, object, applet or iframe, typical of advertisements");
}

View File

@ -61,6 +61,7 @@ public:
// nsAccessible
virtual nsresult GetRoleInternal(PRUint32 *aRole);
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
protected:
@ -210,7 +211,16 @@ protected:
virtual void CacheChildren();
nsresult GetTableNode(nsIDOMNode **_retval);
nsresult GetTableLayout(nsITableLayout **aLayoutObject);
PRBool HasDescendant(const char *aTagName, PRBool aAllowEmpty = PR_TRUE);
/**
* Return true if table has an element with the given tag name.
*
* @param aTagName [in] tag name of searched element
* @param aAllowEmpty [in, optional] points if found element can be empty
* or contain whitespace text only.
*/
PRBool HasDescendant(const nsAString& aTagName, PRBool aAllowEmpty = PR_TRUE);
#ifdef SHOW_LAYOUT_HEURISTIC
nsAutoString mLayoutHeuristic;
#endif

View File

@ -76,6 +76,7 @@ _TEST_FILES =\
test_aria_role_equation.html \
test_aria_role_grid.html \
test_aria_roles.html \
test_aria_roles.xul \
test_aria_token_attrs.html \
test_bug420863.html \
$(warning test_childAtPoint.html temporarily disabled) \

View File

@ -109,8 +109,7 @@ function testTableIndexes(aIdentifier, aIdxes)
* cells states.
* @param aMsg [in] text appended before every message
*/
function testTableSelection(aIdentifier, aCellsArray, aMsg,
aSkipStatesTesting) // bug 501656
function testTableSelection(aIdentifier, aCellsArray, aMsg)
{
var msg = aMsg ? aMsg : "";
var acc = getAccessible(aIdentifier, [nsIAccessibleTable]);
@ -235,9 +234,6 @@ function testTableSelection(aIdentifier, aCellsArray, aMsg,
msg + "Cell at index " + selCells[i] + " should be selected.");
}
if (aSkipStatesTesting)
return;
// selected states tests
for (var rowIdx = 0; rowIdx < rowsCount; rowIdx++) {
for (var colIdx = 0; colIdx < colsCount; colIdx++) {
@ -249,7 +245,7 @@ function testTableSelection(aIdentifier, aCellsArray, aMsg,
if (isSel)
testStates(cell, STATE_SELECTED);
else
testStates(cell, 0, 0, STATE_SELECTED);
testStates(cell, STATE_SELECTABLE, 0, STATE_SELECTED);
}
}
}
@ -321,8 +317,7 @@ function testUnselectTableRow(aIdentifier, aRowIdx, aCellsArray)
/**
* Test selectRow method of accessible table.
*/
function testSelectTableRow(aIdentifier, aRowIdx, aCellsArray,
aSkipStatesTesting) // bug 501656
function testSelectTableRow(aIdentifier, aRowIdx, aCellsArray)
{
var acc = getAccessible(aIdentifier, [nsIAccessibleTable]);
if (!acc)
@ -340,6 +335,5 @@ function testSelectTableRow(aIdentifier, aRowIdx, aCellsArray,
acc.selectRow(aRowIdx);
testTableSelection(aIdentifier, aCellsArray,
"Select " + aRowIdx + " row: ",
aSkipStatesTesting);
"Select " + aRowIdx + " row: ");
}

View File

@ -0,0 +1,57 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessibility Name Calculating Test.">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js"></script>
<script type="application/javascript">
<![CDATA[
function doTest()
{
ok(!isAccessible("presentation_label"),
"Presentation label shouldn't be accessible.");
ok(!isAccessible("presentation_descr"),
"Presentation description shouldn't be accessible.");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=494345"
title="Do not create accessibles for XUL label or description having a role of 'presentation'">
Mozilla Bug 494345
</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<label id="presentation_label" role="presentation" value="label"/>
<description id="presentation_descr" role="presentation" value="description"/>
</vbox>
</hbox>
</window>

View File

@ -107,7 +107,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=410052
testTableIndexes("tableinsane4", idxes);
//////////////////////////////////////////////////////////////////////////
// tableinsane4 (just a crazy table)
// tableinsane5 (just a crazy table)
idxes = [
[ 0, 1, 2, -1, -1],
[-1, -1, -1, -1, -1],
@ -118,6 +118,18 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=410052
];
testTableIndexes("tableinsane5", idxes);
//////////////////////////////////////////////////////////////////////////
// tableinsane6 (overlapping cells, mad table)
idxes = [
[ 0, 1, 2, -1, -1],
[-1, -1, -1, -1, -1],
[ 3, 4, 5, -1, -1],
[ 6, 6, 7, -1, -1],
[ 8, 9, 7, -1, -1],
[ 10, 9, 7, 11, 12]
];
testTableIndexes("tableinsane6", idxes);
SimpleTest.finish();
}
@ -358,5 +370,39 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=410052
</tbody>
<table border="1" id="tableinsane6" >
<caption>overlapping cells</caption>
<thead>
<tr>
<th>header cell 0</th>
<th>header cell 1</th>
<th>header cell 2</th>
</tr>
</thead>
<tbody><tr></tr></tbody>
<tbody></tbody>
<tbody></tbody>
<tbody>
<tr>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td colspan="2">6</td>
<td rowspan="0">7</td>
</tr>
<tr>
<td>8</td>
<td rowspan="0">9</td>
</tr>
<tr>
<td colspan="3">10</td>
<td>11</td>
<td>12</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -35,6 +35,12 @@
// table with caption
testAbsentAttrs("table4", attr);
// table with empty caption
testAttrs("table4.2", attr, true);
// table with two captions
testAbsentAttrs("table4.3", attr);
// table with th element
testAbsentAttrs("table5", attr);
@ -166,6 +172,23 @@
</tr>
</table>
<!-- table with empty caption -->
<table id="table4.2">
<caption> </caption>
<tr>
<td>Cell1</td><td>cell2</td>
</tr>
</table>
<!-- table with two captions -->
<table id="table4.3">
<caption> </caption>
<tr>
<td>Cell1</td><td>cell2</td>
</tr>
<caption>a caption</caption>
</table>
<!-- table with th element -->
<table id="table5">
<tr>

View File

@ -32,7 +32,7 @@
testTableSelection("table", cellsArray);
testSelectTableRow("table", 0, cellsArray, true);
testSelectTableRow("table", 0, cellsArray);
var accTable = getAccessible("table", [nsIAccessibleTable]);
for (var i = 0; i < 4; i++) {

View File

@ -192,7 +192,9 @@ endif
ifeq ($(OS_ARCH),WINNT)
OS_LIBS += $(call EXPAND_LIBNAME,comctl32 comdlg32 uuid shell32 ole32 oleaut32 version winspool)
OS_LIBS += $(call EXPAND_LIBNAME,usp10 msimg32)
endif
ifneq (,$(filter WINNT WINCE,$(OS_ARCH)))
RCINCLUDE = splash.rc
ifndef GNU_CC
RCFLAGS += -DMOZ_PHOENIX -I$(srcdir)
@ -323,7 +325,7 @@ endif
export::
ifndef MOZ_BRANDING_DIRECTORY
$(NSINSTALL) -D $(DIST)/branding
ifeq ($(OS_ARCH),WINNT)
ifneq (,$(filter WINNT WINCE,$(OS_ARCH)))
cp $(srcdir)/firefox.ico $(DIST)/branding/firefox.ico
cp $(srcdir)/firefox.ico $(DIST)/branding/app.ico
cp $(srcdir)/document.ico $(DIST)/branding/document.ico

View File

@ -326,7 +326,11 @@ pref("browser.link.open_newwindow", 3);
pref("browser.link.open_newwindow.restriction", 2);
// Tabbed browser
#ifndef WINCE
pref("browser.tabs.autoHide", false);
#else
pref("browser.tabs.autoHide", true);
#endif
pref("browser.tabs.closeWindowWithLastTab", true);
pref("browser.tabs.warnOnClose", true);
pref("browser.tabs.warnOnOpen", true);
@ -847,6 +851,36 @@ pref("browser.bookmarks.editDialog.firstEditField", "namePicker");
// base url for the wifi geolocation network provider
pref("geo.wifi.uri", "https://www.google.com/loc/json");
#ifdef WINCE
// tweak awesomebar -- increase the delay until a search happens, and reduce
// the amount of time spent waiting for a search result
pref("browser.urlbar.search.chunkSize", 100);
pref("browser.urlbar.search.timeout", 500);
pref("browser.urlbar.delay", 1000);
// disable safe browsing, due to perf hit
pref("browser.safebrowsing.enabled", false);
// don't check for default browser
pref("browser.shell.checkDefaultBrowser", false);
// disable bfcache for memory
pref("browser.sessionhistory.max_total_viewers", 0);
// tweak default content sink prefs
pref("content.sink.interactive_deflect_count", 10); /* default 0 */
pref("content.sink.perf_deflect_count", 50); /* default 200 */
pref("content.sink.interactive_parse_time", 5000); /* default 3000 */
pref("content.sink.perf_parse_time", 150000); /* default 360000 */
pref("content.sink.pending_event_mode", 0); /* default 1 */
pref("content.sink.event_probe_rate", 1); /* default 1 */
pref("content.sink.interactive_time", 750000); /* default 750000 */
pref("content.sink.initial_perf_time", 500000); /* default 2000000 */
pref("content.sink.enable_perf_mode", 0); /* default 0; 0 == switch, 1 == stay interactive, 2 == stay perf */
#endif /* WINCE */
// Whether to use a panel that looks like an OS X sheet for customization
#ifdef XP_MACOSX
pref("toolbar.customization.usesheet", true);

View File

@ -92,6 +92,6 @@ DEFINES += -DCONTEXT_COPY_IMAGE_CONTENTS=1
endif
endif
ifneq (,$(BUILD_OFFICIAL)$(MOZILLA_OFFICIAL))
ifdef MOZILLA_OFFICIAL
DEFINES += -DOFFICIAL_BUILD=1
endif

View File

@ -88,6 +88,7 @@
accesskey="&sendPageCmd.accesskey;"
command="Browser:SendLink"/>
<menuseparator/>
#ifndef WINCE
<menuitem id="menu_printSetup"
label="&printSetupCmd.label;"
accesskey="&printSetupCmd.accesskey;"
@ -110,6 +111,7 @@
oncommand="BrowserImport();"/>
#ifndef XP_MACOSX
<menuseparator/>
#endif
#endif
<menuitem id="goOfflineMenuitem"
label="&goOfflineCmd.label;"
@ -227,7 +229,11 @@
accesskey="&taskbarCmd.accesskey;"
type="checkbox"
command="cmd_toggleTaskbar"
#ifndef WINCE
checked="true" />
#else
checked="false" />
#endif
<menu id="viewSidebarMenuMenu"
label="&viewSidebarMenu.label;"
accesskey="&viewSidebarMenu.accesskey;">

View File

@ -105,12 +105,6 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
display: none;
}
/* Bug 483950 - Hide domain name in status bar pending removal */
#security-button > label {
display: none;
}
/* ::::: Fullscreen pseudo-toolbar ::::: */
#fullscr-toggler {
display: none;

View File

@ -4156,7 +4156,6 @@ var XULBrowserWindow = {
// Properties used to cache security state used to update the UI
_state: null,
_host: undefined,
_tooltipText: null,
_hostChanged: false, // onLocationChange will flip this bit
@ -4181,11 +4180,13 @@ var XULBrowserWindow = {
}
this._state = aState;
#ifdef DEBUG
try {
this._host = gBrowser.contentWindow.location.host;
} catch(ex) {
this._host = null;
}
#endif
this._hostChanged = false;
this._tooltipText = gBrowser.securityUI.tooltipText
@ -4200,17 +4201,14 @@ var XULBrowserWindow = {
wpl.STATE_SECURE_MED |
wpl.STATE_SECURE_LOW;
var level;
var setHost = false;
switch (this._state & wpl_security_bits) {
case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_HIGH:
level = "high";
setHost = true;
break;
case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_MED:
case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_LOW:
level = "low";
setHost = true;
break;
case wpl.STATE_IS_BROKEN:
level = "broken";
@ -4231,11 +4229,6 @@ var XULBrowserWindow = {
gURLBar.removeAttribute("level");
}
if (setHost && this._host)
this.securityButton.setAttribute("label", this._host);
else
this.securityButton.removeAttribute("label");
this.securityButton.setAttribute("tooltiptext", this._tooltipText);
// Don't pass in the actual location object, since it can cause us to

View File

@ -279,6 +279,9 @@
</tooltip>
<toolbox id="navigator-toolbox" class="toolbox-top" mode="icons"
#ifdef WINCE
defaulticonsize="small" iconsize="small"
#endif
defaultmode="icons">
<!-- Menu -->
<toolbar type="menubar" id="toolbar-menubar" class="chromeclass-menubar" customizable="true"
@ -506,12 +509,21 @@
<toolbar id="nav-bar" class="toolbar-primary chromeclass-toolbar"
toolbarname="&navbarCmd.label;" accesskey="&navbarCmd.accesskey;"
fullscreentoolbar="true" mode="icons" iconsize="large"
fullscreentoolbar="true" mode="icons"
#ifdef WINCE
iconsize="small" defaulticonsize="small"
#else
iconsize="large"
#endif
customizable="true"
#ifdef XP_MACOSX
defaultset="unified-back-forward-button,reload-button,stop-button,home-button,urlbar-container,search-container"
#else
#ifdef WINCE
defaultset="unified-back-forward-button,reload-button,stop-button,home-button,urlbar-container,search-container,navigator-throbber,fullscreenflex,window-controls"
#else
defaultset="unified-back-forward-button,reload-button,stop-button,home-button,urlbar-container,search-container,fullscreenflex,window-controls"
#endif
#endif
context="toolbar-context-menu">
#ifndef XP_MACOSX
@ -540,6 +552,9 @@
context="toolbar-context-menu"
defaultset="personal-bookmarks"
toolbarname="&personalbarCmd.label;" accesskey="&personalbarCmd.accesskey;"
#ifdef WINCE
collapsed="true"
#endif
customizable="true"/>
</toolbox>
@ -575,6 +590,9 @@
<findbar browserid="content" id="FindToolbar"/>
<statusbar class="chromeclass-status" id="status-bar"
#ifdef WINCE
hidden="true"
#endif
ondrop="contentAreaDNDObserver.onDrop(event)">
<statusbarpanel id="statusbar-display" label="" flex="1"/>
<statusbarpanel class="statusbarpanel-progress" collapsed="true" id="statusbar-progresspanel">
@ -583,7 +601,7 @@
<statusbarpanel id="download-monitor" class="statusbarpanel-iconic-text"
tooltiptext="&downloadMonitor2.tooltip;" hidden="true"
command="Tools:Downloads"/>
<statusbarpanel id="security-button" class="statusbarpanel-iconic-text"
<statusbarpanel id="security-button" class="statusbarpanel-iconic"
hidden="true"
onclick="if (event.button == 0 &amp;&amp; event.detail == 1) displaySecurityInfo();"/>
<statusbarpanel id="page-report-button" type="menu"

View File

@ -76,7 +76,7 @@
<row id="link-url">
<separator orient="vertical"/>
<label value="&link-url.label; "/>
<textbox readonly="true" id="link-url-text"/>
<textbox readonly="true" id="link-url-text" class="uri-element"/>
</row>
<row id="link-target">
<separator orient="vertical"/>
@ -125,7 +125,7 @@
<row id="image-url">
<separator orient="vertical"/>
<label value="&image-url.label; "/>
<textbox readonly="true" id="image-url-text"/>
<textbox readonly="true" id="image-url-text" class="uri-element"/>
</row>
<row id="image-type">
<separator orient="vertical"/>

View File

@ -180,10 +180,14 @@ nsContextMenu.prototype = {
this.showItem("context-saveimage", this.onLoadedImage || this.onCanvas);
this.showItem("context-savevideo", this.onVideo);
this.showItem("context-saveaudio", this.onAudio);
this.setItemAttr("context-savevideo", "disabled", !this.mediaURL);
this.setItemAttr("context-saveaudio", "disabled", !this.mediaURL);
// Send media URL (but not for canvas, since it's a big data: URL)
this.showItem("context-sendimage", this.onImage);
this.showItem("context-sendvideo", this.onVideo);
this.showItem("context-sendaudio", this.onAudio);
this.setItemAttr("context-sendvideo", "disabled", !this.mediaURL);
this.setItemAttr("context-sendaudio", "disabled", !this.mediaURL);
},
initViewItems: function CM_initViewItems() {
@ -231,6 +235,7 @@ nsContextMenu.prototype = {
(!this.onStandaloneImage || this.inFrame)) || this.onCanvas);
this.showItem("context-viewvideo", this.onVideo);
this.setItemAttr("context-viewvideo", "disabled", !this.mediaURL);
// View background image depends on whether there is one.
this.showItem("context-viewbgimage", shouldShow);
@ -380,6 +385,8 @@ nsContextMenu.prototype = {
this.showItem("context-copyimage", this.onImage);
this.showItem("context-copyvideourl", this.onVideo);
this.showItem("context-copyaudiourl", this.onAudio);
this.setItemAttr("context-copyvideourl", "disabled", !this.mediaURL);
this.setItemAttr("context-copyaudiourl", "disabled", !this.mediaURL);
this.showItem("context-sep-copyimage", this.onImage ||
this.onVideo || this.onAudio);
},
@ -398,6 +405,16 @@ nsContextMenu.prototype = {
this.showItem("context-media-unmute", onMedia && this.target.muted);
this.showItem("context-media-showcontrols", onMedia && !this.target.controls)
this.showItem("context-media-hidecontrols", onMedia && this.target.controls)
// Disable them when there isn't a valid media source loaded.
if (onMedia) {
var hasError = (this.target.error != null);
this.setItemAttr("context-media-play", "disabled", hasError);
this.setItemAttr("context-media-pause", "disabled", hasError);
this.setItemAttr("context-media-mute", "disabled", hasError);
this.setItemAttr("context-media-unmute", "disabled", hasError);
this.setItemAttr("context-media-showcontrols", "disabled", hasError);
this.setItemAttr("context-media-hidecontrols", "disabled", hasError);
}
this.showItem("context-media-sep-commands", onMedia);
},
@ -468,11 +485,11 @@ nsContextMenu.prototype = {
}
else if (this.target instanceof HTMLVideoElement) {
this.onVideo = true;
this.mediaURL = this.target.currentSrc;
this.mediaURL = this.target.currentSrc || this.target.src;
}
else if (this.target instanceof HTMLAudioElement) {
this.onAudio = true;
this.mediaURL = this.target.currentSrc;
this.mediaURL = this.target.currentSrc || this.target.src;
}
else if (this.target instanceof HTMLInputElement ) {
this.onTextInput = this.isTargetATextBox(this.target);

View File

@ -10,7 +10,12 @@
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-arrowscrollbox");
}
.tab-close-button, .tabs-closebutton {
.tabs-alltabs-popup {
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-alltabs-popup");
}
.tab-close-button,
.tabs-closebutton {
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-close-tab-button");
}

View File

@ -941,12 +941,6 @@
if (evt.target != this.contentDocument)
return;
var i = 0;
for ( ; i < this.parentNode.parentNode.childNodes.length; i++) {
if (this.parentNode.parentNode.childNodes[i].firstChild == this)
break;
}
var tabBrowser = this.parentNode.parentNode.parentNode.parentNode;
var tab = document.getAnonymousElementByAttribute(tabBrowser, "linkedpanel", this.parentNode.id);
@ -1195,16 +1189,13 @@
this.mTabContainer.appendChild(t);
if (document.defaultView
.getComputedStyle(this.mTabContainer, "")
.direction == "rtl") {
if (this.tabContainer.mTabstrip._isRTLScrollbox) {
/* In RTL UI, the tab is visually added to the left side of the
* tabstrip. This means the tabstip has to be scrolled back in
* order to make sure the same set of tabs is visible before and
* after the new tab is added */
this.mTabContainer.mTabstrip.scrollBoxObject
.scrollBy(this.mTabContainer.firstChild.boxObject.width, 0);
this.tabContainer.mTabstrip.scrollByPixels(this.mTabs[0].clientWidth);
}
// invalidate cache, because mTabContainer is about to change
@ -1283,21 +1274,21 @@
}
}
// |setTimeout| here to ensure we're post reflow
var _delayedUpdate = function(aTabContainer) {
aTabContainer.adjustTabstrip();
this.tabContainer.adjustTabstrip();
// Do this asynchronically, as we don't know yet if the tab
// will be selected.
setTimeout(function (aTabContainer) {
if (aTabContainer.selectedItem != t)
aTabContainer._notifyBackgroundTab(t);
}, 0, this.tabContainer);
// XXXmano: this is a temporary workaround to bug 343585
// We need to manually update the scroll buttons disabled state
// if a tab was inserted to the overflow area or removed from it
// without any scrolling and when the tabbar has already
// overflowed.
aTabContainer.mTabstrip._updateScrollButtonsDisabledState();
}
setTimeout(_delayedUpdate, 0, this.mTabContainer);
// XXXmano: this is a temporary workaround for bug 345399
// We need to manually update the scroll buttons disabled state
// if a tab was inserted to the overflow area or removed from it
// without any scrolling and when the tabbar has already
// overflowed.
this.tabContainer.mTabstrip._updateScrollButtonsDisabledState();
// Dispatch a new tab notification. We do this once we're
// entirely done, so that things are in a consistent state
@ -1505,15 +1496,12 @@
while (this._removingTabs.length)
this._endRemoveTab([this._removingTabs[0], false]);
} else if (!this._windowIsClosing) {
// see notes in addTab
function _delayedUpdate(aTabContainer) {
aTabContainer.adjustTabstrip();
aTabContainer.mTabstrip._updateScrollButtonsDisabledState();
};
setTimeout(_delayedUpdate, 0, this.tabContainer);
if (aNewTab && gURLBar)
gURLBar.focus();
this.tabContainer.adjustTabstrip();
// workaround for bug 345399
this.tabContainer.mTabstrip._updateScrollButtonsDisabledState();
}
// We're going to remove the tab and the browser now.
@ -1977,8 +1965,9 @@
var newIndex = this.getNewIndex(aEvent);
var ib = this.mTabDropIndicatorBar;
var ind = ib.firstChild;
var tabStripBoxObject = tabStrip.scrollBoxObject;
var minMargin = tabStripBoxObject.x - this.boxObject.x;
var scrollRect = tabStrip.scrollClientRect;
var rect = this.getBoundingClientRect();
var minMargin = scrollRect.left - rect.left;
// make sure we don't place the tab drop indicator past the
// edge, or the containing box will flex and stretch
// the tab drop indicator bar, which will flex the url bar.
@ -1986,13 +1975,13 @@
// just use first value if you can figure out how to get
// the tab drop indicator to crop instead of flex and stretch
// the tab drop indicator bar.
var maxMargin = Math.min(minMargin + tabStripBoxObject.width,
ib.boxObject.x + ib.boxObject.width -
ind.boxObject.width);
var maxMargin = Math.min(minMargin + scrollRect.width,
ib.getBoundingClientRect().right -
ind.clientWidth);
if (!ltr)
[minMargin, maxMargin] = [this.boxObject.width - maxMargin,
this.boxObject.width - minMargin];
var newMargin, tabBoxObject;
[minMargin, maxMargin] = [this.clientWidth - maxMargin,
this.clientWidth - minMargin];
var newMargin;
if (pixelsToScroll) {
// if we are scrolling, put the drop indicator at the edge
// so that it doesn't jump while scrolling
@ -2000,21 +1989,18 @@
}
else {
if (newIndex == this.mTabs.length) {
tabBoxObject = this.mTabs[newIndex-1].boxObject;
let tabRect = this.mTabs[newIndex-1].getBoundingClientRect();
if (ltr)
newMargin = tabBoxObject.screenX - this.boxObject.screenX
+ tabBoxObject.width;
newMargin = tabRect.right - rect.left;
else
newMargin = this.boxObject.screenX - tabBoxObject.screenX
+ this.boxObject.width;
newMargin = rect.right - tabRect.left;
}
else {
tabBoxObject = this.mTabs[newIndex].boxObject;
let tabRect = this.mTabs[newIndex].getBoundingClientRect();
if (ltr)
newMargin = tabBoxObject.screenX - this.boxObject.screenX;
newMargin = tabRect.left - rect.left;
else
newMargin = this.boxObject.screenX - tabBoxObject.screenX
+ this.boxObject.width - tabBoxObject.width;
newMargin = rect.right - tabRect.right;
}
// ensure we never place the drop indicator beyond our limits
if (newMargin < minMargin)
@ -2245,7 +2231,7 @@
this.mTabContainer.childNodes[i]._selected = false;
}
this.mCurrentTab._selected = true;
this.mTabContainer.mTabstrip.scrollBoxObject.ensureElementIsVisible(this.mCurrentTab);
this.mTabContainer.mTabstrip.ensureElementIsVisible(this.mCurrentTab, false);
var evt = document.createEvent("UIEvents");
evt.initUIEvent("TabMove", true, false, window, oldPosition);
@ -2804,7 +2790,7 @@
this._scrollButtonDownBox.collapsed = false;
this._scrollButtonDownBoxAnimate.collapsed = false;
#endif
this.scrollBoxObject.ensureElementIsVisible(tabs.selectedItem);
this.ensureElementIsVisible(tabs.selectedItem, false);
]]></handler>
#ifdef XP_MACOSX
@ -3003,10 +2989,7 @@
this.setAttribute("closebuttons", "activetab");
break;
case 1:
var width = this.firstChild.boxObject.width;
// 0 width is an invalid value and indicates
// an item without display, so ignore.
if (width > this.mTabClipWidth || width == 0)
if (this.firstChild.getBoundingClientRect().width > this.mTabClipWidth)
this.setAttribute("closebuttons", "alltabs");
else
this.setAttribute("closebuttons", "activetab");
@ -3048,15 +3031,9 @@
// of the tabstrip, we need to ensure that we stay
// completely scrolled to the right side
var tabStrip = this.mTabstrip;
var scrollPos = {};
tabStrip.scrollBoxObject.getPosition(scrollPos, {});
var scrolledSize = {};
tabStrip.scrollBoxObject.getScrolledSize(scrolledSize, {});
if (scrollPos.value + tabStrip.boxObject.width >=
scrolledSize.value) {
if (tabStrip.scrollPosition + tabStrip.scrollClientSize >=
tabStrip.scrollSize)
tabStrip.scrollByPixels(-1);
}
} catch (e) {}
]]></body>
</method>
@ -3078,6 +3055,11 @@
]]></body>
</method>
<field name="mAllTabsPopup">
document.getAnonymousElementByAttribute(this,
"anonid", "alltabs-popup");
</field>
<field name="mAllTabsBoxAnimate">
document.getAnonymousElementByAttribute(this,
"anonid",
@ -3120,30 +3102,26 @@
<method name="_notifyBackgroundTab">
<parameter name="aTab"/>
<body><![CDATA[
var tsbo = this.mTabstrip.scrollBoxObject;
var tsboStart = tsbo.screenX;
var tsboEnd = tsboStart + tsbo.width;
var ctbo = aTab.boxObject;
var ctboStart = ctbo.screenX;
var ctboEnd = ctboStart + ctbo.width;
var scrollRect = this.mTabstrip.scrollClientRect;
var tab = aTab.getBoundingClientRect();
// Is the new tab already completely visible?
if (tsboStart <= ctboStart && ctboEnd <= tsboEnd)
if (scrollRect.left <= tab.left && tab.right <= scrollRect.right)
return;
if (this.mTabstrip.smoothScroll) {
var selStart = this.selectedItem.boxObject.screenX;
var selEnd = selStart + this.selectedItem.boxObject.width;
let selected = this.selectedItem.getBoundingClientRect();
// Can we make both the new tab and the selected tab completely visible?
if (Math.max(ctboEnd - selStart, selEnd - ctboStart) <= tsbo.width) {
if (Math.max(tab.right - selected.left, selected.right - tab.left) <=
scrollRect.width) {
this.mTabstrip.ensureElementIsVisible(aTab);
return;
}
this.mTabstrip._smoothScrollByPixels(this.mTabstrip._isRTLScrollbox ?
selEnd - tsboEnd : selStart - tsboStart);
selected.right - scrollRect.right :
selected.left - scrollRect.left);
}
// start the flash timer
@ -3270,6 +3248,7 @@
<implementation>
<field name="mOverCloseButton">false</field>
<field name="mCorrespondingMenuitem">null</field>
</implementation>
<handlers>
@ -3311,4 +3290,213 @@
</handlers>
</binding>
<binding id="tabbrowser-alltabs-popup"
extends="chrome://global/content/bindings/popup.xml#popup">
<implementation implements="nsIDOMEventListener">
<field name="_xulWindow">
null
</field>
<constructor><![CDATA[
// We cannot cache the XULBrowserWindow object itself since it might
// be set after this binding is constructed.
try {
this._xulWindow =
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIXULWindow);
}
catch(ex) { }
]]></constructor>
<method name="_menuItemOnCommand">
<parameter name="aEvent"/>
<body><![CDATA[
var tabcontainer = document.getBindingParent(this);
tabcontainer.selectedItem = aEvent.target.tab;
]]></body>
</method>
<method name="_tabOnAttrModified">
<parameter name="aEvent"/>
<body><![CDATA[
var menuItem = aEvent.target.mCorrespondingMenuitem;
if (menuItem) {
var attrName = aEvent.attrName;
switch (attrName) {
case "label":
case "crop":
case "busy":
case "image":
case "selected":
if (aEvent.attrChange == aEvent.REMOVAL)
menuItem.removeAttribute(attrName);
else
menuItem.setAttribute(attrName, aEvent.newValue);
}
}
]]></body>
</method>
<method name="_tabOnTabClose">
<parameter name="aEvent"/>
<body><![CDATA[
var menuItem = aEvent.target.mCorrespondingMenuitem;
if (menuItem)
this.removeChild(menuItem);
]]></body>
</method>
<method name="handleEvent">
<parameter name="aEvent"/>
<body><![CDATA[
if (!aEvent.isTrusted)
return;
switch (aEvent.type) {
case "command":
this._menuItemOnCommand(aEvent);
break;
case "DOMAttrModified":
this._tabOnAttrModified(aEvent);
break;
case "TabClose":
this._tabOnTabClose(aEvent);
break;
case "TabOpen":
this._createTabMenuItem(aEvent.originalTarget);
break;
case "scroll":
this._updateTabsVisibilityStatus();
break;
}
]]></body>
</method>
<method name="_updateTabsVisibilityStatus">
<body><![CDATA[
var tabContainer = document.getBindingParent(this);
// We don't want menu item decoration unless there is overflow.
if (tabContainer.getAttribute("overflow") != "true")
return;
var tabstripBO = tabContainer.mTabstrip.scrollBoxObject;
for (var i = 0; i < this.childNodes.length; i++) {
var curTabBO = this.childNodes[i].tab.boxObject;
if (curTabBO.screenX >= tabstripBO.screenX &&
curTabBO.screenX + curTabBO.width <= tabstripBO.screenX + tabstripBO.width)
this.childNodes[i].setAttribute("tabIsVisible", "true");
else
this.childNodes[i].removeAttribute("tabIsVisible");
}
]]></body>
</method>
<method name="_createTabMenuItem">
<parameter name="aTab"/>
<body><![CDATA[
var menuItem = document.createElementNS(
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
"menuitem");
menuItem.setAttribute("class", "menuitem-iconic alltabs-item");
menuItem.setAttribute("label", aTab.label);
menuItem.setAttribute("crop", aTab.getAttribute("crop"));
menuItem.setAttribute("image", aTab.getAttribute("image"));
if (aTab.hasAttribute("busy"))
menuItem.setAttribute("busy", aTab.getAttribute("busy"));
if (aTab.selected)
menuItem.setAttribute("selected", "true");
// Keep some attributes of the menuitem in sync with its
// corresponding tab (e.g. the tab label)
aTab.mCorrespondingMenuitem = menuItem;
aTab.addEventListener("DOMAttrModified", this, false);
aTab.addEventListener("TabClose", this, false);
menuItem.tab = aTab;
menuItem.addEventListener("command", this, false);
this.appendChild(menuItem);
return menuItem;
]]></body>
</method>
</implementation>
<handlers>
<handler event="popupshowing">
<![CDATA[
// set up the menu popup
var tabcontainer = document.getBindingParent(this);
var tabs = tabcontainer.childNodes;
// Listen for changes in the tab bar.
var tabbrowser = document.getBindingParent(tabcontainer);
tabbrowser.addEventListener("TabOpen", this, false);
tabcontainer.mTabstrip.addEventListener("scroll", this, false);
// if an animation is in progress and the user
// clicks on the "all tabs" button, stop the animation
tabcontainer._stopAnimation();
for (var i = 0; i < tabs.length; i++) {
this._createTabMenuItem(tabs[i]);
}
this._updateTabsVisibilityStatus();
]]></handler>
<handler event="popuphiding">
<![CDATA[
// clear out the menu popup and remove the listeners
while (this.hasChildNodes()) {
var menuItem = this.lastChild;
menuItem.removeEventListener("command", this, false);
menuItem.tab.removeEventListener("DOMAttrModified", this, false);
menuItem.tab.removeEventListener("TabClose", this, false);
menuItem.tab.mCorrespondingMenuitem = null;
this.removeChild(menuItem);
}
var tabcontainer = document.getBindingParent(this);
tabcontainer.mTabstrip.removeEventListener("scroll", this, false);
document.getBindingParent(tabcontainer).removeEventListener("TabOpen", this, false);
]]></handler>
<handler event="DOMMenuItemActive">
<![CDATA[
if (!this._xulWindow || !this._xulWindow.XULBrowserWindow)
return;
var tab = event.target.tab;
if (tab) {
var statusText = tab.linkedBrowser.currentURI.spec;
if (statusText == "about:blank") {
// XXXhack: Passing a space here (and not "")
// to make sure the the browser implementation would
// still consider it a hovered link.
statusText = " ";
}
this._xulWindow.XULBrowserWindow.setOverLink(statusText, null);
}
]]></handler>
<handler event="DOMMenuItemInactive">
<![CDATA[
if (!this._xulWindow || !this._xulWindow.XULBrowserWindow)
return;
this._xulWindow.XULBrowserWindow.setOverLink("", null);
]]></handler>
</handlers>
</binding>
</bindings>

View File

@ -43,13 +43,15 @@ relativesrcdir = browser/base/content/test
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = test_feed_discovery.html \
_TEST_FILES = \
test_feed_discovery.html \
feed_discovery.html \
test_bug395533.html \
bug395533-data.txt \
test_contextmenu.html \
subtst_contextmenu.html \
ctxmenu-image.png \
video.ogg \
test_offlineNotification.html \
offlineChild.html \
offlineChild.cacheManifest \
@ -63,7 +65,6 @@ _TEST_FILES = test_feed_discovery.html \
$(NULL)
# The following tests are disabled because they are unreliable:
# browser_bug321000.js is bug 474081
# browser_bug423833.js is bug 428712
# browser_sanitize-download-history.js is bug 432425
#
@ -71,7 +72,9 @@ _TEST_FILES = test_feed_discovery.html \
# back to the clear recent history dialog (santize.xul), if it ever is (bug
# 480169)
_BROWSER_FILES = browser_sanitize-timespans.js \
_BROWSER_FILES = \
browser_bug321000.js \
browser_sanitize-timespans.js \
browser_bug405137.js \
browser_bug409481.js \
browser_bug413915.js \

View File

@ -1,48 +1,72 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
* ***** 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 Firefox Browser Test Code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ted Mielczarek <ted.mielczarek@gmail.com> (Original Author)
* Marco Bonardo <mak77@bonardo.net>
*
* 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 ***** */
const Ci = Components.interfaces;
const Cc = Components.classes;
const kUrlBarElm = document.getElementById('urlbar');
const kSearchBarElm = document.getElementById('searchbar');
const kTestString = " hello hello \n world\nworld ";
function testPaste(name, element, expected) {
element.focus();
listener.expected = expected;
listener.name = name;
// Pasting is async because the Accel+V codepath ends up going through
// DocumentViewerImpl::FireClipboardEvent.
EventUtils.synthesizeKey("v", { accelKey: true });
}
var gTests = [
var listener = {
expected: "",
name: "",
handleEvent: function(event) {
var element = event.target;
is(element.value, this.expected, this.name);
switch (element) {
case kUrlBarElm:
continue_test();
case kSearchBarElm:
finish_test();
}
}
}
{ desc: "Urlbar strips newlines and surrounding whitespace",
element: gURLBar,
expected: kTestString.replace(/\s*\n\s*/g,'')
},
// test bug 23485 and bug 321000
// urlbar should strip newlines,
// search bar should replace newlines with spaces
{ desc: "Searchbar replaces newlines with spaces",
element: document.getElementById('searchbar'),
expected: kTestString.replace('\n',' ','g')
},
];
// Test for bug 23485 and bug 321000.
// Urlbar should strip newlines,
// search bar should replace newlines with spaces.
function test() {
waitForExplicitFinish();
// register listeners
kUrlBarElm.addEventListener("input", listener, true);
kSearchBarElm.addEventListener("input", listener, true);
// Put a multi-line string in the clipboard
Components.classes["@mozilla.org/widget/clipboardhelper;1"]
.getService(Components.interfaces.nsIClipboardHelper)
.copyString(kTestString);
// Put a multi-line string in the clipboard.
info("About to put a string in clipboard");
Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper)
.copyString(kTestString);
// Setting the clipboard value is an async OS operation, so we need to poll
// the clipboard for valid data before going on.
@ -51,53 +75,84 @@ function test() {
var runCount = 0;
function poll_clipboard() {
// Poll for a maximum of 5s
// Poll for a maximum of 5s (each run happens after 100ms).
if (++runCount > 50) {
// Log the failure
// Log the failure.
ok(false, "Timed out while polling clipboard for pasted data");
// Cleanup and interrupt the test
// Cleanup and interrupt the test.
finish_test();
return;
}
var clip = Components.classes["@mozilla.org/widget/clipboard;1"].
getService(Components.interfaces.nsIClipboard);
var trans = Components.classes["@mozilla.org/widget/transferable;1"].
createInstance(Components.interfaces.nsITransferable);
info("Polling clipboard cycle " + runCount);
var clip = Cc["@mozilla.org/widget/clipboard;1"].
getService(Ci.nsIClipboard);
var trans = Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable);
trans.addDataFlavor("text/unicode");
var str = new Object();
try {
// This code could throw if the clipboard is not set
clip.getData(trans,clip.kGlobalClipboard);
trans.getTransferData("text/unicode",str,{});
str = str.value.QueryInterface(Components.interfaces.nsISupportsString);
} catch (ex) {}
// This code could throw if the clipboard is not set yet.
clip.getData(trans, clip.kGlobalClipboard);
trans.getTransferData("text/unicode", str, {});
str = str.value.QueryInterface(Ci.nsISupportsString);
}
catch(ex) {}
if (kTestString == str) {
testPaste('urlbar strips newlines and surrounding whitespace',
kUrlBarElm,
kTestString.replace(/\s*\n\s*/g,''));
next_test();
}
else
setTimeout(poll_clipboard, 100);
}
function continue_test() {
testPaste('searchbar replaces newlines with spaces',
kSearchBarElm,
kTestString.replace('\n',' ','g'));
function next_test() {
if (gTests.length) {
var currentTest = gTests.shift();
test_paste(currentTest);
}
else {
// No more tests to run.
// Clear the clipboard, emptyClipboard would not clear the native one, so
// we are setting it to an empty string.
Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper)
.copyString("");
finish();
}
}
function finish_test() {
kUrlBarElm.removeEventListener("input", listener, true);
kSearchBarElm.removeEventListener("input", listener, true);
// Clear the clipboard, emptyClipboard would not clear the native one, so
// setting it to an empty string.
Components.classes["@mozilla.org/widget/clipboardhelper;1"]
.getService(Components.interfaces.nsIClipboardHelper)
.copyString("");
// Clear fields
kUrlBarElm.value="";
kSearchBarElm.value="";
finish();
function test_paste(aCurrentTest) {
var element = aCurrentTest.element;
// Register input listener.
var inputListener = {
test: aCurrentTest,
handleEvent: function(event) {
var element = event.target;
element.removeEventListener("input", this, false);
is(element.value, this.test.expected, this.test.desc);
// Clear the field and go to next test.
element.value = "";
setTimeout(next_test, 0);
}
}
element.addEventListener("input", inputListener, false);
// Focus the window.
window.focus();
// Focus the element and wait for focus event.
info("About to focus " + element.id);
element.addEventListener("focus", function() {
element.removeEventListener("focus", arguments.callee, false);
executeSoon(function() {
// Pasting is async because the Accel+V codepath ends up going through
// DocumentViewerImpl::FireClipboardEvent.
info("Pasting into " + element.id);
EventUtils.synthesizeKey("v", { accelKey: true });
});
}, false);
element.focus();
}

View File

@ -12,7 +12,11 @@ Browser context menu subtest.
<input id="test-input"><br>
<img id="test-image" src="ctxmenu-image.png">
<canvas id="test-canvas" width="100" height="100" style="background-color: blue"></canvas>
<video id="test-video" width="100" height="100" style="background-color: orange"></video>
<video id="test-video-ok" src="video.ogg" width="100" height="100" style="background-color: green"></video>
<video id="test-video-bad" src="bogus.duh" width="100" height="100" style="background-color: orange"></video>
<video id="test-video-bad2" width="100" height="100" style="background-color: yellow">
<source src="bogus.duh" type="video/durrrr;">
</video>
<iframe id="test-iframe" width="98" height="98" style="border: 1px solid black"></iframe>
</body>

View File

@ -76,9 +76,11 @@ function getVisibleMenuItems(aMenu) {
else
accessKeys[key] = item.id
items.push(item.id);
items.push(!item.disabled);
} else if (item.nodeName == "menuseparator") {
ok(true, "--- seperator id is " + item.id);
items.push("---");
items.push(null);
} else if (item.nodeName == "menu") {
ok(item.id, "child menu #" + i + " has an ID");
ok(key, "menu has an access key");
@ -87,9 +89,11 @@ function getVisibleMenuItems(aMenu) {
else
accessKeys[key] = item.id
items.push(item.id);
items.push(!item.disabled);
// Add a dummy item to that the indexes in checkMenu are the same
// for expectedItems and actualItems.
items.push([]);
items.push(null);
} else {
ok(false, "child #" + i + " of menu ID " + aMenu.id +
" has an unknown type (" + item.nodeName + ")");
@ -105,24 +109,37 @@ function checkContextMenu(expectedItems) {
/*
* checkMenu - checks to see if the specified <menupopup> contains the
* expected items, as specified by an array of element IDs. To check the
* contents of a submenu, include a nested array after the expected <menu> ID.
* For example: ["foo, "submenu", ["sub1", "sub2"], "bar"]
* expected items and state.
* expectedItems is a array of (1) item IDs and (2) a boolean specifying if
* the item is enabled or not (or null to ignore it). Submenus can be checked
* by providing a nested array entry after the expected <menu> ID.
* For example: ["blah", true, // item enabled
* "submenu", null, // submenu
* ["sub1", true, // submenu contents
* "sub2", false], null, // submenu contents
* "lol", false] // item disabled
*
*/
function checkMenu(menu, expectedItems) {
var actualItems = getVisibleMenuItems(menu);
//ok(false, "Items are: " + actualItems);
for (var i = 0; i < expectedItems.length; i++) {
if (expectedItems[i] instanceof Array) {
for (var i = 0; i < expectedItems.length; i+=2) {
var actualItem = actualItems[i];
var actualEnabled = actualItems[i + 1];
var expectedItem = expectedItems[i];
var expectedEnabled = expectedItems[i + 1];
if (expectedItem instanceof Array) {
ok(true, "Checking submenu...");
var menuID = expectedItems[i - 1]; // The last item was the menu ID.
var menuID = expectedItems[i - 2]; // The last item was the menu ID.
var submenu = menu.getElementsByAttribute("id", menuID)[0];
ok(submenu && submenu.nodeName == "menu", "got expected submenu element");
checkMenu(submenu.menupopup, expectedItems[i]);
checkMenu(submenu.menupopup, expectedItem);
} else {
is(actualItems[i], expectedItems[i],
"checking item #" + i + " (" + expectedItems[i] + ")");
is(actualItem, expectedItem,
"checking item #" + i/2 + " (" + expectedItem + ") name");
if (expectedEnabled != null)
is(actualEnabled, expectedEnabled,
"checking item #" + i/2 + " (" + expectedItem + ") enabled state");
}
}
// Could find unexpected extra items at the end...
@ -150,136 +167,166 @@ function runTest(testNum) {
case 2:
// Context menu for plain text
checkContextMenu(["context-back",
"context-forward",
"context-reload",
"context-stop",
"---",
"context-bookmarkpage",
"context-savepage",
"context-sendpage",
"---",
"context-viewbgimage",
"context-selectall",
"---",
"context-viewsource",
"context-viewinfo"]);
checkContextMenu(["context-back", false,
"context-forward", false,
"context-reload", true,
"context-stop", false,
"---", null,
"context-bookmarkpage", true,
"context-savepage", true,
"context-sendpage", true,
"---", null,
"context-viewbgimage", false,
"context-selectall", true,
"---", null,
"context-viewsource", true,
"context-viewinfo", true]);
closeContextMenu()
openContextMenuFor(link); // Invoke context menu for next test.
break;
case 3:
// Context menu for text link
checkContextMenu(["context-openlink",
"context-openlinkintab",
"---",
"context-bookmarklink",
"context-savelink",
"context-sendlink",
"context-copylink",
"---",
"context-metadata"]);
checkContextMenu(["context-openlink", true,
"context-openlinkintab", true,
"---", null,
"context-bookmarklink", true,
"context-savelink", true,
"context-sendlink", true,
"context-copylink", true,
"---", null,
"context-metadata", true]);
closeContextMenu()
openContextMenuFor(mailto); // Invoke context menu for next test.
break;
case 4:
// Context menu for text mailto-link
checkContextMenu(["context-copyemail",
"---",
"context-metadata"]);
checkContextMenu(["context-copyemail", true,
"---", null,
"context-metadata", true]);
closeContextMenu()
openContextMenuFor(input); // Invoke context menu for next test.
break;
case 5:
// Context menu for text input field
checkContextMenu(["context-undo",
"---",
"context-cut",
"context-copy",
"context-paste",
"context-delete",
"---",
"context-selectall",
"---",
"spell-check-enabled"]);
checkContextMenu(["context-undo", false,
"---", null,
"context-cut", false,
"context-copy", false,
"context-paste", null, // ignore clipboard state
"context-delete", false,
"---", null,
"context-selectall", true,
"---", null,
"spell-check-enabled", true]);
closeContextMenu()
openContextMenuFor(img); // Invoke context menu for next test.
break;
case 6:
// Context menu for an image
checkContextMenu(["context-viewimage",
"context-copyimage-contents",
"context-copyimage",
"---",
"context-saveimage",
"context-sendimage",
"context-setDesktopBackground",
"context-blockimage",
"---",
"context-metadata"]);
checkContextMenu(["context-viewimage", true,
"context-copyimage-contents", true,
"context-copyimage", true,
"---", null,
"context-saveimage", true,
"context-sendimage", true,
"context-setDesktopBackground", true,
"context-blockimage", true,
"---", null,
"context-metadata", true]);
closeContextMenu();
openContextMenuFor(canvas); // Invoke context menu for next test.
break;
case 7:
// Context menu for a canvas
checkContextMenu(["context-viewimage",
"context-saveimage",
"context-bookmarkpage",
"context-selectall"]);
checkContextMenu(["context-viewimage", true,
"context-saveimage", true,
"context-bookmarkpage", true,
"context-selectall", true]);
closeContextMenu();
openContextMenuFor(video); // Invoke context menu for next test.
openContextMenuFor(video_ok); // Invoke context menu for next test.
break;
case 8:
// Context menu for a video
checkContextMenu(["context-media-play",
"context-media-mute",
"context-media-showcontrols",
"---",
"context-viewvideo",
"context-copyvideourl",
"---",
"context-savevideo",
"context-sendvideo"]);
// Context menu for a video (with a VALID media source)
checkContextMenu(["context-media-play", true,
"context-media-mute", true,
"context-media-showcontrols", true,
"---", null,
"context-viewvideo", true,
"context-copyvideourl", true,
"---", null,
"context-savevideo", true,
"context-sendvideo", true]);
closeContextMenu();
openContextMenuFor(video_bad); // Invoke context menu for next test.
break;
case 9:
// Context menu for a video (with a INVALID media source)
checkContextMenu(["context-media-play", false,
"context-media-mute", false,
"context-media-showcontrols", false,
"---", null,
"context-viewvideo", true,
"context-copyvideourl", true,
"---", null,
"context-savevideo", true,
"context-sendvideo", true]);
closeContextMenu();
openContextMenuFor(video_bad2); // Invoke context menu for next test.
break;
case 10:
// Context menu for a video (with a INVALID media source)
checkContextMenu(["context-media-play", false,
"context-media-mute", false,
"context-media-showcontrols", false,
"---", null,
"context-viewvideo", false,
"context-copyvideourl", false,
"---", null,
"context-savevideo", false,
"context-sendvideo", false]);
closeContextMenu();
openContextMenuFor(iframe); // Invoke context menu for next test.
break;
case 9:
case 11:
// Context menu for an iframe
checkContextMenu(["context-back",
"context-forward",
"context-reload",
"context-stop",
"---",
"context-bookmarkpage",
"context-savepage",
"context-sendpage",
"---",
"context-viewbgimage",
"context-selectall",
"---",
"frame",
["context-showonlythisframe",
"context-openframe",
"context-openframeintab",
"---",
"context-reloadframe",
"---",
"context-bookmarkframe",
"context-saveframe",
"---",
"context-printframe",
"---",
"context-viewframesource",
"context-viewframeinfo"],
"---",
"context-viewsource",
"context-viewinfo"]);
checkContextMenu(["context-back", false,
"context-forward", false,
"context-reload", true,
"context-stop", false,
"---", null,
"context-bookmarkpage", true,
"context-savepage", true,
"context-sendpage", true,
"---", null,
"context-viewbgimage", false,
"context-selectall", true,
"---", null,
"frame", null,
["context-showonlythisframe", true,
"context-openframe", true,
"context-openframeintab", true,
"---", null,
"context-reloadframe", true,
"---", null,
"context-bookmarkframe", true,
"context-saveframe", true,
"---", null,
"context-printframe", true,
"---", null,
"context-viewframesource", true,
"context-viewframeinfo", true], null,
"---", null,
"context-viewsource", true,
"context-viewinfo", true]);
closeContextMenu();
subwindow.close();
@ -327,7 +374,9 @@ function startTest() {
input = subwindow.document.getElementById("test-input");
img = subwindow.document.getElementById("test-image");
canvas = subwindow.document.getElementById("test-canvas");
video = subwindow.document.getElementById("test-video");
video_ok = subwindow.document.getElementById("test-video-ok");
video_bad = subwindow.document.getElementById("test-video-bad");
video_bad2 = subwindow.document.getElementById("test-video-bad2");
iframe = subwindow.document.getElementById("test-iframe");
contextMenu.addEventListener("popupshown", function() { runTest(++testNum); }, false);

Binary file not shown.

View File

@ -44,8 +44,10 @@ ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
cp $(srcdir)/background.png $(DIST)/branding/background.png
cp $(srcdir)/disk.icns $(DIST)/branding/disk.icns
endif
ifeq ($(OS_ARCH),WINNT)
ifneq (,$(filter WINNT WINCE,$(OS_ARCH)))
cp $(srcdir)/firefox.ico $(DIST)/branding/app.ico
endif
ifeq ($(OS_ARCH),WINNT)
cp $(srcdir)/branding.nsi $(DIST)/branding/branding.nsi
cp $(srcdir)/wizHeader.bmp $(DIST)/branding/wizHeader.bmp
cp $(srcdir)/wizHeaderRTL.bmp $(DIST)/branding/wizHeaderRTL.bmp

View File

@ -83,7 +83,7 @@ endif
DIRS += build
ifneq (,$(BUILD_OFFICIAL)$(MOZILLA_OFFICIAL))
ifdef MOZILLA_OFFICIAL
DEFINES += -DOFFICIAL_BUILD=1
endif

View File

@ -2147,6 +2147,7 @@ MicrosummaryResource.prototype = {
this._iframe.docShell.allowMetaRedirects = false;
this._iframe.docShell.allowSubframes = false;
this._iframe.docShell.allowImages = false;
this._iframe.docShell.allowDNSPrefetch = false;
var parseHandler = {
_self: this,

View File

@ -330,3 +330,13 @@ function dump_table(aName)
stmt.finalize();
stmt = null;
}
/**
* Flushes any events in the event loop of the main thread.
*/
function flush_main_thread_events()
{
let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
while (tm.mainThread.hasPendingEvents())
tm.mainThread.processNextEvent(false);
}

View File

@ -41,9 +41,7 @@
// event loop long before code like this would run.
// Not doing so could cause us to close the connection before all tasks have
// been completed, and that would crash badly.
let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
while (tm.mainThread.hasPendingEvents())
tm.mainThread.processNextEvent(false);
flush_main_thread_events();
// XPCShell doesn't dispatch quit-application, to ensure cleanup we have to
// dispatch it after each test run.
@ -52,6 +50,9 @@ var os = Cc['@mozilla.org/observer-service;1'].
os.notifyObservers(null, "quit-application-granted", null);
os.notifyObservers(null, "quit-application", null);
// Run the event loop, since we enqueue some statement finalization.
flush_main_thread_events();
// try to close the connection so we can remove places.sqlite
var pip = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService).

View File

@ -298,18 +298,6 @@ PrivateBrowsingService.prototype = {
getService(Ci.nsIHttpAuthManager);
authMgr.clearAll();
// Prevent any SSL sockets from remaining open. Without this, SSL
// websites may fail to load after switching the private browsing mode
// because the SSL sockets may still be open while the corresponding
// NSS resources have been destroyed by the logoutAndTeardown call
// above. See bug 463256 for more information.
let ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
if (!ios.offline) {
ios.offline = true;
ios.offline = false;
}
if (!this._inPrivateBrowsing) {
// Clear the error console
let consoleService = Cc["@mozilla.org/consoleservice;1"].

View File

@ -59,9 +59,8 @@ _BROWSER_TEST_FILES = \
browser_privatebrowsing_urlbarfocus.js \
browser_privatebrowsing_forgetthissite.js \
browser_privatebrowsing_pageinfo.js \
browser_privatebrowsing_sslsite_transition.js \
$(NULL)
# Test for bug 463256 disabled until we figure why it fails intermittently (bug 486640)
# browser_privatebrowsing_sslsite_transition.js \
libs:: $(_BROWSER_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)

View File

@ -36,9 +36,7 @@
* ***** END LICENSE BLOCK ***** */
// This test makes sure that SSL sites load correctly after leaving the
// Private Browsing mode (bug 463256).
// This test is disabled until we figure why it fails intermittently (bug 486640).
// Private Browsing mode (bug 463256 and bug 496335).
function test() {
// initialization
@ -78,3 +76,5 @@ function test() {
}, true);
browser.contentWindow.location = kTestURL;
waitForExplicitFinish();
}

View File

@ -35,8 +35,8 @@
*
* ***** END LICENSE BLOCK ***** */
// This tests the private browsing service to make sure it switches the offline
// status as expected (see bug 463256).
// This tests the private browsing service to make sure it no longer switches
// the offline status (see bug 463256).
function run_test_on_service() {
// initialization
@ -59,15 +59,11 @@ function run_test_on_service() {
// enter the private browsing mode, and wait for the about:pb page to load
pb.privateBrowsingEnabled = true;
do_check_eq(observer.events.length, 2);
do_check_eq(observer.events[0], "offline");
do_check_eq(observer.events[1], "online");
do_check_eq(observer.events.length, 0);
// leave the private browsing mode, and wait for the SSL page to load again
pb.privateBrowsingEnabled = false;
do_check_eq(observer.events.length, 4);
do_check_eq(observer.events[2], "offline");
do_check_eq(observer.events[3], "online");
do_check_eq(observer.events.length, 0);
os.removeObserver(observer, "network:offline-status-changed", false);
prefBranch.clearUserPref("browser.privatebrowsing.keep_current_session");

View File

@ -49,7 +49,7 @@ ifdef ENABLE_TESTS
DIRS += content/test
endif
ifneq (,$(BUILD_OFFICIAL)$(MOZILLA_OFFICIAL))
ifdef MOZILLA_OFFICIAL
DEFINES += -DOFFICIAL_BUILD=1
endif

View File

@ -1889,9 +1889,8 @@ SessionStoreService.prototype = {
if (aTabs.length > 0) {
// Determine if we can optimize & load visible tabs first
let tabScrollBoxObject = tabbrowser.tabContainer.mTabstrip.scrollBoxObject;
let tabBoxObject = aTabs[0].boxObject;
let maxVisibleTabs = Math.ceil(tabScrollBoxObject.width / tabBoxObject.width);
let maxVisibleTabs = Math.ceil(tabbrowser.tabContainer.mTabstrip.scrollClientSize /
aTabs[0].clientWidth);
// make sure we restore visible tabs first, if there are enough
if (maxVisibleTabs < aTabs.length && aSelectTab > 1) {
@ -2582,6 +2581,7 @@ SessionStoreService.prototype = {
_getWindowDimension: function sss_getWindowDimension(aWindow, aAttribute) {
if (aAttribute == "sizemode") {
switch (aWindow.windowState) {
case aWindow.STATE_FULLSCREEN:
case aWindow.STATE_MAXIMIZED:
return "maximized";
case aWindow.STATE_MINIMIZED:

View File

@ -86,7 +86,11 @@
#define REG_FAILED(val) \
(val != ERROR_SUCCESS)
#ifndef WINCE
NS_IMPL_ISUPPORTS2(nsWindowsShellService, nsIWindowsShellService, nsIShellService)
#else
NS_IMPL_ISUPPORTS1(nsWindowsShellService, nsIShellService)
#endif
static nsresult
OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey)
@ -106,6 +110,33 @@ OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey)
return NS_OK;
}
#ifdef WINCE
static nsresult
OpenKeyForWriting(HKEY aStartKey, const nsAString& aKeyName, HKEY* aKey)
{
const nsString &flatName = PromiseFlatString(aKeyName);
DWORD dwDisp = 0;
DWORD res = ::RegCreateKeyExW(aStartKey, flatName.get(), 0, NULL,
0, KEY_READ | KEY_WRITE, NULL, aKey,
&dwDisp);
switch (res) {
case ERROR_SUCCESS:
break;
case ERROR_ACCESS_DENIED:
return NS_ERROR_FILE_ACCESS_DENIED;
case ERROR_FILE_NOT_FOUND:
res = ::RegCreateKeyExW(aStartKey, flatName.get(), 0, NULL,
0, KEY_READ | KEY_WRITE, NULL, aKey,
NULL);
if (res != ERROR_SUCCESS)
return NS_ERROR_FILE_ACCESS_DENIED;
}
return NS_OK;
}
#endif
///////////////////////////////////////////////////////////////////////////////
// Default Browser Registry Settings
//
@ -181,30 +212,52 @@ typedef struct {
char* valueData;
} SETTING;
#ifndef WINCE
#define APP_REG_NAME L"Firefox"
#define CLS_HTML "FirefoxHTML"
#define CLS_URL "FirefoxURL"
#define VAL_OPEN "\"%APPPATH%\" -requestPending -osint -url \"%1\""
#define VAL_FILE_ICON "%APPPATH%,1"
#else
#define VAL_OPEN "\"%APPPATH%\" -osint -url \"%1\""
#define VAL_FILE_ICON "%APPPATH%,-2"
#endif
#define DI "\\DefaultIcon"
#define SOP "\\shell\\open\\command"
#define CLS_HTML "FirefoxHTML"
#define CLS_URL "FirefoxURL"
#define VAL_FILE_ICON "%APPPATH%,1"
#define VAL_OPEN "\"%APPPATH%\" -requestPending -osint -url \"%1\""
#define MAKE_KEY_NAME1(PREFIX, MID) \
PREFIX MID
// The DefaultIcon registry key value should never be used when checking if
// Firefox is the default browser since other applications (e.g. MS Office) may
// modify the DefaultIcon registry key value to add Icon Handlers.
// see http://msdn2.microsoft.com/en-us/library/aa969357.aspx for more info.
// Firefox is the default browser for file handlers since other applications
// (e.g. MS Office) may modify the DefaultIcon registry key value to add Icon
// Handlers. see http://msdn2.microsoft.com/en-us/library/aa969357.aspx for
// more info.
static SETTING gSettings[] = {
// File Extension Class - as of 1.8.1.2 the value for VAL_OPEN is also checked
// for CLS_HTML since Firefox should also own opeing local files when set as
// the default browser.
#ifndef WINCE
// File Handler Class
{ MAKE_KEY_NAME1(CLS_HTML, SOP), "", VAL_OPEN },
// Protocol Handler Class - for Vista and above
{ MAKE_KEY_NAME1(CLS_URL, SOP), "", VAL_OPEN },
#else
{ MAKE_KEY_NAME1("FTP", DI), "", VAL_FILE_ICON },
{ MAKE_KEY_NAME1("FTP", SOP), "", VAL_OPEN },
// File handlers for Windows CE
{ MAKE_KEY_NAME1("bmpfile", DI), "", VAL_FILE_ICON },
{ MAKE_KEY_NAME1("bmpfile", SOP), "", VAL_OPEN },
{ MAKE_KEY_NAME1("giffile", DI), "", VAL_FILE_ICON },
{ MAKE_KEY_NAME1("giffile", SOP), "", VAL_OPEN },
{ MAKE_KEY_NAME1("jpegfile", DI), "", VAL_FILE_ICON },
{ MAKE_KEY_NAME1("jpegfile", SOP), "", VAL_OPEN },
{ MAKE_KEY_NAME1("pngfile", DI), "", VAL_FILE_ICON },
{ MAKE_KEY_NAME1("pngfile", SOP), "", VAL_OPEN },
{ MAKE_KEY_NAME1("htmlfile", DI), "", VAL_FILE_ICON },
{ MAKE_KEY_NAME1("htmlfile", SOP), "", VAL_OPEN },
#endif
// Protocol Handlers
{ MAKE_KEY_NAME1("HTTP", DI), "", VAL_FILE_ICON },
@ -213,6 +266,7 @@ static SETTING gSettings[] = {
{ MAKE_KEY_NAME1("HTTPS", SOP), "", VAL_OPEN }
};
#ifndef WINCE
PRBool
nsWindowsShellService::IsDefaultBrowserVista(PRBool* aIsDefaultBrowser)
{
@ -236,6 +290,7 @@ nsWindowsShellService::IsDefaultBrowserVista(PRBool* aIsDefaultBrowser)
#endif
return PR_FALSE;
}
#endif
NS_IMETHODIMP
nsWindowsShellService::IsDefaultBrowser(PRBool aStartupCheck,
@ -295,10 +350,12 @@ nsWindowsShellService::IsDefaultBrowser(PRBool aStartupCheck,
}
}
#ifndef WINCE
// Only check if Firefox is the default browser on Vista if the previous
// checks show that Firefox is the default browser.
if (*aIsDefaultBrowser)
IsDefaultBrowserVista(aIsDefaultBrowser);
#endif
return NS_OK;
}
@ -306,6 +363,7 @@ nsWindowsShellService::IsDefaultBrowser(PRBool aStartupCheck,
NS_IMETHODIMP
nsWindowsShellService::SetDefaultBrowser(PRBool aClaimAllTypes, PRBool aForAllUsers)
{
#ifndef WINCE
nsresult rv;
nsCOMPtr<nsIProperties> directoryService =
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
@ -342,10 +400,91 @@ nsWindowsShellService::SetDefaultBrowser(PRBool aClaimAllTypes, PRBool aForAllUs
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
#else
SETTING* settings;
SETTING* end = gSettings + sizeof(gSettings)/sizeof(SETTING);
PRUnichar exePath[MAX_BUF];
if (!::GetModuleFileNameW(0, exePath, MAX_BUF))
return NS_ERROR_FAILURE;
nsAutoString appLongPath(exePath);
// The .png registry key isn't present by default so also add Content Type.
SetRegKey(NS_LITERAL_STRING(".png"), EmptyString(),
NS_LITERAL_STRING("pngfile"));
SetRegKey(NS_LITERAL_STRING(".png"), NS_LITERAL_STRING("Content Type"),
NS_LITERAL_STRING("image/png"));
// Set these keys to their default value for a clean install in case another
// app has changed these keys.
SetRegKey(NS_LITERAL_STRING(".htm"), EmptyString(),
NS_LITERAL_STRING("htmlfile"));
SetRegKey(NS_LITERAL_STRING(".html"), EmptyString(),
NS_LITERAL_STRING("htmlfile"));
SetRegKey(NS_LITERAL_STRING(".bmp"), EmptyString(),
NS_LITERAL_STRING("bmpfile"));
SetRegKey(NS_LITERAL_STRING(".gif"), EmptyString(),
NS_LITERAL_STRING("giffile"));
SetRegKey(NS_LITERAL_STRING(".jpe"), EmptyString(),
NS_LITERAL_STRING("jpegfile"));
SetRegKey(NS_LITERAL_STRING(".jpg"), EmptyString(),
NS_LITERAL_STRING("jpegfile"));
SetRegKey(NS_LITERAL_STRING(".jpeg"), EmptyString(),
NS_LITERAL_STRING("jpegfile"));
for (settings = gSettings; settings < end; ++settings) {
NS_ConvertUTF8toUTF16 dataLongPath(settings->valueData);
NS_ConvertUTF8toUTF16 key(settings->keyName);
NS_ConvertUTF8toUTF16 value(settings->valueName);
PRInt32 offset = dataLongPath.Find("%APPPATH%");
dataLongPath.Replace(offset, 9, appLongPath);
SetRegKey(key, value, dataLongPath);
}
// On Windows CE RegFlushKey can negatively impact performance if there are a
// lot of pending writes to the HKEY_CLASSES_ROOT registry hive but it is
// necessary to save the values in the case where the user performs a hard
// power off of the device.
::RegFlushKey(HKEY_CLASSES_ROOT);
#endif
return NS_OK;
}
#ifdef WINCE
void
nsWindowsShellService::SetRegKey(const nsString& aKeyName,
const nsString& aValueName,
const nsString& aValue)
{
PRUnichar buf[MAX_BUF];
DWORD len = sizeof buf;
HKEY theKey;
nsresult rv = OpenKeyForWriting(HKEY_CLASSES_ROOT, aKeyName, &theKey);
if (NS_FAILED(rv))
return;
// Get the current value.
DWORD res = ::RegQueryValueExW(theKey, PromiseFlatString(aValueName).get(),
NULL, NULL, (LPBYTE)buf, &len);
// Set the new value if it doesn't exist or it is different than the current
// value.
nsAutoString current(buf);
if (REG_FAILED(res) || !current.Equals(aValue)) {
const nsString &flatValue = PromiseFlatString(aValue);
::RegSetValueExW(theKey, PromiseFlatString(aValueName).get(),
0, REG_SZ, (const BYTE *)flatValue.get(),
(flatValue.Length() + 1) * sizeof(PRUnichar));
}
// Close the key we opened.
::RegCloseKey(theKey);
}
#endif
NS_IMETHODIMP
nsWindowsShellService::GetShouldCheckDefaultBrowser(PRBool* aResult)
{
@ -715,6 +854,7 @@ nsWindowsShellService::SetDesktopBackgroundColor(PRUint32 aColor)
return NS_OK;
}
#ifndef WINCE
NS_IMETHODIMP
nsWindowsShellService::GetUnreadMailCount(PRUint32* aCount)
{
@ -774,6 +914,7 @@ nsWindowsShellService::GetMailAccountKey(HKEY* aResult)
::RegCloseKey(mailKey);
return PR_FALSE;
}
#endif
NS_IMETHODIMP
nsWindowsShellService::OpenApplicationWithURI(nsILocalFile* aApplication,

View File

@ -46,7 +46,11 @@
#include <windows.h>
#include <ole2.h>
#ifndef WINCE
class nsWindowsShellService : public nsIWindowsShellService
#else
class nsWindowsShellService : public nsIShellService
#endif
{
public:
nsWindowsShellService() : mCheckedThisSession(PR_FALSE) {};
@ -54,12 +58,20 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSISHELLSERVICE
#ifndef WINCE
NS_DECL_NSIWINDOWSSHELLSERVICE
#endif
protected:
#ifndef WINCE
PRBool IsDefaultBrowserVista(PRBool* aIsDefaultBrowser);
PRBool GetMailAccountKey(HKEY* aResult);
#else
void SetRegKey(const nsString& aKeyName,
const nsString& aValueName,
const nsString& aValue);
#endif
private:
PRBool mCheckedThisSession;

View File

@ -1109,11 +1109,6 @@ statusbarpanel#statusbar-display {
-moz-padding-start: 0;
}
#security-button {
min-width: 20px;
-moz-box-direction: reverse;
}
#security-button[level="high"],
#security-button[level="low"] {
list-style-image: url("chrome://browser/skin/Secure.png");
@ -1123,11 +1118,6 @@ statusbarpanel#statusbar-display {
list-style-image: url("chrome://browser/skin/Security-broken.png");
}
/* XXXsw prevent margins of a value-less label from shifting the image */
#security-button > label:not([value]) {
display: none;
}
#page-report-button {
list-style-image: url("chrome://browser/skin/Info.png");
width: 20px;
@ -1311,6 +1301,28 @@ tabpanels {
margin: 2px 0 1px;
}
.tabs-alltabs-button[type="menu"] > .toolbarbutton-menu-dropmarker {
margin-bottom: -2px;
}
.tabs-alltabs-button[type="menu"] > .toolbarbutton-icon {
display: none;
}
/* All tabs menupopup */
.alltabs-item > .menu-iconic-left > .menu-iconic-icon {
list-style-image: url("chrome://global/skin/icons/folder-item.png");
-moz-image-region: rect(0px, 16px, 16px, 0px);
}
.alltabs-item[selected="true"] {
font-weight: bold;
}
.alltabs-item[busy] > .menu-iconic-left > .menu-iconic-icon {
list-style-image: url("chrome://global/skin/icons/loading_16.png");
}
/* Sidebar */
#sidebar-box .tabs-closebutton {
margin-bottom: 0px !important;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 B

After

Width:  |  Height:  |  Size: 192 B

View File

@ -1406,10 +1406,6 @@ sidebarheader > .tabs-closebutton > .toolbarbutton-text {
/* ----- SECURITY DISPLAY ----- */
#security-button {
-moz-box-direction: reverse;
}
#security-button[level="high"] ,
#security-button[level="low"] {
list-style-image: url("chrome://browser/skin/Secure-statusbar.png");
@ -1733,6 +1729,7 @@ tabbrowser > tabbox > tabpanels {
.tabs-alltabs-button:hover {
-moz-image-region: rect(0, 44px, 20px, 22px);
}
.tabs-alltabs-button[type="menu"][open="true"],
.tabs-alltabs-button:hover:active {
-moz-image-region: rect(0, 66px, 20px, 44px);
}
@ -1745,6 +1742,7 @@ tabbrowser > tabbox > tabpanels {
background-color: rgba(0,0,0,0.20);
}
.tabs-alltabs-button[type="menu"] > .toolbarbutton-menu-dropmarker,
.tabs-alltabs-button > .toolbarbutton-text {
display: none;
}
@ -1761,6 +1759,20 @@ tabbrowser > tabbox > tabpanels {
opacity: 0.0;
}
/* All Tabs Menupopup */
.alltabs-item > .menu-iconic-left > .menu-iconic-icon {
list-style-image: url("chrome://global/skin/tree/item.png");
}
.alltabs-item[selected="true"] {
font-weight: bold;
}
.alltabs-item[busy] > .menu-iconic-left > .menu-iconic-icon {
list-style-image: url("chrome://global/skin/icons/loading_16.png") !important;
}
/* Tabstrip close button */
.tabs-closebutton {
-moz-padding-end: 4px;
list-style-image: url("chrome://global/skin/icons/closetab.png");

View File

@ -1286,11 +1286,6 @@ statusbarpanel#statusbar-display {
border-top: none;
}
#security-button {
min-width: 20px;
-moz-box-direction: reverse;
}
#security-button[level="high"],
#security-button[level="low"] {
list-style-image: url("chrome://browser/skin/Secure.png");
@ -1300,11 +1295,6 @@ statusbarpanel#statusbar-display {
list-style-image: url("chrome://browser/skin/Security-broken.png");
}
/* XXXsw prevent margins of a value-less label from shifting the image */
#security-button > label:not([value]) {
display: none;
}
#page-report-button {
width: 20px;
list-style-image: url("chrome://browser/skin/Info.png");
@ -1571,8 +1561,26 @@ tabpanels {
.tabs-alltabs-button > .toolbarbutton-icon {
list-style-image: url("chrome://browser/skin/tabbrowser/alltabs.png");
margin: 6px 0 4px;
-moz-image-region: auto;
-moz-image-region: rect(0, 14px, 20px, 0);
}
.tabs-alltabs-button:hover:active > .toolbarbutton-icon {
-moz-image-region: rect(0, 28px, 20px, 14px);
}
.tabs-alltabs-button[type="menu"] > .toolbarbutton-icon {
list-style-image: url("chrome://browser/skin/mainwindow-dropdown-arrow.png");
margin: 5px 0 4px;
-moz-image-region: rect(0, 13px, 11px, 0);
}
.tabs-alltabs-button[type="menu"] > .toolbarbutton-menu-dropmarker {
display: none;
}
.tabs-alltabs-button[type="menu"]:hover:active > .toolbarbutton-icon,
.tabs-alltabs-button[type="menu"][open="true"] > .toolbarbutton-icon {
-moz-image-region: rect(0, 26px, 11px, 13px);
}
.tabs-alltabs-box-animate {
@ -1588,6 +1596,20 @@ stack[chromedir="rtl"] > hbox > .tabs-alltabs-box-animate {
background-image: url("chrome://browser/skin/tabbrowser/alltabs-box-overflow-start-bkgnd-animate.png");
}
/* All tabs menupopup */
.alltabs-item > .menu-iconic-left > .menu-iconic-icon {
list-style-image: url("chrome://global/skin/icons/folder-item.png");
-moz-image-region: rect(0px, 16px, 16px, 0px);
}
.alltabs-item[selected="true"] {
font-weight: bold;
}
.alltabs-item[busy] > .menu-iconic-left > .menu-iconic-icon {
list-style-image: url("chrome://global/skin/icons/loading_16.png");
}
/* Tabstrip close button */
.tabs-closebutton {
-moz-appearance: none;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 B

After

Width:  |  Height:  |  Size: 719 B

View File

@ -1,44 +0,0 @@
#!/usr/bin/expect
# ***** 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 Mozilla Corporation Code.
#
# The Initial Developer of the Original Code is
# Clint Talbert.
# Portions created by the Initial Developer are Copyright (C) 2007
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Armen Zambrano Gasparnian <armenzg@mozilla.com>
# Axel Hecht <l10n@mozilla.com>
#
# 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 *****
spawn hdiutil attach -readonly -mountroot /tmp -private -noautoopen $argv
expect {
"byte" {send "G"; exp_continue}
"END" {send "\r"; exp_continue}
"Y/N?" {send "Y\r"; exp_continue}
}

View File

@ -0,0 +1,88 @@
#!/bin/bash
# ***** 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 the installdmg.sh script from taols utilities
#
# The Initial Developer of the Original Code is
# Mozilla Corporation.
# Portions created by the Initial Developer are Copyright (C) 2009
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Chris AtLee <catlee@mozilla.com>
# Robert Kaiser <kairo@kairo.at>
#
# 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 *****
# Unpack a disk image to a specified target folder
#
# Usage: unpack-diskimage <image_file>
# <mountpoint>
# <target_path>
DMG_PATH=$1
MOUNTPOINT=$2
TARGETPATH=$3
# How long to wait before giving up waiting for the mount to finish (seconds)
TIMEOUT=90
# If mnt already exists, then the previous run may not have cleaned up
# properly. We should try to umount and remove the mnt directory.
if [ -d $MOUNTPOINT ]; then
echo "mnt already exists, trying to clean up"
hdiutil detach $MOUNTPOINT -force
rm -rdfv $MOUNTPOINT
fi
# Install an on-exit handler that will unmount and remove the '$MOUNTPOINT' directory
trap "{ if [ -d $MOUNTPOINT ]; then hdiutil detach $MOUNTPOINT -force; rm -rdfv $MOUNTPOINT; fi; }" EXIT
mkdir -p $MOUNTPOINT
hdiutil attach -verbose -noautoopen -mountpoint $MOUNTPOINT "$DMG_PATH"
# Wait for files to show up
# hdiutil uses a helper process, diskimages-helper, which isn't always done its
# work by the time hdiutil exits. So we wait until something shows up in the
# mnt directory. Due to the async nature of diskimages-helper, the best thing
# we can do is to make sure the glob() rsync is making can find files.
i=0
while [ "$(echo $MOUNTPOINT/*)" == "$MOUNTPOINT/*" ]; do
if [ $i -gt $TIMEOUT ]; then
echo "No files found, exiting"
exit 1
fi
sleep 1
i=$(expr $i + 1)
done
# Now we can copy everything out of the $MOUNTPOINT directory into the target directory
rsync -av $MOUNTPOINT/* $MOUNTPOINT/.DS_Store $MOUNTPOINT/.background $MOUNTPOINT/.VolumeIcon.icns $TARGETPATH/.
hdiutil detach $MOUNTPOINT
rm -rdf $MOUNTPOINT
# diskimage-helper prints messages to stdout asynchronously as well, sleep
# for a bit to ensure they don't disturb following commands in a script that
# might parse stdout messages
sleep 5

View File

@ -130,6 +130,7 @@ unsigned int ExpandEnvironmentStringsW(const unsigned short* lpSrc,
unsigned short * _wgetcwd(unsigned short* dir, unsigned long size);
unsigned short *_wfullpath( unsigned short *absPath, const unsigned short *relPath, unsigned long maxLength );
int _unlink(const char *filename );
int _wchdir(const unsigned short* path);
/* The time stuff should be defined here, but it can't be because it
is already defined in time.h.

View File

@ -6,6 +6,7 @@ SetEnvironmentVariableW
_unlink
_wfullpath
_wgetcwd
_wchdir
abort
clock
errno

View File

@ -115,10 +115,21 @@ int errno = 0;
unsigned short * _wgetcwd(unsigned short * dir, unsigned long size)
{
if (!dir)
return 0;
unsigned short tmp[MAX_PATH] = {0};
GetEnvironmentVariableW(L"CWD", tmp, size);
if (tmp && tmp[0]) {
if (wcslen(tmp) > size)
return 0;
wcscpy(dir, tmp);
return dir;
}
unsigned long i;
GetModuleFileName(GetModuleHandle (NULL), dir, MAX_PATH);
for (i = _tcslen(dir); i && dir[i] != TEXT('\\'); i--) {}
dir[i + 1] = TCHAR('\0');
SetEnvironmentVariableW(L"CWD", dir);
return dir;
}
@ -150,6 +161,10 @@ unsigned short *_wfullpath( unsigned short *absPath, const unsigned short *relPa
return NULL;
}
int _wchdir(const WCHAR* path) {
return SetEnvironmentVariableW(L"CWD", path);
}
int _unlink(const char *filename)
{
unsigned short wname[MAX_PATH];

View File

@ -72,6 +72,7 @@ endif
CFLAGS += \
-DVC_PATH='"$(subst \,\\,$(VCINSTALLDIR))\\"' \
-DWM_SDK_PATH='"$(subst \,\\,$(WINCE_SDK_DIR))\\"' \
-DOGLES_SDK_PATH='"$(subst \,\\,$(OGLES_SDK_DIR))\\"' \
-DMOZCE_DEVENV='"$(MOZCE_DEVENV)"' \
-DTOPSRCDIR='"$(TOPSRCDIR)"' \
$(NULL)

View File

@ -25,6 +25,7 @@ main(int argc, char **argv)
#ifdef MOZ_MEMORY
args[i++] = "/DMOZ_MEMORY";
#endif
args[i++] = "/I\"" ATL_INC "\"";
args[i++] = "/DMOZCE_STATIC_BUILD";
args[i++] = "/DUNICODE";
args[i++] = "/D_UNICODE_";
@ -38,6 +39,7 @@ main(int argc, char **argv)
// args[i++] = "/DPOCKETPC2003_UI_MODEL";
args[i++] = "/D_WINDOWS";
args[i++] = "/DNO_ERRNO";
args[i++] = "/D_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA";
args[i++] = "/GS-"; // disable security checks
args[i++] = "/GR-"; // disable C++ RTTI

View File

@ -11,11 +11,11 @@ main(int argc, char **argv)
int s = 0;
args[i++] = RC_PATH;
args[i++] = "/I\"" WCE_RC_INC "\"";
args[i++] = "/I\"" WM_SDK_INC "\"";
args[i++] = "/I\"" WM_SDK_INC "\"";
argpath_conv(&argv[1], &args[i]);
// dumpargs(args);
//dumpargs(args);
return run(args);
}

View File

@ -23,8 +23,13 @@ void checkLinkArgs(int* k, int* s, int* i, int* j, char** args, char** argv) {
void addLinkArgs(int k, int s, int *i, int *j, char** args, char** argv) {
args[(*i)++] = "/LIBPATH:\"" WCE_LIB "\"";
args[(*i)++] = "/LIBPATH:\"" WCE_CRT "\"";
args[(*i)++] = "/LIBPATH:\"" ATL_LIB "\"";
args[(*i)++] = "/LIBPATH:\"" OGLES_SDK_LIB "\"";
args[(*i)++] = "/NODEFAULTLIB";
args[(*i)++] = "/MAP";
args[(*i)++] = "/MAPINFO:EXPORTS";
#ifdef HAVE_SHUNT // simple test to see if we're in configure or not
if(getenv("NO_SHUNT") == NULL) {
args[(*i)++] = "/LIBPATH:\"" SHUNT_LIB "\"";

View File

@ -199,8 +199,8 @@ DWORD run(char** args)
_putenv("LIBPATH=");
_putenv("CC=");
_putenv("INCLUDE=" SHUNT_INC ";" WM_SDK_INC ";" WCE_INC);
_putenv("LIB=" WCE_LIB ";" WCE_CRT);
_putenv("INCLUDE=" SHUNT_INC ";" WM_SDK_INC ";" OGLES_SDK_INC ";" WCE_INC);
_putenv("LIB=" WCE_LIB ";" OGLES_SDK_LIB ";" WCE_CRT);
for (j=1; args[j]; j++)
{

View File

@ -5,6 +5,8 @@
#include <stdio.h>
#include <process.h>
#define OGLES_SDK_INC OGLES_SDK_PATH "inc"
#define OGLES_SDK_LIB OGLES_SDK_PATH "lib\\wince\\nvap\\release"
#define WCE_BIN VC_PATH "ce\\bin\\x86_arm\\"
#define WCE_RC_BIN WIN_SDK_PATH "bin\\"
#define WCE_CRT VC_PATH "ce\\lib\\armv4i"
@ -12,6 +14,8 @@
#define WCE_LIB WM_SDK_PATH "Lib/Armv4i"
#define WCE_RC_INC VC_PATH "ce\\atlmfc\\include"
#define WCE_INC VC_PATH "ce\\include"
#define ATL_INC VC_PATH "ce\\atlmfc\\include"
#define ATL_LIB VC_PATH "ce\\atlmfc\\lib\\armv4i"
#ifndef SHUNT_LIB
#define SHUNT_LIB ""

View File

@ -584,8 +584,6 @@ GSSAPI_INCLUDES = @GSSAPI_INCLUDES@
USE_GSSAPI = @USE_GSSAPI@
MOZILLA_OFFICIAL = @MOZILLA_OFFICIAL@
BUILD_OFFICIAL = @BUILD_OFFICIAL@
MOZ_MILESTONE_RELEASE = @MOZ_MILESTONE_RELEASE@
# Win32 options
MOZ_BROWSE_INFO = @MOZ_BROWSE_INFO@
@ -622,8 +620,12 @@ MOZ_PHOENIX = @MOZ_PHOENIX@
MOZ_XULRUNNER = @MOZ_XULRUNNER@
WINCE = @WINCE@
WINCE_SDK_DIR = @WINCE_SDK_DIR@
OGLES_SDK_DIR = @OGLES_SDK_DIR@
WINCE_WINDOWS_MOBILE = @WINCE_WINDOWS_MOBILE@
HAS_OGLES = @HAS_OGLES@
MOZ_DISTRIBUTION_ID = @MOZ_DISTRIBUTION_ID@
NS_OSSO = @NS_OSSO@

View File

@ -44,9 +44,6 @@ include $(DEPTH)/config/autoconf.mk
USE_STATIC_LIBS = 1
# undefine (as best we can, thanks gmake!) so we don't need build_number
MOZILLA_OFFICIAL =
BUILD_OFFICIAL =
MODULE = mkdepend
HOST_PROGRAM = mkdepend$(BIN_SUFFIX)
ifdef GNU_CC

View File

@ -47,7 +47,7 @@ ifndef RESFILE
RCFILE=./module.rc
RESFILE=./module.res
_RC_STRING = -QUIET 1 -DEPTH $(DEPTH) -TOPSRCDIR $(topsrcdir) -BITS $(MOZ_BITS) -OBJDIR . -SRCDIR $(srcdir) -DISPNAME $(MOZ_APP_DISPLAYNAME) -APPVERSION $(MOZ_APP_VERSION)
ifneq ($(BUILD_OFFICIAL)_$(MOZILLA_OFFICIAL),_)
ifdef MOZILLA_OFFICIAL
_RC_STRING += -OFFICIAL 1
endif
ifdef MOZ_DEBUG

View File

@ -242,6 +242,11 @@ case "$target" in
The path to the Windows CE SDK],
WINCE_SDK_DIR=$withval)
MOZ_ARG_WITH_STRING(ogles-sdk,
[ --with-ogles-sdk=OGLES_SDK_DIR
The path to the OGLES SDK],
OGLES_SDK_DIR=$withval)
dnl Default to Windows Mobile components enabled
WINCE_WINDOWS_MOBILE=1
@ -268,7 +273,7 @@ case "$target" in
_pwdw=`pwd -W`
_pwd=`pwd`
make WINCE_SDK_DIR="$WINCE_SDK_DIR" TOPSRCDIR="$_topsrcdir" OBJDIR="$_pwdw" -C $srcdir/build/wince/tools
make OGLES_SDK_DIR="$OGLES_SDK_DIR" WINCE_SDK_DIR="$WINCE_SDK_DIR" TOPSRCDIR="$_topsrcdir" OBJDIR="$_pwdw" -C $srcdir/build/wince/tools
CC="$_pwd/dist/sdk/bin/arm-wince-gcc"
CXX="$_pwd/dist/sdk/bin/arm-wince-gcc"
@ -3205,7 +3210,6 @@ else
[MISSING_X="$MISSING_X -lX11"], $XLIBS)
AC_CHECK_LIB(Xext, XextAddDisplay, [XEXT_LIBS="-lXext"],
[MISSING_X="$MISSING_X -lXext"], $XLIBS)
echo "green"
AC_CHECK_LIB(Xt, XtFree, [ XT_LIBS="-lXt"], [
unset ac_cv_lib_Xt_XtFree
@ -4210,7 +4214,7 @@ MOZ_ARG_WITH_BOOL(system-nspr,
_USE_SYSTEM_NSPR=1 )
if test -n "$_USE_SYSTEM_NSPR"; then
AM_PATH_NSPR(4.7.0, [MOZ_NATIVE_NSPR=1], [MOZ_NATIVE_NSPR=])
AM_PATH_NSPR(4.8.0, [MOZ_NATIVE_NSPR=1], [MOZ_NATIVE_NSPR=])
fi
if test -n "$MOZ_NATIVE_NSPR"; then
@ -7626,19 +7630,36 @@ if test "$MOZ_TREE_CAIRO"; then
if test "$MOZ_WIDGET_TOOLKIT" = "windows"; then
WIN32_SURFACE_FEATURE="#define CAIRO_HAS_WIN32_SURFACE 1"
if test -z "$WINCE"; then
WIN32_FONT_FEATURE="#define CAIRO_HAS_WIN32_FONT 1"
DDRAW_SURFACE_FEATURE=
WIN32_FONT_FEATURE="#define CAIRO_HAS_WIN32_FONT 1"
else
WIN32_FONT_FEATURE=
WIN32_FONT_FEATURE=
fi
AC_TRY_COMPILE([#include <ddraw.h>], [int foo = DDLOCK_WAITNOTBUSY;], HAS_DDRAW=1, HAS_DDRAW=)
if test -z "$HAS_DDRAW"; then
AC_MSG_WARN([DirectDraw ddraw.h header not found or it's missing DDLOCK_WAITNOTBUSY, disabling DirectDraw surface. If you have an older SDK (such as the CE5 SDK), try copying in ddraw.lib and ddraw.h from the WM6 SDK.])
DDRAW_SURFACE_FEATURE=
AC_MSG_WARN([DirectDraw ddraw.h header not found or it's missing DDLOCK_WAITNOTBUSY, disabling DirectDraw surface. If you have an older SDK (such as the CE5 SDK), try copying in ddraw.lib and ddraw.h from the WM6 SDK.])
DDRAW_SURFACE_FEATURE=
else
DDRAW_SURFACE_FEATURE="#define CAIRO_HAS_DDRAW_SURFACE 1"
DDRAW_SURFACE_FEATURE="#define CAIRO_HAS_DDRAW_SURFACE 1"
fi
if test -z "$OGLES_SDK_DIR"; then
OGLES_SURFACE_FEATURE=
else
AC_TRY_COMPILE([
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
], [ EGLDisplay _cairo_ddraw_egl_dpy = EGL_NO_DISPLAY;], HAS_OGLES=1, HAS_OGLES=)
if test -z "$HAS_OGLES"; then
AC_MSG_WARN([OpenGL ES2 headers not found, disabling OpenGL acceleration surfaces.])
OGLES_SURFACE_FEATURE=
else
OGLES_SURFACE_FEATURE="#define CAIRO_DDRAW_USE_GL 1"
fi
fi
PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
fi
if test "$MOZ_WIDGET_TOOLKIT" = "os2"; then
@ -7659,6 +7680,7 @@ if test "$MOZ_TREE_CAIRO"; then
fi
AC_SUBST(MOZ_ENABLE_CAIRO_FT)
AC_SUBST(CAIRO_FT_CFLAGS)
AC_SUBST(HAS_OGLES)
if test "$MOZ_DEBUG"; then
SANITY_CHECKING_FEATURE="#define CAIRO_DO_SANITY_CHECKING 1"
@ -7678,6 +7700,7 @@ if test "$MOZ_TREE_CAIRO"; then
AC_SUBST(XCB_SURFACE_FEATURE)
AC_SUBST(WIN32_SURFACE_FEATURE)
AC_SUBST(DDRAW_SURFACE_FEATURE)
AC_SUBST(OGLES_SURFACE_FEATURE)
AC_SUBST(OS2_SURFACE_FEATURE)
AC_SUBST(BEOS_SURFACE_FEATURE)
AC_SUBST(DIRECTFB_SURFACE_FEATURE)
@ -8117,8 +8140,7 @@ AC_SUBST(MOZ_OS2_USE_DECLSPEC)
AC_SUBST(MOZ_POST_DSO_LIB_COMMAND)
AC_SUBST(MOZ_POST_PROGRAM_COMMAND)
AC_SUBST(MOZ_TIMELINE)
AC_SUBST(WINCE)
AC_SUBST(WINCE_SDK_DIR)
AC_SUBST(OGLES_SDK_DIR)
AC_SUBST(MOZ_APP_NAME)
AC_SUBST(MOZ_APP_DISPLAYNAME)
@ -8128,8 +8150,6 @@ AC_SUBST(FIREFOX_VERSION)
AC_SUBST(MOZ_PKG_SPECIAL)
AC_SUBST(MOZILLA_OFFICIAL)
AC_SUBST(BUILD_OFFICIAL)
AC_SUBST(MOZ_MILESTONE_RELEASE)
dnl win32 options
AC_SUBST(MOZ_DEBUG_SYMBOLS)
@ -8142,6 +8162,7 @@ AC_SUBST(WIN32_REDIST_DIR)
AC_SUBST(PYTHON)
AC_SUBST(WINCE)
AC_SUBST(WINCE_SDK_DIR)
AC_SUBST(WINCE_WINDOWS_MOBILE)
dnl Echo the CFLAGS to remove extra whitespace.

View File

@ -81,6 +81,7 @@ class nsIURI;
class imgIDecoderObserver;
class imgIRequest;
class imgILoader;
class imgICache;
class nsIPrefBranch;
class nsIImage;
class nsIImageLoadingContent;
@ -647,6 +648,11 @@ public:
PRInt32 aLoadFlags,
imgIRequest** aRequest);
/**
* Returns whether the given URI is in the image cache.
*/
static PRBool IsImageInCache(nsIURI* aURI);
/**
* Method to get an nsIImage from an image loading content
*
@ -1504,6 +1510,7 @@ private:
static nsIPref *sPref;
static imgILoader* sImgLoader;
static imgICache* sImgCache;
static nsIConsoleService* sConsoleService;

View File

@ -105,8 +105,8 @@ class nsIBoxObject;
// IID for the nsIDocument interface
#define NS_IDOCUMENT_IID \
{0x2c155ed0, 0x3302, 0x4cff, \
{0x9d, 0xb3, 0xed, 0x0c, 0xcd, 0xfc, 0x50, 0x06 } }
{ 0x46003091, 0x7f99, 0x420f, \
{ 0x95, 0xbc, 0x28, 0xd7, 0xd5, 0x01, 0x5a, 0x41 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -1148,6 +1148,14 @@ public:
PRUint32 EventHandlingSuppressed() const { return mEventsSuppressed; }
PRBool IsDNSPrefetchAllowed() const { return mAllowDNSPrefetch; }
/**
* Called by nsParser to preload images. Can be removed and code moved
* to nsPreloadURIs::PreloadURIs() in file nsParser.cpp whenever the
* parser-module is linked with gklayout-module.
*/
virtual void MaybePreLoadImage(nsIURI* uri) = 0;
protected:
~nsIDocument()
{

View File

@ -36,6 +36,7 @@
* ***** END LICENSE BLOCK ***** */
#include "nsIObserver.h"
#include "nsCycleCollectionParticipant.h"
class nsCCUncollectableMarker : public nsIObserver
{
@ -50,8 +51,11 @@ class nsCCUncollectableMarker : public nsIObserver
/**
* Checks if we're collecting during a given generation
*/
static PRBool InGeneration(PRUint32 aGeneration) {
return aGeneration && aGeneration == sGeneration;
static PRBool InGeneration(nsCycleCollectionTraversalCallback &cb,
PRUint32 aGeneration) {
return !cb.WantAllTraces() &&
aGeneration &&
aGeneration == sGeneration;
}
static PRUint32 sGeneration;

View File

@ -1780,7 +1780,7 @@ nsContentSink::ReadyToCallDidBuildModelImpl(PRBool aTerminated)
}
if (mScriptLoader) {
mScriptLoader->EndDeferringScripts(aTerminated);
mScriptLoader->ParsingComplete(aTerminated);
}
}

View File

@ -179,6 +179,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "nsIConsoleService.h"
#include "mozAutoDocUpdate.h"
#include "imgICache.h"
#include "jsinterp.h"
const char kLoadAsData[] = "loadAsData";
@ -200,6 +201,7 @@ nsIXTFService *nsContentUtils::sXTFService = nsnull;
nsIPrefBranch *nsContentUtils::sPrefBranch = nsnull;
nsIPref *nsContentUtils::sPref = nsnull;
imgILoader *nsContentUtils::sImgLoader;
imgICache *nsContentUtils::sImgCache;
nsIConsoleService *nsContentUtils::sConsoleService;
nsDataHashtable<nsISupportsHashKey, EventNameMapping>* nsContentUtils::sEventTable = nsnull;
nsIStringBundleService *nsContentUtils::sStringBundleService;
@ -330,6 +332,10 @@ nsContentUtils::Init()
if (NS_FAILED(rv)) {
// no image loading for us. Oh, well.
sImgLoader = nsnull;
sImgCache = nsnull;
} else {
if (NS_FAILED(CallGetService("@mozilla.org/image/cache;1", &sImgCache )))
sImgCache = nsnull;
}
sPtrsToPtrsToRelease = new nsTArray<nsISupports**>();
@ -893,6 +899,7 @@ nsContentUtils::Shutdown()
NS_IF_RELEASE(sXTFService);
#endif
NS_IF_RELEASE(sImgLoader);
NS_IF_RELEASE(sImgCache);
NS_IF_RELEASE(sPrefBranch);
NS_IF_RELEASE(sPref);
#ifdef IBMBIDI
@ -2383,6 +2390,19 @@ nsContentUtils::CanLoadImage(nsIURI* aURI, nsISupports* aContext,
return NS_FAILED(rv) ? PR_FALSE : NS_CP_ACCEPTED(decision);
}
// static
PRBool
nsContentUtils::IsImageInCache(nsIURI* aURI)
{
if (!sImgCache) return PR_FALSE;
// If something unexpected happened we return false, otherwise if props
// is set, the image is cached and we return true
nsCOMPtr<nsIProperties> props;
nsresult rv = sImgCache->FindEntryProperties(aURI, getter_AddRefs(props));
return (NS_SUCCEEDED(rv) && props);
}
// static
nsresult
nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,

View File

@ -1723,7 +1723,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDocument)
// if we're uncollectable.
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
if (nsCCUncollectableMarker::InGeneration(tmp->GetMarkedCCGeneration())) {
if (nsCCUncollectableMarker::InGeneration(cb, tmp->GetMarkedCCGeneration())) {
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
}
@ -1780,6 +1780,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mStyleSheets)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mCatalogSheets)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mVisitednessChangedURIs)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mPreloadingImages)
#ifdef MOZ_SMIL
// Traverse animation components
@ -1824,6 +1825,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
tmp->mParentDocument = nsnull;
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mPreloadingImages)
// nsDocument has a pretty complex destructor, so we're going to
// assume that *most* cycles you actually want to break somewhere
// else, and not unlink an awful lot here.
@ -3863,6 +3866,9 @@ nsDocument::DispatchContentLoadedEvents()
// If you add early returns from this method, make sure you're
// calling UnblockOnload properly.
// Unpin references to preloaded images
mPreloadingImages.Clear();
// Fire a DOM event notifying listeners that this document has been
// loaded (excluding images and other loads initiated by this
// document).
@ -7485,6 +7491,34 @@ FireOrClearDelayedEvents(nsTArray<nsCOMPtr<nsIDocument> >& aDocuments,
}
}
void
nsDocument::MaybePreLoadImage(nsIURI* uri)
{
// Early exit if the img is already present in the img-cache
// which indicates that the "real" load has already started and
// that we shouldn't preload it.
if (nsContentUtils::IsImageInCache(uri)) {
return;
}
// Image not in cache - trigger preload
nsCOMPtr<imgIRequest> request;
nsresult rv =
nsContentUtils::LoadImage(uri,
this,
NodePrincipal(),
mDocumentURI, // uri of document used as referrer
nsnull, // no observer
nsIRequest::LOAD_NORMAL,
getter_AddRefs(request));
// Pin image-reference to avoid evicting it from the img-cache before
// the "real" load occurs. Unpinned in DispatchContentLoadedEvents and
// unlink
if (NS_SUCCEEDED(rv)) {
mPreloadingImages.AppendObject(request);
}
}
class nsDelayedEventDispatcher : public nsRunnable
{
public:

View File

@ -116,6 +116,7 @@
#include "nsIProgressEventSink.h"
#include "nsISecurityEventSink.h"
#include "nsIChannelEventSink.h"
#include "imgIRequest.h"
#define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0)
#define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1)
@ -1006,6 +1007,8 @@ public:
void MaybeInitializeFinalizeFrameLoaders();
void MaybeEndOutermostXBLUpdate();
virtual void MaybePreLoadImage(nsIURI* uri);
protected:
void RegisterNamedItems(nsIContent *aContent);
@ -1264,6 +1267,9 @@ private:
nsExternalResourceMap mExternalResourceMap;
// All images in process of being preloaded
nsCOMArray<imgIRequest> mPreloadingImages;
#ifdef MOZ_SMIL
nsAutoPtr<nsSMILAnimationController> mAnimationController;
#endif // MOZ_SMIL

View File

@ -91,7 +91,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGenericDOMDataNode)
nsIDocument* currentDoc = tmp->GetCurrentDoc();
if (currentDoc && nsCCUncollectableMarker::InGeneration(
currentDoc->GetMarkedCCGeneration())) {
cb, currentDoc->GetMarkedCCGeneration())) {
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
}

View File

@ -4009,7 +4009,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGenericElement)
nsIDocument* currentDoc = tmp->GetCurrentDoc();
if (currentDoc && nsCCUncollectableMarker::InGeneration(
currentDoc->GetMarkedCCGeneration())) {
cb, currentDoc->GetMarkedCCGeneration())) {
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
}

View File

@ -1029,23 +1029,24 @@ nsScriptLoader::ShouldExecuteScript(nsIDocument* aDocument,
}
void
nsScriptLoader::EndDeferringScripts(PRBool aKillDeferred)
nsScriptLoader::ParsingComplete(PRBool aTerminated)
{
if (mDeferEnabled) {
// Have to check because we apparently get EndDeferringScripts
// Have to check because we apparently get ParsingComplete
// without BeginDeferringScripts in some cases
mUnblockOnloadWhenDoneProcessing = PR_TRUE;
}
mDeferEnabled = PR_FALSE;
for (PRUint32 i = 0; i < (PRUint32)mRequests.Count(); ++i) {
if (aKillDeferred && mRequests[i]->mDefer) {
mRequests.RemoveObjectAt(i--);
}
else {
if (aTerminated) {
mRequests.Clear();
} else {
for (PRUint32 i = 0; i < (PRUint32)mRequests.Count(); ++i) {
mRequests[i]->mDefer = PR_FALSE;
}
}
// Have to call this even if aTerminated so we'll correctly unblock
// onload and all.
ProcessPendingRequests();
}

View File

@ -209,16 +209,15 @@ public:
}
/**
* Stops defering scripts and immediately processes the mDeferredRequests
* queue.
* Notifies the script loader that parsing is done. If aTerminated is true,
* this will drop any pending scripts that haven't run yet. Otherwise, it
* will stops deferring scripts and immediately processes the
* mDeferredRequests queue.
*
* WARNING: This function will syncronously execute content scripts, so be
* WARNING: This function will synchronously execute content scripts, so be
* prepared that the world might change around you.
*
* If aKillDeferred is PR_TRUE, deferred scripts won't be run, but instead
* removed.
*/
void EndDeferringScripts(PRBool aKillDeferred);
void ParsingComplete(PRBool aTerminated);
/**
* Returns the number of pending scripts, deferred or not.

View File

@ -1267,6 +1267,12 @@ IsAccessKeyTarget(nsIContent* aContent, nsIFrame* aFrame, nsAString& aKey)
tag == nsGkAtoms::label ||
tag == nsGkAtoms::legend)
return PR_TRUE;
} else if (aContent->IsNodeOfType(nsINode::eXUL)) {
// XUL label elements are never focusable, so we need to check for them
// explicitly before giving up.
if (aContent->Tag() == nsGkAtoms::label)
return PR_TRUE;
}
return PR_FALSE;

View File

@ -1139,14 +1139,14 @@ nsGenericHTMLElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool contentEditable = PR_FALSE;
PRInt32 contentEditableChange;
if (aNameSpaceID == kNameSpaceID_None) {
contentEditable = PR_TRUE;
contentEditableChange = GetContentEditableValue() == eTrue ? -1 : 0;
}
// Check for event handlers
if (aNameSpaceID == kNameSpaceID_None) {
if (nsContentUtils::IsEventAttributeName(aAttribute, EventNameType_HTML)) {
if (aAttribute == nsGkAtoms::contenteditable) {
contentEditable = PR_TRUE;
contentEditableChange = GetContentEditableValue() == eTrue ? -1 : 0;
}
else if (nsContentUtils::IsEventAttributeName(aAttribute,
EventNameType_HTML)) {
nsIEventListenerManager* manager = GetListenerManager(PR_FALSE);
if (manager) {
manager->RemoveScriptEventListener(aAttribute);

View File

@ -59,6 +59,8 @@
#include "nsICanvasRenderingContextInternal.h"
#include "nsLayoutUtils.h"
#define DEFAULT_CANVAS_WIDTH 300
#define DEFAULT_CANVAS_HEIGHT 150
@ -544,7 +546,14 @@ nsHTMLCanvasElement::SetWriteOnly()
NS_IMETHODIMP
nsHTMLCanvasElement::InvalidateFrame()
{
nsIFrame *frame = GetPrimaryFrame(Flush_Frames);
nsIDocument* doc = GetCurrentDoc();
if (!doc) {
return NS_OK;
}
// We don't need to flush anything here; if there's no frame or if
// we plan to reframe we don't need to invalidate it anyway.
nsIFrame *frame = GetPrimaryFrameFor(this, doc);
if (frame) {
nsRect r = frame->GetRect();
r.x = r.y = 0;
@ -557,8 +566,20 @@ nsHTMLCanvasElement::InvalidateFrame()
NS_IMETHODIMP
nsHTMLCanvasElement::InvalidateFrameSubrect(const gfxRect& damageRect)
{
nsIFrame *frame = GetPrimaryFrame(Flush_Frames);
nsIDocument* doc = GetCurrentDoc();
if (!doc) {
return NS_OK;
}
// We don't need to flush anything here; if there's no frame or if
// we plan to reframe we don't need to invalidate it anyway.
nsIFrame *frame = GetPrimaryFrameFor(this, doc);
if (frame) {
// Frame might be dirty, but we don't care about that; if the geometry
// changes the right invalidates will happen anyway. Don't assert on our
// geometry getters.
nsAutoDisableGetUsedXAssertions noAssert;
nsRect contentArea(frame->GetContentRect());
nsIntSize size = GetWidthHeight();

View File

@ -172,6 +172,12 @@ void nsHTMLMediaElement::QueueLoadFromSourceTask()
NS_DispatchToMainThread(event);
}
/**
* There is a reference cycle involving this class: MediaLoadListener
* holds a reference to the nsHTMLMediaElement, which holds a reference
* to an nsIChannel, which holds a reference to this listener.
* We break the reference cycle in OnStartRequest by clearing mElement.
*/
class nsHTMLMediaElement::MediaLoadListener : public nsIStreamListener,
public nsIChannelEventSink,
public nsIInterfaceRequestor
@ -200,30 +206,35 @@ NS_IMPL_ISUPPORTS4(nsHTMLMediaElement::MediaLoadListener, nsIRequestObserver,
NS_IMETHODIMP nsHTMLMediaElement::MediaLoadListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
{
// The element is only needed until we've had a chance to call
// InitializeDecoderForChannel. So make sure mElement is cleared here.
nsRefPtr<nsHTMLMediaElement> element;
element.swap(mElement);
// Don't continue to load if the request failed or has been canceled.
nsresult rv;
nsresult status;
rv = aRequest->GetStatus(&status);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(status)) {
if (mElement)
mElement->NotifyLoadError();
if (element)
element->NotifyLoadError();
return status;
}
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
if (channel &&
mElement &&
NS_SUCCEEDED(rv = mElement->InitializeDecoderForChannel(channel, getter_AddRefs(mNextListener))) &&
element &&
NS_SUCCEEDED(rv = element->InitializeDecoderForChannel(channel, getter_AddRefs(mNextListener))) &&
mNextListener) {
rv = mNextListener->OnStartRequest(aRequest, aContext);
} else {
// If InitializeDecoderForChannel() returned an error, fire a network
// error.
if (NS_FAILED(rv) && !mNextListener && mElement) {
if (NS_FAILED(rv) && !mNextListener && element) {
// Load failed, attempt to load the next candidate resource. If there
// are none, this will trigger a MEDIA_ERR_NONE_SUPPORTED error.
mElement->NotifyLoadError();
element->NotifyLoadError();
}
// If InitializeDecoderForChannel did not return a listener (but may
// have otherwise succeeded), we abort the connection since we aren't
@ -231,10 +242,6 @@ NS_IMETHODIMP nsHTMLMediaElement::MediaLoadListener::OnStartRequest(nsIRequest*
rv = NS_BINDING_ABORTED;
}
// The element is only needed until we've had a chance to call
// InitializeDecoderForChannel.
mElement = nsnull;
return rv;
}

View File

@ -268,18 +268,31 @@ nsHTMLTableRowElement::InsertCell(PRInt32 aIndex, nsIDOMHTMLElement** aValue)
if (aIndex < -1) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
}
// Make sure mCells is initialized.
nsCOMPtr<nsIDOMHTMLCollection> cells;
GetCells(getter_AddRefs(cells));
PRUint32 cellCount;
cells->GetLength(&cellCount);
if (aIndex > PRInt32(cellCount)) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
nsresult rv = GetCells(getter_AddRefs(cells));
if (NS_FAILED(rv)) {
return rv;
}
PRBool doInsert = (aIndex < PRInt32(cellCount)) && (aIndex != -1);
NS_ASSERTION(mCells, "How did that happen?");
nsCOMPtr<nsIDOMNode> nextSibling;
// -1 means append, so should use null nextSibling
if (aIndex != -1) {
cells->Item(aIndex, getter_AddRefs(nextSibling));
// Check whether we're inserting past end of list. We want to avoid doing
// this unless we really have to, since this has to walk all our kids. If
// we have a nextSibling, we're clearly not past end of list.
if (!nextSibling) {
PRUint32 cellCount;
cells->GetLength(&cellCount);
if (aIndex > PRInt32(cellCount)) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
}
}
}
// create the cell
nsCOMPtr<nsINodeInfo> nodeInfo;
@ -295,16 +308,7 @@ nsHTMLTableRowElement::InsertCell(PRInt32 aIndex, nsIDOMHTMLElement** aValue)
NS_ASSERTION(cellNode, "Should implement nsIDOMNode!");
nsCOMPtr<nsIDOMNode> retChild;
nsresult rv;
if (doInsert) {
nsCOMPtr<nsIDOMNode> refCell;
cells->Item(aIndex, getter_AddRefs(refCell));
rv = InsertBefore(cellNode, refCell, getter_AddRefs(retChild));
} else {
rv = AppendChild(cellNode, getter_AddRefs(retChild));
}
InsertBefore(cellNode, nextSibling, getter_AddRefs(retChild));
if (retChild) {
CallQueryInterface(retChild, aValue);

View File

@ -30,41 +30,113 @@ function runTest()
var focused;
anchorInEditor.onfocus = function() { focused = true; };
function isReallyEditable()
{
editor.focus();
var range = document.createRange();
range.selectNodeContents(editor);
var prevStr = range.toString();
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var docShell =
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShell);
var controller =
docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsISelectionDisplay)
.QueryInterface(Components.interfaces.nsISelectionController);
var sel = controller.getSelection(controller.SELECTION_NORMAL);
sel.collapse(anchorInEditor, 0);
synthesizeKey('a', {});
range.selectNodeContents(editor);
return prevStr != range.toString();
}
focused = false;
anchor.focus();
editor.setAttribute("contenteditable", "true");
anchorInEditor.focus();
is(focused, false, "focus moved to element in contenteditable=true");
is(isReallyEditable(), true, "cannot edit by a key event");
// for bug 502273
focused = false;
anchor.focus();
editor.setAttribute("dummy", "dummy");
editor.removeAttribute("dummy");
anchorInEditor.focus();
is(focused, false, "focus moved to element in contenteditable=true (after dummy attribute was removed)");
is(isReallyEditable(), true, "cannot edit by a key event");
focused = false;
anchor.focus();
editor.setAttribute("contenteditable", "false");
anchorInEditor.focus();
is(focused, true, "focus didn't move to element in contenteditable=false");
is(isReallyEditable(), false, "can edit by a key event");
// for bug 502273
focused = false;
anchor.focus();
editor.setAttribute("dummy", "dummy");
editor.removeAttribute("dummy");
anchorInEditor.focus();
is(focused, true, "focus moved to element in contenteditable=true (after dummy attribute was removed)");
is(isReallyEditable(), false, "cannot edit by a key event");
focused = false;
anchor.focus();
editor.setAttribute("contenteditable", "true");
anchorInEditor.focus();
is(focused, false, "focus moved to element in contenteditable=true");
is(isReallyEditable(), true, "cannot edit by a key event");
// for bug 502273
focused = false;
anchor.focus();
editor.setAttribute("dummy", "dummy");
editor.removeAttribute("dummy");
anchorInEditor.focus();
is(focused, false, "focus moved to element in contenteditable=true (after dummy attribute was removed)");
is(isReallyEditable(), true, "cannot edit by a key event");
focused = false;
anchor.focus();
editor.removeAttribute("contenteditable");
anchorInEditor.focus();
is(focused, true, "focus didn't move to element in contenteditable removed element");
is(isReallyEditable(), false, "can edit by a key event");
focused = false;
anchor.focus();
editor.contentEditable = true;
anchorInEditor.focus();
is(focused, false, "focus moved to element in contenteditable=true by property");
is(isReallyEditable(), true, "cannot edit by a key event");
focused = false;
anchor.focus();
editor.contentEditable = false;
anchorInEditor.focus();
is(focused, true, "focus didn't move to element in contenteditable=false by property");
is(isReallyEditable(), false, "can edit by a key event");
focused = false;
anchor.focus();
editor.setAttribute("contenteditable", "true");
anchorInEditor.focus();
is(focused, false, "focus moved to element in contenteditable=true");
is(isReallyEditable(), true, "cannot edit by a key event");
// for bug 502273
focused = false;
anchor.focus();
editor.setAttribute("dummy", "dummy");
editor.removeAttribute("dummy");
anchorInEditor.focus();
is(focused, false, "focus moved to element in contenteditable=true (after dummy attribute was removed)");
is(isReallyEditable(), true, "cannot edit by a key event");
}
SimpleTest.waitForExplicitFinish();

View File

@ -238,7 +238,7 @@ nsHTMLDocument::nsHTMLDocument()
NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
NS_ASSERTION(!nsCCUncollectableMarker::InGeneration(tmp->GetMarkedCCGeneration()),
NS_ASSERTION(!nsCCUncollectableMarker::InGeneration(cb, tmp->GetMarkedCCGeneration()),
"Shouldn't traverse nsHTMLDocument!");
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mImageMaps)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mImages)

View File

@ -43,39 +43,99 @@ relativesrcdir = content/media/test
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
# Media tests should be backend independent, i.e., not conditioned on
# MOZ_OGG, MOZ_WAVE etc. (The only exception is the can_play_type tests,
# which necessarily depend on the backend(s) configured.) As far as possible,
# each test should work with any resource type. This makes it
# easy to add new backends and reduces the amount of test duplication.
# For each supported backend, resources that can be played by that backend
# should be added to the lists in manifest.js. Media tests that aren't
# testing for a bug in handling a specific resource type should pick one of
# the lists in manifest.js and run the test for each resource in the list
# that is supported in the current build (the canPlayType API is useful
# for this).
# To test whether a valid resource can simply be played through correctly,
# and optionally that its metadata is read correctly, just
# add it to gPlayTests in manifest.js. To test whether an invalid
# resource correctly throws an error (and does not cause a crash or hang),
# just add it to gErrorTests in manifest.js.
# To test for a specific bug in handling a specific resource type,
# make the test first check canPlayType for the type, and if it's not
# supported, just do ok(true, "Type not supported") and stop the test.
_TEST_FILES = \
can_play_type_ogg.js \
can_play_type_wave.js \
manifest.js \
seek1.js \
seek2.js \
seek3.js \
seek4.js \
seek5.js \
seek6.js \
seek7.js \
seek8.js \
seek9.js \
test_audio1.html \
test_audio2.html \
test_autobuffer.html \
test_autoplay.html \
test_can_play_type.html \
test_constants.html \
test_controls.html \
test_currentTime.html \
test_decoder_disable.html \
test_load.html \
test_media_selection.html \
test_networkState.html \
test_paused.html \
test_playback.html \
test_playback_errors.html \
test_readyState.html \
test_seek.html \
test_seek2.html \
test_volume.html \
use_large_cache.js \
$(NULL)
# Ogg sample files
_TEST_FILES += \
320x240.ogv \
320x240.allow-origin.ogv \
320x240.allow-origin.ogv^headers^ \
bug461281.ogg \
bug482461.ogv \
seek.ogv \
small-shot.ogg \
sound.ogg \
$(NULL)
# Wave sample files
_TEST_FILES += \
big.wav \
r11025_s16_c1.wav \
r11025_s16_c1_trailing.wav \
r11025_u8_c1.wav \
r11025_u8_c1_trunc.wav \
r16000_u8_c1_list.wav \
$(NULL)
# These tests need to be converted to be backend-independent. This list
# is deprecated, do not add to it.
ifdef MOZ_OGG
_TEST_FILES += \
dynamic_redirect.sjs \
test_access_control.html \
file_access_controls.html \
test_audio1.html \
test_audio2.html \
test_bug448534.html \
test_bug461281.html \
test_bug468190.html \
test_bug482461.html \
test_bug493187.html \
test_bug495145.html \
test_bug495300.html \
test_bug495319.html \
test_can_play_type_ogg.html \
test_closing_connections.html \
test_contentDuration1.html \
test_contentDuration2.html \
@ -100,11 +160,6 @@ _TEST_FILES += \
test_standalone.html \
test_timeupdate1.html \
test_timeupdate2.html \
320x240.ogv \
320x240.allow-origin.ogv \
320x240.allow-origin.ogv^headers^ \
bug461281.ogg \
bug482461.ogv \
redirect.sjs \
contentDuration1.sjs \
contentDuration2.sjs \
@ -112,73 +167,57 @@ _TEST_FILES += \
contentDuration4.sjs \
contentDuration5.sjs \
contentDuration6.sjs \
seek.ogv \
small-shot.ogg \
sound.ogg \
$(NULL)
# These tests disabled until we figure out random failures.
# Bug 492821:
# test_videoDocumentTitle.html
# Bug 493692:
# test_autobuffer2.html
ifneq ($(OS_ARCH),WINNT)
# These tests are disabled on windows until we
# figure out the random failures. See bug 475369.
_TEST_FILES += \
test_seek1.html \
test_seek3.html \
test_seek4.html \
test_seek5.html \
test_seek6.html \
test_seek7.html \
test_seek8.html \
test_seek9.html \
test_timeupdate3.html \
$(NULL)
endif
endif
ifdef MOZ_OGG
_TEST_FILES += \
test_can_play_type_ogg.html \
$(NULL)
else
_TEST_FILES += \
test_can_play_type_no_ogg.html \
$(NULL)
endif
# These tests need to be converted to be backend-independent. This list
# is deprecated, do not add to it.
ifdef MOZ_WAVE
_TEST_FILES += \
big.wav \
test_bug463162.xhtml \
test_bug465498.html \
test_bug468190_wav.html \
test_bug495145_wav.html \
test_can_play_type_wave.html \
test_paused_after_ended.html \
test_progress2.html \
test_progress4.html \
test_wav_8bit.html \
test_wav_ended1.html \
test_wav_ended2.html \
test_wav_list.html \
test_wav_onloadedmetadata.html \
test_wav_seek1.html \
test_wav_seek3.html \
test_wav_seek4.html \
test_wav_seek5.html \
test_wav_seek6.html \
test_wav_seek7.html \
test_wav_seek8.html \
test_wav_seek_past_end.html \
test_wav_seek_then_play.html \
test_wav_timeupdate1.html \
test_wav_timeupdate2.html \
test_wav_trailing.html \
test_wav_trunc.html \
test_wav_trunc_seek.html \
r11025_s16_c1.wav \
r11025_s16_c1_trailing.wav \
r11025_u8_c1.wav \
r11025_u8_c1_trunc.wav \
r16000_u8_c1_list.wav \
$(NULL)
# Disabled since we don't play Wave files standalone, for now
# test_wav_standalone.html
# test_audioDocumentTitle.html
endif
ifdef MOZ_WAVE
_TEST_FILES += \
test_can_play_type_wave.html \
$(NULL)
else
_TEST_FILES += \
@ -186,19 +225,5 @@ _TEST_FILES += \
$(NULL)
endif
# Disabled since we don't play Wave files standalone, for now
# test_wav_standalone.html
# test_audioDocumentTitle.html
ifdef MOZ_OGG
ifdef MOZ_WAVE
_TEST_FILES += \
test_decoder_disable.html \
test_load.html \
test_media_selection.html \
$(NULL)
endif
endif
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)

View File

@ -0,0 +1,45 @@
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus

View File

@ -0,0 +1,45 @@
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus

View File

@ -0,0 +1,45 @@
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus
bogus bogus bogus

View File

@ -0,0 +1,18 @@
<html>
<head>
<script type="text/javascript">
function boom()
{
s = document.createElement("span");
a = document.createElement("audio");
a['src'] = "javascript:4";
a['loopend'] = 3;
s.appendChild(a);
}
</script>
</head>
<body onload="boom();"></body>
</html>

View File

@ -1,3 +1,4 @@
load 468763-1.html
load 474744-1.html
load 493915-1.html
load 495794-1.html

View File

@ -0,0 +1,67 @@
// In each list of tests below, test file types that are not supported should
// be ignored. To make sure tests respect that, we include a file of type
// "bogus/duh" in each list.
// These are small test files, good for just seeing if something loads.
var gSmallTests = [
{ name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
{ name:"320x240.ogv", type:"video/ogg", width:320, height:240 },
{ name:"bogus.duh", type:"bogus/duh" }
];
// These are files that we just want to make sure we can play through.
// We can also check metadata.
// Put files of the same type together in this list so if something crashes
// we have some idea of which backend is responsible.
var gPlayTests = [
// 8-bit samples
{ name:"r11025_u8_c1.wav", type:"audio/x-wav", duration:1.0 },
// 8-bit samples, file is truncated
{ name:"r11025_u8_c1_trunc.wav", type:"audio/x-wav", duration:1.8 },
// file has trailing non-PCM data
{ name:"r11025_s16_c1_trailing.wav", type:"audio/x-wav", duration:1.0 },
// file with list chunk
{ name:"r16000_u8_c1_list.wav", type:"audio/x-wav", duration:4.2 },
// Ogg stream with eof marker
{ name:"bug461281.ogg", type:"application/ogg" },
// oggz-chop stream
{ name:"bug482461.ogv", type:"video/ogg", duration:4.24 },
{ name:"bogus.duh", type:"bogus/duh" }
];
// These are files that should refuse to play and report an error,
// without crashing of course.
// Put files of the same type together in this list so if something crashes
// we have some idea of which backend is responsible.
var gErrorTests = [
{ name:"bogus.wav", type:"audio/x-wav" },
{ name:"bogus.ogv", type:"video/ogg" },
{ name:"bogus.duh", type:"bogus/duh" }
];
// These are files that have nontrivial duration and are useful for seeking within.
var gSeekTests = [
{ name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
{ name:"seek.ogv", type:"video/ogg", duration:3.966 },
{ name:"bogus.duh", type:"bogus/duh", duration:123 }
];
// These are files suitable for using with a "new Audio" constructor.
var gAudioTests = [
{ name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
{ name:"sound.ogg", type:"audio/ogg" },
{ name:"bogus.duh", type:"bogus/duh", duration:123 }
];
function checkMetadata(msg, e, test) {
if (test.width) {
is(e.videoWidth, test.width, msg + " video width");
}
if (test.height) {
is(e.videoHeight, test.height, msg + " video height");
}
if (test.duration) {
ok(Math.abs(e.duration - test.duration) < 0.1,
msg + " duration should be around " + test.duration);
}
}

View File

@ -1,14 +1,5 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Media test: seek test 1</title>
<script type="text/javascript" src="/MochiKit/packed.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">
function test_seek1(v, seekTime, is, ok, finish) {
var startPassed = false;
var endPassed = false;
var seekFlagStart = false;
@ -19,7 +10,6 @@ var completed = false;
function startTest() {
if (completed)
return false;
var v = document.getElementById('v');
ok(!v.seeking, "seeking should default to false");
try {
v.seeking = 1;
@ -31,7 +21,7 @@ function startTest() {
ok(readonly, "seeking should be readonly");
v.play();
v.currentTime=2;
v.currentTime=seekTime;
seekFlagStart = v.seeking;
return false;
}
@ -39,7 +29,6 @@ function startTest() {
function seekStarted() {
if (completed)
return false;
var v = document.getElementById('v');
v.pause();
startPassed = true;
return false;
@ -49,12 +38,11 @@ function seekEnded() {
if (completed)
return false;
var v = document.getElementById('v');
var t = v.currentTime;
// Since we were playing, and we only paused asynchronously, we can't be
// sure that we paused before the seek finished, so we may have played
// ahead arbitrarily far.
ok(t >= 1.9, "Video currentTime should be around 2: " + t);
ok(t >= seekTime - 0.1, "Video currentTime should be around " + seekTime + ": " + t);
v.play();
endPassed = true;
seekFlagEnd = v.seeking;
@ -70,18 +58,13 @@ function playbackEnded() {
ok(endPassed, "seeked event");
ok(seekFlagStart, "seeking flag on start should be true");
ok(!seekFlagEnd, "seeking flag on end should be false");
SimpleTest.finish();
finish();
return false;
}
SimpleTest.waitForExplicitFinish();
</script>
</pre>
<video id='v'
src='seek.ogv'
onended='return playbackEnded();'
onloadedmetadata='return startTest();'
onseeking='return seekStarted();'
onseeked='return seekEnded();'></video>
</body>
</html>
v.addEventListener("ended", playbackEnded, false);
v.addEventListener("loadedmetadata", startTest, false);
v.addEventListener("seeking", seekStarted, false);
v.addEventListener("seeked", seekEnded, false);
}

View File

@ -0,0 +1,52 @@
function test_seek2(v, seekTime, is, ok, finish) {
// Test seeking works if current time is set before video is
// playing.
var startPassed = false;
var endPassed = false;
var completed = false;
function startTest() {
if (completed)
return false;
v.currentTime=seekTime;
v.play();
return false;
}
function seekStarted() {
if (completed)
return false;
startPassed = true;
return false;
}
function seekEnded() {
if (completed)
return false;
endPassed = true;
return false;
}
function playbackEnded() {
if (completed)
return false
completed = true;
ok(startPassed, "send seeking event");
ok(endPassed, "send seeked event");
ok(v.ended, "Checking playback has ended");
ok(Math.abs(v.currentTime - v.duration) <= 0.1, "Checking currentTime at end: " + v.currentTime);
finish();
return false;
}
v.addEventListener("ended", playbackEnded, false);
v.addEventListener("loadedmetadata", startTest, false);
v.addEventListener("seeking", seekStarted, false);
v.addEventListener("seeked", seekEnded, false);
}

View File

@ -0,0 +1,38 @@
function test_seek3(v, seekTime, is, ok, finish) {
// Test seeking works if current time is set but video is not played.
var startPassed = false;
var completed = false;
function startTest() {
if (completed)
return false;
v.currentTime=seekTime;
return false;
}
function seekStarted() {
if (completed)
return false;
startPassed = true;
return false;
}
function seekEnded() {
if (completed)
return false;
var t = v.currentTime;
ok(Math.abs(t - seekTime) <= 0.1, "Video currentTime should be around " + seekTime + ": " + t);
completed = true;
finish();
return false;
}
v.addEventListener("loadedmetadata", startTest, false);
v.addEventListener("seeking", seekStarted, false);
v.addEventListener("seeked", seekEnded, false);
}

View File

@ -0,0 +1,41 @@
function test_seek4(v, seekTime, is, ok, finish) {
// Test for a seek, followed by another seek before the first is complete.
var seekCount = 0;
var completed = false;
function startTest() {
if (completed)
return false;
v.currentTime=seekTime;
return false;
}
function seekStarted() {
if (completed)
return false;
v.currentTime=seekTime/2;
return false;
}
function seekEnded() {
if (completed)
return false;
seekCount++;
if (seekCount == 2) {
ok(Math.abs(v.currentTime - seekTime/2) <= 0.1, "Second seek on target: " + v.currentTime);
completed = true;
finish();
}
return false;
}
v.addEventListener("loadedmetadata", startTest, false);
v.addEventListener("seeking", seekStarted, false);
v.addEventListener("seeked", seekEnded, false);
}

View File

@ -0,0 +1,46 @@
function test_seek5(v, seekTime, is, ok, finish) {
// 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 endPassed = false;
var completed = false;
function startTest() {
if (completed)
return false;
v.currentTime=seekTime;
return false;
}
function seekStarted() {
if (completed)
return false;
startPassed = true;
v.play();
return false;
}
function seekEnded() {
if (completed)
return false;
endPassed = true;
return false;
}
function playbackEnded() {
if (completed)
return false;
ok(startPassed, "Got seeking event");
ok(endPassed, "Got seeked event");
completed = true;
finish();
return false;
}
v.addEventListener("ended", playbackEnded, false);
v.addEventListener("loadedmetadata", startTest, false);
v.addEventListener("seeking", seekStarted, false);
v.addEventListener("seeked", seekEnded, false);
}

View File

@ -0,0 +1,33 @@
function test_seek6(v, seekTime, is, ok, finish) {
// Test for bug identified by Chris Pearce in comment 40 on
// bug 449159.
var seekCount = 0;
var completed = false;
var interval;
function startTest() {
if (completed)
return false;
interval = setInterval(function() { v.currentTime=Math.random()*v.duration; }, 10);
return false;
}
function seekEnded() {
if (completed)
return false;
seekCount++;
ok(true, "Seek " + seekCount);
if (seekCount == 3) {
clearInterval(interval);
completed = true;
finish();
}
return false;
}
v.addEventListener("loadedmetadata", startTest, false);
v.addEventListener("seeked", seekEnded, false);
}

View File

@ -0,0 +1,35 @@
function test_seek7(v, seekTime, is, ok, finish) {
// If a NaN is passed to currentTime, make sure this is caught
// otherwise an infinite loop in the Ogg backend occurs.
var completed = false;
var thrown1 = false;
var thrown2 = false;
var thrown3 = false;
function startTest() {
if (completed)
return false;
try {
v.currentTime = NaN;
} catch(e) {
thrown1 = true;
}
try {
v.currentTime = Math.random;
} catch(e) {
thrown3 = true;
}
completed = true;
ok(thrown1, "Setting currentTime to invalid value of NaN");
ok(thrown3, "Setting currentTime to invalid value of a function");
finish();
return false;
}
v.addEventListener("loadedmetadata", startTest, false);
}

View File

@ -0,0 +1,21 @@
function test_seek8(v, seekTime, is, ok, finish) {
var completed = false;
function startTest() {
v.currentTime = 1000;
}
function seekEnded() {
if (completed)
return false;
ok(Math.abs(v.currentTime - v.duration) < 0.2,
"currentTime " + v.currentTime + " close to " + v.duration);
finish();
}
v.addEventListener("loadedmetadata", startTest, false);
v.addEventListener("seeked", seekEnded, false);
}

View File

@ -0,0 +1,20 @@
function test_seek9(v, seekTime, is, ok, finish) {
var completed = false;
function startTest() {
v.currentTime = -1000;
}
function seekEnded() {
if (completed)
return false;
is(v.currentTime, 0, "currentTime clamped to 0");
finish();
}
v.addEventListener("loadedmetadata", startTest, false);
v.addEventListener("seeked", seekEnded, false);
}

View File

@ -5,17 +5,33 @@
<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" />
<script type="text/javascript" src="use_large_cache.js"></script>
<script type="text/javascript" src="manifest.js"></script>
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
var a1 = new Audio();
a1.addEventListener('load', function() {
is(a1.networkState, HTMLMediaElement.NETWORK_LOADED, "Audio loaded");
SimpleTest.finish();
}, false);
a1.src = 'sound.ogg';
a1.load();
var testsWaiting = 0;
for (var i = 0; i < gAudioTests.length; ++i) {
var test = gAudioTests[i];
var a1 = new Audio();
if (a1.canPlayType(test.type) == "no")
continue;
a1.setAttribute("autobuffer", "");
a1.addEventListener('load', function(event) {
is(event.target.networkState, HTMLMediaElement.NETWORK_LOADED,
"Audio " + event.target.currentSrc + " loaded");
--testsWaiting;
if (testsWaiting == 0) {
SimpleTest.finish();
}
}, false);
a1.src = test.name;
a1.load();
++testsWaiting;
}
SimpleTest.waitForExplicitFinish();
</script>

View File

@ -1,20 +1,37 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Media test: Audio Constructor Test 2</title>
<title>Media test: Audio Constructor Test 1</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" />
<script type="text/javascript" src="use_large_cache.js"></script>
<script type="text/javascript" src="manifest.js"></script>
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
var a1 = Audio('sound.ogg');
a1.addEventListener('load', function() {
is(a1.networkState, HTMLMediaElement.NETWORK_LOADED, "Audio loaded");
SimpleTest.finish();
}, false);
a1.load();
var testsWaiting = 0;
var tmpAudio = new Audio();
for (var i = 0; i < gAudioTests.length; ++i) {
var test = gAudioTests[i];
if (tmpAudio.canPlayType(test.type) == "no")
continue;
var a1 = new Audio(test.name);
a1.setAttribute("autobuffer", "");
a1.addEventListener('load', function(event) {
is(event.target.networkState, HTMLMediaElement.NETWORK_LOADED,
"Audio " + event.target.currentSrc + " loaded");
--testsWaiting;
if (testsWaiting == 0) {
SimpleTest.finish();
}
}, false);
a1.load();
++testsWaiting;
}
SimpleTest.waitForExplicitFinish();
</script>

View File

@ -1,44 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Media test: Bug 461281 - Ogg Streams with eof marker</title>
<script type="text/javascript" src="/MochiKit/packed.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">
// Test if the ended event occurs with media without an eos marker
var endPassed = false;
var completed = false;
function startTest() {
if (completed)
return false;
var v = document.getElementById('v');
v.play();
return false;
}
function playbackEnded() {
if (completed)
return false
completed = true;
var v = document.getElementById('v');
ok(v.ended, "Checking playback has ended");
SimpleTest.finish();
return false;
}
SimpleTest.waitForExplicitFinish();
</script>
</pre>
<video id='v'
src='bug461281.ogg'
onloadedmetadata='return startTest();'
onended='return playbackEnded();'></video>
</body>
</html>

View File

@ -1,49 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=482461
-->
<head>
<title>Media test: Bug 482461 - Play oggz-chop streams</title>
<script type="text/javascript" src="/MochiKit/packed.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=482461">Mozilla Bug 482461</a>
<pre id="test">
<script class="testbody" type="text/javascript">
var v;
var endPassed = false;
var completed = false;
function startTest() {
if (completed)
return false;
v = document.getElementById('v');
v.play();
return false;
}
function playbackEnded() {
if (completed)
return false
completed = true;
ok(v.currentTime > 3 && v.currentTime < 5,
"Checking currentTime at end: " + v.currentTime);
ok(v.ended, "Checking playback has ended");
SimpleTest.finish();
return false;
}
SimpleTest.waitForExplicitFinish();
</script>
</pre>
<video id='v'
src='bug482461.ogv'
onloadedmetadata='return startTest();'
onended='return playbackEnded();'></video>
</body>
</html>

View File

@ -9,6 +9,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=479859
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="use_large_cache.js"></script>
<script type="application/javascript" src="manifest.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=479859">Mozilla Bug 479859</a>
@ -25,15 +26,17 @@ function log(msg) {
// We don't track: progress, canplay, canplaythrough and stalled events,
// as these can be delivered out of order, and/or multiple times.
var gEventTypes = [ 'loadstart', 'load', 'abort', 'error', 'emptied', 'play', 'pause', 'loadedmetadata', 'loadeddata', 'waiting', 'playing', 'seeking', 'seeked', 'timeupdate', 'ended', 'ratechange', 'durationchange', 'volumechange' ];
var gEventTypes = [ 'loadstart', 'load', 'abort', 'error', 'emptied', 'play',
'pause', 'loadedmetadata', 'loadeddata', 'waiting', 'playing', 'seeking',
'seeked', 'timeupdate', 'ended', 'ratechange', 'durationchange', 'volumechange' ];
var gEventNum = 0;
var gTestNum = 0;
var gTestFileNum = 0;
var gExpectedEvents = null;
var gTest = null;
var gTestName = "?";
function listener(evt) {
log('event ' + evt.type);
evt.stopPropagation();
@ -56,12 +59,6 @@ function createMedia(tag) {
}
}
var gWavAudio = 'r11025_s16_c1.wav';
var gWavAudioType = 'audio/x-wav';
var gOggVideo = '320x240.ogv';
var gOggVideoType = "application/ogg";
function addSource(src, type) {
var s = document.createElement("source");
s.src = src;
@ -76,153 +73,74 @@ function prependSource(src, type) {
gMedia.insertBefore(s, gMedia.firstChild);
}
var gTest10Prepended = false;
var gTest11Prepended = false;
var gTests = [
{
// Test 0: adding video to doc, then setting src should load implicitly.
create:
function() {
createMedia("video");
function(src, type) {
document.body.appendChild(gMedia);
gMedia.src = gOggVideo;
gMedia.src = src;
},
expectedEvents: ['loadstart', 'durationchange', 'loadedmetadata', 'loadeddata', 'load']
}, {
// Test 1: adding audio to doc, then setting src should load implicitly.
// Test 1: adding video to doc, then adding source.
create:
function() {
createMedia("audio");
function(src, type) {
document.body.appendChild(gMedia);
gMedia.src = gWavAudio;
addSource(src, type);
},
expectedEvents: ['loadstart', 'durationchange', 'loadedmetadata', 'loadeddata', 'load']
}, {
// Test 2: adding video to doc, then adding source.
// Test 2: video with multiple source, the first of which are bad, we should load the last.
create:
function() {
createMedia("video");
function(src, type) {
document.body.appendChild(gMedia);
addSource(gOggVideo, gOggVideoType);
addSource("404a", type);
addSource("404b", type);
addSource(src, type);
},
expectedEvents: ['loadstart', 'durationchange', 'loadedmetadata', 'loadeddata', 'load']
}, {
// Test 3: adding audio to doc, then adding source.
// Test 3: video with bad src, good <source>, ensure that <source> aren't used.
create:
function() {
createMedia("audio");
document.body.appendChild(gMedia);
addSource(gWavAudio, gWavAudioType);
},
expectedEvents: ['loadstart', 'durationchange', 'loadedmetadata', 'loadeddata', 'load']
}, {
// Test 4: video with multiple source, the first of which are bad, we should load the last.
create:
function() {
createMedia("video");
document.body.appendChild(gMedia);
addSource("404a.ogv", gOggVideoType);
addSource("404b.ogv", gOggVideoType);
addSource(gOggVideo, gOggVideoType);
},
expectedEvents: ['loadstart', 'durationchange', 'loadedmetadata', 'loadeddata', 'load']
}, {
// Test 5: audio with multiple source, the first of which are bad, we should load the last.
create:
function() {
createMedia("audio");
document.body.appendChild(gMedia);
addSource("404a.wav", gWavAudioType);
addSource("404b.wav", gWavAudioType);
addSource(gWavAudio, gWavAudioType);
},
expectedEvents: ['loadstart', 'durationchange', 'loadedmetadata', 'loadeddata', 'load']
}, {
// Test 6: video with bad src, good <source>, ensure that <source> aren't used.
create:
function() {
createMedia("video");
gMedia.src = "404a.ogv";
addSource(gOggVideo, gOggVideoType);
function(src, type) {
gMedia.src = "404a";
addSource(src, type);
document.body.appendChild(gMedia);
},
expectedEvents: ['loadstart', 'error']
}, {
// Test 7: audio with bad src, good <source>, ensure that <source> aren't used.
// Test 4: video with only bad source, loading, then adding a good source
// - should resume load.
create:
function() {
createMedia("audio");
gMedia.src = "404a.wav";
addSource(gWavAudio, gWavAudioType);
document.body.appendChild(gMedia);
},
expectedEvents: ['loadstart', 'error']
}, {
// Test 8: video with only bad source, loading, then adding a good source - should resume load.
create:
function() {
createMedia("video");
addSource("404a.ogv", gOggVideoType);
addSource("404b.ogv", gOggVideoType);
function(src, type) {
addSource("404a", type);
addSource("404b", type);
gMedia.addEventListener("error",
function(e) {
// Should awaken waiting load, causing successful load.
addSource(gOggVideo, gOggVideoType);
addSource(src, type);
},
false);
document.body.appendChild(gMedia);
},
expectedEvents: ['loadstart', 'error', 'durationchange', 'loadedmetadata', 'loadeddata', 'load']
}, {
// Test 9: audio with only bad source, loading, then adding a good source - should resume load.
create:
function() {
createMedia("audio");
addSource("404a.wav", gWavAudioType);
addSource("404b.wav", gWavAudioType);
gMedia.addEventListener("error",
function(e) {
// Should awaken waiting load, causing successful load.
addSource(gWavAudio, gWavAudioType);
},
false);
document.body.appendChild(gMedia);
},
expectedEvents: ['loadstart', 'error', 'durationchange', 'loadedmetadata', 'loadeddata', 'load']
}, {
// Test 10: video with only 1 bad source, let it fail to load, then prepend a good <source> to the video, it shouldn't be selected, because the "pointer" should be after the last child - the bad source.
// Test 5: video with only 1 bad source, let it fail to load, then prepend
// a good <source> to the video, it shouldn't be selected, because the
// "pointer" should be after the last child - the bad source.
prepended: false,
create:
function() {
createMedia("video");
addSource("404a.ogv", gOggVideoType);
addSource("404b.ogv", gOggVideoType);
function(src, type) {
var prepended = false;
addSource("404a", type);
addSource("404b", type);
gMedia.addEventListener("error",
function(e) {
// Should awaken waiting load, causing successful load.
if (!gTest10Prepended) {
prependSource(gOggVideo, gOggVideoType);
gTest10Prepended = true;
}
},
false);
document.body.appendChild(gMedia);
},
expectedEvents: ['loadstart', 'error', 'error']
}, {
// Test 11: audio with only 1 bad source, let it fail to load, then prepend a good <source> to the video, it shouldn't be selected, because the "pointer" should be after the last child - the bad source.
create:
function() {
createMedia("audio");
addSource("404a.wav", gWavAudioType);
addSource("404b.wav", gWavAudioType);
gMedia.addEventListener("error",
function(e) {
// Should awaken waiting load, causing successful load.
if (!gTest11Prepended) {
prependSource(gWavAudio, gWavAudioType);
gTest11Prepended = true;
if (!prepended) {
prependSource(src, type);
prepended = true;
}
},
false);
@ -239,20 +157,34 @@ function nextTest() {
gMedia = null;
}
gEventNum = 0;
if (gTestNum == gTests.length) {
SimpleTest.finish();
return;
gTestNum = 0;
++gTestFileNum;
if (gTestFileNum == gSmallTests.length) {
SimpleTest.finish();
return;
}
}
log("Starting test " + gTestNum);
var src = gSmallTests[gTestFileNum].name;
var type = gSmallTests[gTestFileNum].type;
var t = gTests[gTestNum];
gTestName = "Test"+gTestNum;
gTestNum++;
createMedia(type.match(/^audio\//) ? "audio" : "video");
if (gMedia.canPlayType(type) == "no") {
// Unsupported type, skip to next test
nextTest();
return;
}
gTestName = "Test " + src + " " + (gTestNum - 1);
log("Starting " + gTestName);
gExpectedEvents = t.expectedEvents;
t.create();
t.create(src, type);
}
addLoadEvent(nextTest);

View File

@ -5,17 +5,18 @@
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="application/javascript" src="manifest.js"></script>
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
function maketest(expect_load, attach_media, name, type, check_metadata) {
function maketest(attach_media, name, type, check_metadata) {
return function (testNum) {
var e = document.createElement('video');
var errorRun = false;
if (expect_load) {
if (check_metadata) {
e.addEventListener('loadedmetadata', function () {
ok(e.readyState >= HTMLMediaElement.HAVE_METADATA,
'test ' + testNum + ' readyState ' + e.readyState + ' expected >= ' + HTMLMediaElement.HAVE_METADATA);
@ -31,7 +32,6 @@ function maketest(expect_load, attach_media, name, type, check_metadata) {
} else {
e.addEventListener('error', function(event) {
event.stopPropagation();
is(expect_load, false, "Didn't load when we weren't expecting to.");
is(errorRun, false, "error handler should run once only!");
errorRun = true;
is(e.readyState, HTMLMediaElement.HAVE_NOTHING,
@ -87,56 +87,56 @@ function late_add_sources_first(element, name, type) {
do_add_source(element, name, 'unsupported/type');
}
function check_ogg(e) {
is(e.videoWidth, 320, "video width " + e.currentSrc);
is(e.videoHeight, 240, "video height " + e.currentSrc);
}
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.ogv', null, check_ogg),
maketest(true, add_source, '320x240.ogv', null, check_ogg),
maketest(true, add_source, '320x240.ogv', 'application/ogg', check_ogg),
maketest(true, add_sources_last, '320x240.ogv', null, check_ogg),
maketest(true, add_sources_first, '320x240.ogv', '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),
var subtests = [
maketest(add_source, 'unknown.raw', 'bogus/type', null)
];
var tmpVid = document.createElement('video');
for (var i = 0; i < gSmallTests.length; ++i) {
var test = gSmallTests[i];
var src = test.name;
var type = test.type;
if (tmpVid.canPlayType(type) == "no")
continue;
// The following nested function hack is to ensure that 'test' is correctly
// captured in the closure and we don't end up getting the value 'test'
// had in the last iteration of the loop. I blame Brendan.
var check = function(test) { return function (e) {
checkMetadata(test.name, e, test);
}}(test);
var otherType = type.match(/^video\//) ? "audio/x-wav" : "video/ogg";
subtests.push(maketest(set_src, src, null, check),
maketest(add_source, src, null, check),
maketest(add_source, src, type, check),
maketest(add_sources_last, src, null, check),
maketest(add_sources_first, src, type, check),
// type hint matches a decoder, actual type matches different decoder
maketest(true, add_source, '320x240.ogv', 'audio/x-wav', check_ogg),
maketest(true, add_source, 'r11025_u8_c1.wav', 'application/ogg', check_wav),
maketest(add_source, src, otherType, check),
maketest(add_source, 'unknown.raw', type, null),
// should not start loading, type excludes it from media candiate list
maketest(false, add_source, '320x240.ogv', '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(false, add_source, 'unknown.raw', 'application/ogg', null),
maketest(false, add_source, 'unknown.raw', 'audio/x-wav', null),
maketest(add_source, src, 'bogus/type', null),
// element doesn't notice source children attached later, needs bug 462455 fixed
maketest(true, late_add_sources_last, '320x240.ogv', 'application/ogg', check_ogg),
maketest(true, late_add_sources_first, '320x240.ogv', 'application/ogg', check_ogg),
maketest(true, late_add_sources_last, 'r11025_u8_c1.wav', 'audio/x-wav', check_wav),
maketest(true, late_add_sources_first, 'r11025_u8_c1.wav', 'audio/x-wav', check_wav),
SimpleTest.finish
];
maketest(late_add_sources_last, src, type, check),
maketest(late_add_sources_first, src, type, check));
}
function runNextTest() {
if (nextTest >= subtests.length) {
SimpleTest.finish();
return;
}
setTimeout(function () {
ok(true, 'subtest ' + nextTest);
subTests[nextTest](nextTest);
nextTest += 1;
}, 0);
subtests[nextTest](nextTest);
nextTest += 1;
}, 0);
}
addLoadEvent(runNextTest);

View File

@ -0,0 +1,75 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test playback of media files that should play OK</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
var PARALLEL_TESTS = 2;
var testIndex = 0;
var videos = [];
var testsWaiting = 0;
function startTest() {
if (completed)
return false;
v = document.getElementById('v');
v.play();
return false;
}
function startTests() {
for (var i = 0; i < videos.length; ++i) {
document.body.removeChild(videos[i]);
}
videos = [];
while (videos.length < PARALLEL_TESTS && testIndex < gPlayTests.length) {
var v = document.createElement('video');
var test = gPlayTests[testIndex];
++testIndex;
if (v.canPlayType(test.type) == "no")
continue;
v.src = test.name;
var check = function(test, v) { return function() {
checkMetadata(test.name, v, test);
}}(test, v);
var checkEnded = function(test, v) { return function() {
if (test.duration) {
ok(Math.abs(v.currentTime - test.duration) < 0.1,
test.name + " current time at end: " + v.currentTime);
}
ok(v.ended, test.name + " checking playback has ended");
--testsWaiting;
if (testsWaiting == 0) {
setTimeout(startTests, 0);
}
}}(test, v);
v.addEventListener("loadedmetadata", check, false);
v.addEventListener("ended", checkEnded, false);
++testsWaiting;
document.body.appendChild(v);
v.play();
videos.push(v);
}
if (videos.length == 0) {
// No new tests were spawned, perhaps the remaining tests on the list are
// not supported, or we just reached the end of the list.
SimpleTest.finish();
}
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(startTests);
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,82 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test playback of media files that should have errors</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
var PARALLEL_TESTS = 2;
var testIndex = 0;
var videos = [];
var testsWaiting = 0;
function startTest() {
if (completed)
return false;
v = document.getElementById('v');
v.play();
return false;
}
function startTests() {
for (var i = 0; i < videos.length; ++i) {
document.body.removeChild(videos[i]);
}
videos = [];
while (videos.length < PARALLEL_TESTS && testIndex < gErrorTests.length) {
var v = document.createElement('video');
var test = gErrorTests[testIndex];
++testIndex;
if (v.canPlayType(test.type) == "no")
continue;
v.src = test.name;
v._errorCount = 0;
v._ignore = false;
function endedTest(v) {
if (v._ignore)
return;
v._ignore = true;
--testsWaiting;
if (testsWaiting == 0) {
setTimeout(startTests, 0);
}
}
var checkError = function(test, v) { return function(evt) {
evt.stopPropagation();
v._errorCount++;
is(v._errorCount, 1, test.name + " only one error fired");
endedTest(v);
}}(test, v);
var checkEnded = function(test, v) { return function() {
ok(false, test.name + " successfully played");
endedTest(v);
}}(test, v);
v.addEventListener("error", checkError, false);
v.addEventListener("ended", checkEnded, false);
++testsWaiting;
document.body.appendChild(v);
v.play();
videos.push(v);
}
if (videos.length == 0) {
// No new tests were spawned, perhaps the remaining tests on the list are
// not supported, or we just reached the end of the list.
SimpleTest.finish();
}
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(startTests);
</script>
</pre>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More