mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-28 03:18:41 +00:00
Merge from mozilla-central.
This commit is contained in:
commit
c093e3fa4d
@ -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.
|
||||
|
@ -67,7 +67,6 @@ nsAccessNodeWrap::~nsAccessNodeWrap()
|
||||
|
||||
void nsAccessNodeWrap::InitAccessibility()
|
||||
{
|
||||
nsAccessNode::InitXPAccessibility();
|
||||
}
|
||||
|
||||
void nsAccessNodeWrap::ShutdownAccessibility()
|
||||
|
@ -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
|
||||
|
@ -71,6 +71,7 @@ CPPSRCS = \
|
||||
nsCaretAccessible.cpp \
|
||||
nsTextAccessible.cpp \
|
||||
nsTextEquivUtils.cpp \
|
||||
RoleAsserts.cpp \
|
||||
StyleInfo.cpp \
|
||||
TextAttrs.cpp \
|
||||
TextUpdater.cpp \
|
||||
|
17
accessible/src/base/RoleAsserts.cpp
Normal file
17
accessible/src/base/RoleAsserts.cpp
Normal 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
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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";
|
||||
|
@ -67,7 +67,6 @@ nsAccessNodeWrap::~nsAccessNodeWrap()
|
||||
|
||||
void nsAccessNodeWrap::InitAccessibility()
|
||||
{
|
||||
nsAccessNode::InitXPAccessibility();
|
||||
}
|
||||
|
||||
void nsAccessNodeWrap::ShutdownAccessibility()
|
||||
|
@ -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.
|
||||
|
@ -588,8 +588,6 @@ void nsAccessNodeWrap::InitAccessibility()
|
||||
Compatibility::Init();
|
||||
|
||||
nsWinUtils::MaybeStartWindowEmulation();
|
||||
|
||||
nsAccessNode::InitXPAccessibility();
|
||||
}
|
||||
|
||||
void nsAccessNodeWrap::ShutdownAccessibility()
|
||||
|
@ -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
|
||||
|
||||
|
@ -66,7 +66,6 @@ nsAccessNodeWrap::~nsAccessNodeWrap()
|
||||
|
||||
void nsAccessNodeWrap::InitAccessibility()
|
||||
{
|
||||
nsAccessNode::InitXPAccessibility();
|
||||
}
|
||||
|
||||
void nsAccessNodeWrap::ShutdownAccessibility()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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); \
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 \
|
||||
|
101
accessible/tests/mochitest/text/test_selection.html
Normal file
101
accessible/tests/mochitest/text/test_selection.html
Normal 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>
|
@ -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.
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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">»</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"
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
},
|
||||
|
@ -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)
|
||||
|
671
browser/devtools/shared/DeveloperToolbar.jsm
Normal file
671
browser/devtools/shared/DeveloperToolbar.jsm
Normal 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();
|
||||
}
|
||||
};
|
@ -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)
|
||||
|
@ -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>
|
82
browser/devtools/shared/test/browser_gcli_break.js
Normal file
82
browser/devtools/shared/test/browser_gcli_break.js
Normal 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);
|
||||
}
|
55
browser/devtools/shared/test/browser_gcli_commands.js
Normal file
55
browser/devtools/shared/test/browser_gcli_commands.js
Normal 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");
|
||||
}
|
68
browser/devtools/shared/test/browser_gcli_inspect.js
Normal file
68
browser/devtools/shared/test/browser_gcli_inspect.js
Normal 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"
|
||||
});
|
||||
}
|
40
browser/devtools/shared/test/browser_gcli_integrate.js
Normal file
40
browser/devtools/shared/test/browser_gcli_integrate.js
Normal 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");
|
||||
}
|
@ -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() {
|
3762
browser/devtools/webconsole/test/browser_gcli_web.js → browser/devtools/shared/test/browser_gcli_web.js
Normal file → Executable file
3762
browser/devtools/webconsole/test/browser_gcli_web.js → browser/devtools/shared/test/browser_gcli_web.js
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
35
browser/devtools/shared/test/browser_toolbar_basic.html
Normal file
35
browser/devtools/shared/test/browser_toolbar_basic.html
Normal 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>
|
||||
|
36
browser/devtools/shared/test/browser_toolbar_basic.js
Normal file
36
browser/devtools/shared/test/browser_toolbar_basic.js
Normal 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();
|
||||
}
|
@ -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;
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
|
@ -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;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
});
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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.
|
||||
|
74
browser/devtools/webconsole/gcli.css
Normal file
74
browser/devtools/webconsole/gcli.css
Normal 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
59
browser/devtools/webconsole/gcliblank.xhtml
Normal file
59
browser/devtools/webconsole/gcliblank.xhtml
Normal 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>
|
@ -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)
|
||||
|
@ -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), {});
|
||||
}
|
@ -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");
|
||||
}
|
@ -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();
|
||||
}
|
@ -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), {});
|
||||
}
|
@ -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");
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.");
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user