зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central into e10s.
This commit is contained in:
Коммит
34440c4bbc
|
@ -54,9 +54,9 @@
|
|||
#include "nsIServiceManager.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
//-------------
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsLeafAccessible
|
||||
//-------------
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsLeafAccessible::nsLeafAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
|
||||
nsAccessibleWrap(aNode, aShell)
|
||||
|
@ -65,34 +65,6 @@ nsAccessibleWrap(aNode, aShell)
|
|||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(nsLeafAccessible, nsAccessible)
|
||||
|
||||
/* nsIAccessible getFirstChild (); */
|
||||
NS_IMETHODIMP nsLeafAccessible::GetFirstChild(nsIAccessible **_retval)
|
||||
{
|
||||
*_retval = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* nsIAccessible getLastChild (); */
|
||||
NS_IMETHODIMP nsLeafAccessible::GetLastChild(nsIAccessible **_retval)
|
||||
{
|
||||
*_retval = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* long getAccChildCount (); */
|
||||
NS_IMETHODIMP nsLeafAccessible::GetChildCount(PRInt32 *_retval)
|
||||
{
|
||||
*_retval = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsAccessible::GetAllowsAnonChildAccessibles()
|
||||
PRBool
|
||||
nsLeafAccessible::GetAllowsAnonChildAccessibles()
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// nsAccessible::GetChildAtPoint()
|
||||
nsresult
|
||||
nsLeafAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
|
||||
|
@ -104,19 +76,29 @@ nsLeafAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsAccessible::CacheChildren()
|
||||
void
|
||||
nsLeafAccessible::CacheChildren()
|
||||
{
|
||||
// No children for leaf accessible.
|
||||
mAccChildCount = IsDefunct() ? eChildCountUninitialized : 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsLinkableAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsLinkableAccessible::
|
||||
nsLinkableAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell) :
|
||||
nsHyperTextAccessibleWrap(aNode, aShell),
|
||||
nsAccessibleWrap(aNode, aShell),
|
||||
mActionContent(nsnull),
|
||||
mIsLink(PR_FALSE),
|
||||
mIsOnclick(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(nsLinkableAccessible, nsHyperTextAccessibleWrap)
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(nsLinkableAccessible, nsAccessibleWrap)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsLinkableAccessible. nsIAccessible
|
||||
|
@ -128,14 +110,13 @@ nsLinkableAccessible::TakeFocus()
|
|||
if (actionAcc)
|
||||
return actionAcc->TakeFocus();
|
||||
|
||||
return nsHyperTextAccessibleWrap::TakeFocus();
|
||||
return nsAccessibleWrap::TakeFocus();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsLinkableAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
|
||||
{
|
||||
nsresult rv = nsHyperTextAccessibleWrap::GetStateInternal(aState,
|
||||
aExtraState);
|
||||
nsresult rv = nsAccessibleWrap::GetStateInternal(aState, aExtraState);
|
||||
NS_ENSURE_A11Y_SUCCESS(rv, rv);
|
||||
|
||||
if (mIsLink) {
|
||||
|
@ -153,7 +134,7 @@ nsLinkableAccessible::GetValue(nsAString& aValue)
|
|||
{
|
||||
aValue.Truncate();
|
||||
|
||||
nsHyperTextAccessible::GetValue(aValue);
|
||||
nsAccessible::GetValue(aValue);
|
||||
if (!aValue.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
|
@ -206,7 +187,7 @@ nsLinkableAccessible::DoAction(PRUint8 aIndex)
|
|||
if (actionAcc)
|
||||
return actionAcc->DoAction(aIndex);
|
||||
|
||||
return nsHyperTextAccessibleWrap::DoAction(aIndex);
|
||||
return nsAccessibleWrap::DoAction(aIndex);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -250,14 +231,14 @@ nsresult
|
|||
nsLinkableAccessible::Init()
|
||||
{
|
||||
CacheActionContent();
|
||||
return nsHyperTextAccessibleWrap::Init();
|
||||
return nsAccessibleWrap::Init();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsLinkableAccessible::Shutdown()
|
||||
{
|
||||
mActionContent = nsnull;
|
||||
return nsHyperTextAccessibleWrap::Shutdown();
|
||||
return nsAccessibleWrap::Shutdown();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -62,24 +62,24 @@ public:
|
|||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetFirstChild(nsIAccessible **_retval);
|
||||
NS_IMETHOD GetLastChild(nsIAccessible **_retval);
|
||||
NS_IMETHOD GetChildCount(PRInt32 *_retval);
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
|
||||
PRBool aDeepestChild,
|
||||
nsIAccessible **aChild);
|
||||
virtual PRBool GetAllowsAnonChildAccessibles();
|
||||
|
||||
protected:
|
||||
|
||||
// nsAccessible
|
||||
virtual void CacheChildren();
|
||||
};
|
||||
|
||||
/**
|
||||
* A type of accessible for DOM nodes containing an href="" attribute.
|
||||
* It knows how to report the state of the link ( traveled or not )
|
||||
* and can activate ( click ) the link programmatically.
|
||||
*/
|
||||
class nsLinkableAccessible : public nsHyperTextAccessibleWrap
|
||||
* Used for text or image accessible nodes contained by link accessibles or
|
||||
* accessibles for nodes with registered click event handler. It knows how to
|
||||
* report the state of the host link (traveled or not) and can activate (click)
|
||||
* the host accessible programmatically.
|
||||
*/
|
||||
class nsLinkableAccessible : public nsAccessibleWrap
|
||||
{
|
||||
public:
|
||||
enum { eAction_Jump = 0 };
|
||||
|
@ -96,7 +96,7 @@ public:
|
|||
NS_IMETHOD TakeFocus();
|
||||
NS_IMETHOD GetKeyboardShortcut(nsAString& _retval);
|
||||
|
||||
// nsIHyperLinkAccessible
|
||||
// nsIAccessibleHyperLink
|
||||
NS_IMETHOD GetURI(PRInt32 i, nsIURI **aURI);
|
||||
|
||||
// nsAccessNode
|
||||
|
|
|
@ -38,27 +38,18 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// NOTE: alphabetically ordered
|
||||
#include "nsTextAccessible.h"
|
||||
|
||||
// ------------
|
||||
// Text Accessibles
|
||||
// ------------
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsTextAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsTextAccessible::nsTextAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
|
||||
nsLinkableAccessible(aDOMNode, aShell)
|
||||
{
|
||||
nsTextAccessible::
|
||||
nsTextAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell) :
|
||||
nsLinkableAccessible(aDOMNode, aShell)
|
||||
{
|
||||
}
|
||||
|
||||
// Make sure we don't support text or other irrelevant interfaces.
|
||||
// We have nsLinkableAccessible in our inheritance chain as a convenience in order to
|
||||
// get link actions and states on the text accessibles. Windows screen readers expect that.
|
||||
NS_IMPL_ISUPPORTS_INHERITED2(nsTextAccessible, nsAccessNode,
|
||||
nsAccessible, nsIAccessible)
|
||||
|
||||
/**
|
||||
* We are text
|
||||
*/
|
||||
nsresult
|
||||
nsTextAccessible::GetRoleInternal(PRUint32 *aRole)
|
||||
{
|
||||
|
@ -66,33 +57,6 @@ nsTextAccessible::GetRoleInternal(PRUint32 *aRole)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* No Children
|
||||
*/
|
||||
NS_IMETHODIMP nsTextAccessible::GetFirstChild(nsIAccessible **_retval)
|
||||
{
|
||||
*_retval = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* No Children
|
||||
*/
|
||||
NS_IMETHODIMP nsTextAccessible::GetLastChild(nsIAccessible **_retval)
|
||||
{
|
||||
*_retval = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* No Children
|
||||
*/
|
||||
NS_IMETHODIMP nsTextAccessible::GetChildCount(PRInt32 *_retval)
|
||||
{
|
||||
*_retval = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTextAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset, PRUint32 aLength)
|
||||
{
|
||||
|
@ -102,3 +66,9 @@ nsTextAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset, PRUint32
|
|||
return frame->GetRenderedText(&aText, nsnull, nsnull, aStartOffset, aLength);
|
||||
}
|
||||
|
||||
void
|
||||
nsTextAccessible::CacheChildren()
|
||||
{
|
||||
// No children for text accessible.
|
||||
mAccChildCount = IsDefunct() ? eChildCountUninitialized : 0;
|
||||
}
|
||||
|
|
|
@ -41,27 +41,23 @@
|
|||
|
||||
#include "nsBaseWidgetAccessible.h"
|
||||
|
||||
/**
|
||||
* Text nodes have no children, but since double inheritance
|
||||
* no-worky we have to re-impl the LeafAccessiblity blocks
|
||||
* this way.
|
||||
*/
|
||||
/**
|
||||
* Generic class used for text nodes.
|
||||
*/
|
||||
class nsTextAccessible : public nsLinkableAccessible
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
nsTextAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetFirstChild(nsIAccessible **_retval);
|
||||
NS_IMETHOD GetLastChild(nsIAccessible **_retval);
|
||||
NS_IMETHOD GetChildCount(PRInt32 *_retval);
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetRoleInternal(PRUint32 *aRole);
|
||||
virtual nsresult AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
|
||||
PRUint32 aLength);
|
||||
|
||||
protected:
|
||||
|
||||
// nsAccessible
|
||||
virtual void CacheChildren();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -47,12 +47,13 @@
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLAreaAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsHTMLAreaAccessible::
|
||||
nsHTMLAreaAccessible(nsIDOMNode *aDomNode, nsIAccessible *aParent,
|
||||
nsIWeakReference* aShell):
|
||||
nsHTMLLinkAccessible(aDomNode, aShell)
|
||||
{
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -89,33 +90,6 @@ nsHTMLAreaAccessible::GetDescription(nsAString& aDescription)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLAreaAccessible::GetFirstChild(nsIAccessible **aChild)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aChild);
|
||||
|
||||
*aChild = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLAreaAccessible::GetLastChild(nsIAccessible **aChild)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aChild);
|
||||
|
||||
*aChild = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLAreaAccessible::GetChildCount(PRInt32 *aCount)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCount);
|
||||
|
||||
*aCount = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLAreaAccessible::GetBounds(PRInt32 *x, PRInt32 *y,
|
||||
PRInt32 *width, PRInt32 *height)
|
||||
|
@ -161,7 +135,9 @@ nsHTMLAreaAccessible::GetBounds(PRInt32 *x, PRInt32 *y,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsAccessible::GetChildAtPoint()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessible public implementation
|
||||
|
||||
nsresult
|
||||
nsHTMLAreaAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
|
||||
PRBool aDeepestChild,
|
||||
|
@ -171,3 +147,13 @@ nsHTMLAreaAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
|
|||
NS_ADDREF(*aChild = this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessible protected implementation
|
||||
|
||||
void
|
||||
nsHTMLAreaAccessible::CacheChildren()
|
||||
{
|
||||
// No children for aria accessible.
|
||||
mAccChildCount = IsDefunct() ? eChildCountUninitialized : 0;
|
||||
}
|
||||
|
|
|
@ -41,9 +41,9 @@
|
|||
|
||||
#include "nsHTMLLinkAccessible.h"
|
||||
|
||||
/* Accessible for image map areas - must be child of image
|
||||
/**
|
||||
* Accessible for image map areas - must be child of image.
|
||||
*/
|
||||
|
||||
class nsHTMLAreaAccessible : public nsHTMLLinkAccessible
|
||||
{
|
||||
|
||||
|
@ -54,10 +54,6 @@ public:
|
|||
// nsIAccessible
|
||||
NS_IMETHOD GetDescription(nsAString& aDescription);
|
||||
|
||||
NS_IMETHOD GetFirstChild(nsIAccessible **_retval);
|
||||
NS_IMETHOD GetLastChild(nsIAccessible **_retval);
|
||||
NS_IMETHOD GetChildCount(PRInt32 *_retval);
|
||||
|
||||
NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
|
||||
|
||||
// nsAccessible
|
||||
|
@ -65,6 +61,11 @@ public:
|
|||
virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
|
||||
PRBool aDeepestChild,
|
||||
nsIAccessible **aChild);
|
||||
|
||||
protected:
|
||||
|
||||
// nsAccessible
|
||||
virtual void CacheChildren();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -57,6 +57,8 @@ nsTextAccessibleWrap(aDomNode, aShell)
|
|||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLTextAccessible, nsTextAccessible)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLTextAccessible::GetName(nsAString& aName)
|
||||
{
|
||||
|
|
|
@ -50,7 +50,10 @@ class nsHTMLTextAccessible : public nsTextAccessibleWrap
|
|||
{
|
||||
public:
|
||||
nsHTMLTextAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
|
||||
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetName(nsAString& aName);
|
||||
|
||||
|
|
|
@ -44,6 +44,6 @@ NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLImageAccessibleWrap,
|
|||
nsHTMLImageAccessible)
|
||||
|
||||
IMPL_IUNKNOWN_INHERITED1(nsHTMLImageAccessibleWrap,
|
||||
nsHyperTextAccessibleWrap,
|
||||
nsAccessibleWrap,
|
||||
CAccessibleImage);
|
||||
|
||||
|
|
|
@ -41,11 +41,8 @@
|
|||
#define _nsXULTextAccessible_H_
|
||||
|
||||
#include "nsBaseWidgetAccessible.h"
|
||||
#include "nsTextAccessibleWrap.h"
|
||||
#include "nsHyperTextAccessibleWrap.h"
|
||||
|
||||
class nsIWeakReference;
|
||||
|
||||
class nsXULTextAccessible : public nsHyperTextAccessibleWrap
|
||||
{
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ GRE_BUILDID = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBX
|
|||
|
||||
DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) -DGRE_BUILDID=$(GRE_BUILDID)
|
||||
|
||||
SOURCE_STAMP := $(shell cd $(topsrcdir) ; hg identify 2>/dev/null | cut -f1 -d' ')
|
||||
SOURCE_STAMP := $(shell cd $(topsrcdir) ; hg identify . 2>/dev/null | cut -f1 -d' ')
|
||||
ifdef SOURCE_STAMP
|
||||
DEFINES += -DMOZ_SOURCE_STAMP="$(SOURCE_STAMP)"
|
||||
endif
|
||||
|
|
|
@ -134,6 +134,13 @@ td {
|
|||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
let gPrefService = Cc["@mozilla.org/preferences-service;1"]
|
||||
.getService(Ci.nsIPrefService)
|
||||
.QueryInterface(Ci.nsIPrefBranch2);
|
||||
|
||||
const ELLIPSIS = gPrefService.getComplexValue("intl.ellipsis",
|
||||
Ci.nsIPrefLocalizedString).data;
|
||||
|
||||
// We use a preferences whitelist to make sure we only show preferences that
|
||||
// are useful for support and won't compromise the user's privacy. Note that
|
||||
// entries are *prefixes*: for example, "accessibility." applies to all prefs
|
||||
|
@ -238,7 +245,7 @@ function formatPrefValue(prefValue) {
|
|||
let maxPrefValueLen = 120;
|
||||
let text = "" + prefValue;
|
||||
if (text.length > maxPrefValueLen)
|
||||
text = text.substring(0, maxPrefValueLen) + "…";
|
||||
text = text.substring(0, maxPrefValueLen) + ELLIPSIS;
|
||||
return text;
|
||||
}
|
||||
|
||||
|
@ -247,21 +254,18 @@ function getModifiedPrefs() {
|
|||
// modified, rather that Application.prefs.all since the latter is
|
||||
// much, much slower. Application.prefs.all also gets slower each
|
||||
// time it's called. See bug 517312.
|
||||
let prefService = Cc["@mozilla.org/preferences-service;1"]
|
||||
.getService(Ci.nsIPrefService);
|
||||
let prefRootBranch = prefService.getBranch("");
|
||||
let prefNames = getWhitelistedPrefNames(prefRootBranch);
|
||||
let prefNames = getWhitelistedPrefNames();
|
||||
let prefs = [Application.prefs.get(prefName)
|
||||
for each (prefName in prefNames)
|
||||
if (prefRootBranch.prefHasUserValue(prefName)
|
||||
if (gPrefService.prefHasUserValue(prefName)
|
||||
&& !isBlacklisted(prefName))];
|
||||
return prefs;
|
||||
}
|
||||
|
||||
function getWhitelistedPrefNames(prefRootBranch) {
|
||||
function getWhitelistedPrefNames() {
|
||||
let results = [];
|
||||
PREFS_WHITELIST.forEach(function (prefStem) {
|
||||
let prefNames = prefRootBranch.getChildList(prefStem, {});
|
||||
let prefNames = gPrefService.getChildList(prefStem);
|
||||
results = results.concat(prefNames);
|
||||
});
|
||||
return results;
|
||||
|
@ -333,7 +337,9 @@ function createTextForElement(elem) {
|
|||
text = text.replace(/\n\n\n+/g, "\n\n");
|
||||
|
||||
// Actual CR/LF pairs are needed for some Windows text editors.
|
||||
#ifdef XP_WIN
|
||||
text = text.replace(/\n/g, "\r\n");
|
||||
#endif
|
||||
|
||||
return text;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ toolbarpaletteitem[place="palette"] > toolbaritem > hbox[type="places"] {
|
|||
-moz-binding: url(chrome://browser/content/urlbarBindings.xml#urlbar);
|
||||
}
|
||||
|
||||
#wrapper-urlbar-container #urlbar {
|
||||
#wrapper-urlbar-container > #urlbar-container > #urlbar {
|
||||
-moz-user-input: disabled;
|
||||
cursor: -moz-grab;
|
||||
}
|
||||
|
@ -55,26 +55,30 @@ toolbarpaletteitem[place="palette"] > toolbaritem > hbox[type="places"] {
|
|||
display: none;
|
||||
}
|
||||
|
||||
#feed-menu:-moz-locale-dir(rtl) > menuitem {
|
||||
#feed-menu > .feed-menuitem:-moz-locale-dir(rtl) {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
#urlbar[pageproxystate="invalid"] > #urlbar-icons > :not(#go-button) ,
|
||||
#urlbar[pageproxystate="invalid"] > #urlbar-icons > .urlbar-icon:not(#go-button),
|
||||
#urlbar[pageproxystate="valid"] > #urlbar-icons > #go-button ,
|
||||
#urlbar[isempty="true"] > #urlbar-icons > #go-button {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
#identity-box > hbox {
|
||||
#identity-box-inner {
|
||||
max-width: 22em;
|
||||
min-width: 1px;
|
||||
}
|
||||
|
||||
#wrapper-search-container > #search-container > #searchbar > .searchbar-textbox > .autocomplete-textbox-container > .textbox-input-box > html|*.textbox-input {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/* ::::: Unified Back-/Forward Button ::::: */
|
||||
#back-button > dropmarker,
|
||||
#forward-button > dropmarker,
|
||||
#back-forward-dropmarker > image ,
|
||||
#back-forward-dropmarker > label {
|
||||
#back-button > .toolbarbutton-menu-dropmarker,
|
||||
#forward-button > .toolbarbutton-menu-dropmarker,
|
||||
#back-forward-dropmarker > .toolbarbutton-icon,
|
||||
#back-forward-dropmarker > .toolbarbutton-text {
|
||||
display: none;
|
||||
}
|
||||
.unified-nav-current {
|
||||
|
|
|
@ -1540,8 +1540,7 @@ function initializeSanitizer()
|
|||
*/
|
||||
if (!gPrefService.getBoolPref("privacy.sanitize.migrateFx3Prefs")) {
|
||||
let itemBranch = gPrefService.getBranch("privacy.item.");
|
||||
let itemCount = { value: 0 };
|
||||
let itemArray = itemBranch.getChildList("", itemCount);
|
||||
let itemArray = itemBranch.getChildList("");
|
||||
|
||||
// See if any privacy.item prefs are set
|
||||
let doMigrate = itemArray.some(function (name) itemBranch.prefHasUserValue(name));
|
||||
|
@ -6118,6 +6117,7 @@ var FeedHandler = {
|
|||
var menuItem = document.createElement("menuitem");
|
||||
var baseTitle = feedInfo.title || feedInfo.href;
|
||||
var labelStr = gNavigatorBundle.getFormattedString("feedShowFeedNew", [baseTitle]);
|
||||
menuItem.setAttribute("class", "feed-menuitem");
|
||||
menuItem.setAttribute("label", labelStr);
|
||||
menuItem.setAttribute("feed", feedInfo.href);
|
||||
menuItem.setAttribute("tooltiptext", feedInfo.href);
|
||||
|
|
|
@ -133,14 +133,17 @@
|
|||
<description id="editBookmarkPanelDescription"/>
|
||||
<hbox>
|
||||
<button id="editBookmarkPanelUndoRemoveButton"
|
||||
class="editBookmarkPanelHeaderButton"
|
||||
hidden="true"
|
||||
oncommand="StarUI.undoRemoveBookmarkCommand();"
|
||||
label="&editBookmark.undo.label;"
|
||||
accesskey="&editBookmark.undo.accessKey;"/>
|
||||
<button id="editBookmarkPanelRemoveButton"
|
||||
class="editBookmarkPanelHeaderButton"
|
||||
oncommand="StarUI.removeBookmarkButtonCommand();"
|
||||
accesskey="&editBookmark.removeBookmark.accessKey;"/>
|
||||
<button id="editBookmarkPanelEditButton"
|
||||
class="editBookmarkPanelHeaderButton"
|
||||
oncommand="StarUI.editButtonCommand();"
|
||||
label="&editBookmark.edit.label;"
|
||||
accesskey="&editBookmark.edit.accessKey;"/>
|
||||
|
@ -151,17 +154,21 @@
|
|||
<hbox id="editBookmarkPanelBottomButtons" pack="end">
|
||||
#ifndef XP_UNIX
|
||||
<button id="editBookmarkPanelDoneButton"
|
||||
class="editBookmarkPanelBottomButton"
|
||||
label="&editBookmark.done.label;"
|
||||
default="true"
|
||||
oncommand="StarUI.panel.hidePopup();"/>
|
||||
<button id="editBookmarkPanelDeleteButton"
|
||||
class="editBookmarkPanelBottomButton"
|
||||
label="&editBookmark.cancel.label;"
|
||||
oncommand="StarUI.cancelButtonOnCommand();"/>
|
||||
#else
|
||||
<button id="editBookmarkPanelDeleteButton"
|
||||
class="editBookmarkPanelBottomButton"
|
||||
label="&editBookmark.cancel.label;"
|
||||
oncommand="StarUI.cancelButtonOnCommand();"/>
|
||||
<button id="editBookmarkPanelDoneButton"
|
||||
class="editBookmarkPanelBottomButton"
|
||||
label="&editBookmark.done.label;"
|
||||
default="true"
|
||||
oncommand="StarUI.panel.hidePopup();"/>
|
||||
|
@ -211,25 +218,32 @@
|
|||
<hbox id="identity-popup-container" align="top">
|
||||
<image id="identity-popup-icon"/>
|
||||
<vbox id="identity-popup-content-box">
|
||||
<label id="identity-popup-connectedToLabel" value="&identity.connectedTo;"/>
|
||||
<label id="identity-popup-connectedToLabel"
|
||||
class="identity-popup-label"
|
||||
value="&identity.connectedTo;"/>
|
||||
<label id="identity-popup-connectedToLabel2"
|
||||
class="identity-popup-label"
|
||||
value="&identity.unverifiedsite2;"/>
|
||||
<description id="identity-popup-content-host"/>
|
||||
<label id="identity-popup-runByLabel" value="&identity.runBy;"/>
|
||||
<description id="identity-popup-content-owner"/>
|
||||
<description id="identity-popup-content-supplemental"/>
|
||||
<description id="identity-popup-content-verifier"/>
|
||||
<description id="identity-popup-content-host"
|
||||
class="identity-popup-description"/>
|
||||
<label id="identity-popup-runByLabel"
|
||||
class="identity-popup-label"
|
||||
value="&identity.runBy;"/>
|
||||
<description id="identity-popup-content-owner"
|
||||
class="identity-popup-description"/>
|
||||
<description id="identity-popup-content-supplemental"
|
||||
class="identity-popup-description"/>
|
||||
<description id="identity-popup-content-verifier"
|
||||
class="identity-popup-description"/>
|
||||
<hbox id="identity-popup-encryption" flex="1">
|
||||
<vbox>
|
||||
<image id="identity-popup-encryption-icon"/>
|
||||
<spacer flex="1"/>
|
||||
</vbox>
|
||||
<description id="identity-popup-encryption-label" flex="1"/>
|
||||
<description id="identity-popup-encryption-label" flex="1"
|
||||
class="identity-popup-description"/>
|
||||
</hbox>
|
||||
<spacer flex="1"/>
|
||||
<!-- Footer button to open security page info -->
|
||||
<hbox>
|
||||
<spacer flex="1"/>
|
||||
<hbox pack="end">
|
||||
<button id="identity-popup-more-info-button"
|
||||
label="&identity.moreInfoLinkText;"
|
||||
onblur="gIdentityHandler.hideIdentityPopup();"
|
||||
|
@ -392,7 +406,7 @@
|
|||
<box id="identity-box" role="button"
|
||||
onclick="gIdentityHandler.handleIdentityButtonEvent(event);"
|
||||
onkeypress="gIdentityHandler.handleIdentityButtonEvent(event);">
|
||||
<hbox align="center">
|
||||
<hbox id="identity-box-inner" align="center">
|
||||
<stack id="page-proxy-stack"
|
||||
onclick="PageProxyClickHandler(event);">
|
||||
<image id="urlbar-throbber" busy="false"/>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
#viewGroup radio {
|
||||
#viewGroup > radio {
|
||||
-moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#viewbutton");
|
||||
}
|
||||
|
||||
|
|
|
@ -314,8 +314,9 @@
|
|||
</hbox>
|
||||
|
||||
<vbox id="permList" flex="1">
|
||||
<vbox>
|
||||
<label id="permImageLabel" value="&permImage;" control="imageRadioGroup"/>
|
||||
<vbox class="permission">
|
||||
<label class="permissionLabel" id="permImageLabel"
|
||||
value="&permImage;" control="imageRadioGroup"/>
|
||||
<hbox role="group" aria-labelledby="permImageLabel">
|
||||
<checkbox id="imageDef" command="cmd_imageDef" label="&permUseDefault;"/>
|
||||
<spacer flex="1"/>
|
||||
|
@ -325,8 +326,9 @@
|
|||
</radiogroup>
|
||||
</hbox>
|
||||
</vbox>
|
||||
<vbox>
|
||||
<label id="permPopupLabel" value="&permPopup;" control="popupRadioGroup"/>
|
||||
<vbox class="permission">
|
||||
<label class="permissionLabel" id="permPopupLabel"
|
||||
value="&permPopup;" control="popupRadioGroup"/>
|
||||
<hbox role="group" aria-labelledby="permPopupLabel">
|
||||
<checkbox id="popupDef" command="cmd_popupDef" label="&permUseDefault;"/>
|
||||
<spacer flex="1"/>
|
||||
|
@ -336,8 +338,9 @@
|
|||
</radiogroup>
|
||||
</hbox>
|
||||
</vbox>
|
||||
<vbox>
|
||||
<label id="permCookieLabel" value="&permCookie;" control="cookieRadioGroup"/>
|
||||
<vbox class="permission">
|
||||
<label class="permissionLabel" id="permCookieLabel"
|
||||
value="&permCookie;" control="cookieRadioGroup"/>
|
||||
<hbox role="group" aria-labelledby="permCookieLabel">
|
||||
<checkbox id="cookieDef" command="cmd_cookieDef" label="&permUseDefault;"/>
|
||||
<spacer flex="1"/>
|
||||
|
@ -348,8 +351,9 @@
|
|||
</radiogroup>
|
||||
</hbox>
|
||||
</vbox>
|
||||
<vbox>
|
||||
<label id="permInstallLabel" value="&permInstall;" control="installRadioGroup"/>
|
||||
<vbox class="permission">
|
||||
<label class="permissionLabel" id="permInstallLabel"
|
||||
value="&permInstall;" control="installRadioGroup"/>
|
||||
<hbox role="group" aria-labelledby="permInstallLabel">
|
||||
<checkbox id="installDef" command="cmd_installDef" label="&permUseDefault;"/>
|
||||
<spacer flex="1"/>
|
||||
|
@ -359,9 +363,9 @@
|
|||
</radiogroup>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<vbox>
|
||||
<label id="permGeoLabel" value="&permGeo;" control="geoRadioGroup"/>
|
||||
<vbox class="permission">
|
||||
<label class="permissionLabel" id="permGeoLabel"
|
||||
value="&permGeo;" control="geoRadioGroup"/>
|
||||
<hbox role="group" aria-labelledby="permGeoLabel">
|
||||
<checkbox id="geoDef" command="cmd_geoDef" label="&permAskAlways;"/>
|
||||
<spacer flex="1"/>
|
||||
|
|
|
@ -806,7 +806,7 @@ WebContentConverterRegistrar.prototype = {
|
|||
* branch and stop cycling once that's true. This doesn't fix the case
|
||||
* where a user manually removes a reader, but that's not supported yet!
|
||||
*/
|
||||
var vals = branch.getChildList("", {});
|
||||
var vals = branch.getChildList("");
|
||||
if (vals.length == 0)
|
||||
return;
|
||||
|
||||
|
@ -832,7 +832,7 @@ WebContentConverterRegistrar.prototype = {
|
|||
getService(Ci.nsIPrefService);
|
||||
|
||||
var kids = ps.getBranch(PREF_CONTENTHANDLERS_BRANCH)
|
||||
.getChildList("", {});
|
||||
.getChildList("");
|
||||
|
||||
// first get the numbers of the providers by getting all ###.uri prefs
|
||||
var nums = [];
|
||||
|
@ -857,7 +857,7 @@ WebContentConverterRegistrar.prototype = {
|
|||
// so that getWebContentHandlerByURI can return successfully.
|
||||
try {
|
||||
var autoBranch = ps.getBranch(PREF_CONTENTHANDLERS_AUTO);
|
||||
var childPrefs = autoBranch.getChildList("", { });
|
||||
var childPrefs = autoBranch.getChildList("");
|
||||
for (var i = 0; i < childPrefs.length; ++i) {
|
||||
var type = childPrefs[i];
|
||||
var uri = autoBranch.getCharPref(type);
|
||||
|
|
|
@ -64,8 +64,9 @@
|
|||
<!-- Bookmarks and history tooltip -->
|
||||
<tooltip id="bhTooltip"/>
|
||||
|
||||
<hbox align="center">
|
||||
<label value="&search.label;" accesskey="&search.accesskey;" control="search-box"/>
|
||||
<hbox id="sidebar-search-container" align="center">
|
||||
<label id="sidebar-search-label"
|
||||
value="&search.label;" accesskey="&search.accesskey;" control="search-box"/>
|
||||
<textbox id="search-box" flex="1" type="search" class="compact"
|
||||
aria-controls="bookmarks-view"
|
||||
oncommand="searchBookmarks(this.value);"/>
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
<rows id="editBMPanel_rows">
|
||||
<row align="center" id="editBMPanel_nameRow">
|
||||
<label value="&editBookmarkOverlay.name.label;"
|
||||
class="editBMPanel_rowLabel"
|
||||
accesskey="&editBookmarkOverlay.name.accesskey;"
|
||||
control="editBMPanel_namePicker"
|
||||
observes="paneElementsBroadcaster"/>
|
||||
|
@ -84,6 +85,7 @@
|
|||
|
||||
<row align="center" id="editBMPanel_locationRow">
|
||||
<label value="&editBookmarkOverlay.location.label;"
|
||||
class="editBMPanel_rowLabel"
|
||||
accesskey="&editBookmarkOverlay.location.accesskey;"
|
||||
control="editBMPanel_locationField"
|
||||
observes="paneElementsBroadcaster"/>
|
||||
|
@ -95,6 +97,7 @@
|
|||
|
||||
<row align="center" id="editBMPanel_feedLocationRow">
|
||||
<label value="&editBookmarkOverlay.feedLocation.label;"
|
||||
class="editBMPanel_rowLabel"
|
||||
accesskey="&editBookmarkOverlay.feedLocation.accesskey;"
|
||||
control="editBMPanel_feedLocationField"
|
||||
observes="paneElementsBroadcaster"/>
|
||||
|
@ -106,6 +109,7 @@
|
|||
|
||||
<row align="center" id="editBMPanel_siteLocationRow">
|
||||
<label value="&editBookmarkOverlay.siteLocation.label;"
|
||||
class="editBMPanel_rowLabel"
|
||||
accesskey="&editBookmarkOverlay.siteLocation.accesskey;"
|
||||
control="editBMPanel_siteLocationField"
|
||||
observes="paneElementsBroadcaster"/>
|
||||
|
@ -117,6 +121,7 @@
|
|||
|
||||
<row align="center" id="editBMPanel_folderRow">
|
||||
<label value="&editBookmarkOverlay.folder.label;"
|
||||
class="editBMPanel_rowLabel"
|
||||
control="editBMPanel_folderMenuList"
|
||||
observes="paneElementsBroadcaster"/>
|
||||
<hbox flex="1" align="center">
|
||||
|
@ -178,6 +183,7 @@
|
|||
|
||||
<row align="center" id="editBMPanel_tagsRow">
|
||||
<label value="&editBookmarkOverlay.tags.label;"
|
||||
class="editBMPanel_rowLabel"
|
||||
accesskey="&editBookmarkOverlay.tags.accesskey;"
|
||||
control="editBMPanel_tagsField"
|
||||
observes="paneElementsBroadcaster"/>
|
||||
|
@ -215,6 +221,7 @@
|
|||
<row align="center" id="editBMPanel_keywordRow">
|
||||
<observes element="additionalInfoBroadcaster" attribute="hidden"/>
|
||||
<label value="&editBookmarkOverlay.keyword.label;"
|
||||
class="editBMPanel_rowLabel"
|
||||
accesskey="&editBookmarkOverlay.keyword.accesskey;"
|
||||
control="editBMPanel_keywordField"
|
||||
observes="paneElementsBroadcaster"/>
|
||||
|
@ -226,6 +233,7 @@
|
|||
<row id="editBMPanel_descriptionRow">
|
||||
<observes element="additionalInfoBroadcaster" attribute="hidden"/>
|
||||
<label value="&editBookmarkOverlay.description.label;"
|
||||
class="editBMPanel_rowLabel"
|
||||
accesskey="&editBookmarkOverlay.description.accesskey;"
|
||||
control="editBMPanel_descriptionField"
|
||||
observes="paneElementsBroadcaster"/>
|
||||
|
|
|
@ -80,8 +80,9 @@
|
|||
<!-- Bookmarks and history tooltip -->
|
||||
<tooltip id="bhTooltip"/>
|
||||
|
||||
<hbox align="center">
|
||||
<label value="&find.label;" accesskey="&find.accesskey;"
|
||||
<hbox id="sidebar-search-container" align="center">
|
||||
<label id="sidebar-search-label"
|
||||
value="&find.label;" accesskey="&find.accesskey;"
|
||||
control="search-box"/>
|
||||
<textbox id="search-box" flex="1" type="search" class="compact"
|
||||
aria-controls="historyTree"
|
||||
|
|
|
@ -1555,7 +1555,7 @@ SessionStoreService.prototype = {
|
|||
if (node.type != "file")
|
||||
data[id] = node.type == "checkbox" || node.type == "radio" ? node.checked : node.value;
|
||||
else
|
||||
data[id] = { type: "file", value: node.value };
|
||||
data[id] = { type: "file", fileList: node.mozGetFileNameArray() };
|
||||
}
|
||||
else if (node instanceof Ci.nsIDOMHTMLTextAreaElement)
|
||||
data[id] = node.value;
|
||||
|
@ -2286,8 +2286,8 @@ SessionStoreService.prototype = {
|
|||
try {
|
||||
node.selectedIndex = value;
|
||||
} catch (ex) { /* throws for invalid indices */ }
|
||||
else if (value && value.type && value.type == node.type)
|
||||
node.value = value.value;
|
||||
else if (value && value.fileList && value.type == "file" && node.type == "file")
|
||||
node.mozSetFileNameArray(value.fileList, value.fileList.length);
|
||||
else if (value && typeof value.indexOf == "function" && node.options) {
|
||||
Array.forEach(node.options, function(aOpt, aIx) {
|
||||
aOpt.selected = value.indexOf(aIx) > -1;
|
||||
|
|
|
@ -51,7 +51,8 @@ function test() {
|
|||
"//textarea[1]": "",
|
||||
"//textarea[2]": "Some text... " + Math.random(),
|
||||
"//textarea[3]": "Some more text\n" + new Date(),
|
||||
"//input[@type='file']": "/dev/null"
|
||||
"//input[@type='file'][1]": ["/dev/null"],
|
||||
"//input[@type='file'][2]": ["/dev/null", "/dev/stdin"]
|
||||
};
|
||||
|
||||
function getElementByXPath(aTab, aQuery) {
|
||||
|
@ -68,6 +69,8 @@ function test() {
|
|||
node.checked = aValue;
|
||||
else if (typeof aValue == "number")
|
||||
node.selectedIndex = aValue;
|
||||
else if (node instanceof Ci.nsIDOMHTMLInputElement && node.type == "file")
|
||||
node.mozSetFileNameArray(aValue, aValue.length);
|
||||
else
|
||||
Array.forEach(node.options, function(aOpt, aIx)
|
||||
(aOpt.selected = aValue.indexOf(aIx) > -1));
|
||||
|
@ -77,9 +80,15 @@ function test() {
|
|||
let node = getElementByXPath(aTab, aQuery);
|
||||
if (!node)
|
||||
return false;
|
||||
if (node instanceof Ci.nsIDOMHTMLInputElement)
|
||||
if (node instanceof Ci.nsIDOMHTMLInputElement) {
|
||||
if (node.type == "file") {
|
||||
let fileNames = node.mozGetFileNameArray();
|
||||
return fileNames.length == aValue.length &&
|
||||
Array.every(fileNames, function(aFile) aValue.indexOf(aFile) >= 0);
|
||||
}
|
||||
return aValue == (node.type == "checkbox" || node.type == "radio" ?
|
||||
node.checked : node.value);
|
||||
}
|
||||
if (node instanceof Ci.nsIDOMHTMLTextAreaElement)
|
||||
return aValue == node.value;
|
||||
if (!node.multiple)
|
||||
|
|
|
@ -34,3 +34,4 @@
|
|||
|
||||
<h3>File Selector</h3>
|
||||
<input type="file">
|
||||
<input type="file" multiple>
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
|
||||
[browser]
|
||||
; [Base Browser Files]
|
||||
#ifdef XP_WIN32
|
||||
#ifndef XP_UNIX
|
||||
@BINPATH@/@MOZ_APP_NAME@.exe
|
||||
#else
|
||||
@BINPATH@/@MOZ_APP_NAME@-bin
|
||||
|
@ -87,6 +87,8 @@
|
|||
#ifndef WINCE
|
||||
@BINPATH@/plugins/npnul32.dll
|
||||
#endif
|
||||
#elifdef XP_OS2
|
||||
@BINPATH@/plugins/npnulos2.dll
|
||||
#endif
|
||||
@BINPATH@/@DLL_PREFIX@sqlite3@DLL_SUFFIX@
|
||||
@BINPATH@/README.txt
|
||||
|
@ -298,8 +300,13 @@
|
|||
@BINPATH@/components/nsSessionStartup.js
|
||||
@BINPATH@/components/nsSessionStore.js
|
||||
@BINPATH@/components/nsURLFormatter.js
|
||||
#ifndef XP_OS2
|
||||
@BINPATH@/components/@DLL_PREFIX@browserdirprovider@DLL_SUFFIX@
|
||||
@BINPATH@/components/@DLL_PREFIX@browsercomps@DLL_SUFFIX@
|
||||
#else
|
||||
@BINPATH@/components/brwsrdir@DLL_SUFFIX@
|
||||
@BINPATH@/components/brwsrcmp@DLL_SUFFIX@
|
||||
#endif
|
||||
@BINPATH@/components/txEXSLTRegExFunctions.js
|
||||
@BINPATH@/components/nsLivemarkService.js
|
||||
@BINPATH@/components/nsTaggingService.js
|
||||
|
@ -352,7 +359,7 @@
|
|||
|
||||
|
||||
; shell icons
|
||||
#ifndef XP_WIN32
|
||||
#ifdef XP_UNIX
|
||||
@BINPATH@/icons/*.xpm
|
||||
@BINPATH@/icons/*.png
|
||||
#endif
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
-moz-box-orient: vertical; /* for flex hack */
|
||||
}
|
||||
|
||||
#menubar-items > menubar {
|
||||
#main-menubar {
|
||||
-moz-box-flex: 1; /* make menu items expand to fill toolbar height */
|
||||
}
|
||||
|
||||
|
@ -60,10 +60,6 @@
|
|||
min-height: 29px;
|
||||
}
|
||||
|
||||
#wrapper-search-container #searchbar html|*.textbox-input {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#navigator-toolbox[inFullscreen="true"],
|
||||
#navigator-toolbox[inFullscreen="true"] > #nav-bar {
|
||||
border-top: none;
|
||||
|
@ -71,7 +67,7 @@
|
|||
}
|
||||
|
||||
#urlbar:-moz-lwtheme:not([focused="true"]),
|
||||
#searchbar:-moz-lwtheme > textbox:not([focused="true"]),
|
||||
.searchbar-textbox:-moz-lwtheme:not([focused="true"]),
|
||||
.tabbrowser-tab:-moz-lwtheme:not([selected="true"]) {
|
||||
opacity: .85;
|
||||
}
|
||||
|
@ -856,12 +852,12 @@ toolbar[iconsize="small"] #fullscreen-button {
|
|||
outline: 1px dotted -moz-DialogText;
|
||||
}
|
||||
|
||||
#identity-box:hover > hbox {
|
||||
#identity-box:hover > #identity-box-inner {
|
||||
background-color: rgba(255, 255, 255, .2);
|
||||
}
|
||||
|
||||
#identity-box:hover:active > hbox,
|
||||
#identity-box[open="true"] > hbox {
|
||||
#identity-box:hover:active > #identity-box-inner,
|
||||
#identity-box[open="true"] > #identity-box-inner {
|
||||
background-color: rgba(0, 0, 0, .1);
|
||||
}
|
||||
|
||||
|
@ -902,14 +898,13 @@ toolbar[iconsize="small"] #fullscreen-button {
|
|||
}
|
||||
|
||||
/* Identity popup body text */
|
||||
#identity-popup-content-box > description,
|
||||
#identity-popup-encryption-label {
|
||||
.identity-popup-description {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 2px 0 4px;
|
||||
}
|
||||
|
||||
#identity-popup-content-box > label {
|
||||
.identity-popup-label {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 0;
|
||||
|
@ -947,7 +942,6 @@ toolbar[iconsize="small"] #fullscreen-button {
|
|||
|
||||
/* Identity popup bounding box */
|
||||
#identity-popup-container {
|
||||
background-image: none;
|
||||
min-width: 280px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
@import url("chrome://global/skin/");
|
||||
|
||||
/* View buttons */
|
||||
#viewGroup radio {
|
||||
#viewGroup > radio {
|
||||
list-style-image: url("chrome://browser/skin/pageInfo.png");
|
||||
-moz-box-orient: vertical;
|
||||
-moz-box-align: center;
|
||||
|
@ -53,7 +53,7 @@
|
|||
color: -moz-FieldText;
|
||||
}
|
||||
|
||||
#viewGroup radio[selected="true"] {
|
||||
#viewGroup > radio[selected="true"] {
|
||||
background-color: Highlight;
|
||||
color: HighlightText;
|
||||
}
|
||||
|
@ -255,7 +255,7 @@ treechildren::-moz-tree-cell-text(broken) {
|
|||
color: -moz-FieldText;
|
||||
}
|
||||
|
||||
#permList > vbox {
|
||||
.permission {
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
-moz-padding-start: 7px;
|
||||
|
@ -264,11 +264,11 @@ treechildren::-moz-tree-cell-text(broken) {
|
|||
border-bottom: 1px dotted #C0C0C0;
|
||||
}
|
||||
|
||||
#permList > vbox > label {
|
||||
.permissionLabel {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#permList > vbox:hover {
|
||||
.permission:hover {
|
||||
background-color: -moz-dialog;
|
||||
color: -moz-DialogText;
|
||||
}
|
||||
|
|
|
@ -47,11 +47,11 @@
|
|||
@namespace html url("http://www.w3.org/1999/xhtml");
|
||||
|
||||
#urlbar:-moz-lwtheme:not([focused="true"]),
|
||||
#searchbar:-moz-lwtheme > textbox:not([focused="true"]) {
|
||||
.searchbar-textbox:-moz-lwtheme:not([focused="true"]) {
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
#navigator-toolbox:-moz-lwtheme toolbarbutton {
|
||||
#navigator-toolbox toolbarbutton:-moz-lwtheme {
|
||||
color: inherit !important;
|
||||
text-shadow: inherit;
|
||||
}
|
||||
|
@ -70,10 +70,10 @@
|
|||
background: none !important;
|
||||
}
|
||||
|
||||
.tabbrowser-tab[selected="true"]:-moz-lwtheme {
|
||||
.tabbrowser-tab:-moz-lwtheme[selected="true"] {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
.tabbrowser-tab:not([selected="true"]):-moz-lwtheme:not(:hover) > .tab-text {
|
||||
.tabbrowser-tab:-moz-lwtheme:not([selected="true"]):not(:hover) > .tab-text {
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@
|
|||
-moz-border-right-colors: rgba(255,255,255,.1) rgba(255,255,255,.6) rgba(255,255,255,.2);
|
||||
}
|
||||
|
||||
.tabbrowser-tab[selected="true"]:-moz-lwtheme-brighttext {
|
||||
.tabbrowser-tab:-moz-lwtheme-brighttext[selected="true"] {
|
||||
-moz-border-left-colors: rgba(255,255,255,.6) rgba(255,255,255,.2);
|
||||
-moz-border-bottom-colors: rgba(255,255,255,.6) rgba(255,255,255,.2);
|
||||
-moz-border-right-colors: rgba(255,255,255,.6) rgba(255,255,255,.2);
|
||||
|
@ -159,12 +159,6 @@
|
|||
background-color: -moz-mac-chrome-inactive;
|
||||
}
|
||||
|
||||
/* ----- SEARCH FIELD ----- */
|
||||
|
||||
#wrapper-search-container #searchbar html|*.textbox-input {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/* ----- BOOKMARK TOOLBAR ----- */
|
||||
|
||||
#PersonalToolbar {
|
||||
|
@ -817,7 +811,7 @@ toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarke
|
|||
-moz-margin-start: 0;
|
||||
}
|
||||
|
||||
#wrapper-urlbar-container #urlbar,
|
||||
#wrapper-urlbar-container > #urlbar-container > #urlbar,
|
||||
#urlbar[readonly="true"] {
|
||||
-moz-padding-end: 12px;
|
||||
}
|
||||
|
@ -826,16 +820,10 @@ toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarke
|
|||
max-width: 20em;
|
||||
}
|
||||
|
||||
#wrapper-urlbar-container > #urlbar-container > #urlbar > #identity-box > hbox > #identity-icon-label,
|
||||
#wrapper-urlbar-container #urlbar > .autocomplete-history-dropmarker {
|
||||
#wrapper-urlbar-container > #urlbar-container > #urlbar > .autocomplete-history-dropmarker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#wrapper-urlbar-container > #urlbar-container > #urlbar > #identity-box.verifiedIdentity > hbox > #identity-icon-label,
|
||||
#wrapper-urlbar-container > #urlbar-container > #urlbar > #identity-box.verifiedDomain > hbox > #identity-icon-label {
|
||||
display: -moz-box;
|
||||
}
|
||||
|
||||
/* Keep the URL bar LTR */
|
||||
|
||||
#PopupAutoCompleteRichResult {
|
||||
|
@ -1019,15 +1007,15 @@ richlistitem[selected="true"][current="true"] > hbox > .ac-result-type-bookmark,
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
#editBookmarkPanel > hbox,
|
||||
#editBookmarkPanel > vbox {
|
||||
#editBookmarkPanelContent,
|
||||
#editBookmarkPanelBottomButtons {
|
||||
margin-right: -30px;
|
||||
}
|
||||
|
||||
/**** HUD style buttons ****/
|
||||
|
||||
#editBookmarkPanelHeader > vbox > hbox > button,
|
||||
#editBookmarkPanelBottomButtons > button {
|
||||
.editBookmarkPanelHeaderButton,
|
||||
.editBookmarkPanelBottomButton {
|
||||
-moz-appearance: none;
|
||||
background: url("chrome://browser/skin/hud-style-button-middle-background.png") repeat-x #464646 center center;
|
||||
border-width: 3px;
|
||||
|
@ -1044,19 +1032,19 @@ richlistitem[selected="true"][current="true"] > hbox > .ac-result-type-bookmark,
|
|||
color: #ffffff;
|
||||
}
|
||||
|
||||
#editBookmarkPanelHeader > vbox > hbox > button:hover:active,
|
||||
#editBookmarkPanelBottomButtons > button:hover:active {
|
||||
.editBookmarkPanelHeaderButton:hover:active,
|
||||
.editBookmarkPanelBottomButton:hover:active {
|
||||
background-color: #86888B;
|
||||
}
|
||||
|
||||
#editBookmarkPanelHeader > vbox > hbox > button:focus,
|
||||
#editBookmarkPanelBottomButtons > button:focus {
|
||||
.editBookmarkPanelHeaderButton:focus,
|
||||
.editBookmarkPanelBottomButton:focus {
|
||||
outline: 2px solid -moz-mac-focusring;
|
||||
outline-offset: -2px;
|
||||
-moz-outline-radius: 100%;
|
||||
}
|
||||
|
||||
#editBookmarkPanelBottomButtons > button[default="true"] {
|
||||
.editBookmarkPanelBottomButton[default="true"] {
|
||||
background-color: #666;
|
||||
}
|
||||
|
||||
|
@ -1333,7 +1321,7 @@ richlistitem[selected="true"][current="true"] > hbox > .ac-result-type-bookmark,
|
|||
color: #fff !important;
|
||||
}
|
||||
|
||||
#editBookmarkPanelGrid > rows > row > label {
|
||||
.editBMPanel_rowLabel {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
|
@ -1571,7 +1559,7 @@ tabbrowser > tabbox {
|
|||
}
|
||||
|
||||
.tabbrowser-tab:-moz-lwtheme,
|
||||
#main-window:-moz-lwtheme:not([active="true"]) .tabbrowser-tab {
|
||||
#main-window:not([active="true"]) .tabbrowser-tab:-moz-lwtheme {
|
||||
color: inherit;
|
||||
text-shadow: inherit;
|
||||
}
|
||||
|
@ -1842,7 +1830,7 @@ tabpanels.plain {
|
|||
background-image: url("chrome://browser/skin/urlbar/startcap-focused-graphite.png");
|
||||
}
|
||||
|
||||
#identity-box:focus > hbox > #page-proxy-deck {
|
||||
#identity-box:focus > #identity-box-inner > #page-proxy-deck {
|
||||
outline: 2px solid #4F8EC9;
|
||||
-moz-outline-radius: 2px;
|
||||
}
|
||||
|
@ -1859,7 +1847,7 @@ tabpanels.plain {
|
|||
-moz-padding-end: 14px;
|
||||
}
|
||||
|
||||
#identity-box.unknownIdentity > hbox > #identity-icon-label {
|
||||
#identity-box.unknownIdentity > #identity-box-inner > #identity-icon-label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -1871,13 +1859,13 @@ tabpanels.plain {
|
|||
-moz-padding-start: 13px;
|
||||
}
|
||||
|
||||
#identity-box.verifiedDomain > hbox {
|
||||
#identity-box.verifiedDomain > #identity-box-inner {
|
||||
padding: 0;
|
||||
background: url("chrome://browser/skin/urlbar/startcap-secure-mid.png") repeat-x center center;
|
||||
-moz-box-pack: center;
|
||||
}
|
||||
|
||||
#identity-box.verifiedDomain > hbox > #identity-icon-label {
|
||||
#identity-box.verifiedDomain > #identity-box-inner > #identity-icon-label {
|
||||
background: url("chrome://browser/skin/urlbar/startcap-secure-end.png") no-repeat center right;
|
||||
}
|
||||
|
||||
|
@ -1887,15 +1875,15 @@ tabpanels.plain {
|
|||
background-image: url("chrome://browser/skin/urlbar/startcap-secure-start-active.png");
|
||||
}
|
||||
|
||||
#identity-box.verifiedDomain[open="true"] > hbox,
|
||||
#identity-box.verifiedDomain:hover:active > hbox {
|
||||
#identity-box.verifiedDomain[open="true"] > #identity-box-inner,
|
||||
#identity-box.verifiedDomain:hover:active > #identity-box-inner {
|
||||
padding: 0;
|
||||
background: url("chrome://browser/skin/urlbar/startcap-secure-mid-active.png") repeat-x center center;
|
||||
-moz-box-pack: center;
|
||||
}
|
||||
|
||||
#identity-box.verifiedDomain[open="true"] > hbox > #identity-icon-label,
|
||||
#identity-box.verifiedDomain:hover:active > hbox > #identity-icon-label {
|
||||
#identity-box.verifiedDomain[open="true"] > #identity-box-inner > #identity-icon-label,
|
||||
#identity-box.verifiedDomain:hover:active > #identity-box-inner > #identity-icon-label {
|
||||
background: url("chrome://browser/skin/urlbar/startcap-secure-end-active.png") no-repeat center right;
|
||||
}
|
||||
|
||||
|
@ -1904,11 +1892,11 @@ tabpanels.plain {
|
|||
background-image: url("chrome://browser/skin/urlbar/startcap-secure-start-focused.png");
|
||||
}
|
||||
|
||||
#urlbar[focused="true"] > #identity-box.verifiedDomain > hbox {
|
||||
#urlbar[focused="true"] > #identity-box.verifiedDomain > #identity-box-inner {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-secure-mid-focused.png");
|
||||
}
|
||||
|
||||
#urlbar[focused="true"] > #identity-box.verifiedDomain > hbox > #identity-icon-label {
|
||||
#urlbar[focused="true"] > #identity-box.verifiedDomain > #identity-box-inner > #identity-icon-label {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-secure-end-focused.png");
|
||||
}
|
||||
|
||||
|
@ -1916,15 +1904,15 @@ tabpanels.plain {
|
|||
background-image: url("chrome://browser/skin/urlbar/startcap-secure-start-focused-graphite.png");
|
||||
}
|
||||
|
||||
#urlbar[focused="true"] > #identity-box.verifiedDomain > hbox:-moz-system-metric(mac-graphite-theme) {
|
||||
#urlbar[focused="true"] > #identity-box.verifiedDomain > #identity-box-inner:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-secure-mid-focused-graphite.png");
|
||||
}
|
||||
|
||||
#urlbar[focused="true"] > #identity-box.verifiedDomain > hbox > #identity-icon-label:-moz-system-metric(mac-graphite-theme) {
|
||||
#urlbar[focused="true"] > #identity-box.verifiedDomain > #identity-box-inner > #identity-icon-label:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-secure-end-focused-graphite.png");
|
||||
}
|
||||
|
||||
#identity-box.verifiedDomain > hbox > #identity-icon-label[value=""] {
|
||||
#identity-box.verifiedDomain > #identity-box-inner > #identity-icon-label[value=""] {
|
||||
-moz-padding-start: 3px !important;
|
||||
-moz-padding-end: 8px !important;
|
||||
}
|
||||
|
@ -1937,13 +1925,13 @@ tabpanels.plain {
|
|||
-moz-padding-start: 13px;
|
||||
}
|
||||
|
||||
#identity-box.verifiedIdentity > hbox {
|
||||
#identity-box.verifiedIdentity > #identity-box-inner {
|
||||
padding: 0;
|
||||
background: url("chrome://browser/skin/urlbar/startcap-verified-mid.png") repeat-x center center;
|
||||
-moz-box-pack: center;
|
||||
}
|
||||
|
||||
#identity-box.verifiedIdentity > hbox > #identity-icon-label {
|
||||
#identity-box.verifiedIdentity > #identity-box-inner > #identity-icon-label {
|
||||
background: url("chrome://browser/skin/urlbar/startcap-verified-end.png") no-repeat center right;
|
||||
}
|
||||
|
||||
|
@ -1953,13 +1941,13 @@ tabpanels.plain {
|
|||
background-image: url("chrome://browser/skin/urlbar/startcap-verified-start-active.png");
|
||||
}
|
||||
|
||||
#identity-box.verifiedIdentity[open="true"] > hbox,
|
||||
#identity-box.verifiedIdentity:hover:active > hbox {
|
||||
#identity-box.verifiedIdentity[open="true"] > #identity-box-inner,
|
||||
#identity-box.verifiedIdentity:hover:active > #identity-box-inner {
|
||||
background: url("chrome://browser/skin/urlbar/startcap-verified-mid-active.png") repeat-x center center;
|
||||
}
|
||||
|
||||
#identity-box.verifiedIdentity[open="true"] > hbox > #identity-icon-label,
|
||||
#identity-box.verifiedIdentity:hover:active > hbox > #identity-icon-label {
|
||||
#identity-box.verifiedIdentity[open="true"] > #identity-box-inner > #identity-icon-label,
|
||||
#identity-box.verifiedIdentity:hover:active > #identity-box-inner > #identity-icon-label {
|
||||
background: url("chrome://browser/skin/urlbar/startcap-verified-end-active.png") no-repeat center right;
|
||||
}
|
||||
|
||||
|
@ -1968,11 +1956,11 @@ tabpanels.plain {
|
|||
background-image: url("chrome://browser/skin/urlbar/startcap-verified-start-focused.png");
|
||||
}
|
||||
|
||||
#urlbar[focused="true"] > #identity-box.verifiedIdentity > hbox {
|
||||
#urlbar[focused="true"] > #identity-box.verifiedIdentity > #identity-box-inner {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-verified-mid-focused.png");
|
||||
}
|
||||
|
||||
#urlbar[focused="true"] > #identity-box.verifiedIdentity > hbox > #identity-icon-label {
|
||||
#urlbar[focused="true"] > #identity-box.verifiedIdentity > #identity-box-inner > #identity-icon-label {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-verified-end-focused.png");
|
||||
}
|
||||
|
||||
|
@ -1980,17 +1968,17 @@ tabpanels.plain {
|
|||
background-image: url("chrome://browser/skin/urlbar/startcap-verified-start-focused-graphite.png");
|
||||
}
|
||||
|
||||
#urlbar[focused="true"] > #identity-box.verifiedIdentity > hbox:-moz-system-metric(mac-graphite-theme) {
|
||||
#urlbar[focused="true"] > #identity-box.verifiedIdentity > #identity-box-inner:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-verified-mid-focused-graphite.png");
|
||||
}
|
||||
|
||||
#urlbar[focused="true"] > #identity-box.verifiedIdentity > hbox > #identity-icon-label:-moz-system-metric(mac-graphite-theme) {
|
||||
#urlbar[focused="true"] > #identity-box.verifiedIdentity > #identity-box-inner > #identity-icon-label:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-verified-end-focused-graphite.png");
|
||||
}
|
||||
|
||||
/* Favicon Glow */
|
||||
#identity-box.verifiedIdentity > hbox > #page-proxy-stack,
|
||||
#identity-box.verifiedDomain > hbox > #page-proxy-stack {
|
||||
#identity-box.verifiedIdentity > #identity-box-inner > #page-proxy-stack,
|
||||
#identity-box.verifiedDomain > #identity-box-inner > #page-proxy-stack {
|
||||
-moz-margin-start: -3px;
|
||||
width: 24px;
|
||||
height: 20px;
|
||||
|
@ -2017,15 +2005,14 @@ tabpanels.plain {
|
|||
}
|
||||
|
||||
/* Popup Body Text */
|
||||
#identity-popup-content-box > description,
|
||||
#identity-popup-encryption-label {
|
||||
.identity-popup-description {
|
||||
white-space: pre-wrap;
|
||||
color: #ffffff;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 2px 0 4px;
|
||||
}
|
||||
|
||||
#identity-popup-content-box > label {
|
||||
.identity-popup-label {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 0;
|
||||
|
@ -2074,9 +2061,8 @@ tabpanels.plain {
|
|||
}
|
||||
|
||||
#identity-popup-container {
|
||||
-moz-appearance: none;
|
||||
margin: 4px 3px 2px -30px;
|
||||
color: #ffffff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#identity-popup-content-box {
|
||||
|
@ -2096,7 +2082,7 @@ tabpanels.plain {
|
|||
padding: 1px 9px;
|
||||
margin: 10px 0 0;
|
||||
min-height: 0px;
|
||||
color: #ffffff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#identity-popup-more-info-button > .button-box > .button-text {
|
||||
|
|
|
@ -184,7 +184,7 @@ treechildren::-moz-tree-cell-text(broken) {
|
|||
background-color: -moz-field;
|
||||
}
|
||||
|
||||
#permList > vbox {
|
||||
.permission {
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
-moz-padding-start: 7px;
|
||||
|
@ -193,11 +193,11 @@ treechildren::-moz-tree-cell-text(broken) {
|
|||
border-bottom: 1px dotted #C0C0C0;
|
||||
}
|
||||
|
||||
#permList > vbox > label {
|
||||
.permissionLabel {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#permList > vbox:hover {
|
||||
.permission:hover {
|
||||
background-color: -moz-dialog;
|
||||
}
|
||||
|
||||
|
|
|
@ -394,10 +394,6 @@ window:not([active="true"]) #placesList > treechildren::-moz-tree-row(selected)
|
|||
list-style-image: url("chrome://browser/skin/places/expander-open-active.png") !important;
|
||||
}
|
||||
|
||||
.no-margin-button {
|
||||
min-width:0em;
|
||||
}
|
||||
|
||||
/**
|
||||
* info pane
|
||||
*/
|
||||
|
@ -425,6 +421,6 @@ window:not([active="true"]) #placesList > treechildren::-moz-tree-row(selected)
|
|||
color: GrayText;
|
||||
}
|
||||
|
||||
#editBookmarkPanelGrid > rows > row > label {
|
||||
.editBMPanel_rowLabel {
|
||||
text-align: right !important;
|
||||
}
|
||||
|
|
|
@ -3,11 +3,6 @@
|
|||
/* Sidebars */
|
||||
|
||||
.sidebar-placesTree {
|
||||
border-top: none !important;
|
||||
}
|
||||
|
||||
#sidebar tree,
|
||||
#sidebar page {
|
||||
background-color: transparent !important;
|
||||
-moz-appearance: none !important;
|
||||
border: none !important;
|
||||
|
@ -15,15 +10,14 @@
|
|||
|
||||
#bookmarksPanel,
|
||||
#history-panel,
|
||||
#bookmarksPanel > hbox,
|
||||
#history-panel > hbox {
|
||||
#sidebar-search-container {
|
||||
-moz-appearance: none !important;
|
||||
background-color: transparent !important;
|
||||
border-top: none !important;
|
||||
}
|
||||
|
||||
tree.sidebar-placesTree,
|
||||
tree.sidebar-placesTree treechildren::-moz-tree-row {
|
||||
.sidebar-placesTree,
|
||||
.sidebar-placesTreechildren::-moz-tree-row {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
padding-bottom: 1px;
|
||||
|
@ -32,47 +26,41 @@ tree.sidebar-placesTree treechildren::-moz-tree-row {
|
|||
border: none;
|
||||
}
|
||||
|
||||
tree.sidebar-placesTree treechildren::-moz-tree-separator {
|
||||
.sidebar-placesTreechildren::-moz-tree-separator {
|
||||
border-top: 1px solid #505d6d;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
#historyTree,
|
||||
#bookmarks-view {
|
||||
.sidebar-placesTree {
|
||||
border-top: 1px solid #bebebe;
|
||||
}
|
||||
|
||||
#bookmarks-view treechildren::-moz-tree-row(selected),
|
||||
#historyTree treechildren::-moz-tree-row(selected) {
|
||||
.sidebar-placesTreechildren::-moz-tree-row(selected) {
|
||||
background: @sidebarItemBackground@;
|
||||
border-top: @sidebarItemBorderTop@;
|
||||
}
|
||||
|
||||
#bookmarks-view treechildren::-moz-tree-row(selected,focus),
|
||||
#historyTree treechildren::-moz-tree-row(selected,focus) {
|
||||
.sidebar-placesTreechildren::-moz-tree-row(selected,focus) {
|
||||
background: @sidebarItemFocusedBackground@;
|
||||
border-top: @sidebarItemFocusedBorderTop@;
|
||||
}
|
||||
|
||||
#bookmarks-view:-moz-system-metric(mac-graphite-theme) treechildren::-moz-tree-row(selected),
|
||||
#historyTree:-moz-system-metric(mac-graphite-theme) treechildren::-moz-tree-row(selected) {
|
||||
.sidebar-placesTreechildren::-moz-tree-row(selected):-moz-system-metric(mac-graphite-theme) {
|
||||
background: @sidebarItemGraphiteBackground@;
|
||||
border-top: @sidebarItemGraphiteBorderTop@;
|
||||
}
|
||||
|
||||
#bookmarks-view:-moz-system-metric(mac-graphite-theme) treechildren::-moz-tree-row(selected,focus),
|
||||
#historyTree:-moz-system-metric(mac-graphite-theme) treechildren::-moz-tree-row(selected,focus) {
|
||||
.sidebar-placesTreechildren::-moz-tree-row(selected,focus):-moz-system-metric(mac-graphite-theme) {
|
||||
background: @sidebarItemGraphiteFocusedBackground@;
|
||||
border-top: @sidebarItemGraphiteFocusedBorderTop@;
|
||||
}
|
||||
|
||||
tree.sidebar-placesTree treechildren::-moz-tree-cell-text(selected) {
|
||||
.sidebar-placesTreechildren::-moz-tree-cell-text(selected) {
|
||||
font-weight: bold !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
#bookmarksPanel > hbox > label,
|
||||
#history-panel > hbox > label {
|
||||
#sidebar-search-label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -100,8 +88,8 @@ tree.sidebar-placesTree treechildren::-moz-tree-cell-text(selected) {
|
|||
-moz-outline-radius: 10px;
|
||||
}
|
||||
|
||||
page > hbox {
|
||||
margin: 0 4px 6px 4px;
|
||||
#sidebar-search-container {
|
||||
margin: 0 4px 6px;
|
||||
}
|
||||
|
||||
/* Trees */
|
||||
|
|
|
@ -146,7 +146,7 @@ prefpane .groupbox-body {
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
#paneTabs > vbox {
|
||||
#tabPrefsBox {
|
||||
margin: 12px 4px;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,11 +47,11 @@
|
|||
@namespace html url("http://www.w3.org/1999/xhtml");
|
||||
|
||||
#urlbar:-moz-lwtheme:not([focused="true"]),
|
||||
#searchbar:-moz-lwtheme > textbox:not([focused="true"]) {
|
||||
.searchbar-textbox:-moz-lwtheme:not([focused="true"]) {
|
||||
opacity: .85;
|
||||
}
|
||||
|
||||
.tabbrowser-tab[selected="true"]:-moz-lwtheme {
|
||||
.tabbrowser-tab:-moz-lwtheme[selected="true"] {
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@
|
|||
-moz-box-orient: vertical; /* for flex hack */
|
||||
}
|
||||
|
||||
#menubar-items > menubar {
|
||||
#main-menubar {
|
||||
-moz-box-flex: 1; /* make menu items expand to fill toolbar height */
|
||||
}
|
||||
|
||||
|
@ -77,10 +77,6 @@
|
|||
min-height: 24px;
|
||||
}
|
||||
|
||||
#wrapper-search-container #searchbar html|*.textbox-input {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#navigator-toolbox:-moz-system-metric(windows-default-theme) {
|
||||
padding-bottom: 1px; /* uxtheme border drawing fix/hack */
|
||||
}
|
||||
|
@ -1766,14 +1762,13 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
|
|||
}
|
||||
|
||||
/* Popup Body Text */
|
||||
#identity-popup-content-box > description,
|
||||
#identity-popup-encryption-label {
|
||||
.identity-popup-description {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 2px 0 4px;
|
||||
}
|
||||
|
||||
#identity-popup-content-box > label {
|
||||
.identity-popup-label {
|
||||
white-space: pre-wrap;
|
||||
-moz-padding-start: 15px;
|
||||
margin: 0;
|
||||
|
@ -1835,7 +1830,6 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
|
|||
}
|
||||
|
||||
#identity-popup-container {
|
||||
background-image: none;
|
||||
min-width: 280px;
|
||||
padding: 9px;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
@import "chrome://global/skin/";
|
||||
|
||||
/* View buttons */
|
||||
#viewGroup radio {
|
||||
#viewGroup > radio {
|
||||
list-style-image: url("chrome://browser/skin/pageInfo.png");
|
||||
-moz-box-orient: vertical;
|
||||
-moz-box-align: center;
|
||||
|
@ -234,7 +234,7 @@ treechildren::-moz-tree-cell-text(broken) {
|
|||
background-color: -moz-field;
|
||||
}
|
||||
|
||||
#permList > vbox {
|
||||
.permission {
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
-moz-padding-start: 7px;
|
||||
|
@ -243,11 +243,11 @@ treechildren::-moz-tree-cell-text(broken) {
|
|||
border-bottom: 1px dotted #C0C0C0;
|
||||
}
|
||||
|
||||
#permList > vbox > label {
|
||||
.permissionLabel {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#permList > vbox:hover {
|
||||
.permission:hover {
|
||||
background-color: -moz-dialog;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,8 +60,8 @@
|
|||
-moz-margin-end: 4px;
|
||||
}
|
||||
|
||||
.expander-up > hbox,
|
||||
.expander-down > hbox {
|
||||
.expander-up > .button-box,
|
||||
.expander-down > .button-box {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
color: -moz-win-mediatext;
|
||||
}
|
||||
|
||||
#placesMenu:-moz-system-metric(windows-default-theme) > menu > label {
|
||||
#placesMenu > menu > .menubar-text:-moz-system-metric(windows-default-theme) {
|
||||
-moz-padding-end: 15px;
|
||||
background-image: url(chrome://browser/skin/places/dropDown.png);
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
border: none;
|
||||
}
|
||||
|
||||
#placesToolbar > toolbarbutton > image,
|
||||
#placesToolbar > toolbarbutton > label {
|
||||
#placesToolbar > toolbarbutton > .toolbarbutton-icon,
|
||||
#placesToolbar > toolbarbutton > .toolbarbutton-text {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
@ -89,12 +89,12 @@
|
|||
padding-bottom: 1px;
|
||||
}
|
||||
|
||||
#placesMenu > menu > label {
|
||||
#placesMenu > menu > .menubar-text {
|
||||
-moz-padding-end: 8px;
|
||||
background: url(chrome://global/skin/arrow/arrow-dn.gif) right center no-repeat;
|
||||
}
|
||||
|
||||
#placesMenu:-moz-locale-dir(rtl) > menu > label {
|
||||
#placesMenu > menu > .menubar-text:-moz-locale-dir(rtl) {
|
||||
background-position: left center;
|
||||
}
|
||||
|
||||
|
@ -171,13 +171,12 @@
|
|||
margin: 0 1px;
|
||||
}
|
||||
|
||||
#organizerScopeBar > toolbarbutton > label,
|
||||
#organizerScopeBar > toolbarbutton > image {
|
||||
#organizerScopeBar > toolbarbutton > .toolbarbutton-icon {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#organizerScopeBar .toolbarbutton-text {
|
||||
#organizerScopeBar > toolbarbutton > .toolbarbutton-text {
|
||||
margin: 0;
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ treechildren::-moz-tree-cell-text(date, session-continue) {
|
|||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
#viewButton > hbox > dropmarker {
|
||||
#viewButton > .button-box > .button-menu-dropmarker {
|
||||
height: auto;
|
||||
width: auto;
|
||||
-moz-margin-end: -3px;
|
||||
|
|
|
@ -59,8 +59,8 @@
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
.expander-up > hbox,
|
||||
.expander-down > hbox {
|
||||
.expander-up > .button-box,
|
||||
.expander-down > .button-box {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -335,7 +335,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
|||
for v in extraPrefs:
|
||||
thispref = v.split("=")
|
||||
if len(thispref) < 2:
|
||||
print "Error: syntax error in --extra-pref=" + v
|
||||
print "Error: syntax error in --setpref=" + v
|
||||
sys.exit(1)
|
||||
part = 'user_pref("%s", %s);\n' % (thispref[0], thispref[1])
|
||||
prefs.append(part)
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
repo: f5ab154deef2ffa97f1b2139589ae4a1962090a4
|
||||
node: 0aa14be496b38ea56b28158f375d01dc0cb91d1f
|
||||
node: 3476582628db128ad061c30cab1a74a0c5d14b9b
|
||||
|
|
|
@ -1008,7 +1008,7 @@ class Target(object):
|
|||
makefile.context.defer(cb, error=self.error, didanything=self.didanything)
|
||||
del self._callbacks
|
||||
|
||||
def make(self, makefile, targetstack, cb, avoidremakeloop=False):
|
||||
def make(self, makefile, targetstack, cb, avoidremakeloop=False, printerror=True):
|
||||
"""
|
||||
If we are out of date, asynchronously make ourself. This is a multi-stage process, mostly handled
|
||||
by the helper objects RemakeTargetSerially, RemakeTargetParallel,
|
||||
|
@ -1051,7 +1051,8 @@ class Target(object):
|
|||
try:
|
||||
self.resolvedeps(makefile, targetstack, [], False)
|
||||
except util.MakeError, e:
|
||||
print e
|
||||
if printerror:
|
||||
print e
|
||||
self.error = True
|
||||
self.notifydone(makefile)
|
||||
return
|
||||
|
@ -1312,7 +1313,7 @@ class _RemakeContext(object):
|
|||
|
||||
if len(self.toremake):
|
||||
target, self.required = self.toremake.pop(0)
|
||||
target.make(self.makefile, [], avoidremakeloop=True, cb=self.remakecb)
|
||||
target.make(self.makefile, [], avoidremakeloop=True, cb=self.remakecb, printerror=False)
|
||||
else:
|
||||
for t, required in self.included:
|
||||
if t.wasremade:
|
||||
|
|
|
@ -71,7 +71,7 @@ class Data(object):
|
|||
"""
|
||||
m = _skipws.search(self.s, offset, self.lend)
|
||||
if m is None:
|
||||
return None
|
||||
return self.lend
|
||||
|
||||
return m.start(0)
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import os
|
|||
|
||||
class MakeError(Exception):
|
||||
def __init__(self, message, loc=None):
|
||||
self.message = message
|
||||
self.msg = message
|
||||
self.loc = loc
|
||||
|
||||
def __str__(self):
|
||||
|
@ -10,7 +10,7 @@ class MakeError(Exception):
|
|||
if self.loc is not None:
|
||||
locstr = "%s:" % (self.loc,)
|
||||
|
||||
return "%s%s" % (locstr, self.message)
|
||||
return "%s%s" % (locstr, self.msg)
|
||||
|
||||
def joiniter(fd, it):
|
||||
"""
|
||||
|
@ -32,6 +32,8 @@ def checkmsyscompat():
|
|||
letting Python use the system shell."""
|
||||
if 'SHELL' in os.environ:
|
||||
shell = os.environ['SHELL']
|
||||
elif 'MOZILLABUILD' in os.environ:
|
||||
shell = os.environ['MOZILLABUILD'] + '/msys/bin/sh.exe'
|
||||
elif 'COMSPEC' in os.environ:
|
||||
shell = os.environ['COMSPEC']
|
||||
else:
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
all:
|
||||
@echo TEST-PASS
|
||||
|
||||
foo: ;
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
-include TEST-FAIL.mk
|
||||
|
||||
all:
|
||||
@echo TEST-PASS
|
|
@ -73,7 +73,7 @@ while (<>) {
|
|||
my @deps = split /\s+/, $rest;
|
||||
push @{$alldeps{$obj}}, @deps;
|
||||
if (DEBUG >= 2) {
|
||||
foreach my $dep (@deps) { print "add $obj $dep\n"; }
|
||||
foreach my $dep (@deps) { print STDERR "add $obj $dep\n"; }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,21 +88,21 @@ OBJ_LOOP: foreach my $obj (keys %alldeps) {
|
|||
foreach my $dep_file (@{$deps}) {
|
||||
my $dep_mtime = $modtimes{$dep_file};
|
||||
if (not defined $dep_mtime) {
|
||||
print "Skipping $dep_file for $obj, will stat() later\n" if DEBUG >= 2;
|
||||
print STDERR "Skipping $dep_file for $obj, will stat() later\n" if DEBUG >= 2;
|
||||
$not_in_cache{$dep_file} = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
print "Found $dep_file in cache\n" if DEBUG >= 2;
|
||||
print STDERR "Found $dep_file in cache\n" if DEBUG >= 2;
|
||||
|
||||
if ($dep_mtime > $mtime) {
|
||||
print "$dep_file($dep_mtime) newer than $obj($mtime)\n" if DEBUG;
|
||||
print STDERR "$dep_file($dep_mtime) newer than $obj($mtime)\n" if DEBUG;
|
||||
}
|
||||
elsif ($dep_mtime == -1) {
|
||||
print "Couldn't stat $dep_file for $obj\n" if DEBUG;
|
||||
print STDERR "Couldn't stat $dep_file for $obj\n" if DEBUG;
|
||||
}
|
||||
else {
|
||||
print "$dep_file($dep_mtime) older than $obj($mtime)\n" if DEBUG >= 2;
|
||||
print STDERR "$dep_file($dep_mtime) older than $obj($mtime)\n" if DEBUG >= 2;
|
||||
next;
|
||||
}
|
||||
|
||||
|
@ -111,17 +111,17 @@ OBJ_LOOP: foreach my $obj (keys %alldeps) {
|
|||
}
|
||||
|
||||
foreach my $dep_file (keys %not_in_cache) {
|
||||
print "STAT $dep_file for $obj\n" if DEBUG >= 2;
|
||||
print STDERR "STAT $dep_file for $obj\n" if DEBUG >= 2;
|
||||
my $dep_mtime = $modtimes{$dep_file} = (stat $dep_file)[9] || -1;
|
||||
|
||||
if ($dep_mtime > $mtime) {
|
||||
print "$dep_file($dep_mtime) newer than $obj($mtime)\n" if DEBUG;
|
||||
print STDERR "$dep_file($dep_mtime) newer than $obj($mtime)\n" if DEBUG;
|
||||
}
|
||||
elsif ($dep_mtime == -1) {
|
||||
print "Couldn't stat $dep_file for $obj\n" if DEBUG;
|
||||
print STDERR "Couldn't stat $dep_file for $obj\n" if DEBUG;
|
||||
}
|
||||
else {
|
||||
print "$dep_file($dep_mtime) older than $obj($mtime)\n" if DEBUG >= 2;
|
||||
print STDERR "$dep_file($dep_mtime) older than $obj($mtime)\n" if DEBUG >= 2;
|
||||
next;
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,11 @@ OBJ_LOOP: foreach my $obj (keys %alldeps) {
|
|||
}
|
||||
|
||||
# Output objects to rebuild (if needed).
|
||||
if (@objs) {
|
||||
if ($outfile eq '-') {
|
||||
if (@objs) {
|
||||
print "@objs: FORCE\n";
|
||||
}
|
||||
} elsif (@objs) {
|
||||
my $old_output;
|
||||
my $new_output = "@objs: FORCE\n";
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@ cmdname=`basename "$0"`
|
|||
MOZ_DIST_BIN=`dirname "$0"`
|
||||
MOZ_DEFAULT_NAME="./${cmdname}-bin"
|
||||
MOZ_APPRUNNER_NAME="./mozilla-bin"
|
||||
MOZ_VIEWER_NAME="./viewer"
|
||||
MOZ_PROGRAM=""
|
||||
|
||||
exitcode=1
|
||||
|
@ -62,18 +61,10 @@ echo " --debugger debugger"
|
|||
echo ""
|
||||
echo " Examples:"
|
||||
echo ""
|
||||
echo " Run the viewer"
|
||||
echo ""
|
||||
echo " ${cmdname} viewer"
|
||||
echo ""
|
||||
echo " Run the mozilla-bin binary"
|
||||
echo ""
|
||||
echo " ${cmdname} mozilla-bin"
|
||||
echo ""
|
||||
echo " Debug the viewer in a debugger"
|
||||
echo ""
|
||||
echo " ${cmdname} -g viewer"
|
||||
echo ""
|
||||
echo " Debug the mozilla-bin binary in gdb"
|
||||
echo ""
|
||||
echo " ${cmdname} -g mozilla-bin -d gdb"
|
||||
|
@ -239,11 +230,6 @@ then
|
|||
if [ -x "$MOZ_DEFAULT_NAME" ]
|
||||
then
|
||||
MOZ_PROGRAM=$MOZ_DEFAULT_NAME
|
||||
## Try viewer (this should be deprecated)
|
||||
##
|
||||
elif [ -x "$MOZ_VIEWER_NAME" ]
|
||||
then
|
||||
MOZ_PROGRAM=$MOZ_VIEWER_NAME
|
||||
##
|
||||
## Try mozilla-bin
|
||||
##
|
||||
|
|
|
@ -250,6 +250,7 @@ class JarMaker(object):
|
|||
that against the l10nbases. l10nbases can either be path strings, or
|
||||
callables. In the latter case, that will be called with the
|
||||
relativesrcdir as argument, and is expected to return a path string.
|
||||
This logic is disabled if the jar.mn path is not inside the topsrcdir.
|
||||
'''
|
||||
topsourcedir = os.path.normpath(os.path.abspath(topsourcedir))
|
||||
def resolveL10nBase(relpath):
|
||||
|
@ -265,13 +266,18 @@ class JarMaker(object):
|
|||
l10ndir = srcdir
|
||||
if os.path.basename(srcdir) == 'locales':
|
||||
l10ndir = os.path.dirname(l10ndir)
|
||||
assert srcdir.startswith(topsourcedir), "src dir %s not in topsourcedir %s" % (srcdir, topsourcedir)
|
||||
rell10ndir = l10ndir[len(topsourcedir):].lstrip(os.sep)
|
||||
|
||||
l10ndirs = map(resolveL10nBase(rell10ndir), l10nbases)
|
||||
if localedirs is not None:
|
||||
l10ndirs += [os.path.normpath(os.path.abspath(s))
|
||||
for s in localedirs]
|
||||
|
||||
l10ndirs = None
|
||||
# srcdir may not be a child of topsourcedir, in which case
|
||||
# we assume that the caller passed in suitable sourcedirs,
|
||||
# and just skip passing in localedirs
|
||||
if srcdir.startswith(topsourcedir):
|
||||
rell10ndir = l10ndir[len(topsourcedir):].lstrip(os.sep)
|
||||
|
||||
l10ndirs = map(resolveL10nBase(rell10ndir), l10nbases)
|
||||
if localedirs is not None:
|
||||
l10ndirs += [os.path.normpath(os.path.abspath(s))
|
||||
for s in localedirs]
|
||||
srcdirs = [os.path.normpath(os.path.abspath(s))
|
||||
for s in sourcedirs] + [srcdir]
|
||||
self.makeJar(infile=infile,
|
||||
|
@ -375,7 +381,7 @@ class JarMaker(object):
|
|||
if realsrc is None:
|
||||
if jf is not None:
|
||||
jf.close()
|
||||
raise RuntimeError("file not found: " + src)
|
||||
raise RuntimeError('File "%s" not found in %s' % (src, ', '.join(src_base)))
|
||||
if m.group('optPreprocess'):
|
||||
outf = outHelper.getOutput(out)
|
||||
inf = open(realsrc)
|
||||
|
|
|
@ -157,8 +157,13 @@ clean clobber realclean clobber_all::
|
|||
cd $(MKDEPEND_DIR); $(MAKE) $@
|
||||
endif
|
||||
|
||||
PYUNITS := unit-Expression.py unit-Preprocessor.py unit-nsinstall.py \
|
||||
unit-printprereleasesuffix.py
|
||||
PYUNITS := \
|
||||
unit-Expression.py \
|
||||
unit-Preprocessor.py \
|
||||
unit-nsinstall.py \
|
||||
unit-printprereleasesuffix.py \
|
||||
unit-JarMaker.py \
|
||||
$(NULL)
|
||||
|
||||
check:: check-python-modules check-jar-mn
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ MOZ_BUILD_APP = @MOZ_BUILD_APP@
|
|||
MOZ_APP_NAME = @MOZ_APP_NAME@
|
||||
MOZ_APP_DISPLAYNAME = @MOZ_APP_DISPLAYNAME@
|
||||
MOZ_APP_VERSION = @MOZ_APP_VERSION@
|
||||
MOZ_APP_UA_EXTRA = @MOZ_APP_UA_EXTRA@
|
||||
|
||||
MOZ_PKG_SPECIAL = @MOZ_PKG_SPECIAL@
|
||||
|
||||
|
@ -168,6 +169,7 @@ MOZ_CRASHREPORTER = @MOZ_CRASHREPORTER@
|
|||
MOZ_HELP_VIEWER = @MOZ_HELP_VIEWER@
|
||||
MOC= @MOC@
|
||||
MOZ_NSS_PATCH = @MOZ_NSS_PATCH@
|
||||
MOZ_WEBGL = @MOZ_WEBGL@
|
||||
|
||||
MOZ_JAVAXPCOM = @MOZ_JAVAXPCOM@
|
||||
JAVA_INCLUDE_PATH="@JAVA_INCLUDE_PATH@"
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
from unittest import TextTestRunner as _TestRunner, TestResult as _TestResult
|
||||
import inspect
|
||||
|
||||
'''Helper to make python unit tests report the way that the Mozilla
|
||||
unit test infrastructure expects tests to report.
|
||||
|
||||
Usage:
|
||||
|
||||
import unittest
|
||||
from mozunit import MozTestRunner
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(testRunner=MozTestRunner())
|
||||
'''
|
||||
|
||||
class _MozTestResult(_TestResult):
|
||||
def __init__(self, stream, descriptions):
|
||||
_TestResult.__init__(self)
|
||||
self.stream = stream
|
||||
self.descriptions = descriptions
|
||||
|
||||
def getDescription(self, test):
|
||||
if self.descriptions:
|
||||
return test.shortDescription() or str(test)
|
||||
else:
|
||||
return str(test)
|
||||
|
||||
def addSuccess(self, test):
|
||||
_TestResult.addSuccess(self, test)
|
||||
filename = inspect.getfile(test.__class__)
|
||||
testname = test._testMethodName
|
||||
self.stream.writeln("TEST-PASS | %s | %s" % (filename, testname))
|
||||
|
||||
def addError(self, test, err):
|
||||
_TestResult.addError(self, test, err)
|
||||
self.printFail(test, err)
|
||||
|
||||
def addFailure(self, test, err):
|
||||
_TestResult.addFailure(self, test, err)
|
||||
self.printFail(test,err)
|
||||
|
||||
def printFail(self, test, err):
|
||||
exctype, value, tb = err
|
||||
# Skip test runner traceback levels
|
||||
while tb and self._is_relevant_tb_level(tb):
|
||||
tb = tb.tb_next
|
||||
if not tb:
|
||||
self.stream.writeln("TEST-UNEXPECTED-FAIL | NO TRACEBACK |")
|
||||
_f, _ln, _t = inspect.getframeinfo(tb)[:3]
|
||||
self.stream.writeln("TEST-UNEXPECTED-FAIL | %s | line %d, %s: %s" %
|
||||
(_f, _ln, _t, value.message))
|
||||
|
||||
def printErrorList(self):
|
||||
for test, err in self.errors:
|
||||
self.stream.writeln("ERROR: %s" % self.getDescription(test))
|
||||
self.stream.writeln("%s" % err)
|
||||
|
||||
|
||||
class MozTestRunner(_TestRunner):
|
||||
def _makeResult(self):
|
||||
return _MozTestResult(self.stream, self.descriptions)
|
||||
def run(self, test):
|
||||
result = self._makeResult()
|
||||
test(result)
|
||||
result.printErrorList()
|
||||
return result
|
|
@ -360,6 +360,10 @@ endif # GNU_CC
|
|||
endif # ENABLE_CXX_EXCEPTIONS
|
||||
endif # WINNT
|
||||
|
||||
ifeq ($(SOLARIS_SUNPRO_CXX),1)
|
||||
CXXFLAGS += -features=extensions -D__FUNCTION__=__func__
|
||||
endif # Solaris Sun Studio C++
|
||||
|
||||
ifeq (,$(filter-out WINNT WINCE,$(HOST_OS_ARCH)))
|
||||
HOST_PDBFILE=$(basename $(@F)).pdb
|
||||
endif
|
||||
|
@ -2064,21 +2068,14 @@ ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))
|
|||
MDDEPEND_FILES := $(strip $(wildcard $(MDDEPDIR)/*.pp))
|
||||
|
||||
ifneq (,$(MDDEPEND_FILES))
|
||||
ifdef PERL
|
||||
# The script mddepend.pl checks the dependencies and writes to stdout
|
||||
# one rule to force out-of-date objects. For example,
|
||||
# foo.o boo.o: FORCE
|
||||
# The script has an advantage over including the *.pp files directly
|
||||
# because it handles the case when header files are removed from the build.
|
||||
# 'make' would complain that there is no way to build missing headers.
|
||||
ifeq (,$(MAKE_RESTARTS))
|
||||
$(MDDEPDIR)/.all.pp: FORCE
|
||||
@$(PERL) $(BUILD_TOOLS)/mddepend.pl $@ $(MDDEPEND_FILES)
|
||||
endif
|
||||
-include $(MDDEPDIR)/.all.pp
|
||||
else
|
||||
include $(MDDEPEND_FILES)
|
||||
endif
|
||||
ALL_PP_RESULTS = $(shell $(PERL) $(BUILD_TOOLS)/mddepend.pl - $(MDDEPEND_FILES))
|
||||
$(eval $(ALL_PP_RESULTS))
|
||||
endif
|
||||
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
import unittest
|
||||
|
||||
import os, sys, os.path, time, inspect
|
||||
from filecmp import dircmp
|
||||
from tempfile import mkdtemp
|
||||
from shutil import rmtree, copy2
|
||||
from zipfile import ZipFile
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
|
||||
from mozunit import MozTestRunner
|
||||
from JarMaker import JarMaker
|
||||
|
||||
|
||||
class _TreeDiff(dircmp):
|
||||
"""Helper to report rich results on difference between two directories.
|
||||
"""
|
||||
def _fillDiff(self, dc, rv, basepath="%s"):
|
||||
rv['right_only'] += map(lambda l: basepath % l, dc.right_only)
|
||||
rv['left_only'] += map(lambda l: basepath % l, dc.left_only)
|
||||
rv['diff_files'] += map(lambda l: basepath % l, dc.diff_files)
|
||||
rv['funny'] += map(lambda l: basepath % l, dc.common_funny)
|
||||
rv['funny'] += map(lambda l: basepath % l, dc.funny_files)
|
||||
for subdir, _dc in dc.subdirs.iteritems():
|
||||
self._fillDiff(_dc, rv, basepath % (subdir + "/%s"))
|
||||
def allResults(self, left, right):
|
||||
rv = {'right_only':[], 'left_only':[],
|
||||
'diff_files':[], 'funny': []}
|
||||
self._fillDiff(self, rv)
|
||||
chunks = []
|
||||
if rv['right_only']:
|
||||
chunks.append('%s only in %s' % (', '.join(rv['right_only']),
|
||||
right))
|
||||
if rv['left_only']:
|
||||
chunks.append('%s only in %s' % (', '.join(rv['left_only']),
|
||||
left))
|
||||
if rv['diff_files']:
|
||||
chunks.append('%s differ' % ', '.join(rv['diff_files']))
|
||||
if rv['funny']:
|
||||
chunks.append("%s don't compare" % ', '.join(rv['funny']))
|
||||
return '; '.join(chunks)
|
||||
|
||||
class TestJarMaker(unittest.TestCase):
|
||||
"""
|
||||
Unit tests for JarMaker.py
|
||||
"""
|
||||
debug = False # set to True to debug failing tests on disk
|
||||
def setUp(self):
|
||||
self.tmpdir = mkdtemp()
|
||||
self.srcdir = os.path.join(self.tmpdir, 'src')
|
||||
os.mkdir(self.srcdir)
|
||||
self.builddir = os.path.join(self.tmpdir, 'build')
|
||||
os.mkdir(self.builddir)
|
||||
self.refdir = os.path.join(self.tmpdir, 'ref')
|
||||
os.mkdir(self.refdir)
|
||||
self.stagedir = os.path.join(self.tmpdir, 'stage')
|
||||
os.mkdir(self.stagedir)
|
||||
|
||||
def tearDown(self):
|
||||
if self.debug:
|
||||
print self.tmpdir
|
||||
else:
|
||||
rmtree(self.tmpdir)
|
||||
|
||||
def _jar_and_compare(self, *args, **kwargs):
|
||||
jm = JarMaker(outputFormat='jar')
|
||||
kwargs['jardir'] = os.path.join(self.builddir, 'chrome')
|
||||
if 'topsourcedir' not in kwargs:
|
||||
kwargs['topsourcedir'] = self.srcdir
|
||||
jm.makeJars(*args, **kwargs)
|
||||
cwd = os.getcwd()
|
||||
os.chdir(self.builddir)
|
||||
try:
|
||||
# expand build to stage
|
||||
for path, dirs, files in os.walk('.'):
|
||||
stagedir = os.path.join(self.stagedir, path)
|
||||
if not os.path.isdir(stagedir):
|
||||
os.mkdir(stagedir)
|
||||
for file in files:
|
||||
if file.endswith('.jar'):
|
||||
# expand jar
|
||||
stagepath = os.path.join(stagedir, file)
|
||||
os.mkdir(stagepath)
|
||||
zf = ZipFile(os.path.join(path, file))
|
||||
# extractall is only in 2.6, do this manually :-(
|
||||
for entry_name in zf.namelist():
|
||||
segs = entry_name.split('/')
|
||||
fname = segs.pop()
|
||||
dname = os.path.join(stagepath, *segs)
|
||||
if not os.path.isdir(dname):
|
||||
os.makedirs(dname)
|
||||
if not fname:
|
||||
# directory, we're done
|
||||
continue
|
||||
_c = zf.read(entry_name)
|
||||
open(os.path.join(dname, fname), 'wb').write(_c)
|
||||
zf.close()
|
||||
else:
|
||||
copy2(os.path.join(path, file), stagedir)
|
||||
# compare both dirs
|
||||
os.chdir('..')
|
||||
td = _TreeDiff('ref', 'stage')
|
||||
return td.allResults('reference', 'build')
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
|
||||
def test_a_simple_jar(self):
|
||||
'''Test a simple jar.mn'''
|
||||
# create src content
|
||||
jarf = open(os.path.join(self.srcdir, 'jar.mn'), 'w')
|
||||
jarf.write('''test.jar:
|
||||
dir/foo (bar)
|
||||
''')
|
||||
jarf.close()
|
||||
open(os.path.join(self.srcdir,'bar'),'w').write('content\n')
|
||||
# create reference
|
||||
refpath = os.path.join(self.refdir, 'chrome', 'test.jar', 'dir')
|
||||
os.makedirs(refpath)
|
||||
open(os.path.join(refpath, 'foo'), 'w').write('content\n')
|
||||
# call JarMaker
|
||||
rv = self._jar_and_compare((os.path.join(self.srcdir,'jar.mn'),),
|
||||
tuple(),
|
||||
sourcedirs = [self.srcdir])
|
||||
self.assertTrue(not rv, rv)
|
||||
|
||||
def test_k_multi_relative_jar(self):
|
||||
'''Test the API for multiple l10n jars, with different relative paths'''
|
||||
# create app src content
|
||||
def _mangle(relpath):
|
||||
'method we use to map relpath to srcpaths'
|
||||
return os.path.join(self.srcdir, 'other-' + relpath)
|
||||
jars = []
|
||||
for relpath in ('foo', 'bar'):
|
||||
ldir = os.path.join(self.srcdir, relpath, 'locales')
|
||||
os.makedirs(ldir)
|
||||
jp = os.path.join(ldir, 'jar.mn')
|
||||
jars.append(jp)
|
||||
open(jp, 'w').write('''ab-CD.jar:
|
||||
% locale app ab-CD %app
|
||||
app/''' + relpath + ' (%' + relpath + ''')
|
||||
''')
|
||||
ldir = _mangle(relpath)
|
||||
os.mkdir(ldir)
|
||||
open(os.path.join(ldir, relpath), 'w').write(relpath+" content\n")
|
||||
# create reference
|
||||
chrome_ref = os.path.join(self.refdir, 'chrome')
|
||||
os.mkdir(chrome_ref)
|
||||
mf = open(os.path.join(chrome_ref, 'ab-CD.manifest'), 'wb')
|
||||
mf.write('locale app ab-CD jar:ab-CD.jar!/app\n')
|
||||
mf.close()
|
||||
ldir = os.path.join(chrome_ref, 'ab-CD.jar', 'app')
|
||||
os.makedirs(ldir)
|
||||
for relpath in ('foo', 'bar'):
|
||||
open(os.path.join(ldir, relpath), 'w').write(relpath+" content\n")
|
||||
# call JarMaker
|
||||
difference = self._jar_and_compare(jars,
|
||||
(_mangle,),
|
||||
sourcedirs = [])
|
||||
self.assertTrue(not difference, difference)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(testRunner=MozTestRunner())
|
50
configure.in
50
configure.in
|
@ -288,18 +288,18 @@ case "$target" in
|
|||
|
||||
ac_exeext=.exe
|
||||
|
||||
_pwdw=`pwd -W`
|
||||
_pwd=`pwd`
|
||||
make OGLES_SDK_DIR="$OGLES_SDK_DIR" WINCE_SDK_DIR="$WINCE_SDK_DIR" TOPSRCDIR="$_topsrcdir" OBJDIR="$_pwdw" -C $srcdir/build/wince/tools
|
||||
_pwd=`pwd -W`
|
||||
_topsrcdirwin=`cd \`dirname $0\`; pwd -W`
|
||||
make OGLES_SDK_DIR="$OGLES_SDK_DIR" WINCE_SDK_DIR="$WINCE_SDK_DIR" TOPSRCDIR="$_topsrcdirwin" OBJDIR="$_pwd" -C $srcdir/build/wince/tools
|
||||
|
||||
CC="$_pwd/dist/sdk/bin/arm-wince-gcc"
|
||||
CXX="$_pwd/dist/sdk/bin/arm-wince-gcc"
|
||||
CPP="$_pwd/dist/sdk/bin/arm-wince-gcc -E -nologo"
|
||||
CXXCPP="$_pwd/dist/sdk/bin/arm-wince-gcc -TP -E -nologo"
|
||||
LD="$_pwd/dist/sdk/bin/arm-wince-link"
|
||||
AR="$_pwd/dist/sdk/bin/arm-wince-lib"
|
||||
AS="$_pwd/dist/sdk/bin/arm-wince-as"
|
||||
RC="$_pwd/dist/sdk/bin/arm-wince-res"
|
||||
CC="$_pwd/dist/sdk/bin/arm-wince-gcc.exe"
|
||||
CXX="$_pwd/dist/sdk/bin/arm-wince-gcc.exe"
|
||||
CPP="$_pwd/dist/sdk/bin/arm-wince-gcc.exe -E -nologo"
|
||||
CXXCPP="$_pwd/dist/sdk/bin/arm-wince-gcc.exe -TP -E -nologo"
|
||||
LD="$_pwd/dist/sdk/bin/arm-wince-link.exe"
|
||||
AR="$_pwd/dist/sdk/bin/arm-wince-lib.exe"
|
||||
AS="$_pwd/dist/sdk/bin/arm-wince-as.exe"
|
||||
RC="$_pwd/dist/sdk/bin/arm-wince-res.exe"
|
||||
|
||||
|
||||
echo -----------------------------------------------------------------------------
|
||||
|
@ -508,7 +508,7 @@ MOZ_ARG_DISABLE_BOOL(vista-sdk-requirements,
|
|||
[ --disable-vista-sdk-requirements
|
||||
Do not build Vista SDK specific code],
|
||||
MOZ_DISABLE_VISTA_SDK_REQUIREMENTS=1,
|
||||
MOZ_DISABLE_VISTA_SDK_REQUIREMENTS=)
|
||||
MOZ_DISABLE_VISTA_SDK_REQUIREMENTS=$_PLATFORM_MOZ_DISABLE_VISTA_SDK_REQUIREMENTS)
|
||||
if test -n "$COMPILE_ENVIRONMENT"; then
|
||||
if test -n "$MOZ_DISABLE_VISTA_SDK_REQUIREMENTS"; then
|
||||
AC_MSG_WARN([--disable-vista-sdk-requirements is deprecated, use --with-windows-version=502 instead])
|
||||
|
@ -2004,7 +2004,10 @@ case "$target" in
|
|||
|
||||
*-wince*)
|
||||
TARGET_COMPILER_ABI=msvc
|
||||
MOZ_TOOLS_DIR=`echo $MOZ_TOOLS`
|
||||
_PLATFORM_DEFAULT_TOOLKIT=cairo-windows
|
||||
_PLATFORM_MOZ_DISABLE_VISTA_SDK_REQUIREMENTS=1
|
||||
MOZ_TOOLS_DIR=`cd $MOZ_TOOLS && pwd -W`
|
||||
MOZ_BUILD_ROOT=`cd $MOZ_BUILD_ROOT && pwd -W`
|
||||
AR_LIST="$AR -list"
|
||||
AR_EXTRACT="$AR -extract"
|
||||
AR_DELETE="$AR d"
|
||||
|
@ -3346,7 +3349,7 @@ AC_MSG_CHECKING(for ARM NEON support in compiler)
|
|||
_SAVE_CFLAGS="$CFLAGS"
|
||||
if test "$GNU_CC"; then
|
||||
# gcc needs -mfpu=neon to recognize NEON instructions
|
||||
CFLAGS="$CFLAGS -mfpu=neon"
|
||||
CFLAGS="$CFLAGS -mfpu=neon -mfloat-abi=softfp"
|
||||
fi
|
||||
AC_TRY_COMPILE([],
|
||||
[asm("vadd.i8 d0, d0, d0");],
|
||||
|
@ -4743,12 +4746,16 @@ photon)
|
|||
|
||||
cairo-windows)
|
||||
MOZ_WIDGET_TOOLKIT=windows
|
||||
if test -z "$WINCE"; then
|
||||
MOZ_WEBGL=1
|
||||
fi
|
||||
;;
|
||||
|
||||
cairo-gtk2|cairo-gtk2-x11)
|
||||
MOZ_WIDGET_TOOLKIT=gtk2
|
||||
MOZ_ENABLE_GTK2=1
|
||||
MOZ_ENABLE_XREMOTE=1
|
||||
MOZ_WEBGL=1
|
||||
|
||||
AC_DEFINE(MOZ_X11)
|
||||
MOZ_X11=1
|
||||
|
@ -4761,6 +4768,7 @@ cairo-gtk2|cairo-gtk2-x11)
|
|||
cairo-gtk2-dfb)
|
||||
MOZ_WIDGET_TOOLKIT=gtk2
|
||||
MOZ_ENABLE_GTK2=1
|
||||
MOZ_WEBGL=1
|
||||
|
||||
AC_DEFINE(MOZ_DFB)
|
||||
MOZ_DFB=1
|
||||
|
@ -4813,6 +4821,7 @@ cairo-cocoa)
|
|||
CXXFLAGS="$CXXFLAGS $TK_CFLAGS"
|
||||
LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) $(LIBXUL_DIST)/bin/XUL -lobjc'
|
||||
MOZ_FS_LAYOUT=bundle
|
||||
MOZ_WEBGL=1
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -6235,6 +6244,7 @@ if test $NS_OSSO; then
|
|||
fi
|
||||
AC_DEFINE(NS_OSSO)
|
||||
MOZ_GFX_OPTIMIZE_MOBILE=1
|
||||
MOZ_WEBGL=
|
||||
fi
|
||||
AC_SUBST(LIBOSSO_CFLAGS)
|
||||
AC_SUBST(LIBOSSO_LIBS)
|
||||
|
@ -7848,6 +7858,7 @@ AC_SUBST(MOZ_PLACES_BOOKMARKS)
|
|||
AC_SUBST(MOZ_STORAGE)
|
||||
AC_SUBST(MOZ_FEEDS)
|
||||
AC_SUBST(NS_PRINTING)
|
||||
AC_SUBST(MOZ_WEBGL)
|
||||
|
||||
AC_SUBST(MOZ_JAVAXPCOM)
|
||||
AC_SUBST(JAVA_INCLUDE_PATH)
|
||||
|
@ -7901,6 +7912,7 @@ AC_SUBST(OGLES_SDK_DIR)
|
|||
AC_SUBST(MOZ_APP_NAME)
|
||||
AC_SUBST(MOZ_APP_DISPLAYNAME)
|
||||
AC_SUBST(MOZ_APP_VERSION)
|
||||
AC_SUBST(MOZ_APP_UA_EXTRA)
|
||||
AC_SUBST(FIREFOX_VERSION)
|
||||
|
||||
AC_SUBST(MOZ_PKG_SPECIAL)
|
||||
|
@ -8077,6 +8089,16 @@ if test "$MOZ_X11"; then
|
|||
fi
|
||||
|
||||
fi # MOZ_X11
|
||||
|
||||
dnl Check for headers, etc. needed by WebGL.
|
||||
if test -n "$MOZ_WEBGL"; then
|
||||
if test "$MOZ_WIDGET_TOOLKIT" = gtk2; then
|
||||
AC_CHECK_HEADER(GL/glx.h)
|
||||
if test "$ac_cv_header_GL_glx_h" != "yes"; then
|
||||
AC_MSG_ERROR([Can't find header GL/glx.h for WebGL (install mesa-common-dev (Ubuntu), mesa-libGL-devel (Fedora), or Mesa (SuSE))])
|
||||
fi
|
||||
fi
|
||||
fi # MOZ_WEBGL
|
||||
fi # COMPILE_ENVIRONMENT
|
||||
|
||||
dnl Set various defines and substitutions
|
||||
|
|
|
@ -45,57 +45,46 @@
|
|||
#define NS_HTML_STYLE_PROPERTY_NOT_THERE \
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 2)
|
||||
|
||||
|
||||
/** Error codes for MaybeTriggerAutoLink */
|
||||
#define NS_XML_AUTOLINK_EMBED \
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 3)
|
||||
#define NS_XML_AUTOLINK_NEW \
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 4)
|
||||
#define NS_XML_AUTOLINK_REPLACE \
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 5)
|
||||
#define NS_XML_AUTOLINK_UNDEFINED \
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 6)
|
||||
|
||||
/** Error codes for nsScriptLoader */
|
||||
#define NS_CONTENT_SCRIPT_IS_EVENTHANDLER \
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 7)
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 3)
|
||||
|
||||
/** Error codes for image loading */
|
||||
#define NS_ERROR_IMAGE_SRC_CHANGED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_CONTENT, 8)
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_CONTENT, 4)
|
||||
|
||||
#define NS_ERROR_IMAGE_BLOCKED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_CONTENT, 9)
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_CONTENT, 5)
|
||||
|
||||
/** Error codes for content policy blocking */
|
||||
#define NS_ERROR_CONTENT_BLOCKED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_CONTENT, 10)
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_CONTENT, 6)
|
||||
|
||||
#define NS_ERROR_CONTENT_BLOCKED_SHOW_ALT \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_CONTENT, 11)
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_CONTENT, 7)
|
||||
|
||||
/** Success variations of content policy blocking */
|
||||
#define NS_CONTENT_BLOCKED \
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 12)
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 8)
|
||||
|
||||
#define NS_CONTENT_BLOCKED_SHOW_ALT \
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 13)
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 9)
|
||||
|
||||
#define NS_PROPTABLE_PROP_NOT_THERE \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_CONTENT, 14)
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_CONTENT, 10)
|
||||
|
||||
#define NS_PROPTABLE_PROP_OVERWRITTEN \
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 15)
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 11)
|
||||
|
||||
/* Error codes for FindBroadcaster in nsXULDocument.cpp */
|
||||
|
||||
#define NS_FINDBROADCASTER_NOT_FOUND \
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 16)
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 12)
|
||||
|
||||
#define NS_FINDBROADCASTER_FOUND \
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 17)
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 13)
|
||||
|
||||
#define NS_FINDBROADCASTER_AWAIT_OVERLAYS \
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 18)
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 14)
|
||||
|
||||
#endif // nsContentErrors_h___
|
||||
|
|
|
@ -1294,7 +1294,7 @@ public:
|
|||
|
||||
/**
|
||||
* Hide any XUL popups associated with aDocument, including any documents
|
||||
* displayed in child frames.
|
||||
* displayed in child frames. Does nothing if aDocument is null.
|
||||
*/
|
||||
static void HidePopupsInDocument(nsIDocument* aDocument);
|
||||
|
||||
|
@ -1606,6 +1606,7 @@ public:
|
|||
// Pop() will be a no-op if Push() or PushNull() fail
|
||||
void Pop();
|
||||
|
||||
nsIScriptContext* GetCurrentScriptContext() { return mScx; }
|
||||
private:
|
||||
// Combined code for PushNull() and Push(JSContext*)
|
||||
PRBool DoPush(JSContext* cx);
|
||||
|
|
|
@ -70,10 +70,10 @@ enum nsLinkState {
|
|||
};
|
||||
|
||||
// IID for the nsIContent interface
|
||||
// d510382f-f5eb-48bb-9ad9-b3dc4806faaf
|
||||
// c726e716-a4be-4202-8a5e-32d0525903e8
|
||||
#define NS_ICONTENT_IID \
|
||||
{ 0xd510382f, 0xf5eb, 0x48bb, \
|
||||
{ 0x9a, 0xd9, 0xb3, 0xdc, 0x48, 0x06, 0xfa, 0xaf } }
|
||||
{ 0xc726e716, 0xa4be, 0x4202, \
|
||||
{ 0x8a, 0x5e, 0x32, 0xd0, 0x52, 0x59, 0x03, 0xe8 } }
|
||||
|
||||
/**
|
||||
* A node of content in a document's content model. This interface
|
||||
|
@ -673,26 +673,6 @@ public:
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give this element a chance to fire links that should be fired
|
||||
* automatically when loaded. If the element was an autoloading link
|
||||
* and it was successfully handled, we will throw special nsresult values.
|
||||
*
|
||||
* @param aShell the current doc shell (to possibly load the link on)
|
||||
* @throws NS_OK if nothing happened
|
||||
* @throws NS_XML_AUTOLINK_EMBED if the caller is loading the link embedded
|
||||
* @throws NS_XML_AUTOLINK_NEW if the caller is loading the link in a new
|
||||
* window
|
||||
* @throws NS_XML_AUTOLINK_REPLACE if it is loading a link that will replace
|
||||
* the current window (and thus the caller must stop parsing)
|
||||
* @throws NS_XML_AUTOLINK_UNDEFINED if it is loading in any other way--in
|
||||
* which case, the caller should stop parsing as well.
|
||||
*/
|
||||
virtual nsresult MaybeTriggerAutoLink(nsIDocShell *aShell)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when the parser finishes creating the element. This
|
||||
* particularly means that it has done everything you would expect it to have
|
||||
|
|
|
@ -129,6 +129,8 @@ public:
|
|||
mCompatMode(eCompatibility_FullStandards),
|
||||
mIsInitialDocumentInWindow(PR_FALSE),
|
||||
mMayStartLayout(PR_TRUE),
|
||||
mVisible(PR_TRUE),
|
||||
mRemovedFromDocShell(PR_FALSE),
|
||||
// mAllowDNSPrefetch starts true, so that we can always reliably && it
|
||||
// with various values that might disable it. Since we never prefetch
|
||||
// unless we get a window, and in that case the docshell value will get
|
||||
|
@ -689,12 +691,10 @@ public:
|
|||
nsIPrincipal* aPrincipal) = 0;
|
||||
|
||||
/**
|
||||
* Set the container (docshell) for this document.
|
||||
* Set the container (docshell) for this document. Virtual so that
|
||||
* docshell can call it.
|
||||
*/
|
||||
void SetContainer(nsISupports *aContainer)
|
||||
{
|
||||
mDocumentContainer = do_GetWeakReference(aContainer);
|
||||
}
|
||||
virtual void SetContainer(nsISupports *aContainer);
|
||||
|
||||
/**
|
||||
* Get the container (docshell) for this document.
|
||||
|
@ -1120,6 +1120,16 @@ public:
|
|||
* called yet.
|
||||
*/
|
||||
PRBool IsShowing() { return mIsShowing; }
|
||||
/**
|
||||
* Return whether the document is currently visible (in the sense of
|
||||
* OnPageHide having been called and OnPageShow not yet having been called)
|
||||
*/
|
||||
PRBool IsVisible() { return mVisible; }
|
||||
/**
|
||||
* Return true when this document is active, i.e., the active document
|
||||
* in a content viewer.
|
||||
*/
|
||||
PRBool IsActive() { return mDocumentContainer && !mRemovedFromDocShell; }
|
||||
|
||||
void RegisterFreezableElement(nsIContent* aContent);
|
||||
PRBool UnregisterFreezableElement(nsIContent* aContent);
|
||||
|
@ -1281,6 +1291,15 @@ protected:
|
|||
// True iff IsShowing() should be returning true
|
||||
PRPackedBool mIsShowing;
|
||||
|
||||
// True iff the document "page" is not hidden (i.e. currently in the
|
||||
// bfcache)
|
||||
PRPackedBool mVisible;
|
||||
|
||||
// True if our content viewer has been removed from the docshell
|
||||
// (it may still be displayed, but in zombie state). Form control data
|
||||
// has been saved.
|
||||
PRPackedBool mRemovedFromDocShell;
|
||||
|
||||
// True iff DNS prefetch is allowed for this document. Note that if the
|
||||
// document has no window, DNS prefetch won't be performed no matter what.
|
||||
PRPackedBool mAllowDNSPrefetch;
|
||||
|
|
|
@ -228,7 +228,10 @@ interface nsIXMLHttpRequest : nsISupports
|
|||
* @param password (optional) A password for authentication if necessary.
|
||||
* The default value is the empty string
|
||||
*/
|
||||
void open(in AUTF8String method, in AUTF8String url);
|
||||
[optional_argc] void open(in AUTF8String method, in AUTF8String url,
|
||||
[optional] in boolean async,
|
||||
[optional] in DOMString user,
|
||||
[optional] in DOMString password);
|
||||
|
||||
/**
|
||||
* Sends the request. If the request is asynchronous, returns
|
||||
|
|
|
@ -4601,11 +4601,9 @@ nsContentUtils::ProcessViewportInfo(nsIDocument *aDocument,
|
|||
void
|
||||
nsContentUtils::HidePopupsInDocument(nsIDocument* aDocument)
|
||||
{
|
||||
NS_PRECONDITION(aDocument, "Null document");
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm) {
|
||||
if (pm && aDocument) {
|
||||
nsCOMPtr<nsISupports> container = aDocument->GetContainer();
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShellToHide = do_QueryInterface(container);
|
||||
if (docShellToHide)
|
||||
|
@ -5071,13 +5069,10 @@ nsContentUtils::CanAccessNativeAnon()
|
|||
fp = nsnull;
|
||||
}
|
||||
|
||||
void *annotation = fp ? JS_GetFrameAnnotation(cx, fp) : nsnull;
|
||||
PRBool privileged;
|
||||
if (NS_SUCCEEDED(principal->IsCapabilityEnabled("UniversalXPConnect",
|
||||
annotation,
|
||||
&privileged)) &&
|
||||
if (NS_SUCCEEDED(sSecurityManager->IsSystemPrincipal(principal, &privileged)) &&
|
||||
privileged) {
|
||||
// UniversalXPConnect things are allowed to touch us.
|
||||
// Chrome things are allowed to touch us.
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
@ -5091,6 +5086,12 @@ nsContentUtils::CanAccessNativeAnon()
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// Before we throw, check for UniversalXPConnect.
|
||||
nsresult rv = sSecurityManager->IsCapabilityEnabled("UniversalXPConnect", &privileged);
|
||||
if (NS_SUCCEEDED(rv) && privileged) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -169,6 +169,7 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID);
|
|||
#include "nsIPropertyBag2.h"
|
||||
#include "nsIDOMPageTransitionEvent.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "nsHTMLMediaElement.h"
|
||||
|
||||
#include "mozAutoDocUpdate.h"
|
||||
|
||||
|
@ -1481,8 +1482,7 @@ nsDOMImplementation::Init(nsIURI* aDocumentURI, nsIURI* aBaseURI,
|
|||
// bother initializing members to 0.
|
||||
|
||||
nsDocument::nsDocument(const char* aContentType)
|
||||
: nsIDocument(),
|
||||
mVisible(PR_TRUE)
|
||||
: nsIDocument()
|
||||
{
|
||||
mContentType = aContentType;
|
||||
|
||||
|
@ -3575,6 +3575,25 @@ nsDocument::GetScopeObject()
|
|||
return scope;
|
||||
}
|
||||
|
||||
static void
|
||||
NotifyActivityChanged(nsIContent *aContent, void *aUnused)
|
||||
{
|
||||
#ifdef MOZ_MEDIA
|
||||
nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aContent));
|
||||
if (domMediaElem) {
|
||||
nsHTMLMediaElement* mediaElem = static_cast<nsHTMLMediaElement*>(aContent);
|
||||
mediaElem->NotifyOwnerDocumentActivityChanged();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocument::SetContainer(nsISupports* aContainer)
|
||||
{
|
||||
mDocumentContainer = do_GetWeakReference(aContainer);
|
||||
EnumerateFreezableElements(NotifyActivityChanged, nsnull);
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
|
||||
{
|
||||
|
@ -6973,6 +6992,7 @@ nsDocument::RemovedFromDocShell()
|
|||
return;
|
||||
|
||||
mRemovedFromDocShell = PR_TRUE;
|
||||
EnumerateFreezableElements(NotifyActivityChanged, nsnull);
|
||||
|
||||
PRUint32 i, count = mChildren.ChildCount();
|
||||
for (i = 0; i < count; ++i) {
|
||||
|
@ -7157,6 +7177,8 @@ void
|
|||
nsDocument::OnPageShow(PRBool aPersisted, nsIDOMEventTarget* aDispatchStartTarget)
|
||||
{
|
||||
mVisible = PR_TRUE;
|
||||
|
||||
EnumerateFreezableElements(NotifyActivityChanged, nsnull);
|
||||
UpdateLinkMap();
|
||||
|
||||
nsIContent* root = GetRootContent();
|
||||
|
@ -7237,6 +7259,7 @@ nsDocument::OnPageHide(PRBool aPersisted, nsIDOMEventTarget* aDispatchStartTarge
|
|||
DispatchPageTransition(target, NS_LITERAL_STRING("pagehide"), aPersisted);
|
||||
|
||||
mVisible = PR_FALSE;
|
||||
EnumerateFreezableElements(NotifyActivityChanged, nsnull);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1171,14 +1171,8 @@ protected:
|
|||
|
||||
// True if the document has been detached from its content viewer.
|
||||
PRPackedBool mIsGoingAway:1;
|
||||
// True if our content viewer has been removed from the docshell
|
||||
// (it may still be displayed, but in zombie state). Form control data
|
||||
// has been saved.
|
||||
PRPackedBool mRemovedFromDocShell:1;
|
||||
// True if the document is being destroyed.
|
||||
PRPackedBool mInDestructor:1;
|
||||
// True if the document "page" is not hidden
|
||||
PRPackedBool mVisible:1;
|
||||
// True if document has ever had script handling object.
|
||||
PRPackedBool mHasHadScriptHandlingObject:1;
|
||||
|
||||
|
|
|
@ -96,17 +96,17 @@ public:
|
|||
nsIDocShell* GetExistingDocShell() { return mDocShell; }
|
||||
|
||||
/**
|
||||
* Called from the layout frame associated with this frame loader,
|
||||
* set up and show the base window associated with our docshell.
|
||||
* Called from the layout frame associated with this frame loader;
|
||||
* this notifies us to hook up with the widget and view.
|
||||
*/
|
||||
bool Show(PRInt32 marginWidth, PRInt32 marginHeight,
|
||||
PRInt32 scrollbarPrefX, PRInt32 scrollbarPrefY,
|
||||
nsIFrameFrame* frame);
|
||||
|
||||
/**
|
||||
* Called from the layout frame associated with this frame loader,
|
||||
* which is being torn down: remove our docshell from the widget/view
|
||||
* hierarchy.
|
||||
* Called from the layout frame associated with this frame loader, when
|
||||
* the frame is being torn down; this notifies us that out widget and view
|
||||
* are going away and we should unhook from them.
|
||||
*/
|
||||
void Hide();
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#endif
|
||||
#include "nsBindingManager.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsHTMLMediaElement.h"
|
||||
|
||||
// This macro expects the ownerDocument of content_ to be in scope as
|
||||
// |nsIDocument* doc|
|
||||
|
@ -604,6 +605,8 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep,
|
|||
|
||||
nsIDocument* newDoc = aNode->GetOwnerDoc();
|
||||
if (newDoc) {
|
||||
// XXX what if oldDoc is null, we don't know if this should be
|
||||
// registered or not! Can that really happen?
|
||||
if (wasRegistered) {
|
||||
newDoc->RegisterFreezableElement(static_cast<nsIContent*>(aNode));
|
||||
}
|
||||
|
@ -620,6 +623,16 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_MEDIA
|
||||
if (wasRegistered && oldDoc != newDoc) {
|
||||
nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aNode));
|
||||
if (domMediaElem) {
|
||||
nsHTMLMediaElement* mediaElem = static_cast<nsHTMLMediaElement*>(aNode);
|
||||
mediaElem->NotifyOwnerDocumentActivityChanged();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (elem) {
|
||||
elem->RecompileScriptEventListeners();
|
||||
}
|
||||
|
|
|
@ -261,6 +261,10 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType)
|
|||
nsCOMPtr<nsIStreamLoader> loader;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mDocument->GetScriptGlobalObject()));
|
||||
if (!window) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsIDocShell *docshell = window->GetDocShell();
|
||||
|
||||
nsCOMPtr<nsIInterfaceRequestor> prompter(do_QueryInterface(docshell));
|
||||
|
|
|
@ -1753,30 +1753,14 @@ nsXMLHttpRequest::OpenRequest(const nsACString& method,
|
|||
|
||||
/* void open (in AUTF8String method, in AUTF8String url); */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url)
|
||||
nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
|
||||
PRBool async, const nsAString& user,
|
||||
const nsAString& password, PRUint8 optional_argc)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
PRBool async = PR_TRUE;
|
||||
nsAutoString user, password;
|
||||
|
||||
nsAXPCNativeCallContext *cc = nsnull;
|
||||
nsIXPConnect *xpc = nsContentUtils::XPConnect();
|
||||
if (xpc) {
|
||||
rv = xpc->GetCurrentNativeCallContext(&cc);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && cc) {
|
||||
PRUint32 argc;
|
||||
rv = cc->GetArgc(&argc);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
jsval* argv;
|
||||
rv = cc->GetArgvPtr(&argv);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
JSContext* cx;
|
||||
rv = cc->GetJSContext(&cx);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
if (nsContentUtils::GetCurrentJSContext()) {
|
||||
// We're (likely) called from JS
|
||||
|
||||
// Find out if UniversalBrowserRead privileges are enabled
|
||||
if (nsContentUtils::IsCallerTrustedForRead()) {
|
||||
|
@ -1784,33 +1768,11 @@ nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url)
|
|||
} else {
|
||||
mState &= ~XML_HTTP_REQUEST_XSITEENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc > 2) {
|
||||
JSAutoRequest ar(cx);
|
||||
JSBool asyncBool;
|
||||
::JS_ValueToBoolean(cx, argv[2], &asyncBool);
|
||||
async = (PRBool)asyncBool;
|
||||
|
||||
if (argc > 3 && !JSVAL_IS_NULL(argv[3]) && !JSVAL_IS_VOID(argv[3])) {
|
||||
JSString* userStr = ::JS_ValueToString(cx, argv[3]);
|
||||
|
||||
if (userStr) {
|
||||
user.Assign(reinterpret_cast<PRUnichar *>
|
||||
(::JS_GetStringChars(userStr)),
|
||||
::JS_GetStringLength(userStr));
|
||||
}
|
||||
|
||||
if (argc > 4 && !JSVAL_IS_NULL(argv[4]) && !JSVAL_IS_VOID(argv[4])) {
|
||||
JSString* passwdStr = JS_ValueToString(cx, argv[4]);
|
||||
|
||||
if (passwdStr) {
|
||||
password.Assign(reinterpret_cast<PRUnichar *>
|
||||
(::JS_GetStringChars(passwdStr)),
|
||||
::JS_GetStringLength(passwdStr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!optional_argc) {
|
||||
// No optional arguments were passed in. Default async to true.
|
||||
async = PR_TRUE;
|
||||
}
|
||||
|
||||
return OpenRequest(method, url, async, user, password);
|
||||
|
|
|
@ -55,12 +55,7 @@ CPPSRCS = \
|
|||
|
||||
# Canvas 3D Pieces
|
||||
|
||||
# only allow on platforms/toolkits we know are good
|
||||
ifneq (,$(NS_OSSO)$(WINCE)$(filter-out windows cocoa gtk2,$(MOZ_WIDGET_TOOLKIT)))
|
||||
DISABLE_WEBGL=1
|
||||
endif
|
||||
|
||||
ifndef DISABLE_WEBGL
|
||||
ifdef MOZ_WEBGL
|
||||
|
||||
CPPSRCS += \
|
||||
WebGLContext.cpp \
|
||||
|
|
|
@ -488,14 +488,17 @@ protected:
|
|||
* Gets the pres shell from either the canvas element or the doc shell
|
||||
*/
|
||||
nsIPresShell *GetPresShell() {
|
||||
nsIPresShell *presShell = nsnull;
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mCanvasElement);
|
||||
if (content) {
|
||||
presShell = content->GetOwnerDoc()->GetPrimaryShell();
|
||||
} else if (mDocShell) {
|
||||
mDocShell->GetPresShell(&presShell);
|
||||
nsIDocument* ownerDoc = content->GetOwnerDoc();
|
||||
return ownerDoc ? ownerDoc->GetPrimaryShell() : nsnull;
|
||||
}
|
||||
return presShell;
|
||||
if (mDocShell) {
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
mDocShell->GetPresShell(getter_AddRefs(shell));
|
||||
return shell.get();
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// text
|
||||
|
@ -618,14 +621,6 @@ protected:
|
|||
return mStyleStack[mSaveCount];
|
||||
}
|
||||
|
||||
// stolen from nsJSUtils
|
||||
static PRBool ConvertJSValToUint32(PRUint32* aProp, JSContext* aContext,
|
||||
jsval aValue);
|
||||
static PRBool ConvertJSValToXPCObject(nsISupports** aSupports, REFNSIID aIID,
|
||||
JSContext* aContext, jsval aValue);
|
||||
static PRBool ConvertJSValToDouble(double* aProp, JSContext* aContext,
|
||||
jsval aValue);
|
||||
|
||||
// other helpers
|
||||
void GetAppUnitsValues(PRUint32 *perDevPixel, PRUint32 *perCSSPixel) {
|
||||
// If we don't have a canvas element, we just return something generic.
|
||||
|
@ -2925,45 +2920,19 @@ bitblt(gfxImageSurface *s, int src_x, int src_y, int width, int height,
|
|||
// -- render the region defined by (sx,sy,sw,wh) in image-local space into the region (dx,dy,dw,dh) on the canvas
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::DrawImage()
|
||||
nsCanvasRenderingContext2D::DrawImage(nsIDOMElement *imgElt, float a1,
|
||||
float a2, float a3, float a4, float a5,
|
||||
float a6, float a7, float a8,
|
||||
PRUint8 optional_argc)
|
||||
{
|
||||
NS_ENSURE_ARG(imgElt);
|
||||
|
||||
nsresult rv;
|
||||
gfxRect dirty;
|
||||
|
||||
nsAXPCNativeCallContext *ncc = nsnull;
|
||||
rv = nsContentUtils::XPConnect()->
|
||||
GetCurrentNativeCallContext(&ncc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!ncc)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
JSContext *ctx = nsnull;
|
||||
|
||||
rv = ncc->GetJSContext(&ctx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 argc;
|
||||
jsval *argv = nsnull;
|
||||
|
||||
ncc->GetArgc(&argc);
|
||||
ncc->GetArgvPtr(&argv);
|
||||
|
||||
// we always need at least an image and a dx,dy
|
||||
if (argc < 3)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
JSAutoRequest ar(ctx);
|
||||
|
||||
double sx,sy,sw,sh;
|
||||
double dx,dy,dw,dh;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> imgElt;
|
||||
if (!ConvertJSValToXPCObject(getter_AddRefs(imgElt),
|
||||
NS_GET_IID(nsIDOMElement),
|
||||
ctx, argv[0]))
|
||||
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
|
||||
|
||||
gfxMatrix matrix;
|
||||
nsRefPtr<gfxPattern> pattern;
|
||||
nsRefPtr<gfxPath> path;
|
||||
|
@ -2997,40 +2966,36 @@ nsCanvasRenderingContext2D::DrawImage()
|
|||
|
||||
gfxContextPathAutoSaveRestore pathSR(mThebes, PR_FALSE);
|
||||
|
||||
#define GET_ARG(dest,whicharg) \
|
||||
do { if (!ConvertJSValToDouble(dest, ctx, whicharg)) { rv = NS_ERROR_INVALID_ARG; goto FINISH; } } while (0)
|
||||
|
||||
rv = NS_OK;
|
||||
|
||||
if (argc == 3) {
|
||||
GET_ARG(&dx, argv[1]);
|
||||
GET_ARG(&dy, argv[2]);
|
||||
if (optional_argc == 0) {
|
||||
dx = a1;
|
||||
dy = a2;
|
||||
sx = sy = 0.0;
|
||||
dw = sw = (double) imgSize.width;
|
||||
dh = sh = (double) imgSize.height;
|
||||
} else if (argc == 5) {
|
||||
GET_ARG(&dx, argv[1]);
|
||||
GET_ARG(&dy, argv[2]);
|
||||
GET_ARG(&dw, argv[3]);
|
||||
GET_ARG(&dh, argv[4]);
|
||||
} else if (optional_argc == 2) {
|
||||
dx = a1;
|
||||
dy = a2;
|
||||
dw = a3;
|
||||
dh = a4;
|
||||
sx = sy = 0.0;
|
||||
sw = (double) imgSize.width;
|
||||
sh = (double) imgSize.height;
|
||||
} else if (argc == 9) {
|
||||
GET_ARG(&sx, argv[1]);
|
||||
GET_ARG(&sy, argv[2]);
|
||||
GET_ARG(&sw, argv[3]);
|
||||
GET_ARG(&sh, argv[4]);
|
||||
GET_ARG(&dx, argv[5]);
|
||||
GET_ARG(&dy, argv[6]);
|
||||
GET_ARG(&dw, argv[7]);
|
||||
GET_ARG(&dh, argv[8]);
|
||||
} else if (optional_argc == 6) {
|
||||
sx = a1;
|
||||
sy = a2;
|
||||
sw = a3;
|
||||
sh = a4;
|
||||
dx = a5;
|
||||
dy = a6;
|
||||
dw = a7;
|
||||
dh = a8;
|
||||
} else {
|
||||
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
|
||||
rv = NS_ERROR_INVALID_ARG;
|
||||
goto FINISH;
|
||||
}
|
||||
#undef GET_ARG
|
||||
|
||||
if (dw == 0.0 || dh == 0.0) {
|
||||
rv = NS_OK;
|
||||
|
@ -3039,7 +3004,7 @@ nsCanvasRenderingContext2D::DrawImage()
|
|||
goto FINISH;
|
||||
}
|
||||
|
||||
if (!FloatValidate(sx,sy,sw,sh) || !FloatValidate(dx,dy,dw,dh)) {
|
||||
if (!FloatValidate(sx, sy, sw, sh) || !FloatValidate(dx, dy, dw, dh)) {
|
||||
rv = NS_ERROR_DOM_SYNTAX_ERR;
|
||||
goto FINISH;
|
||||
}
|
||||
|
@ -3225,61 +3190,6 @@ nsCanvasRenderingContext2D::GetGlobalCompositeOperation(nsAString& op)
|
|||
}
|
||||
|
||||
|
||||
//
|
||||
// Utils
|
||||
//
|
||||
PRBool
|
||||
nsCanvasRenderingContext2D::ConvertJSValToUint32(PRUint32* aProp, JSContext* aContext,
|
||||
jsval aValue)
|
||||
{
|
||||
uint32 temp;
|
||||
if (::JS_ValueToECMAUint32(aContext, aValue, &temp)) {
|
||||
*aProp = (PRUint32)temp;
|
||||
}
|
||||
else {
|
||||
::JS_ReportError(aContext, "Parameter must be an integer");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsCanvasRenderingContext2D::ConvertJSValToDouble(double* aProp, JSContext* aContext,
|
||||
jsval aValue)
|
||||
{
|
||||
jsdouble temp;
|
||||
if (::JS_ValueToNumber(aContext, aValue, &temp)) {
|
||||
*aProp = (jsdouble)temp;
|
||||
}
|
||||
else {
|
||||
::JS_ReportError(aContext, "Parameter must be a number");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsCanvasRenderingContext2D::ConvertJSValToXPCObject(nsISupports** aSupports, REFNSIID aIID,
|
||||
JSContext* aContext, jsval aValue)
|
||||
{
|
||||
*aSupports = nsnull;
|
||||
if (JSVAL_IS_NULL(aValue)) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_OBJECT(aValue)) {
|
||||
// WrapJS does all the work to recycle an existing wrapper and/or do a QI
|
||||
nsresult rv = nsContentUtils::XPConnect()->
|
||||
WrapJS(aContext, JSVAL_TO_OBJECT(aValue), aIID, (void**)aSupports);
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
FlushLayoutForTree(nsIDOMWindow* aWindow)
|
||||
{
|
||||
|
@ -3398,6 +3308,15 @@ nsCanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, float aX, float aY
|
|||
//
|
||||
// device pixel getting/setting
|
||||
//
|
||||
extern "C" {
|
||||
#include "jstypes.h"
|
||||
JS_FRIEND_API(JSBool)
|
||||
js_CoerceArrayToCanvasImageData(JSObject *obj, jsuint offset, jsuint count,
|
||||
JSUint8 *dest);
|
||||
JS_FRIEND_API(JSObject *)
|
||||
js_NewArrayObjectWithCapacity(JSContext *cx, jsuint capacity, jsval **vector);
|
||||
}
|
||||
|
||||
|
||||
// ImageData getImageData (in float x, in float y, in float width, in float height);
|
||||
NS_IMETHODIMP
|
||||
|
@ -3469,10 +3388,14 @@ nsCanvasRenderingContext2D::GetImageData()
|
|||
if (len > (((PRUint32)0xfff00000)/sizeof(jsval)))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
nsAutoArrayPtr<jsval> jsvector(new (std::nothrow) jsval[w * h * 4]);
|
||||
if (!jsvector)
|
||||
jsval *dest;
|
||||
JSObject *dataArray = js_NewArrayObjectWithCapacity(ctx, len, &dest);
|
||||
if (!dataArray)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
jsval *dest = jsvector.get();
|
||||
|
||||
nsAutoGCRoot arrayGCRoot(&dataArray, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint8 *row;
|
||||
for (int j = 0; j < h; j++) {
|
||||
row = surfaceData + surfaceDataOffset + (surfaceDataStride * j);
|
||||
|
@ -3504,13 +3427,8 @@ nsCanvasRenderingContext2D::GetImageData()
|
|||
}
|
||||
}
|
||||
|
||||
JSObject *dataArray = JS_NewArrayObject(ctx, w*h*4, jsvector.get());
|
||||
if (!dataArray)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsAutoGCRoot arrayGCRoot(&dataArray, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Allocate result object after array, so if we have to trigger gc
|
||||
// we do it now.
|
||||
JSObject *result = JS_NewObject(ctx, NULL, NULL, NULL);
|
||||
if (!result)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -3531,13 +3449,6 @@ nsCanvasRenderingContext2D::GetImageData()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#include "jstypes.h"
|
||||
JS_FRIEND_API(JSBool)
|
||||
js_CoerceArrayToCanvasImageData(JSObject *obj, jsuint offset, jsuint count,
|
||||
JSUint8 *dest);
|
||||
}
|
||||
|
||||
static inline PRUint8 ToUint8(jsint aInput)
|
||||
{
|
||||
if (PRUint32(aInput) > 255)
|
||||
|
@ -3803,21 +3714,19 @@ nsCanvasRenderingContext2D::CreateImageData()
|
|||
if (len / 4 != len0)
|
||||
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
||||
|
||||
nsAutoArrayPtr<jsval> jsvector(new (std::nothrow) jsval[w * h * 4]);
|
||||
if (!jsvector)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
jsval *dest = jsvector.get();
|
||||
for (PRUint32 i = 0; i < len; i++)
|
||||
*dest++ = JSVAL_ZERO;
|
||||
|
||||
JSObject *dataArray = JS_NewArrayObject(ctx, w*h*4, jsvector.get());
|
||||
jsval *dest;
|
||||
JSObject *dataArray = js_NewArrayObjectWithCapacity(ctx, len, &dest);
|
||||
if (!dataArray)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsAutoGCRoot arrayGCRoot(&dataArray, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRUint32 i = 0; i < len; i++)
|
||||
*dest++ = JSVAL_ZERO;
|
||||
|
||||
// Allocate result object after array, so if we have to trigger gc
|
||||
// we do it now.
|
||||
JSObject *result = JS_NewObject(ctx, NULL, NULL, NULL);
|
||||
if (!result)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
|
|
@ -3649,18 +3649,20 @@ isPixel(ctx, 50,25, 0,255,0,255, 2);
|
|||
|
||||
function test_2d_drawImage_wrongtype() {
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var canvas = document.getElementById('c127');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
var _thrown = undefined; try {
|
||||
ctx.drawImage(undefined, 0, 0);
|
||||
} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TYPE_MISMATCH_ERR");
|
||||
} catch (e) { _thrown = e }; ok(_thrown && _thrown.result == Components.results.NS_ERROR_INVALID_ARG, "should throw NS_ERROR_INVALID_ARG");
|
||||
var _thrown = undefined; try {
|
||||
ctx.drawImage(0, 0, 0);
|
||||
} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TYPE_MISMATCH_ERR");
|
||||
} catch (e) { _thrown = e }; ok(_thrown && _thrown.result == Components.results.NS_ERROR_XPC_BAD_CONVERT_JS_ZERO_ISNOT_NULL, "should throw NS_ERROR_XPC_BAD_CONVERT_JS_ZERO_ISNOT_NULL");
|
||||
var _thrown = undefined; try {
|
||||
ctx.drawImage("", 0, 0);
|
||||
} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TYPE_MISMATCH_ERR");
|
||||
} catch (e) { _thrown = e }; ok(_thrown && _thrown.result == Components.results.NS_ERROR_XPC_BAD_CONVERT_JS, "should throw NS_ERROR_XPC_BAD_CONVERT_JS");
|
||||
var _thrown = undefined; try {
|
||||
ctx.drawImage(document.createElement('p'), 0, 0);
|
||||
} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.TYPE_MISMATCH_ERR, "should throw TYPE_MISMATCH_ERR");
|
||||
|
@ -7352,8 +7354,8 @@ var _thrown_outer = false;
|
|||
|
||||
var imgdata1 = ctx.createImageData(10.01, 10.99);
|
||||
var imgdata2 = ctx.getImageData(0, 0, 10.01, 10.99);
|
||||
ok(imgdata1.width == imgdata2.width, "imgdata1.width == imgdata2.width");
|
||||
ok(imgdata1.height == imgdata2.height, "imgdata1.height == imgdata2.height");
|
||||
is(imgdata1.width, imgdata2.width, "imgdata1.width == imgdata2.width");
|
||||
is(imgdata1.height, imgdata2.height, "imgdata1.height == imgdata2.height");
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -50,13 +50,14 @@ class nsIAtom;
|
|||
class nsPIDOMEventTarget;
|
||||
class nsIEventListenerInfo;
|
||||
template<class E> class nsCOMArray;
|
||||
class nsCxPusher;
|
||||
|
||||
/*
|
||||
* Event listener manager interface.
|
||||
*/
|
||||
#define NS_IEVENTLISTENERMANAGER_IID \
|
||||
{ 0xac49ce4e, 0xaecf, 0x45db, \
|
||||
{ 0xa1, 0xe0, 0xea, 0x1d, 0x38, 0x73, 0x39, 0xa3 } }
|
||||
{ 0x2412fcd0, 0xd168, 0x4a1c, \
|
||||
{ 0xaa, 0x28, 0x70, 0xed, 0x58, 0xf0, 0x4c, 0xec } }
|
||||
|
||||
class nsIEventListenerManager : public nsISupports {
|
||||
|
||||
|
@ -65,6 +66,8 @@ public:
|
|||
|
||||
nsIEventListenerManager() : mMayHavePaintEventListener(PR_FALSE),
|
||||
mMayHaveMutationListeners(PR_FALSE),
|
||||
mMayHaveCapturingListeners(PR_FALSE),
|
||||
mMayHaveSystemGroupListeners(PR_FALSE),
|
||||
mNoListenerForEvent(0)
|
||||
{}
|
||||
|
||||
|
@ -147,7 +150,8 @@ public:
|
|||
nsIDOMEvent** aDOMEvent,
|
||||
nsPIDOMEventTarget* aCurrentTarget,
|
||||
PRUint32 aFlags,
|
||||
nsEventStatus* aEventStatus) = 0;
|
||||
nsEventStatus* aEventStatus,
|
||||
nsCxPusher* aPusher) = 0;
|
||||
|
||||
/**
|
||||
* Tells the event listener manager that its target (which owns it) is
|
||||
|
@ -217,10 +221,9 @@ public:
|
|||
protected:
|
||||
PRUint32 mMayHavePaintEventListener : 1;
|
||||
PRUint32 mMayHaveMutationListeners : 1;
|
||||
// These two member variables are used to cache the information
|
||||
// about the last event which was handled but for which event listener manager
|
||||
// didn't have event listeners.
|
||||
PRUint32 mNoListenerForEvent : 30;
|
||||
PRUint32 mMayHaveCapturingListeners : 1;
|
||||
PRUint32 mMayHaveSystemGroupListeners : 1;
|
||||
PRUint32 mNoListenerForEvent : 28;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIEventListenerManager,
|
||||
|
|
|
@ -75,7 +75,7 @@ interface nsIEventListenerService : nsISupports
|
|||
* If aEventTarget doesn't have any listeners, this returns null.
|
||||
*/
|
||||
void getListenerInfoFor(in nsIDOMEventTarget aEventTarget,
|
||||
out unsigned long aCount,
|
||||
[optional] out unsigned long aCount,
|
||||
[retval, array, size_is(aCount)] out
|
||||
nsIEventListenerInfo aOutArray);
|
||||
|
||||
|
@ -88,7 +88,7 @@ interface nsIEventListenerService : nsISupports
|
|||
* event target chain than what this methods returns.
|
||||
*/
|
||||
void getEventTargetChainFor(in nsIDOMEventTarget aEventTarget,
|
||||
out unsigned long aCount,
|
||||
[optional] out unsigned long aCount,
|
||||
[retval, array, size_is(aCount)] out
|
||||
nsIDOMEventTarget aOutArray);
|
||||
};
|
||||
|
|
|
@ -235,15 +235,21 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|||
// nsIDOMEventInterface
|
||||
NS_METHOD nsDOMEvent::GetType(nsAString& aType)
|
||||
{
|
||||
if (!mCachedType.IsEmpty()) {
|
||||
aType = mCachedType;
|
||||
return NS_OK;
|
||||
}
|
||||
const char* name = GetEventName(mEvent->message);
|
||||
|
||||
if (name) {
|
||||
CopyASCIItoUTF16(name, aType);
|
||||
mCachedType = aType;
|
||||
return NS_OK;
|
||||
} else if (mEvent->message == NS_USER_DEFINED_EVENT && mEvent->userType) {
|
||||
nsAutoString name;
|
||||
mEvent->userType->ToString(name);
|
||||
aType = Substring(name, 2, name.Length() - 2); // Remove "on"
|
||||
mCachedType = aType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -724,7 +730,7 @@ nsDOMEvent::InitEvent(const nsAString& aEventTypeArg, PRBool aCanBubbleArg, PRBo
|
|||
// re-dispatching it.
|
||||
mEvent->target = nsnull;
|
||||
mEvent->originalTarget = nsnull;
|
||||
|
||||
mCachedType = aEventTypeArg;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -212,6 +212,7 @@ protected:
|
|||
nsCOMPtr<nsPresContext> mPresContext;
|
||||
nsCOMPtr<nsIDOMEventTarget> mTmpRealOriginalTarget;
|
||||
nsCOMPtr<nsIDOMEventTarget> mExplicitOriginalTarget;
|
||||
nsString mCachedType;
|
||||
PRPackedBool mEventIsInternal;
|
||||
PRPackedBool mPrivateDataDuplicated;
|
||||
};
|
||||
|
|
|
@ -145,7 +145,8 @@ public:
|
|||
nsresult HandleEventTargetChain(nsEventChainPostVisitor& aVisitor,
|
||||
PRUint32 aFlags,
|
||||
nsDispatchingCallback* aCallback,
|
||||
PRBool aMayHaveNewListenerManagers);
|
||||
PRBool aMayHaveNewListenerManagers,
|
||||
nsCxPusher* aPusher);
|
||||
|
||||
/**
|
||||
* Resets aVisitor object and calls PreHandleEvent.
|
||||
|
@ -159,7 +160,8 @@ public:
|
|||
* and calls nsIEventListenerManager::HandleEvent().
|
||||
*/
|
||||
nsresult HandleEvent(nsEventChainPostVisitor& aVisitor, PRUint32 aFlags,
|
||||
PRBool aMayHaveNewListenerManagers);
|
||||
PRBool aMayHaveNewListenerManagers,
|
||||
nsCxPusher* aPusher);
|
||||
|
||||
/**
|
||||
* Copies mItemFlags and mItemData to aVisitor and calls PostHandleEvent.
|
||||
|
@ -221,7 +223,8 @@ nsEventTargetChainItem::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
|||
nsresult
|
||||
nsEventTargetChainItem::HandleEvent(nsEventChainPostVisitor& aVisitor,
|
||||
PRUint32 aFlags,
|
||||
PRBool aMayHaveNewListenerManagers)
|
||||
PRBool aMayHaveNewListenerManagers,
|
||||
nsCxPusher* aPusher)
|
||||
{
|
||||
if (WantsWillHandleEvent()) {
|
||||
mTarget->WillHandleEvent(aVisitor);
|
||||
|
@ -241,7 +244,8 @@ nsEventTargetChainItem::HandleEvent(nsEventChainPostVisitor& aVisitor,
|
|||
mManager->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent,
|
||||
&aVisitor.mDOMEvent,
|
||||
CurrentTarget(), aFlags,
|
||||
&aVisitor.mEventStatus);
|
||||
&aVisitor.mEventStatus,
|
||||
aPusher);
|
||||
NS_ASSERTION(aVisitor.mEvent->currentTarget == nsnull,
|
||||
"CurrentTarget should be null!");
|
||||
}
|
||||
|
@ -260,7 +264,8 @@ nsEventTargetChainItem::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
|||
nsresult
|
||||
nsEventTargetChainItem::HandleEventTargetChain(nsEventChainPostVisitor& aVisitor, PRUint32 aFlags,
|
||||
nsDispatchingCallback* aCallback,
|
||||
PRBool aMayHaveNewListenerManagers)
|
||||
PRBool aMayHaveNewListenerManagers,
|
||||
nsCxPusher* aPusher)
|
||||
{
|
||||
PRUint32 createdELMs = nsEventListenerManager::sCreatedCount;
|
||||
// Save the target so that it can be restored later.
|
||||
|
@ -276,7 +281,8 @@ nsEventTargetChainItem::HandleEventTargetChain(nsEventChainPostVisitor& aVisitor
|
|||
!(aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH)) {
|
||||
item->HandleEvent(aVisitor, aFlags & NS_EVENT_CAPTURE_MASK,
|
||||
aMayHaveNewListenerManagers ||
|
||||
createdELMs != nsEventListenerManager::sCreatedCount);
|
||||
createdELMs != nsEventListenerManager::sCreatedCount,
|
||||
aPusher);
|
||||
}
|
||||
|
||||
if (item->GetNewTarget()) {
|
||||
|
@ -305,7 +311,8 @@ nsEventTargetChainItem::HandleEventTargetChain(nsEventChainPostVisitor& aVisitor
|
|||
// <xul:dialog>'s buttons. Bug 235441.
|
||||
item->HandleEvent(aVisitor, aFlags,
|
||||
aMayHaveNewListenerManagers ||
|
||||
createdELMs != nsEventListenerManager::sCreatedCount);
|
||||
createdELMs != nsEventListenerManager::sCreatedCount,
|
||||
aPusher);
|
||||
}
|
||||
if (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
|
||||
item->PostHandleEvent(aVisitor);
|
||||
|
@ -327,7 +334,8 @@ nsEventTargetChainItem::HandleEventTargetChain(nsEventChainPostVisitor& aVisitor
|
|||
item->ForceContentDispatch()) &&
|
||||
!(aVisitor.mEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH)) {
|
||||
item->HandleEvent(aVisitor, aFlags & NS_EVENT_BUBBLE_MASK,
|
||||
createdELMs != nsEventListenerManager::sCreatedCount);
|
||||
createdELMs != nsEventListenerManager::sCreatedCount,
|
||||
aPusher);
|
||||
}
|
||||
if (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
|
||||
item->PostHandleEvent(aVisitor);
|
||||
|
@ -357,7 +365,8 @@ nsEventTargetChainItem::HandleEventTargetChain(nsEventChainPostVisitor& aVisitor
|
|||
aVisitor.mEvent->target = firstTarget;
|
||||
HandleEventTargetChain(aVisitor, aFlags | NS_EVENT_FLAG_SYSTEM_EVENT,
|
||||
aCallback,
|
||||
createdELMs != nsEventListenerManager::sCreatedCount);
|
||||
createdELMs != nsEventListenerManager::sCreatedCount,
|
||||
aPusher);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -542,11 +551,13 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
|
|||
} else {
|
||||
// Event target chain is created. Handle the chain.
|
||||
nsEventChainPostVisitor postVisitor(preVisitor);
|
||||
nsCxPusher pusher;
|
||||
rv = topEtci->HandleEventTargetChain(postVisitor,
|
||||
NS_EVENT_FLAG_BUBBLE |
|
||||
NS_EVENT_FLAG_CAPTURE,
|
||||
aCallback,
|
||||
PR_TRUE);
|
||||
PR_TRUE,
|
||||
&pusher);
|
||||
|
||||
preVisitor.mEventStatus = postVisitor.mEventStatus;
|
||||
// If the DOM event was created during event flow.
|
||||
|
|
|
@ -408,6 +408,7 @@ nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener,
|
|||
sysGroup->IsSameEventGroup(aEvtGrp, &isSame);
|
||||
if (isSame) {
|
||||
group = NS_EVENT_FLAG_SYSTEM_EVENT;
|
||||
mMayHaveSystemGroupListeners = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -453,6 +454,9 @@ nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener,
|
|||
ls->mGroupFlags = group;
|
||||
ls->mHandlerIsString = PR_FALSE;
|
||||
ls->mTypeData = aTypeData;
|
||||
if (aFlags & NS_EVENT_FLAG_CAPTURE) {
|
||||
mMayHaveCapturingListeners = PR_TRUE;
|
||||
}
|
||||
|
||||
if (aType == NS_AFTERPAINT) {
|
||||
mMayHavePaintEventListener = PR_TRUE;
|
||||
|
@ -617,7 +621,7 @@ nsEventListenerManager::SetJSEventListener(nsIScriptContext *aContext,
|
|||
// If we didn't find a script listener or no listeners existed
|
||||
// create and add a new one.
|
||||
nsCOMPtr<nsIDOMEventListener> scriptListener;
|
||||
rv = NS_NewJSEventListener(aContext, aScopeObject, aObject,
|
||||
rv = NS_NewJSEventListener(aContext, aScopeObject, aObject, aName,
|
||||
getter_AddRefs(scriptListener));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
AddEventListener(scriptListener, eventType, aName, nsnull,
|
||||
|
@ -880,7 +884,7 @@ nsEventListenerManager::CompileScriptEventListener(nsIScriptContext *aContext,
|
|||
|
||||
if (ls->mHandlerIsString) {
|
||||
rv = CompileEventHandlerInternal(aContext, aScope, aObject, aName,
|
||||
ls, /*XXX fixme*/nsnull);
|
||||
ls, /*XXX fixme*/nsnull, PR_TRUE);
|
||||
}
|
||||
|
||||
// Set *aDidCompile to true even if we didn't really compile
|
||||
|
@ -899,7 +903,8 @@ nsEventListenerManager::CompileEventHandlerInternal(nsIScriptContext *aContext,
|
|||
nsISupports *aObject,
|
||||
nsIAtom *aName,
|
||||
nsListenerStruct *aListenerStruct,
|
||||
nsISupports* aCurrentTarget)
|
||||
nsISupports* aCurrentTarget,
|
||||
PRBool aNeedsCxPush)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
|
||||
|
@ -962,7 +967,8 @@ nsEventListenerManager::CompileEventHandlerInternal(nsIScriptContext *aContext,
|
|||
}
|
||||
|
||||
nsCxPusher pusher;
|
||||
if (!pusher.Push((JSContext*)aContext->GetNativeContext())) {
|
||||
if (aNeedsCxPush &&
|
||||
!pusher.Push((JSContext*)aContext->GetNativeContext())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -1009,7 +1015,8 @@ nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
|
|||
nsIDOMEventListener* aListener,
|
||||
nsIDOMEvent* aDOMEvent,
|
||||
nsPIDOMEventTarget* aCurrentTarget,
|
||||
PRUint32 aPhaseFlags)
|
||||
PRUint32 aPhaseFlags,
|
||||
nsCxPusher* aPusher)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
|
||||
|
@ -1019,15 +1026,30 @@ nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
|
|||
aListenerStruct->mHandlerIsString) {
|
||||
nsCOMPtr<nsIJSEventListener> jslistener = do_QueryInterface(aListener);
|
||||
if (jslistener) {
|
||||
nsAutoString eventString;
|
||||
if (NS_SUCCEEDED(aDOMEvent->GetType(eventString))) {
|
||||
nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + eventString);
|
||||
// We probably have the atom already.
|
||||
nsCOMPtr<nsIAtom> atom = aListenerStruct->mTypeAtom;
|
||||
if (!atom) {
|
||||
nsAutoString eventString;
|
||||
if (NS_SUCCEEDED(aDOMEvent->GetType(eventString))) {
|
||||
atom = do_GetAtom(NS_LITERAL_STRING("on") + eventString);
|
||||
}
|
||||
}
|
||||
|
||||
if (atom) {
|
||||
#ifdef DEBUG
|
||||
nsAutoString type;
|
||||
aDOMEvent->GetType(type);
|
||||
nsCOMPtr<nsIAtom> eventAtom = do_GetAtom(NS_LITERAL_STRING("on") + type);
|
||||
NS_ASSERTION(eventAtom == atom, "Something wrong with event atoms!");
|
||||
#endif
|
||||
result = CompileEventHandlerInternal(jslistener->GetEventContext(),
|
||||
jslistener->GetEventScope(),
|
||||
jslistener->GetEventTarget(),
|
||||
atom, aListenerStruct,
|
||||
aCurrentTarget);
|
||||
aCurrentTarget,
|
||||
!jslistener->GetEventContext() ||
|
||||
jslistener->GetEventContext() !=
|
||||
aPusher->GetCurrentScriptContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1054,12 +1076,23 @@ nsEventListenerManager::HandleEvent(nsPresContext* aPresContext,
|
|||
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
|
||||
nsPIDOMEventTarget* aCurrentTarget,
|
||||
PRUint32 aFlags,
|
||||
nsEventStatus* aEventStatus)
|
||||
nsEventStatus* aEventStatus,
|
||||
nsCxPusher* aPusher)
|
||||
{
|
||||
if (mListeners.IsEmpty() || aEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!mMayHaveCapturingListeners &&
|
||||
!(aEvent->flags & NS_EVENT_FLAG_BUBBLE)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!mMayHaveSystemGroupListeners &&
|
||||
aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check if we already know that there is no event listener for the event.
|
||||
if (mNoListenerForEvent == aEvent->message &&
|
||||
(mNoListenerForEvent != NS_USER_DEFINED_EVENT ||
|
||||
|
@ -1104,7 +1137,6 @@ found:
|
|||
nsAutoTObserverArray<nsListenerStruct, 2>::EndLimitedIterator iter(mListeners);
|
||||
nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
|
||||
PRBool hasListener = PR_FALSE;
|
||||
nsCxPusher pusher;
|
||||
while (iter.HasMore()) {
|
||||
nsListenerStruct* ls = &iter.GetNext();
|
||||
PRBool useTypeInterface =
|
||||
|
@ -1134,13 +1166,13 @@ found:
|
|||
}
|
||||
nsRefPtr<nsIDOMEventListener> kungFuDeathGrip = ls->mListener;
|
||||
if (useTypeInterface) {
|
||||
pusher.Pop();
|
||||
aPusher->Pop();
|
||||
DispatchToInterface(*aDOMEvent, ls->mListener,
|
||||
dispData->method, *typeData->iid);
|
||||
} else if (useGenericInterface &&
|
||||
pusher.RePush(aCurrentTarget)) {
|
||||
aPusher->RePush(aCurrentTarget)) {
|
||||
HandleEventSubType(ls, ls->mListener, *aDOMEvent,
|
||||
aCurrentTarget, aFlags);
|
||||
aCurrentTarget, aFlags, aPusher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1408,7 +1440,8 @@ nsEventListenerManager::GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList)
|
|||
jslistener->GetEventTarget(),
|
||||
ls.mTypeAtom,
|
||||
const_cast<nsListenerStruct*>(&ls),
|
||||
mTarget);
|
||||
mTarget,
|
||||
PR_TRUE);
|
||||
}
|
||||
}
|
||||
if (ls.mTypeData) {
|
||||
|
|
|
@ -116,7 +116,8 @@ public:
|
|||
nsIDOMEvent** aDOMEvent,
|
||||
nsPIDOMEventTarget* aCurrentTarget,
|
||||
PRUint32 aFlags,
|
||||
nsEventStatus* aEventStatus);
|
||||
nsEventStatus* aEventStatus,
|
||||
nsCxPusher* aPusher);
|
||||
|
||||
NS_IMETHOD Disconnect();
|
||||
|
||||
|
@ -154,13 +155,15 @@ protected:
|
|||
nsIDOMEventListener* aListener,
|
||||
nsIDOMEvent* aDOMEvent,
|
||||
nsPIDOMEventTarget* aCurrentTarget,
|
||||
PRUint32 aPhaseFlags);
|
||||
PRUint32 aPhaseFlags,
|
||||
nsCxPusher* aPusher);
|
||||
nsresult CompileEventHandlerInternal(nsIScriptContext *aContext,
|
||||
void *aScopeObject,
|
||||
nsISupports *aObject,
|
||||
nsIAtom *aName,
|
||||
nsListenerStruct *aListenerStruct,
|
||||
nsISupports* aCurrentTarget);
|
||||
nsISupports* aCurrentTarget,
|
||||
PRBool aNeedsCxPush);
|
||||
nsListenerStruct* FindJSEventListener(PRUint32 aEventType, nsIAtom* aTypeAtom);
|
||||
nsresult SetJSEventListener(nsIScriptContext *aContext,
|
||||
void *aScopeGlobal,
|
||||
|
|
|
@ -80,6 +80,7 @@ _TEST_FILES = \
|
|||
test_bug489671.html \
|
||||
test_bug493251.html \
|
||||
test_bug502818.html \
|
||||
test_bug517851.html \
|
||||
$(NULL)
|
||||
|
||||
_CHROME_FILES = \
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=517851
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 517851</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=517851">Mozilla Bug 517851</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 517851 **/
|
||||
|
||||
window.handledCount = 0;
|
||||
window.testReturnValue = false;
|
||||
var target = document.createElement("div");
|
||||
target.setAttribute("onerror", "++window.handledCount; return window.testReturnValue;");
|
||||
target.setAttribute("onmouseover", "++window.handledCount; return window.testReturnValue;");
|
||||
target.setAttribute("onbeforeunload", "++window.handledCount; return window.testReturnValue;");
|
||||
target.setAttribute("onmousemove", "++window.handledCount; return window.testReturnValue;");
|
||||
|
||||
var e = document.createEvent("Event");
|
||||
e.initEvent("error", true, true);
|
||||
window.testReturnValue = false;
|
||||
is(target.dispatchEvent(e), !window.testReturnValue,
|
||||
"error event should have reverse return value handling!");
|
||||
is(handledCount, 1, "Wrong event count!");
|
||||
window.testReturnValue = true;
|
||||
is(target.dispatchEvent(e), !window.testReturnValue,
|
||||
"error event should have reverse return value handling (2)!");
|
||||
is(handledCount, 2, "Wrong event count!");
|
||||
|
||||
e = document.createEvent("MouseEvent");
|
||||
e.initEvent("mouseover", true, true);
|
||||
window.testReturnValue = false;
|
||||
is(target.dispatchEvent(e), !window.testReturnValue,
|
||||
"mouseover event should have reverse return value handling!");
|
||||
is(handledCount, 3, "Wrong event count!");
|
||||
window.testReturnValue = true;
|
||||
is(target.dispatchEvent(e), !window.testReturnValue,
|
||||
"mouseover event should have reverse return value handling (2)!");
|
||||
is(handledCount, 4, "Wrong event count!");
|
||||
|
||||
e = document.createEvent("BeforeUnloadEvent");
|
||||
e.initEvent("beforeunload", true, true);
|
||||
window.testReturnValue = true;
|
||||
is(target.dispatchEvent(e), false,
|
||||
"beforeunload event should be prevented!");
|
||||
is(handledCount, 5, "Wrong event count!");
|
||||
window.testReturnValue = false;
|
||||
is(target.dispatchEvent(e), false,
|
||||
"beforeunload event should be prevented (2)!");
|
||||
is(handledCount, 6, "Wrong event count!");
|
||||
|
||||
// Create normal event for beforeunload.
|
||||
e = document.createEvent("Event");
|
||||
e.initEvent("beforeunload", true, true);
|
||||
window.testReturnValue = true;
|
||||
is(target.dispatchEvent(e), true,
|
||||
"beforeunload event shouldn't be prevented (3)!");
|
||||
is(handledCount, 7, "Wrong event count!");
|
||||
|
||||
e = document.createEvent("MouseEvent");
|
||||
e.initEvent("mousemove", true, true);
|
||||
window.testReturnValue = true;
|
||||
is(target.dispatchEvent(e), window.testReturnValue,
|
||||
"mousemove event shouldn't have reverse return value handling!");
|
||||
is(handledCount, 8, "Wrong event count!");
|
||||
window.testReturnValue = false;
|
||||
is(target.dispatchEvent(e), window.testReturnValue,
|
||||
"mousemove event shouldn't have reverse return value handling (2)!");
|
||||
is(handledCount, 9, "Wrong event count!");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -88,6 +88,8 @@ public:
|
|||
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
nsIAtom* aPrefix, const nsAString& aValue,
|
||||
PRBool aNotify);
|
||||
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttr,
|
||||
PRBool aNotify);
|
||||
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
|
@ -97,7 +99,12 @@ public:
|
|||
|
||||
virtual PRBool IsDoneAddingChildren();
|
||||
virtual nsresult DoneAddingChildren(PRBool aHaveNotified);
|
||||
virtual void DestroyContent();
|
||||
|
||||
/**
|
||||
* Call this to reevaluate whether we should start/stop due to our owner
|
||||
* document being active or inactive.
|
||||
*/
|
||||
void NotifyOwnerDocumentActivityChanged();
|
||||
|
||||
// Called by the video decoder object, on the main thread,
|
||||
// when it has read the metadata containing video dimensions,
|
||||
|
@ -180,6 +187,9 @@ public:
|
|||
// events can be fired.
|
||||
void ChangeReadyState(nsMediaReadyState aState);
|
||||
|
||||
// Return true if we can activate autoplay assuming enough data has arrived.
|
||||
PRBool CanActivateAutoplay();
|
||||
|
||||
// Notify that enough data has arrived to start autoplaying.
|
||||
// If the element is 'autoplay' and is ready to play back (not paused,
|
||||
// autoplay pref enabled, etc), it should start playing back.
|
||||
|
@ -204,11 +214,6 @@ public:
|
|||
// main thread when/if the size changes.
|
||||
void UpdateMediaSize(nsIntSize size);
|
||||
|
||||
// Handle moving into and out of the bfcache by pausing and playing
|
||||
// as needed.
|
||||
void Freeze();
|
||||
void Thaw();
|
||||
|
||||
// Returns true if we can handle this MIME type.
|
||||
// If it returns true, then it also returns a null-terminated list
|
||||
// of supported codecs in *aSupportedCodecs. This
|
||||
|
@ -277,10 +282,10 @@ protected:
|
|||
void SetPlayedOrSeeked(PRBool aValue);
|
||||
|
||||
/**
|
||||
* Create a decoder for the given aMIMEType. Returns false if we
|
||||
* Create a decoder for the given aMIMEType. Returns null if we
|
||||
* were unable to create the decoder.
|
||||
*/
|
||||
PRBool CreateDecoder(const nsACString& aMIMEType);
|
||||
already_AddRefed<nsMediaDecoder> CreateDecoder(const nsACString& aMIMEType);
|
||||
|
||||
/**
|
||||
* Initialize a decoder as a clone of an existing decoder in another
|
||||
|
@ -298,7 +303,7 @@ protected:
|
|||
/**
|
||||
* Finish setting up the decoder after Load() has been called on it.
|
||||
*/
|
||||
nsresult FinishDecoderSetup();
|
||||
nsresult FinishDecoderSetup(nsMediaDecoder* aDecoder);
|
||||
|
||||
/**
|
||||
* Execute the initial steps of the load algorithm that ensure existing
|
||||
|
@ -371,6 +376,18 @@ protected:
|
|||
nsIChannel *aNewChannel,
|
||||
PRUint32 aFlags);
|
||||
|
||||
/**
|
||||
* Call this to reevaluate whether we should be holding a self-reference.
|
||||
*/
|
||||
void AddRemoveSelfReference();
|
||||
|
||||
/**
|
||||
* Alias for Release(), but using stdcall calling convention so on
|
||||
* platforms where Release has a strange calling convention (Windows)
|
||||
* we can still get a method pointer to this method.
|
||||
*/
|
||||
void DoRelease() { Release(); }
|
||||
|
||||
nsRefPtr<nsMediaDecoder> mDecoder;
|
||||
|
||||
// Holds a reference to the first channel we open to the media resource.
|
||||
|
@ -462,10 +479,8 @@ protected:
|
|||
// to raise the 'waiting' event as per 4.7.1.8 in HTML 5 specification.
|
||||
PRPackedBool mPlayingBeforeSeek;
|
||||
|
||||
// PR_TRUE if the video was paused before Freeze was called. This is checked
|
||||
// to ensure that the playstate doesn't change when the user goes Forward/Back
|
||||
// from the bfcache.
|
||||
PRPackedBool mPausedBeforeFreeze;
|
||||
// PR_TRUE iff this element is paused because the document is inactive
|
||||
PRPackedBool mPausedForInactiveDocument;
|
||||
|
||||
// PR_TRUE if we've reported a "waiting" event since the last
|
||||
// readyState change to HAVE_CURRENT_DATA.
|
||||
|
@ -499,4 +514,9 @@ protected:
|
|||
// PR_TRUE if we've played or completed a seek. We use this to determine
|
||||
// when the poster frame should be shown.
|
||||
PRPackedBool mHasPlayedOrSeeked;
|
||||
|
||||
// PR_TRUE if we've added a reference to ourselves to keep the element
|
||||
// alive while no-one is referencing it but the element may still fire
|
||||
// events of its own accord.
|
||||
PRPackedBool mHasSelfReference;
|
||||
};
|
||||
|
|
|
@ -40,7 +40,11 @@
|
|||
#define nsIFileControlElement_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
class nsAString;
|
||||
#include "nsTArray.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
class nsIFile;
|
||||
|
||||
// IID for the nsIFileControl interface
|
||||
#define NS_IFILECONTROLELEMENT_IID \
|
||||
|
@ -57,14 +61,23 @@ public:
|
|||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFILECONTROLELEMENT_IID)
|
||||
|
||||
/**
|
||||
* Gets filename to be uploaded when this control is submitted
|
||||
* Gets a readable string representing the list of files currently
|
||||
* selected by this control. This value might not be a valid file name
|
||||
* and should not be used for anything but displaying the filename to the
|
||||
* user.
|
||||
*/
|
||||
virtual void GetFileName(nsAString& aFileName) = 0;
|
||||
virtual void GetDisplayFileName(nsAString& aFileName) = 0;
|
||||
|
||||
/**
|
||||
* Sets filename to be uploaded when this control is submitted
|
||||
* Sets the list of filenames currently selected by this control.
|
||||
*/
|
||||
virtual void SetFileName(const nsAString& aFileName) = 0;
|
||||
virtual void SetFileNames(const nsTArray<nsString>& aFileNames) = 0;
|
||||
|
||||
/**
|
||||
* Gets a list of nsIFile objects for the files currently selected by
|
||||
* this control.
|
||||
*/
|
||||
virtual void GetFileArray(nsCOMArray<nsIFile>& aFiles) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIFileControlElement,
|
||||
|
|
|
@ -721,7 +721,7 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::ScrollIntoView(PRBool aTop)
|
||||
nsGenericHTMLElement::ScrollIntoView(PRBool aTop, PRUint8 optional_argc)
|
||||
{
|
||||
nsIDocument *document = GetCurrentDoc();
|
||||
|
||||
|
@ -735,6 +735,10 @@ nsGenericHTMLElement::ScrollIntoView(PRBool aTop)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!optional_argc) {
|
||||
aTop = PR_TRUE;
|
||||
}
|
||||
|
||||
PRIntn vpercent = aTop ? NS_PRESSHELL_SCROLL_TOP :
|
||||
NS_PRESSHELL_SCROLL_BOTTOM;
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ public:
|
|||
nsresult GetOffsetParent(nsIDOMElement** aOffsetParent);
|
||||
virtual nsresult GetInnerHTML(nsAString& aInnerHTML);
|
||||
virtual nsresult SetInnerHTML(const nsAString& aInnerHTML);
|
||||
nsresult ScrollIntoView(PRBool aTop);
|
||||
nsresult ScrollIntoView(PRBool aTop, PRUint8 optional_argc);
|
||||
// Declare Focus(), Blur(), GetTabIndex(), SetTabIndex(), GetSpellcheck(),
|
||||
// SetSpellcheck(), and GetDraggable() such that classes that inherit interfaces
|
||||
// with those methods properly override them
|
||||
|
|
|
@ -295,66 +295,23 @@ nsHTMLCanvasElement::ParseAttribute(PRInt32 aNamespaceID,
|
|||
// nsHTMLCanvasElement::toDataURL
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLCanvasElement::ToDataURL(nsAString& aDataURL)
|
||||
nsHTMLCanvasElement::ToDataURL(const nsAString& aType, const nsAString& aParams,
|
||||
PRUint8 optional_argc, nsAString& aDataURL)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsAXPCNativeCallContext *ncc = nsnull;
|
||||
rv = nsContentUtils::XPConnect()->
|
||||
GetCurrentNativeCallContext(&ncc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!ncc)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
JSContext *ctx = nsnull;
|
||||
|
||||
rv = ncc->GetJSContext(&ctx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 argc;
|
||||
jsval *argv = nsnull;
|
||||
|
||||
ncc->GetArgc(&argc);
|
||||
ncc->GetArgvPtr(&argv);
|
||||
|
||||
// do a trust check if this is a write-only canvas
|
||||
// or if we're trying to use the 2-arg form
|
||||
if ((mWriteOnly || argc >= 2) && !nsContentUtils::IsCallerTrustedForRead()) {
|
||||
if ((mWriteOnly || optional_argc >= 2) &&
|
||||
!nsContentUtils::IsCallerTrustedForRead()) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
// 0-arg case; convert to png
|
||||
if (argc == 0) {
|
||||
return ToDataURLImpl(NS_LITERAL_STRING("image/png"), EmptyString(), aDataURL);
|
||||
nsAutoString type(aType);
|
||||
|
||||
if (type.IsEmpty()) {
|
||||
type.AssignLiteral("image/png");
|
||||
}
|
||||
|
||||
JSAutoRequest ar(ctx);
|
||||
|
||||
// 1-arg case; convert to given mime type
|
||||
if (argc == 1) {
|
||||
if (!JSVAL_IS_STRING(argv[0]))
|
||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
JSString *type = JS_ValueToString(ctx, argv[0]);
|
||||
return ToDataURLImpl (nsDependentString(reinterpret_cast<PRUnichar*>((JS_GetStringChars(type)))),
|
||||
EmptyString(), aDataURL);
|
||||
}
|
||||
|
||||
// 2-arg case; trusted only (checked above), convert to mime type with params
|
||||
if (argc == 2) {
|
||||
if (!JSVAL_IS_STRING(argv[0]) || !JSVAL_IS_STRING(argv[1]))
|
||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
|
||||
JSString *type, *params;
|
||||
type = JS_ValueToString(ctx, argv[0]);
|
||||
params = JS_ValueToString(ctx, argv[1]);
|
||||
|
||||
return ToDataURLImpl (nsDependentString(reinterpret_cast<PRUnichar*>(JS_GetStringChars(type))),
|
||||
nsDependentString(reinterpret_cast<PRUnichar*>(JS_GetStringChars(params))),
|
||||
aDataURL);
|
||||
}
|
||||
|
||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
return ToDataURLImpl(type, aParams, aDataURL);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -192,24 +192,23 @@ class nsHTMLInputElementState : public nsISupports
|
|||
mValue = aValue;
|
||||
}
|
||||
|
||||
const nsString& GetFilename() {
|
||||
return mFilename;
|
||||
const nsTArray<nsString>& GetFilenames() {
|
||||
return mFilenames;
|
||||
}
|
||||
|
||||
void SetFilename(const nsAString &aFilename) {
|
||||
mFilename = aFilename;
|
||||
void SetFilenames(const nsTArray<nsString> &aFilenames) {
|
||||
mFilenames = aFilenames;
|
||||
}
|
||||
|
||||
nsHTMLInputElementState()
|
||||
: mValue()
|
||||
, mFilename()
|
||||
, mChecked(PR_FALSE)
|
||||
, mCheckedSet(PR_FALSE)
|
||||
{};
|
||||
|
||||
protected:
|
||||
nsString mValue;
|
||||
nsString mFilename;
|
||||
nsTArray<nsString> mFilenames;
|
||||
PRPackedBool mChecked;
|
||||
PRPackedBool mCheckedSet;
|
||||
};
|
||||
|
@ -298,8 +297,9 @@ public:
|
|||
NS_IMETHOD SetValueChanged(PRBool aValueChanged);
|
||||
|
||||
// nsIFileControlElement
|
||||
virtual void GetFileName(nsAString& aFileName);
|
||||
virtual void SetFileName(const nsAString& aFileName);
|
||||
virtual void GetDisplayFileName(nsAString& aFileName);
|
||||
virtual void GetFileArray(nsCOMArray<nsIFile> &aFile);
|
||||
virtual void SetFileNames(const nsTArray<nsString>& aFileNames);
|
||||
|
||||
// nsIRadioControlElement
|
||||
NS_IMETHOD RadioSetChecked(PRBool aNotify);
|
||||
|
@ -331,6 +331,17 @@ protected:
|
|||
nsITextControlFrame* aFrame,
|
||||
PRBool aUserInput);
|
||||
|
||||
void ClearFileNames() {
|
||||
nsTArray<nsString> fileNames;
|
||||
SetFileNames(fileNames);
|
||||
}
|
||||
|
||||
void SetSingleFileName(const nsAString& aFileName) {
|
||||
nsAutoTArray<nsString, 1> fileNames;
|
||||
fileNames.AppendElement(aFileName);
|
||||
SetFileNames(fileNames);
|
||||
}
|
||||
|
||||
nsresult SetIndeterminateInternal(PRBool aValue,
|
||||
PRBool aShouldInvalidate);
|
||||
|
||||
|
@ -404,11 +415,6 @@ protected:
|
|||
*/
|
||||
nsresult MaybeSubmitForm(nsPresContext* aPresContext);
|
||||
|
||||
/**
|
||||
* Get an nsIFile for the currently selected file in an file control.
|
||||
*/
|
||||
nsresult GetFile(nsIFile** aFile);
|
||||
|
||||
/**
|
||||
* Update mFileList with the currently selected file.
|
||||
*/
|
||||
|
@ -431,16 +437,16 @@ protected:
|
|||
*/
|
||||
char* mValue;
|
||||
/**
|
||||
* The value of the input if it is a file input. This is the filename used
|
||||
* when uploading a file. It is vital that this is kept separate from mValue
|
||||
* so that it won't be possible to 'leak' the value from a text-input to a
|
||||
* file-input. Additionally, the logic for this value is kept as simple as
|
||||
* possible to avoid accidental errors where the wrong filename is used.
|
||||
* Therefor the filename is always owned by this member, never by the frame.
|
||||
* Whenever the frame wants to change the filename it has to call
|
||||
* SetFileName to update this member.
|
||||
* The value of the input if it is a file input. This is the list of filenames
|
||||
* used when uploading a file. It is vital that this is kept separate from
|
||||
* mValue so that it won't be possible to 'leak' the value from a text-input
|
||||
* to a file-input. Additionally, the logic for this value is kept as simple
|
||||
* as possible to avoid accidental errors where the wrong filename is used.
|
||||
* Therefor the list of filenames is always owned by this member, never by
|
||||
* the frame. Whenever the frame wants to change the filename it has to call
|
||||
* SetFileNames to update this member.
|
||||
*/
|
||||
nsAutoPtr<nsString> mFileName;
|
||||
nsTArray<nsString> mFileNames;
|
||||
|
||||
nsRefPtr<nsDOMFileList> mFileList;
|
||||
};
|
||||
|
@ -537,9 +543,7 @@ nsHTMLInputElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
|
|||
}
|
||||
break;
|
||||
case NS_FORM_INPUT_FILE:
|
||||
if (mFileName) {
|
||||
it->mFileName = new nsString(*mFileName);
|
||||
}
|
||||
it->mFileNames = mFileNames;
|
||||
break;
|
||||
case NS_FORM_INPUT_RADIO:
|
||||
case NS_FORM_INPUT_CHECKBOX:
|
||||
|
@ -745,6 +749,7 @@ NS_IMPL_STRING_ATTR(nsHTMLInputElement, Align, align)
|
|||
NS_IMPL_STRING_ATTR(nsHTMLInputElement, Alt, alt)
|
||||
//NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Checked, checked)
|
||||
NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Disabled, disabled)
|
||||
NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Multiple, multiple)
|
||||
NS_IMPL_INT_ATTR(nsHTMLInputElement, MaxLength, maxlength)
|
||||
NS_IMPL_STRING_ATTR(nsHTMLInputElement, Name, name)
|
||||
NS_IMPL_BOOL_ATTR(nsHTMLInputElement, ReadOnly, readonly)
|
||||
|
@ -868,17 +873,17 @@ nsHTMLInputElement::GetValue(nsAString& aValue)
|
|||
|
||||
if (mType == NS_FORM_INPUT_FILE) {
|
||||
if (nsContentUtils::IsCallerTrustedForCapability("UniversalFileRead")) {
|
||||
if (mFileName) {
|
||||
aValue = *mFileName;
|
||||
if (!mFileNames.IsEmpty()) {
|
||||
aValue = mFileNames[0];
|
||||
}
|
||||
else {
|
||||
aValue.Truncate();
|
||||
}
|
||||
} else {
|
||||
// Just return the leaf name
|
||||
nsCOMPtr<nsIFile> file;
|
||||
GetFile(getter_AddRefs(file));
|
||||
if (!file || NS_FAILED(file->GetLeafName(aValue))) {
|
||||
nsCOMArray<nsIFile> files;
|
||||
GetFileArray(files);
|
||||
if (files.Count() == 0 || NS_FAILED(files[0]->GetLeafName(aValue))) {
|
||||
aValue.Truncate();
|
||||
}
|
||||
}
|
||||
|
@ -912,8 +917,11 @@ nsHTMLInputElement::SetValue(const nsAString& aValue)
|
|||
// UniversalFileRead privilege
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
SetSingleFileName(aValue);
|
||||
}
|
||||
else {
|
||||
ClearFileNames();
|
||||
}
|
||||
SetFileName(aValue);
|
||||
}
|
||||
else {
|
||||
SetValueInternal(aValue, nsnull, PR_FALSE);
|
||||
|
@ -922,6 +930,47 @@ nsHTMLInputElement::SetValue(const nsAString& aValue)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLInputElement::MozGetFileNameArray(PRUint32 *aLength, PRUnichar ***aFileNames)
|
||||
{
|
||||
if (!nsContentUtils::IsCallerTrustedForCapability("UniversalFileRead")) {
|
||||
// Since this function returns full paths it's important that normal pages
|
||||
// can't call it.
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
*aLength = mFileNames.Length();
|
||||
PRUnichar **ret =
|
||||
static_cast<PRUnichar **>(NS_Alloc(mFileNames.Length() * sizeof(PRUnichar*)));
|
||||
|
||||
for (PRUint32 i = 0; i < mFileNames.Length(); i++) {
|
||||
ret[i] = NS_strdup(mFileNames[i].get());
|
||||
}
|
||||
|
||||
*aFileNames = ret;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLInputElement::MozSetFileNameArray(const PRUnichar **aFileNames, PRUint32 aLength)
|
||||
{
|
||||
if (!nsContentUtils::IsCallerTrustedForCapability("UniversalFileRead")) {
|
||||
// setting the value of a "FILE" input widget requires the
|
||||
// UniversalFileRead privilege
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
nsTArray<nsString> fileNames(aLength);
|
||||
for (PRUint32 i = 0; i < aLength; ++i) {
|
||||
fileNames.AppendElement(aFileNames[i]);
|
||||
}
|
||||
|
||||
SetFileNames(fileNames);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLInputElement::SetUserInput(const nsAString& aValue)
|
||||
{
|
||||
|
@ -931,7 +980,7 @@ nsHTMLInputElement::SetUserInput(const nsAString& aValue)
|
|||
|
||||
if (mType == NS_FORM_INPUT_FILE)
|
||||
{
|
||||
SetFileName(aValue);
|
||||
SetSingleFileName(aValue);
|
||||
} else {
|
||||
SetValueInternal(aValue, nsnull, PR_TRUE);
|
||||
}
|
||||
|
@ -949,28 +998,36 @@ nsHTMLInputElement::TakeTextFrameValue(const nsAString& aValue)
|
|||
}
|
||||
|
||||
void
|
||||
nsHTMLInputElement::GetFileName(nsAString& aValue)
|
||||
nsHTMLInputElement::GetDisplayFileName(nsAString& aValue)
|
||||
{
|
||||
if (mFileName) {
|
||||
aValue = *mFileName;
|
||||
}
|
||||
else {
|
||||
aValue.Truncate();
|
||||
aValue.Truncate();
|
||||
for (PRUint32 i = 0; i < mFileNames.Length(); ++i) {
|
||||
if (i == 0) {
|
||||
aValue.Append(mFileNames[i]);
|
||||
}
|
||||
else {
|
||||
aValue.Append(NS_LITERAL_STRING(", ") + mFileNames[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLInputElement::SetFileName(const nsAString& aValue)
|
||||
nsHTMLInputElement::SetFileNames(const nsTArray<nsString>& aFileNames)
|
||||
{
|
||||
// No big deal if |new| fails, we simply won't submit the file
|
||||
mFileName = aValue.IsEmpty() ? nsnull : new nsString(aValue);
|
||||
|
||||
mFileNames = aFileNames;
|
||||
#if DEBUG
|
||||
for (PRUint32 i = 0; i < (PRUint32)aFileNames.Length(); ++i) {
|
||||
NS_ASSERTION(!aFileNames[i].IsEmpty(), "Empty file name");
|
||||
}
|
||||
#endif
|
||||
// No need to flush here, if there's no frame at this point we
|
||||
// don't need to force creation of one just to tell it about this
|
||||
// new value. We just want the display to update as needed.
|
||||
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
|
||||
if (formControlFrame) {
|
||||
formControlFrame->SetFormProperty(nsGkAtoms::value, aValue);
|
||||
nsAutoString readableValue;
|
||||
GetDisplayFileName(readableValue);
|
||||
formControlFrame->SetFormProperty(nsGkAtoms::value, readableValue);
|
||||
}
|
||||
|
||||
UpdateFileList();
|
||||
|
@ -978,32 +1035,37 @@ nsHTMLInputElement::SetFileName(const nsAString& aValue)
|
|||
SetValueChanged(PR_TRUE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLInputElement::GetFile(nsIFile** aFile)
|
||||
void
|
||||
nsHTMLInputElement::GetFileArray(nsCOMArray<nsIFile> &aFiles)
|
||||
{
|
||||
*aFile = nsnull;
|
||||
aFiles.Clear();
|
||||
|
||||
if (!mFileName || mType != NS_FORM_INPUT_FILE) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
if (mType != NS_FORM_INPUT_FILE) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = NS_ERROR_NOT_AVAILABLE;
|
||||
for (PRUint32 i = 0; i < mFileNames.Length(); ++i) {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
if (StringBeginsWith(mFileNames[i], NS_LITERAL_STRING("file:"),
|
||||
nsCaseInsensitiveStringComparator())) {
|
||||
// Converts the URL string into the corresponding nsIFile if possible.
|
||||
// A local file will be created if the URL string begins with file://.
|
||||
NS_GetFileFromURLSpec(NS_ConvertUTF16toUTF8(mFileNames[i]),
|
||||
getter_AddRefs(file));
|
||||
}
|
||||
|
||||
if (StringBeginsWith(*mFileName, NS_LITERAL_STRING("file:"),
|
||||
nsCaseInsensitiveStringComparator())) {
|
||||
// Converts the URL string into the corresponding nsIFile if possible.
|
||||
// A local file will be created if the URL string begins with file://.
|
||||
rv = NS_GetFileFromURLSpec(NS_ConvertUTF16toUTF8(*mFileName), aFile);
|
||||
if (!file) {
|
||||
// this is no "file://", try as local file
|
||||
nsCOMPtr<nsILocalFile> localFile;
|
||||
NS_NewLocalFile(mFileNames[i], PR_FALSE, getter_AddRefs(localFile));
|
||||
// Wish there was a better way to downcast an already_AddRefed
|
||||
file = dont_AddRef(static_cast<nsIFile*>(localFile.forget().get()));
|
||||
}
|
||||
|
||||
if (file) {
|
||||
aFiles.AppendObject(file);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(*aFile)) {
|
||||
// this is no "file://", try as local file
|
||||
nsCOMPtr<nsILocalFile> localFile;
|
||||
rv = NS_NewLocalFile(*mFileName, PR_FALSE, getter_AddRefs(localFile));
|
||||
NS_IF_ADDREF(*aFile = localFile);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -1012,12 +1074,10 @@ nsHTMLInputElement::UpdateFileList()
|
|||
if (mFileList) {
|
||||
mFileList->Clear();
|
||||
|
||||
if (mType == NS_FORM_INPUT_FILE && mFileName) {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
nsresult rv = GetFile(getter_AddRefs(file));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<nsDOMFile> domFile = new nsDOMFile(file);
|
||||
nsCOMArray<nsIFile> files;
|
||||
GetFileArray(files);
|
||||
for (PRUint32 i = 0; i < (PRUint32)files.Count(); ++i) {
|
||||
nsRefPtr<nsDOMFile> domFile = new nsDOMFile(files[i]);
|
||||
if (domFile) {
|
||||
if (!mFileList->Append(domFile)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2113,14 +2173,11 @@ nsHTMLInputElement::ParseAttribute(PRInt32 aNamespaceID,
|
|||
// makes assumptions about our frame based on mType, but we won't have
|
||||
// had time to recreate frames yet -- that happens later in the
|
||||
// SetAttr() process).
|
||||
if (newType == NS_FORM_INPUT_FILE) {
|
||||
// These calls aren't strictly needed any more since we'll never
|
||||
// confuse values and filenames. However they're there for backwards
|
||||
if (newType == NS_FORM_INPUT_FILE || mType == NS_FORM_INPUT_FILE) {
|
||||
// This call isn't strictly needed any more since we'll never
|
||||
// confuse values and filenames. However it's there for backwards
|
||||
// compat.
|
||||
SetFileName(EmptyString());
|
||||
SetValueInternal(EmptyString(), nsnull, PR_FALSE);
|
||||
} else if (mType == NS_FORM_INPUT_FILE) {
|
||||
SetFileName(EmptyString());
|
||||
ClearFileNames();
|
||||
}
|
||||
|
||||
mType = newType;
|
||||
|
@ -2471,7 +2528,7 @@ nsHTMLInputElement::Reset()
|
|||
case NS_FORM_INPUT_FILE:
|
||||
{
|
||||
// Resetting it to blank should not perform security check
|
||||
SetFileName(EmptyString());
|
||||
ClearFileNames();
|
||||
break;
|
||||
}
|
||||
// Value is the same as defaultValue for hidden inputs
|
||||
|
@ -2593,87 +2650,65 @@ nsHTMLInputElement::SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
|||
// Submit file if its input type=file and this encoding method accepts files
|
||||
//
|
||||
if (mType == NS_FORM_INPUT_FILE) {
|
||||
//
|
||||
// Open the file
|
||||
//
|
||||
nsCOMPtr<nsIFile> file;
|
||||
|
||||
rv = GetFile(getter_AddRefs(file));
|
||||
// Submit files
|
||||
|
||||
if (file) {
|
||||
nsCOMPtr<nsIMIMEService> MIMEService =
|
||||
do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMArray<nsIFile> files;
|
||||
GetFileArray(files);
|
||||
|
||||
for (PRUint32 i = 0; i < (PRUint32)files.Count(); ++i) {
|
||||
nsIFile* file = files[i];
|
||||
|
||||
//
|
||||
// Get the leaf path name (to be submitted as the value)
|
||||
//
|
||||
PRBool fileSent = PR_FALSE;
|
||||
|
||||
nsAutoString filename;
|
||||
rv = file->GetLeafName(filename);
|
||||
if (NS_FAILED(rv)) {
|
||||
filename.Truncate();
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !filename.IsEmpty()) {
|
||||
PRBool acceptsFiles = aFormSubmission->AcceptsFiles();
|
||||
|
||||
if (acceptsFiles) {
|
||||
//
|
||||
// Get content type
|
||||
//
|
||||
nsCOMPtr<nsIMIMEService> MIMEService =
|
||||
do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCAutoString contentType;
|
||||
rv = MIMEService->GetTypeFromFile(file, contentType);
|
||||
if (NS_FAILED(rv)) {
|
||||
contentType.AssignLiteral("application/octet-stream");
|
||||
}
|
||||
|
||||
//
|
||||
// Get input stream
|
||||
//
|
||||
nsCOMPtr<nsIInputStream> fileStream;
|
||||
rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream),
|
||||
file, -1, -1,
|
||||
nsIFileInputStream::CLOSE_ON_EOF |
|
||||
nsIFileInputStream::REOPEN_ON_REWIND);
|
||||
if (fileStream) {
|
||||
//
|
||||
// Create buffered stream (for efficiency)
|
||||
//
|
||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||
fileStream, 8192);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (bufferedStream) {
|
||||
//
|
||||
// Submit
|
||||
//
|
||||
aFormSubmission->AddNameFilePair(this, name, filename,
|
||||
bufferedStream, contentType,
|
||||
PR_FALSE);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
if (!filename.IsEmpty() && aFormSubmission->AcceptsFiles()) {
|
||||
// Get content type
|
||||
nsCAutoString contentType;
|
||||
rv = MIMEService->GetTypeFromFile(file, contentType);
|
||||
if (NS_FAILED(rv)) {
|
||||
contentType.AssignLiteral("application/octet-stream");
|
||||
}
|
||||
|
||||
//
|
||||
// Get input stream
|
||||
nsCOMPtr<nsIInputStream> fileStream;
|
||||
rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream),
|
||||
file, -1, -1,
|
||||
nsIFileInputStream::CLOSE_ON_EOF |
|
||||
nsIFileInputStream::REOPEN_ON_REWIND);
|
||||
if (fileStream) {
|
||||
// Create buffered stream (for efficiency)
|
||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||
fileStream, 8192);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Submit
|
||||
aFormSubmission->AddNameFilePair(this, name, filename,
|
||||
bufferedStream, contentType,
|
||||
PR_FALSE);
|
||||
fileSent = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fileSent) {
|
||||
// If we don't submit as a file, at least submit the truncated filename.
|
||||
//
|
||||
aFormSubmission->AddNameFilePair(this, name, filename,
|
||||
nsnull, NS_LITERAL_CSTRING("application/octet-stream"),
|
||||
PR_FALSE);
|
||||
return rv;
|
||||
} else {
|
||||
// Ignore error returns from GetLeafName. See bug 199053
|
||||
rv = NS_OK;
|
||||
nsnull, NS_LITERAL_CSTRING("application/octet-stream"),
|
||||
PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If we can't even make a truncated filename, submit empty string
|
||||
// rather than sending everything
|
||||
//
|
||||
aFormSubmission->AddNameFilePair(this, name, EmptyString(),
|
||||
nsnull, NS_LITERAL_CSTRING("application/octet-stream"),
|
||||
PR_FALSE);
|
||||
return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Submit
|
||||
|
@ -2740,13 +2775,13 @@ nsHTMLInputElement::SaveState()
|
|||
}
|
||||
case NS_FORM_INPUT_FILE:
|
||||
{
|
||||
if (mFileName) {
|
||||
if (!mFileNames.IsEmpty()) {
|
||||
inputState = new nsHTMLInputElementState();
|
||||
if (!inputState) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
inputState->SetFilename(*mFileName);
|
||||
inputState->SetFilenames(mFileNames);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2859,7 +2894,7 @@ nsHTMLInputElement::RestoreState(nsPresState* aState)
|
|||
}
|
||||
case NS_FORM_INPUT_FILE:
|
||||
{
|
||||
SetFileName(inputState->GetFilename());
|
||||
SetFileNames(inputState->GetFilenames());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,6 +96,48 @@ static PRLogModuleInfo* gMediaElementEventsLog;
|
|||
#define LOG_EVENT(type, msg)
|
||||
#endif
|
||||
|
||||
// Under certain conditions there may be no-one holding references to
|
||||
// a media element from script, DOM parent, etc, but the element may still
|
||||
// fire meaningful events in the future so we can't destroy it yet:
|
||||
// 1) If the element is delaying the load event (or would be, if it were
|
||||
// in a document), then events up to loadeddata or error could be fired,
|
||||
// so we need to stay alive.
|
||||
// 2) If the element is not paused and playback has not ended, then
|
||||
// we will (or might) play, sending timeupdate and ended events and possibly
|
||||
// audio output, so we need to stay alive.
|
||||
// 3) if the element is seeking then we will fire seeking events and possibly
|
||||
// start playing afterward, so we need to stay alive.
|
||||
// 4) If autoplay could start playback in this element (if we got enough data),
|
||||
// then we need to stay alive.
|
||||
// 5) if the element is currently loading and not suspended,
|
||||
// script might be waiting for progress events or a 'suspend' event,
|
||||
// so we need to stay alive. If we're already suspended then (all other
|
||||
// conditions being met) it's OK to just disappear without firing any more
|
||||
// events, since we have the freedom to remain suspended indefinitely. Note
|
||||
// that we could use this 'suspended' loophole to garbage-collect a suspended
|
||||
// element in case 4 even if it had 'autoplay' set, but we choose not to.
|
||||
// If someone throws away all references to a loading 'autoplay' element
|
||||
// sound should still eventually play.
|
||||
//
|
||||
// Media elements owned by inactive documents (i.e. documents not contained in any
|
||||
// document viewer) should never hold a self-reference because none of the
|
||||
// above conditions are allowed: the element will stop loading and playing
|
||||
// and never resume loading or playing unless its owner document changes to
|
||||
// an active document (which can only happen if there is an external reference
|
||||
// to the element).
|
||||
// Media elements with no owner doc should be able to hold a self-reference.
|
||||
// Something native must have created the element and may expect it to
|
||||
// stay alive to play.
|
||||
|
||||
// It's very important that any change in state which could change the value of
|
||||
// needSelfReference in AddRemoveSelfReference be followed by a call to
|
||||
// AddRemoveSelfReference before this element could die!
|
||||
// It's especially important if needSelfReference would change to 'true',
|
||||
// since if we neglect to add a self-reference, this element might be
|
||||
// garbage collected while there are still event listeners that should
|
||||
// receive events. If we neglect to remove the self-reference then the element
|
||||
// just lives longer than it needs to.
|
||||
|
||||
class nsMediaEvent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
|
@ -414,14 +456,21 @@ void nsHTMLMediaElement::AbortExistingLoads()
|
|||
DispatchSimpleEvent(NS_LITERAL_STRING("emptied"));
|
||||
}
|
||||
|
||||
// We may have changed mPaused, mAutoplaying, mNetworkState and other
|
||||
// things which can affect AddRemoveSelfReference
|
||||
AddRemoveSelfReference();
|
||||
|
||||
mIsRunningSelectResource = PR_FALSE;
|
||||
}
|
||||
|
||||
void nsHTMLMediaElement::NoSupportedMediaSourceError()
|
||||
{
|
||||
NS_ASSERTION(mDelayingLoadEvent, "Load event not delayed during source selection?");
|
||||
|
||||
mError = new nsHTMLMediaError(nsIDOMHTMLMediaError::MEDIA_ERR_SRC_NOT_SUPPORTED);
|
||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE;
|
||||
DispatchAsyncProgressEvent(NS_LITERAL_STRING("error"));
|
||||
// This clears mDelayingLoadEvent, so AddRemoveSelfReference will be called
|
||||
ChangeDelayLoadStatus(PR_FALSE);
|
||||
}
|
||||
|
||||
|
@ -465,16 +514,21 @@ static PRBool HasPotentialResource(nsIContent *aElement)
|
|||
|
||||
void nsHTMLMediaElement::SelectResource()
|
||||
{
|
||||
NS_ASSERTION(mDelayingLoadEvent, "Load event not delayed during resource selection?");
|
||||
|
||||
if (!HasPotentialResource(this)) {
|
||||
// While the media element has neither a src attribute nor any source
|
||||
// element children, wait. (This steps might wait forever.)
|
||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE;
|
||||
mLoadWaitStatus = WAITING_FOR_SRC_OR_SOURCE;
|
||||
// This clears mDelayingLoadEvent, so AddRemoveSelfReference will be called
|
||||
ChangeDelayLoadStatus(PR_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
|
||||
// Load event was delayed, and still is, so no need to call
|
||||
// AddRemoveSelfReference, since it must still be held
|
||||
DispatchAsyncProgressEvent(NS_LITERAL_STRING("loadstart"));
|
||||
|
||||
nsAutoString src;
|
||||
|
@ -508,8 +562,8 @@ void nsHTMLMediaElement::NotifyLoadError()
|
|||
|
||||
void nsHTMLMediaElement::LoadFromSourceChildren()
|
||||
{
|
||||
NS_ASSERTION(!IsInDoc() || mDelayingLoadEvent,
|
||||
"Should delay load event while loading in document");
|
||||
NS_ASSERTION(mDelayingLoadEvent,
|
||||
"Should delay load event (if in document) during load");
|
||||
while (PR_TRUE) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIURI> uri = GetNextSource();
|
||||
|
@ -534,8 +588,8 @@ void nsHTMLMediaElement::LoadFromSourceChildren()
|
|||
|
||||
nsresult nsHTMLMediaElement::LoadResource(nsIURI* aURI)
|
||||
{
|
||||
NS_ASSERTION(!IsInDoc() || mDelayingLoadEvent,
|
||||
"Should delay load event while loading in document");
|
||||
NS_ASSERTION(mDelayingLoadEvent,
|
||||
"Should delay load event (if in document) during load");
|
||||
nsresult rv;
|
||||
|
||||
if (mChannel) {
|
||||
|
@ -721,6 +775,10 @@ NS_IMETHODIMP nsHTMLMediaElement::SetCurrentTime(float aCurrentTime)
|
|||
// event if it changes the playback position as a result of the seek.
|
||||
LOG(PR_LOG_DEBUG, ("%p SetCurrentTime(%f) starting seek", this, aCurrentTime));
|
||||
nsresult rv = mDecoder->Seek(clampedTime);
|
||||
|
||||
// We changed whether we're seeking so we need to AddRemoveSelfReference
|
||||
AddRemoveSelfReference();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -752,6 +810,8 @@ NS_IMETHODIMP nsHTMLMediaElement::Pause()
|
|||
PRBool oldPaused = mPaused;
|
||||
mPaused = PR_TRUE;
|
||||
mAutoplaying = PR_FALSE;
|
||||
// We changed mPaused and mAutoplaying which can affect AddRemoveSelfReference
|
||||
AddRemoveSelfReference();
|
||||
|
||||
if (!oldPaused) {
|
||||
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("timeupdate"));
|
||||
|
@ -827,7 +887,7 @@ nsHTMLMediaElement::nsHTMLMediaElement(nsINodeInfo *aNodeInfo, PRBool aFromParse
|
|||
mMuted(PR_FALSE),
|
||||
mIsDoneAddingChildren(!aFromParser),
|
||||
mPlayingBeforeSeek(PR_FALSE),
|
||||
mPausedBeforeFreeze(PR_FALSE),
|
||||
mPausedForInactiveDocument(PR_FALSE),
|
||||
mWaitingFired(PR_FALSE),
|
||||
mIsBindingToTree(PR_FALSE),
|
||||
mIsRunningLoadMethod(PR_FALSE),
|
||||
|
@ -836,7 +896,8 @@ nsHTMLMediaElement::nsHTMLMediaElement(nsINodeInfo *aNodeInfo, PRBool aFromParse
|
|||
mIsRunningSelectResource(PR_FALSE),
|
||||
mSuspendedAfterFirstFrame(PR_FALSE),
|
||||
mAllowSuspendAfterFirstFrame(PR_TRUE),
|
||||
mHasPlayedOrSeeked(PR_FALSE)
|
||||
mHasPlayedOrSeeked(PR_FALSE),
|
||||
mHasSelfReference(PR_FALSE)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
if (!gMediaElementLog) {
|
||||
|
@ -848,10 +909,14 @@ nsHTMLMediaElement::nsHTMLMediaElement(nsINodeInfo *aNodeInfo, PRBool aFromParse
|
|||
#endif
|
||||
|
||||
RegisterFreezableElement();
|
||||
NotifyOwnerDocumentActivityChanged();
|
||||
}
|
||||
|
||||
nsHTMLMediaElement::~nsHTMLMediaElement()
|
||||
{
|
||||
NS_ASSERTION(!mHasSelfReference,
|
||||
"How can we be destroyed if we're still holding a self reference?");
|
||||
|
||||
UnregisterFreezableElement();
|
||||
if (mDecoder) {
|
||||
mDecoder->Shutdown();
|
||||
|
@ -905,8 +970,10 @@ NS_IMETHODIMP nsHTMLMediaElement::Play()
|
|||
if (mDecoder->IsEnded()) {
|
||||
SetCurrentTime(0);
|
||||
}
|
||||
nsresult rv = mDecoder->Play();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!mPausedForInactiveDocument) {
|
||||
nsresult rv = mDecoder->Play();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: If the playback has ended, then the user agent must set
|
||||
|
@ -928,6 +995,8 @@ NS_IMETHODIMP nsHTMLMediaElement::Play()
|
|||
|
||||
mPaused = PR_FALSE;
|
||||
mAutoplaying = PR_FALSE;
|
||||
// We changed mPaused and mAutoplaying which can affect AddRemoveSelfReference
|
||||
AddRemoveSelfReference();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -979,6 +1048,8 @@ nsresult nsHTMLMediaElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
if (mReadyState == nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) {
|
||||
NotifyAutoplayDataReady();
|
||||
}
|
||||
// This attribute can affect AddRemoveSelfReference
|
||||
AddRemoveSelfReference();
|
||||
} else if (aName == nsGkAtoms::autobuffer) {
|
||||
StopSuspendingAfterFirstFrame();
|
||||
}
|
||||
|
@ -987,6 +1058,22 @@ nsresult nsHTMLMediaElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsHTMLMediaElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttr,
|
||||
PRBool aNotify)
|
||||
{
|
||||
nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttr, aNotify);
|
||||
if (aNotify && aNameSpaceID == kNameSpaceID_None) {
|
||||
if (aAttr == nsGkAtoms::autoplay) {
|
||||
// This attribute can affect AddRemoveSelfReference
|
||||
AddRemoveSelfReference();
|
||||
}
|
||||
// We perhaps should stop loading if 'autobuffer' is being removed,
|
||||
// and we're buffering only because of 'autobuffer', but why bother?
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static PRBool IsAutoplayEnabled()
|
||||
{
|
||||
return nsContentUtils::GetBoolPref("media.autoplay.enabled");
|
||||
|
@ -1227,25 +1314,26 @@ void nsHTMLMediaElement::ShutdownMediaTypes()
|
|||
}
|
||||
}
|
||||
|
||||
PRBool nsHTMLMediaElement::CreateDecoder(const nsACString& aType)
|
||||
already_AddRefed<nsMediaDecoder>
|
||||
nsHTMLMediaElement::CreateDecoder(const nsACString& aType)
|
||||
{
|
||||
#ifdef MOZ_OGG
|
||||
if (IsOggType(aType)) {
|
||||
mDecoder = new nsOggDecoder();
|
||||
if (mDecoder && !mDecoder->Init(this)) {
|
||||
mDecoder = nsnull;
|
||||
nsRefPtr<nsOggDecoder> decoder = new nsOggDecoder();
|
||||
if (decoder && decoder->Init(this)) {
|
||||
return decoder.forget().get();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef MOZ_WAVE
|
||||
if (IsWaveType(aType)) {
|
||||
mDecoder = new nsWaveDecoder();
|
||||
if (mDecoder && !mDecoder->Init(this)) {
|
||||
mDecoder = nsnull;
|
||||
nsRefPtr<nsWaveDecoder> decoder = new nsWaveDecoder();
|
||||
if (decoder && decoder->Init(this)) {
|
||||
return decoder.forget().get();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return mDecoder != nsnull;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult nsHTMLMediaElement::InitializeDecoderAsClone(nsMediaDecoder* aOriginal)
|
||||
|
@ -1253,38 +1341,35 @@ nsresult nsHTMLMediaElement::InitializeDecoderAsClone(nsMediaDecoder* aOriginal)
|
|||
nsMediaStream* originalStream = aOriginal->GetCurrentStream();
|
||||
if (!originalStream)
|
||||
return NS_ERROR_FAILURE;
|
||||
mDecoder = aOriginal->Clone();
|
||||
if (!mDecoder)
|
||||
nsRefPtr<nsMediaDecoder> decoder = aOriginal->Clone();
|
||||
if (!decoder)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
LOG(PR_LOG_DEBUG, ("%p Cloned decoder %p from %p", this, mDecoder.get(), aOriginal));
|
||||
LOG(PR_LOG_DEBUG, ("%p Cloned decoder %p from %p", this, decoder.get(), aOriginal));
|
||||
|
||||
if (!mDecoder->Init(this)) {
|
||||
mDecoder = nsnull;
|
||||
if (!decoder->Init(this)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
float duration = aOriginal->GetDuration();
|
||||
if (duration >= 0) {
|
||||
mDecoder->SetDuration(PRInt64(NS_round(duration * 1000)));
|
||||
mDecoder->SetSeekable(aOriginal->GetSeekable());
|
||||
decoder->SetDuration(PRInt64(NS_round(duration * 1000)));
|
||||
decoder->SetSeekable(aOriginal->GetSeekable());
|
||||
}
|
||||
|
||||
nsMediaStream* stream = originalStream->CloneData(mDecoder);
|
||||
nsMediaStream* stream = originalStream->CloneData(decoder);
|
||||
if (!stream) {
|
||||
mDecoder = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
|
||||
|
||||
nsresult rv = mDecoder->Load(stream, nsnull);
|
||||
nsresult rv = decoder->Load(stream, nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
mDecoder = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
return FinishDecoderSetup();
|
||||
return FinishDecoderSetup(decoder);
|
||||
}
|
||||
|
||||
nsresult nsHTMLMediaElement::InitializeDecoderForChannel(nsIChannel *aChannel,
|
||||
|
@ -1293,20 +1378,21 @@ nsresult nsHTMLMediaElement::InitializeDecoderForChannel(nsIChannel *aChannel,
|
|||
nsCAutoString mimeType;
|
||||
aChannel->GetContentType(mimeType);
|
||||
|
||||
if (!CreateDecoder(mimeType))
|
||||
nsRefPtr<nsMediaDecoder> decoder = CreateDecoder(mimeType);
|
||||
if (!decoder) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, mDecoder.get(), mimeType.get()));
|
||||
LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, decoder.get(), mimeType.get()));
|
||||
|
||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
|
||||
|
||||
nsMediaStream* stream = nsMediaStream::Create(mDecoder, aChannel);
|
||||
nsMediaStream* stream = nsMediaStream::Create(decoder, aChannel);
|
||||
if (!stream)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv = mDecoder->Load(stream, aListener);
|
||||
nsresult rv = decoder->Load(stream, aListener);
|
||||
if (NS_FAILED(rv)) {
|
||||
mDecoder = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -1314,18 +1400,28 @@ nsresult nsHTMLMediaElement::InitializeDecoderForChannel(nsIChannel *aChannel,
|
|||
// which owns the channel.
|
||||
mChannel = nsnull;
|
||||
|
||||
return FinishDecoderSetup();
|
||||
return FinishDecoderSetup(decoder);
|
||||
}
|
||||
|
||||
nsresult nsHTMLMediaElement::FinishDecoderSetup()
|
||||
nsresult nsHTMLMediaElement::FinishDecoderSetup(nsMediaDecoder* aDecoder)
|
||||
{
|
||||
mDecoder = aDecoder;
|
||||
|
||||
// The new stream has not been suspended by us.
|
||||
mPausedForInactiveDocument = PR_FALSE;
|
||||
// But we may want to suspend it now.
|
||||
// This will also do an AddRemoveSelfReference.
|
||||
NotifyOwnerDocumentActivityChanged();
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
mDecoder->SetVolume(mMuted ? 0.0 : mVolume);
|
||||
|
||||
if (!mPaused) {
|
||||
SetPlayedOrSeeked(PR_TRUE);
|
||||
rv = mDecoder->Play();
|
||||
if (!mPausedForInactiveDocument) {
|
||||
rv = mDecoder->Play();
|
||||
}
|
||||
}
|
||||
|
||||
mBegun = PR_TRUE;
|
||||
|
@ -1393,6 +1489,7 @@ void nsHTMLMediaElement::ResourceLoaded()
|
|||
{
|
||||
mBegun = PR_FALSE;
|
||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
|
||||
AddRemoveSelfReference();
|
||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA);
|
||||
// The download has stopped
|
||||
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("suspend"));
|
||||
|
@ -1404,6 +1501,7 @@ void nsHTMLMediaElement::NetworkError()
|
|||
mBegun = PR_FALSE;
|
||||
DispatchAsyncProgressEvent(NS_LITERAL_STRING("error"));
|
||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_EMPTY;
|
||||
AddRemoveSelfReference();
|
||||
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("emptied"));
|
||||
ChangeDelayLoadStatus(PR_FALSE);
|
||||
}
|
||||
|
@ -1414,6 +1512,7 @@ void nsHTMLMediaElement::DecodeError()
|
|||
mBegun = PR_FALSE;
|
||||
DispatchAsyncProgressEvent(NS_LITERAL_STRING("error"));
|
||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_EMPTY;
|
||||
AddRemoveSelfReference();
|
||||
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("emptied"));
|
||||
ChangeDelayLoadStatus(PR_FALSE);
|
||||
}
|
||||
|
@ -1421,6 +1520,9 @@ void nsHTMLMediaElement::DecodeError()
|
|||
void nsHTMLMediaElement::PlaybackEnded()
|
||||
{
|
||||
NS_ASSERTION(mDecoder->IsEnded(), "Decoder fired ended, but not in ended state");
|
||||
// We changed the state of IsPlaybackEnded which can affect AddRemoveSelfReference
|
||||
AddRemoveSelfReference();
|
||||
|
||||
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("ended"));
|
||||
}
|
||||
|
||||
|
@ -1434,12 +1536,15 @@ void nsHTMLMediaElement::SeekCompleted()
|
|||
mPlayingBeforeSeek = PR_FALSE;
|
||||
SetPlayedOrSeeked(PR_TRUE);
|
||||
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("seeked"));
|
||||
// We changed whether we're seeking so we need to AddRemoveSelfReference
|
||||
AddRemoveSelfReference();
|
||||
}
|
||||
|
||||
void nsHTMLMediaElement::DownloadSuspended()
|
||||
{
|
||||
if (mBegun) {
|
||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
|
||||
AddRemoveSelfReference();
|
||||
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("suspend"));
|
||||
}
|
||||
}
|
||||
|
@ -1448,6 +1553,7 @@ void nsHTMLMediaElement::DownloadResumed()
|
|||
{
|
||||
if (mBegun) {
|
||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
|
||||
AddRemoveSelfReference();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1578,13 +1684,21 @@ void nsHTMLMediaElement::ChangeReadyState(nsMediaReadyState aState)
|
|||
}
|
||||
}
|
||||
|
||||
PRBool nsHTMLMediaElement::CanActivateAutoplay()
|
||||
{
|
||||
return mAutoplaying &&
|
||||
mPaused &&
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay) &&
|
||||
mAutoplayEnabled;
|
||||
}
|
||||
|
||||
void nsHTMLMediaElement::NotifyAutoplayDataReady()
|
||||
{
|
||||
if (mAutoplaying &&
|
||||
mPaused &&
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay) &&
|
||||
mAutoplayEnabled) {
|
||||
if (CanActivateAutoplay()) {
|
||||
mPaused = PR_FALSE;
|
||||
// We changed mPaused which can affect AddRemoveSelfReference
|
||||
AddRemoveSelfReference();
|
||||
|
||||
if (mDecoder) {
|
||||
SetPlayedOrSeeked(PR_TRUE);
|
||||
mDecoder->Play();
|
||||
|
@ -1685,7 +1799,7 @@ PRBool nsHTMLMediaElement::IsPotentiallyPlaying() const
|
|||
// TODO:
|
||||
// playback has not stopped due to errors,
|
||||
// and the element has not paused for user interaction
|
||||
return
|
||||
return
|
||||
!mPaused &&
|
||||
(mReadyState == nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA ||
|
||||
mReadyState == nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA) &&
|
||||
|
@ -1714,38 +1828,61 @@ void nsHTMLMediaElement::UpdateMediaSize(nsIntSize size)
|
|||
mMediaSize = size;
|
||||
}
|
||||
|
||||
void nsHTMLMediaElement::DestroyContent()
|
||||
void nsHTMLMediaElement::NotifyOwnerDocumentActivityChanged()
|
||||
{
|
||||
if (mDecoder) {
|
||||
mDecoder->Shutdown();
|
||||
mDecoder = nsnull;
|
||||
nsIDocument* ownerDoc = GetOwnerDoc();
|
||||
// Don't pause if we have no ownerDoc. Something native must have created
|
||||
// us and be expecting us to work without a document.
|
||||
PRBool pauseForInactiveDocument =
|
||||
ownerDoc && (!ownerDoc->IsActive() || !ownerDoc->IsVisible());
|
||||
|
||||
if (pauseForInactiveDocument != mPausedForInactiveDocument) {
|
||||
mPausedForInactiveDocument = pauseForInactiveDocument;
|
||||
if (mDecoder) {
|
||||
if (pauseForInactiveDocument) {
|
||||
mDecoder->Pause();
|
||||
mDecoder->Suspend();
|
||||
} else {
|
||||
mDecoder->Resume();
|
||||
if (IsPotentiallyPlaying()) {
|
||||
mDecoder->Play();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mChannel) {
|
||||
mChannel->Cancel(NS_BINDING_ABORTED);
|
||||
mChannel = nsnull;
|
||||
}
|
||||
nsGenericHTMLElement::DestroyContent();
|
||||
|
||||
AddRemoveSelfReference();
|
||||
}
|
||||
|
||||
void nsHTMLMediaElement::Freeze()
|
||||
void nsHTMLMediaElement::AddRemoveSelfReference()
|
||||
{
|
||||
mPausedBeforeFreeze = mPaused;
|
||||
if (!mPaused) {
|
||||
Pause();
|
||||
}
|
||||
if (mDecoder) {
|
||||
mDecoder->Suspend();
|
||||
}
|
||||
}
|
||||
// XXX we could release earlier here in many situations if we examined
|
||||
// which event listeners are attached. Right now we assume there is a
|
||||
// potential listener for every event. We would also have to keep the
|
||||
// element alive if it was playing and producing audio output --- right now
|
||||
// that's covered by the !mPaused check.
|
||||
nsIDocument* ownerDoc = GetOwnerDoc();
|
||||
|
||||
void nsHTMLMediaElement::Thaw()
|
||||
{
|
||||
if (!mPausedBeforeFreeze) {
|
||||
Play();
|
||||
}
|
||||
// See the comment at the top of this file for the explanation of this
|
||||
// boolean expression.
|
||||
PRBool needSelfReference = (!ownerDoc || ownerDoc->IsActive()) &&
|
||||
(mDelayingLoadEvent ||
|
||||
(!mPaused && mDecoder && !mDecoder->IsEnded()) ||
|
||||
(mDecoder && mDecoder->IsSeeking()) ||
|
||||
CanActivateAutoplay() ||
|
||||
mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING);
|
||||
|
||||
if (mDecoder) {
|
||||
mDecoder->Resume();
|
||||
if (needSelfReference != mHasSelfReference) {
|
||||
mHasSelfReference = needSelfReference;
|
||||
if (needSelfReference) {
|
||||
NS_ADDREF(this);
|
||||
} else {
|
||||
// Dispatch Release asynchronously so that we don't destroy this object
|
||||
// inside a call stack of method calls on this object
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NEW_RUNNABLE_METHOD(nsHTMLMediaElement, this, DoRelease);
|
||||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1848,6 +1985,9 @@ void nsHTMLMediaElement::ChangeDelayLoadStatus(PRBool aDelay) {
|
|||
mLoadBlockedDoc->UnblockOnload(PR_FALSE);
|
||||
mLoadBlockedDoc = nsnull;
|
||||
}
|
||||
|
||||
// We changed mDelayingLoadEvent which can affect AddRemoveSelfReference
|
||||
AddRemoveSelfReference();
|
||||
}
|
||||
|
||||
already_AddRefed<nsILoadGroup> nsHTMLMediaElement::GetDocumentLoadGroup()
|
||||
|
|
|
@ -1945,3 +1945,36 @@ nsHTMLOptionCollection::GetSelect(nsIDOMHTMLSelectElement **aReturn)
|
|||
NS_IF_ADDREF(*aReturn = mSelect);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLOptionCollection::Add(nsIDOMHTMLOptionElement *aOption,
|
||||
PRInt32 aIndex, PRUint8 optional_argc)
|
||||
{
|
||||
if (!aOption) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (aIndex < -1) {
|
||||
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
||||
}
|
||||
|
||||
if (!mSelect) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
PRUint32 length;
|
||||
GetLength(&length);
|
||||
|
||||
if (optional_argc == 0 || aIndex == -1 || aIndex > (PRInt32)length) {
|
||||
// IE appends in these cases
|
||||
aIndex = length;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> beforeNode;
|
||||
Item(aIndex, getter_AddRefs(beforeNode));
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLOptionElement> beforeElement =
|
||||
do_QueryInterface(beforeNode);
|
||||
|
||||
return mSelect->Add(aOption, beforeElement);
|
||||
}
|
||||
|
|
|
@ -139,6 +139,8 @@ _TEST_FILES = test_bug589.html \
|
|||
test_bug514856.html \
|
||||
bug514856_iframe.html \
|
||||
test_bug519987.html \
|
||||
test_bug523771.html \
|
||||
form_submit_server.sjs \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
const CC = Components.Constructor;
|
||||
const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
|
||||
"nsIBinaryInputStream",
|
||||
"setInputStream");
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
var bodyStream = new BinaryInputStream(request.bodyInputStream);
|
||||
var bodyBytes = [];
|
||||
var result = [];
|
||||
while ((bodyAvail = bodyStream.available()) > 0)
|
||||
Array.prototype.push.apply(bodyBytes, bodyStream.readByteArray(bodyAvail));
|
||||
|
||||
if (request.method == "POST") {
|
||||
// assume UTF8 for now
|
||||
var requestBody = decodeURIComponent(
|
||||
escape(String.fromCharCode.apply(null, bodyBytes)));
|
||||
|
||||
var contentTypeParams = {};
|
||||
request.getHeader("Content-Type").split(/\s*\;\s*/).forEach(function(s) {
|
||||
if (s.indexOf('=') >= 0) {
|
||||
let [name, value] = s.split('=');
|
||||
contentTypeParams[name] = value;
|
||||
}
|
||||
else {
|
||||
contentTypeParams[''] = s;
|
||||
}
|
||||
});
|
||||
|
||||
if (contentTypeParams[''] == "multipart/form-data") {
|
||||
requestBody.split("--" + contentTypeParams.boundary).slice(1, -1).forEach(function (s) {
|
||||
|
||||
let headers = {};
|
||||
headerEnd = s.indexOf("\r\n\r\n");
|
||||
s.substr(2, headerEnd-2).split("\r\n").forEach(function(s) {
|
||||
let [name, value] = s.split(': ');
|
||||
headers[name] = value;
|
||||
});
|
||||
result.push({ headers: headers, body: s.substring(headerEnd + 4, s.length - 2)});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Send response body
|
||||
response.setHeader("Content-Type", "text/plain", false);
|
||||
response.write(JSON.stringify(result));
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=523771
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 523771</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=523771">Mozilla Bug 523771</a>
|
||||
<p id="display"></p>
|
||||
<iframe name="target_iframe" id="target_iframe"></iframe>
|
||||
<form action="form_submit_server.sjs" target="target_iframe" id="form"
|
||||
method="POST" enctype="multipart/form-data">
|
||||
<input id=singleFile name=singleFile type=file>
|
||||
<input id=multiFile name=multiFile type=file multiple>
|
||||
</form>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
var filesToKill = [];
|
||||
singleFileInput = document.getElementById('singleFile');
|
||||
multiFileInput = document.getElementById('multiFile');
|
||||
var input1File = { name: "523771_file1", type: null, body: "file1 contents"};
|
||||
var input2Files =
|
||||
[{ name: "523771_file2", type: null, body: "second file contents" },
|
||||
{ name: "523771_file3.txt", type: "text/plain", body: "123456" },
|
||||
{ name: "523771_file4.html", type: "text/html", body: "<html>content</html>" }
|
||||
];
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function setFileInputs () {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
f = createFileWithData(input1File.name, input1File.body);
|
||||
singleFileInput.mozSetFileNameArray([f.path], 1);
|
||||
|
||||
var input2FileNames = [];
|
||||
for each (file in input2Files) {
|
||||
f = createFileWithData(file.name, file.body);
|
||||
input2FileNames.push(f.path);
|
||||
}
|
||||
multiFileInput.mozSetFileNameArray(input2FileNames, input2FileNames.length);
|
||||
}
|
||||
|
||||
function createFileWithData(fileName, fileData) {
|
||||
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Components.interfaces.nsIProperties);
|
||||
var testFile = dirSvc.get("ProfD", Components.interfaces.nsIFile);
|
||||
testFile.append(fileName);
|
||||
var outStream = Components.
|
||||
classes["@mozilla.org/network/file-output-stream;1"].
|
||||
createInstance(Components.interfaces.nsIFileOutputStream);
|
||||
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
|
||||
0666, 0);
|
||||
outStream.write(fileData, fileData.length);
|
||||
outStream.close();
|
||||
|
||||
filesToKill.push(testFile);
|
||||
|
||||
return testFile;
|
||||
}
|
||||
|
||||
function cleanupFiles() {
|
||||
singleFileInput.value = "";
|
||||
multiFileInput.value = "";
|
||||
filesToKill.forEach(
|
||||
function (testFile) {
|
||||
try {
|
||||
testFile.remove(false);
|
||||
} catch (e) {}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
is(singleFileInput.files.length, 0, "single-file .files.length"); // bug 524421
|
||||
is(multiFileInput.files.length, 0, "multi-file .files.length"); // bug 524421
|
||||
|
||||
setFileInputs();
|
||||
|
||||
is(singleFileInput.multiple, false, "single-file input .multiple");
|
||||
is(multiFileInput.multiple, true, "multi-file input .multiple");
|
||||
is(singleFileInput.value, input1File.name, "single-file input .value");
|
||||
is(multiFileInput.value, input2Files[0].name, "multi-file input .value");
|
||||
is(singleFileInput.files[0].name, input1File.name, "single-file input .files[n].name");
|
||||
is(singleFileInput.files[0].size, input1File.body.length, "single-file input .files[n].size");
|
||||
is(singleFileInput.files[0].mediaType, input1File.type, "single-file input .files[n].mediaType");
|
||||
for(i = 0; i < input2Files.length; ++i) {
|
||||
is(multiFileInput.files[i].name, input2Files[i].name, "multi-file input .files[n].name");
|
||||
is(multiFileInput.files[i].size, input2Files[i].body.length, "multi-file input .files[n].size");
|
||||
is(multiFileInput.files[i].mediaType, input2Files[i].type, "multi-file input .files[n].mediaType");
|
||||
}
|
||||
|
||||
document.getElementById('form').submit();
|
||||
iframe = document.getElementById('target_iframe');
|
||||
iframe.onload = function() {
|
||||
response = JSON.parse(iframe.contentDocument.documentElement.textContent);
|
||||
is(response[0].headers["Content-Disposition"],
|
||||
"form-data; name=\"singleFile\"; filename=\"" + input1File.name +
|
||||
"\"",
|
||||
"singleFile Content-Disposition");
|
||||
is(response[0].headers["Content-Type"], input1File.type || "application/octet-stream",
|
||||
"singleFile Content-Type");
|
||||
is(response[0].body, input1File.body, "singleFile body");
|
||||
|
||||
for(i = 0; i < input2Files.length; ++i) {
|
||||
is(response[i + 1].headers["Content-Disposition"],
|
||||
"form-data; name=\"multiFile\"; filename=\"" + input2Files[i].name +
|
||||
"\"",
|
||||
"multiFile Content-Disposition");
|
||||
is(response[i + 1].headers["Content-Type"], input2Files[i].type || "application/octet-stream",
|
||||
"multiFile Content-Type");
|
||||
is(response[i + 1].body, input2Files[i].body, "multiFile body");
|
||||
}
|
||||
|
||||
cleanupFiles();
|
||||
|
||||
is(singleFileInput.files.length, 0, "single-file .files.length"); // bug 524421
|
||||
is(multiFileInput.files.length, 0, "multi-file .files.length"); // bug 524421
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -465,6 +465,8 @@ nsMediaCacheStream::BlockList::NotifyBlockSwapped(PRInt32 aBlockIndex1,
|
|||
e1Prev = e1->mPrevBlock;
|
||||
e1Next = e1->mNextBlock;
|
||||
mEntries.RemoveEntry(aBlockIndex1);
|
||||
// Refresh pointer after hashtable mutation.
|
||||
e2 = mEntries.GetEntry(aBlockIndex2);
|
||||
}
|
||||
if (e2) {
|
||||
e2Prev = e2->mPrevBlock;
|
||||
|
@ -973,263 +975,297 @@ nsMediaCache::PredictNextUseForIncomingData(nsMediaCacheStream* aStream)
|
|||
PR_MIN(millisecondsAhead, PR_INT32_MAX));
|
||||
}
|
||||
|
||||
enum StreamAction { NONE, SEEK, RESUME, SUSPEND };
|
||||
|
||||
void
|
||||
nsMediaCache::Update()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
nsAutoMonitor mon(mMonitor);
|
||||
mUpdateQueued = PR_FALSE;
|
||||
// The action to use for each stream. We store these so we can make
|
||||
// decisions while holding the cache lock but implement those decisions
|
||||
// without holding the cache lock, since we need to call out to
|
||||
// stream, decoder and element code.
|
||||
nsAutoTArray<StreamAction,10> actions;
|
||||
|
||||
{
|
||||
nsAutoMonitor mon(mMonitor);
|
||||
mUpdateQueued = PR_FALSE;
|
||||
#ifdef DEBUG
|
||||
mInUpdate = PR_TRUE;
|
||||
mInUpdate = PR_TRUE;
|
||||
#endif
|
||||
|
||||
PRInt32 maxBlocks = GetMaxBlocks();
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
PRInt32 maxBlocks = GetMaxBlocks();
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
|
||||
PRInt32 freeBlockCount = mFreeBlocks.GetCount();
|
||||
// Try to trim back the cache to its desired maximum size. The cache may
|
||||
// have overflowed simply due to data being received when we have
|
||||
// no blocks in the main part of the cache that are free or lower
|
||||
// priority than the new data. The cache can also be overflowing because
|
||||
// the media.cache_size preference was reduced.
|
||||
// First, figure out what the least valuable block in the cache overflow
|
||||
// is. We don't want to replace any blocks in the main part of the
|
||||
// cache whose expected time of next use is earlier or equal to that.
|
||||
// If we allow that, we can effectively end up discarding overflowing
|
||||
// blocks (by moving an overflowing block to the main part of the cache,
|
||||
// and then overwriting it with another overflowing block), and we try
|
||||
// to avoid that since it requires HTTP seeks.
|
||||
// We also use this loop to eliminate overflowing blocks from
|
||||
// freeBlockCount.
|
||||
TimeDuration latestPredictedUseForOverflow = 0;
|
||||
for (PRInt32 blockIndex = mIndex.Length() - 1; blockIndex >= maxBlocks;
|
||||
--blockIndex) {
|
||||
if (IsBlockFree(blockIndex)) {
|
||||
// Don't count overflowing free blocks in our free block count
|
||||
--freeBlockCount;
|
||||
continue;
|
||||
}
|
||||
TimeDuration predictedUse = PredictNextUse(now, blockIndex);
|
||||
latestPredictedUseForOverflow = PR_MAX(latestPredictedUseForOverflow, predictedUse);
|
||||
}
|
||||
|
||||
// Now try to move overflowing blocks to the main part of the cache.
|
||||
for (PRInt32 blockIndex = mIndex.Length() - 1; blockIndex >= maxBlocks;
|
||||
--blockIndex) {
|
||||
if (IsBlockFree(blockIndex))
|
||||
continue;
|
||||
|
||||
Block* block = &mIndex[blockIndex];
|
||||
// Try to relocate the block close to other blocks for the first stream.
|
||||
// There is no point in trying to make it close to other blocks in
|
||||
// *all* the streams it might belong to.
|
||||
PRInt32 destinationBlockIndex =
|
||||
FindReusableBlock(now, block->mOwners[0].mStream,
|
||||
block->mOwners[0].mStreamBlock, maxBlocks);
|
||||
if (destinationBlockIndex < 0) {
|
||||
// Nowhere to place this overflow block. We won't be able to
|
||||
// place any more overflow blocks.
|
||||
break;
|
||||
PRInt32 freeBlockCount = mFreeBlocks.GetCount();
|
||||
// Try to trim back the cache to its desired maximum size. The cache may
|
||||
// have overflowed simply due to data being received when we have
|
||||
// no blocks in the main part of the cache that are free or lower
|
||||
// priority than the new data. The cache can also be overflowing because
|
||||
// the media.cache_size preference was reduced.
|
||||
// First, figure out what the least valuable block in the cache overflow
|
||||
// is. We don't want to replace any blocks in the main part of the
|
||||
// cache whose expected time of next use is earlier or equal to that.
|
||||
// If we allow that, we can effectively end up discarding overflowing
|
||||
// blocks (by moving an overflowing block to the main part of the cache,
|
||||
// and then overwriting it with another overflowing block), and we try
|
||||
// to avoid that since it requires HTTP seeks.
|
||||
// We also use this loop to eliminate overflowing blocks from
|
||||
// freeBlockCount.
|
||||
TimeDuration latestPredictedUseForOverflow = 0;
|
||||
for (PRInt32 blockIndex = mIndex.Length() - 1; blockIndex >= maxBlocks;
|
||||
--blockIndex) {
|
||||
if (IsBlockFree(blockIndex)) {
|
||||
// Don't count overflowing free blocks in our free block count
|
||||
--freeBlockCount;
|
||||
continue;
|
||||
}
|
||||
TimeDuration predictedUse = PredictNextUse(now, blockIndex);
|
||||
latestPredictedUseForOverflow = PR_MAX(latestPredictedUseForOverflow, predictedUse);
|
||||
}
|
||||
|
||||
if (IsBlockFree(destinationBlockIndex) ||
|
||||
PredictNextUse(now, destinationBlockIndex) > latestPredictedUseForOverflow) {
|
||||
// Reuse blocks in the main part of the cache that are less useful than
|
||||
// the least useful overflow blocks
|
||||
char buf[BLOCK_SIZE];
|
||||
nsresult rv = ReadCacheFileAllBytes(blockIndex*BLOCK_SIZE, buf, sizeof(buf));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = WriteCacheFile(destinationBlockIndex*BLOCK_SIZE, buf, BLOCK_SIZE);
|
||||
// Now try to move overflowing blocks to the main part of the cache.
|
||||
for (PRInt32 blockIndex = mIndex.Length() - 1; blockIndex >= maxBlocks;
|
||||
--blockIndex) {
|
||||
if (IsBlockFree(blockIndex))
|
||||
continue;
|
||||
|
||||
Block* block = &mIndex[blockIndex];
|
||||
// Try to relocate the block close to other blocks for the first stream.
|
||||
// There is no point in trying to make it close to other blocks in
|
||||
// *all* the streams it might belong to.
|
||||
PRInt32 destinationBlockIndex =
|
||||
FindReusableBlock(now, block->mOwners[0].mStream,
|
||||
block->mOwners[0].mStreamBlock, maxBlocks);
|
||||
if (destinationBlockIndex < 0) {
|
||||
// Nowhere to place this overflow block. We won't be able to
|
||||
// place any more overflow blocks.
|
||||
break;
|
||||
}
|
||||
|
||||
if (IsBlockFree(destinationBlockIndex) ||
|
||||
PredictNextUse(now, destinationBlockIndex) > latestPredictedUseForOverflow) {
|
||||
// Reuse blocks in the main part of the cache that are less useful than
|
||||
// the least useful overflow blocks
|
||||
char buf[BLOCK_SIZE];
|
||||
nsresult rv = ReadCacheFileAllBytes(blockIndex*BLOCK_SIZE, buf, sizeof(buf));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// We successfully copied the file data.
|
||||
LOG(PR_LOG_DEBUG, ("Swapping blocks %d and %d (trimming cache)",
|
||||
blockIndex, destinationBlockIndex));
|
||||
// Swapping the block metadata here lets us maintain the
|
||||
// correct positions in the linked lists
|
||||
SwapBlocks(blockIndex, destinationBlockIndex);
|
||||
} else {
|
||||
// If the write fails we may have corrupted the destination
|
||||
// block. Free it now.
|
||||
rv = WriteCacheFile(destinationBlockIndex*BLOCK_SIZE, buf, BLOCK_SIZE);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// We successfully copied the file data.
|
||||
LOG(PR_LOG_DEBUG, ("Swapping blocks %d and %d (trimming cache)",
|
||||
blockIndex, destinationBlockIndex));
|
||||
// Swapping the block metadata here lets us maintain the
|
||||
// correct positions in the linked lists
|
||||
SwapBlocks(blockIndex, destinationBlockIndex);
|
||||
} else {
|
||||
// If the write fails we may have corrupted the destination
|
||||
// block. Free it now.
|
||||
LOG(PR_LOG_DEBUG, ("Released block %d (trimming cache)",
|
||||
destinationBlockIndex));
|
||||
FreeBlock(destinationBlockIndex);
|
||||
}
|
||||
// Free the overflowing block even if the copy failed.
|
||||
LOG(PR_LOG_DEBUG, ("Released block %d (trimming cache)",
|
||||
destinationBlockIndex));
|
||||
FreeBlock(destinationBlockIndex);
|
||||
blockIndex));
|
||||
FreeBlock(blockIndex);
|
||||
}
|
||||
// Free the overflowing block even if the copy failed.
|
||||
LOG(PR_LOG_DEBUG, ("Released block %d (trimming cache)",
|
||||
blockIndex));
|
||||
FreeBlock(blockIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Try chopping back the array of cache entries and the cache file.
|
||||
Truncate();
|
||||
// Try chopping back the array of cache entries and the cache file.
|
||||
Truncate();
|
||||
|
||||
// Count the blocks allocated for readahead of non-seekable streams
|
||||
// (these blocks can't be freed but we don't want them to monopolize the
|
||||
// cache)
|
||||
PRInt32 nonSeekableReadaheadBlockCount = 0;
|
||||
for (PRUint32 i = 0; i < mStreams.Length(); ++i) {
|
||||
nsMediaCacheStream* stream = mStreams[i];
|
||||
if (!stream->mIsSeekable) {
|
||||
nonSeekableReadaheadBlockCount += stream->mReadaheadBlocks.GetCount();
|
||||
}
|
||||
}
|
||||
|
||||
// If freeBlockCount is zero, then compute the latest of
|
||||
// the predicted next-uses for all blocks
|
||||
TimeDuration latestNextUse;
|
||||
if (freeBlockCount == 0) {
|
||||
PRInt32 reusableBlock = FindReusableBlock(now, nsnull, 0, maxBlocks);
|
||||
if (reusableBlock >= 0) {
|
||||
latestNextUse = PredictNextUse(now, reusableBlock);
|
||||
}
|
||||
}
|
||||
|
||||
// This array holds a list of streams which need to be closed due
|
||||
// to fatal errors. We can't close streams immediately since it would
|
||||
// confuse iteration over mStreams and generally just be confusing.
|
||||
nsTArray<nsMediaCacheStream*> streamsToClose;
|
||||
for (PRUint32 i = 0; i < mStreams.Length(); ++i) {
|
||||
nsMediaCacheStream* stream = mStreams[i];
|
||||
if (stream->mClosed)
|
||||
continue;
|
||||
|
||||
// Figure out where we should be reading from. It's normally the first
|
||||
// uncached byte after the current mStreamOffset.
|
||||
PRInt64 desiredOffset = stream->GetCachedDataEndInternal(stream->mStreamOffset);
|
||||
if (stream->mIsSeekable) {
|
||||
if (desiredOffset > stream->mChannelOffset &&
|
||||
desiredOffset <= stream->mChannelOffset + SEEK_VS_READ_THRESHOLD) {
|
||||
// Assume it's more efficient to just keep reading up to the
|
||||
// desired position instead of trying to seek
|
||||
desiredOffset = stream->mChannelOffset;
|
||||
// Count the blocks allocated for readahead of non-seekable streams
|
||||
// (these blocks can't be freed but we don't want them to monopolize the
|
||||
// cache)
|
||||
PRInt32 nonSeekableReadaheadBlockCount = 0;
|
||||
for (PRUint32 i = 0; i < mStreams.Length(); ++i) {
|
||||
nsMediaCacheStream* stream = mStreams[i];
|
||||
if (!stream->mIsSeekable) {
|
||||
nonSeekableReadaheadBlockCount += stream->mReadaheadBlocks.GetCount();
|
||||
}
|
||||
} else {
|
||||
// We can't seek directly to the desired offset...
|
||||
if (stream->mChannelOffset > desiredOffset) {
|
||||
// Reading forward won't get us anywhere, we need to go backwards.
|
||||
// Seek back to 0 (the client will reopen the stream) and then
|
||||
// read forward.
|
||||
NS_WARNING("Can't seek backwards, so seeking to 0");
|
||||
desiredOffset = 0;
|
||||
// Flush cached blocks out, since if this is a live stream
|
||||
// the cached data may be completely different next time we
|
||||
// read it. We have to assume that live streams don't
|
||||
// advertise themselves as being seekable...
|
||||
ReleaseStreamBlocks(stream);
|
||||
}
|
||||
|
||||
// If freeBlockCount is zero, then compute the latest of
|
||||
// the predicted next-uses for all blocks
|
||||
TimeDuration latestNextUse;
|
||||
if (freeBlockCount == 0) {
|
||||
PRInt32 reusableBlock = FindReusableBlock(now, nsnull, 0, maxBlocks);
|
||||
if (reusableBlock >= 0) {
|
||||
latestNextUse = PredictNextUse(now, reusableBlock);
|
||||
}
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < mStreams.Length(); ++i) {
|
||||
actions.AppendElement(NONE);
|
||||
|
||||
nsMediaCacheStream* stream = mStreams[i];
|
||||
if (stream->mClosed)
|
||||
continue;
|
||||
|
||||
// Figure out where we should be reading from. It's normally the first
|
||||
// uncached byte after the current mStreamOffset.
|
||||
PRInt64 desiredOffset = stream->GetCachedDataEndInternal(stream->mStreamOffset);
|
||||
if (stream->mIsSeekable) {
|
||||
if (desiredOffset > stream->mChannelOffset &&
|
||||
desiredOffset <= stream->mChannelOffset + SEEK_VS_READ_THRESHOLD) {
|
||||
// Assume it's more efficient to just keep reading up to the
|
||||
// desired position instead of trying to seek
|
||||
desiredOffset = stream->mChannelOffset;
|
||||
}
|
||||
} else {
|
||||
// otherwise reading forward is looking good, so just stay where we
|
||||
// are and don't trigger a channel seek!
|
||||
desiredOffset = stream->mChannelOffset;
|
||||
}
|
||||
}
|
||||
|
||||
// Figure out if we should be reading data now or not. It's amazing
|
||||
// how complex this is, but each decision is simple enough.
|
||||
PRBool enableReading;
|
||||
if (stream->mStreamLength >= 0 &&
|
||||
desiredOffset >= stream->mStreamLength) {
|
||||
// We want to read at the end of the stream, where there's nothing to
|
||||
// read. We don't want to try to read if we're suspended, because that
|
||||
// might create a new channel and seek unnecessarily (and incorrectly,
|
||||
// since HTTP doesn't allow seeking to the actual EOF), and we don't want
|
||||
// to suspend if we're not suspended and already reading at the end of
|
||||
// the stream, since there just might be more data than the server
|
||||
// advertised with Content-Length, and we may as well keep reading.
|
||||
// But we don't want to seek to the end of the stream if we're not
|
||||
// already there.
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p at end of stream", stream));
|
||||
enableReading = !stream->mCacheSuspended &&
|
||||
desiredOffset == stream->mChannelOffset;
|
||||
} else if (desiredOffset < stream->mStreamOffset) {
|
||||
// We're reading to try to catch up to where the current stream
|
||||
// reader wants to be. Better not stop.
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p catching up", stream));
|
||||
enableReading = PR_TRUE;
|
||||
} else if (desiredOffset < stream->mStreamOffset + BLOCK_SIZE) {
|
||||
// The stream reader is waiting for us, or nearly so. Better feed it.
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p feeding reader", stream));
|
||||
enableReading = PR_TRUE;
|
||||
} else if (!stream->mIsSeekable &&
|
||||
nonSeekableReadaheadBlockCount >= maxBlocks*NONSEEKABLE_READAHEAD_MAX) {
|
||||
// This stream is not seekable and there are already too many blocks
|
||||
// being cached for readahead for nonseekable streams (which we can't
|
||||
// free). So stop reading ahead now.
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p throttling non-seekable readahead", stream));
|
||||
enableReading = PR_FALSE;
|
||||
} else if (mIndex.Length() > PRUint32(maxBlocks)) {
|
||||
// We're in the process of bringing the cache size back to the
|
||||
// desired limit, so don't bring in more data yet
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p throttling to reduce cache size", stream));
|
||||
enableReading = PR_FALSE;
|
||||
} else if (freeBlockCount > 0 || mIndex.Length() < PRUint32(maxBlocks)) {
|
||||
// Free blocks in the cache, so keep reading
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p reading since there are free blocks", stream));
|
||||
enableReading = PR_TRUE;
|
||||
} else if (latestNextUse <= TimeDuration(0)) {
|
||||
// No reusable blocks, so can't read anything
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p throttling due to no reusable blocks", stream));
|
||||
enableReading = PR_FALSE;
|
||||
} else {
|
||||
// Read ahead if the data we expect to read is more valuable than
|
||||
// the least valuable block in the main part of the cache
|
||||
TimeDuration predictedNewDataUse = PredictNextUseForIncomingData(stream);
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p predict next data in %f, current worst block is %f",
|
||||
stream, predictedNewDataUse.ToSeconds(), latestNextUse.ToSeconds()));
|
||||
enableReading = predictedNewDataUse < latestNextUse;
|
||||
}
|
||||
|
||||
if (enableReading) {
|
||||
for (PRUint32 j = 0; j < i; ++j) {
|
||||
nsMediaCacheStream* other = mStreams[j];
|
||||
if (other->mResourceID == stream->mResourceID &&
|
||||
!other->mCacheSuspended &&
|
||||
other->mChannelOffset/BLOCK_SIZE == stream->mChannelOffset/BLOCK_SIZE) {
|
||||
// This block is already going to be read by the other stream.
|
||||
// So don't try to read it from this stream as well.
|
||||
enableReading = PR_FALSE;
|
||||
break;
|
||||
// We can't seek directly to the desired offset...
|
||||
if (stream->mChannelOffset > desiredOffset) {
|
||||
// Reading forward won't get us anywhere, we need to go backwards.
|
||||
// Seek back to 0 (the client will reopen the stream) and then
|
||||
// read forward.
|
||||
NS_WARNING("Can't seek backwards, so seeking to 0");
|
||||
desiredOffset = 0;
|
||||
// Flush cached blocks out, since if this is a live stream
|
||||
// the cached data may be completely different next time we
|
||||
// read it. We have to assume that live streams don't
|
||||
// advertise themselves as being seekable...
|
||||
ReleaseStreamBlocks(stream);
|
||||
} else {
|
||||
// otherwise reading forward is looking good, so just stay where we
|
||||
// are and don't trigger a channel seek!
|
||||
desiredOffset = stream->mChannelOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Figure out if we should be reading data now or not. It's amazing
|
||||
// how complex this is, but each decision is simple enough.
|
||||
PRBool enableReading;
|
||||
if (stream->mStreamLength >= 0 &&
|
||||
desiredOffset >= stream->mStreamLength) {
|
||||
// We want to read at the end of the stream, where there's nothing to
|
||||
// read. We don't want to try to read if we're suspended, because that
|
||||
// might create a new channel and seek unnecessarily (and incorrectly,
|
||||
// since HTTP doesn't allow seeking to the actual EOF), and we don't want
|
||||
// to suspend if we're not suspended and already reading at the end of
|
||||
// the stream, since there just might be more data than the server
|
||||
// advertised with Content-Length, and we may as well keep reading.
|
||||
// But we don't want to seek to the end of the stream if we're not
|
||||
// already there.
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p at end of stream", stream));
|
||||
enableReading = !stream->mCacheSuspended &&
|
||||
desiredOffset == stream->mChannelOffset;
|
||||
} else if (desiredOffset < stream->mStreamOffset) {
|
||||
// We're reading to try to catch up to where the current stream
|
||||
// reader wants to be. Better not stop.
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p catching up", stream));
|
||||
enableReading = PR_TRUE;
|
||||
} else if (desiredOffset < stream->mStreamOffset + BLOCK_SIZE) {
|
||||
// The stream reader is waiting for us, or nearly so. Better feed it.
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p feeding reader", stream));
|
||||
enableReading = PR_TRUE;
|
||||
} else if (!stream->mIsSeekable &&
|
||||
nonSeekableReadaheadBlockCount >= maxBlocks*NONSEEKABLE_READAHEAD_MAX) {
|
||||
// This stream is not seekable and there are already too many blocks
|
||||
// being cached for readahead for nonseekable streams (which we can't
|
||||
// free). So stop reading ahead now.
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p throttling non-seekable readahead", stream));
|
||||
enableReading = PR_FALSE;
|
||||
} else if (mIndex.Length() > PRUint32(maxBlocks)) {
|
||||
// We're in the process of bringing the cache size back to the
|
||||
// desired limit, so don't bring in more data yet
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p throttling to reduce cache size", stream));
|
||||
enableReading = PR_FALSE;
|
||||
} else if (freeBlockCount > 0 || mIndex.Length() < PRUint32(maxBlocks)) {
|
||||
// Free blocks in the cache, so keep reading
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p reading since there are free blocks", stream));
|
||||
enableReading = PR_TRUE;
|
||||
} else if (latestNextUse <= TimeDuration(0)) {
|
||||
// No reusable blocks, so can't read anything
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p throttling due to no reusable blocks", stream));
|
||||
enableReading = PR_FALSE;
|
||||
} else {
|
||||
// Read ahead if the data we expect to read is more valuable than
|
||||
// the least valuable block in the main part of the cache
|
||||
TimeDuration predictedNewDataUse = PredictNextUseForIncomingData(stream);
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p predict next data in %f, current worst block is %f",
|
||||
stream, predictedNewDataUse.ToSeconds(), latestNextUse.ToSeconds()));
|
||||
enableReading = predictedNewDataUse < latestNextUse;
|
||||
}
|
||||
|
||||
if (enableReading) {
|
||||
for (PRUint32 j = 0; j < i; ++j) {
|
||||
nsMediaCacheStream* other = mStreams[j];
|
||||
if (other->mResourceID == stream->mResourceID &&
|
||||
!other->mCacheSuspended &&
|
||||
other->mChannelOffset/BLOCK_SIZE == stream->mChannelOffset/BLOCK_SIZE) {
|
||||
// This block is already going to be read by the other stream.
|
||||
// So don't try to read it from this stream as well.
|
||||
enableReading = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stream->mChannelOffset != desiredOffset && enableReading) {
|
||||
// We need to seek now.
|
||||
NS_ASSERTION(stream->mIsSeekable || desiredOffset == 0,
|
||||
"Trying to seek in a non-seekable stream!");
|
||||
// Round seek offset down to the start of the block. This is essential
|
||||
// because we don't want to think we have part of a block already
|
||||
// in mPartialBlockBuffer.
|
||||
stream->mChannelOffset = (desiredOffset/BLOCK_SIZE)*BLOCK_SIZE;
|
||||
actions[i] = SEEK;
|
||||
} else if (enableReading && stream->mCacheSuspended) {
|
||||
actions[i] = RESUME;
|
||||
} else if (!enableReading && !stream->mCacheSuspended) {
|
||||
actions[i] = SUSPEND;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
mInUpdate = PR_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Update the channel state without holding our cache lock. While we're
|
||||
// doing this, decoder threads may be running and seeking, reading or changing
|
||||
// other cache state. That's OK, they'll trigger new Update events and we'll
|
||||
// get back here and revise our decisions. The important thing here is that
|
||||
// performing these actions only depends on mChannelOffset and
|
||||
// mCacheSuspended, which can only be written by the main thread (i.e., this
|
||||
// thread), so we don't have races here.
|
||||
for (PRUint32 i = 0; i < mStreams.Length(); ++i) {
|
||||
nsMediaCacheStream* stream = mStreams[i];
|
||||
nsresult rv = NS_OK;
|
||||
if (stream->mChannelOffset != desiredOffset && enableReading) {
|
||||
// We need to seek now.
|
||||
NS_ASSERTION(stream->mIsSeekable || desiredOffset == 0,
|
||||
"Trying to seek in a non-seekable stream!");
|
||||
// Round seek offset down to the start of the block
|
||||
stream->mChannelOffset = (desiredOffset/BLOCK_SIZE)*BLOCK_SIZE;
|
||||
switch (actions[i]) {
|
||||
case SEEK:
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p CacheSeek to %lld (resume=%d)", stream,
|
||||
(long long)stream->mChannelOffset, stream->mCacheSuspended));
|
||||
(long long)stream->mChannelOffset, stream->mCacheSuspended));
|
||||
rv = stream->mClient->CacheClientSeek(stream->mChannelOffset,
|
||||
stream->mCacheSuspended);
|
||||
stream->mCacheSuspended = PR_FALSE;
|
||||
} else if (enableReading && stream->mCacheSuspended) {
|
||||
break;
|
||||
|
||||
case RESUME:
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p Resumed", stream));
|
||||
rv = stream->mClient->CacheClientResume();
|
||||
stream->mCacheSuspended = PR_FALSE;
|
||||
} else if (!enableReading && !stream->mCacheSuspended) {
|
||||
break;
|
||||
|
||||
case SUSPEND:
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p Suspended", stream));
|
||||
rv = stream->mClient->CacheClientSuspend();
|
||||
stream->mCacheSuspended = PR_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
streamsToClose.AppendElement(stream);
|
||||
// Close the streams that failed due to error. This will cause all
|
||||
// client Read and Seek operations on those streams to fail. Blocked
|
||||
// Reads will also be woken up.
|
||||
nsAutoMonitor mon(mMonitor);
|
||||
stream->CloseInternal(&mon);
|
||||
}
|
||||
}
|
||||
|
||||
// Close the streams that failed due to error. This will cause all
|
||||
// client Read and Seek operations on those streams to fail. Blocked
|
||||
// Reads will also be woken up.
|
||||
for (PRUint32 i = 0; i < streamsToClose.Length(); ++i) {
|
||||
streamsToClose[i]->CloseInternal(&mon);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
mInUpdate = PR_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
class UpdateEvent : public nsRunnable
|
||||
|
|
|
@ -220,13 +220,14 @@ public:
|
|||
// aClient provides the underlying transport that cache will use to read
|
||||
// data for this stream.
|
||||
nsMediaCacheStream(nsMediaChannelStream* aClient)
|
||||
: mClient(aClient), mResourceID(0), mChannelOffset(0),
|
||||
mStreamOffset(0), mStreamLength(-1), mPlaybackBytesPerSecond(10000),
|
||||
mPinCount(0), mCurrentMode(MODE_PLAYBACK),
|
||||
mInitialized(PR_FALSE), mClosed(PR_FALSE),
|
||||
: mClient(aClient), mResourceID(0), mInitialized(PR_FALSE),
|
||||
mIsSeekable(PR_FALSE), mCacheSuspended(PR_FALSE),
|
||||
mUsingNullPrincipal(PR_FALSE),
|
||||
mChannelOffset(0), mStreamLength(-1),
|
||||
mStreamOffset(0), mPlaybackBytesPerSecond(10000),
|
||||
mPinCount(0), mCurrentMode(MODE_PLAYBACK),
|
||||
mMetadataInPartialBlockBuffer(PR_FALSE),
|
||||
mUsingNullPrincipal(PR_FALSE) {}
|
||||
mClosed(PR_FALSE) {}
|
||||
~nsMediaCacheStream();
|
||||
|
||||
// Set up this stream with the cache. Can fail on OOM. One
|
||||
|
@ -432,16 +433,32 @@ private:
|
|||
// All streams with the same mResourceID are loading the same
|
||||
// underlying resource and should share data.
|
||||
PRInt64 mResourceID;
|
||||
// Set to true when Init or InitAsClone has been called
|
||||
PRPackedBool mInitialized;
|
||||
|
||||
// All other fields are all protected by the cache's monitor and
|
||||
// can be accessed by by any thread.
|
||||
// The following fields are protected by the cache's monitor but are
|
||||
// only written on the main thread.
|
||||
|
||||
// The last reported seekability state for the underlying channel
|
||||
PRPackedBool mIsSeekable;
|
||||
// true if the cache has suspended our channel because the cache is
|
||||
// full and the priority of the data that would be received is lower
|
||||
// than the priority of the data already in the cache
|
||||
PRPackedBool mCacheSuspended;
|
||||
// true if mPrincipal is a null principal because we saw data from
|
||||
// multiple origins
|
||||
PRPackedBool mUsingNullPrincipal;
|
||||
// The offset where the next data from the channel will arrive
|
||||
PRInt64 mChannelOffset;
|
||||
// The offset where the reader is positioned in the stream
|
||||
PRInt64 mStreamOffset;
|
||||
PRInt64 mChannelOffset;
|
||||
// The reported or discovered length of the data, or -1 if nothing is
|
||||
// known
|
||||
PRInt64 mStreamLength;
|
||||
PRInt64 mStreamLength;
|
||||
|
||||
// The following fields are protected by the cache's monitor can can be written
|
||||
// by any thread.
|
||||
|
||||
// The offset where the reader is positioned in the stream
|
||||
PRInt64 mStreamOffset;
|
||||
// For each block in the stream data, maps to the cache entry for the
|
||||
// block, or -1 if the block is not cached.
|
||||
nsTArray<PRInt32> mBlocks;
|
||||
|
@ -460,22 +477,14 @@ private:
|
|||
PRUint32 mPinCount;
|
||||
// The last reported read mode
|
||||
ReadMode mCurrentMode;
|
||||
// Set to true when Init or InitAsClone has been called
|
||||
PRPackedBool mInitialized;
|
||||
// true if some data in mPartialBlockBuffer has been read as metadata
|
||||
PRPackedBool mMetadataInPartialBlockBuffer;
|
||||
// Set to true when the stream has been closed either explicitly or
|
||||
// due to an internal cache error
|
||||
PRPackedBool mClosed;
|
||||
// The last reported seekability state for the underlying channel
|
||||
PRPackedBool mIsSeekable;
|
||||
// true if the cache has suspended our channel because the cache is
|
||||
// full and the priority of the data that would be received is lower
|
||||
// than the priority of the data already in the cache
|
||||
PRPackedBool mCacheSuspended;
|
||||
// true if some data in mPartialBlockBuffer has been read as metadata
|
||||
PRPackedBool mMetadataInPartialBlockBuffer;
|
||||
// true if mPrincipal is a null principal because we saw data from
|
||||
// multiple origins
|
||||
PRPackedBool mUsingNullPrincipal;
|
||||
|
||||
// The following field is protected by the cache's monitor but are
|
||||
// only written on the main thread.
|
||||
|
||||
// Data received for the block containing mChannelOffset. Data needs
|
||||
// to wait here so we can write back a complete block. The first
|
||||
|
|
|
@ -251,9 +251,9 @@ protected:
|
|||
// Timer used for updating progress events
|
||||
nsCOMPtr<nsITimer> mProgressTimer;
|
||||
|
||||
// The element is not reference counted. Instead the decoder is
|
||||
// notified when it is able to be used. It should only ever be
|
||||
// accessed from the main thread.
|
||||
// This should only ever be accessed from the main thread.
|
||||
// It is set in Init and cleared in Shutdown when the element goes away.
|
||||
// The decoder does not add a reference the element.
|
||||
nsHTMLMediaElement* mElement;
|
||||
|
||||
// RGB data for last decoded frame of video data.
|
||||
|
|
|
@ -540,7 +540,7 @@ PRInt64 nsMediaChannelStream::Tell()
|
|||
|
||||
void nsMediaChannelStream::Suspend(PRBool aCloseImmediately)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on main thread");
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
|
||||
|
||||
nsHTMLMediaElement* element = mDecoder->GetMediaElement();
|
||||
if (!element) {
|
||||
|
@ -569,7 +569,7 @@ void nsMediaChannelStream::Suspend(PRBool aCloseImmediately)
|
|||
|
||||
void nsMediaChannelStream::Resume()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on main thread");
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
|
||||
NS_ASSERTION(mSuspendCount > 0, "Too many resumes!");
|
||||
|
||||
nsHTMLMediaElement* element = mDecoder->GetMediaElement();
|
||||
|
@ -641,7 +641,9 @@ nsMediaChannelStream::DoNotifyDataReceived()
|
|||
void
|
||||
nsMediaChannelStream::CacheClientNotifyDataReceived()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on main thread");
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
|
||||
// NOTE: this can be called with the media cache lock held, so don't
|
||||
// block or do anything which might try to acquire a lock!
|
||||
|
||||
if (mDataReceivedEvent.IsPending())
|
||||
return;
|
||||
|
@ -667,7 +669,9 @@ private:
|
|||
void
|
||||
nsMediaChannelStream::CacheClientNotifyDataEnded(nsresult aStatus)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on main thread");
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
|
||||
// NOTE: this can be called with the media cache lock held, so don't
|
||||
// block or do anything which might try to acquire a lock!
|
||||
|
||||
nsCOMPtr<nsIRunnable> event = new DataEnded(mDecoder, aStatus);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
|
@ -676,7 +680,7 @@ nsMediaChannelStream::CacheClientNotifyDataEnded(nsresult aStatus)
|
|||
nsresult
|
||||
nsMediaChannelStream::CacheClientSeek(PRInt64 aOffset, PRBool aResume)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on main thread");
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
|
||||
|
||||
CloseChannel();
|
||||
|
||||
|
@ -703,12 +707,7 @@ nsMediaChannelStream::CacheClientSuspend()
|
|||
}
|
||||
Suspend(PR_FALSE);
|
||||
|
||||
// We have to spawn an event here since we're being called back from
|
||||
// a sensitive place in nsMediaCache, which doesn't want us to reenter
|
||||
// the decoder and cause deadlocks or other unpleasantness
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NEW_RUNNABLE_METHOD(nsMediaDecoder, mDecoder, NotifySuspendedStatusChanged);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
mDecoder->NotifySuspendedStatusChanged();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -721,12 +720,7 @@ nsMediaChannelStream::CacheClientResume()
|
|||
--mCacheSuspendCount;
|
||||
}
|
||||
|
||||
// We have to spawn an event here since we're being called back from
|
||||
// a sensitive place in nsMediaCache, which doesn't want us to reenter
|
||||
// the decoder and cause deadlocks or other unpleasantness
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NEW_RUNNABLE_METHOD(nsMediaDecoder, mDecoder, NotifySuspendedStatusChanged);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
mDecoder->NotifySuspendedStatusChanged();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -308,7 +308,7 @@ public:
|
|||
~nsMediaChannelStream();
|
||||
|
||||
// These are called on the main thread by nsMediaCache. These must
|
||||
// not block or grab locks.
|
||||
// not block or grab locks, because the media cache is holding its lock.
|
||||
// Notify that data is available from the cache. This can happen even
|
||||
// if this stream didn't read any data, since another stream might have
|
||||
// received data for the same resource.
|
||||
|
@ -317,6 +317,10 @@ public:
|
|||
// if this stream didn't read any data, since another stream might have
|
||||
// received data for the same resource.
|
||||
void CacheClientNotifyDataEnded(nsresult aStatus);
|
||||
|
||||
// These are called on the main thread by nsMediaCache. These shouldn't block,
|
||||
// but they may grab locks --- the media cache is not holding its lock
|
||||
// when these are called.
|
||||
// Start a new load at the given aOffset. The old load is cancelled
|
||||
// and no more data from the old load will be notified via
|
||||
// nsMediaCacheStream::NotifyDataReceived/Ended.
|
||||
|
|
|
@ -397,8 +397,8 @@ protected:
|
|||
|
||||
// Decodes from the current position until encountering a frame with time
|
||||
// greater or equal to aSeekTime.
|
||||
void DecodeToFrame(nsAutoMonitor& aMonitor,
|
||||
float aSeekTime);
|
||||
PRBool DecodeToFrame(nsAutoMonitor& aMonitor,
|
||||
float aSeekTime);
|
||||
|
||||
// Convert the OggPlay frame information into a format used by Gecko
|
||||
// (RGB for video, float for sound, etc).The decoder monitor must be
|
||||
|
@ -1315,8 +1315,8 @@ nsresult nsOggDecodeStateMachine::Seek(float aTime, nsChannelReader* aReader)
|
|||
return (rv < 0) ? NS_ERROR_FAILURE : NS_OK;
|
||||
}
|
||||
|
||||
void nsOggDecodeStateMachine::DecodeToFrame(nsAutoMonitor& aMonitor,
|
||||
float aTime)
|
||||
PRBool nsOggDecodeStateMachine::DecodeToFrame(nsAutoMonitor& aMonitor,
|
||||
float aTime)
|
||||
{
|
||||
// Drop frames before the target time.
|
||||
float target = aTime - mCallbackPeriod / 2.0;
|
||||
|
@ -1356,7 +1356,7 @@ void nsOggDecodeStateMachine::DecodeToFrame(nsAutoMonitor& aMonitor,
|
|||
|
||||
if (mState == DECODER_STATE_SHUTDOWN) {
|
||||
delete frame;
|
||||
return;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_ASSERTION(frame != nsnull, "No frame after decode!");
|
||||
|
@ -1380,6 +1380,8 @@ void nsOggDecodeStateMachine::DecodeToFrame(nsAutoMonitor& aMonitor,
|
|||
UpdatePlaybackPosition(frame->mDecodedFrameTime);
|
||||
PlayVideo(frame);
|
||||
}
|
||||
|
||||
return r == E_OGGPLAY_OK;
|
||||
}
|
||||
|
||||
void nsOggDecodeStateMachine::StopStepDecodeThread(nsAutoMonitor* aMonitor)
|
||||
|
@ -1411,8 +1413,8 @@ nsresult nsOggDecodeStateMachine::Run()
|
|||
nsChannelReader* reader = mDecoder->GetReader();
|
||||
NS_ENSURE_TRUE(reader, NS_ERROR_NULL_POINTER);
|
||||
while (PR_TRUE) {
|
||||
nsAutoMonitor mon(mDecoder->GetMonitor());
|
||||
switch(mState) {
|
||||
nsAutoMonitor mon(mDecoder->GetMonitor());
|
||||
switch(mState) {
|
||||
case DECODER_STATE_SHUTDOWN:
|
||||
if (mPlaying) {
|
||||
StopPlayback();
|
||||
|
@ -1557,7 +1559,7 @@ nsresult nsOggDecodeStateMachine::Run()
|
|||
PRPackedBool reliable;
|
||||
double playbackRate = mDecoder->ComputePlaybackRate(&reliable);
|
||||
mBufferingEndOffset = mDecoder->mDecoderPosition +
|
||||
BUFFERING_RATE(playbackRate) * BUFFERING_WAIT;
|
||||
BUFFERING_RATE(playbackRate) * BUFFERING_WAIT;
|
||||
mState = DECODER_STATE_BUFFERING;
|
||||
if (mPlaying) {
|
||||
PausePlayback();
|
||||
|
@ -1621,8 +1623,9 @@ nsresult nsOggDecodeStateMachine::Run()
|
|||
if (mState == DECODER_STATE_SHUTDOWN)
|
||||
continue;
|
||||
|
||||
PRBool atEnd = PR_FALSE;
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
DecodeToFrame(mon, seekTime);
|
||||
atEnd = DecodeToFrame(mon, seekTime);
|
||||
// mSeekTime should not have changed. While we seek, mPlayState
|
||||
// should always be PLAY_STATE_SEEKING and no-one will call
|
||||
// nsOggDecoderStateMachine::Seek.
|
||||
|
@ -1631,29 +1634,34 @@ nsresult nsOggDecodeStateMachine::Run()
|
|||
continue;
|
||||
}
|
||||
|
||||
OggPlayErrorCode r;
|
||||
// Now try to decode another frame to see if we're at the end.
|
||||
do {
|
||||
mon.Exit();
|
||||
r = DecodeFrame();
|
||||
mon.Enter();
|
||||
} while (mState != DECODER_STATE_SHUTDOWN && r == E_OGGPLAY_TIMEOUT);
|
||||
HandleDecodeErrors(r);
|
||||
if (mState == DECODER_STATE_SHUTDOWN)
|
||||
continue;
|
||||
if (!atEnd) {
|
||||
OggPlayErrorCode r;
|
||||
// Now try to decode another frame to see if we're at the end.
|
||||
do {
|
||||
mon.Exit();
|
||||
r = DecodeFrame();
|
||||
mon.Enter();
|
||||
} while (mState != DECODER_STATE_SHUTDOWN && r == E_OGGPLAY_TIMEOUT);
|
||||
HandleDecodeErrors(r);
|
||||
if (mState == DECODER_STATE_SHUTDOWN)
|
||||
continue;
|
||||
atEnd = r == E_OGGPLAY_OK;
|
||||
}
|
||||
QueueDecodedFrames();
|
||||
}
|
||||
|
||||
// Change state to DECODING now. SeekingStopped will call
|
||||
// nsOggDecodeStateMachine::Seek to reset our state to SEEKING
|
||||
// Change state to DECODING or COMPLETED now. SeekingStopped will
|
||||
// call nsOggDecodeStateMachine::Seek to reset our state to SEEKING
|
||||
// if we need to seek again.
|
||||
LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %f) to DECODING", mDecoder, seekTime));
|
||||
mState = DECODER_STATE_DECODING;
|
||||
nsCOMPtr<nsIRunnable> stopEvent;
|
||||
if (mDecodedFrames.GetCount() > 1) {
|
||||
if (!atEnd && mDecodedFrames.GetCount() > 1) {
|
||||
LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %f) to DECODING",
|
||||
mDecoder, seekTime));
|
||||
stopEvent = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStopped);
|
||||
mState = DECODER_STATE_DECODING;
|
||||
} else {
|
||||
LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %f) to COMPLETED",
|
||||
mDecoder, seekTime));
|
||||
stopEvent = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStoppedAtEnd);
|
||||
mState = DECODER_STATE_COMPLETED;
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ _TEST_FILES = \
|
|||
can_play_type_wave.js \
|
||||
cancellable_request.sjs \
|
||||
manifest.js \
|
||||
reactivate_helper.html \
|
||||
seek1.js \
|
||||
seek2.js \
|
||||
seek3.js \
|
||||
|
@ -85,6 +86,7 @@ _TEST_FILES = \
|
|||
test_audio2.html \
|
||||
test_autobuffer.html \
|
||||
test_autoplay.html \
|
||||
test_bug495300.html \
|
||||
test_can_play_type.html \
|
||||
test_constants.html \
|
||||
test_controls.html \
|
||||
|
@ -98,6 +100,7 @@ _TEST_FILES = \
|
|||
test_paused.html \
|
||||
test_playback.html \
|
||||
test_playback_errors.html \
|
||||
test_reactivate.html \
|
||||
test_readyState.html \
|
||||
test_seek2.html \
|
||||
test_volume.html \
|
||||
|
@ -144,6 +147,7 @@ _TEST_FILES += \
|
|||
bug520500.ogg \
|
||||
bug520908.ogv \
|
||||
bug520908.ogv^headers^ \
|
||||
bug523816.ogv \
|
||||
chain.ogv \
|
||||
dirac.ogg \
|
||||
seek.ogv \
|
||||
|
@ -181,7 +185,6 @@ _TEST_FILES += \
|
|||
test_bug486646.html \
|
||||
test_bug493187.html \
|
||||
test_bug495145.html \
|
||||
test_bug495300.html \
|
||||
test_bug495319.html \
|
||||
test_closing_connections.html \
|
||||
test_contentDuration1.html \
|
||||
|
|
Двоичный файл не отображается.
|
@ -61,6 +61,7 @@ var gPlayTests = [
|
|||
{ name:"bug498855-3.ogv", type:"video/ogg", duration:0.2 },
|
||||
{ name:"bug504644.ogv", type:"video/ogg", duration:1.56 },
|
||||
{ name:"chain.ogv", type:"video/ogg", duration:Number.NaN },
|
||||
{ name:"bug523816.ogv", type:"video/ogg", duration:0.5 },
|
||||
|
||||
{ name:"bogus.duh", type:"bogus/duh" }
|
||||
];
|
||||
|
@ -85,6 +86,7 @@ var gErrorTests = [
|
|||
var gSeekTests = [
|
||||
{ name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
|
||||
{ name:"seek.ogv", type:"video/ogg", duration:3.966 },
|
||||
{ name:"320x240.ogv", type:"video/ogg", duration:0.233 },
|
||||
{ name:"bogus.duh", type:"bogus/duh", duration:123 }
|
||||
];
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
var loadsWaiting = 0;
|
||||
var elements = [];
|
||||
|
||||
function loadedData(event) {
|
||||
parent.ok(elements.indexOf(event.target) == -1, "Element already loaded: " + event.target.currentSrc);
|
||||
|
||||
elements.push(event.target);
|
||||
|
||||
--loadsWaiting;
|
||||
parent.ok(true, "Loaded " + event.target.currentSrc);
|
||||
if (loadsWaiting == 0) {
|
||||
parent.loadedAll(elements);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < parent.gSmallTests.length; ++i) {
|
||||
var test = parent.gSmallTests[i];
|
||||
var elemType = /^audio/.test(test.type) ? "audio" : "video";
|
||||
// Associate these elements with the subframe's document
|
||||
var e = document.createElement(elemType);
|
||||
if (e.canPlayType(test.type)) {
|
||||
e.src = test.name;
|
||||
e.addEventListener("loadeddata", loadedData, false);
|
||||
e.load();
|
||||
++loadsWaiting;
|
||||
}
|
||||
}
|
||||
|
||||
if (loadsWaiting == 0) {
|
||||
parent.todo(false, "Can't play anything");
|
||||
} else {
|
||||
parent.SimpleTest.waitForExplicitFinish();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче