зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to fx-team a=merge CLOSED TREE
This commit is contained in:
Коммит
b9799a40ef
|
@ -32,10 +32,6 @@ static const uint32_t kGenericAccType = 0;
|
|||
*
|
||||
* When no Role enum mapping exists for an ARIA role, the role will be exposed
|
||||
* via the object attribute "xml-roles".
|
||||
*
|
||||
* There are no Role enums for the following landmark roles:
|
||||
* banner, contentinfo, main, navigation, note, search, secondary,
|
||||
* seealso, breadcrumbs.
|
||||
*/
|
||||
|
||||
static nsRoleMapEntry sWAIRoleMaps[] =
|
||||
|
@ -67,7 +63,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
|
|||
eNoValue,
|
||||
eNoAction,
|
||||
eNoLiveAttr,
|
||||
kGenericAccType,
|
||||
eLandmark,
|
||||
kNoReqStates
|
||||
},
|
||||
{ // article
|
||||
|
@ -81,6 +77,16 @@ static nsRoleMapEntry sWAIRoleMaps[] =
|
|||
kNoReqStates,
|
||||
eReadonlyUntilEditable
|
||||
},
|
||||
{ // banner
|
||||
&nsGkAtoms::banner,
|
||||
roles::NOTHING,
|
||||
kUseNativeRole,
|
||||
eNoValue,
|
||||
eNoAction,
|
||||
eNoLiveAttr,
|
||||
eLandmark,
|
||||
kNoReqStates
|
||||
},
|
||||
{ // button
|
||||
&nsGkAtoms::button,
|
||||
roles::PUSHBUTTON,
|
||||
|
@ -129,6 +135,26 @@ static nsRoleMapEntry sWAIRoleMaps[] =
|
|||
eARIAReadonly,
|
||||
eARIAOrientation
|
||||
},
|
||||
{ // complementary
|
||||
&nsGkAtoms::complementary,
|
||||
roles::NOTHING,
|
||||
kUseNativeRole,
|
||||
eNoValue,
|
||||
eNoAction,
|
||||
eNoLiveAttr,
|
||||
eLandmark,
|
||||
kNoReqStates
|
||||
},
|
||||
{ // contentinfo
|
||||
&nsGkAtoms::contentinfo,
|
||||
roles::NOTHING,
|
||||
kUseNativeRole,
|
||||
eNoValue,
|
||||
eNoAction,
|
||||
eNoLiveAttr,
|
||||
eLandmark,
|
||||
kNoReqStates
|
||||
},
|
||||
{ // dialog
|
||||
&nsGkAtoms::dialog,
|
||||
roles::DIALOG,
|
||||
|
@ -167,7 +193,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
|
|||
eNoValue,
|
||||
eNoAction,
|
||||
eNoLiveAttr,
|
||||
kGenericAccType,
|
||||
eLandmark,
|
||||
kNoReqStates
|
||||
},
|
||||
{ // grid
|
||||
|
@ -290,6 +316,16 @@ static nsRoleMapEntry sWAIRoleMaps[] =
|
|||
kGenericAccType,
|
||||
kNoReqStates
|
||||
},
|
||||
{ // main
|
||||
&nsGkAtoms::main,
|
||||
roles::NOTHING,
|
||||
kUseNativeRole,
|
||||
eNoValue,
|
||||
eNoAction,
|
||||
eNoLiveAttr,
|
||||
eLandmark,
|
||||
kNoReqStates
|
||||
},
|
||||
{ // marquee
|
||||
&nsGkAtoms::marquee,
|
||||
roles::ANIMATION,
|
||||
|
@ -366,6 +402,16 @@ static nsRoleMapEntry sWAIRoleMaps[] =
|
|||
kNoReqStates,
|
||||
eARIACheckableBool
|
||||
},
|
||||
{ // navigation
|
||||
&nsGkAtoms::navigation,
|
||||
roles::NOTHING,
|
||||
kUseNativeRole,
|
||||
eNoValue,
|
||||
eNoAction,
|
||||
eNoLiveAttr,
|
||||
eLandmark,
|
||||
kNoReqStates
|
||||
},
|
||||
{ // none
|
||||
&nsGkAtoms::none,
|
||||
roles::NOTHING,
|
||||
|
@ -496,6 +542,29 @@ static nsRoleMapEntry sWAIRoleMaps[] =
|
|||
eARIAOrientation,
|
||||
eARIAReadonly
|
||||
},
|
||||
{ // search
|
||||
&nsGkAtoms::search,
|
||||
roles::NOTHING,
|
||||
kUseNativeRole,
|
||||
eNoValue,
|
||||
eNoAction,
|
||||
eNoLiveAttr,
|
||||
eLandmark,
|
||||
kNoReqStates
|
||||
},
|
||||
{ // searchbox
|
||||
&nsGkAtoms::searchbox,
|
||||
roles::ENTRY,
|
||||
kUseMapRole,
|
||||
eNoValue,
|
||||
eActivateAction,
|
||||
eNoLiveAttr,
|
||||
kGenericAccType,
|
||||
kNoReqStates,
|
||||
eARIAAutoComplete,
|
||||
eARIAMultiline,
|
||||
eARIAReadonlyOrEditable
|
||||
},
|
||||
{ // separator
|
||||
&nsGkAtoms::separator_,
|
||||
roles::SEPARATOR,
|
||||
|
|
|
@ -74,13 +74,14 @@ enum AccGenericType {
|
|||
eCombobox = 1 << 3,
|
||||
eDocument = 1 << 4,
|
||||
eHyperText = 1 << 5,
|
||||
eList = 1 << 6,
|
||||
eListControl = 1 << 7,
|
||||
eMenuButton = 1 << 8,
|
||||
eSelect = 1 << 9,
|
||||
eTable = 1 << 10,
|
||||
eTableCell = 1 << 11,
|
||||
eTableRow = 1 << 12,
|
||||
eLandmark = 1 << 6,
|
||||
eList = 1 << 7,
|
||||
eListControl = 1 << 8,
|
||||
eMenuButton = 1 << 9,
|
||||
eSelect = 1 << 10,
|
||||
eTable = 1 << 11,
|
||||
eTableCell = 1 << 12,
|
||||
eTableRow = 1 << 13,
|
||||
|
||||
eLastAccGenericType = eTableRow
|
||||
};
|
||||
|
|
|
@ -37,11 +37,18 @@ nsAccUtils::SetAccAttr(nsIPersistentProperties *aAttributes,
|
|||
nsIAtom *aAttrName, const nsAString& aAttrValue)
|
||||
{
|
||||
nsAutoString oldValue;
|
||||
nsAutoCString attrName;
|
||||
|
||||
aAttributes->SetStringProperty(nsAtomCString(aAttrName), aAttrValue, oldValue);
|
||||
}
|
||||
|
||||
void
|
||||
nsAccUtils::SetAccAttr(nsIPersistentProperties *aAttributes,
|
||||
nsIAtom* aAttrName, nsIAtom* aAttrValue)
|
||||
{
|
||||
nsAutoString oldValue;
|
||||
aAttributes->SetStringProperty(nsAtomCString(aAttrName),
|
||||
nsAtomString(aAttrValue), oldValue);
|
||||
}
|
||||
|
||||
void
|
||||
nsAccUtils::SetAccGroupAttrs(nsIPersistentProperties *aAttributes,
|
||||
int32_t aLevel, int32_t aSetSize,
|
||||
|
|
|
@ -50,6 +50,10 @@ public:
|
|||
nsIAtom *aAttrName,
|
||||
const nsAString& aAttrValue);
|
||||
|
||||
static void SetAccAttr(nsIPersistentProperties *aAttributes,
|
||||
nsIAtom* aAttrName,
|
||||
nsIAtom* aAttrValue);
|
||||
|
||||
/**
|
||||
* Set group attributes ('level', 'setsize', 'posinset').
|
||||
*/
|
||||
|
|
|
@ -44,6 +44,15 @@ Accessible::ARIARole()
|
|||
return ARIATransformRole(mRoleMapEntry->role);
|
||||
}
|
||||
|
||||
inline bool
|
||||
Accessible::IsSearchbox() const
|
||||
{
|
||||
return (mRoleMapEntry && mRoleMapEntry->Is(nsGkAtoms::searchbox)) ||
|
||||
(mContent->IsHTML(nsGkAtoms::input) &&
|
||||
mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
|
||||
nsGkAtoms::textInputType, eCaseMatters));
|
||||
}
|
||||
|
||||
inline bool
|
||||
Accessible::HasGenericType(AccGenericType aType) const
|
||||
{
|
||||
|
|
|
@ -860,14 +860,20 @@ Accessible::Attributes()
|
|||
if (!HasOwnContent() || !mContent->IsElement())
|
||||
return attributes.forget();
|
||||
|
||||
// 'xml-roles' attribute coming from ARIA.
|
||||
nsAutoString xmlRoles, unused;
|
||||
if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::role, xmlRoles)) {
|
||||
attributes->SetStringProperty(NS_LITERAL_CSTRING("xml-roles"),
|
||||
xmlRoles, unused);
|
||||
// 'xml-roles' attribute for landmark.
|
||||
nsIAtom* landmark = LandmarkRole();
|
||||
if (landmark) {
|
||||
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles, landmark);
|
||||
|
||||
} else {
|
||||
// 'xml-roles' attribute coming from ARIA.
|
||||
nsAutoString xmlRoles;
|
||||
if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::role, xmlRoles))
|
||||
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles, xmlRoles);
|
||||
}
|
||||
|
||||
// Expose object attributes from ARIA attributes.
|
||||
nsAutoString unused;
|
||||
aria::AttrIterator attribIter(mContent);
|
||||
nsAutoString name, value;
|
||||
while(attribIter.Next(name, value))
|
||||
|
@ -881,6 +887,11 @@ Accessible::Attributes()
|
|||
// If there is no aria-live attribute then expose default value of 'live'
|
||||
// object attribute used for ARIA role of this accessible.
|
||||
if (mRoleMapEntry) {
|
||||
if (mRoleMapEntry->Is(nsGkAtoms::searchbox)) {
|
||||
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::textInputType,
|
||||
NS_LITERAL_STRING("search"));
|
||||
}
|
||||
|
||||
nsAutoString live;
|
||||
nsAccUtils::GetAccAttr(attributes, nsGkAtoms::live, live);
|
||||
if (live.IsEmpty()) {
|
||||
|
@ -1385,6 +1396,13 @@ Accessible::ARIATransformRole(role aRole)
|
|||
return aRole;
|
||||
}
|
||||
|
||||
nsIAtom*
|
||||
Accessible::LandmarkRole() const
|
||||
{
|
||||
return mRoleMapEntry && mRoleMapEntry->IsOfType(eLandmark) ?
|
||||
*(mRoleMapEntry->roleAtom) : nullptr;
|
||||
}
|
||||
|
||||
role
|
||||
Accessible::NativeRole()
|
||||
{
|
||||
|
|
|
@ -230,6 +230,11 @@ public:
|
|||
*/
|
||||
mozilla::a11y::role ARIARole();
|
||||
|
||||
/**
|
||||
* Return a landmark role if applied.
|
||||
*/
|
||||
virtual nsIAtom* LandmarkRole() const;
|
||||
|
||||
/**
|
||||
* Returns enumerated accessible role from native markup (see constants in
|
||||
* Role.h). Doesn't take into account ARIA roles.
|
||||
|
@ -621,6 +626,8 @@ public:
|
|||
bool IsRoot() const { return mType == eRootType; }
|
||||
a11y::RootAccessible* AsRoot();
|
||||
|
||||
bool IsSearchbox() const;
|
||||
|
||||
bool IsSelect() const { return HasGenericType(eSelect); }
|
||||
|
||||
bool IsTable() const { return HasGenericType(eTable); }
|
||||
|
@ -1098,7 +1105,7 @@ protected:
|
|||
static const uint8_t kStateFlagsBits = 9;
|
||||
static const uint8_t kContextFlagsBits = 2;
|
||||
static const uint8_t kTypeBits = 6;
|
||||
static const uint8_t kGenericTypesBits = 13;
|
||||
static const uint8_t kGenericTypesBits = 14;
|
||||
|
||||
/**
|
||||
* Keep in sync with ChildrenFlags, StateFlags, ContextFlags, and AccTypes.
|
||||
|
|
|
@ -944,45 +944,13 @@ HyperTextAccessible::NativeAttributes()
|
|||
if (!HasOwnContent())
|
||||
return attributes.forget();
|
||||
|
||||
// For the html landmark elements we expose them like we do aria landmarks to
|
||||
// make AT navigation schemes "just work".
|
||||
nsIAtom* tag = mContent->Tag();
|
||||
if (tag == nsGkAtoms::nav) {
|
||||
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("navigation"));
|
||||
} else if (tag == nsGkAtoms::section) {
|
||||
if (tag == nsGkAtoms::section) {
|
||||
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("region"));
|
||||
} else if (tag == nsGkAtoms::header || tag == nsGkAtoms::footer) {
|
||||
// Only map header and footer if they are not descendants
|
||||
// of an article or section tag.
|
||||
nsIContent* parent = mContent->GetParent();
|
||||
while (parent) {
|
||||
if (parent->Tag() == nsGkAtoms::article ||
|
||||
parent->Tag() == nsGkAtoms::section)
|
||||
break;
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
|
||||
// No article or section elements found.
|
||||
if (!parent) {
|
||||
if (tag == nsGkAtoms::header) {
|
||||
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("banner"));
|
||||
} else if (tag == nsGkAtoms::footer) {
|
||||
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("contentinfo"));
|
||||
}
|
||||
}
|
||||
} else if (tag == nsGkAtoms::aside) {
|
||||
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("complementary"));
|
||||
} else if (tag == nsGkAtoms::article) {
|
||||
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("article"));
|
||||
} else if (tag == nsGkAtoms::main) {
|
||||
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("main"));
|
||||
} else if (tag == nsGkAtoms::time) {
|
||||
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("time"));
|
||||
|
@ -997,6 +965,47 @@ HyperTextAccessible::NativeAttributes()
|
|||
return attributes.forget();
|
||||
}
|
||||
|
||||
nsIAtom*
|
||||
HyperTextAccessible::LandmarkRole() const
|
||||
{
|
||||
// For the html landmark elements we expose them like we do ARIA landmarks to
|
||||
// make AT navigation schemes "just work".
|
||||
nsIAtom* tag = mContent->Tag();
|
||||
if (tag == nsGkAtoms::nav)
|
||||
return nsGkAtoms::navigation;
|
||||
|
||||
if (tag == nsGkAtoms::header || tag == nsGkAtoms::footer) {
|
||||
// Only map header and footer if they are not descendants of an article
|
||||
// or section tag.
|
||||
nsIContent* parent = mContent->GetParent();
|
||||
while (parent) {
|
||||
if (parent->Tag() == nsGkAtoms::article ||
|
||||
parent->Tag() == nsGkAtoms::section)
|
||||
break;
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
|
||||
// No article or section elements found.
|
||||
if (!parent) {
|
||||
if (tag == nsGkAtoms::header)
|
||||
return nsGkAtoms::banner;
|
||||
|
||||
if (tag == nsGkAtoms::footer) {
|
||||
return nsGkAtoms::contentinfo;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (tag == nsGkAtoms::aside)
|
||||
return nsGkAtoms::complementary;
|
||||
|
||||
if (tag == nsGkAtoms::main)
|
||||
return nsGkAtoms::main;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int32_t
|
||||
HyperTextAccessible::OffsetAtPoint(int32_t aX, int32_t aY, uint32_t aCoordType)
|
||||
{
|
||||
|
|
|
@ -54,6 +54,7 @@ public:
|
|||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// Accessible
|
||||
virtual nsIAtom* LandmarkRole() const MOZ_OVERRIDE;
|
||||
virtual int32_t GetLevelInternal() MOZ_OVERRIDE;
|
||||
virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
|
||||
virtual mozilla::a11y::role NativeRole() MOZ_OVERRIDE;
|
||||
|
|
|
@ -306,8 +306,13 @@ HTMLTextFieldAccessible::NativeAttributes()
|
|||
// Expose type for text input elements as it gives some useful context,
|
||||
// especially for mobile.
|
||||
nsAutoString type;
|
||||
if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type))
|
||||
if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type)) {
|
||||
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::textInputType, type);
|
||||
if (!mRoleMapEntry && type.EqualsLiteral("search")) {
|
||||
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("searchbox"));
|
||||
}
|
||||
}
|
||||
|
||||
return attributes.forget();
|
||||
}
|
||||
|
|
|
@ -430,42 +430,37 @@ GetClosestInterestingAccessible(id anObject)
|
|||
if (!mGeckoAccessible)
|
||||
return nil;
|
||||
|
||||
// XXX maybe we should cache the subrole.
|
||||
nsAutoString xmlRoles;
|
||||
|
||||
// XXX we don't need all the attributes (see bug 771113)
|
||||
nsCOMPtr<nsIPersistentProperties> attributes = mGeckoAccessible->Attributes();
|
||||
if (attributes)
|
||||
nsAccUtils::GetAccAttr(attributes, nsGkAtoms::xmlroles, xmlRoles);
|
||||
|
||||
nsWhitespaceTokenizer tokenizer(xmlRoles);
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
const nsDependentSubstring token(tokenizer.nextToken());
|
||||
|
||||
if (token.EqualsLiteral("banner"))
|
||||
nsIAtom* landmark = mGeckoAccessible->LandmarkRole();
|
||||
if (landmark) {
|
||||
if (landmark == nsGkAtoms::application)
|
||||
return @"AXLandmarkApplication";
|
||||
if (landmark == nsGkAtoms::banner)
|
||||
return @"AXLandmarkBanner";
|
||||
|
||||
if (token.EqualsLiteral("complementary"))
|
||||
if (landmark == nsGkAtoms::complementary)
|
||||
return @"AXLandmarkComplementary";
|
||||
|
||||
if (token.EqualsLiteral("contentinfo"))
|
||||
if (landmark == nsGkAtoms::contentinfo)
|
||||
return @"AXLandmarkContentInfo";
|
||||
|
||||
if (token.EqualsLiteral("main"))
|
||||
if (landmark == nsGkAtoms::form)
|
||||
return @"AXLandmarkForm";
|
||||
if (landmark == nsGkAtoms::main)
|
||||
return @"AXLandmarkMain";
|
||||
|
||||
if (token.EqualsLiteral("navigation"))
|
||||
if (landmark == nsGkAtoms::navigation)
|
||||
return @"AXLandmarkNavigation";
|
||||
|
||||
if (token.EqualsLiteral("search"))
|
||||
if (landmark == nsGkAtoms::search)
|
||||
return @"AXLandmarkSearch";
|
||||
if (landmark == nsGkAtoms::searchbox)
|
||||
return @"AXSearchField";
|
||||
}
|
||||
|
||||
switch (mRole) {
|
||||
case roles::LIST:
|
||||
return @"AXContentList"; // 10.6+ NSAccessibilityContentListSubrole;
|
||||
|
||||
case roles::ENTRY:
|
||||
if (mGeckoAccessible->IsSearchbox())
|
||||
return @"AXSearchField";
|
||||
break;
|
||||
|
||||
case roles::DEFINITION_LIST:
|
||||
return @"AXDefinitionList"; // 10.6+ NSAccessibilityDefinitionListSubrole;
|
||||
|
||||
|
@ -485,6 +480,33 @@ GetClosestInterestingAccessible(id anObject)
|
|||
return nil;
|
||||
}
|
||||
|
||||
struct RoleDescrMap
|
||||
{
|
||||
NSString* role;
|
||||
const nsString& description;
|
||||
};
|
||||
|
||||
static const RoleDescrMap sRoleDescrMap[] = {
|
||||
{ @"AXDefinition", NS_LITERAL_STRING("definition") },
|
||||
{ @"AXLandmarkBanner", NS_LITERAL_STRING("banner") },
|
||||
{ @"AXLandmarkComplementary", NS_LITERAL_STRING("complementary") },
|
||||
{ @"AXLandmarkContentInfo", NS_LITERAL_STRING("content") },
|
||||
{ @"AXLandmarkMain", NS_LITERAL_STRING("main") },
|
||||
{ @"AXLandmarkNavigation", NS_LITERAL_STRING("navigation") },
|
||||
{ @"AXLandmarkSearch", NS_LITERAL_STRING("search") },
|
||||
{ @"AXSearchField", NS_LITERAL_STRING("searchTextField") },
|
||||
{ @"AXTerm", NS_LITERAL_STRING("term") }
|
||||
};
|
||||
|
||||
struct RoleDescrComparator
|
||||
{
|
||||
const NSString* mRole;
|
||||
explicit RoleDescrComparator(const NSString* aRole) : mRole(aRole) {}
|
||||
int operator()(const RoleDescrMap& aEntry) const {
|
||||
return [mRole compare:aEntry.role];
|
||||
}
|
||||
};
|
||||
|
||||
- (NSString*)roleDescription
|
||||
{
|
||||
if (mRole == roles::DOCUMENT)
|
||||
|
@ -492,30 +514,13 @@ GetClosestInterestingAccessible(id anObject)
|
|||
|
||||
NSString* subrole = [self subrole];
|
||||
|
||||
if ((mRole == roles::LISTITEM) && [subrole isEqualToString:@"AXTerm"])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("term"));
|
||||
if ((mRole == roles::PARAGRAPH) && [subrole isEqualToString:@"AXDefinition"])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("definition"));
|
||||
|
||||
NSString* role = [self role];
|
||||
|
||||
// the WAI-ARIA Landmarks
|
||||
if ([role isEqualToString:NSAccessibilityGroupRole]) {
|
||||
if ([subrole isEqualToString:@"AXLandmarkBanner"])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("banner"));
|
||||
if ([subrole isEqualToString:@"AXLandmarkComplementary"])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("complementary"));
|
||||
if ([subrole isEqualToString:@"AXLandmarkContentInfo"])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("content"));
|
||||
if ([subrole isEqualToString:@"AXLandmarkMain"])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("main"));
|
||||
if ([subrole isEqualToString:@"AXLandmarkNavigation"])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("navigation"));
|
||||
if ([subrole isEqualToString:@"AXLandmarkSearch"])
|
||||
return utils::LocalizedString(NS_LITERAL_STRING("search"));
|
||||
size_t idx = 0;
|
||||
if (BinarySearchIf(sRoleDescrMap, 0, ArrayLength(sRoleDescrMap),
|
||||
RoleDescrComparator(subrole), &idx)) {
|
||||
return utils::LocalizedString(sRoleDescrMap[idx].description);
|
||||
}
|
||||
|
||||
return NSAccessibilityRoleDescription(role, subrole);
|
||||
return NSAccessibilityRoleDescription([self role], subrole);
|
||||
}
|
||||
|
||||
- (NSString*)title
|
||||
|
|
|
@ -108,6 +108,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
|
|||
testAttrs("tel", {"text-input-type" : "tel"}, true);
|
||||
testAttrs("url", {"text-input-type" : "url"}, true);
|
||||
|
||||
// ARIA
|
||||
testAttrs("searchbox", {"text-input-type" : "search"}, true);
|
||||
|
||||
// html
|
||||
testAttrs("radio", {"checkable" : "true"}, true);
|
||||
testAttrs("checkbox", {"checkable" : "true"}, true);
|
||||
|
@ -183,6 +186,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
|
|||
title="aria-hidden false value shouldn't be exposed via object attributes">
|
||||
Mozilla Bug 838407
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1121518"
|
||||
title="ARIA 1.1: Support role 'searchbox'">
|
||||
Mozilla Bug 1121518
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
|
@ -242,6 +250,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
|
|||
<input id="search" type="search"/>
|
||||
<input id="tel" type="tel"/>
|
||||
<input id="url" type="url"/>
|
||||
<div id="searchbox" role="searchbox"></div>
|
||||
|
||||
<!-- html -->
|
||||
<input id="radio" type="radio"/>
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
testAttrs("article", {"xml-roles" : "article"}, true);
|
||||
testAttrs("main_element", {"xml-roles" : "main"}, true);
|
||||
|
||||
testAttrs("search", {"xml-roles" : "searchbox"}, true);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -78,6 +80,11 @@
|
|||
title="modify HTML5 header and footer accessibility API mapping">
|
||||
Bug 849624
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1121518"
|
||||
title="ARIA 1.1: Support role 'searchbox'">
|
||||
Bug 1121518
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
|
@ -101,5 +108,6 @@
|
|||
<article id="article">article</article>
|
||||
<main id="main_element">another main area</main>
|
||||
|
||||
<input id="search" type="search"/>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -165,22 +165,22 @@
|
|||
</a><br>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=648133"
|
||||
title="fire state change event for aria-busy"
|
||||
title="fire state change event for aria-busy">
|
||||
Mozilla Bug 648133
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=467143"
|
||||
title="mixed state change event is fired for focused accessible only"
|
||||
title="mixed state change event is fired for focused accessible only">
|
||||
Mozilla Bug 467143
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=989958"
|
||||
title="Pressed state is not exposed on a button element with aria-pressed attribute"
|
||||
title="Pressed state is not exposed on a button element with aria-pressed attribute">
|
||||
Mozilla Bug 989958
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1136563"
|
||||
title="Support ARIA 1.1 switch role"
|
||||
title="Support ARIA 1.1 switch role">
|
||||
Mozilla Bug 1136563
|
||||
</a>
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
testRole("aria_row", ROLE_ROW);
|
||||
testRole("aria_rowheader", ROLE_ROWHEADER);
|
||||
testRole("aria_scrollbar", ROLE_SCROLLBAR);
|
||||
testRole("aria_searchbox", ROLE_ENTRY);
|
||||
testRole("aria_separator", ROLE_SEPARATOR);
|
||||
testRole("aria_slider", ROLE_SLIDER);
|
||||
testRole("aria_spinbutton", ROLE_SPINBUTTON);
|
||||
|
@ -181,9 +182,14 @@
|
|||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1136563"
|
||||
title="Support ARIA 1.1 switch role"
|
||||
title="Support ARIA 1.1 switch role">
|
||||
Bug 1136563
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1121518"
|
||||
title="Support ARIA 1.1 searchbox role">
|
||||
Bug 1121518
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
|
@ -227,6 +233,7 @@
|
|||
<span id="aria_row" role="row"/>
|
||||
<span id="aria_rowheader" role="rowheader"/>
|
||||
<span id="aria_scrollbar" role="scrollbar"/>
|
||||
<span id="aria_searchbox" role="textbox"/>
|
||||
<span id="aria_separator" role="separator"/>
|
||||
<span id="aria_slider" role="slider"/>
|
||||
<span id="aria_spinbutton" role="spinbutton"/>
|
||||
|
|
|
@ -349,12 +349,12 @@
|
|||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=989958"
|
||||
title="Pressed state is not exposed on a button element with aria-pressed attribute"
|
||||
title="Pressed state is not exposed on a button element with aria-pressed attribute">
|
||||
Mozilla Bug 989958
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1136563"
|
||||
title="Support ARIA 1.1 switch role"
|
||||
title="Support ARIA 1.1 switch role">
|
||||
Mozilla Bug 1136563
|
||||
</a>
|
||||
|
||||
|
|
|
@ -123,11 +123,6 @@ SettingsListener.observe('language.current', 'en-US', function(value) {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Debug flag
|
||||
SettingsListener.observe('ril.debugging.enabled', false, function(value) {
|
||||
Services.prefs.setBoolPref('ril.debugging.enabled', value);
|
||||
});
|
||||
})();
|
||||
|
||||
//=================== DeviceInfo ====================
|
||||
|
@ -528,6 +523,7 @@ let settingsToObserve = {
|
|||
'layers.effect.grayscale': false,
|
||||
'layers.effect.contrast': "0.0",
|
||||
'privacy.donottrackheader.enabled': false,
|
||||
'ril.debugging.enabled': false,
|
||||
'ril.radio.disabled': false,
|
||||
'ril.mms.requestReadReport.enabled': {
|
||||
prefName: 'dom.mms.requestReadReport',
|
||||
|
|
|
@ -27,4 +27,4 @@ skip-if = toolkit != "gonk"
|
|||
|
||||
[test_logshake_gonk.js]
|
||||
# only run on b2g builds due to requiring b2g-specific log files to exist
|
||||
skip-if = ((toolkit != "gonk") || ((toolkit == "gonk") && (debug == true))) # bug 1125989: disabled because of race condition in OS.File.makeDir
|
||||
skip-if = (toolkit != "gonk")
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f34ce82a840ad3c0aed3bfff18517b3f6a0eb37f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="c8ed1085a67490a1ecd7f275e5de9487e1b93b1d"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f34ce82a840ad3c0aed3bfff18517b3f6a0eb37f"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c8ed1085a67490a1ecd7f275e5de9487e1b93b1d"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f34ce82a840ad3c0aed3bfff18517b3f6a0eb37f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="c8ed1085a67490a1ecd7f275e5de9487e1b93b1d"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1ddea3133e0807350326cee5dcf0d06fad00c08"/>
|
||||
|
@ -135,7 +135,7 @@
|
|||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c5f8d282efe4a4e8b1e31a37300944e338e60e4f"/>
|
||||
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9f28c4faea3b2f01db227b2467b08aeba96d9bec"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="84395037a7a04546e8ef7cb81572eb516b85562b"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="2eac5a8f931ab1c4aa41be7ac02db8a821df6efc"/>
|
||||
<project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/>
|
||||
<project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
|
||||
</manifest>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f34ce82a840ad3c0aed3bfff18517b3f6a0eb37f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="c8ed1085a67490a1ecd7f275e5de9487e1b93b1d"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f34ce82a840ad3c0aed3bfff18517b3f6a0eb37f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="c8ed1085a67490a1ecd7f275e5de9487e1b93b1d"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -145,6 +145,7 @@
|
|||
<!-- external/qemu for emulator-l need to be updated in bug-1121378 -->
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="7639c5c496ffd207bb627f2a59b2c5203ae6fefc"/>
|
||||
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="16abda2258c9aa1ed78f00bb0a9b2b43b4cb919e"/>
|
||||
<project name="platform/development" path="development" revision="7ec1ce5e75f943a4a673aa12d8177d5cf2c0a4cf"/>
|
||||
<project name="android-sdk" path="sdk" remote="b2g" revision="94704df982a90d2ab74bd620d54155d148c415b2"/>
|
||||
<!-- hardware-ril for emulator-l need to be updated in bug-1113054 -->
|
||||
<project name="platform/hardware/ril" path="hardware/ril" revision="71dfa8228ad0d6cdf6bac0426ac59404ab74b7f3"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f34ce82a840ad3c0aed3bfff18517b3f6a0eb37f"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="c8ed1085a67490a1ecd7f275e5de9487e1b93b1d"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f34ce82a840ad3c0aed3bfff18517b3f6a0eb37f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="c8ed1085a67490a1ecd7f275e5de9487e1b93b1d"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -146,7 +146,7 @@
|
|||
<project name="platform/hardware/ril" path="hardware/ril" revision="12b1977cc704b35f2e9db2bb423fa405348bc2f3"/>
|
||||
<project name="platform/system/bluetooth" path="system/bluetooth" revision="985bf15264d865fe7b9c5b45f61c451cbaafa43d"/>
|
||||
<project name="platform/system/core" path="system/core" revision="42839aedcf70bf6bc92a3b7ea4a5cc9bf9aef3f9"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="84395037a7a04546e8ef7cb81572eb516b85562b"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="2eac5a8f931ab1c4aa41be7ac02db8a821df6efc"/>
|
||||
<project name="platform/system/qcom" path="system/qcom" revision="63e3f6f176caad587d42bba4c16b66d953fb23c2"/>
|
||||
<project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="d8952a42771045fca73ec600e2b42a4c7129d723"/>
|
||||
<project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4c187c1f3a0dffd8e51a961735474ea703535b99"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f34ce82a840ad3c0aed3bfff18517b3f6a0eb37f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="c8ed1085a67490a1ecd7f275e5de9487e1b93b1d"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1ddea3133e0807350326cee5dcf0d06fad00c08"/>
|
||||
|
@ -145,7 +145,7 @@
|
|||
<project name="platform/hardware/ril" path="hardware/ril" revision="c4e2ac95907a5519a0e09f01a0d8e27fec101af0"/>
|
||||
<project name="platform/system/bluetooth" path="system/bluetooth" revision="e1eb226fa3ad3874ea7b63c56a9dc7012d7ff3c2"/>
|
||||
<project name="platform/system/core" path="system/core" revision="adc485d8755af6a61641d197de7cfef667722580"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="84395037a7a04546e8ef7cb81572eb516b85562b"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="2eac5a8f931ab1c4aa41be7ac02db8a821df6efc"/>
|
||||
<project name="platform/system/qcom" path="system/qcom" revision="1cdab258b15258b7f9657da70e6f06ebd5a2fc25"/>
|
||||
<project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4ae5df252123591d5b941191790e7abed1bce5a4"/>
|
||||
<project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="ce18b47b4a4f93a581d672bbd5cb6d12fe796ca9"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "f34ce82a840ad3c0aed3bfff18517b3f6a0eb37f",
|
||||
"git_revision": "c8ed1085a67490a1ecd7f275e5de9487e1b93b1d",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "c00390d70e15726ba3e4c50bd2353fbf991f25c9",
|
||||
"revision": "45fe49a5560cdaa07920739af65722a63b2de4f9",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f34ce82a840ad3c0aed3bfff18517b3f6a0eb37f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="c8ed1085a67490a1ecd7f275e5de9487e1b93b1d"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1ddea3133e0807350326cee5dcf0d06fad00c08"/>
|
||||
|
@ -130,7 +130,7 @@
|
|||
<project name="device-mako" path="device/lge/mako" remote="b2g" revision="78d17f0c117f0c66dd55ee8d5c5dde8ccc93ecba"/>
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
|
||||
<project name="device/lge/mako-kernel" path="device/lge/mako-kernel" revision="d1729e53d71d711c8fde25eab8728ff2b9b4df0e"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="84395037a7a04546e8ef7cb81572eb516b85562b"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="2eac5a8f931ab1c4aa41be7ac02db8a821df6efc"/>
|
||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
|
||||
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
|
||||
<project name="platform/hardware/broadcom/wlan" path="hardware/broadcom/wlan" revision="0e1929fa3aa38bf9d40e9e953d619fab8164c82e"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f34ce82a840ad3c0aed3bfff18517b3f6a0eb37f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="c8ed1085a67490a1ecd7f275e5de9487e1b93b1d"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2e85143db5d5f6edc4c2b97263c02b558fee757e"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -157,5 +157,5 @@
|
|||
<project name="platform/hardware/qcom/sensors" path="hardware/qcom/sensors" revision="3724fd91ef5183684d97e2bf1d7ff948faabe090"/>
|
||||
<project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="2e54754cc0529d26ccac37ed291600048adbf6c0"/>
|
||||
<project name="platform/hardware/ril" path="hardware/ril" revision="71dfa8228ad0d6cdf6bac0426ac59404ab74b7f3"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="84395037a7a04546e8ef7cb81572eb516b85562b"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="2eac5a8f931ab1c4aa41be7ac02db8a821df6efc"/>
|
||||
</manifest>
|
||||
|
|
|
@ -462,23 +462,28 @@
|
|||
@BINPATH@/components/CellBroadcastService.manifest
|
||||
@BINPATH@/components/MmsService.js
|
||||
@BINPATH@/components/MmsService.manifest
|
||||
@BINPATH@/components/MobileConnectionService.js
|
||||
@BINPATH@/components/MobileConnectionService.manifest
|
||||
@BINPATH@/components/MobileMessageDatabaseService.js
|
||||
@BINPATH@/components/MobileMessageDatabaseService.manifest
|
||||
#ifndef DISABLE_MOZ_RIL_GEOLOC
|
||||
@BINPATH@/components/MobileConnectionService.js
|
||||
@BINPATH@/components/MobileConnectionService.manifest
|
||||
@BINPATH@/components/RadioInterfaceLayer.js
|
||||
@BINPATH@/components/RadioInterfaceLayer.manifest
|
||||
@BINPATH@/components/RILContentHelper.js
|
||||
@BINPATH@/components/RILSystemMessengerHelper.js
|
||||
@BINPATH@/components/RILSystemMessengerHelper.manifest
|
||||
@BINPATH@/components/SmsService.js
|
||||
@BINPATH@/components/SmsService.manifest
|
||||
#endif
|
||||
@BINPATH@/components/RILContentHelper.js
|
||||
@BINPATH@/components/RILContentHelper.manifest
|
||||
@BINPATH@/components/RILSystemMessengerHelper.js
|
||||
@BINPATH@/components/RILSystemMessengerHelper.manifest
|
||||
@BINPATH@/components/TelephonyAudioService.js
|
||||
@BINPATH@/components/TelephonyAudioService.manifest
|
||||
#ifndef DISABLE_MOZ_RIL_GEOLOC
|
||||
@BINPATH@/components/TelephonyService.js
|
||||
@BINPATH@/components/TelephonyService.manifest
|
||||
@BINPATH@/components/VoicemailService.js
|
||||
@BINPATH@/components/VoicemailService.manifest
|
||||
#endif
|
||||
#endif // MOZ_WIDGET_GONK && MOZ_B2G_RIL
|
||||
|
||||
#ifndef MOZ_WIDGET_GONK
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1423697587000">
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1424991539000">
|
||||
<emItems>
|
||||
<emItem blockID="i58" id="webmaster@buzzzzvideos.info">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
|
@ -72,6 +72,14 @@
|
|||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i862" id="{CA8C84C6-3918-41b1-BE77-049B2BDD887C}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
<pref>browser.startup.homepage</pref>
|
||||
<pref>browser.search.defaultenginename</pref>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i430" id="1chtw@facebook.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
|
@ -121,8 +129,8 @@
|
|||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i810" id="{41339ee8-61ed-489d-b049-01e41fd5d7e0}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
<emItem blockID="i364" id="{FE1DEEEA-DB6D-44b8-83F0-34FC0F9D1052}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
|
@ -387,7 +395,7 @@
|
|||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i404" id="{a9bb9fa0-4122-4c75-bd9a-bc27db3f9155}">
|
||||
<emItem blockID="i860" id="PrivDog@AdTrustMedia.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
|
@ -741,6 +749,12 @@
|
|||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i340" id="chiang@programmer.net">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i99" id="pfzPXmnzQRXX6@2iABkVe.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
|
@ -1019,6 +1033,12 @@
|
|||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i91" id="crossriderapp4926@crossrider.com">
|
||||
<versionRange minVersion="0" maxVersion="0.81.43" severity="1">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i700" id="2bbadf1f-a5af-499f-9642-9942fcdb7c76@f05a14cc-8842-4eee-be17-744677a917ed.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
|
@ -1960,8 +1980,8 @@
|
|||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i364" id="{FE1DEEEA-DB6D-44b8-83F0-34FC0F9D1052}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
<emItem blockID="i810" id="{41339ee8-61ed-489d-b049-01e41fd5d7e0}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
|
@ -2084,8 +2104,8 @@
|
|||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i340" id="chiang@programmer.net">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
<emItem blockID="i866" id="faststartff@gmail.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
|
@ -2157,11 +2177,25 @@
|
|||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i91" id="crossriderapp4926@crossrider.com">
|
||||
<versionRange minVersion="0" maxVersion="0.81.43" severity="1">
|
||||
<emItem blockID="i404" id="{a9bb9fa0-4122-4c75-bd9a-bc27db3f9155}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i868" id="{6e7f6f9f-8ce6-4611-add2-05f0f7049ee6}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i864" id="{0A92F062-6AC6-8180-5881-B6E0C0DC2CC5}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
<pref>browser.startup.homepage</pref>
|
||||
<pref>browser.search.defaultenginename</pref>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i814" id="liiros@facebook.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
|
|
|
@ -1760,12 +1760,19 @@ pref("plain_text.wrap_long_lines", true);
|
|||
pref("dom.debug.propagate_gesture_events_through_content", false);
|
||||
|
||||
// The request URL of the GeoLocation backend.
|
||||
#ifdef RELEASE_BUILD
|
||||
pref("geo.wifi.uri", "https://www.googleapis.com/geolocation/v1/geolocate?key=%GOOGLE_API_KEY%");
|
||||
#else
|
||||
pref("geo.wifi.uri", "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%");
|
||||
#endif
|
||||
|
||||
// On Mac, the default geo provider is corelocation.
|
||||
#ifdef XP_MACOSX
|
||||
#ifdef RELEASE_BUILD
|
||||
pref("geo.provider.use_corelocation", false);
|
||||
#else
|
||||
pref("geo.provider.use_corelocation", true);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Necko IPC security checks only needed for app isolation for cookies/cache/etc:
|
||||
// currently irrelevant for desktop e10s
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.. _healthreport_dataformat:
|
||||
.. _sslerrorreport_dataformat:
|
||||
|
||||
==============
|
||||
Payload Format
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.. _sslerrorreport
|
||||
.. _sslerrorreport:
|
||||
|
||||
===================
|
||||
SSL Error Reporting
|
||||
|
|
|
@ -981,7 +981,7 @@
|
|||
// Strip out any null bytes in the content title, since the
|
||||
// underlying widget implementations of nsWindow::SetTitle pass
|
||||
// null-terminated strings to system APIs.
|
||||
var docTitle = aBrowser.contentTitle.replace("\0", "", "g");
|
||||
var docTitle = aBrowser.contentTitle.replace(/\0/g, "");
|
||||
|
||||
if (!docTitle)
|
||||
docTitle = docElement.getAttribute("titledefault");
|
||||
|
@ -3229,8 +3229,7 @@
|
|||
addonInfo: aMessage.data.addonInfo };
|
||||
let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
|
||||
let event = gContextMenuContentData.event;
|
||||
let pos = browser.mapScreenCoordinatesFromContent(event.screenX, event.screenY);
|
||||
popup.openPopupAtScreen(pos.x, pos.y, true);
|
||||
popup.openPopupAtScreen(event.screenX, event.screenY, true);
|
||||
break;
|
||||
}
|
||||
case "DOMWebNotificationClicked": {
|
||||
|
|
|
@ -15,7 +15,7 @@ var gTests = [
|
|||
|
||||
{ desc: "Searchbar replaces newlines with spaces",
|
||||
element: document.getElementById('searchbar'),
|
||||
expected: kTestString.replace('\n',' ','g')
|
||||
expected: kTestString.replace(/\n/g,' ')
|
||||
},
|
||||
|
||||
];
|
||||
|
|
|
@ -323,7 +323,7 @@ DistributionCustomizer.prototype = {
|
|||
for (let key in enumerate(this._ini.getKeys("LocalizablePreferences"))) {
|
||||
try {
|
||||
let value = eval(this._ini.getString("LocalizablePreferences", key));
|
||||
value = value.replace("%LOCALE%", this._locale, "g");
|
||||
value = value.replace(/%LOCALE%/g, this._locale);
|
||||
localizedStr.data = "data:text/plain," + key + "=" + value;
|
||||
defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
|
||||
} catch (e) { /* ignore bad prefs and move on */ }
|
||||
|
|
|
@ -3276,7 +3276,7 @@ let SessionStoreInternal = {
|
|||
|
||||
// By creating a regex we reduce overhead and there is only one loop pass
|
||||
// through either array (cookieHosts and aWinState.cookies).
|
||||
let hosts = Object.keys(cookieHosts).join("|").replace("\\.", "\\.", "g");
|
||||
let hosts = Object.keys(cookieHosts).join("|").replace(/\./g, "\\.");
|
||||
// If we don't actually have any hosts, then we don't want to do anything.
|
||||
if (!hosts.length)
|
||||
return;
|
||||
|
|
|
@ -100,7 +100,7 @@ TabMatcher.prototype = {
|
|||
tabs = tabs.filter(function TabMatcher__filterAndSortForMatches_filter(tab) {
|
||||
let name = TabUtils.nameOf(tab);
|
||||
let url = TabUtils.URLOf(tab);
|
||||
return name.match(self.term, "i") || url.match(self.term, "i");
|
||||
return name.match(new RegExp(self.term, "i")) || url.match(new RegExp(self.term, "i"));
|
||||
});
|
||||
|
||||
tabs.sort(function TabMatcher__filterAndSortForMatches_sort(x, y) {
|
||||
|
@ -121,7 +121,7 @@ TabMatcher.prototype = {
|
|||
return tabs.filter(function TabMatcher__filterForUnmatches_filter(tab) {
|
||||
let name = tab.$tabTitle[0].textContent;
|
||||
let url = TabUtils.URLOf(tab);
|
||||
return !name.match(self.term, "i") && !url.match(self.term, "i");
|
||||
return !name.match(new RegExp(self.term, "i")) && !url.match(new RegExp(self.term, "i"));
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@ this.BingTranslator.prototype = {
|
|||
if (root.isSimpleRoot) {
|
||||
// Workaround for Bing's service problem in which "&" chars in
|
||||
// plain-text TranslationItems are double-escaped.
|
||||
result = result.replace("&", "&", "g");
|
||||
result = result.replace(/&/g, "&");
|
||||
}
|
||||
|
||||
root.parseResult(result);
|
||||
|
@ -422,11 +422,11 @@ let BingTokenManager = {
|
|||
*/
|
||||
function escapeXML(aStr) {
|
||||
return aStr.toString()
|
||||
.replace("&", "&", "g")
|
||||
.replace('"', """, "g")
|
||||
.replace("'", "'", "g")
|
||||
.replace("<", "<", "g")
|
||||
.replace(">", ">", "g");
|
||||
.replace(/&/g, "&")
|
||||
.replace(/\"/g, """)
|
||||
.replace(/\'/g, "'")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,7 +6,7 @@ UI Telemetry sends its data as a JSON blob. This document describes the differen
|
|||
of the JSON blob.
|
||||
|
||||
``toolbars``
|
||||
------------
|
||||
============
|
||||
|
||||
This tracks the state of the user's UI customizations. It has the following properties:
|
||||
|
||||
|
@ -34,15 +34,16 @@ This tracks the state of the user's UI customizations. It has the following prop
|
|||
- ``countableEvents`` - please refer to the next section.
|
||||
- ``durations`` - an object mapping descriptions to duration records, which records the amount of
|
||||
time a user spent doing something. Currently only has one property:
|
||||
- ``customization`` - how long a user spent customizing the browser. This is an array of
|
||||
objects, where each object has a ``duration`` property indicating the time in milliseconds,
|
||||
and a ``bucket`` property indicating a bucket in which the duration info falls.
|
||||
|
||||
- ``customization`` - how long a user spent customizing the browser. This is an array of
|
||||
objects, where each object has a ``duration`` property indicating the time in milliseconds,
|
||||
and a ``bucket`` property indicating a bucket in which the duration info falls.
|
||||
|
||||
|
||||
.. _UITelemetry_countableEvents:
|
||||
|
||||
``countableEvents``
|
||||
-------------------
|
||||
===================
|
||||
|
||||
Countable events are stored under the ``toolbars`` section. They count the number of times certain
|
||||
events happen. No timing or other correlating information is stored - purely the number of times
|
||||
|
@ -66,23 +67,27 @@ Each bucket is an object with the following properties:
|
|||
or ``other``, depending on the kind of item clicked. Note that this is not tracked on OS X, where
|
||||
we can't listen for these events because of the global menubar.
|
||||
- ``click-bookmarks-menu-button`` is also similar, with the item IDs being replaced by:
|
||||
- ``menu`` for clicks on the 'menu' part of the item;
|
||||
- ``add`` for clicks that add a bookmark;
|
||||
- ``edit`` for clicks that open the panel to edit an existing bookmark;
|
||||
- ``in-panel`` for clicks when the button is in the menu panel, and clicking it does none of the
|
||||
|
||||
- ``menu`` for clicks on the 'menu' part of the item;
|
||||
- ``add`` for clicks that add a bookmark;
|
||||
- ``edit`` for clicks that open the panel to edit an existing bookmark;
|
||||
- ``in-panel`` for clicks when the button is in the menu panel, and clicking it does none of the
|
||||
above;
|
||||
- ``customize`` tracks different types of customization events without the ``left``, ``middle`` and
|
||||
``right`` distinctions. The different events are the following, with each storing a count of the
|
||||
number of times they occurred:
|
||||
- ``start`` counts the number of times the user starts customizing;
|
||||
- ``add`` counts the number of times an item is added somewhere from the palette;
|
||||
- ``move`` counts the number of times an item is moved somewhere else (but not to the palette);
|
||||
- ``remove`` counts the number of times an item is removed to the palette;
|
||||
- ``reset`` counts the number of times the 'restore defaults' button is used;
|
||||
|
||||
- ``start`` counts the number of times the user starts customizing;
|
||||
- ``add`` counts the number of times an item is added somewhere from the palette;
|
||||
- ``move`` counts the number of times an item is moved somewhere else (but not to the palette);
|
||||
- ``remove`` counts the number of times an item is removed to the palette;
|
||||
- ``reset`` counts the number of times the 'restore defaults' button is used;
|
||||
- ``search`` is an object tracking searches of various types, keyed off the search
|
||||
location, storing a number indicating how often the respective type of search
|
||||
has happened.
|
||||
|
||||
- There are also two special keys that mean slightly different things.
|
||||
|
||||
- ``urlbar-keyword`` records searches that would have been an invalid-protocol
|
||||
error, but are now keyword searches. They are also counted in the ``urlbar``
|
||||
keyword (along with all the other urlbar searches).
|
||||
|
@ -93,7 +98,8 @@ Each bucket is an object with the following properties:
|
|||
|
||||
|
||||
``UITour``
|
||||
----------
|
||||
==========
|
||||
|
||||
The UITour API provides ways for pages on trusted domains to safely interact with the browser UI and request it to perform actions such as opening menus and showing highlights over the browser chrome - for the purposes of interactive tours. We track some usage of this API via the ``UITour`` object in the UI Telemetry output.
|
||||
|
||||
Each page is able to register itself with an identifier, a ``Page ID``. A list of Page IDs that have been seen over the last 8 weeks is available via ``seenPageIDs``.
|
||||
|
@ -107,7 +113,8 @@ Page IDs are also used to identify buckets for :ref:`UITelemetry_countableEvents
|
|||
|
||||
|
||||
``contextmenu``
|
||||
---------------
|
||||
===============
|
||||
|
||||
We track context menu interactions to figure out which ones are most often used and/or how
|
||||
effective they are. In the ``contextmenu`` object, we first store things per-bucket. Next, we
|
||||
divide the following different context menu situations:
|
||||
|
|
|
@ -761,7 +761,7 @@ var Browser = {
|
|||
hasher.updateFromStream(stringStream, -1);
|
||||
let hashASCII = hasher.finish(true);
|
||||
// Replace '/' with a valid filesystem character
|
||||
return ("FFTileID_" + hashASCII).replace('/', '_', 'g');
|
||||
return ("FFTileID_" + hashASCII).replace(/\//g, '_');
|
||||
},
|
||||
|
||||
unpinSite: function browser_unpinSite() {
|
||||
|
|
|
@ -193,7 +193,7 @@ BrowserCLH.prototype = {
|
|||
if (searchParam) {
|
||||
var ss = Components.classes["@mozilla.org/browser/search-service;1"]
|
||||
.getService(nsIBrowserSearchService);
|
||||
var submission = ss.defaultEngine.getSubmission(searchParam.replace("\"", "", "g"));
|
||||
var submission = ss.defaultEngine.getSubmission(searchParam.replace(/\"/g, ""));
|
||||
uris.push(submission.uri);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
ICON_FILES := ../shared/icon.png
|
||||
ICON_DEST = $(FINAL_TARGET)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
|
||||
INSTALL_TARGETS += ICON
|
||||
|
||||
# By default, the pre-processor used for jar.mn will use "%" as a marker for ".css" files and "#"
|
||||
# otherwise. This falls apart when a file using one marker needs to include a file with the other
|
||||
# marker since the pre-processor instructions in the included file will not be processed. The
|
||||
# following SVG files need to include a file which uses "%" as the marker so we invoke the pre-
|
||||
# processor ourselves here with the marker specified. The resulting SVG files will get packaged by
|
||||
# the processing of the jar file in this directory.
|
||||
tab-selected-svg: $(srcdir)/../shared/tab-selected.svg
|
||||
$(call py_action,preprocessor, \
|
||||
--marker % -D TAB_SIDE=start \
|
||||
$(ACDEFINES) \
|
||||
$(srcdir)/../shared/tab-selected.svg -o tab-selected-start.svg)
|
||||
$(call py_action,preprocessor, \
|
||||
--marker % -D TAB_SIDE=end \
|
||||
$(ACDEFINES) \
|
||||
$(srcdir)/../shared/tab-selected.svg -o tab-selected-end.svg)
|
||||
|
||||
.PHONY: tab-selected-svg
|
||||
|
||||
export:: tab-selected-svg
|
|
@ -7,3 +7,5 @@
|
|||
DIRS += ['communicator']
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
include('../tab-svgs.mozbuild')
|
||||
|
|
|
@ -12,3 +12,5 @@ elif toolkit in ('gtk2', 'gtk3', 'qt'):
|
|||
DIRS += ['linux']
|
||||
else:
|
||||
DIRS += ['windows']
|
||||
|
||||
FINAL_TARGET_FILES.extensions['{972ce4c6-7e08-4474-a285-3208198ce6fd}'] += ['shared/icon.png']
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
ICON_FILES := ../shared/icon.png
|
||||
ICON_DEST = $(FINAL_TARGET)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
|
||||
INSTALL_TARGETS += ICON
|
||||
|
||||
# By default, the pre-processor used for jar.mn will use "%" as a marker for ".css" files and "#"
|
||||
# otherwise. This falls apart when a file using one marker needs to include a file with the other
|
||||
# marker since the pre-processor instructions in the included file will not be processed. The
|
||||
# following SVG files need to include a file which uses "%" as the marker so we invoke the pre-
|
||||
# processor ourselves here with the marker specified. The resulting SVG files will get packaged by
|
||||
# the processing of the jar file in this directory.
|
||||
tab-selected-svg: $(srcdir)/../shared/tab-selected.svg
|
||||
$(call py_action,preprocessor, \
|
||||
--marker % -D TAB_SIDE=start \
|
||||
$(ACDEFINES) \
|
||||
$(srcdir)/../shared/tab-selected.svg -o tab-selected-start.svg)
|
||||
$(call py_action,preprocessor, \
|
||||
--marker % -D TAB_SIDE=end \
|
||||
$(ACDEFINES) \
|
||||
$(srcdir)/../shared/tab-selected.svg -o tab-selected-end.svg)
|
||||
|
||||
.PHONY: tab-selected-svg
|
||||
|
||||
export:: tab-selected-svg
|
|
@ -7,3 +7,5 @@
|
|||
DIRS += ['communicator']
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
include('../tab-svgs.mozbuild')
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
#!/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/.
|
||||
|
||||
import buildconfig
|
||||
|
||||
from mozbuild.preprocessor import preprocess
|
||||
|
||||
# By default, the pre-processor used for jar.mn will use "%" as a marker
|
||||
# for ".css" files and "#" otherwise. This falls apart when a file using
|
||||
# one marker needs to include a file with the other marker since the
|
||||
# pre-processor instructions in the included file will not be
|
||||
# processed. The following SVG files need to include a file which uses
|
||||
# "%" as the marker so we invoke the pre- processor ourselves here with
|
||||
# the marker specified. The resulting SVG files will get packaged by the
|
||||
# processing of the jar file in the appropriate directory.
|
||||
def _do_preprocessing(output_svg, input_svg_file, additional_defines):
|
||||
additional_defines.update(buildconfig.defines)
|
||||
preprocess(output=output_svg,
|
||||
includes=[input_svg_file],
|
||||
marker='%',
|
||||
defines=additional_defines)
|
||||
|
||||
def tab_side_start(output_svg, input_svg_file):
|
||||
_do_preprocessing(output_svg, input_svg_file, {'TAB_SIDE': 'start'})
|
||||
|
||||
def tab_side_end(output_svg, input_svg_file):
|
||||
_do_preprocessing(output_svg, input_svg_file, {'TAB_SIDE': 'end'})
|
||||
|
||||
def aero_tab_side_start(output_svg, input_svg_file):
|
||||
_do_preprocessing(output_svg, input_svg_file,
|
||||
{'TAB_SIDE': 'start',
|
||||
'WINDOWS_AERO': 1})
|
||||
|
||||
def aero_tab_side_end(output_svg, input_svg_file):
|
||||
_do_preprocessing(output_svg, input_svg_file,
|
||||
{'TAB_SIDE': 'end',
|
||||
'WINDOWS_AERO': 1})
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=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/.
|
||||
|
||||
script = TOPSRCDIR + '/browser/themes/preprocess-tab-svgs.py'
|
||||
input = [TOPSRCDIR + '/browser/themes/shared/tab-selected.svg']
|
||||
|
||||
# Context variables can't be used inside functions, so hack around that.
|
||||
generated_files = GENERATED_FILES
|
||||
|
||||
def generate_svg(svg_name, script_function):
|
||||
global generated_files
|
||||
generated_files += [svg_name]
|
||||
svg = generated_files[svg_name]
|
||||
svg.script = script + ':' + script_function
|
||||
svg.inputs = input
|
||||
|
||||
generate_svg('tab-selected-end.svg', 'tab_side_end')
|
||||
generate_svg('tab-selected-start.svg', 'tab_side_start')
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
# Same as above, but for aero.
|
||||
generate_svg('tab-selected-end-aero.svg', 'aero_tab_side_end')
|
||||
generate_svg('tab-selected-start-aero.svg', 'aero_tab_side_start')
|
|
@ -1,36 +0,0 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
ICON_FILES := ../shared/icon.png
|
||||
ICON_DEST = $(FINAL_TARGET)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
|
||||
INSTALL_TARGETS += ICON
|
||||
|
||||
# By default, the pre-processor used for jar.mn will use "%" as a marker for ".css" files and "#"
|
||||
# otherwise. This falls apart when a file using one marker needs to include a file with the other
|
||||
# marker since the pre-processor instructions in the included file will not be processed. The
|
||||
# following SVG files need to include a file which uses "%" as the marker so we invoke the pre-
|
||||
# processor ourselves here with the marker specified. The resulting SVG files will get packaged by
|
||||
# the processing of the jar file in this directory.
|
||||
tab-selected-svg: $(srcdir)/../shared/tab-selected.svg
|
||||
$(call py_action,preprocessor, \
|
||||
--marker % -D TAB_SIDE=start \
|
||||
$(ACDEFINES) \
|
||||
$(srcdir)/../shared/tab-selected.svg -o tab-selected-start.svg)
|
||||
$(call py_action,preprocessor, \
|
||||
--marker % -D TAB_SIDE=end \
|
||||
$(ACDEFINES) \
|
||||
$(srcdir)/../shared/tab-selected.svg -o tab-selected-end.svg)
|
||||
# Same as above for aero.
|
||||
$(call py_action,preprocessor, \
|
||||
--marker % -D TAB_SIDE=start -D WINDOWS_AERO \
|
||||
$(ACDEFINES) \
|
||||
$(srcdir)/../shared/tab-selected.svg -o tab-selected-start-aero.svg)
|
||||
$(call py_action,preprocessor, \
|
||||
--marker % -D TAB_SIDE=end -D WINDOWS_AERO \
|
||||
$(ACDEFINES) \
|
||||
$(srcdir)/../shared/tab-selected.svg -o tab-selected-end-aero.svg)
|
||||
|
||||
.PHONY: tab-selected-svg
|
||||
|
||||
export:: tab-selected-svg
|
|
@ -7,3 +7,5 @@
|
|||
DIRS += ['communicator']
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
include('../tab-svgs.mozbuild')
|
||||
|
|
|
@ -21,6 +21,8 @@ are no conflicting variables in those source files.
|
|||
``SOURCES`` and ``UNIFIED_SOURCES`` are lists which must be appended to, and
|
||||
each append requires the given list to be alphanumerically ordered.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'FirstSource.cpp',
|
||||
'SecondSource.cpp',
|
||||
|
@ -41,6 +43,8 @@ Static Libraries
|
|||
To build a static library, other than defining the source files (see above), one
|
||||
just needs to define a library name with the ``Library`` template.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
Library('foo')
|
||||
|
||||
The library file name will be ``libfoo.a`` on UNIX systems and ``foo.lib`` on
|
||||
|
@ -50,12 +54,16 @@ If the static library needs to aggregate other static libraries, a list of
|
|||
``Library`` names can be added to the ``USE_LIBS`` variable. Like ``SOURCES``, it
|
||||
requires the appended list to be alphanumerically ordered.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
USE_LIBS += ['bar', 'baz']
|
||||
|
||||
If there are multiple directories containing the same ``Library`` name, it is
|
||||
possible to disambiguate by prefixing with the path to the wanted one (relative
|
||||
or absolute):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
USE_LIBS += [
|
||||
'/path/from/topsrcdir/to/bar',
|
||||
'../relative/baz',
|
||||
|
@ -82,6 +90,8 @@ required libraries to ``USE_LIBS`` for the bigger one, it is possible to tell
|
|||
the build system that the library built in the current directory is meant to
|
||||
be linked to that bigger library, with the ``FINAL_LIBRARY`` variable.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
The ``FINAL_LIBRARY`` value must match a unique ``Library`` name somewhere
|
||||
|
@ -98,6 +108,8 @@ Sometimes, we want shared libraries, a.k.a. dynamic libraries. Such libraries
|
|||
are defined similarly to static libraries, using the ``SharedLibrary`` template
|
||||
instead of ``Library``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
SharedLibrary('foo')
|
||||
|
||||
When this template is used, no static library is built. See further below to
|
||||
|
@ -113,6 +125,8 @@ systems.
|
|||
On OSX, one may want to create a special kind of dynamic library: frameworks.
|
||||
This is done with the ``Framework`` template.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
Framework('foo')
|
||||
|
||||
With a ``Framework`` name of ``foo``, the framework file name will be ``foo``.
|
||||
|
@ -126,6 +140,8 @@ Executables
|
|||
Executables, a.k.a. programs, are, in the simplest form, defined with the
|
||||
``Program`` template.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
Program('foobar')
|
||||
|
||||
On UNIX systems, the executable file name will be ``foobar``, while on Windows,
|
||||
|
@ -138,6 +154,8 @@ names.
|
|||
In some cases, we want to create an executable per source file in the current
|
||||
directory, in which case we can use the ``SimplePrograms`` template
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
SimplePrograms([
|
||||
'FirstProgram',
|
||||
'SecondProgram',
|
||||
|
@ -148,6 +166,8 @@ Contrary to ``Program``, which requires corresponding ``SOURCES``, when using
|
|||
corresponding ``sources`` have an extension different from ``.cpp``, it is
|
||||
possible to specify the proper extension:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
SimplePrograms([
|
||||
'ThirdProgram',
|
||||
'FourthProgram',
|
||||
|
@ -170,6 +190,8 @@ Programs and libraries usually need to link with system libraries, such as a
|
|||
widget toolkit, etc. Those required dependencies can be given with the
|
||||
``OS_LIBS`` variable.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
OS_LIBS += [
|
||||
'foo',
|
||||
'bar',
|
||||
|
@ -182,6 +204,8 @@ For convenience with ``pkg-config``, ``OS_LIBS`` can also take linker flags
|
|||
such as ``-L/some/path`` and ``-llib``, such that it is possible to directly
|
||||
assign ``LIBS`` variables from ``CONFIG``, such as:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
OS_LIBS += CONFIG['MOZ_PANGO_LIBS']
|
||||
|
||||
(assuming ``CONFIG['MOZ_PANGO_LIBS']`` is a list, not a string)
|
||||
|
@ -201,6 +225,8 @@ path (like when disambiguating identical ``Library`` names). The same naming
|
|||
rules apply as other uses of ``USE_LIBS``, so only the library name without
|
||||
prefix and suffix shall be given.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
USE_LIBS += [
|
||||
'/path/from/topsrcdir/to/third-party/bar',
|
||||
'../relative/third-party/baz',
|
||||
|
@ -217,6 +243,8 @@ Building both static and shared libraries
|
|||
When both types of libraries are required, one needs to set both
|
||||
``FORCE_SHARED_LIB`` and ``FORCE_STATIC_LIB`` boolean variables.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
FORCE_SHARED_LIB = True
|
||||
FORCE_STATIC_LIB = True
|
||||
|
||||
|
@ -227,6 +255,8 @@ than the name given to the ``Library`` template.
|
|||
The ``STATIC_LIBRARY_NAME`` and ``SHARED_LIBRARY_NAME`` variables can be used
|
||||
to change either the static or the shared library name.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
Library('foo')
|
||||
STATIC_LIBRARY_NAME = 'foo_s'
|
||||
|
||||
|
@ -236,6 +266,8 @@ With the above, on Windows, ``foo_s.lib`` will be the static library,
|
|||
In some cases, for convenience, it is possible to set both
|
||||
``STATIC_LIBRARY_NAME`` and ``SHARED_LIBRARY_NAME``. For example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
Library('mylib')
|
||||
STATIC_LIBRARY_NAME = 'mylib_s'
|
||||
SHARED_LIBRARY_NAME = CONFIG['SHARED_NAME']
|
||||
|
@ -248,6 +280,8 @@ When refering to a ``Library`` name building both types of libraries in
|
|||
it is wanted to link the static version, in which case the ``Library`` name
|
||||
needs to be prefixed with ``static:`` in ``USE_LIBS``
|
||||
|
||||
::
|
||||
|
||||
a/moz.build:
|
||||
Library('mylib')
|
||||
FORCE_SHARED_LIB = True
|
||||
|
@ -272,6 +306,8 @@ linking to a library with a ``SONAME``, the resulting library or program will
|
|||
have a dependency on the library with the name corresponding to the ``SONAME``
|
||||
instead of the ``Library`` name. This only impacts ELF systems.
|
||||
|
||||
::
|
||||
|
||||
a/moz.build:
|
||||
Library('mylib')
|
||||
b/moz.build:
|
||||
|
|
|
@ -1741,14 +1741,14 @@ ilen = dnaInput.length;
|
|||
dnaInput = dnaInput.replace(/>.*\n|\n/g,"")
|
||||
clen = dnaInput.length
|
||||
|
||||
var dnaOutputString;
|
||||
var dnaOutputString = "";
|
||||
|
||||
for(i in seqs)
|
||||
dnaOutputString += seqs[i].source + " " + (dnaInput.match(seqs[i]) || []).length + "\n";
|
||||
// match returns null if no matches, so replace with empty
|
||||
|
||||
for(k in subs)
|
||||
dnaInput = dnaInput.replace(k, subs[k], "g")
|
||||
dnaInput = dnaInput.replace(k, subs[k]) // FIXME: Would like this to be a global substitution in a future version of SunSpider.
|
||||
// search string, replacement string, flags
|
||||
|
||||
|
||||
|
|
15
configure.in
15
configure.in
|
@ -7217,6 +7217,9 @@ if test -z "$MOZ_MEMORY"; then
|
|||
esac
|
||||
else
|
||||
AC_DEFINE(MOZ_MEMORY)
|
||||
if test -n "$NIGHTLY_BUILD"; then
|
||||
MOZ_JEMALLOC3=1
|
||||
fi
|
||||
if test -n "$MOZ_JEMALLOC3"; then
|
||||
AC_DEFINE(MOZ_JEMALLOC3)
|
||||
fi
|
||||
|
@ -7654,6 +7657,18 @@ MOZ_ARG_WITH_STRING(jitreport-granularity,
|
|||
|
||||
AC_DEFINE_UNQUOTED(JS_DEFAULT_JITREPORT_GRANULARITY, $JITREPORT_GRANULARITY)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Disable Mozilla's versions of RIL and Geolocation
|
||||
dnl ========================================================
|
||||
MOZ_ARG_DISABLE_BOOL(mozril-geoloc,
|
||||
[ --disable-mozril-geoloc Disable Mozilla's RIL and geolocation],
|
||||
DISABLE_MOZ_RIL_GEOLOC=1,
|
||||
DISABLE_MOZ_RIL_GEOLOC= )
|
||||
if test -n "$DISABLE_MOZ_RIL_GEOLOC"; then
|
||||
AC_DEFINE(DISABLE_MOZ_RIL_GEOLOC)
|
||||
fi
|
||||
AC_SUBST(DISABLE_MOZ_RIL_GEOLOC)
|
||||
|
||||
dnl ========================================================
|
||||
dnl =
|
||||
dnl = Misc. Options
|
||||
|
|
|
@ -621,14 +621,14 @@ function do_single_test_run() {
|
|||
if (couldDoKeywordLookup) {
|
||||
if (expectKeywordLookup) {
|
||||
if (!affectedByWhitelist || (affectedByWhitelist && !inWhitelist)) {
|
||||
let urlparamInput = encodeURIComponent(sanitize(testInput)).replace("%20", "+", "g");
|
||||
let urlparamInput = encodeURIComponent(sanitize(testInput)).replace(/%20/g, "+");
|
||||
// If the input starts with `?`, then info.preferredURI.spec will omit it
|
||||
// In order to test this behaviour, remove `?` only if it is the first character
|
||||
if (urlparamInput.startsWith("%3F")) {
|
||||
urlparamInput = urlparamInput.replace("%3F", "");
|
||||
}
|
||||
let searchURL = kSearchEngineURL.replace("{searchTerms}", urlparamInput);
|
||||
let spec = info.preferredURI.spec.replace("%27", "'", "g");
|
||||
let spec = info.preferredURI.spec.replace(/%27/g, "'");
|
||||
do_check_eq(spec, searchURL);
|
||||
} else {
|
||||
do_check_eq(info.preferredURI, null);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
@ -8,18 +9,11 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "nsAttrValue.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
struct MiscContainer;
|
||||
|
||||
namespace mozilla {
|
||||
template<>
|
||||
struct HasDangerousPublicDestructor<MiscContainer>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
}
|
||||
|
||||
struct MiscContainer
|
||||
struct MiscContainer MOZ_FINAL
|
||||
{
|
||||
typedef nsAttrValue::ValueType ValueType;
|
||||
|
||||
|
@ -70,6 +64,10 @@ struct MiscContainer
|
|||
mValue.mCached = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Only nsAttrValue should be able to delete us.
|
||||
friend class nsAttrValue;
|
||||
|
||||
~MiscContainer()
|
||||
{
|
||||
if (IsRefCounted()) {
|
||||
|
@ -79,6 +77,7 @@ struct MiscContainer
|
|||
MOZ_COUNT_DTOR(MiscContainer);
|
||||
}
|
||||
|
||||
public:
|
||||
bool GetString(nsAString& aString) const;
|
||||
|
||||
inline bool IsRefCounted() const
|
||||
|
|
|
@ -914,8 +914,7 @@ nsFrameLoader::ShowRemoteFrame(const nsIntSize& size,
|
|||
|
||||
// Don't show remote iframe if we are waiting for the completion of reflow.
|
||||
if (!aFrame || !(aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
||||
nsIntPoint chromeDisp = aFrame->GetChromeDisplacement();
|
||||
mRemoteBrowser->UpdateDimensions(dimensions, size, chromeDisp);
|
||||
mRemoteBrowser->UpdateDimensions(dimensions, size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1960,8 +1959,7 @@ nsFrameLoader::UpdatePositionAndSize(nsSubDocumentFrame *aIFrame)
|
|||
nsIntSize size = aIFrame->GetSubdocumentSize();
|
||||
nsIntRect dimensions;
|
||||
NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), NS_ERROR_FAILURE);
|
||||
nsIntPoint chromeDisp = aIFrame->GetChromeDisplacement();
|
||||
mRemoteBrowser->UpdateDimensions(dimensions, size, chromeDisp);
|
||||
mRemoteBrowser->UpdateDimensions(dimensions, size);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -227,6 +227,9 @@ public:
|
|||
void ActivateUpdateHitRegion();
|
||||
void DeactivateUpdateHitRegion();
|
||||
|
||||
// Properly retrieves documentSize of any subdocument type.
|
||||
nsresult GetWindowDimensions(nsIntRect& aRect);
|
||||
|
||||
private:
|
||||
|
||||
void SetOwnerContent(mozilla::dom::Element* aContent);
|
||||
|
@ -282,9 +285,6 @@ private:
|
|||
nsresult MaybeCreateDocShell();
|
||||
nsresult EnsureMessageManager();
|
||||
|
||||
// Properly retrieves documentSize of any subdocument type.
|
||||
nsresult GetWindowDimensions(nsIntRect& aRect);
|
||||
|
||||
// Updates the subdocument position and size. This gets called only
|
||||
// when we have our own in-process DocShell.
|
||||
void UpdateBaseWindowPositionAndSize(nsSubDocumentFrame *aIFrame);
|
||||
|
|
|
@ -514,7 +514,7 @@ nsFrameMessageManager::GetDelayedScripts(JSContext* aCx, JS::MutableHandle<JS::V
|
|||
pair = JS_NewArrayObject(aCx, pairElts);
|
||||
NS_ENSURE_TRUE(pair, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
NS_ENSURE_TRUE(JS_SetElement(aCx, array, i, pair),
|
||||
NS_ENSURE_TRUE(JS_DefineElement(aCx, array, i, pair, JSPROP_ENUMERATE),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
|
@ -696,7 +696,7 @@ nsFrameMessageManager::SendMessage(const nsAString& aMessageName,
|
|||
retval[i].Length(), &ret)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
NS_ENSURE_TRUE(JS_SetElement(aCx, dataArray, i, ret),
|
||||
NS_ENSURE_TRUE(JS_DefineElement(aCx, dataArray, i, ret, JSPROP_ENUMERATE),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
|
|
|
@ -2256,14 +2256,17 @@ GK_ATOM(aria_valuemax, "aria-valuemax")
|
|||
GK_ATOM(aria_valuetext, "aria-valuetext")
|
||||
GK_ATOM(AreaFrame, "AreaFrame")
|
||||
GK_ATOM(auto_generated, "auto-generated")
|
||||
GK_ATOM(banner, "banner")
|
||||
GK_ATOM(checkable, "checkable")
|
||||
GK_ATOM(choices, "choices")
|
||||
GK_ATOM(columnheader, "columnheader")
|
||||
GK_ATOM(complementary, "complementary")
|
||||
GK_ATOM(containerAtomic, "container-atomic")
|
||||
GK_ATOM(containerBusy, "container-busy")
|
||||
GK_ATOM(containerLive, "container-live")
|
||||
GK_ATOM(containerLiveRole, "container-live-role")
|
||||
GK_ATOM(containerRelevant, "container-relevant")
|
||||
GK_ATOM(contentinfo, "contentinfo")
|
||||
GK_ATOM(cycles, "cycles")
|
||||
GK_ATOM(datatable, "datatable")
|
||||
GK_ATOM(directory, "directory")
|
||||
|
@ -2284,6 +2287,7 @@ GK_ATOM(menuitemcheckbox, "menuitemcheckbox")
|
|||
GK_ATOM(menuitemradio, "menuitemradio")
|
||||
GK_ATOM(mixed, "mixed")
|
||||
GK_ATOM(multiline, "multiline")
|
||||
GK_ATOM(navigation, "navigation")
|
||||
GK_ATOM(password, "password")
|
||||
GK_ATOM(posinset, "posinset")
|
||||
GK_ATOM(presentation, "presentation")
|
||||
|
@ -2291,6 +2295,8 @@ GK_ATOM(progressbar, "progressbar")
|
|||
GK_ATOM(region, "region")
|
||||
GK_ATOM(rowgroup, "rowgroup")
|
||||
GK_ATOM(rowheader, "rowheader")
|
||||
GK_ATOM(search, "search")
|
||||
GK_ATOM(searchbox, "searchbox")
|
||||
GK_ATOM(select1, "select1")
|
||||
GK_ATOM(setsize, "setsize")
|
||||
GK_ATOM(spelling, "spelling")
|
||||
|
|
|
@ -9184,6 +9184,8 @@ nsGlobalWindow::ShowModalDialog(const nsAString& aUrl, nsIVariant* aArgument,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Telemetry::Accumulate(Telemetry::DOM_WINDOW_SHOWMODALDIALOG_USED, true);
|
||||
|
||||
nsRefPtr<DialogValueHolder> argHolder =
|
||||
new DialogValueHolder(nsContentUtils::SubjectPrincipal(), aArgument);
|
||||
|
||||
|
|
|
@ -27,8 +27,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=902847
|
|||
var range = document.createRange();
|
||||
range.selectNodeContents(element);
|
||||
encoder.setRange(range);
|
||||
return encoder.encodeToString().replace('\n', '\\n', 'g')
|
||||
.replace('\r', '\\r', 'g');
|
||||
return encoder.encodeToString().replace(/\n/g, '\\n')
|
||||
.replace(/\r/g, '\\r');
|
||||
}
|
||||
|
||||
// Test cases.
|
||||
|
|
|
@ -1941,15 +1941,15 @@ struct FakeString {
|
|||
return reinterpret_cast<const nsString*>(this);
|
||||
}
|
||||
|
||||
nsAString* ToAStringPtr() {
|
||||
return reinterpret_cast<nsString*>(this);
|
||||
}
|
||||
|
||||
operator const nsAString& () const {
|
||||
operator const nsAString& () const {
|
||||
return *reinterpret_cast<const nsString*>(this);
|
||||
}
|
||||
|
||||
private:
|
||||
nsAString* ToAStringPtr() {
|
||||
return reinterpret_cast<nsString*>(this);
|
||||
}
|
||||
|
||||
nsString::char_type* mData;
|
||||
nsString::size_type mLength;
|
||||
uint32_t mFlags;
|
||||
|
@ -1965,6 +1965,8 @@ private:
|
|||
mData = const_cast<nsString::char_type*>(aData);
|
||||
}
|
||||
|
||||
friend class NonNull<nsAString>;
|
||||
|
||||
// A class to use for our static asserts to ensure our object layout
|
||||
// matches that of nsString.
|
||||
class StringAsserter;
|
||||
|
|
|
@ -196,16 +196,12 @@ BluetoothManager::HandleAdapterRemoved(const BluetoothValue& aValue)
|
|||
// Remove the adapter of given address from adapters array
|
||||
nsString addressToRemove = aValue.get_nsString();
|
||||
|
||||
uint32_t numAdapters = mAdapters.Length();
|
||||
for (uint32_t i = 0; i < numAdapters; i++) {
|
||||
uint32_t i;
|
||||
for (i = 0; i < mAdapters.Length(); i++) {
|
||||
nsString address;
|
||||
mAdapters[i]->GetAddress(address);
|
||||
if (address.Equals(addressToRemove)) {
|
||||
mAdapters.RemoveElementAt(i);
|
||||
|
||||
if (mDefaultAdapterIndex == (int)i) {
|
||||
ReselectDefaultAdapter();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -214,6 +210,11 @@ BluetoothManager::HandleAdapterRemoved(const BluetoothValue& aValue)
|
|||
BluetoothAdapterEventInit init;
|
||||
init.mAddress = addressToRemove;
|
||||
DispatchAdapterEvent(NS_LITERAL_STRING("adapterremoved"), init);
|
||||
|
||||
// Reselect default adapter if it's removed
|
||||
if (mDefaultAdapterIndex == (int)i) {
|
||||
ReselectDefaultAdapter();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -56,12 +56,12 @@ StringToUuid(const char* aString, BluetoothUuid& aUuid)
|
|||
uuid4 = htonl(uuid4);
|
||||
uuid5 = htons(uuid5);
|
||||
|
||||
memcpy(&aUuid.mUuid[0], &uuid0, 4);
|
||||
memcpy(&aUuid.mUuid[4], &uuid1, 2);
|
||||
memcpy(&aUuid.mUuid[6], &uuid2, 2);
|
||||
memcpy(&aUuid.mUuid[8], &uuid3, 2);
|
||||
memcpy(&aUuid.mUuid[10], &uuid4, 4);
|
||||
memcpy(&aUuid.mUuid[14], &uuid5, 2);
|
||||
memcpy(&aUuid.mUuid[0], &uuid0, sizeof(uint32_t));
|
||||
memcpy(&aUuid.mUuid[4], &uuid1, sizeof(uint16_t));
|
||||
memcpy(&aUuid.mUuid[6], &uuid2, sizeof(uint16_t));
|
||||
memcpy(&aUuid.mUuid[8], &uuid3, sizeof(uint16_t));
|
||||
memcpy(&aUuid.mUuid[10], &uuid4, sizeof(uint32_t));
|
||||
memcpy(&aUuid.mUuid[14], &uuid5, sizeof(uint16_t));
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -42,11 +42,19 @@ if (!('BrowserElementIsPreloaded' in this)) {
|
|||
}
|
||||
}
|
||||
|
||||
if (docShell.asyncPanZoomEnabled === false) {
|
||||
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementPanningAPZDisabled.js");
|
||||
ContentPanningAPZDisabled.init();
|
||||
}
|
||||
|
||||
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementPanning.js");
|
||||
ContentPanning.init();
|
||||
|
||||
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementChildPreload.js");
|
||||
} else {
|
||||
if (docShell.asyncPanZoomEnabled === false) {
|
||||
ContentPanningAPZDisabled.init();
|
||||
}
|
||||
ContentPanning.init();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@ let { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
|
|||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Geometry.jsm");
|
||||
|
||||
var global = this;
|
||||
|
||||
const kObservedEvents = [
|
||||
"BEC:ShownModalPrompt",
|
||||
"Activity:Success",
|
||||
|
@ -21,21 +19,7 @@ const kObservedEvents = [
|
|||
];
|
||||
|
||||
const ContentPanning = {
|
||||
// Are we listening to touch or mouse events?
|
||||
watchedEventsType: '',
|
||||
|
||||
// Are mouse events being delivered to this content along with touch
|
||||
// events, in violation of spec?
|
||||
hybridEvents: false,
|
||||
|
||||
init: function cp_init() {
|
||||
// If APZ is enabled, we do active element handling in C++
|
||||
// (see widget/xpwidgets/ActiveElementManager.h), and panning
|
||||
// itself in APZ, so we don't need to handle any touch events here.
|
||||
if (docShell.asyncPanZoomEnabled === false) {
|
||||
this._setupListenersForPanning();
|
||||
}
|
||||
|
||||
addEventListener("unload",
|
||||
this._unloadHandler.bind(this),
|
||||
/* useCapture = */ false,
|
||||
|
@ -49,441 +33,16 @@ const ContentPanning = {
|
|||
});
|
||||
},
|
||||
|
||||
_setupListenersForPanning: function cp_setupListenersForPanning() {
|
||||
let events;
|
||||
|
||||
if (content.TouchEvent) {
|
||||
events = ['touchstart', 'touchend', 'touchmove'];
|
||||
this.watchedEventsType = 'touch';
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
// The gonk widget backend does not deliver mouse events per
|
||||
// spec. Third-party content isn't exposed to this behavior,
|
||||
// but that behavior creates some extra work for us here.
|
||||
let appInfo = Cc["@mozilla.org/xre/app-info;1"];
|
||||
let isParentProcess =
|
||||
!appInfo || appInfo.getService(Ci.nsIXULRuntime)
|
||||
.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
|
||||
this.hybridEvents = isParentProcess;
|
||||
#endif
|
||||
} else {
|
||||
// Touch events aren't supported, so fall back on mouse.
|
||||
events = ['mousedown', 'mouseup', 'mousemove'];
|
||||
this.watchedEventsType = 'mouse';
|
||||
}
|
||||
|
||||
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(Ci.nsIEventListenerService);
|
||||
|
||||
events.forEach(function(type) {
|
||||
// Using the system group for mouse/touch events to avoid
|
||||
// missing events if .stopPropagation() has been called.
|
||||
els.addSystemEventListener(global, type,
|
||||
this.handleEvent.bind(this),
|
||||
/* useCapture = */ false);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
handleEvent: function cp_handleEvent(evt) {
|
||||
// Ignore events targeting an oop <iframe mozbrowser> since those will be
|
||||
// handle by the BrowserElementPanning.js instance in the child process.
|
||||
if (evt.target instanceof Ci.nsIMozBrowserFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
// For in-process <iframe mozbrowser> the events are not targetting
|
||||
// directly the container iframe element, but some node of the document.
|
||||
// So, the BrowserElementPanning instance of the system app will receive
|
||||
// the sequence of touch events, as well as the BrowserElementPanning
|
||||
// instance in the targetted app.
|
||||
// As a result, multiple mozbrowser iframes will try to interpret the
|
||||
// sequence of touch events, which may results into multiple clicks.
|
||||
let targetWindow = evt.target.ownerDocument.defaultView;
|
||||
let frameElement = targetWindow.frameElement;
|
||||
while (frameElement) {
|
||||
targetWindow = frameElement.ownerDocument.defaultView;
|
||||
frameElement = targetWindow.frameElement;
|
||||
}
|
||||
|
||||
if (content !== targetWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (evt.defaultPrevented || evt.multipleActionsPrevented) {
|
||||
// clean up panning state even if touchend/mouseup has been preventDefault.
|
||||
if(evt.type === 'touchend' || evt.type === 'mouseup') {
|
||||
if (this.dragging &&
|
||||
(this.watchedEventsType === 'mouse' ||
|
||||
this.findPrimaryPointer(evt.changedTouches))) {
|
||||
this._finishPanning();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (evt.type) {
|
||||
case 'mousedown':
|
||||
case 'touchstart':
|
||||
this.onTouchStart(evt);
|
||||
break;
|
||||
case 'mousemove':
|
||||
case 'touchmove':
|
||||
this.onTouchMove(evt);
|
||||
break;
|
||||
case 'mouseup':
|
||||
case 'touchend':
|
||||
this.onTouchEnd(evt);
|
||||
break;
|
||||
case 'click':
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
|
||||
let target = evt.target;
|
||||
let view = target.ownerDocument ? target.ownerDocument.defaultView
|
||||
: target;
|
||||
view.removeEventListener('click', this, true, true);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
observe: function cp_observe(subject, topic, data) {
|
||||
this._resetHover();
|
||||
},
|
||||
|
||||
position: new Point(0 , 0),
|
||||
|
||||
findPrimaryPointer: function cp_findPrimaryPointer(touches) {
|
||||
if (!('primaryPointerId' in this))
|
||||
return null;
|
||||
|
||||
for (let i = 0; i < touches.length; i++) {
|
||||
if (touches[i].identifier === this.primaryPointerId) {
|
||||
return touches[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
onTouchStart: function cp_onTouchStart(evt) {
|
||||
let screenX, screenY;
|
||||
if (this.watchedEventsType == 'touch') {
|
||||
if ('primaryPointerId' in this || evt.touches.length >= 2) {
|
||||
this._resetActive();
|
||||
return;
|
||||
}
|
||||
|
||||
let firstTouch = evt.changedTouches[0];
|
||||
this.primaryPointerId = firstTouch.identifier;
|
||||
this.pointerDownTarget = firstTouch.target;
|
||||
screenX = firstTouch.screenX;
|
||||
screenY = firstTouch.screenY;
|
||||
} else {
|
||||
this.pointerDownTarget = evt.target;
|
||||
screenX = evt.screenX;
|
||||
screenY = evt.screenY;
|
||||
}
|
||||
this.dragging = true;
|
||||
this.panning = false;
|
||||
|
||||
let oldTarget = this.target;
|
||||
[this.target, this.scrollCallback] = this.getPannable(this.pointerDownTarget);
|
||||
|
||||
// If we have a pointer down target, we may need to fill in for EventStateManager
|
||||
// in setting the active state on the target element. Set a timer to
|
||||
// ensure the pointer-down target is active. (If it's already
|
||||
// active, the timer is a no-op.)
|
||||
if (this.pointerDownTarget !== null) {
|
||||
// If there's no possibility this is a drag/pan, activate now.
|
||||
// Otherwise wait a little bit to see if the gesture isn't a
|
||||
// tap.
|
||||
if (this.target === null) {
|
||||
this.notify(this._activationTimer);
|
||||
} else {
|
||||
this._activationTimer.initWithCallback(this,
|
||||
this._activationDelayMs,
|
||||
Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
}
|
||||
}
|
||||
|
||||
// If there is a pan animation running (from a previous pan gesture) and
|
||||
// the user touch back the screen, stop this animation immediatly and
|
||||
// prevent the possible click action if the touch happens on the same
|
||||
// target.
|
||||
this.preventNextClick = false;
|
||||
if (KineticPanning.active) {
|
||||
KineticPanning.stop();
|
||||
|
||||
if (oldTarget && oldTarget == this.target)
|
||||
this.preventNextClick = true;
|
||||
}
|
||||
|
||||
this.position.set(screenX, screenY);
|
||||
KineticPanning.reset();
|
||||
KineticPanning.record(new Point(0, 0), evt.timeStamp);
|
||||
|
||||
// We prevent start events to avoid sending a focus event at the end of this
|
||||
// touch series. See bug 889717.
|
||||
if ((this.panning || this.preventNextClick)) {
|
||||
evt.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
onTouchEnd: function cp_onTouchEnd(evt) {
|
||||
let touch = null;
|
||||
if (!this.dragging ||
|
||||
(this.watchedEventsType == 'touch' &&
|
||||
!(touch = this.findPrimaryPointer(evt.changedTouches)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// !isPan() and evt.detail should always give the same answer here
|
||||
// since they use the same heuristics, but use the native gecko
|
||||
// computation when possible.
|
||||
//
|
||||
// NB: when we're using touch events, then !KineticPanning.isPan()
|
||||
// => this.panning, so we'll never attempt to block the click
|
||||
// event. That's OK however, because we won't fire a synthetic
|
||||
// click when we're using touch events and this touch series
|
||||
// wasn't a "tap" gesture.
|
||||
let click = (this.watchedEventsType == 'mouse') ?
|
||||
evt.detail : !KineticPanning.isPan();
|
||||
// Additionally, if we're seeing non-compliant hybrid events, a
|
||||
// "real" click will be generated if we started and ended on the
|
||||
// same element.
|
||||
if (this.hybridEvents) {
|
||||
let target =
|
||||
content.document.elementFromPoint(touch.clientX, touch.clientY);
|
||||
click |= (target === this.pointerDownTarget);
|
||||
}
|
||||
|
||||
if (this.target && click && (this.panning || this.preventNextClick)) {
|
||||
if (this.hybridEvents) {
|
||||
let target = this.target;
|
||||
let view = target.ownerDocument ? target.ownerDocument.defaultView
|
||||
: target;
|
||||
view.addEventListener('click', this, true, true);
|
||||
} else {
|
||||
// We prevent end events to avoid sending a focus event. See bug 889717.
|
||||
evt.preventDefault();
|
||||
}
|
||||
} else if (this.target && click && !this.panning) {
|
||||
this.notify(this._activationTimer);
|
||||
}
|
||||
|
||||
this._finishPanning();
|
||||
|
||||
// Now that we're done, avoid entraining the thing we just panned.
|
||||
this.pointerDownTarget = null;
|
||||
},
|
||||
|
||||
onTouchMove: function cp_onTouchMove(evt) {
|
||||
if (!this.dragging)
|
||||
return;
|
||||
|
||||
let screenX, screenY;
|
||||
if (this.watchedEventsType == 'touch') {
|
||||
let primaryTouch = this.findPrimaryPointer(evt.changedTouches);
|
||||
if (evt.touches.length > 1 || !primaryTouch)
|
||||
return;
|
||||
screenX = primaryTouch.screenX;
|
||||
screenY = primaryTouch.screenY;
|
||||
} else {
|
||||
screenX = evt.screenX;
|
||||
screenY = evt.screenY;
|
||||
}
|
||||
|
||||
let current = this.position;
|
||||
let delta = new Point(screenX - current.x, screenY - current.y);
|
||||
current.set(screenX, screenY);
|
||||
|
||||
KineticPanning.record(delta, evt.timeStamp);
|
||||
|
||||
let isPan = KineticPanning.isPan();
|
||||
|
||||
// If we've detected a pan gesture, cancel the active state of the
|
||||
// current target.
|
||||
if (!this.panning && isPan) {
|
||||
this._resetActive();
|
||||
}
|
||||
|
||||
// There's no possibility of us panning anything.
|
||||
if (!this.scrollCallback) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scroll manually.
|
||||
this.scrollCallback(delta.scale(-1));
|
||||
|
||||
if (!this.panning && isPan) {
|
||||
this.panning = true;
|
||||
this._activationTimer.cancel();
|
||||
}
|
||||
|
||||
if (this.panning) {
|
||||
// Only do this when we're actually executing a pan gesture.
|
||||
// Otherwise synthetic mouse events will be canceled.
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
// nsITimerCallback
|
||||
notify: function cp_notify(timer) {
|
||||
this._setActive(this.pointerDownTarget);
|
||||
},
|
||||
|
||||
onKineticBegin: function cp_onKineticBegin(evt) {
|
||||
},
|
||||
|
||||
onKineticPan: function cp_onKineticPan(delta) {
|
||||
return !this.scrollCallback(delta);
|
||||
},
|
||||
|
||||
onKineticEnd: function cp_onKineticEnd() {
|
||||
if (!this.dragging)
|
||||
this.scrollCallback = null;
|
||||
},
|
||||
|
||||
getPannable: function cp_getPannable(node) {
|
||||
let pannableNode = this._findPannable(node);
|
||||
if (pannableNode) {
|
||||
return [pannableNode, this._generateCallback(pannableNode)];
|
||||
}
|
||||
|
||||
return [null, null];
|
||||
},
|
||||
|
||||
_findPannable: function cp_findPannable(node) {
|
||||
if (!(node instanceof Ci.nsIDOMHTMLElement) || node.tagName == 'HTML') {
|
||||
return null;
|
||||
}
|
||||
|
||||
let nodeContent = node.ownerDocument.defaultView;
|
||||
while (!(node instanceof Ci.nsIDOMHTMLBodyElement)) {
|
||||
let style = nodeContent.getComputedStyle(node, null);
|
||||
|
||||
let overflow = [style.getPropertyValue('overflow'),
|
||||
style.getPropertyValue('overflow-x'),
|
||||
style.getPropertyValue('overflow-y')];
|
||||
|
||||
let rect = node.getBoundingClientRect();
|
||||
let isAuto = (overflow.indexOf('auto') != -1 &&
|
||||
(rect.height < node.scrollHeight ||
|
||||
rect.width < node.scrollWidth));
|
||||
|
||||
let isScroll = (overflow.indexOf('scroll') != -1);
|
||||
|
||||
let isScrollableTextarea = (node.tagName == 'TEXTAREA' &&
|
||||
(node.scrollHeight > node.clientHeight ||
|
||||
node.scrollWidth > node.clientWidth ||
|
||||
('scrollLeftMax' in node && node.scrollLeftMax > 0) ||
|
||||
('scrollTopMax' in node && node.scrollTopMax > 0)));
|
||||
if (isScroll || isAuto || isScrollableTextarea) {
|
||||
return node;
|
||||
}
|
||||
|
||||
node = node.parentNode;
|
||||
}
|
||||
|
||||
if (nodeContent.scrollMaxX || nodeContent.scrollMaxY) {
|
||||
return nodeContent;
|
||||
}
|
||||
|
||||
if (nodeContent.frameElement) {
|
||||
return this._findPannable(nodeContent.frameElement);
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
_generateCallback: function cp_generateCallback(root) {
|
||||
let firstScroll = true;
|
||||
let target;
|
||||
let current;
|
||||
let win, doc, htmlNode, bodyNode;
|
||||
|
||||
function doScroll(node, delta) {
|
||||
if (node instanceof Ci.nsIDOMHTMLElement) {
|
||||
return node.scrollByNoFlush(delta.x, delta.y);
|
||||
} else if (node instanceof Ci.nsIDOMWindow) {
|
||||
win = node;
|
||||
doc = win.document;
|
||||
|
||||
// "overflow:hidden" on either the <html> or the <body> node should
|
||||
// prevent the user from scrolling the root viewport.
|
||||
if (doc instanceof Ci.nsIDOMHTMLDocument) {
|
||||
htmlNode = doc.documentElement;
|
||||
bodyNode = doc.body;
|
||||
if (win.getComputedStyle(htmlNode, null).overflowX == "hidden" ||
|
||||
win.getComputedStyle(bodyNode, null).overflowX == "hidden") {
|
||||
delta.x = 0;
|
||||
}
|
||||
if (win.getComputedStyle(htmlNode, null).overflowY == "hidden" ||
|
||||
win.getComputedStyle(bodyNode, null).overflowY == "hidden") {
|
||||
delta.y = 0;
|
||||
}
|
||||
}
|
||||
let oldX = node.scrollX;
|
||||
let oldY = node.scrollY;
|
||||
node.scrollBy(delta.x, delta.y);
|
||||
return (node.scrollX != oldX || node.scrollY != oldY);
|
||||
}
|
||||
// If we get here, |node| isn't an HTML element and it's not a window,
|
||||
// but findPannable apparently thought it was scrollable... What is it?
|
||||
return false;
|
||||
}
|
||||
|
||||
function targetParent(node) {
|
||||
return node.parentNode || node.frameElement || null;
|
||||
}
|
||||
|
||||
function scroll(delta) {
|
||||
current = root;
|
||||
firstScroll = true;
|
||||
while (current) {
|
||||
if (doScroll(current, delta)) {
|
||||
firstScroll = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO The current code looks for possible scrolling regions only if
|
||||
// this is the first scroll action but this should be more dynamic.
|
||||
if (!firstScroll) {
|
||||
return false;
|
||||
}
|
||||
|
||||
current = ContentPanning._findPannable(targetParent(current));
|
||||
}
|
||||
|
||||
// There is nothing scrollable here.
|
||||
return false;
|
||||
}
|
||||
return scroll;
|
||||
},
|
||||
|
||||
get _domUtils() {
|
||||
delete this._domUtils;
|
||||
return this._domUtils = Cc['@mozilla.org/inspector/dom-utils;1']
|
||||
.getService(Ci.inIDOMUtils);
|
||||
},
|
||||
|
||||
get _activationTimer() {
|
||||
delete this._activationTimer;
|
||||
return this._activationTimer = Cc["@mozilla.org/timer;1"]
|
||||
.createInstance(Ci.nsITimer);
|
||||
},
|
||||
|
||||
get _activationDelayMs() {
|
||||
let delay = Services.prefs.getIntPref('ui.touch_activation.delay_ms');
|
||||
delete this._activationDelayMs;
|
||||
return this._activationDelayMs = delay;
|
||||
},
|
||||
|
||||
_resetActive: function cp_resetActive() {
|
||||
let elt = this.pointerDownTarget || this.target;
|
||||
let root = elt.ownerDocument || elt.document;
|
||||
this._setActive(root.documentElement);
|
||||
},
|
||||
|
||||
_resetHover: function cp_resetHover() {
|
||||
const kStateHover = 0x00000004;
|
||||
try {
|
||||
|
@ -492,11 +51,6 @@ const ContentPanning = {
|
|||
} catch(e) {}
|
||||
},
|
||||
|
||||
_setActive: function cp_setActive(elt) {
|
||||
const kStateActive = 0x00000001;
|
||||
this._domUtils.setContentState(elt, kStateActive);
|
||||
},
|
||||
|
||||
_recvViewportChange: function(data) {
|
||||
let metrics = data.json;
|
||||
this._viewport = new Rect(metrics.x, metrics.y,
|
||||
|
@ -610,17 +164,6 @@ const ContentPanning = {
|
|||
return (showing > 0.9 && (ratioW > 0.9 || ratioH > 0.9));
|
||||
},
|
||||
|
||||
_finishPanning: function() {
|
||||
this.dragging = false;
|
||||
delete this.primaryPointerId;
|
||||
this._activationTimer.cancel();
|
||||
|
||||
// If there is a scroll action, let's do a manual kinetic panning action.
|
||||
if (this.panning) {
|
||||
KineticPanning.start(this);
|
||||
}
|
||||
},
|
||||
|
||||
_unloadHandler: function() {
|
||||
kObservedEvents.forEach((topic) => {
|
||||
Services.obs.removeObserver(this, topic);
|
||||
|
@ -628,206 +171,6 @@ const ContentPanning = {
|
|||
}
|
||||
};
|
||||
|
||||
// Min/max velocity of kinetic panning. This is in pixels/millisecond.
|
||||
const kMinVelocity = 0.2;
|
||||
const kMaxVelocity = 6;
|
||||
|
||||
// Constants that affect the "friction" of the scroll pane.
|
||||
const kExponentialC = 1000;
|
||||
const kPolynomialC = 100 / 1000000;
|
||||
|
||||
// How often do we change the position of the scroll pane?
|
||||
// Too often and panning may jerk near the end.
|
||||
// Too little and panning will be choppy. In milliseconds.
|
||||
const kUpdateInterval = 16;
|
||||
|
||||
// The numbers of momentums to use for calculating the velocity of the pan.
|
||||
// Those are taken from the end of the action
|
||||
const kSamples = 5;
|
||||
|
||||
const KineticPanning = {
|
||||
_position: new Point(0, 0),
|
||||
_velocity: new Point(0, 0),
|
||||
_acceleration: new Point(0, 0),
|
||||
|
||||
get active() {
|
||||
return this.target !== null;
|
||||
},
|
||||
|
||||
target: null,
|
||||
start: function kp_start(target) {
|
||||
this.target = target;
|
||||
|
||||
// Calculate the initial velocity of the movement based on user input
|
||||
let momentums = this.momentums;
|
||||
let flick = momentums[momentums.length - 1].time - momentums[0].time < 300;
|
||||
|
||||
let distance = new Point(0, 0);
|
||||
momentums.forEach(function(momentum) {
|
||||
distance.add(momentum.dx, momentum.dy);
|
||||
});
|
||||
|
||||
function clampFromZero(x, min, max) {
|
||||
if (x >= 0)
|
||||
return Math.max(min, Math.min(max, x));
|
||||
return Math.min(-min, Math.max(-max, x));
|
||||
}
|
||||
|
||||
let elapsed = momentums[momentums.length - 1].time - momentums[0].time;
|
||||
let velocityX = clampFromZero(distance.x / elapsed, 0, kMaxVelocity);
|
||||
let velocityY = clampFromZero(distance.y / elapsed, 0, kMaxVelocity);
|
||||
|
||||
let velocity = this._velocity;
|
||||
if (flick) {
|
||||
// Very fast pan action that does not generate a click are very often pan
|
||||
// action. If this is a small gesture then it will not move the view a lot
|
||||
// and so it will be above the minimun threshold and not generate any
|
||||
// kinetic panning. This does not look on a device since this is often
|
||||
// a real gesture, so let's lower the velocity threshold for such moves.
|
||||
velocity.set(velocityX, velocityY);
|
||||
} else {
|
||||
velocity.set(Math.abs(velocityX) < kMinVelocity ? 0 : velocityX,
|
||||
Math.abs(velocityY) < kMinVelocity ? 0 : velocityY);
|
||||
}
|
||||
this.momentums = [];
|
||||
|
||||
// Set acceleration vector to opposite signs of velocity
|
||||
function sign(x) {
|
||||
return x ? (x > 0 ? 1 : -1) : 0;
|
||||
}
|
||||
|
||||
this._acceleration.set(velocity.clone().map(sign).scale(-kPolynomialC));
|
||||
|
||||
// Reset the position
|
||||
this._position.set(0, 0);
|
||||
|
||||
this._startAnimation();
|
||||
|
||||
this.target.onKineticBegin();
|
||||
},
|
||||
|
||||
stop: function kp_stop() {
|
||||
this.reset();
|
||||
|
||||
if (!this.target)
|
||||
return;
|
||||
|
||||
this.target.onKineticEnd();
|
||||
this.target = null;
|
||||
},
|
||||
|
||||
reset: function kp_reset() {
|
||||
this.momentums = [];
|
||||
this.distance.set(0, 0);
|
||||
},
|
||||
|
||||
momentums: [],
|
||||
record: function kp_record(delta, timestamp) {
|
||||
this.momentums.push({ 'time': this._getTime(timestamp),
|
||||
'dx' : delta.x, 'dy' : delta.y });
|
||||
|
||||
// We only need to keep kSamples in this.momentums.
|
||||
if (this.momentums.length > kSamples) {
|
||||
this.momentums.shift();
|
||||
}
|
||||
|
||||
this.distance.add(delta.x, delta.y);
|
||||
},
|
||||
|
||||
_getTime: function kp_getTime(time) {
|
||||
// Touch events generated by the platform or hand-made are defined in
|
||||
// microseconds instead of milliseconds. Bug 77992 will fix this at the
|
||||
// platform level.
|
||||
if (time > Date.now()) {
|
||||
return Math.floor(time / 1000);
|
||||
} else {
|
||||
return time;
|
||||
}
|
||||
},
|
||||
|
||||
get threshold() {
|
||||
let dpi = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.displayDPI;
|
||||
|
||||
let threshold = Services.prefs.getIntPref('ui.dragThresholdX') / 240 * dpi;
|
||||
|
||||
delete this.threshold;
|
||||
return this.threshold = threshold;
|
||||
},
|
||||
|
||||
distance: new Point(0, 0),
|
||||
isPan: function cp_isPan() {
|
||||
return (Math.abs(this.distance.x) > this.threshold ||
|
||||
Math.abs(this.distance.y) > this.threshold);
|
||||
},
|
||||
|
||||
_startAnimation: function kp_startAnimation() {
|
||||
let c = kExponentialC;
|
||||
function getNextPosition(position, v, a, t) {
|
||||
// Important traits for this function:
|
||||
// p(t=0) is 0
|
||||
// p'(t=0) is v0
|
||||
//
|
||||
// We use exponential to get a smoother stop, but by itself exponential
|
||||
// is too smooth at the end. Adding a polynomial with the appropriate
|
||||
// weight helps to balance
|
||||
position.set(v.x * Math.exp(-t / c) * -c + a.x * t * t + v.x * c,
|
||||
v.y * Math.exp(-t / c) * -c + a.y * t * t + v.y * c);
|
||||
}
|
||||
|
||||
let startTime = content.mozAnimationStartTime;
|
||||
let elapsedTime = 0, targetedTime = 0, averageTime = 0;
|
||||
|
||||
let velocity = this._velocity;
|
||||
let acceleration = this._acceleration;
|
||||
|
||||
let position = this._position;
|
||||
let nextPosition = new Point(0, 0);
|
||||
let delta = new Point(0, 0);
|
||||
|
||||
let callback = (function(timestamp) {
|
||||
if (!this.target)
|
||||
return;
|
||||
|
||||
// To make animation end fast enough but to keep smoothness, average the
|
||||
// ideal time frame (smooth animation) with the actual time lapse
|
||||
// (end fast enough).
|
||||
// Animation will never take longer than 2 times the ideal length of time.
|
||||
elapsedTime = timestamp - startTime;
|
||||
targetedTime += kUpdateInterval;
|
||||
averageTime = (targetedTime + elapsedTime) / 2;
|
||||
|
||||
// Calculate new position.
|
||||
getNextPosition(nextPosition, velocity, acceleration, averageTime);
|
||||
delta.set(Math.round(nextPosition.x - position.x),
|
||||
Math.round(nextPosition.y - position.y));
|
||||
|
||||
// Test to see if movement is finished for each component.
|
||||
if (delta.x * acceleration.x > 0)
|
||||
delta.x = position.x = velocity.x = acceleration.x = 0;
|
||||
|
||||
if (delta.y * acceleration.y > 0)
|
||||
delta.y = position.y = velocity.y = acceleration.y = 0;
|
||||
|
||||
if (velocity.equals(0, 0) || delta.equals(0, 0)) {
|
||||
this.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
position.add(delta);
|
||||
if (this.target.onKineticPan(delta.scale(-1))) {
|
||||
this.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
content.mozRequestAnimationFrame(callback);
|
||||
}).bind(this);
|
||||
|
||||
content.mozRequestAnimationFrame(callback);
|
||||
}
|
||||
};
|
||||
|
||||
const ElementTouchHelper = {
|
||||
anyElementFromPoint: function(aWindow, aX, aY) {
|
||||
let cwu = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
|
|
@ -0,0 +1,675 @@
|
|||
/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ts=2 sw=2 sts=2 et: */
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
dump("############################### browserElementPanningAPZDisabled.js loaded\n");
|
||||
|
||||
let { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Geometry.jsm");
|
||||
|
||||
var global = this;
|
||||
|
||||
const ContentPanningAPZDisabled = {
|
||||
// Are we listening to touch or mouse events?
|
||||
watchedEventsType: '',
|
||||
|
||||
// Are mouse events being delivered to this content along with touch
|
||||
// events, in violation of spec?
|
||||
hybridEvents: false,
|
||||
|
||||
init: function cp_init() {
|
||||
this._setupListenersForPanning();
|
||||
},
|
||||
|
||||
_setupListenersForPanning: function cp_setupListenersForPanning() {
|
||||
let events;
|
||||
|
||||
if (content.TouchEvent) {
|
||||
events = ['touchstart', 'touchend', 'touchmove'];
|
||||
this.watchedEventsType = 'touch';
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
// The gonk widget backend does not deliver mouse events per
|
||||
// spec. Third-party content isn't exposed to this behavior,
|
||||
// but that behavior creates some extra work for us here.
|
||||
let appInfo = Cc["@mozilla.org/xre/app-info;1"];
|
||||
let isParentProcess =
|
||||
!appInfo || appInfo.getService(Ci.nsIXULRuntime)
|
||||
.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
|
||||
this.hybridEvents = isParentProcess;
|
||||
#endif
|
||||
} else {
|
||||
// Touch events aren't supported, so fall back on mouse.
|
||||
events = ['mousedown', 'mouseup', 'mousemove'];
|
||||
this.watchedEventsType = 'mouse';
|
||||
}
|
||||
|
||||
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(Ci.nsIEventListenerService);
|
||||
|
||||
events.forEach(function(type) {
|
||||
// Using the system group for mouse/touch events to avoid
|
||||
// missing events if .stopPropagation() has been called.
|
||||
els.addSystemEventListener(global, type,
|
||||
this.handleEvent.bind(this),
|
||||
/* useCapture = */ false);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
handleEvent: function cp_handleEvent(evt) {
|
||||
// Ignore events targeting an oop <iframe mozbrowser> since those will be
|
||||
// handle by the BrowserElementPanning.js instance in the child process.
|
||||
if (evt.target instanceof Ci.nsIMozBrowserFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
// For in-process <iframe mozbrowser> the events are not targetting
|
||||
// directly the container iframe element, but some node of the document.
|
||||
// So, the BrowserElementPanning instance of the system app will receive
|
||||
// the sequence of touch events, as well as the BrowserElementPanning
|
||||
// instance in the targetted app.
|
||||
// As a result, multiple mozbrowser iframes will try to interpret the
|
||||
// sequence of touch events, which may results into multiple clicks.
|
||||
let targetWindow = evt.target.ownerDocument.defaultView;
|
||||
let frameElement = targetWindow.frameElement;
|
||||
while (frameElement) {
|
||||
targetWindow = frameElement.ownerDocument.defaultView;
|
||||
frameElement = targetWindow.frameElement;
|
||||
}
|
||||
|
||||
if (content !== targetWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (evt.defaultPrevented || evt.multipleActionsPrevented) {
|
||||
// clean up panning state even if touchend/mouseup has been preventDefault.
|
||||
if(evt.type === 'touchend' || evt.type === 'mouseup') {
|
||||
if (this.dragging &&
|
||||
(this.watchedEventsType === 'mouse' ||
|
||||
this.findPrimaryPointer(evt.changedTouches))) {
|
||||
this._finishPanning();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (evt.type) {
|
||||
case 'mousedown':
|
||||
case 'touchstart':
|
||||
this.onTouchStart(evt);
|
||||
break;
|
||||
case 'mousemove':
|
||||
case 'touchmove':
|
||||
this.onTouchMove(evt);
|
||||
break;
|
||||
case 'mouseup':
|
||||
case 'touchend':
|
||||
this.onTouchEnd(evt);
|
||||
break;
|
||||
case 'click':
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
|
||||
let target = evt.target;
|
||||
let view = target.ownerDocument ? target.ownerDocument.defaultView
|
||||
: target;
|
||||
view.removeEventListener('click', this, true, true);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
position: new Point(0 , 0),
|
||||
|
||||
findPrimaryPointer: function cp_findPrimaryPointer(touches) {
|
||||
if (!('primaryPointerId' in this))
|
||||
return null;
|
||||
|
||||
for (let i = 0; i < touches.length; i++) {
|
||||
if (touches[i].identifier === this.primaryPointerId) {
|
||||
return touches[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
onTouchStart: function cp_onTouchStart(evt) {
|
||||
let screenX, screenY;
|
||||
if (this.watchedEventsType == 'touch') {
|
||||
if ('primaryPointerId' in this || evt.touches.length >= 2) {
|
||||
this._resetActive();
|
||||
return;
|
||||
}
|
||||
|
||||
let firstTouch = evt.changedTouches[0];
|
||||
this.primaryPointerId = firstTouch.identifier;
|
||||
this.pointerDownTarget = firstTouch.target;
|
||||
screenX = firstTouch.screenX;
|
||||
screenY = firstTouch.screenY;
|
||||
} else {
|
||||
this.pointerDownTarget = evt.target;
|
||||
screenX = evt.screenX;
|
||||
screenY = evt.screenY;
|
||||
}
|
||||
this.dragging = true;
|
||||
this.panning = false;
|
||||
|
||||
let oldTarget = this.target;
|
||||
[this.target, this.scrollCallback] = this.getPannable(this.pointerDownTarget);
|
||||
|
||||
// If we have a pointer down target, we may need to fill in for EventStateManager
|
||||
// in setting the active state on the target element. Set a timer to
|
||||
// ensure the pointer-down target is active. (If it's already
|
||||
// active, the timer is a no-op.)
|
||||
if (this.pointerDownTarget !== null) {
|
||||
// If there's no possibility this is a drag/pan, activate now.
|
||||
// Otherwise wait a little bit to see if the gesture isn't a
|
||||
// tap.
|
||||
if (this.target === null) {
|
||||
this.notify(this._activationTimer);
|
||||
} else {
|
||||
this._activationTimer.initWithCallback(this,
|
||||
this._activationDelayMs,
|
||||
Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
}
|
||||
}
|
||||
|
||||
// If there is a pan animation running (from a previous pan gesture) and
|
||||
// the user touch back the screen, stop this animation immediatly and
|
||||
// prevent the possible click action if the touch happens on the same
|
||||
// target.
|
||||
this.preventNextClick = false;
|
||||
if (KineticPanning.active) {
|
||||
KineticPanning.stop();
|
||||
|
||||
if (oldTarget && oldTarget == this.target)
|
||||
this.preventNextClick = true;
|
||||
}
|
||||
|
||||
this.position.set(screenX, screenY);
|
||||
KineticPanning.reset();
|
||||
KineticPanning.record(new Point(0, 0), evt.timeStamp);
|
||||
|
||||
// We prevent start events to avoid sending a focus event at the end of this
|
||||
// touch series. See bug 889717.
|
||||
if ((this.panning || this.preventNextClick)) {
|
||||
evt.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
onTouchEnd: function cp_onTouchEnd(evt) {
|
||||
let touch = null;
|
||||
if (!this.dragging ||
|
||||
(this.watchedEventsType == 'touch' &&
|
||||
!(touch = this.findPrimaryPointer(evt.changedTouches)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// !isPan() and evt.detail should always give the same answer here
|
||||
// since they use the same heuristics, but use the native gecko
|
||||
// computation when possible.
|
||||
//
|
||||
// NB: when we're using touch events, then !KineticPanning.isPan()
|
||||
// => this.panning, so we'll never attempt to block the click
|
||||
// event. That's OK however, because we won't fire a synthetic
|
||||
// click when we're using touch events and this touch series
|
||||
// wasn't a "tap" gesture.
|
||||
let click = (this.watchedEventsType == 'mouse') ?
|
||||
evt.detail : !KineticPanning.isPan();
|
||||
// Additionally, if we're seeing non-compliant hybrid events, a
|
||||
// "real" click will be generated if we started and ended on the
|
||||
// same element.
|
||||
if (this.hybridEvents) {
|
||||
let target =
|
||||
content.document.elementFromPoint(touch.clientX, touch.clientY);
|
||||
click |= (target === this.pointerDownTarget);
|
||||
}
|
||||
|
||||
if (this.target && click && (this.panning || this.preventNextClick)) {
|
||||
if (this.hybridEvents) {
|
||||
let target = this.target;
|
||||
let view = target.ownerDocument ? target.ownerDocument.defaultView
|
||||
: target;
|
||||
view.addEventListener('click', this, true, true);
|
||||
} else {
|
||||
// We prevent end events to avoid sending a focus event. See bug 889717.
|
||||
evt.preventDefault();
|
||||
}
|
||||
} else if (this.target && click && !this.panning) {
|
||||
this.notify(this._activationTimer);
|
||||
}
|
||||
|
||||
this._finishPanning();
|
||||
|
||||
// Now that we're done, avoid entraining the thing we just panned.
|
||||
this.pointerDownTarget = null;
|
||||
},
|
||||
|
||||
onTouchMove: function cp_onTouchMove(evt) {
|
||||
if (!this.dragging)
|
||||
return;
|
||||
|
||||
let screenX, screenY;
|
||||
if (this.watchedEventsType == 'touch') {
|
||||
let primaryTouch = this.findPrimaryPointer(evt.changedTouches);
|
||||
if (evt.touches.length > 1 || !primaryTouch)
|
||||
return;
|
||||
screenX = primaryTouch.screenX;
|
||||
screenY = primaryTouch.screenY;
|
||||
} else {
|
||||
screenX = evt.screenX;
|
||||
screenY = evt.screenY;
|
||||
}
|
||||
|
||||
let current = this.position;
|
||||
let delta = new Point(screenX - current.x, screenY - current.y);
|
||||
current.set(screenX, screenY);
|
||||
|
||||
KineticPanning.record(delta, evt.timeStamp);
|
||||
|
||||
let isPan = KineticPanning.isPan();
|
||||
|
||||
// If we've detected a pan gesture, cancel the active state of the
|
||||
// current target.
|
||||
if (!this.panning && isPan) {
|
||||
this._resetActive();
|
||||
}
|
||||
|
||||
// There's no possibility of us panning anything.
|
||||
if (!this.scrollCallback) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scroll manually.
|
||||
this.scrollCallback(delta.scale(-1));
|
||||
|
||||
if (!this.panning && isPan) {
|
||||
this.panning = true;
|
||||
this._activationTimer.cancel();
|
||||
}
|
||||
|
||||
if (this.panning) {
|
||||
// Only do this when we're actually executing a pan gesture.
|
||||
// Otherwise synthetic mouse events will be canceled.
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
// nsITimerCallback
|
||||
notify: function cp_notify(timer) {
|
||||
this._setActive(this.pointerDownTarget);
|
||||
},
|
||||
|
||||
onKineticBegin: function cp_onKineticBegin(evt) {
|
||||
},
|
||||
|
||||
onKineticPan: function cp_onKineticPan(delta) {
|
||||
return !this.scrollCallback(delta);
|
||||
},
|
||||
|
||||
onKineticEnd: function cp_onKineticEnd() {
|
||||
if (!this.dragging)
|
||||
this.scrollCallback = null;
|
||||
},
|
||||
|
||||
getPannable: function cp_getPannable(node) {
|
||||
let pannableNode = this._findPannable(node);
|
||||
if (pannableNode) {
|
||||
return [pannableNode, this._generateCallback(pannableNode)];
|
||||
}
|
||||
|
||||
return [null, null];
|
||||
},
|
||||
|
||||
_findPannable: function cp_findPannable(node) {
|
||||
if (!(node instanceof Ci.nsIDOMHTMLElement) || node.tagName == 'HTML') {
|
||||
return null;
|
||||
}
|
||||
|
||||
let nodeContent = node.ownerDocument.defaultView;
|
||||
while (!(node instanceof Ci.nsIDOMHTMLBodyElement)) {
|
||||
let style = nodeContent.getComputedStyle(node, null);
|
||||
|
||||
let overflow = [style.getPropertyValue('overflow'),
|
||||
style.getPropertyValue('overflow-x'),
|
||||
style.getPropertyValue('overflow-y')];
|
||||
|
||||
let rect = node.getBoundingClientRect();
|
||||
let isAuto = (overflow.indexOf('auto') != -1 &&
|
||||
(rect.height < node.scrollHeight ||
|
||||
rect.width < node.scrollWidth));
|
||||
|
||||
let isScroll = (overflow.indexOf('scroll') != -1);
|
||||
|
||||
let isScrollableTextarea = (node.tagName == 'TEXTAREA' &&
|
||||
(node.scrollHeight > node.clientHeight ||
|
||||
node.scrollWidth > node.clientWidth ||
|
||||
('scrollLeftMax' in node && node.scrollLeftMax > 0) ||
|
||||
('scrollTopMax' in node && node.scrollTopMax > 0)));
|
||||
if (isScroll || isAuto || isScrollableTextarea) {
|
||||
return node;
|
||||
}
|
||||
|
||||
node = node.parentNode;
|
||||
}
|
||||
|
||||
if (nodeContent.scrollMaxX || nodeContent.scrollMaxY) {
|
||||
return nodeContent;
|
||||
}
|
||||
|
||||
if (nodeContent.frameElement) {
|
||||
return this._findPannable(nodeContent.frameElement);
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
_generateCallback: function cp_generateCallback(root) {
|
||||
let firstScroll = true;
|
||||
let target;
|
||||
let current;
|
||||
let win, doc, htmlNode, bodyNode;
|
||||
|
||||
function doScroll(node, delta) {
|
||||
if (node instanceof Ci.nsIDOMHTMLElement) {
|
||||
return node.scrollByNoFlush(delta.x, delta.y);
|
||||
} else if (node instanceof Ci.nsIDOMWindow) {
|
||||
win = node;
|
||||
doc = win.document;
|
||||
|
||||
// "overflow:hidden" on either the <html> or the <body> node should
|
||||
// prevent the user from scrolling the root viewport.
|
||||
if (doc instanceof Ci.nsIDOMHTMLDocument) {
|
||||
htmlNode = doc.documentElement;
|
||||
bodyNode = doc.body;
|
||||
if (win.getComputedStyle(htmlNode, null).overflowX == "hidden" ||
|
||||
win.getComputedStyle(bodyNode, null).overflowX == "hidden") {
|
||||
delta.x = 0;
|
||||
}
|
||||
if (win.getComputedStyle(htmlNode, null).overflowY == "hidden" ||
|
||||
win.getComputedStyle(bodyNode, null).overflowY == "hidden") {
|
||||
delta.y = 0;
|
||||
}
|
||||
}
|
||||
let oldX = node.scrollX;
|
||||
let oldY = node.scrollY;
|
||||
node.scrollBy(delta.x, delta.y);
|
||||
return (node.scrollX != oldX || node.scrollY != oldY);
|
||||
}
|
||||
// If we get here, |node| isn't an HTML element and it's not a window,
|
||||
// but findPannable apparently thought it was scrollable... What is it?
|
||||
return false;
|
||||
}
|
||||
|
||||
function targetParent(node) {
|
||||
return node.parentNode || node.frameElement || null;
|
||||
}
|
||||
|
||||
function scroll(delta) {
|
||||
current = root;
|
||||
firstScroll = true;
|
||||
while (current) {
|
||||
if (doScroll(current, delta)) {
|
||||
firstScroll = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO The current code looks for possible scrolling regions only if
|
||||
// this is the first scroll action but this should be more dynamic.
|
||||
if (!firstScroll) {
|
||||
return false;
|
||||
}
|
||||
|
||||
current = ContentPanningAPZDisabled._findPannable(targetParent(current));
|
||||
}
|
||||
|
||||
// There is nothing scrollable here.
|
||||
return false;
|
||||
}
|
||||
return scroll;
|
||||
},
|
||||
|
||||
get _activationTimer() {
|
||||
delete this._activationTimer;
|
||||
return this._activationTimer = Cc["@mozilla.org/timer;1"]
|
||||
.createInstance(Ci.nsITimer);
|
||||
},
|
||||
|
||||
get _activationDelayMs() {
|
||||
let delay = Services.prefs.getIntPref('ui.touch_activation.delay_ms');
|
||||
delete this._activationDelayMs;
|
||||
return this._activationDelayMs = delay;
|
||||
},
|
||||
|
||||
get _domUtils() {
|
||||
delete this._domUtils;
|
||||
return this._domUtils = Cc['@mozilla.org/inspector/dom-utils;1']
|
||||
.getService(Ci.inIDOMUtils);
|
||||
},
|
||||
|
||||
_resetActive: function cp_resetActive() {
|
||||
let elt = this.pointerDownTarget || this.target;
|
||||
let root = elt.ownerDocument || elt.document;
|
||||
this._setActive(root.documentElement);
|
||||
},
|
||||
|
||||
_setActive: function cp_setActive(elt) {
|
||||
const kStateActive = 0x00000001;
|
||||
this._domUtils.setContentState(elt, kStateActive);
|
||||
},
|
||||
|
||||
_finishPanning: function() {
|
||||
this.dragging = false;
|
||||
delete this.primaryPointerId;
|
||||
this._activationTimer.cancel();
|
||||
|
||||
// If there is a scroll action, let's do a manual kinetic panning action.
|
||||
if (this.panning) {
|
||||
KineticPanning.start(this);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Min/max velocity of kinetic panning. This is in pixels/millisecond.
|
||||
const kMinVelocity = 0.2;
|
||||
const kMaxVelocity = 6;
|
||||
|
||||
// Constants that affect the "friction" of the scroll pane.
|
||||
const kExponentialC = 1000;
|
||||
const kPolynomialC = 100 / 1000000;
|
||||
|
||||
// How often do we change the position of the scroll pane?
|
||||
// Too often and panning may jerk near the end.
|
||||
// Too little and panning will be choppy. In milliseconds.
|
||||
const kUpdateInterval = 16;
|
||||
|
||||
// The numbers of momentums to use for calculating the velocity of the pan.
|
||||
// Those are taken from the end of the action
|
||||
const kSamples = 5;
|
||||
|
||||
const KineticPanning = {
|
||||
_position: new Point(0, 0),
|
||||
_velocity: new Point(0, 0),
|
||||
_acceleration: new Point(0, 0),
|
||||
|
||||
get active() {
|
||||
return this.target !== null;
|
||||
},
|
||||
|
||||
target: null,
|
||||
start: function kp_start(target) {
|
||||
this.target = target;
|
||||
|
||||
// Calculate the initial velocity of the movement based on user input
|
||||
let momentums = this.momentums;
|
||||
let flick = momentums[momentums.length - 1].time - momentums[0].time < 300;
|
||||
|
||||
let distance = new Point(0, 0);
|
||||
momentums.forEach(function(momentum) {
|
||||
distance.add(momentum.dx, momentum.dy);
|
||||
});
|
||||
|
||||
function clampFromZero(x, min, max) {
|
||||
if (x >= 0)
|
||||
return Math.max(min, Math.min(max, x));
|
||||
return Math.min(-min, Math.max(-max, x));
|
||||
}
|
||||
|
||||
let elapsed = momentums[momentums.length - 1].time - momentums[0].time;
|
||||
let velocityX = clampFromZero(distance.x / elapsed, 0, kMaxVelocity);
|
||||
let velocityY = clampFromZero(distance.y / elapsed, 0, kMaxVelocity);
|
||||
|
||||
let velocity = this._velocity;
|
||||
if (flick) {
|
||||
// Very fast pan action that does not generate a click are very often pan
|
||||
// action. If this is a small gesture then it will not move the view a lot
|
||||
// and so it will be above the minimun threshold and not generate any
|
||||
// kinetic panning. This does not look on a device since this is often
|
||||
// a real gesture, so let's lower the velocity threshold for such moves.
|
||||
velocity.set(velocityX, velocityY);
|
||||
} else {
|
||||
velocity.set(Math.abs(velocityX) < kMinVelocity ? 0 : velocityX,
|
||||
Math.abs(velocityY) < kMinVelocity ? 0 : velocityY);
|
||||
}
|
||||
this.momentums = [];
|
||||
|
||||
// Set acceleration vector to opposite signs of velocity
|
||||
function sign(x) {
|
||||
return x ? (x > 0 ? 1 : -1) : 0;
|
||||
}
|
||||
|
||||
this._acceleration.set(velocity.clone().map(sign).scale(-kPolynomialC));
|
||||
|
||||
// Reset the position
|
||||
this._position.set(0, 0);
|
||||
|
||||
this._startAnimation();
|
||||
|
||||
this.target.onKineticBegin();
|
||||
},
|
||||
|
||||
stop: function kp_stop() {
|
||||
this.reset();
|
||||
|
||||
if (!this.target)
|
||||
return;
|
||||
|
||||
this.target.onKineticEnd();
|
||||
this.target = null;
|
||||
},
|
||||
|
||||
reset: function kp_reset() {
|
||||
this.momentums = [];
|
||||
this.distance.set(0, 0);
|
||||
},
|
||||
|
||||
momentums: [],
|
||||
record: function kp_record(delta, timestamp) {
|
||||
this.momentums.push({ 'time': this._getTime(timestamp),
|
||||
'dx' : delta.x, 'dy' : delta.y });
|
||||
|
||||
// We only need to keep kSamples in this.momentums.
|
||||
if (this.momentums.length > kSamples) {
|
||||
this.momentums.shift();
|
||||
}
|
||||
|
||||
this.distance.add(delta.x, delta.y);
|
||||
},
|
||||
|
||||
_getTime: function kp_getTime(time) {
|
||||
// Touch events generated by the platform or hand-made are defined in
|
||||
// microseconds instead of milliseconds. Bug 77992 will fix this at the
|
||||
// platform level.
|
||||
if (time > Date.now()) {
|
||||
return Math.floor(time / 1000);
|
||||
} else {
|
||||
return time;
|
||||
}
|
||||
},
|
||||
|
||||
get threshold() {
|
||||
let dpi = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.displayDPI;
|
||||
|
||||
let threshold = Services.prefs.getIntPref('ui.dragThresholdX') / 240 * dpi;
|
||||
|
||||
delete this.threshold;
|
||||
return this.threshold = threshold;
|
||||
},
|
||||
|
||||
distance: new Point(0, 0),
|
||||
isPan: function cp_isPan() {
|
||||
return (Math.abs(this.distance.x) > this.threshold ||
|
||||
Math.abs(this.distance.y) > this.threshold);
|
||||
},
|
||||
|
||||
_startAnimation: function kp_startAnimation() {
|
||||
let c = kExponentialC;
|
||||
function getNextPosition(position, v, a, t) {
|
||||
// Important traits for this function:
|
||||
// p(t=0) is 0
|
||||
// p'(t=0) is v0
|
||||
//
|
||||
// We use exponential to get a smoother stop, but by itself exponential
|
||||
// is too smooth at the end. Adding a polynomial with the appropriate
|
||||
// weight helps to balance
|
||||
position.set(v.x * Math.exp(-t / c) * -c + a.x * t * t + v.x * c,
|
||||
v.y * Math.exp(-t / c) * -c + a.y * t * t + v.y * c);
|
||||
}
|
||||
|
||||
let startTime = content.mozAnimationStartTime;
|
||||
let elapsedTime = 0, targetedTime = 0, averageTime = 0;
|
||||
|
||||
let velocity = this._velocity;
|
||||
let acceleration = this._acceleration;
|
||||
|
||||
let position = this._position;
|
||||
let nextPosition = new Point(0, 0);
|
||||
let delta = new Point(0, 0);
|
||||
|
||||
let callback = (function(timestamp) {
|
||||
if (!this.target)
|
||||
return;
|
||||
|
||||
// To make animation end fast enough but to keep smoothness, average the
|
||||
// ideal time frame (smooth animation) with the actual time lapse
|
||||
// (end fast enough).
|
||||
// Animation will never take longer than 2 times the ideal length of time.
|
||||
elapsedTime = timestamp - startTime;
|
||||
targetedTime += kUpdateInterval;
|
||||
averageTime = (targetedTime + elapsedTime) / 2;
|
||||
|
||||
// Calculate new position.
|
||||
getNextPosition(nextPosition, velocity, acceleration, averageTime);
|
||||
delta.set(Math.round(nextPosition.x - position.x),
|
||||
Math.round(nextPosition.y - position.y));
|
||||
|
||||
// Test to see if movement is finished for each component.
|
||||
if (delta.x * acceleration.x > 0)
|
||||
delta.x = position.x = velocity.x = acceleration.x = 0;
|
||||
|
||||
if (delta.y * acceleration.y > 0)
|
||||
delta.y = position.y = velocity.y = acceleration.y = 0;
|
||||
|
||||
if (velocity.equals(0, 0) || delta.equals(0, 0)) {
|
||||
this.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
position.add(delta);
|
||||
if (this.target.onKineticPan(delta.scale(-1))) {
|
||||
this.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
content.mozRequestAnimationFrame(callback);
|
||||
}).bind(this);
|
||||
|
||||
content.mozRequestAnimationFrame(callback);
|
||||
}
|
||||
};
|
|
@ -111,8 +111,7 @@ const browserElementTestHelpers = {
|
|||
|
||||
// Returns a promise which is resolved when a subprocess is created. The
|
||||
// argument to resolve() is the childID of the subprocess.
|
||||
function expectProcessCreated(/* optional */ initialPriority,
|
||||
/* optional */ initialCPUPriority) {
|
||||
function expectProcessCreated(/* optional */ initialPriority) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var observed = false;
|
||||
browserElementTestHelpers.addProcessPriorityObserver(
|
||||
|
@ -128,7 +127,7 @@ function expectProcessCreated(/* optional */ initialPriority,
|
|||
var childID = parseInt(data);
|
||||
ok(true, 'Got new process, id=' + childID);
|
||||
if (initialPriority) {
|
||||
expectPriorityChange(childID, initialPriority, initialCPUPriority).then(function() {
|
||||
expectPriorityChange(childID, initialPriority).then(function() {
|
||||
resolve(childID);
|
||||
});
|
||||
} else {
|
||||
|
@ -141,9 +140,8 @@ function expectProcessCreated(/* optional */ initialPriority,
|
|||
|
||||
// Just like expectProcessCreated(), except we'll call ok(false) if a second
|
||||
// process is created.
|
||||
function expectOnlyOneProcessCreated(/* optional */ initialPriority,
|
||||
/* optional */ initialCPUPriority) {
|
||||
var p = expectProcessCreated(initialPriority, initialCPUPriority);
|
||||
function expectOnlyOneProcessCreated(/* optional */ initialPriority) {
|
||||
var p = expectProcessCreated(initialPriority);
|
||||
p.then(function() {
|
||||
expectProcessCreated().then(function(childID) {
|
||||
ok(false, 'Got unexpected process creation, childID=' + childID);
|
||||
|
@ -153,15 +151,10 @@ function expectOnlyOneProcessCreated(/* optional */ initialPriority,
|
|||
}
|
||||
|
||||
// Returns a promise which is resolved or rejected the next time the process
|
||||
// childID changes its priority. We resolve if the (priority, CPU priority)
|
||||
// tuple matches (expectedPriority, expectedCPUPriority) and we reject
|
||||
// otherwise.
|
||||
//
|
||||
// expectedCPUPriority is an optional argument; if it's not specified, we
|
||||
// resolve if priority matches expectedPriority.
|
||||
// childID changes its priority. We resolve if the priority matches
|
||||
// expectedPriority, and we reject otherwise.
|
||||
|
||||
function expectPriorityChange(childID, expectedPriority,
|
||||
/* optional */ expectedCPUPriority) {
|
||||
function expectPriorityChange(childID, expectedPriority) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var observed = false;
|
||||
browserElementTestHelpers.addProcessPriorityObserver(
|
||||
|
@ -171,7 +164,7 @@ function expectPriorityChange(childID, expectedPriority,
|
|||
return;
|
||||
}
|
||||
|
||||
var [id, priority, cpuPriority] = data.split(":");
|
||||
var [id, priority] = data.split(":");
|
||||
if (id != childID) {
|
||||
return;
|
||||
}
|
||||
|
@ -184,14 +177,7 @@ function expectPriorityChange(childID, expectedPriority,
|
|||
'Expected priority of childID ' + childID +
|
||||
' to change to ' + expectedPriority);
|
||||
|
||||
if (expectedCPUPriority) {
|
||||
is(cpuPriority, expectedCPUPriority,
|
||||
'Expected CPU priority of childID ' + childID +
|
||||
' to change to ' + expectedCPUPriority);
|
||||
}
|
||||
|
||||
if (priority == expectedPriority &&
|
||||
(!expectedCPUPriority || expectedCPUPriority == cpuPriority)) {
|
||||
if (priority == expectedPriority) {
|
||||
resolve();
|
||||
} else {
|
||||
reject();
|
||||
|
@ -212,13 +198,14 @@ function expectPriorityWithBackgroundLRUSet(childID, expectedBackgroundLRU) {
|
|||
'process-priority-with-background-LRU-set',
|
||||
function(subject, topic, data) {
|
||||
|
||||
var [id, priority, cpuPriority, backgroundLRU] = data.split(":");
|
||||
var [id, priority, backgroundLRU] = data.split(":");
|
||||
if (id != childID) {
|
||||
return;
|
||||
}
|
||||
|
||||
is(backgroundLRU, expectedBackgroundLRU,
|
||||
'Expected backgroundLRU ' + backgroundLRU + ' of childID ' + childID +
|
||||
'Expected backgroundLRU ' + backgroundLRU +
|
||||
' of childID ' + childID +
|
||||
' to change to ' + expectedBackgroundLRU);
|
||||
|
||||
if (backgroundLRU == expectedBackgroundLRU) {
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
A word to the wise:
|
||||
|
||||
You must ensure that if your test finishes successfully, no processes have
|
||||
priority FOREGROUND_HIGH.
|
||||
|
||||
If you don't do this, expect to see tests randomly fail with mysterious
|
||||
FOREGROUND --> FOREGROUND priority transitions.
|
||||
|
||||
What's happening in this case is that your FOREGROUND_HIGH process lives until
|
||||
the beginning of the next test. This causes the process started by the next
|
||||
test to have low CPU priority. Then the FOREGROUND_HIGH process dies, because
|
||||
its iframe gets GC'ed, and we transition the new test's process from low CPU
|
||||
priority to regular CPU priority.
|
||||
|
||||
Ouch.
|
|
@ -10,8 +10,6 @@ skip-if = toolkit != "gtk2" || ((buildapp =='mulet' || buildapp == 'b2g') && (to
|
|||
[test_Visibility.html]
|
||||
[test_HighPriority.html]
|
||||
support-files = file_HighPriority.html
|
||||
[test_HighPriorityDowngrade.html]
|
||||
[test_HighPriorityDowngrade2.html]
|
||||
[test_Background.html]
|
||||
[test_BackgroundLRU.html]
|
||||
[test_Audio.html]
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test that high-priority processes downgrade the CPU priority of regular
|
||||
processes.
|
||||
-->
|
||||
<head>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="../browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="application/javascript;version=1.7">
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
browserElementTestHelpers.enableProcessPriorityManager();
|
||||
SpecialPowers.addPermission("embed-apps", true, document);
|
||||
|
||||
var iframe = null;
|
||||
var childID = null;
|
||||
|
||||
function runTest() {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', true);
|
||||
|
||||
iframe.src = browserElementTestHelpers.emptyPage1;
|
||||
|
||||
var highPriorityIframe = null;
|
||||
var childID = null;
|
||||
var lock = null;
|
||||
var p = null;
|
||||
|
||||
expectProcessCreated('FOREGROUND', 'CPU_NORMAL').then(function(chid) {
|
||||
childID = chid;
|
||||
}).then(function() {
|
||||
// Create a new, high-priority iframe.
|
||||
highPriorityIframe = document.createElement('iframe');
|
||||
highPriorityIframe.setAttribute('mozbrowser', true);
|
||||
highPriorityIframe.setAttribute('expecting-system-message', true);
|
||||
highPriorityIframe.setAttribute('mozapptype', 'critical');
|
||||
highPriorityIframe.setAttribute('mozapp', 'http://example.org/manifest.webapp');
|
||||
highPriorityIframe.src = browserElementTestHelpers.emptyPage2;
|
||||
|
||||
p = expectPriorityChange(childID, 'FOREGROUND', 'CPU_LOW');
|
||||
|
||||
document.body.appendChild(highPriorityIframe);
|
||||
|
||||
return p;
|
||||
}).then(function() {
|
||||
return expectPriorityChange(childID, 'FOREGROUND', 'CPU_NORMAL');
|
||||
}).then(function() {
|
||||
p = expectPriorityChange(childID, 'FOREGROUND', 'CPU_LOW');
|
||||
lock = navigator.requestWakeLock('high-priority');
|
||||
return p;
|
||||
}).then(function() {
|
||||
p = expectPriorityChange(childID, 'FOREGROUND', 'CPU_NORMAL');
|
||||
lock.unlock();
|
||||
return p;
|
||||
}).then(SimpleTest.finish);
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
|
||||
addEventListener('testready', function() {
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{set: [
|
||||
/* Cause the CPU wake lock taken on behalf of the high-priority process
|
||||
* to time out after 1s. */
|
||||
["dom.ipc.systemMessageCPULockTimeoutSec", 1],
|
||||
["dom.wakelock.enabled", true]
|
||||
]},
|
||||
runTest);
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,76 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test that high-priority processes downgrade the CPU priority of regular
|
||||
processes.
|
||||
|
||||
This is just like test_HighPriorityDowngrade, except instead of waiting for the
|
||||
high-priority process's wake lock to expire, we kill the process by removing
|
||||
its iframe from the DOM.
|
||||
-->
|
||||
<head>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="../browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="application/javascript;version=1.7">
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
browserElementTestHelpers.enableProcessPriorityManager();
|
||||
SpecialPowers.addPermission("embed-apps", true, document);
|
||||
|
||||
function runTest() {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', true);
|
||||
|
||||
iframe.src = browserElementTestHelpers.emptyPage1;
|
||||
|
||||
var highPriorityIframe = null;
|
||||
var childID = null;
|
||||
|
||||
expectProcessCreated('FOREGROUND', 'CPU_NORMAL').then(function(chid) {
|
||||
childID = chid;
|
||||
}).then(function() {
|
||||
// Create a new, high-priority iframe.
|
||||
highPriorityIframe = document.createElement('iframe');
|
||||
highPriorityIframe.setAttribute('mozbrowser', true);
|
||||
highPriorityIframe.setAttribute('expecting-system-message', true);
|
||||
highPriorityIframe.setAttribute('mozapptype', 'critical');
|
||||
highPriorityIframe.setAttribute('mozapp', 'http://example.org/manifest.webapp');
|
||||
highPriorityIframe.src = browserElementTestHelpers.emptyPage2;
|
||||
|
||||
var p = Promise.all(
|
||||
[expectPriorityChange(childID, 'FOREGROUND', 'CPU_LOW'),
|
||||
expectMozbrowserEvent(highPriorityIframe, 'loadend')]
|
||||
);
|
||||
|
||||
document.body.appendChild(highPriorityIframe);
|
||||
|
||||
return p;
|
||||
}).then(function() {
|
||||
// Killing the high-priority iframe should cause our CPU priority to go back
|
||||
// up to regular.
|
||||
var p = expectPriorityChange(childID, 'FOREGROUND', 'CPU_NORMAL');
|
||||
document.body.removeChild(highPriorityIframe);
|
||||
return p;
|
||||
}).then(SimpleTest.finish);
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
|
||||
addEventListener('testready', function() {
|
||||
// Cause the CPU wake lock taken on behalf of the high-priority process never
|
||||
// to time out during this test.
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{set: [["dom.ipc.systemMessageCPULockTimeoutSec", 1000]]},
|
||||
runTest);
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -53,7 +53,7 @@ function runTest()
|
|||
|
||||
// Ensure that the preallocated process initially gets BACKGROUND priority.
|
||||
// That's it.
|
||||
expectProcessCreated('PREALLOC', 'CPU_LOW').then(function() {
|
||||
expectProcessCreated('PREALLOC').then(function() {
|
||||
// We need to set the pref asynchoronously or the preallocated process won't
|
||||
// be shut down.
|
||||
SimpleTest.executeSoon(function(){
|
||||
|
|
|
@ -499,6 +499,7 @@ support-files = webgl-conformance/../webgl-mochitest/driver-info.js
|
|||
[webgl-conformance/_wrappers/test_conformance__buffers__index-validation-with-resized-buffer.html]
|
||||
[webgl-conformance/_wrappers/test_conformance__buffers__index-validation.html]
|
||||
[webgl-conformance/_wrappers/test_conformance__canvas__buffer-offscreen-test.html]
|
||||
skip-if = os == 'android'
|
||||
[webgl-conformance/_wrappers/test_conformance__canvas__buffer-preserve-test.html]
|
||||
[webgl-conformance/_wrappers/test_conformance__canvas__canvas-test.html]
|
||||
[webgl-conformance/_wrappers/test_conformance__canvas__canvas-zero-size.html]
|
||||
|
@ -775,6 +776,7 @@ skip-if = (os == 'android') || (os == 'b2g') || (os == 'linux')
|
|||
[webgl-conformance/_wrappers/test_conformance__textures__texture-npot-video.html]
|
||||
skip-if = os == 'win'
|
||||
[webgl-conformance/_wrappers/test_conformance__textures__texture-npot.html]
|
||||
skip-if = os == 'android'
|
||||
[webgl-conformance/_wrappers/test_conformance__textures__texture-size.html]
|
||||
skip-if = os == 'android'
|
||||
[webgl-conformance/_wrappers/test_conformance__textures__texture-size-cube-maps.html]
|
||||
|
|
|
@ -159,7 +159,7 @@ function do_canvas(row, col, type, options)
|
|||
|
||||
var color = document.getElementById('c' + row).textContent;
|
||||
color = color.substr(5, color.length - 6); // strip off the 'argb()'
|
||||
var colors = color.replace(' ', '', 'g').split(',');
|
||||
var colors = color.replace(/ /g, '').split(',');
|
||||
var r = colors[0]*colors[3],
|
||||
g = colors[1]*colors[3],
|
||||
b = colors[2]*colors[3];
|
||||
|
|
|
@ -122,7 +122,6 @@ function GetExpectedTestFailSet() {
|
|||
failSet['conformance/textures/tex-image-with-format-and-type.html'] = true;
|
||||
failSet['conformance/textures/tex-sub-image-2d.html'] = true;
|
||||
failSet['conformance/textures/texture-mips.html'] = true;
|
||||
failSet['conformance/textures/texture-npot.html'] = true;
|
||||
failSet['conformance/textures/texture-size-cube-maps.html'] = true;
|
||||
} else {
|
||||
// Android 2.3 slaves.
|
||||
|
|
|
@ -53,6 +53,10 @@ skip-if = (os == 'android') || (os == 'b2g') || (os == 'linux')
|
|||
# Crashes on 'Android 2.3'
|
||||
# Asserts on 'B2G ICS Emulator Debug'.
|
||||
skip-if = (os == 'android') || (os == 'b2g') || (os == 'linux')
|
||||
[_wrappers/test_conformance__canvas__buffer-offscreen-test.html]
|
||||
# Causes frequent *blues*: "DMError: Remote Device Error: unable to
|
||||
# connect to 127.0.0.1 after 5 attempts" on 'Android 2.3 Opt'.
|
||||
skip-if = os == 'android'
|
||||
|
||||
########################################################################
|
||||
# Android
|
||||
|
@ -68,6 +72,9 @@ skip-if = os == 'android'
|
|||
[_wrappers/test_conformance__textures__texture-size-cube-maps.html]
|
||||
# Crashes on Android 4.0.
|
||||
skip-if = os == 'android'
|
||||
[_wrappers/test_conformance__textures__texture-npot.html]
|
||||
# Intermittent fail on Android 4.0.
|
||||
skip-if = os == 'android'
|
||||
|
||||
########################################################################
|
||||
# B2G
|
||||
|
|
|
@ -28,9 +28,13 @@ XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
|
|||
"@mozilla.org/settingsService;1",
|
||||
"nsISettingsService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gRadioInterfaceLayer",
|
||||
"@mozilla.org/ril;1",
|
||||
"nsIRadioInterfaceLayer");
|
||||
XPCOMUtils.defineLazyGetter(this, "gRadioInterfaceLayer", function() {
|
||||
let ril = { numRadioInterfaces: 0 };
|
||||
try {
|
||||
ril = Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer);
|
||||
} catch(e) {}
|
||||
return ril;
|
||||
});
|
||||
|
||||
const GONK_CELLBROADCAST_SERVICE_CONTRACTID =
|
||||
"@mozilla.org/cellbroadcast/gonkservice;1";
|
||||
|
|
|
@ -18,7 +18,7 @@ UNIFIED_SOURCES += [
|
|||
'ipc/CellBroadcastParent.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL'] and not CONFIG['DISABLE_MOZ_RIL_GEOLOC']:
|
||||
EXTRA_COMPONENTS += [
|
||||
'gonk/CellBroadcastService.js',
|
||||
'gonk/CellBroadcastService.manifest',
|
||||
|
|
|
@ -33,13 +33,13 @@ function readTemplate(path) {
|
|||
cis.init(fis, "UTF-8", 0, 0);
|
||||
|
||||
var data = "";
|
||||
let (str = {}) {
|
||||
let read = 0;
|
||||
do {
|
||||
read = cis.readString(0xffffffff, str); // read as much as we can and put it in str.value
|
||||
data += str.value;
|
||||
} while (read != 0);
|
||||
}
|
||||
let str = {};
|
||||
let read = 0;
|
||||
do {
|
||||
read = cis.readString(0xffffffff, str); // read as much as we can and put it in str.value
|
||||
data += str.value;
|
||||
} while (read != 0);
|
||||
|
||||
cis.close();
|
||||
return data;
|
||||
}
|
||||
|
@ -52,4 +52,3 @@ function getQuery(request) {
|
|||
});
|
||||
return query;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MLSFallback.h"
|
||||
#include "nsGeoPosition.h"
|
||||
#include "nsIGeolocationProvider.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(MLSFallback, nsITimerCallback)
|
||||
|
||||
MLSFallback::MLSFallback(uint32_t delay)
|
||||
: mDelayMs(delay)
|
||||
{
|
||||
}
|
||||
|
||||
MLSFallback::~MLSFallback()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
MLSFallback::Startup(nsIGeolocationUpdate* aWatcher)
|
||||
{
|
||||
if (mHandoffTimer || mMLSFallbackProvider) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mUpdateWatcher = aWatcher;
|
||||
nsresult rv;
|
||||
mHandoffTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mHandoffTimer->InitWithCallback(this, mDelayMs, nsITimer::TYPE_ONE_SHOT);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MLSFallback::Shutdown()
|
||||
{
|
||||
mUpdateWatcher = nullptr;
|
||||
|
||||
if (mHandoffTimer) {
|
||||
mHandoffTimer->Cancel();
|
||||
mHandoffTimer = nullptr;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if (mMLSFallbackProvider) {
|
||||
rv = mMLSFallbackProvider->Shutdown();
|
||||
mMLSFallbackProvider = nullptr;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MLSFallback::Notify(nsITimer* aTimer)
|
||||
{
|
||||
return CreateMLSFallbackProvider();
|
||||
}
|
||||
|
||||
nsresult
|
||||
MLSFallback::CreateMLSFallbackProvider()
|
||||
{
|
||||
if (mMLSFallbackProvider || !mUpdateWatcher) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
mMLSFallbackProvider = do_CreateInstance("@mozilla.org/geolocation/mls-provider;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mMLSFallbackProvider) {
|
||||
rv = mMLSFallbackProvider->Startup();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mMLSFallbackProvider->Watch(mUpdateWatcher);
|
||||
}
|
||||
}
|
||||
mUpdateWatcher = nullptr;
|
||||
return rv;
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsITimer.h"
|
||||
|
||||
class nsIGeolocationUpdate;
|
||||
class nsIGeolocationProvider;
|
||||
|
||||
/*
|
||||
This class wraps the NetworkGeolocationProvider in a delayed startup.
|
||||
It is for providing a fallback to MLS when:
|
||||
1) using another provider as the primary provider, and
|
||||
2) that primary provider may fail to return a result (i.e. the error returned
|
||||
is indeterminate, or no error callback occurs)
|
||||
|
||||
The intent is that the primary provider is started, then MLSFallback
|
||||
is started with sufficient delay that the primary provider will respond first
|
||||
if successful (in the majority of cases).
|
||||
|
||||
MLS has an average response of 3s, so with the 2s default delay, a response can
|
||||
be expected in 5s.
|
||||
|
||||
Telemetry is recommended to monitor that the primary provider is responding
|
||||
first when expected to do so.
|
||||
*/
|
||||
class MLSFallback : public nsITimerCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
|
||||
explicit MLSFallback(uint32_t delayMs = 2000);
|
||||
nsresult Startup(nsIGeolocationUpdate* aWatcher);
|
||||
nsresult Shutdown();
|
||||
|
||||
private:
|
||||
nsresult CreateMLSFallbackProvider();
|
||||
virtual ~MLSFallback();
|
||||
nsCOMPtr<nsITimer> mHandoffTimer;
|
||||
nsCOMPtr<nsIGeolocationProvider> mMLSFallbackProvider;
|
||||
nsCOMPtr<nsIGeolocationUpdate> mUpdateWatcher;
|
||||
const uint32_t mDelayMs;
|
||||
};
|
||||
|
|
@ -15,6 +15,7 @@ SOURCES += [
|
|||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'MLSFallback.cpp',
|
||||
'nsGeoGridFuzzer.cpp',
|
||||
'nsGeolocationSettings.cpp',
|
||||
'nsGeoPosition.cpp',
|
||||
|
|
|
@ -44,7 +44,7 @@ function sendKeyEventToSubmitForm() {
|
|||
}
|
||||
|
||||
function urlify(aStr) {
|
||||
return aStr.replace(':', '%3A', 'g');
|
||||
return aStr.replace(/:/g, '%3A');
|
||||
}
|
||||
|
||||
function runTestsForNextInputType()
|
||||
|
|
|
@ -42,7 +42,7 @@ function testNumSame() {
|
|||
is(document.all.id3.length, 3, "three length");
|
||||
}
|
||||
testNumSame();
|
||||
p.innerHTML = p.innerHTML.replace("id=", "name=", "g");
|
||||
p.innerHTML = p.innerHTML.replace(/id=/g, "name=");
|
||||
testNumSame();
|
||||
|
||||
|
||||
|
|
|
@ -580,10 +580,10 @@ function checkMPSubmission(sub, expected, test) {
|
|||
return l;
|
||||
}
|
||||
function mpquote(s) {
|
||||
return s.replace("\r\n", " ", "g")
|
||||
.replace("\r", " ", "g")
|
||||
.replace("\n", " ", "g")
|
||||
.replace("\"", "\\\"", "g");
|
||||
return s.replace(/\r\n/g, " ")
|
||||
.replace(/\r/g, " ")
|
||||
.replace(/\n/g, " ")
|
||||
.replace(/\"/g, "\\\"");
|
||||
}
|
||||
|
||||
is(sub.length, expected.length,
|
||||
|
@ -628,9 +628,9 @@ function utf8encode(s) {
|
|||
|
||||
function checkURLSubmission(sub, expected) {
|
||||
function urlEscape(s) {
|
||||
return escape(utf8encode(s)).replace("%20", "+", "g")
|
||||
.replace("/", "%2F", "g")
|
||||
.replace("@", "%40", "g");
|
||||
return escape(utf8encode(s)).replace(/%20/g, "+")
|
||||
.replace(/\//g, "%2F")
|
||||
.replace(/@/g, "%40");
|
||||
}
|
||||
|
||||
subItems = sub.split("&");
|
||||
|
|
|
@ -452,7 +452,8 @@ private:
|
|||
return rv;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!JS_SetElement(aCx, array, index, value))) {
|
||||
if (NS_WARN_IF(!JS_DefineElement(aCx, array, index, value,
|
||||
JSPROP_ENUMERATE))) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
@ -505,7 +506,8 @@ private:
|
|||
return rv;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!JS_SetElement(aCx, array, index, value))) {
|
||||
if (NS_WARN_IF(!JS_DefineElement(aCx, array, index, value,
|
||||
JSPROP_ENUMERATE))) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
@ -1094,7 +1096,7 @@ BackgroundFactoryRequestChild::Recv__delete__(
|
|||
|
||||
IDBOpenDBRequest* request = GetOpenDBRequest();
|
||||
MOZ_ASSERT(request);
|
||||
|
||||
|
||||
request->NoteComplete();
|
||||
|
||||
if (NS_WARN_IF(!result)) {
|
||||
|
|
|
@ -218,7 +218,7 @@ Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd,
|
|||
|
||||
aTypeOffset = 0;
|
||||
|
||||
if (!JS_SetElement(aCx, array, index++, val)) {
|
||||
if (!JS_DefineElement(aCx, array, index++, val, JSPROP_ENUMERATE)) {
|
||||
NS_WARNING("Failed to set array element!");
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
|
|
|
@ -359,7 +359,7 @@ KeyPath::ExtractKeyAsJSVal(JSContext* aCx, const JS::Value& aValue,
|
|||
return rv;
|
||||
}
|
||||
|
||||
if (!JS_SetElement(aCx, arrayObj, i, value)) {
|
||||
if (!JS_DefineElement(aCx, arrayObj, i, value, JSPROP_ENUMERATE)) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
@ -471,7 +471,7 @@ KeyPath::ToJSVal(JSContext* aCx, JS::MutableHandle<JS::Value> aValue) const
|
|||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
if (!JS_SetElement(aCx, array, i, val)) {
|
||||
if (!JS_DefineElement(aCx, array, i, val, JSPROP_ENUMERATE)) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
|
|
@ -138,13 +138,6 @@ public:
|
|||
void FireTestOnlyObserverNotification(const char* aTopic,
|
||||
const nsACString& aData = EmptyCString());
|
||||
|
||||
/**
|
||||
* Does some process, other than the one handled by aParticularManager, have
|
||||
* priority FOREGROUND_HIGH?
|
||||
*/
|
||||
bool OtherProcessHasHighPriority(
|
||||
ParticularProcessPriorityManager* aParticularManager);
|
||||
|
||||
/**
|
||||
* Does one of the child processes have priority FOREGROUND_HIGH?
|
||||
*/
|
||||
|
@ -182,7 +175,6 @@ private:
|
|||
|
||||
void ObserveContentParentCreated(nsISupports* aContentParent);
|
||||
void ObserveContentParentDestroyed(nsISupports* aSubject);
|
||||
void ResetAllCPUPriorities();
|
||||
|
||||
nsDataHashtable<nsUint64HashKey, nsRefPtr<ParticularProcessPriorityManager> >
|
||||
mParticularManagers;
|
||||
|
@ -267,23 +259,11 @@ public:
|
|||
|
||||
ProcessPriority CurrentPriority();
|
||||
ProcessPriority ComputePriority();
|
||||
ProcessCPUPriority ComputeCPUPriority(ProcessPriority aPriority);
|
||||
|
||||
void ScheduleResetPriority(const char* aTimeoutPref);
|
||||
void ResetPriority();
|
||||
void ResetPriorityNow();
|
||||
void ResetCPUPriorityNow();
|
||||
|
||||
/**
|
||||
* This overload is equivalent to SetPriorityNow(aPriority,
|
||||
* ComputeCPUPriority()).
|
||||
*/
|
||||
void SetPriorityNow(ProcessPriority aPriority,
|
||||
uint32_t aBackgroundLRU = 0);
|
||||
|
||||
void SetPriorityNow(ProcessPriority aPriority,
|
||||
ProcessCPUPriority aCPUPriority,
|
||||
uint32_t aBackgroundLRU = 0);
|
||||
void SetPriorityNow(ProcessPriority aPriority, uint32_t aBackgroundLRU = 0);
|
||||
|
||||
void ShutDown();
|
||||
|
||||
|
@ -299,7 +279,6 @@ private:
|
|||
ContentParent* mContentParent;
|
||||
uint64_t mChildID;
|
||||
ProcessPriority mPriority;
|
||||
ProcessCPUPriority mCPUPriority;
|
||||
bool mHoldsCPUWakeLock;
|
||||
bool mHoldsHighPriorityWakeLock;
|
||||
|
||||
|
@ -439,8 +418,7 @@ ProcessPriorityManagerImpl::Init()
|
|||
// The master process's priority never changes; set it here and then forget
|
||||
// about it. We'll manage only subprocesses' priorities using the process
|
||||
// priority manager.
|
||||
hal::SetProcessPriority(getpid(), PROCESS_PRIORITY_MASTER,
|
||||
PROCESS_CPU_PRIORITY_NORMAL);
|
||||
hal::SetProcessPriority(getpid(), PROCESS_PRIORITY_MASTER);
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (os) {
|
||||
|
@ -517,18 +495,6 @@ ProcessPriorityManagerImpl::ObserveContentParentCreated(
|
|||
GetParticularProcessPriorityManager(cp->AsContentParent());
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
EnumerateParticularProcessPriorityManagers(
|
||||
const uint64_t& aKey,
|
||||
nsRefPtr<ParticularProcessPriorityManager> aValue,
|
||||
void* aUserData)
|
||||
{
|
||||
nsTArray<nsRefPtr<ParticularProcessPriorityManager> >* aArray =
|
||||
static_cast<nsTArray<nsRefPtr<ParticularProcessPriorityManager> >*>(aUserData);
|
||||
aArray->AppendElement(aValue);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
ProcessPriorityManagerImpl::ObserveContentParentDestroyed(nsISupports* aSubject)
|
||||
{
|
||||
|
@ -548,38 +514,10 @@ ProcessPriorityManagerImpl::ObserveContentParentDestroyed(nsISupports* aSubject)
|
|||
|
||||
if (mHighPriorityChildIDs.Contains(childID)) {
|
||||
mHighPriorityChildIDs.RemoveEntry(childID);
|
||||
|
||||
// We just lost a high-priority process; reset everyone's CPU priorities.
|
||||
ResetAllCPUPriorities();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProcessPriorityManagerImpl::ResetAllCPUPriorities( void )
|
||||
{
|
||||
nsTArray<nsRefPtr<ParticularProcessPriorityManager> > pppms;
|
||||
mParticularManagers.EnumerateRead(
|
||||
&EnumerateParticularProcessPriorityManagers,
|
||||
&pppms);
|
||||
|
||||
for (uint32_t i = 0; i < pppms.Length(); i++) {
|
||||
pppms[i]->ResetCPUPriorityNow();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ProcessPriorityManagerImpl::OtherProcessHasHighPriority(
|
||||
ParticularProcessPriorityManager* aParticularManager)
|
||||
{
|
||||
if (mHighPriority) {
|
||||
return true;
|
||||
} else if (mHighPriorityChildIDs.Contains(aParticularManager->ChildID())) {
|
||||
return mHighPriorityChildIDs.Count() > 1;
|
||||
}
|
||||
return mHighPriorityChildIDs.Count() > 0;
|
||||
}
|
||||
|
||||
bool
|
||||
ProcessPriorityManagerImpl::ChildProcessHasHighPriority( void )
|
||||
{
|
||||
|
@ -591,8 +529,9 @@ ProcessPriorityManagerImpl::NotifyProcessPriorityChanged(
|
|||
ParticularProcessPriorityManager* aParticularManager,
|
||||
ProcessPriority aOldPriority)
|
||||
{
|
||||
// This priority change can only affect other processes' priorities if we're
|
||||
// changing to/from FOREGROUND_HIGH.
|
||||
/* We're interested only in changes to/from FOREGROUND_HIGH as we use we
|
||||
* need to track high priority processes so that we can react to their
|
||||
* presence. */
|
||||
|
||||
if (aOldPriority < PROCESS_PRIORITY_FOREGROUND_HIGH &&
|
||||
aParticularManager->CurrentPriority() <
|
||||
|
@ -607,17 +546,6 @@ ProcessPriorityManagerImpl::NotifyProcessPriorityChanged(
|
|||
} else {
|
||||
mHighPriorityChildIDs.RemoveEntry(aParticularManager->ChildID());
|
||||
}
|
||||
|
||||
nsTArray<nsRefPtr<ParticularProcessPriorityManager> > pppms;
|
||||
mParticularManagers.EnumerateRead(
|
||||
&EnumerateParticularProcessPriorityManagers,
|
||||
&pppms);
|
||||
|
||||
for (uint32_t i = 0; i < pppms.Length(); i++) {
|
||||
if (pppms[i] != aParticularManager) {
|
||||
pppms[i]->ResetCPUPriorityNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
|
@ -633,10 +561,6 @@ ProcessPriorityManagerImpl::Notify(const WakeLockInformation& aInfo)
|
|||
mHighPriority = false;
|
||||
}
|
||||
|
||||
/* The main process got a high-priority wakelock change; reset everyone's
|
||||
* CPU priorities. */
|
||||
ResetAllCPUPriorities();
|
||||
|
||||
LOG("Got wake lock changed event. "
|
||||
"Now mHighPriorityParent = %d\n", mHighPriority);
|
||||
}
|
||||
|
@ -653,7 +577,6 @@ ParticularProcessPriorityManager::ParticularProcessPriorityManager(
|
|||
: mContentParent(aContentParent)
|
||||
, mChildID(aContentParent->ChildID())
|
||||
, mPriority(PROCESS_PRIORITY_UNKNOWN)
|
||||
, mCPUPriority(PROCESS_CPU_PRIORITY_NORMAL)
|
||||
, mHoldsCPUWakeLock(false)
|
||||
, mHoldsHighPriorityWakeLock(false)
|
||||
{
|
||||
|
@ -1015,40 +938,9 @@ ParticularProcessPriorityManager::ComputePriority()
|
|||
PROCESS_PRIORITY_BACKGROUND;
|
||||
}
|
||||
|
||||
ProcessCPUPriority
|
||||
ParticularProcessPriorityManager::ComputeCPUPriority(ProcessPriority aPriority)
|
||||
{
|
||||
if (aPriority == PROCESS_PRIORITY_PREALLOC) {
|
||||
return PROCESS_CPU_PRIORITY_LOW;
|
||||
}
|
||||
|
||||
if (aPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH) {
|
||||
return PROCESS_CPU_PRIORITY_NORMAL;
|
||||
}
|
||||
|
||||
return ProcessPriorityManagerImpl::GetSingleton()->
|
||||
OtherProcessHasHighPriority(this) ?
|
||||
PROCESS_CPU_PRIORITY_LOW :
|
||||
PROCESS_CPU_PRIORITY_NORMAL;
|
||||
}
|
||||
|
||||
void
|
||||
ParticularProcessPriorityManager::ResetCPUPriorityNow()
|
||||
{
|
||||
SetPriorityNow(mPriority);
|
||||
}
|
||||
|
||||
void
|
||||
ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority,
|
||||
uint32_t aBackgroundLRU)
|
||||
{
|
||||
SetPriorityNow(aPriority, ComputeCPUPriority(aPriority), aBackgroundLRU);
|
||||
}
|
||||
|
||||
void
|
||||
ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority,
|
||||
ProcessCPUPriority aCPUPriority,
|
||||
uint32_t aBackgroundLRU)
|
||||
{
|
||||
if (aPriority == PROCESS_PRIORITY_UNKNOWN) {
|
||||
MOZ_ASSERT(false);
|
||||
|
@ -1058,11 +950,10 @@ ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority,
|
|||
if (aBackgroundLRU > 0 &&
|
||||
aPriority == PROCESS_PRIORITY_BACKGROUND &&
|
||||
mPriority == PROCESS_PRIORITY_BACKGROUND) {
|
||||
hal::SetProcessPriority(Pid(), mPriority, mCPUPriority, aBackgroundLRU);
|
||||
hal::SetProcessPriority(Pid(), mPriority, aBackgroundLRU);
|
||||
|
||||
nsPrintfCString ProcessPriorityWithBackgroundLRU("%s:%d",
|
||||
ProcessPriorityToString(mPriority, mCPUPriority),
|
||||
aBackgroundLRU);
|
||||
ProcessPriorityToString(mPriority), aBackgroundLRU);
|
||||
|
||||
FireTestOnlyObserverNotification("process-priority-with-background-LRU-set",
|
||||
ProcessPriorityWithBackgroundLRU.get());
|
||||
|
@ -1070,7 +961,7 @@ ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority,
|
|||
|
||||
if (!mContentParent ||
|
||||
!ProcessPriorityManagerImpl::PrefsEnabled() ||
|
||||
(mPriority == aPriority && mCPUPriority == aCPUPriority)) {
|
||||
(mPriority == aPriority)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1095,16 +986,18 @@ ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority,
|
|||
}
|
||||
|
||||
LOGP("Changing priority from %s to %s.",
|
||||
ProcessPriorityToString(mPriority, mCPUPriority),
|
||||
ProcessPriorityToString(aPriority, aCPUPriority));
|
||||
ProcessPriorityToString(mPriority),
|
||||
ProcessPriorityToString(aPriority));
|
||||
|
||||
ProcessPriority oldPriority = mPriority;
|
||||
|
||||
mPriority = aPriority;
|
||||
mCPUPriority = aCPUPriority;
|
||||
hal::SetProcessPriority(Pid(), mPriority, mCPUPriority);
|
||||
hal::SetProcessPriority(Pid(), mPriority);
|
||||
|
||||
if (oldPriority != mPriority) {
|
||||
ProcessPriorityManagerImpl::GetSingleton()->
|
||||
NotifyProcessPriorityChanged(this, oldPriority);
|
||||
|
||||
unused << mContentParent->SendNotifyProcessPriorityChanged(mPriority);
|
||||
}
|
||||
|
||||
|
@ -1113,12 +1006,7 @@ ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority,
|
|||
}
|
||||
|
||||
FireTestOnlyObserverNotification("process-priority-set",
|
||||
ProcessPriorityToString(mPriority, mCPUPriority));
|
||||
|
||||
if (oldPriority != mPriority) {
|
||||
ProcessPriorityManagerImpl::GetSingleton()->
|
||||
NotifyProcessPriorityChanged(this, oldPriority);
|
||||
}
|
||||
ProcessPriorityToString(mPriority));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -2011,7 +2011,7 @@ TabChild::RecvUpdateDimensions(const nsIntRect& rect, const nsIntSize& size,
|
|||
ScreenIntSize oldScreenSize = mInnerSize;
|
||||
mInnerSize = ScreenIntSize::FromUnknownSize(
|
||||
gfx::IntSize(size.width, size.height));
|
||||
mWidget->Resize(0, 0, size.width, size.height,
|
||||
mWidget->Resize(rect.x + chromeDisp.x, rect.y + chromeDisp.y, size.width, size.height,
|
||||
true);
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation());
|
||||
|
@ -2227,7 +2227,7 @@ TabChild::UpdateTapState(const WidgetTouchEvent& aEvent, nsEventStatus aStatus)
|
|||
return;
|
||||
}
|
||||
if (aStatus == nsEventStatus_eConsumeNoDefault ||
|
||||
nsIPresShell::gPreventMouseEvents ||
|
||||
TouchManager::gPreventMouseEvents ||
|
||||
aEvent.mFlags.mMultipleActionsPrevented) {
|
||||
return;
|
||||
}
|
||||
|
@ -2268,7 +2268,7 @@ TabChild::UpdateTapState(const WidgetTouchEvent& aEvent, nsEventStatus aStatus)
|
|||
return;
|
||||
|
||||
case NS_TOUCH_END:
|
||||
if (!nsIPresShell::gPreventMouseEvents) {
|
||||
if (!TouchManager::gPreventMouseEvents) {
|
||||
APZCCallbackHelper::DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, currentPoint, mWidget);
|
||||
APZCCallbackHelper::DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, currentPoint, mWidget);
|
||||
APZCCallbackHelper::DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_UP, time, currentPoint, mWidget);
|
||||
|
|
|
@ -80,6 +80,7 @@
|
|||
#include "nsICancelable.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "nsILoginManagerPrompter.h"
|
||||
#include "nsPIWindowRoot.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
@ -321,7 +322,27 @@ TabParent::RemoveTabParentFromTable(uint64_t aLayersId)
|
|||
void
|
||||
TabParent::SetOwnerElement(Element* aElement)
|
||||
{
|
||||
// If we held previous content then unregister for its events.
|
||||
if (mFrameElement && mFrameElement->OwnerDoc()->GetWindow()) {
|
||||
nsCOMPtr<nsPIDOMWindow> window = mFrameElement->OwnerDoc()->GetWindow();
|
||||
nsCOMPtr<EventTarget> eventTarget = window->GetTopWindowRoot();
|
||||
if (eventTarget) {
|
||||
eventTarget->RemoveEventListener(NS_LITERAL_STRING("MozUpdateWindowPos"),
|
||||
this, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Update to the new content, and register to listen for events from it.
|
||||
mFrameElement = aElement;
|
||||
if (mFrameElement && mFrameElement->OwnerDoc()->GetWindow()) {
|
||||
nsCOMPtr<nsPIDOMWindow> window = mFrameElement->OwnerDoc()->GetWindow();
|
||||
nsCOMPtr<EventTarget> eventTarget = window->GetTopWindowRoot();
|
||||
if (eventTarget) {
|
||||
eventTarget->AddEventListener(NS_LITERAL_STRING("MozUpdateWindowPos"),
|
||||
this, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
TryCacheDPIAndScale();
|
||||
}
|
||||
|
||||
|
@ -357,6 +378,8 @@ TabParent::Destroy()
|
|||
return;
|
||||
}
|
||||
|
||||
SetOwnerElement(nullptr);
|
||||
|
||||
// If this fails, it's most likely due to a content-process crash,
|
||||
// and auto-cleanup will kick in. Otherwise, the child side will
|
||||
// destroy itself and send back __delete__().
|
||||
|
@ -881,9 +904,40 @@ TabParent::RecvSetDimensions(const uint32_t& aFlags,
|
|||
return false;
|
||||
}
|
||||
|
||||
static nsIntPoint
|
||||
GetChromeDisplacement(nsFrameLoader *aFrameLoader)
|
||||
{
|
||||
if (!aFrameLoader) {
|
||||
return nsIntPoint();
|
||||
}
|
||||
|
||||
// Calculate the displacement from the primary frame of the tab
|
||||
// content to the top-level frame of the widget we are in.
|
||||
nsIFrame* contentFrame = aFrameLoader->GetPrimaryFrameOfOwningContent();
|
||||
if (!contentFrame) {
|
||||
return nsIntPoint();
|
||||
}
|
||||
|
||||
nsIFrame* nextFrame = nsLayoutUtils::GetCrossDocParentFrame(contentFrame);
|
||||
if (!nextFrame) {
|
||||
NS_WARNING("Couldn't find window chrome to calculate displacement to.");
|
||||
return nsIntPoint();
|
||||
}
|
||||
|
||||
nsIFrame* rootFrame = nextFrame;
|
||||
while (nextFrame) {
|
||||
rootFrame = nextFrame;
|
||||
nextFrame = nsLayoutUtils::GetCrossDocParentFrame(rootFrame);
|
||||
}
|
||||
|
||||
nsPoint offset = contentFrame->GetOffsetToCrossDoc(rootFrame);
|
||||
int32_t appUnitsPerDevPixel = rootFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
return nsIntPoint((int)(offset.x/appUnitsPerDevPixel),
|
||||
(int)(offset.y/appUnitsPerDevPixel));
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::UpdateDimensions(const nsIntRect& rect, const nsIntSize& size,
|
||||
const nsIntPoint& aChromeDisp)
|
||||
TabParent::UpdateDimensions(const nsIntRect& rect, const nsIntSize& size)
|
||||
{
|
||||
if (mIsDestroyed) {
|
||||
return;
|
||||
|
@ -894,12 +948,22 @@ TabParent::UpdateDimensions(const nsIntRect& rect, const nsIntSize& size,
|
|||
|
||||
if (!mUpdatedDimensions || mOrientation != orientation ||
|
||||
mDimensions != size || !mRect.IsEqualEdges(rect)) {
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
nsIntRect contentRect = rect;
|
||||
if (widget) {
|
||||
contentRect.x += widget->GetClientOffset().x;
|
||||
contentRect.y += widget->GetClientOffset().y;
|
||||
}
|
||||
|
||||
mUpdatedDimensions = true;
|
||||
mRect = rect;
|
||||
mRect = contentRect;
|
||||
mDimensions = size;
|
||||
mOrientation = orientation;
|
||||
|
||||
unused << SendUpdateDimensions(mRect, mDimensions, mOrientation, aChromeDisp);
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
||||
nsIntPoint chromeOffset = GetChromeDisplacement(frameLoader);
|
||||
|
||||
unused << SendUpdateDimensions(mRect, mDimensions, mOrientation, chromeOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2654,6 +2718,27 @@ TabParent::DeallocPPluginWidgetParent(mozilla::plugins::PPluginWidgetParent* aAc
|
|||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TabParent::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsAutoString eventType;
|
||||
aEvent->GetType(eventType);
|
||||
|
||||
if (eventType.EqualsLiteral("MozUpdateWindowPos")) {
|
||||
// This event is sent when the widget moved. Therefore we only update
|
||||
// the position.
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
||||
if (!frameLoader) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsIntRect windowDims;
|
||||
NS_ENSURE_SUCCESS(frameLoader->GetWindowDimensions(windowDims), NS_ERROR_FAILURE);
|
||||
UpdateDimensions(windowDims, mDimensions);
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class FakeChannel MOZ_FINAL : public nsIChannel,
|
||||
public nsIAuthPromptCallback,
|
||||
public nsIInterfaceRequestor,
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "Units.h"
|
||||
#include "WritingModes.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
|
||||
class nsFrameLoader;
|
||||
class nsIFrameLoader;
|
||||
|
@ -58,7 +59,8 @@ class nsIContentParent;
|
|||
class Element;
|
||||
struct StructuredCloneData;
|
||||
|
||||
class TabParent : public PBrowserParent
|
||||
class TabParent : public PBrowserParent
|
||||
, public nsIDOMEventListener
|
||||
, public nsITabParent
|
||||
, public nsIAuthPromptProvider
|
||||
, public nsISecureBrowserUI
|
||||
|
@ -98,6 +100,9 @@ public:
|
|||
mBrowserDOMWindow = aBrowserDOMWindow;
|
||||
}
|
||||
|
||||
// nsIDOMEventListener interfaces
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
already_AddRefed<nsILoadContext> GetLoadContext();
|
||||
|
||||
nsIXULBrowserWindow* GetXULBrowserWindow();
|
||||
|
@ -241,8 +246,7 @@ public:
|
|||
// message-sending functions under a layer of indirection and
|
||||
// eating the return values
|
||||
void Show(const nsIntSize& size, bool aParentIsActive);
|
||||
void UpdateDimensions(const nsIntRect& rect, const nsIntSize& size,
|
||||
const nsIntPoint& chromeDisp);
|
||||
void UpdateDimensions(const nsIntRect& rect, const nsIntSize& size);
|
||||
void UpdateFrame(const layers::FrameMetrics& aFrameMetrics);
|
||||
void UIResolutionChanged();
|
||||
void AcknowledgeScrollUpdate(const ViewID& aScrollId, const uint32_t& aScrollGeneration);
|
||||
|
|
|
@ -8,5 +8,6 @@ toolkit.jar:
|
|||
content/global/BrowserElementChild.js (../browser-element/BrowserElementChild.js)
|
||||
content/global/BrowserElementChildPreload.js (../browser-element/BrowserElementChildPreload.js)
|
||||
* content/global/BrowserElementPanning.js (../browser-element/BrowserElementPanning.js)
|
||||
* content/global/BrowserElementPanningAPZDisabled.js (../browser-element/BrowserElementPanningAPZDisabled.js)
|
||||
content/global/preload.js (preload.js)
|
||||
content/global/post-fork-preload.js (post-fork-preload.js)
|
||||
|
|
|
@ -91,6 +91,13 @@ const BrowserElementIsPreloaded = true;
|
|||
} catch (e) {
|
||||
}
|
||||
|
||||
try {
|
||||
if (Services.prefs.getBoolPref("layers.async-pan-zoom.enabled") === false) {
|
||||
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementPanningAPZDisabled.js", global);
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementPanning.js", global);
|
||||
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementChildPreload.js", global);
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ tab = tab
|
|||
# The Role Description for definition list dl, dt and dd
|
||||
term = term
|
||||
definition = definition
|
||||
# The Role Description for an input type="search" text field
|
||||
searchTextField = search text field
|
||||
# The Role Description for WAI-ARIA Landmarks
|
||||
search = search
|
||||
banner = banner
|
||||
|
|
|
@ -85,6 +85,15 @@ AudioSink::GetPosition()
|
|||
return mLastGoodPosition;
|
||||
}
|
||||
|
||||
bool
|
||||
AudioSink::HasUnplayedFrames()
|
||||
{
|
||||
AssertCurrentThreadInMonitor();
|
||||
// Experimentation suggests that GetPositionInFrames() is zero-indexed,
|
||||
// so we need to add 1 here before comparing it to mWritten.
|
||||
return mAudioStream && mAudioStream->GetPositionInFrames() + 1 < mWritten;
|
||||
}
|
||||
|
||||
void
|
||||
AudioSink::PrepareToShutdown()
|
||||
{
|
||||
|
|
|
@ -27,6 +27,10 @@ public:
|
|||
|
||||
int64_t GetPosition();
|
||||
|
||||
// Check whether we've pushed more frames to the audio hardware than it has
|
||||
// played.
|
||||
bool HasUnplayedFrames();
|
||||
|
||||
// Tell the AudioSink to stop processing and initiate shutdown. Must be
|
||||
// called with the decoder monitor held.
|
||||
void PrepareToShutdown();
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче