Merge from mozilla-central.

This commit is contained in:
David Anderson 2012-05-11 14:35:58 -07:00
commit c093e3fa4d
342 changed files with 12329 additions and 17082 deletions

View File

@ -69,18 +69,7 @@ CPPSRCS = \
$(NULL)
EXPORTS = \
ARIAGridAccessibleWrap.h \
AtkSocketAccessible.h \
nsAccessNodeWrap.h \
nsAccessibleWrap.h \
nsDocAccessibleWrap.h \
nsTextAccessibleWrap.h \
nsXULMenuAccessibleWrap.h \
nsXULListboxAccessibleWrap.h \
nsXULTreeGridAccessibleWrap.h \
nsHyperTextAccessibleWrap.h \
nsHTMLImageAccessibleWrap.h \
nsHTMLTableAccessibleWrap.h \
$(NULL)
# we want to force the creation of a static lib.

View File

@ -67,7 +67,6 @@ nsAccessNodeWrap::~nsAccessNodeWrap()
void nsAccessNodeWrap::InitAccessibility()
{
nsAccessNode::InitXPAccessibility();
}
void nsAccessNodeWrap::ShutdownAccessibility()

View File

@ -75,22 +75,16 @@ refAtCB(AtkTable *aTable, gint aRow, gint aColumn)
}
static gint
getIndexAtCB(AtkTable *aTable, gint aRow, gint aColumn)
getIndexAtCB(AtkTable* aTable, gint aRow, gint aColumn)
{
nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
if (!accWrap)
return -1;
nsAccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
if (!accWrap)
return -1;
nsCOMPtr<nsIAccessibleTable> accTable;
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
getter_AddRefs(accTable));
NS_ENSURE_TRUE(accTable, -1);
TableAccessible* table = accWrap->AsTable();
NS_ENSURE_TRUE(table, -1);
PRInt32 index;
nsresult rv = accTable->GetCellIndexAt(aRow, aColumn, &index);
NS_ENSURE_SUCCESS(rv, -1);
return static_cast<gint>(index);
return static_cast<gint>(table->CellIndexAt(aRow, aColumn));
}
static gint

View File

@ -71,6 +71,7 @@ CPPSRCS = \
nsCaretAccessible.cpp \
nsTextAccessible.cpp \
nsTextEquivUtils.cpp \
RoleAsserts.cpp \
StyleInfo.cpp \
TextAttrs.cpp \
TextUpdater.cpp \

View File

@ -0,0 +1,17 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsIAccessibleRole.h"
#include "Role.h"
#include "mozilla/Assertions.h"
using namespace mozilla::a11y;
#define ROLE(geckoRole, stringRole, atkRole, macRole, msaaRole, ia2Role) \
MOZ_STATIC_ASSERT(roles::geckoRole == nsIAccessibleRole::ROLE_ ## geckoRole, "internal and xpcom roles differ!");
#include "RoleMap.h"
#undef ROLE

View File

@ -51,7 +51,6 @@
#include "nsIInterfaceRequestorUtils.h"
#include "nsIPresShell.h"
#include "nsIServiceManager.h"
#include "nsIStringBundle.h"
#include "nsFocusManager.h"
#include "nsPresContext.h"
#include "mozilla/Services.h"
@ -62,8 +61,6 @@ using namespace mozilla::a11y;
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
*/
nsIStringBundle *nsAccessNode::gStringBundle = 0;
ApplicationAccessible* nsAccessNode::gApplicationAccessible = nsnull;
/*
@ -149,25 +146,12 @@ nsAccessNode::GetApplicationAccessible()
return gApplicationAccessible;
}
void nsAccessNode::InitXPAccessibility()
{
nsCOMPtr<nsIStringBundleService> stringBundleService =
mozilla::services::GetStringBundleService();
if (stringBundleService) {
// Static variables are released in ShutdownAllXPAccessibility();
stringBundleService->CreateBundle(ACCESSIBLE_BUNDLE_URL,
&gStringBundle);
}
}
void nsAccessNode::ShutdownXPAccessibility()
{
// Called by nsAccessibilityService::Shutdown()
// which happens when xpcom is shutting down
// at exit of program
NS_IF_RELEASE(gStringBundle);
// Release gApplicationAccessible after everything else is shutdown
// so we don't accidently create it again while tearing down root accessibles
ApplicationAccessibleWrap::Unload();

View File

@ -69,9 +69,6 @@ class nsPresContext;
class nsIFrame;
class nsIDocShellTreeItem;
#define ACCESSIBLE_BUNDLE_URL "chrome://global-platform/locale/accessible.properties"
#define PLATFORM_KEYS_BUNDLE_URL "chrome://global-platform/locale/platformKeys.properties"
class nsAccessNode: public nsISupports
{
public:
@ -79,11 +76,10 @@ public:
nsAccessNode(nsIContent* aContent, nsDocAccessible* aDoc);
virtual ~nsAccessNode();
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(nsAccessNode)
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(nsAccessNode)
static void InitXPAccessibility();
static void ShutdownXPAccessibility();
static void ShutdownXPAccessibility();
/**
* Return an application accessible.
@ -164,9 +160,6 @@ protected:
nsCOMPtr<nsIContent> mContent;
nsDocAccessible* mDoc;
// Static data, we do our own refcounting for our static data.
static nsIStringBundle* gStringBundle;
private:
nsAccessNode() MOZ_DELETE;
nsAccessNode(const nsAccessNode&) MOZ_DELETE;

View File

@ -82,6 +82,7 @@
#include "nsLayoutUtils.h"
#include "nsIPresShell.h"
#include "nsIStringBundle.h"
#include "nsPresContext.h"
#include "nsIFrame.h"
#include "nsIView.h"
@ -626,12 +627,24 @@ nsAccessible::GetIndexInParent(PRInt32 *aIndexInParent)
}
void
nsAccessible::TranslateString(const nsAString& aKey, nsAString& aStringOut)
nsAccessible::TranslateString(const nsString& aKey, nsAString& aStringOut)
{
nsXPIDLString xsValue;
nsCOMPtr<nsIStringBundleService> stringBundleService =
services::GetStringBundleService();
if (!stringBundleService)
return;
gStringBundle->GetStringFromName(PromiseFlatString(aKey).get(), getter_Copies(xsValue));
aStringOut.Assign(xsValue);
nsCOMPtr<nsIStringBundle> stringBundle;
stringBundleService->CreateBundle(
"chrome://global-platform/locale/accessible.properties",
getter_AddRefs(stringBundle));
if (!stringBundle)
return;
nsXPIDLString xsValue;
nsresult rv = stringBundle->GetStringFromName(aKey.get(), getter_Copies(xsValue));
if (NS_SUCCEEDED(rv))
aStringOut.Assign(xsValue);
}
PRUint64
@ -3293,8 +3306,9 @@ KeyBinding::ToPlatformFormat(nsAString& aValue) const
nsCOMPtr<nsIStringBundleService> stringBundleService =
mozilla::services::GetStringBundleService();
if (stringBundleService)
stringBundleService->CreateBundle(PLATFORM_KEYS_BUNDLE_URL,
getter_AddRefs(keyStringBundle));
stringBundleService->CreateBundle(
"chrome://global-platform/locale/platformKeys.properties",
getter_AddRefs(keyStringBundle));
if (!keyStringBundle)
return;

View File

@ -662,7 +662,7 @@ public:
/**
* Return the localized string for the given key.
*/
static void TranslateString(const nsAString& aKey, nsAString& aStringOut);
static void TranslateString(const nsString& aKey, nsAString& aStringOut);
/**
* Return true if the accessible is defunct.

View File

@ -133,30 +133,6 @@ ARIAGridAccessible::GetCellAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
return NS_OK;
}
NS_IMETHODIMP
ARIAGridAccessible::GetCellIndexAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
PRInt32* aCellIndex)
{
NS_ENSURE_ARG_POINTER(aCellIndex);
*aCellIndex = -1;
if (IsDefunct())
return NS_ERROR_FAILURE;
NS_ENSURE_ARG(aRowIndex >= 0 && aColumnIndex >= 0);
PRInt32 rowCount = 0;
GetRowCount(&rowCount);
NS_ENSURE_ARG(aRowIndex < rowCount);
PRInt32 colsCount = 0;
GetColumnCount(&colsCount);
NS_ENSURE_ARG(aColumnIndex < colsCount);
*aCellIndex = colsCount * aRowIndex + aColumnIndex;
return NS_OK;
}
NS_IMETHODIMP
ARIAGridAccessible::GetColumnIndexAt(PRInt32 aCellIndex,
PRInt32* aColumnIndex)

View File

@ -35,3 +35,25 @@ LOCAL_INCLUDES = \
-I$(srcdir)/../../../layout/generic \
-I$(srcdir)/../../../layout/xul/base/src \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
LOCAL_INCLUDES += \
-I$(srcdir)/../atk \
$(NULL)
else
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
LOCAL_INCLUDES += \
-I$(srcdir)/../msaa \
$(NULL)
else
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
LOCAL_INCLUDES += \
-I$(srcdir)/../mac \
$(NULL)
else
LOCAL_INCLUDES += \
-I$(srcdir)/../other \
$(NULL)
endif
endif
endif

View File

@ -51,7 +51,8 @@ public:
/**
* Return the index of the cell at the given row and column.
*/
virtual PRInt32 CellIndexAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return -1; }
virtual PRInt32 CellIndexAt(PRUint32 aRowIdx, PRUint32 aColIdx)
{ return ColCount() * aRowIdx + aColIdx; }
/**
* Return the column index of the cell with the given index.

View File

@ -80,3 +80,25 @@ LOCAL_INCLUDES = \
-I$(srcdir)/../../../layout/generic \
-I$(srcdir)/../../../layout/xul/base/src \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
LOCAL_INCLUDES += \
-I$(srcdir)/../atk \
$(NULL)
else
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
LOCAL_INCLUDES += \
-I$(srcdir)/../msaa \
$(NULL)
else
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
LOCAL_INCLUDES += \
-I$(srcdir)/../mac \
$(NULL)
else
LOCAL_INCLUDES += \
-I$(srcdir)/../other \
$(NULL)
endif
endif
endif

View File

@ -265,9 +265,12 @@ nsHTMLSelectOptionAccessible::NativeState()
// because we don't want EDITABLE or SELECTABLE_TEXT
PRUint64 state = nsAccessible::NativeState();
PRUint64 selectState = 0;
nsIContent* selectContent = GetSelectState(&selectState);
if (!selectContent || selectState & states::INVISIBLE)
nsAccessible* select = GetSelect();
if (!select)
return state;
PRUint64 selectState = select->State();
if (selectState & states::INVISIBLE)
return state;
// Focusable and selectable
@ -391,30 +394,6 @@ nsHTMLSelectOptionAccessible::ContainerWidget() const
return mParent && mParent->IsListControl() ? mParent : nsnull;
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLSelectOptionAccessible: private methods
nsIContent*
nsHTMLSelectOptionAccessible::GetSelectState(PRUint64* aState)
{
*aState = 0;
nsIContent* selectNode = mContent;
while (selectNode && selectNode->Tag() != nsGkAtoms::select) {
selectNode = selectNode->GetParent();
}
if (selectNode) {
nsAccessible* select = mDoc->GetAccessible(selectNode);
if (select) {
*aState = select->State();
return selectNode;
}
}
return nsnull;
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLSelectOptGroupAccessible
////////////////////////////////////////////////////////////////////////////////

View File

@ -133,11 +133,17 @@ public:
private:
/**
* Get Select element's accessible state
* @param aState, Select element state
* @return Select element content, returns null if not avaliable
* Return a select accessible the option belongs to if any.
*/
nsIContent* GetSelectState(PRUint64* aState);
nsAccessible* GetSelect() const
{
if (mParent && mParent->IsListControl()) {
nsAccessible* combobox = mParent->Parent();
return combobox && combobox->IsCombobox() ? combobox : mParent.get();
}
return nsnull;
}
/**
* Return a combobox accessible the option belongs to if any.
@ -146,7 +152,7 @@ private:
{
if (mParent && mParent->IsListControl()) {
nsAccessible* combobox = mParent->Parent();
return combobox->IsCombobox() ? combobox : nsnull;
return combobox && combobox->IsCombobox() ? combobox : nsnull;
}
return nsnull;

View File

@ -900,20 +900,14 @@ nsHTMLTableAccessible::GetCellAt(PRInt32 aRow, PRInt32 aColumn,
return NS_OK;
}
NS_IMETHODIMP
nsHTMLTableAccessible::GetCellIndexAt(PRInt32 aRow, PRInt32 aColumn,
PRInt32 *aIndex)
PRInt32
nsHTMLTableAccessible::CellIndexAt(PRUint32 aRowIdx, PRUint32 aColIdx)
{
NS_ENSURE_ARG_POINTER(aIndex);
nsITableLayout* tableLayout = GetTableLayout();
nsITableLayout *tableLayout = GetTableLayout();
NS_ENSURE_STATE(tableLayout);
nsresult rv = tableLayout->GetIndexByRowAndColumn(aRow, aColumn, aIndex);
if (rv == NS_TABLELAYOUT_CELL_NOT_FOUND)
return NS_ERROR_INVALID_ARG;
return NS_OK;
PRInt32 index = -1;
tableLayout->GetIndexByRowAndColumn(aRowIdx, aColIdx, &index);
return index;
}
NS_IMETHODIMP

View File

@ -132,6 +132,7 @@ public:
virtual void Summary(nsString& aSummary);
virtual PRUint32 ColCount();
virtual PRUint32 RowCount();
virtual PRInt32 CellIndexAt(PRUint32 aRowIdx, PRUint32 aColIdx);
virtual void UnselectCol(PRUint32 aColIdx);
virtual void UnselectRow(PRUint32 aRowIdx);
virtual bool IsProbablyLayoutTable();

View File

@ -48,8 +48,7 @@ var AccessFu = {
} catch (x) {
}
if (this.amINeeded(accessPref))
this.enable();
this.processPreferences(accessPref);
},
/**
@ -57,6 +56,10 @@ var AccessFu = {
* with arrow keys.
*/
enable: function enable() {
if (this._enabled)
return;
this._enabled = true;
dump('AccessFu enable');
this.addPresenter(new VisualPresenter());
@ -77,6 +80,10 @@ var AccessFu = {
* Disable AccessFu and return to default interaction mode.
*/
disable: function disable() {
if (!this._enabled)
return;
this._enabled = false;
dump('AccessFu disable');
this.presenters.forEach(function(p) { p.detach(); });
@ -91,26 +98,29 @@ var AccessFu = {
this.chromeWin.removeEventListener('TabOpen', this, true);
},
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;
processPreferences: function processPreferences(aPref) {
if (Services.appinfo.OS == 'Android') {
if (aPref == ACCESSFU_AUTO) {
if (!this._observingSystemSettings) {
Services.obs.addObserver(this, 'Accessibility:Settings', false);
this._observingSystemSettings = true;
}
default:
return false;
Cc['@mozilla.org/android/bridge;1'].
getService(Ci.nsIAndroidBridge).handleGeckoMessage(
JSON.stringify({ gecko: { type: 'Accessibility:Ready' } }));
return;
}
if (this._observingSystemSettings) {
Services.obs.removeObserver(this, 'Accessibility:Settings');
this._observingSystemSettings = false;
}
}
if (aPref == ACCESSFU_ENABLE)
this.enable();
else
this.disable();
},
addPresenter: function addPresenter(presenter) {
@ -159,13 +169,15 @@ var AccessFu = {
observe: function observe(aSubject, aTopic, aData) {
switch (aTopic) {
case 'Accessibility:Settings':
if (JSON.parse(aData).enabled)
this.enable();
else
this.disable();
break;
case 'nsPref:changed':
if (aData == 'accessfu') {
if (this.amINeeded(this.prefsBranch.getIntPref('accessfu')))
this.enable();
else
this.disable();
}
if (aData == 'accessfu')
this.processPreferences(this.prefsBranch.getIntPref('accessfu'));
break;
case 'accessible-event':
let event;
@ -392,7 +404,13 @@ var AccessFu = {
},
// A hash of documents that don't yet have an accessible tree.
_pendingDocuments: {}
_pendingDocuments: {},
// So we don't enable/disable twice
_enabled: false,
// Observing accessibility settings
_observingSystemSettings: false
};
function getAccessible(aNode) {

View File

@ -60,24 +60,9 @@ CMMSRCS = nsAccessNodeWrap.mm \
RootAccessibleWrap.mm \
$(NULL)
EXPORTS = \
ARIAGridAccessibleWrap.h \
nsAccessNodeWrap.h \
nsTextAccessibleWrap.h \
nsAccessibleWrap.h \
nsDocAccessibleWrap.h \
nsXULMenuAccessibleWrap.h \
nsXULListboxAccessibleWrap.h \
nsXULTreeGridAccessibleWrap.h \
nsHyperTextAccessibleWrap.h \
nsHTMLImageAccessibleWrap.h \
nsHTMLTableAccessibleWrap.h \
mozDocAccessible.h \
mozAccessible.h \
mozAccessibleProtocol.h \
mozActionElements.h \
mozTextAccessible.h \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a static lib.

View File

@ -476,10 +476,10 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
{
switch (mRole) {
case roles::LIST:
return NSAccessibilityContentListSubrole;
return @"AXContentList"; // 10.6+ NSAccessibilityContentListSubrole;
case roles::DEFINITION_LIST:
return NSAccessibilityDefinitionListSubrole;
return @"AXDefinitionList"; // 10.6+ NSAccessibilityDefinitionListSubrole;
case roles::TERM:
return @"AXTerm";

View File

@ -67,7 +67,6 @@ nsAccessNodeWrap::~nsAccessNodeWrap()
void nsAccessNodeWrap::InitAccessibility()
{
nsAccessNode::InitXPAccessibility();
}
void nsAccessNodeWrap::ShutdownAccessibility()

View File

@ -78,28 +78,7 @@ CPPSRCS = \
$(NULL)
EXPORTS = \
ARIAGridAccessibleWrap.h \
nsAccessNodeWrap.h \
nsAccessibleWrap.h \
nsTextAccessibleWrap.h \
nsDocAccessibleWrap.h \
nsHTMLWin32ObjectAccessible.h \
nsXULMenuAccessibleWrap.h \
nsXULListboxAccessibleWrap.h \
nsXULTreeGridAccessibleWrap.h \
nsHyperTextAccessibleWrap.h \
nsHTMLImageAccessibleWrap.h \
nsHTMLTableAccessibleWrap.h \
ia2AccessibleAction.h \
ia2AccessibleComponent.h \
CAccessibleImage.h \
CAccessibleText.h \
CAccessibleEditableText.h \
CAccessibleHyperlink.h \
ia2AccessibleHypertext.h \
CAccessibleTable.h \
CAccessibleTableCell.h \
CAccessibleValue.h \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a static lib.

View File

@ -588,8 +588,6 @@ void nsAccessNodeWrap::InitAccessibility()
Compatibility::Init();
nsWinUtils::MaybeStartWindowEmulation();
nsAccessNode::InitXPAccessibility();
}
void nsAccessNodeWrap::ShutdownAccessibility()

View File

@ -52,20 +52,6 @@ CPPSRCS = \
nsAccessibleWrap.cpp \
$(NULL)
EXPORTS = \
ARIAGridAccessibleWrap.h \
nsAccessNodeWrap.h \
nsTextAccessibleWrap.h \
nsAccessibleWrap.h \
nsDocAccessibleWrap.h \
nsXULMenuAccessibleWrap.h \
nsXULListboxAccessibleWrap.h \
nsXULTreeGridAccessibleWrap.h \
nsHyperTextAccessibleWrap.h \
nsHTMLImageAccessibleWrap.h \
nsHTMLTableAccessibleWrap.h \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a static lib.
FORCE_STATIC_LIB = 1

View File

@ -66,7 +66,6 @@ nsAccessNodeWrap::~nsAccessNodeWrap()
void nsAccessNodeWrap::InitAccessibility()
{
nsAccessNode::InitXPAccessibility();
}
void nsAccessNodeWrap::ShutdownAccessibility()

View File

@ -66,3 +66,24 @@ LOCAL_INCLUDES = \
-I$(srcdir)/../html \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
LOCAL_INCLUDES += \
-I$(srcdir)/../atk \
$(NULL)
else
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
LOCAL_INCLUDES += \
-I$(srcdir)/../msaa \
$(NULL)
else
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
LOCAL_INCLUDES += \
-I$(srcdir)/../mac \
$(NULL)
else
LOCAL_INCLUDES += \
-I$(srcdir)/../other \
$(NULL)
endif
endif
endif

View File

@ -62,3 +62,25 @@ LOCAL_INCLUDES = \
-I$(srcdir)/../base \
-I$(srcdir)/../generic \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
LOCAL_INCLUDES += \
-I$(srcdir)/../atk \
$(NULL)
else
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
LOCAL_INCLUDES += \
-I$(srcdir)/../msaa \
$(NULL)
else
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
LOCAL_INCLUDES += \
-I$(srcdir)/../mac \
$(NULL)
else
LOCAL_INCLUDES += \
-I$(srcdir)/../other \
$(NULL)
endif
endif
endif

View File

@ -47,6 +47,24 @@ xpcAccessibleTable::GetRowCount(PRInt32* aRowCount)
return NS_OK;
}
nsresult
xpcAccessibleTable::GetCellIndexAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
PRInt32* aCellIndex)
{
NS_ENSURE_ARG_POINTER(aCellIndex);
*aCellIndex = -1;
if (!mTable)
return NS_ERROR_FAILURE;
if (aRowIndex < 0 || aRowIndex >= mTable->RowCount() ||
aColumnIndex < 0 || aColumnIndex >= mTable->ColCount())
return NS_ERROR_INVALID_ARG;
*aCellIndex = mTable->CellIndexAt(aRowIndex, aColumnIndex);
return NS_OK;
}
nsresult
xpcAccessibleTable::GetSummary(nsAString& aSummary)
{

View File

@ -26,6 +26,8 @@ public:
nsresult GetSummary(nsAString& aSummary);
nsresult GetColumnCount(PRInt32* aColumnCount);
nsresult GetRowCount(PRInt32* aRowCount);
nsresult GetCellIndexAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
PRInt32* aCellIndex);
nsresult UnselectColumn(PRInt32 aColIdx);
nsresult UnselectRow(PRInt32 aRowIdx);
nsresult IsProbablyForLayout(bool* aIsForLayout);
@ -44,7 +46,8 @@ protected:
NS_SCRIPTABLE NS_IMETHOD GetRowCount(PRInt32* aRowCount) \
{ return xpcAccessibleTable::GetRowCount(aRowCount); } \
NS_SCRIPTABLE NS_IMETHOD GetCellAt(PRInt32 rowIndex, PRInt32 columnIndex, nsIAccessible * *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetCellIndexAt(PRInt32 rowIndex, PRInt32 columnIndex, PRInt32 *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetCellIndexAt(PRInt32 rowIndex, PRInt32 columnIndex, PRInt32 *_retval NS_OUTPARAM) \
{ return xpcAccessibleTable::GetCellIndexAt(rowIndex, columnIndex, _retval); } \
NS_SCRIPTABLE NS_IMETHOD GetColumnIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetRowIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetRowAndColumnIndicesAt(PRInt32 cellIndex, PRInt32 *rowIndex NS_OUTPARAM, PRInt32 *columnIndex NS_OUTPARAM); \

View File

@ -78,3 +78,25 @@ LOCAL_INCLUDES = \
-I$(srcdir)/../../../layout/generic \
-I$(srcdir)/../../../layout/xul/base/src \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
LOCAL_INCLUDES += \
-I$(srcdir)/../atk \
$(NULL)
else
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
LOCAL_INCLUDES += \
-I$(srcdir)/../msaa \
$(NULL)
else
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
LOCAL_INCLUDES += \
-I$(srcdir)/../mac \
$(NULL)
else
LOCAL_INCLUDES += \
-I$(srcdir)/../other \
$(NULL)
endif
endif
endif

View File

@ -307,27 +307,6 @@ nsXULListboxAccessible::GetCellAt(PRInt32 aRow, PRInt32 aColumn,
return NS_OK;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetCellIndexAt(PRInt32 aRow, PRInt32 aColumn,
PRInt32 *aIndex)
{
NS_ENSURE_ARG_POINTER(aIndex);
*aIndex = -1;
PRInt32 rowCount = 0;
nsresult rv = GetRowCount(&rowCount);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(0 <= aRow && aRow <= rowCount, NS_ERROR_INVALID_ARG);
PRInt32 columnCount = 0;
rv = GetColumnCount(&columnCount);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(0 <= aColumn && aColumn <= columnCount, NS_ERROR_INVALID_ARG);
*aIndex = aRow * columnCount + aColumn;
return NS_OK;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetColumnIndexAt(PRInt32 aIndex, PRInt32 *aColumn)
{

View File

@ -356,24 +356,6 @@ nsXULTreeGridAccessible::GetCellAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
return NS_OK;
}
NS_IMETHODIMP
nsXULTreeGridAccessible::GetCellIndexAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
PRInt32 *aCellIndex)
{
NS_ENSURE_ARG_POINTER(aCellIndex);
*aCellIndex = -1;
if (IsDefunct())
return NS_ERROR_FAILURE;
PRInt32 columnCount = 0;
nsresult rv = GetColumnCount(&columnCount);
NS_ENSURE_SUCCESS(rv, rv);
*aCellIndex = aRowIndex * columnCount + aColumnIndex;
return NS_OK;
}
NS_IMETHODIMP
nsXULTreeGridAccessible::GetColumnIndexAt(PRInt32 aCellIndex,
PRInt32 *aColumnIndex)

View File

@ -337,6 +337,118 @@ function testWords(aElement, aWords, aToDoFlag)
}
}
/**
* Remove all selections.
*
* @param aID [in] Id, DOM node, or acc obj
*/
function cleanTextSelections(aID)
{
var acc = getAccessible(aID, [nsIAccessibleText]);
while (acc.selectionCount > 0)
acc.removeSelection(0);
}
/**
* Test addSelection method.
*
* @param aID [in] Id, DOM node, or acc obj
* @param aStartOffset [in] start offset for the new selection
* @param aEndOffset [in] end offset for the new selection
* @param aSelectionsCount [in] expected number of selections after addSelection
*/
function testTextAddSelection(aID, aStartOffset, aEndOffset, aSelectionsCount)
{
var acc = getAccessible(aID, [nsIAccessibleText]);
var text = acc.getText(0, -1);
acc.addSelection(aStartOffset, aEndOffset);
ok(acc.selectionCount, aSelectionsCount,
text + ": failed to add selection from offset '" + aStartOffset +
"' to offset '" + aEndOffset + "': selectionCount after");
}
/**
* Test removeSelection method.
*
* @param aID [in] Id, DOM node, or acc obj
* @param aSelectionIndex [in] index of the selection to be removed
* @param aSelectionsCount [in] expected number of selections after
* removeSelection
*/
function testTextRemoveSelection(aID, aSelectionIndex, aSelectionsCount)
{
var acc = getAccessible(aID, [nsIAccessibleText]);
var text = acc.getText(0, -1);
acc.removeSelection(aSelectionIndex);
ok(acc.selectionCount, aSelectionsCount,
text + ": failed to remove selection at index '" +
aSelectionIndex + "': selectionCount after");
}
/**
* Test setSelectionBounds method.
*
* @param aID [in] Id, DOM node, or acc obj
* @param aStartOffset [in] new start offset for the selection
* @param aEndOffset [in] new end offset for the selection
* @param aSelectionIndex [in] index of the selection to set
* @param aSelectionsCount [in] expected number of selections after
* setSelectionBounds
*/
function testTextSetSelection(aID, aStartOffset, aEndOffset,
aSelectionIndex, aSelectionsCount)
{
var acc = getAccessible(aID, [nsIAccessibleText]);
var text = acc.getText(0, -1);
acc.setSelectionBounds(aSelectionIndex, aStartOffset, aEndOffset);
is(acc.selectionCount, aSelectionsCount,
text + ": failed to set selection at index '" +
aSelectionIndex + "': selectionCount after");
}
/**
* Test selectionCount method.
*
* @param aID [in] Id, DOM node, or acc obj
* @param aCount [in] expected selection count
*/
function testTextSelectionCount(aID, aCount)
{
var acc = getAccessible(aID, [nsIAccessibleText]);
var text = acc.getText(0, -1);
is(acc.selectionCount, aCount, text + ": wrong selectionCount: ");
}
/**
* Test getSelectionBounds method.
*
* @param aID [in] Id, DOM node, or acc obj
* @param aStartOffset [in] expected start offset for the selection
* @param aEndOffset [in] expected end offset for the selection
* @param aSelectionIndex [in] index of the selection to get
*/
function testTextGetSelection(aID, aStartOffset, aEndOffset, aSelectionIndex)
{
var acc = getAccessible(aID, [nsIAccessibleText]);
var text = acc.getText(0, -1);
var startObj = {}, endObj = {};
acc.getSelectionBounds(aSelectionIndex, startObj, endObj);
is(startObj.value, aStartOffset, text + ": wrong start offset for index '" +
aSelectionIndex + "'");
is(endObj.value, aEndOffset, text + ": wrong end offset for index '" +
aSelectionIndex + "'");
}
////////////////////////////////////////////////////////////////////////////////
// Private

View File

@ -50,6 +50,7 @@ _TEST_FILES = \
test_doc.html \
test_hypertext.html \
test_passwords.html \
test_selection.html \
test_singleline.html \
test_whitespaces.html \
test_words.html \

View File

@ -0,0 +1,101 @@
<!DOCTYPE html>
<html>
<head>
<title>Test text selection functions</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../text.js"></script>
<script type="application/javascript">
function doTest()
{
// Test selection count: clean selection / check count.
testTextAddSelection("div0", 0, 2, 1); // |Test selection...
cleanTextSelections("div0");
testTextSelectionCount("div0", 0);
// Test addition: adding two equal selections, the second one should
// not be added.
testTextAddSelection("div1", 7, 9, 1); // Test ad|di|ng two...
testTextAddSelection("div1", 7, 9, 1); // Test ad|di|ng two...
testTextGetSelection("div1", 7, 9, 0);
// Test overlapping selections: adding three selections, one adjacent.
testTextAddSelection("div2", 0, 3, 1); // |Tes|t adding 3...
testTextAddSelection("div2", 7, 9, 2); // |Tes|t ad|di|ng 3...
testTextAddSelection("div2", 3, 4, 3); // |Tes||t| ad|di|ng 3...
testTextGetSelection("div2", 0, 3, 0);
testTextGetSelection("div2", 3, 4, 1);
testTextGetSelection("div2", 7, 9, 2);
// Test selection re-ordering: adding two selections.
// NOTE: removeSelections aSelectionIndex is from start of document.
testTextAddSelection("div3", 0, 3, 1); // |Tes|t adding 2...
testTextAddSelection("div3", 7, 9, 2); // |Tes|t ad|di|ng 2...
testTextRemoveSelection("div3", 4, 1); // Test ad|di|ng 2...
// Test extending existing selection.
// NOTE: setSelectionBounds aSelectionIndex is from start of document.
testTextAddSelection("div4", 4, 5, 1); // Test| |extending...
testTextSetSelection("div4", 4, 9, 6, 1); // Test| exte|nding...
// Test moving an existing selection.
// NOTE: setSelectionBounds aSelectionIndex is from start of document.
testTextAddSelection("div5", 1, 3, 1); // T|es|t moving...
testTextSetSelection("div5", 5, 9, 6, 1); // Test |movi|ng...
// Test adding selections to multiple inner elements.
testTextAddSelection("div71", 0, 3, 1); // |Tes|t adding...
testTextAddSelection("div71", 7, 8, 2); // |Tes|t ad|d|ing...
testTextAddSelection("div72", 4, 6, 1); // Test| a|dding...
testTextAddSelection("div72", 7, 8, 2); // Test| a|d|d|ing...
// Test adding selection to parent element.
// NOTE: If inner elements are represented as embedded chars
// we count their internal selections.
testTextAddSelection("div7", 7, 8, 5); // Test ad|d|ing...
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="div0">Test selection count</div>
</br>
<div id="div1">Test adding two equal selections </div>
<div id="div2">Test adding 3 selections one adjacent </div>
<div id="div3">Test adding 2 selections, remove first one </div>
<div id="div4">Test extending a selection </div>
<div id="div5">Test moving a selection </div>
</br>
<div id="div7">Test adding selections to parent element
<div id="div71">Test adding selections to inner element1 </div>
<div id="div72">Test adding selections to inner element2 </div>
</div>
</body>
</html>

View File

@ -1042,12 +1042,17 @@ pref("services.sync.prefs.sync.xpinstall.whitelist.required", true);
// Disable the error console
pref("devtools.errorconsole.enabled", false);
// Enable the developer toolbar
pref("devtools.toolbar.enabled", false);
// Enable the Inspector
pref("devtools.inspector.enabled", true);
pref("devtools.inspector.htmlHeight", 112);
pref("devtools.inspector.htmlPanelOpen", false);
pref("devtools.inspector.sidebarOpen", false);
pref("devtools.inspector.activeSidebar", "ruleview");
pref("devtools.inspector.highlighterShowVeil", true);
pref("devtools.inspector.highlighterShowInfobar", true);
// Enable the Layout View
pref("devtools.layoutview.enabled", false);
@ -1088,8 +1093,14 @@ pref("devtools.styleeditor.transitions", true);
// Enable tools for Chrome development.
pref("devtools.chrome.enabled", false);
// Disable the GCLI enhanced command line.
pref("devtools.gcli.enable", false);
// Display the introductory text
pref("devtools.gcli.hideIntro", false);
// How eager are we to show help: never=1, sometimes=2, always=3
pref("devtools.gcli.eagerHelper", 2);
// Do we allow the 'pref set' command
pref("devtools.gcli.allowSet", false);
// The last Web Console height. This is initially 0 which means that the Web
// Console will use the default height next time it shows.

View File

@ -176,8 +176,14 @@
<menuseparator class="appmenu-menuseparator"/>
<menu id="appmenu_webDeveloper"
label="&appMenuWebDeveloper.label;">
<menupopup id="appmenu_webDeveloper_popup"
onpopupshowing="onWebDeveloperMenuShowing();">
<menupopup id="appmenu_webDeveloper_popup">
<menuitem id="appmenu_devToolbar"
type="checkbox"
autocheck="false"
hidden="true"
label="&devToolbarMenu.label;"
command="Tools:DevToolbar"
key="key_devToolbar"/>
<menuitem id="appmenu_webConsole"
label="&webConsoleCmd.label;"
type="checkbox"
@ -191,6 +197,7 @@
key="key_inspect"/>
<menuitem id="appmenu_debugger"
hidden="true"
type="checkbox"
label="&debuggerMenu.label;"
key="key_debugger"
command="Tools:Debugger"/>

View File

@ -531,8 +531,15 @@
<menu id="webDeveloperMenu"
label="&webDeveloperMenu.label;"
accesskey="&webDeveloperMenu.accesskey;">
<menupopup id="menuWebDeveloperPopup"
onpopupshowing="onWebDeveloperMenuShowing();">
<menupopup id="menuWebDeveloperPopup">
<menuitem id="menu_devToolbar"
type="checkbox"
autocheck="false"
hidden="true"
label="&devToolbarMenu.label;"
accesskey="&devToolbarMenu.accesskey;"
key="key_devToolbar"
command="Tools:DevToolbar"/>
<menuitem id="webConsole"
type="checkbox"
label="&webConsoleCmd.label;"
@ -548,6 +555,7 @@
command="Tools:Inspect"/>
<menuitem id="menu_debugger"
hidden="true"
type="checkbox"
label="&debuggerMenu.label;"
key="key_debugger"
command="Tools:Debugger"/>

View File

@ -126,6 +126,7 @@
<command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>
<command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/>
<command id="Tools:DevToolbar" oncommand="DeveloperToolbar.toggle();" disabled="true"/>
<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"/>
@ -164,6 +165,10 @@
oncommand="InspectorUI.copyOuterHTML();"/>
<command id="Inspector:DeleteNode"
oncommand="InspectorUI.deleteNode();"/>
<command id="Inspector:ToggleVeil"
oncommand="InspectorUI.toggleVeil();"/>
<command id="Inspector:ToggleInfobar"
oncommand="InspectorUI.toggleInfobar();"/>
</commandset>
<broadcasterset id="mainBroadcasterSet">
@ -257,6 +262,13 @@
#endif
<key id="key_openAddons" key="&addons.commandkey;" command="Tools:Addons" modifiers="accel,shift"/>
<key id="key_errorConsole" key="&errorConsoleCmd.commandkey;" oncommand="toJavaScriptConsole();" modifiers="accel,shift" disabled="true"/>
<key id="key_devToolbar" key="&devToolbar.commandkey;" command="Tools:DevToolbar"
#ifdef XP_MACOSX
modifiers="accel,alt"
#else
modifiers="accel,shift"
#endif
/>
<key id="key_webConsole" key="&webConsoleCmd.commandkey;" oncommand="HUDConsoleUI.toggleHUD();"
#ifdef XP_MACOSX
modifiers="accel,alt"

View File

@ -179,6 +179,12 @@ XPCOMUtils.defineLazyGetter(this, "PopupNotifications", function () {
}
});
XPCOMUtils.defineLazyGetter(this, "DeveloperToolbar", function() {
let tmp = {};
Cu.import("resource:///modules/devtools/DeveloperToolbar.jsm", tmp);
return new tmp.DeveloperToolbar(window, document.getElementById("developer-toolbar"));
});
XPCOMUtils.defineLazyGetter(this, "InspectorUI", function() {
let tmp = {};
Cu.import("resource:///modules/inspector.jsm", tmp);
@ -1695,6 +1701,16 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
setUrlAndSearchBarWidthForConditionalForwardButton();
});
// Enable developer toolbar?
let devToolbarEnabled = gPrefService.getBoolPref("devtools.toolbar.enabled");
if (devToolbarEnabled) {
document.getElementById("menu_devToolbar").hidden = false;
document.getElementById("Tools:DevToolbar").removeAttribute("disabled");
#ifdef MENUBAR_CAN_AUTOHIDE
document.getElementById("appmenu_devToolbar").hidden = false;
#endif
}
// Enable Inspector?
let enabled = gPrefService.getBoolPref("devtools.inspector.enabled");
if (enabled) {
@ -1703,6 +1719,7 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
#ifdef MENUBAR_CAN_AUTOHIDE
document.getElementById("appmenu_pageInspect").hidden = false;
#endif
document.getElementById("developer-toolbar-inspector").hidden = false;
}
// Enable Debugger?
@ -1713,6 +1730,7 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
#ifdef MENUBAR_CAN_AUTOHIDE
document.getElementById("appmenu_debugger").hidden = false;
#endif
document.getElementById("developer-toolbar-debugger").hidden = false;
}
// Enable Remote Debugger?
@ -9321,10 +9339,6 @@ var StyleEditor = {
}
};
function onWebDeveloperMenuShowing() {
document.getElementById("Tools:WebConsole").setAttribute("checked", HUDConsoleUI.getOpenHUD() != null);
}
XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () {
#ifdef XP_WIN

View File

@ -1015,9 +1015,28 @@
hidden="true">
#ifdef XP_MACOSX
<toolbarbutton id="highlighter-closebutton"
class="devtools-closebutton"
oncommand="InspectorUI.closeInspectorUI(false);"
tooltiptext="&inspectCloseButton.tooltiptext;"/>
#endif
<toolbarbutton id="inspector-option-toolbarbutton"
type="menu"
tabindex="0"
tooltiptext="&inspectOptionButton.tooltiptext;">
<menupopup id="inspector-option-popup"
position="before_start">
<menuitem id="inspectorToggleVeil"
type="checkbox"
label="&inspectorToggleVeil.label;"
accesskey="&inspectorToggleVeil.accesskey;"
command="Inspector:ToggleVeil"/>
<menuitem id="inspectorToggleInfobar"
type="checkbox"
label="&inspectorToggleInfobar.label;"
accesskey="&inspectorToggleInfobar.accesskey;"
command="Inspector:ToggleInfobar"/>
</menupopup>
</toolbarbutton>
<toolbarbutton id="inspector-inspect-toolbutton"
class="devtools-toolbarbutton"
command="Inspector:Inspect"/>
@ -1048,10 +1067,46 @@
</hbox>
#ifndef XP_MACOSX
<toolbarbutton id="highlighter-closebutton"
class="devtools-closebutton"
oncommand="InspectorUI.closeInspectorUI(false);"
tooltiptext="&inspectCloseButton.tooltiptext;"/>
#endif
</toolbar>
<toolbar id="developer-toolbar"
class="devtools-toolbar"
hidden="true">
#ifdef XP_MACOSX
<toolbarbutton id="developer-toolbar-closebutton"
oncommand="DeveloperToolbar.hide();"
tooltiptext="&devToolbarCloseButton.tooltiptext;"/>
#endif
<stack class="gclitoolbar-stack-node" flex="1">
<description class="gclitoolbar-prompt">&#187;</description>
<description class="gclitoolbar-complete-node"/>
<textbox class="gclitoolbar-input-node" rows="1"/>
</stack>
<toolbarbutton id="developer-toolbar-webconsole"
label="&webConsoleButton.label;"
class="devtools-toolbarbutton"
command="Tools:WebConsole"/>
<toolbarbutton id="developer-toolbar-inspector"
label="&inspectorButton.label;"
class="devtools-toolbarbutton"
hidden="true"
command="Tools:Inspect"/>
<toolbarbutton id="developer-toolbar-debugger"
label="&scriptsButton.label;"
class="devtools-toolbarbutton"
hidden="true"
command="Tools:Debugger"/>
#ifndef XP_MACOSX
<toolbarbutton id="developer-toolbar-closebutton"
oncommand="DeveloperToolbar.hide();"
tooltiptext="&devToolbarCloseButton.tooltiptext;"/>
#endif
</toolbar>
<toolbar id="addon-bar"
toolbarname="&addonBarCmd.label;" accesskey="&addonBarCmd.accesskey;"
collapsed="true"

View File

@ -12,6 +12,11 @@
overflow: hidden;
}
#highlighter-veil-container:not([dim]) > .highlighter-veil,
#highlighter-veil-container:not([dim]) > hbox > .highlighter-veil {
visibility: hidden;
}
#highlighter-veil-container:not([disable-transitions]) > .highlighter-veil,
#highlighter-veil-container:not([disable-transitions]) > #highlighter-veil-middlebox,
#highlighter-veil-container:not([disable-transitions]) > #highlighter-veil-middlebox > .highlighter-veil,
@ -101,6 +106,10 @@ html|*#highlighter-nodeinfobar-tagname {
display: none;
}
#inspector-option-toolbarbutton > .toolbarbutton-menu-dropmarker {
display: none;
}
#inspector-layoutview-container > iframe {
-moz-transition-property: height;
-moz-transition-duration: 0.1s;

View File

@ -67,6 +67,20 @@ function DebuggerUI(aWindow) {
}
DebuggerUI.prototype = {
/**
* Called by the DebuggerPane to update the Debugger toggle switches with the
* debugger state.
*/
refreshCommand: function DUI_refreshCommand() {
let selectedTab = this.chromeWindow.getBrowser().selectedTab;
let command = this.chromeWindow.document.getElementById("Tools:Debugger");
if (this.getDebugger(selectedTab) != null) {
command.setAttribute("checked", "true");
} else {
command.removeAttribute("checked");
}
},
/**
* Starts a debugger for the current tab, or stops it if already started.
@ -79,7 +93,7 @@ DebuggerUI.prototype = {
tab._scriptDebugger.close();
return null;
}
return new DebuggerPane(tab);
return new DebuggerPane(this, tab);
},
/**
@ -115,7 +129,7 @@ DebuggerUI.prototype = {
* @return DebuggerPane if a debugger exists for the tab, null otherwise.
*/
getDebugger: function DUI_getDebugger(aTab) {
return aTab._scriptDebugger;
return '_scriptDebugger' in aTab ? aTab._scriptDebugger : null;
},
/**
@ -153,7 +167,8 @@ DebuggerUI.prototype = {
* @param XULElement aTab
* The tab in which to create the debugger.
*/
function DebuggerPane(aTab) {
function DebuggerPane(aDebuggerUI, aTab) {
this._globalUI = aDebuggerUI;
this._tab = aTab;
this._initServer();
@ -182,7 +197,7 @@ DebuggerPane.prototype = {
let ownerDocument = gBrowser.parentNode.ownerDocument;
this._splitter = ownerDocument.createElement("splitter");
this._splitter.setAttribute("class", "hud-splitter");
this._splitter.setAttribute("class", "devtools-horizontal-splitter");
this._frame = ownerDocument.createElement("iframe");
this._frame.height = DebuggerPreferences.height;
@ -207,6 +222,7 @@ DebuggerPane.prototype = {
}, true);
this._frame.setAttribute("src", DBG_XUL);
this._globalUI.refreshCommand();
},
/**
@ -229,6 +245,8 @@ DebuggerPane.prototype = {
this._splitter = null;
this._frame = null;
this._nbox = null;
this._globalUI.refreshCommand();
},
/**

View File

@ -98,6 +98,7 @@
<menulist id="scripts" class="devtools-menulist"
label="&debuggerUI.emptyScriptText;"/>
<textbox id="scripts-search" type="search"
class="devtools-searchinput"
emptytext="&debuggerUI.emptyFilterText;"/>
<spacer flex="1"/>
#ifndef XP_MACOSX

View File

@ -168,6 +168,7 @@ TreePanel.prototype = {
this.splitter = this.document.createElement("splitter");
this.splitter.id = "inspector-tree-splitter";
this.splitter.className = "devtools-horizontal-splitter";
let container = this.document.getElementById("appcontent");
container.appendChild(this.splitter);

View File

@ -104,7 +104,13 @@ const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
* // Is a node highlightable.
* boolean isNodeHighlightable(aNode);
*
* // Add/Remove lsiteners
* // Show/hide the veil and the infobar
* void showInfobar();
* void hideInfobar();
* void showVeil();
* void hideVeil();
*
* // Add/Remove listeners
* // @param aEvent - event name
* // @param aListener - function callback
* void addListener(aEvent, aListener);
@ -171,6 +177,7 @@ Highlighter.prototype = {
// The veil will make the whole page darker except
// for the region of the selected box.
this.buildVeil(this.veilContainer);
this.showVeil();
this.buildInfobar(controlsBox);
@ -367,6 +374,36 @@ Highlighter.prototype = {
let nodeName = aNode.nodeName.toLowerCase();
return !INSPECTOR_INVISIBLE_ELEMENTS[nodeName];
},
/**
* Hide the veil
*/
hideVeil: function Highlighter_hideVeil() {
this.veilContainer.removeAttribute("dim");
},
/**
* Show the veil
*/
showVeil: function Highlighter_showVeil() {
this.veilContainer.setAttribute("dim", "true");
},
/**
* Hide the infobar
*/
hideInfobar: function Highlighter_hideInfobar() {
this.nodeInfo.container.setAttribute("hidden", "true");
},
/**
* Show the infobar
*/
showInfobar: function Highlighter_showInfobar() {
this.nodeInfo.container.removeAttribute("hidden");
this.moveInfobar();
},
/**
* Build the veil:
*
@ -383,7 +420,6 @@ Highlighter.prototype = {
* @param nsIDOMElement aParent
* The container of the veil boxes.
*/
buildVeil: function Highlighter_buildVeil(aParent)
{
// We will need to resize these boxes to surround a node.

View File

@ -383,7 +383,7 @@ InspectorUI.prototype = {
/**
* Toggle the TreePanel.
*/
toggleHTMLPanel: function TP_toggle()
toggleHTMLPanel: function TP_toggleHTMLPanel()
{
if (this.treePanel.isOpen()) {
this.treePanel.close();
@ -403,7 +403,39 @@ InspectorUI.prototype = {
*/
get isInspectorOpen()
{
return this.toolbar && !this.toolbar.hidden && this.highlighter;
return !!(this.toolbar && !this.toolbar.hidden && this.highlighter);
},
/**
* Toggle highlighter veil.
*/
toggleVeil: function IUI_toggleVeil()
{
if (this.currentInspector._highlighterShowVeil) {
this.highlighter.hideVeil();
this.currentInspector._highlighterShowVeil = false;
Services.prefs.setBoolPref("devtools.inspector.highlighterShowVeil", false);
} else {
this.highlighter.showVeil();
this.currentInspector._highlighterShowVeil = true;
Services.prefs.setBoolPref("devtools.inspector.highlighterShowVeil", true);
}
},
/**
* Toggle highlighter infobar.
*/
toggleInfobar: function IUI_toggleInfobar()
{
if (this.currentInspector._highlighterShowInfobar) {
this.highlighter.hideInfobar();
this.currentInspector._highlighterShowInfobar = false;
Services.prefs.setBoolPref("devtools.inspector.highlighterShowInfobar", false);
} else {
this.highlighter.showInfobar();
this.currentInspector._highlighterShowInfobar = true;
Services.prefs.setBoolPref("devtools.inspector.highlighterShowInfobar", true);
}
},
/**
@ -502,7 +534,7 @@ InspectorUI.prototype = {
// is limited to some specific elements and has moved the focus somewhere else.
// So in this case, we want to focus the content window.
// See: https://developer.mozilla.org/en/XUL_Tutorial/Focus_and_Selection#Platform_Specific_Behaviors
if (!this.toolbar.querySelector("-moz-focusring")) {
if (!this.toolbar.querySelector(":-moz-focusring")) {
this.win.focus();
}
@ -543,6 +575,12 @@ InspectorUI.prototype = {
inspector._activeSidebar =
Services.prefs.getCharPref("devtools.inspector.activeSidebar");
inspector._highlighterShowVeil =
Services.prefs.getBoolPref("devtools.inspector.highlighterShowVeil");
inspector._highlighterShowInfobar =
Services.prefs.getBoolPref("devtools.inspector.highlighterShowInfobar");
this.win.addEventListener("pagehide", this, true);
this._currentInspector = inspector;
@ -652,7 +690,7 @@ InspectorUI.prototype = {
if (!aKeepInspector)
this.store.deleteInspector(this.winID);
this.inspectMenuitem.setAttribute("checked", false);
this.inspectMenuitem.removeAttribute("checked");
this.browser = this.win = null; // null out references to browser and window
this.winID = null;
this.selection = null;
@ -849,6 +887,23 @@ InspectorUI.prototype = {
this._sidebar.show();
}
let menu = this.chromeDoc.getElementById("inspectorToggleVeil");
if (this.currentInspector._highlighterShowVeil) {
menu.setAttribute("checked", "true");
} else {
menu.removeAttribute("checked");
this.highlighter.hideVeil();
}
menu = this.chromeDoc.getElementById("inspectorToggleInfobar");
if (this.currentInspector._highlighterShowInfobar) {
menu.setAttribute("checked", "true");
this.highlighter.showInfobar();
} else {
menu.removeAttribute("checked");
this.highlighter.hideInfobar();
}
Services.obs.notifyObservers({wrappedJSObject: this},
INSPECTOR_NOTIFICATIONS.OPENED, null);
},

View File

@ -17,3 +17,5 @@ browser.jar:
content/browser/debugger.css (debugger/debugger.css)
content/browser/debugger-controller.js (debugger/debugger-controller.js)
content/browser/debugger-view.js (debugger/debugger-view.js)
content/browser/devtools/gcli.css (webconsole/gcli.css)
content/browser/devtools/gcliblank.xhtml (webconsole/gcliblank.xhtml)

View File

@ -0,0 +1,671 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Firefox Developer Toolbar.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dave Camp <dcamp@mozilla.com> (Original Author)
* Joe Walker <jwalker@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
"use strict";
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
let EXPORTED_SYMBOLS = [ "DeveloperToolbar", "loadCommands" ];
const NS_XHTML = 'http://www.w3.org/1999/xhtml';
XPCOMUtils.defineLazyGetter(this, "gcli", function () {
let obj = {};
Components.utils.import("resource:///modules/gcli.jsm", obj);
return obj.gcli;
});
let console = gcli._internal.console;
/**
* Load the various Command JSMs.
* Should be called when the developer toolbar first opens.
*/
function loadCommands()
{
Components.utils.import("resource:///modules/GcliCommands.jsm", {});
Components.utils.import("resource:///modules/GcliTiltCommands.jsm", {});
}
let commandsLoaded = false;
/**
* A component to manage the global developer toolbar, which contains a GCLI
* and buttons for various developer tools.
* @param aChromeWindow The browser window to which this toolbar is attached
* @param aToolbarElement See browser.xul:<toolbar id="developer-toolbar">
*/
function DeveloperToolbar(aChromeWindow, aToolbarElement)
{
if (!commandsLoaded) {
loadCommands();
commandsLoaded = true;
}
this._chromeWindow = aChromeWindow;
this._element = aToolbarElement;
this._element.hidden = true;
this._doc = this._element.ownerDocument;
this._lastState = NOTIFICATIONS.HIDE;
this._pendingShowCallback = undefined;
this._pendingHide = false;
}
/**
* Inspector notifications dispatched through the nsIObserverService
*/
const NOTIFICATIONS = {
/** DeveloperToolbar.show() has been called, and we're working on it */
LOAD: "developer-toolbar-load",
/** DeveloperToolbar.show() has completed */
SHOW: "developer-toolbar-show",
/** DeveloperToolbar.hide() has been called */
HIDE: "developer-toolbar-hide"
};
/**
* Attach notification constants to the object prototype so tests etc can
* use them without needing to import anything
*/
DeveloperToolbar.prototype.NOTIFICATIONS = NOTIFICATIONS;
/**
* Is the toolbar open?
*/
Object.defineProperty(DeveloperToolbar.prototype, 'visible', {
get: function DT_visible() {
return !this._element.hidden;
},
enumerable: true
});
/**
* Called from browser.xul in response to menu-click or keyboard shortcut to
* toggle the toolbar
*/
DeveloperToolbar.prototype.toggle = function DT_toggle()
{
if (this.visible) {
this.hide();
} else {
this.show();
this._input.focus();
}
};
/**
* Even if the user has not clicked on 'Got it' in the intro, we only show it
* once per session.
* Warning this is slightly messed up because this.DeveloperToolbar is not the
* same as this.DeveloperToolbar when in browser.js context.
*/
DeveloperToolbar.introShownThisSession = false;
/**
* Show the developer toolbar
* @param aCallback show events can be asynchronous. If supplied aCallback will
* be called when the DeveloperToolbar is visible
*/
DeveloperToolbar.prototype.show = function DT_show(aCallback)
{
if (this._lastState != NOTIFICATIONS.HIDE) {
return;
}
this._notify(NOTIFICATIONS.LOAD);
this._pendingShowCallback = aCallback;
this._pendingHide = false;
let checkLoad = function() {
if (this.tooltipPanel && this.tooltipPanel.loaded &&
this.outputPanel && this.outputPanel.loaded) {
this._onload();
}
}.bind(this);
this._input = this._doc.querySelector(".gclitoolbar-input-node");
this.tooltipPanel = new TooltipPanel(this._doc, this._input, checkLoad);
this.outputPanel = new OutputPanel(this._doc, this._input, checkLoad);
};
/**
* Initializing GCLI can only be done when we've got content windows to write
* to, so this needs to be done asynchronously.
*/
DeveloperToolbar.prototype._onload = function DT_onload()
{
this._doc.getElementById("Tools:DevToolbar").setAttribute("checked", "true");
let contentDocument = this._chromeWindow.getBrowser().contentDocument;
this.display = gcli._internal.createDisplay({
contentDocument: contentDocument,
chromeDocument: this._doc,
chromeWindow: this._chromeWindow,
hintElement: this.tooltipPanel.hintElement,
inputElement: this._input,
completeElement: this._doc.querySelector(".gclitoolbar-complete-node"),
backgroundElement: this._doc.querySelector(".gclitoolbar-stack-node"),
outputDocument: this.outputPanel.document,
environment: {
chromeDocument: this._doc,
contentDocument: contentDocument
},
tooltipClass: 'gcliterm-tooltip',
eval: null,
scratchpad: null
});
this.display.onVisibilityChange.add(this.outputPanel._visibilityChanged, this.outputPanel);
this.display.onVisibilityChange.add(this.tooltipPanel._visibilityChanged, this.tooltipPanel);
this.display.onOutput.add(this.outputPanel._outputChanged, this.outputPanel);
this._chromeWindow.getBrowser().tabContainer.addEventListener("TabSelect", this, false);
this._chromeWindow.getBrowser().addEventListener("load", this, true);
this._element.hidden = false;
this._notify(NOTIFICATIONS.SHOW);
if (this._pendingShowCallback) {
this._pendingShowCallback.call();
this._pendingShowCallback = undefined;
}
// If a hide event happened while we were loading, then we need to hide.
// We could make this check earlier, but then cleanup would be complex so
// we're being inefficient for now.
if (this._pendingHide) {
this.hide();
return;
}
if (!DeveloperToolbar.introShownThisSession) {
this.display.maybeShowIntro();
DeveloperToolbar.introShownThisSession = true;
}
};
/**
* Hide the developer toolbar.
*/
DeveloperToolbar.prototype.hide = function DT_hide()
{
if (this._lastState == NOTIFICATIONS.HIDE) {
return;
}
if (this._lastState == NOTIFICATIONS.LOAD) {
this._pendingHide = true;
return;
}
this._element.hidden = true;
this._doc.getElementById("Tools:DevToolbar").setAttribute("checked", "false");
this.destroy();
this._notify(NOTIFICATIONS.HIDE);
};
/**
* Hide the developer toolbar
*/
DeveloperToolbar.prototype.destroy = function DT_destroy()
{
this._chromeWindow.getBrowser().tabContainer.removeEventListener("TabSelect", this, false);
this._chromeWindow.getBrowser().removeEventListener("load", this, true);
this.display.onVisibilityChange.remove(this.outputPanel._visibilityChanged, this.outputPanel);
this.display.onVisibilityChange.remove(this.tooltipPanel._visibilityChanged, this.tooltipPanel);
this.display.onOutput.remove(this.outputPanel._outputChanged, this.outputPanel);
this.display.destroy();
this.outputPanel.destroy();
this.tooltipPanel.destroy();
delete this._input;
// We could "delete this.display" etc if we have hard-to-track-down memory
// leaks as a belt-and-braces approach, however this prevents our DOM node
// hunter from looking in all the nooks and crannies, so it's better if we
// can be leak-free without
delete this.display;
delete this.outputPanel;
delete this.tooltipPanel;
};
/**
* Utility for sending notifications
* @param aTopic a NOTIFICATION constant
*/
DeveloperToolbar.prototype._notify = function DT_notify(aTopic)
{
this._lastState = aTopic;
let data = { toolbar: this };
data.wrappedJSObject = data;
Services.obs.notifyObservers(data, aTopic, null);
};
/**
* Update various parts of the UI when the current tab changes
* @param aEvent
*/
DeveloperToolbar.prototype.handleEvent = function DT_handleEvent(aEvent)
{
if (aEvent.type == "TabSelect" || aEvent.type == "load") {
this._chromeWindow.HUDConsoleUI.refreshCommand();
this._chromeWindow.DebuggerUI.refreshCommand();
if (this.visible) {
let contentDocument = this._chromeWindow.getBrowser().contentDocument;
this.display.reattach({
contentDocument: contentDocument,
chromeWindow: this._chromeWindow,
environment: {
chromeDocument: this._doc,
contentDocument: contentDocument
},
});
}
}
};
/**
* Add class="gcli-panel-inner-arrowcontent" to a panel's
* |<xul:box class="panel-inner-arrowcontent">| so we can alter the styling
* without complex CSS expressions.
* @param aPanel The panel to affect
*/
function getContentBox(aPanel)
{
let container = aPanel.ownerDocument.getAnonymousElementByAttribute(
aPanel, "anonid", "container");
return container.querySelector(".panel-inner-arrowcontent");
}
/**
* Helper function to calculate the sum of the vertical padding and margins
* between a nested node |aNode| and an ancestor |aRoot|. Iff all of the
* children of aRoot are 'only-childs' until you get to aNode then to avoid
* scroll-bars, the 'correct' height of aRoot is verticalSpacing + aNode.height.
* @param aNode The child node whose height is known.
* @param aRoot The parent height whose height we can affect.
* @return The sum of the vertical padding/margins in between aNode and aRoot.
*/
function getVerticalSpacing(aNode, aRoot)
{
let win = aNode.ownerDocument.defaultView;
function pxToNum(styles, property) {
return parseInt(styles.getPropertyValue(property).replace(/px$/, ''), 10);
}
let vertSpacing = 0;
do {
let styles = win.getComputedStyle(aNode);
vertSpacing += pxToNum(styles, "padding-top");
vertSpacing += pxToNum(styles, "padding-bottom");
vertSpacing += pxToNum(styles, "margin-top");
vertSpacing += pxToNum(styles, "margin-bottom");
vertSpacing += pxToNum(styles, "border-top-width");
vertSpacing += pxToNum(styles, "border-bottom-width");
let prev = aNode.previousSibling;
while (prev != null) {
vertSpacing += prev.clientHeight;
prev = prev.previousSibling;
}
let next = aNode.nextSibling;
while (next != null) {
vertSpacing += next.clientHeight;
next = next.nextSibling;
}
aNode = aNode.parentNode;
} while (aNode !== aRoot);
return vertSpacing + 9;
}
/**
* Panel to handle command line output.
* @param aChromeDoc document from which we can pull the parts we need.
* @param aInput the input element that should get focus.
* @param aLoadCallback called when the panel is loaded properly.
*/
function OutputPanel(aChromeDoc, aInput, aLoadCallback)
{
this._input = aInput;
this._anchor = aChromeDoc.getElementById("developer-toolbar");
this._loadCallback = aLoadCallback;
/*
<panel id="gcli-output"
type="arrow"
noautofocus="true"
noautohide="true"
class="gcli-panel">
<iframe id="gcli-output-frame"
src="chrome://browser/content/devtools/gcliblank.xhtml"
flex="1"/>
</panel>
*/
this._panel = aChromeDoc.createElement("panel");
this._panel.id = "gcli-output";
this._panel.classList.add("gcli-panel");
this._panel.setAttribute("type", "arrow");
this._panel.setAttribute("noautofocus", "true");
this._panel.setAttribute("noautohide", "true");
this._anchor.parentElement.insertBefore(this._panel, this._anchor);
this._frame = aChromeDoc.createElement("iframe");
this._frame.id = "gcli-output-frame";
this._frame.setAttribute("src", "chrome://browser/content/devtools/gcliblank.xhtml");
this._frame.setAttribute("flex", "1");
this._panel.appendChild(this._frame);
this.displayedOutput = undefined;
this._onload = this._onload.bind(this);
this._frame.addEventListener("load", this._onload, true);
this.loaded = false;
}
/**
* Wire up the element from the iframe, and inform the _loadCallback.
*/
OutputPanel.prototype._onload = function OP_onload()
{
this._frame.removeEventListener("load", this._onload, true);
delete this._onload;
this._content = getContentBox(this._panel);
this._content.classList.add("gcli-panel-inner-arrowcontent");
this.document = this._frame.contentDocument;
this.document.body.classList.add("gclichrome-output");
this._div = this.document.querySelector("div");
this._div.classList.add('gcli-row-out');
this._div.setAttribute('aria-live', 'assertive');
this.loaded = true;
if (this._loadCallback) {
this._loadCallback();
delete this._loadCallback;
}
};
/**
* Display the OutputPanel.
*/
OutputPanel.prototype.show = function OP_show()
{
this._panel.ownerDocument.defaultView.setTimeout(function() {
this._resize();
}.bind(this), 0);
this._resize();
this._panel.openPopup(this._anchor, "before_end", -300, 0, false, false, null);
this._input.focus();
};
/**
* Internal helper to set the height of the output panel to fit the available
* content;
*/
OutputPanel.prototype._resize = function CLP_resize()
{
let vertSpacing = getVerticalSpacing(this._content, this._panel);
let idealHeight = this.document.body.scrollHeight + vertSpacing;
this._panel.sizeTo(400, Math.min(idealHeight, 500));
};
/**
* Called by GCLI when a command is executed.
*/
OutputPanel.prototype._outputChanged = function OP_outputChanged(aEvent)
{
if (aEvent.output.hidden) {
return;
}
this.remove();
this.displayedOutput = aEvent.output;
this.update();
this.displayedOutput.onChange.add(this.update, this);
this.displayedOutput.onClose.add(this.remove, this);
};
/**
* Called when displayed Output says it's changed or from outputChanged, which
* happens when there is a new displayed Output.
*/
OutputPanel.prototype.update = function OP_update()
{
if (this.displayedOutput.data == null) {
while (this._div.hasChildNodes()) {
this._div.removeChild(this._div.firstChild);
}
} else {
this.displayedOutput.toDom(this._div);
this.show();
}
};
/**
* Detach listeners from the currently displayed Output.
*/
OutputPanel.prototype.remove = function OP_remove()
{
this._panel.hidePopup();
if (this.displayedOutput) {
this.displayedOutput.onChange.remove(this.update, this);
this.displayedOutput.onClose.remove(this.remove, this);
delete this.displayedOutput;
}
};
/**
* Detach listeners from the currently displayed Output.
*/
OutputPanel.prototype.destroy = function OP_destroy()
{
this.remove();
this._panel.removeChild(this._frame);
this._anchor.parentElement.removeChild(this._panel);
delete this._input;
delete this._anchor;
delete this._panel;
delete this._frame;
delete this._content;
delete this._div;
delete this.document;
};
/**
* Called by GCLI to indicate that we should show or hide one either the
* tooltip panel or the output panel.
*/
OutputPanel.prototype._visibilityChanged = function OP_visibilityChanged(aEvent)
{
if (aEvent.outputVisible === true) {
// this.show is called by _outputChanged
} else {
this._panel.hidePopup();
}
};
/**
* Panel to handle tooltips.
* @param aChromeDoc document from which we can pull the parts we need.
* @param aInput the input element that should get focus.
* @param aLoadCallback called when the panel is loaded properly.
*/
function TooltipPanel(aChromeDoc, aInput, aLoadCallback)
{
this._input = aInput;
this._anchor = aChromeDoc.getElementById("developer-toolbar");
this._onload = this._onload.bind(this);
this._loadCallback = aLoadCallback;
/*
<panel id="gcli-tooltip"
type="arrow"
noautofocus="true"
noautohide="true"
class="gcli-panel">
<iframe id="gcli-tooltip-frame"
src="chrome://browser/content/devtools/gcliblank.xhtml"
flex="1"/>
</panel>
*/
this._panel = aChromeDoc.createElement("panel");
this._panel.id = "gcli-tooltip";
this._panel.classList.add("gcli-panel");
this._panel.setAttribute("type", "arrow");
this._panel.setAttribute("noautofocus", "true");
this._panel.setAttribute("noautohide", "true");
this._anchor.parentElement.insertBefore(this._panel, this._anchor);
this._frame = aChromeDoc.createElement("iframe");
this._frame.id = "gcli-tooltip-frame";
this._frame.setAttribute("src", "chrome://browser/content/devtools/gcliblank.xhtml");
this._frame.setAttribute("flex", "1");
this._panel.appendChild(this._frame);
this._frame.addEventListener("load", this._onload, true);
this.loaded = false;
}
/**
* Wire up the element from the iframe, and inform the _loadCallback.
*/
TooltipPanel.prototype._onload = function TP_onload()
{
this._frame.removeEventListener("load", this._onload, true);
this._content = getContentBox(this._panel);
this._content.classList.add("gcli-panel-inner-arrowcontent");
this.document = this._frame.contentDocument;
this.document.body.classList.add("gclichrome-tooltip");
this.hintElement = this.document.querySelector("div");
this.loaded = true;
if (this._loadCallback) {
this._loadCallback();
delete this._loadCallback;
}
};
/**
* Display the TooltipPanel.
*/
TooltipPanel.prototype.show = function TP_show()
{
let vertSpacing = getVerticalSpacing(this._content, this._panel);
let idealHeight = this.document.body.scrollHeight + vertSpacing;
this._panel.sizeTo(350, Math.min(idealHeight, 500));
this._panel.openPopup(this._anchor, "before_start", 0, 0, false, false, null);
this._input.focus();
};
/**
* Hide the TooltipPanel.
*/
TooltipPanel.prototype.remove = function TP_remove()
{
this._panel.hidePopup();
};
/**
* Hide the TooltipPanel.
*/
TooltipPanel.prototype.destroy = function TP_destroy()
{
this.remove();
this._panel.removeChild(this._frame);
this._anchor.parentElement.removeChild(this._panel);
delete this._input;
delete this._onload;
delete this._panel;
delete this._frame;
delete this._anchor;
delete this._content;
delete this.document;
delete this.hintElement;
};
/**
* Called by GCLI to indicate that we should show or hide one either the
* tooltip panel or the output panel.
*/
TooltipPanel.prototype._visibilityChanged = function TP_visibilityChanged(aEvent)
{
if (aEvent.tooltipVisible === true) {
this.show();
} else {
this._panel.hidePopup();
}
};

View File

@ -49,11 +49,21 @@ include $(topsrcdir)/config/rules.mk
_BROWSER_TEST_FILES = \
browser_promise_basic.js \
browser_templater_basic.js \
browser_toolbar_basic.js \
browser_gcli_commands.js \
browser_gcli_inspect.js \
browser_gcli_integrate.js \
browser_gcli_require.js \
browser_gcli_web.js \
browser_gcli_break.js \
head.js \
$(NULL)
_BROWSER_TEST_PAGES = \
browser_templater_basic.html \
browser_toolbar_basic.html \
browser_gcli_inspect.html \
browser_gcli_break.html \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)

View File

@ -1,8 +1,8 @@
<!DOCTYPE HTML>
<html>
<head>
<head>
<meta charset="utf-8">
<title>Browser GCLI break command test</title>
<title>Browser GCLI break command test</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script type="text/javascript">
@ -13,7 +13,7 @@
eval("debugger;");
}
</script>
</head>
<body>
</body>
</head>
<body>
</body>
</html>

View File

@ -0,0 +1,82 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the break command works as it should
const TEST_URI = "http://example.com/browser/browser/devtools/shared/test/browser_gcli_break.html";
function test() {
DeveloperToolbarTest.test(TEST_URI, function(browser, tab) {
testBreakCommands();
});
}
function testBreakCommands() {
DeveloperToolbarTest.checkInputStatus({
typed: "brea",
directTabText: "k",
status: "ERROR"
});
DeveloperToolbarTest.checkInputStatus({
typed: "break",
status: "ERROR"
});
DeveloperToolbarTest.checkInputStatus({
typed: "break add",
status: "ERROR"
});
DeveloperToolbarTest.checkInputStatus({
typed: "break add line",
emptyParameters: [ " <file>", " <line>" ],
status: "ERROR"
});
let pane = DebuggerUI.toggleDebugger();
pane._frame.addEventListener("Debugger:Connecting", function dbgConnected() {
pane._frame.removeEventListener("Debugger:Connecting", dbgConnected, true);
// Wait for the initial resume.
let client = pane.contentWindow.gClient;
client.addOneTimeListener("resumed", function() {
client.activeThread.addOneTimeListener("framesadded", function() {
DeveloperToolbarTest.checkInputStatus({
typed: "break add line " + TEST_URI + " " + content.wrappedJSObject.line0,
status: "VALID"
});
DeveloperToolbarTest.exec({
args: {
type: 'line',
file: TEST_URI,
line: content.wrappedJSObject.line0
},
completed: false
});
DeveloperToolbarTest.checkInputStatus({
typed: "break list",
status: "VALID"
});
DeveloperToolbarTest.exec();
client.activeThread.resume(function() {
DeveloperToolbarTest.checkInputStatus({
typed: "break del 0",
status: "VALID"
});
DeveloperToolbarTest.exec({
args: { breakid: 0 },
completed: false
});
finish();
});
});
// Trigger newScript notifications using eval.
content.wrappedJSObject.firstCall();
});
}, true);
}

View File

@ -0,0 +1,55 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test various GCLI commands
let imported = {};
Components.utils.import("resource:///modules/HUDService.jsm", imported);
const TEST_URI = "data:text/html;charset=utf-8,gcli-commands";
function test() {
DeveloperToolbarTest.test(TEST_URI, function(browser, tab) {
testEcho();
testConsoleClear();
testConsoleOpenClose(tab);
imported = undefined;
finish();
});
}
function testEcho() {
DeveloperToolbarTest.exec({
typed: "echo message",
args: { message: "message" },
outputMatch: /^message$/,
});
}
function testConsoleClear() {
DeveloperToolbarTest.exec({
typed: "console clear",
args: {},
blankOutput: true,
});
}
function testConsoleOpenClose(tab) {
DeveloperToolbarTest.exec({
typed: "console open",
args: {},
blankOutput: true,
});
let hud = imported.HUDService.getHudByWindow(content);
ok(hud.hudId in imported.HUDService.hudReferences, "console open");
DeveloperToolbarTest.exec({
typed: "console close",
args: {},
blankOutput: true,
});
ok(!(hud.hudId in imported.HUDService.hudReferences), "console closed");
}

View File

@ -0,0 +1,68 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the inspect command works as it should
const TEST_URI = "http://example.com/browser/browser/devtools/shared/test/browser_gcli_inspect.html";
function test() {
DeveloperToolbarTest.test(TEST_URI, function(browser, tab) {
testInspect();
finish();
});
}
function testInspect() {
DeveloperToolbarTest.checkInputStatus({
typed: "inspec",
directTabText: "t",
status: "ERROR"
});
DeveloperToolbarTest.checkInputStatus({
typed: "inspect",
emptyParameters: [ " <node>" ],
status: "ERROR"
});
DeveloperToolbarTest.checkInputStatus({
typed: "inspect h1",
status: "ERROR"
});
DeveloperToolbarTest.checkInputStatus({
typed: "inspect span",
status: "ERROR"
});
DeveloperToolbarTest.checkInputStatus({
typed: "inspect div",
status: "VALID"
});
DeveloperToolbarTest.checkInputStatus({
typed: "inspect .someclass",
status: "VALID"
});
DeveloperToolbarTest.checkInputStatus({
typed: "inspect #someid",
status: "VALID"
});
DeveloperToolbarTest.checkInputStatus({
typed: "inspect button[disabled]",
status: "VALID"
});
DeveloperToolbarTest.checkInputStatus({
typed: "inspect p>strong",
status: "VALID"
});
DeveloperToolbarTest.checkInputStatus({
typed: "inspect :root",
status: "VALID"
});
}

View File

@ -0,0 +1,40 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that source URLs in the Web Console can be clicked to display the
// standard View Source window.
function test() {
testCreateCommands();
testRemoveCommands();
}
let tselarr = {
name: 'tselarr',
params: [
{ name: 'num', type: { name: 'selection', data: [ '1', '2', '3' ] } },
{ name: 'arr', type: { name: 'array', subtype: 'string' } },
],
exec: function(args, env) {
return "flu " + args.num + "-" + args.arr.join("_");
}
};
function testCreateCommands() {
let gcliIndex = require("gcli/index");
gcliIndex.addCommand(tselarr);
let canon = require("gcli/canon");
let tselcmd = canon.getCommand("tselarr");
ok(tselcmd != null, "tselarr exists in the canon");
ok(tselcmd instanceof canon.Command, "canon storing commands");
}
function testRemoveCommands() {
let gcliIndex = require("gcli/index");
gcliIndex.removeCommand(tselarr);
let canon = require("gcli/canon");
let tselcmd = canon.getCommand("tselarr");
ok(tselcmd == null, "tselcmd removed from the canon");
}

View File

@ -1,25 +1,10 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// For more information on GCLI see:
// - https://github.com/mozilla/gcli/blob/master/docs/index.md
// - https://wiki.mozilla.org/DevTools/Features/GCLI
// Tests that source URLs in the Web Console can be clicked to display the
// standard View Source window.
var modules = { gcli: null };
Components.utils.import("resource:///modules/gcli.jsm", modules);
var define, require, console;
function test() {
define = modules.gcli._internal.define;
require = modules.gcli._internal.require;
console = modules.gcli._internal.console;
define('gclitest/requirable', [], function(require, exports, module) {
exports.thing1 = 'thing1';
exports.thing2 = 2;
@ -43,8 +28,6 @@ function test() {
testRecursive();
testUncompilable();
finishTest();
delete define.modules['gclitest/requirable'];
delete define.globalDomain.modules['gclitest/requirable'];
delete define.modules['gclitest/unrequirable'];
@ -52,11 +35,7 @@ function test() {
delete define.modules['gclitest/recurse'];
delete define.globalDomain.modules['gclitest/recurse'];
define = null;
require = null;
console = null;
modules = null;
finish();
}
function testWorking() {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
<!doctype html>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<html>
<head>
<meta charset="UTF-8">
<title>Developer Toolbar Tests</title>
<style type="text/css">
#single { color: red; }
</style>
<script type="text/javascript">var a=1;</script>
</head>
<body>
<p id=single>
1
</p>
<p class=twin>
2a
</p>
<p class=twin>
2b
</p>
<style>
.twin { color: blue; }
</style>
<script>var b=2;</script>
</body>
</html>

View File

@ -0,0 +1,36 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the developer toolbar works properly
const URL = "http://example.com/browser/browser/devtools/shared/test/browser_toolbar_basic.html";
function test() {
addTab(URL, function(browser, tab) {
info("Starting browser_toolbar_basic.js");
runTest();
});
}
function runTest() {
Services.obs.addObserver(checkOpen, DeveloperToolbar.NOTIFICATIONS.SHOW, false);
// TODO: reopen the window so the pref has a chance to take effect
// EventUtils.synthesizeKey("v", { ctrlKey: true, shiftKey: true });
DeveloperToolbarTest.show();
}
function checkOpen() {
Services.obs.removeObserver(checkOpen, DeveloperToolbar.NOTIFICATIONS.SHOW, false);
ok(DeveloperToolbar.visible, "DeveloperToolbar is visible");
Services.obs.addObserver(checkClosed, DeveloperToolbar.NOTIFICATIONS.HIDE, false);
// EventUtils.synthesizeKey("v", { ctrlKey: true, shiftKey: true });
DeveloperToolbarTest.hide();
}
function checkClosed() {
Services.obs.removeObserver(checkClosed, DeveloperToolbar.NOTIFICATIONS.HIDE, false);
ok(!DeveloperToolbar.visible, "DeveloperToolbar is not visible");
finish();
}

View File

@ -36,23 +36,37 @@
*
* ***** END LICENSE BLOCK ***** */
let tab;
let browser;
let console;
let define;
let require;
let gcli;
let tempScope = {};
Components.utils.import("resource:///modules/gcli.jsm", tempScope);
gcli = tempScope.gcli;
console = gcli._internal.console;
define = gcli._internal.define;
require = gcli._internal.require;
/**
* Open a new tab at a URL and call a callback on load
*/
function addTab(aURL, aCallback)
{
waitForExplicitFinish();
function onTabLoad() {
browser.removeEventListener("load", onTabLoad, true);
aCallback();
}
gBrowser.selectedTab = gBrowser.addTab();
content.location = aURL;
tab = gBrowser.selectedTab;
browser = gBrowser.getBrowserForTab(tab);
let tab = gBrowser.selectedTab;
let browser = gBrowser.getBrowserForTab(tab);
function onTabLoad() {
browser.removeEventListener("load", onTabLoad, true);
aCallback(browser, tab, browser.contentDocument);
}
browser.addEventListener("load", onTabLoad, true);
}
@ -62,6 +76,246 @@ registerCleanupFunction(function tearDown() {
gBrowser.removeCurrentTab();
}
tab = undefined;
browser = undefined;
console = undefined;
define = undefined;
require = undefined;
gcli = undefined;
});
/**
* Various functions for testing DeveloperToolbar
*/
let DeveloperToolbarTest = {
/**
* Paranoid DeveloperToolbar.show();
*/
show: function DTT_show(aCallback) {
if (DeveloperToolbar.visible) {
ok(false, "DeveloperToolbar.visible at start of openDeveloperToolbar");
}
else {
DeveloperToolbar.show(aCallback);
}
},
/**
* Paranoid DeveloperToolbar.hide();
*/
hide: function DTT_hide() {
if (!DeveloperToolbar.visible) {
ok(false, "!DeveloperToolbar.visible at start of closeDeveloperToolbar");
}
else {
DeveloperToolbar.display.inputter.setInput("");
DeveloperToolbar.hide();
}
},
/**
* Check that we can parse command input.
* Doesn't execute the command, just checks that we grok the input properly:
*
* DeveloperToolbarTest.checkInputStatus({
* // Test inputs
* typed: "ech", // Required
* cursor: 3, // Optional cursor position
*
* // Thing to check
* status: "INCOMPLETE", // One of "VALID", "ERROR", "INCOMPLETE"
* emptyParameters: [ "<message>" ], // Still to type
* directTabText: "o", // Simple completion text
* arrowTabText: "", // When the completion is not an extension
* });
*/
checkInputStatus: function DTT_checkInputStatus(test) {
if (test.typed) {
DeveloperToolbar.display.inputter.setInput(test.typed);
}
else {
ok(false, "Missing typed for " + JSON.stringify(test));
return;
}
if (test.cursor) {
DeveloperToolbar.display.inputter.setCursor(test.cursor)
}
if (test.status) {
is(DeveloperToolbar.display.requisition.getStatus().toString(),
test.status,
"status for " + test.typed);
}
if (test.emptyParameters == null) {
test.emptyParameters = [];
}
let completer = DeveloperToolbar.display.completer;
let realParams = completer.emptyParameters;
is(realParams.length, test.emptyParameters.length,
'emptyParameters.length for \'' + test.typed + '\'');
if (realParams.length === test.emptyParameters.length) {
for (let i = 0; i < realParams.length; i++) {
is(realParams[i].replace(/\u00a0/g, ' '), test.emptyParameters[i],
'emptyParameters[' + i + '] for \'' + test.typed + '\'');
}
}
if (test.directTabText) {
is(completer.directTabText, test.directTabText,
'directTabText for \'' + test.typed + '\'');
}
else {
is(completer.directTabText, '', 'directTabText for \'' + test.typed + '\'');
}
if (test.arrowTabText) {
is(completer.arrowTabText, ' \u00a0\u21E5 ' + test.arrowTabText,
'arrowTabText for \'' + test.typed + '\'');
}
else {
is(completer.arrowTabText, '', 'arrowTabText for \'' + test.typed + '\'');
}
},
/**
* Execute a command:
*
* DeveloperToolbarTest.exec({
* // Test inputs
* typed: "echo hi", // Optional, uses existing if undefined
*
* // Thing to check
* args: { message: "hi" }, // Check that the args were understood properly
* outputMatch: /^hi$/, // Regex to test against textContent of output
* blankOutput: true, // Special checks when there is no output
* });
*/
exec: function DTT_exec(test) {
test = test || {};
if (test.typed) {
DeveloperToolbar.display.inputter.setInput(test.typed);
}
let typed = DeveloperToolbar.display.inputter.getInputState().typed;
let output = DeveloperToolbar.display.requisition.exec();
is(typed, output.typed, 'output.command for: ' + typed);
if (test.completed !== false) {
ok(output.completed, 'output.completed false for: ' + typed);
}
else {
// It is actually an error if we say something is async and it turns
// out not to be? For now we're saying 'no'
// ok(!output.completed, 'output.completed true for: ' + typed);
}
if (test.args != null) {
is(Object.keys(test.args).length, Object.keys(output.args).length,
'arg count for ' + typed);
Object.keys(output.args).forEach(function(arg) {
let expectedArg = test.args[arg];
let actualArg = output.args[arg];
if (Array.isArray(expectedArg)) {
if (!Array.isArray(actualArg)) {
ok(false, 'actual is not an array. ' + typed + '/' + arg);
return;
}
is(expectedArg.length, actualArg.length,
'array length: ' + typed + '/' + arg);
for (let i = 0; i < expectedArg.length; i++) {
is(expectedArg[i], actualArg[i],
'member: "' + typed + '/' + arg + '/' + i);
}
}
else {
is(expectedArg, actualArg, 'typed: "' + typed + '" arg: ' + arg);
}
});
}
let displayed = DeveloperToolbar.outputPanel._div.textContent;
if (test.outputMatch) {
if (!test.outputMatch.test(displayed)) {
ok(false, "html output for " + typed + " (textContent sent to info)");
info("Actual textContent");
info(displayed);
}
}
if (test.blankOutput != null) {
if (!/^$/.test(displayed)) {
ok(false, "html output for " + typed + " (textContent sent to info)");
info("Actual textContent");
info(displayed);
}
}
},
/**
* Quick wrapper around the things you need to do to run DeveloperToolbar
* command tests:
* - Set the pref 'devtools.toolbar.enabled' to true
* - Add a tab pointing at |uri|
* - Open the DeveloperToolbar
* - Register a cleanup function to undo the above
* - Run the tests
*
* @param uri The uri of a page to load. Can be 'about:blank' or 'data:...'
* @param testFunc A function containing the tests to run. This should
* arrange for 'finish()' to be called on completion.
*/
test: function DTT_test(uri, testFunc) {
let menuItem = document.getElementById("menu_devToolbar");
let command = document.getElementById("Tools:DevToolbar");
let appMenuItem = document.getElementById("appmenu_devToolbar");
registerCleanupFunction(function() {
DeveloperToolbarTest.hide();
// a.k.a Services.prefs.clearUserPref("devtools.toolbar.enabled");
if (menuItem) {
menuItem.hidden = true;
}
if (command) {
command.setAttribute("disabled", "true");
}
if (appMenuItem) {
appMenuItem.hidden = true;
}
});
// a.k.a: Services.prefs.setBoolPref("devtools.toolbar.enabled", true);
if (menuItem) {
menuItem.hidden = false;
}
if (command) {
command.removeAttribute("disabled");
}
if (appMenuItem) {
appMenuItem.hidden = false;
}
addTab(uri, function(browser, tab) {
DeveloperToolbarTest.show(function() {
try {
testFunc(browser, tab);
}
catch (ex) {
ok(false, "" + ex);
console.error(ex);
finish();
throw ex;
}
});
});
},
};

View File

@ -438,8 +438,13 @@ Rule.prototype = {
* Reapply all the properties in this rule, and update their
* computed styles. Store disabled properties in the element
* style's store. Will re-mark overridden properties.
*
* @param {string} [aName]
* A text property name (such as "background" or "border-top") used
* when calling from setPropertyValue & setPropertyName to signify that
* the property should be saved in store.userProperties.
*/
applyProperties: function Rule_applyProperties()
applyProperties: function Rule_applyProperties(aName)
{
let disabledProps = [];
let store = this.elementStyle.store;
@ -454,7 +459,9 @@ Rule.prototype = {
continue;
}
store.userProperties.setProperty(this.style, prop.name, prop.value);
if (aName && prop.name == aName) {
store.userProperties.setProperty(this.style, prop.name, prop.value);
}
this.style.setProperty(prop.name, prop.value, prop.priority);
// Refresh the property's priority from the style, to reflect
@ -486,7 +493,7 @@ Rule.prototype = {
}
this.style.removeProperty(aProperty.name);
aProperty.name = aName;
this.applyProperties();
this.applyProperties(aName);
},
/**
@ -506,7 +513,7 @@ Rule.prototype = {
}
aProperty.value = aValue;
aProperty.priority = aPriority;
this.applyProperties();
this.applyProperties(aProperty.name);
},
/**
@ -1422,7 +1429,8 @@ TextPropertyEditor.prototype = {
this.element.classList.remove("ruleview-overridden");
}
this.nameSpan.textContent = this.prop.name;
let name = this.prop.name;
this.nameSpan.textContent = name;
// Combine the property's value and priority into one string for
// the value.
@ -1433,6 +1441,14 @@ TextPropertyEditor.prototype = {
this.valueSpan.textContent = val;
this.warning.hidden = this._validate();
let store = this.prop.rule.elementStyle.store;
let propDirty = store.userProperties.contains(this.prop.rule.style, name);
if (propDirty) {
this.element.setAttribute("dirty", "");
} else {
this.element.removeAttribute("dirty");
}
// Populate the computed styles.
this._updateComputed();
},
@ -1879,6 +1895,19 @@ UserProperties.prototype = {
this.weakMap.set(aStyle, props);
}
},
/**
* Check whether a named property for a given CSSStyleDeclaration is stored.
*
* @param {CSSStyleDeclaration} aStyle
* The CSSStyleDeclaration against which the property would be mapped.
* @param {String} aName
* The name of the property to check.
*/
contains: function UP_contains(aStyle, aName) {
let entry = this.weakMap.get(aStyle, null);
return !!entry && aName in entry;
},
};
/**

View File

@ -155,6 +155,12 @@ function testEditProperty()
expectChange();
is(idRuleEditor.rule.style.getPropertyValue("border-color"), "red",
"border-color should have been set.");
let props = ruleView.element.querySelectorAll(".ruleview-property");
for (let i = 0; i < props.length; i++) {
is(props[i].hasAttribute("dirty"), i <= 1,
"props[" + i + "] marked dirty as appropriate");
}
testDisableProperty();
});

View File

@ -101,11 +101,23 @@ gcli.addCommand({
name: "console close",
description: gcli.lookup("consolecloseDesc"),
exec: function Command_consoleClose(args, context) {
let tab = HUDService.getHudReferenceById(context.environment.hudId).tab;
let tab = context.environment.chromeDocument.defaultView.gBrowser.selectedTab
HUDService.deactivateHUDForContext(tab);
}
});
/**
* 'console open' command
*/
gcli.addCommand({
name: "console open",
description: gcli.lookup("consoleopenDesc"),
exec: function Command_consoleOpen(args, context) {
let tab = context.environment.chromeDocument.defaultView.gBrowser.selectedTab
HUDService.activateHUDForContext(tab);
}
});
/**
* 'inspect' command
*/

View File

@ -151,24 +151,6 @@ function LogFactory(aMessagePrefix)
return log;
}
/**
* Load the various Command JSMs.
* Should be called when the console first opens.
*
* @return an object containing the EXPORTED_SYMBOLS from all the command
* modules. In general there is no reason when JSMs need to export symbols
* except when they need the host environment to inform them of things like the
* current window/document/etc.
*/
function loadCommands() {
let commandExports = {};
Cu.import("resource:///modules/GcliCommands.jsm", commandExports);
Cu.import("resource:///modules/GcliTiltCommands.jsm", commandExports);
return commandExports;
}
let log = LogFactory("*** HUDService:");
const HUD_STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
@ -1570,6 +1552,7 @@ HUD_SERVICE.prototype =
if (procInstr.contexts.indexOf(hudId) == -1) {
procInstr.contexts.push(hudId);
}
HeadsUpDisplayUICommands.refreshCommand();
},
/**
@ -1600,6 +1583,7 @@ HUD_SERVICE.prototype =
this.unregisterDisplay(hudId);
window.focus();
HeadsUpDisplayUICommands.refreshCommand();
}
// Remove this context from the list of contexts that need the GCLI CSS
@ -3614,7 +3598,7 @@ HeadsUpDisplay.prototype = {
{
let usegcli = false;
try {
usegcli = Services.prefs.getBoolPref("devtools.gcli.enable");
// usegcli = Services.prefs.getBoolPref("devtools.gcli.enable");
}
catch (ex) {}
@ -6335,6 +6319,16 @@ ConsoleUtils = {
//////////////////////////////////////////////////////////////////////////
HeadsUpDisplayUICommands = {
refreshCommand: function UIC_refreshCommand() {
var window = HUDService.currentContext();
let command = window.document.getElementById("Tools:WebConsole");
if (this.getOpenHUD() != null) {
command.setAttribute("checked", true);
} else {
command.removeAttribute("checked");
}
},
toggleHUD: function UIC_toggleHUD() {
var window = HUDService.currentContext();
var gBrowser = window.gBrowser;
@ -6835,93 +6829,76 @@ function GcliTerm(aContentWindow, aHudId, aDocument, aConsole, aHintNode, aConso
this.createUI();
this.createSandbox();
this.show = this.show.bind(this);
this.hide = this.hide.bind(this);
this.gcliConsole = gcli._internal.createDisplay({
contentDocument: aContentWindow.document,
chromeDocument: this.document,
outputDocument: this.document,
chromeWindow: this.document.defaultView,
// Allow GCLI:Inputter to decide how and when to open a scratchpad window
let scratchpad = {
shouldActivate: function Scratchpad_shouldActivate(aEvent) {
return aEvent.shiftKey &&
aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RETURN;
},
activate: function Scratchpad_activate(aValue) {
aValue = aValue.replace(/^\s*{\s*/, '');
ScratchpadManager.openScratchpad({ text: aValue });
return true;
},
linkText: stringBundle.GetStringFromName('scratchpad.linkText')
};
hintElement: this.hintNode,
inputElement: this.inputNode,
completeElement: this.completeNode,
backgroundElement: this.inputStack,
consoleWrap: aConsoleWrap,
eval: this.evalInSandbox.bind(this),
this.opts = {
environment: {
hudId: this.hudId,
chromeDocument: this.document,
contentDocument: aContentWindow.document
},
chromeDocument: this.document,
contentDocument: aContentWindow.document,
jsEnvironment: {
globalObject: unwrap(aContentWindow),
evalFunction: this.evalInSandbox.bind(this)
tooltipClass: 'gcliterm-tooltip',
// Allow GCLI:Inputter to decide how and when to open a scratchpad window
scratchpad: {
shouldActivate: function Scratchpad_shouldActivate(aEvent) {
return aEvent.shiftKey &&
aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RETURN;
},
activate: function Scratchpad_activate(aValue) {
aValue = aValue.replace(/^\s*{\s*/, '');
ScratchpadManager.openScratchpad({ text: aValue });
return true;
},
linkText: stringBundle.GetStringFromName('scratchpad.linkText')
},
inputElement: this.inputNode,
completeElement: this.completeNode,
inputBackgroundElement: this.inputStack,
hintElement: this.hintNode,
consoleWrap: aConsoleWrap,
scratchpad: scratchpad,
gcliTerm: this
};
});
gcli._internal.commandOutputManager.addListener(this.onCommandOutput, this);
gcli._internal.createView(this.opts);
if (!commandExports) {
commandExports = loadCommands();
}
this.gcliConsole.onVisibilityChange.add(this.onVisibilityChange, this);
this.gcliConsole.onOutput.add(this.onOutput, this);
}
GcliTerm.prototype = {
/**
* Remove the hint column from the display.
* Show or remove the hint column from the display.
*/
hide: function GcliTerm_hide()
onVisibilityChange: function GcliTerm_onVisibilityChange(ev)
{
let permaHint = false;
try {
permaHint = Services.prefs.getBoolPref("devtools.gcli.permaHint");
if (ev.visible) {
this.hintNode.parentNode.hidden = false;
}
catch (ex) {}
else {
let permaHint = false;
try {
permaHint = Services.prefs.getBoolPref("devtools.gcli.permaHint");
}
catch (ex) {}
if (!permaHint) {
this.hintNode.parentNode.hidden = true;
if (!permaHint) {
this.hintNode.parentNode.hidden = true;
}
}
},
/**
* Undo the effects of calling hide().
*/
show: function GcliTerm_show()
{
this.hintNode.parentNode.hidden = false;
},
/**
* Destroy the GcliTerm object. Call this method to avoid memory leaks.
*/
destroy: function Gcli_destroy()
{
gcli._internal.removeView(this.opts);
gcli._internal.commandOutputManager.removeListener(this.onCommandOutput, this);
delete this.opts.chromeDocument;
delete this.opts.inputElement;
delete this.opts.completeElement;
delete this.opts.inputBackgroundElement;
delete this.opts.hintElement;
delete this.opts.contentDocument;
delete this.opts.jsEnvironment;
delete this.opts.gcliTerm;
this.gcliConsole.onVisibilityChange.remove(this.onVisibilityChange, this);
this.gcliConsole.onOutput.remove(this.onOutput, this);
this.gcliConsole.destroy();
delete this.context;
delete this.document;
@ -6930,10 +6907,10 @@ GcliTerm.prototype = {
delete this._window;
delete this.sandbox;
delete this.element
delete this.inputStack
delete this.completeNode
delete this.inputNode
delete this.element;
delete this.inputStack;
delete this.completeNode;
delete this.inputNode;
},
/**
@ -6950,11 +6927,13 @@ GcliTerm.prototype = {
this.console = aConsole;
this.createSandbox();
this.opts.environment.contentDocument = aContentWindow.document;
this.opts.contentDocument = aContentWindow.document;
this.opts.jsEnvironment.globalObject = unwrap(aContentWindow);
gcli._internal.reattachConsole(this.opts);
this.gcliConsole.reattach({
contentDocument: aContentWindow.document,
environment: {
chromeDocument: this.document,
contentDocument: aContentWindow.document
},
});
},
/**
@ -6985,7 +6964,7 @@ GcliTerm.prototype = {
/**
* Called by GCLI/canon when command line output changes.
*/
onCommandOutput: function Gcli_onCommandOutput(aEvent)
onOutput: function Gcli_onOutput(aEvent)
{
// When we can update the history of the console, then we should stop
// filtering incomplete reports.

View File

@ -0,0 +1,74 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the GCLI.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Joe Walker <jwalker@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
.gclichrome-output {
max-width: 350px;
}
.gclichrome-tooltip {
max-width: 350px;
}
.gcli-help-name {
text-align: end;
}
.gcli-help-synopsis {
cursor: pointer;
display: inline-block;
}
.gcli-help-synopsis:before {
content: '\bb';
}
.gcli-menu-option {
overflow: hidden;
white-space: nowrap;
cursor: pointer;
}
.gcli-menu-template {
border-collapse: collapse;
width: 100%;
}
.gcli-menu-error {
overflow: hidden;
white-space: nowrap;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
[
<!ENTITY % webConsoleDTD SYSTEM "chrome://browser/locale/devtools/webConsole.dtd">
%webConsoleDTD;
]
>
<!-- ***** 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 GCLI.
-
- The Initial Developer of the Original Code is
- Mozilla Foundation.
- Portions created by the Initial Developer are Copyright (C) 2010
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Joe Walker <jwalker@mozilla.com>
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- in which case the provisions of the GPL or the LGPL are applicable instead
- of those above. If you wish to allow use of your version of this file only
- under the terms of either the GPL or the LGPL, and not to allow others to
- use your version of this file under the terms of the MPL, indicate your
- decision by deleting the provisions above and replace them with the notice
- and other provisions required by the LGPL or the GPL. 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 ***** -->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" href="chrome://global/skin/global.css" type="text/css"/>
<link rel="stylesheet" href="chrome://browser/content/devtools/gcli.css" type="text/css"/>
<link rel="stylesheet" href="chrome://browser/skin/devtools/gcli.css" type="text/css"/>
</head>
<body id="gclichrome-body">
<div>
</div>
</body>
</html>

View File

@ -144,17 +144,10 @@ _BROWSER_TEST_FILES = \
browser_webconsole_bug_678816.js \
browser_webconsole_bug_664131_console_group.js \
browser_webconsole_bug_704295.js \
browser_gcli_commands.js \
browser_gcli_helpers.js \
browser_gcli_inspect.js \
browser_gcli_integrate.js \
browser_gcli_require.js \
browser_gcli_web.js \
browser_webconsole_bug_658368_time_methods.js \
browser_webconsole_bug_622303_persistent_filters.js \
browser_webconsole_window_zombie.js \
browser_cached_messages.js \
browser_gcli_break.js \
head.js \
$(NULL)
@ -225,11 +218,9 @@ _BROWSER_TEST_PAGES = \
test-bug-646025-console-file-location.html \
test-bug-678816-content.js \
test-file-location.js \
browser_gcli_inspect.html \
test-bug-658368-time-methods.html \
test-webconsole-error-observer.html \
test-for-of.html \
browser_gcli_break.html \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)

View File

@ -1,105 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// For more information on GCLI see:
// - https://github.com/mozilla/gcli/blob/master/docs/index.md
// - https://wiki.mozilla.org/DevTools/Features/GCLI
// Tests that the break command works as it should
let tempScope = {};
Components.utils.import("resource:///modules/gcli.jsm", tempScope);
let gcli = tempScope.gcli;
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/browser_gcli_break.html";
registerCleanupFunction(function() {
gcliterm = undefined;
requisition = undefined;
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", true);
addTab(TEST_URI);
browser.addEventListener("DOMContentLoaded", onLoad, false);
}
let gcliterm;
let requisition;
function onLoad() {
browser.removeEventListener("DOMContentLoaded", onLoad, false);
try {
openConsole();
let hud = HUDService.getHudByWindow(content);
gcliterm = hud.gcliterm;
requisition = gcliterm.opts.requisition;
testSetup();
testCreateCommands();
}
catch (ex) {
ok(false, "Caught exception: " + ex)
gcli._internal.console.error("Test Failure", ex);
closeConsole();
finishTest();
}
}
function testSetup() {
ok(gcliterm, "We have a GCLI term");
ok(requisition, "We have a Requisition");
}
function testCreateCommands() {
type("brea");
is(gcliterm.completeNode.textContent, " break", "Completion for 'brea'");
is(requisition.getStatus().toString(), "ERROR", "brea is ERROR");
type("break");
is(requisition.getStatus().toString(), "ERROR", "break is ERROR");
type("break add");
is(requisition.getStatus().toString(), "ERROR", "break add is ERROR");
type("break add line");
is(requisition.getStatus().toString(), "ERROR", "break add line is ERROR");
let pane = DebuggerUI.toggleDebugger();
pane._frame.addEventListener("Debugger:Connecting", function dbgConnected() {
pane._frame.removeEventListener("Debugger:Connecting", dbgConnected, true);
// Wait for the initial resume.
pane.contentWindow.gClient.addOneTimeListener("resumed", function() {
pane.contentWindow.gClient.activeThread.addOneTimeListener("framesadded", function() {
type("break add line " + TEST_URI + " " + content.wrappedJSObject.line0);
is(requisition.getStatus().toString(), "VALID", "break add line is VALID");
requisition.exec();
type("break list");
is(requisition.getStatus().toString(), "VALID", "break list is VALID");
requisition.exec();
pane.contentWindow.gClient.activeThread.resume(function() {
type("break del 0");
is(requisition.getStatus().toString(), "VALID", "break del 0 is VALID");
requisition.exec();
closeConsole();
finishTest();
});
});
// Trigger newScript notifications using eval.
content.wrappedJSObject.firstCall();
});
}, true);
}
function type(command) {
gcliterm.inputNode.value = command.slice(0, -1);
gcliterm.inputNode.focus();
EventUtils.synthesizeKey(command.slice(-1), {});
}

View File

@ -1,80 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// For more information on GCLI see:
// - https://github.com/mozilla/gcli/blob/master/docs/index.md
// - https://wiki.mozilla.org/DevTools/Features/GCLI
let tmp = {};
Components.utils.import("resource:///modules/gcli.jsm", tmp);
let gcli = tmp.gcli;
let hud;
let gcliterm;
registerCleanupFunction(function() {
gcliterm = undefined;
hud = undefined;
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", true);
addTab("http://example.com/browser/browser/devtools/webconsole/test/browser_gcli_inspect.html");
browser.addEventListener("DOMContentLoaded", onLoad, false);
}
function onLoad() {
browser.removeEventListener("DOMContentLoaded", onLoad, false);
openConsole();
hud = HUDService.getHudByWindow(content);
gcliterm = hud.gcliterm;
testEcho();
// gcli._internal.console.error("Command Tests Completed");
}
function testEcho() {
let nodes = exec("echo message");
is(nodes.length, 2, "after echo");
is(nodes[0].textContent, "echo message", "output 0");
is(nodes[1].textContent.trim(), "message", "output 1");
testConsoleClear();
}
function testConsoleClear() {
let nodes = exec("console clear");
is(nodes.length, 1, "after console clear 1");
executeSoon(function() {
let nodes = hud.outputNode.querySelectorAll("richlistitem");
is(nodes.length, 0, "after console clear 2");
testConsoleClose();
});
}
function testConsoleClose() {
ok(hud.hudId in HUDService.hudReferences, "console open");
exec("console close");
ok(!(hud.hudId in HUDService.hudReferences), "console closed");
finishTest();
}
function exec(command) {
gcliterm.clearOutput();
let nodes = hud.outputNode.querySelectorAll("richlistitem");
is(nodes.length, 0, "setup - " + command);
gcliterm.opts.console.inputter.setInput(command);
gcliterm.opts.requisition.exec();
return hud.outputNode.querySelectorAll("richlistitem");
}

View File

@ -1,124 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// For more information on GCLI see:
// - https://github.com/mozilla/gcli/blob/master/docs/index.md
// - https://wiki.mozilla.org/DevTools/Features/GCLI
let tmp = {};
Components.utils.import("resource:///modules/gcli.jsm", tmp);
let gcli = tmp.gcli;
let hud;
let gcliterm;
registerCleanupFunction(function() {
gcliterm = undefined;
hud = undefined;
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", true);
addTab("http://example.com/browser/browser/devtools/webconsole/test/test-console.html");
browser.addEventListener("DOMContentLoaded", onLoad, false);
}
function onLoad() {
browser.removeEventListener("DOMContentLoaded", onLoad, false);
openConsole();
hud = HUDService.getHudByWindow(content);
gcliterm = hud.gcliterm;
testHelpers();
testScripts();
closeConsole();
finishTest();
// gcli._internal.console.error("Command Tests Completed");
}
function testScripts() {
check("{ 'id=' + $('header').getAttribute('id')", '"id=header"');
check("{ headerQuery = $$('h1')", "Instance of NodeList");
check("{ 'length=' + headerQuery.length", '"length=1"');
check("{ xpathQuery = $x('.//*', document.body);", 'Instance of Array');
check("{ 'headerFound=' + (xpathQuery[0] == headerQuery[0])", '"headerFound=true"');
check("{ 'keysResult=' + (keys({b:1})[0] == 'b')", '"keysResult=true"');
check("{ 'valuesResult=' + (values({b:1})[0] == 1)", '"valuesResult=true"');
check("{ [] instanceof Array", "true");
check("{ ({}) instanceof Object", "true");
check("{ document", "Instance of HTMLDocument");
check("{ null", "null");
check("{ undefined", undefined);
check("{ for (var x=0; x<9; x++) x;", "8");
}
function check(command, reply) {
gcliterm.clearOutput();
gcliterm.opts.console.inputter.setInput(command);
gcliterm.opts.requisition.exec();
let labels = hud.outputNode.querySelectorAll(".webconsole-msg-output");
if (reply === undefined) {
is(labels.length, 0, "results count for: " + command);
}
else {
is(labels.length, 1, "results count for: " + command);
is(labels[0].textContent.trim(), reply, "message for: " + command);
}
gcliterm.opts.console.inputter.setInput("");
}
function testHelpers() {
gcliterm.clearOutput();
gcliterm.opts.console.inputter.setInput("{ pprint({b:2, a:1})");
gcliterm.opts.requisition.exec();
// Doesn't conform to check() format
let label = hud.outputNode.querySelector(".webconsole-msg-output");
is(label.textContent.trim(), "a: 1\n b: 2", "pprint() worked");
// no gcliterm.clearOutput() here as we clear the output using the clear() fn.
gcliterm.opts.console.inputter.setInput("{ clear()");
gcliterm.opts.requisition.exec();
ok(!hud.outputNode.querySelector(".hud-group"), "clear() worked");
// check that pprint(window) and keys(window) don't throw, bug 608358
gcliterm.clearOutput();
gcliterm.opts.console.inputter.setInput("{ pprint(window)");
gcliterm.opts.requisition.exec();
let labels = hud.outputNode.querySelectorAll(".webconsole-msg-output");
is(labels.length, 1, "one line of output for pprint(window)");
gcliterm.clearOutput();
gcliterm.opts.console.inputter.setInput("{ keys(window)");
gcliterm.opts.requisition.exec();
labels = hud.outputNode.querySelectorAll(".webconsole-msg-output");
is(labels.length, 1, "one line of output for keys(window)");
gcliterm.clearOutput();
gcliterm.opts.console.inputter.setInput("{ pprint('hi')");
gcliterm.opts.requisition.exec();
// Doesn't conform to check() format, bug 614561
label = hud.outputNode.querySelector(".webconsole-msg-output");
is(label.textContent.trim(), '0: "h"\n 1: "i"', 'pprint("hi") worked');
// Causes a memory leak. FIXME Bug 717892
/*
// check that pprint(function) shows function source, bug 618344
gcliterm.clearOutput();
gcliterm.opts.console.inputter.setInput("{ pprint(print)");
gcliterm.opts.requisition.exec();
label = hud.outputNode.querySelector(".webconsole-msg-output");
isnot(label.textContent.indexOf("SEVERITY_LOG"), -1, "pprint(function) shows function source");
*/
gcliterm.clearOutput();
}

View File

@ -1,95 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// For more information on GCLI see:
// - https://github.com/mozilla/gcli/blob/master/docs/index.md
// - https://wiki.mozilla.org/DevTools/Features/GCLI
// Tests that the inspect command works as it should
let tempScope = {};
Components.utils.import("resource:///modules/gcli.jsm", tempScope);
let gcli = tempScope.gcli;
registerCleanupFunction(function() {
gcliterm = undefined;
requisition = undefined;
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", true);
addTab("http://example.com/browser/browser/devtools/webconsole/test/browser_gcli_inspect.html");
browser.addEventListener("DOMContentLoaded", onLoad, false);
}
let gcliterm;
let requisition;
function onLoad() {
browser.removeEventListener("DOMContentLoaded", onLoad, false);
try {
openConsole();
let hud = HUDService.getHudByWindow(content);
gcliterm = hud.gcliterm;
requisition = gcliterm.opts.requisition;
testSetup();
testCreateCommands();
}
catch (ex) {
ok(false, "Caught exception: " + ex)
gcli._internal.console.error("Test Failure", ex);
}
finally {
closeConsole();
finishTest();
}
}
function testSetup() {
ok(gcliterm, "We have a GCLI term");
ok(requisition, "We have a Requisition");
}
function testCreateCommands() {
type("inspec");
is(gcliterm.completeNode.textContent, " inspect", "Completion for \"inspec\"");
is(requisition.getStatus().toString(), "ERROR", "inspec is ERROR");
type("inspect");
is(requisition.getStatus().toString(), "ERROR", "inspect is ERROR");
type("inspect h1");
is(requisition.getStatus().toString(), "ERROR", "inspect h1 is ERROR");
type("inspect span");
is(requisition.getStatus().toString(), "ERROR", "inspect span is ERROR");
type("inspect div");
is(requisition.getStatus().toString(), "VALID", "inspect div is VALID");
type("inspect .someclass");
is(requisition.getStatus().toString(), "VALID", "inspect .someclass is VALID");
type("inspect #someid");
is(requisition.getStatus().toString(), "VALID", "inspect #someid is VALID");
type("inspect button[disabled]");
is(requisition.getStatus().toString(), "VALID", "inspect button[disabled] is VALID");
type("inspect p>strong");
is(requisition.getStatus().toString(), "VALID", "inspect p>strong is VALID");
type("inspect :root");
is(requisition.getStatus().toString(), "VALID", "inspect :root is VALID");
}
function type(command) {
gcliterm.inputNode.value = command.slice(0, -1);
gcliterm.inputNode.focus();
EventUtils.synthesizeKey(command.slice(-1), {});
}

View File

@ -1,106 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// For more information on GCLI see:
// - https://github.com/mozilla/gcli/blob/master/docs/index.md
// - https://wiki.mozilla.org/DevTools/Features/GCLI
// Tests that source URLs in the Web Console can be clicked to display the
// standard View Source window.
let tempScope = {};
Components.utils.import("resource:///modules/gcli.jsm", tempScope);
let gcli = tempScope.gcli;
let require = gcli._internal.require;
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
registerCleanupFunction(function() {
require = undefined;
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", true);
addTab(TEST_URI);
browser.addEventListener("DOMContentLoaded", onLoad, false);
}
function onLoad() {
browser.removeEventListener("DOMContentLoaded", onLoad, false);
try {
openConsole();
testCreateCommands();
testCallCommands();
testRemoveCommands();
}
catch (ex) {
gcli._internal.console.error('Test Failure', ex);
ok(false, '' + ex);
}
finally {
closeConsole();
finishTest();
}
}
let tselarr = {
name: 'tselarr',
params: [
{ name: 'num', type: { name: 'selection', data: [ '1', '2', '3' ] } },
{ name: 'arr', type: { name: 'array', subtype: 'string' } },
],
exec: function(args, env) {
return "flu " + args.num + "-" + args.arr.join("_");
}
};
function testCreateCommands() {
let gcli = require("gcli/index");
gcli.addCommand(tselarr);
let canon = require("gcli/canon");
let tselcmd = canon.getCommand("tselarr");
ok(tselcmd != null, "tselarr exists in the canon");
ok(tselcmd instanceof canon.Command, "canon storing commands");
}
function testCallCommands() {
let hud = HUDService.getHudByWindow(content);
let gcliterm = hud.gcliterm;
ok(gcliterm, "We have a GCLI term");
// Test successful auto-completion
gcliterm.inputNode.value = "h";
gcliterm.inputNode.focus();
EventUtils.synthesizeKey("e", {});
is(gcliterm.completeNode.textContent, " help", "Completion for \"he\"");
// Test unsuccessful auto-completion
gcliterm.inputNode.value = "ec";
gcliterm.inputNode.focus();
EventUtils.synthesizeKey("d", {});
is(gcliterm.completeNode.textContent, " ecd", "Completion for \"ecd\"");
// Test a normal command's life cycle
gcliterm.opts.console.inputter.setInput("echo hello world");
gcliterm.opts.requisition.exec();
let nodes = hud.outputNode.querySelectorAll(".gcliterm-msg-body");
is(nodes.length, 1, "Right number of output nodes");
ok(/hello world/.test(nodes[0].textContent), "the command's output is correct.");
gcliterm.clearOutput();
}
function testRemoveCommands() {
let gcli = require("gcli/index");
gcli.removeCommand(tselarr);
let canon = require("gcli/canon");
let tselcmd = canon.getCommand("tselarr");
ok(tselcmd == null, "tselcmd removed from the canon");
}

View File

@ -42,12 +42,7 @@
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("DOMContentLoaded", testInputFocus, false);
}

View File

@ -43,12 +43,7 @@
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("DOMContentLoaded", testClosingAfterCompletion,
false);

View File

@ -42,12 +42,7 @@
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("DOMContentLoaded", testGroups, false);
}

View File

@ -43,12 +43,7 @@
const TEST_DUPLICATE_ERROR_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-duplicate-error.html";
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
expectUncaughtException();
addTab(TEST_DUPLICATE_ERROR_URI);
browser.addEventListener("DOMContentLoaded", testDuplicateErrors, false);

View File

@ -39,12 +39,7 @@
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/browser/test-console.html";
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("DOMContentLoaded", testCompletion, false);
}

View File

@ -39,12 +39,7 @@
const TEST_URI = "data:text/html;charset=utf-8,<p>bug 585991 - autocomplete popup keyboard usage test";
let HUD;
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("load", tabLoaded, true);
}

View File

@ -38,12 +38,7 @@
const TEST_URI = "data:text/html;charset=utf-8,<p>bug 585991 - autocomplete popup test";
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("load", tabLoaded, true);
}

View File

@ -10,12 +10,7 @@
const TEST_URI = "http://example.com/";
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("DOMContentLoaded",
testSelectionWhenMovingBetweenBoxes, false);

View File

@ -10,12 +10,7 @@
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("load", tabLoaded, true);
}

View File

@ -11,12 +11,7 @@
const TEST_URI = "data:text/html;charset=utf-8,Web Console test for bug 588342";
let fm, notificationBox, input;
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
addTab(TEST_URI);
browser.addEventListener("load", tabLoad, true);

View File

@ -38,12 +38,7 @@
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("DOMContentLoaded", testInputExpansion, false);
}

View File

@ -13,12 +13,7 @@
// Tests that, when the user types an extraneous closing bracket, no error
// appears.
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab("data:text/html;charset=utf-8,test for bug 592442");
browser.addEventListener("load", testExtraneousClosingBrackets, true);
}

View File

@ -154,12 +154,7 @@ function propertyPanelHidden(aEvent) {
});
}
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("load", tabLoad1, true);
}

View File

@ -155,12 +155,7 @@ function performTests() {
executeSoon(finishTest);
}
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab("data:text/html;charset=utf-8,Web Console test for bug 594497 and bug 619598");
browser.addEventListener("load", tabLoad, true);
}

View File

@ -172,7 +172,6 @@ function testNext() {
}
function testEnd() {
Services.prefs.clearUserPref("devtools.gcli.enable");
Services.console.unregisterListener(TestObserver);
output.removeEventListener("DOMNodeInserted", onDOMNodeInserted, false);
output = jsterm = null;
@ -192,7 +191,6 @@ function onDOMNodeInserted(aEvent) {
}
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
registerCleanupFunction(testEnd);
addTab("data:text/html;charset=utf-8,Web Console test for bug 595934 - message categories coverage.");

View File

@ -225,12 +225,7 @@ function testEnd() {
executeSoon(finishTest);
}
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("load", tabLoad, true);
}

View File

@ -57,12 +57,7 @@ function tabLoad(aEvent) {
});
}
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab("data:text/html;charset=utf-8,Web Console test for bug 601352");
browser.addEventListener("load", tabLoad, true);
}

View File

@ -32,17 +32,12 @@ function onContentLoaded()
finishTest();
}
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
/**
* Unit test for bug 611795:
* Repeated CSS messages get collapsed into one.
*/
function test()
{
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("load", function() {
browser.removeEventListener("load", arguments.callee, true);

View File

@ -8,12 +8,7 @@
const TEST_URI = "data:text/html;charset=utf-8,Web Console test for bug 613280";
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("load", tabLoaded, true);
}

View File

@ -36,12 +36,7 @@ function tabLoad(aEvent) {
finishTest();
}
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab("data:text/html;charset=utf-8,Web Console test for bug 614793: jsterm result scroll");
browser.addEventListener("load", tabLoad, true);
}

View File

@ -38,12 +38,7 @@
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("load", function() {
browser.removeEventListener("load", arguments.callee, true);

View File

@ -41,12 +41,7 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/te
let pb = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService);
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab("data:text/html;charset=utf-8,Web Console test for bug 618311 (private browsing)");
browser.addEventListener("load", function() {

View File

@ -42,12 +42,7 @@ function tabLoad(aEvent) {
}, content);
}
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("load", tabLoad, true);
}

View File

@ -2,12 +2,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
let itemsSet, HUD;
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab("data:text/html;charset=utf-8,Web Console test for bug 626484");
browser.addEventListener("load", tabLoaded, true);
}

View File

@ -3,12 +3,7 @@
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-632275-getters.html";
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("load", tabLoaded, true);
}

View File

@ -38,12 +38,7 @@
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-632347-iterators-generators.html";
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("load", tabLoaded, true);
}

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