This commit is contained in:
Uri Bernstein 2008-08-09 19:34:08 +03:00
Родитель 514fbf8ecc 31bc441e4d
Коммит 8c80506f1c
1632 изменённых файлов: 141373 добавлений и 55665 удалений

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

@ -19,8 +19,7 @@
^security/manager/\.nss\.checkout$
# Build directories
^obj-
^objdir-
^obj
# Build directories for js shell
_DBG\.OBJ/

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

@ -2,3 +2,9 @@ df7a3c8ffeeaba229067efee5a20e21dae0dd877 MOZILLA_1_9_a4_BASE
4209e16b58411750ac73f761023e46b76b793e2c MOZILLA_1_9_a6_BASE
66a5c7bce7ee86a820d3c0d54fa07cb719be751c MOZILLA_1_9_a7_BASE
caeba7562e495a9f604984df0b48b6f99bec3e2e FENNEC_M4
9d9941eacb14827fdab4716710042fdde84eb60d FIREFOX_3_1a1_RELEASE
9d9941eacb14827fdab4716710042fdde84eb60d FIREFOX_3_1a1_BUILD1
c1d7e318a27574c995631fec166ad42672475702 FIREFOX_3_1a1_BUILD2
c1d7e318a27574c995631fec166ad42672475702 FIREFOX_3_1a1_RELEASE
afc4ee509d9ca3bb4031015c3c22963dcb4b7e7f FIREFOX_3_1a1_RELEASE
afc4ee509d9ca3bb4031015c3c22963dcb4b7e7f FIREFOX_3_1a1_BUILD2

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

@ -66,6 +66,11 @@ ifdef MOZ_MEMORY
tier_base_dirs += memory/jemalloc
endif
ifdef ENABLE_TESTS
# Additional makefile targets to call automated test suites
include $(topsrcdir)/testing/testsuite-targets.mk
endif
include $(topsrcdir)/$(MOZ_BUILD_APP)/build.mk
TIERS += testharness

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

@ -94,7 +94,10 @@ EXTRA_DSO_LDOPTS += $(MOZ_GTK2_LIBS)
endif
ifeq ($(OS_ARCH),WINNT)
OS_LIBS += oleaut32.lib
OS_LIBS += \
oleaut32.lib \
version.lib \
$(NULL)
endif
include $(topsrcdir)/config/rules.mk

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

@ -92,35 +92,27 @@ cpp_quote("")
import "objidl.idl";
import "oaidl.idl";
const long DISPID_DOC_URL = -5904;
const long DISPID_DOC_TITLE = -5905;
const long DISPID_DOC_MIMETYPE = -5906;
const long DISPID_DOC_DOCTYPE = -5907;
const long DISPID_DOC_NAMESPACE = -5908;
const long DISPID_DOC_MEDIATYPES = -5909;
[object, uuid(0D68D6D0-D93D-4d08-A30D-F00DD1F45B24)]
interface ISimpleDOMDocument : IUnknown
{
[propget, id(DISPID_DOC_URL)] HRESULT URL(
[propget] HRESULT URL(
[out, retval] BSTR * url
);
[propget, id(DISPID_DOC_TITLE)] HRESULT title(
[propget] HRESULT title(
[out, retval] BSTR * title
);
[propget, id(DISPID_DOC_MIMETYPE)] HRESULT mimeType(
[propget] HRESULT mimeType(
[out, retval] BSTR * mimeType
);
[propget, id(DISPID_DOC_DOCTYPE)] HRESULT docType(
[propget] HRESULT docType(
[out, retval] BSTR * docType
);
[propget, id(DISPID_DOC_NAMESPACE)] HRESULT nameSpaceURIForID(
[propget] HRESULT nameSpaceURIForID(
[in] short nameSpaceID,
[out, retval] BSTR * nameSpaceURI
);
[propput, id(DISPID_DOC_MEDIATYPES)] HRESULT alternateViewMediaTypes(
[propput] HRESULT alternateViewMediaTypes(
[in] BSTR * commaSeparatedMediaTypes
);
}

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

@ -133,13 +133,9 @@ cpp_quote("")
import "objidl.idl";
import "oaidl.idl";
const long DISPID_NODE_NODEINFO = -5900;
const long DISPID_NODE_ATTRIBUTES = -5901;
const long DISPID_NODE_ATTRIBUTESFORNAMES = -5902;
const long DISPID_NODE_COMPSTYLE = -5903;
const long DISPID_NODE_COMPSTYLEFORPROPS = -5904;
const long DISPID_NODE_LANGUAGE = -5905;
import "ISimpleDOMText.idl";
import "ISimpleDOMDocument.idl";
[object, uuid(1814ceeb-49e2-407f-af99-fa755a7d2607)]
interface ISimpleDOMNode : IUnknown
@ -157,7 +153,7 @@ interface ISimpleDOMNode : IUnknown
const unsigned short NODETYPE_DOCUMENT_FRAGMENT = 11;
const unsigned short NODETYPE_NOTATION = 12;
[propget, id(DISPID_NODE_NODEINFO)] HRESULT nodeInfo(
[propget] HRESULT nodeInfo(
[out] BSTR *nodeName, // for performance returns NULL for text nodes (true nodeName would be "#text")
[out] short *nameSpaceID,
[out] BSTR *nodeValue,
@ -166,7 +162,7 @@ interface ISimpleDOMNode : IUnknown
[out, retval] unsigned short *nodeType
);
[propget, id(DISPID_NODE_ATTRIBUTES)] HRESULT attributes(
[propget] HRESULT attributes(
[in] unsigned short maxAttribs,
[out, size_is(maxAttribs), length_is(*numAttribs)] BSTR *attribNames,
[out, size_is(maxAttribs), length_is(*numAttribs)] short *nameSpaceID,
@ -174,14 +170,14 @@ interface ISimpleDOMNode : IUnknown
[out, retval] unsigned short *numAttribs
);
[propget, id(DISPID_NODE_ATTRIBUTESFORNAMES)] HRESULT attributesForNames(
[propget] HRESULT attributesForNames(
[in] unsigned short numAttribs,
[in, size_is(numAttribs), length_is(numAttribs)] BSTR *attribNames,
[in, size_is(numAttribs), length_is(numAttribs)] short *nameSpaceID,
[out, retval, size_is(numAttribs), length_is(numAttribs)] BSTR *attribValues
);
[propget, id(DISPID_NODE_COMPSTYLE)] HRESULT computedStyle(
[propget] HRESULT computedStyle(
[in] unsigned short maxStyleProperties,
[in] boolean useAlternateView, // If TRUE, returns properites for media as set in nsIDOMDocument::set_alternateViewMediaTypes
[out, size_is(maxStyleProperties), length_is(*numStyleProperties)] BSTR *styleProperties,
@ -189,7 +185,7 @@ interface ISimpleDOMNode : IUnknown
[out, retval] unsigned short *numStyleProperties
);
[propget, id(DISPID_NODE_COMPSTYLEFORPROPS)] HRESULT computedStyleForProperties(
[propget] HRESULT computedStyleForProperties(
[in] unsigned short numStyleProperties,
[in] boolean useAlternateView, // If TRUE, returns properites for media as set in nsIDOMDocument::set_alternateViewMediaTypes
[in, size_is(numStyleProperties), length_is(numStyleProperties)] BSTR *styleProperties,
@ -210,7 +206,18 @@ interface ISimpleDOMNode : IUnknown
[propget, local] HRESULT localInterface([out][retval] void **localInterface);
[propget, id(DISPID_NODE_LANGUAGE)] HRESULT language([out, retval] BSTR *language);
[propget] HRESULT language([out, retval] BSTR *language);
}
[
uuid(a6245497-9c0b-4449-85a5-bd6ad07df8ea),
helpstring("ISimpleDOM Type Library")
]
library ISimpleDOM
{
interface ISimpleDOMNode;
interface ISimpleDOMText;
interface ISimpleDOMDocument;
};

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

@ -98,7 +98,7 @@ done_gen: ISimpleDOMNode.idl \
ISimpleDOMDocument.idl \
ISimpleDOMText.idl
$(MIDL) $(MIDL_FLAGS) -Oicf $(srcdir)/ISimpleDOMNode.idl
$(MIDL) $(MIDL_FLAGS) -I $(srcdir) -Oicf $(srcdir)/ISimpleDOMNode.idl
$(MIDL) $(MIDL_FLAGS) -Oicf $(srcdir)/ISimpleDOMDocument.idl
$(MIDL) $(MIDL_FLAGS) -Oicf $(srcdir)/ISimpleDOMText.idl
touch $@

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

@ -44,8 +44,9 @@
typedef long nsAccessibleTextBoundary;
interface nsIAccessible;
interface nsIPersistentProperties;
[scriptable, uuid(caa4f543-070e-4705-8428-2e53575c41bb)]
[scriptable, uuid(0f4633b1-550c-4b50-8c04-0eb1005eef2f)]
interface nsIAccessibleText : nsISupports
{
// In parameters for character offsets:
@ -102,13 +103,24 @@ interface nsIAccessibleText : nsISupports
wchar getCharacterAtOffset (in long offset);
/**
* Get the accessible and start/end offsets around the given offset.
* This accessible get return the DOM node and layout frame
* with the uniform attributes for this range of text
* Get the accessible start/end offsets around the given offset,
* return the text attributes for this range of text.
*
* @param includeDefAttrs [in] points whether text attributes applied to
* the entire accessible should be included or not.
* @param offset [in] text offset
* @param rangeStartOffset [out] start offset of the range of text
* @param rangeEndOffset [out] end offset of the range of text
*/
nsIAccessible getAttributeRange (in long offset,
out long rangeStartOffset,
out long rangeEndOffset);
nsIPersistentProperties getTextAttributes(in boolean includeDefAttrs,
in long offset,
out long rangeStartOffset,
out long rangeEndOffset);
/**
* Return the text attributes that apply to the entire accessible.
*/
readonly attribute nsIPersistentProperties defaultTextAttributes;
/**
* Returns the bounding box of the specified position.
@ -223,11 +235,6 @@ interface nsIAccessibleText : nsISupports
(since not every text component will allow every operation):
setSelectionBounds, addSelection, removeSelection, setCaretOffset.
getRangeAttributes defined to return an nsISupports
interface instead of a pango specific data structure.
It may be that some other return type is more appropriate
for mozilla text attributes.
we assume that all text components support the idea of
a caret offset, whether visible or "virtual". If this
isn't the case, caretOffset can be made readonly and

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

@ -786,13 +786,50 @@ getRoleCB(AtkObject *aAtkObj)
return aAtkObj->role;
}
AtkAttributeSet*
ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes)
{
if (!aAttributes)
return nsnull;
AtkAttributeSet *objAttributeSet = nsnull;
nsCOMPtr<nsISimpleEnumerator> propEnum;
nsresult rv = aAttributes->Enumerate(getter_AddRefs(propEnum));
NS_ENSURE_SUCCESS(rv, nsnull);
PRBool hasMore;
while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
nsCOMPtr<nsISupports> sup;
rv = propEnum->GetNext(getter_AddRefs(sup));
NS_ENSURE_SUCCESS(rv, objAttributeSet);
nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(sup));
NS_ENSURE_TRUE(propElem, objAttributeSet);
nsCAutoString name;
rv = propElem->GetKey(name);
NS_ENSURE_SUCCESS(rv, objAttributeSet);
nsAutoString value;
rv = propElem->GetValue(value);
NS_ENSURE_SUCCESS(rv, objAttributeSet);
AtkAttribute *objAttr = (AtkAttribute *)g_malloc(sizeof(AtkAttribute));
objAttr->name = g_strdup(name.get());
objAttr->value = g_strdup(NS_ConvertUTF16toUTF8(value).get());
objAttributeSet = g_slist_prepend(objAttributeSet, objAttr);
}
//libspi will free it
return objAttributeSet;
}
AtkAttributeSet *
GetAttributeSet(nsIAccessible* aAccessible)
{
AtkAttributeSet *objAttributeSet = nsnull;
nsCOMPtr<nsIPersistentProperties> attributes;
aAccessible->GetAttributes(getter_AddRefs(attributes));
if (attributes) {
// Deal with attributes that we only need to expose in ATK
PRUint32 state;
@ -804,33 +841,10 @@ GetAttributeSet(nsIAccessible* aAccessible)
oldValueUnused);
}
nsCOMPtr<nsISimpleEnumerator> propEnum;
nsresult rv = attributes->Enumerate(getter_AddRefs(propEnum));
NS_ENSURE_SUCCESS(rv, nsnull);
PRBool hasMore;
while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
nsCOMPtr<nsISupports> sup;
rv = propEnum->GetNext(getter_AddRefs(sup));
nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(sup));
NS_ENSURE_TRUE(propElem, nsnull);
nsCAutoString name;
rv = propElem->GetKey(name);
NS_ENSURE_SUCCESS(rv, nsnull);
nsAutoString value;
rv = propElem->GetValue(value);
NS_ENSURE_SUCCESS(rv, nsnull);
AtkAttribute *objAttribute = (AtkAttribute *)g_malloc(sizeof(AtkAttribute));
objAttribute->name = g_strdup(name.get());
objAttribute->value = g_strdup(NS_ConvertUTF16toUTF8(value).get());
objAttributeSet = g_slist_prepend(objAttributeSet, objAttribute);
}
return ConvertToAtkAttributeSet(attributes);
}
return objAttributeSet;
return nsnull;
}
AtkAttributeSet *
@ -855,8 +869,9 @@ getParentCB(AtkObject *aAtkObj)
if (NS_FAILED(rv) || !accParent)
return nsnull;
atk_object_set_parent(aAtkObj,
nsAccessibleWrap::GetAtkObject(accParent));
AtkObject *parent = nsAccessibleWrap::GetAtkObject(accParent);
if (parent)
atk_object_set_parent(aAtkObj, parent);
}
return aAtkObj->accessible_parent;
}
@ -1197,6 +1212,13 @@ nsAccessibleWrap::FirePlatformEvent(nsIAccessibleEvent *aEvent)
caretOffset);
} break;
case nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED:
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TEXT_ATTRIBUTE_CHANGED\n"));
g_signal_emit_by_name(atkObj,
"text-attributes-changed");
break;
case nsIAccessibleEvent::EVENT_TABLE_MODEL_CHANGED:
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_MODEL_CHANGED\n"));
g_signal_emit_by_name(atkObj, "model_changed");

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

@ -41,8 +41,9 @@
#include "nsMaiInterfaceText.h"
#include "nsString.h"
#include "nsIPersistentProperties2.h"
AtkAttributeSet * GetAttributeSet(nsIAccessible* aAccessible);
AtkAttributeSet* ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes);
void
textInterfaceInitCB(AtkTextIface *aIface)
@ -245,6 +246,9 @@ getRunAttributesCB(AtkText *aText, gint aOffset,
gint *aStartOffset,
gint *aEndOffset)
{
*aStartOffset = -1;
*aEndOffset = -1;
nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
if (!accWrap)
return nsnull;
@ -254,24 +258,37 @@ getRunAttributesCB(AtkText *aText, gint aOffset,
getter_AddRefs(accText));
NS_ENSURE_TRUE(accText, nsnull);
nsCOMPtr<nsIAccessible> accessibleWithAttrs;
nsCOMPtr<nsIPersistentProperties> attributes;
PRInt32 startOffset = 0, endOffset = 0;
nsresult rv =
accText->GetAttributeRange(aOffset, &startOffset, &endOffset,
getter_AddRefs(accessibleWithAttrs));
nsresult rv = accText->GetTextAttributes(PR_FALSE, aOffset,
&startOffset, &endOffset,
getter_AddRefs(attributes));
NS_ENSURE_SUCCESS(rv, nsnull);
*aStartOffset = startOffset;
*aEndOffset = endOffset;
if (NS_FAILED(rv))
return nsnull;
return GetAttributeSet(accessibleWithAttrs);
return ConvertToAtkAttributeSet(attributes);
}
AtkAttributeSet *
getDefaultAttributesCB(AtkText *aText)
{
/* not supported ??? */
return nsnull;
nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
if (!accWrap)
return nsnull;
nsCOMPtr<nsIAccessibleText> accText;
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
getter_AddRefs(accText));
NS_ENSURE_TRUE(accText, nsnull);
nsCOMPtr<nsIPersistentProperties> attributes;
nsresult rv = accText->GetDefaultTextAttributes(getter_AddRefs(attributes));
if (NS_FAILED(rv))
return nsnull;
return ConvertToAtkAttributeSet(attributes);
}
void

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

@ -90,6 +90,7 @@ CPPSRCS = \
nsApplicationAccessible.cpp \
nsCaretAccessible.cpp \
nsTextAccessible.cpp \
nsTextUtils.cpp \
$(NULL)
EXPORTS = \

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

@ -112,12 +112,23 @@ nsIAccessibilityService *nsAccessNode::GetAccService()
* Class nsAccessNode
*/
//-----------------------------------------------------
// construction
//-----------------------------------------------------
NS_IMPL_QUERY_INTERFACE2(nsAccessNode, nsIAccessNode, nsPIAccessNode)
NS_IMPL_ADDREF(nsAccessNode)
NS_IMPL_RELEASE_WITH_DESTROY(nsAccessNode, LastRelease())
////////////////////////////////////////////////////////////////////////////////
// nsAccessible. nsISupports
NS_IMPL_CYCLE_COLLECTION_0(nsAccessNode)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsAccessNode)
NS_INTERFACE_MAP_ENTRY(nsIAccessNode)
NS_INTERFACE_MAP_ENTRY(nsPIAccessNode)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessNode)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsAccessNode, nsIAccessNode)
NS_IMPL_CYCLE_COLLECTING_RELEASE_FULL(nsAccessNode, nsIAccessNode,
LastRelease())
////////////////////////////////////////////////////////////////////////////////
// nsAccessible. Constructor
nsAccessNode::nsAccessNode(nsIDOMNode *aNode, nsIWeakReference* aShell):
mDOMNode(aNode), mWeakShell(aShell)
@ -191,8 +202,7 @@ NS_IMETHODIMP nsAccessNode::Init()
// so that nsDocAccessible::RefreshNodes() can find the anonymous subtree to release when
// the root node goes away
nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
if (content && (content->IsNativeAnonymous() ||
content->GetBindingParent())) {
if (content && content->IsInAnonymousSubtree()) {
// Specific examples of where this is used: <input type="file"> and <xul:findbar>
nsCOMPtr<nsIAccessible> parentAccessible;
docAccessible->GetAccessibleInParentChain(mDOMNode, PR_TRUE, getter_AddRefs(parentAccessible));
@ -876,10 +886,7 @@ nsAccessNode::GetLanguage(nsAString& aLanguage)
}
}
nsIContent *walkUp = content;
while (walkUp && !walkUp->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::lang, aLanguage)) {
walkUp = walkUp->GetParent();
}
nsAccUtils::GetLanguageFor(content, nsnull, aLanguage);
if (aLanguage.IsEmpty()) { // Nothing found, so use document's language
nsIDocument *doc = content->GetOwnerDoc();

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

@ -45,6 +45,8 @@
#include "nsCOMPtr.h"
#include "nsAccessibilityAtoms.h"
#include "nsAccessibilityUtils.h"
#include "nsIAccessibleTypes.h"
#include "nsIAccessNode.h"
#include "nsIContent.h"
@ -72,13 +74,16 @@ class nsIDocShellTreeItem;
typedef nsInterfaceHashtable<nsVoidPtrHashKey, nsIAccessNode>
nsAccessNodeHashtable;
class nsAccessNode: public nsIAccessNode, public nsPIAccessNode
class nsAccessNode: public nsIAccessNode,
public nsPIAccessNode
{
public: // construction, destruction
nsAccessNode(nsIDOMNode *, nsIWeakReference* aShell);
virtual ~nsAccessNode();
NS_DECL_ISUPPORTS
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsAccessNode, nsIAccessNode)
NS_DECL_NSIACCESSNODE
NS_DECL_NSPIACCESSNODE

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

@ -149,7 +149,7 @@ ACCESSIBILITY_ATOM(tooltip, "tooltip") // XUL
ACCESSIBILITY_ATOM(tr, "tr")
ACCESSIBILITY_ATOM(ul, "ul")
// Alphabetical list of attributes
// Alphabetical list of attributes (DOM)
ACCESSIBILITY_ATOM(acceltext, "acceltext")
ACCESSIBILITY_ATOM(accesskey, "accesskey")
ACCESSIBILITY_ATOM(alt, "alt")
@ -186,6 +186,10 @@ ACCESSIBILITY_ATOM(tooltiptext, "tooltiptext")
ACCESSIBILITY_ATOM(type, "type")
ACCESSIBILITY_ATOM(value, "value")
// Alphabetical list of text attributes (AT API)
ACCESSIBILITY_ATOM(invalid, "invalid")
ACCESSIBILITY_ATOM(language, "language")
// ARIA (DHTML accessibility) attributes
// Also add to nsARIAMap.cpp and nsARIAMap.h
// ARIA role attribute

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

@ -65,6 +65,7 @@
#include "nsIEventStateManager.h"
#include "nsISelection2.h"
#include "nsISelectionController.h"
#include "nsGUIEvent.h"
#include "nsContentCID.h"
#include "nsComponentManagerUtils.h"
@ -291,6 +292,48 @@ nsAccUtils::HasListener(nsIContent *aContent, const nsAString& aEventType)
return listenerManager && listenerManager->HasListenersFor(aEventType);
}
PRBool
nsAccUtils::DispatchMouseEvent(PRUint32 aEventType,
nsIPresShell *aPresShell,
nsIContent *aContent)
{
nsIFrame *frame = aPresShell->GetPrimaryFrameFor(aContent);
if (!frame)
return PR_FALSE;
nsIFrame* rootFrame = aPresShell->GetRootFrame();
if (!rootFrame)
return PR_FALSE;
nsCOMPtr<nsIWidget> rootWidget = rootFrame->GetWindow();
if (!rootWidget)
return PR_FALSE;
// Compute x and y coordinates.
nsPoint point = frame->GetOffsetToExternal(rootFrame);
nsSize size = frame->GetSize();
nsPresContext* presContext = aPresShell->GetPresContext();
PRInt32 x = presContext->AppUnitsToDevPixels(point.x + size.width / 2);
PRInt32 y = presContext->AppUnitsToDevPixels(point.y + size.height / 2);
// Fire mouse event.
nsMouseEvent event(PR_TRUE, aEventType, rootWidget,
nsMouseEvent::eReal, nsMouseEvent::eNormal);
event.refPoint = nsIntPoint(x, y);
event.clickCount = 1;
event.button = nsMouseEvent::eLeftButton;
event.time = PR_IntervalNow();
nsEventStatus status = nsEventStatus_eIgnore;
aPresShell->HandleEventWithTarget(&event, frame, aContent, &status);
return PR_TRUE;
}
PRUint32
nsAccUtils::GetAccessKeyFor(nsIContent *aContent)
{
@ -340,6 +383,24 @@ nsAccUtils::FireAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible,
return pAccessible->FireAccessibleEvent(event);
}
already_AddRefed<nsIDOMElement>
nsAccUtils::GetDOMElementFor(nsIDOMNode *aNode)
{
nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
nsIDOMElement *element = nsnull;
if (node->IsNodeOfType(nsINode::eELEMENT))
CallQueryInterface(node, &element);
else if (node->IsNodeOfType(nsINode::eTEXT))
CallQueryInterface(node->GetNodeParent(), &element);
else if (node->IsNodeOfType(nsINode::eDOCUMENT)) {
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(node));
domDoc->GetDocumentElement(&element);
}
return element;
}
PRBool
nsAccUtils::IsAncestorOf(nsIDOMNode *aPossibleAncestorNode,
nsIDOMNode *aPossibleDescendantNode)
@ -774,11 +835,9 @@ nsAccUtils::FindNeighbourPointingToNode(nsIContent *aForNode,
nsIAtom *aTagName,
PRUint32 aAncestorLevelsToSearch)
{
nsCOMPtr<nsIContent> binding;
nsAutoString controlID;
if (!nsAccUtils::GetID(aForNode, controlID)) {
binding = aForNode->GetBindingParent();
if (binding == aForNode)
if (!aForNode->IsInAnonymousSubtree())
return nsnull;
aForNode->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::anonid, controlID);
@ -787,6 +846,7 @@ nsAccUtils::FindNeighbourPointingToNode(nsIContent *aForNode,
}
// Look for label in subtrees of nearby ancestors
nsCOMPtr<nsIContent> binding(aForNode->GetBindingParent());
PRUint32 count = 0;
nsIContent *labelContent = nsnull;
nsIContent *prevSearched = nsnull;
@ -921,6 +981,19 @@ nsAccUtils::FindDescendantPointingToIDImpl(nsCString& aIdWithSpaces,
return nsnull;
}
void
nsAccUtils::GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
nsAString& aLanguage)
{
aLanguage.Truncate();
nsIContent *walkUp = aContent;
while (walkUp && walkUp != aRootContent &&
!walkUp->GetAttr(kNameSpaceID_None,
nsAccessibilityAtoms::lang, aLanguage))
walkUp = walkUp->GetParent();
}
nsRoleMapEntry*
nsAccUtils::GetRoleMapEntry(nsIDOMNode *aNode)
{

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

@ -124,6 +124,17 @@ public:
*/
static PRBool HasListener(nsIContent *aContent, const nsAString& aEventType);
/**
* Send mouse events to the given element.
*
* @param aEventType an event type (see nsGUIEvent.h for constants)
* @param aPresShell the presshell for the given element
* @param aContent the element element
*/
static PRBool DispatchMouseEvent(PRUint32 aEventType,
nsIPresShell *aPresShell,
nsIContent *aContent);
/**
* Return an accesskey registered on the given element by
* nsIEventStateManager or 0 if there is no registered accesskey.
@ -138,6 +149,16 @@ public:
static nsresult FireAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible,
PRBool aIsAsynch = PR_FALSE);
/**
* Return DOM element related with the given node, i.e.
* a) itself if it is DOM element
* b) parent element if it is text node
* c) document element if it is document node.
*
* @param aNode [in] the given DOM node
*/
static already_AddRefed<nsIDOMElement> GetDOMElementFor(nsIDOMNode *aNode);
/**
* Is the first passed in node an ancestor of the second?
* Note: A node is not considered to be the ancestor of itself.
@ -302,6 +323,16 @@ public:
*/
static PRBool IsXLink(nsIContent *aContent);
/**
* Returns language for the given node.
*
* @param aContent [in] the given node
* @param aRootContent [in] container of the given node
* @param aLanguage [out] language
*/
static void GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
nsAString& aLanguage);
/**
* Get the role map entry for a given DOM node. This will use the first
* ARIA role if the role attribute provides a space delimited list of roles.

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

@ -140,9 +140,23 @@ nsAccessibleDOMStringList::Contains(const nsAString& aString, PRBool *aResult)
* Class nsAccessible
*/
//-----------------------------------------------------
// construction
//-----------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
// nsAccessible. nsISupports
NS_IMPL_CYCLE_COLLECTION_CLASS(nsAccessible)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsAccessible, nsAccessNode)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstChild)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNextSibling)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsAccessible, nsAccessNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstChild)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNextSibling)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_ADDREF_INHERITED(nsAccessible, nsAccessNode)
NS_IMPL_RELEASE_INHERITED(nsAccessible, nsAccessNode)
@ -188,7 +202,12 @@ nsresult nsAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
// Custom-built QueryInterface() knows when we support nsIAccessibleSelectable
// based on role attribute and aria-multiselectable
*aInstancePtr = nsnull;
if (aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) {
*aInstancePtr = &NS_CYCLE_COLLECTION_NAME(nsAccessible);
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIAccessible))) {
*aInstancePtr = static_cast<nsIAccessible*>(this);
NS_ADDREF_THIS();
@ -483,7 +502,7 @@ NS_IMETHODIMP nsAccessible::SetFirstChild(nsIAccessible *aFirstChild)
NS_IMETHODIMP nsAccessible::SetNextSibling(nsIAccessible *aNextSibling)
{
mNextSibling = aNextSibling? aNextSibling: DEAD_END_ACCESSIBLE;
mNextSibling = aNextSibling;
return NS_OK;
}
@ -538,15 +557,13 @@ NS_IMETHODIMP nsAccessible::InvalidateChildren()
// CacheChildren() is called.
// Note: we don't want to start creating accessibles at this point,
// so don't use GetNextSibling() here. (bug 387252)
nsAccessible* child = static_cast<nsAccessible*>(mFirstChild);
nsAccessible* child = static_cast<nsAccessible*>(mFirstChild.get());
while (child) {
child->mParent = nsnull;
if (child->mNextSibling == DEAD_END_ACCESSIBLE) {
break;
}
nsIAccessible *next = child->mNextSibling;
nsCOMPtr<nsIAccessible> next = child->mNextSibling;
child->mNextSibling = nsnull;
child = static_cast<nsAccessible*>(next);
child = static_cast<nsAccessible*>(next.get());
}
mAccChildCount = eChildCountUninitialized;
@ -608,9 +625,8 @@ NS_IMETHODIMP nsAccessible::GetNextSibling(nsIAccessible * *aNextSibling)
if (mNextSibling || !mParent) {
// If no parent, don't try to calculate a new sibling
// It either means we're at the root or shutting down the parent
if (mNextSibling != DEAD_END_ACCESSIBLE) {
NS_IF_ADDREF(*aNextSibling = mNextSibling);
}
NS_IF_ADDREF(*aNextSibling = mNextSibling);
return NS_OK;
}
@ -1593,15 +1609,6 @@ nsresult nsAccessible::AppendFlatStringFromContentNode(nsIContent *aContent, nsA
nsAutoString textEquivalent;
if (!aContent->IsNodeOfType(nsINode::eHTML)) {
if (aContent->IsNodeOfType(nsINode::eXUL)) {
nsCOMPtr<nsIPresShell> shell = GetPresShell();
if (!shell) {
return NS_ERROR_FAILURE;
}
nsIFrame *frame = shell->GetPrimaryFrameFor(aContent);
if (!frame || !frame->GetStyleVisibility()->IsVisible()) {
return NS_OK;
}
nsCOMPtr<nsIDOMXULLabeledControlElement> labeledEl(do_QueryInterface(aContent));
if (labeledEl) {
labeledEl->GetLabel(textEquivalent);
@ -1661,8 +1668,17 @@ nsresult nsAccessible::AppendFlatStringFromSubtree(nsIContent *aContent, nsAStri
if (isAlreadyHere) {
return NS_OK;
}
isAlreadyHere = PR_TRUE;
nsresult rv = AppendFlatStringFromSubtreeRecurse(aContent, aFlatString);
nsCOMPtr<nsIPresShell> shell = GetPresShell();
NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE);
nsIFrame *frame = shell->GetPrimaryFrameFor(aContent);
PRBool isHidden = (!frame || !frame->GetStyleVisibility()->IsVisible());
nsresult rv = AppendFlatStringFromSubtreeRecurse(aContent, aFlatString,
isHidden);
isAlreadyHere = PR_FALSE;
if (NS_SUCCEEDED(rv) && !aFlatString->IsEmpty()) {
@ -1681,7 +1697,10 @@ nsresult nsAccessible::AppendFlatStringFromSubtree(nsIContent *aContent, nsAStri
return rv;
}
nsresult nsAccessible::AppendFlatStringFromSubtreeRecurse(nsIContent *aContent, nsAString *aFlatString)
nsresult
nsAccessible::AppendFlatStringFromSubtreeRecurse(nsIContent *aContent,
nsAString *aFlatString,
PRBool aIsRootHidden)
{
// Depth first search for all text nodes that are decendants of content node.
// Append all the text into one flat string
@ -1698,10 +1717,25 @@ nsresult nsAccessible::AppendFlatStringFromSubtreeRecurse(nsIContent *aContent,
}
// There are relevant children: use them to get the text.
nsCOMPtr<nsIPresShell> shell = GetPresShell();
NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE);
PRUint32 index;
for (index = 0; index < numChildren; index++) {
AppendFlatStringFromSubtreeRecurse(aContent->GetChildAt(index), aFlatString);
nsCOMPtr<nsIContent> childContent = aContent->GetChildAt(index);
// Walk into hidden subtree if the the root parent is also hidden. This
// happens when the author explictly uses a hidden label or description.
if (!aIsRootHidden) {
nsIFrame *childFrame = shell->GetPrimaryFrameFor(childContent);
if (!childFrame || !childFrame->GetStyleVisibility()->IsVisible())
continue;
}
AppendFlatStringFromSubtreeRecurse(childContent, aFlatString,
aIsRootHidden);
}
return NS_OK;
}
@ -3119,40 +3153,30 @@ NS_IMETHODIMP nsAccessible::GetNativeInterface(void **aOutAccessible)
void nsAccessible::DoCommandCallback(nsITimer *aTimer, void *aClosure)
{
NS_ASSERTION(gDoCommandTimer, "How did we get here if there was no gDoCommandTimer?");
NS_ASSERTION(gDoCommandTimer,
"How did we get here if there was no gDoCommandTimer?");
NS_RELEASE(gDoCommandTimer);
nsIContent *content = reinterpret_cast<nsIContent*>(aClosure);
nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(content));
if (xulElement) {
xulElement->Click();
}
else {
nsIDocument *doc = content->GetDocument();
if (!doc) {
return;
}
nsCOMPtr<nsIPresShell> presShell = doc->GetPrimaryShell();
nsPIDOMWindow *outerWindow = doc->GetWindow();
if (presShell && outerWindow) {
nsAutoPopupStatePusher popupStatePusher(outerWindow, openAllowed);
nsCOMPtr<nsIContent> content =
reinterpret_cast<nsIContent*>(aClosure);
nsMouseEvent downEvent(PR_TRUE, NS_MOUSE_BUTTON_DOWN, nsnull,
nsMouseEvent::eSynthesized);
nsMouseEvent upEvent(PR_TRUE, NS_MOUSE_BUTTON_UP, nsnull,
nsMouseEvent::eSynthesized);
nsMouseEvent clickEvent(PR_TRUE, NS_MOUSE_CLICK, nsnull,
nsMouseEvent::eSynthesized);
nsIDocument *doc = content->GetDocument();
if (!doc)
return;
nsEventStatus eventStatus = nsEventStatus_eIgnore;
content->DispatchDOMEvent(&downEvent, nsnull,
presShell->GetPresContext(), &eventStatus);
content->DispatchDOMEvent(&upEvent, nsnull,
presShell->GetPresContext(), &eventStatus);
content->DispatchDOMEvent(&clickEvent, nsnull,
presShell->GetPresContext(), &eventStatus);
}
}
nsCOMPtr<nsIPresShell> presShell = doc->GetPrimaryShell();
// Scroll into view.
presShell->ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_ANYWHERE,
NS_PRESSHELL_SCROLL_ANYWHERE);
// Fire mouse down and mouse up events.
PRBool res = nsAccUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, presShell,
content);
if (!res)
return;
nsAccUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_UP, presShell, content);
}
/*

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

@ -40,7 +40,6 @@
#define _nsAccessible_H_
#include "nsAccessNodeWrap.h"
#include "nsAccessibilityUtils.h"
#include "nsIAccessible.h"
#include "nsPIAccessible.h"
@ -70,9 +69,6 @@ class nsIView;
#define NS_OK_NO_ARIA_VALUE \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x21)
// When mNextSibling is set to this, it indicates there ar eno more siblings
#define DEAD_END_ACCESSIBLE static_cast<nsIAccessible*>((void*)1)
// Saves a data member -- if child count equals this value we haven't
// cached children or child count yet
enum { eChildCountUninitialized = -1 };
@ -107,6 +103,8 @@ public:
virtual ~nsAccessible();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsAccessible, nsAccessNode)
NS_DECL_NSIACCESSIBLE
NS_DECL_NSPIACCESSIBLE
NS_DECL_NSIACCESSIBLEHYPERLINK
@ -197,7 +195,22 @@ protected:
// helper method to verify frames
static nsresult GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut);
static nsresult GetTranslatedString(const nsAString& aKey, nsAString& aStringOut);
nsresult AppendFlatStringFromSubtreeRecurse(nsIContent *aContent, nsAString *aFlatString);
/**
* Walk into subtree and calculate the string which is used as the accessible
* name or description.
*
* @param aContent [in] traversed content
* @param aFlatString [in, out] result string
* @param aIsRootHidden [in] specifies whether root content (we started to
* traverse from) is hidden, in this case the result
* string is calculated from hidden children
* (this is used when hidden root content is explicitly
* specified as label or description by author)
*/
nsresult AppendFlatStringFromSubtreeRecurse(nsIContent *aContent,
nsAString *aFlatString,
PRBool aIsRootHidden);
// Helpers for dealing with children
virtual void CacheChildren();
@ -258,7 +271,9 @@ protected:
// Data Members
nsCOMPtr<nsIAccessible> mParent;
nsIAccessible *mFirstChild, *mNextSibling;
nsCOMPtr<nsIAccessible> mFirstChild;
nsCOMPtr<nsIAccessible> mNextSibling;
nsRoleMapEntry *mRoleMapEntry; // Non-null indicates author-supplied role; possibly state & value as well
PRInt32 mAccChildCount;
};

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

@ -57,7 +57,22 @@
PRBool nsAccEvent::gLastEventFromUserInput = PR_FALSE;
nsIDOMNode* nsAccEvent::gLastEventNodeWeak = 0;
NS_IMPL_ISUPPORTS2(nsAccEvent, nsAccEvent, nsIAccessibleEvent)
////////////////////////////////////////////////////////////////////////////////
// nsAccEvent. nsISupports
NS_IMPL_CYCLE_COLLECTION_2(nsAccEvent, mAccessible, mDocAccessible)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsAccEvent)
NS_INTERFACE_MAP_ENTRY(nsIAccessibleEvent)
NS_INTERFACE_MAP_ENTRY(nsAccEvent)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsAccEvent)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsAccEvent)
////////////////////////////////////////////////////////////////////////////////
// nsAccEvent. Constructors
nsAccEvent::nsAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible,
PRBool aIsAsynch, EEventRule aEventRule):

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

@ -49,6 +49,7 @@
#include "nsIAccessibleDocument.h"
#include "nsIDOMNode.h"
#include "nsString.h"
#include "nsCycleCollectionParticipant.h"
class nsIPresShell;
@ -93,7 +94,9 @@ public:
EEventRule aEventRule = eRemoveDupes);
virtual ~nsAccEvent() {}
NS_DECL_ISUPPORTS
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(nsAccEvent)
NS_DECL_NSIACCESSIBLEEVENT
static void GetLastEventAttributes(nsIDOMNode *aNode,
@ -105,13 +108,13 @@ protected:
void CaptureIsFromUserInput(PRBool aIsAsynch);
PRBool mIsFromUserInput;
private:
PRUint32 mEventType;
EEventRule mEventRule;
nsCOMPtr<nsIAccessible> mAccessible;
nsCOMPtr<nsIDOMNode> mDOMNode;
nsCOMPtr<nsIAccessibleDocument> mDocAccessible;
private:
static PRBool gLastEventFromUserInput;
static nsIDOMNode* gLastEventNodeWeak;

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

@ -50,11 +50,48 @@ nsApplicationAccessible::nsApplicationAccessible():
{
}
////////////////////////////////////////////////////////////////////////////////
// nsISupports
NS_IMPL_ISUPPORTS_INHERITED0(nsApplicationAccessible,
nsAccessible)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsApplicationAccessible)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsApplicationAccessible,
nsAccessible)
nsCOMPtr<nsISimpleEnumerator> enumerator;
tmp->mChildren->Enumerate(getter_AddRefs(enumerator));
nsCOMPtr<nsIWeakReference> childWeakRef;
nsCOMPtr<nsIAccessible> accessible;
PRBool hasMoreElements;
while(NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements))
&& hasMoreElements) {
enumerator->GetNext(getter_AddRefs(childWeakRef));
accessible = do_QueryReferent(childWeakRef);
if (accessible) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, accessible);
cb.NoteXPCOMChild(accessible);
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsApplicationAccessible,
nsAccessible)
tmp->mChildren->Clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsApplicationAccessible)
NS_INTERFACE_MAP_END_INHERITING(nsAccessible)
NS_IMPL_ADDREF_INHERITED(nsApplicationAccessible, nsAccessible)
NS_IMPL_RELEASE_INHERITED(nsApplicationAccessible, nsAccessible)
////////////////////////////////////////////////////////////////////////////////
// nsIAccessNode
NS_IMETHODIMP
nsApplicationAccessible::Init()
{

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

@ -63,6 +63,8 @@ public:
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsApplicationAccessible,
nsAccessible)
// nsPIAccessNode
NS_IMETHOD Init();

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

@ -188,11 +188,14 @@ nsLinkableAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
NS_IMETHODIMP
nsLinkableAccessible::DoAction(PRUint8 aIndex)
{
if (aIndex != eAction_Jump)
return NS_ERROR_INVALID_ARG;
nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
if (actionAcc)
return actionAcc->DoAction(aIndex);
return NS_ERROR_INVALID_ARG;
return nsHyperTextAccessibleWrap::DoAction(aIndex);
}
NS_IMETHODIMP

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

@ -39,7 +39,7 @@
#include "nsAccessibilityService.h"
#include "nsCaretAccessible.h"
#include "nsIAccessibleEvent.h"
#include "nsICaret.h"
#include "nsCaret.h"
#include "nsIDOMDocument.h"
#include "nsIDOMHTMLAnchorElement.h"
#include "nsIDOMHTMLInputElement.h"
@ -47,8 +47,8 @@
#include "nsIFrame.h"
#include "nsIPresShell.h"
#include "nsRootAccessible.h"
#include "nsISelectionController.h"
#include "nsISelectionPrivate.h"
#include "nsISelection2.h"
#include "nsServiceManagerUtils.h"
#include "nsIViewManager.h"
#include "nsIWidget.h"
@ -78,13 +78,31 @@ void nsCaretAccessible::Shutdown()
nsresult nsCaretAccessible::ClearControlSelectionListener()
{
mCurrentControl = nsnull;
mCurrentControlSelection = nsnull;
nsCOMPtr<nsISelectionController> controller =
GetSelectionControllerForNode(mCurrentControl);
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryReferent(mCurrentControlSelection));
if (!selPrivate) {
mCurrentControl = nsnull;
if (!controller)
return NS_OK;
}
// Remove 'this' registered as selection listener for the normal selection.
nsCOMPtr<nsISelection> normalSel;
controller->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(normalSel));
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(normalSel));
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
nsresult rv = selPrivate->RemoveSelectionListener(this);
NS_ENSURE_SUCCESS(rv, rv);
// Remove 'this' registered as selection listener for the spellcheck
// selection.
nsCOMPtr<nsISelection> spellcheckSel;
controller->GetSelection(nsISelectionController::SELECTION_SPELLCHECK,
getter_AddRefs(spellcheckSel));
selPrivate = do_QueryInterface(spellcheckSel);
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
return selPrivate->RemoveSelectionListener(this);
}
@ -99,39 +117,29 @@ nsresult nsCaretAccessible::SetControlSelectionListener(nsIDOMNode *aCurrentNode
mLastTextAccessible = nsnull;
// When focus moves such that the caret is part of a new frame selection
// this removes the old selection listener and attaches a new one for the current focus
nsCOMPtr<nsIPresShell> presShell =
mRootAccessible->GetPresShellFor(aCurrentNode);
if (!presShell)
return NS_ERROR_FAILURE;
// this removes the old selection listener and attaches a new one for
// the current focus.
nsCOMPtr<nsISelectionController> controller =
GetSelectionControllerForNode(mCurrentControl);
NS_ENSURE_TRUE(controller, NS_ERROR_FAILURE);
nsCOMPtr<nsIDocument> doc = presShell->GetDocument();
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
nsCOMPtr<nsIContent> content(do_QueryInterface(aCurrentNode));
// The control selection listener is only for form controls, not for the document
// When there is no document, the content will be null
if (!content) {
return NS_OK;
}
nsIFrame *frame = presShell->GetPrimaryFrameFor(content);
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
nsPresContext *presContext = presShell->GetPresContext();
NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
nsCOMPtr<nsISelectionController> selCon;
frame->GetSelectionController(presContext, getter_AddRefs(selCon));
NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
nsCOMPtr<nsISelection> domSel;
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel));
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(domSel));
// Register 'this' as selection listener for the normal selection.
nsCOMPtr<nsISelection> normalSel;
controller->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(normalSel));
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(normalSel));
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
mCurrentControlSelection = do_GetWeakReference(domSel);
nsresult rv = selPrivate->AddSelectionListener(this);
NS_ENSURE_SUCCESS(rv, rv);
// Register 'this' as selection listener for the spellcheck selection.
nsCOMPtr<nsISelection> spellcheckSel;
controller->GetSelection(nsISelectionController::SELECTION_SPELLCHECK,
getter_AddRefs(spellcheckSel));
selPrivate = do_QueryInterface(spellcheckSel);
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
return selPrivate->AddSelectionListener(this);
}
@ -148,6 +156,15 @@ nsCaretAccessible::AddDocSelectionListener(nsIPresShell *aShell)
nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(domSel);
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
nsresult rv = selPrivate->AddSelectionListener(this);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISelection> spellcheckSel;
selCon->GetSelection(nsISelectionController::SELECTION_SPELLCHECK,
getter_AddRefs(spellcheckSel));
selPrivate = do_QueryInterface(spellcheckSel);
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
return selPrivate->AddSelectionListener(this);
}
@ -162,10 +179,39 @@ nsCaretAccessible::RemoveDocSelectionListener(nsIPresShell *aShell)
nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(domSel);
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
selPrivate->RemoveSelectionListener(this);
nsCOMPtr<nsISelection> spellcheckSel;
selCon->GetSelection(nsISelectionController::SELECTION_SPELLCHECK,
getter_AddRefs(spellcheckSel));
selPrivate = do_QueryInterface(spellcheckSel);
NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
return selPrivate->RemoveSelectionListener(this);
}
NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel, PRInt16 aReason)
NS_IMETHODIMP
nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc,
nsISelection *aSel,
PRInt16 aReason)
{
nsCOMPtr<nsISelection2> sel2(do_QueryInterface(aSel));
PRInt16 type = 0;
sel2->GetType(&type);
if (type == nsISelectionController::SELECTION_NORMAL)
return NormalSelectionChanged(aDoc, aSel);
if (type == nsISelectionController::SELECTION_SPELLCHECK)
return SpellcheckSelectionChanged(aDoc, aSel);
return NS_OK;
}
nsresult
nsCaretAccessible::NormalSelectionChanged(nsIDOMDocument *aDoc,
nsISelection *aSel)
{
NS_ENSURE_TRUE(mRootAccessible, NS_ERROR_FAILURE);
@ -247,6 +293,38 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
return mRootAccessible->FireDelayedAccessibleEvent(event);
}
nsresult
nsCaretAccessible::SpellcheckSelectionChanged(nsIDOMDocument *aDoc,
nsISelection *aSel)
{
// XXX: fire an event for accessible of focus node of the selection. If
// spellchecking is enabled then we will fire the number of events for
// the same accessible for newly appended range of the selection (for every
// misspelled word). If spellchecking is disabled (for example,
// @spellcheck="false" on html:body) then we won't fire any event.
nsCOMPtr<nsIDOMNode> targetNode;
aSel->GetFocusNode(getter_AddRefs(targetNode));
if (!targetNode)
return NS_OK;
nsCOMPtr<nsIAccessibleDocument> docAccessible =
nsAccessNode::GetDocAccessibleFor(targetNode);
NS_ENSURE_STATE(docAccessible);
nsCOMPtr<nsIAccessible> containerAccessible;
nsresult rv =
docAccessible->GetAccessibleInParentChain(targetNode, PR_TRUE,
getter_AddRefs(containerAccessible));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIAccessibleEvent> event =
new nsAccEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED,
containerAccessible, nsnull);
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
return mRootAccessible->FireAccessibleEvent(event);
}
nsRect
nsCaretAccessible::GetCaretRect(nsIWidget **aOutWidget)
{
@ -269,7 +347,7 @@ nsCaretAccessible::GetCaretRect(nsIWidget **aOutWidget)
nsCOMPtr<nsIPresShell> presShell = mRootAccessible->GetPresShellFor(lastNodeWithCaret);
NS_ENSURE_TRUE(presShell, caretRect);
nsCOMPtr<nsICaret> caret;
nsRefPtr<nsCaret> caret;
presShell->GetCaret(getter_AddRefs(caret));
NS_ENSURE_TRUE(caret, caretRect);
@ -278,7 +356,7 @@ nsCaretAccessible::GetCaretRect(nsIWidget **aOutWidget)
nsCOMPtr<nsISelection> caretSelection(do_QueryReferent(mLastUsedSelection));
NS_ENSURE_TRUE(caretSelection, caretRect);
caret->GetCaretCoordinates(nsICaret::eRenderingViewCoordinates, caretSelection,
caret->GetCaretCoordinates(nsCaret::eRenderingViewCoordinates, caretSelection,
&caretRect, &isCollapsed, &view);
if (!view || caretRect.IsEmpty()) {
return nsRect(); // Return empty rect
@ -317,3 +395,35 @@ nsCaretAccessible::GetCaretRect(nsIWidget **aOutWidget)
return caretRect;
}
already_AddRefed<nsISelectionController>
nsCaretAccessible::GetSelectionControllerForNode(nsIDOMNode *aNode)
{
if (!aNode)
return nsnull;
nsCOMPtr<nsIPresShell> presShell = mRootAccessible->GetPresShellFor(aNode);
if (!presShell)
return nsnull;
nsCOMPtr<nsIDocument> doc = presShell->GetDocument();
if (!doc)
return nsnull;
// Get selection controller only for form controls, not for the document.
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
if (!content)
return nsnull;
nsIFrame *frame = presShell->GetPrimaryFrameFor(content);
if (!frame)
return nsnull;
nsPresContext *presContext = presShell->GetPresContext();
if (!presContext)
return nsnull;
nsISelectionController *controller = nsnull;
frame->GetSelectionController(presContext, &controller);
return controller;
}

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

@ -40,13 +40,15 @@
#include "nsIWeakReference.h"
#include "nsIAccessibleText.h"
#include "nsICaret.h"
#include "nsIDOMNode.h"
#include "nsISelectionListener.h"
#include "nsISelectionController.h"
#include "nsRect.h"
class nsRootAccessible;
class nsIView;
class nsIPresShell;
class nsIWidget;
/*
* This special accessibility class is for the caret, which is really the currently focused selection.
@ -119,17 +121,23 @@ public:
nsRect GetCaretRect(nsIWidget **aOutWidget);
protected:
nsresult NormalSelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel);
nsresult SpellcheckSelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel);
already_AddRefed<nsISelectionController>
GetSelectionControllerForNode(nsIDOMNode *aNode);
private:
// The currently focused control -- never a document.
// We listen to selection for one control at a time (the focused one)
// Document selection is handled separately via additional listeners on all active documents
// The current control is set via SetControlSelectionListener()
nsCOMPtr<nsIDOMNode> mCurrentControl; // Selection controller for the currently focused control
nsCOMPtr<nsIWeakReference> mCurrentControlSelection;
// Info for the the last selection event
// If it was on a control, then mLastUsedSelection == mCurrentControlSelection
// Otherwise, it's for a document where the selection changed
// Info for the the last selection event.
// If it was on a control, then it's control's selection. Otherwise, it's for
// a document where the selection changed.
nsCOMPtr<nsIWeakReference> mLastUsedSelection; // Weak ref to nsISelection
nsCOMPtr<nsIAccessibleText> mLastTextAccessible;
PRInt32 mLastCaretOffset;

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

@ -135,7 +135,34 @@ nsDocAccessible::~nsDocAccessible()
{
}
NS_INTERFACE_MAP_BEGIN(nsDocAccessible)
////////////////////////////////////////////////////////////////////////////////
// nsDocAccessible. nsISupports
PR_STATIC_CALLBACK(PLDHashOperator)
ElementTraverser(const void *aKey, nsIAccessNode *aAccessNode,
void *aUserArg)
{
nsCycleCollectionTraversalCallback *cb =
static_cast<nsCycleCollectionTraversalCallback*>(aUserArg);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, aAccessNode);
cb->NoteXPCOMChild(aAccessNode);
return PL_DHASH_NEXT;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocAccessible)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDocAccessible, nsAccessible)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mEventsToFire)
tmp->mAccessNodeCache.EnumerateRead(ElementTraverser, &cb);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDocAccessible, nsAccessible)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mEventsToFire)
tmp->ClearCache(tmp->mAccessNodeCache);
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDocAccessible)
NS_INTERFACE_MAP_ENTRY(nsIAccessibleDocument)
NS_INTERFACE_MAP_ENTRY(nsPIAccessibleDocument)
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
@ -1760,9 +1787,8 @@ void nsDocAccessible::RefreshNodes(nsIDOMNode *aStartNode)
getter_AddRefs(childAccessNode));
childAccessNode->GetDOMNode(getter_AddRefs(possibleAnonNode));
nsCOMPtr<nsIContent> iterContent = do_QueryInterface(possibleAnonNode);
if (iterContent && (iterContent->IsNativeAnonymous() ||
iterContent->GetBindingParent())) {
// GetBindingParent() check is a perf win -- make sure we don't
if (iterContent && iterContent->IsInAnonymousSubtree()) {
// IsInAnonymousSubtree() check is a perf win -- make sure we don't
// shut down the same subtree twice since we'll reach non-anon content via
// DOM traversal later in this method
RefreshNodes(possibleAnonNode);

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

@ -65,6 +65,8 @@ class nsDocAccessible : public nsHyperTextAccessibleWrap,
public nsSupportsWeakReference
{
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDocAccessible, nsAccessible)
NS_DECL_NSIACCESSIBLEDOCUMENT
NS_DECL_NSPIACCESSIBLEDOCUMENT
NS_DECL_NSIOBSERVER

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

@ -40,7 +40,6 @@
#include "nsAccessibleEventData.h"
#include "nsHTMLSelectAccessible.h"
#include "nsIBaseWindow.h"
#include "nsICaret.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocShellTreeNode.h"

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

@ -0,0 +1,181 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsTextUtils.h"
#include "nsAccessNode.h"
////////////////////////////////////////////////////////////////////////////////
// nsLangTextAttr
PRBool
nsLangTextAttr::equal(nsIDOMElement *aElm)
{
nsCOMPtr<nsIContent> content(do_QueryInterface(aElm));
if (!content)
return PR_FALSE;
nsAutoString lang;
nsAccUtils::GetLanguageFor(content, mRootContent, lang);
return lang == mLang;
}
////////////////////////////////////////////////////////////////////////////////
// nsCSSTextAttr
/**
* Item of the gCSSTextAttrsMap map.
*/
struct nsCSSTextAttrMapItem
{
const char* mCSSName;
const char* mCSSValue;
const char* mAttrName;
const char* mAttrValue;
};
/**
* The map of CSS properties to text attributes.
*/
const char* const kAnyValue = nsnull;
const char* const kCopyName = nsnull;
const char* const kCopyValue = nsnull;
static nsCSSTextAttrMapItem gCSSTextAttrsMap[] = {
// CSS name CSS value Attribute name Attribute name
{ "background-color", kAnyValue, kCopyName, kCopyValue },
{ "color", kAnyValue, kCopyName, kCopyValue },
{ "font-family", kAnyValue, kCopyName, kCopyValue },
{ "font-size", kAnyValue, kCopyName, kCopyValue },
{ "font-style", kAnyValue, kCopyName, kCopyValue },
{ "font-weight", kAnyValue, kCopyName, kCopyValue },
{ "text-decoration", "line-through", "text-line-through-style", "solid" },
{ "text-decoration", "underline", "text-underline-style", "solid" },
{ "text-align", kAnyValue, kCopyName, kCopyValue },
{ "text-indent", kAnyValue, kCopyName, kCopyValue },
{ "vertical-align", kAnyValue, "text-position", kCopyValue }
};
nsCSSTextAttr::nsCSSTextAttr(PRBool aIncludeDefAttrValue, nsIDOMElement *aElm,
nsIDOMElement *aRootElm) :
mIndex(-1), mIncludeDefAttrValue(aIncludeDefAttrValue)
{
nsAccessNode::GetComputedStyleDeclaration(EmptyString(), aElm,
getter_AddRefs(mStyleDecl));
if (!mIncludeDefAttrValue)
nsAccessNode::GetComputedStyleDeclaration(EmptyString(), aRootElm,
getter_AddRefs(mDefStyleDecl));
}
PRBool
nsCSSTextAttr::equal(nsIDOMElement *aElm)
{
if (!aElm || !mStyleDecl)
return PR_FALSE;
nsCOMPtr<nsIDOMCSSStyleDeclaration> currStyleDecl;
nsAccessNode::GetComputedStyleDeclaration(EmptyString(), aElm,
getter_AddRefs(currStyleDecl));
if (!currStyleDecl)
return PR_FALSE;
NS_ConvertASCIItoUTF16 cssName(gCSSTextAttrsMap[mIndex].mCSSName);
nsAutoString currValue;
nsresult rv = currStyleDecl->GetPropertyValue(cssName, currValue);
if (NS_FAILED(rv))
return PR_FALSE;
nsAutoString value;
rv = mStyleDecl->GetPropertyValue(cssName, value);
return NS_SUCCEEDED(rv) && value == currValue;
}
PRBool
nsCSSTextAttr::iterate()
{
return ++mIndex < static_cast<PRInt32>(NS_ARRAY_LENGTH(gCSSTextAttrsMap));
}
PRBool
nsCSSTextAttr::get(nsACString& aName, nsAString& aValue)
{
if (!mStyleDecl)
return PR_FALSE;
NS_ConvertASCIItoUTF16 cssName(gCSSTextAttrsMap[mIndex].mCSSName);
nsresult rv = mStyleDecl->GetPropertyValue(cssName, aValue);
if (NS_FAILED(rv))
return PR_FALSE;
// Don't expose text attribute if corresponding CSS value on the element
// equals to CSS value on the root element and we don't want to include
// default values.
if (!mIncludeDefAttrValue) {
if (!mDefStyleDecl)
return PR_FALSE;
nsAutoString defValue;
mDefStyleDecl->GetPropertyValue(cssName, defValue);
if (defValue == aValue)
return PR_FALSE;
}
// Don't expose text attribute if its required specific CSS value isn't
// matched with the CSS value we got.
const char *cssValue = gCSSTextAttrsMap[mIndex].mCSSValue;
if (cssValue != kAnyValue && !aValue.EqualsASCII(cssValue))
return PR_FALSE;
// Get the name of text attribute.
if (gCSSTextAttrsMap[mIndex].mAttrName != kCopyName)
aName = gCSSTextAttrsMap[mIndex].mAttrName;
else
aName = gCSSTextAttrsMap[mIndex].mCSSName;
// Get the value of text attribute.
const char *attrValue = gCSSTextAttrsMap[mIndex].mAttrValue;
if (attrValue != kCopyValue)
AppendASCIItoUTF16(attrValue, aValue);
return PR_TRUE;
}

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

@ -0,0 +1,112 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsTextUtils_h_
#define nsTextUtils_h_
#include "nsIDOMElement.h"
#include "nsIDOMCSSStyleDeclaration.h"
#include "nsIContent.h"
#include "nsCOMPtr.h"
#include "nsString.h"
/**
* Base class to work with text attributes. See derived classes below.
*/
class nsTextAttr
{
public:
/**
* Return true if the text attribute for the given element equals with
* predefined attribute.
*/
virtual PRBool equal(nsIDOMElement *aElm) = 0;
};
/**
* Class is used for the work with 'lang' text attributes. Used in
* nsHyperTextAccessible.
*/
class nsLangTextAttr : public nsTextAttr
{
public:
nsLangTextAttr(nsAString& aLang, nsIContent *aRootContent) :
mLang(aLang), mRootContent(aRootContent) { }
virtual PRBool equal(nsIDOMElement *aElm);
private:
nsString mLang;
nsCOMPtr<nsIContent> mRootContent;
};
/**
* Class is used for the work with CSS based text attributes. Used in
* nsHyperTextAccessible.
*/
class nsCSSTextAttr : public nsTextAttr
{
public:
nsCSSTextAttr(PRBool aIncludeDefAttrValue, nsIDOMElement *aElm,
nsIDOMElement *aRootElm);
// nsTextAttr
virtual PRBool equal(nsIDOMElement *aElm);
// nsCSSTextAttr
/**
* Interates through attributes.
*/
PRBool iterate();
/**
* Get name and value of attribute.
*/
PRBool get(nsACString& aName, nsAString& aValue);
private:
PRInt32 mIndex;
PRBool mIncludeDefAttrValue;
nsCOMPtr<nsIDOMCSSStyleDeclaration> mStyleDecl;
nsCOMPtr<nsIDOMCSSStyleDeclaration> mDefStyleDecl;
};
#endif

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

@ -41,6 +41,8 @@
#include "nsAccessibilityAtoms.h"
#include "nsAccessibilityService.h"
#include "nsAccessibleTreeWalker.h"
#include "nsTextUtils.h"
#include "nsPIAccessNode.h"
#include "nsIClipboard.h"
#include "nsContentCID.h"
@ -50,6 +52,7 @@
#include "nsPIDOMWindow.h"
#include "nsIDOMDocumentView.h"
#include "nsIDOMRange.h"
#include "nsIDOMNSRange.h"
#include "nsIDOMWindowInternal.h"
#include "nsIDOMXULDocument.h"
#include "nsIEditingSession.h"
@ -637,7 +640,9 @@ nsresult nsHyperTextAccessible::DOMPointToHypertextOffset(nsIDOMNode* aNode, PRI
if (findContent->IsNodeOfType(nsINode::eHTML) &&
findContent->NodeInfo()->Equals(nsAccessibilityAtoms::br)) {
nsIContent *parent = findContent->GetParent();
if (parent && parent->IsNativeAnonymous() && parent->GetChildCount() == 1) {
if (parent &&
parent->IsRootOfNativeAnonymousSubtree() &&
parent->GetChildCount() == 1) {
// This <br> is the only node in a text control, therefore it is the hacky
// "bogus node" used when there is no text in a control
*aHyperTextOffset = 0;
@ -671,7 +676,7 @@ nsresult nsHyperTextAccessible::DOMPointToHypertextOffset(nsIDOMNode* aNode, PRI
// Start offset, inclusive
// Make sure the offset lands on the embedded object character in order to indicate
// the true inner offset is inside the subtree for that link
addTextOffset = (TextLength(descendantAccessible) == addTextOffset) ? 1 : 0;
addTextOffset = (TextLength(descendantAccessible) == static_cast<PRInt32>(addTextOffset)) ? 1 : 0;
}
descendantAccessible = parentAccessible;
}
@ -698,6 +703,18 @@ nsresult nsHyperTextAccessible::DOMPointToHypertextOffset(nsIDOMNode* aNode, PRI
return NS_OK;
}
nsresult
nsHyperTextAccessible::HypertextOffsetToDOMPoint(PRInt32 aHTOffset,
nsIDOMNode **aNode,
PRInt32 *aOffset)
{
nsCOMPtr<nsIDOMNode> endNode;
PRInt32 endOffset;
return HypertextOffsetsToDOMRange(aHTOffset, aHTOffset, aNode, aOffset,
getter_AddRefs(endNode), &endOffset);
}
nsresult
nsHyperTextAccessible::HypertextOffsetsToDOMRange(PRInt32 aStartHTOffset,
PRInt32 aEndHTOffset,
@ -869,6 +886,9 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
nsAString &aText)
{
aText.Truncate();
NS_ENSURE_ARG_POINTER(aStartOffset);
NS_ENSURE_ARG_POINTER(aEndOffset);
*aStartOffset = *aEndOffset = 0;
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
@ -888,11 +908,15 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
// otherwise screen readers will announce the wrong line as the user presses up or down arrow and land
// at the end of a line.
nsCOMPtr<nsISelection> domSel;
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
nsnull, getter_AddRefs(domSel));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSel));
nsCOMPtr<nsFrameSelection> frameSelection;
rv = privateSelection->GetFrameSelection(getter_AddRefs(frameSelection));
NS_ENSURE_SUCCESS(rv, rv);
if (frameSelection->GetHint() == nsFrameSelection::HINTLEFT) {
-- aOffset; // We are at the start of a line
}
@ -902,6 +926,52 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
return NS_ERROR_FAILURE;
}
nsSelectionAmount amount;
PRBool needsStart = PR_FALSE;
switch (aBoundaryType) {
case BOUNDARY_CHAR:
amount = eSelectCharacter;
if (aType == eGetAt)
aType = eGetAfter; // Avoid returning 2 characters
break;
case BOUNDARY_WORD_START:
needsStart = PR_TRUE;
amount = eSelectWord;
break;
case BOUNDARY_WORD_END:
amount = eSelectWord;
break;
case BOUNDARY_LINE_START:
// Newlines are considered at the end of a line. Since getting
// the BOUNDARY_LINE_START gets the text from the line-start to the next
// line-start, the newline is included at the end of the string.
needsStart = PR_TRUE;
amount = eSelectLine;
break;
case BOUNDARY_LINE_END:
// Newlines are considered at the end of a line. Since getting
// the BOUNDARY_END_START gets the text from the line-end to the next
//line-end, the newline is included at the beginning of the string.
amount = eSelectLine;
break;
case BOUNDARY_ATTRIBUTE_RANGE:
{
nsresult rv = GetTextAttributes(PR_FALSE, aOffset,
aStartOffset, aEndOffset, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
return GetText(*aStartOffset, *aEndOffset, aText);
}
default: // Note, sentence support is deprecated and falls through to here
return NS_ERROR_INVALID_ARG;
}
PRInt32 startOffset = aOffset + (aBoundaryType == BOUNDARY_LINE_END); // Avoid getting the previous line
PRInt32 endOffset = startOffset;
@ -929,60 +999,6 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
}
}
nsSelectionAmount amount;
PRBool needsStart = PR_FALSE;
switch (aBoundaryType)
{
case BOUNDARY_CHAR:
amount = eSelectCharacter;
if (aType == eGetAt) {
aType = eGetAfter; // Avoid returning 2 characters
}
break;
case BOUNDARY_WORD_START:
needsStart = PR_TRUE;
amount = eSelectWord;
break;
case BOUNDARY_WORD_END:
amount = eSelectWord;
break;
case BOUNDARY_LINE_START:
// Newlines are considered at the end of a line,
// Since getting the BOUNDARY_LINE_START gets the text from the line-start
// to the next line-start, the newline is included at the end of the string
needsStart = PR_TRUE;
amount = eSelectLine;
break;
case BOUNDARY_LINE_END:
// Newlines are considered at the end of a line,
// Since getting the BOUNDARY_END_START gets the text from the line-end
// to the next line-end, the newline is included at the beginning of the string
amount = eSelectLine;
break;
case BOUNDARY_ATTRIBUTE_RANGE:
{
// XXX We should merge identically formatted frames
// XXX deal with static text case
// XXX deal with boundary type
nsIContent *textContent = startFrame->GetContent();
// If not text, then it's represented by an embedded object char
// (length of 1)
// XXX did this mean to check for eTEXT?
// XXX This is completely wrong, needs to be reimplemented
PRInt32 textLength = textContent ? textContent->TextLength() : 1;
if (textLength < 0) {
return NS_ERROR_FAILURE;
}
*aStartOffset = aOffset - startOffset;
*aEndOffset = *aStartOffset + textLength;
startOffset = *aStartOffset;
endOffset = *aEndOffset;
return GetText(startOffset, endOffset, aText);
}
default: // Note, sentence support is deprecated and falls through to here
return NS_ERROR_INVALID_ARG;
}
PRInt32 finalStartOffset, finalEndOffset;
// If aType == eGetAt we'll change both the start and end offset from
@ -1071,31 +1087,106 @@ NS_IMETHODIMP nsHyperTextAccessible::GetTextAfterOffset(PRInt32 aOffset, nsAcces
return GetTextHelper(eGetAfter, aBoundaryType, aOffset, aStartOffset, aEndOffset, aText);
}
NS_IMETHODIMP nsHyperTextAccessible::GetAttributeRange(PRInt32 aOffset, PRInt32 *aRangeStartOffset,
PRInt32 *aRangeEndOffset, nsIAccessible **aAccessibleWithAttrs)
// nsIPersistentProperties
// nsIAccessibleText::getTextAttributes(in boolean includeDefAttrs,
// in long offset,
// out long rangeStartOffset,
// out long rangeEndOffset);
NS_IMETHODIMP
nsHyperTextAccessible::GetTextAttributes(PRBool aIncludeDefAttrs,
PRInt32 aOffset,
PRInt32 *aStartOffset,
PRInt32 *aEndOffset,
nsIPersistentProperties **aAttributes)
{
// Return the range of text with common attributes around aOffset
*aRangeStartOffset = *aRangeEndOffset = 0;
*aAccessibleWithAttrs = nsnull;
// 1. First we get spell check, then language, then the set of CSS-based
// attributes.
// 2. As we get each new attribute, we pass the current start and end offsets
// as in/out parameters. In other words, as attributes are collected,
// the attribute range itself can only stay the same or get smaller.
//
// Example:
// Current: range 5-10
// Adding: range 7-12
// Result: range 7-10
if (!mDOMNode) {
NS_ENSURE_ARG_POINTER(aStartOffset);
*aStartOffset = 0;
NS_ENSURE_ARG_POINTER(aEndOffset);
nsresult rv = GetCharacterCount(aEndOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (aAttributes) {
*aAttributes = nsnull;
nsCOMPtr<nsIPersistentProperties> attributes =
do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
NS_ENSURE_TRUE(attributes, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aAttributes = attributes);
}
if (!mDOMNode)
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIAccessible> accessible;
while (NextChild(accessible)) {
PRInt32 length = TextLength(accessible);
NS_ENSURE_TRUE(length >= 0, NS_ERROR_FAILURE);
if (*aRangeStartOffset + length > aOffset) {
*aRangeEndOffset = *aRangeStartOffset + length;
NS_ADDREF(*aAccessibleWithAttrs = accessible);
return NS_OK;
}
*aRangeStartOffset += length;
}
nsCOMPtr<nsIDOMNode> node;
PRInt32 nodeOffset = 0;
rv = HypertextOffsetToDOMPoint(aOffset, getter_AddRefs(node), &nodeOffset);
NS_ENSURE_SUCCESS(rv, rv);
return NS_ERROR_FAILURE;
// Set 'misspelled' text attribute.
rv = GetSpellTextAttribute(node, nodeOffset, aStartOffset, aEndOffset,
aAttributes ? *aAttributes : nsnull);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> content(do_QueryInterface(node));
if (content && content->IsNodeOfType(nsINode::eELEMENT))
node = do_QueryInterface(content->GetChildAt(nodeOffset));
if (!node)
return NS_OK;
// Set 'lang' text attribute.
rv = GetLangTextAttributes(aIncludeDefAttrs, node,
aStartOffset, aEndOffset,
aAttributes ? *aAttributes : nsnull);
NS_ENSURE_SUCCESS(rv, rv);
// Set CSS based text attributes.
rv = GetCSSTextAttributes(aIncludeDefAttrs, node,
aStartOffset, aEndOffset,
aAttributes ? *aAttributes : nsnull);
return rv;
}
// nsIPersistentProperties
// nsIAccessibleText::defaultTextAttributes
NS_IMETHODIMP
nsHyperTextAccessible::GetDefaultTextAttributes(nsIPersistentProperties **aAttributes)
{
NS_ENSURE_ARG_POINTER(aAttributes);
*aAttributes = nsnull;
nsCOMPtr<nsIPersistentProperties> attributes =
do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
NS_ENSURE_TRUE(attributes, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aAttributes = attributes);
if (!mDOMNode)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMElement> element = nsAccUtils::GetDOMElementFor(mDOMNode);
nsCSSTextAttr textAttr(PR_TRUE, element, nsnull);
while (textAttr.iterate()) {
nsCAutoString name;
nsAutoString value, oldValue;
if (textAttr.get(name, value))
attributes->SetStringProperty(name, value, oldValue);
}
return NS_OK;
}
nsresult
@ -1474,7 +1565,8 @@ nsresult nsHyperTextAccessible::SetSelectionRange(PRInt32 aStartPos, PRInt32 aEn
// ranges remaining from previous selection
nsCOMPtr<nsISelection> domSel;
nsCOMPtr<nsISelectionController> selCon;
GetSelections(getter_AddRefs(selCon), getter_AddRefs(domSel));
GetSelections(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(selCon), getter_AddRefs(domSel));
if (domSel) {
PRInt32 numRanges;
domSel->GetRangeCount(&numRanges);
@ -1509,7 +1601,8 @@ NS_IMETHODIMP nsHyperTextAccessible::GetCaretOffset(PRInt32 *aCaretOffset)
*aCaretOffset = 0;
nsCOMPtr<nsISelection> domSel;
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
nsnull, getter_AddRefs(domSel));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> caretNode;
@ -1527,7 +1620,8 @@ PRInt32 nsHyperTextAccessible::GetCaretLineNumber()
// Provide the line number for the caret, relative to the
// currently focused node. Use a 1-based index
nsCOMPtr<nsISelection> domSel;
GetSelections(nsnull, getter_AddRefs(domSel));
GetSelections(nsISelectionController::SELECTION_NORMAL, nsnull,
getter_AddRefs(domSel));
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSel));
NS_ENSURE_TRUE(privateSelection, -1);
nsCOMPtr<nsFrameSelection> frameSelection;
@ -1590,9 +1684,11 @@ PRInt32 nsHyperTextAccessible::GetCaretLineNumber()
return lineNumber;
}
nsresult nsHyperTextAccessible::GetSelections(nsISelectionController **aSelCon,
nsISelection **aDomSel,
nsCOMArray<nsIDOMRange>* aRanges)
nsresult
nsHyperTextAccessible::GetSelections(PRInt16 aType,
nsISelectionController **aSelCon,
nsISelection **aDomSel,
nsCOMArray<nsIDOMRange>* aRanges)
{
if (!mDOMNode) {
return NS_ERROR_FAILURE;
@ -1610,7 +1706,6 @@ nsresult nsHyperTextAccessible::GetSelections(nsISelectionController **aSelCon,
nsCOMPtr<nsISelection> domSel;
nsCOMPtr<nsISelectionController> selCon;
nsCOMPtr<nsIDOMNode> startNode;
nsCOMPtr<nsIEditor> editor;
GetAssociatedEditor(getter_AddRefs(editor));
nsCOMPtr<nsIPlaintextEditor> peditor(do_QueryInterface(editor));
@ -1619,18 +1714,7 @@ nsresult nsHyperTextAccessible::GetSelections(nsISelectionController **aSelCon,
// This is for form controls which have their own
// selection controller separate from the document, for example
// HTML:input, HTML:textarea, XUL:textbox, etc.
if (aSelCon) {
editor->GetSelectionController(getter_AddRefs(selCon));
NS_ENSURE_TRUE(*aSelCon, NS_ERROR_FAILURE);
}
editor->GetSelection(getter_AddRefs(domSel));
NS_ENSURE_TRUE(domSel, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMElement> editorRoot;
editor->GetRootElement(getter_AddRefs(editorRoot));
startNode = do_QueryInterface(editorRoot);
NS_ENSURE_STATE(startNode);
editor->GetSelectionController(getter_AddRefs(selCon));
}
else {
// Case 2: rich content subtree (can be rich editor)
@ -1641,13 +1725,11 @@ nsresult nsHyperTextAccessible::GetSelections(nsISelectionController **aSelCon,
// Get the selection and selection controller
frame->GetSelectionController(GetPresContext(),
getter_AddRefs(selCon));
NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(domSel));
NS_ENSURE_TRUE(domSel, NS_ERROR_FAILURE);
startNode = mDOMNode;
}
NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
selCon->GetSelection(aType, getter_AddRefs(domSel));
NS_ENSURE_TRUE(domSel, NS_ERROR_FAILURE);
if (aSelCon) {
NS_ADDREF(*aSelCon = selCon);
@ -1655,10 +1737,19 @@ nsresult nsHyperTextAccessible::GetSelections(nsISelectionController **aSelCon,
if (aDomSel) {
NS_ADDREF(*aDomSel = domSel);
}
if (aRanges) {
nsCOMPtr<nsISelection2> selection2(do_QueryInterface(domSel));
NS_ENSURE_TRUE(selection2, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMNode> startNode(mDOMNode);
if (peditor) {
nsCOMPtr<nsIDOMElement> editorRoot;
editor->GetRootElement(getter_AddRefs(editorRoot));
startNode = do_QueryInterface(editorRoot);
}
NS_ENSURE_STATE(startNode);
nsCOMPtr<nsIDOMNodeList> childNodes;
nsresult rv = startNode->GetChildNodes(getter_AddRefs(childNodes));
NS_ENSURE_SUCCESS(rv, rv);
@ -1692,7 +1783,8 @@ NS_IMETHODIMP nsHyperTextAccessible::GetSelectionCount(PRInt32 *aSelectionCount)
{
nsCOMPtr<nsISelection> domSel;
nsCOMArray<nsIDOMRange> ranges;
nsresult rv = GetSelections(nsnull, nsnull, &ranges);
nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
nsnull, nsnull, &ranges);
NS_ENSURE_SUCCESS(rv, rv);
*aSelectionCount = ranges.Count();
@ -1709,7 +1801,8 @@ NS_IMETHODIMP nsHyperTextAccessible::GetSelectionBounds(PRInt32 aSelectionNum, P
nsCOMPtr<nsISelection> domSel;
nsCOMArray<nsIDOMRange> ranges;
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel), &ranges);
nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
nsnull, getter_AddRefs(domSel), &ranges);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 rangeCount = ranges.Count();
@ -1762,7 +1855,8 @@ nsHyperTextAccessible::SetSelectionBounds(PRInt32 aSelectionNum,
PRInt32 aEndOffset)
{
nsCOMPtr<nsISelection> domSel;
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
nsnull, getter_AddRefs(domSel));
NS_ENSURE_SUCCESS(rv, rv);
// Caret is a collapsed selection
@ -1810,7 +1904,8 @@ nsHyperTextAccessible::SetSelectionBounds(PRInt32 aSelectionNum,
NS_IMETHODIMP nsHyperTextAccessible::AddSelection(PRInt32 aStartOffset, PRInt32 aEndOffset)
{
nsCOMPtr<nsISelection> domSel;
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
nsnull, getter_AddRefs(domSel));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 rangeCount;
@ -1825,7 +1920,8 @@ NS_IMETHODIMP nsHyperTextAccessible::AddSelection(PRInt32 aStartOffset, PRInt32
NS_IMETHODIMP nsHyperTextAccessible::RemoveSelection(PRInt32 aSelectionNum)
{
nsCOMPtr<nsISelection> domSel;
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
nsnull, getter_AddRefs(domSel));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 rangeCount;
@ -2037,3 +2133,356 @@ nsHyperTextAccessible::GetDOMPointByFrameOffset(nsIFrame *aFrame,
return NS_OK;
}
// nsHyperTextAccessible
nsresult
nsHyperTextAccessible::DOMRangeBoundToHypertextOffset(nsIDOMRange *aRange,
PRBool aIsStartBound,
PRBool aIsStartHTOffset,
PRInt32 *aHTOffset)
{
nsCOMPtr<nsIDOMNode> node;
PRInt32 nodeOffset = 0;
nsresult rv;
if (aIsStartBound) {
rv = aRange->GetStartContainer(getter_AddRefs(node));
NS_ENSURE_SUCCESS(rv, rv);
rv = aRange->GetStartOffset(&nodeOffset);
NS_ENSURE_SUCCESS(rv, rv);
} else {
rv = aRange->GetEndContainer(getter_AddRefs(node));
NS_ENSURE_SUCCESS(rv, rv);
rv = aRange->GetEndOffset(&nodeOffset);
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsIAccessible> startAcc;
rv = DOMPointToHypertextOffset(node, nodeOffset, aHTOffset,
getter_AddRefs(startAcc));
NS_ENSURE_SUCCESS(rv, rv);
if (aIsStartHTOffset && !startAcc)
*aHTOffset = 0;
return NS_OK;
}
// nsHyperTextAccessible
nsresult
nsHyperTextAccessible::GetSpellTextAttribute(nsIDOMNode *aNode,
PRInt32 aNodeOffset,
PRInt32 *aHTStartOffset,
PRInt32 *aHTEndOffset,
nsIPersistentProperties *aAttributes)
{
nsCOMArray<nsIDOMRange> ranges;
nsresult rv = GetSelections(nsISelectionController::SELECTION_SPELLCHECK,
nsnull, nsnull, &ranges);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 rangeCount = ranges.Count();
if (!rangeCount)
return NS_OK;
for (PRInt32 index = 0; index < rangeCount; index++) {
nsCOMPtr<nsIDOMRange> range = ranges[index];
nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
NS_ENSURE_STATE(nsrange);
PRInt16 result;
rv = nsrange->ComparePoint(aNode, aNodeOffset, &result);
NS_ENSURE_SUCCESS(rv, rv);
if (result == 1) { // range is before point
PRInt32 startHTOffset = 0;
rv = DOMRangeBoundToHypertextOffset(range, PR_FALSE, PR_TRUE,
&startHTOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (startHTOffset > *aHTStartOffset)
*aHTStartOffset = startHTOffset;
} else if (result == -1) { // range is after point
PRInt32 endHTOffset = 0;
rv = DOMRangeBoundToHypertextOffset(range, PR_TRUE, PR_FALSE,
&endHTOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (endHTOffset < *aHTEndOffset)
*aHTEndOffset = endHTOffset;
} else { // point is in range
PRInt32 startHTOffset = 0;
rv = DOMRangeBoundToHypertextOffset(range, PR_TRUE, PR_TRUE,
&startHTOffset);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 endHTOffset = 0;
rv = DOMRangeBoundToHypertextOffset(range, PR_FALSE, PR_FALSE,
&endHTOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (startHTOffset > *aHTStartOffset)
*aHTStartOffset = startHTOffset;
if (endHTOffset < *aHTEndOffset)
*aHTEndOffset = endHTOffset;
if (aAttributes) {
nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::invalid,
NS_LITERAL_STRING("spelling"));
}
return NS_OK;
}
}
return NS_OK;
}
// nsHyperTextAccessible
nsresult
nsHyperTextAccessible::GetLangTextAttributes(PRBool aIncludeDefAttrs,
nsIDOMNode *aSourceNode,
PRInt32 *aStartHTOffset,
PRInt32 *aEndHTOffset,
nsIPersistentProperties *aAttributes)
{
nsCOMPtr<nsIDOMElement> sourceElm(nsAccUtils::GetDOMElementFor(aSourceNode));
nsCOMPtr<nsIContent> content(do_QueryInterface(sourceElm));
nsCOMPtr<nsIContent> rootContent(do_QueryInterface(mDOMNode));
nsAutoString lang;
nsAccUtils::GetLanguageFor(content, rootContent, lang);
nsAutoString rootLang;
nsresult rv = GetLanguage(rootLang);
NS_ENSURE_SUCCESS(rv, rv);
if (aAttributes) {
// Expose 'language' text attribute if the DOM 'lang' attribute is
// presented and it's different from the 'lang' attribute on the root
// element or we should include default values of text attribute.
const nsAString& resultLang = lang.IsEmpty() ? rootLang : lang;
if (!resultLang.IsEmpty() && (aIncludeDefAttrs || lang != rootLang))
nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::language,
resultLang);
}
nsLangTextAttr textAttr(lang, rootContent);
return GetRangeForTextAttr(aSourceNode, &textAttr,
aStartHTOffset, aEndHTOffset);
}
// nsHyperTextAccessible
nsresult
nsHyperTextAccessible::GetCSSTextAttributes(PRBool aIncludeDefAttrs,
nsIDOMNode *aSourceNode,
PRInt32 *aStartHTOffset,
PRInt32 *aEndHTOffset,
nsIPersistentProperties *aAttributes)
{
nsCOMPtr<nsIDOMElement> sourceElm(nsAccUtils::GetDOMElementFor(aSourceNode));
nsCOMPtr<nsIDOMElement> rootElm(nsAccUtils::GetDOMElementFor(mDOMNode));
nsCSSTextAttr textAttr(aIncludeDefAttrs, sourceElm, rootElm);
while (textAttr.iterate()) {
nsCAutoString name;
nsAutoString value, oldValue;
if (aAttributes && textAttr.get(name, value))
aAttributes->SetStringProperty(name, value, oldValue);
nsresult rv = GetRangeForTextAttr(aSourceNode, &textAttr,
aStartHTOffset, aEndHTOffset);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
// nsHyperTextAccessible
nsresult
nsHyperTextAccessible::GetRangeForTextAttr(nsIDOMNode *aNode,
nsTextAttr *aComparer,
PRInt32 *aStartHTOffset,
PRInt32 *aEndHTOffset)
{
nsCOMPtr<nsIDOMElement> rootElm(nsAccUtils::GetDOMElementFor(mDOMNode));
NS_ENSURE_STATE(rootElm);
nsCOMPtr<nsIDOMNode> tmpNode(aNode);
nsCOMPtr<nsIDOMNode> currNode(aNode);
// Navigate backwards and forwards from current node to the root node to
// calculate range bounds for the text attribute. Navigation sequence is the
// following:
// 1. Navigate through the siblings.
// 2. If the traversed sibling has children then navigate from its leaf child
// to it through whole tree of the traversed sibling.
// 3. Get the parent and cycle algorithm until the root node.
// Navigate backwards (find the start offset).
while (currNode && currNode != rootElm) {
nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(currNode));
NS_ENSURE_STATE(currElm);
if (currNode != aNode && !aComparer->equal(currElm)) {
PRInt32 startHTOffset = 0;
nsCOMPtr<nsIAccessible> startAcc;
nsresult rv = DOMPointToHypertextOffset(tmpNode, -1, &startHTOffset,
getter_AddRefs(startAcc));
NS_ENSURE_SUCCESS(rv, rv);
if (!startAcc)
startHTOffset = 0;
if (startHTOffset > *aStartHTOffset)
*aStartHTOffset = startHTOffset;
break;
}
currNode->GetPreviousSibling(getter_AddRefs(tmpNode));
if (tmpNode) {
// Navigate through the subtree of traversed children to calculate
// left bound of the range.
FindStartOffsetInSubtree(tmpNode, currNode, aComparer, aStartHTOffset);
}
currNode->GetParentNode(getter_AddRefs(tmpNode));
currNode.swap(tmpNode);
}
// Navigate forwards (find the end offset).
PRBool moveIntoSubtree = PR_TRUE;
currNode = aNode;
while (currNode && currNode != rootElm) {
nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(currNode));
NS_ENSURE_STATE(currElm);
// Stop new end offset searching if the given text attribute changes its
// value.
if (!aComparer->equal(currElm)) {
PRInt32 endHTOffset = 0;
nsresult rv = DOMPointToHypertextOffset(currNode, -1, &endHTOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (endHTOffset < *aEndHTOffset)
*aEndHTOffset = endHTOffset;
break;
}
if (moveIntoSubtree) {
// Navigate through subtree of traversed node. We use 'moveIntoSubtree'
// flag to avoid traversing the same subtree twice.
currNode->GetFirstChild(getter_AddRefs(tmpNode));
if (tmpNode)
FindEndOffsetInSubtree(tmpNode, aComparer, aEndHTOffset);
}
currNode->GetNextSibling(getter_AddRefs(tmpNode));
moveIntoSubtree = PR_TRUE;
if (!tmpNode) {
currNode->GetParentNode(getter_AddRefs(tmpNode));
moveIntoSubtree = PR_FALSE;
}
currNode.swap(tmpNode);
}
return NS_OK;
}
PRBool
nsHyperTextAccessible::FindEndOffsetInSubtree(nsIDOMNode *aCurrNode,
nsTextAttr *aComparer,
PRInt32 *aHTOffset)
{
if (!aCurrNode)
return PR_FALSE;
nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(aCurrNode));
NS_ENSURE_STATE(currElm);
// If the given text attribute (pointed by nsTextAttr object) changes its
// value on the traversed element then fit the end of range.
if (!aComparer->equal(currElm)) {
PRInt32 endHTOffset = 0;
nsresult rv = DOMPointToHypertextOffset(aCurrNode, -1, &endHTOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (endHTOffset < *aHTOffset)
*aHTOffset = endHTOffset;
return PR_TRUE;
}
// Deeply traverse into the tree to fit the end of range.
nsCOMPtr<nsIDOMNode> nextNode;
aCurrNode->GetFirstChild(getter_AddRefs(nextNode));
if (nextNode) {
PRBool res = FindEndOffsetInSubtree(nextNode, aComparer, aHTOffset);
if (res)
return res;
}
aCurrNode->GetNextSibling(getter_AddRefs(nextNode));
if (nextNode) {
if (FindEndOffsetInSubtree(nextNode, aComparer, aHTOffset))
return PR_TRUE;
}
return PR_FALSE;
}
PRBool
nsHyperTextAccessible::FindStartOffsetInSubtree(nsIDOMNode *aCurrNode,
nsIDOMNode *aPrevNode,
nsTextAttr *aComparer,
PRInt32 *aHTOffset)
{
if (!aCurrNode)
return PR_FALSE;
// Find the closest element back to the traversed element.
nsCOMPtr<nsIDOMNode> nextNode;
aCurrNode->GetLastChild(getter_AddRefs(nextNode));
if (nextNode) {
if (FindStartOffsetInSubtree(nextNode, aPrevNode, aComparer, aHTOffset))
return PR_TRUE;
}
nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(aCurrNode));
NS_ENSURE_STATE(currElm);
// If the given text attribute (pointed by nsTextAttr object) changes its
// value on the traversed element then fit the start of range.
if (!aComparer->equal(currElm)) {
PRInt32 startHTOffset = 0;
nsCOMPtr<nsIAccessible> startAcc;
nsresult rv = DOMPointToHypertextOffset(aPrevNode, -1, &startHTOffset,
getter_AddRefs(startAcc));
NS_ENSURE_SUCCESS(rv, rv);
if (!startAcc)
startHTOffset = 0;
if (startHTOffset > *aHTOffset)
*aHTOffset = startHTOffset;
return PR_TRUE;
}
// Moving backwards to find the start of range.
aCurrNode->GetPreviousSibling(getter_AddRefs(nextNode));
if (nextNode) {
if (FindStartOffsetInSubtree(nextNode, aCurrNode, aComparer, aHTOffset))
return PR_TRUE;
}
return PR_FALSE;
}

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

@ -45,6 +45,8 @@
#include "nsIAccessibleHyperText.h"
#include "nsIAccessibleEditableText.h"
#include "nsAccessibleEventData.h"
#include "nsTextUtils.h"
#include "nsFrameSelection.h"
#include "nsISelectionController.h"
@ -64,7 +66,6 @@ const PRUnichar kForcedNewLineChar = '\n';
{ 0xa9, 0x2e, 0x95, 0x23, 0x97, 0x05, 0xf3, 0x0b } \
}
/**
* Special Accessible that knows how contain both text and embedded objects
*/
@ -81,8 +82,11 @@ public:
NS_DECL_NSIACCESSIBLEEDITABLETEXT
NS_DECLARE_STATIC_IID_ACCESSOR(NS_HYPERTEXTACCESSIBLE_IMPL_CID)
// nsIAccessible
NS_IMETHOD GetRole(PRUint32 *aRole);
NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
// nsAccessible
virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
void CacheChildren();
@ -124,6 +128,17 @@ public:
nsIAccessible **aFinalAccessible = nsnull,
PRBool aIsEndOffset = PR_FALSE);
/**
* Turn a hypertext offsets into DOM point.
*
* @param aHTOffset [in] the given start hypertext offset
* @param aNode [out] start node
* @param aOffset [out] offset inside the start node
*/
nsresult HypertextOffsetToDOMPoint(PRInt32 aHTOffset,
nsIDOMNode **aNode,
PRInt32 *aOffset);
/**
* Turn a start and end hypertext offsets into DOM range.
*
@ -211,15 +226,23 @@ protected:
// Selection helpers
/**
* Get the relevant selection interfaces and ranges for the current hyper text
* @param aSelCon The selection controller for the current hyper text, or nsnull if not needed
* @param aDomSel The selection interface for the current hyper text, or nsnull if not needed
* @param aRanges The selected ranges within the current subtree, or nsnull if not needed
/**
* Get the relevant selection interfaces and ranges for the current hyper
* text.
*
* @param aType [in] the selection type
* @param aSelCon [out, optional] the selection controller for the current
* hyper text
* @param aDomSel [out, optional] the selection interface for the current
* hyper text
* @param aRanges [out, optional] the selected ranges within the current
* subtree
*/
nsresult GetSelections(nsISelectionController **aSelCon,
nsresult GetSelections(PRInt16 aType,
nsISelectionController **aSelCon,
nsISelection **aDomSel = nsnull,
nsCOMArray<nsIDOMRange>* aRanges = nsnull);
nsresult SetSelectionRange(PRInt32 aStartPos, PRInt32 aEndPos);
/**
@ -233,6 +256,125 @@ protected:
nsresult GetDOMPointByFrameOffset(nsIFrame *aFrame, PRInt32 aOffset,
nsIAccessible *aAccessible,
nsIDOMNode **aNode, PRInt32 *aNodeOffset);
/**
* Return hyper text offset for the specified bound of the given DOM range.
* If the bound is outside of the hyper text then offset value is either
* 0 or number of characters of hyper text, it depends on type of requested
* offset. The method is a wrapper for DOMPointToHypertextOffset.
*
* @param aRange [in] the given range
* @param aIsStartBound [in] specifies whether the required range bound is
* start bound
* @param aIsStartOffset [in] the offset type, used when the range bound is
* outside of hyper text
* @param aHTOffset [out] the result offset
*/
nsresult DOMRangeBoundToHypertextOffset(nsIDOMRange *aRange,
PRBool aIsStartBound,
PRBool aIsStartOffset,
PRInt32 *aHTOffset);
/**
* Set 'misspelled' text attribute and return range offsets where the
* attibute is stretched. If the text is not misspelled at the given offset
* then we expose only range offsets where text is not misspelled. The method
* is used by GetTextAttributes() method.
*
* @param aIncludeDefAttrs [in] points whether text attributes having default
* values of attributes should be included
* @param aSourceNode [in] the node we start to traverse from
* @param aStartOffset [in, out] the start offset
* @param aEndOffset [in, out] the end offset
* @param aAttributes [out, optional] result attributes
*/
nsresult GetSpellTextAttribute(nsIDOMNode *aNode, PRInt32 aNodeOffset,
PRInt32 *aStartOffset,
PRInt32 *aEndOffset,
nsIPersistentProperties *aAttributes);
/**
* Set 'lang' text attribute and return range offsets where attibute is
* stretched. The method is used by GetTextAttributes() method.
*
* @param aIncludeDefAttrs [in] points whether text attributes having default
* values of attributes should be included
* @param aSourceNode [in] the node we start to traverse from
* @param aStartOffset [in, out] the start offset
* @param aEndOffset [in, out] the end offset
* @param aAttributes [out, optional] result attributes
*/
nsresult GetLangTextAttributes(PRBool aIncludeDefAttrs,
nsIDOMNode *aSourceNode,
PRInt32 *aStartOffset,
PRInt32 *aEndOffset,
nsIPersistentProperties *aAttributes);
/**
* Set CSS based text attribute and return range offsets where attibutes are
* stretched. The method is used by GetTextAttributes() method.
*
* @param aIncludeDefAttrs [in] points whether text attributes having default
* values of attributes should be included
* @param aSourceNode [in] the node we start to traverse from
* @param aStartOffset [in, out] the start offset
* @param aEndOffset [in, out] the end offset
* @param aAttributes [out, optional] result attributes
*/
nsresult GetCSSTextAttributes(PRBool aIncludeDefAttrs,
nsIDOMNode *aSourceNode,
PRInt32 *aStartOffset,
PRInt32 *aEndOffset,
nsIPersistentProperties *aAttributes);
/**
* Calculates range (start and end offsets) of text where the text attribute
* (pointed by nsTextAttr object) is stretched. New offsets may be smaller if
* the given text attribute changes its value before or after the given
* offsets.
*
* @param aNode [in] the node we start to traverse from
* @param aComparer [in] object used to describe the text attribute
* @param aStartHTOffset [in, out] the start offset
* @param aEndHTOffset [in, out] the end offset
*/
nsresult GetRangeForTextAttr(nsIDOMNode *aNode,
nsTextAttr *aComparer,
PRInt32 *aStartHTOffset,
PRInt32 *aEndHTOffset);
/**
* Find new end offset for text attributes navigating through the tree. New
* end offset may be smaller if the given text attribute (pointed by
* nsTextAttr object) changes its value before the given end offset.
*
* @param aCurrNode [in] the first node of the tree
* @param aComparer [in] object used to describe the text attribute
* @param aHTOffset [in, out] the end offset
* @return true if the end offset has been changed
*/
PRBool FindEndOffsetInSubtree(nsIDOMNode *aCurrNode,
nsTextAttr *aComparer,
PRInt32 *aHTOffset);
/**
* Find the start offset for text attributes navigating through the tree. New
* start offset may be bigger if the given text attribute (pointed by
* nsTextAttr object) changes its value after the given start offset.
*
* @param aCurrNode [in] the node navigating through thee thee is started
* from
* @param aPrevNode [in] the previous node placed before the start node
* @param aComparer [in] object used to describe the text attribute
* @param aHTOffset [in, out] the start offset
* @return true if the start offset has been changed
*/
PRBool FindStartOffsetInSubtree(nsIDOMNode *aCurrNode,
nsIDOMNode *aPrevNode,
nsTextAttr *aComparer,
PRInt32 *aHTOffset);
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsHyperTextAccessible,

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

@ -48,6 +48,7 @@
#include "nsIAccessibleTypes.h"
#include "nsIWinAccessNode.h"
#include "nsAccessNodeWrap.h"
#include "nsAccessibleWrap.h"
#include "nsCOMPtr.h"
#include "nsString.h"
@ -108,32 +109,26 @@ __try {
GET_NSIACCESSIBLETEXT
nsCOMPtr<nsIAccessible> accessible;
PRInt32 startOffset = 0, endOffset = 0;
textAcc->GetAttributeRange(aOffset, &startOffset, &endOffset,
getter_AddRefs(accessible));
if (!accessible)
return E_FAIL;
nsCOMPtr<nsIWinAccessNode> winAccessNode(do_QueryInterface(accessible));
if (!winAccessNode)
return E_FAIL;
void *instancePtr = 0;
winAccessNode->QueryNativeInterface(IID_IAccessible2, &instancePtr);
if (!instancePtr)
return E_FAIL;
IAccessible2 *pAccessible2 = static_cast<IAccessible2*>(instancePtr);
HRESULT hr = pAccessible2->get_attributes(aTextAttributes);
pAccessible2->Release();
nsCOMPtr<nsIPersistentProperties> attributes;
nsresult rv = textAcc->GetTextAttributes(PR_TRUE, aOffset,
&startOffset, &endOffset,
getter_AddRefs(attributes));
if (NS_FAILED(rv))
return GetHRESULT(rv);
HRESULT hr = nsAccessibleWrap::ConvertToIA2Attributes(attributes,
aTextAttributes);
if (FAILED(hr))
return hr;
*aStartOffset = startOffset;
*aEndOffset = endOffset;
return hr;
return S_OK;
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return E_NOTIMPL;
return E_FAIL;
}
STDMETHODIMP

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

@ -37,6 +37,7 @@
* ***** END LICENSE BLOCK ***** */
#include "nsAccessNodeWrap.h"
#include <tchar.h>
#include "ISimpleDOMNode_i.c"
#include "nsAccessibilityAtoms.h"
#include "nsIAccessibilityService.h"
@ -66,6 +67,8 @@ LPFNNOTIFYWINEVENT nsAccessNodeWrap::gmNotifyWinEvent = nsnull;
LPFNGETGUITHREADINFO nsAccessNodeWrap::gmGetGUIThreadInfo = nsnull;
PRBool nsAccessNodeWrap::gIsEnumVariantSupportDisabled = 0;
// Used to determine whether an IAccessible2 compatible screen reader is loaded.
PRBool nsAccessNodeWrap::gIsIA2Disabled = PR_FALSE;
nsIAccessibleTextChangeEvent *nsAccessNodeWrap::gTextEvent = nsnull;
@ -599,6 +602,8 @@ void nsAccessNodeWrap::InitAccessibility()
gmGetGUIThreadInfo = (LPFNGETGUITHREADINFO)GetProcAddress(gmUserLib,"GetGUIThreadInfo");
}
DoATSpecificProcessing();
nsAccessNode::InitXPAccessibility();
}
@ -655,3 +660,40 @@ GetHRESULT(nsresult aResult)
}
}
PRBool nsAccessNodeWrap::IsOnlyMsaaCompatibleJawsPresent()
{
HMODULE jhookhandle = ::GetModuleHandleW(NS_LITERAL_STRING("jhook").get());
if (!jhookhandle)
return PR_FALSE; // No JAWS, or some other screen reader, use IA2
PRUnichar fileName[MAX_PATH];
::GetModuleFileNameW(jhookhandle, fileName, MAX_PATH);
DWORD dummy;
DWORD length = ::GetFileVersionInfoSizeW(fileName, &dummy);
LPBYTE versionInfo = new BYTE[length];
::GetFileVersionInfoW(fileName, 0, length, versionInfo);
UINT uLen;
VS_FIXEDFILEINFO *fixedFileInfo;
::VerQueryValueW(versionInfo, L"\\", (LPVOID*)&fixedFileInfo, &uLen);
DWORD dwFileVersionMS = fixedFileInfo->dwFileVersionMS;
DWORD dwFileVersionLS = fixedFileInfo->dwFileVersionLS;
delete [] versionInfo;
DWORD dwLeftMost = HIWORD(dwFileVersionMS);
// DWORD dwSecondLeft = LOWORD(dwFileVersionMS);
DWORD dwSecondRight = HIWORD(dwFileVersionLS);
// DWORD dwRightMost = LOWORD(dwFileVersionLS);
return (dwLeftMost < 8
|| (dwLeftMost == 8 && dwSecondRight < 2173));
}
void nsAccessNodeWrap::DoATSpecificProcessing()
{
if (IsOnlyMsaaCompatibleJawsPresent())
// All versions below 8.0.2173 are not compatible
gIsIA2Disabled = PR_TRUE;
}

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

@ -158,12 +158,20 @@ class nsAccessNodeWrap : public nsAccessNode,
static int FilterA11yExceptions(unsigned int aCode, EXCEPTION_POINTERS *aExceptionInfo);
static PRBool IsOnlyMsaaCompatibleJawsPresent();
static void DoATSpecificProcessing();
protected:
void GetAccessibleFor(nsIDOMNode *node, nsIAccessible **newAcc);
ISimpleDOMNode* MakeAccessNode(nsIDOMNode *node);
static PRBool gIsEnumVariantSupportDisabled;
/**
* Used to determine whether an IAccessible2 compatible screen reader is
* loaded. Currently used for JAWS versions older than 8.0.2173.
*/
static PRBool gIsIA2Disabled;
/**
* It is used in nsHyperTextAccessibleWrap for IA2::newText/oldText
* implementation.

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

@ -117,7 +117,7 @@ __try {
*ppv = static_cast<IEnumVARIANT*>(this);
} else if (IID_IServiceProvider == iid)
*ppv = static_cast<IServiceProvider*>(this);
else if (IID_IAccessible2 == iid)
else if (IID_IAccessible2 == iid && !gIsIA2Disabled)
*ppv = static_cast<IAccessible2*>(this);
if (NULL == *ppv) {
@ -1584,60 +1584,7 @@ __try {
if (NS_FAILED(rv))
return GetHRESULT(rv);
if (!attributes)
return S_FALSE;
nsCOMPtr<nsISimpleEnumerator> propEnum;
attributes->Enumerate(getter_AddRefs(propEnum));
if (!propEnum)
return E_FAIL;
nsAutoString strAttrs;
const char kCharsToEscape[] = ":;=,\\";
PRBool hasMore = PR_FALSE;
while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
nsCOMPtr<nsISupports> propSupports;
propEnum->GetNext(getter_AddRefs(propSupports));
nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(propSupports));
if (!propElem)
return E_FAIL;
nsCAutoString name;
rv = propElem->GetKey(name);
if (NS_FAILED(rv))
return GetHRESULT(rv);
PRUint32 offset = 0;
while ((offset = name.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
name.Insert('\\', offset);
offset += 2;
}
nsAutoString value;
rv = propElem->GetValue(value);
if (NS_FAILED(rv))
return E_FAIL;
offset = 0;
while ((offset = value.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
value.Insert('\\', offset);
offset += 2;
}
AppendUTF8toUTF16(name, strAttrs);
strAttrs.Append(':');
strAttrs.Append(value);
strAttrs.Append(';');
}
if (strAttrs.IsEmpty())
return S_FALSE;
*aAttributes = ::SysAllocStringLen(strAttrs.get(), strAttrs.Length());
return *aAttributes ? S_OK : E_OUTOFMEMORY;
return ConvertToIA2Attributes(attributes, aAttributes);
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return E_FAIL;
@ -1829,6 +1776,69 @@ nsAccessibleWrap::GetHWNDFor(nsIAccessible *aAccessible)
return hWnd;
}
HRESULT
nsAccessibleWrap::ConvertToIA2Attributes(nsIPersistentProperties *aAttributes,
BSTR *aIA2Attributes)
{
*aIA2Attributes = NULL;
// The format is name:value;name:value; with \ for escaping these
// characters ":;=,\".
if (!aAttributes)
return S_FALSE;
nsCOMPtr<nsISimpleEnumerator> propEnum;
aAttributes->Enumerate(getter_AddRefs(propEnum));
if (!propEnum)
return E_FAIL;
nsAutoString strAttrs;
const char kCharsToEscape[] = ":;=,\\";
PRBool hasMore = PR_FALSE;
while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
nsCOMPtr<nsISupports> propSupports;
propEnum->GetNext(getter_AddRefs(propSupports));
nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(propSupports));
if (!propElem)
return E_FAIL;
nsCAutoString name;
if (NS_FAILED(propElem->GetKey(name)))
return E_FAIL;
PRUint32 offset = 0;
while ((offset = name.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
name.Insert('\\', offset);
offset += 2;
}
nsAutoString value;
if (NS_FAILED(propElem->GetValue(value)))
return E_FAIL;
offset = 0;
while ((offset = value.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
value.Insert('\\', offset);
offset += 2;
}
AppendUTF8toUTF16(name, strAttrs);
strAttrs.Append(':');
strAttrs.Append(value);
strAttrs.Append(';');
}
if (strAttrs.IsEmpty())
return S_FALSE;
*aIA2Attributes = ::SysAllocStringLen(strAttrs.get(), strAttrs.Length());
return *aIA2Attributes ? S_OK : E_OUTOFMEMORY;
}
IDispatch *nsAccessibleWrap::NativeAccessible(nsIAccessible *aXPAccessible)
{
if (!aXPAccessible) {

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

@ -296,6 +296,8 @@ class nsAccessibleWrap : public nsAccessible,
// Helper methods
static PRInt32 GetChildIDFor(nsIAccessible* aAccessible);
static HWND GetHWNDFor(nsIAccessible *aAccessible);
static HRESULT ConvertToIA2Attributes(nsIPersistentProperties *aAttributes,
BSTR *aIA2Attributes);
/**
* System caret support: update the Windows caret position.

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

@ -47,13 +47,20 @@ include $(topsrcdir)/config/rules.mk
_TEST_FILES =\
moz.png \
nsIAccessible_actions.js \
nsIAccessible_name.css \
nsIAccessible_name.xbl \
test_aria_activedescendant.html \
test_aria_role_article.html \
test_bug368835.xul \
test_bug420863.html \
test_cssattrs.html \
test_groupattrs.xul \
test_table_indexes.html \
$(warning test_table_indexes.html temporarily disabled) \
test_nsIAccessible_actions.html \
test_nsIAccessible_actions.xul \
test_nsIAccessible_name.html \
test_nsIAccessible_name.xul \
test_nsIAccessibleTable_1.html \
test_nsIAccessibleTable_2.html \
test_nsIAccessibleTable_3.html \
@ -65,6 +72,7 @@ _TEST_FILES =\
test_nsIAccessibleHyperText.html \
test_nsIAccessibleImage.html \
test_nsOuterDocAccessible.html \
test_textattrs.html \
test_textboxes.html \
test_textboxes.xul \
testTextboxes.js \

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

@ -0,0 +1,150 @@
////////////////////////////////////////////////////////////////////////////////
// General
const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole;
var gAccRetrieval = null;
function initialize()
{
gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
getService(nsIAccessibleRetrieval);
}
addLoadEvent(initialize);
////////////////////////////////////////////////////////////////////////////////
// Event constants
const MOUSEDOWN_EVENT = 1;
const MOUSEUP_EVENT = 2;
const CLICK_EVENT = 4;
const COMMAND_EVENT = 8;
const CLICK_EVENTS = MOUSEDOWN_EVENT | MOUSEUP_EVENT | CLICK_EVENT;
const ALL_EVENTS = CLICK_EVENTS | COMMAND_EVENT;
////////////////////////////////////////////////////////////////////////////////
// Public functions
function testActions(aArray, aIndex)
{
if (!aIndex)
aIndex = 0;
if (aIndex == aArray.length) {
SimpleTest.finish();
return;
}
var ID = aArray[aIndex].ID;
var actionName = aArray[aIndex].actionName;
var events = aArray[aIndex].events;
var elm = document.getElementById(ID);
if (!elm) {
ok(false, "There is no element with ID " + ID);
SimpleTest.finish();
return null;
}
var acc = null;
try {
acc = gAccRetrieval.getAccessibleFor(elm);
} catch(e) {
}
if (!acc) {
ok(false, "There is no accessible for " + ID);
SimpleTest.finish();
return null;
}
is(acc.getActionName(0), actionName,
"Wrong action name of the accessible for " + ID);
gEventHandler.initialize(ID, elm, events);
acc.doAction(0);
window.setTimeout(
function()
{
gEventHandler.checkEvents();
testActions(aArray, aIndex + 1);
},
200
);
}
////////////////////////////////////////////////////////////////////////////////
// Private
var gEventHandler =
{
initialize: function(aID, aElm, aExpectedEvents)
{
this.ID = aID,
this.element = aElm;
this.mExpectedEvents = aExpectedEvents;
this.mFiredEvents = 0;
if (this.mExpectedEvents & MOUSEDOWN_EVENT)
aElm.addEventListener("mousedown", this, false);
if (this.mExpectedEvents & MOUSEUP_EVENT)
aElm.addEventListener("mouseup", this, false);
if (this.mExpectedEvents & CLICK_EVENT)
aElm.addEventListener("click", this, false);
if (this.mExpectedEvents & COMMAND_EVENT)
aElm.addEventListener("command", this, false);
},
checkEvents: function()
{
if (this.mExpectedEvents & MOUSEDOWN_EVENT) {
ok(this.mFiredEvents & MOUSEDOWN_EVENT,
"mousedown hasn't been fired for " + this.ID);
this.element.removeEventListener("mousedown", this, false);
}
if (this.mExpectedEvents & MOUSEUP_EVENT) {
ok(this.mFiredEvents & MOUSEUP_EVENT,
"mouseup hasn't been fired for " + this.ID);
this.element.removeEventListener("mouseup", this, false);
}
if (this.mExpectedEvents & CLICK_EVENT) {
ok(this.mFiredEvents & CLICK_EVENT,
"click hasn't been fired for " + this.ID);
this.element.removeEventListener("click", this, false);
}
if (this.mExpectedEvents & COMMAND_EVENT) {
ok(this.mFiredEvents & COMMAND_EVENT,
"command hasn't been fired for " + this.ID);
this.element.removeEventListener("command", this, false);
}
},
ID: "",
element: null,
handleEvent : function(aEvent)
{
if (aEvent.type == "mousedown")
this.mFiredEvents |= MOUSEDOWN_EVENT;
else if(aEvent.type == "mouseup")
this.mFiredEvents |= MOUSEUP_EVENT;
else if(aEvent.type == "click")
this.mFiredEvents |= CLICK_EVENT;
else if(aEvent.type == "command")
this.mFiredEvents |= COMMAND_EVENT;
},
mExpectedEvents: 0,
mFiredEvents: 0
};

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

@ -0,0 +1,11 @@
box.first {
-moz-binding: url('chrome://mochikit/content/a11y/accessible/nsIAccessible_name.xbl#first');
}
.second {
-moz-binding: url('chrome://mochikit/content/a11y/accessible/nsIAccessible_name.xbl#second');
}
.third {
-moz-binding: url('chrome://mochikit/content/a11y/accessible/nsIAccessible_name.xbl#third');
}

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

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<bindings xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="first">
<content>
<xul:textbox anonid="labeled" class="bottom"/>
<xul:label control="labeled" value="Label"/>
<children/>
</content>
</binding>
<binding id="second">
<content>
<xul:box class="first">
<xul:label control="toplabeled" value="Top textbox"/>
<xul:textbox anonid="toplabeled" class="top"/>
</xul:box>
<children/>
</content>
</binding>
</bindings>

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

@ -0,0 +1,49 @@
<html>
<head>
<title>nsIAccessible actions testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/nsIAccessible_actions.js"></script>
<script type="application/javascript">
function doTest()
{
var actionsArray = [
{
ID: "clickable",
actionName: "click",
events: CLICK_EVENTS
}
];
testActions(actionsArray);
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=410765"
title="nsIAccessible actions testing">
Mozilla Bug 410765
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="clickable" onclick="">Clickable text</div>
</body>
</html>

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

@ -0,0 +1,98 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/a11y/accessible/nsIAccessible_name.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="nsIAccessible actions testing">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/nsIAccessible_actions.js" />
<script type="application/javascript">
<![CDATA[
function doTest()
{
var actionsArray = [
{
ID: "menu",
actionName: "click",
events: CLICK_EVENTS
},
{
ID: "submenu",
actionName: "click",
events: CLICK_EVENTS
},
{
ID: "menuitem",
actionName: "click",
events: ALL_EVENTS
},
{
ID: "button",
actionName: "press",
events: ALL_EVENTS
},
{
ID: "buttonmenu",
actionName: "press",
events: CLICK_EVENTS
},
{
ID: "buttonmenu_item",
actionName: "click",
events: CLICK_EVENTS
}
];
testActions(actionsArray);
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doTest);
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=410765"
title="nsIAccessible actions testing">
Mozilla Bug 410765
</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<menubar>
<menu label="menu" id="menu">
<menupopup>
<menuitem label="menu item" id="menuitem"/>
<menu label="submenu" id="submenu">
<menupopup>
<menuitem label="menu item"/>
</menupopup>
</menu>
</menupopup>
</menu>
</menubar>
<button label="button" id="button"/>
<button type="menu" id="buttonmenu" label="button">
<menupopup>
<menuitem label="item1" id="buttonmenu_item"/>
<menuitem label="item1"/>
</menupopup>
</button>
</window>

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

@ -0,0 +1,273 @@
<html>
<head>
<title>nsIAccessible::name calculation</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">
const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole;
var gAccRetrieval = null;
function testName(aID, aName)
{
var elm = document.getElementById(aID);
if (!elm) {
ok(false, "There is no element with ID " + aID);
return;
}
var acc = null;
try {
acc = gAccRetrieval.getAccessibleFor(elm);
} catch(e) {
}
if (!acc) {
ok(false, "There is no accessible for " + aID);
return;
}
is(acc.name, aName, "Wrong name of the accessible for " + aID);
}
function doTest()
{
gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
getService(nsIAccessibleRetrieval);
//////////////////////////////////////////////////////////////////////////
// aria-labelledby
// Single relation. The value of 'aria-labelledby' contains the ID of
// an element. Gets the name from text node of that element.
testName("btn_labelledby_text", "text");
// Multiple relations. The value of 'aria-labelledby' contains the IDs
// of elements. Gets the name from text nodes of those elements.
testName("btn_labelledby_texts", "text1 text2");
//////////////////////////////////////////////////////////////////////////
// Name from subtree (single relation labelled_by).
// Gets the name from text nodes contained by nested elements
testName("btn_labelledby_mixed", "nomore text");
// Gets the name from text nodes contained by nested elements, ignores
// hidden elements (bug 443081).
testName("btn_labelledby_mixed_hidden_child", "nomore text2");
// Gets the name from hidden text nodes contained by nested elements,
// (label element is hidden entirely), (bug 443081).
testName("btn_labelledby_mixed_hidden", "lala more hidden text");
// Gets the name from text nodes contained by nested elements having block
// representation (every text node value in the name should be devided by
// spaces)
testName("btn_labelledby_mixed_block", "text more text");
// Gets the name from text nodes contained by html:td (every text node
// value in the name should be devided by spaces).
// XXX: this case is rather a feature than strong wanted behaviour.
testName("btn_labelledby_mixed_table", "text space text");
// Gets the name from image accessible.
testName("btn_labelledby_mixed_img", "text image");
// Gets the name from input accessibles
// Note: if input have label elements then the name isn't calculated
// from them.
testName("btn_labelledby_mixed_input",
"input button Submit Query Reset input image");
// Gets the name from the title of object element.
testName("btn_labelledby_mixed_object", "object");
// Gets the name from text nodes. Element br adds space between them.
testName("btn_labelledby_mixed_br", "text text");
//////////////////////////////////////////////////////////////////////////
// label element
// The label element contains the button. The name is calculated from
// this button.
// Note: the name contains the content of the button.
testName("btn_label_inside", "text10text");
// The label element and the button are placed in the same form. Gets
// the name from the label subtree.
testName("btn_label_inform", "in form");
// The label element is placed outside of form where the button is.
// Do not take into account the label.
testName("btn_label_outform", "12");
// The label element and the button are in the same document. Gets the
// name from the label subtree.
testName("btn_label_indocument", "in document");
//////////////////////////////////////////////////////////////////////////
// name from children
// ARIA role button is presented allowing the name calculation from
// children.
testName("btn_children", "14");
// ARIA role option is presented allowing the name calculation from
// visible children (bug 443081).
testName("lb_opt1_children_hidden", "i am visible");
//////////////////////////////////////////////////////////////////////////
// title attribute
// If nothing is left. Let's try title attribute.
testName("btn_title", "title");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=444279"
title="mochitest for accessible name calculating">
Mozilla Bug 444279
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<!-- aria-labelledby, single relation -->
<span id="labelledby_text">text</span>
<button id="btn_labelledby_text"
aria-labelledby="labelledby_text">1</button>
<br/>
<!-- aria-labelledby, multiple relations -->
<span id="labelledby_text1">text1</span>
<span id="labelledby_text2">text2</span>
<button id="btn_labelledby_texts"
aria-labelledby="labelledby_text1 labelledby_text2">2</button>
<br/>
<!-- the name from subtree, mixed content -->
<span id="labelledby_mixed">no<span>more text</span></span>
<button id="btn_labelledby_mixed"
aria-labelledby="labelledby_mixed">3</button>
<br/>
<!-- the name from subtree, mixed/hidden content -->
<span id="labelledby_mixed_hidden_child">
no<span>more
<span style="display: none;">hidden</span>
text2
<span style="visibility: hidden">hidden2</span>
</span>
</span>
<button id="btn_labelledby_mixed_hidden_child"
aria-labelledby="labelledby_mixed_hidden_child">3.1</button>
<br/>
<!-- the name from subtree, mixed/completely hidden content -->
<span id="labelledby_mixed_hidden"
style="display: none;">lala <span>more hidden </span>text</span></span>
<button id="btn_labelledby_mixed_hidden"
aria-labelledby="labelledby_mixed_hidden">3.2</button>
<br/>
<!-- the name from subtree, mixed content, block structure -->
<div id="labelledby_mixed_block"><div>text</div>more text</div></div>
<button id="btn_labelledby_mixed_block"
aria-labelledby="labelledby_mixed_block">4</button>
<br/>
<!-- the name from subtree, mixed content, table structure -->
<table><tr>
<td id="labelledby_mixed_table">text<span>space</span>text</td>
</tr></table>
<button id="btn_labelledby_mixed_table"
aria-labelledby="labelledby_mixed_table">5</button>
<br/>
<!-- the name from subtree, child img -->
<span id="labelledby_mixed_img">text<img alt="image"/></span>
<button id="btn_labelledby_mixed_img"
aria-labelledby="labelledby_mixed_img">6</button>
<br/>
<!-- the name from subtree, child inputs -->
<span id="labelledby_mixed_input">
<input type="button" id="input_button" title="input button"/>
<input type="submit" id="input_submit"/>
<input type="reset" id="input_reset"/>
<input type="image" id="input_image" title="input image"/>
</span>
<button id="btn_labelledby_mixed_input"
aria-labelledby="labelledby_mixed_input">7</button>
<br/>
<!-- the name from subtree, child object -->
<span id="labelledby_mixed_object">
<object data="about:blank" title="object"></object>
</span>
<button id="btn_labelledby_mixed_object"
aria-labelledby="labelledby_mixed_object">8</button>
<br/>
<!-- the name from subtree, child br -->
<span id="labelledby_mixed_br">text<br/>text</span>
<button id="btn_labelledby_mixed_br"
aria-labelledby="labelledby_mixed_br">9</button>
<br/>
<!-- label element, label contains the button -->
<label>text<button id="btn_label_inside">10</button>text</label>
<br/>
<!-- label element, label and the button are in the same form -->
<form>
<label for="btn_label_inform">in form</label>
<button id="btn_label_inform">11</button>
</form>
<!-- label element, label is outside of the form of the button -->
<label for="btn_label_outform">out form</label>
<form>
<button id="btn_label_outform">12</button>
</form>
<!-- label element, label and the button are in the same document -->
<label for="btn_label_indocument">in document</label>
<button id="btn_label_indocument">13</button>
<!-- name from children -->
<span id="btn_children" role="button">14</span>
<!-- name from children, hidden children -->
<div role="listbox" tabindex="0">
<div id="lb_opt1_children_hidden" role="option" tabindex="0">
<span>i am visible</span>
<span style="display:none">i am hidden</span>
</div>
</div>
<!-- name from title attribute -->
<span id="btn_title" role="group" title="title">15</span>
</body>
</html>

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

@ -0,0 +1,318 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/a11y/accessible/nsIAccessible_name.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessibility Name Calculating Test.">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript">
<![CDATA[
const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole;
var gAccRetrieval = null;
function testName(aID, aName)
{
var elm = document.getElementById(aID);
if (!elm) {
ok(false, "There is no element with ID " + aID);
return null;
}
var acc = null;
try {
acc = gAccRetrieval.getAccessibleFor(elm);
} catch(e) {
}
if (!acc) {
ok(false, "There is no accessible for " + aID);
return null;
}
is(acc.name, aName, "Wrong name of the accessible for " + aID);
return acc;
}
function doTest()
{
gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
getService(nsIAccessibleRetrieval);
//////////////////////////////////////////////////////////////////////////
// aria-labelledby
// Single relation. The value of 'aria-labelledby' contains the ID of
// an element. Gets the name from text node of that element.
testName("btn_labelledby_text", "text");
// Multiple relations. The value of 'aria-labelledby' contains the IDs
// of elements. Gets the name from text nodes of those elements.
testName("btn_labelledby_texts", "text1 text2");
//////////////////////////////////////////////////////////////////////////
// Name from subtree (single relation labelled_by).
// Gets the name from text nodes contained by nested elements.
testName("btn_labelledby_mixed", "nomore text");
// Gets the name from text nodes and selected item of menulist
// (other items are ignored).
testName("btn_labelledby_mixed_menulist",
"nomore text selected item more text");
// Gets the name from text nodes contained by nested elements, ignores
// hidden elements (bug 443081).
testName("btn_labelledby_mixed_hidden_child", "nomore text2");
// Gets the name from hidden text nodes contained by nested elements,
// (label element is hidden entirely), (bug 443081)
testName("btn_labelledby_mixed_hidden", "lala more hidden text");
//////////////////////////////////////////////////////////////////////////
// Name for nsIDOMXULLabeledControlElement.
// Gets the name from @label attribute.
testName("btn_nsIDOMXULLabeledControlElement", "labeled element");
//////////////////////////////////////////////////////////////////////////
// Name for nsIDOMXULSelectControlItemElement.
// Gets the name from @label attribute.
testName("li_nsIDOMXULSelectControlItemElement", "select control item");
//////////////////////////////////////////////////////////////////////////
// Name if the XUL element doesn't implement nsIDOMXULSelectControlElement
// and has @label attribute.
testName("box_not_nsIDOMXULSelectControlElement", "box");
//////////////////////////////////////////////////////////////////////////
// Name from the label element.
// The label and button are placed on 2nd level relative common parent.
testName("btn_label_1", "label1");
// The label is on 1st, the button is on 5th level relative common parent.
testName("btn_label_2", "label2");
// The label and button are siblings.
testName("btn_label_3", "label3");
//////////////////////////////////////////////////////////////////////////
// Name from the label element in anonymous content (see bug 362365).
// Get the name from anonymous label element for anonymous textbox
// (@anonid is used).
var ID = "box_label_anon1";
var box1Acc = testName(ID, "");
if (box1Acc) {
var textboxAcc = box1Acc.firstChild;
is(textboxAcc.name, "Label",
"Wrong label for anonymous textbox of " + ID);
}
// Get the name from anonymous label element for anonymous textbox
// (@anonid is used). Nested bindings.
ID = "box_label_anon2";
var box2Acc = testName(ID, "");
if (box2Acc) {
var textboxAcc = box2Acc.firstChild;
is(textboxAcc.name, "Label",
"Wrong label for anonymous textbox of " + ID);
var topTextboxAcc = box2Acc.lastChild;
is(topTextboxAcc.name, "Top textbox",
"Wrong label for anonymous textbox of " + ID);
}
//////////////////////////////////////////////////////////////////////////
// tooltiptext (if nothing above isn't presented then tooltiptext is used)
testName("box_tooltiptext", "tooltiptext label");
//////////////////////////////////////////////////////////////////////////
// Name from the @title attribute of <toolbaritem/> (original bug 237249).
// Direct child of toolbaritem.
var textboxAcc = testName("toolbaritem_textbox", "ooospspss");
// Element from anonymous content of direct child of toolbaritem.
var dropmarkerAcc = textboxAcc.lastChild;
is(dropmarkerAcc.finalRole, nsIAccessibleRole.ROLE_PUSHBUTTON,
"The last child of autocomplete textbox 'toolbaritem_textbox' should be dropmarker.");
is(dropmarkerAcc.name, "ooospspss",
"Wrong name for dropmarker of autocomplete textbox 'toolbaritem_textbox'.");
// Child from subtree of toolbaritem.
testName("toolbaritem_hboxbutton", "ooospspss");
//////////////////////////////////////////////////////////////////////////
// Name from children
// ARIA role button is presented allowing the name calculation from
// children.
testName("box_children", "14");
// ARIA role option is presented allowing the name calculation from
// the visible children (bug 443081)
testName("lb_opt1_children_hidden", "i am visible");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doTest);
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=444279"
title="mochitest for accessible name calculating">
Mozilla Bug 444279
</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<!-- aria-labelledby, single relation -->
<description id="labelledby_text">text</description>
<button id="btn_labelledby_text"
aria-labelledby="labelledby_text"/>
<!-- aria-labelledby, multiple relations -->
<description id="labelledby_text1">text1</description>
<description id="labelledby_text2">text2</description>
<button id="btn_labelledby_texts"
aria-labelledby="labelledby_text1 labelledby_text2"/>
<!-- the name from subtree, mixed content -->
<description id="labelledby_mixed">
no<description>more text</description>
</description>
<button id="btn_labelledby_mixed"
aria-labelledby="labelledby_mixed"/>
<!-- the name from subtree, mixed/hidden content -->
<description id="labelledby_mixed_hidden_child">no<description>more <description hidden="true">hidden</description>text2</description></description>
<button id="btn_labelledby_mixed_hidden_child"
aria-labelledby="labelledby_mixed_hidden_child"/>
<!-- the name from subtree, mixed/completely hidden content -->
<description id="labelledby_mixed_hidden"
hidden="true">lala <description>more hidden </description>text</description>
<button id="btn_labelledby_mixed_hidden"
aria-labelledby="labelledby_mixed_hidden"/>
<br/>
<!-- the name from subtree, mixed content, ignore items of menulist -->
<description id="labelledby_mixed_menulist">
no<description>more text</description>
<menulist>
<menupopup>
<menuitem label="selected item"/>
<menuitem label="item"/>
</menupopup>
</menulist>
more text
</description>
<button id="btn_labelledby_mixed_menulist"
aria-labelledby="labelledby_mixed_menulist"/>
<!-- nsIDOMXULLabeledControlElement -->
<button id="btn_nsIDOMXULLabeledControlElement"
label="labeled element"/>
<!-- nsIDOMXULSelectControlItemElement -->
<listbox>
<listitem id="li_nsIDOMXULSelectControlItemElement"
label="select control item"/>
</listbox>
<!-- not nsIDOMXULSelectControlElement -->
<box id="box_not_nsIDOMXULSelectControlElement" role="group" label="box"/>
<!-- label element -->
<hbox>
<box>
<label control="btn_label_1">label1</label>
</box>
<label control="btn_label_2">label2</label>
<box>
<button id="btn_label_1"/>
<box>
<box>
<box>
<button id="btn_label_2"/>
</box>
</box>
</box>
</box>
<label control="btn_label_3">label3</label>
<button id="btn_label_3"/>
</hbox>
<!-- label element, anonymous content -->
<box id="box_label_anon1"
class="first"
role="group"/>
<box id="box_label_anon2"
class="second"
role="group"/>
<!-- tooltiptext -->
<box id="box_tooltiptext"
role="group"
tooltiptext="tooltiptext label"/>
<!-- the name from @title of toolbaritem -->
<toolbar>
<toolbaritem title="ooospspss">
<textbox id="toolbaritem_textbox"
flex="1"
type="autocomplete"
enablehistory="true">
<hbox role="button" id="toolbaritem_hboxbutton">
<description value="button"/>
</hbox>
</textbox>
</toolbaritem>
</toolbar>
<!-- name from children -->
<box id="box_children" role="button">14</box>
<!-- name from children, hidden children -->
<vbox role="listbox" tabindex="0">
<hbox id="lb_opt1_children_hidden" role="option" tabindex="0">
<description>i am visible</description>
<description style="display:none">i am hidden</description>
</hbox>
</vbox>
</window>

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

@ -0,0 +1,476 @@
<html>
<head>
<title>Text attributes 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">
const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
const nsIAccessibleText = Components.interfaces.nsIAccessibleText;
const nsIAccessibleEvent = Components.interfaces.nsIAccessibleEvent;
const nsIDOMNSEditableElement =
Components.interfaces.nsIDOMNSEditableElement;
const nsIObserverService = Components.interfaces.nsIObserverService;
var gAccRetrieval = null;
/**
* Test text attributes.
*
* @param aID the ID of DOM element having text accessible
* @param aOffset the offset inside text accessible to fetch
* text attributes
* @param aAttrs the map of text attributes (name/value pairs)
* @param aStartOffset the start offset where text attributes are
* applied
* @param aEndOffset the end offset where text attribute are applied
* @param aDefAttrs the list of default text attributes (name/value
* pairs)
*/
function testTextAttrs(aID, aOffset,
aAttrs, aStartOffset, aEndOffset, aDefAttrs)
{
var node = document.getElementById(aID);
if (!node) {
ok(false, "Can't get the element with ID " + aID);
return;
}
var accessible = null;
try {
accessible = gAccRetrieval.getAccessibleFor(node);
accessible.QueryInterface(nsIAccessibleText);
} catch (e) {
}
if (!accessible) {
ok(false, "Can't query nsIAccessibleText interface for " + aID);
return;
}
var startOffset = { value: -1 };
var endOffset = { value: -1 };
var attrs = null;
try {
attrs = accessible.getTextAttributes(false,
aOffset,
startOffset, endOffset);
} catch (e) {
}
if (!attrs) {
ok(false, "Can't get text attributes for " + aID);
return;
}
var errorMsg = " for " + aID + "at offset " + aOffset;
is(startOffset.value, aStartOffset,
"Wrong start offset" + errorMsg);
is(endOffset.value, aEndOffset,
"Wrong end offset" + errorMsg);
compareTextAttrs(errorMsg, attrs, aAttrs);
var defAttrs = null;
try{
defAttrs = accessible.defaultTextAttributes;
} catch (e) {
}
if (!defAttrs) {
ok(false, "Can't get default attributes for " + aID);
return;
}
compareTextAttrs(errorMsg, defAttrs, aDefAttrs);
}
function compareTextAttrs(aErrorMsg, aAttrs, aExpectedAttrs)
{
var enumerate = aAttrs.enumerate();
while (enumerate.hasMoreElements()) {
var prop = enumerate.getNext().
QueryInterface(Components.interfaces.nsIPropertyElement);
if (!(prop.key in aExpectedAttrs))
ok(false,
"Unexpected attribute '" + prop.key + "'" + aErrorMsg);
else
is(prop.value, aExpectedAttrs[prop.key],
"Attribute '" + prop.key + "' has wrong value" + aErrorMsg);
}
for (var name in aExpectedAttrs) {
var value = "";
try {
value = aAttrs.getStringProperty(name);
} catch(e) {
}
if (!value)
ok(false,
"There is no expected attribute '" + name + "'" + aErrorMsg);
}
}
var gObserverService = null;
var gA11yEventObserver = null;
function testSpellTextAttrs()
{
gA11yEventObserver = {
observe: function observe(aSubject, aTopic, aData)
{
if (aTopic != "accessible-event")
return;
var event = aSubject.QueryInterface(nsIAccessibleEvent);
if (event.eventType == nsIAccessibleEvent.EVENT_TEXT_ATTRIBUTE_CHANGED)
this.mTextAttrChangedEventCounter++;
},
mTextAttrChangedEventCounter: 0
};
// Add accessibility event listeners
var gObserverService = Components.classes["@mozilla.org/observer-service;1"].
getService(nsIObserverService);
gObserverService.addObserver(gA11yEventObserver, "accessible-event",
false);
ID = "area8";
var node = document.getElementById(ID);
node.focus();
var editor = node.QueryInterface(nsIDOMNSEditableElement).editor;
var spellchecker = editor.getInlineSpellChecker(true);
spellchecker.enableRealTimeSpell = true;
window.setTimeout(function()
{
var defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "11px",
"background-color": "rgb(255, 255, 255)",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "Lucida Grande",
"text-position": "baseline"
};
var attrs = { "background-color": "transparent" };
var misspelledAttrs = {
"background-color": "transparent",
"invalid": "spelling"
};
testTextAttrs(ID, 0, attrs, 0, 11, defAttrs);
testTextAttrs(ID, 11, misspelledAttrs, 11, 17, defAttrs);
testTextAttrs(ID, 18, misspelledAttrs, 18, 22, defAttrs);
is(gA11yEventObserver.mTextAttrChangedEventCounter, 2,
"Wrong count of 'text attribute changed' events for " + ID);
// Remove a11y events listener
gObserverService.removeObserver(gA11yEventObserver,
"accessible-event");
SimpleTest.finish();
}, 0);
}
function doTest()
{
gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
getService(nsIAccessibleRetrieval);
//////////////////////////////////////////////////////////////////////////
// area1
var ID = "area1";
var defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
"background-color": "transparent",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
};
var attrs = {};
testTextAttrs(ID, 0, attrs, 0, 7, defAttrs);
attrs = {"font-weight": "401"};
testTextAttrs(ID, 7, attrs, 7, 11, defAttrs);
attrs = {};
testTextAttrs(ID, 12, attrs, 11, 18, defAttrs);
//////////////////////////////////////////////////////////////////////////
// area2
ID = "area2";
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
"background-color": "transparent",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
};
attrs = {};
testTextAttrs(ID, 0, attrs, 0, 7, defAttrs);
attrs = {"font-weight": "401"};
testTextAttrs(ID, 7, attrs, 7, 12, defAttrs);
attrs = {"font-style": "italic", "font-weight": "401"};
testTextAttrs(ID, 13, attrs, 12, 19, defAttrs);
attrs = {"font-weight": "401"};
testTextAttrs(ID, 20, attrs, 19, 23, defAttrs);
attrs = {};
testTextAttrs(ID, 24, attrs, 23, 30, defAttrs);
//////////////////////////////////////////////////////////////////////////
// area3
ID = "area3";
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
"background-color": "transparent",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
};
attrs = {"color": "rgb(0, 128, 0)"};
testTextAttrs(ID, 0, attrs, 0, 6, defAttrs);
attrs = {"color": "rgb(255, 0, 0)"};
testTextAttrs(ID, 6, attrs, 6, 26, defAttrs);
attrs = {"color": "rgb(0, 128, 0)"};
testTextAttrs(ID, 26, attrs, 26, 50, defAttrs);
//////////////////////////////////////////////////////////////////////////
// area4
ID = "area4";
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
"background-color": "transparent",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
};
attrs = {"color": "rgb(0, 128, 0)"};
testTextAttrs(ID, 0, attrs, 0, 16, defAttrs);
attrs = {"color": "rgb(255, 0, 0)"};
testTextAttrs(ID, 16, attrs, 16, 33, defAttrs);
attrs = {"color": "rgb(0, 128, 0)"};
testTextAttrs(ID, 34, attrs, 33, 46, defAttrs);
//////////////////////////////////////////////////////////////////////////
// area5
ID = "area5";
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
"background-color": "transparent",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
};
attrs = {"color": "rgb(0, 128, 0)"};
testTextAttrs(ID, 0, attrs, 0, 5, defAttrs);
attrs = {};
testTextAttrs(ID, 7, attrs, 5, 8, defAttrs);
attrs = {"color": "rgb(255, 0, 0)"};
testTextAttrs(ID, 9, attrs, 8, 11, defAttrs);
attrs = {};
testTextAttrs(ID, 11, attrs, 11, 18, defAttrs);
//////////////////////////////////////////////////////////////////////////
// area6 (CSS vertical-align property, bug 445938)
ID = "area6";
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
"background-color": "transparent",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
};
attrs = {};
testTextAttrs(ID, 0, attrs, 0, 5, defAttrs);
attrs = {"text-position": "super", "font-size": "13px" };
testTextAttrs(ID, 5, attrs, 5, 13, defAttrs);
attrs = {};
testTextAttrs(ID, 13, attrs, 13, 27, defAttrs);
attrs = {"text-position": "super" };
testTextAttrs(ID, 27, attrs, 27, 35, defAttrs);
attrs = {};
testTextAttrs(ID, 35, attrs, 35, 39, defAttrs);
attrs = {"text-position": "sub", "font-size": "13px" };
testTextAttrs(ID, 39, attrs, 39, 50, defAttrs);
attrs = {};
testTextAttrs(ID, 50, attrs, 50, 55, defAttrs);
attrs = {"text-position": "sub" };
testTextAttrs(ID, 55, attrs, 55, 64, defAttrs);
//////////////////////////////////////////////////////////////////////////
// area7
ID = "area7";
defAttrs = {
"font-style": "normal",
"text-align": "start",
"font-size": "16px",
"background-color": "transparent",
"font-weight": "400",
"text-indent": "0px",
"color": "rgb(0, 0, 0)",
"font-family": "serif",
"text-position": "baseline"
};
attrs = {"language": "ru"};
testTextAttrs(ID, 0, attrs, 0, 12, defAttrs);
attrs = {"language": "en"};
testTextAttrs(ID, 12, attrs, 12, 13, defAttrs);
attrs = {"language" :"en", "background-color": "rgb(0, 0, 255)"};
testTextAttrs(ID, 13, attrs, 13, 26, defAttrs);
attrs = {"language": "en" };
testTextAttrs(ID, 26, attrs, 26, 27, defAttrs);
attrs = {"language": "de"};
testTextAttrs(ID, 27, attrs, 27, 42, defAttrs);
attrs = {"language": "en"};
testTextAttrs(ID, 42, attrs, 42, 43, defAttrs);
attrs = {};
testTextAttrs(ID, 43, attrs, 43, 50, defAttrs);
attrs = {"color": "rgb(255, 0, 255)"};
testTextAttrs(ID, 50, attrs, 50, 57, defAttrs);
attrs = {"font-weight": "401", "color": "rgb(255, 0, 255)" };
testTextAttrs(ID, 57, attrs, 57, 61, defAttrs);
attrs = {"color": "rgb(255, 0, 255)"};
testTextAttrs(ID, 61, attrs, 61, 68, defAttrs);
//////////////////////////////////////////////////////////////////////////
// test spelling text attributes
testSpellTextAttrs(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=345759"
title="Implement text attributes">
Mozilla Bug 345759
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<p id="area1">Normal <b>Bold</b> Normal</p>
<p id="area2">Normal <b>Bold <i>Italic </i>Bold</b> Normal</p>
<p id="area3">
<span style="color: green">
Green
<span style="color: red">but children are red</span>
</span><span style="color: green">
Another green section.
</span>
</p>
<p id="area4">
<span style="color: green">
Green
</span><span style="color: green">
Green too
<span style="color: red">with red children</span>
Green again
</span>
</p>
<p id="area5">
<span style="color: green">Green</span>
<img src="moz.png" alt="image"/>
<span style="color: red">Red</span>Normal
</p>
<p id="area6">
This <sup>sentence</sup> has the word
<span style="vertical-align:super;">sentence</span> in
<sub>superscript</sub> and
<span style="vertical-align:sub;">subscript</span>
</p>
<p lang="en" id="area7">
<span lang="ru">Привет</span>
<span style="background-color: blue">Blue BG color</span>
<span lang="de">Ich bin/Du bist</span>
<span lang="en">
Normal
<span style="color: magenta">Magenta<b>Bold</b>Magenta</span>
</span>
</p>
<input id="area8" value="valid text inalid tixt"/>
<p id="output"/>
</body>
</html>

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

@ -1,7 +1,7 @@
WIN32_MODULE_COMPANYNAME=Mozilla Corporation
WIN32_MODULE_COPYRIGHT=©Firefox and Mozilla Developers, according to the MPL 1.1/GPL 2.0/LGPL 2.1 licenses, as applicable.
WIN32_MODULE_PRODUCTVERSION=3,1,0,0
WIN32_MODULE_PRODUCTVERSION_STRING=3.1a1pre
WIN32_MODULE_PRODUCTVERSION_STRING=3.1a2pre
WIN32_MODULE_TRADEMARKS=Firefox is a Trademark of The Mozilla Foundation.
WIN32_MODULE_DESCRIPTION=Firefox
WIN32_MODULE_PRODUCTNAME=Firefox

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

@ -227,6 +227,15 @@ pref("browser.urlbar.maxRichResults", 12);
pref("browser.urlbar.search.chunkSize", 1000);
pref("browser.urlbar.search.timeout", 100);
// The special characters below can be typed into the urlbar to either restrict
// the search to visited history, bookmarked, tagged pages; or force a match on
// just the title text or url.
pref("browser.urlbar.restrict.history", "^");
pref("browser.urlbar.restrict.bookmark", "*");
pref("browser.urlbar.restrict.tag", "+");
pref("browser.urlbar.match.title", "#");
pref("browser.urlbar.match.url", "@");
// Number of milliseconds to wait for the http headers (and thus
// the Content-Disposition filename) before giving up and falling back to
// picking a filename without that info in hand so that the user sees some
@ -327,6 +336,9 @@ pref("browser.tabs.closeButtons", 1);
// false return to the adjacent tab (old default)
pref("browser.tabs.selectOwnerOnClose", true);
pref("browser.ctrlTab.mostRecentlyUsed", true);
pref("browser.ctrlTab.smoothScroll", true);
// Default bookmark sorting
pref("browser.bookmarks.sort.direction", "descending");
pref("browser.bookmarks.sort.resource", "rdf:http://home.netscape.com/NC-rdf#Name");

Двоичные данные
browser/base/content/aboutRobots-icon-rtl.png Normal file

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

После

Ширина:  |  Высота:  |  Размер: 7.7 KiB

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

@ -29,6 +29,7 @@
# Jeff Walden <jwalden+code@mit.edu>
# Johnathan Nightingale <johnath@mozilla.com>
# Justin Dolske <dolske@mozilla.com>
# Ehsan Akhgari <ehsan.akhgari@gmail.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
@ -80,13 +81,32 @@
}
}
]]></script>
<style type="text/css"><![CDATA[
#errorPageContainer {
background: url('chrome://browser/content/aboutRobots-icon.png') left 0 no-repeat -moz-Field;
-moz-background-origin: content;
}
#errorTrailerDescText {
float: right;
}
body[dir=rtl] #errorPageContainer {
background-image: url('chrome://browser/content/aboutRobots-icon-rtl.png');
background-position: right 0;
}
body[dir=rtl] #errorTrailerDescText {
float: left;
}
]]></style>
</head>
<body dir="&locale.dir;">
<!-- PAGE CONTAINER (for styling purposes only) -->
<div id="errorPageContainer"
style="background: url('chrome://browser/content/aboutRobots-icon.png') left 0 no-repeat -moz-Field; -moz-background-origin: content;">
<div id="errorPageContainer">
<!-- Error Title -->
<div id="errorTitle">
@ -113,7 +133,7 @@
<!-- Short Description -->
<div id="errorTrailerDesc">
<p id="errorTrailerDescText" style="float: right;">&robots.errorTrailerDescText;</p>
<p id="errorTrailerDescText">&robots.errorTrailerDescText;</p>
</div>
</div>

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

@ -179,7 +179,6 @@
accesskey="&keywordfield.accesskey;"
oncommand="AddKeywordForSearchField();"/>
<menuitem id="context-searchselect"
accesskey="&search.accesskey;"
oncommand="BrowserSearch.loadSearch(getBrowserSelection(), true);"/>
<menuseparator id="frame-sep"/>
<menu id="frame" label="&thisFrameMenu.label;" accesskey="&thisFrameMenu.accesskey;">

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

@ -22,7 +22,6 @@
# Annie Sullivan <annie.sullivan@gmail.com>
# Joe Hughes <joe@retrovirus.com>
# Asaf Romano <mano@mozilla.com>
# Ehsan Akhgari <ehsan.akhgari@gmail.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or

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

@ -0,0 +1,559 @@
/*
#ifdef 0
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Tab Previews.
*
* The Initial Developer of the Original Code is Mozilla.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dão Gottwald <dao@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK *****
#endif
*/
/**
* Tab previews utility, produces thumbnails
*/
var tabPreviews = {
aspectRatio: 0.6875, // 16:11
init: function () {
this.width = Math.ceil(screen.availWidth / 7.5);
this.height = Math.round(this.width * this.aspectRatio);
gBrowser.tabContainer.addEventListener("TabSelect", this, false);
gBrowser.tabContainer.addEventListener("SSTabRestored", this, false);
},
uninit: function () {
gBrowser.tabContainer.removeEventListener("TabSelect", this, false);
gBrowser.tabContainer.removeEventListener("SSTabRestored", this, false);
this._selectedTab = null;
},
get: function (aTab) {
return aTab.__thumbnail || this.capture(aTab, !aTab.hasAttribute("busy"));
},
capture: function (aTab, aStore) {
var win = aTab.linkedBrowser.contentWindow;
var thumbnail = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
thumbnail.mozOpaque = true;
thumbnail.height = this.height;
thumbnail.width = this.width;
var ctx = thumbnail.getContext("2d");
var widthScale = this.width / win.innerWidth;
ctx.scale(widthScale, widthScale);
ctx.drawWindow(win, win.scrollX, win.scrollY,
win.innerWidth, win.innerWidth * this.aspectRatio, "rgb(255,255,255)");
var data = thumbnail.toDataURL("image/jpeg", "quality=60");
if (aStore)
aTab.__thumbnail = data;
return data;
},
handleEvent: function (event) {
switch (event.type) {
case "TabSelect":
if (this._selectedTab &&
this._selectedTab.parentNode &&
!this._pendingUpdate) {
// Generate a thumbnail for the tab that was selected.
// The timeout keeps the UI snappy and prevents us from generating thumbnails
// for tabs that will be closed. During that timeout, don't generate other
// thumbnails in case multiple TabSelect events occur fast in succession.
this._pendingUpdate = true;
setTimeout(function (self, aTab) {
self._pendingUpdate = false;
if (aTab.parentNode && !aTab.hasAttribute("busy"))
self.capture(aTab, true);
}, 2000, this, this._selectedTab);
}
this._selectedTab = event.target;
break;
case "SSTabRestored":
this.capture(event.target, true);
break;
}
}
};
/**
* Ctrl-Tab panel
*/
var ctrlTab = {
tabs: null,
visibleCount: 3,
_uniqid: 0,
get panel () {
delete this.panel;
return this.panel = document.getElementById("ctrlTab-panel");
},
get label () {
delete this.label;
return this.label = document.getElementById("ctrlTab-label");
},
get svgRoot () {
delete this.svgRoot;
let (groundFade = document.getElementById("ctrlTab-groundFade")) {
groundFade.setAttribute("height", Math.ceil(tabPreviews.height * .25) + 1);
groundFade.setAttribute("y", tabPreviews.height + 1);
}
this.svgRoot = document.getElementById("ctrlTab-svgRoot");
this.svgRoot.setAttribute("height", tabPreviews.height * 1.25 + 2);
return this.svgRoot;
},
get container () {
delete this.container;
return this.container = document.getElementById("ctrlTab-container");
},
get rtl () {
delete this.rtl;
return this.rtl = getComputedStyle(this.panel, "").direction == "rtl";
},
get iconSize () {
delete this.iconSize;
return this.iconSize = Math.round(tabPreviews.height / 4);
},
get closeCharCode () {
delete this.closeCharCode;
return this.closeCharCode = document.getElementById("key_close")
.getAttribute("key")
.toLowerCase().charCodeAt(0);
},
get smoothScroll () {
delete this.smoothScroll;
return this.smoothScroll = gPrefService.getBoolPref("browser.ctrlTab.smoothScroll");
},
get offscreenStart () {
return Array.indexOf(this.container.childNodes, this.selected) - 1;
},
get offscreenEnd () {
return this.container.childNodes.length - this.visibleCount - this.offscreenStart;
},
get offsetX () {
return - tabPreviews.width * (this.rtl ? this.offscreenEnd : this.offscreenStart);
},
get isOpen () {
return this.panel.state == "open" || this.panel.state == "showing";
},
init: function () {
if (this.tabs)
return;
var tabContainer = gBrowser.tabContainer;
this.tabs = [];
Array.forEach(tabContainer.childNodes, function (tab) {
this.attachTab(tab, tab == gBrowser.selectedTab);
}, this);
tabContainer.addEventListener("TabOpen", this, false);
tabContainer.addEventListener("TabSelect", this, false);
tabContainer.addEventListener("TabClose", this, false);
gBrowser.mTabBox.handleCtrlTab = false;
window.addEventListener("keydown", this, true);
},
uninit: function () {
this.tabs = null;
var tabContainer = gBrowser.tabContainer;
tabContainer.removeEventListener("TabOpen", this, false);
tabContainer.removeEventListener("TabSelect", this, false);
tabContainer.removeEventListener("TabClose", this, false);
this.panel.removeEventListener("popuphiding", this, false);
window.removeEventListener("keydown", this, true);
},
addBox: function (aAtStart) {
const SVGNS = "http://www.w3.org/2000/svg";
var thumbnail = document.createElementNS(SVGNS, "image");
thumbnail.setAttribute("class", "ctrlTab-thumbnail");
thumbnail.setAttribute("height", tabPreviews.height);
thumbnail.setAttribute("width", tabPreviews.width);
var thumbnail_border = document.createElementNS(SVGNS, "rect");
thumbnail_border.setAttribute("class", "ctrlTab-thumbnailborder");
thumbnail_border.setAttribute("height", tabPreviews.height);
thumbnail_border.setAttribute("width", tabPreviews.width);
var icon = document.createElementNS(SVGNS, "image");
icon.setAttribute("class", "ctrlTab-icon");
icon.setAttribute("height", this.iconSize);
icon.setAttribute("width", this.iconSize);
icon.setAttribute("transform", "skewY(10)");
icon.setAttribute("x", - this.iconSize / 3);
icon.setAttribute("y", tabPreviews.height * .9 - this.iconSize);
var thumbnail_and_icon = document.createElementNS(SVGNS, "g");
thumbnail_and_icon.appendChild(thumbnail);
thumbnail_and_icon.appendChild(thumbnail_border);
thumbnail_and_icon.appendChild(icon);
var reflection = document.createElementNS(SVGNS, "use");
reflection.setAttribute("class", "ctrlTab-reflection");
var ref_scale = .5;
reflection.setAttribute("transform", "scale(1,-" + ref_scale + ")");
reflection.setAttribute("y", - ((1 / ref_scale + 1) * tabPreviews.height +
(1 / ref_scale) * 2));
var box = document.createElementNS(SVGNS, "g");
box.setAttribute("class", "ctrlTab-box");
box.appendChild(thumbnail_and_icon);
box.appendChild(reflection);
if (aAtStart)
this.container.insertBefore(box, this.container.firstChild);
else
this.container.appendChild(box);
return box;
},
removeBox: function (aBox) {
this.container.removeChild(aBox);
if (!Array.some(this.container.childNodes, function (box) box._tab == aBox._tab))
aBox._tab.removeEventListener("DOMAttrModified", this, false);
aBox._tab = null;
},
addPreview: function (aBox, aTab) {
const XLinkNS = "http://www.w3.org/1999/xlink";
aBox._tab = aTab;
let (thumbnail = aBox.firstChild.firstChild)
thumbnail.setAttributeNS(XLinkNS, "href", tabPreviews.get(aTab));
this.updateIcon(aBox);
aTab.addEventListener("DOMAttrModified", this, false);
if (!aBox.firstChild.hasAttribute("id")) {
// set up reflection
this._uniqid++;
aBox.firstChild.setAttribute("id", "ctrlTab-preview-" + this._uniqid);
aBox.lastChild.setAttributeNS(XLinkNS, "href", "#ctrlTab-preview-" + this._uniqid);
}
},
updateIcon: function (aBox) {
const XLinkNS = "http://www.w3.org/1999/xlink";
var url = aBox._tab.hasAttribute("busy") ?
"chrome://global/skin/icons/loading_16.png" :
aBox._tab.getAttribute("image");
var icon = aBox.firstChild.lastChild;
if (url)
icon.setAttributeNS(XLinkNS, "href", url);
else
icon.removeAttributeNS(XLinkNS, "href");
},
tabAttrModified: function (aTab, aAttrName) {
switch (aAttrName) {
case "busy":
case "image":
Array.forEach(this.container.childNodes, function (box) {
if (box._tab == aTab) {
if (aAttrName == "busy")
this.addPreview(box, aTab);
else
this.updateIcon(box);
}
}, this);
break;
case "label":
case "crop":
if (!this._scrollTimer) {
let boxes = this.container.childNodes;
for (let i = boxes.length - 1; i >= 0; i--) {
if (boxes[i]._tab == aTab && boxes[i] == this.selected) {
this.label[aAttrName == "label" ? "value" : aAttrName] =
aTab.getAttribute(aAttrName);
break;
}
}
}
break;
}
},
scroll: function () {
if (!this.smoothScroll) {
this.advanceSelected();
this.arrangeBoxes();
return;
}
this.stopScroll();
let (next = this.invertDirection ? this.selected.previousSibling : this.selected.nextSibling) {
this.setStatusbarValue(next);
this.label.value = next._tab.label;
this.label.crop = next._tab.crop;
}
const FRAME_LENGTH = 40;
var x = this.offsetX;
var scrollAmounts = let (tenth = tabPreviews.width / (this.invertDirection == this.rtl ? -10 : 10))
[3 * tenth, 4 * tenth, 2 * tenth, tenth];
function processFrame(self, lateness) {
lateness += FRAME_LENGTH / 2;
do {
x += scrollAmounts.shift();
lateness -= FRAME_LENGTH;
} while (lateness > 0 && scrollAmounts.length);
self.container.setAttribute("transform", "translate("+ x +",0)");
self.svgRoot.forceRedraw();
if (!scrollAmounts.length)
self.stopScroll();
}
this._scrollTimer = setInterval(processFrame, FRAME_LENGTH, this);
processFrame(this, 0);
},
stopScroll: function () {
if (this._scrollTimer) {
clearInterval(this._scrollTimer);
this._scrollTimer = 0;
this.advanceSelected();
this.arrangeBoxes();
}
},
advanceSelected: function () {
// regardless of visibleCount, the new highlighted tab will be
// the first or third-visible tab, depending on whether Shift is pressed
var index = ((this.invertDirection ? 0 : 2) + this.offscreenStart + this.tabs.length)
% this.tabs.length;
if (index < 2)
index += this.tabs.length;
if (index > this.container.childNodes.length - this.visibleCount + 1)
index -= this.tabs.length;
this.selected = this.container.childNodes[index];
},
arrangeBoxes: function () {
this.addOffscreenBox(this.invertDirection);
this.addOffscreenBox(!this.invertDirection);
// having lots of off-screen boxes reduce the scrolling speed, remove some
for (let i = this.offscreenStart; i > 1; i--)
this.removeBox(this.container.firstChild);
for (let i = this.offscreenEnd; i > 1; i--)
this.removeBox(this.container.lastChild);
this.container.setAttribute("transform", "translate("+ this.offsetX +", 0)");
for (let i = 0, l = this.container.childNodes.length; i < l; i++)
this.arrange(i);
},
addOffscreenBox: function (aAtStart) {
if (this.container.childNodes.length < this.tabs.length + this.visibleCount + 1 &&
!(aAtStart ? this.offscreenStart : this.offscreenEnd)) {
let i = aAtStart ?
this.tabs.indexOf(this.container.firstChild._tab) - 1:
this.tabs.indexOf(this.container.lastChild._tab) + 1;
i = (i + this.tabs.length) % this.tabs.length;
this.addPreview(this.addBox(aAtStart), this.tabs[i]);
}
},
arrange: function (aIndex) {
var box = this.container.childNodes[aIndex];
var selected = box == this.selected;
if (selected) {
box.setAttribute("selected", "true");
this.setStatusbarValue(box);
this.label.value = box._tab.label;
this.label.crop = box._tab.crop;
} else {
box.removeAttribute("selected");
}
var scale = selected ? 1 : .75;
var pos = this.rtl ? this.container.childNodes.length - 1 - aIndex : aIndex;
var trans_x = tabPreviews.width * (pos + (1 - scale) / 2) / scale;
var trans_y = (tabPreviews.height + 1) * (1 / scale - 1);
box.setAttribute("transform", "scale(" + scale + "," + scale + ") " +
"translate("+ trans_x + "," + trans_y + ")");
},
setStatusbarValue: function (aBox) {
var value = "";
if (aBox) {
value = aBox._tab.linkedBrowser.currentURI.spec;
if (value == "about:blank") {
// XXXhack: Passing a space here (and not "")
// to make sure the browser implementation would
// still consider it a hovered link.
value = " ";
} else {
try {
value = decodeURI(value);
} catch (e) {}
}
}
XULBrowserWindow.setOverLink(value, null);
},
attachTab: function (aTab, aSelected) {
if (aSelected)
this.tabs.unshift(aTab);
else
this.tabs.push(aTab);
},
detachTab: function (aTab) {
var i = this.tabs.indexOf(aTab);
if (i >= 0)
this.tabs.splice(i, 1);
},
open: function () {
this._deferOnTabSelect = [];
window.addEventListener("keyup", this, true);
window.addEventListener("keypress", this, true);
this.panel.addEventListener("popuphiding", this, false);
this.panel.hidden = false;
this.panel.width = tabPreviews.width * this.visibleCount;
this.panel.openPopupAtScreen(screen.availLeft + (screen.availWidth - this.panel.width) / 2,
screen.availTop + (screen.availHeight - this.svgRoot.getAttribute("height")) / 2,
false);
// display $visibleCount tabs, starting with the first or
// the second to the last tab, depending on whether Shift is pressed
for (let index = this.invertDirection ? this.tabs.length - 2 : 0,
i = this.visibleCount; i > 0; i--)
this.addPreview(this.addBox(), this.tabs[index++ % this.tabs.length]);
// regardless of visibleCount, highlight the second-visible tab
this.selected = this.container.childNodes[1];
this.arrangeBoxes();
},
onKeyDown: function (event) {
var isOpen = this.isOpen;
var propagate = !isOpen;
switch (event.keyCode) {
case event.DOM_VK_TAB:
if (event.ctrlKey && !event.altKey && !event.metaKey && this.tabs.length > 1) {
propagate = false;
this.invertDirection = event.shiftKey;
if (isOpen)
this.scroll();
else if (this.tabs.length == 2)
gBrowser.selectedTab = this.tabs[1];
else
this.open();
}
break;
case event.DOM_VK_ESCAPE:
if (isOpen)
this.panel.hidePopup();
break;
}
if (!propagate) {
event.stopPropagation();
event.preventDefault();
}
},
onKeyUp: function (event) {
if (event.keyCode == event.DOM_VK_CONTROL) {
this.stopScroll();
let selectedTab = this.selected._tab;
this.panel.hidePopup();
gBrowser.selectedTab = selectedTab;
}
},
onPopupHiding: function () {
this.stopScroll();
window.removeEventListener("keyup", this, true);
window.removeEventListener("keypress", this, true);
while (this.container.childNodes.length)
this.removeBox(this.container.lastChild);
this.selected = null;
this.invertDirection = false;
this._uniqid = 0;
this.label.value = "";
this.setStatusbarValue();
this.container.removeAttribute("transform");
this.svgRoot.forceRedraw();
this._deferOnTabSelect.forEach(this.onTabSelect, this);
this._deferOnTabSelect = null;
},
onTabSelect: function (aTab) {
if (aTab.parentNode) {
this.detachTab(aTab);
this.attachTab(aTab, true);
}
},
handleEvent: function (event) {
switch (event.type) {
case "DOMAttrModified":
this.tabAttrModified(event.target, event.attrName);
break;
case "TabSelect":
if (this.isOpen)
// don't change the tab order while the panel is open
this._deferOnTabSelect.push(event.target);
else
this.onTabSelect(event.target);
break;
case "TabOpen":
this.attachTab(event.target);
break;
case "TabClose":
if (this.isOpen) {
if (this.tabs.length == 2) {
// we have two tabs, one is being closed, so the panel isn't needed anymore
this.panel.hidePopup();
} else {
if (event.target == this.selected._tab)
this.advanceSelected();
this.detachTab(event.target);
Array.slice(this.container.childNodes).forEach(function (box) {
if (box._tab == event.target) {
this.removeBox(box);
this.arrangeBoxes();
}
}, this);
}
}
this.detachTab(event.target);
break;
case "keydown":
this.onKeyDown(event);
break;
case "keypress":
// the panel is open; don't propagate any key events
event.stopPropagation();
event.preventDefault();
if (event.charCode == this.closeCharCode) {
this.stopScroll();
gBrowser.removeTab(this.selected._tab);
}
break;
case "keyup":
// the panel is open; don't propagate any key events
event.stopPropagation();
event.preventDefault();
this.onKeyUp(event);
break;
case "popuphiding":
this.onPopupHiding();
break;
}
}
};

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

@ -1,3 +1,7 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace svg url("http://www.w3.org/2000/svg");
@namespace xlink url("http://www.w3.org/1999/xlink");
searchbar {
-moz-binding: url("chrome://browser/content/search/search.xml#searchbar");
}
@ -82,3 +86,17 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
#navigator-toolbox[inFullscreen="true"] #fullscr-toggler {
display: -moz-box;
}
/* Tab Previews */
svg|*.ctrlTab-icon:not([xlink|href]) ,
svg|*.ctrlTab-thumbnail:not([xlink|href]) {
display: none;
}
svg|*.ctrlTab-thumbnailborder {
fill: transparent;
}
svg|*.ctrlTab-icon {
filter: url(chrome://browser/content/browser.xul#ctrlTab-iconShadow);
}

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

@ -73,19 +73,12 @@ var gURIFixup = null;
var gCharsetMenu = null;
var gLastBrowserCharset = null;
var gPrevCharset = null;
var gURLBar = null;
var gFindBar = null;
var gProxyFavIcon = null;
var gNavigatorBundle = null;
var gIsLoadingBlank = false;
var gLastValidURLStr = "";
var gMustLoadSidebar = false;
var gProgressMeterPanel = null;
var gProgressCollapseTimer = null;
var gPrefService = null;
var appCore = null;
var gBrowser = null;
var gNavToolbox = null;
var gSidebarCommand = "";
var gInPrintPreviewMode = false;
let gDownloadMgr = null;
@ -108,6 +101,34 @@ var gClickAndHoldTimer = null;
var gEditUIVisible = true;
#endif
[
["gBrowser", "content"],
["gNavToolbox", "navigator-toolbox"],
["gURLBar", "urlbar"],
["gNavigatorBundle", "bundle_browser"],
["gProgressMeterPanel", "statusbar-progresspanel"],
["gFindBar", "FindToolbar"]
].forEach(function (elementGlobal) {
var [name, id] = elementGlobal;
window.__defineGetter__(name, function () {
var element = document.getElementById(id);
if (!element)
return null;
delete window[name];
return window[name] = element;
});
window.__defineSetter__(name, function (val) {
delete window[name];
return window[name] = val;
});
});
__defineGetter__("gPrefService", function() {
delete this.gPrefService;
return this.gPrefService = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch2);
});
/**
* We can avoid adding multiple load event listeners and save some time by adding
* one listener that calls all real handlers.
@ -253,9 +274,9 @@ function SetClickAndHoldHandlers()
function BookmarkThisTab()
{
var tab = getBrowser().mContextTab;
var tab = gBrowser.mContextTab;
if (tab.localName != "tab")
tab = getBrowser().mCurrentTab;
tab = gBrowser.mCurrentTab;
PlacesCommandHook.bookmarkPage(tab.linkedBrowser,
PlacesUtils.bookmarksMenuFolderId, true);
@ -334,9 +355,6 @@ const gPopupBlockerObserver = {
// notifications are per-browser, we don't need to worry about re-adding
// it.
if (!gBrowser.pageReport.reported) {
if (!gPrefService)
gPrefService = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch2);
if (gPrefService.getBoolPref("privacy.popups.showBrowserMessage")) {
var bundle_browser = document.getElementById("bundle_browser");
var brandBundle = document.getElementById("bundle_brand");
@ -577,9 +595,8 @@ const gXPInstallObserver = {
_getBrowser: function (aDocShell)
{
var tabbrowser = getBrowser();
for (var i = 0; i < tabbrowser.browsers.length; ++i) {
var browser = tabbrowser.getBrowserAtIndex(i);
for (var i = 0; i < gBrowser.browsers.length; ++i) {
var browser = gBrowser.getBrowserAtIndex(i);
if (this._findChildShell(browser.docShell, aDocShell))
return browser;
}
@ -656,8 +673,6 @@ const gXPInstallObserver = {
function BrowserStartup()
{
gBrowser = document.getElementById("content");
var uriToLoad = null;
// window.arguments[0]: URI to load (string), or an nsISupportsArray of
@ -826,10 +841,6 @@ function HandleAppCommandEvent(evt)
function prepareForStartup()
{
gURLBar = document.getElementById("urlbar");
gNavigatorBundle = document.getElementById("bundle_browser");
gProgressMeterPanel = document.getElementById("statusbar-progresspanel");
gFindBar = document.getElementById("FindToolbar");
gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver.onUpdatePageReport, false);
// Note: we need to listen to untrusted events, because the pluginfinder XBL
// binding can't fire trusted ones (runs with page privileges).
@ -912,9 +923,6 @@ function delayedStartup()
os.addObserver(gSessionHistoryObserver, "browser:purge-session-history", false);
os.addObserver(gXPInstallObserver, "xpinstall-install-blocked", false);
if (!gPrefService)
gPrefService = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch2);
BrowserOffline.init();
OfflineApps.init();
@ -946,9 +954,8 @@ function delayedStartup()
else
focusElement(content);
var navToolbox = getNavToolbox();
navToolbox.customizeDone = BrowserToolboxCustomizeDone;
navToolbox.customizeChange = BrowserToolboxCustomizeChange;
gNavToolbox.customizeDone = BrowserToolboxCustomizeDone;
gNavToolbox.customizeChange = BrowserToolboxCustomizeChange;
// Set up Sanitize Item
gSanitizeListener = new SanitizeListener();
@ -1074,6 +1081,10 @@ function delayedStartup()
// themselves.
gBrowser.addEventListener("command", BrowserOnCommand, false);
tabPreviews.init();
if (gPrefService.getBoolPref("browser.ctrlTab.mostRecentlyUsed"))
ctrlTab.init();
// Delayed initialization of the livemarks update timer.
// Livemark updates don't need to start until after bookmark UI
// such as the toolbar has initialized. Starting 5 seconds after
@ -1104,6 +1115,9 @@ function delayedStartup()
function BrowserShutdown()
{
tabPreviews.uninit();
ctrlTab.uninit();
try {
FullZoom.destroy();
}
@ -1202,17 +1216,12 @@ function nonBrowserWindowStartup()
element.setAttribute("hidden", "true");
}
gNavigatorBundle = document.getElementById("bundle_browser");
setTimeout(nonBrowserWindowDelayedStartup, 0);
}
function nonBrowserWindowDelayedStartup()
{
// init global pref service
gPrefService = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch2);
// initialise the offline listener
BrowserOffline.init();
@ -1330,7 +1339,7 @@ function gotoHistoryIndex(aEvent)
// Normal click. Go there in the current tab and update session history.
try {
getBrowser().gotoIndex(index);
gBrowser.gotoIndex(index);
}
catch(ex) {
return false;
@ -1355,7 +1364,7 @@ function BrowserForward(aEvent, aIgnoreAlt)
if (where == "current") {
try {
getBrowser().goForward();
gBrowser.goForward();
}
catch(ex) {
}
@ -1375,7 +1384,7 @@ function BrowserBack(aEvent, aIgnoreAlt)
if (where == "current") {
try {
getBrowser().goBack();
gBrowser.goBack();
}
catch(ex) {
}
@ -1646,7 +1655,7 @@ function loadURI(uri, referrer, postData, allowThirdPartyFixup)
if (allowThirdPartyFixup) {
flags = nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
}
getBrowser().loadURIWithFlags(uri, flags, referrer, null, postData);
gBrowser.loadURIWithFlags(uri, flags, referrer, null, postData);
} catch (e) {
}
}
@ -1927,7 +1936,7 @@ function checkForDirectoryListing()
}
function URLBarSetURI(aURI) {
var value = getBrowser().userTypedValue;
var value = gBrowser.userTypedValue;
var state = "invalid";
if (!value) {
@ -2392,7 +2401,7 @@ function toggleAffectedChrome(aHide)
// (*) find bar
// (*) statusbar
getNavToolbox().hidden = aHide;
gNavToolbox.hidden = aHide;
if (aHide)
{
gChromeState = {};
@ -2453,7 +2462,7 @@ function onExitPrintPreview()
function getPPBrowser()
{
return getBrowser();
return gBrowser;
}
function getMarkupDocumentViewer()
@ -2992,8 +3001,8 @@ const BrowserSearch = {
return;
if (useNewTab) {
getBrowser().loadOneTab(submission.uri.spec, null, null,
submission.postData, null, false);
gBrowser.loadOneTab(submission.uri.spec, null, null,
submission.postData, null, false);
} else
loadURI(submission.uri.spec, null, submission.postData, false);
},
@ -3199,12 +3208,12 @@ function BrowserCustomizeToolbar()
// hidden
var sheetWidth = sheetFrame.style.width.match(/([0-9]+)px/)[1];
document.getElementById("customizeToolbarSheetPopup")
.openPopup(getNavToolbox(), "after_start", (window.innerWidth - sheetWidth) / 2, 0);
.openPopup(gNavToolbox, "after_start", (window.innerWidth - sheetWidth) / 2, 0);
#else
window.openDialog(customizeURL,
"CustomizeToolbar",
"chrome,all,dependent",
getNavToolbox());
gNavToolbox);
#endif
}
@ -3398,7 +3407,7 @@ var FullScreen =
// The user may quit fullscreen during an animation
clearInterval(this._animationInterval);
clearTimeout(this._animationTimeout);
getNavToolbox().style.marginTop = "0px";
gNavToolbox.style.marginTop = "0px";
if (this._isChromeCollapsed)
this.mouseoverToggle(true);
this._isAnimating = false;
@ -3509,21 +3518,20 @@ var FullScreen =
return;
}
var navToolbox = getNavToolbox();
var animateFrameAmount = 2;
function animateUpFrame() {
animateFrameAmount *= 2;
if (animateFrameAmount >=
(navToolbox.boxObject.height + gBrowser.mStrip.boxObject.height)) {
(gNavToolbox.boxObject.height + gBrowser.mStrip.boxObject.height)) {
// We've animated enough
clearInterval(FullScreen._animationInterval);
navToolbox.style.marginTop = "0px";
gNavToolbox.style.marginTop = "0px";
FullScreen._isAnimating = false;
FullScreen._shouldAnimate = false; // Just to make sure
FullScreen.mouseoverToggle(false);
return;
}
navToolbox.style.marginTop = (animateFrameAmount * -1) + "px";
gNavToolbox.style.marginTop = (animateFrameAmount * -1) + "px";
}
FullScreen._animationInterval = setInterval(animateUpFrame, 70);
@ -3631,11 +3639,10 @@ var FullScreen =
}
}
var toolbox = getNavToolbox();
if (aShow)
toolbox.removeAttribute("inFullscreen");
gNavToolbox.removeAttribute("inFullscreen");
else
toolbox.setAttribute("inFullscreen", true);
gNavToolbox.setAttribute("inFullscreen", true);
#ifndef XP_MACOSX
var controls = document.getElementsByAttribute("fullscreencontrol", "true");
@ -3707,7 +3714,7 @@ nsBrowserStatusHandler.prototype =
// Initialize the security button's state and tooltip text. Remember to reset
// _hostChanged, otherwise onSecurityChange will short circuit.
var securityUI = getBrowser().securityUI;
var securityUI = gBrowser.securityUI;
this._hostChanged = true;
this.onSecurityChange(null, null, securityUI.state);
},
@ -3853,7 +3860,7 @@ nsBrowserStatusHandler.prototype =
// For keyword URIs clear the user typed value since they will be changed into real URIs
if (location.scheme == "keyword" && aWebProgress.DOMWindow == content)
getBrowser().userTypedValue = null;
gBrowser.userTypedValue = null;
if (location.spec != "about:blank") {
const kErrorBindingAborted = 0x804B0002;
@ -3930,7 +3937,7 @@ nsBrowserStatusHandler.prototype =
// <a href="#" onclick="return install();">Install Foo</a>
//
// - which fires a onLocationChange message to uri + '#'...
var selectedBrowser = getBrowser().selectedBrowser;
var selectedBrowser = gBrowser.selectedBrowser;
if (selectedBrowser.lastURI) {
var oldSpec = selectedBrowser.lastURI.spec;
var oldIndexOfHash = oldSpec.indexOf("#");
@ -3962,7 +3969,7 @@ nsBrowserStatusHandler.prototype =
// Update urlbar only if a new page was loaded on the primary content area
// Do not update urlbar if there was a subframe navigation
var browser = getBrowser().selectedBrowser;
var browser = gBrowser.selectedBrowser;
if (aWebProgress.DOMWindow == content) {
if ((location == "about:blank" && !content.opener) ||
@ -4264,10 +4271,6 @@ nsBrowserAccess.prototype =
return null;
}
if (!gPrefService)
gPrefService = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch2);
var loadflags = isExternal ?
Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL :
Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
@ -4424,9 +4427,8 @@ function onViewToolbarsPopupShowing(aEvent)
var firstMenuItem = popup.firstChild;
var toolbox = getNavToolbox();
for (i = 0; i < toolbox.childNodes.length; ++i) {
var toolbar = toolbox.childNodes[i];
for (i = 0; i < gNavToolbox.childNodes.length; ++i) {
var toolbar = gNavToolbox.childNodes[i];
var toolbarName = toolbar.getAttribute("toolbarname");
var type = toolbar.getAttribute("type");
if (toolbarName && type != "menubar") {
@ -4446,9 +4448,8 @@ function onViewToolbarsPopupShowing(aEvent)
function onViewToolbarCommand(aEvent)
{
var toolbox = getNavToolbox();
var index = aEvent.originalTarget.getAttribute("toolbarindex");
var toolbar = toolbox.childNodes[index];
var toolbar = gNavToolbox.childNodes[index];
toolbar.collapsed = aEvent.originalTarget.getAttribute("checked") != "true";
document.persist(toolbar.id, "collapsed");
@ -4953,20 +4954,6 @@ var contentAreaDNDObserver = {
};
function getBrowser()
{
if (!gBrowser)
gBrowser = document.getElementById("content");
return gBrowser;
}
function getNavToolbox()
{
if (!gNavToolbox)
gNavToolbox = document.getElementById("navigator-toolbox");
return gNavToolbox;
}
function MultiplexHandler(event)
{ try {
var node = event.target;
@ -5023,8 +5010,7 @@ function SetForcedCharset(charset)
function BrowserSetForcedCharacterSet(aCharset)
{
var docCharset = getBrowser().docShell.QueryInterface(
Components.interfaces.nsIDocCharset);
var docCharset = gBrowser.docShell.QueryInterface(Ci.nsIDocCharset);
docCharset.charset = aCharset;
// Save the forced character-set
PlacesUtils.history.setCharsetForURI(getWebNavigation().currentURI, aCharset);
@ -5033,7 +5019,7 @@ function BrowserSetForcedCharacterSet(aCharset)
function BrowserSetForcedDetector(doReload)
{
getBrowser().documentCharsetInfo.forcedDetector = true;
gBrowser.documentCharsetInfo.forcedDetector = true;
if (doReload)
BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
}
@ -5399,7 +5385,7 @@ var OfflineApps = {
return gBrowser.mCurrentBrowser;
}
var browsers = getBrowser().browsers;
var browsers = gBrowser.browsers;
for (var i = 0; i < browsers.length; ++i) {
uri = this._getManifestURI(browsers[i].contentWindow);
if (uri && uri.equals(aCacheUpdate.manifestURI)) {
@ -5608,13 +5594,12 @@ var OfflineApps = {
function WindowIsClosing()
{
var browser = getBrowser();
var cn = browser.tabContainer.childNodes;
var cn = gBrowser.tabContainer.childNodes;
var numtabs = cn.length;
var reallyClose = true;
for (var i = 0; reallyClose && i < numtabs; ++i) {
var ds = browser.getBrowserForTab(cn[i]).docShell;
var ds = gBrowser.getBrowserForTab(cn[i]).docShell;
if (ds.contentViewer && !ds.contentViewer.permitUnload())
reallyClose = false;
@ -5628,7 +5613,7 @@ function WindowIsClosing()
// up another dialog so we don't need to.)
return closeWindow(false,
function () {
return browser.warnAboutClosingTabs(true);
return gBrowser.warnAboutClosingTabs(true);
});
}
@ -5797,7 +5782,6 @@ function getPluginInfo(pluginElement)
}
missingPluginInstaller.prototype.installSinglePlugin = function(aEvent){
var tabbrowser = getBrowser();
var missingPluginsArray = {};
var pluginInfo = getPluginInfo(aEvent.target);
@ -5806,7 +5790,7 @@ missingPluginInstaller.prototype.installSinglePlugin = function(aEvent){
if (missingPluginsArray) {
window.openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
"PFSWindow", "chrome,centerscreen,resizable=yes",
{plugins: missingPluginsArray, browser: tabbrowser.selectedBrowser});
{plugins: missingPluginsArray, browser: gBrowser.selectedBrowser});
}
aEvent.preventDefault();
@ -5835,18 +5819,17 @@ missingPluginInstaller.prototype.newMissingPlugin = function(aEvent){
return;
} catch (ex) {} // if the pref is missing, treat it as false, which shows the infobar
var tabbrowser = getBrowser();
const browsers = tabbrowser.mPanelContainer.childNodes;
const browsers = gBrowser.mPanelContainer.childNodes;
var contentWindow = aEvent.target.ownerDocument.defaultView.top;
var i = 0;
for (; i < browsers.length; i++) {
if (tabbrowser.getBrowserAtIndex(i).contentWindow == contentWindow)
if (gBrowser.getBrowserAtIndex(i).contentWindow == contentWindow)
break;
}
var browser = tabbrowser.getBrowserAtIndex(i);
var browser = gBrowser.getBrowserAtIndex(i);
if (!browser.missingPlugins)
browser.missingPlugins = {};
@ -5928,12 +5911,11 @@ function blocklistInfo()
function pluginsMissing()
{
// get the urls of missing plugins
var tabbrowser = getBrowser();
var missingPluginsArray = tabbrowser.selectedBrowser.missingPlugins;
var missingPluginsArray = gBrowser.selectedBrowser.missingPlugins;
if (missingPluginsArray) {
window.openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
"PFSWindow", "chrome,centerscreen,resizable=yes",
{plugins: missingPluginsArray, browser: tabbrowser.selectedBrowser});
{plugins: missingPluginsArray, browser: gBrowser.selectedBrowser});
}
}
@ -6139,6 +6121,8 @@ var FeedHandler = {
#include browser-textZoom.js
#include browser-tabPreviews.js
HistoryMenu.toggleRecentlyClosedTabs = function PHM_toggleRecentlyClosedTabs() {
// enable/disable the Recently Closed Tabs sub menu
var undoPopup = document.getElementById("historyUndoPopup");
@ -6214,7 +6198,7 @@ function undoCloseMiddleClick(aEvent) {
return;
undoCloseTab(aEvent.originalTarget.value);
getBrowser().moveTabToEnd();
gBrowser.moveTabToEnd();
}
/**
@ -6224,15 +6208,14 @@ function undoCloseMiddleClick(aEvent) {
*/
function undoCloseTab(aIndex) {
// wallpaper patch to prevent an unnecessary blank tab (bug 343895)
var tabbrowser = getBrowser();
var blankTabToRemove = null;
if (tabbrowser.tabContainer.childNodes.length == 1 &&
if (gBrowser.tabContainer.childNodes.length == 1 &&
!gPrefService.getBoolPref("browser.tabs.autoHide") &&
tabbrowser.selectedBrowser.sessionHistory.count < 2 &&
tabbrowser.selectedBrowser.currentURI.spec == "about:blank" &&
!tabbrowser.selectedBrowser.contentDocument.body.hasChildNodes() &&
!tabbrowser.selectedTab.hasAttribute("busy"))
blankTabToRemove = tabbrowser.selectedTab;
gBrowser.selectedBrowser.sessionHistory.count < 2 &&
gBrowser.selectedBrowser.currentURI.spec == "about:blank" &&
!gBrowser.selectedBrowser.contentDocument.body.hasChildNodes() &&
!gBrowser.selectedTab.hasAttribute("busy"))
blankTabToRemove = gBrowser.selectedTab;
var ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore);
@ -6241,7 +6224,7 @@ function undoCloseTab(aIndex) {
ss.undoCloseTab(window, aIndex || 0);
if (blankTabToRemove)
tabbrowser.removeTab(blankTabToRemove);
gBrowser.removeTab(blankTabToRemove);
}
/**
@ -6753,3 +6736,7 @@ let DownloadMonitorPanel = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDownloadProgressListener]),
};
/* DEPRECATED */
function getBrowser() gBrowser;
function getNavToolbox() gNavToolbox;

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

@ -29,6 +29,7 @@
# Pierre Chanial <chanial@noos.fr>
# Dean Tessman <dean_tessman@hotmail.com>
# Johnathan Nightingale <johnath@mozilla.com>
# Dão Gottwald <dao@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
@ -61,6 +62,7 @@
<window id="main-window"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="BrowserStartup()" onunload="BrowserShutdown()" onclose="return WindowIsClosing();"
contenttitlesetting="true"
@ -102,10 +104,14 @@
<!-- for url bar autocomplete -->
<panel type="autocomplete-richlistbox" chromedir="&locale.dir;" id="PopupAutoCompleteRichResult" noautofocus="true" hidden="true"/>
<!-- XXX panel element that has one or more text fields should not be
top-most panel, for IME users. See bug 433340 comment 100. -->
<panel id="editBookmarkPanel"
orient="vertical"
ignorekeys="true"
hidden="true"
noautohide="true"
onpopupshowing="this.removeAttribute('noautohide');"
onpopupshown="StarUI.panelShown(event);"
aria-labelledby="editBookmarkPanelTitle">
<hbox flex="1" align="top">
@ -227,6 +233,29 @@
<tooltip id="urlTooltip">
<label crop="center" flex="1"/>
</tooltip>
<panel id="ctrlTab-panel" class="KUI-panel" hidden="true">
<label id="ctrlTab-label" flex="1"/>
<svg:svg id="ctrlTab-svgRoot">
<svg:defs>
<svg:linearGradient id="ctrlTab-fadeGradient" x1="1" y1="1" x2="1" y2="0">
<svg:stop id="ctrlTab-fadeGradientBottom" offset="0"/>
<svg:stop id="ctrlTab-fadeGradientTop" offset="1"/>
</svg:linearGradient>
<svg:filter id="ctrlTab-iconShadow">
<svg:feOffset result="shadow" in="SourceAlpha" dx="2" dy="-1"/>
<svg:feColorMatrix result="transparent-shadow" in="shadow"
values="1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 0.5 0"/>
<svg:feBlend in="SourceGraphic" in2="transparent-shadow"/>
</svg:filter>
</svg:defs>
<svg:g id="ctrlTab-container"/>
<svg:rect id="ctrlTab-groundFade" fill="url(#ctrlTab-fadeGradient)" width="100%"/>
</svg:svg>
</panel>
</popupset>
<!-- bookmarks toolbar tooltip -->

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

@ -1189,6 +1189,8 @@ nsContextMenu.prototype = {
[engineName,
selectedText]);
document.getElementById("context-searchselect").label = menuLabel;
document.getElementById("context-searchselect").accessKey =
gNavigatorBundle.getString("contextMenuSearchText.accesskey");
return true;
},

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

@ -55,7 +55,7 @@
<xul:label xbl:inherits="value=type"/>
</xul:hbox>
<xul:hbox>
<xul:label xbl:inherits="value=feedURL" class="text-link" flex="1"
<xul:label xbl:inherits="value=feedURL,tooltiptext=feedURL" class="text-link" flex="1"
onclick="openUILink(this.value, event);" crop="end"/>
<xul:spacer flex="10000"/>
</xul:hbox>

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

@ -70,11 +70,11 @@
<script type="application/x-javascript" src="chrome://browser/content/pageinfo/feeds.js"/>
<script type="application/x-javascript" src="chrome://browser/content/pageinfo/permissions.js"/>
<script type="application/x-javascript" src="chrome://browser/content/pageinfo/security.js"/>
<script type="application/x-javascript" src="chrome://global/content/strres.js"/>
<script type="application/x-javascript" src="chrome://browser/content/utilityOverlay.js"/>
<stringbundleset id="pageinfobundleset">
<stringbundle id="pageinfobundle" src="chrome://browser/locale/pageInfo.properties"/>
<stringbundle id="pkiBundle" src="chrome://pippki/locale/pippki.properties"/>
</stringbundleset>
<commandset id="pageInfoCommandSet">

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

@ -186,9 +186,6 @@ var security = {
};
function securityOnLoad() {
var bundle = srGetStrBundle("chrome://pippki/locale/pippki.properties");
var pageInfoBundle = document.getElementById("pageinfobundle");
var info = security._getSecurityInfo();
if (!info) {
document.getElementById("securityTab").hidden = true;
@ -200,6 +197,8 @@ function securityOnLoad() {
document.getElementById("securityBox").collapsed = false;
}
const pageInfoBundle = document.getElementById("pageinfobundle");
/* Set Identity section text */
setText("security-identity-domain-value", info.hostName);
@ -273,35 +272,36 @@ function securityOnLoad() {
}
/* Set the Technical Detail section messages */
const pkiBundle = document.getElementById("pkiBundle");
var hdr;
var msg1;
var msg2;
if (info.isBroken) {
hdr = bundle.GetStringFromName("pageInfo_MixedContent");
msg1 = bundle.GetStringFromName("pageInfo_Privacy_Mixed1");
msg2 = bundle.GetStringFromName("pageInfo_Privacy_None2");
hdr = pkiBundle.getString("pageInfo_MixedContent");
msg1 = pkiBundle.getString("pageInfo_Privacy_Mixed1");
msg2 = pkiBundle.getString("pageInfo_Privacy_None2");
}
else if (info.encryptionStrength >= 90) {
hdr = bundle.formatStringFromName("pageInfo_StrongEncryption",
[ info.encryptionAlgorithm, info.encryptionStrength + "" ], 2);
msg1 = bundle.GetStringFromName("pageInfo_Privacy_Strong1");
msg2 = bundle.GetStringFromName("pageInfo_Privacy_Strong2");
hdr = pkiBundle.getFormattedString("pageInfo_StrongEncryption",
[info.encryptionAlgorithm, info.encryptionStrength + ""]);
msg1 = pkiBundle.getString("pageInfo_Privacy_Strong1");
msg2 = pkiBundle.getString("pageInfo_Privacy_Strong2");
security._cert = info.cert;
}
else if (info.encryptionStrength > 0) {
hdr = bundle.formatStringFromName("pageInfo_WeakEncryption",
[ info.encryptionAlgorithm, info.encryptionStrength + "" ], 2);
msg1 = bundle.formatStringFromName("pageInfo_Privacy_Weak1", [ info.hostName ], 1);
msg2 = bundle.GetStringFromName("pageInfo_Privacy_Weak2");
hdr = pkiBundle.getFormattedString("pageInfo_WeakEncryption",
[info.encryptionAlgorithm, info.encryptionStrength + ""]);
msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_Weak1", [info.hostName]);
msg2 = pkiBundle.getString("pageInfo_Privacy_Weak2");
}
else {
hdr = bundle.GetStringFromName("pageInfo_NoEncryption");
hdr = pkiBundle.getString("pageInfo_NoEncryption");
if (info.hostName != null)
msg1 = bundle.formatStringFromName("pageInfo_Privacy_None1", [ info.hostName ], 1);
msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_None1", [info.hostName]);
else
msg1 = bundle.GetStringFromName("pageInfo_Privacy_None3");
msg2 = bundle.GetStringFromName("pageInfo_Privacy_None2");
msg1 = pkiBundle.getString("pageInfo_Privacy_None3");
msg2 = pkiBundle.getString("pageInfo_Privacy_None2");
}
setText("security-technical-shortform", hdr);
setText("security-technical-longform1", msg1);

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

@ -278,7 +278,6 @@
mTab: aTab,
mBrowser: aBrowser,
mBlank: aStartsBlank,
mLastURI: null,
// cache flags for correct status bar update after tab switching
mStateFlags: 0,
@ -1389,6 +1388,18 @@
<method name="removeTab">
<parameter name="aTab"/>
<body>
<![CDATA[
this._endRemoveTab(this._beginRemoveTab(aTab, true));
]]>
</body>
</method>
<!-- Returns the tab being removed. This might not be the same as aTab,
in cases when aTab is not actually a tab -->
<method name="_beginRemoveTab">
<parameter name="aTab"/>
<parameter name="aFireBeforeUnload"/>
<body>
<![CDATA[
this._browsers = null; // invalidate cache
@ -1403,9 +1414,11 @@
return;
}
var ds = this.getBrowserForTab(aTab).docShell;
if (ds.contentViewer && !ds.contentViewer.permitUnload())
return;
if (aFireBeforeUnload) {
var ds = this.getBrowserForTab(aTab).docShell;
if (ds.contentViewer && !ds.contentViewer.permitUnload())
return;
}
// see notes in addTab
var _delayedUpdate = function(aTabContainer) {
@ -1435,15 +1448,7 @@
evt.initEvent("TabClose", true, false);
aTab.dispatchEvent(evt);
var index = -1;
if (this.mCurrentTab == aTab)
index = this.mTabContainer.selectedIndex;
else {
// Find and locate the tab in our list.
for (var i = 0; i < l; i++)
if (this.mTabContainer.childNodes[i] == aTab)
index = i;
}
var index = aTab._tPos;
// Remove the tab's filter and progress listener.
const filter = this.mTabFilters[index];
@ -1459,22 +1464,34 @@
// We are no longer the primary content area.
oldBrowser.setAttribute("type", "content-targetable");
// Get the index of the tab we're removing before unselecting it
var currentIndex = this.mTabContainer.selectedIndex;
var oldTab = aTab;
// clean up the before/afterselected attributes before removing the tab
oldTab._selected = false;
// Remove this tab as the owner of any other tabs, since it's going away.
for (i = 0; i < this.mTabContainer.childNodes.length; ++i) {
for (var i = 0; i < this.mTabs.length; ++i) {
var tab = this.mTabContainer.childNodes[i];
if ("owner" in tab && tab.owner == oldTab)
if ("owner" in tab && tab.owner == aTab)
// |tab| is a child of the tab we're removing, make it an orphan
tab.owner = null;
}
return aTab;
]]>
</body>
</method>
<method name="_endRemoveTab">
<parameter name="aTab"/>
<body>
<![CDATA[
var browser = this.getBrowserForTab(aTab);
var length = this.mTabs.length;
// Get the index of the tab we're removing before unselecting it
var currentIndex = this.mTabContainer.selectedIndex;
var index = aTab._tPos;
// clean up the before/afterselected attributes before removing the
// tab. But make sure this happens after we grab currentIndex.
aTab._selected = false;
// Because of the way XBL works (fields just set JS
// properties on the element) and the code we have in place
// to preserve the JS objects for any elements that have
@ -1485,16 +1502,18 @@
// XBL implementation of nsIObserver still works. But
// clearing focusedWindow happens below because it gets
// reset by updateCurrentBrowser.
oldBrowser.destroy();
browser.destroy();
if (oldBrowser == this.mCurrentBrowser)
if (browser == this.mCurrentBrowser)
this.mCurrentBrowser = null;
// Remove the tab
this.mTabContainer.removeChild(oldTab);
this.mTabContainer.removeChild(aTab);
// Update our length
--length;
// invalidate cache, because mTabContainer is about to change
this._browsers = null;
this.mPanelContainer.removeChild(oldBrowser.parentNode);
this.mPanelContainer.removeChild(browser.parentNode);
try {
// if we're at the right side (and not the logical end,
@ -1523,24 +1542,24 @@
else if (currentIndex < index)
newIndex = currentIndex;
else {
if ("owner" in oldTab && oldTab.owner &&
if ("owner" in aTab && aTab.owner &&
this.mPrefs.getBoolPref("browser.tabs.selectOwnerOnClose")) {
for (i = 0; i < this.mTabContainer.childNodes.length; ++i) {
for (var i = 0; i < length; ++i) {
tab = this.mTabContainer.childNodes[i];
if (tab == oldTab.owner) {
if (tab == aTab.owner) {
newIndex = i;
break;
}
}
}
if (newIndex == -1)
newIndex = (index == l - 1) ? index - 1 : index;
newIndex = (index == length) ? index - 1 : index;
}
// Select the new tab
this.selectedTab = this.mTabContainer.childNodes[newIndex];
this.selectedTab = this.mTabs[newIndex];
for (i = oldTab._tPos; i < this.mTabContainer.childNodes.length; i++) {
for (i = aTab._tPos; i < length; i++) {
this.mTabContainer.childNodes[i]._tPos = i;
}
this.mTabBox.selectedPanel = this.getBrowserForTab(this.mCurrentTab).parentNode;
@ -1549,8 +1568,53 @@
this.updateCurrentBrowser();
// see comment above destroy above
oldBrowser.focusedWindow = null;
oldBrowser.focusedElement = null;
browser.focusedWindow = null;
browser.focusedElement = null;
]]>
</body>
</method>
<method name="swapBrowsersAndCloseOther">
<parameter name="aOurTab"/>
<parameter name="aOtherTab"/>
<body>
<![CDATA[
var remoteBrowser =
aOtherTab.ownerDocument.defaultView.getBrowser();
var tabCount = remoteBrowser.mTabs.length;
// First, start teardown of the other browser. Make sure to not
// fire the beforeunload event in the process.
var tabToRemove = remoteBrowser._beginRemoveTab(aOtherTab, false);
// Unhook our progress listener
var ourIndex = aOurTab._tPos;
const filter = this.mTabFilters[ourIndex];
var tabListener = this.mTabListeners[ourIndex];
var ourBrowser = this.getBrowserForTab(aOurTab);
ourBrowser.webProgress.removeProgressListener(filter);
filter.removeProgressListener(tabListener);
var tabListenerBlank = tabListener.mBlank;
// Swap the docshells
ourBrowser.swapDocShells(remoteBrowser.getBrowserForTab(aOtherTab));
// Finish tearing down the tab that's going away.
remoteBrowser._endRemoveTab(tabToRemove);
// Restore the progress listener
tabListener = this.mTabProgressListener(aOurTab, ourBrowser,
tabListenerBlank);
this.mTabListeners[ourIndex] = tabListener;
filter.addProgressListener(tabListener,
Components.interfaces.nsIWebProgress.NOTIFY_ALL);
ourBrowser.webProgress.addProgressListener(filter,
Components.interfaces.nsIWebProgress.NOTIFY_ALL);
// close the other window if this was its last tab
if (tabCount == 1)
aOtherTab.ownerDocument.defaultView.close();
]]>
</body>
</method>
@ -1879,19 +1943,26 @@
}
}
else if (draggedTab) {
// copy the dropped tab and remove it from the other window
// (making it seem to have moved between windows)
// swap the dropped tab with a new one we create and then close
// it in the other window (making it seem to have moved between
// windows)
newIndex = this.getNewIndex(aEvent);
newTab = this.duplicateTab(draggedTab);
this.moveTabTo(newTab, newIndex);
this.selectedTab = newTab;
newTab = this.addTab("about:blank");
var newBrowser = this.getBrowserForTab(newTab);
// Stop the about:blank load
newBrowser.stop();
// make sure it has a docshell
newBrowser.docShell;
var remoteBrowser = draggedTab.ownerDocument.defaultView.getBrowser();
var tabCount = remoteBrowser.tabContainer.childNodes.length;
remoteBrowser.removeTab(draggedTab);
// close the other window if this was its last tab
if (tabCount == 1)
draggedTab.ownerDocument.defaultView.close();
this.moveTabTo(newTab, newIndex);
this.swapBrowsersAndCloseOther(newTab, draggedTab);
// We need to set selectedTab after we've done
// swapBrowsersAndCloseOther, so that the updateCurrentBrowser
// it triggers will correctly update our URL bar.
this.selectedTab = newTab;
this.setTabTitle(newTab);
}
else {
var url = transferUtils.retrieveURLFromData(aXferData.data, aXferData.flavour.contentType);

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

@ -59,6 +59,8 @@ _BROWSER_FILES = browser_bug321000.js \
autodiscovery.html \
moz.png \
browser_getshortcutoruri.js \
browser_page_style_menu.js \
page_style_sample.html \
$(NULL)
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))

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

@ -8,6 +8,7 @@ function test() {
}
function delayedOpenUrl() {
ok(true, "Ran delayedOpenUrl");
setTimeout(openPanelUrl, 100);
}
@ -26,6 +27,7 @@ function openPanelUrl(event) {
}
function delayedRunTest() {
ok(true, "Ran delayedRunTest");
setTimeout(runTest, 100);
}

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

@ -0,0 +1,66 @@
function test() {
waitForExplicitFinish();
finish();
return;
var tab = gBrowser.addTab();
gBrowser.selectedTab = tab;
tab.linkedBrowser.addEventListener("load", checkPageStyleMenu, true);
content.location =
"chrome://mochikit/content/browser/browser/base/content/test/page_style_sample.html";
}
function checkPageStyleMenu() {
var menupopup = document.getElementById("pageStyleMenu")
.getElementsByTagName("menupopup")[0];
stylesheetFillPopup(menupopup);
var items = [];
var current = menupopup.getElementsByTagName("menuseparator")[0];
while (current.nextSibling) {
current = current.nextSibling;
items.push(current);
}
var validLinks = 0;
Array.forEach(content.document.getElementsByTagName("link"), function (link) {
var title = link.getAttribute("title");
var rel = link.getAttribute("rel");
var media = link.getAttribute("media");
var idstring = "link " + (title ? title : "without title and") +
" with rel=\"" + rel + "\"" +
(media ? " and media=\"" + media + "\"" : "");
var item = items.filter(function (item) item.label == title);
var found = item.length == 1;
var checked = found && (item[0].getAttribute("checked") == "true");
switch (link.getAttribute("data-state")) {
case "0":
ok(!found, idstring + " does not show up in page style menu");
break;
case "0-todo":
validLinks++;
todo(!found, idstring + " should not show up in page style menu");
ok(!checked, idstring + " is not selected");
break;
case "1":
validLinks++;
ok(found, idstring + " shows up in page style menu");
ok(!checked, idstring + " is not selected");
break;
case "2":
validLinks++;
ok(found, idstring + " shows up in page style menu");
ok(checked, idstring + " is selected");
break;
default:
throw "data-state attribute is missing or has invalid value";
}
});
is(validLinks, items.length, "all valid links found");
gBrowser.removeCurrentTab();
finish();
}

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

@ -0,0 +1,31 @@
<html>
<head>
<title>Test for page style menu</title>
<!-- data-state values:
0: should not appear in the page style menu
0-todo: should not appear in the page style menu, but does
1: should appear in the page style menu
2: should appear in the page style menu as the selected stylesheet -->
<link data-state="1" href="404.css" title="1" rel="alternate stylesheet">
<link data-state="0" title="2" rel="alternate stylesheet">
<link data-state="0" href="404.css" rel="alternate stylesheet">
<link data-state="0" href="404.css" title="" rel="alternate stylesheet">
<link data-state="1" href="404.css" title="3" rel="stylesheet alternate">
<link data-state="1" href="404.css" title="4" rel=" alternate stylesheet ">
<link data-state="1" href="404.css" title="5" rel="alternate stylesheet">
<link data-state="2" href="404.css" title="6" rel="stylesheet">
<link data-state="1" href="404.css" title="7" rel="foo stylesheet">
<link data-state="0" href="404.css" title="8" rel="alternate">
<link data-state="1" href="404.css" title="9" rel="alternate STYLEsheet">
<link data-state="1" href="404.css" title="10" rel="alternate stylesheet" media="">
<link data-state="1" href="404.css" title="11" rel="alternate stylesheet" media="all">
<link data-state="1" href="404.css" title="12" rel="alternate stylesheet" media="ALL ">
<link data-state="1" href="404.css" title="13" rel="alternate stylesheet" media="screen">
<link data-state="1" href="404.css" title="14" rel="alternate stylesheet" media=" Screen">
<link data-state="1" href="404.css" title="15" rel="alternate stylesheet" media="screen foo">
<link data-state="1" href="404.css" title="16" rel="alternate stylesheet" media="all screen">
<link data-state="0-todo" href="404.css" title="17" rel="alternate stylesheet" media="allscreen">
<link data-state="0-todo" href="404.css" title="18" rel="alternate stylesheet" media="_all">
</head>
<body></body>
</html>

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

@ -42,7 +42,6 @@
* for shared application glue for the Communicator suite of applications
**/
var goPrefWindow = 0;
var gBidiUI = false;
function getBrowserURL()

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

@ -115,7 +115,6 @@ function load()
null, null);
}
gNavigatorBundle = document.getElementById("bundle_browser");
gLoadFired = true;
}

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

@ -15,6 +15,7 @@ browser.jar:
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-icon-rtl.png (content/aboutRobots-icon-rtl.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)

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

@ -37,17 +37,17 @@
# NSIS branding defines for unofficial builds.
# The official release build branding.nsi is located in other-license/branding/firefox/
# The nightly build branding.nsi is located in browser/installer/windows/nsis/
!define BrandShortName "Gran Paradiso"
!define BrandShortName "Shiretoko"
# BrandFullNameInternal is used for some registry and file system values
# instead of BrandFullName and typically should not be modified.
!define BrandFullNameInternal "Gran Paradiso"
!define BrandFullNameInternal "Shiretoko"
!define CompanyName "mozilla.org"
!define URLInfoAbout "http://www.mozilla.org"
!define URLUpdateInfo "http://www.mozilla.org/projects/firefox"
!define SurveyURL "https://survey.mozilla.com/1/Mozilla%20Firefox/${AppVersion}/${AB_CD}/exit.html"
# Everything below this line may be modified for Alpha / Beta releases.
!define BrandFullName "Gran Paradiso"
!define BrandFullName "Shiretoko"
# Add !define NO_INSTDIR_FROM_REG to prevent finding a non-default installation
# directory in the registry and using that as the default. This prevents

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

@ -1 +1 @@
MOZ_APP_DISPLAYNAME="GranParadiso"
MOZ_APP_DISPLAYNAME="Shiretoko"

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

@ -28,7 +28,7 @@ resource 'STR#' (5000, "English") {
"Save AsÉ",
// Descriptive text, curly quotes are 0xD2 and 0xD3
"You are about to install\n"
"Gran Paradiso.\n"
"Shiretoko.\n"
"\n"
"Please read the license agreement. If you agree to its terms and accept, click ÒAcceptÓ to access the software. Otherwise, click ÒDeclineÓ to cancel."
};
@ -41,7 +41,7 @@ resource 'STR#' (5000, "English") {
// 0xD2 and 0xD3 are curly double-quotes ("), 0xD4 and 0xD5 are curly
// single quotes ('), 0xD5 is also the apostrophe.
data 'TEXT' (5000, "English") {
"GRAN PARADISO END-USER SOFTWARE LICENSE AGREEMENT\n"
"SHIRETOKO END-USER SOFTWARE LICENSE AGREEMENT\n"
"Version 3.0, May 2008\n"
"\n"
"A SOURCE CODE VERSION OF CERTAIN FIREFOX BROWSER FUNCTIONALITY THAT YOU MAY USE, MODIFY AND DISTRIBUTE IS AVAILABLE TO YOU FREE-OF-CHARGE FROM WWW.MOZILLA.ORG UNDER THE MOZILLA PUBLIC LICENSE and other open source software licenses.\n"

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

@ -1,3 +1,3 @@
# Do NOT localize or otherwise change these values
browser.startup.homepage=http://www.mozilla.org/projects/granparadiso/
browser.startup.homepage=http://www.mozilla.org/projects/shiretoko/

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

@ -1,6 +1,6 @@
<!ENTITY brandShortName "Gran Paradiso">
<!ENTITY brandFullName "Gran Paradiso">
<!ENTITY brandShortName "Shiretoko">
<!ENTITY brandFullName "Shiretoko">
<!ENTITY vendorShortName "mozilla.org">
<!-- LOCALIZATION NOTE (releaseBaseURL): The about: page appends __MOZ_APP_VERSION__.html, e.g. 2.0.html -->
<!ENTITY releaseBaseURL "http://www.mozilla.org/projects/granparadiso/releases/">
<!ENTITY releaseBaseURL "http://www.mozilla.org/projects/shiretoko/releases/">

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

@ -1,3 +1,3 @@
brandShortName=Gran Paradiso
brandFullName=Gran Paradiso
brandShortName=Shiretoko
brandFullName=Shiretoko
vendorShortName=mozilla.org

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

@ -2,6 +2,6 @@
@AB_CD@.jar:
% locale branding @AB_CD@ %locale/branding/
# Gran Paradiso branding only exists in en-US
# Unofficial branding only exists in en-US
locale/branding/brand.dtd (en-US/brand.dtd)
* locale/branding/brand.properties (en-US/brand.properties)

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

@ -59,3 +59,14 @@ package:
install::
@$(MAKE) -C browser/installer install
ifdef ENABLE_TESTS
# Implemented in testing/testsuite-targets.mk
mochitest-browser-chrome:
$(RUN_MOCHITEST) --browser-chrome
$(CHECK_TEST_ERROR)
mochitest:: mochitest-browser-chrome
.PHONY: mochitest-browser-chrome
endif

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

@ -226,7 +226,7 @@ DistributionCustomizer.prototype = {
if (!bmProcessed) {
if (sections["BookmarksMenu"])
this._parseBookmarksSection(this._bmSvc.bookmarksRoot,
this._parseBookmarksSection(this._bmSvc.bookmarksMenuFolder,
"BookmarksMenu");
if (sections["BookmarksToolbar"])
this._parseBookmarksSection(this._bmSvc.toolbarFolder,

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

@ -564,13 +564,29 @@ BrowserGlue.prototype = {
this._dataSource = this._rdf.GetDataSource("rdf:local-store");
this._dirty = false;
var currentSet = this._rdf.GetResource("currentset");
// get an nsIRDFResource for the nav-bar item
var navBar = this._rdf.GetResource("chrome://browser/content/browser.xul#nav-bar");
var target = this._getPersist(navBar, currentSet);
if (target && !/(?:^|,)unified-back-forward-button(?:$|,)/.test(target))
this._setPersist(navBar, currentSet, "unified-back-forward-button," + target);
let currentsetResource = this._rdf.GetResource("currentset");
let toolbars = ["nav-bar", "toolbar-menubar", "PersonalToolbar"];
for (let i = 0; i < toolbars.length; i++) {
let toolbar = this._rdf.GetResource("chrome://browser/content/browser.xul#" + toolbars[i]);
let currentset = this._getPersist(toolbar, currentsetResource);
if (!currentset) {
// toolbar isn't customized
if (i == 0)
// new button is in the defaultset, nothing to migrate
break;
continue;
}
if (/(?:^|,)unified-back-forward-button(?:$|,)/.test(currentset))
// new button is already there, nothing to migrate
break;
if (/(?:^|,)back-button(?:$|,)/.test(currentset)) {
let newset = currentset.replace(/(^|,)back-button($|,)/,
"$1unified-back-forward-button,back-button$2")
this._setPersist(toolbar, currentsetResource, newset);
// done migrating
break;
}
}
// force the RDF to be saved
if (this._dirty)

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

@ -63,8 +63,7 @@
<hbox align="center">
<label value="&search.label;" accesskey="&search.accesskey;" control="search-box"/>
<textbox id="search-box" flex="1"
type="timed" timeout="500"
<textbox id="search-box" flex="1" type="search"
oncommand="searchBookmarks(this.value);"/>
</hbox>

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

@ -86,7 +86,7 @@
<hbox align="center">
<label value="&find.label;" accesskey="&find.accesskey;"
control="search-box"/>
<textbox id="search-box" flex="1" type="timed" timeout="500"
<textbox id="search-box" flex="1" type="search"
oncommand="searchHistory(this.value);"/>
<button id="viewButton" style="min-width:0px !important;" type="menu"
label="&view.label;" accesskey="&view.accesskey;" selectedsort="day"

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

@ -902,12 +902,12 @@
<getter><![CDATA[
// By default, the insertion point is at the top level, at the end.
var index = PlacesUtils.bookmarks.DEFAULT_INDEX;
var folderId = 0;
var container = null;
var orientation = Ci.nsITreeView.DROP_BEFORE;
var isTag = false;
if (PlacesUtils.nodeIsFolder(this._resultNode)) {
folderId = PlacesUtils.getConcreteItemId(this._resultNode);
container = this._resultNode;
isTag = PlacesUtils.nodeIsTagQuery(this._resultNode);
}
@ -917,20 +917,37 @@
if (!popupNode.node) {
// If a static menuitem is selected the insertion point
// is inside the folder, at the end.
folderId = PlacesUtils.getConcreteItemId(selectedNode);
container = selectedNode;
orientation = Ci.nsITreeView.DROP_ON;
}
else {
// In all other cases the insertion point is before that node.
folderId = PlacesUtils.getConcreteItemId(selectedNode.parent);
container = selectedNode.parent;
index = PlacesUtils.getIndexOfNode(selectedNode);
isTag = PlacesUtils.nodeIsTagQuery(selectedNode.parent);
}
}
return new InsertionPoint(folderId, index, orientation, isTag);
if (this._disallowInsertion(container))
return null;
return new InsertionPoint(PlacesUtils.getConcreteItemId(container),
index, orientation, isTag);
]]></getter>
</property>
<method name="_disallowInsertion">
<parameter name="aContainer"/>
<body><![CDATA[
// allow dropping into Tag containers
if (PlacesUtils.nodeIsTagQuery(aContainer))
return false;
// Disallow insertion of items under readonly folders
return (!PlacesUtils.nodeIsFolder(aContainer) ||
PlacesUtils.nodeIsReadOnly(aContainer));
]]></body>
</method>
<!-- nsIPlacesView -->
<method name="selectAll">
<body/>

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

@ -853,6 +853,10 @@ var PlacesSearchBox = {
//scopeBtn.label = PlacesOrganizer._places.selectedNode.title;
break;
case "bookmarks":
// Make sure we're getting uri results.
// We do not yet support searching into grouped queries or into
// tag containers, so we must fall to the default case.
currentOptions.resultType = currentOptions.RESULT_TYPE_URI;
content.applyFilter(filterString,
[PlacesUtils.bookmarksMenuFolderId,
PlacesUtils.toolbarFolderId,

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

@ -385,7 +385,7 @@
<getter><![CDATA[
// By default, the insertion point is at the top level, at the end.
var index = PlacesUtils.bookmarks.DEFAULT_INDEX;
var folderId = PlacesUtils.getConcreteItemId(this._result.root);
var container = this._result.root;
var orientation = Ci.nsITreeView.DROP_BEFORE;
var isTag = false;
@ -395,20 +395,37 @@
if (!popupNode.node) {
// If a static menuitem is selected the insertion point
// is inside the folder, at the end.
folderId = PlacesUtils.getConcreteItemId(selectedNode);
container = selectedNode;
orientation = Ci.nsITreeView.DROP_ON;
}
else {
// In all other cases the insertion point is before that node.
folderId = PlacesUtils.getConcreteItemId(selectedNode.parent);
container = selectedNode.parent;
index = PlacesUtils.getIndexOfNode(selectedNode);
isTag = PlacesUtils.nodeIsTagQuery(selectedNode.parent);
}
}
return new InsertionPoint(folderId, index, orientation, isTag);
if (this._disallowInsertion(container))
return null;
return new InsertionPoint(PlacesUtils.getConcreteItemId(container),
index, orientation, isTag);
]]></getter>
</property>
<method name="_disallowInsertion">
<parameter name="aContainer"/>
<body><![CDATA[
// allow dropping into Tag containers
if (PlacesUtils.nodeIsTagQuery(aContainer))
return false;
// Disallow insertion of items under readonly folders
return (!PlacesUtils.nodeIsFolder(aContainer) ||
PlacesUtils.nodeIsReadOnly(aContainer));
]]></body>
</method>
<!-- nsIPlacesView -->
<method name="selectAll">
<body><![CDATA[

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

@ -487,7 +487,7 @@
return this._cachedInsertionPoint;
]]></getter>
</property>
<method name="_disallowInsertion">
<parameter name="aContainer"/>
<body><![CDATA[

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

@ -939,6 +939,11 @@ PlacesTreeView.prototype = {
if (!node.parent)
return true;
// Flat-lists may ignore expandQueries and other query options when
// they are asked to open a container.
if (this._flatList)
return true;
// treat non-expandable childless queries as non-containers
if (PlacesUtils.nodeIsQuery(node)) {
var parent = node.parent;

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

@ -897,14 +897,26 @@ placesSortFolderByNameTransactions.prototype = {
newOrder = newOrder.concat(preSep);
}
// set the nex indexs
for (var i = 0; i < count; ++i)
PlacesUtils.bookmarks.setItemIndex(newOrder[i].itemId, i);
// set the nex indexes
var callback = {
runBatched: function() {
for (var i = 0; i < newOrder.length; ++i) {
PlacesUtils.bookmarks.setItemIndex(newOrder[i].itemId, i);
}
}
};
PlacesUtils.bookmarks.runInBatchMode(callback, null);
},
undoTransaction: function PSSFBN_undoTransaction() {
for (item in this._oldOrder)
PlacesUtils.bookmarks.setItemIndex(item, this._oldOrder[item]);
var callback = {
_self: this,
runBatched: function() {
for (item in this._self._oldOrder)
PlacesUtils.bookmarks.setItemIndex(item, this._self._oldOrder[item]);
}
};
PlacesUtils.bookmarks.runInBatchMode(callback, null);
}
};

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

@ -49,6 +49,7 @@ XPCSHELL_TESTS = unit
ifdef MOZ_MOCHITEST
DIRS += browser
DIRS += perf
endif
include $(topsrcdir)/config/rules.mk

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

@ -1,4 +1,3 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
@ -15,11 +14,12 @@
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2007
# Mozilla Corporation.
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Shawn Wilsher <me@shawnwilsher.com> (Original Author)
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
@ -35,28 +35,18 @@
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = dom/tests/mochitest/ajax/jquery/src
DEPTH = ../../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = browser/components/places/tests/perf
include $(DEPTH)/config/autoconf.mk
DIRS = \
ajax \
event \
fx \
jquery \
selector \
$(NULL)
include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
intro.js \
outro.js \
$(NULL)
_CHROME_FILES = \
perf_large_delete.xul \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
libs:: $(_CHROME_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)

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

@ -0,0 +1,169 @@
<?xml version="1.0"?>
<!--
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* This tests that the performance of deleting a large number of bookmarks. See
* bug 432706 for more details.
*
* To run this test, run it like you would a standard chrome test, with the test
* path being:
* ../chrome/browser/components/places/tests/perf/perf_large_delete.xul
*/
-->
<window title="Places Library Performance Test"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="test();">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"/>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript">
<![CDATA[
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
function test()
{
let ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
// First, add 250 bookmarks
let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
bs.runInBatchMode({
runBatched: function(aUserData)
{
for (let i = 0; i < 250; i++) {
let uri = ios.newURI("http://example.com/" + i, null, null);
bs.insertBookmark(bs.unfiledBookmarksFolder, uri, bs.DEFAULT_INDEX,
"bookmark " + i);
}
}
}, null);
// Close the window if it's already open
let wm = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
let win = wm.getMostRecentWindow("Places:Orgainzier");
if (win)
win.close();
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
ww.registerNotification({
observe: function(aSubject, aTopic, aData)
{
if (aTopic != "domwindowopened")
return;
let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget);
// We need to run after the window is loaded, and has run its startup code
win.addEventListener("DOMContentLoaded", function() {
let tm = Cc["@mozilla.org/thread-manager;1"].
getService(Ci.nsIThreadManager);
tm.mainThread.dispatch({
run: function() doTest(win.QueryInterface(Ci.nsIDOMWindow))
}, Ci.nsIThread.DISPATCH_NORMAL);
}, false);
// and now to unregister ourself as a listener
ww.unregisterNotification(this);
}
});
function doTest(aWin)
{
// Select all the bookmarks
synthesizeKey("a", {accelKey:true}, aWin);
// If we can, start shark
try {
connectShark();
startShark();
}
catch (e) { }
// Delete the bookmarks
let start = Date.now();
synthesizeKey("VK_BACK_SPACE", {}, aWin);
let end = Date.now();
// Stop shark, if we can
try {
stopShark();
disconnectionShark();
}
catch (e) { }
// Close the window, and write the results out
aWin.close();
document.getElementById("test-result").value =
"Duration was " + String(end - start) + "ms";
SimpleTest.finish();
}
// And open the window
wm.getMostRecentWindow("navigator:browser")
.openDialog("chrome://browser/content/places/places.xul",
"", "chrome,toolbar=yes,dialog=no,resizable",
"UnfiledBookmarks");
SimpleTest.waitForExplicitFinish();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display:none;"></div>
<pre id="test"></pre>
</body>
<label id="test-result"/>
</window>

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

@ -50,6 +50,8 @@
style="&appManager.style;"
persist="screenX screenY">
<script type="application/javascript"
src="chrome://browser/content/utilityOverlay.js"/>
<script type="application/javascript"
src="chrome://browser/content/preferences/applicationManager.js"/>
<script type="application/javascript"

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

@ -982,6 +982,10 @@ var gApplicationsPane = {
self._rebuildVisibleTypes();
self._sortVisibleTypes();
self._rebuildView();
// Notify observers that the UI is now ready
Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService).
notifyObservers(window, "app-handler-pane-loaded", null);
}
setTimeout(_delayedPaneLoad, 0, this);
},
@ -1598,36 +1602,7 @@ var gApplicationsPane = {
* Filter the list when the user enters a filter term into the filter field.
*/
filter: function() {
if (this._filter.value == "") {
this.clearFilter();
return;
}
this._rebuildView();
document.getElementById("clearFilter").disabled = false;
},
_filterTimeout: null,
onFilterInput: function() {
if (this._filterTimeout)
clearTimeout(this._filterTimeout);
this._filterTimeout = setTimeout("gApplicationsPane.filter()", 500);
},
onFilterKeyPress: function(aEvent) {
if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE)
this.clearFilter();
},
clearFilter: function() {
this._filter.value = "";
this._rebuildView();
this._filter.focus();
document.getElementById("clearFilter").disabled = true;
},
focusFilterBox: function() {

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

@ -110,12 +110,11 @@
<key key="&focusSearch2.key;" modifiers="accel" oncommand="gApplicationsPane.focusFilterBox();"/>
</keyset>
<hbox align="center">
<label accesskey="&filter.accesskey;" control="filter">&filter.label;</label>
<textbox id="filter" flex="1" oninput="gApplicationsPane.onFilterInput();"
onkeypress="gApplicationsPane.onFilterKeyPress(event);"/>
<button id="clearFilter" icon="clear" label="&clear.label;" accesskey="&clear.accesskey;"
oncommand="gApplicationsPane.clearFilter();" disabled="true"/>
<hbox>
<textbox id="filter" flex="1"
type="search"
emptytext="&filter.emptytext;"
oncommand="gApplicationsPane.filter();"/>
</hbox>
<separator class="thin"/>

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

@ -163,6 +163,7 @@
<filefield id="downloadFolder" flex="1"
preference="browser.download.folderList"
preference-editable="true"
aria-labelledby="saveTo"
onsyncfrompreference="return gMainPane.displayDownloadDirPref();"
onsynctopreference="return gMainPane.getFolderListPref()"/>
<button id="chooseFolder" oncommand="gMainPane.chooseFolder();"

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

@ -16,28 +16,40 @@ function test() {
getService(Ci.nsIHandlerService);
hserv.store(info);
var obs = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
var observer = {
observe: function(win, topic, data) {
if (topic != "app-handler-pane-loaded")
return;
runTest(win);
obs.removeObserver(observer, "app-handler-pane-loaded");
}
};
obs.addObserver(observer, "app-handler-pane-loaded", false);
openDialog("chrome://browser/content/preferences/preferences.xul", "Preferences",
"chrome,titlebar,toolbar,centerscreen,dialog=no", "paneApplications");
setTimeout(runTest, 1000);
}
function runTest() {
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
var win = wm.getMostRecentWindow("Browser:Preferences");
ok(win, "Pref window opened");
function runTest(win) {
var sel = win.document.documentElement.getAttribute("lastSelected");
ok(sel == "paneApplications", "Specified pane was opened");
if (win) {
var sel = win.document.documentElement.getAttribute("lastSelected");
ok(sel == "paneApplications", "Specified pane was opened");
var rbox = win.document.getElementById("handlersView");
ok(rbox, "handlersView is present");
var rbox = win.document.getElementById("handlersView");
ok(rbox, "handlersView is present");
var items = rbox && rbox.getElementsByTagName("richlistitem");
ok(items && items.length > 0, "App handler list populated");
var items = rbox && rbox.getElementsByTagName("richlistitem");
ok(items && items.length > 0, "App handler list populated");
win.close();
var handlerAdded = false;
for (let i = 0; i < items.length; i++) {
if (items[i].type == "apppanetest")
handlerAdded = true;
}
ok(handlerAdded, "apppanetest protocol handler was successfully added");
win.close();
finish();
}

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

@ -228,10 +228,7 @@ SessionStoreService.prototype = {
this._initialState.session && this._initialState.session.state &&
this._initialState.session.state == STATE_RUNNING_STR;
// restore the features of the first window from localstore.rdf
WINDOW_ATTRIBUTES.forEach(function(aAttr) {
delete this._initialState.windows[0][aAttr];
}, this);
// make sure that at least the first window doesn't have anything hidden
delete this._initialState.windows[0].hidden;
}
catch (ex) { debug("The session file is invalid: " + ex); }

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

@ -222,7 +222,7 @@ static SETTING gSettings[] = {
};
PRBool
nsWindowsShellService::IsDefaultBrowserVista(PRBool aStartupCheck, PRBool* aIsDefaultBrowser)
nsWindowsShellService::IsDefaultBrowserVista(PRBool* aIsDefaultBrowser)
{
#if !defined(MOZ_DISABLE_VISTA_SDK_REQUIREMENTS)
IApplicationAssociationRegistration* pAAR;
@ -232,18 +232,12 @@ nsWindowsShellService::IsDefaultBrowserVista(PRBool aStartupCheck, PRBool* aIsDe
CLSCTX_INPROC,
IID_IApplicationAssociationRegistration,
(void**)&pAAR);
if (SUCCEEDED(hr)) {
hr = pAAR->QueryAppIsDefaultAll(AL_EFFECTIVE,
APP_REG_NAME,
aIsDefaultBrowser);
// If this is the first browser window, maintain internal state that we've
// checked this session (so that subsequent window opens don't show the
// default browser dialog).
if (aStartupCheck)
mCheckedThisSession = PR_TRUE;
pAAR->Release();
return PR_TRUE;
}
@ -316,26 +310,29 @@ nsWindowsShellService::IsDefaultBrowser(PRBool aStartupCheck,
::ZeroMemory(currValue, sizeof(currValue));
HKEY theKey;
rv = OpenKeyForReading(HKEY_CLASSES_ROOT, key, &theKey);
if (NS_SUCCEEDED(rv)) {
DWORD len = sizeof currValue;
DWORD res = ::RegQueryValueExW(theKey, PromiseFlatString(value).get(),
NULL, NULL, (LPBYTE)currValue, &len);
// Close the key we opened.
::RegCloseKey(theKey);
if (REG_FAILED(res) ||
!dataLongPath.Equals(currValue, CaseInsensitiveCompare) &&
!dataShortPath.Equals(currValue, CaseInsensitiveCompare)) {
// Key wasn't set, or was set to something else (something else became the default browser)
*aIsDefaultBrowser = PR_FALSE;
return NS_OK;
}
if (NS_FAILED(rv)) {
*aIsDefaultBrowser = PR_FALSE;
return NS_OK;
}
DWORD len = sizeof currValue;
DWORD res = ::RegQueryValueExW(theKey, PromiseFlatString(value).get(),
NULL, NULL, (LPBYTE)currValue, &len);
// Close the key we opened.
::RegCloseKey(theKey);
if (REG_FAILED(res) ||
!dataLongPath.Equals(currValue, CaseInsensitiveCompare) &&
!dataShortPath.Equals(currValue, CaseInsensitiveCompare)) {
// Key wasn't set, or was set to something other than our registry entry
*aIsDefaultBrowser = PR_FALSE;
return NS_OK;
}
}
// Only check if Firefox is the default browser on Vista if the previous
// checks show that Firefox is the default browser.
if (aIsDefaultBrowser)
IsDefaultBrowserVista(aStartupCheck, aIsDefaultBrowser);
if (*aIsDefaultBrowser)
IsDefaultBrowserVista(aIsDefaultBrowser);
return NS_OK;
}
@ -358,8 +355,8 @@ nsWindowsShellService::SetDefaultBrowser(PRBool aClaimAllTypes, PRBool aForAllUs
rv = appHelper->AppendNative(NS_LITERAL_CSTRING("helper.exe"));
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString appHelperPath;
rv = appHelper->GetNativePath(appHelperPath);
nsAutoString appHelperPath;
rv = appHelper->GetPath(appHelperPath);
NS_ENSURE_SUCCESS(rv, rv);
if (aForAllUsers) {
@ -368,11 +365,11 @@ nsWindowsShellService::SetDefaultBrowser(PRBool aClaimAllTypes, PRBool aForAllUs
appHelperPath.AppendLiteral(" /SetAsDefaultAppUser");
}
STARTUPINFO si = {sizeof(si), 0};
STARTUPINFOW si = {sizeof(si), 0};
PROCESS_INFORMATION pi = {0};
BOOL ok = CreateProcess(NULL, (LPSTR)appHelperPath.get(), NULL, NULL,
FALSE, 0, NULL, NULL, &si, &pi);
BOOL ok = CreateProcessW(NULL, (LPWSTR)appHelperPath.get(), NULL, NULL,
FALSE, 0, NULL, NULL, &si, &pi);
if (!ok)
return NS_ERROR_FAILURE;
@ -766,8 +763,8 @@ nsWindowsShellService::GetUnreadMailCount(PRUint32* aCount)
if (REG_SUCCEEDED(res))
*aCount = unreadCount;
// Close the key we opened.
::RegCloseKey(accountKey);
// Close the key we opened.
::RegCloseKey(accountKey);
}
return NS_OK;

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

@ -57,16 +57,9 @@ public:
NS_DECL_NSIWINDOWSSHELLSERVICE
protected:
PRBool IsDefaultBrowserVista(PRBool aStartupCheck, PRBool* aIsDefaultBrowser);
PRBool IsDefaultBrowserVista(PRBool* aIsDefaultBrowser);
PRBool GetMailAccountKey(HKEY* aResult);
void SetRegKey(const nsString& aKeyName,
const nsString& aValueName,
const nsString& aValue, PRBool aHKLMOnly);
DWORD DeleteRegKey(HKEY baseKey, const nsString& keyName);
DWORD DeleteRegKeyDefaultValue(HKEY baseKey,
const nsString& keyName);
private:
PRBool mCheckedThisSession;

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

@ -1 +1 @@
3.1a1pre
3.1a2pre

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

@ -34,11 +34,14 @@ bin/libmozjs.so
bin/libplc4.so
bin/libplds4.so
bin/libxpcom.so
bin/libxpcom_core.so
bin/libnspr4.so
#ifdef MOZ_ENABLE_LIBXUL
bin/libxul.so
#else
bin/libxpcom_core.so
bin/components/libxpinstall.so
bin/components/libjar50.so
#endif
[browser]
; [Base Browser Files]
@ -111,14 +114,14 @@ bin/components/filepicker.xpt
bin/components/find.xpt
bin/components/fuel.xpt
bin/components/gfx.xpt
bin/components/helperAppDlg.xpt
bin/components/htmlparser.xpt
bin/components/imglib2.xpt
; bin/components/imgicon.xpt
bin/components/intl.xpt
bin/components/jar.xpt
bin/components/jsconsole.xpt
#ifndef MOZ_ENABLE_LIBXUL
bin/components/libjsd.so
#endif
bin/components/libimgicon.so
bin/components/jsdservice.xpt
bin/components/layout_base.xpt
@ -140,7 +143,6 @@ bin/components/necko_dns.xpt
bin/components/necko_file.xpt
bin/components/necko_ftp.xpt
bin/components/necko_http.xpt
bin/components/necko_jar.xpt
bin/components/necko_res.xpt
bin/components/necko_socket.xpt
bin/components/necko_strconv.xpt
@ -152,13 +154,11 @@ bin/components/places.xpt
bin/components/plugin.xpt
bin/components/prefetch.xpt
bin/components/pref.xpt
bin/components/progressDlg.xpt
bin/components/proxyObjInst.xpt
bin/components/toolkitremote.xpt
bin/components/rdf.xpt
bin/components/satchel.xpt
bin/components/saxparser.xpt
bin/components/search.xpt
bin/components/shistory.xpt
bin/components/spellchecker.xpt
bin/components/storage.xpt
@ -172,7 +172,6 @@ bin/components/uriloader.xpt
bin/components/webBrowser_core.xpt
bin/components/webbrowserpersist.xpt
bin/components/webshell_idls.xpt
bin/components/websrvcs.xpt
bin/components/widget.xpt
bin/components/windowds.xpt
bin/components/windowwatcher.xpt
@ -185,7 +184,6 @@ bin/components/xpcom_threads.xpt
bin/components/xpcom_xpti.xpt
bin/components/xpconnect.xpt
bin/components/xpinstall.xpt
bin/components/xremoteservice.xpt
bin/components/xulapp.xpt
bin/components/xuldoc.xpt
bin/components/xultmpl.xpt
@ -211,14 +209,10 @@ bin/components/nsLoginManagerPrompter.js
bin/components/storage-Legacy.js
bin/components/jsconsole-clhandler.js
bin/components/nsTryToClose.js
bin/components/nsDictionary.js
bin/components/nsFilePicker.js
bin/components/nsHelperAppDlg.js
bin/components/nsDownloadManagerUI.js
bin/components/nsInterfaceInfoToIDL.js
; bin/components/nsProgressDialog.js not needed for firefox
bin/components/nsProxyAutoConfig.js
; bin/components/nsResetPref.js not needed for firefox
bin/components/nsSidebar.js
bin/components/nsExtensionManager.js
bin/components/nsBlocklistService.js
@ -253,12 +247,8 @@ bin/components/nsUrlClassifierListManager.js
bin/components/nsUrlClassifierLib.js
bin/components/url-classifier.xpt
; Kerberos NegotiateAuth
bin/components/libauth.so
; GNOME hooks
bin/components/libmozgnome.so
bin/components/mozgnome.xpt
; [Browser Chrome Files]
bin/chrome/browser.jar
@ -299,7 +289,6 @@ bin/res/ua.css
bin/res/html.css
bin/res/quirk.css
bin/res/forms.css
bin/res/platform-forms.css
bin/res/EditorOverride.css
bin/res/contenteditable.css
bin/res/designmode.css
@ -357,7 +346,6 @@ bin/libfreebl3.chk
bin/libfreebl3.so
bin/libssl3.so
bin/libnssdbm3.so
bin/chrome/pipnss.jar
bin/chrome/pippki.jar
bin/chrome/pippki.manifest
@ -383,14 +371,3 @@ bin/Throbber-small.gif
; [Extensions]
;
bin/components/libnkgnomevfs.so
bin/components/libauth.so
; [Additional Developer Tools]
[adt]
bin/extensions/inspector@mozilla.org/install.rdf
bin/extensions/inspector@mozilla.org/components/inspector-cmdline.js
bin/extensions/inspector@mozilla.org/chrome.manifest
bin/extensions/inspector@mozilla.org/chrome/inspector.jar
bin/extensions/inspector@mozilla.org/defaults/preferences/inspector.js
bin/extensions/inspector@mozilla.org/platform/Linux/chrome/icons/default/winInspectorMain.xpm
bin/extensions/inspector@mozilla.org/platform/Linux/chrome/icons/default/winInspectorMain16.xpm

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

@ -48,6 +48,8 @@ SetDatablockOptimize on
SetCompress off
CRCCheck on
RequestExecutionLevel user
!addplugindir ./
; empty files - except for the comment line - for generating custom pages.
@ -70,21 +72,11 @@ Var AddDesktopSC
; The following includes are provided by NSIS.
!include FileFunc.nsh
!include LogicLib.nsh
!include MUI.nsh
!include TextFunc.nsh
!include WinMessages.nsh
!include WinVer.nsh
!include WordFunc.nsh
!include MUI.nsh
; WinVer.nsh was added in the same release that RequestExecutionLevel so check
; if ___WINVER__NSH___ is defined to determine if RequestExecutionLevel is
; available.
!include /NONFATAL WinVer.nsh
!ifdef ___WINVER__NSH___
RequestExecutionLevel user
!else
!warning "Installer will be created without Vista compatibility.$\n \
Upgrade your NSIS installation to at least version 2.22 to resolve."
!endif
!insertmacro GetOptions
!insertmacro GetParameters
@ -105,6 +97,7 @@ Var AddDesktopSC
!include version.nsh
VIAddVersionKey "FileDescription" "${BrandShortName} Installer"
VIAddVersionKey "OriginalFilename" "setup.exe"
; Must be inserted before other macros that use logging
!insertmacro _LoggingCommon
@ -356,6 +349,7 @@ Section "-Application" APP_IDX
SetShellVarContext current ; Set SHCTX to HKCU
${RegCleanMain} "Software\Mozilla"
${RegCleanUninstall}
${UpdateProtocolHandlers}
ClearErrors
WriteRegStr HKLM "Software\Mozilla\InstallerTest" "InstallerTest" "Test"
@ -367,6 +361,7 @@ Section "-Application" APP_IDX
StrCpy $TmpVal "HKLM" ; used primarily for logging
${RegCleanMain} "Software\Mozilla"
${RegCleanUninstall}
${UpdateProtocolHandlers}
ReadRegStr $0 HKLM "Software\mozilla.org\Mozilla" "CurrentVersion"
${If} "$0" != "${GREVersion}"
@ -392,7 +387,6 @@ Section "-Application" APP_IDX
${WriteRegDWORD2} $TmpVal "$0" "Create Start Menu Shortcut" $AddStartMenuSC 0
${FixClassKeys}
${UpdateProtocolHandlers}
; On install always add the FirefoxHTML and FirefoxURL keys.
; An empty string is used for the 5th param because FirefoxHTML is not a

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