Merge cvs-trunk-mirror -> mozilla-central. There's a C++ bug in js/src/jsinterp.cpp that I am going to file upstream.
Merge cvs-trunk-mirror -> mozilla-central. There's a C++ bug in js/src/jsinterp.cpp that I am going to file upstream.
--- a/Makefile.in
+++ b/Makefile.in
@@ -70,17 +70,17 @@ include $(topsrcdir)/$(MOZ_BUILD_APP)/bu
TIERS += testharness
# test harnesses
ifdef ENABLE_TESTS
tier_testharness_dirs += tools/test-harness
endif
-GARBAGE_DIRS += dist _javagen _tests staticlib
+GARBAGE_DIRS += dist _javagen _profile _tests staticlib
DIST_GARBAGE = config.cache config.log config.status config-defs.h \
dependencies.beos config/autoconf.mk config/myrules.mk config/myconfig.mk \
unallmakefiles mozilla-config.h \
netwerk/necko-config.h xpcom/xpcom-config.h xpcom/xpcom-private.h \
$(topsrcdir)/.mozconfig.mk $(topsrcdir)/.mozconfig.out
# Build pseudo-external modules first when export is explicitly called
export::
@@ -157,17 +157,17 @@ ifdef UNIVERSAL_BINARY
MAKE_SYM_STORE_ARGS := -a "ppc i386" --vcs-info
MAKE_SYM_STORE_PATH := $(DIST)/universal
else
MAKE_SYM_STORE_ARGS := -a $(OS_TEST) --vcs-info
MAKE_SYM_STORE_PATH := $(DIST)/bin
endif
DUMP_SYMS_BIN ?= $(DIST)/host/bin/dump_syms
endif
-ifeq ($(OS_ARCH),Linux)
+ifeq (,$(filter-out Linux SunOS,$(OS_ARCH)))
MAKE_SYM_STORE_ARGS := --vcs-info
DUMP_SYMS_BIN ?= $(DIST)/host/bin/dump_syms
MAKE_SYM_STORE_PATH := $(DIST)/bin
endif
ifdef MOZ_SYMBOLS_EXTRA_BUILDID
EXTRA_BUILDID := -$(MOZ_SYMBOLS_EXTRA_BUILDID)
endif
--- a/accessible/public/nsPIAccessible.idl
+++ b/accessible/public/nsPIAccessible.idl
@@ -112,10 +112,18 @@ interface nsPIAccessible : nsISupports
/**
* Set the ARIA role map entry for a new accessible.
* For a newly created accessible, specify which role map entry should be used.
* @param aRoleMapEntry The ARIA nsRoleMapEntry* for the accessible, or
* nsnull if none.
*/
void setRoleMapEntry(in nsRoleMapEntryPtr aRoleMapEntry);
+
+ /**
+ * Maps ARIA state attributes to state of accessible. Note the given state
+ * argument should hold states for accessible before you pass it into this
+ * method.
+ * @param in/out where to fill the states into.
+ */
+ void getARIAState(out unsigned long aState);
};
--- a/accessible/src/base/nsAccessibilityAtomList.h
+++ b/accessible/src/base/nsAccessibilityAtomList.h
@@ -229,8 +229,13 @@ ACCESSIBILITY_ATOM(aria_valuetext, "aria
// of an HTML button from the button frame
ACCESSIBILITY_ATOM(defaultLabel, "defaultLabel")
// Object attributes
ACCESSIBILITY_ATOM(level, "level")
ACCESSIBILITY_ATOM(posinset, "posinset")
ACCESSIBILITY_ATOM(setsize, "setsize")
ACCESSIBILITY_ATOM(lineNumber, "line-number")
+ACCESSIBILITY_ATOM(containerRelevant, "container-relevant")
+ACCESSIBILITY_ATOM(containerLive, "container-live")
+ACCESSIBILITY_ATOM(containerChannel, "container-channel")
+ACCESSIBILITY_ATOM(containerAtomic, "container-atomic")
+ACCESSIBILITY_ATOM(containerBusy, "container-busy")
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -448,16 +448,20 @@ nsAccessibilityService::CreateRootAccess
else {
*aRootAcc = new nsRootAccessibleWrap(rootNode, weakShell);
}
if (!*aRootAcc)
return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsPIAccessNode> privateAccessNode(do_QueryInterface(*aRootAcc));
privateAccessNode->Init();
+ nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(rootNode);
+ nsCOMPtr<nsPIAccessible> privateAccessible =
+ do_QueryInterface(privateAccessNode);
+ privateAccessible->SetRoleMapEntry(roleMapEntry);
NS_ADDREF(*aRootAcc);
return NS_OK;
}
/**
* HTML widget creation
--- a/accessible/src/base/nsAccessibilityUtils.cpp
+++ b/accessible/src/base/nsAccessibilityUtils.cpp
@@ -314,31 +314,45 @@ nsAccUtils::FireAccEvent(PRUint32 aEvent
return pAccessible->FireAccessibleEvent(event);
}
PRBool
nsAccUtils::IsAncestorOf(nsIDOMNode *aPossibleAncestorNode,
nsIDOMNode *aPossibleDescendantNode)
{
- NS_ENSURE_TRUE(aPossibleAncestorNode, PR_FALSE);
- NS_ENSURE_TRUE(aPossibleDescendantNode, PR_FALSE);
+ NS_ENSURE_TRUE(aPossibleAncestorNode && aPossibleDescendantNode, PR_FALSE);
nsCOMPtr<nsIDOMNode> loopNode = aPossibleDescendantNode;
nsCOMPtr<nsIDOMNode> parentNode;
while (NS_SUCCEEDED(loopNode->GetParentNode(getter_AddRefs(parentNode))) &&
parentNode) {
if (parentNode == aPossibleAncestorNode) {
return PR_TRUE;
}
loopNode.swap(parentNode);
}
return PR_FALSE;
}
+PRBool
+nsAccUtils::AreSiblings(nsIDOMNode *aDOMNode1,
+ nsIDOMNode *aDOMNode2)
+{
+ NS_ENSURE_TRUE(aDOMNode1 && aDOMNode2, PR_FALSE);
+
+ nsCOMPtr<nsIDOMNode> parentNode1, parentNode2;
+ if (NS_SUCCEEDED(aDOMNode1->GetParentNode(getter_AddRefs(parentNode1))) &&
+ NS_SUCCEEDED(aDOMNode2->GetParentNode(getter_AddRefs(parentNode2))) &&
+ parentNode1 == parentNode2) {
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
already_AddRefed<nsIAccessible>
nsAccUtils::GetAncestorWithRole(nsIAccessible *aDescendant, PRUint32 aRole)
{
nsCOMPtr<nsIAccessible> parentAccessible = aDescendant, testRoleAccessible;
while (NS_SUCCEEDED(parentAccessible->GetParent(getter_AddRefs(testRoleAccessible))) &&
testRoleAccessible) {
PRUint32 testRole;
testRoleAccessible->GetFinalRole(&testRole);
@@ -928,8 +942,38 @@ nsAccUtils::IsARIAPropForObjectAttr(nsIA
aAtom != nsAccessibilityAtoms::aria_relevant &&
aAtom != nsAccessibilityAtoms::aria_required &&
aAtom != nsAccessibilityAtoms::aria_selected &&
aAtom != nsAccessibilityAtoms::aria_valuemax &&
aAtom != nsAccessibilityAtoms::aria_valuemin &&
aAtom != nsAccessibilityAtoms::aria_valuenow &&
aAtom != nsAccessibilityAtoms::aria_valuetext;
}
+
+void nsAccUtils::GetLiveContainerAttributes(nsIPersistentProperties *aAttributes,
+ nsIContent *aStartContent, nsIContent *aTopContent)
+{
+ nsAutoString atomic, live, relevant, channel, busy;
+ nsIContent *ancestor = aStartContent;
+ while (ancestor) {
+ if (relevant.IsEmpty() &&
+ ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_relevant, relevant))
+ SetAccAttr(aAttributes, nsAccessibilityAtoms::containerRelevant, relevant);
+ if (live.IsEmpty() &&
+ ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_live, live))
+ SetAccAttr(aAttributes, nsAccessibilityAtoms::containerLive, live);
+ if (channel.IsEmpty() &&
+ ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_channel, channel))
+ SetAccAttr(aAttributes, nsAccessibilityAtoms::containerChannel, channel);
+ if (atomic.IsEmpty() &&
+ ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_atomic, atomic))
+ SetAccAttr(aAttributes, nsAccessibilityAtoms::containerAtomic, atomic);
+ if (busy.IsEmpty() &&
+ ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_busy, busy))
+ SetAccAttr(aAttributes, nsAccessibilityAtoms::containerBusy, busy);
+ if (ancestor == aTopContent)
+ break;
+ ancestor = ancestor->GetParent();
+ if (!ancestor) {
+ ancestor = aTopContent; // Use <body>/<frameset>
+ }
+ }
+}
--- a/accessible/src/base/nsAccessibilityUtils.h
+++ b/accessible/src/base/nsAccessibilityUtils.h
@@ -144,16 +144,23 @@ public:
* @param aPossibleAncestorNode -- node to test for ancestor-ness of aPossibleDescendantNode
* @param aPossibleDescendantNode -- node to test for descendant-ness of aPossibleAncestorNode
* @return PR_TRUE if aPossibleAncestorNode is an ancestor of aPossibleDescendantNode
*/
static PRBool IsAncestorOf(nsIDOMNode *aPossibleAncestorNode,
nsIDOMNode *aPossibleDescendantNode);
/**
+ * Are the first node and the second siblings?
+ * @return PR_TRUE if aDOMNode1 and aDOMNode2 have same parent
+ */
+ static PRBool AreSiblings(nsIDOMNode *aDOMNode1,
+ nsIDOMNode *aDOMNode2);
+
+ /**
* If an ancestor in this document exists with the given role, return it
* @param aDescendant Descendant to start search with
* @param aRole Role to find matching ancestor for
* @return The ancestor accessible with the given role, or nsnull if no match is found
*/
static already_AddRefed<nsIAccessible>
GetAncestorWithRole(nsIAccessible *aDescendant, PRUint32 aRole);
@@ -361,12 +368,22 @@ public:
nsIContent *aLookContent,
nsIAtom **aRelationAttrs,
PRUint32 aAttrNum = 1,
nsIContent *aExcludeContent = nsnull,
nsIAtom *aTagType = nsAccessibilityAtoms::label);
// Return PR_TRUE if the ARIA property should always be exposed as an object attribute
static PRBool IsARIAPropForObjectAttr(nsIAtom *aAtom);
+
+
+ /**
+ * Get container-foo live region attributes for the given node
+ * @param aAttributes Where to store the attributes
+ * @param aStartContent Node to start from
+ * @param aTopContent Node to end at
+ */
+ static void GetLiveContainerAttributes(nsIPersistentProperties *aAttributes,
+ nsIContent *aStartContent, nsIContent *aTopContent);
};
#endif
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -484,32 +484,31 @@ NS_IMETHODIMP nsAccessible::SetNextSibli
{
mNextSibling = aNextSibling? aNextSibling: DEAD_END_ACCESSIBLE;
return NS_OK;
}
nsIContent *nsAccessible::GetRoleContent(nsIDOMNode *aDOMNode)
{
// Given the DOM node for an acessible, return content node that
- // we should look at role string from
+ // we should look for ARIA properties on.
// For non-document accessibles, this is the associated content node.
- // For doc accessibles, first try the <body> if it's HTML and there is
- // a role attribute used there.
+ // For doc accessibles, use the <body>/<frameset> if it's HTML.
// For any other doc accessible , this is the document element.
nsCOMPtr<nsIContent> content(do_QueryInterface(aDOMNode));
if (!content) {
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(aDOMNode));
if (domDoc) {
nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(aDOMNode));
if (htmlDoc) {
nsCOMPtr<nsIDOMHTMLElement> bodyElement;
htmlDoc->GetBody(getter_AddRefs(bodyElement));
content = do_QueryInterface(bodyElement);
}
- if (!content) {
+ else {
nsCOMPtr<nsIDOMElement> docElement;
domDoc->GetDocumentElement(getter_AddRefs(docElement));
content = do_QueryInterface(docElement);
}
}
}
return content;
}
@@ -1998,82 +1997,58 @@ NS_IMETHODIMP nsAccessible::GetFinalRole
}
}
return mDOMNode ? GetRole(aRole) : NS_ERROR_FAILURE; // Node already shut down
}
NS_IMETHODIMP
nsAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
{
- NS_ENSURE_ARG_POINTER(aAttributes);
- *aAttributes = nsnull;
-
+ NS_ENSURE_ARG_POINTER(aAttributes); // In/out param. Created if necessary.
+
nsCOMPtr<nsIContent> content = GetRoleContent(mDOMNode);
if (!content) {
return NS_ERROR_FAILURE;
}
- nsCOMPtr<nsIPersistentProperties> attributes =
- do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
- NS_ENSURE_TRUE(attributes, NS_ERROR_OUT_OF_MEMORY);
-
- nsAccEvent::GetLastEventAttributes(mDOMNode, attributes);
+ nsCOMPtr<nsIPersistentProperties> attributes = *aAttributes;
+ if (!attributes) {
+ // Create only if an array wasn't already passed in
+ attributes = do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
+ NS_ENSURE_TRUE(attributes, NS_ERROR_OUT_OF_MEMORY);
+ NS_ADDREF(*aAttributes = attributes);
+ }
nsresult rv = GetAttributesInternal(attributes);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString id;
nsAutoString oldValueUnused;
if (nsAccUtils::GetID(content, id)) {
+ // Expose ID. If an <iframe id> exists override the one on the <body> of the source doc,
+ // because the specific instance is what makes the ID useful for scripts
attributes->SetStringProperty(NS_LITERAL_CSTRING("id"), id, oldValueUnused);
}
- nsAutoString _class;
- if (content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::_class, _class))
- nsAccUtils::SetAccAttr(attributes, nsAccessibilityAtoms::_class, _class);
-
nsAutoString xmlRoles;
if (content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::role, xmlRoles)) {
attributes->SetStringProperty(NS_LITERAL_CSTRING("xml-roles"), xmlRoles, oldValueUnused);
}
nsCOMPtr<nsIAccessibleValue> supportsValue = do_QueryInterface(static_cast<nsIAccessible*>(this));
if (supportsValue) {
// We support values, so expose the string value as well, via the valuetext object attribute
// We test for the value interface because we don't want to expose traditional get_accValue()
// information such as URL's on links and documents, or text in an input
nsAutoString valuetext;
GetValue(valuetext);
attributes->SetStringProperty(NS_LITERAL_CSTRING("valuetext"), valuetext, oldValueUnused);
}
- // Get container-foo computed live region properties based on the closest container with
- // the live region attribute
- nsAutoString atomic, live, relevant, channel, busy;
- nsIContent *ancestor = content;
- while (ancestor) {
- if (relevant.IsEmpty() &&
- ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_relevant, relevant))
- attributes->SetStringProperty(NS_LITERAL_CSTRING("container-relevant"), relevant, oldValueUnused);
- if (live.IsEmpty() &&
- ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_live, live))
- attributes->SetStringProperty(NS_LITERAL_CSTRING("container-live"), live, oldValueUnused);
- if (channel.IsEmpty() &&
- ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_channel, channel))
- attributes->SetStringProperty(NS_LITERAL_CSTRING("container-channel"), channel, oldValueUnused);
- if (atomic.IsEmpty() &&
- ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_atomic, atomic))
- attributes->SetStringProperty(NS_LITERAL_CSTRING("container-atomic"), atomic, oldValueUnused);
- if (busy.IsEmpty() &&
- ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_busy, busy))
- attributes->SetStringProperty(NS_LITERAL_CSTRING("container-busy"), busy, oldValueUnused);
- ancestor = ancestor->GetParent();
- }
-
PRUint32 role = Role(this);
if (role == nsIAccessibleRole::ROLE_CHECKBUTTON ||
role == nsIAccessibleRole::ROLE_PUSHBUTTON ||
role == nsIAccessibleRole::ROLE_MENUITEM ||
role == nsIAccessibleRole::ROLE_LISTITEM ||
role == nsIAccessibleRole::ROLE_OUTLINEITEM ||
content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_checked)) {
// Might be checkable -- checking role & ARIA attribute first is faster than getting state
@@ -2163,35 +2138,75 @@ nsAccessible::GetAttributes(nsIPersisten
continue; // No need to expose obj attribute -- will be exposed some other way
nsAutoString value;
if (content->GetAttr(kNameSpaceID_None, attrAtom, value)) {
attributes->SetStringProperty(nsDependentCString(attrStr + 5), value, oldValueUnused);
}
}
}
- attributes.swap(*aAttributes);
-
return NS_OK;
}
nsresult
nsAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
{
- nsCOMPtr<nsIDOMElement> element(do_QueryInterface(GetRoleContent(mDOMNode)));
+ // Attributes set by this method will not be used to override attributes on a sub-document accessible
+ // when there is a <frame>/<iframe> element that spawned the sub-document
+ nsIContent *content = GetRoleContent(mDOMNode);
+ nsCOMPtr<nsIDOMElement> element(do_QueryInterface(content));
NS_ENSURE_TRUE(element, NS_ERROR_UNEXPECTED);
nsAutoString tagName;
element->GetTagName(tagName);
if (!tagName.IsEmpty()) {
nsAutoString oldValueUnused;
aAttributes->SetStringProperty(NS_LITERAL_CSTRING("tag"), tagName,
oldValueUnused);
}
+ nsAccEvent::GetLastEventAttributes(mDOMNode, aAttributes);
+
+ // Expose class because it may have useful microformat information
+ // Let the class from an iframe's document be exposed, don't override from <iframe class>
+ nsAutoString _class;
+ if (content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::_class, _class))
+ nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::_class, _class);
+
+ // Get container-foo computed live region properties based on the closest container with
+ // the live region attribute.
+ // Inner nodes override outer nodes within the same document --
+ // The inner nodes can be used to override live region behavior on more general outer nodes
+ // However, nodes in outer documents override nodes in inner documents:
+ // Outer doc author may want to override properties on a widget they used in an iframe
+ nsCOMPtr<nsIDOMNode> startNode = mDOMNode;
+ nsIContent *startContent = content;
+ while (PR_TRUE) {
+ NS_ENSURE_STATE(startContent);
+ nsIDocument *doc = startContent->GetDocument();
+ nsCOMPtr<nsIDOMNode> docNode = do_QueryInterface(doc);
+ NS_ENSURE_STATE(docNode);
+ nsIContent *topContent = GetRoleContent(docNode);
+ NS_ENSURE_STATE(topContent);
+ nsAccUtils::GetLiveContainerAttributes(aAttributes, startContent, topContent);
+ // Allow ARIA live region markup from outer documents to override
+ nsCOMPtr<nsISupports> container = doc->GetContainer();
+ nsIDocShellTreeItem *docShellTreeItem = nsnull;
+ if (container)
+ CallQueryInterface(container, &docShellTreeItem);
+ if (!docShellTreeItem)
+ break;
+ nsIDocShellTreeItem *sameTypeParent = nsnull;
+ docShellTreeItem->GetSameTypeParent(&sameTypeParent);
+ if (!sameTypeParent || sameTypeParent == docShellTreeItem)
+ break;
+ nsIDocument *parentDoc = doc->GetParentDocument();
+ startContent = parentDoc->FindContentForSubDocument(doc);
+ }
+
return NS_OK;
}
NS_IMETHODIMP
nsAccessible::GroupPosition(PRInt32 *aGroupLevel,
PRInt32 *aSimilarItemsInGroup,
PRInt32 *aPositionInGroup)
{
@@ -2261,17 +2276,17 @@ NS_IMETHODIMP
nsAccessible::GetFinalState(PRUint32 *aState, PRUint32 *aExtraState)
{
NS_ENSURE_ARG_POINTER(aState);
nsresult rv = GetState(aState, aExtraState);
NS_ENSURE_SUCCESS(rv, rv);
// Apply ARIA states to be sure accessible states will be overriden.
- *aState |= GetARIAState();
+ GetARIAState(aState);
if (mRoleMapEntry && mRoleMapEntry->role == nsIAccessibleRole::ROLE_PAGETAB) {
if (*aState & nsIAccessibleStates::STATE_FOCUSED) {
*aState |= nsIAccessibleStates::STATE_SELECTED;
} else {
// Expose 'selected' state on ARIA tab if the focus is on internal element
// of related tabpanel.
nsCOMPtr<nsIAccessible> tabPanel;
@@ -2386,49 +2401,49 @@ nsAccessible::GetFinalState(PRUint32 *aS
else {
*aExtraState |= nsIAccessibleStates::EXT_STATE_HORIZONTAL;
}
}
return NS_OK;
}
-PRUint32
-nsAccessible::GetARIAState()
+nsresult
+nsAccessible::GetARIAState(PRUint32 *aState)
{
// Test for universal states first
nsIContent *content = GetRoleContent(mDOMNode);
if (!content) {
- return 0;
+ return NS_OK;
}
PRUint32 ariaState = 0;
PRUint32 index = 0;
- while (MappedAttrState(content, &ariaState, &nsARIAMap::gWAIUnivStateMap[index])) {
+ while (MappedAttrState(content, aState, &nsARIAMap::gWAIUnivStateMap[index])) {
++ index;
}
if (!mRoleMapEntry)
- return ariaState;
+ return NS_OK;
// Once DHTML role is used, we're only readonly if DHTML readonly used
ariaState &= ~nsIAccessibleStates::STATE_READONLY;
ariaState |= mRoleMapEntry->state;
- if (MappedAttrState(content, &ariaState, &mRoleMapEntry->attributeMap1) &&
- MappedAttrState(content, &ariaState, &mRoleMapEntry->attributeMap2) &&
- MappedAttrState(content, &ariaState, &mRoleMapEntry->attributeMap3) &&
- MappedAttrState(content, &ariaState, &mRoleMapEntry->attributeMap4) &&
- MappedAttrState(content, &ariaState, &mRoleMapEntry->attributeMap5) &&
- MappedAttrState(content, &ariaState, &mRoleMapEntry->attributeMap6) &&
- MappedAttrState(content, &ariaState, &mRoleMapEntry->attributeMap7)) {
- MappedAttrState(content, &ariaState, &mRoleMapEntry->attributeMap8);
+ if (MappedAttrState(content, aState, &mRoleMapEntry->attributeMap1) &&
+ MappedAttrState(content, aState, &mRoleMapEntry->attributeMap2) &&
+ MappedAttrState(content, aState, &mRoleMapEntry->attributeMap3) &&
+ MappedAttrState(content, aState, &mRoleMapEntry->attributeMap4) &&
+ MappedAttrState(content, aState, &mRoleMapEntry->attributeMap5) &&
+ MappedAttrState(content, aState, &mRoleMapEntry->attributeMap6) &&
+ MappedAttrState(content, aState, &mRoleMapEntry->attributeMap7)) {
+ MappedAttrState(content, aState, &mRoleMapEntry->attributeMap8);
}
- return ariaState;
+ return NS_OK;
}
// Not implemented by this class
/* DOMString getValue (); */
NS_IMETHODIMP nsAccessible::GetValue(nsAString& aValue)
{
if (!mDOMNode) {
@@ -2548,43 +2563,89 @@ nsAccessible::GetKeyBindings(PRUint8 aAc
NS_IMETHODIMP nsAccessible::GetRole(PRUint32 *aRole)
{
NS_ENSURE_ARG_POINTER(aRole);
*aRole = nsIAccessibleRole::ROLE_NOTHING;
return NS_OK;
}
/* PRUint8 getAccNumActions (); */
-NS_IMETHODIMP nsAccessible::GetNumActions(PRUint8 *aNumActions)
+NS_IMETHODIMP
+nsAccessible::GetNumActions(PRUint8 *aNumActions)
{
+ NS_ENSURE_ARG_POINTER(aNumActions);
*aNumActions = 0;
+
+ if (IsDefunct())
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
+ PRBool isOnclick = nsAccUtils::HasListener(content,
+ NS_LITERAL_STRING("click"));
+
+ if (isOnclick)
+ *aNumActions = 1;
+
return NS_OK;
}
/* DOMString getAccActionName (in PRUint8 index); */
-NS_IMETHODIMP nsAccessible::GetActionName(PRUint8 index, nsAString& aName)
+NS_IMETHODIMP
+nsAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
{
- return NS_ERROR_FAILURE;
+ aName.Truncate();
+
+ if (aIndex != 0)
+ return NS_ERROR_INVALID_ARG;
+
+ if (IsDefunct())
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
+ PRBool isOnclick = nsAccUtils::HasListener(content,
+ NS_LITERAL_STRING("click"));
+
+ if (isOnclick) {
+ aName.AssignLiteral("click");
+ return NS_OK;
+ }
+
+ return NS_ERROR_INVALID_ARG;
}
/* DOMString getActionDescription (in PRUint8 index); */
-NS_IMETHODIMP nsAccessible::GetActionDescription(PRUint8 aIndex, nsAString& aDescription)
+NS_IMETHODIMP
+nsAccessible::GetActionDescription(PRUint8 aIndex, nsAString& aDescription)
{
// default to localized action name.
nsAutoString name;
nsresult rv = GetActionName(aIndex, name);
NS_ENSURE_SUCCESS(rv, rv);
return GetTranslatedString(name, aDescription);
}
/* void doAction (in PRUint8 index); */
-NS_IMETHODIMP nsAccessible::DoAction(PRUint8 index)
+NS_IMETHODIMP
+nsAccessible::DoAction(PRUint8 aIndex)
{
- return NS_ERROR_FAILURE;
+ if (aIndex != 0)
+ return NS_ERROR_INVALID_ARG;
+
+ if (IsDefunct())
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
+ PRBool isOnclick = nsAccUtils::HasListener(content,
+ NS_LITERAL_STRING("click"));
+
+ if (isOnclick)
+ return DoCommand(content);
+
+ return NS_ERROR_INVALID_ARG;
}
/* DOMString getHelp (); */
NS_IMETHODIMP nsAccessible::GetHelp(nsAString& _retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -125,23 +125,16 @@ public:
NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
/**
* Returns attributes for accessible without explicitly setted ARIA
* attributes.
*/
virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
- /**
- * Maps ARIA state attributes to state of accessible. Note the given state
- * argument should hold states for accessible before you pass it into this
- * method.
- */
- PRUint32 GetARIAState();
-
#ifdef DEBUG_A11Y
static PRBool IsTextInterfaceSupportCorrect(nsIAccessible *aAccessible);
#endif
static PRBool IsCorrectFrameType(nsIFrame* aFrame, nsIAtom* aAtom);
static PRUint32 State(nsIAccessible *aAcc) { PRUint32 state = 0; if (aAcc) aAcc->GetFinalState(&state, nsnull); return state; }
static PRUint32 Role(nsIAccessible *aAcc) { PRUint32 role = nsIAccessibleRole::ROLE_NOTHING; if (aAcc) aAcc->GetFinalRole(&role); return role; }
static PRBool IsText(nsIAccessible *aAcc) { PRUint32 role = Role(aAcc); return role == nsIAccessibleRole::ROLE_TEXT_LEAF || role == nsIAccessibleRole::ROLE_STATICTEXT; }
--- a/accessible/src/base/nsAccessibleEventData.cpp
+++ b/accessible/src/base/nsAccessibleEventData.cpp
@@ -52,28 +52,28 @@
#include "nsIAccessibleText.h"
#include "nsIContent.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
PRBool nsAccEvent::gLastEventFromUserInput = PR_FALSE;
nsIDOMNode* nsAccEvent::gLastEventNodeWeak = 0;
-NS_IMPL_ISUPPORTS1(nsAccEvent, nsIAccessibleEvent)
+NS_IMPL_ISUPPORTS2(nsAccEvent, nsAccEvent, nsIAccessibleEvent)
nsAccEvent::nsAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible,
- PRBool aIsAsynch):
- mEventType(aEventType), mAccessible(aAccessible)
+ PRBool aIsAsynch, EEventRule aEventRule):
+ mEventType(aEventType), mAccessible(aAccessible), mEventRule(aEventRule)
{
CaptureIsFromUserInput(aIsAsynch);
}
nsAccEvent::nsAccEvent(PRUint32 aEventType, nsIDOMNode *aDOMNode,
- PRBool aIsAsynch):
- mEventType(aEventType), mDOMNode(aDOMNode)
+ PRBool aIsAsynch, EEventRule aEventRule):
+ mEventType(aEventType), mDOMNode(aDOMNode), mEventRule(aEventRule)
{
CaptureIsFromUserInput(aIsAsynch);
}
void nsAccEvent::GetLastEventAttributes(nsIDOMNode *aNode,
nsIPersistentProperties *aAttributes)
{
if (aNode == gLastEventNodeWeak) {
@@ -277,16 +277,104 @@ nsAccEvent::GetAccessibleByNode()
}
}
}
#endif
return accessible;
}
+/* static */
+void
+nsAccEvent::ApplyEventRules(nsCOMArray<nsIAccessibleEvent> &aEventsToFire)
+{
+ PRUint32 numQueuedEvents = aEventsToFire.Count();
+ for (PRInt32 tail = numQueuedEvents - 1; tail >= 0; tail --) {
+ nsRefPtr<nsAccEvent> tailEvent = GetAccEventPtr(aEventsToFire[tail]);
+ switch(tailEvent->mEventRule) {
+ case nsAccEvent::eCoalesceFromSameSubtree:
+ {
+ for (PRInt32 index = 0; index < tail; index ++) {
+ nsRefPtr<nsAccEvent> thisEvent = GetAccEventPtr(aEventsToFire[index]);
+ if (thisEvent->mEventType != tailEvent->mEventType)
+ continue; // Different type
+
+ if (thisEvent->mEventRule == nsAccEvent::eAllowDupes ||
+ thisEvent->mEventRule == nsAccEvent::eDoNotEmit)
+ continue; // Do not need to check
+
+ if (thisEvent->mDOMNode == tailEvent->mDOMNode) {
+ // Dupe
+ thisEvent->mEventRule = nsAccEvent::eDoNotEmit;
+ continue;
+ }
+ if (nsAccUtils::IsAncestorOf(tailEvent->mDOMNode,
+ thisEvent->mDOMNode)) {
+ // thisDOMNode is a descendant of tailDOMNode
+ // Do not emit thisEvent, also apply this result to sibling
+ // nodes of thisDOMNode.
+ thisEvent->mEventRule = nsAccEvent::eDoNotEmit;
+ ApplyToSiblings(aEventsToFire, 0, index, thisEvent->mEventType,
+ thisEvent->mDOMNode, nsAccEvent::eDoNotEmit);
+ continue;
+ }
+ if (nsAccUtils::IsAncestorOf(thisEvent->mDOMNode,
+ tailEvent->mDOMNode)) {
+ // tailDOMNode is a descendant of thisDOMNode
+ // Do not emit tailEvent, also apply this result to sibling
+ // nodes of tailDOMNode.
+ tailEvent->mEventRule = nsAccEvent::eDoNotEmit;
+ ApplyToSiblings(aEventsToFire, 0, tail, tailEvent->mEventType,
+ tailEvent->mDOMNode, nsAccEvent::eDoNotEmit);
+ break;
+ }
+ } // for (index)
+
+ if (tailEvent->mEventRule != nsAccEvent::eDoNotEmit) {
+ // Not in another event node's subtree, and no other event is in
+ // this event node's subtree.
+ // This event should be emitted
+ // Apply this result to sibling nodes of tailDOMNode
+ ApplyToSiblings(aEventsToFire, 0, tail, tailEvent->mEventType,
+ tailEvent->mDOMNode, nsAccEvent::eAllowDupes);
+ }
+ } break; // case eCoalesceFromSameSubtree
+
+ case nsAccEvent::eRemoveDupes:
+ {
+ // Check for repeat events.
+ for (PRInt32 index = 0; index < tail; index ++) {
+ nsRefPtr<nsAccEvent> accEvent = GetAccEventPtr(aEventsToFire[index]);
+ if (accEvent->mEventType == tailEvent->mEventType &&
+ accEvent->mEventRule == tailEvent->mEventRule &&
+ accEvent->mDOMNode == tailEvent->mDOMNode) {
+ accEvent->mEventRule = nsAccEvent::eDoNotEmit;
+ }
+ }
+ } break; // case eRemoveDupes
+ } // switch
+ } // for (tail)
+}
+
+/* static */
+void
+nsAccEvent::ApplyToSiblings(nsCOMArray<nsIAccessibleEvent> &aEventsToFire,
+ PRUint32 aStart, PRUint32 aEnd,
+ PRUint32 aEventType, nsIDOMNode* aDOMNode,
+ EEventRule aEventRule)
+{
+ for (PRUint32 index = aStart; index < aEnd; index ++) {
+ nsRefPtr<nsAccEvent> accEvent = GetAccEventPtr(aEventsToFire[index]);
+ if (accEvent->mEventType == aEventType &&
+ accEvent->mEventRule != nsAccEvent::eDoNotEmit &&
+ nsAccUtils::AreSiblings(accEvent->mDOMNode, aDOMNode)) {
+ accEvent->mEventRule = aEventRule;
+ }
+ }
+}
// nsAccStateChangeEvent
NS_IMPL_ISUPPORTS_INHERITED1(nsAccStateChangeEvent, nsAccEvent,
nsIAccessibleStateChangeEvent)
nsAccStateChangeEvent::
nsAccStateChangeEvent(nsIAccessible *aAccessible,
PRUint32 aState, PRBool aIsExtraState,
--- a/accessible/src/base/nsAccessibleEventData.h
+++ b/accessible/src/base/nsAccessibleEventData.h
@@ -36,56 +36,106 @@
* 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 _nsAccessibleEventData_H_
#define _nsAccessibleEventData_H_
+#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
+#include "nsCOMArray.h"
#include "nsIAccessibleEvent.h"
#include "nsIAccessible.h"
#include "nsIAccessibleDocument.h"
#include "nsIDOMNode.h"
#include "nsString.h"
class nsIPresShell;
+#define NS_ACCEVENT_IMPL_CID \
+{ /* 55b89892-a83d-4252-ba78-cbdf53a86936 */ \
+ 0x55b89892, \
+ 0xa83d, \
+ 0x4252, \
+ { 0xba, 0x78, 0xcb, 0xdf, 0x53, 0xa8, 0x69, 0x36 } \
+}
+
class nsAccEvent: public nsIAccessibleEvent
{
public:
+
+ // Rule for accessible events.
+ // The rule will be applied when flushing pending events.
+ enum EEventRule {
+ // eAllowDupes : More than one event of the same type is allowed.
+ // This event will always be emitted.
+ eAllowDupes,
+ // eCoalesceFromSameSubtree : For events of the same type from the same
+ // subtree or the same node, only the umbrelle event on the ancestor
+ // will be emitted.
+ eCoalesceFromSameSubtree,
+ // eRemoveDupes : For repeat events, only the newest event in queue
+ // will be emitted.
+ eRemoveDupes,
+ // eDoNotEmit : This event is confirmed as a duplicate, do not emit it.
+ eDoNotEmit
+ };
+
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCEVENT_IMPL_CID)
+
// Initialize with an nsIAccessible
- nsAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible, PRBool aIsAsynch = PR_FALSE);
+ nsAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible,
+ PRBool aIsAsynch = PR_FALSE,
+ EEventRule aEventRule = eRemoveDupes);
// Initialize with an nsIDOMNode
- nsAccEvent(PRUint32 aEventType, nsIDOMNode *aDOMNode, PRBool aIsAsynch = PR_FALSE);
+ nsAccEvent(PRUint32 aEventType, nsIDOMNode *aDOMNode,
+ PRBool aIsAsynch = PR_FALSE,
+ EEventRule aEventRule = eRemoveDupes);
virtual ~nsAccEvent() {}
NS_DECL_ISUPPORTS
NS_DECL_NSIACCESSIBLEEVENT
static void GetLastEventAttributes(nsIDOMNode *aNode,
nsIPersistentProperties *aAttributes);
protected:
already_AddRefed<nsIAccessible> GetAccessibleByNode();
void CaptureIsFromUserInput(PRBool aIsAsynch);
PRBool mIsFromUserInput;
private:
PRUint32 mEventType;
+ EEventRule mEventRule;
nsCOMPtr<nsIAccessible> mAccessible;
nsCOMPtr<nsIDOMNode> mDOMNode;
nsCOMPtr<nsIAccessibleDocument> mDocAccessible;
static PRBool gLastEventFromUserInput;
static nsIDOMNode* gLastEventNodeWeak;
public:
+ static PRUint32 EventType(nsIAccessibleEvent *aAccEvent) {
+ PRUint32 eventType;
+ aAccEvent->GetEventType(&eventType);
+ return eventType;
+ }
+ static EEventRule EventRule(nsIAccessibleEvent *aAccEvent) {
+ nsRefPtr<nsAccEvent> accEvent = GetAccEventPtr(aAccEvent);
+ return accEvent->mEventRule;
+ }
+ static PRBool IsFromUserInput(nsIAccessibleEvent *aAccEvent) {
+ PRBool isFromUserInput;
+ aAccEvent->GetIsFromUserInput(&isFromUserInput);
+ return isFromUserInput;
+ }
+
static void ResetLastInputState()
{gLastEventFromUserInput = PR_FALSE; gLastEventNodeWeak = nsnull; }
/**
* Find and cache the last input state. This will be called automatically
* for synchronous events. For asynchronous events it should be
* called from the synchronous code which is the true source of the event,
* before the event is fired.
@@ -98,18 +148,51 @@ public:
/**
* The input state was previously stored with the nsIAccessibleEvent,
* so use that state now -- call this when about to flush an event that
* was waiting in an event queue
*/
static void PrepareForEvent(nsIAccessibleEvent *aEvent,
PRBool aForceIsFromUserInput = PR_FALSE);
+
+ /**
+ * Apply event rules to pending events, this method is called in
+ * FlushingPendingEvents().
+ * Result of this method:
+ * Event rule of filtered events will be set to eDoNotEmit.
+ * Events with other event rule are good to emit.
+ */
+ static void ApplyEventRules(nsCOMArray<nsIAccessibleEvent> &aEventsToFire);
+
+private:
+ static already_AddRefed<nsAccEvent> GetAccEventPtr(nsIAccessibleEvent *aAccEvent) {
+ nsAccEvent* accEvent = nsnull;
+ aAccEvent->QueryInterface(NS_GET_IID(nsAccEvent), (void**)&accEvent);
+ return accEvent;
+ }
+
+ /**
+ * Apply aEventRule to same type event that from sibling nodes of aDOMNode.
+ * @param aEventsToFire array of pending events
+ * @param aStart start index of pending events to be scanned
+ * @param aEnd end index to be scanned (not included)
+ * @param aEventType target event type
+ * @param aDOMNode target are siblings of this node
+ * @param aEventRule the event rule to be applied
+ * (should be eDoNotEmit or eAllowDupes)
+ */
+ static void ApplyToSiblings(nsCOMArray<nsIAccessibleEvent> &aEventsToFire,
+ PRUint32 aStart, PRUint32 aEnd,
+ PRUint32 aEventType, nsIDOMNode* aDOMNode,
+ EEventRule aEventRule);
};
+NS_DEFINE_STATIC_IID_ACCESSOR(nsAccEvent, NS_ACCEVENT_IMPL_CID)
+
class nsAccStateChangeEvent: public nsAccEvent,
public nsIAccessibleStateChangeEvent
{
public:
nsAccStateChangeEvent(nsIAccessible *aAccessible,
PRUint32 aState, PRBool aIsExtraState,
PRBool aIsEnabled);
--- a/accessible/src/base/nsBaseWidgetAccessible.cpp
+++ b/accessible/src/base/nsBaseWidgetAccessible.cpp
@@ -16,16 +16,17 @@
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* John Gaunt (jgaunt@netscape.com)
+ * Alexander Surkov <surkov.alexander@gmail.com>
*
* 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
@@ -88,211 +89,226 @@ NS_IMETHODIMP nsLeafAccessible::GetChild
/* readonly attribute boolean allowsAnonChildAccessibles; */
NS_IMETHODIMP
nsLeafAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
{
*aAllowsAnonChildren = PR_FALSE;
return NS_OK;
}
-//----------------
+////////////////////////////////////////////////////////////////////////////////
// nsLinkableAccessible
-//----------------
-nsLinkableAccessible::nsLinkableAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell) :
+nsLinkableAccessible::
+ nsLinkableAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell) :
nsHyperTextAccessibleWrap(aNode, aShell),
mActionContent(nsnull),
mIsLink(PR_FALSE),
mIsOnclick(PR_FALSE)
{
}
NS_IMPL_ISUPPORTS_INHERITED0(nsLinkableAccessible, nsHyperTextAccessibleWrap)
-NS_IMETHODIMP nsLinkableAccessible::TakeFocus()
-{
- if (mActionContent && mActionContent->IsFocusable()) {
- nsCOMPtr<nsIDOMNSHTMLElement> htmlElement(do_QueryInterface(mActionContent));
- if (htmlElement) {
- // HTML Elements also set the caret position
- // in order to affect tabbing order
- return htmlElement->Focus();
- }
- NS_WARNING("Has action content that is not an HTML element");
- }
-
+////////////////////////////////////////////////////////////////////////////////
+// nsLinkableAccessible. nsIAccessible
+
+NS_IMETHODIMP
+nsLinkableAccessible::TakeFocus()
+{
+ nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
+ if (actionAcc)
+ return actionAcc->TakeFocus();
+
return NS_OK;
}
-/* long GetState (); */
NS_IMETHODIMP
nsLinkableAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
{
nsresult rv = nsHyperTextAccessibleWrap::GetState(aState, aExtraState);
NS_ENSURE_SUCCESS(rv, rv);
- if (!mDOMNode)
- return NS_OK;
if (mIsLink) {
*aState |= nsIAccessibleStates::STATE_LINKED;
- nsCOMPtr<nsILink> link = do_QueryInterface(mActionContent);
- if (link) {
- nsLinkState linkState;
- link->GetLinkState(linkState);
- if (linkState == eLinkState_Visited) {
- *aState |= nsIAccessibleStates::STATE_TRAVERSED;
- }
- }
+ nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
+ if (actionAcc && (State(actionAcc) & nsIAccessibleStates::STATE_TRAVERSED))
+ *aState |= nsIAccessibleStates::STATE_TRAVERSED;
}
return NS_OK;
}
-NS_IMETHODIMP nsLinkableAccessible::GetValue(nsAString& aValue)
+NS_IMETHODIMP
+nsLinkableAccessible::GetValue(nsAString& aValue)
{
aValue.Truncate();
+
nsHyperTextAccessible::GetValue(aValue);
if (!aValue.IsEmpty())
return NS_OK;
if (mIsLink) {
- nsCOMPtr<nsIDOMNode> linkNode(do_QueryInterface(mActionContent));
- nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
- if (linkNode && presShell)
- return presShell->GetLinkLocation(linkNode, aValue);
+ nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
+ if (actionAcc)
+ return actionAcc->GetValue(aValue);
}
+
return NS_ERROR_NOT_IMPLEMENTED;
}
-/* PRUint8 getAccNumActions (); */
-NS_IMETHODIMP nsLinkableAccessible::GetNumActions(PRUint8 *aNumActions)
+NS_IMETHODIMP
+nsLinkableAccessible::GetNumActions(PRUint8 *aNumActions)
{
+ NS_ENSURE_ARG_POINTER(aNumActions);
+
*aNumActions = mActionContent ? 1 : 0;
return NS_OK;
}
-/* nsAString GetActionName (in PRUint8 Aindex); */
-NS_IMETHODIMP nsLinkableAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
+NS_IMETHODIMP
+nsLinkableAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
{
+ aName.Truncate();
+
// Action 0 (default action): Jump to link
- aName.Truncate();
if (aIndex == eAction_Jump) {
if (mIsLink) {
aName.AssignLiteral("jump");
return NS_OK;
}
else if (mIsOnclick) {
aName.AssignLiteral("click");
return NS_OK;
}
return NS_ERROR_NOT_IMPLEMENTED;
}
return NS_ERROR_INVALID_ARG;
}
-/* void accDoAction (in PRUint8 index); */
-NS_IMETHODIMP nsLinkableAccessible::DoAction(PRUint8 index)
+NS_IMETHODIMP
+nsLinkableAccessible::DoAction(PRUint8 aIndex)
{
- // Action 0 (default action): Jump to link
- if (index == eAction_Jump) {
- if (mActionContent) {
- return DoCommand(mActionContent);
- }
- }
+ nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
+ if (actionAcc)
+ return actionAcc->DoAction(aIndex);
+
return NS_ERROR_INVALID_ARG;
}
-NS_IMETHODIMP nsLinkableAccessible::GetKeyboardShortcut(nsAString& aKeyboardShortcut)
+NS_IMETHODIMP
+nsLinkableAccessible::GetKeyboardShortcut(nsAString& aKeyboardShortcut)
{
- if (mActionContent) {
- nsCOMPtr<nsIDOMNode> actionNode(do_QueryInterface(mActionContent));
- if (actionNode && mDOMNode != actionNode) {
- nsCOMPtr<nsIAccessible> accessible;
- nsCOMPtr<nsIAccessibilityService> accService =
- do_GetService("@mozilla.org/accessibilityService;1");
- accService->GetAccessibleInWeakShell(actionNode, mWeakShell,
- getter_AddRefs(accessible));
- if (accessible) {
- accessible->GetKeyboardShortcut(aKeyboardShortcut);
- }
- return NS_OK;
- }
- }
+ aKeyboardShortcut.Truncate();
+
+ nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
+ if (actionAcc)
+ return actionAcc->GetKeyboardShortcut(aKeyboardShortcut);
+
return nsAccessible::GetKeyboardShortcut(aKeyboardShortcut);
}
-void nsLinkableAccessible::CacheActionContent()
+////////////////////////////////////////////////////////////////////////////////
+// nsLinkableAccessible. nsIAccessibleHyperLink
+
+NS_IMETHODIMP
+nsLinkableAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI)
{
- for (nsCOMPtr<nsIContent> walkUpContent(do_QueryInterface(mDOMNode));
- walkUpContent;
- walkUpContent = walkUpContent->GetParent()) {
- PRBool isOnclick = nsAccUtils::HasListener(walkUpContent, NS_LITERAL_STRING("click"));
- nsIAtom *tag = walkUpContent->Tag();
- if ((tag == nsAccessibilityAtoms::a || tag == nsAccessibilityAtoms::area) &&
- walkUpContent->IsNodeOfType(nsINode::eHTML)) {
- nsCOMPtr<nsILink> link = do_QueryInterface(walkUpContent);
- if (link) {
- // Currently we do not expose <link> tags, because they are not typically
- // in <body> and rendered.
- // We do not yet support xlinks
- nsCOMPtr<nsIURI> uri;
- link->GetHrefURI(getter_AddRefs(uri));
- if (uri) {
- mActionContent = walkUpContent;
- mIsLink = PR_TRUE;
- break;
- }
- }
- if (SameCOMIdentity(mDOMNode, walkUpContent)) {
- // This is the element that caused the creation of a linkable accessible
- // Don't let it keep walking up, otherwise we may report the wrong container
- // as the action node
- mActionContent = walkUpContent;
- mIsOnclick = isOnclick;
- break;
- }
- }
- if (isOnclick) {
- mActionContent = walkUpContent;
- mIsOnclick = PR_TRUE;
- break;
+ if (mIsLink) {
+ nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
+ if (actionAcc) {
+ nsCOMPtr<nsIAccessibleHyperLink> hyperLinkAcc =
+ do_QueryInterface(actionAcc);
+ NS_ASSERTION(hyperLinkAcc,
+ "nsIAccessibleHyperLink isn't implemented.");
+
+ if (hyperLinkAcc)
+ return hyperLinkAcc->GetURI(aIndex, aURI);
}
}
+
+ return NS_ERROR_INVALID_ARG;
}
-// nsIAccessibleHyperLink::GetURI()
-NS_IMETHODIMP nsLinkableAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI)
-{
- // XXX Also implement this for nsHTMLImageAccessible file names
- *aURI = nsnull;
- if (aIndex != 0 || !mIsLink || !SameCOMIdentity(mDOMNode, mActionContent)) {
- return NS_ERROR_FAILURE;
- }
+////////////////////////////////////////////////////////////////////////////////
+// nsLinkableAccessible. nsPIAccessNode
- nsCOMPtr<nsILink> link(do_QueryInterface(mActionContent));
- if (link) {
- return link->GetHrefURI(aURI);
- }
-
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP nsLinkableAccessible::Init()
+NS_IMETHODIMP
+nsLinkableAccessible::Init()
{
CacheActionContent();
return nsHyperTextAccessibleWrap::Init();
}
-NS_IMETHODIMP nsLinkableAccessible::Shutdown()
+NS_IMETHODIMP
+nsLinkableAccessible::Shutdown()
{
mActionContent = nsnull;
return nsHyperTextAccessibleWrap::Shutdown();
}
+////////////////////////////////////////////////////////////////////////////////
+// nsLinkableAccessible
+
+void
+nsLinkableAccessible::CacheActionContent()
+{
+ nsCOMPtr<nsIContent> walkUpContent(do_QueryInterface(mDOMNode));
+ PRBool isOnclick = nsAccUtils::HasListener(walkUpContent,
+ NS_LITERAL_STRING("click"));
+
+ if (isOnclick) {
+ mActionContent = walkUpContent;
+ mIsOnclick = PR_TRUE;
+ return;
+ }
+
+ while ((walkUpContent = walkUpContent->GetParent())) {
+ isOnclick = nsAccUtils::HasListener(walkUpContent,
+ NS_LITERAL_STRING("click"));
+
+ nsCOMPtr<nsIDOMNode> walkUpNode(do_QueryInterface(walkUpContent));
+
+ nsCOMPtr<nsIAccessible> walkUpAcc;
+ GetAccService()->GetAccessibleInWeakShell(walkUpNode, mWeakShell,
+ getter_AddRefs(walkUpAcc));
+
+ if (walkUpAcc && Role(walkUpAcc) == nsIAccessibleRole::ROLE_LINK &&
+ (State(walkUpAcc) & nsIAccessibleStates::STATE_LINKED)) {
+ mIsLink = PR_TRUE;
+ mActionContent = walkUpContent;
+ return;
+ }
+
+ if (isOnclick) {
+ mActionContent = walkUpContent;
+ mIsOnclick = PR_TRUE;
+ return;
+ }
+ }
+}
+
+already_AddRefed<nsIAccessible>
+nsLinkableAccessible::GetActionAccessible()
+{
+ // Return accessible for the action content if it's different from node of
+ // this accessible. If the action accessible is not null then it is used to
+ // redirect methods calls otherwise we use method implementation from the
+ // base class.
+ nsCOMPtr<nsIDOMNode> actionNode(do_QueryInterface(mActionContent));
+ if (!actionNode || mDOMNode == actionNode)
+ return nsnull;
+
+ nsIAccessible *accessible = nsnull;
+ GetAccService()->GetAccessibleInWeakShell(actionNode, mWeakShell,
+ &accessible);
+ return accessible;
+}
+
//---------------------
// nsEnumRoleAccessible
//---------------------
nsEnumRoleAccessible::nsEnumRoleAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell, PRUint32 aRole) :
nsAccessibleWrap(aNode, aShell),
mRole(aRole)
{
--- a/accessible/src/base/nsBaseWidgetAccessible.h
+++ b/accessible/src/base/nsBaseWidgetAccessible.h
@@ -73,30 +73,46 @@ public:
* and can activate ( click ) the link programmatically.
*/
class nsLinkableAccessible : public nsHyperTextAccessibleWrap
{
public:
enum { eAction_Jump = 0 };
nsLinkableAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
+
NS_DECL_ISUPPORTS_INHERITED
+
+ // nsIAccessible
NS_IMETHOD GetNumActions(PRUint8 *_retval);
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
NS_IMETHOD DoAction(PRUint8 index);
NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
NS_IMETHOD GetValue(nsAString& _retval);
NS_IMETHOD TakeFocus();
NS_IMETHOD GetKeyboardShortcut(nsAString& _retval);
+
+ // nsIHyperLinkAccessible
NS_IMETHOD GetURI(PRInt32 i, nsIURI **aURI);
+
+ // nsPIAccessNode
NS_IMETHOD Init();
NS_IMETHOD Shutdown();
protected:
+ /**
+ * Return an accessible for cached action node.
+ */
+ already_AddRefed<nsIAccessible> GetActionAccessible();
+
+ /**
+ * Cache action node.
+ */
virtual void CacheActionContent();
+
nsCOMPtr<nsIContent> mActionContent;
PRPackedBool mIsLink;
PRPackedBool mIsOnclick;
};
/**
* A simple accessible that gets its enumerated role passed into constructor.
*/
--- a/accessible/src/base/nsCaretAccessible.cpp
+++ b/accessible/src/base/nsCaretAccessible.cpp
@@ -239,17 +239,17 @@ NS_IMETHODIMP nsCaretAccessible::NotifyS
}
mLastCaretOffset = caretOffset;
mLastTextAccessible = textAcc;
nsCOMPtr<nsIAccessibleCaretMoveEvent> event =
new nsAccCaretMoveEvent(focusNode);
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
- return mRootAccessible->FireDelayedAccessibleEvent(event, nsDocAccessible::eRemoveDupes);
+ return mRootAccessible->FireDelayedAccessibleEvent(event);
}
nsRect
nsCaretAccessible::GetCaretRect(nsIWidget **aOutWidget)
{
nsRect caretRect;
NS_ENSURE_TRUE(aOutWidget, caretRect);
*aOutWidget = nsnull;
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -147,24 +147,24 @@ NS_INTERFACE_MAP_END_INHERITING(nsHyperT
NS_IMPL_ADDREF_INHERITED(nsDocAccessible, nsHyperTextAccessible)
NS_IMPL_RELEASE_INHERITED(nsDocAccessible, nsHyperTextAccessible)
NS_IMETHODIMP nsDocAccessible::GetName(nsAString& aName)
{
nsresult rv = NS_OK;
aName.Truncate();
- if (mRoleMapEntry) {
- rv = nsAccessible::GetName(aName);
+ if (mParent) {
+ rv = mParent->GetName(aName); // Allow owning iframe to override the name
}
if (aName.IsEmpty()) {
- rv = GetTitle(aName);
+ rv = nsAccessible::GetName(aName); // Allow name via aria-labelledby or title attribute
}
- if (aName.IsEmpty() && mParent) {
- rv = mParent->GetName(aName);
+ if (aName.IsEmpty()) {
+ rv = GetTitle(aName); // Finally try title element
}
return rv;
}
NS_IMETHODIMP nsDocAccessible::GetRole(PRUint32 *aRole)
{
*aRole = nsIAccessibleRole::ROLE_PANE; // Fall back
@@ -197,27 +197,48 @@ NS_IMETHODIMP nsDocAccessible::GetRole(P
else if (itemType == nsIDocShellTreeItem::typeContent) {
*aRole = nsIAccessibleRole::ROLE_DOCUMENT;
}
}
return NS_OK;
}
-NS_IMETHODIMP nsDocAccessible::GetValue(nsAString& aValue)
+NS_IMETHODIMP nsDocAccessible::SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry)
{
- return GetURL(aValue);
+ NS_ENSURE_STATE(mDocument);
+
+ mRoleMapEntry = aRoleMapEntry;
+
+ // Allow use of ARIA role from outer to override
+ nsIDocument *parentDoc = mDocument->GetParentDocument();
+ NS_ENSURE_TRUE(parentDoc, NS_ERROR_FAILURE);
+ nsIContent *ownerContent = parentDoc->FindContentForSubDocument(mDocument);
+ nsCOMPtr<nsIDOMNode> ownerNode(do_QueryInterface(ownerContent));
+ if (ownerNode) {
+ nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(ownerNode);
+ if (roleMapEntry)
+ mRoleMapEntry = roleMapEntry; // Override
+ }
+
+ return NS_OK;
}
NS_IMETHODIMP
nsDocAccessible::GetDescription(nsAString& aDescription)
{
- nsAutoString description;
- GetTextFromRelationID(nsAccessibilityAtoms::aria_describedby, description);
- aDescription = description;
+ if (mParent)
+ mParent->GetDescription(aDescription);
+
+ if (aDescription.IsEmpty()) {
+ nsAutoString description;
+ GetTextFromRelationID(nsAccessibilityAtoms::aria_describedby, description);
+ aDescription = description;
+ }
+
return NS_OK;
}
NS_IMETHODIMP
nsDocAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
{
// nsAccessible::GetState() always fail for document accessible.
nsAccessible::GetState(aState, aExtraState);
@@ -260,16 +281,41 @@ nsDocAccessible::GetState(PRUint32 *aSta
}
else if (aExtraState) {
*aExtraState |= nsIAccessibleStates::EXT_STATE_EDITABLE;
}
return NS_OK;
}
+NS_IMETHODIMP
+nsDocAccessible::GetARIAState(PRUint32 *aState)
+{
+ // Combine with states from outer doc
+ NS_ENSURE_ARG_POINTER(aState);
+ nsresult rv = nsAccessible::GetARIAState(aState);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsPIAccessible> privateParentAccessible = do_QueryInterface(mParent);
+ if (privateParentAccessible) // Allow iframe/frame etc. to have final state override via ARIA
+ return privateParentAccessible->GetARIAState(aState);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsDocAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+{
+ nsAccessible::GetAttributes(aAttributes);
+ if (mParent) {
+ mParent->GetAttributes(aAttributes); // Add parent attributes (override inner)
+ }
+ return NS_OK;
+}
+
NS_IMETHODIMP nsDocAccessible::GetFocusedChild(nsIAccessible **aFocusedChild)
{
if (!gLastFocusedNode) {
*aFocusedChild = nsnull;
return NS_OK;
}
// Return an accessible for the current global focus, which does not have to
@@ -497,28 +543,20 @@ NS_IMETHODIMP nsDocAccessible::GetParent
}
NS_IMETHODIMP nsDocAccessible::Init()
{
PutCacheEntry(gGlobalDocAccessibleCache, mDocument, this);
AddEventListeners();
- nsresult rv = nsHyperTextAccessibleWrap::Init();
+ nsCOMPtr<nsIAccessible> parentAccessible; // Ensure outer doc mParent accessible
+ GetParent(getter_AddRefs(parentAccessible));
- if (mRoleMapEntry && mRoleMapEntry->role != nsIAccessibleRole::ROLE_DIALOG &&
- mRoleMapEntry->role != nsIAccessibleRole::ROLE_APPLICATION &&
- mRoleMapEntry->role != nsIAccessibleRole::ROLE_ALERT &&
- mRoleMapEntry->role != nsIAccessibleRole::ROLE_DOCUMENT) {
- // Document accessible can only have certain roles
- // This was set in nsAccessible::Init() based on dynamic role attribute
- mRoleMapEntry = nsnull; // role attribute is not valid for a document
- }
-
- return rv;
+ return nsHyperTextAccessibleWrap::Init();
}
NS_IMETHODIMP nsDocAccessible::Shutdown()
{
if (!mWeakShell) {
return NS_OK; // Already shutdown
}
@@ -1021,17 +1059,17 @@ nsDocAccessible::AttributeChangedImpl(ns
// in the wrong namespace or an element that doesn't support it
InvalidateCacheSubtree(aContent, nsIAccessibleEvent::EVENT_DOM_SIGNIFICANT_CHANGE);
return;
}
if (aAttribute == nsAccessibilityAtoms::alt ||
aAttribute == nsAccessibilityAtoms::title) {
FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE,
- targetNode, eRemoveDupes);
+ targetNode);
return;
}
if (aAttribute == nsAccessibilityAtoms::selected ||
aAttribute == nsAccessibilityAtoms::aria_selected) {
// ARIA or XUL selection
nsCOMPtr<nsIAccessible> multiSelect = GetMultiSelectFor(targetNode);
// Multi selects use selection_add and selection_remove
@@ -1043,17 +1081,18 @@ nsDocAccessible::AttributeChangedImpl(ns
// Need to find the right event to use here, SELECTION_WITHIN would
// seem right but we had started using it for something else
nsCOMPtr<nsIAccessNode> multiSelectAccessNode =
do_QueryInterface(multiSelect);
nsCOMPtr<nsIDOMNode> multiSelectDOMNode;
multiSelectAccessNode->GetDOMNode(getter_AddRefs(multiSelectDOMNode));
NS_ASSERTION(multiSelectDOMNode, "A new accessible without a DOM node!");
FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_SELECTION_WITHIN,
- multiSelectDOMNode, eAllowDupes);
+ multiSelectDOMNode,
+ nsAccEvent::eAllowDupes);
static nsIContent::AttrValuesArray strings[] =
{&nsAccessibilityAtoms::_empty, &nsAccessibilityAtoms::_false, nsnull};
if (aContent->FindAttrValueIn(kNameSpaceID_None, aAttribute,
strings, eCaseMatters) >= 0) {
FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_SELECTION_REMOVE,
targetNode);
return;
@@ -1098,17 +1137,17 @@ nsDocAccessible::ARIAAttributeChanged(ns
FireDelayedAccessibleEvent(event);
return;
}
if (aAttribute == nsAccessibilityAtoms::aria_activedescendant) {
// The activedescendant universal property redirects accessible focus events
// to the element with the id that activedescendant points to
nsCOMPtr<nsIDOMNode> currentFocus = GetCurrentFocus();
- if (currentFocus == targetNode) {
+ if (SameCOMIdentity(GetRoleContent(currentFocus), targetNode)) {
nsRefPtr<nsRootAccessible> rootAcc = GetRootAccessible();
if (rootAcc)
rootAcc->FireAccessibleFocusEvent(nsnull, currentFocus, nsnull, PR_TRUE);
}
return;
}
if (!aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::role)) {
@@ -1254,16 +1293,29 @@ nsDocAccessible::ContentRemoved(nsIDocum
}
void
nsDocAccessible::ParentChainChanged(nsIContent *aContent)
{
}
void
+nsDocAccessible::FireValueChangeForTextFields(nsIAccessible *aPossibleTextFieldAccessible)
+{
+ if (Role(aPossibleTextFieldAccessible) != nsIAccessibleRole::ROLE_ENTRY)
+ return;
+
+ // Dependent value change event for text changes in textfields
+ nsCOMPtr<nsIAccessibleEvent> valueChangeEvent =
+ new nsAccEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aPossibleTextFieldAccessible,
+ PR_FALSE, nsAccEvent::eRemoveDupes);
+ FireDelayedAccessibleEvent(valueChangeEvent );
+}
+
+void
nsDocAccessible::FireTextChangeEventForText(nsIContent *aContent,
CharacterDataChangeInfo* aInfo,
PRBool aIsInserted)
{
if (!mIsContentLoaded || !mDocument) {
return;
}
@@ -1313,16 +1365,18 @@ nsDocAccessible::FireTextChangeEventForT
if (NS_FAILED(rv))
return;
nsCOMPtr<nsIAccessibleTextChangeEvent> event =
new nsAccTextChangeEvent(accessible, offset,
renderedEndOffset - renderedStartOffset,
aIsInserted, PR_FALSE);
textAccessible->FireAccessibleEvent(event);
+
+ FireValueChangeForTextFields(accessible);
}
}
already_AddRefed<nsIAccessibleTextChangeEvent>
nsDocAccessible::CreateTextChangeEventForNode(nsIAccessible *aContainerAccessible,
nsIDOMNode *aChangeNode,
nsIAccessible *aAccessibleForChangeNode,
PRBool aIsInserting,
@@ -1394,103 +1448,39 @@ nsDocAccessible::CreateTextChangeEventFo
new nsAccTextChangeEvent(aContainerAccessible, offset, length, aIsInserting, aIsAsynch);
NS_IF_ADDREF(event);
return event;
}
nsresult nsDocAccessible::FireDelayedToolkitEvent(PRUint32 aEvent,
nsIDOMNode *aDOMNode,
- EDupeEventRule aAllowDupes,
+ nsAccEvent::EEventRule aAllowDupes,
PRBool aIsAsynch)
{
nsCOMPtr<nsIAccessibleEvent> event =
- new nsAccEvent(aEvent, aDOMNode, aIsAsynch);
+ new nsAccEvent(aEvent, aDOMNode, aIsAsynch, aAllowDupes);
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
- return FireDelayedAccessibleEvent(event, aAllowDupes);
+ return FireDelayedAccessibleEvent(event);
}
nsresult
-nsDocAccessible::FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent,
- EDupeEventRule aAllowDupes)
+nsDocAccessible::FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent)
{
NS_ENSURE_TRUE(aEvent, NS_ERROR_FAILURE);
- PRBool isTimerStarted = PR_TRUE;
- PRInt32 numQueuedEvents = mEventsToFire.Count();
if (!mFireEventTimer) {
// Do not yet have a timer going for firing another event.
mFireEventTimer = do_CreateInstance("@mozilla.org/timer;1");
NS_ENSURE_TRUE(mFireEventTimer, NS_ERROR_OUT_OF_MEMORY);
}
- PRUint32 newEventType;
- aEvent->GetEventType(&newEventType);
-
- nsCOMPtr<nsIDOMNode> newEventDOMNode;
- aEvent->GetDOMNode(getter_AddRefs(newEventDOMNode));
-
- if (numQueuedEvents == 0) {
- isTimerStarted = PR_FALSE;
- } else if (aAllowDupes == eCoalesceFromSameSubtree) {
- // Especially for mutation events, we will define a duplicate event
- // as one on the same node or on a descendant node.
- // This prevents a flood of events when a subtree is changed.
- for (PRInt32 index = 0; index < numQueuedEvents; index ++) {
- nsIAccessibleEvent *accessibleEvent = mEventsToFire[index];
- NS_ASSERTION(accessibleEvent, "Array item is not an accessible event");
- if (!accessibleEvent) {
- continue;
- }
- PRUint32 eventType;
- accessibleEvent->GetEventType(&eventType);
- if (eventType == newEventType) {
- nsCOMPtr<nsIDOMNode> domNode;
- accessibleEvent->GetDOMNode(getter_AddRefs(domNode));
- if (newEventDOMNode == domNode || nsAccUtils::IsAncestorOf(newEventDOMNode, domNode)) {
- mEventsToFire.RemoveObjectAt(index);
- // The other event is the same type, but in a descendant of this
- // event, so remove that one. The umbrella event in the ancestor
- // is already enough
- -- index;
- -- numQueuedEvents;
- }
- else if (nsAccUtils::IsAncestorOf(domNode, newEventDOMNode)) {
- // There is a better SHOW/HIDE event (it's in an ancestor)
- return NS_OK;
- }
- }
- }
- } else if (aAllowDupes == eRemoveDupes) {
- // Check for repeat events. If a redundant event exists remove
- // original and put the new event at the end of the queue
- // so it is fired after the others
- for (PRInt32 index = 0; index < numQueuedEvents; index ++) {
- nsIAccessibleEvent *accessibleEvent = mEventsToFire[index];
- NS_ASSERTION(accessibleEvent, "Array item is not an accessible event");
- if (!accessibleEvent) {
- continue;
- }
- PRUint32 eventType;
- accessibleEvent->GetEventType(&eventType);
- if (eventType == newEventType) {
- nsCOMPtr<nsIDOMNode> domNode;
- accessibleEvent->GetDOMNode(getter_AddRefs(domNode));
- if (domNode == newEventDOMNode) {
- mEventsToFire.RemoveObjectAt(index);
- -- index;
- -- numQueuedEvents;
- }
- }
- }
- }
-
mEventsToFire.AppendObject(aEvent);
- if (!isTimerStarted) {
+ if (mEventsToFire.Count() == 1) {
// This is be the first delayed event in queue, start timer
// so that event gets fired via FlushEventsCallback
NS_ADDREF_THIS(); // Kung fu death grip to prevent crash in callback
mFireEventTimer->InitWithFuncCallback(FlushEventsCallback,
static_cast<nsPIAccessibleDocument*>(this),
0, nsITimer::TYPE_ONE_SHOT);
}
@@ -1499,30 +1489,32 @@ nsDocAccessible::FireDelayedAccessibleEv
NS_IMETHODIMP nsDocAccessible::FlushPendingEvents()
{
PRUint32 length = mEventsToFire.Count();
NS_ASSERTION(length, "How did we get here without events to fire?");
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
if (!presShell)
length = 0; // The doc is now shut down, don't fire events in it anymore
- PRUint32 index;
- for (index = 0; index < length; index ++) {
+ else
+ nsAccEvent::ApplyEventRules(mEventsToFire);
+
+ for (PRUint32 index = 0; index < length; index ++) {
nsCOMPtr<nsIAccessibleEvent> accessibleEvent(
do_QueryInterface(mEventsToFire[index]));
- NS_ASSERTION(accessibleEvent, "Array item is not an accessible event");
+
+ if (nsAccEvent::EventRule(accessibleEvent) == nsAccEvent::eDoNotEmit)
+ continue;
nsCOMPtr<nsIAccessible> accessible;
accessibleEvent->GetAccessible(getter_AddRefs(accessible));
nsCOMPtr<nsIDOMNode> domNode;
accessibleEvent->GetDOMNode(getter_AddRefs(domNode));
- PRUint32 eventType;
- accessibleEvent->GetEventType(&eventType);
- PRBool isFromUserInput;
- accessibleEvent->GetIsFromUserInput(&isFromUserInput);
+ PRUint32 eventType = nsAccEvent::EventType(accessibleEvent);
+ PRBool isFromUserInput = nsAccEvent::IsFromUserInput(accessibleEvent);
if (domNode == gLastFocusedNode &&
eventType == nsIAccessibleEvent::EVENT_ASYNCH_HIDE ||
eventType == nsIAccessibleEvent::EVENT_ASYNCH_SHOW) {
// If frame type didn't change for this event, then we don't actually need to invalidate
// However, we only keep track of the old frame type for the focus, where it's very
// important not to destroy and recreate the accessible for minor style changes,
// such as a:focus { overflow: scroll; }
@@ -1935,53 +1927,58 @@ NS_IMETHODIMP nsDocAccessible::Invalidat
// Fire EVENT_SHOW, EVENT_MENUPOPUP_START for newly visible content.
// Fire after a short timer, because we want to make sure the view has been
// updated to make this accessible content visible. If we don't wait,
// the assistive technology may receive the event and then retrieve
// nsIAccessibleStates::STATE_INVISIBLE for the event's accessible object.
PRUint32 additionEvent = isAsynch ? nsIAccessibleEvent::EVENT_ASYNCH_SHOW :
nsIAccessibleEvent::EVENT_DOM_CREATE;
FireDelayedToolkitEvent(additionEvent, childNode,
- eCoalesceFromSameSubtree, isAsynch);
+ nsAccEvent::eCoalesceFromSameSubtree,
+ isAsynch);
// Check to see change occured in an ARIA menu, and fire
// an EVENT_MENUPOPUP_START if it did.
nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(childNode);
if (roleMapEntry && roleMapEntry->role == nsIAccessibleRole::ROLE_MENUPOPUP) {
FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START,
- childNode, eRemoveDupes, isAsynch);
+ childNode, nsAccEvent::eRemoveDupes,
+ isAsynch);
}
// Check to see if change occured inside an alert, and fire an EVENT_ALERT if it did
nsIContent *ancestor = aChild;
while (PR_TRUE) {
if (roleMapEntry && roleMapEntry->role == nsIAccessibleRole::ROLE_ALERT) {
nsCOMPtr<nsIDOMNode> alertNode(do_QueryInterface(ancestor));
FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_ALERT, alertNode,
- eRemoveDupes, isAsynch);
+ nsAccEvent::eRemoveDupes, isAsynch);
break;
}
ancestor = ancestor->GetParent();
nsCOMPtr<nsIDOMNode> ancestorNode = do_QueryInterface(ancestor);
if (!ancestorNode) {
break;
}
roleMapEntry = nsAccUtils::GetRoleMapEntry(ancestorNode);
}
}
+ FireValueChangeForTextFields(containerAccessible);
+
if (!isShowing) {
// Fire an event so the assistive technology knows the children have changed
// This is only used by older MSAA clients. Newer ones should derive this
// from SHOW and HIDE so that they don't fetch extra objects
if (childAccessible) {
nsCOMPtr<nsIAccessibleEvent> reorderEvent =
- new nsAccEvent(nsIAccessibleEvent::EVENT_REORDER, containerAccessible, isAsynch);
+ new nsAccEvent(nsIAccessibleEvent::EVENT_REORDER, containerAccessible,
+ isAsynch, nsAccEvent::eCoalesceFromSameSubtree);
NS_ENSURE_TRUE(reorderEvent, NS_ERROR_OUT_OF_MEMORY);
- FireDelayedAccessibleEvent(reorderEvent, eCoalesceFromSameSubtree);
+ FireDelayedAccessibleEvent(reorderEvent);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocAccessible::GetAccessibleInParentChain(nsIDOMNode *aNode,
@@ -2047,23 +2044,24 @@ nsDocAccessible::FireShowHideEvents(nsID
if (accessible) {
// Found an accessible, so fire the show/hide on it and don't
// look further into this subtree
PRBool isAsynch = aEventType == nsIAccessibleEvent::EVENT_ASYNCH_HIDE ||
aEventType == nsIAccessibleEvent::EVENT_ASYNCH_SHOW;
nsCOMPtr<nsIAccessibleEvent> event =
- new nsAccEvent(aEventType, accessible, isAsynch);
+ new nsAccEvent(aEventType, accessible, isAsynch,
+ nsAccEvent::eCoalesceFromSameSubtree);
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
if (aForceIsFromUserInput) {
nsAccEvent::PrepareForEvent(event, aForceIsFromUserInput);
}
if (aDelay) {
- return FireDelayedAccessibleEvent(event, eCoalesceFromSameSubtree);
+ return FireDelayedAccessibleEvent(event);
}
return FireAccessibleEvent(event);
}
// Could not find accessible to show hide yet, so fire on any
// accessible descendants in this subtree
nsCOMPtr<nsIContent> content(do_QueryInterface(aDOMNode));
PRUint32 count = content->GetChildCount();
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -69,20 +69,22 @@ class nsDocAccessible : public nsHyperTe
NS_DECL_NSPIACCESSIBLEDOCUMENT
NS_DECL_NSIOBSERVER
public:
nsDocAccessible(nsIDOMNode *aNode, nsIWeakReference* aShell);
virtual ~nsDocAccessible();
NS_IMETHOD GetRole(PRUint32 *aRole);
+ NS_IMETHOD SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry);
NS_IMETHOD GetName(nsAString& aName);
- NS_IMETHOD GetValue(nsAString& aValue);
NS_IMETHOD GetDescription(nsAString& aDescription);
+ NS_IMETHOD GetARIAState(PRUint32 *aState);
NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
+ NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
NS_IMETHOD GetParent(nsIAccessible **aParent);
NS_IMETHOD TakeFocus(void);
// ----- nsIScrollPositionListener ---------------------------
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView *aView, nscoord aX, nscoord aY);
NS_IMETHOD ScrollPositionDidChange(nsIScrollableView *aView, nscoord aX, nscoord aY);
@@ -96,46 +98,40 @@ class nsDocAccessible : public nsHyperTe
NS_IMETHOD Init();
// nsPIAccessNode
NS_IMETHOD_(nsIFrame *) GetFrame(void);
// nsIAccessibleText
NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor);
- enum EDupeEventRule { eAllowDupes, eCoalesceFromSameSubtree, eRemoveDupes };
-
/**
* Non-virtual method to fire a delayed event after a 0 length timeout
*
* @param aEvent - the nsIAccessibleEvent event type
* @param aDOMNode - DOM node the accesible event should be fired for
* @param aAllowDupes - eAllowDupes: more than one event of the same type is allowed.
* eCoalesceFromSameSubtree: if two events are in the same subtree,
* only the event on ancestor is used
* eRemoveDupes (default): events of the same type are discarded
* (the last one is used)
*
* @param aIsAsynch - set to PR_TRUE if this is not being called from code
* synchronous with a DOM event
*/
nsresult FireDelayedToolkitEvent(PRUint32 aEvent, nsIDOMNode *aDOMNode,
- EDupeEventRule aAllowDupes = eRemoveDupes,
+ nsAccEvent::EEventRule aAllowDupes = nsAccEvent::eRemoveDupes,
PRBool aIsAsynch = PR_FALSE);
/**
* Fire accessible event in timeout.
*
* @param aEvent - the event to fire
- * @param aAllowDupes - if false then delayed events of the same type and
- * for the same DOM node in the event queue won't
- * be fired.
*/
- nsresult FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent,
- EDupeEventRule aAllowDupes = eRemoveDupes);
+ nsresult FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent);
void ShutdownChildDocuments(nsIDocShellTreeItem *aStart);
protected:
virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
virtual nsresult AddEventListeners();
virtual nsresult RemoveEventListeners();
void AddScrollListener();
@@ -202,16 +198,21 @@ class nsDocAccessible : public nsHyperTe
* @param aEventType event type to fire an event
* @param aAvoidOnThisNode Call with PR_TRUE the first time to prevent event firing on root node for change
* @param aDelay whether to fire the event on a delay
* @param aForceIsFromUserInput the event is known to be from user input
*/
nsresult FireShowHideEvents(nsIDOMNode *aDOMNode, PRBool aAvoidOnThisNode, PRUint32 aEventType,
PRBool aDelay, PRBool aForceIsFromUserInput);
+ /**
+ * If the given accessible object is a ROLE_ENTRY, fire a value change event for it
+ */
+ void FireValueChangeForTextFields(nsIAccessible *aPossibleTextFieldAccessible);
+
nsAccessNodeHashtable mAccessNodeCache;
void *mWnd;
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsITimer> mScrollWatchTimer;
nsCOMPtr<nsITimer> mFireEventTimer;
PRUint16 mScrollPositionChangedTicks; // Used for tracking scroll events
PRPackedBool mIsContentLoaded;
PRPackedBool mIsLoadCompleteFired;
--- a/accessible/src/base/nsOuterDocAccessible.cpp
+++ b/accessible/src/base/nsOuterDocAccessible.cpp
@@ -150,8 +150,20 @@ void nsOuterDocAccessible::CacheChildren
// Success getting inner document as first child -- now we cache it.
mAccChildCount = 1;
SetFirstChild(innerAccessible); // weak ref
privateInnerAccessible->SetParent(this);
privateInnerAccessible->SetNextSibling(nsnull);
}
+nsresult
+nsOuterDocAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
+{
+ nsAutoString tag;
+ aAttributes->GetStringProperty(NS_LITERAL_CSTRING("tag"), tag);
+ if (!tag.IsEmpty()) {
+ // We're overriding the ARIA attributes on an sub document, but we don't want to
+ // override the other attributes
+ return NS_OK;
+ }
+ return nsAccessible::GetAttributesInternal(aAttributes);
+}
--- a/accessible/src/base/nsOuterDocAccessible.h
+++ b/accessible/src/base/nsOuterDocAccessible.h
@@ -53,11 +53,12 @@ class nsOuterDocAccessible : public nsAc
nsIWeakReference* aShell);
NS_IMETHOD GetName(nsAString& aName);
NS_IMETHOD GetRole(PRUint32 *aRole);
NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
NS_IMETHOD GetChildAtPoint(PRInt32 aX, PRInt32 aY,
nsIAccessible **aAccessible);
void CacheChildren();
+ nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
};
#endif
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -403,18 +403,17 @@ void nsRootAccessible::TryFireEarlyLoadE
return;
}
}
nsCOMPtr<nsIDocShellTreeItem> rootContentTreeItem;
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(rootContentTreeItem));
NS_ASSERTION(rootContentTreeItem, "No root content tree item");
if (rootContentTreeItem == treeItem) {
// No frames or iframes, so we can fire the doc load finished event early
- FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_INTERNAL_LOAD, aDocNode,
- eRemoveDupes);
+ FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_INTERNAL_LOAD, aDocNode);
}
}
PRBool nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *aAccessible,
nsIDOMNode *aNode,
nsIDOMEvent *aFocusEvent,
PRBool aForceEvent,
PRBool aIsAsynch)
@@ -443,30 +442,35 @@ PRBool nsRootAccessible::FireAccessibleF
mCaretAccessible->SetControlSelectionListener(realFocusedNode);
}
}
}
// Check for aria-activedescendant, which changes which element has focus
nsCOMPtr<nsIDOMNode> finalFocusNode = aNode;
nsCOMPtr<nsIAccessible> finalFocusAccessible = aAccessible;
- nsCOMPtr<nsIContent> finalFocusContent = do_QueryInterface(aNode);
+ nsCOMPtr<nsIContent> finalFocusContent = GetRoleContent(finalFocusNode);
if (finalFocusContent) {
nsAutoString id;
if (finalFocusContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_activedescendant, id)) {
nsCOMPtr<nsIDOMDocument> domDoc;
aNode->GetOwnerDocument(getter_AddRefs(domDoc));
+ if (!domDoc) { // Maybe the passed-in node actually is a doc
+ domDoc = do_QueryInterface(aNode);
+ }
if (!domDoc) {
return PR_FALSE;
}
nsCOMPtr<nsIDOMElement> relatedEl;
domDoc->GetElementById(id, getter_AddRefs(relatedEl));
finalFocusNode = do_QueryInterface(relatedEl);
if (!finalFocusNode) {
- return PR_FALSE;
+ // If aria-activedescendant is set to nonextistant ID, then treat as focus
+ // on the activedescendant container (which has real DOM focus)
+ finalFocusNode = aNode;
}
finalFocusAccessible = nsnull;
}
}
// Fire focus only if it changes, but always fire focus events when aForceEvent == PR_TRUE
if (gLastFocusedNode == finalFocusNode && !aForceEvent) {
return PR_FALSE;
@@ -498,19 +502,20 @@ PRBool nsRootAccessible::FireAccessibleF
nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_MENU_START, menuBarAccessible);
}
}
}
}
}
else if (mCurrentARIAMenubar) {
nsCOMPtr<nsIAccessibleEvent> menuEndEvent =
- new nsAccEvent(nsIAccessibleEvent::EVENT_MENU_END, mCurrentARIAMenubar, PR_FALSE);
+ new nsAccEvent(nsIAccessibleEvent::EVENT_MENU_END, mCurrentARIAMenubar,
+ PR_FALSE, nsAccEvent::eAllowDupes);
if (menuEndEvent) {
- FireDelayedAccessibleEvent(menuEndEvent, eAllowDupes);
+ FireDelayedAccessibleEvent(menuEndEvent);
}
mCurrentARIAMenubar = nsnull;
}
NS_IF_RELEASE(gLastFocusedNode);
gLastFocusedNode = finalFocusNode;
NS_IF_ADDREF(gLastFocusedNode);
@@ -531,17 +536,18 @@ PRBool nsRootAccessible::FireAccessibleF
// and that's what we care about
// Make sure we never fire focus for the nsRootAccessible (mDOMNode)
return PR_FALSE;
}
}
FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_FOCUS,
- finalFocusNode, eRemoveDupes, aIsAsynch);
+ finalFocusNode, nsAccEvent::eRemoveDupes,
+ aIsAsynch);
return PR_TRUE;
}
void nsRootAccessible::FireCurrentFocusEvent()
{
nsCOMPtr<nsIDOMNode> focusedNode = GetCurrentFocus();
if (!focusedNode) {
@@ -913,17 +919,17 @@ nsresult nsRootAccessible::HandleEventWi
nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_MENU_START, accessible, PR_TRUE);
}
else if (eventType.EqualsLiteral("DOMMenuBarInactive")) { // Always asynch, always from user input
nsAccEvent::PrepareForEvent(aTargetNode, PR_TRUE);
nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_MENU_END, accessible, PR_TRUE);
FireCurrentFocusEvent();
}
else if (eventType.EqualsLiteral("ValueChange")) {
- nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, accessible);
+ FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aTargetNode, nsAccEvent::eRemoveDupes);
}
#ifdef DEBUG
else if (eventType.EqualsLiteral("mouseover")) {
nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_DRAGDROP_START, accessible);
}
#endif
return NS_OK;
}
--- a/accessible/src/html/nsHTMLAreaAccessible.cpp
+++ b/accessible/src/html/nsHTMLAreaAccessible.cpp
@@ -32,102 +32,107 @@
* 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 ***** */
#include "nsHTMLAreaAccessible.h"
-#include "nsIAccessibilityService.h"
#include "nsIServiceManager.h"
#include "nsIDOMElement.h"
#include "nsIDOMHTMLAreaElement.h"
#include "nsIFrame.h"
#include "nsIImageFrame.h"
#include "nsIImageMap.h"
-// --- area -----
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLAreaAccessible
-nsHTMLAreaAccessible::nsHTMLAreaAccessible(nsIDOMNode *aDomNode, nsIAccessible *aParent, nsIWeakReference* aShell):
-nsLinkableAccessible(aDomNode, aShell)
+nsHTMLAreaAccessible::
+ nsHTMLAreaAccessible(nsIDOMNode *aDomNode, nsIAccessible *aParent,
+ nsIWeakReference* aShell):
+ nsHTMLLinkAccessible(aDomNode, aShell)
{
}
-// Expose nsIAccessibleHyperLink unconditionally
-NS_IMPL_ISUPPORTS_INHERITED1(nsHTMLAreaAccessible, nsLinkableAccessible,
- nsIAccessibleHyperLink)
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessible
+
+NS_IMETHODIMP
+nsHTMLAreaAccessible::GetName(nsAString & aName)
+{
+ aName.Truncate();
-/* wstring getName (); */
-NS_IMETHODIMP nsHTMLAreaAccessible::GetName(nsAString & aName)
-{
- nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
- if (!content) {
+ if (IsDefunct())
return NS_ERROR_FAILURE;
+
+ if (mRoleMapEntry) {
+ nsresult rv = nsAccessible::GetName(aName);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!aName.IsEmpty())
+ return NS_OK;
}
- aName.Truncate();
- if (mRoleMapEntry) {
- nsresult rv = nsAccessible::GetName(aName);
- if (!aName.IsEmpty()) {
- return rv;
- }
- }
+ nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
if (!content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::alt,
aName) &&
!content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::title,
aName)) {
return GetValue(aName);
}
return NS_OK;
}
-/* unsigned long getRole (); */
-NS_IMETHODIMP nsHTMLAreaAccessible::GetRole(PRUint32 *_retval)
+NS_IMETHODIMP
+nsHTMLAreaAccessible::GetDescription(nsAString& aDescription)
{
- *_retval = nsIAccessibleRole::ROLE_LINK;
+ aDescription.Truncate();
+
+ // Still to do - follow IE's standard here
+ nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(mDOMNode));
+ if (area)
+ area->GetShape(aDescription);
+
return NS_OK;
}
-/* wstring getDescription (); */
-NS_IMETHODIMP nsHTMLAreaAccessible::GetDescription(nsAString& _retval)
+NS_IMETHODIMP
+nsHTMLAreaAccessible::GetFirstChild(nsIAccessible **aChild)
{
- // Still to do - follow IE's standard here
- nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(mDOMNode));
- if (area)
- area->GetShape(_retval);
+ NS_ENSURE_ARG_POINTER(aChild);
+
+ *aChild = nsnull;
return NS_OK;
}
+NS_IMETHODIMP
+nsHTMLAreaAccessible::GetLastChild(nsIAccessible **aChild)
+{
+ NS_ENSURE_ARG_POINTER(aChild);
-/* nsIAccessible getFirstChild (); */
-NS_IMETHODIMP nsHTMLAreaAccessible::GetFirstChild(nsIAccessible **_retval)
-{
- *_retval = nsnull;
+ *aChild = nsnull;
return NS_OK;
}
-/* nsIAccessible getLastChild (); */
-NS_IMETHODIMP nsHTMLAreaAccessible::GetLastChild(nsIAccessible **_retval)
+NS_IMETHODIMP
+nsHTMLAreaAccessible::GetChildCount(PRInt32 *aCount)
{
- *_retval = nsnull;
+ NS_ENSURE_ARG_POINTER(aCount);
+
+ *aCount = 0;
return NS_OK;
}
-/* long getAccChildCount (); */
-NS_IMETHODIMP nsHTMLAreaAccessible::GetChildCount(PRInt32 *_retval)
-{
- *_retval = 0;
- return NS_OK;
-}
-
-/* void accGetBounds (out long x, out long y, out long width, out long height); */
-NS_IMETHODIMP nsHTMLAreaAccessible::GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height)
+NS_IMETHODIMP
+nsHTMLAreaAccessible::GetBounds(PRInt32 *x, PRInt32 *y,
+ PRInt32 *width, PRInt32 *height)
{
// Essentially this uses GetRect on mAreas of nsImageMap from nsImageFrame
*x = *y = *width = *height = 0;
nsPresContext *presContext = GetPresContext();
NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
--- a/accessible/src/html/nsHTMLAreaAccessible.h
+++ b/accessible/src/html/nsHTMLAreaAccessible.h
@@ -34,35 +34,34 @@
* 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 _nsHTMLAreaAccessible_H_
#define _nsHTMLAreaAccessible_H_
-#include "nsBaseWidgetAccessible.h"
+#include "nsHTMLLinkAccessible.h"
/* Accessible for image map areas - must be child of image
*/
-class nsHTMLAreaAccessible : public nsLinkableAccessible
+class nsHTMLAreaAccessible : public nsHTMLLinkAccessible
{
public:
nsHTMLAreaAccessible(nsIDOMNode *domNode, nsIAccessible *accParent,
nsIWeakReference* aShell);
- NS_DECL_ISUPPORTS_INHERITED
+ // nsIAccessible
+ NS_IMETHOD GetName(nsAString & aName);
+ NS_IMETHOD GetDescription(nsAString& aDescription);
- // nsIAccessible
- NS_IMETHOD GetName(nsAString & _retval);
- NS_IMETHOD GetRole(PRUint32 *_retval);
NS_IMETHOD GetFirstChild(nsIAccessible **_retval);
NS_IMETHOD GetLastChild(nsIAccessible **_retval);
NS_IMETHOD GetChildCount(PRInt32 *_retval);
- NS_IMETHOD GetDescription(nsAString& _retval);
+
NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
NS_IMETHOD GetChildAtPoint(PRInt32 aX, PRInt32 aY, nsIAccessible **aAccessible)
{ NS_ENSURE_ARG_POINTER(aAccessible); NS_ADDREF(*aAccessible = this); return NS_OK; } // Don't walk into these
};
#endif
--- a/accessible/src/html/nsHTMLLinkAccessible.cpp
+++ b/accessible/src/html/nsHTMLLinkAccessible.cpp
@@ -15,74 +15,173 @@
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Author: Aaron Leventhal (aaronl@netscape.com)
+ * Aaron Leventhal <aleventh@us.ibm.com> (original author)
+ * Alexander Surkov <surkov.alexander@gmail.com>
*
* 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 ***** */
#include "nsHTMLLinkAccessible.h"
-#include "nsAccessibilityAtoms.h"
-#include "nsIAccessibleEvent.h"
-#include "nsINameSpaceManager.h"
+
+#include "nsILink.h"
-NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLLinkAccessible, nsLinkableAccessible)
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLLinkAccessible
-nsHTMLLinkAccessible::nsHTMLLinkAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell):
-nsLinkableAccessible(aDomNode, aShell)
+nsHTMLLinkAccessible::nsHTMLLinkAccessible(nsIDOMNode* aDomNode,
+ nsIWeakReference* aShell):
+ nsHyperTextAccessibleWrap(aDomNode, aShell)
{
}
-/* wstring getName (); */
-NS_IMETHODIMP nsHTMLLinkAccessible::GetName(nsAString& aName)
+// Expose nsIAccessibleHyperLink unconditionally
+NS_IMPL_ISUPPORTS_INHERITED1(nsHTMLLinkAccessible, nsHyperTextAccessibleWrap,
+ nsIAccessibleHyperLink)
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessible
+
+NS_IMETHODIMP
+nsHTMLLinkAccessible::GetName(nsAString& aName)
{
- if (!mActionContent)
+ aName.Truncate();
+
+ if (IsDefunct())
return NS_ERROR_FAILURE;
- return AppendFlatStringFromSubtree(mActionContent, &aName);
+ nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
+ return AppendFlatStringFromSubtree(content, &aName);
}
-/* unsigned long getRole (); */
-NS_IMETHODIMP nsHTMLLinkAccessible::GetRole(PRUint32 *_retval)
+NS_IMETHODIMP
+nsHTMLLinkAccessible::GetRole(PRUint32 *aRole)
{
- *_retval = nsIAccessibleRole::ROLE_LINK;
+ NS_ENSURE_ARG_POINTER(aRole);
+ *aRole = nsIAccessibleRole::ROLE_LINK;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLLinkAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
{
- nsresult rv = nsLinkableAccessible::GetState(aState, aExtraState);
+ nsresult rv = nsHyperTextAccessibleWrap::GetState(aState, aExtraState);
NS_ENSURE_SUCCESS(rv, rv);
if (!mDOMNode)
return NS_OK;
*aState &= ~nsIAccessibleStates::STATE_READONLY;
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
if (content && content->HasAttr(kNameSpaceID_None,
nsAccessibilityAtoms::name)) {
// This is how we indicate it is a named anchor
// In other words, this anchor can be selected as a location :)
// There is no other better state to use to indicate this.
*aState |= nsIAccessibleStates::STATE_SELECTABLE;
}
+ nsCOMPtr<nsILink> link = do_QueryInterface(mDOMNode);
+ NS_ENSURE_STATE(link);
+
+ nsLinkState linkState;
+ link->GetLinkState(linkState);
+ if (linkState == eLinkState_NotLink) {
+ // This is a named anchor, not a link with also a name attribute. bail out.
+ return NS_OK;
+ }
+
+ *aState |= nsIAccessibleStates::STATE_LINKED;
+
+ if (linkState == eLinkState_Visited)
+ *aState |= nsIAccessibleStates::STATE_TRAVERSED;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTMLLinkAccessible::GetValue(nsAString& aValue)
+{
+ aValue.Truncate();
+
+ nsresult rv = nsHyperTextAccessible::GetValue(aValue);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!aValue.IsEmpty())
+ return NS_OK;
+
+ nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
+ if (mDOMNode && presShell)
+ return presShell->GetLinkLocation(mDOMNode, aValue);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTMLLinkAccessible::GetNumActions(PRUint8 *aNumActions)
+{
+ NS_ENSURE_ARG_POINTER(aNumActions);
+
+ *aNumActions = 1;
return NS_OK;
}
+
+NS_IMETHODIMP
+nsHTMLLinkAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
+{
+ // Action 0 (default action): Jump to link
+ aName.Truncate();
+ if (aIndex != eAction_Jump)
+ return NS_ERROR_INVALID_ARG;
+
+ aName.AssignLiteral("jump");
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTMLLinkAccessible::DoAction(PRUint8 aIndex)
+{
+ // Action 0 (default action): Jump to link
+ if (aIndex != eAction_Jump)
+ return NS_ERROR_INVALID_ARG;
+
+ if (IsDefunct())
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
+ return DoCommand(content);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessibleHyperLink
+
+NS_IMETHODIMP
+nsHTMLLinkAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI)
+{
+ NS_ENSURE_ARG_POINTER(aURI);
+ *aURI = nsnull;
+
+ if (aIndex != 0)
+ return NS_ERROR_INVALID_ARG;
+
+ nsCOMPtr<nsILink> link(do_QueryInterface(mDOMNode));
+ NS_ENSURE_STATE(link);
+
+ return link->GetHrefURI(aURI);
+}
--- a/accessible/src/html/nsHTMLLinkAccessible.h
+++ b/accessible/src/html/nsHTMLLinkAccessible.h
@@ -15,17 +15,18 @@
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Author: Aaron Leventhal (aaronl@netscape.com)
+ * Aaron Leventhal <aleventh@us.ibm.com> (original author)
+ * Alexander Surkov <surkov.alexander@gmail.com>
*
* 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
@@ -34,24 +35,35 @@
* 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 _nsHTMLLinkAccessible_H_
#define _nsHTMLLinkAccessible_H_
-#include "nsBaseWidgetAccessible.h"
+#include "nsHyperTextAccessibleWrap.h"
-class nsHTMLLinkAccessible : public nsLinkableAccessible
+class nsHTMLLinkAccessible : public nsHyperTextAccessibleWrap
{
+public:
+ nsHTMLLinkAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
+
NS_DECL_ISUPPORTS_INHERITED
-public:
- nsHTMLLinkAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
-
// nsIAccessible
- NS_IMETHOD GetName(nsAString& _retval);
- NS_IMETHOD GetRole(PRUint32 *_retval);
+ NS_IMETHOD GetName(nsAString& aName);
+ NS_IMETHOD GetRole(PRUint32 *aRole);
NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
+ NS_IMETHOD GetValue(nsAString& aValue);
+
+ NS_IMETHOD GetNumActions(PRUint8 *aNumActions);
+ NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
+ NS_IMETHOD DoAction(PRUint8 aIndex);
+
+ // nsIAccessibleHyperLink
+ NS_IMETHOD GetURI(PRInt32 aIndex, nsIURI **aURI);
+
+protected:
+ enum { eAction_Jump = 0 };
};
#endif
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp
+++ b/accessible/src/html/nsHTMLSelectAccessible.cpp
@@ -453,16 +453,20 @@ void nsHTMLSelectListAccessible::CacheCh
nsCOMPtr<nsIContent> selectContent(do_QueryInterface(mDOMNode));
nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
if (!selectContent || !accService) {
mAccChildCount = eChildCountUninitialized;
return;
}
+ if (mAccChildCount != eChildCountUninitialized) {
+ return;
+ }
+
mAccChildCount = 0; // Avoid reentry
PRInt32 childCount = 0;
nsCOMPtr<nsIAccessible> lastGoodAccessible =
CacheOptSiblings(accService, selectContent, nsnull, &childCount);
mAccChildCount = childCount;
}
/** ----- nsHTMLSelectOptionAccessible ----- */
@@ -1061,17 +1065,16 @@ NS_IMETHODIMP nsHTMLComboboxAccessible::
mListAccessible = nsnull;
}
return NS_OK;
}
/**
* As a nsHTMLComboboxAccessible we can have the following states:
* STATE_FOCUSED
- * STATE_READONLY
* STATE_FOCUSABLE
* STATE_HASPOPUP
* STATE_EXPANDED
* STATE_COLLAPSED
*/
NS_IMETHODIMP
nsHTMLComboboxAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
{
@@ -1091,17 +1094,16 @@ nsHTMLComboboxAccessible::GetState(PRUin
*aState |= nsIAccessibleStates::STATE_EXPANDED;
}
else {
*aState &= ~nsIAccessibleStates::STATE_FOCUSED; // Focus is on an option
*aState |= nsIAccessibleStates::STATE_COLLAPSED;
}
*aState |= nsIAccessibleStates::STATE_HASPOPUP |
- nsIAccessibleStates::STATE_READONLY |
nsIAccessibleStates::STATE_FOCUSABLE;
return NS_OK;
}
NS_IMETHODIMP nsHTMLComboboxAccessible::GetDescription(nsAString& aDescription)
{
aDescription.Truncate();
--- a/accessible/src/msaa/CAccessibleAction.cpp
+++ b/accessible/src/msaa/CAccessibleAction.cpp
@@ -111,22 +111,24 @@ CAccessibleAction::get_description(long
if (!acc)
return E_FAIL;
nsAutoString description;
PRUint8 index = static_cast<PRUint8>(aActionIndex);
if (NS_FAILED(acc->GetActionDescription(index, description)))
return E_FAIL;
- if (!description.IsVoid()) {
- INT result = ::SysReAllocStringLen(aDescription, description.get(),
- description.Length());
- if (!result)
- return E_OUTOFMEMORY;
- }
+ if (description.IsVoid())
+ return S_FALSE;
+
+ *aDescription = ::SysAllocStringLen(description.get(),
+ description.Length());
+ if (!*aDescription)
+ return E_OUTOFMEMORY;
+
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
CAccessibleAction::get_keyBinding(long aActionIndex, long aNumMaxBinding,
BSTR **aKeyBinding,
@@ -151,54 +153,76 @@ CAccessibleAction::get_keyBinding(long a
PRBool aUseNumMaxBinding = length > static_cast<PRUint32>(aNumMaxBinding);
PRUint32 maxBinding = static_cast<PRUint32>(aNumMaxBinding);
PRUint32 numBinding = length > maxBinding ? maxBinding : length;
*aNumBinding = numBinding;
- *aKeyBinding = new BSTR[numBinding];
+ *aKeyBinding = static_cast<BSTR*>(nsMemory::Alloc((numBinding) * sizeof(BSTR*)));
if (!*aKeyBinding)
return E_OUTOFMEMORY;
- for (PRUint32 i = 0; i < numBinding; i++) {
+ PRBool outOfMemory = PR_FALSE;
+ PRUint32 i = 0;
+ for (; i < numBinding; i++) {
nsAutoString key;
keys->Item(i, key);
- INT result = ::SysReAllocStringLen(aKeyBinding[i], key.get(),
- key.Length());
- if (!result)
- return E_OUTOFMEMORY;
+ *(aKeyBinding[i]) = ::SysAllocStringLen(key.get(), key.Length());
+
+ if (!*(aKeyBinding[i])) {
+ outOfMemory = PR_TRUE;
+ break;
+ }
+ }
+
+ if (outOfMemory) {
+ for (PRUint32 j = 0; j < i; j++)
+ ::SysFreeString(*(aKeyBinding[j]));
+
+ nsMemory::Free(*aKeyBinding);
+ *aKeyBinding = NULL;
+
+ return E_OUTOFMEMORY;
}
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
CAccessibleAction::get_name(long aActionIndex, BSTR *aName)
{
__try {
+ *aName = NULL;
+
nsCOMPtr<nsIAccessible> acc(do_QueryInterface(this));
if (!acc)
return E_FAIL;
nsAutoString name;
PRUint8 index = static_cast<PRUint8>(aActionIndex);
if (NS_FAILED(acc->GetActionName(index, name)))
return E_FAIL;
- INT result = ::SysReAllocStringLen(aName, name.get(), name.Length());
- if (!result)
+ if (name.IsEmpty())
+ return S_FALSE;
+
+ *aName = ::SysAllocStringLen(name.get(), name.Length());
+ if (!*aName)
return E_OUTOFMEMORY;
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
CAccessibleAction::get_localizedName(long aActionIndex, BSTR *aLocalizedName)
{
- ::SysFreeString(*aLocalizedName);
+__try {
+ *aLocalizedName = NULL;
+} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
+
return E_NOTIMPL;
}
--- a/accessible/src/msaa/CAccessibleHyperlink.cpp
+++ b/accessible/src/msaa/CAccessibleHyperlink.cpp
@@ -134,18 +134,21 @@ CAccessibleHyperlink::get_anchorTarget(l
if (NS_FAILED(rv))
return E_FAIL;
nsAutoString stringURI;
AppendUTF8toUTF16(prePath, stringURI);
AppendUTF8toUTF16(path, stringURI);
aAnchorTarget->vt = VT_BSTR;
- if (!::SysReAllocStringLen(&aAnchorTarget->bstrVal, stringURI.get(), stringURI.Length()))
+ aAnchorTarget->bstrVal = ::SysAllocStringLen(stringURI.get(),
+ stringURI.Length());
+ if (!aAnchorTarget->bstrVal)
return E_OUTOFMEMORY;
+
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
CAccessibleHyperlink::get_startIndex(long *aIndex)
{
--- a/accessible/src/msaa/CAccessibleImage.cpp
+++ b/accessible/src/msaa/CAccessibleImage.cpp
@@ -71,27 +71,34 @@ CAccessibleImage::QueryInterface(REFIID
}
// IAccessibleImage
STDMETHODIMP
CAccessibleImage::get_description(BSTR *aDescription)
{
__try {
+ *aDescription = NULL;
+
nsCOMPtr<nsIAccessible> acc(do_QueryInterface(this));
if (!acc)
return E_FAIL;
nsAutoString description;
nsresult rv = acc->GetName(description);
if (NS_FAILED(rv))
return E_FAIL;
- if (!::SysReAllocStringLen(aDescription, description.get(), description.Length()))
+ if (description.IsEmpty())
+ return S_FALSE;
+
+ *aDescription = ::SysAllocStringLen(description.get(), description.Length());
+ if (!*aDescription)
return E_OUTOFMEMORY;
+
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
CAccessibleImage::get_imagePosition(enum IA2CoordinateType aCoordType,
long *aX,
--- a/accessible/src/msaa/CAccessibleTable.cpp
+++ b/accessible/src/msaa/CAccessibleTable.cpp
@@ -155,27 +155,33 @@ CAccessibleTable::get_childIndex(long aR
return E_FAIL;
}
STDMETHODIMP
CAccessibleTable::get_columnDescription(long aColumn, BSTR *aDescription)
{
__try {
+ *aDescription = NULL;
+
nsCOMPtr<nsIAccessibleTable> tableAcc(do_QueryInterface(this));
NS_ASSERTION(tableAcc, CANT_QUERY_ASSERTION_MSG);
if (!tableAcc)
return E_FAIL;
nsAutoString descr;
nsresult rv = tableAcc->GetColumnDescription (aColumn, descr);
if (NS_FAILED(rv))
return E_FAIL;
- if (!::SysReAllocStringLen(aDescription, descr.get(), descr.Length()))
+ if (descr.IsEmpty())
+ return S_FALSE;
+
+ *aDescription = ::SysAllocStringLen(descr.get(), descr.Length());
+ if (!*aDescription)
return E_OUTOFMEMORY;
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
CAccessibleTable::get_columnExtentAt(long aRow, long aColumn,
@@ -365,27 +371,33 @@ CAccessibleTable::get_nSelectedRows(long
return E_FAIL;
}
STDMETHODIMP
CAccessibleTable::get_rowDescription(long aRow, BSTR *aDescription)
{
__try {
+ *aDescription = NULL;
+
nsCOMPtr<nsIAccessibleTable> tableAcc(do_QueryInterface(this));
NS_ASSERTION(tableAcc, CANT_QUERY_ASSERTION_MSG);
if (!tableAcc)
return E_FAIL;
nsAutoString descr;
nsresult rv = tableAcc->GetRowDescription (aRow, descr);
if (NS_FAILED(rv))
return E_FAIL;
- if (!::SysReAllocStringLen(aDescription, descr.get(), descr.Length()))
+ if (descr.IsEmpty())
+ return S_FALSE;
+
+ *aDescription = ::SysAllocStringLen(descr.get(), descr.Length());
+ if (!*aDescription)
return E_OUTOFMEMORY;
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
CAccessibleTable::get_rowExtentAt(long aRow, long aColumn, long *aNRowsSpanned)
--- a/accessible/src/msaa/CAccessibleText.cpp
+++ b/accessible/src/msaa/CAccessibleText.cpp
@@ -95,16 +95,18 @@ CAccessibleText::addSelection(long aStar
return E_FAIL;
}
STDMETHODIMP
CAccessibleText::get_attributes(long aOffset, long *aStartOffset,
long *aEndOffset, BSTR *aTextAttributes)
{
__try {
+ *aTextAttributes = NULL;
+
GET_NSIACCESSIBLETEXT
nsCOMPtr<nsIAccessible> accessible;
PRInt32 startOffset = 0, endOffset = 0;
textAcc->GetAttributeRange(aOffset, &startOffset, &endOffset,
getter_AddRefs(accessible));
if (!accessible)
return E_FAIL;
@@ -232,37 +234,46 @@ CAccessibleText::get_selection(long aSel
return E_FAIL;
}
STDMETHODIMP
CAccessibleText::get_text(long aStartOffset, long aEndOffset, BSTR *aText)
{
__try {
+ *aText = NULL;
+
GET_NSIACCESSIBLETEXT
nsAutoString text;
nsresult rv = textAcc->GetText(aStartOffset, aEndOffset, text);
if (NS_FAILED(rv))
return E_FAIL;
- if (!::SysReAllocStringLen(aText, text.get(), text.Length()))
+ if (text.IsEmpty())
+ return S_FALSE;
+
+ *aText = ::SysAllocStringLen(text.get(), text.Length());
+ if (!*aText)
return E_OUTOFMEMORY;
+
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
CAccessibleText::get_textBeforeOffset(long aOffset,
enum IA2TextBoundaryType aBoundaryType,
long *aStartOffset, long *aEndOffset,
BSTR *aText)
{
__try {
+ *aText = NULL;
+
GET_NSIACCESSIBLETEXT
nsresult rv = NS_OK;
nsAutoString text;
PRInt32 startOffset = 0, endOffset = 0;
if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
startOffset = 0;
@@ -277,30 +288,37 @@ CAccessibleText::get_textBeforeOffset(lo
}
if (NS_FAILED(rv))
return E_FAIL;
*aStartOffset = startOffset;
*aEndOffset = endOffset;
- if (!::SysReAllocStringLen(aText, text.get(), text.Length()))
+ if (text.IsEmpty())
+ return S_FALSE;
+
+ *aText = ::SysAllocStringLen(text.get(), text.Length());
+ if (!*aText)
return E_OUTOFMEMORY;
+
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
CAccessibleText::get_textAfterOffset(long aOffset,
enum IA2TextBoundaryType aBoundaryType,
long *aStartOffset, long *aEndOffset,
BSTR *aText)
{
__try {
+ *aText = NULL;
+
GET_NSIACCESSIBLETEXT
nsresult rv = NS_OK;
nsAutoString text;
PRInt32 startOffset = 0, endOffset = 0;
if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
startOffset = 0;
@@ -315,18 +333,23 @@ CAccessibleText::get_textAfterOffset(lon
}
if (NS_FAILED(rv))
return E_FAIL;
*aStartOffset = startOffset;
*aEndOffset = endOffset;
- if (!::SysReAllocStringLen(aText, text.get(), text.Length()))
+ if (text.IsEmpty())
+ return S_FALSE;
+
+ *aText = ::SysAllocStringLen(text.get(), text.Length());
+ if (!*aText)
return E_OUTOFMEMORY;
+
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
CAccessibleText::get_textAtOffset(long aOffset,
enum IA2TextBoundaryType aBoundaryType,
@@ -353,18 +376,23 @@ CAccessibleText::get_textAtOffset(long a
}
if (NS_FAILED(rv))
return E_FAIL;
*aStartOffset = startOffset;
*aEndOffset = endOffset;
- if (!::SysReAllocStringLen(aText, text.get(), text.Length()))
+ if (text.IsEmpty())
+ return S_FALSE;
+
+ *aText = ::SysAllocStringLen(text.get(), text.Length());
+ if (!*aText)
return E_OUTOFMEMORY;
+
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
CAccessibleText::removeSelection(long aSelectionIndex)
{
@@ -492,18 +520,18 @@ CAccessibleText::GetModifiedText(PRBool
nsresult rv = GetModifiedText(aGetInsertedText, text,
&startOffset, &endOffset);
if (NS_FAILED(rv))
return E_FAIL;
aText->start = startOffset;
aText->end = endOffset;
- INT result = ::SysReAllocStringLen(&(aText->text), text.get(), text.Length());
- return result ? NS_OK : E_OUTOFMEMORY;
+ aText->text = ::SysAllocStringLen(text.get(), text.Length());
+ return aText->text ? NS_OK : E_OUTOFMEMORY;
}
nsAccessibleTextBoundary
CAccessibleText::GetGeckoTextBoundary(enum IA2TextBoundaryType aBoundaryType)
{
switch (aBoundaryType) {
case IA2_TEXT_BOUNDARY_CHAR:
return nsIAccessibleText::BOUNDARY_CHAR;
--- a/accessible/src/msaa/nsAccessNodeWrap.cpp
+++ b/accessible/src/msaa/nsAccessNodeWrap.cpp
@@ -526,33 +526,46 @@ nsAccessNodeWrap::get_innerHTML(BSTR __R
*aInnerHTML = nsnull;
nsCOMPtr<nsIDOMNSHTMLElement> domNSElement(do_QueryInterface(mDOMNode));
if (!domNSElement)
return E_FAIL; // Node already shut down
nsAutoString innerHTML;
domNSElement->GetInnerHTML(innerHTML);
- *aInnerHTML = ::SysAllocString(innerHTML.get());
+ if (innerHTML.IsEmpty())
+ return S_FALSE;
+
+ *aInnerHTML = ::SysAllocStringLen(innerHTML.get(), innerHTML.Length());
+ if (!*aInnerHTML)
+ return E_OUTOFMEMORY;
+
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
nsAccessNodeWrap::get_language(BSTR __RPC_FAR *aLanguage)
{
__try {
- *aLanguage = nsnull;
+ *aLanguage = NULL;
nsAutoString language;
if (NS_FAILED(GetLanguage(language))) {
return E_FAIL;
}
- *aLanguage = ::SysAllocString(language.get());
+
+ if (language.IsEmpty())
+ return S_FALSE;
+
+ *aLanguage = ::SysAllocStringLen(language.get(), language.Length());
+ if (!*aLanguage)
+ return E_OUTOFMEMORY;
+
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
nsAccessNodeWrap::get_localInterface(
/* [out] */ void __RPC_FAR *__RPC_FAR *localInterface)
--- a/accessible/src/msaa/nsAccessibleRelationWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleRelationWrap.cpp
@@ -81,67 +81,69 @@ nsAccessibleRelationWrap::QueryInterface
}
// IAccessibleRelation
STDMETHODIMP
nsAccessibleRelationWrap::get_relationType(BSTR *aRelationType)
{
__try {
+ *aRelationType = NULL;
+
PRUint32 type = 0;
nsresult rv = GetRelationType(&type);
if (NS_FAILED(rv))
return E_FAIL;
INT res;
switch (type) {
case RELATION_CONTROLLED_BY:
- res = ::SysReAllocString(aRelationType, IA2_RELATION_CONTROLLED_BY);
+ *aRelationType = ::SysAllocString(IA2_RELATION_CONTROLLED_BY);
break;
case RELATION_CONTROLLER_FOR:
- res = ::SysReAllocString(aRelationType, IA2_RELATION_CONTROLLER_FOR);
+ *aRelationType = ::SysAllocString(IA2_RELATION_CONTROLLER_FOR);
break;
case RELATION_DESCRIBED_BY:
- res = ::SysReAllocString(aRelationType, IA2_RELATION_DESCRIBED_BY);
+ *aRelationType = ::SysAllocString(IA2_RELATION_DESCRIBED_BY);
break;
case RELATION_DESCRIPTION_FOR:
- res = ::SysReAllocString(aRelationType, IA2_RELATION_DESCRIPTION_FOR);
+ *aRelationType = ::SysAllocString(IA2_RELATION_DESCRIPTION_FOR);
break;
case RELATION_EMBEDDED_BY:
- res = ::SysReAllocString(aRelationType, IA2_RELATION_EMBEDDED_BY);
+ *aRelationType = ::SysAllocString(IA2_RELATION_EMBEDDED_BY);
break;
case RELATION_EMBEDS:
- res = ::SysReAllocString(aRelationType, IA2_RELATION_EMBEDS);
+ *aRelationType = ::SysAllocString(IA2_RELATION_EMBEDS);
break;
case RELATION_FLOWS_FROM:
- res = ::SysReAllocString(aRelationType, IA2_RELATION_FLOWS_FROM);
+ *aRelationType = ::SysAllocString(IA2_RELATION_FLOWS_FROM);
break;
case RELATION_FLOWS_TO:
- res = ::SysReAllocString(aRelationType, IA2_RELATION_FLOWS_TO);
+ *aRelationType = ::SysAllocString(IA2_RELATION_FLOWS_TO);
break;
case RELATION_LABEL_FOR:
- res = ::SysReAllocString(aRelationType, IA2_RELATION_LABEL_FOR);
+ *aRelationType = ::SysAllocString(IA2_RELATION_LABEL_FOR);
break;
case RELATION_LABELLED_BY:
- res = ::SysReAllocString(aRelationType, IA2_RELATION_LABELED_BY);
+ *aRelationType = ::SysAllocString(IA2_RELATION_LABELED_BY);
break;
case RELATION_MEMBER_OF:
- res = ::SysReAllocString(aRelationType, IA2_RELATION_MEMBER_OF);
+ *aRelationType = ::SysAllocString(IA2_RELATION_MEMBER_OF);
break;
case RELATION_NODE_CHILD_OF:
- res = ::SysReAllocString(aRelationType, IA2_RELATION_NODE_CHILD_OF);
+ *aRelationType = ::SysAllocString(IA2_RELATION_NODE_CHILD_OF);
break;
case RELATION_PARENT_WINDOW_OF:
- res = ::SysReAllocString(aRelationType, IA2_RELATION_PARENT_WINDOW_OF);
+ *aRelationType = ::SysAllocString(IA2_RELATION_PARENT_WINDOW_OF);
break;
case RELATION_POPUP_FOR:
- res = ::SysReAllocString(aRelationType, IA2_RELATION_POPUP_FOR);
+ *aRelationType = ::SysAllocString(IA2_RELATION_POPUP_FOR);
break;
case RELATION_SUBWINDOW_OF:
- res = ::SysReAllocString(aRelationType, IA2_RELATION_SUBWINDOW_OF);
+ *aRelationType = ::SysAllocString(IA2_RELATION_SUBWINDOW_OF);
break;
default:
return E_FAIL;
}
if (!res)
return E_OUTOFMEMORY;
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -289,20 +289,25 @@ STDMETHODIMP nsAccessibleWrap::get_accNa
{
__try {
*pszName = NULL;
nsCOMPtr<nsIAccessible> xpAccessible;
GetXPAccessibleFor(varChild, getter_AddRefs(xpAccessible));
if (xpAccessible) {
nsAutoString name;
if (NS_FAILED(xpAccessible->GetName(name)))
+ return E_FAIL;
+
+ if (name.IsEmpty())
return S_FALSE;
- if (!name.IsVoid()) {
- *pszName = ::SysAllocString(name.get());
- }
+
+ *pszName = ::SysAllocStringLen(name.get(), name.Length());
+ if (!*pszName)
+ return E_OUTOFMEMORY;
+
#ifdef DEBUG_A11Y
NS_ASSERTION(mIsInitialized, "Access node was not initialized");
#endif
}
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
@@ -314,19 +319,24 @@ STDMETHODIMP nsAccessibleWrap::get_accVa
{
__try {
*pszValue = NULL;
nsCOMPtr<nsIAccessible> xpAccessible;
GetXPAccessibleFor(varChild, getter_AddRefs(xpAccessible));
if (xpAccessible) {
nsAutoString value;
if (NS_FAILED(xpAccessible->GetValue(value)))
+ return E_FAIL;
+
+ if (value.IsEmpty())
return S_FALSE;
- *pszValue = ::SysAllocString(value.get());
+ *pszValue = ::SysAllocStringLen(value.get(), value.Length());
+ if (!*pszValue)
+ return E_OUTOFMEMORY;
}
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
nsAccessibleWrap::get_accDescription(VARIANT varChild,
BSTR __RPC_FAR *pszDescription)
@@ -410,32 +420,39 @@ nsAccessibleWrap::get_accDescription(VAR
positionInGroup, itemsInGroup);
}
} else if (groupLevel > 0) {
nsTextFormatter::ssprintf(description, NS_LITERAL_STRING("L%d").get(),
groupLevel);
}
if (!description.IsEmpty()) {
- *pszDescription = ::SysAllocString(description.get());
- return S_OK;
+ *pszDescription = ::SysAllocStringLen(description.get(),
+ description.Length());
+ return *pszDescription ? S_OK : E_OUTOFMEMORY;
}
xpAccessible->GetDescription(description);
if (!description.IsEmpty()) {
// Signal to screen readers that this description is speakable
// and is not a formatted positional information description
// Don't localize the "Description: " part of this string, it will be
// parsed out by assistive technologies.
description = NS_LITERAL_STRING("Description: ") + description;
}
- *pszDescription = ::SysAllocString(description.get());
+ if (description.IsEmpty())
+ return S_FALSE;
+
+ *pszDescription = ::SysAllocStringLen(description.get(),
+ description.Length());
+ return *pszDescription ? S_OK : E_OUTOFMEMORY;
+
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
- return S_OK;
+ return E_FAIL;
}
STDMETHODIMP nsAccessibleWrap::get_accRole(
/* [optional][in] */ VARIANT varChild,
/* [retval][out] */ VARIANT __RPC_FAR *pvarRole)
{
__try {
VariantInit(pvarRole);
@@ -560,23 +577,27 @@ STDMETHODIMP nsAccessibleWrap::get_accKe
__try {
*pszKeyboardShortcut = NULL;
nsCOMPtr<nsIAccessible> xpAccessible;
GetXPAccessibleFor(varChild, getter_AddRefs(xpAccessible));
if (xpAccessible) {
nsAutoString shortcut;
nsresult rv = xpAccessible->GetKeyboardShortcut(shortcut);
if (NS_FAILED(rv))
+ return E_FAIL;
+
+ if (shortcut.IsEmpty())
return S_FALSE;
- *pszKeyboardShortcut = ::SysAllocString(shortcut.get());
- return S_OK;
+ *pszKeyboardShortcut = ::SysAllocStringLen(shortcut.get(),
+ shortcut.Length());
+ return *pszKeyboardShortcut ? S_OK : E_OUTOFMEMORY;
}
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
- return S_FALSE;
+ return E_FAIL;
}
STDMETHODIMP nsAccessibleWrap::get_accFocus(
/* [retval][out] */ VARIANT __RPC_FAR *pvarChild)
{
// VT_EMPTY: None. This object does not have the keyboard focus itself
// and does not contain a child that has the keyboard focus.
// VT_I4: lVal is CHILDID_SELF. The object itself has the keyboard focus.
@@ -790,23 +811,28 @@ STDMETHODIMP nsAccessibleWrap::get_accDe
{
__try {
*pszDefaultAction = NULL;
nsCOMPtr<nsIAccessible> xpAccessible;
GetXPAccessibleFor(varChild, getter_AddRefs(xpAccessible));
if (xpAccessible) {
nsAutoString defaultAction;
if (NS_FAILED(xpAccessible->GetActionName(0, defaultAction)))
+ return E_FAIL;
+
+ if (defaultAction.IsEmpty())
return S_FALSE;
- *pszDefaultAction = ::SysAllocString(defaultAction.get());
+ *pszDefaultAction = ::SysAllocStringLen(defaultAction.get(),
+ defaultAction.Length());
+ return *pszDefaultAction ? S_OK : E_OUTOFMEMORY;
}
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
- return S_OK;
+ return E_FAIL;
}
STDMETHODIMP nsAccessibleWrap::accSelect(
/* [in] */ long flagsSelect,
/* [optional][in] */ VARIANT varChild)
{
__try {
// currently only handle focus and selection
@@ -1336,49 +1362,68 @@ nsAccessibleWrap::get_states(AccessibleS
if (extraStates & nsIAccessibleStates::EXT_STATE_VERTICAL)
*aStates |= IA2_STATE_VERTICAL;
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
-nsAccessibleWrap::get_extendedRole(BSTR *extendedRole)
+nsAccessibleWrap::get_extendedRole(BSTR *aExtendedRole)
{
+__try {
+ *aExtendedRole = NULL;
+} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
+
return E_NOTIMPL;
}
STDMETHODIMP
-nsAccessibleWrap::get_localizedExtendedRole(BSTR *localizedExtendedRole)
+nsAccessibleWrap::get_localizedExtendedRole(BSTR *aLocalizedExtendedRole)
{
+__try {
+ *aLocalizedExtendedRole = NULL;
+} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
+
return E_NOTIMPL;
}
STDMETHODIMP
-nsAccessibleWrap::get_nExtendedStates(long *nExtendedStates)
+nsAccessibleWrap::get_nExtendedStates(long *aNExtendedStates)
{
- *nExtendedStates = 0;
+__try {
+ *aNExtendedStates = 0;
+} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
+
return E_NOTIMPL;
}
STDMETHODIMP
-nsAccessibleWrap::get_extendedStates(long maxExtendedStates,
- BSTR **extendedStates,
- long *nExtendedStates)
+nsAccessibleWrap::get_extendedStates(long aMaxExtendedStates,
+ BSTR **aExtendedStates,
+ long *aNExtendedStates)
{
- *nExtendedStates = 0;
+__try {
+ *aExtendedStates = NULL;
+ *aNExtendedStates = 0;
+} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
+
return E_NOTIMPL;
}
STDMETHODIMP
-nsAccessibleWrap::get_localizedExtendedStates(long maxLocalizedExtendedStates,
- BSTR **localizedExtendedStates,
- long *nLocalizedExtendedStates)
+nsAccessibleWrap::get_localizedExtendedStates(long aMaxLocalizedExtendedStates,
+ BSTR **aLocalizedExtendedStates,
+ long *aNLocalizedExtendedStates)
{
- *nLocalizedExtendedStates = 0;
+__try {
+ *aLocalizedExtendedStates = NULL;
+ *aNLocalizedExtendedStates = 0;
+} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
+
return E_NOTIMPL;
}
STDMETHODIMP
nsAccessibleWrap::get_uniqueID(long *uniqueID)
{
__try {
void *id = nsnull;
@@ -1518,17 +1563,17 @@ nsAccessibleWrap::get_attributes(BSTR *a
}
AppendUTF8toUTF16(name, strAttrs);
strAttrs.Append(':');
strAttrs.Append(value);
strAttrs.Append(';');
}
- *aAttributes = ::SysAllocString(strAttrs.get());
+ *aAttributes = ::SysAllocStringLen(strAttrs.get(), strAttrs.Length());
if (!*aAttributes)
return E_OUTOFMEMORY;
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
@@ -1622,21 +1667,16 @@ nsAccessibleWrap::FireAccessibleEvent(ns
// Means we're not active.
NS_ENSURE_TRUE(mWeakShell, NS_ERROR_FAILURE);
nsCOMPtr<nsIAccessible> accessible;
aEvent->GetAccessible(getter_AddRefs(accessible));
if (!accessible)
return NS_OK;
- PRUint32 role = ROLE_SYSTEM_TEXT; // Default value
-
- nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(accessible));
- NS_ENSURE_STATE(accessNode);
-
if (eventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED ||
eventType == nsIAccessibleEvent::EVENT_FOCUS) {
UpdateSystemCaret();
}
PRInt32 childID = GetChildIDFor(accessible); // get the id for the accessible
if (!childID)
return NS_OK; // Can't fire an event without a child ID
@@ -1647,17 +1687,17 @@ nsAccessibleWrap::FireAccessibleEvent(ns
eventType == nsIAccessibleEvent::EVENT_DOM_DESTROY) {
// Don't use frame from current accessible when we're hiding that
// accessible.
accessible->GetParent(getter_AddRefs(newAccessible));
} else {
newAccessible = accessible;
}
- HWND hWnd = GetHWNDFor(accessible);
+ HWND hWnd = GetHWNDFor(newAccessible);
NS_ENSURE_TRUE(hWnd, NS_ERROR_FAILURE);
// Gecko uses two windows for every scrollable area. One window contains
// scrollbars and the child window contains only the client area.
// Details of the 2 window system:
// * Scrollbar window: caret drawing window & return value for WindowFromAccessibleObject()
// * Client area window: text drawing window & MSAA event window
--- a/accessible/src/msaa/nsApplicationAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsApplicationAccessibleWrap.cpp
@@ -67,77 +67,99 @@ nsApplicationAccessibleWrap::QueryInterf
}
// IAccessibleApplication
STDMETHODIMP
nsApplicationAccessibleWrap::get_appName(BSTR *aName)
{
__try {
+ *aName = NULL;
+
if (!sAppInfo)
return E_FAIL;
nsCAutoString cname;
nsresult rv = sAppInfo->GetName(cname);
-
if (NS_FAILED(rv))
return E_FAIL;
+ if (cname.IsEmpty())
+ return S_FALSE;
+
NS_ConvertUTF8toUTF16 name(cname);
- if (!::SysReAllocStringLen(aName, name.get(), name.Length()))
+ *aName = ::SysAllocStringLen(name.get(), name.Length());
+ if (!*aName)
return E_OUTOFMEMORY;
+
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
nsApplicationAccessibleWrap::get_appVersion(BSTR *aVersion)
{
__try {
+ *aVersion = NULL;
+
if (!sAppInfo)
return E_FAIL;
nsCAutoString cversion;
nsresult rv = sAppInfo->GetVersion(cversion);
-
if (NS_FAILED(rv))
return E_FAIL;
+ if (cversion.IsEmpty())
+ return S_FALSE;
+
NS_ConvertUTF8toUTF16 version(cversion);
- if (!::SysReAllocStringLen(aVersion, version.get(), version.Length()))
+ *aVersion = ::SysAllocStringLen(version.get(), version.Length());
+ if (!*aVersion)
return E_OUTOFMEMORY;
+
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP
nsApplicationAccessibleWrap::get_toolkitName(BSTR *aName)
{
- return ::SysReAllocString(aName, L"Gecko");
+__try {
+ *aName = ::SysAllocString(L"Gecko");
+ return *aName ? S_OK : E_OUTOFMEMORY;
+} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
+
+ return E_FAIL;
}
STDMETHODIMP
nsApplicationAccessibleWrap::get_toolkitVersion(BSTR *aVersion)
{
__try {
+ *aVersion = NULL;
+
if (!sAppInfo)
return E_FAIL;
nsCAutoString cversion;
nsresult rv = sAppInfo->GetPlatformVersion(cversion);
-
if (NS_FAILED(rv))
return E_FAIL;
+ if (cversion.IsEmpty())
+ return S_FALSE;
+
NS_ConvertUTF8toUTF16 version(cversion);
- if (!::SysReAllocStringLen(aVersion, version.get(), version.Length()))
- return E_OUTOFMEMORY;
+ *aVersion = ::SysAllocStringLen(version.get(), version.Length());
+ return *aVersion ? S_OK : E_OUTOFMEMORY;
+
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
- return S_OK;
+ return E_FAIL;
}
// nsApplicationAccessibleWrap
void
nsApplicationAccessibleWrap::PreCreate()
{
nsresult rv = CallGetService("@mozilla.org/xre/app-info;1", &sAppInfo);
--- a/accessible/src/msaa/nsDocAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsDocAccessibleWrap.cpp
@@ -197,78 +197,137 @@ NS_IMETHODIMP nsDocAccessibleWrap::FireA
return NS_OK;
}
STDMETHODIMP nsDocAccessibleWrap::get_URL(/* [out] */ BSTR __RPC_FAR *aURL)
{
__try {
*aURL = NULL;
+
nsAutoString URL;
- if (NS_SUCCEEDED(GetURL(URL))) {
- *aURL= ::SysAllocString(URL.get());
- return S_OK;
- }
+ nsresult rv = GetURL(URL);
+ if (NS_FAILED(rv))
+ return E_FAIL;
+
+ if (URL.IsEmpty())
+ return S_FALSE;
+
+ *aURL = ::SysAllocStringLen(URL.get(), URL.Length());
+ return *aURL ? S_OK : E_OUTOFMEMORY;
+
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return E_FAIL;
}
STDMETHODIMP nsDocAccessibleWrap::get_title( /* [out] */ BSTR __RPC_FAR *aTitle)
{
__try {
*aTitle = NULL;
+
nsAutoString title;
- if (NS_SUCCEEDED(GetTitle(title))) { // getter_Copies(pszTitle)))) {
- *aTitle= ::SysAllocString(title.get());
- return S_OK;
- }
+ nsresult rv = GetTitle(title);
+ if (NS_FAILED(rv))
+ return E_FAIL;
+
+ *aTitle = ::SysAllocStringLen(title.get(), title.Length());
+ return *aTitle ? S_OK : E_OUTOFMEMORY;
+
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return E_FAIL;
}
STDMETHODIMP nsDocAccessibleWrap::get_mimeType(/* [out] */ BSTR __RPC_FAR *aMimeType)
{
__try {
*aMimeType = NULL;
+
nsAutoString mimeType;
- if (NS_SUCCEEDED(GetMimeType(mimeType))) {
- *aMimeType= ::SysAllocString(mimeType.get());
- return S_OK;
- }
+ nsresult rv = GetMimeType(mimeType);
+ if (NS_FAILED(rv))
+ return E_FAIL;
+
+ if (mimeType.IsEmpty())
+ return S_FALSE;
+
+ *aMimeType = ::SysAllocStringLen(mimeType.get(), mimeType.Length());
+ return *aMimeType ? S_OK : E_OUTOFMEMORY;
+
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return E_FAIL;
}
STDMETHODIMP nsDocAccessibleWrap::get_docType(/* [out] */ BSTR __RPC_FAR *aDocType)
{
__try {
*aDocType = NULL;
+
nsAutoString docType;
- if (NS_SUCCEEDED(GetDocType(docType))) {
- *aDocType= ::SysAllocString(docType.get());
- return S_OK;
- }
+ nsresult rv = GetDocType(docType);
+ if (NS_FAILED(rv))
+ return E_FAIL;
+
+ if (docType.IsEmpty())
+ return S_FALSE;
+
+ *aDocType = ::SysAllocStringLen(docType.get(), docType.Length());
+ return *aDocType ? S_OK : E_OUTOFMEMORY;
+
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return E_FAIL;
}
STDMETHODIMP nsDocAccessibleWrap::get_nameSpaceURIForID(/* [in] */ short aNameSpaceID,
/* [out] */ BSTR __RPC_FAR *aNameSpaceURI)
{
__try {
- if (aNameSpaceID < 0) {
- return E_FAIL; // -1 is kNameSpaceID_Unknown
- }
*aNameSpaceURI = NULL;
+
+ if (aNameSpaceID < 0)
+ return E_INVALIDARG; // -1 is kNameSpaceID_Unknown
+
nsAutoString nameSpaceURI;
- if (NS_SUCCEEDED(GetNameSpaceURIForID(aNameSpaceID, nameSpaceURI))) {
- *aNameSpaceURI = ::SysAllocString(nameSpaceURI.get());
- return S_OK;
- }
+ nsresult rv = GetNameSpaceURIForID(aNameSpaceID, nameSpaceURI);
+ if (NS_FAILED(rv))
+ return E_FAIL;
+
+ if (nameSpaceURI.IsEmpty())
+ return S_FALSE;
+
+ *aNameSpaceURI = ::SysAllocStringLen(nameSpaceURI.get(),
+ nameSpaceURI.Length());
+
+ return *aNameSpaceURI ? S_OK : E_OUTOFMEMORY;
+
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return E_FAIL;
}
-STDMETHODIMP nsDocAccessibleWrap::put_alternateViewMediaTypes( /* [in] */ BSTR __RPC_FAR *commaSeparatedMediaTypes)
+STDMETHODIMP
+nsDocAccessibleWrap::put_alternateViewMediaTypes( /* [in] */ BSTR __RPC_FAR *aCommaSeparatedMediaTypes)
{
+__try {
+ *aCommaSeparatedMediaTypes = NULL;
+} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
+
return E_NOTIMPL;
}
+STDMETHODIMP nsDocAccessibleWrap::get_accValue(
+ /* [optional][in] */ VARIANT varChild,
+ /* [retval][out] */ BSTR __RPC_FAR *pszValue)
+{
+ // For backwards-compat, we still support old MSAA hack to provide URL in accValue
+ *pszValue = NULL;
+ // Check for real value first
+ HRESULT hr = nsAccessibleWrap::get_accValue(varChild, pszValue);
+ if (FAILED(hr) || *pszValue || varChild.lVal != CHILDID_SELF)
+ return hr;
+ // If document is being used to create a widget, don't use the URL hack
+ PRUint32 role = Role(this);
+ if (role != nsIAccessibleRole::ROLE_DOCUMENT &&
+ role != nsIAccessibleRole::ROLE_APPLICATION &&
+ role != nsIAccessibleRole::ROLE_DIALOG &&
+ role != nsIAccessibleRole::ROLE_ALERT)
+ return hr;
+
+ return get_URL(pszValue);
+}
--- a/accessible/src/msaa/nsDocAccessibleWrap.h
+++ b/accessible/src/msaa/nsDocAccessibleWrap.h
@@ -82,12 +82,17 @@ public:
/* [in] */ BSTR __RPC_FAR *commaSeparatedMediaTypes);
// IAccessible
// Override get_accChild so that it can get any child via the unique ID
virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accChild(
/* [in] */ VARIANT varChild,
/* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild);
+ // Override get_accValue to provide URL when no other value is available
+ virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accValue(
+ /* [optional][in] */ VARIANT varChild,
+ /* [retval][out] */ BSTR __RPC_FAR *pszValue);
+
NS_IMETHOD FireAnchorJumpEvent();
};
#endif
--- a/accessible/src/msaa/nsTextAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsTextAccessibleWrap.cpp
@@ -80,25 +80,31 @@ STDMETHODIMP nsTextAccessibleWrap::Query
(reinterpret_cast<IUnknown*>(*ppv))->AddRef();
return S_OK;
}
STDMETHODIMP nsTextAccessibleWrap::get_domText(
/* [retval][out] */ BSTR __RPC_FAR *aDomText)
{
__try {
- *aDomText = nsnull;
+ *aDomText = NULL;
if (!mDOMNode) {
return E_FAIL; // Node already shut down
}
nsAutoString nodeValue;
mDOMNode->GetNodeValue(nodeValue);
- *aDomText = ::SysAllocString(nodeValue.get());
+ if (nodeValue.IsEmpty())
+ return S_FALSE;
+
+ *aDomText = ::SysAllocStringLen(nodeValue.get(), nodeValue.Length());
+ if (!*aDomText)
+ return E_OUTOFMEMORY;
+
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
STDMETHODIMP nsTextAccessibleWrap::get_clippedSubstringBounds(
/* [in] */ unsigned int aStartIndex,
/* [in] */ unsigned int aEndIndex,
@@ -235,17 +241,17 @@ nsresult nsTextAccessibleWrap::GetCharac
return NS_OK;
}
STDMETHODIMP nsTextAccessibleWrap::get_fontFamily(
/* [retval][out] */ BSTR __RPC_FAR *aFontFamily)
{
__try {
- *aFontFamily = nsnull;
+ *aFontFamily = NULL;
nsIFrame *frame = GetFrame();
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
if (!frame || !presShell) {
return E_FAIL;
}
nsCOMPtr<nsIRenderingContext> rc;
@@ -271,14 +277,19 @@ STDMETHODIMP nsTextAccessibleWrap::get_f
nsIFontMetrics *fm;
rc->GetFontMetrics(fm);
if (!fm) {
return E_FAIL;
}
nsAutoString fontFamily;
deviceContext->FirstExistingFont(fm->Font(), fontFamily);
-
- *aFontFamily = ::SysAllocString(fontFamily.get());
+ if (fontFamily.IsEmpty())
+ return S_FALSE;
+
+ *aFontFamily = ::SysAllocStringLen(fontFamily.get(), fontFamily.Length());
+ if (!*aFontFamily)
+ return E_OUTOFMEMORY;
+
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
}
--- a/accessible/src/xul/nsXULSelectAccessible.cpp
+++ b/accessible/src/xul/nsXULSelectAccessible.cpp
@@ -1026,17 +1026,16 @@ NS_IMETHODIMP nsXULComboboxAccessible::G
*aRole = nsIAccessibleRole::ROLE_COMBOBOX;
}
return NS_OK;
}
/**
* As a nsComboboxAccessible we can have the following states:
* STATE_FOCUSED
- * STATE_READONLY
* STATE_FOCUSABLE
* STATE_HASPOPUP
* STATE_EXPANDED
* STATE_COLLAPSED
*/
NS_IMETHODIMP
nsXULComboboxAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
{
@@ -1052,21 +1051,16 @@ nsXULComboboxAccessible::GetState(PRUint
PRBool isOpen;
menuList->GetOpen(&isOpen);
if (isOpen) {
*aState |= nsIAccessibleStates::STATE_EXPANDED;
}
else {
*aState |= nsIAccessibleStates::STATE_COLLAPSED;
}
- PRBool isEditable;
- menuList->GetEditable(&isEditable);
- if (!isEditable) {
- *aState |= nsIAccessibleStates::STATE_READONLY;
- }
}
*aState |= nsIAccessibleStates::STATE_HASPOPUP |
nsIAccessibleStates::STATE_FOCUSABLE;
return NS_OK;
}
--- a/accessible/src/xul/nsXULTextAccessible.cpp
+++ b/accessible/src/xul/nsXULTextAccessible.cpp
@@ -40,16 +40,17 @@
// NOTE: alphabetically ordered
#include "nsAccessibilityAtoms.h"
#include "nsAccessibilityUtils.h"
#include "nsBaseWidgetAccessible.h"
#include "nsIDOMXULDescriptionElement.h"
#include "nsINameSpaceManager.h"
#include "nsString.h"
#include "nsXULTextAccessible.h"
+#include "nsNetUtil.h"
/**
* For XUL descriptions and labels
*/
nsXULTextAccessible::nsXULTextAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell):
nsHyperTextAccessibleWrap(aDomNode, aShell)
{
}
@@ -133,67 +134,123 @@ nsXULTooltipAccessible::GetState(PRUint3
}
NS_IMETHODIMP nsXULTooltipAccessible::GetRole(PRUint32 *_retval)
{
*_retval = nsIAccessibleRole::ROLE_TOOLTIP;
return NS_OK;
}
-/**
- * For XUL text links
- */
-nsXULLinkAccessible::nsXULLinkAccessible(nsIDOMNode *aDomNode, nsIWeakReference *aShell):
-nsLinkableAccessible(aDomNode, aShell)
+////////////////////////////////////////////////////////////////////////////////
+// nsXULLinkAccessible
+
+nsXULLinkAccessible::
+ nsXULLinkAccessible(nsIDOMNode *aDomNode, nsIWeakReference *aShell):
+ nsHyperTextAccessibleWrap(aDomNode, aShell)
{
}
-NS_IMETHODIMP nsXULLinkAccessible::GetValue(nsAString& aValue)
-{
- if (mIsLink) {
- mActionContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::href, aValue);
- return NS_OK;
- }
- return NS_ERROR_NOT_IMPLEMENTED;
-}
+////////////////////////////////////////////////////////////////////////////////
+// nsXULLinkAccessible. nsIAccessible
-NS_IMETHODIMP nsXULLinkAccessible::GetName(nsAString& aName)
-{
+NS_IMETHODIMP
+nsXULLinkAccessible::GetValue(nsAString& aValue)
+{
+ aValue.Truncate();
+
+ if (IsDefunct())
+ return NS_ERROR_FAILURE;
+
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
- if (!content) {
- return NS_ERROR_FAILURE; // Node shut down
- }
- if (!content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::value,
- aName)) {
- // if the value doesn't exist, flatten the inner content as the name (for descriptions)
- return AppendFlatStringFromSubtree(content, &aName);
- }
- // otherwise, use the value attribute as the name (for labels)
+ content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::href, aValue);
return NS_OK;
}
-NS_IMETHODIMP nsXULLinkAccessible::GetRole(PRUint32 *aRole)
+NS_IMETHODIMP
+nsXULLinkAccessible::GetName(nsAString& aName)
{
- // We used to say ROLE_BUTTON if there was no href, but then screen readers
- // would tell users to hit the space bar for activation, which is wrong for a link
+ aName.Truncate();
+
+ if (IsDefunct())
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
+ content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::value, aName);
+ if (!aName.IsEmpty())
+ return NS_OK;
+
+ return AppendFlatStringFromSubtree(content, &aName);
+}
+
+NS_IMETHODIMP
+nsXULLinkAccessible::GetRole(PRUint32 *aRole)
+{
+ NS_ENSURE_ARG_POINTER(aRole);
+
*aRole = nsIAccessibleRole::ROLE_LINK;
return NS_OK;
}
-void nsXULLinkAccessible::CacheActionContent()
+
+NS_IMETHODIMP
+nsXULLinkAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
+{
+ nsresult rv = nsHyperTextAccessibleWrap::GetState(aState, aExtraState);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ *aState |= nsIAccessibleStates::STATE_LINKED;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULLinkAccessible::GetNumActions(PRUint8 *aNumActions)
{
- // not a link if no content
- nsCOMPtr<nsIContent> mTempContent = do_QueryInterface(mDOMNode);
- if (!mTempContent) {
- return;
- }
+ NS_ENSURE_ARG_POINTER(aNumActions);
+
+ *aNumActions = 1;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULLinkAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
+{
+ aName.Truncate();
+
+ if (aIndex != eAction_Jump)
+ return NS_ERROR_INVALID_ARG;
+
+ aName.AssignLiteral("jump");
+ return NS_OK;
+}
- // not a link if there is no href attribute or not on a <link> tag
- if (mTempContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::href) ||
- mTempContent->Tag() == nsAccessibilityAtoms::link) {
- mIsLink = PR_TRUE;
- mActionContent = mTempContent;
- }
- else if (nsAccUtils::HasListener(mTempContent, NS_LITERAL_STRING("click"))) {
- mIsOnclick = PR_TRUE;
- mActionContent = mTempContent;
- }
+NS_IMETHODIMP
+nsXULLinkAccessible::DoAction(PRUint8 aIndex)
+{
+ if (aIndex != eAction_Jump)
+ return NS_ERROR_INVALID_ARG;
+
+ if (IsDefunct())
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
+ return DoCommand(content);
}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULLinkAccessible. nsIAccessibleHyperLink
+
+NS_IMETHODIMP
+nsXULLinkAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI)
+{
+ NS_ENSURE_ARG_POINTER(aURI);
+ *aURI = nsnull;
+
+ if (aIndex != 0)
+ return NS_ERROR_INVALID_ARG;
+
+ nsAutoString href;
+ nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
+ content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::href, href);
+
+ nsCOMPtr<nsIDocument> document = content->GetOwnerDoc();
+ return NS_NewURI(aURI, href,
+ document ? document->GetDocumentCharacterSet().get() : nsnull);
+}
--- a/accessible/src/xul/nsXULTextAccessible.h
+++ b/accessible/src/xul/nsXULTextAccessible.h
@@ -63,22 +63,33 @@ class nsXULTooltipAccessible : public ns
public:
nsXULTooltipAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
NS_IMETHOD GetName(nsAString& _retval);
NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
NS_IMETHOD GetRole(PRUint32 *_retval);
};
-class nsXULLinkAccessible : public nsLinkableAccessible
+class nsXULLinkAccessible : public nsHyperTextAccessibleWrap
{
public:
nsXULLinkAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
- NS_IMETHOD GetName(nsAString& _retval);
+
+ // nsIAccessible
+ NS_IMETHOD GetName(nsAString& aName);
NS_IMETHOD GetRole(PRUint32 *aRole);
- NS_IMETHOD GetValue(nsAString& _retval);
+ NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
+ NS_IMETHOD GetValue(nsAString& aValue);
+
+ NS_IMETHOD GetNumActions(PRUint8 *aNumActions);
+ NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
+ NS_IMETHOD DoAction(PRUint8 aIndex);
+
+ // nsIAccessibleHyperLink
+ NS_IMETHOD GetURI(PRInt32 aIndex, nsIURI **aURI);
protected:
- void CacheActionContent();
+ enum { eAction_Jump = 0 };
+
};
#endif
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -1280,33 +1280,35 @@ nsXULTreeColumnsAccessible::
nsXULTreeColumnsAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
nsXULColumnsAccessible(aDOMNode, aShell)
{
}
NS_IMETHODIMP
nsXULTreeColumnsAccessible::GetNextSibling(nsIAccessible **aNextSibling)
{
- nsresult ret = nsXULColumnsAccessible::GetNextSibling(aNextSibling);
+ NS_ENSURE_ARG_POINTER(aNextSibling);
+ *aNextSibling = nsnull;
- if (*aNextSibling == nsnull) { // if there is not other sibling, use the first row as its sibling
- nsCOMPtr<nsITreeBoxObject> tree;
- nsCOMPtr<nsITreeView> treeView;
+ nsCOMPtr<nsITreeBoxObject> tree;
+ nsCOMPtr<nsITreeView> treeView;
- nsXULTreeAccessible::GetTreeBoxObject(mDOMNode, getter_AddRefs(tree));
- if (tree) {
- tree->GetView(getter_AddRefs(treeView));
- if (treeView) {
- PRInt32 rowCount;
- treeView->GetRowCount(&rowCount);
- if (rowCount > 0) {
- nsCOMPtr<nsITreeColumn> column = nsXULTreeAccessible::GetFirstVisibleColumn(tree);
- nsCOMPtr<nsIAccessibleTreeCache> treeCache(do_QueryInterface(mParent));
- NS_ENSURE_TRUE(treeCache, NS_ERROR_FAILURE);
- ret = treeCache->GetCachedTreeitemAccessible(0, column, aNextSibling);
- }
+ nsXULTreeAccessible::GetTreeBoxObject(mDOMNode, getter_AddRefs(tree));
+ if (tree) {
+ tree->GetView(getter_AddRefs(treeView));
+ if (treeView) {
+ PRInt32 rowCount;
+ treeView->GetRowCount(&rowCount);
+ if (rowCount > 0) {
+ nsCOMPtr<nsITreeColumn> column =
+ nsXULTreeAccessible::GetFirstVisibleColumn(tree);
+
+ nsCOMPtr<nsIAccessibleTreeCache> treeCache(do_QueryInterface(mParent));
+ NS_ENSURE_TRUE(treeCache, NS_ERROR_FAILURE);
+
+ return treeCache->GetCachedTreeitemAccessible(0, column, aNextSibling);
}
}
}
- return ret;
+ return NS_OK;
}
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -42,16 +42,17 @@ srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = accessible
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES =\
test_bug368835.xul \
+ test_bug420863.html \
test_groupattrs.xul \
test_table_indexes.html \
test_nsIAccessibleTable_1.html \
test_nsIAccessibleTable_2.html \
test_nsIAccessibleTable_3.html \
test_nsIAccessibleTable_listboxes.xul \
$(NULL)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_bug420863.html
@@ -0,0 +1,126 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=420863
+-->
+<head>
+ <title>Table indexes chrome 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">
+ var gAccService = null;
+
+ var gTdClickAttr = false;
+ var gTdClickEventHandler = false;
+ var gClickHandler = null;
+
+ var gID = "";
+ var gNode = null;
+ var gAcc = null;
+
+ function doTest()
+ {
+ const nsIAccessibleRetrieval =
+ Components.interfaces.nsIAccessibleRetrieval;
+
+ gAccService = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+ getService(nsIAccessibleRetrieval);
+
+ // Actions should be exposed on any accessible having related DOM node
+ // with registered 'click' event handler.
+
+ //////////////////////////////////////////////////////////////////////////
+ // generic td
+ gID = "td1";
+ gNode = document.getElementById(gID);
+ gAcc = gAccService.getAccessibleFor(gNode);
+
+ is(gAcc.numActions, 0, gID + ": shouldn't have actions");
+
+ //////////////////////////////////////////////////////////////////////////
+ // td with 'onclick' attribute
+ gID = "td2";
+ gNode = document.getElementById(gID);
+ gAcc = gAccService.getAccessibleFor(gNode);
+
+ is(gAcc.numActions, 1, gID + ": should have one action");
+ is(gAcc.getActionName(0), "click", gID + ": should have 'click' action");
+ gAcc.doAction(0);
+
+ // actions are performed via timeout
+ window.setTimeout(doTest2, 0);
+ }
+
+ function doTest2()
+ {
+ //////////////////////////////////////////////////////////////////////////
+ // td with 'onclick' attribute (sequel, see doTest1())
+ ok(gTdClickAttr, gID + ": 'click' action hasn't been performed");
+
+ //////////////////////////////////////////////////////////////////////////
+ // td with registered 'click' event handler
+ gID = "td3";
+ gNode = document.getElementById(gID);
+ gAcc = gAccService.getAccessibleFor(gNode);
+
+ // register 'click' event handler
+ gClickHandler = {
+ handleEvent: function handleEvent(aEvent)
+ {
+ gTdClickEventHandler = true;
+ }
+ };
+ gNode.addEventListener("click", gClickHandler, false);
+
+ // check actions
+ is(gAcc.numActions, 1, gID + ": should have one action");
+ is(gAcc.getActionName(0), "click", gID + ": should have 'click' action");
+ gAcc.doAction(0);
+
+ // actions are performed via timeout
+ window.setTimeout(doTest3, 0);
+ }
+
+ function doTest3()
+ {
+ //////////////////////////////////////////////////////////////////////////
+ // td with registered 'click' event handler (sequel, see doTest2())
+ ok(gTdClickEventHandler, gID + ": 'click' action hasn't been performed");
+
+ // unregister click event handler
+ gNode.removeEventListener("click", gClickHandler, false);
+
+ // check actions
+ is(gAcc.numActions, 0, gID + ": shouldn't have actions");
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(doTest);
+ </script>
+</head>
+<body>
+
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=420863"
+ title="If an HTML element has an onClick attribute, expose its click action on the element rather than its child text leaf node."
+ target="_blank">Mozilla Bug 420863</a>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+
+ <table>
+ <tr>
+ <td id="td1">Can't click this cell</td>
+ <td onclick="gTdClickAttr = true;"
+ id="td2">Cell with 'onclick' attribute</td>
+ <td id="td3">Cell with registered 'click' event handler</td>
+ </tr>
+ </table>
+
+</body>
+</html>
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -68,17 +68,17 @@ DEFINES += -DAPP_UA_NAME="$(APP_UA_NAME)
DIST_FILES = application.ini
GRE_MILESTONE = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build Milestone)
GRE_BUILDID = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build BuildID)
DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) -DGRE_BUILDID=$(GRE_BUILDID)
ifdef MOZ_MEMORY
-ifneq ($(OS_ARCH),WINNT)
+ifeq ($(OS_ARCH),Darwin)
LIBS += -ljemalloc
endif
endif
ifdef LIBXUL_SDK
include $(topsrcdir)/config/rules.mk
else
# Build a binary bootstrapping with XRE_main
@@ -358,16 +358,19 @@ endif
endif
libs::
touch $(DIST)/bin/.autoreg
libs:: $(srcdir)/profile/prefs.js
$(INSTALL) $^ $(DIST)/bin/defaults/profile
+libs:: $(srcdir)/blocklist.xml
+ $(INSTALL) $^ $(DIST)/bin
+
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
APP_NAME = $(MOZ_APP_DISPLAYNAME)
ifdef MOZ_DEBUG
APP_NAME := $(APP_NAME)Debug
endif
new file mode 100644
--- /dev/null
+++ b/browser/app/blocklist.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
+ <emItems>
+ <emItem id="fdm_ffext@freedownloadmanager.org">
+ <versionRange minVersion="1.0" maxVersion="1.3.1">
+ <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+ <versionRange minVersion="3.0a1" maxVersion="*"/>
+ </targetApplication>
+ </versionRange>
+ </emItem>
+ <emItem id="mozilla_cc@internetdownloadmanager.com">
+ <versionRange minVersion="2.1" maxVersion="3.3">
+ <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+ <versionRange minVersion="3.0a1" maxVersion="*"/>
+ </targetApplication>
+ </versionRange>
+ </emItem>
+ </emItems>
+</blocklist>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -208,16 +208,17 @@ pref("browser.urlbar.clickSelectsAll", t
#endif
#ifdef UNIX_BUT_NOT_MAC
pref("browser.urlbar.doubleClickSelectsAll", true);
#else
pref("browser.urlbar.doubleClickSelectsAll", false);
#endif
pref("browser.urlbar.autoFill", false);
pref("browser.urlbar.matchOnlyTyped", false);
+pref("browser.urlbar.matchOnWordBoundary", true);
pref("browser.urlbar.filter.javascript", true);
// the maximum number of results to show in autocomplete when doing richResults
pref("browser.urlbar.maxRichResults", 25);
// Size of "chunks" affects the number of places to process between each search
// timeout (ms). Too big and the UI will be unresponsive; too small and we'll
// be waiting on the timeout too often without many results.
pref("browser.urlbar.search.chunkSize", 1000);
@@ -232,16 +233,17 @@ pref("browser.download.manager.showWhenS
pref("browser.download.manager.useWindow", true);
pref("browser.download.manager.closeWhenDone", false);
pref("browser.download.manager.openDelay", 0);
pref("browser.download.manager.focusWhenStarting", false);
pref("browser.download.manager.flashCount", 2);
pref("browser.download.manager.addToRecentDocs", true);
pref("browser.download.manager.quitBehavior", 0);
pref("browser.download.manager.scanWhenDone", true);
+pref("browser.download.manager.resumeOnWakeDelay", 10000);
// search engines URL
pref("browser.search.searchEnginesURL", "https://%LOCALE%.add-ons.mozilla.com/%LOCALE%/firefox/%VERSION%/search-engines/");
// pointer to the default engine name
pref("browser.search.defaultenginename", "chrome://browser-region/locale/region.properties");
// disable logging for the search service by default
@@ -317,19 +319,20 @@ pref("browser.tabs.closeButtons", 1);
// true return to the tab that opened this tab (its owner)
// false return to the adjacent tab (old default)
pref("browser.tabs.selectOwnerOnClose", true);
// Default bookmark sorting
pref("browser.bookmarks.sort.direction", "descending");
pref("browser.bookmarks.sort.resource", "rdf:http://home.netscape.com/NC-rdf#Name");
-// By default, do not overwrite bookmarks.html in the profile directory
-// See bug #381216 for details
-pref("browser.bookmarks.overwrite", false);
+// By default, do not export HTML at shutdown.
+// If true, at shutdown the bookmarks in your menu and toolbar will
+// be exported as HTML to the bookmarks.html file.
+pref("browser.bookmarks.autoExportHTML", false);
// Scripts & Windows prefs
pref("dom.disable_open_during_load", true);
#ifdef DEBUG
pref("javascript.options.showInConsole", true);
pref("general.warnOnAboutConfig", false);
#else
pref("javascript.options.showInConsole", false);
@@ -339,16 +342,18 @@ pref("javascript.options.showInConsole",
pref("dom.disable_window_open_feature.status", true);
// This is the pref to control the location bar, change this to true to
// force this instead of or in addition to the status bar - this makes
// the origin of popup windows more obvious to avoid spoofing. We would
// rather not do it by default because it affects UE for web applications, but
// without it there isn't a really good way to prevent chrome spoofing, see bug 337344
pref("dom.disable_window_open_feature.location", true);
pref("dom.disable_window_status_change", true);
+// allow JS to move and resize existing windows
+pref("dom.disable_window_move_resize", false);
// prevent JS from monkeying with window focus, etc
pref("dom.disable_window_flip", true);
// popups.policy 1=allow,2=reject
pref("privacy.popups.policy", 1);
pref("privacy.popups.usecustom", true);
pref("privacy.popups.firstTime", true);
pref("privacy.popups.showBrowserMessage", true);
@@ -626,18 +631,16 @@ pref("browser.sessionstore.interval", 10
// maximum amount of POSTDATA to be saved in bytes per history entry (-1 = all of it)
// (NB: POSTDATA will be saved either entirely or not at all)
pref("browser.sessionstore.postdata", 0);
// on which sites to save text data, POSTDATA and cookies
// 0 = everywhere, 1 = unencrypted sites, 2 = nowhere
pref("browser.sessionstore.privacy_level", 1);
// how many tabs can be reopened (per window)
pref("browser.sessionstore.max_tabs_undo", 10);
-// maximum number of pages of back-history per tab to save
-pref("browser.sessionstore.max_tab_back_history", 10);
// allow META refresh by default
pref("accessibility.blockautorefresh", false);
// import bookmarks.html into Places bookmarks
pref("browser.places.importBookmarksHTML", true);
// if false, will add the "Smart Bookmarks" folder to the personal toolbar
new file mode 100644
index 0000000000000000000000000000000000000000..1c4899aaf72ac0ee9dea01bbe90485f34974ee8d
GIT binary patch
literal 9817
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
R2p$A@krI;^tr9T|_z!F)fe8Qr
new file mode 100644
index 0000000000000000000000000000000000000000..3a1e48d5fac2df3655642322baf5925d00eb87a7
GIT binary patch
literal 2224
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
new file mode 100644
index 0000000000000000000000000000000000000000..44a59d6388af7143cd1cb989eb75c68b812659e0
GIT binary patch
literal 2228
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
CN+>7*
--- a/browser/base/content/aboutRobots.xhtml
+++ b/browser/base/content/aboutRobots.xhtml
@@ -80,17 +80,18 @@
}
}
]]></script>
</head>
<body dir="&locale.dir;">
<!-- PAGE CONTAINER (for styling purposes only) -->
- <div id="errorPageContainer">
+ <div id="errorPageContainer"
+ style="background: url('chrome://browser/content/aboutRobots-icon.png') left 0 no-repeat -moz-Field; -moz-background-origin: content;">
<!-- Error Title -->
<div id="errorTitle">
<h1 id="errorTitleText">&robots.errorTitleText;</h1>
</div>
<!-- LONG CONTENT (the section most likely to require scrolling) -->
<div id="errorLongContent">
@@ -119,12 +120,16 @@
<!-- Button -->
<xul:button xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="errorTryAgain"
label="&retry.label;"
label2="&robots.dontpress;"
oncommand="robotButton();" />
+ <img src="chrome://browser/content/aboutRobots-widget-left.png"
+ style="position: absolute; bottom: -12px; left: -10px;"/>
+ <img src="chrome://browser/content/aboutRobots-widget-right.png"
+ style="position: absolute; bottom: -12px; right: -10px;"/>
</div>
</body>
</html>
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -31,17 +31,17 @@
# 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 *****
- <menubar id="main-menubar" statusbar="statusbar-display"
+ <menubar id="main-menubar"
style="border:0px;padding:0px;margin:0px;-moz-appearance:none">
<menu id="file-menu" label="&fileMenu.label;"
accesskey="&fileMenu.accesskey;">
<menupopup id="menu_FilePopup" onpopupshowing="getContentAreaFrameCount();">
<menuitem id="menu_newNavigator"
label="&newNavigatorCmd.label;"
accesskey="&newNavigatorCmd.accesskey;"
key="key_newNavigator"
@@ -338,17 +338,17 @@
<menuitem hidden="true" id="documentDirection-swap"
label="&bidiSwitchPageDirectionItem.label;"
accesskey="&bidiSwitchPageDirectionItem.accesskey;"
oncommand="SwitchDocumentDirection(window.content)"/>
</menupopup>
</menu>
<menu id="history-menu"
- oncommand="var url = event.target.getAttribute('statustext'); if (url) { PlacesUtils.markPageAsTyped(url); openUILink(url, event, false, true); }"
+ oncommand="var node = event.target.node; if (node) { PlacesUIUtils.markPageAsTyped(node.uri); openUILink(node.uri, event, false, true); }"
onclick="checkForMiddleClick(this, event);"
label="&historyMenu.label;"
accesskey="&historyMenu.accesskey;">
<menupopup id="goPopup"
type="places"
onpopupshowing="HistoryMenu.onPopupShowing(this);"
place="place:type=0&sort=4&maxResults=10">
<menuitem id="historyMenuBack"
@@ -395,17 +395,17 @@
<menu id="bookmarksMenu"
label="&bookmarksMenu.label;" accesskey="&bookmarksMenu.accesskey;"
ondragenter="PlacesMenuDNDController.onBookmarksMenuDragEnter(event);"
ondragdrop="nsDragAndDrop.drop(event, BookmarksMenuDropHandler);"
ondragover="nsDragAndDrop.dragOver(event, BookmarksMenuDropHandler);">
<menupopup id="bookmarksMenuPopup"
type="places"
- place="place:folder=2&expandQueries=1"
+ place="place:folder=BOOKMARKS_MENU&expandQueries=1"
context="placesContext"
openInTabs="children"
oncommand="BookmarksEventHandler.onCommand(event);"
onclick="BookmarksEventHandler.onClick(event);"
onpopupshowing="BookmarksEventHandler.onPopupShowing(event);">
<menuitem label="&bookmarkThisPageCmd.label;"
command="Browser:AddBookmarkAs" key="addBookmarkAsKb"/>
<menuitem id="subscribeToPageMenuitem"
@@ -429,18 +429,16 @@
command="Browser:ShowAllBookmarks"
key="manBookmarkKb"/>
<menu id="bookmarksToolbarFolderMenu"
class="menu-iconic bookmark-item"
container="true">
<menupopup id="bookmarksToolbarFolderPopup"
type="places"
context="placesContext"
- oncommand="BookmarksEventHandler.onCommand(event);"
- onclick="BookmarksEventHandler.onClick(event);"
onpopupshowing="BookmarksEventHandler.onPopupShowing(event);"/>
</menu>
<menuseparator builder="start"/>
</menupopup>
</menu>
<menu id="tools-menu" label="&toolsMenu.label;" accesskey="&toolsMenu.accesskey;">
<menupopup id="menu_ToolsPopup">
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -95,36 +95,42 @@ var StarUI = {
},
// nsIDOMEventListener
handleEvent: function SU_handleEvent(aEvent) {
switch (aEvent.type) {
case "popuphidden":
if (aEvent.originalTarget == this.panel) {
if (!this._element("editBookmarkPanelContent").hidden)
- gEditItemOverlay.uninitPanel(true);
+ this.quitEditMode();
this._restoreCommandsState();
this._itemId = -1;
this._uri = null;
if (this._batching) {
- PlacesUtils.ptm.endBatch();
+ PlacesUIUtils.ptm.endBatch();
this._batching = false;
}
}
break;
case "keypress":
if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE) {
- // In edit mode, the ESC key is mapped to the cancel button
- if (!this._element("editBookmarkPanelContent").hidden)
- this.cancelButtonOnCommand();
- else // otherwise we just hide the panel
+ // In edit mode, if we're not editing a folder, the ESC key is mapped
+ // to the cancel button
+ if (!this._element("editBookmarkPanelContent").hidden) {
+ var elt = aEvent.target;
+ if (elt.localName != "tree" ||
+ (elt.localName == "tree" && !elt.hasAttribute("editing")))
+ this.cancelButtonOnCommand();
+ }
+ }
+ else if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN) {
+ // hide the panel unless the folder tree is focused
+ if (aEvent.target.localName != "tree")
this.panel.hidePopup();
}
- else if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN)
- this.panel.hidePopup(); // hide the panel
break;
}
},
_overlayLoaded: false,
_overlayLoading: false,
showEditBookmarkPopup:
function SU_showEditBookmarkPopup(aItemId, aAnchorElement, aPosition) {
@@ -183,21 +189,21 @@ var StarUI = {
this._itemId = aItemId !== undefined ? aItemId : this._itemId;
this.beginBatch();
// XXXmano hack: We push a no-op transaction on the stack so it's always
// safe for the Cancel button to call undoTransaction after endBatch.
// Otherwise, if no changes were done in the edit-item panel, the last
// transaction on the undo stack may be the initial createItem transaction,
// or worse, the batched editing of some other item.
- PlacesUtils.ptm.doTransaction({ doTransaction: function() { },
- undoTransaction: function() { },
- redoTransaction: function() { },
- isTransient: false,
- merge: function() { return false; } });
+ PlacesUIUtils.ptm.doTransaction({ doTransaction: function() { },
+ undoTransaction: function() { },
+ redoTransaction: function() { },
+ isTransient: false,
+ merge: function() { return false; } });
if (this.panel.state == "closed") {
// Consume dismiss clicks, see bug 400924
this.panel.popupBoxObject
.setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_CONSUME);
this.panel.openPopup(aAnchorElement, aPosition, -1, -1);
}
else {
@@ -236,20 +242,16 @@ var StarUI = {
this._element("editBookmarkPanelTitle").value =
bundle.getString("editBookmarkPanel.pageBookmarkedTitle");
// description
this._element("editBookmarkPanelDescription").textContent =
bundle.getFormattedString("editBookmarkPanel.pageBookmarkedDescription",
[brandShortName]);
- // hide the edit panel and the buttons below to it (Cancel, Done)
- this._element("editBookmarkPanelContent").hidden = true;
- this._element("editBookmarkPanelBottomButtons").hidden = true;
-
// show the "Edit.." button and the Remove Bookmark button, hide the
// undo-remove-bookmark button.
this._element("editBookmarkPanelEditButton").hidden = false;
this._element("editBookmarkPanelRemoveButton").hidden = false;
this._element("editBookmarkPanelUndoRemoveButton").hidden = true;
// unset the unstarred state, if set
this._element("editBookmarkPanelStarIcon").removeAttribute("unstarred");
@@ -260,90 +262,101 @@ var StarUI = {
this.panel.popupBoxObject
.setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_CONSUME);
this.panel.openPopup(aAnchorElement, aPosition, -1, -1);
}
else
this.panel.focus();
},
+ quitEditMode: function SU_quitEditMode() {
+ this._element("editBookmarkPanelContent").hidden = true;
+ this._element("editBookmarkPanelBottomButtons").hidden = true;
+ gEditItemOverlay.uninitPanel(true);
+ },
+
editButtonCommand: function SU_editButtonCommand() {
this.showEditBookmarkPopup();
},
cancelButtonOnCommand: function SU_cancelButtonOnCommand() {
+ // The order here is important! We have to hide the panel first, otherwise
+ // changes done as part of Undo may change the panel contents and by
+ // that force it to commit more transactions
+ this.panel.hidePopup();
this.endBatch();
- PlacesUtils.ptm.undoTransaction();
- this.panel.hidePopup();
+ PlacesUIUtils.ptm.undoTransaction();
},
removeBookmarkButtonCommand: function SU_removeBookmarkButtonCommand() {
#ifdef ADVANCED_STARRING_UI
// In minimal mode ("page bookmarked" notification), the bookmark
// is removed and the panel is hidden immediately. In full edit mode,
// a "Bookmark Removed" notification along with an Undo button is
// shown
if (this._batching) {
- PlacesUtils.ptm.endBatch();
- PlacesUtils.ptm.beginBatch(); // allow undo from within the notification
+ PlacesUIUtils.ptm.endBatch();
+ PlacesUIUtils.ptm.beginBatch(); // allow undo from within the notification
var bundle = this._element("bundle_browser");
// "Bookmark Removed" title (the description field is already empty in
// this mode)
this._element("editBookmarkPanelTitle").value =
bundle.getString("editBookmarkPanel.bookmarkedRemovedTitle");
- // hide the edit fields, the buttons below to and the remove bookmark
- // button. Show the undo-remove-bookmark button.
- this._element("editBookmarkPanelContent").hidden = true;
- this._element("editBookmarkPanelBottomButtons").hidden = true;
+
+ // hide the edit panel
+ this.quitEditMode();
+
+ // Hide the remove bookmark button, show the undo-remove-bookmark
+ // button.
this._element("editBookmarkPanelUndoRemoveButton").hidden = false;
this._element("editBookmarkPanelRemoveButton").hidden = true;
this._element("editBookmarkPanelStarIcon").setAttribute("unstarred", "true");
this.panel.focus();
}
#endif
// cache its uri so we can get the new itemId in the case of undo
this._uri = PlacesUtils.bookmarks.getBookmarkURI(this._itemId);
// remove all bookmarks for the bookmark's url, this also removes
// the tags for the url
var itemIds = PlacesUtils.getBookmarksForURI(this._uri);
for (var i=0; i < itemIds.length; i++) {
- var txn = PlacesUtils.ptm.removeItem(itemIds[i]);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm.removeItem(itemIds[i]);
+ PlacesUIUtils.ptm.doTransaction(txn);
}
#ifdef ADVANCED_STARRING_UI
// hidePopup resets our itemId, thus we call it only after removing
// the bookmark
if (!this._batching)
#endif
this.panel.hidePopup();
},
undoRemoveBookmarkCommand: function SU_undoRemoveBookmarkCommand() {
// restore the bookmark by undoing the last transaction and go back
// to the edit state
this.endBatch();
- PlacesUtils.ptm.undoTransaction();
+ PlacesUIUtils.ptm.undoTransaction();
this._itemId = PlacesUtils.getMostRecentBookmarkForURI(this._uri);
this.showEditBookmarkPopup();
},
beginBatch: function SU_beginBatch() {
if (!this._batching) {
- PlacesUtils.ptm.beginBatch();
+ PlacesUIUtils.ptm.beginBatch();
this._batching = true;
}
},
endBatch: function SU_endBatch() {
if (this._batching) {
- PlacesUtils.ptm.endBatch();
+ PlacesUIUtils.ptm.endBatch();
this._batching = false;
}
}
}
var PlacesCommandHook = {
/**
* Adds a bookmark to the page loaded in the given browser.
@@ -367,33 +380,33 @@ var PlacesCommandHook = {
// no DOMWindow (?) but information about the loaded document
// may still be obtained from the webNavigation.
var webNav = aBrowser.webNavigation;
var url = webNav.currentURI;
var title;
var description;
try {
title = webNav.document.title || url.spec;
- description = PlacesUtils.getDescriptionFromDocument(webNav.document);
+ description = PlacesUIUtils.getDescriptionFromDocument(webNav.document);
}
catch (e) { }
if (aShowEditUI) {
// If we bookmark the page here (i.e. page was not "starred" already)
// but open right into the "edit" state, start batching here, so
// "Cancel" in that state removes the bookmark.
StarUI.beginBatch();
}
var parent = aParent != undefined ?
aParent : PlacesUtils.unfiledBookmarksFolderId;
var descAnno = { name: DESCRIPTION_ANNO, value: description };
- var txn = PlacesUtils.ptm.createItem(uri, parent, -1,
- title, null, [descAnno]);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm.createItem(uri, parent, -1,
+ title, null, [descAnno]);
+ PlacesUIUtils.ptm.doTransaction(txn);
itemId = PlacesUtils.getMostRecentBookmarkForURI(uri);
}
// dock the panel to the star icon when possible, otherwise dock
// it to the content area
if (aBrowser.contentWindow == window.content) {
var starIcon = aBrowser.ownerDocument.getElementById("star-button");
if (starIcon && isElementVisible(starIcon)) {
@@ -427,18 +440,18 @@ var PlacesCommandHook = {
* @param aTitle
* The link text
*/
bookmarkLink: function PCH_bookmarkLink(aParent, aURL, aTitle) {
var linkURI = makeURI(aURL);
var itemId = PlacesUtils.getMostRecentBookmarkForURI(linkURI);
if (itemId == -1) {
StarUI.beginBatch();
- var txn = PlacesUtils.ptm.createItem(linkURI, aParent, -1, aTitle);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm.createItem(linkURI, aParent, -1, aTitle);
+ PlacesUIUtils.ptm.doTransaction(txn);
itemId = PlacesUtils.getMostRecentBookmarkForURI(linkURI);
}
StarUI.showEditBookmarkPopup(itemId, getBrowser(), "overlap");
},
/**
* This function returns a list of nsIURI objects characterizing the
@@ -469,17 +482,17 @@ var PlacesCommandHook = {
},
/**
* Adds a folder with bookmarks to all of the currently open tabs in this
* window.
*/
bookmarkCurrentPages: function PCH_bookmarkCurrentPages() {
var tabURIs = this._getUniqueTabInfo();
- PlacesUtils.showMinimalAddMultiBookmarkUI(tabURIs);
+ PlacesUIUtils.showMinimalAddMultiBookmarkUI(tabURIs);
},
/**
* Adds a Live Bookmark to a feed associated with the current page.
* @param url
* The nsIURI of the page the feed was attached to
* @title title
@@ -495,22 +508,22 @@ var PlacesCommandHook = {
var doc = gBrowser.contentDocument;
var title = (arguments.length > 1) ? feedTitle : doc.title;
var description;
if (arguments.length > 2)
description = feedSubtitle;
else
- description = PlacesUtils.getDescriptionFromDocument(doc);
+ description = PlacesUIUtils.getDescriptionFromDocument(doc);
var toolbarIP =
new InsertionPoint(PlacesUtils.bookmarks.toolbarFolder, -1);
- PlacesUtils.showMinimalAddLivemarkUI(feedURI, gBrowser.currentURI,
- title, description, toolbarIP, true);
+ PlacesUIUtils.showMinimalAddLivemarkUI(feedURI, gBrowser.currentURI,
+ title, description, toolbarIP, true);
},
/**
* Opens the Places Organizer.
* @param aLeftPaneRoot
* The query to select in the organizer window - options
* are: History, AllBookmarks, BookmarksMenu, BookmarksToolbar,
* UnfiledBookmarks and Tags.
@@ -564,73 +577,68 @@ var HistoryMenu = {
/**
* Functions for handling events in the Bookmarks Toolbar and menu.
*/
var BookmarksEventHandler = {
/**
* Handler for click event for an item in the bookmarks toolbar or menu.
* Menus and submenus from the folder buttons bubble up to this handler.
- * Only handle middle-click; left-click is handled in the onCommand function.
- * When items are middle-clicked, open them in tabs.
+ * Left-click is handled in the onCommand function.
+ * When items are middle-clicked (or clicked with modifier), open in tabs.
* If the click came through a menu, close the menu.
* @param aEvent
* DOMEvent for the click
*/
onClick: function BT_onClick(aEvent) {
- // Only handle middle-clicks.
- if (aEvent.button != 1)
+ // Only handle middle-click or left-click with modifiers.
+#ifdef XP_MACOSX
+ var modifKey = aEvent.metaKey || aEvent.shiftKey;
+#else
+ var modifKey = aEvent.ctrlKey || aEvent.shiftKey;
+#endif
+ if (aEvent.button == 2 || (aEvent.button == 0 && !modifKey))
return;
var target = aEvent.originalTarget;
- var view = PlacesUtils.getViewForNode(target);
- if (target.node && PlacesUtils.nodeIsFolder(target.node)) {
+ // If this event bubbled up from a menu or menuitem, close the menus.
+ // Do this before opening tabs, to avoid hiding the open tabs confirm-dialog.
+ if (target.localName == "menu" || target.localName == "menuitem") {
+ for (node = target.parentNode; node; node = node.parentNode) {
+ if (node.localName == "menupopup")
+ node.hidePopup();
+ else if (node.localName != "menu")
+ break;
+ }
+ }
+
+ if (target.node && PlacesUtils.nodeIsContainer(target.node)) {
// Don't open the root folder in tabs when the empty area on the toolbar
// is middle-clicked or when a non-bookmark item except for Open in Tabs)
// in a bookmarks menupopup is middle-clicked.
if (target.localName == "menu" || target.localName == "toolbarbutton")
- PlacesUtils.openContainerNodeInTabs(target.node, aEvent);
+ PlacesUIUtils.openContainerNodeInTabs(target.node, aEvent);
}
- else
+ else if (aEvent.button == 1) {
+ // left-clicks with modifier are already served by onCommand
this.onCommand(aEvent);
-
- // If this event bubbled up from a menu or menuitem,
- // close the menus.
- if (target.localName == "menu" ||
- target.localName == "menuitem") {
- var node = target.parentNode;
- while (node &&
- (node.localName == "menu" ||
- node.localName == "menupopup")) {
- if (node.localName == "menupopup")
- node.hidePopup();
-
- node = node.parentNode;
- }
}
- // The event target we get if someone middle clicks on a bookmark in the
- // bookmarks toolbar overflow menu is different from if they click on a
- // bookmark in a folder or in the bookmarks menu; handle this case
- // separately.
- var bookmarksBar = document.getElementById("bookmarksBarContent");
- if (bookmarksBar._chevron.getAttribute("open") == "true")
- bookmarksBar._chevron.firstChild.hidePopup();
},
/**
* Handler for command event for an item in the bookmarks toolbar.
* Menus and submenus from the folder buttons bubble up to this handler.
* Opens the item.
* @param aEvent
* DOMEvent for the command
*/
onCommand: function BM_onCommand(aEvent) {
var target = aEvent.originalTarget;
if (target.node)
- PlacesUtils.openNodeWithEvent(target.node, aEvent);
+ PlacesUIUtils.openNodeWithEvent(target.node, aEvent);
},
/**
* Handler for popupshowing event for an item in bookmarks toolbar or menu.
* If the item isn't the main bookmarks menu, add an "Open All in Tabs"
* menuitem to the bottom of the popup.
* @param event
* DOMEvent for popupshowing
@@ -698,27 +706,29 @@ var BookmarksEventHandler = {
"openUILink(this.getAttribute('siteURI'), event);");
// If a user middle-clicks this item we serve the oncommand event
// We are using checkForMiddleClick because of Bug 246720
// Note: stopPropagation is needed to avoid serving middle-click
// with BT_onClick that would open all items in tabs
target._endOptOpenSiteURI.setAttribute("onclick",
"checkForMiddleClick(this, event); event.stopPropagation();");
target._endOptOpenSiteURI.setAttribute("label",
- PlacesUtils.getFormattedString("menuOpenLivemarkOrigin.label",
+ PlacesUIUtils.getFormattedString("menuOpenLivemarkOrigin.label",
[target.parentNode.getAttribute("label")]));
target.appendChild(target._endOptOpenSiteURI);
}
if (hasMultipleURIs && !target._endOptOpenAllInTabs) {
// Add the "Open All in Tabs" menuitem if there are
// at least two menuitems with places result nodes.
target._endOptOpenAllInTabs = document.createElement("menuitem");
target._endOptOpenAllInTabs.setAttribute("oncommand",
- "PlacesUtils.openContainerNodeInTabs(this.parentNode._resultNode, event);");
+ "PlacesUIUtils.openContainerNodeInTabs(this.parentNode._resultNode, event);");
+ target._endOptOpenAllInTabs.setAttribute("onclick",
+ "checkForMiddleClick(this, event); event.stopPropagation();");
target._endOptOpenAllInTabs.setAttribute("label",
gNavigatorBundle.getString("menuOpenAllInTabs.label"));
target.appendChild(target._endOptOpenAllInTabs);
}
},
fillInBTTooltip: function(aTipElement) {
// Fx2XP: Don't show tooltips for bookmarks under sub-folders
@@ -779,17 +789,18 @@ var BookmarksMenuDropHandler = {
* @param event
* A dragover event
* @param session
* The active DragSession
* @returns true if the user can drop onto the Bookmarks Menu item, false
* otherwise.
*/
canDrop: function BMDH_canDrop(event, session) {
- return PlacesControllerDragHelper.canDrop();
+ var ip = new InsertionPoint(PlacesUtils.bookmarksMenuFolderId, -1);
+ return ip && PlacesControllerDragHelper.canDrop(ip);
},
/**
* Called when the user drops onto the top level Bookmarks Menu item.
* @param event
* A drop event
* @param data
* Data that was dropped
@@ -1009,33 +1020,32 @@ function placesMigrationTasks() {
// Remove the old annotation.
annosvc.removePageAnnotation(uri, oldPostDataAnno);
} catch(ex) {}
}
gPrefService.setBoolPref("browser.places.migratePostDataAnnotations", false);
}
if (gPrefService.getBoolPref("browser.places.updateRecentTagsUri")) {
- var bmsvc = PlacesUtils.bookmarks;
- var tagsFolder = bmsvc.tagsFolder;
- var oldUriSpec = "place:folder=" + tagsFolder + "&group=3&queryType=1"+
+ var oldUriSpec = "place:folder=TAGS&group=3&queryType=1" +
"&applyOptionsToContainers=1&sort=12&maxResults=10";
var maxResults = 10;
var newUriSpec = "place:type=" +
Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
"&sort=" +
Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_DESCENDING +
"&maxResults=" + maxResults;
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var oldUri = ios.newURI(oldUriSpec, null, null);
var newUri = ios.newURI(newUriSpec, null, null);
+ let bmsvc = PlacesUtils.bookmarks;
let bookmarks = bmsvc.getBookmarkIdsForURI( oldUri, {});
for (let i = 0; i < bookmarks.length; i++) {
bmsvc.changeBookmarkURI( bookmarks[i], newUri);
}
gPrefService.setBoolPref("browser.places.updateRecentTagsUri", false);
}
}
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2635,17 +2635,17 @@ function openHomeDialog(aURL)
}
var bookmarksButtonObserver = {
onDrop: function (aEvent, aXferData, aDragSession)
{
var split = aXferData.data.split("\n");
var url = split[0];
if (url != aXferData.data) // do nothing if it's not a valid URL
- PlacesUtils.showMinimalAddBookmarkUI(makeURI(url), split[1]);
+ PlacesUIUtils.showMinimalAddBookmarkUI(makeURI(url), split[1]);
},
onDragOver: function (aEvent, aFlavour, aDragSession)
{
var statusTextFld = document.getElementById("statusbar-display");
statusTextFld.label = gNavigatorBundle.getString("droponbookmarksbutton");
aDragSession.dragAction = Components.interfaces.nsIDragService.DRAGDROP_ACTION_LINK;
},
@@ -3110,17 +3110,17 @@ function addToUrlbarHistory(aUrlToAdd)
{
if (!aUrlToAdd)
return;
if (aUrlToAdd.search(/[\x00-\x1F]/) != -1) // don't store bad URLs
return;
try {
if (aUrlToAdd.indexOf(" ") == -1) {
- PlacesUtils.markPageAsTyped(aUrlToAdd);
+ PlacesUIUtils.markPageAsTyped(aUrlToAdd);
}
}
catch(ex) {
}
}
function toJavaScriptConsole()
{
@@ -3413,16 +3413,17 @@ var FullScreen =
if (fullScrToggler) {
fullScrToggler.removeEventListener("mouseover", this._expandCallback, false);
fullScrToggler.removeEventListener("dragenter", this._expandCallback, false);
}
// The user may quit fullscreen during an animation
clearInterval(this._animationInterval);
+ clearTimeout(this._animationTimeout);
getNavToolbox().style.marginTop = "0px";
if (this._isChromeCollapsed)
this.mouseoverToggle(true);
this._isAnimating = false;
// This is needed if they use the context menu to quit fullscreen
this._isPopupOpen = false;
gBrowser.mPanelContainer.removeEventListener("mousemove",
@@ -3513,16 +3514,17 @@ var FullScreen =
setAutohide: function()
{
gPrefService.setBoolPref("browser.fullscreen.autohide", !gPrefService.getBoolPref("browser.fullscreen.autohide"));
},
// Animate the toolbars disappearing
_shouldAnimate: true,
_isAnimating: false,
+ _animationTimeout: null,
_animationInterval: null,
_animateUp: function()
{
// check again, the user may have done something before the animation was due to start
if (!window.fullScreen || !FullScreen._safeToCollapse(false)) {
FullScreen._isAnimating = false;
FullScreen._shouldAnimate = true;
return;
@@ -3563,17 +3565,17 @@ var FullScreen =
// 1 - animate only for first collapse after entering fullscreen (default for perf's sake)
// 2 - animate every time it collapses
if (gPrefService.getIntPref("browser.fullscreen.animateUp") == 0)
this._shouldAnimate = false;
if (!aShow && this._shouldAnimate) {
this._isAnimating = true;
this._shouldAnimate = false;
- setTimeout(this._animateUp, 800);
+ this._animationTimeout = setTimeout(this._animateUp, 800);
return;
}
// The chrome is collapsed so don't spam needless mousemove events
if (aShow) {
gBrowser.mPanelContainer.addEventListener("mousemove",
this._collapseCallback, false);
}
@@ -4775,19 +4777,19 @@ function asyncOpenWebPanel(event)
loadURI(url, null, postData.value, false);
event.preventDefault();
return false;
}
else if (linkNode.getAttribute("rel") == "sidebar") {
// This is the Opera convention for a special link that - when clicked - allows
// you to add a sidebar panel. We support the Opera convention here. The link's
// title attribute contains the title that should be used for the sidebar panel.
- PlacesUtils.showMinimalAddBookmarkUI(makeURI(wrapper.href),
- wrapper.getAttribute("title"),
- null, null, true, true);
+ PlacesUIUtils.showMinimalAddBookmarkUI(makeURI(wrapper.href),
+ wrapper.getAttribute("title"),
+ null, null, true, true);
event.preventDefault();
return false;
}
else if (target == "_search") {
// Used in WinIE as a way of transiently loading pages in a sidebar. We
// mimic that WinIE functionality here and also load the page transiently.
// DISALLOW_INHERIT_PRINCIPAL is used here in order to also
@@ -5741,19 +5743,19 @@ function AddKeywordForSearchField()
var postData;
if (isURLEncoded)
postData = formData.join("&");
else
spec += "?" + formData.join("&");
- var description = PlacesUtils.getDescriptionFromDocument(node.ownerDocument);
- PlacesUtils.showMinimalAddBookmarkUI(makeURI(spec), "", description, null,
- null, null, "", postData);
+ var description = PlacesUIUtils.getDescriptionFromDocument(node.ownerDocument);
+ PlacesUIUtils.showMinimalAddBookmarkUI(makeURI(spec), "", description, null,
+ null, null, "", postData);
}
function SwitchDocumentDirection(aWindow) {
aWindow.document.dir = (aWindow.document.dir == "ltr" ? "rtl" : "ltr");
for (var run = 0; run < aWindow.frames.length; run++)
SwitchDocumentDirection(aWindow.frames[run]);
}
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -286,17 +286,17 @@
command="Browser:Reload"
tooltiptext="&reloadButton.tooltip;"/>
<toolbarbutton id="stop-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
label="&stopCmd.label;"
command="Browser:Stop"
tooltiptext="&stopButton.tooltip;"/>
- <toolbarbutton id="home-button" class="bookmark-item chromeclass-toolbar-additional"
+ <toolbarbutton id="home-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
persist="class"
label="&homeButton.label;"
ondragover="nsDragAndDrop.dragOver(event, homeButtonObserver);"
ondragdrop="nsDragAndDrop.drop(event, homeButtonObserver);"
ondragexit="nsDragAndDrop.dragExit(event, homeButtonObserver);"
onclick="BrowserGoHome(event);"/>
<toolbaritem id="urlbar-container" align="center" flex="400" persist="width"
@@ -446,19 +446,19 @@
</toolbarpalette>
<toolbar id="nav-bar" class="toolbar-primary chromeclass-toolbar"
toolbarname="&navbarCmd.label;" accesskey="&navbarCmd.accesskey;"
fullscreentoolbar="true" mode="icons" iconsize="large"
customizable="true"
#ifdef XP_MACOSX
- defaultset="unified-back-forward-button,reload-button,stop-button,urlbar-container,search-container,throbber-box"
+ defaultset="unified-back-forward-button,reload-button,stop-button,home-button,urlbar-container,search-container,throbber-box"
#else
- defaultset="unified-back-forward-button,reload-button,stop-button,urlbar-container,search-container,fullscreenflex,window-controls"
+ defaultset="unified-back-forward-button,reload-button,stop-button,home-button,urlbar-container,search-container,fullscreenflex,window-controls"
#endif
context="toolbar-context-menu">
#ifndef XP_MACOSX
<hbox id="fullscreenflex" flex="1" hidden="true" fullscreencontrol="true"/>
<hbox id="window-controls" hidden="true" fullscreencontrol="true">
<toolbarbutton id="minimize-button" class="toolbarbutton-1"
tooltiptext="&fullScreenMinimize.tooltip;"
oncommand="window.minimize();"/>
@@ -475,17 +475,17 @@
</toolbar>
<toolbarset id="customToolbars" context="toolbar-context-menu"/>
<toolbar id="PersonalToolbar"
mode="icons" iconsize="small" defaulticonsize="small"
class="chromeclass-directories"
context="toolbar-context-menu"
- defaultset="home-button,personal-bookmarks"
+ defaultset="personal-bookmarks"
toolbarname="&personalbarCmd.label;" accesskey="&personalbarCmd.accesskey;"
customizable="true"/>
</toolbox>
<hbox flex="1" id="browser">
<vbox id="sidebar-box" hidden="true" class="chromeclass-extrachrome">
<sidebarheader align="center">
<label id="sidebar-title" persist="value" flex="1" crop="end" control="sidebar"/>
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -1186,23 +1186,23 @@ nsContextMenu.prototype = {
addBookmarkForFrame: function CM_addBookmarkForFrame() {
var doc = this.target.ownerDocument;
var uri = doc.documentURIObject;
var itemId = PlacesUtils.getMostRecentBookmarkForURI(uri);
if (itemId == -1) {
var title = doc.title;
- var description = PlacesUtils.getDescriptionFromDocument(doc);
+ var description = PlacesUIUtils.getDescriptionFromDocument(doc);
var descAnno = { name: DESCRIPTION_ANNO, value: description };
- var txn = PlacesUtils.ptm.createItem(uri,
+ var txn = PlacesUIUtils.ptm.createItem(uri,
PlacesUtils.bookmarksMenuFolderId,
-1, title, null, [descAnno]);
- PlacesUtils.ptm.doTransaction(txn);
+ PlacesUIUtils.ptm.doTransaction(txn);
itemId = PlacesUtils.getMostRecentBookmarkForURI(uri);
StarUI.beginBatch();
}
window.top.StarUI.showEditBookmarkPopup(itemId, this.browser, "overlap");
},
savePageAs: function CM_savePageAs() {
--- a/browser/base/content/test/browser_getshortcutoruri.js
+++ b/browser/base/content/test/browser_getshortcutoruri.js
@@ -67,17 +67,17 @@ var testData = [
new keywordResult("http://searchpostget/?search1=foo6", "search2=foo6")],
// Bookmark keywords that don't take parameters should not be activated if a
// parameter is passed (bug 420328).
[new bmKeywordData("bmget-noparam", "http://bmget-noparam/", null, "foo7"),
new keywordResult(null, null)],
[new bmKeywordData("bmpost-noparam", "http://bmpost-noparam/", "not_a=param", "foo8"),
new keywordResult(null, null)],
-
+
// Test escaping (%s = escaped, %S = raw)
// UTF-8 default
[new bmKeywordData("bmget-escaping", "http://bmget/?esc=%s&raw=%S", null, "foé"),
new keywordResult("http://bmget/?esc=fo%C3%A9&raw=foé", null)],
// Explicitly-defined ISO-8859-1
[new bmKeywordData("bmget-escaping2", "http://bmget/?esc=%s&raw=%S&mozcharset=ISO-8859-1", null, "foé"),
new keywordResult("http://bmget/?esc=fo%E9&raw=foé", null)],
];
@@ -103,26 +103,26 @@ function test() {
cleanupKeywords();
}
var gBMFolder = null;
var gAddedEngines = [];
function setupKeywords() {
var searchService = Cc["@mozilla.org/browser/search-service;1"].
getService(Ci.nsIBrowserSearchService);
- gBMFolder = Application.bookmarks.addFolder("keyword-test");
+ gBMFolder = Application.bookmarks.menu.addFolder("keyword-test");
for each (var item in testData) {
var data = item[0];
if (data instanceof bmKeywordData) {
var bm = gBMFolder.addBookmark(data.keyword, data.uri);
bm.keyword = data.keyword;
if (data.postData)
bm.annotations.set("bookmarkProperties/POSTData", data.postData, Ci.nsIAnnotationService.EXPIRE_SESSION);
}
-
+
if (data instanceof searchKeywordData) {
searchService.addEngineWithDetails(data.keyword, "", data.keyword, "", data.method, data.uri.spec);
var addedEngine = searchService.getEngineByName(data.keyword);
if (data.postData) {
var [paramName, paramValue] = data.postData.split("=");
addedEngine.addParam(paramName, paramValue, null);
}
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -9,16 +9,19 @@ browser.jar:
% overlay chrome://global/content/viewSource.xul chrome://browser/content/viewSourceOverlay.xul
% overlay chrome://global/content/viewPartialSource.xul chrome://browser/content/viewSourceOverlay.xul
% style chrome://global/content/customizeToolbar.xul chrome://browser/content/browser.css
% style chrome://global/content/customizeToolbar.xul chrome://browser/skin/
* content/browser/aboutDialog.xul (content/aboutDialog.xul)
* content/browser/aboutDialog.js (content/aboutDialog.js)
content/browser/aboutDialog.css (content/aboutDialog.css)
* content/browser/aboutRobots.xhtml (content/aboutRobots.xhtml)
+ content/browser/aboutRobots-icon.png (content/aboutRobots-icon.png)
+ content/browser/aboutRobots-widget-left.png (content/aboutRobots-widget-left.png)
+ content/browser/aboutRobots-widget-right.png (content/aboutRobots-widget-right.png)
* content/browser/browser.css (content/browser.css)
* content/browser/browser.js (content/browser.js)
* content/browser/browser.xul (content/browser.xul)
* content/browser/credits.xhtml (content/credits.xhtml)
* content/browser/EULA.js (content/EULA.js)
* content/browser/EULA.xhtml (content/EULA.xhtml)
* content/browser/EULA.xul (content/EULA.xul)
* content/browser/metaData.js (content/metaData.js)
--- a/browser/components/migration/content/migration.js
+++ b/browser/components/migration/content/migration.js
@@ -153,17 +153,17 @@ var MigrationWizard = {
onImportSourcePageAdvanced: function ()
{
var newSource = document.getElementById("importSourceGroup").selectedItem.id;
if (newSource == "nothing" || newSource == "fromfile") {
if(newSource == "fromfile")
window.opener.fromFile = true;
document.documentElement.cancel();
- return;
+ return false;
}
if (!this._migrator || (newSource != this._source)) {
// Create the migrator for the selected source.
var contractID = kProfileMigratorContractIDPrefix + newSource;
this._migrator = Components.classes[contractID].createInstance(kIMig);
this._itemsFlags = kIMig.ALL;
--- a/browser/components/migration/content/migration.xul
+++ b/browser/components/migration/content/migration.xul
@@ -51,17 +51,17 @@
<script type="application/x-javascript" src="chrome://browser/content/migration/migration.js"/>
<stringbundle id="bundle" src="chrome://browser/locale/migration/migration.properties"/>
<stringbundle id="brandBundle" src="chrome://branding/locale/brand.properties"/>
<wizardpage id="importSource" pageid="importSource" next="selectProfile"
label="&importSource.title;"
- onpageadvanced="MigrationWizard.onImportSourcePageAdvanced();">
+ onpageadvanced="return MigrationWizard.onImportSourcePageAdvanced();">
#ifdef XP_WIN
<description id="importAll" control="importSourceGroup">&importFrom.label;</description>
#else
<description id="importAll" control="importSourceGroup">&importFromUnix.label;</description>
#endif
<description id="importBookmarks" control="importSourceGroup" hidden="true">&importFromBookmarks.label;</description>
<radiogroup id="importSourceGroup" align="start">
--- a/browser/components/migration/src/nsOperaProfileMigrator.cpp
+++ b/browser/components/migration/src/nsOperaProfileMigrator.cpp
@@ -312,16 +312,18 @@ nsOperaProfileMigrator::GetSourceHomePag
#define _OPM(type) nsOperaProfileMigrator::type
static
nsOperaProfileMigrator::PrefTransform gTransforms[] = {
{ "User Prefs", "Download Directory", _OPM(STRING), "browser.download.dir", _OPM(SetFile), PR_FALSE, -1 },
{ nsnull, "Enable Cookies", _OPM(INT), "network.cookie.cookieBehavior", _OPM(SetCookieBehavior), PR_FALSE, -1 },
{ nsnull, "Accept Cookies Session Only", _OPM(BOOL), "network.cookie.lifetimePolicy", _OPM(SetCookieLifetime), PR_FALSE, -1 },
+ { nsnull, "Allow script to resize window", _OPM(BOOL), "dom.disable_window_move_resize", _OPM(SetBool), PR_FALSE, -1 },
+ { nsnull, "Allow script to move window", _OPM(BOOL), "dom.disable_window_move_resize", _OPM(SetBool), PR_FALSE, -1 },
{ nsnull, "Allow script to raise window", _OPM(BOOL), "dom.disable_window_flip", _OPM(SetBool), PR_FALSE, -1 },
{ nsnull, "Allow script to change status", _OPM(BOOL), "dom.disable_window_status_change", _OPM(SetBool), PR_FALSE, -1 },
{ nsnull, "Ignore Unrequested Popups", _OPM(BOOL), "dom.disable_open_during_load", _OPM(SetBool), PR_FALSE, -1 },
{ nsnull, "Load Figures", _OPM(BOOL), "permissions.default.image", _OPM(SetImageBehavior), PR_FALSE, -1 },
{ "Visited link", nsnull, _OPM(COLOR), "browser.visited_color", _OPM(SetString), PR_FALSE, -1 },
{ "Link", nsnull, _OPM(COLOR), "browser.anchor_color", _OPM(SetString), PR_FALSE, -1 },
{ nsnull, "Underline", _OPM(BOOL), "browser.underline_anchors", _OPM(SetBool), PR_FALSE, -1 },
--- a/browser/components/migration/src/nsSafariProfileMigrator.cpp
+++ b/browser/components/migration/src/nsSafariProfileMigrator.cpp
@@ -69,16 +69,17 @@
#include <Carbon/Carbon.h>
#define SAFARI_PREFERENCES_FILE_NAME NS_LITERAL_STRING("com.apple.Safari.plist")
#define SAFARI_BOOKMARKS_FILE_NAME NS_LITERAL_STRING("Bookmarks.plist")
#define SAFARI_HISTORY_FILE_NAME NS_LITERAL_STRING("History.plist")
#define SAFARI_COOKIES_FILE_NAME NS_LITERAL_STRING("Cookies.plist")
#define SAFARI_COOKIE_BEHAVIOR_FILE_NAME NS_LITERAL_STRING("com.apple.WebFoundation.plist")
#define SAFARI_DATE_OFFSET 978307200
+#define SAFARI_HOME_PAGE_PREF "HomePage"
#define MIGRATION_BUNDLE "chrome://browser/locale/migration/migration.properties"
///////////////////////////////////////////////////////////////////////////////
// nsSafariProfileMigrator
NS_IMPL_ISUPPORTS1(nsSafariProfileMigrator, nsIBrowserProfileMigrator)
nsSafariProfileMigrator::nsSafariProfileMigrator()
@@ -202,43 +203,16 @@ nsSafariProfileMigrator::GetSourceHasMul
NS_IMETHODIMP
nsSafariProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
{
*aResult = nsnull;
return NS_OK;
}
-NS_IMETHODIMP
-nsSafariProfileMigrator::GetSourceHomePageURL(nsACString& aResult)
-{
- aResult.Truncate();
-
- ICInstance internetConfig;
- OSStatus error = ::ICStart(&internetConfig, 'FRFX');
- if (error != noErr)
- return NS_ERROR_FAILURE;
-
- ICAttr dummy;
- Str255 homePagePValue;
- long prefSize = sizeof(homePagePValue);
- error = ::ICGetPref(internetConfig, kICWWWHomePage, &dummy,
- homePagePValue, &prefSize);
- if (error != noErr)
- return NS_ERROR_FAILURE;
-
- char homePageValue[256] = "";
- CopyPascalStringToC((ConstStr255Param)homePagePValue, homePageValue);
- aResult.Assign(homePageValue);
-
- ::ICStop(internetConfig);
-
- return NS_OK;
-}
-
///////////////////////////////////////////////////////////////////////////////
// nsSafariProfileMigrator
CFPropertyListRef CopyPListFromFile(nsILocalFile* aPListFile)
{
PRBool exists;
aPListFile->Exists(&exists);
nsCAutoString filePath;
@@ -1203,8 +1177,48 @@ nsSafariProfileMigrator::CopyOtherData(P
nsCOMPtr<nsIFile> userChromeDir;
NS_GetSpecialDirectory(NS_APP_USER_CHROME_DIR,
getter_AddRefs(userChromeDir));
stylesheetFile->CopyTo(userChromeDir, NS_LITERAL_STRING("userContent.css"));
}
return NS_OK;
}
+
+
+NS_IMETHODIMP
+nsSafariProfileMigrator::GetSourceHomePageURL(nsACString& aResult)
+{
+ aResult.Truncate();
+
+ // Let's first check if there's a home page key in the com.apple.safari file...
+ CFDictionaryRef safariPrefs = CopySafariPrefs();
+ if (GetDictionaryCStringValue(safariPrefs,
+ CFSTR(SAFARI_HOME_PAGE_PREF),
+ aResult, kCFStringEncodingUTF8)) {
+ ::CFRelease(safariPrefs);
+ return NS_OK;
+ }
+
+ ::CFRelease(safariPrefs);
+
+ // Couldn't find the home page in com.apple.safai, time to check
+ // com.apple.internetconfig for this key!
+ ICInstance internetConfig;
+ OSStatus error = ::ICStart(&internetConfig, 'FRFX');
+ if (error != noErr)
+ return NS_ERROR_FAILURE;
+
+ ICAttr dummy;
+ Str255 homePagePValue;
+ long prefSize = sizeof(homePagePValue);
+ error = ::ICGetPref(internetConfig, kICWWWHomePage, &dummy,
+ homePagePValue, &prefSize);
+ if (error != noErr)
+ return NS_ERROR_FAILURE;
+
+ char homePageValue[256] = "";
+ CopyPascalStringToC((ConstStr255Param)homePagePValue, homePageValue);
+ aResult.Assign(homePageValue);
+ ::ICStop(internetConfig);
+
+ return NS_OK;
+}
--- a/browser/components/migration/src/nsSeamonkeyProfileMigrator.cpp
+++ b/browser/components/migration/src/nsSeamonkeyProfileMigrator.cpp
@@ -358,16 +358,17 @@ nsSeamonkeyProfileMigrator::PrefTransfor
MAKESAMETYPEPREFTRANSFORM("security.warn_submit_insecure", Bool),
MAKESAMETYPEPREFTRANSFORM("security.warn_viewing_mixed", Bool),
MAKESAMETYPEPREFTRANSFORM("security.default_personal_cert", String),
MAKESAMETYPEPREFTRANSFORM("security.OSCP.enabled", Int),
MAKESAMETYPEPREFTRANSFORM("security.OSCP.signingCA", String),
MAKESAMETYPEPREFTRANSFORM("security.OSCP.URL", String),
MAKESAMETYPEPREFTRANSFORM("security.enable_java", Bool),
MAKESAMETYPEPREFTRANSFORM("javascript.enabled", Bool),
+ MAKESAMETYPEPREFTRANSFORM("dom.disable_window_move_resize", Bool),
MAKESAMETYPEPREFTRANSFORM("dom.disable_window_flip", Bool),
MAKESAMETYPEPREFTRANSFORM("dom.disable_window_open_feature.status", Bool),
MAKESAMETYPEPREFTRANSFORM("dom.disable_window_status_change", Bool),
MAKESAMETYPEPREFTRANSFORM("dom.disable_image_src_set", Bool),
MAKESAMETYPEPREFTRANSFORM("accessibility.typeaheadfind.autostart", Bool),
MAKESAMETYPEPREFTRANSFORM("accessibility.typeaheadfind.linksonly", Bool),
MAKESAMETYPEPREFTRANSFORM("network.proxy.type", Int),
MAKESAMETYPEPREFTRANSFORM("network.proxy.http", String),
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -42,16 +42,23 @@ const Cc = Components.classes;
const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/distribution.js");
const PREF_EM_NEW_ADDONS_LIST = "extensions.newAddons";
+// Check to see if bookmarks need backing up once per
+// day on 1 hour idle.
+const BOOKMARKS_ARCHIVE_IDLE_TIME = 60 * 60;
+
+// Backup bookmarks once every 24 hours.
+const BOOKMARKS_ARCHIVE_INTERVAL = 86400 * 1000;
+
// Factory object
const BrowserGlueServiceFactory = {
_instance: null,
createInstance: function (outer, iid)
{
if (outer != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
return this._instance == null ?
@@ -103,25 +110,33 @@ BrowserGlue.prototype = {
break;
case "quit-application-requested":
this._onQuitRequest(subject, data);
break;
case "quit-application-granted":
if (this._saveSession) {
this._setPrefToSaveSession();
}
+ this._shutdownPlaces();
+ this.idleService.removeIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
break;
case "session-save":
this._setPrefToSaveSession();
subject.QueryInterface(Ci.nsISupportsPRBool);
subject.data = true;
break;
+ case "idle":
+ if (this.idleService.idleTime > BOOKMARKS_ARCHIVE_IDLE_TIME * 1000) {
+ // Back up bookmarks.
+ this._archiveBookmarks();
+ }
+ break;
}
- }
-,
+ },
+
// initialization (called on application startup)
_init: function()
{
// observer registration
const osvr = Cc['@mozilla.org/observer-service;1'].
getService(Ci.nsIObserverService);
osvr.addObserver(this, "quit-application", false);
osvr.addObserver(this, "xpcom-shutdown", false);
@@ -194,17 +209,17 @@ BrowserGlue.prototype = {
this._initPlaces();
// apply distribution customizations
// prefs are applied in _onAppDefaults()
var distro = new DistributionCustomizer();
distro.applyCustomizations();
// handle any UI migration
- this._migrateUI();
+ // this._migrateUI();
},
// profile shutdown handler (contains profile cleanup routines)
_onProfileShutdown: function()
{
this._shutdownPlaces();
this.Sanitizer.onShutdown();
},
@@ -352,88 +367,128 @@ BrowserGlue.prototype = {
if(typeof(Sanitizer) != "function") { // we should dynamically load the script
Cc["@mozilla.org/moz/jssubscript-loader;1"].
getService(Ci.mozIJSSubScriptLoader).
loadSubScript("chrome://browser/content/sanitize.js", null);
}
return Sanitizer;
},
+ _idleService: null,
+ get idleService() {
+ if (!this._idleService)
+ this._idleService = Cc["@mozilla.org/widget/idleservice;1"].
+ getService(Ci.nsIIdleService);
+ return this._idleService;
+ },
+
/**
* Initialize Places
* - imports the bookmarks html file if bookmarks datastore is empty
*/
_initPlaces: function bg__initPlaces() {
// we need to instantiate the history service before we check the
// the browser.places.importBookmarksHTML pref, as
// nsNavHistory::ForceMigrateBookmarksDB() will set that pref
// if we need to force a migration (due to a schema change)
var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService);
+ var prefBranch = Cc["@mozilla.org/preferences-service;1"].
+ getService(Ci.nsIPrefBranch);
+
var importBookmarks = false;
try {
- var prefBranch = Cc["@mozilla.org/preferences-service;1"].
- getService(Ci.nsIPrefBranch);
importBookmarks = prefBranch.getBoolPref("browser.places.importBookmarksHTML");
} catch(ex) {}
if (!importBookmarks) {
// Call it here for Fx3 profiles created before the Places folder
// has been added, otherwise it's called during import.
this.ensurePlacesDefaultQueriesInitialized();
- return;
}
-
- var dirService = Cc["@mozilla.org/file/directory_service;1"].
- getService(Ci.nsIProperties);
-
- var bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
+ else {
+ // get latest backup
+ Cu.import("resource://gre/modules/utils.js");
+ var bookmarksFile = PlacesUtils.getMostRecentBackup();
- if (bookmarksFile.exists()) {
- // import the file
- try {
- var importer =
- Cc["@mozilla.org/browser/places/import-export-service;1"].
- getService(Ci.nsIPlacesImportExportService);
- importer.importHTMLFromFile(bookmarksFile, true);
- } catch(ex) {
- } finally {
- prefBranch.setBoolPref("browser.places.importBookmarksHTML", false);
+ if (bookmarksFile && bookmarksFile.leafName.match("\.json$")) {
+ // restore a JSON backup
+ PlacesUtils.restoreBookmarksFromJSONFile(bookmarksFile);
}
+ else {
+ // if there's no json backup use bookmarks.html
- // only back up pre-places bookmarks.html if we plan on overwriting it
- if (prefBranch.getBoolPref("browser.bookmarks.overwrite")) {
- // backup pre-places bookmarks.html
- // XXXtodo remove this before betas, after import/export is solid
- var profDir = dirService.get("ProfD", Ci.nsILocalFile);
- var bookmarksBackup = profDir.clone();
- bookmarksBackup.append("bookmarks.preplaces.html");
- if (!bookmarksBackup.exists()) {
- // save old bookmarks.html file as bookmarks.preplaces.html
- try {
- bookmarksFile.copyTo(profDir, "bookmarks.preplaces.html");
- } catch(ex) {
- dump("nsBrowserGlue::_initPlaces(): copy of bookmarks.html to bookmarks.preplaces.html failed: " + ex + "\n");
- }
+ var dirService = Cc["@mozilla.org/file/directory_service;1"].
+ getService(Ci.nsIProperties);
+ var bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
+
+ // import the file
+ try {
+ var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
+ getService(Ci.nsIPlacesImportExportService);
+ importer.importHTMLFromFile(bookmarksFile, true /* overwrite existing */);
+ } finally {
+ prefBranch.setBoolPref("browser.places.importBookmarksHTML", false);
}
}
}
+
+ // Initialize bookmark archiving on idle.
+ // Once a day, either on idle or shutdown, bookmarks are backed up.
+ this.idleService.addIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
},
/**
* Places shut-down tasks
* - back up and archive bookmarks
+ * - export bookmarks as HTML, if so configured
+ *
+ * Note: quit-application-granted notification is received twice
+ * so replace this method with a no-op when first called.
*/
_shutdownPlaces: function bg__shutdownPlaces() {
- // backup bookmarks to bookmarks.html
- var importer =
+ // Backup and archive Places bookmarks.
+ this._archiveBookmarks();
+
+ // Backup bookmarks to bookmarks.html to support apps that depend
+ // on the legacy format.
+ var autoExportHTML = false;
+ try {
+ autoExportHTML = prefs.getIntPref("browser.bookmarks.autoExportHTML");
+ } catch(ex) {}
+
+ if (autoExportHTML) {
Cc["@mozilla.org/browser/places/import-export-service;1"].
- getService(Ci.nsIPlacesImportExportService);
- importer.backupBookmarksFile();
+ getService(Ci.nsIPlacesImportExportService).
+ backupBookmarksFile();
+ }
+ },
+
+ /**
+ * Back up and archive bookmarks
+ */
+ _archiveBookmarks: function nsBrowserGlue__archiveBookmarks() {
+ Cu.import("resource://gre/modules/utils.js");
+
+ var lastBackup = PlacesUtils.getMostRecentBackup();
+
+ // Backup bookmarks if there aren't any backups or
+ // they haven't been backed up in the last 24 hrs.
+ if (!lastBackup ||
+ Date.now() - lastBackup.lastModifiedTime > BOOKMARKS_ARCHIVE_INTERVAL) {
+ var maxBackups = 5;
+ var prefs = Cc["@mozilla.org/preferences-service;1"].
+ getService(Ci.nsIPrefBranch);
+ try {
+ maxBackups = prefs.getIntPref("browser.bookmarks.max_backups");
+ } catch(ex) {}
+
+ PlacesUtils.archiveBookmarksFile(maxBackups, false /* don't force */);
+ }
},
_migrateUI: function bg__migrateUI() {
var prefBranch = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
var migration = 0;
try {
migration = prefBranch.getIntPref("browser.migration.version");
@@ -443,59 +498,22 @@ BrowserGlue.prototype = {
// this code should always migrate pre-FF3 profiles to the current UI state
// grab the localstore.rdf and make changes needed for new UI
this._rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
this._dataSource = this._rdf.GetDataSource("rdf:local-store");
this._dirty = false;
var currentSet = this._rdf.GetResource("currentset");
- var collapsed = this._rdf.GetResource("collapsed");
- var target;
- var moveHome;
- var homePattern = /(?:^|,)home-button(?:$|,)/;
-
- // get an nsIRDFResource for the PersonalToolbar item
- var personalBar = this._rdf.GetResource("chrome://browser/content/browser.xul#PersonalToolbar");
- var personalBarCollapsed = this._getPersist(personalBar, collapsed) == "true";
// get an nsIRDFResource for the nav-bar item
var navBar = this._rdf.GetResource("chrome://browser/content/browser.xul#nav-bar");
- target = this._getPersist(navBar, currentSet);
- if (target) {
- let originalTarget = target;
-
- // move Home if we find it in the nav-bar and the personal toolbar isn't collapsed
- if (!personalBarCollapsed)
- target = target.replace(homePattern, ",");
- moveHome = (target != originalTarget);
-
- // add the new combined back and forward button
- if (!/(?:^|,)unified-back-forward-button(?:$|,)/.test(target))
- target = "unified-back-forward-button," + target;
-
- if (target != originalTarget)
- this._setPersist(navBar, currentSet, target);
- } else {
- // nav-bar doesn't have a currentset, so the defaultset will be used,
- // which means Home will be moved
- moveHome = true;
- }
-
- if (moveHome) {
- // If the personal toolbar has a currentset, add Home. The defaultset will be
- // used otherwise.
- target = this._getPersist(personalBar, currentSet);
- if (target && !homePattern.test(target))
- this._setPersist(personalBar, currentSet, "home-button," + target);
-
- // uncollapse the personal toolbar
- if (personalBarCollapsed)
- this._setPersist(personalBar, collapsed, "false");
- }
+ var target = this._getPersist(navBar, currentSet);
+ if (target && !/(?:^|,)unified-back-forward-button(?:$|,)/.test(target))
+ this._setPersist(navBar, currentSet, "unified-back-forward-button," + target);
// force the RDF to be saved
if (this._dirty)
this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();
// free up the RDF service
this._rdf = null;
this._dataSource = null;
@@ -569,42 +587,39 @@ BrowserGlue.prototype = {
this._placesBundle.GetStringFromName("smartBookmarksFolderTitle");
var mostVisitedTitle =
this._placesBundle.GetStringFromName("mostVisitedTitle");
var recentlyBookmarkedTitle =
this._placesBundle.GetStringFromName("recentlyBookmarkedTitle");
var recentTagsTitle =
this._placesBundle.GetStringFromName("recentTagsTitle");
- var bookmarksMenuFolder = bmsvc.bookmarksMenuFolder;
- var unfiledBookmarksFolder = bmsvc.unfiledBookmarksFolder;
- var toolbarFolder = bmsvc.toolbarFolder;
var defaultIndex = bmsvc.DEFAULT_INDEX;
// index = 0, make it the first folder
- var placesFolder = bmsvc.createFolder(toolbarFolder, smartBookmarksFolderTitle,
+ var placesFolder = bmsvc.createFolder(bmsvc.toolbarFolder, smartBookmarksFolderTitle,
0);
// XXX should this be a pref? see bug #399268
var maxResults = 10;
var mostVisitedItem = bmsvc.insertBookmark(placesFolder,
this._uri("place:queryType=" +
Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY +
"&sort=" +
Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
"&maxResults=" + maxResults),
defaultIndex, mostVisitedTitle);
// excludeQueries=1 so that user created "saved searches"
// and these queries (added automatically) are excluded
var recentlyBookmarkedItem = bmsvc.insertBookmark(placesFolder,
- this._uri("place:folder=" + bookmarksMenuFolder +
- "&folder=" + unfiledBookmarksFolder +
- "&folder=" + toolbarFolder +
+ this._uri("place:folder=BOOKMARKS_MENU" +
+ "&folder=UNFILED_BOOKMARKS" +
+ "&folder=TOOLBAR" +
"&queryType=" + Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
"&sort=" +
Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
"&excludeItemIfParentHasAnnotation=livemark%2FfeedURI" +
"&maxResults=" + maxResults +
"&excludeQueries=1"),
defaultIndex, recentlyBookmarkedTitle);
--- a/browser/components/places/content/bookmarkProperties.js
+++ b/browser/components/places/content/bookmarkProperties.js
@@ -562,18 +562,18 @@ var BookmarkPropertiesPanel = {
if (this._itemType != BOOKMARK_ITEM || !this._bookmarkURI) {
namePicker.selectedItem = userEnteredNameField;
return;
}
var itemToSelect = userEnteredNameField;
try {
this._microsummaries =
- PlacesUtils.microsummaries.getMicrosummaries(this._bookmarkURI,
- this._bookmarkId);
+ PlacesUIUtils.microsummaries.getMicrosummaries(this._bookmarkURI,
+ this._bookmarkId);
}
catch(ex) {
// getMicrosummaries will throw an exception if the page to which the URI
// refers isn't HTML or XML (the only two content types the service knows
// how to summarize).
this._microsummaries = null;
}
if (this._microsummaries) {
@@ -585,18 +585,18 @@ var BookmarkPropertiesPanel = {
var menupopup = namePicker.menupopup;
while (enumerator.hasMoreElements()) {
var microsummary = enumerator.getNext()
.QueryInterface(Ci.nsIMicrosummary);
var menuItem = this._createMicrosummaryMenuItem(microsummary);
if (this._action == ACTION_EDIT &&
- PlacesUtils.microsummaries
- .isMicrosummary(this._bookmarkId, microsummary))
+ PlacesUIUtils.microsummaries
+ .isMicrosummary(this._bookmarkId, microsummary))
itemToSelect = menuItem;
menupopup.appendChild(menuItem);
}
}
this._microsummaries.addObserver(this);
}
@@ -708,29 +708,29 @@ var BookmarkPropertiesPanel = {
* the ID of the textbox element whose contents we'll test
*
* @returns true if the textbox contains a valid URI string, false otherwise
*/
_containsValidURI: function BPP__containsValidURI(aTextboxID) {
try {
var value = this._element(aTextboxID).value;
if (value) {
- var uri = PlacesUtils.createFixedURI(value);
+ var uri = PlacesUIUtils.createFixedURI(value);
return true;
}
} catch (e) { }
return false;
},
/**
* Get an edit title transaction for the item edit/added in the dialog
*/
_getEditTitleTransaction:
function BPP__getEditTitleTransaction(aItemId, aNewTitle) {
- return PlacesUtils.ptm.editItemTitle(aItemId, aNewTitle);
+ return PlacesUIUtils.ptm.editItemTitle(aItemId, aNewTitle);
},
/**
* XXXmano todo:
* 1. Make setAnnotationsForURI unset a given annotation if the value field
* is not set.
* 2. Replace PlacesEditItemDescriptionTransaction and
* PlacesSetLoadInSidebarTransaction transaction with a generic
@@ -808,87 +808,87 @@ var BookmarkPropertiesPanel = {
// title
var newTitle = this._element("userEnteredName").label;
if (newTitle != this._itemTitle)
transactions.push(this._getEditTitleTransaction(itemId, newTitle));
// description
var description = this._element("descriptionTextfield").value;
if (description != this._itemDescription) {
- transactions.push(PlacesUtils.ptm.
+ transactions.push(PlacesUIUtils.ptm.
editItemDescription(itemId, description,
this._itemType != BOOKMARK_ITEM));
}
if (this._itemType == BOOKMARK_ITEM) {
// location
- var url = PlacesUtils.createFixedURI(this._element("editURLBar").value);
+ var url = PlacesUIUtils.createFixedURI(this._element("editURLBar").value);
if (!this._bookmarkURI.equals(url))
- transactions.push(PlacesUtils.ptm.editBookmarkURI(itemId, url));
+ transactions.push(PlacesUIUtils.ptm.editBookmarkURI(itemId, url));
// keyword transactions
var newKeyword = this._element("keywordTextfield").value;
if (newKeyword != this._bookmarkKeyword) {
- transactions.push(PlacesUtils.ptm.
+ transactions.push(PlacesUIUtils.ptm.
editBookmarkKeyword(itemId, newKeyword));
}
// microsummaries
var namePicker = this._element("namePicker");
var newMicrosummary = namePicker.selectedItem.microsummary;
// Only add a microsummary update to the transaction if the
// microsummary has actually changed, i.e. the user selected no
// microsummary, but the bookmark previously had one, or the user
// selected a microsummary which is not the one the bookmark previously
// had.
if ((newMicrosummary == null &&
- PlacesUtils.microsummaries.hasMicrosummary(itemId)) ||
+ PlacesUIUtils.microsummaries.hasMicrosummary(itemId)) ||
(newMicrosummary != null &&
- !PlacesUtils.microsummaries
- .isMicrosummary(itemId, newMicrosummary))) {
+ !PlacesUIUtils.microsummaries
+ .isMicrosummary(itemId, newMicrosummary))) {
transactions.push(
- PlacesUtils.ptm.editBookmarkMicrosummary(itemId, newMicrosummary));
+ PlacesUIUtils.ptm.editBookmarkMicrosummary(itemId, newMicrosummary));
}
// load in sidebar
var loadInSidebarChecked = this._element("loadInSidebarCheckbox").checked;
if (loadInSidebarChecked != this._loadBookmarkInSidebar) {
transactions.push(
- PlacesUtils.ptm.setLoadInSidebar(itemId, loadInSidebarChecked));
+ PlacesUIUtils.ptm.setLoadInSidebar(itemId, loadInSidebarChecked));
}
}
else if (this._itemType == LIVEMARK_CONTAINER) {
var feedURIString = this._element("feedLocationTextfield").value;
- var feedURI = PlacesUtils.createFixedURI(feedURIString);
+ var feedURI = PlacesUIUtils.createFixedURI(feedURIString);
if (!this._feedURI.equals(feedURI)) {
transactions.push(
- PlacesUtils.ptm.editLivemarkFeedURI(this._folderId, feedURI));
+ PlacesUIUtils.ptm.editLivemarkFeedURI(this._folderId, feedURI));
}
// Site Location is empty, we can set its URI to null
var newSiteURIString = this._element("feedSiteLocationTextfield").value;
var newSiteURI = null;
if (newSiteURIString)
- newSiteURI = PlacesUtils.createFixedURI(newSiteURIString);
+ newSiteURI = PlacesUIUtils.createFixedURI(newSiteURIString);
if ((!newSiteURI && this._siteURI) ||
(newSiteURI && (!this._siteURI || !this._siteURI.equals(newSiteURI)))) {
transactions.push(
- PlacesUtils.ptm.editLivemarkSiteURI(this._folderId, newSiteURI));
+ PlacesUIUtils.ptm.editLivemarkSiteURI(this._folderId, newSiteURI));
}
}
// If we have any changes to perform, do them via the
// transaction manager passed by the opener so they can be undone.
if (transactions.length > 0) {
window.arguments[0].performed = true;
var aggregate =
- PlacesUtils.ptm.aggregateTransactions(this._getDialogTitle(), transactions);
- PlacesUtils.ptm.doTransaction(aggregate);
+ PlacesUIUtils.ptm.aggregateTransactions(this._getDialogTitle(), transactions);
+ PlacesUIUtils.ptm.doTransaction(aggregate);
}
},
/**
* [New Item Mode] Get the insertion point details for the new item, given
* dialog state and opening arguments.
*
* The container-identifier and insertion-index are returned separately in
@@ -907,58 +907,58 @@ var BookmarkPropertiesPanel = {
},
/**
* Returns a transaction for creating a new bookmark item representing the
* various fields and opening arguments of the dialog.
*/
_getCreateNewBookmarkTransaction:
function BPP__getCreateNewBookmarkTransaction(aContainer, aIndex) {
- var uri = PlacesUtils.createFixedURI(this._element("editURLBar").value);
+ var uri = PlacesUIUtils.createFixedURI(this._element("editURLBar").value);
var title = this._element("userEnteredName").label;
var keyword = this._element("keywordTextfield").value;
var annotations = [];
var description = this._element("descriptionTextfield").value;
if (description)
annotations.push(this._getDescriptionAnnotation(description));
var loadInSidebar = this._element("loadInSidebarCheckbox").checked;
if (loadInSidebar)
annotations.push(this._getLoadInSidebarAnnotation(true));
var childTransactions = [];
var microsummary = this._element("namePicker").selectedItem.microsummary;
if (microsummary) {
childTransactions.push(
- PlacesUtils.ptm.editBookmarkMicrosummary(-1, microsummary));
+ PlacesUIUtils.ptm.editBookmarkMicrosummary(-1, microsummary));
}
if (this._postData) {
childTransactions.push(
- PlacesUtils.ptm.editBookmarkPostData(-1, this._postData));
+ PlacesUIUtils.ptm.editBookmarkPostData(-1, this._postData));
}
- var transactions = [PlacesUtils.ptm.createItem(uri, aContainer, aIndex,
- title, keyword,
- annotations,
- childTransactions)];
+ var transactions = [PlacesUIUtils.ptm.createItem(uri, aContainer, aIndex,
+ title, keyword,
+ annotations,
+ childTransactions)];
- return PlacesUtils.ptm.aggregateTransactions(this._getDialogTitle(), transactions);
+ return PlacesUIUtils.ptm.aggregateTransactions(this._getDialogTitle(), transactions);
},
/**
* Returns a childItems-transactions array representing the URIList with
* which the dialog has been opened.
*/
_getTransactionsForURIList: function BPP__getTransactionsForURIList() {
var transactions = [];
for (var i = 0; i < this._URIList.length; ++i) {
var uri = this._URIList[i];
var title = this._getURITitleFromHistory(uri);
- transactions.push(PlacesUtils.ptm.createItem(uri, -1, -1, title));
+ transactions.push(PlacesUIUtils.ptm.createItem(uri, -1, -1, title));
}
return transactions;
},
/**
* Returns a transaction for creating a new folder item representing the
* various fields and opening arguments of the dialog.
*/
@@ -968,37 +968,37 @@ var BookmarkPropertiesPanel = {
var annotations = [];
var childItemsTransactions;
if (this._URIList)
childItemsTransactions = this._getTransactionsForURIList();
var description = this._element("descriptionTextfield").value;
if (description)
annotations.push(this._getDescriptionAnnotation(description));
- return PlacesUtils.ptm.createFolder(folderName, aContainer, aIndex,
- annotations, childItemsTransactions);
+ return PlacesUIUtils.ptm.createFolder(folderName, aContainer, aIndex,
+ annotations, childItemsTransactions);
},
/**
* Returns a transaction for creating a new live-bookmark item representing
* the various fields and opening arguments of the dialog.
*/
_getCreateNewLivemarkTransaction:
function BPP__getCreateNewLivemarkTransaction(aContainer, aIndex) {
var feedURIString = this._element("feedLocationTextfield").value;
- var feedURI = PlacesUtils.createFixedURI(feedURIString);
+ var feedURI = PlacesUIUtils.createFixedURI(feedURIString);
var siteURIString = this._element("feedSiteLocationTextfield").value;
var siteURI = null;
if (siteURIString)
- siteURI = PlacesUtils.createFixedURI(siteURIString);
+ siteURI = PlacesUIUtils.createFixedURI(siteURIString);
var name = this._element("namePicker").value;
- return PlacesUtils.ptm.createLivemark(feedURI, siteURI, name,
- aContainer, aIndex);
+ return PlacesUIUtils.ptm.createLivemark(feedURI, siteURI, name,
+ aContainer, aIndex);
},
/**
* Dialog-accept code-path for creating a new item (any type)
*/
_createNewItem: function BPP__getCreateItemTransaction() {
var [container, index] = this._getInsertionPointDetails();
var createTxn;
@@ -1013,17 +1013,17 @@ var BookmarkPropertiesPanel = {
// list
if (container != PlacesUtils.toolbarFolderId &&
container != PlacesUtils.bookmarksMenuFolderId)
this._markFolderAsRecentlyUsed(container);
// perfrom our transaction do via the transaction manager passed by the
// opener so it can be undone.
window.arguments[0].performed = true;
- PlacesUtils.ptm.doTransaction(createTxn);
+ PlacesUIUtils.ptm.doTransaction(createTxn);
},
onNamePickerInput: function BPP_onNamePickerInput() {
this._element("userEnteredName").label = this._element("namePicker").value;
},
toggleTreeVisibility: function BPP_toggleTreeVisibility() {
var expander = this._element("expander");
@@ -1044,17 +1044,17 @@ var BookmarkPropertiesPanel = {
expander.getAttribute("tooltiptextup"));
document.documentElement.buttons = "accept,cancel,extra2";
this._folderTree.collapsed = false;
if (!this._folderTree.place) {
const FOLDER_TREE_PLACE_URI =
"place:excludeItems=1&excludeQueries=1&excludeReadOnlyFolders=1&folder=" +
- PlacesUtils.allBookmarksFolderId;
+ PlacesUIUtils.allBookmarksFolderId;
this._folderTree.place = FOLDER_TREE_PLACE_URI;
}
var currentFolder = this._getFolderIdFromMenuList();
this._folderTree.selectItems([currentFolder]);
this._folderTree.focus();
resizeTo(window.outerWidth, window.outerHeight + this._folderTreeHeight);
--- a/browser/components/places/content/bookmarksPanel.js
+++ b/browser/components/places/content/bookmarksPanel.js
@@ -32,17 +32,17 @@
# 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 init() {
document.getElementById("bookmarks-view").place =
- "place:queryType=1&folder=" + window.top.PlacesUtils.allBookmarksFolderId;
+ "place:queryType=1&folder=" + window.top.PlacesUIUtils.allBookmarksFolderId;
}
function searchBookmarks(aSearchString) {
var tree = document.getElementById('bookmarks-view');
if (!aSearchString)
tree.place = tree.place;
else
tree.applyFilter(aSearchString,
--- a/browser/components/places/content/bookmarksPanel.xul
+++ b/browser/components/places/content/bookmarksPanel.xul
@@ -68,17 +68,17 @@
oncommand="searchBookmarks(this.value);"/>
</hbox>
<tree id="bookmarks-view" class="sidebar-placesTree" type="places"
flex="1"
hidecolumnpicker="true"
context="placesContext"
onkeypress="SidebarUtils.handleTreeKeyPress(event);"
- onclick="SidebarUtils.handleTreeClick(this, event);"
+ onclick="SidebarUtils.handleTreeClick(this, event, true);"
onmousemove="SidebarUtils.handleTreeMouseMove(event);"
onmouseout="SidebarUtils.clearURLFromStatusBar();">
<treecols>
<treecol id="title" flex="1" primary="true" hideheader="true"/>
</treecols>
<treechildren id="bookmarks-view-children" view="bookmarks-view" class="sidebar-placesTreechildren" flex="1"/>
</tree>
</page>
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -34,17 +34,17 @@
* 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 ***** */
// XXXmano: we should move most/all of these constants to PlacesUtils
-const ORGANIZER_ROOT_BOOKMARKS = "place:folder=2&excludeItems=1&queryType=1";
+const ORGANIZER_ROOT_BOOKMARKS = "place:folder=BOOKMARKS_MENU&excludeItems=1&queryType=1";
const ORGANIZER_SUBSCRIPTIONS_QUERY = "place:annotation=livemark%2FfeedURI";
// No change to the view, preserve current selection
const RELOAD_ACTION_NOTHING = 0;
// Inserting items new to the view, select the inserted rows
const RELOAD_ACTION_INSERT = 1;
// Removing items from the view, select the first item after the last selected
const RELOAD_ACTION_REMOVE = 2;
@@ -98,19 +98,19 @@ PlacesController.prototype = {
/**
* The places view.
*/
_view: null,
isCommandEnabled: function PC_isCommandEnabled(aCommand) {
switch (aCommand) {
case "cmd_undo":
- return PlacesUtils.ptm.numberOfUndoItems > 0;
+ return PlacesUIUtils.ptm.numberOfUndoItems > 0;
case "cmd_redo":
- return PlacesUtils.ptm.numberOfRedoItems > 0;
+ return PlacesUIUtils.ptm.numberOfRedoItems > 0;
case "cmd_cut":
case "cmd_delete":
return this._hasRemovableSelection(false);
case "placesCmd_moveBookmarks":
return this._hasRemovableSelection(true);
case "cmd_copy":
return this._view.hasSelection;
case "cmd_paste":
@@ -147,17 +147,17 @@ PlacesController.prototype = {
(PlacesUtils.nodeIsBookmark(selectedNode) &&
!PlacesUtils.nodeIsLivemarkItem(selectedNode)))
return true;
}
return false;
case "placesCmd_reloadMicrosummary":
var selectedNode = this._view.selectedNode;
return selectedNode && PlacesUtils.nodeIsBookmark(selectedNode) &&
- PlacesUtils.microsummaries.hasMicrosummary(selectedNode.itemId);
+ PlacesUIUtils.microsummaries.hasMicrosummary(selectedNode.itemId);
case "placesCmd_reload":
// Livemark containers
var selectedNode = this._view.selectedNode;
return selectedNode && PlacesUtils.nodeIsLivemarkContainer(selectedNode);
case "placesCmd_sortBy:name":
var selectedNode = this._view.selectedNode;
return selectedNode &&
PlacesUtils.nodeIsFolder(selectedNode) &&
@@ -187,20 +187,20 @@ PlacesController.prototype = {
// filters out other commands that we do _not_ support (see 329587).
const CMD_PREFIX = "placesCmd_";
return (aCommand.substr(0, CMD_PREFIX.length) == CMD_PREFIX);
},
doCommand: function PC_doCommand(aCommand) {
switch (aCommand) {
case "cmd_undo":
- PlacesUtils.ptm.undoTransaction();
+ PlacesUIUtils.ptm.undoTransaction();
break;
case "cmd_redo":
- PlacesUtils.ptm.redoTransaction();
+ PlacesUIUtils.ptm.redoTransaction();
break;
case "cmd_cut":
this.cut();
break;
case "cmd_copy":
this.copy();
break;
case "cmd_paste":
@@ -208,23 +208,23 @@ PlacesController.prototype = {
break;
case "cmd_delete":
this.remove("Remove Selection");
break;
case "cmd_selectAll":
this.selectAll();
break;
case "placesCmd_open":
- PlacesUtils.openNodeIn(this._view.selectedNode, "current");
+ PlacesUIUtils.openNodeIn(this._view.selectedNode, "current");
break;
case "placesCmd_open:window":
- PlacesUtils.openNodeIn(this._view.selectedNode, "window");
+ PlacesUIUtils.openNodeIn(this._view.selectedNode, "window");
break;
case "placesCmd_open:tab":
- PlacesUtils.openNodeIn(this._view.selectedNode, "tab");
+ PlacesUIUtils.openNodeIn(this._view.selectedNode, "tab");
break;
case "placesCmd_new:folder":
this.newItem("folder");
break;
case "placesCmd_new:bookmark":
this.newItem("bookmark");
break;
case "placesCmd_new:livemark":
@@ -332,18 +332,18 @@ PlacesController.prototype = {
* @returns true if: - clipboard data is of a TYPE_X_MOZ_PLACE_* flavor,
- clipboard data is of type TEXT_UNICODE and
is a valid URI.
*/
_isClipboardDataPasteable: function PC__isClipboardDataPasteable() {
// if the clipboard contains TYPE_X_MOZ_PLACE_* data, it is definitely
// pasteable, with no need to unwrap all the nodes.
- var flavors = PlacesUtils.placesFlavors;
- var clipboard = PlacesUtils.clipboard;
+ var flavors = PlacesUIUtils.placesFlavors;
+ var clipboard = PlacesUIUtils.clipboard;
var hasPlacesData =
clipboard.hasDataMatchingFlavors(flavors, flavors.length,
Ci.nsIClipboard.kGlobalClipboard);
if (hasPlacesData)
return this._view.insertionPoint != null;
// if the clipboard doesn't have TYPE_X_MOZ_PLACE_* data, we also allow
// pasting of valid "text/unicode" and "text/x-moz-url" data
@@ -437,17 +437,17 @@ PlacesController.prototype = {
break;
case Ci.nsINavHistoryResultNode.RESULT_TYPE_URI:
case Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT:
case Ci.nsINavHistoryResultNode.RESULT_TYPE_FULL_VISIT:
nodeData["link"] = true;
uri = PlacesUtils._uri(node.uri);
if (PlacesUtils.nodeIsBookmark(node)) {
nodeData["bookmark"] = true;
- var mss = PlacesUtils.microsummaries;
+ var mss = PlacesUIUtils.microsummaries;
if (mss.hasMicrosummary(node.itemId))
nodeData["microsummary"] = true;
else if (node.parent &&
PlacesUtils.nodeIsLivemarkContainer(node.parent))
nodeData["livemarkChild"] = true;
}
break;
}
@@ -593,18 +593,17 @@ PlacesController.prototype = {
}
// Set Open Folder/Links In Tabs items enabled state if they're visible
if (anyVisible) {
var openContainerInTabsItem = document.getElementById("placesContext_openContainer:tabs");
if (!openContainerInTabsItem.hidden && this._view.selectedNode &&
PlacesUtils.nodeIsContainer(this._view.selectedNode)) {
openContainerInTabsItem.disabled =
- PlacesUtils.getURLsForContainerNode(this._view.selectedNode)
- .length == 0;
+ !PlacesUtils.hasChildURIs(this._view.selectedNode);
}
else {
// see selectiontype rule in the overlay
var openLinksInTabsItem = document.getElementById("placesContext_openLinks:tabs");
openLinksInTabsItem.disabled = openLinksInTabsItem.hidden;
}
}
@@ -623,19 +622,19 @@ PlacesController.prototype = {
*/
showBookmarkPropertiesForSelection:
function PC_showBookmarkPropertiesForSelection() {
var node = this._view.selectedNode;
if (!node)
return;
if (PlacesUtils.nodeIsFolder(node))
- PlacesUtils.showFolderProperties(node.itemId);
+ PlacesUIUtils.showFolderProperties(node.itemId);
else if (PlacesUtils.nodeIsBookmark(node))
- PlacesUtils.showBookmarkProperties(node.itemId);
+ PlacesUIUtils.showBookmarkProperties(node.itemId);
},
/**
* This method can be run on a URI parameter to ensure that it didn't
* receive a string instead of an nsIURI object.
*/
_assertURINotString: function PC__assertURINotString(value) {
NS_ASSERT((typeof(value) == "object") && !(value instanceof String),
@@ -651,17 +650,17 @@ PlacesController.prototype = {
PlacesUtils.livemarks.reloadLivemarkFolder(selectedNode.itemId);
},
/**
* Reload the microsummary associated with the selection
*/
reloadSelectedMicrosummary: function PC_reloadSelectedMicrosummary() {
var selectedNode = this._view.selectedNode;
- var mss = PlacesUtils.microsummaries;
+ var mss = PlacesUIUtils.microsummaries;
if (mss.hasMicrosummary(selectedNode.itemId))
mss.refreshMicrosummary(selectedNode.itemId);
},
/**
* Gives the user a chance to cancel loading lots of tabs at once
*/
_confirmOpenTabs: function(numTabsToOpen) {
@@ -683,24 +682,24 @@ PlacesController.prototype = {
var strings = document.getElementById("placeBundle");
const BRANDING_BUNDLE_URI = "chrome://branding/locale/brand.properties";
var brandShortName = Cc["@mozilla.org/intl/stringbundle;1"].
getService(Ci.nsIStringBundleService).
createBundle(BRANDING_BUNDLE_URI).
GetStringFromName("brandShortName");
var buttonPressed = promptService.confirmEx(window,
- PlacesUtils.getString("tabs.openWarningTitle"),
- PlacesUtils.getFormattedString(messageKey,
+ PlacesUIUtils.getString("tabs.openWarningTitle"),
+ PlacesUIUtils.getFormattedString(messageKey,
[numTabsToOpen, brandShortName]),
(promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0)
+ (promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1),
- PlacesUtils.getString(openKey),
+ PlacesUIUtils.getString(openKey),
null, null,
- PlacesUtils.getFormattedString("tabs.openWarningPromptMeBranded",
+ PlacesUIUtils.getFormattedString("tabs.openWarningPromptMeBranded",
[brandShortName]),
warnOnOpen);
reallyOpen = (buttonPressed == 0);
// don't set the pref unless they press OK and it's false
if (reallyOpen && !warnOnOpen.value)
pref.setBoolPref(kWarnOnOpenPref, false);
}
@@ -709,39 +708,39 @@ PlacesController.prototype = {
},
/**
* Opens the links in the selected folder, or the selected links in new tabs.
*/
openSelectionInTabs: function PC_openLinksInTabs(aEvent) {
var node = this._view.selectedNode;
if (node && PlacesUtils.nodeIsContainer(node))
- PlacesUtils.openContainerNodeInTabs(this._view.selectedNode, aEvent);
+ PlacesUIUtils.openContainerNodeInTabs(this._view.selectedNode, aEvent);
else
- PlacesUtils.openURINodesInTabs(this._view.getSelectionNodes(), aEvent);
+ PlacesUIUtils.openURINodesInTabs(this._view.getSelectionNodes(), aEvent);
},
/**
* Shows the Add Bookmark UI for the current insertion point.
*
* @param aType
* the type of the new item (bookmark/livemark/folder)
*/
newItem: function PC_newItem(aType) {
var ip = this._view.insertionPoint;
if (!ip)
throw Cr.NS_ERROR_NOT_AVAILABLE;
var performed = false;
if (aType == "bookmark")
- performed = PlacesUtils.showAddBookmarkUI(null, null, null, ip);
+ performed = PlacesUIUtils.showAddBookmarkUI(null, null, null, ip);
else if (aType == "livemark")
- performed = PlacesUtils.showAddLivemarkUI(null, null, null, null, ip);
+ performed = PlacesUIUtils.showAddLivemarkUI(null, null, null, null, ip);
else // folder
- performed = PlacesUtils.showAddFolderUI(null, ip);
+ performed = PlacesUIUtils.showAddFolderUI(null, ip);
if (performed) {
// select the new item
var insertedNodeId = PlacesUtils.bookmarks
.getIdForItemAt(ip.itemId, ip.index);
this._view.selectItems([insertedNodeId], ip.itemId);
}
},
@@ -752,34 +751,34 @@ PlacesController.prototype = {
* of the folder.
*/
newFolder: function PC_newFolder() {
var ip = this._view.insertionPoint;
if (!ip)
throw Cr.NS_ERROR_NOT_AVAILABLE;
var performed = false;
- performed = PlacesUtils.showAddFolderUI(null, ip);
+ performed = PlacesUIUtils.showAddFolderUI(null, ip);
if (performed) {
// select the new item
var insertedNodeId = PlacesUtils.bookmarks
.getIdForItemAt(ip.itemId, ip.index);
this._view.selectItems([insertedNodeId]);
}
},
/**
* Create a new Bookmark separator somewhere.
*/
newSeparator: function PC_newSeparator() {
var ip = this._view.insertionPoint;
if (!ip)
throw Cr.NS_ERROR_NOT_AVAILABLE;
- var txn = PlacesUtils.ptm.createSeparator(ip.itemId, ip.index);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm.createSeparator(ip.itemId, ip.index);
+ PlacesUIUtils.ptm.doTransaction(txn);
// select the new item
var insertedNodeId = PlacesUtils.bookmarks
.getIdForItemAt(ip.itemId, ip.index);
this._view.selectItems([insertedNodeId]);
},
/**
* Opens a dialog for moving the selected nodes.
@@ -790,18 +789,18 @@ PlacesController.prototype = {
this._view.getSelectionNodes());
},
/**
* Sort the selected folder by name
*/
sortFolderByName: function PC_sortFolderByName() {
var itemId = PlacesUtils.getConcreteItemId(this._view.selectedNode);
- var txn = PlacesUtils.ptm.sortFolderByName(itemId);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm.sortFolderByName(itemId);
+ PlacesUIUtils.ptm.doTransaction(txn);
},
/**
* Walk the list of folders we're removing in this delete operation, and
* see if the selected node specified is already implicitly being removed
* because it is a child of that folder.
* @param node
* Node to check for containment.
@@ -851,35 +850,35 @@ PlacesController.prototype = {
for (var i = 0; i < range.length; ++i) {
var node = range[i];
if (this._shouldSkipNode(node, removedFolders))
continue;
if (PlacesUtils.nodeIsFolder(node))
removedFolders.push(node);
- transactions.push(PlacesUtils.ptm.removeItem(node.itemId));
+ transactions.push(PlacesUIUtils.ptm.removeItem(node.itemId));
}
},
/**
* Removes the set of selected ranges from bookmarks.
* @param txnName
* See |remove|.
*/
_removeRowsFromBookmarks: function PC__removeRowsFromBookmarks(txnName) {
var ranges = this._view.getRemovableSelectionRanges();
var transactions = [];
// Delete the selected rows. Do this by walking the selection backward, so
// that when undo is performed they are re-inserted in the correct order.
for (var i = ranges.length - 1; i >= 0 ; --i)
this._removeRange(ranges[i], transactions);
if (transactions.length > 0) {
- var txn = PlacesUtils.ptm.aggregateTransactions(txnName, transactions);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm.aggregateTransactions(txnName, transactions);
+ PlacesUIUtils.ptm.doTransaction(txn);
}
},
/**
* Removes the set of selected ranges from history.
*/
_removeRowsFromHistory: function PC__removeRowsFromHistory() {
// Other containers are history queries, just delete from history
@@ -992,17 +991,17 @@ PlacesController.prototype = {
}
var dataSet = new TransferDataSet();
for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i];
var data = new TransferData();
function addData(type, overrideURI) {
- data.addDataForFlavour(type, PlacesUtils._wrapString(
+ data.addDataForFlavour(type, PlacesUIUtils._wrapString(
PlacesUtils.wrapNode(node, type, overrideURI)));
}
function addURIData(overrideURI) {
addData(PlacesUtils.TYPE_X_MOZ_URL, overrideURI);
addData(PlacesUtils.TYPE_UNICODE, overrideURI);
addData(PlacesUtils.TYPE_HTML, overrideURI);
}
@@ -1070,31 +1069,31 @@ PlacesController.prototype = {
}
// all items wrapped as TYPE_X_MOZ_PLACE
placeString += generateChunk(PlacesUtils.TYPE_X_MOZ_PLACE);
}
function addData(type, data) {
xferable.addDataFlavor(type);
- xferable.setTransferData(type, PlacesUtils._wrapString(data), data.length * 2);
+ xferable.setTransferData(type, PlacesUIUtils._wrapString(data), data.length * 2);
}
// This order is _important_! It controls how this and other applications
// select data to be inserted based on type.
if (placeString)
addData(PlacesUtils.TYPE_X_MOZ_PLACE, placeString);
if (mozURLString)
addData(PlacesUtils.TYPE_X_MOZ_URL, mozURLString);
if (unicodeString)
addData(PlacesUtils.TYPE_UNICODE, unicodeString);
if (htmlString)
addData(PlacesUtils.TYPE_HTML, htmlString);
if (placeString || unicodeString || htmlString || mozURLString) {
- PlacesUtils.clipboard.setData(xferable, null, Ci.nsIClipboard.kGlobalClipboard);
+ PlacesUIUtils.clipboard.setData(xferable, null, Ci.nsIClipboard.kGlobalClipboard);
}
}
finally {
if (oldViewer)
result.viewer = oldViewer;
}
},
@@ -1128,17 +1127,17 @@ PlacesController.prototype = {
var xferable =
Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable);
for (var i = 0; i < types.length; ++i)
xferable.addDataFlavor(types[i]);
return xferable;
}
- var clipboard = PlacesUtils.clipboard;
+ var clipboard = PlacesUIUtils.clipboard;
var ip = this._view.insertionPoint;
if (!ip)
throw Cr.NS_ERROR_NOT_AVAILABLE;
/**
* Gets a list of transactions to perform the paste of specific types.
* @param types
@@ -1156,19 +1155,19 @@ PlacesController.prototype = {
var items = PlacesUtils.unwrapNodes(data, type.value);
var transactions = [];
var index = ip.index;
for (var i = 0; i < items.length; ++i) {
// adjusted to make sure that items are given the correct index -
// transactions insert differently if index == -1
if (ip.index > -1)
index = ip.index + i;
- transactions.push(PlacesUtils.makeTransaction(items[i], type.value,
- ip.itemId, index,
- true));
+ transactions.push(PlacesUIUtils.makeTransaction(items[i], type.value,
+ ip.itemId, index,
+ true));
}
return transactions;
}
catch (e) {
// getAnyTransferData will throw if there is no data of the specified
// type on the clipboard.
// unwrapNodes will throw if the data that is present is malformed in
// some way.
@@ -1177,18 +1176,18 @@ PlacesController.prototype = {
return [];
}
// Get transactions to paste any folders, separators or links that might
// be on the clipboard, aggregate them and execute them.
var transactions = getTransactions([PlacesUtils.TYPE_X_MOZ_PLACE,
PlacesUtils.TYPE_X_MOZ_URL,
PlacesUtils.TYPE_UNICODE]);
- var txn = PlacesUtils.ptm.aggregateTransactions("Paste", transactions);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm.aggregateTransactions("Paste", transactions);
+ PlacesUIUtils.ptm.doTransaction(txn);
// select the pasted items, they should be consecutive
var insertedNodeIds = [];
for (var i = 0; i < transactions.length; ++i)
insertedNodeIds.push(PlacesUtils.bookmarks
.getIdForItemAt(ip.itemId, ip.index + i));
if (insertedNodeIds.length > 0)
this._view.selectItems(insertedNodeIds);
@@ -1234,41 +1233,73 @@ var PlacesControllerDragHelper = {
var dragService = Cc["@mozilla.org/widget/dragservice;1"].
getService(Ci.nsIDragService);
return dragService.getCurrentSession();
},
/**
* Determines whether or not the data currently being dragged can be dropped
* on a places view.
+ * @param ip
+ * The insertion point where the items should be dropped
*/
- canDrop: function PCDH_canDrop() {
+ canDrop: function PCDH_canDrop(ip) {
var session = this.getSession();
- if (session) {
- var types = PlacesUtils.GENERIC_VIEW_DROP_TYPES;
- for (var i = 0; i < types.length; ++i) {
- if (session.isDataFlavorSupported(types[i]))
- return true;
+ if (!session)
+ return false;
+
+ var types = PlacesUIUtils.GENERIC_VIEW_DROP_TYPES;
+ var foundType = false;
+ for (var i = 0; i < types.length && !foundType; ++i) {
+ if (session.isDataFlavorSupported(types[i]))
+ foundType = true;
+ }
+
+ if (!foundType)
+ return false;
+
+ // Check every dragged item
+ var xferable = this._initTransferable(session);
+ var dropCount = session.numDropItems;
+ for (i = 0; i < dropCount; i++) {
+ // Get the information of the dragged item
+ session.getData(xferable, i);
+ var data = { }, flavor = { };
+ xferable.getAnyTransferData(flavor, data, { });
+ data.value.QueryInterface(Ci.nsISupportsString);
+ var dragged = PlacesUtils.unwrapNodes(data.value.data, flavor.value)[0];
+
+ // The following loop disallows the dropping of a folder on itself or
+ // on any of its descendants.
+ if (dragged.type == PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER ||
+ /^place:/.test(dragged.uri)) {
+ var parentId = ip.itemId;
+ while (parentId != PlacesUtils.placesRootId) {
+ if (dragged.concreteId == parentId || dragged.id == parentId)
+ return false;
+ parentId = PlacesUtils.bookmarks.getFolderIdForItem(parentId);
+ }
}
}
- return false;
+
+ return true;
},
/**
* Creates a Transferable object that can be filled with data of types
* supported by a view.
* @param session
* The active drag session
* @returns An object implementing nsITransferable that can receive data
* dropped onto a view.
*/
_initTransferable: function PCDH__initTransferable(session) {
var xferable = Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable);
- var types = PlacesUtils.GENERIC_VIEW_DROP_TYPES;
+ var types = PlacesUIUtils.GENERIC_VIEW_DROP_TYPES;
for (var i = 0; i < types.length; ++i) {
if (session.isDataFlavorSupported(types[i]))
xferable.addDataFlavor(types[i]);
}
return xferable;
},
/**
@@ -1301,23 +1332,23 @@ var PlacesControllerDragHelper = {
// drag multiple elts upward: need to increment index or each successive
// elt will be inserted at the same index, each above the previous.
if ((index != -1) && ((index < unwrapped.index) ||
(unwrapped.folder && (index < unwrapped.folder.index)))) {
index = index + movedCount;
movedCount++;
}
- transactions.push(PlacesUtils.makeTransaction(unwrapped,
+ transactions.push(PlacesUIUtils.makeTransaction(unwrapped,
flavor.value, insertionPoint.itemId,
index, copy));
}
- var txn = PlacesUtils.ptm.aggregateTransactions("DropItems", transactions);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm.aggregateTransactions("DropItems", transactions);
+ PlacesUIUtils.ptm.doTransaction(txn);
}
};
function goUpdatePlacesCommands() {
var placesController;
try {
// Or any other command...
placesController = top.document.commandDispatcher
--- a/browser/components/places/content/editBookmarkOverlay.js
+++ b/browser/components/places/content/editBookmarkOverlay.js
@@ -152,17 +152,17 @@ var gEditItemOverlay = {
// folder picker
this._initFolderMenuList(container);
// name picker
this._initNamePicker();
// description field
this._initTextField("descriptionField",
- PlacesUtils.getItemDescription(this._itemId));
+ PlacesUIUtils.getItemDescription(this._itemId));
this._showHideRows();
// observe changes
if (!this._observersAdded) {
PlacesUtils.bookmarks.addObserver(this, false);
window.addEventListener("unload", this, false);
this._observersAdded = true;
@@ -307,17 +307,20 @@ var gEditItemOverlay = {
return menuItem;
},
_getItemStaticTitle: function EIO__getItemStaticTitle() {
const annos = PlacesUtils.annotations;
if (annos.itemHasAnnotation(this._itemId, STATIC_TITLE_ANNO))
return annos.getItemAnnotation(this._itemId, STATIC_TITLE_ANNO);
- return PlacesUtils.bookmarks.getItemTitle(this._itemId);
+ var title = PlacesUtils.bookmarks.getItemTitle(this._itemId);
+ if (title === null)
+ return PlacesUtils.history.getPageTitle(this._uri);
+ return title;
},
_initNamePicker: function EIO_initNamePicker() {
var userEnteredNameField = this._element("userEnteredName");
var namePicker = this._element("namePicker");
var droppable = false;
userEnteredNameField.label = this._getItemStaticTitle();
@@ -331,18 +334,18 @@ var gEditItemOverlay = {
this._microsummaries.removeObserver(this);
this._microsummaries = null;
}
var itemToSelect = userEnteredNameField;
try {
if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK &&
!this._readOnly)
- this._microsummaries = PlacesUtils.microsummaries
- .getMicrosummaries(this._uri, -1);
+ this._microsummaries = PlacesUIUtils.microsummaries
+ .getMicrosummaries(this._uri, -1);
}
catch(ex) {
// getMicrosummaries will throw an exception in at least two cases:
// 1. the bookmarked URI contains a scheme that the service won't
// download for security reasons (currently it only handles http,
// https, and file);
// 2. the page to which the URI refers isn't HTML or XML (the only two
// content types the service knows how to summarize).
@@ -353,18 +356,18 @@ var gEditItemOverlay = {
if (enumerator.hasMoreElements()) {
// Show the drop marker if there are microsummaries
droppable = true;
while (enumerator.hasMoreElements()) {
var microsummary = enumerator.getNext()
.QueryInterface(Ci.nsIMicrosummary);
var menuItem = this._createMicrosummaryMenuItem(microsummary);
- if (PlacesUtils.microsummaries
- .isMicrosummary(this._itemId, microsummary))
+ if (PlacesUIUtils.microsummaries
+ .isMicrosummary(this._itemId, microsummary))
itemToSelect = menuItem;
menupopup.appendChild(menuItem);
}
}
this._microsummaries.addObserver(this);
}
@@ -456,43 +459,43 @@ var gEditItemOverlay = {
tagsToRemove.push(currentTags[i]);
}
for (i = 0; i < tags.length; i++) {
if (currentTags.indexOf(tags[i]) == -1)
tagsToAdd.push(tags[i]);
}
if (tagsToAdd.length > 0) {
- var tagTxn = PlacesUtils.ptm.tagURI(this._uri, tagsToAdd);
- PlacesUtils.ptm.doTransaction(tagTxn);
+ var tagTxn = PlacesUIUtils.ptm.tagURI(this._uri, tagsToAdd);
+ PlacesUIUtils.ptm.doTransaction(tagTxn);
}
if (tagsToRemove.length > 0) {
- var untagTxn = PlacesUtils.ptm.untagURI(this._uri, tagsToRemove);
- PlacesUtils.ptm.doTransaction(untagTxn);
+ var untagTxn = PlacesUIUtils.ptm.untagURI(this._uri, tagsToRemove);
+ PlacesUIUtils.ptm.doTransaction(untagTxn);
}
}
},
onNamePickerInput: function EIO_onNamePickerInput() {
var title = this._element("namePicker").value;
this._element("userEnteredName").label = title;
},
onNamePickerChange: function EIO_onNamePickerChange() {
if (this._itemId == -1)
return;
var namePicker = this._element("namePicker")
var txns = [];
- const ptm = PlacesUtils.ptm;
+ const ptm = PlacesUIUtils.ptm;
// Here we update either the item title or its cached static title
var newTitle = this._element("userEnteredName").label;
if (this._getItemStaticTitle() != newTitle) {
- if (PlacesUtils.microsummaries.hasMicrosummary(this._itemId)) {
+ if (PlacesUIUtils.microsummaries.hasMicrosummary(this._itemId)) {
// Note: this implicitly also takes care of the microsummary->static
// title case, the removeMicorosummary method in the service will set
// the item-title to the value of this annotation.
//
// XXXmano: use a transaction
PlacesUtils.setAnnotationsForItem(this._itemId,
[{name: STATIC_TITLE_ANNO,
value: newTitle}]);
@@ -503,114 +506,118 @@ var gEditItemOverlay = {
var newMicrosummary = namePicker.selectedItem.microsummary;
// Only add a microsummary update to the transaction if the microsummary
// has actually changed, i.e. the user selected no microsummary, but the
// bookmark previously had one, or the user selected a microsummary which
// is not the one the bookmark previously had
if ((newMicrosummary == null &&
- PlacesUtils.microsummaries.hasMicrosummary(this._itemId)) ||
+ PlacesUIUtils.microsummaries.hasMicrosummary(this._itemId)) ||
(newMicrosummary != null &&
- !PlacesUtils.microsummaries
- .isMicrosummary(this._itemId, newMicrosummary))) {
+ !PlacesUIUtils.microsummaries
+ .isMicrosummary(this._itemId, newMicrosummary))) {
txns.push(ptm.editBookmarkMicrosummary(this._itemId, newMicrosummary));
}
var aggregate = ptm.aggregateTransactions("Edit Item Title", txns);
ptm.doTransaction(aggregate);
},
onDescriptionFieldBlur: function EIO_onDescriptionFieldInput() {
var description = this._element("descriptionField").value;
if (description != PlacesUtils.getItemDescription(this._itemId)) {
- var txn = PlacesUtils.ptm
- .editItemDescription(this._itemId, description);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm
+ .editItemDescription(this._itemId, description);
+ PlacesUIUtils.ptm.doTransaction(txn);
}
},
onLocationFieldBlur: function EIO_onLocationFieldBlur() {
var uri;
try {
- uri = PlacesUtils.createFixedURI(this._element("locationField").value);
+ uri = PlacesUIUtils.createFixedURI(this._element("locationField").value);
}
catch(ex) { return; }
if (!this._uri.equals(uri)) {
- var txn = PlacesUtils.ptm.editBookmarkURI(this._itemId, uri);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm.editBookmarkURI(this._itemId, uri);
+ PlacesUIUtils.ptm.doTransaction(txn);
}
},
onKeywordFieldBlur: function EIO_onKeywordFieldBlur() {
var keyword = this._element("keywordField").value;
if (keyword != PlacesUtils.bookmarks.getKeywordForBookmark(this._itemId)) {
- var txn = PlacesUtils.ptm.editBookmarkKeyword(this._itemId, keyword);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm.editBookmarkKeyword(this._itemId, keyword);
+ PlacesUIUtils.ptm.doTransaction(txn);
}
},
onFeedLocationFieldBlur: function EIO_onFeedLocationFieldBlur() {
var uri;
try {
- uri = PlacesUtils.createFixedURI(this._element("feedLocationField").value);
+ uri = PlacesUIUtils.createFixedURI(this._element("feedLocationField").value);
}
catch(ex) { return; }
var currentFeedURI = PlacesUtils.livemarks.getFeedURI(this._itemId);
if (!currentFeedURI.equals(uri)) {
- var txn = PlacesUtils.ptm.editLivemarkFeedURI(this._itemId, uri);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm.editLivemarkFeedURI(this._itemId, uri);
+ PlacesUIUtils.ptm.doTransaction(txn);
}
},
onSiteLocationFieldBlur: function EIO_onSiteLocationFieldBlur() {
var uri = null;
try {
- uri = PlacesUtils.createFixedURI(this._element("siteLocationField").value);
+ uri = PlacesUIUtils.createFixedURI(this._element("siteLocationField").value);
}
catch(ex) { }
var currentSiteURI = PlacesUtils.livemarks.getSiteURI(this._itemId);
if (!uri || !currentSiteURI.equals(uri)) {
- var txn = PlacesUtils.ptm.editLivemarkSiteURI(this._itemId, uri);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm.editLivemarkSiteURI(this._itemId, uri);
+ PlacesUIUtils.ptm.doTransaction(txn);
}
},
onLoadInSidebarCheckboxCommand:
function EIO_onLoadInSidebarCheckboxCommand() {
var loadInSidebarChecked = this._element("loadInSidebarCheckbox").checked;
- var txn = PlacesUtils.ptm.setLoadInSidebar(this._itemId,
- loadInSidebarChecked);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm.setLoadInSidebar(this._itemId,
+ loadInSidebarChecked);
+ PlacesUIUtils.ptm.doTransaction(txn);
},
toggleFolderTreeVisibility: function EIO_toggleFolderTreeVisibility() {
var expander = this._element("foldersExpander");
if (!this._folderTree.collapsed) {
expander.className = "expander-down";
expander.setAttribute("tooltiptext",
expander.getAttribute("tooltiptextdown"));
- this._folderTree.collapsed = true;
+ this._folderTree.collapsed =
+ this._element("newFolderBox").collapsed = true;
this._element("chooseFolderSeparator").hidden =
this._element("chooseFolderMenuItem").hidden = false;
}
else {
expander.className = "expander-up"
expander.setAttribute("tooltiptext",
expander.getAttribute("tooltiptextup"));
- this._folderTree.collapsed = false;
- if (!this._folderTree.place) {
- const FOLDER_TREE_PLACE_URI =
- "place:excludeItems=1&excludeQueries=1&excludeReadOnlyFolders=1&folder=" +
- window.top.PlacesUtils.allBookmarksFolderId;
- this._folderTree.place = FOLDER_TREE_PLACE_URI;
- }
+ this._folderTree.collapsed =
+ this._element("newFolderBox").collapsed = false;
+
+ // XXXmano: Ideally we would only do this once, but for some odd reason,
+ // the editable mode set on this tree, together with its collapsed state
+ // breaks the view.
+ const FOLDER_TREE_PLACE_URI =
+ "place:excludeItems=1&excludeQueries=1&excludeReadOnlyFolders=1&folder=" +
+ window.top.PlacesUIUtils.allBookmarksFolderId;
+ this._folderTree.place = FOLDER_TREE_PLACE_URI;
this._element("chooseFolderSeparator").hidden =
this._element("chooseFolderMenuItem").hidden = true;
var currentFolder = this._getFolderIdFromMenuList();
this._folderTree.selectItems([currentFolder]);
this._folderTree.focus();
}
},
@@ -658,18 +665,18 @@ var gEditItemOverlay = {
// menulist right away
setTimeout(function(self) self.toggleFolderTreeVisibility(), 100, this);
return;
}
// Move the item
var container = this._getFolderIdFromMenuList();
if (PlacesUtils.bookmarks.getFolderIdForItem(this._itemId) != container) {
- var txn = PlacesUtils.ptm.moveItem(this._itemId, container, -1);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm.moveItem(this._itemId, container, -1);
+ PlacesUIUtils.ptm.doTransaction(txn);
// Mark the containing folder as recently-used if it isn't in the
// static list
if (container != PlacesUtils.unfiledBookmarksFolderId &&
container != PlacesUtils.toolbarFolderId &&
container != PlacesUtils.bookmarksMenuFolderId)
this._markFolderAsRecentlyUsed(container);
}
@@ -761,16 +768,36 @@ var gEditItemOverlay = {
if (tags[i] == "") {
tags.splice(i, 1);
i--;
}
}
return tags;
},
+ newFolder: function EIO_newFolder() {
+ var ip = this._folderTree.insertionPoint;
+
+ // default to the bookmarks menu folder
+ if (ip.itemId == PlacesUIUtils.allBookmarksFolderId ||
+ ip.itemId == PlacesUIUtils.unfiledBookmarksFolderId) {
+ ip.itemId = PlacesUtils.bookmarksMenuFolderId;
+ ip.index = -1;
+ }
+
+ // XXXmano: add a separate "New Folder" string at some point...
+ var defaultLabel = this._element("newFolderButton").label;
+ var txn = PlacesUIUtils.ptm.createFolder(defaultLabel, ip.itemId, ip.index);
+ PlacesUIUtils.ptm.doTransaction(txn);
+ this._folderTree.focus();
+ this._folderTree.selectItems([this._lastNewItem]);
+ this._folderTree.startEditing(this._folderTree.view.selection.currentIndex,
+ this._folderTree.columns.getFirstColumn());
+ },
+
// nsIDOMEventListener
handleEvent: function EIO_nsIDOMEventListener(aEvent) {
switch (aEvent.type) {
case "CheckboxStateChange":
// Update the tags field when items are checked/unchecked in the listbox
var tags = this._getTagsArrayFromTagField();
if (aEvent.target.checked)
@@ -864,14 +891,17 @@ var gEditItemOverlay = {
var folderItem = this._getFolderMenuItem(aNewParent);
// just setting selectItem _does not_ trigger oncommand, so we don't
// recurse
this._folderMenuList.selectedItem = folderItem;
},
+ onItemAdded: function EIO_onItemAdded(aItemId, aFolder, aIndex) {
+ this._lastNewItem = aItemId;
+ },
+
onBeginUpdateBatch: function() { },
onEndUpdateBatch: function() { },
- onItemAdded: function() { },
onItemRemoved: function() { },
onItemVisited: function() { },
};
--- a/browser/components/places/content/editBookmarkOverlay.xul
+++ b/browser/components/places/content/editBookmarkOverlay.xul
@@ -30,19 +30,22 @@
# 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 *****
+<!-- XXXmano: temporary also use moveBookmarks for the "New Folder" button -->
<!DOCTYPE overlay [
-<!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/editBookmarkOverlay.dtd">
-%placesDTD;
+<!ENTITY % editBookmarkOverlayDTD SYSTEM "chrome://browser/locale/places/editBookmarkOverlay.dtd">
+%editBookmarkOverlayDTD;
+<!ENTITY % moveBookmarksDTD SYSTEM "chrome://browser/locale/places/moveBookmarks.dtd">
+%moveBookmarksDTD;
]>
<?xml-stylesheet href="chrome://browser/skin/places/editBookmarkOverlay.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
<overlay id="editBookmarkOverlay"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
@@ -119,46 +122,55 @@
<menupopup>
<!-- Static item for special folders -->
<menuitem id="editBMPanel_unfiledRootItem"
class="menuitem-iconic folder-icon"/>
<menuitem id="editBMPanel_bmRootItem"
class="menuitem-iconic folder-icon"/>
<menuitem id="editBMPanel_toolbarFolderItem"
class="menuitem-iconic folder-icon"/>
- <menuseparator id="editBMPanel_foldersSeparator" hidden="true"/>
<menuseparator id="editBMPanel_chooseFolderSeparator"/>
<menuitem id="editBMPanel_chooseFolderMenuItem"
label="&editBookmarkOverlay.choose.label;"
class="menuitem-iconic folder-icon"/>
+ <menuseparator id="editBMPanel_foldersSeparator" hidden="true"/>
</menupopup>
</menulist>
<button id="editBMPanel_foldersExpander"
class="expander-down"
tooltiptext="&editBookmarkOverlay.foldersExpanderDown.tooltip;"
tooltiptextdown="&editBookmarkOverlay.foldersExpanderDown.tooltip;"
tooltiptextup="&editBookmarkOverlay.expanderUp.tooltip;"
oncommand="gEditItemOverlay.toggleFolderTreeVisibility();"
observes="paneElementsBroadcaster"/>
</row>
<tree id="editBMPanel_folderTree"
class="placesTree"
type="places"
height="150"
collapsed="true"
+ editable="true"
onselect="gEditItemOverlay.onFolderTreeSelect();"
hidecolumnpicker="true"
observes="paneElementsBroadcaster">
<treecols>
<treecol anonid="title" flex="1" primary="true" hideheader="true"/>
</treecols>
<treechildren flex="1"/>
</tree>
+ <hbox id="editBMPanel_newFolderBox" collapsed="true">
+ <button label="&newFolderButton.label;"
+ id="editBMPanel_newFolderButton"
+ accesskey="&newFolderButton.accesskey;"
+ oncommand="gEditItemOverlay.newFolder();"/>
+ <spacer flex="1"/>
+ </hbox>
+
<row align="center" id="editBMPanel_tagsRow">
<label value="&editBookmarkOverlay.tags.label;"
accesskey="&editBookmarkOverlay.tags.accesskey;"
control="editBMPanel_tagsField"
observes="paneElementsBroadcaster"/>
<textbox id="editBMPanel_tagsField"
onblur="gEditItemOverlay.onTagsFieldBlur();"
observes="paneElementsBroadcaster"
--- a/browser/components/places/content/history-panel.js
+++ b/browser/components/places/content/history-panel.js
@@ -97,17 +97,17 @@ function GroupBy(groupingType)
function historyAddBookmarks()
{
// no need to check gHistoryTree.view.selection.count
// node will be null if there is a multiple selection
// or if the selected item is not a URI node
var node = gHistoryTree.selectedNode;
if (node && PlacesUtils.nodeIsURI(node))
- PlacesUtils.showMinimalAddBookmarkUI(PlacesUtils._uri(node.uri), node.title);
+ PlacesUIUtils.showMinimalAddBookmarkUI(PlacesUtils._uri(node.uri), node.title);
}
function searchHistory(aInput)
{
var query = PlacesUtils.history.getNewQuery();
var options = PlacesUtils.history.getNewQueryOptions();
const NHQO = Ci.nsINavHistoryQueryOptions;
--- a/browser/components/places/content/history-panel.xul
+++ b/browser/components/places/content/history-panel.xul
@@ -116,17 +116,17 @@
<tree id="historyTree"
class="sidebar-placesTree"
flex="1"
type="places"
context="placesContext"
hidecolumnpicker="true"
onkeypress="SidebarUtils.handleTreeKeyPress(event);"
- onclick="SidebarUtils.handleTreeClick(this, event);"
+ onclick="SidebarUtils.handleTreeClick(this, event, true);"
onmousemove="SidebarUtils.handleTreeMouseMove(event);"
onmouseout="SidebarUtils.clearURLFromStatusBar();">
<treecols>
<treecol id="title" flex="1" primary="true" hideheader="true"/>
</treecols>
<treechildren class="sidebar-placesTreechildren" flex="1"/>
</tree>
</page>
--- a/browser/components/places/content/menu.xml
+++ b/browser/components/places/content/menu.xml
@@ -71,17 +71,17 @@
"popup-internal-box");
</field>
<!-- markers for start and end of valid places items -->
<field name="_startMarker">-1</field>
<field name="_endMarker">-1</field>
<!-- This is the view that manage the popup -->
- <field name="_rootView">PlacesUtils.getViewForNode(this);</field>
+ <field name="_rootView">PlacesUIUtils.getViewForNode(this);</field>
<field name="_built">false</field>
<method name="onDragOver">
<parameter name="aEvent"/>
<parameter name="aFlavour"/>
<parameter name="aDragSession"/>
<body><![CDATA[
@@ -212,17 +212,17 @@
PlacesControllerDragHelper.onDrop(dropPoint.ip);
]]></body>
</method>
<!-- This returns the FavourSet accepted by this popup -->
<method name="getSupportedFlavours">
<body><![CDATA[
var flavourSet = new FlavourSet();
- var acceptedDropFlavours = PlacesUtils.GENERIC_VIEW_DROP_TYPES;
+ var acceptedDropFlavours = PlacesUIUtils.GENERIC_VIEW_DROP_TYPES;
acceptedDropFlavours.forEach(flavourSet.appendFlavour, flavourSet);
return flavourSet;
]]></body>
</method>
<!-- Check if we should hide the drop indicator for the target -->
<method name="_hideDropIndicator">
<parameter name="aEvent"/>
@@ -310,22 +310,18 @@
dropPoint.ip = new InsertionPoint(resultNode.itemId, -1, 1);
dropPoint.beforeIndex = -1;
return dropPoint;
]]></body>
</method>
<method name="canDrop">
<body><![CDATA[
- // Can't drop if the menu isn't a folder
- var resultNode = this._rootView.getResultNode();
- if (!PlacesUtils.nodeIsFolder(resultNode))
- return false;
-
- return PlacesControllerDragHelper.canDrop();
+ var ip = this._rootView.insertionPoint;
+ return ip && PlacesControllerDragHelper.canDrop(ip);
]]></body>
</method>
<!-- Sub-menus should be opened when the mouse drags over them, and closed
when the mouse drags off. The overFolder object manages opening and
closing of folders when the mouse hovers. -->
<field name="_overFolder"><![CDATA[({
_self: this,
@@ -575,17 +571,17 @@
</method>
<method name="insertNewItem">
<parameter name="aChild"/>
<parameter name="aParentPopup"/>
<parameter name="aBefore"/>
<body><![CDATA[
var element =
- PlacesUtils.createMenuItemForNode(aChild, this._containerNodesMap);
+ PlacesUIUtils.createMenuItemForNode(aChild, this._containerNodesMap);
if (aBefore)
aParentPopup.insertBefore(element, aBefore);
else {
// Add the new element to the menu. If there is static content at
// the end of the menu, add the element before that. Otherwise,
// just add to the end.
if (aParentPopup._endMarker != -1)
@@ -600,28 +596,28 @@
<method name="_showEmptyMenuItem">
<parameter name="aPopup"/>
<body><![CDATA[
if (aPopup._emptyMenuItem) {
aPopup._emptyMenuItem.hidden = false;
return;
}
- var label = PlacesUtils.getString("bookmarksMenuEmptyFolder");
+ var label = PlacesUIUtils.getString("bookmarksMenuEmptyFolder");
aPopup._emptyMenuItem = document.createElement("menuitem");
aPopup._emptyMenuItem.setAttribute("label", label);
aPopup._emptyMenuItem.setAttribute("disabled", true);
aPopup.appendChild(aPopup._emptyMenuItem);
]]></body>
</method>
<method name="_rebuild">
<parameter name="aPopup"/>
<body><![CDATA[
- PlacesUtils.cleanPlacesPopup(aPopup);
+ PlacesUIUtils.cleanPlacesPopup(aPopup);
var cc = aPopup._resultNode.childCount;
if (cc > 0) {
if (aPopup._emptyMenuItem)
aPopup._emptyMenuItem.hidden = true;
for (var i = 0; i < cc; ++i) {
var child = aPopup._resultNode.getChild(i);
@@ -751,17 +747,17 @@
if (iconURI) {
var spec = iconURI.spec;
if (menuitem.getAttribute("image") != spec)
menuitem.setAttribute("image", spec);
}
else
menuitem.removeAttribute("image");
- var title = PlacesUtils.getBestTitle(aNode);
+ var title = PlacesUIUtils.getBestTitle(aNode);
if (menuitem.getAttribute("label") != title)
menuitem.setAttribute("label", title);
if (!menuitem.hasAttribute("livemark") &&
PlacesUtils.nodeIsLivemarkContainer(aNode))
menuitem.setAttribute("livemark", "true");
},
@@ -948,23 +944,28 @@
window.content.focus();
]]>
</body>
</method>
</implementation>
<handlers>
<handler event="popupshowing" phase="capturing"><![CDATA[
this._ensureInitialized();
- if (event.target._resultNode)
- this.onPopupShowing(event);
+ var popup = event.target;
+ // Avoid handling popupshowing of inner views
+ if (!popup._resultNode || PlacesUIUtils.getViewForNode(popup) != this)
+ return;
+
+ this.onPopupShowing(event);
]]></handler>
<handler event="popuphidden"><![CDATA[
var popup = event.target;
- if (!popup._resultNode)
+ // We should avoid to handle events of inner views
+ if (!popup._resultNode || PlacesUIUtils.getViewForNode(popup) != this)
return;
// UI performance: folder queries are cheap, keep the resultnode open
// so we don't rebuild its contents whenever the popup is reopened.
if (!PlacesUtils.nodeIsFolder(popup._resultNode))
popup._resultNode.containerOpen = false;
// The autoopened attribute is set for folders which have been
--- a/browser/components/places/content/moveBookmarks.js
+++ b/browser/components/places/content/moveBookmarks.js
@@ -47,38 +47,38 @@ var gMoveBookmarksDialog = {
return this._foldersTree;
},
init: function() {
this._nodes = window.arguments[0];
this.foldersTree.place =
"place:excludeItems=1&excludeQueries=1&excludeReadOnlyFolders=1&folder=" +
- PlacesUtils.allBookmarksFolderId;
+ PlacesUIUtils.allBookmarksFolderId;
},
onOK: function MBD_onOK(aEvent) {
var selectedNode = this.foldersTree.selectedNode;
NS_ASSERT(selectedNode,
"selectedNode must be set in a single-selection tree with initial selection set");
var selectedFolderID = PlacesUtils.getConcreteItemId(selectedNode);
var transactions = [];
for (var i=0; i < this._nodes.length; i++) {
// Nothing to do if the node is already under the selected folder
if (this._nodes[i].parent.itemId == selectedFolderID)
continue;
transactions.push(new
- PlacesUtils.ptm.moveItem(this._nodes[i].itemId, selectedFolderID, -1));
+ PlacesUIUtils.ptm.moveItem(this._nodes[i].itemId, selectedFolderID, -1));
}
if (transactions.length != 0) {
- var txn = PlacesUtils.ptm.aggregateTransactions("Move Items", transactions);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm.aggregateTransactions("Move Items", transactions);
+ PlacesUIUtils.ptm.doTransaction(txn);
}
},
newFolder: function MBD_newFolder() {
// The command is disabled when the tree is not focused
this.foldersTree.focus();
goDoCommand("placesCmd_new:folder");
}
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -38,22 +38,22 @@
*
* ***** END LICENSE BLOCK ***** */
var PlacesOrganizer = {
_places: null,
_content: null,
_initFolderTree: function() {
- var leftPaneRoot = PlacesUtils.leftPaneFolderId;
+ var leftPaneRoot = PlacesUIUtils.leftPaneFolderId;
this._places.place = "place:excludeItems=1&expandQueries=0&folder=" + leftPaneRoot;
},
selectLeftPaneQuery: function PO_selectLeftPaneQuery(aQueryName) {
- var itemId = PlacesUtils.leftPaneQueries[aQueryName];
+ var itemId = PlacesUIUtils.leftPaneQueries[aQueryName];
this._places.selectItems([itemId]);
// Forcefully expand all-bookmarks
if (aQueryName == "AllBookmarks")
asContainer(this._places.selectedNode).containerOpen = true;
},
init: function PO_init() {
this._places = document.getElementById("placesList");
@@ -220,17 +220,17 @@ var PlacesOrganizer = {
var searchFilter = document.getElementById("searchFilter");
searchFilter.reset();
}
// Update the "Find in <current collection>" command and the gray text in
// the search box in the toolbar if the active collection is the current
// collection.
var findCommand = document.getElementById("OrganizerCommand_find:current");
- var findLabel = PlacesUtils.getFormattedString("findInPrefix", [node.title]);
+ var findLabel = PlacesUIUtils.getFormattedString("findInPrefix", [node.title]);
findCommand.setAttribute("label", findLabel);
if (PlacesSearchBox.filterCollection == "collection")
PlacesSearchBox.updateCollectionTitle(node.title);
},
/**
* Handle clicks on the tree. If the user middle clicks on a URL, load that
* URL according to rules. Single clicks or modified clicks do not result in
@@ -241,35 +241,35 @@ var PlacesOrganizer = {
onTreeClick: function PO_onTreeClick(aEvent) {
if (aEvent.target.localName != "treechildren")
return;
var currentView = aEvent.currentTarget;
var selectedNode = currentView.selectedNode;
if (selectedNode && aEvent.button == 1) {
if (PlacesUtils.nodeIsURI(selectedNode))
- PlacesUtils.openNodeWithEvent(selectedNode, aEvent);
+ PlacesUIUtils.openNodeWithEvent(selectedNode, aEvent);
else if (PlacesUtils.nodeIsContainer(selectedNode)) {
// The command execution function will take care of seeing the
// selection is a folder/container and loading its contents in
// tabs for us.
- PlacesUtils.openContainerNodeInTabs(selectedNode);
+ PlacesUIUtils.openContainerNodeInTabs(selectedNode);
}
}
},
openFlatContainer: function PO_openFlatContainerFlatContainer(aContainer) {
if (aContainer.itemId != -1)
this._places.selectItems([aContainer.itemId]);
else if (PlacesUtils.nodeIsQuery(aContainer))
this._places.selectPlaceURI(aContainer.uri);
},
openSelectedNode: function PU_openSelectedNode(aEvent) {
- PlacesUtils.openNodeWithEvent(this._content.selectedNode, aEvent);
+ PlacesUIUtils.openNodeWithEvent(this._content.selectedNode, aEvent);
},
/**
* Returns the options associated with the query currently loaded in the
* main places pane.
*/
getCurrentOptions: function PO_getCurrentOptions() {
return asQuery(this._content.getResult().root).queryOptions;
@@ -300,17 +300,17 @@ var PlacesOrganizer = {
},
/**
* Open a file-picker and import the selected file into the bookmarks store
*/
importFromFile: function PO_importFromFile() {
var fp = Cc["@mozilla.org/filepicker;1"].
createInstance(Ci.nsIFilePicker);
- fp.init(window, PlacesUtils.getString("SelectImport"),
+ fp.init(window, PlacesUIUtils.getString("SelectImport"),
Ci.nsIFilePicker.modeOpen);
fp.appendFilters(Ci.nsIFilePicker.filterHTML | Ci.nsIFilePicker.filterAll);
if (fp.show() != Ci.nsIFilePicker.returnCancel) {
if (fp.file) {
var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
getService(Ci.nsIPlacesImportExportService);
var file = fp.file.QueryInterface(Ci.nsILocalFile);
importer.importHTMLFromFile(file, false);
@@ -319,17 +319,17 @@ var PlacesOrganizer = {
},
/**
* Allows simple exporting of bookmarks.
*/
exportBookmarks: function PO_exportBookmarks() {
var fp = Cc["@mozilla.org/filepicker;1"].
createInstance(Ci.nsIFilePicker);
- fp.init(window, PlacesUtils.getString("EnterExport"),
+ fp.init(window, PlacesUIUtils.getString("EnterExport"),
Ci.nsIFilePicker.modeSave);
fp.appendFilters(Ci.nsIFilePicker.filterHTML);
fp.defaultString = "bookmarks.html";
if (fp.show() != Ci.nsIFilePicker.returnCancel) {
var exporter = Cc["@mozilla.org/browser/places/import-export-service;1"].
getService(Ci.nsIPlacesImportExportService);
exporter.exportHTMLToFile(fp.file);
}
@@ -354,34 +354,34 @@ var PlacesOrganizer = {
if (!bookmarksBackupDir.exists())
return; // no backup files
// get list of files
var fileList = [];
var files = bookmarksBackupDir.directoryEntries;
while (files.hasMoreElements()) {
var f = files.getNext().QueryInterface(Ci.nsIFile);
- if (!f.isHidden() && f.leafName.match(/\.html?$/))
+ if (!f.isHidden() && f.leafName.match(/^bookmarks-.+(html|json)?$/))
fileList.push(f);
}
fileList.sort(function PO_fileList_compare(a, b) {
- return b.lastModifiedTime - a.lastModifiedTime;
- });
+ return b.lastModifiedTime - a.lastModifiedTime;
+ });
if (fileList.length == 0)
return;
// populate menu
for (var i = 0; i < fileList.length; i++) {
var m = restorePopup.insertBefore
(document.createElement("menuitem"),
document.getElementById("restoreFromFile"));
var dateStr = fileList[i].leafName.replace("bookmarks-", "").
- replace(".html", "");
+ replace(/\.(html|json)$/, "");
if (!dateStr.length)
dateStr = fileList[i].leafName;
m.setAttribute("label", dateStr);
m.setAttribute("value", fileList[i].leafName);
m.setAttribute("oncommand",
"PlacesOrganizer.onRestoreMenuItemClick(this);");
}
restorePopup.insertBefore(document.createElement("menuseparator"),
@@ -394,82 +394,82 @@ var PlacesOrganizer = {
onRestoreMenuItemClick: function PO_onRestoreMenuItemClick(aMenuItem) {
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
var bookmarksFile = dirSvc.get("ProfD", Ci.nsIFile);
bookmarksFile.append("bookmarkbackups");
bookmarksFile.append(aMenuItem.getAttribute("value"));
if (!bookmarksFile.exists())
return;
+ this.restoreBookmarksFromFile(bookmarksFile);
+ },
+ /**
+ * Called when 'Choose File...' is selected from the restore menu.
+ * Prompts for a file and restores bookmarks to those in the file.
+ */
+ onRestoreBookmarksFromFile: function PO_onRestoreBookmarksFromFile() {
+ var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+ fp.init(window, PlacesUIUtils.getString("bookmarksRestoreTitle"),
+ Ci.nsIFilePicker.modeOpen);
+
+ var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
+ getService(Ci.nsIProperties);
+ var backupsDir = dirSvc.get("Desk", Ci.nsILocalFile);
+ fp.displayDirectory = backupsDir;
+
+ if (fp.show() != Ci.nsIFilePicker.returnCancel)
+ PlacesUtils.restoreBookmarksFromFile(fp.file);
+ },
+
+ /**
+ * Restores bookmarks from an HTML or JSON file.
+ */
+ restoreBookmarksFromFile: function PO_restoreBookmarksFromFile(aFile) {
var prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService);
if (!prompts.confirm(null,
- PlacesUtils.getString("bookmarksRestoreAlertTitle"),
- PlacesUtils.getString("bookmarksRestoreAlert")))
+ PlacesUIUtils.getString("bookmarksRestoreAlertTitle"),
+ PlacesUIUtils.getString("bookmarksRestoreAlert")))
return;
- var ieSvc = Cc["@mozilla.org/browser/places/import-export-service;1"].
- getService(Ci.nsIPlacesImportExportService);
- ieSvc.importHTMLFromFile(bookmarksFile, true);
+ if (aFile.leafName.match("\.json$")) {
+ // restore a JSON backup
+ PlacesUtils.restoreBookmarksFromJSONFile(aFile);
+ }
+ else {
+ var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
+ getService(Ci.nsIPlacesImportExportService);
+ importer.importHTMLFromFile(aFile, true /* overwrite existing */);
+ }
},
/**
- * Backup bookmarks to desktop, auto-generate a filename with a date
+ * Backup bookmarks to desktop, auto-generate a filename with a date.
+ * The file is a JSON serialization of bookmarks, tags and any annotations
+ * of those items.
*/
backupBookmarks: function PO_backupBookmarks() {
var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
- fp.init(window, PlacesUtils.getString("bookmarksBackupTitle"),
+ fp.init(window, PlacesUIUtils.getString("bookmarksBackupTitle"),
Ci.nsIFilePicker.modeSave);
- fp.appendFilters(Ci.nsIFilePicker.filterHTML);
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
var backupsDir = dirSvc.get("Desk", Ci.nsILocalFile);
fp.displayDirectory = backupsDir;
// Use YYYY-MM-DD (ISO 8601) as it doesn't contain illegal characters
// and makes the alphabetical order of multiple backup files more useful.
var date = (new Date).toLocaleFormat("%Y-%m-%d");
fp.defaultString = PlacesUtils.getFormattedString("bookmarksBackupFilename",
- [date]);
-
- if (fp.show() != Ci.nsIFilePicker.returnCancel) {
- var ieSvc = Cc["@mozilla.org/browser/places/import-export-service;1"].
- getService(Ci.nsIPlacesImportExportService);
- ieSvc.exportHTMLToFile(fp.file);
- }
- },
+ [date]);
- /**
- * Called when 'Choose File...' is selected from the Revert menupopup
- * Prompts for a file and reverts bookmarks to those in the file
- */
- restoreFromFile: function PO_restoreFromFile() {
- var prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].
- getService(Ci.nsIPromptService);
- if (!prompts.confirm(null, PlacesUtils.getString("bookmarksRestoreAlertTitle"),
- PlacesUtils.getString("bookmarksRestoreAlert")))
- return;
-
- var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
- fp.init(window, PlacesUtils.getString("bookmarksRestoreTitle"),
- Ci.nsIFilePicker.modeOpen);
- fp.appendFilters(Ci.nsIFilePicker.filterHTML);
-
- var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
- getService(Ci.nsIProperties);
- var backupsDir = dirSvc.get("Desk", Ci.nsILocalFile);
- fp.displayDirectory = backupsDir;
-
- if (fp.show() != Ci.nsIFilePicker.returnCancel) {
- var ieSvc = Cc["@mozilla.org/browser/places/import-export-service;1"].
- getService(Ci.nsIPlacesImportExportService);
- ieSvc.importHTMLFromFile(fp.file, true);
- }
+ if (fp.show() != Ci.nsIFilePicker.returnCancel)
+ PlacesUtils.backupBookmarksToFile(fp.file);
},
_paneDisabled: false,
_setDetailsFieldsDisabledState:
function PO__setDetailsFieldsDisabledState(aDisabled) {
if (aDisabled) {
document.getElementById("paneElementsBroadcaster")
.setAttribute("disabled", "true");
@@ -562,26 +562,26 @@ var PlacesOrganizer = {
}
else {
detailsDeck.selectedIndex = 0;
var selectItemDesc = document.getElementById("selectItemDescription");
var itemsCountLabel = document.getElementById("itemsCountText");
var rowCount = this._content.treeBoxObject.view.rowCount;
if (rowCount == 0) {
selectItemDesc.hidden = true;
- itemsCountLabel.value = PlacesUtils.getString("detailsPane.noItems");
+ itemsCountLabel.value = PlacesUIUtils.getString("detailsPane.noItems");
}
else {
selectItemDesc.hidden = false;
if (rowCount == 1)
- itemsCountLabel.value = PlacesUtils.getString("detailsPane.oneItem");
+ itemsCountLabel.value = PlacesUIUtils.getString("detailsPane.oneItem");
else {
itemsCountLabel.value =
- PlacesUtils.getFormattedString("detailsPane.multipleItems",
- [rowCount]);
+ PlacesUIUtils.getFormattedString("detailsPane.multipleItems",
+ [rowCount]);
}
}
}
// Nothing to do if the pane was already disabled
if (!this._paneDisabled) {
gEditItemOverlay.uninitPanel();
this._setDetailsFieldsDisabledState(true);
@@ -656,36 +656,36 @@ var PlacesOrganizer = {
options);
var placeURI = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService).
newURI(placeSpec, null, null);
// Prompt the user for a name for the query.
// XXX - using prompt service for now; will need to make
// a real dialog and localize when we're sure this is the UI we want.
- var title = PlacesUtils.getString("saveSearch.title");
- var inputLabel = PlacesUtils.getString("saveSearch.inputLabel");
- var defaultText = PlacesUtils.getString("saveSearch.defaultText");
+ var title = PlacesUIUtils.getString("saveSearch.title");
+ var inputLabel = PlacesUIUtils.getString("saveSearch.inputLabel");
+ var defaultText = PlacesUIUtils.getString("saveSearch.defaultText");
var prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService);
var check = {value: false};
var input = {value: defaultText};
var save = prompts.prompt(null, title, inputLabel, input, null, check);
// Don't add the query if the user cancels or clears the seach name.
if (!save || input.value == "")
return;
// Add the place: uri as a bookmark under the bookmarks root.
- var txn = PlacesUtils.ptm.createItem(placeURI,
- PlacesUtils.bookmarksMenuFolderId,
- PlacesUtils.bookmarks.DEFAULT_INDEX,
- input.value);
- PlacesUtils.ptm.doTransaction(txn);
+ var txn = PlacesUIUtils.ptm.createItem(placeURI,
+ PlacesUtils.bookmarksMenuFolderId,
+ PlacesUtils.bookmarks.DEFAULT_INDEX,
+ input.value);
+ PlacesUIUtils.ptm.doTransaction(txn);
// select and load the new query
this._places.selectPlaceURI(placeSpec);
}
};
/**
* A set of utilities relating to search within Bookmarks and History.
@@ -788,18 +788,18 @@ var PlacesSearchBox = {
/**
* Updates the display with the title of the current collection.
* @param title
* The title of the current collection.
*/
updateCollectionTitle: function PSB_updateCollectionTitle(title) {
this.searchFilter.emptyText =
title ?
- PlacesUtils.getFormattedString("searchCurrentDefault", [title]) :
- PlacesUtils.getString("searchBookmarks");
+ PlacesUIUtils.getFormattedString("searchCurrentDefault", [title]) :
+ PlacesUIUtils.getString("searchBookmarks");
},
/**
* Gets/sets the active collection from the dropdown menu.
*/
get filterCollection() {
return this.searchFilter.getAttribute("collection");
},
@@ -1347,17 +1347,17 @@ var PlacesQueryBuilder = {
case "scopeBarHistory":
PlacesSearchBox.filterCollection = "history";
folders = [];
break;
case "scopeBarFolder":
var selectedFolder = PlacesOrganizer._places.selectedNode.itemId;
// note "all bookmarks" isn't the concrete parent of the top-level
// bookmark folders
- if (selectedFolder != PlacesUtils.allBookmarksFolderId) {
+ if (selectedFolder != PlacesUIUtils.allBookmarksFolderId) {
PlacesSearchBox.filterCollection = "collection";
folders.push(PlacesOrganizer._places.selectedNode.itemId);
break;
}
default: // all bookmarks
PlacesSearchBox.filterCollection = "bookmarks";
folders.push(PlacesUtils.bookmarksMenuFolderId,
PlacesUtils.toolbarFolderId,
@@ -1459,18 +1459,18 @@ var ViewMenu = {
menuitem.column = column;
var label = column.getAttribute("label");
if (propertyPrefix) {
var menuitemPrefix = propertyPrefix;
// for string properties, use "name" as the id, instead of "title"
// see bug #386287 for details
var columnId = column.getAttribute("anonid");
menuitemPrefix += columnId == "title" ? "name" : columnId;
- label = PlacesUtils.getString(menuitemPrefix + ".label");
- var accesskey = PlacesUtils.getString(menuitemPrefix + ".accesskey");
+ label = PlacesUIUtils.getString(menuitemPrefix + ".label");
+ var accesskey = PlacesUIUtils.getString(menuitemPrefix + ".accesskey");
menuitem.setAttribute("accesskey", accesskey);
}
menuitem.setAttribute("label", label);
if (type == "radio") {
menuitem.setAttribute("type", "radio");
menuitem.setAttribute("name", "columns");
// This column is the sort key. Its item is checked.
if (column.getAttribute("sortDirection") != "") {
--- a/browser/components/places/content/places.xul
+++ b/browser/components/places/content/places.xul
@@ -104,17 +104,17 @@
oncommand="PlacesSearchBox.findCurrent();"/>
<command id="OrganizerCommand_export"
oncommand="PlacesOrganizer.exportBookmarks();"/>
<command id="OrganizerCommand_import"
oncommand="PlacesOrganizer.importBookmarks();"/>
<command id="OrganizerCommand_backup"
oncommand="PlacesOrganizer.backupBookmarks();"/>
<command id="OrganizerCommand_restoreFromFile"
- oncommand="PlacesOrganizer.restoreFromFile();"/>
+ oncommand="PlacesOrganizer.onRestoreBookmarksFromFile();"/>
<command id="OrganizerCommand_search:save"
oncommand="PlacesOrganizer.saveSearch();"/>
<command id="OrganizerCommand_search:moreCriteria"
oncommand="PlacesQueryBuilder.addRow();"/>
<command id="OrganizerCommand:Back"
oncommand="PlacesOrganizer.back();"/>
<command id="OrganizerCommand:Forward"
oncommand="PlacesOrganizer.forward();"/>
@@ -427,30 +427,27 @@
<toolbarbutton id="scopeBarDownloads" type="radio" group="scopeBar"
oncommand="PlacesQueryBuilder.onScopeSelected(this);"
label="&search.scopeDownloads.label;"/>
-->
<toolbarbutton id="scopeBarHistory" type="radio" group="scopeBar"
oncommand="PlacesQueryBuilder.onScopeSelected(this);"
label="&search.scopeHistory.label;"/>
<spacer flex="1"/>
+ <button id="saveSearch" class="small"
+ label="&saveSearch.label;" accesskey="&saveSearch.accesskey;"
+ command="OrganizerCommand_search:save"/>
<button id="organizerScopeBarExpander"
class="expander-down"
tooltiptext="&search.scopeBarExpanderDown.tooltip;"
tooltiptextdown="&search.scopeBarExpanderDown.tooltip;"
tooltiptextup="&search.scopeBarExpanderUp.tooltip;"
oncommand="PlacesQueryBuilder.toggleVisibility();"/>
</toolbar>
-#include advancedSearch.inc
- <hbox id="searchActions" align="center">
- <spacer flex="1"/>
- <button id="saveSearch" class="small"
- label="&saveSearch.label;" accesskey="&saveSearch.accesskey;"
- command="OrganizerCommand_search:save"/>
- </hbox>
+#include advancedSearch.inc
</vbox>
<vbox flex="1">
<tree id="placeContent" class="placesTree" context="placesContext"
flex="1" type="places"
flatList="true"
enableColumnDrag="true"
onkeypress="if (event.keyCode == KeyEvent.DOM_VK_RETURN) PlacesOrganizer.openSelectedNode(event);"
ondblclick="PlacesOrganizer.openSelectedNode(event);"
--- a/browser/components/places/content/placesOverlay.xul
+++ b/browser/components/places/content/placesOverlay.xul
@@ -89,17 +89,17 @@
oncommand="goDoCommand('placesCmd_reloadMicrosummary');"/>
<command id="placesCmd_sortBy:name"
oncommand="goDoCommand('placesCmd_sortBy:name');"/>
<command id="placesCmd_moveBookmarks"
oncommand="goDoCommand('placesCmd_moveBookmarks');"/>
</commandset>
<popup id="placesContext"
- onpopupshowing="this._view = PlacesUtils.getViewForNode(document.popupNode);
+ onpopupshowing="this._view = PlacesUIUtils.getViewForNode(document.popupNode);
return this._view.buildContextMenu(this);"
onpopuphiding="this._view.destroyContextMenu();">
<menuitem id="placesContext_open"
command="placesCmd_open"
label="&cmd.open.label;"
accesskey="&cmd.open.accesskey;"
default="true"
selectiontype="single"
@@ -112,25 +112,25 @@
selection="link"/>
<menuitem id="placesContext_open:newtab"
command="placesCmd_open:tab"
label="&cmd.open_tab.label;"
accesskey="&cmd.open_tab.accesskey;"
selectiontype="single"
selection="link"/>
<menuitem id="placesContext_openContainer:tabs"
- oncommand="var view = PlacesUtils.getViewForNode(document.popupNode);
+ oncommand="var view = PlacesUIUtils.getViewForNode(document.popupNode);
view.controller.openSelectionInTabs(event);"
onclick="checkForMiddleClick(this, event);"
label="&cmd.open_all_in_tabs.label;"
accesskey="&cmd.open_all_in_tabs.accesskey;"
selectiontype="single"
selection="folder|host|query"/>
<menuitem id="placesContext_openLinks:tabs"
- oncommand="var view = PlacesUtils.getViewForNode(document.popupNode);
+ oncommand="var view = PlacesUIUtils.getViewForNode(document.popupNode);
view.controller.openSelectionInTabs(event);"
onclick="checkForMiddleClick(this, event);"
label="&cmd.open_all_in_tabs.label;"
accesskey="&cmd.open_all_in_tabs.accesskey;"
selectiontype="multiple"
selection="link"/>
<menuseparator id="placesContext_openSeparator"/>
<menuitem id="placesContext_new:bookmark"
--- a/browser/components/places/content/sidebarUtils.js
+++ b/browser/components/places/content/sidebarUtils.js
@@ -16,16 +16,17 @@
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1998
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Dan Mills <thunder@mozilla.com> (Ported from history-panel.js)
+# Marco Bonardo <mak77@supereva.it>
#
# 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
@@ -33,52 +34,69 @@
# 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 *****
var SidebarUtils = {
handleTreeClick: function SU_handleTreeClick(aTree, aEvent, aGutterSelect) {
+ // right-clicks are not handled here
+ if (aEvent.button == 2)
+ return;
+
var tbo = aTree.treeBoxObject;
-
var row = { }, col = { }, obj = { };
tbo.getCellAt(aEvent.clientX, aEvent.clientY, row, col, obj);
if (row.value == -1 || obj.value == "twisty")
return;
var mouseInGutter = false;
if (aGutterSelect) {
var x = { }, y = { }, w = { }, h = { };
tbo.getCoordsForCellItem(row.value, col.value, "image",
x, y, w, h);
mouseInGutter = aEvent.clientX < x.value;
}
-
- var modifKey = aEvent.shiftKey || aEvent.ctrlKey || aEvent.altKey ||
- aEvent.metaKey || (aEvent.button != 0);
- if (!modifKey && tbo.view.isContainer(row.value)) {
+
+#ifdef XP_MACOSX
+ var modifKey = aEvent.metaKey || aEvent.shiftKey;
+#else
+ var modifKey = aEvent.ctrlKey || aEvent.shiftKey;
+#endif
+
+ var isContainer = tbo.view.isContainer(row.value);
+ var openInTabs = isContainer &&
+ (aEvent.button == 1 ||
+ (aEvent.button == 0 && modifKey)) &&
+ PlacesUtils.hasChildURIs(tbo.view.nodeForTreeIndex(row.value));
+
+ if (aEvent.button == 0 && isContainer && !openInTabs) {
tbo.view.toggleOpenState(row.value);
return;
}
- if (!mouseInGutter &&
- aEvent.originalTarget.localName == "treechildren" &&
- (aEvent.button == 0 || aEvent.button == 1)) {
+ else if (!mouseInGutter && openInTabs &&
+ aEvent.originalTarget.localName == "treechildren") {
+ tbo.view.selection.select(row.value);
+ PlacesUIUtils.openContainerNodeInTabs(aTree.selectedNode, aEvent);
+ }
+ else if (!mouseInGutter && !isContainer &&
+ aEvent.originalTarget.localName == "treechildren") {
// Clear all other selection since we're loading a link now. We must
// do this *before* attempting to load the link since openURL uses
- // selection as an indication of which link to load.
+ // selection as an indication of which link to load.
tbo.view.selection.select(row.value);
- PlacesUtils.openNodeWithEvent(aTree.selectedNode, aEvent);
+ PlacesUIUtils.openNodeWithEvent(aTree.selectedNode, aEvent);
}
},
handleTreeKeyPress: function SU_handleTreeKeyPress(aEvent) {
if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN)
- PlacesUtils.openNodeWithEvent(aEvent.target.selectedNode, aEvent);
+ PlacesUIUtils.openNodeWithEvent(aEvent.target.selectedNode, aEvent);
},
/**
* The following function displays the URL of a node that is being
* hovered over.
*/
handleTreeMouseMove: function SU_handleTreeMouseMove(aEvent) {
if (aEvent.target.localName != "treechildren")
--- a/browser/components/places/content/toolbar.xml
+++ b/browser/components/places/content/toolbar.xml
@@ -553,17 +553,17 @@
var children = popup.childNodes;
for (var i = 0; i < children.length; i++) {
if (children[i].node == aNode) {
element = children[i];
break;
}
}
- var title = PlacesUtils.getBestTitle(aNode);
+ var title = PlacesUIUtils.getBestTitle(aNode);
}
if (PlacesUtils.nodeIsSeparator(aNode)) {
// nothing to do when a separator changes
return;
}
var iconURI = aNode.icon;
@@ -746,17 +746,16 @@
var dropPoint = { ip: null, beforeIndex: null, folderNode: null };
// Loop through all the nodes to see which one this should
// get dropped in/next to
for (var i = 0; i < this._self.childNodes.length; i++) {
var xulNode = this._self.childNodes[i];
if (PlacesUtils.nodeIsFolder(xulNode.node) &&
!PlacesUtils.nodeIsReadOnly(xulNode.node)) {
- NS_ASSERT(xulNode.getAttribute("type") == "menu");
// This is a folder. If the mouse is in the left 25% of the
// node, drop to the left of the folder. If it's in the middle
// 50%, drop into the folder. If it's past that, drop to the right.
if (event.clientX < xulNode.boxObject.x + (xulNode.boxObject.width * 0.25)) {
// Drop to the left of this folder.
dropPoint.ip =
new InsertionPoint(PlacesUtils.getConcreteItemId(result.root),
i, -1);
@@ -774,27 +773,27 @@
}
}
else {
// This is a non-folder node. If the mouse is left of the middle,
// drop to the left of the folder. If it's right, drop to the right.
if (event.clientX < xulNode.boxObject.x + (xulNode.boxObject.width / 2)) {
// Drop to the left of this bookmark.
dropPoint.ip =
- new InsertionPoint(PlacesUtils.getConcreteItemId(result.root),
- i, -1);
+ new InsertionPoint(PlacesUtils.getConcreteItemId(result.root),
+ i, -1);
dropPoint.beforeIndex = i;
return dropPoint;
}
}
}
// Should drop to the right of the last node.
dropPoint.ip =
- new InsertionPoint(PlacesUtils.getConcreteItemId(result.root),
- -1, 1);
+ new InsertionPoint(PlacesUtils.getConcreteItemId(result.root),
+ -1, 1);
dropPoint.beforeIndex = -1;
return dropPoint;
},
onDragStart: function TBV_DO_onDragStart(event, xferData, dragAction) {
// sub menus have their own d&d handlers
if (event.target.parentNode != this._self)
return false;
@@ -821,17 +820,18 @@
this._self.focus();
xferData.data = this._self._controller.getTransferData(dragAction.action);
#ifdef XP_WIN
return true;
#endif
},
canDrop: function TBV_DO_canDrop(event, session) {
- return PlacesControllerDragHelper.canDrop();
+ var ip = this._self.insertionPoint;
+ return ip && PlacesControllerDragHelper.canDrop(ip);
},
onDragOver: function TBV_DO_onDragOver(event, flavor, session) {
PlacesControllerDragHelper.currentDropTarget = event.target;
var dropPoint = this._getDropPoint(event);
var ib = this._self._dropIndicatorBar;
if (this._ibTimer) {
@@ -904,17 +904,17 @@
// Close any folder being hovered over
if (this._overFolder.node)
this._overFolder.closeTimer = this._setTimer(this._overFolder.hoverTime);
PlacesControllerDragHelper.currentDropTarget = null;
},
getSupportedFlavours: function TBV_DO_getSupportedFlavours() {
var flavorSet = new FlavourSet();
- var types = PlacesUtils.GENERIC_VIEW_DROP_TYPES;
+ var types = PlacesUIUtils.GENERIC_VIEW_DROP_TYPES;
for (var i = 0; i < types.length; ++i)
flavorSet.appendFlavour(types[i]);
return flavorSet;
}
})]]></field>
<method name="checkForMenuEvent">
<parameter name="event"/>
@@ -963,31 +963,31 @@
<method name="_showEmptyMenuItem">
<parameter name="aPopup"/>
<body><![CDATA[
if (aPopup._emptyMenuItem) {
aPopup._emptyMenuItem.hidden = false;
return;
}
- var label = PlacesUtils.getString("bookmarksMenuEmptyFolder");
+ var label = PlacesUIUtils.getString("bookmarksMenuEmptyFolder");
aPopup._emptyMenuItem = document.createElement("menuitem");
aPopup._emptyMenuItem.setAttribute("label", label);
aPopup._emptyMenuItem.setAttribute("disabled", true);
aPopup.appendChild(aPopup._emptyMenuItem);
]]></body>
</method>
<method name="insertNewItemToPopup">
<parameter name="aChild"/>
<parameter name="aParentPopup"/>
<parameter name="aBefore"/>
<body><![CDATA[
var element =
- PlacesUtils.createMenuItemForNode(aChild, this._containerNodesMap);
+ PlacesUIUtils.createMenuItemForNode(aChild, this._containerNodesMap);
if (aBefore)
aParentPopup.insertBefore(element, aBefore);
else {
// Add the new element to the menu. If there is static content at
// the end of the menu, add the element before that. Otherwise,
// just add to the end.
if (aParentPopup._endMarker != -1) {
@@ -1001,17 +1001,17 @@
</method>
<method name="_containerPopupShowing">
<parameter name="aPopup"/>
<body><![CDATA[
if (aPopup._built)
return;
- PlacesUtils.cleanPlacesPopup(aPopup);
+ PlacesUIUtils.cleanPlacesPopup(aPopup);
var resultNode = aPopup._resultNode;
if (!resultNode.containerOpen)
resultNode.containerOpen = true;
var cc = resultNode.childCount;
if (cc > 0) {
if (aPopup._emptyMenuItem)
@@ -1026,33 +1026,16 @@
// This menu is empty. If there is no static content, add
// an element to show it is empty.
if (aPopup._startMarker == -1 && aPopup._endMarker == -1)
this._showEmptyMenuItem(aPopup);
}
aPopup._built = true;
]]></body>
</method>
-
- <method name="_isChevronChild">
- <parameter name="aChild"/>
- <body><![CDATA[
- if (!this._chevron.firstChild.hasAttribute("type"))
- return false;
-
- var parent = aChild.parentNode;
- while (parent != this) {
- if (parent == this._chevron)
- return true;
-
- parent = parent.parentNode;
- }
- return false;
- ]]></body>
- </method>
</implementation>
<handlers>
<handler event="mouseover"><![CDATA[
var button = event.target;
if (button.parentNode == this && button.node &&
PlacesUtils.nodeIsURI(button.node))
window.XULBrowserWindow.setOverLink(event.target.node.uri, null);
@@ -1073,46 +1056,40 @@
if (!this.checkForMenuEvent(event, "drop"))
nsDragAndDrop.drop(event, this._DNDObserver);
]]></handler>
<handler event="dragexit"><![CDATA[
if (!this.checkForMenuEvent(event, "dragExit"))
nsDragAndDrop.dragExit(event, this._DNDObserver);
]]></handler>
<handler event="popupshowing" phase="capturing"><![CDATA[
- var target = event.originalTarget;
-
- // the chevron has its own view
- if (this._isChevronChild(target))
- return;
+ var popup = event.originalTarget;
- if (target._resultNode)
- this._containerPopupShowing(target);
+ // Avoid handling popupshowing of inner views
+ if (popup._resultNode && PlacesUIUtils.getViewForNode(popup) == this)
+ this._containerPopupShowing(popup);
- var targetParent = target.parentNode;
- if (targetParent.localName == "toolbarbutton" &&
+ var parent = popup.parentNode;
+ if (parent.localName == "toolbarbutton" &&
!PlacesControllerDragHelper.getSession())
- this._openedMenuButton = targetParent;
+ this._openedMenuButton = parent;
]]></handler>
<handler event="popuphidden"><![CDATA[
- var target = event.originalTarget;
- if (!target._resultNode)
- return;
-
- // the chevron has its own view
- if (this._isChevronChild(target))
- return;
+ var popup = event.originalTarget;
- // UI performance: folder queries are cheap, keep the resultnode open
- // so we don't rebuild its contents whenever the popup is reopened.
- if (!PlacesUtils.nodeIsFolder(target._resultNode))
- target._resultNode.containerOpen = false;
+ // Avoid handling popupshowing of inner views
+ if (popup._resultNode && PlacesUIUtils.getViewForNode(popup) == this) {
+ // UI performance: folder queries are cheap, keep the resultnode open
+ // so we don't rebuild its contents whenever the popup is reopened.
+ if (!PlacesUtils.nodeIsFolder(popup._resultNode))
+ popup._resultNode.containerOpen = false;
+ }
- var targetParent = target.parentNode;
- if (targetParent.localName == "toolbarbutton" &&
+ var parent = popup.parentNode;
+ if (parent.localName == "toolbarbutton" &&
!PlacesControllerDragHelper.getSession())
this._openedMenuButton = null;
]]></handler>
<handler event="mousemove"><![CDATA[
if (this._openedMenuButton == null || PlacesControllerDragHelper.getSession())
return;
--- a/browser/components/places/content/tree.xml
+++ b/browser/components/places/content/tree.xml
@@ -510,20 +510,16 @@
if (index != -1) {
var lastSelected = resultview.nodeForTreeIndex(index);
if (resultview.isContainer(index) && orientation == Ci.nsITreeView.DROP_ON) {
// If the last selected item is an open container, append _into_
// it, rather than insert adjacent to it.
container = lastSelected;
index = -1;
}
- else if (resultview.isSorted()) {
- // If we are into a sorted view we should append at the end
- index = -1;
- }
else if (!this._disallowInsertion(lastSelected) &&
lastSelected.containerOpen &&
orientation == Ci.nsITreeView.DROP_AFTER) {
// If the last selected item is an open container and the user is
// trying to drag into it as a first item, really insert into it.
container = lastSelected;
orientation = Ci.nsITreeView.DROP_BEFORE;
index = 0;
@@ -534,18 +530,28 @@
// insertion point.
container = lastSelected.parent || container;
// avoid the potentially expensive call to getIndexOfNode()
// if we know this container doesn't allow insertion
if (this._disallowInsertion(container))
return null;
- var lsi = PlacesUtils.getIndexOfNode(lastSelected);
- index = orientation == Ci.nsITreeView.DROP_BEFORE ? lsi : lsi + 1;
+ var queryOptions = asQuery(result.root).queryOptions;
+ if (queryOptions.excludeItems || queryOptions.excludeQueries ||
+ queryOptions.excludeReadOnlyFolders ||
+ queryOptions.sortingMode != Ci.nsINavHistoryQueryOptions.SORT_BY_NONE) {
+ // If we are within either a sorted view or a view in which
+ // some items may be invisible, insert at the end
+ index = -1;
+ }
+ else {
+ var lsi = PlacesUtils.getIndexOfNode(lastSelected);
+ index = orientation == Ci.nsITreeView.DROP_BEFORE ? lsi : lsi + 1;
+ }
}
}
if (this._disallowInsertion(container))
return null;
return new InsertionPoint(PlacesUtils.getConcreteItemId(container),
index, orientation);
@@ -706,17 +712,17 @@
}
]]></body>
</method>
<!-- nsDragAndDrop -->
<method name="getSupportedFlavours">
<body><![CDATA[
var flavorSet = new FlavourSet();
- var types = PlacesUtils.GENERIC_VIEW_DROP_TYPES;
+ var types = PlacesUIUtils.GENERIC_VIEW_DROP_TYPES;
for (var i = 0; i < types.length; ++i)
flavorSet.appendFlavour(types[i]);
return flavorSet;
]]></body>
</method>
<method name="buildContextMenu">
<parameter name="aPopup"/>
--- a/browser/components/places/content/treeView.js
+++ b/browser/components/places/content/treeView.js
@@ -187,18 +187,18 @@ PlacesTreeView.prototype = {
* It is used to compute each node's viewIndex.
*/
_buildVisibleSection:
function PTV__buildVisibleSection(aContainer, aVisible, aToOpen, aVisibleStartIndex)
{
if (!aContainer.containerOpen)
return; // nothing to do
- const openLiteral = PlacesUtils.RDF.GetResource("http://home.netscape.com/NC-rdf#open");
- const trueLiteral = PlacesUtils.RDF.GetLiteral("true");
+ const openLiteral = PlacesUIUtils.RDF.GetResource("http://home.netscape.com/NC-rdf#open");
+ const trueLiteral = PlacesUIUtils.RDF.GetLiteral("true");
var cc = aContainer.childCount;
for (var i=0; i < cc; i++) {
var curChild = aContainer.getChild(i);
var curChildType = curChild.type;
// don't display separators when sorted
if (curChildType == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) {
@@ -214,18 +214,18 @@ PlacesTreeView.prototype = {
aVisible.push({ node: curChild, properties: null });
// recursively do containers
if (!this._flatList && PlacesUtils.containerTypes.indexOf(curChildType) != -1) {
asContainer(curChild);
var resource = this._getResourceForNode(curChild);
var isopen = resource != null &&
- PlacesUtils.localStore.HasAssertion(resource, openLiteral,
- trueLiteral, true);
+ PlacesUIUtils.localStore.HasAssertion(resource, openLiteral,
+ trueLiteral, true);
if (isopen != curChild.containerOpen)
aToOpen.push(curChild);
else if (curChild.containerOpen && curChild.childCount > 0)
this._buildVisibleSection(curChild, aVisible, aToOpen, aVisibleStartIndex);
}
}
},
@@ -829,17 +829,17 @@ PlacesTreeView.prototype = {
"Node's visible index and array out of sync");
return viewIndex;
},
_getResourceForNode: function PTV_getResourceForNode(aNode)
{
var uri = aNode.uri;
NS_ASSERT(uri, "if there is no uri, we can't persist the open state");
- return uri ? PlacesUtils.RDF.GetResource(uri) : null;
+ return uri ? PlacesUIUtils.RDF.GetResource(uri) : null;
},
// nsITreeView
get rowCount() {
return this._visibleElements.length;
},
get selection() {
@@ -981,17 +981,19 @@ PlacesTreeView.prototype = {
var dragSession = dragService.getCurrentSession();
var elt = dragSession.sourceNode.parentNode;
if (elt.localName == "tree" && elt.view == this &&
this.selection.isSelected(aRow))
return false;
if (node.parent && PlacesUtils.nodeIsReadOnly(node.parent))
return false;
}
- return PlacesControllerDragHelper.canDrop();
+
+ var ip = this._getInsertionPoint(aRow, aOrientation);
+ return ip && PlacesControllerDragHelper.canDrop(ip);
},
// XXXmano: these two are copied over from tree.xml, to fix this we need to
// either add a helper to PlacesUtils or keep it here and add insertionPoint
// to the view interface.
_disallowInsertion: function PTV__disallowInsertion(aContainer) {
// Disallow insertion of items under readonly folders
return (!PlacesUtils.nodeIsFolder(aContainer) ||
@@ -1126,17 +1128,17 @@ PlacesTreeView.prototype = {
switch (columnType) {
case this.COLUMN_TYPE_TITLE:
// normally, this is just the title, but we don't want empty items in
// the tree view so return a special string if the title is empty.
// Do it here so that callers can still get at the 0 length title
// if they go through the "result" API.
if (PlacesUtils.nodeIsSeparator(node))
return "";
- return PlacesUtils.getBestTitle(node);
+ return PlacesUIUtils.getBestTitle(node);
case this.COLUMN_TYPE_TAGS:
return node.tags;
case this.COLUMN_TYPE_URI:
if (PlacesUtils.nodeIsURI(node))
return node.uri;
return "";
case this.COLUMN_TYPE_DATE:
if (node.time == 0 || !PlacesUtils.nodeIsURI(node)) {
@@ -1200,23 +1202,23 @@ PlacesTreeView.prototype = {
if (this._flatList && this._openContainerCallback) {
this._openContainerCallback(node);
return;
}
var resource = this._getResourceForNode(node);
if (resource) {
- const openLiteral = PlacesUtils.RDF.GetResource("http://home.netscape.com/NC-rdf#open");
- const trueLiteral = PlacesUtils.RDF.GetLiteral("true");
+ const openLiteral = PlacesUIUtils.RDF.GetResource("http://home.netscape.com/NC-rdf#open");
+ const trueLiteral = PlacesUIUtils.RDF.GetLiteral("true");
if (node.containerOpen)
- PlacesUtils.localStore.Unassert(resource, openLiteral, trueLiteral);
+ PlacesUIUtils.localStore.Unassert(resource, openLiteral, trueLiteral);
else
- PlacesUtils.localStore.Assert(resource, openLiteral, trueLiteral, true);
+ PlacesUIUtils.localStore.Assert(resource, openLiteral, trueLiteral, true);
}
node.containerOpen = !node.containerOpen;
},
cycleHeader: function PTV_cycleHeader(aColumn) {
if (!this._result)
throw Cr.NS_ERROR_UNEXPECTED;
@@ -1337,21 +1339,43 @@ PlacesTreeView.prototype = {
break;
default:
throw Cr.NS_ERROR_INVALID_ARG;
}
this._result.sortingAnnotation = newSortingAnnotation;
this._result.sortingMode = newSort;
},
+ isEditable: function PTV_isEditable(aRow, aColumn) {
+ // At this point we only support editing the title field.
+ if (aColumn.index != 0)
+ return false;
+
+ var node = this.nodeForTreeIndex(aRow);
+ if (!PlacesUtils.nodeIsReadOnly(node) &&
+ (PlacesUtils.nodeIsFolder(node) ||
+ (PlacesUtils.nodeIsBookmark(node) &&
+ !PlacesUtils.nodeIsLivemarkItem(node))))
+ return true;
+
+ return false;
+ },
+
+ setCellText: function PTV_setCellText(aRow, aColumn, aText) {
+ // we may only get here if the cell is editable
+ var node = this.nodeForTreeIndex(aRow);
+ if (node.title != aText) {
+ var txn = PlacesUIUtils.ptm.editItemTitle(node.itemId, aText);
+ PlacesUIUtils.ptm.doTransaction(txn);
+ }
+ },
+
selectionChanged: function() { },
cycleCell: function PTV_cycleCell(aRow, aColumn) { },
- isEditable: function(aRow, aColumn) { return false; },
isSelectable: function(aRow, aColumn) { return false; },
- setCellText: function(aRow, aColumn) { },
performAction: function(aAction) { },
performActionOnRow: function(aAction, aRow) { },
performActionOnCell: function(aAction, aRow, aColumn) { }
};
function PlacesTreeView(aShowRoot, aFlatList, aOnOpenFlatContainer) {
if (aShowRoot && aFlatList)
throw("Flat-list mode is not supported when show-root is set");
--- a/browser/components/places/content/utils.js
+++ b/browser/components/places/content/utils.js
@@ -18,16 +18,17 @@
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <beng@google.com>
* Myk Melez <myk@mozilla.org>
* Asaf Romano <mano@mozilla.com>
* Sungjoon Steve Won <stevewon@gmail.com>
+ * Dietrich Ayala <dietrich@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
@@ -41,133 +42,57 @@
function LOG(str) {
dump("*** " + str + "\n");
}
var Ci = Components.interfaces;
var Cc = Components.classes;
var Cr = Components.results;
-Components.utils.import("resource://gre/modules/JSON.jsm");
+__defineGetter__("PlacesUtils", function() {
+ delete this.PlacesUtils
+ var tmpScope = {};
+ Components.utils.import("resource://gre/modules/utils.js", tmpScope);
+ return this.PlacesUtils = tmpScope.PlacesUtils;
+});
const LOAD_IN_SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar";
const DESCRIPTION_ANNO = "bookmarkProperties/description";
-const POST_DATA_ANNO = "bookmarkProperties/POSTData";
const LMANNO_FEEDURI = "livemark/feedURI";
const LMANNO_SITEURI = "livemark/siteURI";
const ORGANIZER_FOLDER_ANNO = "PlacesOrganizer/OrganizerFolder";
const ORGANIZER_QUERY_ANNO = "PlacesOrganizer/OrganizerQuery";
#ifdef XP_MACOSX
// On Mac OSX, the transferable system converts "\r\n" to "\n\n", where we
// really just want "\n".
const NEWLINE= "\n";
#else
// On other platforms, the transferable system converts "\r\n" to "\n".
const NEWLINE = "\r\n";
#endif
function QI_node(aNode, aIID) {
- var result = null;
- try {
- result = aNode.QueryInterface(aIID);
- }
- catch (e) {
- }
- NS_ASSERT(result, "Node QI Failed");
- return result;
+ return aNode.QueryInterface(aIID);
}
function asVisit(aNode) { return QI_node(aNode, Ci.nsINavHistoryVisitResultNode); }
function asFullVisit(aNode){ return QI_node(aNode, Ci.nsINavHistoryFullVisitResultNode);}
function asContainer(aNode){ return QI_node(aNode, Ci.nsINavHistoryContainerResultNode);}
function asQuery(aNode) { return QI_node(aNode, Ci.nsINavHistoryQueryResultNode); }
-var PlacesUtils = {
- // Place entries that are containers, e.g. bookmark folders or queries.
- TYPE_X_MOZ_PLACE_CONTAINER: "text/x-moz-place-container",
- // Place entries that are bookmark separators.
- TYPE_X_MOZ_PLACE_SEPARATOR: "text/x-moz-place-separator",
- // Place entries that are not containers or separators
- TYPE_X_MOZ_PLACE: "text/x-moz-place",
- // Place entries in shortcut url format (url\ntitle)
- TYPE_X_MOZ_URL: "text/x-moz-url",
- // Place entries formatted as HTML anchors
- TYPE_HTML: "text/html",
- // Place entries as raw URL text
- TYPE_UNICODE: "text/unicode",
-
- /**
- * The Bookmarks Service.
- */
- get bookmarks() {
- delete this.bookmarks;
- return this.bookmarks = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
- getService(Ci.nsINavBookmarksService);
- },
-
- /**
- * The Nav History Service.
- */
- get history() {
- delete this.history;
- return this.history = Cc["@mozilla.org/browser/nav-history-service;1"].
- getService(Ci.nsINavHistoryService);
- },
-
- get globalHistory() {
- delete this.globalHistory;
- return this.globalHistory = Cc["@mozilla.org/browser/global-history;2"].
- getService(Ci.nsIBrowserHistory);
- },
-
- /**
- * The Live Bookmark Service.
- */
- get livemarks() {
- delete this.livemarks;
- return this.livemarks = Cc["@mozilla.org/browser/livemark-service;2"].
- getService(Ci.nsILivemarkService);
- },
-
- /**
- * The Annotations Service.
- */
- get annotations() {
- delete this.annotations;
- return this.annotations = Cc["@mozilla.org/browser/annotation-service;1"].
- getService(Ci.nsIAnnotationService);
- },
-
- /**
- * The Favicons Service
- */
- get favicons() {
- delete this.favicons;
- return this.favicons = Cc["@mozilla.org/browser/favicon-service;1"].
- getService(Ci.nsIFaviconService);
- },
-
+var PlacesUIUtils = {
/**
* The Microsummary Service
*/
get microsummaries() {
delete this.microsummaries;
return this.microsummaries = Cc["@mozilla.org/microsummary/service;1"].
getService(Ci.nsIMicrosummaryService);
},
- /**
- * The Places Tagging Service
- */
- get tagging() {
- delete this.tagging;
- return this.tagging = Cc["@mozilla.org/browser/tagging-service;1"].
- getService(Ci.nsITaggingService);
- },
-
get RDF() {
delete this.RDF;
return this.RDF = Cc["@mozilla.org/rdf/rdf-service;1"].
getService(Ci.nsIRDFService);
},
get localStore() {
delete this.localStore;
@@ -196,29 +121,16 @@ var PlacesUtils = {
delete this.ellipsis;
var pref = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
return this.ellipsis = pref.getComplexValue("intl.ellipsis",
Ci.nsIPrefLocalizedString).data;
},
/**
- * Makes a URI from a spec.
- * @param aSpec
- * The string spec of the URI
- * @returns A URI object for the spec.
- */
- _uri: function PU__uri(aSpec) {
- NS_ASSERT(aSpec, "empty URL spec");
- return Cc["@mozilla.org/network/io-service;1"].
- getService(Ci.nsIIOService).
- newURI(aSpec, null, null);
- },
-
- /**
* Makes a URI from a spec, and do fixup
* @param aSpec
* The string spec of the URI
* @returns A URI object for the spec.
*/
createFixedURI: function PU_createFixedURI(aSpec) {
return this.URIFixup.createFixupURI(aSpec, 0);
},
@@ -252,438 +164,28 @@ var PlacesUtils = {
return this._bundle.formatStringFromName(key, params, params.length);
},
getString: function PU_getString(key) {
return this._bundle.GetStringFromName(key);
},
/**
- * Determines whether or not a ResultNode is a Bookmark folder.
- * @param aNode
- * A result node
- * @returns true if the node is a Bookmark folder, false otherwise
- */
- nodeIsFolder: function PU_nodeIsFolder(aNode) {
- NS_ASSERT(aNode, "null node");
- return (aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER ||
- aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT);
- },
-
- /**
- * Determines whether or not a ResultNode represents a bookmarked URI.
- * @param aNode
- * A result node
- * @returns true if the node represents a bookmarked URI, false otherwise
- */
- nodeIsBookmark: function PU_nodeIsBookmark(aNode) {
- NS_ASSERT(aNode, "null node");
- return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_URI &&
- aNode.itemId != -1;
- },
-
- /**
- * Determines whether or not a ResultNode is a Bookmark separator.
- * @param aNode
- * A result node
- * @returns true if the node is a Bookmark separator, false otherwise
- */
- nodeIsSeparator: function PU_nodeIsSeparator(aNode) {
- NS_ASSERT(aNode, "null node");
-
- return (aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR);
- },
-
- /**
- * Determines whether or not a ResultNode is a visit item.
- * @param aNode
- * A result node
- * @returns true if the node is a visit item, false otherwise
- */
- nodeIsVisit: function PU_nodeIsVisit(aNode) {
- NS_ASSERT(aNode, "null node");
-
- const NHRN = Ci.nsINavHistoryResultNode;
- var type = aNode.type;
- return type == NHRN.RESULT_TYPE_VISIT ||
- type == NHRN.RESULT_TYPE_FULL_VISIT;
- },
-
- /**
- * Determines whether or not a ResultNode is a URL item.
- * @param aNode
- * A result node
- * @returns true if the node is a URL item, false otherwise
- */
- uriTypes: [Ci.nsINavHistoryResultNode.RESULT_TYPE_URI,
- Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT,
- Ci.nsINavHistoryResultNode.RESULT_TYPE_FULL_VISIT],
- nodeIsURI: function PU_nodeIsURI(aNode) {
- NS_ASSERT(aNode, "null node");
- return this.uriTypes.indexOf(aNode.type) != -1;
- },
-
- /**
- * Determines whether or not a ResultNode is a Query item.
- * @param aNode
- * A result node
- * @returns true if the node is a Query item, false otherwise
- */
- nodeIsQuery: function PU_nodeIsQuery(aNode) {
- NS_ASSERT(aNode, "null node");
- return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY;
- },
-
- /**
- * Determines if a node is read only (children cannot be inserted, sometimes
- * they cannot be removed depending on the circumstance)
- * @param aNode
- * A result node
- * @returns true if the node is readonly, false otherwise
- */
- nodeIsReadOnly: function PU_nodeIsReadOnly(aNode) {
- NS_ASSERT(aNode, "null node");
-
- if (this.nodeIsFolder(aNode))
- return this.bookmarks.getFolderReadonly(asQuery(aNode).folderItemId);
- if (this.nodeIsQuery(aNode))
- return asQuery(aNode).childrenReadOnly;
- return false;
- },
-
- /**
- * Determines whether or not a ResultNode is a host container.
- * @param aNode
- * A result node
- * @returns true if the node is a host container, false otherwise
- */
- nodeIsHost: function PU_nodeIsHost(aNode) {
- NS_ASSERT(aNode, "null node");
- return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY &&
- aNode.parent &&
- asQuery(aNode.parent).queryOptions.resultType ==
- Ci.nsINavHistoryQueryOptions.RESULTS_AS_SITE_QUERY;
- },
-
- /**
- * Determines whether or not a ResultNode is a day container.
- * @param node
- * A NavHistoryResultNode
- * @returns true if the node is a day container, false otherwise
- */
- nodeIsDay: function PU_nodeIsDay(aNode) {
- NS_ASSERT(aNode, "null node");
- var resultType;
- return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY &&
- aNode.parent &&
- ((resultType = asQuery(aNode.parent).queryOptions.resultType) ==
- Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY ||
- resultType == Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_SITE_QUERY);
- },
-
- /**
- * Determines whether or not a ResultNode is a container.
- * @param aNode
- * A result node
- * @returns true if the node is a container item, false otherwise
- */
- containerTypes: [Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER,
- Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT,
- Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY,
- Ci.nsINavHistoryResultNode.RESULT_TYPE_DYNAMIC_CONTAINER],
- nodeIsContainer: function PU_nodeIsContainer(aNode) {
- NS_ASSERT(aNode, "null node");
- return this.containerTypes.indexOf(aNode.type) != -1;
- },
-
- /**
- * Determines whether or not a result-node is a dynamic-container item.
- * The dynamic container result node type is for dynamically created
- * containers (e.g. for the file browser service where you get your folders
- * in bookmark menus).
- * @param aNode
- * A result node
- * @returns true if the node is a dynamic container item, false otherwise
- */
- nodeIsDynamicContainer: function PU_nodeIsDynamicContainer(aNode) {
- NS_ASSERT(aNode, "null node");
- if (aNode.type == NHRN.RESULT_TYPE_DYNAMIC_CONTAINER)
- return true;
- return false;
- },
-
- /**
- * Determines whether a result node is a remote container registered by the
- * livemark service.
- * @param aNode
- * A result Node
- * @returns true if the node is a livemark container item
- */
- nodeIsLivemarkContainer: function PU_nodeIsLivemarkContainer(aNode) {
- // Use the annotations service directly to avoid instantiating
- // the Livemark service on startup. (bug 398300)
- return this.nodeIsFolder(aNode) &&
- this.annotations.itemHasAnnotation(aNode.itemId, LMANNO_FEEDURI);
- },
-
- /**
- * Determines whether a result node is a live-bookmark item
- * @param aNode
- * A result node
- * @returns true if the node is a livemark container item
- */
- nodeIsLivemarkItem: function PU_nodeIsLivemarkItem(aNode) {
- return aNode.parent && this.nodeIsLivemarkContainer(aNode.parent);
- },
-
- /**
- * Determines whether or not a node is a readonly folder.
- * @param aNode
- * The node to test.
- * @returns true if the node is a readonly folder.
- */
- isReadonlyFolder: function(aNode) {
- NS_ASSERT(aNode, "null node");
-
- return this.nodeIsFolder(aNode) &&
- this.bookmarks.getFolderReadonly(asQuery(aNode).folderItemId);
- },
-
- /**
- * Gets the concrete item-id for the given node. Generally, this is just
- * node.itemId, but for folder-shortcuts that's node.folderItemId.
- */
- getConcreteItemId: function PU_getConcreteItemId(aNode) {
- if (aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT)
- return asQuery(aNode).folderItemId;
- return aNode.itemId;
- },
-
- /**
- * Gets the index of a node within its parent container
- * @param aNode
- * The node to look up
- * @returns The index of the node within its parent container, or -1 if the
- * node was not found or the node specified has no parent.
- */
- getIndexOfNode: function PU_getIndexOfNode(aNode) {
- NS_ASSERT(aNode, "null node");
-
- var parent = aNode.parent;
- if (!parent)
- return -1;
- var wasOpen = parent.containerOpen;
- var result, oldViewer;
- if (!wasOpen) {
- result = parent.parentResult;
- oldViewer = result.viewer;
- result.viewer = null;
- parent.containerOpen = true;
- }
- var cc = parent.childCount;
- for (var i = 0; i < cc && parent.getChild(i) != aNode; ++i);
- if (!wasOpen) {
- parent.containerOpen = false;
- result.viewer = oldViewer;
- }
- return i < cc ? i : -1;
- },
-
- /**
- * String-wraps a result node according to the rules of the specified
- * content type.
- * @param aNode
- * The Result node to wrap (serialize)
- * @param aType
- * The content type to serialize as
- * @param [optional] aOverrideURI
- * Used instead of the node's URI if provided.
- * This is useful for wrapping a container as TYPE_X_MOZ_URL,
- * TYPE_HTML or TYPE_UNICODE.
- * @returns A string serialization of the node
- */
- wrapNode: function PU_wrapNode(aNode, aType, aOverrideURI) {
- var self = this;
-
- // when wrapping a node, we want all the items, even if the original
- // query options are excluding them.
- // this can happen when copying from the left hand pane of the bookmarks
- // organizer
- function convertNode(cNode) {
- try {
- if (self.nodeIsFolder(cNode) && cNode.queryOptions.excludeItems)
- return self.getFolderContents(cNode.itemId, false, true).root;
- }
- catch (e) {
- }
- return cNode;
- }
-
- switch (aType) {
- case this.TYPE_X_MOZ_PLACE:
- case this.TYPE_X_MOZ_PLACE_SEPARATOR:
- case this.TYPE_X_MOZ_PLACE_CONTAINER:
- function gatherDataPlace(bNode) {
- var nodeId = 0;
- if (bNode.itemId != -1)
- nodeId = bNode.itemId;
- var nodeUri = bNode.uri
- var nodeTitle = bNode.title;
- var nodeParentId = 0;
- if (bNode.parent && self.nodeIsFolder(bNode.parent))
- nodeParentId = bNode.parent.itemId;
- var nodeIndex = self.getIndexOfNode(bNode);
- var nodeKeyword = self.bookmarks.getKeywordForBookmark(bNode.itemId);
- var nodeAnnos = self.getAnnotationsForItem(bNode.itemId);
- var nodeType = "";
- if (self.nodeIsContainer(bNode))
- nodeType = self.TYPE_X_MOZ_PLACE_CONTAINER;
- else if (self.nodeIsURI(bNode)) // a bookmark or a history visit
- nodeType = self.TYPE_X_MOZ_PLACE;
- else if (self.nodeIsSeparator(bNode))
- nodeType = self.TYPE_X_MOZ_PLACE_SEPARATOR;
-
- var node = { id: nodeId,
- uri: nodeUri,
- title: nodeTitle,
- parent: nodeParentId,
- index: nodeIndex,
- keyword: nodeKeyword,
- annos: nodeAnnos,
- type: nodeType };
-
- // Recurse down children if the node is a folder
- if (self.nodeIsContainer(bNode)) {
- asContainer(bNode);
- if (self.nodeIsLivemarkContainer(bNode)) {
- // just save the livemark info, reinstantiate on other end
- var feedURI = self.livemarks.getFeedURI(bNode.itemId).spec;
- var siteURI = self.livemarks.getSiteURI(bNode.itemId).spec;
- node.uri = { feed: feedURI,
- site: siteURI };
- }
- else { // bookmark folders + history containers
- var wasOpen = bNode.containerOpen;
- if (!wasOpen)
- bNode.containerOpen = true;
- var childNodes = [];
- var cc = bNode.childCount;
- for (var i = 0; i < cc; ++i) {
- var childObj = gatherDataPlace(bNode.getChild(i));
- if (childObj != null)
- childNodes.push(childObj);
- }
- var parent = node;
- node = { folder: parent,
- children: childNodes,
- type: self.TYPE_X_MOZ_PLACE_CONTAINER };
- bNode.containerOpen = wasOpen;
- }
- }
- return node;
- }
- return JSON.toString(gatherDataPlace(convertNode(aNode)));
-
- case this.TYPE_X_MOZ_URL:
- function gatherDataUrl(bNode) {
- if (self.nodeIsLivemarkContainer(bNode)) {
- var siteURI = self.livemarks.getSiteURI(bNode.itemId).spec;
- return siteURI + NEWLINE + bNode.title;
- }
- if (self.nodeIsURI(bNode))
- return (aOverrideURI || bNode.uri) + NEWLINE + bNode.title;
- // ignore containers and separators - items without valid URIs
- return "";
- }
- return gatherDataUrl(convertNode(aNode));
-
- case this.TYPE_HTML:
- function gatherDataHtml(bNode) {
- function htmlEscape(s) {
- s = s.replace(/&/g, "&");
- s = s.replace(/>/g, ">");
- s = s.replace(/</g, "<");
- s = s.replace(/"/g, """);
- s = s.replace(/'/g, "'");
- return s;
- }
- // escape out potential HTML in the title
- var escapedTitle = htmlEscape(bNode.title);
- if (self.nodeIsLivemarkContainer(bNode)) {
- var siteURI = self.livemarks.getSiteURI(bNode.itemId).spec;
- return "<A HREF=\"" + siteURI + "\">" + escapedTitle + "</A>" + NEWLINE;
- }
- if (self.nodeIsContainer(bNode)) {
- asContainer(bNode);
- var wasOpen = bNode.containerOpen;
- if (!wasOpen)
- bNode.containerOpen = true;
-
- var childString = "<DL><DT>" + escapedTitle + "</DT>" + NEWLINE;
- var cc = bNode.childCount;
- for (var i = 0; i < cc; ++i)
- childString += "<DD>"
- + NEWLINE
- + gatherDataHtml(bNode.getChild(i))
- + "</DD>"
- + NEWLINE;
- bNode.containerOpen = wasOpen;
- return childString + "</DL>" + NEWLINE;
- }
- if (self.nodeIsURI(bNode))
- return "<A HREF=\"" + bNode.uri + "\">" + escapedTitle + "</A>" + NEWLINE;
- if (self.nodeIsSeparator(bNode))
- return "<HR>" + NEWLINE;
- return "";
- }
- return gatherDataHtml(convertNode(aNode));
- }
- // case this.TYPE_UNICODE:
- function gatherDataText(bNode) {
- if (self.nodeIsLivemarkContainer(bNode))
- return self.livemarks.getSiteURI(bNode.itemId).spec;
- if (self.nodeIsContainer(bNode)) {
- asContainer(bNode);
- var wasOpen = bNode.containerOpen;
- if (!wasOpen)
- bNode.containerOpen = true;
-
- var childString = bNode.title + NEWLINE;
- var cc = bNode.childCount;
- for (var i = 0; i < cc; ++i) {
- var child = bNode.getChild(i);
- var suffix = i < (cc - 1) ? NEWLINE : "";
- childString += gatherDataText(child) + suffix;
- }
- bNode.containerOpen = wasOpen;
- return childString;
- }
- if (self.nodeIsURI(bNode))
- return (aOverrideURI || bNode.uri);
- if (self.nodeIsSeparator(bNode))
- return "--------------------";
- return "";
- }
-
- return gatherDataText(convertNode(aNode));
- },
-
- /**
* Get a transaction for copying a uri item from one container to another
* as a bookmark.
* @param aURI
* The URI of the item being copied
* @param aContainer
* The container being copied into
* @param aIndex
* The index within the container the item is copied to
* @returns A nsITransaction object that performs the copy.
*/
_getURIItemCopyTransaction: function (aData, aContainer, aIndex) {
- return this.ptm.createItem(this._uri(aData.uri), aContainer, aIndex,
+ return this.ptm.createItem(PlacesUtils._uri(aData.uri), aContainer, aIndex,
aData.title, "");
},
/**
* Get a transaction for copying a bookmark item from one container to
* another.
* @param aID
* The identifier of the bookmark item being copied
@@ -694,25 +196,24 @@ var PlacesUtils = {
* @param [optional] aExcludeAnnotations
* Optional, array of annotations (listed by their names) to exclude
* when copying the item.
* @returns A nsITransaction object that performs the copy.
*/
_getBookmarkItemCopyTransaction:
function PU__getBookmarkItemCopyTransaction(aData, aContainer, aIndex,
aExcludeAnnotations) {
- var itemURL = this._uri(aData.uri);
+ var itemURL = PlacesUtils._uri(aData.uri);
var itemTitle = aData.title;
- var keyword = aData.keyword;
- var annos = aData.annos;
+ var keyword = aData.keyword || null;
+ var annos = aData.annos || [];
if (aExcludeAnnotations) {
- annos =
- annos.filter(function(aValue, aIndex, aArray) {
- return aExcludeAnnotations.indexOf(aValue.name) == -1;
- });
+ annos = annos.filter(function(aValue, aIndex, aArray) {
+ return aExcludeAnnotations.indexOf(aValue.name) == -1;
+ });
}
var childTxns = [];
if (aData.dateAdded)
childTxns.push(this.ptm.editItemDateAdded(null, aData.dateAdded));
if (aData.lastModified)
childTxns.push(this.ptm.editItemLastModified(null, aData.lastModified));
return this.ptm.createItem(itemURL, aContainer, aIndex, itemTitle, keyword,
@@ -742,113 +243,87 @@ var PlacesUtils = {
var txn = null;
var node = aChildren[i];
// adjusted to make sure that items are given the correct index -
// transactions insert differently if index == -1
if (aIndex > -1)
index = aIndex + i;
- if (node.type == self.TYPE_X_MOZ_PLACE_CONTAINER) {
- if (node.folder) {
- var title = node.folder.title;
- var annos = node.folder.annos;
- var folderItemsTransactions =
- getChildItemsTransactions(node.children);
- txn = self.ptm.createFolder(title, -1, index, annos,
+ if (node.type == PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER) {
+ if (node.livemark && node.annos) // node is a livemark
+ txn = self._getLivemarkCopyTransaction(node, aContainer, index);
+ else {
+ var folderItemsTransactions = [];
+ if (node.dateAdded)
+ folderItemsTransactions.push(self.ptm.editItemDateAdded(null, node.dateAdded));
+ if (node.lastModified)
+ folderItemsTransactions.push(self.ptm.editItemLastModified(null, node.lastModified));
+ var annos = node.annos || [];
+ txn = self.ptm.createFolder(node.title, -1, index, annos,
folderItemsTransactions);
}
- else { // node is a livemark
- var feedURI = self._uri(node.uri.feed);
- var siteURI = self._uri(node.uri.site);
- txn = self.ptm.createLivemark(feedURI, siteURI, node.title,
- aContainer, index, node.annos);
- }
}
- else if (node.type == self.TYPE_X_MOZ_PLACE_SEPARATOR)
+ else if (node.type == PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR)
txn = self.ptm.createSeparator(-1, index);
- else if (node.type == self.TYPE_X_MOZ_PLACE)
+ else if (node.type == PlacesUtils.TYPE_X_MOZ_PLACE)
txn = self._getBookmarkItemCopyTransaction(node, -1, index);
NS_ASSERT(txn, "Unexpected item under a bookmarks folder");
if (txn)
childItemsTransactions.push(txn);
}
return childItemsTransactions;
}
- var title = aData.folder.title;
- var annos = aData.folder.annos;
- var childItems = getChildItemsTransactions(aData.children);
- if (aData.folder.dateAdded)
- childItems.push(this.ptm.editItemDateAdded(null, aData.folder.dateAdded));
- if (aData.folder.lastModified)
- childItems.push(this.ptm.editItemLastModified(null, aData.folder.lastModified));
- return this.ptm.createFolder(title, aContainer, aIndex, annos, childItems);
+ // tag folders use tag transactions
+ if (aContainer == PlacesUtils.bookmarks.tagsFolder) {
+ var txns = [];
+ if (aData.children) {
+ aData.children.forEach(function(aChild) {
+ txns.push(this.ptm.tagURI(PlacesUtils._uri(aChild.uri), [aData.title]));
+ }, this);
+ }
+ return this.ptm.aggregateTransactions("addTags", txns);
+ }
+ else if (aData.livemark && aData.annos) {
+ // Place is a Livemark Container
+ return this._getLivemarkCopyTransaction(aData, aContainer, aIndex);
+ }
+ else {
+ var childItems = getChildItemsTransactions(aData.children);
+ if (aData.dateAdded)
+ childItems.push(this.ptm.editItemDateAdded(null, aData.dateAdded));
+ if (aData.lastModified)
+ childItems.push(this.ptm.editItemLastModified(null, aData.lastModified));
+
+ var annos = aData.annos || [];
+ return this.ptm.createFolder(aData.title, aContainer, aIndex, annos, childItems);
+ }
},
- /**
- * Unwraps data from the Clipboard or the current Drag Session.
- * @param blob
- * A blob (string) of data, in some format we potentially know how
- * to parse.
- * @param type
- * The content type of the blob.
- * @returns An array of objects representing each item contained by the source.
- */
- unwrapNodes: function PU_unwrapNodes(blob, type) {
- // We split on "\n" because the transferable system converts "\r\n" to "\n"
- var nodes = [];
- switch(type) {
- case this.TYPE_X_MOZ_PLACE:
- case this.TYPE_X_MOZ_PLACE_SEPARATOR:
- case this.TYPE_X_MOZ_PLACE_CONTAINER:
- nodes = JSON.fromString("[" + blob + "]");
- break;
- case this.TYPE_X_MOZ_URL:
- var parts = blob.split("\n");
- // data in this type has 2 parts per entry, so if there are fewer
- // than 2 parts left, the blob is malformed and we should stop
- // but drag and drop of files from the shell has parts.length = 1
- if (parts.length != 1 && parts.length % 2)
- break;
- for (var i = 0; i < parts.length; i=i+2) {
- var uriString = parts[i];
- var titleString = "";
- if (parts.length > i+1)
- titleString = parts[i+1];
- else {
- // for drag and drop of files, try to use the leafName as title
- try {
- titleString = this._uri(uriString).QueryInterface(Ci.nsIURL)
- .fileName;
- }
- catch (e) {}
- }
- // note: this._uri() will throw if uriString is not a valid URI
- if (this._uri(uriString)) {
- nodes.push({ uri: uriString,
- title: titleString ? titleString : uriString });
- }
- }
- break;
- case this.TYPE_UNICODE:
- var parts = blob.split("\n");
- for (var i = 0; i < parts.length; i++) {
- var uriString = parts[i];
- // note: this._uri() will throw if uriString is not a valid URI
- if (uriString != "" && this._uri(uriString))
- nodes.push({ uri: uriString, title: uriString });
- }
- break;
- default:
- LOG("Cannot unwrap data of type " + type);
- throw Cr.NS_ERROR_INVALID_ARG;
- }
- return nodes;
+ _getLivemarkCopyTransaction:
+ function PU__getLivemarkCopyTransaction(aData, aContainer, aIndex) {
+ NS_ASSERT(aData.livemark && aData.annos, "node is not a livemark");
+ // Place is a Livemark Container
+ var feedURI = null;
+ var siteURI = null;
+ aData.annos = aData.annos.filter(function(aAnno) {
+ if (aAnno.name == LMANNO_FEEDURI) {
+ feedURI = PlacesUtils._uri(aAnno.value);
+ return false;
+ }
+ else if (aAnno.name == LMANNO_SITEURI) {
+ siteURI = PlacesUtils._uri(aAnno.value);
+ return false;
+ }
+ return true;
+ }, this);
+ return this.ptm.createLivemark(feedURI, siteURI, aData.title, aContainer,
+ aIndex, aData.annos);
},
/**
* Constructs a Transaction for the drop or paste of a blob of data into
* a container.
* @param data
* The unwrapped data blob of dropped or pasted data.
* @param type
@@ -860,91 +335,52 @@ var PlacesUtils = {
* @param copy
* The drag action was copy, so don't move folders or links.
* @returns An object implementing nsITransaction that can perform
* the move/insert.
*/
makeTransaction: function PU_makeTransaction(data, type, container,
index, copy) {
switch (data.type) {
- case this.TYPE_X_MOZ_PLACE_CONTAINER:
- if (data.folder) {
- // Place is a folder.
+ case PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER:
if (copy)
return this._getFolderCopyTransaction(data, container, index);
- }
- else if (copy) {
- // Place is a Livemark Container, should be reinstantiated
- var feedURI = this._uri(data.uri.feed);
- var siteURI = this._uri(data.uri.site);
- return this.ptm.createLivemark(feedURI, siteURI, data.title, container,
- index, data.annos);
- }
- break;
- case this.TYPE_X_MOZ_PLACE:
- if (data.id <= 0)
- return this._getURIItemCopyTransaction(data, container, index);
-
- if (copy) {
- // Copying a child of a live-bookmark by itself should result
- // as a new normal bookmark item (bug 376731)
- var copyBookmarkAnno =
- this._getBookmarkItemCopyTransaction(data, container, index,
- ["livemark/bookmarkFeedURI"]);
- return copyBookmarkAnno;
- }
- break;
- case this.TYPE_X_MOZ_PLACE_SEPARATOR:
- if (copy) {
+ else { // Move the item
+ var id = data.folder ? data.folder.id : data.id;
+ return this.ptm.moveItem(id, container, index);
+ }
+ break;
+ case PlacesUtils.TYPE_X_MOZ_PLACE:
+ if (data.id <= 0) // non-bookmark item
+ return this._getURIItemCopyTransaction(data, container, index);
+
+ if (copy) {
+ // Copying a child of a live-bookmark by itself should result
+ // as a new normal bookmark item (bug 376731)
+ var copyBookmarkAnno =
+ this._getBookmarkItemCopyTransaction(data, container, index,
+ ["livemark/bookmarkFeedURI"]);
+ return copyBookmarkAnno;
+ }
+ else
+ return this.ptm.moveItem(data.id, container, index);
+ break;
+ case PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR:
// There is no data in a separator, so copying it just amounts to
// inserting a new separator.
return this.ptm.createSeparator(container, index);
- }
- break;
- default:
- if (type == this.TYPE_X_MOZ_URL || type == this.TYPE_UNICODE) {
- var title = (type == this.TYPE_X_MOZ_URL) ? data.title : data.uri;
- return this.ptm.createItem(this._uri(data.uri), container, index,
- title);
- }
- return null;
+ break;
+ default:
+ if (type == PlacesUtils.TYPE_X_MOZ_URL || type == PlacesUtils.TYPE_UNICODE) {
+ var title = (type == PlacesUtils.TYPE_X_MOZ_URL) ? data.title : data.uri;
+ return this.ptm.createItem(PlacesUtils._uri(data.uri), container, index,
+ title);
+ }
}
- if (data.id <= 0)
- return null;
-
- // Move the item otherwise
- var id = data.folder ? data.folder.id : data.id;
- return this.ptm.moveItem(id, container, index);
- },
-
- /**
- * Generates a nsINavHistoryResult for the contents of a folder.
- * @param folderId
- * The folder to open
- * @param [optional] excludeItems
- * True to hide all items (individual bookmarks). This is used on
- * the left places pane so you just get a folder hierarchy.
- * @param [optional] expandQueries
- * True to make query items expand as new containers. For managing,
- * you want this to be false, for menus and such, you want this to
- * be true.
- * @returns A nsINavHistoryResult containing the contents of the
- * folder. The result.root is guaranteed to be open.
- */
- getFolderContents:
- function PU_getFolderContents(aFolderId, aExcludeItems, aExpandQueries) {
- var query = this.history.getNewQuery();
- query.setFolders([aFolderId], 1);
- var options = this.history.getNewQueryOptions();
- options.excludeItems = aExcludeItems;
- options.expandQueries = aExpandQueries;
-
- var result = this.history.executeQuery(query, options);
- result.root.containerOpen = true;
- return result;
+ return null;
},
/**
* Methods to show the bookmarkProperties dialog in its various modes.
*
* The showMinimalAdd* methods open the dialog by its alternative URI. Thus
* they persist the dialog dimensions separately from the showAdd* methods.
* Note these variants also do not return the dialog "performed" state since
@@ -1310,41 +746,42 @@ var PlacesUtils = {
* By calling this before we visit a URL, we will use TRANSITION_TYPED
* as the transition for the visit to that URL (if we don't have a referrer).
* This is used when visiting pages from the history menu, history sidebar,
* url bar, url autocomplete results, and history searches from the places
* organizer. If we don't call this, we'll treat those visits as
* TRANSITION_LINK.
*/
markPageAsTyped: function PU_markPageAsTyped(aURL) {
- this.globalHistory.markPageAsTyped(this.createFixedURI(aURL));
+ PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory)
+ .markPageAsTyped(this.createFixedURI(aURL));
},
/**
* By calling this before we visit a URL, we will use TRANSITION_BOOKMARK
* as the transition for the visit to that URL (if we don't have a referrer).
* This is used when visiting pages from the bookmarks menu,
* personal toolbar, and bookmarks from within the places organizer.
* If we don't call this, we'll treat those visits as TRANSITION_LINK.
*/
markPageAsFollowedBookmark: function PU_markPageAsFollowedBookmark(aURL) {
- this.history.markPageAsFollowedBookmark(this.createFixedURI(aURL));
+ PlacesUtils.history.markPageAsFollowedBookmark(this.createFixedURI(aURL));
},
/**
* Allows opening of javascript/data URI only if the given node is
* bookmarked (see bug 224521).
* @param aURINode
* a URI node
* @return true if it's safe to open the node in the browser, false otherwise.
*
*/
checkURLSecurity: function PU_checkURLSecurity(aURINode) {
- if (!this.nodeIsBookmark(aURINode)) {
- var uri = this._uri(aURINode.uri);
+ if (!PlacesUtils.nodeIsBookmark(aURINode)) {
+ var uri = PlacesUtils._uri(aURINode.uri);
if (uri.schemeIs("javascript") || uri.schemeIs("data")) {
const BRANDING_BUNDLE_URI = "chrome://branding/locale/brand.properties";
var brandShortName = Cc["@mozilla.org/intl/stringbundle;1"].
getService(Ci.nsIStringBundleService).
createBundle(BRANDING_BUNDLE_URI).
GetStringFromName("brandShortName");
var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService);
@@ -1353,147 +790,16 @@ var PlacesUtils = {
promptService.alert(window, brandShortName, errorStr);
return false;
}
}
return true;
},
/**
- * Fetch all annotations for a URI, including all properties of each
- * annotation which would be required to recreate it.
- * @param aURI
- * The URI for which annotations are to be retrieved.
- * @return Array of objects, each containing the following properties:
- * name, flags, expires, mimeType, type, value
- */
- getAnnotationsForURI: function PU_getAnnotationsForURI(aURI) {
- var annosvc = this.annotations;
- var annos = [], val = null;
- var annoNames = annosvc.getPageAnnotationNames(aURI, {});
- for (var i = 0; i < annoNames.length; i++) {
- var flags = {}, exp = {}, mimeType = {}, storageType = {};
- annosvc.getPageAnnotationInfo(aURI, annoNames[i], flags, exp, mimeType, storageType);
- if (storageType.value == annosvc.TYPE_BINARY) {
- var data = {}, length = {}, mimeType = {};
- annosvc.getPageAnnotationBinary(aURI, annoNames[i], data, length, mimeType);
- val = data.value;
- }
- else
- val = annosvc.getPageAnnotation(aURI, annoNames[i]);