зеркало из https://github.com/mozilla/gecko-dev.git
Merge from mozilla-central.
This commit is contained in:
Коммит
68a2caab6c
|
@ -721,7 +721,7 @@ getRoleCB(AtkObject *aAtkObj)
|
|||
if (!accWrap)
|
||||
return ATK_ROLE_INVALID;
|
||||
|
||||
#ifdef DEBUG_A11Y
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(accWrap),
|
||||
"Does not support nsIAccessibleText when it should");
|
||||
#endif
|
||||
|
|
|
@ -74,9 +74,9 @@ public:
|
|||
mFirstIter(nsnull), mLastIter(nsnull)
|
||||
{ AppendTarget(aAcc); }
|
||||
|
||||
Relation(nsIContent* aContent) :
|
||||
Relation(nsDocAccessible* aDocument, nsIContent* aContent) :
|
||||
mFirstIter(nsnull), mLastIter(nsnull)
|
||||
{ AppendTarget(aContent); }
|
||||
{ AppendTarget(aDocument, aContent); }
|
||||
|
||||
Relation& operator = (const RelationCopyHelper& aRH)
|
||||
{
|
||||
|
@ -120,10 +120,10 @@ public:
|
|||
* Append the one accessible for this content node to the set of related
|
||||
* accessibles.
|
||||
*/
|
||||
inline void AppendTarget(nsIContent* aContent)
|
||||
void AppendTarget(nsDocAccessible* aDocument, nsIContent* aContent)
|
||||
{
|
||||
if (aContent)
|
||||
AppendTarget(GetAccService()->GetAccessible(aContent, nsnull));
|
||||
AppendTarget(aDocument->GetAccessible(aContent));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -443,10 +443,10 @@ nsAccUtils::GetLiveAttrValue(PRUint32 aRule, nsAString& aValue)
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_A11Y
|
||||
#ifdef DEBUG
|
||||
|
||||
bool
|
||||
nsAccUtils::IsTextInterfaceSupportCorrect(nsAccessible *aAccessible)
|
||||
nsAccUtils::IsTextInterfaceSupportCorrect(nsAccessible* aAccessible)
|
||||
{
|
||||
// Don't test for accessible docs, it makes us create accessibles too
|
||||
// early and fire mutation events before we need to
|
||||
|
@ -455,8 +455,8 @@ nsAccUtils::IsTextInterfaceSupportCorrect(nsAccessible *aAccessible)
|
|||
|
||||
bool foundText = false;
|
||||
PRInt32 childCount = aAccessible->GetChildCount();
|
||||
for (PRint32 childIdx = 0; childIdx < childCount; childIdx++) {
|
||||
nsAccessible *child = GetChildAt(childIdx);
|
||||
for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
|
||||
nsAccessible* child = aAccessible->GetChildAt(childIdx);
|
||||
if (IsText(child)) {
|
||||
foundText = true;
|
||||
break;
|
||||
|
@ -470,7 +470,7 @@ nsAccUtils::IsTextInterfaceSupportCorrect(nsAccessible *aAccessible)
|
|||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -270,7 +270,7 @@ public:
|
|||
*/
|
||||
static bool GetLiveAttrValue(PRUint32 aRule, nsAString& aValue);
|
||||
|
||||
#ifdef DEBUG_A11Y
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* Detect whether the given accessible object implements nsIAccessibleText,
|
||||
* when it is text or has text child node.
|
||||
|
|
|
@ -49,9 +49,6 @@
|
|||
#include "nsIDOMWindow.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIStringBundle.h"
|
||||
|
@ -67,8 +64,6 @@ using namespace mozilla::a11y;
|
|||
|
||||
nsIStringBundle *nsAccessNode::gStringBundle = 0;
|
||||
|
||||
bool nsAccessNode::gIsFormFillEnabled = false;
|
||||
|
||||
ApplicationAccessible* nsAccessNode::gApplicationAccessible = nsnull;
|
||||
|
||||
/*
|
||||
|
@ -163,28 +158,6 @@ void nsAccessNode::InitXPAccessibility()
|
|||
stringBundleService->CreateBundle(ACCESSIBLE_BUNDLE_URL,
|
||||
&gStringBundle);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||
if (prefBranch) {
|
||||
prefBranch->GetBoolPref("browser.formfill.enable", &gIsFormFillEnabled);
|
||||
}
|
||||
|
||||
NotifyA11yInitOrShutdown(true);
|
||||
}
|
||||
|
||||
// nsAccessNode protected static
|
||||
void nsAccessNode::NotifyA11yInitOrShutdown(bool aIsInit)
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> obsService =
|
||||
mozilla::services::GetObserverService();
|
||||
NS_ASSERTION(obsService, "No observer service to notify of a11y init/shutdown");
|
||||
if (!obsService)
|
||||
return;
|
||||
|
||||
static const PRUnichar kInitIndicator[] = { '1', 0 };
|
||||
static const PRUnichar kShutdownIndicator[] = { '0', 0 };
|
||||
obsService->NotifyObservers(nsnull, "a11y-init-or-shutdown",
|
||||
aIsInit ? kInitIndicator : kShutdownIndicator);
|
||||
}
|
||||
|
||||
void nsAccessNode::ShutdownXPAccessibility()
|
||||
|
@ -202,8 +175,6 @@ void nsAccessNode::ShutdownXPAccessibility()
|
|||
gApplicationAccessible->Shutdown();
|
||||
NS_RELEASE(gApplicationAccessible);
|
||||
}
|
||||
|
||||
NotifyA11yInitOrShutdown(false);
|
||||
}
|
||||
|
||||
RootAccessible*
|
||||
|
|
|
@ -164,16 +164,9 @@ protected:
|
|||
nsCOMPtr<nsIContent> mContent;
|
||||
nsDocAccessible* mDoc;
|
||||
|
||||
/**
|
||||
* Notify global nsIObserver's that a11y is getting init'd or shutdown.
|
||||
*/
|
||||
static void NotifyA11yInitOrShutdown(bool aIsInit);
|
||||
|
||||
// Static data, we do our own refcounting for our static data.
|
||||
static nsIStringBundle* gStringBundle;
|
||||
|
||||
static bool gIsFormFillEnabled;
|
||||
|
||||
private:
|
||||
nsAccessNode() MOZ_DELETE;
|
||||
nsAccessNode(const nsAccessNode&) MOZ_DELETE;
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "AtkSocketAccessible.h"
|
||||
#endif
|
||||
#include "FocusManager.h"
|
||||
#include "HTMLListAccessible.h"
|
||||
#include "nsAccessiblePivot.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsARIAMap.h"
|
||||
|
@ -222,7 +223,7 @@ nsAccessibilityService::CreateHTMLLIAccessible(nsIContent* aContent,
|
|||
nsIPresShell* aPresShell)
|
||||
{
|
||||
nsAccessible* accessible =
|
||||
new nsHTMLLIAccessible(aContent, GetDocAccessible(aPresShell));
|
||||
new HTMLLIAccessible(aContent, GetDocAccessible(aPresShell));
|
||||
NS_ADDREF(accessible);
|
||||
return accessible;
|
||||
}
|
||||
|
@ -599,7 +600,7 @@ nsAccessibilityService::UpdateListBullet(nsIPresShell* aPresShell,
|
|||
if (document) {
|
||||
nsAccessible* accessible = document->GetAccessible(aHTMLListItemContent);
|
||||
if (accessible) {
|
||||
nsHTMLLIAccessible* listItem = accessible->AsHTMLListItem();
|
||||
HTMLLIAccessible* listItem = accessible->AsHTMLListItem();
|
||||
if (listItem)
|
||||
listItem->UpdateBullet(aHasBullet);
|
||||
}
|
||||
|
@ -1271,6 +1272,9 @@ nsAccessibilityService::Init()
|
|||
|
||||
observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
|
||||
static const PRUnichar kInitIndicator[] = { '1', 0 };
|
||||
observerService->NotifyObservers(nsnull, "a11y-init-or-shutdown", kInitIndicator);
|
||||
|
||||
// Initialize accessibility.
|
||||
nsAccessNodeWrap::InitAccessibility();
|
||||
|
||||
|
@ -1284,9 +1288,13 @@ nsAccessibilityService::Shutdown()
|
|||
// Remove observers.
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
if (observerService)
|
||||
if (observerService) {
|
||||
observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||
|
||||
static const PRUnichar kShutdownIndicator[] = { '0', 0 };
|
||||
observerService->NotifyObservers(nsnull, "a11y-init-or-shutdown", kShutdownIndicator);
|
||||
}
|
||||
|
||||
// Stop accessible document loader.
|
||||
nsAccDocManager::Shutdown();
|
||||
|
||||
|
@ -1651,7 +1659,7 @@ nsAccessibilityService::CreateHTMLAccessibleByMarkup(nsIFrame* aFrame,
|
|||
|
||||
if (tag == nsGkAtoms::ul || tag == nsGkAtoms::ol ||
|
||||
tag == nsGkAtoms::dl) {
|
||||
nsAccessible* accessible = new nsHTMLListAccessible(aContent, aDoc);
|
||||
nsAccessible* accessible = new HTMLListAccessible(aContent, aDoc);
|
||||
NS_IF_ADDREF(accessible);
|
||||
return accessible;
|
||||
}
|
||||
|
@ -1678,7 +1686,7 @@ nsAccessibilityService::CreateHTMLAccessibleByMarkup(nsIFrame* aFrame,
|
|||
// Normally for li, it is created by the list item frame (in nsBlockFrame)
|
||||
// which knows about the bullet frame; however, in this case the list item
|
||||
// must have been styled using display: foo
|
||||
nsAccessible* accessible = new nsHTMLLIAccessible(aContent, aDoc);
|
||||
nsAccessible* accessible = new HTMLLIAccessible(aContent, aDoc);
|
||||
NS_IF_ADDREF(accessible);
|
||||
return accessible;
|
||||
}
|
||||
|
|
|
@ -914,7 +914,7 @@ void nsAccessible::GetBoundsRect(nsRect& aTotalBounds, nsIFrame** aBoundingFrame
|
|||
|
||||
// Initialization area
|
||||
*aBoundingFrame = nsnull;
|
||||
nsIFrame *firstFrame = GetBoundsFrame();
|
||||
nsIFrame* firstFrame = GetFrame();
|
||||
if (!firstFrame)
|
||||
return;
|
||||
|
||||
|
@ -1029,13 +1029,6 @@ nsAccessible::GetBounds(PRInt32* aX, PRInt32* aY,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// helpers
|
||||
|
||||
nsIFrame* nsAccessible::GetBoundsFrame()
|
||||
{
|
||||
return GetFrame();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAccessible::SetSelected(bool aSelect)
|
||||
{
|
||||
if (IsDefunct())
|
||||
|
@ -2109,7 +2102,7 @@ nsAccessible::RelationByType(PRUint32 aType)
|
|||
if (form) {
|
||||
nsCOMPtr<nsIContent> formContent =
|
||||
do_QueryInterface(form->GetDefaultSubmitElement());
|
||||
return Relation(formContent);
|
||||
return Relation(mDoc, formContent);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -2150,13 +2143,13 @@ nsAccessible::RelationByType(PRUint32 aType)
|
|||
}
|
||||
}
|
||||
nsCOMPtr<nsIContent> relatedContent(do_QueryInterface(buttonEl));
|
||||
return Relation(relatedContent);
|
||||
return Relation(mDoc, relatedContent);
|
||||
}
|
||||
}
|
||||
return Relation();
|
||||
}
|
||||
case nsIAccessibleRelation::RELATION_MEMBER_OF:
|
||||
return Relation(GetAtomicRegion());
|
||||
return Relation(mDoc, GetAtomicRegion());
|
||||
case nsIAccessibleRelation::RELATION_SUBWINDOW_OF:
|
||||
case nsIAccessibleRelation::RELATION_EMBEDS:
|
||||
case nsIAccessibleRelation::RELATION_EMBEDDED_BY:
|
||||
|
|
|
@ -62,12 +62,13 @@ class nsAccessible;
|
|||
class nsHyperTextAccessible;
|
||||
class nsHTMLImageAccessible;
|
||||
class nsHTMLImageMapAccessible;
|
||||
class nsHTMLLIAccessible;
|
||||
struct nsRoleMapEntry;
|
||||
class Relation;
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
class HTMLLIAccessible;
|
||||
class TableAccessible;
|
||||
|
||||
/**
|
||||
|
@ -445,6 +446,11 @@ public:
|
|||
*/
|
||||
void TestChildCache(nsAccessible* aCachedChild) const;
|
||||
|
||||
/**
|
||||
* Return boundaries rect relative the bounding frame.
|
||||
*/
|
||||
virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Downcasting and types
|
||||
|
||||
|
@ -471,7 +477,7 @@ public:
|
|||
inline bool IsHTMLFileInput() const { return mFlags & eHTMLFileInputAccessible; }
|
||||
|
||||
inline bool IsHTMLListItem() const { return mFlags & eHTMLListItemAccessible; }
|
||||
nsHTMLLIAccessible* AsHTMLListItem();
|
||||
mozilla::a11y::HTMLLIAccessible* AsHTMLListItem();
|
||||
|
||||
inline bool IsImageAccessible() const { return mFlags & eImageAccessible; }
|
||||
nsHTMLImageAccessible* AsImage();
|
||||
|
@ -745,9 +751,6 @@ protected:
|
|||
*/
|
||||
mozilla::a11y::role ARIATransformRole(mozilla::a11y::role aRole);
|
||||
|
||||
virtual nsIFrame* GetBoundsFrame();
|
||||
virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Name helpers
|
||||
|
||||
|
|
|
@ -123,6 +123,8 @@ public:
|
|||
virtual nsresult HandleAccEvent(AccEvent* aAccEvent);
|
||||
#endif
|
||||
|
||||
virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
|
||||
|
||||
// nsHyperTextAccessible
|
||||
virtual already_AddRefed<nsIEditor> GetEditor() const;
|
||||
|
||||
|
@ -384,7 +386,6 @@ protected:
|
|||
virtual void CacheChildren();
|
||||
|
||||
// nsDocAccessible
|
||||
virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
|
||||
virtual nsresult AddEventListeners();
|
||||
virtual nsresult RemoveEventListeners();
|
||||
|
||||
|
|
|
@ -63,6 +63,9 @@
|
|||
#include "nsIServiceManager.h"
|
||||
#include "nsITextControlFrame.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -496,7 +499,7 @@ HTMLTextFieldAccessible::NativeState()
|
|||
|
||||
// No parent can mean a fake widget created for XUL textbox. If accessible
|
||||
// is unattached from tree then we don't care.
|
||||
if (mParent && gIsFormFillEnabled) {
|
||||
if (mParent && Preferences::GetBool("browser.formfill.enable")) {
|
||||
// Check to see if autocompletion is allowed on this input. We don't expose
|
||||
// it for password fields even though the entire password can be remembered
|
||||
// for a page if the user asks it to be. However, the kind of autocomplete
|
||||
|
@ -704,7 +707,7 @@ HTMLGroupboxAccessible::RelationByType(PRUint32 aType)
|
|||
Relation rel = nsHyperTextAccessibleWrap::RelationByType(aType);
|
||||
// No override for label, so use <legend> for this <fieldset>
|
||||
if (aType == nsIAccessibleRelation::RELATION_LABELLED_BY)
|
||||
rel.AppendTarget(GetLegend());
|
||||
rel.AppendTarget(mDoc, GetLegend());
|
||||
|
||||
return rel;
|
||||
}
|
||||
|
@ -790,7 +793,7 @@ HTMLFigureAccessible::RelationByType(PRUint32 aType)
|
|||
{
|
||||
Relation rel = nsHyperTextAccessibleWrap::RelationByType(aType);
|
||||
if (aType == nsIAccessibleRelation::RELATION_LABELLED_BY)
|
||||
rel.AppendTarget(Caption());
|
||||
rel.AppendTarget(mDoc, Caption());
|
||||
|
||||
return rel;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
/* -*- 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 "HTMLListAccessible.h"
|
||||
|
||||
#include "nsDocAccessible.h"
|
||||
#include "Role.h"
|
||||
#include "States.h"
|
||||
|
||||
#include "nsBlockFrame.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// HTMLListAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(HTMLListAccessible, nsHyperTextAccessible)
|
||||
|
||||
role
|
||||
HTMLListAccessible::NativeRole()
|
||||
{
|
||||
if (mContent->Tag() == nsGkAtoms::dl)
|
||||
return roles::DEFINITION_LIST;
|
||||
|
||||
return roles::LIST;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
HTMLListAccessible::NativeState()
|
||||
{
|
||||
return nsHyperTextAccessibleWrap::NativeState() | states::READONLY;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// HTMLLIAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HTMLLIAccessible::
|
||||
HTMLLIAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
|
||||
nsHyperTextAccessibleWrap(aContent, aDoc), mBullet(nsnull)
|
||||
{
|
||||
mFlags |= eHTMLListItemAccessible;
|
||||
|
||||
nsBlockFrame* blockFrame = do_QueryFrame(GetFrame());
|
||||
if (blockFrame && blockFrame->HasBullet()) {
|
||||
mBullet = new HTMLListBulletAccessible(mContent, mDoc);
|
||||
if (!Document()->BindToDocument(mBullet, nsnull))
|
||||
mBullet = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(HTMLLIAccessible, nsHyperTextAccessible)
|
||||
|
||||
void
|
||||
HTMLLIAccessible::Shutdown()
|
||||
{
|
||||
mBullet = nsnull;
|
||||
|
||||
nsHyperTextAccessibleWrap::Shutdown();
|
||||
}
|
||||
|
||||
role
|
||||
HTMLLIAccessible::NativeRole()
|
||||
{
|
||||
if (mContent->Tag() == nsGkAtoms::dt)
|
||||
return roles::TERM;
|
||||
|
||||
return roles::LISTITEM;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
HTMLLIAccessible::NativeState()
|
||||
{
|
||||
return nsHyperTextAccessibleWrap::NativeState() | states::READONLY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLLIAccessible::GetBounds(PRInt32* aX, PRInt32* aY,
|
||||
PRInt32* aWidth, PRInt32* aHeight)
|
||||
{
|
||||
nsresult rv = nsAccessibleWrap::GetBounds(aX, aY, aWidth, aHeight);
|
||||
if (NS_FAILED(rv) || !mBullet)
|
||||
return rv;
|
||||
|
||||
PRInt32 bulletX = 0, bulletY = 0, bulletWidth = 0, bulletHeight = 0;
|
||||
rv = mBullet->GetBounds(&bulletX, &bulletY, &bulletWidth, &bulletHeight);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aX = bulletX; // Move x coordinate of list item over to cover bullet as well
|
||||
*aWidth += bulletWidth;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// HTMLLIAccessible: public
|
||||
|
||||
void
|
||||
HTMLLIAccessible::UpdateBullet(bool aHasBullet)
|
||||
{
|
||||
if (aHasBullet == !!mBullet) {
|
||||
NS_NOTREACHED("Bullet and accessible are in sync already!");
|
||||
return;
|
||||
}
|
||||
|
||||
nsDocAccessible* document = Document();
|
||||
if (aHasBullet) {
|
||||
mBullet = new HTMLListBulletAccessible(mContent, mDoc);
|
||||
if (document->BindToDocument(mBullet, nsnull)) {
|
||||
InsertChildAt(0, mBullet);
|
||||
}
|
||||
} else {
|
||||
RemoveChild(mBullet);
|
||||
document->UnbindFromDocument(mBullet);
|
||||
mBullet = nsnull;
|
||||
}
|
||||
|
||||
// XXXtodo: fire show/hide and reorder events. That's hard to make it
|
||||
// right now because coalescence happens by DOM node.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// HTMLLIAccessible: nsAccessible protected
|
||||
|
||||
void
|
||||
HTMLLIAccessible::CacheChildren()
|
||||
{
|
||||
if (mBullet)
|
||||
AppendChild(mBullet);
|
||||
|
||||
// Cache children from subtree.
|
||||
nsAccessibleWrap::CacheChildren();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// HTMLListBulletAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// HTMLListBulletAccessible: nsAccessNode
|
||||
|
||||
bool
|
||||
HTMLListBulletAccessible::IsPrimaryForNode() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// HTMLListBulletAccessible: nsAccessible
|
||||
|
||||
ENameValueFlag
|
||||
HTMLListBulletAccessible::Name(nsString &aName)
|
||||
{
|
||||
aName.Truncate();
|
||||
|
||||
// Native anonymous content, ARIA can't be used. Get list bullet text.
|
||||
nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
|
||||
NS_ASSERTION(blockFrame, "No frame for list item!");
|
||||
if (blockFrame) {
|
||||
blockFrame->GetBulletText(aName);
|
||||
|
||||
// Append space otherwise bullets are jammed up against list text.
|
||||
aName.Append(' ');
|
||||
}
|
||||
|
||||
return eNameOK;
|
||||
}
|
||||
|
||||
role
|
||||
HTMLListBulletAccessible::NativeRole()
|
||||
{
|
||||
return roles::STATICTEXT;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
HTMLListBulletAccessible::NativeState()
|
||||
{
|
||||
PRUint64 state = nsLeafAccessible::NativeState();
|
||||
|
||||
state &= ~states::FOCUSABLE;
|
||||
state |= states::READONLY;
|
||||
return state;
|
||||
}
|
||||
|
||||
void
|
||||
HTMLListBulletAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
|
||||
PRUint32 aLength)
|
||||
{
|
||||
nsAutoString bulletText;
|
||||
nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
|
||||
NS_ASSERTION(blockFrame, "No frame for list item!");
|
||||
if (blockFrame)
|
||||
blockFrame->GetBulletText(bulletText);
|
||||
|
||||
aText.Append(Substring(bulletText, aStartOffset, aLength));
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_a11y_HTMLListAccessible_h__
|
||||
#define mozilla_a11y_HTMLListAccessible_h__
|
||||
|
||||
#include "nsHyperTextAccessibleWrap.h"
|
||||
#include "nsBaseWidgetAccessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
class HTMLListBulletAccessible;
|
||||
|
||||
/**
|
||||
* Used for HTML list (like HTML ul).
|
||||
*/
|
||||
class HTMLListAccessible : public nsHyperTextAccessibleWrap
|
||||
{
|
||||
public:
|
||||
HTMLListAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
|
||||
nsHyperTextAccessibleWrap(aContent, aDoc) { }
|
||||
virtual ~HTMLListAccessible() { }
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsAccessible
|
||||
virtual a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Used for HTML list item (e.g. HTML li).
|
||||
*/
|
||||
class HTMLLIAccessible : public nsHyperTextAccessibleWrap
|
||||
{
|
||||
public:
|
||||
HTMLLIAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
|
||||
virtual ~HTMLLIAccessible() { }
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsAccessNode
|
||||
virtual void Shutdown();
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetBounds(PRInt32* aX, PRInt32* aY,
|
||||
PRInt32* aWidth, PRInt32* aHeight);
|
||||
|
||||
// nsAccessible
|
||||
virtual a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
|
||||
// nsHTMLLIAccessible
|
||||
void UpdateBullet(bool aHasBullet);
|
||||
|
||||
protected:
|
||||
// nsAccessible
|
||||
virtual void CacheChildren();
|
||||
|
||||
private:
|
||||
nsRefPtr<HTMLListBulletAccessible> mBullet;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Used for bullet of HTML list item element (for example, HTML li).
|
||||
*/
|
||||
class HTMLListBulletAccessible : public nsLeafAccessible
|
||||
{
|
||||
public:
|
||||
HTMLListBulletAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
|
||||
nsLeafAccessible(aContent, aDoc) { }
|
||||
virtual ~HTMLListBulletAccessible() { }
|
||||
|
||||
// nsAccessNode
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
virtual ENameValueFlag Name(nsString& aName);
|
||||
virtual a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual void AppendTextTo(nsAString& aText, PRUint32 aStartOffset = 0,
|
||||
PRUint32 aLength = PR_UINT32_MAX);
|
||||
};
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
inline mozilla::a11y::HTMLLIAccessible*
|
||||
nsAccessible::AsHTMLListItem()
|
||||
{
|
||||
return mFlags & eHTMLListItemAccessible ?
|
||||
static_cast<mozilla::a11y::HTMLLIAccessible*>(this) : nsnull;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -52,6 +52,7 @@ LIBXUL_LIBRARY = 1
|
|||
CPPSRCS = \
|
||||
nsHTMLCanvasAccessible.cpp \
|
||||
HTMLFormControlAccessible.cpp \
|
||||
HTMLListAccessible.cpp \
|
||||
nsHTMLImageAccessible.cpp \
|
||||
nsHTMLImageMapAccessible.cpp \
|
||||
nsHTMLLinkAccessible.cpp \
|
||||
|
|
|
@ -105,6 +105,7 @@ public:
|
|||
virtual PRUint64 NativeState();
|
||||
virtual nsAccessible* ChildAtPoint(PRInt32 aX, PRInt32 aY,
|
||||
EWhichChildAtPoint aWhichChild);
|
||||
virtual void GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame);
|
||||
|
||||
// HyperLinkAccessible
|
||||
virtual PRUint32 StartOffset();
|
||||
|
@ -114,7 +115,6 @@ protected:
|
|||
|
||||
// nsAccessible
|
||||
virtual void CacheChildren();
|
||||
virtual void GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -256,22 +256,6 @@ nsHTMLSelectOptionAccessible::GetNameInternal(nsAString& aName)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsAccessible protected
|
||||
nsIFrame* nsHTMLSelectOptionAccessible::GetBoundsFrame()
|
||||
{
|
||||
PRUint64 state = 0;
|
||||
nsIContent* content = GetSelectState(&state);
|
||||
if (state & states::COLLAPSED) {
|
||||
if (content) {
|
||||
return content->GetPrimaryFrame();
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return nsAccessible::GetBoundsFrame();
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsHTMLSelectOptionAccessible::NativeState()
|
||||
{
|
||||
|
@ -348,8 +332,16 @@ nsHTMLSelectOptionAccessible::GetLevelInternal()
|
|||
return level;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLSelectOptionAccessible: nsIAccessible
|
||||
void
|
||||
nsHTMLSelectOptionAccessible::GetBoundsRect(nsRect& aTotalBounds,
|
||||
nsIFrame** aBoundingFrame)
|
||||
{
|
||||
nsAccessible* combobox = GetCombobox();
|
||||
if (combobox && (combobox->State() & states::COLLAPSED))
|
||||
combobox->GetBoundsRect(aTotalBounds, aBoundingFrame);
|
||||
else
|
||||
nsHyperTextAccessibleWrap::GetBoundsRect(aTotalBounds, aBoundingFrame);
|
||||
}
|
||||
|
||||
/** select us! close combo box if necessary*/
|
||||
NS_IMETHODIMP nsHTMLSelectOptionAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
|
||||
|
@ -551,8 +543,6 @@ nsHTMLComboboxAccessible::Shutdown()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
PRUint64
|
||||
nsHTMLComboboxAccessible::NativeState()
|
||||
{
|
||||
|
@ -561,8 +551,7 @@ nsHTMLComboboxAccessible::NativeState()
|
|||
// Get focus status from base class
|
||||
PRUint64 state = nsAccessible::NativeState();
|
||||
|
||||
nsIFrame *frame = GetBoundsFrame();
|
||||
nsIComboboxControlFrame *comboFrame = do_QueryFrame(frame);
|
||||
nsIComboboxControlFrame* comboFrame = do_QueryFrame(GetFrame());
|
||||
if (comboFrame && comboFrame->IsDroppedDown())
|
||||
state |= states::EXPANDED;
|
||||
else
|
||||
|
@ -750,8 +739,7 @@ nsHTMLComboboxListAccessible::NativeState()
|
|||
// Get focus status from base class
|
||||
PRUint64 state = nsAccessible::NativeState();
|
||||
|
||||
nsIFrame *boundsFrame = GetBoundsFrame();
|
||||
nsIComboboxControlFrame* comboFrame = do_QueryFrame(boundsFrame);
|
||||
nsIComboboxControlFrame* comboFrame = do_QueryFrame(mParent->GetFrame());
|
||||
if (comboFrame && comboFrame->IsDroppedDown())
|
||||
state |= states::FLOATING;
|
||||
else
|
||||
|
|
|
@ -122,6 +122,7 @@ public:
|
|||
virtual PRUint64 NativeState();
|
||||
|
||||
virtual PRInt32 GetLevelInternal();
|
||||
virtual void GetBoundsRect(nsRect& aTotalBounds, nsIFrame** aBoundingFrame);
|
||||
|
||||
// ActionAccessible
|
||||
virtual PRUint8 ActionCount();
|
||||
|
@ -129,10 +130,6 @@ public:
|
|||
// Widgets
|
||||
virtual nsAccessible* ContainerWidget() const;
|
||||
|
||||
protected:
|
||||
// nsAccessible
|
||||
virtual nsIFrame* GetBoundsFrame();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
|
@ -141,6 +138,19 @@ private:
|
|||
* @return Select element content, returns null if not avaliable
|
||||
*/
|
||||
nsIContent* GetSelectState(PRUint64* aState);
|
||||
|
||||
/**
|
||||
* Return a combobox accessible the option belongs to if any.
|
||||
*/
|
||||
nsAccessible* GetCombobox() const
|
||||
{
|
||||
if (mParent && mParent->IsListControl()) {
|
||||
nsAccessible* combobox = mParent->Parent();
|
||||
return combobox->IsCombobox() ? combobox : nsnull;
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -41,19 +41,12 @@
|
|||
|
||||
#include "nsDocAccessible.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsIAccessibleRelation.h"
|
||||
#include "nsTextEquivUtils.h"
|
||||
#include "Relation.h"
|
||||
#include "Role.h"
|
||||
#include "States.h"
|
||||
|
||||
#include "nsIAccessibleRelation.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsBlockFrame.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsISelectionController.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -227,198 +220,3 @@ nsHTMLOutputAccessible::GetAttributesInternal(nsIPersistentProperties* aAttribut
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLLIAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsHTMLLIAccessible::
|
||||
nsHTMLLIAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
|
||||
nsHyperTextAccessibleWrap(aContent, aDoc), mBullet(nsnull)
|
||||
{
|
||||
mFlags |= eHTMLListItemAccessible;
|
||||
|
||||
nsBlockFrame* blockFrame = do_QueryFrame(GetFrame());
|
||||
if (blockFrame && blockFrame->HasBullet()) {
|
||||
mBullet = new nsHTMLListBulletAccessible(mContent, mDoc);
|
||||
if (!Document()->BindToDocument(mBullet, nsnull))
|
||||
mBullet = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLLIAccessible, nsHyperTextAccessible)
|
||||
|
||||
void
|
||||
nsHTMLLIAccessible::Shutdown()
|
||||
{
|
||||
mBullet = nsnull;
|
||||
|
||||
nsHyperTextAccessibleWrap::Shutdown();
|
||||
}
|
||||
|
||||
role
|
||||
nsHTMLLIAccessible::NativeRole()
|
||||
{
|
||||
if (mContent->Tag() == nsGkAtoms::dt)
|
||||
return roles::TERM;
|
||||
|
||||
return roles::LISTITEM;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsHTMLLIAccessible::NativeState()
|
||||
{
|
||||
return nsHyperTextAccessibleWrap::NativeState() | states::READONLY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLLIAccessible::GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height)
|
||||
{
|
||||
nsresult rv = nsAccessibleWrap::GetBounds(x, y, width, height);
|
||||
if (NS_FAILED(rv) || !mBullet)
|
||||
return rv;
|
||||
|
||||
PRInt32 bulletX, bulletY, bulletWidth, bulletHeight;
|
||||
rv = mBullet->GetBounds(&bulletX, &bulletY, &bulletWidth, &bulletHeight);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*x = bulletX; // Move x coordinate of list item over to cover bullet as well
|
||||
*width += bulletWidth;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLLIAccessible: public
|
||||
|
||||
void
|
||||
nsHTMLLIAccessible::UpdateBullet(bool aHasBullet)
|
||||
{
|
||||
if (aHasBullet == !!mBullet) {
|
||||
NS_NOTREACHED("Bullet and accessible are in sync already!");
|
||||
return;
|
||||
}
|
||||
|
||||
nsDocAccessible* document = Document();
|
||||
if (aHasBullet) {
|
||||
mBullet = new nsHTMLListBulletAccessible(mContent, mDoc);
|
||||
if (document->BindToDocument(mBullet, nsnull)) {
|
||||
InsertChildAt(0, mBullet);
|
||||
}
|
||||
} else {
|
||||
RemoveChild(mBullet);
|
||||
document->UnbindFromDocument(mBullet);
|
||||
mBullet = nsnull;
|
||||
}
|
||||
|
||||
// XXXtodo: fire show/hide and reorder events. That's hard to make it
|
||||
// right now because coalescence happens by DOM node.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLLIAccessible: nsAccessible protected
|
||||
|
||||
void
|
||||
nsHTMLLIAccessible::CacheChildren()
|
||||
{
|
||||
if (mBullet)
|
||||
AppendChild(mBullet);
|
||||
|
||||
// Cache children from subtree.
|
||||
nsAccessibleWrap::CacheChildren();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLListBulletAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsHTMLListBulletAccessible::
|
||||
nsHTMLListBulletAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
|
||||
nsLeafAccessible(aContent, aDoc)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLListBulletAccessible: nsAccessNode
|
||||
|
||||
bool
|
||||
nsHTMLListBulletAccessible::IsPrimaryForNode() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLListBulletAccessible: nsAccessible
|
||||
|
||||
ENameValueFlag
|
||||
nsHTMLListBulletAccessible::Name(nsString &aName)
|
||||
{
|
||||
aName.Truncate();
|
||||
|
||||
// Native anonymous content, ARIA can't be used. Get list bullet text.
|
||||
nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
|
||||
NS_ASSERTION(blockFrame, "No frame for list item!");
|
||||
if (blockFrame) {
|
||||
blockFrame->GetBulletText(aName);
|
||||
|
||||
// Append space otherwise bullets are jammed up against list text.
|
||||
aName.Append(' ');
|
||||
}
|
||||
|
||||
return eNameOK;
|
||||
}
|
||||
|
||||
role
|
||||
nsHTMLListBulletAccessible::NativeRole()
|
||||
{
|
||||
return roles::STATICTEXT;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsHTMLListBulletAccessible::NativeState()
|
||||
{
|
||||
PRUint64 state = nsLeafAccessible::NativeState();
|
||||
|
||||
state &= ~states::FOCUSABLE;
|
||||
state |= states::READONLY;
|
||||
return state;
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLListBulletAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
|
||||
PRUint32 aLength)
|
||||
{
|
||||
nsAutoString bulletText;
|
||||
nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
|
||||
NS_ASSERTION(blockFrame, "No frame for list item!");
|
||||
if (blockFrame)
|
||||
blockFrame->GetBulletText(bulletText);
|
||||
|
||||
aText.Append(Substring(bulletText, aStartOffset, aLength));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLListAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsHTMLListAccessible::
|
||||
nsHTMLListAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
|
||||
nsHyperTextAccessibleWrap(aContent, aDoc)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLListAccessible, nsHyperTextAccessible)
|
||||
|
||||
role
|
||||
nsHTMLListAccessible::NativeRole()
|
||||
{
|
||||
if (mContent->Tag() == nsGkAtoms::dl)
|
||||
return roles::DEFINITION_LIST;
|
||||
|
||||
return roles::LIST;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsHTMLListAccessible::NativeState()
|
||||
{
|
||||
return nsHyperTextAccessibleWrap::NativeState() | states::READONLY;
|
||||
}
|
||||
|
||||
|
|
|
@ -119,78 +119,4 @@ public:
|
|||
virtual Relation RelationByType(PRUint32 aType);
|
||||
};
|
||||
|
||||
/**
|
||||
* Used for bullet of HTML list item element (for example, HTML li).
|
||||
*/
|
||||
class nsHTMLListBulletAccessible : public nsLeafAccessible
|
||||
{
|
||||
public:
|
||||
nsHTMLListBulletAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
|
||||
|
||||
// nsAccessNode
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
virtual mozilla::a11y::ENameValueFlag Name(nsString& aName);
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual void AppendTextTo(nsAString& aText, PRUint32 aStartOffset = 0,
|
||||
PRUint32 aLength = PR_UINT32_MAX);
|
||||
};
|
||||
|
||||
/**
|
||||
* Used for HTML list (like HTML ul).
|
||||
*/
|
||||
class nsHTMLListAccessible : public nsHyperTextAccessibleWrap
|
||||
{
|
||||
public:
|
||||
nsHTMLListAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsAccessible
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
};
|
||||
|
||||
/**
|
||||
* Used for HTML list item (e.g. HTML li).
|
||||
*/
|
||||
class nsHTMLLIAccessible : public nsHyperTextAccessibleWrap
|
||||
{
|
||||
public:
|
||||
nsHTMLLIAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsAccessNode
|
||||
virtual void Shutdown();
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
|
||||
|
||||
// nsAccessible
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
|
||||
// nsHTMLLIAccessible
|
||||
void UpdateBullet(bool aHasBullet);
|
||||
|
||||
protected:
|
||||
// nsAccessible
|
||||
virtual void CacheChildren();
|
||||
|
||||
private:
|
||||
nsRefPtr<nsHTMLListBulletAccessible> mBullet;
|
||||
};
|
||||
|
||||
inline nsHTMLLIAccessible*
|
||||
nsAccessible::AsHTMLListItem()
|
||||
{
|
||||
return mFlags & eHTMLListItemAccessible ?
|
||||
static_cast<nsHTMLLIAccessible*>(this) : nsnull;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -53,9 +53,8 @@ var AccessFu = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Start the special AccessFu mode, this primarily means controlling the virtual
|
||||
* cursor with arrow keys. Currently, on platforms other than Android this needs
|
||||
* to be called explicitly.
|
||||
* Start AccessFu mode, this primarily means controlling the virtual cursor
|
||||
* with arrow keys.
|
||||
*/
|
||||
enable: function enable() {
|
||||
dump('AccessFu enable');
|
||||
|
@ -72,8 +71,6 @@ var AccessFu = {
|
|||
this.chromeWin.addEventListener('resize', this, true);
|
||||
this.chromeWin.addEventListener('scroll', this, true);
|
||||
this.chromeWin.addEventListener('TabOpen', this, true);
|
||||
this.chromeWin.addEventListener('TabSelect', this, true);
|
||||
this.chromeWin.addEventListener('TabClosed', this, true);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -82,18 +79,16 @@ var AccessFu = {
|
|||
disable: function disable() {
|
||||
dump('AccessFu disable');
|
||||
|
||||
this.presenters.forEach(function(p) {p.detach();});
|
||||
this.presenters.forEach(function(p) { p.detach(); });
|
||||
this.presenters = [];
|
||||
|
||||
VirtualCursorController.detach();
|
||||
|
||||
Services.obs.addObserver(this, 'accessible-event', false);
|
||||
this.chromeWin.removeEventListener('DOMActivate', this);
|
||||
this.chromeWin.removeEventListener('resize', this);
|
||||
this.chromeWin.removeEventListener('scroll', this);
|
||||
this.chromeWin.removeEventListener('TabOpen', this);
|
||||
this.chromeWin.removeEventListener('TabSelect', this);
|
||||
this.chromeWin.removeEventListener('TabClose', this);
|
||||
Services.obs.removeObserver(this, 'accessible-event');
|
||||
this.chromeWin.removeEventListener('DOMActivate', this, true);
|
||||
this.chromeWin.removeEventListener('resize', this, true);
|
||||
this.chromeWin.removeEventListener('scroll', this, true);
|
||||
this.chromeWin.removeEventListener('TabOpen', this, true);
|
||||
},
|
||||
|
||||
amINeeded: function(aPref) {
|
||||
|
@ -125,14 +120,17 @@ var AccessFu = {
|
|||
|
||||
handleEvent: function handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case 'TabSelect':
|
||||
{
|
||||
this.getDocAccessible(
|
||||
function(docAcc) {
|
||||
this.presenters.forEach(function(p) {p.tabSelected(docAcc);});
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'TabOpen':
|
||||
{
|
||||
let browser = aEvent.target.linkedBrowser || aEvent.target;
|
||||
// Store the new browser node. We will need to check later when a new
|
||||
// content document is attached if it has been attached to this new tab.
|
||||
// If it has, than we will need to send a 'loading' message along with
|
||||
// the usual 'newdoc' to presenters.
|
||||
this._pendingDocuments[browser] = true;
|
||||
this.presenters.forEach(function(p) { p.tabStateChanged(null, 'newtab'); });
|
||||
break;
|
||||
}
|
||||
case 'DOMActivate':
|
||||
{
|
||||
let activatedAcc = getAccessible(aEvent.originalTarget);
|
||||
|
@ -153,25 +151,12 @@ var AccessFu = {
|
|||
case 'scroll':
|
||||
case 'resize':
|
||||
{
|
||||
this.presenters.forEach(function(p) {p.viewportChanged();});
|
||||
this.presenters.forEach(function(p) { p.viewportChanged(); });
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getDocAccessible: function getDocAccessible(aCallback) {
|
||||
let browserApp = (Services.appinfo.OS == 'Android') ?
|
||||
this.chromeWin.BrowserApp : this.chromeWin.gBrowser;
|
||||
|
||||
let docAcc = getAccessible(browserApp.selectedBrowser.contentDocument);
|
||||
if (!docAcc) {
|
||||
// Wait for a reorder event fired by the parent of the new doc.
|
||||
this._pendingDocuments[browserApp.selectedBrowser] = aCallback;
|
||||
} else {
|
||||
aCallback.apply(this, [docAcc]);
|
||||
}
|
||||
},
|
||||
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case 'nsPref:changed':
|
||||
|
@ -223,16 +208,86 @@ var AccessFu = {
|
|||
}
|
||||
);
|
||||
}
|
||||
else if (event.state == Ci.nsIAccessibleStates.STATE_BUSY &&
|
||||
!(event.isExtraState()) && event.isEnabled()) {
|
||||
let role = event.accessible.role;
|
||||
if ((role == Ci.nsIAccessibleRole.ROLE_DOCUMENT ||
|
||||
role == Ci.nsIAccessibleRole.ROLE_APPLICATION)) {
|
||||
// An existing document has changed to state "busy", this means
|
||||
// something is loading. Send a 'loading' message to presenters.
|
||||
this.presenters.forEach(
|
||||
function(p) {
|
||||
p.tabStateChanged(event.accessible, 'loading');
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Ci.nsIAccessibleEvent.EVENT_REORDER:
|
||||
{
|
||||
let node = aEvent.accessible.DOMNode;
|
||||
let callback = this._pendingDocuments[node];
|
||||
if (callback && aEvent.accessible.childCount) {
|
||||
// We have a callback associated with a document.
|
||||
callback.apply(this, [aEvent.accessible.getChildAt(0)]);
|
||||
delete this._pendingDocuments[node];
|
||||
let acc = aEvent.accessible;
|
||||
if (acc.childCount) {
|
||||
let docAcc = acc.getChildAt(0);
|
||||
if (this._pendingDocuments[aEvent.DOMNode]) {
|
||||
// This is a document in a new tab. Check if it is
|
||||
// in a BUSY state (i.e. loading), and inform presenters.
|
||||
// We need to do this because a state change event will not be
|
||||
// fired when an object is created with the BUSY state.
|
||||
// If this is not a new tab, don't bother because we sent 'loading'
|
||||
// when the previous doc changed its state to BUSY.
|
||||
let state = {};
|
||||
docAcc.getState(state, {});
|
||||
if (state.value & Ci.nsIAccessibleStates.STATE_BUSY &&
|
||||
this.isNotChromeDoc(docAcc))
|
||||
this.presenters.forEach(
|
||||
function(p) { p.tabStateChanged(docAcc, 'loading'); }
|
||||
);
|
||||
delete this._pendingDocuments[aEvent.DOMNode];
|
||||
}
|
||||
if (this.isBrowserDoc(docAcc))
|
||||
// A new top-level content document has been attached
|
||||
this.presenters.forEach(
|
||||
function(p) { p.tabStateChanged(docAcc, 'newdoc'); }
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Ci.nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_COMPLETE:
|
||||
{
|
||||
if (this.isNotChromeDoc(aEvent.accessible)) {
|
||||
this.presenters.forEach(
|
||||
function(p) {
|
||||
p.tabStateChanged(aEvent.accessible, 'loaded');
|
||||
}
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Ci.nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_STOPPED:
|
||||
{
|
||||
this.presenters.forEach(
|
||||
function(p) {
|
||||
p.tabStateChanged(aEvent.accessible, 'loadstopped');
|
||||
}
|
||||
);
|
||||
break;
|
||||
}
|
||||
case Ci.nsIAccessibleEvent.EVENT_DOCUMENT_RELOAD:
|
||||
{
|
||||
this.presenters.forEach(
|
||||
function(p) {
|
||||
p.tabStateChanged(aEvent.accessible, 'reload');
|
||||
}
|
||||
);
|
||||
break;
|
||||
}
|
||||
case Ci.nsIAccessibleEvent.EVENT_FOCUS:
|
||||
{
|
||||
if (this.isBrowserDoc(aEvent.accessible)) {
|
||||
// The document recieved focus, call tabSelected to present current tab.
|
||||
this.presenters.forEach(
|
||||
function(p) { p.tabSelected(aEvent.accessible); });
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -269,6 +324,38 @@ var AccessFu = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if accessible is a top-level content document (i.e. a child of a XUL
|
||||
* browser node).
|
||||
* @param {nsIAccessible} aDocAcc the accessible to check.
|
||||
* @return {boolean} true if this is a top-level content document.
|
||||
*/
|
||||
isBrowserDoc: function isBrowserDoc(aDocAcc) {
|
||||
let parent = aDocAcc.parent;
|
||||
if (!parent)
|
||||
return false;
|
||||
|
||||
let domNode = parent.DOMNode;
|
||||
if (!domNode)
|
||||
return false;
|
||||
|
||||
const ns = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
|
||||
return (domNode.localName == 'browser' && domNode.namespaceURI == ns);
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if document is not a local "chrome" document, like about:home.
|
||||
* @param {nsIDOMDocument} aDocument the document to check.
|
||||
* @return {boolean} true if this is not a chrome document.
|
||||
*/
|
||||
isNotChromeDoc: function isNotChromeDoc(aDocument) {
|
||||
let location = aDocument.DOMNode.location;
|
||||
if (!location)
|
||||
return false;
|
||||
|
||||
return location.protocol != "about:";
|
||||
},
|
||||
|
||||
getNewContext: function getNewContext(aOldObject, aNewObject) {
|
||||
let newLineage = [];
|
||||
let oldLineage = [];
|
||||
|
|
|
@ -66,15 +66,21 @@ Presenter.prototype = {
|
|||
selectionChanged: function selectionChanged(aObject) {},
|
||||
|
||||
/**
|
||||
* The page state has changed, loading, stopped loading, etc. TODO.
|
||||
* The tab, or the tab's document state has changed.
|
||||
* @param {nsIAccessible} aDocObj the tab document accessible that has had its
|
||||
* state changed, or null if the tab has no associated document yet.
|
||||
* @param {string} aPageState the state name for the tab, valid states are:
|
||||
* 'newtab', 'loading', 'newdoc', 'loaded', 'stopped', and 'reload'.
|
||||
*/
|
||||
pageStateChanged: function pageStateChanged() {},
|
||||
tabStateChanged: function tabStateChanged(aDocObj, aPageState) {},
|
||||
|
||||
/**
|
||||
* The tab has changed.
|
||||
* @param {nsIAccessible} aObject the document contained in the tab.
|
||||
* The current tab has changed.
|
||||
* @param {nsIAccessible} aObject the document contained by the tab
|
||||
* accessible, or null if it is a new tab with no attached
|
||||
* document yet.
|
||||
*/
|
||||
tabSelected: function tabSelected(aObject) {},
|
||||
tabSelected: function tabSelected(aDocObj) {},
|
||||
|
||||
/**
|
||||
* The viewport has changed, either a scroll, pan, zoom, or
|
||||
|
@ -147,9 +153,17 @@ VisualPresenter.prototype.pivotChanged = function(aObject, aNewContext) {
|
|||
}
|
||||
};
|
||||
|
||||
VisualPresenter.prototype.tabSelected = function(aObject) {
|
||||
let vcDoc = aObject.QueryInterface(Ci.nsIAccessibleCursorable);
|
||||
this.pivotChanged(vcDoc.virtualCursor.position);
|
||||
VisualPresenter.prototype.tabSelected = function(aDocObj) {
|
||||
let vcPos = aDocObj ?
|
||||
aDocObj.QueryInterface(Ci.nsIAccessibleCursorable).virtualCursor.position :
|
||||
null;
|
||||
|
||||
this.pivotChanged(vcPos);
|
||||
};
|
||||
|
||||
VisualPresenter.prototype.tabStateChanged = function(aDocObj, aPageState) {
|
||||
if (aPageState == "newdoc")
|
||||
this.pivotChanged(null);
|
||||
};
|
||||
|
||||
// Internals
|
||||
|
@ -242,16 +256,40 @@ AndroidPresenter.prototype.actionInvoked = function(aObject, aActionName) {
|
|||
});
|
||||
};
|
||||
|
||||
AndroidPresenter.prototype.tabSelected = function(aObject) {
|
||||
let vcDoc = aObject.QueryInterface(Ci.nsIAccessibleCursorable);
|
||||
AndroidPresenter.prototype.tabSelected = function(aDocObj) {
|
||||
// Send a pivot change message with the full context utterance for this doc.
|
||||
let vcDoc = aDocObj.QueryInterface(Ci.nsIAccessibleCursorable);
|
||||
let context = [];
|
||||
|
||||
let parent = vcDoc.virtualCursor.position || aObject;
|
||||
while ((parent = parent.parent))
|
||||
let parent = vcDoc.virtualCursor.position || aDocObj;
|
||||
while ((parent = parent.parent)) {
|
||||
context.push(parent);
|
||||
if (parent == aDocObj)
|
||||
break;
|
||||
}
|
||||
|
||||
context.reverse();
|
||||
|
||||
this.pivotChanged(vcDoc.virtualCursor.position || aObject, context);
|
||||
this.pivotChanged(vcDoc.virtualCursor.position || aDocObj, context);
|
||||
};
|
||||
|
||||
AndroidPresenter.prototype.tabStateChanged = function(aDocObj, aPageState) {
|
||||
let stateUtterance = UtteranceGenerator.
|
||||
genForTabStateChange(aDocObj, aPageState);
|
||||
|
||||
if (!stateUtterance.length)
|
||||
return;
|
||||
|
||||
this.sendMessageToJava({
|
||||
gecko: {
|
||||
type: 'Accessibility:Event',
|
||||
eventType: ANDROID_TYPE_VIEW_TEXT_CHANGED,
|
||||
text: stateUtterance,
|
||||
addedCount: stateUtterance.join(' ').length,
|
||||
removedCount: 0,
|
||||
fromIndex: 0
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
AndroidPresenter.prototype.textChanged = function(aIsInserted, aStart, aLength, aText, aModifiedText) {
|
||||
|
|
|
@ -22,6 +22,22 @@ var gAccRetrieval = Cc['@mozilla.org/accessibleRetrieval;1'].
|
|||
|
||||
var EXPORTED_SYMBOLS = ['UtteranceGenerator'];
|
||||
|
||||
/**
|
||||
* Generates speech utterances from objects, actions and state changes.
|
||||
* An utterance is an array of strings.
|
||||
*
|
||||
* It should not be assumed that flattening an utterance array would create a
|
||||
* gramatically correct sentence. For example, {@link genForObject} might
|
||||
* return: ['graphic', 'Welcome to my home page'].
|
||||
* Each string element in an utterance should be gramatically correct in itself.
|
||||
* Another example from {@link genForObject}: ['list item 2 of 5', 'Alabama'].
|
||||
*
|
||||
* An utterance is ordered from the least to the most important. Speaking the
|
||||
* last string usually makes sense, but speaking the first often won't.
|
||||
* For example {@link genForAction} might return ['button', 'clicked'] for a
|
||||
* clicked event. Speaking only 'clicked' makes sense. Speaking 'button' does
|
||||
* not.
|
||||
*/
|
||||
var UtteranceGenerator = {
|
||||
gActionMap: {
|
||||
jump: 'jumpAction',
|
||||
|
@ -39,6 +55,19 @@ var UtteranceGenerator = {
|
|||
cycle: 'cycleAction'
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Generates an utterance for an object.
|
||||
* @param {nsIAccessible} aAccessible accessible object to generate utterance
|
||||
* for.
|
||||
* @param {boolean} aForceName include the object's name in the utterance
|
||||
* even if this object type does not usually have it's name uttered.
|
||||
* @return {Array} Two string array. The first string describes the object
|
||||
* and its states. The second string is the object's name. Some object
|
||||
* types may have the description or name omitted, instead an empty string
|
||||
* is returned as a placeholder. Whether the object's description or it's role
|
||||
* is included is determined by {@link verbosityRoleMap}.
|
||||
*/
|
||||
genForObject: function(aAccessible, aForceName) {
|
||||
let roleString = gAccRetrieval.getStringRole(aAccessible.role);
|
||||
|
||||
|
@ -53,10 +82,45 @@ var UtteranceGenerator = {
|
|||
return func.apply(this, [aAccessible, roleString, flags]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Generates an utterance for an action performed.
|
||||
* TODO: May become more verbose in the future.
|
||||
* @param {nsIAccessible} aAccessible accessible object that the action was
|
||||
* invoked in.
|
||||
* @param {string} aActionName the name of the action, one of the keys in
|
||||
* {@link gActionMap}.
|
||||
* @return {Array} A one string array with the action.
|
||||
*/
|
||||
genForAction: function(aObject, aActionName) {
|
||||
return [gStringBundle.GetStringFromName(this.gActionMap[aActionName])];
|
||||
},
|
||||
|
||||
/**
|
||||
* Generates an utterance for a tab state change.
|
||||
* @param {nsIAccessible} aAccessible accessible object of the tab's attached
|
||||
* document.
|
||||
* @param {string} aTabState the tab state name, see
|
||||
* {@link Presenter.tabStateChanged}.
|
||||
* @return {Array} The tab state utterace.
|
||||
*/
|
||||
genForTabStateChange: function (aObject, aTabState) {
|
||||
switch (aTabState) {
|
||||
case 'newtab':
|
||||
return [gStringBundle.GetStringFromName('tabNew')];
|
||||
case 'loading':
|
||||
return [gStringBundle.GetStringFromName('tabLoading')];
|
||||
case 'loaded':
|
||||
return [aObject.name || '',
|
||||
gStringBundle.GetStringFromName('tabLoaded')];
|
||||
case 'loadstopped':
|
||||
return [gStringBundle.GetStringFromName('tabLoadStopped')];
|
||||
case 'reload':
|
||||
return [gStringBundle.GetStringFromName('tabReload')];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
verbosityRoleMap: {
|
||||
'menubar': INCLUDE_ROLE,
|
||||
'scrollbar': INCLUDE_ROLE,
|
||||
|
@ -115,35 +179,45 @@ var UtteranceGenerator = {
|
|||
let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
|
||||
let desc = (aFlags & INCLUDE_ROLE) ? this._getLocalizedRole(aRoleStr) : '';
|
||||
|
||||
if (!name && !desc)
|
||||
return [];
|
||||
let utterance = [];
|
||||
|
||||
let state = {};
|
||||
let extState = {};
|
||||
aAccessible.getState(state, extState);
|
||||
if (desc) {
|
||||
let state = {};
|
||||
let extState = {};
|
||||
aAccessible.getState(state, extState);
|
||||
|
||||
if (state.value & Ci.nsIAccessibleStates.STATE_CHECKABLE) {
|
||||
let stateStr = (state.value & Ci.nsIAccessibleStates.STATE_CHECKED) ?
|
||||
'objChecked' : 'objNotChecked';
|
||||
desc = gStringBundle.formatStringFromName(stateStr, [desc], 1);
|
||||
if (state.value & Ci.nsIAccessibleStates.STATE_CHECKABLE) {
|
||||
let stateStr = (state.value & Ci.nsIAccessibleStates.STATE_CHECKED) ?
|
||||
'objChecked' : 'objNotChecked';
|
||||
desc = gStringBundle.formatStringFromName(stateStr, [desc], 1);
|
||||
}
|
||||
|
||||
if (extState.value & Ci.nsIAccessibleStates.EXT_STATE_EXPANDABLE) {
|
||||
let stateStr = (state.value & Ci.nsIAccessibleStates.STATE_EXPANDED) ?
|
||||
'objExpanded' : 'objCollapsed';
|
||||
desc = gStringBundle.formatStringFromName(stateStr, [desc], 1);
|
||||
}
|
||||
|
||||
utterance.push(desc);
|
||||
}
|
||||
|
||||
if (extState.value & Ci.nsIAccessibleStates.EXT_STATE_EXPANDABLE) {
|
||||
let stateStr = (state.value & Ci.nsIAccessibleStates.STATE_EXPANDED) ?
|
||||
'objExpanded' : 'objCollapsed';
|
||||
desc = gStringBundle.formatStringFromName(stateStr, [desc], 1);
|
||||
}
|
||||
if (name)
|
||||
utterance.push(name);
|
||||
|
||||
return [desc, name];
|
||||
return utterance;
|
||||
},
|
||||
|
||||
heading: function(aAccessible, aRoleStr, aFlags) {
|
||||
let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
|
||||
let level = {};
|
||||
aAccessible.groupPosition(level, {}, {});
|
||||
let desc = gStringBundle.formatStringFromName('headingLevel',
|
||||
[level.value], 1);
|
||||
return [desc, name];
|
||||
let utterance =
|
||||
[gStringBundle.formatStringFromName('headingLevel', [level.value], 1)];
|
||||
|
||||
if (name)
|
||||
utterance.push(name);
|
||||
|
||||
return utterance;
|
||||
},
|
||||
|
||||
listitem: function(aAccessible, aRoleStr, aFlags) {
|
||||
|
@ -152,10 +226,14 @@ var UtteranceGenerator = {
|
|||
let itemno = {};
|
||||
let itemof = {};
|
||||
aAccessible.groupPosition({}, itemof, itemno);
|
||||
let desc = gStringBundle.formatStringFromName(
|
||||
'objItemOf', [localizedRole, itemno.value, itemof.value], 3);
|
||||
let utterance =
|
||||
[gStringBundle.formatStringFromName(
|
||||
'objItemOf', [localizedRole, itemno.value, itemof.value], 3)];
|
||||
|
||||
return [desc, name];
|
||||
if (name)
|
||||
utterance.push(name);
|
||||
|
||||
return utterance;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ var VirtualCursorController = {
|
|||
},
|
||||
|
||||
detach: function detach() {
|
||||
this.chromeWin.document.removeEventListener('keypress', this.onkeypress);
|
||||
this.chromeWin.document.removeEventListener('keypress', this.onkeypress, true);
|
||||
},
|
||||
|
||||
getBrowserApp: function getBrowserApp() {
|
||||
|
@ -114,38 +114,67 @@ var VirtualCursorController = {
|
|||
|
||||
SimpleTraversalRule: {
|
||||
getMatchRoles: function(aRules) {
|
||||
aRules.value = [];
|
||||
return 0;
|
||||
aRules.value = this._matchRoles;
|
||||
return this._matchRoles.length;
|
||||
},
|
||||
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function(aAccessible) {
|
||||
if (aAccessible.childCount)
|
||||
// Non-leafs do not interest us.
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
|
||||
// XXX: Find a better solution for ROLE_STATICTEXT.
|
||||
// It allows to filter list bullets but the same time it
|
||||
// filters CSS generated content too as unwanted side effect.
|
||||
let ignoreRoles = [Ci.nsIAccessibleRole.ROLE_WHITESPACE,
|
||||
Ci.nsIAccessibleRole.ROLE_STATICTEXT];
|
||||
|
||||
if (ignoreRoles.indexOf(aAccessible.role) < 0) {
|
||||
let name = aAccessible.name;
|
||||
if (name && name.trim())
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
}
|
||||
|
||||
let state = {};
|
||||
aAccessible.getState(state, {});
|
||||
if (state.value & Ci.nsIAccessibleStates.STATE_FOCUSABLE)
|
||||
switch (aAccessible.role) {
|
||||
case Ci.nsIAccessibleRole.ROLE_COMBOBOX:
|
||||
// We don't want to ignore the subtree because this is often
|
||||
// where the list box hangs out.
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
case Ci.nsIAccessibleRole.ROLE_TEXT_LEAF:
|
||||
{
|
||||
// Nameless text leaves are boring, skip them.
|
||||
let name = aAccessible.name;
|
||||
if (name && name.trim())
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
else
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
}
|
||||
case Ci.nsIAccessibleRole.ROLE_LINK:
|
||||
// If the link has children we should land on them instead.
|
||||
// Image map links don't have children so we need to match those.
|
||||
if (aAccessible.childCount == 0)
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
else
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
default:
|
||||
// Ignore the subtree, if there is one. So that we don't land on
|
||||
// the same content that was already presented by its parent.
|
||||
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH |
|
||||
Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule]),
|
||||
|
||||
_matchRoles: [
|
||||
Ci.nsIAccessibleRole.ROLE_MENUITEM,
|
||||
Ci.nsIAccessibleRole.ROLE_LINK,
|
||||
Ci.nsIAccessibleRole.ROLE_PAGETAB,
|
||||
Ci.nsIAccessibleRole.ROLE_GRAPHIC,
|
||||
// XXX: Find a better solution for ROLE_STATICTEXT.
|
||||
// It allows to filter list bullets but at the same time it
|
||||
// filters CSS generated content too as an unwanted side effect.
|
||||
// Ci.nsIAccessibleRole.ROLE_STATICTEXT,
|
||||
Ci.nsIAccessibleRole.ROLE_TEXT_LEAF,
|
||||
Ci.nsIAccessibleRole.ROLE_PUSHBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_CHECKBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_RADIOBUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_COMBOBOX,
|
||||
Ci.nsIAccessibleRole.ROLE_PROGRESSBAR,
|
||||
Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWN,
|
||||
Ci.nsIAccessibleRole.ROLE_BUTTONMENU,
|
||||
Ci.nsIAccessibleRole.ROLE_CHECK_MENU_ITEM,
|
||||
Ci.nsIAccessibleRole.ROLE_PASSWORD_TEXT,
|
||||
Ci.nsIAccessibleRole.ROLE_RADIO_MENU_ITEM,
|
||||
Ci.nsIAccessibleRole.ROLE_TOGGLE_BUTTON,
|
||||
Ci.nsIAccessibleRole.ROLE_ENTRY
|
||||
]
|
||||
}
|
||||
};
|
||||
|
|
|
@ -453,7 +453,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
|
||||
- (NSString*)role
|
||||
{
|
||||
#ifdef DEBUG_A11Y
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(mGeckoAccessible),
|
||||
"Does not support nsIAccessibleText when it should");
|
||||
#endif
|
||||
|
|
|
@ -372,7 +372,7 @@ __try {
|
|||
if (xpAccessible->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
#ifdef DEBUG_A11Y
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(xpAccessible),
|
||||
"Does not support nsIAccessibleText when it should");
|
||||
#endif
|
||||
|
@ -1670,7 +1670,7 @@ nsAccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
|
|||
aid->ToUTF8String(id);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_A11Y
|
||||
#ifdef DEBUG
|
||||
printf("\n\nMSAA event: event: %d, target: %s@id='%s', childid: %d, hwnd: %d\n\n",
|
||||
eventType, NS_ConvertUTF16toUTF8(tag).get(), id.get(),
|
||||
childID, hWnd);
|
||||
|
|
|
@ -463,23 +463,19 @@ nsXULMenupopupAccessible::NativeState()
|
|||
{
|
||||
PRUint64 state = nsAccessible::NativeState();
|
||||
|
||||
#ifdef DEBUG_A11Y
|
||||
#ifdef DEBUG
|
||||
// We are onscreen if our parent is active
|
||||
bool isActive = mContent->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::menuactive);
|
||||
bool isActive = mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::menuactive);
|
||||
if (!isActive) {
|
||||
nsAccessible* parent = Parent();
|
||||
if (!parent)
|
||||
return state;
|
||||
|
||||
nsIContent *parentContent = parnet->GetContent();
|
||||
NS_ENSURE_TRUE(parentContent, state);
|
||||
|
||||
isActive = parentContent->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::open);
|
||||
if (parent) {
|
||||
nsIContent* parentContent = parent->GetContent();
|
||||
if (parentContent)
|
||||
isActive = parentContent->HasAttr(kNameSpaceID_None, nsGkAtoms::open);
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(isActive || states & states::INVISIBLE,
|
||||
NS_ASSERTION(isActive || (state & states::INVISIBLE),
|
||||
"XULMenupopup doesn't have INVISIBLE when it's inactive");
|
||||
#endif
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ nsXULTabAccessible::RelationByType(PRUint32 aType)
|
|||
return rel;
|
||||
|
||||
nsCOMPtr<nsIContent> tabpanelContent(do_QueryInterface(tabpanelNode));
|
||||
rel.AppendTarget(tabpanelContent);
|
||||
rel.AppendTarget(mDoc, tabpanelContent);
|
||||
return rel;
|
||||
}
|
||||
|
||||
|
@ -254,6 +254,6 @@ nsXULTabpanelAccessible::RelationByType(PRUint32 aType)
|
|||
return rel;
|
||||
|
||||
nsCOMPtr<nsIContent> tabContent(do_QueryInterface(tabNode));
|
||||
rel.AppendTarget(tabContent);
|
||||
rel.AppendTarget(mDoc, tabContent);
|
||||
return rel;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ include $(DEPTH)/config/autoconf.mk
|
|||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES =\
|
||||
test_select.html \
|
||||
test_zoom.html \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Accessible boundaries when page is zoomed</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<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="../role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../layout.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function openComboboxNCheckBounds(aID)
|
||||
{
|
||||
this.combobox = getAccessible(aID);
|
||||
this.comboboxList = this.combobox.firstChild;
|
||||
this.comboboxOption = this.comboboxList.firstChild;
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_FOCUS, this.comboboxOption)
|
||||
];
|
||||
|
||||
this.invoke = function openComboboxNCheckBounds_invoke()
|
||||
{
|
||||
getNode(aID).focus();
|
||||
synthesizeKey("VK_DOWN", { altKey: true });
|
||||
}
|
||||
|
||||
this.finalCheck = function openComboboxNCheckBounds_invoke()
|
||||
{
|
||||
testBounds(this.comboboxOption);
|
||||
}
|
||||
|
||||
this.getID = function openComboboxNCheckBounds_getID()
|
||||
{
|
||||
return "open combobox and test boundaries";
|
||||
}
|
||||
}
|
||||
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
function doTest()
|
||||
{
|
||||
// Combobox
|
||||
testBounds("combobox");
|
||||
|
||||
// Option boundaries matches to combobox boundaries when collapsed.
|
||||
var selectBounds = getBoundsForDOMElm("combobox");
|
||||
testBounds("option1", selectBounds);
|
||||
|
||||
// Open combobox and test option boundaries.
|
||||
gQueue = new eventQueue();
|
||||
gQueue.push(new openComboboxNCheckBounds("combobox"));
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<select id="combobox">
|
||||
<option id="option1">item1</option>
|
||||
<option>item2</option>
|
||||
</select>
|
||||
</body>
|
||||
</html>
|
|
@ -94,10 +94,10 @@ function getChildAtPoint(aIdentifier, aX, aY, aFindDeepestChild)
|
|||
/**
|
||||
* Test the accessible boundaries.
|
||||
*/
|
||||
function testBounds(aID)
|
||||
function testBounds(aID, aRect)
|
||||
{
|
||||
var [expectedX, expectedY, expectedWidth, expectedHeight] =
|
||||
getBoundsForDOMElm(aID);
|
||||
(aRect != undefined) ? aRect : getBoundsForDOMElm(aID);
|
||||
|
||||
var [x, y, width, height] = getBounds(aID);
|
||||
is(x, expectedX, "Wrong x coordinate of " + prettyName(aID));
|
||||
|
@ -166,6 +166,9 @@ function CSSToDevicePixels(aWindow, aX, aY, aWidth, aHeight)
|
|||
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
|
||||
var ratio = winUtil.screenPixelsPerCSSPixel;
|
||||
return [aX * ratio, aY * ratio, aWidth * ratio, aHeight * ratio];
|
||||
}
|
||||
|
||||
// CSS pixels and ratio can be not integer. Device pixels are always integer.
|
||||
// Do our best and hope it works.
|
||||
return [ Math.round(aX * ratio), Math.round(aY * ratio),
|
||||
Math.round(aWidth * ratio), Math.round(aHeight * ratio) ];
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ const STATE_COLLAPSED = nsIAccessibleStates.STATE_COLLAPSED;
|
|||
const STATE_DEFAULT = nsIAccessibleStates.STATE_DEFAULT;
|
||||
const STATE_EXPANDED = nsIAccessibleStates.STATE_EXPANDED;
|
||||
const STATE_EXTSELECTABLE = nsIAccessibleStates.STATE_EXTSELECTABLE;
|
||||
const STATE_FLOATING = nsIAccessibleStates.STATE_FLOATING;
|
||||
const STATE_FOCUSABLE = nsIAccessibleStates.STATE_FOCUSABLE;
|
||||
const STATE_FOCUSED = nsIAccessibleStates.STATE_FOCUSED;
|
||||
const STATE_HASPOPUP = nsIAccessibleStates.STATE_HASPOPUP;
|
||||
|
|
|
@ -7,14 +7,53 @@
|
|||
|
||||
<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="../role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../states.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function openComboboxNCheckStates(aID)
|
||||
{
|
||||
this.combobox = getAccessible(aID);
|
||||
this.comboboxList = this.combobox.firstChild;
|
||||
this.comboboxOption = this.comboboxList.firstChild;
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_FOCUS, this.comboboxOption)
|
||||
];
|
||||
|
||||
this.invoke = function openComboboxNCheckStates_invoke()
|
||||
{
|
||||
getNode(aID).focus();
|
||||
synthesizeKey("VK_DOWN", { altKey: true });
|
||||
}
|
||||
|
||||
this.finalCheck = function openComboboxNCheckStates_invoke()
|
||||
{
|
||||
// Expanded state on combobox.
|
||||
testStates(this.combobox, STATE_EXPANDED);
|
||||
|
||||
// Floating state on combobox list.
|
||||
testStates(this.comboboxList, STATE_FLOATING);
|
||||
}
|
||||
|
||||
this.getID = function openComboboxNCheckStates_getID()
|
||||
{
|
||||
return "open combobox and test states";
|
||||
}
|
||||
}
|
||||
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
var gQueue = null;
|
||||
function doTest()
|
||||
{
|
||||
// combobox
|
||||
|
@ -24,7 +63,7 @@
|
|||
STATE_FOCUSED, 0);
|
||||
|
||||
var comboboxList = combobox.firstChild;
|
||||
testStates(comboboxList, 0, 0, STATE_FOCUSABLE, 0);
|
||||
testStates(comboboxList, STATE_INVISIBLE, 0, STATE_FOCUSABLE, 0);
|
||||
|
||||
var opt1 = comboboxList.firstChild;
|
||||
testStates(opt1, STATE_SELECTABLE | STATE_SELECTED | STATE_FOCUSABLE,
|
||||
|
@ -46,7 +85,10 @@
|
|||
STATE_SELECTED | STATE_FOCUSED | STATE_FOCUSED,
|
||||
0, 0, EXT_STATE_ACTIVE);
|
||||
|
||||
SimpleTest.finish();
|
||||
// open combobox
|
||||
gQueue = new eventQueue();
|
||||
gQueue.push(new openComboboxNCheckStates("combobox"));
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
|
|
@ -503,3 +503,12 @@ pref("app.update.download.backgroundInterval", 0);
|
|||
// field.
|
||||
pref("app.update.log", true);
|
||||
#endif
|
||||
|
||||
// Extensions preferences
|
||||
pref("extensions.update.enabled", false);
|
||||
pref("extensions.getAddons.cache.enabled", false);
|
||||
|
||||
// Context Menu
|
||||
pref("ui.click_hold_context_menus", true);
|
||||
pref("ui.click_hold_context_menus.delay", 1000);
|
||||
|
||||
|
|
|
@ -14,36 +14,31 @@ Cu.import('resource://gre/modules/Services.jsm');
|
|||
Cu.import('resource://gre/modules/ContactService.jsm');
|
||||
Cu.import('resource://gre/modules/Webapps.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyGetter(Services, 'env', function() {
|
||||
return Cc['@mozilla.org/process/environment;1']
|
||||
.getService(Ci.nsIEnvironment);
|
||||
});
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, 'env',
|
||||
'@mozilla.org/process/environment;1',
|
||||
'nsIEnvironment');
|
||||
|
||||
XPCOMUtils.defineLazyGetter(Services, 'ss', function() {
|
||||
return Cc['@mozilla.org/content/style-sheet-service;1']
|
||||
.getService(Ci.nsIStyleSheetService);
|
||||
});
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, 'ss',
|
||||
'@mozilla.org/content/style-sheet-service;1',
|
||||
'nsIStyleSheetService');
|
||||
|
||||
XPCOMUtils.defineLazyGetter(Services, 'idle', function() {
|
||||
return Cc['@mozilla.org/widget/idleservice;1']
|
||||
.getService(Ci.nsIIdleService);
|
||||
});
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, 'idle',
|
||||
'@mozilla.org/widget/idleservice;1',
|
||||
'nsIIdleService');
|
||||
|
||||
XPCOMUtils.defineLazyGetter(Services, 'audioManager', function() {
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
return Cc['@mozilla.org/telephony/audiomanager;1']
|
||||
.getService(Ci.nsIAudioManager);
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, 'audioManager',
|
||||
'@mozilla.org/telephony/audiomanager;1',
|
||||
'nsIAudioManager');
|
||||
#else
|
||||
return {
|
||||
"masterVolume": 0
|
||||
};
|
||||
Services.audioManager = {
|
||||
'masterVolume': 0
|
||||
};
|
||||
#endif
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, 'fm', function() {
|
||||
return Cc['@mozilla.org/focus-manager;1']
|
||||
.getService(Ci.nsFocusManager);
|
||||
});
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, 'fm',
|
||||
'@mozilla.org/focus-manager;1',
|
||||
'nsIFocusManager');
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'DebuggerServer', function() {
|
||||
Cu.import('resource://gre/modules/devtools/dbg-server.jsm');
|
||||
|
@ -144,9 +139,20 @@ var shell = {
|
|||
},
|
||||
|
||||
stop: function shell_stop() {
|
||||
['keydown', 'keypress', 'keyup'].forEach((function unlistenKey(type) {
|
||||
window.removeEventListener(type, this, false, true);
|
||||
window.removeEventListener(type, this, true, true);
|
||||
}).bind(this));
|
||||
|
||||
window.addEventListener('MozApplicationManifest', this);
|
||||
window.removeEventListener('MozApplicationManifest', this);
|
||||
window.removeEventListener('mozfullscreenchange', this);
|
||||
window.removeEventListener('sizemodechange', this);
|
||||
this.contentBrowser.removeEventListener('load', this, true);
|
||||
|
||||
#ifndef MOZ_WIDGET_GONK
|
||||
delete Services.audioManager;
|
||||
#endif
|
||||
},
|
||||
|
||||
toggleDebug: function shell_toggleDebug() {
|
||||
|
@ -301,118 +307,6 @@ var shell = {
|
|||
}
|
||||
};
|
||||
|
||||
(function PowerManager() {
|
||||
// This will eventually be moved to content, so use content API as
|
||||
// much as possible here. TODO: Bug 738530
|
||||
let power = navigator.mozPower;
|
||||
let idleHandler = function idleHandler(subject, topic, time) {
|
||||
if (topic === "idle") {
|
||||
if (power.getWakeLockState("screen") != "locked-foreground") {
|
||||
navigator.mozPower.screenEnabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let wakeLockHandler = function wakeLockHandler(topic, state) {
|
||||
// Turn off the screen when no one needs the it or all of them are
|
||||
// invisible, otherwise turn the screen on. Note that the CPU
|
||||
// might go to sleep as soon as the screen is turned off and
|
||||
// acquiring wake lock will not bring it back (actually the code
|
||||
// is not executed at all).
|
||||
if (topic == "screen") {
|
||||
if (state != "locked-foreground") {
|
||||
if (Services.idle.idleTime > idleTimeout*1000) {
|
||||
navigator.mozPower.screenEnabled = false;
|
||||
}
|
||||
} else {
|
||||
navigator.mozPower.screenEnabled = true;
|
||||
}
|
||||
}
|
||||
if (topic == "cpu") {
|
||||
navigator.mozPower.cpuSleepAllowed = (state != "locked-foreground" &&
|
||||
state != "locked-background");
|
||||
}
|
||||
}
|
||||
|
||||
let idleTimeout = Services.prefs.getIntPref("power.screen.timeout");
|
||||
if (!('mozSettings' in navigator))
|
||||
return;
|
||||
|
||||
let request = navigator.mozSettings.getLock().get("power.screen.timeout");
|
||||
request.onsuccess = function onSuccess() {
|
||||
idleTimeout = request.result["power.screen.timeout"] || idleTimeout;
|
||||
if (idleTimeout) {
|
||||
Services.idle.addIdleObserver(idleHandler, idleTimeout);
|
||||
power.addWakeLockListener(wakeLockHandler);
|
||||
}
|
||||
};
|
||||
|
||||
request.onerror = function onError() {
|
||||
if (idleTimeout) {
|
||||
Services.idle.addIdleObserver(idleHandler, idleTimeout);
|
||||
power.addWakeLockListener(wakeLockHandler);
|
||||
}
|
||||
};
|
||||
|
||||
// XXX We may override other's callback here, but this is the only
|
||||
// user of mozSettings in shell.js at this moment.
|
||||
navigator.mozSettings.onsettingchange = function onSettingChange(e) {
|
||||
if (e.settingName == "power.screen.timeout" && e.settingValue) {
|
||||
Services.idle.removeIdleObserver(idleHandler, idleTimeout);
|
||||
idleTimeout = e.settingValue;
|
||||
Services.idle.addIdleObserver(idleHandler, idleTimeout);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
const DATA_CALL_SETTING_BOLKEYS = ["ril.data.enabled",
|
||||
"ril.data.roaming.enabled"];
|
||||
const DATA_CALL_SETTING_CHARKEYS = ["ril.data.apn",
|
||||
"ril.data.user",
|
||||
"ril.data.passwd"];
|
||||
(function DataCallSettings() {
|
||||
let sm = navigator.mozSettings;
|
||||
let lock = sm.getLock();
|
||||
DATA_CALL_SETTING_BOLKEYS.forEach(function(key) {
|
||||
let request = lock.get(key);
|
||||
request.onsuccess = function onSuccess() {
|
||||
let value = request.result[key] || false;
|
||||
Services.prefs.setBoolPref(key, value);
|
||||
dump("DataCallSettings - " + key + ":" + value);
|
||||
};
|
||||
request.onerror = function onError() {
|
||||
Services.prefs.setBoolPref(key, false);
|
||||
};
|
||||
});
|
||||
|
||||
DATA_CALL_SETTING_CHARKEYS.forEach(function(key) {
|
||||
let request = lock.get(key);
|
||||
request.onsuccess = function onSuccess() {
|
||||
let value = request.result[key] || "";
|
||||
Services.prefs.setCharPref(key, value);
|
||||
dump("DataCallSettings - " + key + ":" + value);
|
||||
};
|
||||
request.onerror = function onError() {
|
||||
Services.prefs.setCharPref(key, "");
|
||||
};
|
||||
});
|
||||
|
||||
navigator.mozSettings.onsettingchange = function onSettingChange(e) {
|
||||
dump("DataCallSettings - onsettingchange: " + e.settingName +
|
||||
": " + e.settingValue);
|
||||
if (e.settingValue) {
|
||||
if (DATA_CALL_SETTING_BOLKEYS.indexOf(e.settingName) > -1 ) {
|
||||
Services.prefs.setBoolPref(e.settingName, e.settingValue);
|
||||
return;
|
||||
}
|
||||
if (DATA_CALL_SETTING_CHARKEYS.indexOf(e.settingName) > -1) {
|
||||
Services.prefs.setCharPref(e.settingName, e.settingValue);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
function nsBrowserAccess() {
|
||||
}
|
||||
|
||||
|
@ -593,7 +487,11 @@ var WebappsHelper = {
|
|||
return;
|
||||
|
||||
let manifest = new DOMApplicationManifest(aManifest, json.origin);
|
||||
shell.sendEvent(content, "mozChromeEvent", { type: "webapps-launch", url: manifest.fullLaunchPath(), origin: json.origin });
|
||||
shell.sendEvent(content, "mozChromeEvent", {
|
||||
"type": "webapps-launch",
|
||||
"url": manifest.fullLaunchPath(json.startPoint),
|
||||
"origin": json.origin
|
||||
});
|
||||
});
|
||||
break;
|
||||
case "webapps-ask-install":
|
||||
|
@ -623,4 +521,136 @@ window.addEventListener('ContentStart', function(evt) {
|
|||
if (Services.prefs.getBoolPref('devtools.debugger.enabled')) {
|
||||
startDebugger();
|
||||
}
|
||||
}, false);
|
||||
});
|
||||
|
||||
|
||||
// Once Bug 731746 - Allow chrome JS object to implement nsIDOMEventTarget
|
||||
// is resolved this helper could be removed.
|
||||
var SettingsListener = {
|
||||
_callbacks: {},
|
||||
|
||||
init: function sl_init() {
|
||||
if ('mozSettings' in navigator && navigator.mozSettings)
|
||||
navigator.mozSettings.onsettingchange = this.onchange.bind(this);
|
||||
},
|
||||
|
||||
onchange: function sl_onchange(evt) {
|
||||
var callback = this._callbacks[evt.settingName];
|
||||
if (callback) {
|
||||
callback(evt.settingValue);
|
||||
}
|
||||
},
|
||||
|
||||
observe: function sl_observe(name, defaultValue, callback) {
|
||||
var settings = window.navigator.mozSettings;
|
||||
if (!settings) {
|
||||
window.setTimeout(function() { callback(defaultValue); });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!callback || typeof callback !== 'function') {
|
||||
throw new Error('Callback is not a function');
|
||||
}
|
||||
|
||||
var req = settings.getLock().get(name);
|
||||
req.addEventListener('success', (function onsuccess() {
|
||||
callback(typeof(req.result[name]) != 'undefined' ?
|
||||
req.result[name] : defaultValue);
|
||||
}));
|
||||
|
||||
this._callbacks[name] = callback;
|
||||
}
|
||||
};
|
||||
|
||||
SettingsListener.init();
|
||||
|
||||
SettingsListener.observe('language.current', 'en-US', function(value) {
|
||||
Services.prefs.setCharPref('intl.accept_languages', value);
|
||||
});
|
||||
|
||||
|
||||
(function PowerManager() {
|
||||
// This will eventually be moved to content, so use content API as
|
||||
// much as possible here. TODO: Bug 738530
|
||||
let power = navigator.mozPower;
|
||||
let idleHandler = function idleHandler(subject, topic, time) {
|
||||
if (topic !== 'idle')
|
||||
return;
|
||||
|
||||
if (power.getWakeLockState("screen") != "locked-foreground") {
|
||||
navigator.mozPower.screenEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
let wakeLockHandler = function(topic, state) {
|
||||
// Turn off the screen when no one needs the it or all of them are
|
||||
// invisible, otherwise turn the screen on. Note that the CPU
|
||||
// might go to sleep as soon as the screen is turned off and
|
||||
// acquiring wake lock will not bring it back (actually the code
|
||||
// is not executed at all).
|
||||
if (topic === 'screen') {
|
||||
if (state != "locked-foreground") {
|
||||
if (Services.idle.idleTime > idleTimeout*1000) {
|
||||
navigator.mozPower.screenEnabled = false;
|
||||
}
|
||||
} else {
|
||||
navigator.mozPower.screenEnabled = true;
|
||||
}
|
||||
} else if (topic == 'cpu') {
|
||||
navigator.mozPower.cpuSleepAllowed = (state != 'locked-foreground' &&
|
||||
state != 'locked-background');
|
||||
}
|
||||
}
|
||||
|
||||
let idleTimeout = Services.prefs.getIntPref('power.screen.timeout');
|
||||
if (!('mozSettings' in navigator))
|
||||
return;
|
||||
|
||||
let request = navigator.mozSettings.getLock().get('power.screen.timeout');
|
||||
request.onsuccess = function onSuccess() {
|
||||
idleTimeout = request.result['power.screen.timeout'] || idleTimeout;
|
||||
if (!idleTimeout)
|
||||
return;
|
||||
|
||||
Services.idle.addIdleObserver(idleHandler, idleTimeout);
|
||||
power.addWakeLockListener(wakeLockHandler);
|
||||
};
|
||||
|
||||
request.onerror = function onError() {
|
||||
if (!idleTimeout)
|
||||
return;
|
||||
|
||||
Services.idle.addIdleObserver(idleHandler, idleTimeout);
|
||||
power.addWakeLockListener(wakeLockHandler);
|
||||
};
|
||||
|
||||
SettingsListener.observe('power.screen.timeout', 30, function(value) {
|
||||
if (!value)
|
||||
return;
|
||||
|
||||
Services.idle.removeIdleObserver(idleHandler, idleTimeout);
|
||||
idleTimeout = value;
|
||||
Services.idle.addIdleObserver(idleHandler, idleTimeout);
|
||||
});
|
||||
|
||||
window.addEventListener('unload', function removeIdleObjects() {
|
||||
Services.idle.removeIdleObserver(idleHandler, idleTimeout);
|
||||
power.removeWakeLockListener(wakeLockHandler);
|
||||
});
|
||||
})();
|
||||
|
||||
|
||||
(function RILSettingsToPrefs() {
|
||||
['ril.data.enabled', 'ril.data.roaming.enabled'].forEach(function(key) {
|
||||
SettingsListener.observe(key, false, function(value) {
|
||||
Services.prefs.setBoolPref(key, value);
|
||||
});
|
||||
});
|
||||
|
||||
['ril.data.apn', 'ril.data.user', 'ril.data.passwd'].forEach(function(key) {
|
||||
SettingsListener.observe(key, false, function(value) {
|
||||
Services.prefs.setBoolPref(key, value);
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
onunload="shell.stop();">
|
||||
|
||||
<script type="application/javascript" src="chrome://browser/content/shell.js"/>
|
||||
#ifndef MOZ_TOUCH
|
||||
<script type="application/javascript" src="chrome://browser/content/touch.js"/>
|
||||
#endif
|
||||
|
||||
<browser id="homescreen"
|
||||
type="content-primary"
|
||||
|
|
|
@ -1,201 +0,0 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
/* 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/. */
|
||||
|
||||
(function touchEventHandler() {
|
||||
let debugging = false;
|
||||
function debug(str) {
|
||||
if (debugging)
|
||||
dump(str + '\n');
|
||||
};
|
||||
|
||||
let contextMenuTimeout = 0;
|
||||
|
||||
// This guard is used to not re-enter the events processing loop for
|
||||
// self dispatched events
|
||||
let ignoreEvents = false;
|
||||
|
||||
// During a 'touchstart' and the first 'touchmove' mouse events can be
|
||||
// prevented for the current touch sequence.
|
||||
let canPreventMouseEvents = false;
|
||||
|
||||
// Used to track the first mousemove and to cancel click dispatc if it's not
|
||||
// true.
|
||||
let isNewTouchAction = false;
|
||||
|
||||
// If this is set to true all mouse events will be cancelled by calling
|
||||
// both evt.preventDefault() and evt.stopPropagation().
|
||||
// This will not prevent a contextmenu event to be fired.
|
||||
// This can be turned on if canPreventMouseEvents is true and the consumer
|
||||
// application call evt.preventDefault();
|
||||
let preventMouseEvents = false;
|
||||
|
||||
let TouchEventHandler = {
|
||||
events: ['mousedown', 'mousemove', 'mouseup', 'click', 'unload'],
|
||||
start: function teh_start() {
|
||||
this.events.forEach((function(evt) {
|
||||
shell.contentBrowser.addEventListener(evt, this, true);
|
||||
}).bind(this));
|
||||
},
|
||||
stop: function teh_stop() {
|
||||
this.events.forEach((function(evt) {
|
||||
shell.contentBrowser.removeEventListener(evt, this, true);
|
||||
}).bind(this));
|
||||
},
|
||||
handleEvent: function teh_handleEvent(evt) {
|
||||
if (evt.button || ignoreEvents)
|
||||
return;
|
||||
|
||||
let eventTarget = this.target;
|
||||
let type = '';
|
||||
switch (evt.type) {
|
||||
case 'mousedown':
|
||||
debug('mousedown:');
|
||||
|
||||
this.target = evt.target;
|
||||
this.timestamp = evt.timeStamp;
|
||||
|
||||
preventMouseEvents = false;
|
||||
canPreventMouseEvents = true;
|
||||
isNewTouchAction = true;
|
||||
|
||||
contextMenuTimeout =
|
||||
this.sendContextMenu(evt.target, evt.pageX, evt.pageY, 2000);
|
||||
this.startX = evt.pageX;
|
||||
this.startY = evt.pageY;
|
||||
type = 'touchstart';
|
||||
break;
|
||||
|
||||
case 'mousemove':
|
||||
if (!eventTarget)
|
||||
return;
|
||||
|
||||
// On device a mousemove event if fired right after the mousedown
|
||||
// because of the size of the finger, so let's ignore what happens
|
||||
// below 5ms
|
||||
if (evt.timeStamp - this.timestamp < 30)
|
||||
break;
|
||||
|
||||
if (isNewTouchAction) {
|
||||
canPreventMouseEvents = true;
|
||||
isNewTouchAction = false;
|
||||
}
|
||||
|
||||
if (Math.abs(this.startX - evt.pageX) > 15 ||
|
||||
Math.abs(this.startY - evt.pageY) > 15)
|
||||
window.clearTimeout(contextMenuTimeout);
|
||||
type = 'touchmove';
|
||||
break;
|
||||
|
||||
case 'mouseup':
|
||||
if (!eventTarget)
|
||||
return;
|
||||
debug('mouseup:');
|
||||
|
||||
window.clearTimeout(contextMenuTimeout);
|
||||
this.target = null;
|
||||
type = 'touchend';
|
||||
break;
|
||||
|
||||
case 'unload':
|
||||
if (!eventTarget)
|
||||
return;
|
||||
|
||||
window.clearTimeout(contextMenuTimeout);
|
||||
this.target = null;
|
||||
TouchEventHandler.stop();
|
||||
return;
|
||||
|
||||
case 'click':
|
||||
if (isNewTouchAction) {
|
||||
// Mouse events has been cancelled so dispatch a sequence
|
||||
// of events to where touchend has been fired
|
||||
if (preventMouseEvents) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
|
||||
let target = evt.target;
|
||||
ignoreEvents = true;
|
||||
window.setTimeout(function dispatchMouseEvents(self) {
|
||||
self.fireMouseEvent('mousemove', evt);
|
||||
self.fireMouseEvent('mousedown', evt);
|
||||
self.fireMouseEvent('mouseup', evt);
|
||||
ignoreEvents = false;
|
||||
}, 0, this);
|
||||
}
|
||||
|
||||
debug('click: fire');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let target = eventTarget || this.target;
|
||||
if (target && type) {
|
||||
let touchEvent = this.sendTouchEvent(evt, target, type);
|
||||
if (touchEvent.defaultPrevented && canPreventMouseEvents)
|
||||
preventMouseEvents = true;
|
||||
}
|
||||
|
||||
if (preventMouseEvents) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
|
||||
if (type != 'touchmove')
|
||||
debug('cancelled (fire ' + type + ')');
|
||||
}
|
||||
},
|
||||
fireMouseEvent: function teh_fireMouseEvent(type, evt) {
|
||||
debug(type + ': fire');
|
||||
|
||||
let content = evt.target.ownerDocument.defaultView;
|
||||
var utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
utils.sendMouseEvent(type, evt.pageX, evt.pageY, 0, 1, 0, true);
|
||||
},
|
||||
sendContextMenu: function teh_sendContextMenu(target, x, y, delay) {
|
||||
let doc = target.ownerDocument;
|
||||
let evt = doc.createEvent('MouseEvent');
|
||||
evt.initMouseEvent('contextmenu', true, true, doc.defaultView,
|
||||
0, x, y, x, y, false, false, false, false,
|
||||
0, null);
|
||||
|
||||
let timeout = window.setTimeout((function contextMenu() {
|
||||
debug('fire context-menu');
|
||||
|
||||
target.dispatchEvent(evt);
|
||||
if (!evt.defaultPrevented)
|
||||
return;
|
||||
|
||||
doc.releaseCapture();
|
||||
this.target = null;
|
||||
|
||||
isNewTouchAction = false;
|
||||
}).bind(this), delay);
|
||||
return timeout;
|
||||
},
|
||||
sendTouchEvent: function teh_sendTouchEvent(evt, target, name) {
|
||||
let touchEvent = document.createEvent('touchevent');
|
||||
let point = document.createTouch(window, target, 0,
|
||||
evt.pageX, evt.pageY,
|
||||
evt.screenX, evt.screenY,
|
||||
evt.clientX, evt.clientY,
|
||||
1, 1, 0, 0);
|
||||
let touches = document.createTouchList(point);
|
||||
let targetTouches = touches;
|
||||
let changedTouches = touches;
|
||||
touchEvent.initTouchEvent(name, true, true, window, 0,
|
||||
false, false, false, false,
|
||||
touches, targetTouches, changedTouches);
|
||||
target.dispatchEvent(touchEvent);
|
||||
return touchEvent;
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('ContentStart', function touchStart(evt) {
|
||||
window.removeEventListener('ContentStart', touchStart);
|
||||
TouchEventHandler.start();
|
||||
});
|
||||
})();
|
||||
|
|
@ -13,10 +13,9 @@ Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
|||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
Cu.import('resource://gre/modules/Geometry.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyGetter(Services, 'fm', function() {
|
||||
return Cc['@mozilla.org/focus-manager;1']
|
||||
.getService(Ci.nsIFocusManager);
|
||||
});
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, 'fm',
|
||||
'@mozilla.org/focus-manager;1',
|
||||
'nsIFocusManager');
|
||||
|
||||
// MozKeyboard
|
||||
(function VirtualKeyboardManager() {
|
||||
|
|
|
@ -7,9 +7,6 @@ chrome.jar:
|
|||
content/dbg-browser-actors.js (content/dbg-browser-actors.js)
|
||||
* content/shell.xul (content/shell.xul)
|
||||
* content/shell.js (content/shell.js)
|
||||
#ifndef MOZ_TOUCH
|
||||
content/touch.js (content/touch.js)
|
||||
#endif
|
||||
content/webapi.js (content/webapi.js)
|
||||
content/content.css (content/content.css)
|
||||
|
||||
|
|
|
@ -344,7 +344,7 @@ let TestPilotSetup = {
|
|||
appcontent.addEventListener("DOMContentLoaded", function(event) {
|
||||
let newUrl = event.originalTarget.URL;
|
||||
self._feedbackManager.fillInFeedbackPage(newUrl, window);
|
||||
for (i = 0; i < self.taskList.length; i++) {
|
||||
for (let i = 0; i < self.taskList.length; i++) {
|
||||
self.taskList[i].onUrlLoad(newUrl, event);
|
||||
}
|
||||
}, true);
|
||||
|
|
|
@ -873,12 +873,6 @@ pref("places.frecency.unvisitedTypedBonus", 200);
|
|||
// 2 - pre-populate site URL and pre-fetch certificate
|
||||
pref("browser.ssl_override_behavior", 2);
|
||||
|
||||
// Controls the display of domain in the identity box for SSL connections.
|
||||
// 0 - do not show domain
|
||||
// 1 - show effectiveTLD + 1 (e.g. mozilla.org)
|
||||
// 2 - show full domain (e.g. bugzilla.mozilla.org)
|
||||
pref("browser.identity.ssl_domain_display", 0);
|
||||
|
||||
// True if the user should be prompted when a web application supports
|
||||
// offline apps.
|
||||
pref("browser.offline-apps.notify", true);
|
||||
|
@ -1061,6 +1055,9 @@ pref("devtools.debugger.enabled", false);
|
|||
pref("devtools.debugger.remote-enabled", false);
|
||||
pref("devtools.debugger.remote-host", "localhost");
|
||||
pref("devtools.debugger.remote-port", 6000);
|
||||
pref("devtools.debugger.remote-autoconnect", false);
|
||||
pref("devtools.debugger.remote-connection-retries", 3);
|
||||
pref("devtools.debugger.remote-timeout", 3000);
|
||||
|
||||
// The default Debugger UI height
|
||||
pref("devtools.debugger.ui.height", 250);
|
||||
|
|
|
@ -1025,27 +1025,31 @@ let gGestureSupport = {
|
|||
switch (aEvent.type) {
|
||||
case "MozSwipeGesture":
|
||||
aEvent.preventDefault();
|
||||
return this.onSwipe(aEvent);
|
||||
this.onSwipe(aEvent);
|
||||
break;
|
||||
case "MozMagnifyGestureStart":
|
||||
aEvent.preventDefault();
|
||||
#ifdef XP_WIN
|
||||
return this._setupGesture(aEvent, "pinch", def(25, 0), "out", "in");
|
||||
this._setupGesture(aEvent, "pinch", def(25, 0), "out", "in");
|
||||
#else
|
||||
return this._setupGesture(aEvent, "pinch", def(150, 1), "out", "in");
|
||||
this._setupGesture(aEvent, "pinch", def(150, 1), "out", "in");
|
||||
#endif
|
||||
break;
|
||||
case "MozRotateGestureStart":
|
||||
aEvent.preventDefault();
|
||||
return this._setupGesture(aEvent, "twist", def(25, 0), "right", "left");
|
||||
this._setupGesture(aEvent, "twist", def(25, 0), "right", "left");
|
||||
break;
|
||||
case "MozMagnifyGestureUpdate":
|
||||
case "MozRotateGestureUpdate":
|
||||
aEvent.preventDefault();
|
||||
return this._doUpdate(aEvent);
|
||||
this._doUpdate(aEvent);
|
||||
break;
|
||||
case "MozTapGesture":
|
||||
aEvent.preventDefault();
|
||||
return this._doAction(aEvent, ["tap"]);
|
||||
case "MozPressTapGesture":
|
||||
// Fall through to default behavior
|
||||
return;
|
||||
this._doAction(aEvent, ["tap"]);
|
||||
break;
|
||||
/* case "MozPressTapGesture":
|
||||
break; */
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1130,8 +1134,6 @@ let gGestureSupport = {
|
|||
* The original gesture event to convert into a fake click event
|
||||
* @param aGesture
|
||||
* Array of gesture name parts (to be joined by periods)
|
||||
* @return Name of the command found for the event's keys and gesture. If no
|
||||
* command is found, no value is returned (undefined).
|
||||
*/
|
||||
_doAction: function GS__doAction(aEvent, aGesture) {
|
||||
// Create an array of pressed keys in a fixed order so that a command for
|
||||
|
@ -1169,9 +1171,8 @@ let gGestureSupport = {
|
|||
goDoCommand(command);
|
||||
}
|
||||
|
||||
return command;
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1192,10 +1193,12 @@ let gGestureSupport = {
|
|||
*/
|
||||
onSwipe: function GS_onSwipe(aEvent) {
|
||||
// Figure out which one (and only one) direction was triggered
|
||||
["UP", "RIGHT", "DOWN", "LEFT"].forEach(function (dir) {
|
||||
if (aEvent.direction == aEvent["DIRECTION_" + dir])
|
||||
return this._doAction(aEvent, ["swipe", dir.toLowerCase()]);
|
||||
}, this);
|
||||
for (let dir of ["UP", "RIGHT", "DOWN", "LEFT"]) {
|
||||
if (aEvent.direction == aEvent["DIRECTION_" + dir]) {
|
||||
this._doAction(aEvent, ["swipe", dir.toLowerCase()]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -5201,10 +5204,13 @@ var TabsProgressListener = {
|
|||
aFlags) {
|
||||
// Filter out any sub-frame loads
|
||||
if (aBrowser.contentWindow == aWebProgress.DOMWindow) {
|
||||
// initialize the click-to-play state
|
||||
aBrowser._clickToPlayDoorhangerShown = false;
|
||||
aBrowser._clickToPlayPluginsActivated = false;
|
||||
|
||||
// Filter out any onLocationChanges triggered by anchor navigation
|
||||
// or history.push/pop/replaceState.
|
||||
if (aRequest) {
|
||||
// Initialize the click-to-play state.
|
||||
aBrowser._clickToPlayDoorhangerShown = false;
|
||||
aBrowser._clickToPlayPluginsActivated = false;
|
||||
}
|
||||
FullZoom.onLocationChange(aLocationURI, false, aBrowser);
|
||||
}
|
||||
},
|
||||
|
@ -8199,30 +8205,19 @@ var gIdentityHandler = {
|
|||
* @param newMode The newly set identity mode. Should be one of the IDENTITY_MODE_* constants.
|
||||
*/
|
||||
setIdentityMessages : function(newMode) {
|
||||
if (newMode == this.IDENTITY_MODE_DOMAIN_VERIFIED) {
|
||||
var iData = this.getIdentityData();
|
||||
let icon_label = "";
|
||||
let tooltip = "";
|
||||
let icon_country_label = "";
|
||||
let icon_labels_dir = "ltr";
|
||||
|
||||
// It would be sort of nice to use the CN= field in the cert, since that's
|
||||
// typically what we want here, but thanks to x509 certs being extensible,
|
||||
// it's not the only place you have to check, there can be more than one domain,
|
||||
// et cetera, ad nauseum. We know the cert is valid for location.host, so
|
||||
// let's just use that. Check the pref to determine how much of the verified
|
||||
// hostname to show
|
||||
var icon_label = "";
|
||||
var icon_country_label = "";
|
||||
var icon_labels_dir = "ltr";
|
||||
switch (gPrefService.getIntPref("browser.identity.ssl_domain_display")) {
|
||||
case 2 : // Show full domain
|
||||
icon_label = this._lastLocation.hostname;
|
||||
break;
|
||||
case 1 : // Show eTLD.
|
||||
icon_label = this.getEffectiveHost();
|
||||
}
|
||||
switch (newMode) {
|
||||
case this.IDENTITY_MODE_DOMAIN_VERIFIED: {
|
||||
let iData = this.getIdentityData();
|
||||
|
||||
// Verifier is either the CA Org, for a normal cert, or a special string
|
||||
// for certs that are trusted because of a security exception.
|
||||
var tooltip = gNavigatorBundle.getFormattedString("identity.identified.verifier",
|
||||
[iData.caOrg]);
|
||||
tooltip = gNavigatorBundle.getFormattedString("identity.identified.verifier",
|
||||
[iData.caOrg]);
|
||||
|
||||
// Check whether this site is a security exception. XPConnect does the right
|
||||
// thing here in terms of converting _lastLocation.port from string to int, but
|
||||
|
@ -8237,15 +8232,16 @@ var gIdentityHandler = {
|
|||
(this._lastLocation.port || 443),
|
||||
iData.cert, {}, {}))
|
||||
tooltip = gNavigatorBundle.getString("identity.identified.verified_by_you");
|
||||
}
|
||||
else if (newMode == this.IDENTITY_MODE_IDENTIFIED) {
|
||||
break; }
|
||||
case this.IDENTITY_MODE_IDENTIFIED: {
|
||||
// If it's identified, then we can populate the dialog with credentials
|
||||
iData = this.getIdentityData();
|
||||
let iData = this.getIdentityData();
|
||||
tooltip = gNavigatorBundle.getFormattedString("identity.identified.verifier",
|
||||
[iData.caOrg]);
|
||||
icon_label = iData.subjectOrg;
|
||||
if (iData.country)
|
||||
icon_country_label = "(" + iData.country + ")";
|
||||
|
||||
// If the organization name starts with an RTL character, then
|
||||
// swap the positions of the organization and country code labels.
|
||||
// The Unicode ranges reflect the definition of the UCS2_CHAR_IS_BIDI
|
||||
|
@ -8254,18 +8250,11 @@ var gIdentityHandler = {
|
|||
// Unicode Bidirectional Algorithm proper (at the paragraph level).
|
||||
icon_labels_dir = /^[\u0590-\u08ff\ufb1d-\ufdff\ufe70-\ufefc]/.test(icon_label) ?
|
||||
"rtl" : "ltr";
|
||||
}
|
||||
else if (newMode == this.IDENTITY_MODE_CHROMEUI) {
|
||||
icon_label = "";
|
||||
tooltip = "";
|
||||
icon_country_label = "";
|
||||
icon_labels_dir = "ltr";
|
||||
}
|
||||
else {
|
||||
break; }
|
||||
case this.IDENTITY_MODE_CHROMEUI:
|
||||
break;
|
||||
default:
|
||||
tooltip = gNavigatorBundle.getString("identity.unknown.tooltip");
|
||||
icon_label = "";
|
||||
icon_country_label = "";
|
||||
icon_labels_dir = "ltr";
|
||||
}
|
||||
|
||||
// Push the appropriate strings out to the UI
|
||||
|
@ -8295,19 +8284,20 @@ var gIdentityHandler = {
|
|||
this._identityPopupEncLabel.textContent = this._encryptionLabel[newMode];
|
||||
|
||||
// Initialize the optional strings to empty values
|
||||
var supplemental = "";
|
||||
var verifier = "";
|
||||
let supplemental = "";
|
||||
let verifier = "";
|
||||
let host = "";
|
||||
let owner = "";
|
||||
|
||||
if (newMode == this.IDENTITY_MODE_DOMAIN_VERIFIED) {
|
||||
var iData = this.getIdentityData();
|
||||
var host = this.getEffectiveHost();
|
||||
var owner = gNavigatorBundle.getString("identity.ownerUnknown2");
|
||||
switch (newMode) {
|
||||
case this.IDENTITY_MODE_DOMAIN_VERIFIED:
|
||||
host = this.getEffectiveHost();
|
||||
owner = gNavigatorBundle.getString("identity.ownerUnknown2");
|
||||
verifier = this._identityBox.tooltipText;
|
||||
supplemental = "";
|
||||
}
|
||||
else if (newMode == this.IDENTITY_MODE_IDENTIFIED) {
|
||||
break;
|
||||
case this.IDENTITY_MODE_IDENTIFIED: {
|
||||
// If it's identified, then we can populate the dialog with credentials
|
||||
iData = this.getIdentityData();
|
||||
let iData = this.getIdentityData();
|
||||
host = this.getEffectiveHost();
|
||||
owner = iData.subjectOrg;
|
||||
verifier = this._identityBox.tooltipText;
|
||||
|
@ -8322,11 +8312,7 @@ var gIdentityHandler = {
|
|||
supplemental += iData.state;
|
||||
else if (iData.country) // Country only
|
||||
supplemental += iData.country;
|
||||
}
|
||||
else {
|
||||
// These strings will be hidden in CSS anyhow
|
||||
host = "";
|
||||
owner = "";
|
||||
break; }
|
||||
}
|
||||
|
||||
// Push the appropriate strings out to the UI
|
||||
|
|
|
@ -775,7 +775,8 @@ nsContextMenu.prototype = {
|
|||
urlSecurityCheck(frameURL, this.browser.contentPrincipal,
|
||||
Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
|
||||
var referrer = doc.referrer;
|
||||
this.browser.loadURI(frameURL, referrer ? makeURI(referrer) : null);
|
||||
openUILinkIn(frameURL, "current", { disallowInheritPrincipal: true,
|
||||
referrerURI: referrer ? makeURI(referrer) : null });
|
||||
},
|
||||
|
||||
// View Partial Source
|
||||
|
@ -847,7 +848,8 @@ nsContextMenu.prototype = {
|
|||
}
|
||||
|
||||
var doc = this.target.ownerDocument;
|
||||
openUILink(viewURL, e, null, null, null, null, doc.documentURIObject );
|
||||
openUILink(viewURL, e, { disallowInheritPrincipal: true,
|
||||
referrerURI: doc.documentURIObject });
|
||||
},
|
||||
|
||||
saveVideoFrameAsImage: function () {
|
||||
|
@ -883,7 +885,8 @@ nsContextMenu.prototype = {
|
|||
this.browser.contentPrincipal,
|
||||
Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
|
||||
var doc = this.target.ownerDocument;
|
||||
openUILink(this.bgImageURL, e, null, null, null, null, doc.documentURIObject );
|
||||
openUILink(this.bgImageURL, e, { disallowInheritPrincipal: true,
|
||||
referrerURI: doc.documentURIObject });
|
||||
},
|
||||
|
||||
disableSetDesktopBackground: function() {
|
||||
|
|
|
@ -181,6 +181,8 @@ _BROWSER_FILES = \
|
|||
browser_bug664672.js \
|
||||
browser_bug710878.js \
|
||||
browser_bug719271.js \
|
||||
browser_bug743421.js \
|
||||
browser_bug749738.js \
|
||||
browser_canonizeURL.js \
|
||||
browser_findbarClose.js \
|
||||
browser_homeDrop.js \
|
||||
|
@ -253,6 +255,7 @@ _BROWSER_FILES = \
|
|||
plugin_alternate_content.html \
|
||||
plugin_both.html \
|
||||
plugin_both2.html \
|
||||
plugin_bug743421.html \
|
||||
plugin_clickToPlayAllow.html \
|
||||
plugin_clickToPlayDeny.html \
|
||||
alltabslistener.html \
|
||||
|
@ -278,6 +281,7 @@ _BROWSER_FILES = \
|
|||
redirect_bug623155.sjs \
|
||||
browser_tabDrop.js \
|
||||
browser_lastAccessedTab.js \
|
||||
browser_bug734076.js \
|
||||
$(NULL)
|
||||
|
||||
ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab();
|
||||
registerCleanupFunction(function () {
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
||||
let browser = tab.linkedBrowser;
|
||||
browser.stop(); // stop the about:blank load
|
||||
|
||||
let writeDomainURL = encodeURI("data:text/html,<script>document.write(document.domain);</script>");
|
||||
let tests = [
|
||||
{
|
||||
name: "view background image",
|
||||
url: "http://mochi.test:8888/",
|
||||
go: function (cb) {
|
||||
let contentBody = browser.contentDocument.body;
|
||||
contentBody.style.backgroundImage = "url('" + writeDomainURL + "')";
|
||||
doOnLoad(function () {
|
||||
let domain = browser.contentDocument.body.textContent;
|
||||
is(domain, "", "no domain was inherited for view background image");
|
||||
cb();
|
||||
});
|
||||
|
||||
let contextMenu = initContextMenu(contentBody);
|
||||
contextMenu.viewBGImage();
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "view image",
|
||||
url: "http://mochi.test:8888/",
|
||||
go: function (cb) {
|
||||
doOnLoad(function () {
|
||||
let domain = browser.contentDocument.body.textContent;
|
||||
is(domain, "", "no domain was inherited for view image");
|
||||
cb();
|
||||
});
|
||||
|
||||
let doc = browser.contentDocument;
|
||||
let img = doc.createElement("img");
|
||||
img.setAttribute("src", writeDomainURL);
|
||||
doc.body.appendChild(img);
|
||||
|
||||
let contextMenu = initContextMenu(img);
|
||||
contextMenu.viewMedia();
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "show only this frame",
|
||||
url: "http://mochi.test:8888/",
|
||||
go: function (cb) {
|
||||
doOnLoad(function () {
|
||||
let domain = browser.contentDocument.body.textContent;
|
||||
is(domain, "", "no domain was inherited for 'show only this frame'");
|
||||
cb();
|
||||
});
|
||||
|
||||
let doc = browser.contentDocument;
|
||||
let iframe = doc.createElement("iframe");
|
||||
iframe.setAttribute("src", writeDomainURL);
|
||||
doc.body.appendChild(iframe);
|
||||
|
||||
iframe.addEventListener("load", function onload() {
|
||||
let contextMenu = initContextMenu(iframe.contentDocument.body);
|
||||
contextMenu.showOnlyThisFrame();
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
function doOnLoad(cb) {
|
||||
browser.addEventListener("load", function onLoad(e) {
|
||||
if (e.target != browser.contentDocument)
|
||||
return;
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
cb();
|
||||
}, true);
|
||||
}
|
||||
|
||||
function doNext() {
|
||||
let test = tests.shift();
|
||||
if (test) {
|
||||
info("Running test: " + test.name);
|
||||
doOnLoad(function () {
|
||||
test.go(function () {
|
||||
executeSoon(doNext);
|
||||
});
|
||||
});
|
||||
browser.contentDocument.location = test.url;
|
||||
} else {
|
||||
executeSoon(finish);
|
||||
}
|
||||
}
|
||||
|
||||
doNext();
|
||||
}
|
||||
|
||||
function initContextMenu(aNode) {
|
||||
document.popupNode = aNode;
|
||||
let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
|
||||
let contextMenu = new nsContextMenu(contentAreaContextMenu, gBrowser);
|
||||
return contextMenu;
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
var rootDir = getRootDirectory(gTestPath);
|
||||
const gTestRoot = rootDir;
|
||||
|
||||
var gTestBrowser = null;
|
||||
var gNextTest = null;
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
registerCleanupFunction(function() { Services.prefs.clearUserPref("plugins.click_to_play"); });
|
||||
Services.prefs.setBoolPref("plugins.click_to_play", true);
|
||||
|
||||
var newTab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = newTab;
|
||||
gTestBrowser = gBrowser.selectedBrowser;
|
||||
gTestBrowser.addEventListener("load", pageLoad, true);
|
||||
prepareTest(test1a, gTestRoot + "plugin_bug743421.html");
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
gTestBrowser.removeEventListener("load", pageLoad, true);
|
||||
gBrowser.removeCurrentTab();
|
||||
window.focus();
|
||||
finish();
|
||||
}
|
||||
|
||||
function pageLoad() {
|
||||
// The plugin events are async dispatched and can come after the load event
|
||||
// This just allows the events to fire before we then go on to test the states
|
||||
executeSoon(gNextTest);
|
||||
}
|
||||
|
||||
function prepareTest(nextTest, url) {
|
||||
gNextTest = nextTest;
|
||||
gTestBrowser.contentWindow.location = url;
|
||||
}
|
||||
|
||||
// Tests that navigation within the page and the window.history API doesn't break click-to-play state.
|
||||
function test1a() {
|
||||
var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(!popupNotification, "Test 1a, Should not have a click-to-play notification");
|
||||
var plugin = gTestBrowser.contentWindow.addPlugin();
|
||||
|
||||
setTimeout(test1b, 500);
|
||||
}
|
||||
|
||||
function test1b() {
|
||||
var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(popupNotification, "Test 1b, Should have a click-to-play notification");
|
||||
var plugin = gTestBrowser.contentDocument.getElementsByTagName("embed")[0];
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(!objLoadingContent.activated, "Test 1b, Plugin should not be activated");
|
||||
|
||||
EventUtils.synthesizeMouse(plugin, 100, 100, { });
|
||||
setTimeout(test1c, 500);
|
||||
}
|
||||
|
||||
function test1c() {
|
||||
var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(!popupNotification, "Test 1c, Should not have a click-to-play notification");
|
||||
var plugin = gTestBrowser.contentWindow.addPlugin();
|
||||
|
||||
setTimeout(test1d, 500);
|
||||
}
|
||||
|
||||
function test1d() {
|
||||
var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(!popupNotification, "Test 1d, Should not have a click-to-play notification");
|
||||
var plugin = gTestBrowser.contentDocument.getElementsByTagName("embed")[1];
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.activated, "Test 1d, Plugin should be activated");
|
||||
|
||||
gNextTest = test1e;
|
||||
gTestBrowser.contentWindow.addEventListener("hashchange", test1e, false);
|
||||
gTestBrowser.contentWindow.location += "#anchorNavigation";
|
||||
}
|
||||
|
||||
function test1e() {
|
||||
gTestBrowser.contentWindow.removeEventListener("hashchange", test1e, false);
|
||||
var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(!popupNotification, "Test 1e, Should not have a click-to-play notification");
|
||||
var plugin = gTestBrowser.contentWindow.addPlugin();
|
||||
|
||||
setTimeout(test1f, 500);
|
||||
}
|
||||
|
||||
function test1f() {
|
||||
var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(!popupNotification, "Test 1f, Should not have a click-to-play notification");
|
||||
var plugin = gTestBrowser.contentDocument.getElementsByTagName("embed")[2];
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.activated, "Test 1f, Plugin should be activated");
|
||||
|
||||
gTestBrowser.contentWindow.history.replaceState({}, "", "replacedState");
|
||||
gTestBrowser.contentWindow.addPlugin();
|
||||
setTimeout(test1g, 500);
|
||||
}
|
||||
|
||||
function test1g() {
|
||||
var popupNotification2 = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(!popupNotification2, "Test 1g, Should not have a click-to-play notification after replaceState");
|
||||
var plugin = gTestBrowser.contentDocument.getElementsByTagName("embed")[3];
|
||||
var objLoadingContent2 = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent2.activated, "Test 1g, Plugin should be activated");
|
||||
finishTest();
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const DUMMY_PAGE = "http://example.org/browser/browser/base/content/test/dummy_page.html";
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let tab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = tab;
|
||||
|
||||
load(tab, DUMMY_PAGE, function() {
|
||||
gFindBar.onFindCommand();
|
||||
EventUtils.sendString("Dummy");
|
||||
gBrowser.removeTab(tab);
|
||||
|
||||
try {
|
||||
gFindBar.close();
|
||||
ok(true, "findbar.close should not throw an exception");
|
||||
} catch(e) {
|
||||
ok(false, "findbar.close threw exception: " + e);
|
||||
}
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
function load(aTab, aUrl, aCallback) {
|
||||
aTab.linkedBrowser.addEventListener("load", function onload(aEvent) {
|
||||
aEvent.currentTarget.removeEventListener("load", onload, true);
|
||||
waitForFocus(aCallback, content);
|
||||
}, true);
|
||||
aTab.linkedBrowser.loadURI(aUrl);
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
/* Tests for correct behaviour of getEffectiveHost on identity handler */
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref("browser.identity.ssl_domain_display");
|
||||
});
|
||||
|
||||
ok(gIdentityHandler, "gIdentityHandler should exist");
|
||||
|
||||
|
@ -102,7 +99,6 @@ function nextTest() {
|
|||
gTestDesc += " (second time)";
|
||||
if (gCurrentTest.isHTTPS) {
|
||||
gCheckETLD = true;
|
||||
Services.prefs.setIntPref("browser.identity.ssl_domain_display", 1);
|
||||
}
|
||||
content.location = gCurrentTest.location;
|
||||
} else {
|
||||
|
@ -110,18 +106,11 @@ function nextTest() {
|
|||
gTestDesc = "#" + gCurrentTestIndex + " (" + gCurrentTest.name + " without eTLD in identity icon label)";
|
||||
if (!gForward)
|
||||
gTestDesc += " (second time)";
|
||||
Services.prefs.clearUserPref("browser.identity.ssl_domain_display");
|
||||
content.location.reload(true);
|
||||
}
|
||||
}
|
||||
|
||||
function checkResult() {
|
||||
if (gCurrentTest.isHTTPS && Services.prefs.getIntPref("browser.identity.ssl_domain_display") == 1) {
|
||||
// Check that the effective host is displayed in the UI
|
||||
let label = document.getElementById("identity-icon-label");
|
||||
is(label.value, gCurrentTest.effectiveHost, "effective host is displayed in identity icon label for test " + gTestDesc);
|
||||
}
|
||||
|
||||
// Sanity check other values, and the value of gIdentityHandler.getEffectiveHost()
|
||||
is(gIdentityHandler._lastLocation.host, gCurrentTest.host, "host matches for test " + gTestDesc);
|
||||
is(gIdentityHandler.getEffectiveHost(), gCurrentTest.effectiveHost, "effectiveHost matches for test " + gTestDesc);
|
||||
|
|
|
@ -191,7 +191,7 @@ var wrongBrowserNotification;
|
|||
var tests = [
|
||||
{ // Test #0
|
||||
run: function () {
|
||||
this.notifyObj = new basicNotification(),
|
||||
this.notifyObj = new basicNotification();
|
||||
showNotification(this.notifyObj);
|
||||
},
|
||||
onShown: function (popup) {
|
||||
|
@ -206,7 +206,7 @@ var tests = [
|
|||
},
|
||||
{ // Test #1
|
||||
run: function () {
|
||||
this.notifyObj = new basicNotification(),
|
||||
this.notifyObj = new basicNotification();
|
||||
showNotification(this.notifyObj);
|
||||
},
|
||||
onShown: function (popup) {
|
||||
|
@ -221,7 +221,7 @@ var tests = [
|
|||
},
|
||||
{ // Test #2
|
||||
run: function () {
|
||||
this.notifyObj = new basicNotification(),
|
||||
this.notifyObj = new basicNotification();
|
||||
this.notification = showNotification(this.notifyObj);
|
||||
},
|
||||
onShown: function (popup) {
|
||||
|
@ -285,7 +285,7 @@ var tests = [
|
|||
// notification.
|
||||
{ // Test #6
|
||||
run: function () {
|
||||
this.notifyObj = new basicNotification(),
|
||||
this.notifyObj = new basicNotification();
|
||||
// Show the same notification twice
|
||||
this.notification1 = showNotification(this.notifyObj);
|
||||
this.notification2 = showNotification(this.notifyObj);
|
||||
|
@ -332,7 +332,7 @@ var tests = [
|
|||
// Test notification without mainAction
|
||||
{ // Test #8
|
||||
run: function () {
|
||||
this.notifyObj = new basicNotification(),
|
||||
this.notifyObj = new basicNotification();
|
||||
this.notifyObj.mainAction = null;
|
||||
this.notification = showNotification(this.notifyObj);
|
||||
},
|
||||
|
@ -568,7 +568,7 @@ var tests = [
|
|||
// Test notification "Not Now" menu item
|
||||
{ // Test #17
|
||||
run: function () {
|
||||
this.notifyObj = new basicNotification(),
|
||||
this.notifyObj = new basicNotification();
|
||||
this.notification = showNotification(this.notifyObj);
|
||||
},
|
||||
onShown: function (popup) {
|
||||
|
@ -584,7 +584,7 @@ var tests = [
|
|||
// Test notification close button
|
||||
{ // Test #18
|
||||
run: function () {
|
||||
this.notifyObj = new basicNotification(),
|
||||
this.notifyObj = new basicNotification();
|
||||
this.notification = showNotification(this.notifyObj);
|
||||
},
|
||||
onShown: function (popup) {
|
||||
|
@ -677,7 +677,7 @@ var tests = [
|
|||
this.notification2.remove();
|
||||
ok(this.notifyObj2.removedCallbackTriggered, "removed callback triggered");
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
// Test that multiple notification icons are removed when switching tabs
|
||||
{ // Test #22
|
||||
|
@ -718,7 +718,7 @@ var tests = [
|
|||
gBrowser.selectedTab = this.oldSelectedTab;
|
||||
this.notificationOld.remove();
|
||||
}
|
||||
],
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
function addPlugin(callback) {
|
||||
var embed = document.createElement("embed");
|
||||
embed.style.width = "200px";
|
||||
embed.style.height = "200px";
|
||||
embed.setAttribute("type", "application/x-test");
|
||||
return document.body.appendChild(embed);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -2901,11 +2901,6 @@ SessionStoreService.prototype = {
|
|||
ScratchpadManager.restoreSession(aState.scratchpads);
|
||||
}
|
||||
|
||||
// This will force the keypress listener that Panorama has to attach if it
|
||||
// isn't already. This will be the case if tab view wasn't entered or there
|
||||
// were only visible tabs when TabView.init was first called.
|
||||
aWindow.TabView.init();
|
||||
|
||||
// set smoothScroll back to the original value
|
||||
tabstrip.smoothScroll = smoothScroll;
|
||||
|
||||
|
|
|
@ -7,7 +7,11 @@ export MOZILLA_OFFICIAL=1
|
|||
|
||||
mk_add_options MOZ_MAKE_FLAGS=-j1
|
||||
|
||||
. $topsrcdir/build/win32/mozconfig.vs2010
|
||||
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
|
||||
. $topsrcdir/build/win32/mozconfig.vs2010-win64
|
||||
else
|
||||
. $topsrcdir/build/win32/mozconfig.vs2010
|
||||
fi
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
|
|
@ -3,4 +3,8 @@ ac_add_options --enable-update-packaging
|
|||
ac_add_options --enable-official-branding
|
||||
ac_add_options --with-l10n-base=../../l10n-central
|
||||
|
||||
. $topsrcdir/build/win32/mozconfig.vs2010
|
||||
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
|
||||
. $topsrcdir/build/win32/mozconfig.vs2010-win64
|
||||
else
|
||||
. $topsrcdir/build/win32/mozconfig.vs2010
|
||||
fi
|
||||
|
|
|
@ -16,7 +16,11 @@ export MOZ_TELEMETRY_REPORTING=1
|
|||
|
||||
mk_add_options MOZ_MAKE_FLAGS=-j1
|
||||
|
||||
. $topsrcdir/build/win32/mozconfig.vs2010
|
||||
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
|
||||
. $topsrcdir/build/win32/mozconfig.vs2010-win64
|
||||
else
|
||||
. $topsrcdir/build/win32/mozconfig.vs2010
|
||||
fi
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
|
|
@ -12,7 +12,11 @@ export MOZILLA_OFFICIAL=1
|
|||
|
||||
export MOZ_TELEMETRY_REPORTING=1
|
||||
|
||||
. $topsrcdir/build/win32/mozconfig.vs2010
|
||||
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
|
||||
. $topsrcdir/build/win32/mozconfig.vs2010-win64
|
||||
else
|
||||
. $topsrcdir/build/win32/mozconfig.vs2010
|
||||
fi
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
|
|
@ -46,6 +46,7 @@ const Ci = Components.interfaces;
|
|||
const Cu = Components.utils;
|
||||
|
||||
const DBG_XUL = "chrome://browser/content/debugger.xul";
|
||||
const DBG_STRINGS_URI = "chrome://browser/locale/devtools/debugger.properties";
|
||||
const REMOTE_PROFILE_NAME = "_remote-debug";
|
||||
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
|
||||
|
@ -82,24 +83,22 @@ DebuggerUI.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Starts a remote debugger in a new process, or stops it if already started.
|
||||
* @see DebuggerProcess.constructor
|
||||
* @return DebuggerProcess if the debugger is started, null if it's stopped.
|
||||
* Starts a remote debugger in a new window, or stops it if already started.
|
||||
* @return RemoteDebuggerWindow if the debugger is started, null if stopped.
|
||||
*/
|
||||
toggleRemoteDebugger: function DUI_toggleRemoteDebugger(aOnClose, aOnRun) {
|
||||
toggleRemoteDebugger: function DUI_toggleRemoteDebugger() {
|
||||
let win = this.chromeWindow;
|
||||
|
||||
if (win._remoteDebugger) {
|
||||
win._remoteDebugger.close();
|
||||
return null;
|
||||
}
|
||||
return new DebuggerProcess(win, aOnClose, aOnRun);
|
||||
return new RemoteDebuggerWindow(this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts a chrome debugger in a new process, or stops it if already started.
|
||||
* @see DebuggerProcess.constructor
|
||||
* @return DebuggerProcess if the debugger is started, null if it's stopped.
|
||||
* @return ChromeDebuggerProcess if the debugger is started, null if stopped.
|
||||
*/
|
||||
toggleChromeDebugger: function DUI_toggleChromeDebugger(aOnClose, aOnRun) {
|
||||
let win = this.chromeWindow;
|
||||
|
@ -108,17 +107,35 @@ DebuggerUI.prototype = {
|
|||
win._chromeDebugger.close();
|
||||
return null;
|
||||
}
|
||||
return new DebuggerProcess(win, aOnClose, aOnRun, true);
|
||||
return new ChromeDebuggerProcess(win, aOnClose, aOnRun, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the debugger for a specified tab.
|
||||
* @return DebuggerPane if a debugger exists for the tab, null otherwise
|
||||
* @return DebuggerPane if a debugger exists for the tab, null otherwise.
|
||||
*/
|
||||
getDebugger: function DUI_getDebugger(aTab) {
|
||||
return aTab._scriptDebugger;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the remote debugger for the current chrome window.
|
||||
* @return RemoteDebuggerWindow if a remote debugger exists, null otherwise.
|
||||
*/
|
||||
getRemoteDebugger: function DUI_getRemoteDebugger() {
|
||||
let win = this.chromeWindow;
|
||||
return '_remoteDebugger' in win ? win._remoteDebugger : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the chrome debugger for the current firefox instance.
|
||||
* @return ChromeDebuggerProcess if a chrome debugger exists, null otherwise.
|
||||
*/
|
||||
getChromeDebugger: function DUI_getChromeDebugger() {
|
||||
let win = this.chromeWindow;
|
||||
return '_chromeDebugger' in win ? win._chromeDebugger : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the preferences associated with the debugger frontend.
|
||||
* @return object
|
||||
|
@ -131,12 +148,14 @@ DebuggerUI.prototype = {
|
|||
/**
|
||||
* Creates a pane that will host the debugger.
|
||||
*
|
||||
* @param DebuggerUI aDebuggerUI
|
||||
* The parent instance creating the new debugger.
|
||||
* @param XULElement aTab
|
||||
* The tab in which to create the debugger.
|
||||
*/
|
||||
function DebuggerPane(aTab) {
|
||||
this._tab = aTab;
|
||||
|
||||
|
||||
this._initServer();
|
||||
this._create();
|
||||
}
|
||||
|
@ -181,7 +200,7 @@ DebuggerPane.prototype = {
|
|||
self._frame.addEventListener("unload", self.close, true);
|
||||
|
||||
// Bind shortcuts for accessing the breakpoint methods in the debugger.
|
||||
let bkp = self.debuggerWindow.DebuggerController.Breakpoints;
|
||||
let bkp = self.contentWindow.DebuggerController.Breakpoints;
|
||||
self.addBreakpoint = bkp.addBreakpoint;
|
||||
self.removeBreakpoint = bkp.removeBreakpoint;
|
||||
self.getBreakpoint = bkp.getBreakpoint;
|
||||
|
@ -216,7 +235,7 @@ DebuggerPane.prototype = {
|
|||
* Gets the debugger content window.
|
||||
* @return nsIDOMWindow if a debugger window exists, null otherwise
|
||||
*/
|
||||
get debuggerWindow() {
|
||||
get contentWindow() {
|
||||
return this._frame ? this._frame.contentWindow : null;
|
||||
},
|
||||
|
||||
|
@ -225,38 +244,115 @@ DebuggerPane.prototype = {
|
|||
* @return object if a debugger window exists, null otherwise
|
||||
*/
|
||||
get breakpoints() {
|
||||
let debuggerWindow = this.debuggerWindow;
|
||||
if (debuggerWindow) {
|
||||
return debuggerWindow.DebuggerController.Breakpoints.store;
|
||||
let contentWindow = this.contentWindow;
|
||||
if (contentWindow) {
|
||||
return contentWindow.DebuggerController.Breakpoints.store;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a process that will hold the remote debugger.
|
||||
* Creates a window that will host a remote debugger.
|
||||
*
|
||||
* @param DebuggerUI aDebuggerUI
|
||||
* The parent instance creating the new debugger.
|
||||
*/
|
||||
function RemoteDebuggerWindow(aDebuggerUI) {
|
||||
this._globalUI = aDebuggerUI;
|
||||
this._win = aDebuggerUI.chromeWindow;
|
||||
|
||||
this._create();
|
||||
}
|
||||
|
||||
RemoteDebuggerWindow.prototype = {
|
||||
|
||||
/**
|
||||
* Creates and initializes the widgets containing the remote debugger UI.
|
||||
*/
|
||||
_create: function DP__create() {
|
||||
this._win._remoteDebugger = this;
|
||||
|
||||
this._dbgwin = this._globalUI.chromeWindow.open(DBG_XUL,
|
||||
L10N.getStr("remoteDebuggerWindowTitle"),
|
||||
"width=" + DebuggerPreferences.remoteWinWidth + "," +
|
||||
"height=" + DebuggerPreferences.remoteWinHeight + "," +
|
||||
"chrome,dependent,resizable,centerscreen");
|
||||
|
||||
this._dbgwin._remoteFlag = true;
|
||||
|
||||
this.close = this.close.bind(this);
|
||||
let self = this;
|
||||
|
||||
this._dbgwin.addEventListener("Debugger:Loaded", function dbgLoaded() {
|
||||
self._dbgwin.removeEventListener("Debugger:Loaded", dbgLoaded, true);
|
||||
self._dbgwin.addEventListener("Debugger:Close", self.close, true);
|
||||
self._dbgwin.addEventListener("unload", self.close, true);
|
||||
|
||||
// Bind shortcuts for accessing the breakpoint methods in the debugger.
|
||||
let bkp = self.contentWindow.DebuggerController.Breakpoints;
|
||||
self.addBreakpoint = bkp.addBreakpoint;
|
||||
self.removeBreakpoint = bkp.removeBreakpoint;
|
||||
self.getBreakpoint = bkp.getBreakpoint;
|
||||
}, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Closes the remote debugger, along with the parent window if necessary.
|
||||
*/
|
||||
close: function DP_close() {
|
||||
if (!this._win) {
|
||||
return;
|
||||
}
|
||||
delete this._win._remoteDebugger;
|
||||
this._win = null;
|
||||
|
||||
this._dbgwin.close();
|
||||
this._dbgwin = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the remote debugger content window.
|
||||
* @return nsIDOMWindow if a debugger window exists, null otherwise.
|
||||
*/
|
||||
get contentWindow() {
|
||||
return this._dbgwin;
|
||||
},
|
||||
|
||||
/**
|
||||
* Shortcut for accessing the list of breakpoints in the remote debugger.
|
||||
* @return object if a debugger window exists, null otherwise.
|
||||
*/
|
||||
get breakpoints() {
|
||||
let contentWindow = this.contentWindow;
|
||||
if (contentWindow) {
|
||||
return contentWindow.DebuggerController.Breakpoints.store;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a process that will hold a chrome debugger.
|
||||
*
|
||||
* @param function aOnClose
|
||||
* Optional, a function called when the process exits.
|
||||
* @param function aOnRun
|
||||
* Optional, a function called when the process starts running.
|
||||
* @param boolean aInitServerFlag
|
||||
* True to initialize the server. This should happen only in the chrome
|
||||
* debugging case. This should also be true by default after bug #747429.
|
||||
* @param nsIDOMWindow aWindow
|
||||
* The chrome window for which the remote debugger instance is created.
|
||||
* The chrome window for which the debugger instance is created.
|
||||
*/
|
||||
function DebuggerProcess(aWindow, aOnClose, aOnRun, aInitServerFlag) {
|
||||
function ChromeDebuggerProcess(aWindow, aOnClose, aOnRun) {
|
||||
this._win = aWindow;
|
||||
this._closeCallback = aOnClose;
|
||||
this._runCallback = aOnRun;
|
||||
|
||||
aInitServerFlag && this._initServer();
|
||||
this._initServer();
|
||||
this._initProfile();
|
||||
this._create();
|
||||
}
|
||||
|
||||
DebuggerProcess.prototype = {
|
||||
ChromeDebuggerProcess.prototype = {
|
||||
|
||||
/**
|
||||
* Initializes the debugger server.
|
||||
|
@ -293,7 +389,7 @@ DebuggerProcess.prototype = {
|
|||
* Creates and initializes the profile & process for the remote debugger.
|
||||
*/
|
||||
_create: function RDP__create() {
|
||||
this._win._remoteDebugger = this;
|
||||
this._win._chromeDebugger = this;
|
||||
|
||||
let file = FileUtils.getFile("CurProcD",
|
||||
[Services.appinfo.OS == "WINNT" ? "firefox.exe"
|
||||
|
@ -323,7 +419,7 @@ DebuggerProcess.prototype = {
|
|||
if (!this._win) {
|
||||
return;
|
||||
}
|
||||
delete this._win._remoteDebugger;
|
||||
delete this._win._chromeDebugger;
|
||||
this._win = null;
|
||||
|
||||
if (this._dbgProcess.isRunning) {
|
||||
|
@ -341,6 +437,26 @@ DebuggerProcess.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Localization convenience methods.
|
||||
*/
|
||||
let L10N = {
|
||||
|
||||
/**
|
||||
* L10N shortcut function.
|
||||
*
|
||||
* @param string aName
|
||||
* @return string
|
||||
*/
|
||||
getStr: function L10N_getStr(aName) {
|
||||
return this.stringBundle.GetStringFromName(aName);
|
||||
}
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(L10N, "stringBundle", function() {
|
||||
return Services.strings.createBundle(DBG_STRINGS_URI);
|
||||
});
|
||||
|
||||
/**
|
||||
* Various debugger preferences.
|
||||
*/
|
||||
|
|
|
@ -87,6 +87,7 @@ let DebuggerController = {
|
|||
DebuggerView.StackFrames.initialize();
|
||||
DebuggerView.Properties.initialize();
|
||||
DebuggerView.Scripts.initialize();
|
||||
DebuggerView.showCloseButton(!this._isRemoteDebugger && !this._isChromeDebugger);
|
||||
|
||||
this.dispatchEvent("Debugger:Loaded");
|
||||
this._connect();
|
||||
|
@ -114,7 +115,48 @@ let DebuggerController = {
|
|||
|
||||
this.dispatchEvent("Debugger:Unloaded");
|
||||
this._disconnect();
|
||||
this._isRemote && this._quitApp();
|
||||
this._isChromeDebugger && this._quitApp();
|
||||
},
|
||||
|
||||
/**
|
||||
* Prepares the hostname and port number for a remote debugger connection
|
||||
* and handles connection retries and timeouts.
|
||||
*
|
||||
* @return boolean true if connection should proceed normally
|
||||
*/
|
||||
_prepareConnection: function DC__prepareConnection() {
|
||||
// If we exceeded the total number of connection retries, bail.
|
||||
if (this._remoteConnectionTry === Prefs.remoteConnectionRetries) {
|
||||
Services.prompt.alert(null,
|
||||
L10N.getStr("remoteDebuggerPromptTitle"),
|
||||
L10N.getStr("remoteDebuggerConnectionFailedMessage"));
|
||||
this.dispatchEvent("Debugger:Close");
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: This is ugly, need to rethink the design for the UI in #751677.
|
||||
if (!Prefs.remoteAutoConnect) {
|
||||
let prompt = new RemoteDebuggerPrompt();
|
||||
let result = prompt.show(!!this._remoteConnectionTimeout);
|
||||
if (!result) {
|
||||
this.dispatchEvent("Debugger:Close");
|
||||
return false;
|
||||
}
|
||||
Prefs.remoteHost = prompt.uri.host;
|
||||
Prefs.remotePort = prompt.uri.port;
|
||||
}
|
||||
|
||||
// If this debugger is connecting remotely to a server, we need to check
|
||||
// after a while if the connection actually succeeded.
|
||||
this._remoteConnectionTry = ++this._remoteConnectionTry || 1;
|
||||
this._remoteConnectionTimeout = window.setTimeout(function() {
|
||||
// If we couldn't connect to any server yet, try again...
|
||||
if (!DebuggerController.activeThread) {
|
||||
DebuggerController._connect();
|
||||
}
|
||||
}, Prefs.remoteTimeout);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -122,9 +164,15 @@ let DebuggerController = {
|
|||
* wiring event handlers as necessary.
|
||||
*/
|
||||
_connect: function DC__connect() {
|
||||
let transport =
|
||||
this._isRemote ? debuggerSocketConnect(Prefs.remoteHost, Prefs.remotePort)
|
||||
: DebuggerServer.connectPipe();
|
||||
if (this._isRemoteDebugger) {
|
||||
if (!this._prepareConnection()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let transport = (this._isChromeDebugger || this._isRemoteDebugger)
|
||||
? debuggerSocketConnect(Prefs.remoteHost, Prefs.remotePort)
|
||||
: DebuggerServer.connectPipe();
|
||||
|
||||
let client = this.client = new DebuggerClient(transport);
|
||||
|
||||
|
@ -223,8 +271,16 @@ let DebuggerController = {
|
|||
* Returns true if this is a remote debugger instance.
|
||||
* @return boolean
|
||||
*/
|
||||
get _isRemote() {
|
||||
return !window.parent.content;
|
||||
get _isRemoteDebugger() {
|
||||
return window._remoteFlag;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if this is a chrome debugger instance.
|
||||
* @return boolean
|
||||
*/
|
||||
get _isChromeDebugger() {
|
||||
return !window.parent.content && !this._isRemoteDebugger;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1325,7 +1381,29 @@ XPCOMUtils.defineLazyGetter(L10N, "stringBundle", function() {
|
|||
/**
|
||||
* Shortcuts for accessing various debugger preferences.
|
||||
*/
|
||||
let Prefs = {};
|
||||
let Prefs = {
|
||||
|
||||
/**
|
||||
* Gets a flag specifying if the the debugger should automatically connect to
|
||||
* the default host and port number.
|
||||
* @return boolean
|
||||
*/
|
||||
get remoteAutoConnect() {
|
||||
if (this._autoConn === undefined) {
|
||||
this._autoConn = Services.prefs.getBoolPref("devtools.debugger.remote-autoconnect");
|
||||
}
|
||||
return this._autoConn;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets a flag specifying if the the debugger should automatically connect.
|
||||
* @param boolean value
|
||||
*/
|
||||
set remoteAutoConnect(value) {
|
||||
Services.prefs.setBoolPref("devtools.debugger.remote-autoconnect", value);
|
||||
this._autoConn = value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the preferred default remote debugging host.
|
||||
|
@ -1343,6 +1421,22 @@ XPCOMUtils.defineLazyGetter(Prefs, "remotePort", function() {
|
|||
return Services.prefs.getIntPref("devtools.debugger.remote-port");
|
||||
});
|
||||
|
||||
/**
|
||||
* Gets the max number of attempts to reconnect to a remote server.
|
||||
* @return number
|
||||
*/
|
||||
XPCOMUtils.defineLazyGetter(Prefs, "remoteConnectionRetries", function() {
|
||||
return Services.prefs.getIntPref("devtools.debugger.remote-connection-retries");
|
||||
});
|
||||
|
||||
/**
|
||||
* Gets the remote debugging connection timeout (in milliseconds).
|
||||
* @return number
|
||||
*/
|
||||
XPCOMUtils.defineLazyGetter(Prefs, "remoteTimeout", function() {
|
||||
return Services.prefs.getIntPref("devtools.debugger.remote-timeout");
|
||||
});
|
||||
|
||||
/**
|
||||
* Preliminary setup for the DebuggerController object.
|
||||
*/
|
||||
|
|
|
@ -82,6 +82,61 @@ let DebuggerView = {
|
|||
*/
|
||||
_onEditorLoad: function DV__onEditorLoad() {
|
||||
DebuggerController.Breakpoints.initialize();
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the close button hidden or visible. It's hidden by default.
|
||||
* @param boolean aVisibleFlag
|
||||
*/
|
||||
showCloseButton: function DV_showCloseButton(aVisibleFlag) {
|
||||
document.getElementById("close").setAttribute("hidden", !aVisibleFlag);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A simple way of displaying a "Connect to..." prompt.
|
||||
*/
|
||||
function RemoteDebuggerPrompt() {
|
||||
|
||||
/**
|
||||
* The remote uri the user wants to connect to.
|
||||
*/
|
||||
this.uri = null;
|
||||
}
|
||||
|
||||
RemoteDebuggerPrompt.prototype = {
|
||||
|
||||
/**
|
||||
* Shows the prompt and sets the uri using the user input.
|
||||
*
|
||||
* @param boolean aIsReconnectingFlag
|
||||
* True to show the reconnect message instead.
|
||||
*/
|
||||
show: function RDP_show(aIsReconnectingFlag) {
|
||||
let check = { value: Prefs.remoteAutoConnect };
|
||||
let input = { value: "http://" + Prefs.remoteHost +
|
||||
":" + Prefs.remotePort + "/" };
|
||||
|
||||
while (true) {
|
||||
let result = Services.prompt.prompt(null,
|
||||
L10N.getStr("remoteDebuggerPromptTitle"),
|
||||
L10N.getStr(aIsReconnectingFlag
|
||||
? "remoteDebuggerReconnectMessage"
|
||||
: "remoteDebuggerPromptMessage"), input,
|
||||
L10N.getStr("remoteDebuggerPromptCheck"), check);
|
||||
|
||||
Prefs.remoteAutoConnect = check.value;
|
||||
|
||||
try {
|
||||
let uri = Services.io.newURI(input.value, null, null);
|
||||
let url = uri.QueryInterface(Ci.nsIURL);
|
||||
|
||||
// If a url could be successfully retrieved, then the uri is correct.
|
||||
this.uri = uri;
|
||||
return result;
|
||||
}
|
||||
catch(e) { }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
|
||||
<div id="body" class="vbox flex">
|
||||
<xul:toolbar id="dbg-toolbar">
|
||||
<xul:button id="close">&debuggerUI.closeButton;</xul:button>
|
||||
<xul:button id="close" hidden="false">&debuggerUI.closeButton;</xul:button>
|
||||
<xul:button id="resume"/>
|
||||
<xul:button id="step-over">&debuggerUI.stepOverButton;</xul:button>
|
||||
<xul:button id="step-in">&debuggerUI.stepInButton;</xul:button>
|
||||
|
|
|
@ -47,6 +47,7 @@ include $(topsrcdir)/config/rules.mk
|
|||
|
||||
_BROWSER_TEST_FILES = \
|
||||
browser_dbg_createRemote.js \
|
||||
browser_dbg_createChrome.js \
|
||||
browser_dbg_debuggerstatement.js \
|
||||
browser_dbg_listtabs.js \
|
||||
browser_dbg_tabactor-01.js \
|
||||
|
|
|
@ -30,7 +30,7 @@ function test()
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
resumed = true;
|
||||
|
||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
||||
|
|
|
@ -28,7 +28,7 @@ function test()
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
resumed = true;
|
||||
|
||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
||||
|
|
|
@ -15,7 +15,7 @@ function test() {
|
|||
debug_tab_pane(DEBUGGER_TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
gTab = aTab;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testCleanExit();
|
||||
});
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests that a chrome debugger can be created in a new process.
|
||||
|
||||
var gProcess = null;
|
||||
var gTab = null;
|
||||
var gDebuggee = null;
|
||||
|
||||
function test() {
|
||||
debug_chrome(STACK_URL, aOnClosing, function(aTab, aDebuggee, aProcess) {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gProcess = aProcess;
|
||||
|
||||
testSimpleCall();
|
||||
});
|
||||
}
|
||||
|
||||
function testSimpleCall() {
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
ok(gProcess._dbgProcess,
|
||||
"The remote debugger process wasn't created properly!");
|
||||
ok(gProcess._dbgProcess.isRunning,
|
||||
"The remote debugger process isn't running!");
|
||||
is(typeof gProcess._dbgProcess.pid, "number",
|
||||
"The remote debugger process doesn't have a pid (?!)");
|
||||
|
||||
info("process location: " + gProcess._dbgProcess.location);
|
||||
info("process pid: " + gProcess._dbgProcess.pid);
|
||||
info("process name: " + gProcess._dbgProcess.processName);
|
||||
info("process sig: " + gProcess._dbgProcess.processSignature);
|
||||
|
||||
ok(gProcess._dbgProfile,
|
||||
"The remote debugger profile wasn't created properly!");
|
||||
ok(gProcess._dbgProfile.localDir,
|
||||
"The remote debugger profile doesn't have a localDir...");
|
||||
ok(gProcess._dbgProfile.rootDir,
|
||||
"The remote debugger profile doesn't have a rootDir...");
|
||||
ok(gProcess._dbgProfile.name,
|
||||
"The remote debugger profile doesn't have a name...");
|
||||
|
||||
info("profile localDir: " + gProcess._dbgProfile.localDir);
|
||||
info("profile rootDir: " + gProcess._dbgProfile.rootDir);
|
||||
info("profile name: " + gProcess._dbgProfile.name);
|
||||
|
||||
let profileService = Cc["@mozilla.org/toolkit/profile-service;1"]
|
||||
.createInstance(Ci.nsIToolkitProfileService);
|
||||
|
||||
let profile = profileService.getProfileByName(gProcess._dbgProfile.name);
|
||||
|
||||
ok(profile,
|
||||
"The remote debugger profile wasn't *actually* created properly!");
|
||||
is(profile.localDir.path, gProcess._dbgProfile.localDir.path,
|
||||
"The remote debugger profile doesn't have the correct localDir!");
|
||||
is(profile.rootDir.path, gProcess._dbgProfile.rootDir.path,
|
||||
"The remote debugger profile doesn't have the correct rootDir!");
|
||||
|
||||
DebuggerUI.toggleChromeDebugger();
|
||||
}}, 0);
|
||||
}
|
||||
|
||||
function aOnClosing() {
|
||||
ok(!gProcess._dbgProcess.isRunning,
|
||||
"The remote debugger process isn't closed as it should be!");
|
||||
is(gProcess._dbgProcess.exitValue, (Services.appinfo.OS == "WINNT" ? 0 : 256),
|
||||
"The remote debugger process didn't die cleanly.");
|
||||
|
||||
info("process exit value: " + gProcess._dbgProcess.exitValue);
|
||||
|
||||
info("profile localDir: " + gProcess._dbgProfile.localDir.path);
|
||||
info("profile rootDir: " + gProcess._dbgProfile.rootDir.path);
|
||||
info("profile name: " + gProcess._dbgProfile.name);
|
||||
|
||||
executeSoon(function() {
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
removeTab(gTab);
|
||||
gProcess = null;
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
});
|
|
@ -1,86 +1,80 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
var gProcess = null;
|
||||
|
||||
// Tests that a remote debugger can be created in a new window.
|
||||
|
||||
var gWindow = null;
|
||||
var gTab = null;
|
||||
var gDebuggee = null;
|
||||
var gAutoConnect = null;
|
||||
|
||||
const TEST_URL = EXAMPLE_URL + "browser_dbg_iframes.html";
|
||||
|
||||
function test() {
|
||||
remote_debug_tab_pane(STACK_URL, aOnClosing, function(aTab, aDebuggee, aProcess) {
|
||||
debug_remote(TEST_URL, function(aTab, aDebuggee, aWindow) {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gProcess = aProcess;
|
||||
gWindow = aWindow;
|
||||
let gDebugger = gWindow.contentWindow;
|
||||
|
||||
testSimpleCall();
|
||||
});
|
||||
}
|
||||
is(gDebugger.document.getElementById("close").getAttribute("hidden"), "true",
|
||||
"The close button should be hidden in a remote debugger.");
|
||||
|
||||
function testSimpleCall() {
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
is(gDebugger.DebuggerController.activeThread.paused, false,
|
||||
"Should be running after debug_remote.");
|
||||
|
||||
ok(gProcess._dbgProcess,
|
||||
"The remote debugger process wasn't created properly!");
|
||||
ok(gProcess._dbgProcess.isRunning,
|
||||
"The remote debugger process isn't running!");
|
||||
is(typeof gProcess._dbgProcess.pid, "number",
|
||||
"The remote debugger process doesn't have a pid (?!)");
|
||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
info("process location: " + gProcess._dbgProcess.location);
|
||||
info("process pid: " + gProcess._dbgProcess.pid);
|
||||
info("process name: " + gProcess._dbgProcess.processName);
|
||||
info("process sig: " + gProcess._dbgProcess.processSignature);
|
||||
let frames = gDebugger.DebuggerView.StackFrames._frames;
|
||||
let childNodes = frames.childNodes;
|
||||
|
||||
ok(gProcess._dbgProfile,
|
||||
"The remote debugger profile wasn't created properly!");
|
||||
ok(gProcess._dbgProfile.localDir,
|
||||
"The remote debugger profile doesn't have a localDir...");
|
||||
ok(gProcess._dbgProfile.rootDir,
|
||||
"The remote debugger profile doesn't have a rootDir...");
|
||||
ok(gProcess._dbgProfile.name,
|
||||
"The remote debugger profile doesn't have a name...");
|
||||
is(gDebugger.DebuggerController.activeThread.paused, true,
|
||||
"Should be paused after an interrupt request.");
|
||||
|
||||
info("profile localDir: " + gProcess._dbgProfile.localDir);
|
||||
info("profile rootDir: " + gProcess._dbgProfile.rootDir);
|
||||
info("profile name: " + gProcess._dbgProfile.name);
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 1,
|
||||
"Should have one frame in the stack.");
|
||||
|
||||
let profileService = Cc["@mozilla.org/toolkit/profile-service;1"]
|
||||
.createInstance(Ci.nsIToolkitProfileService);
|
||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("resumed", function() {
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
closeDebuggerAndFinish(gTab, true);
|
||||
}}, 0);
|
||||
});
|
||||
|
||||
let profile = profileService.getProfileByName(gProcess._dbgProfile.name);
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
gDebugger.document.getElementById("resume"),
|
||||
gDebugger);
|
||||
}}, 0);
|
||||
});
|
||||
|
||||
ok(profile,
|
||||
"The remote debugger profile wasn't *actually* created properly!");
|
||||
is(profile.localDir.path, gProcess._dbgProfile.localDir.path,
|
||||
"The remote debugger profile doesn't have the correct localDir!");
|
||||
is(profile.rootDir.path, gProcess._dbgProfile.rootDir.path,
|
||||
"The remote debugger profile doesn't have the correct rootDir!");
|
||||
let iframe = gTab.linkedBrowser.contentWindow.wrappedJSObject.frames[0];
|
||||
|
||||
DebuggerUI.toggleRemoteDebugger();
|
||||
}}, 0);
|
||||
}
|
||||
is(iframe.document.title, "Browser Debugger Test Tab", "Found the iframe");
|
||||
|
||||
function aOnClosing() {
|
||||
ok(!gProcess._dbgProcess.isRunning,
|
||||
"The remote debugger process isn't closed as it should be!");
|
||||
is(gProcess._dbgProcess.exitValue, (Services.appinfo.OS == "WINNT" ? 0 : 256),
|
||||
"The remote debugger process didn't die cleanly.");
|
||||
iframe.runDebuggerStatement();
|
||||
},
|
||||
function beforeTabAdded() {
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
DebuggerServer.closeListener();
|
||||
|
||||
info("process exit value: " + gProcess._dbgProcess.exitValue);
|
||||
gAutoConnect = Services.prefs.getBoolPref("devtools.debugger.remote-autoconnect");
|
||||
Services.prefs.setBoolPref("devtools.debugger.remote-autoconnect", true);
|
||||
|
||||
info("profile localDir: " + gProcess._dbgProfile.localDir.path);
|
||||
info("profile rootDir: " + gProcess._dbgProfile.rootDir.path);
|
||||
info("profile name: " + gProcess._dbgProfile.name);
|
||||
|
||||
executeSoon(function() {
|
||||
finish();
|
||||
// Open the listener at some point in the future to test automatic reconnect.
|
||||
window.setTimeout(function() {
|
||||
DebuggerServer.openListener(
|
||||
Services.prefs.getIntPref("devtools.debugger.remote-port"));
|
||||
}, Math.random() * 1000);
|
||||
});
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.setBoolPref("devtools.debugger.remote-autoconnect", gAutoConnect);
|
||||
removeTab(gTab);
|
||||
gProcess = null;
|
||||
gWindow = null;
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gAutoConnect = null;
|
||||
});
|
||||
|
|
|
@ -15,7 +15,7 @@ function test() {
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testAnonCall();
|
||||
});
|
||||
|
|
|
@ -14,7 +14,10 @@ function test() {
|
|||
debug_tab_pane(TEST_URL, function(aTab, aDebuggee, aPane) {
|
||||
gTab = aTab;
|
||||
gPane = aPane;
|
||||
let gDebugger = gPane.debuggerWindow;
|
||||
let gDebugger = gPane.contentWindow;
|
||||
|
||||
is(gDebugger.document.getElementById("close").getAttribute("hidden"), "false",
|
||||
"The close button should be visible in a normal content debugger.");
|
||||
|
||||
is(gDebugger.DebuggerController.activeThread.paused, false,
|
||||
"Should be running after debug_tab_pane.");
|
||||
|
|
|
@ -17,7 +17,7 @@ function test()
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testSimpleCall();
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@ function test() {
|
|||
debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
|
||||
gTab = aTab;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testPause();
|
||||
});
|
||||
|
|
|
@ -13,7 +13,7 @@ function test() {
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testSimpleCall();
|
||||
});
|
||||
|
|
|
@ -13,7 +13,7 @@ function test() {
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testSimpleCall();
|
||||
});
|
||||
|
|
|
@ -13,7 +13,7 @@ function test() {
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testSimpleCall();
|
||||
});
|
||||
|
|
|
@ -13,7 +13,7 @@ function test() {
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testSimpleCall();
|
||||
});
|
||||
|
|
|
@ -13,7 +13,7 @@ function test() {
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testSimpleCall();
|
||||
});
|
||||
|
|
|
@ -13,7 +13,7 @@ function test() {
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testSimpleCall();
|
||||
});
|
||||
|
@ -25,6 +25,9 @@ function testSimpleCall() {
|
|||
|
||||
let globalScope = gDebugger.DebuggerView.Properties.globalScope;
|
||||
let localScope = gDebugger.DebuggerView.Properties.localScope;
|
||||
globalScope.empty();
|
||||
localScope.empty();
|
||||
|
||||
let windowVar = globalScope.addVar("window");
|
||||
let documentVar = globalScope.addVar("document");
|
||||
let localVar0 = localScope.addVar("localVariable");
|
||||
|
@ -79,10 +82,18 @@ function testSimpleCall() {
|
|||
ok(localVar5, "The localVar5 hasn't been created correctly.");
|
||||
|
||||
|
||||
for each (let elt in globalScope.querySelector(".details").childNodes) {
|
||||
info("globalScope :: " + {
|
||||
id: elt.id, className: elt.className }.toSource());
|
||||
}
|
||||
is(globalScope.querySelector(".details").childNodes.length, 2,
|
||||
"The globalScope doesn't contain all the created variable elements.");
|
||||
|
||||
is(localScope.querySelector(".details").childNodes.length, 7,
|
||||
for each (let elt in localScope.querySelector(".details").childNodes) {
|
||||
info("localScope :: " + {
|
||||
id: elt.id, className: elt.className }.toSource());
|
||||
}
|
||||
is(localScope.querySelector(".details").childNodes.length, 6,
|
||||
"The localScope doesn't contain all the created variable elements.");
|
||||
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ function test()
|
|||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
gTab = aTab;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testFrameParameters();
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ function test()
|
|||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
gTab = aTab;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testFrameParameters();
|
||||
});
|
||||
|
|
|
@ -25,7 +25,7 @@ function test()
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
resumed = true;
|
||||
|
||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
||||
|
|
|
@ -20,7 +20,7 @@ function test()
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
||||
framesAdded = true;
|
||||
|
|
|
@ -22,7 +22,7 @@ function test()
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
||||
framesAdded = true;
|
||||
|
|
|
@ -13,7 +13,7 @@ function test() {
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testSimpleCall();
|
||||
});
|
||||
|
|
|
@ -24,7 +24,7 @@ function test()
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testSelectLine();
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@ function test() {
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testSimpleCall();
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@ function test() {
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testEvalCall();
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@ function test() {
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testRecurse();
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@ function test() {
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testEvalCallResume();
|
||||
});
|
||||
|
|
|
@ -22,7 +22,7 @@ function test() {
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
||||
framesAdded = true;
|
||||
|
|
|
@ -29,7 +29,7 @@ function test()
|
|||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.debuggerWindow;
|
||||
gDebugger = gPane.contentWindow;
|
||||
resumed = true;
|
||||
|
||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
||||
|
|
|
@ -49,12 +49,16 @@ function removeTab(aTab) {
|
|||
gBrowser.removeTab(aTab);
|
||||
}
|
||||
|
||||
function closeDebuggerAndFinish(aTab) {
|
||||
function closeDebuggerAndFinish(aTab, aRemoteFlag) {
|
||||
DebuggerUI.chromeWindow.addEventListener("Debugger:Shutdown", function cleanup() {
|
||||
DebuggerUI.chromeWindow.removeEventListener("Debugger:Shutdown", cleanup, false);
|
||||
finish();
|
||||
}, false);
|
||||
DebuggerUI.getDebugger(aTab).close();
|
||||
if (!aRemoteFlag) {
|
||||
DebuggerUI.getDebugger(aTab).close();
|
||||
} else {
|
||||
DebuggerUI.getRemoteDebugger().close();
|
||||
}
|
||||
}
|
||||
|
||||
function get_tab_actor_for_url(aClient, aURL, aCallback) {
|
||||
|
@ -99,20 +103,41 @@ function debug_tab_pane(aURL, aOnDebugging)
|
|||
pane._frame.removeEventListener("Debugger:Connecting", dbgConnected, true);
|
||||
|
||||
// Wait for the initial resume...
|
||||
pane.debuggerWindow.gClient.addOneTimeListener("resumed", function() {
|
||||
pane.contentWindow.gClient.addOneTimeListener("resumed", function() {
|
||||
aOnDebugging(tab, debuggee, pane);
|
||||
});
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
|
||||
function remote_debug_tab_pane(aURL, aOnClosing, aOnDebugging)
|
||||
function debug_remote(aURL, aOnDebugging, aBeforeTabAdded)
|
||||
{
|
||||
// Make any necessary preparations (start the debugger server etc.)
|
||||
aBeforeTabAdded();
|
||||
|
||||
let tab = addTab(aURL, function() {
|
||||
gBrowser.selectedTab = gTab;
|
||||
let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
|
||||
|
||||
let win = DebuggerUI.toggleRemoteDebugger();
|
||||
win._dbgwin.addEventListener("Debugger:Connecting", function dbgConnected() {
|
||||
win._dbgwin.removeEventListener("Debugger:Connecting", dbgConnected, true);
|
||||
|
||||
// Wait for the initial resume...
|
||||
win.contentWindow.gClient.addOneTimeListener("resumed", function() {
|
||||
aOnDebugging(tab, debuggee, win);
|
||||
});
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
|
||||
function debug_chrome(aURL, aOnClosing, aOnDebugging)
|
||||
{
|
||||
let tab = addTab(aURL, function() {
|
||||
gBrowser.selectedTab = gTab;
|
||||
let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
|
||||
|
||||
DebuggerUI.toggleRemoteDebugger(aOnClosing, function dbgRan(process) {
|
||||
DebuggerUI.toggleChromeDebugger(aOnClosing, function dbgRan(process) {
|
||||
|
||||
// Wait for the remote debugging process to start...
|
||||
aOnDebugging(tab, debuggee, process);
|
||||
|
|
|
@ -61,6 +61,7 @@ Cu.import("resource://gre/modules/NetUtil.jsm");
|
|||
Cu.import("resource:///modules/PropertyPanel.jsm");
|
||||
Cu.import("resource:///modules/source-editor.jsm");
|
||||
Cu.import("resource:///modules/devtools/scratchpad-manager.jsm");
|
||||
Cu.import("resource://gre/modules/jsdebugger.jsm");
|
||||
|
||||
|
||||
const SCRATCHPAD_CONTEXT_CONTENT = 1;
|
||||
|
@ -295,6 +296,7 @@ var Scratchpad = {
|
|||
this._chromeSandbox = new Cu.Sandbox(this.browserWindow,
|
||||
{ sandboxPrototype: this.browserWindow, wantXrays: false,
|
||||
sandboxName: 'scratchpad-chrome'});
|
||||
addDebuggerToGlobal(this._chromeSandbox);
|
||||
|
||||
this._previousBrowserWindow = this.browserWindow;
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ gcli.addCommand({
|
|||
let dbg = win.DebuggerUI.getDebugger(win.gBrowser.selectedTab);
|
||||
let files = [];
|
||||
if (dbg) {
|
||||
let scriptsView = dbg.debuggerWindow.DebuggerView.Scripts;
|
||||
let scriptsView = dbg.contentWindow.DebuggerView.Scripts;
|
||||
for each (let script in scriptsView.scriptLocations) {
|
||||
files.push(script);
|
||||
}
|
||||
|
|
|
@ -73,8 +73,8 @@ function testCreateCommands() {
|
|||
pane._frame.removeEventListener("Debugger:Connecting", dbgConnected, true);
|
||||
|
||||
// Wait for the initial resume.
|
||||
pane.debuggerWindow.gClient.addOneTimeListener("resumed", function() {
|
||||
pane.debuggerWindow.gClient.activeThread.addOneTimeListener("framesadded", function() {
|
||||
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();
|
||||
|
@ -83,7 +83,7 @@ function testCreateCommands() {
|
|||
is(requisition.getStatus().toString(), "VALID", "break list is VALID");
|
||||
requisition.exec();
|
||||
|
||||
pane.debuggerWindow.gClient.activeThread.resume(function() {
|
||||
pane.contentWindow.gClient.activeThread.resume(function() {
|
||||
type("break del 0");
|
||||
is(requisition.getStatus().toString(), "VALID", "break del 0 is VALID");
|
||||
requisition.exec();
|
||||
|
|
|
@ -114,6 +114,10 @@ ifdef MOZ_JSDEBUGGER
|
|||
DEFINES += -DMOZ_JSDEBUGGER
|
||||
endif
|
||||
|
||||
ifdef NECKO_WIFI
|
||||
DEFINES += -DNECKO_WIFI
|
||||
endif
|
||||
|
||||
ifdef MOZ_PKG_MANIFEST_P
|
||||
MOZ_PKG_MANIFEST = package-manifest
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
<!-- LOCALIZATION NOTE (chromeDebuggerMenu.label): This is the label for the
|
||||
- application menu item that opens the browser debugger UI. -->
|
||||
<!ENTITY chromeDebuggerMenu.label "Browser Debugger">
|
||||
<!ENTITY chromeDebuggerMenu.label "Browser Debugger">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerMenu.commandkey): This is the command key that
|
||||
- launches the debugger UI. Do not translate this one! -->
|
||||
|
|
|
@ -6,6 +6,30 @@
|
|||
# A good criteria is the language in which you'd find the best
|
||||
# documentation on web development on the web.
|
||||
|
||||
# LOCALIZATION NOTE (remoteDebuggerWindowTitle): The title displayed for the
|
||||
# remote debugger window.
|
||||
remoteDebuggerWindowTitle=Remote Debugger
|
||||
|
||||
# LOCALIZATION NOTE (remoteDebuggerPromptTitle): The title displayed on the
|
||||
# debugger prompt asking for the remote host and port to connect to.
|
||||
remoteDebuggerPromptTitle=Remote Connection
|
||||
|
||||
# LOCALIZATION NOTE (remoteDebuggerPromptMessage): The message displayed on the
|
||||
# debugger prompt asking for the remote host and port to connect to.
|
||||
remoteDebuggerPromptMessage=Enter hostname and port number (host:port)
|
||||
|
||||
# LOCALIZATION NOTE (remoteDebuggerPromptCheck): The message displayed on the
|
||||
# debugger prompt asking if the prompt should be shown again next time.
|
||||
remoteDebuggerPromptCheck=Don't ask me again
|
||||
|
||||
# LOCALIZATION NOTE (remoteDebuggerReconnectMessage): The message displayed on the
|
||||
# debugger prompt asking for the remote host and port to connect to.
|
||||
remoteDebuggerReconnectMessage=Server not found. Try again? (host:port)
|
||||
|
||||
# LOCALIZATION NOTE (remoteDebuggerReconnectMessage): The message displayed on the
|
||||
# debugger prompt asking for the remote host and port to connect to.
|
||||
remoteDebuggerConnectionFailedMessage=Could not find a server at the specified hostname and port number.
|
||||
|
||||
# LOCALIZATION NOTE (pauseLabel): The label that is displayed on the pause
|
||||
# button when the debugger is in a running state.
|
||||
pauseLabel=Pause
|
||||
|
|
Двоичные данные
browser/themes/gnomestripe/actionicon-tab.png
Двоичные данные
browser/themes/gnomestripe/actionicon-tab.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 293 B После Ширина: | Высота: | Размер: 244 B |
|
@ -1069,6 +1069,7 @@ toolbar[iconsize="small"] #feed-button {
|
|||
padding: 1px;
|
||||
margin: -1px;
|
||||
-moz-margin-end: 0;
|
||||
font-size: .9em;
|
||||
}
|
||||
|
||||
#identity-box:-moz-locale-dir(ltr) {
|
||||
|
@ -1093,9 +1094,19 @@ toolbar[iconsize="small"] #feed-button {
|
|||
|
||||
#identity-box.verifiedIdentity {
|
||||
background-color: #fff;
|
||||
color: hsl(92,81%,16%);
|
||||
-moz-border-end: 1px solid hsla(92,81%,16%,.2);
|
||||
color: hsl(92,100%,30%);
|
||||
-moz-margin-end: 4px;
|
||||
background-image: -moz-linear-gradient(hsla(92,81%,16%,0),
|
||||
hsla(92,81%,16%,.2) 25%,
|
||||
hsla(92,81%,16%,.2) 75%,
|
||||
hsla(92,81%,16%,0));
|
||||
background-position: right;
|
||||
background-size: 1px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#identity-box.verifiedIdentity:-moz-locale-dir(rtl) {
|
||||
background-position: left;
|
||||
}
|
||||
|
||||
/* Identity popup icons */
|
||||
|
@ -1335,6 +1346,7 @@ toolbar[iconsize="small"] #feed-button {
|
|||
|
||||
richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-icon {
|
||||
list-style-image: url("chrome://browser/skin/actionicon-tab.png");
|
||||
padding: 0 3px;
|
||||
}
|
||||
|
||||
.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {
|
||||
|
@ -1730,7 +1742,7 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
|||
|
||||
.alltabs-item[tabIsVisible] {
|
||||
/* box-shadow instead of background-color to work around native styling */
|
||||
box-shadow: inset 0 0 0 2em hsla(0,0%,50%,.15);
|
||||
box-shadow: inset -5px 0 ThreeDShadow;
|
||||
}
|
||||
|
||||
/* Sidebar */
|
||||
|
|
Двоичные данные
browser/themes/pinstripe/actionicon-tab.png
Двоичные данные
browser/themes/pinstripe/actionicon-tab.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 293 B После Ширина: | Высота: | Размер: 649 B |
|
@ -980,6 +980,7 @@ toolbar[mode="icons"] #zoom-in-button {
|
|||
padding-bottom: 1px;
|
||||
-moz-padding-start: 4px;
|
||||
-moz-padding-end: 0;
|
||||
font-size: .9em;
|
||||
}
|
||||
|
||||
#identity-box:-moz-locale-dir(ltr) {
|
||||
|
@ -1025,9 +1026,19 @@ toolbar[mode="icons"] #zoom-in-button {
|
|||
}
|
||||
|
||||
#identity-box.verifiedIdentity {
|
||||
color: hsl(92,100%,20%);
|
||||
-moz-border-end: 1px solid hsla(92,81%,16%,.2);
|
||||
color: hsl(92,100%,30%);
|
||||
-moz-padding-end: 4px;
|
||||
background-image: -moz-linear-gradient(hsla(92,81%,16%,0),
|
||||
hsla(92,81%,16%,.2) 25%,
|
||||
hsla(92,81%,16%,.2) 75%,
|
||||
hsla(92,81%,16%,0));
|
||||
background-position: right;
|
||||
background-size: 1px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#identity-box.verifiedIdentity:-moz-locale-dir(rtl) {
|
||||
background-position: left;
|
||||
}
|
||||
|
||||
#identity-box:-moz-focusring {
|
||||
|
@ -1170,6 +1181,20 @@ richlistitem[selected="true"][current="true"] > hbox > .ac-result-type-bookmark,
|
|||
|
||||
richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-icon {
|
||||
list-style-image: url("chrome://browser/skin/actionicon-tab.png");
|
||||
-moz-image-region: rect(0, 16px, 16px, 0);
|
||||
padding: 0 3px;
|
||||
}
|
||||
|
||||
richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-box > .ac-action-icon {
|
||||
-moz-image-region: rect(16px, 16px, 32px, 0);
|
||||
}
|
||||
|
||||
window[tabsontop="false"] richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-icon {
|
||||
-moz-image-region: rect(0, 32px, 16px, 16px);
|
||||
}
|
||||
|
||||
window[tabsontop="false"] richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-box > .ac-action-icon {
|
||||
-moz-image-region: rect(16px, 32px, 32px, 16px);
|
||||
}
|
||||
|
||||
.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {
|
||||
|
@ -2171,7 +2196,7 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
|||
|
||||
.alltabs-item[tabIsVisible] {
|
||||
/* box-shadow instead of background-color to work around native styling */
|
||||
box-shadow: inset 0 0 0 2em hsla(0,0%,50%,.15);
|
||||
box-shadow: inset -5px 0 ThreeDShadow;
|
||||
}
|
||||
|
||||
/* Tabstrip close button */
|
||||
|
|
Двоичные данные
browser/themes/winstripe/actionicon-tab.png
Двоичные данные
browser/themes/winstripe/actionicon-tab.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 293 B После Ширина: | Высота: | Размер: 434 B |
|
@ -1359,6 +1359,7 @@ html|*.urlbar-input:-moz-lwtheme:-moz-placeholder,
|
|||
|
||||
#identity-box {
|
||||
padding: 2px;
|
||||
font-size: .9em;
|
||||
}
|
||||
|
||||
#identity-box:-moz-locale-dir(ltr) {
|
||||
|
@ -1406,9 +1407,19 @@ html|*.urlbar-input:-moz-lwtheme:-moz-placeholder,
|
|||
}
|
||||
|
||||
#identity-box.verifiedIdentity {
|
||||
color: hsl(92,100%,20%);
|
||||
-moz-border-end: 1px solid hsla(92,81%,16%,.2);
|
||||
color: hsl(92,100%,30%);
|
||||
-moz-margin-end: 4px;
|
||||
background-image: -moz-linear-gradient(hsla(92,81%,16%,0),
|
||||
hsla(92,81%,16%,.2) 25%,
|
||||
hsla(92,81%,16%,.2) 75%,
|
||||
hsla(92,81%,16%,0));
|
||||
background-position: right;
|
||||
background-size: 1px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#identity-box.verifiedIdentity:-moz-locale-dir(rtl) {
|
||||
background-position: left;
|
||||
}
|
||||
|
||||
#identity-box.verifiedIdentity:not(:-moz-lwtheme) {
|
||||
|
@ -1536,6 +1547,12 @@ html|*.urlbar-input:-moz-lwtheme:-moz-placeholder,
|
|||
|
||||
richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-icon {
|
||||
list-style-image: url("chrome://browser/skin/actionicon-tab.png");
|
||||
-moz-image-region: rect(0, 16px, 16px, 0);
|
||||
padding: 0 3px;
|
||||
}
|
||||
|
||||
richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-box > .ac-action-icon {
|
||||
-moz-image-region: rect(16px, 16px, 32px, 0);
|
||||
}
|
||||
|
||||
.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {
|
||||
|
@ -2069,7 +2086,7 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
|||
|
||||
.alltabs-item[tabIsVisible] {
|
||||
/* box-shadow instead of background-color to work around native styling */
|
||||
box-shadow: inset 0 0 0 2em hsla(0,0%,50%,.15);
|
||||
box-shadow: inset -5px 0 ThreeDShadow;
|
||||
}
|
||||
|
||||
/* Tabstrip close button */
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче