Merge from mozilla-central.

--HG--
rename : accessible/src/base/nsRootAccessible.cpp => accessible/src/generic/RootAccessible.cpp
rename : accessible/src/base/nsRootAccessible.h => accessible/src/generic/RootAccessible.h
rename : js/src/jsgcmark.cpp => js/src/gc/Marking.cpp
rename : js/src/jsgcmark.h => js/src/gc/Marking.h
This commit is contained in:
David Anderson 2012-05-04 19:16:35 -07:00
commit 526de59b44
822 changed files with 31612 additions and 12203 deletions

175
.gdbinit Normal file
View File

@ -0,0 +1,175 @@
# .gdbinit file for debugging Mozilla
# Don't stop for the SIG32/33/etc signals that Flash produces
handle SIG32 noprint nostop pass
handle SIG33 noprint nostop pass
handle SIGPIPE noprint nostop pass
# Show the concrete types behind nsIFoo
set print object on
# run when using the auto-solib-add trick
def prun
tbreak main
run
set auto-solib-add 0
cont
end
# run -mail, when using the auto-solib-add trick
def pmail
tbreak main
run -mail
set auto-solib-add 0
cont
end
# Define a "pu" command to display PRUnichar * strings (100 chars max)
# Also allows an optional argument for how many chars to print as long as
# it's less than 100.
def pu
set $uni = $arg0
if $argc == 2
set $limit = $arg1
if $limit > 100
set $limit = 100
end
else
set $limit = 100
end
# scratch array with space for 100 chars plus null terminator. Make
# sure to not use ' ' as the char so this copy/pastes well.
set $scratch = "____________________________________________________________________________________________________"
set $i = 0
set $scratch_idx = 0
while (*$uni && $i++ < $limit)
if (*$uni < 0x80)
set $scratch[$scratch_idx++] = *(char*)$uni++
else
if ($scratch_idx > 0)
set $scratch[$scratch_idx] = '\0'
print $scratch
set $scratch_idx = 0
end
print /x *(short*)$uni++
end
end
if ($scratch_idx > 0)
set $scratch[$scratch_idx] = '\0'
print $scratch
end
end
# Define a "ps" command to display subclasses of nsAC?String. Note that
# this assumes strings as of Gecko 1.9 (well, and probably a few
# releases before that as well); going back far enough will get you
# to string classes that this function doesn't work for.
def ps
set $str = $arg0
if (sizeof(*$str.mData) == 1 && ($str.mFlags & 1) != 0)
print $str.mData
else
pu $str.mData $str.mLength
end
end
# Define a "pa" command to display the string value for an nsIAtom
def pa
set $atom = $arg0
if (sizeof(*((&*$atom)->mString)) == 2)
pu (&*$atom)->mString
end
end
# define a "pxul" command to display the type of a XUL element from
# an nsXULDocument* pointer.
def pxul
set $p = $arg0
print $p->mNodeInfo.mRawPtr->mInner.mName->mStaticAtom->mString
end
# define a "prefcnt" command to display the refcount of an XPCOM obj
def prefcnt
set $p = $arg0
print ((nsPurpleBufferEntry*)$p->mRefCnt.mTagged)->mRefCnt
end
# define a "ptag" command to display the tag name of a content node
def ptag
set $p = $arg0
pa $p->mNodeInfo.mRawPtr->mInner.mName
end
##
## nsTArray
##
define ptarray
if $argc == 0
help ptarray
else
set $size = $arg0.mHdr->mLength
set $capacity = $arg0.mHdr->mCapacity
set $size_max = $size - 1
set $elts = $arg0.Elements()
end
if $argc == 1
set $i = 0
while $i < $size
printf "elem[%u]: ", $i
p *($elts + $i)
set $i++
end
end
if $argc == 2
set $idx = $arg1
if $idx < 0 || $idx > $size_max
printf "idx1, idx2 are not in acceptable range: [0..%u].\n", $size_max
else
printf "elem[%u]: ", $idx
p *($elts + $idx)
end
end
if $argc == 3
set $start_idx = $arg1
set $stop_idx = $arg2
if $start_idx > $stop_idx
set $tmp_idx = $start_idx
set $start_idx = $stop_idx
set $stop_idx = $tmp_idx
end
if $start_idx < 0 || $stop_idx < 0 || $start_idx > $size_max || $stop_idx > $size_max
printf "idx1, idx2 are not in acceptable range: [0..%u].\n", $size_max
else
set $i = $start_idx
while $i <= $stop_idx
printf "elem[%u]: ", $i
p *($elts + $i)
set $i++
end
end
end
if $argc > 0
printf "nsTArray length = %u\n", $size
printf "nsTArray capacity = %u\n", $capacity
printf "Element "
whatis *$elts
end
end
document ptarray
Prints nsTArray information.
Syntax: ptarray
Note: idx, idx1 and idx2 must be in acceptable range [0...size()-1].
Examples:
ptarray a - Prints tarray content, size, capacity and T typedef
ptarray a 0 - Prints element[idx] from tarray
ptarray a 1 2 - Prints elements in range [idx1..idx2] from tarray
end
def js
call DumpJSStack()
end
def ft
call nsFrame::DumpFrameTree($arg0)
end

View File

@ -13,7 +13,7 @@
# User files that may appear at the root
^\.mozconfig
^mozconfig$
^mozconfig*
^configure$
^config\.cache$
^config\.log$
@ -44,4 +44,3 @@ _OPT\.OBJ/
\.project$
\.cproject$
\.settings/

View File

@ -237,6 +237,10 @@ maybe_clobber_profiledbuild:
find $(DIST)/$(MOZ_APP_NAME) -name "*.pgc" -exec mv {} $(DIST)/bin \;
endif
# put in our default gdbinit so that the gdb debugging experience is happier.
libs:: .gdbinit
$(INSTALL) $< $(DIST)/bin
.PHONY: maybe_clobber_profiledbuild
# Look for R_386_PC32 relocations in shared libs, these

View File

@ -837,11 +837,11 @@ which is handled in <a
via the creation of an <a
href="http://lxr.mozilla.org/seamonkey/find?string=msaa/nsDocAccessibleWrap">nsDocAccessibleWrap</a>
for an inner window or <a
href="http://lxr.mozilla.org/seamonkey/find?string=msaa/nsRootAccessibleWrap">nsRootAccessibleWrap</a>
href="http://lxr.mozilla.org/seamonkey/find?string=msaa/RootAccessibleWrap">RootAccessibleWrap</a>
for a top level window. These classes implement both nsIAccessible, our
cross platform API, as well as IAccessible, which is specific to
Windows/MSAA/COM. The cross-platform nsDocAccessible and
nsRootAccessible classes they inherit from are then told to start
RootAccessible classes they inherit from are then told to start
listening for DOM, page load and scroll events.&nbsp; These events cause
MSAA-specific events, such as EVENT_OBJECT_FOCUS or
EVENT_OBJECT_STATECHANGE, to fire on UI and document objects within the
@ -970,7 +970,7 @@ important one is EVENT_OBJECT_FOCUS.<br>
</p>
<p>When a potential accessibility-related event occurs within
Mozilla, it is typically listened for by nsDocAccessible or
nsRootAccessible. The event listeners on these classes call
RootAccessible. The event listeners on these classes call
FireToolkitEvent(), which is implemented for every accessible.
Eventually, the event ends up at nsDocAccessibleWrap::FireToolkitEvent()
which calls NotifyWinEvent from the Win32 API. NotifyWinEvent is passed

View File

@ -52,7 +52,6 @@ CPPSRCS = \
nsAccessNodeWrap.cpp \
nsAccessibleWrap.cpp \
nsDocAccessibleWrap.cpp \
nsRootAccessibleWrap.cpp \
ApplicationAccessibleWrap.cpp \
nsMaiInterfaceComponent.cpp \
nsMaiInterfaceAction.cpp \
@ -66,6 +65,7 @@ CPPSRCS = \
nsMaiInterfaceTable.cpp \
nsMaiInterfaceDocument.cpp \
nsMaiInterfaceImage.cpp \
RootAccessibleWrap.cpp \
$(NULL)
EXPORTS = \
@ -74,7 +74,6 @@ EXPORTS = \
nsAccessNodeWrap.h \
nsAccessibleWrap.h \
nsDocAccessibleWrap.h \
nsRootAccessibleWrap.h \
nsTextAccessibleWrap.h \
nsXULMenuAccessibleWrap.h \
nsXULListboxAccessibleWrap.h \

View File

@ -38,11 +38,14 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsMai.h"
#include "nsRootAccessibleWrap.h"
#include "RootAccessibleWrap.h"
nsNativeRootAccessibleWrap::nsNativeRootAccessibleWrap(AtkObject *aAccessible):
nsRootAccessible(nsnull, nsnull, nsnull)
#include "nsMai.h"
using namespace mozilla::a11y;
NativeRootAccessibleWrap::NativeRootAccessibleWrap(AtkObject* aAccessible):
RootAccessible(nsnull, nsnull, nsnull)
{
// XXX: mark the object as defunct to ensure no single internal method is
// running on it.
@ -52,7 +55,7 @@ nsNativeRootAccessibleWrap::nsNativeRootAccessibleWrap(AtkObject *aAccessible):
mAtkObject = aAccessible;
}
nsNativeRootAccessibleWrap::~nsNativeRootAccessibleWrap()
NativeRootAccessibleWrap::~NativeRootAccessibleWrap()
{
g_object_unref(mAtkObject);
mAtkObject = nsnull;

View File

@ -38,23 +38,30 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef __NS_ROOT_ACCESSIBLE_WRAP_H__
#define __NS_ROOT_ACCESSIBLE_WRAP_H__
#ifndef mozilla_a11y_RootAccessibleWrap_h__
#define mozilla_a11y_RootAccessibleWrap_h__
#include "nsRootAccessible.h"
#include "RootAccessible.h"
typedef nsRootAccessible nsRootAccessibleWrap;
namespace mozilla {
namespace a11y {
/* nsNativeRootAccessibleWrap is the accessible class for gtk+ native window.
* The instance of nsNativeRootAccessibleWrap is a child of MaiAppRoot instance.
typedef RootAccessible RootAccessibleWrap;
/* NativeRootAccessibleWrap is the accessible class for gtk+ native window.
* The instance of NativeRootAccessibleWrap is a child of MaiAppRoot instance.
* It is added into root when the toplevel window is created, and removed
* from root when the toplevel window is destroyed.
*/
class nsNativeRootAccessibleWrap: public nsRootAccessible
class NativeRootAccessibleWrap : public RootAccessible
{
public:
nsNativeRootAccessibleWrap(AtkObject *aAccessible);
~nsNativeRootAccessibleWrap();
NativeRootAccessibleWrap(AtkObject* aAccessible);
virtual ~NativeRootAccessibleWrap();
};
#endif /* __NS_ROOT_ACCESSIBLE_WRAP_H__ */
} // namespace a11y
} // namespace mozilla
#endif /* mozilla_a11y_Root_Accessible_Wrap_h__ */

View File

@ -45,8 +45,7 @@
#include "InterfaceInitFuncs.h"
#include "nsAccUtils.h"
#include "nsIAccessibleRelation.h"
#include "nsRootAccessible.h"
#include "nsDocAccessibleWrap.h"
#include "RootAccessible.h"
#include "nsIAccessibleValue.h"
#include "nsMai.h"
#include "nsMaiHyperlink.h"
@ -55,6 +54,7 @@
#include "prprf.h"
#include "nsStateMap.h"
#include "Relation.h"
#include "RootAccessible.h"
#include "States.h"
#include "mozilla/Util.h"
@ -729,8 +729,21 @@ getRoleCB(AtkObject *aAtkObj)
if (aAtkObj->role != ATK_ROLE_INVALID)
return aAtkObj->role;
return aAtkObj->role =
static_cast<AtkRole>(nsAccessibleWrap::AtkRoleFor(accWrap->Role()));
#define ROLE(geckoRole, stringRole, atkRole, macRole, msaaRole, ia2Role) \
case roles::geckoRole: \
aAtkObj->role = atkRole; \
break;
switch (accWrap->Role()) {
#include "RoleMap.h"
default:
MOZ_NOT_REACHED("Unknown role.");
aAtkObj->role = ATK_ROLE_UNKNOWN;
};
#undef ROLE
return aAtkObj->role;
}
AtkAttributeSet*
@ -1027,7 +1040,7 @@ nsAccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
case nsIAccessibleEvent::EVENT_FOCUS:
{
MAI_LOG_DEBUG(("\n\nReceived: EVENT_FOCUS\n"));
nsRootAccessible* rootAccWrap = accWrap->RootAccessible();
a11y::RootAccessible* rootAccWrap = accWrap->RootAccessible();
if (rootAccWrap && rootAccWrap->mActivated) {
atk_focus_tracker_notify(atkObj);
// Fire state change event for focus
@ -1220,9 +1233,7 @@ nsAccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
case nsIAccessibleEvent::EVENT_WINDOW_ACTIVATE:
{
MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_ACTIVATED\n"));
nsRootAccessible *rootAcc =
static_cast<nsRootAccessible *>(accessible);
rootAcc->mActivated = true;
accessible->AsRoot()->mActivated = true;
guint id = g_signal_lookup ("activate", MAI_TYPE_ATK_OBJECT);
g_signal_emit(atkObj, id, 0);
@ -1233,9 +1244,7 @@ nsAccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
case nsIAccessibleEvent::EVENT_WINDOW_DEACTIVATE:
{
MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_DEACTIVATED\n"));
nsRootAccessible *rootAcc =
static_cast<nsRootAccessible *>(accessible);
rootAcc->mActivated = false;
accessible->AsRoot()->mActivated = false;
guint id = g_signal_lookup ("deactivate", MAI_TYPE_ATK_OBJECT);
g_signal_emit(atkObj, id, 0);
} break;
@ -1390,20 +1399,3 @@ nsAccessibleWrap::FireAtkShowHideEvent(AccEvent* aEvent,
return NS_OK;
}
PRUint32
nsAccessibleWrap::AtkRoleFor(role aRole)
{
#define ROLE(geckoRole, stringRole, atkRole, macRole, msaaRole, ia2Role) \
case roles::geckoRole: \
return atkRole;
switch (aRole) {
#include "RoleMap.h"
default:
MOZ_NOT_REACHED("Unknown role.");
return ATK_ROLE_UNKNOWN;
}
#undef ROLE
}

View File

@ -116,11 +116,6 @@ public:
return returnedString.get();
}
/**
* Function mapping from cross platform roles to ATK roles.
*/
static PRUint32 AtkRoleFor(mozilla::a11y::role aRole);
protected:
virtual nsresult FirePlatformEvent(AccEvent* aEvent);

View File

@ -45,14 +45,15 @@
#include "nsIPersistentProperties2.h"
using namespace mozilla::a11y;
AtkAttributeSet* ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes);
static void
ConvertTexttoAsterisks(nsAccessibleWrap* accWrap, nsAString& aString)
{
// convert each char to "*" when it's "password text"
PRUint32 atkRole = nsAccessibleWrap::AtkRoleFor(accWrap->NativeRole());
if (atkRole == ATK_ROLE_PASSWORD_TEXT) {
if (accWrap->NativeRole() == roles::PASSWORD_TEXT) {
for (PRUint32 i = 0; i < aString.Length(); i++)
aString.Replace(i, 1, NS_LITERAL_STRING("*"));
}
@ -142,9 +143,9 @@ getTextAtOffsetCB(AtkText *aText, gint aOffset,
}
static gunichar
getCharacterAtOffsetCB(AtkText *aText, gint aOffset)
getCharacterAtOffsetCB(AtkText* aText, gint aOffset)
{
nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
nsAccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
if (!accWrap)
return 0;
@ -153,18 +154,18 @@ getCharacterAtOffsetCB(AtkText *aText, gint aOffset)
getter_AddRefs(accText));
NS_ENSURE_TRUE(accText, 0);
/* PRUnichar is unsigned short in Mozilla */
/* gnuichar is guint32 in glib */
PRUnichar uniChar;
nsresult rv =
accText->GetCharacterAtOffset(aOffset, &uniChar);
// PRUnichar is unsigned short in Mozilla
// gnuichar is guint32 in glib
PRUnichar uniChar = 0;
nsresult rv = accText->GetCharacterAtOffset(aOffset, &uniChar);
if (NS_FAILED(rv))
return 0;
// convert char to "*" when it's "password text"
PRUint32 atkRole = nsAccessibleWrap::AtkRoleFor(accWrap->NativeRole());
if (atkRole == ATK_ROLE_PASSWORD_TEXT)
// Convert char to "*" when it's "password text".
if (accWrap->NativeRole() == roles::PASSWORD_TEXT)
uniChar = '*';
return (NS_FAILED(rv)) ? 0 : static_cast<gunichar>(uniChar);
return static_cast<gunichar>(uniChar);
}
static gchar*

View File

@ -40,8 +40,8 @@
#include "Accessible-inl.h"
#include "nsAccessibilityService.h"
#include "nsAccUtils.h"
#include "nsRootAccessible.h"
#include "Role.h"
#include "RootAccessible.h"
#include "nsEventStateManager.h"
#include "nsFocusManager.h"
@ -157,7 +157,7 @@ FocusManager::NotifyOfDOMFocus(nsISupports* aTarget)
if (document) {
// Set selection listener for focused element.
if (targetNode->IsElement()) {
nsRootAccessible* root = document->RootAccessible();
RootAccessible* root = document->RootAccessible();
nsCaretAccessible* caretAcc = root->GetCaretAccessible();
caretAcc->SetControlSelectionListener(targetNode->AsElement());
}

View File

@ -68,7 +68,6 @@ CPPSRCS = \
nsAccTreeWalker.cpp \
nsBaseWidgetAccessible.cpp \
nsEventShell.cpp \
nsRootAccessible.cpp \
nsCaretAccessible.cpp \
nsTextAccessible.cpp \
nsTextEquivUtils.cpp \

View File

@ -814,7 +814,7 @@ enum Role {
/**
* Represent a definition in a definition list (dd in HTML)
*/
DEFINITION = 128,
DEFINITION = 128
};
} // namespace role

View File

@ -42,7 +42,7 @@
#include "nsAccessibilityService.h"
#include "nsAccUtils.h"
#include "nsARIAMap.h"
#include "nsRootAccessibleWrap.h"
#include "RootAccessibleWrap.h"
#include "States.h"
#include "nsCURILoader.h"
@ -356,7 +356,7 @@ nsAccDocManager::AddListeners(nsIDocument *aDocument,
}
nsDocAccessible*
nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
nsAccDocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
{
// Ignore temporary, hiding, resource documents and documents without
// docshell.
@ -391,7 +391,7 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
// We only create root accessibles for the true root, otherwise create a
// doc accessible.
nsRefPtr<nsDocAccessible> docAcc = isRootDoc ?
new nsRootAccessibleWrap(aDocument, rootElm, presShell) :
new RootAccessibleWrap(aDocument, rootElm, presShell) :
new nsDocAccessibleWrap(aDocument, rootElm, presShell);
// Cache the document accessible into document cache.

View File

@ -42,7 +42,7 @@
#include "nsAccessibilityService.h"
#include "nsAccUtils.h"
#include "nsCoreUtils.h"
#include "nsRootAccessible.h"
#include "RootAccessible.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
@ -59,6 +59,8 @@
#include "nsPresContext.h"
#include "mozilla/Services.h"
using namespace mozilla::a11y;
/* For documentation of the accessibility architecture,
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
*/
@ -92,9 +94,6 @@ nsAccessNode::
nsAccessNode(nsIContent* aContent, nsDocAccessible* aDoc) :
mContent(aContent), mDoc(aDoc)
{
#ifdef DEBUG_A11Y
mIsInitialized = false;
#endif
}
nsAccessNode::~nsAccessNode()
@ -207,7 +206,7 @@ void nsAccessNode::ShutdownXPAccessibility()
NotifyA11yInitOrShutdown(false);
}
nsRootAccessible*
RootAccessible*
nsAccessNode::RootAccessible() const
{
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =

View File

@ -57,7 +57,12 @@ class ApplicationAccessible;
class nsAccessNode;
class nsDocAccessible;
class nsIAccessibleDocument;
class nsRootAccessible;
namespace mozilla {
namespace a11y {
class RootAccessible;
}
}
class nsIPresShell;
class nsPresContext;
@ -93,7 +98,7 @@ public:
/**
* Return the root document accessible for this accessnode.
*/
nsRootAccessible* RootAccessible() const;
mozilla::a11y::RootAccessible* RootAccessible() const;
/**
* Initialize the access node object, add it to the cache.

View File

@ -57,11 +57,11 @@
#include "nsHTMLTableAccessibleWrap.h"
#include "nsHTMLTextAccessible.h"
#include "nsHyperTextAccessibleWrap.h"
#include "nsRootAccessibleWrap.h"
#include "nsXFormsFormControlsAccessible.h"
#include "nsXFormsWidgetsAccessible.h"
#include "OuterDocAccessible.h"
#include "Role.h"
#include "RootAccessibleWrap.h"
#include "States.h"
#include "Statistics.h"
#ifdef XP_WIN
@ -657,7 +657,7 @@ nsAccessibilityService::PresShellActivated(nsIPresShell* aPresShell)
if (DOMDoc) {
nsDocAccessible* document = GetDocAccessibleFromCache(DOMDoc);
if (document) {
nsRootAccessible* rootDocument = document->RootAccessible();
RootAccessible* rootDocument = document->RootAccessible();
NS_ASSERTION(rootDocument, "Entirely broken tree: no root document!");
if (rootDocument)
rootDocument->DocumentActivated(document);
@ -1728,15 +1728,15 @@ nsAccessibilityService::CreateHTMLAccessibleByMarkup(nsIFrame* aFrame,
nsAccessible*
nsAccessibilityService::AddNativeRootAccessible(void* aAtkAccessible)
{
{
#ifdef MOZ_ACCESSIBILITY_ATK
ApplicationAccessible* applicationAcc =
nsAccessNode::GetApplicationAccessible();
if (!applicationAcc)
return nsnull;
nsRefPtr<nsNativeRootAccessibleWrap> nativeRootAcc =
new nsNativeRootAccessibleWrap((AtkObject*)aAtkAccessible);
nsRefPtr<NativeRootAccessibleWrap> nativeRootAcc =
new NativeRootAccessibleWrap(static_cast<AtkObject*>(aAtkAccessible));
if (!nativeRootAcc)
return nsnull;
@ -1745,7 +1745,7 @@ nsAccessibilityService::AddNativeRootAccessible(void* aAtkAccessible)
#endif
return nsnull;
}
}
void
nsAccessibilityService::RemoveNativeRootAccessible(nsAccessible* aAccessible)

View File

@ -50,10 +50,10 @@
#include "nsAccTreeWalker.h"
#include "nsIAccessibleRelation.h"
#include "nsEventShell.h"
#include "nsRootAccessible.h"
#include "nsTextEquivUtils.h"
#include "Relation.h"
#include "Role.h"
#include "RootAccessible.h"
#include "States.h"
#include "StyleInfo.h"
@ -257,8 +257,7 @@ nsAccessible::GetRootDocument(nsIAccessibleDocument **aRootDocument)
{
NS_ENSURE_ARG_POINTER(aRootDocument);
nsRootAccessible* rootDocument = RootAccessible();
NS_IF_ADDREF(*aRootDocument = rootDocument);
NS_IF_ADDREF(*aRootDocument = RootAccessible());
return NS_OK;
}

View File

@ -489,7 +489,7 @@ public:
inline bool IsMenuPopup() const { return mFlags & eMenuPopupAccessible; }
inline bool IsRoot() const { return mFlags & eRootAccessible; }
nsRootAccessible* AsRoot();
mozilla::a11y::RootAccessible* AsRoot();
virtual mozilla::a11y::TableAccessible* AsTable() { return nsnull; }

View File

@ -41,6 +41,7 @@
#include "nsAccUtils.h"
#include "nsCoreUtils.h"
#include "nsIAccessibleEvent.h"
#include "RootAccessible.h"
#include "nsCaret.h"
#include "nsIDOMDocument.h"
@ -49,15 +50,16 @@
#include "nsIDOMHTMLTextAreaElement.h"
#include "nsIFrame.h"
#include "nsIPresShell.h"
#include "nsRootAccessible.h"
#include "nsISelectionPrivate.h"
#include "nsServiceManagerUtils.h"
class nsIWidget;
using namespace mozilla::a11y;
NS_IMPL_ISUPPORTS1(nsCaretAccessible, nsISelectionListener)
nsCaretAccessible::nsCaretAccessible( nsRootAccessible *aRootAccessible):
nsCaretAccessible::nsCaretAccessible(RootAccessible* aRootAccessible) :
mLastCaretOffset(-1), mRootAccessible(aRootAccessible)
{
}
@ -68,8 +70,8 @@ nsCaretAccessible::~nsCaretAccessible()
void nsCaretAccessible::Shutdown()
{
// The caret accessible isn't shut down until the nsRootAccessible owning it is shut down
// Each nsDocAccessible, including the nsRootAccessible, is responsible for clearing the
// The caret accessible isn't shut down until the RootAccessible owning it is shut down
// Each nsDocAccessible, including the RootAccessible, is responsible for clearing the
// doc selection listeners they registered in this nsCaretAccessible
ClearControlSelectionListener(); // Clear the selection listener for the currently focused control

View File

@ -43,11 +43,9 @@
#include "nsISelectionListener.h"
class nsRootAccessible;
/*
* This special accessibility class is for the caret, which is really the currently focused selection.
* There is only 1 visible caret per top level window (nsRootAccessible),
* There is only 1 visible caret per top level window (RootAccessible),
* However, there may be several visible selections.
*
* The important selections are the one owned by each document, and the one in the currently focused control.
@ -59,8 +57,8 @@ class nsRootAccessible;
* For ATK and Iaccessible2, the caret accessible is used to fire
* caret move and selection change events.
*
* The caret accessible is owned by the nsRootAccessible for the top level window that it's in.
* The nsRootAccessible needs to tell the nsCaretAccessible about focus changes via
* The caret accessible is owned by the RootAccessible for the top level window that it's in.
* The RootAccessible needs to tell the nsCaretAccessible about focus changes via
* setControlSelectionListener().
* Each nsDocAccessible needs to tell the nsCaretAccessible owned by the root to
* listen for selection events via addDocSelectionListener() and then needs to remove the
@ -72,7 +70,7 @@ class nsCaretAccessible : public nsISelectionListener
public:
NS_DECL_ISUPPORTS
nsCaretAccessible(nsRootAccessible *aRootAccessible);
nsCaretAccessible(mozilla::a11y::RootAccessible* aRootAccessible);
virtual ~nsCaretAccessible();
void Shutdown();
@ -155,7 +153,7 @@ private:
nsRefPtr<nsHyperTextAccessible> mLastTextAccessible;
PRInt32 mLastCaretOffset;
nsRootAccessible *mRootAccessible;
mozilla::a11y::RootAccessible* mRootAccessible;
};
#endif

View File

@ -43,9 +43,9 @@
#include "nsAccessiblePivot.h"
#include "nsAccTreeWalker.h"
#include "nsAccUtils.h"
#include "nsRootAccessible.h"
#include "nsTextEquivUtils.h"
#include "Role.h"
#include "RootAccessible.h"
#include "States.h"
#include "nsIMutableArray.h"
@ -764,7 +764,7 @@ nsresult nsDocAccessible::AddEventListeners()
nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
docShellTreeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
if (rootTreeItem) {
nsRootAccessible* rootAccessible = RootAccessible();
a11y::RootAccessible* rootAccessible = RootAccessible();
NS_ENSURE_TRUE(rootAccessible, NS_ERROR_FAILURE);
nsRefPtr<nsCaretAccessible> caretAccessible = rootAccessible->GetCaretAccessible();
if (caretAccessible) {
@ -811,7 +811,7 @@ nsresult nsDocAccessible::RemoveEventListeners()
NS_RELEASE_THIS(); // Kung fu death grip
}
nsRootAccessible* rootAccessible = RootAccessible();
a11y::RootAccessible* rootAccessible = RootAccessible();
if (rootAccessible) {
nsRefPtr<nsCaretAccessible> caretAccessible = rootAccessible->GetCaretAccessible();
if (caretAccessible)
@ -1767,11 +1767,6 @@ nsDocAccessible::ProcessPendingEvent(AccEvent* aEvent)
PRInt32 caretOffset;
if (hyperText &&
NS_SUCCEEDED(hyperText->GetCaretOffset(&caretOffset))) {
#ifdef DEBUG_A11Y
PRUnichar chAtOffset;
hyperText->GetCharacterAtOffset(caretOffset, &chAtOffset);
printf("\nCaret moved to %d with char %c", caretOffset, chAtOffset);
#endif
nsRefPtr<AccEvent> caretMoveEvent =
new AccCaretMoveEvent(hyperText, caretOffset);
nsEventShell::FireEvent(caretMoveEvent);

View File

@ -19,6 +19,7 @@ CPPSRCS = \
ARIAGridAccessible.cpp \
FormControlAccessible.cpp \
OuterDocAccessible.cpp \
RootAccessible.cpp \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a static lib.
@ -29,6 +30,8 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES = \
-I$(srcdir)/../xpcom \
-I$(srcdir)/../base \
-I$(srcdir)/../html \
-I$(srcdir)/../xul \
-I$(srcdir)/../../../layout/generic \
-I$(srcdir)/../../../layout/xul/base/src \
$(NULL)

View File

@ -35,6 +35,8 @@
*
* ***** END LICENSE BLOCK ***** */
#include "RootAccessible.h"
#include "mozilla/Util.h"
#define CreateEvent CreateEventA
@ -76,7 +78,6 @@
#include "nsPIDOMWindow.h"
#include "nsIWebBrowserChrome.h"
#include "nsReadableUtils.h"
#include "nsRootAccessible.h"
#include "nsIPrivateDOMEvent.h"
#include "nsFocusManager.h"
@ -92,20 +93,20 @@ using namespace mozilla::a11y;
////////////////////////////////////////////////////////////////////////////////
// nsISupports
NS_IMPL_ISUPPORTS_INHERITED1(nsRootAccessible, nsDocAccessible, nsIAccessibleDocument)
NS_IMPL_ISUPPORTS_INHERITED1(RootAccessible, nsDocAccessible, nsIAccessibleDocument)
////////////////////////////////////////////////////////////////////////////////
// Constructor/desctructor
// Constructor/destructor
nsRootAccessible::
nsRootAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
RootAccessible::
RootAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
nsIPresShell* aPresShell) :
nsDocAccessibleWrap(aDocument, aRootContent, aPresShell)
{
mFlags |= eRootAccessible;
}
nsRootAccessible::~nsRootAccessible()
RootAccessible::~RootAccessible()
{
}
@ -113,7 +114,7 @@ nsRootAccessible::~nsRootAccessible()
// nsAccessible
ENameValueFlag
nsRootAccessible::Name(nsString& aName)
RootAccessible::Name(nsString& aName)
{
aName.Truncate();
@ -124,12 +125,13 @@ nsRootAccessible::Name(nsString& aName)
}
nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(mDocument);
NS_ENSURE_TRUE(document, eNameOK);
document->GetTitle(aName);
return eNameOK;
}
role
nsRootAccessible::NativeRole()
RootAccessible::NativeRole()
{
// If it's a <dialog> or <wizard>, use roles::DIALOG instead
dom::Element *root = mDocument->GetRootElement();
@ -147,9 +149,10 @@ nsRootAccessible::NativeRole()
return nsDocAccessibleWrap::NativeRole();
}
// nsRootAccessible protected member
// RootAccessible protected member
#ifdef MOZ_XUL
PRUint32 nsRootAccessible::GetChromeFlags()
PRUint32
RootAccessible::GetChromeFlags()
{
// Return the flag set for the top level window as defined
// by nsIWebBrowserChrome::CHROME_WINDOW_[FLAGNAME]
@ -171,7 +174,7 @@ PRUint32 nsRootAccessible::GetChromeFlags()
#endif
PRUint64
nsRootAccessible::NativeState()
RootAccessible::NativeState()
{
PRUint64 states = nsDocAccessibleWrap::NativeState();
@ -231,7 +234,8 @@ const char* const docEvents[] = {
"DOMMenuBarInactive"
};
nsresult nsRootAccessible::AddEventListeners()
nsresult
RootAccessible::AddEventListeners()
{
// nsIDOMEventTarget interface allows to register event listeners to
// receive untrusted events (synthetic events generated by untrusted code).
@ -256,7 +260,8 @@ nsresult nsRootAccessible::AddEventListeners()
return nsDocAccessible::AddEventListeners();
}
nsresult nsRootAccessible::RemoveEventListeners()
nsresult
RootAccessible::RemoveEventListeners()
{
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mDocument));
if (target) {
@ -284,13 +289,13 @@ nsresult nsRootAccessible::RemoveEventListeners()
// public
nsCaretAccessible*
nsRootAccessible::GetCaretAccessible()
RootAccessible::GetCaretAccessible()
{
return mCaretAccessible;
}
void
nsRootAccessible::DocumentActivated(nsDocAccessible* aDocument)
RootAccessible::DocumentActivated(nsDocAccessible* aDocument)
{
}
@ -298,7 +303,7 @@ nsRootAccessible::DocumentActivated(nsDocAccessible* aDocument)
// nsIDOMEventListener
NS_IMETHODIMP
nsRootAccessible::HandleEvent(nsIDOMEvent* aDOMEvent)
RootAccessible::HandleEvent(nsIDOMEvent* aDOMEvent)
{
nsCOMPtr<nsIDOMNSEvent> DOMNSEvent(do_QueryInterface(aDOMEvent));
nsCOMPtr<nsIDOMEventTarget> DOMEventTarget;
@ -335,16 +340,16 @@ nsRootAccessible::HandleEvent(nsIDOMEvent* aDOMEvent)
// Root accessible exists longer than any of its descendant documents so
// that we are guaranteed notification is processed before root accessible
// is destroyed.
document->HandleNotification<nsRootAccessible, nsIDOMEvent>
(this, &nsRootAccessible::ProcessDOMEvent, aDOMEvent);
document->HandleNotification<RootAccessible, nsIDOMEvent>
(this, &RootAccessible::ProcessDOMEvent, aDOMEvent);
}
return NS_OK;
}
// nsRootAccessible protected
// RootAccessible protected
void
nsRootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
{
nsCOMPtr<nsIDOMNSEvent> DOMNSEvent(do_QueryInterface(aDOMEvent));
nsCOMPtr<nsIDOMEventTarget> DOMEventTarget;
@ -534,7 +539,7 @@ nsRootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
// nsAccessNode
void
nsRootAccessible::Shutdown()
RootAccessible::Shutdown()
{
// Called manually or by nsAccessNode::LastRelease()
if (!PresShell())
@ -545,7 +550,7 @@ nsRootAccessible::Shutdown()
// nsIAccessible method
Relation
nsRootAccessible::RelationByType(PRUint32 aType)
RootAccessible::RelationByType(PRUint32 aType)
{
if (!mDocument || aType != nsIAccessibleRelation::RELATION_EMBEDS)
return nsDocAccessibleWrap::RelationByType(aType);
@ -575,7 +580,7 @@ nsRootAccessible::RelationByType(PRUint32 aType)
// Protected members
void
nsRootAccessible::HandlePopupShownEvent(nsAccessible* aAccessible)
RootAccessible::HandlePopupShownEvent(nsAccessible* aAccessible)
{
roles::Role role = aAccessible->Role();
@ -613,7 +618,7 @@ nsRootAccessible::HandlePopupShownEvent(nsAccessible* aAccessible)
}
void
nsRootAccessible::HandlePopupHidingEvent(nsINode* aPopupNode)
RootAccessible::HandlePopupHidingEvent(nsINode* aPopupNode)
{
// Get popup accessible. There are cases when popup element isn't accessible
// but an underlying widget is and behaves like popup, an example is
@ -718,7 +723,7 @@ nsRootAccessible::HandlePopupHidingEvent(nsINode* aPopupNode)
#ifdef MOZ_XUL
void
nsRootAccessible::HandleTreeRowCountChangedEvent(nsIDOMEvent* aEvent,
RootAccessible::HandleTreeRowCountChangedEvent(nsIDOMEvent* aEvent,
nsXULTreeAccessible* aAccessible)
{
nsCOMPtr<nsIDOMDataContainerEvent> dataEvent(do_QueryInterface(aEvent));
@ -745,7 +750,7 @@ nsRootAccessible::HandleTreeRowCountChangedEvent(nsIDOMEvent* aEvent,
}
void
nsRootAccessible::HandleTreeInvalidatedEvent(nsIDOMEvent* aEvent,
RootAccessible::HandleTreeInvalidatedEvent(nsIDOMEvent* aEvent,
nsXULTreeAccessible* aAccessible)
{
nsCOMPtr<nsIDOMDataContainerEvent> dataEvent(do_QueryInterface(aEvent));

View File

@ -35,8 +35,8 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef _nsRootAccessible_H_
#define _nsRootAccessible_H_
#ifndef mozilla_a11y_RootAccessible_h__
#define mozilla_a11y_RootAccessible_h__
#include "nsCaretAccessible.h"
#include "nsDocAccessibleWrap.h"
@ -50,17 +50,18 @@
class nsXULTreeAccessible;
class Relation;
const PRInt32 SCROLL_HASH_START_SIZE = 6;
namespace mozilla {
namespace a11y {
class nsRootAccessible : public nsDocAccessibleWrap,
class RootAccessible : public nsDocAccessibleWrap,
public nsIDOMEventListener
{
NS_DECL_ISUPPORTS_INHERITED
public:
nsRootAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
RootAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
nsIPresShell* aPresShell);
virtual ~nsRootAccessible();
virtual ~RootAccessible();
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
@ -74,7 +75,7 @@ public:
virtual mozilla::a11y::role NativeRole();
virtual PRUint64 NativeState();
// nsRootAccessible
// RootAccessible
nsCaretAccessible* GetCaretAccessible();
/**
@ -117,11 +118,14 @@ protected:
nsRefPtr<nsCaretAccessible> mCaretAccessible;
};
inline nsRootAccessible*
} // namespace a11y
} // namespace mozilla
inline mozilla::a11y::RootAccessible*
nsAccessible::AsRoot()
{
return mFlags & eRootAccessible ?
static_cast<nsRootAccessible*>(this) : nsnull;
static_cast<mozilla::a11y::RootAccessible*>(this) : nsnull;
}
#endif

View File

@ -1297,10 +1297,8 @@ nsHTMLTableAccessible::Description(nsString& aDescription)
bool isProbablyForLayout = IsProbablyLayoutTable();
aDescription = mLayoutHeuristic;
}
#ifdef DEBUG_A11Y
printf("\nTABLE: %s\n", NS_ConvertUTF16toUTF8(mLayoutHeuristic).get());
#endif
#endif
}
bool

View File

@ -16,6 +16,10 @@ Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/accessibility/Presenters.jsm');
Cu.import('resource://gre/modules/accessibility/VirtualCursorController.jsm');
const ACCESSFU_DISABLE = 0;
const ACCESSFU_ENABLE = 1;
const ACCESSFU_AUTO = 2;
var AccessFu = {
/**
* Attach chrome-layer accessibility functionality to the given chrome window.
@ -26,27 +30,25 @@ var AccessFu = {
* AccessFu.
*/
attach: function attach(aWindow) {
if (this.chromeWin)
// XXX: only supports attaching to one window now.
throw new Error('Only one window could be attached to AccessFu');
dump('AccessFu attach!! ' + Services.appinfo.OS + '\n');
this.chromeWin = aWindow;
this.presenters = [];
function checkA11y() {
if (Services.appinfo.OS == 'Android') {
let msg = Cc['@mozilla.org/android/bridge;1'].
getService(Ci.nsIAndroidBridge).handleGeckoMessage(
JSON.stringify(
{ gecko: {
type: 'Accessibility:IsEnabled',
eventType: 1,
text: []
}
}));
return JSON.parse(msg).enabled;
}
return false;
this.prefsBranch = Cc['@mozilla.org/preferences-service;1']
.getService(Ci.nsIPrefService).getBranch('accessibility.');
this.prefsBranch.addObserver('accessfu', this, false);
let accessPref = ACCESSFU_DISABLE;
try {
accessPref = this.prefsBranch.getIntPref('accessfu');
} catch (x) {
}
if (checkA11y())
if (this.amINeeded(accessPref))
this.enable();
},
@ -94,6 +96,28 @@ var AccessFu = {
this.chromeWin.removeEventListener('TabClose', this);
},
amINeeded: function(aPref) {
switch (aPref) {
case ACCESSFU_ENABLE:
return true;
case ACCESSFU_AUTO:
if (Services.appinfo.OS == 'Android') {
let msg = Cc['@mozilla.org/android/bridge;1'].
getService(Ci.nsIAndroidBridge).handleGeckoMessage(
JSON.stringify(
{ gecko: {
type: 'Accessibility:IsEnabled',
eventType: 1,
text: []
}
}));
return JSON.parse(msg).enabled;
}
default:
return false;
}
},
addPresenter: function addPresenter(presenter) {
this.presenters.push(presenter);
presenter.attach(this.chromeWin);
@ -150,6 +174,14 @@ var AccessFu = {
observe: function observe(aSubject, aTopic, aData) {
switch (aTopic) {
case 'nsPref:changed':
if (aData == 'accessfu') {
if (this.amINeeded(this.prefsBranch.getIntPref('accessfu')))
this.enable();
else
this.disable();
}
break;
case 'accessible-event':
let event;
try {
@ -204,6 +236,34 @@ var AccessFu = {
}
break;
}
case Ci.nsIAccessibleEvent.EVENT_TEXT_INSERTED:
case Ci.nsIAccessibleEvent.EVENT_TEXT_REMOVED:
{
if (aEvent.isFromUserInput) {
// XXX support live regions as well.
let event = aEvent.QueryInterface(Ci.nsIAccessibleTextChangeEvent);
let isInserted = event.isInserted();
let textIface = aEvent.accessible.QueryInterface(Ci.nsIAccessibleText);
let text = '';
try {
text = textIface.
getText(0, Ci.nsIAccessibleText.TEXT_OFFSET_END_OF_TEXT);
} catch (x) {
// XXX we might have gotten an exception with of a
// zero-length text. If we did, ignore it (bug #749810).
if (textIface.characterCount)
throw x;
}
this.presenters.forEach(
function(p) {
p.textChanged(isInserted, event.start, event.length, text, event.modifiedText);
}
);
}
break;
}
default:
break;
}

View File

@ -52,7 +52,7 @@ Presenter.prototype = {
/**
* Text has changed, either by the user or by the system. TODO.
*/
textChanged: function textChanged() {},
textChanged: function textChanged(aIsInserted, aStartOffset, aLength, aText, aModifiedText) {},
/**
* Text selection has changed. TODO.
@ -254,6 +254,27 @@ AndroidPresenter.prototype.tabSelected = function(aObject) {
this.pivotChanged(vcDoc.virtualCursor.position || aObject, context);
};
AndroidPresenter.prototype.textChanged = function(aIsInserted, aStart, aLength, aText, aModifiedText) {
let androidEvent = {
type: 'Accessibility:Event',
eventType: ANDROID_TYPE_VIEW_TEXT_CHANGED,
text: [aText],
fromIndex: aStart
};
if (aIsInserted) {
androidEvent.addedCount = aLength;
androidEvent.beforeText =
aText.substring(0, aStart) + aText.substring(aStart + aLength);
} else {
androidEvent.removedCount = aLength;
androidEvent.beforeText =
aText.substring(0, aStart) + aModifiedText + aText.substring(aStart);
}
this.sendMessageToJava({gecko: androidEvent});
};
AndroidPresenter.prototype.sendMessageToJava = function(aMessage) {
return Cc['@mozilla.org/android/bridge;1'].
getService(Ci.nsIAndroidBridge).

View File

@ -50,7 +50,7 @@ var UtteranceGenerator = {
if (aForceName)
flags |= INCLUDE_NAME;
return func(aAccessible, roleString, flags);
return func.apply(this, [aAccessible, roleString, flags]);
},
genForAction: function(aObject, aActionName) {
@ -113,8 +113,7 @@ var UtteranceGenerator = {
objectUtteranceFunctions: {
defaultFunc: function defaultFunc(aAccessible, aRoleStr, aFlags) {
let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
let desc = (aFlags & INCLUDE_ROLE) ?
gStringBundle.GetStringFromName(aRoleStr) : '';
let desc = (aFlags & INCLUDE_ROLE) ? this._getLocalizedRole(aRoleStr) : '';
if (!name && !desc)
return [];
@ -149,7 +148,7 @@ var UtteranceGenerator = {
listitem: function(aAccessible, aRoleStr, aFlags) {
let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
let localizedRole = gStringBundle.GetStringFromName(aRoleStr);
let localizedRole = this._getLocalizedRole(aRoleStr);
let itemno = {};
let itemof = {};
aAccessible.groupPosition({}, itemof, itemno);
@ -158,5 +157,13 @@ var UtteranceGenerator = {
return [desc, name];
}
},
_getLocalizedRole: function _getLocalizedRole(aRoleStr) {
try {
return gStringBundle.GetStringFromName(aRoleStr.replace(' ', ''));
} catch (x) {
return '';
}
}
};

View File

@ -122,20 +122,28 @@ var VirtualCursorController = {
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
match: function(aAccessible) {
let rv = Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
if (aAccessible.childCount == 0) {
// TODO: Find a better solution for ROLE_STATICTEXT.
// Right now it helps filter list bullets, but it is also used
// in CSS generated content.
if (aAccessible.childCount)
// Non-leafs do not interest us.
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
// XXX: Find a better solution for ROLE_STATICTEXT.
// It allows to filter list bullets but the same time it
// filters CSS generated content too as unwanted side effect.
let ignoreRoles = [Ci.nsIAccessibleRole.ROLE_WHITESPACE,
Ci.nsIAccessibleRole.ROLE_STATICTEXT];
if (ignoreRoles.indexOf(aAccessible.role) < 0) {
let name = aAccessible.name;
if (name && name.trim())
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
}
let state = {};
aAccessible.getState(state, {});
if ((state.value & Ci.nsIAccessibleStates.STATE_FOCUSABLE) ||
(aAccessible.name && ignoreRoles.indexOf(aAccessible.role) < 0))
rv = Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
}
return rv;
if (state.value & Ci.nsIAccessibleStates.STATE_FOCUSABLE)
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])

View File

@ -50,7 +50,6 @@ LIBXUL_LIBRARY = 1
CMMSRCS = nsAccessNodeWrap.mm \
nsDocAccessibleWrap.mm \
nsRootAccessibleWrap.mm \
nsAccessibleWrap.mm \
mozAccessible.mm \
mozDocAccessible.mm \
@ -58,6 +57,7 @@ CMMSRCS = nsAccessNodeWrap.mm \
mozTextAccessible.mm \
mozHTMLAccessible.mm \
MacUtils.mm \
RootAccessibleWrap.mm \
$(NULL)
@ -67,7 +67,6 @@ EXPORTS = \
nsTextAccessibleWrap.h \
nsAccessibleWrap.h \
nsDocAccessibleWrap.h \
nsRootAccessibleWrap.h \
nsXULMenuAccessibleWrap.h \
nsXULListboxAccessibleWrap.h \
nsXULTreeGridAccessibleWrap.h \

View File

@ -40,19 +40,22 @@
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
*/
#ifndef _nsRootAccessibleWrap_H_
#define _nsRootAccessibleWrap_H_
#ifndef mozilla_a11y_RootAccessibleWrap_h__
#define mozilla_a11y_RootAccessibleWrap_h__
#include "nsRootAccessible.h"
#include "RootAccessible.h"
namespace mozilla {
namespace a11y {
struct objc_class;
class nsRootAccessibleWrap : public nsRootAccessible
class RootAccessibleWrap : public RootAccessible
{
public:
nsRootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
RootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
nsIPresShell* aPresShell);
virtual ~nsRootAccessibleWrap();
virtual ~RootAccessibleWrap();
Class GetNativeType ();
@ -61,5 +64,7 @@ public:
void GetNativeWidget (void **aOutView);
};
} // namespace a11y
} // namespace mozilla
#endif

View File

@ -36,7 +36,7 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsRootAccessibleWrap.h"
#include "RootAccessibleWrap.h"
#include "mozDocAccessible.h"
@ -45,19 +45,21 @@
#include "nsIWidget.h"
#include "nsIViewManager.h"
nsRootAccessibleWrap::
nsRootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
using namespace mozilla::a11y;
RootAccessibleWrap::
RootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
nsIPresShell* aPresShell) :
nsRootAccessible(aDocument, aRootContent, aPresShell)
RootAccessible(aDocument, aRootContent, aPresShell)
{
}
nsRootAccessibleWrap::~nsRootAccessibleWrap()
RootAccessibleWrap::~RootAccessibleWrap()
{
}
Class
nsRootAccessibleWrap::GetNativeType ()
RootAccessibleWrap::GetNativeType()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
@ -67,7 +69,7 @@ nsRootAccessibleWrap::GetNativeType ()
}
void
nsRootAccessibleWrap::GetNativeWidget (void **aOutView)
RootAccessibleWrap::GetNativeWidget(void** aOutView)
{
nsIFrame *frame = GetFrame();
if (frame) {

View File

@ -45,9 +45,9 @@
#include "nsIAccessibleRelation.h"
#include "nsIAccessibleText.h"
#include "nsIAccessibleEditableText.h"
#include "nsRootAccessible.h"
#include "Relation.h"
#include "Role.h"
#include "RootAccessible.h"
#include "mozilla/Services.h"
#include "nsRect.h"
@ -353,7 +353,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
// (which might be the owning NSWindow in the application, for example).
//
// get the native root accessible, and tell it to return its first parent unignored accessible.
nsRootAccessible* root = mGeckoAccessible->RootAccessible();
RootAccessible* root = mGeckoAccessible->RootAccessible();
id nativeParent = GetNativeFromGeckoAccessible(static_cast<nsIAccessible*>(root));
NSAssert1 (nativeParent, @"!!! we can't find a parent for %@", self);

View File

@ -44,7 +44,7 @@
/*
The root accessible. There is one per window.
Created by the nsRootAccessibleWrap.
Created by the RootAccessibleWrap.
*/
@interface mozRootAccessible : mozAccessible
{

View File

@ -36,16 +36,20 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsRootAccessibleWrap.h"
#include "nsObjCExceptions.h"
#include "RootAccessibleWrap.h"
#import "mozDocAccessible.h"
#import "mozView.h"
static id <mozAccessible, mozView> getNativeViewFromRootAccessible (nsAccessible *accessible)
using namespace mozilla::a11y;
static id <mozAccessible, mozView>
getNativeViewFromRootAccessible(nsAccessible* aAccessible)
{
nsRootAccessibleWrap *root = static_cast<nsRootAccessibleWrap*>(accessible);
RootAccessibleWrap* root =
static_cast<RootAccessibleWrap*>(aAccessible->AsRoot());
id <mozAccessible, mozView> nativeView = nil;
root->GetNativeWidget ((void**)&nativeView);
return nativeView;

View File

@ -55,7 +55,6 @@ CPPSRCS = \
nsTextAccessibleWrap.cpp \
nsDocAccessibleWrap.cpp \
nsHTMLWin32ObjectAccessible.cpp \
nsRootAccessibleWrap.cpp \
nsXULMenuAccessibleWrap.cpp \
nsXULListboxAccessibleWrap.cpp \
nsXULTreeGridAccessibleWrap.cpp \
@ -75,6 +74,7 @@ CPPSRCS = \
CAccessibleTableCell.cpp \
CAccessibleValue.cpp \
Compatibility.cpp \
RootAccessibleWrap.cpp \
$(NULL)
EXPORTS = \
@ -83,7 +83,6 @@ EXPORTS = \
nsAccessibleWrap.h \
nsTextAccessibleWrap.h \
nsDocAccessibleWrap.h \
nsRootAccessibleWrap.h \
nsHTMLWin32ObjectAccessible.h \
nsXULMenuAccessibleWrap.h \
nsXULListboxAccessibleWrap.h \

View File

@ -36,7 +36,7 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsRootAccessibleWrap.h"
#include "RootAccessibleWrap.h"
#include "Compatibility.h"
#include "nsWinUtils.h"
@ -49,22 +49,22 @@ using namespace mozilla::a11y;
////////////////////////////////////////////////////////////////////////////////
// Constructor/desctructor
nsRootAccessibleWrap::
nsRootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
RootAccessibleWrap::
RootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
nsIPresShell* aPresShell) :
nsRootAccessible(aDocument, aRootContent, aPresShell)
RootAccessible(aDocument, aRootContent, aPresShell)
{
}
nsRootAccessibleWrap::~nsRootAccessibleWrap()
RootAccessibleWrap::~RootAccessibleWrap()
{
}
////////////////////////////////////////////////////////////////////////////////
// nsRootAccessible
// RootAccessible
void
nsRootAccessibleWrap::DocumentActivated(nsDocAccessible* aDocument)
RootAccessibleWrap::DocumentActivated(nsDocAccessible* aDocument)
{
if (Compatibility::IsDolphin() &&
nsCoreUtils::IsTabDocument(aDocument->GetDocumentNode())) {

View File

@ -37,20 +37,26 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef _nsRootAccessibleWrap_H_
#define _nsRootAccessibleWrap_H_
#ifndef mozilla_a11y_RootAccessibleWrap_h__
#define mozilla_a11y_RootAccessibleWrap_h__
#include "nsRootAccessible.h"
#include "RootAccessible.h"
class nsRootAccessibleWrap : public nsRootAccessible
namespace mozilla {
namespace a11y {
class RootAccessibleWrap : public RootAccessible
{
public:
nsRootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
RootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
nsIPresShell* aPresShell);
virtual ~nsRootAccessibleWrap();
virtual ~RootAccessibleWrap();
// nsRootAccessible
// RootAccessible
virtual void DocumentActivated(nsDocAccessible* aDocument);
};
} // namespace a11y
} // namespace mozilla
#endif

View File

@ -45,8 +45,8 @@
#include "Compatibility.h"
#include "nsAccessibilityService.h"
#include "nsCoreUtils.h"
#include "nsRootAccessible.h"
#include "nsWinUtils.h"
#include "RootAccessible.h"
#include "Statistics.h"
#include "nsAttrName.h"

View File

@ -54,6 +54,7 @@
#include "Accessible2_i.c"
#include "AccessibleRole.h"
#include "AccessibleStates.h"
#include "RootAccessible.h"
#include "nsIMutableArray.h"
#include "nsIDOMDocument.h"
@ -61,7 +62,6 @@
#include "nsIScrollableFrame.h"
#include "nsINameSpaceManager.h"
#include "nsINodeInfo.h"
#include "nsRootAccessible.h"
#include "nsIServiceManager.h"
#include "nsTextFormatter.h"
#include "nsIView.h"
@ -76,19 +76,6 @@ using namespace mozilla::a11y;
const PRUint32 USE_ROLE_STRING = 0;
#ifndef ROLE_SYSTEM_SPLITBUTTON
const PRUint32 ROLE_SYSTEM_SPLITBUTTON = 0x3e; // Not defined in all oleacc.h versions
#endif
#ifndef ROLE_SYSTEM_IPADDRESS
const PRUint32 ROLE_SYSTEM_IPADDRESS = 0x3f; // Not defined in all oleacc.h versions
#endif
#ifndef ROLE_SYSTEM_OUTLINEBUTTON
const PRUint32 ROLE_SYSTEM_OUTLINEBUTTON = 0x40; // Not defined in all oleacc.h versions
#endif
/* For documentation of the accessibility architecture,
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
*/
@ -1893,7 +1880,7 @@ void nsAccessibleWrap::UpdateSystemCaret()
// off-screen model can follow the caret
::DestroyCaret();
nsRootAccessible* rootAccessible = RootAccessible();
a11y::RootAccessible* rootAccessible = RootAccessible();
if (!rootAccessible) {
return;
}

View File

@ -42,9 +42,9 @@
#include "nsDocAccessibleWrap.h"
#include "ISimpleDOMDocument_i.c"
#include "nsIAccessibilityService.h"
#include "nsRootAccessible.h"
#include "nsWinUtils.h"
#include "Role.h"
#include "RootAccessible.h"
#include "Statistics.h"
#include "nsIDocShell.h"
@ -57,6 +57,7 @@
#include "nsIViewManager.h"
#include "nsIWebNavigation.h"
using namespace mozilla;
using namespace mozilla::a11y;
/* For documentation of the accessibility architecture,
@ -280,7 +281,7 @@ nsDocAccessibleWrap::DoInitialUpdate()
mozilla::dom::TabChild* tabChild =
mozilla::dom::GetTabChildFrom(mDocument->GetShell());
nsRootAccessible* rootDocument = RootAccessible();
a11y::RootAccessible* rootDocument = RootAccessible();
mozilla::WindowsHandle nativeData = nsnull;
if (tabChild)

View File

@ -41,8 +41,8 @@
#include "nsWinUtils.h"
#include "Compatibility.h"
#include "nsIWinAccessNode.h"
#include "nsRootAccessible.h"
#include "nsDocAccessible.h"
#include "nsCoreUtils.h"
#include "mozilla/Preferences.h"
#include "nsArrayUtils.h"

View File

@ -50,7 +50,6 @@ LIBXUL_LIBRARY = 1
CPPSRCS = \
nsAccessNodeWrap.cpp \
nsAccessibleWrap.cpp \
nsRootAccessibleWrap.cpp \
$(NULL)
EXPORTS = \
@ -59,7 +58,6 @@ EXPORTS = \
nsTextAccessibleWrap.h \
nsAccessibleWrap.h \
nsDocAccessibleWrap.h \
nsRootAccessibleWrap.h \
nsXULMenuAccessibleWrap.h \
nsXULListboxAccessibleWrap.h \
nsXULTreeGridAccessibleWrap.h \

View File

@ -40,18 +40,17 @@
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
*/
#ifndef _nsRootAccessibleWrap_H_
#define _nsRootAccessibleWrap_H_
#ifndef mozilla_a11y_RootAccessibleWrap_h__
#define mozilla_a11y_RootAccessibleWrap_h__
#include "nsRootAccessible.h"
#include "RootAccessible.h"
class nsRootAccessibleWrap: public nsRootAccessible
{
public:
nsRootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
nsIPresShell* aPresShell);
virtual ~nsRootAccessibleWrap();
};
namespace mozilla {
namespace a11y {
typedef RootAccessible RootAccessibleWrap;
} // namespace a11y
} // namespace mozilla
#endif

View File

@ -1,58 +0,0 @@
/* -*- 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
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Original Author: Aaron Leventhal (aaronl@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsRootAccessibleWrap.h"
#include "nsIServiceManager.h"
#include "nsIAccessibilityService.h"
////////////////////////////////////////////////////////////////////////////////
// nsRootAccessibleWrap
////////////////////////////////////////////////////////////////////////////////
nsRootAccessibleWrap::
nsRootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
nsIPresShell* aPresShell) :
nsRootAccessible(aDocument, aRootContent, aPresShell)
{
}
nsRootAccessibleWrap::~nsRootAccessibleWrap()
{
}

View File

@ -201,10 +201,14 @@ else
APPFILES = MacOS
endif
libs repackage:: $(PROGRAM)
$(MKDIR) -p $(dist_dest)/Contents/MacOS
libs-preqs = \
$(call mkdir_deps,$(dist_dest)/Contents/MacOS) \
$(call mkdir_deps,$(dist_dest)/Contents/Resources/$(AB).lproj) \
$(NULL)
.PHONY: repackage
libs repackage:: $(PROGRAM) $(libs-preqs)
rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents $(dist_dest) --exclude English.lproj
$(MKDIR) -p $(dist_dest)/Contents/Resources/$(AB).lproj
rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(dist_dest)/Contents/Resources/$(AB).lproj
sed -e "s/%APP_VERSION%/$(MOZ_APP_VERSION)/" -e "s/%MAC_APP_NAME%/$(MAC_APP_NAME)/" -e "s/%LOWER_MAC_APP_NAME%/$(LOWER_MAC_APP_NAME)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(dist_dest)/Contents/Info.plist
sed -e "s/%MAC_APP_NAME%/$(MAC_APP_NAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(dist_dest)/Contents/Resources/$(AB).lproj/InfoPlist.strings

View File

@ -1058,9 +1058,14 @@ pref("devtools.layoutview.open", false);
// Enable the Debugger
pref("devtools.debugger.enabled", false);
pref("devtools.debugger.remote-enabled", false);
pref("devtools.debugger.remote-host", "localhost");
pref("devtools.debugger.remote-port", 6000);
// The default Debugger UI height
pref("devtools.debugger.ui.height", 250);
pref("devtools.debugger.ui.remote-win.width", 900);
pref("devtools.debugger.ui.remote-win.height", 400);
// Enable the style inspector
pref("devtools.styleinspector.enabled", true);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 438 B

After

Width:  |  Height:  |  Size: 961 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -194,6 +194,14 @@
label="&debuggerMenu.label;"
key="key_debugger"
command="Tools:Debugger"/>
<menuitem id="appmenu_remoteDebugger"
hidden="true"
label="&remoteDebuggerMenu.label;"
command="Tools:RemoteDebugger"/>
<menuitem id="appmenu_chromeDebugger"
hidden="true"
label="&chromeDebuggerMenu.label;"
command="Tools:ChromeDebugger"/>
<menuitem id="appmenu_scratchpad"
hidden="true"
label="&scratchpad.label;"

View File

@ -225,7 +225,7 @@ var FullZoom = {
return;
// Avoid the cps roundtrip and apply the default/global pref.
if (isBlankPageURL(aURI.spec)) {
if (aURI.spec == "about:blank") {
this._applyPrefToSetting(undefined, aBrowser);
return;
}

View File

@ -551,6 +551,14 @@
label="&debuggerMenu.label;"
key="key_debugger"
command="Tools:Debugger"/>
<menuitem id="menu_remoteDebugger"
hidden="true"
label="&remoteDebuggerMenu.label;"
command="Tools:RemoteDebugger"/>
<menuitem id="menu_chromeDebugger"
hidden="true"
label="&chromeDebuggerMenu.label;"
command="Tools:ChromeDebugger"/>
<menuitem id="menu_scratchpad"
hidden="true"
label="&scratchpad.label;"

View File

@ -129,6 +129,8 @@
<command id="Tools:WebConsole" oncommand="HUDConsoleUI.toggleHUD();"/>
<command id="Tools:Inspect" oncommand="InspectorUI.toggleInspectorUI();" disabled="true"/>
<command id="Tools:Debugger" oncommand="DebuggerUI.toggleDebugger();" disabled="true"/>
<command id="Tools:RemoteDebugger" oncommand="DebuggerUI.toggleRemoteDebugger();" disabled="true"/>
<command id="Tools:ChromeDebugger" oncommand="DebuggerUI.toggleChromeDebugger();" disabled="true"/>
<command id="Tools:Scratchpad" oncommand="Scratchpad.openScratchpad();" disabled="true"/>
<command id="Tools:StyleEditor" oncommand="StyleEditor.openChrome();" disabled="true"/>
<command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>

View File

@ -430,20 +430,11 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
/* notification anchors should only be visible when their associated
notifications are */
.notification-anchor-icon {
display: none;
-moz-user-focus: normal;
}
/* We use the iconBox as the notification anchor when a popup notification is
created with a null anchorID, so in that case use a default anchor icon. */
#notification-popup-box[anchorid="notification-popup-box"] > #default-notification-icon,
#notification-popup-box[anchorid="geo-notification-icon"] > #geo-notification-icon,
#notification-popup-box[anchorid="indexedDB-notification-icon"] > #indexedDB-notification-icon,
#notification-popup-box[anchorid="addons-notification-icon"] > #addons-notification-icon,
#notification-popup-box[anchorid="password-notification-icon"] > #password-notification-icon,
#notification-popup-box[anchorid="webapps-notification-icon"] > #webapps-notification-icon,
#notification-popup-box[anchorid="plugins-notification-icon"] > #plugins-notification-icon {
display: -moz-box;
.notification-anchor-icon:not([showing]) {
display: none;
}
#invalid-form-popup > description {

View File

@ -1716,6 +1716,26 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
#endif
}
// Enable Remote Debugger?
let enabled = gPrefService.getBoolPref("devtools.debugger.remote-enabled");
if (enabled) {
document.getElementById("menu_remoteDebugger").hidden = false;
document.getElementById("Tools:RemoteDebugger").removeAttribute("disabled");
#ifdef MENUBAR_CAN_AUTOHIDE
document.getElementById("appmenu_remoteDebugger").hidden = false;
#endif
}
// Enable Chrome Debugger?
let enabled = gPrefService.getBoolPref("devtools.chrome.enabled");
if (enabled) {
document.getElementById("menu_chromeDebugger").hidden = false;
document.getElementById("Tools:ChromeDebugger").removeAttribute("disabled");
#ifdef MENUBAR_CAN_AUTOHIDE
document.getElementById("appmenu_chromeDebugger").hidden = false;
#endif
}
// Enable Error Console?
// XXX Temporarily always-enabled, see bug 601201
let consoleEnabled = true || gPrefService.getBoolPref("devtools.errorconsole.enabled");
@ -4433,10 +4453,10 @@ var FullScreen = {
XPCOMUtils.defineLazyGetter(FullScreen, "useLionFullScreen", function() {
// We'll only use OS X Lion full screen if we're
// * on OS X
// * on Lion (Darwin 11.x) -- this will need to be updated for OS X 10.8
// * on Lion or higher (Darwin 11+)
// * have fullscreenbutton="true"
#ifdef XP_MACOSX
return /^11\./.test(Services.sysinfo.getProperty("version")) &&
return parseFloat(Services.sysinfo.getProperty("version")) >= 11 &&
document.documentElement.getAttribute("fullscreenbutton") == "true";
#else
return false;

View File

@ -642,6 +642,84 @@ var tests = [
ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
}
},
// Test multiple notification icons are shown
{ // Test #21
run: function () {
this.notifyObj1 = new basicNotification();
this.notifyObj1.id += "_1";
this.notifyObj1.anchorID = "default-notification-icon";
this.notification1 = showNotification(this.notifyObj1);
this.notifyObj2 = new basicNotification();
this.notifyObj2.id += "_2";
this.notifyObj2.anchorID = "geo-notification-icon";
this.notification2 = showNotification(this.notifyObj2);
},
onShown: function (popup) {
checkPopup(popup, this.notifyObj2);
// check notifyObj1 anchor icon is showing
isnot(document.getElementById("default-notification-icon").boxObject.width, 0,
"default anchor should be visible");
// check notifyObj2 anchor icon is showing
isnot(document.getElementById("geo-notification-icon").boxObject.width, 0,
"geo anchor should be visible");
dismissNotification(popup);
},
onHidden: [
function (popup) {
},
function (popup) {
this.notification1.remove();
ok(this.notifyObj1.removedCallbackTriggered, "removed callback triggered");
this.notification2.remove();
ok(this.notifyObj2.removedCallbackTriggered, "removed callback triggered");
}
],
},
// Test that multiple notification icons are removed when switching tabs
{ // Test #22
run: function () {
// show the notification on old tab.
this.notifyObjOld = new basicNotification();
this.notifyObjOld.anchorID = "default-notification-icon";
this.notificationOld = showNotification(this.notifyObjOld);
// switch tab
this.oldSelectedTab = gBrowser.selectedTab;
gBrowser.selectedTab = gBrowser.addTab("about:blank");
// show the notification on new tab.
this.notifyObjNew = new basicNotification();
this.notifyObjNew.anchorID = "geo-notification-icon";
this.notificationNew = showNotification(this.notifyObjNew);
},
onShown: function (popup) {
checkPopup(popup, this.notifyObjNew);
// check notifyObjOld anchor icon is removed
is(document.getElementById("default-notification-icon").boxObject.width, 0,
"default anchor shouldn't be visible");
// check notifyObjNew anchor icon is showing
isnot(document.getElementById("geo-notification-icon").boxObject.width, 0,
"geo anchor should be visible");
dismissNotification(popup);
},
onHidden: [
function (popup) {
},
function (popup) {
this.notificationNew.remove();
gBrowser.removeTab(gBrowser.selectedTab);
gBrowser.selectedTab = this.oldSelectedTab;
this.notificationOld.remove();
}
],
}
];
function showNotification(notifyObj) {

View File

@ -811,7 +811,7 @@ BrowserGlue.prototype = {
try {
// This will throw NS_ERROR_NOT_AVAILABLE if the notification cannot
// be displayed per the idl.
notifier.showAlertNotification("post-update-notification", title, text,
notifier.showAlertNotification(null, title, text,
true, url, clickCallback);
}
catch (e) {

View File

@ -241,16 +241,13 @@ var PlacesOrganizer = {
}
// Update the selected folder title where it appears in the UI: the folder
// scope button, "Find in <current collection>" command, and the search box
// emptytext. They must be updated even if the selection hasn't changed --
// scope button, and the search box emptytext.
// They must be updated even if the selection hasn't changed --
// specifically when node's title changes. In that case a selection event
// is generated, this method is called, but the selection does not change.
var folderButton = document.getElementById("scopeBarFolder");
var folderTitle = node.title || folderButton.getAttribute("emptytitle");
folderButton.setAttribute("label", folderTitle);
var cmd = document.getElementById("OrganizerCommand_find:current");
var label = PlacesUIUtils.getFormattedString("findInPrefix", [folderTitle]);
cmd.setAttribute("label", label);
if (PlacesSearchBox.filterCollection == "collection")
PlacesSearchBox.updateCollectionTitle(folderTitle);
@ -925,18 +922,20 @@ var PlacesSearchBox = {
},
/**
* Finds across all bookmarks
* Finds across all history, downloads or all bookmarks.
*/
findAll: function PSB_findAll() {
switch (this.filterCollection) {
case "history":
PlacesQueryBuilder.setScope("history");
break;
case "downloads":
PlacesQueryBuilder.setScope("downloads");
break;
default:
PlacesQueryBuilder.setScope("bookmarks");
this.focus();
},
/**
* Finds in the currently selected Place.
*/
findCurrent: function PSB_findCurrent() {
PlacesQueryBuilder.setScope("collection");
break;
}
this.focus();
},
@ -947,12 +946,15 @@ var PlacesSearchBox = {
*/
updateCollectionTitle: function PSB_updateCollectionTitle(aTitle) {
let title = "";
// This is needed when a user performs a folder-specific search
// using the scope bar, removes the search-string, and unfocuses
// the search box, at least until the removal of the scope bar.
if (aTitle) {
title = PlacesUIUtils.getFormattedString("searchCurrentDefault",
[aTitle]);
}
else {
switch(this.filterCollection) {
switch (this.filterCollection) {
case "history":
title = PlacesUIUtils.getString("searchHistory");
break;

View File

@ -99,13 +99,7 @@
<commandset id="organizerCommandSet">
<command id="OrganizerCommand_find:all"
label="&cmd.findInBookmarks.label;"
accesskey="&cmd.findInBookmarks.accesskey;"
oncommand="PlacesSearchBox.findAll();"/>
<command id="OrganizerCommand_find:current"
label="&cmd.findCurrent.label;"
accesskey="&cmd.findCurrent.accesskey;"
oncommand="PlacesSearchBox.findCurrent();"/>
<command id="OrganizerCommand_export"
oncommand="PlacesOrganizer.exportBookmarks();"/>
<command id="OrganizerCommand_import"
@ -137,10 +131,6 @@
command="OrganizerCommand_find:all"
key="&cmd.find.key;"
modifiers="accel"/>
<key id="placesKey_find:current"
command="OrganizerCommand_find:current"
key="&cmd.find.key;"
modifiers="accel,shift"/>
<!-- Back/Forward Keys Support -->
#ifndef XP_MACOSX

View File

@ -34,7 +34,7 @@ function onTabViewWindowLoaded() {
is(appTabCount(groupItemOne), 0, "there are no app tab icons");
// pin the tab, make sure the TabItem goes away and the icon comes on
whenAppTabIconAdded(function() {
whenAppTabIconAdded(groupItemOne, function () {
is(groupItemOne._children.length, 0,
"the app tab's TabItem was removed from the group");
is(appTabCount(groupItemOne), 1, "there's now one app tab icon");
@ -43,7 +43,7 @@ function onTabViewWindowLoaded() {
box.offset(box.width + 20, 0);
let groupItemTwo = new contentWindow.GroupItem([],
{ bounds: box, title: "test2" });
whenAppTabIconAdded(function() {
whenAppTabIconAdded(groupItemTwo, function() {
is(contentWindow.GroupItems.groupItems.length, 3, "we now have three groups");
is(appTabCount(groupItemTwo), 1,
"there's an app tab icon in the second group");
@ -58,7 +58,7 @@ function onTabViewWindowLoaded() {
is(appTabCount(groupItemOne), 0, "the icon is gone from group one");
is(appTabCount(groupItemTwo), 0, "the icon is gone from group two");
whenAppTabIconAdded(function() {
whenAppTabIconAdded(groupItemOne, function() {
// close the second group
groupItemTwo.close();

View File

@ -53,7 +53,7 @@ function onTabViewShown(win) {
"$appTabTray container is not visible");
// pin the tab, make sure the TabItem goes away and the icon comes on
whenAppTabIconAdded(function() {
whenAppTabIconAdded(groupItem, function () {
is(groupItem._children.length, 0,
"the app tab's TabItem was removed from the group");
is(appTabCount(groupItem), 1, "there's now one app tab icon");
@ -80,7 +80,7 @@ function onTabViewShown(win) {
// add one more tab
xulTabs.push(gBrowser.loadOneTab("about:blank"));
whenAppTabIconAdded(function() {
whenAppTabIconAdded(groupItem, function () {
is(tray.css("-moz-column-count"), 3,
"$appTabTray column count is 3");
@ -129,7 +129,7 @@ function onTabViewShown(win) {
executeSoon(finish);
}, win);
}, win);
});
win.gBrowser.pinTab(xulTabs[xulTabs.length-1]);
};
@ -137,13 +137,13 @@ function onTabViewShown(win) {
let returnCount = 0;
for (let i = 1; i < icons; i++) {
xulTabs.push(gBrowser.loadOneTab("about:blank"));
whenAppTabIconAdded(function() {
whenAppTabIconAdded(groupItem, function () {
if (++returnCount == (icons - 1))
executeSoon(pinnedSomeTabs);
}, win);
});
win.gBrowser.pinTab(xulTabs[i]);
}
}, win);
});
win.gBrowser.pinTab(xulTabs[0]);
}

View File

@ -18,13 +18,14 @@ function test() {
newTab = gBrowser.addTab();
showTabView(function() {
whenAppTabIconAdded(onTabPinned);
let cw = TabView.getContentWindow();
whenAppTabIconAdded(cw.GroupItems.groupItems[0], onTabPinned);
gBrowser.pinTab(newTab);
})
}
function onTabPinned() {
let contentWindow = document.getElementById("tab-view").contentWindow;
let contentWindow = TabView.getContentWindow();
is(contentWindow.GroupItems.groupItems.length, 1,
"There is one group item on startup");

View File

@ -23,9 +23,9 @@ function test() {
groupItem = contentWindow.GroupItems.groupItems[0];
whenAppTabIconAdded(function() {
whenAppTabIconAdded(function() {
whenAppTabIconAdded(function() {
whenAppTabIconAdded(groupItem, function () {
whenAppTabIconAdded(groupItem, function () {
whenAppTabIconAdded(groupItem, function () {
is(xulTabForAppTabIcon(0), newTabOne,
"New tab one matches the first app tab icon in tabview");

View File

@ -25,12 +25,12 @@ function test() {
is(newTabItemOne.$favImage[0].src, ICON_URL, "The tab item is showing the right icon.");
// test pin tab
whenAppTabIconAdded(function() {
whenAppTabIconAdded(groupItem, function() {
let icon = cw.iQ(".appTabIcon", groupItem.$appTabTray)[0];
is(icon.src, ICON_URL, "The app tab is showing the right icon");
finish();
}, win);
});
win.gBrowser.pinTab(newTabTwo);
});
}, function(win) {

View File

@ -8,8 +8,8 @@ function test() {
let tab = gBrowser.addTab();
registerCleanupFunction(function () gBrowser.removeTab(tab));
whenAppTabIconAdded(function() {
let cw = TabView.getContentWindow();
whenAppTabIconAdded(cw.GroupItems.groupItems[0], function() {
let body = cw.document.body;
let [appTabIcon] = cw.iQ(".appTabTray .appTabIcon");

View File

@ -411,15 +411,9 @@ function goToNextGroup(win) {
}
// ----------
function whenAppTabIconAdded(callback, win) {
win = win || window;
let contentWindow = win.TabView.getContentWindow();
let groupItems = contentWindow.GroupItems.groupItems;
let groupItem = groupItems[(groupItems.length - 1)];
function whenAppTabIconAdded(groupItem, callback) {
groupItem.addSubscriber("appTabIconAdded", function onAppTabIconAdded() {
groupItem.removeSubscriber("appTabIconAdded", onAppTabIconAdded);
callback();
executeSoon(callback);
});
}

View File

@ -45,7 +45,13 @@ const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const DBG_XUL = "chrome://browser/content/debugger.xul";
const REMOTE_PROFILE_NAME = "_remote-debug";
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
let EXPORTED_SYMBOLS = ["DebuggerUI"];
@ -75,6 +81,36 @@ DebuggerUI.prototype = {
return new DebuggerPane(tab);
},
/**
* Starts a remote debugger in a new process, or stops it if already started.
* @see DebuggerProcess.constructor
* @return DebuggerProcess if the debugger is started, null if it's stopped.
*/
toggleRemoteDebugger: function DUI_toggleRemoteDebugger(aOnClose, aOnRun) {
let win = this.chromeWindow;
if (win._remoteDebugger) {
win._remoteDebugger.close();
return null;
}
return new DebuggerProcess(win, aOnClose, aOnRun);
},
/**
* Starts a chrome debugger in a new process, or stops it if already started.
* @see DebuggerProcess.constructor
* @return DebuggerProcess if the debugger is started, null if it's stopped.
*/
toggleChromeDebugger: function DUI_toggleChromeDebugger(aOnClose, aOnRun) {
let win = this.chromeWindow;
if (win._chromeDebugger) {
win._chromeDebugger.close();
return null;
}
return new DebuggerProcess(win, aOnClose, aOnRun, true);
},
/**
* Get the debugger for a specified tab.
* @return DebuggerPane if a debugger exists for the tab, null otherwise
@ -88,7 +124,7 @@ DebuggerUI.prototype = {
* @return object
*/
get preferences() {
return DebuggerUIPreferences;
return DebuggerPreferences;
}
};
@ -100,11 +136,23 @@ DebuggerUI.prototype = {
*/
function DebuggerPane(aTab) {
this._tab = aTab;
this._initServer();
this._create();
}
DebuggerPane.prototype = {
/**
* Initializes the debugger server.
*/
_initServer: function DP__initServer() {
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
},
/**
* Creates and initializes the widgets containing the debugger UI.
*/
@ -118,7 +166,7 @@ DebuggerPane.prototype = {
this._splitter.setAttribute("class", "hud-splitter");
this._frame = ownerDocument.createElement("iframe");
this._frame.height = DebuggerUIPreferences.height;
this._frame.height = DebuggerPreferences.height;
this._nbox = gBrowser.getNotificationBox(this._tab.linkedBrowser);
this._nbox.appendChild(this._splitter);
@ -139,7 +187,7 @@ DebuggerPane.prototype = {
self.getBreakpoint = bkp.getBreakpoint;
}, true);
this._frame.setAttribute("src", "chrome://browser/content/debugger.xul");
this._frame.setAttribute("src", DBG_XUL);
},
/**
@ -149,10 +197,10 @@ DebuggerPane.prototype = {
if (!this._tab) {
return;
}
this._tab._scriptDebugger = null;
delete this._tab._scriptDebugger;
this._tab = null;
DebuggerUIPreferences.height = this._frame.height;
DebuggerPreferences.height = this._frame.height;
this._frame.removeEventListener("Debugger:Close", this.close, true);
this._frame.removeEventListener("unload", this.close, true);
@ -186,9 +234,117 @@ DebuggerPane.prototype = {
};
/**
* Various debugger UI preferences (currently just the pane height).
* Creates a process that will hold the remote debugger.
*
* @param function aOnClose
* Optional, a function called when the process exits.
* @param function aOnRun
* Optional, a function called when the process starts running.
* @param boolean aInitServerFlag
* True to initialize the server. This should happen only in the chrome
* debugging case. This should also be true by default after bug #747429.
* @param nsIDOMWindow aWindow
* The chrome window for which the remote debugger instance is created.
*/
let DebuggerUIPreferences = {
function DebuggerProcess(aWindow, aOnClose, aOnRun, aInitServerFlag) {
this._win = aWindow;
this._closeCallback = aOnClose;
this._runCallback = aOnRun;
aInitServerFlag && this._initServer();
this._initProfile();
this._create();
}
DebuggerProcess.prototype = {
/**
* Initializes the debugger server.
*/
_initServer: function RDP__initServer() {
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
DebuggerServer.closeListener();
DebuggerServer.openListener(DebuggerPreferences.remotePort, false);
},
/**
* Initializes a profile for the remote debugger process.
*/
_initProfile: function RDP__initProfile() {
let profileService = Cc["@mozilla.org/toolkit/profile-service;1"]
.createInstance(Ci.nsIToolkitProfileService);
let dbgProfileName;
try {
dbgProfileName = profileService.selectedProfile.name + REMOTE_PROFILE_NAME;
} catch(e) {
dbgProfileName = REMOTE_PROFILE_NAME;
Cu.reportError(e);
}
this._dbgProfile = profileService.createProfile(null, null, dbgProfileName);
profileService.flush();
},
/**
* Creates and initializes the profile & process for the remote debugger.
*/
_create: function RDP__create() {
this._win._remoteDebugger = this;
let file = FileUtils.getFile("CurProcD",
[Services.appinfo.OS == "WINNT" ? "firefox.exe"
: "firefox-bin"]);
let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
process.init(file);
let args = [
"-no-remote", "-P", this._dbgProfile.name,
"-chrome", DBG_XUL,
"-width", DebuggerPreferences.remoteWinWidth,
"-height", DebuggerPreferences.remoteWinHeight];
process.runwAsync(args, args.length, { observe: this.close.bind(this) });
this._dbgProcess = process;
if (typeof this._runCallback === "function") {
this._runCallback.call({}, this);
}
},
/**
* Closes the remote debugger, removing the profile and killing the process.
*/
close: function RDP_close() {
if (!this._win) {
return;
}
delete this._win._remoteDebugger;
this._win = null;
if (this._dbgProcess.isRunning) {
this._dbgProcess.kill();
}
if (this._dbgProfile) {
this._dbgProfile.remove(false);
}
if (typeof this._closeCallback === "function") {
this._closeCallback.call({}, this);
}
this._dbgProcess = null;
this._dbgProfile = null;
}
};
/**
* Various debugger preferences.
*/
let DebuggerPreferences = {
/**
* Gets the preferred height of the debugger pane.
@ -210,3 +366,35 @@ let DebuggerUIPreferences = {
this._height = value;
}
};
/**
* Gets the preferred width of the remote debugger window.
* @return number
*/
XPCOMUtils.defineLazyGetter(DebuggerPreferences, "remoteWinWidth", function() {
return Services.prefs.getIntPref("devtools.debugger.ui.remote-win.width");
});
/**
* Gets the preferred height of the remote debugger window.
* @return number
*/
XPCOMUtils.defineLazyGetter(DebuggerPreferences, "remoteWinHeight", function() {
return Services.prefs.getIntPref("devtools.debugger.ui.remote-win.height");
});
/**
* Gets the preferred default remote debugging host.
* @return string
*/
XPCOMUtils.defineLazyGetter(DebuggerPreferences, "remoteHost", function() {
return Services.prefs.getCharPref("devtools.debugger.remote-host");
});
/**
* Gets the preferred default remote debugging port.
* @return number
*/
XPCOMUtils.defineLazyGetter(DebuggerPreferences, "remotePort", function() {
return Services.prefs.getIntPref("devtools.debugger.remote-port");
});

View File

@ -114,6 +114,7 @@ let DebuggerController = {
this.dispatchEvent("Debugger:Unloaded");
this._disconnect();
this._isRemote && this._quitApp();
},
/**
@ -121,12 +122,10 @@ let DebuggerController = {
* wiring event handlers as necessary.
*/
_connect: function DC__connect() {
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
let transport =
this._isRemote ? debuggerSocketConnect(Prefs.remoteHost, Prefs.remotePort)
: DebuggerServer.connectPipe();
let transport = DebuggerServer.connectPipe();
let client = this.client = new DebuggerClient(transport);
client.addListener("tabNavigated", this._onTabNavigated);
@ -220,6 +219,31 @@ let DebuggerController = {
}.bind(this));
},
/**
* Returns true if this is a remote debugger instance.
* @return boolean
*/
get _isRemote() {
return !window.parent.content;
},
/**
* Attempts to quit the current process if allowed.
*/
_quitApp: function DC__quitApp() {
let canceled = Cc["@mozilla.org/supports-PRBool;1"]
.createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(canceled, "quit-application-requested", null);
// Somebody canceled our quit request.
if (canceled.data) {
return;
}
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
},
/**
* Convenience method, dispatching a custom event.
*
@ -470,6 +494,38 @@ StackFrames.prototype = {
this._addExpander(thisVar, frame.this);
}
if (frame.environment) {
// Add nodes for every argument.
let variables = frame.environment.bindings.arguments;
for each (let variable in variables) {
let name = Object.getOwnPropertyNames(variable)[0];
let paramVar = localScope.addVar(name);
let paramVal = variable[name].value;
paramVar.setGrip(paramVal);
this._addExpander(paramVar, paramVal);
}
// Add nodes for every other variable in scope.
variables = frame.environment.bindings.variables;
for (let variable in variables) {
let paramVar = localScope.addVar(variable);
let paramVal = variables[variable].value;
paramVar.setGrip(paramVal);
this._addExpander(paramVar, paramVal);
}
// If we already found 'arguments', we are done here.
if ("arguments" in frame.environment.bindings.variables) {
// Signal that variables have been fetched.
DebuggerController.dispatchEvent("Debugger:FetchedVariables");
return;
}
}
// Sometimes in call frames with arguments we don't get 'arguments' in the
// environment (bug 746601) and we have to construct it manually. Note, that
// in this case arguments.callee will be absent, even in the cases where it
// shouldn't be.
if (frame.arguments && frame.arguments.length > 0) {
// Add "arguments".
let argsVar = localScope.addVar("arguments");
@ -479,33 +535,20 @@ StackFrames.prototype = {
});
this._addExpander(argsVar, frame.arguments);
// Add variables for every argument.
let objClient = this.activeThread.pauseGrip(frame.callee);
objClient.getSignature(function SF_getSignature(aResponse) {
for (let i = 0, l = aResponse.parameters.length; i < l; i++) {
let param = aResponse.parameters[i];
let paramVar = localScope.addVar(param);
let paramVal = frame.arguments[i];
paramVar.setGrip(paramVal);
this._addExpander(paramVar, paramVal);
// Signal that variables have been fetched.
DebuggerController.dispatchEvent("Debugger:FetchedVariables");
}
// Signal that call parameters have been fetched.
DebuggerController.dispatchEvent("Debugger:FetchedParameters");
}.bind(this));
}
},
/**
* Adds a onexpand callback for a variable, lazily handling the addition of
* Adds an 'onexpand' callback for a variable, lazily handling the addition of
* new properties.
*/
_addExpander: function SF__addExpander(aVar, aObject) {
// No need for expansion for null and undefined values, but we do need them
// for frame.arguments which is a regular array.
if (!aObject || typeof aObject !== "object" ||
if (!aVar || !aObject || typeof aObject !== "object" ||
(aObject.type !== "object" && !Array.isArray(aObject))) {
return;
}
@ -686,7 +729,7 @@ SourceScripts.prototype = {
* Handler for the debugger client's unsolicited newScript notification.
*/
_onNewScript: function SS__onNewScript(aNotification, aPacket) {
this._addScript({ url: aPacket.url, startLine: aPacket.startLine });
this._addScript({ url: aPacket.url, startLine: aPacket.startLine }, true);
},
/**
@ -694,8 +737,9 @@ SourceScripts.prototype = {
*/
_onScriptsAdded: function SS__onScriptsAdded() {
for each (let script in this.activeThread.cachedScripts) {
this._addScript(script);
this._addScript(script, false);
}
DebuggerView.Scripts.commitScripts();
},
/**
@ -747,6 +791,22 @@ SourceScripts.prototype = {
return aUrl;
},
/**
* Gets the prePath for a script URL.
*
* @param string aUrl
* The script url.
* @return string
* The script prePath if the url is valid, null otherwise.
*/
_getScriptPrePath: function SS__getScriptDomain(aUrl) {
try {
return Services.io.newURI(aUrl, null, null).prePath + "/";
} catch (e) {
}
return null;
},
/**
* Gets a unique, simplified label from a script url.
* ex: a). ici://some.address.com/random/subrandom/
@ -763,7 +823,7 @@ SourceScripts.prototype = {
* The script url.
* @param string aHref
* The content location href to be used. If unspecified, it will
* defalult to debugged panrent window location.
* default to the script url prepath.
* @return string
* The simplified label.
*/
@ -774,15 +834,18 @@ SourceScripts.prototype = {
return this._labelsCache[url];
}
let href = aHref || window.parent.content.location.href;
let content = window.parent.content;
let domain = content ? content.location.href : this._getScriptPrePath(aUrl);
let href = aHref || domain;
let pathElements = url.split("/");
let label = pathElements.pop() || (pathElements.pop() + "/");
// if the label as a leaf name is alreay present in the scripts list
// If the label as a leaf name is already present in the scripts list.
if (DebuggerView.Scripts.containsLabel(label)) {
label = url.replace(href.substring(0, href.lastIndexOf("/") + 1), "");
// if the path/to/script is exactly the same, we're in different domains
// If the path/to/script is exactly the same, we're in different domains.
if (DebuggerView.Scripts.containsLabel(label)) {
label = url;
}
@ -800,15 +863,16 @@ SourceScripts.prototype = {
},
/**
* Add the specified script to the list and display it in the editor if the
* editor is empty.
* Add the specified script to the list.
*
* @param object aScript
* The script object coming from the active thread.
* @param boolean aForceFlag
* True to force the script to be immediately added.
*/
_addScript: function SS__addScript(aScript) {
DebuggerView.Scripts.addScript(this._getScriptLabel(aScript.url), aScript);
if (DebuggerView.editor.getCharCount() == 0) {
this.showScript(aScript);
}
_addScript: function SS__addScript(aScript, aForceFlag) {
DebuggerView.Scripts.addScript(
this._getScriptLabel(aScript.url), aScript, aForceFlag);
},
/**
@ -876,7 +940,7 @@ SourceScripts.prototype = {
* Handles notifications to load a source script from the cache or from a
* local file.
*
* XXX: Tt may be better to use nsITraceableChannel to get to the sources
* XXX: It may be better to use nsITraceableChannel to get to the sources
* without relying on caching when we can (not for eval, etc.):
* http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/
*/
@ -967,7 +1031,7 @@ SourceScripts.prototype = {
* The failure status code.
*/
_logError: function SS__logError(aUrl, aStatus) {
Components.utils.reportError(L10N.getFormatStr("loadingError", [aUrl, aStatus]));
Cu.reportError(L10N.getFormatStr("loadingError", [aUrl, aStatus]));
},
};
@ -1258,6 +1322,27 @@ XPCOMUtils.defineLazyGetter(L10N, "stringBundle", function() {
return Services.strings.createBundle(DBG_STRINGS_URI);
});
/**
* Shortcuts for accessing various debugger preferences.
*/
let Prefs = {};
/**
* Gets the preferred default remote debugging host.
* @return string
*/
XPCOMUtils.defineLazyGetter(Prefs, "remoteHost", function() {
return Services.prefs.getCharPref("devtools.debugger.remote-host");
});
/**
* Gets the preferred default remote debugging port.
* @return number
*/
XPCOMUtils.defineLazyGetter(Prefs, "remotePort", function() {
return Services.prefs.getIntPref("devtools.debugger.remote-port");
});
/**
* Preliminary setup for the DebuggerController object.
*/

View File

@ -90,6 +90,7 @@ let DebuggerView = {
*/
function ScriptsView() {
this._onScriptsChange = this._onScriptsChange.bind(this);
this._onScriptsSearch = this._onScriptsSearch.bind(this);
}
ScriptsView.prototype = {
@ -103,6 +104,14 @@ ScriptsView.prototype = {
}
},
/**
* Removes the input in the searchbox and unhides all the scripts.
*/
clearSearch: function DVS_clearSearch() {
this._searchbox.value = "";
this._onScriptsSearch({});
},
/**
* Checks whether the script with the specified URL is among the scripts
* known to the debugger and shown in the list.
@ -112,6 +121,11 @@ ScriptsView.prototype = {
* @return boolean
*/
contains: function DVS_contains(aUrl) {
if (this._tmpScripts.some(function(element) {
return element.script.url == aUrl;
})) {
return true;
}
if (this._scripts.getElementsByAttribute("value", aUrl).length > 0) {
return true;
}
@ -127,6 +141,11 @@ ScriptsView.prototype = {
* @return boolean
*/
containsLabel: function DVS_containsLabel(aLabel) {
if (this._tmpScripts.some(function(element) {
return element.label == aLabel;
})) {
return true;
}
if (this._scripts.getElementsByAttribute("label", aLabel).length > 0) {
return true;
}
@ -171,6 +190,18 @@ ScriptsView.prototype = {
this._scripts.selectedItem.value : null;
},
/**
* Returns the list of labels in the scripts container.
* @return array
*/
get scriptLabels() {
let labels = [];
for (let i = 0, l = this._scripts.itemCount; i < l; i++) {
labels.push(this._scripts.getItemAtIndex(i).label);
}
return labels;
},
/**
* Returns the list of URIs for scripts in the page.
* @return array
@ -184,50 +215,212 @@ ScriptsView.prototype = {
},
/**
* Adds a script to the scripts container.
* If the script already exists (was previously added), null is returned.
* Otherwise, the newly created element is returned.
* Gets the number of visible (hidden=false) scripts in the container.
* @return number
*/
get visibleItemsCount() {
let count = 0;
for (let i = 0, l = this._scripts.itemCount; i < l; i++) {
count += this._scripts.getItemAtIndex(i).hidden ? 0 : 1;
}
return count;
},
/**
* Prepares a script to be added to the scripts container. This allows
* for a large number of scripts to be batched up before being
* alphabetically sorted and added in the container.
* @see ScriptsView.commitScripts
*
* If aForceFlag is true, the script will be immediately inserted at the
* necessary position in the container so that all the scripts remain sorted.
* This can be much slower than batching up multiple scripts.
*
* @param string aLabel
* The simplified script location to be shown.
* @param string aScript
* The source script.
* @return object
* The newly created html node representing the added script.
* @param boolean aForceFlag
* True to force the script to be immediately added.
*/
addScript: function DVS_addScript(aLabel, aScript) {
// Make sure we don't duplicate anything.
if (this.containsLabel(aLabel)) {
return null;
addScript: function DVS_addScript(aLabel, aScript, aForceFlag) {
// Batch the script to be added later.
if (!aForceFlag) {
this._tmpScripts.push({ label: aLabel, script: aScript });
return;
}
let script = this._scripts.appendItem(aLabel, aScript.url);
script.setAttribute("tooltiptext", aScript.url);
script.setUserData("sourceScript", aScript, null);
this._scripts.selectedItem = script;
return script;
// Find the target position in the menulist and insert the script there.
for (let i = 0, l = this._scripts.itemCount; i < l; i++) {
if (this._scripts.getItemAtIndex(i).label > aLabel) {
this._createScriptElement(aLabel, aScript, i);
return;
}
}
// The script is alphabetically the last one.
this._createScriptElement(aLabel, aScript, -1, true);
},
/**
* The cached click listener for the scripts container.
* Adds all the prepared scripts to the scripts container.
* If a script already exists (was previously added), nothing happens.
*/
commitScripts: function DVS_commitScripts() {
let newScripts = this._tmpScripts;
this._tmpScripts = [];
if (!newScripts || !newScripts.length) {
return;
}
newScripts.sort(function(a, b) {
return a.label.toLowerCase() > b.label.toLowerCase();
});
for (let i = 0, l = newScripts.length; i < l; i++) {
let item = newScripts[i];
this._createScriptElement(item.label, item.script, -1, true);
}
},
/**
* Creates a custom script element and adds it to the scripts container.
* If the script with the specified label already exists, nothing happens.
*
* @param string aLabel
* The simplified script location to be shown.
* @param string aScript
* The source script.
* @param number aIndex
* The index where to insert to new script in the container.
* Pass -1 to append the script at the end.
* @param boolean aSelectIfEmptyFlag
* True to set the newly created script as the currently selected item
* if there are no other existing scripts in the container.
*/
_createScriptElement: function DVS__createScriptElement(
aLabel, aScript, aIndex, aSelectIfEmptyFlag)
{
// Make sure we don't duplicate anything.
if (aLabel == "null" || this.containsLabel(aLabel)) {
return;
}
let scriptItem =
aIndex == -1 ? this._scripts.appendItem(aLabel, aScript.url)
: this._scripts.insertItemAt(aIndex, aLabel, aScript.url);
scriptItem.setAttribute("tooltiptext", aScript.url);
scriptItem.setUserData("sourceScript", aScript, null);
if (this._scripts.itemCount == 1 && aSelectIfEmptyFlag) {
this._scripts.selectedItem = scriptItem;
}
},
/**
* The click listener for the scripts container.
*/
_onScriptsChange: function DVS__onScriptsChange() {
let script = this._scripts.selectedItem.getUserData("sourceScript");
this._preferredScript = script;
DebuggerController.SourceScripts.showScript(script);
},
/**
* The cached scripts container.
* The search listener for the scripts search box.
*/
_onScriptsSearch: function DVS__onScriptsSearch(e) {
let editor = DebuggerView.editor;
let scripts = this._scripts;
let rawValue = this._searchbox.value.toLowerCase();
let rawLength = rawValue.length;
let lastColon = rawValue.lastIndexOf(":");
let lastAt = rawValue.lastIndexOf("@");
let fileEnd = lastColon != -1 ? lastColon : lastAt != -1 ? lastAt : rawLength;
let lineEnd = lastAt != -1 ? lastAt : rawLength;
let file = rawValue.slice(0, fileEnd);
let line = window.parseInt(rawValue.slice(fileEnd + 1, lineEnd)) || -1;
let token = rawValue.slice(lineEnd + 1);
// Presume we won't find anything.
scripts.selectedItem = this._preferredScript;
// If we're not searching for a file anymore, unhide all the scripts.
if (!file) {
for (let i = 0, l = scripts.itemCount; i < l; i++) {
scripts.getItemAtIndex(i).hidden = false;
}
} else {
for (let i = 0, l = scripts.itemCount, found = false; i < l; i++) {
let item = scripts.getItemAtIndex(i);
let target = item.value.toLowerCase();
// Search is not case sensitive, and is tied to the url not the label.
if (target.match(file)) {
item.hidden = false;
if (!found) {
found = true;
scripts.selectedItem = item;
}
}
// Hide what doesn't match our search.
else {
item.hidden = true;
}
}
}
if (line > -1) {
editor.setCaretPosition(line - 1);
}
if (token) {
let offset = editor.find(token, { ignoreCase: true });
if (offset > -1) {
editor.setCaretPosition(0);
editor.setCaretOffset(offset);
}
}
},
/**
* The keyup listener for the scripts search box.
*/
_onScriptsKeyUp: function DVS__onScriptsKeyUp(e) {
if (e.keyCode === e.DOM_VK_ESCAPE) {
DebuggerView.editor.focus();
return;
}
if (e.keyCode === e.DOM_VK_RETURN || e.keyCode === e.DOM_VK_ENTER) {
let editor = DebuggerView.editor;
let offset = editor.findNext(true);
if (offset > -1) {
editor.setCaretPosition(0);
editor.setCaretOffset(offset);
}
}
},
/**
* The cached scripts container and search box.
*/
_scripts: null,
_searchbox: null,
/**
* Initialization function, called when the debugger is initialized.
*/
initialize: function DVS_initialize() {
this._scripts = document.getElementById("scripts");
this._searchbox = document.getElementById("scripts-search");
this._scripts.addEventListener("select", this._onScriptsChange, false);
this._searchbox.addEventListener("select", this._onScriptsSearch, false);
this._searchbox.addEventListener("input", this._onScriptsSearch, false);
this._searchbox.addEventListener("keyup", this._onScriptsKeyUp, false);
this.commitScripts();
},
/**
@ -235,7 +428,11 @@ ScriptsView.prototype = {
*/
destroy: function DVS_destroy() {
this._scripts.removeEventListener("select", this._onScriptsChange, false);
this._searchbox.removeEventListener("select", this._onScriptsSearch, false);
this._searchbox.removeEventListener("input", this._onScriptsSearch, false);
this._searchbox.removeEventListener("keyup", this._onScriptsKeyUp, false);
this._scripts = null;
this._searchbox = null;
}
};
@ -277,6 +474,8 @@ StackFramesView.prototype = {
else {
status.textContent = "";
}
DebuggerView.Scripts.clearSearch();
},
/**
@ -300,7 +499,7 @@ StackFramesView.prototype = {
// The empty node should look grayed out to avoid confusion.
item.className = "empty list-item";
item.appendChild(document.createTextNode(L10N.getStr("emptyText")));
item.appendChild(document.createTextNode(L10N.getStr("emptyStackText")));
this._frames.appendChild(item);
},
@ -381,7 +580,7 @@ StackFramesView.prototype = {
* The frame depth specified by the debugger.
*/
unhighlightFrame: function DVF_unhighlightFrame(aDepth) {
this.highlightFrame(aDepth, true)
this.highlightFrame(aDepth, true);
},
/**

View File

@ -81,6 +81,8 @@
<xul:button id="step-in">&debuggerUI.stepInButton;</xul:button>
<xul:button id="step-out">&debuggerUI.stepOutButton;</xul:button>
<xul:menulist id="scripts"/>
<xul:textbox id="scripts-search" type="search"
emptytext="&debuggerUI.emptyFilterText;"/>
</xul:toolbar>
<div id="dbg-content" class="hbox flex">
<div id="stack" class="vbox">

View File

@ -46,6 +46,7 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_BROWSER_TEST_FILES = \
browser_dbg_createRemote.js \
browser_dbg_debuggerstatement.js \
browser_dbg_listtabs.js \
browser_dbg_tabactor-01.js \
@ -70,6 +71,9 @@ _BROWSER_TEST_FILES = \
browser_dbg_stack-05.js \
browser_dbg_location-changes.js \
browser_dbg_script-switching.js \
browser_dbg_scripts-sorting.js \
browser_dbg_scripts-searching-01.js \
browser_dbg_scripts-searching-02.js \
browser_dbg_pause-resume.js \
browser_dbg_update-editor-mode.js \
$(warning browser_dbg_select-line.js temporarily disabled due to oranges, see bug 726609) \

View File

@ -23,37 +23,44 @@ function test()
let SourceEditor = tempScope.SourceEditor;
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.debuggerWindow;
resumed = true;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
runTest();
executeSoon(startTest);
});
executeSoon(function() {
gDebuggee.firstCall();
});
window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
let url = aEvent.detail.url;
if (url.indexOf("-02.js") != -1) {
scriptShown = true;
window.removeEventListener(aEvent.type, _onEvent);
runTest();
}
});
function runTest()
function onScriptShown(aEvent)
{
if (scriptShown && framesAdded) {
Services.tm.currentThread.dispatch({ run: onScriptShown }, 0);
scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
executeSoon(startTest);
}
window.addEventListener("Debugger:ScriptShown", onScriptShown);
function startTest()
{
if (scriptShown && framesAdded && resumed && !testStarted) {
window.removeEventListener("Debugger:ScriptShown", onScriptShown);
testStarted = true;
Services.tm.currentThread.dispatch({ run: performTest }, 0);
}
}
function onScriptShown()
function performTest()
{
gScripts = gDebugger.DebuggerView.Scripts;

View File

@ -21,37 +21,43 @@ function test()
let contextMenu = null;
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.debuggerWindow;
resumed = true;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
runTest();
executeSoon(startTest);
});
executeSoon(function() {
gDebuggee.firstCall();
});
window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
let url = aEvent.detail.url;
if (url.indexOf("-02.js") != -1) {
scriptShown = true;
window.removeEventListener(aEvent.type, _onEvent);
runTest();
}
});
function runTest()
function onScriptShown(aEvent) {
scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
executeSoon(startTest);
}
window.addEventListener("Debugger:ScriptShown", onScriptShown);
function startTest()
{
if (scriptShown && framesAdded) {
Services.tm.currentThread.dispatch({ run: onScriptShown }, 0);
if (scriptShown && framesAdded && resumed && !testStarted) {
testStarted = true;
window.removeEventListener("Debugger:ScriptShown", onScriptShown);
Services.tm.currentThread.dispatch({ run: performTest }, 0);
}
}
function onScriptShown()
function performTest()
{
let scripts = gDebugger.DebuggerView.Scripts._scripts;

View File

@ -0,0 +1,86 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var gProcess = null;
var gTab = null;
var gDebuggee = null;
function test() {
remote_debug_tab_pane(STACK_URL, aOnClosing, function(aTab, aDebuggee, aProcess) {
gTab = aTab;
gDebuggee = aDebuggee;
gProcess = aProcess;
testSimpleCall();
});
}
function testSimpleCall() {
Services.tm.currentThread.dispatch({ run: function() {
ok(gProcess._dbgProcess,
"The remote debugger process wasn't created properly!");
ok(gProcess._dbgProcess.isRunning,
"The remote debugger process isn't running!");
is(typeof gProcess._dbgProcess.pid, "number",
"The remote debugger process doesn't have a pid (?!)");
info("process location: " + gProcess._dbgProcess.location);
info("process pid: " + gProcess._dbgProcess.pid);
info("process name: " + gProcess._dbgProcess.processName);
info("process sig: " + gProcess._dbgProcess.processSignature);
ok(gProcess._dbgProfile,
"The remote debugger profile wasn't created properly!");
ok(gProcess._dbgProfile.localDir,
"The remote debugger profile doesn't have a localDir...");
ok(gProcess._dbgProfile.rootDir,
"The remote debugger profile doesn't have a rootDir...");
ok(gProcess._dbgProfile.name,
"The remote debugger profile doesn't have a name...");
info("profile localDir: " + gProcess._dbgProfile.localDir);
info("profile rootDir: " + gProcess._dbgProfile.rootDir);
info("profile name: " + gProcess._dbgProfile.name);
let profileService = Cc["@mozilla.org/toolkit/profile-service;1"]
.createInstance(Ci.nsIToolkitProfileService);
let profile = profileService.getProfileByName(gProcess._dbgProfile.name);
ok(profile,
"The remote debugger profile wasn't *actually* created properly!");
is(profile.localDir.path, gProcess._dbgProfile.localDir.path,
"The remote debugger profile doesn't have the correct localDir!");
is(profile.rootDir.path, gProcess._dbgProfile.rootDir.path,
"The remote debugger profile doesn't have the correct rootDir!");
DebuggerUI.toggleRemoteDebugger();
}}, 0);
}
function aOnClosing() {
ok(!gProcess._dbgProcess.isRunning,
"The remote debugger process isn't closed as it should be!");
is(gProcess._dbgProcess.exitValue, (Services.appinfo.OS == "WINNT" ? 0 : 256),
"The remote debugger process didn't die cleanly.");
info("process exit value: " + gProcess._dbgProcess.exitValue);
info("profile localDir: " + gProcess._dbgProfile.localDir.path);
info("profile rootDir: " + gProcess._dbgProfile.rootDir.path);
info("profile name: " + gProcess._dbgProfile.name);
executeSoon(function() {
finish();
});
}
registerCleanupFunction(function() {
removeTab(gTab);
gProcess = null;
gTab = null;
gDebuggee = null;
});

View File

@ -85,7 +85,8 @@ function resumeAndFinish() {
gDebugger.DebuggerController.activeThread.resume(function() {
let vs = gDebugger.DebuggerView.Scripts;
let ss = gDebugger.DebuggerController.SourceScripts;
ss._onScriptsCleared();
vs.empty();
vs._scripts.removeEventListener("select", vs._onScriptsChange, false);
is(ss._trimUrlQuery("a/b/c.d?test=1&random=4"), "a/b/c.d",
"Trimming the url query isn't done properly.");
@ -101,12 +102,11 @@ function resumeAndFinish() {
{ href: "si://interesting.address.moc/random/x/y/", leaf: "script.js?a=1&b=2&c=3" }
];
vs._scripts.removeEventListener("select", vs._onScriptsChange, false);
urls.forEach(function(url) {
executeSoon(function() {
let loc = url.href + url.leaf;
vs.addScript(ss._getScriptLabel(loc, url.href), { url: loc });
vs.commitScripts();
});
});

View File

@ -27,10 +27,10 @@ function testFrameParameters()
{
dump("Started testFrameParameters!\n");
gDebugger.addEventListener("Debugger:FetchedParameters", function test() {
dump("Entered Debugger:FetchedParameters!\n");
gDebugger.addEventListener("Debugger:FetchedVariables", function test() {
dump("Entered Debugger:FetchedVariables!\n");
gDebugger.removeEventListener("Debugger:FetchedParameters", test, false);
gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
Services.tm.currentThread.dispatch({ run: function() {
dump("After currentThread.dispatch!\n");
@ -52,33 +52,42 @@ function testFrameParameters()
is(frames.querySelectorAll(".dbg-stackframe").length, 3,
"Should have three frames.");
is(localNodes.length, 8,
is(localNodes.length, 11,
"The localScope should contain all the created variable elements.");
is(localNodes[0].querySelector(".info").textContent, "[object Proxy]",
"Should have the right property value for 'this'.");
is(localNodes[1].querySelector(".info").textContent, "[object Arguments]",
"Should have the right property value for 'arguments'.");
is(localNodes[2].querySelector(".info").textContent, "[object Object]",
is(localNodes[1].querySelector(".info").textContent, "[object Object]",
"Should have the right property value for 'aArg'.");
is(localNodes[3].querySelector(".info").textContent, '"beta"',
is(localNodes[2].querySelector(".info").textContent, '"beta"',
"Should have the right property value for 'bArg'.");
is(localNodes[4].querySelector(".info").textContent, "3",
is(localNodes[3].querySelector(".info").textContent, "3",
"Should have the right property value for 'cArg'.");
is(localNodes[5].querySelector(".info").textContent, "false",
is(localNodes[4].querySelector(".info").textContent, "false",
"Should have the right property value for 'dArg'.");
is(localNodes[6].querySelector(".info").textContent, "null",
is(localNodes[5].querySelector(".info").textContent, "null",
"Should have the right property value for 'eArg'.");
is(localNodes[7].querySelector(".info").textContent, "undefined",
is(localNodes[6].querySelector(".info").textContent, "undefined",
"Should have the right property value for 'fArg'.");
is(localNodes[7].querySelector(".info").textContent, "1",
"Should have the right property value for 'a'.");
is(localNodes[8].querySelector(".info").textContent, "[object Object]",
"Should have the right property value for 'b'.");
is(localNodes[9].querySelector(".info").textContent, "[object Object]",
"Should have the right property value for 'c'.");
is(localNodes[10].querySelector(".info").textContent, "[object Arguments]",
"Should have the right property value for 'arguments'.");
resumeAndFinish();
}}, 0);
}, false);

View File

@ -27,10 +27,10 @@ function testFrameParameters()
{
dump("Started testFrameParameters!\n");
gDebugger.addEventListener("Debugger:FetchedParameters", function test() {
dump("Entered Debugger:FetchedParameters!\n");
gDebugger.addEventListener("Debugger:FetchedVariables", function test() {
dump("Entered Debugger:FetchedVariables!\n");
gDebugger.removeEventListener("Debugger:FetchedParameters", test, false);
gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
Services.tm.currentThread.dispatch({ run: function() {
dump("After currentThread.dispatch!\n");
@ -50,16 +50,17 @@ function testFrameParameters()
is(frames.querySelectorAll(".dbg-stackframe").length, 3,
"Should have three frames.");
is(localNodes.length, 8,
is(localNodes.length, 11,
"The localScope should contain all the created variable elements.");
is(localNodes[0].querySelector(".info").textContent, "[object Proxy]",
"Should have the right property value for 'this'.");
// Expand the __proto__ and arguments tree nodes. This causes their
// properties to be retrieved and displayed.
// Expand the '__proto__', 'arguments' and 'a' tree nodes. This causes
// their properties to be retrieved and displayed.
localNodes[0].expand();
localNodes[1].expand();
localNodes[9].expand();
localNodes[10].expand();
// Poll every few milliseconds until the properties are retrieved.
// It's important to set the timer in the chrome window, because the
@ -70,7 +71,9 @@ function testFrameParameters()
ok(false, "Timed out while polling for the properties.");
resumeAndFinish();
}
if (!localNodes[0].fetched || !localNodes[1].fetched) {
if (!localNodes[0].fetched ||
!localNodes[9].fetched ||
!localNodes[10].fetched) {
return;
}
window.clearInterval(intervalID);
@ -82,14 +85,26 @@ function testFrameParameters()
.textContent.search(/object/) != -1,
"__proto__ should be an object.");
is(localNodes[1].querySelector(".info").textContent, "[object Arguments]",
is(localNodes[9].querySelector(".info").textContent, "[object Object]",
"Should have the right property value for 'c'.");
is(localNodes[9].querySelectorAll(".property > .title > .key")[1]
.textContent, "a",
"Should have the right property name for 'a'.");
is(localNodes[9].querySelectorAll(".property > .title > .value")[1]
.textContent, 1,
"Should have the right value for 'c.a'.");
is(localNodes[10].querySelector(".info").textContent,
"[object Arguments]",
"Should have the right property value for 'arguments'.");
is(localNodes[1].querySelector(".property > .title > .key")
is(localNodes[10].querySelector(".property > .title > .key")
.textContent, "length",
"Should have the right property name for length.");
"Should have the right property name for 'length'.");
is(localNodes[1].querySelector(".property > .title > .value")
is(localNodes[10].querySelector(".property > .title > .value")
.textContent, 5,
"Should have the right argument length.");
@ -104,7 +119,8 @@ function testFrameParameters()
}
function resumeAndFinish() {
gDebugger.DebuggerController.activeThread.addOneTimeListener("framescleared", function() {
let thread = gDebugger.DebuggerController.activeThread;
thread.addOneTimeListener("framescleared", function() {
Services.tm.currentThread.dispatch({ run: function() {
var frames = gDebugger.DebuggerView.StackFrames._frames;
@ -115,7 +131,7 @@ function resumeAndFinish() {
}}, 0);
});
gDebugger.DebuggerController.activeThread.resume();
thread.resume();
}
registerCleanupFunction(function() {

View File

@ -8,10 +8,6 @@
const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
let tempScope = {};
Cu.import("resource:///modules/source-editor.jsm", tempScope);
let SourceEditor = tempScope.SourceEditor;
var gPane = null;
var gTab = null;
var gDebuggee = null;
@ -22,33 +18,39 @@ function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.debuggerWindow;
resumed = true;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
runTest();
executeSoon(startTest);
});
executeSoon(function() {
gDebuggee.firstCall();
});
window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
let url = aEvent.detail.url;
if (url.indexOf("-02.js") != -1) {
scriptShown = true;
window.removeEventListener(aEvent.type, _onEvent);
runTest();
}
});
function runTest()
function onScriptShown(aEvent)
{
if (scriptShown && framesAdded) {
scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
executeSoon(startTest);
}
window.addEventListener("Debugger:ScriptShown", onScriptShown);
function startTest()
{
if (scriptShown && framesAdded && resumed && !testStarted) {
window.removeEventListener("Debugger:ScriptShown", onScriptShown);
testStarted = true;
Services.tm.currentThread.dispatch({ run: testScriptsDisplay }, 0);
}
}
@ -79,8 +81,6 @@ function testScriptsDisplay() {
ok(gDebugger.DebuggerView.Scripts.containsLabel(
label2), "Second script label is incorrect.");
dump("Debugger editor text:\n" + gDebugger.editor.getText() + "\n");
ok(gDebugger.editor.getText().search(/debugger/) != -1,
"The correct script was loaded initially.");
@ -100,8 +100,6 @@ function testScriptsDisplay() {
function testSwitchPaused()
{
dump("Debugger editor text:\n" + gDebugger.editor.getText() + "\n");
ok(gDebugger.editor.getText().search(/debugger/) == -1,
"The second script is no longer displayed.");
@ -127,6 +125,8 @@ function testSwitchPaused()
function testSwitchRunning()
{
dump("Debugger editor text:\n" + gDebugger.editor.getText() + "\n");
ok(gDebugger.editor.getText().search(/debugger/) != -1,
"The second script is displayed again.");

View File

@ -0,0 +1,188 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
var gEditor = null;
var gScripts = null;
var gSearchBox = null;
var gMenulist = null;
function test()
{
let scriptShown = false;
let framesAdded = false;
debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.debuggerWindow;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
runTest();
});
gDebuggee.simpleCall();
});
window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
window.removeEventListener(aEvent.type, _onEvent);
scriptShown = true;
runTest();
});
function runTest()
{
if (scriptShown && framesAdded) {
Services.tm.currentThread.dispatch({ run: testScriptSearching }, 0);
}
}
}
function testScriptSearching() {
gDebugger.DebuggerController.activeThread.resume(function() {
gEditor = gDebugger.DebuggerView.editor;
gScripts = gDebugger.DebuggerView.Scripts;
gSearchBox = gScripts._searchbox;
gMenulist = gScripts._scripts;
write(":12");
ok(gEditor.getCaretPosition().line == 11 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't jump to the correct line.");
write("@debugger");
ok(gEditor.getCaretPosition().line == 2 &&
gEditor.getCaretPosition().col == 44,
"The editor didn't jump to the correct token. (1)");
EventUtils.sendKey("RETURN");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2,
"The editor didn't jump to the correct token. (2)");
EventUtils.sendKey("ENTER");
ok(gEditor.getCaretPosition().line == 12 &&
gEditor.getCaretPosition().col == 8,
"The editor didn't jump to the correct token. (3)");
EventUtils.sendKey("ENTER");
ok(gEditor.getCaretPosition().line == 19 &&
gEditor.getCaretPosition().col == 4,
"The editor didn't jump to the correct token. (4)");
EventUtils.sendKey("RETURN");
ok(gEditor.getCaretPosition().line == 2 &&
gEditor.getCaretPosition().col == 44,
"The editor didn't jump to the correct token. (5)");
write(":bogus@debugger;");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2,
"The editor didn't jump to the correct token. (7)");
write(":13@debugger;");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2,
"The editor didn't jump to the correct token. (7)");
write(":@debugger;");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2,
"The editor didn't jump to the correct token. (8)");
write("::@debugger;");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2,
"The editor didn't jump to the correct token. (9)");
write(":::@debugger;");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2,
"The editor didn't jump to the correct token. (10)");
write(":i am not a number");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2,
"The editor didn't remain at the correct token. (11)");
write("@__i do not exist__");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2,
"The editor didn't remain at the correct token. (12)");
write(":1:2:3:a:b:c:::12");
ok(gEditor.getCaretPosition().line == 11 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't jump to the correct line. (13)");
write("@don't@find@me@instead@find@debugger");
ok(gEditor.getCaretPosition().line == 2 &&
gEditor.getCaretPosition().col == 44,
"The editor didn't jump to the correct token. (14)");
EventUtils.sendKey("RETURN");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2,
"The editor didn't jump to the correct token. (15)");
EventUtils.sendKey("ENTER");
ok(gEditor.getCaretPosition().line == 12 &&
gEditor.getCaretPosition().col == 8,
"The editor didn't jump to the correct token. (16)");
EventUtils.sendKey("RETURN");
ok(gEditor.getCaretPosition().line == 19 &&
gEditor.getCaretPosition().col == 4,
"The editor didn't jump to the correct token. (17)");
EventUtils.sendKey("ENTER");
ok(gEditor.getCaretPosition().line == 2 &&
gEditor.getCaretPosition().col == 44,
"The editor didn't jump to the correct token. (18)");
clear();
ok(gEditor.getCaretPosition().line == 2 &&
gEditor.getCaretPosition().col == 44,
"The editor didn't remain at the correct token. (19)");
is(gScripts.visibleItemsCount, 1,
"Not all the scripts are shown after the search. (20)");
closeDebuggerAndFinish(gTab);
});
}
function clear() {
gSearchBox.focus();
gSearchBox.value = "";
}
function write(text) {
clear();
for (let i = 0; i < text.length; i++) {
EventUtils.sendChar(text[i]);
}
dump("editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
gEditor = null;
gScripts = null;
gSearchBox = null;
gMenulist = null;
});

View File

@ -0,0 +1,146 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
var gEditor = null;
var gScripts = null;
var gSearchBox = null;
var gMenulist = null;
function test()
{
let scriptShown = false;
let framesAdded = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.debuggerWindow;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
runTest();
});
gDebuggee.firstCall();
});
window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
let url = aEvent.detail.url;
if (url.indexOf("-02.js") != -1) {
scriptShown = true;
window.removeEventListener(aEvent.type, _onEvent);
runTest();
}
});
function runTest()
{
if (scriptShown && framesAdded) {
Services.tm.currentThread.dispatch({ run: testScriptSearching }, 0);
}
}
}
function testScriptSearching() {
gDebugger.DebuggerController.activeThread.resume(function() {
gEditor = gDebugger.DebuggerView.editor;
gScripts = gDebugger.DebuggerView.Scripts;
gSearchBox = gScripts._searchbox;
gMenulist = gScripts._scripts;
firstSearch();
});
}
function firstSearch() {
window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
dump("Current script url:\n" + aEvent.detail.url + "\n");
dump("Debugger editor text:\n" + gEditor.getText() + "\n");
let url = aEvent.detail.url;
if (url.indexOf("-01.js") != -1) {
window.removeEventListener(aEvent.type, _onEvent);
executeSoon(function() {
dump("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
ok(gEditor.getCaretPosition().line == 4 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't jump to the correct line. (1)");
is(gScripts.visibleItemsCount, 1,
"Not all the correct scripts are shown after the search. (1)");
secondSearch();
});
}
});
write(".*-01\.js:5");
}
function secondSearch() {
window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
dump("Current script url:\n" + aEvent.detail.url + "\n");
dump("Debugger editor text:\n" + gEditor.getText() + "\n");
let url = aEvent.detail.url;
if (url.indexOf("-02.js") != -1) {
window.removeEventListener(aEvent.type, _onEvent);
executeSoon(function() {
dump("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
ok(gEditor.getCaretPosition().line == 5 &&
gEditor.getCaretPosition().col == 8,
"The editor didn't jump to the correct line. (2)");
is(gScripts.visibleItemsCount, 1,
"Not all the correct scripts are shown after the search. (2)");
finalCheck();
});
}
});
write(".*-02\.js@debugger;");
}
function finalCheck() {
clear();
ok(gEditor.getCaretPosition().line == 5 &&
gEditor.getCaretPosition().col == 8,
"The editor didn't remain at the correct token. (3)");
is(gScripts.visibleItemsCount, 2,
"Not all the scripts are shown after the search. (3)");
closeDebuggerAndFinish(gTab);
}
function clear() {
gSearchBox.focus();
gSearchBox.value = "";
}
function write(text) {
clear();
for (let i = 0; i < text.length; i++) {
EventUtils.sendChar(text[i]);
}
dump("editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
gEditor = null;
gScripts = null;
gSearchBox = null;
gMenulist = null;
});

View File

@ -0,0 +1,124 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
function test() {
debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.debuggerWindow;
testSimpleCall();
});
}
function testSimpleCall() {
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
resumeAndFinish();
}}, 0);
});
gDebuggee.simpleCall();
}
function resumeAndFinish() {
gDebugger.DebuggerController.activeThread.resume(function() {
checkScriptsOrder();
addScriptsAndCheckOrder(1, function() {
addScriptsAndCheckOrder(2, function() {
addScriptsAndCheckOrder(3, function() {
closeDebuggerAndFinish(gTab);
});
});
});
});
}
function addScriptsAndCheckOrder(method, callback) {
let vs = gDebugger.DebuggerView.Scripts;
let ss = gDebugger.DebuggerController.SourceScripts;
vs.empty();
vs._scripts.removeEventListener("select", vs._onScriptsChange, false);
let urls = [
{ href: "ici://some.address.com/random/", leaf: "subrandom/" },
{ href: "ni://another.address.org/random/subrandom/", leaf: "page.html" },
{ href: "san://interesting.address.gro/random/", leaf: "script.js" },
{ href: "si://interesting.address.moc/random/", leaf: "script.js" },
{ href: "si://interesting.address.moc/random/", leaf: "x/script.js" },
{ href: "si://interesting.address.moc/random/", leaf: "x/y/script.js?a=1" },
{ href: "si://interesting.address.moc/random/x/", leaf: "y/script.js?a=1&b=2" },
{ href: "si://interesting.address.moc/random/x/y/", leaf: "script.js?a=1&b=2&c=3" }
];
urls.sort(function(a, b) {
return Math.random() - 0.5;
});
switch (method) {
case 1:
urls.forEach(function(url) {
let loc = url.href + url.leaf;
vs.addScript(ss._getScriptLabel(loc, url.href), { url: loc });
});
vs.commitScripts();
break;
case 2:
urls.forEach(function(url) {
let loc = url.href + url.leaf;
vs.addScript(ss._getScriptLabel(loc, url.href), { url: loc }, true);
});
break;
case 3:
let i = 0
for (; i < urls.length / 2; i++) {
let url = urls[i];
let loc = url.href + url.leaf;
vs.addScript(ss._getScriptLabel(loc, url.href), { url: loc });
}
vs.commitScripts();
for (; i < urls.length; i++) {
let url = urls[i];
let loc = url.href + url.leaf;
vs.addScript(ss._getScriptLabel(loc, url.href), { url: loc }, true);
}
break;
}
executeSoon(function() {
checkScriptsOrder(method);
callback();
});
}
function checkScriptsOrder(method) {
let labels = gDebugger.DebuggerView.Scripts.scriptLabels;
let sorted = labels.reduce(function(prev, curr, index, array) {
return array[index - 1] < array[index];
});
ok(sorted,
"Using method " + method + ", " +
"the scripts weren't in the correct order: " + labels.toSource());
return sorted;
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
});

View File

@ -22,32 +22,38 @@ function test()
{
let scriptShown = false;
let framesAdded = false;
let testStarted = false;
let resumed = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.debuggerWindow;
resumed = true;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
runTest();
executeSoon(startTest);
});
executeSoon(function() {
gDebuggee.firstCall();
});
window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
let url = aEvent.detail.url;
if (url.indexOf("editor-mode") != -1) {
scriptShown = true;
window.removeEventListener(aEvent.type, _onEvent);
runTest();
}
});
function runTest()
function onScriptShown(aEvent) {
scriptShown = aEvent.detail.url.indexOf("test-editor-mode") != -1;
executeSoon(startTest);
}
window.addEventListener("Debugger:ScriptShown", onScriptShown);
function startTest()
{
if (scriptShown && framesAdded) {
if (scriptShown && framesAdded && resumed && !testStarted) {
window.removeEventListener("Debugger:ScriptShown", onScriptShown);
testStarted = true;
Services.tm.currentThread.dispatch({ run: testScriptsDisplay }, 0);
}
}

View File

@ -92,7 +92,6 @@ function debug_tab_pane(aURL, aOnDebugging)
{
let tab = addTab(aURL, function() {
gBrowser.selectedTab = gTab;
let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
let pane = DebuggerUI.toggleDebugger();
@ -106,3 +105,17 @@ function debug_tab_pane(aURL, aOnDebugging)
}, true);
});
}
function remote_debug_tab_pane(aURL, aOnClosing, aOnDebugging)
{
let tab = addTab(aURL, function() {
gBrowser.selectedTab = gTab;
let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
DebuggerUI.toggleRemoteDebugger(aOnClosing, function dbgRan(process) {
// Wait for the remote debugging process to start...
aOnDebugging(tab, debuggee, process);
});
});
}

View File

@ -293,11 +293,15 @@ InspectorUI.prototype = {
buildButtonsTooltip: function IUI_buildButtonsTooltip()
{
let keysbundle = Services.strings.createBundle("chrome://global-platform/locale/platformKeys.properties");
let separator = keysbundle.GetStringFromName("MODIFIER_SEPARATOR");
let button, tooltip;
// Inspect Button - the shortcut string is built from the <key> element
let key = this.chromeDoc.getElementById("key_inspect");
if (key) {
let modifiersAttr = key.getAttribute("modifiers");
let combo = [];
@ -319,11 +323,13 @@ InspectorUI.prototype = {
combo.push(key.getAttribute("key"));
let separator = keysbundle.GetStringFromName("MODIFIER_SEPARATOR");
let tooltip = this.strings.formatStringFromName("inspectButton.tooltiptext",
tooltip = this.strings.formatStringFromName("inspectButtonWithShortcutKey.tooltip",
[combo.join(separator)], 1);
let button = this.chromeDoc.getElementById("inspector-inspect-toolbutton");
} else {
tooltip = this.strings.GetStringFromName("inspectButton.tooltip");
}
button = this.chromeDoc.getElementById("inspector-inspect-toolbutton");
button.setAttribute("tooltiptext", tooltip);
// Markup Button - the shortcut string is built from the accesskey attribute
@ -335,7 +341,6 @@ InspectorUI.prototype = {
#else
let altString = keysbundle.GetStringFromName("VK_ALT");
let accesskey = button.getAttribute("accesskey");
let separator = keysbundle.GetStringFromName("MODIFIER_SEPARATOR");
let shortcut = altString + separator + accesskey;
tooltip = this.strings.formatStringFromName("markupButton.tooltipWithAccesskey",
[shortcut], 1);

View File

@ -42,6 +42,11 @@ var EXPORTED_SYMBOLS = [ "Templater", "template" ];
Components.utils.import("resource://gre/modules/Services.jsm");
const Node = Components.interfaces.nsIDOMNode;
/**
* For full documentation, see:
* https://github.com/mozilla/domtemplate/blob/master/README.md
*/
// WARNING: do not 'use_strict' without reading the notes in _envEval();
/**
@ -50,8 +55,16 @@ const Node = Components.interfaces.nsIDOMNode;
* @param data Data to use in filling out the template
* @param options Options to customize the template processing. One of:
* - allowEval: boolean (default false) Basic template interpolations are
* either property paths (e.g. ${a.b.c.d}), however if allowEval=true then we
* either property paths (e.g. ${a.b.c.d}), or if allowEval=true then we
* allow arbitrary JavaScript
* - stack: string or array of strings (default empty array) The template
* engine maintains a stack of tasks to help debug where it is. This allows
* this stack to be prefixed with a template name
* - blankNullUndefined: By default DOMTemplate exports null and undefined
* values using the strings 'null' and 'undefined', which can be helpful for
* debugging, but can introduce unnecessary extra logic in a template to
* convert null/undefined to ''. By setting blankNullUndefined:true, this
* conversion is handled by DOMTemplate
*/
function template(node, data, options) {
var template = new Templater(options || {});
@ -68,7 +81,15 @@ function Templater(options) {
options = { allowEval: true };
}
this.options = options;
if (options.stack && Array.isArray(options.stack)) {
this.stack = options.stack;
}
else if (typeof options.stack === 'string') {
this.stack = [ options.stack ];
}
else {
this.stack = [];
}
}
/**
@ -90,7 +111,7 @@ Templater.prototype._splitSpecial = /\uF001|\uF002/;
* Cached regex used to detect if a script is capable of being interpreted
* using Template._property() or if we need to use Template._envEval()
*/
Templater.prototype._isPropertyScript = /^[a-zA-Z0-9.]*$/;
Templater.prototype._isPropertyScript = /^[_a-zA-Z0-9.]*$/;
/**
* Recursive function to walk the tree processing the attributes as it goes.
@ -153,7 +174,11 @@ Templater.prototype.processNode = function(node, data) {
} else {
// Replace references in all other attributes
var newValue = value.replace(this._templateRegion, function(path) {
return this._envEval(path.slice(2, -1), data, value);
var insert = this._envEval(path.slice(2, -1), data, value);
if (this.options.blankNullUndefined && insert == null) {
insert = '';
}
return insert;
}.bind(this));
// Remove '_' prefix of attribute names so the DOM won't try
// to use them before we've processed the template
@ -177,7 +202,7 @@ Templater.prototype.processNode = function(node, data) {
this.processNode(childNodes[j], data);
}
if (node.nodeType === Node.TEXT_NODE) {
if (node.nodeType === 3 /*Node.TEXT_NODE*/) {
this._processTextNode(node, data);
}
} finally {
@ -347,8 +372,27 @@ Templater.prototype._processTextNode = function(node, data) {
part = this._envEval(part.slice(1), data, node.data);
}
this._handleAsync(part, node, function(reply, siblingNode) {
reply = this._toNode(reply, siblingNode.ownerDocument);
var doc = siblingNode.ownerDocument;
if (reply == null) {
reply = this.options.blankNullUndefined ? '' : '' + reply;
}
if (typeof reply.cloneNode === 'function') {
// i.e. if (reply instanceof Element) { ...
reply = this._maybeImportNode(reply, doc);
siblingNode.parentNode.insertBefore(reply, siblingNode);
} else if (typeof reply.item === 'function' && reply.length) {
// if thing is a NodeList, then import the children
for (var i = 0; i < reply.length; i++) {
var child = this._maybeImportNode(reply.item(i), doc);
siblingNode.parentNode.insertBefore(child, siblingNode);
}
}
else {
// if thing isn't a DOM element then wrap its string value in one
reply = doc.createTextNode(reply.toString());
siblingNode.parentNode.insertBefore(reply, siblingNode);
}
}.bind(this));
}, this);
node.parentNode.removeChild(node);
@ -356,21 +400,13 @@ Templater.prototype._processTextNode = function(node, data) {
};
/**
* Helper to convert a 'thing' to a DOM Node.
* This is (obviously) a no-op for DOM Elements (which are detected using
* 'typeof thing.cloneNode !== "function"' (is there a better way that will
* work in all environments, including a .jsm?)
* Non DOM elements are converted to a string and wrapped in a TextNode.
* Return node or a import of node, if it's not in the given document
* @param node The node that we want to be properly owned
* @param doc The document that the given node should belong to
* @return A node that belongs to the given document
*/
Templater.prototype._toNode = function(thing, document) {
if (thing == null) {
thing = '' + thing;
}
// if thing isn't a DOM element then wrap its string value in one
if (typeof thing.cloneNode !== 'function') {
thing = document.createTextNode(thing.toString());
}
return thing;
Templater.prototype._maybeImportNode = function(node, doc) {
return node.ownerDocument === doc ? node : doc.importNode(node, true);
};
/**
@ -429,7 +465,6 @@ Templater.prototype._stripBraces = function(str) {
* <tt>newValue</tt> is applied.
*/
Templater.prototype._property = function(path, data, newValue) {
this.stack.push(path);
try {
if (typeof path === 'string') {
path = path.split('.');
@ -445,12 +480,13 @@ Templater.prototype._property = function(path, data, newValue) {
return value;
}
if (!value) {
this._handleError('Can\'t find path=' + path);
this._handleError('"' + path[0] + '" is undefined');
return null;
}
return this._property(path.slice(1), value, newValue);
} finally {
this.stack.pop();
} catch (ex) {
this._handleError('Path error with \'' + path + '\'', ex);
return '${' + path + '}';
}
};
@ -469,7 +505,7 @@ Templater.prototype._property = function(path, data, newValue) {
*/
Templater.prototype._envEval = function(script, data, frame) {
try {
this.stack.push(frame);
this.stack.push(frame.replace(/\s+/g, ' '));
if (this._isPropertyScript.test(script)) {
return this._property(script, data);
} else {
@ -483,8 +519,7 @@ Templater.prototype._envEval = function(script, data, frame) {
}
}
} catch (ex) {
this._handleError('Template error evaluating \'' + script + '\'' +
' environment=' + Object.keys(data).join(', '), ex);
this._handleError('Template error evaluating \'' + script + '\'', ex);
return '${' + script + '}';
} finally {
this.stack.pop();
@ -498,8 +533,7 @@ Templater.prototype._envEval = function(script, data, frame) {
* @param ex optional associated exception.
*/
Templater.prototype._handleError = function(message, ex) {
this._logError(message);
this._logError('In: ' + this.stack.join(' > '));
this._logError(message + ' (In: ' + this.stack.join(' > ') + ')');
if (ex) {
this._logError(ex);
}

View File

@ -3,11 +3,15 @@
// Tests that the DOM Template engine works properly
let tempScope = {};
Cu.import("resource:///modules/devtools/Templater.jsm", tempScope);
Cu.import("resource:///modules/devtools/Promise.jsm", tempScope);
let template = tempScope.template;
let Promise = tempScope.Promise;
/*
* These tests run both in Mozilla/Mochitest and plain browsers (as does
* domtemplate)
* We should endevour to keep the source in sync.
*/
var imports = {};
Cu.import("resource:///modules/devtools/Templater.jsm", imports);
Cu.import("resource:///modules/devtools/Promise.jsm", imports);
function test() {
addTab("http://example.com/browser/browser/devtools/shared/test/browser_templater_basic.html", function() {
@ -25,7 +29,7 @@ function runTest(index) {
holder.innerHTML = options.template;
info('Running ' + options.name);
template(holder, options.data, options.options);
imports.template(holder, options.data, options.options);
if (typeof options.result == 'string') {
is(holder.innerHTML, options.result, options.name);
@ -238,11 +242,43 @@ var tests = [
name: 'propertyFail',
template: '<p>${Math.max(1, 2)}</p>',
result: '<p>${Math.max(1, 2)}</p>'
};},
// Bug 723431: DOMTemplate should allow customisation of display of
// null/undefined values
function() { return {
name: 'propertyUndefAttrFull',
template: '<p>${nullvar}|${undefinedvar1}|${undefinedvar2}</p>',
data: { nullvar: null, undefinedvar1: undefined },
result: '<p>null|undefined|undefined</p>'
};},
function() { return {
name: 'propertyUndefAttrBlank',
template: '<p>${nullvar}|${undefinedvar1}|${undefinedvar2}</p>',
data: { nullvar: null, undefinedvar1: undefined },
options: { blankNullUndefined: true },
result: '<p>||</p>'
};},
function() { return {
name: 'propertyUndefAttrFull',
template: '<div><p value="${nullvar}"></p><p value="${undefinedvar1}"></p><p value="${undefinedvar2}"></p></div>',
data: { nullvar: null, undefinedvar1: undefined },
result: '<div><p value="null"></p><p value="undefined"></p><p value="undefined"></p></div>'
};},
function() { return {
name: 'propertyUndefAttrBlank',
template: '<div><p value="${nullvar}"></p><p value="${undefinedvar1}"></p><p value="${undefinedvar2}"></p></div>',
data: { nullvar: null, undefinedvar1: undefined },
options: { blankNullUndefined: true },
result: '<div><p value=""></p><p value=""></p><p value=""></p></div>'
};}
];
function delayReply(data) {
var p = new Promise();
var p = new imports.Promise();
executeSoon(function() {
p.resolve(data);
});

View File

@ -11,6 +11,14 @@
- application menu item that opens the debugger UI. -->
<!ENTITY debuggerMenu.label "Script Debugger">
<!-- LOCALIZATION NOTE (remoteDebuggerMenu.label): This is the label for the
- application menu item that opens the remote debugger UI. -->
<!ENTITY remoteDebuggerMenu.label "Remote Debugger">
<!-- LOCALIZATION NOTE (chromeDebuggerMenu.label): This is the label for the
- application menu item that opens the browser debugger UI. -->
<!ENTITY chromeDebuggerMenu.label "Browser Debugger">
<!-- LOCALIZATION NOTE (debuggerMenu.commandkey): This is the command key that
- launches the debugger UI. Do not translate this one! -->
<!ENTITY debuggerMenu.commandkey "S">
@ -44,3 +52,7 @@
- widget that displays the variables in the various available scopes in the
- debugger. -->
<!ENTITY debuggerUI.propertiesTitle "Scope variables">
<!-- LOCALIZATION NOTE (debuggerUI.emptyFilterText): This is the text that
- appears in the filter text box when it is empty. -->
<!ENTITY debuggerUI.emptyFilterText "Filter scripts">

View File

@ -38,9 +38,9 @@ withScope=With block
# pane as a header on container for identifiers in a closure scope.
closureScope=Closure
# LOCALIZATION NOTE (emptyText): The text that is displayed in the stack frames
# list when there are no frames to display.
emptyText=Empty
# LOCALIZATION NOTE (emptyStackText): The text that is displayed in the stack
# frames list when there are no frames to display.
emptyStackText=No stacks to display.
# LOCALIZATION NOTE (loadingText): The text that is displayed in the script
# editor when the laoding process has started but there is no file to display

View File

@ -20,11 +20,16 @@ breadcrumbs.siblings=Siblings
# LOCALIZATION NOTE (htmlPanel): Used in the Inspector tool's openInspectorUI
# method when registering the HTML panel.
# LOCALIZATION NOTE (inspectButton.tooltiptext):
# LOCALIZATION NOTE (inspectButtonWithShortcutKey.tooltip):
# This button appears in the Inspector Toolbar. inspectButton is stateful,
# if it's pressed users can select an element with the mouse.
# %S is the keyboard shortcut.
inspectButton.tooltiptext=Select element with mouse (%S)
inspectButtonWithShortcutKey.tooltip=Select element with mouse (%S)
# LOCALIZATION NOTE (inspectButton.tooltip):
# Same as inspectButtonWithShortcutKey.tooltip but used when an add-on
# overrides the shortcut key.
inspectButton.tooltip=Select element with mouse
# LOCALIZATION NOTE (markupButton.*):
# This button is the button located at the beginning of the breadcrumbs

View File

@ -23,11 +23,6 @@
<!ENTITY view.sortDescending.label "Z > A Sort Order">
<!ENTITY view.sortDescending.accesskey "Z">
<!ENTITY cmd.findInBookmarks.label "Find in Bookmarks…">
<!ENTITY cmd.findInBookmarks.accesskey "F">
<!ENTITY cmd.findCurrent.label "Find in Current Collection…">
<!ENTITY cmd.findCurrent.accesskey "i">
<!ENTITY importBookmarksFromHTML.label "Import Bookmarks from HTML…">
<!ENTITY importBookmarksFromHTML.accesskey "I">
<!ENTITY exportBookmarksToHTML.label "Export Bookmarks to HTML…">

View File

@ -44,7 +44,6 @@ searchBookmarks=Search Bookmarks
searchHistory=Search History
searchDownloads=Search Downloads
searchCurrentDefault=Search in '%S'
findInPrefix=Find in '%S'…
tabs.openWarningTitle=Confirm open
tabs.openWarningMultipleBranded=You are about to open %S tabs. This might slow down %S while the pages are loading. Are you sure you want to continue?

View File

@ -1260,6 +1260,7 @@ toolbar[iconsize="small"] #feed-button {
.notification-anchor-icon {
width: 16px;
height: 16px;
margin: 0 2px;
}
.notification-anchor-icon:-moz-focusring {

View File

@ -2321,6 +2321,7 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
.notification-anchor-icon {
width: 16px;
height: 16px;
margin: 0 2px;
}
.notification-anchor-icon:-moz-focusring {

View File

@ -1,5 +1,53 @@
dnl Add compiler specific options
AC_DEFUN([MOZ_DEFAULT_COMPILER],
[
dnl Default to MSVC for win32 and gcc-4.2 for darwin
dnl ==============================================================
if test -z "$CROSS_COMPILE"; then
case "$target" in
*-mingw*)
if test -z "$CC"; then CC=cl; fi
if test -z "$CXX"; then CXX=cl; fi
if test -z "$CPP"; then CPP="cl -E -nologo"; fi
if test -z "$CXXCPP"; then CXXCPP="cl -TP -E -nologo"; ac_cv_prog_CXXCPP="$CXXCPP"; fi
if test -z "$LD"; then LD=link; fi
if test -z "$AS"; then
case "${target_cpu}" in
i*86)
AS=ml;
;;
x86_64)
AS=ml64;
;;
esac
fi
if test -z "$MIDL"; then MIDL=midl; fi
# need override this flag since we don't use $(LDFLAGS) for this.
if test -z "$HOST_LDFLAGS" ; then
HOST_LDFLAGS=" "
fi
;;
*-darwin*)
# we prefer gcc-4.2 over gcc on older darwin, so
# use that specific version if it's available.
# On newer versions of darwin, gcc is llvm-gcc while gcc-4.2 is the plain
# one, so we also try that first. If that fails, we fall back to clang
# as llvm-gcc is an unsupported dead end.
MOZ_PATH_PROGS(CC, $CC gcc-4.2 clang gcc)
MOZ_PATH_PROGS(CXX, $CXX g++-4.2 clang++ g++)
IS_LLVM_GCC=$($CC -v 2>&1 | grep llvm-gcc)
if test -n "$IS_LLVM_GCC"
then
echo llvm-gcc is known to be broken, please use gcc-4.2 or clang.
exit 1
fi
;;
esac
fi
])
AC_DEFUN([MOZ_COMPILER_OPTS],
[
if test "$CLANG_CXX"; then

View File

@ -507,6 +507,10 @@ class ShutdownLeakLogger(object):
created = line[:2] == "++"
id = self._parseValue(line, "serial")
# log line has invalid format
if not id:
return
if self.currentTest:
windows = self.currentTest["windows"]
if created:
@ -520,6 +524,10 @@ class ShutdownLeakLogger(object):
created = line[:2] == "++"
id = self._parseValue(line, "id")
# log line has invalid format
if not id:
return
if self.currentTest:
docShells = self.currentTest["docShells"]
if created:
@ -530,7 +538,10 @@ class ShutdownLeakLogger(object):
self.leakedDocShells.add(id)
def _parseValue(self, line, name):
return re.search("\[%s = (.+?)\]" % name, line).group(1)
match = re.search("\[%s = (.+?)\]" % name, line)
if match:
return match.group(1)
return None
def _parseLeakingTests(self):
leakingTests = []

View File

@ -70,7 +70,7 @@ import org.json.*;
import com.jayway.android.robotium.solo.Solo;
public class FennecNativeDriver implements Driver {
private static final int FRAME_TIME_THRESHOLD = 17; // allow 17ms per frame (~60fps)
private static final int FRAME_TIME_THRESHOLD = 25; // allow 25ms per frame (40fps)
// Map of IDs to element names.
private HashMap mLocators = null;
@ -231,20 +231,27 @@ public class FennecNativeDriver implements Driver {
try {
Object [] params = null;
List<Long> frames = (List<Long>)_stopFrameRecording.invoke(null, params);
int numDelays = 0;
int badness = 0;
for (int i = 1; i < frames.size(); i++) {
if (frames.get(i) - frames.get(i-1) > FRAME_TIME_THRESHOLD) {
numDelays++;
long frameTime = frames.get(i) - frames.get(i - 1);
int delay = (int)(frameTime - FRAME_TIME_THRESHOLD);
// for each frame we miss, add the square of the delay. This
// makes large delays much worse than small delays.
if (delay > 0) {
badness += delay * delay;
}
}
return numDelays;
// Don't do any averaging of the numbers because really we want to
// know how bad the jank was at its worst
return badness;
} catch (IllegalAccessException e) {
log(LogLevel.ERROR, e);
} catch (InvocationTargetException e) {
log(LogLevel.ERROR, e);
}
return 0;
// higher values are worse, and the test failing is the worst!
return Integer.MAX_VALUE;
}
public void startCheckerboardRecording() {

View File

@ -92,7 +92,7 @@ def build_linux_headers_aux(inst_dir):
run_in(linux_source_dir, [old_make, "headers_check"])
run_in(linux_source_dir, [old_make, "INSTALL_HDR_PATH=dest",
"headers_install"])
shutil.move(linux_source_dir + "/dest", inst_dir)
shutil.move(linux_source_dir + "/dest/include", inst_dir + '/include')
def build_linux_headers(inst_dir):
def f():
@ -151,6 +151,10 @@ def build_one_stage_aux(stage_dir, is_stage_one):
"--with-mpfr=%s" % lib_inst_dir])
tool_inst_dir = stage_dir + '/inst'
os.mkdir(tool_inst_dir)
os.mkdir(tool_inst_dir + '/lib64')
os.symlink('lib64', tool_inst_dir + '/lib')
build_linux_headers(tool_inst_dir)
binutils_build_dir = stage_dir + '/binutils'

View File

@ -0,0 +1,12 @@
export INCLUDE=/c/tools/msvs10/vc/include:/c/tools/msvs10/vc/atlmfc/include:/c/tools/sdks/v7.0/include:/c/tools/sdks/v7.0/include/atl:/c/tools/sdks/dx10/include
export LIBPATH=/c/tools/msvs10/vc/lib:/c/tools/msvs10/vc/atlmfc/lib
export LIB=/c/tools/msvs10/vc/lib:/c/tools/msvs10/vc/atlmfc/lib:/c/tools/sdks/v7.0/lib:/c/tools/sdks/dx10/lib
export PATH="/c/tools/msvs10/Common7/IDE:/c/tools/msvs10/VC/BIN:/c/tools/msvs10/Common7/Tools:/c/tools/msvs10/VC/VCPackages:${PATH}"
export WIN32_REDIST_DIR=/c/tools/msvs10/VC/redist/x86/Microsoft.VC100.CRT
mk_add_options "export LIB=$LIB"
mk_add_options "export LIBPATH=$LIBPATH"
mk_add_options "export PATH=$PATH"
mk_add_options "export INCLUDE=$INCLUDE"
mk_add_options "export WIN32_REDIST_DIR=$WIN32_REDIST_DIR"

View File

@ -94,7 +94,7 @@
#include "nsIContentSecurityPolicy.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/bindings/Utils.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/StandardInteger.h"
using namespace mozilla;
@ -2483,8 +2483,8 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
priv = (nsISupports *) js::GetObjectPrivate(aObj);
} else if ((jsClass->flags & JSCLASS_IS_DOMJSCLASS) &&
bindings::DOMJSClass::FromJSClass(jsClass)->mDOMObjectIsISupports) {
priv = bindings::UnwrapDOMObject<nsISupports>(aObj, jsClass);
DOMJSClass::FromJSClass(jsClass)->mDOMObjectIsISupports) {
priv = UnwrapDOMObject<nsISupports>(aObj, jsClass);
} else {
priv = nsnull;
}

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