mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 12:25:53 +00:00
Merge mozilla-central into build-system
This commit is contained in:
commit
cdcc783f10
@ -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
|
||||
|
@ -52,6 +52,7 @@ enum AccType {
|
||||
eMenuPopupType,
|
||||
eProgressType,
|
||||
eRootType,
|
||||
eXULLabelType,
|
||||
eXULTabpanelsType,
|
||||
eXULTreeType,
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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']
|
||||
|
||||
|
@ -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)
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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 \
|
||||
|
177
accessible/tests/mochitest/events/test_label.xul
Normal file
177
accessible/tests/mochitest/events/test_label.xul
Normal 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>
|
||||
|
@ -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 \
|
||||
|
64
accessible/tests/mochitest/text/test_label.xul
Normal file
64
accessible/tests/mochitest/text/test_label.xul
Normal 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>
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -10,3 +10,4 @@ run-mozilla.sh
|
||||
#endif
|
||||
defaults/preferences/services-sync.js
|
||||
defaults/preferences/healthreport-prefs.js
|
||||
components/dom_sms.xpt
|
@ -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>
|
||||
|
@ -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");
|
||||
|
@ -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>
|
||||
|
@ -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 \
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.">
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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)
|
||||
|
@ -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 -->
|
||||
|
@ -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)) {
|
||||
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
60
build/mach_bootstrap.py
Executable 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
|
@ -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::
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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":
|
||||
|
@ -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:
|
||||
|
@ -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:])
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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:])))
|
||||
|
@ -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__':
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user