Merge mozilla-central into build-system

This commit is contained in:
Gregory Szorc 2013-03-02 17:42:20 -08:00
commit 98868fc43b
468 changed files with 6543 additions and 3656 deletions

View File

@ -28,15 +28,19 @@ SHARED_LIBRARY_LIBS = \
../src/generic/$(LIB_PREFIX)accessibility_generic_s.$(LIB_SUFFIX) \
../src/html/$(LIB_PREFIX)accessibility_html_s.$(LIB_SUFFIX) \
../src/xpcom/$(LIB_PREFIX)accessibility_xpcom_s.$(LIB_SUFFIX) \
../src/$(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX) \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
SHARED_LIBRARY_LIBS += \
../src/windows/msaa/$(LIB_PREFIX)accessibility_toolkit_msaa_s.$(LIB_SUFFIX) \
../src/windows/ia2/$(LIB_PREFIX)accessibility_toolkit_ia2_s.$(LIB_SUFFIX) \
../src/windows/sdn/$(LIB_PREFIX)accessibility_toolkit_sdn_s.$(LIB_SUFFIX) \
../src/windows/uia/$(LIB_PREFIX)accessibility_toolkit_uia_s.$(LIB_SUFFIX) \
$(NULL)
else
SHARED_LIBRARY_LIBS += \
../src/$(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX) \
$(NULL)
endif
ifdef MOZ_XUL

View File

@ -52,6 +52,7 @@ enum AccType {
eMenuPopupType,
eProgressType,
eRootType,
eXULLabelType,
eXULTabpanelsType,
eXULTreeType,

View File

@ -65,7 +65,7 @@ EnableLogging(const char* aModulesStr)
size_t tokenLen = strcspn(token, ",");
for (unsigned int idx = 0; idx < ArrayLength(sModuleMap); idx++) {
if (strncmp(token, sModuleMap[idx].mStr, tokenLen) == 0) {
#if !defined(MOZ_PROFILING) && (!defined(MOZ_DEBUG) || defined(MOZ_OPTIMIZE))
#if !defined(MOZ_PROFILING) && (!defined(DEBUG) || defined(MOZ_OPTIMIZE))
// Stack tracing on profiling enabled or debug not optimized builds.
if (strncmp(token, "stack", tokenLen) == 0)
break;

View File

@ -94,7 +94,7 @@ LOCAL_INCLUDES += \
else
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
LOCAL_INCLUDES += \
-I$(srcdir)/../msaa \
-I$(srcdir)/../windows/msaa \
-I$(srcdir)/../windows/ia2 \
$(NULL)
else

View File

@ -402,6 +402,24 @@ nsAccessibilityService::UpdateImageMap(nsImageFrame* aImageFrame)
}
}
void
nsAccessibilityService::UpdateLabelValue(nsIPresShell* aPresShell,
nsIContent* aLabelElm,
const nsString& aNewValue)
{
DocAccessible* document = GetDocAccessible(aPresShell);
if (document) {
Accessible* accessible = document->GetAccessible(aLabelElm);
if (accessible) {
XULLabelAccessible* xulLabel = accessible->AsXULLabel();
NS_ASSERTION(xulLabel,
"UpdateLabelValue was called for wrong accessible!");
if (xulLabel)
xulLabel->UpdateLabelValue(aNewValue);
}
}
}
void
nsAccessibilityService::PresShellActivated(nsIPresShell* aPresShell)
{

View File

@ -104,6 +104,12 @@ public:
*/
void UpdateImageMap(nsImageFrame* aImageFrame);
/**
* Update the label accessible tree when rendered @value is changed.
*/
void UpdateLabelValue(nsIPresShell* aPresShell, nsIContent* aLabelElm,
const nsString& aNewValue);
/**
* Notify accessibility that anchor jump has been accomplished to the given
* target. Used by layout.

View File

@ -46,6 +46,7 @@ class Relation;
class TableAccessible;
class TableCellAccessible;
class TextLeafAccessible;
class XULLabelAccessible;
class XULTreeAccessible;
/**
@ -523,6 +524,9 @@ public:
bool IsTextLeaf() const { return mType == eTextLeafType; }
TextLeafAccessible* AsTextLeaf();
bool IsXULLabel() const { return mType == eXULLabelType; }
XULLabelAccessible* AsXULLabel();
bool IsXULTabpanels() const { return mType == eXULTabpanelsType; }
bool IsXULTree() const { return mType == eXULTreeType; }
@ -892,7 +896,7 @@ protected:
static const uint8_t kChildrenFlagsBits = 2;
static const uint8_t kStateFlagsBits = 5;
static const uint8_t kTypeBits = 5;
static const uint8_t kTypeBits = 6;
static const uint8_t kGenericTypesBits = 12;
/**

View File

@ -60,7 +60,7 @@ LOCAL_INCLUDES += \
else
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
LOCAL_INCLUDES += \
-I$(srcdir)/../msaa \
-I$(srcdir)/../windows/msaa \
$(NULL)
else
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)

View File

@ -50,7 +50,7 @@ LOCAL_INCLUDES += \
else
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
LOCAL_INCLUDES += \
-I$(srcdir)/../msaa \
-I$(srcdir)/../windows/msaa \
-I$(srcdir)/../windows/ia2 \
$(NULL)
else

View File

@ -8,7 +8,7 @@ toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
if toolkit == 'gtk2':
DIRS += ['atk']
elif toolkit == 'windows':
DIRS += ['msaa', 'windows']
DIRS += ['windows']
elif toolkit == 'cocoa':
DIRS += ['mac']
else:

View File

@ -51,10 +51,10 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES += \
-I$(srcdir) \
-I$(srcdir)/../msaa \
-I$(srcdir)/../../base \
-I$(srcdir)/../../generic \
-I$(srcdir)/../../html \
-I$(srcdir)/../../msaa \
-I$(srcdir)/../../xpcom \
-I$(srcdir)/../../xul \
$(NULL)

View File

@ -3,5 +3,5 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DIRS += ['ia2', 'sdn', 'uia']
DIRS += ['msaa', 'ia2', 'sdn', 'uia']

View File

@ -10,8 +10,8 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = accessibility
LIBRARY_NAME = accessibility_toolkit_s
EXPORT_LIBRARY = ..
LIBRARY_NAME = accessibility_toolkit_msaa_s
EXPORT_LIBRARY = 1
LIBXUL_LIBRARY = 1
@ -63,16 +63,16 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES += \
-I$(srcdir) \
-I$(srcdir)/../base \
-I$(srcdir)/../generic \
-I$(srcdir)/../html \
-I$(srcdir)/../xpcom \
-I$(srcdir)/../xul \
-I$(srcdir)/../windows/ia2 \
-I$(srcdir)/../windows/sdn \
-I$(srcdir)/../windows/uia \
-I$(srcdir)/../../../content/base/src \
-I$(srcdir)/../../../content/events/src \
-I$(srcdir)/../../base \
-I$(srcdir)/../../generic \
-I$(srcdir)/../../html \
-I$(srcdir)/../../xpcom \
-I$(srcdir)/../../xul \
-I$(srcdir)/../ia2 \
-I$(srcdir)/../sdn \
-I$(srcdir)/../uia \
-I$(srcdir)/../../../../content/base/src \
-I$(srcdir)/../../../../content/events/src \
$(NULL)
ifneq ($(A11Y_LOG),0)

View File

@ -29,10 +29,10 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES += \
-I$(srcdir) \
-I$(srcdir)/../msaa \
-I$(srcdir)/../../base \
-I$(srcdir)/../../generic \
-I$(srcdir)/../../html \
-I$(srcdir)/../../msaa \
-I$(srcdir)/../../xpcom \
-I$(srcdir)/../../xul \
$(NULL)

View File

@ -30,10 +30,10 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES += \
-I$(srcdir) \
-I$(srcdir)/../msaa \
-I$(srcdir)/../../base \
-I$(srcdir)/../../generic \
-I$(srcdir)/../../html \
-I$(srcdir)/../../msaa \
-I$(srcdir)/../../xpcom \
-I$(srcdir)/../../xul \
$(NULL)

View File

@ -38,7 +38,7 @@ LOCAL_INCLUDES += \
else
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
LOCAL_INCLUDES += \
-I$(srcdir)/../msaa \
-I$(srcdir)/../windows/msaa \
$(NULL)
else
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)

View File

@ -53,7 +53,7 @@ LOCAL_INCLUDES += \
else
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
LOCAL_INCLUDES += \
-I$(srcdir)/../msaa \
-I$(srcdir)/../windows/msaa \
-I$(srcdir)/../windows/ia2 \
$(NULL)
else

View File

@ -7,18 +7,25 @@
#include "Accessible-inl.h"
#include "BaseAccessibles.h"
#include "DocAccessible-inl.h"
#include "nsAccUtils.h"
#include "nsCoreUtils.h"
#include "nsTextEquivUtils.h"
#include "Relation.h"
#include "Role.h"
#include "States.h"
#include "TextUpdater.h"
#ifdef A11Y_LOG
#include "Logging.h"
#endif
#include "nsIAccessibleRelation.h"
#include "nsIDOMXULDescriptionElement.h"
#include "nsINameSpaceManager.h"
#include "nsString.h"
#include "nsNetUtil.h"
#include "nsString.h"
#include "nsTextBoxFrame.h"
using namespace mozilla::a11y;
@ -30,6 +37,31 @@ XULLabelAccessible::
XULLabelAccessible(nsIContent* aContent, DocAccessible* aDoc) :
HyperTextAccessibleWrap(aContent, aDoc)
{
mType = eXULLabelType;
// If @value attribute is given then it's rendered instead text content. In
// this case we need to create a text leaf accessible to make @value attribute
// accessible.
// XXX: text interface doesn't let you get the text by words.
nsTextBoxFrame* textBoxFrame = do_QueryFrame(mContent->GetPrimaryFrame());
if (textBoxFrame) {
mValueTextLeaf = new XULLabelTextLeafAccessible(mContent, mDoc);
if (mDoc->BindToDocument(mValueTextLeaf, nullptr)) {
nsAutoString text;
textBoxFrame->GetCroppedTitle(text);
mValueTextLeaf->SetText(text);
return;
}
mValueTextLeaf = nullptr;
}
}
void
XULLabelAccessible::Shutdown()
{
mValueTextLeaf = nullptr;
HyperTextAccessibleWrap::Shutdown();
}
ENameValueFlag
@ -37,7 +69,9 @@ XULLabelAccessible::NativeName(nsString& aName)
{
// if the value attr doesn't exist, the screen reader must get the accessible text
// from the accessible text interface or from the children
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName);
if (mValueTextLeaf)
return mValueTextLeaf->Name(aName);
return eNameOK;
}
@ -72,6 +106,53 @@ XULLabelAccessible::RelationByType(uint32_t aType)
return rel;
}
void
XULLabelAccessible::UpdateLabelValue(const nsString& aValue)
{
#ifdef A11Y_LOG
if (logging::IsEnabled(logging::eText)) {
logging::MsgBegin("TEXT", "text may be changed (xul:label @value update)");
logging::Node("container", mContent);
logging::MsgEntry("old text '%s'",
NS_ConvertUTF16toUTF8(mValueTextLeaf->Text()).get());
logging::MsgEntry("new text: '%s'",
NS_ConvertUTF16toUTF8(aValue).get());
logging::MsgEnd();
}
#endif
TextUpdater::Run(mDoc, mValueTextLeaf, aValue);
}
void
XULLabelAccessible::CacheChildren()
{
if (mValueTextLeaf) {
AppendChild(mValueTextLeaf);
return;
}
// Cache children from subtree.
AccessibleWrap::CacheChildren();
}
////////////////////////////////////////////////////////////////////////////////
// XULLabelTextLeafAccessible
////////////////////////////////////////////////////////////////////////////////
role
XULLabelTextLeafAccessible::NativeRole()
{
return roles::TEXT_LEAF;
}
uint64_t
XULLabelTextLeafAccessible::NativeState()
{
return TextLeafAccessibleWrap::NativeState() | states::READONLY;
}
////////////////////////////////////////////////////////////////////////////////
// XULTooltipAccessible

View File

@ -6,12 +6,14 @@
#ifndef mozilla_a11y_XULElementAccessibles_h__
#define mozilla_a11y_XULElementAccessibles_h__
#include "BaseAccessibles.h"
#include "HyperTextAccessibleWrap.h"
#include "TextLeafAccessibleWrap.h"
namespace mozilla {
namespace a11y {
class XULLabelTextLeafAccessible;
/**
* Used for XUL description and label elements.
*/
@ -21,15 +23,48 @@ public:
XULLabelAccessible(nsIContent* aContent, DocAccessible* aDoc);
// Accessible
virtual void Shutdown();
virtual a11y::role NativeRole();
virtual uint64_t NativeState();
virtual Relation RelationByType(uint32_t aRelationType);
void UpdateLabelValue(const nsString& aValue);
protected:
// Accessible
virtual ENameValueFlag NativeName(nsString& aName) MOZ_OVERRIDE;
virtual void CacheChildren() MOZ_OVERRIDE;
private:
nsRefPtr<XULLabelTextLeafAccessible> mValueTextLeaf;
};
inline XULLabelAccessible*
Accessible::AsXULLabel()
{
return IsXULLabel() ? static_cast<XULLabelAccessible*>(this) : nullptr;
}
/**
* Used to implement text interface on XUL label accessible in case when text
* is provided by @value attribute (no underlying text frame).
*/
class XULLabelTextLeafAccessible MOZ_FINAL : public TextLeafAccessibleWrap
{
public:
XULLabelTextLeafAccessible(nsIContent* aContent, DocAccessible* aDoc) :
TextLeafAccessibleWrap(aContent, aDoc)
{ mStateFlags |= eSharedNode; }
virtual ~XULLabelTextLeafAccessible() { }
// Accessible
virtual a11y::role NativeRole() MOZ_OVERRIDE;
virtual uint64_t NativeState() MOZ_OVERRIDE;
};
/**
* Used for XUL tooltip element.
*/

View File

@ -582,13 +582,13 @@ function getTextFromClipboard()
var clip = Components.classes["@mozilla.org/widget/clipboard;1"].
getService(Components.interfaces.nsIClipboard);
if (!clip)
return;
return "";
var trans = Components.classes["@mozilla.org/widget/transferable;1"].
createInstance(Components.interfaces.nsITransferable);
trans.init(getLoadContext());
if (!trans)
return;
return "";
trans.addDataFlavor("text/unicode");
clip.getData(trans, clip.kGlobalClipboard);

View File

@ -1548,16 +1548,21 @@ function textChangeChecker(aID, aStart, aEnd, aTextOrFunc, aIsInserted, aFromUse
{
this.target = getNode(aID);
this.type = aIsInserted ? EVENT_TEXT_INSERTED : EVENT_TEXT_REMOVED;
this.startOffset = aStart;
this.endOffset = aEnd;
this.textOrFunc = aTextOrFunc;
this.check = function textChangeChecker_check(aEvent)
{
aEvent.QueryInterface(nsIAccessibleTextChangeEvent);
var modifiedText = (typeof aTextOrFunc == "function") ?
aTextOrFunc() : aTextOrFunc;
var modifiedTextLen = (aEnd == -1) ? modifiedText.length : aEnd - aStart;
var modifiedText = (typeof this.textOrFunc == "function") ?
this.textOrFunc() : this.textOrFunc;
var modifiedTextLen =
(this.endOffset == -1) ? modifiedText.length : aEnd - aStart;
is(aEvent.start, aStart, "Wrong start offset for " + prettyName(aID));
is(aEvent.start, this.startOffset,
"Wrong start offset for " + prettyName(aID));
is(aEvent.length, modifiedTextLen, "Wrong length for " + prettyName(aID));
var changeInfo = (aIsInserted ? "inserted" : "removed");
is(aEvent.isInserted(), aIsInserted,

View File

@ -46,6 +46,7 @@ MOCHITEST_A11Y_FILES =\
test_focus_tabbox.xul \
test_focus_tree.xul \
test_fromUserInput.html \
test_label.xul \
test_menu.xul \
test_mutation.html \
test_mutation.xhtml \

View File

@ -0,0 +1,177 @@
<?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"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Tests: accessible XUL label/description events">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../role.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Invokers
const kRecreated = 0;
const kTextRemoved = 1;
const kTextChanged = 2;
const kNoValue = 0;
/**
* Set/remove @value attribute.
*/
function setValue(aID, aValue, aResult, aOldValue)
{
this.labelNode = getNode(aID);
this.eventSeq = [];
switch (aResult) {
case kRecreated:
this.eventSeq.push(new invokerChecker(EVENT_HIDE, this.labelNode));
this.eventSeq.push(new invokerChecker(EVENT_SHOW, this.labelNode));
break;
case kTextRemoved:
this.eventSeq.push(
new textChangeChecker(this.labelNode, 0, aOldValue.length,
aOldValue, false));
break;
case kTextChanged:
this.eventSeq.push(
new textChangeChecker(this.labelNode, 0, aOldValue.length,
aOldValue, false));
this.eventSeq.push(
new textChangeChecker(this.labelNode, 0, aValue.length,
aValue, true));
break;
}
this.invoke = function setValue_invoke()
{
if (aValue === kNoValue)
this.labelNode.removeAttribute("value");
else
this.labelNode.setAttribute("value", aValue);
}
this.finalCheck = function setValue_finalCheck()
{
var tree =
{ LABEL: [
{ TEXT_LEAF: [ ] }
] };
testAccessibleTree(aID, tree);
}
this.getID = function setValue_getID()
{
return "set @value='" + aValue + "' for label " + prettyName(aID);
}
}
/**
* Change @crop attribute.
*/
function setCrop(aID, aCropValue, aRemovedText, aInsertedText)
{
this.labelNode = getNode(aID);
this.width = this.labelNode.boxObject.width;
this.charWidth = this.width / this.labelNode.value.length;
this.eventSeq = [
new textChangeChecker(this.labelNode, 0, -1, aRemovedText, false),
new textChangeChecker(this.labelNode, 0, -1, aInsertedText, true)
];
this.invoke = function setCrop_invoke()
{
if (!this.labelNode.hasAttribute("crop"))
this.labelNode.width = Math.floor(this.width - 2 * this.charWidth);
this.labelNode.setAttribute("crop", aCropValue);
}
this.getID = function setCrop_finalCheck()
{
return "set crop " + aCropValue;
}
}
////////////////////////////////////////////////////////////////////////////
// Test
gA11yEventDumpToConsole = true;
var gQueue = null;
function doTest()
{
gQueue = new eventQueue();
gQueue.push(new setValue("label", "shiroka strana", kRecreated));
gQueue.push(new setValue("label", "?<>!+_", kTextChanged, "shiroka strana"));
gQueue.push(new setValue("label", "", kTextRemoved, "?<>!+_"));
gQueue.push(new setValue("label", kNoValue, kRecreated));
gQueue.push(new setValue("descr", "hello world", kRecreated));
gQueue.push(new setValue("descr", "si_ya", kTextChanged, "hello world"));
gQueue.push(new setValue("descr", "", kTextRemoved, "si_ya"));
gQueue.push(new setValue("descr", kNoValue, kRecreated));
if (MAC) {
// "valuetocro" -> "…etocro"
gQueue.push(new setCrop("croplabel", "left", "valu", "…"));
// "…etocro", "val…cro"
gQueue.push(new setCrop("croplabel", "center", "…eto", "val…"));
} else {
// "valuetocro" -> "…uetocro"
gQueue.push(new setCrop("croplabel", "left", "val", "…"));
// "…uetocro" -> "valu…cro"
gQueue.push(new setCrop("croplabel", "center", "…ueto", "valu…"));
}
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</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=396166"
title="xul:label@value accessible should implement nsIAccessibleText">
Bug 396166
</a>
<br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<label id="label">hello</label>
<description id="descr">hello</description>
<hbox>
<label id="croplabel" value="valuetocro"
style="font-family: monospace;"/>
</hbox>
</vbox>
</hbox>
</window>

View File

@ -15,6 +15,7 @@ MOCHITEST_A11Y_FILES = \
doc.html \
test_doc.html \
test_hypertext.html \
test_label.xul \
test_passwords.html \
test_selection.html \
test_singleline.html \

View File

@ -0,0 +1,64 @@
<?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"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Tests: XUL label text interface">
<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>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../text.js"></script>
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Testing
var gQueue = null;
function doTests()
{
var ids = ["label1", "label2"];
testCharacterCount(ids, 5);
testText(ids, 0, -1, "Hello");
testText(ids, 0, 1, "H");
testCharAfterOffset(ids, 0, "e", 1, 2);
testCharBeforeOffset(ids, 1, "H", 0, 1);
testCharAtOffset(ids, 1, "e", 1, 2);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
]]>
</script>
<vbox 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=396166"
title="xul:label@value accessible should implement nsIAccessibleText">
Bug 396166
</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<label id="label1" value="Hello"/>
<label id="label2">Hello</label>
</vbox>
</window>

View File

@ -21,20 +21,13 @@
function doTest()
{
var accTree = {
role: ROLE_GROUPING,
children: [
{
role: ROLE_LABEL,
children: [ ]
},
{
role: ROLE_CHECKBUTTON,
children: [ ]
}
]
};
var accTree =
{ GROUPING: [
{ LABEL: [
{ TEXT_LEAF: [ ] }
] },
{ CHECKBUTTON: [ ] }
] };
testAccessibleTree("groupbox", accTree);
SimpleTest.finish()

View File

@ -203,7 +203,6 @@
@BINPATH@/components/dom_permissionsettings.xpt
@BINPATH@/components/dom_sidebar.xpt
@BINPATH@/components/dom_mobilemessage.xpt
@BINPATH@/components/dom_sms.xpt
@BINPATH@/components/dom_storage.xpt
@BINPATH@/components/dom_stylesheets.xpt
@BINPATH@/components/dom_threads.xpt

View File

@ -10,3 +10,4 @@ run-mozilla.sh
#endif
defaults/preferences/services-sync.js
defaults/preferences/healthreport-prefs.js
components/dom_sms.xpt

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1361213668000">
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1362088263000">
<emItems>
<emItem blockID="i58" id="webmaster@buzzzzvideos.info">
<versionRange minVersion="0" maxVersion="*">
@ -139,6 +139,10 @@
<versionRange minVersion="0" maxVersion="*">
</versionRange>
</emItem>
<emItem blockID="i310" id="{5ebdca98-43b3-45bb-87e0-716029fb42ab}">
<versionRange minVersion="0" maxVersion="*" severity="1">
</versionRange>
</emItem>
<emItem blockID="i168" id="flashX@adobe.com">
<versionRange minVersion="0" maxVersion="*" severity="3">
</versionRange>
@ -195,10 +199,6 @@
<versionRange minVersion="0" maxVersion="*">
</versionRange>
</emItem>
<emItem blockID="i284" id="playbryte@playbryte.com">
<versionRange minVersion="0" maxVersion="*" severity="1">
</versionRange>
</emItem>
<emItem blockID="i59" id="ghostviewer@youtube2.com">
<versionRange minVersion="0" maxVersion="*">
</versionRange>
@ -300,6 +300,10 @@
</targetApplication>
</versionRange>
</emItem>
<emItem blockID="i308" id="9518042e-7ad6-4dac-b377-056e28d00c8f@f1cc0a13-4df1-4d66-938f-088db8838882.com">
<versionRange minVersion="0" maxVersion="*" severity="1">
</versionRange>
</emItem>
<emItem blockID="i13" id="{E8E88AB0-7182-11DF-904E-6045E0D72085}">
</emItem>
<emItem blockID="i83" id="flash@adobee.com">
@ -376,6 +380,10 @@
</targetApplication>
</versionRange>
</emItem>
<emItem blockID="i304" id="{f0e59437-6148-4a98-b0a6-60d557ef57f4}">
<versionRange minVersion="0" maxVersion="*" severity="1">
</versionRange>
</emItem>
<emItem blockID="i86" id="{45147e67-4020-47e2-8f7a-55464fb535aa}">
<versionRange minVersion="0" maxVersion="*">
</versionRange>
@ -418,6 +426,10 @@
<versionRange minVersion="0" maxVersion="*" severity="1">
</versionRange>
</emItem>
<emItem blockID="i306" id="{ADFA33FD-16F5-4355-8504-DF4D664CFE10}">
<versionRange minVersion="0" maxVersion="*" severity="1">
</versionRange>
</emItem>
<emItem blockID="i165" id="{EEF73632-A085-4fd3-A778-ECD82C8CB297}">
<versionRange minVersion="0" maxVersion="*" severity="3">
</versionRange>
@ -715,6 +727,55 @@
</targetApplication>
</versionRange>
</pluginItem>
<pluginItem blockID="p290">
<match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" /> <versionRange minVersion="10.3.183.19" maxVersion="10.3.183.42" severity="0" vulnerabilitystatus="1">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
<versionRange minVersion="20.0a1" maxVersion="*" />
</targetApplication>
</versionRange>
</pluginItem>
<pluginItem blockID="p292">
<match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 7 Update 12" maxVersion="Java 7 Update 15" severity="0" vulnerabilitystatus="2">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
<versionRange minVersion="17.0" maxVersion="*" />
</targetApplication>
</versionRange>
</pluginItem>
<pluginItem blockID="p294">
<match name="name" exp="Java\(TM\) Platform SE 7 U1[2-5](\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="0" vulnerabilitystatus="2">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
<versionRange minVersion="17.0" maxVersion="*" />
</targetApplication>
</versionRange>
</pluginItem>
<pluginItem blockID="p296">
<match name="name" exp="Java\(TM\) Plug-in 1\.7\.0_1[2-5]([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="0" vulnerabilitystatus="2">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
<versionRange minVersion="17.0" maxVersion="*" />
</targetApplication>
</versionRange>
</pluginItem>
<pluginItem blockID="p298">
<match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 6 Update 39" maxVersion="Java 6 Update 41" severity="0" vulnerabilitystatus="2">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
<versionRange minVersion="17.0" maxVersion="*" />
</targetApplication>
</versionRange>
</pluginItem>
<pluginItem blockID="p300">
<match name="name" exp="Java\(TM\) Platform SE 6 U(39|40|41)(\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="0" vulnerabilitystatus="2">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
<versionRange minVersion="17.0" maxVersion="*" />
</targetApplication>
</versionRange>
</pluginItem>
<pluginItem blockID="p302">
<match name="name" exp="Java\(TM\) Plug-in 1\.6\.0_(39|40|41)([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="0" vulnerabilitystatus="2">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
<versionRange minVersion="17.0" maxVersion="*" />
</targetApplication>
</versionRange>
</pluginItem>
</pluginItems>
<gfxItems>

View File

@ -351,8 +351,14 @@ let SocialChatBar = {
return !!this.chatbar.firstElementChild;
},
openChat: function(aProvider, aURL, aCallback, aMode) {
if (this.isAvailable)
if (this.isAvailable) {
this.chatbar.openChat(aProvider, aURL, aCallback, aMode);
// We only want to focus the chat if it is as a result of user input.
let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
if (dwu.isHandlingUserInput)
this.chatbar.focus();
}
},
update: function() {
let command = document.getElementById("Social:FocusChat");

View File

@ -20,6 +20,37 @@
</content>
<implementation implements="nsIDOMEventListener">
<constructor><![CDATA[
let Social = Components.utils.import("resource:///modules/Social.jsm", {}).Social;
Social.setErrorListener(this.iframe, function(iframe) {
iframe.webNavigation.loadURI("about:socialerror?mode=compactInfo", null, null, null, null);
});
let iframeWindow = this.iframe.contentWindow;
this.addEventListener("DOMContentLoaded", function DOMContentLoaded() {
this.removeEventListener("DOMContentLoaded", DOMContentLoaded);
this.isActive = !this.minimized;
// process this._callbacks, then set to null so the chatbox creator
// knows to make new callbacks immediately.
for (let callback of this._callbacks) {
if (callback)
callback(iframeWindow);
}
this._callbacks = null;
// content can send a socialChatActivity event to have the UI update.
let chatActivity = function() {
this.setAttribute("activity", true);
this.parentNode.updateTitlebar(this);
}.bind(this);
iframeWindow.addEventListener("socialChatActivity", chatActivity);
iframeWindow.addEventListener("unload", function unload() {
iframeWindow.removeEventListener("unload", unload);
iframeWindow.removeEventListener("socialChatActivity", chatActivity);
});
});
this.setAttribute("src", this.src);
]]></constructor>
<field name="iframe" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "iframe");
</field>
@ -61,9 +92,12 @@
<method name="onTitlebarClick">
<parameter name="aEvent"/>
<body><![CDATA[
if (aEvent.button == 0) // left-click: toggle minimized.
if (aEvent.button == 0) { // left-click: toggle minimized.
this.toggle();
else if (aEvent.button == 1) // middle-click: close chat
// if we restored it, we want to focus it.
if (!this.minimized)
this.parentNode.focus();
} else if (aEvent.button == 1) // middle-click: close chat
this.close();
]]></body>
</method>
@ -145,8 +179,25 @@
<body><![CDATA[
if (!this.selectedChat)
return;
let commandDispatcher = gBrowser.ownerDocument.commandDispatcher;
commandDispatcher.advanceFocusIntoSubtree(this.selectedChat);
Services.focus.focusedWindow = this.selectedChat.iframe.contentWindow;
]]></body>
</method>
<method name="_isChatFocused">
<parameter name="aChatbox"/>
<body><![CDATA[
// If there are no XBL bindings for the chat it can't be focused.
if (!aChatbox.iframe)
return false;
let fw = Services.focus.focusedWindow;
if (!fw)
return false;
// We want to see if the focused window is in the subtree below our iframe...
let containingBrowser = fw.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.chromeEventHandler;
return containingBrowser == aChatbox.iframe;
]]></body>
</method>
@ -168,7 +219,6 @@
this._selectedChat = val;
if (val) {
this._selectedChat.setAttribute("selected", "true");
this.focus();
}
}
if (val) {
@ -231,9 +281,12 @@
// It's possible in the future we will track most-recently-selected
// chats or similar to find the "best" candidate - for now though
// the choice is somewhat arbitrary.
let moveFocus = this.selectedChat && this._isChatFocused(this.selectedChat);
for (let other of this.children) {
if (other != this.selectedChat && !other.minimized && !other.collapsed) {
this.selectedChat = other;
if (moveFocus)
this.focus();
return;
}
}
@ -381,51 +434,6 @@
]]></body>
</method>
<method name="initChatBox">
<!-- ideally this would be a method on the chatbox itself, but the
vagaries of XBL bindings means that in some edge cases the
chatbox methods don't exist yet when we need them to...
-->
<parameter name="aChatBox"/>
<parameter name="aProvider"/>
<parameter name="aURL"/>
<parameter name="aCallback"/>
<body><![CDATA[
// callbacks to be called when onload fires - more might be added
// if the same chat is requested before onload has fired. Set back
// to null in DOMContentLoaded, so null means DOMContentLoaded has
// already fired and new callbacks can be made immediately.
aChatBox._callbacks = [aCallback];
var tmp = {};
Components.utils.import("resource:///modules/Social.jsm", tmp);
tmp.Social.setErrorListener(aChatBox.iframe, function(iframe) {
iframe.webNavigation.loadURI("about:socialerror?mode=compactInfo", null, null, null, null);
});
let iframeWindow = aChatBox.iframe.contentWindow;
aChatBox.addEventListener("DOMContentLoaded", function DOMContentLoaded() {
aChatBox.removeEventListener("DOMContentLoaded", DOMContentLoaded);
aChatBox.isActive = !aChatBox.minimized;
for (let callback of aChatBox._callbacks) {
if (callback)
callback(iframeWindow);
}
aChatBox._callbacks = null;
function chatActivity() {
aChatBox.setAttribute("activity", true);
aChatBox.parentNode.updateTitlebar(aChatBox);
};
iframeWindow.addEventListener("socialChatActivity", chatActivity);
iframeWindow.addEventListener("unload", function unload() {
iframeWindow.removeEventListener("unload", unload);
iframeWindow.removeEventListener("socialChatActivity", chatActivity);
});
});
aChatBox.setAttribute("origin", aProvider.origin);
aChatBox.setAttribute("src", aURL);
]]></body>
</method>
<method name="openChat">
<parameter name="aProvider"/>
<parameter name="aURL"/>
@ -451,11 +459,16 @@
this.chatboxForURL.delete(aURL);
}
cb = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "chatbox");
// _callbacks is a javascript property instead of a <field> as it
// must exist before the (possibly delayed) bindings are created.
cb._callbacks = [aCallback];
// src also a javascript property; the src attribute is set in the ctor.
cb.src = aURL;
if (aMode == "minimized")
cb.setAttribute("minimized", "true");
cb.setAttribute("origin", aProvider.origin);
this.insertBefore(cb, this.firstChild);
this.selectedChat = cb;
this.initChatBox(cb, aProvider, aURL, aCallback);
this.chatboxForURL.set(aURL, Cu.getWeakReference(cb));
this.resize();
]]></body>

View File

@ -24,6 +24,7 @@ _BROWSER_FILES = \
browser_social_mozSocial_API.js \
browser_social_isVisible.js \
browser_social_chatwindow.js \
browser_social_chatwindowfocus.js \
browser_social_multiprovider.js \
browser_social_errorPage.js \
social_panel.html \

View File

@ -0,0 +1,309 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Is the currently opened tab focused?
function isTabFocused() {
let tabb = gBrowser.getBrowserForTab(gBrowser.selectedTab);
return Services.focus.focusedWindow == tabb.contentWindow;
}
function isChatFocused(chat) {
return SocialChatBar.chatbar._isChatFocused(chat);
}
function openChatViaUser() {
let sidebarDoc = document.getElementById("social-sidebar-browser").contentDocument;
let button = sidebarDoc.getElementById("chat-opener");
// Note we must use synthesizeMouseAtCenter() rather than calling
// .click() directly as this causes nsIDOMWindowUtils.isHandlingUserInput
// to be true.
EventUtils.synthesizeMouseAtCenter(button, {}, sidebarDoc.defaultView);
}
function openChatViaSidebarMessage(port, data, callback) {
port.onmessage = function (e) {
if (e.data.topic == "chatbox-opened")
callback();
}
port.postMessage({topic: "test-chatbox-open", data: data});
}
function openChatViaWorkerMessage(port, data, callback) {
// sadly there is no message coming back to tell us when the chat has
// been opened, so we wait until one appears.
let chatbar = SocialChatBar.chatbar;
let numExpected = chatbar.childElementCount + 1;
port.postMessage({topic: "test-worker-chat", data: data});
waitForCondition(function() chatbar.childElementCount == numExpected,
function() {
// so the child has been added, but we don't know if it
// has been intialized - re-request it and the callback
// means it's done. Minimized, same as the worker.
SocialChatBar.openChat(Social.provider,
data,
function() {
callback();
},
"minimized");
},
"No new chat appeared");
}
let isSidebarLoaded = false;
function startTestAndWaitForSidebar(callback) {
let doneCallback;
let port = Social.provider.getWorkerPort();
function maybeCallback() {
if (!doneCallback)
callback(port);
doneCallback = true;
}
port.onmessage = function(e) {
let topic = e.data.topic;
switch (topic) {
case "got-sidebar-message":
isSidebarLoaded = true;
maybeCallback();
break;
case "test-init-done":
if (isSidebarLoaded)
maybeCallback();
break;
}
}
port.postMessage({topic: "test-init"});
}
let manifest = { // normal provider
name: "provider 1",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
};
function test() {
waitForExplicitFinish();
// Note that (probably) due to bug 604289, if a tab is focused but the
// focused element is null, our chat windows can "steal" focus. This is
// avoided if we explicitly focus an element in the tab.
// So we load a page with an <input> field and focus that before testing.
let url = "data:text/html;charset=utf-8," + encodeURI('<input id="theinput">');
let tab = gBrowser.selectedTab = gBrowser.addTab(url, {skipAnimation: true});
tab.linkedBrowser.addEventListener("load", function tabLoad(event) {
tab.linkedBrowser.removeEventListener("load", tabLoad, true);
// before every test we focus the input field.
let preSubTest = function(cb) {
// XXX - when bug 604289 is fixed it should be possible to just do:
// tab.linkedBrowser.contentWindow.focus()
// but instead we must do:
tab.linkedBrowser.contentDocument.getElementById("theinput").focus();
cb();
}
let postSubTest = function(cb) {
window.SocialChatBar.chatbar.removeAll();
cb();
}
// and run the tests.
runSocialTestWithProvider(manifest, function (finishcb) {
runSocialTests(tests, preSubTest, postSubTest, function () {
finishcb();
});
});
}, true);
registerCleanupFunction(function() {
gBrowser.removeTab(tab);
});
}
var tests = {
// In this test the worker asks the sidebar to open a chat. As that means
// we aren't handling user-input we will not focus the chatbar.
// Then we do it again - should still not be focused.
// Then we perform a user-initiated request - it should get focus.
testNoFocusWhenViaWorker: function(next) {
startTestAndWaitForSidebar(function(port) {
openChatViaSidebarMessage(port, {stealFocus: 1}, function() {
ok(true, "got chatbox message");
is(SocialChatBar.chatbar.childElementCount, 1, "exactly 1 chat open");
ok(isTabFocused(), "tab should still be focused");
// re-request the same chat via a message.
openChatViaSidebarMessage(port, {stealFocus: 1}, function() {
is(SocialChatBar.chatbar.childElementCount, 1, "still exactly 1 chat open");
ok(isTabFocused(), "tab should still be focused");
// re-request the same chat via user event.
openChatViaUser();
is(SocialChatBar.chatbar.childElementCount, 1, "still exactly 1 chat open");
// should now be focused
ok(isChatFocused(SocialChatBar.chatbar.firstElementChild), "chat should be focused");
next();
});
});
});
},
// In this test we arrange for the sidebar to open the chat via a simulated
// click. This should cause the new chat to be opened and focused.
testFocusWhenViaUser: function(next) {
startTestAndWaitForSidebar(function(port) {
openChatViaUser();
ok(SocialChatBar.chatbar.firstElementChild, "chat opened");
ok(isChatFocused(SocialChatBar.chatbar.firstElementChild), "chat should be focused");
next();
});
},
// Open a chat via the worker - it will open minimized and not have focus.
// Then open the same chat via a sidebar message - it will be restored but
// should still not have grabbed focus.
testNoFocusOnAutoRestore: function(next) {
const chatUrl = "https://example.com/browser/browser/base/content/test/social/social_chat.html?id=1";
let chatbar = SocialChatBar.chatbar;
startTestAndWaitForSidebar(function(port) {
openChatViaWorkerMessage(port, chatUrl, function() {
is(chatbar.childElementCount, 1, "exactly 1 chat open");
ok(chatbar.firstElementChild.minimized, "chat is minimized");
ok(isTabFocused(), "tab should be focused");
openChatViaSidebarMessage(port, {stealFocus: 1, id: 1}, function() {
is(chatbar.childElementCount, 1, "still 1 chat open");
ok(!chatbar.firstElementChild.minimized, "chat no longer minimized");
ok(isTabFocused(), "tab should still be focused");
next();
});
});
});
},
// Here we open a chat, which will not be focused. Then we minimize it and
// restore it via a titlebar clock - it should get focus at that point.
testFocusOnExplicitRestore: function(next) {
startTestAndWaitForSidebar(function(port) {
openChatViaSidebarMessage(port, {stealFocus: 1}, function() {
ok(true, "got chatbox message");
ok(isTabFocused(), "tab should still be focused");
let chatbox = SocialChatBar.chatbar.firstElementChild;
ok(chatbox, "chat opened");
chatbox.minimized = true;
ok(isTabFocused(), "tab should still be focused");
// pretend we clicked on the titlebar
chatbox.onTitlebarClick({button: 0});
ok(!chatbox.minimized, "chat should have been restored");
ok(isChatFocused(chatbox), "chat should be focused");
next();
});
});
},
// Open 2 chats and give 1 focus. Minimize the focused one - the second
// should get focus.
testMinimizeFocused: function(next) {
let chatbar = SocialChatBar.chatbar;
startTestAndWaitForSidebar(function(port) {
openChatViaSidebarMessage(port, {stealFocus: 1, id: 1}, function() {
let chat1 = chatbar.firstElementChild;
openChatViaSidebarMessage(port, {stealFocus: 1, id: 2}, function() {
is(chatbar.childElementCount, 2, "exactly 2 chats open");
let chat2 = chat1.nextElementSibling || chat1.previousElementSibling;
chatbar.selectedChat = chat1;
chatbar.focus();
ok(isChatFocused(chat1), "first chat should be focused");
chat1.minimized = true;
// minimizing the chat with focus should give it to another.
ok(isChatFocused(chat2), "second chat should be focused");
next();
});
});
});
},
// Open 2 chats, select (but not focus) one, then re-request it be
// opened via a message. Focus should not move.
testReopenNonFocused: function(next) {
let chatbar = SocialChatBar.chatbar;
startTestAndWaitForSidebar(function(port) {
openChatViaSidebarMessage(port, {id: 1}, function() {
let chat1 = chatbar.firstElementChild;
openChatViaSidebarMessage(port, {id: 2}, function() {
let chat2 = chat1.nextElementSibling || chat1.previousElementSibling;
chatbar.selectedChat = chat2;
// tab still has focus
ok(isTabFocused(), "tab should still be focused");
// re-request the first.
openChatViaSidebarMessage(port, {id: 1}, function() {
is(chatbar.selectedChat, chat1, "chat1 now selected");
ok(isTabFocused(), "tab should still be focused");
next();
});
});
});
});
},
// Open 2 chats, select and focus the second. Pressing the TAB key should
// cause focus to move between all elements in our chat window before moving
// to the next chat window.
testTab: function(next) {
let chatbar = SocialChatBar.chatbar;
startTestAndWaitForSidebar(function(port) {
openChatViaSidebarMessage(port, {id: 1}, function() {
let chat1 = chatbar.firstElementChild;
openChatViaSidebarMessage(port, {id: 2}, function() {
let chat2 = chat1.nextElementSibling || chat1.previousElementSibling;
chatbar.selectedChat = chat2;
chatbar.focus();
ok(isChatFocused(chat2), "new chat is focused");
// Our chats have 3 focusable elements, so it takes 4 TABs to move
// to the new chat.
EventUtils.sendKey("tab");
ok(isChatFocused(chat2), "new chat still focused after first tab");
is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "input1",
"first input field has focus");
EventUtils.sendKey("tab");
ok(isChatFocused(chat2), "new chat still focused after tab");
is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "input2",
"second input field has focus");
EventUtils.sendKey("tab");
ok(isChatFocused(chat2), "new chat still focused after tab");
is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "iframe",
"iframe has focus");
// this tab now should move to the next chat.
EventUtils.sendKey("tab");
ok(isChatFocused(chat1), "first chat is focused");
next();
});
});
});
},
// Open a chat and focus an element other than the first. Move focus to some
// other item (the tab itself in this case), then focus the chatbar - the
// same element that was previously focused should still have focus.
testFocusedElement: function(next) {
let chatbar = SocialChatBar.chatbar;
startTestAndWaitForSidebar(function(port) {
openChatViaUser();
let chat = chatbar.firstElementChild;
// need to wait for the content to load before we can focus it.
chat.addEventListener("DOMContentLoaded", function DOMContentLoaded() {
chat.removeEventListener("DOMContentLoaded", DOMContentLoaded);
chat.iframe.contentDocument.getElementById("input2").focus();
is(chat.iframe.contentDocument.activeElement.getAttribute("id"), "input2",
"correct input field has focus");
// set focus to the tab.
let tabb = gBrowser.getBrowserForTab(gBrowser.selectedTab);
Services.focus.moveFocus(tabb.contentWindow, null, Services.focus.MOVEFOCUS_ROOT, 0);
ok(isTabFocused(), "tab took focus");
chatbar.focus();
ok(isChatFocused(chat), "chat took focus");
is(chat.iframe.contentDocument.activeElement.getAttribute("id"), "input2",
"correct input field still has focus");
next();
});
});
},
};

View File

@ -21,6 +21,10 @@
</head>
<body onload="pingWorker();">
<p>This is a test social chat window.</p>
<!-- a couple of input fields to help with focus testing -->
<input id="input1"/>
<input id="input2"/>
<!-- an iframe here so this one page generates multiple load events -->
<iframe id="iframe" src="data:text/plain:this is an iframe"></iframe>
</body>

View File

@ -21,6 +21,11 @@
url = url + "?id="+data.id;
}
navigator.mozSocial.openChatWindow(url, function(chatwin) {
// Note that the following .focus() call should *not* arrange
// to steal focus - see browser_social_chatwindowfocus.js
if (data && data.stealFocus && chatwin) {
chatwin.focus();
}
port.postMessage({topic: "chatbox-opened",
result: chatwin ? "ok" : "failed"});
});
@ -37,5 +42,6 @@
</head>
<body onload="pingWorker();">
<p>This is a test social sidebar.</p>
<button id="chat-opener" onclick="navigator.mozSocial.openChatWindow('./social_chat.html');"/>
</body>
</html>

View File

@ -244,10 +244,11 @@
<!-- Character Encoding -->
<groupbox>
<caption label="&languages.customize.Charset.grouplabel;"/>
<caption label="&languages.customize.Fallback.grouplabel;"/>
<description>&languages.customize.Fallback.desc;</description>
<hbox align="center">
<label value="&languages.customize.DefaultCharset.label;"
accesskey="&languages.customize.DefaultCharset.accesskey;"
<label value="&languages.customize.Fallback.label;"
accesskey="&languages.customize.Fallback.accesskey;"
control="DefaultCharsetList"/>
<menulist id="DefaultCharsetList" ref="NC:DecodersRoot" datasources="rdf:charset-menu"
preference="intl.charset.default"

View File

@ -20,73 +20,9 @@ this.EXPORTED_SYMBOLS = [ "Node", "HTMLElement", "setTimeout", "clearTimeout" ];
this.Node = Components.interfaces.nsIDOMNode;
this.HTMLElement = Components.interfaces.nsIDOMHTMLElement;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
/**
* The next value to be returned by setTimeout
/*
* Import and re-export the timeout functions from Timer.jsm.
*/
let nextID = 1;
/**
* The map of outstanding timeouts
*/
const timers = {};
/**
* Object to be passed to Timer.initWithCallback()
*/
function TimerCallback(callback) {
this._callback = callback;
const interfaces = [ Components.interfaces.nsITimerCallback ];
this.QueryInterface = XPCOMUtils.generateQI(interfaces);
}
TimerCallback.prototype.notify = function(timer) {
try {
for (let timerID in timers) {
if (timers[timerID] === timer) {
delete timers[timerID];
break;
}
}
this._callback.apply(null, []);
}
catch (ex) {
dump(ex + '\n');
}
};
/**
* Executes a code snippet or a function after specified delay.
* This is designed to have the same interface contract as the browser
* function.
* @param callback is the function you want to execute after the delay.
* @param delay is the number of milliseconds that the function call should
* be delayed by. Note that the actual delay may be longer, see Notes below.
* @return the ID of the timeout, which can be used later with
* window.clearTimeout.
*/
this.setTimeout = function setTimeout(callback, delay) {
const timer = Components.classes["@mozilla.org/timer;1"]
.createInstance(Components.interfaces.nsITimer);
let timerID = nextID++;
timers[timerID] = timer;
timer.initWithCallback(new TimerCallback(callback), delay, timer.TYPE_ONE_SHOT);
return timerID;
};
/**
* Clears the delay set by window.setTimeout() and prevents the callback from
* being executed (if it hasn't been executed already)
* @param timerID the ID of the timeout you wish to clear, as returned by
* window.setTimeout().
*/
this.clearTimeout = function clearTimeout(timerID) {
let timer = timers[timerID];
if (timer) {
timer.cancel();
delete timers[timerID];
}
};
let Timer = Components.utils.import("resource://gre/modules/Timer.jsm", {});
this.setTimeout = Timer.setTimeout;
this.clearTimeout = Timer.clearTimeout;

View File

@ -19,19 +19,10 @@ function test() {
}
function runTest(browser, tab, document) {
let timeout = imported.setTimeout(shouldNotBeCalled, 100);
imported.clearTimeout(timeout);
var p = document.getElementById("id");
ok(p instanceof imported.Node, "Node correctly defined");
ok(p instanceof imported.HTMLElement, "HTMLElement correctly defined");
let timeout = imported.setTimeout(function() {
finish();
}, 100);
}
function shouldNotBeCalled() {
ok(false, "Timeout cleared");
finish();
}

View File

@ -204,7 +204,6 @@
@BINPATH@/components/dom_permissionsettings.xpt
@BINPATH@/components/dom_sidebar.xpt
@BINPATH@/components/dom_mobilemessage.xpt
@BINPATH@/components/dom_sms.xpt
@BINPATH@/components/dom_storage.xpt
@BINPATH@/components/dom_stylesheets.xpt
@BINPATH@/components/dom_traversal.xpt

View File

@ -79,6 +79,7 @@ components/dom_telephony.xpt
components/dom_wifi.xpt
components/dom_system_b2g.xpt
#endif
components/dom_sms.xpt
components/uconvd.dll
components/WeaveCrypto.js
components/WeaveCrypto.manifest

View File

@ -68,6 +68,7 @@
<!ENTITY allowPagesToUse.label "Allow pages to choose their own fonts, instead of my selections above">
<!ENTITY allowPagesToUse.accesskey "A">
<!ENTITY languages.customize.Charset.grouplabel "Character Encoding">
<!ENTITY languages.customize.DefaultCharset.label "Default Character Encoding:">
<!ENTITY languages.customize.DefaultCharset.accesskey "C">
<!ENTITY languages.customize.Fallback.grouplabel "Character Encoding for Legacy Content">
<!ENTITY languages.customize.Fallback.label "Fallback Character Encoding:">
<!ENTITY languages.customize.Fallback.accesskey "C">
<!ENTITY languages.customize.Fallback.desc "This character encoding is used for legacy content that fails to declare its encoding.">

View File

@ -10,6 +10,15 @@
var ContextCommands = {
_picker: null,
get _ellipsis() {
delete this._ellipsis;
this._ellipsis = "\u2026";
try {
this._ellipsis = Services.prefs.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString).data;
} catch (ex) { }
return this._ellipsis;
},
get clipboard() {
return Cc["@mozilla.org/widget/clipboardhelper;1"]
.getService(Ci.nsIClipboardHelper);
@ -98,6 +107,7 @@ var ContextCommands = {
searchTextSetup: function cc_searchTextSetup(aRichListItem, aSearchString) {
let defaultURI;
let defaultName;
aSearchString = aSearchString.trim();
try {
let defaultPB = Services.prefs.getDefaultBranch(null);
const nsIPLS = Ci.nsIPrefLocalizedString;
@ -108,11 +118,15 @@ var ContextCommands = {
Cu.reportError(ex);
return false;
}
let displayString = aSearchString;
if (displayString.length > 15) {
displayString = displayString.substring(0, 15) + this._ellipsis;
}
// label child node
let label = Services.strings
.createBundle("chrome://browser/locale/browser.properties")
.formatStringFromName("browser.search.contextTextSearchLabel",
[defaultName], 1);
.formatStringFromName("browser.search.contextTextSearchLabel2",
[defaultName, displayString], 2);
aRichListItem.childNodes[0].setAttribute("value", label);
aRichListItem.setAttribute("searchString", defaultURI);
return true;
@ -128,7 +142,8 @@ var ContextCommands = {
// Link specific
openLinkInNewTab: function cc_openLinkInNewTab() {
BrowserUI.newTab(ContextMenuUI.popupState.linkURL, Browser.selectedTab);
Browser.addTab(ContextMenuUI.popupState.linkURL, false, Browser.selectedTab);
ContextUI.peekTabs();
},
copyLink: function cc_copyLink() {
@ -354,7 +369,6 @@ var ContextCommands = {
var newDir = file.parent.QueryInterface(Ci.nsILocalFile);
Services.prefs.setComplexValue("browser.download.lastDir", Ci.nsILocalFile, newDir);
},
};
function AutoChosen(aFileAutoChosen, aUriAutoChosen) {

View File

@ -758,6 +758,32 @@ var BrowserUI = {
}
},
openFile: function() {
try {
const nsIFilePicker = Ci.nsIFilePicker;
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
let self = this;
let fpCallback = function fpCallback_done(aResult) {
if (aResult == nsIFilePicker.returnOK) {
self.goToURI(fp.fileURL.spec);
}
};
let windowTitle = Strings.browser.GetStringFromName("browserForOpenLocation");
fp.init(window, windowTitle, nsIFilePicker.modeOpen);
fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText |
nsIFilePicker.filterImages | nsIFilePicker.filterXML |
nsIFilePicker.filterHTML);
fp.open(fpCallback);
} catch (ex) {
dump ('BrowserUI openFile exception: ' + ex + '\n');
}
},
savePage: function() {
Browser.savePage();
},
receiveMessage: function receiveMessage(aMessage) {
let browser = aMessage.target;
let json = aMessage.json;
@ -812,6 +838,8 @@ var BrowserUI = {
case "cmd_zoomout":
case "cmd_volumeLeft":
case "cmd_volumeRight":
case "cmd_openFile":
case "cmd_savePage":
isSupported = true;
break;
default:
@ -935,6 +963,12 @@ var BrowserUI = {
// Zoom out (portrait) or in (landscape)
Browser.zoom(Util.isPortrait() ? 1 : -1);
break;
case "cmd_openFile":
this.openFile();
break;
case "cmd_savePage":
this.savePage();
break;
}
}
};

View File

@ -476,6 +476,10 @@ var Browser = {
tab.browser.messageManager.sendAsyncMessage("Browser:CanUnload", {});
},
savePage: function() {
ContentAreaUtils.saveDocument(this.selectedBrowser.contentWindow.document);
},
_doCloseTab: function _doCloseTab(aTab) {
let nextTab = this._getNextTab(aTab);
if (!nextTab)

View File

@ -67,6 +67,8 @@
<command id="cmd_go" oncommand="CommandUpdater.doCommand(this.id);"/>
<command id="cmd_openLocation" oncommand="CommandUpdater.doCommand(this.id);"/>
<command id="cmd_home" oncommand="CommandUpdater.doCommand(this.id);"/>
<command id="cmd_openFile" oncommand="CommandUpdater.doCommand(this.id);"/>
<command id="cmd_savePage" oncommand="CommandUpdater.doCommand(this.id);"/>
<!-- tabs -->
<command id="cmd_newTab" oncommand="CommandUpdater.doCommand(this.id);"/>
@ -133,6 +135,8 @@
<key id="key_focusURL" key="l" modifiers="accel" command="cmd_openLocation"/>
<key id="key_focusURL2" key="&urlbar.accesskey;" modifiers="alt" command="cmd_openLocation"/>
<key id="key_home" keycode="VK_HOME" modifiers="accel" command="cmd_home"/>
<key id="key_open" key="o" modifiers="accel" command="cmd_openFile"/>
<key id="key_save" key="s" modifiers="accel" command="cmd_savePage"/>
<!-- misc -->
<key id="key_zoomin" key="+" modifiers="accel" command="cmd_zoomin"/>
@ -572,6 +576,8 @@
<richlistbox id="context-commands" bindingType="contextmenu" flex="1">
<!-- priority="low" items are hidden by default when a context is being displayed
for two or more media types. (e.g. a linked image) -->
<!-- content types preceeded by '!' act as exclusion rules, the menu item will not
be displayed if the content type is present. -->
<!-- Note the order of richlistitem here is important as it is reflected in the
menu itself. -->
<!-- ux spec: https://bug782810.bugzilla.mozilla.org/attachment.cgi?id=714804 -->
@ -585,8 +591,8 @@
<richlistitem id="context-paste" type="paste" onclick="ContextCommands.paste();">
<label value="&contextTextPaste.label;"/>
</richlistitem>
<!-- Search Bing for "..." -->
<richlistitem id="context-search" type="copy,selected-text" onclick="ContextCommands.searchText(this);">
<!-- Search Bing for "(text..)", displayed on selected content text only -->
<richlistitem id="context-search" type="selected-text,!input-text" onclick="ContextCommands.searchText(this);">
<label id="context-search-label" value=""/>
</richlistitem>
<!-- only display if there is text on the clipboard and the target is the urlbar -->

View File

@ -161,6 +161,10 @@ var ContextMenuUI = {
continue;
for (let i = 0; i < types.length; i++) {
// If one of the item's types has '!' before it, treat it as an exclusion rule.
if (types[i].charAt(0) == '!' && contentTypes.indexOf(types[i].substring(1)) != -1) {
break;
}
if (contentTypes.indexOf(types[i]) != -1) {
// If this is the special search text item, we need to set its label dynamically.
if (searchTextItem && !ContextCommands.searchTextSetup(command, this._popupState.string)) {

View File

@ -236,7 +236,7 @@ function waitForImageLoad(aWindow, aImageId) {
*/
function waitForObserver(aObsEvent, aTimeoutMs) {
try {
let deferred = Promise.defer();
let timeoutMs = aTimeoutMs || kDefaultWait;
let timerID = 0;
@ -276,7 +276,7 @@ function waitForObserver(aObsEvent, aTimeoutMs) {
Services.obs.addObserver(observeWatcher, aObsEvent, true);
return deferred.promise;
} catch (ex) {
info(ex.message);
}
@ -412,10 +412,15 @@ function runTests() {
Task.spawn(function() {
while((gCurrentTest = gTests.shift())){
info(gCurrentTest.desc);
yield Task.spawn(gCurrentTest.run);
if ('function' == typeof gCurrentTest.setUp) {
yield Task.spawn(gCurrentTest.setUp.bind(gCurrentTest));
}
yield Task.spawn(gCurrentTest.run.bind(gCurrentTest));
if ('function' == typeof gCurrentTest.tearDown) {
yield Task.spawn(gCurrentTest.tearDown.bind(gCurrentTest));
}
info("END "+gCurrentTest.desc);
}
info("done with gTests while loop, calling finish");
finish();
});
}

View File

@ -10,8 +10,8 @@ browser.search.order.1=Bing
browser.search.order.2=Google
browser.search.order.3=Yahoo
# l10n: search context menu item text will be: |Search (browser.search.defaultenginename) for ".."
browser.search.contextTextSearchLabel=Search %S for ".."
# l10n: search context menu item text will be: |Search (browser.search.defaultenginename) for "(string).."
browser.search.contextTextSearchLabel2=Search %S for "%S"
# Settings Charms
aboutCharm1=About
@ -21,6 +21,7 @@ helpOnlineCharm=Help (online)
# General
browserForSaveLocation=Save Location
browserForOpenLocation=Open Location
# Download Manager
downloadsUnknownSize=Unknown size

View File

@ -21,13 +21,13 @@ XPCOMUtils.defineLazyServiceGetter(this, "MediaManagerService",
this.webrtcUI = {
init: function () {
Services.obs.addObserver(handleRequest, "getUserMedia:request", false);
Services.obs.addObserver(updateGlobalIndicator, "recording-device-events", false);
Services.obs.addObserver(updateIndicators, "recording-device-events", false);
Services.obs.addObserver(removeBrowserSpecificIndicator, "recording-window-ended", false);
},
uninit: function () {
Services.obs.removeObserver(handleRequest, "getUserMedia:request");
Services.obs.removeObserver(updateGlobalIndicator, "recording-device-events");
Services.obs.removeObserver(updateIndicators, "recording-device-events");
Services.obs.removeObserver(removeBrowserSpecificIndicator, "recording-window-ended");
},
@ -185,18 +185,6 @@ function prompt(aBrowser, aCallID, aAudioRequested, aVideoRequested, aDevices) {
}
Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow", aCallID);
// Show browser-specific indicator for the active camera/mic access.
let message = stringBundle.getFormattedString("getUserMedia.sharing" + requestType + ".message",
[ host ]);
let mainAction = null;
let secondaryActions = null;
let options = {
dismissed: true
};
chromeWin.PopupNotifications.show(aBrowser, "webRTC-sharingDevices", message,
"webRTC-sharingDevices-notification-icon", mainAction,
secondaryActions, options);
}
};
@ -215,13 +203,49 @@ function prompt(aBrowser, aCallID, aAudioRequested, aVideoRequested, aDevices) {
secondaryActions, options);
}
function updateGlobalIndicator() {
function updateIndicators() {
webrtcUI.showGlobalIndicator =
MediaManagerService.activeMediaCaptureWindows.Count() > 0;
let e = Services.wm.getEnumerator("navigator:browser");
while (e.hasMoreElements())
e.getNext().WebrtcIndicator.updateButton();
for (let {tab: tab} of webrtcUI.activeStreams)
showBrowserSpecificIndicator(tab.linkedBrowser);
}
function showBrowserSpecificIndicator(aBrowser) {
let hasVideo = {};
let hasAudio = {};
MediaManagerService.mediaCaptureWindowState(aBrowser.contentWindow,
hasVideo, hasAudio);
let captureState;
if (hasVideo.value && hasAudio.value) {
captureState = "CameraAndMicrophone";
} else if (hasVideo.value) {
captureState = "Camera";
} else if (hasAudio.value) {
captureState = "Microphone";
} else {
Cu.reportError("showBrowserSpecificIndicator: got neither video nor audio access");
return;
}
let chromeWin = aBrowser.ownerDocument.defaultView;
let stringBundle = chromeWin.gNavigatorBundle;
let host = aBrowser.contentDocument.documentURIObject.asciiHost;
let message = stringBundle.getFormattedString("getUserMedia.sharing" + captureState + ".message",
[ host ]);
let mainAction = null;
let secondaryActions = null;
let options = {
dismissed: true
};
chromeWin.PopupNotifications.show(aBrowser, "webRTC-sharingDevices", message,
"webRTC-sharingDevices-notification-icon", mainAction,
secondaryActions, options);
}
function removeBrowserSpecificIndicator(aSubject, aTopic, aData) {

60
build/mach_bootstrap.py Executable file
View File

@ -0,0 +1,60 @@
#!/usr/bin/env python
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import print_function, unicode_literals
import os
import platform
import sys
# TODO Bug 794506 Integrate with the in-tree virtualenv configuration.
SEARCH_PATHS = [
'python/mach',
'python/mozboot',
'python/mozbuild',
'build/pymake',
'python/blessings',
'python/psutil',
'python/which',
'other-licenses/ply',
'xpcom/idl-parser',
'testing',
'testing/xpcshell',
'testing/mozbase/mozprocess',
'testing/mozbase/mozfile',
'testing/mozbase/mozinfo',
]
# Individual files providing mach commands.
MACH_MODULES = [
'addon-sdk/mach_commands.py',
'layout/tools/reftest/mach_commands.py',
'python/mozboot/mozboot/mach_commands.py',
'python/mozbuild/mozbuild/config.py',
'python/mozbuild/mozbuild/mach_commands.py',
'python/mozbuild/mozbuild/frontend/mach_commands.py',
'testing/mochitest/mach_commands.py',
'testing/xpcshell/mach_commands.py',
]
def bootstrap(topsrcdir):
# Ensure we are running Python 2.7+. We put this check here so we generate a
# user-friendly error message rather than a cryptic stack trace on module
# import.
if sys.version_info[0] != 2 or sys.version_info[1] < 7:
print('Python 2.7 or above (but not Python 3) is required to run mach.')
print('You are running Python', platform.python_version())
sys.exit(1)
try:
import mach.main
except ImportError:
sys.path[0:0] = [os.path.join(topsrcdir, path) for path in SEARCH_PATHS]
import mach.main
mach = mach.main.Mach(topsrcdir)
for path in MACH_MODULES:
mach.load_commands_from_file(os.path.join(topsrcdir, path))
return mach

View File

@ -41,6 +41,7 @@ _TEST_FILES = \
_ROBOCOP_TOOLS = \
$(TESTPATH)/robocop.ini \
$(TESTPATH)/robocop_autophone.ini \
parse_ids.py \
$(NULL)
@ -80,6 +81,7 @@ $(_JAVA_TESTS): % : $(TESTPATH)/%.in
$(_ROBOCOP_TOOLS):
cp $(TESTPATH)/robocop.ini robocop.ini
cp $(TESTPATH)/robocop_autophone.ini robocop_autophone.ini
libs:: $(_TEST_FILES)
$(NSINSTALL) -D $(DEPTH)/_tests/testing/mochitest/tests/robocop
@ -100,6 +102,7 @@ robocop.ap_: AndroidManifest.xml $(TESTPATH)/assets/*
robocop.apk: robocop.ap_ classes.dex
cp $(TESTPATH)/robocop.ini robocop.ini
cp $(TESTPATH)/robocop_autophone.ini robocop_autophone.ini
cp $(srcdir)/parse_ids.py parse_ids.py
export::

View File

@ -117,6 +117,8 @@ http://sub1.xn--lt-uia.example.org:8000 privileged
http://sub2.xn--lt-uia.example.org:80 privileged
http://xn--exmple-cua.test:80 privileged
http://sub1.xn--exmple-cua.test:80 privileged
http://xn--exaple-kqf.test:80 privileged
http://sub1.xn--exaple-kqf.test:80 privileged
https://xn--hxajbheg2az3al.xn--jxalpdlp:443 privileged
https://sub1.xn--hxajbheg2az3al.xn--jxalpdlp:443 privileged

View File

@ -33,6 +33,7 @@ namespace std {
template istream& istream::_M_extract(float&);
template istream& istream::_M_extract(unsigned int&);
template istream& istream::_M_extract(unsigned long&);
template istream& istream::_M_extract(unsigned short&);
#endif
#if MOZ_LIBSTDCXX_VERSION >= GLIBCXX_VERSION(3, 4, 14)
/* Instantiate these templates to avoid GLIBCXX_3.4.14 symbol versions

View File

@ -218,7 +218,8 @@ class Expression:
self.offset = expression.offset
self.content = expression.content[:3]
def __str__(self):
return 'Unexpected content at offset %i, "%s"'%(self.offset, self.content)
return 'Unexpected content at offset {0}, "{1}"'.format(self.offset,
self.content)
class Context(dict):
"""

View File

@ -7,7 +7,6 @@ processing jar.mn files.
See the documentation for jar.mn on MDC for further details on the format.
'''
import sys
import os
import os.path
@ -152,11 +151,12 @@ class JarMaker(object):
'..', 'chrome.manifest')
if self.useJarfileManifest:
self.updateManifest(jarPath + '.manifest', chromebasepath % '',
self.updateManifest(jarPath + '.manifest', chromebasepath.format(''),
register)
addEntriesToListFile(chromeManifest, ['manifest chrome/%s.manifest' % (os.path.basename(jarPath),)])
addEntriesToListFile(chromeManifest, ['manifest chrome/{0}.manifest'
.format(os.path.basename(jarPath))])
if self.useChromeManifest:
self.updateManifest(chromeManifest, chromebasepath % 'chrome/',
self.updateManifest(chromeManifest, chromebasepath.format('chrome/'),
register)
# If requested, add a root chrome manifest entry (assumed to be in the parent directory
@ -258,9 +258,9 @@ class JarMaker(object):
'''
# chromebasepath is used for chrome registration manifests
# %s is getting replaced with chrome/ for chrome.manifest, and with
# {0} is getting replaced with chrome/ for chrome.manifest, and with
# an empty string for jarfile.manifest
chromebasepath = '%s' + os.path.basename(jarfile)
chromebasepath = '{0}' + os.path.basename(jarfile)
if self.outputFormat == 'jar':
chromebasepath = 'jar:' + chromebasepath + '.jar!'
chromebasepath += '/'
@ -272,7 +272,7 @@ class JarMaker(object):
jarfilepath = jarfile + '.jar'
try:
os.makedirs(os.path.dirname(jarfilepath))
except OSError, error:
except OSError as error:
if error.errno != errno.EEXIST:
raise
jf = ZipFile(jarfilepath, 'a', lock = True)
@ -345,7 +345,8 @@ class JarMaker(object):
if realsrc is None:
if jf is not None:
jf.close()
raise RuntimeError('File "%s" not found in %s' % (src, ', '.join(src_base)))
raise RuntimeError('File "{0}" not found in {1}'
.format(src, ', '.join(src_base)))
if m.group('optPreprocess'):
outf = outHelper.getOutput(out)
inf = open(realsrc)
@ -401,7 +402,7 @@ class JarMaker(object):
# remove previous link or file
try:
os.remove(out)
except OSError, e:
except OSError as e:
if e.errno != errno.ENOENT:
raise
return open(out, 'wb')
@ -411,7 +412,7 @@ class JarMaker(object):
if not os.path.isdir(outdir):
try:
os.makedirs(outdir)
except OSError, error:
except OSError as error:
if error.errno != errno.EEXIST:
raise
return out
@ -425,7 +426,7 @@ class JarMaker(object):
# remove previous link or file
try:
os.remove(out)
except OSError, e:
except OSError as e:
if e.errno != errno.ENOENT:
raise
if sys.platform != "win32":

View File

@ -77,9 +77,9 @@ class Preprocessor:
def warnUnused(self, file):
if self.actionLevel == 0:
sys.stderr.write('%s: WARNING: no preprocessor directives found\n' % file)
sys.stderr.write('{0}: WARNING: no preprocessor directives found\n'.format(file))
elif self.actionLevel == 1:
sys.stderr.write('%s: WARNING: no useful preprocessor directives found\n' % file)
sys.stderr.write('{0}: WARNING: no useful preprocessor directives found\n'.format(file))
pass
def setLineEndings(self, aLE):
@ -96,7 +96,9 @@ class Preprocessor:
"""
self.marker = aMarker
if aMarker:
self.instruction = re.compile('%s(?P<cmd>[a-z]+)(?:\s(?P<args>.*))?$'%aMarker, re.U)
self.instruction = re.compile('{0}(?P<cmd>[a-z]+)(?:\s(?P<args>.*))?$'
.format(aMarker),
re.U)
self.comment = re.compile(aMarker, re.U)
else:
class NoMatch(object):
@ -129,9 +131,9 @@ class Preprocessor:
self.writtenLines += 1
ln = self.context['LINE']
if self.writtenLines != ln:
self.out.write('//@line %(line)d "%(file)s"%(le)s'%{'line': ln,
'file': self.context['FILE'],
'le': self.LE})
self.out.write('//@line {line} "{file}"{le}'.format(line=ln,
file=self.context['FILE'],
le=self.LE))
self.writtenLines = ln
filteredLine = self.applyFilters(aLine)
if filteredLine != aLine:

View File

@ -7,6 +7,7 @@ if the entry does not already exist.
Usage: buildlist.py <filename> <entry> [<entry> ...]
'''
from __future__ import print_function
import sys
import os
@ -20,14 +21,14 @@ def addEntriesToListFile(listFile, entries):
try:
if os.path.exists(listFile):
f = open(listFile)
existing = set([x.strip() for x in f.readlines()])
existing = set(x.strip() for x in f.readlines())
f.close()
else:
existing = set()
f = open(listFile, 'a')
for e in entries:
if e not in existing:
f.write("%s\n" % e)
f.write("{0}\n".format(e))
existing.add(e)
f.close()
finally:
@ -35,6 +36,7 @@ def addEntriesToListFile(listFile, entries):
if __name__ == '__main__':
if len(sys.argv) < 3:
print >>sys.stderr, "Usage: buildlist.py <list file> <entry> [<entry> ...]"
print("Usage: buildlist.py <list file> <entry> [<entry> ...]",
file=sys.stderr)
sys.exit(1)
addEntriesToListFile(sys.argv[1], sys.argv[2:])

View File

@ -9,7 +9,7 @@
# not, an error message is printed, quoting ERROR_LOCATION, which should
# probably be the filename and line number of the erroneous call to
# check_source_count.py.
from __future__ import print_function
import sys
import os
import re
@ -32,17 +32,26 @@ for f in files:
details[f] = num
if count == expected_count:
print "TEST-PASS | check_source_count.py %s | %d" % (search_string, expected_count)
print("TEST-PASS | check_source_count.py {0} | {1}"
.format(search_string, expected_count))
else:
print "TEST-UNEXPECTED-FAIL | check_source_count.py %s | " % (search_string),
print("TEST-UNEXPECTED-FAIL | check_source_count.py {0} | "
.format(search_string),
end='')
if count < expected_count:
print "There are fewer occurrences of /%s/ than expected. This may mean that you have removed some, but forgotten to account for it %s." % (search_string, error_location)
print("There are fewer occurrences of /{0}/ than expected. "
"This may mean that you have removed some, but forgotten to "
"account for it {1}.".format(search_string, error_location))
else:
print "There are more occurrences of /%s/ than expected. We're trying to prevent an increase in the number of %s's, using %s if possible. If it in unavoidable, you should update the expected count %s." % (search_string, search_string, replacement, error_location)
print("There are more occurrences of /{0}/ than expected. We're trying "
"to prevent an increase in the number of {1}'s, using {2} if "
"possible. If it is unavoidable, you should update the expected "
"count {3}.".format(search_string, search_string, replacement,
error_location))
print "Expected: %d; found: %d" % (expected_count, count)
print("Expected: {0}; found: {1}".format(expected_count, count))
for k in sorted(details):
print "Found %d occurences in %s" % (details[k],k)
print("Found {0} occurences in {1}".format(details[k],k))
sys.exit(-1)

View File

@ -26,7 +26,6 @@ ${LIB_PREFIX}${ROOT}.${LIB_SUFFIX} following these rules:
descriptor contains. And for each of these LIBS, also apply the same
rules.
'''
from __future__ import with_statement
import sys, os, errno
import expandlibs_config as conf
@ -36,7 +35,7 @@ def ensureParentDir(file):
if dir and not os.path.exists(dir):
try:
os.makedirs(dir)
except OSError, error:
except OSError as error:
if error.errno != errno.EEXIST:
raise
@ -90,7 +89,8 @@ class LibDescriptor(dict):
def __str__(self):
'''Serializes the lib descriptor'''
return '\n'.join('%s = %s' % (k, ' '.join(self[k])) for k in self.KEYS if len(self[k]))
return '\n'.join('{0} = {1}'.format(k, ' '.join(self[k]))
for k in self.KEYS if len(self[k]))
class ExpandArgs(list):
def __init__(self, args):
@ -135,4 +135,4 @@ class ExpandLibsDeps(ExpandArgs):
return objs
if __name__ == '__main__':
print " ".join(ExpandArgs(sys.argv[1:]))
print(" ".join(ExpandArgs(sys.argv[1:])))

View File

@ -20,10 +20,11 @@ With the --symbol-order argument, followed by a file name, it will add the
relevant linker options to change the order in which the linker puts the
symbols appear in the resulting binary. Only works for ELF targets.
'''
from __future__ import with_statement
from __future__ import print_function
import sys
import os
from expandlibs import ExpandArgs, relativize, isObject, ensureParentDir, ExpandLibsDeps
from expandlibs import (ExpandArgs, relativize, isObject, ensureParentDir,
ExpandLibsDeps)
import expandlibs_config as conf
from optparse import OptionParser
import subprocess
@ -92,10 +93,10 @@ class ExpandArgsMore(ExpandArgs):
if not len(objs): return
fd, tmp = tempfile.mkstemp(suffix=".list",dir=os.curdir)
if conf.EXPAND_LIBS_LIST_STYLE == "linkerscript":
content = ['INPUT("%s")\n' % obj for obj in objs]
content = ['INPUT("{0}")\n'.format(obj) for obj in objs]
ref = tmp
elif conf.EXPAND_LIBS_LIST_STYLE == "list":
content = ["%s\n" % obj for obj in objs]
content = ["{0}\n".format(obj) for obj in objs]
ref = "@" + tmp
else:
os.close(fd)
@ -139,9 +140,13 @@ class ExpandArgsMore(ExpandArgs):
def _getOrderedSections(self, ordered_symbols):
'''Given an ordered list of symbols, returns the corresponding list
of sections following the order.'''
if not conf.EXPAND_LIBS_ORDER_STYLE in ['linkerscript', 'section-ordering-file']:
raise Exception('EXPAND_LIBS_ORDER_STYLE "%s" is not supported' % conf.EXPAND_LIBS_ORDER_STYLE)
finder = SectionFinder([arg for arg in self if isObject(arg) or os.path.splitext(arg)[1] == conf.LIB_SUFFIX])
if conf.EXPAND_LIBS_ORDER_STYLE not in ['linkerscript',
'section-ordering-file']:
raise Exception('EXPAND_LIBS_ORDER_STYLE "{0}" is not supported'
.format(conf.EXPAND_LIBS_ORDER_STYLE))
finder = SectionFinder([arg for arg in self
if isObject(arg) or
os.path.splitext(arg)[1] == conf.LIB_SUFFIX])
folded = self._getFoldedSections()
sections = set()
ordered_sections = []
@ -182,32 +187,35 @@ class ExpandArgsMore(ExpandArgs):
linked_sections = [s for s in linked_sections if s in split_sections]
if conf.EXPAND_LIBS_ORDER_STYLE == 'section-ordering-file':
option = '-Wl,--section-ordering-file,%s'
option = '-Wl,--section-ordering-file,{0}'
content = sections
for linked_section in linked_sections:
content.extend(split_sections[linked_section])
content.append('%s.*' % linked_section)
content.append('{0}.*'.format(linked_section))
content.append(linked_section)
elif conf.EXPAND_LIBS_ORDER_STYLE == 'linkerscript':
option = '-Wl,-T,%s'
option = '-Wl,-T,{0}'
section_insert_before = dict(SECTION_INSERT_BEFORE)
for linked_section in linked_sections:
content.append('SECTIONS {')
content.append(' %s : {' % linked_section)
content.extend(' *(%s)' % s for s in split_sections[linked_section])
content.append(' }')
content.append('}')
content.append('INSERT BEFORE %s' % section_insert_before[linked_section])
content.append('SECTIONS {{')
content.append(' {0} : {{'.format(linked_section))
content.extend(' *({0})'
.format(s for s in split_sections[linked_section]))
content.append(' }}')
content.append('}}')
content.append('INSERT BEFORE {0}'
.format(section_insert_before[linked_section]))
else:
raise Exception('EXPAND_LIBS_ORDER_STYLE "%s" is not supported' % conf.EXPAND_LIBS_ORDER_STYLE)
raise Exception('EXPAND_LIBS_ORDER_STYLE "{0}" is not supported'
.format(conf.EXPAND_LIBS_ORDER_STYLE))
fd, tmp = tempfile.mkstemp(dir=os.curdir)
f = os.fdopen(fd, "w")
f.write('\n'.join(content)+'\n')
f.close()
self.tmp.append(tmp)
self.append(option % tmp)
self.append(option.format(tmp))
class SectionFinder(object):
'''Instances of this class allow to map symbol names to sections in
@ -216,15 +224,17 @@ class SectionFinder(object):
def __init__(self, objs):
'''Creates an instance, given a list of object files.'''
if not conf.EXPAND_LIBS_ORDER_STYLE in ['linkerscript', 'section-ordering-file']:
raise Exception('EXPAND_LIBS_ORDER_STYLE "%s" is not supported' % conf.EXPAND_LIBS_ORDER_STYLE)
raise Exception('EXPAND_LIBS_ORDER_STYLE "{0}" is not supported'
.format(conf.EXPAND_LIBS_ORDER_STYLE))
self.mapping = {}
for obj in objs:
if not isObject(obj) and os.path.splitext(obj)[1] != conf.LIB_SUFFIX:
raise Exception('%s is not an object nor a static library' % obj)
raise Exception('{0} is not an object nor a static library'
.format(obj))
for symbol, section in SectionFinder._getSymbols(obj):
sym = SectionFinder._normalize(symbol)
if sym in self.mapping:
if not section in self.mapping[sym]:
if section not in self.mapping[sym]:
self.mapping[sym].append(section)
else:
self.mapping[sym] = [section]
@ -268,11 +278,11 @@ class SectionFinder(object):
return syms
def print_command(out, args):
print >>out, "Executing: " + " ".join(args)
print("Executing: " + " ".join(args), file=out)
for tmp in [f for f in args.tmp if os.path.isfile(f)]:
print >>out, tmp + ":"
print(tmp + ":", file=out)
with open(tmp) as file:
print >>out, "".join([" " + l for l in file.readlines()])
print("".join([" " + l for l in file.readlines()]), file=out)
out.flush()
def main():
@ -323,7 +333,10 @@ def main():
return
ensureParentDir(options.depend)
with open(options.depend, 'w') as depfile:
depfile.write("%s : %s\n" % (options.target, ' '.join(dep for dep in deps if os.path.isfile(dep) and dep != options.target)))
depfile.write("{0} : {1}\n"
.format(options.target, ' '.join(dep for dep in deps
if os.path.isfile(dep) and
dep != options.target)))
if __name__ == '__main__':

View File

@ -1,11 +1,10 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import print_function
'''Given a list of object files and library names, prints a library
descriptor to standard output'''
from __future__ import with_statement
import sys
import os
import expandlibs_config as conf
@ -19,12 +18,12 @@ def generate(args):
if os.path.exists(arg):
desc['OBJS'].append(os.path.abspath(arg))
else:
raise Exception("File not found: %s" % arg)
raise Exception("File not found: {0}".format(arg))
elif os.path.splitext(arg)[1] == conf.LIB_SUFFIX:
if os.path.exists(arg) or os.path.exists(arg + conf.LIBS_DESC_SUFFIX):
desc['LIBS'].append(os.path.abspath(arg))
else:
raise Exception("File not found: %s" % arg)
raise Exception("File not found: {0}".format(arg))
return desc
if __name__ == '__main__':
@ -40,8 +39,9 @@ if __name__ == '__main__':
ensureParentDir(options.output)
with open(options.output, 'w') as outfile:
print >>outfile, generate(args)
print(generate(args), file=outfile)
if options.depend:
ensureParentDir(options.depend)
with open(options.depend, 'w') as depfile:
depfile.write("%s : %s\n" % (options.output, ' '.join(ExpandLibsDeps(args))))
depfile.write("{0} : {1}\n".format(options.output,
' '.join(ExpandLibsDeps(args))))

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