Merge mozilla-central to tracemonkey.

This commit is contained in:
Chris Leary 2011-06-06 09:41:22 -07:00
Родитель fd209390e5 1685509a2e
Коммит b1d3530553
1770 изменённых файлов: 76756 добавлений и 44463 удалений

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

@ -63,3 +63,6 @@ a71bd564ebf5bf4f93d13e84114f759c263130b0 MOBILE_MERGE_DONE
a71bd564ebf5bf4f93d13e84114f759c263130b0 MOBILE_MERGE_DONE_20110406
a95d426422816513477e5863add1b00ac7041dcb AURORA_BASE_20110412
138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R14
9eae975b3d6fb7748fe5a3c0113d449b1c7cc0b2 AURORA_BASE_20110524
138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R14
462c726144bc1fb45b61e774f64ac5d61b4e047c UPDATE_PACKAGING_R14

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

@ -477,7 +477,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eSwitchAction,
eNoLiveAttr,
kNoReqStates
kNoReqStates,
eARIASelectable
},
{
"tablist",

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

@ -55,9 +55,6 @@
#include "nsIDOMCSSPrimitiveValue.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
#include "nsIDOMHTMLDocument.h"
#include "nsIDOMHTMLElement.h"
#include "nsIDOMNSDocument.h"
#include "nsIDOMNSHTMLElement.h"
#include "nsIDOMWindow.h"
#include "nsPIDOMWindow.h"
@ -135,6 +132,12 @@ void nsAccessNode::LastRelease()
////////////////////////////////////////////////////////////////////////////////
// nsAccessNode public
bool
nsAccessNode::IsDefunct() const
{
return !mContent;
}
PRBool
nsAccessNode::Init()
{

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

@ -120,11 +120,6 @@ public:
*/
already_AddRefed<nsINode> GetCurrentFocus();
/**
* Returns true when the accessible is defunct.
*/
virtual PRBool IsDefunct() { return !mContent; }
/**
* Initialize the access node object, add it to the cache.
*/
@ -135,6 +130,11 @@ public:
*/
virtual void Shutdown();
/**
* Returns true when the accessible is defunct.
*/
virtual bool IsDefunct() const;
/**
* Return frame for the given access node object.
*/

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

@ -107,7 +107,6 @@
#include "mozilla/FunctionTimer.h"
#include "mozilla/dom/Element.h"
#include "nsImageMapUtils.h"
////////////////////////////////////////////////////////////////////////////////
// nsAccessibilityService
@ -275,8 +274,10 @@ nsAccessibilityService::CreateHTMLImageAccessible(nsIContent* aContent,
aContent->GetAttr(kNameSpaceID_None,
nsAccessibilityAtoms::usemap,
mapElmName);
nsCOMPtr<nsIDOMHTMLMapElement> mapElm =
nsImageMapUtils::FindImageMap(aContent->GetCurrentDoc(), mapElmName);
nsCOMPtr<nsIDOMHTMLMapElement> mapElm;
if (nsIDocument* document = aContent->GetCurrentDoc()) {
mapElm = do_QueryInterface(document->FindImageMap(mapElmName));
}
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aPresShell));
nsAccessible* accessible = mapElm ?

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

@ -75,6 +75,7 @@
#include "nsIForm.h"
#include "nsIFormControl.h"
#include "nsLayoutUtils.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsIFrame.h"
@ -88,8 +89,6 @@
#include "nsReadableUtils.h"
#include "prdtoa.h"
#include "nsIAtom.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsIURI.h"
#include "nsArrayUtils.h"
#include "nsIMutableArray.h"
@ -105,6 +104,9 @@
#endif
#include "mozilla/unused.h"
#include "mozilla/Preferences.h"
using namespace mozilla;
////////////////////////////////////////////////////////////////////////////////
@ -338,22 +340,14 @@ nsAccessible::Description(nsString& aDescription)
static PRInt32
GetAccessModifierMask(nsIContent* aContent)
{
nsCOMPtr<nsIPrefBranch> prefBranch =
do_GetService(NS_PREFSERVICE_CONTRACTID);
if (!prefBranch)
return 0;
// use ui.key.generalAccessKey (unless it is -1)
PRInt32 accessKey;
nsresult rv = prefBranch->GetIntPref("ui.key.generalAccessKey", &accessKey);
if (NS_SUCCEEDED(rv) && accessKey != -1) {
switch (accessKey) {
case nsIDOMKeyEvent::DOM_VK_SHIFT: return NS_MODIFIER_SHIFT;
case nsIDOMKeyEvent::DOM_VK_CONTROL: return NS_MODIFIER_CONTROL;
case nsIDOMKeyEvent::DOM_VK_ALT: return NS_MODIFIER_ALT;
case nsIDOMKeyEvent::DOM_VK_META: return NS_MODIFIER_META;
default: return 0;
}
switch (Preferences::GetInt("ui.key.generalAccessKey", -1)) {
case -1: break;
case nsIDOMKeyEvent::DOM_VK_SHIFT: return NS_MODIFIER_SHIFT;
case nsIDOMKeyEvent::DOM_VK_CONTROL: return NS_MODIFIER_CONTROL;
case nsIDOMKeyEvent::DOM_VK_ALT: return NS_MODIFIER_ALT;
case nsIDOMKeyEvent::DOM_VK_META: return NS_MODIFIER_META;
default: return 0;
}
// get the docShell to this DOMNode, return 0 on failure
@ -368,17 +362,17 @@ GetAccessModifierMask(nsIContent* aContent)
return 0;
// determine the access modifier used in this context
nsresult rv = NS_ERROR_FAILURE;
PRInt32 itemType, accessModifierMask = 0;
treeItem->GetItemType(&itemType);
switch (itemType) {
case nsIDocShellTreeItem::typeChrome:
rv = Preferences::GetInt("ui.key.chromeAccess", &accessModifierMask);
break;
case nsIDocShellTreeItem::typeChrome:
rv = prefBranch->GetIntPref("ui.key.chromeAccess", &accessModifierMask);
break;
case nsIDocShellTreeItem::typeContent:
rv = prefBranch->GetIntPref("ui.key.contentAccess", &accessModifierMask);
break;
case nsIDocShellTreeItem::typeContent:
rv = Preferences::GetInt("ui.key.contentAccess", &accessModifierMask);
break;
}
return NS_SUCCEEDED(rv) ? accessModifierMask : 0;
@ -682,15 +676,7 @@ nsAccessible::IsVisible(PRBool* aIsOffscreen)
}
// The frame intersects the viewport, but we need to check the parent view chain :(
nsIDocument* doc = mContent->GetOwnerDoc();
if (!doc) {
return PR_FALSE;
}
nsIFrame* frameWithView =
frame->HasView() ? frame : frame->GetAncestorWithViewExternal();
nsIView* view = frameWithView->GetViewExternal();
PRBool isVisible = CheckVisibilityInParentChain(doc, view);
bool isVisible = nsCoreUtils::CheckVisibilityInParentChain(frame);
if (isVisible && rectVisibility == nsRectVisibility_kVisible) {
*aIsOffscreen = PR_FALSE;
}
@ -701,20 +687,23 @@ PRUint64
nsAccessible::NativeState()
{
PRUint64 state = 0;
nsEventStates intrinsicState = mContent->IntrinsicState();
PRBool disabled = PR_FALSE;
if (mContent->IsElement()) {
nsEventStates elementState = mContent->AsElement()->State();
if (intrinsicState.HasState(NS_EVENT_STATE_INVALID))
state |= states::INVALID;
if (elementState.HasState(NS_EVENT_STATE_INVALID))
state |= states::INVALID;
if (intrinsicState.HasState(NS_EVENT_STATE_REQUIRED))
state |= states::REQUIRED;
if (elementState.HasState(NS_EVENT_STATE_REQUIRED))
state |= states::REQUIRED;
PRBool disabled = mContent->IsHTML() ?
(intrinsicState.HasState(NS_EVENT_STATE_DISABLED)) :
(mContent->AttrValueIs(kNameSpaceID_None,
nsAccessibilityAtoms::disabled,
nsAccessibilityAtoms::_true,
eCaseMatters));
disabled = mContent->IsHTML() ?
(elementState.HasState(NS_EVENT_STATE_DISABLED)) :
(mContent->AttrValueIs(kNameSpaceID_None,
nsAccessibilityAtoms::disabled,
nsAccessibilityAtoms::_true,
eCaseMatters));
}
// Set unavailable state based on disabled state, otherwise set focus states
if (disabled) {
@ -1533,15 +1522,20 @@ nsAccessible::State()
return states::DEFUNCT;
PRUint64 state = NativeState();
// Apply ARIA states to be sure accessible states will be overriden.
// Apply ARIA states to be sure accessible states will be overridden.
ApplyARIAState(&state);
if (mRoleMapEntry && mRoleMapEntry->role == nsIAccessibleRole::ROLE_PAGETAB) {
if (mRoleMapEntry && mRoleMapEntry->role == nsIAccessibleRole::ROLE_PAGETAB &&
!(state & states::SELECTED) &&
!mContent->AttrValueIs(kNameSpaceID_None,
nsAccessibilityAtoms::aria_selected,
nsAccessibilityAtoms::_false, eCaseMatters)) {
// Special case: for tabs, focused implies selected, unless explicitly
// false, i.e. aria-selected="false".
if (state & states::FOCUSED) {
state |= states::SELECTED;
} else {
// Expose 'selected' state on ARIA tab if the focus is on internal element
// of related tabpanel.
// If focus is in a child of the tab panel surely the tab is selected!
nsCOMPtr<nsIAccessible> tabPanel = nsRelUtils::
GetRelatedAccessible(this, nsIAccessibleRelation::RELATION_LABEL_FOR);
@ -3246,44 +3240,6 @@ nsAccessible::GetFirstAvailableAccessible(nsINode *aStartNode) const
return nsnull;
}
PRBool nsAccessible::CheckVisibilityInParentChain(nsIDocument* aDocument, nsIView* aView)
{
nsIDocument* document = aDocument;
nsIView* view = aView;
// both view chain and widget chain are broken between chrome and content
while (document != nsnull) {
while (view != nsnull) {
if (view->GetVisibility() == nsViewVisibility_kHide) {
return PR_FALSE;
}
view = view->GetParent();
}
nsIDocument* parentDoc = document->GetParentDocument();
if (parentDoc != nsnull) {
nsIContent* content = parentDoc->FindContentForSubDocument(document);
if (content != nsnull) {
nsIPresShell* shell = parentDoc->GetShell();
if (!shell) {
return PR_FALSE;
}
nsIFrame* frame = content->GetPrimaryFrame();
while (frame != nsnull && !frame->HasView()) {
frame = frame->GetParent();
}
if (frame != nsnull) {
view = frame->GetViewExternal();
}
}
}
document = parentDoc;
}
return PR_TRUE;
}
nsresult
nsAccessible::GetAttrValue(nsIAtom *aProperty, double *aValue)
{

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

@ -518,7 +518,7 @@ protected:
* Return true if the children flag is set.
*/
inline bool IsChildrenFlag(ChildrenFlags aFlag) const
{ return (mFlags & kChildrenFlagsMask) == aFlag; }
{ return static_cast<ChildrenFlags> (mFlags & kChildrenFlagsMask) == aFlag; }
/**
* Set children flag.
@ -606,9 +606,6 @@ protected:
//////////////////////////////////////////////////////////////////////////////
// Helpers
// Check the visibility across both parent content and chrome
PRBool CheckVisibilityInParentChain(nsIDocument* aDocument, nsIView* aView);
/**
* Get the container node for an atomic region, defined by aria-atomic="true"
* @return the container node

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

@ -332,8 +332,8 @@ nsApplicationAccessible::GetPlatformVersion(nsAString& aVersion)
////////////////////////////////////////////////////////////////////////////////
// nsAccessNode public methods
PRBool
nsApplicationAccessible::IsDefunct()
bool
nsApplicationAccessible::IsDefunct() const
{
return nsAccessibilityService::IsShutdown();
}

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

@ -115,7 +115,7 @@ public:
NS_DECL_NSIACCESSIBLEAPPLICATION
// nsAccessNode
virtual PRBool IsDefunct();
virtual bool IsDefunct() const;
virtual PRBool Init();
virtual void Shutdown();
virtual bool IsPrimaryForNode() const;

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

@ -141,7 +141,7 @@ nsLinkableAccessible::GetNumActions(PRUint8 *aNumActions)
{
NS_ENSURE_ARG_POINTER(aNumActions);
*aNumActions = mActionAcc ? 1 : 0;
*aNumActions = (mIsOnclick || mIsLink) ? 1 : 0;
return NS_OK;
}
@ -228,7 +228,6 @@ nsLinkableAccessible::BindToParent(nsAccessible* aParent,
mIsOnclick = PR_FALSE;
if (nsCoreUtils::HasClickListener(mContent)) {
mActionAcc = this;
mIsOnclick = PR_TRUE;
return;
}

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

@ -352,12 +352,15 @@ nsCaretAccessible::GetCaretRect(nsIWidget **aOutWidget)
}
nsPoint offset;
// Offset from widget origin to the frame origin, which includes chrome
// on the widget.
*aOutWidget = frame->GetNearestWidget(offset);
NS_ENSURE_TRUE(*aOutWidget, nsIntRect());
rect.MoveBy(offset);
caretRect = rect.ToOutsidePixels(frame->PresContext()->AppUnitsPerDevPixel());
caretRect.MoveBy((*aOutWidget)->WidgetToScreenOffset());
// ((content screen origin) - (content offset in the widget)) = widget origin on the screen
caretRect.MoveBy((*aOutWidget)->WidgetToScreenOffset() - (*aOutWidget)->GetClientOffset());
// Correct for character size, so that caret always matches the size of the character
// This is important for font size transitions, and is necessary because the Gecko caret uses the

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

@ -63,6 +63,7 @@
#include "nsPIDOMWindow.h"
#include "nsGUIEvent.h"
#include "nsIView.h"
#include "nsLayoutUtils.h"
#include "nsContentCID.h"
#include "nsComponentManagerUtils.h"
@ -753,6 +754,30 @@ nsCoreUtils::IsColumnHidden(nsITreeColumn *aColumn)
nsAccessibilityAtoms::_true, eCaseMatters);
}
bool
nsCoreUtils::CheckVisibilityInParentChain(nsIFrame* aFrame)
{
nsIView* view = aFrame->GetClosestView();
if (view && !view->IsEffectivelyVisible())
return false;
nsIPresShell* presShell = aFrame->PresContext()->GetPresShell();
while (presShell) {
if (!presShell->IsActive()) {
return false;
}
nsIFrame* rootFrame = presShell->GetRootFrame();
presShell = nsnull;
if (rootFrame) {
nsIFrame* frame = nsLayoutUtils::GetCrossDocParentFrame(rootFrame);
if (frame) {
presShell = frame->PresContext()->GetPresShell();
}
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// nsAccessibleDOMStringList

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

@ -367,6 +367,12 @@ public:
return aContent->NodeInfo()->Equals(nsAccessibilityAtoms::th) ||
aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::scope);
}
/**
* Check the visibility across both parent content and chrome.
*/
static bool CheckVisibilityInParentChain(nsIFrame* aFrame);
};

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

@ -54,8 +54,6 @@
#include "nsIDOMCharacterData.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentType.h"
#include "nsIDOMNSDocument.h"
#include "nsIDOMNSHTMLDocument.h"
#include "nsIDOMXULDocument.h"
#include "nsIDOMMutationEvent.h"
#include "nsPIDOMWindow.h"
@ -315,12 +313,7 @@ nsDocAccessible::NativeState()
}
nsIFrame* frame = GetFrame();
while (frame != nsnull && !frame->HasView()) {
frame = frame->GetParent();
}
if (frame == nsnull ||
!CheckVisibilityInParentChain(mDocument, frame->GetViewExternal())) {
if (!frame || !nsCoreUtils::CheckVisibilityInParentChain(frame)) {
state |= states::INVISIBLE | states::OFFSCREEN;
}
@ -411,22 +404,24 @@ NS_IMETHODIMP nsDocAccessible::GetURL(nsAString& aURL)
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::GetTitle(nsAString& aTitle)
NS_IMETHODIMP
nsDocAccessible::GetTitle(nsAString& aTitle)
{
nsCOMPtr<nsIDOMNSDocument> domnsDocument(do_QueryInterface(mDocument));
if (domnsDocument) {
return domnsDocument->GetTitle(aTitle);
nsCOMPtr<nsIDOMDocument> domDocument = do_QueryInterface(mDocument);
if (!domDocument) {
return NS_ERROR_FAILURE;
}
return NS_ERROR_FAILURE;
return domDocument->GetTitle(aTitle);
}
NS_IMETHODIMP nsDocAccessible::GetMimeType(nsAString& aMimeType)
NS_IMETHODIMP
nsDocAccessible::GetMimeType(nsAString& aMimeType)
{
nsCOMPtr<nsIDOMNSDocument> domnsDocument(do_QueryInterface(mDocument));
if (domnsDocument) {
return domnsDocument->GetContentType(aMimeType);
nsCOMPtr<nsIDOMDocument> domDocument = do_QueryInterface(mDocument);
if (!domDocument) {
return NS_ERROR_FAILURE;
}
return NS_ERROR_FAILURE;
return domDocument->GetContentType(aMimeType);
}
NS_IMETHODIMP nsDocAccessible::GetDocType(nsAString& aDocType)
@ -607,6 +602,12 @@ nsDocAccessible::Init()
if (!mNotificationController)
return PR_FALSE;
// Mark the document accessible as loaded if its DOM document was loaded at
// this point (this can happen because a11y is started late or DOM document
// having no container was loaded.
if (mDocument->GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE)
mIsLoaded = PR_TRUE;
AddEventListeners();
return PR_TRUE;
}
@ -670,8 +671,8 @@ nsDocAccessible::GetFrame() const
return root;
}
PRBool
nsDocAccessible::IsDefunct()
bool
nsDocAccessible::IsDefunct() const
{
return nsHyperTextAccessibleWrap::IsDefunct() || !mDocument;
}
@ -1037,6 +1038,14 @@ nsDocAccessible::AttributeChangedImpl(nsIContent* aContent, PRInt32 aNameSpaceID
return;
}
if (aAttribute == nsAccessibilityAtoms::aria_busy) {
PRBool isOn = !aContent->AttrValueIs(aNameSpaceID, aAttribute,
nsAccessibilityAtoms::_true, eCaseMatters);
nsRefPtr<AccEvent> event = new AccStateChangeEvent(aContent, states::BUSY, isOn);
FireDelayedAccessibleEvent(event);
return;
}
if (aAttribute == nsAccessibilityAtoms::selected ||
aAttribute == nsAccessibilityAtoms::aria_selected) {
// ARIA or XUL selection

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

@ -108,7 +108,7 @@ public:
virtual PRBool Init();
virtual void Shutdown();
virtual nsIFrame* GetFrame() const;
virtual PRBool IsDefunct();
virtual bool IsDefunct() const;
virtual nsINode* GetNode() const { return mDocument; }
virtual nsIDocument* GetDocumentNode() const { return mDocument; }

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

@ -35,6 +35,9 @@
*
* ***** END LICENSE BLOCK ***** */
#define CreateEvent CreateEventA
#include "nsIDOMDocument.h"
#include "States.h"
#include "nsAccessibilityService.h"
#include "nsApplicationAccessibleWrap.h"
@ -48,7 +51,6 @@
#include "nsIDocShellTreeItem.h"
#include "nsIDocShellTreeNode.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
#include "nsIDOMEventListener.h"
#include "nsIDOMEventTarget.h"
@ -57,7 +59,6 @@
#include "nsIDOMHTMLInputElement.h"
#include "nsIDOMHTMLSelectElement.h"
#include "nsIDOMDataContainerEvent.h"
#include "nsIDOMNSDocument.h"
#include "nsIDOMNSEvent.h"
#include "nsIDOMXULMenuListElement.h"
#include "nsIDOMXULMultSelectCntrlEl.h"
@ -76,11 +77,8 @@
#include "nsReadableUtils.h"
#include "nsRootAccessible.h"
#include "nsIDOMNSEventTarget.h"
#include "nsIDOMDocumentEvent.h"
#include "nsIPrivateDOMEvent.h"
#include "nsFocusManager.h"
#include "mozilla/dom/Element.h"
#ifdef MOZ_XUL
#include "nsXULTreeAccessible.h"
@ -140,7 +138,7 @@ nsRootAccessible::GetName(nsAString& aName)
}
}
nsCOMPtr<nsIDOMNSDocument> document(do_QueryInterface(mDocument));
nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(mDocument);
return document->GetTitle(aName);
}
@ -415,11 +413,11 @@ nsRootAccessible::FireCurrentFocusEvent()
return; // No current focus
}
nsCOMPtr<nsIDOMDocumentEvent> docEvent = do_QueryInterface(mDocument);
if (docEvent) {
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument);
if (domDoc) {
nsCOMPtr<nsIDOMEvent> event;
if (NS_SUCCEEDED(docEvent->CreateEvent(NS_LITERAL_STRING("Events"),
getter_AddRefs(event))) &&
if (NS_SUCCEEDED(domDoc->CreateEvent(NS_LITERAL_STRING("Events"),
getter_AddRefs(event))) &&
NS_SUCCEEDED(event->InitEvent(NS_LITERAL_STRING("focus"), PR_TRUE, PR_TRUE))) {
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event));

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

@ -81,7 +81,7 @@ nsHTMLLinkAccessible::NativeState()
states |= states::SELECTABLE;
}
nsEventStates state = mContent->IntrinsicState();
nsEventStates state = mContent->AsElement()->State();
if (state.HasAtLeastOneOfStates(NS_EVENT_STATE_VISITED |
NS_EVENT_STATE_UNVISITED)) {
states |= states::LINKED;
@ -187,7 +187,7 @@ nsHTMLLinkAccessible::IsLinked()
if (IsDefunct())
return PR_FALSE;
nsEventStates state = mContent->IntrinsicState();
nsEventStates state = mContent->AsElement()->State();
return state.HasAtLeastOneOfStates(NS_EVENT_STATE_VISITED |
NS_EVENT_STATE_UNVISITED);
}

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

@ -54,11 +54,13 @@
#include "nsIDOMNSHTMLElement.h"
#include "nsIFrame.h"
#include "nsINameSpaceManager.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsPIDOMWindow.h"
#include "nsIServiceManager.h"
#include "mozilla/Preferences.h"
using namespace mozilla;
/// the accessible library and cached methods
HINSTANCE nsAccessNodeWrap::gmAccLib = nsnull;
HINSTANCE nsAccessNodeWrap::gmUserLib = nsnull;
@ -711,22 +713,16 @@ void nsAccessNodeWrap::TurnOffNewTabSwitchingForJawsAndWE()
// Check to see if the pref for disallowing CtrlTab is already set.
// If so, bail out.
// If not, set it.
nsCOMPtr<nsIPrefBranch> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID));
if (prefs) {
PRBool hasDisallowNewCtrlTabPref = PR_FALSE;
nsresult rv = prefs->PrefHasUserValue(CTRLTAB_DISALLOW_FOR_SCREEN_READERS_PREF,
&hasDisallowNewCtrlTabPref);
if (NS_SUCCEEDED(rv) && hasDisallowNewCtrlTabPref) {
// This pref has been set before. There is no default for it.
// Do nothing further, respect the setting that's there.
// That way, if noone touches it, it'll stay on after toggled once.
// If someone decided to turn it off, we respect that, too.
return;
}
// Value has never been set, set it.
prefs->SetBoolPref(CTRLTAB_DISALLOW_FOR_SCREEN_READERS_PREF, PR_TRUE);
if (Preferences::HasUserValue(CTRLTAB_DISALLOW_FOR_SCREEN_READERS_PREF)) {
// This pref has been set before. There is no default for it.
// Do nothing further, respect the setting that's there.
// That way, if noone touches it, it'll stay on after toggled once.
// If someone decided to turn it off, we respect that, too.
return;
}
// Value has never been set, set it.
Preferences::SetBool(CTRLTAB_DISALLOW_FOR_SCREEN_READERS_PREF, PR_TRUE);
}
void nsAccessNodeWrap::DoATSpecificProcessing()

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

@ -58,7 +58,6 @@
#include "nsIScrollableFrame.h"
#include "nsINameSpaceManager.h"
#include "nsINodeInfo.h"
#include "nsIPrefService.h"
#include "nsRootAccessible.h"
#include "nsIServiceManager.h"
#include "nsTextFormatter.h"

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

@ -50,8 +50,6 @@
#include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsIDOMXULMultSelectCntrlEl.h"
#include "nsIDOMKeyEvent.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsIServiceManager.h"
#include "nsIPresShell.h"
#include "nsIContent.h"
@ -59,6 +57,10 @@
#include "nsILookAndFeel.h"
#include "nsWidgetsCID.h"
#include "mozilla/Preferences.h"
using namespace mozilla;
static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
@ -410,10 +412,7 @@ nsXULMenuitemAccessible::GetKeyboardShortcut(nsAString& aAccessKey)
// No need to cache pref service, this happens rarely
if (gMenuAccesskeyModifier == -1) {
// Need to initialize cached global accesskey pref
gMenuAccesskeyModifier = 0;
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
if (prefBranch)
prefBranch->GetIntPref("ui.key.menuAccessKey", &gMenuAccesskeyModifier);
gMenuAccesskeyModifier = Preferences::GetInt("ui.key.menuAccessKey", 0);
}
nsAutoString propertyKey;

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

@ -156,8 +156,8 @@ nsXULTreeAccessible::GetValue(nsAString& aValue)
////////////////////////////////////////////////////////////////////////////////
// nsXULTreeAccessible: nsAccessNode implementation
PRBool
nsXULTreeAccessible::IsDefunct()
bool
nsXULTreeAccessible::IsDefunct() const
{
return nsAccessibleWrap::IsDefunct() || !mTree || !mTreeView;
}
@ -834,8 +834,8 @@ nsXULTreeItemAccessibleBase::DoAction(PRUint8 aIndex)
////////////////////////////////////////////////////////////////////////////////
// nsXULTreeItemAccessibleBase: nsAccessNode implementation
PRBool
nsXULTreeItemAccessibleBase::IsDefunct()
bool
nsXULTreeItemAccessibleBase::IsDefunct() const
{
if (nsAccessibleWrap::IsDefunct() || !mTree || !mTreeView || mRow < 0)
return PR_TRUE;
@ -1091,8 +1091,8 @@ nsXULTreeItemAccessible::GetName(nsAString& aName)
////////////////////////////////////////////////////////////////////////////////
// nsXULTreeItemAccessible: nsAccessNode implementation
PRBool
nsXULTreeItemAccessible::IsDefunct()
bool
nsXULTreeItemAccessible::IsDefunct() const
{
return nsXULTreeItemAccessibleBase::IsDefunct() || !mColumn;
}

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

@ -80,7 +80,7 @@ public:
NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
// nsAccessNode
virtual PRBool IsDefunct();
virtual bool IsDefunct() const;
virtual void Shutdown();
// nsAccessible
@ -201,7 +201,7 @@ public:
NS_IMETHOD DoAction(PRUint8 aIndex);
// nsAccessNode
virtual PRBool IsDefunct();
virtual bool IsDefunct() const;
virtual void Shutdown();
virtual bool IsPrimaryForNode() const;
@ -266,7 +266,7 @@ public:
NS_IMETHOD GetName(nsAString& aName);
// nsAccessNode
virtual PRBool IsDefunct();
virtual bool IsDefunct() const;
virtual PRBool Init();
virtual void Shutdown();

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

@ -1087,8 +1087,8 @@ nsXULTreeGridCellAccessible::IsSelected(PRBool *aIsSelected)
////////////////////////////////////////////////////////////////////////////////
// nsXULTreeGridCellAccessible: nsAccessNode implementation
PRBool
nsXULTreeGridCellAccessible::IsDefunct()
bool
nsXULTreeGridCellAccessible::IsDefunct() const
{
return nsLeafAccessible::IsDefunct() || !mParent || !mTree || !mTreeView ||
!mColumn;

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

@ -155,7 +155,7 @@ public:
NS_DECL_NSIACCESSIBLETABLECELL
// nsAccessNode
virtual PRBool IsDefunct();
virtual bool IsDefunct() const;
virtual PRBool Init();
virtual bool IsPrimaryForNode() const;

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

@ -90,16 +90,14 @@ _TEST_FILES =\
test_aria_roles.xul \
test_aria_token_attrs.html \
test_bug420863.html \
$(warning test_childAtPoint.html temporarily disabled) \
$(warning test_childAtPoint.xul temporarily disabled) \
test_childAtPoint.html \
test_childAtPoint.xul \
test_descr.html \
test_elm_landmarks.html \
test_elm_listbox.xul \
$(warning test_elm_media.html temporarily disabled) \
test_elm_nsApplicationAcc.html \
test_elm_plugin.html \
test_keys.html \
$(warning test_nsIAccessible_comboboxes.xul temporarily disabled) \
test_nsIAccessible_selects.html \
test_nsIAccessibleDocument.html \
test_nsIAccessibleImage.html \

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

@ -52,6 +52,7 @@ _TEST_FILES =\
test_general.xul \
test_inputs.html \
test_link.html \
test_media.html \
test_tree.xul \
test_treegrid.xul \
$(NULL)

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

@ -36,9 +36,19 @@
ID: "li_clickable3",
actionName: "click",
events: CLICK_EVENTS
},
{
ID: "onclick_img",
actionName: "click",
events: CLICK_EVENTS
}
];
testActions(actionsArray);
getAccessible("onclick_img").takeFocus();
is(getAccessible("link1").numActions, 1, "links should have one action");
is(getAccessible("link2").numActions, 1, "link with onclick handler should have 1 action");
}
SimpleTest.waitForExplicitFinish();
@ -58,6 +68,11 @@
title="Expose click action if mouseup and mousedown are registered">
Mozilla Bug 423409
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=659620"
title="hang when trying to edit a page on wikimo with NVDA running">
Mozilla Bug 659620
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
@ -68,5 +83,11 @@
<li id="li_clickable2" onmousedown="">Clickable list item</li>
<li id="li_clickable3" onmouseup="">Clickable list item</li>
</ul>
<!-- linkable accessibles -->
<img id="onclick_img" onclick="" src="../moz.png">
<a id="link1" href="www">linkable textleaf accessible</a>
<div id="link2" onclick="">linkable textleaf accessible</div>
</body>
</html>

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

@ -13,15 +13,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=483573
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="common.js"></script>
src="../common.js"></script>
<script type="application/javascript"
src="events.js"></script>
src="../events.js"></script>
<script type="application/javascript"
src="actions.js"></script>
src="../actions.js"></script>
<script type="application/javascript"
src="role.js"></script>
src="../role.js"></script>
<script type="application/javascript"
src="states.js"></script>
src="../states.js"></script>
<script type="application/javascript">
@ -58,49 +58,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=483573
function doTest()
{
//////////////////////////////////////////////////////////////////////////
// test the accessible tree
var accTree = {
role: ROLE_GROUPING,
children: [
{ // start/stop button
role: ROLE_PUSHBUTTON,
name: "Play",
states: {
states: STATE_FOCUSABLE
}
},
{ // buffer bar
role: ROLE_PROGRESSBAR
},
{ // progress bar
role: ROLE_PROGRESSBAR
},
{ // slider of progress bar
role: ROLE_SLIDER,
name: "0:00 of 0:01 elapsed",
states: {
states: STATE_FOCUSABLE
}
},
{ // duration label, role="presentation"
role: ROLE_NOTHING
},
{ // mute button
role: ROLE_PUSHBUTTON,
name: "Mute",
states: {
states: STATE_FOCUSABLE
}
}
]
};
testAccessibleTree("audio", accTree);
//////////////////////////////////////////////////////////////////////////
// test actions of audio controls
todo(false, "Focus test are disabled until bug 494175 is fixed.");
var audioElm = getAccessible("audio");
var playBtn = audioElm.firstChild;
var scrubber = playBtn.nextSibling.nextSibling.nextSibling;
@ -112,24 +74,24 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=483573
actionName: "press",
events: CLICK_EVENTS,
eventSeq: [
new focusChecker(muteBtn),
// new focusChecker(muteBtn),
new nameChecker(muteBtn, "Unmute"),
]
},
{
ID: scrubber,
actionName: "activate",
events: null,
eventSeq: [
new focusChecker(scrubber)
]
},
// {
// ID: scrubber,
// actionName: "activate",
// events: null,
// eventSeq: [
// new focusChecker(scrubber)
// ]
// },
{
ID: playBtn,
actionName: "press",
events: CLICK_EVENTS,
eventSeq: [
new focusChecker(playBtn),
// new focusChecker(playBtn),
new nameChecker(playBtn, "Pause"),
]
}
@ -152,7 +114,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=483573
<pre id="test">
</pre>
<audio id="audio" src="bug461281.ogg"
<audio id="audio" src="../bug461281.ogg"
controls="true"></audio>
<div id="eventDump"></div>

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

@ -30,11 +30,11 @@
var menu1 = document.getElementById("menu_item1");
menu1.open = true;
window.setTimeout(function() {
menu1.addEventListener("popupshown", function() {
var menu2 = document.getElementById("menu_item2");
menu2.open = true;
window.setTimeout(function() {
menu2.addEventListener("popupshown", function() {
testGroupAttrs("menu_item1.1", 1, 1);
testGroupAttrs("menu_item1.2", 1, 3);
testGroupAttrs("menu_item1.4", 2, 3);
@ -42,9 +42,12 @@
testGroupAttrs("menu_item2.1", 1, 2, 1);
testGroupAttrs("menu_item2.2", 2, 2, 1);
menu1.open = false;
menu2.open = false;
SimpleTest.finish();
}, 200);
}, 200);
}, false);
}, false);
//////////////////////////////////////////////////////////////////////////
// xul:tab

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

@ -93,7 +93,7 @@ function addA11yLoadEvent(aFunc)
if (state.value & STATE_BUSY)
return waitForDocLoad();
window.setTimeout(aFunc, 150);
window.setTimeout(aFunc, 0);
},
0
);

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

@ -26,35 +26,60 @@
*/
var gQueue = null;
// Debug stuff.
//gA11yEventDumpID = "eventdump";
// gA11yEventDumpToConsole = true;
function expandNode(aNodeOrID, bExpand)
{
this.DOMNode = getNode(aNodeOrID);
this.invoke = function expand_invoke() {
this.invoke = function expandNode_invoke() {
// Note: this should fire an EVENT_STATE_CHANGE
this.DOMNode.setAttribute("aria-expanded", bExpand);
};
this.check = function expand_check() {
this.check = function expandNode_check() {
testStates(aNodeOrID,
bExpand ? STATE_EXPANDED : STATE_COLLAPSED,
EXT_STATE_EXPANDABLE);
};
this.getID = function changeValue_getID() {
this.getID = function expandNode_getID() {
return prettyName(aNodeOrID) + " aria-expanded changed";
};
}
function busyify(aNodeOrID, aBusy)
{
this.DOMNode = getNode(aNodeOrID);
this.invoke = function busyify_invoke() {
this.DOMNode.setAttribute("aria-busy", aBusy);
};
this.check = function busyify_check(event) {
testStates(aNodeOrID,
(aBusy ? STATE_BUSY : 0), 0,
(aBusy ? 0 : STATE_BUSY), 0);
};
this.getID = function busyify_getID() {
return prettyName(aNodeOrID) + " aria-busy changed to " + aBusy;
};
}
function doTests()
{
gQueue = new eventQueue(nsIAccessibleEvent.EVENT_STATE_CHANGE);
gQueue = new eventQueue(EVENT_STATE_CHANGE);
gQueue.push(new expandNode("section", true));
gQueue.push(new expandNode("section", false));
gQueue.push(new expandNode("div", true));
gQueue.push(new expandNode("div", false));
gQueue.push(new busyify("aria_doc", true));
gQueue.push(new busyify("aria_doc", false));
gQueue.invoke(); // Will call SimpleTest.finish();
}
@ -71,6 +96,11 @@
Mozilla Bug 551684
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=648133"
title="fire state change event for aria-busy"
Mozilla Bug 648133
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
@ -81,5 +111,7 @@
<div id="section" role="section" aria-expanded="false">expandable section</div>
<div id="div" aria-expanded="false">expandable native div</div>
<!-- aria-busy -->
<div id="aria_doc" role="document" tabindex="0">A document</div>
</body>
</html>

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

@ -118,6 +118,25 @@
}
}
function makeIFrameVisible(aID)
{
this.DOMNode = getNode(aID);
this.eventSeq = [
new invokerChecker(EVENT_REORDER, this.DOMNode.parentNode)
];
this.invoke = function makeIFrameVisible_invoke()
{
this.DOMNode.style.visibility = "visible";
}
this.getID = function makeIFrameVisible_getID()
{
return "The accessible for DOM document loaded before it's shown shouldn't have busy state.";
}
}
function openDialogWnd(aURL)
{
// Get application root accessible.
@ -224,7 +243,7 @@
// Debug stuff.
// gA11yEventDumpID = "eventdump";
// gA11yEventDumpToConsole = true;
//gA11yEventDumpToConsole = true;
function doTests()
{
@ -235,12 +254,30 @@
gQueue.push(new morphIFrame("iframe", kHide));
gQueue.push(new morphIFrame("iframe", kShow));
gQueue.push(new morphIFrame("iframe", kRemove));
gQueue.push(new makeIFrameVisible("iframe2"));
gQueue.push(new openDialogWnd("about:"));
gQueue.push(new openWndShutdownDoc());
gQueue.onFinish = doLastCallTests;
gQueue.invoke(); // Will call SimpleTest.finish();
}
function doLastCallTests()
{
//////////////////////////////////////////////////////////////////////////
// makeIFrameVisible() test, part2
// The document shouldn't have busy state (the DOM document was loaded
// before its accessible was created). Do this test lately to make sure
// the content of document accessible was created initially, prior to this
// the document accessible keeps busy state. The initial creation happens
// asynchronously after document creation, there are no events we could
// use to catch it.
var iframeDoc = getAccessible("iframe2").firstChild;
testStates(iframeDoc, 0, 0, STATE_BUSY);
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
@ -268,6 +305,11 @@
title="Shutdown document accessible when presshell goes away">
Mozilla Bug 571459
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=658185"
title="The DOM document loaded before it's shown shouldn't have busy state">
Mozilla Bug 658185
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
@ -275,6 +317,7 @@
</pre>
<div id="testContainer"><iframe id="iframe"></iframe></div>
<div id="testContainer2"><iframe id="iframe2" src="about:" style="visibility: hidden;"></iframe></div>
<div id="eventdump"></div>
</body>
</html>

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

@ -48,6 +48,8 @@ include $(topsrcdir)/config/rules.mk
_TEST_FILES =\
test_aria.html \
test_aria_imgmap.html \
test_aria_tabs.html \
test_comboboxes.xul \
test_doc.html \
test_docarticle.html \
test_editablebody.html \

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

@ -0,0 +1,137 @@
<!DOCTYPE html>
<html>
<head>
<title>Test ARIA tab accessible selected state</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
function focusARIATab(aID, aIsSelected)
{
this.DOMNode = getNode(aID);
this.invoke = function focusARIATab_invoke()
{
this.DOMNode.focus();
}
this.check = function focusARIATab_check(aEvent)
{
testStates(this.DOMNode, aIsSelected ? STATE_SELECTED : 0, 0,
aIsSelected ? 0 : STATE_SELECTED);
}
this.getID = function focusARIATab_getID()
{
return "Focused ARIA Tab with aria-selected=" +
(aIsSelected ? "true, should" : "false, shouldn't") +
" have selected state on " + prettyName(aID);
}
}
function focusActiveDescendantTab(aTabID, aTabListID, aIsSelected)
{
this.DOMNode = getNode(aTabID);
this.tabListDOMNode = getNode(aTabListID);
this.invoke = function focusActiveDescendantTab_invoke()
{
this.tabListDOMNode.setAttribute("aria-activedescendant", aTabID);
this.tabListDOMNode.focus();
}
this.check = function focusActiveDescendantTab_check(aEvent)
{
testStates(this.DOMNode, aIsSelected ? STATE_SELECTED : 0, 0,
aIsSelected ? 0 : STATE_SELECTED);
}
this.getID = function tabActiveDescendant_getID()
{
return "ARIA Tab with activedescendant " +
(aIsSelected ? "should" : "shouldn't") +
" have the selected state on " + prettyName(aTabID);
}
}
////////////////////////////////////////////////////////////////////////////
// Test
//gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true;
var gQueue = null;
function doTest()
{
// simple tabs
testStates("aria_tab1", 0, 0, STATE_SELECTED);
testStates("aria_tab2", STATE_SELECTED);
// To make sure our focus != selected is truly under test, we need to
// make sure our cache of what currently has focus is correct, which
// we update asyncronously.
gQueue = new eventQueue(EVENT_FOCUS);
gQueue.push(new focusARIATab("aria_tab1", true));
gQueue.push(new focusARIATab("aria_tab3", false));
gQueue.push(new focusARIATab("aria_tab2", true));
// selection through aria-activedescendant
// Make sure initially setting it selects the tab.
gQueue.push(new focusActiveDescendantTab("aria_tab5", "aria_tablist2", true));
// Now, make sure if one is selected selection gets transferred properly.
gQueue.push(new focusActiveDescendantTab("aria_tab6", "aria_tablist2", true));
// Now, make sure the focused but explicitly unselected one behaves.
gQueue.push(new focusActiveDescendantTab("aria_tab4", "aria_tablist2", false));
gQueue.invoke(); // SimpleTest.finish() will be called in the end
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=653601"
title="aria-selected ignored for ARIA tabs">
Mozilla Bug 653601
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<!-- tab -->
<div id="aria_tablist" role="tablist">
<div id="aria_tab1" role="tab" tabindex="0">unselected tab</div>
<div id="aria_tab2" role="tab" tabindex="0" aria-selected="true">selected tab</div>
<div id="aria_tab3" role="tab" tabindex="0" aria-selected="false">focused explicitly unselected tab</div>
</div>
<!-- test activeDescendant -->
<div id="aria_tablist2" role="tablist" tabindex="0">
<div id="aria_tab4" role="tab" aria-selected="false">focused explicitly unselected tab</div>
<div id="aria_tab5" role="tab">initially selected tab</div>
<div id="aria_tab6" role="tab">later selected tab</div>
</div>
</body>
</html>

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

@ -16,9 +16,9 @@
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js" />
<script type="application/javascript"
src="common.js" />
src="../common.js" />
<script type="application/javascript"
src="events.js" />
src="../events.js" />
<script type="application/javascript">
<![CDATA[
@ -64,6 +64,7 @@
//var searchbar = document.getElementById("searchbar");
//gQueue.push(new openHideCombobox(searchbar, true));
//gQueue.push(new openHideCombobox(searchbar, false));
todo(false, "Enable states test for XUL searchbar widget!");
gQueue.invoke(); // Will call SimpleTest.finish();
}

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

@ -25,19 +25,19 @@
testChildAtPoint(list, 1, 1, true, image.firstChild);
// ::MustPrune case (in this case childAtPoint doesn't look inside a
// button), point is inside of button.
var btn = getAccessible("btn");
testChildAtPoint(btn, 1, 1, false, btn);
testChildAtPoint(btn, 1, 1, true, btn);
// textbox), point is inside of textbox.
var txt = getAccessible("txt");
testChildAtPoint(txt, 1, 1, false, txt);
testChildAtPoint(txt, 1, 1, true, txt);
// ::MustPrune case, point is outside of button accessible but is in
// ::MustPrune case, point is outside of textbox accessible but is in
// document.
testChildAtPoint(btn, -1, 1, false, null);
testChildAtPoint(btn, -1, 1, true, null);
testChildAtPoint(txt, -1, 1, false, null);
testChildAtPoint(txt, -1, 1, true, null);
// ::MustPrune case, point is outside of root accessible.
testChildAtPoint(btn, -10000, 10000, false, null);
testChildAtPoint(btn, -10000, 10000, true, null);
testChildAtPoint(txt, -10000, 10000, false, null);
testChildAtPoint(txt, -10000, 10000, true, null);
// Not specific case, point is inside of label accessible.
var label = getAccessible("label");
@ -82,7 +82,7 @@
<span role="label">label1</span><span role="label" id="label">label2</span>
<span role="button">btn1</span><span role="button" id="btn">btn2</span>
<span role="textbox">textbox1</span><span role="textbox" id="txt">textbox2</span>
<div id="outofflow" style="width: 10px; height: 10px; position: absolute; left: 0px; top: 0px; background-color: yellow;">
</div>

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

@ -24,8 +24,7 @@
function doTest()
{
// Initialize the tree
var view = new inTreeView();
view.mRowCount = 5;
var view = new nsTableTreeView(5);
var tree = getNode("tree");
var treeBox = tree.treeBoxObject;

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

@ -30,24 +30,33 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=483573
role: ROLE_GROUPING,
children: [
{ // start/stop button
role: ROLE_PUSHBUTTON
role: ROLE_PUSHBUTTON,
name: "Play",
children: []
},
{ // buffer bar
role: ROLE_PROGRESSBAR
role: ROLE_PROGRESSBAR,
children: []
},
{ // progress bar
role: ROLE_PROGRESSBAR
role: ROLE_PROGRESSBAR,
children: []
},
{ // slider of progress bar
role: ROLE_SLIDER
role: ROLE_SLIDER,
//name: "0:00 of 0:02 elapsed",
children: []
},
{ // mute button
role: ROLE_PUSHBUTTON
role: ROLE_PUSHBUTTON,
name: "Mute",
children: []
}
]
};
testAccessibleTree("audio", accTree);
todo(false, "Enable name test for slider. Fail on Linux.");
SimpleTest.finish();
}

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

@ -15,6 +15,8 @@
src="../common.js" />
<script type="application/javascript"
src="../role.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript">
<![CDATA[
@ -108,6 +110,11 @@
]
};
function test_txc7() {
testAccessibleTree("txc7", accTree);
SimpleTest.finish();
}
// XPFE and Toolkit autocomplete widgets differ.
var txc7 = document.getElementById("txc7");
if ("clearResults" in txc7) {
@ -139,11 +146,14 @@
}
]
}
);
);
test_txc7();
} else {
SimpleTest.ok(true, "Testing (New) Toolkit autocomplete widget.");
// Dumb access to trigger popup lazy creation. (See code below.)
// Dumb access to trigger popup lazy creation.
waitForEvent(EVENT_REORDER, txc7, test_txc7);
txc7.popup;
accTree.children.push(
@ -161,17 +171,8 @@
}
]
}
);
);
}
// Delay txc7 test a bit, to let Toolkit popup lazy creation complete.
function test_txc7() {
testAccessibleTree("txc7", accTree);
SimpleTest.finish();
}
// SimpleTest.executeSoon() doesn't help here: use setTimeout() with a little delay.
setTimeout(test_txc7, 25);
}
SimpleTest.waitForExplicitFinish();

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

@ -102,51 +102,20 @@ CPPSRCS = nsBrowserApp.cpp
LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base
ifdef BUILD_STATIC_LIBS
ifdef _MSC_VER
STATIC_COMPONENTS_LINKER_PATH = -LIBPATH:$(DEPTH)/staticlib
else
STATIC_COMPONENTS_LINKER_PATH = -L$(DEPTH)/staticlib
endif
LIBS += $(DEPTH)/toolkit/xre/$(LIB_PREFIX)xulapp_s.$(LIB_SUFFIX)
else
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
LIBS += $(DIST)/bin/XUL
TK_LIBS := $(TK_LIBS)
else
EXTRA_DSO_LIBS += xul
endif
endif
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
TK_LIBS := $(TK_LIBS)
endif
ifdef MOZ_ENABLE_LIBXUL
APP_XPCOM_LIBS = $(XPCOM_GLUE_LDOPTS)
else
MOZILLA_INTERNAL_API = 1
APP_XPCOM_LIBS = $(XPCOM_LIBS)
endif
LIBS += \
$(STATIC_COMPONENTS_LINKER_PATH) \
$(EXTRA_DSO_LIBS) \
$(APP_XPCOM_LIBS) \
$(XPCOM_GLUE_LDOPTS) \
$(NSPR_LIBS) \
$(NULL)
ifdef BUILD_STATIC_LIBS
LIBS += \
$(MOZ_JS_LIBS) \
$(TK_LIBS) \
$(NULL)
# Add explicit X11 dependency when building against X11 toolkits
ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT)))
LIBS += $(XLDFLAGS) $(XLIBS) $(ZLIB_LIBS)
endif
endif
ifdef MOZ_JPROF
LIBS += -ljprof
endif
@ -171,18 +140,6 @@ ifdef _MSC_VER
WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup
endif
ifdef BUILD_STATIC_LIBS
include $(topsrcdir)/config/static-config.mk
EXTRA_DEPS += \
$(STATIC_EXTRA_DEPS) \
$(NULL)
DEFINES += $(STATIC_DEFINES)
CPPSRCS += $(STATIC_CPPSRCS)
EXTRA_DSO_LIBS += $(STATIC_EXTRA_DSO_LIBS)
EXTRA_LIBS += $(STATIC_EXTRA_LIBS)
endif
ifeq ($(OS_ARCH),WINNT)
OS_LIBS += $(call EXPAND_LIBNAME,comctl32 comdlg32 uuid shell32 ole32 oleaut32 version winspool)
OS_LIBS += $(call EXPAND_LIBNAME,usp10 msimg32)
@ -195,9 +152,6 @@ RCFLAGS += -DMOZ_PHOENIX -I$(srcdir)
else
RCFLAGS += -DMOZ_PHOENIX --include-dir $(srcdir)
endif
ifdef BUILD_STATIC_LIBS
RCFLAGS += -DMOZ_STATIC_BUILD
endif
ifdef DEBUG
RCFLAGS += -DDEBUG
endif
@ -206,9 +160,6 @@ endif
ifeq ($(OS_ARCH),OS2)
RESFILE=splashos2.res
RCFLAGS += -DMOZ_PHOENIX
ifdef BUILD_STATIC_LIBS
RCFLAGS += -DMOZ_STATIC_BUILD -i $(DIST)/include
endif
ifdef DEBUG
RCFLAGS += -DDEBUG
endif
@ -217,12 +168,6 @@ endif
include $(topsrcdir)/config/rules.mk
ifdef BUILD_STATIC_LIBS
include $(topsrcdir)/config/static-rules.mk
DEFINES += -DIMPL_XREAPI
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),photon)
LIBS += -lphexlib
endif

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

@ -97,6 +97,11 @@
<versionRange minVersion="3.7a1" maxVersion="*"/>
</targetApplication>
</versionRange>
<versionRange minVersion="3.3.1" maxVersion="*">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
<versionRange minVersion="5.0a1" maxVersion="*"/>
</targetApplication>
</versionRange>
</emItem>
<emItem id="{E8E88AB0-7182-11DF-904E-6045E0D72085}"/>
</emItems>

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

@ -92,6 +92,55 @@
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>oga</string>
<string>ogg</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>audio/ogg</string>
</array>
<key>CFBundleTypeName</key>
<string>HTML5 Audio (Ogg)</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>ogv</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>video/ogg</string>
</array>
<key>CFBundleTypeName</key>
<string>HTML5 Video (Ogg)</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>webm</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>video/webm</string>
</array>
<key>CFBundleTypeName</key>
<string>HTML5 Video (WebM)</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>firefox-bin</string>

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

@ -123,7 +123,7 @@ var stringBundle;
// and targets
let io = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
let source = io.newURI(canvas.toDataURL("image/png", ""), "UTF8", null);
let source = io.newURI(canvas.toDataURL("image/png"), "UTF8", null);
let target = io.newFileURI(file);
// prepare to save the canvas data

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

@ -91,6 +91,9 @@ function onBuiltinSurveyLoad() {
explanation.innerHTML = "";
}
drawSurveyForm(task, contentDiv);
// Allow surveys to define arbitrary page load handlers - call them
// after creating the rest of the page:
task.onPageLoad(task, document);
}
}
@ -114,7 +117,7 @@ function drawSurveyForm(task, contentDiv) {
for (let i = 0; i < surveyQuestions.length; i++) {
let question = surveyQuestions[i].question;
let explanation = surveyQuestions[i].explanation;
let elem;
let elem, j;
elem = document.createElement("h3");
elem.innerHTML = (i+1) + ". " + question;
@ -129,7 +132,7 @@ function drawSurveyForm(task, contentDiv) {
let choices = surveyQuestions[i].choices;
switch (surveyQuestions[i].type) {
case MULTIPLE_CHOICE:
for (let j = 0; j < choices.length; j++) {
for (j = 0; j < choices.length; j++) {
let newRadio = document.createElement("input");
newRadio.setAttribute("type", "radio");
newRadio.setAttribute("name", "answer_to_" + i);
@ -148,7 +151,7 @@ function drawSurveyForm(task, contentDiv) {
case CHECK_BOXES_WITH_FREE_ENTRY:
let checkboxName = "answer_to_" + i;
// Check boxes:
for (let j = 0; j < choices.length; j++) {
for (j = 0; j < choices.length; j++) {
let newCheck = document.createElement("input");
newCheck.setAttribute("type", "checkbox");
newCheck.setAttribute("name", checkboxName);
@ -188,7 +191,7 @@ function drawSurveyForm(task, contentDiv) {
inputBox.addEventListener(
"keypress", function() {
let elements = document.getElementsByName(checkboxName);
for (let j = (elements.length - 1); j >= 0; j--) {
for (j = (elements.length - 1); j >= 0; j--) {
if (elements[j].value == freeformId) {
elements[j].checked = true;
break;
@ -213,7 +216,7 @@ function drawSurveyForm(task, contentDiv) {
let label = document.createElement("span");
label.innerHTML = surveyQuestions[i].min_label;
contentDiv.appendChild(label);
for (let j = surveyQuestions[i].scale_minimum;
for (j = surveyQuestions[i].scale_minimum;
j <= surveyQuestions[i].scale_maximum;
j++) {
let newRadio = document.createElement("input");
@ -243,7 +246,7 @@ function drawSurveyForm(task, contentDiv) {
let freeformId = "freeform_" + i;
let radioName = "answer_to_" + i;
for (let j = 0; j < choices.length; j++) {
for (j = 0; j < choices.length; j++) {
let newRadio = document.createElement("input");
newRadio.setAttribute("type", "radio");
newRadio.setAttribute("name", radioName);

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

@ -4,7 +4,7 @@
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>testpilot@labs.mozilla.com</em:id>
<em:version>1.1.1</em:version>
<em:version>1.1.2</em:version>
<em:type>2</em:type>
<!-- Target Application this extension can install into,
@ -13,7 +13,7 @@
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>3.5</em:minVersion>
<em:maxVersion>5.0</em:maxVersion>
<em:maxVersion>6.0</em:maxVersion>
</Description>
</em:targetApplication>

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

@ -512,15 +512,15 @@ exports.RemoteExperimentLoader.prototype = {
remoteExperiments[filename] = this._loader.require(filename);
this._logger.info("Loaded " + filename + " OK.");
} catch(e) {
/* Turn the load-time errors into strings and store them, so we can display
* them on a debug page or include them with a data upload! (Don't store
* exception objects directly as that causes garbage collector problems-
* aka bug 646122) */
let errStr = e.name + " on line " + e.lineNumber + " of file " +
e.fileName + ": " + e.message;
/* Turn the load-time errors into strings and store them, so we can display
* them on a debug page or include them with a data upload! (Don't store
* exception objects directly as that causes garbage collector problems-
* aka bug 646122) */
let errStr = e.name + " on line " + e.lineNumber + " of file " +
e.fileName + ": " + e.message;
this._loadErrors.push(errStr);
this._logger.warn("Error loading " + filename);
this._logger.warn(e);
this._logger.warn(errStr);
}
}
return remoteExperiments;

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

@ -597,7 +597,7 @@ TestPilotExperiment.prototype = {
}
}
} catch(e) {
this._logger.warn("Error in getStudyMetadata: " + e);
this._dataStore.logException("getStudyMetadata: " + e);
}
return null;
},
@ -660,6 +660,7 @@ TestPilotExperiment.prototype = {
// This method handles all date-related status changes and should be
// called periodically.
let currentDate = this._now();
let self = this;
// Reset automatically recurring tests:
if (this._recursAutomatically &&
@ -703,7 +704,6 @@ TestPilotExperiment.prototype = {
currentDate <= this._endDate) {
this._logger.info("Study now starting.");
// clear the data before starting.
let self = this;
this._dataStore.wipeAllData(function() {
// Experiment is now in progress.
self.changeStatus(TaskConstants.STATUS_IN_PROGRESS, true);
@ -714,7 +714,6 @@ TestPilotExperiment.prototype = {
// What happens when a test finishes:
if (this._status < TaskConstants.STATUS_FINISHED &&
currentDate > this._endDate) {
let self = this;
let setDataDeletionDate = true;
this._logger.info("Passed End Date - Switched Task Status to Finished");
this.changeStatus(TaskConstants.STATUS_FINISHED);
@ -896,7 +895,6 @@ TestPilotExperiment.prototype = {
optOut: function TestPilotExperiment_optOut(reason, callback) {
// Regardless of study ID, post the opt-out message to a special
// database table of just opt-out messages; include study ID in metadata.
let url = Application.prefs.getValue(DATA_UPLOAD_PREF, "") + "opt-out";
let logger = this._logger;
this.onExperimentShutdown();
@ -909,6 +907,7 @@ TestPilotExperiment.prototype = {
if (reason) {
// Send us the reason...
// (TODO: include metadata?)
let url = Application.prefs.getValue(DATA_UPLOAD_PREF, "") + "opt-out";
let answer = {id: this._id,
reason: reason};
let dataString = JSON.stringify(answer);
@ -924,17 +923,23 @@ TestPilotExperiment.prototype = {
if (req.readyState == 4) {
if (req.status == 200 || req.status == 201 || req.status == 202) {
logger.info("Quit reason posted successfully " + req.responseText);
callback(true);
if (callback) {
callback(true);
}
} else {
logger.warn(req.status + " posting error " + req.responseText);
callback(false);
if (callback) {
callback(false);
}
}
}
};
logger.trace("Sending quit reason.");
req.send(dataString);
} else {
callback(false);
if (callback) {
callback(false);
}
}
},
@ -961,6 +966,7 @@ TestPilotBuiltinSurvey.prototype = {
this._versionNumber = surveyInfo.versionNumber;
this._questions = surveyInfo.surveyQuestions;
this._explanation = surveyInfo.surveyExplanation;
this._onPageLoad = surveyInfo.onPageLoad;
},
get taskType() {
@ -988,6 +994,12 @@ TestPilotBuiltinSurvey.prototype = {
return this._studyId;
},
onPageLoad: function(task, document) {
if (this._onPageLoad) {
this._onPageLoad(task, document);
}
},
onDetailPageOpened: function TPS_onDetailPageOpened() {
if (this._status < TaskConstants.STATUS_IN_PROGRESS) {
this.changeStatus( TaskConstants.STATUS_IN_PROGRESS, true );
@ -1204,4 +1216,4 @@ TestPilotLegacyStudy.prototype = {
// TODO test that they don't say "thanks for contributing" if the
// user didn't actually complete them...
};
TestPilotLegacyStudy.prototype.__proto__ = TestPilotTask;
TestPilotLegacyStudy.prototype.__proto__ = TestPilotTask;

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

@ -43,8 +43,6 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
DEFINES += -DFIREFOX_VERSION=$(FIREFOX_VERSION)
FILES := \
install.rdf \
$(NULL)

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

@ -70,6 +70,7 @@ pref("extensions.blocklist.interval", 86400);
pref("extensions.blocklist.level", 2);
pref("extensions.blocklist.url", "https://addons.mozilla.org/blocklist/3/%APP_ID%/%APP_VERSION%/%PRODUCT%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/%PING_COUNT%/%TOTAL_PING_COUNT%/%DAYS_SINCE_LAST_PING%/");
pref("extensions.blocklist.detailsURL", "https://www.mozilla.com/%LOCALE%/blocklist/");
pref("extensions.blocklist.itemURL", "https://addons.mozilla.org/%LOCALE%/%APP%/blocked/%blockID%");
pref("extensions.update.autoUpdateDefault", true);
@ -901,6 +902,17 @@ pref("dom.ipc.plugins.enabled.x86_64", true);
pref("dom.ipc.plugins.enabled", true);
#endif
// This pref governs whether we attempt to work around problems caused by
// plugins using OS calls to manipulate the cursor while running out-of-
// process. These workarounds all involve intercepting (hooking) certain
// OS calls in the plugin process, then arranging to make certain OS calls
// in the browser process. Eventually plugins will be required to use the
// NPAPI to manipulate the cursor, and these workarounds will be removed.
// See bug 621117.
#ifdef XP_MACOSX
pref("dom.ipc.plugins.nativeCursorSupport", true);
#endif
#ifdef XP_WIN
pref("browser.taskbar.previews.enable", false);
pref("browser.taskbar.previews.max", 20);

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

@ -72,33 +72,3 @@
padding: 0;
font-weight: bold;
}
#channelSelector {
margin-top: 10px;
}
#channelSelectorStart {
-moz-margin-start: 0;
}
#channelMenulist {
margin: 0;
}
.channel-description {
margin: 10px 0;
}
#detailsBox,
#channelSelector,
.channel-description {
-moz-transition: opacity 250ms;
}
#contentDeck:not([selectedIndex="0"]) > #detailsBox,
#contentDeck:not([selectedIndex="1"]) > #channelSelector,
#channelDescriptionDeck:not([selectedIndex="0"]) > #releaseDescription,
#channelDescriptionDeck:not([selectedIndex="1"]) > #betaDescription,
#channelDescriptionDeck:not([selectedIndex="2"]) > #auroraDescription {
opacity: 0;
}

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

@ -88,7 +88,9 @@ function init(aEvent)
gAppUpdater = new appUpdater();
#endif
gChannelSelector.init();
let defaults = Services.prefs.getDefaultBranch("");
let channelLabel = document.getElementById("currentChannel");
channelLabel.value = defaults.getCharPref("app.update.channel");
#ifdef XP_MACOSX
// it may not be sized at this point, and we need its width to calculate its position
@ -573,72 +575,3 @@ appUpdater.prototype =
}
};
#endif
var gChannelSelector = {
validChannels: { release: 1, beta: 1, aurora: 1 },
init: function() {
try {
this.channelValue = Services.prefs.getCharPref("app.update.desiredChannel");
} catch (e) {
let defaults = Services.prefs.getDefaultBranch("");
this.channelValue = defaults.getCharPref("app.update.channel");
}
// Only show channel selector UI on valid update channels.
if (this.channelValue in this.validChannels) {
document.getElementById("currentChannelText").hidden = false;
this.setChannelLabel(this.channelValue);
this.setChannelMenuitem(this.channelValue);
}
},
selectChannel: function(aSelectedItem) {
document.getElementById("channelDescriptionDeck").selectedPanel =
document.getElementById(aSelectedItem.value + "Description");
document.getElementById("channelMenulist").setAttribute("aria-describedby",
aSelectedItem.value + "Description");
},
cancel: function() {
this.setChannelMenuitem(this.channelValue);
this.hide();
},
apply: function() {
this.channelValue = document.getElementById("channelMenulist").selectedItem.value;
this.setChannelLabel(this.channelValue);
// Change app update channel.
Services.prefs.setCharPref("app.update.desiredChannel", this.channelValue);
// Stop any downloads in progress
gAppUpdater.aus.pauseDownload();
// App updater will look at app.update.desiredChannel for new channel value
// and will clear it when the update is complete.
gAppUpdater.isChecking = true;
gAppUpdater.checker.checkForUpdates(gAppUpdater.updateCheckListener, true);
this.hide();
},
show: function() {
document.getElementById("contentDeck").selectedPanel =
document.getElementById("channelSelector");
},
hide: function() {
document.getElementById("contentDeck").selectedPanel =
document.getElementById("detailsBox");
},
setChannelLabel: function(aValue) {
let channelLabel = document.getElementById("currentChannel");
channelLabel.value = document.getElementById(aValue + "Menuitem").label;
},
setChannelMenuitem: function(aValue) {
document.getElementById("channelMenulist").selectedItem =
document.getElementById(aValue + "Menuitem");
}
}

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

@ -80,85 +80,50 @@
<label id="distribution" class="text-blurb"/>
<label id="distributionId" class="text-blurb"/>
<!-- Make sure the selectedIndex attribute is always set so that the CSS
selectors for transitions work -->
<deck id="contentDeck" selectedIndex="0">
<vbox id="detailsBox" aria-describedby="communityDesc contributeDesc">
<vbox id="updateBox">
<vbox id="detailsBox" aria-describedby="communityDesc contributeDesc">
<vbox id="updateBox">
#ifdef MOZ_UPDATER
<deck id="updateDeck" orient="vertical">
<hbox id="updateButtonBox" align="center">
<button id="updateButton" align="start"
oncommand="gAppUpdater.buttonOnCommand();"/>
<spacer flex="1"/>
</hbox>
<hbox id="checkingForUpdates" align="center">
<image class="update-throbber"/><label>&update.checkingForUpdates;</label>
</hbox>
<hbox id="checkingAddonCompat" align="center">
<image class="update-throbber"/><label>&update.checkingAddonCompat;</label>
</hbox>
<hbox id="downloading" align="center">
<image class="update-throbber"/><label>&update.downloading.start;</label><label id="downloadStatus"/><label>&update.downloading.end;</label>
</hbox>
<hbox id="downloadFailed" align="center">
<label>&update.failed.start;</label><label id="failedLink" class="text-link">&update.failed.linkText;</label><label>&update.failed.end;</label>
</hbox>
<hbox id="adminDisabled" align="center">
<label>&update.adminDisabled;</label>
</hbox>
<hbox id="noUpdatesFound" align="center">
<label>&update.noUpdatesFound;</label>
</hbox>
<hbox id="manualUpdate" align="center">
<label>&update.manual.start;</label><label id="manualLink" class="text-link"/><label>&update.manual.end;</label>
</hbox>
</deck>
#endif
</vbox>
<description class="text-blurb" id="currentChannelText" hidden="true">
&channel.description.start;<label id="currentChannel"/>&channel.description.end;<label id="channelChangeLink" class="text-link" onclick="gChannelSelector.show();">&channel.change;</label>
</description>
<description class="text-blurb" id="communityDesc">
&community.start2;<label class="text-link" href="http://www.mozilla.org/">&community.mozillaLink;</label>&community.middle2;<label class="text-link" href="about:credits">&community.creditsLink;</label>&community.end2;
</description>
<description class="text-blurb" id="contributeDesc">
&contribute.start;<label class="text-link" href="http://www.mozilla.org/contribute/">&contribute.getInvolvedLink;</label>&contribute.end;
</description>
</vbox>
<vbox id="channelSelector">
<hbox pack="start" align="center">
<label id="channelSelectorStart">&channel.selector.start;</label>
<menulist id="channelMenulist" onselect="gChannelSelector.selectChannel(this.selectedItem);" aria-labelledby="channelSelectorStart channelMenulist channelSelectorEnd">
<menupopup>
<menuitem id="releaseMenuitem" label="Release" value="release"/>
<menuitem id="betaMenuitem" label="Beta" value="beta"/>
<menuseparator/>
<menuitem id="auroraMenuitem" label="Aurora" value="aurora"/>
</menupopup>
</menulist>
<label id="channelSelectorEnd">&channel.selector.end;</label>
</hbox>
<deck id="channelDescriptionDeck" selectedIndex="0">
<description id="releaseDescription" class="channel-description">&channel.release.description;</description>
<description id="betaDescription" class="channel-description">&channel.beta.description;</description>
<description id="auroraDescription" class="channel-description">&channel.aurora.description;</description>
<deck id="updateDeck" orient="vertical">
<hbox id="updateButtonBox" align="center">
<button id="updateButton" align="start"
oncommand="gAppUpdater.buttonOnCommand();"/>
<spacer flex="1"/>
</hbox>
<hbox id="checkingForUpdates" align="center">
<image class="update-throbber"/><label>&update.checkingForUpdates;</label>
</hbox>
<hbox id="checkingAddonCompat" align="center">
<image class="update-throbber"/><label>&update.checkingAddonCompat;</label>
</hbox>
<hbox id="downloading" align="center">
<image class="update-throbber"/><label>&update.downloading.start;</label><label id="downloadStatus"/><label>&update.downloading.end;</label>
</hbox>
<hbox id="downloadFailed" align="center">
<label>&update.failed.start;</label><label id="failedLink" class="text-link">&update.failed.linkText;</label><label>&update.failed.end;</label>
</hbox>
<hbox id="adminDisabled" align="center">
<label>&update.adminDisabled;</label>
</hbox>
<hbox id="noUpdatesFound" align="center">
<label>&update.noUpdatesFound;</label>
</hbox>
<hbox id="manualUpdate" align="center">
<label>&update.manual.start;</label><label id="manualLink" class="text-link"/><label>&update.manual.end;</label>
</hbox>
</deck>
<hbox id="channelSelectorButtons" pack="end">
#ifdef XP_UNIX
<button oncommand="gChannelSelector.cancel();" label="&channel.selector.cancelButton;"/>
<button oncommand="gChannelSelector.apply();" label="&channel.selector.applyButton;"/>
#else
<button oncommand="gChannelSelector.apply();" label="&channel.selector.applyButton;"/>
<button oncommand="gChannelSelector.cancel();" label="&channel.selector.cancelButton;"/>
#endif
</hbox>
</vbox>
</deck>
<description class="text-blurb" id="currentChannelText">
&channel.description.start;<label id="currentChannel"/>&channel.description.end;
</description>
<description class="text-blurb" id="communityDesc">
&community.start2;<label class="text-link" href="http://www.mozilla.org/">&community.mozillaLink;</label>&community.middle2;<label class="text-link" href="about:credits">&community.creditsLink;</label>&community.end2;
</description>
<description class="text-blurb" id="contributeDesc">
&contribute.start;<label class="text-link" href="http://www.mozilla.org/contribute/">&contribute.getInvolvedLink;</label>&contribute.end;
</description>
</vbox>
</vbox>
</hbox>
<vbox id="bottomBox">

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

@ -201,6 +201,10 @@
label="&errorConsoleCmd.label;"
key="key_errorConsole"
oncommand="toJavaScriptConsole();"/>
<menuseparator id="appmenu_devToolsEndSeparator"/>
<menuitem id="appmenu_getMoreDevtools"
label="&getMoreDevtoolsCmd.label;"
oncommand="openUILinkIn('https://addons.mozilla.org/firefox/collections/mozilla/webdeveloper/', 'tab');"/>
<menuseparator/>
#define ID_PREFIX appmenu_developer_
#define OMIT_ACCESSKEYS

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

@ -567,6 +567,11 @@
accesskey="&errorConsoleCmd.accesskey;"
key="key_errorConsole"
oncommand="toJavaScriptConsole();"/>
<menuseparator id="devToolsEndSeparator"/>
<menuitem id="getMoreDevtools"
label="&getMoreDevtoolsCmd.label;"
accesskey="&getMoreDevtoolsCmd.accesskey;"
oncommand="openUILinkIn('https://addons.mozilla.org/firefox/collections/mozilla/webdeveloper/', 'tab');"/>
</menupopup>
</menu>
<menuitem id="menu_pageInfo"

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

@ -328,7 +328,7 @@ let gSyncUI = {
// Show the day-of-week and time (HH:MM) of last sync
let lastSyncDate = new Date(lastSync).toLocaleFormat("%a %H:%M");
let lastSyncLabel =
this._stringBundle.formatStringFromName("lastSync.label", [lastSyncDate], 1);
this._stringBundle.formatStringFromName("lastSync2.label", [lastSyncDate], 1);
syncButton.setAttribute("tooltiptext", lastSyncLabel);
},

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

@ -48,6 +48,7 @@ let TabView = {
PREF_STARTUP_PAGE: "browser.startup.page",
PREF_RESTORE_ENABLED_ONCE: "browser.panorama.session_restore_enabled_once",
VISIBILITY_IDENTIFIER: "tabview-visibility",
GROUPS_IDENTIFIER: "tabview-groups",
// ----------
get windowTitle() {
@ -95,14 +96,21 @@ let TabView = {
// ___ visibility
let sessionstore =
Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
let data = sessionstore.getWindowValue(window, this.VISIBILITY_IDENTIFIER);
let data = sessionstore.getWindowValue(window, this.VISIBILITY_IDENTIFIER);
if (data && data == "true") {
this.show();
} else {
let self = this;
try {
data = sessionstore.getWindowValue(window, this.GROUPS_IDENTIFIER);
if (data) {
let parsedData = JSON.parse(data);
this.updateGroupNumberBroadcaster(parsedData.totalNumber || 0);
}
} catch (e) { }
// if a tab is changed from hidden to unhidden and the iframe is not
let self = this;
// if a tab is changed from hidden to unhidden and the iframe is not
// initialized, load the iframe and setup the tab.
this._tabShowEventListener = function (event) {
if (!self._window)
@ -380,6 +388,14 @@ let TabView = {
document.persist(toolbar.id, "currentset");
},
// ----------
// Function: updateGroupNumberBroadcaster
// Updates the group number broadcaster.
updateGroupNumberBroadcaster: function TabView_updateGroupNumberBroadcaster(number) {
let groupsNumber = document.getElementById("tabviewGroupsNumber");
groupsNumber.setAttribute("groups", number);
},
// ----------
// Function: enableSessionRestore
// Enables automatic session restore when the browser is started. Does

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

@ -496,3 +496,7 @@ statuspanel[label=""] {
width: 100%;
-moz-box-align: end;
}
.panel-inner-arrowcontentfooter[footertype="promobox"] {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#promobox");
}

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

@ -261,10 +261,10 @@ function UpdateBackForwardCommands(aWebNavigation) {
function SetClickAndHoldHandlers() {
var timer;
function timerCallback(aButton) {
function openMenu(aButton) {
cancelHold(aButton);
aButton.firstChild.hidden = false;
aButton.open = true;
timer = null;
}
function mousedownHandler(aEvent) {
@ -276,7 +276,29 @@ function SetClickAndHoldHandlers() {
// Prevent the menupopup from opening immediately
aEvent.currentTarget.firstChild.hidden = true;
timer = setTimeout(timerCallback, 500, aEvent.currentTarget);
aEvent.currentTarget.addEventListener("mouseout", mouseoutHandler, false);
aEvent.currentTarget.addEventListener("mouseup", mouseupHandler, false);
timer = setTimeout(openMenu, 500, aEvent.currentTarget);
}
function mouseoutHandler(aEvent) {
let buttonRect = aEvent.currentTarget.getBoundingClientRect();
if (aEvent.clientX >= buttonRect.left &&
aEvent.clientX <= buttonRect.right &&
aEvent.clientY >= buttonRect.bottom)
openMenu(aEvent.currentTarget);
else
cancelHold(aEvent.currentTarget);
}
function mouseupHandler(aEvent) {
cancelHold(aEvent.currentTarget);
}
function cancelHold(aButton) {
clearTimeout(timer);
aButton.removeEventListener("mouseout", mouseoutHandler, false);
aButton.removeEventListener("mouseup", mouseupHandler, false);
}
function clickHandler(aEvent) {
@ -292,17 +314,8 @@ function SetClickAndHoldHandlers() {
}
}
function stopTimer(aEvent) {
if (timer) {
clearTimeout(timer);
timer = null;
}
}
function _addClickAndHoldListenersOnElement(aElm) {
aElm.addEventListener("mousedown", mousedownHandler, true);
aElm.addEventListener("mouseup", stopTimer, false);
aElm.addEventListener("mouseout", stopTimer, false);
aElm.addEventListener("click", clickHandler, true);
}
@ -2244,7 +2257,11 @@ function loadURI(uri, referrer, postData, allowThirdPartyFixup)
}
}
function getShortcutOrURI(aURL, aPostDataRef) {
function getShortcutOrURI(aURL, aPostDataRef, aMayInheritPrincipal) {
// Initialize outparam to false
if (aMayInheritPrincipal)
aMayInheritPrincipal.value = false;
var shortcutURL = null;
var keyword = aURL;
var param = "";
@ -2316,6 +2333,11 @@ function getShortcutOrURI(aURL, aPostDataRef) {
return aURL;
}
// This URL came from a bookmark, so it's safe to let it inherit the current
// document's principal.
if (aMayInheritPrincipal)
aMayInheritPrincipal.value = true;
return shortcutURL;
}
@ -2860,7 +2882,7 @@ var PrintPreviewListener = {
this._printPreviewTab = null;
},
_toggleAffectedChrome: function () {
gNavToolbox.hidden = gInPrintPreviewMode;
gNavToolbox.collapsed = gInPrintPreviewMode;
if (gInPrintPreviewMode)
this._hideChrome();
@ -2951,11 +2973,7 @@ function FillInHTMLTooltip(tipElement)
var titleText = null;
var XLinkTitleText = null;
var SVGTitleText = null;
#ifdef MOZ_SVG
var lookingForSVGTitle = true;
#else
var lookingForSVGTitle = false;
#endif // MOZ_SVG
var direction = tipElement.ownerDocument.dir;
// If the element is invalid per HTML5 Forms specifications and has no title,
@ -2976,11 +2994,8 @@ function FillInHTMLTooltip(tipElement)
titleText = tipElement.getAttribute("title");
if ((tipElement instanceof HTMLAnchorElement && tipElement.href) ||
(tipElement instanceof HTMLAreaElement && tipElement.href) ||
(tipElement instanceof HTMLLinkElement && tipElement.href)
#ifdef MOZ_SVG
|| (tipElement instanceof SVGAElement && tipElement.hasAttributeNS(XLinkNS, "href"))
#endif // MOZ_SVG
) {
(tipElement instanceof HTMLLinkElement && tipElement.href) ||
(tipElement instanceof SVGAElement && tipElement.hasAttributeNS(XLinkNS, "href"))) {
XLinkTitleText = tipElement.getAttributeNS(XLinkNS, "title");
}
if (lookingForSVGTitle &&
@ -3333,7 +3348,7 @@ const BrowserSearch = {
var win = getTopWin();
if (win) {
// If there's an open browser window, it should handle this command
win.focus()
win.focus();
win.BrowserSearch.webSearch();
} else {
// If there are no open browser windows, open a new one
@ -3343,7 +3358,7 @@ const BrowserSearch = {
Services.obs.removeObserver(observer, "browser-delayed-startup-finished");
}
}
win = window.openDialog("chrome://browser/content/", "_blank",
win = window.openDialog(getBrowserURL(), "_blank",
"chrome,all,dialog=no", "about:blank");
Services.obs.addObserver(observer, "browser-delayed-startup-finished", false);
}
@ -7673,12 +7688,6 @@ var gIdentityHandler = {
icon_label = this.getEffectiveHost();
}
// We need a port number for all lookups. If one hasn't been specified, use
// the https default
var lookupHost = this._lastLocation.host;
if (lookupHost.indexOf(':') < 0)
lookupHost += ":443";
// 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",
@ -7688,7 +7697,12 @@ var gIdentityHandler = {
// thing here in terms of converting _lastLocation.port from string to int, but
// the overrideService doesn't like undefined ports, so make sure we have
// something in the default case (bug 432241).
if (this._overrideService.hasMatchingOverride(this._lastLocation.hostname,
// .hostname can return an empty string in some exceptional cases -
// hasMatchingOverride does not handle that, so avoid calling it.
// Updating the tooltip value in those cases isn't critical.
// FIXME: Fixing bug 646690 would probably makes this check unnecessary
if (this._lastLocation.hostname &&
this._overrideService.hasMatchingOverride(this._lastLocation.hostname,
(this._lastLocation.port || 443),
iData.cert, {}, {}))
tooltip = gNavigatorBundle.getString("identity.identified.verified_by_you");

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

@ -177,6 +177,7 @@
<panel id="editBookmarkPanel"
type="arrow"
footertype="promobox"
orient="vertical"
ignorekeys="true"
hidden="true"
@ -337,8 +338,13 @@
<menupopup id="placesContext"/>
<panel id="notification-popup" type="arrow" position="after_start"
hidden="true" orient="vertical"/>
<panel id="notification-popup"
type="arrow"
footertype="promobox"
position="after_start"
hidden="true"
orient="vertical"
role="alert"/>
<!-- Popup for site identity information -->
<panel id="identity-popup"

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

@ -626,7 +626,6 @@ function grabAll(elem)
if (elem instanceof HTMLImageElement)
addImage(elem.src, gStrings.mediaImg,
(elem.hasAttribute("alt")) ? elem.alt : gStrings.notSet, elem, false);
#ifdef MOZ_SVG
else if (elem instanceof SVGImageElement) {
try {
// Note: makeURLAbsolute will throw if either the baseURI is not a valid URI
@ -635,7 +634,6 @@ function grabAll(elem)
addImage(href, gStrings.mediaImg, "", elem, false);
} catch (e) { }
}
#endif
#ifdef MOZ_MEDIA
else if (elem instanceof HTMLVideoElement) {
addImage(elem.currentSrc, gStrings.mediaVideo, "", elem, false);
@ -841,9 +839,7 @@ function makePreview(row)
var imageText;
if (!isBG &&
#ifdef MOZ_SVG
!(item instanceof SVGImageElement) &&
#endif
!(gDocument instanceof ImageDocument)) {
imageText = item.title || item.alt;
@ -941,9 +937,7 @@ function makePreview(row)
if ((item instanceof HTMLLinkElement || item instanceof HTMLInputElement ||
item instanceof HTMLImageElement ||
#ifdef MOZ_SVG
item instanceof SVGImageElement ||
#endif
(item instanceof HTMLObjectElement && /^image\//.test(mimeType)) || isBG) && isProtocolAllowed) {
newImage.setAttribute("src", url);
physWidth = newImage.width || 0;
@ -963,12 +957,10 @@ function makePreview(row)
newImage.height = newImage.naturalHeight;
}
#ifdef MOZ_SVG
if (item instanceof SVGImageElement) {
newImage.width = item.width.baseVal.value;
newImage.height = item.height.baseVal.value;
}
#endif
width = newImage.width;
height = newImage.height;

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

@ -54,6 +54,7 @@
id="wizard"
title="&addDevice.title.label;"
windowtype="Sync:AddDevice"
persist="screenX screenY"
onwizardnext="return gSyncAddDevice.onWizardAdvance();"
onwizardback="return gSyncAddDevice.onWizardBack();"
onwizardcancel="gSyncAddDevice.onWizardCancel();"

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

@ -55,6 +55,7 @@
xmlns:html="http://www.w3.org/1999/xhtml"
id="change-dialog"
windowtype="Weave:ChangeSomething"
persist="screenX screenY"
onwizardnext="Change.onLoad()"
onwizardfinish="return Change.onDialogAccept();">

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

@ -51,6 +51,7 @@
<head>
<title>&syncKey.page.title;</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="robots" content="noindex"/>
<style type="text/css">
#synckey { font-size: 150% }
footer { font-size: 70% }

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

@ -50,6 +50,7 @@
]>
<dialog id="quotaDialog"
windowtype="Sync:ViewQuota"
persist="screenX screenY width height"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
onload="gSyncQuota.init()"

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

@ -64,6 +64,7 @@ const RECAPTCHA_DOMAIN = "https://www.google.com";
Cu.import("resource://services-sync/main.js");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/PlacesUtils.jsm");
Cu.import("resource://gre/modules/PluralForm.jsm");
var gSyncSetup = {
@ -822,7 +823,9 @@ var gSyncSetup = {
if (this._case1Setup)
break;
let places_db = Weave.Svc.History.DBConnection;
let places_db = PlacesUtils.history
.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
if (Weave.Engines.get("history").enabled) {
let daysOfHistory = 0;
let stm = places_db.createStatement(
@ -853,7 +856,7 @@ var gSyncSetup = {
"FROM moz_bookmarks b " +
"LEFT JOIN moz_bookmarks t ON " +
"b.parent = t.id WHERE b.type = 1 AND t.parent <> :tag");
stm.params.tag = Weave.Svc.Bookmark.tagsFolder;
stm.params.tag = PlacesUtils.tagsFolderId;
if (stm.executeStep())
bookmarks = stm.row.bookmarks;
// Support %S for historical reasons (see bug 600141)
@ -867,7 +870,7 @@ var gSyncSetup = {
}
if (Weave.Engines.get("passwords").enabled) {
let logins = Weave.Svc.Login.getAllLogins({});
let logins = Services.logins.getAllLogins({});
// Support %S for historical reasons (see bug 600141)
document.getElementById("passwordCount").value =
PluralForm.get(logins.length,

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

@ -54,6 +54,7 @@
]>
<wizard id="accountSetup" title="&accountSetupTitle.label;"
windowtype="Weave:AccountSetup"
persist="screenX screenY"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
onwizardnext="return gSyncSetup.onWizardAdvance()"

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

@ -55,8 +55,8 @@ let gSyncUtils = {
else if (thisDocEl.id == "BrowserPreferences" && !thisDocEl.instantApply)
openUILinkIn(url, "window");
else if (document.documentElement.id == "change-dialog")
Weave.Svc.WinMediator.getMostRecentWindow("navigator:browser")
.openUILinkIn(url, "tab");
Services.wm.getMostRecentWindow("navigator:browser")
.openUILinkIn(url, "tab");
else
openUILinkIn(url, "tab");
},
@ -69,7 +69,7 @@ let gSyncUtils = {
openChange: function openChange(type, duringSetup) {
// Just re-show the dialog if it's already open
let openedDialog = Weave.Svc.WinMediator.getMostRecentWindow("Sync:" + type);
let openedDialog = Services.wm.getMostRecentWindow("Sync:" + type);
if (openedDialog != null) {
openedDialog.focus();
return;
@ -78,8 +78,8 @@ let gSyncUtils = {
// Open up the change dialog
let changeXUL = "chrome://browser/content/syncGenericChange.xul";
let changeOpt = "centerscreen,chrome,resizable=no";
Weave.Svc.WinWatcher.activeWindow.openDialog(changeXUL, "", changeOpt,
type, duringSetup);
Services.ww.activeWindow.openDialog(changeXUL, "", changeOpt,
type, duringSetup);
},
changePassword: function () {

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

@ -95,7 +95,7 @@
<property name="visibleTabs" readonly="true">
<getter><![CDATA[
return Array.filter(this.tabs, function(tab) {
return !tab.hidden && this._removingTabs.indexOf(tab) == -1;
return !tab.hidden && !tab.closing;
}, this);
]]></getter>
</property>
@ -208,7 +208,7 @@
//
// Fixing bug 630826 could make that happen automatically.
// Fixing bug 630830 could avoid the ugly hack below.
let closeMenuItem = document.getElementById("menu_close");
let parentPopup = closeMenuItem.parentNode;
let nextItem = closeMenuItem.nextSibling;
@ -963,6 +963,10 @@
// if the tab is a blank one.
oldBrowser._urlbarFocused = (gURLBar && gURLBar.focused);
if (newBrowser._urlbarFocused && gURLBar) {
// Explicitly close the popup if the URL bar retains focus
gURLBar.closePopup();
if (!window.fullScreen) {
gURLBar.focus();
break;
@ -999,7 +1003,7 @@
<method name="_tabAttrModified">
<parameter name="aTab"/>
<body><![CDATA[
if (this._removingTabs.indexOf(aTab) > -1)
if (aTab.closing)
return;
// This event should be dispatched when any of these attributes change:
@ -1330,9 +1334,9 @@
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL;
try {
b.loadURIWithFlags(aURI, flags, aReferrerURI, aCharset, aPostData);
} catch (ex) {
Cu.reportError(ex);
}
catch (ex) { }
}
// We start our browsers out as inactive, and then maintain
@ -1455,7 +1459,7 @@
// Handle requests for synchronously removing an already
// asynchronously closing tab.
if (!animate &&
this._removingTabs.indexOf(aTab) > -1) {
aTab.closing) {
this._endRemoveTab(aTab);
return;
}
@ -1509,7 +1513,7 @@
<parameter name="aCloseWindowFastpath"/>
<body>
<![CDATA[
if (this._removingTabs.indexOf(aTab) > -1 || this._windowIsClosing)
if (aTab.closing || this._windowIsClosing)
return false;
var browser = this.getBrowserForTab(aTab);
@ -1539,6 +1543,7 @@
newTab = true;
}
aTab.closing = true;
this._removingTabs.push(aTab);
if (newTab)
this.addTab("about:blank", {skipAnimation: true});
@ -1707,7 +1712,7 @@
if (aTab.owner &&
!aTab.owner.hidden &&
this._removingTabs.indexOf(aTab.owner) == -1 &&
!aTab.owner.closing &&
Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose")) {
this.selectedTab = aTab.owner;
return;
@ -1718,7 +1723,7 @@
let numTabs = remainingTabs.length;
if (numTabs == 0 || numTabs == 1 && remainingTabs[0] == aTab) {
remainingTabs = Array.filter(this.tabs, function(tab) {
return this._removingTabs.indexOf(tab) == -1;
return !tab.closing;
}, this);
}
@ -1933,7 +1938,7 @@
<body>
<![CDATA[
if (!aTab.hidden && !aTab.pinned && !aTab.selected &&
this._removingTabs.indexOf(aTab) == -1) {
!aTab.closing) {
aTab.setAttribute("hidden", "true");
this.tabContainer.adjustTabstrip();
let event = document.createEvent("Events");
@ -2948,8 +2953,7 @@
<body><![CDATA[
var numPinned = this.tabbrowser._numPinnedTabs;
var doPosition = this.getAttribute("overflow") == "true" &&
numPinned > 0 &&
numPinned < this.tabbrowser.visibleTabs.length;
numPinned > 0;
if (doPosition) {
this.setAttribute("positionpinnedtabs", "true");
@ -3077,7 +3081,7 @@
var tab = this._getDragTargetTab(event);
if (window.getComputedStyle(this, null).direction == "ltr") {
for (let i = tab ? tab._tPos : 0; i < tabs.length; i++)
if (event.screenX < tabs[i].boxObject.screenX + tabs[i].boxObject.width / 2)
if (event.screenX < tabs[i].boxObject.screenX + tabs[i].boxObject.width / 2)
return i;
} else {
for (let i = tab ? tab._tPos : 0; i < tabs.length; i++)
@ -3171,7 +3175,7 @@
<parameter name="aTab"/>
<body>
<![CDATA[
return this.tabbrowser._removingTabs.indexOf(aTab) == -1;
return !aTab.closing;
]]>
</body>
</method>
@ -3194,7 +3198,7 @@
if (tab.getAttribute("fadein") == "true")
this._handleNewTab(tab);
else if (this.tabbrowser._removingTabs.indexOf(tab) > -1)
else if (tab.closing)
this.tabbrowser._endRemoveTab(tab);
]]></handler>
@ -3337,7 +3341,7 @@
var scrollRect = tabStrip.scrollClientRect;
var rect = this.getBoundingClientRect();
var minMargin = scrollRect.left - rect.left;
var maxMargin = Math.min(minMargin + scrollRect.width,
var maxMargin = Math.min(minMargin + scrollRect.width,
scrollRect.right);
if (!ltr)
[minMargin, maxMargin] = [this.clientWidth - maxMargin,
@ -3635,6 +3639,7 @@
<field name="mOverCloseButton">false</field>
<field name="mCorrespondingMenuitem">null</field>
<field name="_fullyOpen">false</field>
<field name="closing">false</field>
</implementation>
<handlers>
@ -3746,7 +3751,7 @@
continue;
if (curTabBO.screenX >= tabstripBO.screenX &&
curTabBO.screenX + curTabBO.width <= tabstripBO.screenX + tabstripBO.width)
this.childNodes[i].setAttribute("tabIsVisible", "true");
this.childNodes[i].setAttribute("tabIsVisible", "true");
else
this.childNodes[i].removeAttribute("tabIsVisible");
}
@ -3757,7 +3762,7 @@
<parameter name="aTab"/>
<body><![CDATA[
var menuItem = document.createElementNS(
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
"menuitem");
menuItem.setAttribute("class", "menuitem-iconic alltabs-item menuitem-with-favicon");

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

@ -2032,7 +2032,7 @@ let GroupItems = {
if (UI.shouldLoadFavIcon(xulTab.linkedBrowser))
iconUrl = UI.getFavIconUrlForTab(xulTab);
else
iconUrl = Utils.defaultFaviconURL;
iconUrl = gFavIconService.defaultFavicon.spec;
return iconUrl;
},
@ -2107,7 +2107,9 @@ let GroupItems = {
let activeGroupId = this._activeGroupItem ? this._activeGroupItem.id : null;
Storage.saveGroupItemsData(
gWindow, { nextID: this.nextID, activeGroupId: activeGroupId });
gWindow,
{ nextID: this.nextID, activeGroupId: activeGroupId,
totalNumber: this.groupItems.length });
},
// ----------

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

@ -608,7 +608,7 @@ iQClass.prototype = {
});
this.css({
'-moz-transition-property': 'all', // TODO: just animate the properties we're changing
'-moz-transition-property': Object.keys(css).join(", "),
'-moz-transition-duration': (duration / 1000) + 's',
'-moz-transition-timing-function': easing
});

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

@ -57,10 +57,7 @@ let AllTabs = {
get tabs() {
// Get tabs from each browser window and flatten them into one array
return Array.concat.apply(null, browserWindows.map(function(browserWindow) {
let removingTabs = browserWindow.gBrowser._removingTabs;
return Array.filter(browserWindow.gBrowser.tabs, function (tab) {
return removingTabs.indexOf(tab) == -1;
});
return Array.filter(browserWindow.gBrowser.tabs, function (tab) !tab.closing);
}));
},

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

@ -490,8 +490,6 @@ Subscribable.prototype = {
// Class: Utils
// Singelton with common utility functions.
let Utils = {
defaultFaviconURL: "chrome://mozapps/skin/places/defaultFavicon.png",
// ----------
// Function: toString
// Prints [Utils] for debug use

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

@ -47,8 +47,6 @@ let Storage = {
GROUPS_DATA_IDENTIFIER: "tabview-groups",
TAB_DATA_IDENTIFIER: "tabview-tab",
UI_DATA_IDENTIFIER: "tabview-ui",
CACHE_CLIENT_IDENTIFIER: "tabview-cache",
CACHE_PREFIX: "moz-panorama:",
// ----------
// Function: toString
@ -64,28 +62,12 @@ let Storage = {
this._sessionStore =
Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore);
// Create stream-based cache session for tabview
let cacheService =
Cc["@mozilla.org/network/cache-service;1"].
getService(Ci.nsICacheService);
this._cacheSession = cacheService.createSession(
this.CACHE_CLIENT_IDENTIFIER, Ci.nsICache.STORE_ON_DISK, true);
this.StringInputStream = Components.Constructor(
"@mozilla.org/io/string-input-stream;1", "nsIStringInputStream",
"setData");
this.StorageStream = Components.Constructor(
"@mozilla.org/storagestream;1", "nsIStorageStream",
"init");
},
// ----------
// Function: uninit
uninit: function Storage_uninit () {
this._sessionStore = null;
this._cacheSession = null;
this.StringInputStream = null;
this.StorageStream = null;
},
// ----------
@ -114,137 +96,6 @@ let Storage = {
}
},
// ----------
// Function: _openCacheEntry
// Opens a cache entry for the given <url> and requests access <access>.
// Calls <successCallback>(entry) when the entry was successfully opened with
// requested access rights. Otherwise calls <errorCallback>().
_openCacheEntry: function Storage__openCacheEntry(url, access, successCallback, errorCallback) {
let onCacheEntryAvailable = function (entry, accessGranted, status) {
if (entry && access == accessGranted && Components.isSuccessCode(status)) {
successCallback(entry);
} else {
entry && entry.close();
errorCallback();
}
}
let key = this.CACHE_PREFIX + url;
// switch to synchronous mode if parent window is about to close
if (UI.isDOMWindowClosing) {
let entry = this._cacheSession.openCacheEntry(key, access, true);
let status = Components.results.NS_OK;
onCacheEntryAvailable(entry, entry.accessGranted, status);
} else {
let listener = new CacheListener(onCacheEntryAvailable);
this._cacheSession.asyncOpenCacheEntry(key, access, listener);
}
},
// ----------
// Function: saveThumbnail
// Saves the <imageData> to the cache using the given <url> as key.
// Calls <callback>(status) when finished (passing true or false indicating
// whether the operation succeeded).
saveThumbnail: function Storage_saveThumbnail(url, imageData, callback) {
Utils.assert(url, "url");
Utils.assert(imageData, "imageData");
Utils.assert(typeof callback == "function", "callback arg must be a function");
let self = this;
let StringInputStream = this.StringInputStream;
let onCacheEntryAvailable = function (entry) {
let outputStream = entry.openOutputStream(0);
let cleanup = function () {
outputStream.close();
entry.close();
}
// switch to synchronous mode if parent window is about to close
if (UI.isDOMWindowClosing) {
outputStream.write(imageData, imageData.length);
cleanup();
callback(true);
return;
}
// asynchronous mode
let inputStream = new StringInputStream(imageData, imageData.length);
gNetUtil.asyncCopy(inputStream, outputStream, function (result) {
cleanup();
inputStream.close();
callback(Components.isSuccessCode(result));
});
}
let onCacheEntryUnavailable = function () {
callback(false);
}
this._openCacheEntry(url, Ci.nsICache.ACCESS_WRITE,
onCacheEntryAvailable, onCacheEntryUnavailable);
},
// ----------
// Function: loadThumbnail
// Asynchrously loads image data from the cache using the given <url> as key.
// Calls <callback>(status, data) when finished, passing true or false
// (indicating whether the operation succeeded) and the retrieved image data.
loadThumbnail: function Storage_loadThumbnail(url, callback) {
Utils.assert(url, "url");
Utils.assert(typeof callback == "function", "callback arg must be a function");
let self = this;
let onCacheEntryAvailable = function (entry) {
let imageChunks = [];
let nativeInputStream = entry.openInputStream(0);
const CHUNK_SIZE = 0x10000; // 65k
const PR_UINT32_MAX = 0xFFFFFFFF;
let storageStream = new self.StorageStream(CHUNK_SIZE, PR_UINT32_MAX, null);
let storageOutStream = storageStream.getOutputStream(0);
let cleanup = function () {
nativeInputStream.close();
storageStream.close();
storageOutStream.close();
entry.close();
}
gNetUtil.asyncCopy(nativeInputStream, storageOutStream, function (result) {
// cancel if parent window has already been closed
if (typeof UI == "undefined") {
cleanup();
return;
}
let imageData = null;
let isSuccess = Components.isSuccessCode(result);
if (isSuccess) {
let storageInStream = storageStream.newInputStream(0);
imageData = gNetUtil.readInputStreamToString(storageInStream,
storageInStream.available());
storageInStream.close();
}
cleanup();
callback(isSuccess, imageData);
});
}
let onCacheEntryUnavailable = function () {
callback(false);
}
this._openCacheEntry(url, Ci.nsICache.ACCESS_READ,
onCacheEntryAvailable, onCacheEntryUnavailable);
},
// ----------
// Function: saveTab
// Saves the data for a single tab.
@ -255,16 +106,9 @@ let Storage = {
let imageData = data.imageData;
// Remove imageData from payload
delete data.imageData;
if (imageData != null) {
this.saveThumbnail(data.url, imageData, function (status) {
if (status) {
// Notify subscribers
tab._tabViewTabItem._sendToSubscribers("savedCachedImageData");
} else {
Utils.log("Error while saving thumbnail: " + e);
}
});
}
if (imageData != null)
ThumbnailStorage.saveThumbnail(tab, imageData);
}
this._sessionStore.setTabValue(tab, this.TAB_DATA_IDENTIFIER,
@ -292,18 +136,13 @@ let Storage = {
}
if (existingData) {
this.loadThumbnail(existingData.url, function (status, imageData) {
if (status) {
ThumbnailStorage.loadThumbnail(
tab, existingData.url,
function(status, imageData) {
callback(imageData);
// Notify subscribers
tab._tabViewTabItem._sendToSubscribers("loadedCachedImageData");
} else {
Utils.log("Error while loading thumbnail");
}
});
);
}
return existingData;
},
@ -409,26 +248,3 @@ let Storage = {
}
};
// ##########
// Class: CacheListener
// Generic CacheListener for feeding to asynchronous cache calls.
// Calls <callback>(entry, access, status) when the requested cache entry
// is available.
function CacheListener(callback) {
Utils.assert(typeof callback == "function", "callback arg must be a function");
this.callback = callback;
};
CacheListener.prototype = {
// ----------
// Function: toString
// Prints [CacheListener] for debug use
toString: function CacheListener_toString() {
return "[CacheListener]";
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsICacheListener]),
onCacheEntryAvailable: function (entry, access, status) {
this.callback(entry, access, status);
}
};

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

@ -1558,6 +1558,6 @@ TabCanvas.prototype = {
// ----------
// Function: toImageData
toImageData: function TabCanvas_toImageData() {
return this.canvas.toDataURL("image/png", "");
return this.canvas.toDataURL("image/png");
}
};

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

@ -1,6 +1,7 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
Cu.import("resource:///modules/tabview/AllTabs.jsm");
Cu.import("resource:///modules/tabview/utils.jsm");
@ -50,5 +51,6 @@ var gTabViewFrame = gWindow.document.getElementById("tab-view");
#include tabitems.js
#include drag.js
#include trench.js
#include thumbnailStorage.js
#include ui.js
#include search.js

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

@ -0,0 +1,373 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is thumbnailStorage.js.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Raymond Lee <raymond@appcoast.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
// **********
// Title: thumbnailStorage.js
// ##########
// Class: ThumbnailStorage
// Singleton for persistent storage of thumbnail data.
let ThumbnailStorage = {
CACHE_CLIENT_IDENTIFIER: "tabview-cache",
CACHE_PREFIX: "moz-panorama:",
PREF_DISK_CACHE_SSL: "browser.cache.disk_cache_ssl",
// Holds the cache session reference
_cacheSession: null,
// Holds the string input stream reference
_stringInputStream: null,
// Holds the storage stream reference
_storageStream: null,
// Holds the progress listener reference
_progressListener: null,
// Used to keep track of disk_cache_ssl preference
enablePersistentHttpsCaching: null,
// Used to keep track of browsers whose thumbs we shouldn't save
excludedBrowsers: [],
// ----------
// Function: toString
// Prints [ThumbnailStorage] for debug use.
toString: function ThumbnailStorage_toString() {
return "[ThumbnailStorage]";
},
// ----------
// Function: init
// Should be called when UI is initialized.
init: function ThumbnailStorage_init() {
// Create stream-based cache session for tabview
let cacheService =
Cc["@mozilla.org/network/cache-service;1"].
getService(Ci.nsICacheService);
this._cacheSession = cacheService.createSession(
this.CACHE_CLIENT_IDENTIFIER, Ci.nsICache.STORE_ON_DISK, true);
this._stringInputStream = Components.Constructor(
"@mozilla.org/io/string-input-stream;1", "nsIStringInputStream",
"setData");
this._storageStream = Components.Constructor(
"@mozilla.org/storagestream;1", "nsIStorageStream",
"init");
// store the preference value
this.enablePersistentHttpsCaching =
Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
Services.prefs.addObserver(this.PREF_DISK_CACHE_SSL, this, false);
let self = this;
// tabs are already loaded before UI is initialized so cache-control
// values are unknown. We add browsers with https to the list for now.
gBrowser.browsers.forEach(function(browser) {
let checkAndAddToList = function(browserObj) {
if (!self.enablePersistentHttpsCaching &&
browserObj.currentURI.schemeIs("https"))
self.excludedBrowsers.push(browserObj);
};
if (browser.contentDocument.readyState != "complete" ||
browser.webProgress.isLoadingDocument) {
browser.addEventListener("load", function() {
browser.removeEventListener("load", arguments.callee, true);
checkAndAddToList(browser);
}, true);
} else {
checkAndAddToList(browser);
}
});
gBrowser.addTabsProgressListener(this);
},
// Function: uninit
// Should be called when window is unloaded.
uninit: function ThumbnailStorage_uninit() {
gBrowser.removeTabsProgressListener(this);
Services.prefs.removeObserver(this.PREF_DISK_CACHE_SSL, this);
},
// ----------
// Function: _openCacheEntry
// Opens a cache entry for the given <url> and requests access <access>.
// Calls <successCallback>(entry) when the entry was successfully opened with
// requested access rights. Otherwise calls <errorCallback>().
_openCacheEntry: function ThumbnailStorage__openCacheEntry(url, access, successCallback, errorCallback) {
let onCacheEntryAvailable = function(entry, accessGranted, status) {
if (entry && access == accessGranted && Components.isSuccessCode(status)) {
successCallback(entry);
} else {
entry && entry.close();
errorCallback();
}
}
let key = this.CACHE_PREFIX + url;
// switch to synchronous mode if parent window is about to close
if (UI.isDOMWindowClosing) {
let entry = this._cacheSession.openCacheEntry(key, access, true);
let status = Cr.NS_OK;
onCacheEntryAvailable(entry, entry.accessGranted, status);
} else {
let listener = new CacheListener(onCacheEntryAvailable);
this._cacheSession.asyncOpenCacheEntry(key, access, listener);
}
},
// Function: _shouldSaveThumbnail
// Checks whether to save tab's thumbnail or not.
_shouldSaveThumbnail : function ThumbnailStorage__shouldSaveThumbnail(tab) {
return (this.excludedBrowsers.indexOf(tab.linkedBrowser) == -1);
},
// ----------
// Function: saveThumbnail
// Saves the <imageData> to the cache using the given <url> as key.
// Calls <callback>(status, data) when finished, passing true or false
// (indicating whether the operation succeeded).
saveThumbnail: function ThumbnailStorage_saveThumbnail(tab, imageData, callback) {
Utils.assert(tab, "tab");
Utils.assert(imageData, "imageData");
if (!this._shouldSaveThumbnail(tab)) {
tab._tabViewTabItem._sendToSubscribers("deniedToCacheImageData");
if (callback)
callback(false);
return;
}
let self = this;
let completed = function(status) {
if (callback)
callback(status);
if (status) {
// Notify subscribers
tab._tabViewTabItem._sendToSubscribers("savedCachedImageData");
} else {
Utils.log("Error while saving thumbnail: " + e);
}
};
let onCacheEntryAvailable = function(entry) {
let outputStream = entry.openOutputStream(0);
let cleanup = function() {
outputStream.close();
entry.close();
}
// switch to synchronous mode if parent window is about to close
if (UI.isDOMWindowClosing) {
outputStream.write(imageData, imageData.length);
cleanup();
completed(true);
return;
}
// asynchronous mode
let inputStream = new self._stringInputStream(imageData, imageData.length);
gNetUtil.asyncCopy(inputStream, outputStream, function (result) {
cleanup();
inputStream.close();
completed(Components.isSuccessCode(result));
});
}
let onCacheEntryUnavailable = function() {
completed(false);
}
this._openCacheEntry(tab.linkedBrowser.currentURI.spec,
Ci.nsICache.ACCESS_WRITE, onCacheEntryAvailable,
onCacheEntryUnavailable);
},
// ----------
// Function: loadThumbnail
// Asynchrously loads image data from the cache using the given <url> as key.
// Calls <callback>(status, data) when finished, passing true or false
// (indicating whether the operation succeeded) and the retrieved image data.
loadThumbnail: function ThumbnailStorage_loadThumbnail(tab, url, callback) {
Utils.assert(tab, "tab");
Utils.assert(url, "url");
Utils.assert(typeof callback == "function", "callback arg must be a function");
let self = this;
let completed = function(status, imageData) {
callback(status, imageData);
if (status) {
// Notify subscribers
tab._tabViewTabItem._sendToSubscribers("loadedCachedImageData");
} else {
Utils.log("Error while loading thumbnail");
}
}
let onCacheEntryAvailable = function(entry) {
let imageChunks = [];
let nativeInputStream = entry.openInputStream(0);
const CHUNK_SIZE = 0x10000; // 65k
const PR_UINT32_MAX = 0xFFFFFFFF;
let storageStream = new self._storageStream(CHUNK_SIZE, PR_UINT32_MAX, null);
let storageOutStream = storageStream.getOutputStream(0);
let cleanup = function () {
nativeInputStream.close();
storageStream.close();
storageOutStream.close();
entry.close();
}
gNetUtil.asyncCopy(nativeInputStream, storageOutStream, function (result) {
// cancel if parent window has already been closed
if (typeof UI == "undefined") {
cleanup();
return;
}
let imageData = null;
let isSuccess = Components.isSuccessCode(result);
if (isSuccess) {
let storageInStream = storageStream.newInputStream(0);
imageData = gNetUtil.readInputStreamToString(storageInStream,
storageInStream.available());
storageInStream.close();
}
cleanup();
completed(isSuccess, imageData);
});
}
let onCacheEntryUnavailable = function() {
completed(false);
}
this._openCacheEntry(url, Ci.nsICache.ACCESS_READ,
onCacheEntryAvailable, onCacheEntryUnavailable);
},
// ----------
// Function: observe
// Implements the observer interface.
observe: function ThumbnailStorage_observe(subject, topic, data) {
this.enablePersistentHttpsCaching =
Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
},
// ----------
// Implements progress listener interface.
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference,
Ci.nsISupports]),
onStateChange: function ThumbnailStorage_onStateChange(
browser, webProgress, request, flag, status) {
if (flag & Ci.nsIWebProgressListener.STATE_START &&
flag & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
// ensure the dom window is the top one
if (webProgress.DOMWindow.parent == webProgress.DOMWindow) {
let index = this.excludedBrowsers.indexOf(browser);
if (index != -1)
this.excludedBrowsers.splice(index, 1);
}
}
if (flag & Ci.nsIWebProgressListener.STATE_STOP &&
flag & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
// ensure the dom window is the top one
if (webProgress.DOMWindow.parent == webProgress.DOMWindow &&
request && request instanceof Ci.nsIHttpChannel) {
request.QueryInterface(Ci.nsIHttpChannel);
let inhibitPersistentThumb = false;
if (request.isNoStoreResponse()) {
inhibitPersistentThumb = true;
} else if (!this.enablePersistentHttpsCaching &&
request.URI.schemeIs("https")) {
let cacheControlHeader;
try {
cacheControlHeader = request.getResponseHeader("Cache-Control");
} catch(e) {
// this error would occur when "Cache-Control" doesn't exist in
// the eaders
}
if (cacheControlHeader && !(/public/i).test(cacheControlHeader))
inhibitPersistentThumb = true;
}
if (inhibitPersistentThumb &&
this.excludedBrowsers.indexOf(browser) == -1)
this.excludedBrowsers.push(browser);
}
}
}
}
// ##########
// Class: CacheListener
// Generic CacheListener for feeding to asynchronous cache calls.
// Calls <callback>(entry, access, status) when the requested cache entry
// is available.
function CacheListener(callback) {
Utils.assert(typeof callback == "function", "callback arg must be a function");
this.callback = callback;
};
CacheListener.prototype = {
// ----------
// Function: toString
// Prints [CacheListener] for debug use
toString: function CacheListener_toString() {
return "[CacheListener]";
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsICacheListener]),
onCacheEntryAvailable: function CacheListener_onCacheEntryAvailable(
entry, access, status) {
this.callback(entry, access, status);
}
};

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

@ -157,6 +157,9 @@ let UI = {
// initialize the direction of the page
this._initPageDirection();
// ___ thumbnail storage
ThumbnailStorage.init();
// ___ storage
Storage.init();
let data = Storage.readUIData(gWindow);
@ -278,7 +281,7 @@ let UI = {
// initialized.
let event = document.createEvent("Events");
event.initEvent("tabviewframeinitialized", true, false);
dispatchEvent(event);
dispatchEvent(event);
} catch(e) {
Utils.log(e);
} finally {
@ -286,6 +289,8 @@ let UI = {
}
},
// Function: uninit
// Should be called when window is unloaded.
uninit: function UI_uninit() {
// call our cleanup functions
this._cleanupFunctions.forEach(function(func) {
@ -297,6 +302,7 @@ let UI = {
TabItems.uninit();
GroupItems.uninit();
Storage.uninit();
ThumbnailStorage.uninit();
this._removeTabActionHandlers();
this._currentTab = null;
@ -680,22 +686,22 @@ let UI = {
// don't reenter Panorama due to all of the session restore tab
// manipulation (which otherwise we might). When transitioning away from
// PB, we reenter Panorama if we had been there directly before PB.
function pbObserver(aSubject, aTopic, aData) {
if (aTopic == "private-browsing") {
function pbObserver(subject, topic, data) {
if (topic == "private-browsing") {
// We could probably do this in private-browsing-change-granted, but
// this seems like a nicer spot, right in the middle of the process.
if (aData == "enter") {
if (data == "enter") {
// If we are in Tab View, exit.
self._privateBrowsing.wasInTabView = self.isTabViewVisible();
if (self.isTabViewVisible())
self.goToTab(gBrowser.selectedTab);
}
} else if (aTopic == "private-browsing-change-granted") {
if (aData == "enter" || aData == "exit") {
self._privateBrowsing.transitionMode = aData;
} else if (topic == "private-browsing-change-granted") {
if (data == "enter" || data == "exit") {
self._privateBrowsing.transitionMode = data;
self.storageBusy();
}
} else if (aTopic == "private-browsing-transition-complete") {
} else if (topic == "private-browsing-transition-complete") {
// We use .transitionMode here, as aData is empty.
if (self._privateBrowsing.transitionMode == "exit" &&
self._privateBrowsing.wasInTabView)
@ -749,8 +755,7 @@ let UI = {
if (gBrowser.tabs.length > 1) {
// Don't return to TabView if there are any app tabs
for (let a = 0; a < gBrowser._numPinnedTabs; a++) {
let theTab = gBrowser.tabs[a];
if (gBrowser._removingTabs.indexOf(theTab) == -1)
if (!gBrowser.tabs[a].closing)
return;
}
@ -956,12 +961,11 @@ let UI = {
// ----------
updateTabButton: function UI__updateTabButton() {
let groupsNumber = gWindow.document.getElementById("tabviewGroupsNumber");
let exitButton = document.getElementById("exit-button");
let numberOfGroups = GroupItems.groupItems.length;
groupsNumber.setAttribute("groups", numberOfGroups);
exitButton.setAttribute("groups", numberOfGroups);
gTabView.updateGroupNumberBroadcaster(numberOfGroups);
},
// ----------
@ -991,20 +995,28 @@ let UI = {
[
#ifdef XP_UNIX
"quitApplication",
#else
"redo",
#endif
#ifdef XP_MACOSX
"preferencesCmdMac", "minimizeWindow",
"preferencesCmdMac", "minimizeWindow", "hideThisAppCmdMac",
#endif
"newNavigator", "newNavigatorTab", "find"
].forEach(function(key) {
"newNavigator", "newNavigatorTab", "undo", "cut", "copy", "paste",
"selectAll", "find"
].forEach(function(key) {
let element = gWindow.document.getElementById("key_" + key);
keys[key] = element.getAttribute("key").toLocaleLowerCase().charCodeAt(0);
});
// for key combinations with shift key, the charCode of upper case letters
// are different to the lower case ones so need to handle them differently.
["closeWindow", "tabview", "undoCloseTab", "undoCloseWindow",
"privatebrowsing"].forEach(function(key) {
[
#ifdef XP_UNIX
"redo",
#endif
"closeWindow", "tabview", "undoCloseTab", "undoCloseWindow",
"privatebrowsing"
].forEach(function(key) {
let element = gWindow.document.getElementById("key_" + key);
keys[key] = element.getAttribute("key").toLocaleUpperCase().charCodeAt(0);
});
@ -1031,6 +1043,10 @@ let UI = {
Keys.meta = true;
function processBrowserKeys(evt) {
// let any keys with alt to pass through
if (evt.altKey)
return;
#ifdef XP_MACOSX
if (evt.metaKey) {
#else
@ -1039,36 +1055,43 @@ let UI = {
let preventDefault = true;
if (evt.shiftKey) {
switch (evt.charCode) {
case self._browserKeys.privatebrowsing:
case self._browserKeys.undoCloseTab:
case self._browserKeys.undoCloseWindow:
case self._browserKeys.closeWindow:
preventDefault = false;
break;
case self._browserKeys.tabview:
self.exit();
break;
#ifdef XP_UNIX
case self._browserKeys.redo:
#endif
case self._browserKeys.closeWindow:
case self._browserKeys.undoCloseTab:
case self._browserKeys.undoCloseWindow:
case self._browserKeys.privatebrowsing:
preventDefault = false;
break;
}
} else {
switch (evt.charCode) {
case self._browserKeys.find:
self.enableSearch();
break;
case self._browserKeys.newNavigator:
case self._browserKeys.newNavigatorTab:
preventDefault = false;
break;
#ifdef XP_UNIX
case self._browserKeys.quitApplication:
preventDefault = false;
break;
#else
case self._browserKeys.redo:
#endif
#ifdef XP_MACOSX
case self._browserKeys.preferencesCmdMac:
case self._browserKeys.minimizeWindow:
case self._browserKeys.hideThisAppCmdMac:
#endif
case self._browserKeys.newNavigator:
case self._browserKeys.newNavigatorTab:
case self._browserKeys.undo:
case self._browserKeys.cut:
case self._browserKeys.copy:
case self._browserKeys.paste:
case self._browserKeys.selectAll:
preventDefault = false;
break;
#endif
}
}
if (preventDefault) {

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

@ -112,7 +112,7 @@ _BROWSER_FILES = \
browser_bug416661.js \
browser_bug417483.js \
browser_bug419612.js \
browser_bug420160.js \
browser_identity_UI.js \
browser_bug422590.js \
browser_bug424101.js \
browser_bug427559.js \
@ -170,7 +170,10 @@ _BROWSER_FILES = \
browser_bug616836.js \
browser_bug623893.js \
browser_bug624734.js \
browser_bug647886.js \
browser_bug655584.js \
browser_findbarClose.js \
browser_keywordBookmarklets.js \
browser_contextSearchTabPosition.js \
browser_ctrlTab.js \
browser_customize_popupNotification.js \
@ -231,7 +234,6 @@ _BROWSER_FILES = \
browser_visibleTabs_bookmarkAllPages.js \
browser_visibleTabs_bookmarkAllTabs.js \
browser_visibleTabs_tabPreview.js \
browser_webdev_menu.js \
bug592338.html \
disablechrome.html \
discovery.html \

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

@ -1,53 +0,0 @@
var listener = {
testFunction: null,
handleEvent: function (e) {
this.testFunction();
}
}
/* Tests for correct behaviour of getEffectiveHost on identity handler */
function test() {
waitForExplicitFinish();
ok(gIdentityHandler, "gIdentityHandler should exist");
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", listener, true);
listener.testFunction = testNormalDomain;
content.location = "http://test1.example.org/";
}
// Greek IDN for 'example.test'.
var idnDomain = "\u03C0\u03B1\u03C1\u03AC\u03B4\u03B5\u03B9\u03B3\u03BC\u03B1.\u03B4\u03BF\u03BA\u03B9\u03BC\u03AE";
function testNormalDomain() {
is(gIdentityHandler._lastLocation.host, 'test1.example.org', "Identity handler is getting the full location");
is(gIdentityHandler.getEffectiveHost(), 'example.org', "getEffectiveHost should return example.org for test1.example.org");
listener.testFunction = testIDNDomain;
content.location = "http://sub1." + idnDomain + "/";
}
function testIDNDomain() {
is(gIdentityHandler._lastLocation.host, "sub1." + idnDomain, "Identity handler is getting the full location");
is(gIdentityHandler.getEffectiveHost(), idnDomain, "getEffectiveHost should return the IDN base domain in UTF-8");
listener.testFunction = testNormalDomainWithPort;
content.location = "http://sub1.test1.example.org:8000/";
}
function testNormalDomainWithPort() {
is(gIdentityHandler._lastLocation.host, 'sub1.test1.example.org:8000', "Identity handler is getting port information");
is(gIdentityHandler.getEffectiveHost(), 'example.org', "getEffectiveHost should return example.org for sub1.test1.example.org:8000");
listener.testFunction = testIPWithPort;
content.location = "http://127.0.0.1:8888/";
}
function testIPWithPort() {
is(gIdentityHandler.getEffectiveHost(), '127.0.0.1', "getEffectiveHost should return 127.0.0.1 for 127.0.0.1:8888");
gBrowser.selectedBrowser.removeEventListener("load", listener, true);
gBrowser.removeCurrentTab();
finish();
}

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

@ -31,7 +31,7 @@ function test() {
content.location =
"data:text/html," +
"<style type='text/css'>#test-image,#not-test-image {background-image: url('about:logo?c');}</style>" +
"<style type='text/css'>%23test-image,%23not-test-image {background-image: url('about:logo?c');}</style>" +
"<img src='about:logo?b' height=300 width=350 alt=2 id='not-test-image'>" +
"<img src='about:logo?b' height=300 width=350 alt=2>" +
"<img src='about:logo?a' height=200 width=250>" +

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

@ -44,6 +44,7 @@ function test() {
// Verify that about:addons loads
waitForExplicitFinish();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
let browser = blanktab.linkedBrowser;
is(browser.currentURI.spec, "about:addons", "about:addons should load into blank tab.");
gBrowser.removeTab(blanktab);

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

@ -0,0 +1,34 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
waitForExplicitFinish();
gBrowser.selectedBrowser.addEventListener("load", function () {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
content.history.pushState({}, "2", "2.html");
testBackButton();
}, true);
loadURI("http://example.com");
}
function testBackButton() {
var backButton = document.getElementById("back-button");
var rect = backButton.getBoundingClientRect();
info("waiting for the history menu to open");
backButton.addEventListener("popupshown", function (event) {
backButton.removeEventListener("popupshown", arguments.callee, false);
ok(true, "history menu opened");
event.target.hidePopup();
finish();
}, false);
EventUtils.synthesizeMouseAtCenter(backButton, {type: "mousedown"});
EventUtils.synthesizeMouse(backButton, rect.width / 2, rect.height, {type: "mouseup"});
}

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

@ -0,0 +1,23 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Bug 655584 - awesomebar suggestions don't update after tab is closed
function test() {
var tab1 = gBrowser.addTab();
var tab2 = gBrowser.addTab();
// When urlbar in a new tab is focused, and a tab switch occurs,
// the urlbar popup should be closed
gBrowser.selectedTab = tab2;
gURLBar.focus(); // focus the urlbar in the tab we will switch to
gBrowser.selectedTab = tab1;
gURLBar.openPopup();
gBrowser.selectedTab = tab2;
ok(!gURLBar.popupOpen, "urlbar focused in tab to switch to, close popup");
// cleanup
gBrowser.removeCurrentTab();
gBrowser.removeCurrentTab();
}

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

@ -11,9 +11,10 @@ function getPostDataString(aIS) {
return dataLines[dataLines.length-1];
}
function keywordResult(aURL, aPostData) {
function keywordResult(aURL, aPostData, aIsUnsafe) {
this.url = aURL;
this.postData = aPostData;
this.isUnsafe = aIsUnsafe;
}
function keyWordData() {}
@ -52,20 +53,20 @@ var testData = [
new keywordResult("http://bmget-nosearch/", null)],
[new searchKeywordData("searchget", "http://searchget/?search={searchTerms}", null, "foo4"),
new keywordResult("http://searchget/?search=foo4", null)],
new keywordResult("http://searchget/?search=foo4", null, true)],
[new searchKeywordData("searchpost", "http://searchpost/", "search={searchTerms}", "foo5"),
new keywordResult("http://searchpost/", "search=foo5")],
new keywordResult("http://searchpost/", "search=foo5", true)],
[new searchKeywordData("searchpostget", "http://searchpostget/?search1={searchTerms}", "search2={searchTerms}", "foo6"),
new keywordResult("http://searchpostget/?search1=foo6", "search2=foo6")],
new keywordResult("http://searchpostget/?search1=foo6", "search2=foo6", true)],
// Bookmark keywords that don't take parameters should not be activated if a
// parameter is passed (bug 420328).
[new bmKeywordData("bmget-noparam", "http://bmget-noparam/", null, "foo7"),
new keywordResult(null, null)],
new keywordResult(null, null, true)],
[new bmKeywordData("bmpost-noparam", "http://bmpost-noparam/", "not_a=param", "foo8"),
new keywordResult(null, null)],
new keywordResult(null, null, true)],
// Test escaping (%s = escaped, %S = raw)
// UTF-8 default
@ -82,6 +83,12 @@ var testData = [
// Explicitly-defined ISO-8859-1
[new bmKeywordData("bmget-escaping2", "http://bmget/?esc=%s&raw=%S&mozcharset=ISO-8859-1", null, "+/@"),
new keywordResult("http://bmget/?esc=%2B%2F%40&raw=+/@", null)],
// Test using a non-bmKeywordData object, to test the behavior of
// getShortcutOrURI for non-keywords (setupKeywords only adds keywords for
// bmKeywordData objects)
[{keyword: "http://gavinsharp.com"},
new keywordResult(null, null, true)]
];
function test() {
@ -94,12 +101,14 @@ function test() {
var query = data.keyword;
if (data.searchWord)
query += " " + data.searchWord;
var url = getShortcutOrURI(query, postData);
var mayInheritPrincipal = {};
var url = getShortcutOrURI(query, postData, mayInheritPrincipal);
// null result.url means we should expect the same query we sent in
var expected = result.url || query;
is(url, expected, "got correct URL for " + data.keyword);
is(getPostDataString(postData.value), result.postData, "got correct postData for " + data.keyword);
is(mayInheritPrincipal.value, !result.isUnsafe, "got correct mayInheritPrincipal for " + data.keyword);
}
cleanupKeywords();

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

@ -0,0 +1,113 @@
/* Tests for correct behaviour of getEffectiveHost on identity handler */
function test() {
waitForExplicitFinish();
ok(gIdentityHandler, "gIdentityHandler should exist");
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", checkResult, true);
nextTest();
}
// Greek IDN for 'example.test'.
var idnDomain = "\u03C0\u03B1\u03C1\u03AC\u03B4\u03B5\u03B9\u03B3\u03BC\u03B1.\u03B4\u03BF\u03BA\u03B9\u03BC\u03AE";
var tests = [
{
name: "normal domain",
location: "http://test1.example.org/",
host: "test1.example.org",
effectiveHost: "example.org"
},
{
name: "view-source",
location: "view-source:http://example.com/",
// TODO: these should not be blank, bug 646690
host: "",
effectiveHost: ""
},
{
name: "normal HTTPS",
location: "https://example.com/",
host: "example.com",
effectiveHost: "example.com",
isHTTPS: true
},
{
name: "IDN subdomain",
location: "http://sub1." + idnDomain + "/",
host: "sub1." + idnDomain,
effectiveHost: idnDomain
},
{
name: "subdomain with port",
location: "http://sub1.test1.example.org:8000/",
host: "sub1.test1.example.org:8000",
effectiveHost: "example.org"
},
{
name: "subdomain HTTPS",
location: "https://test1.example.com",
host: "test1.example.com",
effectiveHost: "example.com",
isHTTPS: true
},
{
name: "view-source HTTPS",
location: "view-source:https://example.com/",
// TODO: these should not be blank, bug 646690
host: "",
effectiveHost: "",
isHTTPS: true
},
{
name: "IP address",
location: "http://127.0.0.1:8888/",
host: "127.0.0.1:8888",
effectiveHost: "127.0.0.1"
},
]
let gCurrentTest, gCurrentTestIndex = -1;
// Go through the tests in both directions, to add additional coverage for
// transitions between different states.
let gForward = true;
function nextTest() {
if (gForward)
gCurrentTestIndex++;
else
gCurrentTestIndex--;
if (gCurrentTestIndex == tests.length) {
// Went too far, reverse
gCurrentTestIndex--;
gForward = false;
}
if (gCurrentTestIndex == -1) {
gBrowser.selectedBrowser.removeEventListener("load", checkResult, true);
gBrowser.removeCurrentTab();
finish();
return;
}
gCurrentTest = tests[gCurrentTestIndex];
gTestDesc = "#" + gCurrentTestIndex + " (" + gCurrentTest.name + ")";
if (!gForward)
gTestDesc += " (second time)";
content.location = gCurrentTest.location;
}
function checkResult() {
if (gCurrentTest.isHTTPS) {
// 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);
executeSoon(nextTest);
}

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

@ -0,0 +1,38 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
waitForExplicitFinish();
let bmFolder = Application.bookmarks.menu.addFolder("keyword-test");
let tab = gBrowser.selectedTab = gBrowser.addTab();
registerCleanupFunction (function () {
bmFolder.remove();
gBrowser.removeTab(tab);
});
let bm = bmFolder.addBookmark("bookmarklet", makeURI("javascript:1;"));
bm.keyword = "bm";
addPageShowListener(function () {
let originalPrincipal = gBrowser.contentPrincipal;
// Enter bookmarklet keyword in the URL bar
gURLBar.value = "bm";
gURLBar.focus();
EventUtils.synthesizeKey("VK_RETURN", {});
addPageShowListener(function () {
ok(gBrowser.contentPrincipal.equals(originalPrincipal), "javascript bookmarklet should inherit principal");
finish();
});
});
}
function addPageShowListener(func) {
gBrowser.selectedBrowser.addEventListener("pageshow", function loadListener() {
gBrowser.selectedBrowser.removeEventListener("pageshow", loadListener, false);
func();
});
}

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

@ -9,30 +9,46 @@ function test() {
let urls = [
"javascript:'foopy';",
"data:text/html,<script>document.write(document.domain);</script>"
"data:text/html,<body>hi"
];
function urlEnter(url) {
gURLBar.value = url;
gURLBar.focus();
EventUtils.synthesizeKey("VK_RETURN", {});
}
function urlClick(url) {
gURLBar.value = url;
gURLBar.focus();
let goButton = document.getElementById("urlbar-go-button");
EventUtils.synthesizeMouseAtCenter(goButton, {});
}
function nextTest() {
let url = urls.shift();
if (url)
testURL(url, nextTest);
if (url) {
testURL(url, urlEnter, function () {
testURL(url, urlClick, nextTest);
});
}
else
finish();
}
function testURL(newURL, func) {
function testURL(url, loadFunc, endFunc) {
let tab = gBrowser.selectedTab = gBrowser.addTab();
registerCleanupFunction(function () {
gBrowser.removeTab(tab);
});
addPageShowListener(function () {
let pagePrincipal = gBrowser.contentPrincipal;
gURLBar.value = newURL;
gURLBar.handleCommand();
loadFunc(url);
addPageShowListener(function () {
ok(!gBrowser.contentPrincipal.equals(pagePrincipal), "load of " + newURL + " produced a page with a different principal");
func();
ok(!gBrowser.contentPrincipal.equals(pagePrincipal),
"load of " + url + " by " + loadFunc.name + " should produce a page with a different principal");
endFunc();
});
});
}

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

@ -54,6 +54,9 @@ function test() {
testVal("<http://sub.>mozilla.org<:666/file.ext>");
testVal("<http://>[fe80::222:19ff:fe11:8c76]</file.ext>");
testVal("<http://user:pass@>[fe80::222:19ff:fe11:8c76]<:666/file.ext>");
testVal("mailto:admin@mozilla.org");
testVal("gopher://mozilla.org/");
testVal("about:config");

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

@ -1,43 +0,0 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function menuTest()
{
gBrowser.selectedBrowser.removeEventListener("load", menuTest, true);
let menuContents = [
"menu_pageinspect",
"webConsole",
"menu_scratchpad",
"menu_pageSource",
"javascriptConsole"
];
let menu = document.getElementById("webDeveloperMenu");
ok(menu, "we have the menu");
let popup = menu.firstChild;
is(popup.id, "menuWebDeveloperPopup", "menu first child is menuWebDeveloperPopup");
is(popup.childNodes.length, menuContents.length, "popup childNodes.length matches");
for(let a = 0; a < popup.children.length; a++) {
isnot(menuContents.indexOf(popup.children[a].id), -1, "menuitem " + popup.children[a].id + " in popup");
};
gBrowser.removeCurrentTab();
finish();
}
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", menuTest, true);
content.location = "data:text/html,<title>Web Developer Menu Test</title>" +
"<p>testing the Web Developer Menu";
}

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

@ -18,12 +18,27 @@ function test() {
waitForExplicitFinish();
ok(gFindBar.hidden, "Find bar should not be visible");
run_test_1();
nextTest();
}
function run_test_1() {
load("about:config", function() {
let urls = [
"about:config",
"about:addons",
"about:permissions"
];
function nextTest() {
let url = urls.shift();
if (url) {
testFindDisabled(url, nextTest);
} else {
// Make sure the find bar is re-enabled after disabled page is closed.
testFindEnabled("about:blank", finish);
}
}
function testFindDisabled(url, cb) {
load(url, function() {
ok(gFindBar.hidden, "Find bar should not be visible");
EventUtils.synthesizeKey("/", {}, gTab.linkedBrowser.contentWindow);
ok(gFindBar.hidden, "Find bar should not be visible");
@ -33,31 +48,16 @@ function run_test_1() {
"Find command should be disabled");
gBrowser.removeTab(gTab);
run_test_2();
cb();
});
}
function run_test_2() {
load("about:addons", function() {
ok(gFindBar.hidden, "Find bar should not be visible");
EventUtils.synthesizeKey("/", {}, gTab.linkedBrowser.contentWindow);
ok(gFindBar.hidden, "Find bar should not be visible");
EventUtils.synthesizeKey("f", { accelKey: true });
ok(gFindBar.hidden, "Find bar should not be visible");
ok(document.getElementById("cmd_find").getAttribute("disabled"),
"Find command should be disabled");
gBrowser.removeTab(gTab);
run_test_3();
});
}
function run_test_3() {
load("about:blank", function() {
function testFindEnabled(url, cb) {
load(url, function() {
ok(!document.getElementById("cmd_find").getAttribute("disabled"),
"Find command should not be disabled");
gBrowser.removeTab(gTab);
finish();
cb();
});
}
}

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

@ -113,8 +113,10 @@ _BROWSER_FILES = \
browser_tabview_bug626368.js \
browser_tabview_bug626525.js \
browser_tabview_bug626791.js \
browser_tabview_bug627239.js \
browser_tabview_bug627288.js \
browser_tabview_bug627736.js \
browser_tabview_bug628061.js \
browser_tabview_bug628165.js \
browser_tabview_bug628270.js \
browser_tabview_bug629189.js \

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

@ -15,12 +15,12 @@ function test() {
}
// very long page that produces black bars at the right
let html1 = '<html><body style="background-color: #00f;">' +
'<div style="background: #fff; width: 95%; height: 10000px; ' +
let html1 = '<html><body style="background-color: %2300f;">' +
'<div style="background: %23fff; width: 95%; height: 10000px; ' +
' margin: 0 auto;"></div></body></html>';
// very short page that produces black bars at the bottom
let html2 = '<html><body style="background-color: #00f;"></body></html>';
let html2 = '<html><body style="background-color: %2300f;"></body></html>';
let tests = [{
url: 'data:text/html,' + html1,

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

@ -1,6 +1,9 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const fi = Cc["@mozilla.org/browser/favicon-service;1"].
getService(Ci.nsIFaviconService);
let newTab;
function test() {
@ -27,7 +30,7 @@ function onTabViewWindowLoaded() {
is($icon.data("xulTab"), newTab,
"The app tab icon has the right tab reference")
// check to see whether it's showing the default one or not.
is($icon.attr("src"), contentWindow.Utils.defaultFaviconURL,
is($icon.attr("src"), fi.defaultFavicon.spec,
"The icon is showing the default fav icon for blank tab");
let errorHandler = function(event) {
@ -37,7 +40,7 @@ function onTabViewWindowLoaded() {
// fired, a delay is used here to avoid the test code run before the browser
// code.
executeSoon(function() {
is($icon.attr("src"), contentWindow.Utils.defaultFaviconURL,
is($icon.attr("src"), fi.defaultFavicon.spec,
"The icon is showing the default fav icon");
// clean up

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

@ -2,8 +2,9 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
let url = "http://non.existant/url";
let url = "http://www.example.com/";
let cw;
let tab = gBrowser.tabs[0];
let finishTest = function () {
is(1, gBrowser.tabs.length, "there is one tab, only");
@ -14,7 +15,7 @@ function test() {
waitForExplicitFinish();
let testErroneousLoading = function () {
cw.Storage.loadThumbnail(url, function (status, data) {
cw.ThumbnailStorage.loadThumbnail(tab, url, function (status, data) {
ok(!status, "thumbnail entry failed to load");
is(null, data, "no thumbnail data received");
next();
@ -25,11 +26,11 @@ function test() {
let saved = false;
let data = "thumbnail-data-asynchronous";
cw.Storage.saveThumbnail(url, data, function (status) {
cw.ThumbnailStorage.saveThumbnail(tab, data, function (status) {
ok(status, "thumbnail entry was saved");
ok(saved, "thumbnail was saved asynchronously");
cw.Storage.loadThumbnail(url, function (status, imageData) {
cw.ThumbnailStorage.loadThumbnail(tab, url, function (status, imageData) {
ok(status, "thumbnail entry was loaded");
is(imageData, data, "valid thumbnail data received");
next();
@ -46,11 +47,11 @@ function test() {
cw.UI.isDOMWindowClosing = true;
registerCleanupFunction(function () cw.UI.isDOMWindowClosing = false);
cw.Storage.saveThumbnail(url, data, function (status) {
cw.ThumbnailStorage.saveThumbnail(tab, data, function (status) {
ok(status, "thumbnail entry was saved");
ok(!saved, "thumbnail was saved synchronously");
cw.Storage.loadThumbnail(url, function (status, imageData) {
cw.ThumbnailStorage.loadThumbnail(tab, url, function (status, imageData) {
ok(status, "thumbnail entry was loaded");
is(imageData, data, "valid thumbnail data received");
@ -72,10 +73,13 @@ function test() {
hideTabView(finishTest);
}
showTabView(function () {
registerCleanupFunction(function () TabView.hide());
cw = TabView.getContentWindow();
tab.linkedBrowser.loadURI(url);
afterAllTabsLoaded(function() {
showTabView(function () {
registerCleanupFunction(function () TabView.hide());
cw = TabView.getContentWindow();
next();
next();
});
});
}

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

@ -19,15 +19,6 @@ function test() {
is(gBrowser.visibleTabs.length, numTabs, 'There should be ' + numTabs + ' visible tabs');
}
let restoreTab = function (callback) {
let tab = undoCloseTab(0);
tab._tabViewTabItem.addSubscriber(tab, 'reconnected', function () {
tab._tabViewTabItem.removeSubscriber(tab, 'reconnected');
afterAllTabsLoaded(callback);
});
}
let next = function () {
while (gBrowser.tabs.length-1)
gBrowser.removeTab(gBrowser.tabs[1]);
@ -86,7 +77,7 @@ function test() {
let tab = gBrowser.loadOneTab('http://mochi.test:8888/#1', {inBackground: true});
gBrowser.selectedTab = tab;
let continueTest = function () {
afterAllTabsLoaded(function () {
tab.linkedBrowser.loadURI('http://mochi.test:8888/#2');
afterAllTabsLoaded(function () {
@ -106,13 +97,7 @@ function test() {
});
});
});
}
// The executeSoon() call is really needed here because there's probably
// some callback waiting to be fired after gBrowser.loadOneTab(). After
// that the browser is in a state where loadURI() will create a new entry
// in the session history (that is vital for back/forward functionality).
afterAllTabsLoaded(function () executeSoon(continueTest));
});
}
// ----------
@ -156,45 +141,30 @@ function test() {
// ----------
function loadTabView(callback) {
window.addEventListener('tabviewshown', function () {
window.removeEventListener('tabviewshown', arguments.callee, false);
hideTabView(function () {
window.removeEventListener('tabviewhidden', arguments.callee, false);
callback();
});
}, false);
TabView.show();
}
// ----------
function hideTabView(callback) {
if (!TabView.isVisible())
return callback();
window.addEventListener('tabviewhidden', function () {
window.removeEventListener('tabviewhidden', arguments.callee, false);
callback();
}, false);
TabView.hide();
showTabView(function () {
hideTabView(callback);
});
}
// ----------
function enterAndLeavePrivateBrowsing(callback) {
togglePrivateBrowsing(function () {
togglePrivateBrowsing(callback);
});
}
// ----------
function togglePrivateBrowsing(callback) {
let topic = "private-browsing-transition-complete";
function pbObserver(aSubject, aTopic, aData) {
if (aTopic != "private-browsing-transition-complete")
if (aTopic != topic)
return;
if (pb.privateBrowsingEnabled)
pb.privateBrowsingEnabled = false;
else {
Services.obs.removeObserver(pbObserver, "private-browsing-transition-complete");
afterAllTabsLoaded(function () executeSoon(callback));
}
Services.obs.removeObserver(pbObserver, topic, false);
afterAllTabsLoaded(callback);
}
Services.obs.addObserver(pbObserver, "private-browsing-transition-complete", false);
pb.privateBrowsingEnabled = true;
Services.obs.addObserver(pbObserver, topic, false);
pb.privateBrowsingEnabled = !pb.privateBrowsingEnabled;
}

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

@ -0,0 +1,156 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let contentWindow;
let enablePersistentHttpsCaching;
let newTab;
function test() {
waitForExplicitFinish();
newTab = gBrowser.addTab();
HttpRequestObserver.register();
registerCleanupFunction(function () {
HttpRequestObserver.unregister();
if (gBrowser.tabs[1])
gBrowser.removeTab(gBrowser.tabs[1]);
hideTabView(function () {});
contentWindow.ThumbnailStorage.enablePersistentHttpsCaching =
enablePersistentHttpsCaching;
});
showTabView(function() {
contentWindow = TabView.getContentWindow();
test1();
});
}
function test1() {
// page with cache-control: no-store, should not save thumbnail
HttpRequestObserver.cacheControlValue = "no-store";
newTab.linkedBrowser.loadURI("http://www.example.com/browser/browser/base/content/test/tabview/dummy_page.html");
afterAllTabsLoaded(function() {
let tabItem = newTab._tabViewTabItem;
ok(!contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
"Should not save the thumbnail for tab");
tabItem.addSubscriber(tabItem, "deniedToCacheImageData", function() {
tabItem.removeSubscriber(tabItem, "deniedToCacheImageData");
test2();
});
tabItem.save(true);
HttpRequestObserver.cacheControlValue = null;
});
}
function test2() {
// page with cache-control: private, should save thumbnail
HttpRequestObserver.cacheControlValue = "private";
newTab.linkedBrowser.loadURI("http://www.example.com/");
afterAllTabsLoaded(function() {
let tabItem = newTab._tabViewTabItem;
ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
"Should save the thumbnail for tab");
tabItem.addSubscriber(tabItem, "savedCachedImageData", function() {
tabItem.removeSubscriber(tabItem, "savedCachedImageData");
test3();
});
tabItem.save(true);
});
}
function test3() {
// page with cache-control: private with https caching enabled, should save thumbnail
HttpRequestObserver.cacheControlValue = "private";
enablePersistentHttpsCaching =
contentWindow.ThumbnailStorage.enablePersistentHttpsCaching;
contentWindow.ThumbnailStorage.enablePersistentHttpsCaching = true;
newTab.linkedBrowser.loadURI("https://example.com/browser/browser/base/content/test/tabview/dummy_page.html");
afterAllTabsLoaded(function() {
let tabItem = newTab._tabViewTabItem;
ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
"Should save the thumbnail for tab");
tabItem.addSubscriber(tabItem, "savedCachedImageData", function() {
tabItem.removeSubscriber(tabItem, "savedCachedImageData");
test4();
});
tabItem.save(true);
});
}
function test4() {
// page with cache-control: public with https caching disabled, should save thumbnail
HttpRequestObserver.cacheControlValue = "public";
contentWindow.ThumbnailStorage.enablePersistentHttpsCaching = false;
newTab.linkedBrowser.loadURI("https://example.com/browser/browser/base/content/test/tabview/");
afterAllTabsLoaded(function() {
let tabItem = newTab._tabViewTabItem;
ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
"Should save the thumbnail for tab");
tabItem.addSubscriber(tabItem, "savedCachedImageData", function() {
tabItem.removeSubscriber(tabItem, "savedCachedImageData");
test5();
});
tabItem.save(true);
});
}
function test5() {
// page with cache-control: private with https caching disabled, should not save thumbnail
HttpRequestObserver.cacheControlValue = "private";
newTab.linkedBrowser.loadURI("https://example.com/");
afterAllTabsLoaded(function() {
let tabItem = newTab._tabViewTabItem;
ok(!contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
"Should not the thumbnail for tab");
tabItem.addSubscriber(tabItem, "deniedToCacheImageData", function() {
tabItem.removeSubscriber(tabItem, "deniedToCacheImageData");
hideTabView(function () {
gBrowser.removeTab(gBrowser.tabs[1]);
finish();
});
});
tabItem.save(true);
});
}
let HttpRequestObserver = {
cacheControlValue: null,
observe: function(subject, topic, data) {
if (topic == "http-on-examine-response" && this.cacheControlValue) {
let httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
httpChannel.setResponseHeader("Cache-Control", this.cacheControlValue, false);
}
},
register: function() {
Services.obs.addObserver(this, "http-on-examine-response", false);
},
unregister: function() {
Services.obs.removeObserver(this, "http-on-examine-response");
}
};

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

@ -0,0 +1,37 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
let state = {
windows: [{
tabs: [{
entries: [{ url: "about:blank" }],
hidden: true,
extData: {"tabview-tab": '{"url":"about:blank","groupID":1,"bounds":{"left":20,"top":20,"width":20,"height":20}}'}
},{
entries: [{ url: "about:blank" }],
hidden: false,
extData: {"tabview-tab": '{"url":"about:blank","groupID":2,"bounds":{"left":20,"top":20,"width":20,"height":20}}'},
}],
selected: 2,
extData: {
"tabview-groups": '{"nextID":3,"activeGroupId":2, "totalNumber":2}',
"tabview-group":
'{"1":{"bounds":{"left":15,"top":5,"width":280,"height":232},"id":1},' +
'"2":{"bounds":{"left":309,"top":5,"width":267,"height":226},"id":2}}'
}
}]
};
function test() {
waitForExplicitFinish();
newWindowWithState(state, function(win) {
registerCleanupFunction(function() win.close());
is(win.document.getElementById("tabviewGroupsNumber").getAttribute("groups"),
"2", "There are two groups");
waitForFocus(finish);
});
}

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

@ -7,17 +7,18 @@ var prefsBranch = Cc["@mozilla.org/preferences-service;1"].
function animateZoom() prefsBranch.getBoolPref("animate_zoom");
function registerCleanupFunction() {
prefsBranch.setUserPref("animate_zoom", true);
}
function test() {
waitForExplicitFinish();
let charsetArg = "charset=" + window.content.document.characterSet;
let win = window.openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no",
"about:blank", charsetArg, null, null, true);
registerCleanupFunction(function() {
prefsBranch.setBoolPref("animate_zoom", true);
win.close();
});
ok(animateZoom(), "By default, we animate on zoom.");
prefsBranch.setBoolPref("animate_zoom", false);
ok(!animateZoom(), "animate_zoom = false");
@ -29,27 +30,24 @@ function test() {
let tabViewWindow = null;
let transitioned = 0;
let onShown = function() {
win.removeEventListener("tabviewshown", onShown, false);
ok(!transitioned, "There should be no transitions");
win.close();
finish();
};
let initCallback = function() {
tabViewWindow = win.TabView._window;
function onTransitionEnd(event) {
transitioned++;
tabViewWindow.Utils.log(transitioned);
info(transitioned);
}
tabViewWindow.document.addEventListener("transitionend", onTransitionEnd, false);
win.TabView.show();
showTabView(function() {
ok(!transitioned, "There should be no transitions");
tabViewWindow.document.removeEventListener(
"transitionend", onTransitionEnd, false);
finish();
}, win);
};
win.addEventListener("tabviewshown", onShown, false);
win.TabView._initFrame(initCallback);
}
win.addEventListener("load", onLoad, false);

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

@ -31,7 +31,9 @@ function onTabViewWindowLoaded() {
is(groupItem.getChildren().length, 1, "The new group has a tab item");
// start the tests
testUndoGroup(contentWindow, groupItem);
waitForFocus(function() {
testUndoGroup(contentWindow, groupItem);
}, contentWindow);
};
window.addEventListener("tabviewhidden", onTabViewHidden, false);
window.addEventListener("tabviewshown", onTabViewShown, false);
@ -80,7 +82,7 @@ function testUndoGroup(contentWindow, groupItem) {
});
let closeButton = groupItem.container.getElementsByClassName("close");
ok(closeButton, "Group item close button exists");
ok(closeButton[0], "Group item close button exists");
EventUtils.sendMouseEvent({ type: "click" }, closeButton[0], contentWindow);
}
@ -129,6 +131,6 @@ function testCloseUndoGroup(contentWindow, groupItem) {
});
let closeButton = groupItem.container.getElementsByClassName("close");
ok(closeButton, "Group item close button exists");
ok(closeButton[0], "Group item close button exists");
EventUtils.sendMouseEvent({ type: "click" }, closeButton[0], contentWindow);
}

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

@ -105,7 +105,7 @@ function afterAllTabsLoaded(callback, win) {
this.removeEventListener("load", onLoad, true);
stillToLoad--;
if (!stillToLoad)
callback();
executeSoon(callback);
}
for (let a = 0; a < win.gBrowser.tabs.length; a++) {
@ -301,3 +301,21 @@ function newWindowWithState(state, callback) {
afterAllTabsLoaded(function () callback(win), win);
});
}
// ----------
function restoreTab(callback, index, win) {
win = win || window;
let tab = win.undoCloseTab(index || 0);
let tabItem = tab._tabViewTabItem;
if (tabItem._reconnected) {
afterAllTabsLoaded(callback, win);
return;
}
tab._tabViewTabItem.addSubscriber(tab, "reconnected", function onReconnected() {
tab._tabViewTabItem.removeSubscriber(tab, "reconnected");
afterAllTabsLoaded(callback, win);
});
}

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