Merge mozilla-central into electrolysis.

This commit is contained in:
Benjamin Smedberg 2009-11-11 12:35:42 -05:00
commit d8c7dfc1dd
333 changed files with 9654 additions and 4039 deletions

View File

@ -196,6 +196,7 @@ ifdef MOZ_CRASHREPORTER
$(MAKE_SYM_STORE_PATH) > \
$(DIST)/crashreporter-symbols/$(SYMBOL_INDEX_NAME)
echo packing symbols
$(NSINSTALL) -D $(DIST)/$(PKG_PATH)
cd $(DIST)/crashreporter-symbols && \
zip -r9D "../$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip" .
endif # MOZ_CRASHREPORTER

View File

@ -902,13 +902,15 @@ nsAccUtils::MustPrune(nsIAccessible *aAccessible)
{
PRUint32 role = nsAccUtils::Role(aAccessible);
// We don't prune buttons any more however AT don't expect children inside of
// button in general, we allow menu buttons to have children to make them
// accessible.
return role == nsIAccessibleRole::ROLE_MENUITEM ||
role == nsIAccessibleRole::ROLE_COMBOBOX_OPTION ||
role == nsIAccessibleRole::ROLE_OPTION ||
role == nsIAccessibleRole::ROLE_ENTRY ||
role == nsIAccessibleRole::ROLE_FLAT_EQUATION ||
role == nsIAccessibleRole::ROLE_PASSWORD_TEXT ||
role == nsIAccessibleRole::ROLE_PUSHBUTTON ||
role == nsIAccessibleRole::ROLE_TOGGLE_BUTTON ||
role == nsIAccessibleRole::ROLE_GRAPHIC ||
role == nsIAccessibleRole::ROLE_SLIDER ||

View File

@ -279,6 +279,19 @@ public:
return state;
}
/**
* Return the extended state for the given accessible.
*/
static PRUint32 ExtendedState(nsIAccessible *aAcc)
{
PRUint32 state = 0;
PRUint32 extstate = 0;
if (aAcc)
aAcc->GetState(&state, &extstate);
return extstate;
}
/**
* Get the ARIA attribute characteristics for a given ARIA attribute.
*

View File

@ -61,6 +61,9 @@ ACCESSIBILITY_ATOM(col, "col")
ACCESSIBILITY_ATOM(_empty, "")
ACCESSIBILITY_ATOM(_false, "false")
ACCESSIBILITY_ATOM(image, "image")
ACCESSIBILITY_ATOM(menu, "menu")
ACCESSIBILITY_ATOM(menuButton, "menu-button")
ACCESSIBILITY_ATOM(menugenerated, "menugenerated")
ACCESSIBILITY_ATOM(password, "password")
ACCESSIBILITY_ATOM(reset, "reset")
ACCESSIBILITY_ATOM(row, "row")
@ -125,12 +128,12 @@ ACCESSIBILITY_ATOM(listhead, "listhead") // XUL
ACCESSIBILITY_ATOM(listheader, "listheader") // XUL
ACCESSIBILITY_ATOM(map, "map")
ACCESSIBILITY_ATOM(math, "math")
ACCESSIBILITY_ATOM(menu, "menu") // XUL
ACCESSIBILITY_ATOM(menupopup, "menupopup") // XUL
ACCESSIBILITY_ATOM(object, "object")
ACCESSIBILITY_ATOM(ol, "ol")
ACCESSIBILITY_ATOM(optgroup, "optgroup")
ACCESSIBILITY_ATOM(option, "option")
ACCESSIBILITY_ATOM(panel, "panel") // XUL
ACCESSIBILITY_ATOM(q, "q")
ACCESSIBILITY_ATOM(select, "select")
ACCESSIBILITY_ATOM(select1, "select1") // XForms
@ -164,6 +167,7 @@ ACCESSIBILITY_ATOM(_class, "class")
ACCESSIBILITY_ATOM(cycles, "cycles") // used for XUL cycler attribute
ACCESSIBILITY_ATOM(curpos, "curpos") // XUL
ACCESSIBILITY_ATOM(data, "data")
ACCESSIBILITY_ATOM(_default, "default") // XUL button
ACCESSIBILITY_ATOM(draggable, "draggable")
ACCESSIBILITY_ATOM(droppable, "droppable") // XUL combo box
ACCESSIBILITY_ATOM(editable, "editable")

View File

@ -1107,3 +1107,45 @@ nsCoreUtils::IsColumnHidden(nsITreeColumn *aColumn)
return content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::hidden,
nsAccessibilityAtoms::_true, eCaseMatters);
}
void
nsCoreUtils::GeneratePopupTree(nsIDOMNode *aNode, PRBool aIsAnon)
{
// Set menugenerated="true" on the menupopup node to generate the sub-menu
// items if they have not been generated.
nsCOMPtr<nsIDOMNodeList> list;
if (aIsAnon) {
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
nsIDocument* document = content->GetCurrentDoc();
if (document)
document->GetXBLChildNodesFor(content, getter_AddRefs(list));
} else {
aNode->GetChildNodes(getter_AddRefs(list));
}
PRUint32 length = 0;
if (!list || NS_FAILED(list->GetLength(&length)))
return;
for (PRUint32 idx = 0; idx < length; idx++) {
nsCOMPtr<nsIDOMNode> childNode;
list->Item(idx, getter_AddRefs(childNode));
nsCOMPtr<nsIContent> child(do_QueryInterface(childNode));
PRBool isPopup = child->NodeInfo()->Equals(nsAccessibilityAtoms::menupopup,
kNameSpaceID_XUL) ||
child->NodeInfo()->Equals(nsAccessibilityAtoms::panel,
kNameSpaceID_XUL);
if (isPopup && !child->AttrValueIs(kNameSpaceID_None,
nsAccessibilityAtoms::menugenerated,
nsAccessibilityAtoms::_true,
eCaseMatters)) {
child->SetAttr(kNameSpaceID_None, nsAccessibilityAtoms::menugenerated,
NS_LITERAL_STRING("true"), PR_TRUE);
return;
}
}
}

View File

@ -446,6 +446,15 @@ public:
return aContent->NodeInfo()->Equals(nsAccessibilityAtoms::th) ||
aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::scope);
}
/**
* Generates frames for popup subtree.
*
* @param aNode [in] DOM node containing the menupopup element as a child
* @param aIsAnon [in] specifies whether popup should be searched inside of
* anonymous or explicit content
*/
static void GeneratePopupTree(nsIDOMNode *aNode, PRBool aIsAnon = PR_FALSE);
};
#endif

View File

@ -401,11 +401,12 @@ void nsRootAccessible::TryFireEarlyLoadEvent(nsIDOMNode *aDocNode)
}
}
PRBool nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *aAccessible,
nsIDOMNode *aNode,
nsIDOMEvent *aFocusEvent,
PRBool aForceEvent,
PRBool aIsAsynch)
PRBool
nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *aAccessible,
nsIDOMNode *aNode,
nsIDOMEvent *aFocusEvent,
PRBool aForceEvent,
PRBool aIsAsynch)
{
if (mCaretAccessible) {
nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(aFocusEvent));
@ -531,10 +532,16 @@ PRBool nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *aAccessible,
if (docAccessible) {
// Doc is gaining focus, but actual focus may be on an element within document
nsCOMPtr<nsIDOMNode> realFocusedNode = GetCurrentFocus();
if (realFocusedNode != aNode || realFocusedNode == mDOMNode) {
if ((realFocusedNode != aNode || realFocusedNode == mDOMNode) &&
!(nsAccUtils::ExtendedState(finalFocusAccessible) &
nsIAccessibleStates::EXT_STATE_EDITABLE)) {
// Suppress document focus, because real DOM focus will be fired next,
// and that's what we care about
// except in the case of editable documents because we can't rely on a
// followup focus event for an element in an editable document.
// Make sure we never fire focus for the nsRootAccessible (mDOMNode)
// XXX todo dig deeper on editor focus inconsistency in bug 526313
return PR_FALSE;
}
}

View File

@ -563,7 +563,7 @@ PRUint32 nsTextEquivUtils::gRoleToNameRulesMap[] =
eFromValue, // ROLE_ENTRY
eNoRule, // ROLE_CAPTION
eNoRule, // ROLE_DOCUMENT_FRAME
eNoRule, // ROLE_HEADING
eFromSubtreeIfRec, // ROLE_HEADING
eNoRule, // ROLE_PAGE
eFromSubtreeIfRec, // ROLE_SECTION
eNoRule, // ROLE_REDUNDANT_OBJECT

View File

@ -403,6 +403,8 @@ nsHTMLTableHeaderCellAccessible::GetRoleInternal(PRUint32 *aRole)
// Assume it's columnheader if there are headers in siblings, oterwise
// rowheader.
nsIContent* parent = content->GetParent();
NS_ENSURE_STATE(parent);
PRInt32 indexInParent = parent->IndexOf(content);
for (PRInt32 idx = indexInParent - 1; idx >= 0; idx--) {

View File

@ -2032,6 +2032,11 @@ nsHyperTextAccessible::ScrollSubstringToPoint(PRInt32 aStartIndex,
presContext->DevPixelsToAppUnits(devOffsetY));
nsSize size(parentFrame->GetSize());
// avoid divide by zero
size.width = size.width ? size.width : 1;
size.height = size.height ? size.height : 1;
PRInt16 hPercent = offsetPoint.x * 100 / size.width;
PRInt16 vPercent = offsetPoint.y * 100 / size.height;

View File

@ -36,26 +36,43 @@
*
* ***** END LICENSE BLOCK ***** */
// NOTE: alphabetically ordered
#include "nsXULColorPickerAccessible.h"
#include "nsAccessibleTreeWalker.h"
#include "nsIDOMElement.h"
/**
* XUL Color Picker Tile
*/
////////////////////////////////////////////////////////////////////////////////
// nsXULColorPickerTileAccessible
////////////////////////////////////////////////////////////////////////////////
/**
* Default Constructor
*/
nsXULColorPickerTileAccessible::nsXULColorPickerTileAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
nsFormControlAccessible(aNode, aShell)
{
nsXULColorPickerTileAccessible::
nsXULColorPickerTileAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell) :
nsAccessibleWrap(aNode, aShell)
{
}
/**
* We are a pushbutton
*/
////////////////////////////////////////////////////////////////////////////////
// nsXULColorPickerTileAccessible: nsIAccessible
NS_IMETHODIMP
nsXULColorPickerTileAccessible::GetValue(nsAString& aValue)
{
aValue.Truncate();
if (IsDefunct())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::color, aValue);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsXULColorPickerTileAccessible: nsAccessible
nsresult
nsXULColorPickerTileAccessible::GetRoleInternal(PRUint32 *aRole)
{
@ -63,15 +80,14 @@ nsXULColorPickerTileAccessible::GetRoleInternal(PRUint32 *aRole)
return NS_OK;
}
/**
* Possible states: focused, focusable, selected
*/
nsresult
nsXULColorPickerTileAccessible::GetStateInternal(PRUint32 *aState,
PRUint32 *aExtraState)
{
// Possible states: focused, focusable, selected.
// get focus and disable status from base class
nsresult rv = nsFormControlAccessible::GetStateInternal(aState, aExtraState);
nsresult rv = nsAccessibleWrap::GetStateInternal(aState, aExtraState);
NS_ENSURE_A11Y_SUCCESS(rv, rv);
*aState |= nsIAccessibleStates::STATE_FOCUSABLE;
@ -92,19 +108,10 @@ nsXULColorPickerTileAccessible::GetStateInternal(PRUint32 *aState,
return NS_OK;
}
NS_IMETHODIMP nsXULColorPickerTileAccessible::GetValue(nsAString& _retval)
{
if (!mDOMNode)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));
NS_ASSERTION(element, "No XUL Element for colorpicker");
return element->GetAttribute(NS_LITERAL_STRING("color"), _retval);
}
/**
* XUL Color Picker
*/
////////////////////////////////////////////////////////////////////////////////
// nsXULColorPickerAccessible
////////////////////////////////////////////////////////////////////////////////
/**
* Default Constructor
@ -114,15 +121,30 @@ nsXULColorPickerTileAccessible(aNode, aShell)
{
}
/**
* Possible states: focused, focusable, unavailable(disabled)
*/
////////////////////////////////////////////////////////////////////////////////
// nsXULColorPickerAccessible: nsAccessNode
nsresult
nsXULColorPickerAccessible::Init()
{
nsresult rv = nsXULColorPickerTileAccessible::Init();
NS_ENSURE_SUCCESS(rv, rv);
nsCoreUtils::GeneratePopupTree(mDOMNode, PR_TRUE);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsXULColorPickerAccessible: nsAccessible
nsresult
nsXULColorPickerAccessible::GetStateInternal(PRUint32 *aState,
PRUint32 *aExtraState)
{
// Possible states: focused, focusable, unavailable(disabled).
// get focus and disable status from base class
nsresult rv = nsFormControlAccessible::GetStateInternal(aState, aExtraState);
nsresult rv = nsAccessibleWrap::GetStateInternal(aState, aExtraState);
NS_ENSURE_A11Y_SUCCESS(rv, rv);
*aState |= nsIAccessibleStates::STATE_FOCUSABLE |
@ -138,3 +160,46 @@ nsXULColorPickerAccessible::GetRoleInternal(PRUint32 *aRole)
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsXULColorPickerAccessible: protected nsAccessible
void
nsXULColorPickerAccessible::CacheChildren()
{
if (IsDefunct()) {
mAccChildCount = eChildCountUninitialized;
return; // This outer doc node has been shut down
}
if (mAccChildCount != eChildCountUninitialized)
return;
mAccChildCount = 0; // Avoid reentry
nsCOMPtr<nsIAccessible> menupopupAccessible;
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
walker.GetFirstChild();
while (walker.mState.accessible) {
PRUint32 role = nsAccUtils::Role(walker.mState.accessible);
if (role == nsIAccessibleRole::ROLE_ALERT) {
// Get an accessbile for menupopup or panel elements.
menupopupAccessible = walker.mState.accessible;
break;
}
walker.GetNextSibling();
}
if (!menupopupAccessible)
return;
SetFirstChild(menupopupAccessible);
nsRefPtr<nsAccessible> menupopupAcc =
nsAccUtils::QueryObject<nsAccessible>(menupopupAccessible);
menupopupAcc->SetParent(this);
mAccChildCount++;
}

View File

@ -40,9 +40,12 @@
#define _nsXULColorPickerAccessible_H_
// NOTE: alphabetically ordered
#include "nsFormControlAccessible.h"
#include "nsAccessibleWrap.h"
class nsXULColorPickerTileAccessible : public nsFormControlAccessible
/**
* Used for color button in colorpicker palette.
*/
class nsXULColorPickerTileAccessible : public nsAccessibleWrap
{
public:
nsXULColorPickerTileAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
@ -55,14 +58,26 @@ public:
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
};
/**
* Used for colorpicker button (xul:colorpicker@type="button").
*/
class nsXULColorPickerAccessible : public nsXULColorPickerTileAccessible
{
public:
nsXULColorPickerAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
// nsAccessNode
virtual nsresult Init();
// nsAccessible
virtual nsresult GetRoleInternal(PRUint32 *aRole);
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
protected:
// nsAccessible
virtual void CacheChildren();
};
#endif

View File

@ -58,7 +58,7 @@ nsresult
nsXULComboboxAccessible::Init()
{
nsresult rv = nsAccessibleWrap::Init();
nsXULMenupopupAccessible::GenerateMenu(mDOMNode);
nsCoreUtils::GeneratePopupTree(mDOMNode);
return rv;
}

View File

@ -56,33 +56,35 @@
#include "nsITextControlFrame.h"
#include "nsIPresShell.h"
/**
* XUL Button: can contain arbitrary HTML content
*/
////////////////////////////////////////////////////////////////////////////////
// nsXULButtonAccessible
////////////////////////////////////////////////////////////////////////////////
/**
* Default Constructor
*/
// Don't inherit from nsFormControlAccessible - it doesn't allow children and a button can have a dropmarker child
nsXULButtonAccessible::nsXULButtonAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
nsAccessibleWrap(aNode, aShell)
{
nsXULButtonAccessible::
nsXULButtonAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell) :
nsAccessibleWrap(aNode, aShell)
{
}
/**
* Only one actions available
*/
NS_IMETHODIMP nsXULButtonAccessible::GetNumActions(PRUint8 *_retval)
////////////////////////////////////////////////////////////////////////////////
// nsXULButtonAccessible: nsISupports
NS_IMPL_ISUPPORTS_INHERITED0(nsXULButtonAccessible, nsAccessible)
////////////////////////////////////////////////////////////////////////////////
// nsXULButtonAccessible: nsIAccessible
NS_IMETHODIMP
nsXULButtonAccessible::GetNumActions(PRUint8 *aCount)
{
*_retval = 1;
NS_ENSURE_ARG_POINTER(aCount);
*aCount = 1;
return NS_OK;
}
/**
* Return the name of our only action
*/
NS_IMETHODIMP nsXULButtonAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
NS_IMETHODIMP
nsXULButtonAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
{
if (aIndex == eAction_Click) {
aName.AssignLiteral("press");
@ -91,20 +93,33 @@ NS_IMETHODIMP nsXULButtonAccessible::GetActionName(PRUint8 aIndex, nsAString& aN
return NS_ERROR_INVALID_ARG;
}
/**
* Tell the button to do its action
*/
NS_IMETHODIMP nsXULButtonAccessible::DoAction(PRUint8 index)
NS_IMETHODIMP
nsXULButtonAccessible::DoAction(PRUint8 aIndex)
{
if (index == 0) {
if (aIndex == 0)
return DoCommand();
}
return NS_ERROR_INVALID_ARG;
}
/**
* We are a pushbutton
*/
////////////////////////////////////////////////////////////////////////////////
// nsXULButtonAccessible: nsAccessNode
nsresult
nsXULButtonAccessible::Init()
{
nsresult rv = nsAccessibleWrap::Init();
NS_ENSURE_SUCCESS(rv, rv);
if (ContainsMenu())
nsCoreUtils::GeneratePopupTree(mDOMNode);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsXULButtonAccessible: nsAccessible
nsresult
nsXULButtonAccessible::GetRoleInternal(PRUint32 *aRole)
{
@ -112,12 +127,11 @@ nsXULButtonAccessible::GetRoleInternal(PRUint32 *aRole)
return NS_OK;
}
/**
* Possible states: focused, focusable, unavailable(disabled)
*/
nsresult
nsXULButtonAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
{
// Possible states: focused, focusable, unavailable(disabled).
// get focus and disable status from base class
nsresult rv = nsAccessible::GetStateInternal(aState, aExtraState);
NS_ENSURE_A11Y_SUCCESS(rv, rv);
@ -152,63 +166,118 @@ nsXULButtonAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
}
}
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));
if (element) {
PRBool isDefault = PR_FALSE;
element->HasAttribute(NS_LITERAL_STRING("default"), &isDefault) ;
if (isDefault)
*aState |= nsIAccessibleStates::STATE_DEFAULT;
if (ContainsMenu())
*aState |= nsIAccessibleStates::STATE_HASPOPUP;
nsAutoString type;
element->GetAttribute(NS_LITERAL_STRING("type"), type);
if (type.EqualsLiteral("menu") || type.EqualsLiteral("menu-button")) {
*aState |= nsIAccessibleStates::STATE_HASPOPUP;
}
}
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
if (content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::_default))
*aState |= nsIAccessibleStates::STATE_DEFAULT;
return NS_OK;
}
void nsXULButtonAccessible::CacheChildren()
////////////////////////////////////////////////////////////////////////////////
// nsXULButtonAccessible: nsAccessible protected
void
nsXULButtonAccessible::CacheChildren()
{
// An XUL button accessible may have 1 child dropmarker accessible
// In general XUL button has not accessible children. Nevertheless menu
// buttons can have button (@type="menu-button") and popup accessibles
// (@type="menu-button" or @type="menu").
if (!mWeakShell) {
mAccChildCount = eChildCountUninitialized;
return; // This outer doc node has been shut down
}
if (mAccChildCount == eChildCountUninitialized) {
mAccChildCount = 0; // Avoid reentry
SetFirstChild(nsnull);
PRBool allowsAnonChildren = GetAllowsAnonChildAccessibles();
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, allowsAnonChildren);
// XXX: no children until the button is menu button. Probably it's not
// totally correct but in general AT wants to have leaf buttons.
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
PRBool isMenu = content->AttrValueIs(kNameSpaceID_None,
nsAccessibilityAtoms::type,
nsAccessibilityAtoms::menu,
eCaseMatters);
PRBool isMenuButton = isMenu ?
PR_FALSE :
content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::type,
nsAccessibilityAtoms::menuButton, eCaseMatters);
if (!isMenu && !isMenuButton)
return;
nsCOMPtr<nsIAccessible> buttonAccessible;
nsCOMPtr<nsIAccessible> menupopupAccessible;
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
walker.GetFirstChild();
nsCOMPtr<nsIAccessible> dropMarkerAccessible;
while (walker.mState.accessible) {
dropMarkerAccessible = walker.mState.accessible;
PRUint32 role = nsAccUtils::Role(walker.mState.accessible);
if (role == nsIAccessibleRole::ROLE_MENUPOPUP) {
// Get an accessbile for menupopup or panel elements.
menupopupAccessible = walker.mState.accessible;
} else if (isMenuButton && role == nsIAccessibleRole::ROLE_PUSHBUTTON) {
// Button type="menu-button" contains a real button. Get an accessible
// for it. Ignore dropmarker button what is placed as a last child.
buttonAccessible = walker.mState.accessible;
break;
}
walker.GetNextSibling();
}
// If the anonymous tree walker can find accessible children,
// and the last one is a push button, then use it as the only accessible
// child -- because this is the scenario where we have a dropmarker child
if (!menupopupAccessible)
return;
if (dropMarkerAccessible) {
if (nsAccUtils::RoleInternal(dropMarkerAccessible) ==
nsIAccessibleRole::ROLE_PUSHBUTTON) {
SetFirstChild(dropMarkerAccessible);
nsRefPtr<nsAccessible> childAcc =
nsAccUtils::QueryAccessible(dropMarkerAccessible);
childAcc->SetNextSibling(nsnull);
childAcc->SetParent(this);
mAccChildCount = 1;
}
SetFirstChild(menupopupAccessible);
nsRefPtr<nsAccessible> menupopupAcc =
nsAccUtils::QueryObject<nsAccessible>(menupopupAccessible);
menupopupAcc->SetParent(this);
mAccChildCount++;
if (buttonAccessible) {
if (menupopupAcc)
menupopupAcc->SetNextSibling(buttonAccessible);
else
SetFirstChild(buttonAccessible);
nsRefPtr<nsAccessible> buttonAcc =
nsAccUtils::QueryObject<nsAccessible>(buttonAccessible);
buttonAcc->SetParent(this);
mAccChildCount++;
}
}
}
/**
* XUL Dropmarker: can contain arbitrary HTML content
*/
////////////////////////////////////////////////////////////////////////////////
// nsXULButtonAccessible protected
PRBool
nsXULButtonAccessible::ContainsMenu()
{
static nsIContent::AttrValuesArray strings[] =
{&nsAccessibilityAtoms::menu, &nsAccessibilityAtoms::menuButton, nsnull};
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
return content->FindAttrValueIn(kNameSpaceID_None, nsAccessibilityAtoms::type,
strings, eCaseMatters) >= 0;
}
////////////////////////////////////////////////////////////////////////////////
// nsXULDropmarkerAccessible
////////////////////////////////////////////////////////////////////////////////
/**
* Default Constructor

View File

@ -46,26 +46,46 @@
#include "nsXULMenuAccessible.h"
#include "nsHyperTextAccessibleWrap.h"
/**
* Used for XUL button.
*
* @note Don't inherit from nsFormControlAccessible - it doesn't allow children
* and a button can have a dropmarker child.
*/
class nsXULButtonAccessible : public nsAccessibleWrap
// Don't inherit from nsFormControlAccessible - it doesn't allow children and a button can have a dropmarker child
{
public:
enum { eAction_Click = 0 };
nsXULButtonAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIAccessible
NS_IMETHOD GetNumActions(PRUint8 *_retval);
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
NS_IMETHOD DoAction(PRUint8 index);
// nsAccessNode
virtual nsresult Init();
// nsAccessible
virtual nsresult GetRoleInternal(PRUint32 *aRole);
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
protected:
// nsAccessible
void CacheChildren();
// nsXULButtonAccessible
PRBool ContainsMenu();
};
/**
* Used for XUL checkbox.
*/
class nsXULCheckboxAccessible : public nsFormControlAccessible
{
public:

View File

@ -273,7 +273,7 @@ nsresult
nsXULMenuitemAccessible::Init()
{
nsresult rv = nsAccessibleWrap::Init();
nsXULMenupopupAccessible::GenerateMenu(mDOMNode);
nsCoreUtils::GeneratePopupTree(mDOMNode);
return rv;
}
@ -642,46 +642,6 @@ nsXULMenupopupAccessible::GetStateInternal(PRUint32 *aState,
return NS_OK;
}
already_AddRefed<nsIDOMNode>
nsXULMenupopupAccessible::FindInNodeList(nsIDOMNodeList *aNodeList,
nsIAtom *aAtom, PRUint32 aNameSpaceID)
{
PRUint32 numChildren;
if (!aNodeList || NS_FAILED(aNodeList->GetLength(&numChildren))) {
return nsnull;
}
nsCOMPtr<nsIDOMNode> childNode;
for (PRUint32 childIndex = 0; childIndex < numChildren; childIndex++) {
aNodeList->Item(childIndex, getter_AddRefs(childNode));
nsCOMPtr<nsIContent> content = do_QueryInterface(childNode);
if (content && content->NodeInfo()->Equals(aAtom, kNameSpaceID_XUL)) {
nsIDOMNode *matchNode = childNode;
NS_ADDREF(matchNode);
return matchNode;
}
}
return nsnull;
}
void nsXULMenupopupAccessible::GenerateMenu(nsIDOMNode *aNode)
{
// Set menugenerated="true" on the menupopup node to generate the
// sub-menu items if they have not been generated
nsCOMPtr<nsIDOMNodeList> nodeList;
aNode->GetChildNodes(getter_AddRefs(nodeList));
nsCOMPtr<nsIDOMNode> menuPopup = FindInNodeList(nodeList, nsAccessibilityAtoms::menupopup,
kNameSpaceID_XUL);
nsCOMPtr<nsIDOMElement> popupElement(do_QueryInterface(menuPopup));
if (popupElement) {
nsAutoString attr;
popupElement->GetAttribute(NS_LITERAL_STRING("menugenerated"), attr);
if (!attr.EqualsLiteral("true")) {
popupElement->SetAttribute(NS_LITERAL_STRING("menugenerated"), NS_LITERAL_STRING("true"));
}
}
}
nsresult
nsXULMenupopupAccessible::GetNameInternal(nsAString& aName)
{
@ -704,15 +664,23 @@ nsXULMenupopupAccessible::GetRoleInternal(PRUint32 *aRole)
nsCOMPtr<nsIAccessible> parent;
GetParent(getter_AddRefs(parent));
if (parent) {
// Some widgets like the search bar have several popups, owned by buttons
PRUint32 role = nsAccUtils::Role(parent);
if (role == nsIAccessibleRole::ROLE_COMBOBOX ||
role == nsIAccessibleRole::ROLE_PUSHBUTTON ||
role == nsIAccessibleRole::ROLE_AUTOCOMPLETE) {
*aRole = nsIAccessibleRole::ROLE_COMBOBOX_LIST;
return NS_OK;
} else if (role == nsIAccessibleRole::ROLE_PUSHBUTTON) {
// Some widgets like the search bar have several popups, owned by buttons.
nsCOMPtr<nsIAccessible> grandParent;
parent->GetParent(getter_AddRefs(grandParent));
if (role == nsIAccessibleRole::ROLE_AUTOCOMPLETE) {
*aRole = nsIAccessibleRole::ROLE_COMBOBOX_LIST;
return NS_OK;
}
}
}
*aRole = nsIAccessibleRole::ROLE_MENUPOPUP;
return NS_OK;
}

View File

@ -113,6 +113,10 @@ public:
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
};
/**
* Used for XUL menupopup and panel.
*/
class nsXULMenupopupAccessible : public nsXULSelectableAccessible
{
public:
@ -122,11 +126,6 @@ public:
virtual nsresult GetNameInternal(nsAString& aName);
virtual nsresult GetRoleInternal(PRUint32 *aRole);
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
// nsXULMenupopupAccessible
static already_AddRefed<nsIDOMNode> FindInNodeList(nsIDOMNodeList *aNodeList,
nsIAtom *aAtom, PRUint32 aNameSpaceID);
static void GenerateMenu(nsIDOMNode *aNode);
};
class nsXULMenubarAccessible : public nsAccessibleWrap

View File

@ -42,6 +42,8 @@ srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = accessible
DIRS = tree
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
@ -88,13 +90,9 @@ _TEST_FILES =\
$(warning test_childAtPoint.xul temporarily disabled) \
test_cssattrs.html \
test_descr.html \
test_elm_filectrl.html \
test_elm_listbox.xul \
$(warning test_elm_media.html temporarily disabled) \
test_elm_plugin.html \
test_elm_select.html \
test_elm_tree.xul \
test_elm_txtcntnr.html \
test_events_caretmove.html \
test_events_coalescence.html \
test_events_doc.html \
@ -102,6 +100,7 @@ _TEST_FILES =\
test_events_flush.html \
test_events_focus.html \
test_events_focus.xul \
test_events_focusdoc.html \
test_events_mutation.html \
test_events_scroll.xul \
test_events_tree.xul \

View File

@ -4,6 +4,8 @@
const ROLE_ALERT = nsIAccessibleRole.ROLE_ALERT;
const ROLE_APPLICATION = nsIAccessibleRole.ROLE_APPLICATION;
const ROLE_APP_ROOT = nsIAccessibleRole.ROLE_APP_ROOT;
const ROLE_AUTOCOMPLETE = nsIAccessibleRole.ROLE_AUTOCOMPLETE;
const ROLE_BUTTONDROPDOWNGRID = nsIAccessibleRole.ROLE_BUTTONDROPDOWNGRID;
const ROLE_CAPTION = nsIAccessibleRole.ROLE_CAPTION;
const ROLE_CELL = nsIAccessibleRole.ROLE_CELL;
const ROLE_CHROME_WINDOW = nsIAccessibleRole.ROLE_CHROME_WINDOW;
@ -27,11 +29,14 @@ const ROLE_LINK = nsIAccessibleRole.ROLE_LINK;
const ROLE_LIST = nsIAccessibleRole.ROLE_LIST;
const ROLE_LISTBOX = nsIAccessibleRole.ROLE_LISTBOX;
const ROLE_LISTITEM = nsIAccessibleRole.ROLE_LISTITEM;
const ROLE_MENUITEM = nsIAccessibleRole.ROLE_MENUITEM;
const ROLE_MENUPOPUP = nsIAccessibleRole.ROLE_MENUPOPUP;
const ROLE_NOTHING = nsIAccessibleRole.ROLE_NOTHING;
const ROLE_OPTION = nsIAccessibleRole.ROLE_OPTION;
const ROLE_OUTLINE = nsIAccessibleRole.ROLE_OUTLINE;
const ROLE_OUTLINEITEM = nsIAccessibleRole.ROLE_OUTLINEITEM;
const ROLE_PARAGRAPH = nsIAccessibleRole.ROLE_PARAGRAPH;
const ROLE_PARENT_MENUITEM = nsIAccessibleRole.ROLE_PARENT_MENUITEM;
const ROLE_PASSWORD_TEXT = nsIAccessibleRole.ROLE_PASSWORD_TEXT;
const ROLE_PROGRESSBAR = nsIAccessibleRole.ROLE_PROGRESSBAR;
const ROLE_PUSHBUTTON = nsIAccessibleRole.ROLE_PUSHBUTTON;

View File

@ -35,6 +35,9 @@
// attribute.
testDescr("img3", "description");
// Description from content of h2.
testDescr("p", "heading");
SimpleTest.finish();
}
@ -61,5 +64,7 @@
<img id="img2" title="title" />
<img id="img3" alt="name" title="description" />
<h2 id="heading">heading</h2>
<p id="p" aria-describedby="heading" role="button">click me</p>
</body>
</html>

View File

@ -0,0 +1,102 @@
<html>
<head>
<title>Accessible document focus event testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/events.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/states.js"></script>
<script type="application/javascript">
/**
* Focus invoker.
*/
function takeFocus(aAcc)
{
this.DOMNode = aAcc; // xxx rename this expected property in events.js
this.invoke = function takeFocus_invoke()
{
this.DOMNode.takeFocus();
};
this.check = function takeFocus_check()
{
testStates(this.DOMNode, STATE_FOCUSABLE | STATE_FOCUSED);
};
this.getID = function takeFocus_getID() { return aAcc.name + " focus"; };
}
/**
* Do tests.
*/
var gQueue = null;
//var gA11yEventDumpID = "eventdump";
function doTests()
{
// setup
var frameDoc = document.getElementById("iframe").contentDocument;
frameDoc.designMode = "on";
var frameDocAcc = getAccessible(frameDoc, [nsIAccessibleDocument]);
var buttonAcc = getAccessible("b1");
// Test focus events.
gQueue = new eventQueue(nsIAccessibleEvent.EVENT_FOCUS);
// try to give focus to contentEditable frame twice to cover bug 512059
gQueue.push(new takeFocus(buttonAcc));
gQueue.push(new takeFocus(frameDocAcc));
gQueue.push(new takeFocus(buttonAcc));
gQueue.push(new takeFocus(frameDocAcc));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=512058"
title="Can't set focus to designMode document via accessibility APIs">
Mozilla Bug 512058
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=512059"
title="Accessibility focus event never fired for designMode document after the first focus">
Mozilla Bug 512059
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="eventdump"></div>
<div id="testContainer">
<button id="b1">a button</button>
<iframe id="iframe" src="about:blank"></iframe>
<button id="b2">a button</button>
</div>
</body>
</html>

View File

@ -0,0 +1,61 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Mozilla Corporation.
# Portions created by the Initial Developer are Copyright (C) 2009
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Alexander Surkov <surkov.alexander@gmail.com> (original author)
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = accessible/tree
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES =\
test_button.xul \
test_colorpicker.xul \
test_combobox.xul \
test_filectrl.html \
test_media.html \
test_menu.xul \
test_select.html \
test_tree.xul \
test_txtctrl.html \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)

View File

@ -0,0 +1,198 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible XUL button hierarchy tests">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/role.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Test
function doTest()
{
//////////////////////////////////////////////////////////////////////////
// button1
var accTree = {
role: ROLE_PUSHBUTTON,
name: "hello",
children: [ ]
};
testAccessibleTree("button1", accTree);
//////////////////////////////////////////////////////////////////////////
// button2
accTree = {
role: ROLE_PUSHBUTTON,
name: "hello",
children: [
{
role: ROLE_MENUPOPUP,
children: [
{
role: ROLE_MENUITEM
},
{
role: ROLE_MENUITEM
}
]
}
]
};
testAccessibleTree("button2", accTree);
//////////////////////////////////////////////////////////////////////////
// button3
accTree = {
role: ROLE_PUSHBUTTON,
name: "hello",
children: [
{
role: ROLE_MENUPOPUP,
children: [
{
role: ROLE_MENUITEM
},
{
role: ROLE_MENUITEM
}
]
},
{
role: ROLE_PUSHBUTTON,
children: [
]
}
]
};
testAccessibleTree("button3", accTree);
//////////////////////////////////////////////////////////////////////////
// button4
var accTree = {
role: ROLE_PUSHBUTTON,
name: "hello",
children: [ ]
};
testAccessibleTree("button4", accTree);
//////////////////////////////////////////////////////////////////////////
// button5
accTree = {
role: ROLE_PUSHBUTTON,
name: "hello",
children: [
{
role: ROLE_MENUPOPUP,
children: [
{
role: ROLE_MENUITEM
},
{
role: ROLE_MENUITEM
}
]
}
]
};
testAccessibleTree("button5", accTree);
//////////////////////////////////////////////////////////////////////////
// button6
accTree = {
role: ROLE_PUSHBUTTON,
name: "hello",
children: [
{
role: ROLE_MENUPOPUP,
children: [
{
role: ROLE_MENUITEM
},
{
role: ROLE_MENUITEM
}
]
},
{
role: ROLE_PUSHBUTTON,
children: [
]
}
]
};
testAccessibleTree("button6", accTree);
SimpleTest.finish()
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=249292"
title="Ensure accessible children for toolbarbutton types 'menu' and 'menu-button'">
Mozilla Bug 249292
</a><br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<button id="button1" label="hello"/>
<button id="button2" type="menu" label="hello">
<menupopup>
<menuitem label="menuitem"/>
<menuitem label="menuitem"/>
</menupopup>
</button>
<button id="button3" type="menu-button" label="hello">
<menupopup>
<menuitem label="menuitem"/>
<menuitem label="menuitem"/>
</menupopup>
</button>
<toolbarbutton id="button4" label="hello"/>
<toolbarbutton id="button5" type="menu" label="hello">
<menupopup>
<menuitem label="menuitem"/>
<menuitem label="menuitem"/>
</menupopup>
</toolbarbutton>
<toolbarbutton id="button6" type="menu-button" label="hello">
<menupopup>
<menuitem label="menuitem"/>
<menuitem label="menuitem"/>
</menupopup>
</toolbarbutton>
</vbox>
</hbox>
</window>

View File

@ -0,0 +1,75 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible XUL button hierarchy tests">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/role.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Test
function doTest()
{
//////////////////////////////////////////////////////////////////////////
// button1
var accTree = {
role: ROLE_BUTTONDROPDOWNGRID,
children: [
{
role: ROLE_ALERT,
children: [ ]
}
]
};
var colorButtons = accTree.children[0].children;
for (var idx = 0; idx < 70; idx++) {
var obj = { role: ROLE_PUSHBUTTON };
colorButtons.push(obj);
}
testAccessibleTree("colorpicker", accTree);
SimpleTest.finish()
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=249292"
title="Ensure accessible children for toolbarbutton types 'menu' and 'menu-button'">
Mozilla Bug 249292
</a><br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<colorpicker id="colorpicker" type="button"/>
</vbox>
</hbox>
</window>

View File

@ -0,0 +1,138 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible XUL menulist and textbox @autocomplete hierarchy tests">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/role.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Test
function doTest()
{
//////////////////////////////////////////////////////////////////////////
// menulist
var accTree = {
role: ROLE_COMBOBOX,
children: [
{
role: ROLE_COMBOBOX_LIST,
children: [
{
role: ROLE_COMBOBOX_OPTION
},
{
role: ROLE_COMBOBOX_OPTION
}
]
}
]
};
testAccessibleTree("menulist", accTree);
//////////////////////////////////////////////////////////////////////////
// textbox@type=autocomplete #1 (history)
accTree = {
role: ROLE_AUTOCOMPLETE,
children: [
{
role: ROLE_ENTRY,
children: [
{
role: ROLE_TEXT_LEAF
}
]
},
{
role: ROLE_COMBOBOX_LIST, // context menu popup
children: [ ]
}
]
};
testAccessibleTree("autocomplete", accTree);
//////////////////////////////////////////////////////////////////////////
// textbox@type=autocomplete #2 (child menupoup)
accTree = {
role: ROLE_AUTOCOMPLETE,
children: [
{
role: ROLE_COMBOBOX_LIST, // autocomplete menu popup
children: [
{
role: ROLE_COMBOBOX_OPTION
}
]
},
{
role: ROLE_ENTRY,
children: [ ]
},
{
role: ROLE_COMBOBOX_LIST, // context menu popup
children: [ ]
}
]
};
testAccessibleTree("autocomplete2", accTree);
SimpleTest.finish()
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=249292"
title="Ensure accessible children for toolbarbutton types 'menu' and 'menu-button'">
Mozilla Bug 249292
</a><br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<menulist id="menulist">
<menupopup>
<menuitem label="item"/>
<menuitem label="item"/>
</menupopup>
</menulist>
<textbox id="autocomplete" type="autocomplete"
autocompletesearch="history"
value="http://localhost:8888/redirect-a11y.html"/>
<textbox id="autocomplete2" type="autocomplete">
<menupopup>
<menuitem label="item1"/>
</menupopup>
</textbox>
</vbox>
</hbox>
</window>

View File

@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=483573
-->
<head>
<title>HTML5 audio/video tests</title>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/role.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/states.js"></script>
<script type="application/javascript">
function doTest()
{
//////////////////////////////////////////////////////////////////////////
// test the accessible tree
var accTree = {
role: ROLE_GROUPING,
children: [
{ // start/stop button
role: ROLE_PUSHBUTTON
},
{ // buffer bar
role: ROLE_PROGRESSBAR
},
{ // progress bar
role: ROLE_PROGRESSBAR
},
{ // slider of progress bar
role: ROLE_SLIDER
},
{ // mute button
role: ROLE_PUSHBUTTON
}
]
};
testAccessibleTree("audio", accTree);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
title="Expose HTML5 video and audio elements' embedded controls through accessibility APIs"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=483573">Mozilla Bug 483573</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<audio id="audio" src="chrome://mochikit/content/a11y/accessible/bug461281.ogg"
controls="true"></audio>
<div id="eventDump"></div>
</body>
</html>

View File

@ -0,0 +1,86 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible XUL menu hierarchy tests">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/role.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Test
function doTest()
{
if (LINUX) {
// XXX: bug 527646
todo(false, "Failure on linux.");
SimpleTest.finish();
return;
}
var accTree = {
role: ROLE_PARENT_MENUITEM,
name: "menu",
children: [
{
role: ROLE_MENUPOPUP,
children: [
{
role: ROLE_MENUITEM
},
{
role: ROLE_MENUITEM
}
]
}
]
};
testAccessibleTree("menu", accTree);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=249292"
title="Ensure accessible children for toolbarbutton types 'menu' and 'menu-button'">
Mozilla Bug 249292
</a><br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<menu id="menu" label="menu">
<menupopup>
<menuitem label="menuitem"/>
<menuitem label="menuitem"/>
</menupopup>
</menu>
</vbox>
</hbox>
</window>

View File

@ -1288,7 +1288,7 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
}
let NP = {};
Cu.import("resource://gre/modules/NetworkPrioritizer.jsm", NP);
Cu.import("resource:///modules/NetworkPrioritizer.jsm", NP);
NP.trackBrowserWindow(window);
// initialize the session-restore service (in case it's not already running)

View File

@ -138,6 +138,10 @@ window.addEventListener("unload", function () {
}
}, false);
window.addEventListener("deactivate", function () {
window.close();
}, false);
window.addEventListener("keypress", function (event) {
if (event.keyCode == event.DOM_VK_ESCAPE) {
window.close();

View File

@ -49,7 +49,7 @@ try {
// not critical, remain silent
}
Components.utils.import("resource://gre/modules/openLocationLastURL.jsm");
Components.utils.import("resource:///modules/openLocationLastURL.jsm");
function onLoad()
{

View File

@ -283,6 +283,11 @@ function onLoadPageInfo()
window.arguments.length >= 1 &&
window.arguments[0];
if (!args || !args.doc) {
gWindow = window.opener.content;
gDocument = gWindow.document;
}
// init media view
var imageTree = document.getElementById("imagetree");
imageTree.view = gImageView;
@ -339,6 +344,7 @@ function resetPageInfo(args)
/* Call registered overlay reset functions */
onResetRegistry.forEach(function(func) { func(); });
/* Rebuild the data */
loadTab(args);
}
@ -383,18 +389,7 @@ function loadTab(args)
gDocument = args.doc;
gWindow = gDocument.defaultView;
}
else {
if ("gBrowser" in window.opener)
gWindow = window.opener.gBrowser.contentWindow;
else
gWindow = window.opener.frames[0];
gDocument = gWindow.document;
}
if (args && args.imageElement)
gImageElement = args.imageElement;
/* Rebuild the data */
gImageElement = args && args.imageElement;
/* Load the page info */
@ -597,6 +592,8 @@ function addImage(url, type, alt, elem, isBg)
else {
var i = gImageHash[url][type][alt];
gImageView.data[i][COL_IMAGE_COUNT]++;
if (elem == gImageElement)
gImageView.data[i][COL_IMAGE_NODE] = elem;
}
}
@ -1184,6 +1181,8 @@ function selectImage() {
for (var i = 0; i < tree.view.rowCount; i++) {
if (gImageElement == gImageView.data[i][COL_IMAGE_NODE]) {
tree.view.selection.select(i);
tree.treeBoxObject.ensureRowIsVisible(i);
tree.focus();
return;
}
}

View File

@ -83,7 +83,7 @@ function disableAddons() {
var em = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager);
var type = nsIUpdateItem.TYPE_EXTENSION + nsIUpdateItem.TYPE_LOCALE;
var items = em.getItemList(type, { });
var items = em.getItemList(type);
for (var i = 0; i < items.length; ++i)
em.disableItem(items[i].id);
@ -96,7 +96,7 @@ function disableAddons() {
// Disable plugins
var phs = Components.classes["@mozilla.org/plugin/host;1"]
.getService(Components.interfaces.nsIPluginHost);
var plugins = phs.getPluginTags({ });
var plugins = phs.getPluginTags();
for (i = 0; i < plugins.length; ++i)
plugins[i].disabled = true;
}

View File

@ -356,19 +356,19 @@ Sanitizer.prototype = {
{
// Clear site-specific permissions like "Allow this site to open popups"
var pm = Components.classes["@mozilla.org/permissionmanager;1"]
.getService(Components.interfaces.nsIPermissionManager);
.getService(Components.interfaces.nsIPermissionManager);
pm.removeAll();
// Clear site-specific settings like page-zoom level
var cps = Components.classes["@mozilla.org/content-pref/service;1"]
.getService(Components.interfaces.nsIContentPrefService);
.getService(Components.interfaces.nsIContentPrefService);
cps.removeGroupedPrefs();
// Clear "Never remember passwords for this site", which is not handled by
// the permission manager
var pwmgr = Components.classes["@mozilla.org/login-manager;1"]
.getService(Components.interfaces.nsILoginManager);
var hosts = pwmgr.getAllDisabledHosts({})
.getService(Components.interfaces.nsILoginManager);
var hosts = pwmgr.getAllDisabledHosts();
for each (var host in hosts) {
pwmgr.setLoginSavingEnabled(host, true);
}

View File

@ -1514,9 +1514,9 @@
var l = this.mTabs.length - this._removingTabs.length;
var newTab = false;
if (l == 1) {
closeWindow = aCloseWindowWithLastTab != null ?
aCloseWindowWithLastTab :
this.mPrefs.getBoolPref("browser.tabs.closeWindowWithLastTab");
closeWindow = aCloseWindowWithLastTab != null ? aCloseWindowWithLastTab :
!window.toolbar.visible ||
this.mPrefs.getBoolPref("browser.tabs.closeWindowWithLastTab");
// Closing the tab and replacing it with a blank one is notably slower
// than closing the window right away. If the caller opts in, take

View File

@ -97,6 +97,7 @@ _BROWSER_FILES = \
browser_bug455852.js \
browser_bug462673.js \
browser_bug481560.js \
browser_bug484315.js \
browser_bug477014.js \
browser_bug495058.js \
browser_bug517902.js \

View File

@ -104,31 +104,31 @@ function test() {
window_B.addEventListener("load", function(aEvent) {
window_B.removeEventListener("load", arguments.callee, false);
window_B.gBrowser.addEventListener("load", function(aEvent) {
// waitForFocus can attach to the wrong "window" with about:blank loading first
// So just ensure that we're getting the load event for the right URI
if (window_B.gBrowser.currentURI.spec == "about:blank")
return;
window_B.gBrowser.removeEventListener("load", arguments.callee, true);
// On Linux, waitForFocus doesn't work if the window is already focused,
// so focus window_A first.
waitForFocus(function() {
isWindowState(window_A, [10, 0]);
isWindowState(window_B, [-10]);
waitForFocus(function() {
isWindowState(window_A, [10, 0]);
isWindowState(window_B, [-10]);
isWindowState(window_A, [0, -10]);
isWindowState(window_B, [0]);
waitForFocus(function() {
isWindowState(window_A, [0, -10]);
isWindowState(window_B, [0]);
isWindowState(window_A, [10, 0]);
isWindowState(window_B, [-10]);
waitForFocus(function() {
isWindowState(window_A, [10, 0]);
isWindowState(window_B, [-10]);
// And we're done. Cleanup & run the next test
window_B.close();
window_A.gBrowser.removeTab(tab_A3);
executeSoon(runNextTest);
}, window_B);
}, window_A);
}, window_B);
}, window_A);
// And we're done. Cleanup & run the next test
window_B.close();
window_A.gBrowser.removeTab(tab_A3);
executeSoon(runNextTest);
}, window_B);
}, window_A);
}, window_B);
}, true);
}, false);

View File

@ -1,15 +1,6 @@
function test() {
waitForExplicitFinish();
// focus the url field so that it will can ensure the focus is there when
// the window is refocused after the dialog closes
gURLBar.focus();
window.addEventListener("focus", function () {
window.removeEventListener("focus", arguments.callee, false);
finish();
}, false);
var win = openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
win.addEventListener("load", function () {
@ -18,13 +9,15 @@ function test() {
win.content.addEventListener("focus", function () {
win.content.removeEventListener("focus", arguments.callee, false);
win.gBrowser.selectedTab.addEventListener("TabClose", function () {
ok(false, "shouldn't have gotten the TabClose event for the last tab");
}, false);
EventUtils.synthesizeKey("w", { accelKey: true }, win);
ok(win.closed, "accel+w closed the window immediately");
}, false);
win.gBrowser.selectedTab.addEventListener("TabClose", function () {
ok(false, "shouldn't have gotten the TabClose event for the last tab");
finish();
}, false);
}, false);
}

View File

@ -0,0 +1,25 @@
function test() {
var contentWin = window.open("about:blank", "", "width=100,height=100");
var enumerator = Cc["@mozilla.org/appshell/window-mediator;1"]
.getService(Ci.nsIWindowMediator)
.getEnumerator("navigator:browser");
while (enumerator.hasMoreElements()) {
let win = enumerator.getNext();
if (win.content == contentWin) {
gPrefService.setBoolPref("browser.tabs.closeWindowWithLastTab", false);
win.gBrowser.removeCurrentTab();
ok(win.closed, "popup is closed");
// clean up
if (!win.closed)
win.close();
if (gPrefService.prefHasUserValue("browser.tabs.closeWindowWithLastTab"))
gPrefService.clearUserPref("browser.tabs.closeWindowWithLastTab");
return;
}
}
throw "couldn't find the content window";
}

View File

@ -33,5 +33,6 @@ function test() {
"data:text/html," +
"<img src='about:logo?a' height=200 width=250>" +
"<img src='about:logo?b' height=200 width=250 alt=1>" +
"<img src='about:logo?b' height=200 width=250 alt=2>" +
"<img src='about:logo?b' height=100 width=150 alt=2 id='test-image'>";
}

View File

@ -6,7 +6,7 @@ var gNextTest = null;
function get_test_plugin() {
var ph = Components.classes["@mozilla.org/plugin/host;1"]
.getService(Components.interfaces.nsIPluginHost);
var tags = ph.getPluginTags({});
var tags = ph.getPluginTags();
// Find the test plugin
for (var i = 0; i < tags.length; i++) {

View File

@ -198,11 +198,15 @@ function openUILinkIn( url, where, allowThirdPartyFixup, postData, referrerUrl )
createInstance(Ci.nsISupportsString);
wuri.data = url;
var allowThirdPartyFixupSupports = Cc["@mozilla.org/supports-PRBool;1"].
createInstance(Ci.nsISupportsPRBool);
allowThirdPartyFixupSupports.data = allowThirdPartyFixup;
sa.AppendElement(wuri);
sa.AppendElement(null);
sa.AppendElement(referrerUrl);
sa.AppendElement(postData);
sa.AppendElement(allowThirdPartyFixup);
sa.AppendElement(allowThirdPartyFixupSupports);
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);

View File

@ -36,6 +36,7 @@ LOCAL_INCLUDES = \
-I$(srcdir)/../places/src \
-I$(srcdir)/../privatebrowsing/src \
-I$(srcdir)/../about \
-I$(srcdir)/../dirprovider \
$(NULL)
ifeq ($(OS_ARCH),WINNT)
@ -47,6 +48,7 @@ SHARED_LIBRARY_LIBS = \
../places/src/$(LIB_PREFIX)browserplaces_s.$(LIB_SUFFIX) \
../privatebrowsing/src/$(LIB_PREFIX)privatebrowsing_s.$(LIB_SUFFIX) \
../about/$(LIB_PREFIX)browserabout_s.$(LIB_SUFFIX) \
../dirprovider/$(LIB_PREFIX)browserdir_s.$(LIB_SUFFIX) \
$(NULL)
ifneq (,$(filter windows cocoa gtk2, $(MOZ_WIDGET_TOOLKIT)))

View File

@ -106,3 +106,6 @@
#define NS_BROWSER_ABOUT_REDIRECTOR_CID \
{ 0x7e4bb6ad, 0x2fc4, 0x4dc6, { 0x89, 0xef, 0x23, 0xe8, 0xe5, 0xcc, 0xf9, 0x80 } }
// {6DEB193C-F87D-4078-BC78-5E64655B4D62}
#define NS_BROWSERDIRECTORYPROVIDER_CID \
{ 0x6deb193c, 0xf87d, 0x4078, { 0xbc, 0x78, 0x5e, 0x64, 0x65, 0x5b, 0x4d, 0x62 } }

View File

@ -39,6 +39,7 @@
#include "nsIGenericFactory.h"
#include "nsBrowserCompsCID.h"
#include "DirectoryProvider.h"
#include "nsPlacesImportExportService.h"
#if defined(XP_WIN)
@ -84,6 +85,7 @@ using namespace mozilla::browser;
/////////////////////////////////////////////////////////////////////////////
NS_GENERIC_FACTORY_CONSTRUCTOR(DirectoryProvider)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsPlacesImportExportService)
#if defined(XP_WIN)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindowsShellService)
@ -124,6 +126,14 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrivateBrowsingServiceWrapper, Init)
static const nsModuleComponentInfo components[] =
{
{ "Browser Directory Provider",
NS_BROWSERDIRECTORYPROVIDER_CID,
NS_BROWSERDIRECTORYPROVIDER_CONTRACTID,
DirectoryProviderConstructor,
DirectoryProvider::Register,
DirectoryProvider::Unregister
},
#if defined(XP_WIN)
{ "Browser Shell Service",
NS_SHELLSERVICE_CID,

View File

@ -36,6 +36,7 @@
* ***** END LICENSE BLOCK ***** */
#include "nsIDirectoryService.h"
#include "DirectoryProvider.h"
#include "nsIFile.h"
#include "nsISimpleEnumerator.h"
@ -56,52 +57,15 @@
#include "nsStringAPI.h"
#include "nsXULAppAPI.h"
class nsBrowserDirectoryProvider :
public nsIDirectoryServiceProvider2
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDIRECTORYSERVICEPROVIDER
NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
namespace mozilla {
namespace browser {
static NS_METHOD Register(nsIComponentManager* aCompMgr,
nsIFile* aPath, const char *aLoaderStr,
const char *aType,
const nsModuleComponentInfo *aInfo);
static NS_METHOD Unregister(nsIComponentManager* aCompMgr,
nsIFile* aPath, const char *aLoaderStr,
const nsModuleComponentInfo *aInfo);
private:
nsresult RestoreBookmarksFromBackup(const nsACString& aLeafName,
nsIFile* aParentDir, nsIFile* aTarget);
void EnsureProfileFile(const nsACString& aLeafName,
nsIFile* aParentDir, nsIFile* aTarget);
class AppendingEnumerator : public nsISimpleEnumerator
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
AppendingEnumerator(nsISimpleEnumerator* aBase,
char const *const *aAppendList);
private:
nsCOMPtr<nsISimpleEnumerator> mBase;
char const *const *const mAppendList;
nsCOMPtr<nsIFile> mNext;
};
};
NS_IMPL_ISUPPORTS2(nsBrowserDirectoryProvider,
NS_IMPL_ISUPPORTS2(DirectoryProvider,
nsIDirectoryServiceProvider,
nsIDirectoryServiceProvider2)
NS_IMETHODIMP
nsBrowserDirectoryProvider::GetFile(const char *aKey, PRBool *aPersist,
nsIFile* *aResult)
DirectoryProvider::GetFile(const char *aKey, PRBool *aPersist, nsIFile* *aResult)
{
nsresult rv;
@ -290,8 +254,7 @@ AppendDistroSearchDirs(nsIProperties* aDirSvc, nsCOMArray<nsIFile> &array)
}
NS_IMETHODIMP
nsBrowserDirectoryProvider::GetFiles(const char *aKey,
nsISimpleEnumerator* *aResult)
DirectoryProvider::GetFiles(const char *aKey, nsISimpleEnumerator* *aResult)
{
nsresult rv;
@ -331,17 +294,10 @@ nsBrowserDirectoryProvider::GetFiles(const char *aKey,
return NS_ERROR_FAILURE;
}
static char const kContractID[] = "@mozilla.org/browser/directory-provider;1";
// {6DEB193C-F87D-4078-BC78-5E64655B4D62}
#define NS_BROWSERDIRECTORYPROVIDER_CID \
{ 0x6deb193c, 0xf87d, 0x4078, { 0xbc, 0x78, 0x5e, 0x64, 0x65, 0x5b, 0x4d, 0x62 } }
NS_METHOD
nsBrowserDirectoryProvider::Register(nsIComponentManager* aCompMgr,
nsIFile* aPath, const char *aLoaderStr,
const char *aType,
const nsModuleComponentInfo *aInfo)
DirectoryProvider::Register(nsIComponentManager* aCompMgr, nsIFile* aPath,
const char *aLoaderStr, const char *aType,
const nsModuleComponentInfo *aInfo)
{
nsresult rv;
@ -352,15 +308,16 @@ nsBrowserDirectoryProvider::Register(nsIComponentManager* aCompMgr,
rv = catMan->AddCategoryEntry(XPCOM_DIRECTORY_PROVIDER_CATEGORY,
"browser-directory-provider",
kContractID, PR_TRUE, PR_TRUE, nsnull);
NS_BROWSERDIRECTORYPROVIDER_CONTRACTID,
PR_TRUE, PR_TRUE, nsnull);
return rv;
}
NS_METHOD
nsBrowserDirectoryProvider::Unregister(nsIComponentManager* aCompMgr,
nsIFile* aPath, const char *aLoaderStr,
const nsModuleComponentInfo *aInfo)
DirectoryProvider::Unregister(nsIComponentManager* aCompMgr,
nsIFile* aPath, const char *aLoaderStr,
const nsModuleComponentInfo *aInfo)
{
nsresult rv;
@ -374,32 +331,17 @@ nsBrowserDirectoryProvider::Unregister(nsIComponentManager* aCompMgr,
return rv;
}
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBrowserDirectoryProvider)
static const nsModuleComponentInfo components[] = {
{
"nsBrowserDirectoryProvider",
NS_BROWSERDIRECTORYPROVIDER_CID,
kContractID,
nsBrowserDirectoryProviderConstructor,
nsBrowserDirectoryProvider::Register,
nsBrowserDirectoryProvider::Unregister
}
};
NS_IMPL_NSGETMODULE(BrowserDirProvider, components)
NS_IMPL_ISUPPORTS1(nsBrowserDirectoryProvider::AppendingEnumerator,
nsISimpleEnumerator)
NS_IMPL_ISUPPORTS1(DirectoryProvider::AppendingEnumerator, nsISimpleEnumerator)
NS_IMETHODIMP
nsBrowserDirectoryProvider::AppendingEnumerator::HasMoreElements(PRBool *aResult)
DirectoryProvider::AppendingEnumerator::HasMoreElements(PRBool *aResult)
{
*aResult = mNext ? PR_TRUE : PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsBrowserDirectoryProvider::AppendingEnumerator::GetNext(nsISupports* *aResult)
DirectoryProvider::AppendingEnumerator::GetNext(nsISupports* *aResult)
{
if (aResult)
NS_ADDREF(*aResult = mNext);
@ -440,7 +382,7 @@ nsBrowserDirectoryProvider::AppendingEnumerator::GetNext(nsISupports* *aResult)
return NS_OK;
}
nsBrowserDirectoryProvider::AppendingEnumerator::AppendingEnumerator
DirectoryProvider::AppendingEnumerator::AppendingEnumerator
(nsISimpleEnumerator* aBase,
char const *const *aAppendList) :
mBase(aBase),
@ -449,3 +391,6 @@ nsBrowserDirectoryProvider::AppendingEnumerator::AppendingEnumerator
// Initialize mNext to begin.
GetNext(nsnull);
}
} // namespace browser
} // namespace mozilla

View File

@ -0,0 +1,89 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla Firefox browser.
*
* The Initial Developer of the Original Code is
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef DirectoryProvider_h__
#define DirectoryProvider_h__
#include "nsIDirectoryService.h"
#include "nsComponentManagerUtils.h"
#include "nsISimpleEnumerator.h"
#include "nsIFile.h"
#include "nsIGenericFactory.h"
#define NS_BROWSERDIRECTORYPROVIDER_CONTRACTID \
"@mozilla.org/browser/directory-provider;1"
namespace mozilla {
namespace browser {
class DirectoryProvider : public nsIDirectoryServiceProvider2
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDIRECTORYSERVICEPROVIDER
NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
static NS_METHOD Register(nsIComponentManager* aCompMgr,
nsIFile* aPath, const char *aLoaderStr,
const char *aType,
const nsModuleComponentInfo *aInfo);
static NS_METHOD Unregister(nsIComponentManager* aCompMgr,
nsIFile* aPath, const char *aLoaderStr,
const nsModuleComponentInfo *aInfo);
private:
class AppendingEnumerator : public nsISimpleEnumerator
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
AppendingEnumerator(nsISimpleEnumerator* aBase,
char const *const *aAppendList);
private:
nsCOMPtr<nsISimpleEnumerator> mBase;
char const *const *const mAppendList;
nsCOMPtr<nsIFile> mNext;
};
};
} // namespace browser
} // namespace mozilla
#endif // DirectoryProvider_h__

View File

@ -42,12 +42,13 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = browsercomps
LIBRARY_NAME = browserdirprovider
SHORT_LIBNAME = brwsrdir
IS_COMPONENT = 1
MODULE_NAME = BrowserDirProvider
FORCE_SHARED_LIB = 1
MODULE = browserdir
LIBRARY_NAME = browserdir_s
DIRS = tests
FORCE_STATIC_LIB = 1
FORCE_USE_PIC = 1
# Because we are an application component, link against the CRT statically
# (on Windows, but only if we're not building our own CRT for jemalloc)
@ -55,7 +56,12 @@ ifndef MOZ_MEMORY
USE_STATIC_LIBS = 1
endif
CPPSRCS = nsBrowserDirectoryProvider.cpp
EXPORTS_NAMESPACES = mozilla/browser
EXPORTS_mozilla/browser = DirectoryProvider.h
CPPSRCS = DirectoryProvider.cpp
LOCAL_INCLUDES = -I$(srcdir)/../build
EXTRA_DSO_LDOPTS = \
$(XPCOM_GLUE_LDOPTS) \

View File

@ -0,0 +1,49 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2009
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Ryan Flint <rflint@mozilla.com> (Original Author)
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = browser/components/dirprovider/tests
include $(DEPTH)/config/autoconf.mk
MODULE = test_browserdir
XPCSHELL_TESTS = unit
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,52 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ryan Flint <rflint@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
const Cc = Components.classes;
const Ci = Components.interfaces;
var gProfD = do_get_profile();
var gDirSvc = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
var gPrefSvc = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
function writeTestFile(aParent, aName) {
let file = aParent.clone();
file.append(aName);
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0644);
return file;
}

View File

@ -0,0 +1,46 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ryan Flint <rflint@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
// We need to run this test separately since DirectoryProvider persists BMarks
function run_test() {
let dir = gProfD.clone();
let tfile = writeTestFile(dir, "bookmarkfile.test");
gPrefSvc.setCharPref("browser.bookmarks.file", tfile.path);
let bmarks = gDirSvc.get("BMarks", Ci.nsIFile);
do_check_true(tfile.equals(bmarks));
}

View File

@ -0,0 +1,91 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ryan Flint <rflint@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
function test_usr_micsum() {
let mdir = gProfD.clone();
mdir.append("microsummary-generators");
let tmdir = gDirSvc.get("UsrMicsumGens", Ci.nsIFile);
do_check_true(tmdir.equals(mdir));
if (!tmdir.exists())
tmdir.create(Ci.nsIFile.DIRECTORY_TYPE, 0777);
do_check_true(tmdir.isWritable());
let tfile = writeTestFile(tmdir, "usrmicsum");
do_check_true(tfile.exists());
mdir.append(tfile.leafName);
do_check_true(mdir.exists());
}
function test_app_micsum() {
let mdir = gDirSvc.get("XCurProcD", Ci.nsIFile);
mdir.append("microsummary-generators");
let tmdir = gDirSvc.get("MicsumGens", Ci.nsIFile);
do_check_true(tmdir.equals(mdir));
}
function test_bookmarkhtml() {
let bmarks = gProfD.clone();
bmarks.append("bookmarks.html");
let tbmarks = gDirSvc.get("BMarks", Ci.nsIFile);
do_check_true(bmarks.equals(tbmarks));
}
function test_prefoverride() {
let dir = gDirSvc.get("DefRt", Ci.nsIFile);
dir.append("existing-profile-defaults.js");
let tdir = gDirSvc.get("ExistingPrefOverride", Ci.nsIFile);
do_check_true(dir.equals(tdir));
}
function run_test() {
[test_usr_micsum,
test_app_micsum,
test_bookmarkhtml,
test_prefoverride
].forEach(function(f) {
do_test_pending();
print("Running test: " + f.name);
f();
do_test_finished();
});
}

View File

@ -134,7 +134,8 @@ interface nsIWebContentConverterService : nsIWebContentHandlerRegistrar
* The content type to get handlers for
* @returns An array of nsIWebContentHandlerInfo objects
*/
void getContentHandlers(in AString contentType, out unsigned long count,
void getContentHandlers(in AString contentType,
[optional] out unsigned long count,
[retval,array,size_is(count)] out nsIWebContentHandlerInfo handlers);
/**

View File

@ -1041,7 +1041,7 @@ FeedWriter.prototype = {
// List of web handlers
var wccr = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
getService(Ci.nsIWebContentConverterService);
var handlers = wccr.getContentHandlers(this._getMimeTypeForFeedType(feedType), {});
var handlers = wccr.getContentHandlers(this._getMimeTypeForFeedType(feedType));
if (handlers.length != 0) {
for (var i = 0; i < handlers.length; ++i) {
menuItem = this._document.createElementNS(XUL_NS, "menuitem");

View File

@ -335,23 +335,24 @@ PlacesTreeView.prototype = {
},
_convertPRTimeToString: function PTV__convertPRTimeToString(aTime) {
var timeInMilliseconds = aTime / 1000; // PRTime is in microseconds
const MS_PER_MINUTE = 60000;
const MS_PER_DAY = 86400000;
let timeMs = aTime / 1000; // PRTime is in microseconds
// Date is calculated starting from midnight, so the modulo with a day are
// milliseconds from today's midnight.
// getTimezoneOffset corrects that based on local time.
// 86400000 = 24 * 60 * 60 * 1000 = 1 day
// 60000 = 60 * 1000 = 1 minute
var dateObj = new Date();
var timeZoneOffsetInMs = dateObj.getTimezoneOffset() * 60000;
var now = dateObj.getTime() - timeZoneOffsetInMs;
var midnight = now - (now % (86400000));
// getTimezoneOffset corrects that based on local time, notice midnight
// can have a different offset during DST-change days.
let dateObj = new Date();
let now = dateObj.getTime() - dateObj.getTimezoneOffset() * MS_PER_MINUTE;
let midnight = now - (now % MS_PER_DAY);
midnight += new Date(midnight).getTimezoneOffset() * MS_PER_MINUTE;
var dateFormat = timeInMilliseconds - timeZoneOffsetInMs >= midnight ?
let dateFormat = timeMs >= midnight ?
Ci.nsIScriptableDateFormat.dateFormatNone :
Ci.nsIScriptableDateFormat.dateFormatShort;
var timeObj = new Date(timeInMilliseconds);
let timeObj = new Date(timeMs);
return (this._dateService.FormatDateTime("", dateFormat,
Ci.nsIScriptableDateFormat.timeFormatNoSeconds,
timeObj.getFullYear(), timeObj.getMonth() + 1,

View File

@ -1138,64 +1138,146 @@ var PlacesUIUtils = {
// Get the folder id for the organizer left-pane folder.
get leftPaneFolderId() {
var leftPaneRoot = -1;
var allBookmarksId;
let leftPaneRoot = -1;
let allBookmarksId;
// Shortcuts to services.
var bs = PlacesUtils.bookmarks;
var as = PlacesUtils.annotations;
let bs = PlacesUtils.bookmarks;
let as = PlacesUtils.annotations;
// Get all items marked as being the left pane folder. We should only have
// one of them.
var items = as.getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO);
// This is the list of the left pane queries.
let queries = {
"PlacesRoot": { title: "" },
"History": { title: this.getString("OrganizerQueryHistory") },
"Tags": { title: this.getString("OrganizerQueryTags") },
"AllBookmarks": { title: this.getString("OrganizerQueryAllBookmarks") },
"BookmarksToolbar":
{ title: null,
concreteTitle: PlacesUtils.getString("BookmarksToolbarFolderTitle"),
concreteId: PlacesUtils.toolbarFolderId },
"BookmarksMenu":
{ title: null,
concreteTitle: PlacesUtils.getString("BookmarksMenuFolderTitle"),
concreteId: PlacesUtils.bookmarksMenuFolderId },
"UnfiledBookmarks":
{ title: null,
concreteTitle: PlacesUtils.getString("UnsortedBookmarksFolderTitle"),
concreteId: PlacesUtils.unfiledBookmarksFolderId },
};
// All queries but PlacesRoot.
const EXPECTED_QUERY_COUNT = 6;
// Removes an item and associated annotations, ignoring eventual errors.
function safeRemoveItem(aItemId) {
try {
if (as.itemHasAnnotation(aItemId, ORGANIZER_QUERY_ANNO) &&
!(as.getItemAnnotation(aItemId, ORGANIZER_QUERY_ANNO) in queries)) {
// Some extension annotated their roots with our query annotation,
// so we should not delete them.
return;
}
// removeItemAnnotation does not check if item exists, nor the anno,
// so this is safe to do.
as.removeItemAnnotation(aItemId, ORGANIZER_FOLDER_ANNO);
as.removeItemAnnotation(aItemId, ORGANIZER_QUERY_ANNO);
// This will throw if the annotation is an orphan.
bs.removeItem(aItemId);
}
catch(e) { /* orphan anno */ }
}
// Returns true if item really exists, false otherwise.
function itemExists(aItemId) {
try {
bs.getItemIndex(aItemId);
return true;
}
catch(e) {
return false;
}
}
// Get all items marked as being the left pane folder.
let items = as.getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO, {});
if (items.length > 1) {
// Something went wrong, we cannot have more than one left pane folder,
// remove all left pane folders and continue. We will create a new one.
items.forEach(bs.removeItem);
items.forEach(safeRemoveItem);
}
else if (items.length == 1 && items[0] != -1) {
leftPaneRoot = items[0];
// Check organizer left pane version.
var version = as.getItemAnnotation(leftPaneRoot, ORGANIZER_FOLDER_ANNO);
if (version != ORGANIZER_LEFTPANE_VERSION) {
// If version is not valid we must rebuild the left pane.
bs.removeItem(leftPaneRoot);
// Check that organizer left pane root is valid.
let version = as.getItemAnnotation(leftPaneRoot, ORGANIZER_FOLDER_ANNO);
if (version != ORGANIZER_LEFTPANE_VERSION || !itemExists(leftPaneRoot)) {
// Invalid root, we must rebuild the left pane.
safeRemoveItem(leftPaneRoot);
leftPaneRoot = -1;
}
}
var queriesTitles = {
"PlacesRoot": "",
"History": this.getString("OrganizerQueryHistory"),
// TODO: Bug 489681, Tags needs its own string in places.properties
"Tags": bs.getItemTitle(PlacesUtils.tagsFolderId),
"AllBookmarks": this.getString("OrganizerQueryAllBookmarks"),
"Downloads": this.getString("OrganizerQueryDownloads"),
"BookmarksToolbar": null,
"BookmarksMenu": null,
"UnfiledBookmarks": null
};
if (leftPaneRoot != -1) {
// A valid left pane folder has been found.
// Build the leftPaneQueries Map. This is used to quickly access them
// Build the leftPaneQueries Map. This is used to quickly access them,
// associating a mnemonic name to the real item ids.
delete this.leftPaneQueries;
this.leftPaneQueries = {};
var items = as.getItemsWithAnnotation(ORGANIZER_QUERY_ANNO);
// While looping through queries we will also check for titles validity.
for (var i = 0; i < items.length; i++) {
var queryName = as.getItemAnnotation(items[i], ORGANIZER_QUERY_ANNO);
this.leftPaneQueries[queryName] = items[i];
let items = as.getItemsWithAnnotation(ORGANIZER_QUERY_ANNO, {});
// While looping through queries we will also check for their validity.
let queriesCount = 0;
for(let i = 0; i < items.length; i++) {
let queryName = as.getItemAnnotation(items[i], ORGANIZER_QUERY_ANNO);
// Some extension did use our annotation to decorate their items
// with icons, so we should check only our elements, to avoid dataloss.
if (!(queryName in queries))
continue;
let query = queries[queryName];
query.itemId = items[i];
if (!itemExists(query.itemId)) {
// Orphan annotation, bail out and create a new left pane root.
break;
}
// Check that all queries have valid parents.
let parentId = bs.getFolderIdForItem(query.itemId);
if (items.indexOf(parentId) == -1 && parentId != leftPaneRoot) {
// The parent is not part of the left pane, bail out and create a new
// left pane root.
break;
}
// Titles could have been corrupted or the user could have changed his
// locale. Check title is correctly set and eventually fix it.
if (bs.getItemTitle(items[i]) != queriesTitles[queryName])
bs.setItemTitle(items[i], queriesTitles[queryName]);
// locale. Check title and eventually fix it.
if (bs.getItemTitle(query.itemId) != query.title)
bs.setItemTitle(query.itemId, query.title);
if ("concreteId" in query) {
if (bs.getItemTitle(query.concreteId) != query.concreteTitle)
bs.setItemTitle(query.concreteId, query.concreteTitle);
}
// Add the query to our cache.
this.leftPaneQueries[queryName] = query.itemId;
queriesCount++;
}
if (queriesCount != EXPECTED_QUERY_COUNT) {
// Queries number is wrong, so the left pane must be corrupt.
// Note: we can't just remove the leftPaneRoot, because some query could
// have a bad parent, so we have to remove all items one by one.
items.forEach(safeRemoveItem);
safeRemoveItem(leftPaneRoot);
}
else {
// Everything is fine, return the current left pane folder.
delete this.leftPaneFolderId;
return this.leftPaneFolderId = leftPaneRoot;
}
delete this.leftPaneFolderId;
return this.leftPaneFolderId = leftPaneRoot;
}
// Create a new left pane folder.
var self = this;
var callback = {
// Helper to create an organizer special query.
@ -1203,7 +1285,7 @@ var PlacesUIUtils = {
let itemId = bs.insertBookmark(aParentId,
PlacesUtils._uri(aQueryUrl),
bs.DEFAULT_INDEX,
queriesTitles[aQueryName]);
queries[aQueryName].title);
// Mark as special organizer query.
as.setItemAnnotation(itemId, ORGANIZER_QUERY_ANNO, aQueryName,
0, as.EXPIRE_NEVER);
@ -1219,7 +1301,7 @@ var PlacesUIUtils = {
create_folder: function CB_create_folder(aFolderName, aParentId, aIsRoot) {
// Left Pane Root Folder.
let folderId = bs.createFolder(aParentId,
queriesTitles[aFolderName],
queries[aFolderName].title,
bs.DEFAULT_INDEX);
// We should never backup this, since it changes between profiles.
as.setItemAnnotation(folderId, EXCLUDE_FROM_BACKUP_ANNO, 1,

View File

@ -62,6 +62,10 @@ var windowObserver = {
var query = leftPaneQueries[i];
is(PlacesUtils.bookmarks.getItemTitle(query.itemId),
query.correctTitle, "Title is correct for query " + query.name);
if ("concreteId" in query) {
is(PlacesUtils.bookmarks.getItemTitle(query.concreteId),
query.concreteTitle, "Concrete title is correct for query " + query.name);
}
}
// Close Library window.
@ -105,12 +109,28 @@ function test() {
var queryName = PlacesUtils.annotations
.getItemAnnotation(items[i],
ORGANIZER_QUERY_ANNO);
leftPaneQueries.push({ name: queryName,
itemId: itemId,
correctTitle: PlacesUtils.bookmarks
.getItemTitle(itemId) });
var query = { name: queryName,
itemId: itemId,
correctTitle: PlacesUtils.bookmarks.getItemTitle(itemId) }
switch (queryName) {
case "BookmarksToolbar":
query.concreteId = PlacesUtils.toolbarFolderId;
query.concreteTitle = PlacesUtils.bookmarks.getItemTitle(query.concreteId);
break;
case "BookmarksMenu":
query.concreteId = PlacesUtils.bookmarksMenuFolderId;
query.concreteTitle = PlacesUtils.bookmarks.getItemTitle(query.concreteId);
break;
case "UnfiledBookmarks":
query.concreteId = PlacesUtils.unfiledBookmarksFolderId;
query.concreteTitle = PlacesUtils.bookmarks.getItemTitle(query.concreteId);
break;
}
leftPaneQueries.push(query);
// Rename to a bad title.
PlacesUtils.bookmarks.setItemTitle(itemId, "badName");
PlacesUtils.bookmarks.setItemTitle(query.itemId, "badName");
if ("concreteId" in query)
PlacesUtils.bookmarks.setItemTitle(query.concreteId, "badName");
}
// Open Library, this will kick-off left pane code.

View File

@ -156,7 +156,11 @@
var text = treeView.getCellText(r, c);
switch (c.element.getAttribute("anonid")) {
case "title":
is(text, node.title, "Title is correct");
// The title can differ, we did not set any title so we would
// expect null, but in such a case the view will generate a title
// through PlacesUIUtils.getBestTitle.
if (node.title)
is(text, node.title, "Title is correct");
break;
case "url":
is(text, node.uri, "Uri is correct");

View File

@ -0,0 +1,224 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Places Unit Test code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Marco Bonardo <mak77@bonardo.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* Tests that we build a working leftpane in various corruption situations.
*/
// Used to store the original leftPaneFolderId getter.
let gLeftPaneFolderIdGetter;
let gAllBookmarksFolderIdGetter;
// Used to store the original left Pane status as a JSON string.
let gReferenceJSON;
let gLeftPaneFolderId;
// Third party annotated folder.
let gFolderId;
// Corruption cases.
let gTests = [
function test1() {
print("1. Do nothing, checks test calibration.");
},
function test2() {
print("2. Delete the left pane folder.");
PlacesUtils.bookmarks.removeItem(gLeftPaneFolderId);
},
function test3() {
print("3. Delete a child of the left pane folder.");
let id = PlacesUtils.bookmarks.getIdForItemAt(gLeftPaneFolderId, 0);
PlacesUtils.bookmarks.removeItem(id);
},
function test4() {
print("4. Delete AllBookmarks.");
PlacesUtils.bookmarks.removeItem(PlacesUIUtils.allBookmarksFolderId);
},
function test5() {
print("5. Create a duplicated left pane folder.");
let id = PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId,
"PlacesRoot",
PlacesUtils.bookmarks.DEFAULT_INDEX);
PlacesUtils.annotations.setItemAnnotation(id, ORGANIZER_FOLDER_ANNO,
"PlacesRoot", 0,
PlacesUtils.annotations.EXPIRE_NEVER);
},
function test6() {
print("6. Create a duplicated left pane query.");
let id = PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId,
"AllBookmarks",
PlacesUtils.bookmarks.DEFAULT_INDEX);
PlacesUtils.annotations.setItemAnnotation(id, ORGANIZER_QUERY_ANNO,
"AllBookmarks", 0,
PlacesUtils.annotations.EXPIRE_NEVER);
},
function test7() {
print("7. Remove the left pane folder annotation.");
PlacesUtils.annotations.removeItemAnnotation(gLeftPaneFolderId,
ORGANIZER_FOLDER_ANNO);
},
function test8() {
print("8. Remove a left pane query annotation.");
PlacesUtils.annotations.removeItemAnnotation(PlacesUIUtils.allBookmarksFolderId,
ORGANIZER_QUERY_ANNO);
},
function test9() {
print("9. Remove a child of AllBookmarks.");
let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUIUtils.allBookmarksFolderId, 0);
PlacesUtils.bookmarks.removeItem(id);
},
];
function run_test() {
// We want empty roots.
remove_all_bookmarks();
// Import PlacesUIUtils.
let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
getService(Ci.mozIJSSubScriptLoader);
scriptLoader.loadSubScript("chrome://browser/content/places/utils.js", this);
do_check_true(!!PlacesUIUtils);
// Check getters.
gLeftPaneFolderIdGetter = PlacesUIUtils.__lookupGetter__("leftPaneFolderId");
do_check_eq(typeof(gLeftPaneFolderIdGetter), "function");
gAllBookmarksFolderIdGetter = PlacesUIUtils.__lookupGetter__("allBookmarksFolderId");
do_check_eq(typeof(gAllBookmarksFolderIdGetter), "function");
// Add a third party bogus annotated item. Should not be removed.
gFolderId = PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId,
"test",
PlacesUtils.bookmarks.DEFAULT_INDEX);
PlacesUtils.annotations.setItemAnnotation(gFolderId, ORGANIZER_QUERY_ANNO,
"test", 0,
PlacesUtils.annotations.EXPIRE_NEVER);
// Create the left pane, and store its current status, it will be used
// as reference value.
gLeftPaneFolderId = PlacesUIUtils.leftPaneFolderId;
gReferenceJSON = folderToJSON(gLeftPaneFolderId);
// Kick-off tests.
do_test_pending();
do_timeout(0, "run_next_test();");
}
function run_next_test() {
if (gTests.length) {
// Create corruption.
let test = gTests.shift();
test();
// Regenerate getters.
PlacesUIUtils.__defineGetter__("leftPaneFolderId", gLeftPaneFolderIdGetter);
gLeftPaneFolderId = PlacesUIUtils.leftPaneFolderId;
PlacesUIUtils.__defineGetter__("allBookmarksFolderId", gAllBookmarksFolderIdGetter);
// Check the new left pane folder.
let leftPaneJSON = folderToJSON(gLeftPaneFolderId);
do_check_true(compareJSON(gReferenceJSON, leftPaneJSON));
do_check_eq(PlacesUtils.bookmarks.getItemTitle(gFolderId), "test");
// Go to next test.
do_timeout(0, "run_next_test();");
}
else {
// All tests finished.
remove_all_bookmarks();
do_test_finished();
}
}
/**
* Convert a folder item id to a JSON representation of it and its contents.
*/
function folderToJSON(aItemId) {
let query = PlacesUtils.history.getNewQuery();
query.setFolders([aItemId], 1);
let options = PlacesUtils.history.getNewQueryOptions();
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS;
let root = PlacesUtils.history.executeQuery(query, options).root;
let writer = {
value: "",
write: function PU_wrapNode__write(aStr, aLen) {
this.value += aStr;
}
};
PlacesUtils.serializeNodeAsJSONToOutputStream(root, writer, false, false);
do_check_true(writer.value.length > 0);
return writer.value;
}
/**
* Compare the JSON representation of 2 nodes, skipping everchanging properties
* like dates.
*/
function compareJSON(aNodeJSON_1, aNodeJSON_2) {
let JSON = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);
node1 = JSON.decode(aNodeJSON_1);
node2 = JSON.decode(aNodeJSON_2);
// List of properties we should not compare (expected to be different).
const SKIP_PROPS = ["dateAdded", "lastModified", "id"];
function compareObjects(obj1, obj2) {
do_check_eq(obj1.__count__, obj2.__count__);
for (let prop in obj1) {
// Skip everchanging values.
if (SKIP_PROPS.indexOf(prop) != -1)
continue;
// Skip undefined objects, otherwise we hang on them.
if (!obj1[prop])
continue;
if (typeof(obj1[prop]) == "object")
return compareObjects(obj1[prop], obj2[prop]);
if (obj1[prop] !== obj2[prop]) {
print(prop + ": " + obj1[prop] + "!=" + obj2[prop]);
return false;
}
}
return true;
}
return compareObjects(node1, node2);
}

View File

@ -661,7 +661,7 @@ FeedHandlerInfo.prototype = {
}
// Add the registered web handlers. There can be any number of these.
var webHandlers = this._converterSvc.getContentHandlers(this.type, {});
var webHandlers = this._converterSvc.getContentHandlers(this.type);
for each (let webHandler in webHandlers)
this._possibleApplicationHandlers.appendElement(webHandler, false);

View File

@ -365,6 +365,10 @@ PrivateBrowsingService.prototype = {
getService(Ci.nsIHttpAuthManager);
authMgr.clearAll();
try {
this._prefs.deleteBranch("geo.wifi.access_token.");
} catch (ex) {}
if (!this._inPrivateBrowsing) {
// Clear the error console
let consoleService = Cc["@mozilla.org/consoleservice;1"].
@ -557,7 +561,7 @@ PrivateBrowsingService.prototype = {
getService(Ci.nsILoginManager)) {
// Clear all passwords for domain
try {
let logins = lm.getAllLogins({});
let logins = lm.getAllLogins();
for (let i = 0; i < logins.length; i++)
if (logins[i].hostname.hasRootDomain(aDomain))
lm.removeLogin(logins[i]);
@ -567,7 +571,7 @@ PrivateBrowsingService.prototype = {
catch (ex if ex.message.indexOf("User canceled Master Password entry") != -1) { }
// Clear any "do not save for this site" for this domain
let disabledHosts = lm.getAllDisabledHosts({});
let disabledHosts = lm.getAllDisabledHosts();
for (let i = 0; i < disabledHosts.length; i++)
if (disabledHosts[i].hasRootDomain(aDomain))
lm.setLoginSavingEnabled(disabledHosts, true);

View File

@ -37,19 +37,23 @@
// This provides the tests with a download URL which never finishes.
var timer;
function handleRequest(request, response) {
response.setStatusLine(request.httpVersion, 200, "OK");
response.processAsync();
const nsITimer = Components.interfaces.nsITimer;
function stall() {
timer = null;
// This write will throw if the connection has been closed by the browser.
response.write("stalling...\n");
timer = Components.classes["@mozilla.org/timer;1"]
.createInstance(nsITimer);
timer.initWithCallback(stall, 500, nsITimer.TYPE_ONE_SHOT);
}
response.setHeader("Content-Type", "text/plain", false);
stall();
const nsITimer = Components.interfaces.nsITimer;
var timer = Components.classes["@mozilla.org/timer;1"]
.createInstance(nsITimer);
timer.initWithCallback(stall, 500, nsITimer.TYPE_REPEATING_SLACK);
}

View File

@ -0,0 +1,74 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Private Browsing Tests.
*
* The Initial Developer of the Original Code is
* Nochum Sossonko.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Nochum Sossonko <nsossonko@hotmail.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
// Test to ensure the geolocation token is cleared when changing the private
// browsing mode
const accessToken = '{"location":{"latitude":51.5090332,"longitude":-0.1212726,"accuracy":150.0},"access_token":"2:jVhRZJ-j6PiRchH_:RGMrR0W1BiwdZs12"}'
function run_test_on_service() {
var prefBranch = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch2);
var pb = Cc[PRIVATEBROWSING_CONTRACT_ID].
getService(Ci.nsIPrivateBrowsingService);
prefBranch.setCharPref("geo.wifi.access_token.test", accessToken);
var token = prefBranch.getCharPref("geo.wifi.access_token.test");
do_check_eq(token, accessToken);
pb.privateBrowsingEnabled = true;
token = "";
try {
token = prefBranch.getCharPref("geo.wifi.access_token.test");
}
catch(e){}
finally {
do_check_eq(token, "");
}
token = "";
prefBranch.setCharPref("geo.wifi.access_token.test", accessToken);
pb.privateBrowsingEnabled = false;
try {
token = prefBranch.getCharPref("geo.wifi.access_token.test");
}
catch(e){}
finally {
do_check_eq(token, "");
}
}
// Support running tests on both the service itself and its wrapper
function run_test() {
run_test_on_all_services();
}

View File

@ -41,7 +41,7 @@ function run_test_on_service()
let Cc = Components.classes;
let Ci = Components.interfaces;
let Cu = Components.utils;
Cu.import("resource://gre/modules/openLocationLastURL.jsm");
Cu.import("resource:///modules/openLocationLastURL.jsm");
let pb = Cc[PRIVATEBROWSING_CONTRACT_ID].
getService(Ci.nsIPrivateBrowsingService);

View File

@ -300,13 +300,13 @@ EngineChangeOp.prototype = {
function EngineStore() {
var searchService = Cc["@mozilla.org/browser/search-service;1"].
getService(Ci.nsIBrowserSearchService);
this._engines = searchService.getVisibleEngines({}).map(this._cloneEngine);
this._defaultEngines = searchService.getDefaultEngines({}).map(this._cloneEngine);
this._engines = searchService.getVisibleEngines().map(this._cloneEngine);
this._defaultEngines = searchService.getDefaultEngines().map(this._cloneEngine);
this._ops = [];
// check if we need to disable the restore defaults button
var someHidden = this._defaultEngines.some(function (e) {return e.hidden;});
var someHidden = this._defaultEngines.some(function (e) e.hidden);
gEngineManagerDialog.showRestoreDefaults(someHidden);
}
EngineStore.prototype = {

View File

@ -149,7 +149,7 @@
<property name="engines" readonly="true">
<getter><![CDATA[
if (!this._engines)
this._engines = this.searchService.getVisibleEngines({ });
this._engines = this.searchService.getVisibleEngines();
return this._engines;
]]></getter>
</property>

View File

@ -69,6 +69,8 @@ components/aboutRights.js
components/aboutRobots.js
components/aboutSessionRestore.js
components/compreg.dat
components/@DLL_PREFIX@browserdirprovider@DLL_SUFFIX@
components/@DLL_PREFIX@brwsrdir@DLL_SUFFIX@
components/@DLL_PREFIX@myspell@DLL_SUFFIX@
components/@DLL_PREFIX@spellchecker@DLL_SUFFIX@
components/@DLL_PREFIX@spellchk@DLL_SUFFIX@

View File

@ -6,8 +6,6 @@ deleteDomainNoSelection=Delete domain
load-js-data-url-error=For security reasons, javascript or data urls cannot be loaded from the history window or sidebar.
noTitle=(no title)
bookmarksMenuName=Bookmarks Menu
bookmarksToolbarName=Bookmarks Toolbar
bookmarksMenuEmptyFolder=(Empty)
# LOCALIZATION NOTE (bookmarksBackupFilename) :
@ -94,6 +92,7 @@ recentTagsTitle=Recent Tags
OrganizerQueryHistory=History
OrganizerQueryDownloads=Downloads
OrganizerQueryAllBookmarks=All Bookmarks
OrganizerQueryTags=Tags
# LOCALIZATION NOTE (tagResultLabel) :
# This is what we use to form the label (for screen readers)

View File

@ -103,7 +103,7 @@ toolbarbutton.bookmark-item-microsummarized {
max-width: 20em;
}
toolbarbutton.bookmark-item:hover:active,
toolbarbutton.bookmark-item:hover:active:not([disabled="true"]),
toolbarbutton.bookmark-item[open="true"] {
padding-top: 3px;
padding-bottom: 1px;

View File

@ -150,15 +150,18 @@ shellMkdir (wchar_t **pArgv)
/* check if directory already exists */
_wgetcwd ( path, _MAX_PATH );
if ( _wchdir ( tmpPath ) != -1 ) {
_wchdir ( path );
if ( _wchdir ( tmpPath ) == -1 &&
_wmkdir ( tmpPath ) == -1 && // might have hit EEXIST
_wchdir ( tmpPath ) == -1) { // so try again
char buf[2048];
_snprintf(buf, 2048, "Could not create the directory: %S",
tmpPath);
perror ( buf );
retVal = 3;
break;
} else {
if ( _wmkdir ( tmpPath ) == -1 ) {
printf ( "%ls: ", tmpPath );
perror ( "Could not create the directory" );
retVal = 3;
break;
}
// get back to the cwd
_wchdir ( path );
}
if ( *pArg == '\0' ) /* complete path? */
break;

View File

@ -7762,14 +7762,10 @@ dnl
dnl Build jsctypes on the platforms we can.
dnl
AC_SUBST(BUILD_CTYPES)
case "$OS_TEST" in
arm*)
;;
*)
if test "$OS_TARGET" != "WINCE" -o `echo $OS_TEST | grep -ic arm` != 1; then
BUILD_CTYPES=1
AC_DEFINE(BUILD_CTYPES)
;;
esac
fi
dnl NECKO_ configuration options are not global
_NON_GLOBAL_ACDEFINES="$_NON_GLOBAL_ACDEFINES NECKO_"

View File

@ -93,7 +93,7 @@ XPIDLSRCS = \
nsIContentPolicy.idl \
nsIDocumentEncoder.idl \
nsIDOMFile.idl \
nsIDOMFileRequest.idl \
nsIDOMFileReader.idl \
nsIDOMFileInternal.idl \
nsIDOMFileList.idl \
nsIDOMFileException.idl \

View File

@ -41,8 +41,8 @@ interface nsIDOMEventListener;
interface nsIDOMFile;
interface nsIDOMFileError;
[scriptable, uuid(074FEC26-7FAB-4E05-9E60-EC49E148F5EF)]
interface nsIDOMFileRequest : nsISupports
[scriptable, uuid(5db0ce80-de44-40c0-a346-e28aac4aa978)]
interface nsIDOMFileReader : nsISupports
{
void readAsBinaryString(in nsIDOMFile filedata);
void readAsText(in nsIDOMFile filedata, [optional] in DOMString encoding);
@ -55,7 +55,7 @@ interface nsIDOMFileRequest : nsISupports
const unsigned short DONE = 2;
readonly attribute unsigned short readyState;
readonly attribute DOMString response;
readonly attribute DOMString result;
readonly attribute nsIDOMFileError error;
// event handler attributes
@ -63,9 +63,9 @@ interface nsIDOMFileRequest : nsISupports
};
%{ C++
#define NS_FILEREQUEST_CID \
#define NS_FILEREADER_CID \
{0x06aa7c21, 0xfe05, 0x4cf2, \
{0xb1, 0xc4, 0x0c, 0x71, 0x26, 0xa4, 0xf7, 0x13}}
#define NS_FILEREQUEST_CONTRACTID \
"@mozilla.org/files/filerequest;1"
#define NS_FILEREADER_CONTRACTID \
"@mozilla.org/files/filereader;1"
%}

View File

@ -44,9 +44,10 @@
#include "nsCOMPtr.h"
#include "nsIScriptLoaderObserver.h"
// e68ddc48-4055-4ba9-978d-c49d9cf3189a
#define NS_ISCRIPTELEMENT_IID \
{ 0x4b916da5, 0x82c4, 0x45ab, \
{ 0x99, 0x15, 0xcc, 0xcd, 0x9e, 0x2c, 0xb1, 0xe6 } }
{ 0xe68ddc48, 0x4055, 0x4ba9, \
{ 0x97, 0x8d, 0xc4, 0x9d, 0x9c, 0xf3, 0x18, 0x9a } }
/**
* Internal interface implemented by script elements
@ -87,6 +88,11 @@ public:
*/
virtual PRBool GetScriptDeferred() = 0;
/**
* Is the script async. Currently only supported by HTML scripts.
*/
virtual PRBool GetScriptAsync() = 0;
void SetScriptLineNumber(PRUint32 aLineNumber)
{
mLineNumber = aLineNumber;

View File

@ -84,7 +84,7 @@ CPPSRCS = \
nsDOMAttributeMap.cpp \
nsDOMDocumentType.cpp \
nsDOMFile.cpp \
nsDOMFileRequest.cpp \
nsDOMFileReader.cpp \
nsDOMLists.cpp \
nsDOMParser.cpp \
nsDOMSerializer.cpp \

View File

@ -115,8 +115,18 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE);
// We always require a plaintext version
// note that we assign text/unicode as mime type, but in fact nsHTMLCopyEncoder
// ignore it and use text/html or text/plain depending where the selection
// is. if it is a selection into input/textarea element or in a html content
// with pre-wrap style : text/plain. Otherwise text/html.
// see nsHTMLCopyEncoder::SetSelection
mimeType.AssignLiteral(kUnicodeMime);
PRUint32 flags = nsIDocumentEncoder::OutputPreformatted;
// we want preformatted for the case where the selection is inside input/textarea
// and we don't want pretty printing for others cases, to not have additionnal
// line breaks which are then converted into spaces by the htmlConverter (see bug #524975)
PRUint32 flags = nsIDocumentEncoder::OutputPreformatted | nsIDocumentEncoder::OutputRaw;
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc);
NS_ASSERTION(domDoc, "Need a document");

View File

@ -35,7 +35,7 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsDOMFileRequest.h"
#include "nsDOMFileReader.h"
#include "nsContentCID.h"
#include "nsContentUtils.h"
@ -89,9 +89,9 @@
#define NS_PROGRESS_EVENT_INTERVAL 50
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMFileRequest)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMFileReader)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMFileRequest,
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMFileReader,
nsXHREventTarget)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnLoadEndListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFile)
@ -100,7 +100,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMFileRequest,
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannel)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMFileRequest,
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMFileReader,
nsXHREventTarget)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnLoadEndListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFile)
@ -109,32 +109,32 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMFileRequest,
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannel)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMFileRequest)
NS_INTERFACE_MAP_ENTRY(nsIDOMFileRequest)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMFileReader)
NS_INTERFACE_MAP_ENTRY(nsIDOMFileReader)
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
NS_INTERFACE_MAP_ENTRY(nsICharsetDetectionObserver)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(FileRequest)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(FileReader)
NS_INTERFACE_MAP_END_INHERITING(nsXHREventTarget)
NS_IMPL_ADDREF_INHERITED(nsDOMFileRequest, nsXHREventTarget)
NS_IMPL_RELEASE_INHERITED(nsDOMFileRequest, nsXHREventTarget)
NS_IMPL_ADDREF_INHERITED(nsDOMFileReader, nsXHREventTarget)
NS_IMPL_RELEASE_INHERITED(nsDOMFileReader, nsXHREventTarget)
static const PRUint32 FILE_AS_BINARY = 1;
static const PRUint32 FILE_AS_TEXT = 2;
static const PRUint32 FILE_AS_DATAURL = 3;
NS_IMETHODIMP
nsDOMFileRequest::GetOnloadend(nsIDOMEventListener** aOnloadend)
nsDOMFileReader::GetOnloadend(nsIDOMEventListener** aOnloadend)
{
return GetInnerEventListener(mOnLoadEndListener, aOnloadend);
}
NS_IMETHODIMP
nsDOMFileRequest::SetOnloadend(nsIDOMEventListener* aOnloadend)
nsDOMFileReader::SetOnloadend(nsIDOMEventListener* aOnloadend)
{
return RemoveAddEventListener(NS_LITERAL_STRING(LOADEND_STR),
mOnLoadEndListener, aOnloadend);
@ -143,18 +143,18 @@ nsDOMFileRequest::SetOnloadend(nsIDOMEventListener* aOnloadend)
//nsICharsetDetectionObserver
NS_IMETHODIMP
nsDOMFileRequest::Notify(const char *aCharset, nsDetectionConfident aConf)
nsDOMFileReader::Notify(const char *aCharset, nsDetectionConfident aConf)
{
CopyASCIItoUTF16(aCharset, mCharset);
return NS_OK;
}
//nsDOMFileRequest constructors/initializers
//nsDOMFileReader constructors/initializers
nsDOMFileRequest::nsDOMFileRequest()
nsDOMFileReader::nsDOMFileReader()
: mFileData(nsnull), mReadCount(0),
mDataLen(0), mDataFormat(0),
mReadyState(nsIDOMFileRequest::INITIAL),
mReadyState(nsIDOMFileReader::INITIAL),
mProgressEventWasDelayed(PR_FALSE),
mTimerIsActive(PR_FALSE),
mReadTotal(0), mReadTransferred(0),
@ -163,7 +163,7 @@ nsDOMFileRequest::nsDOMFileRequest()
nsLayoutStatics::AddRef();
}
nsDOMFileRequest::~nsDOMFileRequest()
nsDOMFileReader::~nsDOMFileReader()
{
if (mListenerManager)
mListenerManager->Disconnect();
@ -172,7 +172,7 @@ nsDOMFileRequest::~nsDOMFileRequest()
}
nsresult
nsDOMFileRequest::Init()
nsDOMFileReader::Init()
{
// Set the original mScriptContext and mPrincipal, if available.
// Get JSContext from stack.
@ -211,8 +211,8 @@ nsDOMFileRequest::Init()
}
NS_IMETHODIMP
nsDOMFileRequest::Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
PRUint32 argc, jsval *argv)
nsDOMFileReader::Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
PRUint32 argc, jsval *argv)
{
mOwner = do_QueryInterface(aOwner);
if (!mOwner) {
@ -236,57 +236,57 @@ nsDOMFileRequest::Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
// nsIInterfaceRequestor
NS_IMETHODIMP
nsDOMFileRequest::GetInterface(const nsIID & aIID, void **aResult)
nsDOMFileReader::GetInterface(const nsIID & aIID, void **aResult)
{
return QueryInterface(aIID, aResult);
}
// nsIDOMFileRequest
// nsIDOMFileReader
NS_IMETHODIMP
nsDOMFileRequest::GetReadyState(PRUint16 *aReadyState)
nsDOMFileReader::GetReadyState(PRUint16 *aReadyState)
{
*aReadyState = mReadyState;
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileRequest::GetResponse(nsAString& aResponse)
nsDOMFileReader::GetResult(nsAString& aResult)
{
aResponse = mResponse;
aResult = mResult;
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileRequest::GetError(nsIDOMFileError** aError)
nsDOMFileReader::GetError(nsIDOMFileError** aError)
{
NS_IF_ADDREF(*aError = mError);
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileRequest::ReadAsBinaryString(nsIDOMFile* aFile)
nsDOMFileReader::ReadAsBinaryString(nsIDOMFile* aFile)
{
return ReadFileContent(aFile, EmptyString(), FILE_AS_BINARY);
}
NS_IMETHODIMP
nsDOMFileRequest::ReadAsText(nsIDOMFile* aFile,
const nsAString &aCharset)
nsDOMFileReader::ReadAsText(nsIDOMFile* aFile,
const nsAString &aCharset)
{
return ReadFileContent(aFile, aCharset, FILE_AS_TEXT);
}
NS_IMETHODIMP
nsDOMFileRequest::ReadAsDataURL(nsIDOMFile* aFile)
nsDOMFileReader::ReadAsDataURL(nsIDOMFile* aFile)
{
return ReadFileContent(aFile, EmptyString(), FILE_AS_DATAURL);
}
NS_IMETHODIMP
nsDOMFileRequest::Abort()
nsDOMFileReader::Abort()
{
if (mReadyState != nsIDOMFileRequest::LOADING)
if (mReadyState != nsIDOMFileReader::LOADING)
return NS_OK;
//Clear progress and file data
@ -298,9 +298,9 @@ nsDOMFileRequest::Abort()
mReadCount = 0;
mDataLen = 0;
//Revert status, response and readystate attributes
SetDOMStringToNull(mResponse);
mReadyState = nsIDOMFileRequest::DONE;
//Revert status, result and readystate attributes
SetDOMStringToNull(mResult);
mReadyState = nsIDOMFileReader::DONE;
mError = new nsDOMFileError(nsIDOMFileError::ABORT_ERR);
//Non-null channel indicates a read is currently active
@ -319,14 +319,14 @@ nsDOMFileRequest::Abort()
DispatchProgressEvent(NS_LITERAL_STRING(ABORT_STR));
DispatchProgressEvent(NS_LITERAL_STRING(LOADEND_STR));
mReadyState = nsIDOMFileRequest::INITIAL;
mReadyState = nsIDOMFileReader::INITIAL;
return NS_OK;
}
// nsITimerCallback
NS_IMETHODIMP
nsDOMFileRequest::Notify(nsITimer* aTimer)
nsDOMFileReader::Notify(nsITimer* aTimer)
{
mTimerIsActive = PR_FALSE;
if (mProgressEventWasDelayed) {
@ -338,7 +338,7 @@ nsDOMFileRequest::Notify(nsITimer* aTimer)
}
void
nsDOMFileRequest::StartProgressEventTimer()
nsDOMFileReader::StartProgressEventTimer()
{
if (!mProgressNotifier) {
mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID);
@ -355,17 +355,17 @@ nsDOMFileRequest::StartProgressEventTimer()
// nsIStreamListener
NS_IMETHODIMP
nsDOMFileRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
nsDOMFileReader::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
{
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileRequest::OnDataAvailable(nsIRequest *aRequest,
nsISupports *aContext,
nsIInputStream *aInputStream,
PRUint32 aOffset,
PRUint32 aCount)
nsDOMFileReader::OnDataAvailable(nsIRequest *aRequest,
nsISupports *aContext,
nsIInputStream *aInputStream,
PRUint32 aOffset,
PRUint32 aCount)
{
//Update memory buffer to reflect the contents of the file
mFileData = (char *)PR_Realloc(mFileData, aOffset + aCount);
@ -377,11 +377,11 @@ nsDOMFileRequest::OnDataAvailable(nsIRequest *aRequest,
//Continuously update our binary string as data comes in
if (mDataFormat == FILE_AS_BINARY) {
PRUint32 oldLen = mResponse.Length();
PRUint32 oldLen = mResult.Length();
PRUint32 newLen = oldLen + aCount;
PRUnichar *buf;
if (mResponse.GetMutableData(&buf, newLen) != newLen) {
if (mResult.GetMutableData(&buf, newLen) != newLen) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -409,9 +409,9 @@ nsDOMFileRequest::OnDataAvailable(nsIRequest *aRequest,
}
NS_IMETHODIMP
nsDOMFileRequest::OnStopRequest(nsIRequest *aRequest,
nsISupports *aContext,
nsresult aStatus)
nsDOMFileReader::OnStopRequest(nsIRequest *aRequest,
nsISupports *aContext,
nsresult aStatus)
{
//If we're here as a result of a call from Abort(),
//simply ignore the request.
@ -425,8 +425,8 @@ nsDOMFileRequest::OnStopRequest(nsIRequest *aRequest,
mProgressNotifier->Cancel();
}
//FileRequest must be in DONE stage after a load
mReadyState = nsIDOMFileRequest::DONE;
//FileReader must be in DONE stage after a load
mReadyState = nsIDOMFileReader::DONE;
//Set the status field as appropriate
if (NS_FAILED(aStatus)) {
@ -437,12 +437,12 @@ nsDOMFileRequest::OnStopRequest(nsIRequest *aRequest,
nsresult rv;
switch (mDataFormat) {
case FILE_AS_BINARY:
break; //Already accumulated mResponse
break; //Already accumulated mResult
case FILE_AS_TEXT:
rv = GetAsText(mCharset, mFileData, mDataLen, mResponse);
rv = GetAsText(mCharset, mFileData, mDataLen, mResult);
break;
case FILE_AS_DATAURL:
rv = GetAsDataURL(mFile, mFileData, mDataLen, mResponse);
rv = GetAsDataURL(mFile, mFileData, mDataLen, mResult);
break;
default:
return NS_ERROR_FAILURE;
@ -458,9 +458,9 @@ nsDOMFileRequest::OnStopRequest(nsIRequest *aRequest,
// Helper methods
nsresult
nsDOMFileRequest::ReadFileContent(nsIDOMFile* aFile,
const nsAString &aCharset,
PRUint32 aDataFormat)
nsDOMFileReader::ReadFileContent(nsIDOMFile* aFile,
const nsAString &aCharset,
PRUint32 aDataFormat)
{
NS_ENSURE_TRUE(aFile, NS_ERROR_NULL_POINTER);
@ -490,15 +490,15 @@ nsDOMFileRequest::ReadFileContent(nsIDOMFile* aFile,
rv = mChannel->AsyncOpen(this, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
//FileRequest should be in loading state here
mReadyState = nsIDOMFileRequest::LOADING;
//FileReader should be in loading state here
mReadyState = nsIDOMFileReader::LOADING;
DispatchProgressEvent(NS_LITERAL_STRING(LOADSTART_STR));
return NS_OK;
}
void
nsDOMFileRequest::DispatchError(nsresult rv)
nsDOMFileReader::DispatchError(nsresult rv)
{
//Set the status attribute, and dispatch the error event
switch (rv) {
@ -519,7 +519,7 @@ nsDOMFileRequest::DispatchError(nsresult rv)
}
void
nsDOMFileRequest::DispatchProgressEvent(const nsAString& aType)
nsDOMFileReader::DispatchProgressEvent(const nsAString& aType)
{
nsCOMPtr<nsIDOMEvent> event;
nsresult rv = nsEventDispatcher::CreateEvent(nsnull, nsnull,
@ -547,10 +547,10 @@ nsDOMFileRequest::DispatchProgressEvent(const nsAString& aType)
}
nsresult
nsDOMFileRequest::GetAsText(const nsAString &aCharset,
const char *aFileData,
PRUint32 aDataLen,
nsAString& aResult)
nsDOMFileReader::GetAsText(const nsAString &aCharset,
const char *aFileData,
PRUint32 aDataLen,
nsAString& aResult)
{
nsresult rv;
nsCAutoString charsetGuess;
@ -574,10 +574,10 @@ nsDOMFileRequest::GetAsText(const nsAString &aCharset,
}
nsresult
nsDOMFileRequest::GetAsDataURL(nsIFile *aFile,
const char *aFileData,
PRUint32 aDataLen,
nsAString& aResult)
nsDOMFileReader::GetAsDataURL(nsIFile *aFile,
const char *aFileData,
PRUint32 aDataLen,
nsAString& aResult)
{
aResult.AssignLiteral("data:");
@ -621,10 +621,10 @@ nsDOMFileRequest::GetAsDataURL(nsIFile *aFile,
}
nsresult
nsDOMFileRequest::ConvertStream(const char *aFileData,
PRUint32 aDataLen,
const char *aCharset,
nsAString &aResult)
nsDOMFileReader::ConvertStream(const char *aFileData,
PRUint32 aDataLen,
const char *aCharset,
nsAString &aResult)
{
nsresult rv;
nsCOMPtr<nsICharsetConverterManager> charsetConverter =
@ -650,9 +650,9 @@ nsDOMFileRequest::ConvertStream(const char *aFileData,
}
nsresult
nsDOMFileRequest::GuessCharset(const char *aFileData,
PRUint32 aDataLen,
nsACString &aCharset)
nsDOMFileReader::GuessCharset(const char *aFileData,
PRUint32 aDataLen,
nsACString &aCharset)
{
// First try the universal charset detector
nsCOMPtr<nsICharsetDetector> detector

View File

@ -35,8 +35,8 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsDOMFileRequest_h__
#define nsDOMFileRequest_h__
#ifndef nsDOMFileReader_h__
#define nsDOMFileReader_h__
#include "nsISupportsUtils.h"
#include "nsString.h"
@ -53,7 +53,7 @@
#include "nsICharsetDetectionObserver.h"
#include "nsIDOMFile.h"
#include "nsIDOMFileRequest.h"
#include "nsIDOMFileReader.h"
#include "nsIDOMFileList.h"
#include "nsIDOMFileError.h"
#include "nsIInputStream.h"
@ -63,23 +63,23 @@
#include "nsXMLHttpRequest.h"
class nsDOMFileRequest : public nsXHREventTarget,
public nsIDOMFileRequest,
public nsIStreamListener,
public nsIInterfaceRequestor,
public nsSupportsWeakReference,
public nsIJSNativeInitializer,
public nsITimerCallback,
public nsICharsetDetectionObserver
class nsDOMFileReader : public nsXHREventTarget,
public nsIDOMFileReader,
public nsIStreamListener,
public nsIInterfaceRequestor,
public nsSupportsWeakReference,
public nsIJSNativeInitializer,
public nsITimerCallback,
public nsICharsetDetectionObserver
{
public:
nsDOMFileRequest();
virtual ~nsDOMFileRequest();
nsDOMFileReader();
virtual ~nsDOMFileReader();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMFILEREQUEST
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMFileRequest, nsXHREventTarget)
NS_DECL_NSIDOMFILEREADER
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMFileReader, nsXHREventTarget)
NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXHREventTarget::);
@ -126,7 +126,7 @@ protected:
PRUint32 mDataLen;
PRUint32 mDataFormat;
nsString mResponse;
nsString mResult;
PRUint16 mReadyState;
PRBool mProgressEventWasDelayed;

View File

@ -111,6 +111,7 @@ GK_ATOM(area, "area")
GK_ATOM(ascending, "ascending")
GK_ATOM(aspectRatio, "aspect-ratio")
GK_ATOM(assign, "assign")
GK_ATOM(async, "async")
GK_ATOM(attribute, "attribute")
GK_ATOM(attributeSet, "attribute-set")
GK_ATOM(aural, "aural")

View File

@ -139,6 +139,10 @@ nsScriptLoader::~nsScriptLoader()
mRequests[i]->FireScriptAvailable(NS_ERROR_ABORT);
}
for (PRInt32 i = 0; i < mAsyncRequests.Count(); i++) {
mAsyncRequests[i]->FireScriptAvailable(NS_ERROR_ABORT);
}
// Unblock the kids, in case any of them moved to a different document
// subtree in the meantime and therefore aren't actually going away.
for (PRUint32 j = 0; j < mPendingChildLoaders.Length(); ++j) {
@ -501,7 +505,8 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
request = mPreloads[i].mRequest;
request->mElement = aElement;
request->mJSVersion = version;
request->mDefer = mDeferEnabled && aElement->GetScriptDeferred();
request->mDefer = mDeferEnabled && aElement->GetScriptDeferred() &&
!aElement->GetScriptAsync();
mPreloads.RemoveElementAt(i);
rv = CheckContentPolicy(mDocument, aElement, request->mURI, type);
@ -510,21 +515,34 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
return rv;
}
if (!request->mLoading && !request->mDefer && !hadPendingRequests &&
ReadyToExecuteScripts() && nsContentUtils::IsSafeToRunScript()) {
// Can we run the script now?
// This is true if we're done loading, the script isn't deferred and
// there are either no scripts or stylesheets to wait for, or the
// script is async
PRBool readyToRun =
!request->mLoading && !request->mDefer &&
((!hadPendingRequests && ReadyToExecuteScripts()) ||
aElement->GetScriptAsync());
if (readyToRun && nsContentUtils::IsSafeToRunScript()) {
return ProcessRequest(request);
}
// Not done loading yet. Move into the real requests queue and wait.
mRequests.AppendObject(request);
if (aElement->GetScriptAsync()) {
mAsyncRequests.AppendObject(request);
}
else {
mRequests.AppendObject(request);
}
if (!request->mLoading && !hadPendingRequests && ReadyToExecuteScripts() &&
!request->mDefer) {
if (readyToRun) {
nsContentUtils::AddScriptRunner(new nsRunnableMethod<nsScriptLoader>(this,
&nsScriptLoader::ProcessPendingRequests));
}
return request->mDefer ? NS_OK : NS_ERROR_HTMLPARSER_BLOCK;
return request->mDefer || aElement->GetScriptAsync() ?
NS_OK : NS_ERROR_HTMLPARSER_BLOCK;
}
}
@ -532,10 +550,10 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
request = new nsScriptLoadRequest(aElement, version);
NS_ENSURE_TRUE(request, NS_ERROR_OUT_OF_MEMORY);
request->mDefer = mDeferEnabled && aElement->GetScriptDeferred();
// First check to see if this is an external script
if (scriptURI) {
request->mDefer = mDeferEnabled && aElement->GetScriptDeferred() &&
!aElement->GetScriptAsync();
request->mURI = scriptURI;
request->mIsInline = PR_FALSE;
request->mLoading = PR_TRUE;
@ -545,6 +563,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
return rv;
}
} else {
request->mDefer = PR_FALSE;
request->mLoading = PR_FALSE;
request->mIsInline = PR_TRUE;
request->mURI = mDocument->GetDocumentURI();
@ -553,17 +572,19 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// If we've got existing pending requests, add ourselves
// to this list.
if (!request->mDefer && !hadPendingRequests &&
ReadyToExecuteScripts() && nsContentUtils::IsSafeToRunScript()) {
if (!hadPendingRequests && ReadyToExecuteScripts() &&
nsContentUtils::IsSafeToRunScript()) {
return ProcessRequest(request);
}
}
// Add the request to our requests list
NS_ENSURE_TRUE(mRequests.AppendObject(request),
NS_ENSURE_TRUE(aElement->GetScriptAsync() ?
mAsyncRequests.AppendObject(request) :
mRequests.AppendObject(request),
NS_ERROR_OUT_OF_MEMORY);
if (request->mDefer) {
if (request->mDefer || aElement->GetScriptAsync()) {
return NS_OK;
}
@ -736,11 +757,30 @@ nsScriptLoader::ProcessPendingRequestsAsync()
void
nsScriptLoader::ProcessPendingRequests()
{
nsRefPtr<nsScriptLoadRequest> request;
while (ReadyToExecuteScripts() &&
(request = GetFirstPendingRequest()) &&
!request->mLoading) {
mRequests.RemoveObject(request);
while (1) {
nsRefPtr<nsScriptLoadRequest> request;
if (ReadyToExecuteScripts()) {
request = GetFirstPendingRequest();
if (request && !request->mLoading) {
mRequests.RemoveObject(request);
}
else {
request = nsnull;
}
}
for (PRInt32 i = 0;
!request && mEnabled && i < mAsyncRequests.Count();
++i) {
if (!mAsyncRequests[i]->mLoading) {
request = mAsyncRequests[i];
mAsyncRequests.RemoveObjectAt(i);
}
}
if (!request)
break;
ProcessRequest(request);
}
@ -751,7 +791,7 @@ nsScriptLoader::ProcessPendingRequests()
}
if (mUnblockOnloadWhenDoneProcessing && mDocument &&
!GetFirstPendingRequest()) {
!GetFirstPendingRequest() && !mAsyncRequests.Count()) {
// No more pending scripts; time to unblock onload.
// OK to unblock onload synchronously here, since callers must be
// prepared for the world changing anyway.
@ -920,10 +960,11 @@ nsScriptLoader::OnStreamComplete(nsIStreamLoader* aLoader,
nsresult rv = PrepareLoadedRequest(request, aLoader, aStatus, aStringLen,
aString);
if (NS_FAILED(rv)) {
if (!mRequests.RemoveObject(request)) {
mPreloads.RemoveElement(request, PreloadRequestComparator());
} else {
if (mRequests.RemoveObject(request) ||
mAsyncRequests.RemoveObject(request)) {
FireScriptAvailable(rv, request);
} else {
mPreloads.RemoveElement(request, PreloadRequestComparator());
}
}
@ -993,6 +1034,7 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
// so if you see this assertion it is likely something else that is
// wrong, especially if you see it more than once.
NS_ASSERTION(mRequests.IndexOf(aRequest) >= 0 ||
mAsyncRequests.IndexOf(aRequest) >= 0 ||
mPreloads.Contains(aRequest, PreloadRequestComparator()),
"aRequest should be pending!");

View File

@ -300,6 +300,7 @@ protected:
nsIDocument* mDocument; // [WEAK]
nsCOMArray<nsIScriptLoaderObserver> mObservers;
nsCOMArray<nsScriptLoadRequest> mRequests;
nsCOMArray<nsScriptLoadRequest> mAsyncRequests;
// In mRequests, the additional information here is stored by the element.
struct PreloadInfo {

View File

@ -323,6 +323,11 @@ _TEST_FILES = test_bug5141.html \
test_range_bounds.html \
test_bug475156.html \
bug475156.sjs \
test_copypaste.html \
test_bug503481.html \
file_bug503481.sjs \
test_bug503481b.html \
file_bug503481b_inner.html \
$(NULL)
# Disabled; see bug 492181

View File

@ -0,0 +1,43 @@
// 'timer' is global to avoid getting GCed which would cancel the timer
var timer;
const nsITimer = Components.interfaces.nsITimer;
function attemptUnblock(s) {
try {
let blockedResponse = null;
getObjectState("bug503481_" + s, function(x) {blockedResponse = x.wrappedJSObject.r});
blockedResponse.finish();
setObjectState("bug503481_" + s, null);
} catch(e) {
dump("unable to unblock " + s + "retrying in half a second\n");
timer = Components.classes["@mozilla.org/timer;1"]
.createInstance(nsITimer);
timer.initWithCallback(function () { attemptUnblock(s) }, 500, nsITimer.TYPE_ONE_SHOT);
}
}
function handleRequest(request, response)
{
var query = {};
request.queryString.split('&').forEach(function (val) {
var [name, value] = val.split('=');
query[name] = unescape(value);
});
dump("processing:" + request.queryString + "\n");
if (query.unblock) {
attemptUnblock(query.unblock);
}
if (query.blockOn) {
response.processAsync();
x = { r: response, QueryInterface: function(iid) { return this } };
x.wrappedJSObject = x;
setObjectState("bug503481_" + query.blockOn, x);
}
response.setHeader("Cache-Control", "no-cache", false);
response.setHeader("Content-Type", "text/plain", false);
response.write(query.body);
}

View File

@ -0,0 +1,85 @@
<!DOCTYPE HTML>
<html>
<head>
<!-- Async script that isn't preloaded -->
<script async src="file_bug503481.sjs?blockOn=R&body=runFirst();"></script>
<script>
firstRan = false;
secondRan = false;
thirdRan = false;
forthRan = false;
fifthRan = false;
sixthRan = false;
function runFirst() {
firstRan = true;
}
function runThird() {
parent.is(forthRan, false, "forth should still be blocked");
unblock("T");
thirdRan = true;
}
function runForth() {
forthRan = true;
}
function runFifth() {
parent.is(sixthRan, false, "sixth should be not run before non-async fifth");
fifthRan = true;
}
function runSixth() {
parent.is(fifthRan, true, "fifth should run before async sixth");
sixthRan = true;
}
function done() {
parent.is(firstRan, true, "first should have run by onload");
parent.is(secondRan, true, "second should have run by onload");
parent.is(thirdRan, true, "third should have run by onload");
parent.is(forthRan, true, "forth should have run by onload");
parent.is(fifthRan, true, "fifth should have run by onload");
parent.is(sixthRan, true, "sixth should have run by onload");
parent.SimpleTest.finish();
}
var reqs = [];
function unblock(s) {
xhr = new XMLHttpRequest();
xhr.open("GET", "file_bug503481.sjs?unblock=" + s);
xhr.send();
reqs.push(xhr);
}
parent.is(firstRan, false, "First async script shouldn't have run");
unblock("R");
</script>
<!-- test that inline async isn't actually async -->
<script async>
secondRan = true;
</script>
<script async>
parent.is(secondRan, true, "Second script shouldn't be async");
</script>
<!-- test that setting both defer and async treats the script as async -->
<script defer async src="file_bug503481.sjs?blockOn=S&body=runThird();"></script>
<script>
parent.is(thirdRan, false, "third should not have run yet");
unblock("S");
</script>
<script src="file_bug503481.sjs?blockOn=T&body=runForth();"></script>
<!-- test that preloading an async script works -->
<script>
setTimeout(function () { unblock("U"); }, 1000);
</script>
<script src="file_bug503481.sjs?blockOn=U&body=runFifth();"></script>
<script async src="file_bug503481.sjs?blockOn=V&body=runSixth();"></script>
<script>
parent.is(fifthRan, true, "fifth should have run by now");
parent.is(sixthRan, false, "sixth should not have run yet");
unblock("V");
</script>
</head>
<body onload="done()">

View File

@ -0,0 +1,70 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=503481
-->
<head>
<title>Test for Bug 503481</title>
<script src="/MochiKit/packed.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="done();">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=503481"
target="_blank" >Mozilla Bug 503481</a>
<p id="display"></p>
<script>
SimpleTest.waitForExplicitFinish();
function done() {
is(firstRan, true, "first has run");
is(secondRan, true, "second has run");
is(thirdRan, true, "third has run");
SimpleTest.finish();
}
var reqs = [];
function unblock(s) {
xhr = new XMLHttpRequest();
xhr.open("GET", "file_bug503481.sjs?unblock=" + s);
xhr.send();
reqs.push(xhr);
}
var firstRan = false, secondRan = false, thirdRan = false;
function runFirst() { firstRan = true; }
function runSecond() {
is(thirdRan, true, "should have run third already");
secondRan = true;
}
function runThird() {
is(secondRan, false, "shouldn't have unblocked second yet");
thirdRan = true;
unblock("B");
}
</script>
<script id=firstScript async src="file_bug503481.sjs?blockOn=A&body=runFirst();"></script>
<script id=firstScriptHelper>
is(document.getElementById("firstScript").async, true,
"async set");
is(document.getElementById("firstScriptHelper").async, false,
"async not set");
document.getElementById("firstScript").async = false;
is(document.getElementById("firstScript").async, false,
"async no longer set");
is(document.getElementById("firstScript").hasAttribute("async"), false,
"async attribute no longer set");
is(firstRan, false, "First async script shouldn't have run");
unblock("A");
</script>
<script async src="file_bug503481.sjs?blockOn=B&body=runSecond();"></script>
<script async src="file_bug503481.sjs?blockOn=C&body=runThird();"></script>
<script>
is(secondRan, false, "Second async script shouldn't have run");
is(thirdRan, false, "Third async script shouldn't have run");
unblock("C");
</script>
</body>
</html>

View File

@ -0,0 +1,23 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=503481
-->
<head>
<title>Test for Bug 503481</title>
<script src="/MochiKit/packed.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=503481"
target="_blank" >Mozilla Bug 503481</a>
<iframe src="file_bug503481b_inner.html"></iframe>
<script>
SimpleTest.waitForExplicitFinish();
// script in the iframe will call SimpleTest.finish()
</script>
</body>
</html>

View File

@ -0,0 +1,94 @@
<!DOCTYPE HTML>
<html>
<!--
-->
<head>
<title>Test for copy/paste</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=524975">Mozilla Bug </a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
function testCopyPaste () {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
// selection of the node
var node = document.getElementById('draggable');
window.getSelection().selectAllChildren(node);
// let's copy the selection
var webnav = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
var docShell = webnav.QueryInterface(Components.interfaces.nsIDocShell);
var documentViewer = docShell.contentViewer
.QueryInterface(Components.interfaces.nsIContentViewerEdit);
documentViewer.copySelection();
//--------- now check the content of the clipboard
var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
.getService(Components.interfaces.nsIClipboard);
// is the clipboard contain a text/unicode data ?
var transferable = Components.classes['@mozilla.org/widget/transferable;1']
.createInstance(Components.interfaces.nsITransferable);
transferable.addDataFlavor("text/unicode");
clipboard.getData(transferable, 1);
var data = {}
transferable.getTransferData ("text/unicode", data, {} ) ;
is (data.value.QueryInterface(Components.interfaces.nsISupportsString).data,
"This is a draggable bit of text.");
// is the clipboard contain a text/html data ?
transferable = Components.classes['@mozilla.org/widget/transferable;1']
.createInstance(Components.interfaces.nsITransferable);
transferable.addDataFlavor("text/html");
clipboard.getData(transferable, 1);
transferable.getTransferData ("text/html", data, {} ) ;
is (data.value.QueryInterface(Components.interfaces.nsISupportsString).data,
"<div id=\"draggable\" title=\"title to have a long HTML line\">This is a <em>draggable</em>\n bit of text.</div>");
//------ let's paste now in the textarea and verify its content
var textarea = document.getElementById('input');
textarea.focus();
textarea.QueryInterface(Components.interfaces.nsIDOMNSEditableElement)
.editor.paste(1);
is(textarea.value, "This is a draggable bit of text.");
// test copy/paste from/to textarea
var val = "1\n 2\n 3"
textarea.value=val;
textarea.select();
textarea.editor.copy();
textarea.value="";
textarea.editor.paste(1);
is(textarea.value, val);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(testCopyPaste);
</script>
</pre>
<div>
<div id="draggable" title="title to have a long HTML line">This is a <em>draggable</em> bit of text.</div>
<textarea id="input"></textarea>
</div>
</body>
</html>

View File

@ -61,48 +61,48 @@ var domFileBinary = file.getAsBinary();
var domFileBinary2 = utf16File.getAsBinary();
var domFileBinary3 = utf32File.getAsBinary();
var request1 = new FileRequest();
var request1 = new FileReader();
request1.onload = handleTextISO1;
request1.readAsText(file, "iso-8859-1");
var request2 = new FileRequest();
var request2 = new FileReader();
request2.onload = handleTextUTF8;
request2.readAsText(file);
var request3 = new FileRequest();
var request3 = new FileReader();
request3.onload = handleTextUTF8;
request3.readAsText(file, "");
var request4 = new FileRequest();
var request4 = new FileReader();
request4.onload = handleTextUTF8;
request4.readAsText(file, "UTF-8");
//Test a variety of encodings, and make sure they work properly
//Also, test a variety of the same calls with different numbers of arguments
var request5 = new FileRequest();
var request5 = new FileReader();
request5.onload = handleTextUTF16;
request5.readAsText(utf16File, "UTF-16");
var request6 = new FileRequest();
var request6 = new FileReader();
request6.onload = handleTextUTF32;
request6.readAsText(utf32File, "UTF-32");
//Test binary data accessor
var request7 = new FileRequest();
var request7 = new FileReader();
request7.onload = handleDataBinary;
request7.readAsBinaryString(file);
var request71 = new FileRequest();
var request71 = new FileReader();
request71.onload = handleDataBinary16;
request71.readAsBinaryString(utf16File);
var request72 = new FileRequest();
var request72 = new FileReader();
request72.onload = handleDataBinary32;
request72.readAsBinaryString(utf32File);
//Test data URI encoding on differing file sizes
//Testing data URI when length % 3 == 0
var request8 = new FileRequest();
var request8 = new FileReader();
request8.onload = handleDataURI;
request8.readAsDataURL(file);
@ -110,7 +110,7 @@ request8.readAsDataURL(file);
var file2 = createFileWithData(testData2, "02");
var domFileData1 = file2.getAsDataURL();
var request9 = new FileRequest();
var request9 = new FileReader();
request9.onload = handleDataURI1;
request9.readAsDataURL(file2);
@ -118,13 +118,13 @@ request9.readAsDataURL(file2);
var file3 = createFileWithData(testData3, "03");
var domFileData2 = file3.getAsDataURL();
var request10 = new FileRequest();
var request10 = new FileReader();
request10.onload = handleDataURI2;
request10.readAsDataURL(file3);
//Test asynchronous property of file access
var globalVar = 0;
var request105 = new FileRequest();
var request105 = new FileReader();
request105.onload = incGlobalVar;
request105.readAsText(file, "");
is(globalVar, 0, "testing to make sure getAsText doesn't block subsequent execution");
@ -142,19 +142,19 @@ var fileList = document.getElementById('fileList');
fileList.value = testFile4.path;
var file4 = fileList.files[0];
var request11 = new FileRequest();
var request11 = new FileReader();
request11.onabort = handleCancel;
request11.readAsText(file4);
request11.abort();
//Test error handling - Note: currently throws exceptions
/*testFile4.permissions = 0;
var request12 = new FileRequest();
var request12 = new FileReader();
request12.onerror = handleSecurityError;
request12.readAsText(file4, "");
testFile4.remove(false);
var request13 = new FileRequest();
var request13 = new FileReader();
request13.onerror = handleNotFoundError;
request13.readAsText(file4, "");*/
@ -164,7 +164,7 @@ function incGlobalVar(fileAsText) {
}
function handleCancel(event) {
var fileAsText = event.target.response;
var fileAsText = event.target.result;
var error = event.target.error;
is(error.code, FileError.ABORT_ERR, "error code set to CANCELED for canceled reads");
is(fileAsText, null, "file data should be null on canceled reads");
@ -172,7 +172,7 @@ function handleCancel(event) {
}
function handleTextISO1(event) {
var fileAsText = event.target.response;
var fileAsText = event.target.result;
var error = event.target.error;
is(error, null, "error code set to null for successful data accesses");
is(testData.length, fileAsText.length, "iso-1 async length should match testdata");
@ -181,7 +181,7 @@ function handleTextISO1(event) {
}
function handleTextUTF8(event) {
var fileAsUTF8 = event.target.response;
var fileAsUTF8 = event.target.result;
var error = event.target.error;
is(error, null, "error code set to null for successful data accesses");
is(testData.length, fileAsUTF8.length, "UTF-8 async length should match testdata");
@ -190,7 +190,7 @@ function handleTextUTF8(event) {
}
function handleTextUTF16(event) {
var fileAsUTF16 = event.target.response;
var fileAsUTF16 = event.target.result;
var error = event.target.error;
is(error, null, "error code set to SUCCESS for successful data accesses");
is(testData.length, fileAsUTF16.length, "UTF-16 async length should match testdata");
@ -199,7 +199,7 @@ function handleTextUTF16(event) {
}
function handleTextUTF32(event) {
var fileAsUTF32 = event.target.response;
var fileAsUTF32 = event.target.result;
var error = event.target.error;
is(error, null, "error code set to SUCCESS for successful data accesses");
is(testData.length, fileAsUTF32.length, "UTF-32 async length should match testdata");
@ -209,7 +209,7 @@ function handleTextUTF32(event) {
//Tests dataURI.length % 3 == 0
function handleDataURI(event) {
var fileAsDataURI = event.target.response;
var fileAsDataURI = event.target.result;
is(domFileData.length, fileAsDataURI.length, "data URI async length should match dom file data");
is(domFileData, fileAsDataURI, "data URI async string result should match dom file data");
testHasRun();
@ -217,7 +217,7 @@ function handleDataURI(event) {
//Tests dataURI.length % 3 == 1
function handleDataURI1(event) {
var fileAsDataURI = event.target.response;
var fileAsDataURI = event.target.result;
is(domFileData1.length, fileAsDataURI.length, "data URI async length should match dom file data1");
is(domFileData1, fileAsDataURI, "data URI async string result should match dom file data1");
testHasRun();
@ -225,35 +225,35 @@ function handleDataURI1(event) {
//Tests dataURI.length % 3 == 2
function handleDataURI2(event) {
var fileAsDataURI = event.target.response;
var fileAsDataURI = event.target.result;
is(domFileData2.length, fileAsDataURI.length, "data URI async length should match dom file data2");
is(domFileData2, fileAsDataURI, "data URI async string result should match dom file data2");
testHasRun();
}
function handleDataBinary(event) {
var fileAsBinary = event.target.response;
var fileAsBinary = event.target.result;
is(domFileBinary.length, fileAsBinary.length, "binary data async length should match dom file binary");
is(domFileBinary, fileAsBinary, "binary data async string result should match dom file binary");
testHasRun();
}
function handleDataBinary16(event) {
var fileAsBinary = event.target.response;
var fileAsBinary = event.target.result;
is(domFileBinary2.length, fileAsBinary.length, "binary data async length should match dom file binary16");
is(domFileBinary2, fileAsBinary, "binary data async string result should match dom file binary16");
testHasRun();
}
function handleDataBinary32(event) {
var fileAsBinary = event.target.response;
var fileAsBinary = event.target.result;
is(domFileBinary3.length, fileAsBinary.length, "binary data async length should match dom file binary32");
is(domFileBinary3, fileAsBinary, "binary data async string result should match dom file binary32");
testHasRun();
}
function handleSecurityError(event) {
var fileAsText = event.target.response;
var fileAsText = event.target.result;
var error = event.target.error;
is(error.code, FileError.SECURITY_ERR, "code for file security error should have value 18");
is(fileAsText, null, "file content should be null when error is encountered");
@ -261,7 +261,7 @@ function handleSecurityError(event) {
}
function handleNotFoundError(event) {
var fileAsText = event.target.response;
var fileAsText = event.target.result;
var error = event.target.error;
is(error.code, FileError.NOT_FOUND_ERR, "code for file not found error should have value 8");
is(fileAsText, null, "file content should be null when error is encountered");

View File

@ -1983,9 +1983,13 @@ nsEventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
// change during the drag.
dataTransfer->SetReadOnly();
if (status != nsEventStatus_eConsumeNoDefault)
DoDefaultDragStart(aPresContext, event, dataTransfer,
targetContent, isSelection);
if (status != nsEventStatus_eConsumeNoDefault) {
PRBool dragStarted = DoDefaultDragStart(aPresContext, event, dataTransfer,
targetContent, isSelection);
if (dragStarted) {
aEvent->flags |= NS_EVENT_FLAG_STOP_DISPATCH;
}
}
// Note that frame event handling doesn't care about NS_DRAGDROP_GESTURE,
// which is just as well since we don't really know which frame to
@ -2106,7 +2110,7 @@ nsEventStateManager::DetermineDragTarget(nsPresContext* aPresContext,
}
}
void
PRBool
nsEventStateManager::DoDefaultDragStart(nsPresContext* aPresContext,
nsDragEvent* aDragEvent,
nsDOMDataTransfer* aDataTransfer,
@ -2116,18 +2120,19 @@ nsEventStateManager::DoDefaultDragStart(nsPresContext* aPresContext,
nsCOMPtr<nsIDragService> dragService =
do_GetService("@mozilla.org/widget/dragservice;1");
if (!dragService)
return;
return PR_FALSE;
// Default handling for the draggesture/dragstart event.
//
// First, check if a drag session already exists. This means that the drag
// service was called directly within a draggesture handler. In this case,
// don't do anything more, as it is assumed that the handler is managing
// drag and drop manually.
// drag and drop manually. Make sure to return true to indicate that a drag
// began.
nsCOMPtr<nsIDragSession> dragSession;
dragService->GetCurrentSession(getter_AddRefs(dragSession));
if (dragSession)
return; // already a drag in progress
return PR_TRUE;
// No drag session is currently active, so check if a handler added
// any items to be dragged. If not, there isn't anything to drag.
@ -2135,7 +2140,7 @@ nsEventStateManager::DoDefaultDragStart(nsPresContext* aPresContext,
if (aDataTransfer)
aDataTransfer->GetMozItemCount(&count);
if (!count)
return;
return PR_FALSE;
// Get the target being dragged, which may not be the same as the
// target of the mouse event. If one wasn't set in the
@ -2148,7 +2153,7 @@ nsEventStateManager::DoDefaultDragStart(nsPresContext* aPresContext,
if (!dragTarget) {
dragTarget = do_QueryInterface(aDragTarget);
if (!dragTarget)
return;
return PR_FALSE;
}
// check which drag effect should initially be used. If the effect was not
@ -2183,7 +2188,7 @@ nsEventStateManager::DoDefaultDragStart(nsPresContext* aPresContext,
nsCOMPtr<nsISupportsArray> transArray;
aDataTransfer->GetTransferables(getter_AddRefs(transArray));
if (!transArray)
return;
return PR_FALSE;
// XXXndeakin don't really want to create a new drag DOM event
// here, but we need something to pass to the InvokeDragSession
@ -2231,6 +2236,8 @@ nsEventStateManager::DoDefaultDragStart(nsPresContext* aPresContext,
imageX, imageY, domDragEvent,
aDataTransfer);
}
return PR_TRUE;
}
nsresult
@ -3598,7 +3605,7 @@ nsEventStateManager::DispatchMouseEvent(nsGUIEvent* aEvent, PRUint32 aMessage,
event.isControl = ((nsMouseEvent*)aEvent)->isControl;
event.isAlt = ((nsMouseEvent*)aEvent)->isAlt;
event.isMeta = ((nsMouseEvent*)aEvent)->isMeta;
event.nativeMsg = ((nsMouseEvent*)aEvent)->nativeMsg;
event.pluginEvent = ((nsMouseEvent*)aEvent)->pluginEvent;
event.relatedTarget = aRelatedContent;
mCurrentTargetContent = aTargetContent;

View File

@ -322,18 +322,19 @@ protected:
/*
* Perform the default handling for the dragstart/draggesture event and set up a
* drag for aDataTransfer if it contains any data.
* drag for aDataTransfer if it contains any data. Returns true if a drag has
* started.
*
* aDragEvent - the dragstart/draggesture event
* aDataTransfer - the data transfer that holds the data to be dragged
* aDragTarget - the target of the drag
* aIsSelection - true if a selection is being dragged
*/
void DoDefaultDragStart(nsPresContext* aPresContext,
nsDragEvent* aDragEvent,
nsDOMDataTransfer* aDataTransfer,
nsIContent* aDragTarget,
PRBool aIsSelection);
PRBool DoDefaultDragStart(nsPresContext* aPresContext,
nsDragEvent* aDragEvent,
nsDOMDataTransfer* aDataTransfer,
nsIContent* aDragTarget,
PRBool aIsSelection);
PRBool IsTrackingDragGesture ( ) const { return mGestureDownContent != nsnull; }
/**

View File

@ -54,7 +54,7 @@ INPUT(popupText1): blur \n\
setPrefAndDoTest(eventLogForNewWindow,'Body',2); // 2 = open new window as window
}
if (navigator.platform.indexOf("Lin") == -1) {
if (navigator.platform.indexOf("Lin") == -1 && navigator.platform.indexOf("SunOS") == -1) {
SimpleTest.waitForExplicitFinish(); // the finish() call is in bug299673.js
addLoadEvent(doTest);
} else {

View File

@ -268,15 +268,9 @@ nsHTMLLinkElement::CreateAndDispatchEvent(nsIDocument* aDoc,
nsRefPtr<nsPLDOMEvent> event = new nsPLDOMEvent(this, aEventName, PR_TRUE);
if (event) {
// If we have script blockers on the stack then we want to run as soon as
// they are removed. Otherwise punt the runable to the event loop as we
// don't know when it will be safe to run script. In particular, we might
// be in the middle of a pagehide right now, and firing this event at that
// point is not such a great idea.
if (nsContentUtils::IsSafeToRunScript())
event->PostDOMEvent();
else
event->RunDOMEventWhenSafe();
// Always run async in order to avoid running script when the content
// sink isn't expecting it.
event->PostDOMEvent();
}
}

View File

@ -36,6 +36,7 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsIDOMHTMLScriptElement.h"
#include "nsIDOMNSHTMLScriptElement.h"
#include "nsIDOMEventTarget.h"
#include "nsGenericHTMLElement.h"
#include "nsGkAtoms.h"
@ -304,6 +305,7 @@ nsHTMLScriptEventHandler::Invoke(nsISupports *aTargetObject,
class nsHTMLScriptElement : public nsGenericHTMLElement,
public nsIDOMHTMLScriptElement,
public nsIDOMNSHTMLScriptElement,
public nsScriptElement
{
public:
@ -322,8 +324,8 @@ public:
// nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
// nsIDOMHTMLScriptElement
NS_DECL_NSIDOMHTMLSCRIPTELEMENT
NS_DECL_NSIDOMNSHTMLSCRIPTELEMENT
// nsIScriptElement
virtual void GetScriptType(nsAString& type);
@ -331,6 +333,7 @@ public:
virtual void GetScriptText(nsAString& text);
virtual void GetScriptCharset(nsAString& charset);
virtual PRBool GetScriptDeferred();
virtual PRBool GetScriptAsync();
// nsIContent
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
@ -378,10 +381,11 @@ NS_IMPL_RELEASE_INHERITED(nsHTMLScriptElement, nsGenericElement)
// QueryInterface implementation for nsHTMLScriptElement
NS_INTERFACE_TABLE_HEAD(nsHTMLScriptElement)
NS_HTML_CONTENT_INTERFACE_TABLE4(nsHTMLScriptElement,
NS_HTML_CONTENT_INTERFACE_TABLE5(nsHTMLScriptElement,
nsIDOMHTMLScriptElement,
nsIScriptLoaderObserver,
nsIScriptElement,
nsIDOMNSHTMLScriptElement,
nsIMutationObserver)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLScriptElement,
nsGenericHTMLElement)
@ -450,6 +454,7 @@ nsHTMLScriptElement::SetText(const nsAString& aValue)
NS_IMPL_STRING_ATTR(nsHTMLScriptElement, Charset, charset)
NS_IMPL_BOOL_ATTR(nsHTMLScriptElement, Defer, defer)
NS_IMPL_BOOL_ATTR(nsHTMLScriptElement, Async, async)
NS_IMPL_URI_ATTR(nsHTMLScriptElement, Src, src)
NS_IMPL_STRING_ATTR(nsHTMLScriptElement, Type, type)
NS_IMPL_STRING_ATTR(nsHTMLScriptElement, HtmlFor, _for)
@ -519,11 +524,22 @@ nsHTMLScriptElement::GetScriptCharset(nsAString& charset)
PRBool
nsHTMLScriptElement::GetScriptDeferred()
{
PRBool defer;
PRBool defer, async;
GetAsync(&async);
GetDefer(&defer);
nsCOMPtr<nsIURI> uri = GetScriptURI();
return defer && uri;
return !async && defer && uri;
}
PRBool
nsHTMLScriptElement::GetScriptAsync()
{
PRBool async;
GetAsync(&async);
nsCOMPtr<nsIURI> uri = GetScriptURI();
return async && uri;
}
PRBool

View File

@ -155,7 +155,7 @@ _TEST_FILES += \
small-shot.ogg \
sound.ogg \
$(NULL)
# Wave sample files
_TEST_FILES += \
big.wav \
@ -178,7 +178,6 @@ _TEST_FILES += \
ifdef MOZ_OGG
_TEST_FILES += \
dynamic_redirect.sjs \
test_access_control.html \
file_access_controls.html \
test_bug448534.html \
test_bug468190.html \
@ -225,9 +224,10 @@ _TEST_FILES += \
# test_autobuffer2.html
ifneq ($(OS_ARCH),WINNT)
# These tests are disabled on windows until we
# figure out the random failures. See bug 475369.
# figure out the random failures. See bug 475369 and bug 526323
_TEST_FILES += \
test_timeupdate3.html \
test_access_control.html \
$(NULL)
endif
endif

View File

@ -4084,7 +4084,7 @@ ConvolvePixel(const PRUint8 *aSourceData,
}
for (PRInt32 i = 0; i < channels; i++) {
aTargetData[aY * aStride + 4 * aX + offsets[i]] =
BoundInterval(static_cast<PRInt32>(sum[i] / aDivisor + aBias * 255), 256);
BoundInterval(static_cast<PRInt32>(sum[i] / aDivisor + aBias), 256);
}
if (aPreserveAlpha) {
aTargetData[aY * aStride + 4 * aX + GFX_ARGB32_OFFSET_A] =

View File

@ -80,6 +80,7 @@ public:
virtual void GetScriptText(nsAString& text);
virtual void GetScriptCharset(nsAString& charset);
virtual PRBool GetScriptDeferred();
virtual PRBool GetScriptAsync();
// nsScriptElement
virtual PRBool HasScriptContent();
@ -232,6 +233,12 @@ nsSVGScriptElement::GetScriptDeferred()
return PR_FALSE;
}
PRBool
nsSVGScriptElement::GetScriptAsync()
{
return PR_FALSE;
}
//----------------------------------------------------------------------
// nsScriptElement methods

View File

@ -2892,7 +2892,8 @@ nsXULDocument::ResumeWalk()
// <html:script src="..." />) can be properly re-loaded if the
// cached copy of the document becomes stale.
nsresult rv;
nsCOMPtr<nsIURI> overlayURI = mCurrentPrototype->GetURI();
nsCOMPtr<nsIURI> overlayURI =
mCurrentPrototype ? mCurrentPrototype->GetURI() : nsnull;
while (1) {
// Begin (or resume) walking the current prototype.

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