зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central into services-central
This commit is contained in:
Коммит
2df88561d9
|
@ -32,6 +32,10 @@ SHARED_LIBRARY_LIBS = \
|
|||
../src/xforms/$(LIB_PREFIX)accessibility_xforms_s.$(LIB_SUFFIX) \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
|
||||
SHARED_LIBRARY_LIBS += ../src/windows/uia/$(LIB_PREFIX)accessibility_toolkit_uia_s.$(LIB_SUFFIX)
|
||||
endif
|
||||
|
||||
ifdef MOZ_XUL
|
||||
SHARED_LIBRARY_LIBS += ../src/xul/$(LIB_PREFIX)accessibility_xul_s.$(LIB_SUFFIX)
|
||||
endif
|
||||
|
|
|
@ -62,8 +62,8 @@ interface nsIAccessibleProvider : nsISupports
|
|||
const long XULTab = 0x00001017;
|
||||
/** Used for XUL tabs element, a container for tab elements */
|
||||
const long XULTabs = 0x00001018;
|
||||
/** Used for XUL tabpanels container element */
|
||||
const long XULTabpanels = 0x00001019;
|
||||
/** Used for XUL deck frame */
|
||||
const long XULDeck = 0x00001019;
|
||||
|
||||
const long XULText = 0x0000101A;
|
||||
const long XULTextBox = 0x0000101B;
|
||||
|
|
|
@ -14,7 +14,10 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
|
|||
PLATFORM_DIR = atk
|
||||
else
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
|
||||
PLATFORM_DIR = msaa
|
||||
PLATFORM_DIR = \
|
||||
msaa \
|
||||
windows \
|
||||
$(null)
|
||||
else
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
|
||||
PLATFORM_DIR += mac
|
||||
|
|
|
@ -1153,11 +1153,14 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
|||
}
|
||||
|
||||
if (!newAcc) {
|
||||
// Create generic accessibles for SVG and MathML nodes.
|
||||
if (content->IsSVG(nsGkAtoms::svg)) {
|
||||
// xul:deck does not have XBL and nsIFrame::CreateAccessible() is only called
|
||||
// on HTML elements
|
||||
nsIAtom* tag = content->Tag();
|
||||
if ((tag == nsGkAtoms::deck) || (tag == nsGkAtoms::tabpanels)) {
|
||||
newAcc = new XULDeckAccessible(content, docAcc);
|
||||
} else if (content->IsSVG(nsGkAtoms::svg)) {
|
||||
newAcc = new EnumRoleAccessible(content, docAcc, roles::DIAGRAM);
|
||||
}
|
||||
else if (content->IsMathML(nsGkAtoms::math)) {
|
||||
} else if (content->IsMathML(nsGkAtoms::math)) {
|
||||
newAcc = new EnumRoleAccessible(content, docAcc, roles::EQUATION);
|
||||
}
|
||||
}
|
||||
|
@ -1326,6 +1329,10 @@ nsAccessibilityService::CreateAccessibleByType(nsIContent* aContent,
|
|||
accessible = new XULComboboxAccessible(aContent, aDoc);
|
||||
break;
|
||||
|
||||
case nsIAccessibleProvider::XULDeck:
|
||||
accessible = new XULDeckAccessible(aContent, aDoc);
|
||||
break;
|
||||
|
||||
case nsIAccessibleProvider::XULDropmarker:
|
||||
accessible = new XULDropmarkerAccessible(aContent, aDoc);
|
||||
break;
|
||||
|
@ -1430,10 +1437,6 @@ nsAccessibilityService::CreateAccessibleByType(nsIContent* aContent,
|
|||
accessible = new XULTabsAccessible(aContent, aDoc);
|
||||
break;
|
||||
|
||||
case nsIAccessibleProvider::XULTabpanels:
|
||||
accessible = new XULTabpanelsAccessible(aContent, aDoc);
|
||||
break;
|
||||
|
||||
case nsIAccessibleProvider::XULText:
|
||||
accessible = new XULLabelAccessible(aContent, aDoc);
|
||||
break;
|
||||
|
|
|
@ -508,6 +508,8 @@ public:
|
|||
inline bool IsXULTree() const { return mFlags & eXULTreeAccessible; }
|
||||
mozilla::a11y::XULTreeAccessible* AsXULTree();
|
||||
|
||||
inline bool IsXULDeck() const { return mFlags & eXULDeckAccessible; }
|
||||
|
||||
inline bool IsListControl() const { return mFlags & eListControlAccessible; }
|
||||
|
||||
inline bool IsMenuButton() const { return mFlags & eMenuButtonAccessible; }
|
||||
|
@ -766,7 +768,8 @@ protected:
|
|||
eMenuPopupAccessible = 1 << 16,
|
||||
eRootAccessible = 1 << 17,
|
||||
eTextLeafAccessible = 1 << 18,
|
||||
eXULTreeAccessible = 1 << 19
|
||||
eXULDeckAccessible = 1 << 19,
|
||||
eXULTreeAccessible = 1 << 20
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -59,6 +59,9 @@ AccessibleWrap::GetNativeType ()
|
|||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if (IsXULDeck())
|
||||
return [mozPaneAccessible class];
|
||||
|
||||
roles::Role role = Role();
|
||||
switch (role) {
|
||||
case roles::PUSHBUTTON:
|
||||
|
@ -81,15 +84,17 @@ AccessibleWrap::GetNativeType ()
|
|||
|
||||
case roles::PAGETABLIST:
|
||||
return [mozTabsAccessible class];
|
||||
|
||||
|
||||
case roles::ENTRY:
|
||||
case roles::STATICTEXT:
|
||||
case roles::CAPTION:
|
||||
case roles::ACCEL_LABEL:
|
||||
case roles::TEXT_LEAF:
|
||||
case roles::PASSWORD_TEXT:
|
||||
// normal textfield (static or editable)
|
||||
return [mozTextAccessible class];
|
||||
return [mozTextAccessible class];
|
||||
|
||||
case roles::TEXT_LEAF:
|
||||
return [mozTextLeafAccessible class];
|
||||
|
||||
case roles::LINK:
|
||||
return [mozLinkAccessible class];
|
||||
|
|
|
@ -14,8 +14,6 @@ LIBRARY_NAME = accessibility_toolkit_s
|
|||
EXPORT_LIBRARY = ..
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
||||
|
||||
|
||||
CMMSRCS = \
|
||||
AccessibleWrap.mm \
|
||||
ApplicationAccessibleWrap.mm \
|
||||
|
@ -48,5 +46,7 @@ LOCAL_INCLUDES += \
|
|||
-I$(srcdir)/../xul \
|
||||
-I$(topsrcdir)/widget/cocoa \
|
||||
-I$(topsrcdir)/widget/xpwidgets \
|
||||
-I$(topsrcdir)/layout/xul/base/src \
|
||||
-I$(topsrcdir)/layout/generic \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -23,6 +23,14 @@ GetObjectOrRepresentedView(id <mozAccessible> aObject)
|
|||
return [aObject hasRepresentedView] ? [aObject representedView] : aObject;
|
||||
}
|
||||
|
||||
inline mozAccessible*
|
||||
GetNativeFromGeckoAccessible(nsIAccessible* aAccessible)
|
||||
{
|
||||
mozAccessible* native = nil;
|
||||
aAccessible->GetNativeInterface((void**)&native);
|
||||
return native;
|
||||
}
|
||||
|
||||
@interface mozAccessible : NSObject <mozAccessible>
|
||||
{
|
||||
/**
|
||||
|
@ -39,15 +47,7 @@ GetObjectOrRepresentedView(id <mozAccessible> aObject)
|
|||
* Weak reference to the parent
|
||||
*/
|
||||
mozAccessible* mParent;
|
||||
|
||||
/**
|
||||
* We can be marked as 'expired' if Shutdown() is called on our geckoAccessible.
|
||||
* since we might still be retained by some third-party, we need to do cleanup
|
||||
* in |expire|, and prevent any potential harm that could come from someone using us
|
||||
* after this point.
|
||||
*/
|
||||
BOOL mIsExpired;
|
||||
|
||||
|
||||
/**
|
||||
* The nsIAccessible role of our gecko accessible.
|
||||
*/
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#import "mozView.h"
|
||||
|
||||
#include "Accessible-inl.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsIAccessibleRelation.h"
|
||||
#include "nsIAccessibleText.h"
|
||||
#include "nsIAccessibleEditableText.h"
|
||||
|
@ -21,6 +22,7 @@
|
|||
#include "nsCocoaUtils.h"
|
||||
#include "nsCoord.h"
|
||||
#include "nsObjCExceptions.h"
|
||||
#include "nsWhitespaceTokenizer.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
@ -63,18 +65,6 @@ GetClosestInterestingAccessible(id anObject)
|
|||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
static inline mozAccessible*
|
||||
GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSNULL;
|
||||
|
||||
mozAccessible *native = nil;
|
||||
anAccessible->GetNativeInterface ((void**)&native);
|
||||
return native;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation mozAccessible
|
||||
|
@ -85,7 +75,6 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
|
||||
if ((self = [super init])) {
|
||||
mGeckoAccessible = geckoAccessible;
|
||||
mIsExpired = NO;
|
||||
mRole = geckoAccessible->Role();
|
||||
}
|
||||
|
||||
|
@ -112,7 +101,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
|
||||
// unknown (either unimplemented, or irrelevant) elements are marked as ignored
|
||||
// as well as expired elements.
|
||||
return mIsExpired || [[self role] isEqualToString:NSAccessibilityUnknownRole];
|
||||
return !mGeckoAccessible || [[self role] isEqualToString:NSAccessibilityUnknownRole];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
|
||||
}
|
||||
|
@ -122,7 +111,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
// if we're expired, we don't support any attributes.
|
||||
if (mIsExpired)
|
||||
if (!mGeckoAccessible)
|
||||
return [NSArray array];
|
||||
|
||||
static NSArray *generalAttributes = nil;
|
||||
|
@ -160,7 +149,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if (mIsExpired)
|
||||
if (!mGeckoAccessible)
|
||||
return nil;
|
||||
|
||||
#if DEBUG
|
||||
|
@ -246,7 +235,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
|
||||
- (id)accessibilityHitTest:(NSPoint)point
|
||||
{
|
||||
if (mIsExpired)
|
||||
if (!mGeckoAccessible)
|
||||
return nil;
|
||||
|
||||
// Convert from cocoa's coordinate system to gecko's. According to the docs
|
||||
|
@ -288,7 +277,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
|
||||
- (id)accessibilityFocusedUIElement
|
||||
{
|
||||
if (mIsExpired)
|
||||
if (!mGeckoAccessible)
|
||||
return nil;
|
||||
|
||||
Accessible* focusedGeckoChild = mGeckoAccessible->FocusedChild();
|
||||
|
@ -420,7 +409,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
|
||||
- (NSString*)role
|
||||
{
|
||||
if (mIsExpired)
|
||||
if (!mGeckoAccessible)
|
||||
return nil;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -444,6 +433,42 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
|
||||
- (NSString*)subrole
|
||||
{
|
||||
if (!mGeckoAccessible)
|
||||
return nil;
|
||||
|
||||
// XXX maybe we should cache the subrole.
|
||||
nsAutoString xmlRoles;
|
||||
nsCOMPtr<nsIPersistentProperties> attributes;
|
||||
|
||||
// XXX we don't need all the attributes (see bug 771113)
|
||||
nsresult rv = mGeckoAccessible->GetAttributes(getter_AddRefs(attributes));
|
||||
if (NS_SUCCEEDED(rv) && attributes)
|
||||
nsAccUtils::GetAccAttr(attributes, nsGkAtoms::xmlroles, xmlRoles);
|
||||
|
||||
nsWhitespaceTokenizer tokenizer(xmlRoles);
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
const nsDependentSubstring token(tokenizer.nextToken());
|
||||
|
||||
if (token.EqualsLiteral("banner"))
|
||||
return @"AXLandmarkBanner";
|
||||
|
||||
if (token.EqualsLiteral("complementary"))
|
||||
return @"AXLandmarkComplementary";
|
||||
|
||||
if (token.EqualsLiteral("contentinfo"))
|
||||
return @"AXLandmarkContentInfo";
|
||||
|
||||
if (token.EqualsLiteral("main"))
|
||||
return @"AXLandmarkMain";
|
||||
|
||||
if (token.EqualsLiteral("navigation"))
|
||||
return @"AXLandmarkNavigation";
|
||||
|
||||
if (token.EqualsLiteral("search"))
|
||||
return @"AXLandmarkSearch";
|
||||
}
|
||||
|
||||
switch (mRole) {
|
||||
case roles::LIST:
|
||||
return @"AXContentList"; // 10.6+ NSAccessibilityContentListSubrole;
|
||||
|
@ -468,15 +493,33 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
{
|
||||
if (mRole == roles::DOCUMENT)
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("htmlContent"));
|
||||
|
||||
|
||||
NSString* subrole = [self subrole];
|
||||
|
||||
|
||||
if ((mRole == roles::LISTITEM) && [subrole isEqualToString:@"AXTerm"])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("term"));
|
||||
if ((mRole == roles::PARAGRAPH) && [subrole isEqualToString:@"AXDefinition"])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("definition"));
|
||||
|
||||
return NSAccessibilityRoleDescription([self role], subrole);
|
||||
|
||||
NSString* role = [self role];
|
||||
|
||||
// the WAI-ARIA Landmarks
|
||||
if ([role isEqualToString:NSAccessibilityGroupRole]) {
|
||||
if ([subrole isEqualToString:@"AXLandmarkBanner"])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("banner"));
|
||||
if ([subrole isEqualToString:@"AXLandmarkComplementary"])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("complementary"));
|
||||
if ([subrole isEqualToString:@"AXLandmarkContentInfo"])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("content"));
|
||||
if ([subrole isEqualToString:@"AXLandmarkMain"])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("main"));
|
||||
if ([subrole isEqualToString:@"AXLandmarkNavigation"])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("navigation"));
|
||||
if ([subrole isEqualToString:@"AXLandmarkSearch"])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("search"));
|
||||
}
|
||||
|
||||
return NSAccessibilityRoleDescription(role, subrole);
|
||||
}
|
||||
|
||||
- (NSString*)title
|
||||
|
@ -485,7 +528,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
|
||||
nsAutoString title;
|
||||
mGeckoAccessible->Name(title);
|
||||
return title.IsEmpty() ? nil : [NSString stringWithCharacters:title.BeginReading() length:title.Length()];
|
||||
return nsCocoaUtils::ToNSString(title);
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
@ -528,7 +571,8 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
|
||||
nsAutoString desc;
|
||||
mGeckoAccessible->Description(desc);
|
||||
return desc.IsEmpty() ? nil : [NSString stringWithCharacters:desc.BeginReading() length:desc.Length()];
|
||||
|
||||
return nsCocoaUtils::ToNSString(desc);
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
@ -561,18 +605,21 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
|
||||
- (BOOL)canBeFocused
|
||||
{
|
||||
return mGeckoAccessible->InteractiveState() & states::FOCUSABLE;
|
||||
return mGeckoAccessible && (mGeckoAccessible->InteractiveState() & states::FOCUSABLE);
|
||||
}
|
||||
|
||||
- (BOOL)focus
|
||||
{
|
||||
if (!mGeckoAccessible)
|
||||
return NO;
|
||||
|
||||
nsresult rv = mGeckoAccessible->TakeFocus();
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
- (BOOL)isEnabled
|
||||
{
|
||||
return (mGeckoAccessible->InteractiveState() & states::UNAVAILABLE) == 0;
|
||||
return mGeckoAccessible && ((mGeckoAccessible->InteractiveState() & states::UNAVAILABLE) == 0);
|
||||
}
|
||||
|
||||
// The root accessible calls this when the focused node was
|
||||
|
@ -637,7 +684,6 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
|
||||
[self invalidateChildren];
|
||||
|
||||
mIsExpired = YES;
|
||||
mGeckoAccessible = nsnull;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
|
@ -645,7 +691,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
|
||||
- (BOOL)isExpired
|
||||
{
|
||||
return mIsExpired;
|
||||
return !mGeckoAccessible;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
|
|
@ -29,3 +29,10 @@
|
|||
}
|
||||
-(id)tabs;
|
||||
@end
|
||||
|
||||
/**
|
||||
* Accessible for a PANE
|
||||
*/
|
||||
@interface mozPaneAccessible : mozAccessible
|
||||
|
||||
@end
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
|
||||
#import "MacUtils.h"
|
||||
#include "Accessible-inl.h"
|
||||
#include "DocAccessible.h"
|
||||
#include "XULTabAccessible.h"
|
||||
|
||||
#include "nsDeckFrame.h"
|
||||
#include "nsObjCExceptions.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
@ -71,7 +73,7 @@ enum CheckboxValue {
|
|||
|
||||
- (BOOL)accessibilityIsIgnored
|
||||
{
|
||||
return mIsExpired;
|
||||
return !mGeckoAccessible;
|
||||
}
|
||||
|
||||
- (NSArray*)accessibilityActionNames
|
||||
|
@ -333,3 +335,30 @@ enum CheckboxValue {
|
|||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation mozPaneAccessible
|
||||
|
||||
- (NSArray*)children
|
||||
{
|
||||
if (!mGeckoAccessible)
|
||||
return nil;
|
||||
|
||||
nsDeckFrame* deckFrame = do_QueryFrame(mGeckoAccessible->GetFrame());
|
||||
nsIFrame* selectedFrame = deckFrame ? deckFrame->GetSelectedBox() : nsnull;
|
||||
|
||||
Accessible* selectedAcc = nsnull;
|
||||
if (selectedFrame) {
|
||||
nsINode* node = selectedFrame->GetContent();
|
||||
selectedAcc = mGeckoAccessible->Document()->GetAccessible(node);
|
||||
}
|
||||
|
||||
if (selectedAcc) {
|
||||
mozAccessible *curNative = GetNativeFromGeckoAccessible(selectedAcc);
|
||||
if (curNative)
|
||||
return [NSArray arrayWithObjects:GetObjectOrRepresentedView(curNative), nil];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -31,7 +31,7 @@ getNativeViewFromRootAccessible(Accessible* aAccessible)
|
|||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
// if we're expired, we don't support any attributes.
|
||||
if (mIsExpired)
|
||||
if (!mGeckoAccessible)
|
||||
return [NSArray array];
|
||||
|
||||
// standard attributes that are shared and supported by root accessible (AXMain) elements.
|
||||
|
|
|
@ -13,6 +13,17 @@
|
|||
|
||||
@implementation mozHeadingAccessible
|
||||
|
||||
- (NSString*)title
|
||||
{
|
||||
nsAutoString title;
|
||||
// XXX use the flattening API when there are available
|
||||
// see bug 768298
|
||||
nsresult rv = mGeckoAccessible->GetContent()->GetTextContent(title);
|
||||
NS_ENSURE_SUCCESS(rv, nil);
|
||||
|
||||
return nsCocoaUtils::ToNSString(title);
|
||||
}
|
||||
|
||||
- (id)value
|
||||
{
|
||||
if (!mGeckoAccessible || !mGeckoAccessible->IsHyperText())
|
||||
|
@ -33,7 +44,7 @@
|
|||
- (NSArray*)accessibilityAttributeNames
|
||||
{
|
||||
// if we're expired, we don't support any attributes.
|
||||
if (mIsExpired)
|
||||
if (!mGeckoAccessible)
|
||||
return [NSArray array];
|
||||
|
||||
static NSMutableArray* attributes = nil;
|
||||
|
@ -57,7 +68,7 @@
|
|||
- (NSArray*)accessibilityActionNames
|
||||
{
|
||||
// if we're expired, we don't support any attributes.
|
||||
if (mIsExpired)
|
||||
if (!mGeckoAccessible)
|
||||
return [NSArray array];
|
||||
|
||||
static NSArray* actionNames = nil;
|
||||
|
|
|
@ -14,3 +14,8 @@
|
|||
nsIAccessibleEditableText *mGeckoEditableTextAccessible; // strong
|
||||
}
|
||||
@end
|
||||
|
||||
@interface mozTextLeafAccessible : mozAccessible
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
|
||||
#include "AccessibleWrap.h"
|
||||
#include "TextLeafAccessible.h"
|
||||
|
||||
#include "nsCocoaUtils.h"
|
||||
#include "nsObjCExceptions.h"
|
||||
|
@ -67,7 +68,7 @@ ToNSString(id aValue)
|
|||
|
||||
- (BOOL)accessibilityIsIgnored
|
||||
{
|
||||
return mIsExpired;
|
||||
return !mGeckoAccessible;
|
||||
}
|
||||
|
||||
- (NSArray*)accessibilityAttributeNames
|
||||
|
@ -110,13 +111,18 @@ ToNSString(id aValue)
|
|||
if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute])
|
||||
return [self selectedText];
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityTitleAttribute])
|
||||
return @"";
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
|
||||
// Apple's SpeechSynthesisServer expects AXValue to return an AXStaticText
|
||||
// object's AXSelectedText attribute. See bug 674612 for details.
|
||||
// Also if there is no selected text, we return the full text.
|
||||
// See bug 369710 for details.
|
||||
if ([[self role] isEqualToString:NSAccessibilityStaticTextRole])
|
||||
return [self selectedText] ? : [self text];
|
||||
if ([[self role] isEqualToString:NSAccessibilityStaticTextRole]) {
|
||||
NSString* selectedText = [self selectedText];
|
||||
return (selectedText && [selectedText length]) ? selectedText : [self text];
|
||||
}
|
||||
|
||||
return [self text];
|
||||
}
|
||||
|
@ -226,7 +232,7 @@ ToNSString(id aValue)
|
|||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityValueAttribute])
|
||||
return [self isReadOnly];
|
||||
return ![self isReadOnly];
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute] ||
|
||||
[attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute] ||
|
||||
|
@ -359,7 +365,7 @@ ToNSString(id aValue)
|
|||
|
||||
- (NSString*)text
|
||||
{
|
||||
if (!mGeckoTextAccessible)
|
||||
if (!mGeckoAccessible || !mGeckoTextAccessible)
|
||||
return nil;
|
||||
|
||||
// A password text field returns an empty value
|
||||
|
@ -378,6 +384,9 @@ ToNSString(id aValue)
|
|||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
if (!mGeckoAccessible || !mGeckoTextAccessible)
|
||||
return 0;
|
||||
|
||||
return mGeckoTextAccessible ? mGeckoTextAccessible->CharacterCount() : 0;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
|
||||
|
@ -484,3 +493,45 @@ ToNSString(id aValue)
|
|||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation mozTextLeafAccessible
|
||||
|
||||
- (NSArray*)accessibilityAttributeNames
|
||||
{
|
||||
static NSMutableArray* supportedAttributes = nil;
|
||||
if (!supportedAttributes) {
|
||||
supportedAttributes = [[super accessibilityAttributeNames] mutableCopy];
|
||||
[supportedAttributes removeObject:NSAccessibilityChildrenAttribute];
|
||||
}
|
||||
|
||||
return supportedAttributes;
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute
|
||||
{
|
||||
if ([attribute isEqualToString:NSAccessibilityTitleAttribute])
|
||||
return @"";
|
||||
|
||||
if ([attribute isEqualToString:NSAccessibilityValueAttribute])
|
||||
return [self text];
|
||||
|
||||
return [super accessibilityAttributeValue:attribute];
|
||||
}
|
||||
|
||||
- (NSString*)text
|
||||
{
|
||||
if (!mGeckoAccessible)
|
||||
return nil;
|
||||
|
||||
return nsCocoaUtils::ToNSString(mGeckoAccessible->AsTextLeaf()->Text());
|
||||
}
|
||||
|
||||
- (long)textLength
|
||||
{
|
||||
if (!mGeckoAccessible)
|
||||
return 0;
|
||||
|
||||
return mGeckoAccessible->AsTextLeaf()->Text().Length();
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -8,22 +8,17 @@
|
|||
#include "Compatibility.h"
|
||||
#include "DocAccessible-inl.h"
|
||||
#include "EnumVariant.h"
|
||||
#include "ia2AccessibleRelation.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "nsIAccessibleEvent.h"
|
||||
#include "nsIAccessibleRelation.h"
|
||||
#include "nsWinUtils.h"
|
||||
#include "Relation.h"
|
||||
#include "Role.h"
|
||||
#include "States.h"
|
||||
|
||||
#include "ia2AccessibleRelation.h"
|
||||
|
||||
#include "nsIAccessibleEvent.h"
|
||||
#include "nsIAccessibleRelation.h"
|
||||
|
||||
#include "Accessible2_i.c"
|
||||
#include "AccessibleRole.h"
|
||||
#include "AccessibleStates.h"
|
||||
#include "RootAccessible.h"
|
||||
#include "States.h"
|
||||
#include "uiaRawElmProvider.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "Logging.h"
|
||||
|
@ -40,7 +35,11 @@
|
|||
#include "nsIViewManager.h"
|
||||
#include "nsEventMap.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#include "Accessible2_i.c"
|
||||
#include "AccessibleRole.h"
|
||||
#include "AccessibleStates.h"
|
||||
#include "OLEACC.H"
|
||||
|
||||
using namespace mozilla;
|
||||
|
@ -122,6 +121,32 @@ __try {
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// IServiceProvider
|
||||
|
||||
STDMETHODIMP
|
||||
AccessibleWrap::QueryService(REFGUID aGuidService, REFIID aIID,
|
||||
void** aInstancePtr)
|
||||
{
|
||||
if (!aInstancePtr)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*aInstancePtr = NULL;
|
||||
|
||||
// UIA IAccessibleEx
|
||||
if (aGuidService == IID_IAccessibleEx &&
|
||||
Preferences::GetBool("accessibility.uia.enable")) {
|
||||
IAccessibleEx* accEx = new uiaRawElmProvider(this);
|
||||
HRESULT hr = accEx->QueryInterface(aIID, aInstancePtr);
|
||||
if (FAILED(hr))
|
||||
delete accEx;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
return nsAccessNodeWrap::QueryService(aGuidService, aIID, aInstancePtr);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
// IAccessible methods
|
||||
//-----------------------------------------------------
|
||||
|
|
|
@ -17,51 +17,104 @@
|
|||
#include "ia2AccessibleHyperlink.h"
|
||||
#include "CAccessibleValue.h"
|
||||
|
||||
#define DECL_IUNKNOWN_INHERITED \
|
||||
public: \
|
||||
STDMETHODIMP QueryInterface(REFIID, void**); \
|
||||
#define DECL_IUNKNOWN \
|
||||
public: \
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**); \
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef() MOZ_FINAL \
|
||||
{ return ++mRefCnt; } \
|
||||
virtual ULONG STDMETHODCALLTYPE Release() MOZ_FINAL \
|
||||
{ \
|
||||
mRefCnt--; \
|
||||
if (mRefCnt) \
|
||||
return mRefCnt; \
|
||||
\
|
||||
delete this; \
|
||||
return 0; \
|
||||
} \
|
||||
private: \
|
||||
ULONG mRefCnt; \
|
||||
public:
|
||||
|
||||
#define IMPL_IUNKNOWN_QUERY_HEAD(Class) \
|
||||
STDMETHODIMP \
|
||||
Class::QueryInterface(REFIID iid, void** ppv) \
|
||||
{ \
|
||||
HRESULT hr = E_NOINTERFACE; \
|
||||
*ppv = NULL; \
|
||||
#define DECL_IUNKNOWN_INHERITED \
|
||||
public: \
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**); \
|
||||
|
||||
#define IMPL_IUNKNOWN_QUERY_TAIL \
|
||||
return hr; \
|
||||
} \
|
||||
#define IMPL_IUNKNOWN_QUERY_HEAD(Class) \
|
||||
STDMETHODIMP \
|
||||
Class::QueryInterface(REFIID aIID, void** aInstancePtr) \
|
||||
{ \
|
||||
__try { \
|
||||
if (!aInstancePtr) \
|
||||
return E_INVALIDARG; \
|
||||
*aInstancePtr = NULL; \
|
||||
\
|
||||
HRESULT hr = E_NOINTERFACE;
|
||||
|
||||
#define IMPL_IUNKNOWN_QUERY_ENTRY(Class) \
|
||||
hr = Class::QueryInterface(iid, ppv); \
|
||||
if (SUCCEEDED(hr)) \
|
||||
return hr; \
|
||||
#define IMPL_IUNKNOWN_QUERY_TAIL \
|
||||
return hr; \
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), \
|
||||
GetExceptionInformation())) { } \
|
||||
return E_NOINTERFACE; \
|
||||
}
|
||||
|
||||
#define IMPL_IUNKNOWN_QUERY_ENTRY_COND(Class, Cond) \
|
||||
if (Cond) { \
|
||||
hr = Class::QueryInterface(iid, ppv); \
|
||||
if (SUCCEEDED(hr)) \
|
||||
return hr; \
|
||||
} \
|
||||
#define IMPL_IUNKNOWN_QUERY_IFACE(Iface) \
|
||||
if (aIID == IID_##Iface) { \
|
||||
*aInstancePtr = static_cast<Iface*>(this); \
|
||||
AddRef(); \
|
||||
return S_OK; \
|
||||
}
|
||||
|
||||
#define IMPL_IUNKNOWN_INHERITED0(Class, Super) \
|
||||
IMPL_IUNKNOWN_QUERY_HEAD(Class) \
|
||||
IMPL_IUNKNOWN_QUERY_ENTRY(Super) \
|
||||
IMPL_IUNKNOWN_QUERY_TAIL \
|
||||
#define IMPL_IUNKNOWN_QUERY_IFACE_AMBIGIOUS(Iface, aResolveIface) \
|
||||
if (aIID == IID_##Iface) { \
|
||||
*aInstancePtr = static_cast<Iface*>(static_cast<aResolveIface*>(this)); \
|
||||
AddRef(); \
|
||||
return S_OK; \
|
||||
}
|
||||
|
||||
#define IMPL_IUNKNOWN_INHERITED1(Class, Super, I1) \
|
||||
IMPL_IUNKNOWN_QUERY_HEAD(Class) \
|
||||
IMPL_IUNKNOWN_QUERY_ENTRY(I1); \
|
||||
IMPL_IUNKNOWN_QUERY_ENTRY(Super) \
|
||||
IMPL_IUNKNOWN_QUERY_TAIL \
|
||||
#define IMPL_IUNKNOWN_QUERY_CLASS(Class) \
|
||||
hr = Class::QueryInterface(aIID, aInstancePtr); \
|
||||
if (SUCCEEDED(hr)) \
|
||||
return hr;
|
||||
|
||||
#define IMPL_IUNKNOWN_INHERITED2(Class, Super, I1, I2) \
|
||||
IMPL_IUNKNOWN_QUERY_HEAD(Class) \
|
||||
IMPL_IUNKNOWN_QUERY_ENTRY(I1); \
|
||||
IMPL_IUNKNOWN_QUERY_ENTRY(I2); \
|
||||
IMPL_IUNKNOWN_QUERY_ENTRY(Super) \
|
||||
IMPL_IUNKNOWN_QUERY_TAIL \
|
||||
#define IMPL_IUNKNOWN_QUERY_CLASS_COND(Class, Cond) \
|
||||
if (Cond) { \
|
||||
hr = Class::QueryInterface(aIID, aInstancePtr); \
|
||||
if (SUCCEEDED(hr)) \
|
||||
return hr; \
|
||||
}
|
||||
|
||||
#define IMPL_IUNKNOWN_QUERY_AGGR_COND(Member, Cond) \
|
||||
if (Cond) { \
|
||||
hr = Member->QueryInterface(aIID, aInstancePtr); \
|
||||
if (SUCCEEDED(hr)) \
|
||||
return hr; \
|
||||
}
|
||||
|
||||
#define IMPL_IUNKNOWN1(Class, I1) \
|
||||
IMPL_IUNKNOWN_QUERY_HEAD(Class) \
|
||||
IMPL_IUNKNOWN_QUERY_IFACE(I1); \
|
||||
IMPL_IUNKNOWN_QUERY_IFACE(IUnknown); \
|
||||
IMPL_IUNKNOWN_QUERY_TAIL \
|
||||
|
||||
#define IMPL_IUNKNOWN2(Class, I1, I2) \
|
||||
IMPL_IUNKNOWN_QUERY_HEAD(Class) \
|
||||
IMPL_IUNKNOWN_QUERY_IFACE(I1); \
|
||||
IMPL_IUNKNOWN_QUERY_IFACE(I2); \
|
||||
IMPL_IUNKNOWN_QUERY_IFACE_AMBIGIOUS(IUnknown, I1); \
|
||||
IMPL_IUNKNOWN_QUERY_TAIL \
|
||||
|
||||
#define IMPL_IUNKNOWN_INHERITED1(Class, Super0, Super1) \
|
||||
IMPL_IUNKNOWN_QUERY_HEAD(Class) \
|
||||
IMPL_IUNKNOWN_QUERY_CLASS(Super1); \
|
||||
IMPL_IUNKNOWN_QUERY_CLASS(Super0) \
|
||||
IMPL_IUNKNOWN_QUERY_TAIL \
|
||||
|
||||
#define IMPL_IUNKNOWN_INHERITED2(Class, Super0, Super1, Super2) \
|
||||
IMPL_IUNKNOWN_QUERY_HEAD(Class) \
|
||||
IMPL_IUNKNOWN_QUERY_CLASS(Super1); \
|
||||
IMPL_IUNKNOWN_QUERY_CLASS(Super2); \
|
||||
IMPL_IUNKNOWN_QUERY_CLASS(Super0) \
|
||||
IMPL_IUNKNOWN_QUERY_TAIL
|
||||
|
||||
class AccessibleWrap : public Accessible,
|
||||
public ia2AccessibleComponent,
|
||||
|
@ -83,6 +136,11 @@ public: // construction, destruction
|
|||
// Return the registered OLE class ID of this object's CfDataObj.
|
||||
CLSID GetClassID() const;
|
||||
|
||||
// IServiceProvider
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID aGuidService,
|
||||
REFIID aIID,
|
||||
void** aInstancePtr);
|
||||
|
||||
public: // COM interface IAccessible
|
||||
virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accParent(
|
||||
/* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispParent);
|
||||
|
|
|
@ -13,51 +13,11 @@ using namespace mozilla::a11y;
|
|||
// ChildrenEnumVariant
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
STDMETHODIMP
|
||||
ChildrenEnumVariant::QueryInterface(REFIID aIID, void** aObject)
|
||||
{
|
||||
__try {
|
||||
if (!aObject)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (aIID == IID_IEnumVARIANT) {
|
||||
*aObject = static_cast<IEnumVARIANT*>(this);
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (aIID == IID_IUnknown) {
|
||||
*aObject = static_cast<IUnknown*>(this);
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Redirect QI to IAccessible this enum was retrieved for.
|
||||
if (!mAnchorAcc->IsDefunct())
|
||||
return mAnchorAcc->QueryInterface(aIID, aObject);
|
||||
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(),
|
||||
GetExceptionInformation())) { }
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE
|
||||
ChildrenEnumVariant::AddRef()
|
||||
{
|
||||
return ++mRefCnt;
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE
|
||||
ChildrenEnumVariant::Release()
|
||||
{
|
||||
mRefCnt--;
|
||||
ULONG r = mRefCnt;
|
||||
if (r == 0)
|
||||
delete this;
|
||||
|
||||
return r;
|
||||
}
|
||||
IMPL_IUNKNOWN_QUERY_HEAD(ChildrenEnumVariant)
|
||||
IMPL_IUNKNOWN_QUERY_IFACE(IEnumVARIANT);
|
||||
IMPL_IUNKNOWN_QUERY_IFACE(IUnknown);
|
||||
IMPL_IUNKNOWN_QUERY_AGGR_COND(mAnchorAcc, !mAnchorAcc->IsDefunct());
|
||||
IMPL_IUNKNOWN_QUERY_TAIL
|
||||
|
||||
STDMETHODIMP
|
||||
ChildrenEnumVariant::Next(ULONG aCount, VARIANT FAR* aItems,
|
||||
|
|
|
@ -22,12 +22,7 @@ public:
|
|||
mCurAcc(mAnchorAcc->GetChildAt(0)), mCurIndex(0), mRefCnt(0) { }
|
||||
|
||||
// IUnknown
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
|
||||
/* [in] */ REFIID aRefIID,
|
||||
/* [annotation][iid_is][out] */ void** aObject);
|
||||
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef();
|
||||
virtual ULONG STDMETHODCALLTYPE Release();
|
||||
DECL_IUNKNOWN
|
||||
|
||||
// IEnumVariant
|
||||
virtual /* [local] */ HRESULT STDMETHODCALLTYPE Next(
|
||||
|
@ -56,9 +51,6 @@ protected:
|
|||
nsRefPtr<AccessibleWrap> mAnchorAcc;
|
||||
Accessible* mCurAcc;
|
||||
PRUint32 mCurIndex;
|
||||
|
||||
private:
|
||||
ULONG mRefCnt;
|
||||
};
|
||||
|
||||
} // a11y namespace
|
||||
|
|
|
@ -69,6 +69,7 @@ LOCAL_INCLUDES += \
|
|||
-I$(srcdir)/../html \
|
||||
-I$(srcdir)/../xpcom \
|
||||
-I$(srcdir)/../xul \
|
||||
-I$(srcdir)/../windows/uia \
|
||||
-I$(srcdir)/../../../content/base/src \
|
||||
-I$(srcdir)/../../../content/events/src \
|
||||
$(NULL)
|
||||
|
|
|
@ -21,8 +21,8 @@ NS_IMPL_ISUPPORTS_INHERITED0(XULListboxAccessibleWrap,
|
|||
XULListboxAccessible)
|
||||
|
||||
IMPL_IUNKNOWN_QUERY_HEAD(XULListboxAccessibleWrap)
|
||||
IMPL_IUNKNOWN_QUERY_ENTRY_COND(CAccessibleTable, IsMulticolumn());
|
||||
IMPL_IUNKNOWN_QUERY_ENTRY(AccessibleWrap)
|
||||
IMPL_IUNKNOWN_QUERY_CLASS_COND(CAccessibleTable, IsMulticolumn());
|
||||
IMPL_IUNKNOWN_QUERY_CLASS(AccessibleWrap)
|
||||
IMPL_IUNKNOWN_QUERY_TAIL
|
||||
|
||||
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
|
@ -87,22 +85,13 @@ nsAccessNodeWrap::QueryService(REFGUID guidService, REFIID iid, void** ppv)
|
|||
{
|
||||
*ppv = nsnull;
|
||||
|
||||
static const GUID IID_SimpleDOMDeprecated = {0x0c539790,0x12e4,0x11cf,0xb6,0x61,0x00,0xaa,0x00,0x4c,0xd6,0xd8};
|
||||
|
||||
// Provide a special service ID for getting the accessible for the browser tab
|
||||
// document that contains this accessible object. If this accessible object
|
||||
// is not inside a browser tab then the service fails with E_NOINTERFACE.
|
||||
// A use case for this is for screen readers that need to switch context or
|
||||
// 'virtual buffer' when focus moves from one browser tab area to another.
|
||||
static const GUID SID_IAccessibleContentDocument = {0xa5d8e1f3,0x3571,0x4d8f,0x95,0x21,0x07,0xed,0x28,0xfb,0x07,0x2e};
|
||||
|
||||
if (guidService != IID_ISimpleDOMNode &&
|
||||
guidService != IID_SimpleDOMDeprecated &&
|
||||
guidService != IID_IAccessible && guidService != IID_IAccessible2 &&
|
||||
guidService != IID_IAccessibleApplication &&
|
||||
guidService != SID_IAccessibleContentDocument)
|
||||
return E_INVALIDARG;
|
||||
|
||||
static const GUID SID_IAccessibleContentDocument =
|
||||
{ 0xa5d8e1f3,0x3571,0x4d8f,0x95,0x21,0x07,0xed,0x28,0xfb,0x07,0x2e };
|
||||
if (guidService == SID_IAccessibleContentDocument) {
|
||||
if (iid != IID_IAccessible)
|
||||
return E_NOINTERFACE;
|
||||
|
@ -139,7 +128,7 @@ nsAccessNodeWrap::QueryService(REFGUID guidService, REFIID iid, void** ppv)
|
|||
}
|
||||
|
||||
// Can get to IAccessibleApplication from any node via QS
|
||||
if (iid == IID_IAccessibleApplication) {
|
||||
if (guidService == IID_IAccessibleApplication) {
|
||||
ApplicationAccessible* applicationAcc = GetApplicationAccessible();
|
||||
if (!applicationAcc)
|
||||
return E_NOINTERFACE;
|
||||
|
@ -162,7 +151,14 @@ nsAccessNodeWrap::QueryService(REFGUID guidService, REFIID iid, void** ppv)
|
|||
* }
|
||||
*/
|
||||
|
||||
return QueryInterface(iid, ppv);
|
||||
static const GUID IID_SimpleDOMDeprecated =
|
||||
{ 0x0c539790,0x12e4,0x11cf,0xb6,0x61,0x00,0xaa,0x00,0x4c,0xd6,0xd8 };
|
||||
if (guidService == IID_ISimpleDOMNode ||
|
||||
guidService == IID_SimpleDOMDeprecated ||
|
||||
guidService == IID_IAccessible || guidService == IID_IAccessible2)
|
||||
return QueryInterface(iid, ppv);
|
||||
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
|
|
|
@ -34,6 +34,14 @@
|
|||
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
||||
#define A11Y_TRYBLOCK_BEGIN \
|
||||
__try {
|
||||
|
||||
#define A11Y_TRYBLOCK_END \
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), \
|
||||
GetExceptionInformation()))\
|
||||
{ } \
|
||||
return E_FAIL;
|
||||
|
||||
class AccTextChangeEvent;
|
||||
|
||||
|
@ -46,18 +54,20 @@ class nsAccessNodeWrap : public nsAccessNode,
|
|||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIWINACCESSNODE
|
||||
|
||||
public: // IServiceProvider
|
||||
STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void** ppv);
|
||||
|
||||
public: // construction, destruction
|
||||
nsAccessNodeWrap(nsIContent* aContent, DocAccessible* aDoc);
|
||||
virtual ~nsAccessNodeWrap();
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(REFIID, void**);
|
||||
// IUnknown
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID aIID,
|
||||
void** aInstancePtr);
|
||||
|
||||
public:
|
||||
// IServiceProvider
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID aGuidService,
|
||||
REFIID aIID,
|
||||
void** aInstancePtr);
|
||||
|
||||
// ISimpleDOMNode
|
||||
virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_nodeInfo(
|
||||
/* [out] */ BSTR __RPC_FAR *tagName,
|
||||
/* [out] */ short __RPC_FAR *nameSpaceID,
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
#
|
||||
# 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/.
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS += uia \
|
||||
$(null)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,36 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = accessibility
|
||||
LIBRARY_NAME = accessibility_toolkit_uia_s
|
||||
EXPORT_LIBRARY = ..
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
||||
|
||||
CPPSRCS += \
|
||||
uiaRawElmProvider.cpp \
|
||||
$(NULL)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a static lib.
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(srcdir) \
|
||||
-I$(srcdir)/../../base \
|
||||
-I$(srcdir)/../../generic \
|
||||
-I$(srcdir)/../../html \
|
||||
-I$(srcdir)/../../msaa \
|
||||
-I$(srcdir)/../../xpcom \
|
||||
-I$(srcdir)/../../xul \
|
||||
$(NULL)
|
|
@ -0,0 +1,170 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "uiaRawElmProvider.h"
|
||||
|
||||
#include "AccessibleWrap.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// uiaRawElmProvider
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_IUNKNOWN2(uiaRawElmProvider,
|
||||
IAccessibleEx,
|
||||
IRawElementProviderSimple)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// IAccessibleEx
|
||||
|
||||
STDMETHODIMP
|
||||
uiaRawElmProvider::GetObjectForChild(long aIdChild,
|
||||
__RPC__deref_out_opt IAccessibleEx** aAccEx)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aAccEx)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*aAccEx = NULL;
|
||||
|
||||
return mAcc->IsDefunct() ? CO_E_OBJNOTCONNECTED : S_OK;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
uiaRawElmProvider::GetIAccessiblePair(__RPC__deref_out_opt IAccessible** aAcc,
|
||||
__RPC__out long* aIdChild)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aAcc || !aIdChild)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*aAcc = NULL;
|
||||
*aIdChild = 0;
|
||||
|
||||
if (mAcc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
*aIdChild = CHILDID_SELF;
|
||||
*aAcc = mAcc;
|
||||
mAcc->AddRef();
|
||||
|
||||
return S_OK;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
uiaRawElmProvider::GetRuntimeId(__RPC__deref_out_opt SAFEARRAY** aRuntimeIds)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aRuntimeIds)
|
||||
return E_INVALIDARG;
|
||||
|
||||
int ids[] = { UiaAppendRuntimeId, reinterpret_cast<int>(mAcc->UniqueID()) };
|
||||
*aRuntimeIds = SafeArrayCreateVector(VT_I4, 0, 2);
|
||||
if (!*aRuntimeIds)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
for (LONG i = 0; i < ArrayLength(ids); i++)
|
||||
SafeArrayPutElement(*aRuntimeIds, &i, (void*)&(ids[i]));
|
||||
|
||||
return S_OK;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
uiaRawElmProvider::ConvertReturnedElement(__RPC__in_opt IRawElementProviderSimple* aRawElmProvider,
|
||||
__RPC__deref_out_opt IAccessibleEx** aAccEx)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aRawElmProvider || !aAccEx)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*aAccEx = NULL;
|
||||
|
||||
void* instancePtr = NULL;
|
||||
HRESULT hr = aRawElmProvider->QueryInterface(IID_IAccessibleEx, &instancePtr);
|
||||
if (SUCCEEDED(hr))
|
||||
*aAccEx = static_cast<IAccessibleEx*>(instancePtr);
|
||||
|
||||
return hr;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// IRawElementProviderSimple
|
||||
|
||||
STDMETHODIMP
|
||||
uiaRawElmProvider::get_ProviderOptions(__RPC__out enum ProviderOptions* aOptions)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aOptions)
|
||||
return E_INVALIDARG;
|
||||
|
||||
// This method is not used with IAccessibleEx implementations.
|
||||
*aOptions = ProviderOptions_ServerSideProvider;
|
||||
return S_OK;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
uiaRawElmProvider::GetPatternProvider(PATTERNID aPatternId,
|
||||
__RPC__deref_out_opt IUnknown** aPatternProvider)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aPatternProvider)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*aPatternProvider = NULL;
|
||||
return S_OK;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
uiaRawElmProvider::GetPropertyValue(PROPERTYID aPropertyId,
|
||||
__RPC__out VARIANT* aPropertyValue)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aPropertyValue)
|
||||
return E_INVALIDARG;
|
||||
|
||||
// UI Automation will attempt to get the property from the host
|
||||
//window provider.
|
||||
aPropertyValue->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
uiaRawElmProvider::get_HostRawElementProvider(__RPC__deref_out_opt IRawElementProviderSimple** aRawElmProvider)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aRawElmProvider)
|
||||
return E_INVALIDARG;
|
||||
|
||||
// This method is not used with IAccessibleEx implementations.
|
||||
*aRawElmProvider = NULL;
|
||||
return S_OK;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_a11y_uiaRawElmProvider_h__
|
||||
#define mozilla_a11y_uiaRawElmProvider_h__
|
||||
|
||||
#include "objbase.h"
|
||||
#include "AccessibleWrap.h"
|
||||
#include "UIAutomation.h"
|
||||
|
||||
class AccessibleWrap;
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
/**
|
||||
* IRawElementProviderSimple implementation (maintains IAccessibleEx approach).
|
||||
*/
|
||||
class uiaRawElmProvider MOZ_FINAL : public IAccessibleEx,
|
||||
public IRawElementProviderSimple
|
||||
{
|
||||
public:
|
||||
uiaRawElmProvider(AccessibleWrap* aAcc) : mAcc(aAcc), mRefCnt(0) { }
|
||||
|
||||
// IUnknown
|
||||
DECL_IUNKNOWN
|
||||
|
||||
// IAccessibleEx
|
||||
virtual HRESULT STDMETHODCALLTYPE GetObjectForChild(
|
||||
/* [in] */ long aIdChild,
|
||||
/* [retval][out] */ __RPC__deref_out_opt IAccessibleEx** aAccEx);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetIAccessiblePair(
|
||||
/* [out] */ __RPC__deref_out_opt IAccessible** aAcc,
|
||||
/* [out] */ __RPC__out long* aIdChild);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetRuntimeId(
|
||||
/* [retval][out] */ __RPC__deref_out_opt SAFEARRAY** aRuntimeIds);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE ConvertReturnedElement(
|
||||
/* [in] */ __RPC__in_opt IRawElementProviderSimple* aRawElmProvider,
|
||||
/* [out] */ __RPC__deref_out_opt IAccessibleEx** aAccEx);
|
||||
|
||||
// IRawElementProviderSimple
|
||||
virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ProviderOptions(
|
||||
/* [retval][out] */ __RPC__out enum ProviderOptions* aProviderOptions);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetPatternProvider(
|
||||
/* [in] */ PATTERNID aPatternId,
|
||||
/* [retval][out] */ __RPC__deref_out_opt IUnknown** aPatternProvider);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetPropertyValue(
|
||||
/* [in] */ PROPERTYID aPropertyId,
|
||||
/* [retval][out] */ __RPC__out VARIANT* aPropertyValue);
|
||||
|
||||
virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_HostRawElementProvider(
|
||||
/* [retval][out] */ __RPC__deref_out_opt IRawElementProviderSimple** aRawElmProvider);
|
||||
|
||||
private:
|
||||
uiaRawElmProvider() MOZ_DELETE;
|
||||
uiaRawElmProvider& operator =(const uiaRawElmProvider&) MOZ_DELETE;
|
||||
uiaRawElmProvider(const uiaRawElmProvider&) MOZ_DELETE;
|
||||
|
||||
protected:
|
||||
nsRefPtr<AccessibleWrap> mAcc;
|
||||
};
|
||||
|
||||
} // a11y namespace
|
||||
} // mozilla namespace
|
||||
|
||||
#endif
|
|
@ -164,22 +164,15 @@ XULTabsAccessible::GetNameInternal(nsAString& aName)
|
|||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// XULTabpanelsAccessible
|
||||
// XULDeckAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
XULTabpanelsAccessible::
|
||||
XULTabpanelsAccessible(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
AccessibleWrap(aContent, aDoc)
|
||||
{
|
||||
}
|
||||
|
||||
role
|
||||
XULTabpanelsAccessible::NativeRole()
|
||||
XULDeckAccessible::NativeRole()
|
||||
{
|
||||
return roles::PANE;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// XULTabpanelAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -56,13 +56,15 @@ public:
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* A container of tab panels, xul:tabpanels element.
|
||||
*/
|
||||
class XULTabpanelsAccessible : public AccessibleWrap
|
||||
class XULDeckAccessible : public AccessibleWrap
|
||||
{
|
||||
public:
|
||||
XULTabpanelsAccessible(nsIContent* aContent, DocAccessible* aDoc);
|
||||
XULDeckAccessible(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
AccessibleWrap(aContent, aDoc)
|
||||
{ mFlags |= eXULDeckAccessible; }
|
||||
|
||||
// Accessible
|
||||
virtual a11y::role NativeRole();
|
||||
|
|
|
@ -542,6 +542,23 @@
|
|||
testTextAttrs(ID, 2, { }, defAttrs, 2, 6);
|
||||
testTextAttrs(ID, 6, attrs, defAttrs, 6, 7);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// area19, "HTML5 mark tag" test
|
||||
// text enclosed in mark tag will have a different background color
|
||||
ID = "area19";
|
||||
defAttrs = buildDefaultTextAttrs(ID, "12pt");
|
||||
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 0, attrs, defAttrs, 0, 10);
|
||||
|
||||
tempElem = getNode(ID).firstChild.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = { "background-color": gComputedStyle.backgroundColor };
|
||||
testTextAttrs(ID, 11, attrs, defAttrs, 10, 17);
|
||||
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 18, attrs, defAttrs, 17, 28);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -692,5 +709,9 @@
|
|||
<li id="area18" class="gencontent">item</li>
|
||||
</ul>
|
||||
|
||||
<p id="area19">uncolored
|
||||
<mark>colored</mark> uncolored
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -378,6 +378,9 @@ pref("dom.sms.enabled", true);
|
|||
// Temporary permission hack for WebContacts
|
||||
pref("dom.mozContacts.enabled", true);
|
||||
|
||||
// WebAlarms
|
||||
pref("dom.mozAlarms.enabled", true);
|
||||
|
||||
// WebSettings
|
||||
pref("dom.mozSettings.enabled", true);
|
||||
|
||||
|
|
|
@ -161,7 +161,7 @@ DeviceTabActor.prototype = {
|
|||
'tab should have an actorID.');
|
||||
return {
|
||||
'actor': this.actorID,
|
||||
'title': this.browser.contentTitle,
|
||||
'title': this.browser.title,
|
||||
'url': this.browser.document.documentURI
|
||||
}
|
||||
},
|
||||
|
@ -222,7 +222,7 @@ DeviceTabActor.prototype = {
|
|||
this.conn.addActorPool(this._contextPool);
|
||||
|
||||
this.threadActor = new ThreadActor(this);
|
||||
this._addDebuggees(this.browser.content.wrappedJSObject);
|
||||
this._addDebuggees(this.browser.wrappedJSObject);
|
||||
this._contextPool.addActor(this.threadActor);
|
||||
},
|
||||
|
||||
|
@ -293,7 +293,7 @@ DeviceTabActor.prototype = {
|
|||
* Prepare to enter a nested event loop by disabling debuggee events.
|
||||
*/
|
||||
preNest: function DTA_preNest() {
|
||||
let windowUtils = this.browser.content
|
||||
let windowUtils = this.browser
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
windowUtils.suppressEventHandling(true);
|
||||
|
@ -304,7 +304,7 @@ DeviceTabActor.prototype = {
|
|||
* Prepare to exit a nested event loop by enabling debuggee events.
|
||||
*/
|
||||
postNest: function DTA_postNest(aNestData) {
|
||||
let windowUtils = this.browser.content
|
||||
let windowUtils = this.browser
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
windowUtils.resumeTimeouts();
|
||||
|
|
|
@ -79,15 +79,18 @@ SettingsListener.observe('language.current', 'en-US', function(value) {
|
|||
|
||||
|
||||
// =================== Debugger ====================
|
||||
SettingsListener.observe('devtools.debugger.enabled', false, function(enabled) {
|
||||
Services.prefs.setBoolPref('devtools.debugger.enabled', value);
|
||||
SettingsListener.observe('devtools.debugger.remote-enabled', false, function(enabled) {
|
||||
Services.prefs.setBoolPref('devtools.debugger.remote-enabled', value);
|
||||
});
|
||||
|
||||
SettingsListener.observe('devtools.debugger.log', false, function(value) {
|
||||
Services.prefs.setBoolPref('devtools.debugger.log', value);
|
||||
});
|
||||
|
||||
SettingsListener.observe('devtools.debugger.port', 6000, function(value) {
|
||||
Services.prefs.setIntPref('devtools.debugger.port', value);
|
||||
SettingsListener.observe('devtools.debugger.remote-port', 6000, function(value) {
|
||||
Services.prefs.setIntPref('devtools.debugger.remote-port', value);
|
||||
});
|
||||
|
||||
SettingsListener.observe('devtools.debugger.force-local', true, function(value) {
|
||||
Services.prefs.setBoolPref('devtools.debugger.force-local', value);
|
||||
});
|
||||
|
|
|
@ -14,6 +14,7 @@ Cu.import('resource://gre/modules/Services.jsm');
|
|||
Cu.import('resource://gre/modules/ContactService.jsm');
|
||||
Cu.import('resource://gre/modules/SettingsChangeNotifier.jsm');
|
||||
Cu.import('resource://gre/modules/Webapps.jsm');
|
||||
Cu.import('resource://gre/modules/AlarmService.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, 'env',
|
||||
'@mozilla.org/process/environment;1',
|
||||
|
@ -48,10 +49,10 @@ XPCOMUtils.defineLazyGetter(this, 'DebuggerServer', function() {
|
|||
// XXX never grant 'content-camera' to non-gaia apps
|
||||
function addPermissions(urls) {
|
||||
let permissions = [
|
||||
'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app', 'pin-app',
|
||||
'indexedDB-unlimited', 'webapps-manage', 'offline-app', 'pin-app',
|
||||
'websettings-read', 'websettings-readwrite',
|
||||
'content-camera', 'webcontacts-manage', 'wifi-manage', 'desktop-notification',
|
||||
'geolocation', 'device-storage'
|
||||
'geolocation', 'device-storage', 'alarms'
|
||||
];
|
||||
urls.forEach(function(url) {
|
||||
url = url.trim();
|
||||
|
|
|
@ -7,7 +7,6 @@ ac_add_options --enable-application=b2g
|
|||
ac_add_options --target=arm-android-eabi
|
||||
ac_add_options --with-gonk="$topsrcdir/gonk-toolchain"
|
||||
ac_add_options --with-gonk-toolchain-prefix="$topsrcdir/gonk-toolchain/prebuilt/$TOOLCHAIN_HOST/toolchain/arm-eabi-4.4.3/bin/arm-eabi-"
|
||||
ac_add_options --with-endian=little
|
||||
ac_add_options --disable-elf-hack
|
||||
ac_add_options --enable-debug-symbols
|
||||
ac_add_options --enable-debug
|
||||
|
|
|
@ -7,7 +7,6 @@ ac_add_options --enable-application=b2g
|
|||
ac_add_options --target=arm-android-eabi
|
||||
ac_add_options --with-gonk="$topsrcdir/gonk-toolchain"
|
||||
ac_add_options --with-gonk-toolchain-prefix="$topsrcdir/gonk-toolchain/prebuilt/$TOOLCHAIN_HOST/toolchain/arm-eabi-4.4.3/bin/arm-eabi-"
|
||||
ac_add_options --with-endian=little
|
||||
ac_add_options --disable-elf-hack
|
||||
ac_add_options --enable-debug-symbols
|
||||
ac_add_options --enable-profiling
|
||||
|
|
|
@ -55,6 +55,10 @@ BINPATH = bin
|
|||
endif
|
||||
DEFINES += -DBINPATH=$(BINPATH)
|
||||
|
||||
ifneq (,$(filter WINNT Darwin Android,$(OS_TARGET)))
|
||||
DEFINES += -DMOZ_SHARED_MOZGLUE=1
|
||||
endif
|
||||
|
||||
ifdef MOZ_PKG_MANIFEST_P
|
||||
$(MOZ_PKG_MANIFEST): $(MOZ_PKG_MANIFEST_P) FORCE
|
||||
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $< > $@
|
||||
|
|
|
@ -82,11 +82,13 @@
|
|||
@BINPATH@/mozcpp19.dll
|
||||
#endif
|
||||
#endif
|
||||
#ifdef MOZ_SHARED_MOZGLUE
|
||||
@BINPATH@/@DLL_PREFIX@mozglue@DLL_SUFFIX@
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
@BINPATH@/AndroidManifest.xml
|
||||
@BINPATH@/resources.arsc
|
||||
@BINPATH@/classes.dex
|
||||
@BINPATH@/@DLL_PREFIX@mozglue@DLL_SUFFIX@
|
||||
@BINPATH@/res/drawable
|
||||
@BINPATH@/res/drawable-hdpi
|
||||
@BINPATH@/res/layout
|
||||
|
@ -161,6 +163,7 @@
|
|||
#endif
|
||||
@BINPATH@/components/dom_canvas.xpt
|
||||
@BINPATH@/components/dom_contacts.xpt
|
||||
@BINPATH@/components/dom_alarm.xpt
|
||||
@BINPATH@/components/dom_core.xpt
|
||||
@BINPATH@/components/dom_css.xpt
|
||||
@BINPATH@/components/dom_devicestorage.xpt
|
||||
|
@ -317,6 +320,8 @@
|
|||
@BINPATH@/components/BrowserElementParent.js
|
||||
@BINPATH@/components/ContactManager.js
|
||||
@BINPATH@/components/ContactManager.manifest
|
||||
@BINPATH@/components/AlarmsManager.js
|
||||
@BINPATH@/components/AlarmsManager.manifest
|
||||
@BINPATH@/components/FeedProcessor.manifest
|
||||
@BINPATH@/components/FeedProcessor.js
|
||||
@BINPATH@/components/BrowserFeeds.manifest
|
||||
|
|
|
@ -1023,7 +1023,7 @@ pref("services.sync.prefs.sync.xpinstall.whitelist.required", true);
|
|||
pref("devtools.errorconsole.enabled", false);
|
||||
|
||||
// Developer toolbar and GCLI preferences
|
||||
pref("devtools.toolbar.enabled", false);
|
||||
pref("devtools.toolbar.enabled", true);
|
||||
pref("devtools.toolbar.visible", false);
|
||||
pref("devtools.gcli.allowSet", false);
|
||||
pref("devtools.commands.dir", "");
|
||||
|
@ -1073,6 +1073,11 @@ pref("devtools.ruleview.enabled", true);
|
|||
// Enable the Scratchpad tool.
|
||||
pref("devtools.scratchpad.enabled", true);
|
||||
|
||||
// The maximum number of recently-opened files stored.
|
||||
// Setting this preference to 0 will not clear any recent files, but rather hide
|
||||
// the 'Open Recent'-menu.
|
||||
pref("devtools.scratchpad.recentFilesMax", 10);
|
||||
|
||||
// Enable the Style Editor.
|
||||
pref("devtools.styleeditor.enabled", true);
|
||||
pref("devtools.styleeditor.transitions", true);
|
||||
|
@ -1177,3 +1182,6 @@ pref("pdfjs.previousHandler.alwaysAskBeforeHandling", false);
|
|||
// might keep around more than this, but we'll try to get down to this value).
|
||||
// (This is intentionally on the high side; see bug 746055.)
|
||||
pref("image.mem.max_decoded_image_kb", 256000);
|
||||
|
||||
// Example social provider
|
||||
pref("social.manifest.motown", "{\"origin\":\"https://motown-dev.mozillalabs.com\",\"name\":\"MoTown\",\"workerURL\":\"https://motown-dev.mozillalabs.com/social/worker.js\"}");
|
||||
|
|
|
@ -118,7 +118,7 @@
|
|||
command="Browser:SavePage"
|
||||
key="key_savePage"/>
|
||||
<menuitem id="appmenu_sendLink"
|
||||
label="&sendPageCmd.label;"
|
||||
label="&emailPageCmd.label;"
|
||||
command="Browser:SendLink"/>
|
||||
<splitmenu id="appmenu_print"
|
||||
iconic="true"
|
||||
|
|
|
@ -37,10 +37,6 @@
|
|||
label="&saveLinkCmd.label;"
|
||||
accesskey="&saveLinkCmd.accesskey;"
|
||||
oncommand="gContextMenu.saveLink();"/>
|
||||
<menuitem id="context-sendlink"
|
||||
label="&sendLinkCmd.label;"
|
||||
accesskey="&sendLinkCmd.accesskey;"
|
||||
oncommand="gContextMenu.sendLink();"/>
|
||||
<menuitem id="context-copyemail"
|
||||
label="©EmailCmd.label;"
|
||||
accesskey="©EmailCmd.accesskey;"
|
||||
|
@ -129,8 +125,8 @@
|
|||
accesskey="&saveImageCmd.accesskey;"
|
||||
oncommand="gContextMenu.saveMedia();"/>
|
||||
<menuitem id="context-sendimage"
|
||||
label="&sendImageCmd.label;"
|
||||
accesskey="&sendImageCmd.accesskey;"
|
||||
label="&emailImageCmd.label;"
|
||||
accesskey="&emailImageCmd.accesskey;"
|
||||
oncommand="gContextMenu.sendMedia();"/>
|
||||
<menuitem id="context-setDesktopBackground"
|
||||
label="&setDesktopBackgroundCmd.label;"
|
||||
|
@ -153,12 +149,12 @@
|
|||
label="&videoSaveImage.label;"
|
||||
oncommand="gContextMenu.saveVideoFrameAsImage();"/>
|
||||
<menuitem id="context-sendvideo"
|
||||
label="&sendVideoCmd.label;"
|
||||
accesskey="&sendVideoCmd.accesskey;"
|
||||
label="&emailVideoCmd.label;"
|
||||
accesskey="&emailVideoCmd.accesskey;"
|
||||
oncommand="gContextMenu.sendMedia();"/>
|
||||
<menuitem id="context-sendaudio"
|
||||
label="&sendAudioCmd.label;"
|
||||
accesskey="&sendAudioCmd.accesskey;"
|
||||
label="&emailAudioCmd.label;"
|
||||
accesskey="&emailAudioCmd.accesskey;"
|
||||
oncommand="gContextMenu.sendMedia();"/>
|
||||
<menuitem id="context-back"
|
||||
label="&backCmd.label;"
|
||||
|
@ -188,10 +184,6 @@
|
|||
label="&savePageCmd.label;"
|
||||
accesskey="&savePageCmd.accesskey2;"
|
||||
oncommand="gContextMenu.savePageAs();"/>
|
||||
<menuitem id="context-sendpage"
|
||||
label="&sendPageCmd.label;"
|
||||
accesskey="&sendPageCmd.accesskey;"
|
||||
oncommand="gContextMenu.sendPage();"/>
|
||||
<menuseparator id="context-sep-viewbgimage"/>
|
||||
<menuitem id="context-viewbgimage"
|
||||
label="&viewBGImageCmd.label;"
|
||||
|
|
|
@ -53,8 +53,8 @@
|
|||
key="key_savePage"
|
||||
command="Browser:SavePage"/>
|
||||
<menuitem id="menu_sendLink"
|
||||
label="&sendPageCmd.label;"
|
||||
accesskey="&sendPageCmd.accesskey;"
|
||||
label="&emailPageCmd.label;"
|
||||
accesskey="&emailPageCmd.accesskey;"
|
||||
command="Browser:SendLink"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_printSetup"
|
||||
|
@ -519,7 +519,6 @@
|
|||
autocheck="false"
|
||||
hidden="true"
|
||||
label="&devToolbarMenu.label;"
|
||||
accesskey="&devToolbarMenu.accesskey;"
|
||||
key="key_devToolbar"
|
||||
command="Tools:DevToolbar"/>
|
||||
<menuitem id="webConsole"
|
||||
|
|
|
@ -225,13 +225,6 @@
|
|||
#endif
|
||||
<key id="key_openAddons" key="&addons.commandkey;" command="Tools:Addons" modifiers="accel,shift"/>
|
||||
<key id="key_errorConsole" key="&errorConsoleCmd.commandkey;" oncommand="toJavaScriptConsole();" modifiers="accel,shift" disabled="true"/>
|
||||
<key id="key_devToolbar" key="&devToolbar.commandkey;" command="Tools:DevToolbar"
|
||||
#ifdef XP_MACOSX
|
||||
modifiers="accel,alt"
|
||||
#else
|
||||
modifiers="accel,shift"
|
||||
#endif
|
||||
/>
|
||||
<key id="key_webConsole" key="&webConsoleCmd.commandkey;" oncommand="HUDConsoleUI.toggleHUD();"
|
||||
#ifdef XP_MACOSX
|
||||
modifiers="accel,alt"
|
||||
|
|
|
@ -568,6 +568,16 @@ html|*#gcli-output-frame,
|
|||
direction: ltr;
|
||||
}
|
||||
|
||||
#developer-toolbar-webconsole[error-count] > .toolbarbutton-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#developer-toolbar-webconsole[error-count]:before {
|
||||
content: attr(error-count);
|
||||
display: -moz-box;
|
||||
-moz-box-pack: center;
|
||||
}
|
||||
|
||||
/* Responsive Mode */
|
||||
|
||||
vbox[anonid=browserContainer][responsivemode] {
|
||||
|
|
|
@ -1400,7 +1400,7 @@ var gBrowserInit = {
|
|||
|
||||
// Show the toolbar if it was previously visible
|
||||
if (gPrefService.getBoolPref("devtools.toolbar.visible")) {
|
||||
DeveloperToolbar.show();
|
||||
DeveloperToolbar.show(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2610,13 +2610,16 @@ function BrowserOnClick(event) {
|
|||
if (previousNotification)
|
||||
notificationBox.removeNotification(previousNotification);
|
||||
|
||||
notificationBox.appendNotification(
|
||||
let notification = notificationBox.appendNotification(
|
||||
title,
|
||||
value,
|
||||
"chrome://global/skin/icons/blacklist_favicon.png",
|
||||
notificationBox.PRIORITY_CRITICAL_HIGH,
|
||||
buttons
|
||||
);
|
||||
// Persist the notification until the user removes so it
|
||||
// doesn't get removed on redirects.
|
||||
notification.persistence = -1;
|
||||
}
|
||||
}
|
||||
else if (/^about:home$/i.test(ownerDoc.documentURI)) {
|
||||
|
@ -5261,10 +5264,9 @@ function middleMousePaste(event) {
|
|||
Cu.reportError(ex);
|
||||
}
|
||||
|
||||
// FIXME: Bug 631500, use openUILink directly
|
||||
let where = whereToOpenLink(event, true);
|
||||
openUILinkIn(url, where,
|
||||
{ disallowInheritPrincipal: !mayInheritPrincipal.value });
|
||||
openUILink(url, event,
|
||||
{ ignoreButton: true,
|
||||
disallowInheritPrincipal: !mayInheritPrincipal.value });
|
||||
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
@ -6914,6 +6916,7 @@ let gPrivateBrowsingUI = {
|
|||
_searchBarValue: null,
|
||||
_findBarValue: null,
|
||||
_inited: false,
|
||||
_initCallbacks: [],
|
||||
|
||||
init: function PBUI_init() {
|
||||
Services.obs.addObserver(this, "private-browsing", false);
|
||||
|
@ -6926,6 +6929,9 @@ let gPrivateBrowsingUI = {
|
|||
this.onEnterPrivateBrowsing(true);
|
||||
|
||||
this._inited = true;
|
||||
|
||||
this._initCallbacks.forEach(function (callback) callback.apply());
|
||||
this._initCallbacks = [];
|
||||
},
|
||||
|
||||
uninit: function PBUI_unint() {
|
||||
|
@ -6936,6 +6942,17 @@ let gPrivateBrowsingUI = {
|
|||
Services.obs.removeObserver(this, "private-browsing-transition-complete");
|
||||
},
|
||||
|
||||
get initialized() {
|
||||
return this._inited;
|
||||
},
|
||||
|
||||
addInitializationCallback: function PBUI_addInitializationCallback(aCallback) {
|
||||
if (this._inited)
|
||||
return;
|
||||
|
||||
this._initCallbacks.push(aCallback);
|
||||
},
|
||||
|
||||
get _disableUIOnToggle() {
|
||||
if (this._privateBrowsingService.autoStarted)
|
||||
return false;
|
||||
|
@ -7138,14 +7155,16 @@ let gPrivateBrowsingUI = {
|
|||
!this.privateBrowsingEnabled;
|
||||
},
|
||||
|
||||
get autoStarted() {
|
||||
return this._privateBrowsingService.autoStarted;
|
||||
},
|
||||
|
||||
get privateBrowsingEnabled() {
|
||||
return this._privateBrowsingService.privateBrowsingEnabled;
|
||||
},
|
||||
|
||||
/**
|
||||
* These accessors are used to support per-window Private Browsing mode.
|
||||
* For now the getter returns nsIPrivateBrowsingService.privateBrowsingEnabled,
|
||||
* and the setter should only be used in tests.
|
||||
* This accessor is used to support per-window Private Browsing mode.
|
||||
*/
|
||||
get privateWindow() {
|
||||
if (!gBrowser)
|
||||
|
|
|
@ -1037,21 +1037,21 @@
|
|||
</stack>
|
||||
<toolbarbutton id="developer-toolbar-webconsole"
|
||||
label="&webConsoleButton.label;"
|
||||
class="devtools-toolbarbutton"
|
||||
class="developer-toolbar-button"
|
||||
command="Tools:WebConsole"/>
|
||||
<toolbarbutton id="developer-toolbar-inspector"
|
||||
label="&inspectorButton.label;"
|
||||
class="devtools-toolbarbutton"
|
||||
class="developer-toolbar-button"
|
||||
hidden="true"
|
||||
command="Tools:Inspect"/>
|
||||
<toolbarbutton id="developer-toolbar-styleeditor"
|
||||
label="&styleeditor.label;"
|
||||
class="devtools-toolbarbutton"
|
||||
class="developer-toolbar-button"
|
||||
hidden="true"
|
||||
command="Tools:StyleEditor"/>
|
||||
<toolbarbutton id="developer-toolbar-debugger"
|
||||
label="&debuggerMenu.label2;"
|
||||
class="devtools-toolbarbutton"
|
||||
class="developer-toolbar-button"
|
||||
hidden="true"
|
||||
command="Tools:Debugger"/>
|
||||
#ifndef XP_MACOSX
|
||||
|
|
|
@ -38,10 +38,13 @@ let gDrag = {
|
|||
|
||||
// Mark nodes as being dragged.
|
||||
let selector = ".newtab-site, .newtab-control, .newtab-thumbnail";
|
||||
let nodes = aSite.node.parentNode.querySelectorAll(selector);
|
||||
let parentCell = aSite.node.parentNode;
|
||||
let nodes = parentCell.querySelectorAll(selector);
|
||||
for (let i = 0; i < nodes.length; i++)
|
||||
nodes[i].setAttribute("dragged", "true");
|
||||
|
||||
parentCell.setAttribute("dragged", "true");
|
||||
|
||||
this._setDragData(aSite, aEvent);
|
||||
|
||||
// Store the cursor offset.
|
||||
|
@ -88,7 +91,7 @@ let gDrag = {
|
|||
* @param aEvent The 'dragend' event.
|
||||
*/
|
||||
end: function Drag_end(aSite, aEvent) {
|
||||
let nodes = aSite.node.parentNode.querySelectorAll("[dragged]");
|
||||
let nodes = gGrid.node.querySelectorAll("[dragged]")
|
||||
for (let i = 0; i < nodes.length; i++)
|
||||
nodes[i].removeAttribute("dragged");
|
||||
|
||||
|
|
|
@ -148,8 +148,9 @@ nsContextMenu.prototype = {
|
|||
this.onTextInput);
|
||||
this.showItem("context-back", shouldShow);
|
||||
this.showItem("context-forward", shouldShow);
|
||||
this.showItem("context-reload", shouldShow);
|
||||
this.showItem("context-stop", shouldShow);
|
||||
var shouldShowReload = XULBrowserWindow.stopCommand.getAttribute("disabled") == "true";
|
||||
this.showItem("context-reload", shouldShow && shouldShowReload);
|
||||
this.showItem("context-stop", shouldShow && !shouldShowReload);
|
||||
this.showItem("context-sep-stop", shouldShow);
|
||||
|
||||
// XXX: Stop is determined in browser.js; the canStop broadcaster is broken
|
||||
|
@ -171,11 +172,9 @@ nsContextMenu.prototype = {
|
|||
this.isContentSelected || this.onImage ||
|
||||
this.onCanvas || this.onVideo || this.onAudio);
|
||||
this.showItem("context-savepage", shouldShow);
|
||||
this.showItem("context-sendpage", shouldShow);
|
||||
|
||||
// Save+Send link depends on whether we're in a link, or selected text matches valid URL pattern.
|
||||
// Save link depends on whether we're in a link, or selected text matches valid URL pattern.
|
||||
this.showItem("context-savelink", this.onSaveableLink || this.onPlainTextLink);
|
||||
this.showItem("context-sendlink", this.onSaveableLink || this.onPlainTextLink);
|
||||
|
||||
// Save image depends on having loaded its content, video and audio don't.
|
||||
this.showItem("context-saveimage", this.onLoadedImage || this.onCanvas);
|
||||
|
@ -1050,11 +1049,6 @@ nsContextMenu.prototype = {
|
|||
this.saveHelper(this.linkURL, linkText, null, true, doc);
|
||||
},
|
||||
|
||||
sendLink: function() {
|
||||
// we don't know the title of the link so pass in an empty string
|
||||
MailIntegration.sendMessage( this.linkURL, "" );
|
||||
},
|
||||
|
||||
// Backwards-compatibility wrapper
|
||||
saveImage : function() {
|
||||
if (this.onCanvas || this.onImage)
|
||||
|
@ -1403,10 +1397,6 @@ nsContextMenu.prototype = {
|
|||
saveDocument(this.browser.contentDocument);
|
||||
},
|
||||
|
||||
sendPage: function CM_sendPage() {
|
||||
MailIntegration.sendLinkForWindow(this.browser.contentWindow);
|
||||
},
|
||||
|
||||
printFrame: function CM_printFrame() {
|
||||
PrintUtils.print(this.target.ownerDocument.defaultView);
|
||||
},
|
||||
|
|
|
@ -354,18 +354,23 @@
|
|||
<label class="permissionLabel" id="permIndexedDBLabel"
|
||||
value="&permIndexedDB;" control="indexedDBRadioGroup"/>
|
||||
<hbox role="group" aria-labelledby="permIndexedDBLabel">
|
||||
<checkbox id="indexedDBDef" command="cmd_indexedDBDef" label="&permAskAlways;"/>
|
||||
<checkbox id="indexedDBDef" command="cmd_indexedDBDef" label="&permUseDefault;"/>
|
||||
<spacer flex="1"/>
|
||||
<vbox pack="center">
|
||||
<label id="indexedDBStatus" control="indexedDBClear"/>
|
||||
</vbox>
|
||||
<button id="indexedDBClear" label="&permClearStorage;"
|
||||
accesskey="&permClearStorage.accesskey;" onclick="onIndexedDBClear();"/>
|
||||
<radiogroup id="indexedDBRadioGroup" orient="horizontal">
|
||||
<radio id="indexedDB#1" command="cmd_indexedDBToggle" label="&permAllow;"/>
|
||||
<!-- Ask and Allow are purposefully reversed here! -->
|
||||
<radio id="indexedDB#1" command="cmd_indexedDBToggle" label="&permAskAlways;"/>
|
||||
<radio id="indexedDB#0" command="cmd_indexedDBToggle" label="&permAllow;"/>
|
||||
<radio id="indexedDB#2" command="cmd_indexedDBToggle" label="&permBlock;"/>
|
||||
</radiogroup>
|
||||
</hbox>
|
||||
<hbox>
|
||||
<spacer flex="1"/>
|
||||
<vbox pack="center">
|
||||
<label id="indexedDBStatus" control="indexedDBClear" hidden="true"/>
|
||||
</vbox>
|
||||
<button id="indexedDBClear" label="&permClearStorage;" hidden="true"
|
||||
accesskey="&permClearStorage.accesskey;" onclick="onIndexedDBClear();"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
<vbox class="permission" id="permPluginsRow">
|
||||
<label class="permissionLabel" id="permPluginsLabel"
|
||||
|
|
|
@ -51,7 +51,7 @@ var gPermObj = {
|
|||
},
|
||||
indexedDB: function getIndexedDBDefaultPermissions()
|
||||
{
|
||||
return BLOCK;
|
||||
return UNKNOWN;
|
||||
},
|
||||
plugins: function getPluginsDefaultPermissions()
|
||||
{
|
||||
|
@ -149,9 +149,6 @@ function onCheckboxClick(aPartId)
|
|||
var checkbox = document.getElementById(aPartId + "Def");
|
||||
if (checkbox.checked) {
|
||||
permissionManager.remove(gPermURI.host, aPartId);
|
||||
if (aPartId == "indexedDB") {
|
||||
permissionManager.remove(gPermURI.host, "indexedDB-unlimited");
|
||||
}
|
||||
command.setAttribute("disabled", "true");
|
||||
var perm = gPermObj[aPartId]();
|
||||
setRadioState(aPartId, perm);
|
||||
|
@ -171,7 +168,8 @@ function onRadioClick(aPartId)
|
|||
var id = radioGroup.selectedItem.id;
|
||||
var permission = id.split('#')[1];
|
||||
permissionManager.add(gPermURI, aPartId, permission);
|
||||
if (aPartId == "indexedDB" && permission == BLOCK) {
|
||||
if (aPartId == "indexedDB" &&
|
||||
(permission == ALLOW || permission == BLOCK)) {
|
||||
permissionManager.remove(gPermURI.host, "indexedDB-unlimited");
|
||||
}
|
||||
if (aPartId == "fullscreen" && permission == UNKNOWN) {
|
||||
|
@ -207,7 +205,6 @@ function onIndexedDBClear()
|
|||
|
||||
var permissionManager = Components.classes[PERMISSION_CONTRACTID]
|
||||
.getService(nsIPermissionManager);
|
||||
permissionManager.remove(gPermURI.host, "indexedDB");
|
||||
permissionManager.remove(gPermURI.host, "indexedDB-unlimited");
|
||||
initIndexedDBRow();
|
||||
}
|
||||
|
|
|
@ -1413,10 +1413,9 @@
|
|||
if (tabsToClose <= 1)
|
||||
return true;
|
||||
|
||||
var canDisablePrompt = !!aAll;
|
||||
const pref = "browser.tabs.warnOnClose";
|
||||
var shouldPrompt = Services.prefs.getBoolPref(pref);
|
||||
|
||||
if (!shouldPrompt)
|
||||
if (canDisablePrompt && !Services.prefs.getBoolPref(pref))
|
||||
return true;
|
||||
|
||||
var ps = Services.prompt;
|
||||
|
@ -1440,11 +1439,13 @@
|
|||
+ (ps.BUTTON_TITLE_CANCEL * ps.BUTTON_POS_1),
|
||||
bundle.getString("tabs.closeButtonMultiple"),
|
||||
null, null,
|
||||
bundle.getString('tabs.closeWarningPromptMe'),
|
||||
canDisablePrompt ?
|
||||
bundle.getString("tabs.closeWarningPromptMe") : null,
|
||||
warnOnClose);
|
||||
var reallyClose = (buttonPressed == 0);
|
||||
|
||||
// don't set the pref unless they press OK and it's false
|
||||
if (reallyClose && !warnOnClose.value)
|
||||
if (canDisablePrompt && reallyClose && !warnOnClose.value)
|
||||
Services.prefs.setBoolPref(pref, false);
|
||||
|
||||
return reallyClose;
|
||||
|
|
|
@ -153,6 +153,7 @@ _BROWSER_FILES = \
|
|||
browser_bug743421.js \
|
||||
browser_bug749738.js \
|
||||
browser_bug763468.js \
|
||||
browser_bug767836.js \
|
||||
browser_canonizeURL.js \
|
||||
browser_customize.js \
|
||||
browser_findbarClose.js \
|
||||
|
|
|
@ -11,12 +11,12 @@ function test() {
|
|||
|
||||
var newWindow;
|
||||
var tabToDetach;
|
||||
var documentToDetach;
|
||||
|
||||
function onPageShow(event) {
|
||||
// we get here if the test is executed before the pageshow
|
||||
// event for the window's first tab
|
||||
if (!tabToDetach ||
|
||||
tabToDetach.linkedBrowser.contentDocument != event.target)
|
||||
if (!tabToDetach || documentToDetach != event.target)
|
||||
return;
|
||||
|
||||
event.currentTarget.removeEventListener("pageshow", onPageShow, false);
|
||||
|
@ -46,6 +46,10 @@ function test() {
|
|||
finish();
|
||||
}
|
||||
|
||||
gBrowser.addEventListener("pageshow", onPageShow, false);
|
||||
tabToDetach = gBrowser.addTab(testPage);
|
||||
tabToDetach.linkedBrowser.addEventListener("load", function onLoad() {
|
||||
tabToDetach.linkedBrowser.removeEventListener("load", onLoad, true);
|
||||
documentToDetach = tabToDetach.linkedBrowser.contentDocument;
|
||||
gBrowser.addEventListener("pageshow", onPageShow, false);
|
||||
}, true);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/* 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/. */
|
||||
|
||||
// initialization
|
||||
const pb = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
const PREF = "browser.newtab.url";
|
||||
const NEWTABURL = Services.prefs.getCharPref(PREF) || "about:blank";
|
||||
const TESTURL = "http://example.com/";
|
||||
|
||||
function test() {
|
||||
|
||||
waitForExplicitFinish();
|
||||
// check whether the mode that we start off with is normal or not
|
||||
ok(!pb.privateBrowsingEnabled, "private browsing is disabled");
|
||||
// check whether any custom new tab url has been configured
|
||||
ok(!Services.prefs.prefHasUserValue(PREF), "No custom newtab url is set");
|
||||
|
||||
openNewTab(function () {
|
||||
// Check the new tab opened while in normal mode
|
||||
is(gBrowser.selectedBrowser.currentURI.spec, NEWTABURL,
|
||||
"URL of NewTab should be browser.newtab.url in Normal mode");
|
||||
// Set the custom newtab url
|
||||
Services.prefs.setCharPref(PREF, TESTURL);
|
||||
ok(Services.prefs.prefHasUserValue(PREF), "Custom newtab url is set");
|
||||
|
||||
// Open a newtab after setting the custom newtab url
|
||||
openNewTab(function () {
|
||||
is(gBrowser.selectedBrowser.currentURI.spec, TESTURL,
|
||||
"URL of NewTab should be the custom url");
|
||||
|
||||
// clear the custom url preference
|
||||
Services.prefs.clearUserPref(PREF);
|
||||
ok(!Services.prefs.prefHasUserValue(PREF), "No custom newtab url is set");
|
||||
|
||||
// enter private browsing mode
|
||||
togglePrivateBrowsing(function () {
|
||||
ok(pb.privateBrowsingEnabled, "private browsing is enabled");
|
||||
|
||||
// Open a new tab page in private browsing mode
|
||||
openNewTab(function () {
|
||||
// Check the new tab opened while in private browsing mode
|
||||
is(gBrowser.selectedBrowser.currentURI.spec, "about:privatebrowsing",
|
||||
"URL of NewTab should be about:privatebrowsing in PB mode");
|
||||
|
||||
Services.prefs.setCharPref(PREF, TESTURL);
|
||||
ok(Services.prefs.prefHasUserValue(PREF), "Custom newtab url is set");
|
||||
|
||||
// Open a newtab after setting the custom newtab url
|
||||
openNewTab(function () {
|
||||
is(gBrowser.selectedBrowser.currentURI.spec, TESTURL,
|
||||
"URL of NewTab should be the custom url");
|
||||
|
||||
Services.prefs.clearUserPref(PREF);
|
||||
ok(!Services.prefs.prefHasUserValue(PREF), "No custom newtab url is set");
|
||||
|
||||
// exit private browsing mode
|
||||
togglePrivateBrowsing(function () {
|
||||
ok(!pb.privateBrowsingEnabled, "private browsing is disabled");
|
||||
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function togglePrivateBrowsing(aCallback) {
|
||||
let topic = "private-browsing-transition-complete";
|
||||
|
||||
Services.obs.addObserver(function observe() {
|
||||
Services.obs.removeObserver(observe, topic);
|
||||
executeSoon(aCallback);
|
||||
}, topic, false);
|
||||
|
||||
pb.privateBrowsingEnabled = !pb.privateBrowsingEnabled;
|
||||
}
|
||||
|
||||
function openNewTab(aCallback) {
|
||||
// Open a new tab
|
||||
BrowserOpenTab();
|
||||
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
executeSoon(aCallback);
|
||||
}, true);
|
||||
}
|
|
@ -16,6 +16,7 @@ _BROWSER_FILES = \
|
|||
browser_newtab_disable.js \
|
||||
browser_newtab_drag_drop.js \
|
||||
browser_newtab_drop_preview.js \
|
||||
browser_newtab_focus.js \
|
||||
browser_newtab_private_browsing.js \
|
||||
browser_newtab_reset.js \
|
||||
browser_newtab_tabsync.js \
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
function runTests() {
|
||||
// we remove sites and expect the gaps to be filled as long as there still
|
||||
// are some sites available
|
||||
setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||
setPinnedLinks("");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -26,7 +26,7 @@ function runTests() {
|
|||
|
||||
// we removed a pinned site
|
||||
yield restore();
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks(",1");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -38,7 +38,7 @@ function runTests() {
|
|||
// we remove the last site on the grid (which is pinned) and expect the gap
|
||||
// to be re-filled and the new site to be unpinned
|
||||
yield restore();
|
||||
setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||
setPinnedLinks(",,,,,,,,8");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -50,7 +50,7 @@ function runTests() {
|
|||
// we remove the first site on the grid with the last one pinned. all cells
|
||||
// but the last one should shift to the left and a new site fades in
|
||||
yield restore();
|
||||
setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||
setPinnedLinks(",,,,,,,,8");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
|
|
@ -2,19 +2,19 @@
|
|||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function runTests() {
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
NewTabUtils.pinnedLinks._links = [
|
||||
{url: "about:blank#7", title: ""},
|
||||
{url: "about:blank#8", title: "title"},
|
||||
{url: "about:blank#9", title: "about:blank#9"}
|
||||
];
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks([
|
||||
{url: "http://example.com/#7", title: ""},
|
||||
{url: "http://example.com/#8", title: "title"},
|
||||
{url: "http://example.com/#9", title: "http://example.com/#9"}
|
||||
]);
|
||||
|
||||
yield addNewTabPageTab();
|
||||
checkGrid("7p,8p,9p,0,1,2,3,4,5");
|
||||
|
||||
checkTooltip(0, "about:blank#7", "1st tooltip is correct");
|
||||
checkTooltip(1, "title\nabout:blank#8", "2nd tooltip is correct");
|
||||
checkTooltip(2, "about:blank#9", "3rd tooltip is correct");
|
||||
checkTooltip(0, "http://example.com/#7", "1st tooltip is correct");
|
||||
checkTooltip(1, "title\nhttp://example.com/#8", "2nd tooltip is correct");
|
||||
checkTooltip(2, "http://example.com/#9", "3rd tooltip is correct");
|
||||
}
|
||||
|
||||
function checkTooltip(aIndex, aExpected, aMessage) {
|
||||
|
|
|
@ -5,30 +5,26 @@ const NOW = Date.now() * 1000;
|
|||
const URL = "http://fake-site.com/";
|
||||
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/NewTabUtils.jsm", tmp);
|
||||
Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader)
|
||||
.loadSubScript("chrome://browser/content/sanitize.js", tmp);
|
||||
|
||||
let {NewTabUtils, Sanitizer} = tmp;
|
||||
|
||||
let bhist = Cc["@mozilla.org/browser/global-history;2"]
|
||||
.getService(Ci.nsIBrowserHistory);
|
||||
let {Sanitizer} = tmp;
|
||||
|
||||
function runTests() {
|
||||
clearHistory();
|
||||
yield fillHistory();
|
||||
sanitizeHistory();
|
||||
yield addFakeVisits();
|
||||
yield addNewTabPageTab();
|
||||
|
||||
is(getCell(0).site.url, URL, "first site is our fake site");
|
||||
|
||||
whenPagesUpdated();
|
||||
yield clearHistory();
|
||||
yield sanitizeHistory();
|
||||
|
||||
ok(!getCell(0).site, "the fake site is gone");
|
||||
}
|
||||
|
||||
function fillHistory() {
|
||||
function addFakeVisits() {
|
||||
let visits = [];
|
||||
for (let i = 59; i > 0; i--) {
|
||||
visits.push({
|
||||
|
@ -42,13 +38,18 @@ function fillHistory() {
|
|||
visits: visits
|
||||
};
|
||||
PlacesUtils.asyncHistory.updatePlaces(place, {
|
||||
handleError: function () do_throw("Unexpected error in adding visit."),
|
||||
handleResult: function () { },
|
||||
handleCompletion: function () TestRunner.next()
|
||||
handleError: function () ok(false, "couldn't add visit"),
|
||||
handleResult: function () {},
|
||||
handleCompletion: function () {
|
||||
NewTabUtils.links.populateCache(function () {
|
||||
NewTabUtils.allPages.update();
|
||||
TestRunner.next();
|
||||
}, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function clearHistory() {
|
||||
function sanitizeHistory() {
|
||||
let s = new Sanitizer();
|
||||
s.prefDomain = "privacy.cpd.";
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
function runTests() {
|
||||
// create a new tab page and hide it.
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -12,7 +12,7 @@ function runTests() {
|
|||
yield addNewTabPageTab();
|
||||
gBrowser.removeTab(firstTab);
|
||||
|
||||
ok(NewTabUtils.allPages.enabled, true, "page is enabled");
|
||||
ok(NewTabUtils.allPages.enabled, "page is enabled");
|
||||
NewTabUtils.allPages.enabled = false;
|
||||
ok(getGrid().node.hasAttribute("page-disabled"), "page is disabled");
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function runTests() {
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function runTests() {
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -10,14 +10,14 @@ function runTests() {
|
|||
|
||||
let cell = getCell(0).node;
|
||||
|
||||
sendDragEvent("drop", cell, "about:blank#99\nblank");
|
||||
is(NewTabUtils.pinnedLinks.links[0].url, "about:blank#99",
|
||||
sendDragEvent("drop", cell, "http://example.com/#99\nblank");
|
||||
is(NewTabUtils.pinnedLinks.links[0].url, "http://example.com/#99",
|
||||
"first cell is pinned and contains the dropped site");
|
||||
|
||||
yield whenPagesUpdated();
|
||||
checkGrid("99p,0,1,2,3,4,5,6,7");
|
||||
|
||||
sendDragEvent("drop", cell, "");
|
||||
is(NewTabUtils.pinnedLinks.links[0].url, "about:blank#99",
|
||||
is(NewTabUtils.pinnedLinks.links[0].url, "http://example.com/#99",
|
||||
"first cell is still pinned with the site we dropped before");
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function runTests() {
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function runTests() {
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
function runTests() {
|
||||
// create a new tab page and hide it.
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
*/
|
||||
function runTests() {
|
||||
// test a simple drag-and-drop scenario
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -19,7 +19,7 @@ function runTests() {
|
|||
checkGrid("1,0p,2,3,4,5,6,7,8");
|
||||
|
||||
// drag a cell to its current cell and make sure it's not pinned afterwards
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -29,7 +29,7 @@ function runTests() {
|
|||
checkGrid("0,1,2,3,4,5,6,7,8");
|
||||
|
||||
// ensure that pinned pages aren't moved if that's not necessary
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks(",1,2");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -40,7 +40,7 @@ function runTests() {
|
|||
|
||||
// pinned sites should always be moved around as blocks. if a pinned site is
|
||||
// moved around, neighboring pinned are affected as well
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("0,1");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -51,7 +51,7 @@ function runTests() {
|
|||
|
||||
// pinned sites should not be pushed out of the grid (unless there are only
|
||||
// pinned ones left on the grid)
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks(",,,,,,,7,8");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -61,7 +61,7 @@ function runTests() {
|
|||
checkGrid("0,1,3,4,5,6,7p,8p,2p");
|
||||
|
||||
// make sure that pinned sites are re-positioned correctly
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("0,1,2,,,5");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -71,7 +71,7 @@ function runTests() {
|
|||
checkGrid("3,1p,2p,4,0p,5p,6,7,8");
|
||||
|
||||
// drag a new site onto the very first cell
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks(",,,,,,,7,8");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -82,7 +82,7 @@ function runTests() {
|
|||
|
||||
// drag a new site onto the grid and make sure that pinned cells don't get
|
||||
// pushed out
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks(",,,,,,,7,8");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -93,7 +93,7 @@ function runTests() {
|
|||
|
||||
// drag a new site beneath a pinned cell and make sure the pinned cell is
|
||||
// not moved
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks(",,,,,,,,8");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -104,7 +104,7 @@ function runTests() {
|
|||
|
||||
// drag a new site onto a block of pinned sites and make sure they're shifted
|
||||
// around accordingly
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("0,1,2,,,,,,");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
function runTests() {
|
||||
// the first three sites are pinned - make sure they're re-arranged correctly
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("0,1,2,,,5");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*
|
||||
* These tests make sure that focusing the 'New Tage Page' works as expected.
|
||||
*/
|
||||
function runTests() {
|
||||
// Focus count in new tab page.
|
||||
// 28 = 9 * 3 + 1 = 9 sites and 1 toggle button, each site has a link, a pin
|
||||
// and a remove button.
|
||||
let FOCUS_COUNT = 28;
|
||||
if ("nsILocalFileMac" in Ci) {
|
||||
// 19 = Mac doesn't focus links, so 9 focus targets less than Windows/Linux.
|
||||
FOCUS_COUNT = 19;
|
||||
}
|
||||
|
||||
// Create a new tab page.
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
gURLBar.focus();
|
||||
|
||||
// Count the focus with the enabled page.
|
||||
yield countFocus(FOCUS_COUNT);
|
||||
|
||||
// Disable page and count the focus with the disabled page.
|
||||
NewTabUtils.allPages.enabled = false;
|
||||
yield countFocus(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus the urlbar and count how many focus stops to return again to the urlbar.
|
||||
*/
|
||||
function countFocus(aExpectedCount) {
|
||||
let focusCount = 0;
|
||||
let contentDoc = getContentDocument();
|
||||
|
||||
window.addEventListener("focus", function onFocus() {
|
||||
let focusedElement = document.commandDispatcher.focusedElement;
|
||||
if (focusedElement && focusedElement.classList.contains("urlbar-input")) {
|
||||
window.removeEventListener("focus", onFocus, true);
|
||||
is(focusCount, aExpectedCount, "Validate focus count in the new tab page.");
|
||||
executeSoon(TestRunner.next);
|
||||
} else {
|
||||
if (focusedElement && focusedElement.ownerDocument == contentDoc &&
|
||||
focusedElement instanceof HTMLElement) {
|
||||
focusCount++;
|
||||
}
|
||||
document.commandDispatcher.advanceFocus();
|
||||
}
|
||||
}, true);
|
||||
|
||||
document.commandDispatcher.advanceFocus();
|
||||
}
|
|
@ -12,7 +12,7 @@ let pb = Cc["@mozilla.org/privatebrowsing;1"]
|
|||
|
||||
function runTests() {
|
||||
// prepare the grid
|
||||
setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||
ok(!pb.privateBrowsingEnabled, "private browsing is disabled");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
|
|
@ -9,7 +9,7 @@ function runTests() {
|
|||
return;
|
||||
|
||||
// create a new tab page and check its modified state after blocking a site
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
|
|
@ -11,7 +11,7 @@ function runTests() {
|
|||
// Disabled until bug 716543 is fixed.
|
||||
return;
|
||||
|
||||
setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||
setPinnedLinks(",1");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
function runTests() {
|
||||
// we have a pinned link that didn't change its position since it was pinned.
|
||||
// nothing should happend when we unpin it.
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks(",1");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -20,7 +20,7 @@ function runTests() {
|
|||
// we have a pinned link that is not anymore in the list of the most-visited
|
||||
// links. this should disappear, the remaining links adjust their positions
|
||||
// and a new link will appear at the end of the grid.
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks(",99");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -31,7 +31,7 @@ function runTests() {
|
|||
|
||||
// we have a pinned link that changed its position since it was pinned. it
|
||||
// should be moved to its new position after being unpinned.
|
||||
setLinks("0,1,2,3,4,5,6,7");
|
||||
yield setLinks("0,1,2,3,4,5,6,7");
|
||||
setPinnedLinks(",1,,,,,,,0");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
@ -45,7 +45,7 @@ function runTests() {
|
|||
|
||||
// we have pinned link that changed its position since it was pinned. the
|
||||
// link will disappear from the grid because it's now a much lower priority
|
||||
setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||
yield setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||
setPinnedLinks("9");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
|
|
|
@ -7,7 +7,17 @@ Services.prefs.setBoolPref(PREF_NEWTAB_ENABLED, true);
|
|||
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/NewTabUtils.jsm", tmp);
|
||||
let NewTabUtils = tmp.NewTabUtils;
|
||||
Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader)
|
||||
.loadSubScript("chrome://browser/content/sanitize.js", tmp);
|
||||
|
||||
let {NewTabUtils, Sanitizer} = tmp;
|
||||
|
||||
let uri = Services.io.newURI("about:newtab", null, null);
|
||||
let principal = Services.scriptSecurityManager.getCodebasePrincipal(uri);
|
||||
|
||||
let sm = Services.domStorageManager;
|
||||
let storage = sm.getLocalStorageForPrincipal(principal, "");
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
while (gBrowser.tabs.length > 1)
|
||||
|
@ -16,11 +26,6 @@ registerCleanupFunction(function () {
|
|||
Services.prefs.clearUserPref(PREF_NEWTAB_ENABLED);
|
||||
});
|
||||
|
||||
/**
|
||||
* We'll want to restore the original links provider later.
|
||||
*/
|
||||
let originalProvider = NewTabUtils.links._provider;
|
||||
|
||||
/**
|
||||
* Provide the default test function to start our test runner.
|
||||
*/
|
||||
|
@ -58,9 +63,7 @@ let TestRunner = {
|
|||
*/
|
||||
finish: function () {
|
||||
function cleanupAndFinish() {
|
||||
// Restore the old provider.
|
||||
NewTabUtils.links._provider = originalProvider;
|
||||
|
||||
clearHistory();
|
||||
whenPagesUpdated(finish);
|
||||
NewTabUtils.restore();
|
||||
}
|
||||
|
@ -113,17 +116,52 @@ function getCell(aIndex) {
|
|||
* @param aLinksPattern the pattern (see below)
|
||||
*
|
||||
* Example: setLinks("1,2,3")
|
||||
* Result: [{url: "about:blank#1", title: "site#1"},
|
||||
* {url: "about:blank#2", title: "site#2"}
|
||||
* {url: "about:blank#3", title: "site#3"}]
|
||||
* Result: [{url: "http://example.com/#1", title: "site#1"},
|
||||
* {url: "http://example.com/#2", title: "site#2"}
|
||||
* {url: "http://example.com/#3", title: "site#3"}]
|
||||
*/
|
||||
function setLinks(aLinksPattern) {
|
||||
let links = aLinksPattern.split(/\s*,\s*/).map(function (id) {
|
||||
return {url: "about:blank#" + id, title: "site#" + id};
|
||||
});
|
||||
function setLinks(aLinks) {
|
||||
let links = aLinks;
|
||||
|
||||
NewTabUtils.links._provider = {getLinks: function (c) c(links)};
|
||||
NewTabUtils.links._links = links;
|
||||
if (typeof links == "string") {
|
||||
links = aLinks.split(/\s*,\s*/).map(function (id) {
|
||||
return {url: "http://example.com/#" + id, title: "site#" + id};
|
||||
});
|
||||
}
|
||||
|
||||
clearHistory();
|
||||
fillHistory(links, function () {
|
||||
NewTabUtils.links.populateCache(function () {
|
||||
NewTabUtils.allPages.update();
|
||||
TestRunner.next();
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
|
||||
function clearHistory() {
|
||||
PlacesUtils.history.removeAllPages();
|
||||
}
|
||||
|
||||
function fillHistory(aLinks, aCallback) {
|
||||
let numLinks = aLinks.length;
|
||||
let transitionLink = Ci.nsINavHistoryService.TRANSITION_LINK;
|
||||
|
||||
for (let link of aLinks.reverse()) {
|
||||
let place = {
|
||||
uri: makeURI(link.url),
|
||||
title: link.title,
|
||||
visits: [{visitDate: Date.now() * 1000, transitionType: transitionLink}]
|
||||
};
|
||||
|
||||
PlacesUtils.asyncHistory.updatePlaces(place, {
|
||||
handleError: function () ok(false, "couldn't add visit to history"),
|
||||
handleResult: function () {},
|
||||
handleCompletion: function () {
|
||||
if (--numLinks == 0)
|
||||
aCallback();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,23 +170,22 @@ function setLinks(aLinksPattern) {
|
|||
* @param aLinksPattern the pattern (see below)
|
||||
*
|
||||
* Example: setPinnedLinks("3,,1")
|
||||
* Result: 'about:blank#3' is pinned in the first cell. 'about:blank#1' is
|
||||
* Result: 'http://example.com/#3' is pinned in the first cell. 'http://example.com/#1' is
|
||||
* pinned in the third cell.
|
||||
*/
|
||||
function setPinnedLinks(aLinksPattern) {
|
||||
let pinnedLinks = [];
|
||||
function setPinnedLinks(aLinks) {
|
||||
let links = aLinks;
|
||||
|
||||
aLinksPattern.split(/\s*,\s*/).forEach(function (id, index) {
|
||||
let link;
|
||||
if (typeof links == "string") {
|
||||
links = aLinks.split(/\s*,\s*/).map(function (id) {
|
||||
if (id)
|
||||
return {url: "http://example.com/#" + id, title: "site#" + id};
|
||||
});
|
||||
}
|
||||
|
||||
if (id)
|
||||
link = {url: "about:blank#" + id, title: "site#" + id};
|
||||
|
||||
pinnedLinks[index] = link;
|
||||
});
|
||||
|
||||
// Inject the list of pinned links to work with.
|
||||
NewTabUtils.pinnedLinks._links = pinnedLinks;
|
||||
storage.setItem("pinnedLinks", JSON.stringify(links));
|
||||
NewTabUtils.pinnedLinks.resetCache();
|
||||
NewTabUtils.allPages.update();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -187,9 +224,9 @@ function addNewTabPageTab() {
|
|||
* @param the array of sites to compare with (optional)
|
||||
*
|
||||
* Example: checkGrid("3p,2,,1p")
|
||||
* Result: We expect the first cell to contain the pinned site 'about:blank#3'.
|
||||
* The second cell contains 'about:blank#2'. The third cell is empty.
|
||||
* The fourth cell contains the pinned site 'about:blank#4'.
|
||||
* Result: We expect the first cell to contain the pinned site 'http://example.com/#3'.
|
||||
* The second cell contains 'http://example.com/#2'. The third cell is empty.
|
||||
* The fourth cell contains the pinned site 'http://example.com/#4'.
|
||||
*/
|
||||
function checkGrid(aSitesPattern, aSites) {
|
||||
let length = aSitesPattern.split(",").length;
|
||||
|
@ -205,7 +242,7 @@ function checkGrid(aSitesPattern, aSites) {
|
|||
if (pinned != hasPinnedAttr)
|
||||
ok(false, "invalid state (site.isPinned() != site[pinned])");
|
||||
|
||||
return aSite.url.replace(/^about:blank#(\d+)$/, "$1") + (pinned ? "p" : "");
|
||||
return aSite.url.replace(/^http:\/\/example\.com\/#(\d+)$/, "$1") + (pinned ? "p" : "");
|
||||
});
|
||||
|
||||
is(current, aSitesPattern, "grid status = " + aSitesPattern);
|
||||
|
@ -246,7 +283,7 @@ function unpinCell(aIndex) {
|
|||
function simulateDrop(aDropIndex, aDragIndex) {
|
||||
let draggedSite;
|
||||
let {gDrag: drag, gDrop: drop} = getContentWindow();
|
||||
let event = createDragEvent("drop", "about:blank#99\nblank");
|
||||
let event = createDragEvent("drop", "http://example.com/#99\nblank");
|
||||
|
||||
if (typeof aDragIndex != "undefined")
|
||||
draggedSite = getCell(aDragIndex).site;
|
||||
|
|
|
@ -272,11 +272,9 @@ function runTest(testNum) {
|
|||
plainTextItems = ["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-stop", false,
|
||||
"---", null,
|
||||
"context-bookmarkpage", true,
|
||||
"context-savepage", true,
|
||||
"context-sendpage", true,
|
||||
"---", null,
|
||||
"context-viewbgimage", false,
|
||||
"context-selectall", true,
|
||||
|
@ -296,7 +294,6 @@ function runTest(testNum) {
|
|||
"---", null,
|
||||
"context-bookmarklink", true,
|
||||
"context-savelink", true,
|
||||
"context-sendlink", true,
|
||||
"context-copylink", true
|
||||
].concat(inspectItems));
|
||||
closeContextMenu();
|
||||
|
@ -430,11 +427,9 @@ function runTest(testNum) {
|
|||
checkContextMenu(["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-stop", false,
|
||||
"---", null,
|
||||
"context-bookmarkpage", true,
|
||||
"context-savepage", true,
|
||||
"context-sendpage", true,
|
||||
"---", null,
|
||||
"context-viewbgimage", false,
|
||||
"context-selectall", true,
|
||||
|
@ -656,11 +651,9 @@ function runTest(testNum) {
|
|||
"context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-stop", false,
|
||||
"---", null,
|
||||
"context-bookmarkpage", true,
|
||||
"context-savepage", true,
|
||||
"context-sendpage", true,
|
||||
"---", null,
|
||||
"context-viewbgimage", false,
|
||||
"context-selectall", true,
|
||||
|
@ -691,11 +684,9 @@ function runTest(testNum) {
|
|||
"context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-stop", false,
|
||||
"---", null,
|
||||
"context-bookmarkpage", true,
|
||||
"context-savepage", true,
|
||||
"context-sendpage", true,
|
||||
"---", null,
|
||||
"context-viewbgimage", false,
|
||||
"context-selectall", true,
|
||||
|
@ -721,11 +712,9 @@ function runTest(testNum) {
|
|||
checkContextMenu(["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-stop", false,
|
||||
"---", null,
|
||||
"context-bookmarkpage", true,
|
||||
"context-savepage", true,
|
||||
"context-sendpage", true,
|
||||
"---", null,
|
||||
"context-viewbgimage", false,
|
||||
"context-selectall", true,
|
||||
|
@ -764,7 +753,6 @@ function runTest(testNum) {
|
|||
"---", null,
|
||||
"context-bookmarklink", true,
|
||||
"context-savelink", true,
|
||||
"context-sendlink", true,
|
||||
"context-copy", true,
|
||||
"context-selectall", true,
|
||||
"---", null,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
# -*- Mode: javascript; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
# 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/.
|
||||
|
@ -12,10 +12,17 @@ XPCOMUtils.defineLazyGetter(this, "BROWSER_NEW_TAB_URL", function () {
|
|||
const TOPIC = "private-browsing-transition-complete";
|
||||
|
||||
function getNewTabPageURL() {
|
||||
if (("gPrivateBrowsingUI" in window) && gPrivateBrowsingUI.privateWindow)
|
||||
return "about:privatebrowsing";
|
||||
else
|
||||
return Services.prefs.getCharPref(PREF) || "about:blank";
|
||||
if (("gPrivateBrowsingUI" in window) &&
|
||||
!Services.prefs.prefHasUserValue(PREF)) {
|
||||
// gPrivateBrowsingUI may not be initialized yet, in that case we'll
|
||||
// update BROWSER_NEW_TAB_URL when it gets initialized.
|
||||
if (!gPrivateBrowsingUI.initialized)
|
||||
gPrivateBrowsingUI.addInitializationCallback(update);
|
||||
else if (gPrivateBrowsingUI.privateWindow &&
|
||||
!gPrivateBrowsingUI.autoStarted)
|
||||
return "about:privatebrowsing";
|
||||
}
|
||||
return Services.prefs.getCharPref(PREF) || "about:blank";
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsIFile.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#define NS_BROWSERDIRECTORYPROVIDER_CONTRACTID \
|
||||
"@mozilla.org/browser/directory-provider;1"
|
||||
|
@ -16,7 +17,7 @@
|
|||
namespace mozilla {
|
||||
namespace browser {
|
||||
|
||||
class DirectoryProvider : public nsIDirectoryServiceProvider2
|
||||
class DirectoryProvider MOZ_FINAL : public nsIDirectoryServiceProvider2
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -24,7 +25,7 @@ public:
|
|||
NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
|
||||
|
||||
private:
|
||||
class AppendingEnumerator : public nsISimpleEnumerator
|
||||
class AppendingEnumerator MOZ_FINAL : public nsISimpleEnumerator
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
|
|
@ -51,7 +51,7 @@ const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
|
|||
const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
|
||||
const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
|
||||
const URI_BUNDLE = "chrome://browser/locale/feeds/subscribe.properties";
|
||||
const SUBSCRIBE_PAGE_URI = "chrome://browser/content/feeds/subscribe.xhtml";
|
||||
const FEEDHANDLER_URI = "about:feeds";
|
||||
|
||||
const PREF_SELECTED_APP = "browser.feeds.handlers.application";
|
||||
const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
|
||||
|
@ -673,7 +673,7 @@ FeedWriter.prototype = {
|
|||
*/
|
||||
_getFileIconURL: function FW__getFileIconURL(file) {
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Components.interfaces.nsIIOService);
|
||||
getService(Ci.nsIIOService);
|
||||
var fph = ios.getProtocolHandler("file")
|
||||
.QueryInterface(Ci.nsIFileProtocolHandler);
|
||||
var urlSpec = fph.getURLSpecFromFile(file);
|
||||
|
@ -1089,10 +1089,9 @@ FeedWriter.prototype = {
|
|||
getInterface(Ci.nsIWebNavigation).
|
||||
QueryInterface(Ci.nsIDocShell).currentDocumentChannel;
|
||||
|
||||
var uri = makeURI(SUBSCRIBE_PAGE_URI);
|
||||
var resolvedURI = Cc["@mozilla.org/chrome/chrome-registry;1"].
|
||||
getService(Ci.nsIChromeRegistry).
|
||||
convertChromeURL(uri);
|
||||
var resolvedURI = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService).
|
||||
newChannel(FEEDHANDLER_URI, null, null).URI;
|
||||
|
||||
if (resolvedURI.equals(chan.URI))
|
||||
return chan.originalURI;
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
#include "nsIContentSniffer.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsStringAPI.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
class nsFeedSniffer : public nsIContentSniffer, nsIStreamListener
|
||||
class nsFeedSniffer MOZ_FINAL : public nsIContentSniffer,
|
||||
nsIStreamListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
|
|
@ -5,11 +5,12 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsIPrivateBrowsingService.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
class nsIJSContextStack;
|
||||
|
||||
class nsPrivateBrowsingServiceWrapper : public nsIPrivateBrowsingService,
|
||||
public nsIObserver
|
||||
class nsPrivateBrowsingServiceWrapper MOZ_FINAL : public nsIPrivateBrowsingService,
|
||||
public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
|
|
@ -12,8 +12,6 @@ function test() {
|
|||
waitForExplicitFinish();
|
||||
|
||||
let tabBlank = gBrowser.selectedTab;
|
||||
gBrowser.removeAllTabsBut(tabBlank);
|
||||
|
||||
let blankBrowser = gBrowser.getBrowserForTab(tabBlank);
|
||||
blankBrowser.addEventListener("load", function() {
|
||||
blankBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
|
|
@ -2823,6 +2823,108 @@ let SessionStoreInternal = {
|
|||
this._sendRestoreCompletedNotifications();
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the tabs restoring order with the following priority:
|
||||
* Selected tab, pinned tabs, visible tabs, unhidden tabs and hidden tabs.
|
||||
* @param aTabBrowser
|
||||
* Tab browser object
|
||||
* @param aTabs
|
||||
* Array of tab references
|
||||
* @param aTabData
|
||||
* Array of tab data
|
||||
* @param aSelectedTab
|
||||
* Index of selected tab
|
||||
*/
|
||||
_setTabsRestoringOrder : function ssi__setTabsRestoringOrder(
|
||||
aTabBrowser, aTabs, aTabData, aSelectedTab) {
|
||||
// Temporally store the pinned tabs before moving the hidden tabs and
|
||||
// optimizing the visible tabs. In case the selected tab is a pinned tab,
|
||||
// the index is also stored.
|
||||
let pinnedTabs = aTabData.filter(function (aData) aData.pinned).length;
|
||||
let pinnedTabsArray = [];
|
||||
let pinnedTabsDataArray = [];
|
||||
let pinnedSelectedTab = null;
|
||||
if (pinnedTabs && aTabs.length > 1) {
|
||||
for (let t = aTabs.length - 1; t >= 0; t--) {
|
||||
if (aTabData[t].pinned) {
|
||||
pinnedTabsArray.unshift(aTabs.splice(t, 1)[0]);
|
||||
pinnedTabsDataArray.unshift(aTabData.splice(t, 1)[0]);
|
||||
if (aSelectedTab) {
|
||||
if (aSelectedTab > (t + 1))
|
||||
--aSelectedTab;
|
||||
else if (aSelectedTab == (t + 1)) {
|
||||
aSelectedTab = null;
|
||||
pinnedSelectedTab = 1;
|
||||
}
|
||||
} else if (pinnedSelectedTab)
|
||||
++pinnedSelectedTab;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Without the pinned tabs, we move the hidden tabs to the end of the list
|
||||
// and optimize the visible tabs.
|
||||
let unhiddenTabs = aTabData.filter(function (aData) !aData.hidden).length;
|
||||
if (unhiddenTabs && aTabs.length > 1) {
|
||||
// Load hidden tabs last, by pushing them to the end of the list.
|
||||
for (let t = 0, tabsToReorder = aTabs.length - unhiddenTabs; tabsToReorder > 0; ) {
|
||||
if (aTabData[t].hidden) {
|
||||
aTabs = aTabs.concat(aTabs.splice(t, 1));
|
||||
aTabData = aTabData.concat(aTabData.splice(t, 1));
|
||||
if (aSelectedTab && aSelectedTab > t)
|
||||
--aSelectedTab;
|
||||
--tabsToReorder;
|
||||
continue;
|
||||
}
|
||||
++t;
|
||||
}
|
||||
|
||||
// Determine if we can optimize & load visible tabs first
|
||||
let maxVisibleTabs = Math.ceil(aTabBrowser.tabContainer.mTabstrip.scrollClientSize /
|
||||
aTabs[unhiddenTabs - 1].getBoundingClientRect().width);
|
||||
|
||||
// Make sure we restore visible tabs first, if there are enough
|
||||
if (aSelectedTab && maxVisibleTabs < unhiddenTabs && aSelectedTab > 1) {
|
||||
let firstVisibleTab = 0;
|
||||
if (unhiddenTabs - maxVisibleTabs > aSelectedTab) {
|
||||
// aSelectedTab is leftmost since we scroll to it when possible
|
||||
firstVisibleTab = aSelectedTab - 1;
|
||||
} else {
|
||||
// aSelectedTab is rightmost or no more room to scroll right
|
||||
firstVisibleTab = unhiddenTabs - maxVisibleTabs;
|
||||
}
|
||||
aTabs = aTabs.splice(firstVisibleTab, maxVisibleTabs).concat(aTabs);
|
||||
aTabData = aTabData.splice(firstVisibleTab, maxVisibleTabs).concat(aTabData);
|
||||
aSelectedTab -= firstVisibleTab;
|
||||
}
|
||||
}
|
||||
|
||||
// Load the pinned tabs at the beginning of the list and restore the
|
||||
// selected tab index.
|
||||
if (pinnedTabsArray) {
|
||||
// Restore the selected tab index.
|
||||
if (pinnedSelectedTab) {
|
||||
aSelectedTab = pinnedSelectedTab;
|
||||
} else {
|
||||
aSelectedTab += pinnedTabsArray.length;
|
||||
}
|
||||
// Load the pinned tabs at the beginning of the list.
|
||||
for (let t = pinnedTabsArray.length - 1; t >= 0; t--) {
|
||||
aTabs.unshift(pinnedTabsArray.splice(t, 1)[0]);
|
||||
aTabData.unshift(pinnedTabsDataArray.splice(t, 1)[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Load the selected tab to the first position.
|
||||
if (aSelectedTab-- && aTabs[aSelectedTab]) {
|
||||
aTabs.unshift(aTabs.splice(aSelectedTab, 1)[0]);
|
||||
aTabData.unshift(aTabData.splice(aSelectedTab, 1)[0]);
|
||||
aTabBrowser.selectedTab = aTabs[0];
|
||||
}
|
||||
|
||||
return [aTabs, aTabData];
|
||||
},
|
||||
|
||||
/**
|
||||
* Manage history restoration for a window
|
||||
* @param aWindow
|
||||
|
@ -2875,48 +2977,9 @@ let SessionStoreInternal = {
|
|||
return;
|
||||
}
|
||||
|
||||
let unhiddenTabs = aTabData.filter(function (aData) !aData.hidden).length;
|
||||
|
||||
if (unhiddenTabs && aTabs.length > 1) {
|
||||
// Load hidden tabs last, by pushing them to the end of the list
|
||||
for (let t = 0, tabsToReorder = aTabs.length - unhiddenTabs; tabsToReorder > 0; ) {
|
||||
if (aTabData[t].hidden) {
|
||||
aTabs = aTabs.concat(aTabs.splice(t, 1));
|
||||
aTabData = aTabData.concat(aTabData.splice(t, 1));
|
||||
if (aSelectTab > t)
|
||||
--aSelectTab;
|
||||
--tabsToReorder;
|
||||
continue;
|
||||
}
|
||||
++t;
|
||||
}
|
||||
|
||||
// Determine if we can optimize & load visible tabs first
|
||||
let maxVisibleTabs = Math.ceil(tabbrowser.tabContainer.mTabstrip.scrollClientSize /
|
||||
aTabs[unhiddenTabs - 1].getBoundingClientRect().width);
|
||||
|
||||
// make sure we restore visible tabs first, if there are enough
|
||||
if (maxVisibleTabs < unhiddenTabs && aSelectTab > 1) {
|
||||
let firstVisibleTab = 0;
|
||||
if (unhiddenTabs - maxVisibleTabs > aSelectTab) {
|
||||
// aSelectTab is leftmost since we scroll to it when possible
|
||||
firstVisibleTab = aSelectTab - 1;
|
||||
} else {
|
||||
// aSelectTab is rightmost or no more room to scroll right
|
||||
firstVisibleTab = unhiddenTabs - maxVisibleTabs;
|
||||
}
|
||||
aTabs = aTabs.splice(firstVisibleTab, maxVisibleTabs).concat(aTabs);
|
||||
aTabData = aTabData.splice(firstVisibleTab, maxVisibleTabs).concat(aTabData);
|
||||
aSelectTab -= firstVisibleTab;
|
||||
}
|
||||
}
|
||||
|
||||
// make sure to restore the selected tab first (if any)
|
||||
if (aSelectTab-- && aTabs[aSelectTab]) {
|
||||
aTabs.unshift(aTabs.splice(aSelectTab, 1)[0]);
|
||||
aTabData.unshift(aTabData.splice(aSelectTab, 1)[0]);
|
||||
tabbrowser.selectedTab = aTabs[0];
|
||||
}
|
||||
// Sets the tabs restoring order.
|
||||
[aTabs, aTabData] =
|
||||
this._setTabsRestoringOrder(tabbrowser, aTabs, aTabData, aSelectTab);
|
||||
|
||||
// Prepare the tabs so that they can be properly restored. We'll pin/unpin
|
||||
// and show/hide tabs as necessary. We'll also set the labels, user typed
|
||||
|
|
|
@ -8,15 +8,23 @@ function test() {
|
|||
requestLongerTimeout(3);
|
||||
|
||||
// builds the tests state based on a few parameters
|
||||
function buildTestState(num, selected, hidden) {
|
||||
let state = { windows: [ { "tabs": [], "selected": selected } ] };
|
||||
function buildTestState(num, selected, hidden, pinned) {
|
||||
let state = { windows: [ { "tabs": [], "selected": selected + 1 } ] };
|
||||
while (num--) {
|
||||
state.windows[0].tabs.push({entries: [{url: "http://example.com/"}]});
|
||||
state.windows[0].tabs.push({
|
||||
entries: [
|
||||
{ url: "http://example.com/?t=" + state.windows[0].tabs.length }
|
||||
]
|
||||
});
|
||||
let i = state.windows[0].tabs.length - 1;
|
||||
if (hidden.length > 0 && i == hidden[0]) {
|
||||
state.windows[0].tabs[i].hidden = true;
|
||||
hidden.splice(0, 1);
|
||||
}
|
||||
if (pinned.length > 0 && i == pinned[0]) {
|
||||
state.windows[0].tabs[i].pinned = true;
|
||||
pinned.splice(0, 1);
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
@ -24,56 +32,128 @@ function test() {
|
|||
let tests = [
|
||||
{ testNum: 1,
|
||||
totalTabs: 13,
|
||||
selectedTab: 1,
|
||||
selectedTab: 0,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [],
|
||||
pinnedTabs: [],
|
||||
order: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
|
||||
},
|
||||
{ testNum: 2,
|
||||
totalTabs: 13,
|
||||
selectedTab: 13,
|
||||
selectedTab: 12,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [],
|
||||
pinnedTabs: [],
|
||||
order: [12, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6]
|
||||
},
|
||||
{ testNum: 3,
|
||||
totalTabs: 13,
|
||||
selectedTab: 4,
|
||||
selectedTab: 3,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [],
|
||||
pinnedTabs: [],
|
||||
order: [3, 4, 5, 6, 7, 8, 0, 1, 2, 9, 10, 11, 12]
|
||||
},
|
||||
{ testNum: 4,
|
||||
totalTabs: 13,
|
||||
selectedTab: 11,
|
||||
selectedTab: 10,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [],
|
||||
pinnedTabs: [],
|
||||
order: [10, 7, 8, 9, 11, 12, 0, 1, 2, 3, 4, 5, 6]
|
||||
},
|
||||
{ testNum: 5,
|
||||
totalTabs: 13,
|
||||
selectedTab: 13,
|
||||
selectedTab: 12,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [0, 4, 9],
|
||||
pinnedTabs: [],
|
||||
order: [12, 6, 7, 8, 10, 11, 1, 2, 3, 5, 0, 4, 9]
|
||||
},
|
||||
{ testNum: 6,
|
||||
totalTabs: 13,
|
||||
selectedTab: 4,
|
||||
selectedTab: 3,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [1, 7, 12],
|
||||
pinnedTabs: [],
|
||||
order: [3, 4, 5, 6, 8, 9, 0, 2, 10, 11, 1, 7, 12]
|
||||
},
|
||||
{ testNum: 7,
|
||||
totalTabs: 13,
|
||||
selectedTab: 4,
|
||||
selectedTab: 3,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [0, 1, 2],
|
||||
pinnedTabs: [],
|
||||
order: [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2]
|
||||
},
|
||||
{ testNum: 8,
|
||||
totalTabs: 13,
|
||||
selectedTab: 0,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [],
|
||||
pinnedTabs: [0],
|
||||
order: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
|
||||
},
|
||||
{ testNum: 9,
|
||||
totalTabs: 13,
|
||||
selectedTab: 1,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [],
|
||||
pinnedTabs: [0],
|
||||
order: [1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
|
||||
},
|
||||
{ testNum: 10,
|
||||
totalTabs: 13,
|
||||
selectedTab: 3,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [2],
|
||||
pinnedTabs: [0,1],
|
||||
order: [3, 0, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 2]
|
||||
},
|
||||
{ testNum: 11,
|
||||
totalTabs: 13,
|
||||
selectedTab: 12,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [],
|
||||
pinnedTabs: [0,1,2],
|
||||
order: [12, 0, 1, 2, 7, 8, 9, 10, 11, 3, 4, 5, 6]
|
||||
},
|
||||
{ testNum: 12,
|
||||
totalTabs: 13,
|
||||
selectedTab: 6,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [3,4,5],
|
||||
pinnedTabs: [0,1,2],
|
||||
order: [6, 0, 1, 2, 7, 8, 9, 10, 11, 12, 3, 4, 5]
|
||||
},
|
||||
{ testNum: 13,
|
||||
totalTabs: 13,
|
||||
selectedTab: 1,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [3,4,5],
|
||||
pinnedTabs: [0,1,2],
|
||||
order: [1, 0, 2, 6, 7, 8, 9, 10, 11, 12, 3, 4, 5]
|
||||
},
|
||||
{ testNum: 14,
|
||||
totalTabs: 13,
|
||||
selectedTab: 2,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [],
|
||||
pinnedTabs: [0,1,2],
|
||||
order: [2, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
|
||||
},
|
||||
{ testNum: 15,
|
||||
totalTabs: 13,
|
||||
selectedTab: 3,
|
||||
shownTabs: 6,
|
||||
hiddenTabs: [1,4],
|
||||
pinnedTabs: [0,1,2],
|
||||
order: [3, 0, 1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 4]
|
||||
}
|
||||
];
|
||||
|
||||
let tabMinWidth = parseInt(getComputedStyle(gBrowser.selectedTab, null).minWidth);
|
||||
let tabMinWidth =
|
||||
parseInt(getComputedStyle(gBrowser.selectedTab, null).minWidth);
|
||||
let testIndex = 0;
|
||||
|
||||
function runNextTest() {
|
||||
|
@ -84,41 +164,46 @@ function test() {
|
|||
|
||||
info ("Starting test " + (++testIndex));
|
||||
let test = tests.shift();
|
||||
let state = buildTestState(test.totalTabs, test.selectedTab, test.hiddenTabs);
|
||||
let state = buildTestState(test.totalTabs, test.selectedTab,
|
||||
test.hiddenTabs, test.pinnedTabs);
|
||||
let tabbarWidth = Math.floor((test.shownTabs - 0.5) * tabMinWidth);
|
||||
let win = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||
let actualOrder = [];
|
||||
let tabsRestored = [];
|
||||
|
||||
win.addEventListener("SSTabRestoring", function onSSTabRestoring(aEvent) {
|
||||
let tab = aEvent.originalTarget;
|
||||
let currentIndex = Array.indexOf(win.gBrowser.tabs, tab);
|
||||
actualOrder.push(currentIndex);
|
||||
let tabLink = tab.linkedBrowser.currentURI.spec;
|
||||
let tabIndex =
|
||||
tabLink.substring(tabLink.indexOf("?t=") + 3, tabLink.length);
|
||||
|
||||
if (actualOrder.length < state.windows[0].tabs.length)
|
||||
// we need to compare with the tab's restoring index, no with the
|
||||
// position index, since the pinned tabs change the positions in the
|
||||
// tabbar.
|
||||
tabsRestored.push(tabIndex);
|
||||
|
||||
if (tabsRestored.length < state.windows[0].tabs.length)
|
||||
return;
|
||||
|
||||
// all of the tabs should be restoring or restored by now
|
||||
is(actualOrder.length, state.windows[0].tabs.length,
|
||||
is(tabsRestored.length, state.windows[0].tabs.length,
|
||||
"Test #" + testIndex + ": Number of restored tabs is as expected");
|
||||
|
||||
is(actualOrder.join(" "), test.order.join(" "),
|
||||
is(tabsRestored.join(" "), test.order.join(" "),
|
||||
"Test #" + testIndex + ": 'visible' tabs restored first");
|
||||
|
||||
// Cleanup.
|
||||
// cleanup
|
||||
win.removeEventListener("SSTabRestoring", onSSTabRestoring, false);
|
||||
win.close();
|
||||
executeSoon(runNextTest);
|
||||
}, false);
|
||||
|
||||
win.addEventListener("load", function onLoad(aEvent) {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
executeSoon(function () {
|
||||
let extent = win.outerWidth - win.gBrowser.tabContainer.mTabstrip.scrollClientSize;
|
||||
let windowWidth = tabbarWidth + extent;
|
||||
win.resizeTo(windowWidth, win.outerHeight);
|
||||
ss.setWindowState(win, JSON.stringify(state), true);
|
||||
});
|
||||
}, false);
|
||||
whenWindowLoaded(win, function(aEvent) {
|
||||
let extent =
|
||||
win.outerWidth - win.gBrowser.tabContainer.mTabstrip.scrollClientSize;
|
||||
let windowWidth = tabbarWidth + extent;
|
||||
win.resizeTo(windowWidth, win.outerHeight);
|
||||
ss.setWindowState(win, JSON.stringify(state), true);
|
||||
});
|
||||
};
|
||||
|
||||
runNextTest();
|
||||
|
|
|
@ -41,9 +41,7 @@ let WindowEventHandler = {
|
|||
// Sends an asynchronous message when the "onMozAfterPaint" event
|
||||
// is fired.
|
||||
onMozAfterPaint: function WEH_onMozAfterPaint(event) {
|
||||
if (event.clientRects.length > 0) {
|
||||
sendAsyncMessage("Panorama:MozAfterPaint");
|
||||
}
|
||||
sendAsyncMessage("Panorama:MozAfterPaint");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
|||
ac_add_options --enable-update-packaging
|
||||
ac_add_options --enable-codesighs
|
||||
ac_add_options --enable-signmar
|
||||
ac_add_options --enable-profiling
|
||||
#ac_add_options --enable-profiling
|
||||
|
||||
# Nightlies only since this has a cost in performance
|
||||
ac_add_options --enable-js-diagnostics
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[
|
||||
{"clang_version": "r159409"},
|
||||
{"clang_version": "r159509"},
|
||||
{
|
||||
"size": 47,
|
||||
"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
|
||||
|
@ -7,8 +7,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 74004324,
|
||||
"digest": "c5bb558a5958458b11da385d57897a1f7e57a7be2f452438f6813cf1e9f2a4ce93769c36e304126f97dbd753732b70446c7fa3c779267e80152d7ac0175057fc",
|
||||
"size": 74071397,
|
||||
"digest": "390e499161e8b5e91c179f3352ecbb07431e3d5a190298de7f338b48fe3807f3ddbeca72d8df39d11f89864fb1135f14500471faa741d3886b875b8e2b1d4416",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[
|
||||
{"clang_version": "r159409"},
|
||||
{"clang_version": "r159509"},
|
||||
{
|
||||
"size": 47,
|
||||
"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
|
||||
|
@ -7,8 +7,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 72533541,
|
||||
"digest": "f092080caed28db1ed7d9f0612aef1d885d2587b4e069d3662af5c241950ee772b6bc249d766a47b4fe2c170a46cfe05010269a3cbc1123d1f4126bc182b7b40",
|
||||
"size": 72518043,
|
||||
"digest": "447dac319a8d7fa902cc065b758440bf6d4a7a98104362162fbdb0479a44d9b84c5878506f09be4398053a6ddc07935c7fb4f71e59b178073876fb5f90a45219",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[
|
||||
{"clang_version": "r159409"},
|
||||
{"clang_version": "r159509"},
|
||||
{
|
||||
"size": 47,
|
||||
"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
|
||||
|
@ -7,8 +7,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 63604770,
|
||||
"digest": "c664beadb01a4e8ba7f32698b3ef694ade9044a9117d90d57f1475f2cefea82d74d1b0f3da89dcb9932ba90e048ae3d908bff05ab09d0ce2c82731e949e62a47",
|
||||
"size": 63679229,
|
||||
"digest": "5257503e537b8d440b17e40aa06f0f70f1b124129c02f10e45b46ac642fc4170bfa77ae737a8bcac3ed7602ccd934a88cbe349986eb971d66a6fb553ae31f13c",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -46,270 +46,358 @@ registerCleanupFunction(function tearDown() {
|
|||
* - browser/devtools/commandline/test/head.js
|
||||
* - browser/devtools/shared/test/head.js
|
||||
*/
|
||||
let DeveloperToolbarTest = {
|
||||
/**
|
||||
* Paranoid DeveloperToolbar.show();
|
||||
*/
|
||||
show: function DTT_show(aCallback) {
|
||||
if (DeveloperToolbar.visible) {
|
||||
ok(false, "DeveloperToolbar.visible at start of openDeveloperToolbar");
|
||||
}
|
||||
else {
|
||||
DeveloperToolbar.show(aCallback);
|
||||
}
|
||||
},
|
||||
let DeveloperToolbarTest = { };
|
||||
|
||||
/**
|
||||
* Paranoid DeveloperToolbar.hide();
|
||||
*/
|
||||
hide: function DTT_hide() {
|
||||
if (!DeveloperToolbar.visible) {
|
||||
ok(false, "!DeveloperToolbar.visible at start of closeDeveloperToolbar");
|
||||
}
|
||||
else {
|
||||
DeveloperToolbar.display.inputter.setInput("");
|
||||
DeveloperToolbar.hide();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Paranoid DeveloperToolbar.show();
|
||||
*/
|
||||
DeveloperToolbarTest.show = function DTT_show(aCallback) {
|
||||
if (DeveloperToolbar.visible) {
|
||||
ok(false, "DeveloperToolbar.visible at start of openDeveloperToolbar");
|
||||
}
|
||||
else {
|
||||
DeveloperToolbar.show(true, aCallback);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check that we can parse command input.
|
||||
* Doesn't execute the command, just checks that we grok the input properly:
|
||||
*
|
||||
* DeveloperToolbarTest.checkInputStatus({
|
||||
* // Test inputs
|
||||
* typed: "ech", // Required
|
||||
* cursor: 3, // Optional cursor position
|
||||
*
|
||||
* // Thing to check
|
||||
* status: "INCOMPLETE", // One of "VALID", "ERROR", "INCOMPLETE"
|
||||
* emptyParameters: [ "<message>" ], // Still to type
|
||||
* directTabText: "o", // Simple completion text
|
||||
* arrowTabText: "", // When the completion is not an extension
|
||||
* markup: "VVVIIIEEE", // What state should the error markup be in
|
||||
* });
|
||||
*/
|
||||
checkInputStatus: function DTT_checkInputStatus(tests) {
|
||||
let display = DeveloperToolbar.display;
|
||||
/**
|
||||
* Paranoid DeveloperToolbar.hide();
|
||||
*/
|
||||
DeveloperToolbarTest.hide = function DTT_hide() {
|
||||
if (!DeveloperToolbar.visible) {
|
||||
ok(false, "!DeveloperToolbar.visible at start of closeDeveloperToolbar");
|
||||
}
|
||||
else {
|
||||
DeveloperToolbar.display.inputter.setInput("");
|
||||
DeveloperToolbar.hide();
|
||||
}
|
||||
};
|
||||
|
||||
if (tests.typed) {
|
||||
display.inputter.setInput(tests.typed);
|
||||
}
|
||||
else {
|
||||
ok(false, "Missing typed for " + JSON.stringify(tests));
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* check() is the new status. Similar API except that it doesn't attempt to
|
||||
* alter the display/requisition at all, and it makes extra checks.
|
||||
* Test inputs
|
||||
* typed: The text to type at the input
|
||||
* Available checks:
|
||||
* input: The text displayed in the input field
|
||||
* cursor: The position of the start of the cursor
|
||||
* status: One of "VALID", "ERROR", "INCOMPLETE"
|
||||
* emptyParameters: Array of parameters still to type. e.g. [ "<message>" ]
|
||||
* directTabText: Simple completion text
|
||||
* arrowTabText: When the completion is not an extension (without arrow)
|
||||
* markup: What state should the error markup be in. e.g. "VVVIIIEEE"
|
||||
* args: Maps of checks to make against the arguments:
|
||||
* value: i.e. assignment.value (which ignores defaultValue)
|
||||
* type: Argument/BlankArgument/MergedArgument/etc i.e. what's assigned
|
||||
* Care should be taken with this since it's something of an
|
||||
* implementation detail
|
||||
* arg: The toString value of the argument
|
||||
* status: i.e. assignment.getStatus
|
||||
* message: i.e. assignment.getMessage
|
||||
* name: For commands - checks assignment.value.name
|
||||
*/
|
||||
DeveloperToolbarTest.checkInputStatus = function DTT_checkInputStatus(checks) {
|
||||
if (!checks.emptyParameters) {
|
||||
checks.emptyParameters = [];
|
||||
}
|
||||
if (!checks.directTabText) {
|
||||
checks.directTabText = '';
|
||||
}
|
||||
if (!checks.arrowTabText) {
|
||||
checks.arrowTabText = '';
|
||||
}
|
||||
|
||||
if (tests.cursor) {
|
||||
display.inputter.setCursor(tests.cursor)
|
||||
}
|
||||
var display = DeveloperToolbar.display;
|
||||
|
||||
if (tests.status) {
|
||||
is(display.requisition.getStatus().toString(),
|
||||
tests.status, "status for " + tests.typed);
|
||||
}
|
||||
if (checks.typed) {
|
||||
display.inputter.setInput(checks.typed);
|
||||
}
|
||||
else {
|
||||
ok(false, "Missing typed for " + JSON.stringify(checks));
|
||||
return;
|
||||
}
|
||||
|
||||
if (tests.emptyParameters == null) {
|
||||
tests.emptyParameters = [];
|
||||
}
|
||||
if (checks.cursor) {
|
||||
display.inputter.setCursor(checks.cursor)
|
||||
}
|
||||
|
||||
let realParams = display.completer.emptyParameters;
|
||||
is(realParams.length, tests.emptyParameters.length,
|
||||
'emptyParameters.length for \'' + tests.typed + '\'');
|
||||
var cursor = checks.cursor ? checks.cursor.start : checks.typed.length;
|
||||
|
||||
if (realParams.length === tests.emptyParameters.length) {
|
||||
for (let i = 0; i < realParams.length; i++) {
|
||||
is(realParams[i].replace(/\u00a0/g, ' '), tests.emptyParameters[i],
|
||||
'emptyParameters[' + i + '] for \'' + tests.typed + '\'');
|
||||
var requisition = display.requisition;
|
||||
var completer = display.completer;
|
||||
var actual = completer._getCompleterTemplateData();
|
||||
|
||||
/*
|
||||
if (checks.input) {
|
||||
is(display.inputter.element.value,
|
||||
checks.input,
|
||||
'input');
|
||||
}
|
||||
|
||||
if (checks.cursor) {
|
||||
is(display.inputter.element.selectionStart,
|
||||
checks.cursor,
|
||||
'cursor');
|
||||
}
|
||||
*/
|
||||
|
||||
if (checks.status) {
|
||||
is(requisition.getStatus().toString(),
|
||||
checks.status,
|
||||
'status');
|
||||
}
|
||||
|
||||
if (checks.markup) {
|
||||
var statusMarkup = requisition.getInputStatusMarkup(cursor);
|
||||
var actualMarkup = statusMarkup.map(function(s) {
|
||||
return Array(s.string.length + 1).join(s.status.toString()[0]);
|
||||
}).join('');
|
||||
|
||||
is(checks.markup,
|
||||
actualMarkup,
|
||||
'markup');
|
||||
}
|
||||
|
||||
if (checks.emptyParameters) {
|
||||
var actualParams = actual.emptyParameters;
|
||||
is(actualParams.length,
|
||||
checks.emptyParameters.length,
|
||||
'emptyParameters.length');
|
||||
|
||||
if (actualParams.length === checks.emptyParameters.length) {
|
||||
for (var i = 0; i < actualParams.length; i++) {
|
||||
is(actualParams[i].replace(/\u00a0/g, ' '),
|
||||
checks.emptyParameters[i],
|
||||
'emptyParameters[' + i + ']');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tests.directTabText) {
|
||||
is(display.completer.directTabText, tests.directTabText,
|
||||
'directTabText for \'' + tests.typed + '\'');
|
||||
}
|
||||
else {
|
||||
is(display.completer.directTabText, '',
|
||||
'directTabText for \'' + tests.typed + '\'');
|
||||
}
|
||||
if (checks.directTabText) {
|
||||
is(actual.directTabText,
|
||||
checks.directTabText,
|
||||
'directTabText');
|
||||
}
|
||||
|
||||
if (tests.arrowTabText) {
|
||||
is(display.completer.arrowTabText, ' \u00a0\u21E5 ' + tests.arrowTabText,
|
||||
'arrowTabText for \'' + tests.typed + '\'');
|
||||
}
|
||||
else {
|
||||
is(display.completer.arrowTabText, '',
|
||||
'arrowTabText for \'' + tests.typed + '\'');
|
||||
}
|
||||
if (checks.arrowTabText) {
|
||||
is(actual.arrowTabText,
|
||||
' \u00a0\u21E5 ' + checks.arrowTabText,
|
||||
'arrowTabText');
|
||||
}
|
||||
|
||||
if (tests.markup) {
|
||||
let cursor = tests.cursor ? tests.cursor.start : tests.typed.length;
|
||||
let statusMarkup = display.requisition.getInputStatusMarkup(cursor);
|
||||
let actualMarkup = statusMarkup.map(function(s) {
|
||||
return Array(s.string.length + 1).join(s.status.toString()[0]);
|
||||
}).join('');
|
||||
is(tests.markup, actualMarkup, 'markup for ' + tests.typed);
|
||||
}
|
||||
},
|
||||
if (checks.args) {
|
||||
Object.keys(checks.args).forEach(function(paramName) {
|
||||
var check = checks.args[paramName];
|
||||
|
||||
/**
|
||||
* Execute a command:
|
||||
*
|
||||
* DeveloperToolbarTest.exec({
|
||||
* // Test inputs
|
||||
* typed: "echo hi", // Optional, uses existing if undefined
|
||||
*
|
||||
* // Thing to check
|
||||
* args: { message: "hi" }, // Check that the args were understood properly
|
||||
* outputMatch: /^hi$/, // RegExp to test against textContent of output
|
||||
* // (can also be array of RegExps)
|
||||
* blankOutput: true, // Special checks when there is no output
|
||||
* });
|
||||
*/
|
||||
exec: function DTT_exec(tests) {
|
||||
tests = tests || {};
|
||||
|
||||
if (tests.typed) {
|
||||
DeveloperToolbar.display.inputter.setInput(tests.typed);
|
||||
}
|
||||
|
||||
let typed = DeveloperToolbar.display.inputter.getInputState().typed;
|
||||
let output = DeveloperToolbar.display.requisition.exec();
|
||||
|
||||
is(typed, output.typed, 'output.command for: ' + typed);
|
||||
|
||||
if (tests.completed !== false) {
|
||||
ok(output.completed, 'output.completed false for: ' + typed);
|
||||
}
|
||||
else {
|
||||
// It is actually an error if we say something is async and it turns
|
||||
// out not to be? For now we're saying 'no'
|
||||
// ok(!output.completed, 'output.completed true for: ' + typed);
|
||||
}
|
||||
|
||||
if (tests.args != null) {
|
||||
is(Object.keys(tests.args).length, Object.keys(output.args).length,
|
||||
'arg count for ' + typed);
|
||||
|
||||
Object.keys(output.args).forEach(function(arg) {
|
||||
let expectedArg = tests.args[arg];
|
||||
let actualArg = output.args[arg];
|
||||
|
||||
if (typeof expectedArg === 'function') {
|
||||
ok(expectedArg(actualArg), 'failed test func. ' + typed + '/' + arg);
|
||||
}
|
||||
else {
|
||||
if (Array.isArray(expectedArg)) {
|
||||
if (!Array.isArray(actualArg)) {
|
||||
ok(false, 'actual is not an array. ' + typed + '/' + arg);
|
||||
return;
|
||||
}
|
||||
|
||||
is(expectedArg.length, actualArg.length,
|
||||
'array length: ' + typed + '/' + arg);
|
||||
for (let i = 0; i < expectedArg.length; i++) {
|
||||
is(expectedArg[i], actualArg[i],
|
||||
'member: "' + typed + '/' + arg + '/' + i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
is(expectedArg, actualArg, 'typed: "' + typed + '" arg: ' + arg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let displayed = DeveloperToolbar.outputPanel._div.textContent;
|
||||
|
||||
if (tests.outputMatch) {
|
||||
function doTest(match, against) {
|
||||
if (!match.test(against)) {
|
||||
ok(false, "html output for " + typed + " against " + match.source +
|
||||
" (textContent sent to info)");
|
||||
info("Actual textContent");
|
||||
info(against);
|
||||
}
|
||||
}
|
||||
if (Array.isArray(tests.outputMatch)) {
|
||||
tests.outputMatch.forEach(function(match) {
|
||||
doTest(match, displayed);
|
||||
});
|
||||
var assignment;
|
||||
if (paramName === 'command') {
|
||||
assignment = requisition.commandAssignment;
|
||||
}
|
||||
else {
|
||||
doTest(tests.outputMatch, displayed);
|
||||
}
|
||||
}
|
||||
|
||||
if (tests.blankOutput != null) {
|
||||
if (!/^$/.test(displayed)) {
|
||||
ok(false, "html output for " + typed + " (textContent sent to info)");
|
||||
info("Actual textContent");
|
||||
info(displayed);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Quick wrapper around the things you need to do to run DeveloperToolbar
|
||||
* command tests:
|
||||
* - Set the pref 'devtools.toolbar.enabled' to true
|
||||
* - Add a tab pointing at |uri|
|
||||
* - Open the DeveloperToolbar
|
||||
* - Register a cleanup function to undo the above
|
||||
* - Run the tests
|
||||
*
|
||||
* @param uri The uri of a page to load. Can be 'about:blank' or 'data:...'
|
||||
* @param testFunc A function containing the tests to run. This should
|
||||
* arrange for 'finish()' to be called on completion.
|
||||
*/
|
||||
test: function DTT_test(uri, testFunc) {
|
||||
let menuItem = document.getElementById("menu_devToolbar");
|
||||
let command = document.getElementById("Tools:DevToolbar");
|
||||
let appMenuItem = document.getElementById("appmenu_devToolbar");
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
DeveloperToolbarTest.hide();
|
||||
|
||||
// a.k.a Services.prefs.clearUserPref("devtools.toolbar.enabled");
|
||||
if (menuItem) {
|
||||
menuItem.hidden = true;
|
||||
}
|
||||
if (command) {
|
||||
command.setAttribute("disabled", "true");
|
||||
}
|
||||
if (appMenuItem) {
|
||||
appMenuItem.hidden = true;
|
||||
assignment = requisition.getAssignment(paramName);
|
||||
}
|
||||
|
||||
// leakHunt({ DeveloperToolbar: DeveloperToolbar });
|
||||
if (assignment == null) {
|
||||
ok(false, 'Unknown parameter: ' + paramName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (check.value) {
|
||||
is(assignment.value,
|
||||
check.value,
|
||||
'checkStatus value for ' + paramName);
|
||||
}
|
||||
|
||||
if (check.name) {
|
||||
is(assignment.value.name,
|
||||
check.name,
|
||||
'checkStatus name for ' + paramName);
|
||||
}
|
||||
|
||||
if (check.type) {
|
||||
is(assignment.arg.type,
|
||||
check.type,
|
||||
'checkStatus type for ' + paramName);
|
||||
}
|
||||
|
||||
if (check.arg) {
|
||||
is(assignment.arg.toString(),
|
||||
check.arg,
|
||||
'checkStatus arg for ' + paramName);
|
||||
}
|
||||
|
||||
if (check.status) {
|
||||
is(assignment.getStatus().toString(),
|
||||
check.status,
|
||||
'checkStatus status for ' + paramName);
|
||||
}
|
||||
|
||||
if (check.message) {
|
||||
is(assignment.getMessage(),
|
||||
check.message,
|
||||
'checkStatus message for ' + paramName);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// a.k.a: Services.prefs.setBoolPref("devtools.toolbar.enabled", true);
|
||||
/**
|
||||
* Execute a command:
|
||||
*
|
||||
* DeveloperToolbarTest.exec({
|
||||
* // Test inputs
|
||||
* typed: "echo hi", // Optional, uses existing if undefined
|
||||
*
|
||||
* // Thing to check
|
||||
* args: { message: "hi" }, // Check that the args were understood properly
|
||||
* outputMatch: /^hi$/, // RegExp to test against textContent of output
|
||||
* // (can also be array of RegExps)
|
||||
* blankOutput: true, // Special checks when there is no output
|
||||
* });
|
||||
*/
|
||||
DeveloperToolbarTest.exec = function DTT_exec(tests) {
|
||||
tests = tests || {};
|
||||
|
||||
if (tests.typed) {
|
||||
DeveloperToolbar.display.inputter.setInput(tests.typed);
|
||||
}
|
||||
|
||||
let typed = DeveloperToolbar.display.inputter.getInputState().typed;
|
||||
let output = DeveloperToolbar.display.requisition.exec();
|
||||
|
||||
is(typed, output.typed, 'output.command for: ' + typed);
|
||||
|
||||
if (tests.completed !== false) {
|
||||
ok(output.completed, 'output.completed false for: ' + typed);
|
||||
}
|
||||
else {
|
||||
// It is actually an error if we say something is async and it turns
|
||||
// out not to be? For now we're saying 'no'
|
||||
// ok(!output.completed, 'output.completed true for: ' + typed);
|
||||
}
|
||||
|
||||
if (tests.args != null) {
|
||||
is(Object.keys(tests.args).length, Object.keys(output.args).length,
|
||||
'arg count for ' + typed);
|
||||
|
||||
Object.keys(output.args).forEach(function(arg) {
|
||||
let expectedArg = tests.args[arg];
|
||||
let actualArg = output.args[arg];
|
||||
|
||||
if (typeof expectedArg === 'function') {
|
||||
ok(expectedArg(actualArg), 'failed test func. ' + typed + '/' + arg);
|
||||
}
|
||||
else {
|
||||
if (Array.isArray(expectedArg)) {
|
||||
if (!Array.isArray(actualArg)) {
|
||||
ok(false, 'actual is not an array. ' + typed + '/' + arg);
|
||||
return;
|
||||
}
|
||||
|
||||
is(expectedArg.length, actualArg.length,
|
||||
'array length: ' + typed + '/' + arg);
|
||||
for (let i = 0; i < expectedArg.length; i++) {
|
||||
is(expectedArg[i], actualArg[i],
|
||||
'member: "' + typed + '/' + arg + '/' + i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
is(expectedArg, actualArg, 'typed: "' + typed + '" arg: ' + arg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let displayed = DeveloperToolbar.outputPanel._div.textContent;
|
||||
|
||||
if (tests.outputMatch) {
|
||||
function doTest(match, against) {
|
||||
if (!match.test(against)) {
|
||||
ok(false, "html output for " + typed + " against " + match.source +
|
||||
" (textContent sent to info)");
|
||||
info("Actual textContent");
|
||||
info(against);
|
||||
}
|
||||
}
|
||||
if (Array.isArray(tests.outputMatch)) {
|
||||
tests.outputMatch.forEach(function(match) {
|
||||
doTest(match, displayed);
|
||||
});
|
||||
}
|
||||
else {
|
||||
doTest(tests.outputMatch, displayed);
|
||||
}
|
||||
}
|
||||
|
||||
if (tests.blankOutput != null) {
|
||||
if (!/^$/.test(displayed)) {
|
||||
ok(false, "html output for " + typed + " (textContent sent to info)");
|
||||
info("Actual textContent");
|
||||
info(displayed);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Quick wrapper around the things you need to do to run DeveloperToolbar
|
||||
* command tests:
|
||||
* - Set the pref 'devtools.toolbar.enabled' to true
|
||||
* - Add a tab pointing at |uri|
|
||||
* - Open the DeveloperToolbar
|
||||
* - Register a cleanup function to undo the above
|
||||
* - Run the tests
|
||||
*
|
||||
* @param uri The uri of a page to load. Can be 'about:blank' or 'data:...'
|
||||
* @param testFunc A function containing the tests to run. This should
|
||||
* arrange for 'finish()' to be called on completion.
|
||||
*/
|
||||
DeveloperToolbarTest.test = function DTT_test(uri, testFunc) {
|
||||
let menuItem = document.getElementById("menu_devToolbar");
|
||||
let command = document.getElementById("Tools:DevToolbar");
|
||||
let appMenuItem = document.getElementById("appmenu_devToolbar");
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
DeveloperToolbarTest.hide();
|
||||
|
||||
// a.k.a Services.prefs.clearUserPref("devtools.toolbar.enabled");
|
||||
if (menuItem) {
|
||||
menuItem.hidden = false;
|
||||
menuItem.hidden = true;
|
||||
}
|
||||
if (command) {
|
||||
command.removeAttribute("disabled");
|
||||
command.setAttribute("disabled", "true");
|
||||
}
|
||||
if (appMenuItem) {
|
||||
appMenuItem.hidden = false;
|
||||
appMenuItem.hidden = true;
|
||||
}
|
||||
|
||||
addTab(uri, function(browser, tab) {
|
||||
DeveloperToolbarTest.show(function() {
|
||||
// leakHunt({ DeveloperToolbar: DeveloperToolbar });
|
||||
});
|
||||
|
||||
try {
|
||||
testFunc(browser, tab);
|
||||
}
|
||||
catch (ex) {
|
||||
ok(false, "" + ex);
|
||||
console.error(ex);
|
||||
finish();
|
||||
throw ex;
|
||||
}
|
||||
});
|
||||
// a.k.a: Services.prefs.setBoolPref("devtools.toolbar.enabled", true);
|
||||
if (menuItem) {
|
||||
menuItem.hidden = false;
|
||||
}
|
||||
if (command) {
|
||||
command.removeAttribute("disabled");
|
||||
}
|
||||
if (appMenuItem) {
|
||||
appMenuItem.hidden = false;
|
||||
}
|
||||
|
||||
addTab(uri, function(browser, tab) {
|
||||
DeveloperToolbarTest.show(function() {
|
||||
|
||||
try {
|
||||
testFunc(browser, tab);
|
||||
}
|
||||
catch (ex) {
|
||||
ok(false, "" + ex);
|
||||
console.error(ex);
|
||||
finish();
|
||||
throw ex;
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -552,8 +552,6 @@ StackFramesView.prototype = {
|
|||
resume.setAttribute("tooltiptext", L10N.getStr("pauseTooltip"));
|
||||
resume.removeAttribute("checked");
|
||||
}
|
||||
|
||||
DebuggerView.Scripts.clearSearch();
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -101,7 +101,7 @@ var ScratchpadManager = {
|
|||
}
|
||||
let win = Services.ww.openWindow(null, SCRATCHPAD_WINDOW_URL, "_blank",
|
||||
SCRATCHPAD_WINDOW_FEATURES, params);
|
||||
// Only add shutdown observer if we've opened a scratchpad window
|
||||
// Only add the shutdown observer if we've opened a scratchpad window.
|
||||
ShutdownObserver.init();
|
||||
|
||||
return win;
|
||||
|
|
|
@ -31,6 +31,7 @@ const SCRATCHPAD_CONTEXT_CONTENT = 1;
|
|||
const SCRATCHPAD_CONTEXT_BROWSER = 2;
|
||||
const SCRATCHPAD_L10N = "chrome://browser/locale/devtools/scratchpad.properties";
|
||||
const DEVTOOLS_CHROME_ENABLED = "devtools.chrome.enabled";
|
||||
const PREF_RECENT_FILES_MAX = "devtools.scratchpad.recentFilesMax";
|
||||
const BUTTON_POSITION_SAVE = 0;
|
||||
const BUTTON_POSITION_CANCEL = 1;
|
||||
const BUTTON_POSITION_DONT_SAVE = 2;
|
||||
|
@ -160,7 +161,7 @@ var Scratchpad = {
|
|||
* @param object aState
|
||||
* An object with filename and executionContext properties.
|
||||
*/
|
||||
setState: function SP_getState(aState)
|
||||
setState: function SP_setState(aState)
|
||||
{
|
||||
if (aState.filename) {
|
||||
this.setFilename(aState.filename);
|
||||
|
@ -615,19 +616,203 @@ var Scratchpad = {
|
|||
|
||||
/**
|
||||
* Open a file to edit in the Scratchpad.
|
||||
*
|
||||
* @param integer aIndex
|
||||
* Optional integer: clicked menuitem in the 'Open Recent'-menu.
|
||||
*/
|
||||
openFile: function SP_openFile()
|
||||
openFile: function SP_openFile(aIndex)
|
||||
{
|
||||
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
|
||||
fp.init(window, this.strings.GetStringFromName("openFile.title"),
|
||||
Ci.nsIFilePicker.modeOpen);
|
||||
fp.defaultString = "";
|
||||
if (fp.show() != Ci.nsIFilePicker.returnCancel) {
|
||||
this.setFilename(fp.file.path);
|
||||
this.importFromFile(fp.file, false);
|
||||
let fp;
|
||||
if (!aIndex && aIndex !== 0) {
|
||||
fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
|
||||
fp.init(window, this.strings.GetStringFromName("openFile.title"),
|
||||
Ci.nsIFilePicker.modeOpen);
|
||||
fp.defaultString = "";
|
||||
}
|
||||
|
||||
if (aIndex > -1 || fp.show() != Ci.nsIFilePicker.returnCancel) {
|
||||
this.promptSave(function(aCloseFile, aSaved, aStatus) {
|
||||
let shouldOpen = aCloseFile;
|
||||
if (aSaved && !Components.isSuccessCode(aStatus)) {
|
||||
shouldOpen = false;
|
||||
}
|
||||
|
||||
if (shouldOpen) {
|
||||
this._skipClosePrompt = true;
|
||||
|
||||
let file;
|
||||
if (fp) {
|
||||
file = fp.file;
|
||||
} else {
|
||||
file = Components.classes["@mozilla.org/file/local;1"].
|
||||
createInstance(Components.interfaces.nsILocalFile);
|
||||
let filePath = this.getRecentFiles()[aIndex];
|
||||
file.initWithPath(filePath);
|
||||
}
|
||||
|
||||
this.setFilename(file.path);
|
||||
this.importFromFile(file, false);
|
||||
this.setRecentFile(file);
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get recent files.
|
||||
*
|
||||
* @return Array
|
||||
* File paths.
|
||||
*/
|
||||
getRecentFiles: function SP_getRecentFiles()
|
||||
{
|
||||
let maxRecent = Services.prefs.getIntPref(PREF_RECENT_FILES_MAX);
|
||||
let branch = Services.prefs.
|
||||
getBranch("devtools.scratchpad.");
|
||||
|
||||
let filePaths = [];
|
||||
if (branch.prefHasUserValue("recentFilePaths")) {
|
||||
filePaths = JSON.parse(branch.getCharPref("recentFilePaths"));
|
||||
}
|
||||
|
||||
return filePaths;
|
||||
},
|
||||
|
||||
/**
|
||||
* Save a recent file in a JSON parsable string.
|
||||
*
|
||||
* @param nsILocalFile aFile
|
||||
* The nsILocalFile we want to save as a recent file.
|
||||
*/
|
||||
setRecentFile: function SP_setRecentFile(aFile)
|
||||
{
|
||||
let maxRecent = Services.prefs.getIntPref(PREF_RECENT_FILES_MAX);
|
||||
if (maxRecent < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
let filePaths = this.getRecentFiles();
|
||||
let filesCount = filePaths.length;
|
||||
let pathIndex = filePaths.indexOf(aFile.path);
|
||||
|
||||
// We are already storing this file in the list of recent files.
|
||||
if (pathIndex > -1) {
|
||||
// If it's already the most recent file, we don't have to do anything.
|
||||
if (pathIndex === (filesCount - 1)) {
|
||||
// Updating the menu to clear the disabled state from the wrong menuitem
|
||||
// in rare cases when two or more Scratchpad windows are open and the
|
||||
// same file has been opened in two or more windows.
|
||||
this.populateRecentFilesMenu();
|
||||
return;
|
||||
}
|
||||
|
||||
// It is not the most recent file. Remove it from the list, we add it as
|
||||
// the most recent farther down.
|
||||
filePaths.splice(pathIndex, 1);
|
||||
}
|
||||
// If we are not storing the file and the 'recent files'-list is full,
|
||||
// remove the oldest file from the list.
|
||||
else if (filesCount === maxRecent) {
|
||||
filePaths.shift();
|
||||
}
|
||||
|
||||
filePaths.push(aFile.path);
|
||||
|
||||
let branch = Services.prefs.
|
||||
getBranch("devtools.scratchpad.");
|
||||
branch.setCharPref("recentFilePaths", JSON.stringify(filePaths));
|
||||
return;
|
||||
},
|
||||
|
||||
/**
|
||||
* Populates the 'Open Recent'-menu.
|
||||
*/
|
||||
populateRecentFilesMenu: function SP_populateRecentFilesMenu()
|
||||
{
|
||||
let maxRecent = Services.prefs.getIntPref(PREF_RECENT_FILES_MAX);
|
||||
let recentFilesMenu = document.getElementById("sp-open_recent-menu");
|
||||
|
||||
if (maxRecent < 1) {
|
||||
recentFilesMenu.setAttribute("hidden", true);
|
||||
return;
|
||||
}
|
||||
|
||||
let recentFilesPopup = recentFilesMenu.firstChild;
|
||||
let filePaths = this.getRecentFiles();
|
||||
let filename = this.getState().filename;
|
||||
|
||||
recentFilesMenu.setAttribute("disabled", true);
|
||||
while (recentFilesPopup.hasChildNodes()) {
|
||||
recentFilesPopup.removeChild(recentFilesPopup.firstChild);
|
||||
}
|
||||
|
||||
if (filePaths.length > 0) {
|
||||
recentFilesMenu.removeAttribute("disabled");
|
||||
|
||||
// Print out menuitems with the most recent file first.
|
||||
for (let i = filePaths.length - 1; i >= 0; --i) {
|
||||
let menuitem = document.createElement("menuitem");
|
||||
menuitem.setAttribute("type", "radio");
|
||||
menuitem.setAttribute("label", filePaths[i]);
|
||||
|
||||
if (filePaths[i] === filename) {
|
||||
menuitem.setAttribute("checked", true);
|
||||
menuitem.setAttribute("disabled", true);
|
||||
}
|
||||
|
||||
menuitem.setAttribute("oncommand", "Scratchpad.openFile(" + i + ");");
|
||||
recentFilesPopup.appendChild(menuitem);
|
||||
}
|
||||
|
||||
recentFilesPopup.appendChild(document.createElement("menuseparator"));
|
||||
let clearItems = document.createElement("menuitem");
|
||||
clearItems.setAttribute("id", "sp-menu-clear_recent");
|
||||
clearItems.setAttribute("label",
|
||||
this.strings.
|
||||
GetStringFromName("clearRecentMenuItems.label"));
|
||||
clearItems.setAttribute("command", "sp-cmd-clearRecentFiles");
|
||||
recentFilesPopup.appendChild(clearItems);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear all recent files.
|
||||
*/
|
||||
clearRecentFiles: function SP_clearRecentFiles()
|
||||
{
|
||||
Services.prefs.clearUserPref("devtools.scratchpad.recentFilePaths");
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle changes to the 'PREF_RECENT_FILES_MAX'-preference.
|
||||
*/
|
||||
handleRecentFileMaxChange: function SP_handleRecentFileMaxChange()
|
||||
{
|
||||
let maxRecent = Services.prefs.getIntPref(PREF_RECENT_FILES_MAX);
|
||||
let menu = document.getElementById("sp-open_recent-menu");
|
||||
|
||||
// Hide the menu if the 'PREF_RECENT_FILES_MAX'-pref is set to zero or less.
|
||||
if (maxRecent < 1) {
|
||||
menu.setAttribute("hidden", true);
|
||||
} else {
|
||||
if (menu.hasAttribute("hidden")) {
|
||||
if (!menu.firstChild.hasChildNodes()) {
|
||||
this.populateRecentFilesMenu();
|
||||
}
|
||||
|
||||
menu.removeAttribute("hidden");
|
||||
}
|
||||
|
||||
let filePaths = this.getRecentFiles();
|
||||
if (maxRecent < filePaths.length) {
|
||||
let branch = Services.prefs.
|
||||
getBranch("devtools.scratchpad.");
|
||||
let diff = filePaths.length - maxRecent;
|
||||
filePaths.splice(0, diff);
|
||||
branch.setCharPref("recentFilePaths", JSON.stringify(filePaths));
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Save the textbox content to the currently open file.
|
||||
*
|
||||
|
@ -646,6 +831,7 @@ var Scratchpad = {
|
|||
this.exportToFile(file, true, false, function(aStatus) {
|
||||
if (Components.isSuccessCode(aStatus)) {
|
||||
this.editor.dirty = false;
|
||||
this.setRecentFile(file);
|
||||
}
|
||||
if (aCallback) {
|
||||
aCallback(aStatus);
|
||||
|
@ -671,6 +857,7 @@ var Scratchpad = {
|
|||
this.exportToFile(fp.file, true, false, function(aStatus) {
|
||||
if (Components.isSuccessCode(aStatus)) {
|
||||
this.editor.dirty = false;
|
||||
this.setRecentFile(fp.file);
|
||||
}
|
||||
if (aCallback) {
|
||||
aCallback(aStatus);
|
||||
|
@ -827,6 +1014,9 @@ var Scratchpad = {
|
|||
this.initialized = true;
|
||||
|
||||
this._triggerObservers("Ready");
|
||||
|
||||
this.populateRecentFilesMenu();
|
||||
PreferenceObserver.init();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -887,6 +1077,8 @@ var Scratchpad = {
|
|||
this.resetContext();
|
||||
this.editor.removeEventListener(SourceEditor.EVENTS.DIRTY_CHANGED,
|
||||
this._onDirtyChanged);
|
||||
PreferenceObserver.uninit();
|
||||
|
||||
this.editor.destroy();
|
||||
this.editor = null;
|
||||
this.initialized = false;
|
||||
|
@ -1063,6 +1255,48 @@ var Scratchpad = {
|
|||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* The PreferenceObserver listens for preference changes while Scratchpad is
|
||||
* running.
|
||||
*/
|
||||
var PreferenceObserver = {
|
||||
_initialized: false,
|
||||
|
||||
init: function PO_init()
|
||||
{
|
||||
if (this._initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.branch = Services.prefs.getBranch("devtools.scratchpad.");
|
||||
this.branch.addObserver("", this, false);
|
||||
this._initialized = true;
|
||||
},
|
||||
|
||||
observe: function PO_observe(aMessage, aTopic, aData)
|
||||
{
|
||||
if (aTopic != "nsPref:changed") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aData == "recentFilesMax") {
|
||||
Scratchpad.handleRecentFileMaxChange();
|
||||
}
|
||||
else if (aData == "recentFilePaths") {
|
||||
Scratchpad.populateRecentFilesMenu();
|
||||
}
|
||||
},
|
||||
|
||||
uninit: function PO_uninit () {
|
||||
if (!this.branch) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.branch.removeObserver("", this);
|
||||
this.branch = null;
|
||||
}
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(Scratchpad, "strings", function () {
|
||||
return Services.strings.createBundle(SCRATCHPAD_L10N);
|
||||
});
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
<commandset id="sp-commandset">
|
||||
<command id="sp-cmd-newWindow" oncommand="Scratchpad.openScratchpad();"/>
|
||||
<command id="sp-cmd-openFile" oncommand="Scratchpad.openFile();"/>
|
||||
<command id="sp-cmd-clearRecentFiles" oncommand="Scratchpad.clearRecentFiles();"/>
|
||||
<command id="sp-cmd-save" oncommand="Scratchpad.saveFile();"/>
|
||||
<command id="sp-cmd-saveas" oncommand="Scratchpad.saveFileAs();"/>
|
||||
|
||||
|
@ -117,6 +118,11 @@
|
|||
command="sp-cmd-openFile"
|
||||
key="sp-key-open"
|
||||
accesskey="&openFileCmd.accesskey;"/>
|
||||
<menu id="sp-open_recent-menu" label="&openRecentMenu.label;"
|
||||
accesskey="&openRecentMenu.accesskey;"
|
||||
disabled="true">
|
||||
<menupopup id="sp-menu-open_recentPopup"/>
|
||||
</menu>
|
||||
<menuitem id="sp-menu-save"
|
||||
label="&saveFileCmd.label;"
|
||||
accesskey="&saveFileCmd.accesskey;"
|
||||
|
|
|
@ -32,6 +32,7 @@ _BROWSER_TEST_FILES = \
|
|||
browser_scratchpad_bug650345_find_ui.js \
|
||||
browser_scratchpad_bug714942_goto_line_ui.js \
|
||||
browser_scratchpad_bug_650760_help_key.js \
|
||||
browser_scratchpad_bug_651942_recent_files.js \
|
||||
head.js \
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
|
|
|
@ -0,0 +1,314 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let tempScope = {};
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm", tempScope);
|
||||
let NetUtil = tempScope.NetUtil;
|
||||
let FileUtils = tempScope.FileUtils;
|
||||
|
||||
// Reference to the Scratchpad object.
|
||||
let gScratchpad;
|
||||
|
||||
// References to the temporary nsIFiles.
|
||||
let gFile01;
|
||||
let gFile02;
|
||||
let gFile03;
|
||||
let gFile04;
|
||||
|
||||
// lists of recent files.
|
||||
var lists = {
|
||||
recentFiles01: null,
|
||||
recentFiles02: null,
|
||||
recentFiles03: null,
|
||||
recentFiles04: null,
|
||||
};
|
||||
|
||||
// Temporary file names.
|
||||
let gFileName01 = "file01_ForBug651942.tmp"
|
||||
let gFileName02 = "file02_ForBug651942.tmp"
|
||||
let gFileName03 = "file03_ForBug651942.tmp"
|
||||
let gFileName04 = "file04_ForBug651942.tmp"
|
||||
|
||||
// Content for the temporary files.
|
||||
let gFileContent;
|
||||
let gFileContent01 = "hello.world.01('bug651942');";
|
||||
let gFileContent02 = "hello.world.02('bug651942');";
|
||||
let gFileContent03 = "hello.world.03('bug651942');";
|
||||
let gFileContent04 = "hello.world.04('bug651942');";
|
||||
|
||||
function startTest()
|
||||
{
|
||||
gScratchpad = gScratchpadWindow.Scratchpad;
|
||||
|
||||
gFile01 = createAndLoadTemporaryFile(gFile01, gFileName01, gFileContent01);
|
||||
gFile02 = createAndLoadTemporaryFile(gFile02, gFileName02, gFileContent02);
|
||||
gFile03 = createAndLoadTemporaryFile(gFile03, gFileName03, gFileContent03);
|
||||
}
|
||||
|
||||
// Test to see if the three files we created in the 'startTest()'-method have
|
||||
// been added to the list of recent files.
|
||||
function testAddedToRecent()
|
||||
{
|
||||
lists.recentFiles01 = gScratchpad.getRecentFiles();
|
||||
|
||||
is(lists.recentFiles01.length, 3,
|
||||
"Temporary files created successfully and added to list of recent files.");
|
||||
|
||||
// Create a 4th file, this should clear the oldest file.
|
||||
gFile04 = createAndLoadTemporaryFile(gFile04, gFileName04, gFileContent04);
|
||||
}
|
||||
|
||||
// We have opened a 4th file. Test to see if the oldest recent file was removed,
|
||||
// and that the other files were reordered successfully.
|
||||
function testOverwriteRecent()
|
||||
{
|
||||
lists.recentFiles02 = gScratchpad.getRecentFiles();
|
||||
|
||||
is(lists.recentFiles02[0], lists.recentFiles01[1],
|
||||
"File02 was reordered successfully in the 'recent files'-list.");
|
||||
is(lists.recentFiles02[1], lists.recentFiles01[2],
|
||||
"File03 was reordered successfully in the 'recent files'-list.");
|
||||
isnot(lists.recentFiles02[2], lists.recentFiles01[2],
|
||||
"File04: was added successfully.");
|
||||
|
||||
// Open the oldest recent file.
|
||||
gScratchpad.openFile(0);
|
||||
}
|
||||
|
||||
// We have opened the "oldest"-recent file. Test to see if it is now the most
|
||||
// recent file, and that the other files were reordered successfully.
|
||||
function testOpenOldestRecent()
|
||||
{
|
||||
lists.recentFiles03 = gScratchpad.getRecentFiles();
|
||||
|
||||
is(lists.recentFiles02[0], lists.recentFiles03[2],
|
||||
"File04 was reordered successfully in the 'recent files'-list.");
|
||||
is(lists.recentFiles02[1], lists.recentFiles03[0],
|
||||
"File03 was reordered successfully in the 'recent files'-list.");
|
||||
is(lists.recentFiles02[2], lists.recentFiles03[1],
|
||||
"File02 was reordered successfully in the 'recent files'-list.");
|
||||
|
||||
Services.prefs.setIntPref("devtools.scratchpad.recentFilesMax", 0);
|
||||
}
|
||||
|
||||
// The "devtools.scratchpad.recentFilesMax"-preference was set to zero (0).
|
||||
// This should disable the "Open Recent"-menu by hiding it (this should not
|
||||
// remove any files from the list). Test to see if it's been hidden.
|
||||
function testHideMenu()
|
||||
{
|
||||
let menu = gScratchpadWindow.document.getElementById("sp-open_recent-menu");
|
||||
ok(menu.hasAttribute("hidden"), "The menu was hidden successfully.");
|
||||
|
||||
Services.prefs.setIntPref("devtools.scratchpad.recentFilesMax", 1);
|
||||
}
|
||||
|
||||
// We have set the recentFilesMax-pref to one (1), this enables the feature,
|
||||
// removes the two oldest files, rebuilds the menu and removes the
|
||||
// "hidden"-attribute from it. Test to see if this works.
|
||||
function testChangedMaxRecent()
|
||||
{
|
||||
let menu = gScratchpadWindow.document.getElementById("sp-open_recent-menu");
|
||||
ok(!menu.hasAttribute("hidden"), "The menu is visible. \\o/");
|
||||
|
||||
lists.recentFiles04 = gScratchpad.getRecentFiles();
|
||||
|
||||
is(lists.recentFiles04.length, 1,
|
||||
"Two recent files were successfully removed from the 'recent files'-list");
|
||||
|
||||
let doc = gScratchpadWindow.document;
|
||||
let popup = doc.getElementById("sp-menu-open_recentPopup");
|
||||
|
||||
let menuitemLabel = popup.children[0].getAttribute("label");
|
||||
let correctMenuItem = false;
|
||||
if (menuitemLabel === lists.recentFiles03[2] &&
|
||||
menuitemLabel === lists.recentFiles04[0]) {
|
||||
correctMenuItem = true;
|
||||
}
|
||||
|
||||
is(correctMenuItem, true,
|
||||
"Two recent files were successfully removed from the 'Open Recent'-menu");
|
||||
|
||||
gScratchpad.clearRecentFiles();
|
||||
}
|
||||
|
||||
// We have cleared the last file. Test to see if the last file was removed,
|
||||
// the menu is empty and was disabled successfully.
|
||||
function testClearedAll()
|
||||
{
|
||||
let doc = gScratchpadWindow.document;
|
||||
let menu = doc.getElementById("sp-open_recent-menu");
|
||||
let popup = doc.getElementById("sp-menu-open_recentPopup");
|
||||
|
||||
is(gScratchpad.getRecentFiles().length, 0,
|
||||
"All recent files removed successfully.");
|
||||
is(popup.children.length, 0, "All menuitems removed successfully.");
|
||||
ok(menu.hasAttribute("disabled"),
|
||||
"No files in the menu, it was disabled successfully.");
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
||||
function createAndLoadTemporaryFile(aFile, aFileName, aFileContent)
|
||||
{
|
||||
// Create a temporary file.
|
||||
aFile = FileUtils.getFile("TmpD", [aFileName]);
|
||||
aFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
|
||||
|
||||
// Write the temporary file.
|
||||
let fout = Cc["@mozilla.org/network/file-output-stream;1"].
|
||||
createInstance(Ci.nsIFileOutputStream);
|
||||
fout.init(aFile.QueryInterface(Ci.nsILocalFile), 0x02 | 0x08 | 0x20,
|
||||
0644, fout.DEFER_OPEN);
|
||||
|
||||
gScratchpad.setFilename(aFile.path);
|
||||
gScratchpad.importFromFile(aFile.QueryInterface(Ci.nsILocalFile), true,
|
||||
fileImported);
|
||||
gScratchpad.saveFile(fileSaved);
|
||||
|
||||
return aFile;
|
||||
}
|
||||
|
||||
function fileImported(aStatus)
|
||||
{
|
||||
ok(Components.isSuccessCode(aStatus),
|
||||
"the temporary file was imported successfully with Scratchpad");
|
||||
}
|
||||
|
||||
function fileSaved(aStatus)
|
||||
{
|
||||
ok(Components.isSuccessCode(aStatus),
|
||||
"the temporary file was saved successfully with Scratchpad");
|
||||
|
||||
checkIfMenuIsPopulated();
|
||||
}
|
||||
|
||||
function checkIfMenuIsPopulated()
|
||||
{
|
||||
let doc = gScratchpadWindow.document;
|
||||
let expectedMenuitemCount = doc.getElementById("sp-menu-open_recentPopup").
|
||||
children.length;
|
||||
// The number of recent files stored, plus the separator and the
|
||||
// clearRecentMenuItems-item.
|
||||
let recentFilesPlusExtra = gScratchpad.getRecentFiles().length + 2;
|
||||
|
||||
if (expectedMenuitemCount > 2) {
|
||||
is(expectedMenuitemCount, recentFilesPlusExtra,
|
||||
"the recent files menu was populated successfully.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The PreferenceObserver listens for preference changes while Scratchpad is
|
||||
* running.
|
||||
*/
|
||||
var PreferenceObserver = {
|
||||
_initialized: false,
|
||||
|
||||
_timesFired: 0,
|
||||
set timesFired(aNewValue) {
|
||||
this._timesFired = aNewValue;
|
||||
},
|
||||
get timesFired() {
|
||||
return this._timesFired;
|
||||
},
|
||||
|
||||
init: function PO_init()
|
||||
{
|
||||
if (this._initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.branch = Services.prefs.getBranch("devtools.scratchpad.");
|
||||
this.branch.addObserver("", this, false);
|
||||
this._initialized = true;
|
||||
},
|
||||
|
||||
observe: function PO_observe(aMessage, aTopic, aData)
|
||||
{
|
||||
if (aTopic != "nsPref:changed") {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this.timesFired) {
|
||||
case 0:
|
||||
this.timesFired = 1;
|
||||
break;
|
||||
case 1:
|
||||
this.timesFired = 2;
|
||||
break;
|
||||
case 2:
|
||||
this.timesFired = 3;
|
||||
testAddedToRecent();
|
||||
break;
|
||||
case 3:
|
||||
this.timesFired = 4;
|
||||
testOverwriteRecent();
|
||||
break;
|
||||
case 4:
|
||||
this.timesFired = 5;
|
||||
testOpenOldestRecent();
|
||||
break;
|
||||
case 5:
|
||||
this.timesFired = 6;
|
||||
testHideMenu();
|
||||
break;
|
||||
case 6:
|
||||
this.timesFired = 7;
|
||||
testChangedMaxRecent();
|
||||
break;
|
||||
case 7:
|
||||
this.timesFired = 8;
|
||||
testClearedAll();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
uninit: function PO_uninit () {
|
||||
this.branch.removeObserver("", this);
|
||||
}
|
||||
};
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
gFile01.remove(false);
|
||||
gFile01 = null;
|
||||
gFile02.remove(false);
|
||||
gFile02 = null;
|
||||
gFile03.remove(false);
|
||||
gFile03 = null;
|
||||
gFile04.remove(false);
|
||||
gFile04 = null;
|
||||
lists.recentFiles01 = null;
|
||||
lists.recentFiles02 = null;
|
||||
lists.recentFiles03 = null;
|
||||
lists.recentFiles04 = null;
|
||||
gScratchpad = null;
|
||||
|
||||
PreferenceObserver.uninit();
|
||||
Services.prefs.clearUserPref("devtools.scratchpad.recentFilesMax");
|
||||
});
|
||||
|
||||
Services.prefs.setIntPref("devtools.scratchpad.recentFilesMax", 3);
|
||||
|
||||
// Initiate the preference observer after we have set the temporary recent
|
||||
// files max for this test.
|
||||
PreferenceObserver.init();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||
openScratchpad(startTest);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,<p>test recent files in Scratchpad";
|
||||
}
|
||||
|
||||
function finishTest()
|
||||
{
|
||||
finish();
|
||||
}
|
|
@ -43,7 +43,6 @@ function DeveloperToolbar(aChromeWindow, aToolbarElement)
|
|||
this._errorsCount = {};
|
||||
this._webConsoleButton = this._doc
|
||||
.getElementById("developer-toolbar-webconsole");
|
||||
this._webConsoleButtonLabel = this._webConsoleButton.label;
|
||||
|
||||
try {
|
||||
GcliCommands.refreshAutoCommands(aChromeWindow);
|
||||
|
@ -107,7 +106,7 @@ DeveloperToolbar.prototype.toggle = function DT_toggle()
|
|||
if (this.visible) {
|
||||
this.hide();
|
||||
} else {
|
||||
this.show();
|
||||
this.show(true);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -124,7 +123,7 @@ DeveloperToolbar.introShownThisSession = false;
|
|||
* @param aCallback show events can be asynchronous. If supplied aCallback will
|
||||
* be called when the DeveloperToolbar is visible
|
||||
*/
|
||||
DeveloperToolbar.prototype.show = function DT_show(aCallback)
|
||||
DeveloperToolbar.prototype.show = function DT_show(aFocus, aCallback)
|
||||
{
|
||||
if (this._lastState != NOTIFICATIONS.HIDE) {
|
||||
return;
|
||||
|
@ -139,7 +138,7 @@ DeveloperToolbar.prototype.show = function DT_show(aCallback)
|
|||
let checkLoad = function() {
|
||||
if (this.tooltipPanel && this.tooltipPanel.loaded &&
|
||||
this.outputPanel && this.outputPanel.loaded) {
|
||||
this._onload();
|
||||
this._onload(aFocus);
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
|
@ -152,7 +151,7 @@ DeveloperToolbar.prototype.show = function DT_show(aCallback)
|
|||
* Initializing GCLI can only be done when we've got content windows to write
|
||||
* to, so this needs to be done asynchronously.
|
||||
*/
|
||||
DeveloperToolbar.prototype._onload = function DT_onload()
|
||||
DeveloperToolbar.prototype._onload = function DT_onload(aFocus)
|
||||
{
|
||||
this._doc.getElementById("Tools:DevToolbar").setAttribute("checked", "true");
|
||||
|
||||
|
@ -179,6 +178,9 @@ DeveloperToolbar.prototype._onload = function DT_onload()
|
|||
scratchpad: null
|
||||
});
|
||||
|
||||
this.display.focusManager.addMonitoredElement(this.outputPanel._frame);
|
||||
this.display.focusManager.addMonitoredElement(this._element);
|
||||
|
||||
this.display.onVisibilityChange.add(this.outputPanel._visibilityChanged, this.outputPanel);
|
||||
this.display.onVisibilityChange.add(this.tooltipPanel._visibilityChanged, this.tooltipPanel);
|
||||
this.display.onOutput.add(this.outputPanel._outputChanged, this.outputPanel);
|
||||
|
@ -187,12 +189,14 @@ DeveloperToolbar.prototype._onload = function DT_onload()
|
|||
this._chromeWindow.getBrowser().tabContainer.addEventListener("TabClose", this, false);
|
||||
this._chromeWindow.getBrowser().addEventListener("load", this, true);
|
||||
this._chromeWindow.getBrowser().addEventListener("beforeunload", this, true);
|
||||
this._chromeWindow.addEventListener("resize", this, false);
|
||||
|
||||
this._initErrorsCount(this._chromeWindow.getBrowser().selectedTab);
|
||||
|
||||
this._element.hidden = false;
|
||||
this._input.focus();
|
||||
|
||||
if (aFocus) {
|
||||
this._input.focus();
|
||||
}
|
||||
|
||||
this._notify(NOTIFICATIONS.SHOW);
|
||||
if (this._pendingShowCallback) {
|
||||
|
@ -307,11 +311,13 @@ DeveloperToolbar.prototype.destroy = function DT_destroy()
|
|||
this._chromeWindow.getBrowser().tabContainer.removeEventListener("TabSelect", this, false);
|
||||
this._chromeWindow.getBrowser().removeEventListener("load", this, true);
|
||||
this._chromeWindow.getBrowser().removeEventListener("beforeunload", this, true);
|
||||
this._chromeWindow.removeEventListener("resize", this, false);
|
||||
|
||||
let tabs = this._chromeWindow.getBrowser().tabs;
|
||||
Array.prototype.forEach.call(tabs, this._stopErrorsCount, this);
|
||||
|
||||
this.display.focusManager.removeMonitoredElement(this.outputPanel._frame);
|
||||
this.display.focusManager.removeMonitoredElement(this._element);
|
||||
|
||||
this.display.onVisibilityChange.remove(this.outputPanel._visibilityChanged, this.outputPanel);
|
||||
this.display.onVisibilityChange.remove(this.tooltipPanel._visibilityChanged, this.tooltipPanel);
|
||||
this.display.onOutput.remove(this.outputPanel._outputChanged, this.outputPanel);
|
||||
|
@ -368,9 +374,6 @@ DeveloperToolbar.prototype.handleEvent = function DT_handleEvent(aEvent)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (aEvent.type == "resize") {
|
||||
this.outputPanel._resize();
|
||||
}
|
||||
else if (aEvent.type == "TabClose") {
|
||||
this._stopErrorsCount(aEvent.target);
|
||||
}
|
||||
|
@ -498,11 +501,9 @@ function DT__updateErrorsCount(aChangedTabId)
|
|||
let errors = this._errorsCount[tabId];
|
||||
|
||||
if (errors) {
|
||||
this._webConsoleButton.label =
|
||||
this._webConsoleButtonLabel + " (" + errors + ")";
|
||||
}
|
||||
else {
|
||||
this._webConsoleButton.label = this._webConsoleButtonLabel;
|
||||
this._webConsoleButton.setAttribute("error-count", errors);
|
||||
} else {
|
||||
this._webConsoleButton.removeAttribute("error-count");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -812,7 +813,7 @@ TooltipPanel.prototype._resize = function TP_resize()
|
|||
}
|
||||
|
||||
let offset = 10 + Math.floor(this._dimensions.start * AVE_CHAR_WIDTH);
|
||||
this._frame.style.marginLeft = offset + "px";
|
||||
this._panel.style.marginLeft = offset + "px";
|
||||
|
||||
/*
|
||||
// Bug 744906: UX review - Not sure if we want this code to fatten connector
|
||||
|
|
|
@ -40,6 +40,6 @@ function runTest() {
|
|||
}
|
||||
|
||||
function getLeftMargin() {
|
||||
let style = DeveloperToolbar.tooltipPanel._frame.style.marginLeft;
|
||||
let style = DeveloperToolbar.tooltipPanel._panel.style.marginLeft;
|
||||
return parseInt(style.slice(0, -2), 10);
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@ function test() {
|
|||
addTab(TEST_URI, openToolbar);
|
||||
|
||||
function getErrorsCount() {
|
||||
let match = webconsole.label.match(/\((\d+)\)$/);
|
||||
return match ? match[1] : 0;
|
||||
let count = webconsole.getAttribute("error-count");
|
||||
return count ? count : "0";
|
||||
}
|
||||
|
||||
function onOpenToolbar() {
|
||||
|
|
|
@ -52,7 +52,7 @@ let DeveloperToolbarTest = {
|
|||
ok(false, "DeveloperToolbar.visible at start of openDeveloperToolbar");
|
||||
}
|
||||
else {
|
||||
DeveloperToolbar.show(aCallback);
|
||||
DeveloperToolbar.show(true, aCallback);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -161,6 +161,7 @@
|
|||
@BINPATH@/components/dom.xpt
|
||||
@BINPATH@/components/dom_apps.xpt
|
||||
@BINPATH@/components/dom_base.xpt
|
||||
@BINPATH@/components/dom_system.xpt
|
||||
#ifdef MOZ_B2G_RIL
|
||||
@BINPATH@/components/dom_telephony.xpt
|
||||
@BINPATH@/components/dom_wifi.xpt
|
||||
|
@ -172,6 +173,7 @@
|
|||
#endif
|
||||
@BINPATH@/components/dom_canvas.xpt
|
||||
@BINPATH@/components/dom_contacts.xpt
|
||||
@BINPATH@/components/dom_alarm.xpt
|
||||
@BINPATH@/components/dom_core.xpt
|
||||
@BINPATH@/components/dom_css.xpt
|
||||
@BINPATH@/components/dom_devicestorage.xpt
|
||||
|
@ -217,6 +219,7 @@
|
|||
@BINPATH@/components/gfx.xpt
|
||||
@BINPATH@/components/html5.xpt
|
||||
@BINPATH@/components/htmlparser.xpt
|
||||
@BINPATH@/components/identity.xpt
|
||||
@BINPATH@/components/imglib2.xpt
|
||||
@BINPATH@/components/imgicon.xpt
|
||||
@BINPATH@/components/inspector.xpt
|
||||
|
@ -471,6 +474,8 @@
|
|||
|
||||
@BINPATH@/components/ContactManager.js
|
||||
@BINPATH@/components/ContactManager.manifest
|
||||
@BINPATH@/components/AlarmsManager.js
|
||||
@BINPATH@/components/AlarmsManager.manifest
|
||||
#ifdef ENABLE_MARIONETTE
|
||||
@BINPATH@/chrome/marionette@JAREXT@
|
||||
@BINPATH@/chrome/marionette.manifest
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче