Merge mc to kiwifox

This commit is contained in:
Benoit Girard 2011-12-12 10:15:41 -05:00
commit dac76df26c
560 changed files with 141416 additions and 20723 deletions

View File

@ -44,7 +44,6 @@
#include "nsMai.h"
#include "prlink.h"
#include "prenv.h"
#include "mozilla/Preferences.h"
#include "nsIGConfService.h"
#include "nsIServiceManager.h"
#include "nsAutoPtr.h"
@ -64,10 +63,6 @@ static const char sATKLibName[] = "libatk-1.0.so.0";
static const char sATKHyperlinkImplGetTypeSymbol[] =
"atk_hyperlink_impl_get_type";
static const char sAccEnv [] = "GNOME_ACCESSIBILITY";
static const char sUseSystemPrefsKey[] =
"config.use_system_prefs";
static const char sAccessibilityKey [] =
"config.use_system_prefs.accessibility";
static const char sGconfAccessibilityKey[] =
"/desktop/gnome/interface/accessibility";
@ -630,7 +625,6 @@ nsApplicationAccessibleWrap::Init()
isGnomeATEnabled = !!atoi(envValue);
} else {
//check gconf-2 setting
if (Preferences::GetBool(sUseSystemPrefsKey, false)) {
nsresult rv;
nsCOMPtr<nsIGConfService> gconf =
do_GetService(NS_GCONFSERVICE_CONTRACTID, &rv);
@ -638,10 +632,6 @@ nsApplicationAccessibleWrap::Init()
gconf->GetBool(NS_LITERAL_CSTRING(sGconfAccessibilityKey),
&isGnomeATEnabled);
}
} else {
isGnomeATEnabled =
Preferences::GetBool(sAccessibilityKey, false);
}
}
if (isGnomeATEnabled) {

View File

@ -1066,7 +1066,6 @@ NS_IMETHODIMP nsAccessible::TakeSelection()
return NS_ERROR_FAILURE;
}
/* void takeFocus (); */
NS_IMETHODIMP
nsAccessible::TakeFocus()
{
@ -1078,30 +1077,16 @@ nsAccessible::TakeFocus()
nsIContent* focusContent = mContent;
// If the current element can't take real DOM focus and if it has an ID and
// an ancestor with an aria-activedescendant attribute present, then set DOM
// focus to that ancestor and set aria-activedescendant on the ancestor to
// the ID of the desired element.
// If the accessible focus is managed by container widget then focus the
// widget and set the accessible as its current item.
if (!frame->IsFocusable()) {
nsAutoString id;
if (nsCoreUtils::GetID(mContent, id)) {
nsIContent* ancestorContent = mContent;
while ((ancestorContent = ancestorContent->GetParent()) &&
!ancestorContent->HasAttr(kNameSpaceID_None,
nsGkAtoms::aria_activedescendant));
if (ancestorContent) {
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
if (presShell) {
nsIFrame *frame = ancestorContent->GetPrimaryFrame();
if (frame && frame->IsFocusable()) {
focusContent = ancestorContent;
focusContent->SetAttr(kNameSpaceID_None,
nsGkAtoms::aria_activedescendant,
id, true);
}
}
nsAccessible* widget = ContainerWidget();
if (widget && widget->AreItemsOperable()) {
nsIContent* widgetElm = widget->GetContent();
nsIFrame* widgetFrame = widgetElm->GetPrimaryFrame();
if (widgetFrame && widgetFrame->IsFocusable()) {
focusContent = widgetElm;
widget->SetCurrentItem(this);
}
}
}
@ -2937,6 +2922,18 @@ nsAccessible::CurrentItem()
return nsnull;
}
void
nsAccessible::SetCurrentItem(nsAccessible* aItem)
{
nsIAtom* id = aItem->GetContent()->GetID();
if (id) {
nsAutoString idStr;
id->ToString(idStr);
mContent->SetAttr(kNameSpaceID_None,
nsGkAtoms::aria_activedescendant, idStr, true);
}
}
nsAccessible*
nsAccessible::ContainerWidget() const
{

View File

@ -588,6 +588,11 @@ public:
*/
virtual nsAccessible* CurrentItem();
/**
* Set the current item of the widget.
*/
virtual void SetCurrentItem(nsAccessible* aItem);
/**
* Return container widget this accessible belongs to.
*/

View File

@ -151,6 +151,14 @@ nsHTMLSelectListAccessible::CurrentItem()
return nsnull;
}
void
nsHTMLSelectListAccessible::SetCurrentItem(nsAccessible* aItem)
{
aItem->GetContent()->SetAttr(kNameSpaceID_None,
nsGkAtoms::selected, NS_LITERAL_STRING("true"),
true);
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLSelectListAccessible: nsAccessible protected
@ -686,6 +694,13 @@ nsHTMLComboboxAccessible::CurrentItem()
return AreItemsOperable() ? mListAccessible->CurrentItem() : nsnull;
}
void
nsHTMLComboboxAccessible::SetCurrentItem(nsAccessible* aItem)
{
if (AreItemsOperable())
mListAccessible->SetCurrentItem(aItem);
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLComboboxAccessible: protected

View File

@ -85,6 +85,7 @@ public:
virtual bool IsActiveWidget() const;
virtual bool AreItemsOperable() const;
virtual nsAccessible* CurrentItem();
virtual void SetCurrentItem(nsAccessible* aItem);
protected:
@ -209,6 +210,7 @@ public:
virtual bool IsActiveWidget() const;
virtual bool AreItemsOperable() const;
virtual nsAccessible* CurrentItem();
virtual void SetCurrentItem(nsAccessible* aItem);
protected:
// nsAccessible

View File

@ -46,16 +46,32 @@
@interface mozAccessible : NSObject <mozAccessible>
{
nsAccessibleWrap *mGeckoAccessible; // weak reference; it owns us.
NSMutableArray *mChildren; // strong ref to array of children
/**
* Weak reference; it owns us.
*/
nsAccessibleWrap* mGeckoAccessible;
// 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.
/**
* Strong ref to array of children
*/
NSMutableArray* mChildren;
/**
* 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.
/**
* The nsIAccessible role of our gecko accessible.
*/
PRUint32 mRole;
}
@ -114,6 +130,9 @@
// invalidates and removes all our children from our cached array.
- (void)invalidateChildren;
// invalidates the cached parent, used by invalidateChildren.
- (void)invalidateParent;
// makes ourselves "expired". after this point, we might be around if someone
// has retained us (e.g., a third-party), but we really contain no information.
- (void)expire;
@ -124,7 +143,7 @@
- (void)printHierarchyWithLevel:(unsigned)numSpaces;
- (void)sanityCheckChildren;
- (void)sanityCheckChildren:(NSArray *)theChildren;
- (void)sanityCheckChildren:(NSArray*)theChildren;
#endif
// ---- NSAccessibility methods ---- //

View File

@ -47,20 +47,15 @@
#include "nsObjCExceptions.h"
#include "nsIAccessible.h"
#include "nsIAccessibleRelation.h"
#include "nsIAccessibleText.h"
#include "nsIAccessibleEditableText.h"
#include "Relation.h"
#include "nsRootAccessible.h"
using namespace mozilla::a11y;
// These constants are only defined in OS X SDK 10.4, so we define them in order
// to be able to use for earlier OS versions.
const NSString *kInstanceDescriptionAttribute = @"AXDescription"; // NSAccessibilityDescriptionAttribute
const NSString *kTopLevelUIElementAttribute = @"AXTopLevelUIElement"; // NSAccessibilityTopLevelUIElementAttribute
const NSString *kTextLinkSubrole = @"AXTextLink"; // NSAccessibilitySecureTextFieldSubrole
const NSString *kURLAttribute = @"AXURL";
// converts a screen-global point in the cocoa coordinate system (with origo in the bottom-left corner
// of the screen), into a top-left screen point, that gecko can use.
static inline void
@ -198,8 +193,8 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
NSAccessibilityFocusedAttribute,
NSAccessibilityHelpAttribute,
NSAccessibilityTitleUIElementAttribute,
kTopLevelUIElementAttribute,
kInstanceDescriptionAttribute,
NSAccessibilityTopLevelUIElementAttribute,
NSAccessibilityDescriptionAttribute,
nil];
}
@ -236,7 +231,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
return [self value];
if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute])
return NSAccessibilityRoleDescription([self role], nil);
if ([attribute isEqualToString: (NSString*) kInstanceDescriptionAttribute])
if ([attribute isEqualToString:NSAccessibilityDescriptionAttribute])
return [self customDescription];
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute])
return [NSNumber numberWithBool:[self isFocused]];
@ -244,18 +239,22 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
return [self size];
if ([attribute isEqualToString:NSAccessibilityWindowAttribute])
return [self window];
if ([attribute isEqualToString: (NSString*) kTopLevelUIElementAttribute])
if ([attribute isEqualToString:NSAccessibilityTopLevelUIElementAttribute])
return [self window];
if ([attribute isEqualToString:NSAccessibilityTitleAttribute] ||
[attribute isEqualToString:NSAccessibilityTitleUIElementAttribute])
if ([attribute isEqualToString:NSAccessibilityTitleAttribute])
return [self title];
if ([attribute isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
Relation rel = mGeckoAccessible->RelationByType(nsIAccessibleRelation::RELATION_LABELLED_BY);
nsAccessible* tempAcc = rel.Next();
return tempAcc ? GetNativeFromGeckoAccessible(tempAcc) : nil;
}
if ([attribute isEqualToString:NSAccessibilityHelpAttribute])
return [self help];
#ifdef DEBUG
NSLog (@"!!! %@ can't respond to attribute %@", self, attribute);
#endif
return nil; // be nice and return empty string instead?
return nil;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
@ -349,11 +348,14 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if (mParent)
return mParent;
nsCOMPtr<nsIAccessible> accessibleParent(mGeckoAccessible->GetUnignoredParent());
if (accessibleParent) {
id nativeParent = GetNativeFromGeckoAccessible(accessibleParent);
if (nativeParent)
return GetClosestInterestingAccessible(nativeParent);
return mParent = GetClosestInterestingAccessible(nativeParent);
}
// GetUnignoredParent() returns null when there is no unignored accessible all the way up to
@ -365,7 +367,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
id nativeParent = GetNativeFromGeckoAccessible(static_cast<nsIAccessible*>(root));
NSAssert1 (nativeParent, @"!!! we can't find a parent for %@", self);
return GetClosestInterestingAccessible(nativeParent);
return mParent = GetClosestInterestingAccessible(nativeParent);
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
@ -604,6 +606,8 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
[mChildren makeObjectsPerformSelector:@selector(invalidateParent)];
// make room for new children
[mChildren release];
mChildren = nil;
@ -611,6 +615,11 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (void)invalidateParent
{
mParent = nil;
}
- (void)expire
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;

View File

@ -43,9 +43,6 @@
using namespace mozilla::a11y;
extern const NSString *kInstanceDescriptionAttribute; // NSAccessibilityDescriptionAttribute
extern const NSString *kTopLevelUIElementAttribute; // NSAccessibilityTopLevelUIElementAttribute
enum CheckboxValue {
// these constants correspond to the values in the OS
kUnchecked = 0,
@ -67,12 +64,12 @@ enum CheckboxValue {
NSAccessibilitySizeAttribute, // required
NSAccessibilityWindowAttribute, // required
NSAccessibilityPositionAttribute, // required
kTopLevelUIElementAttribute, // required
NSAccessibilityTopLevelUIElementAttribute, // required
NSAccessibilityHelpAttribute,
NSAccessibilityEnabledAttribute, // required
NSAccessibilityFocusedAttribute, // required
NSAccessibilityTitleAttribute, // required
kInstanceDescriptionAttribute,
NSAccessibilityDescriptionAttribute,
nil];
}
return attributes;
@ -194,13 +191,13 @@ enum CheckboxValue {
NSAccessibilityRoleAttribute, // required
NSAccessibilitySizeAttribute, // required
NSAccessibilityWindowAttribute, // required
kTopLevelUIElementAttribute, // required
NSAccessibilityTopLevelUIElementAttribute, // required
NSAccessibilityHelpAttribute,
NSAccessibilityEnabledAttribute, // required
NSAccessibilityFocusedAttribute, // required
NSAccessibilityTitleAttribute, // required for popupmenus, and for menubuttons with a title
NSAccessibilityChildrenAttribute, // required
kInstanceDescriptionAttribute, // required if it has no title attr
NSAccessibilityDescriptionAttribute, // required if it has no title attr
nil];
}
return attributes;

View File

@ -55,6 +55,43 @@ static id <mozAccessible, mozView> getNativeViewFromRootAccessible (nsAccessible
@implementation mozRootAccessible
- (NSArray*)accessibilityAttributeNames
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
// if we're expired, we don't support any attributes.
if (mIsExpired)
return [NSArray array];
// standard attributes that are shared and supported by root accessible (AXMain) elements.
static NSMutableArray* attributes = nil;
if (!attributes) {
attributes = [[super accessibilityAttributeNames] mutableCopy];
[attributes addObject:NSAccessibilityMainAttribute];
[attributes addObject:NSAccessibilityMinimizedAttribute];
}
return attributes;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (id)accessibilityAttributeValue:(NSString *)attribute
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if ([attribute isEqualToString:NSAccessibilityMainAttribute])
return [NSNumber numberWithBool:[[self window] isMainWindow]];
if ([attribute isEqualToString:NSAccessibilityMinimizedAttribute])
return [NSNumber numberWithBool:[[self window] isMiniaturized]];
return [super accessibilityAttributeValue:attribute];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
// return the AXParent that our parallell NSView tells us about.
- (id)parent
{

View File

@ -5,9 +5,6 @@
using namespace mozilla::a11y;
extern const NSString *kInstanceDescriptionAttribute; // NSAccessibilityDescriptionAttribute
extern const NSString *kTopLevelUIElementAttribute; // NSAccessibilityTopLevelUIElementAttribute
@interface mozTextAccessible (Private)
- (NSString*)subrole;
- (NSString*)selectedText;
@ -55,8 +52,8 @@ extern const NSString *kTopLevelUIElementAttribute; // NSAccessibilityTopLevel
NSAccessibilityWindowAttribute, // required
NSAccessibilityFocusedAttribute, // required
NSAccessibilityEnabledAttribute, // required
kTopLevelUIElementAttribute, // required (on OS X 10.4+)
kInstanceDescriptionAttribute, // required (on OS X 10.4+)
NSAccessibilityTopLevelUIElementAttribute, // required
NSAccessibilityDescriptionAttribute, // required
/* text-specific attributes */
NSAccessibilitySelectedTextAttribute, // required
NSAccessibilitySelectedTextRangeAttribute, // required
@ -256,8 +253,8 @@ extern const NSString *kTopLevelUIElementAttribute; // NSAccessibilityTopLevel
NSAccessibilityChildrenAttribute, // required
NSAccessibilityHelpAttribute,
// NSAccessibilityExpandedAttribute, // required
kTopLevelUIElementAttribute, // required (on OS X 10.4+)
kInstanceDescriptionAttribute, // required (on OS X 10.4+)
NSAccessibilityTopLevelUIElementAttribute, // required
NSAccessibilityDescriptionAttribute, // required
/* text-specific attributes */
NSAccessibilitySelectedTextAttribute, // required
NSAccessibilitySelectedTextRangeAttribute, // required

View File

@ -302,6 +302,22 @@ nsXULSelectableAccessible::CurrentItem()
return nsnull;
}
void
nsXULSelectableAccessible::SetCurrentItem(nsAccessible* aItem)
{
if (!mSelectControl)
return;
nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
do_QueryInterface(aItem->GetContent());
nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
do_QueryInterface(mSelectControl);
if (multiSelectControl)
multiSelectControl->SetCurrentItem(itemElm);
else
mSelectControl->SetSelectedItem(itemElm);
}
////////////////////////////////////////////////////////////////////////////////
// nsXULMenuitemAccessible
////////////////////////////////////////////////////////////////////////////////
@ -893,3 +909,9 @@ nsXULMenubarAccessible::CurrentItem()
}
return nsnull;
}
void
nsXULMenubarAccessible::SetCurrentItem(nsAccessible* aItem)
{
NS_ERROR("nsXULMenubarAccessible::SetCurrentItem not implemented");
}

View File

@ -67,6 +67,7 @@ public:
// Widgets
virtual nsAccessible* CurrentItem();
virtual void SetCurrentItem(nsAccessible* aItem);
protected:
// nsIDOMXULMultiSelectControlElement inherits from this, so we'll always have
@ -170,6 +171,7 @@ public:
virtual bool IsActiveWidget() const;
virtual bool AreItemsOperable() const;
virtual nsAccessible* CurrentItem();
virtual void SetCurrentItem(nsAccessible* aItem);
};
#endif

View File

@ -279,6 +279,12 @@ nsXULTreeAccessible::CurrentItem()
return nsnull;
}
void
nsXULTreeAccessible::SetCurrentItem(nsAccessible* aItem)
{
NS_ERROR("nsXULTreeAccessible::SetCurrentItem not implemented");
}
already_AddRefed<nsIArray>
nsXULTreeAccessible::SelectedItems()
{

View File

@ -106,6 +106,7 @@ public:
virtual bool IsActiveWidget() const;
virtual bool AreItemsOperable() const;
virtual nsAccessible* CurrentItem();
virtual void SetCurrentItem(nsAccessible* aItem);
virtual nsAccessible* ContainerWidget() const;

View File

@ -48,6 +48,7 @@ include $(topsrcdir)/config/rules.mk
_TEST_FILES =\
test_focusedChild.html \
test_takeFocus.html \
test_takeFocus.xul \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -18,9 +18,7 @@
<script type="application/javascript">
////////////////////////////////////////////////////////////////////////////
// Test
var gQueue = null;
// Invokers
function takeFocusInvoker(aID)
{
@ -39,6 +37,12 @@
}
}
////////////////////////////////////////////////////////////////////////////
// Test
//gA11yEventDumpToConsole = true; // debug stuff
var gQueue = null;
function doTest()
{
gQueue = new eventQueue();
@ -49,6 +53,7 @@
gQueue.push(new takeFocusInvoker("item2"));
gQueue.push(new takeFocusInvoker("plugin"));
gQueue.push(new takeFocusInvoker(document));
gQueue.push(new takeFocusInvoker("lb_item2"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
@ -75,6 +80,11 @@
title="No focus event fired on document when focus is set to the document while focused in a plugin">
Mozilla Bug 646361
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=706067"
title="Make takeFocus work on widget items">
Mozilla Bug 706067
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
@ -92,5 +102,10 @@
</div>
<embed id="plugin" type="application/x-test" width="200" height="200" wmode="window"></embed>
<select id="listbox" size="5">
<option id="lb_item1">item1</option>
<option id="lb_item2">item2</option>
</select>
</body>
</html>

View File

@ -0,0 +1,125 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/browser.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible focus testing">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../states.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript"
src="../treeview.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Invokers
function setTreeView(aTreeID, aView)
{
this.DOMNode = getNode(aTreeID);
this.eventSeq = [
new invokerChecker(EVENT_REORDER, this.DOMNode)
];
this.invoke = function setTreeView_invoke()
{
this.DOMNode.treeBoxObject.view = aView;
}
this.getID = function setTreeView_getID()
{ return "set tree view for " + prettyName(aTreeID); }
};
function takeFocusInvoker(aID, aArgConverterFunc)
{
this.targetFunc = aArgConverterFunc ? aArgConverterFunc : getAccessible;
this.eventSeq = [ new focusChecker(this.targetFunc, aID) ];
this.invoke = function takeFocusInvoker_invoke()
{
this.targetFunc.call(null, aID).takeFocus();
}
this.getID = function takeFocusInvoker_getID()
{
return "takeFocus for " + prettyName(aID);
}
}
function getLastChild(aID)
{
return getAccessible(aID).lastChild;
}
////////////////////////////////////////////////////////////////////////////
// Tests
//gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true; // debug stuff
var gQueue = null;
function doTests()
{
// Test focus events.
gQueue = new eventQueue();
gQueue.push(new setTreeView("tree", new nsTableTreeView(5)));
gQueue.push(new takeFocusInvoker("tree", getLastChild));
gQueue.push(new takeFocusInvoker("listitem2"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=706067"
title="Make takeFocus work on widget items">
Mozilla Bug 706067
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<tree id="tree" flex="1">
<treecols>
<treecol id="col1" flex="1" primary="true" label="column"/>
<treecol id="col2" flex="1" label="column 2"/>
</treecols>
<treechildren id="treechildren"/>
</tree>
<listbox id="listbox">
<listitem id="listitem1">item1</listitem>
<listitem id="listitem2">item2</listitem>
</listbox>
<vbox id="eventdump"/>
</vbox>
</hbox>
</window>

View File

@ -97,6 +97,22 @@
// disabled, too. See bug 429285.
testAriaDisabledTree("group");
// aria-multiline
testStates("aria_multiline_textbox", 0, EXT_STATE_MULTI_LINE);
// aria-multiselectable
testStates("aria_multiselectable_listbox",
STATE_MULTISELECTABLE | STATE_EXTSELECTABLE);
// aria-pressed
testStates("aria_pressed_button", STATE_PRESSED | STATE_CHECKABLE);
// aria-readonly
testStates("aria_readonly_textbox", STATE_READONLY);
// aria-selectable
testStates("aria_selectable_listitem", STATE_SELECTABLE | STATE_SELECTED);
// active state caused by aria-activedescendant
testStates("as_item1", 0, EXT_STATE_ACTIVE);
testStates("as_item2", 0, 0, 0, EXT_STATE_ACTIVE);
@ -193,6 +209,11 @@
title="Expose active state on current item of selectable widgets">
Mozilla Bug 689847
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=457226"
title="Mochitests for ARIA states">
Mozilla Bug 457226
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
@ -225,6 +246,13 @@
<div id="aria_mixed_checkbox" role="checkbox" aria-checked="mixed">
I might agree
</div>
<div id="aria_multiline_textbox" role="textbox" aria-multiline="true"></div>
<div id="aria_multiselectable_listbox" role="listbox" aria-multiselectable="true"></div>
<div id="aria_pressed_button" role="button" aria-pressed="true">Button</div>
<div id="aria_readonly_textbox" role="textbox" aria-readonly="true">This text should be readonly</div>
<div role="listbox">
<div id="aria_selectable_listitem" role="option" aria-selected="true">Item1</div>
</div>
<!-- Test that aria-disabled state gets propagated to all descendants -->
<div id="group" role="group" aria-disabled="true">

5211
b2g/chrome/content/httpd.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -39,22 +39,55 @@ const Ci = Components.interfaces;
const Cu = Components.utils;
const CC = Components.Constructor;
Cu.import('resource://gre/modules/Services.jsm');
const LocalFile = CC('@mozilla.org/file/local;1',
'nsILocalFile',
'initWithPath');
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
XPCOMUtils.defineLazyGetter(Services, 'env', function() {
return Cc['@mozilla.org/process/environment;1']
.getService(Ci.nsIEnvironment);
});
XPCOMUtils.defineLazyGetter(Services, 'ss', function() {
return Cc['@mozilla.org/content/style-sheet-service;1']
.getService(Ci.nsIStyleSheetService);
});
XPCOMUtils.defineLazyGetter(Services, 'fm', function() {
return Cc['@mozilla.org/focus-manager;1']
.getService(Ci.nsIFocusManager);
});
// In order to use http:// scheme instead of file:// scheme
// (that is much more restricted) the following code kick-off
// a local http server listening on http://127.0.0.1:8888 and
// http://localhost:8888.
function startupHttpd(baseDir, port) {
const httpdURL = 'chrome://browser/content/httpd.js';
let httpd = {};
Services.scriptloader.loadSubScript(httpdURL, httpd);
let server = new httpd.nsHttpServer();
server.registerDirectory('/', new LocalFile(baseDir));
server.start(port);
}
// XXX until we have a security model, just let the pre-installed
// app used indexedDB.
function allowIndexedDB(url) {
let uri = Services.io.newURI(url, null, null);
Services.perms.add(uri, 'indexedDB', Ci.nsIPermissionManager.ALLOW_ACTION);
}
var shell = {
get home() {
delete this.home;
return this.home = document.getElementById('homescreen');
},
get homeSrc() {
get homeURL() {
try {
let homeSrc = Cc['@mozilla.org/process/environment;1']
.getService(Ci.nsIEnvironment)
.get('B2G_HOMESCREEN');
let homeSrc = Services.env.get('B2G_HOMESCREEN');
if (homeSrc)
return homeSrc;
} catch (e) {}
@ -73,16 +106,41 @@ var shell = {
},
start: function shell_init() {
let homeURL = this.homeURL;
if (!homeURL) {
let msg = 'Fatal error during startup: [No homescreen found]';
return alert(msg);
}
window.controllers.appendController(this);
window.addEventListener('keypress', this);
this.home.addEventListener('load', this, true);
let ioService = Cc['@mozilla.org/network/io-service;1']
.getService(Ci.nsIIOService2);
ioService.offline = false;
try {
Services.io.offline = false;
let fileScheme = 'file://';
if (homeURL.substring(0, fileScheme.length) == fileScheme) {
homeURL = homeURL.replace(fileScheme, '');
let baseDir = homeURL.split('/');
baseDir.pop();
baseDir = baseDir.join('/');
const SERVER_PORT = 8888;
startupHttpd(baseDir, SERVER_PORT);
let baseHost = 'http://localhost';
homeURL = homeURL.replace(baseDir, baseHost + ':' + SERVER_PORT);
}
allowIndexedDB(homeURL);
} catch (e) {
let msg = 'Fatal error during startup: [' + e + '[' + homeURL + ']';
return alert(msg);
}
let browser = this.home;
browser.homePage = this.homeSrc;
browser.homePage = homeURL;
browser.goHome();
},
@ -183,9 +241,7 @@ var shell = {
let shouldOpen = parseInt(data);
if (shouldOpen && !isKeyboardOpened) {
activeElement = Cc['@mozilla.org/focus-manager;1']
.getService(Ci.nsIFocusManager)
.focusedElement;
activeElement = Services.fm.focusedElement;
if (!activeElement)
return;
@ -198,7 +254,7 @@ var shell = {
}
};
Services.obs.addObserver(constructor, "ime-enabled-state-changed", false);
Services.obs.addObserver(constructor, 'ime-enabled-state-changed', false);
['ContentStart', 'keypress', 'mousedown'].forEach(function vkm_events(type) {
window.addEventListener(type, constructor, true);
});

View File

@ -151,18 +151,17 @@
// Mouse events has been cancelled so dispatch a sequence
// of events to where touchend has been fired
if (preventMouseEvents) {
let target = evt.target;
ignoreEvents = true;
try {
this.fireMouseEvent('mousemove', evt);
this.fireMouseEvent('mousedown', evt);
this.fireMouseEvent('mouseup', evt);
} catch (e) {
alert(e);
}
evt.preventDefault();
evt.stopPropagation();
let target = evt.target;
ignoreEvents = true;
window.setTimeout(function dispatchMouseEvents(self) {
self.fireMouseEvent('mousemove', evt);
self.fireMouseEvent('mousedown', evt);
self.fireMouseEvent('mouseup', evt);
ignoreEvents = false;
}, 0, this);
}
debug('click: fire');

View File

@ -8,6 +8,7 @@ chrome.jar:
content/shell.js (content/shell.js)
content/touch.js (content/touch.js)
content/commandUtil.js (content/commandUtil.js)
content/httpd.js (content/httpd.js)
% override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
content/netError.xhtml (content/netError.xhtml)

View File

@ -391,6 +391,12 @@
@BINPATH@/components/messageWakeupService.manifest
@BINPATH@/components/nsFilePicker.js
@BINPATH@/components/nsFilePicker.manifest
#ifdef MOZ_B2G_RIL
@BINPATH@/components/nsTelephonyWorker.manifest
@BINPATH@/components/nsTelephonyWorker.js
@BINPATH@/components/Telephony.manifest
@BINPATH@/components/Telephony.js
#endif
#ifdef XP_MACOSX
@BINPATH@/components/libalerts_s.dylib
#endif

View File

@ -66,7 +66,7 @@ pref("extensions.getAddons.cache.enabled", true);
pref("extensions.getAddons.maxResults", 15);
pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/guid:%IDS%?src=firefox&appOS=%OS%&appVersion=%VERSION%");
pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/firefox/search?q=%TERMS%");
pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/%TERMS%/all/%MAX_RESULTS%/%OS%/%VERSION%?src=firefox");
pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/%TERMS%/all/%MAX_RESULTS%/%OS%/%VERSION%/%COMPATIBILITY_MODE%?src=firefox");
pref("extensions.webservice.discoverURL", "https://services.addons.mozilla.org/%LOCALE%/firefox/discovery/pane/%VERSION%/%OS%");
// Blocklist preferences

View File

@ -243,11 +243,6 @@ panel[noactions] > richlistbox > richlistitem[type~="action"] > .ac-url-box > .a
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#urlbar-rich-result-popup");
}
#urlbar-throbber:not([busy="true"]),
#urlbar-throbber[busy="true"] + #page-proxy-favicon {
display: none;
}
#urlbar-container[combined] > #urlbar > #urlbar-icons > #go-button,
#urlbar[pageproxystate="invalid"] > #urlbar-icons > .urlbar-icon:not(#go-button),
#urlbar[pageproxystate="valid"] > #urlbar-icons > #go-button,

View File

@ -2601,28 +2601,6 @@ function UpdateUrlbarSearchSplitterState()
splitter.parentNode.removeChild(splitter);
}
var LocationBarHelpers = {
_timeoutID: null,
_searchBegin: function LocBar_searchBegin() {
function delayedBegin(self) {
self._timeoutID = null;
document.getElementById("urlbar-throbber").setAttribute("busy", "true");
}
this._timeoutID = setTimeout(delayedBegin, 500, this);
},
_searchComplete: function LocBar_searchComplete() {
// Did we finish the search before delayedBegin was invoked?
if (this._timeoutID) {
clearTimeout(this._timeoutID);
this._timeoutID = null;
}
document.getElementById("urlbar-throbber").removeAttribute("busy");
}
};
function UpdatePageProxyState()
{
if (gURLBar && gURLBar.value != gLastValidURLStr)

View File

@ -516,8 +516,6 @@
ontextentered="this.handleCommand(param);"
ontextreverted="return this.handleRevert();"
pageproxystate="invalid"
onsearchbegin="LocationBarHelpers._searchBegin();"
onsearchcomplete="LocationBarHelpers._searchComplete();"
onfocus="document.getElementById('identity-box').style.MozUserFocus= 'normal'"
onblur="setTimeout(function() document.getElementById('identity-box').style.MozUserFocus = '', 0);">
<box id="notification-popup-box" hidden="true" align="center">
@ -538,7 +536,6 @@
<hbox id="identity-box-inner" align="center">
<stack id="page-proxy-stack"
onclick="PageProxyClickHandler(event);">
<image id="urlbar-throbber" busy="false"/>
<image id="page-proxy-favicon" validate="never"
pageproxystate="invalid"
onerror="this.removeAttribute('src');"/>

View File

@ -52,20 +52,15 @@ ifneq (,$(filter windows cocoa gtk2, $(MOZ_WIDGET_TOOLKIT)))
SHARED_LIBRARY_LIBS += ../shell/src/$(LIB_PREFIX)shellservice_s.$(LIB_SUFFIX)
endif
EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME_PATH,unicharutil_external_s,$(LIBXUL_DIST)/lib)
# migration requires mozreg
LOCAL_INCLUDES += -I$(srcdir)/../migration/src
SHARED_LIBRARY_LIBS += ../migration/src/$(LIB_PREFIX)migration_s.$(LIB_SUFFIX)
EXTRA_DSO_LDOPTS += $(LIBXUL_DIST)/lib/$(LIB_PREFIX)mozreg_s.$(LIB_SUFFIX)
# This has to come after the above chunk, because mozreg_s has dependencies on
# stuff in MOZ_COMPONENT_LIBS.
EXTRA_DSO_LDOPTS += \
$(call EXPAND_LIBNAME_PATH,unicharutil_external_s,$(LIBXUL_DIST)/lib) \
$(LIBXUL_DIST)/lib/$(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
LOCAL_INCLUDES += -I$(srcdir)/../migration/src
SHARED_LIBRARY_LIBS += ../migration/src/$(LIB_PREFIX)migration_s.$(LIB_SUFFIX)
# Mac: Need to link with CoreFoundation for Mac Migrators (PList reading code)
# GTK2: Need to link with glib for GNOME shell service
ifneq (,$(filter cocoa gtk2,$(MOZ_WIDGET_TOOLKIT)))

View File

@ -56,7 +56,6 @@
#include "nsDirectoryServiceDefs.h"
#include "nsServiceManagerUtils.h"
#include "NSReg.h"
#include "nsStringAPI.h"
#include "nsUnicharUtils.h"
#ifdef XP_WIN
@ -69,18 +68,6 @@
#include "nsAutoPtr.h"
#ifndef MAXPATHLEN
#ifdef PATH_MAX
#define MAXPATHLEN PATH_MAX
#elif defined(_MAX_PATH)
#define MAXPATHLEN _MAX_PATH
#elif defined(CCHMAXPATH)
#define MAXPATHLEN CCHMAXPATH
#else
#define MAXPATHLEN 1024
#endif
#endif
///////////////////////////////////////////////////////////////////////////////
// nsIProfileMigrator
@ -143,15 +130,6 @@ nsProfileMigrator::Migrate(nsIProfileStartup* aStartup)
getter_AddRefs(migrateWizard));
}
NS_IMETHODIMP
nsProfileMigrator::Import()
{
if (ImportRegistryProfiles(NS_LITERAL_CSTRING("Firefox")))
return NS_OK;
return NS_ERROR_FAILURE;
}
///////////////////////////////////////////////////////////////////////////////
// nsProfileMigrator
@ -272,110 +250,3 @@ nsProfileMigrator::GetDefaultBrowserMigratorKey(nsACString& aKey,
#endif
return NS_ERROR_FAILURE;
}
bool
nsProfileMigrator::ImportRegistryProfiles(const nsACString& aAppName)
{
nsresult rv;
nsCOMPtr<nsIToolkitProfileService> profileSvc
(do_GetService(NS_PROFILESERVICE_CONTRACTID));
NS_ENSURE_TRUE(profileSvc, false);
nsCOMPtr<nsIProperties> dirService
(do_GetService("@mozilla.org/file/directory_service;1"));
NS_ENSURE_TRUE(dirService, false);
nsCOMPtr<nsILocalFile> regFile;
#ifdef XP_WIN
rv = dirService->Get(NS_WIN_APPDATA_DIR, NS_GET_IID(nsILocalFile),
getter_AddRefs(regFile));
NS_ENSURE_SUCCESS(rv, false);
regFile->AppendNative(aAppName);
regFile->AppendNative(NS_LITERAL_CSTRING("registry.dat"));
#elif defined(XP_MACOSX)
rv = dirService->Get(NS_MAC_USER_LIB_DIR, NS_GET_IID(nsILocalFile),
getter_AddRefs(regFile));
NS_ENSURE_SUCCESS(rv, false);
regFile->AppendNative(aAppName);
regFile->AppendNative(NS_LITERAL_CSTRING("Application Registry"));
#elif defined(XP_OS2)
rv = dirService->Get(NS_OS2_HOME_DIR, NS_GET_IID(nsILocalFile),
getter_AddRefs(regFile));
NS_ENSURE_SUCCESS(rv, false);
regFile->AppendNative(aAppName);
regFile->AppendNative(NS_LITERAL_CSTRING("registry.dat"));
#else
rv = dirService->Get(NS_UNIX_HOME_DIR, NS_GET_IID(nsILocalFile),
getter_AddRefs(regFile));
NS_ENSURE_SUCCESS(rv, false);
nsCAutoString dotAppName;
ToLowerCase(aAppName, dotAppName);
dotAppName.Insert('.', 0);
regFile->AppendNative(dotAppName);
regFile->AppendNative(NS_LITERAL_CSTRING("appreg"));
#endif
nsCAutoString path;
rv = regFile->GetNativePath(path);
NS_ENSURE_SUCCESS(rv, false);
if (NR_StartupRegistry())
return false;
bool migrated = false;
HREG reg = nsnull;
RKEY profiles = 0;
REGENUM enumstate = 0;
char profileName[MAXREGNAMELEN];
if (NR_RegOpen(path.get(), &reg))
goto cleanup;
if (NR_RegGetKey(reg, ROOTKEY_COMMON, "Profiles", &profiles))
goto cleanup;
while (!NR_RegEnumSubkeys(reg, profiles, &enumstate,
profileName, MAXREGNAMELEN, REGENUM_CHILDREN)) {
#ifdef DEBUG_bsmedberg
printf("Found profile %s.\n", profileName);
#endif
RKEY profile = 0;
if (NR_RegGetKey(reg, profiles, profileName, &profile)) {
NS_ERROR("Could not get the key that was enumerated.");
continue;
}
char profilePath[MAXPATHLEN];
if (NR_RegGetEntryString(reg, profile, "directory",
profilePath, MAXPATHLEN))
continue;
nsCOMPtr<nsILocalFile> profileFile
(do_CreateInstance("@mozilla.org/file/local;1"));
if (!profileFile)
continue;
#if defined (XP_MACOSX)
rv = profileFile->SetPersistentDescriptor(nsDependentCString(profilePath));
#else
NS_ConvertUTF8toUTF16 widePath(profilePath);
rv = profileFile->InitWithPath(widePath);
#endif
if (NS_FAILED(rv)) continue;
nsCOMPtr<nsIToolkitProfile> tprofile;
profileSvc->CreateProfile(profileFile, nsnull,
nsDependentCString(profileName),
getter_AddRefs(tprofile));
migrated = true;
}
cleanup:
if (reg)
NR_RegClose(reg);
NR_ShutdownRegistry();
return migrated;
}

View File

@ -58,12 +58,6 @@ protected:
nsresult GetDefaultBrowserMigratorKey(nsACString& key,
nsCOMPtr<nsIBrowserProfileMigrator>& bpm);
/**
* Import profiles from ~/.firefox/
* @return true if any profiles imported.
*/
bool ImportRegistryProfiles(const nsACString& aAppName);
};
#endif

View File

@ -1339,7 +1339,7 @@ PlacesTreeView.prototype = {
// if they go through the "result" API.
if (PlacesUtils.nodeIsSeparator(node))
return "";
return PlacesUIUtils.getBestTitle(node);
return PlacesUIUtils.getBestTitle(node, true);
case this.COLUMN_TYPE_TAGS:
return node.tags;
case this.COLUMN_TYPE_URI:

View File

@ -719,7 +719,7 @@ var PlacesUIUtils = {
return aUrlString.substr(0, aUrlString.indexOf(":"));
},
getBestTitle: function PUIU_getBestTitle(aNode) {
getBestTitle: function PUIU_getBestTitle(aNode, aDoNotCutTitle) {
var title;
if (!aNode.title && PlacesUtils.uriTypes.indexOf(aNode.type) != -1) {
// if node title is empty, try to set the label using host and filename
@ -729,10 +729,14 @@ var PlacesUIUtils = {
var host = uri.host;
var fileName = uri.QueryInterface(Ci.nsIURL).fileName;
// if fileName is empty, use path to distinguish labels
if (aDoNotCutTitle) {
title = host + uri.path;
} else {
title = host + (fileName ?
(host ? "/" + this.ellipsis + "/" : "") + fileName :
uri.path);
}
}
catch (e) {
// Use (no title) for non-standard URIs (data:, javascript:, ...)
title = "";

View File

@ -336,7 +336,7 @@ var bookmarksObserver = {
let cellText = tree.view.getCellText(aElementOrTreeIndex,
tree.columns.getColumnAt(0));
if (!aNewValue)
return cellText == PlacesUIUtils.getBestTitle(tree.view.nodeForTreeIndex(aElementOrTreeIndex));
return cellText == PlacesUIUtils.getBestTitle(tree.view.nodeForTreeIndex(aElementOrTreeIndex), true);
return cellText == aNewValue;
}
else {

View File

@ -1861,6 +1861,8 @@ SessionStoreService.prototype = {
var entry = { url: aEntry.URI.spec };
try {
// throwing is expensive, we know that about: pages will throw
if (entry.url.indexOf("about:") != 0)
aHostSchemeData.push({ host: aEntry.URI.host, scheme: aEntry.URI.scheme });
}
catch (ex) {
@ -1959,24 +1961,26 @@ SessionStoreService.prototype = {
}
if (aEntry.childCount > 0) {
entry.children = [];
let children = [];
for (var i = 0; i < aEntry.childCount; i++) {
var child = aEntry.GetChildAt(i);
if (child) {
entry.children.push(this._serializeHistoryEntry(child, aFullData,
aIsPinned, aHostSchemeData));
}
else { // to maintain the correct frame order, insert a dummy entry
entry.children.push({ url: "about:blank" });
}
// don't try to restore framesets containing wyciwyg URLs (cf. bug 424689 and bug 450595)
if (/^wyciwyg:\/\//.test(entry.children[i].url)) {
delete entry.children;
if (child.URI.schemeIs("wyciwyg")) {
children = [];
break;
}
children.push(this._serializeHistoryEntry(child, aFullData,
aIsPinned, aHostSchemeData));
}
}
if (children.length)
entry.children = children;
}
return entry;
},

View File

@ -159,6 +159,7 @@ _BROWSER_TEST_FILES = \
browser_687710.js \
browser_687710_2.js \
browser_694378.js \
browser_705597.js \
$(NULL)
ifneq ($(OS_ARCH),Darwin)

View File

@ -0,0 +1,57 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let tabState = {
entries: [{url: "about:home", children: [{url: "about:mozilla"}]}]
};
function test() {
waitForExplicitFinish();
let tab = gBrowser.addTab("about:blank");
registerCleanupFunction(function () gBrowser.removeTab(tab));
let browser = tab.linkedBrowser;
whenBrowserLoaded(browser, function () {
ss.setTabState(tab, JSON.stringify(tabState));
let sessionHistory = browser.sessionHistory;
let entry = sessionHistory.getEntryAtIndex(0, false);
whenChildCount(entry, 1, function () {
whenChildCount(entry, 2, function () {
whenBrowserLoaded(browser, function () {
let {entries} = JSON.parse(ss.getTabState(tab));
is(entries.length, 1, "tab has one history entry");
ok(!entries[0].children, "history entry has no subframes");
finish();
});
// reload the browser to deprecate the subframes
browser.reload();
});
// create a dynamic subframe
let doc = browser.contentDocument;
let iframe = doc.createElement("iframe");
iframe.setAttribute("src", "about:mozilla");
doc.body.appendChild(iframe);
});
});
}
function whenBrowserLoaded(aBrowser, aCallback) {
aBrowser.addEventListener("load", function onLoad() {
aBrowser.removeEventListener("load", onLoad, true);
executeSoon(aCallback);
}, true);
}
function whenChildCount(aEntry, aChildCount, aCallback) {
if (aEntry.childCount == aChildCount)
aCallback();
else
executeSoon(function () whenChildCount(aEntry, aChildCount, aCallback));
}

View File

@ -169,6 +169,7 @@ _BROWSER_FILES = \
browser_tabview_bug705621.js \
browser_tabview_bug706430.js \
browser_tabview_bug706736.js \
browser_tabview_bug707466.js \
browser_tabview_click_group.js \
browser_tabview_dragdrop.js \
browser_tabview_exit_button.js \

View File

@ -0,0 +1,60 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
waitForExplicitFinish();
// create two groups and each group has one tab item
let newState = {
windows: [{
tabs: [{
entries: [{ url: "about:blank" }],
hidden: true,
attributes: {},
extData: {
"tabview-tab":
'{"bounds":{"left":21,"top":29,"width":204,"height":153},' +
'"userSize":null,"url":"about:blank","groupID":1,' +
'"imageData":null,"title":null}'
}
},{
entries: [{ url: "about:blank" }],
hidden: false,
attributes: {},
extData: {
"tabview-tab":
'{"bounds":{"left":315,"top":29,"width":111,"height":84},' +
'"userSize":null,"url":"about:blank","groupID":2,' +
'"imageData":null,"title":null}'
},
}],
selected:2,
_closedTabs: [],
extData: {
"tabview-groups": '{"nextID":3,"activeGroupId":2}',
"tabview-group":
'{"1":{"bounds":{"left":15,"top":5,"width":280,"height":232},' +
'"userSize":null,"title":"","id":1},' +
'"2":{"bounds":{"left":309,"top":5,"width":267,"height":226},' +
'"userSize":null,"title":"","id":2}}',
"tabview-ui": '{"pageBounds":{"left":0,"top":0,"width":788,"height":548}}'
}, sizemode:"normal"
}]
};
newWindowWithState(newState, function(win) {
registerCleanupFunction(function () win.close());
whenTabViewIsShown(function() {
let cw = win.TabView.getContentWindow();
is(cw.GroupItems.groupItems.length, 2, "There are still two groups");
is(win.gBrowser.tabs.length, 1, "There is only one tab");
is(cw.UI.getActiveTab(), win.gBrowser.selectedTab._tabViewTabItem, "The last tab is selected");
finish();
}, win);
win.gBrowser.removeTab(win.gBrowser.selectedTab);
});
}

View File

@ -475,7 +475,7 @@ let UI = {
} else {
GroupItems.setActiveGroupItem(item);
if (!options || !options.dontSetActiveTabInGroup) {
let activeTab = item.getActiveTab()
let activeTab = item.getActiveTab();
if (activeTab)
this._setActiveTab(activeTab);
}
@ -574,6 +574,7 @@ let UI = {
TabItems.resumePainting();
});
} else {
if (!currentTab || !currentTab._tabViewTabItem)
self.clearActiveTab();
self._isChangingVisibility = false;
dispatchEvent(event);

View File

@ -1,3 +1,5 @@
. $topsrcdir/build/macosx/common
ac_add_options --enable-debug
ac_add_options --enable-trace-malloc
ac_add_options --enable-accessibility

View File

@ -37,7 +37,7 @@
* ***** END LICENSE BLOCK ***** */
var EXPORTED_SYMBOLS = [ "Templater" ];
var EXPORTED_SYMBOLS = [ "Templater", "template" ];
Components.utils.import("resource://gre/modules/Services.jsm");
const Node = Components.interfaces.nsIDOMNode;
@ -45,12 +45,53 @@ const Node = Components.interfaces.nsIDOMNode;
// WARNING: do not 'use_strict' without reading the notes in _envEval();
/**
* A templater that allows one to quickly template DOM nodes.
* Begin a new templating process.
* @param node A DOM element or string referring to an element's id
* @param data Data to use in filling out the template
* @param options Options to customize the template processing. One of:
* - allowEval: boolean (default false) Basic template interpolations are
* either property paths (e.g. ${a.b.c.d}), however if allowEval=true then we
* allow arbitrary JavaScript
*/
function Templater() {
function template(node, data, options) {
var template = new Templater(options || {});
template.processNode(node, data);
return template;
}
/**
* Construct a Templater object. Use template() in preference to this ctor.
* @deprecated Use template(node, data, options);
*/
function Templater(options) {
if (options == null) {
options = { allowEval: true };
}
this.options = options;
this.stack = [];
}
/**
* Cached regex used to find ${...} sections in some text.
* Performance note: This regex uses ( and ) to capture the 'script' for
* further processing. Not all of the uses of this regex use this feature so
* if use of the capturing group is a performance drain then we should split
* this regex in two.
*/
Templater.prototype._templateRegion = /\$\{([^}]*)\}/g;
/**
* Cached regex used to split a string using the unicode chars F001 and F002.
* See Templater._processTextNode() for details.
*/
Templater.prototype._splitSpecial = /\uF001|\uF002/;
/**
* Cached regex used to detect if a script is capable of being interpreted
* using Template._property() or if we need to use Template._envEval()
*/
Templater.prototype._isPropertyScript = /^[a-zA-Z0-9.]*$/;
/**
* Recursive function to walk the tree processing the attributes as it goes.
* @param node the node to process. If you pass a string in instead of a DOM
@ -111,7 +152,7 @@ Templater.prototype.processNode = function(node, data) {
}
} else {
// Replace references in all other attributes
var newValue = value.replace(/\$\{[^}]*\}/g, function(path) {
var newValue = value.replace(this._templateRegion, function(path) {
return this._envEval(path.slice(2, -1), data, value);
}.bind(this));
// Remove '_' prefix of attribute names so the DOM won't try
@ -295,8 +336,8 @@ Templater.prototype._processTextNode = function(node, data) {
// We can then split using \uF001 or \uF002 to get an array of strings
// where scripts are prefixed with $.
// \uF001 and \uF002 are just unicode chars reserved for private use.
value = value.replace(/\$\{([^}]*)\}/g, '\uF001$$$1\uF002');
var parts = value.split(/\uF001|\uF002/);
value = value.replace(this._templateRegion, '\uF001$$$1\uF002');
var parts = value.split(this._splitSpecial);
if (parts.length > 1) {
parts.forEach(function(part) {
if (part === null || part === undefined || part === '') {
@ -363,7 +404,7 @@ Templater.prototype._handleAsync = function(thing, siblingNode, inserter) {
* @return The string stripped of ${ and }, or untouched if it does not match
*/
Templater.prototype._stripBraces = function(str) {
if (!str.match(/\$\{.*\}/g)) {
if (!str.match(this._templateRegion)) {
this._handleError('Expected ' + str + ' to match ${...}');
return str;
}
@ -427,18 +468,27 @@ Templater.prototype._property = function(path, data, newValue) {
* execution failed.
*/
Templater.prototype._envEval = function(script, data, frame) {
with (data) {
try {
this.stack.push(frame);
if (this._isPropertyScript.test(script)) {
return this._property(script, data);
} else {
if (!this.options.allowEval) {
this._handleError('allowEval is not set, however \'' + script + '\'' +
' can not be resolved using a simple property path.');
return '${' + script + '}';
}
with (data) {
return eval(script);
}
}
} catch (ex) {
this._handleError('Template error evaluating \'' + script + '\'' +
' environment=' + Object.keys(data).join(', '), ex);
return script;
return '${' + script + '}';
} finally {
this.stack.pop();
}
}
};
/**

View File

@ -22,7 +22,7 @@ function runTest(index) {
holder.innerHTML = options.template;
info('Running ' + options.name);
new Templater().processNode(holder, options.data);
template(holder, options.data, options.options);
if (typeof options.result == 'string') {
is(holder.innerHTML, options.result, options.name);
@ -88,6 +88,7 @@ var tests = [
function() { return {
name: 'returnDom',
template: '<div id="ex2">${__element.ownerDocument.createTextNode(\'pass 2\')}</div>',
options: { allowEval: true },
data: {},
result: '<div id="ex2">pass 2</div>'
};},
@ -102,6 +103,7 @@ var tests = [
function() { return {
name: 'ifTrue',
template: '<p if="${name !== \'jim\'}">hello ${name}</p>',
options: { allowEval: true },
data: { name: 'fred' },
result: '<p>hello fred</p>'
};},
@ -109,6 +111,7 @@ var tests = [
function() { return {
name: 'ifFalse',
template: '<p if="${name !== \'jim\'}">hello ${name}</p>',
options: { allowEval: true },
data: { name: 'jim' },
result: ''
};},
@ -116,6 +119,7 @@ var tests = [
function() { return {
name: 'simpleLoop',
template: '<p foreach="index in ${[ 1, 2, 3 ]}">${index}</p>',
options: { allowEval: true },
data: {},
result: '<p>1</p><p>2</p><p>3</p>'
};},
@ -127,6 +131,7 @@ var tests = [
result: '123'
};},
// Bug 692028: DOMTemplate memory leak with asynchronous arrays
// Bug 692031: DOMTemplate async loops do not drop the loop element
function() { return {
name: 'asyncLoopElement',
@ -150,6 +155,7 @@ var tests = [
function() { return {
name: 'useElement',
template: '<p id="pass9">${adjust(__element)}</p>',
options: { allowEval: true },
data: {
adjust: function(element) {
is('pass9', element.id, 'useElement adjust');
@ -167,6 +173,7 @@ var tests = [
later: 'inline'
};},
// Bug 692028: DOMTemplate memory leak with asynchronous arrays
function() { return {
name: 'asyncArray',
template: '<p foreach="i in ${delayed}">${i}</p>',
@ -183,6 +190,7 @@ var tests = [
later: '<p>4</p><p>5</p><p>6</p>'
};},
// Bug 692028: DOMTemplate memory leak with asynchronous arrays
function() { return {
name: 'asyncBoth',
template: '<p foreach="i in ${delayed}">${i}</p>',
@ -195,6 +203,38 @@ var tests = [
},
result: '<span></span>',
later: '<p>4</p><p>5</p><p>6</p>'
};},
// Bug 701762: DOMTemplate fails when ${foo()} returns undefined
function() { return {
name: 'functionReturningUndefiend',
template: '<p>${foo()}</p>',
options: { allowEval: true },
data: {
foo: function() {}
},
result: '<p>undefined</p>'
};},
// Bug 702642: DOMTemplate is relatively slow when evaluating JS ${}
function() { return {
name: 'propertySimple',
template: '<p>${a.b.c}</p>',
data: { a: { b: { c: 'hello' } } },
result: '<p>hello</p>'
};},
function() { return {
name: 'propertyPass',
template: '<p>${Math.max(1, 2)}</p>',
options: { allowEval: true },
result: '<p>2</p>'
};},
function() { return {
name: 'propertyFail',
template: '<p>${Math.max(1, 2)}</p>',
result: '<p>${Math.max(1, 2)}</p>'
};}
];

View File

@ -214,7 +214,10 @@ CssHtmlTree.processTemplate = function CssHtmlTree_processTemplate(aTemplate,
// All the templater does is to populate a given DOM tree with the given
// values, so we need to clone the template first.
let duplicated = aTemplate.cloneNode(true);
new Templater().processNode(duplicated, aData);
// See https://github.com/mozilla/domtemplate/blob/master/README.md
// for docs on the template() function
template(duplicated, aData, { allowEval: true });
while (duplicated.firstChild) {
aDestination.appendChild(duplicated.firstChild);
}

View File

@ -62,40 +62,6 @@ gcli.addCommand({
});
let canon = gcli._internal.require("gcli/canon");
/**
* 'help' command
*/
gcli.addCommand({
name: "help",
returnType: "html",
description: gcli.lookup("helpDesc"),
exec: function Command_help(args, context) {
let output = [];
output.push("<strong>" + gcli.lookup("helpAvailable") + ":</strong><br/>");
let commandNames = canon.getCommandNames();
commandNames.sort();
output.push("<table>");
for (let i = 0; i < commandNames.length; i++) {
let command = canon.getCommand(commandNames[i]);
if (!command.hidden && command.description) {
output.push("<tr>");
output.push('<th class="gcli-help-right">' + command.name + "</th>");
output.push("<td>&#x2192; " + command.description + "</td>");
output.push("</tr>");
}
}
output.push("</table>");
return output.join("");
}
});
/**
* 'console' command
*/

View File

@ -92,6 +92,12 @@ XPCOMUtils.defineLazyGetter(this, "NetUtil", function () {
return obj.NetUtil;
});
XPCOMUtils.defineLazyGetter(this, "template", function () {
var obj = {};
Cu.import("resource:///modules/devtools/Templater.jsm", obj);
return obj.template;
});
XPCOMUtils.defineLazyGetter(this, "PropertyPanel", function () {
var obj = {};
try {
@ -6854,14 +6860,38 @@ GcliTerm.prototype = {
let output = aEvent.output.output;
if (aEvent.output.command.returnType == "html" && typeof output == "string") {
let frag = this.document.createRange().createContextualFragment(
output = this.document.createRange().createContextualFragment(
'<div xmlns="' + HTML_NS + '" xmlns:xul="' + XUL_NS + '">' +
output + '</div>');
output = this.document.createElementNS(HTML_NS, "div");
output.appendChild(frag);
output + '</div>').firstChild;
}
this.writeOutput(output);
// See https://github.com/mozilla/domtemplate/blob/master/README.md
// for docs on the template() function
let element = this.document.createRange().createContextualFragment(
'<richlistitem xmlns="' + XUL_NS + '" clipboardText="${clipboardText}"' +
' timestamp="${timestamp}" id="${id}" class="hud-msg-node">' +
' <label class="webconsole-timestamp" value="${timestampString}"/>' +
' <vbox class="webconsole-msg-icon-container" style="${iconContainerStyle}">' +
' <image class="webconsole-msg-icon"/>' +
' <spacer flex="1"/>' +
' </vbox>' +
' <hbox flex="1" class="gcliterm-msg-body">${output}</hbox>' +
' <hbox align="start"><label value="1" class="webconsole-msg-repeat"/></hbox>' +
'</richlistitem>').firstChild;
let hud = HUDService.getHudReferenceById(this.hudId);
let timestamp = ConsoleUtils.timestamp();
template(element, {
iconContainerStyle: "margin-left=" + (hud.groupDepth * GROUP_INDENT) + "px",
output: output,
timestamp: timestamp,
timestampString: ConsoleUtils.timestampString(timestamp),
clipboardText: output.innerText,
id: "console-msg-" + HUDService.sequenceId()
});
ConsoleUtils.setMessageType(element, CATEGORY_OUTPUT, SEVERITY_LOG);
ConsoleUtils.outputMessageNode(element, this.hudId);
},
/**

View File

@ -686,7 +686,7 @@ var mozl10n = {};
})(mozl10n);
define('gcli/index', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/types/basic', 'gcli/types/javascript', 'gcli/types/node', 'gcli/cli', 'gcli/ui/display'], function(require, exports, module) {
define('gcli/index', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/types/basic', 'gcli/types/javascript', 'gcli/types/node', 'gcli/cli', 'gcli/commands/help', 'gcli/ui/console'], function(require, exports, module) {
// The API for use by command authors
exports.addCommand = require('gcli/canon').addCommand;
@ -699,9 +699,10 @@ define('gcli/index', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/types
require('gcli/types/javascript').startup();
require('gcli/types/node').startup();
require('gcli/cli').startup();
require('gcli/commands/help').startup();
var Requisition = require('gcli/cli').Requisition;
var Display = require('gcli/ui/display').Display;
var Console = require('gcli/ui/console').Console;
var cli = require('gcli/cli');
var jstype = require('gcli/types/javascript');
@ -739,15 +740,15 @@ define('gcli/index', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/types
opts.requisition = new Requisition(opts.environment, opts.chromeDocument);
}
opts.display = new Display(opts);
opts.console = new Console(opts);
},
/**
* Undo the effects of createView() to prevent memory leaks
*/
removeView: function(opts) {
opts.display.destroy();
delete opts.display;
opts.console.destroy();
delete opts.console;
opts.requisition.destroy();
delete opts.requisition;
@ -1029,7 +1030,8 @@ canon.removeCommand = function removeCommand(commandOrName) {
* @param name The name of the command to retrieve
*/
canon.getCommand = function getCommand(name) {
return commands[name];
// '|| undefined' is to silence 'reference to undefined property' warnings
return commands[name] || undefined;
};
/**
@ -1190,8 +1192,16 @@ exports.createEvent = function(name) {
var dom = {};
/**
* XHTML namespace
*/
dom.NS_XHTML = 'http://www.w3.org/1999/xhtml';
/**
* XUL namespace
*/
dom.NS_XUL = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
/**
* Create an HTML or XHTML element depending on whether the document is HTML
* or XML based. Where HTML/XHTML elements are distinguished by whether they
@ -1246,24 +1256,30 @@ dom.importCss = function(cssText, doc) {
*/
dom.setInnerHtml = function(elem, html) {
if (dom.isXmlDocument(elem.ownerDocument)) {
try {
dom.clearElement(elem);
html = '<div xmlns="' + dom.NS_XHTML + '">' + html + '</div>';
var range = elem.ownerDocument.createRange();
var child = range.createContextualFragment(html).childNodes[0];
var child = range.createContextualFragment(html).firstChild;
while (child.hasChildNodes()) {
elem.appendChild(child.firstChild);
}
}
catch (ex) {
console.error('Bad XHTML', ex);
console.trace();
throw ex;
}
}
else {
elem.innerHTML = html;
}
};
/**
* How to detect if we're in an XUL document (and therefore should create
* elements in an XHTML namespace)
* In a Mozilla XUL document, document.xmlVersion = null, however in Chrome
* document.contentType = undefined.
* How to detect if we're in an XML document.
* In a Mozilla we check that document.xmlVersion = null, however in Chrome
* we use document.contentType = undefined.
* @param doc The document element to work from (defaulted to the global
* 'document' if missing
*/
@ -1479,6 +1495,13 @@ exports.lookup = function(key) {
}
};
/** @see propertyLookup in lib/gcli/l10n.js */
exports.propertyLookup = Proxy.create({
get: function(rcvr, name) {
return exports.lookup(name);
}
});
/** @see lookupFormat in lib/gcli/l10n.js */
exports.lookupFormat = function(key, swaps) {
try {
@ -3462,6 +3485,14 @@ exports.unsetDocument = function() {
doc = undefined;
};
/**
* Getter for the document that contains the nodes we're matching
* Most for changing things back to how they were for unit testing
*/
exports.getDocument = function() {
return doc;
};
/**
* A CSS expression that refers to a single node
@ -4042,7 +4073,15 @@ UnassignedAssignment.prototype.setUnassigned = function(args) {
*/
function Requisition(environment, doc) {
this.environment = environment;
this.document = doc || document;
this.document = doc;
if (this.document == null) {
try {
this.document = document;
}
catch (ex) {
// Ignore
}
}
// The command that we are about to execute.
// @see setCommandConversion()
@ -4508,7 +4547,8 @@ Requisition.prototype.exec = function(input) {
var outputObject = {
command: command,
args: args,
typed: this.toCanonicalString(),
typed: this.toString(),
canonical: this.toCanonicalString(),
completed: false,
start: new Date()
};
@ -4527,7 +4567,7 @@ Requisition.prototype.exec = function(input) {
}).bind(this);
try {
var context = new ExecutionContext(this.environment, this.document);
var context = new ExecutionContext(this);
var reply = command.exec(args, context);
if (reply != null && reply.isPromise) {
@ -5012,9 +5052,10 @@ exports.Requisition = Requisition;
/**
* Functions and data related to the execution of a command
*/
function ExecutionContext(environment, document) {
this.environment = environment;
this.document = document;
function ExecutionContext(requisition) {
this.requisition = requisition;
this.environment = requisition.environment;
this.document = requisition.document;
}
ExecutionContext.prototype.createPromise = function() {
@ -5041,7 +5082,275 @@ define('gcli/promise', ['require', 'exports', 'module' ], function(require, expo
* http://opensource.org/licenses/BSD-3-Clause
*/
define('gcli/ui/display', ['require', 'exports', 'module' , 'gcli/ui/inputter', 'gcli/ui/arg_fetch', 'gcli/ui/menu', 'gcli/ui/focus'], function(require, exports, module) {
define('gcli/commands/help', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/util', 'gcli/l10n', 'gcli/ui/domtemplate', 'text!gcli/commands/help.css', 'text!gcli/commands/help_intro.html', 'text!gcli/commands/help_list.html', 'text!gcli/commands/help_man.html'], function(require, exports, module) {
var help = exports;
var canon = require('gcli/canon');
var util = require('gcli/util');
var l10n = require('gcli/l10n');
var domtemplate = require('gcli/ui/domtemplate');
var helpCss = require('text!gcli/commands/help.css');
var helpStyle = undefined;
var helpIntroHtml = require('text!gcli/commands/help_intro.html');
var helpIntroTemplate = undefined;
var helpListHtml = require('text!gcli/commands/help_list.html');
var helpListTemplate = undefined;
var helpManHtml = require('text!gcli/commands/help_man.html');
var helpManTemplate = undefined;
/**
* 'help' command
* We delay definition of helpCommandSpec until help.startup() to ensure that
* the l10n strings have been loaded
*/
var helpCommandSpec;
/**
* Registration and de-registration.
*/
help.startup = function() {
helpCommandSpec = {
name: 'help',
description: l10n.lookup('helpDesc'),
manual: l10n.lookup('helpManual'),
params: [
{
name: 'search',
type: 'string',
description: l10n.lookup('helpSearchDesc'),
manual: l10n.lookup('helpSearchManual'),
defaultValue: null
}
],
returnType: 'html',
exec: function(args, context) {
help.onFirstUseStartup(context.document);
var match = canon.getCommand(args.search);
if (match) {
var clone = helpManTemplate.cloneNode(true);
domtemplate.template(clone, getManTemplateData(match, context),
{ allowEval: true, stack: 'help_man.html' });
return clone;
}
var parent = util.dom.createElement(context.document, 'div');
if (!args.search) {
parent.appendChild(helpIntroTemplate.cloneNode(true));
}
parent.appendChild(helpListTemplate.cloneNode(true));
domtemplate.template(parent, getListTemplateData(args, context),
{ allowEval: true, stack: 'help_intro.html | help_list.html' });
return parent;
}
};
canon.addCommand(helpCommandSpec);
};
help.shutdown = function() {
canon.removeCommand(helpCommandSpec);
helpListTemplate = undefined;
helpStyle.parentElement.removeChild(helpStyle);
helpStyle = undefined;
};
/**
* Called when the command is executed
*/
help.onFirstUseStartup = function(document) {
if (!helpIntroTemplate) {
helpIntroTemplate = util.dom.createElement(document, 'div');
util.dom.setInnerHtml(helpIntroTemplate, helpIntroHtml);
}
if (!helpListTemplate) {
helpListTemplate = util.dom.createElement(document, 'div');
util.dom.setInnerHtml(helpListTemplate, helpListHtml);
}
if (!helpManTemplate) {
helpManTemplate = util.dom.createElement(document, 'div');
util.dom.setInnerHtml(helpManTemplate, helpManHtml);
}
if (!helpStyle && helpCss != null) {
helpStyle = util.dom.importCss(helpCss, document);
}
};
/**
* Find an element within the passed element with the class gcli-help-command
* and update the requisition to contain this text.
*/
function updateCommand(element, context) {
context.requisition.update({
typed: element.querySelector('.gcli-help-command').textContent
});
}
/**
* Find an element within the passed element with the class gcli-help-command
* and execute this text.
*/
function executeCommand(element, context) {
context.requisition.exec({
visible: true,
typed: element.querySelector('.gcli-help-command').textContent
});
}
/**
* Create a block of data suitable to be passed to the help_list.html template
*/
function getListTemplateData(args, context) {
return {
l10n: l10n.propertyLookup,
lang: context.document.defaultView.navigator.language,
onclick: function(ev) {
updateCommand(ev.currentTarget, context);
},
ondblclick: function(ev) {
executeCommand(ev.currentTarget, context);
},
getHeading: function() {
return args.search == null ?
'Available Commands:' :
'Commands starting with \'' + args.search + '\':';
},
getMatchingCommands: function() {
var matching = canon.getCommands().filter(function(command) {
if (args.search && command.name.indexOf(args.search) !== 0) {
// Filtered out because they don't match the search
return false;
}
if (!args.search && command.name.indexOf(' ') != -1) {
// We don't show sub commands with plain 'help'
return false;
}
return true;
});
matching.sort();
return matching;
}
};
}
/**
* Create a block of data suitable to be passed to the help_man.html template
*/
function getManTemplateData(command, context) {
return {
l10n: l10n.propertyLookup,
lang: context.document.defaultView.navigator.language,
command: command,
onclick: function(ev) {
updateCommand(ev.currentTarget, context);
},
getTypeDescription: function(param) {
var input = '';
if (param.defaultValue === undefined) {
input = 'required';
}
else if (param.defaultValue === null) {
input = 'optional';
}
else {
input = param.defaultValue;
}
return '(' + param.type.name + ', ' + input + ')';
}
};
}
});
/*
* Copyright 2009-2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE.txt or:
* http://opensource.org/licenses/BSD-3-Clause
*/
define('gcli/ui/domtemplate', ['require', 'exports', 'module' ], function(require, exports, module) {
var obj = {};
Components.utils.import('resource:///modules/devtools/Templater.jsm', obj);
exports.template = obj.template;
});
define("text!gcli/commands/help.css", [], void 0);
define("text!gcli/commands/help_intro.html", [], "\n" +
"<h2>${l10n.introHeader}</h2>\n" +
"\n" +
"<p>\n" +
" <a target=\"_blank\" href=\"https://developer.mozilla.org/AppLinks/WebConsoleHelp?locale=${lang}\">\n" +
" ${l10n.introBody}\n" +
" </a>\n" +
"</p>\n" +
"");
define("text!gcli/commands/help_list.html", [], "\n" +
"<h3>${getHeading()}</h3>\n" +
"\n" +
"<table>\n" +
" <tr foreach=\"command in ${getMatchingCommands()}\"\n" +
" onclick=\"${onclick}\" ondblclick=\"${ondblclick}\">\n" +
" <th class=\"gcli-help-name\">${command.name}</th>\n" +
" <td class=\"gcli-help-arrow\">&#x2192;</td>\n" +
" <td>\n" +
" ${command.description}\n" +
" <span class=\"gcli-out-shortcut gcli-help-command\">help ${command.name}</span>\n" +
" </td>\n" +
" </tr>\n" +
"</table>\n" +
"");
define("text!gcli/commands/help_man.html", [], "\n" +
"<h3>${command.name}</h3>\n" +
"\n" +
"<h4 class=\"gcli-help-header\">\n" +
" ${l10n.helpManSynopsis}:\n" +
" <span class=\"gcli-help-synopsis\" onclick=\"${onclick}\">\n" +
" <span class=\"gcli-help-command\">${command.name}</span>\n" +
" <span foreach=\"param in ${command.params}\">\n" +
" ${param.defaultValue !== undefined ? '[' + param.name + ']' : param.name}\n" +
" </span>\n" +
" </span>\n" +
"</h4>\n" +
"\n" +
"<h4 class=\"gcli-help-header\">${l10n.helpManDescription}:</h4>\n" +
"\n" +
"<p class=\"gcli-help-description\">\n" +
" ${command.manual || command.description}\n" +
"</p>\n" +
"\n" +
"<h4 class=\"gcli-help-header\">${l10n.helpManParameters}:</h4>\n" +
"\n" +
"<ul class=\"gcli-help-parameter\">\n" +
" <li if=\"${command.params.length === 0}\">${l10n.helpManNone}</li>\n" +
" <li foreach=\"param in ${command.params}\">\n" +
" <tt>${param.name}</tt> ${getTypeDescription(param)}\n" +
" <br/>\n" +
" ${param.manual || param.description}\n" +
" </li>\n" +
"</ul>\n" +
"");
/*
* Copyright 2009-2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE.txt or:
* http://opensource.org/licenses/BSD-3-Clause
*/
define('gcli/ui/console', ['require', 'exports', 'module' , 'gcli/ui/inputter', 'gcli/ui/arg_fetch', 'gcli/ui/menu', 'gcli/ui/focus'], function(require, exports, module) {
var Inputter = require('gcli/ui/inputter').Inputter;
var ArgFetcher = require('gcli/ui/arg_fetch').ArgFetcher;
@ -5049,10 +5358,10 @@ var CommandMenu = require('gcli/ui/menu').CommandMenu;
var FocusManager = require('gcli/ui/focus').FocusManager;
/**
* Display is responsible for generating the UI for GCLI, this implementation
* Console is responsible for generating the UI for GCLI, this implementation
* is a special case for use inside Firefox
*/
function Display(options) {
function Console(options) {
this.hintElement = options.hintElement;
this.gcliTerm = options.gcliTerm;
this.consoleWrap = options.consoleWrap;
@ -5097,7 +5406,7 @@ function Display(options) {
/**
* Avoid memory leaks
*/
Display.prototype.destroy = function() {
Console.prototype.destroy = function() {
this.chromeWindow.removeEventListener('resize', this.resizer, false);
delete this.resizer;
delete this.chromeWindow;
@ -5122,10 +5431,17 @@ Display.prototype.destroy = function() {
/**
* Called on chrome window resize, or on divider slide
*/
Display.prototype.resizer = function() {
Console.prototype.resizer = function() {
// Bug 705109: There are several numbers hard-coded in this function.
// This is simpler than calculating them, but error-prone when the UI setup,
// the styling or display settings change.
var parentRect = this.consoleWrap.getBoundingClientRect();
// Magic number: 64 is the size of the toolbar above the output area
var parentHeight = parentRect.bottom - parentRect.top - 64;
// Magic number: 100 is the size at which we decide the hints are too small
// to be useful, so we hide them
if (parentHeight < 100) {
this.hintElement.classList.add('gcliterm-hint-nospace');
}
@ -5136,20 +5452,14 @@ Display.prototype.resizer = function() {
if (isMenuVisible) {
this.menu.setMaxHeight(parentHeight);
// Magic numbers. We have 2 options - lots of complex dom math to derive
// the height of a menu item (19 pixels) and the vertical padding
// (22 pixels), or we could just hard-code. The former is *slightly* more
// resilient to refactoring (but still breaks with dom structure changes),
// the latter is simpler, faster and easier.
// Magic numbers: 19 = height of a menu item, 22 = total vertical padding
// of container
var idealMenuHeight = (19 * this.menu.items.length) + 22;
if (idealMenuHeight > parentHeight) {
this.hintElement.style.overflowY = 'scroll';
this.hintElement.style.borderBottomColor = 'threedshadow';
this.hintElement.classList.add('gcliterm-hint-scroll');
}
else {
this.hintElement.style.overflowY = null;
this.hintElement.style.borderBottomColor = 'white';
this.hintElement.classList.remove('gcliterm-hint-scroll');
}
}
else {
@ -5161,7 +5471,7 @@ Display.prototype.resizer = function() {
}
};
exports.Display = Display;
exports.Console = Console;
});
/*
@ -5582,8 +5892,9 @@ cliView.Inputter = Inputter;
* - document (required) DOM document to be used in creating elements
* - requisition (required) A GCLI Requisition object whose state is monitored
* - completeElement (optional) An element to use
* - completionPrompt (optional) The prompt to show before a completion.
* Defaults to '&#x00bb;' (double greater-than, a.k.a right guillemet).
* - completionPrompt (optional) The prompt - defaults to '\u00bb'
* (double greater-than, a.k.a right guillemet). The prompt is used directly
* in a TextNode, so HTML entities are not allowed.
*/
function Completer(options) {
this.document = options.document || document;
@ -5606,7 +5917,7 @@ function Completer(options) {
this.completionPrompt = typeof options.completionPrompt === 'string'
? options.completionPrompt
: '&#x00bb;';
: '\u00bb';
if (options.inputBackgroundElement) {
this.backgroundElement = options.inputBackgroundElement;
@ -5714,50 +6025,85 @@ Completer.prototype.update = function(input) {
var current = this.requisition.getAssignmentAt(input.cursor.start);
var predictions = current.getPredictions();
var completion = '<span class="gcli-prompt">' + this.completionPrompt + '</span> ';
dom.clearElement(this.element);
// All this DOM manipulation is equivalent to the HTML below.
// It's not a template because it's very simple except appendMarkupStatus()
// which is complex due to a need to merge spans.
// Bug 707131 questions if we couldn't simplify this to use a template.
//
// <span class="gcli-prompt">${completionPrompt}</span>
// ${appendMarkupStatus()}
// ${prefix}
// <span class="gcli-in-ontab">${contents}</span>
// <span class="gcli-in-closebrace" if="${unclosedJs}">}<span>
var document = this.element.ownerDocument;
var prompt = document.createElement('span');
prompt.classList.add('gcli-prompt');
prompt.appendChild(document.createTextNode(this.completionPrompt + ' '));
this.element.appendChild(prompt);
if (input.typed.length > 0) {
var scores = this.requisition.getInputStatusMarkup(input.cursor.start);
completion += this.markupStatusScore(scores, input);
this.appendMarkupStatus(this.element, scores, input);
}
if (input.typed.length > 0 && predictions.length > 0) {
var tab = predictions[0].name;
var existing = current.getArg().text;
if (isStrictCompletion(existing, tab) && input.cursor.start === input.typed.length) {
// Display the suffix of the prediction as the completion.
var contents;
var prefix = null;
if (isStrictCompletion(existing, tab) &&
input.cursor.start === input.typed.length) {
// Display the suffix of the prediction as the completion
var numLeadingSpaces = existing.match(/^(\s*)/)[0].length;
var suffix = tab.slice(existing.length - numLeadingSpaces);
completion += '<span class="gcli-in-ontab">' + suffix + '</span>';
contents = tab.slice(existing.length - numLeadingSpaces);
} else {
// Display the '-> prediction' at the end of the completer element
completion += ' &#xa0;<span class="gcli-in-ontab">&#x21E5; ' +
tab + '</span>';
}
prefix = ' \u00a0'; // aka &nbsp;
contents = '\u21E5 ' + tab; // aka &rarr; the right arrow
}
// A hack to add a grey '}' to the end of the command line when we've opened
if (prefix != null) {
this.element.appendChild(document.createTextNode(prefix));
}
var suffix = document.createElement('span');
suffix.classList.add('gcli-in-ontab');
suffix.appendChild(document.createTextNode(contents));
this.element.appendChild(suffix);
}
// Add a grey '}' to the end of the command line when we've opened
// with a { but haven't closed it
var command = this.requisition.commandAssignment.getValue();
if (command && command.name === '{') {
if (this.requisition.getAssignment(0).getArg().suffix.indexOf('}') === -1) {
completion += '<span class="gcli-in-closebrace">}</span>';
var unclosedJs = command && command.name === '{' &&
this.requisition.getAssignment(0).getArg().suffix.indexOf('}') === -1;
if (unclosedJs) {
var close = document.createElement('span');
close.classList.add('gcli-in-closebrace');
close.appendChild(document.createTextNode('}'));
this.element.appendChild(close);
}
}
dom.setInnerHtml(this.element, completion);
};
/**
* Mark-up an array of Status values with spans
*/
Completer.prototype.markupStatusScore = function(scores, input) {
var completion = '';
Completer.prototype.appendMarkupStatus = function(element, scores, input) {
if (scores.length === 0) {
return completion;
return;
}
var document = element.ownerDocument;
var i = 0;
var lastStatus = -1;
var span;
var contents = '';
while (true) {
if (lastStatus !== scores[i]) {
var state = scores[i];
@ -5765,25 +6111,27 @@ Completer.prototype.markupStatusScore = function(scores, input) {
console.error('No state at i=' + i + '. scores.len=' + scores.length);
state = Status.VALID;
}
completion += '<span class="gcli-in-' + state.toString().toLowerCase() + '">';
span = document.createElement('span');
span.classList.add('gcli-in-' + state.toString().toLowerCase());
lastStatus = scores[i];
}
var char = input.typed[i];
if (char === ' ') {
char = '&#xa0;';
char = '\u00a0';
}
completion += char;
contents += char;
i++;
if (i === input.typed.length) {
completion += '</span>';
span.appendChild(document.createTextNode(contents));
this.element.appendChild(span);
break;
}
if (lastStatus !== scores[i]) {
completion += '</span>';
span.appendChild(document.createTextNode(contents));
this.element.appendChild(span);
contents = '';
}
}
return completion;
};
cliView.Completer = Completer;
@ -5867,7 +6215,7 @@ var dom = require('gcli/util').dom;
var Status = require('gcli/types').Status;
var getField = require('gcli/ui/field').getField;
var Templater = require('gcli/ui/domtemplate').Templater;
var domtemplate = require('gcli/ui/domtemplate');
var editorCss = require('text!gcli/ui/arg_fetch.css');
var argFetchHtml = require('text!gcli/ui/arg_fetch.html');
@ -5896,7 +6244,6 @@ function ArgFetcher(options) {
// We cache the fields we create so we can destroy them later
this.fields = [];
this.tmpl = new Templater();
// Populated by template
this.okElement = null;
@ -5953,7 +6300,8 @@ ArgFetcher.prototype.onCommandChange = function(ev) {
this.fields = [];
var reqEle = this.reqTempl.cloneNode(true);
this.tmpl.processNode(reqEle, this);
domtemplate.template(reqEle, this,
{ allowEval: true, stack: 'arg_fetch.html' });
dom.clearElement(this.element);
this.element.appendChild(reqEle);
@ -6008,7 +6356,7 @@ ArgFetcher.prototype.getInputFor = function(assignment) {
return newField.element;
}
catch (ex) {
// This is called from within Templater which can make tracing errors hard
// This is called from within template() which can make tracing errors hard
// so we log here if anything goes wrong
console.error(ex);
return '';
@ -6252,7 +6600,7 @@ function StringField(type, options) {
this.element = dom.createElement(this.document, 'input');
this.element.type = 'text';
this.element.className = 'gcli-field';
this.element.classList.add('gcli-field');
this.onInputChange = this.onInputChange.bind(this);
this.element.addEventListener('keyup', this.onInputChange, false);
@ -6412,7 +6760,7 @@ function SelectionField(type, options) {
this.items = [];
this.element = dom.createElement(this.document, 'select');
this.element.className = 'gcli-field';
this.element.classList.add('gcli-field');
this._addOption({
name: l10n.lookupFormat('fieldSelectionSelect', [ options.name ])
});
@ -6487,8 +6835,8 @@ function JavascriptField(type, options) {
this.input = dom.createElement(this.document, 'input');
this.input.type = 'text';
this.input.addEventListener('keyup', this.onInputChange, false);
this.input.style.marginBottom = '0';
this.input.className = 'gcli-field';
this.input.classList.add('gcli-field');
this.input.classList.add('gcli-field-javascript');
this.element.appendChild(this.input);
this.menu = new Menu({ document: this.document, field: true });
@ -6680,18 +7028,18 @@ function ArrayField(type, options) {
// <div class=gcliArrayParent save="${element}">
this.element = dom.createElement(this.document, 'div');
this.element.className = 'gcliArrayParent';
this.element.classList.add('gcli-array-parent');
// <button class=gcliArrayMbrAdd onclick="${_onAdd}" save="${addButton}">Add
this.addButton = dom.createElement(this.document, 'button');
this.addButton.className = 'gcliArrayMbrAdd';
this.addButton.classList.add('gcli-array-member-add');
this.addButton.addEventListener('click', this._onAdd, false);
this.addButton.innerHTML = l10n.lookup('fieldArrayAdd');
this.element.appendChild(this.addButton);
// <div class=gcliArrayMbrs save="${mbrElement}">
this.container = dom.createElement(this.document, 'div');
this.container.className = 'gcliArrayMbrs';
this.container.classList.add('gcli-array-members');
this.element.appendChild(this.container);
this.onInputChange = this.onInputChange.bind(this);
@ -6734,7 +7082,7 @@ ArrayField.prototype.getConversion = function() {
ArrayField.prototype._onAdd = function(ev, subConversion) {
// <div class=gcliArrayMbr save="${element}">
var element = dom.createElement(this.document, 'div');
element.className = 'gcliArrayMbr';
element.classList.add('gcli-array-member');
this.container.appendChild(element);
// ${field.element}
@ -6752,7 +7100,7 @@ ArrayField.prototype._onAdd = function(ev, subConversion) {
// <div class=gcliArrayMbrDel onclick="${_onDel}">
var delButton = dom.createElement(this.document, 'button');
delButton.className = 'gcliArrayMbrDel';
delButton.classList.add('gcli-array-member-del');
delButton.addEventListener('click', this._onDel, false);
delButton.innerHTML = l10n.lookup('fieldArrayDel');
element.appendChild(delButton);
@ -6794,7 +7142,7 @@ var Conversion = require('gcli/types').Conversion;
var Argument = require('gcli/argument').Argument;
var canon = require('gcli/canon');
var Templater = require('gcli/ui/domtemplate').Templater;
var domtemplate = require('gcli/ui/domtemplate');
var menuCss = require('text!gcli/ui/menu.css');
var menuHtml = require('text!gcli/ui/menu.html');
@ -6877,7 +7225,7 @@ Menu.prototype.show = function(items, error) {
}
var options = this.optTempl.cloneNode(true);
new Templater().processNode(options, this);
domtemplate.template(options, this, { allowEval: true, stack: 'menu.html' });
dom.clearElement(this.element);
this.element.appendChild(options);
@ -6984,18 +7332,6 @@ CommandMenu.prototype.onCommandChange = function(ev) {
exports.CommandMenu = CommandMenu;
});
/*
* Copyright 2009-2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE.txt or:
* http://opensource.org/licenses/BSD-3-Clause
*/
define('gcli/ui/domtemplate', ['require', 'exports', 'module' ], function(require, exports, module) {
Components.utils.import("resource:///modules/devtools/Templater.jsm");
exports.Templater = Templater;
});
define("text!gcli/ui/menu.css", [], void 0);
define("text!gcli/ui/menu.html", [], "\n" +

View File

@ -83,12 +83,12 @@ function testCallCommands() {
is(gcliterm.completeNode.textContent, " ecd", "Completion for \"ecd\"");
// Test a normal command's life cycle
gcliterm.opts.display.inputter.setInput("echo hello world");
gcliterm.opts.console.inputter.setInput("echo hello world");
gcliterm.opts.requisition.exec();
let nodes = hud.outputNode.querySelectorAll("description");
let nodes = hud.outputNode.querySelectorAll(".gcliterm-msg-body");
is(nodes.length, 2, "Right number of output nodes");
is(nodes.length, 1, "Right number of output nodes");
ok(/hello world/.test(nodes[0].textContent), "the command's output is correct.");
gcliterm.clearOutput();

View File

@ -54,7 +54,7 @@ var Node = Components.interfaces.nsIDOMNode;
* http://opensource.org/licenses/BSD-3-Clause
*/
define('gclitest/suite', ['require', 'exports', 'module' , 'gcli/index', 'test/examiner', 'gclitest/testTokenize', 'gclitest/testSplit', 'gclitest/testCli', 'gclitest/testHistory', 'gclitest/testRequire', 'gclitest/testJs'], function(require, exports, module) {
define('gclitest/suite', ['require', 'exports', 'module' , 'gcli/index', 'test/examiner', 'gclitest/testTokenize', 'gclitest/testSplit', 'gclitest/testCli', 'gclitest/testExec', 'gclitest/testKeyboard', 'gclitest/testHistory', 'gclitest/testRequire', 'gclitest/testJs'], function(require, exports, module) {
// We need to make sure GCLI is initialized before we begin testing it
require('gcli/index');
@ -67,11 +67,15 @@ define('gclitest/suite', ['require', 'exports', 'module' , 'gcli/index', 'test/e
examiner.addSuite('gclitest/testTokenize', require('gclitest/testTokenize'));
examiner.addSuite('gclitest/testSplit', require('gclitest/testSplit'));
examiner.addSuite('gclitest/testCli', require('gclitest/testCli'));
examiner.addSuite('gclitest/testExec', require('gclitest/testExec'));
examiner.addSuite('gclitest/testKeyboard', require('gclitest/testKeyboard'));
examiner.addSuite('gclitest/testHistory', require('gclitest/testHistory'));
examiner.addSuite('gclitest/testRequire', require('gclitest/testRequire'));
examiner.addSuite('gclitest/testJs', require('gclitest/testJs'));
examiner.run();
console.log('Completed test suite');
// examiner.log();
});
/*
@ -167,6 +171,19 @@ examiner.toRemote = function() {
};
};
/**
* Output a test summary to console.log
*/
examiner.log = function() {
var remote = this.toRemote();
remote.suites.forEach(function(suite) {
console.log(suite.name);
suite.tests.forEach(function(test) {
console.log('- ' + test.name, test.status.name, test.message || '');
});
});
};
/**
* Used by assert to record a failure against the current test
*/
@ -299,8 +316,8 @@ Test.prototype.run = function() {
this.status = stati.fail;
this.messages.push('' + ex);
console.error(ex);
if (console.trace) {
console.trace();
if (ex.stack) {
console.error(ex.stack);
}
}
@ -703,11 +720,12 @@ exports.testJavascript = function() {
* http://opensource.org/licenses/BSD-3-Clause
*/
define('gclitest/commands', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/types/basic', 'gcli/types'], function(require, exports, module) {
define('gclitest/commands', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/util', 'gcli/types/basic', 'gcli/types'], function(require, exports, module) {
var commands = exports;
var canon = require('gcli/canon');
var util = require('gcli/util');
var SelectionType = require('gcli/types/basic').SelectionType;
var DeferredType = require('gcli/types/basic').DeferredType;
@ -725,6 +743,10 @@ commands.setup = function() {
canon.addCommand(commands.tsv);
canon.addCommand(commands.tsr);
canon.addCommand(commands.tse);
canon.addCommand(commands.tsj);
canon.addCommand(commands.tsb);
canon.addCommand(commands.tss);
canon.addCommand(commands.tsu);
canon.addCommand(commands.tsn);
canon.addCommand(commands.tsnDif);
@ -734,11 +756,16 @@ commands.setup = function() {
canon.addCommand(commands.tsnExtend);
canon.addCommand(commands.tselarr);
canon.addCommand(commands.tsm);
canon.addCommand(commands.tsg);
};
commands.shutdown = function() {
canon.removeCommand(commands.tsv);
canon.removeCommand(commands.tsr);
canon.removeCommand(commands.tse);
canon.removeCommand(commands.tsj);
canon.removeCommand(commands.tsb);
canon.removeCommand(commands.tss);
canon.removeCommand(commands.tsu);
canon.removeCommand(commands.tsn);
canon.removeCommand(commands.tsnDif);
@ -748,14 +775,15 @@ commands.shutdown = function() {
canon.removeCommand(commands.tsnExtend);
canon.removeCommand(commands.tselarr);
canon.removeCommand(commands.tsm);
canon.removeCommand(commands.tsg);
types.deregisterType(commands.optionType);
types.deregisterType(commands.optionValue);
};
commands.option1 = { };
commands.option2 = { };
commands.option1 = { type: types.getType('string') };
commands.option2 = { type: types.getType('number') };
commands.optionType = new SelectionType({
name: 'optionType',
@ -789,25 +817,62 @@ commands.optionValue = new DeferredType({
}
});
commands.commandExec = util.createEvent('commands.commandExec');
function createExec(name) {
return function(args, context) {
var data = {
command: commands[name],
args: args,
context: context
};
commands.commandExec(data);
return data;
};
}
commands.tsv = {
name: 'tsv',
params: [
{ name: 'optionType', type: 'optionType' },
{ name: 'optionValue', type: 'optionValue' }
],
exec: function(args, context) { }
exec: createExec('tsv')
};
commands.tsr = {
name: 'tsr',
params: [ { name: 'text', type: 'string' } ],
exec: function(args, context) { }
exec: createExec('tsr')
};
commands.tse = {
name: 'tse',
params: [ { name: 'node', type: 'node' } ],
exec: createExec('tse')
};
commands.tsj = {
name: 'tsj',
params: [ { name: 'javascript', type: 'javascript' } ],
exec: createExec('tsj')
};
commands.tsb = {
name: 'tsb',
params: [ { name: 'toggle', type: 'boolean' } ],
exec: createExec('tsb')
};
commands.tss = {
name: 'tss',
exec: createExec('tss')
};
commands.tsu = {
name: 'tsu',
params: [ { name: 'num', type: 'number' } ],
exec: function(args, context) { }
params: [ { name: 'num', type: { name: 'number', max: 10, min: -5, step: 3 } } ],
exec: createExec('tsu')
};
commands.tsn = {
@ -817,31 +882,31 @@ commands.tsn = {
commands.tsnDif = {
name: 'tsn dif',
params: [ { name: 'text', type: 'string' } ],
exec: function(text) { }
exec: createExec('tsnDif')
};
commands.tsnExt = {
name: 'tsn ext',
params: [ { name: 'text', type: 'string' } ],
exec: function(text) { }
exec: createExec('tsnExt')
};
commands.tsnExte = {
name: 'tsn exte',
params: [ { name: 'text', type: 'string' } ],
exec: function(text) { }
exec: createExec('')
};
commands.tsnExten = {
name: 'tsn exten',
params: [ { name: 'text', type: 'string' } ],
exec: function(text) { }
exec: createExec('tsnExte')
};
commands.tsnExtend = {
name: 'tsn extend',
params: [ { name: 'text', type: 'string' } ],
exec: function(text) { }
exec: createExec('tsnExtend')
};
commands.tselarr = {
@ -850,7 +915,7 @@ commands.tselarr = {
{ name: 'num', type: { name: 'selection', data: [ '1', '2', '3' ] } },
{ name: 'arr', type: { name: 'array', subtype: 'string' } },
],
exec: function(args, context) {}
exec: createExec('tselarr')
};
commands.tsm = {
@ -862,7 +927,31 @@ commands.tsm = {
{ name: 'txt', type: 'string' },
{ name: 'num', type: { name: 'number', max: 42, min: 0 } },
],
exec: function(args, context) {}
exec: createExec('tsm')
};
commands.tsg = {
name: 'tsg',
hidden: true,
description: 'a param group test',
params: [
{ name: 'solo', type: { name: 'selection', data: [ 'aaa', 'bbb', 'ccc' ] } },
{
group: 'First',
params: [
{ name: 'txt1', type: 'string', defaultValue: null },
{ name: 'boolean1', type: 'boolean' }
]
},
{
group: 'Second',
params: [
{ name: 'txt2', type: 'string', defaultValue: 'd' },
{ name: 'num2', type: { name: 'number', defaultValue: 42 } }
]
}
],
exec: createExec('tsg')
};
@ -1211,6 +1300,278 @@ exports.testNestedCommand = function() {
};
});
/*
* Copyright 2009-2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE.txt or:
* http://opensource.org/licenses/BSD-3-Clause
*/
define('gclitest/testExec', ['require', 'exports', 'module' , 'gcli/cli', 'gcli/types', 'gcli/canon', 'gclitest/commands', 'gcli/types/node', 'test/assert'], function(require, exports, module) {
var Requisition = require('gcli/cli').Requisition;
var Status = require('gcli/types').Status;
var canon = require('gcli/canon');
var commands = require('gclitest/commands');
var nodetype = require('gcli/types/node');
var test = require('test/assert');
var actualExec;
var actualOutput;
exports.setup = function() {
commands.setup();
commands.commandExec.add(onCommandExec);
canon.commandOutputManager.addListener(onCommandOutput);
};
exports.shutdown = function() {
commands.shutdown();
commands.commandExec.remove(onCommandExec);
canon.commandOutputManager.removeListener(onCommandOutput);
};
function onCommandExec(ev) {
actualExec = ev;
}
function onCommandOutput(ev) {
actualOutput = ev.output;
}
function exec(command, expectedArgs) {
var environment = {};
var requisition = new Requisition(environment);
var reply = requisition.exec({ typed: command });
test.is(command.indexOf(actualExec.command.name), 0, 'Command name: ' + command);
if (reply !== true) {
test.ok(false, 'reply = false for command: ' + command);
}
if (expectedArgs == null) {
test.ok(false, 'expectedArgs == null for ' + command);
return;
}
if (actualExec.args == null) {
test.ok(false, 'actualExec.args == null for ' + command);
return;
}
test.is(Object.keys(expectedArgs).length, Object.keys(actualExec.args).length,
'Arg count: ' + command);
Object.keys(expectedArgs).forEach(function(arg) {
var expectedArg = expectedArgs[arg];
var actualArg = actualExec.args[arg];
if (Array.isArray(expectedArg)) {
if (!Array.isArray(actualArg)) {
test.ok(false, 'actual is not an array. ' + command + '/' + arg);
return;
}
test.is(expectedArg.length, actualArg.length,
'Array length: ' + command + '/' + arg);
for (var i = 0; i < expectedArg.length; i++) {
test.is(expectedArg[i], actualArg[i],
'Member: "' + command + '/' + arg + '/' + i);
}
}
else {
test.is(expectedArg, actualArg, 'Command: "' + command + '" arg: ' + arg);
}
});
test.is(environment, actualExec.context.environment, 'Environment');
test.is(false, actualOutput.error, 'output error is false');
test.is(command, actualOutput.typed, 'command is typed');
test.ok(typeof actualOutput.canonical === 'string', 'canonical exists');
test.is(actualExec.args, actualOutput.args, 'actualExec.args is actualOutput.args');
}
exports.testExec = function() {
exec('tss', {});
// Bug 707008 - GCLI defered types don't work properly
// exec('tsv option1 10', { optionType: commands.option1, optionValue: '10' });
// exec('tsv option2 10', { optionType: commands.option1, optionValue: 10 });
exec('tsr fred', { text: 'fred' });
exec('tsr fred bloggs', { text: 'fred bloggs' });
exec('tsr "fred bloggs"', { text: 'fred bloggs' });
exec('tsb', { toggle: false });
exec('tsb --toggle', { toggle: true });
exec('tsu 10', { num: 10 });
exec('tsu --num 10', { num: 10 });
// Bug 704829 - Enable GCLI Javascript parameters
// The answer to this should be 2
exec('tsj { 1 + 1 }', { javascript: '1 + 1' });
var origDoc = nodetype.getDocument();
nodetype.setDocument(mockDoc);
exec('tse :root', { node: mockBody });
nodetype.setDocument(origDoc);
exec('tsn dif fred', { text: 'fred' });
exec('tsn exten fred', { text: 'fred' });
exec('tsn extend fred', { text: 'fred' });
exec('tselarr 1', { num: '1', arr: [ ] });
exec('tselarr 1 a', { num: '1', arr: [ 'a' ] });
exec('tselarr 1 a b', { num: '1', arr: [ 'a', 'b' ] });
exec('tsm a 10 10', { abc: 'a', txt: '10', num: 10 });
// Bug 707009 - GCLI doesn't always fill in default parameters properly
// exec('tsg a', { solo: 'a', txt1: null, boolean1: false, txt2: 'd', num2: 42 });
};
var mockBody = {
style: {}
};
var mockDoc = {
querySelectorAll: function(css) {
if (css === ':root') {
return {
length: 1,
item: function(i) {
return mockBody;
}
};
}
throw new Error('mockDoc.querySelectorAll(\'' + css + '\') error');
}
};
});
/*
* Copyright 2009-2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE.txt or:
* http://opensource.org/licenses/BSD-3-Clause
*/
define('gclitest/testKeyboard', ['require', 'exports', 'module' , 'gcli/cli', 'gcli/types', 'gcli/canon', 'gclitest/commands', 'gcli/types/node', 'test/assert'], function(require, exports, module) {
var Requisition = require('gcli/cli').Requisition;
var Status = require('gcli/types').Status;
var canon = require('gcli/canon');
var commands = require('gclitest/commands');
var nodetype = require('gcli/types/node');
var test = require('test/assert');
exports.setup = function() {
commands.setup();
};
exports.shutdown = function() {
commands.shutdown();
};
var COMPLETES_TO = 'complete';
var KEY_UPS_TO = 'keyup';
var KEY_DOWNS_TO = 'keydown';
function check(initial, action, after) {
var requisition = new Requisition();
requisition.update({
typed: initial,
cursor: { start: initial.length, end: initial.length }
});
var assignment = requisition.getAssignmentAt(initial.length);
switch (action) {
case COMPLETES_TO:
assignment.complete();
break;
case KEY_UPS_TO:
assignment.increment();
break;
case KEY_DOWNS_TO:
assignment.decrement();
break;
}
test.is(after, requisition.toString(), initial + ' + ' + action + ' -> ' + after);
}
exports.testComplete = function() {
check('tsela', COMPLETES_TO, 'tselarr ');
check('tsn di', COMPLETES_TO, 'tsn dif ');
check('tsg a', COMPLETES_TO, 'tsg aaa ');
check('{ wind', COMPLETES_TO, '{ window');
check('{ window.docum', COMPLETES_TO, '{ window.document');
check('{ window.document.titl', COMPLETES_TO, '{ window.document.title ');
};
exports.testIncrDecr = function() {
check('tsu -70', KEY_UPS_TO, 'tsu -5');
check('tsu -7', KEY_UPS_TO, 'tsu -5');
check('tsu -6', KEY_UPS_TO, 'tsu -5');
check('tsu -5', KEY_UPS_TO, 'tsu -3');
check('tsu -4', KEY_UPS_TO, 'tsu -3');
check('tsu -3', KEY_UPS_TO, 'tsu 0');
check('tsu -2', KEY_UPS_TO, 'tsu 0');
check('tsu -1', KEY_UPS_TO, 'tsu 0');
check('tsu 0', KEY_UPS_TO, 'tsu 3');
check('tsu 1', KEY_UPS_TO, 'tsu 3');
check('tsu 2', KEY_UPS_TO, 'tsu 3');
check('tsu 3', KEY_UPS_TO, 'tsu 6');
check('tsu 4', KEY_UPS_TO, 'tsu 6');
check('tsu 5', KEY_UPS_TO, 'tsu 6');
check('tsu 6', KEY_UPS_TO, 'tsu 9');
check('tsu 7', KEY_UPS_TO, 'tsu 9');
check('tsu 8', KEY_UPS_TO, 'tsu 9');
check('tsu 9', KEY_UPS_TO, 'tsu 10');
check('tsu 10', KEY_UPS_TO, 'tsu 10');
check('tsu 100', KEY_UPS_TO, 'tsu -5');
check('tsu -70', KEY_DOWNS_TO, 'tsu 10');
check('tsu -7', KEY_DOWNS_TO, 'tsu 10');
check('tsu -6', KEY_DOWNS_TO, 'tsu 10');
check('tsu -5', KEY_DOWNS_TO, 'tsu -5');
check('tsu -4', KEY_DOWNS_TO, 'tsu -5');
check('tsu -3', KEY_DOWNS_TO, 'tsu -5');
check('tsu -2', KEY_DOWNS_TO, 'tsu -3');
check('tsu -1', KEY_DOWNS_TO, 'tsu -3');
check('tsu 0', KEY_DOWNS_TO, 'tsu -3');
check('tsu 1', KEY_DOWNS_TO, 'tsu 0');
check('tsu 2', KEY_DOWNS_TO, 'tsu 0');
check('tsu 3', KEY_DOWNS_TO, 'tsu 0');
check('tsu 4', KEY_DOWNS_TO, 'tsu 3');
check('tsu 5', KEY_DOWNS_TO, 'tsu 3');
check('tsu 6', KEY_DOWNS_TO, 'tsu 3');
check('tsu 7', KEY_DOWNS_TO, 'tsu 6');
check('tsu 8', KEY_DOWNS_TO, 'tsu 6');
check('tsu 9', KEY_DOWNS_TO, 'tsu 6');
check('tsu 10', KEY_DOWNS_TO, 'tsu 9');
check('tsu 100', KEY_DOWNS_TO, 'tsu 10');
// Bug 707007 - GCLI increment and decrement operations cycle through
// selection options in the wrong order
check('tselarr 1', KEY_DOWNS_TO, 'tselarr 2');
check('tselarr 2', KEY_DOWNS_TO, 'tselarr 3');
check('tselarr 3', KEY_DOWNS_TO, 'tselarr 1');
check('tselarr 3', KEY_UPS_TO, 'tselarr 2');
};
});
/*
* Copyright 2009-2011 Mozilla Foundation and contributors
@ -1544,6 +1905,8 @@ function undefine() {
delete define.modules['gclitest/testSplit'];
delete define.modules['gclitest/commands'];
delete define.modules['gclitest/testCli'];
delete define.modules['gclitest/testExec'];
delete define.modules['gclitest/testKeyboard'];
delete define.modules['gclitest/testHistory'];
delete define.modules['gclitest/testRequire'];
delete define.modules['gclitest/requirable'];
@ -1556,6 +1919,8 @@ function undefine() {
delete define.globalDomain.modules['gclitest/testSplit'];
delete define.globalDomain.modules['gclitest/commands'];
delete define.globalDomain.modules['gclitest/testCli'];
delete define.globalDomain.modules['gclitest/testExec'];
delete define.globalDomain.modules['gclitest/testKeyboard'];
delete define.globalDomain.modules['gclitest/testHistory'];
delete define.globalDomain.modules['gclitest/testRequire'];
delete define.globalDomain.modules['gclitest/requirable'];

View File

@ -67,12 +67,12 @@ typesNumberNan=Can't convert "%S" to a number.
# LOCALIZATION NOTE (typesNumberMax): When the command line is passed a
# number, but the number is bigger than the largest allowed number, this error
# message is displayed.
typesNumberMax=%1$S is greater that maximum allowed: %2$S.
typesNumberMax=%1$S is greater than maximum allowed: %2$S.
# LOCALIZATION NOTE (typesNumberMin): When the command line is passed a
# number, but the number is lower than the smallest allowed number, this error
# message is displayed.
typesNumberMin=%1$S is smaller that minimum allowed: %2$S.
typesNumberMin=%1$S is smaller than minimum allowed: %2$S.
# LOCALIZATION NOTE (typesSelectionNomatch): When the command line is passed
# an option with a limited number of correct values, but the passed value is
@ -94,3 +94,50 @@ nodeParseMultiple=Too many matches (%S)
# displayed.
nodeParseNone=No matches
# LOCALIZATION NOTE (helpDesc): A very short description of the 'help'
# command. This string is designed to be shown in a menu alongside the command
# name, which is why it should be as short as possible. See helpManual for a
# fuller description of what it does.
helpDesc=Get help on the available commands
# LOCALIZATION NOTE (helpManual): A fuller description of the 'help' command.
# Displayed when the user asks for help on what it does.
helpManual=Provide help either on a specific command (if a search string is provided and an exact match is found) or on the available commands (if a search string is not provided, or if no exact match is found).
# LOCALIZATION NOTE (helpSearchDesc): A very short description of the 'search'
# parameter to the 'help' command. See helpSearchManual for a fuller
# description of what it does. This string is designed to be shown in a dialog
# with restricted space, which is why it should be as short as possible.
helpSearchDesc=Search string
# LOCALIZATION NOTE (helpSearchManual): A fuller description of the 'search'
# parameter to the 'help' command. Displayed when the user asks for help on
# what it does.
helpSearchManual=A search string to use in narrowing down the list of commands that are displayed to the user. Any part of the string can match, regular expressions are not supported.
# LOCALIZATION NOTE (helpManSynopsis): A heading shown at the top of a help
# page for a command in the console It labels a summary of the parameters to
# the command
helpManSynopsis=Synopsis
# LOCALIZATION NOTE (helpManDescription): A heading shown in a help page for a
# command in the console. This heading precedes the top level description.
helpManDescription=Description
# LOCALIZATION NOTE (helpManParameters): A heading shown above the parameters
# in a help page for a command in the console.
helpManParameters=Parameters
# LOCALIZATION NOTE (helpManNone): Some text shown under the parameters
# heading in a help page for a command which has no parameters.
helpManNone=None
# LOCALIZATION NOTE (introHeader): The heading displayed at the top of the
# output for the help command
introHeader=Welcome to Firefox Developer Tools
# LOCALIZATION NOTE (introBody): The text displayed at the top of the output
# for the help command, just before the list of commands. This text is wrapped
# inside a link to a localized MDN article
introBody=For more information see MDN.

View File

@ -44,8 +44,7 @@ inspectDesc=Inspect a node
# LOCALIZATION NOTE (inspectManual) A fuller description of the 'inspect'
# command, displayed when the user asks for help on what it does.
inspectManual=Investigate the dimensions and properties of an element using \
a CSS selector to open the DOM highlighter
inspectManual=Investigate the dimensions and properties of an element using a CSS selector to open the DOM highlighter
# LOCALIZATION NOTE (inspectNodeDesc) A very short string to describe the
# 'node' parameter to the 'inspect' command, which is displayed in a dialog
@ -55,5 +54,4 @@ inspectNodeDesc=CSS selector
# LOCALIZATION NOTE (inspectNodeManual) A fuller description of the 'node'
# parameter to the 'inspect' command, displayed when the user asks for help
# on what it does.
inspectNodeManual=A CSS selector for use with Document.querySelector which \
identifies a single element
inspectNodeManual=A CSS selector for use with Document.querySelector which identifies a single element

View File

@ -1024,8 +1024,7 @@ toolbar[iconsize="small"] #feed-button {
}
/* Favicon */
#page-proxy-favicon,
#urlbar-throbber {
#page-proxy-favicon {
width: 16px;
height: 16px;
}
@ -1044,10 +1043,6 @@ toolbar[iconsize="small"] #feed-button {
opacity: 0.3;
}
#urlbar-throbber {
list-style-image: url("chrome://browser/skin/places/searching_16.png");
}
/* Identity indicator */
#identity-box {
background-image: -moz-linear-gradient(hsl(0,0%,98%), hsl(0,0%,92%));

View File

@ -46,7 +46,6 @@
height: 100%;
vertical-align: middle;
background-color: transparent;
font: 12px Consolas, "Lucida Console", monospace;
}
.gcliterm-input-node {
@ -64,24 +63,6 @@
-moz-padding-end: 4px;
}
.gcli-in-valid {
border-bottom: none;
}
.gcli-in-incomplete {
color: #DDD;
border-bottom: 1px dotted #999;
}
.gcli-in-error {
color: #DDD;
border-bottom: 1px dotted #F00;
}
.gcli-in-ontab {
color: #999;
}
.gcliterm-stack-node {
background: url("chrome://global/skin/icons/commandline.png") 4px center no-repeat;
width: 100%;
@ -109,19 +90,47 @@
border-bottom: 1px solid threedshadow;
}
.gcli-help-right {
text-align: right;
}
.gcliterm-menu {
display: -moz-box;
-moz-box-flex: 1;
border-bottom-color: white;
}
.gcliterm-hint-scroll {
overflow-y: scroll;
border-bottom-color: threedshadow;
}
.gcliterm-hint-nospace {
display: none;
}
.gcliterm-msg-body {
margin-top: 0;
margin-bottom: 3px;
-moz-margin-start: 3px;
-moz-margin-end: 6px;
}
/* Extract from display.css, we only want these 2 rules */
.gcli-out-shortcut {
border: 1px solid #999;
border-radius: 3px;
padding: 0 4px;
margin: 0 4px;
font-size: 70%;
color: #666;
cursor: pointer;
vertical-align: bottom;
}
.gcli-out-shortcut:before {
color: #66F;
content: '\bb';
padding: 0 2px;
}
/*
* The language of a console is not en_US or any other common language
* (i.e we don't attempt to translate 'console.log(x)')
@ -151,6 +160,15 @@
/* From: $GCLI/mozilla/gcli/ui/gcliterm-gnomestripe.css */
.gcliterm-input-node,
.gcliterm-complete-node {
font: 12px "DejaVu Sans Mono", monospace;
}
.gcli-out-shortcut {
font-family: "DejaVu Sans Mono", monospace;
}
/* From: $GCLI/lib/gcli/ui/arg_fetch.css */
.gcli-argfetch {
@ -181,7 +199,7 @@
.gcli-af-required {
font-size: 90%;
color: #f66;
padding-left: 5px;
-moz-padding-start: 5px;
}
.gcli-af-error {
@ -197,6 +215,10 @@
width: 100%;
}
.gcli-field-javascript {
margin-bottom: 0;
}
/* From: $GCLI/lib/gcli/ui/menu.css */
.gcli-menu {
@ -284,3 +306,45 @@
color: #66F;
font-weight: bold;
}
/* From: $GCLI/lib/gcli/commands/help.css */
.gcli-help-name {
text-align: end;
}
.gcli-help-arrow {
font-size: 70%;
color: #AAA;
}
.gcli-help-synopsis {
font-family: monospace;
font-weight: normal;
padding: 0 3px;
margin: 0 10px;
border: 1px solid #999;
border-radius: 3px;
color: #666;
cursor: pointer;
display: inline-block;
}
.gcli-help-synopsis:before {
color: #66F;
content: '\bb';
}
.gcli-help-description {
margin: 0 20px;
padding: 0;
}
.gcli-help-parameter {
margin: 0 30px;
padding: 0;
}
.gcli-help-header {
margin: 10px 0 6px;
}

View File

@ -57,7 +57,6 @@ browser.jar:
skin/classic/browser/places/organizer.css (places/organizer.css)
* skin/classic/browser/places/organizer.xml (places/organizer.xml)
skin/classic/browser/places/query.png (places/query.png)
skin/classic/browser/places/searching_16.png (places/searching_16.png)
skin/classic/browser/places/starPage.png (places/starPage.png)
skin/classic/browser/places/tag.png (places/tag.png)
skin/classic/browser/places/toolbarDropMarker.png (places/toolbarDropMarker.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -1106,8 +1106,7 @@ toolbar[mode="icons"] #zoom-in-button {
height: 22px;
}
#page-proxy-favicon,
#urlbar-throbber {
#page-proxy-favicon {
width: 16px;
height: 16px;
margin: 0px;
@ -1127,10 +1126,6 @@ toolbar[mode="icons"] #zoom-in-button {
opacity: 0.5;
}
#urlbar-throbber {
list-style-image: url("chrome://browser/skin/places/searching_16.png");
}
#wrapper-urlbar-container[place="palette"] {
max-width: 20em;
}

View File

@ -46,7 +46,6 @@
height: 100%;
vertical-align: middle;
background-color: transparent;
font: 12px Consolas, "Lucida Console", monospace;
}
.gcliterm-input-node {
@ -64,24 +63,6 @@
-moz-padding-end: 4px;
}
.gcli-in-valid {
border-bottom: none;
}
.gcli-in-incomplete {
color: #DDD;
border-bottom: 1px dotted #999;
}
.gcli-in-error {
color: #DDD;
border-bottom: 1px dotted #F00;
}
.gcli-in-ontab {
color: #999;
}
.gcliterm-stack-node {
background: url("chrome://global/skin/icons/commandline.png") 4px center no-repeat;
width: 100%;
@ -109,19 +90,47 @@
border-bottom: 1px solid threedshadow;
}
.gcli-help-right {
text-align: right;
}
.gcliterm-menu {
display: -moz-box;
-moz-box-flex: 1;
border-bottom-color: white;
}
.gcliterm-hint-scroll {
overflow-y: scroll;
border-bottom-color: threedshadow;
}
.gcliterm-hint-nospace {
display: none;
}
.gcliterm-msg-body {
margin-top: 0;
margin-bottom: 3px;
-moz-margin-start: 3px;
-moz-margin-end: 6px;
}
/* Extract from display.css, we only want these 2 rules */
.gcli-out-shortcut {
border: 1px solid #999;
border-radius: 3px;
padding: 0 4px;
margin: 0 4px;
font-size: 70%;
color: #666;
cursor: pointer;
vertical-align: bottom;
}
.gcli-out-shortcut:before {
color: #66F;
content: '\bb';
padding: 0 2px;
}
/*
* The language of a console is not en_US or any other common language
* (i.e we don't attempt to translate 'console.log(x)')
@ -151,10 +160,19 @@
/* From: $GCLI/mozilla/gcli/ui/gcliterm-pinstripe.css */
.gcliterm-input-node,
.gcliterm-complete-node {
font: 11px Menlo, Monaco, monospace;
}
.gcliterm-complete-node {
padding-top: 6px !important;
}
.gcli-out-shortcut {
font-family: Menlo, Monaco, monospace;
}
/* From: $GCLI/lib/gcli/ui/arg_fetch.css */
.gcli-argfetch {
@ -185,7 +203,7 @@
.gcli-af-required {
font-size: 90%;
color: #f66;
padding-left: 5px;
-moz-padding-start: 5px;
}
.gcli-af-error {
@ -201,6 +219,10 @@
width: 100%;
}
.gcli-field-javascript {
margin-bottom: 0;
}
/* From: $GCLI/lib/gcli/ui/menu.css */
.gcli-menu {
@ -288,3 +310,45 @@
color: #66F;
font-weight: bold;
}
/* From: $GCLI/lib/gcli/commands/help.css */
.gcli-help-name {
text-align: end;
}
.gcli-help-arrow {
font-size: 70%;
color: #AAA;
}
.gcli-help-synopsis {
font-family: monospace;
font-weight: normal;
padding: 0 3px;
margin: 0 10px;
border: 1px solid #999;
border-radius: 3px;
color: #666;
cursor: pointer;
display: inline-block;
}
.gcli-help-synopsis:before {
color: #66F;
content: '\bb';
}
.gcli-help-description {
margin: 0 20px;
padding: 0;
}
.gcli-help-parameter {
margin: 0 30px;
padding: 0;
}
.gcli-help-header {
margin: 10px 0 6px;
}

View File

@ -76,7 +76,6 @@ browser.jar:
skin/classic/browser/places/plus.png (places/plus.png)
skin/classic/browser/places/plus-active.png (places/plus-active.png)
skin/classic/browser/places/starPage.png (places/starPage.png)
skin/classic/browser/places/searching_16.png (places/searching_16.png)
skin/classic/browser/places/starred48.png (places/starred48.png)
skin/classic/browser/places/unstarred48.png (places/unstarred48.png)
skin/classic/browser/places/unfiledBookmarks.png (places/unfiledBookmarks.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -1489,8 +1489,7 @@ html|*.urlbar-input:-moz-lwtheme:-moz-placeholder,
/* page proxy icon */
#page-proxy-favicon,
#urlbar-throbber {
#page-proxy-favicon {
width: 16px;
height: 16px;
}
@ -1509,10 +1508,6 @@ html|*.urlbar-input:-moz-lwtheme:-moz-placeholder,
opacity: 0.5;
}
#urlbar-throbber {
list-style-image: url("chrome://browser/skin/places/searching_16.png");
}
/* autocomplete */
#treecolAutoCompleteImage {

View File

@ -46,7 +46,6 @@
height: 100%;
vertical-align: middle;
background-color: transparent;
font: 12px Consolas, "Lucida Console", monospace;
}
.gcliterm-input-node {
@ -64,24 +63,6 @@
-moz-padding-end: 4px;
}
.gcli-in-valid {
border-bottom: none;
}
.gcli-in-incomplete {
color: #DDD;
border-bottom: 1px dotted #999;
}
.gcli-in-error {
color: #DDD;
border-bottom: 1px dotted #F00;
}
.gcli-in-ontab {
color: #999;
}
.gcliterm-stack-node {
background: url("chrome://global/skin/icons/commandline.png") 4px center no-repeat;
width: 100%;
@ -109,19 +90,47 @@
border-bottom: 1px solid threedshadow;
}
.gcli-help-right {
text-align: right;
}
.gcliterm-menu {
display: -moz-box;
-moz-box-flex: 1;
border-bottom-color: white;
}
.gcliterm-hint-scroll {
overflow-y: scroll;
border-bottom-color: threedshadow;
}
.gcliterm-hint-nospace {
display: none;
}
.gcliterm-msg-body {
margin-top: 0;
margin-bottom: 3px;
-moz-margin-start: 3px;
-moz-margin-end: 6px;
}
/* Extract from display.css, we only want these 2 rules */
.gcli-out-shortcut {
border: 1px solid #999;
border-radius: 3px;
padding: 0 4px;
margin: 0 4px;
font-size: 70%;
color: #666;
cursor: pointer;
vertical-align: bottom;
}
.gcli-out-shortcut:before {
color: #66F;
content: '\bb';
padding: 0 2px;
}
/*
* The language of a console is not en_US or any other common language
* (i.e we don't attempt to translate 'console.log(x)')
@ -151,6 +160,15 @@
/* From: $GCLI/mozilla/gcli/ui/gcliterm-winstripe.css */
.gcliterm-input-node,
.gcliterm-complete-node {
font: 12px Consolas, "Lucida Console", monospace;
}
.gcli-out-shortcut {
font-family: Consolas, Inconsolata, "Courier New", monospace;
}
/* From: $GCLI/lib/gcli/ui/arg_fetch.css */
.gcli-argfetch {
@ -181,7 +199,7 @@
.gcli-af-required {
font-size: 90%;
color: #f66;
padding-left: 5px;
-moz-padding-start: 5px;
}
.gcli-af-error {
@ -197,6 +215,10 @@
width: 100%;
}
.gcli-field-javascript {
margin-bottom: 0;
}
/* From: $GCLI/lib/gcli/ui/menu.css */
.gcli-menu {
@ -284,3 +306,45 @@
color: #66F;
font-weight: bold;
}
/* From: $GCLI/lib/gcli/commands/help.css */
.gcli-help-name {
text-align: end;
}
.gcli-help-arrow {
font-size: 70%;
color: #AAA;
}
.gcli-help-synopsis {
font-family: monospace;
font-weight: normal;
padding: 0 3px;
margin: 0 10px;
border: 1px solid #999;
border-radius: 3px;
color: #666;
cursor: pointer;
display: inline-block;
}
.gcli-help-synopsis:before {
color: #66F;
content: '\bb';
}
.gcli-help-description {
margin: 0 20px;
padding: 0;
}
.gcli-help-parameter {
margin: 0 30px;
padding: 0;
}
.gcli-help-header {
margin: 10px 0 6px;
}

View File

@ -75,7 +75,6 @@ browser.jar:
skin/classic/browser/places/history.png (places/history.png)
skin/classic/browser/places/allBookmarks.png (places/allBookmarks.png)
skin/classic/browser/places/unsortedBookmarks.png (places/unsortedBookmarks.png)
skin/classic/browser/places/searching_16.png (places/searching_16.png)
skin/classic/browser/places/downloads.png (places/downloads.png)
skin/classic/browser/preferences/alwaysAsk.png (preferences/alwaysAsk.png)
skin/classic/browser/preferences/application.png (preferences/application.png)
@ -231,7 +230,6 @@ browser.jar:
skin/classic/aero/browser/places/history.png (places/history-aero.png)
skin/classic/aero/browser/places/allBookmarks.png (places/allBookmarks-aero.png)
skin/classic/aero/browser/places/unsortedBookmarks.png (places/unsortedBookmarks-aero.png)
skin/classic/aero/browser/places/searching_16.png (places/searching_16.png)
skin/classic/aero/browser/places/downloads.png (places/downloads.png)
skin/classic/aero/browser/preferences/alwaysAsk.png (preferences/alwaysAsk-aero.png)
skin/classic/aero/browser/preferences/application.png (preferences/application-aero.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

2
build/macosx/common Normal file
View File

@ -0,0 +1,2 @@
CC=/usr/bin/gcc-4.2
CXX=/usr/bin/g++-4.2

View File

@ -1,10 +1,4 @@
if test -z "$CC" ; then
CC=gcc-4.2
fi
if test -z "$CXX" ; then
CXX=g++-4.2
fi
. $topsrcdir/build/macosx/common
# Mac builds don't nomally have to be handled as cross
# compilation, but some of the libraries on the bots

View File

@ -45,6 +45,8 @@ ac_add_app_options x86_64 --target=x86_64-apple-darwin10
ac_add_app_options i386 --with-macos-sdk=/Developer/SDKs/MacOSX10.5.sdk
ac_add_app_options x86_64 --with-macos-sdk=/Developer/SDKs/MacOSX10.6.sdk
. $topsrcdir/build/macosx/common
# $MOZ_BUILD_APP is only defined when sourced by configure. That's not a
# problem, because the variables it affects only need to be set for
# configure.
@ -52,14 +54,6 @@ if test -n "$MOZ_BUILD_APP" ; then
if test "$MOZ_BUILD_APP" = "i386" -o "$MOZ_BUILD_APP" = "x86_64"; then
TARGET_CPU=$MOZ_BUILD_APP
if test -z "$CC" ; then
CC=gcc-4.2
fi
if test -z "$CXX" ; then
CXX=g++-4.2
fi
# $HOST_CXX is presently unused. $HOST_CC will only be used during a cross
# compile.
HOST_CC=$CC

View File

@ -115,7 +115,7 @@ endif
####################################
# Sanity checks
ifneq (,$(filter MINGW%,$(shell uname -s)))
ifneq (,$(findstring mingw,$(CONFIG_GUESS)))
# check for CRLF line endings
ifneq (0,$(shell $(PERL) -e 'binmode(STDIN); while (<STDIN>) { if (/\r/) { print "1"; exit } } print "0"' < $(TOPSRCDIR)/client.mk))
$(error This source tree appears to have Windows-style line endings. To \
@ -133,8 +133,6 @@ MOZCONFIG_LOADER := build/autoconf/mozconfig2client-mk
MOZCONFIG_FINDER := build/autoconf/mozconfig-find
MOZCONFIG_MODULES := build/unix/uniq.pl
run_for_side_effects := \
$(shell $(TOPSRCDIR)/$(MOZCONFIG_LOADER) $(TOPSRCDIR) $(TOPSRCDIR)/.mozconfig.mk > $(TOPSRCDIR)/.mozconfig.out)
@ -142,6 +140,13 @@ include $(TOPSRCDIR)/.mozconfig.mk
ifndef MOZ_OBJDIR
MOZ_OBJDIR = obj-$(CONFIG_GUESS)
else
# On Windows Pymake builds check MOZ_OBJDIR doesn't start with "/"
ifneq (,$(findstring mingw,$(CONFIG_GUESS)))
ifeq (1_a,$(.PYMAKE)_$(firstword a$(subst /, ,$(MOZ_OBJDIR))))
$(error For Windows Pymake builds, MOZ_OBJDIR must be a Windows [and not MSYS] style path.)
endif
endif
endif
ifdef MOZ_BUILD_PROJECTS
@ -294,6 +299,10 @@ CONFIG_STATUS_DEPS := \
$(wildcard $(addsuffix confvars.sh,$(wildcard $(TOPSRCDIR)/*/))) \
$(NULL)
CONFIGURE_ENV_ARGS += \
MAKE="$(MAKE)" \
$(NULL)
# configure uses the program name to determine @srcdir@. Calling it without
# $(TOPSRCDIR) will set @srcdir@ to "."; otherwise, it is set to the full
# path of $(TOPSRCDIR).

View File

@ -474,6 +474,8 @@ endif
QCMS_LIBS = @QCMS_LIBS@
MOZ_HARFBUZZ_LIBS = @MOZ_HARFBUZZ_LIBS@
MOZ_GRAPHITE_LIBS = @MOZ_GRAPHITE_LIBS@
MOZ_GRAPHITE = @MOZ_GRAPHITE@
MOZ_OTS_LIBS = @MOZ_OTS_LIBS@
MOZ_SKIA_LIBS = @MOZ_SKIA_LIBS@

View File

@ -64,6 +64,8 @@ ifdef SDK_HEADERS
EXPORTS += $(SDK_HEADERS)
endif
REPORT_BUILD = @echo $(notdir $<)
ifeq ($(OS_ARCH),OS2)
EXEC =
else
@ -1148,25 +1150,32 @@ endif # MOZ_AUTO_DEPS
# Rules for building native targets must come first because of the host_ prefix
host_%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
host_%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
host_%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
host_%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
host_%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
%:: %.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS)
%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
@ -1177,6 +1186,7 @@ moc_%.cpp: %.h $(GLOBAL_DEPS)
$(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@
moc_%.cc: %.cc $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@
ifdef ASFILES
@ -1197,10 +1207,12 @@ endif
# Please keep the next two rules in sync.
#
%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CXX)
$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CXX)
ifdef STRICT_CPLUSPLUS_SUFFIX
echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > t_$*.cc
@ -1211,10 +1223,12 @@ else
endif #STRICT_CPLUSPLUS_SUFFIX
$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CXX)
$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS)
$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS)
@ -1464,6 +1478,7 @@ XPIDL_DEPS = \
$(NULL)
$(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
$(REPORT_BUILD)
$(PYTHON_PATH) \
-I$(topsrcdir)/other-licenses/ply \
-I$(topsrcdir)/xpcom/idl-parser \
@ -1475,6 +1490,7 @@ ifndef NO_GEN_XPT
# generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
# into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
$(REPORT_BUILD)
$(PYTHON_PATH) \
-I$(topsrcdir)/other-licenses/ply \
-I$(topsrcdir)/xpcom/idl-parser \
@ -1763,12 +1779,15 @@ define MAKE_DEPS_NOAUTO
endef
$(MDDEPDIR)/%.pp: %.c
$(REPORT_BUILD)
@$(MAKE_DEPS_NOAUTO)
$(MDDEPDIR)/%.pp: %.cpp
$(REPORT_BUILD)
@$(MAKE_DEPS_NOAUTO)
$(MDDEPDIR)/%.pp: %.s
$(REPORT_BUILD)
@$(MAKE_DEPS_NOAUTO)
ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))

View File

@ -20,18 +20,20 @@ new
algorithm
deque
iostream
iterator
limits
list
map
memory
set
stack
string
utility
vector
set
cassert
climits
cstdarg
cstdio
cstdlib
cstring
utility
cwchar

View File

@ -2114,10 +2114,24 @@ if test -n "$MOZ_VALGRIND"; then
AC_MSG_ERROR(
[--enable-valgrind specified but Valgrind is not installed]))
AC_DEFINE(MOZ_VALGRIND)
MOZ_VALGRIND=1
fi
AC_SUBST(MOZ_VALGRIND)
dnl ========================================================
dnl = Use DMD
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(dmd,
[ --enable-dmd Enable DMD; also disables jemalloc (default=no)],
MOZ_DMD=1,
MOZ_DMD= )
if test -n "$MOZ_DMD"; then
MOZ_CHECK_HEADER([valgrind/valgrind.h], [],
AC_MSG_ERROR(
[--enable-dmd specified but Valgrind is not installed]))
AC_DEFINE(MOZ_DMD)
fi
AC_SUBST(MOZ_DMD)
dnl ========================================================
dnl jprof
dnl ========================================================
@ -2251,6 +2265,17 @@ if test "$_python_res" != 0; then
fi
AC_MSG_RESULT([yes])
dnl Check for using a custom <stdint.h> implementation
dnl ========================================================
AC_MSG_CHECKING(for custom <stdint.h> implementation)
if test "$MOZ_CUSTOM_STDINT_H"; then
AC_DEFINE_UNQUOTED(MOZ_CUSTOM_STDINT_H, "$MOZ_CUSTOM_STDINT_H")
AC_SUBST(MOZ_CUSTOM_STDINT_H)
AC_MSG_RESULT(using $MOZ_CUSTOM_STDINT_H)
else
AC_MSG_RESULT(none specified)
fi
dnl Get mozilla version from central milestone file
MOZILLA_VERSION=`$PERL $srcdir/config/milestone.pl -topsrcdir $srcdir`
@ -3017,47 +3042,8 @@ else
AC_MSG_RESULT(no)
fi
dnl Check for int16_t, int32_t, int64_t, int64, uint, uint_t, and uint16_t.
dnl Check for int64, uint, and uint_t.
dnl ========================================================
AC_MSG_CHECKING(for int16_t)
AC_CACHE_VAL(ac_cv_int16_t,
[AC_TRY_COMPILE([#include <stdio.h>
#include <sys/types.h>],
[int16_t foo = 0;],
[ac_cv_int16_t=true],
[ac_cv_int16_t=false])])
if test "$ac_cv_int16_t" = true ; then
AC_DEFINE(HAVE_INT16_T)
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
AC_MSG_CHECKING(for int32_t)
AC_CACHE_VAL(ac_cv_int32_t,
[AC_TRY_COMPILE([#include <stdio.h>
#include <sys/types.h>],
[int32_t foo = 0;],
[ac_cv_int32_t=true],
[ac_cv_int32_t=false])])
if test "$ac_cv_int32_t" = true ; then
AC_DEFINE(HAVE_INT32_T)
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
AC_MSG_CHECKING(for int64_t)
AC_CACHE_VAL(ac_cv_int64_t,
[AC_TRY_COMPILE([#include <stdio.h>
#include <sys/types.h>],
[int64_t foo = 0;],
[ac_cv_int64_t=true],
[ac_cv_int64_t=false])])
if test "$ac_cv_int64_t" = true ; then
AC_DEFINE(HAVE_INT64_T)
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
AC_MSG_CHECKING(for int64)
AC_CACHE_VAL(ac_cv_int64,
[AC_TRY_COMPILE([#include <stdio.h>
@ -3097,19 +3083,6 @@ if test "$ac_cv_uint_t" = true ; then
else
AC_MSG_RESULT(no)
fi
AC_MSG_CHECKING(for uint16_t)
AC_CACHE_VAL(ac_cv_uint16_t,
[AC_TRY_COMPILE([#include <stdio.h>
#include <sys/types.h>],
[uint16_t foo = 0;],
[ac_cv_uint16_t=true],
[ac_cv_uint16_t=false])])
if test "$ac_cv_uint16_t" = true ; then
AC_DEFINE(HAVE_UINT16_T)
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
dnl On the gcc trunk (as of 2001-02-09) _GNU_SOURCE, and thus __USE_GNU,
dnl are defined when compiling C++ but not C. Since the result of this
@ -4680,6 +4653,7 @@ USE_ARM_KUSER=
BUILD_CTYPES=1
MOZ_USE_NATIVE_POPUP_WINDOWS=
MOZ_ANDROID_HISTORY=
MOZ_GRAPHITE=
case "${target}" in
*darwin*)
@ -7136,7 +7110,7 @@ dnl = Enable trace malloc
dnl ========================================================
NS_TRACE_MALLOC=${MOZ_TRACE_MALLOC}
MOZ_ARG_ENABLE_BOOL(trace-malloc,
[ --enable-trace-malloc Enable malloc tracing],
[ --enable-trace-malloc Enable malloc tracing; also disables jemalloc],
NS_TRACE_MALLOC=1,
NS_TRACE_MALLOC= )
if test "$NS_TRACE_MALLOC"; then
@ -7158,6 +7132,9 @@ MOZ_ARG_ENABLE_BOOL(jemalloc,
if test "$NS_TRACE_MALLOC"; then
MOZ_MEMORY=
fi
if test "$MOZ_DMD"; then
MOZ_MEMORY=
fi
if test "${OS_TARGET}" = "Android"; then
dnl On Android, we use WRAP_LDFLAGS to link everything to mozutils
@ -7748,35 +7725,12 @@ MOZ_ARG_HEADER(Compiler Options)
dnl ========================================================
dnl Check for gcc -pipe support
dnl ========================================================
AC_MSG_CHECKING([for gcc -pipe support])
if test -n "$GNU_CC" -a -n "$GNU_CXX" -a -n "$GNU_AS"; then
echo '#include <stdio.h>' > dummy-hello.c
echo 'int main() { printf("Hello World\n"); exit(0); }' >> dummy-hello.c
${CC} -S dummy-hello.c -o dummy-hello.s 2>&5
cat dummy-hello.s 2> /dev/null | ${AS_BIN} -o dummy-hello.S - 2>&5
if test $? = 0; then
_res_as_stdin="yes"
else
_res_as_stdin="no"
fi
if test "$_res_as_stdin" = "yes"; then
_SAVE_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS -pipe"
AC_TRY_COMPILE( [ #include <stdio.h> ],
[printf("Hello World\n");],
[_res_gcc_pipe="yes"],
[_res_gcc_pipe="no"] )
CFLAGS=$_SAVE_CFLAGS
fi
if test "$_res_as_stdin" = "yes" -a "$_res_gcc_pipe" = "yes"; then
_res="yes";
AC_MSG_CHECKING([for -pipe support])
if test -n "$GNU_CC" -a -n "$GNU_CXX"; then
dnl Any gcc that supports firefox supports -pipe.
CFLAGS="$CFLAGS -pipe"
CXXFLAGS="$CXXFLAGS -pipe"
else
_res="no"
fi
rm -f dummy-hello.c dummy-hello.s dummy-hello.S dummy-hello a.out
AC_MSG_RESULT([$_res])
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
@ -8224,6 +8178,18 @@ dnl ========================================================
MOZ_HARFBUZZ_LIBS='$(DEPTH)/gfx/harfbuzz/src/$(LIB_PREFIX)mozharfbuzz.$(LIB_SUFFIX)'
AC_SUBST(MOZ_HARFBUZZ_LIBS)
dnl ========================================================
dnl SIL Graphite
dnl ========================================================
if test "$MOZ_GRAPHITE"; then
MOZ_GRAPHITE_LIBS='$(DEPTH)/gfx/graphite2/src/$(LIB_PREFIX)mozgraphite2.$(LIB_SUFFIX)'
AC_DEFINE(MOZ_GRAPHITE)
else
MOZ_GRAPHITE_LIBS=
fi
AC_SUBST(MOZ_GRAPHITE)
AC_SUBST(MOZ_GRAPHITE_LIBS)
dnl ========================================================
dnl OTS
dnl ========================================================

View File

@ -297,7 +297,6 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
// The redirecting channel isn't a writable property bag, we won't be able
// to enforce the load policy if it redirects again, so we stop it now.
nsXPIDLString message;
nsCAutoString newUriSpec;
newUri->GetSpec(newUriSpec);
const PRUnichar *formatParams[] = { NS_ConvertUTF8toUTF16(newUriSpec).get() };

View File

@ -350,6 +350,7 @@ GK_ATOM(empty, "empty")
GK_ATOM(encoding, "encoding")
GK_ATOM(enctype, "enctype")
GK_ATOM(end, "end")
GK_ATOM(endEvent, "endEvent")
GK_ATOM(end_after, "end_after")
GK_ATOM(end_before, "end_before")
GK_ATOM(equalsize, "equalsize")
@ -1370,6 +1371,7 @@ GK_ATOM(attributeName, "attributeName")
GK_ATOM(attributeType, "attributeType")
GK_ATOM(auto_reverse, "auto-reverse")
GK_ATOM(begin, "begin")
GK_ATOM(beginEvent, "beginEvent")
GK_ATOM(by, "by")
GK_ATOM(calcMode, "calcMode")
GK_ATOM(css, "CSS")

View File

@ -176,8 +176,7 @@ public:
if (mState.mIs2b) {
aString.Append(m2b, mState.mLength);
} else {
AppendASCIItoUTF16(Substring(m1b, m1b + mState.mLength),
aString);
AppendASCIItoUTF16(Substring(m1b, mState.mLength), aString);
}
}
@ -190,7 +189,7 @@ public:
if (mState.mIs2b) {
aString.Append(m2b + aOffset, aLength);
} else {
AppendASCIItoUTF16(Substring(m1b + aOffset, m1b + aOffset + aLength), aString);
AppendASCIItoUTF16(Substring(m1b + aOffset, aLength), aString);
}
}

View File

@ -701,6 +701,25 @@ nsXMLHttpRequest::GetChannel(nsIChannel **aChannel)
return NS_OK;
}
static void LogMessage(const char* aWarning, nsPIDOMWindow* aWindow)
{
nsCOMPtr<nsIDocument> doc;
if (aWindow) {
doc = do_QueryInterface(aWindow->GetExtantDocument());
}
nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
aWarning,
nsnull,
0,
nsnull, // Response URL not kept around
EmptyString(),
0,
0,
nsIScriptError::warningFlag,
"DOM",
doc);
}
/* readonly attribute nsIDOMDocument responseXML; */
NS_IMETHODIMP
nsXMLHttpRequest::GetResponseXML(nsIDOMDocument **aResponseXML)
@ -717,31 +736,11 @@ nsXMLHttpRequest::GetResponseXML(nsIDOMDocument **aResponseXML)
}
if (mWarnAboutMultipartHtml) {
mWarnAboutMultipartHtml = false;
nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
"HTMLMultipartXHRWarning",
nsnull,
0,
nsnull, // Response URL not kept around
EmptyString(),
0,
0,
nsIScriptError::warningFlag,
"DOM",
mOwner->WindowID());
LogMessage("HTMLMultipartXHRWarning", mOwner);
}
if (mWarnAboutSyncHtml) {
mWarnAboutSyncHtml = false;
nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
"HTMLSyncXHRWarning",
nsnull,
0,
nsnull, // Response URL not kept around
EmptyString(),
0,
0,
nsIScriptError::warningFlag,
"DOM",
mOwner->WindowID());
LogMessage("HTMLSyncXHRWarning", mOwner);
}
return NS_OK;
}
@ -784,6 +783,13 @@ nsXMLHttpRequest::DetectCharset()
mResponseCharset.AssignLiteral("UTF-8");
}
if (mResponseType == XML_HTTP_RESPONSE_TYPE_JSON &&
!mResponseCharset.EqualsLiteral("UTF-8")) {
// The XHR spec says only UTF-8 is supported for responseType == "json"
LogMessage("JSONCharsetWarning", mOwner);
mResponseCharset.AssignLiteral("UTF-8");
}
nsCOMPtr<nsICharsetConverterManager> ccm =
do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
@ -921,7 +927,7 @@ nsXMLHttpRequest::CreateResponseParsedJSON(JSContext* aCx)
if (!aCx) {
return NS_ERROR_FAILURE;
}
// The Unicode converter has already zapped the BOM if there was one
if (!JS_ParseJSON(aCx,
(jschar*)mResponseText.get(),
mResponseText.Length(), &mResultJSON)) {
@ -974,7 +980,7 @@ NS_IMETHODIMP nsXMLHttpRequest::GetResponseType(nsAString& aResponseType)
aResponseType.AssignLiteral("text");
break;
case XML_HTTP_RESPONSE_TYPE_JSON:
aResponseType.AssignLiteral("moz-json");
aResponseType.AssignLiteral("json");
break;
case XML_HTTP_RESPONSE_TYPE_CHUNKED_TEXT:
aResponseType.AssignLiteral("moz-chunked-text");
@ -998,6 +1004,13 @@ NS_IMETHODIMP nsXMLHttpRequest::SetResponseType(const nsAString& aResponseType)
XML_HTTP_REQUEST_HEADERS_RECEIVED)))
return NS_ERROR_DOM_INVALID_STATE_ERR;
// sync request is not allowed setting responseType in window context
if (mOwner &&
!(mState & (XML_HTTP_REQUEST_UNSENT | XML_HTTP_REQUEST_ASYNC))) {
LogMessage("ResponseTypeSyncXHRWarning", mOwner);
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
}
// Set the responseType attribute's value to the given value.
if (aResponseType.IsEmpty()) {
mResponseType = XML_HTTP_RESPONSE_TYPE_DEFAULT;
@ -1009,7 +1022,7 @@ NS_IMETHODIMP nsXMLHttpRequest::SetResponseType(const nsAString& aResponseType)
mResponseType = XML_HTTP_RESPONSE_TYPE_DOCUMENT;
} else if (aResponseType.EqualsLiteral("text")) {
mResponseType = XML_HTTP_RESPONSE_TYPE_TEXT;
} else if (aResponseType.EqualsLiteral("moz-json")) {
} else if (aResponseType.EqualsLiteral("json")) {
mResponseType = XML_HTTP_RESPONSE_TYPE_JSON;
} else if (aResponseType.EqualsLiteral("moz-chunked-text")) {
if (!(mState & XML_HTTP_REQUEST_ASYNC)) {
@ -1098,9 +1111,15 @@ NS_IMETHODIMP nsXMLHttpRequest::GetResponse(JSContext *aCx, jsval *aResult)
if (mState & XML_HTTP_REQUEST_DONE) {
if (mResultJSON == JSVAL_VOID) {
rv = CreateResponseParsedJSON(aCx);
NS_ENSURE_SUCCESS(rv, rv);
mResponseText.Truncate();
if (NS_FAILED(rv)) {
// Per spec, errors aren't propagated. null is returned instead.
rv = NS_OK;
// It would be nice to log the error to the console. That's hard to
// do without calling window.onerror as a side effect, though.
JS_ClearPendingException(aCx);
mResultJSON = JSVAL_NULL;
}
}
*aResult = mResultJSON;
} else {
@ -1519,6 +1538,20 @@ nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
return NS_ERROR_INVALID_ARG;
}
// sync request is not allowed using withCredential or responseType
// in window context
if (!async && mOwner &&
(mState & XML_HTTP_REQUEST_AC_WITH_CREDENTIALS ||
mResponseType != XML_HTTP_RESPONSE_TYPE_DEFAULT)) {
if (mState & XML_HTTP_REQUEST_AC_WITH_CREDENTIALS) {
LogMessage("WithCredentialsSyncXHRWarning", mOwner);
}
if (mResponseType != XML_HTTP_RESPONSE_TYPE_DEFAULT) {
LogMessage("ResponseTypeSyncXHRWarning", mOwner);
}
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
}
nsresult rv;
nsCOMPtr<nsIURI> uri;
bool authp = false;
@ -2921,6 +2954,13 @@ nsXMLHttpRequest::SetWithCredentials(bool aWithCredentials)
return NS_ERROR_FAILURE;
}
// sync request is not allowed setting withCredentials in window context
if (mOwner &&
!(mState & (XML_HTTP_REQUEST_UNSENT | XML_HTTP_REQUEST_ASYNC))) {
LogMessage("WithCredentialsSyncXHRWarning", mOwner);
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
}
if (aWithCredentials) {
mState |= XML_HTTP_REQUEST_AC_WITH_CREDENTIALS;
}

View File

@ -533,6 +533,10 @@ _TEST_FILES2 = \
test_bug702439.html \
test_bug702439.html^headers^ \
file_bug702439.html \
test_bug707142.html \
file_bug707142_baseline.json \
file_bug707142_bom.json \
file_bug707142_utf-16.json \
$(NULL)
_CHROME_FILES = \

View File

@ -0,0 +1 @@
{"foo": "bar"}

View File

@ -0,0 +1 @@
{"foo": "bar"}

Binary file not shown.

View File

@ -5,15 +5,20 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<body onload="gen.next();">
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
<script class="testbody" type="application/javascript;version=1.7">
SimpleTest.waitForExplicitFinish();
var gen = runTests();
function continueTest() { gen.next(); }
function runTests() {
var path = "/tests/content/base/test/";
var passFiles = [['file_XHR_pass1.xml', 'GET'],
@ -63,7 +68,6 @@ for (i = 0; i < failFiles.length; ++i) {
}
}
// test response (responseType='document')
function checkResponseTextAccessThrows(xhr) {
var didthrow = false;
try { xhr.responseText } catch (e) { didthrow = true; }
@ -74,26 +78,42 @@ function checkResponseXMLAccessThrows(xhr) {
try { xhr.responseXML } catch (e) { didthrow = true; }
ok(didthrow, "should have thrown when accessing responseXML");
}
function checkResponseAccessThrows(xhr) {
var didthrow = false;
try { xhr.response } catch (e) { didthrow = true; }
ok(didthrow, "should have thrown when accessing response");
}
function checkSetResponseTypeThrows(xhr, type) {
var didthrow = false;
try { xhr.responseType = type; } catch (e) { didthrow = true; }
ok(didthrow, "should have thrown when setting responseType");
}
function checkOpenThrows(xhr, method, url, async) {
var didthrow = false;
try { xhr.open(method, url, async); } catch (e) { didthrow = true; }
ok(didthrow, "should have thrown when open is called");
}
// test response (sync, responseType is not changeable)
xhr = new XMLHttpRequest();
xhr.open("GET", 'file_XHR_pass2.txt', false);
checkSetResponseTypeThrows(xhr, "");
checkSetResponseTypeThrows(xhr, "text");
checkSetResponseTypeThrows(xhr, "document");
xhr.open("GET", 'file_XHR_pass1.xml', false);
checkSetResponseTypeThrows(xhr, "arraybuffer");
checkSetResponseTypeThrows(xhr, "blob");
checkSetResponseTypeThrows(xhr, "json");
checkSetResponseTypeThrows(xhr, "moz-chunked-text");
checkSetResponseTypeThrows(xhr, "moz-chunked-arraybuffer");
xhr.responseType = 'document';
xhr.send(null);
checkSetResponseTypeThrows(xhr, "document");
is(xhr.status, 200, "wrong status");
is(xhr.response, "hello pass\n", "wrong response");
// test response (responseType='document')
xhr = new XMLHttpRequest();
xhr.open("GET", 'file_XHR_pass1.xml');
xhr.responseType = 'document';
xhr.onloadend = continueTest;
xhr.send(null);
yield;
checkSetResponseTypeThrows(xhr, "document");
is(xhr.status, 200, "wrong status");
checkResponseTextAccessThrows(xhr);
is((new XMLSerializer()).serializeToString(xhr.response.documentElement),
"<res>hello</res>",
@ -101,9 +121,11 @@ is((new XMLSerializer()).serializeToString(xhr.response.documentElement),
// test response (responseType='text')
xhr = new XMLHttpRequest();
xhr.open("GET", 'file_XHR_pass2.txt', false);
xhr.open("GET", 'file_XHR_pass2.txt');
xhr.responseType = 'text';
xhr.onloadend = continueTest;
xhr.send(null);
yield;
is(xhr.status, 200, "wrong status");
checkResponseXMLAccessThrows(xhr);
is(xhr.response, "hello pass\n", "wrong response");
@ -118,9 +140,11 @@ function arraybuffer_equals_to(ab, s) {
// with a simple text file
xhr = new XMLHttpRequest();
xhr.open("GET", 'file_XHR_pass2.txt', false);
xhr.open("GET", 'file_XHR_pass2.txt');
xhr.responseType = 'arraybuffer';
xhr.onloadend = continueTest;
xhr.send(null);
yield;
is(xhr.status, 200, "wrong status");
checkResponseTextAccessThrows(xhr);
checkResponseXMLAccessThrows(xhr);
@ -129,9 +153,11 @@ ok(ab != null, "should have a non-null arraybuffer");
arraybuffer_equals_to(ab, "hello pass\n");
// test reusing the same XHR (Bug 680816)
xhr.open("GET", 'file_XHR_binary1.bin', false);
xhr.open("GET", 'file_XHR_binary1.bin');
xhr.responseType = 'arraybuffer';
xhr.onloadend = continueTest;
xhr.send(null);
yield;
is(xhr.status, 200, "wrong status");
ab2 = xhr.response;
ok(ab2 != null, "should have a non-null arraybuffer");
@ -141,9 +167,11 @@ arraybuffer_equals_to(ab2, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb");
// with a binary file
xhr = new XMLHttpRequest();
xhr.open("GET", 'file_XHR_binary1.bin', false);
xhr.open("GET", 'file_XHR_binary1.bin');
xhr.responseType = 'arraybuffer';
xhr.send(null)
xhr.onloadend = continueTest;
xhr.send(null);
yield;
is(xhr.status, 200, "wrong status");
checkResponseTextAccessThrows(xhr);
checkResponseXMLAccessThrows(xhr);
@ -152,12 +180,14 @@ ok(ab != null, "should have a non-null arraybuffer");
arraybuffer_equals_to(ab, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb");
is(xhr.response, xhr.response, "returns the same ArrayBuffer");
// test response (responseType='moz-json')
// test response (responseType='json')
var xhr = new XMLHttpRequest();
xhr.open("POST", 'responseIdentical.sjs', false);
xhr.responseType = 'moz-json';
xhr.open("POST", 'responseIdentical.sjs');
xhr.responseType = 'json';
jsonObjStr = JSON.stringify({title: "aBook", author: "john"});
xhr.onloadend = continueTest;
xhr.send(jsonObjStr);
yield;
is(xhr.status, 200, "wrong status");
checkResponseTextAccessThrows(xhr);
checkResponseXMLAccessThrows(xhr);
@ -166,14 +196,16 @@ is(xhr.response, xhr.response, "returning the same object on each access");
// with invalid json
var xhr = new XMLHttpRequest();
xhr.open("POST", 'responseIdentical.sjs', false);
xhr.responseType = 'moz-json';
xhr.open("POST", 'responseIdentical.sjs');
xhr.responseType = 'json';
xhr.onloadend = continueTest;
xhr.send("{");
yield;
is(xhr.status, 200, "wrong status");
checkResponseTextAccessThrows(xhr);
checkResponseXMLAccessThrows(xhr);
checkResponseAccessThrows(xhr);
checkResponseAccessThrows(xhr); // Check twice to ensure that we still throw
is(xhr.response, null, "Bad JSON should result in null response.");
is(xhr.response, null, "Bad JSON should result in null response even 2nd time.");
// test response (responseType='blob')
var onloadCount = 0;
@ -183,9 +215,11 @@ function checkOnloadCount() {
// with a simple text file
xhr = new XMLHttpRequest();
xhr.open("GET", 'file_XHR_pass2.txt', false);
xhr.open("GET", 'file_XHR_pass2.txt');
xhr.responseType = 'blob';
xhr.onloadend = continueTest;
xhr.send(null);
yield;
is(xhr.status, 200, "wrong status");
checkResponseTextAccessThrows(xhr);
checkResponseXMLAccessThrows(xhr);
@ -281,6 +315,8 @@ client.open("GET", "file_XHR_pass1.xml", true);
client.send();
client.abort();
yield;
} /* runTests */
</script>
</pre>
</body>

View File

@ -8,7 +8,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=464848
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<body onload="gen.next();">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=464848">Mozilla Bug 464848</a>
<p id="display">
@ -19,6 +19,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=464848
</div>
<pre id="test">
<script class="testbody" type="application/javascript;version=1.8">
SimpleTest.waitForExplicitFinish();
var gen = runTests();
function continueTest() { gen.next(); }
function runTests() {
xhr = new XMLHttpRequest();
xhr.open("GET", "file_XHRSendData_doc.xml", false);
@ -176,12 +182,16 @@ for (var i = 0; i < testDOMFiles.length; i++) {
try {
for each(test in tests) {
xhr = new XMLHttpRequest;
xhr.open("POST", "file_XHRSendData.sjs", false);
xhr.open("POST", "file_XHRSendData.sjs", !!test.resType);
if (test.contentType)
xhr.setRequestHeader("Content-Type", test.contentType);
if (test.resType)
if (test.resType) {
xhr.responseType = test.resType;
xhr.onloadend = continueTest;
}
xhr.send(test.body);
if (test.resType)
yield;
if (test.resContentType) {
is(xhr.getResponseHeader("Result-Content-Type"), test.resContentType,
@ -234,6 +244,10 @@ function is_identical_arraybuffer(ab1, ab2) {
String.fromCharCode.apply(String, u8v2), "arraybuffer values not equal");
}
SimpleTest.finish();
yield;
} /* runTests */
</script>
</pre>
</body>

View File

@ -424,8 +424,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
var xhr = SpecialPowers.createSystemXHR();
xhr.withCredentials = true;
// also, test mixed mode UI
xhr.open("GET", "https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_xhr", false, "user 1", "password 1");
xhr.open("GET", "https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_xhr", true, "user 1", "password 1");
xhr.send();
xhr.onloadend = function() {
ok(xhr.status == 200, "Failed to set credentials in test 5.c");
gEventSourceObj5_c = new EventSource("https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_evtsrc",
@ -444,14 +445,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
gEventSourceObj5_c.close();
doTest5_d(test_id);
}, parseInt(3000*stress_factor));
};
}
function doTest5_d(test_id)
{
var xhr = SpecialPowers.createSystemXHR();
xhr.withCredentials = true;
xhr.open("GET", "https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_xhr", false, "user 2", "password 2");
xhr.open("GET", "https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_xhr", true, "user 2", "password 2");
xhr.send();
xhr.onloadend = function() {
ok(xhr.status == 200, "Failed to set credentials in test 5.d");
gEventSourceObj5_d = new EventSource("https://example.com/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_evtsrc");
@ -469,6 +472,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
gEventSourceObj5_d.close();
setTestHasFinished(test_id);
}, parseInt(3000*stress_factor));
};
}
function doTest5_e(test_id)
@ -476,8 +480,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
// credentials using the auth cache and cookies
var xhr = SpecialPowers.createSystemXHR();
xhr.withCredentials = true;
xhr.open("GET", "http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_xhr", false, "user 1", "password 1");
xhr.open("GET", "http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_xhr", true, "user 1", "password 1");
xhr.send();
xhr.onloadend = function() {
ok(xhr.status == 200, "Failed to set credentials in test 5.e");
gEventSourceObj5_e = new EventSource("http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user1_evtsrc",
@ -496,14 +501,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
gEventSourceObj5_e.close();
doTest5_f(test_id);
}, parseInt(5000*stress_factor));
};
}
function doTest5_f(test_id)
{
var xhr = SpecialPowers.createSystemXHR();
xhr.withCredentials = true;
xhr.open("GET", "http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_xhr", false, "user 2", "password 2");
xhr.open("GET", "http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_xhr", true, "user 2", "password 2");
xhr.send();
xhr.onloadend = function() {
ok(xhr.status == 200, "Failed to set credentials in test 5.f");
gEventSourceObj5_f = new EventSource("http://example.org/tests/content/base/test/file_restrictedEventSource.sjs?test=user2_evtsrc",
@ -522,6 +529,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
gEventSourceObj5_f.close();
setTestHasFinished(test_id);
}, parseInt(3000*stress_factor));
};
}
function doTest6(test_id)

View File

@ -86,13 +86,13 @@ function onWindowLoad() {
ok(document.iframeWasLoaded, "Loading resource via src-attribute");
for each (test in alltests) {
function runTest(test) {
var xhr = new XMLHttpRequest();
var method = "GET";
if (test.method != null) { method = test.method; }
xhr.open(method, test.url, false);
xhr.open(method, test.url);
xhr.withCredentials = test.withCredentials;
@ -104,11 +104,20 @@ function onWindowLoad() {
xhr.send();
} catch(e) {
}
xhr.onloadend = function() {
var success = eval(xhr.status + test.status_check);
ok(success, test.error);
if (alltests.length == 0) {
SimpleTest.finish();
} else {
runTest(alltests.shift());
}
};
}
SimpleTest.finish();
runTest(alltests.shift());
}
SimpleTest.waitForExplicitFinish();

View File

@ -0,0 +1,51 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=707142
-->
<head>
<title>Test for Bug 707142</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=707142">Mozilla Bug 707142</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 707142 **/
SimpleTest.waitForExplicitFinish();
var xhr = new XMLHttpRequest();
xhr.onload = function() {
is(xhr.response["foo"], "bar", "Should have gotten bar on baseline");
xhr.onload = function() {
is(xhr.response["foo"], "bar", "Should have gotten bar with BOM");
xhr.onload = function() {
is(xhr.response, null, "Should have gotten null response with UTF-16 JSON");
SimpleTest.finish();
};
xhr.open("GET", "file_bug707142_utf-16.json");
xhr.responseType = "json";
xhr.send();
};
xhr.open("GET", "file_bug707142_bom.json");
xhr.responseType = "json";
xhr.send();
};
xhr.open("GET", "file_bug707142_baseline.json");
xhr.responseType = "json";
xhr.send();
</script>
</pre>
</body>
</html>

View File

@ -115,7 +115,7 @@ function runTests() {
{ type: "arraybuffer", text: false, nodata: true },
{ type: "blob", text: false, nodata: true },
{ type: "document", text: true, nodata: true },
{ type: "moz-json", text: true, nodata: true },
{ type: "json", text: true, nodata: true },
{ type: "", text: true },
{ type: "moz-chunked-text", text: true, chunked: true },
{ type: "moz-chunked-arraybuffer", text: false, chunked: true },

View File

@ -0,0 +1,21 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Test setting .responseType and .withCredentials is allowed
// in non-window non-Worker context
function run_test()
{
var xhr = Components.classes['@mozilla.org/xmlextras/xmlhttprequest;1'].
createInstance(Components.interfaces.nsIXMLHttpRequest);
xhr.open('GET', 'data:,', false);
var exceptionThrown = false;
try {
xhr.responseType = '';
xhr.withCredentials = false;
} catch (e) {
exceptionThrown = true;
}
do_check_eq(false, exceptionThrown);
}

View File

@ -7,4 +7,5 @@ tail =
[test_csputils.js]
[test_error_codes.js]
[test_thirdpartyutil.js]
[test_xhr_standalone.js]
[test_xmlserializer.js]

View File

@ -2771,7 +2771,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessor : public nsBidiPresUtils::BidiProces
virtual void DrawText(nscoord xOffset, nscoord width)
{
gfxPoint point = mPt;
point.x += xOffset * mAppUnitsPerDevPixel;
point.x += xOffset;
// offset is given in terms of left side of string
if (mTextRun->IsRightToLeft()) {

View File

@ -1915,15 +1915,11 @@ nsCanvasRenderingContext2DAzure::CreatePattern(nsIDOMHTMLElement *image,
if (size.width == 0 || size.height == 0) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
}
// Special case for Canvas, which could be an Azure canvas!
if (canvas) {
if (canvas->CountContexts() == 1) {
nsICanvasRenderingContextInternal *srcCanvas = canvas->GetContextAtIndex(0);
// This might not be an Azure canvas!
if (srcCanvas) {
// This might not be an Azure canvas!
RefPtr<SourceSurface> srcSurf = srcCanvas->GetSurfaceSnapshot();
nsRefPtr<nsCanvasPatternAzure> pat =
@ -1933,7 +1929,6 @@ nsCanvasRenderingContext2DAzure::CreatePattern(nsIDOMHTMLElement *image,
return NS_OK;
}
}
}
// The canvas spec says that createPattern should use the first frame
// of animated images
@ -2975,7 +2970,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP
virtual void DrawText(nscoord xOffset, nscoord width)
{
gfxPoint point = mPt;
point.x += xOffset * mAppUnitsPerDevPixel;
point.x += xOffset;
// offset is given in terms of left side of string
if (mTextRun->IsRightToLeft()) {
@ -3591,38 +3586,24 @@ nsCanvasRenderingContext2DAzure::DrawImage(nsIDOMElement *imgElt, float a1,
double sx,sy,sw,sh;
double dx,dy,dw,dh;
RefPtr<SourceSurface> srcSurf;
gfxIntSize imgSize;
nsHTMLCanvasElement* canvas = nsHTMLCanvasElement::FromContent(content);
if (canvas) {
nsIntSize size = canvas->GetSize();
if (size.width == 0 || size.height == 0) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
}
RefPtr<SourceSurface> srcSurf;
gfxIntSize imgSize;
nsRefPtr<gfxASurface> imgsurf =
CanvasImageCache::Lookup(imgElt, HTMLCanvasElement(), &imgSize);
if (imgsurf) {
srcSurf = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mTarget, imgsurf);
}
// We know an Azure canvas always has an HTMLCanvasElement!
if (canvas == HTMLCanvasElement()) {
// Special case for Canvas, which could be an Azure canvas!
nsICanvasRenderingContextInternal *srcCanvas = canvas->GetContextAtIndex(0);
if (srcCanvas == this) {
// Self-copy.
srcSurf = mTarget->Snapshot();
imgSize = gfxIntSize(mWidth, mHeight);
}
// Special case for Canvas, which could be an Azure canvas!
if (canvas) {
if (canvas->CountContexts() == 1) {
nsICanvasRenderingContextInternal *srcCanvas = canvas->GetContextAtIndex(0);
} else if (srcCanvas) {
// This might not be an Azure canvas!
if (srcCanvas) {
srcSurf = srcCanvas->GetSurfaceSnapshot();
if (srcSurf && mCanvasElement) {
@ -3630,10 +3611,14 @@ nsCanvasRenderingContext2DAzure::DrawImage(nsIDOMElement *imgElt, float a1,
CanvasUtils::DoDrawImageSecurityCheck(HTMLCanvasElement(),
content->NodePrincipal(), canvas->IsWriteOnly(),
false);
imgSize = gfxIntSize(srcSurf->GetSize().width, srcSurf->GetSize().height);
}
}
} else {
gfxASurface* imgsurf =
CanvasImageCache::Lookup(imgElt, HTMLCanvasElement(), &imgSize);
if (imgsurf) {
srcSurf = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mTarget, imgsurf);
}
}
@ -3654,7 +3639,6 @@ nsCanvasRenderingContext2DAzure::DrawImage(nsIDOMElement *imgElt, float a1,
return NS_OK;
}
imgsurf = res.mSurface.forget();
imgSize = res.mSize;
if (mCanvasElement) {
@ -3665,10 +3649,10 @@ nsCanvasRenderingContext2DAzure::DrawImage(nsIDOMElement *imgElt, float a1,
if (res.mImageRequest) {
CanvasImageCache::NotifyDrawImage(imgElt, HTMLCanvasElement(),
res.mImageRequest, imgsurf, imgSize);
res.mImageRequest, res.mSurface, imgSize);
}
srcSurf = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mTarget, imgsurf);
srcSurf = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mTarget, res.mSurface);
}
if (optional_argc == 0) {

View File

@ -135,6 +135,7 @@
#include "mozilla/Preferences.h"
#include "mozilla/LookAndFeel.h"
#include "sampler.h"
#ifdef XP_MACOSX
#import <ApplicationServices/ApplicationServices.h>
@ -3808,6 +3809,7 @@ nsEventStateManager::DispatchMouseEvent(nsGUIEvent* aEvent, PRUint32 aMessage,
nsIContent* aTargetContent,
nsIContent* aRelatedContent)
{
SAMPLE_LABEL("Input", "DispatchMouseEvent");
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(NS_IS_TRUSTED_EVENT(aEvent), aMessage, aEvent->widget,
nsMouseEvent::eReal);

View File

@ -50,9 +50,12 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMStringMap)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMStringMap)
// Check that mElement exists in case the unlink code is run more than once.
if (tmp->mElement) {
// Call back to element to null out weak reference to this object.
tmp->mElement->ClearDataset();
tmp->mElement = nsnull;
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMStringMap)

View File

@ -1976,8 +1976,8 @@ nsresult nsHTMLMediaElement::FinishDecoderSetup(nsMediaDecoder* aDecoder)
nsCAutoString src;
GetCurrentSpec(src);
printf("*** nsHTMLElement::FinishDecoderSetup() mDecoder=%p src=%s\n",
aDecoder, src.get());
printf("*** nsHTMLElement::FinishDecoderSetup() mDecoder=%p stream=%p src=%s\n",
aDecoder, aDecoder->GetStream(), src.get());
mDecoder = aDecoder;
AddMediaElementToURITable();

View File

@ -49,7 +49,14 @@ var gTestWindows = [
var testWindow = null;
var gTestIndex = 0;
const isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1;
function nextTest() {
if (isWinXP) {
todo(false, "Can't reliably run full-screen tests on Windows XP due to bug 704010");
SimpleTest.finish();
return;
}
if (testWindow) {
testWindow.close();
}

View File

@ -644,8 +644,10 @@ void nsBuiltinDecoder::NotifySuspendedStatusChanged()
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
if (!mStream)
return;
bool suspended = mStream->IsSuspendedByCache();
printf("*** nsBuiltinDecoder::NotifySuspendedStatusChanged(%p), suspended=%d\n", this, suspended);
nsMediaStream* activeStream;
bool suspended = mStream->IsSuspendedByCache(&activeStream);
printf("*** nsBuiltinDecoder::NotifySuspendedStatusChanged(%p), suspended=%d, active-stream=%p\n", this, suspended, activeStream);
if (suspended && mElement) {
// if this is an autoplay element, we need to kick off its autoplaying
// now so we consume data and hopefully free up cache space

View File

@ -1908,14 +1908,21 @@ nsMediaCacheStream::IsSeekable()
}
bool
nsMediaCacheStream::AreAllStreamsForResourceSuspended()
nsMediaCacheStream::AreAllStreamsForResourceSuspended(nsMediaStream** aActiveStream)
{
ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
nsMediaCache::ResourceStreamIterator iter(mResourceID);
while (nsMediaCacheStream* stream = iter.Next()) {
if (!stream->mCacheSuspended && !stream->mChannelEnded)
if (!stream->mCacheSuspended && !stream->mChannelEnded) {
if (aActiveStream) {
*aActiveStream = stream->mClient;
}
return false;
}
}
if (aActiveStream) {
*aActiveStream = nsnull;
}
return true;
}

View File

@ -43,7 +43,9 @@
#include "nsIPrincipal.h"
#include "nsCOMPtr.h"
class nsMediaStream;
class nsByteRange;
namespace mozilla {
class ReentrantMonitorAutoEnter;
}
@ -354,7 +356,9 @@ public:
// Returns true when all streams for this resource are suspended or their
// channel has ended.
bool AreAllStreamsForResourceSuspended();
// If aActiveStream is non-null, fills it with a pointer to a stream
// for this resource that is not suspended or ended.
bool AreAllStreamsForResourceSuspended(nsMediaStream** aActiveStream);
// These methods must be called on a different thread from the main
// thread. They should always be called on the same thread for a given

View File

@ -831,9 +831,9 @@ nsMediaChannelStream::EnsureCacheUpToDate()
}
bool
nsMediaChannelStream::IsSuspendedByCache()
nsMediaChannelStream::IsSuspendedByCache(nsMediaStream** aActiveStream)
{
return mCacheStream.AreAllStreamsForResourceSuspended();
return mCacheStream.AreAllStreamsForResourceSuspended(aActiveStream);
}
bool
@ -949,7 +949,13 @@ public:
}
virtual PRInt64 GetCachedDataEnd(PRInt64 aOffset) { return NS_MAX(aOffset, mSize); }
virtual bool IsDataCachedToEndOfStream(PRInt64 aOffset) { return true; }
virtual bool IsSuspendedByCache() { return false; }
virtual bool IsSuspendedByCache(nsMediaStream** aActiveStream)
{
if (aActiveStream) {
*aActiveStream = nsnull;
}
return false;
}
virtual bool IsSuspended() { return false; }
nsresult GetCachedRanges(nsTArray<nsByteRange>& aRanges);

View File

@ -272,7 +272,9 @@ public:
// changes.
// For resources using the media cache, this returns true only when all
// streams for the same resource are all suspended.
virtual bool IsSuspendedByCache() = 0;
// If aActiveStream is non-null, fills it with a pointer to a stream
// for this resource that is not suspended or ended.
virtual bool IsSuspendedByCache(nsMediaStream** aActiveStream) = 0;
// Returns true if this stream has been suspended.
virtual bool IsSuspended() = 0;
// Reads only data which is cached in the media cache. If you try to read
@ -404,7 +406,7 @@ public:
virtual PRInt64 GetNextCachedData(PRInt64 aOffset);
virtual PRInt64 GetCachedDataEnd(PRInt64 aOffset);
virtual bool IsDataCachedToEndOfStream(PRInt64 aOffset);
virtual bool IsSuspendedByCache();
virtual bool IsSuspendedByCache(nsMediaStream** aActiveStream);
virtual bool IsSuspended();
class Listener : public nsIStreamListener,

View File

@ -39,13 +39,18 @@
#if !defined(nsWebMReader_h_)
#define nsWebMReader_h_
#include "mozilla/StdInt.h"
#include "nsDeque.h"
#include "nsBuiltinDecoderReader.h"
#include "nsWebMBufferedParser.h"
#include "nsAutoRef.h"
#include "nestegg/nestegg.h"
#define VPX_DONT_DEFINE_STDINT_TYPES
#include "vpx/vpx_decoder.h"
#include "vpx/vp8dx.h"
#ifdef MOZ_TREMOR
#include "tremor/ivorbiscodec.h"
#else

View File

@ -322,6 +322,28 @@ nsSMILTimeValueSpec::GetTimedElement(Element* aElement)
return &animElement->TimedElement();
}
// Indicates whether we're allowed to register an event-listener
// when scripting is disabled.
bool
nsSMILTimeValueSpec::IsWhitelistedEvent()
{
// The category of (SMIL-specific) "repeat(n)" events are allowed.
if (mParams.mType == nsSMILTimeValueSpecParams::REPEAT) {
return true;
}
// A specific list of other SMIL-related events are allowed, too.
if (mParams.mType == nsSMILTimeValueSpecParams::EVENT &&
(mParams.mEventSymbol == nsGkAtoms::repeat ||
mParams.mEventSymbol == nsGkAtoms::repeatEvent ||
mParams.mEventSymbol == nsGkAtoms::beginEvent ||
mParams.mEventSymbol == nsGkAtoms::endEvent)) {
return true;
}
return false;
}
void
nsSMILTimeValueSpec::RegisterEventListener(Element* aTarget)
{
@ -334,10 +356,11 @@ nsSMILTimeValueSpec::RegisterEventListener(Element* aTarget)
if (!aTarget)
return;
// Don't listen for accessKey events if script is disabled. (see bug 704482)
if (mParams.mType == nsSMILTimeValueSpecParams::ACCESSKEY &&
!aTarget->GetOwnerDocument()->IsScriptEnabled())
// When script is disabled, only allow registration for whitelisted events.
if (!aTarget->GetOwnerDocument()->IsScriptEnabled() &&
!IsWhitelistedEvent()) {
return;
}
if (!mEventListener) {
mEventListener = new EventListener(this);

View File

@ -93,6 +93,7 @@ protected:
void UpdateReferencedElement(Element* aFrom, Element* aTo);
void UnregisterFromReferencedElement(Element* aElement);
nsSMILTimedElement* GetTimedElement(Element* aElement);
bool IsWhitelistedEvent();
void RegisterEventListener(Element* aElement);
void UnregisterEventListener(Element* aElement);
nsEventListenerManager* GetEventListenerManager(Element* aElement);

Some files were not shown because too many files have changed in this diff Show More