Mergi mc to kiwifox, lots of conflicts so may not build

This commit is contained in:
Benoit Girard 2012-01-30 13:38:20 -05:00
Родитель ac4cd6008e 9d8f91ffd1
Коммит e0bcc5a6d2
2291 изменённых файлов: 77950 добавлений и 36958 удалений

2
.gitignore поставляемый
Просмотреть файл

@ -23,7 +23,7 @@ ID
security/manager/.nss.checkout
# Build directories
obj*/
/obj*/
# Build directories for js shell
*/_DBG.OBJ/

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

@ -72,3 +72,4 @@ c0983049bcaa9551e5f276d5a77ce154c151e0b0 AURORA_BASE_20110927
462c726144bc1fb45b61e774f64ac5d61b4e047c UPDATE_PACKAGING_R15
54bfd8bf682e295ffd7f22fa921ca343957b6c1c AURORA_BASE_20111108
a8506ab2c65480cf2f85f54e203ea746522c62bb AURORA_BASE_20111220
462c726144bc1fb45b61e774f64ac5d61b4e047c UPDATE_PACKAGING_R16

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

@ -49,6 +49,9 @@ namespace statistics {
inline void A11yInitialized()
{ Telemetry::Accumulate(Telemetry::A11Y_INSTANTIATED, true); }
inline void A11yConsumers(PRUint32 aConsumer)
{ Telemetry::Accumulate(Telemetry::A11Y_CONSUMERS, aConsumer); }
/**
* Report that ISimpleDOM* has been used.
*/

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

@ -195,12 +195,6 @@ public:
*/
virtual bool IsPrimaryForNode() const;
/**
* Return the string bundle
*/
static nsIStringBundle* GetStringBundle()
{ return gStringBundle; }
protected:
nsPresContext* GetPresContext();

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

@ -395,7 +395,7 @@ nsAccessibilityService::CreateHTMLObjectFrameAccessible(nsObjectFrame* aFrame,
nsCString plugId;
nsresult rv = pluginInstance->GetValueFromPlugin(
NPPVpluginNativeAccessibleAtkPlugId, &plugId);
if (NS_SUCCEEDED(rv) && !plugId.IsVoid()) {
if (NS_SUCCEEDED(rv) && !plugId.IsEmpty()) {
AtkSocketAccessible* socketAccessible =
new AtkSocketAccessible(aContent, weakShell, plugId);
@ -909,19 +909,8 @@ static bool HasRelatedContent(nsIContent *aContent)
// If the given ID is referred by relation attribute then create an accessible
// for it. Take care of HTML elements only for now.
if (aContent->IsHTML() &&
nsAccUtils::GetDocAccessibleFor(aContent)->IsDependentID(id))
return true;
nsIContent *ancestorContent = aContent;
while ((ancestorContent = ancestorContent->GetParent()) != nsnull) {
if (ancestorContent->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant)) {
// ancestor has activedescendant property, this content could be active
return true;
}
}
return false;
return aContent->IsHTML() &&
nsAccUtils::GetDocAccessibleFor(aContent)->IsDependentID(id);
}
nsAccessible*

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

@ -579,16 +579,13 @@ nsAccessible::GetIndexInParent(PRInt32 *aIndexInParent)
return *aIndexInParent != -1 ? NS_OK : NS_ERROR_FAILURE;
}
nsresult nsAccessible::GetTranslatedString(const nsAString& aKey, nsAString& aStringOut)
void
nsAccessible::TranslateString(const nsAString& aKey, nsAString& aStringOut)
{
nsXPIDLString xsValue;
if (!gStringBundle ||
NS_FAILED(gStringBundle->GetStringFromName(PromiseFlatString(aKey).get(), getter_Copies(xsValue))))
return NS_ERROR_FAILURE;
gStringBundle->GetStringFromName(PromiseFlatString(aKey).get(), getter_Copies(xsValue));
aStringOut.Assign(xsValue);
return NS_OK;
}
PRUint64
@ -616,6 +613,9 @@ nsAccessible::VisibilityState()
} while (accessible = accessible->Parent());
nsIFrame* frame = GetFrame();
if (!frame)
return vstates;
const nsCOMPtr<nsIPresShell> shell(GetPresShell());
// We need to know if at least a kMinPixels around the object is visible,
@ -1473,23 +1473,34 @@ nsAccessible::State()
// Apply ARIA states to be sure accessible states will be overridden.
ApplyARIAState(&state);
if (mRoleMapEntry && mRoleMapEntry->role == roles::PAGETAB &&
!(state & states::SELECTED) &&
// If this is an ARIA item of the selectable widget and if it's focused and
// not marked unselected explicitly (i.e. aria-selected="false") then expose
// it as selected to make ARIA widget authors life easier.
if (mRoleMapEntry && !(state & states::SELECTED) &&
!mContent->AttrValueIs(kNameSpaceID_None,
nsGkAtoms::aria_selected,
nsGkAtoms::_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 {
// If focus is in a child of the tab panel surely the tab is selected!
Relation rel = RelationByType(nsIAccessibleRelation::RELATION_LABEL_FOR);
nsAccessible* relTarget = nsnull;
while ((relTarget = rel.Next())) {
if (relTarget->Role() == roles::PROPERTYPAGE &&
FocusMgr()->IsFocusWithin(relTarget))
state |= states::SELECTED;
// Special case for tabs: focused tab or focus inside related tab panel
// implies selected state.
if (mRoleMapEntry->role == roles::PAGETAB) {
if (state & states::FOCUSED) {
state |= states::SELECTED;
} else {
// If focus is in a child of the tab panel surely the tab is selected!
Relation rel = RelationByType(nsIAccessibleRelation::RELATION_LABEL_FOR);
nsAccessible* relTarget = nsnull;
while ((relTarget = rel.Next())) {
if (relTarget->Role() == roles::PROPERTYPAGE &&
FocusMgr()->IsFocusWithin(relTarget))
state |= states::SELECTED;
}
}
} else if (state & states::FOCUSED) {
nsAccessible* container = nsAccUtils::GetSelectableContainer(this, state);
if (container &&
!nsAccUtils::HasDefinedARIAToken(container->GetContent(),
nsGkAtoms::aria_multiselectable)) {
state |= states::SELECTED;
}
}
}
@ -1882,7 +1893,8 @@ nsAccessible::GetActionDescription(PRUint8 aIndex, nsAString& aDescription)
nsresult rv = GetActionName(aIndex, name);
NS_ENSURE_SUCCESS(rv, rv);
return GetTranslatedString(name, aDescription);
TranslateString(name, aDescription);
return NS_OK;
}
// void doAction(in PRUint8 index)
@ -2914,21 +2926,18 @@ nsAccessible::SetCurrentItem(nsAccessible* aItem)
nsAccessible*
nsAccessible::ContainerWidget() const
{
nsIAtom* idAttribute = mContent->GetIDAttributeName();
if (idAttribute) {
if (mContent->HasAttr(kNameSpaceID_None, idAttribute)) {
for (nsAccessible* parent = Parent(); parent; parent = parent->Parent()) {
nsIContent* parentContent = parent->GetContent();
if (parentContent &&
parentContent->HasAttr(kNameSpaceID_None,
nsGkAtoms::aria_activedescendant)) {
return parent;
}
// Don't cross DOM document boundaries.
if (parent->IsDocumentNode())
break;
if (HasARIARole() && mContent->HasID()) {
for (nsAccessible* parent = Parent(); parent; parent = parent->Parent()) {
nsIContent* parentContent = parent->GetContent();
if (parentContent &&
parentContent->HasAttr(kNameSpaceID_None,
nsGkAtoms::aria_activedescendant)) {
return parent;
}
// Don't cross DOM document boundaries.
if (parent->IsDocumentNode())
break;
}
}
return nsnull;

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

@ -166,6 +166,14 @@ public:
return ARIARoleInternal();
}
/**
* Return true if ARIA role is specified on the element.
*/
inline bool HasARIARole() const
{
return mRoleMapEntry;
}
/**
* Return accessible role specified by ARIA (see constants in
* roles).
@ -603,6 +611,11 @@ public:
*/
virtual nsAccessible* ContainerWidget() const;
/**
* Return the localized string for the given key.
*/
static void TranslateString(const nsAString& aKey, nsAString& aStringOut);
protected:
//////////////////////////////////////////////////////////////////////////////
@ -695,7 +708,6 @@ protected:
// helper method to verify frames
static nsresult GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut);
static nsresult GetTranslatedString(const nsAString& aKey, nsAString& aStringOut);
/**
* Return an accessible for the given DOM node, or if that node isn't

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

@ -1345,7 +1345,7 @@ nsHTMLTableAccessible::HasDescendant(const nsAString& aTagName,
if (foundItemContent->GetChildCount() > 1)
return true; // Treat multiple child nodes as non-empty
nsIContent *innerItemContent = foundItemContent->GetChildAt(0);
nsIContent *innerItemContent = foundItemContent->GetFirstChild();
if (innerItemContent && !innerItemContent->TextIsOnlyWhitespace())
return true;

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

@ -1,4 +1,5 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -15,11 +16,12 @@
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Original Author: Hubert Figuiere <hub@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -35,25 +37,24 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsDocumentCharsetInfo_h__
#define nsDocumentCharsetInfo_h__
#ifndef _MacUtils_H_
#define _MacUtils_H_
#include "nsIFactory.h"
#include "nsIDocumentCharsetInfo.h"
@class NSString;
class nsString;
class nsDocumentCharsetInfo : public nsIDocumentCharsetInfo
{
public:
nsDocumentCharsetInfo ();
virtual ~nsDocumentCharsetInfo ();
namespace mozilla {
namespace a11y {
namespace utils {
NS_DECL_ISUPPORTS
NS_DECL_NSIDOCUMENTCHARSETINFO
/**
* Get a localized string from the string bundle.
* Return nil if not found.
*/
NSString* LocalizedString(const nsString& aString);
private:
nsCOMPtr<nsIAtom> mForcedCharset;
nsCOMPtr<nsIAtom> mParentCharset;
PRInt32 mParentCharsetSource;
};
}
}
}
#endif // nsDocumentCharsetInfo_h__
#endif

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

@ -0,0 +1,66 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Original Author: Hubert Figuiere <hub@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import "MacUtils.h"
#include "nsAccessible.h"
#include "nsCocoaUtils.h"
namespace mozilla {
namespace a11y {
namespace utils {
/**
* Get a localized string from the a11y string bundle.
* Return nil if not found.
*/
NSString*
LocalizedString(const nsString& aString)
{
nsString text;
nsAccessible::TranslateString(aString, text);
return text.IsEmpty() ? nil : nsCocoaUtils::ToNSString(text);
}
}
}
}

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

@ -56,8 +56,10 @@ CMMSRCS = nsAccessNodeWrap.mm \
mozDocAccessible.mm \
mozActionElements.mm \
mozTextAccessible.mm \
mozHTMLAccessible.mm \
MacUtils.mm \
$(NULL)
EXPORTS = \
nsAccessNodeWrap.h \

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

@ -38,7 +38,7 @@
#import "mozAccessible.h"
// to get the mozView formal protocol, that all gecko's ChildViews implement.
#import "MacUtils.h"
#import "mozView.h"
#import "nsRoleMap.h"
@ -127,24 +127,6 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL;
}
/**
* Get a localized string from the string bundle.
* Return nil is not found.
*/
static NSString*
GetLocalizedString(const nsString& aString)
{
if (!nsAccessNode::GetStringBundle())
return nil;
nsXPIDLString text;
nsresult rv = nsAccessNode::GetStringBundle()->GetStringFromName(aString.get(),
getter_Copies(text));
NS_ENSURE_SUCCESS(rv, nil);
return !text.IsEmpty() ? nsCocoaUtils::ToNSString(text) : nil;
}
#pragma mark -
@implementation mozAccessible
@ -219,6 +201,9 @@ GetLocalizedString(const nsString& aString)
NSAccessibilityTitleUIElementAttribute,
NSAccessibilityTopLevelUIElementAttribute,
NSAccessibilityDescriptionAttribute,
#if DEBUG
@"AXMozDescription",
#endif
nil];
}
@ -233,6 +218,11 @@ GetLocalizedString(const nsString& aString)
if (mIsExpired)
return nil;
#if DEBUG
if ([attribute isEqualToString:@"AXMozDescription"])
return [NSString stringWithFormat:@"role = %u native = %@", mRole, [self class]];
#endif
if ([attribute isEqualToString:NSAccessibilityChildrenAttribute])
return [self children];
@ -254,8 +244,8 @@ GetLocalizedString(const nsString& aString)
if ([attribute isEqualToString:NSAccessibilityValueAttribute])
return [self value];
if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
if (mRole == roles::INTERNAL_FRAME || mRole == roles::DOCUMENT_FRAME)
return GetLocalizedString(NS_LITERAL_STRING("htmlContent")) ? : @"HTML Content";
if (mRole == roles::DOCUMENT)
return utils::LocalizedString(NS_LITERAL_STRING("htmlContent"));
return NSAccessibilityRoleDescription([self role], nil);
}
@ -348,7 +338,9 @@ GetLocalizedString(const nsString& aString)
- (NSString*)accessibilityActionDescription:(NSString*)action
{
return nil;
// by default we return whatever the MacOS API know about.
// if you have custom actions, override.
return NSAccessibilityActionDescription(action);
}
- (void)accessibilityPerformAction:(NSString*)action

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

@ -43,6 +43,7 @@
@interface mozButtonAccessible : mozAccessible
- (void)click;
- (BOOL)isTab;
@end
@interface mozCheckboxAccessible : mozButtonAccessible
@ -53,3 +54,11 @@
/* Used for buttons that may pop up a menu. */
@interface mozPopupButtonAccessible : mozButtonAccessible
@end
/* Class for tabs - not individual tabs */
@interface mozTabsAccessible : mozAccessible
{
NSMutableArray* mTabs;
}
-(id)tabs;
@end

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

@ -37,7 +37,11 @@
* ***** END LICENSE BLOCK ***** */
#import "mozActionElements.h"
#import "MacUtils.h"
#import "nsIAccessible.h"
#import "nsXULTabAccessible.h"
#include "nsObjCExceptions.h"
@ -60,6 +64,7 @@ enum CheckboxValue {
if (!attributes) {
attributes = [[NSArray alloc] initWithObjects:NSAccessibilityParentAttribute, // required
NSAccessibilityRoleAttribute, // required
NSAccessibilityRoleDescriptionAttribute,
NSAccessibilityPositionAttribute, // required
NSAccessibilitySizeAttribute, // required
NSAccessibilityWindowAttribute, // required
@ -70,6 +75,9 @@ enum CheckboxValue {
NSAccessibilityFocusedAttribute, // required
NSAccessibilityTitleAttribute, // required
NSAccessibilityDescriptionAttribute,
#if DEBUG
@"AXMozDescription",
#endif
nil];
}
return attributes;
@ -83,6 +91,13 @@ enum CheckboxValue {
if ([attribute isEqualToString:NSAccessibilityChildrenAttribute])
return nil;
if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
if ([self isTab])
return utils::LocalizedString(NS_LITERAL_STRING("tab"));
return NSAccessibilityRoleDescription([self role], nil);
}
return [super accessibilityAttributeValue:attribute];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
@ -109,9 +124,13 @@ enum CheckboxValue {
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if ([action isEqualToString:NSAccessibilityPressAction])
if ([action isEqualToString:NSAccessibilityPressAction]) {
if ([self isTab])
return utils::LocalizedString(NS_LITERAL_STRING("switch"));
return @"press button"; // XXX: localize this later?
}
return nil;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
@ -134,6 +153,11 @@ enum CheckboxValue {
mGeckoAccessible->DoAction(0);
}
- (BOOL)isTab
{
return (mGeckoAccessible && (mGeckoAccessible->Role() == roles::PAGETAB));
}
@end
@implementation mozCheckboxAccessible
@ -198,6 +222,9 @@ enum CheckboxValue {
NSAccessibilityTitleAttribute, // required for popupmenus, and for menubuttons with a title
NSAccessibilityChildrenAttribute, // required
NSAccessibilityDescriptionAttribute, // required if it has no title attr
#if DEBUG
@"AXMozDescription",
#endif
nil];
}
return attributes;
@ -258,3 +285,85 @@ enum CheckboxValue {
}
@end
@implementation mozTabsAccessible
- (void)dealloc
{
[mTabs release];
[super dealloc];
}
- (NSArray*)accessibilityAttributeNames
{
// standard attributes that are shared and supported by root accessible (AXMain) elements.
static NSMutableArray* attributes = nil;
if (!attributes) {
attributes = [[super accessibilityAttributeNames] mutableCopy];
[attributes addObject:NSAccessibilityContentsAttribute];
[attributes addObject:NSAccessibilityTabsAttribute];
}
return attributes;
}
- (id)accessibilityAttributeValue:(NSString *)attribute
{
if ([attribute isEqualToString:NSAccessibilityContentsAttribute])
return [super children];
if ([attribute isEqualToString:NSAccessibilityTabsAttribute])
return [self tabs];
return [super accessibilityAttributeValue:attribute];
}
/**
* Returns the selected tab (the mozAccessible)
*/
- (id)value
{
if (!mGeckoAccessible)
return nil;
nsAccessible* accessible = mGeckoAccessible->GetSelectedItem(0);
if (!accessible)
return nil;
mozAccessible* nativeAcc = nil;
nsresult rv = accessible->GetNativeInterface((void**)&nativeAcc);
NS_ENSURE_SUCCESS(rv, nil);
return nativeAcc;
}
/**
* Return the mozAccessibles that are the tabs.
*/
- (id)tabs
{
if (mTabs)
return mTabs;
NSArray* children = [self children];
NSEnumerator* enumerator = [children objectEnumerator];
mTabs = [[NSMutableArray alloc] init];
id obj;
while ((obj = [enumerator nextObject]))
if ([obj isTab])
[mTabs addObject:obj];
return mTabs;
}
- (void)invalidateChildren
{
[super invalidateChildren];
[mTabs release];
mTabs = nil;
}
@end

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

@ -1,4 +1,6 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -15,11 +17,12 @@
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1999
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Original Author: Hub Figuière <hub@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -35,16 +38,12 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsXMLEncodingCID_h__
#define nsXMLEncodingCID_h__
#import "mozAccessible.h"
#include "nscore.h"
@interface mozHeadingAccessible : mozAccessible
#define NS_XML_ENCODING_CONTRACTID "@mozilla.org/intl/xmlencoding;1"
@end
// {12BB8F16-2389-11d3-B3BF-00805F8A6670}
#define NS_XML_ENCODING_CID \
{ 0x12bb8f16, 0x2389, 0x11d3, { 0xb3, 0xbf, 0x0, 0x80, 0x5f, 0x8a, 0x66, 0x70 } }
@interface mozLinkAccessible : mozAccessible
#endif // nsXMLEncodingCID_h__
@end

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

@ -0,0 +1,133 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Original Author: Hub Figuière <hub@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import "mozHTMLAccessible.h"
#import "nsHyperTextAccessible.h"
#import "nsCocoaUtils.h"
@implementation mozHeadingAccessible
- (id)value
{
if (!mGeckoAccessible || !mGeckoAccessible->IsHyperText())
return nil;
PRUint32 level = mGeckoAccessible->AsHyperText()->GetLevelInternal();
return [NSNumber numberWithInt:level];
}
@end
@interface mozLinkAccessible ()
-(NSURL*)url;
@end
@implementation mozLinkAccessible
- (NSArray*)accessibilityAttributeNames
{
// if we're expired, we don't support any attributes.
if (mIsExpired)
return [NSArray array];
static NSMutableArray* attributes = nil;
if (!attributes) {
attributes = [[super accessibilityAttributeNames] mutableCopy];
[attributes addObject:NSAccessibilityURLAttribute];
}
return attributes;
}
- (id)accessibilityAttributeValue:(NSString *)attribute
{
if ([attribute isEqualToString:NSAccessibilityURLAttribute])
return [self url];
return [super accessibilityAttributeValue:attribute];
}
- (NSArray*)accessibilityActionNames
{
// if we're expired, we don't support any attributes.
if (mIsExpired)
return [NSArray array];
static NSArray* actionNames = nil;
if (!actionNames) {
actionNames = [[NSArray alloc] initWithObjects:NSAccessibilityPressAction,
nil];
}
return actionNames;
}
- (void)accessibilityPerformAction:(NSString*)action
{
if (!mGeckoAccessible)
return;
if ([action isEqualToString:NSAccessibilityPressAction])
mGeckoAccessible->DoAction(0);
else
[super accessibilityPerformAction:action];
}
- (NSURL*)url
{
if (!mGeckoAccessible)
return nil;
nsAutoString value;
nsresult rv = mGeckoAccessible->GetValue(value);
NS_ENSURE_SUCCESS(rv, nil);
NSString* urlString = value.IsEmpty() ? nil : nsCocoaUtils::ToNSString(value);
if (!urlString)
return nil;
return [NSURL URLWithString:urlString];
}
@end

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

@ -1,4 +1,6 @@
#include "nsAccessibleWrap.h"
#include "nsCocoaUtils.h"
#include "nsObjCExceptions.h"
#import "mozTextAccessible.h"
@ -12,6 +14,7 @@ using namespace mozilla::a11y;
- (long)textLength;
- (BOOL)isReadOnly;
- (void)setText:(NSString*)newText;
- (NSString*)text;
@end
@implementation mozTextAccessible
@ -60,6 +63,9 @@ using namespace mozilla::a11y;
NSAccessibilityNumberOfCharactersAttribute, // required
// TODO: NSAccessibilityVisibleCharacterRangeAttribute, // required
// TODO: NSAccessibilityInsertionPointLineNumberAttribute
#if DEBUG
@"AXMozDescription",
#endif
nil];
}
return supportedAttributes;
@ -79,8 +85,9 @@ using namespace mozilla::a11y;
return [self selectedText];
// Apple's SpeechSynthesisServer expects AXValue to return an AXStaticText
// object's AXSelectedText attribute. See bug 674612.
// Also if there is no selected text, we return the full text.See bug 369710
if ([attribute isEqualToString:NSAccessibilityValueAttribute])
return [self selectedText];
return [self selectedText] ? : [self text];
// let mozAccessible handle all other attributes
return [super accessibilityAttributeValue:attribute];
@ -158,6 +165,20 @@ using namespace mozilla::a11y;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (NSString*)text
{
if (!mGeckoTextAccessible)
return nil;
nsAutoString text;
nsresult rv =
mGeckoTextAccessible->GetText(0, nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT,
text);
NS_ENSURE_SUCCESS(rv, nil);
return text.IsEmpty() ? nil : nsCocoaUtils::ToNSString(text);
}
- (long)textLength
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
@ -261,6 +282,9 @@ using namespace mozilla::a11y;
NSAccessibilityNumberOfCharactersAttribute, // required
// TODO: NSAccessibilityVisibleCharacterRangeAttribute, // required
// TODO: NSAccessibilityInsertionPointLineNumberAttribute
#if DEBUG
@"AXMozDescription",
#endif
nil];
}
return supportedAttributes;

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

@ -45,6 +45,7 @@
#import "mozAccessible.h"
#import "mozActionElements.h"
#import "mozHTMLAccessible.h"
#import "mozTextAccessible.h"
using namespace mozilla::a11y;
@ -103,22 +104,33 @@ nsAccessibleWrap::GetNativeType ()
[mozButtonAccessible class];
}
case roles::PAGETAB:
return [mozButtonAccessible class];
case roles::CHECKBUTTON:
return [mozCheckboxAccessible class];
case roles::AUTOCOMPLETE:
return [mozComboboxAccessible class];
case roles::HEADING:
return [mozHeadingAccessible class];
case roles::PAGETABLIST:
return [mozTabsAccessible class];
case roles::ENTRY:
case roles::STATICTEXT:
case roles::HEADING:
case roles::LABEL:
case roles::CAPTION:
case roles::ACCEL_LABEL:
case roles::TEXT_LEAF:
// normal textfield (static or editable)
return [mozTextAccessible class];
case roles::LINK:
return [mozLinkAccessible class];
case roles::COMBOBOX:
return [mozPopupButtonAccessible class];

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

@ -52,12 +52,12 @@ static const NSString* AXRoles [] = {
NSAccessibilityUnknownRole, // ROLE_CARET. unused on OS X
NSAccessibilityWindowRole, // ROLE_ALERT
NSAccessibilityWindowRole, // ROLE_WINDOW. irrelevant on OS X; all window a11y is handled by the system.
@"AXWebArea", // ROLE_INTERNAL_FRAME
NSAccessibilityScrollAreaRole, // ROLE_INTERNAL_FRAME
NSAccessibilityMenuRole, // ROLE_MENUPOPUP. the parent of menuitems
NSAccessibilityMenuItemRole, // ROLE_MENUITEM.
@"AXHelpTag", // ROLE_TOOLTIP. 10.4+ only, so we re-define the constant.
NSAccessibilityGroupRole, // ROLE_APPLICATION. unused on OS X. the system will take care of this.
NSAccessibilityGroupRole, // ROLE_DOCUMENT
@"AXWebArea", // ROLE_DOCUMENT
NSAccessibilityGroupRole, // ROLE_PANE
NSAccessibilityUnknownRole, // ROLE_CHART
NSAccessibilityWindowRole, // ROLE_DIALOG. there's a dialog subrole.
@ -74,12 +74,12 @@ static const NSString* AXRoles [] = {
NSAccessibilityGroupRole, // ROLE_CELL
@"AXLink", // ROLE_LINK. 10.4+ the attr first define in SDK 10.4, so we define it here too. ROLE_LINK
@"AXHelpTag", // ROLE_HELPBALLOON
NSAccessibilityUnknownRole, // ROLE_CHARACTER. unusued on OS X
NSAccessibilityUnknownRole, // ROLE_CHARACTER. unused on OS X
NSAccessibilityListRole, // ROLE_LIST
NSAccessibilityRowRole, // ROLE_LISTITEM
NSAccessibilityOutlineRole, // ROLE_OUTLINE
NSAccessibilityRowRole, // ROLE_OUTLINEITEM. XXX: use OutlineRow as subrole.
NSAccessibilityGroupRole, // ROLE_PAGETAB
NSAccessibilityRadioButtonRole, // ROLE_PAGETAB
NSAccessibilityGroupRole, // ROLE_PROPERTYPAGE
NSAccessibilityUnknownRole, // ROLE_INDICATOR
NSAccessibilityImageRole, // ROLE_GRAPHIC
@ -102,7 +102,7 @@ static const NSString* AXRoles [] = {
NSAccessibilityMenuButtonRole, // ROLE_BUTTONMENU
NSAccessibilityGroupRole, // ROLE_BUTTONDROPDOWNGRID
NSAccessibilityUnknownRole, // ROLE_WHITESPACE
NSAccessibilityGroupRole, // ROLE_PAGETABLIST
NSAccessibilityTabGroupRole, // ROLE_PAGETABLIST
NSAccessibilityUnknownRole, // ROLE_CLOCK. unused on OS X
NSAccessibilityButtonRole, // ROLE_SPLITBUTTON
NSAccessibilityUnknownRole, // ROLE_IPADDRESS
@ -146,9 +146,9 @@ static const NSString* AXRoles [] = {
NSAccessibilityTextFieldRole, // ROLE_EDITBAR
NSAccessibilityTextFieldRole, // ROLE_ENTRY
NSAccessibilityStaticTextRole, // ROLE_CAPTION
@"AXWebArea", // ROLE_DOCUMENT_FRAME
NSAccessibilityStaticTextRole, // ROLE_HEADING
NSAccessibilityGroupRole, // ROLE_PAGE
NSAccessibilityScrollAreaRole, // ROLE_DOCUMENT_FRAME
@"AXHeading", // ROLE_HEADING
NSAccessibilityGroupRole, // ROLE_PAG
NSAccessibilityGroupRole, // ROLE_SECTION
NSAccessibilityUnknownRole, // ROLE_REDUNDANT_OBJECT
NSAccessibilityGroupRole, // ROLE_FORM

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

@ -40,6 +40,7 @@
#include "Compatibility.h"
#include "nsWinUtils.h"
#include "Statistics.h"
#include "mozilla/Preferences.h"
@ -84,18 +85,37 @@ PRUint32 Compatibility::sMode = Compatibility::NoCompatibilityMode;
void
Compatibility::Init()
{
// Note we collect some AT statistics/telemetry here for convenience.
HMODULE jawsHandle = ::GetModuleHandleW(L"jhook");
if (jawsHandle) {
sMode |= JAWSMode;
// IA2 off mode for JAWS versions below 8.0.2173.
if (IsModuleVersionLessThan(jawsHandle, 8, 2173))
if (IsModuleVersionLessThan(jawsHandle, 8, 2173)) {
sMode |= IA2OffMode;
statistics::A11yConsumers(OLDJAWS);
} else {
statistics::A11yConsumers(JAWS);
}
}
if (::GetModuleHandleW(L"gwm32inc"))
if (::GetModuleHandleW(L"gwm32inc")) {
sMode |= WEMode;
if (::GetModuleHandleW(L"dolwinhk"))
statistics::A11yConsumers(WE);
}
if (::GetModuleHandleW(L"dolwinhk")) {
sMode |= DolphinMode;
statistics::A11yConsumers(DOLPHIN);
}
if (::GetModuleHandleW(L"STSA32"))
statistics::A11yConsumers(SEROTEK);
if (::GetModuleHandleW(L"nvdaHelperRemote"))
statistics::A11yConsumers(NVDA);
if (::GetModuleHandleW(L"OsmHooks"))
statistics::A11yConsumers(COBRA);
// Turn off new tab switching for Jaws and WE.
if (sMode & JAWSMode || sMode & WEMode) {

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

@ -97,6 +97,19 @@ private:
IA2OffMode = 1 << 3
};
/**
* List of detected consumers of a11y (used for statistics/telemetry)
*/
enum {
NVDA = 0,
JAWS = 1,
OLDJAWS = 2,
WE = 3,
DOLPHIN = 4,
SEROTEK = 5,
COBRA = 6
};
private:
static PRUint32 sMode;
};

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

@ -75,6 +75,7 @@ _TEST_FILES =\
actions.js \
attributes.js \
autocomplete.js \
browser.js \
common.js \
events.js \
grid.js \

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

@ -0,0 +1,96 @@
/**
* Load the browser with the given url and then invokes the given function.
*/
function openBrowserWindow(aFunc, aURL)
{
gBrowserContext.testFunc = aFunc;
gBrowserContext.startURL = aURL;
addLoadEvent(openBrowserWindowIntl);
}
/**
* Close the browser window.
*/
function closeBrowserWindow()
{
gBrowserContext.browserWnd.close();
}
/**
* Return the browser window object.
*/
function browserWindow()
{
return gBrowserContext.browserWnd;
}
/**
* Return tab browser object.
*/
function tabBrowser()
{
return browserWindow().gBrowser;
}
/**
* Return browser element of the current tab.
*/
function currentBrowser()
{
return tabBrowser().selectedBrowser;
}
/**
* Return DOM document of the current tab.
*/
function currentTabDocument()
{
return currentBrowser().contentDocument;
}
/**
* Return input element of address bar.
*/
function urlbarInput()
{
return browserWindow().document.getElementById("urlbar").inputField;
}
/**
* Return reload button.
*/
function reloadButton()
{
return browserWindow().document.getElementById("urlbar-reload-button");
}
////////////////////////////////////////////////////////////////////////////////
// private section
Components.utils.import("resource://gre/modules/Services.jsm");
var gBrowserContext =
{
browserWnd: null,
testFunc: null,
startURL: ""
};
function openBrowserWindowIntl()
{
gBrowserContext.browserWnd =
window.openDialog(Services.prefs.getCharPref("browser.chromeURL"),
"_blank", "chrome,all,dialog=no",
gBrowserContext.startURL);
addA11yLoadEvent(startBrowserTests, browserWindow());
}
function startBrowserTests()
{
if (gBrowserContext.startURL) // wait for load
addA11yLoadEvent(gBrowserContext.testFunc, currentBrowser().contentWindow);
else
gBrowserContext.testFunc();
}

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

@ -31,6 +31,8 @@ const EVENT_VALUE_CHANGE = nsIAccessibleEvent.EVENT_VALUE_CHANGE;
////////////////////////////////////////////////////////////////////////////////
// General
Components.utils.import("resource://gre/modules/Services.jsm");
/**
* Set up this variable to dump events into DOM.
*/
@ -172,7 +174,7 @@ const DO_NOT_FINISH_TEST = 1;
* // phase getter: function() {},
* //
* // * Callback, called to match handled event. *
* // match : function() {},
* // match : function(aEvent) {},
* //
* // * Callback, called when event is handled
* // check: function(aEvent) {},
@ -1338,10 +1340,10 @@ function caretMoveChecker(aCaretOffset, aTargetOrFunc, aTargetFuncArg)
* State change checker.
*/
function stateChangeChecker(aState, aIsExtraState, aIsEnabled,
aTargetOrFunc, aTargetFuncArg)
aTargetOrFunc, aTargetFuncArg, aIsAsync)
{
this.__proto__ = new invokerChecker(EVENT_STATE_CHANGE, aTargetOrFunc,
aTargetFuncArg);
aTargetFuncArg, aIsAsync);
this.check = function stateChangeChecker_check(aEvent)
{
@ -1368,6 +1370,22 @@ function stateChangeChecker(aState, aIsExtraState, aIsEnabled,
var unxpdExtraState = aIsEnabled ? 0 : (aIsExtraState ? aState : 0);
testStates(event.accessible, state, extraState, unxpdState, unxpdExtraState);
}
this.match = function stateChangeChecker_match(aEvent)
{
if (aEvent instanceof nsIAccessibleStateChangeEvent) {
var scEvent = aEvent.QueryInterface(nsIAccessibleStateChangeEvent);
return aEvent.accessible = this.target && scEvent.state == aState;
}
return false;
}
}
function asyncStateChangeChecker(aState, aIsExtraState, aIsEnabled,
aTargetOrFunc, aTargetFuncArg)
{
this.__proto__ = new stateChangeChecker(aState, aIsExtraState, aIsEnabled,
aTargetOrFunc, aTargetFuncArg, true);
}
/**
@ -1414,12 +1432,6 @@ var gA11yEventApplicantsCount = 0;
var gA11yEventObserver =
{
// The service reference needs to live in the observer, instead of as a global var,
// to be available in observe() catch case too.
observerService :
Components.classes["@mozilla.org/observer-service;1"]
.getService(nsIObserverService),
observe: function observe(aSubject, aTopic, aData)
{
if (aTopic != "accessible-event")
@ -1431,7 +1443,7 @@ var gA11yEventObserver =
} catch (ex) {
// After a test is aborted (i.e. timed out by the harness), this exception is soon triggered.
// Remove the leftover observer, otherwise it "leaks" to all the following tests.
this.observerService.removeObserver(this, "accessible-event");
Services.obs.removeObserver(this, "accessible-event");
// Forward the exception, with added explanation.
throw "[accessible/events.js, gA11yEventObserver.observe] This is expected if a previous test has been aborted... Initial exception was: [ " + ex + " ]";
}
@ -1485,14 +1497,12 @@ function listenA11yEvents(aStartToListen)
if (aStartToListen) {
// Add observer when adding the first applicant only.
if (!(gA11yEventApplicantsCount++))
gA11yEventObserver.observerService
.addObserver(gA11yEventObserver, "accessible-event", false);
Services.obs.addObserver(gA11yEventObserver, "accessible-event", false);
} else {
// Remove observer when there are no more applicants only.
// '< 0' case should not happen, but just in case: removeObserver() will throw.
if (--gA11yEventApplicantsCount <= 0)
gA11yEventObserver.observerService
.removeObserver(gA11yEventObserver, "accessible-event");
Services.obs.removeObserver(gA11yEventObserver, "accessible-event");
}
}
@ -1609,11 +1619,8 @@ var gLogger =
logToAppConsole: function logger_logToAppConsole(aMsg)
{
if (gA11yEventDumpToAppConsole)
consoleService.logStringMessage("events: " + aMsg);
},
consoleService: Components.classes["@mozilla.org/consoleservice;1"].
getService(Components.interfaces.nsIConsoleService)
Services.console.logStringMessage("events: " + aMsg);
}
};

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

@ -45,7 +45,7 @@ relativesrcdir = accessible/events
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
# test_docload.xul, docload_wnd.xul, test_scroll.xul disabled for misusing <tabbrowser> (bug 715857)
# test_scroll.xul disabled for misusing <tabbrowser> (bug 715857)
_TEST_FILES =\
docload_wnd.html \
@ -61,6 +61,7 @@ _TEST_FILES =\
test_coalescence.html \
test_contextmenu.html \
test_docload.html \
test_docload.xul \
test_dragndrop.html \
test_flush.html \
test_focus_aria_activedescendant.html \

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

@ -1,275 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<!-- Firefox tabbrowser -->
<?xml-stylesheet href="chrome://browser/content/browser.css"
type="text/css"?>
<!-- SeaMonkey tabbrowser -->
<?xml-stylesheet href="chrome://navigator/content/navigator.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// SimpleTest stuffs
var gOpenerWnd = window.opener.wrappedJSObject;
function ok(aCond, aMsg) {
gOpenerWnd.SimpleTest.ok(aCond, aMsg);
}
function is(aExpected, aActual, aMsg) {
gOpenerWnd.SimpleTest.is(aExpected, aActual, aMsg);
}
function testStates(aAccOrElmOrID, aState, aExtraState, aAbsentState,
aAbsentExtraState)
{
gOpenerWnd.testStates(aAccOrElmOrID, aState, aExtraState, aAbsentState,
aAbsentExtraState);
}
var invokerChecker = gOpenerWnd.invokerChecker;
var asyncInvokerChecker = gOpenerWnd.asyncInvokerChecker;
const STATE_BUSY = gOpenerWnd.STATE_BUSY;
const EVENT_DOCUMENT_LOAD_COMPLETE =
gOpenerWnd.EVENT_DOCUMENT_LOAD_COMPLETE;
const EVENT_DOCUMENT_RELOAD = gOpenerWnd.EVENT_DOCUMENT_RELOAD;
const EVENT_DOCUMENT_LOAD_STOPPED =
gOpenerWnd.EVENT_DOCUMENT_LOAD_STOPPED;
const EVENT_REORDER = gOpenerWnd.EVENT_REORDER;
const EVENT_STATE_CHANGE = gOpenerWnd.EVENT_STATE_CHANGE;
const nsIAccessibleStateChangeEvent =
gOpenerWnd.nsIAccessibleStateChangeEvent;
//gOpenerWnd.gA11yEventDumpToConsole = true; // debug
////////////////////////////////////////////////////////////////////////////
// Hacks to make xul:tabbrowser work.
var handleDroppedLink = null; // needed for tabbrowser usage
Components.utils.import("resource://gre/modules/Services.jsm");
var XULBrowserWindow = {
isBusy: false,
setOverLink: function (link, b) {
}
};
gFindBarInitialized = false;
////////////////////////////////////////////////////////////////////////////
// Helpers.
function getContainer()
{
var idx = gTabBrowser.tabContainer.selectedIndex;
return gTabBrowser.getBrowserAtIndex(idx);
}
function getDocument()
{
return getContainer().contentDocument;
}
////////////////////////////////////////////////////////////////////////////
// Invoker checkers.
function stateBusyChecker(aIsEnabled)
{
this.type = EVENT_STATE_CHANGE;
this.__defineGetter__("target", getDocument);
this.check = function stateBusyChecker_check(aEvent)
{
var event = null;
try {
var event = aEvent.QueryInterface(nsIAccessibleStateChangeEvent);
} catch (e) {
ok(false, "State change event was expected");
}
if (!event)
return;
is(event.state, STATE_BUSY, "Wrong state of statechange event.");
is(event.isEnabled(), aIsEnabled,
"Wrong value of state of statechange event");
testStates(event.accessible, (aIsEnabled ? STATE_BUSY : 0), 0,
(aIsEnabled ? 0 : STATE_BUSY), 0);
}
}
function documentReloadChecker(aIsFromUserInput)
{
this.type = EVENT_DOCUMENT_RELOAD;
this.__defineGetter__("target", getDocument);
this.check = function documentReloadChecker_check(aEvent)
{
is(aEvent.isFromUserInput, aIsFromUserInput,
"Wrong value of isFromUserInput");
}
}
////////////////////////////////////////////////////////////////////////////
// Invokers.
/**
* Load URI.
*/
function loadURIInvoker(aURI)
{
this.invoke = function loadURIInvoker_invoke()
{
gTabBrowser.loadURI(aURI);
}
this.eventSeq = [
// We don't expect state change event for busy true since things happen
// quickly and it's coalesced.
new asyncInvokerChecker(EVENT_REORDER, getContainer),
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getDocument),
new stateBusyChecker(false)
];
this.getID = function loadURIInvoker_getID()
{
return "load uri " + aURI;
}
}
/**
* Click reload page button.
*/
function clickReloadBtnInvoker()
{
this.invoke = function clickReloadBtnInvoker_invoke()
{
synthesizeMouse(document.getElementById("reloadbtn"), 5, 5, {});
}
this.eventSeq = [
new documentReloadChecker(true),
new asyncInvokerChecker(EVENT_REORDER, getContainer),
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getDocument),
new stateBusyChecker(false)
];
this.getID = function reloadInvoker_getID()
{
return "click reload page button";
}
}
/**
* Reload the page.
*/
function reloadInvoker()
{
this.invoke = function reloadInvoker_invoke()
{
gTabBrowser.reload();
}
this.eventSeq = [
new documentReloadChecker(false),
new asyncInvokerChecker(EVENT_REORDER, getContainer),
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getDocument),
new stateBusyChecker(false)
];
this.getID = function reloadInvoker_getID()
{
return "reload page";
}
}
/**
* Load wrong URI what results in error page loading.
*/
function loadErrorPageInvoker(aURL, aURLDescr)
{
this.invoke = function loadErrorPageInvoker_invoke()
{
gTabBrowser.loadURI(aURL);
}
this.eventSeq = [
// We don't expect state change for busy true, load stopped events since
// things happen quickly and it's coalesced.
new asyncInvokerChecker(EVENT_REORDER, getContainer),
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getDocument),
new stateBusyChecker(false)
];
this.getID = function loadErrorPageInvoker_getID()
{
return "load error page: '" + aURLDescr + "'";
}
}
////////////////////////////////////////////////////////////////////////////
// Tests
var gQueue = null;
const Ci = Components.interfaces;
var gTabBrowser = null;
function doTest()
{
gTabBrowser = document.getElementById("content");
gQueue = new gOpenerWnd.eventQueue();
gQueue.push(new loadURIInvoker("about:"));
gQueue.push(new clickReloadBtnInvoker());
gQueue.push(new loadURIInvoker("about:mozilla"));
gQueue.push(new reloadInvoker());
gQueue.push(new loadErrorPageInvoker("www.wronguri.wronguri",
"Server not found"));
gQueue.push(new loadErrorPageInvoker("https://nocert.example.com:443",
"Untrusted Connection"));
gQueue.onFinish = function() { window.close(); }
gQueue.invoke();
}
gOpenerWnd.addA11yLoadEvent(doTest);
]]>
</script>
<!-- Hack to make xul:tabbrowser work -->
<menubar>
<menu label="menu">
<menupopup>
<menuitem label="close window hook" id="menu_closeWindow"/>
<menuitem label="close hook" id="menu_close"/>
</menupopup>
</menu>
</menubar>
<button id="reloadbtn" label="reload page"
oncommand="gTabBrowser.reload();"/>
<toolbar>
<tabs id="tabbrowser-tabs" class="tabbrowser-tabs"
tabbrowser="content"
flex="1"
setfocus="false">
<tab class="tabbrowser-tab" selected="true"/>
</tabs>
</toolbar>
<tabbrowser id="content"
type="content-primary"
tabcontainer="tabbrowser-tabs"
flex="1"/>
</window>

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

@ -19,20 +19,172 @@
src="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../browser.js"></script>
<script type="application/javascript">
<![CDATA[
// var gA11yEventDumpID = "eventdump"; // debug stuff
function doTest()
////////////////////////////////////////////////////////////////////////////
// Invoker checkers.
function stateBusyChecker(aIsEnabled)
{
var w = window.openDialog("../events/docload_wnd.xul",
"docload_test",
"chrome,width=600,height=600");
this.type = EVENT_STATE_CHANGE;
this.__defineGetter__("target", currentTabDocument);
this.check = function stateBusyChecker_check(aEvent)
{
var event = null;
try {
var event = aEvent.QueryInterface(nsIAccessibleStateChangeEvent);
} catch (e) {
ok(false, "State change event was expected");
}
if (!event)
return;
is(event.state, STATE_BUSY, "Wrong state of statechange event.");
is(event.isEnabled(), aIsEnabled,
"Wrong value of state of statechange event");
testStates(event.accessible, (aIsEnabled ? STATE_BUSY : 0), 0,
(aIsEnabled ? 0 : STATE_BUSY), 0);
}
}
function documentReloadChecker(aIsFromUserInput)
{
this.type = EVENT_DOCUMENT_RELOAD;
this.__defineGetter__("target", currentTabDocument);
this.check = function documentReloadChecker_check(aEvent)
{
is(aEvent.isFromUserInput, aIsFromUserInput,
"Wrong value of isFromUserInput");
}
}
////////////////////////////////////////////////////////////////////////////
// Invokers.
/**
* Load URI.
*/
function loadURIInvoker(aURI)
{
this.invoke = function loadURIInvoker_invoke()
{
tabBrowser().loadURI(aURI);
}
this.eventSeq = [
// We don't expect state change event for busy true since things happen
// quickly and it's coalesced.
new asyncInvokerChecker(EVENT_REORDER, currentBrowser),
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument),
new stateBusyChecker(false)
];
this.getID = function loadURIInvoker_getID()
{
return "load uri " + aURI;
}
}
/**
* Reload the page by F5 (isFromUserInput flag is true).
*/
function userReloadInvoker()
{
this.invoke = function userReloadInvoker_invoke()
{
synthesizeKey("VK_F5", {}, browserWindow());
}
this.eventSeq = [
new documentReloadChecker(true),
new asyncInvokerChecker(EVENT_REORDER, currentBrowser),
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument),
new stateBusyChecker(false)
];
this.getID = function userReloadInvoker_getID()
{
return "user reload page";
}
}
/**
* Reload the page (isFromUserInput flag is false).
*/
function reloadInvoker()
{
this.invoke = function reloadInvoker_invoke()
{
tabBrowser().reload();
}
this.eventSeq = [
new documentReloadChecker(false),
new asyncInvokerChecker(EVENT_REORDER, currentBrowser),
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument),
new stateBusyChecker(false)
];
this.getID = function reloadInvoker_getID()
{
return "reload page";
}
}
/**
* Load wrong URI what results in error page loading.
*/
function loadErrorPageInvoker(aURL, aURLDescr)
{
this.invoke = function loadErrorPageInvoker_invoke()
{
tabBrowser().loadURI(aURL);
}
this.eventSeq = [
// We don't expect state change for busy true, load stopped events since
// things happen quickly and it's coalesced.
new asyncInvokerChecker(EVENT_REORDER, currentBrowser),
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument),
new stateBusyChecker(false)
];
this.getID = function loadErrorPageInvoker_getID()
{
return "load error page: '" + aURLDescr + "'";
}
}
////////////////////////////////////////////////////////////////////////////
// Tests
gA11yEventDumpToConsole = true; // debug
var gQueue = null;
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new loadURIInvoker("about:"));
gQueue.push(new userReloadInvoker());
gQueue.push(new loadURIInvoker("about:mozilla"));
gQueue.push(new reloadInvoker());
gQueue.push(new loadErrorPageInvoker("www.wronguri.wronguri",
"Server not found"));
gQueue.push(new loadErrorPageInvoker("https://nocert.example.com:443",
"Untrusted Connection"));
gQueue.onFinish = function() { closeBrowserWindow(); }
gQueue.invoke();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doTest);
openBrowserWindow(doTests);
]]>
</script>

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

@ -3,8 +3,12 @@
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!-- Firefox searchbar -->
<?xml-stylesheet href="chrome://browser/content/browser.css"
type="text/css"?>
<!-- SeaMonkey searchbar -->
<?xml-stylesheet href="chrome://navigator/content/navigator.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible focus event testing">

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

@ -19,40 +19,20 @@
src="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../browser.js"></script>
<script type="application/javascript">
<![CDATA[
Components.utils.import("resource://gre/modules/Services.jsm");
////////////////////////////////////////////////////////////////////////////
// Helpers
function tabBrowser()
{
return gBrowserWnd.gBrowser;
}
function currentBrowser()
{
return tabBrowser().selectedBrowser;
}
function currentTabDocument()
{
return currentBrowser().contentDocument;
}
function inputInDocument()
{
var tabdoc = currentTabDocument();
return tabdoc.getElementById("input");
}
function urlbarInput()
{
return gBrowserWnd.document.getElementById("urlbar").inputField;
}
////////////////////////////////////////////////////////////////////////////
// Invokers
@ -96,22 +76,6 @@
var gInputDocURI = "data:text/html,<html><input id='input'></html>";
var gButtonDocURI = "data:text/html,<html><input id='input' type='button' value='button'></html>";
var gBrowserWnd = null;
function loadBrowser()
{
gBrowserWnd = window.openDialog(Services.prefs.getCharPref("browser.chromeURL"),
"_blank", "chrome,all,dialog=no", gInputDocURI);
addA11yLoadEvent(startTests, gBrowserWnd);
}
function startTests()
{
// Wait for tab load.
var browser = gBrowserWnd.gBrowser.selectedBrowser;
addA11yLoadEvent(doTests, browser.contentWindow);
}
//gA11yEventDumpToConsole = true; // debug
var gQueue = null;
@ -123,7 +87,8 @@
var input = inputInDocument();
// move focus to input inside tab document
gQueue.push(new synthTab(tabDocument, new focusChecker(input), gBrowserWnd));
gQueue.push(new synthTab(tabDocument, new focusChecker(input),
browserWindow()));
// open new url, focus moves to new document
gQueue.push(new loadURI(gButtonDocURI));
@ -132,22 +97,22 @@
gQueue.push(new goBack());
// open new tab, focus moves to urlbar
gQueue.push(new synthKey(tabDocument, "t", { ctrlKey: true, window: gBrowserWnd },
gQueue.push(new synthKey(tabDocument, "t", { ctrlKey: true, window: browserWindow() },
new focusChecker(urlbarInput)));
// close open tab, focus goes on input of tab document
gQueue.push(new synthKey(tabDocument, "w", { ctrlKey: true, window: gBrowserWnd },
gQueue.push(new synthKey(tabDocument, "w", { ctrlKey: true, window: browserWindow() },
new focusChecker(inputInDocument)));
gQueue.onFinish = function()
{
gBrowserWnd.close();
closeBrowserWindow();
}
gQueue.invoke();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(loadBrowser);
openBrowserWindow(doTests, gInputDocURI);
]]>
</script>

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

@ -15,6 +15,8 @@
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://browser/content/utilityOverlay.js"/>
<script type="application/javascript"
src="../common.js" />

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

@ -3,9 +3,6 @@
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/browser.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible focus testing">

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

@ -139,6 +139,18 @@
<rule attr="title" type="string"/>
</ruleset>
<ruleset id="htmlimage">
<ruleset ref="aria"/>
<rule attr="alt" type="string"/>
<ruleset ref="htmlelm_end"/>
</ruleset>
<ruleset id="htmlimageemptyalt">
<ruleset ref="aria"/>
<ruleset ref="htmlelm_end"/>
<rule attr="alt" type="string"/>
</ruleset>
<ruleset id="htmltable">
<ruleset ref="htmlelm_start"/>
<rule elm="caption"/>
@ -190,6 +202,28 @@
</html:select>
</markup>
<markup ref="html:img" ruleset="htmlimage">
<html:span id="l1" a11yname="test2">test2</html:span>
<html:span id="l2" a11yname="test3">test3</html:span>
<html:img id="img"
aria-label="Logo of Mozilla"
aria-labelledby="l1 l2"
alt="Mozilla logo"
title="This is a logo"
src="moz.png"/>
</markup>
<markup ref="html:img" ruleset="htmlimageemptyalt">
<html:span id="l1" a11yname="test2">test2</html:span>
<html:span id="l2" a11yname="test3">test3</html:span>
<html:img id="img"
aria-label="Logo of Mozilla"
aria-labelledby="l1 l2"
title="This is a logo"
alt=""
src="moz.png"/>
</markup>
<markup ref="html:table/html:tr/html:td" ruleset="htmlelm"
id="markup4test">
<html:span id="l1" a11yname="test2">test2</html:span>

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

@ -10,6 +10,9 @@
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://browser/content/utilityOverlay.js"/>
<script type="application/javascript">
<![CDATA[
var gOpenerWnd = window.opener.wrappedJSObject;

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

@ -15,6 +15,8 @@
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://browser/content/utilityOverlay.js"/>
<script type="application/javascript"
src="../common.js" />

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

@ -37,9 +37,11 @@ const STATE_UNAVAILABLE = nsIAccessibleStates.STATE_UNAVAILABLE;
const EXT_STATE_ACTIVE = nsIAccessibleStates.EXT_STATE_ACTIVE;
const EXT_STATE_DEFUNCT = nsIAccessibleStates.EXT_STATE_DEFUNCT;
const EXT_STATE_EDITABLE = nsIAccessibleStates.EXT_STATE_EDITABLE;
const EXT_STATE_ENABLED = nsIAccessibleStates.EXT_STATE_ENABLED;
const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE;
const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL;
const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
const EXT_STATE_SENSITIVE = nsIAccessibleStates.EXT_STATE_SENSITIVE;
const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
const EXT_STATE_STALE = nsIAccessibleStates.EXT_STATE_STALE;
const EXT_STATE_SUPPORTS_AUTOCOMPLETION =

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

@ -48,7 +48,7 @@ include $(topsrcdir)/config/rules.mk
_TEST_FILES =\
test_aria.html \
test_aria_imgmap.html \
test_aria_tabs.html \
test_aria_widgetitems.html \
test_buttons.html \
test_doc.html \
test_docarticle.html \

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

@ -1,135 +0,0 @@
<!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/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>

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

@ -0,0 +1,160 @@
<!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/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 focusARIAItem(aID, aIsSelected)
{
this.DOMNode = getNode(aID);
this.invoke = function focusARIAItem_invoke()
{
this.DOMNode.focus();
}
this.check = function focusARIAItem_check(aEvent)
{
testStates(this.DOMNode, aIsSelected ? STATE_SELECTED : 0, 0,
aIsSelected ? 0 : STATE_SELECTED);
}
this.getID = function focusARIAItem_getID()
{
return "Focused ARIA widget item with aria-selected='" +
(aIsSelected ? "true', should" : "false', shouldn't") +
" have selected state on " + prettyName(aID);
}
}
function focusActiveDescendantItem(aItemID, aWidgetID, aIsSelected)
{
this.DOMNode = getNode(aItemID);
this.widgetDOMNode = getNode(aWidgetID);
this.invoke = function focusActiveDescendantItem_invoke()
{
this.widgetDOMNode.setAttribute("aria-activedescendant", aItemID);
this.widgetDOMNode.focus();
}
this.check = function focusActiveDescendantItem_check(aEvent)
{
testStates(this.DOMNode, aIsSelected ? STATE_SELECTED : 0, 0,
aIsSelected ? 0 : STATE_SELECTED);
}
this.getID = function tabActiveDescendant_getID()
{
return "ARIA widget item managed by activedescendant " +
(aIsSelected ? "should" : "shouldn't") +
" have the selected state on " + prettyName(aItemID);
}
}
////////////////////////////////////////////////////////////////////////////
// Test
//gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true;
var gQueue = null;
function doTest()
{
// aria-selected
testStates("aria_tab1", 0, 0, STATE_SELECTED);
testStates("aria_tab2", STATE_SELECTED);
testStates("aria_tab3", 0, 0, STATE_SELECTED);
testStates("aria_option1", 0, 0, STATE_SELECTED);
testStates("aria_option2", STATE_SELECTED);
testStates("aria_option3", 0, 0, STATE_SELECTED);
testStates("aria_treeitem1", 0, 0, STATE_SELECTED);
testStates("aria_treeitem2", STATE_SELECTED);
testStates("aria_treeitem3", 0, 0, STATE_SELECTED);
// selected state when widget item is focused
gQueue = new eventQueue(EVENT_FOCUS);
gQueue.push(new focusARIAItem("aria_tab1", true));
gQueue.push(new focusARIAItem("aria_tab2", true));
gQueue.push(new focusARIAItem("aria_tab3", false));
gQueue.push(new focusARIAItem("aria_option1", true));
gQueue.push(new focusARIAItem("aria_option2", true));
gQueue.push(new focusARIAItem("aria_option3", false));
gQueue.push(new focusARIAItem("aria_treeitem1", true));
gQueue.push(new focusARIAItem("aria_treeitem2", true));
gQueue.push(new focusARIAItem("aria_treeitem3", false));
// selected state when widget item is focused (by aria-activedescendant)
gQueue.push(new focusActiveDescendantItem("aria_tab5", "aria_tablist2", true));
gQueue.push(new focusActiveDescendantItem("aria_tab6", "aria_tablist2", true));
gQueue.push(new focusActiveDescendantItem("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>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=526703"
title="Focused widget item should expose selected state by default">
Mozilla Bug 526703
</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>
<!-- listbox -->
<div id="aria_listbox" role="listbox">
<div id="aria_option1" role="option" tabindex="0">unselected option</div>
<div id="aria_option2" role="option" tabindex="0" aria-selected="true">selected option</div>
<div id="aria_option3" role="option" tabindex="0" aria-selected="false">focused explicitly unselected option</div>
</div>
<!-- tree -->
<div id="aria_tree" role="tree">
<div id="aria_treeitem1" role="treeitem" tabindex="0">unselected treeitem</div>
<div id="aria_treeitem2" role="treeitem" tabindex="0" aria-selected="true">selected treeitem</div>
<div id="aria_treeitem3" role="treeitem" tabindex="0" aria-selected="false">focused explicitly unselected treeitem</div>
</div>
<!-- tab managed by active-descendant -->
<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>

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

@ -2,8 +2,13 @@
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!-- Firefox searchbar -->
<?xml-stylesheet href="chrome://browser/content/browser.css"
type="text/css"?>
<!-- SeaMonkey searchbar -->
<?xml-stylesheet href="chrome://navigator/content/navigator.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Expanded state change events tests for comboboxes and autocompletes.">

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

@ -76,15 +76,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429659
is(height.value, aHeight, "wrong height for " + aID + "!");
}
function testThis(aID, aName, aSRC, aWidth, aHeight,
function testThis(aID, aSRC, aWidth, aHeight,
aNumActions, aActionNames)
{
var acc = getAccessible(aID, [nsIAccessibleImage]);
if (!acc)
return;
is(acc.name, aName, "wrong name for " + aID + "!");
// Test role
testRole(aID, ROLE_GRAPHIC);
@ -108,50 +106,26 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429659
function doTest()
{
// Test non-linked image
testThis("nonLinkedImage", null, "moz.png", 89, 38);
testThis("nonLinkedImage", "moz.png", 89, 38);
// Test linked image
testThis("linkedImage", null, "moz.png", 89, 38);
// Test non-linked image with alt attribute
testThis("nonLinkedImageWithAlt", "MoFo", "moz.png", 89, 38);
// Test linked image with alt attribute
testThis("linkedImageWithAlt", "MoFo link", "moz.png", 89, 38);
// Test non-linked image with title attribute
testThis("nonLinkedImageWithTitle", "MoFo logo", "moz.png", 89, 38);
// Test linked image with title attribute
testThis("linkedImageWithTitle", "Link to MoFo", "moz.png", 89, 38);
// Test simple image with empty alt attribute
testThis("nonLinkedImageEmptyAlt", "", "moz.png", 89, 38);
// Test linked image with empty alt attribute
testThis("linkedImageEmptyAlt", "", "moz.png", 89, 38);
// Test simple image with empty alt attribute and title
testThis("nonLinkedImageEmptyAltAndTitle", "MozillaFoundation", "moz.png", 89, 38);
// Test linked image with empty alt attribute and title
testThis("linkedImageEmptyAltAndTitle", "Link to Mozilla Foundation", "moz.png", 89, 38);
testThis("linkedImage", "moz.png", 89, 38);
// Image with long desc
var actionNamesArray = new Array("showlongdesc");
testThis("longdesc", "Image of Mozilla logo", "moz.png", 89, 38, 1,
testThis("longdesc", "moz.png", 89, 38, 1,
actionNamesArray);
// Image with click and long desc
actionNamesArray = null;
actionNamesArray = new Array("click", "showlongdesc");
testThis("clickAndLongdesc", "Another image of Mozilla logo", "moz.png",
testThis("clickAndLongdesc", "moz.png",
89, 38, 2, actionNamesArray);
// Image with click
actionNamesArray = null;
actionNamesArray = new Array("click");
testThis("click", "A third image of Mozilla logo", "moz.png",
testThis("click", "moz.png",
89, 38, 1, actionNamesArray);
SimpleTest.finish();
@ -172,23 +146,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429659
<img id="nonLinkedImage" src="moz.png"/>
<br>Linked image:<br>
<a href="http://www.mozilla.org"><img id="linkedImage" src="moz.png"></a>
<br>Simple image with alt:<br>
<img id="nonLinkedImageWithAlt" src="moz.png" alt="MoFo"/>
<br>Linked image with alt:<br>
<a href="http://www.mozilla.org"><img id="linkedImageWithAlt" src="moz.png" alt="MoFo link"/></a>
<br>Simple image with title:<br>
<img id="nonLinkedImageWithTitle" src="moz.png" title="MoFo logo"/>
<br>Linked image with title:<br>
<a href="http://www.mozilla.org"><img id="linkedImageWithTitle" src="moz.png" title="Link to MoFo"/></a>
<br>Simple image with empty alt:<br>
<img id="nonLinkedImageEmptyAlt" src="moz.png" alt=""/>
<br>Linked image with empty alt:<br>
<a href="http://www.mozilla.org"><img id="linkedImageEmptyAlt" src="moz.png" alt=""/></a>
<br>Simple image with empty alt and title:<br>
<img id="nonLinkedImageEmptyAltAndTitle" src="moz.png" alt="" title="MozillaFoundation"/>
<br>Linked image with empty alt and title:<br>
<a href="http://www.mozilla.org"><img id="linkedImageEmptyAltAndTitle" src="moz.png" alt=""
title="Link to Mozilla Foundation"/></a>
<br>Image with longdesc:<br>
<img id="longdesc" src="moz.png" longdesc="longdesc_src.html"
alt="Image of Mozilla logo"/>

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

@ -16,6 +16,8 @@
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://browser/content/utilityOverlay.js"/>
<script type="application/javascript"
src="../common.js" />

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

@ -394,6 +394,10 @@ pref("layers.acceleration.force-enabled", true);
pref("dom.screenEnabledProperty.enabled", true);
pref("dom.screenBrightnessProperty.enabled", true);
// Enable browser frame
pref("dom.mozBrowserFramesEnabled", true);
pref("dom.mozBrowserFramesWhitelist", "http://localhost:6666");
// Temporary permission hack for WebSMS
pref("dom.sms.enabled", true);
pref("dom.sms.whitelist", "file://,http://localhost:6666");

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

@ -201,6 +201,11 @@ var shell = {
break;
case evt.DOM_VK_SLEEP:
this.toggleScreen();
let details = {
'enabled': screen.mozEnabled
};
this.sendEvent(this.home.contentWindow, 'sleep', details);
break;
case evt.DOM_VK_ESCAPE:
if (evt.defaultPrevented)

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

@ -395,10 +395,8 @@
@BINPATH@/components/nsFilePicker.js
@BINPATH@/components/nsFilePicker.manifest
#ifdef MOZ_B2G_RIL
@BINPATH@/components/nsTelephonyWorker.manifest
@BINPATH@/components/nsTelephonyWorker.js
@BINPATH@/components/Telephony.manifest
@BINPATH@/components/Telephony.js
@BINPATH@/components/RadioInterfaceLayer.manifest
@BINPATH@/components/RadioInterfaceLayer.js
@BINPATH@/components/nsWifiWorker.js
@BINPATH@/components/nsWifiWorker.manifest
#endif
@ -602,3 +600,5 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
@BINPATH@/chrome/icons/
@BINPATH@/chrome/chrome@JAREXT@
@BINPATH@/chrome/chrome.manifest
@BINPATH@/components/B2GComponents.manifest
@BINPATH@/components/B2GComponents.xpt

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

@ -83,6 +83,10 @@ LIBS += \
$(XPCOM_STANDALONE_GLUE_LDOPTS) \
$(NULL)
ifdef MOZ_LINKER
LIBS += $(ZLIB_LIBS)
endif
ifndef MOZ_WINCONSOLE
ifdef MOZ_DEBUG
MOZ_WINCONSOLE = 1

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

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1325894427000">
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1327685994000">
<emItems>
<emItem blockID="i41" id="{99079a25-328f-4bd4-be04-00955acaa0a7}">
<versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1">
@ -27,6 +27,10 @@
<versionRange minVersion="1.1b1" maxVersion="1.1b1">
</versionRange>
</emItem>
<emItem blockID="i54" id="applebeegifts@mozilla.doslash.org">
<versionRange minVersion="0" maxVersion="*">
</versionRange>
</emItem>
<emItem blockID="i16" id="{27182e60-b5f3-411c-b545-b44205977502}">
<versionRange minVersion="1.0" maxVersion="1.0">
</versionRange>
@ -39,6 +43,10 @@
<versionRange minVersion="0.1" maxVersion="14.4.0" severity="1">
</versionRange>
</emItem>
<emItem blockID="i53" id="{a3a5c777-f583-4fef-9380-ab4add1bc2a8}">
<versionRange minVersion="2.0.3" maxVersion="2.0.3">
</versionRange>
</emItem>
<emItem blockID="i10" id="{8CE11043-9A15-4207-A565-0C94C42D590D}">
</emItem>
<emItem blockID="i1" id="mozilla_cc@internetdownloadmanager.com">
@ -66,10 +74,21 @@
</targetApplication>
</versionRange>
</emItem>
<emItem blockID="i50" id="firebug@software.joehewitt.com">
<versionRange minVersion="0" maxVersion="0">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
<versionRange minVersion="9.0a1" maxVersion="9.*" />
</targetApplication>
</versionRange>
</emItem>
<emItem blockID="i40" id="{28387537-e3f9-4ed7-860c-11e69af4a8a0}">
<versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1">
</versionRange>
</emItem>
<emItem blockID="i51" id="admin@youtubeplayer.com">
<versionRange minVersion="0" maxVersion="*">
</versionRange>
</emItem>
<emItem blockID="i46" id="{841468a1-d7f4-4bd3-84e6-bb0f13a06c64}">
<versionRange minVersion="0.1" maxVersion="*">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
@ -84,13 +103,12 @@
</targetApplication>
</versionRange>
</emItem>
<emItem blockID="i11" id="yslow@yahoo-inc.com">
<versionRange minVersion="2.0.5" maxVersion="2.0.5">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
<versionRange minVersion="3.5.7" maxVersion="*" />
</targetApplication>
<emItem blockID="i55" id="youtube@youtube7.com">
<versionRange minVersion="0" maxVersion="*">
</versionRange>
</emItem>
<emItem blockID="i47" id="youtube@youtube2.com">
</emItem>
<emItem blockID="i22" id="ShopperReports@ShopperReports.com">
<versionRange minVersion="3.1.22.0" maxVersion="3.1.22.0">
</versionRange>
@ -122,8 +140,13 @@
<versionRange minVersion="0.1" maxVersion="5.2.0.7164" severity="1">
</versionRange>
</emItem>
<emItem blockID="i47" id="youtube@youtube2.com">
</emItem>
<emItem blockID="i11" id="yslow@yahoo-inc.com">
<versionRange minVersion="2.0.5" maxVersion="2.0.5">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
<versionRange minVersion="3.5.7" maxVersion="*" />
</targetApplication>
</versionRange>
</emItem>
<emItem blockID="i17" id="{3252b9ae-c69a-4eaf-9502-dc9c1f6c009e}">
<versionRange minVersion="2.2" maxVersion="2.2">
</versionRange>
@ -139,10 +162,12 @@
<versionRange minVersion="2.0" maxVersion="2.0">
</versionRange>
</emItem>
<emItem blockID="i49" id="{ADFA33FD-16F5-4355-8504-DF4D664CFE63}">
</emItem>
<emItem blockID="i7" id="{2224e955-00e9-4613-a844-ce69fccaae91}">
</emItem>
<emItem blockID="i52" id="ff-ext@youtube">
<versionRange minVersion="0" maxVersion="*">
</versionRange>
</emItem>
<emItem blockID="i24" id="{6E19037A-12E3-4295-8915-ED48BC341614}">
<versionRange minVersion="0.1" maxVersion="1.3.328.4" severity="1">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">

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

@ -244,8 +244,7 @@ pref("general.autoScroll", false);
pref("general.autoScroll", true);
#endif
// Whether or not the application should check at startup each time if it
// is the default browser.
// At startup, check if we're the default browser and prompt user if not.
pref("browser.shell.checkDefaultBrowser", true);
// 0 = blank, 1 = home (browser.startup.homepage), 2 = last visited page, 3 = resume previous browser session
@ -281,7 +280,7 @@ pref("browser.urlbar.doubleClickSelectsAll", true);
#else
pref("browser.urlbar.doubleClickSelectsAll", false);
#endif
pref("browser.urlbar.autoFill", false);
pref("browser.urlbar.autoFill", true);
// 0: Match anywhere (e.g., middle of words)
// 1: Match on word boundaries and then try matching anywhere
// 2: Match only on word boundaries (e.g., after / or .)
@ -294,7 +293,7 @@ pref("browser.urlbar.maxRichResults", 12);
// The amount of time (ms) to wait after the user has stopped typing
// before starting to perform autocomplete. 50 is the default set in
// autocomplete.xml.
pref("browser.urlbar.delay", 50);
pref("browser.urlbar.delay", 0);
// The special characters below can be typed into the urlbar to either restrict
// the search to visited history, bookmarked, tagged pages; or force a match on
@ -804,6 +803,10 @@ pref("browser.sessionstore.max_resumed_crashes", 1);
pref("browser.sessionstore.restore_on_demand", false);
// Whether to automatically restore hidden tabs (i.e., tabs in other tab groups) or not
pref("browser.sessionstore.restore_hidden_tabs", false);
// If restore_on_demand is set, pinned tabs are restored on startup by default.
// When set to true, this pref overrides that behavior, and pinned tabs will only
// be restored when they are focused.
pref("browser.sessionstore.restore_pinned_tabs_on_demand", false);
// allow META refresh by default
pref("accessibility.blockautorefresh", false);
@ -1032,6 +1035,8 @@ pref("devtools.styleinspector.enabled", true);
// Enable the Tilt inspector
pref("devtools.tilt.enabled", true);
pref("devtools.tilt.intro_transition", true);
pref("devtools.tilt.outro_transition", true);
// Enable the rules view
pref("devtools.ruleview.enabled", true);
@ -1041,12 +1046,13 @@ pref("devtools.scratchpad.enabled", true);
// Enable the Style Editor.
pref("devtools.styleeditor.enabled", true);
pref("devtools.styleeditor.transitions", true);
// Enable tools for Chrome development.
pref("devtools.chrome.enabled", false);
// Disable the GCLI enhanced command line.
pref("devtools.gcli.enable", true);
pref("devtools.gcli.enable", false);
// The last Web Console height. This is initially 0 which means that the Web
// Console will use the default height next time it shows.
@ -1104,5 +1110,11 @@ pref("prompts.tab_modal.enabled", true);
// Whether the Panorama should animate going in/out of tabs
pref("browser.panorama.animate_zoom", true);
// Defines the url to be used for new tabs.
pref("browser.newtab.url", "about:blank");
// Toggles the content of 'about:newtab'. Shows the grid when enabled.
pref("browser.newtabpage.enabled", false);
// Enable the DOM full-screen API.
pref("full-screen-api.enabled", true);

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

@ -57,7 +57,6 @@
list-style-image: url("chrome://global/skin/icons/loading_16.png");
}
.trademark-label,
.text-link,
.text-link:focus {
margin: 0px;

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

@ -77,17 +77,6 @@ function init(aEvent)
document.getElementById("communityDesc").hidden = true;
}
#ifdef MOZ_OFFICIAL_BRANDING
// Hide the Charlton trademark attribution for non-en-US/en-GB
// DO NOT REMOVE without consulting people involved with bug 616193
let chromeRegistry = Components.classes["@mozilla.org/chrome/chrome-registry;1"].
getService(Components.interfaces.nsIXULChromeRegistry);
let currentLocale = chromeRegistry.getSelectedLocale("global");
if (currentLocale != "en-US" && currentLocale != "en-GB") {
document.getElementById("extra-trademark").hidden = true;
}
#endif
#ifdef MOZ_UPDATER
gAppUpdater = new appUpdater();

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

@ -146,13 +146,7 @@
<label class="text-link bottom-link" href="about:rights">&bottomLinks.rights;</label>
<label class="text-link bottom-link" href="http://www.mozilla.com/legal/privacy/">&bottomLinks.privacy;</label>
</hbox>
<description id="trademark">
<label class="trademark-label">&trademarkInfo.part1;</label>
#ifdef MOZ_OFFICIAL_BRANDING
<!-- DO NOT REMOVE without consulting people involved with bug 616193 -->
<label id="extra-trademark" class="trademark-label">Some of the trademarks used under license from The Charlton Company.</label>
#endif
</description>
<description id="trademark">&trademarkInfo.part1;</description>
</vbox>
</vbox>

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

@ -176,7 +176,8 @@
<menuseparator class="appmenu-menuseparator"/>
<menu id="appmenu_webDeveloper"
label="&appMenuWebDeveloper.label;">
<menupopup id="appmenu_webDeveloper_popup">
<menupopup id="appmenu_webDeveloper_popup"
onpopupshowing="onWebDeveloperMenuShowing();">
<menuitem id="appmenu_webConsole"
label="&webConsoleCmd.label;"
type="checkbox"

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

@ -225,13 +225,19 @@ var FullZoom = {
return;
// Avoid the cps roundtrip and apply the default/global pref.
if (aURI.spec == "about:blank") {
if (isBlankPageURL(aURI.spec)) {
this._applyPrefToSetting(undefined, aBrowser);
return;
}
let browser = aBrowser || gBrowser.selectedBrowser;
// Media documents should always start at 1, and are not affected by prefs.
if (!aIsTabSwitch && browser.contentDocument.mozSyntheticDocument) {
ZoomManager.setZoomForBrowser(browser, 1);
return;
}
if (Services.contentPrefs.hasCachedPref(aURI, this.name)) {
let zoomValue = Services.contentPrefs.getPref(aURI, this.name);
this._applyPrefToSetting(zoomValue, browser);
@ -303,9 +309,10 @@ var FullZoom = {
var browser = aBrowser || (gBrowser && gBrowser.selectedBrowser);
try {
if (browser.contentDocument instanceof Ci.nsIImageDocument)
ZoomManager.setZoomForBrowser(browser, 1);
else if (typeof aValue != "undefined")
if (browser.contentDocument.mozSyntheticDocument)
return;
if (typeof aValue != "undefined")
ZoomManager.setZoomForBrowser(browser, this._ensureValid(aValue));
else if (typeof this.globalValue != "undefined")
ZoomManager.setZoomForBrowser(browser, this.globalValue);
@ -317,7 +324,7 @@ var FullZoom = {
_applySettingToPref: function FullZoom__applySettingToPref() {
if (!this.siteSpecific || gInPrintPreviewMode ||
content.document instanceof Ci.nsIImageDocument)
content.document.mozSyntheticDocument)
return;
var zoomLevel = ZoomManager.zoom;
@ -325,7 +332,7 @@ var FullZoom = {
},
_removePref: function FullZoom__removePref() {
if (!(content.document instanceof Ci.nsIImageDocument))
if (!(content.document.mozSyntheticDocument))
Services.contentPrefs.removePref(gBrowser.currentURI, this.name);
},

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

@ -531,7 +531,8 @@
<menu id="webDeveloperMenu"
label="&webDeveloperMenu.label;"
accesskey="&webDeveloperMenu.accesskey;">
<menupopup id="menuWebDeveloperPopup">
<menupopup id="menuWebDeveloperPopup"
onpopupshowing="onWebDeveloperMenuShowing();">
<menuitem id="webConsole"
type="checkbox"
label="&webConsoleCmd.label;"

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

@ -1012,7 +1012,7 @@ var PlacesStarButton = {
}
// We can load about:blank before the actual page, but there is no point in handling that page.
if (this._uri.spec == "about:blank") {
if (isBlankPageURL(this._uri.spec)) {
return;
}

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

@ -0,0 +1,137 @@
#ifdef 0
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#endif
/**
* Keeps thumbnails of open web pages up-to-date.
*/
let gBrowserThumbnails = {
_captureDelayMS: 2000,
/**
* Map of capture() timeouts assigned to their browsers.
*/
_timeouts: null,
/**
* Cache for the PageThumbs module.
*/
_pageThumbs: null,
/**
* List of tab events we want to listen for.
*/
_tabEvents: ["TabClose", "TabSelect"],
init: function Thumbnails_init() {
gBrowser.addTabsProgressListener(this);
this._tabEvents.forEach(function (aEvent) {
gBrowser.tabContainer.addEventListener(aEvent, this, false);
}, this);
this._timeouts = new WeakMap();
XPCOMUtils.defineLazyModuleGetter(this, "_pageThumbs",
"resource:///modules/PageThumbs.jsm", "PageThumbs");
},
uninit: function Thumbnails_uninit() {
gBrowser.removeTabsProgressListener(this);
this._tabEvents.forEach(function (aEvent) {
gBrowser.tabContainer.removeEventListener(aEvent, this, false);
}, this);
this._timeouts = null;
this._pageThumbs = null;
},
handleEvent: function Thumbnails_handleEvent(aEvent) {
switch (aEvent.type) {
case "scroll":
let browser = aEvent.currentTarget;
if (this._timeouts.has(browser))
this._delayedCapture(browser);
break;
case "TabSelect":
this._delayedCapture(aEvent.target.linkedBrowser);
break;
case "TabClose": {
this._clearTimeout(aEvent.target.linkedBrowser);
break;
}
}
},
/**
* State change progress listener for all tabs.
*/
onStateChange: function Thumbnails_onStateChange(aBrowser, aWebProgress,
aRequest, aStateFlags, aStatus) {
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK)
this._delayedCapture(aBrowser);
},
_capture: function Thumbnails_capture(aBrowser) {
if (this._shouldCapture(aBrowser)) {
let canvas = this._pageThumbs.capture(aBrowser.contentWindow);
this._pageThumbs.store(aBrowser.currentURI.spec, canvas);
}
},
_delayedCapture: function Thumbnails_delayedCapture(aBrowser) {
if (this._timeouts.has(aBrowser))
clearTimeout(this._timeouts.get(aBrowser));
else
aBrowser.addEventListener("scroll", this, true);
let timeout = setTimeout(function () {
this._clearTimeout(aBrowser);
this._capture(aBrowser);
}.bind(this), this._captureDelayMS);
this._timeouts.set(aBrowser, timeout);
},
_shouldCapture: function Thumbnails_shouldCapture(aBrowser) {
let doc = aBrowser.contentDocument;
// FIXME Bug 720575 - Don't capture thumbnails for SVG or XML documents as
// that currently regresses Talos SVG tests.
if (doc instanceof SVGDocument || doc instanceof XMLDocument)
return false;
// There's no point in taking screenshot of loading pages.
if (aBrowser.docShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE)
return false;
// Don't take screenshots of about: pages.
if (aBrowser.currentURI.schemeIs("about"))
return false;
let channel = aBrowser.docShell.currentDocumentChannel;
try {
// If the channel is a nsIHttpChannel get its http status code.
let httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
// Continue only if we have a 2xx status code.
return Math.floor(httpChannel.responseStatus / 100) == 2;
} catch (e) {
// Not a http channel, we just assume a success status code.
return true;
}
},
_clearTimeout: function Thumbnails_clearTimeout(aBrowser) {
if (this._timeouts.has(aBrowser)) {
aBrowser.removeEventListener("scroll", this, false);
clearTimeout(this._timeouts.get(aBrowser));
this._timeouts.delete(aBrowser);
}
}
};

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

@ -188,6 +188,7 @@ XPCOMUtils.defineLazyGetter(this, "Tilt", function() {
let gInitialPages = [
"about:blank",
"about:newtab",
"about:privatebrowsing",
"about:sessionrestore"
];
@ -196,6 +197,7 @@ let gInitialPages = [
#include browser-places.js
#include browser-tabPreviews.js
#include browser-tabview.js
#include browser-thumbnails.js
#ifdef MOZ_SERVICES_SYNC
#include browser-syncui.js
@ -1501,6 +1503,8 @@ function prepareForStartup() {
}
function delayedStartup(isLoadingBlank, mustLoadSidebar) {
Cu.import("resource:///modules/TelemetryTimestamps.jsm");
TelemetryTimestamps.add("delayedStartupStarted");
gDelayedStartupTimeoutId = null;
Services.obs.addObserver(gSessionHistoryObserver, "browser:purge-session-history", false);
@ -1554,7 +1558,11 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
// Perform default browser checking (after window opens).
var shell = getShellService();
if (shell) {
#ifdef DEBUG
var shouldCheck = false;
#else
var shouldCheck = shell.shouldCheckDefaultBrowser;
#endif
var willRecoverSession = false;
try {
var ss = Cc["@mozilla.org/browser/sessionstartup;1"].
@ -1699,6 +1707,7 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
gSyncUI.init();
#endif
gBrowserThumbnails.init();
TabView.init();
setUrlAndSearchBarWidthForConditionalForwardButton();
@ -1761,6 +1770,7 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
window.addEventListener("dragover", MousePosTracker, false);
Services.obs.notifyObservers(window, "browser-delayed-startup-finished", "");
TelemetryTimestamps.add("delayedStartupFinished");
}
function BrowserShutdown() {
@ -1820,6 +1830,7 @@ function BrowserShutdown() {
gPrefService.removeObserver(allTabs.prefName, allTabs);
ctrlTab.uninit();
TabView.uninit();
gBrowserThumbnails.uninit();
try {
FullZoom.destroy();
@ -2194,7 +2205,7 @@ function openLocation() {
else {
// If there are no open browser windows, open a new one
win = window.openDialog("chrome://browser/content/", "_blank",
"chrome,all,dialog=no", "about:blank");
"chrome,all,dialog=no", BROWSER_NEW_TAB_URL);
win.addEventListener("load", openLocationCallback, false);
}
return;
@ -2212,7 +2223,7 @@ function openLocationCallback()
function BrowserOpenTab()
{
openUILinkIn("about:blank", "tab");
openUILinkIn(BROWSER_NEW_TAB_URL, "tab");
}
/* Called from the openLocation dialog. This allows that dialog to instruct
@ -2547,7 +2558,7 @@ function URLBarSetURI(aURI) {
else
value = losslessDecodeURI(uri);
valid = (uri.spec != "about:blank");
valid = !isBlankPageURL(uri.spec);
}
gURLBar.value = value;
@ -2864,7 +2875,7 @@ function getMeOutOfHere() {
// Get the start page from the *default* pref branch, not the user's
var prefs = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefService).getDefaultBranch(null);
var url = "about:blank";
var url = BROWSER_NEW_TAB_URL;
try {
url = prefs.getComplexValue("browser.startup.homepage",
Ci.nsIPrefLocalizedString).data;
@ -3040,7 +3051,7 @@ function FillInHTMLTooltip(tipElement)
// Don't show the tooltip if the tooltip node is a XUL element, a document or is disconnected.
if (tipElement.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" ||
!tipElement.ownerDocument ||
tipElement.ownerDocument.compareDocumentPosition(tipElement) == document.DOCUMENT_POSITION_DISCONNECTED)
(tipElement.ownerDocument.compareDocumentPosition(tipElement) & document.DOCUMENT_POSITION_DISCONNECTED))
return retVal;
const XLinkNS = "http://www.w3.org/1999/xlink";
@ -3105,20 +3116,13 @@ function FillInHTMLTooltip(tipElement)
[titleText, XLinkTitleText, SVGTitleText].forEach(function (t) {
if (t && /\S/.test(t)) {
// Per HTML 4.01 6.2 (CDATA section), literal CRs and tabs should be
// replaced with spaces, and LFs should be removed entirely.
// XXX Bug 322270: We don't preserve the result of entities like &#13;,
// which should result in a line break in the tooltip, because we can't
// distinguish that from a literal character in the source by this point.
t = t.replace(/[\r\t]/g, ' ');
t = t.replace(/\n/g, '');
// Make CRLF and CR render one line break each.
t = t.replace(/\r\n?/g, '\n');
tipNode.setAttribute("label", t);
retVal = true;
}
});
return retVal;
}
@ -4785,6 +4789,7 @@ var XULBrowserWindow = {
},
hideChromeForLocation: function(aLocation) {
aLocation = aLocation.toLowerCase();
return this.inContentWhitelist.some(function(aSpec) {
return aSpec == aLocation;
});
@ -5188,7 +5193,7 @@ nsBrowserAccess.prototype = {
case Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW :
// FIXME: Bug 408379. So how come this doesn't send the
// referrer like the other loads do?
var url = aURI ? aURI.spec : "about:blank";
var url = aURI ? aURI.spec : BROWSER_NEW_TAB_URL;
// Pass all params to openDialog to ensure that "url" isn't passed through
// loadOneOrMoreURIs, which splits based on "|"
newWindow = openDialog(getBrowserURL(), "_blank", "all,dialog=no", url, null, null, null);
@ -5197,7 +5202,7 @@ nsBrowserAccess.prototype = {
let win, needToFocusWin;
// try the current window. if we're in a popup, fall back on the most recent browser window
if (!window.document.documentElement.getAttribute("chromehidden"))
if (window.toolbar.visible)
win = window;
else {
win = Cc["@mozilla.org/browser/browserglue;1"]
@ -5221,7 +5226,7 @@ nsBrowserAccess.prototype = {
let loadInBackground = gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground");
let referrer = aOpener ? makeURI(aOpener.location.href) : null;
let tab = win.gBrowser.loadOneTab(aURI ? aURI.spec : "about:blank", {
let tab = win.gBrowser.loadOneTab(aURI ? aURI.spec : BROWSER_NEW_TAB_URL, {
referrerURI: referrer,
fromExternal: isExternal,
inBackground: loadInBackground});
@ -5969,12 +5974,12 @@ function MultiplexHandler(event)
var name = node.getAttribute('name');
if (name == 'detectorGroup') {
SetForcedDetector(true);
BrowserCharsetReload();
SelectDetector(event, false);
} else if (name == 'charsetGroup') {
var charset = node.getAttribute('id');
charset = charset.substring('charset.'.length, charset.length)
SetForcedCharset(charset);
BrowserSetForcedCharacterSet(charset);
} else if (name == 'charsetCustomize') {
//do nothing - please remove this else statement, once the charset prefs moves to the pref window
} else {
@ -6005,30 +6010,17 @@ function SelectDetector(event, doReload)
}
}
function SetForcedDetector(doReload)
{
BrowserSetForcedDetector(doReload);
}
function SetForcedCharset(charset)
{
BrowserSetForcedCharacterSet(charset);
}
function BrowserSetForcedCharacterSet(aCharset)
{
var docCharset = gBrowser.docShell.QueryInterface(Ci.nsIDocCharset);
docCharset.charset = aCharset;
gBrowser.docShell.charset = aCharset;
// Save the forced character-set
PlacesUtils.history.setCharsetForURI(getWebNavigation().currentURI, aCharset);
BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
BrowserCharsetReload();
}
function BrowserSetForcedDetector(doReload)
function BrowserCharsetReload()
{
gBrowser.documentCharsetInfo.forcedDetector = true;
if (doReload)
BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
}
function charsetMenuGetElement(parent, id) {
@ -7783,9 +7775,11 @@ function undoCloseWindow(aIndex) {
*/
function isTabEmpty(aTab) {
let browser = aTab.linkedBrowser;
let uri = browser.currentURI.spec;
let body = browser.contentDocument.body;
return browser.sessionHistory.count < 2 &&
browser.currentURI.spec == "about:blank" &&
!browser.contentDocument.body.hasChildNodes() &&
isBlankPageURL(uri) &&
(!body || !body.hasChildNodes()) &&
!aTab.hasAttribute("busy");
}
@ -8872,8 +8866,8 @@ function restoreLastSession() {
var TabContextMenu = {
contextTab: null,
updateContextMenu: function updateContextMenu(aPopupMenu) {
this.contextTab = document.popupNode.localName == "tab" ?
document.popupNode : gBrowser.selectedTab;
this.contextTab = aPopupMenu.triggerNode.localName == "tab" ?
aPopupMenu.triggerNode : gBrowser.selectedTab;
let disabled = gBrowser.tabs.length == 1;
// Enable the "Close Tab" menuitem when the window doesn't close with the last tab.
@ -8918,9 +8912,10 @@ var TabContextMenu = {
};
XPCOMUtils.defineLazyGetter(this, "HUDConsoleUI", function () {
Cu.import("resource:///modules/HUDService.jsm");
let tempScope = {};
Cu.import("resource:///modules/HUDService.jsm", tempScope);
try {
return HUDService.consoleUI;
return tempScope.HUDService.consoleUI;
}
catch (ex) {
Components.utils.reportError(ex);
@ -9072,6 +9067,11 @@ var StyleEditor = {
}
};
function onWebDeveloperMenuShowing() {
document.getElementById("Tools:WebConsole").setAttribute("checked", HUDConsoleUI.getOpenHUD() != null);
}
XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () {
#ifdef XP_WIN
// Only show resizers on Windows 2000 and XP
@ -9146,6 +9146,7 @@ var MousePosTracker = {
}
}
};
function focusNextFrame(event) {
let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
let dir = event.shiftKey ? fm.MOVEFOCUS_BACKWARDDOC : fm.MOVEFOCUS_FORWARDDOC;

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

@ -391,7 +391,7 @@
<panel id="customizeToolbarSheetPopup"
noautohide="true">
<iframe id="customizeToolbarSheetIFrame"
style="&dialog.style;"
style="&dialog.dimensions;"
hidden="true"/>
</panel>
@ -502,7 +502,7 @@
<textbox id="urlbar" flex="1"
placeholder="&urlbar.placeholder;"
type="autocomplete"
autocompletesearch="history"
autocompletesearch="urlinline history"
autocompletesearchparam="enable-actions"
autocompletepopup="PopupAutoCompleteRichResult"
completeselectedindex="true"
@ -534,12 +534,12 @@
onkeypress="gIdentityHandler.handleIdentityButtonEvent(event);"
ondragstart="gIdentityHandler.onDragStart(event);">
<hbox id="identity-box-inner" align="center">
<stack id="page-proxy-stack"
onclick="PageProxyClickHandler(event);">
<hbox id="page-proxy-stack"
onclick="PageProxyClickHandler(event);">
<image id="page-proxy-favicon" validate="never"
pageproxystate="invalid"
onerror="this.removeAttribute('src');"/>
</stack>
</hbox>
<hbox id="identity-icon-labels">
<label id="identity-icon-label" class="plain" flex="1"/>
<label id="identity-icon-country-label" class="plain"/>
@ -993,7 +993,6 @@
hidden="true">
<vbox flex="1">
<resizer id="inspector-top-resizer" flex="1"
class="inspector-resizer"
dir="top" disabled="true"
element="inspector-tree-box"/>
<hbox>
@ -1029,10 +1028,6 @@
oncommand="InspectorUI.closeInspectorUI(false);"
tooltiptext="&inspectCloseButton.tooltiptext;"/>
#endif
<resizer id="inspector-end-resizer"
class="inspector-resizer"
dir="top" disabled="true"
element="inspector-tree-box"/>
</hbox>
</vbox>
</toolbar>

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

@ -34,12 +34,11 @@
direction: ltr;
}
.inspector-resizer {
#inspector-top-resizer {
display: none;
}
#inspector-toolbar[treepanel-open] > vbox > #inspector-top-resizer,
#inspector-toolbar[treepanel-open] > vbox > hbox > #inspector-end-resizer {
#inspector-toolbar[treepanel-open] > vbox > #inspector-top-resizer {
display: -moz-box;
}

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

@ -0,0 +1,76 @@
#ifdef 0
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#endif
/**
* This class makes it easy to wait until a batch of callbacks has finished.
*
* Example:
*
* let batch = new Batch(function () alert("finished"));
* let pop = batch.pop.bind(batch);
*
* for (let i = 0; i < 5; i++) {
* batch.push();
* setTimeout(pop, i * 1000);
* }
*
* batch.close();
*/
function Batch(aCallback) {
this._callback = aCallback;
}
Batch.prototype = {
/**
* The number of batch entries.
*/
_count: 0,
/**
* Whether this batch is closed.
*/
_closed: false,
/**
* Increases the number of batch entries by one.
*/
push: function Batch_push() {
if (!this._closed)
this._count++;
},
/**
* Decreases the number of batch entries by one.
*/
pop: function Batch_pop() {
if (this._count)
this._count--;
if (this._closed)
this._check();
},
/**
* Closes the batch so that no new entries can be added.
*/
close: function Batch_close() {
if (this._closed)
return;
this._closed = true;
this._check();
},
/**
* Checks if the batch has finished.
*/
_check: function Batch_check() {
if (this._count == 0 && this._callback) {
this._callback();
this._callback = null;
}
}
};

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

@ -0,0 +1,137 @@
#ifdef 0
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#endif
/**
* This class manages a cell's DOM node (not the actually cell content, a site).
* It's mostly read-only, i.e. all manipulation of both position and content
* aren't handled here.
*/
function Cell(aGrid, aNode) {
this._grid = aGrid;
this._node = aNode;
this._node._newtabCell = this;
// Register drag-and-drop event handlers.
["DragEnter", "DragOver", "DragExit", "Drop"].forEach(function (aType) {
let method = "on" + aType;
this[method] = this[method].bind(this);
this._node.addEventListener(aType.toLowerCase(), this[method], false);
}, this);
}
Cell.prototype = {
/**
*
*/
_grid: null,
/**
* The cell's DOM node.
*/
get node() this._node,
/**
* The cell's offset in the grid.
*/
get index() {
let index = this._grid.cells.indexOf(this);
// Cache this value, overwrite the getter.
Object.defineProperty(this, "index", {value: index, enumerable: true});
return index;
},
/**
* The previous cell in the grid.
*/
get previousSibling() {
let prev = this.node.previousElementSibling;
prev = prev && prev._newtabCell;
// Cache this value, overwrite the getter.
Object.defineProperty(this, "previousSibling", {value: prev, enumerable: true});
return prev;
},
/**
* The next cell in the grid.
*/
get nextSibling() {
let next = this.node.nextElementSibling;
next = next && next._newtabCell;
// Cache this value, overwrite the getter.
Object.defineProperty(this, "nextSibling", {value: next, enumerable: true});
return next;
},
/**
* The site contained in the cell, if any.
*/
get site() {
let firstChild = this.node.firstElementChild;
return firstChild && firstChild._newtabSite;
},
/**
* Checks whether the cell contains a pinned site.
* @return Whether the cell contains a pinned site.
*/
containsPinnedSite: function Cell_containsPinnedSite() {
let site = this.site;
return site && site.isPinned();
},
/**
* Checks whether the cell contains a site (is empty).
* @return Whether the cell is empty.
*/
isEmpty: function Cell_isEmpty() {
return !this.site;
},
/**
* Event handler for the 'dragenter' event.
* @param aEvent The dragenter event.
*/
onDragEnter: function Cell_onDragEnter(aEvent) {
if (gDrag.isValid(aEvent)) {
aEvent.preventDefault();
gDrop.enter(this, aEvent);
}
},
/**
* Event handler for the 'dragover' event.
* @param aEvent The dragover event.
*/
onDragOver: function Cell_onDragOver(aEvent) {
if (gDrag.isValid(aEvent))
aEvent.preventDefault();
},
/**
* Event handler for the 'dragexit' event.
* @param aEvent The dragexit event.
*/
onDragExit: function Cell_onDragExit(aEvent) {
gDrop.exit(this, aEvent);
},
/**
* Event handler for the 'drop' event.
* @param aEvent The drop event.
*/
onDrop: function Cell_onDrop(aEvent) {
if (gDrag.isValid(aEvent)) {
aEvent.preventDefault();
gDrop.drop(this, aEvent);
}
}
};

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

@ -0,0 +1,140 @@
#ifdef 0
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#endif
/**
* This singleton implements site dragging functionality.
*/
let gDrag = {
/**
* The site offset to the drag start point.
*/
_offsetX: null,
_offsetY: null,
/**
* The site that is dragged.
*/
_draggedSite: null,
get draggedSite() this._draggedSite,
/**
* The cell width/height at the point the drag started.
*/
_cellWidth: null,
_cellHeight: null,
get cellWidth() this._cellWidth,
get cellHeight() this._cellHeight,
/**
* Start a new drag operation.
* @param aSite The site that's being dragged.
* @param aEvent The 'dragstart' event.
*/
start: function Drag_start(aSite, aEvent) {
this._draggedSite = aSite;
// Prevent moz-transform for left, top.
aSite.node.setAttribute("dragged", "true");
// Make sure the dragged site is floating above the grid.
aSite.node.setAttribute("ontop", "true");
this._setDragData(aSite, aEvent);
// Store the cursor offset.
let node = aSite.node;
let rect = node.getBoundingClientRect();
this._offsetX = aEvent.clientX - rect.left;
this._offsetY = aEvent.clientY - rect.top;
// Store the cell dimensions.
let cellNode = aSite.cell.node;
this._cellWidth = cellNode.offsetWidth;
this._cellHeight = cellNode.offsetHeight;
gTransformation.freezeSitePosition(aSite);
},
/**
* Handles the 'drag' event.
* @param aSite The site that's being dragged.
* @param aEvent The 'drag' event.
*/
drag: function Drag_drag(aSite, aEvent) {
// Get the viewport size.
let {clientWidth, clientHeight} = document.documentElement;
// We'll want a padding of 5px.
let border = 5;
// Enforce minimum constraints to keep the drag image inside the window.
let left = Math.max(scrollX + aEvent.clientX - this._offsetX, border);
let top = Math.max(scrollY + aEvent.clientY - this._offsetY, border);
// Enforce maximum constraints to keep the drag image inside the window.
left = Math.min(left, scrollX + clientWidth - this.cellWidth - border);
top = Math.min(top, scrollY + clientHeight - this.cellHeight - border);
// Update the drag image's position.
gTransformation.setSitePosition(aSite, {left: left, top: top});
},
/**
* Ends the current drag operation.
* @param aSite The site that's being dragged.
* @param aEvent The 'dragend' event.
*/
end: function Drag_end(aSite, aEvent) {
aSite.node.removeAttribute("dragged");
// Slide the dragged site back into its cell (may be the old or the new cell).
gTransformation.slideSiteTo(aSite, aSite.cell, {
unfreeze: true,
callback: function () aSite.node.removeAttribute("ontop")
});
this._draggedSite = null;
},
/**
* Checks whether we're responsible for a given drag event.
* @param aEvent The drag event to check.
* @return Whether we should handle this drag and drop operation.
*/
isValid: function Drag_isValid(aEvent) {
let dt = aEvent.dataTransfer;
return dt && dt.types.contains("text/x-moz-url");
},
/**
* Initializes the drag data for the current drag operation.
* @param aSite The site that's being dragged.
* @param aEvent The 'dragstart' event.
*/
_setDragData: function Drag_setDragData(aSite, aEvent) {
let {url, title} = aSite;
let dt = aEvent.dataTransfer;
dt.mozCursor = "default";
dt.effectAllowed = "move";
dt.setData("text/plain", url);
dt.setData("text/uri-list", url);
dt.setData("text/x-moz-url", url + "\n" + title);
dt.setData("text/html", "<a href=\"" + url + "\">" + url + "</a>");
// Create and use an empty drag element. We don't want to use the default
// drag image with its default opacity.
let dragElement = document.createElementNS(HTML_NAMESPACE, "div");
dragElement.classList.add("drag-element");
let body = document.getElementById("body");
body.appendChild(dragElement);
dt.setDragImage(dragElement, 0, 0);
// After the 'dragstart' event has been processed we can remove the
// temporary drag element from the DOM.
setTimeout(function () body.removeChild(dragElement), 0);
}
};

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

@ -0,0 +1,147 @@
#ifdef 0
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#endif
// A little delay that prevents the grid from being too sensitive when dragging
// sites around.
const DELAY_REARRANGE_MS = 100;
/**
* This singleton implements site dropping functionality.
*/
let gDrop = {
/**
* The last drop target.
*/
_lastDropTarget: null,
/**
* Handles the 'dragenter' event.
* @param aCell The drop target cell.
*/
enter: function Drop_enter(aCell) {
this._delayedRearrange(aCell);
},
/**
* Handles the 'dragexit' event.
* @param aCell The drop target cell.
* @param aEvent The 'dragexit' event.
*/
exit: function Drop_exit(aCell, aEvent) {
if (aEvent.dataTransfer && !aEvent.dataTransfer.mozUserCancelled) {
this._delayedRearrange();
} else {
// The drag operation has been cancelled.
this._cancelDelayedArrange();
this._rearrange();
}
},
/**
* Handles the 'drop' event.
* @param aCell The drop target cell.
* @param aEvent The 'dragexit' event.
* @param aCallback The callback to call when the drop is finished.
*/
drop: function Drop_drop(aCell, aEvent, aCallback) {
// The cell that is the drop target could contain a pinned site. We need
// to find out where that site has gone and re-pin it there.
if (aCell.containsPinnedSite())
this._repinSitesAfterDrop(aCell);
// Pin the dragged or insert the new site.
this._pinDraggedSite(aCell, aEvent);
this._cancelDelayedArrange();
// Update the grid and move all sites to their new places.
gUpdater.updateGrid(aCallback);
},
/**
* Re-pins all pinned sites in their (new) positions.
* @param aCell The drop target cell.
*/
_repinSitesAfterDrop: function Drop_repinSitesAfterDrop(aCell) {
let sites = gDropPreview.rearrange(aCell);
// Filter out pinned sites.
let pinnedSites = sites.filter(function (aSite) {
return aSite && aSite.isPinned();
});
// Re-pin all shifted pinned cells.
pinnedSites.forEach(function (aSite) aSite.pin(sites.indexOf(aSite)), this);
},
/**
* Pins the dragged site in its new place.
* @param aCell The drop target cell.
* @param aEvent The 'dragexit' event.
*/
_pinDraggedSite: function Drop_pinDraggedSite(aCell, aEvent) {
let index = aCell.index;
let draggedSite = gDrag.draggedSite;
if (draggedSite) {
// Pin the dragged site at its new place.
if (aCell != draggedSite.cell)
draggedSite.pin(index);
} else {
// A new link was dragged onto the grid. Create it by pinning its URL.
let dt = aEvent.dataTransfer;
let [url, title] = dt.getData("text/x-moz-url").split(/[\r\n]+/);
gPinnedLinks.pin({url: url, title: title}, index);
}
},
/**
* Time a rearrange with a little delay.
* @param aCell The drop target cell.
*/
_delayedRearrange: function Drop_delayedRearrange(aCell) {
// The last drop target didn't change so there's no need to re-arrange.
if (this._lastDropTarget == aCell)
return;
let self = this;
function callback() {
self._rearrangeTimeout = null;
self._rearrange(aCell);
}
this._cancelDelayedArrange();
this._rearrangeTimeout = setTimeout(callback, DELAY_REARRANGE_MS);
// Store the last drop target.
this._lastDropTarget = aCell;
},
/**
* Cancels a timed rearrange, if any.
*/
_cancelDelayedArrange: function Drop_cancelDelayedArrange() {
if (this._rearrangeTimeout) {
clearTimeout(this._rearrangeTimeout);
this._rearrangeTimeout = null;
}
},
/**
* Rearrange all sites in the grid depending on the current drop target.
* @param aCell The drop target cell.
*/
_rearrange: function Drop_rearrange(aCell) {
let sites = gGrid.sites;
// We need to rearrange the grid only if there's a current drop target.
if (aCell)
sites = gDropPreview.rearrange(aCell);
gTransformation.rearrangeSites(sites, {unfreeze: !aCell});
}
};

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

@ -0,0 +1,222 @@
#ifdef 0
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#endif
/**
* This singleton provides the ability to re-arrange the current grid to
* indicate the transformation that results from dropping a cell at a certain
* position.
*/
let gDropPreview = {
/**
* Rearranges the sites currently contained in the grid when a site would be
* dropped onto the given cell.
* @param aCell The drop target cell.
* @return The re-arranged array of sites.
*/
rearrange: function DropPreview_rearrange(aCell) {
let sites = gGrid.sites;
// Insert the dragged site into the current grid.
this._insertDraggedSite(sites, aCell);
// After the new site has been inserted we need to correct the positions
// of all pinned tabs that have been moved around.
this._repositionPinnedSites(sites, aCell);
return sites;
},
/**
* Inserts the currently dragged site into the given array of sites.
* @param aSites The array of sites to insert into.
* @param aCell The drop target cell.
*/
_insertDraggedSite: function DropPreview_insertDraggedSite(aSites, aCell) {
let dropIndex = aCell.index;
let draggedSite = gDrag.draggedSite;
// We're currently dragging a site.
if (draggedSite) {
let dragCell = draggedSite.cell;
let dragIndex = dragCell.index;
// Move the dragged site into its new position.
if (dragIndex != dropIndex) {
aSites.splice(dragIndex, 1);
aSites.splice(dropIndex, 0, draggedSite);
}
// We're handling an external drag item.
} else {
aSites.splice(dropIndex, 0, null);
}
},
/**
* Correct the position of all pinned sites that might have been moved to
* different positions after the dragged site has been inserted.
* @param aSites The array of sites containing the dragged site.
* @param aCell The drop target cell.
*/
_repositionPinnedSites:
function DropPreview_repositionPinnedSites(aSites, aCell) {
// Collect all pinned sites.
let pinnedSites = this._filterPinnedSites(aSites, aCell);
// Correct pinned site positions.
pinnedSites.forEach(function (aSite) {
aSites[aSites.indexOf(aSite)] = aSites[aSite.cell.index];
aSites[aSite.cell.index] = aSite;
}, this);
// There might be a pinned cell that got pushed out of the grid, try to
// sneak it in by removing a lower-priority cell.
if (this._hasOverflowedPinnedSite(aSites, aCell))
this._repositionOverflowedPinnedSite(aSites, aCell);
},
/**
* Filter pinned sites out of the grid that are still on their old positions
* and have not moved.
* @param aSites The array of sites to filter.
* @param aCell The drop target cell.
* @return The filtered array of sites.
*/
_filterPinnedSites: function DropPreview_filterPinnedSites(aSites, aCell) {
let draggedSite = gDrag.draggedSite;
// When dropping on a cell that contains a pinned site make sure that all
// pinned cells surrounding the drop target are moved as well.
let range = this._getPinnedRange(aCell);
return aSites.filter(function (aSite, aIndex) {
// The site must be valid, pinned and not the dragged site.
if (!aSite || aSite == draggedSite || !aSite.isPinned())
return false;
let index = aSite.cell.index;
// If it's not in the 'pinned range' it's a valid pinned site.
return (index > range.end || index < range.start);
});
},
/**
* Determines the range of pinned sites surrounding the drop target cell.
* @param aCell The drop target cell.
* @return The range of pinned cells.
*/
_getPinnedRange: function DropPreview_getPinnedRange(aCell) {
let dropIndex = aCell.index;
let range = {start: dropIndex, end: dropIndex};
// We need a pinned range only when dropping on a pinned site.
if (aCell.containsPinnedSite()) {
let links = gPinnedLinks.links;
// Find all previous siblings of the drop target that are pinned as well.
while (range.start && links[range.start - 1])
range.start--;
let maxEnd = links.length - 1;
// Find all next siblings of the drop target that are pinned as well.
while (range.end < maxEnd && links[range.end + 1])
range.end++;
}
return range;
},
/**
* Checks if the given array of sites contains a pinned site that has
* been pushed out of the grid.
* @param aSites The array of sites to check.
* @param aCell The drop target cell.
* @return Whether there is an overflowed pinned cell.
*/
_hasOverflowedPinnedSite:
function DropPreview_hasOverflowedPinnedSite(aSites, aCell) {
// If the drop target isn't pinned there's no way a pinned site has been
// pushed out of the grid so we can just exit here.
if (!aCell.containsPinnedSite())
return false;
let cells = gGrid.cells;
// No cells have been pushed out of the grid, nothing to do here.
if (aSites.length <= cells.length)
return false;
let overflowedSite = aSites[cells.length];
// Nothing to do if the site that got pushed out of the grid is not pinned.
return (overflowedSite && overflowedSite.isPinned());
},
/**
* We have a overflowed pinned site that we need to re-position so that it's
* visible again. We try to find a lower-priority cell (empty or containing
* an unpinned site) that we can move it to.
* @param aSites The array of sites.
* @param aCell The drop target cell.
*/
_repositionOverflowedPinnedSite:
function DropPreview_repositionOverflowedPinnedSite(aSites, aCell) {
// Try to find a lower-priority cell (empty or containing an unpinned site).
let index = this._indexOfLowerPrioritySite(aSites, aCell);
if (index > -1) {
let cells = gGrid.cells;
let dropIndex = aCell.index;
// Move all pinned cells to their new positions to let the overflowed
// site fit into the grid.
for (let i = index + 1, lastPosition = index; i < aSites.length; i++) {
if (i != dropIndex) {
aSites[lastPosition] = aSites[i];
lastPosition = i;
}
}
// Finally, remove the overflowed site from its previous position.
aSites.splice(cells.length, 1);
}
},
/**
* Finds the index of the last cell that is empty or contains an unpinned
* site. These are considered to be of a lower priority.
* @param aSites The array of sites.
* @param aCell The drop target cell.
* @return The cell's index.
*/
_indexOfLowerPrioritySite:
function DropPreview_indexOfLowerPrioritySite(aSites, aCell) {
let cells = gGrid.cells;
let dropIndex = aCell.index;
// Search (beginning with the last site in the grid) for a site that is
// empty or unpinned (an thus lower-priority) and can be pushed out of the
// grid instead of the pinned site.
for (let i = cells.length - 1; i >= 0; i--) {
// The cell that is our drop target is not a good choice.
if (i == dropIndex)
continue;
let site = aSites[i];
// We can use the cell only if it's empty or the site is un-pinned.
if (!site || !site.isPinned())
return i;
}
return -1;
}
};

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

@ -0,0 +1,178 @@
#ifdef 0
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#endif
/**
* This singleton provides a custom drop target detection. We need this because
* the default DnD target detection relies on the cursor's position. We want
* to pick a drop target based on the dragged site's position.
*/
let gDropTargetShim = {
/**
* Cache for the position of all cells, cleaned after drag finished.
*/
_cellPositions: null,
/**
* The last drop target that was hovered.
*/
_lastDropTarget: null,
/**
* Initializes the drop target shim.
*/
init: function DropTargetShim_init() {
let node = gGrid.node;
this._dragover = this._dragover.bind(this);
// Add drag event handlers.
node.addEventListener("dragstart", this._start.bind(this), true);
// XXX bug 505521 - Don't listen for drag, it's useless at the moment.
//node.addEventListener("drag", this._drag.bind(this), false);
node.addEventListener("dragend", this._end.bind(this), true);
},
/**
* Handles the 'dragstart' event.
* @param aEvent The 'dragstart' event.
*/
_start: function DropTargetShim_start(aEvent) {
gGrid.lock();
// XXX bug 505521 - Listen for dragover on the document.
document.documentElement.addEventListener("dragover", this._dragover, false);
},
/**
* Handles the 'drag' event and determines the current drop target.
* @param aEvent The 'drag' event.
*/
_drag: function DropTargetShim_drag(aEvent) {
// Let's see if we find a drop target.
let target = this._findDropTarget(aEvent);
if (target == this._lastDropTarget) {
// XXX bug 505521 - Don't fire dragover for now (causes recursion).
/*if (target)
// The last drop target is valid and didn't change.
this._dispatchEvent(aEvent, "dragover", target);*/
} else {
if (this._lastDropTarget)
// We left the last drop target.
this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget);
if (target)
// We're now hovering a (new) drop target.
this._dispatchEvent(aEvent, "dragenter", target);
if (this._lastDropTarget)
// We left the last drop target.
this._dispatchEvent(aEvent, "dragleave", this._lastDropTarget);
this._lastDropTarget = target;
}
},
/**
* Handles the 'dragover' event as long as bug 505521 isn't fixed to get
* current mouse cursor coordinates while dragging.
* @param aEvent The 'dragover' event.
*/
_dragover: function DropTargetShim_dragover(aEvent) {
let sourceNode = aEvent.dataTransfer.mozSourceNode;
gDrag.drag(sourceNode._newtabSite, aEvent);
this._drag(aEvent);
},
/**
* Handles the 'dragend' event.
* @param aEvent The 'dragend' event.
*/
_end: function DropTargetShim_end(aEvent) {
// Make sure to determine the current drop target in case the dragenter
// event hasn't been fired.
this._drag(aEvent);
if (this._lastDropTarget) {
if (aEvent.dataTransfer.mozUserCancelled) {
// The drag operation was cancelled.
this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget);
this._dispatchEvent(aEvent, "dragleave", this._lastDropTarget);
} else {
// A site was successfully dropped.
this._dispatchEvent(aEvent, "drop", this._lastDropTarget);
}
// Clean up.
this._lastDropTarget = null;
this._cellPositions = null;
}
gGrid.unlock();
// XXX bug 505521 - Remove the document's dragover listener.
document.documentElement.removeEventListener("dragover", this._dragover, false);
},
/**
* Determines the current drop target by matching the dragged site's position
* against all cells in the grid.
* @return The currently hovered drop target or null.
*/
_findDropTarget: function DropTargetShim_findDropTarget() {
// These are the minimum intersection values - we want to use the cell if
// the site is >= 50% hovering its position.
let minWidth = gDrag.cellWidth / 2;
let minHeight = gDrag.cellHeight / 2;
let cellPositions = this._getCellPositions();
let rect = gTransformation.getNodePosition(gDrag.draggedSite.node);
// Compare each cell's position to the dragged site's position.
for (let i = 0; i < cellPositions.length; i++) {
let inter = rect.intersect(cellPositions[i].rect);
// If the intersection is big enough we found a drop target.
if (inter.width >= minWidth && inter.height >= minHeight)
return cellPositions[i].cell;
}
// No drop target found.
return null;
},
/**
* Gets the positions of all cell nodes.
* @return The (cached) cell positions.
*/
_getCellPositions: function DropTargetShim_getCellPositions() {
if (this._cellPositions)
return this._cellPositions;
return this._cellPositions = gGrid.cells.map(function (cell) {
return {cell: cell, rect: gTransformation.getNodePosition(cell.node)};
});
},
/**
* Dispatches a custom DragEvent on the given target node.
* @param aEvent The source event.
* @param aType The event type.
* @param aTarget The target node that receives the event.
*/
_dispatchEvent:
function DropTargetShim_dispatchEvent(aEvent, aType, aTarget) {
let node = aTarget.node;
let event = document.createEvent("DragEvents");
event.initDragEvent(aType, true, true, window, 0, 0, 0, 0, 0, false, false,
false, false, 0, node, aEvent.dataTransfer);
node.dispatchEvent(event);
}
};

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

@ -0,0 +1,132 @@
#ifdef 0
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#endif
/**
* This singleton represents the grid that contains all sites.
*/
let gGrid = {
/**
* The DOM node of the grid.
*/
_node: null,
get node() this._node,
/**
* The cached DOM fragment for sites.
*/
_siteFragment: null,
/**
* All cells contained in the grid.
*/
get cells() {
let children = this.node.querySelectorAll("li");
let cells = [new Cell(this, child) for each (child in children)];
// Replace the getter with our cached value.
Object.defineProperty(this, "cells", {value: cells, enumerable: true});
return cells;
},
/**
* All sites contained in the grid's cells. Sites may be empty.
*/
get sites() [cell.site for each (cell in this.cells)],
/**
* Initializes the grid.
* @param aSelector The query selector of the grid.
*/
init: function Grid_init(aSelector) {
this._node = document.querySelector(aSelector);
this._createSiteFragment();
this._draw();
},
/**
* Creates a new site in the grid.
* @param aLink The new site's link.
* @param aCell The cell that will contain the new site.
* @return The newly created site.
*/
createSite: function Grid_createSite(aLink, aCell) {
let node = aCell.node;
node.appendChild(this._siteFragment.cloneNode(true));
return new Site(node.firstElementChild, aLink);
},
/**
* Refreshes the grid and re-creates all sites.
*/
refresh: function Grid_refresh() {
// Remove all sites.
this.cells.forEach(function (cell) {
let node = cell.node;
let child = node.firstElementChild;
if (child)
node.removeChild(child);
}, this);
// Draw the grid again.
this._draw();
},
/**
* Locks the grid to block all pointer events.
*/
lock: function Grid_lock() {
this.node.setAttribute("locked", "true");
},
/**
* Unlocks the grid to allow all pointer events.
*/
unlock: function Grid_unlock() {
this.node.removeAttribute("locked");
},
/**
* Creates the DOM fragment that is re-used when creating sites.
*/
_createSiteFragment: function Grid_createSiteFragment() {
let site = document.createElementNS(HTML_NAMESPACE, "a");
site.classList.add("site");
site.setAttribute("draggable", "true");
// Create the site's inner HTML code.
site.innerHTML =
'<img class="site-img" width="' + THUMB_WIDTH +'" ' +
' height="' + THUMB_HEIGHT + '" alt=""/>' +
'<span class="site-title"/>' +
'<span class="site-strip">' +
' <input class="button strip-button strip-button-pin" type="button"' +
' tabindex="-1" title="' + newTabString("pin") + '"/>' +
' <input class="button strip-button strip-button-block" type="button"' +
' tabindex="-1" title="' + newTabString("block") + '"/>' +
'</span>';
this._siteFragment = document.createDocumentFragment();
this._siteFragment.appendChild(site);
},
/**
* Draws the grid, creates all sites and puts them into their cells.
*/
_draw: function Grid_draw() {
let cells = this.cells;
// Put sites into the cells.
let links = gLinks.getLinks();
let length = Math.min(links.length, cells.length);
for (let i = 0; i < length; i++) {
if (links[i])
this.createSite(links[i], cells[i]);
}
}
};

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

@ -0,0 +1,173 @@
:root {
-moz-appearance: none;
}
#scrollbox:not([page-disabled]) {
overflow: auto;
}
#body {
position: relative;
margin: 0;
min-width: 675px;
-moz-user-select: none;
}
.button {
cursor: pointer;
}
/* TOOLBAR */
#toolbar {
position: absolute;
}
#toolbar[page-disabled] {
position: fixed;
}
#toolbar:-moz-locale-dir(rtl) {
left: 8px;
right: auto;
}
.toolbar-button {
position: absolute;
cursor: pointer;
-moz-transition: opacity 200ms ease-out;
}
#toolbar-button-show,
#toolbar-button-reset {
opacity: 0;
pointer-events: none;
}
#toolbar-button-reset[modified],
#toolbar-button-show[page-disabled] {
opacity: 1;
pointer-events: auto;
}
#toolbar-button-hide[page-disabled],
#toolbar-button-reset[page-disabled] {
opacity: 0;
pointer-events: none;
}
/* GRID */
#grid {
width: 637px;
height: 411px;
overflow: hidden;
list-style-type: none;
-moz-transition: opacity 200ms ease-out;
}
#grid[page-disabled] {
opacity: 0;
}
#grid[page-disabled],
#grid[locked] {
pointer-events: none;
}
/* CELLS */
.cell {
float: left;
width: 201px;
height: 127px;
margin-bottom: 15px;
-moz-margin-end: 16px;
}
.cell:-moz-locale-dir(rtl) {
float: right;
}
.cell:nth-child(3n+3) {
-moz-margin-end: 0;
}
/* SITES */
.site {
display: block;
position: relative;
width: 201px;
height: 127px;
}
.site[frozen] {
position: absolute;
pointer-events: none;
}
.site[ontop] {
z-index: 10;
}
/* SITE IMAGE */
.site-img {
display: block;
opacity: 0.75;
-moz-transition: opacity 200ms ease-out;
}
.site:hover > .site-img,
.site[ontop] > .site-img,
.site:-moz-focusring > .site-img {
opacity: 1;
}
.site-img[loading] {
display: none;
}
/* SITE TITLE */
.site-title {
position: absolute;
left: 0;
bottom: 0;
overflow: hidden;
}
/* SITE STRIP */
.site-strip {
position: absolute;
left: 0;
top: 0;
width: 195px;
height: 17px;
overflow: hidden;
opacity: 0;
-moz-transition: opacity 200ms ease-out;
}
.site:hover:not([frozen]) > .site-strip {
opacity: 1;
}
.strip-button-pin,
.strip-button-block:-moz-locale-dir(rtl) {
float: left;
}
.strip-button-block,
.strip-button-pin:-moz-locale-dir(rtl) {
float: right;
}
/* DRAG & DROP */
/*
* This is just a temporary drag element used for dataTransfer.setDragImage()
* so that we can use custom drag images and elements. It needs an opacity of
* 0.01 so that the core code detects that it's in fact a visible element.
*/
.drag-element {
width: 1px;
height: 1px;
background-color: #fff;
opacity: 0.01;
}

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

@ -0,0 +1,47 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let Cu = Components.utils;
let Ci = Components.interfaces;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource:///modules/PageThumbs.jsm");
Cu.import("resource:///modules/NewTabUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Rect",
"resource://gre/modules/Geometry.jsm");
let {
links: gLinks,
allPages: gAllPages,
pinnedLinks: gPinnedLinks,
blockedLinks: gBlockedLinks
} = NewTabUtils;
XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() {
return Services.strings.
createBundle("chrome://browser/locale/newTab.properties");
});
function newTabString(name) gStringBundle.GetStringFromName('newtab.' + name);
const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
const THUMB_WIDTH = 201;
const THUMB_HEIGHT = 127;
#include batch.js
#include transformations.js
#include page.js
#include toolbar.js
#include grid.js
#include cells.js
#include sites.js
#include drag.js
#include drop.js
#include dropTargetShim.js
#include dropPreview.js
#include updater.js

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

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
<?xml-stylesheet href="chrome://global/skin/global.css"?>
<?xml-stylesheet href="chrome://browser/content/newtab/newTab.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/newtab/newTab.css" type="text/css"?>
<!DOCTYPE window [
<!ENTITY % newTabDTD SYSTEM "chrome://browser/locale/newTab.dtd">
%newTabDTD;
]>
<xul:window xmlns="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
disablefastfind="true" title="&newtab.pageTitle;">
<xul:vbox id="scrollbox" flex="1" title=" ">
<body id="body">
<div id="toolbar">
<input class="button toolbar-button" id="toolbar-button-show"
type="button" title="&newtab.show;"/>
<input class="button toolbar-button" id="toolbar-button-hide"
type="button" title="&newtab.hide;"/>
<input class="button toolbar-button" id="toolbar-button-reset"
type="button" title="&newtab.reset;"/>
</div>
<ul id="grid">
<li class="cell"/><li class="cell"/><li class="cell"/>
<li class="cell"/><li class="cell"/><li class="cell"/>
<li class="cell"/><li class="cell"/><li class="cell"/>
</ul>
<xul:script type="text/javascript;version=1.8" src="chrome://browser/content/newtab/newTab.js"/>
<xul:script type="text/javascript;version=1.8">
gPage.init("#toolbar", "#grid");
</xul:script>
</body>
</xul:vbox>
</xul:window>

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

@ -0,0 +1,173 @@
#ifdef 0
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#endif
/**
* This singleton represents the whole 'New Tab Page' and takes care of
* initializing all its components.
*/
let gPage = {
/**
* Initializes the page.
* @param aToolbarSelector The query selector for the page toolbar.
* @param aGridSelector The query selector for the grid.
*/
init: function Page_init(aToolbarSelector, aGridSelector) {
gToolbar.init(aToolbarSelector);
this._gridSelector = aGridSelector;
// Add ourselves to the list of pages to receive notifications.
gAllPages.register(this);
// Listen for 'unload' to unregister this page.
function unload() gAllPages.unregister(self);
addEventListener("unload", unload, false);
// Check if the new tab feature is enabled.
if (gAllPages.enabled)
this._init();
else
this._updateAttributes(false);
},
/**
* Listens for notifications specific to this page.
*/
observe: function Page_observe() {
let enabled = gAllPages.enabled;
this._updateAttributes(enabled);
// Initialize the whole page if we haven't done that, yet.
if (enabled)
this._init();
},
/**
* Updates the whole page and the grid when the storage has changed.
*/
update: function Page_update() {
this.updateModifiedFlag();
gGrid.refresh();
},
/**
* Checks if the page is modified and sets the CSS class accordingly
*/
updateModifiedFlag: function Page_updateModifiedFlag() {
let node = document.getElementById("toolbar-button-reset");
let modified = this._isModified();
if (modified)
node.setAttribute("modified", "true");
else
node.removeAttribute("modified");
this._updateTabIndices(gAllPages.enabled, modified);
},
/**
* Internally initializes the page. This runs only when/if the feature
* is/gets enabled.
*/
_init: function Page_init() {
if (this._initialized)
return;
this._initialized = true;
gLinks.populateCache(function () {
// Check if the grid is modified.
this.updateModifiedFlag();
// Initialize and render the grid.
gGrid.init(this._gridSelector);
// Initialize the drop target shim.
gDropTargetShim.init();
// Workaround to prevent a delay on MacOSX due to a slow drop animation.
let doc = document.documentElement;
doc.addEventListener("dragover", this.onDragOver, false);
doc.addEventListener("drop", this.onDrop, false);
}.bind(this));
},
/**
* Updates the 'page-disabled' attributes of the respective DOM nodes.
* @param aValue Whether to set or remove attributes.
*/
_updateAttributes: function Page_updateAttributes(aValue) {
let nodes = document.querySelectorAll("#grid, #scrollbox, #toolbar, .toolbar-button");
// Set the nodes' states.
for (let i = 0; i < nodes.length; i++) {
let node = nodes[i];
if (aValue)
node.removeAttribute("page-disabled");
else
node.setAttribute("page-disabled", "true");
}
this._updateTabIndices(aValue, this._isModified());
},
/**
* Checks whether the page is modified.
* @return Whether the page is modified or not.
*/
_isModified: function Page_isModified() {
// The page is considered modified only if sites have been removed.
return !gBlockedLinks.isEmpty();
},
/**
* Updates the tab indices of focusable elements.
* @param aEnabled Whether the page is currently enabled.
* @param aModified Whether the page is currently modified.
*/
_updateTabIndices: function Page_updateTabIndices(aEnabled, aModified) {
function setFocusable(aNode, aFocusable) {
if (aFocusable)
aNode.removeAttribute("tabindex");
else
aNode.setAttribute("tabindex", "-1");
}
// Sites and the 'hide' button are always focusable when the grid is shown.
let nodes = document.querySelectorAll(".site, #toolbar-button-hide");
for (let i = 0; i < nodes.length; i++)
setFocusable(nodes[i], aEnabled);
// The 'show' button is focusable when the grid is hidden.
let btnShow = document.getElementById("toolbar-button-show");
setFocusable(btnShow, !aEnabled);
// The 'reset' button is focusable when the grid is shown and modified.
let btnReset = document.getElementById("toolbar-button-reset");
setFocusable(btnReset, aEnabled && aModified);
},
/**
* Handles the 'dragover' event. Workaround to prevent a delay on MacOSX
* due to a slow drop animation.
* @param aEvent The 'dragover' event.
*/
onDragOver: function Page_onDragOver(aEvent) {
if (gDrag.isValid(aEvent))
aEvent.preventDefault();
},
/**
* Handles the 'drop' event. Workaround to prevent a delay on MacOSX due to
* a slow drop animation.
* @param aEvent The 'drop' event.
*/
onDrop: function Page_onDrop(aEvent) {
if (gDrag.isValid(aEvent)) {
aEvent.preventDefault();
aEvent.stopPropagation();
}
}
};

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

@ -0,0 +1,209 @@
#ifdef 0
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#endif
/**
* This class represents a site that is contained in a cell and can be pinned,
* moved around or deleted.
*/
function Site(aNode, aLink) {
this._node = aNode;
this._node._newtabSite = this;
this._link = aLink;
this._render();
this._addEventHandlers();
}
Site.prototype = {
/**
* The site's DOM node.
*/
get node() this._node,
/**
* The site's link.
*/
get link() this._link,
/**
* The url of the site's link.
*/
get url() this.link.url,
/**
* The title of the site's link.
*/
get title() this.link.title,
/**
* The site's parent cell.
*/
get cell() {
let parentNode = this.node.parentNode;
return parentNode && parentNode._newtabCell;
},
/**
* Pins the site on its current or a given index.
* @param aIndex The pinned index (optional).
*/
pin: function Site_pin(aIndex) {
if (typeof aIndex == "undefined")
aIndex = this.cell.index;
this._updateAttributes(true);
gPinnedLinks.pin(this._link, aIndex);
},
/**
* Unpins the site and calls the given callback when done.
* @param aCallback The callback to be called when finished.
*/
unpin: function Site_unpin(aCallback) {
if (this.isPinned()) {
this._updateAttributes(false);
gPinnedLinks.unpin(this._link);
gUpdater.updateGrid(aCallback);
}
},
/**
* Checks whether this site is pinned.
* @return Whether this site is pinned.
*/
isPinned: function Site_isPinned() {
return gPinnedLinks.isPinned(this._link);
},
/**
* Blocks the site (removes it from the grid) and calls the given callback
* when done.
* @param aCallback The callback to be called when finished.
*/
block: function Site_block(aCallback) {
gBlockedLinks.block(this._link);
gUpdater.updateGrid(aCallback);
gPage.updateModifiedFlag();
},
/**
* Gets the DOM node specified by the given query selector.
* @param aSelector The query selector.
* @return The DOM node we found.
*/
_querySelector: function Site_querySelector(aSelector) {
return this.node.querySelector(aSelector);
},
/**
* Updates attributes for all nodes which status depends on this site being
* pinned or unpinned.
* @param aPinned Whether this site is now pinned or unpinned.
*/
_updateAttributes: function (aPinned) {
let buttonPin = this._querySelector(".strip-button-pin");
if (aPinned) {
this.node.setAttribute("pinned", true);
buttonPin.setAttribute("title", newTabString("unpin"));
} else {
this.node.removeAttribute("pinned");
buttonPin.setAttribute("title", newTabString("pin"));
}
},
/**
* Renders the site's data (fills the HTML fragment).
*/
_render: function Site_render() {
let title = this.title || this.url;
this.node.setAttribute("title", title);
this.node.setAttribute("href", this.url);
this._querySelector(".site-title").textContent = title;
if (this.isPinned())
this._updateAttributes(true);
this._renderThumbnail();
},
/**
* Renders the site's thumbnail.
*/
_renderThumbnail: function Site_renderThumbnail() {
let img = this._querySelector(".site-img")
img.setAttribute("alt", this.title || this.url);
img.setAttribute("loading", "true");
// Wait until the image has loaded.
img.addEventListener("load", function onLoad() {
img.removeEventListener("load", onLoad, false);
img.removeAttribute("loading");
}, false);
// Set the thumbnail url.
img.setAttribute("src", PageThumbs.getThumbnailURL(this.url));
},
/**
* Adds event handlers for the site and its buttons.
*/
_addEventHandlers: function Site_addEventHandlers() {
// Register drag-and-drop event handlers.
["DragStart", /*"Drag",*/ "DragEnd"].forEach(function (aType) {
let method = "_on" + aType;
this[method] = this[method].bind(this);
this._node.addEventListener(aType.toLowerCase(), this[method], false);
}, this);
let self = this;
function pin(aEvent) {
if (aEvent)
aEvent.preventDefault();
if (self.isPinned())
self.unpin();
else
self.pin();
}
function block(aEvent) {
if (aEvent)
aEvent.preventDefault();
self.block();
}
this._querySelector(".strip-button-pin").addEventListener("click", pin, false);
this._querySelector(".strip-button-block").addEventListener("click", block, false);
},
/**
* Event handler for the 'dragstart' event.
* @param aEvent The drag event.
*/
_onDragStart: function Site_onDragStart(aEvent) {
gDrag.start(this, aEvent);
},
/**
* Event handler for the 'drag' event.
* @param aEvent The drag event.
*/
_onDrag: function Site_onDrag(aEvent) {
gDrag.drag(this, aEvent);
},
/**
* Event handler for the 'dragend' event.
* @param aEvent The drag event.
*/
_onDragEnd: function Site_onDragEnd(aEvent) {
gDrag.end(this, aEvent);
}
};

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

@ -0,0 +1,87 @@
#ifdef 0
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#endif
/**
* This singleton represents the page's toolbar that allows to enable/disable
* the 'New Tab Page' feature and to reset the whole page.
*/
let gToolbar = {
/**
* Initializes the toolbar.
* @param aSelector The query selector of the toolbar.
*/
init: function Toolbar_init(aSelector) {
this._node = document.querySelector(aSelector);
let buttons = this._node.querySelectorAll("input");
// Listen for 'click' events on the toolbar buttons.
["show", "hide", "reset"].forEach(function (aType, aIndex) {
let self = this;
let button = buttons[aIndex];
let handler = function () self[aType]();
button.addEventListener("click", handler, false);
#ifdef XP_MACOSX
// Per default buttons lose focus after being clicked on Mac OS X.
// So when the URL bar has focus and a toolbar button is clicked the
// URL bar regains focus and the history pops up. We need to prevent
// that by explicitly removing its focus.
button.addEventListener("mousedown", function () {
window.focus();
}, false);
#endif
}, this);
},
/**
* Enables the 'New Tab Page' feature.
*/
show: function Toolbar_show() {
this._passButtonFocus("show", "hide");
gAllPages.enabled = true;
},
/**
* Disables the 'New Tab Page' feature.
*/
hide: function Toolbar_hide() {
this._passButtonFocus("hide", "show");
gAllPages.enabled = false;
},
/**
* Resets the whole page and forces it to re-render its content.
* @param aCallback The callback to call when the page has been reset.
*/
reset: function Toolbar_reset(aCallback) {
this._passButtonFocus("reset", "hide");
let node = gGrid.node;
// animate the page reset
gTransformation.fadeNodeOut(node, function () {
NewTabUtils.reset();
gLinks.populateCache(function () {
gAllPages.update();
// Without the setTimeout() we have a strange flicker.
setTimeout(function () gTransformation.fadeNodeIn(node, aCallback));
}, true);
});
},
/**
* Passes the focus from the current button to the next.
* @param aCurrent The button that currently has focus.
* @param aNext The button that is focused next.
*/
_passButtonFocus: function Toolbar_passButtonFocus(aCurrent, aNext) {
if (document.querySelector("#toolbar-button-" + aCurrent + ":-moz-focusring"))
document.getElementById("toolbar-button-" + aNext).focus();
}
};

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

@ -0,0 +1,226 @@
#ifdef 0
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#endif
/**
* This singleton allows to transform the grid by repositioning a site's node
* in the DOM and by showing or hiding the node. It additionally provides
* convenience methods to work with a site's DOM node.
*/
let gTransformation = {
/**
* Gets a DOM node's position.
* @param aNode The DOM node.
* @return A Rect instance with the position.
*/
getNodePosition: function Transformation_getNodePosition(aNode) {
let {left, top, width, height} = aNode.getBoundingClientRect();
return new Rect(left + scrollX, top + scrollY, width, height);
},
/**
* Fades a given node from zero to full opacity.
* @param aNode The node to fade.
* @param aCallback The callback to call when finished.
*/
fadeNodeIn: function Transformation_fadeNodeIn(aNode, aCallback) {
this._setNodeOpacity(aNode, 1, function () {
// Clear the style property.
aNode.style.opacity = "";
if (aCallback)
aCallback();
});
},
/**
* Fades a given node from full to zero opacity.
* @param aNode The node to fade.
* @param aCallback The callback to call when finished.
*/
fadeNodeOut: function Transformation_fadeNodeOut(aNode, aCallback) {
this._setNodeOpacity(aNode, 0, aCallback);
},
/**
* Fades a given site from zero to full opacity.
* @param aSite The site to fade.
* @param aCallback The callback to call when finished.
*/
showSite: function Transformation_showSite(aSite, aCallback) {
this.fadeNodeIn(aSite.node, aCallback);
},
/**
* Fades a given site from full to zero opacity.
* @param aSite The site to fade.
* @param aCallback The callback to call when finished.
*/
hideSite: function Transformation_hideSite(aSite, aCallback) {
this.fadeNodeOut(aSite.node, aCallback);
},
/**
* Allows to set a site's position.
* @param aSite The site to re-position.
* @param aPosition The desired position for the given site.
*/
setSitePosition: function Transformation_setSitePosition(aSite, aPosition) {
let style = aSite.node.style;
let {top, left} = aPosition;
style.top = top + "px";
style.left = left + "px";
},
/**
* Freezes a site in its current position by positioning it absolute.
* @param aSite The site to freeze.
*/
freezeSitePosition: function Transformation_freezeSitePosition(aSite) {
aSite.node.setAttribute("frozen", "true");
this.setSitePosition(aSite, this.getNodePosition(aSite.node));
},
/**
* Unfreezes a site by removing its absolute positioning.
* @param aSite The site to unfreeze.
*/
unfreezeSitePosition: function Transformation_unfreezeSitePosition(aSite) {
let style = aSite.node.style;
style.left = style.top = "";
aSite.node.removeAttribute("frozen");
},
/**
* Slides the given site to the target node's position.
* @param aSite The site to move.
* @param aTarget The slide target.
* @param aOptions Set of options (see below).
* unfreeze - unfreeze the site after sliding
* callback - the callback to call when finished
*/
slideSiteTo: function Transformation_slideSiteTo(aSite, aTarget, aOptions) {
let currentPosition = this.getNodePosition(aSite.node);
let targetPosition = this.getNodePosition(aTarget.node)
let callback = aOptions && aOptions.callback;
let self = this;
function finish() {
if (aOptions && aOptions.unfreeze)
self.unfreezeSitePosition(aSite);
if (callback)
callback();
}
// Nothing to do here if the positions already match.
if (currentPosition.equals(targetPosition)) {
finish();
} else {
this.setSitePosition(aSite, targetPosition);
this._whenTransitionEnded(aSite.node, finish);
}
},
/**
* Rearranges a given array of sites and moves them to their new positions or
* fades in/out new/removed sites.
* @param aSites An array of sites to rearrange.
* @param aOptions Set of options (see below).
* unfreeze - unfreeze the site after rearranging
* callback - the callback to call when finished
*/
rearrangeSites: function Transformation_rearrangeSites(aSites, aOptions) {
let batch;
let cells = gGrid.cells;
let callback = aOptions && aOptions.callback;
let unfreeze = aOptions && aOptions.unfreeze;
if (callback) {
batch = new Batch(callback);
callback = function () batch.pop();
}
aSites.forEach(function (aSite, aIndex) {
// Do not re-arrange empty cells or the dragged site.
if (!aSite || aSite == gDrag.draggedSite)
return;
if (batch)
batch.push();
if (!cells[aIndex])
// The site disappeared from the grid, hide it.
this.hideSite(aSite, callback);
else if (this._getNodeOpacity(aSite.node) != 1)
// The site disappeared before but is now back, show it.
this.showSite(aSite, callback);
else
// The site's position has changed, move it around.
this._moveSite(aSite, aIndex, {unfreeze: unfreeze, callback: callback});
}, this);
if (batch)
batch.close();
},
/**
* Listens for the 'transitionend' event on a given node and calls the given
* callback.
* @param aNode The node that is transitioned.
* @param aCallback The callback to call when finished.
*/
_whenTransitionEnded:
function Transformation_whenTransitionEnded(aNode, aCallback) {
aNode.addEventListener("transitionend", function onEnd() {
aNode.removeEventListener("transitionend", onEnd, false);
aCallback();
}, false);
},
/**
* Gets a given node's opacity value.
* @param aNode The node to get the opacity value from.
* @return The node's opacity value.
*/
_getNodeOpacity: function Transformation_getNodeOpacity(aNode) {
let cstyle = window.getComputedStyle(aNode, null);
return cstyle.getPropertyValue("opacity");
},
/**
* Sets a given node's opacity.
* @param aNode The node to set the opacity value for.
* @param aOpacity The opacity value to set.
* @param aCallback The callback to call when finished.
*/
_setNodeOpacity:
function Transformation_setNodeOpacity(aNode, aOpacity, aCallback) {
if (this._getNodeOpacity(aNode) == aOpacity) {
if (aCallback)
aCallback();
} else {
if (aCallback)
this._whenTransitionEnded(aNode, aCallback);
aNode.style.opacity = aOpacity;
}
},
/**
* Moves a site to the cell with the given index.
* @param aSite The site to move.
* @param aIndex The target cell's index.
* @param aOptions Options that are directly passed to slideSiteTo().
*/
_moveSite: function Transformation_moveSite(aSite, aIndex, aOptions) {
this.freezeSitePosition(aSite);
this.slideSiteTo(aSite, gGrid.cells[aIndex], aOptions);
}
};

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

@ -0,0 +1,182 @@
#ifdef 0
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#endif
/**
* This singleton provides functionality to update the current grid to a new
* set of pinned and blocked sites. It adds, moves and removes sites.
*/
let gUpdater = {
/**
* Updates the current grid according to its pinned and blocked sites.
* This removes old, moves existing and creates new sites to fill gaps.
* @param aCallback The callback to call when finished.
*/
updateGrid: function Updater_updateGrid(aCallback) {
let links = gLinks.getLinks().slice(0, gGrid.cells.length);
// Find all sites that remain in the grid.
let sites = this._findRemainingSites(links);
let self = this;
// Remove sites that are no longer in the grid.
this._removeLegacySites(sites, function () {
// Freeze all site positions so that we can move their DOM nodes around
// without any visual impact.
self._freezeSitePositions(sites);
// Move the sites' DOM nodes to their new position in the DOM. This will
// have no visual effect as all the sites have been frozen and will
// remain in their current position.
self._moveSiteNodes(sites);
// Now it's time to animate the sites actually moving to their new
// positions.
self._rearrangeSites(sites, function () {
// Try to fill empty cells and finish.
self._fillEmptyCells(links, aCallback);
// Update other pages that might be open to keep them synced.
gAllPages.update(gPage);
});
});
},
/**
* Takes an array of links and tries to correlate them to sites contained in
* the current grid. If no corresponding site can be found (i.e. the link is
* new and a site will be created) then just set it to null.
* @param aLinks The array of links to find sites for.
* @return Array of sites mapped to the given links (can contain null values).
*/
_findRemainingSites: function Updater_findRemainingSites(aLinks) {
let map = {};
// Create a map to easily retrieve the site for a given URL.
gGrid.sites.forEach(function (aSite) {
if (aSite)
map[aSite.url] = aSite;
});
// Map each link to its corresponding site, if any.
return aLinks.map(function (aLink) {
return aLink && (aLink.url in map) && map[aLink.url];
});
},
/**
* Freezes the given sites' positions.
* @param aSites The array of sites to freeze.
*/
_freezeSitePositions: function Updater_freezeSitePositions(aSites) {
aSites.forEach(function (aSite) {
if (aSite)
gTransformation.freezeSitePosition(aSite);
});
},
/**
* Moves the given sites' DOM nodes to their new positions.
* @param aSites The array of sites to move.
*/
_moveSiteNodes: function Updater_moveSiteNodes(aSites) {
let cells = gGrid.cells;
// Truncate the given array of sites to not have more sites than cells.
// This can happen when the user drags a bookmark (or any other new kind
// of link) onto the grid.
let sites = aSites.slice(0, cells.length);
sites.forEach(function (aSite, aIndex) {
let cell = cells[aIndex];
let cellSite = cell.site;
// The site's position didn't change.
if (!aSite || cellSite != aSite) {
let cellNode = cell.node;
// Empty the cell if necessary.
if (cellSite)
cellNode.removeChild(cellSite.node);
// Put the new site in place, if any.
if (aSite)
cellNode.appendChild(aSite.node);
}
}, this);
},
/**
* Rearranges the given sites and slides them to their new positions.
* @param aSites The array of sites to re-arrange.
* @param aCallback The callback to call when finished.
*/
_rearrangeSites: function Updater_rearrangeSites(aSites, aCallback) {
let options = {callback: aCallback, unfreeze: true};
gTransformation.rearrangeSites(aSites, options);
},
/**
* Removes all sites from the grid that are not in the given links array or
* exceed the grid.
* @param aSites The array of sites remaining in the grid.
* @param aCallback The callback to call when finished.
*/
_removeLegacySites: function Updater_removeLegacySites(aSites, aCallback) {
let batch = new Batch(aCallback);
// Delete sites that were removed from the grid.
gGrid.sites.forEach(function (aSite) {
// The site must be valid and not in the current grid.
if (!aSite || aSites.indexOf(aSite) != -1)
return;
batch.push();
// Fade out the to-be-removed site.
gTransformation.hideSite(aSite, function () {
let node = aSite.node;
// Remove the site from the DOM.
node.parentNode.removeChild(node);
batch.pop();
});
});
batch.close();
},
/**
* Tries to fill empty cells with new links if available.
* @param aLinks The array of links.
* @param aCallback The callback to call when finished.
*/
_fillEmptyCells: function Updater_fillEmptyCells(aLinks, aCallback) {
let {cells, sites} = gGrid;
let batch = new Batch(aCallback);
// Find empty cells and fill them.
sites.forEach(function (aSite, aIndex) {
if (aSite || !aLinks[aIndex])
return;
batch.push();
// Create the new site and fade it in.
let site = gGrid.createSite(aLinks[aIndex], cells[aIndex]);
// Set the site's initial opacity to zero.
site.node.style.opacity = 0;
// Without the setTimeout() the node would just appear instead of fade in.
setTimeout(function () {
gTransformation.showSite(site, function () batch.pop());
}, 0);
});
batch.close();
}
};

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

@ -69,7 +69,7 @@
<hbox align="center">
<textbox id="dialog.input" flex="1" type="autocomplete"
completeselectedindex="true"
autocompletesearch="history"
autocompletesearch="urlinline history"
enablehistory="true"
class="uri-element"
oninput="doEnabling();"/>

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

@ -42,17 +42,18 @@
# ***** END LICENSE BLOCK *****
//******** define a js object to implement nsITreeView
function pageInfoTreeView(copycol)
function pageInfoTreeView(treeid, copycol)
{
// copycol is the index number for the column that we want to add to
// the copy-n-paste buffer when the user hits accel-c
this.treeid = treeid;
this.copycol = copycol;
this.rows = 0;
this.tree = null;
this.data = [ ];
this.selection = null;
this.sortcol = null;
this.sortdir = 0;
this.sortcol = -1;
this.sortdir = false;
}
pageInfoTreeView.prototype = {
@ -121,6 +122,25 @@ pageInfoTreeView.prototype = {
}
},
onPageMediaSort : function(columnname)
{
var tree = document.getElementById(this.treeid);
var treecol = tree.columns.getNamedColumn(columnname);
this.sortdir =
gTreeUtils.sort(
tree,
this,
this.data,
treecol.index,
function textComparator(a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); },
this.sortcol,
this.sortdir
);
this.sortcol = treecol.index;
},
getRowProperties: function(row, prop) { },
getCellProperties: function(row, column, prop) { },
getColumnProperties: function(column, prop) { },
@ -166,9 +186,8 @@ const COPYCOL_META_CONTENT = 1;
const COPYCOL_IMAGE = COL_IMAGE_ADDRESS;
// one nsITreeView for each tree in the window
var gMetaView = new pageInfoTreeView(COPYCOL_META_CONTENT);
var gImageView = new pageInfoTreeView(COPYCOL_IMAGE);
var gMetaView = new pageInfoTreeView('metatree', COPYCOL_META_CONTENT);
var gImageView = new pageInfoTreeView('imagetree', COPYCOL_IMAGE);
var atomSvc = Components.classes["@mozilla.org/atom-service;1"]
.getService(Components.interfaces.nsIAtomService);
@ -187,6 +206,44 @@ gImageView.getCellProperties = function(row, col, props) {
props.AppendElement(this._ltrAtom);
};
gImageView.getCellText = function(row, column) {
var value = this.data[row][column.index];
if (column.index == COL_IMAGE_SIZE) {
if (value == -1) {
return gStrings.unknown;
} else {
var kbSize = Number(Math.round(value / 1024 * 100) / 100);
return gBundle.getFormattedString("mediaFileSize", [kbSize]);
}
}
return value || "";
};
gImageView.onPageMediaSort = function(columnname) {
var tree = document.getElementById(this.treeid);
var treecol = tree.columns.getNamedColumn(columnname);
var comparator;
if (treecol.index == COL_IMAGE_SIZE) {
comparator = function numComparator(a, b) { return a - b; };
} else {
comparator = function textComparator(a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); };
}
this.sortdir =
gTreeUtils.sort(
tree,
this,
this.data,
treecol.index,
comparator,
this.sortcol,
this.sortdir
);
this.sortcol = treecol.index;
};
var gImageHash = { };
// localized strings (will be filled in when the document is loaded)
@ -585,15 +642,8 @@ function addImage(url, type, alt, elem, isBg)
catch(ex2) { }
}
var sizeText;
if (cacheEntryDescriptor) {
var pageSize = cacheEntryDescriptor.dataSize;
var kbSize = formatNumber(Math.round(pageSize / 1024 * 100) / 100);
sizeText = gBundle.getFormattedString("mediaFileSize", [kbSize]);
}
else
sizeText = gStrings.unknown;
gImageView.addRow([url, type, sizeText, alt, 1, elem, isBg]);
var dataSize = (cacheEntryDescriptor) ? cacheEntryDescriptor.dataSize : -1;
gImageView.addRow([url, type, dataSize, alt, 1, elem, isBg]);
// Add the observer, only once.
if (gImageView.data.length == 1) {
@ -700,7 +750,10 @@ function getSelectedImage(tree)
return null;
// Only works if only one item is selected
var clickedRow = tree.currentIndex;
var clickedRow = tree.view.selection.currentIndex;
if (clickedRow == -1)
return null;
// image-node
return gImageView.data[clickedRow][COL_IMAGE_NODE];
}

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

@ -66,6 +66,7 @@
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
<script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/>
<script type="application/javascript" src="chrome://global/content/treeUtils.js"/>
<script type="application/javascript" src="chrome://browser/content/pageinfo/pageInfo.js"/>
<script type="application/javascript" src="chrome://browser/content/pageinfo/feeds.js"/>
<script type="application/javascript" src="chrome://browser/content/pageinfo/permissions.js"/>
@ -192,10 +193,12 @@
<tree id="metatree" flex="1" hidecolumnpicker="true" contextmenu="picontext">
<treecols>
<treecol id="meta-name" label="&generalMetaName;"
persist="width" flex="1"/>
persist="width" flex="1"
onclick="gMetaView.onPageMediaSort('meta-name');"/>
<splitter class="tree-splitter"/>
<treecol id="meta-content" label="&generalMetaContent;"
persist="width" flex="4"/>
persist="width" flex="4"
onclick="gMetaView.onPageMediaSort('meta-content');"/>
</treecols>
<treechildren flex="1"/>
</tree>
@ -218,19 +221,24 @@
ondragstart="onBeginLinkDrag(event,'image-address','image-alt')">
<treecols>
<treecol sortSeparators="true" primary="true" persist="width" flex="10"
width="10" id="image-address" label="&mediaAddress;"/>
width="10" id="image-address" label="&mediaAddress;"
onclick="gImageView.onPageMediaSort('image-address');"/>
<splitter class="tree-splitter"/>
<treecol sortSeparators="true" persist="hidden width" flex="2"
width="2" id="image-type" label="&mediaType;"/>
width="2" id="image-type" label="&mediaType;"
onclick="gImageView.onPageMediaSort('image-type');"/>
<splitter class="tree-splitter"/>
<treecol sortSeparators="true" hidden="true" persist="hidden width" flex="2"
width="2" id="image-size" label="&mediaSize;"/>
width="2" id="image-size" label="&mediaSize;" value="size"
onclick="gImageView.onPageMediaSort('image-size');"/>
<splitter class="tree-splitter"/>
<treecol sortSeparators="true" hidden="true" persist="hidden width" flex="4"
width="4" id="image-alt" label="&mediaAltHeader;"/>
width="4" id="image-alt" label="&mediaAltHeader;"
onclick="gImageView.onPageMediaSort('image-alt');"/>
<splitter class="tree-splitter"/>
<treecol sortSeparators="true" hidden="true" persist="hidden width" flex="1"
width="1" id="image-count" label="&mediaCount;"/>
width="1" id="image-count" label="&mediaCount;"
onclick="gImageView.onPageMediaSort('image-count');"/>
</treecols>
<treechildren flex="1"/>
</tree>

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

@ -260,23 +260,24 @@
value="&addDevice.showMeHow.label;"
href="https://services.mozilla.com/sync/help/easy-setup"/>
</description>
<description>&addDevice.setup.enterCode.label;</description>
<label value="&addDevice.setup.enterCode.label;"
control="easySetupPIN1"/>
<spacer flex="1"/>
<vbox align="center" flex="1">
<textbox id="easySetupPIN1"
class="pin"
value=""
disabled="true"
readonly="true"
/>
<textbox id="easySetupPIN2"
class="pin"
value=""
disabled="true"
readonly="true"
/>
<textbox id="easySetupPIN3"
class="pin"
value=""
disabled="true"
readonly="true"
/>
</vbox>
<spacer flex="3"/>

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

@ -632,7 +632,7 @@
autocomplete.unregisterOpenPage(this.mBrowser.registeredOpenURI);
delete this.mBrowser.registeredOpenURI;
}
if (aLocation.spec != "about:blank") {
if (!isBlankPageURL(aLocation.spec)) {
autocomplete.registerOpenPage(aLocation);
this.mBrowser.registeredOpenURI = aLocation;
}
@ -1065,7 +1065,7 @@
}
}
if (title && title != "about:blank") {
if (title && !isBlankPageURL(title)) {
// At this point, we now have a URI.
// Let's try to unescape it using a character set
// in case the URI is not ASCII.
@ -1589,7 +1589,7 @@
aTab.closing = true;
this._removingTabs.push(aTab);
if (newTab)
this.addTab("about:blank", {skipAnimation: true});
this.addTab(BROWSER_NEW_TAB_URL, {skipAnimation: true});
else
this.tabContainer.updateVisibility();
@ -2375,10 +2375,6 @@
onget="return this.mCurrentBrowser.contentViewerFile;"
readonly="true"/>
<property name="documentCharsetInfo"
onget="return this.mCurrentBrowser.documentCharsetInfo;"
readonly="true"/>
<property name="contentDocument"
onget="return this.mCurrentBrowser.contentDocument;"
readonly="true"/>
@ -3811,49 +3807,34 @@
<binding id="tabbrowser-alltabs-popup"
extends="chrome://global/content/bindings/popup.xml#popup">
<implementation implements="nsIDOMEventListener">
<method name="_menuItemOnCommand">
<parameter name="aEvent"/>
<body><![CDATA[
gBrowser.selectedTab = aEvent.target.tab;
]]></body>
</method>
<method name="_tabOnAttrModified">
<parameter name="aEvent"/>
<body><![CDATA[
var tab = aEvent.target;
this._setMenuitemAttributes(tab.mCorrespondingMenuitem, tab);
if (tab.mCorrespondingMenuitem)
this._setMenuitemAttributes(tab.mCorrespondingMenuitem, tab);
]]></body>
</method>
<method name="_tabOnTabClose">
<parameter name="aEvent"/>
<body><![CDATA[
var menuItem = aEvent.target.mCorrespondingMenuitem;
if (menuItem)
this.removeChild(menuItem);
var tab = aEvent.target;
if (tab.mCorrespondingMenuitem)
this.removeChild(tab.mCorrespondingMenuitem);
]]></body>
</method>
<method name="handleEvent">
<parameter name="aEvent"/>
<body><![CDATA[
if (!aEvent.isTrusted)
return;
switch (aEvent.type) {
case "command":
this._menuItemOnCommand(aEvent);
break;
case "TabAttrModified":
this._tabOnAttrModified(aEvent);
break;
case "TabClose":
this._tabOnTabClose(aEvent);
break;
case "TabOpen":
this._createTabMenuItem(aEvent.originalTarget);
break;
case "scroll":
this._updateTabsVisibilityStatus();
break;
@ -3874,8 +3855,6 @@
if (!curTab) // "Tab Groups" menuitem and its menuseparator
continue;
let curTabBO = curTab.boxObject;
if (!curTabBO) // "Tabs From Other Computers" menuitem
continue;
if (curTabBO.screenX >= tabstripBO.screenX &&
curTabBO.screenX + curTabBO.width <= tabstripBO.screenX + tabstripBO.width)
this.childNodes[i].setAttribute("tabIsVisible", "true");
@ -3896,14 +3875,10 @@
this._setMenuitemAttributes(menuItem, aTab);
// Keep some attributes of the menuitem in sync with its
// corresponding tab (e.g. the tab label)
aTab.mCorrespondingMenuitem = menuItem;
menuItem.tab = aTab;
menuItem.addEventListener("command", this, false);
this.appendChild(menuItem);
return menuItem;
]]></body>
</method>
@ -3938,18 +3913,17 @@
<handlers>
<handler event="popupshowing">
<![CDATA[
// set up the menu popup
var tabcontainer = gBrowser.tabContainer;
let tabs = gBrowser.visibleTabs;
// Listen for changes in the tab bar.
tabcontainer.addEventListener("TabOpen", this, false);
tabcontainer.addEventListener("TabAttrModified", this, false);
tabcontainer.addEventListener("TabClose", this, false);
tabcontainer.mTabstrip.addEventListener("scroll", this, false);
let tabs = gBrowser.visibleTabs;
for (var i = 0; i < tabs.length; i++) {
this._createTabMenuItem(tabs[i]);
if (!tabs[i].pinned)
this._createTabMenuItem(tabs[i]);
}
this._updateTabsVisibilityStatus();
]]></handler>
@ -3960,14 +3934,12 @@
for (let i = this.childNodes.length - 1; i > 0; i--) {
let menuItem = this.childNodes[i];
if (menuItem.tab) {
menuItem.removeEventListener("command", this, false);
menuItem.tab.mCorrespondingMenuitem = null;
this.removeChild(menuItem);
}
}
var tabcontainer = gBrowser.tabContainer;
tabcontainer.mTabstrip.removeEventListener("scroll", this, false);
tabcontainer.removeEventListener("TabOpen", this, false);
tabcontainer.removeEventListener("TabAttrModified", this, false);
tabcontainer.removeEventListener("TabClose", this, false);
]]></handler>
@ -3988,6 +3960,11 @@
XULBrowserWindow.setOverLink("", null);
]]></handler>
<handler event="command"><![CDATA[
if (event.target.tab)
gBrowser.selectedTab = event.target.tab;
]]></handler>
</handlers>
</binding>

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

@ -40,6 +40,10 @@ srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = browser/base/content/test
DIRS += \
newtab \
$(NULL)
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
@ -83,7 +87,7 @@ endif
# browser_sanitize-download-history.js is bug 432425
#
# browser_sanitizeDialog_treeView.js is disabled until the tree view is added
# back to the clear recent history dialog (santize.xul), if it ever is (bug
# back to the clear recent history dialog (sanitize.xul), if it ever is (bug
# 480169)
# browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
@ -91,6 +95,7 @@ endif
# browser_bug321000.js is disabled because newline handling is shaky (bug 592528)
_BROWSER_FILES = \
head.js \
browser_typeAheadFind.js \
browser_keywordSearch.js \
browser_allTabsPanel.js \
@ -145,6 +150,7 @@ _BROWSER_FILES = \
browser_bug567306.js \
browser_zbug569342.js \
browser_bug575561.js \
browser_bug575830.js \
browser_bug577121.js \
browser_bug578534.js \
browser_bug579872.js \
@ -172,6 +178,7 @@ _BROWSER_FILES = \
browser_bug655584.js \
browser_bug664672.js \
browser_bug710878.js \
browser_bug719271.js \
browser_canonizeURL.js \
browser_findbarClose.js \
browser_keywordBookmarklets.js \
@ -213,6 +220,7 @@ _BROWSER_FILES = \
browser_tabfocus.js \
browser_tabs_isActive.js \
browser_tabs_owner.js \
browser_urlbarAutoFillTrimURLs.js \
browser_urlbarCopying.js \
browser_urlbarEnter.js \
browser_urlbarTrimURLs.js \
@ -228,6 +236,7 @@ _BROWSER_FILES = \
discovery.html \
domplate_test.js \
moz.png \
video.ogg \
test_bug435035.html \
test_bug462673.html \
page_style_sample.html \

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

@ -11,16 +11,16 @@ function test () {
is(tooltip.getAttribute("label"), "This is a non-root SVG element title");
ok(FillInHTMLTooltip(doc.getElementById("text1"), "should get title"));
is(tooltip.getAttribute("label"), " This is a title ");
is(tooltip.getAttribute("label"), "\n\n\n This is a title\n\n ");
ok(!FillInHTMLTooltip(doc.getElementById("text2"), "should not get title"));
ok(!FillInHTMLTooltip(doc.getElementById("text3"), "should not get title"));
ok(FillInHTMLTooltip(doc.getElementById("link1"), "should get title"));
is(tooltip.getAttribute("label"), " This is a title ");
is(tooltip.getAttribute("label"), "\n This is a title\n ");
ok(FillInHTMLTooltip(doc.getElementById("text4"), "should get title"));
is(tooltip.getAttribute("label"), " This is a title ");
is(tooltip.getAttribute("label"), "\n This is a title\n ");
ok(!FillInHTMLTooltip(doc.getElementById("link2"), "should not get title"));

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

@ -54,12 +54,10 @@ function thirdPageLoaded() {
function imageLoaded() {
zoomTest(gTab1, 1, "Zoom should be 1 when image was loaded in the background");
afterZoom(function() {
zoomTest(gTab1, 1, "Zoom should still be 1 when tab with image is selected");
executeSoon(imageZoomSwitch);
});
gBrowser.selectedTab = gTab1;
zoomTest(gTab1, 1, "Zoom should still be 1 when tab with image is selected");
executeSoon(imageZoomSwitch);
}
function imageZoomSwitch() {
@ -136,12 +134,10 @@ function navigate(direction, cb) {
}
function afterZoom(cb) {
let oldAPTS = FullZoom._applyPrefToSetting;
FullZoom._applyPrefToSetting = function(value, browser) {
if (!value)
value = undefined;
oldAPTS.call(FullZoom, value, browser);
FullZoom._applyPrefToSetting = oldAPTS;
let oldSZFB = ZoomManager.setZoomForBrowser;
ZoomManager.setZoomForBrowser = function(browser, value) {
oldSZFB.call(ZoomManager, browser, value);
ZoomManager.setZoomForBrowser = oldSZFB;
executeSoon(cb);
};
}

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

@ -43,19 +43,18 @@ function test() {
}
function afterZoomAndLoad(cb) {
let didLoad = didZoom = false;
let didLoad = false;
let didZoom = false;
tabElm.linkedBrowser.addEventListener("load", function() {
tabElm.linkedBrowser.removeEventListener("load", arguments.callee, true);
didLoad = true;
if (didZoom)
executeSoon(cb);
}, true);
let oldAPTS = FullZoom._applyPrefToSetting;
FullZoom._applyPrefToSetting = function(value, browser) {
if (!value)
value = undefined;
oldAPTS.call(FullZoom, value, browser);
FullZoom._applyPrefToSetting = oldAPTS;
let oldSZFB = ZoomManager.setZoomForBrowser;
ZoomManager.setZoomForBrowser = function(browser, value) {
oldSZFB.call(ZoomManager, browser, value);
ZoomManager.setZoomForBrowser = oldSZFB;
didZoom = true;
if (didLoad)
executeSoon(cb);

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

@ -37,7 +37,8 @@ const TEST_PAGE = "/browser/browser/base/content/test/dummy_page.html";
var gTestTab, gBgTab, gTestZoom;
function afterZoomAndLoad(aCallback, aTab) {
let didLoad = didZoom = false;
let didLoad = false;
let didZoom = false;
aTab.linkedBrowser.addEventListener("load", function() {
aTab.linkedBrowser.removeEventListener("load", arguments.callee, true);
didLoad = true;

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

@ -0,0 +1,37 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
function test() {
let tab1, tab2;
const TEST_IMAGE = "http://example.org/browser/browser/base/content/test/moz.png";
waitForExplicitFinish();
registerCleanupFunction(function cleanup() {
gBrowser.removeTab(tab1);
gBrowser.removeTab(tab2);
});
tab1 = gBrowser.addTab(TEST_IMAGE);
tab2 = gBrowser.addTab();
gBrowser.selectedTab = tab1;
tab1.linkedBrowser.addEventListener("load", function onload() {
tab1.linkedBrowser.removeEventListener("load", onload, true);
is(ZoomManager.zoom, 1, "initial zoom level for first should be 1");
FullZoom.enlarge();
let zoom = ZoomManager.zoom;
isnot(zoom, 1, "zoom level should have changed");
gBrowser.selectedTab = tab2;
is(ZoomManager.zoom, 1, "initial zoom level for second tab should be 1");
gBrowser.selectedTab = tab1;
is(ZoomManager.zoom, zoom, "zoom level for first tab should not have changed");
finish();
}, true);
}

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

@ -4,9 +4,7 @@ function numClosedTabs()
getClosedTabCount(window);
function isUndoCloseEnabled() {
document.popupNode = gBrowser.tabs[0];
TabContextMenu.updateContextMenu(document.getElementById("tabContextMenu"));
TabContextMenu.contextTab = null;
updateTabContextMenu();
return !document.getElementById("context_undoCloseTab").disabled;
}

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

@ -4,7 +4,9 @@
const TESTROOT = "http://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/";
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm");
var tempScope = {};
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", tempScope);
var LightweightThemeManager = tempScope.LightweightThemeManager;
function wait_for_notification(aCallback) {
PopupNotifications.panel.addEventListener("popupshown", function() {

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

@ -43,6 +43,8 @@ https://example.com/browser/browser/base/content/test/redirect_bug623155.sjs#FG
*/
var gNewTab;
function test() {
waitForExplicitFinish();

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

@ -0,0 +1,141 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const TEST_PAGE = "http://example.org/browser/browser/base/content/test/zoom_test.html";
const TEST_VIDEO = "http://example.org/browser/browser/base/content/test/video.ogg";
var gTab1, gTab2, gLevel1, gLevel2;
function test() {
waitForExplicitFinish();
gTab1 = gBrowser.addTab();
gTab2 = gBrowser.addTab();
gBrowser.selectedTab = gTab1;
load(gTab1, TEST_PAGE, function() {
load(gTab2, TEST_VIDEO, zoomTab1);
});
}
function zoomTab1() {
is(gBrowser.selectedTab, gTab1, "Tab 1 is selected");
zoomTest(gTab1, 1, "Initial zoom of tab 1 should be 1");
zoomTest(gTab2, 1, "Initial zoom of tab 2 should be 1");
FullZoom.enlarge();
gLevel1 = ZoomManager.getZoomForBrowser(gBrowser.getBrowserForTab(gTab1));
ok(gLevel1 > 1, "New zoom for tab 1 should be greater than 1");
zoomTest(gTab2, 1, "Zooming tab 1 should not affect tab 2");
gBrowser.selectedTab = gTab2;
zoomTest(gTab2, 1, "Tab 2 is still unzoomed after it is selected");
zoomTest(gTab1, gLevel1, "Tab 1 is still zoomed");
zoomTab2();
}
function zoomTab2() {
is(gBrowser.selectedTab, gTab2, "Tab 2 is selected");
FullZoom.reduce();
let gLevel2 = ZoomManager.getZoomForBrowser(gBrowser.getBrowserForTab(gTab2));
ok(gLevel2 < 1, "New zoom for tab 2 should be less than 1");
zoomTest(gTab1, gLevel1, "Zooming tab 2 should not affect tab 1");
afterZoom(function() {
zoomTest(gTab1, gLevel1, "Tab 1 should have the same zoom after it's selected");
testNavigation();
});
gBrowser.selectedTab = gTab1;
}
function testNavigation() {
load(gTab1, TEST_VIDEO, function() {
zoomTest(gTab1, 1, "Zoom should be 1 when a video was loaded");
navigate(BACK, function() {
zoomTest(gTab1, gLevel1, "Zoom should be restored when a page is loaded");
navigate(FORWARD, function() {
zoomTest(gTab1, 1, "Zoom should be 1 again when navigating back to a video");
finishTest();
});
});
});
}
var finishTestStarted = false;
function finishTest() {
ok(!finishTestStarted, "finishTest called more than once");
finishTestStarted = true;
gBrowser.selectedTab = gTab1;
FullZoom.reset();
gBrowser.removeTab(gTab1);
gBrowser.selectedTab = gTab2;
FullZoom.reset();
gBrowser.removeTab(gTab2);
finish();
}
function zoomTest(tab, val, msg) {
is(ZoomManager.getZoomForBrowser(tab.linkedBrowser), val, msg);
}
function load(tab, url, cb) {
let didLoad = false;
let didZoom = false;
tab.linkedBrowser.addEventListener("load", function onload(event) {
event.currentTarget.removeEventListener("load", onload, true);
didLoad = true;
if (didZoom)
executeSoon(cb);
}, true);
afterZoom(function() {
didZoom = true;
if (didLoad)
executeSoon(cb);
});
tab.linkedBrowser.loadURI(url);
}
const BACK = 0;
const FORWARD = 1;
function navigate(direction, cb) {
let didPs = false;
let didZoom = false;
gBrowser.addEventListener("pageshow", function onpageshow(event) {
gBrowser.removeEventListener("pageshow", onpageshow, true);
didPs = true;
if (didZoom)
executeSoon(cb);
}, true);
afterZoom(function() {
didZoom = true;
if (didPs)
executeSoon(cb);
});
if (direction == BACK)
gBrowser.goBack();
else if (direction == FORWARD)
gBrowser.goForward();
}
function afterZoom(cb) {
let oldSZFB = ZoomManager.setZoomForBrowser;
ZoomManager.setZoomForBrowser = function(browser, value) {
oldSZFB.call(ZoomManager, browser, value);
ZoomManager.setZoomForBrowser = oldSZFB;
executeSoon(cb);
};
}

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

@ -7,8 +7,10 @@
const testURL1 = "http://mochi.test:8888/browser/browser/base/content/test/browser_clearplugindata.html";
const testURL2 = "http://mochi.test:8888/browser/browser/base/content/test/browser_clearplugindata_noage.html";
let tempScope = {};
Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://browser/content/sanitize.js");
.loadSubScript("chrome://browser/content/sanitize.js", tempScope);
let Sanitizer = tempScope.Sanitizer;
const pluginHostIface = Ci.nsIPluginHost;
var pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);

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

@ -104,7 +104,6 @@ function end_test() {
function test_url(aURL, aCanHide, aNextTest) {
is_chrome_visible();
info("Page load");
load_page(aURL, aCanHide, function() {
info("Switch away");
@ -163,5 +162,30 @@ function run_http_test_2() {
// Should not hide the chrome
function run_chrome_about_test_2() {
info("Chrome about: tests");
test_url("about:addons", true, end_test);
test_url("about:addons", true, run_http_test3);
}
function run_http_test3() {
info("HTTP tests");
test_url(HTTPSRC + "disablechrome.html", false, run_chrome_about_test_3);
}
// Should not hide the chrome
function run_chrome_about_test_3() {
info("Chrome about: tests");
test_url("about:Addons", true, function(){
info("Tabs on top");
TabsOnTop.enabled = true;
run_http_test4();
});
}
function run_http_test4() {
info("HTTP tests");
test_url(HTTPSRC + "disablechrome.html", false, run_chrome_about_test_4);
}
function run_chrome_about_test_4() {
info("Chrome about: tests");
test_url("about:Addons", true, end_test);
}

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

@ -383,7 +383,7 @@ function test_latchedGesture(gesture, inc, dec, eventPrefix)
// Restore the gesture to its original configuration.
gPrefService.setBoolPref(branch + "latched", oldLatchedValue);
for (dir in cmd)
for (let dir in cmd)
test_removeCommand(cmd[dir]);
}

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

@ -68,7 +68,7 @@ var tests = [
},
]
let gCurrentTest, gCurrentTestIndex = -1;
let gCurrentTest, gCurrentTestIndex = -1, gTestDesc;
// Go through the tests in both directions, to add additional coverage for
// transitions between different states.
let gForward = true;

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

@ -1,8 +1,10 @@
// Bug 474792 - Clear "Never remember passwords for this site" when
// clearing site-specific settings in Clear Recent History dialog
let tempScope = {};
Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://browser/content/sanitize.js");
.loadSubScript("chrome://browser/content/sanitize.js", tempScope);
let Sanitizer = tempScope.Sanitizer;
function test() {

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

@ -1,7 +1,9 @@
// Bug 380852 - Delete permission manager entries in Clear Recent History
let tempScope = {};
Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://browser/content/sanitize.js");
.loadSubScript("chrome://browser/content/sanitize.js", tempScope);
let Sanitizer = tempScope.Sanitizer;
function test() {

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

@ -5,8 +5,10 @@ const dm = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManage
const bhist = Cc["@mozilla.org/browser/global-history;2"].getService(Ci.nsIBrowserHistory);
const formhist = Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2);
let tempScope = {};
Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://browser/content/sanitize.js");
.loadSubScript("chrome://browser/content/sanitize.js", tempScope);
let Sanitizer = tempScope.Sanitizer;
function test() {

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

@ -50,9 +50,10 @@
* browser/base/content/test/browser_sanitize-timespans.js.
*/
Cc["@mozilla.org/moz/jssubscript-loader;1"].
getService(Ci.mozIJSSubScriptLoader).
loadSubScript("chrome://browser/content/sanitize.js");
let tempScope = {};
Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://browser/content/sanitize.js", tempScope);
let Sanitizer = tempScope.Sanitizer;
const dm = Cc["@mozilla.org/download-manager;1"].
getService(Ci.nsIDownloadManager);

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

@ -0,0 +1,85 @@
/* This Source Code is subject to the terms of the Mozilla Public License
* version 2.0 (the "License"). You can obtain a copy of the License at
* http://mozilla.org/MPL/2.0/. */
// This test ensures that autoFilled values are not trimmed, unless the user
// selects from the autocomplete popup.
function test() {
waitForExplicitFinish();
const PREF_TRIMURL = "browser.urlbar.trimURLs";
const PREF_AUTOFILL = "browser.urlbar.autoFill";
registerCleanupFunction(function () {
Services.prefs.clearUserPref(PREF_TRIMURL);
Services.prefs.clearUserPref(PREF_AUTOFILL);
URLBarSetURI();
});
Services.prefs.setBoolPref(PREF_TRIMURL, true);
Services.prefs.setBoolPref(PREF_AUTOFILL, true);
// Adding a tab would hit switch-to-tab, so it's safer to just add a visit.
let callback = {
handleError: function () {},
handleResult: function () {},
handleCompletion: continue_test
};
let history = Cc["@mozilla.org/browser/history;1"]
.getService(Ci.mozIAsyncHistory);
history.updatePlaces({ uri: NetUtil.newURI("http://www.autofilltrimurl.com/")
, visits: [ { transitionType: Ci.nsINavHistoryService.TRANSITION_TYPED
, visitDate: Date.now() * 1000
} ]
}, callback);
}
function continue_test() {
function test_autoFill(aTyped, aExpected, aCallback) {
gURLBar.inputField.value = aTyped.substr(0, aTyped.length - 1);
gURLBar.focus();
gURLBar.selectionStart = aTyped.length - 1;
gURLBar.selectionEnd = aTyped.length - 1;
EventUtils.synthesizeKey(aTyped.substr(-1), {});
is(gURLBar.value, aExpected, "trim was applied correctly");
aCallback();
}
test_autoFill("http://", "http://", function () {
test_autoFill("http://a", "http://autofilltrimurl.com/", function () {
test_autoFill("http://www.autofilltrimurl.com", "http://www.autofilltrimurl.com/", function () {
// Now ensure selecting from the popup correctly trims.
waitForSearchComplete(function () {
EventUtils.synthesizeKey("VK_DOWN", {});
is(gURLBar.value, "www.autofilltrimurl.com", "trim was applied correctly");
gURLBar.closePopup();
waitForClearHistory(finish);
});
});
});
});
}
function waitForClearHistory(aCallback) {
Services.obs.addObserver(function observeCH(aSubject, aTopic, aData) {
Services.obs.removeObserver(observeCH, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
aCallback();
}, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
PlacesUtils.bhistory.removeAllPages();
}
function waitForSearchComplete(aCallback) {
info("Waiting for onSearchComplete");
let onSearchComplete = gURLBar.onSearchComplete;
registerCleanupFunction(function () {
gURLBar.onSearchComplete = onSearchComplete;
});
gURLBar.onSearchComplete = function () {
ok(gURLBar.popupOpen, "The autocomplete popup is correctly open");
is(gURLBar.controller.matchCount, 1, "Found the expected number of matches")
onSearchComplete.apply(gURLBar);
aCallback();
}
}

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

@ -89,15 +89,11 @@ function test() {
}
function Disabled() {
document.popupNode = gBrowser.selectedTab;
TabContextMenu.updateContextMenu(document.getElementById("tabContextMenu"));
TabContextMenu.contextTab = null;
updateTabContextMenu();
return document.getElementById("Browser:BookmarkAllTabs").getAttribute("disabled") == "true";
}
function Hidden() {
document.popupNode = gBrowser.selectedTab;
TabContextMenu.updateContextMenu(document.getElementById("tabContextMenu"));
TabContextMenu.contextTab = null;
updateTabContextMenu();
return document.getElementById("context_bookmarkAllTabs").hidden;
}

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

@ -43,7 +43,7 @@ function test() {
is(gBrowser.visibleTabs.length, 2, "there are now two visible tabs");
// Check the context menu with two tabs
popup(origTab);
updateTabContextMenu(origTab);
is(document.getElementById("context_closeTab").disabled, false, "Close Tab is enabled");
is(document.getElementById("context_reloadAllTabs").disabled, false, "Reload All Tabs is enabled");
@ -53,7 +53,7 @@ function test() {
is(gBrowser.visibleTabs.length, 1, "now there is only one visible tab");
// Check the context menu with one tab.
popup(testTab);
updateTabContextMenu(testTab);
is(document.getElementById("context_closeTab").disabled, false, "Close Tab is enabled when more than one tab exists");
is(document.getElementById("context_reloadAllTabs").disabled, true, "Reload All Tabs is disabled");
@ -64,7 +64,7 @@ function test() {
is(gBrowser.visibleTabs.length, 2, "now there are two visible tabs");
// Check the context menu on the unpinned visible tab
popup(testTab);
updateTabContextMenu(testTab);
is(document.getElementById("context_closeOtherTabs").disabled, true, "Close Other Tabs is disabled");
// Show all tabs
@ -72,16 +72,9 @@ function test() {
gBrowser.showOnlyTheseTabs(allTabs);
// Check the context menu now
popup(testTab);
updateTabContextMenu(testTab);
is(document.getElementById("context_closeOtherTabs").disabled, false, "Close Other Tabs is enabled");
gBrowser.removeTab(testTab);
gBrowser.removeTab(pinned);
}
function popup(tab) {
document.popupNode = tab;
TabContextMenu.updateContextMenu(document.getElementById("tabContextMenu"));
is(TabContextMenu.contextTab, tab, "TabContextMenu context is the expected tab");
TabContextMenu.contextTab = null;
}

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

@ -0,0 +1,8 @@
function updateTabContextMenu(tab) {
let menu = document.getElementById("tabContextMenu");
if (!tab)
tab = gBrowser.selectedTab;
menu.openPopup(tab, "end_after", 0, 0, true, false, {target: tab});
is(TabContextMenu.contextTab, tab, "TabContextMenu context is the expected tab");
menu.hidePopup();
}

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